Commit | Line | Data |
---|---|---|
0a36d31a BA |
1 | import ChessRules from "/base_rules.js"; |
2 | import { randInt, shuffle } from "@/utils/alea"; | |
3 | import { ArrayFun } from "@/utils/array"; | |
4 | ||
5 | export default class AmbiguousRules extends ChessRules { | |
6 | ||
7 | // TODO: options | |
8 | ||
9 | get hasFlags() { | |
10 | return false; | |
11 | } | |
12 | ||
13 | setOtherVariables(fenParsed) { | |
14 | super.setOtherVariables(fenParsed); | |
15 | if (this.movesCount == 0) | |
16 | this.subTurn = 2; | |
17 | else | |
18 | this.subTurn = 1; | |
19 | } | |
20 | ||
21 | genRandInitFen(seed) { | |
22 | const gr = new GiveawayRules( | |
23 | {mode: "suicide", options: this.options, genFenOnly: true}); | |
24 | return gr.genRandInitFen(seed); | |
25 | } | |
26 | ||
27 | // Subturn 1: play a move for the opponent on the designated square. | |
28 | // Subturn 2: play a move for me (which just indicate a square). | |
29 | getPotentialMovesFrom([x, y]) { | |
30 | const color = this.turn; | |
31 | const oppCol = V.GetOppCol(color); | |
32 | if (this.subTurn == 2) { | |
33 | // Just play a normal move (which in fact only indicate a square) | |
34 | let movesHash = {}; | |
35 | return ( | |
36 | super.getPotentialMovesFrom([x, y]) | |
37 | .filter(m => { | |
38 | // Filter promotions: keep only one, since no choice now. | |
39 | if (m.appear[0].p != m.vanish[0].p) { | |
40 | const hash = V.CoordsToSquare(m.start) + V.CoordsToSquare(m.end); | |
41 | if (!movesHash[hash]) { | |
42 | movesHash[hash] = true; | |
43 | return true; | |
44 | } | |
45 | return false; | |
46 | } | |
47 | return true; | |
48 | }) | |
49 | .map(m => { | |
50 | if (m.vanish.length == 1) m.appear[0].p = V.GOAL; | |
51 | else m.appear[0].p = V.TARGET_CODE[m.vanish[1].p]; | |
52 | m.appear[0].c = oppCol; | |
53 | m.vanish.shift(); | |
54 | return m; | |
55 | }) | |
56 | ); | |
57 | } | |
58 | // At subTurn == 1, play a targeted move for opponent | |
59 | // Search for target (we could also have it in a stack...) | |
60 | let target = { x: -1, y: -1 }; | |
61 | outerLoop: for (let i = 0; i < V.size.x; i++) { | |
62 | for (let j = 0; j < V.size.y; j++) { | |
63 | if (this.board[i][j] != V.EMPTY) { | |
64 | const piece = this.board[i][j][1]; | |
65 | if ( | |
66 | piece == V.GOAL || | |
67 | Object.keys(V.TARGET_DECODE).includes(piece) | |
68 | ) { | |
69 | target = { x: i, y: j}; | |
70 | break outerLoop; | |
71 | } | |
72 | } | |
73 | } | |
74 | } | |
75 | // TODO: could be more efficient than generating all moves. | |
76 | this.turn = oppCol; | |
77 | const emptyTarget = (this.board[target.x][target.y][1] == V.GOAL); | |
78 | if (emptyTarget) this.board[target.x][target.y] = V.EMPTY; | |
79 | let moves = super.getPotentialMovesFrom([x, y]); | |
80 | if (emptyTarget) { | |
81 | this.board[target.x][target.y] = color + V.GOAL; | |
82 | moves.forEach(m => { | |
83 | m.vanish.push({ | |
84 | x: target.x, | |
85 | y: target.y, | |
86 | c: color, | |
87 | p: V.GOAL | |
88 | }); | |
89 | }); | |
90 | } | |
91 | this.turn = color; | |
92 | return moves.filter(m => m.end.x == target.x && m.end.y == target.y); | |
93 | } | |
94 | ||
95 | canIplay(x, y) { | |
96 | const color = this.getColor(x, y); | |
97 | return ( | |
98 | (this.subTurn == 1 && ![this.turn, this.playerColor].includes(color)) || | |
99 | (this.subTurn == 2 && super.canIplay(x, y)) | |
100 | ); | |
101 | } | |
102 | ||
103 | // Code for empty square target | |
104 | static get GOAL() { | |
105 | return 'g'; | |
106 | } | |
107 | ||
108 | static get TARGET_DECODE() { | |
109 | return { | |
110 | 's': 'p', | |
111 | 't': 'q', | |
112 | 'u': 'r', | |
113 | 'o': 'n', | |
114 | 'c': 'b', | |
115 | 'l': 'k' | |
116 | }; | |
117 | } | |
118 | ||
119 | static get TARGET_CODE() { | |
120 | return { | |
121 | 'p': 's', | |
122 | 'q': 't', | |
123 | 'r': 'u', | |
124 | 'n': 'o', | |
125 | 'b': 'c', | |
126 | 'k': 'l' | |
127 | }; | |
128 | } | |
129 | ||
130 | pieces() { | |
131 | // ......... | |
132 | } | |
133 | ||
134 | atLeastOneMove() { | |
135 | // Since there are no checks this seems true (same as for Magnetic...) | |
136 | return true; | |
137 | } | |
138 | ||
139 | filterValid(moves) { | |
140 | return moves; | |
141 | } | |
142 | ||
143 | getCurrentScore() { | |
144 | // This function is only called at subTurn 1 | |
145 | const color = V.GetOppCol(this.turn); | |
146 | if (this.kingPos[color][0] < 0) return (color == 'w' ? "0-1" : "1-0"); | |
147 | return "*"; | |
148 | } | |
149 | ||
150 | play(move) { | |
151 | let kingCaptured = false; | |
152 | if (this.subTurn == 1) { | |
153 | this.prePlay(move); | |
154 | this.epSquares.push(this.getEpSquare(move)); | |
155 | kingCaptured = this.kingPos[this.turn][0] < 0; | |
156 | } | |
157 | if (kingCaptured) move.kingCaptured = true; | |
158 | V.PlayOnBoard(this.board, move); | |
159 | if (this.subTurn == 2 || kingCaptured) { | |
160 | this.turn = V.GetOppCol(this.turn); | |
161 | this.movesCount++; | |
162 | } | |
163 | if (!kingCaptured) this.subTurn = 3 - this.subTurn; | |
164 | } | |
165 | ||
166 | }; |