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() {
22 static get BOMB_CODE() {
33 return ChessRules
.PIECES
.concat(Object
.keys(V
.BOMB_DECODE
));
37 const piece
= this.board
[i
][j
].charAt(1);
39 ChessRules
.PIECES
.includes(piece
) ||
40 // 'side' is used to determine what I see: normal or "loaded" piece?
41 this.getColor(i
, j
) == this.side
45 // Loaded piece, but no right to view it
46 return V
.BOMB_DECODE
[piece
];
49 getPpath(b
, color
, score
) {
50 if (Object
.keys(V
.BOMB_DECODE
).includes(b
[1])) {
51 // Supposed to be hidden.
52 if (score
== "*" && (!color
|| color
!= b
[0]))
53 return b
[0] + V
.BOMB_DECODE
[b
[1]];
54 return "Stealthbomb/" + b
;
59 hoverHighlight([x
, y
]) {
62 this.movesCount
<= 1 &&
64 (c
== 'w' && x
>= 6) ||
72 this.movesCount
<= 1 ||
73 // TODO: next line theoretically shouldn't be required...
74 (this.movesCount
== 2 && this.getColor(x
, y
) != this.turn
)
78 // Initiate the game by choosing a piece holding the bomb:
82 this.movesCount
>= 2 ||
84 (c
== 'w' && square
[0] < 6) ||
85 (c
== 'b' && square
[0] > 1)
90 const [x
, y
] = square
;
91 const piece
= super.getPiece(x
, y
);
92 if (piece
== V
.KING
) return null; //no bomb on king!
94 appear: [ new PiPo({ x: x
, y: y
, c: c
, p: V
.BOMB_CODE
[piece
] }) ],
95 vanish: [ new PiPo({ x: x
, y: y
, c: c
, p: piece
}) ],
96 start: { x: -1, y: -1 },
97 end: { x: x
, y: y
, noHighlight: true }
101 getPotentialMovesFrom([x
, y
]) {
102 if (this.movesCount
<= 1) {
103 const setup
= this.doClick([x
, y
]);
104 return (!setup
? [] : [setup
]);
106 let moves
= super.getPotentialMovesFrom([x
, y
]);
108 // Add bomb explosion
109 if (Object
.keys(V
.BOMB_DECODE
).includes(this.board
[x
][y
][1])) {
112 vanish: [ new PiPo({ x: x
, y: y
, c: c
, p: this.board
[x
][y
][1] }) ],
113 end: { x: this.kingPos
[c
][0], y: this.kingPos
[c
][1] }
115 for (let s
of V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
])) {
116 let [i
, j
] = [x
+ s
[0], y
+ s
[1]];
117 if (V
.OnBoard(i
, j
) && this.board
[i
][j
] != V
.EMPTY
) {
122 c: this.getColor(i
, j
),
123 p: this.board
[i
][j
][1]
133 // NOTE: a lot of copy-paste from Atomic from here.
135 if (this.movesCount
>= 3) {
136 super.postPlay(move);
137 if (move.appear
.length
== 0) {
139 const firstRank
= { w: 7, b: 0 };
140 for (let c
of ["w", "b"]) {
141 // Did we explode king of color c ?
143 Math
.abs(this.kingPos
[c
][0] - move.start
.x
) <= 1 &&
144 Math
.abs(this.kingPos
[c
][1] - move.start
.y
) <= 1
146 this.kingPos
[c
] = [-1, -1];
147 this.castleFlags
[c
] = [8, 8];
150 // Now check if init rook(s) exploded
151 if (Math
.abs(move.start
.x
- firstRank
[c
]) <= 1) {
152 if (Math
.abs(move.start
.y
- this.castleFlags
[c
][0]) <= 1)
153 this.castleFlags
[c
][0] = 8;
154 if (Math
.abs(move.start
.y
- this.castleFlags
[c
][1]) <= 1)
155 this.castleFlags
[c
][1] = 8;
164 if (this.movesCount
>= 2) {
165 super.postUndo(move);
167 const oppCol
= V
.GetOppCol(c
);
168 if ([this.kingPos
[c
][0], this.kingPos
[oppCol
][0]].some(e
=> e
< 0)) {
169 // Last move exploded some king..
170 for (let psq
of move.vanish
) {
172 this.kingPos
[psq
.c
== c
? c : oppCol
] = [psq
.x
, psq
.y
];
179 const oppCol
= V
.GetOppCol(color
);
181 // If our king disappeared, move is not valid
182 if (this.kingPos
[color
][0] < 0) res
= true;
183 // If opponent king disappeared, move is valid
184 else if (this.kingPos
[oppCol
][0] < 0) res
= false;
185 // Otherwise, if we remain under check, move is not valid
186 else res
= this.isAttacked(this.kingPos
[color
], oppCol
);
191 const color
= this.turn
;
194 this.kingPos
[color
][0] >= 0 && //king might have exploded
195 this.isAttacked(this.kingPos
[color
], V
.GetOppCol(color
))
197 res
= [JSON
.parse(JSON
.stringify(this.kingPos
[color
]))];
203 const color
= this.turn
;
204 const kp
= this.kingPos
[color
];
207 return color
== "w" ? "0-1" : "1-0";
208 if (this.atLeastOneMove()) return "*";
209 if (!this.isAttacked(kp
, V
.GetOppCol(color
))) return "1/2";
210 return color
== "w" ? "0-1" : "1-0"; //checkmate
214 if (this.movesCount
<= 1) return "Bomb?";
216 if (move.end
.x
== this.kingPos
[c
][0] && move.end
.y
== this.kingPos
[c
][1])
217 return V
.CoordsToSquare(move.start
) + "~X";
218 if (Object
.keys(V
.BOMB_DECODE
).includes(move.vanish
[0].p
)) {
219 let cpMove
= JSON
.parse(JSON
.stringify(move));
220 cpMove
.vanish
[0].p
= V
.BOMB_DECODE
[move.vanish
[0].p
];
221 if (Object
.keys(V
.BOMB_DECODE
).includes(move.appear
[0].p
))
222 cpMove
.appear
[0].p
= V
.BOMB_DECODE
[move.appear
[0].p
];
223 return super.getNotation(cpMove
);
225 return super.getNotation(move);