1 import { ChessRules
, PiPo
, Move
} from "@/base_rules";
3 export const VariantRules
= class SuctionRules
extends ChessRules
{
4 static get HasFlags() {
8 setOtherVariables(fen
) {
12 super.setOtherVariables(fen
);
13 // Local stack of "captures"
15 const cmove
= V
.ParseFen(fen
).cmove
;
16 if (cmove
== "-") this.cmoves
.push(null);
19 start: ChessRules
.SquareToCoords(cmove
.substr(0, 2)),
20 end: ChessRules
.SquareToCoords(cmove
.substr(2))
25 static ParseFen(fen
) {
26 return Object
.assign({}, ChessRules
.ParseFen(fen
), {
27 cmove: fen
.split(" ")[4]
31 static IsGoodFen(fen
) {
32 if (!ChessRules
.IsGoodFen(fen
)) return false;
33 const fenParts
= fen
.split(" ");
34 if (fenParts
.length
!= 6) return false;
35 if (fenParts
[5] != "-" && !fenParts
[5].match(/^([a-h][1-8]){2}$/))
41 if (move.vanish
.length
== 2)
42 return { start: move.start
, end: move.end
};
46 getBasicMove([sx
, sy
], [ex
, ey
]) {
47 const startColor
= this.getColor(sx
, sy
);
48 const startPiece
= this.getPiece(sx
, sy
);
68 if (this.board
[ex
][ey
] != V
.EMPTY
) {
69 const endColor
= this.getColor(ex
, ey
);
70 const endPiece
= this.getPiece(ex
, ey
);
91 getPotentialPawnMoves([x
, y
]) {
92 const color
= this.turn
;
94 const [sizeX
, sizeY
] = [V
.size
.x
, V
.size
.y
];
95 const shiftX
= color
== "w" ? -1 : 1;
96 const startRank
= color
== "w" ? sizeX
- 2 : 1;
97 const firstRank
= color
== "w" ? sizeX
- 1 : 0;
99 if (x
+ shiftX
>= 0 && x
+ shiftX
< sizeX
) {
100 // One square forward
101 if (this.board
[x
+ shiftX
][y
] == V
.EMPTY
) {
103 this.getBasicMove([x
, y
], [x
+ shiftX
, y
], {
109 [startRank
,firstRank
].includes(x
) &&
110 this.board
[x
+ 2 * shiftX
][y
] == V
.EMPTY
113 moves
.push(this.getBasicMove([x
, y
], [x
+ 2 * shiftX
, y
]));
117 for (let shiftY
of [-1, 1]) {
120 y
+ shiftY
< sizeY
&&
121 this.board
[x
+ shiftX
][y
+ shiftY
] != V
.EMPTY
&&
122 this.canTake([x
, y
], [x
+ shiftX
, y
+ shiftY
])
125 this.getBasicMove([x
, y
], [x
+ shiftX
, y
+ shiftY
], {
135 const Lep
= this.epSquares
.length
;
136 const epSquare
= this.epSquares
[Lep
- 1]; //always at least one element
139 epSquare
.x
== x
+ shiftX
&&
140 Math
.abs(epSquare
.y
- y
) == 1
142 let enpassantMove
= this.getBasicMove([x
, y
], [epSquare
.x
, epSquare
.y
]);
143 const oppCol
= V
.GetOppCol(color
);
144 enpassantMove
.vanish
.push({
150 enpassantMove
.appear
.push({
156 moves
.push(enpassantMove
);
162 getPotentialKingMoves() {
166 // Does m2 un-do m1 ? (to disallow undoing captures)
167 oppositeMoves(m1
, m2
) {
170 m2
.vanish
.length
== 2 &&
171 m1
.start
.x
== m2
.start
.x
&&
172 m1
.end
.x
== m2
.end
.x
&&
173 m1
.start
.y
== m2
.start
.y
&&
179 if (moves
.length
== 0) return [];
180 const color
= this.turn
;
181 return moves
.filter(m
=> {
182 const L
= this.cmoves
.length
; //at least 1: init from FEN
183 return !this.oppositeMoves(this.cmoves
[L
- 1], m
);
187 static GenRandInitFen(randomness
) {
189 return ChessRules
.GenRandInitFen(randomness
).slice(0, -6) + "- -";
193 const L
= this.cmoves
.length
;
194 const cmoveFen
= !this.cmoves
[L
- 1]
196 : ChessRules
.CoordsToSquare(this.cmoves
[L
- 1].start
) +
197 ChessRules
.CoordsToSquare(this.cmoves
[L
- 1].end
);
198 return super.getFen() + " " + cmoveFen
;
202 super.postPlay(move);
203 if (move.vanish
.length
== 2) {
204 // Was opponent king swapped?
205 if (move.vanish
[1].p
== V
.KING
)
206 this.kingPos
[this.turn
] = [move.appear
[1].x
, move.appear
[1].y
];
208 this.cmoves
.push(this.getCmove(move));
212 super.postUndo(move);
213 if (move.appear
.length
== 2) {
214 if (move.appear
[1].p
== V
.KING
)
215 this.kingPos
[move.vanish
[1].c
] = [move.vanish
[1].x
, move.vanish
[1].y
];
229 const color
= this.turn
;
230 const kp
= this.kingPos
[color
];
231 if (color
== "w" && kp
[0] == 0)
233 if (color
== "b" && kp
[0] == V
.size
.x
- 1)
235 // King is not on the opposite edge: game not over
240 // Very simple criterion for now: kings position
241 return this.kingPos
["w"][0] + this.kingPos
["b"][0];
245 // Translate final square
246 const finalSquare
= V
.CoordsToSquare(move.end
);
248 const piece
= this.getPiece(move.start
.x
, move.start
.y
);
249 if (piece
== V
.PAWN
) {
252 if (move.vanish
.length
== 2) {
254 const startColumn
= V
.CoordToColumn(move.start
.y
);
255 notation
= startColumn
+ "x" + finalSquare
;
257 else notation
= finalSquare
;
262 piece
.toUpperCase() +
263 (move.vanish
.length
== 2 ? "x" : "") +