Add Monochrome Chess
[vchess.git] / client / src / variants / Monochrome.js
1 import { ChessRules } from "@/base_rules";
2
3 export class MonochromeRules extends ChessRules {
4 static get HasEnpassant() {
5 // Pawns would be on the same side
6 return false;
7 }
8
9 static IsGoodPosition(position) {
10 if (position.length == 0) return false;
11 const rows = position.split("/");
12 if (rows.length != V.size.x) return false;
13 for (let row of rows) {
14 let sumElts = 0;
15 for (let i = 0; i < row.length; i++) {
16 if (V.PIECES.includes(row[i])) sumElts++;
17 else {
18 const num = parseInt(row[i]);
19 if (isNaN(num)) return false;
20 sumElts += num;
21 }
22 }
23 if (sumElts != V.size.y) return false;
24 }
25 return true;
26 }
27
28 canIplay(side, [x, y]) {
29 const xBounds = side == 'w' ? [4,7] : [0,3];
30 return this.turn == side && x >= xBounds[0] && x <= xBounds[1];
31 }
32
33 canTake([x1, y1], [x2, y2]) {
34 // Capture in other half-board
35 return ((x1 <= 3 && x2 >= 4) || (x1 >= 4 && x2 <= 3));
36 }
37
38 // Trim all non-capturing moves
39 static KeepCaptures(moves) {
40 return moves.filter(m => m.vanish.length == 2 && m.appear.length == 1);
41 }
42
43 getAllPotentialMoves() {
44 const xBounds = this.turn == 'w' ? [4,7] : [0,3];
45 let potentialMoves = [];
46 for (let i = xBounds[0]; i <= xBounds[1]; i++) {
47 for (let j = 0; j < V.size.y; j++) {
48 if (this.board[i][j] != V.EMPTY) {
49 Array.prototype.push.apply(
50 potentialMoves,
51 this.getPotentialMovesFrom([i, j])
52 );
53 }
54 }
55 }
56 if (potentialMoves.some(m => m.vanish.length == 2 && m.appear.length == 1))
57 return V.KeepCaptures(potentialMoves);
58 return potentialMoves;
59 }
60
61 atLeastOneMove() {
62 const xBounds = this.turn == 'w' ? [4,7] : [0,3];
63 for (let i = xBounds[0]; i <= xBounds[1]; i++) {
64 for (let j = 0; j < V.size.y; j++) {
65 if (
66 this.board[i][j] != V.EMPTY &&
67 this.getPotentialMovesFrom([i, j]).length > 0
68 ) {
69 return true;
70 }
71 }
72 }
73 return false;
74 }
75
76 // Stop at the first capture found (if any)
77 atLeastOneCapture() {
78 const xBounds = this.turn == 'w' ? [4,7] : [0,3];
79 for (let i = xBounds[0]; i <= xBounds[1]; i++) {
80 for (let j = 0; j < V.size.y; j++) {
81 if (
82 this.board[i][j] != V.EMPTY &&
83 this.getPotentialMovesFrom([i, j]).some(m =>
84 // Warning: discard castle moves
85 m.vanish.length == 2 && m.appear.length == 1)
86 ) {
87 return true;
88 }
89 }
90 }
91 return false;
92 }
93
94 getPossibleMovesFrom(sq) {
95 let moves = this.getPotentialMovesFrom(sq);
96 const captureMoves = V.KeepCaptures(moves);
97 if (captureMoves.length > 0) return captureMoves;
98 if (this.atLeastOneCapture()) return [];
99 return moves;
100 }
101
102 filterValid(moves) {
103 return moves;
104 }
105
106 isAttacked() {
107 return false;
108 }
109
110 getCheckSquares() {
111 return [];
112 }
113
114 getCurrentScore() {
115 // Is there anything in my half board?
116 const color = V.GetOppCol(this.turn);
117 const xBounds = color == 'w' ? [4,7] : [0,3];
118 let nothingHere = true;
119 outerLoop: for (let i = xBounds[0]; i <= xBounds[1]; i++) {
120 for (let j = 0; j < V.size.y; j++) {
121 if (this.board[i][j] != V.EMPTY) {
122 nothingHere = false;
123 break outerLoop;
124 }
125 }
126 }
127 if (nothingHere) return color == 'w' ? "0-1" : "1-0";
128 if (this.atLeastOneMove()) return '*';
129 return "1/2";
130 }
131
132 static GenRandInitFen(randomness) {
133 // Remove the en-passant part of the FEN
134 const fen = ChessRules.GenRandInitFen(randomness).slice(0, -2);
135 const firstSpace = fen.indexOf(' ');
136 return (
137 fen.substr(0, firstSpace).replace(/[A-Z]/g, (c) => c.toLowerCase()) +
138 fen.substr(firstSpace)
139 );
140 }
141
142 static get SEARCH_DEPTH() {
143 return 4;
144 }
145
146 evalPosition() {
147 let evaluation = 0;
148 for (let i = 0; i < 8; i++) {
149 for (let j = 0; j < V.size.y; j++) {
150 if (this.board[i][j] != V.EMPTY) {
151 const sign = (i <= 3 ? -1 : 1);
152 // I don't think taking pieces' values into account would help
153 evaluation += sign; //* V.VALUES[this.getPiece(i, j)];
154 }
155 }
156 }
157 return evaluation;
158 }
159 };