285dd4c864f7661181df11e2e774d08cd46119a5
[vchess.git] / client / src / variants / Arena.js
1 import { ChessRules } from "@/base_rules";
2
3 export class ArenaRules extends ChessRules {
4
5 static get HasFlags() {
6 return false;
7 }
8
9 static get PawnSpecs() {
10 return Object.assign(
11 {},
12 ChessRules.PawnSpecs,
13 { captureBackward: true }
14 );
15 }
16
17 static IsGoodPosition(position) {
18 if (position.length == 0) return false;
19 const rows = position.split("/");
20 if (rows.length != V.size.x) return false;
21 // At most and at least one king or queen per color
22 let royals = { "k": 0, "K": 0, "q": 0, "Q": 0 };
23 for (let row of rows) {
24 let sumElts = 0;
25 for (let i = 0; i < row.length; i++) {
26 if (['K','k','Q','q'].includes(row[i])) royals[row[i]]++;
27 if (V.PIECES.includes(row[i].toLowerCase())) sumElts++;
28 else {
29 const num = parseInt(row[i], 10);
30 if (isNaN(num)) return false;
31 sumElts += num;
32 }
33 }
34 if (sumElts != V.size.y) return false;
35 }
36 if (
37 Object.values(royals).some(v => v >= 2) ||
38 royals['K'] + royals['Q'] == 0 ||
39 royals['k'] + royals['q'] == 0
40 ) {
41 return false;
42 }
43 return true;
44 }
45
46 scanKings() {}
47
48 static GenRandInitFen(randomness) {
49 return ChessRules.GenRandInitFen(randomness).slice(0, -6) + "-";
50 }
51
52 static InArena(x) {
53 return Math.abs(3.5 - x) <= 1.5;
54 }
55
56 getPotentialMovesFrom([x, y]) {
57 const moves = super.getPotentialMovesFrom([x, y]);
58 // Eliminate moves which neither enter the arena or capture something
59 return moves.filter(m => {
60 const startInArena = V.InArena(m.start.x);
61 const endInArena = V.InArena(m.end.x);
62 return (
63 (startInArena && endInArena && m.vanish.length == 2) ||
64 (!startInArena && endInArena)
65 );
66 });
67
68 return moves;
69 }
70
71 getPotentialQueenMoves(sq) {
72 return this.getSlideNJumpMoves(
73 sq,
74 V.steps[V.ROOK].concat(V.steps[V.BISHOP])
75 ).filter(m => {
76 // Filter out moves longer than 3 squares
77 return Math.max(
78 Math.abs(m.end.x - m.start.x),
79 Math.abs(m.end.y - m.start.y)) <= 3;
80 });
81 }
82
83 getPotentialKingMoves(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 getCheckSquares() {
96 return [];
97 }
98
99 filterValid(moves) {
100 // No check conditions
101 return moves;
102 }
103
104 postPlay() {} //no kingPos no castleFlags
105 postUndo() {}
106
107 getCurrentScore() {
108 const color = this.turn;
109 if (!this.atLeastOneMove())
110 // I cannot move anymore
111 return color == "w" ? "0-1" : "1-0";
112 // Win if the opponent has no more pieces left (in the Arena),
113 // (and/)or if he lost both his dukes.
114 let someUnitRemain = false;
115 let atLeastOneDuke = false;
116 let somethingInArena = false;
117 outerLoop: for (let i=0; i<V.size.x; i++) {
118 for (let j=0; j<V.size.y; j++) {
119 if (this.getColor(i,j) == color) {
120 someUnitRemain = true;
121 if (this.movesCount >= 2 && V.InArena(i)) {
122 somethingInArena = true;
123 if (atLeastOneDuke)
124 break outerLoop;
125 }
126 if ([V.QUEEN,V.KING].includes(this.getPiece(i,j))) {
127 atLeastOneDuke = true;
128 if (this.movesCount < 2 || somethingInArena)
129 break outerLoop;
130 }
131 }
132 }
133 }
134 if (
135 !someUnitRemain ||
136 !atLeastOneDuke ||
137 (this.movesCount >= 2 && !somethingInArena)
138 ) {
139 return color == "w" ? "0-1" : "1-0";
140 }
141 return "*";
142 }
143
144 static get SEARCH_DEPTH() {
145 return 4;
146 }
147
148 };