Fix typo
[vchess.git] / client / src / variants / Suicide.js
1 import { ChessRules } from "@/base_rules";
2 import { ArrayFun } from "@/utils/array";
3 import { shuffle } from "@/utils/alea";
4
5 export class SuicideRules extends ChessRules {
6 static get HasFlags() {
7 return false;
8 }
9
10 static get PawnSpecs() {
11 return Object.assign(
12 {},
13 ChessRules.PawnSpecs,
14 { promotions: ChessRules.PawnSpecs.promotions.concat([V.KING]) }
15 );
16 }
17
18 static IsGoodPosition(position) {
19 if (position.length == 0) return false;
20 const rows = position.split("/");
21 if (rows.length != V.size.x) return false;
22 // Just check that at least one piece of each color is there:
23 let pieces = { "w": 0, "b": 0 };
24 for (let row of rows) {
25 let sumElts = 0;
26 for (let i = 0; i < row.length; i++) {
27 const lowerRi = row[i].toLowerCase();
28 if (V.PIECES.includes(lowerRi)) {
29 pieces[row[i] == lowerRi ? "b" : "w"]++;
30 sumElts++;
31 } else {
32 const num = parseInt(row[i], 10);
33 if (isNaN(num)) return false;
34 sumElts += num;
35 }
36 }
37 if (sumElts != V.size.y) return false;
38 }
39 if (Object.values(pieces).some(v => v == 0)) return false;
40 return true;
41 }
42
43 scanKings() {}
44
45 // Trim all non-capturing moves (not the most efficient, but easy)
46 static KeepCaptures(moves) {
47 return moves.filter(m => m.vanish.length == 2);
48 }
49
50 // Stop at the first capture found (if any)
51 atLeastOneCapture() {
52 const color = this.turn;
53 for (let i = 0; i < V.size.x; i++) {
54 for (let j = 0; j < V.size.y; j++) {
55 if (
56 this.board[i][j] != V.EMPTY &&
57 this.getColor(i, j) == color &&
58 this.getPotentialMovesFrom([i, j]).some(m => m.vanish.length == 2)
59 ) {
60 return true;
61 }
62 }
63 }
64 return false;
65 }
66
67 getPossibleMovesFrom(sq) {
68 let moves = this.getPotentialMovesFrom(sq);
69 const captureMoves = V.KeepCaptures(moves);
70 if (captureMoves.length > 0) return captureMoves;
71 if (this.atLeastOneCapture()) return [];
72 return moves;
73 }
74
75 filterValid(moves) {
76 return moves;
77 }
78
79 getAllValidMoves() {
80 const moves = super.getAllValidMoves();
81 if (moves.some(m => m.vanish.length == 2)) return V.KeepCaptures(moves);
82 return moves;
83 }
84
85 atLeastOneMove() {
86 const color = this.turn;
87 for (let i = 0; i < V.size.x; i++) {
88 for (let j = 0; j < V.size.y; j++) {
89 if (
90 this.getColor(i, j) == color &&
91 this.getPotentialMovesFrom([i, j]).length > 0
92 ) {
93 return true;
94 }
95 }
96 }
97 return false;
98 }
99
100 getCheckSquares() {
101 return [];
102 }
103
104 // No variables update because no royal king + no castling
105 prePlay() {}
106 postPlay() {}
107 preUndo() {}
108 postUndo() {}
109
110 getCurrentScore() {
111 if (this.atLeastOneMove()) return "*";
112 // No valid move: the side who cannot move wins
113 return this.turn == "w" ? "1-0" : "0-1";
114 }
115
116 static get VALUES() {
117 return {
118 p: 1,
119 r: 7,
120 n: 3,
121 b: 3,
122 q: 5,
123 k: 5
124 };
125 }
126
127 static get SEARCH_DEPTH() {
128 return 4;
129 }
130
131 evalPosition() {
132 // Less material is better:
133 return -super.evalPosition();
134 }
135
136 static GenRandInitFen(randomness) {
137 if (randomness == 0)
138 return "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w 0 -";
139
140 let pieces = { w: new Array(8), b: new Array(8) };
141 for (let c of ["w", "b"]) {
142 if (c == 'b' && randomness == 1) {
143 pieces['b'] = pieces['w'];
144 break;
145 }
146
147 // Get random squares for every piece, totally freely
148 let positions = shuffle(ArrayFun.range(8));
149 const composition = ['b', 'b', 'r', 'r', 'n', 'n', 'k', 'q'];
150 const rem2 = positions[0] % 2;
151 if (rem2 == positions[1] % 2) {
152 // Fix bishops (on different colors)
153 for (let i=2; i<8; i++) {
154 if (positions[i] % 2 != rem2)
155 [positions[1], positions[i]] = [positions[i], positions[1]];
156 }
157 }
158 for (let i = 0; i < 8; i++) pieces[c][positions[i]] = composition[i];
159 }
160 return (
161 pieces["b"].join("") +
162 "/pppppppp/8/8/8/8/PPPPPPPP/" +
163 pieces["w"].join("").toUpperCase() +
164 // En-passant allowed, but no flags
165 " w 0 -"
166 );
167 }
168 };