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