From 7c03823594cef3ce6e8da7ac1d7d3504c73695a9 Mon Sep 17 00:00:00 2001
From: Benjamin Auder <benjamin.auder@somewhere>
Date: Tue, 13 Sep 2022 16:21:23 +0200
Subject: [PATCH] Finish code refactoring to generate initial positions
 (untested)

---
 base_rules.js               | 11 +++----
 utils/setupPieces.js        |  5 +--
 variants/Alapo/class.js     | 64 +++++++++----------------------------
 variants/Ambiguous/class.js | 12 ++++---
 variants/Balaklava/class.js |  9 ++++--
 variants/Baroque/class.js   | 35 ++++++++------------
 variants/Chakart/class.js   | 14 ++++----
 variants/Giveaway/class.js  | 47 +++++++--------------------
 variants/Suction/class.js   | 12 ++++---
 variants/Weiqi/class.js     |  2 +-
 10 files changed, 80 insertions(+), 131 deletions(-)

diff --git a/base_rules.js b/base_rules.js
index cdce2a1..162fad0 100644
--- a/base_rules.js
+++ b/base_rules.js
@@ -220,11 +220,13 @@ export default class ChessRules {
       ['r', 'n', 'b', 'q', 'k', 'b', 'n', 'r'],
       {
         between: {p1: 'k', p2: 'r'},
-        diffCol: ['b']
+        diffCol: ['b'],
+        flags: ['r']
       }
     );
     return {
-      fen: s.b + "/pppppppp/8/8/8/8/PPPPPPPP/" + s.w,
+      fen: s.b.join("") + "/pppppppp/8/8/8/8/PPPPPPPP/" +
+           s.w.join("").toUpperCase(),
       o: {flags: s.flags}
     };
   }
@@ -356,9 +358,6 @@ export default class ChessRules {
       if (this.options[opt.variable] === undefined)
         this.options[opt.variable] = opt.defaut;
     });
-    if (o.genFenOnly)
-      // This object will be used only for initial FEN generation
-      return;
 
     // Some variables
     this.playerColor = o.color;
@@ -965,7 +964,7 @@ export default class ChessRules {
     // TODO: onpointerdown/move/up ? See reveal.js /controllers/touch.js
   }
 
