Add Avalanche, write Avalam rules
authorBenjamin Auder <benjamin.auder@somewhere>
Tue, 5 Jul 2022 15:28:38 +0000 (17:28 +0200)
committerBenjamin Auder <benjamin.auder@somewhere>
Tue, 5 Jul 2022 15:28:38 +0000 (17:28 +0200)
base_rules.js
variants.js
variants/Avalam/rules.html
variants/Avalanche/class.js [new file with mode: 0644]
variants/Avalanche/rules.html [new file with mode: 0644]
variants/Avalanche/style.css [new file with mode: 0644]

index 01a2c24..8eed3d3 100644 (file)
@@ -2420,7 +2420,11 @@ export default class ChessRules {
   }
 
   // What is the score ? (Interesting if game is over)
-  getCurrentScore(move) {
+  getCurrentScore(move_s) {
+    const move = move_s[move_s.length - 1];
+    // Shortcut in case the score was computed before:
+    if (move.result)
+      return move.result;
     const color = this.turn;
     const oppCol = C.GetOppCol(color);
     const kingPos = {
index 8662316..b65a564 100644 (file)
@@ -13,7 +13,7 @@ const variants = [
   {name: 'Atarigo', desc: 'First capture wins', disp: 'Atari-Go'},
   {name: 'Atomic', desc: 'Explosive captures'},
   {name: 'Avalam', desc: 'Build towers'},
-//  {name: 'Avalanche', desc: 'Pawnfalls'},
+  {name: 'Avalanche', desc: 'Pawnfalls'},
 //  {name: 'Ball', desc: 'Score a goal'},
 //  {name: 'Balaklava', desc: 'Meet the Mammoth'},
 //  {name: 'Bario', desc: 'A quantum story'},
index c65158e..83e301e 100644 (file)
@@ -1 +1,16 @@
-<p>TODO</p>
+<p>
+  At each turn, take any tower of less than 5 pieces (the number printed on it)
+  and put it on an adjacent tower, such that the resulting construction isn't
+  more than 5 units tall.
+</p>
+
+<p>
+  When no moves are possible anymore, the game is over. The player having the
+  largest number of towers of his color (on top) wins.
+</p>
+
+<a href="http://jeuxstrategie.free.fr/Avalam_complet.php">
+  More informations.
+</a>
+
+<p class="author">Philippe Deweys (1995).</p>
diff --git a/variants/Avalanche/class.js b/variants/Avalanche/class.js
new file mode 100644 (file)
index 0000000..ea2b9dd
--- /dev/null
@@ -0,0 +1,158 @@
+import ChessRules from "/base_rules.js";
+import {Random} from "/utils/alea.js";
+import PiPo from "/utils/PiPo.js";
+import Move from "/utils/Move.js";
+
+export default class AvalancheRules extends ChessRules {
+
+  static get Options() {
+    return {
+      select: C.Options.select,
+      styles: [
+        "atomic",
+        "cannibal",
+        "capture",
+        "crazyhouse",
+        "cylinder",
+        "dark",
+        "madrasi",
+        "recycle",
+        "rifle",
+        "teleport",
+        "zen"
+      ]
+    };
+  }
+
+  get hasEnpassant() {
+    return false;
+  }
+
+  getPartFen(o) {
+    return Object.assign(
+      {promotion: o.init ? false : this.promotion},
+      super.getPartFen(o)
+    );
+  }
+
+  setOtherVariables(fenParsed) {
+    super.setOtherVariables(fenParsed);
+    this.promotion = (fenParsed.promotion == '1');
+    this.subTurn = 1 - (this.promotion ? 1 : 0);
+  }
+
+  doClick(coords) {
+    const myLastRank = (this.turn == 'w' ? 0 : this.size.x - 1);
+    if (
+      this.subTurn != 0 ||
+      coords.x != myLastRank ||
+      this.getPiece(coords.x, coords.y) != 'p'
+    ) {
+      return null;
+    }
+    let moves = [];
+    this.pawnPromotions.forEach(pr => {
+      moves.push(
+        new Move({
+          vanish: [new PiPo({x: coords.x, y: coords.y, c: this.turn, p: 'p'})],
+          appear: [new PiPo({x: coords.x, y: coords.y, c: this.turn, p: pr})]
+        })
+      );
+    });
+    super.showChoices(moves);
+  }
+
+  canIplay(x, y) {
+    const pieceColor = this.getColor(x, y);
+    return (
+      this.playerColor == this.turn &&
+      (
+        (this.subTurn <= 1 && pieceColor == this.playerColor) ||
+        (
+          this.subTurn == 2 &&
+          pieceColor != this.playerColor &&
+          this.getPiece(x, y) == 'p'
+        )
+      )
+    );
+  }
+
+  getPotentialMovesFrom([x, y]) {
+    if (this.subTurn == 0)
+      return [];
+    if (this.subTurn == 1)
+      // Usual case:
+      return super.getPotentialMovesFrom([x, y]);
+    // subTurn == 2: only allowed to push an opponent's pawn (if possible)
+    const oppPawnShift = (this.turn == 'w' ? 1 : -1);
+    if (
+      this.onBoard(x + oppPawnShift, y) &&
+      this.board[x + oppPawnShift][y] == ""
+    ) {
+      return [this.getBasicMove([x, y], [x + oppPawnShift, y])];
+    }
+    return [];
+  }
+
+  filterValid(moves) {
+    if (this.subTurn != 1)
+      return moves; //self-checks by pawns are allowed
+    return super.filterValid(moves);
+  }
+
+  atLeastOnePawnPush(color) {
+    const pawnShift = (color == 'w' ? -1 : 1);
+    for (let i = 0; i < 8; i++) {
+      for (let j = 0; j < 8; j++) {
+        if (
+          this.board[i][j] != "" &&
+          this.getColor(i, j) == color &&
+          this.getPiece(i, j) == 'p' &&
+          this.board[i + pawnShift][j] == ""
+        ) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  postPlay(move) {
+    const color = this.turn;
+    const oppCol = C.GetOppCol(color);
+    this.promotion = (
+      this.subTurn == 2 &&
+      move.end.x == (oppCol == 'w' ? 0 : this.size.x - 1) &&
+      move.vanish[0].p == 'p'
+    );
+    if (this.subTurn == 0) {
+      this.subTurn++;
+      if (!this.atLeastOneMove(color)) {
+        move.result = "1/2"; //avoid re-computation
+        this.turn = oppCol;
+      }
+    }
+    else if (this.subTurn == 2) {
+      this.turn = oppCol;
+      this.subTurn = this.promotion ? 0 : 1;
+    }
+    else { //subTurn == 1, usual case
+      const kingCapture = this.searchKingPos(oppCol).length == 0;
+      if (kingCapture)
+        move.result = (color == 'w' ? "1-0" : "0-1");
+      if (!kingCapture && this.atLeastOnePawnPush(oppCol))
+        this.subTurn++;
+      else {
+        this.turn = oppCol;
+        this.subTurn = this.promotion ? 0 : 1;
+      }
+    }
+  }
+
+  atLeastOneMove(color, lastMove) {
+    if (this.subTurn == 0)
+      return true;
+    return super.atLeastOneMove(color);
+  }
+
+};
diff --git a/variants/Avalanche/rules.html b/variants/Avalanche/rules.html
new file mode 100644 (file)
index 0000000..a25d2cf
--- /dev/null
@@ -0,0 +1,12 @@
+<p>
+  After each normal move, push an opponent pawn one square forward.
+  If the pawn promotes, its owner will select into which piece on next turn.
+</p>
+
+<p>The goal is either to checkmate or to capture the enemy king.</p>
+
+<a href="https://www.chessvariants.com/mvopponent.dir/avalanche.html">
+  chessvariants page.
+</a>
+
+<p class="author">Ralph Betza (1977).</p>
diff --git a/variants/Avalanche/style.css b/variants/Avalanche/style.css
new file mode 100644 (file)
index 0000000..a3550bc
--- /dev/null
@@ -0,0 +1 @@
+@import url("/base_pieces.css");