Commit | Line | Data |
---|---|---|
7d7e947f BA |
1 | import { ChessRules, Move, PiPo } from "@/base_rules"; |
2 | ||
f10a644e | 3 | export class Align4Rules extends ChessRules { |
7d7e947f | 4 | |
4313762d BA |
5 | static get Options() { |
6 | return { | |
7 | check: [ | |
8 | { | |
9 | label: "Random", | |
10 | defaut: false, | |
11 | variable: "random" | |
12 | } | |
13 | ] | |
14 | }; | |
15 | } | |
16 | ||
17 | static GenRandInitFen(options) { | |
18 | const baseFen = ChessRules.GenRandInitFen( | |
19 | { randomness: (options.random ? 1 : 0) }); | |
7d7e947f BA |
20 | return "4k3/8" + baseFen.substring(17, 50) + " -"; |
21 | } | |
22 | ||
23 | getReservePpath() { | |
24 | return "bp"; | |
25 | } | |
26 | ||
27 | static get RESERVE_PIECES() { | |
28 | return [V.PAWN]; //only black pawns | |
29 | } | |
30 | ||
31 | getColor(i, j) { | |
32 | if (i >= V.size.x) return "b"; | |
33 | return this.board[i][j].charAt(0); | |
34 | } | |
35 | ||
36 | getPiece(i, j) { | |
37 | if (i >= V.size.x) return V.PAWN; | |
38 | return this.board[i][j].charAt(1); | |
39 | } | |
40 | ||
41 | static IsGoodFlags(flags) { | |
42 | // Only white can castle | |
43 | return !!flags.match(/^[a-z]{2,2}$/); | |
44 | } | |
45 | ||
46 | getFlagsFen() { | |
47 | return this.castleFlags['w'].map(V.CoordToColumn).join(""); | |
48 | } | |
49 | ||
50 | setFlags(fenflags) { | |
51 | this.castleFlags = { 'w': [-1, -1] }; | |
52 | for (let i = 0; i < 2; i++) | |
53 | this.castleFlags['w'][i] = V.ColumnToCoord(fenflags.charAt(i)); | |
54 | } | |
55 | ||
56 | setOtherVariables(fen) { | |
57 | super.setOtherVariables(fen); | |
58 | this.reserve = { b: { [V.PAWN]: 1 } }; | |
59 | } | |
60 | ||
61 | getReserveMoves() { | |
62 | if (this.turn != 'b') return []; | |
63 | let moves = []; | |
64 | for (let i = 1; i <= 6; i++) { | |
65 | for (let j = 0; j < V.size.y; j++) { | |
66 | if (this.board[i][j] == V.EMPTY) { | |
67 | let mv = new Move({ | |
68 | appear: [ | |
69 | new PiPo({ | |
70 | x: i, | |
71 | y: j, | |
72 | c: 'b', | |
73 | p: 'p' | |
74 | }) | |
75 | ], | |
76 | vanish: [], | |
77 | start: { x: 9, y: 0 }, | |
78 | end: { x: i, y: j } | |
79 | }); | |
80 | moves.push(mv); | |
81 | } | |
82 | } | |
83 | } | |
84 | return moves; | |
85 | } | |
86 | ||
87 | getPotentialMovesFrom(sq) { | |
88 | if (sq[0] >= V.size.x) return this.getReserveMoves(); | |
89 | return super.getPotentialMovesFrom(sq); | |
90 | } | |
91 | ||
92 | getPotentialKingMoves([x, y]) { | |
93 | if (this.getColor(x, y) == 'w') return super.getPotentialKingMoves([x, y]); | |
94 | // Black doesn't castle: | |
95 | return super.getSlideNJumpMoves( | |
4313762d | 96 | [x, y], V.steps[V.ROOK].concat(V.steps[V.BISHOP]), 1); |
7d7e947f BA |
97 | } |
98 | ||
99 | getAllValidMoves() { | |
100 | return ( | |
101 | super.getAllValidMoves().concat( | |
102 | super.filterValid(this.getReserveMoves())) | |
103 | ); | |
104 | } | |
105 | ||
106 | atLeastOneMove() { | |
107 | if (super.atLeastOneMove()) return true; | |
108 | // Search one reserve move | |
109 | if (this.filterValid(this.getReserveMoves()).length > 0) return true; | |
110 | return false; | |
111 | } | |
112 | ||
113 | updateCastleFlags(move, piece) { | |
114 | // Only white can castle: | |
115 | const firstRank = 7; | |
116 | if (piece == V.KING && move.appear[0].c == 'w') | |
117 | this.castleFlags['w'] = [8, 8]; | |
118 | else if ( | |
119 | move.start.x == firstRank && | |
120 | this.castleFlags['w'].includes(move.start.y) | |
121 | ) { | |
122 | const flagIdx = (move.start.y == this.castleFlags['w'][0] ? 0 : 1); | |
123 | this.castleFlags['w'][flagIdx] = 8; | |
124 | } | |
125 | else if ( | |
126 | move.end.x == firstRank && | |
127 | this.castleFlags['w'].includes(move.end.y) | |
128 | ) { | |
129 | const flagIdx = (move.end.y == this.castleFlags['w'][0] ? 0 : 1); | |
130 | this.castleFlags['w'][flagIdx] = 8; | |
131 | } | |
132 | } | |
133 | ||
134 | getCurrentScore() { | |
135 | const score = super.getCurrentScore(); | |
136 | if (score != "*") return score; | |
137 | // Check pawns connection: | |
138 | for (let i = 0; i < V.size.x; i++) { | |
139 | for (let j = 0; j < V.size.y; j++) { | |
140 | if ( | |
141 | this.board[i][j] != V.EMPTY && | |
142 | this.getColor(i, j) == 'b' && | |
143 | this.getPiece(i, j) == V.PAWN | |
144 | ) { | |
145 | // Exploration "rightward + downward" is enough | |
146 | for (let step of [[1, 0], [0, 1], [1, 1], [-1, 1]]) { | |
147 | let [ii, jj] = [i + step[0], j + step[1]]; | |
148 | let kounter = 1; | |
149 | while ( | |
150 | V.OnBoard(ii, jj) && | |
151 | this.board[ii][jj] != V.EMPTY && | |
152 | this.getColor(ii, jj) == 'b' && | |
153 | this.getPiece(ii, jj) != V.KING | |
154 | ) { | |
155 | kounter++; | |
156 | ii += step[0]; | |
157 | jj += step[1]; | |
158 | } | |
159 | if (kounter == 4) return "0-1"; | |
160 | } | |
161 | } | |
162 | } | |
163 | } | |
164 | return "*"; | |
165 | } | |
166 | ||
167 | evalPosition() { | |
168 | let evaluation = 0; | |
169 | // Count white material + check pawns alignments | |
170 | let maxAlign = 0; | |
171 | for (let i = 0; i < V.size.x; i++) { | |
172 | for (let j = 0; j < V.size.y; j++) { | |
173 | if (this.board[i][j] != V.EMPTY) { | |
174 | const piece = this.getPiece(i, j); | |
175 | if (piece != V.KING) { | |
176 | const color = this.getColor(i, j); | |
177 | if (color == 'w') evaluation += V.VALUES[piece]; | |
178 | else { | |
179 | // Exploration "rightward + downward" is enough | |
180 | for (let step of [[1, 0], [0, 1], [1, 1], [-1, 1]]) { | |
181 | let [ii, jj] = [i + step[0], j + step[1]]; | |
182 | let kounter = 1; | |
183 | while ( | |
184 | V.OnBoard(ii, jj) && | |
185 | this.board[ii][jj] != V.EMPTY && | |
186 | this.getColor(ii, jj) == 'b' && | |
187 | this.getPiece(ii, jj) != V.KING | |
188 | ) { | |
189 | kounter++; | |
190 | ii += step[0]; | |
191 | jj += step[1]; | |
192 | } | |
193 | if (kounter > maxAlign) maxAlign = kounter; | |
194 | } | |
195 | } | |
196 | } | |
197 | } | |
198 | } | |
199 | } | |
200 | // -1 for two aligned pawns, -3 for 3 aligned pawns. | |
201 | if ([1, 2].includes(maxAlign)) maxAlign--; | |
202 | return evaluation - maxAlign; | |
203 | } | |
204 | ||
205 | getNotation(move) { | |
206 | if (move.vanish.length == 0) return "@" + V.CoordsToSquare(move.end); | |
207 | return super.getNotation(move); | |
208 | } | |
209 | ||
210 | }; | |
211 |