a7639aa6fc9ef4dbcf2f19e6e04cdc8910930748
[vchess.git] / client / src / variants / Cylinder.js
1 import { ChessRules, PiPo, Move } from "@/base_rules";
2 import { ArrayFun } from "@/utils/array";
3 import { randInt, shuffle } from "@/utils/alea";
4
5 export const VariantRules = class CylinderRules extends ChessRules {
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
100 isAttackedByPawn([x, y], colors) {
101 for (let c of colors) {
102 let pawnShift = c == "w" ? 1 : -1;
103 if (x + pawnShift >= 0 && x + pawnShift < V.size.x) {
104 for (let i of [-1, 1]) {
105 const nextFile = V.ComputeY(y + i);
106 if (
107 this.getPiece(x + pawnShift, nextFile) == V.PAWN &&
108 this.getColor(x + pawnShift, nextFile) == c
109 ) {
110 return true;
111 }
112 }
113 }
114 }
115 return false;
116 }
117
118 isAttackedBySlideNJump([x, y], colors, piece, steps, oneStep) {
119 for (let step of steps) {
120 let rx = x + step[0],
121 ry = V.ComputeY(y + step[1]);
122 while (V.OnBoard(rx, ry) && this.board[rx][ry] == V.EMPTY && !oneStep) {
123 rx += step[0];
124 ry = V.ComputeY(ry + step[1]);
125 }
126 if (
127 V.OnBoard(rx, ry) &&
128 this.getPiece(rx, ry) === piece &&
129 colors.includes(this.getColor(rx, ry))
130 ) {
131 return true;
132 }
133 }
134 return false;
135 }
136
137 static get SEARCH_DEPTH() {
138 return 2;
139 }
140
141 static get VALUES() {
142 return {
143 p: 1,
144 r: 5,
145 n: 3,
146 b: 4,
147 q: 10,
148 k: 1000
149 };
150 }
151 };