Commit | Line | Data |
---|---|---|
2a0672a9 BA |
1 | import { ChessRules } from "@/base_rules"; |
2 | import { randInt } from "@/utils/alea"; | |
3 | ||
39867b70 BA |
4 | export class Refusal1Rules extends ChessRules { |
5 | ||
6 | static get HasFlags() { | |
7 | return false; | |
8 | } | |
2a0672a9 BA |
9 | |
10 | static IsGoodFen(fen) { | |
11 | if (!ChessRules.IsGoodFen(fen)) return false; | |
12 | if (!V.ParseFen(fen).lastMove) return false; | |
13 | return true; | |
14 | } | |
15 | ||
16 | static ParseFen(fen) { | |
17 | return Object.assign( | |
39867b70 | 18 | { lastMove: fen.split(" ")[4] }, |
2a0672a9 BA |
19 | ChessRules.ParseFen(fen) |
20 | ); | |
21 | } | |
22 | ||
23 | getFen() { | |
24 | const L = this.lastMove.length; | |
25 | const lm = this.lastMove[L-1]; | |
26 | return super.getFen() + " " + JSON.stringify(lm); | |
27 | } | |
28 | ||
29 | // NOTE: with this variant's special rule, | |
30 | // some extra repetitions could be detected... TODO (...) | |
31 | ||
32 | static GenRandInitFen(randomness) { | |
39867b70 | 33 | return ChessRules.GenRandInitFen(randomness).slice(0, -6) + "- null"; |
2a0672a9 BA |
34 | } |
35 | ||
36 | setOtherVariables(fen) { | |
37 | super.setOtherVariables(fen); | |
38 | this.lastMove = [JSON.parse(V.ParseFen(fen).lastMove)]; //may be null | |
39 | } | |
40 | ||
41 | canIplay(side, [x, y]) { | |
42 | if (super.canIplay(side, [x, y])) return true; | |
43 | if (this.turn != side) return false; | |
44 | // Check if playing last move, reversed: | |
45 | const L = this.lastMove.length; | |
46 | const lm = this.lastMove[L-1]; | |
47 | return (!!lm && !lm.noRef && x == lm.end.x && y == lm.end.y); | |
48 | } | |
49 | ||
50 | getPotentialMovesFrom([x, y]) { | |
51 | if (this.getColor(x, y) != this.turn) { | |
52 | const L = this.lastMove.length; | |
53 | const lm = this.lastMove[L-1]; | |
2da551a3 BA |
54 | const beforeLastRank = (this.turn == 'w' ? 1 : 6); |
55 | if ( | |
56 | !!lm && !lm.noRef && x == lm.end.x && y == lm.end.y && | |
57 | (this.getPiece(x, y) != V.PAWN || x != beforeLastRank) | |
58 | ) { | |
2a0672a9 BA |
59 | let revLm = JSON.parse(JSON.stringify(lm)); |
60 | let tmp = revLm.appear; | |
61 | revLm.appear = revLm.vanish; | |
62 | revLm.vanish = tmp; | |
63 | tmp = revLm.start; | |
64 | revLm.start = revLm.end; | |
65 | revLm.end = tmp; | |
66 | return [revLm]; | |
67 | } | |
68 | return []; | |
69 | } | |
70 | return super.getPotentialMovesFrom([x, y]); | |
71 | } | |
72 | ||
2a0672a9 BA |
73 | filterValid(moves) { |
74 | if (moves.length == 0) return []; | |
75 | const color = this.turn; | |
76 | const L = this.lastMove.length; | |
77 | const lm = this.lastMove[L-1]; | |
78 | return moves.filter(m => { | |
79 | if ( | |
80 | !!lm && !!lm.refusal && | |
81 | m.start.x == lm.end.x && m.start.y == lm.end.y && | |
2da551a3 BA |
82 | m.end.x == lm.start.x && m.end.y == lm.start.y && |
83 | (m.vanish[0].p != V.PAWN || m.appear[0].p == lm.vanish[0].p) | |
2a0672a9 BA |
84 | ) { |
85 | return false; | |
86 | } | |
87 | // NOTE: not using this.play()/undo() ==> infinite loop | |
88 | V.PlayOnBoard(this.board, m); | |
89 | if (m.appear[0].p == V.KING) | |
90 | this.kingPos[m.appear[0].c] = [m.appear[0].x, m.appear[0].y]; | |
91 | const res = !this.underCheck(color); | |
92 | V.UndoOnBoard(this.board, m); | |
93 | if (m.vanish[0].p == V.KING) | |
94 | this.kingPos[m.vanish[0].c] = [m.vanish[0].x, m.vanish[0].y]; | |
95 | return res; | |
96 | }); | |
97 | } | |
98 | ||
99 | prePlay(move) { | |
100 | const L = this.lastMove.length; | |
101 | const lm = this.lastMove[L-1]; | |
2a0672a9 BA |
102 | // NOTE: refusal could be recomputed, but, it's easier like this |
103 | if (move.vanish[0].c != this.turn) move.refusal = true; | |
39867b70 BA |
104 | move.noRef = ( |
105 | !!move.refusal || | |
106 | // My previous move was already refused? | |
107 | !!lm && this.getColor(lm.end.x, lm.end.y) == this.turn | |
108 | ); | |
2a0672a9 BA |
109 | } |
110 | ||
111 | getEpSquare(move) { | |
112 | if (!move.refusal) return super.getEpSquare(move); | |
113 | return null; //move refusal | |
114 | } | |
115 | ||
116 | postPlay(move) { | |
117 | if (!move.refusal) super.postPlay(move); | |
118 | else { | |
119 | const L = this.lastMove.length; | |
120 | const lm = this.lastMove[L-1]; | |
39867b70 BA |
121 | if (move.appear[0].p == V.KING) |
122 | this.kingPos[move.appear[0].c] = [move.end.x, move.end.y]; | |
2a0672a9 BA |
123 | } |
124 | // NOTE: explicitely give fields, because some are assigned in BaseGame | |
125 | let mvInLm = { | |
126 | start: move.start, | |
127 | end: move.end, | |
128 | appear: move.appear, | |
129 | vanish: move.vanish, | |
2a0672a9 BA |
130 | }; |
131 | if (!!move.noRef) mvInLm.noRef = true; | |
132 | if (!!move.refusal) mvInLm.refusal = true; | |
133 | this.lastMove.push(mvInLm); | |
134 | } | |
135 | ||
136 | postUndo(move) { | |
137 | if (!move.refusal) super.postUndo(move); | |
39867b70 BA |
138 | else { |
139 | if (move.appear[0].p == V.KING) | |
140 | this.kingPos[move.appear[0].c] = [move.start.x, move.start.y]; | |
141 | } | |
2a0672a9 BA |
142 | this.lastMove.pop(); |
143 | } | |
144 | ||
145 | getAllPotentialMoves() { | |
146 | const color = this.turn; | |
147 | const L = this.lastMove.length; | |
148 | const lm = this.lastMove[L-1]; | |
149 | let potentialMoves = []; | |
39867b70 BA |
150 | if (!!lm && !lm.noRef) |
151 | // Add refusal move: | |
152 | potentialMoves = this.getPotentialMovesFrom([lm.end.x, lm.end.y]); | |
2a0672a9 BA |
153 | for (let i = 0; i < V.size.x; i++) { |
154 | for (let j = 0; j < V.size.y; j++) { | |
39867b70 | 155 | if (this.board[i][j] != V.EMPTY && this.getColor(i, j) == color) { |
2a0672a9 BA |
156 | Array.prototype.push.apply( |
157 | potentialMoves, | |
158 | this.getPotentialMovesFrom([i, j]) | |
159 | ); | |
160 | } | |
161 | } | |
162 | } | |
163 | return potentialMoves; | |
164 | } | |
165 | ||
39867b70 BA |
166 | atLeastOneMove() { |
167 | const L = this.lastMove.length; | |
168 | const lm = this.lastMove[L-1]; | |
169 | if (!!lm && !lm.noRef) return true; | |
170 | return super.atLeastOneMove(); | |
171 | } | |
172 | ||
2a0672a9 BA |
173 | getComputerMove() { |
174 | // Just play at random for now... (TODO?) | |
175 | // Refuse last move with odds 1/3. | |
176 | const moves = this.getAllValidMoves(); | |
177 | const refusal = moves.find(m => m.vanish[0].c != this.turn); | |
178 | if (!!refusal) { | |
39867b70 | 179 | if (moves.length == 1 || Math.random() <= 0.33) return refusal; |
2a0672a9 BA |
180 | const others = moves.filter(m => m.vanish[0].c == this.turn); |
181 | return others[randInt(others.length)]; | |
182 | } | |
183 | else return moves[randInt(moves.length)]; | |
184 | } | |
185 | ||
186 | getNotation(move) { | |
187 | if (move.vanish[0].c != this.turn) return "Refuse"; | |
188 | return super.getNotation(move); | |
189 | } | |
190 | ||
191 | }; |