Some simplifactions, a few fixes, update TODO
[vchess.git] / client / src / variants / Perfect.js
index 4bd2ac9..0c5e6e1 100644 (file)
@@ -138,67 +138,50 @@ export class PerfectRules extends ChessRules {
     if (randomness == 0)
       return "esqakbnr/pppppppp/8/8/8/8/PPPPPPPP/ESQAKBNR w 0 ahah -";
 
-    let pieces = { w: new Array(8), b: new Array(8) };
-    let flags = "";
-    let whiteBishopPos = -1;
-    for (let c of ["w", "b"]) {
-      if (c == 'b' && randomness == 1) {
-        pieces['b'] = pieces['w'];
-        flags += flags;
-        break;
+    const baseFen = ChessRules.GenRandInitFen(randomness);
+    const fenParts = baseFen.split(' ');
+    const posParts = fenParts[0].split('/');
+
+    // Replace a random rook per side by an empress,
+    // a random knight by a princess, and a bishop by an amazon
+    // (Constraint: the two remaining bishops on different colors).
+
+    let newPos = { 0: "", 7: "" };
+    let amazonOddity = -1;
+    for (let rank of [0, 7]) {
+      let replaced = { 'b': -2, 'n': -2, 'r': -2 };
+      for (let i = 0; i < 8; i++) {
+        const curChar = posParts[rank].charAt(i).toLowerCase();
+        if (['b', 'n', 'r'].includes(curChar)) {
+          if (
+            replaced[curChar] == -1 ||
+            (curChar == 'b' && rank == 7 && i % 2 == amazonOddity) ||
+            (
+              (curChar != 'b' || rank == 0) &&
+              replaced[curChar] == -2 &&
+              randInt(2) == 0
+            )
+          ) {
+            replaced[curChar] = i;
+            if (curChar == 'b') {
+              if (amazonOddity < 0) amazonOddity = i % 2;
+              newPos[rank] += 'a';
+            }
+            else if (curChar == 'r') newPos[rank] += 'e';
+            else newPos[rank] += 's';
+          }
+          else {
+            if (replaced[curChar] == -2) replaced[curChar]++;
+            newPos[rank] += curChar;
+          }
+        }
+        else newPos[rank] += curChar;
       }
-
-      let positions = ArrayFun.range(8);
-
-      // Get random squares for bishop: if black, pick a different color
-      // than where the white one stands.
-      let randIndex =
-        c == 'w'
-          ? randInt(8)
-          : 2 * randInt(4) + (1 - whiteBishopPos % 2);
-      if (c == 'w') whiteBishopPos = randIndex;
-      const bishopPos = positions[randIndex];
-      positions.splice(randIndex, 1);
-
-      randIndex = randInt(7);
-      const knightPos = positions[randIndex];
-      positions.splice(randIndex, 1);
-
-      randIndex = randInt(6);
-      const queenPos = positions[randIndex];
-      positions.splice(randIndex, 1);
-
-      randIndex = randInt(5);
-      const amazonPos = positions[randIndex];
-      positions.splice(randIndex, 1);
-
-      randIndex = randInt(4);
-      const princessPos = positions[randIndex];
-      positions.splice(randIndex, 1);
-
-      // Rook, empress and king positions are now almost fixed,
-      // only the ordering rook->empress or empress->rook must be decided.
-      let rookPos = positions[0];
-      let empressPos = positions[2];
-      const kingPos = positions[1];
-      flags += V.CoordToColumn(rookPos) + V.CoordToColumn(empressPos);
-      if (Math.random() < 0.5) [rookPos, empressPos] = [empressPos, rookPos];
-
-      pieces[c][rookPos] = "r";
-      pieces[c][knightPos] = "n";
-      pieces[c][bishopPos] = "b";
-      pieces[c][queenPos] = "q";
-      pieces[c][kingPos] = "k";
-      pieces[c][amazonPos] = "a";
-      pieces[c][princessPos] = "s";
-      pieces[c][empressPos] = "e";
     }
-    // Add turn + flags + enpassant
+
     return (
-      pieces["b"].join("") +
-      "/pppppppp/8/8/8/8/PPPPPPPP/" +
-      pieces["w"].join("").toUpperCase() +
-      " w 0 " + flags + " -"
+      newPos[0] + "/" + posParts.slice(1, 7).join('/') + "/" +
+      newPos[7].toUpperCase() + " " + fenParts.slice(1, 5).join(' ') + " -"
     );
   }