1 import ChessRules
from "/base_rules.js";
2 import { randInt
, shuffle
} from "@/utils/alea";
3 import { ArrayFun
} from "@/utils/array";
5 export default class AmbiguousRules
extends ChessRules
{
13 setOtherVariables(fenParsed
) {
14 super.setOtherVariables(fenParsed
);
15 if (this.movesCount
== 0)
21 genRandInitFen(seed
) {
22 const gr
= new GiveawayRules(
23 {mode: "suicide", options: this.options
, genFenOnly: true});
24 return gr
.genRandInitFen(seed
);
27 // Subturn 1: play a move for the opponent on the designated square.
28 // Subturn 2: play a move for me (which just indicate a square).
29 getPotentialMovesFrom([x
, y
]) {
30 const color
= this.turn
;
31 const oppCol
= V
.GetOppCol(color
);
32 if (this.subTurn
== 2) {
33 // Just play a normal move (which in fact only indicate a square)
36 super.getPotentialMovesFrom([x
, y
])
38 // Filter promotions: keep only one, since no choice now.
39 if (m
.appear
[0].p
!= m
.vanish
[0].p
) {
40 const hash
= V
.CoordsToSquare(m
.start
) + V
.CoordsToSquare(m
.end
);
41 if (!movesHash
[hash
]) {
42 movesHash
[hash
] = true;
50 if (m
.vanish
.length
== 1) m
.appear
[0].p
= V
.GOAL
;
51 else m
.appear
[0].p
= V
.TARGET_CODE
[m
.vanish
[1].p
];
52 m
.appear
[0].c
= oppCol
;
58 // At subTurn == 1, play a targeted move for opponent
59 // Search for target (we could also have it in a stack...)
60 let target
= { x: -1, y: -1 };
61 outerLoop: for (let i
= 0; i
< V
.size
.x
; i
++) {
62 for (let j
= 0; j
< V
.size
.y
; j
++) {
63 if (this.board
[i
][j
] != V
.EMPTY
) {
64 const piece
= this.board
[i
][j
][1];
67 Object
.keys(V
.TARGET_DECODE
).includes(piece
)
69 target
= { x: i
, y: j
};
75 // TODO: could be more efficient than generating all moves.
77 const emptyTarget
= (this.board
[target
.x
][target
.y
][1] == V
.GOAL
);
78 if (emptyTarget
) this.board
[target
.x
][target
.y
] = V
.EMPTY
;
79 let moves
= super.getPotentialMovesFrom([x
, y
]);
81 this.board
[target
.x
][target
.y
] = color
+ V
.GOAL
;
92 return moves
.filter(m
=> m
.end
.x
== target
.x
&& m
.end
.y
== target
.y
);
96 const color
= this.getColor(x
, y
);
98 (this.subTurn
== 1 && ![this.turn
, this.playerColor
].includes(color
)) ||
99 (this.subTurn
== 2 && super.canIplay(x
, y
))
103 // Code for empty square target
108 static get TARGET_DECODE() {
119 static get TARGET_CODE() {
135 // Since there are no checks this seems true (same as for Magnetic...)
144 // This function is only called at subTurn 1
145 const color
= V
.GetOppCol(this.turn
);
146 if (this.kingPos
[color
][0] < 0) return (color
== 'w' ? "0-1" : "1-0");
151 let kingCaptured
= false;
152 if (this.subTurn
== 1) {
154 this.epSquares
.push(this.getEpSquare(move));
155 kingCaptured
= this.kingPos
[this.turn
][0] < 0;
157 if (kingCaptured
) move.kingCaptured
= true;
158 V
.PlayOnBoard(this.board
, move);
159 if (this.subTurn
== 2 || kingCaptured
) {
160 this.turn
= V
.GetOppCol(this.turn
);
163 if (!kingCaptured
) this.subTurn
= 3 - this.subTurn
;