Fix Dynamo complete_rules. Started rewriting of Eightpieces main
authorBenjamin Auder <benjamin.auder@somewhere>
Thu, 5 Jun 2025 16:05:26 +0000 (18:05 +0200)
committerBenjamin Auder <benjamin.auder@somewhere>
Thu, 5 Jun 2025 16:05:26 +0000 (18:05 +0200)
base_rules.js
variants/Dynamo/complete_rules.html
variants/Eightpieces/class.js
variants/Eightpieces/complete_rules.html
variants/Eightpieces/rules.html

index 912b08f..de3fa44 100644 (file)
@@ -175,6 +175,14 @@ export default class ChessRules {
     return Object.values(cd).map(c => c.toString(36)).join("");
   }
 
+  // b4 --> {x:4, y:1}
+  coordsFromUsual(sq) {
+    return {
+      x: this.size.x - parseInt(sq.charAt(1), 10),
+      y: sq.charCodeAt(0) - 97
+    };
+  }
+
   coordsToId(cd) {
     if (typeof cd.x == "number") {
       return (
@@ -651,8 +659,7 @@ export default class ChessRules {
         this[arrName] = ArrayFun.init(this.size.x, this.size.y, null);
       if (arrName == "d_pieces")
         this.marks.forEach((m) => {
-          const formattedSquare = C.SquareFromUsual(m);
-          const mCoords = C.SquareToCoords(formattedSquare);
+          const mCoords = this.coordsFromUsual(m);
           addPiece(mCoords.x, mCoords.y, arrName, "mark");
         });
     };
index 68e9cc0..5856fc2 100644 (file)
@@ -36,7 +36,7 @@
 
 <figure>
   <div class="diag"
-       data-fen='rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR ...'
+       data-fen='rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w 0 {"flags":"0707","amove":"-"}'
        data-mks="e1,e3,e4,c3,f3,g4,h5,d3,c4,b5,a6">
   </div>
   <figcaption>Possible "pawn moves" in the initial position.</figcaption>
 
 <figure>
   <div class="diag left"
-       data-fen='rnbqkbnr/ppp1pppp/8/3p4/8/2N5/PPPPPPPP/R1BQKBNR ...'>
+       data-fen='rnbqkbnr/ppp1pppp/8/3p4/8/2N5/PPPPPPPP/R1BQKBNR w 0 {"flags":"0707","amove":"-"}'>
   </div>
   <div class="diag right"
-       data-fen='rnbqkbnr/ppp1pppp/8/8/8/2p5/PPPPPPPP/RNBQKBNR ...'>
+       data-fen='rnbqkbnr/ppp1pppp/8/8/8/2p5/PPPPPPPP/RNBQKBNR w 0 {"flags":"0707","amove":"-"}'>
   </div>
   <figcaption>
     Pulling the d5 pawn to c3 (left: before, right: after).
@@ -80,7 +80,7 @@
 
 <figure>
   <div class="diag"
-       data-fen='rnb1qbnr/pppkpppp/3p4/8/Q1P5/5NP1/PP1PPP1P/RNB1KB1R ...'>
+       data-fen='rnb1qbnr/pppkpppp/3p4/8/Q1P5/5NP1/PP1PPP1P/RNB1KB1R w 0 {"flags":"0707","amove":"-"}'>
   </div>
   <figcaption>
     Check: the queen threatens to pull the king off the board
 
 <figure>
   <div class="diag left"
-       data-fen='rnbqk1nr/ppppppbp/6p1/8/3B4/1P6/P1PPPPPP/RN1QKBNR ...'>
+       data-fen='rnbqk1nr/ppppppbp/6p1/8/3B4/1P6/P1PPPPPP/RN1QKBNR w 0 {"flags":"0707","amove":"-"}'>
   </div>
   <div class="diag right"
-       data-fen='rnbqk1nr/pppppp1p/6p1/8/3b4/1P6/PBPPPPPP/RN1QKBNR ...'>
+       data-fen='rnbqk1nr/pppppp1p/6p1/8/3b4/1P6/PBPPPPPP/RN1QKBNR w 0 {"flags":"0707","amove":"-"}'>
   <figcaption>
     Pushing the d4 bishop to b2 (left: before, right: after).
   </figcaption>
 
 <figure>
   <div class="diag"
-       data-fen='8/4B3/8/8/6Qk/8/4N3/K7 ...'>
+       data-fen='8/4B3/8/8/6Qk/8/4N3/K7 w 0 {"flags":"0707","amove":"-"}'>
   </div>
   <figcaption>Dynamo checkmate ("Dynamate" :) )</figcaption>
 </figure>
   <a href="http://www.pion.ch/echecs/variante.php?jeu=dynamo">this page</a>
   might help too.
 </p>
+
+</body>
+<script src="/utils/drawDiagrams.js"></script>
+<script>fenToDiag("Dynamo");</script>
+</html>
index 3808a16..eb68c76 100644 (file)
@@ -1,99 +1,75 @@
-import { randInt, sample } from "@/utils/alea";
-import { ChessRules, PiPo, Move } from "@/base_rules";
+//import { randInt, sample } from "@/utils/alea";
+import ChessRules from "/base_rules.js";
+//PiPo, Move ?
 
-export class EightpiecesRules extends ChessRules {
+export default class EightpiecesRules extends ChessRules {
 
-  static get JAILER() {
-    return "j";
-  }
-  static get SENTRY() {
-    return "s";
-  }
-  static get LANCER() {
-    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() {
+  static get Options() {
     return {
-      'c': [-1, 0], //north
-      'd': [-1, 1], //N-E
-      'e': [0, 1], //east
-      'f': [1, 1], //S-E
-      'g': [1, 0], //south
-      'h': [1, -1], //S-W
-      'm': [0, -1], //west
-      'o': [-1, -1] //N-W
+      select: C.Options.select,
+      input: [],
+      styles: ["doublemove", "progressive"]
     };
   }
 
-  static get PIECES() {
-    return ChessRules.PIECES
-      .concat([V.JAILER, V.SENTRY])
-      .concat(Object.keys(V.LANCER_DIRS));
-  }
+// TODO: variable (setupOthers) for lancers directions (x,y) => dir ("0, 1, 2, ...") 0 = top 1 = north east... / white viewpoint
+
+//variable lancer_orient ... --> array size 8 x 8 (TODO?)
+  //
 
-  getPiece(i, j) {
-    const piece = this.board[i][j].charAt(1);
-    // Special lancer case: 8 possible orientations
-    if (Object.keys(V.LANCER_DIRS).includes(piece)) return V.LANCER;
-    return piece;
+  static get LANCER_STEP() {
+    return {
+      'N': [-1, 0],
+      'NE': [-1, 1],
+      'E': [0, 1],
+      'SE': [1, 1],
+      'S': [1, 0],
+      'SO': [1, 61],
+      'O': [0, -1],
+      'NO': [-1, -1]
+    };
   }
 
-  getPpath(b, color, score, orientation) {
-    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/tmp_png/" + b;
-      // Find opposite direction for adequate display:
-      let oppDir = '';
-      switch (b[1]) {
-        case 'c':
-          oppDir = 'g';
-          break;
-        case 'g':
-          oppDir = 'c';
-          break;
-        case 'd':
-          oppDir = 'h';
-          break;
-        case 'h':
-          oppDir = 'd';
-          break;
-        case 'e':
-          oppDir = 'm';
-          break;
-        case 'm':
-          oppDir = 'e';
-          break;
-        case 'f':
-          oppDir = 'o';
-          break;
-        case 'o':
-          oppDir = 'f';
-          break;
+  pieces(color, x, y) {
+    let basePieces = super.pieces(color, x, y);
+    const extension = {
+      'j': {
+        "class": "jailer",
+        moves: [
+          {
+            steps: [[1, 0], [0, 1], [-1, 0], [0, -1]]
+          }
+        ]
+      },
+      's': {
+        "class": "sentry",
+        moves: [
+          {
+            steps: [[1, 1], [1, -1], [-1, 1], [-1, -1]]
+          }
+        ]
+      },
+      'l': {
+        "class": "lancer",
+        both: [
+          {
+            steps: [ V.LANCER_STEP [
+              this.lancer_orient[(x*this.size.y+y).toString()] ]
+            ]
+          }
+        ]
       }
-      return "Eightpieces/tmp_png/" + b[0] + oppDir;
-    }
-    // TODO: after we have SVG pieces, remove the folder and next prefix:
-    return "Eightpieces/tmp_png/" + b;
+    };
   }
 
-  getPPpath(m, orientation) {
-    return (
-      this.getPpath(
-        m.appear[0].c + m.appear[0].p,
-        null,
-        null,
-        orientation
-      )
-    );
+  // lorient : "{z1:NO,z2:SE, ...etc}"
+  setOtherVariables(fenParsed) {
+    super.setOtherVariables(fenParsed);
+    this.lancer_orient = JSON.parse(fenParsed.lorient);
   }
 
+  //TODO: from here
+
   static ParseFen(fen) {
     const fenParts = fen.split(" ");
     return Object.assign(
@@ -102,19 +78,6 @@ export class EightpiecesRules extends ChessRules {
     );
   }
 
-  static IsGoodFen(fen) {
-    if (!ChessRules.IsGoodFen(fen)) return false;
-    const fenParsed = V.ParseFen(fen);
-    // 5) Check sentry push (if any)
-    if (
-      fenParsed.sentrypush != "-" &&
-      !fenParsed.sentrypush.match(/^([a-h][1-8]){2,2}$/)
-    ) {
-      return false;
-    }
-    return true;
-  }
-
   getFen() {
     return super.getFen() + " " + this.getSentrypushFen();
   }
index c1d12ab..d12574f 100644 (file)
@@ -1,48 +1,74 @@
-p.boxed
-  | Three new pieces appear. All pieces are unique.
+<html>
+<head>
+  <title>Eightpieces Rules</title>
+  <link href="/common.css" rel="stylesheet"/>
+  <link href="/variants/Eightpieces/style.css" rel="stylesheet"/>
+</head>
+<body>
+<div class="full-rules">
+<h1>Eightpieces Rules</h1>
 
-p.
+<p>
+  Three new pieces appear. All pieces are unique.
+</p>
+
+<p>
   There are only one rook, one bishop and one knight per side in this variant.
   That explains the name. The king and queen are still there,
   and the three remaining slots are taken by new pieces:
+</p>
 
-ul
-  li.
+<ul>
+  <li>
     The lancer 'L' is oriented and can only move in the direction it points,
     by any number of squares as long as an enemy isn't met
     (it can jump over friendly pieces). If an opponent' piece is found,
     it can be captured. After moving you can reorient the lancer.
-  li.
+  </li>
+  <li>
     The sentry 'S' moves like a bishop but doesn't capture directly.
     It "pushes" enemy pieces instead, either on an empty square or on other
     enemy pieces which are thus (self-)captured.
-  li.
+  </li>
+  <li>
     The jailer 'J' moves like a rook but also doesn't capture.
     It immobilizes enemy pieces which are vertically or horizontally adjacent.
+  </li>
+</ul>
 
-p.
+<p>
   On the following diagram the white sentry can push the black lancer to
   capture the black pawn on b4. The lancer is then immobilized
   by the white jailer at a4.
+</p>
+
+<figure>
+  <div class="diag left"
+       data-fen='7k/8/8/8/Jp3m2/8/3S4/K7 ...'>
+  </div>
+  <div class="diag right"
+       data-fen='7k/8/8/8/Jm3S2/8/8/K7 ...'>
+  </div>
+  <figcaption>Left: before white move S"push"f4. Right: after this move.</figcaption>
+</figure>
+
+<span>To reorient a stuck lancer,</span>
+<ul>
+  <li>Just after being pushed: play a move which 'capture your king".</li>
+  <li>Later in the game: click on the lancer.</li>
+</ul>
+
+<h3>Complete rules</h3>
+
+<p>
+  The rules were invented by Jeff Kubach (2020), who described them much
+  more precisely on the 
+  <a href="https://www.chessvariants.com/rules/8-piece-chess">chessvariants page</a>.
+  While the summary given above may suffice to start playing,
+  you should read the complete rules to fully understand this variant.
+</p>
 
-figure.diagram-container
-  .diagram.diag12
-    | fen:7k/8/8/8/Jp3m2/8/3S4/K7:
-  .diagram.diag22
-    | 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
-  | The rules were invented by Jeff Kubach (2020), who described them much
-  | more precisely on the 
-  a(href="https://www.chessvariants.com/rules/8-piece-chess")
-    | chessvariants page
-  | . While the summary given above may suffice to start playing,
-  | you should read the complete rules to fully understand this variant.
+</body>
+<script src="/utils/drawDiagrams.js"></script>
+<script>fenToDiag("Eightpieces");</script>
+</html>
index 41e9d42..69ac8aa 100644 (file)
@@ -1,3 +1,7 @@
-Three new pieces appear: the lancer is a rook with a constrained direction, the sentry moves like a bishop and pushes pieces, and the jailer immobilizes pieces orthogonally adjacent.
+<p>
+  Three new pieces appear: the lancer is a rook with a constrained direction,
+  the sentry moves like a bishop and pushes pieces,
+  and the jailer immobilizes pieces orthogonally adjacent.
+</p>
 
-The goal is still to checkmate.
+<p>The goal is still to checkmate.</p>