Fix pawn promotions in Eightpieces
[vchess.git] / client / src / variants / Eightpieces.js
index 6efb182..583b1c5 100644 (file)
@@ -406,12 +406,18 @@ export class EightpiecesRules extends ChessRules {
     // Pawns might be pushed on 1st rank and attempt to move again:
     if (!V.OnBoard(x + shiftX, y)) return [];
 
-    const finalPieces =
-      // A push cannot put a pawn on last rank (it goes backward)
-      x + shiftX == lastRank
-        ? Object.keys(V.LANCER_DIRS).concat(
-          [V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN, V.SENTRY, V.JAILER])
-        : [V.PAWN];
+    // A push cannot put a pawn on last rank (it goes backward)
+    let finalPieces = [V.PAWN];
+    if (x + shiftX == lastRank) {
+      // Only allow direction facing inside board:
+      const allowedLancerDirs =
+        lastRank == 0
+          ? ['e', 'f', 'g', 'h', 'm']
+          : ['c', 'd', 'e', 'm', 'o'];
+      finalPieces =
+        allowedLancerDirs
+        .concat([V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN, V.SENTRY, V.JAILER]);
+    }
     if (this.board[x + shiftX][y] == V.EMPTY) {
       // One square forward
       for (let piece of finalPieces) {
@@ -557,6 +563,7 @@ export class EightpiecesRules extends ChessRules {
     const L = this.sentryPush.length;
     const color = this.getColor(x, y);
     const dirCode = this.board[x][y][1];
+    const curDir = V.LANCER_DIRS[dirCode];
     if (!!this.sentryPush[L-1]) {
       // Maybe I was pushed
       const pl = this.sentryPush[L-1].length;
@@ -567,7 +574,6 @@ export class EightpiecesRules extends ChessRules {
         // I was pushed: allow all directions (for this move only), but
         // do not change direction after moving, *except* if I keep the
         // same orientation in which I was pushed.
-        const curDir = V.LANCER_DIRS[dirCode];
         // Also allow simple reorientation ("capturing king"):
         if (!V.OnBoard(x + curDir[0], y + curDir[1])) {
           const kp = this.kingPos[color];
@@ -622,13 +628,18 @@ export class EightpiecesRules extends ChessRules {
             let chooseMoves = [];
             dirMoves.forEach(m => {
               Object.keys(V.LANCER_DIRS).forEach(k => {
-                let mk = JSON.parse(JSON.stringify(m));
-                mk.appear[0].p = k;
-                moves.push(mk);
+                const newDir = V.LANCER_DIRS[k];
+                // Prevent orientations toward outer board:
+                if (V.OnBoard(m.end.x + newDir[0], m.end.y + newDir[1])) {
+                  let mk = JSON.parse(JSON.stringify(m));
+                  mk.appear[0].p = k;
+                  chooseMoves.push(mk);
+                }
               });
             });
             Array.prototype.push.apply(moves, chooseMoves);
-          } else Array.prototype.push.apply(moves, dirMoves);
+          }
+          else Array.prototype.push.apply(moves, dirMoves);
         });
         return moves;
       }
@@ -640,17 +651,23 @@ export class EightpiecesRules extends ChessRules {
     if (this.subTurn == 1) {
       monodirMoves.forEach(m => {
         Object.keys(V.LANCER_DIRS).forEach(k => {
-          let mk = JSON.parse(JSON.stringify(m));
-          mk.appear[0].p = k;
-          moves.push(mk);
+          const newDir = V.LANCER_DIRS[k];
+          // Prevent orientations toward outer board:
+          if (V.OnBoard(m.end.x + newDir[0], m.end.y + newDir[1])) {
+            let mk = JSON.parse(JSON.stringify(m));
+            mk.appear[0].p = k;
+            moves.push(mk);
+          }
         });
       });
       return moves;
-    } else {
-      // I'm pushed: add potential nudges
+    }
+    else {
+      // I'm pushed: add potential nudges, except for current orientation
       let potentialNudges = [];
       for (let step of V.steps[V.ROOK].concat(V.steps[V.BISHOP])) {
         if (
+          (step[0] != curDir[0] || step[1] != curDir[1]) &&
           V.OnBoard(x + step[0], y + step[1]) &&
           this.board[x + step[0]][y + step[1]] == V.EMPTY
         ) {
@@ -842,9 +859,21 @@ export class EightpiecesRules extends ChessRules {
         coord.x += step[0];
         coord.y += step[1];
       }
+      const L = this.sentryPush.length;
+      const pl = (!!this.sentryPush[L-1] ? this.sentryPush[L-1].length : 0);
       for (let xy of lancerPos) {
         const dir = V.LANCER_DIRS[this.board[xy.x][xy.y].charAt(1)];
-        if (dir[0] == -step[0] && dir[1] == -step[1]) return true;
+        if (
+          (dir[0] == -step[0] && dir[1] == -step[1]) ||
+          // If the lancer was just pushed, this is an attack too:
+          (
+            !!this.sentryPush[L-1] &&
+            this.sentryPush[L-1][pl-1].x == xy.x &&
+            this.sentryPush[L-1][pl-1].y == xy.y
+          )
+        ) {
+          return true;
+        }
       }
     }
     return false;