Fix Dice chess
[vchess.git] / client / src / variants / Dice.js
CommitLineData
68971030
BA
1import { ChessRules, Move } from "@/base_rules";
2import { randInt } from "@/utils/alea";
3
4export class DiceRules extends ChessRules {
5 static get CanAnalyze() {
0ada7ac5 6 return false;
68971030
BA
7 }
8
9 doClick(square) {
10 if (
11 this.subTurn == 2 ||
12 isNaN(square[0]) ||
13 this.board[square[0]][square[1]] != V.EMPTY
14 ) {
15 return null;
16 }
17 // Announce the piece' type to be played:
18 return this.getRandPieceMove();
19 }
20
21 getPotentialMovesFrom([x, y]) {
0ada7ac5 22 if (this.subTurn == 1) return [];
68971030 23 const L = this.p2play.length;
0ada7ac5
BA
24 const piece = this.getPiece(x, y);
25 if (piece == V.PAWN && this.p2play[L-1] != V.PAWN) {
26 // The piece must be a pawn about to promote.
27 const color = this.turn;
28 const beforeLastRank = (color == 'w' ? 1 : 0);
29 const forward = (color == 'w' ? -1 : 1);
30 let moves = [];
31 if (this.board[x + forward][y] == V.EMPTY) {
32 moves.push(
33 this.getBasicMove(
34 [x, y], [x + forward], { c: color, p: this.p2play[L-1] })
35 );
36 }
37 for (let shift of [-1, 1]) {
38 const [i, j] = [x + forward, y + shift];
39 if (
40 V.OnBoard(i, j) &&
41 this.board[i][j] != V.EMPTY &&
42 this.getColor(i, j) != color
43 ) {
44 moves.push(
45 this.getBasicMove(
46 [x, y], [i, j], { c: color, p: this.p2play[L-1] })
47 );
48 }
49 }
50 return moves;
51 }
52 if (piece != this.p2play[L-1])
68971030 53 // The piece type must match last p2play
68971030 54 return [];
68971030
BA
55 return super.getPotentialMovesFrom([x, y]);
56 }
57
58 setOtherVariables(fen) {
59 super.setOtherVariables(fen);
60 this.p2play = [];
61 this.subTurn = 1;
62 }
63
64 filterValid(moves) {
65 return moves;
66 }
67
68 getCheckSquares() {
69 return [];
70 }
71
72 getCurrentScore() {
73 const color = this.turn;
74 if (this.kingPos[color][0] < 0) return (color == 'w' ? "0-1" : "1-0");
75 return "*";
76 }
77
78 play(move) {
79 if (this.subTurn == 1) {
80 this.subTurn = 2;
81 this.p2play.push(move.appear[0].p);
82 return;
83 }
84 // Subturn == 2 means the (dice-constrained) move is played
85 move.flags = JSON.stringify(this.aggregateFlags());
86 V.PlayOnBoard(this.board, move);
87 this.epSquares.push(this.getEpSquare(move));
88 this.movesCount++;
89 this.turn = V.GetOppCol(this.turn);
90 this.subTurn = 1;
91 this.postPlay(move);
92 }
93
94 postPlay(move) {
95 if (move.vanish.length == 2 && move.vanish[1].p == V.KING)
96 this.kingPos[move.vanish[1].c] = [-1, -1];
97 // Castle flags for captured king won't be updated (not important...)
98 super.postPlay(move);
99 }
100
101 undo(move) {
102 if (this.subTurn == 2) {
103 this.subTurn = 1;
104 this.p2play.pop();
105 return;
106 }
107 this.disaggregateFlags(JSON.parse(move.flags));
108 V.UndoOnBoard(this.board, move);
109 this.epSquares.pop();
110 this.movesCount--;
111 this.turn = V.GetOppCol(this.turn);
112 this.subTurn = 2;
113 this.postUndo(move);
114 }
115
116 postUndo(move) {
117 if (move.vanish.length == 2 && move.vanish[1].p == V.KING)
118 this.kingPos[move.vanish[1].c] = [move.vanish[1].x, move.vanish[1].y];
119 super.postUndo(move);
120 }
121
122 getRandPieceMove() {
123 // For current turn, find pieces which can move and roll a dice
124 let canMove = {};
125 const color = this.turn;
126 for (let i=0; i<8; i++) {
127 for (let j=0; j<8; j++) {
128 if (this.board[i][j] != V.EMPTY && this.getColor(i, j) == color) {
129 const piece = this.getPiece(i, j);
130 if (
131 !canMove[piece] &&
132 super.getPotentialMovesFrom([i, j]).length > 0
133 ) {
134 canMove[piece] = [i, j];
135 }
136 }
137 }
138 }
139 const options = Object.keys(canMove);
140 const randPiece = options[randInt(options.length)];
141 return (
142 new Move({
143 appear: [{ p: randPiece }],
144 vanish: [],
145 start: { x: -1, y: -1 },
146 end: { x: canMove[randPiece][0], y: canMove[randPiece][1] }
147 })
148 );
149 }
150
151 // Random mover
152 getComputerMove() {
153 const toPlay = this.getRandPieceMove();
154 this.play(toPlay);
155 const moves = this.getAllValidMoves();
156 const choice = moves[randInt(moves.length)];
157 this.undo(toPlay);
158 return [toPlay, choice];
159 }
160
161 getNotation(move) {
162 if (this.subTurn == 1) return move.appear[0].p.toUpperCase();
163 return super.getNotation(move);
164 }
165};