1 import { ChessRules
, Move
, PiPo
} from "@/base_rules";
3 export class Stealthbomb1Rules
extends ChessRules
{
5 static get CanAnalyze() {
9 static get SomeHiddenMoves() {
13 static get BOMB_DECODE() {
23 static get BOMB_CODE() {
35 return ChessRules
.PIECES
.concat(Object
.keys(V
.BOMB_DECODE
));
39 const piece
= this.board
[i
][j
].charAt(1);
41 ChessRules
.PIECES
.includes(piece
) ||
42 // 'side' is used to determine what I see: normal or "loaded" piece?
43 this.getColor(i
, j
) == this.side
47 // Loaded piece, but no right to view it
48 return V
.BOMB_DECODE
[piece
];
51 getPpath(b
, color
, score
) {
52 if (Object
.keys(V
.BOMB_DECODE
).includes(b
[1])) {
53 // Supposed to be hidden.
54 if (score
== "*" && (!color
|| color
!= b
[0]))
55 return b
[0] + V
.BOMB_DECODE
[b
[1]];
56 return "Stealthbomb/" + b
;
61 hoverHighlight([x
, y
]) {
64 this.movesCount
<= 1 &&
66 (c
== 'w' && x
>= 6) ||
74 this.movesCount
<= 1 ||
75 // TODO: next line theoretically shouldn't be required...
76 (this.movesCount
== 2 && this.getColor(x
, y
) != this.turn
)
80 // Initiate the game by choosing a square for the bomb:
84 this.movesCount
>= 2 ||
86 (c
== 'w' && square
[0] < 6) ||
87 (c
== 'b' && square
[0] > 1)
92 const [x
, y
] = square
;
93 const piece
= super.getPiece(x
, y
);
95 appear: [ new PiPo({ x: x
, y: y
, c: c
, p: V
.BOMB_CODE
[piece
] }) ],
96 vanish: [ new PiPo({ x: x
, y: y
, c: c
, p: piece
}) ],
97 start: { x: -1, y: -1 },
98 end: { x: x
, y: y
, noHighlight: true }
102 getPotentialMovesFrom([x
, y
]) {
103 if (this.movesCount
<= 1) {
104 const setup
= this.doClick([x
, y
]);
105 return (!setup
? [] : [setup
]);
107 let moves
= super.getPotentialMovesFrom([x
, y
]);
109 // Add bomb explosion
110 if (Object
.keys(V
.BOMB_DECODE
).includes(this.board
[x
][y
][1])) {
113 vanish: [ new PiPo({ x: x
, y: y
, c: c
, p: this.board
[x
][y
][1] }) ],
114 end: { x: this.kingPos
[c
][0], y: this.kingPos
[c
][1] }
116 for (let s
of V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
])) {
117 let [i
, j
] = [x
+ s
[0], y
+ s
[1]];
118 if (V
.OnBoard(i
, j
) && this.board
[i
][j
] != V
.EMPTY
) {
123 c: this.getColor(i
, j
),
124 p: this.board
[i
][j
][1]
134 // NOTE: a lot of copy-paste from Atomic from here.
136 if (this.movesCount
>= 3) {
137 super.postPlay(move);
138 if (move.appear
.length
== 0) {
140 const firstRank
= { w: 7, b: 0 };
141 for (let c
of ["w", "b"]) {
142 // Did we explode king of color c ?
144 Math
.abs(this.kingPos
[c
][0] - move.start
.x
) <= 1 &&
145 Math
.abs(this.kingPos
[c
][1] - move.start
.y
) <= 1
147 this.kingPos
[c
] = [-1, -1];
148 this.castleFlags
[c
] = [8, 8];
151 // Now check if init rook(s) exploded
152 if (Math
.abs(move.start
.x
- firstRank
[c
]) <= 1) {
153 if (Math
.abs(move.start
.y
- this.castleFlags
[c
][0]) <= 1)
154 this.castleFlags
[c
][0] = 8;
155 if (Math
.abs(move.start
.y
- this.castleFlags
[c
][1]) <= 1)
156 this.castleFlags
[c
][1] = 8;
165 if (this.movesCount
>= 2) {
166 super.postUndo(move);
168 const oppCol
= V
.GetOppCol(c
);
169 if ([this.kingPos
[c
][0], this.kingPos
[oppCol
][0]].some(e
=> e
< 0)) {
170 // Last move exploded some king..
171 for (let psq
of move.vanish
) {
173 this.kingPos
[psq
.c
== c
? c : oppCol
] = [psq
.x
, psq
.y
];
180 const oppCol
= V
.GetOppCol(color
);
182 // If our king disappeared, move is not valid
183 if (this.kingPos
[color
][0] < 0) res
= true;
184 // If opponent king disappeared, move is valid
185 else if (this.kingPos
[oppCol
][0] < 0) res
= false;
186 // Otherwise, if we remain under check, move is not valid
187 else res
= this.isAttacked(this.kingPos
[color
], oppCol
);
192 const color
= this.turn
;
195 this.kingPos
[color
][0] >= 0 && //king might have exploded
196 this.isAttacked(this.kingPos
[color
], V
.GetOppCol(color
))
198 res
= [JSON
.parse(JSON
.stringify(this.kingPos
[color
]))];
204 const color
= this.turn
;
205 const kp
= this.kingPos
[color
];
208 return color
== "w" ? "0-1" : "1-0";
209 if (this.atLeastOneMove()) return "*";
210 if (!this.isAttacked(kp
, V
.GetOppCol(color
))) return "1/2";
211 return color
== "w" ? "0-1" : "1-0"; //checkmate
215 if (this.movesCount
<= 1) return "Bomb?";
217 if (move.end
.x
== this.kingPos
[c
][0] && move.end
.y
== this.kingPos
[c
][1])
218 return V
.CoordsToSquare(move.start
) + "~X";
219 if (Object
.keys(V
.BOMB_DECODE
).includes(move.vanish
[0].p
)) {
220 let cpMove
= JSON
.parse(JSON
.stringify(move));
221 cpMove
.vanish
[0].p
= V
.BOMB_DECODE
[move.vanish
[0].p
];
222 if (Object
.keys(V
.BOMB_DECODE
).includes(move.appear
[0].p
))
223 cpMove
.appear
[0].p
= V
.BOMB_DECODE
[move.appear
[0].p
];
224 return super.getNotation(cpMove
);
226 return super.getNotation(move);