Fix animation for Cylinder chess
[xogo.git] / base_rules.js
index df49f84..7191c56 100644 (file)
@@ -455,7 +455,7 @@ export default class ChessRules {
     const steps = this.pieces(this.playerColor)["p"].attack[0].steps;
     for (let step of steps) {
       const x = this.epSquare.x - step[0],
-            y = this.computeY(this.epSquare.y - step[1]);
+            y = this.getY(this.epSquare.y - step[1]);
       if (
         this.onBoard(x, y) &&
         this.getColor(x, y) == this.playerColor &&
@@ -1159,7 +1159,7 @@ export default class ChessRules {
   // MOVES GENERATION
 
   // For Cylinder: get Y coordinate
-  computeY(y) {
+  getY(y) {
     if (!this.options["cylinder"])
       return y;
     let res = y % this.size.y;
@@ -1180,13 +1180,13 @@ export default class ChessRules {
           const attacks = specs.attack || specs.moves;
           for (let a of attacks) {
             outerLoop: for (let step of a.steps) {
-              let [ii, jj] = [i + step[0], this.computeY(j + step[1])];
+              let [ii, jj] = [i + step[0], this.getY(j + step[1])];
               let stepCounter = 1;
               while (this.onBoard(ii, jj) && this.board[ii][jj] == "") {
                 if (a.range <= stepCounter++)
                   continue outerLoop;
                 ii += step[0];
-                jj = this.computeY(jj + step[1]);
+                jj = this.getY(jj + step[1]);
               }
               if (
                 this.onBoard(ii, jj) &&
@@ -1323,7 +1323,7 @@ export default class ChessRules {
         ];
         for (let step of steps) {
           let x = m.end.x + step[0];
-          let y = this.computeY(m.end.y + step[1]);
+          let y = this.getY(m.end.y + step[1]);
           if (
             this.onBoard(x, y) &&
             this.board[x][y] != "" &&
@@ -1455,7 +1455,7 @@ export default class ChessRules {
           if (a.range <= stepCounter++)
             continue outerLoop;
           i += step[0];
-          j = this.computeY(j + step[1]);
+          j = this.getY(j + step[1]);
         }
         if (
           this.onBoard(i, j) &&
@@ -1474,23 +1474,49 @@ export default class ChessRules {
     const color = this.getColor(x, y);
     const stepSpec = this.pieces(color, x, y)[piece];
     let moves = [];
-    let explored = {}; //for Cylinder mode
+    // Next 3 for Cylinder mode:
+    let explored = {};
+    let segments = [];
+    let segStart = [];
+
+    const addMove = (start, end) => {
+      let newMove = this.getBasicMove(start, end);
+      if (segments.length > 0) {
+        newMove.segments = JSON.parse(JSON.stringify(segments));
+        newMove.segments.push([[segStart[0], segStart[1]], [end[0], end[1]]]);
+      }
+      moves.push(newMove);
+    };
 
     const findAddMoves = (type, stepArray) => {
       for (let s of stepArray) {
-        // TODO: if jump in y (computeY, Cylinder), move.segments
         outerLoop: for (let step of s.steps) {
-          let [i, j] = [x + step[0], this.computeY(y + step[1])];
-          let stepCounter = 1;
-          while (this.onBoard(i, j) && this.board[i][j] == "") {
-            if (type != "attack" && !explored[i + "." + j]) {
+          segments = [];
+          segStart = [x, y];
+          let [i, j] = [x, y];
+          let stepCounter = 0;
+          while (
+            this.onBoard(i, j) &&
+            (this.board[i][j] == "" || (i == x && j == y))
+          ) {
+            if (
+              type != "attack" &&
+              !explored[i + "." + j] &&
+              (i != x || j != y)
+            ) {
               explored[i + "." + j] = true;
-              moves.push(this.getBasicMove([x, y], [i, j]));
+              addMove([x, y], [i, j]);
             }
             if (s.range <= stepCounter++)
               continue outerLoop;
+            const oldIJ = [i, j];
             i += step[0];
-            j = this.computeY(j + step[1]);
+            j = this.getY(j + step[1]);
+            if (Math.abs(j - oldIJ[1]) > 1) {
+              // Boundary between segments (cylinder mode)
+              segments.push([[segStart[0], segStart[1]], oldIJ]);
+              segStart = [i, j];
+            }
           }
           if (!this.onBoard(i, j))
             continue;
@@ -1511,7 +1537,7 @@ export default class ChessRules {
             )
           ) {
             explored[i + "." + j] = true;
-            moves.push(this.getBasicMove([x, y], [i, j]));
+            addMove([x, y], [i, j]);
           }
         }
       }
@@ -1521,26 +1547,29 @@ export default class ChessRules {
     if (specialAttack)
       findAddMoves("attack", stepSpec.attack);
     findAddMoves(specialAttack ? "moveonly" : "all", stepSpec.moves);
-    if (this.options["zen"])
-      Array.prototype.push.apply(moves, this.findCapturesOn([x, y], true));
+    if (this.options["zen"]) {
+      Array.prototype.push.apply(moves,
+                                 this.findCapturesOn([x, y], {zen: true}));
+    }
     return moves;
   }
 
-  findCapturesOn([x, y], zen) {
+  // Search for enemy (or not) pieces attacking [x, y]
+  findCapturesOn([x, y], args) {
     let moves = [];
-    // Find reverse captures (opponent takes)
-    const color = this.getColor(x, y);
-    const oppCol = C.GetOppCol(color);
+    if (!args.oppCol)
+      args.oppCol = C.GetOppCol(this.getColor(x, y) || this.turn);
     for (let i=0; i<this.size.x; i++) {
       for (let j=0; j<this.size.y; j++) {
         if (
           this.board[i][j] != "" &&
-          this.canTake([i, j], [x, y]) &&
+          this.getColor(i, j) == args.oppCol &&
           !this.isImmobilized([i, j])
         ) {
-          if (zen && this.isKing(this.getPiece(i, j)))
+          if (args.zen && this.isKing(this.getPiece(i, j)))
             continue; //king not captured in this way
-          const stepSpec = this.pieces(oppCol, i, j)[this.getPieceType(i, j)];
+          const stepSpec =
+            this.pieces(args.oppCol, i, j)[this.getPieceType(i, j)];
           const attacks = stepSpec.attack || stepSpec.moves;
           for (let a of attacks) {
             for (let s of a.steps) {
@@ -1548,15 +1577,23 @@ export default class ChessRules {
               if (!C.CompatibleStep([i, j], [x, y], s, a.range))
                 continue;
               // Finally verify that nothing stand in-between
-              let [ii, jj] = [i + s[0], this.computeY(j + s[1])];
+              let [ii, jj] = [i + s[0], this.getY(j + s[1])];
               let stepCounter = 1;
-              while (this.onBoard(ii, jj) && this.board[ii][jj] == "") {
+              while (
+                this.onBoard(ii, jj) &&
+                this.board[ii][jj] == "" &&
+                (ii != x || jj != y) //condition to attack empty squares too
+              ) {
                 ii += s[0];
-                jj = this.computeY(jj + s[1]);
+                jj = this.getY(jj + s[1]);
               }
               if (ii == x && jj == y) {
-                moves.push(this.getBasicMove([x, y], [i, j]));
-                if (!zen)
+                if (args.zen)
+                  // Reverse capture:
+                  moves.push(this.getBasicMove([x, y], [i, j]));
+                else
+                  moves.push(this.getBasicMove([i, j], [x, y]));
+                if (args.one)
                   return moves; //test for underCheck
               }
             }
@@ -1695,7 +1732,7 @@ export default class ChessRules {
     if (
       !!this.epSquare &&
       this.epSquare.x == x + shiftX &&
-      Math.abs(this.computeY(this.epSquare.y - y)) == 1 &&
+      Math.abs(this.getY(this.epSquare.y - y)) == 1 &&
       this.getColor(x, this.epSquare.y) == oppCol //Doublemove guard...
     ) {
       const [epx, epy] = [this.epSquare.x, this.epSquare.y];
@@ -1813,11 +1850,13 @@ export default class ChessRules {
   ////////////////////
   // MOVES VALIDATION
 
-  // Is (king at) given position under check by "color" ?
-  underCheck([x, y], color) {
+  // Is (king at) given position under check by "oppCol" ?
+  underCheck([x, y], oppCol) {
     if (this.options["taking"] || this.options["dark"])
       return false;
-    return (this.findCapturesOn([x, y]).length >= 1);
+    return (
+      this.findCapturesOn([x, y], {oppCol: oppCol, one: true}).length >= 1
+    );
   }
 
   // Stop at first king found (TODO: multi-kings)
@@ -2158,6 +2197,12 @@ export default class ChessRules {
     let container =
       document.getElementById(this.containerId)
     const r = container.querySelector(".chessboard").getBoundingClientRect();
+    if (typeof move.start.x == "string") {
+      // Need to bound width/height (was 100% for reserve pieces)
+      const pieceWidth = this.getPieceWidth(r.width);
+      movingPiece.style.width = pieceWidth + "px";
+      movingPiece.style.height = pieceWidth + "px";
+    }
     const maxDist = this.getMaxDistance(r.width);
     const pieces = this.pieces();
     if (move.drag) {
@@ -2185,7 +2230,7 @@ export default class ChessRules {
       // TODO: unclear why we need this new delay below:
       setTimeout(() => {
         movingPiece.style.transitionDuration = duration + "s";
-        // movingPiece is child of container: no need to adjust cordinates
+        // movingPiece is child of container: no need to adjust coordinates
         movingPiece.style.transform = `translate(${arr[0]}px, ${arr[1]}px)`;
         setTimeout(cb, duration * 1000);
       }, 50);