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