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