Commit | Line | Data |
---|---|---|
65cf1690 BA |
1 | import ChessRules from "/base_rules.js"; |
2 | import { ArrayFun } from "/utils/array.js"; | |
3 | ||
4 | export default class AliceRules extends ChessRules { | |
5 | ||
6 | static get Options() { | |
7 | return { | |
8 | select: C.Options.select, | |
9 | input: C.Options.input, | |
10 | styles: [ | |
11 | "balance", | |
12 | "capture", | |
13 | "cylinder", | |
14 | "dark", | |
15 | "doublemove", | |
16 | "progressive", | |
17 | "zen" | |
18 | ] | |
19 | }; | |
20 | } | |
21 | ||
22 | // To the other side of the mirror and back... | |
23 | static get ALICE_PIECES() { | |
24 | return { | |
25 | s: "p", | |
26 | u: "r", | |
27 | o: "n", | |
28 | c: "b", | |
29 | t: "q", | |
30 | l: "k" | |
31 | }; | |
32 | } | |
33 | static get ALICE_CODES() { | |
34 | return { | |
35 | p: "s", | |
36 | r: "u", | |
37 | n: "o", | |
38 | b: "c", | |
39 | q: "t", | |
40 | k: "l" | |
41 | }; | |
42 | } | |
43 | ||
44 | getPieceType(x, y, p) { | |
45 | if (!p) | |
46 | p = super.getPiece(x, y); | |
47 | return V.ALICE_PIECES[p] || p; | |
48 | } | |
49 | ||
50 | pieces(color, x, y) { | |
51 | let alices = { | |
52 | 's': {"class": "alice-pawn", "moveas": "p"}, | |
53 | 'u': {"class": "alice-rook", "moveas": "r"}, | |
54 | 'o': {"class": "alice-knight", "moveas": "n"}, | |
55 | 'c': {"class": "alice-bishop", "moveas": "b"}, | |
56 | 't': {"class": "alice-queen", "moveas": "q"}, | |
57 | 'l': {"class": "alice-king", "moveas": "k"} | |
58 | }; | |
59 | return Object.assign(alices, super.pieces(color, x, y)); | |
60 | } | |
61 | ||
62 | fromSameWorld(p1, p2) { | |
63 | return ( | |
64 | (V.ALICE_PIECES[p1] && V.ALICE_PIECES[p2]) || | |
65 | (V.ALICE_CODES[p1] && V.ALICE_CODES[p2]) | |
66 | ); | |
67 | } | |
68 | ||
69 | // Step of p over i,j ? | |
70 | canStepOver(i, j, p) { | |
71 | return ( | |
72 | this.board[i][j] == "" || !this.fromSameWorld(this.getPiece(i, j), p)); | |
73 | } | |
74 | ||
75 | // NOTE: castle & enPassant | |
76 | // https://www.chessvariants.com/other.dir/alice.html | |
77 | getPotentialMovesFrom([x, y]) { | |
78 | return super.getPotentialMovesFrom([x, y]).filter(m => { | |
79 | // Remove moves landing on occupied square on other board | |
80 | return ( | |
81 | this.board[m.end.x][m.end.y] == "" || | |
82 | this.fromSameWorld(m.vanish[0].p, m.vanish[1].p) | |
83 | ); | |
84 | }).map(m => { | |
85 | // Apply Alice rule: go to the other side of the mirror | |
86 | if (Object.keys(V.ALICE_CODES).includes(m.vanish[0].p)) | |
87 | // Board 1 | |
88 | m.appear.forEach(a => a.p = V.ALICE_CODES[a.p]) | |
89 | else | |
90 | // Board 2 | |
91 | m.appear.forEach(a => a.p = V.ALICE_PIECES[a.p]) | |
92 | return m; | |
93 | }); | |
94 | } | |
95 | ||
96 | isKing(symbol) { | |
97 | return ['k', 'l'].includes(symbol); | |
98 | } | |
99 | ||
100 | getCurrentScore() { | |
101 | const color = this.turn; | |
102 | const inCheck = this.underCheck(this.searchKingPos(color)); | |
103 | let someLegalMove = false; | |
104 | // Search for legal moves: if any is found and | |
105 | // does not change king world (if under check), then game not over. | |
106 | for (let i=0; i<this.size.x; i++) { | |
107 | for (let j=0; j<this.size.y; j++) { | |
108 | if (this.getColor(i, j) == color) { | |
109 | const moves = this.filterValid(this.getPotentialMovesFrom([i, j])); | |
110 | if ( | |
111 | moves.length >= 1 && | |
112 | ( | |
113 | !inCheck || | |
114 | moves.some(m => m.vanish.every(v => !this.isKing(v.p))) | |
115 | ) | |
116 | ) { | |
117 | return "*"; | |
118 | } | |
119 | } | |
120 | } | |
121 | } | |
122 | // Couldn't find any legal move | |
123 | return (inCheck ? "1/2" : (color == 'w' ? "0-1" : "1-0")); | |
124 | } | |
125 | ||
126 | }; |