| 1 | import ChessRules from "/base_rules.js"; |
| 2 | |
| 3 | export default class CwdaRules extends ChessRules { |
| 4 | |
| 5 | static get Options() { |
| 6 | return { |
| 7 | select: ChessRules.Options.select.concat([ |
| 8 | { |
| 9 | label: "Army 1", |
| 10 | variable: "army1", |
| 11 | defaut: 'C', |
| 12 | options: [ |
| 13 | { label: "Colorbound Clobberers", value: 'C' }, |
| 14 | { label: "Nutty Knights", value: 'N' }, |
| 15 | { label: "Remarkable Rookies", value: 'R' }, |
| 16 | { label: "Fide", value: 'F' } |
| 17 | ] |
| 18 | }, |
| 19 | { |
| 20 | label: "Army 2", |
| 21 | variable: "army2", |
| 22 | defaut: 'C', |
| 23 | options: [ |
| 24 | { label: "Colorbound Clobberers", value: 'C' }, |
| 25 | { label: "Nutty Knights", value: 'N' }, |
| 26 | { label: "Remarkable Rookies", value: 'R' }, |
| 27 | { label: "Fide", value: 'F' } |
| 28 | ] |
| 29 | } |
| 30 | ]), |
| 31 | input: ChessRules.Options.input, |
| 32 | styles: ChessRules.Options.styles |
| 33 | }; |
| 34 | } |
| 35 | |
| 36 | static get PiecesMap() { |
| 37 | return { |
| 38 | // Colorbound Clobberers |
| 39 | 'C': { |
| 40 | 'r': 'd', |
| 41 | 'n': 'w', |
| 42 | 'b': 'f', |
| 43 | 'q': 'c', |
| 44 | 'k': 'm', |
| 45 | 'p': 'z' |
| 46 | }, |
| 47 | // Nutty Knights |
| 48 | 'N': { |
| 49 | 'r': 'g', |
| 50 | 'n': 'i', |
| 51 | 'b': 't', |
| 52 | 'q': 'l', |
| 53 | 'k': 'e', |
| 54 | 'p': 'v' |
| 55 | }, |
| 56 | // Remarkable Rookies |
| 57 | 'R': { |
| 58 | 'r': 's', |
| 59 | 'n': 'y', |
| 60 | 'b': 'h', |
| 61 | 'q': 'o', |
| 62 | 'k': 'a', |
| 63 | 'p': 'u' |
| 64 | } |
| 65 | }; |
| 66 | } |
| 67 | |
| 68 | genRandInitBaseFen() { |
| 69 | let s = FenUtil.setupPieces( |
| 70 | ['r', 'n', 'b', 'q', 'k', 'b', 'n', 'r'], |
| 71 | { |
| 72 | randomness: this.options["randomness"], |
| 73 | between: [{p1: 'k', p2: 'r'}], |
| 74 | diffCol: ['b'], |
| 75 | flags: ['r', 'k'] |
| 76 | } |
| 77 | ); |
| 78 | let pawnLines = { |
| 79 | w: "pppppppp", |
| 80 | b: "pppppppp" |
| 81 | }; |
| 82 | for (const c of ['w', 'b']) { |
| 83 | const army = "army" + (c == 'w' ? "1" : "2"); |
| 84 | if (this.options[army] != 'F') { |
| 85 | for (let obj of [s, pawnLines]) { |
| 86 | obj[c] = obj[c].split("") |
| 87 | .map(p => V.PiecesMap[this.options[army]][p]).join(""); |
| 88 | } |
| 89 | } |
| 90 | } |
| 91 | return { |
| 92 | fen: s.b.join("") + "/" + |
| 93 | pawnLines['b'] + "/8/8/8/8/" + pawnLines['w'].toUpperCase() + |
| 94 | "/" + s.w.join("").toUpperCase(), |
| 95 | o: {flags: s.flags} |
| 96 | }; |
| 97 | } |
| 98 | |
| 99 | getPartFen(o) { |
| 100 | return Object.assign( |
| 101 | { "armies": this.options["army1"] + this.options["army2"] }, |
| 102 | super.getPartFen(o) |
| 103 | ); |
| 104 | } |
| 105 | |
| 106 | setOtherVariables(fenParsed) { |
| 107 | super.setOtherVariables(fenParsed); |
| 108 | this.army1 = fenParsed.armies.charAt(0); |
| 109 | this.army2 = fenParsed.armies.charAt(1); |
| 110 | } |
| 111 | |
| 112 | isKing(x, y, p) { |
| 113 | if (!p) |
| 114 | p = this.getPiece(x, y); |
| 115 | return (super.isKing(x, y, p) || ['a', 'e', 'm'].includes(p)); |
| 116 | } |
| 117 | |
| 118 | // Helper to describe pieces movements |
| 119 | static get steps() { |
| 120 | return { |
| 121 | // Dabbabah |
| 122 | 'd': [ |
| 123 | [-2, 0], |
| 124 | [0, -2], |
| 125 | [2, 0], |
| 126 | [0, 2] |
| 127 | ], |
| 128 | // Alfil |
| 129 | 'a': [ |
| 130 | [2, 2], |
| 131 | [2, -2], |
| 132 | [-2, 2], |
| 133 | [-2, -2] |
| 134 | ], |
| 135 | // Ferz |
| 136 | 'f': [ |
| 137 | [1, 1], |
| 138 | [1, -1], |
| 139 | [-1, 1], |
| 140 | [-1, -1] |
| 141 | ], |
| 142 | // Wazir |
| 143 | 'w': [ |
| 144 | [-1, 0], |
| 145 | [0, -1], |
| 146 | [1, 0], |
| 147 | [0, 1] |
| 148 | ], |
| 149 | // Threeleaper |
| 150 | '$3': [ |
| 151 | [-3, 0], |
| 152 | [0, -3], |
| 153 | [3, 0], |
| 154 | [0, 3] |
| 155 | ], |
| 156 | // Narrow knight |
| 157 | '$n': [ |
| 158 | [-2, -1], |
| 159 | [-2, 1], |
| 160 | [2, -1], |
| 161 | [2, 1] |
| 162 | ] |
| 163 | }; |
| 164 | } |
| 165 | |
| 166 | pieces(color, x, y) { |
| 167 | const res = super.pieces(color, x, y); |
| 168 | return Object.assign( |
| 169 | { |
| 170 | 'd': { |
| 171 | "class": "c_rook", |
| 172 | both: [ |
| 173 | {steps: V.steps.b}, |
| 174 | {steps: V.steps.d, range: 1} |
| 175 | ] |
| 176 | }, |
| 177 | 'w': { |
| 178 | "class": "c_knight", |
| 179 | both: [ |
| 180 | {steps: V.steps.a, range: 1}, |
| 181 | {steps: V.steps.r, range: 1} |
| 182 | ] |
| 183 | }, |
| 184 | 'f': { |
| 185 | "class": "c_bishop", |
| 186 | both: [ |
| 187 | {steps: V.steps.d, range: 1}, |
| 188 | {steps: V.steps.a, range: 1}, |
| 189 | {steps: V.steps.b, range: 1} |
| 190 | ] |
| 191 | }, |
| 192 | 'c': { |
| 193 | "class": "c_queen", |
| 194 | both: [ |
| 195 | {steps: V.steps.b}, |
| 196 | {steps: V.steps.n, range: 1} |
| 197 | ] |
| 198 | }, |
| 199 | 'm': { moveas: 'k' }, |
| 200 | 'z': { moveas: 'p' }, |
| 201 | 'g': { |
| 202 | |
| 203 | }, |
| 204 | 'i': { |
| 205 | |
| 206 | }, |
| 207 | 't': { |
| 208 | |
| 209 | }, |
| 210 | 'l': { |
| 211 | |
| 212 | }, |
| 213 | 'e': { moveas: 'k' }, |
| 214 | 'v': { moveas: 'p' }, |
| 215 | 's': { |
| 216 | |
| 217 | }, |
| 218 | 'y': { |
| 219 | |
| 220 | }, |
| 221 | 'h': { |
| 222 | |
| 223 | }, |
| 224 | 'o': { |
| 225 | |
| 226 | }, |
| 227 | 'a': { moveas: 'k' }, |
| 228 | 'u': { moveas: 'p' } |
| 229 | }, |
| 230 | res |
| 231 | ); |
| 232 | |
| 233 | |
| 234 | |
| 235 | |
| 236 | |
| 237 | getPotentialN_rookMoves(sq) { |
| 238 | const c = this.turn; |
| 239 | const rookSteps = [ [0, -1], [0, 1], [c == 'w' ? -1 : 1, 0] ]; |
| 240 | const backward = (c == 'w' ? 1 : -1); |
| 241 | const kingSteps = [ [backward, -1], [backward, 0], [backward, 1] ]; |
| 242 | return ( |
| 243 | this.getSlideNJumpMoves(sq, rookSteps).concat( |
| 244 | this.getSlideNJumpMoves(sq, kingSteps, 1)) |
| 245 | ); |
| 246 | } |
| 247 | |
| 248 | getPotentialN_knightMoves(sq) { |
| 249 | return ( |
| 250 | this.getSlideNJumpMoves(sq, V.steps.$n, 1).concat( |
| 251 | this.getSlideNJumpMoves(sq, V.steps.f, 1)) |
| 252 | ); |
| 253 | } |
| 254 | |
| 255 | getPotentialN_bishopMoves(sq) { |
| 256 | const backward = (this.turn == 'w' ? 1 : -1); |
| 257 | const kingSteps = [ |
| 258 | [0, -1], [0, 1], [backward, -1], [backward, 0], [backward, 1] |
| 259 | ]; |
| 260 | const forward = -backward; |
| 261 | const knightSteps = [ |
| 262 | [2*forward, -1], [2*forward, 1], [forward, -2], [forward, 2] |
| 263 | ]; |
| 264 | return ( |
| 265 | this.getSlideNJumpMoves(sq, knightSteps, 1).concat( |
| 266 | this.getSlideNJumpMoves(sq, kingSteps, 1)) |
| 267 | ); |
| 268 | } |
| 269 | |
| 270 | getPotentialN_queenMoves(sq) { |
| 271 | const backward = (this.turn == 'w' ? 1 : -1); |
| 272 | const forward = -backward; |
| 273 | const kingSteps = [ |
| 274 | [forward, -1], [forward, 1], |
| 275 | [backward, -1], [backward, 0], [backward, 1] |
| 276 | ]; |
| 277 | const knightSteps = [ |
| 278 | [2*forward, -1], [2*forward, 1], [forward, -2], [forward, 2] |
| 279 | ]; |
| 280 | const rookSteps = [ [0, -1], [0, 1], [forward, 0] ]; |
| 281 | return ( |
| 282 | this.getSlideNJumpMoves(sq, rookSteps).concat( |
| 283 | this.getSlideNJumpMoves(sq, kingSteps, 1)).concat( |
| 284 | this.getSlideNJumpMoves(sq, knightSteps, 1)) |
| 285 | ); |
| 286 | } |
| 287 | |
| 288 | getPotentialR_rookMoves(sq) { |
| 289 | return this.getSlideNJumpMoves(sq, V.steps.r, 4); |
| 290 | } |
| 291 | |
| 292 | getPotentialR_knightMoves(sq) { |
| 293 | return ( |
| 294 | this.getSlideNJumpMoves(sq, V.steps.d, 1).concat( |
| 295 | this.getSlideNJumpMoves(sq, V.steps.w, 1)) |
| 296 | ); |
| 297 | } |
| 298 | |
| 299 | getPotentialR_bishopMoves(sq) { |
| 300 | return ( |
| 301 | this.getSlideNJumpMoves(sq, V.steps.d, 1).concat( |
| 302 | this.getSlideNJumpMoves(sq, V.steps.f, 1)).concat( |
| 303 | this.getSlideNJumpMoves(sq, V.steps.$3, 1)) |
| 304 | ); |
| 305 | } |
| 306 | |
| 307 | getPotentialR_queenMoves(sq) { |
| 308 | return ( |
| 309 | this.getSlideNJumpMoves(sq, V.steps.r).concat( |
| 310 | this.getSlideNJumpMoves(sq, V.steps.n, 1)) |
| 311 | ); |
| 312 | } |
| 313 | |
| 314 | case V.PAWN: { |
| 315 | // Can promote in anything from the two current armies |
| 316 | let promotions = []; |
| 317 | for (let army of ["army1", "army2"]) { |
| 318 | if (army == "army2" && this.army2 == this.army1) break; |
| 319 | switch (this[army]) { |
| 320 | case 'C': { |
| 321 | Array.prototype.push.apply(promotions, |
| 322 | [V.C_ROOK, V.C_KNIGHT, V.C_BISHOP, V.C_QUEEN]); |
| 323 | break; |
| 324 | } |
| 325 | case 'N': { |
| 326 | Array.prototype.push.apply(promotions, |
| 327 | [V.N_ROOK, V.N_KNIGHT, V.N_BISHOP, V.N_QUEEN]); |
| 328 | break; |
| 329 | } |
| 330 | case 'R': { |
| 331 | Array.prototype.push.apply(promotions, |
| 332 | [V.R_ROOK, V.R_KNIGHT, V.R_BISHOP, V.R_QUEEN]); |
| 333 | break; |
| 334 | } |
| 335 | case 'F': { |
| 336 | Array.prototype.push.apply(promotions, |
| 337 | [V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN]); |
| 338 | break; |
| 339 | } |
| 340 | } |
| 341 | } |
| 342 | return super.getPotentialPawnMoves(sq, promotions); |
| 343 | } |
| 344 | default: return super.getPotentialMovesFrom(sq); |
| 345 | } |
| 346 | |
| 347 | getCastleMoves([x, y]) { |
| 348 | const color = this.getColor(x, y); |
| 349 | let finalSquares = [ [2, 3], [V.size.y - 2, V.size.y - 3] ]; |
| 350 | if ( |
| 351 | (color == 'w' && this.army1 == 'C') || |
| 352 | (color == 'b' && this.army2 == 'C') |
| 353 | ) { |
| 354 | // Colorbound castle long in an unusual way: |
| 355 | finalSquares[0] = [1, 2]; |
| 356 | } |
| 357 | return super.getCastleMoves([x, y], finalSquares); |
| 358 | } |
| 359 | |
| 360 | }; |