Commit | Line | Data |
---|---|---|
a6abf094 BA |
1 | class LoserRules extends ChessRules |
2 | { | |
2d7194bd | 3 | static get HasFlags() { return false; } |
7931e479 | 4 | |
2d7194bd | 5 | setOtherVariables(fen) |
1970e049 | 6 | { |
2d7194bd BA |
7 | const parsedFen = V.ParseFen(fen); |
8 | const epSq = parsedFen.enpassant != "-" | |
9 | ? V.SquareToCoords(parsedFen.enpassant) | |
10 | : undefined; | |
11 | this.epSquares = [ epSq ]; | |
12 | this.scanKingsRooks(fen); | |
1970e049 | 13 | } |
a6abf094 BA |
14 | |
15 | getPotentialPawnMoves([x,y]) | |
16 | { | |
17 | let moves = super.getPotentialPawnMoves([x,y]); | |
18 | ||
19 | // Complete with promotion(s) into king, if possible | |
20 | const color = this.turn; | |
a6abf094 | 21 | const shift = (color == "w" ? -1 : 1); |
0b7d99ec | 22 | const lastRank = (color == "w" ? 0 : V.size.x-1); |
a6abf094 BA |
23 | if (x+shift == lastRank) |
24 | { | |
a6abf094 BA |
25 | // Normal move |
26 | if (this.board[x+shift][y] == V.EMPTY) | |
92342261 | 27 | moves.push(this.getBasicMove([x,y], [x+shift,y], {c:color,p:V.KING})); |
a6abf094 | 28 | // Captures |
92342261 BA |
29 | if (y>0 && this.canTake([x,y], [x+shift,y-1]) |
30 | && this.board[x+shift][y-1] != V.EMPTY) | |
31 | { | |
32 | moves.push(this.getBasicMove([x,y], [x+shift,y-1], {c:color,p:V.KING})); | |
33 | } | |
0b7d99ec | 34 | if (y<V.size.y-1 && this.canTake([x,y], [x+shift,y+1]) |
92342261 BA |
35 | && this.board[x+shift][y+1] != V.EMPTY) |
36 | { | |
37 | moves.push(this.getBasicMove([x,y], [x+shift,y+1], {c:color,p:V.KING})); | |
38 | } | |
a6abf094 BA |
39 | } |
40 | ||
41 | return moves; | |
42 | } | |
43 | ||
44 | getPotentialKingMoves(sq) | |
45 | { | |
2d7194bd | 46 | // No castle: |
a6abf094 BA |
47 | return this.getSlideNJumpMoves(sq, |
48 | V.steps[V.ROOK].concat(V.steps[V.BISHOP]), "oneStep"); | |
49 | } | |
50 | ||
51 | // Stop at the first capture found (if any) | |
52 | atLeastOneCapture() | |
53 | { | |
54 | const color = this.turn; | |
55 | const oppCol = this.getOppCol(color); | |
0b7d99ec | 56 | for (let i=0; i<V.size.x; i++) |
a6abf094 | 57 | { |
0b7d99ec | 58 | for (let j=0; j<V.size.y; j++) |
a6abf094 | 59 | { |
0b7d99ec | 60 | if (this.board[i][j] != V.EMPTY && this.getColor(i,j) != oppCol) |
a6abf094 BA |
61 | { |
62 | const moves = this.getPotentialMovesFrom([i,j]); | |
63 | if (moves.length > 0) | |
64 | { | |
65 | for (let k=0; k<moves.length; k++) | |
66 | { | |
67 | if (moves[k].vanish.length==2 && this.filterValid([moves[k]]).length > 0) | |
68 | return true; | |
69 | } | |
70 | } | |
71 | } | |
72 | } | |
73 | } | |
74 | return false; | |
75 | } | |
76 | ||
77 | // Trim all non-capturing moves | |
78 | static KeepCaptures(moves) | |
79 | { | |
80 | return moves.filter(m => { return m.vanish.length == 2; }); | |
81 | } | |
82 | ||
83 | getPossibleMovesFrom(sq) | |
84 | { | |
85 | let moves = this.filterValid( this.getPotentialMovesFrom(sq) ); | |
86 | // This is called from interface: we need to know if a capture is possible | |
87 | if (this.atLeastOneCapture()) | |
0b7d99ec | 88 | moves = V.KeepCaptures(moves); |
a6abf094 BA |
89 | return moves; |
90 | } | |
91 | ||
92 | getAllValidMoves() | |
93 | { | |
94 | let moves = super.getAllValidMoves(); | |
95 | if (moves.some(m => { return m.vanish.length == 2; })) | |
0b7d99ec | 96 | moves = V.KeepCaptures(moves); |
a6abf094 BA |
97 | return moves; |
98 | } | |
99 | ||
100 | underCheck(move) | |
101 | { | |
102 | return false; //No notion of check | |
103 | } | |
104 | ||
105 | getCheckSquares(move) | |
106 | { | |
107 | return []; | |
108 | } | |
109 | ||
2d7194bd | 110 | // No variables update because no castling |
6752407b BA |
111 | updateVariables(move) { } |
112 | unupdateVariables(move) { } | |
a6abf094 BA |
113 | |
114 | checkGameEnd() | |
115 | { | |
116 | // No valid move: you win! | |
117 | return this.turn == "w" ? "1-0" : "0-1"; | |
118 | } | |
119 | ||
2d7194bd BA |
120 | static get VALUES() |
121 | { | |
122 | // Experimental... | |
a6abf094 BA |
123 | return { |
124 | 'p': 1, | |
125 | 'r': 7, | |
126 | 'n': 3, | |
127 | 'b': 3, | |
128 | 'q': 5, | |
129 | 'k': 5 | |
130 | }; | |
131 | } | |
132 | ||
133 | static get SEARCH_DEPTH() { return 4; } | |
134 | ||
135 | evalPosition() | |
136 | { | |
137 | return - super.evalPosition(); //better with less material | |
138 | } | |
2eef6db6 BA |
139 | |
140 | static GenRandInitFen() | |
141 | { | |
142 | let pieces = { "w": new Array(8), "b": new Array(8) }; | |
143 | // Shuffle pieces on first and last rank | |
144 | for (let c of ["w","b"]) | |
145 | { | |
146 | let positions = _.range(8); | |
147 | ||
148 | // Get random squares for bishops | |
149 | let randIndex = 2 * _.random(3); | |
150 | let bishop1Pos = positions[randIndex]; | |
151 | // The second bishop must be on a square of different color | |
152 | let randIndex_tmp = 2 * _.random(3) + 1; | |
153 | let bishop2Pos = positions[randIndex_tmp]; | |
154 | // Remove chosen squares | |
155 | positions.splice(Math.max(randIndex,randIndex_tmp), 1); | |
156 | positions.splice(Math.min(randIndex,randIndex_tmp), 1); | |
157 | ||
158 | // Get random squares for knights | |
159 | randIndex = _.random(5); | |
160 | let knight1Pos = positions[randIndex]; | |
161 | positions.splice(randIndex, 1); | |
162 | randIndex = _.random(4); | |
163 | let knight2Pos = positions[randIndex]; | |
164 | positions.splice(randIndex, 1); | |
165 | ||
166 | // Get random square for queen | |
167 | randIndex = _.random(3); | |
168 | let queenPos = positions[randIndex]; | |
169 | positions.splice(randIndex, 1); | |
170 | ||
171 | // Random square for king (no castle) | |
172 | randIndex = _.random(2); | |
173 | let kingPos = positions[randIndex]; | |
174 | positions.splice(randIndex, 1); | |
175 | ||
176 | // Rooks positions are now fixed | |
177 | let rook1Pos = positions[0]; | |
178 | let rook2Pos = positions[1]; | |
179 | ||
180 | // Finally put the shuffled pieces in the board array | |
181 | pieces[c][rook1Pos] = 'r'; | |
182 | pieces[c][knight1Pos] = 'n'; | |
183 | pieces[c][bishop1Pos] = 'b'; | |
184 | pieces[c][queenPos] = 'q'; | |
185 | pieces[c][kingPos] = 'k'; | |
186 | pieces[c][bishop2Pos] = 'b'; | |
187 | pieces[c][knight2Pos] = 'n'; | |
188 | pieces[c][rook2Pos] = 'r'; | |
189 | } | |
190 | return pieces["b"].join("") + | |
191 | "/pppppppp/8/8/8/8/PPPPPPPP/" + | |
192 | pieces["w"].join("").toUpperCase() + | |
2d7194bd | 193 | " w -"; //no en-passant |
2eef6db6 | 194 | } |
a6abf094 | 195 | } |