Several small improvements + integrate options + first working draft of Cwda
[vchess.git] / client / src / variants / Antiking1.js
CommitLineData
0c3fe8a6 1import { ChessRules } from "@/base_rules";
32f6285e 2import { BerolinaRules } from "@/variants/Berolina";
6808d7a1 3import { ArrayFun } from "@/utils/array";
0c3fe8a6
BA
4import { randInt } from "@/utils/alea";
5
32f6285e 6export class Antiking1Rules extends BerolinaRules {
7e8a7ea1 7
4313762d
BA
8 static get Options() {
9 return null;
10 }
11
32f6285e
BA
12 static get PawnSpecs() {
13 return Object.assign(
14 {},
15 ChessRules.PawnSpecs,
16 { twoSquares: false }
17 );
c583ef1c
BA
18 }
19
20 static get HasCastle() {
21 return false;
22 }
23
6808d7a1
BA
24 static get ANTIKING() {
25 return "a";
26 }
dac39588 27
6808d7a1 28 static get PIECES() {
dac39588
BA
29 return ChessRules.PIECES.concat([V.ANTIKING]);
30 }
31
241bf8f2
BA
32 getPpath(b) {
33 return b[1] == "a" ? "Antiking/" + b : b;
34 }
35
6f2f9437
BA
36 static IsGoodPosition(position) {
37 if (!ChessRules.IsGoodPosition(position)) return false;
38 const rows = position.split("/");
39 // Check that exactly one antiking of each color is there:
40 let antikings = { 'a': 0, 'A': 0 };
41 for (let row of rows) {
42 for (let i = 0; i < row.length; i++)
43 if (['A','a'].includes(row[i])) antikings[row[i]]++;
44 }
45 if (Object.values(antikings).some(v => v != 1)) return false;
46 return true;
47 }
48
6808d7a1 49 setOtherVariables(fen) {
dac39588 50 super.setOtherVariables(fen);
6808d7a1 51 this.antikingPos = { w: [-1, -1], b: [-1, -1] };
dac39588 52 const rows = V.ParseFen(fen).position.split("/");
6808d7a1 53 for (let i = 0; i < rows.length; i++) {
dac39588 54 let k = 0;
6808d7a1
BA
55 for (let j = 0; j < rows[i].length; j++) {
56 switch (rows[i].charAt(j)) {
57 case "a":
58 this.antikingPos["b"] = [i, k];
dac39588 59 break;
6808d7a1
BA
60 case "A":
61 this.antikingPos["w"] = [i, k];
dac39588 62 break;
6808d7a1 63 default: {
e50a8025 64 const num = parseInt(rows[i].charAt(j), 10);
6808d7a1
BA
65 if (!isNaN(num)) k += num - 1;
66 }
dac39588
BA
67 }
68 k++;
69 }
70 }
71 }
72
c583ef1c
BA
73 // (Anti)King flags at 1 (true) if they can knight-jump
74 setFlags(fenflags) {
75 this.kingFlags = {
76 // King then antiking
77 w: [...Array(2).fill(false)],
78 b: [...Array(2).fill(false)]
79 };
80 for (let c of ["w", "b"]) {
81 for (let i = 0; i < 2; i++)
82 this.kingFlags[c][i] = fenflags.charAt((c == "w" ? 0 : 2) + i) == "1";
83 }
84 }
85
86 aggregateFlags() {
87 return this.kingFlags;
88 }
89
90 disaggregateFlags(flags) {
91 this.kingFlags = flags;
92 }
93
94 getFlagsFen() {
95 // Return kings flags
96 let flags = "";
97 for (let c of ["w", "b"]) {
98 for (let i = 0; i < 2; i++) flags += this.kingFlags[c][i] ? "1" : "0";
99 }
100 return flags;
101 }
102
6808d7a1
BA
103 canTake([x1, y1], [x2, y2]) {
104 const piece1 = this.getPiece(x1, y1);
105 const piece2 = this.getPiece(x2, y2);
106 const color1 = this.getColor(x1, y1);
107 const color2 = this.getColor(x2, y2);
108 return (
109 piece2 != "a" &&
110 ((piece1 != "a" && color1 != color2) ||
111 (piece1 == "a" && color1 == color2))
112 );
dac39588
BA
113 }
114
6808d7a1 115 getPotentialMovesFrom([x, y]) {
c583ef1c
BA
116 let moves = [];
117 let addKnightJumps = false;
118 const piece = this.getPiece(x, y);
119 const color = this.getColor(x, y);
120 if (piece == V.ANTIKING) {
121 moves = this.getPotentialAntikingMoves([x, y]);
122 addKnightJumps = this.kingFlags[color][1];
123 } else {
124 moves = super.getPotentialMovesFrom([x, y]);
125 if (piece == V.KING) addKnightJumps = this.kingFlags[color][0];
126 }
127 if (addKnightJumps) {
128 // Add potential knight jump to (anti)kings
129 const knightJumps = super.getPotentialKnightMoves([x, y]);
130 // Remove captures (TODO: could be done more efficiently...)
131 moves = moves.concat(knightJumps.filter(m => m.vanish.length == 1));
132 }
133 return moves;
134 }
135
6808d7a1 136 getPotentialAntikingMoves(sq) {
c583ef1c 137 // The antiking moves like a king (only captured colors differ)
6808d7a1 138 return this.getSlideNJumpMoves(
4313762d 139 sq, V.steps[V.ROOK].concat(V.steps[V.BISHOP]), 1);
dac39588
BA
140 }
141
68e19a44 142 isAttacked(sq, color) {
6808d7a1 143 return (
68e19a44
BA
144 super.isAttacked(sq, color) ||
145 this.isAttackedByAntiking(sq, color)
6808d7a1 146 );
dac39588
BA
147 }
148
68e19a44
BA
149 isAttackedByKing([x, y], color) {
150 // Antiking is not attacked by king:
151 if (this.getPiece(x, y) == V.ANTIKING) return false;
6808d7a1 152 return this.isAttackedBySlideNJump(
4313762d 153 [x, y], color, V.KING, V.steps[V.ROOK].concat(V.steps[V.BISHOP]), 1);
dac39588
BA
154 }
155
68e19a44
BA
156 isAttackedByAntiking([x, y], color) {
157 // (Anti)King is not attacked by antiking
158 if ([V.KING, V.ANTIKING].includes(this.getPiece(x, y))) return false;
6808d7a1 159 return this.isAttackedBySlideNJump(
4313762d 160 [x, y], color, V.ANTIKING, V.steps[V.ROOK].concat(V.steps[V.BISHOP]), 1);
dac39588
BA
161 }
162
6808d7a1 163 underCheck(color) {
dac39588 164 const oppCol = V.GetOppCol(color);
6808d7a1 165 let res =
68e19a44
BA
166 this.isAttacked(this.kingPos[color], oppCol) ||
167 !this.isAttacked(this.antikingPos[color], oppCol);
dac39588
BA
168 return res;
169 }
170
af34341d
BA
171 getCheckSquares() {
172 const color = this.turn;
c583ef1c
BA
173 let res = [];
174 const oppCol = V.GetOppCol(color);
175 if (this.isAttacked(this.kingPos[color], oppCol))
176 res.push(JSON.parse(JSON.stringify(this.kingPos[color])));
177 if (!this.isAttacked(this.antikingPos[color], oppCol))
dac39588
BA
178 res.push(JSON.parse(JSON.stringify(this.antikingPos[color])));
179 return res;
180 }
181
3a2a7b5f
BA
182 postPlay(move) {
183 super.postPlay(move);
dac39588
BA
184 const piece = move.vanish[0].p;
185 const c = move.vanish[0].c;
c583ef1c 186 // Update antiking position, and kings flags
6808d7a1 187 if (piece == V.ANTIKING) {
dac39588
BA
188 this.antikingPos[c][0] = move.appear[0].x;
189 this.antikingPos[c][1] = move.appear[0].y;
c583ef1c
BA
190 this.kingFlags[c][1] = false;
191 } else if (piece == V.KING) this.kingFlags[c][0] = false;
dac39588
BA
192 }
193
3a2a7b5f
BA
194 postUndo(move) {
195 super.postUndo(move);
dac39588
BA
196 const c = move.vanish[0].c;
197 if (move.vanish[0].p == V.ANTIKING)
198 this.antikingPos[c] = [move.start.x, move.start.y];
199 }
200
dac39588 201 static get VALUES() {
a97bdbda
BA
202 return Object.assign(
203 { a: 1000 },
204 ChessRules.VALUES
205 );
dac39588
BA
206 }
207
c583ef1c
BA
208 static GenRandInitFen() {
209 // Always deterministic setup
210 return "2prbkqA/2p1nnbr/2pppppp/8/8/PPPPPP2/RBNN1P2/aQKBRP2 w 0 1111";
dac39588 211 }
b83a675a
BA
212
213 static get SEARCH_DEPTH() {
214 return 2;
215 }
7e8a7ea1 216
6808d7a1 217};