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