Commit | Line | Data |
---|---|---|
a6abf094 BA |
1 | class CrazyhouseRules extends ChessRules |
2 | { | |
3 | initVariables(fen) | |
4 | { | |
1221ac47 | 5 | super.initVariables(fen); |
a6abf094 BA |
6 | // Also init reserves (used by the interface to show landing pieces) |
7 | const V = VariantRules; | |
8 | this.reserve = | |
9 | { | |
10 | "w": | |
11 | { | |
12 | [V.PAWN]: 0, | |
13 | [V.ROOK]: 0, | |
14 | [V.KNIGHT]: 0, | |
15 | [V.BISHOP]: 0, | |
16 | [V.QUEEN]: 0, | |
17 | }, | |
18 | "b": | |
19 | { | |
20 | [V.PAWN]: 0, | |
21 | [V.ROOK]: 0, | |
22 | [V.KNIGHT]: 0, | |
23 | [V.BISHOP]: 0, | |
24 | [V.QUEEN]: 0, | |
25 | } | |
26 | }; | |
6752407b BA |
27 | const [sizeX,sizeY] = VariantRules.size; |
28 | this.promoted = doubleArray(sizeX, sizeY, false); | |
29 | // May be a continuation: adjust numbers of pieces in reserve + promoted pieces | |
30 | this.moves.forEach(m => { this.updateVariables(m); }); | |
5c42c64e BA |
31 | } |
32 | ||
33 | getColor(i,j) | |
34 | { | |
35 | const sizeX = VariantRules.size[0]; | |
36 | if (i >= sizeX) | |
37 | return (i==sizeX ? "w" : "b"); | |
38 | return this.board[i][j].charAt(0); | |
39 | } | |
40 | getPiece(i,j) | |
41 | { | |
42 | const sizeX = VariantRules.size[0]; | |
43 | if (i >= sizeX) | |
44 | return VariantRules.RESERVE_PIECES[j]; | |
45 | return this.board[i][j].charAt(1); | |
a6abf094 BA |
46 | } |
47 | ||
48 | // Used by the interface: | |
1221ac47 | 49 | getReservePpath(color, index) |
a6abf094 | 50 | { |
1221ac47 | 51 | return color + VariantRules.RESERVE_PIECES[index]; |
a6abf094 BA |
52 | } |
53 | ||
1221ac47 BA |
54 | // Put an ordering on reserve pieces |
55 | static get RESERVE_PIECES() { | |
56 | const V = VariantRules; | |
57 | return [V.PAWN,V.ROOK,V.KNIGHT,V.BISHOP,V.QUEEN]; | |
58 | } | |
59 | ||
60 | getReserveMoves([x,y]) | |
a6abf094 | 61 | { |
a6abf094 | 62 | const color = this.turn; |
1221ac47 BA |
63 | const p = VariantRules.RESERVE_PIECES[y]; |
64 | if (this.reserve[color][p] == 0) | |
65 | return []; | |
66 | let moves = []; | |
5c42c64e BA |
67 | const [sizeX,sizeY] = VariantRules.size; |
68 | const pawnShift = (p==VariantRules.PAWN ? 1 : 0); | |
69 | for (let i=pawnShift; i<sizeX-pawnShift; i++) | |
1221ac47 BA |
70 | { |
71 | for (let j=0; j<sizeY; j++) | |
72 | { | |
5c42c64e | 73 | if (this.board[i][j] == VariantRules.EMPTY) |
1221ac47 BA |
74 | { |
75 | let mv = new Move({ | |
76 | appear: [ | |
77 | new PiPo({ | |
78 | x: i, | |
79 | y: j, | |
80 | c: color, | |
81 | p: p | |
82 | }) | |
5c42c64e BA |
83 | ], |
84 | vanish: [], | |
6752407b | 85 | start: {x:x, y:y}, //a bit artificial... |
5c42c64e | 86 | end: {x:i, y:j} |
1221ac47 BA |
87 | }); |
88 | moves.push(mv); | |
89 | } | |
90 | } | |
91 | } | |
a6abf094 BA |
92 | return moves; |
93 | } | |
94 | ||
1221ac47 | 95 | getPotentialMovesFrom([x,y]) |
a6abf094 | 96 | { |
1221ac47 | 97 | const sizeX = VariantRules.size[0]; |
6752407b BA |
98 | if (x >= sizeX) |
99 | { | |
100 | // Reserves, outside of board: x == sizeX | |
101 | return this.getReserveMoves([x,y]); | |
102 | } | |
103 | // Standard moves | |
104 | return super.getPotentialMovesFrom([x,y]); | |
a6abf094 BA |
105 | } |
106 | ||
a6abf094 BA |
107 | getAllValidMoves() |
108 | { | |
1221ac47 BA |
109 | let moves = super.getAllValidMoves(); |
110 | const color = this.turn; | |
111 | const sizeX = VariantRules.size[0]; | |
112 | for (let i=0; i<VariantRules.RESERVE_PIECES.length; i++) | |
6752407b | 113 | moves = moves.concat(this.getReserveMoves([sizeX+(color=="w"?0:1),i])); |
1221ac47 | 114 | return this.filterValid(moves); |
a6abf094 BA |
115 | } |
116 | ||
a6abf094 BA |
117 | atLeastOneMove() |
118 | { | |
1221ac47 BA |
119 | if (!super.atLeastOneMove()) |
120 | { | |
121 | const sizeX = VariantRules.size[0]; | |
122 | // Scan for reserve moves | |
123 | for (let i=0; i<VariantRules.RESERVE_PIECES.length; i++) | |
124 | { | |
125 | let moves = this.filterValid(this.getReserveMoves([sizeX,i])); | |
126 | if (moves.length > 0) | |
127 | return true; | |
128 | } | |
129 | return false; | |
130 | } | |
131 | return true; | |
a6abf094 BA |
132 | } |
133 | ||
a6abf094 BA |
134 | updateVariables(move) |
135 | { | |
1221ac47 | 136 | super.updateVariables(move); |
6752407b BA |
137 | if (move.vanish.length == 2 && move.appear.length == 2) |
138 | return; //skip castle | |
1221ac47 | 139 | const color = this.turn; |
6752407b BA |
140 | const V = VariantRules; |
141 | // Three types of move: | |
142 | // 1. Rebirth: just update material | |
143 | // 2. Standard move: | |
144 | // a. check if a promoted piece is moving | |
145 | // b. check if it's a promotion (mutually exclusive) | |
146 | // 3. Capture: | |
147 | // a. check if a promoted piece is captured (and mark move) | |
148 | // b. check if a promoted piece is moving | |
149 | // c. check if it's a promotion (mutually exclusive with b) | |
150 | if (move.vanish.length == 0) | |
1221ac47 | 151 | this.reserve[color][move.appear[0].p]--; |
6752407b BA |
152 | else if (move.vanish.length == 1) |
153 | { | |
154 | if (this.promoted[move.start.x][move.start.y]) | |
155 | { | |
156 | this.promoted[move.start.x][move.start.y] = false; | |
157 | this.promoted[move.end.x][move.end.y] = true; | |
158 | } | |
159 | else if (move.vanish[0].p == V.PAWN && move.appear[0].p != V.PAWN) | |
160 | this.promoted[move.end.x][move.end.y] = true; | |
161 | } | |
162 | else //capture | |
163 | { | |
164 | if (this.promoted[move.end.x][move.end.y]) | |
165 | { | |
166 | move.capturePromoted = true; //required for undo | |
167 | this.reserve[color][VariantRules.PAWN]++; | |
168 | this.promoted[move.end.x][move.end.y] = false; | |
169 | } | |
170 | else | |
171 | this.reserve[color][move.vanish[1].p]++; | |
172 | if (this.promoted[move.start.x][move.start.y]) | |
173 | { | |
174 | this.promoted[move.start.x][move.start.y] = false; | |
175 | this.promoted[move.end.x][move.end.y] = true; | |
176 | } | |
177 | else if (move.vanish[0].p == V.PAWN && move.appear[0].p != V.PAWN) | |
178 | this.promoted[move.end.x][move.end.y] = true; | |
179 | } | |
a6abf094 | 180 | } |
1221ac47 | 181 | |
a6abf094 BA |
182 | unupdateVariables(move) |
183 | { | |
1221ac47 BA |
184 | super.unupdateVariables(move); |
185 | const color = this.turn; | |
6752407b BA |
186 | const V = VariantRules; |
187 | if (move.vanish.length == 0) | |
1221ac47 | 188 | this.reserve[color][move.appear[0].p]++; |
6752407b BA |
189 | else if (move.vanish.length == 1) |
190 | { | |
191 | if (this.promoted[move.end.x][move.end.y]) | |
192 | { | |
193 | this.promoted[move.end.x][move.end.y] = false; | |
194 | if (move.vanish[0].p != V.PAWN || move.appear[0].p == V.PAWN) | |
195 | { | |
196 | // Not a promotion (= promoted piece creation) | |
197 | this.promoted[move.start.x][move.start.y] = true; | |
198 | } | |
199 | } | |
200 | } | |
201 | else //capture | |
202 | { | |
203 | if (this.promoted[move.end.x][move.end.y]) | |
204 | { | |
205 | this.promoted[move.end.x][move.end.y] = !!move.capturePromoted; | |
206 | if (move.vanish[0].p != V.PAWN || move.appear[0].p == V.PAWN) | |
207 | this.promoted[move.start.x][move.start.y] = true; | |
208 | } | |
209 | // Un-update material: | |
210 | if (move.capturePromoted) | |
211 | this.reserve[color][VariantRules.PAWN]--; | |
212 | else | |
213 | this.reserve[color][move.vanish[1].p]--; | |
214 | } | |
a6abf094 BA |
215 | } |
216 | ||
217 | static get SEARCH_DEPTH() { return 2; } //high branching factor | |
218 | ||
6752407b BA |
219 | evalPosition() |
220 | { | |
221 | let evaluation = super.evalPosition(); | |
222 | // Add reserves: | |
223 | for (let i=0; i<VariantRules.RESERVE_PIECES.length; i++) | |
224 | { | |
225 | const p = VariantRules.RESERVE_PIECES[i]; | |
226 | evaluation += this.reserve["w"][p] * VariantRules.VALUES[p]; | |
227 | evaluation -= this.reserve["b"][p] * VariantRules.VALUES[p]; | |
228 | } | |
229 | return evaluation; | |
230 | } | |
231 | ||
a6abf094 BA |
232 | getNotation(move) |
233 | { | |
234 | if (move.vanish.length > 0) | |
235 | return super.getNotation(move); | |
236 | // Rebirth: | |
237 | const piece = | |
5c42c64e | 238 | (move.appear[0].p != VariantRules.PAWN ? move.appear[0].p.toUpperCase() : ""); |
a6abf094 BA |
239 | const finalSquare = |
240 | String.fromCharCode(97 + move.end.y) + (VariantRules.size[0]-move.end.x); | |
241 | return piece + "@" + finalSquare; | |
242 | } | |
6752407b BA |
243 | |
244 | getLongNotation(move) | |
245 | { | |
246 | if (move.vanish.length > 0) | |
247 | return super.getLongNotation(move); | |
248 | const finalSquare = | |
249 | String.fromCharCode(97 + move.end.y) + (VariantRules.size[0]-move.end.x); | |
250 | return "@" + finalSquare; | |
251 | } | |
a6abf094 | 252 | } |