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