42b1f4af5f998e940a29e26f1c29283174f4d590
[vchess.git] / client / src / variants / Arena.js
1 import { ChessRules } from "@/base_rules";
2
3 export const VariantRules = class ArenaRules extends ChessRules {
4 static get hasFlags() {
5 return false;
6 }
7
8 static GenRandInitFen() {
9 return ChessRules.GenRandInitFen().replace("w 1111 -", "w -");
10 }
11
12 static InArena(x) {
13 return Math.abs(3.5 - x) <= 1.5;
14 }
15
16 getPotentialMovesFrom([x, y]) {
17 const moves = super.getPotentialMovesFrom([x, y]);
18 // Eliminate moves which neither enter the arena or capture something
19 return moves.filter(m => {
20 const startInArena = V.InArena(m.start.x);
21 const endInArena = V.InArena(m.end.x);
22 return (
23 (startInArena && endInArena && m.vanish.length == 2) ||
24 (!startInArena && endInArena)
25 );
26 });
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
38 if (this.board[x + shiftX][y] == V.EMPTY) {
39 // One square forward
40 moves.push(this.getBasicMove([x, y], [x + shiftX, y]));
41 // Next condition because pawns on 1st rank can generally jump
42 if (
43 x == startRank &&
44 this.board[x + 2 * shiftX][y] == V.EMPTY
45 ) {
46 // Two squares jump
47 moves.push(this.getBasicMove([x, y], [x + 2 * shiftX, y]));
48 }
49 }
50 // Captures: also possible backward
51 for (let shiftY of [-1, 1]) {
52 if (y + shiftY >= 0 && y + shiftY < sizeY) {
53 for (let direction of [-1,1]) {
54 if (
55 this.board[x + direction][y + shiftY] != V.EMPTY &&
56 this.canTake([x, y], [x + direction, y + shiftY])
57 ) {
58 moves.push(this.getBasicMove([x, y], [x + direction, y + shiftY]));
59 }
60 }
61 }
62 }
63
64 // En passant
65 const Lep = this.epSquares.length;
66 const epSquare = this.epSquares[Lep - 1]; //always at least one element
67 if (
68 !!epSquare &&
69 epSquare.x == x + shiftX &&
70 Math.abs(epSquare.y - y) == 1
71 ) {
72 let enpassantMove = this.getBasicMove([x, y], [epSquare.x, epSquare.y]);
73 enpassantMove.vanish.push({
74 x: x,
75 y: epSquare.y,
76 p: "p",
77 c: this.getColor(x, epSquare.y)
78 });
79 moves.push(enpassantMove);
80 }
81
82 return moves;
83 }
84
85 getPotentialQueenMoves(sq) {
86 return this.getSlideNJumpMoves(
87 sq,
88 V.steps[V.ROOK].concat(V.steps[V.BISHOP])
89 ).filter(m => {
90 // Filter out moves longer than 3 squares
91 return Math.max(
92 Math.abs(m.end.x - m.start.x),
93 Math.abs(m.end.y - m.start.y)) <= 3;
94 });
95 }
96
97 getPotentialKingMoves(sq) {
98 return this.getSlideNJumpMoves(
99 sq,
100 V.steps[V.ROOK].concat(V.steps[V.BISHOP])
101 ).filter(m => {
102 // Filter out moves longer than 3 squares
103 return Math.max(
104 Math.abs(m.end.x - m.start.x),
105 Math.abs(m.end.y - m.start.y)) <= 3;
106 });
107 }
108
109 getCheckSquares() {
110 return [];
111 }
112
113 filterValid(moves) {
114 // No check conditions
115 return moves;
116 }
117
118 getCurrentScore() {
119 const color = this.turn;
120 if (!this.atLeastOneMove())
121 // I cannot move anymore
122 return color == "w" ? "0-1" : "1-0";
123 // Win if the opponent has no more pieces left (in the Arena),
124 // (and/)or if he lost both his dukes.
125 let someUnitRemain = false;
126 let atLeastOneDuke = false;
127 let somethingInArena = false;
128 outerLoop: for (let i=0; i<V.size.x; i++) {
129 for (let j=0; j<V.size.y; j++) {
130 if (this.getColor(i,j) == color) {
131 someUnitRemain = true;
132 if (this.movesCount >= 2 && V.InArena(i)) {
133 somethingInArena = true;
134 if (atLeastOneDuke)
135 break outerLoop;
136 }
137 if ([V.QUEEN,V.KING].includes(this.getPiece(i,j))) {
138 atLeastOneDuke = true;
139 if (this.movesCount < 2 || somethingInArena)
140 break outerLoop;
141 }
142 }
143 }
144 }
145 if (
146 !someUnitRemain ||
147 !atLeastOneDuke ||
148 (this.movesCount >= 2 && !somethingInArena)
149 ) {
150 return color == "w" ? "0-1" : "1-0";
151 }
152 return "*";
153 }
154 };