Monochrome: fixing attempt
[vchess.git] / client / src / variants / Monochrome.js
CommitLineData
665eed90
BA
1import { ChessRules } from "@/base_rules";
2
3export class MonochromeRules extends ChessRules {
4 static get HasEnpassant() {
5 // Pawns would be on the same side
6 return false;
7 }
8
8ca6042e
BA
9 static get HasFlags() {
10 return false;
11 }
12
ad030c7d
BA
13 static get Lines() {
14 return [ [[4, 0], [4, 8]] ];
15 }
16
5246b49d
BA
17 get showFirstTurn() {
18 return true;
19 }
20
665eed90
BA
21 static IsGoodPosition(position) {
22 if (position.length == 0) return false;
23 const rows = position.split("/");
24 if (rows.length != V.size.x) return false;
25 for (let row of rows) {
26 let sumElts = 0;
27 for (let i = 0; i < row.length; i++) {
28 if (V.PIECES.includes(row[i])) sumElts++;
29 else {
e50a8025 30 const num = parseInt(row[i], 10);
665eed90
BA
31 if (isNaN(num)) return false;
32 sumElts += num;
33 }
34 }
35 if (sumElts != V.size.y) return false;
36 }
37 return true;
38 }
39
40 canIplay(side, [x, y]) {
41 const xBounds = side == 'w' ? [4,7] : [0,3];
42 return this.turn == side && x >= xBounds[0] && x <= xBounds[1];
43 }
44
45 canTake([x1, y1], [x2, y2]) {
46 // Capture in other half-board
47 return ((x1 <= 3 && x2 >= 4) || (x1 >= 4 && x2 <= 3));
48 }
49
50 // Trim all non-capturing moves
51 static KeepCaptures(moves) {
8ca6042e
BA
52 return moves.filter(m => m.vanish.length == 2);
53 }
54
f9ecc499
BA
55 getPotentialKnightMoves(sq) {
56 // Knight becomes knightrider:
57 return this.getSlideNJumpMoves(sq, V.steps[V.KNIGHT]);
58 }
59
60 getPotentialKingMoves(sq) {
61 // King become queen:
62 return (
63 this.getSlideNJumpMoves(sq, V.steps[V.ROOK].concat(V.steps[V.BISHOP]));
64 )
665eed90
BA
65 }
66
67 getAllPotentialMoves() {
68 const xBounds = this.turn == 'w' ? [4,7] : [0,3];
69 let potentialMoves = [];
70 for (let i = xBounds[0]; i <= xBounds[1]; i++) {
71 for (let j = 0; j < V.size.y; j++) {
72 if (this.board[i][j] != V.EMPTY) {
73 Array.prototype.push.apply(
74 potentialMoves,
75 this.getPotentialMovesFrom([i, j])
76 );
77 }
78 }
79 }
80 if (potentialMoves.some(m => m.vanish.length == 2 && m.appear.length == 1))
81 return V.KeepCaptures(potentialMoves);
82 return potentialMoves;
83 }
84
85 atLeastOneMove() {
86 const xBounds = this.turn == 'w' ? [4,7] : [0,3];
87 for (let i = xBounds[0]; i <= xBounds[1]; i++) {
88 for (let j = 0; j < V.size.y; j++) {
89 if (
90 this.board[i][j] != V.EMPTY &&
91 this.getPotentialMovesFrom([i, j]).length > 0
92 ) {
93 return true;
94 }
95 }
96 }
97 return false;
98 }
99
100 // Stop at the first capture found (if any)
101 atLeastOneCapture() {
102 const xBounds = this.turn == 'w' ? [4,7] : [0,3];
103 for (let i = xBounds[0]; i <= xBounds[1]; i++) {
104 for (let j = 0; j < V.size.y; j++) {
105 if (
106 this.board[i][j] != V.EMPTY &&
8ca6042e 107 this.getPotentialMovesFrom([i, j]).some(m => m.vanish.length == 2)
665eed90
BA
108 ) {
109 return true;
110 }
111 }
112 }
113 return false;
114 }
115
116 getPossibleMovesFrom(sq) {
117 let moves = this.getPotentialMovesFrom(sq);
118 const captureMoves = V.KeepCaptures(moves);
119 if (captureMoves.length > 0) return captureMoves;
120 if (this.atLeastOneCapture()) return [];
121 return moves;
122 }
123
124 filterValid(moves) {
125 return moves;
126 }
127
128 isAttacked() {
129 return false;
130 }
131
132 getCheckSquares() {
133 return [];
134 }
135
136 getCurrentScore() {
8ca6042e 137 // Is there anything in opponent's half board?
665eed90
BA
138 const color = V.GetOppCol(this.turn);
139 const xBounds = color == 'w' ? [4,7] : [0,3];
140 let nothingHere = true;
141 outerLoop: for (let i = xBounds[0]; i <= xBounds[1]; i++) {
142 for (let j = 0; j < V.size.y; j++) {
143 if (this.board[i][j] != V.EMPTY) {
144 nothingHere = false;
145 break outerLoop;
146 }
147 }
148 }
149 if (nothingHere) return color == 'w' ? "0-1" : "1-0";
150 if (this.atLeastOneMove()) return '*';
151 return "1/2";
152 }
153
154 static GenRandInitFen(randomness) {
8ca6042e
BA
155 // Remove the en-passant + castle part of the FEN
156 const fen = ChessRules.GenRandInitFen(randomness).slice(0, -6);
665eed90
BA
157 const firstSpace = fen.indexOf(' ');
158 return (
159 fen.substr(0, firstSpace).replace(/[A-Z]/g, (c) => c.toLowerCase()) +
160 fen.substr(firstSpace)
161 );
162 }
163
164 static get SEARCH_DEPTH() {
165 return 4;
166 }
167
168 evalPosition() {
169 let evaluation = 0;
170 for (let i = 0; i < 8; i++) {
171 for (let j = 0; j < V.size.y; j++) {
172 if (this.board[i][j] != V.EMPTY) {
173 const sign = (i <= 3 ? -1 : 1);
174 // I don't think taking pieces' values into account would help
175 evaluation += sign; //* V.VALUES[this.getPiece(i, j)];
176 }
177 }
178 }
179 return evaluation;
180 }
8ca6042e
BA
181
182 getNotation(move) {
183 // Translate initial square (because pieces may fly unusually!)
184 const initialSquare = V.CoordsToSquare(move.start);
185
186 // Translate final square
187 const finalSquare = V.CoordsToSquare(move.end);
188
189 let notation = "";
190 const piece = this.getPiece(move.start.x, move.start.y);
191 if (piece == V.PAWN) {
192 // pawn move (TODO: enPassant indication)
193 if (move.vanish.length == 2) {
194 // capture
195 notation = initialSquare + "x" + finalSquare;
196 }
197 else notation = finalSquare;
198 if (piece != move.appear[0].p)
199 //promotion
200 notation += "=" + move.appear[0].p.toUpperCase();
201 }
202 else {
203 // Piece movement
204 notation = piece.toUpperCase();
205 if (move.vanish.length > 1) notation += initialSquare + "x";
206 notation += finalSquare;
207 }
208 return notation;
209 }
665eed90 210};