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