Some simplifactions, a few fixes, update TODO
[vchess.git] / client / src / variants / Dice.js
1 import { ChessRules, Move } from "@/base_rules";
2 import { randInt } from "@/utils/alea";
3
4 export class DiceRules extends ChessRules {
5
6 static get CanAnalyze() {
7 return false;
8 }
9
10 static ParseFen(fen) {
11 const fenParts = fen.split(" ");
12 return Object.assign(
13 ChessRules.ParseFen(fen),
14 { toplay: fenParts[5] }
15 );
16 }
17
18 setOtherVariables(fen) {
19 super.setOtherVariables(fen);
20 this.p2play = [];
21 const toplay = V.ParseFen(fen).toplay;
22 if (toplay != "-") this.p2play.push(toplay);
23 }
24
25 getFen() {
26 return super.getFen() + " " + this.getToplayFen();
27 }
28
29 getFenForRepeat() {
30 return super.getFenForRepeat() + "_" + this.getToplayFen();
31 }
32
33 getToplayFen() {
34 const L = this.p2play.length;
35 return (L > 0 ? this.p2play[L-1] : "-");
36 }
37
38 static GenRandInitFen(randomness) {
39 return ChessRules.GenRandInitFen(randomness) + " -";
40 }
41
42 canMove(piece, color, [x, y]) {
43 const oppCol = V.GetOppCol(color);
44 if (piece == V.PAWN) {
45 const forward = (color == 'w' ? -1 : 1);
46 if (this.board[x + forward][y] == V.EMPTY) return true;
47 for (let shift of [-1, 1]) {
48 const [i, j] = [x + forward, y + shift];
49 if (
50 V.OnBoard(i, j) &&
51 this.board[i][j] != V.EMPTY &&
52 this.getColor(i, j) == oppCol
53 ) {
54 return true;
55 }
56 }
57 }
58 else {
59 const steps =
60 [V.KING, V.QUEEN].includes(piece)
61 ? V.steps[V.ROOK].concat(V.steps[V.BISHOP])
62 : V.steps[piece];
63 for (let s of steps) {
64 const [i, j] = [x + s[0], y + s[1]];
65 if (
66 V.OnBoard(i, j) &&
67 (this.board[i][j] == V.EMPTY || this.getColor(i, j) == oppCol)
68 ) {
69 return true;
70 }
71 }
72 }
73 return false;
74 }
75
76 getRandPiece(color) {
77 // Find pieces which can move and roll a dice
78 let canMove = {};
79 for (let i=0; i<8; i++) {
80 for (let j=0; j<8; j++) {
81 if (this.board[i][j] != V.EMPTY && this.getColor(i, j) == color) {
82 const piece = this.getPiece(i, j);
83 if (!canMove[piece] && this.canMove(piece, color, [i, j]))
84 canMove[piece] = [i, j];
85 }
86 }
87 }
88 const options = Object.keys(canMove);
89 const randPiece = options[randInt(options.length)];
90 return [randPiece, canMove[randPiece]];
91 }
92
93 getPotentialMovesFrom([x, y]) {
94 const color = this.turn;
95 let moves = undefined;
96 if (this.movesCount == 0) moves = super.getPotentialMovesFrom([x, y]);
97 else {
98 const L = this.p2play.length; //L is >= 1
99 const piece = this.getPiece(x, y);
100 if (
101 piece == V.PAWN &&
102 this.p2play[L-1] != V.PAWN &&
103 ((color == 'w' && x == 1) || (color == 'b' && x == 6))
104 ) {
105 // The piece is a pawn about to promote
106 const destX = (color == 'w' ? 0 : 7);
107 moves = [];
108 if (this.board[destX][y] == V.EMPTY) {
109 moves.push(
110 this.getBasicMove(
111 [x, y], [destX, y], { c: color, p: this.p2play[L-1] })
112 );
113 }
114 for (let shift of [-1, 1]) {
115 const [i, j] = [destX, y + shift];
116 if (
117 V.OnBoard(i, j) &&
118 this.board[i][j] != V.EMPTY &&
119 this.getColor(i, j) != color
120 ) {
121 moves.push(
122 this.getBasicMove(
123 [x, y], [i, j], { c: color, p: this.p2play[L-1] })
124 );
125 }
126 }
127 }
128 else if (piece != this.p2play[L-1])
129 // The piece type must match last p2play
130 return [];
131 else moves = super.getPotentialMovesFrom([x, y]);
132 }
133 // Decide which piece the opponent will play:
134 const oppCol = V.GetOppCol(color);
135 moves.forEach(m => {
136 V.PlayOnBoard(this.board, m);
137 const [piece, square] = this.getRandPiece(oppCol);
138 m.start.toplay = square;
139 m.end.p = piece;
140 V.UndoOnBoard(this.board, m);
141 });
142 return moves;
143 }
144
145 filterValid(moves) {
146 return moves;
147 }
148
149 getCheckSquares() {
150 return [];
151 }
152
153 getCurrentScore() {
154 const color = this.turn;
155 if (this.kingPos[color][0] < 0) return (color == 'w' ? "0-1" : "1-0");
156 return "*";
157 }
158
159 postPlay(move) {
160 this.p2play.push(move.end.p);
161 if (move.vanish.length == 2 && move.vanish[1].p == V.KING)
162 this.kingPos[move.vanish[1].c] = [-1, -1];
163 // Castle flags for captured king won't be updated (not important...)
164 super.postPlay(move);
165 }
166
167 postUndo(move) {
168 this.p2play.pop();
169 if (move.vanish.length == 2 && move.vanish[1].p == V.KING)
170 this.kingPos[move.vanish[1].c] = [move.vanish[1].x, move.vanish[1].y];
171 super.postUndo(move);
172 }
173
174 static get SEARCH_DEPTH() {
175 return 1;
176 }
177
178 getNotation(move) {
179 return super.getNotation(move) + "/" + move.end.p.toUpperCase();
180 }
181
182 };