From 0adfbdb55452c79532875beb8eed61b1ed4c6cd2 Mon Sep 17 00:00:00 2001
From: Benjamin Auder <benjamin.auder@somewhere>
Date: Mon, 12 Sep 2022 16:04:12 +0200
Subject: [PATCH] Complete FenUtil draft. Untested

---
 base_rules.js        |  70 +++++----------------------
 utils/alea.js        |   4 ++
 utils/setupPieces.js | 109 +++++++++++++++----------------------------
 3 files changed, 53 insertions(+), 130 deletions(-)

diff --git a/base_rules.js b/base_rules.js
index b315fd5..cdce2a1 100644
--- a/base_rules.js
+++ b/base_rules.js
@@ -1,5 +1,6 @@
 import {Random} from "/utils/alea.js";
 import {ArrayFun} from "/utils/array.js";
+import {FenUtil} from "/utils/setupPieces.js";
 import PiPo from "/utils/PiPo.js";
 import Move from "/utils/Move.js";
 
@@ -215,66 +216,17 @@ export default class ChessRules {
 
   // Setup the initial random-or-not (asymmetric-or-not) position
   genRandInitBaseFen() {
-    let fen, flags = "0707";
-    if (!this.options.randomness)
-      // Deterministic:
-      fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR";
-
-    else {
-      // Randomize
-      let pieces = {w: new Array(8), b: new Array(8)};
-      flags = "";
-      // 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'];
-          flags += flags;
-          break;
-        }
-        let positions = ArrayFun.range(8);
-        // Get random squares for bishops
-        let randIndex = 2 * Random.randInt(4);
-        const bishop1Pos = positions[randIndex];
-        // The second bishop must be on a square of different color
-        let randIndex_tmp = 2 * Random.randInt(4) + 1;
-        const bishop2Pos = positions[randIndex_tmp];
-        // Remove chosen squares
-        positions.splice(Math.max(randIndex, randIndex_tmp), 1);
-        positions.splice(Math.min(randIndex, randIndex_tmp), 1);
-        // Get random squares for knights
-        randIndex = Random.randInt(6);
-        const knight1Pos = positions[randIndex];
-        positions.splice(randIndex, 1);
-        randIndex = Random.randInt(5);
-        const knight2Pos = positions[randIndex];
-        positions.splice(randIndex, 1);
-        // Get random square for queen
-        randIndex = Random.randInt(4);
-        const queenPos = positions[randIndex];
-        positions.splice(randIndex, 1);
-        // Rooks and king positions are now fixed,
-        // because of the ordering rook-king-rook
-        const rook1Pos = positions[0];
-        const kingPos = positions[1];
-        const rook2Pos = positions[2];
-        // Finally put the shuffled pieces in the board array
-        pieces[c][rook1Pos] = "r";
-        pieces[c][knight1Pos] = "n";
-        pieces[c][bishop1Pos] = "b";
-        pieces[c][queenPos] = "q";
-        pieces[c][kingPos] = "k";
-        pieces[c][bishop2Pos] = "b";
-        pieces[c][knight2Pos] = "n";
-        pieces[c][rook2Pos] = "r";
-        flags += rook1Pos.toString() + rook2Pos.toString();
+    const s = FenUtil.setupPieces(
+      ['r', 'n', 'b', 'q', 'k', 'b', 'n', 'r'],
+      {
+        between: {p1: 'k', p2: 'r'},
+        diffCol: ['b']
       }
-      fen = (
-        pieces["b"].join("") +
-        "/pppppppp/8/8/8/8/PPPPPPPP/" +
-        pieces["w"].join("").toUpperCase()
-      );
-    }
-    return { fen: fen, o: {flags: flags} };
+    );
+    return {
+      fen: s.b + "/pppppppp/8/8/8/8/PPPPPPPP/" + s.w,
+      o: {flags: s.flags}
+    };
   }
 
   // "Parse" FEN: just return untransformed string data
diff --git a/utils/alea.js b/utils/alea.js
index 077970d..d892824 100644
--- a/utils/alea.js
+++ b/utils/alea.js
@@ -26,6 +26,10 @@ export const Random = {
     return Math.floor(Random.rand() * (max - min)) + min;
   },
 
