Add Knightrelay1. Some fixes. Move odd 'isAttackedBy_multiple_colors' to Checkered...
[vchess.git] / client / src / variants / Eightpieces.js
index 46fe6b8..a0eed50 100644 (file)
@@ -13,6 +13,11 @@ export const VariantRules = class EightpiecesRules extends ChessRules {
     return "l";
   }
 
+  static get IMAGE_EXTENSION() {
+    // Temporarily, for the time SVG pieces are being designed:
+    return ".png";
+  }
+
   // Lancer directions *from white perspective*
   static get LANCER_DIRS() {
     return {
@@ -41,9 +46,9 @@ export const VariantRules = class EightpiecesRules extends ChessRules {
   }
 
   getPpath(b, color, score, orientation) {
-    if ([V.JAILER, V.SENTRY].includes(b[1])) return "Eightpieces/" + b;
+    if ([V.JAILER, V.SENTRY].includes(b[1])) return "Eightpieces/tmp_png/" + b;
     if (Object.keys(V.LANCER_DIRS).includes(b[1])) {
-      if (orientation == 'w') return "Eightpieces/" + b;
+      if (orientation == 'w') return "Eightpieces/tmp_png/" + b;
       // Find opposite direction for adequate display:
       let oppDir = '';
       switch (b[1]) {
@@ -72,9 +77,10 @@ export const VariantRules = class EightpiecesRules extends ChessRules {
           oppDir = 'f';
           break;
       }
-      return "Eightpieces/" + b[0] + oppDir;
+      return "Eightpieces/tmp_png/" + b[0] + oppDir;
     }
-    return b;
+    // TODO: after we have SVG pieces, remove the folder and next prefix:
+    return "Eightpieces/tmp_png/" + b;
   }
 
   getPPpath(b, orientation) {
@@ -284,12 +290,14 @@ export const VariantRules = class EightpiecesRules extends ChessRules {
 
   getPotentialMovesFrom([x, y]) {
     // At subTurn == 2, jailers aren't effective (Jeff K)
+    const piece = this.getPiece(x, y);
+    const L = this.sentryPush.length;
     if (this.subTurn == 1) {
       const jsq = this.isImmobilized([x, y]);
       if (!!jsq) {
         let moves = [];
         // Special pass move if king:
-        if (this.getPiece(x, y) == V.KING) {
+        if (piece == V.KING) {
           moves.push(
             new Move({
               appear: [],
@@ -299,11 +307,26 @@ export const VariantRules = class EightpiecesRules extends ChessRules {
             })
           );
         }
+        else if (piece == V.LANCER && !!this.sentryPush[L-1]) {
+          // A pushed lancer next to the jailer: reorient
+          const color = this.getColor(x, y);
+          const curDir = this.board[x][y].charAt(1);
+          Object.keys(V.LANCER_DIRS).forEach(k => {
+            moves.push(
+              new Move({
+                appear: [{ x: x, y: y, c: color, p: k }],
+                vanish: [{ x: x, y: y, c: color, p: curDir }],
+                start: { x: x, y: y },
+                end: { x: jsq[0], y: jsq[1] }
+              })
+            );
+          });
+        }
         return moves;
       }
     }
     let moves = [];
-    switch (this.getPiece(x, y)) {
+    switch (piece) {
       case V.JAILER:
         moves = this.getPotentialJailerMoves([x, y]);
         break;
@@ -317,12 +340,15 @@ export const VariantRules = class EightpiecesRules extends ChessRules {
         moves = super.getPotentialMovesFrom([x, y]);
         break;
     }
-    const L = this.sentryPush.length;
     if (!!this.sentryPush[L-1]) {
-      // Delete moves walking back on sentry push path
+      // Delete moves walking back on sentry push path,
+      // only if not a pawn, and the piece is the pushed one.
+      const pl = this.sentryPush[L-1].length;
+      const finalPushedSq = this.sentryPush[L-1][pl-1];
       moves = moves.filter(m => {
         if (
           m.vanish[0].p != V.PAWN &&
+          m.start.x == finalPushedSq.x && m.start.y == finalPushedSq.y &&
           this.sentryPush[L-1].some(sq => sq.x == m.end.x && sq.y == m.end.y)
         ) {
           return false;
@@ -609,7 +635,7 @@ export const VariantRules = class EightpiecesRules extends ChessRules {
       i = y;
       do {
         if (
-          this.isAttacked([x, i], [oppCol]) ||
+          this.isAttacked([x, i], oppCol) ||
           (this.board[x][i] != V.EMPTY &&
             (this.getColor(x, i) != c ||
               ![V.KING, V.ROOK, V.JAILER].includes(this.getPiece(x, i))))
@@ -811,15 +837,15 @@ export const VariantRules = class EightpiecesRules extends ChessRules {
     this.sentryPush.pop();
   }
 
-  isAttacked(sq, colors) {
+  isAttacked(sq, color) {
     return (
-      super.isAttacked(sq, colors) ||
-      this.isAttackedByLancer(sq, colors) ||
-      this.isAttackedBySentry(sq, colors)
+      super.isAttacked(sq, color) ||
+      this.isAttackedByLancer(sq, color) ||
+      this.isAttackedBySentry(sq, color)
     );
   }
 
-  isAttackedBySlideNJump([x, y], colors, piece, steps, oneStep) {
+  isAttackedBySlideNJump([x, y], color, piece, steps, oneStep) {
     for (let step of steps) {
       let rx = x + step[0],
           ry = y + step[1];
@@ -829,8 +855,8 @@ export const VariantRules = class EightpiecesRules extends ChessRules {
       }
       if (
         V.OnBoard(rx, ry) &&
-        this.getPiece(rx, ry) === piece &&
-        colors.includes(this.getColor(rx, ry)) &&
+        this.getPiece(rx, ry) == piece &&
+        this.getColor(rx, ry) == color &&
         !this.isImmobilized([rx, ry])
       ) {
         return true;
@@ -839,27 +865,25 @@ export const VariantRules = class EightpiecesRules extends ChessRules {
     return false;
   }
 
-  isAttackedByPawn([x, y], colors) {
-    for (let c of colors) {
-      const pawnShift = c == "w" ? 1 : -1;
-      if (x + pawnShift >= 0 && x + pawnShift < V.size.x) {
-        for (let i of [-1, 1]) {
-          if (
-            y + i >= 0 &&
-            y + i < V.size.y &&
-            this.getPiece(x + pawnShift, y + i) == V.PAWN &&
-            this.getColor(x + pawnShift, y + i) == c &&
-            !this.isImmobilized([x + pawnShift, y + i])
-          ) {
-            return true;
-          }
+  isAttackedByPawn([x, y], color) {
+    const pawnShift = (color == "w" ? 1 : -1);
+    if (x + pawnShift >= 0 && x + pawnShift < V.size.x) {
+      for (let i of [-1, 1]) {
+        if (
+          y + i >= 0 &&
+          y + i < V.size.y &&
+          this.getPiece(x + pawnShift, y + i) == V.PAWN &&
+          this.getColor(x + pawnShift, y + i) == color &&
+          !this.isImmobilized([x + pawnShift, y + i])
+        ) {
+          return true;
         }
       }
     }
     return false;
   }
 
-  isAttackedByLancer([x, y], colors) {
+  isAttackedByLancer([x, y], color) {
     for (let step of V.steps[V.ROOK].concat(V.steps[V.BISHOP])) {
       // If in this direction there are only enemy pieces and empty squares,
       // and we meet a lancer: can he reach us?
@@ -870,7 +894,7 @@ export const VariantRules = class EightpiecesRules extends ChessRules {
         V.OnBoard(coord.x, coord.y) &&
         (
           this.board[coord.x][coord.y] == V.EMPTY ||
-          colors.includes(this.getColor(coord.x, coord.y))
+          this.getColor(coord.x, coord.y) == color
         )
       ) {
         if (
@@ -898,7 +922,7 @@ export const VariantRules = class EightpiecesRules extends ChessRules {
             absDeltaX = Math.abs(deltaX);
       const deltaY = y2 - y1,
             absDeltaY = Math.abs(deltaY);
-      const step = [ deltaX / absDeltaX, deltaY / absDeltaY ];
+      const step = [ deltaX / absDeltaX || 0, deltaY / absDeltaY || 0 ];
       if (
         // Check that the step is a priori valid:
         (absDeltaX != absDeltaY && deltaX != 0 && deltaY != 0) ||
@@ -907,7 +931,7 @@ export const VariantRules = class EightpiecesRules extends ChessRules {
         return false;
       }
       let sq = [ x1 + step[0], y1 + step[1] ];
-      while (sq[0] != x2 && sq[1] != y2) {
+      while (sq[0] != x2 || sq[1] != y2) {
         if (
           // NOTE: no need to check OnBoard in this special case
           (!lancer && this.board[sq[0]][sq[1]] != V.EMPTY) ||
@@ -952,17 +976,17 @@ export const VariantRules = class EightpiecesRules extends ChessRules {
     return false;
   }
 
-  isAttackedBySentry([x, y], colors) {
+  isAttackedBySentry([x, y], color) {
     // Attacked by sentry means it can self-take our king.
     // Just check diagonals of enemy sentry(ies), and if it reaches
     // one of our pieces: can I self-take?
-    const color = V.GetOppCol(colors[0]);
+    const myColor = V.GetOppCol(color);
     let candidates = [];
     for (let i=0; i<V.size.x; i++) {
       for (let j=0; j<V.size.y; j++) {
         if (
           this.getPiece(i,j) == V.SENTRY &&
-          colors.includes(this.getColor(i,j)) &&
+          this.getColor(i,j) == color &&
           !this.isImmobilized([i, j])
         ) {
           for (let step of V.steps[V.BISHOP]) {
@@ -976,7 +1000,7 @@ export const VariantRules = class EightpiecesRules extends ChessRules {
             }
             if (
               V.OnBoard(sq[0], sq[1]) &&
-              this.getColor(sq[0], sq[1]) == color
+              this.getColor(sq[0], sq[1]) == myColor
             ) {
               candidates.push([ sq[0], sq[1] ]);
             }
@@ -1054,9 +1078,24 @@ export const VariantRules = class EightpiecesRules extends ChessRules {
     return (!choice.second ? choice : [choice, choice.second]);
   }
 
+  // For moves notation:
+  static get LANCER_DIRNAMES() {
+    return {
+      'c': "N",
+      'd': "NE",
+      'e': "E",
+      'f': "SE",
+      'g': "S",
+      'h': "SW",
+      'm': "W",
+      'o': "NW"
+    };
+  }
+
   getNotation(move) {
     // Special case "king takes jailer" is a pass move
     if (move.appear.length == 0 && move.vanish.length == 0) return "pass";
+    let notation = undefined;
     if (this.subTurn == 2) {
       // Do not consider appear[1] (sentry) for sentry pushes
       const simpleMove = {
@@ -1065,8 +1104,11 @@ export const VariantRules = class EightpiecesRules extends ChessRules {
         start: move.start,
         end: move.end
       };
-      return super.getNotation(simpleMove);
-    }
-    return super.getNotation(move);
+      notation = super.getNotation(simpleMove);
+    } else notation = super.getNotation(move);
+    if (Object.keys(V.LANCER_DIRNAMES).includes(move.vanish[0].p))
+      // Lancer: add direction info
+      notation += "=" + V.LANCER_DIRNAMES[move.appear[0].p];
+    return notation;
   }
 };