Add expert mode
[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);
117 let lastRank = (color == "w" ? 0 : sizeY-1);
118
119 if (x+shift >= 0 && x+shift < sizeX && x+shift != lastRank)
120 {
121 // Normal moves
122 if (this.board[x+shift][y] == V.EMPTY)
123 {
124 moves.push(this.getBasicMove(x, y, x+shift, y));
125 if (x==startRank && this.board[x+2*shift][y] == V.EMPTY)
126 {
127 //two squares jump
128 moves.push(this.getBasicMove(x, y, x+2*shift, y));
129 }
130 }
131 }
132
133 if (x+shift == lastRank)
134 {
135 // Promotion
136 let promotionPieces = [V.ROOK,V.KNIGHT,V.BISHOP,V.QUEEN];
137 promotionPieces.forEach(p => {
138 // Normal move
139 if (this.board[x+shift][y] == V.EMPTY)
140 moves.push(this.getBasicMove(x, y, x+shift, y, p));
141 });
142 }
143
33ee1916 144 // No en passant here
1d184b4c
BA
145
146 // Add "zen" captures
147 Array.prototype.push.apply(moves, this.findCaptures(x, y, color));
148
149 return moves;
150 }
151
152 getPotentialRookMoves(x, y, color)
153 {
154 let noCaptures = this.getSlideNJumpMoves(
155 x, y, color, VariantRules.steps[VariantRules.ROOK]);
156 let captures = this.findCaptures(x, y, color);
157 return noCaptures.concat(captures);
158 }
159
160 getPotentialKnightMoves(x, y, color)
161 {
162 let noCaptures = this.getSlideNJumpMoves(
163 x, y, color, VariantRules.steps[VariantRules.KNIGHT], "oneStep");
164 let captures = this.findCaptures(x, y, color);
165 return noCaptures.concat(captures);
166 }
167
168 getPotentialBishopMoves(x, y, color)
169 {
170 let noCaptures = this.getSlideNJumpMoves(
171 x, y, color, VariantRules.steps[VariantRules.BISHOP]);
172 let captures = this.findCaptures(x, y, color);
173 return noCaptures.concat(captures);
174 }
175
176 getPotentialQueenMoves(x, y, color)
177 {
178 let noCaptures = this.getSlideNJumpMoves(
179 x, y, color, VariantRules.steps[VariantRules.QUEEN]);
180 let captures = this.findCaptures(x, y, color);
181 return noCaptures.concat(captures);
182 }
183
184 getPotentialKingMoves(x, y, c)
185 {
186 // Initialize with normal moves
187 let noCaptures = this.getSlideNJumpMoves(
188 x, y, c, VariantRules.steps[VariantRules.QUEEN], "oneStep");
189 let captures = this.findCaptures(x, y, c);
190
191 let moves = noCaptures
192 .concat(captures)
193 .concat(this.getCastleMoves(x, y, c));
194
195 return moves;
196 }
197
198 getNotation(move)
199 {
200 // Recognize special moves first
201 if (move.appear.length == 2)
202 {
203 // castle
204 if (move.end.y < move.start.y)
205 return "0-0-0";
206 else
207 return "0-0";
208 }
209
210 // Translate initial square (because pieces may fly unusually in this variant!)
211 let initialSquare =
212 String.fromCharCode(97 + move.start.y) + (VariantRules.size[0]-move.start.x);
213
214 // Translate final square
215 let finalSquare =
216 String.fromCharCode(97 + move.end.y) + (VariantRules.size[0]-move.end.x);
217
218 let notation = "";
52b1e238 219 let piece = this.getPiece(move.start.x, move.start.y);
1d184b4c
BA
220 if (piece == VariantRules.PAWN)
221 {
222 // pawn move (TODO: enPassant indication)
223 if (move.vanish.length > 1)
224 {
225 // capture
226 notation = initialSquare + "x" + finalSquare;
227 }
228 else //no capture
229 notation = finalSquare;
230 if (piece != move.appear[0].p) //promotion
231 notation += "=" + move.appear[0].p.toUpperCase();
232 }
233
234 else
235 {
236 // Piece movement
237 notation = piece.toUpperCase();
238 if (move.vanish.length > 1)
239 notation += initialSquare + "x";
240 notation += finalSquare;
241 }
242 return notation;
243 }
244
245 static get VALUES() { //TODO: experimental
246 return {
247 'p': 1,
248 'r': 3,
249 'n': 2,
250 'b': 2,
251 'q': 5,
252 'k': 1000
253 }
254 }
255}