Add Avalam
[xogo.git] / variants / Avalam / class.js
diff --git a/variants/Avalam/class.js b/variants/Avalam/class.js
new file mode 100644 (file)
index 0000000..f35df83
--- /dev/null
@@ -0,0 +1,195 @@
+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 AvalamRules extends ChessRules {
+
+  static get Options() {
+    return {
+      select: [{
+        label: "Randomness",
+        variable: "randomness",
+        defaut: 1,
+        options: [
+          {label: "Deterministic", value: 0},
+          {label: "Random", value: 1},
+        ]
+      }],
+      input: [
+        {
+          label: "Free placement",
+          variable: "freefill",
+          type: "checkbox",
+          defaut: false
+        }
+      ]
+    };
+  }
+
+  get hasFlags() {
+    return false;
+  }
+  get hasEnpassant() {
+    return false;
+  }
+
+  pieces(color, x, y) {
+    const steps = [
+      [1, 0], [0, 1], [-1, 0], [0, -1],
+      [1, 1], [1, -1], [-1, 1], [-1, -1]
+    ];
+    return {
+      'b': {
+        "class": "stack",
+        moves: [{steps: steps, range: 1}]
+      },
+      'c': {
+        "class": "stack2",
+        moveas: 'b'
+      },
+      'd': {
+        "class": "stack3",
+        moveas: 'b'
+      },
+      'e': {
+        "class": "stack4",
+        moveas: 'b'
+      },
+      'f': {
+        "class": "stack5",
+        moveas: 'b'
+      }
+    };
+  }
+
+  genRandInitBaseFen() {
+    let fen = "";
+    if (this.freefill)
+      fen = "9/".repeat(8) + "9 w 0";
+    else if (this.options["randomness"] == 0) {
+      fen = "2Bb5/1BbBb4/1bBbBbB2/1BbBbBbBb/BbBb1bBbB/" +
+            "bBbBbBbB1/2BbBbBb1/4bBbB1/5bB2 w 0";
+    }
+    else {
+      const pieces = ('B'.repeat(24) + 'b'.repeat(24)).split("");
+      const a = Random.shuffle(pieces, 48).join("");
+      fen = (
+        "2" + a.substr(0, 2) + "5/1" + a.substr(2, 4) +
+        "4/1" + a.substr(6, 6) + "2/1" + a.substr(12, 8) +
+        "/" + a.substr(20, 4) + "1" + a.substr(24, 4) +
+        "/" + a.substr(28, 8) + "1/2" + a.substr(36, 6) +
+        "1/4" + a.substr(42, 4) + "1/5" + a.substr(46, 2) +
+        "2 w 0"
+      );
+    }
+    return { fen: fen, o: {} };
+  }
+
+  getSquareColorClass(x, y) {
+    return "board-sq";
+  }
+
+  get size() {
+    return {x: 9, y: 9};
+  }
+
+  onBoard(x, y) {
+    if (!super.onBoard(x, y))
+      return false;
+    switch (x) {
+      case 0:
+        return [2, 3].includes(y);
+      case 1:
+        return [1, 2, 3, 4].includes(y);
+      case 2:
+        return [1, 2, 3, 4, 5, 6].includes(y);
+      case 3:
+        return y >= 1;
+      case 4:
+        return y != 4;
+      case 5:
+        return y <= 7;
+      case 6:
+        return [2, 3, 4, 5, 6, 7].includes(y);
+      case 7:
+        return [4, 5, 6, 7].includes(y);
+      case 8:
+        return [5, 6].includes(y);
+    }
+    return false; //never reached
+  }
+
+  canIplay() {
+    return this.playerColor == this.turn;
+  }
+
+  doClick(coords) {
+    if (!this.freefill || this.board[coords.x][coords.y] != "")
+      return null;
+    return new Move({
+      start: {x: coords.x, y: coords.y},
+      vanish: [],
+      appear: [new PiPo({x: coords.x, y: coords.y, c: this.turn, p: 'b'})]
+    });
+  }
+
+  getBasicMove([x1, y1], [x2, y2]) {
+    const cp1 = this.board[x1][y1],
+          cp2 = this.board[x2][y2];
+    const newPiece =
+      String.fromCharCode(cp1.charCodeAt(1) + cp2.charCodeAt(1) - 97);
+    return (
+      new Move({
+        vanish: [
+          new PiPo({ x: x1, y: y1, c: cp1.charAt(0), p: cp1.charAt(1) }),
+          new PiPo({ x: x2, y: y2, c: cp2.charAt(0), p: cp2.charAt(1) })
+        ],
+        appear: [
+          new PiPo({ x: x2, y: y2, c: cp1.charAt(0), p: newPiece })
+        ]
+      })
+    );
+  }
+
+  getPotentialMovesFrom([x, y]) {
+    const height = this.board[x][y].charCodeAt(1) - 97;
+    if (height == 5)
+      return [];
+    let moves = [];
+    for (let s of this.pieces()['b'].moves[0].steps) {
+      const [i, j] = [x + s[0], y + s[1]];
+      if (
+        this.onBoard(i, j) &&
+        this.board[i][j] != "" &&
+        (height + this.board[i][j].charCodeAt(1) - 97 <= 5)
+      ) {
+        moves.push(this.getBasicMove([x, y], [i, j]));
+      }
+    }
+    return moves;
+  }
+
+  filterValid(moves) {
+    return moves;
+  }
+
+  getCurrentScore() {
+    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] != "") {
+          if (this.getPotentialMovesFrom([i, j]).length > 0)
+            return '*';
+          towersCount[ this.board[i][j][0] ]++;
+        }
+      }
+    }
+    if (towersCount['w'] > towersCount['b'])
+      return "1-0";
+    if (towersCount['b'] > towersCount['w'])
+      return "0-1";
+    return "1/2";
+  }
+
+};