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