Fix Avalam, Bario, Balaklava main
authorBenjamin Auder <benjamin.auder@somewhere>
Mon, 11 May 2026 16:19:38 +0000 (18:19 +0200)
committerBenjamin Auder <benjamin.auder@somewhere>
Mon, 11 May 2026 16:19:38 +0000 (18:19 +0200)
css/common.css
js/base_rules.js
variants/Atarigo/class.js
variants/Avalam/class.js
variants/Avalam/style.css
variants/Avalanche/class.js
variants/Balaklava/class.js
variants/Bario/class.js

index 38d0f95..d9b2990 100644 (file)
@@ -308,7 +308,7 @@ piece.mark.transparent {
   margin-right: 15px;
 }
 .option-input input[type=number] {
-  width: 64px;
+  width: 50px;
 }
 .btn-wrap {
   text-align: center;
index 347d5b2..bc85aa8 100644 (file)
@@ -261,15 +261,13 @@ export default class ChessRules {
 
   // "Parse" FEN: just return untransformed string data
   parseFen(fen) {
-    const fenParts = fen.split(" ");
-    let res = {
-      position: fenParts[0],
-      turn: fenParts[1],
-      movesCount: fenParts[2]
+    const [position, turn, movesCount, extraData] = fen.split(" ");
+    return {
+      position,
+      turn,
+      movesCount,
+      ...(extraData ? JSON.parse(extraData) : {})
     };
-    if (fenParts.length > 3)
-      res = Object.assign(res, JSON.parse(fenParts[3]));
-    return res;
   }
 
   // Return current fen (game state)
@@ -913,7 +911,8 @@ export default class ChessRules {
       r = chessboard.getBoundingClientRect();
       pieceWidth = this.getPieceWidth(r.width);
       const cd = this.idToCoords(e.target.id);
-      if (cd) {
+      const [x, y] = Object.values(cd || {x: -1, y: -1});
+      if (cd && this.canIplay(x, y)) {
         const move_s = this.doClick(cd);
         if (move_s) {
           if (Array.isArray(move_s)) //8-pieces (at least.. only?)
@@ -923,12 +922,11 @@ export default class ChessRules {
             this.buildMoveStack(move_s, r);
         }
         else if (!this.clickOnly) {
-          const [x, y] = Object.values(cd);
           if (typeof x != "number")
             startPiece = this.r_pieces[x][y];
           else
             startPiece = this.g_pieces[x][y];
-          if (startPiece && this.canIplay(x, y)) {
+          if (startPiece) {
             e.preventDefault();
             start = cd;
             curPiece = startPiece.cloneNode();
index 120afdc..e743268 100644 (file)
@@ -19,7 +19,7 @@ export default class AtarigoRules extends WeiqiRules {
   }
 
   getCurrentScore(move_s) {
-    if (move_s[0].vanish.length > 0)
+    if (move_s.some(mv => mv.vanish.length > 0))
       return (this.turn == 'w' ? "0-1" : "1-0");
     return "*";
   }
index 13cc55e..6c61af3 100644 (file)
@@ -69,7 +69,7 @@ export default class AvalamRules extends ChessRules {
 
   genRandInitBaseFen() {
     let fen = "";
-    if (this.freefill)
+    if (this.options.freefill)
       fen = "9/".repeat(8) + "9";
     else if (this.options["randomness"] == 0) {
       fen = "2Bb5/1BbBb4/1bBbBbB2/1BbBbBbBb/BbBb1bBbB/" +
@@ -128,7 +128,7 @@ export default class AvalamRules extends ChessRules {
   }
 
   doClick(coords) {
-    if (!this.freefill || this.board[coords.x][coords.y] != "")
+    if (!this.options.freefill || this.board[coords.x][coords.y] != "")
       return null;
     return new Move({
       start: {x: coords.x, y: coords.y},
@@ -157,8 +157,16 @@ export default class AvalamRules extends ChessRules {
 
   getPotentialMovesFrom([x, y]) {
     const height = this.board[x][y].charCodeAt(1) - 97;
-    if (height == 5)
+    if (
+      height == 5
+      ||
+      (
+        this.options.freefill &&
+        this.board.some(row => row.some(sq => sq == ""))
+      )
+    ) {
       return [];
+    }
     let moves = [];
     for (let s of this.pieces(this.turn, x, y)['b'].both[0].steps) {
       const [i, j] = [x + s[0], y + s[1]];
@@ -181,6 +189,8 @@ export default class AvalamRules extends ChessRules {
     let towersCount = {w: 0, b: 0};
     for (let i = 0; i < this.size.x; i++) {
       for (let j = 0; j < this.size.y; j++) {
+        if (this.board[i][j] == "")
+          return "*"; //freefill
         if (this.board[i][j] != "") {
           if (this.getPotentialMovesFrom([i, j]).length > 0)
             return '*';
index 04463d1..ab964d3 100644 (file)
@@ -32,4 +32,7 @@ piece.black.stack5 {
 
 .board-sq {
   fill: grey;
+  stroke: darkblue;
+  stroke-width: 0.1;
+  paint-order: stroke fill;
 }
index 2016588..28ec007 100644 (file)
@@ -21,11 +21,9 @@ export default class AvalancheRules extends ChessRules {
         "capture",
         "crazyhouse",
         "cylinder",
-        "dark",
         "madrasi",
         "recycle",
         "rifle",
-        "teleport",
         "zen"
       ]
     };
index df441af..c9910d4 100644 (file)
@@ -37,18 +37,9 @@ export default class BalaklavaRules extends ChessRules {
   }
 
   genRandInitBaseFen() {
-    const s = FenUtil.setupPieces(
-      ['r', 'm', 'b', 'q', 'k', 'b', 'm', 'r'],
-      {
-        randomness: this.options["randomness"],
-        diffCol: ['b']
-      }
-    );
-    return {
-      fen: s.b.join("") + "/pppppppp/8/8/8/8/PPPPPPPP/" +
-           s.w.join("").toUpperCase(),
-      o: {flags: s.flags}
-    };
+    let res = super.genRandInitBaseFen();
+    res.fen = res.fen.replaceAll(/[nN]/g, match => (match == 'n' ? 'm' : 'M'));
+    return res;
   }
 
   pawnPostProcess(moves) {
index 93573f0..e1fd396 100644 (file)
@@ -31,7 +31,7 @@ export default class BarioRules extends ChessRules {
     );
   }
 
-  get onlyClick() {
+  get clickOnly() {
     return this.movesCount <= 1;
   }
 
@@ -79,8 +79,12 @@ export default class BarioRules extends ChessRules {
     );
   }
 
+  static get ReserveArray() {
+    return ['r', 'n', 'b', 'q'];
+  }
+
   initReserves(reserveStr) {
-    super.initReserves(reserveStr, ['r', 'n', 'b', 'q']);
+    super.initReserves(reserveStr, V.ReserveArray);
   }
 
   setOtherVariables(fenParsed) {
@@ -96,7 +100,11 @@ export default class BarioRules extends ChessRules {
       case 0:
         return i == this.captureUndef.x && j == this.captureUndef.y;
       case 1:
-        return this.getPiece(i, j) == 'u' && c == this.getColor(i, j);
+        return (
+          this.board[i][j] != "" &&
+          this.getPiece(i, j) == 'u' &&
+          c == this.getColor(i, j)
+        );
     }
     return false; //never reached
   }
@@ -198,6 +206,63 @@ export default class BarioRules extends ChessRules {
     return false;
   }
 
+  resetReserve(move, computeNext) {
+    const variety = (c) => {
+      return (
+        [...new Set(
+          Array.prototype.concat.apply([],
+            this.board.map(row =>
+              row.filter(cell =>
+                cell.charAt(0) == c && !['p', 'k'].includes(cell.charAt(1))
+              ).map(cell => cell.charAt(1))
+            )
+          )
+        )].length >= 2
+      );
+    };
+    let next;
+    if (computeNext) {
+      next = {start: move.end, end: move.end, vanish: [], appear: []};
+      this.playOnBoard(move);
+    }
+    const twoOrMorePieces = {w: variety('w'), b: variety('b')};
+    const resetCols =
+      Object.keys(twoOrMorePieces).filter(k => twoOrMorePieces[k]);
+    if (resetCols.length >= 1) {
+      for (let i=0; i<this.size.x; i++) {
+        for (let j=0; j<this.size.y; j++) {
+          if (this.board[i][j] == "")
+            continue;
+          const colIJ = this.getColor(i, j);
+          const pieceIJ = this.getPiece(i, j);
+          if (resetCols.includes(colIJ) && !['p', 'k', 'u'].includes(pieceIJ))
+          {
+            if (computeNext) {
+              // NOTE: could also use a "flip" strategy similar to Benedict
+              next.vanish.push(new PiPo({c: colIJ, p: pieceIJ, x: i, y: j}));
+              next.appear.push(new PiPo({c: colIJ, p: 'u', x: i, y: j}));
+            }
+            this.reserve[colIJ][pieceIJ]++;
+          }
+        }
+      }
+      super.re_drawReserve(resetCols);
+    }
+    if (computeNext) {
+      this.undoOnBoard(move);
+      if (next.vanish.length >= 1) {
+        next.reset = true;
+        move.next = next;
+      }
+    }
+  }
+
+  prePlay(move) {
+    super.prePlay(move);
+    if (move.reset && move.vanish[0].c != this.playerColor)
+      this.resetReserve(move);
+  }
+
   postPlay(move) {
     const color = this.turn;
     if (this.movesCount <= 1 || move.reset || move.next) {
@@ -239,53 +304,13 @@ export default class BarioRules extends ChessRules {
 
   computeNextMove(move) {
     if (
-      !this.definition || this.playerColor != this.turn ||
-      this.board.some(row => row.some(cell =>
-        cell.charAt(0) == this.turn && cell.charAt(1) == 'u'))
+      this.definition && this.playerColor == this.turn &&
+      this.board.every(row => row.every(cell => {
+        return (
+          cell == "" || cell.charAt(0) != this.turn || cell.charAt(1) != 'u');
+      }))
     ) {
-      return;
-    }
-    const variety = (c) => {
-      return (
-        [...new Set(
-          Array.prototype.concat.apply([],
-            this.board.map(row =>
-              row.filter(cell =>
-                cell.charAt(0) == c && !['p', 'k'].includes(cell.charAt(1))
-              ).map(cell => cell.charAt(1))
-            )
-          )
-        )].length >= 2
-      );
-    };
-    let next = {start: move.end, end: move.end, vanish: [], appear: []};
-    this.playOnBoard(move);
-    const twoOrMorePieces = {w: variety('w'), b: variety('b')};
-    const resetCols =
-      Object.keys(twoOrMorePieces).filter(k => twoOrMorePieces[k]);
-    if (resetCols.length >= 1) {
-      for (let i=0; i<this.size.x; i++) {
-        for (let j=0; j<this.size.y; j++) {
-          const colIJ = this.getColor(i, j);
-          const pieceIJ = this.getPiece(i, j);
-          if (
-            resetCols.includes(colIJ) &&
-            this.board[i][j] != "" &&
-            !['p', 'k', 'u'].includes(pieceIJ)
-          ) {
-            // NOTE: could also use a "flip" strategy similar to Benedict
-            next.vanish.push(new PiPo({c: colIJ, p: pieceIJ, x: i, y: j}));
-            next.appear.push(new PiPo({c: colIJ, p: 'u', x: i, y: j}));
-            this.reserve[colIJ][pieceIJ]++;
-          }
-        }
-      }
-      super.re_drawReserve(resetCols);
-    }
-    this.undoOnBoard(move);
-    if (next.vanish.length >= 1) {
-      next.reset = true;
-      move.next = next;
+      this.resetReserve(move, true);
     }
   }