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