Attempt to clarify installation instructions a little
[vchess.git] / client / src / variants / Berolina.js
CommitLineData
0c3fe8a6
BA
1import { ChessRules } from "@/base_rules";
2
32f6285e 3export class BerolinaRules extends ChessRules {
7e8a7ea1 4
c350b3e5
BA
5 getPpath(b) {
6 return (b[1] == 'p' ? "Berolina/" : "") + b;
7 }
8
dac39588 9 // En-passant after 2-sq jump
6808d7a1
BA
10 getEpSquare(moveOrSquare) {
11 if (!moveOrSquare) return undefined;
12 if (typeof moveOrSquare === "string") {
dac39588 13 const square = moveOrSquare;
6808d7a1 14 if (square == "-") return undefined;
dac39588
BA
15 // Enemy pawn initial column must be given too:
16 let res = [];
17 const epParts = square.split(",");
18 res.push(V.SquareToCoords(epParts[0]));
19 res.push(V.ColumnToCoord(epParts[1]));
20 return res;
21 }
22 // Argument is a move:
23 const move = moveOrSquare;
6808d7a1
BA
24 const [sx, ex, sy] = [move.start.x, move.end.x, move.start.y];
25 if (this.getPiece(sx, sy) == V.PAWN && Math.abs(sx - ex) == 2) {
8d1fcc37
BA
26 return [
27 {
28 x: (ex + sx) / 2,
29 y: (move.end.y + sy) / 2
30 },
31 // The arrival column must be remembered, because
32 // potentially two pawns could be candidates to be captured:
33 // one on our left, and one on our right.
34 move.end.y
35 ];
dac39588
BA
36 }
37 return undefined; //default
38 }
375ecdd1 39
8d1fcc37
BA
40 static IsGoodEnpassant(enpassant) {
41 if (enpassant != "-") {
42 const epParts = enpassant.split(",");
43 const epSq = V.SquareToCoords(epParts[0]);
44 if (isNaN(epSq.x) || isNaN(epSq.y) || !V.OnBoard(epSq)) return false;
45 const arrCol = V.ColumnToCoord(epParts[1]);
46 if (isNaN(arrCol) || arrCol < 0 || arrCol >= V.size.y) return false;
47 }
48 return true;
49 }
50
51 getEnpassantFen() {
52 const L = this.epSquares.length;
53 if (!this.epSquares[L - 1]) return "-"; //no en-passant
54 return (
55 V.CoordsToSquare(this.epSquares[L - 1][0]) +
56 "," +
57 V.CoordToColumn(this.epSquares[L - 1][1])
58 );
59 }
60
f52671e5
BA
61 getEnpassantCaptures([x, y], shift) {
62 const Lep = this.epSquares.length;
63 const epSquare = this.epSquares[Lep - 1]; //always at least one element
64 if (
65 !!epSquare &&
66 epSquare[0].x == x + shift &&
67 epSquare[0].y == y
68 ) {
69 let enpassantMove = this.getBasicMove([x, y], [x + shift, y]);
70 enpassantMove.vanish.push({
71 x: x,
72 y: epSquare[1],
73 p: "p",
74 c: this.getColor(x, epSquare[1])
75 });
76 return [enpassantMove];
77 }
78 return [];
79 }
80
dac39588 81 // Special pawns movements
6808d7a1 82 getPotentialPawnMoves([x, y]) {
dac39588
BA
83 const color = this.turn;
84 let moves = [];
6808d7a1
BA
85 const [sizeX, sizeY] = [V.size.x, V.size.y];
86 const shiftX = color == "w" ? -1 : 1;
87 const startRank = color == "w" ? sizeX - 2 : 1;
88 const lastRank = color == "w" ? 0 : sizeX - 1;
89 const finalPieces =
2c5d7b20
BA
90 x + shiftX == lastRank
91 ? [V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN]
92 : [V.PAWN];
375ecdd1 93
dac39588 94 // One square diagonally
6808d7a1
BA
95 for (let shiftY of [-1, 1]) {
96 if (this.board[x + shiftX][y + shiftY] == V.EMPTY) {
97 for (let piece of finalPieces) {
98 moves.push(
99 this.getBasicMove([x, y], [x + shiftX, y + shiftY], {
100 c: color,
101 p: piece
102 })
103 );
dac39588 104 }
6808d7a1 105 if (
32f6285e 106 V.PawnSpecs.twoSquares &&
6808d7a1
BA
107 x == startRank &&
108 y + 2 * shiftY >= 0 &&
109 y + 2 * shiftY < sizeY &&
110 this.board[x + 2 * shiftX][y + 2 * shiftY] == V.EMPTY
111 ) {
dac39588 112 // Two squares jump
6808d7a1
BA
113 moves.push(
114 this.getBasicMove([x, y], [x + 2 * shiftX, y + 2 * shiftY])
115 );
dac39588
BA
116 }
117 }
118 }
119 // Capture
6808d7a1
BA
120 if (
121 this.board[x + shiftX][y] != V.EMPTY &&
122 this.canTake([x, y], [x + shiftX, y])
123 ) {
6e47d367 124 for (let piece of finalPieces) {
6808d7a1
BA
125 moves.push(
126 this.getBasicMove([x, y], [x + shiftX, y], { c: color, p: piece })
127 );
6e47d367 128 }
dac39588 129 }
375ecdd1 130
32f6285e 131 // Next condition so that other variants could inherit from this class
f52671e5
BA
132 if (V.HasEnpassant) {
133 // NOTE: backward en-passant captures are not considered
134 // because no rules define them (for now).
135 Array.prototype.push.apply(
136 moves,
137 this.getEnpassantCaptures([x, y], shiftX)
138 );
dac39588 139 }
375ecdd1 140
dac39588
BA
141 return moves;
142 }
f6dbe8e3 143
68e19a44
BA
144 isAttackedByPawn([x, y], color) {
145 let pawnShift = (color == "w" ? 1 : -1);
59e74176
BA
146 return (
147 x + pawnShift >= 0 && x + pawnShift < V.size.x &&
148 this.getPiece(x + pawnShift, y) == V.PAWN &&
149 this.getColor(x + pawnShift, y) == color
150 );
dac39588 151 }
26c1e3bd 152
32f6285e
BA
153 static get SEARCH_DEPTH() {
154 return 2;
155 }
156
6808d7a1 157 getNotation(move) {
dac39588 158 const piece = this.getPiece(move.start.x, move.start.y);
6808d7a1 159 if (piece == V.PAWN) {
dac39588
BA
160 // Pawn move
161 const finalSquare = V.CoordsToSquare(move.end);
162 let notation = "";
6808d7a1 163 if (move.vanish.length == 2)
6e47d367 164 // Capture
dac39588 165 notation = "Px" + finalSquare;
6808d7a1 166 else {
dac39588
BA
167 // No capture: indicate the initial square for potential ambiguity
168 const startSquare = V.CoordsToSquare(move.start);
169 notation = startSquare + finalSquare;
170 }
6808d7a1 171 if (move.appear[0].p != V.PAWN)
11482348 172 // Promotion
dac39588
BA
173 notation += "=" + move.appear[0].p.toUpperCase();
174 return notation;
175 }
176 return super.getNotation(move); //all other pieces are orthodox
177 }
7e8a7ea1 178
6808d7a1 179};