Commit | Line | Data |
---|---|---|
f31de5e4 | 1 | import ChessRules from "/base_rules.js"; |
462947f0 | 2 | import {ArrayFun} from "/utils/array.js"; |
f31de5e4 BA |
3 | |
4 | export class ApocalypseRules extends ChessRules { | |
5 | ||
6 | static get Options() { | |
7 | return {}; | |
8 | } | |
9 | ||
10 | get pawnPromotions() { | |
11 | return ['n', 'p']; | |
12 | } | |
13 | ||
14 | get size() { | |
15 | return {x: 5, y: 5}; | |
16 | } | |
17 | ||
462947f0 BA |
18 | setOtherVariables(fenParsed) { |
19 | super.setOtherVariables(fenParsed); | |
20 | this.whiteMove = fenParsed.whiteMove != "-" | |
21 | ? JSON.parse(fenParsed.whiteMove) | |
22 | : null; | |
23 | } | |
24 | ||
f31de5e4 BA |
25 | genRandInitBaseFen() { |
26 | return { | |
27 | fen: "npppn/p3p/5/P3P/NPPPN w 0", | |
28 | o: {"flags":"00"} | |
29 | }; | |
30 | } | |
31 | ||
32 | getPartFen(o) { | |
33 | let parts = super.getPartFen(o); | |
34 | parts["whiteMove"] = this.whiteMove || "-"; | |
35 | return parts; | |
36 | } | |
37 | ||
38 | getFlagsFen() { | |
462947f0 | 39 | return Object.values(this.penaltyFlags).join(""); |
f31de5e4 BA |
40 | } |
41 | ||
42 | setFlags(fenflags) { | |
462947f0 BA |
43 | this.penaltyFlags = ArrayFun.toObject( |
44 | ['w', 'b'], [0, 1].map(i => parseInt(fenflags.charAt(i), 10))); | |
f31de5e4 BA |
45 | } |
46 | ||
f31de5e4 | 47 | getWhitemoveFen() { |
462947f0 | 48 | return !this.whiteMove ? "-" : JSON.stringify(this.whiteMove); |
f31de5e4 BA |
49 | } |
50 | ||
462947f0 BA |
51 | // Allow pawns to move diagonally and capture vertically, |
52 | // because some of these moves might be valid a posteriori. | |
53 | // They will be flagged as 'illegal' in a first time, however. | |
f31de5e4 BA |
54 | pieces(color, x, y) { |
55 | const pawnShift = (color == "w" ? -1 : 1); | |
56 | return { | |
57 | 'p': { | |
58 | "class": "pawn", | |
59 | moves: [ | |
60 | { | |
61 | steps: [[pawnShift, 0], [pawnShift, -1], [pawnShift, 1]], | |
62 | range: 1 | |
63 | } | |
64 | ], | |
65 | }, | |
66 | 'n': super.pieces(color, x, y)['n'] | |
67 | }; | |
68 | } | |
69 | ||
462947f0 BA |
70 | // Allow self-captures, because they might be valid |
71 | // if opponent takes on the same square (luck...) | |
f31de5e4 BA |
72 | canTake() { |
73 | return true; | |
74 | } | |
75 | ||
76 | getPotentialMovesFrom([x, y]) { | |
77 | let moves = []; | |
78 | if (this.subTurn == 2) { | |
79 | const start = this.moveStack[0].end; | |
80 | if (x == start.x && y == start.y) { | |
81 | // Move the pawn to any empty square not on last rank (== x) | |
82 | for (let i=0; i<this.size.x; i++) { | |
83 | if (i == x) | |
84 | continue; | |
85 | for (let j=0; j<this.size.y; j++) { | |
86 | if (this.board[i][j] == "") | |
87 | moves.push(this.getBasicMove([x, y], [i, j])); | |
88 | } | |
89 | } | |
90 | } | |
91 | } | |
92 | else { | |
93 | moves = super.getPotentialMovesFrom([x, y]) | |
94 | // Flag a priori illegal moves | |
95 | moves.forEach(m => { | |
96 | if ( | |
97 | // Self-capture test: | |
98 | (m.vanish.length == 2 && m.vanish[1].c == m.vanish[0].c) || | |
99 | // Pawn going diagonaly to empty square, or vertically to occupied | |
100 | ( | |
101 | m.vanish[0].p == 'p' && | |
102 | ( | |
103 | (m.end.y == m.start.y && m.vanish.length == 2) || | |
104 | (m.end.y != m.start.y && m.vanish.length == 1) | |
105 | ) | |
106 | ) | |
107 | ) { | |
108 | m.illegal = true; | |
109 | } | |
110 | }); | |
111 | } | |
112 | return moves; | |
113 | } | |
114 | ||
115 | filterValid(moves) { | |
116 | // No checks: | |
117 | return moves; | |
118 | } | |
119 | ||
462947f0 BA |
120 | |
121 | //TODO: from here | |
122 | ||
f31de5e4 BA |
123 | // White and black (partial) moves were played: merge |
124 | // + animate both at the same time ! | |
125 | resolveSynchroneMove(move) { | |
126 | // TODO | |
127 | } | |
128 | ||
129 | play(move) { | |
462947f0 | 130 | if (this.subTurn...) //TODO: detect (mark?) if pawn move arriving on last rank (=> subTurn++) |
f31de5e4 BA |
131 | this.turn = V.GetOppCol(this.turn); |
132 | this.movesCount++; | |
133 | this.postPlay(move); | |
134 | } | |
135 | ||
136 | postPlay(move) { | |
137 | if (pawn promotion into pawn) { | |
138 | this.curMove move; //TODO: animate both move at same time + effects AFTER ! | |
139 | this.subTurn = 2 | |
140 | } | |
141 | else if (this.turn == 'b') | |
142 | // NOTE: whiteMove is used read-only, so no need to copy | |
143 | this.whiteMove = move; | |
144 | } | |
145 | else { | |
146 | // A full turn just ended: | |
462947f0 | 147 | const [wMove, bMove] = this.resolveSynchroneMove(move); |
f31de5e4 BA |
148 | V.PlayOnBoard(this.board, smove); //----> ici : animate both ! |
149 | this.whiteMove = null; | |
150 | } | |
151 | } | |
152 | ||
462947f0 BA |
153 | //until here |
154 | ||
155 | ||
156 | atLeastOneLegalMove(color) { | |
157 | for (let i=0; i<this.size.x; i++) { | |
158 | for (let j=0; j<this.size.y; j++) { | |
159 | if ( | |
160 | this.board[i][j] != "" && | |
161 | this.getColor(i, j) == color && | |
162 | this.getPotentialMoves([i, j]).some(m => !m.illegal) | |
163 | ) { | |
164 | return true; | |
165 | } | |
166 | } | |
167 | } | |
168 | return false; | |
f31de5e4 BA |
169 | } |
170 | ||
171 | getCurrentScore() { | |
462947f0 BA |
172 | if (this.turn == 'b') { |
173 | // Turn (white + black) not over yet. | |
174 | // Could be stalemate if black cannot move (legally): | |
175 | if (!this.atLeastOneLegalMove('b')) | |
176 | return "1/2"; | |
f31de5e4 | 177 | return "*"; |
462947f0 | 178 | } |
f31de5e4 BA |
179 | // Count footmen: if a side has none, it loses |
180 | let fmCount = { 'w': 0, 'b': 0 }; | |
181 | for (let i=0; i<5; i++) { | |
182 | for (let j=0; j<5; j++) { | |
183 | if (this.board[i][j] != V.EMPTY && this.getPiece(i, j) == V.PAWN) | |
184 | fmCount[this.getColor(i, j)]++; | |
185 | } | |
186 | } | |
187 | if (Object.values(fmCount).some(v => v == 0)) { | |
188 | if (fmCount['w'] == 0 && fmCount['b'] == 0) | |
189 | // Everyone died | |
190 | return "1/2"; | |
191 | if (fmCount['w'] == 0) return "0-1"; | |
192 | return "1-0"; //fmCount['b'] == 0 | |
193 | } | |
194 | // Check penaltyFlags: if a side has 2 or more, it loses | |
195 | if (Object.values(this.penaltyFlags).every(v => v == 2)) return "1/2"; | |
196 | if (this.penaltyFlags['w'] == 2) return "0-1"; | |
197 | if (this.penaltyFlags['b'] == 2) return "1-0"; | |
198 | if (!this.atLeastOneLegalMove('w') || !this.atLeastOneLegalMove('b')) | |
199 | // Stalemate (should be very rare) | |
200 | return "1/2"; | |
201 | return "*"; | |
202 | } | |
203 | ||
204 | }; |