1 import { ChessRules
} from "@/base_rules";
3 export const VariantRules
= class BerolinaRules
extends ChessRules
5 // En-passant after 2-sq jump
6 getEpSquare(moveOrSquare
)
10 if (typeof moveOrSquare
=== "string")
12 const square
= moveOrSquare
;
15 // Enemy pawn initial column must be given too:
17 const epParts
= square
.split(",");
18 res
.push(V
.SquareToCoords(epParts
[0]));
19 res
.push(V
.ColumnToCoord(epParts
[1]));
22 // Argument is a move:
23 const move = moveOrSquare
;
24 const [sx
,ex
,sy
] = [move.start
.x
,move.end
.x
,move.start
.y
];
25 if (this.getPiece(sx
,sy
) == V
.PAWN
&& Math
.abs(sx
- ex
) == 2)
31 y: (move.end
.y
+ sy
)/2
36 return undefined; //default
39 // Special pawns movements
40 getPotentialPawnMoves([x
,y
])
42 const color
= this.turn
;
44 const [sizeX
,sizeY
] = [V
.size
.x
,V
.size
.y
];
45 const shiftX
= (color
== "w" ? -1 : 1);
46 const firstRank
= (color
== 'w' ? sizeX
-1 : 0);
47 const startRank
= (color
== "w" ? sizeX
-2 : 1);
48 const lastRank
= (color
== "w" ? 0 : sizeX
-1);
49 const finalPieces
= x
+ shiftX
== lastRank
50 ? [V
.ROOK
,V
.KNIGHT
,V
.BISHOP
,V
.QUEEN
]
53 // One square diagonally
54 for (let shiftY
of [-1,1])
56 if (this.board
[x
+shiftX
][y
+shiftY
] == V
.EMPTY
)
58 for (let piece
of finalPieces
)
60 moves
.push(this.getBasicMove([x
,y
], [x
+shiftX
,y
+shiftY
],
63 if (x
== startRank
&& y
+2*shiftY
>=0 && y
+2*shiftY
<sizeY
64 && this.board
[x
+2*shiftX
][y
+2*shiftY
] == V
.EMPTY
)
67 moves
.push(this.getBasicMove([x
,y
], [x
+2*shiftX
,y
+2*shiftY
]));
72 if (this.board
[x
+shiftX
][y
] != V
.EMPTY
73 && this.canTake([x
,y
], [x
+shiftX
,y
]))
75 for (let piece
of finalPieces
)
76 moves
.push(this.getBasicMove([x
,y
], [x
+shiftX
,y
], {c:color
,p:piece
}));
80 const Lep
= this.epSquares
.length
;
81 const epSquare
= this.epSquares
[Lep
-1]; //always at least one element
82 if (!!epSquare
&& epSquare
[0].x
== x
+shiftX
&& epSquare
[0].y
== y
83 && Math
.abs(epSquare
[1] - y
) == 1)
85 let enpassantMove
= this.getBasicMove([x
,y
], [x
+shiftX
,y
]);
86 enpassantMove
.vanish
.push({
90 c: this.getColor(x
,epSquare
[1])
92 moves
.push(enpassantMove
);
98 isAttackedByPawn([x
,y
], colors
)
100 for (let c
of colors
)
102 let pawnShift
= (c
=="w" ? 1 : -1);
103 if (x
+pawnShift
>=0 && x
+pawnShift
<V
.size
.x
)
105 if (this.getPiece(x
+pawnShift
,y
)==V
.PAWN
106 && this.getColor(x
+pawnShift
,y
)==c
)
117 const piece
= this.getPiece(move.start
.x
, move.start
.y
);
121 const finalSquare
= V
.CoordsToSquare(move.end
);
123 if (move.vanish
.length
== 2) //capture
124 notation
= "Px" + finalSquare
;
127 // No capture: indicate the initial square for potential ambiguity
128 const startSquare
= V
.CoordsToSquare(move.start
);
129 notation
= startSquare
+ finalSquare
;
131 if (move.appear
[0].p
!= V
.PAWN
) //promotion
132 notation
+= "=" + move.appear
[0].p
.toUpperCase();
135 return super.getNotation(move); //all other pieces are orthodox