+  randBool: function() {
+    return Random.randInt(0, 2) == 0;
+  },
+
   // Inspired by https://github.com/jashkenas/underscore
   sample: function(arr, n) {
     n = n || 1;
diff --git a/utils/setupPieces.js b/utils/setupPieces.js
index f0a8cfc..988903e 100644
--- a/utils/setupPieces.js
+++ b/utils/setupPieces.js
@@ -1,6 +1,6 @@
 import {Random} from "/utils/alea.js";
 
-export class Fenutil = {
+export class FenUtil = {
 
   // arg o (constraints): "between" with p1 and p2.
   //                      "flags", "diffCol": array of pieceType
@@ -15,84 +15,51 @@ export class Fenutil = {
           flags += i;
       });
     }
+    if (o.diffCol) {
+      o.diffCol.forEach(p => {
+        // Pieces of type p on different colors:
+        const firstP = res.indexOf(p),
+              lastP = res.lastIndexOf(p);
+        if ((firstP - lastP) % 2 != 0) {
+          const choice1 = Random.randBool() ? firstP : lastP;
+          let choice2;
+          do {
+            choice2 = Random.randInt(arr.length);
+          }
+          while (
+            choice2 == choice1 ||
+            o.diffCol.includes(choice2) ||
+            (choice2 - choice1) % 2 != 0
+          );
+          res[choice1] = res[choice2];
+          res[choice2] = p;
+        }
+      });
+    }
     if (o.between) {
       // Locate p1. If appearing first, exchange with first p2.
       // If appearing last, exchange with last p2.
-      res.findIndex(p => p == o.between["p1"])
+      const p1 = res.indexOf(o.between["p1"]);
+      const firstP2 = res.indexOf(o.between["p2"]),
+            lastP2 = res.lastIndexOf(o.between["p2"]);
+      if (p1 < firstP2 || p1 > lastP2) {
+        res[p1] = o.between["p2"];
+        if (p1 < firstP2)
+          res[firstP2] = o.between["p1"];
+        else //p1 > lastP2
+          res[lastP2] = o.between["p1"];
+      }
     }
-
     return {fen: res, flags: flags};
   }
 
   setupPieces(arr, o) {
-    if (o.randomness == 0)
-
-
+    const row1 = FenUtil.setupRow(arr, o);
+    const row2 = o.randomness == 2 ? FenUtil.setupRow(arr, o) : row1;
     return {
-      row1: 
-
-
-
+      w: row1.fen.toUpperCase,
+      b: row2.fen,
+      flags: row1.flags + row2.flags
+    };
   }
 };
-
-let fen, flags = "0707";
-    if (!this.options.randomness)
-      // Deterministic:
-      fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR";
-
-    else {
-      // Randomize
-      let pieces = {w: new Array(8), b: new Array(8)};
-      flags = "";
-      // 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'];
-          flags += flags;
-          break;
-        }
-        let positions = ArrayFun.range(8);
-        // Get random squares for bishops
-        let randIndex = 2 * Random.randInt(4);
-        const bishop1Pos = positions[randIndex];
-        // The second bishop must be on a square of different color
-        let randIndex_tmp = 2 * Random.randInt(4) + 1;
-        const bishop2Pos = positions[randIndex_tmp];
-        // Remove chosen squares
-        positions.splice(Math.max(randIndex, randIndex_tmp), 1);
-        positions.splice(Math.min(randIndex, randIndex_tmp), 1);
-        // Get random squares for knights
-        randIndex = Random.randInt(6);
-        const knight1Pos = positions[randIndex];
-        positions.splice(randIndex, 1);
-        randIndex = Random.randInt(5);
-        const knight2Pos = positions[randIndex];
-        positions.splice(randIndex, 1);
-        // Get random square for queen
-        randIndex = Random.randInt(4);
-        const queenPos = positions[randIndex];
-        positions.splice(randIndex, 1);
-        // Rooks and king positions are now fixed,
-        // because of the ordering rook-king-rook
-        const rook1Pos = positions[0];
-        const kingPos = positions[1];
-        const rook2Pos = positions[2];
-        // Finally put the shuffled pieces in the board array
-        pieces[c][rook1Pos] = "r";
-        pieces[c][knight1Pos] = "n";
-        pieces[c][bishop1Pos] = "b";
-        pieces[c][queenPos] = "q";
-        pieces[c][kingPos] = "k";
-        pieces[c][bishop2Pos] = "b";
-        pieces[c][knight2Pos] = "n";
-        pieces[c][rook2Pos] = "r";
-        flags += rook1Pos.toString() + rook2Pos.toString();
-      }
-      fen = (
-        pieces["b"].join("") +
-        "/pppppppp/8/8/8/8/PPPPPPPP/" +
-        pieces["w"].join("").toUpperCase()
-      );
-    }
-    return { fen: fen, o: {flags: flags} };
-- 
2.44.0