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