Add Ambiguous. Fix a few issues with FEN generation / options
[xogo.git] / variants / Benedict / class.js
1 import ChessRules from "/base_rules.js";
2 import PiPo from "/utils/PiPo.js";
3
4 export default class BenedictRules extends ChessRules {
5
6 static get Options() {
7 return {
8 select: C.Options.select,
9 styles: [
10 "balance",
11 "cylinder",
12 "dark",
13 "doublemove",
14 "progressive",
15 "zen"
16 ]
17 };
18 }
19
20 get hasEnpassant() {
21 return false;
22 }
23
24 canTake() {
25 return false;
26 }
27
28 // Find potential captures from a square
29 // follow steps from x,y until something is met.
30 findAttacks([x, y]) {
31 const [color, piece] = [this.getColor(x, y), this.getPiece(x, y)];
32 const oppCol = C.GetOppCol(color);
33 let squares = {};
34 const specs = this.pieces(color, x, y)[piece];
35 const attacks = specs.attack || specs.moves;
36 for (let a of attacks) {
37 outerLoop: for (let step of a.steps) {
38 let [i, j] = [x + step[0], this.getY(y + step[1])];
39 let nbSteps = 1;
40 while (this.onBoard(i, j) && this.board[i][j] == "") {
41 if (a.range <= nbSteps++)
42 continue outerLoop;
43 i += step[0];
44 j = this.getY(j + step[1]);
45 }
46 if (
47 this.onBoard(i, j) && this.getColor(i, j) == oppCol &&
48 (!this.options["zen"] || this.getPieceType(i, j) == "k")
49 ) {
50 squares[C.CoordsToSquare({x: i, y: j})] = true;
51 }
52 }
53 }
54 return Object.keys(squares);
55 }
56
57 postProcessPotentialMoves(moves) {
58 moves.forEach(m => {
59 super.playOnBoard(m);
60 let attacks = this.findAttacks([m.end.x, m.end.y])
61 if (this.options["zen"]) {
62 let endSquares = {};
63 super.findCapturesOn([m.end.x, m.end.y], {zen: true}).forEach(c => {
64 endSquares[C.CoordsToSquare(c.end)] = true;
65 });
66 Array.prototype.push.apply(attacks, Object.keys(endSquares));
67 }
68 super.undoOnBoard(m);
69 m.flips = [];
70 attacks.map(C.SquareToCoords).forEach(a => {
71 m.flips.push({x: a.x, y: a.y});
72 });
73 });
74 return moves;
75 }
76
77 playOnBoard(move) {
78 super.playOnBoard(move);
79 this.flipColorOf(move.flips);
80 }
81 undoOnBoard(move) {
82 super.undoOnBoard(move);
83 this.flipColorOf(move.flips);
84 }
85
86 flipColorOf(flips) {
87 for (let xy of flips) {
88 const newColor = C.GetOppCol(this.getColor(xy.x, xy.y));
89 this.board[xy.x][xy.y] = newColor + this.board[xy.x][xy.y][1];
90 }
91 }
92
93 postPlay(move) {
94 if (this.options["balance"] && [1, 3].includes(this.movesCount)) {
95 // If enemy king is flipped: game over
96 const oppCol = C.GetOppCol(move.vanish[0].c);
97 const oppKingPos = this.searchKingPos(oppCol);
98 if (oppKingPos[0] < 0) {
99 this.turn = oppCol;
100 this.movesCount++;
101 return;
102 }
103 }
104 super.postPlay(move);
105 }
106
107 // Moves cannot flip our king's color, so all are valid
108 filterValid(moves) {
109 return moves;
110 }
111
112 // A king under (regular) check flips color, and the game is over.
113 underCheck() {
114 return false;
115 }
116
117 playVisual(move, r) {
118 super.playVisual(move, r);
119 move.flips.forEach(f => {
120 this.g_pieces[f.x][f.y].classList.toggle("white");
121 this.g_pieces[f.x][f.y].classList.toggle("black");
122 });
123 }
124
125 };