b92be1eec4a9802c5dee95762977e97d410f2ca8
[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
51 for (let shiftY of [-1, 1]) {
52 if (
53 y + shiftY >= 0 &&
54 y + shiftY < sizeY &&
55 this.board[x + shiftX][y + shiftY] != V.EMPTY &&
56 this.canTake([x, y], [x + shiftX, y + shiftY])
57 ) {
58 moves.push(this.getBasicMove([x, y], [x + shiftX, y + shiftY]));
59 }
60 }
61
62 // En passant
63 const Lep = this.epSquares.length;
64 const epSquare = this.epSquares[Lep - 1]; //always at least one element
65 if (
66 !!epSquare &&
67 epSquare.x == x + shiftX &&
68 Math.abs(epSquare.y - y) == 1
69 ) {
70 let enpassantMove = this.getBasicMove([x, y], [epSquare.x, epSquare.y]);
71 enpassantMove.vanish.push({
72 x: x,
73 y: epSquare.y,
74 p: "p",
75 c: this.getColor(x, epSquare.y)
76 });
77 moves.push(enpassantMove);
78 }
79
80 return moves;
81 }
82
83 getPotentialQueenMoves(sq) {
84 return this.getSlideNJumpMoves(
85 sq,
86 V.steps[V.ROOK].concat(V.steps[V.BISHOP])
87 ).filter(m => {
88 // Filter out moves longer than 3 squares
89 return Math.max(
90 Math.abs(m.end.x - m.start.x),
91 Math.abs(m.end.y - m.start.y)) <= 3;
92 });
93 }
94
95 getPotentialKingMoves(sq) {
96 return this.getSlideNJumpMoves(
97 sq,
98 V.steps[V.ROOK].concat(V.steps[V.BISHOP])
99 ).filter(m => {
100 // Filter out moves longer than 3 squares
101 return Math.max(
102 Math.abs(m.end.x - m.start.x),
103 Math.abs(m.end.y - m.start.y)) <= 3;
104 });
105 }
106
107 getCheckSquares() {
108 return [];
109 }
110
111 filterValid(moves) {
112 // No check conditions
113 return moves;
114 }
115
116 getCurrentScore() {
117 const color = this.turn;
118 if (!this.atLeastOneMove())
119 // I cannot move anymore
120 return color == "w" ? "0-1" : "1-0";
121 // Win if the opponent has no more pieces left (in the Arena),
122 // (and/)or if he lost both his dukes.
123 let someUnitRemain = false;
124 let atLeastOneDuke = false;
125 let somethingInArena = false;
126 outerLoop: for (let i=0; i<V.size.x; i++) {
127 for (let j=0; j<V.size.y; j++) {
128 if (this.getColor(i,j) == color) {
129 someUnitRemain = true;
130 if (this.movesCount >= 2 && V.InArena(i)) {
131 somethingInArena = true;
132 if (atLeastOneDuke)
133 break outerLoop;
134 }
135 if ([V.QUEEN,V.KING].includes(this.getPiece(i,j))) {
136 atLeastOneDuke = true;
137 if (this.movesCount < 2 || somethingInArena)
138 break outerLoop;
139 }
140 }
141 }
142 }
143 if (
144 !someUnitRemain ||
145 !atLeastOneDuke ||
146 (this.movesCount >= 2 && !somethingInArena)
147 ) {
148 return color == "w" ? "0-1" : "1-0";
149 }
150 return "*";
151 }
152 };