Commit | Line | Data |
---|---|---|
68971030 BA |
1 | import { ChessRules, Move } from "@/base_rules"; |
2 | import { randInt } from "@/utils/alea"; | |
3 | ||
4 | export class DiceRules extends ChessRules { | |
7e8a7ea1 | 5 | |
68971030 | 6 | static get CanAnalyze() { |
0ada7ac5 | 7 | return false; |
68971030 BA |
8 | } |
9 | ||
6e0f2842 BA |
10 | static ParseFen(fen) { |
11 | const fenParts = fen.split(" "); | |
12 | return Object.assign( | |
13 | ChessRules.ParseFen(fen), | |
14 | { toplay: fenParts[5] } | |
15 | ); | |
68971030 BA |
16 | } |
17 | ||
6e0f2842 BA |
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 | ||
c98f15e7 | 29 | getFenForRepeat() { |
6e0f2842 BA |
30 | return super.getFenForRepeat() + "_" + this.getToplayFen(); |
31 | } | |
32 | ||
33 | getToplayFen() { | |
68971030 | 34 | const L = this.p2play.length; |
6e0f2842 BA |
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) { | |
0ada7ac5 | 45 | const forward = (color == 'w' ? -1 : 1); |
6e0f2842 | 46 | if (this.board[x + forward][y] == V.EMPTY) return true; |
0ada7ac5 BA |
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 && | |
6e0f2842 | 52 | this.getColor(i, j) == oppCol |
0ada7ac5 | 53 | ) { |
6e0f2842 BA |
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) { | |
0ada7ac5 BA |
109 | moves.push( |
110 | this.getBasicMove( | |
6e0f2842 | 111 | [x, y], [destX, y], { c: color, p: this.p2play[L-1] }) |
0ada7ac5 BA |
112 | ); |
113 | } | |
6e0f2842 BA |
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 | } | |
0ada7ac5 | 127 | } |
6e0f2842 BA |
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]); | |
0ada7ac5 | 132 | } |
6e0f2842 BA |
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; | |
c98f15e7 | 139 | m.end.p = piece; |
6e0f2842 BA |
140 | V.UndoOnBoard(this.board, m); |
141 | }); | |
142 | return moves; | |
68971030 BA |
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 | ||
68971030 | 159 | postPlay(move) { |
c98f15e7 | 160 | this.p2play.push(move.end.p); |
68971030 BA |
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 | ||
68971030 | 167 | postUndo(move) { |
6e0f2842 | 168 | this.p2play.pop(); |
68971030 BA |
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 | ||
6e0f2842 BA |
174 | static get SEARCH_DEPTH() { |
175 | return 1; | |
68971030 BA |
176 | } |
177 | ||
178 | getNotation(move) { | |
c98f15e7 | 179 | return super.getNotation(move) + "/" + move.end.p.toUpperCase(); |
68971030 | 180 | } |
7e8a7ea1 | 181 | |
68971030 | 182 | }; |