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