Code simplification + a few fixes
[vchess.git] / public / javascripts / variants / Loser.js
CommitLineData
a6abf094
BA
1class LoserRules extends ChessRules
2{
3 initVariables(fen)
4 {
a6abf094
BA
5 const epSq = this.moves.length > 0 ? this.getEpSquare(this.lastMove) : undefined;
6 this.epSquares = [ epSq ];
7 }
8
1970e049
BA
9 setFlags(fen)
10 {
11 // No castling, hence no flags; but flags defined for compatibility
77e1ec78 12 this.castleFlags = { "w":[false,false], "b":[false,false] };
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 {
a6abf094
BA
46 return this.getSlideNJumpMoves(sq,
47 V.steps[V.ROOK].concat(V.steps[V.BISHOP]), "oneStep");
48 }
49
50 // Stop at the first capture found (if any)
51 atLeastOneCapture()
52 {
53 const color = this.turn;
54 const oppCol = this.getOppCol(color);
0b7d99ec 55 for (let i=0; i<V.size.x; i++)
a6abf094 56 {
0b7d99ec 57 for (let j=0; j<V.size.y; j++)
a6abf094 58 {
0b7d99ec 59 if (this.board[i][j] != V.EMPTY && this.getColor(i,j) != oppCol)
a6abf094
BA
60 {
61 const moves = this.getPotentialMovesFrom([i,j]);
62 if (moves.length > 0)
63 {
64 for (let k=0; k<moves.length; k++)
65 {
66 if (moves[k].vanish.length==2 && this.filterValid([moves[k]]).length > 0)
67 return true;
68 }
69 }
70 }
71 }
72 }
73 return false;
74 }
75
76 // Trim all non-capturing moves
77 static KeepCaptures(moves)
78 {
79 return moves.filter(m => { return m.vanish.length == 2; });
80 }
81
82 getPossibleMovesFrom(sq)
83 {
84 let moves = this.filterValid( this.getPotentialMovesFrom(sq) );
85 // This is called from interface: we need to know if a capture is possible
86 if (this.atLeastOneCapture())
0b7d99ec 87 moves = V.KeepCaptures(moves);
a6abf094
BA
88 return moves;
89 }
90
91 getAllValidMoves()
92 {
93 let moves = super.getAllValidMoves();
94 if (moves.some(m => { return m.vanish.length == 2; }))
0b7d99ec 95 moves = V.KeepCaptures(moves);
a6abf094
BA
96 return moves;
97 }
98
99 underCheck(move)
100 {
101 return false; //No notion of check
102 }
103
104 getCheckSquares(move)
105 {
106 return [];
107 }
108
6752407b
BA
109 // Unused:
110 updateVariables(move) { }
111 unupdateVariables(move) { }
a6abf094 112
77e1ec78
BA
113 getFlagsFen()
114 {
92342261 115 return "-";
77e1ec78
BA
116 }
117
a6abf094
BA
118 checkGameEnd()
119 {
120 // No valid move: you win!
121 return this.turn == "w" ? "1-0" : "0-1";
122 }
123
124 static get VALUES() { //experimental...
125 return {
126 'p': 1,
127 'r': 7,
128 'n': 3,
129 'b': 3,
130 'q': 5,
131 'k': 5
132 };
133 }
134
135 static get SEARCH_DEPTH() { return 4; }
136
137 evalPosition()
138 {
139 return - super.evalPosition(); //better with less material
140 }
2eef6db6
BA
141
142 static GenRandInitFen()
143 {
144 let pieces = { "w": new Array(8), "b": new Array(8) };
145 // Shuffle pieces on first and last rank
146 for (let c of ["w","b"])
147 {
148 let positions = _.range(8);
149
150 // Get random squares for bishops
151 let randIndex = 2 * _.random(3);
152 let bishop1Pos = positions[randIndex];
153 // The second bishop must be on a square of different color
154 let randIndex_tmp = 2 * _.random(3) + 1;
155 let bishop2Pos = positions[randIndex_tmp];
156 // Remove chosen squares
157 positions.splice(Math.max(randIndex,randIndex_tmp), 1);
158 positions.splice(Math.min(randIndex,randIndex_tmp), 1);
159
160 // Get random squares for knights
161 randIndex = _.random(5);
162 let knight1Pos = positions[randIndex];
163 positions.splice(randIndex, 1);
164 randIndex = _.random(4);
165 let knight2Pos = positions[randIndex];
166 positions.splice(randIndex, 1);
167
168 // Get random square for queen
169 randIndex = _.random(3);
170 let queenPos = positions[randIndex];
171 positions.splice(randIndex, 1);
172
173 // Random square for king (no castle)
174 randIndex = _.random(2);
175 let kingPos = positions[randIndex];
176 positions.splice(randIndex, 1);
177
178 // Rooks positions are now fixed
179 let rook1Pos = positions[0];
180 let rook2Pos = positions[1];
181
182 // Finally put the shuffled pieces in the board array
183 pieces[c][rook1Pos] = 'r';
184 pieces[c][knight1Pos] = 'n';
185 pieces[c][bishop1Pos] = 'b';
186 pieces[c][queenPos] = 'q';
187 pieces[c][kingPos] = 'k';
188 pieces[c][bishop2Pos] = 'b';
189 pieces[c][knight2Pos] = 'n';
190 pieces[c][rook2Pos] = 'r';
191 }
192 return pieces["b"].join("") +
193 "/pppppppp/8/8/8/8/PPPPPPPP/" +
194 pieces["w"].join("").toUpperCase() +
195 " 0000"; //add flags (TODO?!)
196 }
a6abf094 197}