1 import { ChessRules
} from "@/base_rules";
3 export class Knightrelay1Rules
extends ChessRules
{
4 static get HasEnpassant() {
8 // TODO: IsGoodPosition to check that 2 knights are on the board...
10 getPotentialMovesFrom([x
, y
]) {
11 let moves
= super.getPotentialMovesFrom([x
, y
]);
13 // Expand possible moves if guarded by a knight, and is not a king:
14 const piece
= this.getPiece(x
,y
);
15 if (![V
.KNIGHT
,V
.KING
].includes(piece
)) {
16 const color
= this.turn
;
17 let guardedByKnight
= false;
18 for (const step
of V
.steps
[V
.KNIGHT
]) {
20 V
.OnBoard(x
+step
[0],y
+step
[1]) &&
21 this.getPiece(x
+step
[0],y
+step
[1]) == V
.KNIGHT
&&
22 this.getColor(x
+step
[0],y
+step
[1]) == color
24 guardedByKnight
= true;
28 if (guardedByKnight
) {
29 const lastRank
= (color
== "w" ? 0 : V
.size
.x
- 1);
30 for (const step
of V
.steps
[V
.KNIGHT
]) {
32 V
.OnBoard(x
+step
[0],y
+step
[1]) &&
33 this.getColor(x
+step
[0],y
+step
[1]) != color
&&
34 // Pawns cannot promote by knight-relay
35 (piece
!= V
.PAWN
|| x
+step
[0] != lastRank
)
37 moves
.push(this.getBasicMove([x
,y
], [x
+step
[0],y
+step
[1]]));
43 // Forbid captures of knights (invincible in this variant)
44 return moves
.filter(m
=> {
46 m
.vanish
.length
== 1 ||
47 m
.appear
.length
== 2 ||
48 m
.vanish
[1].p
!= V
.KNIGHT
53 getPotentialKnightMoves(sq
) {
54 // Knights don't capture:
55 return super.getPotentialKnightMoves(sq
).filter(m
=> m
.vanish
.length
== 1);
58 isAttacked(sq
, color
) {
59 if (super.isAttacked(sq
, color
)) return true;
61 // Check if a (non-knight) piece at knight distance
62 // is guarded by a knight (and thus attacking)
63 // --> Except for pawns targetting last rank.
66 // Last rank for me, that is to say oppCol of color:
67 const lastRank
= (color
== 'w' ? V
.size
.x
- 1 : 0);
68 for (const step
of V
.steps
[V
.KNIGHT
]) {
70 V
.OnBoard(x
+step
[0],y
+step
[1]) &&
71 this.getColor(x
+step
[0],y
+step
[1]) == color
73 const piece
= this.getPiece(x
+step
[0],y
+step
[1]);
74 if (piece
!= V
.KNIGHT
&& (piece
!= V
.PAWN
|| x
!= lastRank
)) {
75 for (const step2
of V
.steps
[V
.KNIGHT
]) {
76 const xx
= x
+step
[0]+step2
[0],
77 yy
= y
+step
[1]+step2
[1];
80 this.getColor(xx
,yy
) == color
&&
81 this.getPiece(xx
,yy
) == V
.KNIGHT
93 isAttackedByKnight(sq
, color
) {
94 // Knights don't attack
102 n: 0, //the knight isn't captured - value doesn't matter
109 static get SEARCH_DEPTH() {
114 if (move.appear
.length
== 2 && move.appear
[0].p
== V
.KING
)
116 return move.end
.y
< move.start
.y
? "0-0-0" : "0-0";
118 // Translate final and initial square
119 const initSquare
= V
.CoordsToSquare(move.start
);
120 const finalSquare
= V
.CoordsToSquare(move.end
);
121 const piece
= this.getPiece(move.start
.x
, move.start
.y
);
123 // Since pieces and pawns could move like knight,
124 // indicate start and end squares
126 piece
.toUpperCase() +
128 (move.vanish
.length
> move.appear
.length
? "x" : "") +
133 move.appear
.length
> 0 &&
134 move.appear
[0].p
!= V
.PAWN
137 notation
+= "=" + move.appear
[0].p
.toUpperCase();