Add Alapo, Crossing, Kingsmaker, Squatter variants
[vchess.git] / client / src / variants / Zen.js
CommitLineData
0c3fe8a6
BA
1import { ChessRules } from "@/base_rules";
2
32f6285e 3export class ZenRules extends ChessRules {
7e8a7ea1 4
ffeaef85
BA
5 getEpSquare(moveOrSquare) {
6 if (!moveOrSquare) return undefined;
7 if (typeof moveOrSquare === "string") {
8 const square = moveOrSquare;
9 if (square == "-") return undefined;
10 return V.SquareToCoords(square);
11 }
12 const move = moveOrSquare;
13 const s = move.start,
14 e = move.end;
15 if (
16 // Exclude captures (of rooks for example)
17 move.vanish.length == 1 &&
18 s.y == e.y &&
19 Math.abs(s.x - e.x) == 2 &&
20 move.appear[0].p == V.PAWN
21 ) {
22 return {
23 x: (s.x + e.x) / 2,
24 y: s.y
25 };
26 }
27 return undefined;
6808d7a1 28 }
dac39588
BA
29
30 // TODO(?): some duplicated code in 2 next functions
6808d7a1 31 getSlideNJumpMoves([x, y], steps, oneStep) {
dac39588 32 let moves = [];
6808d7a1 33 outerLoop: for (let loop = 0; loop < steps.length; loop++) {
dac39588
BA
34 const step = steps[loop];
35 let i = x + step[0];
36 let j = y + step[1];
6808d7a1
BA
37 while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) {
38 moves.push(this.getBasicMove([x, y], [i, j]));
39 if (oneStep) continue outerLoop;
dac39588
BA
40 i += step[0];
41 j += step[1];
42 }
43 // No capture check: handled elsewhere (next method)
44 }
45 return moves;
46 }
47
48 // follow steps from x,y until something is met.
49 // if met piece is opponent and same movement (asA): eat it!
6808d7a1
BA
50 findCaptures_aux([x, y], asA) {
51 const color = this.getColor(x, y);
9bd6786b 52 let moves = [];
6808d7a1
BA
53 const steps =
54 asA != V.PAWN
55 ? asA == V.QUEEN
56 ? V.steps[V.ROOK].concat(V.steps[V.BISHOP])
57 : V.steps[asA]
58 : color == "w"
59 ? [
60 [-1, -1],
61 [-1, 1]
62 ]
63 : [
64 [1, -1],
65 [1, 1]
66 ];
9bd6786b 67 const oneStep = [V.KNIGHT,V.PAWN].includes(asA); //we don't capture king
6808d7a1
BA
68 const lastRank = color == "w" ? 0 : V.size.x - 1;
69 const promotionPieces = [V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN];
8ca6042e 70 const oppCol = V.GetOppCol(color);
6808d7a1 71 outerLoop: for (let loop = 0; loop < steps.length; loop++) {
dac39588
BA
72 const step = steps[loop];
73 let i = x + step[0];
74 let j = y + step[1];
6808d7a1
BA
75 while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) {
76 if (oneStep) continue outerLoop;
dac39588
BA
77 i += step[0];
78 j += step[1];
79 }
6808d7a1
BA
80 if (
81 V.OnBoard(i, j) &&
0f7762c1 82 this.board[i][j] != V.EMPTY &&
8ca6042e 83 this.getColor(i, j) == oppCol &&
6808d7a1
BA
84 this.getPiece(i, j) == asA
85 ) {
dac39588 86 // eat!
6808d7a1 87 if (this.getPiece(x, y) == V.PAWN && i == lastRank) {
dac39588
BA
88 // Special case of promotion:
89 promotionPieces.forEach(p => {
6808d7a1 90 moves.push(this.getBasicMove([x, y], [i, j], { c: color, p: p }));
dac39588 91 });
0f7762c1
BA
92 }
93 else {
dac39588 94 // All other cases
6808d7a1 95 moves.push(this.getBasicMove([x, y], [i, j]));
dac39588
BA
96 }
97 }
98 }
99 return moves;
100 }
101
102 // Find possible captures from a square: look in every direction!
6808d7a1 103 findCaptures(sq) {
dac39588 104 let moves = [];
dac39588
BA
105 Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.PAWN));
106 Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.ROOK));
107 Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.KNIGHT));
108 Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.BISHOP));
109 Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.QUEEN));
dac39588
BA
110 return moves;
111 }
112
e9b736ee
BA
113 canTake(sq1, sq2) {
114 return false; //captures handled separately
115 }
dac39588 116
8ca6042e
BA
117 getPotentialMovesFrom(sq) {
118 return super.getPotentialMovesFrom(sq).concat(this.findCaptures(sq));
dac39588
BA
119 }
120
6808d7a1 121 getNotation(move) {
dac39588 122 // Recognize special moves first
6808d7a1 123 if (move.appear.length == 2) {
dac39588 124 // castle
6808d7a1
BA
125 if (move.end.y < move.start.y) return "0-0-0";
126 return "0-0";
dac39588
BA
127 }
128
2c5d7b20 129 // Translate initial square (because pieces may fly unusually!)
dac39588
BA
130 const initialSquare = V.CoordsToSquare(move.start);
131
132 // Translate final square
133 const finalSquare = V.CoordsToSquare(move.end);
134
135 let notation = "";
136 const piece = this.getPiece(move.start.x, move.start.y);
6808d7a1 137 if (piece == V.PAWN) {
dac39588 138 // pawn move (TODO: enPassant indication)
8ca6042e 139 if (move.vanish.length == 2) {
dac39588
BA
140 // capture
141 notation = initialSquare + "x" + finalSquare;
8ca6042e 142 }
6808d7a1
BA
143 else notation = finalSquare;
144 if (piece != move.appear[0].p)
145 //promotion
dac39588 146 notation += "=" + move.appear[0].p.toUpperCase();
8ca6042e
BA
147 }
148 else {
dac39588
BA
149 // Piece movement
150 notation = piece.toUpperCase();
6808d7a1 151 if (move.vanish.length > 1) notation += initialSquare + "x";
dac39588
BA
152 notation += finalSquare;
153 }
154 return notation;
155 }
156
6808d7a1 157 static get VALUES() {
dac39588 158 return {
6808d7a1
BA
159 p: 1,
160 r: 3,
161 n: 2,
162 b: 2,
163 q: 5,
164 k: 1000
165 };
dac39588 166 }
7e8a7ea1 167
6808d7a1 168};