Commit | Line | Data |
---|---|---|
a6abf094 BA |
1 | class CrazyhouseRules extends ChessRules |
2 | { | |
2d7194bd | 3 | static IsGoodFen(fen) |
a6abf094 | 4 | { |
2d7194bd BA |
5 | if (!ChessRules.IsGoodFen(fen)) |
6 | return false; | |
7 | const fenParsed = V.ParseFen(fen); | |
8 | // 5) Check reserves | |
9 | if (!fenParsed.reserve || !fenParsed.reserve.match(/^[0-9]{10,10}$/)) | |
10 | return false; | |
11 | // 6) Check promoted array | |
12 | if (!fenParsed.promoted) | |
13 | return false; | |
14 | fenpromoted = fenParsed.promoted; | |
15 | if (fenpromoted == "-") | |
16 | return true; //no promoted piece on board | |
17 | const squares = fenpromoted.split(","); | |
18 | for (let square of squares) | |
19 | { | |
20 | const c = V.SquareToCoords(square); | |
21 | if (c.y < 0 || c.y > V.size.y || isNaN(c.x) || c.x < 0 || c.x > V.size.x) | |
22 | return false; | |
23 | } | |
24 | return true; | |
25 | } | |
26 | ||
27 | static GenRandInitFen() | |
28 | { | |
29 | const fen = ChessRules.GenRandInitFen(); | |
30 | return fen.replace(" w 1111", " w 1111 0000000000 -"); | |
31 | } | |
32 | ||
33 | getFen() | |
34 | { | |
35 | return super.getFen() + " " + this.getReserveFen() + " " + this.getPromotedFen(); | |
36 | } | |
37 | ||
38 | getReserveFen() | |
39 | { | |
40 | let counts = _.map(_.range(10), 0); | |
41 | for (let i=0; i<V.PIECES.length; i++) | |
42 | { | |
43 | counts[i] = this.reserve["w"][V.PIECES[i]]; | |
44 | counts[5+i] = this.reserve["b"][V.PIECES[i]]; | |
45 | } | |
46 | return counts.join(""); | |
47 | } | |
48 | ||
49 | getPromotedFen() | |
50 | { | |
51 | let res = ""; | |
52 | for (let i=0; i<V.size.x; i++) | |
53 | { | |
54 | for (let j=0; j<V.size.y; j++) | |
55 | { | |
56 | if (this.promoted[i][j]) | |
57 | res += V.CoordsToSquare({x:i,y:j}); | |
58 | } | |
59 | } | |
60 | if (res.length > 0) | |
61 | res = res.slice(0,-1); //remove last comma | |
62 | return res; | |
63 | } | |
64 | ||
65 | setOtherVariables(fen) | |
66 | { | |
67 | super.setOtherVariables(fen); | |
68 | const fenParsed = V.ParseFen(fen); | |
69 | // Also init reserves (used by the interface to show landable pieces) | |
a6abf094 BA |
70 | this.reserve = |
71 | { | |
72 | "w": | |
73 | { | |
2d7194bd BA |
74 | [V.PAWN]: parseInt(fenParsed.reserve[0]), |
75 | [V.ROOK]: parseInt(fenParsed.reserve[1]), | |
76 | [V.KNIGHT]: parseInt(fenParsed.reserve[2]), | |
77 | [V.BISHOP]: parseInt(fenParsed.reserve[3]), | |
78 | [V.QUEEN]: parseInt(fenParsed.reserve[4]), | |
a6abf094 BA |
79 | }, |
80 | "b": | |
81 | { | |
2d7194bd BA |
82 | [V.PAWN]: parseInt(fenParsed.reserve[5]), |
83 | [V.ROOK]: parseInt(fenParsed.reserve[6]), | |
84 | [V.KNIGHT]: parseInt(fenParsed.reserve[7]), | |
85 | [V.BISHOP]: parseInt(fenParsed.reserve[8]), | |
86 | [V.QUEEN]: parseInt(fenParsed.reserve[9]), | |
a6abf094 BA |
87 | } |
88 | }; | |
0b7d99ec | 89 | this.promoted = doubleArray(V.size.x, V.size.y, false); |
2d7194bd BA |
90 | for (let square of fenParsd.promoted.split(",")) |
91 | { | |
92 | const [x,y] = V.SquareToCoords(square); | |
93 | promoted[x][y] = true; | |
94 | } | |
5c42c64e BA |
95 | } |
96 | ||
97 | getColor(i,j) | |
98 | { | |
0b7d99ec BA |
99 | if (i >= V.size.x) |
100 | return (i==V.size.x ? "w" : "b"); | |
5c42c64e BA |
101 | return this.board[i][j].charAt(0); |
102 | } | |
2d7194bd | 103 | |
5c42c64e BA |
104 | getPiece(i,j) |
105 | { | |
0b7d99ec BA |
106 | if (i >= V.size.x) |
107 | return V.RESERVE_PIECES[j]; | |
5c42c64e | 108 | return this.board[i][j].charAt(1); |
a6abf094 BA |
109 | } |
110 | ||
111 | // Used by the interface: | |
1221ac47 | 112 | getReservePpath(color, index) |
a6abf094 | 113 | { |
0b7d99ec | 114 | return color + V.RESERVE_PIECES[index]; |
a6abf094 BA |
115 | } |
116 | ||
92342261 | 117 | // Ordering on reserve pieces |
2d7194bd BA |
118 | static get RESERVE_PIECES() |
119 | { | |
1221ac47 BA |
120 | return [V.PAWN,V.ROOK,V.KNIGHT,V.BISHOP,V.QUEEN]; |
121 | } | |
122 | ||
123 | getReserveMoves([x,y]) | |
a6abf094 | 124 | { |
a6abf094 | 125 | const color = this.turn; |
0b7d99ec | 126 | const p = V.RESERVE_PIECES[y]; |
1221ac47 BA |
127 | if (this.reserve[color][p] == 0) |
128 | return []; | |
129 | let moves = []; | |
0b7d99ec BA |
130 | const pawnShift = (p==V.PAWN ? 1 : 0); |
131 | for (let i=pawnShift; i<V.size.x-pawnShift; i++) | |
1221ac47 | 132 | { |
0b7d99ec | 133 | for (let j=0; j<V.size.y; j++) |
1221ac47 | 134 | { |
0b7d99ec | 135 | if (this.board[i][j] == V.EMPTY) |
1221ac47 BA |
136 | { |
137 | let mv = new Move({ | |
138 | appear: [ | |
139 | new PiPo({ | |
140 | x: i, | |
141 | y: j, | |
142 | c: color, | |
143 | p: p | |
144 | }) | |
5c42c64e BA |
145 | ], |
146 | vanish: [], | |
6752407b | 147 | start: {x:x, y:y}, //a bit artificial... |
5c42c64e | 148 | end: {x:i, y:j} |
1221ac47 BA |
149 | }); |
150 | moves.push(mv); | |
151 | } | |
152 | } | |
153 | } | |
a6abf094 BA |
154 | return moves; |
155 | } | |
156 | ||
1221ac47 | 157 | getPotentialMovesFrom([x,y]) |
a6abf094 | 158 | { |
0b7d99ec | 159 | if (x >= V.size.x) |
6752407b | 160 | { |
92342261 | 161 | // Reserves, outside of board: x == sizeX(+1) |
6752407b BA |
162 | return this.getReserveMoves([x,y]); |
163 | } | |
164 | // Standard moves | |
165 | return super.getPotentialMovesFrom([x,y]); | |
a6abf094 BA |
166 | } |
167 | ||
a6abf094 BA |
168 | getAllValidMoves() |
169 | { | |
1221ac47 BA |
170 | let moves = super.getAllValidMoves(); |
171 | const color = this.turn; | |
0b7d99ec BA |
172 | for (let i=0; i<V.RESERVE_PIECES.length; i++) |
173 | moves = moves.concat(this.getReserveMoves([V.size.x+(color=="w"?0:1),i])); | |
1221ac47 | 174 | return this.filterValid(moves); |
a6abf094 BA |
175 | } |
176 | ||
a6abf094 BA |
177 | atLeastOneMove() |
178 | { | |
1221ac47 BA |
179 | if (!super.atLeastOneMove()) |
180 | { | |
0b7d99ec BA |
181 | const color = this.turn; |
182 | // Search one reserve move | |
183 | for (let i=0; i<V.RESERVE_PIECES.length; i++) | |
1221ac47 | 184 | { |
0b7d99ec BA |
185 | let moves = this.filterValid( |
186 | this.getReserveMoves([V.size.x+(this.turn=="w"?0:1), i]) ); | |
1221ac47 BA |
187 | if (moves.length > 0) |
188 | return true; | |
189 | } | |
190 | return false; | |
191 | } | |
192 | return true; | |
a6abf094 BA |
193 | } |
194 | ||
a6abf094 BA |
195 | updateVariables(move) |
196 | { | |
1221ac47 | 197 | super.updateVariables(move); |
6752407b BA |
198 | if (move.vanish.length == 2 && move.appear.length == 2) |
199 | return; //skip castle | |
1221ac47 | 200 | const color = this.turn; |
6752407b | 201 | if (move.vanish.length == 0) |
6752407b | 202 | { |
8a60cacd BA |
203 | this.reserve[color][move.appear[0].p]--; |
204 | return; | |
6752407b | 205 | } |
8a60cacd BA |
206 | move.movePromoted = this.promoted[move.start.x][move.start.y]; |
207 | move.capturePromoted = this.promoted[move.end.x][move.end.y] | |
208 | this.promoted[move.start.x][move.start.y] = false; | |
209 | this.promoted[move.end.x][move.end.y] = move.movePromoted | |
210 | || (move.vanish[0].p == V.PAWN && move.appear[0].p != V.PAWN); | |
211 | if (move.capturePromoted) | |
0b7d99ec | 212 | this.reserve[color][V.PAWN]++; |
8a60cacd BA |
213 | else if (move.vanish.length == 2) |
214 | this.reserve[color][move.vanish[1].p]++; | |
a6abf094 | 215 | } |
1221ac47 | 216 | |
a6abf094 BA |
217 | unupdateVariables(move) |
218 | { | |
1221ac47 | 219 | super.unupdateVariables(move); |
8a60cacd BA |
220 | if (move.vanish.length == 2 && move.appear.length == 2) |
221 | return; | |
1221ac47 | 222 | const color = this.turn; |
6752407b | 223 | if (move.vanish.length == 0) |
6752407b | 224 | { |
8a60cacd BA |
225 | this.reserve[color][move.appear[0].p]++; |
226 | return; | |
6752407b | 227 | } |
8a60cacd BA |
228 | if (move.movePromoted) |
229 | this.promoted[move.start.x][move.start.y] = true; | |
230 | this.promoted[move.end.x][move.end.y] = move.capturePromoted; | |
231 | if (move.capturePromoted) | |
0b7d99ec | 232 | this.reserve[color][V.PAWN]--; |
8a60cacd BA |
233 | else if (move.vanish.length == 2) |
234 | this.reserve[color][move.vanish[1].p]--; | |
a6abf094 BA |
235 | } |
236 | ||
237 | static get SEARCH_DEPTH() { return 2; } //high branching factor | |
238 | ||
6752407b BA |
239 | evalPosition() |
240 | { | |
241 | let evaluation = super.evalPosition(); | |
242 | // Add reserves: | |
0b7d99ec | 243 | for (let i=0; i<V.RESERVE_PIECES.length; i++) |
6752407b | 244 | { |
0b7d99ec BA |
245 | const p = V.RESERVE_PIECES[i]; |
246 | evaluation += this.reserve["w"][p] * V.VALUES[p]; | |
247 | evaluation -= this.reserve["b"][p] * V.VALUES[p]; | |
6752407b BA |
248 | } |
249 | return evaluation; | |
250 | } | |
251 | ||
a6abf094 BA |
252 | getNotation(move) |
253 | { | |
254 | if (move.vanish.length > 0) | |
255 | return super.getNotation(move); | |
256 | // Rebirth: | |
257 | const piece = | |
0b7d99ec | 258 | (move.appear[0].p != V.PAWN ? move.appear[0].p.toUpperCase() : ""); |
2d7194bd | 259 | return piece + "@" + V.CoordsToSquare(move.end); |
a6abf094 | 260 | } |
6752407b BA |
261 | |
262 | getLongNotation(move) | |
263 | { | |
264 | if (move.vanish.length > 0) | |
265 | return super.getLongNotation(move); | |
2d7194bd | 266 | return "@" + V.CoordsToSquare(move.end); |
6752407b | 267 | } |
a6abf094 | 268 | } |