Refactor models (merge Players in Games), add cursor to correspondance games. Finishe...
[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);
9bd6786b 31 let 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 ];
9bd6786b 46 const oneStep = [V.KNIGHT,V.PAWN].includes(asA); //we don't capture king
6808d7a1
BA
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
e9b736ee
BA
91 canTake(sq1, sq2) {
92 return false; //captures handled separately
93 }
dac39588 94
e9b736ee
BA
95 getPotentialPawnMoves([x, y]) {
96 let moves = super.getPotentialPawnMoves([x, y]);
dac39588 97 // Add "zen" captures
6808d7a1 98 Array.prototype.push.apply(moves, this.findCaptures([x, y]));
dac39588
BA
99 return moves;
100 }
101
6808d7a1 102 getPotentialRookMoves(sq) {
dac39588
BA
103 let noCaptures = this.getSlideNJumpMoves(sq, V.steps[V.ROOK]);
104 let captures = this.findCaptures(sq);
105 return noCaptures.concat(captures);
106 }
107
6808d7a1 108 getPotentialKnightMoves(sq) {
dac39588
BA
109 let noCaptures = this.getSlideNJumpMoves(sq, V.steps[V.KNIGHT], "oneStep");
110 let captures = this.findCaptures(sq);
111 return noCaptures.concat(captures);
112 }
113
6808d7a1 114 getPotentialBishopMoves(sq) {
dac39588
BA
115 let noCaptures = this.getSlideNJumpMoves(sq, V.steps[V.BISHOP]);
116 let captures = this.findCaptures(sq);
117 return noCaptures.concat(captures);
118 }
119
6808d7a1 120 getPotentialQueenMoves(sq) {
dac39588 121 let noCaptures = this.getSlideNJumpMoves(
6808d7a1
BA
122 sq,
123 V.steps[V.ROOK].concat(V.steps[V.BISHOP])
124 );
dac39588
BA
125 let captures = this.findCaptures(sq);
126 return noCaptures.concat(captures);
127 }
128
6808d7a1 129 getPotentialKingMoves(sq) {
dac39588 130 // Initialize with normal moves
6808d7a1
BA
131 let noCaptures = this.getSlideNJumpMoves(
132 sq,
133 V.steps[V.ROOK].concat(V.steps[V.BISHOP]),
134 "oneStep"
135 );
dac39588
BA
136 let captures = this.findCaptures(sq);
137 return noCaptures.concat(captures).concat(this.getCastleMoves(sq));
138 }
139
6808d7a1 140 getNotation(move) {
dac39588 141 // Recognize special moves first
6808d7a1 142 if (move.appear.length == 2) {
dac39588 143 // castle
6808d7a1
BA
144 if (move.end.y < move.start.y) return "0-0-0";
145 return "0-0";
dac39588
BA
146 }
147
148 // Translate initial square (because pieces may fly unusually in this variant!)
149 const initialSquare = V.CoordsToSquare(move.start);
150
151 // Translate final square
152 const finalSquare = V.CoordsToSquare(move.end);
153
154 let notation = "";
155 const piece = this.getPiece(move.start.x, move.start.y);
6808d7a1 156 if (piece == V.PAWN) {
dac39588 157 // pawn move (TODO: enPassant indication)
6808d7a1 158 if (move.vanish.length > 1) {
dac39588
BA
159 // capture
160 notation = initialSquare + "x" + finalSquare;
6808d7a1
BA
161 } //no capture
162 else notation = finalSquare;
163 if (piece != move.appear[0].p)
164 //promotion
dac39588 165 notation += "=" + move.appear[0].p.toUpperCase();
6808d7a1 166 } else {
dac39588
BA
167 // Piece movement
168 notation = piece.toUpperCase();
6808d7a1 169 if (move.vanish.length > 1) notation += initialSquare + "x";
dac39588
BA
170 notation += finalSquare;
171 }
172 return notation;
173 }
174
6808d7a1 175 static get VALUES() {
dac39588 176 return {
6808d7a1
BA
177 p: 1,
178 r: 3,
179 n: 2,
180 b: 2,
181 q: 5,
182 k: 1000
183 };
dac39588 184 }
6808d7a1 185};