Improve(?) Monochrome + simplify Zen variant
authorBenjamin Auder <benjamin.auder@somewhere>
Fri, 5 Jun 2020 19:26:32 +0000 (21:26 +0200)
committerBenjamin Auder <benjamin.auder@somewhere>
Fri, 5 Jun 2020 19:26:32 +0000 (21:26 +0200)
client/src/translations/rules/Monochrome/en.pug
client/src/translations/rules/Monochrome/es.pug
client/src/translations/rules/Monochrome/fr.pug
client/src/translations/variants/en.pug
client/src/translations/variants/es.pug
client/src/translations/variants/fr.pug
client/src/variants/Monochrome.js
client/src/variants/Zen.js

index 639f735..81175e1 100644 (file)
@@ -20,7 +20,10 @@ figure.diagram-container
     | fen:3b4/3r4/8/8/8/8/8/3n4:
   figcaption Before and after Rxd7
 
-p Kings have no royal status. There are no en-passant captures.
+p.
+  Kings have no royal status. There are no en-passant captures, and no castle.
+  "Zen" captures are possible too: if a piece A attacks a piece B
+  (in the usual way), then B can capture A.
 
 h3 Source
 
index 3cb4262..f77fc21 100644 (file)
@@ -22,7 +22,10 @@ figure.diagram-container
     | fen:3b4/3r4/8/8/8/8/8/3n4:
   figcaption Antes y después de Rxd7
 
-p Los reyes no tienen estatus real. No hay capturas en-passant.
+p.
+  Los reyes no tienen estatus real. No hay capturas en passant ni enroque.
+  Las capturas "Zen" también son posibles: si una pieza A ataca a un
+  pieza B (en el sentido habitual), entonces B puede capturar a A.
 
 h3 Fuente
 
index a37e52c..7073855 100644 (file)
@@ -22,7 +22,10 @@ figure.diagram-container
     | fen:3b4/3r4/8/8/8/8/8/3n4:
   figcaption Avant et après Rxd7
 
-p Les rois n'ont pas de statut royal. Il n'y pas de prises en passant.
+p.
+  Les rois n'ont pas de statut royal. Il n'y a ni prise en passant ni roque.
+  Les captures "Zen" sont possible également : si une pièce A attaque une
+  pièce B (au sens usuel), alors B peut capturer A.
 
 h3 Source
 
index a1e14b4..29c4a89 100644 (file)
@@ -34,8 +34,8 @@ p.
   var varlist = [
     "Arena",
     "Capture",
-    "Interweave",
     "Losers",
+    "Monochrome",
     "Suicide"
   ]
 ul
@@ -162,6 +162,7 @@ p.
     "Baroque",
     "Dynamo",
     "Fugue",
+    "Interweave",
     "Rococo",
     "Maxima"
   ]
@@ -386,7 +387,6 @@ p.
     "Gridolina",
     "Hamilton",
     "Magnetic",
-    "Monochrome",
     "Parachute",
     "Takenmake",
     "Wormhole"
index 3cb8fa6..b6939cc 100644 (file)
@@ -36,8 +36,8 @@ p.
   var varlist = [
     "Arena",
     "Capture",
-    "Interweave",
     "Losers",
+    "Monochrome",
     "Suicide"
   ]
 ul
@@ -169,6 +169,7 @@ p.
     "Baroque",
     "Dynamo",
     "Fugue",
+    "Interweave",
     "Rococo",
     "Maxima"
   ]
@@ -397,7 +398,6 @@ p.
     "Gridolina",
     "Hamilton",
     "Magnetic",
-    "Monochrome",
     "Parachute",
     "Takenmake",
     "Wormhole"
index 5f0036b..d108dcd 100644 (file)
@@ -35,8 +35,8 @@ p.
   var varlist = [
     "Arena",
     "Capture",
-    "Interweave",
     "Losers",
+    "Monochrome",
     "Suicide"
   ]
 ul
@@ -168,6 +168,7 @@ p.
     "Baroque",
     "Dynamo",
     "Fugue",
+    "Interweave",
     "Rococo",
     "Maxima"
   ]
@@ -396,7 +397,6 @@ p.
     "Gridolina",
     "Hamilton",
     "Magnetic",
-    "Monochrome",
     "Parachute",
     "Takenmake",
     "Wormhole"
index 31cf59e..ba56c69 100644 (file)
@@ -6,6 +6,10 @@ export class MonochromeRules extends ChessRules {
     return false;
   }
 
