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