Several small improvements + integrate options + first working draft of Cwda
[vchess.git] / client / src / variants / Maharajah.js
1 import { ChessRules } from "@/base_rules";
2
3 export class MaharajahRules extends ChessRules {
4
5 static get Options() {
6 return {
7 check: [
8 {
9 label: "Random",
10 defaut: false,
11 variable: "random"
12 }
13 ]
14 };
15 }
16
17 static get HasEnpassant() {
18 return false;
19 }
20
21 static get MAHARAJAH() {
22 return 'm';
23 }
24
25 getPpath(b) {
26 return b.charAt(0) == 'w' ? b : "Maharajah/bm";
27 }
28
29 static get PIECES() {
30 return ChessRules.PIECES.concat([V.MAHARAJAH]);
31 }
32
33 static get M_EXTRA_STEPS() {
34 return [
35 // Jumping options:
36 [-2, -2],
37 [-2, 0],
38 [-2, 2],
39 [0, -2],
40 [0, 2],
41 [2, -2],
42 [2, 0],
43 [2, 2]
44 ];
45 }
46
47 static IsGoodPosition(position) {
48 if (position.length == 0) return false;
49 const rows = position.split("/");
50 if (rows.length != V.size.x) return false;
51 let wKingCount = 0;
52 for (let row of rows) {
53 let sumElts = 0;
54 for (let i = 0; i < row.length; i++) {
55 const lowR = row[i].toLowerCase();
56 if (!!lowR.match(/[a-z]/)) {
57 if (row[i] == lowR && row[i] != 'm') return false;
58 if (row[i] == 'K') wKingCount++;
59 if (V.PIECES.includes(lowR)) sumElts++;
60 }
61 else {
62 const num = parseInt(row[i], 10);
63 if (isNaN(num) || num <= 0) return false;
64 sumElts += num;
65 }
66 }
67 if (sumElts != V.size.y) return false;
68 }
69 if (wKingCount != 1) return false;
70 return true;
71 }
72
73 static IsGoodFlags(flags) {
74 // Only white can castle
75 return !!flags.match(/^[a-z]{2,2}$/);
76 }
77
78 scanKings(fen) {
79 // Square of white king only:
80 this.kingPos = { w: [-1, -1], b: [-1, -1] };
81 const fenRows = V.ParseFen(fen).position.split("/");
82 for (let i = 0; i < fenRows.length; i++) {
83 let k = 0; //column index on board
84 for (let j = 0; j < fenRows[i].length; j++) {
85 switch (fenRows[i].charAt(j)) {
86 case "K":
87 this.kingPos["w"] = [i, k];
88 break;
89 default: {
90 const num = parseInt(fenRows[i].charAt(j), 10);
91 if (!isNaN(num)) k += num - 1;
92 }
93 }
94 k++;
95 }
96 }
97 }
98
99 static GenRandInitFen(options) {
100 const baseFen = ChessRules.GenRandInitFen(
101 { randomness: (options.random ? 1 : 0) });
102 return "3mm3/8/" + baseFen.substring(18, 50);
103 }
104
105 getFlagsFen() {
106 return this.castleFlags['w'].map(V.CoordToColumn).join("");
107 }
108
109 setFlags(fenflags) {
110 this.castleFlags = { 'w': [-1, -1] };
111 for (let i = 0; i < 2; i++)
112 this.castleFlags['w'][i] = V.ColumnToCoord(fenflags.charAt(i));
113 }
114
115 getPotentialMovesFrom(sq) {
116 if (this.turn == 'w') return super.getPotentialMovesFrom(sq);
117 return this.getPotentialMaharajahMoves(sq);
118 }
119
120 getPotentialMaharajahMoves(sq) {
121 let moves = super.getPotentialQueenMoves(sq);
122 moves = moves.concat(super.getPotentialKnightMoves(sq));
123 const otherJumpMoves =
124 super.getSlideNJumpMoves(sq, V.M_EXTRA_STEPS, 1)
125 .filter(m =>
126 moves.every(mv => mv.end.x != m.end.x || mv.end.y != m.end.y));
127 return moves.concat(otherJumpMoves);
128 }
129
130 isAttacked() {
131 return false;
132 }
133 getCheckSquares() {
134 return [];
135 }
136 filterValid(moves) {
137 return moves;
138 }
139
140 updateCastleFlags(move, piece) {
141 // Only white can castle:
142 const firstRank = 7;
143 if (piece == V.KING && move.appear[0].c == 'w')
144 this.castleFlags['w'] = [8, 8];
145 else if (
146 move.start.x == firstRank &&
147 this.castleFlags['w'].includes(move.start.y)
148 ) {
149 const flagIdx = (move.start.y == this.castleFlags['w'][0] ? 0 : 1);
150 this.castleFlags['w'][flagIdx] = 8;
151 }
152 else if (
153 move.end.x == firstRank &&
154 this.castleFlags['w'].includes(move.end.y)
155 ) {
156 const flagIdx = (move.end.y == this.castleFlags['w'][0] ? 0 : 1);
157 this.castleFlags['w'][flagIdx] = 8;
158 }
159 }
160
161 postPlay(move) {
162 if (this.turn == 'b') super.postPlay(move);
163 else {
164 // After a black move: white king may have disappeared
165 if (move.vanish.length == 2 && move.vanish[1].p == V.KING)
166 this.kingPos['w'] = [-1, -1];
167 }
168 }
169
170 postUndo(move) {
171 if (this.turn == 'w') super.postUndo(move);
172 else {
173 // After undoing a black move (may have captured king)
174 if (move.vanish.length == 2 && move.vanish[1].p == V.KING)
175 this.kingPos['w'] = [move.end.x, move.end.y];
176 }
177 }
178
179 getCurrentScore() {
180 if (this.turn == 'w' && this.kingPos['w'][0] < 0) return "0-1";
181 if (
182 this.turn == 'b' &&
183 this.board.every(row => row.every(cell => cell.charAt(0) != 'b'))
184 ) {
185 return "1-0";
186 }
187 return "*";
188 }
189
190 static get VALUES() {
191 return Object.assign({ m: 15 }, ChessRules.VALUES);
192 }
193
194 static get SEARCH_DEPTH() {
195 return 2;
196 }
197
198 };