-  // NOTE: not called if isDiagram, or genFenOnly
+  // NOTE: not called if isDiagram
   removeListeners() {
     let container = document.getElementById(this.containerId);
     this.windowResizeObs.unobserve(container);
diff --git a/utils/setupPieces.js b/utils/setupPieces.js
index 988903e..7cd6779 100644
--- a/utils/setupPieces.js
+++ b/utils/setupPieces.js
@@ -5,7 +5,7 @@ export class FenUtil = {
   // arg o (constraints): "between" with p1 and p2.
   //                      "flags", "diffCol": array of pieceType
   setupRow(arr, o) {
-    let res = arr;
+    let res = JSON.parse(JSON.stringify(arr));
     if (o.randomness >= 1)
       res = Random.shuffle(arr);
     let flags = "";
@@ -57,9 +57,10 @@ export class FenUtil = {
     const row1 = FenUtil.setupRow(arr, o);
     const row2 = o.randomness == 2 ? FenUtil.setupRow(arr, o) : row1;
     return {
-      w: row1.fen.toUpperCase,
+      w: row1.fen,
       b: row2.fen,
       flags: row1.flags + row2.flags
     };
   }
+
 };
diff --git a/variants/Alapo/class.js b/variants/Alapo/class.js
index e613140..3707ac8 100644
--- a/variants/Alapo/class.js
+++ b/variants/Alapo/class.js
@@ -1,6 +1,7 @@
 import ChessRules from "/base_rules.js";
 import {ArrayFun} from "/utils/array.js";
 import {Random} from "/utils/alea.js";
+import {FenUtil} from "/utils/setupPieces.js";
 
 export default class AlapoRules extends ChessRules {
 
@@ -29,55 +30,20 @@ export default class AlapoRules extends ChessRules {
   }
 
   genRandInitBaseFen() {
-    let fen = "";
-    if (this.options["randomness"] == 0)
-      fen = "rbqqbr/tcssct/6/6/TCSSCT/RBQQBR";
-    else {
-      const piece2pawn = {
-        r: 't',
-        q: 's',
-        b: 'c'
-      };
-      let pieces = { w: new Array(6), b: new Array(6) };
-      // Shuffle pieces on first (and last rank if randomness == 2)
-      for (let c of ["w", "b"]) {
-        if (c == 'b' && this.options["randomness"] == 1) {
-          pieces['b'] = pieces['w'];
-          break;
-        }
-        let positions = ArrayFun.range(6);
-        // Get random squares for bishops
-        let randIndex = 2 * Random.randInt(3);
-        const bishop1Pos = positions[randIndex];
-        let randIndex_tmp = 2 * Random.randInt(3) + 1;
-        const bishop2Pos = positions[randIndex_tmp];
-        positions.splice(Math.max(randIndex, randIndex_tmp), 1);
-        positions.splice(Math.min(randIndex, randIndex_tmp), 1);
-        // Get random square for queens
-        randIndex = Random.randInt(4);
-        const queen1Pos = positions[randIndex];
-        positions.splice(randIndex, 1);
-        randIndex = Random.randInt(3);
-        const queen2Pos = positions[randIndex];
-        positions.splice(randIndex, 1);
-        // Rooks positions are now fixed,
-        const rook1Pos = positions[0];
-        const rook2Pos = positions[1];
-        pieces[c][rook1Pos] = "r";
-        pieces[c][bishop1Pos] = "b";
-        pieces[c][queen1Pos] = "q";
-        pieces[c][queen2Pos] = "q";
-        pieces[c][bishop2Pos] = "b";
-        pieces[c][rook2Pos] = "r";
-      }
-      fen = (
-        pieces["b"].join("") + "/" +
-        pieces["b"].map(p => piece2pawn[p]).join("") +
-        "/6/6/" +
-        pieces["w"].map(p => piece2pawn[p].toUpperCase()).join("") + "/" +
-        pieces["w"].join("").toUpperCase()
-      );
-    }
+    const s =
+      FenUtil.setupPieces(['r', 'b', 'q', 'q', 'b', 'r'], {diffCol: ['b']});
+    const piece2pawn = {
+      r: 't',
+      q: 's',
+      b: 'c'
+    };
+    const fen = (
+      s.b.join("") + "/" +
+      s.b.map(p => piece2pawn[p]).join("") +
+      "/6/6/" +
+      s.w.map(p => piece2pawn[p].toUpperCase()).join("") + "/" +
+      s.w.join("").toUpperCase()
+    );
     return { fen: fen, o: {} };
   }
 
diff --git a/variants/Ambiguous/class.js b/variants/Ambiguous/class.js
index 5e7029c..3043b7b 100644
--- a/variants/Ambiguous/class.js
+++ b/variants/Ambiguous/class.js
@@ -1,5 +1,5 @@
 import ChessRules from "/base_rules.js";
-import GiveawayRules from "/variants/Giveaway/class.js";
+import {FenUtil} from "/utils/setupPieces.js";
 
 export default class AmbiguousRules extends ChessRules {
 
@@ -23,9 +23,13 @@ export default class AmbiguousRules extends ChessRules {
   }
 
   genRandInitBaseFen() {
-    const options = Object.assign({mode: "suicide"}, this.options);
-    const gr = new GiveawayRules({options: options, genFenOnly: true});
-    return gr.genRandInitBaseFen();
+    const s = FenUtil.setupPieces(
+      ['r', 'n', 'b', 'q', 'k', 'b', 'n', 'r'], {diffCol: ['b']});
+    return {
+      fen: s.b.join("") + "/pppppppp/8/8/8/8/PPPPPPPP/" +
+           s.w.join("").toUpperCase(),
+      o: {}
+    };
   }
 
   canStepOver(x, y) {
diff --git a/variants/Balaklava/class.js b/variants/Balaklava/class.js
index 2922b02..ad189cb 100644
--- a/variants/Balaklava/class.js
+++ b/variants/Balaklava/class.js
@@ -1,4 +1,5 @@
 import ChessRules from "/base_rules.js";
+import {FenUtil} from "/utils/setupPieces.js";
 
 export default class BalaklavaRules extends ChessRules {
 
@@ -32,10 +33,12 @@ export default class BalaklavaRules extends ChessRules {
   }
 
   genRandInitBaseFen() {
-    const baseFen = super.genRandInitBaseFen();
+    const s = FenUtil.setupPieces(
+      ['r', 'm', 'b', 'q', 'k', 'b', 'm', 'r'], {diffCol: ['b']});
     return {
-      fen: baseFen.fen.replace(/n/g, 'm').replace(/N/g, 'M'),
-      o: baseFen.o
+      fen: s.b.join("") + "/pppppppp/8/8/8/8/PPPPPPPP/" +
+           s.w.join("").toUpperCase(),
+      o: {}
     };
   }
 
diff --git a/variants/Baroque/class.js b/variants/Baroque/class.js
index 240f130..f87d768 100644
--- a/variants/Baroque/class.js
+++ b/variants/Baroque/class.js
@@ -1,5 +1,5 @@
-import GiveawayRules from "/variants/Giveaway/class.js";
 import AbstractSpecialCaptureRules from "/variants/_SpecialCaptures.js";
+import {FenUtil} from "/utils/setupPieces.js";
 import {Random} from "/utils/alea.js";
 
 export default class BaroqueRules extends AbstractSpecialCaptureRules {
@@ -33,27 +33,20 @@ export default class BaroqueRules extends AbstractSpecialCaptureRules {
   }
 
   genRandInitBaseFen() {
-    if (this.options["randomness"] == 0)
-      return "rnbkqbnm/pppppppp/8/8/8/8/PPPPPPPP/MNBQKBNR";
-    const options = Object.assign({mode: "suicide"}, this.options);
-    const gr = new GiveawayRules({options: options, genFenOnly: true});
-    let res = gr.genRandInitBaseFen();
-    let immPos = {};
-    for (let c of ['w', 'b']) {
-      const rookChar = (c == 'w' ? 'R' : 'r');
-      switch (Random.randInt(2)) {
-        case 0:
-          immPos[c] = res.fen.indexOf(rookChar);
-          break;
-        case 1:
-          immPos[c] = res.fen.lastIndexOf(rookChar);
-          break;
-      }
+    const s = FenUtil.setupPieces(
+      ['r', 'n', 'b', 'q', 'k', 'b', 'n', 'i'], {diffCol: ['b']});
+    if (this.options["randomness"] <= 1) {
+      // Fix immobilizers/rooks pattern
+      const toExchange1 = s.w.indexOf('r'),
+            toExchange2 = s.w.indexOf('i');
+      s.w[toExchange1] = 'i';
+      s.w[toExchange2] = 'r';
     }
-    res.fen = res.fen.substring(0, immPos['b']) + 'i' +
-              res.fen.substring(immPos['b'] + 1, immPos['w']) + 'I' +
-              res.fen.substring(immPos['w'] + 1);
-    return res;
+    return {
+      fen: s.b.join("") + "/pppppppp/8/8/8/8/PPPPPPPP/" +
+           s.w.join("").toUpperCase(),
+      o: {}
+    };
   }
 
   pieces() {
diff --git a/variants/Chakart/class.js b/variants/Chakart/class.js
index 96a53f3..aefbcd0 100644
--- a/variants/Chakart/class.js
+++ b/variants/Chakart/class.js
@@ -1,7 +1,7 @@
 import ChessRules from "/base_rules.js";
-import GiveawayRules from "/variants/Giveaway/class.js";
 import {ArrayFun} from "/utils/array.js";
 import {Random} from "/utils/alea.js";
+import {FenUtil} from "/utils/setupPieces.js";
 import PiPo from "/utils/PiPo.js";
 import Move from "/utils/Move.js";
 
@@ -131,11 +131,13 @@ export default class ChakartRules extends ChessRules {
   }
 
   genRandInitBaseFen() {
-    const options = Object.assign({mode: "suicide"}, this.options);
-    const gr = new GiveawayRules({options: options, genFenOnly: true});
-    let res = gr.genRandInitBaseFen();
-    res.o["flags"] = "1111"; //Peach + Mario flags
-    return res;
+    const s = FenUtil.setupPieces(
+      ['r', 'n', 'b', 'q', 'k', 'b', 'n', 'r'], {diffCol: ['b']});
+    return {
+      fen: s.b.join("") + "/pppppppp/8/8/8/8/PPPPPPPP/" +
+           s.w.join("").toUpperCase(),
+      o: {flags: "1111"} //Peach + Mario
+    };
   }
 
   fen2board(f) {
diff --git a/variants/Giveaway/class.js b/variants/Giveaway/class.js
index 3f27e5f..fd23954 100644
--- a/variants/Giveaway/class.js
+++ b/variants/Giveaway/class.js
@@ -1,6 +1,7 @@
 import ChessRules from "/base_rules.js";
 import {ArrayFun} from "/utils/array.js";
 import {Random} from "/utils/alea.js";
+import {FenUtil} from "/utils/setupPieces.js";
 
 export default class GiveawayRules extends ChessRules {
 
@@ -37,42 +38,18 @@ export default class GiveawayRules extends ChessRules {
   }
 
   genRandInitBaseFen() {
-    if (this.options["mode"] == "losers")
-      return super.genRandInitBaseFen();
-
-    let fen = "";
-    if (this.options["randomness"] == 0)
-      fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR";
-    else {
-      let pieces = { w: new Array(8), b: new Array(8) };
-      for (let c of ["w", "b"]) {
-        if (c == 'b' && this.options["randomness"] == 1) {
-          pieces['b'] = pieces['w'];
-          break;
-        }
-        // Get random squares for every piece, totally freely
-        let positions = Random.shuffle(ArrayFun.range(8));
-        const composition = ['b', 'b', 'r', 'r', 'n', 'n', 'k', 'q'];
-        const rem2 = positions[0] % 2;
-        if (rem2 == positions[1] % 2) {
-          // Fix bishops (on different colors)
-          for (let i=2; i<8; i++) {
-            if (positions[i] % 2 != rem2) {
-              [positions[1], positions[i]] = [positions[i], positions[1]];
-              break;
-            }
-          }
-        }
-        for (let i = 0; i < 8; i++)
-          pieces[c][positions[i]] = composition[i];
-      }
-      fen = (
-        pieces["b"].join("") +
-        "/pppppppp/8/8/8/8/PPPPPPPP/" +
-        pieces["w"].join("").toUpperCase()
-      );
+    let setupOpts = {diffCol: ['b']};
+    if (this.options["mode"] == "losers") {
+      setupOpts["between"] = ['k', 'r'];
+      setupOpts["flags"] = ['r'];
     }
-    return { fen: fen, o: {} };
+    const s = FenUtil.setupPieces(
+      ['r', 'n', 'b', 'q', 'k', 'b', 'n', 'r'], setupOpts);
+    return {
+      fen: s.b.join("") + "/pppppppp/8/8/8/8/PPPPPPPP/" +
+           s.w.join("").toUpperCase(),
+      o: {flags: s.flags}
+    };
   }
 
   constructor(o) {
diff --git a/variants/Suction/class.js b/variants/Suction/class.js
index 889a37f..6a66a06 100644
--- a/variants/Suction/class.js
+++ b/variants/Suction/class.js
@@ -1,5 +1,5 @@
 import ChessRules from "/base_rules.js";
-import GiveawayRules from "/variants/Giveaway/class.js";
+import {FenUtil} from "/utils/setupPieces.js";
 import PiPo from "/utils/PiPo.js";
 import Move from "/utils/Move.js";
 
@@ -42,9 +42,13 @@ export default class SuctionRules extends ChessRules {
   }
 
   genRandInitBaseFen() {
-    const options = Object.assign({mode: "suicide"}, this.options);
-    const gr = new GiveawayRules({options: options, genFenOnly: true});
-    return gr.genRandInitBaseFen();
+    const s = FenUtil.setupPieces(
+      ['r', 'n', 'b', 'q', 'k', 'b', 'n', 'r'], {diffCol: ['b']});
+    return {
+      fen: s.b.join("") + "/pppppppp/8/8/8/8/PPPPPPPP/" +
+           s.w.join("").toUpperCase(),
+      o: {}
+    };
   }
 
   getPartFen(o) {
diff --git a/variants/Weiqi/class.js b/variants/Weiqi/class.js
index 714ada8..ca13fe1 100644
--- a/variants/Weiqi/class.js
+++ b/variants/Weiqi/class.js
@@ -89,7 +89,7 @@ export default class WeiqiRules extends ChessRules {
 
   constructor(o) {
     super(o);
-    if (!o.genFenOnly && !o.diagram) {
+    if (!o.diagram) {
       this.passListener = () => {
         if (this.turn == this.playerColor) {
           let mv = {
-- 
2.44.0