Fix complete rules of Cwda
[xogo.git] / variants / Avalanche / class.js
1 import ChessRules from "/base_rules.js";
2 import PiPo from "/utils/PiPo.js";
3 import Move from "/utils/Move.js";
4
5 export default class AvalancheRules extends ChessRules {
6
7 static get Options() {
8 return {
9 select: C.Options.select,
10 input: [
11 {
12 label: "Balanced",
13 variable: "balanced",
14 type: "checkbox",
15 defaut: false
16 }
17 ],
18 styles: [
19 "atomic",
20 "cannibal",
21 "capture",
22 "crazyhouse",
23 "cylinder",
24 "dark",
25 "madrasi",
26 "recycle",
27 "rifle",
28 "teleport",
29 "zen"
30 ]
31 };
32 }
33
34 get hasEnpassant() {
35 return false;
36 }
37
38 getPartFen(o) {
39 return Object.assign(
40 {promotion: o.init ? false : this.promotion},
41 super.getPartFen(o)
42 );
43 }
44
45 setOtherVariables(fenParsed) {
46 super.setOtherVariables(fenParsed);
47 this.promotion = (fenParsed.promotion == '1');
48 this.subTurn = 1 - (this.promotion ? 1 : 0);
49 }
50
51 doClick(coords) {
52 const myLastRank = (this.turn == 'w' ? 0 : this.size.x - 1);
53 if (
54 this.subTurn != 0 ||
55 coords.x != myLastRank ||
56 this.getPiece(coords.x, coords.y) != 'p'
57 ) {
58 return null;
59 }
60 let moves = [];
61 this.pawnPromotions.forEach(pr => {
62 moves.push(
63 new Move({
64 vanish: [new PiPo({x: coords.x, y: coords.y, c: this.turn, p: 'p'})],
65 appear: [new PiPo({x: coords.x, y: coords.y, c: this.turn, p: pr})]
66 })
67 );
68 });
69 super.showChoices(moves);
70 }
71
72 canIplay(x, y) {
73 const pieceColor = this.getColor(x, y);
74 return (
75 this.playerColor == this.turn &&
76 (
77 (this.subTurn <= 1 && pieceColor == this.playerColor) ||
78 (
79 this.subTurn == 2 &&
80 pieceColor != this.playerColor &&
81 this.getPiece(x, y) == 'p'
82 )
83 )
84 );
85 }
86
87 getPotentialMovesFrom([x, y]) {
88 if (this.subTurn == 0)
89 return [];
90 if (this.subTurn == 1)
91 // Usual case:
92 return super.getPotentialMovesFrom([x, y]);
93 // subTurn == 2: only allowed to push an opponent's pawn (if possible)
94 const oppPawnShift = (this.turn == 'w' ? 1 : -1);
95 if (
96 this.onBoard(x + oppPawnShift, y) &&
97 this.board[x + oppPawnShift][y] == ""
98 ) {
99 return [this.getBasicMove([x, y], [x + oppPawnShift, y])];
100 }
101 return [];
102 }
103
104 filterValid(moves) {
105 if (this.subTurn != 1)
106 return moves; //self-checks by pawns are allowed
107 return super.filterValid(moves);
108 }
109
110 atLeastOnePawnPush(color) {
111 const pawnShift = (color == 'w' ? -1 : 1);
112 for (let i = 0; i < 8; i++) {
113 for (let j = 0; j < 8; j++) {
114 if (
115 this.board[i][j] != "" &&
116 this.getColor(i, j) == color &&
117 this.getPiece(i, j) == 'p' &&
118 this.board[i + pawnShift][j] == ""
119 ) {
120 return true;
121 }
122 }
123 }
124 return false;
125 }
126
127 tryChangeTurn(move) {
128 const color = this.turn;
129 const oppCol = C.GetOppTurn(color);
130 const incrementTurn = () => {
131 if (this.options["balanced"] && this.movesCount == 0) {
132 // No pawn push on move 1:
133 return true;
134 }
135 this.promotion = (
136 this.subTurn == 2 &&
137 move.end.x == (oppCol == 'w' ? 0 : this.size.x - 1) &&
138 move.vanish[0].p == 'p'
139 );
140 if (this.subTurn == 0) {
141 this.subTurn++;
142 if (!this.atLeastOneMove(color)) {
143 move.result = "1/2"; //avoid re-computation
144 return true;
145 }
146 return false;
147 }
148 if (this.subTurn == 2) {
149 this.subTurn = (this.promotion ? 0 : 1);
150 return true;
151 }
152 // subTurn == 1, usual case
153 const kingCapture = this.searchKingPos(oppCol).length == 0;
154 if (kingCapture)
155 move.result = (color == 'w' ? "1-0" : "0-1");
156 if (kingCapture || !this.atLeastOnePawnPush(oppCol)) {
157 this.subTurn = (this.promotion ? 0 : 1);
158 return true;
159 }
160 // A pawn push is possible: usual case
161 this.subTurn++;
162 return false;
163 };
164 if (incrementTurn()) {
165 this.turn = oppCol;
166 this.movesCount++;
167 }
168 }
169
170 atLeastOneMove(color, lastMove) {
171 if (this.subTurn == 0)
172 return true;
173 return super.atLeastOneMove(color);
174 }
175
176 };