Experimental in-place reorientation for Eightpieces + small fixes in BaseGame
authorBenjamin Auder <benjamin.auder@somewhere>
Wed, 27 May 2020 02:35:23 +0000 (04:35 +0200)
committerBenjamin Auder <benjamin.auder@somewhere>
Wed, 27 May 2020 02:35:23 +0000 (04:35 +0200)
client/src/components/BaseGame.vue
client/src/translations/rules/Balaklava/en.pug
client/src/translations/rules/Balaklava/es.pug
client/src/translations/rules/Balaklava/fr.pug
client/src/translations/rules/Eightpieces/en.pug
client/src/translations/rules/Eightpieces/es.pug
client/src/translations/rules/Eightpieces/fr.pug
client/src/variants/Eightpieces.js

index 87d18ab..61c67de 100644 (file)
@@ -230,33 +230,34 @@ export default {
       const firstMoveColor = parsedFen.turn;
       this.firstMoveNumber = Math.floor(parsedFen.movesCount / 2) + 1;
       let L = this.moves.length;
       const firstMoveColor = parsedFen.turn;
       this.firstMoveNumber = Math.floor(parsedFen.movesCount / 2) + 1;
       let L = this.moves.length;
-      if (L == 0) {
-        // Could be started on a random position in analysis mode:
-        this.incheck = this.vr.getCheckSquares();
-        this.score = this.vr.getCurrentScore();
-        if (this.score != '*') {
-          // Show score on screen
-          const message = getScoreMessage(this.score);
-          this.showEndgameMsg(this.score + " . " + this.st.tr[message]);
-        }
-      }
-      else {
-        this.moves.forEach((move,idx) => {
-          // Strategy working also for multi-moves:
-          if (!Array.isArray(move)) move = [move];
-          const Lm = move.length;
-          move.forEach((m,idxM) => {
-            m.notation = this.vr.getNotation(m);
-            m.unambiguous = V.GetUnambiguousNotation(m);
-            this.vr.play(m);
-            const checkSquares = this.vr.getCheckSquares();
-            if (checkSquares.length > 0) m.notation += "+";
-            if (idxM == Lm - 1) m.fen = this.vr.getFen();
-            if (idx == L - 1 && idxM == Lm - 1) this.incheck = checkSquares;
-          });
-          this.score = this.vr.getCurrentScore();
-          if (["1-0", "0-1"].includes(this.score)) m.notation += "#";
+      this.moves.forEach((move,idx) => {
+        // Strategy working also for multi-moves:
+        if (!Array.isArray(move)) move = [move];
+        move.forEach(m => {
+          m.notation = this.vr.getNotation(m);
+          m.unambiguous = V.GetUnambiguousNotation(m);
+          this.vr.play(m);
         });
         });
+        const Lm = move.length;
+        move[Lm - 1].fen = this.vr.getFen();
+        if (idx < L - 1 && this.vr.getCheckSquares().length > 0)
+          move[Lm - 1].notation += "+";
+      });
+      this.incheck = this.vr.getCheckSquares();
+      this.score = this.vr.getCurrentScore();
+      if (L >= 1) {
+        const move =
+          !Array.isArray(this.moves[L - 1])
+            ? [this.moves[L - 1]]
+            : this.moves[L - 1];
+        const Lm = move.length;
+        if (["1-0", "0-1"].includes(this.score)) move[Lm - 1].notation += "#";
+        else if (this.incheck.length > 0) move[Lm - 1].notation += "+";
+      }
+      if (this.score != '*') {
+        // Show score on screen
+        const message = getScoreMessage(this.score);
+        this.showEndgameMsg(this.score + " . " + this.st.tr[message]);
       }
       if (firstMoveColor == "b") {
         // 'start' & 'end' is required for Board component
       }
       if (firstMoveColor == "b") {
         // 'start' & 'end' is required for Board component
@@ -431,8 +432,11 @@ export default {
     },
     clickSquare: function(square) {
       // Some variants make use of a single click at specific times:
     },
     clickSquare: function(square) {
       // Some variants make use of a single click at specific times:
-      const move = this.vr.doClick(square);
-      if (!!move) this.play(move);
+      const move_s = this.vr.doClick(square);
+      if (!!move_s) {
+        if (!Array.isArray(move_s)) this.play(move_s);
+        else this.$refs["board"].choices = move_s;
+      }
     },
     // "light": if gotoMove() or gotoEnd()
     play: function(move, received, light, autoplay) {
     },
     // "light": if gotoMove() or gotoEnd()
     play: function(move, received, light, autoplay) {
@@ -480,9 +484,6 @@ export default {
             this.lastMove = [this.lastMove, smove];
           else this.lastMove.push(smove);
         }
             this.lastMove = [this.lastMove, smove];
           else this.lastMove.push(smove);
         }
-        // Is opponent (or me) in check?
-        this.incheck = this.vr.getCheckSquares();
-        if (this.incheck.length > 0) smove.notation += "+";
         if (!this.inMultimove) {
           // First sub-move:
           this.lastMove = smove;
         if (!this.inMultimove) {
           // First sub-move:
           this.lastMove = smove;
@@ -555,6 +556,8 @@ export default {
             smove.fen = this.vr.getFen();
           this.emitFenIfAnalyze();
           this.inMultimove = false;
             smove.fen = this.vr.getFen();
           this.emitFenIfAnalyze();
           this.inMultimove = false;
+          this.incheck = this.vr.getCheckSquares();
+          if (this.incheck.length > 0) smove.notation += "+";
           this.score = computeScore();
           if (this.autoplay) {
             if (this.cursor < this.moves.length - 1)
           this.score = computeScore();
           if (this.autoplay) {
             if (this.cursor < this.moves.length - 1)
index 6ed42f5..aef3a7a 100644 (file)
@@ -2,8 +2,9 @@ p.boxed
   | Pieces can also move as a knight. The knight is replaced by a mammoth.
 
 p.
   | Pieces can also move as a knight. The knight is replaced by a mammoth.
 
 p.
-  In addition to their usual abilities, pawns and non-royal pieces (eveything
+  In addition to their usual abilities, pawns and non-royal pieces (everything
   but the king) may make non-capturing knight moves.
   but the king) may make non-capturing knight moves.
+  Pawns move forward only.
 
 p.
   The new piece instead of the knight is a Mammoth: it leaps two squares in
 
 p.
   The new piece instead of the knight is a Mammoth: it leaps two squares in
index 1218cf4..8407967 100644 (file)
@@ -5,6 +5,7 @@ p.boxed
 p.
   Además de sus habilidades habituales, peones y piezas no reales
   (todo excepto el rey) puede hacer saltos de caballo non capturado.
 p.
   Además de sus habilidades habituales, peones y piezas no reales
   (todo excepto el rey) puede hacer saltos de caballo non capturado.
+  Los peones solo avanzan.
 
 p.
   La nueva pieza reemplaza para el caballo es un Mamut: salta dos
 
 p.
   La nueva pieza reemplaza para el caballo es un Mamut: salta dos
index 8b22d69..c5a155f 100644 (file)
@@ -5,6 +5,7 @@ p.boxed
 p.
   En plus de leurs capacités habituelles, les pions et pièces non royales
   (tout sauf le roi) peuvent effectuer des coups de cavalier non capturants.
 p.
   En plus de leurs capacités habituelles, les pions et pièces non royales
   (tout sauf le roi) peuvent effectuer des coups de cavalier non capturants.
+  Les pions ne se déplacent que vers l'avant.
 
 p.
   La nouvelle pièce remplaçant le cavalier est un Mammouth : il saute de deux
 
 p.
   La nouvelle pièce remplaçant le cavalier est un Mammouth : il saute de deux
index 6610552..c1d12ab 100644 (file)
@@ -32,6 +32,11 @@ figure.diagram-container
     | fen:7k/8/8/8/Jm3S2/8/8/K7:
   figcaption Left: before white move S"push"f4. Right: after this move.
 
     | fen:7k/8/8/8/Jm3S2/8/8/K7:
   figcaption Left: before white move S"push"f4. Right: after this move.
 
+p To reorient a stuck lancer,
+ul
+  li Just after being pushed: play a move which 'capture your king".
+  li Later in the game: click on the lancer.
+
 h3 Complete rules
 
 p
 h3 Complete rules
 
 p
index 9ef6a66..6299266 100644 (file)
@@ -38,6 +38,11 @@ figure.diagram-container
     Izquierda: antes del movimiento blanco S"empuja"f4.
     Derecha: después de esta jugada.
 
     Izquierda: antes del movimiento blanco S"empuja"f4.
     Derecha: después de esta jugada.
 
+p Para redirigir una lanza atascada,
+ul
+  li Justo después de ser empujado: haz un movimiento que "capture a tu rey".
+  li Más adelante en el juego: haz clic en la lanza.
+
 h3 Reglas completas
 
 p
 h3 Reglas completas
 
 p
index a91103b..d03e534 100644 (file)
@@ -35,6 +35,11 @@ figure.diagram-container
     | fen:7k/8/8/8/Jm3S2/8/8/K7:
   figcaption Gauche : avant le coup blanc S"pousse"f4. Droite : après ce coup.
 
     | fen:7k/8/8/8/Jm3S2/8/8/K7:
   figcaption Gauche : avant le coup blanc S"pousse"f4. Droite : après ce coup.
 
+p Pour réorienter un lancier coincé,
+ul
+  li Juste après avoir été poussé : jouez un coup qui "capture votre roi".
+  li Plus tard dans le jeu : cliquez sur le lancier.
+
 h3 Règles complètes
 
 p
 h3 Règles complètes
 
 p
index 8cf8747..6efb182 100644 (file)
@@ -317,9 +317,9 @@ export class EightpiecesRules extends ChessRules {
   }
 
   getPotentialMovesFrom([x, y]) {
   }
 
   getPotentialMovesFrom([x, y]) {
-    // At subTurn == 2, jailers aren't effective (Jeff K)
     const piece = this.getPiece(x, y);
     const L = this.sentryPush.length;
     const piece = this.getPiece(x, y);
     const L = this.sentryPush.length;
+    // At subTurn == 2, jailers aren't effective (Jeff K)
     if (this.subTurn == 1) {
       const jsq = this.isImmobilized([x, y]);
       if (!!jsq) {
     if (this.subTurn == 1) {
       const jsq = this.isImmobilized([x, y]);
       if (!!jsq) {
@@ -473,6 +473,60 @@ export class EightpiecesRules extends ChessRules {
     return moves;
   }
 
     return moves;
   }
 
+  doClick(square) {
+    if (isNaN(square[0])) return null;
+    const L = this.sentryPush.length;
+    const [x, y] = [square[0], square[1]];
+    const color = this.turn;
+    if (
+      this.subTurn == 2 ||
+      this.board[x][y] == V.EMPTY ||
+      this.getPiece(x, y) != V.LANCER ||
+      this.getColor(x, y) != color ||
+      !!this.sentryPush[L-1]
+    ) {
+      return null;
+    }
+    // Stuck lancer?
+    const orientation = this.board[x][y][1];
+    const step = V.LANCER_DIRS[orientation];
+    if (!V.OnBoard(x + step[0], y + step[1])) {
+      let choices = [];
+      Object.keys(V.LANCER_DIRS).forEach(k => {
+        const dir = V.LANCER_DIRS[k];
+        if (
+          (dir[0] != step[0] || dir[1] != step[1]) &&
+          V.OnBoard(x + dir[0], y + dir[1])
+        ) {
+          choices.push(
+            new Move({
+              vanish: [
+                new PiPo({
+                  x: x,
+                  y: y,
+                  c: color,
+                  p: orientation
+                })
+              ],
+              appear: [
+                new PiPo({
+                  x: x,
+                  y: y,
+                  c: color,
+                  p: k
+                })
+              ],
+              start: { x: x, y : y },
+              end: { x: -1, y: -1 }
+            })
+          );
+        }
+      });
+      return choices;
+    }
+    return null;
+  }
+
   // Obtain all lancer moves in "step" direction
   getPotentialLancerMoves_aux([x, y], step, tr) {
     let moves = [];
   // Obtain all lancer moves in "step" direction
   getPotentialLancerMoves_aux([x, y], step, tr) {
     let moves = [];
@@ -502,6 +556,7 @@ export class EightpiecesRules extends ChessRules {
     // Except if just after a push: allow all movements from init square then
     const L = this.sentryPush.length;
     const color = this.getColor(x, y);
     // Except if just after a push: allow all movements from init square then
     const L = this.sentryPush.length;
     const color = this.getColor(x, y);
+    const dirCode = this.board[x][y][1];
     if (!!this.sentryPush[L-1]) {
       // Maybe I was pushed
       const pl = this.sentryPush[L-1].length;
     if (!!this.sentryPush[L-1]) {
       // Maybe I was pushed
       const pl = this.sentryPush[L-1].length;
@@ -512,7 +567,43 @@ 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.
         // 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[this.board[x][y].charAt(1)];
+        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];
+          let reorientMoves = [];
+          Object.keys(V.LANCER_DIRS).forEach(k => {
+            const dir = V.LANCER_DIRS[k];
+            if (
+              (dir[0] != curDir[0] || dir[1] != curDir[1]) &&
+              V.OnBoard(x + dir[0], y + dir[1])
+            ) {
+              reorientMoves.push(
+                new Move({
+                  vanish: [
+                    new PiPo({
+                      x: x,
+                      y: y,
+                      c: color,
+                      p: dirCode
+                    })
+                  ],
+                  appear: [
+                    new PiPo({
+                      x: x,
+                      y: y,
+                      c: color,
+                      p: k
+                    })
+                  ],
+                  start: { x: x, y : y },
+                  end: { x: kp[0], y: kp[1] }
+                })
+              );
+            }
+          });
+          Array.prototype.push.apply(moves, reorientMoves);
+        }
         Object.values(V.LANCER_DIRS).forEach(step => {
           const dirCode = Object.keys(V.LANCER_DIRS).find(k => {
             return (
         Object.values(V.LANCER_DIRS).forEach(step => {
           const dirCode = Object.keys(V.LANCER_DIRS).find(k => {
             return (
@@ -543,7 +634,6 @@ export class EightpiecesRules extends ChessRules {
       }
     }
     // I wasn't pushed: standard lancer move
       }
     }
     // I wasn't pushed: standard lancer move
-    const dirCode = this.board[x][y][1];
     const monodirMoves =
       this.getPotentialLancerMoves_aux([x, y], V.LANCER_DIRS[dirCode]);
     // Add all possible orientations aftermove except if I'm being pushed
     const monodirMoves =
       this.getPotentialLancerMoves_aux([x, y], V.LANCER_DIRS[dirCode]);
     // Add all possible orientations aftermove except if I'm being pushed
@@ -1052,7 +1142,16 @@ export class EightpiecesRules extends ChessRules {
         end: move.end
       };
       notation = super.getNotation(simpleMove);
         end: move.end
       };
       notation = super.getNotation(simpleMove);
-    } else notation = super.getNotation(move);
+    }
+    else if (
+      move.appear.length > 0 &&
+      move.vanish[0].x == move.appear[0].x &&
+      move.vanish[0].y == move.appear[0].y
+    ) {
+      // Lancer in-place reorientation:
+      notation = "L" + V.CoordsToSquare(move.start) + ":R";
+    }
+    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];
     if (Object.keys(V.LANCER_DIRNAMES).includes(move.vanish[0].p))
       // Lancer: add direction info
       notation += "=" + V.LANCER_DIRNAMES[move.appear[0].p];