+  static get HasFlags() {
+    return false;
+  }
+
   static get Lines() {
     return [ [[4, 0], [4, 8]] ];
   }
@@ -43,9 +47,65 @@ export class MonochromeRules extends ChessRules {
     return ((x1 <= 3 && x2 >= 4) || (x1 >= 4 && x2 <= 3));
   }
 
+  // follow steps from x,y until something is met.
+  // if met piece is opponent and same movement (asA): eat it!
+  findCaptures_aux([x, y], asA) {
+    let moves = [];
+    const steps =
+      asA != V.PAWN
+        ? [V.QUEEN, V.KING].includes(asA)
+          ? V.steps[V.ROOK].concat(V.steps[V.BISHOP])
+          : V.steps[asA]
+        : this.turn == "w"
+          ? [
+            [-1, -1],
+            [-1, 1]
+          ]
+          : [
+            [1, -1],
+            [1, 1]
+          ];
+    const oneStep = [V.KNIGHT, V.PAWN, V.KING].includes(asA);
+    outerLoop: for (let loop = 0; loop < steps.length; loop++) {
+      const step = steps[loop];
+      let i = x + step[0];
+      let j = y + step[1];
+      while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) {
+        if (oneStep) continue outerLoop;
+        i += step[0];
+        j += step[1];
+      }
+      if (
+        V.OnBoard(i, j) &&
+        this.getPiece(i, j) == asA &&
+        this.canTake([i, j], [x, y])
+      ) {
+        // eat!
+        moves.push(this.getBasicMove([x, y], [i, j]));
+      }
+    }
+    return moves;
+  }
+
+  // Find possible captures from a square: look in every direction!
+  findCaptures(sq) {
+    let moves = [];
+    Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.PAWN));
+    Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.ROOK));
+    Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.KNIGHT));
+    Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.BISHOP));
+    Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.QUEEN));
+    Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.KING));
+    return moves;
+  }
+
   // Trim all non-capturing moves
   static KeepCaptures(moves) {
-    return moves.filter(m => m.vanish.length == 2 && m.appear.length == 1);
+    return moves.filter(m => m.vanish.length == 2);
+  }
+
+  getPotentialMovesFrom(sq) {
+    return super.getPotentialMovesFrom(sq).concat(this.findCaptures(sq));
   }
 
   getAllPotentialMoves() {
@@ -88,9 +148,7 @@ export class MonochromeRules extends ChessRules {
       for (let j = 0; j < V.size.y; j++) {
         if (
           this.board[i][j] != V.EMPTY &&
-          this.getPotentialMovesFrom([i, j]).some(m =>
-            // Warning: discard castle moves
-            m.vanish.length == 2 && m.appear.length == 1)
+          this.getPotentialMovesFrom([i, j]).some(m => m.vanish.length == 2)
         ) {
           return true;
         }
@@ -120,7 +178,7 @@ export class MonochromeRules extends ChessRules {
   }
 
   getCurrentScore() {
-    // Is there anything in my half board?
+    // Is there anything in opponent's half board?
     const color = V.GetOppCol(this.turn);
     const xBounds = color == 'w' ? [4,7] : [0,3];
     let nothingHere = true;
@@ -138,8 +196,8 @@ export class MonochromeRules extends ChessRules {
   }
 
   static GenRandInitFen(randomness) {
-    // Remove the en-passant part of the FEN
-    const fen = ChessRules.GenRandInitFen(randomness).slice(0, -2);
+    // Remove the en-passant + castle part of the FEN
+    const fen = ChessRules.GenRandInitFen(randomness).slice(0, -6);
     const firstSpace = fen.indexOf(' ');
     return (
       fen.substr(0, firstSpace).replace(/[A-Z]/g, (c) => c.toLowerCase()) +
@@ -164,4 +222,33 @@ export class MonochromeRules extends ChessRules {
     }
     return evaluation;
   }
+
+  getNotation(move) {
+    // Translate initial square (because pieces may fly unusually!)
+    const initialSquare = V.CoordsToSquare(move.start);
+
+    // Translate final square
+    const finalSquare = V.CoordsToSquare(move.end);
+
+    let notation = "";
+    const piece = this.getPiece(move.start.x, move.start.y);
+    if (piece == V.PAWN) {
+      // pawn move (TODO: enPassant indication)
+      if (move.vanish.length == 2) {
+        // capture
+        notation = initialSquare + "x" + finalSquare;
+      }
+      else notation = finalSquare;
+      if (piece != move.appear[0].p)
+        //promotion
+        notation += "=" + move.appear[0].p.toUpperCase();
+    }
+    else {
+      // Piece movement
+      notation = piece.toUpperCase();
+      if (move.vanish.length > 1) notation += initialSquare + "x";
+      notation += finalSquare;
+    }
+    return notation;
+  }
 };
index 0424e07..808d543 100644 (file)
@@ -66,6 +66,7 @@ export class ZenRules extends ChessRules {
     const oneStep = [V.KNIGHT,V.PAWN].includes(asA); //we don't capture king
     const lastRank = color == "w" ? 0 : V.size.x - 1;
     const promotionPieces = [V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN];
+    const oppCol = V.GetOppCol(color);
     outerLoop: for (let loop = 0; loop < steps.length; loop++) {
       const step = steps[loop];
       let i = x + step[0];
@@ -77,7 +78,7 @@ export class ZenRules extends ChessRules {
       }
       if (
         V.OnBoard(i, j) &&
-        this.getColor(i, j) == V.GetOppCol(color) &&
+        this.getColor(i, j) == oppCol &&
         this.getPiece(i, j) == asA
       ) {
         // eat!
@@ -98,13 +99,11 @@ export class ZenRules extends ChessRules {
   // Find possible captures from a square: look in every direction!
   findCaptures(sq) {
     let moves = [];
-
     Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.PAWN));
     Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.ROOK));
     Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.KNIGHT));
     Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.BISHOP));
     Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.QUEEN));
