Check variants. All OK except Dark (bug), Checkered (missing internal moves stack...
[vchess.git] / client / src / variants / Antiking.js
CommitLineData
0c3fe8a6
BA
1import { ChessRules } from "@/base_rules";
2import { ArrayFun} from "@/utils/array";
3import { randInt } from "@/utils/alea";
4
5export const VariantRules = class AntikingRules extends ChessRules
7d6b0773 6{
7d6b0773
BA
7 static getPpath(b)
8 {
9 return b[1]=='a' ? "Antiking/"+b : b;
10 }
11
12 static get ANTIKING() { return 'a'; }
7931e479 13
2d7194bd
BA
14 static get PIECES()
15 {
7931e479
BA
16 return ChessRules.PIECES.concat([V.ANTIKING]);
17 }
18
2d7194bd 19 setOtherVariables(fen)
46302e64 20 {
2d7194bd 21 super.setOtherVariables(fen);
204e289b 22 this.antikingPos = {'w':[-1,-1], 'b':[-1,-1]};
2d7194bd
BA
23 const rows = V.ParseFen(fen).position.split("/");
24 for (let i=0; i<rows.length; i++)
204e289b 25 {
6037f1d8 26 let k = 0;
2d7194bd 27 for (let j=0; j<rows[i].length; j++)
204e289b 28 {
2d7194bd 29 switch (rows[i].charAt(j))
204e289b
BA
30 {
31 case 'a':
6037f1d8 32 this.antikingPos['b'] = [i,k];
204e289b
BA
33 break;
34 case 'A':
6037f1d8 35 this.antikingPos['w'] = [i,k];
204e289b
BA
36 break;
37 default:
2d7194bd 38 const num = parseInt(rows[i].charAt(j));
204e289b 39 if (!isNaN(num))
6037f1d8 40 k += (num-1);
204e289b 41 }
6037f1d8 42 k++;
204e289b
BA
43 }
44 }
46302e64 45 }
7d6b0773 46
204e289b 47 canTake([x1,y1], [x2,y2])
7d6b0773 48 {
204e289b
BA
49 const piece1 = this.getPiece(x1,y1);
50 const piece2 = this.getPiece(x2,y2);
51 const color1 = this.getColor(x1,y1);
52 const color2 = this.getColor(x2,y2);
a6abf094 53 return piece2 != "a" &&
204e289b 54 ((piece1 != "a" && color1 != color2) || (piece1 == "a" && color1 == color2));
7d6b0773
BA
55 }
56
57 getPotentialMovesFrom([x,y])
58 {
7d6b0773
BA
59 switch (this.getPiece(x,y))
60 {
0b7d99ec 61 case V.ANTIKING:
204e289b 62 return this.getPotentialAntikingMoves([x,y]);
7d6b0773 63 default:
204e289b 64 return super.getPotentialMovesFrom([x,y]);
7d6b0773
BA
65 }
66 }
67
204e289b 68 getPotentialAntikingMoves(sq)
7d6b0773 69 {
a37076f1
BA
70 return this.getSlideNJumpMoves(sq,
71 V.steps[V.ROOK].concat(V.steps[V.BISHOP]), "oneStep");
7d6b0773
BA
72 }
73
46302e64 74 isAttacked(sq, colors)
7d6b0773 75 {
46302e64 76 return (super.isAttacked(sq, colors) || this.isAttackedByAntiking(sq, colors));
7d6b0773
BA
77 }
78
6037f1d8
BA
79 isAttackedByKing([x,y], colors)
80 {
a37076f1 81 if (this.getPiece(x,y) == V.ANTIKING)
6037f1d8 82 return false; //antiking is not attacked by king
a37076f1
BA
83 return this.isAttackedBySlideNJump([x,y], colors, V.KING,
84 V.steps[V.ROOK].concat(V.steps[V.BISHOP]), "oneStep");
6037f1d8
BA
85 }
86
204e289b 87 isAttackedByAntiking([x,y], colors)
7d6b0773 88 {
a734a1a0
BA
89 if ([V.KING,V.ANTIKING].includes(this.getPiece(x,y)))
90 return false; //(anti)king is not attacked by antiking
a37076f1
BA
91 return this.isAttackedBySlideNJump([x,y], colors, V.ANTIKING,
92 V.steps[V.ROOK].concat(V.steps[V.BISHOP]), "oneStep");
7d6b0773
BA
93 }
94
f6dbe8e3 95 underCheck(color)
7d6b0773 96 {
26b8e4f7 97 const oppCol = V.GetOppCol(color);
f6dbe8e3
BA
98 let res = this.isAttacked(this.kingPos[color], [oppCol])
99 || !this.isAttacked(this.antikingPos[color], [oppCol]);
7d6b0773
BA
100 return res;
101 }
102
f6dbe8e3 103 getCheckSquares(color)
7d6b0773 104 {
f6dbe8e3 105 let res = super.getCheckSquares(color);
26b8e4f7 106 if (!this.isAttacked(this.antikingPos[color], [V.GetOppCol(color)]))
f6dbe8e3 107 res.push(JSON.parse(JSON.stringify(this.antikingPos[color])));
7d6b0773
BA
108 return res;
109 }
110
7d6b0773
BA
111 updateVariables(move)
112 {
204e289b 113 super.updateVariables(move);
388e4c40
BA
114 const piece = move.vanish[0].p;
115 const c = move.vanish[0].c;
204e289b 116 // Update antiking position
0b7d99ec 117 if (piece == V.ANTIKING)
204e289b
BA
118 {
119 this.antikingPos[c][0] = move.appear[0].x;
120 this.antikingPos[c][1] = move.appear[0].y;
121 }
7d6b0773
BA
122 }
123
124 unupdateVariables(move)
125 {
204e289b 126 super.unupdateVariables(move);
388e4c40
BA
127 const c = move.vanish[0].c;
128 if (move.vanish[0].p == V.ANTIKING)
204e289b 129 this.antikingPos[c] = [move.start.x, move.start.y];
7d6b0773
BA
130 }
131
0c3fe8a6 132 getCurrentScore()
7d6b0773 133 {
0c3fe8a6
BA
134 if (this.atLeastOneMove()) // game not over
135 return "*";
136
137 const color = this.turn;
26b8e4f7 138 const oppCol = V.GetOppCol(color);
cf130369
BA
139 if (!this.isAttacked(this.kingPos[color], [oppCol])
140 && this.isAttacked(this.antikingPos[color], [oppCol]))
204e289b 141 {
7d6b0773 142 return "1/2";
204e289b 143 }
7d6b0773
BA
144 return color == "w" ? "0-1" : "1-0";
145 }
146
7d6b0773 147 static get VALUES() {
92342261
BA
148 return Object.assign(
149 ChessRules.VALUES,
150 { 'a': 1000 }
151 );
7d6b0773
BA
152 }
153
154 static GenRandInitFen()
155 {
7364deaa
BA
156 let pieces = { "w": new Array(8), "b": new Array(8) };
157 let antikingPos = { "w": -1, "b": -1 };
158 for (let c of ["w","b"])
159 {
0c3fe8a6 160 let positions = ArrayFun.range(8);
7364deaa
BA
161
162 // Get random squares for bishops, but avoid corners; because,
163 // if an antiking blocks a cornered bishop, it can never be checkmated
656b1878 164 let randIndex = 2 * randInt(1,4);
7364deaa 165 const bishop1Pos = positions[randIndex];
656b1878 166 let randIndex_tmp = 2 * randInt(3) + 1;
7364deaa
BA
167 const bishop2Pos = positions[randIndex_tmp];
168 positions.splice(Math.max(randIndex,randIndex_tmp), 1);
169 positions.splice(Math.min(randIndex,randIndex_tmp), 1);
170
656b1878 171 randIndex = randInt(6);
7364deaa
BA
172 const knight1Pos = positions[randIndex];
173 positions.splice(randIndex, 1);
656b1878 174 randIndex = randInt(5);
7364deaa
BA
175 const knight2Pos = positions[randIndex];
176 positions.splice(randIndex, 1);
177
656b1878 178 randIndex = randInt(4);
7364deaa
BA
179 const queenPos = positions[randIndex];
180 positions.splice(randIndex, 1);
181
182 const rook1Pos = positions[0];
183 const kingPos = positions[1];
184 const rook2Pos = positions[2];
185
186 // Random squares for antikings
656b1878 187 antikingPos[c] = randInt(8);
7364deaa
BA
188
189 pieces[c][rook1Pos] = 'r';
190 pieces[c][knight1Pos] = 'n';
191 pieces[c][bishop1Pos] = 'b';
192 pieces[c][queenPos] = 'q';
193 pieces[c][kingPos] = 'k';
194 pieces[c][bishop2Pos] = 'b';
195 pieces[c][knight2Pos] = 'n';
196 pieces[c][rook2Pos] = 'r';
197 }
198 const ranks23_black = "pppppppp/" + (antikingPos["w"]>0?antikingPos["w"]:"")
199 + "A" + (antikingPos["w"]<7?7-antikingPos["w"]:"");
200 const ranks23_white = (antikingPos["b"]>0?antikingPos["b"]:"") + "a"
201 + (antikingPos["b"]<7?7-antikingPos["b"]:"") + "/PPPPPPPP";
c794dbb8 202 return pieces["b"].join("") + "/" + ranks23_black +
7364deaa
BA
203 "/8/8/" +
204 ranks23_white + "/" + pieces["w"].join("").toUpperCase() +
0c3fe8a6 205 " w 0 1111 -";
7d6b0773
BA
206 }
207}