1 import { ChessRules
, Move
} from "@/base_rules";
2 import { randInt
} from "@/utils/alea";
4 export class DiceRules
extends ChessRules
{
11 variable: "randomness",
14 { label: "Deterministic", value: 0 },
15 { label: "Symmetric random", value: 1 },
16 { label: "Asymmetric random", value: 2 }
23 static get CanAnalyze() {
27 static ParseFen(fen
) {
28 const fenParts
= fen
.split(" ");
30 ChessRules
.ParseFen(fen
),
31 { toplay: fenParts
[5] }
35 setOtherVariables(fen
) {
36 super.setOtherVariables(fen
);
38 const toplay
= V
.ParseFen(fen
).toplay
;
39 if (toplay
!= "-") this.p2play
.push(toplay
);
43 return super.getFen() + " " + this.getToplayFen();
47 return super.getFenForRepeat() + "_" + this.getToplayFen();
51 const L
= this.p2play
.length
;
52 return (L
> 0 ? this.p2play
[L
-1] : "-");
55 static GenRandInitFen(options
) {
56 return ChessRules
.GenRandInitFen(options
) + " -";
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
];
68 this.board
[i
][j
] != V
.EMPTY
&&
69 this.getColor(i
, j
) == oppCol
77 [V
.KING
, V
.QUEEN
].includes(piece
)
78 ? V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
])
80 for (let s
of steps
) {
81 const [i
, j
] = [x
+ s
[0], y
+ s
[1]];
84 (this.board
[i
][j
] == V
.EMPTY
|| this.getColor(i
, j
) == oppCol
)
94 // Find pieces which can move and roll a dice
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
];
105 const options
= Object
.keys(canMove
);
106 const randPiece
= options
[randInt(options
.length
)];
107 return [randPiece
, canMove
[randPiece
]];
110 getPotentialMovesFrom([x
, y
]) {
111 const color
= this.turn
;
112 let moves
= undefined;
113 if (this.movesCount
== 0) moves
= super.getPotentialMovesFrom([x
, y
]);
115 const L
= this.p2play
.length
; //L is >= 1
116 const piece
= this.getPiece(x
, y
);
119 this.p2play
[L
-1] != V
.PAWN
&&
120 ((color
== 'w' && x
== 1) || (color
== 'b' && x
== 6))
122 // The piece is a pawn about to promote
123 const destX
= (color
== 'w' ? 0 : 7);
125 if (this.board
[destX
][y
] == V
.EMPTY
) {
128 [x
, y
], [destX
, y
], { c: color
, p: this.p2play
[L
-1] })
131 for (let shift
of [-1, 1]) {
132 const [i
, j
] = [destX
, y
+ shift
];
135 this.board
[i
][j
] != V
.EMPTY
&&
136 this.getColor(i
, j
) != color
140 [x
, y
], [i
, j
], { c: color
, p: this.p2play
[L
-1] })
145 else if (piece
!= this.p2play
[L
-1])
146 // The piece type must match last p2play
148 else moves
= super.getPotentialMovesFrom([x
, y
]);
150 // Decide which piece the opponent will play:
151 const oppCol
= V
.GetOppCol(color
);
153 V
.PlayOnBoard(this.board
, m
);
154 const [piece
, square
] = this.getRandPiece(oppCol
);
155 m
.start
.toplay
= square
;
157 V
.UndoOnBoard(this.board
, m
);
171 const color
= this.turn
;
172 if (this.kingPos
[color
][0] < 0) return (color
== 'w' ? "0-1" : "1-0");
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);
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);
191 static get SEARCH_DEPTH() {
196 return super.getNotation(move) + "/" + move.end
.p
.toUpperCase();