Add Alice Chess, fix a few things in base_rules.js
[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 input: [
10 {
11 label: "Cleopatra",
12 variable: "cleopatra",
13 type: "checkbox",
14 defaut: false
15 }
16 ],
17 styles: [
18 "balance",
19 "cylinder",
20 "dark",
21 "doublemove",
22 "progressive",
23 "zen"
24 ]
25 };
26 }
27
28 get hasEnpassant() {
29 return false;
30 }
31
32 canTake() {
33 return false;
34 }
35
36 pieces(color, x, y) {
37 if (!this.options["cleopatra"])
38 return super.pieces(color, x, y);
39 const allSpecs = super.pieces(color, x, y);
40 return Object.assign({},
41 allSpecs,
42 {'q': Object.assign({}, allSpecs['q'], {"class": "cleopatra"})}
43 );
44 }
45
46 // Find potential captures from a square
47 // follow steps from x,y until something is met.
48 findAttacks([x, y]) {
49 const [color, piece] = [this.getColor(x, y), this.getPiece(x, y)];
50 const oppCol = C.GetOppCol(color);
51 let squares = {};
52 const specs = this.pieces(color, x, y)[piece];
53 const attacks = specs.attack || specs.moves;
54 for (let a of attacks) {
55 outerLoop: for (let step of a.steps) {
56 let [i, j] = [x + step[0], this.getY(y + step[1])];
57 let nbSteps = 1;
58 while (this.onBoard(i, j) && this.board[i][j] == "") {
59 if (a.range <= nbSteps++)
60 continue outerLoop;
61 i += step[0];
62 j = this.getY(j + step[1]);
63 }
64 if (
65 this.onBoard(i, j) && this.getColor(i, j) == oppCol &&
66 (!this.options["zen"] || this.getPieceType(i, j) == "k")
67 ) {
68 squares[C.CoordsToSquare({x: i, y: j})] = true;
69 }
70 }
71 }
72 return Object.keys(squares);
73 }
74
75 postProcessPotentialMoves(moves) {
76 moves.forEach(m => {
77 m.flips = [];
78 if (!this.options["cleopatra"] || m.vanish[0].p == 'q') {
79 super.playOnBoard(m);
80 let attacks = this.findAttacks([m.end.x, m.end.y])
81 if (this.options["zen"]) {
82 let endSquares = {};
83 super.findCapturesOn([m.end.x, m.end.y], {zen: true}).forEach(c => {
84 endSquares[C.CoordsToSquare(c.end)] = true;
85 });
86 Array.prototype.push.apply(attacks, Object.keys(endSquares));
87 }
88 super.undoOnBoard(m);
89 attacks.map(C.SquareToCoords).forEach(a => {
90 m.flips.push({x: a.x, y: a.y});
91 });
92 }
93 });
94 return moves;
95 }
96
97 playOnBoard(move) {
98 super.playOnBoard(move);
99 this.flipColorOf(move.flips);
100 }
101 undoOnBoard(move) {
102 super.undoOnBoard(move);
103 this.flipColorOf(move.flips);
104 }
105
106 flipColorOf(flips) {
107 for (let xy of flips) {
108 const newColor = C.GetOppCol(this.getColor(xy.x, xy.y));
109 this.board[xy.x][xy.y] = newColor + this.board[xy.x][xy.y][1];
110 }
111 }
112
113 postPlay(move) {
114 if (this.options["balance"] && [1, 3].includes(this.movesCount)) {
115 // If enemy king is flipped: game over
116 const oppCol = C.GetOppCol(move.vanish[0].c);
117 const oppKingPos = this.searchKingPos(oppCol);
118 if (oppKingPos[0] < 0) {
119 this.turn = oppCol;
120 this.movesCount++;
121 return;
122 }
123 }
124 super.postPlay(move);
125 }
126
127 // Moves cannot flip our king's color, so all are valid
128 filterValid(moves) {
129 return moves;
130 }
131
132 // A king under (regular) check flips color, and the game is over.
133 underCheck() {
134 return false;
135 }
136
137 playVisual(move, r) {
138 super.playVisual(move, r);
139 move.flips.forEach(f => {
140 this.g_pieces[f.x][f.y].classList.toggle("white");
141 this.g_pieces[f.x][f.y].classList.toggle("black");
142 });
143 }
144
145 };