Commit | Line | Data |
---|---|---|
0c3fe8a6 | 1 | import { ChessRules } from "@/base_rules"; |
6808d7a1 | 2 | import { ArrayFun } from "@/utils/array"; |
0c3fe8a6 BA |
3 | import { randInt } from "@/utils/alea"; |
4 | ||
32f6285e | 5 | export class Antiking2Rules extends ChessRules { |
7e8a7ea1 | 6 | |
6808d7a1 BA |
7 | static get ANTIKING() { |
8 | return "a"; | |
9 | } | |
dac39588 | 10 | |
6808d7a1 | 11 | static get PIECES() { |
dac39588 BA |
12 | return ChessRules.PIECES.concat([V.ANTIKING]); |
13 | } | |
14 | ||
241bf8f2 BA |
15 | getPpath(b) { |
16 | return b[1] == "a" ? "Antiking/" + b : b; | |
17 | } | |
18 | ||
6f2f9437 BA |
19 | static IsGoodPosition(position) { |
20 | if (!ChessRules.IsGoodPosition(position)) return false; | |
21 | const rows = position.split("/"); | |
22 | // Check that exactly one antiking of each color is there: | |
23 | let antikings = { 'a': 0, 'A': 0 }; | |
24 | for (let row of rows) { | |
25 | for (let i = 0; i < row.length; i++) | |
26 | if (['A','a'].includes(row[i])) antikings[row[i]]++; | |
27 | } | |
28 | if (Object.values(antikings).some(v => v != 1)) return false; | |
29 | return true; | |
30 | } | |
31 | ||
6808d7a1 | 32 | setOtherVariables(fen) { |
dac39588 | 33 | super.setOtherVariables(fen); |
6808d7a1 | 34 | this.antikingPos = { w: [-1, -1], b: [-1, -1] }; |
dac39588 | 35 | const rows = V.ParseFen(fen).position.split("/"); |
6808d7a1 | 36 | for (let i = 0; i < rows.length; i++) { |
dac39588 | 37 | let k = 0; |
6808d7a1 BA |
38 | for (let j = 0; j < rows[i].length; j++) { |
39 | switch (rows[i].charAt(j)) { | |
40 | case "a": | |
41 | this.antikingPos["b"] = [i, k]; | |
dac39588 | 42 | break; |
6808d7a1 BA |
43 | case "A": |
44 | this.antikingPos["w"] = [i, k]; | |
dac39588 | 45 | break; |
6808d7a1 | 46 | default: { |
e50a8025 | 47 | const num = parseInt(rows[i].charAt(j), 10); |
6808d7a1 BA |
48 | if (!isNaN(num)) k += num - 1; |
49 | } | |
dac39588 BA |
50 | } |
51 | k++; | |
52 | } | |
53 | } | |
54 | } | |
55 | ||
6808d7a1 BA |
56 | canTake([x1, y1], [x2, y2]) { |
57 | const piece1 = this.getPiece(x1, y1); | |
58 | const piece2 = this.getPiece(x2, y2); | |
59 | const color1 = this.getColor(x1, y1); | |
60 | const color2 = this.getColor(x2, y2); | |
61 | return ( | |
62 | piece2 != "a" && | |
c583ef1c BA |
63 | ( |
64 | (piece1 != "a" && color1 != color2) || | |
65 | (piece1 == "a" && color1 == color2) | |
66 | ) | |
6808d7a1 | 67 | ); |
dac39588 BA |
68 | } |
69 | ||
6808d7a1 BA |
70 | getPotentialMovesFrom([x, y]) { |
71 | switch (this.getPiece(x, y)) { | |
dac39588 | 72 | case V.ANTIKING: |
6808d7a1 | 73 | return this.getPotentialAntikingMoves([x, y]); |
dac39588 | 74 | default: |
6808d7a1 | 75 | return super.getPotentialMovesFrom([x, y]); |
dac39588 BA |
76 | } |
77 | } | |
78 | ||
6808d7a1 | 79 | getPotentialAntikingMoves(sq) { |
c583ef1c | 80 | // The antiking moves like a king (only captured colors differ) |
6808d7a1 BA |
81 | return this.getSlideNJumpMoves( |
82 | sq, | |
83 | V.steps[V.ROOK].concat(V.steps[V.BISHOP]), | |
84 | "oneStep" | |
85 | ); | |
dac39588 BA |
86 | } |
87 | ||
68e19a44 | 88 | isAttacked(sq, color) { |
6808d7a1 | 89 | return ( |
68e19a44 BA |
90 | super.isAttacked(sq, color) || |
91 | this.isAttackedByAntiking(sq, color) | |
6808d7a1 | 92 | ); |
dac39588 BA |
93 | } |
94 | ||
68e19a44 BA |
95 | isAttackedByKing([x, y], color) { |
96 | // Antiking is not attacked by king: | |
97 | if (this.getPiece(x, y) == V.ANTIKING) return false; | |
c583ef1c | 98 | return super.isAttackedByKing([x, y], color); |
dac39588 BA |
99 | } |
100 | ||
68e19a44 BA |
101 | isAttackedByAntiking([x, y], color) { |
102 | // (Anti)King is not attacked by antiking | |
103 | if ([V.KING, V.ANTIKING].includes(this.getPiece(x, y))) return false; | |
6808d7a1 BA |
104 | return this.isAttackedBySlideNJump( |
105 | [x, y], | |
68e19a44 | 106 | color, |
6808d7a1 BA |
107 | V.ANTIKING, |
108 | V.steps[V.ROOK].concat(V.steps[V.BISHOP]), | |
109 | "oneStep" | |
110 | ); | |
dac39588 BA |
111 | } |
112 | ||
6808d7a1 | 113 | underCheck(color) { |
dac39588 | 114 | const oppCol = V.GetOppCol(color); |
6808d7a1 | 115 | let res = |
68e19a44 BA |
116 | this.isAttacked(this.kingPos[color], oppCol) || |
117 | !this.isAttacked(this.antikingPos[color], oppCol); | |
dac39588 BA |
118 | return res; |
119 | } | |
120 | ||
af34341d BA |
121 | getCheckSquares() { |
122 | const color = this.turn; | |
c583ef1c BA |
123 | let res = []; |
124 | const oppCol = V.GetOppCol(color); | |
125 | if (this.isAttacked(this.kingPos[color], oppCol)) | |
126 | res.push(JSON.parse(JSON.stringify(this.kingPos[color]))); | |
127 | if (!this.isAttacked(this.antikingPos[color], oppCol)) | |
dac39588 BA |
128 | res.push(JSON.parse(JSON.stringify(this.antikingPos[color]))); |
129 | return res; | |
130 | } | |
131 | ||
3a2a7b5f BA |
132 | postPlay(move) { |
133 | super.postPlay(move); | |
dac39588 BA |
134 | const piece = move.vanish[0].p; |
135 | const c = move.vanish[0].c; | |
136 | // Update antiking position | |
6808d7a1 | 137 | if (piece == V.ANTIKING) { |
dac39588 BA |
138 | this.antikingPos[c][0] = move.appear[0].x; |
139 | this.antikingPos[c][1] = move.appear[0].y; | |
140 | } | |
141 | } | |
142 | ||
3a2a7b5f BA |
143 | postUndo(move) { |
144 | super.postUndo(move); | |
dac39588 BA |
145 | const c = move.vanish[0].c; |
146 | if (move.vanish[0].p == V.ANTIKING) | |
147 | this.antikingPos[c] = [move.start.x, move.start.y]; | |
148 | } | |
149 | ||
dac39588 | 150 | static get VALUES() { |
a97bdbda BA |
151 | return Object.assign( |
152 | { a: 1000 }, | |
153 | ChessRules.VALUES | |
154 | ); | |
dac39588 BA |
155 | } |
156 | ||
7ba4a5bc | 157 | static GenRandInitFen(randomness) { |
7ba4a5bc | 158 | if (randomness == 0) |
3a2a7b5f | 159 | return "rnbqkbnr/pppppppp/3A4/8/8/3a4/PPPPPPPP/RNBQKBNR w 0 ahah -"; |
7ba4a5bc | 160 | |
6808d7a1 | 161 | let pieces = { w: new Array(8), b: new Array(8) }; |
3a2a7b5f | 162 | let flags = ""; |
6808d7a1 BA |
163 | let antikingPos = { w: -1, b: -1 }; |
164 | for (let c of ["w", "b"]) { | |
7ba4a5bc BA |
165 | if (c == 'b' && randomness == 1) { |
166 | pieces['b'] = pieces['w']; | |
42a92848 | 167 | antikingPos['b'] = antikingPos['w']; |
3a2a7b5f | 168 | flags += flags; |
7ba4a5bc BA |
169 | break; |
170 | } | |
171 | ||
dac39588 BA |
172 | let positions = ArrayFun.range(8); |
173 | ||
174 | // Get random squares for bishops, but avoid corners; because, | |
175 | // if an antiking blocks a cornered bishop, it can never be checkmated | |
6808d7a1 | 176 | let randIndex = 2 * randInt(1, 4); |
dac39588 BA |
177 | const bishop1Pos = positions[randIndex]; |
178 | let randIndex_tmp = 2 * randInt(3) + 1; | |
179 | const bishop2Pos = positions[randIndex_tmp]; | |
6808d7a1 BA |
180 | positions.splice(Math.max(randIndex, randIndex_tmp), 1); |
181 | positions.splice(Math.min(randIndex, randIndex_tmp), 1); | |
dac39588 BA |
182 | |
183 | randIndex = randInt(6); | |
184 | const knight1Pos = positions[randIndex]; | |
185 | positions.splice(randIndex, 1); | |
186 | randIndex = randInt(5); | |
187 | const knight2Pos = positions[randIndex]; | |
188 | positions.splice(randIndex, 1); | |
189 | ||
190 | randIndex = randInt(4); | |
191 | const queenPos = positions[randIndex]; | |
192 | positions.splice(randIndex, 1); | |
193 | ||
194 | const rook1Pos = positions[0]; | |
195 | const kingPos = positions[1]; | |
196 | const rook2Pos = positions[2]; | |
197 | ||
198 | // Random squares for antikings | |
199 | antikingPos[c] = randInt(8); | |
200 | ||
6808d7a1 BA |
201 | pieces[c][rook1Pos] = "r"; |
202 | pieces[c][knight1Pos] = "n"; | |
203 | pieces[c][bishop1Pos] = "b"; | |
204 | pieces[c][queenPos] = "q"; | |
205 | pieces[c][kingPos] = "k"; | |
206 | pieces[c][bishop2Pos] = "b"; | |
207 | pieces[c][knight2Pos] = "n"; | |
208 | pieces[c][rook2Pos] = "r"; | |
3a2a7b5f | 209 | flags += V.CoordToColumn(rook1Pos) + V.CoordToColumn(rook2Pos); |
dac39588 | 210 | } |
6808d7a1 BA |
211 | const ranks23_black = |
212 | "pppppppp/" + | |
213 | (antikingPos["w"] > 0 ? antikingPos["w"] : "") + | |
214 | "A" + | |
215 | (antikingPos["w"] < 7 ? 7 - antikingPos["w"] : ""); | |
216 | const ranks23_white = | |
217 | (antikingPos["b"] > 0 ? antikingPos["b"] : "") + | |
218 | "a" + | |
219 | (antikingPos["b"] < 7 ? 7 - antikingPos["b"] : "") + | |
220 | "/PPPPPPPP"; | |
221 | return ( | |
222 | pieces["b"].join("") + | |
223 | "/" + | |
224 | ranks23_black + | |
dac39588 | 225 | "/8/8/" + |
6808d7a1 BA |
226 | ranks23_white + |
227 | "/" + | |
228 | pieces["w"].join("").toUpperCase() + | |
3a2a7b5f | 229 | " w 0 " + flags + " -" |
6808d7a1 | 230 | ); |
dac39588 | 231 | } |
b83a675a BA |
232 | |
233 | static get SEARCH_DEPTH() { | |
234 | return 2; | |
235 | } | |
7e8a7ea1 | 236 | |
6808d7a1 | 237 | }; |