// 5) Check sentry push (if any)
if (
fenParsed.sentrypush != "-" &&
- !fenParsed.sentrypush.match(/^([a-h][1-8],?)+$/)
+ !fenParsed.sentrypush.match(/^([a-h][1-8]){2,2}$/)
) {
return false;
}
const L = this.sentryPush.length;
if (!this.sentryPush[L-1]) return "-";
let res = "";
- this.sentryPush[L-1].forEach(coords =>
- res += V.CoordsToSquare(coords) + ",");
- return res.slice(0, -1);
+ const spL = this.sentryPush[L-1].length;
+ // Condensate path: just need initial and final squares:
+ return [0, spL - 1]
+ .map(i => V.CoordsToSquare(this.sentryPush[L-1][i]))
+ .join("");
}
setOtherVariables(fen) {
const parsedFen = V.ParseFen(fen);
if (parsedFen.sentrypush == "-") this.sentryPush = [null];
else {
- this.sentryPush = [
- parsedFen.sentrypush.split(",").map(sq => {
- return V.SquareToCoords(sq);
- })
- ];
+ // Expand init + dest squares into a full path:
+ const init = V.SquareToCoords(parsedFen.sentrypush.substr(0, 2)),
+ dest = V.SquareToCoords(parsedFen.sentrypush.substr(2));
+ let newPath = [init];
+ const delta = ['x', 'y'].map(i => Math.abs(dest[i] - init[i]));
+ // Check that it's not a knight movement:
+ if (delta[0] == 0 || delta[1] == 0 || delta[0] == delta[1]) {
+ const step = ['x', 'y'].map((i, idx) => {
+ return (dest[i] - init[i]) / delta[idx] || 0
+ });
+ let x = init.x + step[0],
+ y = init.y + step[1];
+ while (x != dest.x || y != dest.y) {
+ newPath.push({ x: x, y: y });
+ x += step[0];
+ y += step[1];
+ }
+ }
+ newPath.push(dest);
+ this.sentryPush = [newPath];
}
}
}
getPotentialMovesFrom([x, y]) {
- // At subTurn == 2, jailers aren't effective (Jeff K)
const piece = this.getPiece(x, y);
const L = this.sentryPush.length;
+ // At subTurn == 2, jailers aren't effective (Jeff K)
if (this.subTurn == 1) {
const jsq = this.isImmobilized([x, y]);
if (!!jsq) {
return moves;
}
+ doClick(square) {
+ if (isNaN(square[0])) return null;
+ const L = this.sentryPush.length;
+ const [x, y] = [square[0], square[1]];
+ const color = this.turn;
+ if (
+ this.subTurn == 2 ||
+ this.board[x][y] == V.EMPTY ||
+ this.getPiece(x, y) != V.LANCER ||
+ this.getColor(x, y) != color ||
+ !!this.sentryPush[L-1]
+ ) {
+ return null;
+ }
+ // Stuck lancer?
+ const orientation = this.board[x][y][1];
+ const step = V.LANCER_DIRS[orientation];
+ if (!V.OnBoard(x + step[0], y + step[1])) {
+ let choices = [];
+ Object.keys(V.LANCER_DIRS).forEach(k => {
+ const dir = V.LANCER_DIRS[k];
+ if (
+ (dir[0] != step[0] || dir[1] != step[1]) &&
+ V.OnBoard(x + dir[0], y + dir[1])
+ ) {
+ choices.push(
+ new Move({
+ vanish: [
+ new PiPo({
+ x: x,
+ y: y,
+ c: color,
+ p: orientation
+ })
+ ],
+ appear: [
+ new PiPo({
+ x: x,
+ y: y,
+ c: color,
+ p: k
+ })
+ ],
+ start: { x: x, y : y },
+ end: { x: -1, y: -1 }
+ })
+ );
+ }
+ });
+ return choices;
+ }
+ return null;
+ }
+
// Obtain all lancer moves in "step" direction
getPotentialLancerMoves_aux([x, y], step, tr) {
let moves = [];
// Except if just after a push: allow all movements from init square then
const L = this.sentryPush.length;
const color = this.getColor(x, y);
+ const dirCode = this.board[x][y][1];
+ const curDir = V.LANCER_DIRS[dirCode];
if (!!this.sentryPush[L-1]) {
// Maybe I was pushed
const pl = this.sentryPush[L-1].length;
// I was pushed: allow all directions (for this move only), but
// do not change direction after moving, *except* if I keep the
// same orientation in which I was pushed.
- const curDir = V.LANCER_DIRS[this.board[x][y].charAt(1)];
+ // Also allow simple reorientation ("capturing king"):
+ if (!V.OnBoard(x + curDir[0], y + curDir[1])) {
+ const kp = this.kingPos[color];
+ let reorientMoves = [];
+ Object.keys(V.LANCER_DIRS).forEach(k => {
+ const dir = V.LANCER_DIRS[k];
+ if (
+ (dir[0] != curDir[0] || dir[1] != curDir[1]) &&
+ V.OnBoard(x + dir[0], y + dir[1])
+ ) {
+ reorientMoves.push(
+ new Move({
+ vanish: [
+ new PiPo({
+ x: x,
+ y: y,
+ c: color,
+ p: dirCode
+ })
+ ],
+ appear: [
+ new PiPo({
+ x: x,
+ y: y,
+ c: color,
+ p: k
+ })
+ ],
+ start: { x: x, y : y },
+ end: { x: kp[0], y: kp[1] }
+ })
+ );
+ }
+ });
+ Array.prototype.push.apply(moves, reorientMoves);
+ }
Object.values(V.LANCER_DIRS).forEach(step => {
const dirCode = Object.keys(V.LANCER_DIRS).find(k => {
return (
}
}
// I wasn't pushed: standard lancer move
- const dirCode = this.board[x][y][1];
const monodirMoves =
this.getPotentialLancerMoves_aux([x, y], V.LANCER_DIRS[dirCode]);
// Add all possible orientations aftermove except if I'm being pushed
});
return moves;
} else {
- // I'm pushed: add potential nudges
+ // I'm pushed: add potential nudges, except for current orientation
let potentialNudges = [];
for (let step of V.steps[V.ROOK].concat(V.steps[V.BISHOP])) {
if (
+ (step[0] != curDir[0] || step[1] != curDir[1]) &&
V.OnBoard(x + step[0], y + step[1]) &&
this.board[x + step[0]][y + step[1]] == V.EMPTY
) {
coord.x += step[0];
coord.y += step[1];
}
+ const L = this.sentryPush.length;
+ const pl = (!!this.sentryPush[L-1] ? this.sentryPush[L-1].length : 0);
for (let xy of lancerPos) {
const dir = V.LANCER_DIRS[this.board[xy.x][xy.y].charAt(1)];
- if (dir[0] == -step[0] && dir[1] == -step[1]) return true;
+ if (
+ (dir[0] == -step[0] && dir[1] == -step[1]) ||
+ // If the lancer was just pushed, this is an attack too:
+ (
+ !!this.sentryPush[L-1] &&
+ this.sentryPush[L-1][pl-1].x == xy.x &&
+ this.sentryPush[L-1][pl-1].y == xy.y
+ )
+ ) {
+ return true;
+ }
}
}
return false;
end: move.end
};
notation = super.getNotation(simpleMove);
- } else notation = super.getNotation(move);
+ }
+ else if (
+ move.appear.length > 0 &&
+ move.vanish[0].x == move.appear[0].x &&
+ move.vanish[0].y == move.appear[0].y
+ ) {
+ // Lancer in-place reorientation:
+ notation = "L" + V.CoordsToSquare(move.start) + ":R";
+ }
+ else notation = super.getNotation(move);
if (Object.keys(V.LANCER_DIRNAMES).includes(move.vanish[0].p))
// Lancer: add direction info
notation += "=" + V.LANCER_DIRNAMES[move.appear[0].p];