Generalize pawn movements: cleaner and smaller code
[vchess.git] / client / src / variants / Cylinder.js
CommitLineData
71ef1664
BA
1import { ChessRules, PiPo, Move } from "@/base_rules";
2import { ArrayFun } from "@/utils/array";
3import { randInt, shuffle } from "@/utils/alea";
4
32f6285e 5export class CylinderRules extends ChessRules {
71ef1664
BA
6 // Output basically x % 8 (circular board)
7 static ComputeY(y) {
8 let res = y % V.size.y;
9 if (res < 0)
10 res += V.size.y;
11 return res;
12 }
13
14 getSlideNJumpMoves([x, y], steps, oneStep) {
15 let moves = [];
16 outerLoop: for (let step of steps) {
17 let i = x + step[0];
18 let j = V.ComputeY(y + step[1]);
19 while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) {
20 moves.push(this.getBasicMove([x, y], [i, j]));
21 if (oneStep !== undefined) continue outerLoop;
22 i += step[0];
23 j = V.ComputeY(j + step[1]);
24 }
25 if (V.OnBoard(i, j) && this.canTake([x, y], [i, j]))
26 moves.push(this.getBasicMove([x, y], [i, j]));
27 }
28 return moves;
29 }
30
31 getPotentialPawnMoves([x, y]) {
32 const color = this.turn;
33 let moves = [];
34 const [sizeX, sizeY] = [V.size.x, V.size.y];
35 const shiftX = color == "w" ? -1 : 1;
36 const startRank = color == "w" ? sizeX - 2 : 1;
37 const lastRank = color == "w" ? 0 : sizeX - 1;
38
39 const finalPieces =
40 x + shiftX == lastRank
41 ? [V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN]
42 : [V.PAWN];
43 if (this.board[x + shiftX][y] == V.EMPTY) {
44 // One square forward
45 for (let piece of finalPieces) {
46 moves.push(
47 this.getBasicMove([x, y], [x + shiftX, y], {
48 c: color,
49 p: piece
50 })
51 );
52 }
53 if (
54 x == startRank &&
55 this.board[x + 2 * shiftX][y] == V.EMPTY
56 ) {
57 // Two squares jump
58 moves.push(this.getBasicMove([x, y], [x + 2 * shiftX, y]));
59 }
60 }
61 // Captures
62 for (let shiftY of [-1, 1]) {
63 const nextFile = V.ComputeY(y + shiftY);
64 if (
65 this.board[x + shiftX][nextFile] != V.EMPTY &&
66 this.canTake([x, y], [x + shiftX, nextFile])
67 ) {
68 for (let piece of finalPieces) {
69 moves.push(
70 this.getBasicMove([x, y], [x + shiftX, nextFile], {
71 c: color,
72 p: piece
73 })
74 );
75 }
76 }
77 }
78
79 // En passant
80 const Lep = this.epSquares.length;
81 const epSquare = this.epSquares[Lep - 1]; //always at least one element
82 if (
83 !!epSquare &&
84 epSquare.x == x + shiftX &&
85 Math.abs( (epSquare.y - y) % V.size.y ) == 1
86 ) {
87 let enpassantMove = this.getBasicMove([x, y], [epSquare.x, epSquare.y]);
88 enpassantMove.vanish.push({
89 x: x,
90 y: epSquare.y,
91 p: "p",
92 c: this.getColor(x, epSquare.y)
93 });
94 moves.push(enpassantMove);
95 }
96
97 return moves;
98 }
99
68e19a44
BA
100 isAttackedByPawn([x, y], color) {
101 let pawnShift = (color == "w" ? 1 : -1);
102 if (x + pawnShift >= 0 && x + pawnShift < V.size.x) {
103 for (let i of [-1, 1]) {
104 const nextFile = V.ComputeY(y + i);
105 if (
106 this.getPiece(x + pawnShift, nextFile) == V.PAWN &&
107 this.getColor(x + pawnShift, nextFile) == color
108 ) {
109 return true;
71ef1664
BA
110 }
111 }
112 }
113 return false;
114 }
115
68e19a44 116 isAttackedBySlideNJump([x, y], color, piece, steps, oneStep) {
71ef1664
BA
117 for (let step of steps) {
118 let rx = x + step[0],
119 ry = V.ComputeY(y + step[1]);
120 while (V.OnBoard(rx, ry) && this.board[rx][ry] == V.EMPTY && !oneStep) {
121 rx += step[0];
122 ry = V.ComputeY(ry + step[1]);
123 }
124 if (
125 V.OnBoard(rx, ry) &&
68e19a44
BA
126 this.getPiece(rx, ry) == piece &&
127 this.getColor(rx, ry) == color
71ef1664
BA
128 ) {
129 return true;
130 }
131 }
132 return false;
133 }
134
b83a675a
BA
135 static get SEARCH_DEPTH() {
136 return 2;
137 }
138
71ef1664
BA
139 static get VALUES() {
140 return {
141 p: 1,
142 r: 5,
143 n: 3,
144 b: 4,
145 q: 10,
146 k: 1000
147 };
148 }
149};