Fix Chakart (promotions + queen visibility)
[vchess.git] / client / src / variants / Zen.js
CommitLineData
0c3fe8a6
BA
1import { ChessRules } from "@/base_rules";
2
32f6285e 3export class ZenRules extends ChessRules {
ffeaef85
BA
4 getEpSquare(moveOrSquare) {
5 if (!moveOrSquare) return undefined;
6 if (typeof moveOrSquare === "string") {
7 const square = moveOrSquare;
8 if (square == "-") return undefined;
9 return V.SquareToCoords(square);
10 }
11 const move = moveOrSquare;
12 const s = move.start,
13 e = move.end;
14 if (
15 // Exclude captures (of rooks for example)
16 move.vanish.length == 1 &&
17 s.y == e.y &&
18 Math.abs(s.x - e.x) == 2 &&
19 move.appear[0].p == V.PAWN
20 ) {
21 return {
22 x: (s.x + e.x) / 2,
23 y: s.y
24 };
25 }
26 return undefined;
6808d7a1 27 }
dac39588
BA
28
29 // TODO(?): some duplicated code in 2 next functions
6808d7a1 30 getSlideNJumpMoves([x, y], steps, oneStep) {
dac39588 31 let moves = [];
6808d7a1 32 outerLoop: for (let loop = 0; loop < steps.length; loop++) {
dac39588
BA
33 const step = steps[loop];
34 let i = x + step[0];
35 let j = y + step[1];
6808d7a1
BA
36 while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) {
37 moves.push(this.getBasicMove([x, y], [i, j]));
38 if (oneStep) continue outerLoop;
dac39588
BA
39 i += step[0];
40 j += step[1];
41 }
42 // No capture check: handled elsewhere (next method)
43 }
44 return moves;
45 }
46
47 // follow steps from x,y until something is met.
48 // if met piece is opponent and same movement (asA): eat it!
6808d7a1
BA
49 findCaptures_aux([x, y], asA) {
50 const color = this.getColor(x, y);
9bd6786b 51 let moves = [];
6808d7a1
BA
52 const steps =
53 asA != V.PAWN
54 ? asA == V.QUEEN
55 ? V.steps[V.ROOK].concat(V.steps[V.BISHOP])
56 : V.steps[asA]
57 : color == "w"
58 ? [
59 [-1, -1],
60 [-1, 1]
61 ]
62 : [
63 [1, -1],
64 [1, 1]
65 ];
9bd6786b 66 const oneStep = [V.KNIGHT,V.PAWN].includes(asA); //we don't capture king
6808d7a1
BA
67 const lastRank = color == "w" ? 0 : V.size.x - 1;
68 const promotionPieces = [V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN];
69 outerLoop: for (let loop = 0; loop < steps.length; loop++) {
dac39588
BA
70 const step = steps[loop];
71 let i = x + step[0];
72 let j = y + step[1];
6808d7a1
BA
73 while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) {
74 if (oneStep) continue outerLoop;
dac39588
BA
75 i += step[0];
76 j += step[1];
77 }
6808d7a1
BA
78 if (
79 V.OnBoard(i, j) &&
80 this.getColor(i, j) == V.GetOppCol(color) &&
81 this.getPiece(i, j) == asA
82 ) {
dac39588 83 // eat!
6808d7a1 84 if (this.getPiece(x, y) == V.PAWN && i == lastRank) {
dac39588
BA
85 // Special case of promotion:
86 promotionPieces.forEach(p => {
6808d7a1 87 moves.push(this.getBasicMove([x, y], [i, j], { c: color, p: p }));
dac39588 88 });
6808d7a1 89 } else {
dac39588 90 // All other cases
6808d7a1 91 moves.push(this.getBasicMove([x, y], [i, j]));
dac39588
BA
92 }
93 }
94 }
95 return moves;
96 }
97
98 // Find possible captures from a square: look in every direction!
6808d7a1 99 findCaptures(sq) {
dac39588
BA
100 let moves = [];
101
102 Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.PAWN));
103 Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.ROOK));
104 Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.KNIGHT));
105 Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.BISHOP));
106 Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.QUEEN));
107
108 return moves;
109 }
110
e9b736ee
BA
111 canTake(sq1, sq2) {
112 return false; //captures handled separately
113 }
dac39588 114
e9b736ee
BA
115 getPotentialPawnMoves([x, y]) {
116 let moves = super.getPotentialPawnMoves([x, y]);
dac39588 117 // Add "zen" captures
6808d7a1 118 Array.prototype.push.apply(moves, this.findCaptures([x, y]));
dac39588
BA
119 return moves;
120 }
121
6808d7a1 122 getPotentialRookMoves(sq) {
dac39588
BA
123 let noCaptures = this.getSlideNJumpMoves(sq, V.steps[V.ROOK]);
124 let captures = this.findCaptures(sq);
125 return noCaptures.concat(captures);
126 }
127
6808d7a1 128 getPotentialKnightMoves(sq) {
dac39588
BA
129 let noCaptures = this.getSlideNJumpMoves(sq, V.steps[V.KNIGHT], "oneStep");
130 let captures = this.findCaptures(sq);
131 return noCaptures.concat(captures);
132 }
133
6808d7a1 134 getPotentialBishopMoves(sq) {
dac39588
BA
135 let noCaptures = this.getSlideNJumpMoves(sq, V.steps[V.BISHOP]);
136 let captures = this.findCaptures(sq);
137 return noCaptures.concat(captures);
138 }
139
6808d7a1 140 getPotentialQueenMoves(sq) {
dac39588 141 let noCaptures = this.getSlideNJumpMoves(
6808d7a1
BA
142 sq,
143 V.steps[V.ROOK].concat(V.steps[V.BISHOP])
144 );
dac39588
BA
145 let captures = this.findCaptures(sq);
146 return noCaptures.concat(captures);
147 }
148
6808d7a1 149 getPotentialKingMoves(sq) {
dac39588 150 // Initialize with normal moves
6808d7a1
BA
151 let noCaptures = this.getSlideNJumpMoves(
152 sq,
153 V.steps[V.ROOK].concat(V.steps[V.BISHOP]),
154 "oneStep"
155 );
dac39588
BA
156 let captures = this.findCaptures(sq);
157 return noCaptures.concat(captures).concat(this.getCastleMoves(sq));
158 }
159
6808d7a1 160 getNotation(move) {
dac39588 161 // Recognize special moves first
6808d7a1 162 if (move.appear.length == 2) {
dac39588 163 // castle
6808d7a1
BA
164 if (move.end.y < move.start.y) return "0-0-0";
165 return "0-0";
dac39588
BA
166 }
167
2c5d7b20 168 // Translate initial square (because pieces may fly unusually!)
dac39588
BA
169 const initialSquare = V.CoordsToSquare(move.start);
170
171 // Translate final square
172 const finalSquare = V.CoordsToSquare(move.end);
173
174 let notation = "";
175 const piece = this.getPiece(move.start.x, move.start.y);
6808d7a1 176 if (piece == V.PAWN) {
dac39588 177 // pawn move (TODO: enPassant indication)
6808d7a1 178 if (move.vanish.length > 1) {
dac39588
BA
179 // capture
180 notation = initialSquare + "x" + finalSquare;
6808d7a1
BA
181 } //no capture
182 else notation = finalSquare;
183 if (piece != move.appear[0].p)
184 //promotion
dac39588 185 notation += "=" + move.appear[0].p.toUpperCase();
6808d7a1 186 } else {
dac39588
BA
187 // Piece movement
188 notation = piece.toUpperCase();
6808d7a1 189 if (move.vanish.length > 1) notation += initialSquare + "x";
dac39588
BA
190 notation += finalSquare;
191 }
192 return notation;
193 }
194
6808d7a1 195 static get VALUES() {
dac39588 196 return {
6808d7a1
BA
197 p: 1,
198 r: 3,
199 n: 2,
200 b: 2,
201 q: 5,
202 k: 1000
203 };
dac39588 204 }
6808d7a1 205};