1 import { ChessRules
} from "@/base_rules";
2 import { ArrayFun
} from "@/utils/array";
3 import { randInt
} from "@/utils/alea";
5 export const VariantRules
= class AntikingRules
extends ChessRules
{
6 static get ANTIKING() {
11 return ChessRules
.PIECES
.concat([V
.ANTIKING
]);
15 return b
[1] == "a" ? "Antiking/" + b : b
;
18 setOtherVariables(fen
) {
19 super.setOtherVariables(fen
);
20 this.antikingPos
= { w: [-1, -1], b: [-1, -1] };
21 const rows
= V
.ParseFen(fen
).position
.split("/");
22 for (let i
= 0; i
< rows
.length
; i
++) {
24 for (let j
= 0; j
< rows
[i
].length
; j
++) {
25 switch (rows
[i
].charAt(j
)) {
27 this.antikingPos
["b"] = [i
, k
];
30 this.antikingPos
["w"] = [i
, k
];
33 const num
= parseInt(rows
[i
].charAt(j
));
34 if (!isNaN(num
)) k
+= num
- 1;
42 canTake([x1
, y1
], [x2
, y2
]) {
43 const piece1
= this.getPiece(x1
, y1
);
44 const piece2
= this.getPiece(x2
, y2
);
45 const color1
= this.getColor(x1
, y1
);
46 const color2
= this.getColor(x2
, y2
);
49 ((piece1
!= "a" && color1
!= color2
) ||
50 (piece1
== "a" && color1
== color2
))
54 getPotentialMovesFrom([x
, y
]) {
55 switch (this.getPiece(x
, y
)) {
57 return this.getPotentialAntikingMoves([x
, y
]);
59 return super.getPotentialMovesFrom([x
, y
]);
63 getPotentialAntikingMoves(sq
) {
64 return this.getSlideNJumpMoves(
66 V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
]),
71 isAttacked(sq
, colors
) {
73 super.isAttacked(sq
, colors
) || this.isAttackedByAntiking(sq
, colors
)
77 isAttackedByKing([x
, y
], colors
) {
78 if (this.getPiece(x
, y
) == V
.ANTIKING
) return false; //antiking is not attacked by king
79 return this.isAttackedBySlideNJump(
83 V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
]),
88 isAttackedByAntiking([x
, y
], colors
) {
89 if ([V
.KING
, V
.ANTIKING
].includes(this.getPiece(x
, y
))) return false; //(anti)king is not attacked by antiking
90 return this.isAttackedBySlideNJump(
94 V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
]),
100 const oppCol
= V
.GetOppCol(color
);
102 this.isAttacked(this.kingPos
[color
], [oppCol
]) ||
103 !this.isAttacked(this.antikingPos
[color
], [oppCol
]);
107 getCheckSquares(color
) {
108 let res
= super.getCheckSquares(color
);
109 if (!this.isAttacked(this.antikingPos
[color
], [V
.GetOppCol(color
)]))
110 res
.push(JSON
.parse(JSON
.stringify(this.antikingPos
[color
])));
114 updateVariables(move) {
115 super.updateVariables(move);
116 const piece
= move.vanish
[0].p
;
117 const c
= move.vanish
[0].c
;
118 // Update antiking position
119 if (piece
== V
.ANTIKING
) {
120 this.antikingPos
[c
][0] = move.appear
[0].x
;
121 this.antikingPos
[c
][1] = move.appear
[0].y
;
125 unupdateVariables(move) {
126 super.unupdateVariables(move);
127 const c
= move.vanish
[0].c
;
128 if (move.vanish
[0].p
== V
.ANTIKING
)
129 this.antikingPos
[c
] = [move.start
.x
, move.start
.y
];
133 if (this.atLeastOneMove())
136 const color
= this.turn
;
137 const oppCol
= V
.GetOppCol(color
);
139 !this.isAttacked(this.kingPos
[color
], [oppCol
]) &&
140 this.isAttacked(this.antikingPos
[color
], [oppCol
])
144 return color
== "w" ? "0-1" : "1-0";
147 static get VALUES() {
148 return Object
.assign(
154 static GenRandInitFen(randomness
) {
156 return "rnbqkbnr/pppppppp/3A4/8/8/3a4/PPPPPPPP/RNBQKBNR w 0 1111 -";
158 let pieces
= { w: new Array(8), b: new Array(8) };
159 let antikingPos
= { w: -1, b: -1 };
160 for (let c
of ["w", "b"]) {
161 if (c
== 'b' && randomness
== 1) {
162 pieces
['b'] = pieces
['w'];
163 antikingPos
['b'] = antikingPos
['w'];
167 let positions
= ArrayFun
.range(8);
169 // Get random squares for bishops, but avoid corners; because,
170 // if an antiking blocks a cornered bishop, it can never be checkmated
171 let randIndex
= 2 * randInt(1, 4);
172 const bishop1Pos
= positions
[randIndex
];
173 let randIndex_tmp
= 2 * randInt(3) + 1;
174 const bishop2Pos
= positions
[randIndex_tmp
];
175 positions
.splice(Math
.max(randIndex
, randIndex_tmp
), 1);
176 positions
.splice(Math
.min(randIndex
, randIndex_tmp
), 1);
178 randIndex
= randInt(6);
179 const knight1Pos
= positions
[randIndex
];
180 positions
.splice(randIndex
, 1);
181 randIndex
= randInt(5);
182 const knight2Pos
= positions
[randIndex
];
183 positions
.splice(randIndex
, 1);
185 randIndex
= randInt(4);
186 const queenPos
= positions
[randIndex
];
187 positions
.splice(randIndex
, 1);
189 const rook1Pos
= positions
[0];
190 const kingPos
= positions
[1];
191 const rook2Pos
= positions
[2];
193 // Random squares for antikings
194 antikingPos
[c
] = randInt(8);
196 pieces
[c
][rook1Pos
] = "r";
197 pieces
[c
][knight1Pos
] = "n";
198 pieces
[c
][bishop1Pos
] = "b";
199 pieces
[c
][queenPos
] = "q";
200 pieces
[c
][kingPos
] = "k";
201 pieces
[c
][bishop2Pos
] = "b";
202 pieces
[c
][knight2Pos
] = "n";
203 pieces
[c
][rook2Pos
] = "r";
205 const ranks23_black
=
207 (antikingPos
["w"] > 0 ? antikingPos
["w"] : "") +
209 (antikingPos
["w"] < 7 ? 7 - antikingPos
["w"] : "");
210 const ranks23_white
=
211 (antikingPos
["b"] > 0 ? antikingPos
["b"] : "") +
213 (antikingPos
["b"] < 7 ? 7 - antikingPos
["b"] : "") +
216 pieces
["b"].join("") +
222 pieces
["w"].join("").toUpperCase() +
227 static get SEARCH_DEPTH() {