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