Advances on Fanorona main
authorBenjamin Auder <benjamin.auder@somewhere>
Mon, 22 Jun 2026 16:46:24 +0000 (18:46 +0200)
committerBenjamin Auder <benjamin.auder@somewhere>
Mon, 22 Jun 2026 16:46:24 +0000 (18:46 +0200)
variants/Fanorona/class.js
variants/Fanorona/rules.html [new file with mode: 0644]
variants/Fanorona/style.css [new file with mode: 0644]
variants/Weiqi/class.js

index 01d662e..d9a9cdd 100644 (file)
@@ -1,79 +1,76 @@
-import { ChessRules, Move, PiPo } from "@/js/base_rules";
-import { randInt } from "@/utils/alea";
+import ChessRules from "/js/base_rules.js";
+import WeiqiRules from "/variants/Weiqi/class.js";
+// TODO: PiPo
 
 
-export class FanoronaRules extends ChessRules {
+export default class FanoronaRules extends ChessRules {
 
   static get Options() {
 
   static get Options() {
-    return null;
+    return {};
   }
 
   }
 
-  static get HasFlags() {
+  get hasFlags() {
     return false;
   }
 
     return false;
   }
 
-  static get HasEnpassant() {
+  get hasEnpassant() {
     return false;
   }
     return false;
   }
-
-  static get Monochrome() {
-    return true;
-  }
-
-  static get Lines() {
-    let lines = [];
-    // Draw all inter-squares lines, shifted:
-    for (let i = 0; i < V.size.x; i++)
-      lines.push([[i+0.5, 0.5], [i+0.5, V.size.y-0.5]]);
-    for (let j = 0; j < V.size.y; j++)
-      lines.push([[0.5, j+0.5], [V.size.x-0.5, j+0.5]]);
-    const columnDiags = [
-      [[0.5, 0.5], [2.5, 2.5]],
-      [[0.5, 2.5], [2.5, 0.5]],
-      [[2.5, 0.5], [4.5, 2.5]],
-      [[4.5, 0.5], [2.5, 2.5]]
-    ];
-    for (let j of [0, 2, 4, 6]) {
-      lines = lines.concat(
-        columnDiags.map(L => [[L[0][0], L[0][1] + j], [L[1][0], L[1][1] + j]])
-      );
-    }
-    return lines;
-  }
-
-  static get Notoodark() {
-    return true;
+  static get HasKing() {
+    return false;
   }
 
   }
 
-  static GenRandInitFen() {
-    return "ppppppppp/ppppppppp/pPpP1pPpP/PPPPPPPPP/PPPPPPPPP w 0";
+  genRandInitBaseFen() {
+    return {
+      fen: "sssssssss/sssssssss/sSsS1sSsS/SSSSSSSSS/SSSSSSSSS w 0",
+      o: {}
+    };
   }
 
   setOtherVariables(fen) {
     // Local stack of captures during a turn (squares + directions)
   }
 
   setOtherVariables(fen) {
     // Local stack of captures during a turn (squares + directions)
-    this.captures = [ [] ];
+    this.captures = [ [] ]; //TODO
   }
 
   }
 
-  static get size() {
+  get size() {
     return { x: 5, y: 9 };
   }
 
     return { x: 5, y: 9 };
   }
 
+  getSvgChessboard() {
+    return WeiqiRules.SvgChessboard_share(
+      this.playerColor, this.size, this.coordsToId);
+  }
+
   getPiece() {
   getPiece() {
-    return V.PAWN;
+    return 's';
+  }
+
+  pieceDef(piece, color, x, y) {
+    if (piece == 's') //stone
+      return { "class": "stone" };
+    // Arrow
+    if (piece.charCodeAt(0) >= 105) {
+      return {
+        "class": "arrow-" + (piece.charCodeAt(0) >= 105 ? "base" : "point")
+      };
+    }
+  }
+
+  // a,b,c,d,e,f,g,h : dot on point, N to NO
+  // i,j,k,l,m,n,o,p : dot on base, N to NO
+  static ArrowToAngle(arrow) {
+    let ccode = arrow.charCodeAt(0);
+    if (ccode >= 105) { //i
+      ccode -= 8;
+      arrow = String.fromCharCode(ccode);
+    }
+    return (45 * (ccode - 97)) + "deg";
   }
 
   }
 
-  getPPpath(m, orientation) {
-    // m.vanish.length >= 2, first capture gives direction
-    const ref = (Math.abs(m.vanish[1].x - m.start.x) == 1 ? m.start : m.end);
-    const step = [m.vanish[1].x - ref.x, m.vanish[1].y - ref.y];
-    const multStep = (orientation == 'w' ? 1 : -1);
-    const normalizedStep = [
-      multStep * step[0] / Math.abs(step[0]),
-      multStep * step[1] / Math.abs(step[1])
-    ];
-    return (
-      "Fanorona/arrow_" +
-      (normalizedStep[0] || 0) + "_" + (normalizedStep[1] || 0)
-    );
+  // Draw arrow
+  setPieceBackground(domPiece, piece) {
+    if (piece == 'p')
+      return;
+    domPiece.style.setProperty('--rotate-by', V.ArrowToAngle(piece));
   }
 
   // After moving, add stones captured in "step" direction from new location
   }
 
   // After moving, add stones captured in "step" direction from new location
@@ -82,17 +79,20 @@ export class FanoronaRules extends ChessRules {
     let [i, j] = [x + step[0], y + step[1]];
     const oppCol = V.GetOppCol(move.vanish[0].c);
     while (
     let [i, j] = [x + step[0], y + step[1]];
     const oppCol = V.GetOppCol(move.vanish[0].c);
     while (
-      V.OnBoard(i, j) &&
-      this.board[i][j] != V.EMPTY &&
+      this.onBoard(i, j) &&
+      this.board[i][j] != "" &&
       this.getColor(i, j) == oppCol
     ) {
       this.getColor(i, j) == oppCol
     ) {
-      move.vanish.push(new PiPo({ x: i, y: j, c: oppCol, p: V.PAWN }));
-      i += step[0];
-      j += step[1];
+      move.vanish.push(new PiPo({ x: i, y: j, c: oppCol, p: 's' }));
+      [i, j] = [i + step[0], j + step[1]];
     }
     return (move.vanish.length >= 2);
   }
 
     }
     return (move.vanish.length >= 2);
   }
 
+
+  // TODO from here
+
+
   getPotentialMovesFrom([x, y]) {
     const L0 = this.captures.length;
     const captures = this.captures[L0 - 1];
   getPotentialMovesFrom([x, y]) {
     const L0 = this.captures.length;
     const captures = this.captures[L0 - 1];
@@ -122,7 +122,7 @@ export class FanoronaRules extends ChessRules {
       let [i, j] = [x + s[0], y + s[1]];
       if (captures.some(c => c.square.x == i && c.square.y == j)) continue;
       if (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) {
       let [i, j] = [x + s[0], y + s[1]];
       if (captures.some(c => c.square.x == i && c.square.y == j)) continue;
       if (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) {
-        // The move is potentially allowed. Might lead to 2 different captures
+        // The move is potentially allowed. Might lead to 2 different captures ---------> TODO
         let mv = super.getBasicMove([x, y], [i, j]);
         const capt = this.addCapture([i, j], s, mv);
         if (capt) {
         let mv = super.getBasicMove([x, y], [i, j]);
         const capt = this.addCapture([i, j], s, mv);
         if (capt) {
diff --git a/variants/Fanorona/rules.html b/variants/Fanorona/rules.html
new file mode 100644 (file)
index 0000000..c65158e
--- /dev/null
@@ -0,0 +1 @@
+<p>TODO</p>
diff --git a/variants/Fanorona/style.css b/variants/Fanorona/style.css
new file mode 100644 (file)
index 0000000..287477f
--- /dev/null
@@ -0,0 +1,20 @@
+.chessboard_SVG {
+  background-color: #BA8C63;
+}
+
+piece.white.stone {
+  background-image: url('/pieces/Weiqi/black_stone.svg');
+}
+piece.black.stone {
+  background-image: url('/pieces/Weiqi/white_stone.svg');
+}
+
+.arrow-point {
+  background-image: url('/pieces/Fanorona/arrow_point.svg');
+  rotate: var(--rotate-by);
+}
+
+.arrow-base {
+  background-image: url('/pieces/Fanorona/arrow_base.svg');
+  rotate: var(--rotate-by);
+}
index 1a3bc4d..735c0f0 100644 (file)
@@ -38,19 +38,19 @@ export default class WeiqiRules extends ChessRules {
     return false;
   }
 
     return false;
   }
 
-  getSvgChessboard() {
-    const flipped = (this.playerColor == 'b');
+  static SvgChessboard_share(color, bsize, coordsToId) {
+    const flipped = (color == 'b');
     let board = `
       <svg
     let board = `
       <svg
-        viewBox="0 0 ${10*(this.size.y)} ${10*(this.size.x)}"
+        viewBox="0 0 ${10*(bsize.y)} ${10*(bsize.x)}"
         class="chessboard_SVG">`;
         class="chessboard_SVG">`;
-    for (let i=0; i < this.size.x; i++) {
-      for (let j=0; j < this.size.y; j++) {
-        const ii = (flipped ? this.size.x - 1 - i : i);
-        const jj = (flipped ? this.size.y - 1 - j : j);
+    for (let i=0; i < bsize.x; i++) {
+      for (let j=0; j < bsize.y; j++) {
+        const ii = (flipped ? bsize.x - 1 - i : i);
+        const jj = (flipped ? bsize.y - 1 - j : j);
         board += `
           <rect
         board += `
           <rect
-            id="${this.coordsToId({x: ii, y: jj})}"
+            id="${coordsToId({x: ii, y: jj})}"
             width="10"
             height="10"
             x="${10*j}"
             width="10"
             height="10"
             x="${10*j}"
@@ -60,14 +60,14 @@ export default class WeiqiRules extends ChessRules {
       }
     }
     // Add lines to delimitate "squares"
       }
     }
     // Add lines to delimitate "squares"
-    for (let i = 0; i < this.size.x; i++) {
-      const y = i * 10 + 5, maxX = this.size.y * 10 - 5;
+    for (let i = 0; i < bsize.x; i++) {
+      const y = i * 10 + 5, maxX = bsize.y * 10 - 5;
       board += `
         <line x1="5" y1="${y}" x2="${maxX}" y2="${y}"
               stroke="black" stroke-width="0.2"/>`;
     }
       board += `
         <line x1="5" y1="${y}" x2="${maxX}" y2="${y}"
               stroke="black" stroke-width="0.2"/>`;
     }
-    for (let i = 0; i < this.size.x; i++) {
-      const x = i * 10 + 5, maxY = this.size.x * 10 - 5;
+    for (let i = 0; i < bsize.x; i++) {
+      const x = i * 10 + 5, maxY = bsize.x * 10 - 5;
       board += `
         <line x1="${x}" y1="5" x2="${x}" y2="${maxY}"
               stroke="black" stroke-width="0.2"/>`;
       board += `
         <line x1="${x}" y1="5" x2="${x}" y2="${maxY}"
               stroke="black" stroke-width="0.2"/>`;
@@ -76,6 +76,10 @@ export default class WeiqiRules extends ChessRules {
     return board;
   }
 
     return board;
   }
 
+  getSvgChessboard() {
+    return V.SvgChessboard_share(this.playerColor, this.size, this.coordsToId);
+  }
+
   get size() {
     return {
       x: this.options["bsize"],
   get size() {
     return {
       x: this.options["bsize"],