update
[xogo.git] / variants / Cwda / class.js
diff --git a/variants/Cwda/class.js b/variants/Cwda/class.js
new file mode 100644 (file)
index 0000000..393e407
--- /dev/null
@@ -0,0 +1,360 @@
+import ChessRules from "/base_rules.js";
+
+export default class CwdaRules extends ChessRules {
+
+  static get Options() {
+    return {
+      select: ChessRules.Options.select.concat([
+        {
+          label: "Army 1",
+          variable: "army1",
+          defaut: 'C',
+          options: [
+            { label: "Colorbound Clobberers", value: 'C' },
+            { label: "Nutty Knights", value: 'N' },
+            { label: "Remarkable Rookies", value: 'R' },
+            { label: "Fide", value: 'F' }
+          ]
+        },
+        {
+          label: "Army 2",
+          variable: "army2",
+          defaut: 'C',
+          options: [
+            { label: "Colorbound Clobberers", value: 'C' },
+            { label: "Nutty Knights", value: 'N' },
+            { label: "Remarkable Rookies", value: 'R' },
+            { label: "Fide", value: 'F' }
+          ]
+        }
+      ]),
+      input: ChessRules.Options.input,
+      styles: ChessRules.Options.styles
+    };
+  }
+
+  static get PiecesMap() {
+    return {
+      // Colorbound Clobberers
+      'C': {
+        'r': 'd',
+        'n': 'w',
+        'b': 'f',
+        'q': 'c',
+        'k': 'm',
+        'p': 'z'
+      },
+      // Nutty Knights
+      'N': {
+        'r': 'g',
+        'n': 'i',
+        'b': 't',
+        'q': 'l',
+        'k': 'e',
+        'p': 'v'
+      },
+      // Remarkable Rookies
+      'R': {
+        'r': 's',
+        'n': 'y',
+        'b': 'h',
+        'q': 'o',
+        'k': 'a',
+        'p': 'u'
+      }
+    };
+  }
+
+  genRandInitBaseFen() {
+    let s = FenUtil.setupPieces(
+      ['r', 'n', 'b', 'q', 'k', 'b', 'n', 'r'],
+      {
+        randomness: this.options["randomness"],
+        between: [{p1: 'k', p2: 'r'}],
+        diffCol: ['b'],
+        flags: ['r', 'k']
+      }
+    );
+    let pawnLines = {
+      w: "pppppppp",
+      b: "pppppppp"
+    };
+    for (const c of ['w', 'b']) {
+      const army = "army" + (c == 'w' ? "1" : "2");
+      if (this.options[army] != 'F') {
+        for (let obj of [s, pawnLines]) {
+          obj[c] = obj[c].split("")
+            .map(p => V.PiecesMap[this.options[army]][p]).join("");
+        }
+      }
+    }
+    return {
+      fen: s.b.join("") + "/" +
+           pawnLines['b'] + "/8/8/8/8/" + pawnLines['w'].toUpperCase() +
+           "/" + s.w.join("").toUpperCase(),
+      o: {flags: s.flags}
+    };
+  }
+
+  getPartFen(o) {
+    return Object.assign(
+      { "armies": this.options["army1"] + this.options["army2"] },
+      super.getPartFen(o)
+    );
+  }
+
+  setOtherVariables(fenParsed) {
+    super.setOtherVariables(fenParsed);
+    this.army1 = fenParsed.armies.charAt(0);
+    this.army2 = fenParsed.armies.charAt(1);
+  }
+
+  isKing(x, y, p) {
+    if (!p)
+      p = this.getPiece(x, y);
+    return (super.isKing(x, y, p) || ['a', 'e', 'm'].includes(p));
+  }
+
+  // Helper to describe pieces movements
+  static get steps() {
+    return {
+      // Dabbabah
+      'd': [
+        [-2, 0],
+        [0, -2],
+        [2, 0],
+        [0, 2]
+      ],
+      // Alfil
+      'a': [
+        [2, 2],
+        [2, -2],
+        [-2, 2],
+        [-2, -2]
+      ],
+      // Ferz
+      'f': [
+        [1, 1],
+        [1, -1],
+        [-1, 1],
+        [-1, -1]
+      ],
+      // Wazir
+      'w': [
+        [-1, 0],
+        [0, -1],
+        [1, 0],
+        [0, 1]
+      ],
+      // Threeleaper
+      '$3': [
+        [-3, 0],
+        [0, -3],
+        [3, 0],
+        [0, 3]
+      ],
+      // Narrow knight
+      '$n': [
+        [-2, -1],
+        [-2, 1],
+        [2, -1],
+        [2, 1]
+      ]
+    };
+  }
+
+  pieces(color, x, y) {
+    const res = super.pieces(color, x, y);
+    return Object.assign(
+      {
+        'd': {
+          "class": "c_rook",
+          both: [
+            {steps: V.steps.b},
+            {steps: V.steps.d, range: 1}
+          ]
+        },
+        'w': {
+          "class": "c_knight",
+          both: [
+            {steps: V.steps.a, range: 1},
+            {steps: V.steps.r, range: 1}
+          ]
+        },
+        'f': {
+          "class": "c_bishop",
+          both: [
+            {steps: V.steps.d, range: 1},
+            {steps: V.steps.a, range: 1},
+            {steps: V.steps.b, range: 1}
+          ]
+        },
+        'c': {
+          "class": "c_queen",
+          both: [
+            {steps: V.steps.b},
+            {steps: V.steps.n, range: 1}
+          ]
+        },
+        'm': { moveas: 'k' },
+        'z': { moveas: 'p' },
+        'g': {
+
+        },
+        'i': {
+
+        },
+        't': {
+
+        },
+        'l': {
+
+        },
+        'e': { moveas: 'k' },
+        'v': { moveas: 'p' },
+        's': {
+
+        },
+        'y': {
+
+        },
+        'h': {
+
+        },
+        'o': {
+
+        },
+        'a': { moveas: 'k' },
+        'u': { moveas: 'p' }
+      },
+      res
+    );
+
+
+
+
+
+  getPotentialN_rookMoves(sq) {
+    const c = this.turn;
+    const rookSteps = [ [0, -1], [0, 1], [c == 'w' ? -1 : 1, 0] ];
+    const backward = (c == 'w' ? 1 : -1);
+    const kingSteps = [ [backward, -1], [backward, 0], [backward, 1] ];
+    return (
+      this.getSlideNJumpMoves(sq, rookSteps).concat(
+      this.getSlideNJumpMoves(sq, kingSteps, 1))
+    );
+  }
+
+  getPotentialN_knightMoves(sq) {
+    return (
+      this.getSlideNJumpMoves(sq, V.steps.$n, 1).concat(
+      this.getSlideNJumpMoves(sq, V.steps.f, 1))
+    );
+  }
+
+  getPotentialN_bishopMoves(sq) {
+    const backward = (this.turn == 'w' ? 1 : -1);
+    const kingSteps = [
+      [0, -1], [0, 1], [backward, -1], [backward, 0], [backward, 1]
+    ];
+    const forward = -backward;
+    const knightSteps = [
+      [2*forward, -1], [2*forward, 1], [forward, -2], [forward, 2]
+    ];
+    return (
+      this.getSlideNJumpMoves(sq, knightSteps, 1).concat(
+      this.getSlideNJumpMoves(sq, kingSteps, 1))
+    );
+  }
+
+  getPotentialN_queenMoves(sq) {
+    const backward = (this.turn == 'w' ? 1 : -1);
+    const forward = -backward;
+    const kingSteps = [
+      [forward, -1], [forward, 1],
+      [backward, -1], [backward, 0], [backward, 1]
+    ];
+    const knightSteps = [
+      [2*forward, -1], [2*forward, 1], [forward, -2], [forward, 2]
+    ];
+    const rookSteps = [ [0, -1], [0, 1], [forward, 0] ];
+    return (
+      this.getSlideNJumpMoves(sq, rookSteps).concat(
+      this.getSlideNJumpMoves(sq, kingSteps, 1)).concat(
+      this.getSlideNJumpMoves(sq, knightSteps, 1))
+    );
+  }
+
+  getPotentialR_rookMoves(sq) {
+    return this.getSlideNJumpMoves(sq, V.steps.r, 4);
+  }
+
+  getPotentialR_knightMoves(sq) {
+    return (
+      this.getSlideNJumpMoves(sq, V.steps.d, 1).concat(
+      this.getSlideNJumpMoves(sq, V.steps.w, 1))
+    );
+  }
+
+  getPotentialR_bishopMoves(sq) {
+    return (
+      this.getSlideNJumpMoves(sq, V.steps.d, 1).concat(
+      this.getSlideNJumpMoves(sq, V.steps.f, 1)).concat(
+      this.getSlideNJumpMoves(sq, V.steps.$3, 1))
+    );
+  }
+
+  getPotentialR_queenMoves(sq) {
+    return (
+      this.getSlideNJumpMoves(sq, V.steps.r).concat(
+      this.getSlideNJumpMoves(sq, V.steps.n, 1))
+    );
+  }
+
+      case V.PAWN: {
+        // Can promote in anything from the two current armies
+        let promotions = [];
+        for (let army of ["army1", "army2"]) {
+          if (army == "army2" && this.army2 == this.army1) break;
+          switch (this[army]) {
+            case 'C': {
+              Array.prototype.push.apply(promotions,
+                [V.C_ROOK, V.C_KNIGHT, V.C_BISHOP, V.C_QUEEN]);
+              break;
+            }
+            case 'N': {
+              Array.prototype.push.apply(promotions,
+                [V.N_ROOK, V.N_KNIGHT, V.N_BISHOP, V.N_QUEEN]);
+              break;
+            }
+            case 'R': {
+              Array.prototype.push.apply(promotions,
+                [V.R_ROOK, V.R_KNIGHT, V.R_BISHOP, V.R_QUEEN]);
+              break;
+            }
+            case 'F': {
+              Array.prototype.push.apply(promotions,
+                [V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN]);
+              break;
+            }
+          }
+        }
+        return super.getPotentialPawnMoves(sq, promotions);
+      }
+      default: return super.getPotentialMovesFrom(sq);
+    }
+
+  getCastleMoves([x, y]) {
+    const color = this.getColor(x, y);
+    let finalSquares = [ [2, 3], [V.size.y - 2, V.size.y - 3] ];
+    if (
+      (color == 'w' && this.army1 == 'C') ||
+      (color == 'b' && this.army2 == 'C')
+    ) {
+      // Colorbound castle long in an unusual way:
+      finalSquares[0] = [1, 2];
+    }
+    return super.getCastleMoves([x, y], finalSquares);
+  }
+
+};