-
     return moves;
   }
 
@@ -112,49 +111,8 @@ export class ZenRules extends ChessRules {
     return false; //captures handled separately
   }
 
-  getPotentialPawnMoves([x, y]) {
-    let moves = super.getPotentialPawnMoves([x, y]);
-    // Add "zen" captures
-    Array.prototype.push.apply(moves, this.findCaptures([x, y]));
-    return moves;
-  }
-
-  getPotentialRookMoves(sq) {
-    let noCaptures = this.getSlideNJumpMoves(sq, V.steps[V.ROOK]);
-    let captures = this.findCaptures(sq);
-    return noCaptures.concat(captures);
-  }
-
-  getPotentialKnightMoves(sq) {
-    let noCaptures = this.getSlideNJumpMoves(sq, V.steps[V.KNIGHT], "oneStep");
-    let captures = this.findCaptures(sq);
-    return noCaptures.concat(captures);
-  }
-
-  getPotentialBishopMoves(sq) {
-    let noCaptures = this.getSlideNJumpMoves(sq, V.steps[V.BISHOP]);
-    let captures = this.findCaptures(sq);
-    return noCaptures.concat(captures);
-  }
-
-  getPotentialQueenMoves(sq) {
-    let noCaptures = this.getSlideNJumpMoves(
-      sq,
-      V.steps[V.ROOK].concat(V.steps[V.BISHOP])
-    );
-    let captures = this.findCaptures(sq);
-    return noCaptures.concat(captures);
-  }
-
-  getPotentialKingMoves(sq) {
-    // Initialize with normal moves
-    let noCaptures = this.getSlideNJumpMoves(
-      sq,
-      V.steps[V.ROOK].concat(V.steps[V.BISHOP]),
-      "oneStep"
-    );
-    let captures = this.findCaptures(sq);
-    return noCaptures.concat(captures).concat(this.getCastleMoves(sq));
+  getPotentialMovesFrom(sq) {
+    return super.getPotentialMovesFrom(sq).concat(this.findCaptures(sq));
   }
 
   getNotation(move) {
@@ -175,15 +133,16 @@ export class ZenRules extends ChessRules {
     const piece = this.getPiece(move.start.x, move.start.y);
     if (piece == V.PAWN) {
       // pawn move (TODO: enPassant indication)
-      if (move.vanish.length > 1) {
+      if (move.vanish.length == 2) {
         // capture
         notation = initialSquare + "x" + finalSquare;
-      } //no capture
+      }
       else notation = finalSquare;
       if (piece != move.appear[0].p)
         //promotion
         notation += "=" + move.appear[0].p.toUpperCase();
-    } else {
+    }
+    else {
       // Piece movement
       notation = piece.toUpperCase();
       if (move.vanish.length > 1) notation += initialSquare + "x";