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