Commit | Line | Data |
---|---|---|
31e9e40a | 1 | import { ChessRules, PiPo, Move } from "@/base_rules"; |
964eda04 | 2 | import { SuicideRules } from "@/variants/Suicide"; |
31e9e40a | 3 | |
32f6285e | 4 | export class SuctionRules extends ChessRules { |
7e8a7ea1 | 5 | |
2ac5c764 BA |
6 | static get PawnSpecs() { |
7 | return Object.assign( | |
8 | {}, | |
9 | ChessRules.PawnSpecs, | |
10 | // No promotions: | |
11 | { promotions: [V.PAWN] } | |
12 | ); | |
13 | } | |
14 | ||
3a2a7b5f BA |
15 | static get HasFlags() { |
16 | return false; | |
17 | } | |
18 | ||
241bf8f2 BA |
19 | setOtherVariables(fen) { |
20 | super.setOtherVariables(fen); | |
3a2a7b5f | 21 | // Local stack of "captures" |
241bf8f2 | 22 | this.cmoves = []; |
3a2a7b5f | 23 | const cmove = V.ParseFen(fen).cmove; |
241bf8f2 BA |
24 | if (cmove == "-") this.cmoves.push(null); |
25 | else { | |
26 | this.cmoves.push({ | |
27 | start: ChessRules.SquareToCoords(cmove.substr(0, 2)), | |
28 | end: ChessRules.SquareToCoords(cmove.substr(2)) | |
29 | }); | |
30 | } | |
31 | } | |
32 | ||
3a2a7b5f | 33 | static ParseFen(fen) { |
6f2f9437 BA |
34 | return Object.assign( |
35 | ChessRules.ParseFen(fen), | |
36 | { cmove: fen.split(" ")[4] } | |
37 | ); | |
3a2a7b5f BA |
38 | } |
39 | ||
241bf8f2 BA |
40 | static IsGoodFen(fen) { |
41 | if (!ChessRules.IsGoodFen(fen)) return false; | |
42 | const fenParts = fen.split(" "); | |
61656127 BA |
43 | if (fenParts.length != 5) return false; |
44 | if (fenParts[4] != "-" && !fenParts[4].match(/^([a-h][1-8]){2}$/)) | |
241bf8f2 BA |
45 | return false; |
46 | return true; | |
47 | } | |
48 | ||
49 | getCmove(move) { | |
50 | if (move.vanish.length == 2) | |
51 | return { start: move.start, end: move.end }; | |
52 | return null; | |
53 | } | |
54 | ||
31e9e40a BA |
55 | getBasicMove([sx, sy], [ex, ey]) { |
56 | const startColor = this.getColor(sx, sy); | |
57 | const startPiece = this.getPiece(sx, sy); | |
58 | let mv = new Move({ | |
59 | appear: [ | |
60 | new PiPo({ | |
61 | x: ex, | |
62 | y: ey, | |
63 | c: startColor, | |
64 | p: startPiece | |
65 | }) | |
66 | ], | |
67 | vanish: [ | |
68 | new PiPo({ | |
69 | x: sx, | |
70 | y: sy, | |
71 | c: startColor, | |
72 | p: startPiece | |
73 | }) | |
74 | ] | |
75 | }); | |
76 | ||
77 | if (this.board[ex][ey] != V.EMPTY) { | |
78 | const endColor = this.getColor(ex, ey); | |
79 | const endPiece = this.getPiece(ex, ey); | |
80 | mv.vanish.push( | |
81 | new PiPo({ | |
82 | x: ex, | |
83 | y: ey, | |
84 | c: endColor, | |
85 | p: endPiece | |
86 | }) | |
87 | ); | |
88 | mv.appear.push( | |
89 | new PiPo({ | |
90 | x: sx, | |
91 | y: sy, | |
92 | c: endColor, | |
93 | p: endPiece | |
94 | }) | |
95 | ); | |
96 | } | |
97 | return mv; | |
98 | } | |
99 | ||
32f6285e | 100 | getEnpassantCaptures([x, y], shiftX) { |
31e9e40a | 101 | let moves = []; |
31e9e40a BA |
102 | const Lep = this.epSquares.length; |
103 | const epSquare = this.epSquares[Lep - 1]; //always at least one element | |
104 | if ( | |
105 | !!epSquare && | |
106 | epSquare.x == x + shiftX && | |
107 | Math.abs(epSquare.y - y) == 1 | |
108 | ) { | |
109 | let enpassantMove = this.getBasicMove([x, y], [epSquare.x, epSquare.y]); | |
58bf4670 | 110 | const oppCol = V.GetOppCol(this.turn); |
31e9e40a BA |
111 | enpassantMove.vanish.push({ |
112 | x: x, | |
113 | y: epSquare.y, | |
114 | p: "p", | |
115 | c: oppCol | |
116 | }); | |
117 | enpassantMove.appear.push({ | |
118 | x: x, | |
119 | y: y, | |
120 | p: "p", | |
121 | c: oppCol | |
122 | }); | |
123 | moves.push(enpassantMove); | |
124 | } | |
31e9e40a BA |
125 | return moves; |
126 | } | |
127 | ||
128 | getPotentialKingMoves() { | |
129 | return []; | |
130 | } | |
131 | ||
241bf8f2 BA |
132 | // Does m2 un-do m1 ? (to disallow undoing captures) |
133 | oppositeMoves(m1, m2) { | |
134 | return ( | |
61656127 | 135 | !!m1 && |
241bf8f2 BA |
136 | m2.vanish.length == 2 && |
137 | m1.start.x == m2.start.x && | |
138 | m1.end.x == m2.end.x && | |
139 | m1.start.y == m2.start.y && | |
140 | m1.end.y == m2.end.y | |
141 | ); | |
142 | } | |
143 | ||
144 | filterValid(moves) { | |
145 | if (moves.length == 0) return []; | |
241bf8f2 BA |
146 | return moves.filter(m => { |
147 | const L = this.cmoves.length; //at least 1: init from FEN | |
148 | return !this.oppositeMoves(this.cmoves[L - 1], m); | |
149 | }); | |
150 | } | |
151 | ||
7ba4a5bc | 152 | static GenRandInitFen(randomness) { |
241bf8f2 | 153 | // Add empty cmove: |
964eda04 | 154 | return SuicideRules.GenRandInitFen(randomness) + " -"; |
31e9e40a BA |
155 | } |
156 | ||
2f8dce6a | 157 | getCmoveFen() { |
241bf8f2 | 158 | const L = this.cmoves.length; |
2f8dce6a BA |
159 | return ( |
160 | !this.cmoves[L - 1] | |
161 | ? "-" | |
162 | : ChessRules.CoordsToSquare(this.cmoves[L - 1].start) + | |
163 | ChessRules.CoordsToSquare(this.cmoves[L - 1].end) | |
164 | ); | |
165 | } | |
166 | ||
167 | getFen() { | |
168 | return super.getFen() + " " + this.getCmoveFen(); | |
169 | } | |
170 | ||
171 | getFenForRepeat() { | |
172 | return super.getFenForRepeat() + "_" + this.getCmoveFen(); | |
241bf8f2 BA |
173 | } |
174 | ||
3a2a7b5f BA |
175 | postPlay(move) { |
176 | super.postPlay(move); | |
177 | if (move.vanish.length == 2) { | |
178 | // Was opponent king swapped? | |
179 | if (move.vanish[1].p == V.KING) | |
180 | this.kingPos[this.turn] = [move.appear[1].x, move.appear[1].y]; | |
181 | } | |
241bf8f2 | 182 | this.cmoves.push(this.getCmove(move)); |
241bf8f2 BA |
183 | } |
184 | ||
3a2a7b5f BA |
185 | postUndo(move) { |
186 | super.postUndo(move); | |
187 | if (move.appear.length == 2) { | |
188 | if (move.appear[1].p == V.KING) | |
189 | this.kingPos[move.vanish[1].c] = [move.vanish[1].x, move.vanish[1].y]; | |
190 | } | |
241bf8f2 | 191 | this.cmoves.pop(); |
241bf8f2 BA |
192 | } |
193 | ||
194 | atLeastOneMove() { | |
195 | return true; | |
31e9e40a BA |
196 | } |
197 | ||
198 | getCheckSquares() { | |
199 | return []; | |
200 | } | |
201 | ||
202 | getCurrentScore() { | |
203 | const color = this.turn; | |
204 | const kp = this.kingPos[color]; | |
bb688df5 BA |
205 | if (color == "w" && kp[0] == 0) return "0-1"; |
206 | if (color == "b" && kp[0] == V.size.x - 1) return "1-0"; | |
31e9e40a BA |
207 | // King is not on the opposite edge: game not over |
208 | return "*"; | |
209 | } | |
210 | ||
211 | evalPosition() { | |
212 | // Very simple criterion for now: kings position | |
213 | return this.kingPos["w"][0] + this.kingPos["b"][0]; | |
214 | } | |
71ef1664 BA |
215 | |
216 | getNotation(move) { | |
217 | // Translate final square | |
218 | const finalSquare = V.CoordsToSquare(move.end); | |
219 | ||
220 | const piece = this.getPiece(move.start.x, move.start.y); | |
221 | if (piece == V.PAWN) { | |
222 | // Pawn move | |
223 | let notation = ""; | |
224 | if (move.vanish.length == 2) { | |
225 | // Capture | |
226 | const startColumn = V.CoordToColumn(move.start.y); | |
227 | notation = startColumn + "x" + finalSquare; | |
228 | } | |
229 | else notation = finalSquare; | |
230 | return notation; | |
231 | } | |
232 | // Piece movement | |
233 | return ( | |
234 | piece.toUpperCase() + | |
235 | (move.vanish.length == 2 ? "x" : "") + | |
236 | finalSquare | |
237 | ); | |
238 | } | |
7e8a7ea1 | 239 | |
31e9e40a | 240 | }; |