'n': 'w',
'b': 'f',
'q': 'c',
- 'k': 'k'
+ 'k': 'm',
+ 'p': 'z'
},
// Nutty Knights
'N': {
'n': 'i',
'b': 't',
'q': 'l',
- 'k': 'k'
+ 'k': 'e',
+ 'p': 'v'
},
// Remarkable Rookies
'R': {
'n': 'y',
'b': 'h',
'q': 'o',
- 'k': 'k'
+ 'k': 'a',
+ 'p': 'u'
}
};
}
static GenRandInitFen(options) {
const baseFen = ChessRules.GenRandInitFen(options.randomness);
- let blackLine = baseFen.substr(0, 8);
+ let blackLine = baseFen.substr(0, 8), blackPawns = "pppppppp";
if (options.army2 != 'F') {
blackLine = blackLine.split('')
.map(p => V.PiecesMap[options.army2][p]).join('');
+ blackPawns = V.PiecesMap[options.army2]['p'].repeat(8);
}
- let whiteLine = baseFen.substr(35, 8);
+ let whiteLine = baseFen.substr(35, 8), whitePawns = "PPPPPPPP";
if (options.army1 != 'F') {
whiteLine = whiteLine.split('')
.map(p => V.PiecesMap[options.army1][p.toLowerCase()])
.join('').toUpperCase();
+ whitePawns = V.PiecesMap[options.army1]['p'].toUpperCase().repeat(8);
}
return (
- blackLine + baseFen.substring(8, 35) + whiteLine +
+ blackLine + "/" + blackPawns +
+ baseFen.substring(17, 26) +
+ whitePawns + "/" + whiteLine +
baseFen.substr(43) + " " + options.army1 + options.army2
);
}
this.army2 = armies.charAt(1);
}
+ scanKings(fen) {
+ this.kingPos = { w: [-1, -1], b: [-1, -1] };
+ const fenRows = V.ParseFen(fen).position.split("/");
+ for (let i = 0; i < fenRows.length; i++) {
+ let k = 0;
+ for (let j = 0; j < fenRows[i].length; j++) {
+ const newChar = fenRows[i].charAt(j);
+ if (['a', 'e', 'k', 'm'].includes(newChar))
+ this.kingPos["b"] = [i, k];
+ else if (['A', 'E', 'K', 'M'].includes(newChar))
+ this.kingPos["w"] = [i, k];
+ else {
+ const num = parseInt(fenRows[i].charAt(j), 10);
+ if (!isNaN(num)) k += num - 1;
+ }
+ k++;
+ }
+ }
+ }
+
static ParseFen(fen) {
return Object.assign(
{ armies: fen.split(" ")[5] },
static IsGoodFen(fen) {
if (!ChessRules.IsGoodFen(fen)) return false;
const armies = V.ParseFen(fen).armies;
- if (!armies || !armies.match(/^[CNRF]{2,2}$/)) return false;
- return true;
+ return (!!armies && armies.match(/^[CNRF]{2,2}$/));
}
getFen() {
static get C_QUEEN() {
return 'c';
}
+ static get C_KING() {
+ return 'm';
+ }
+ static get C_PAWN() {
+ return 'z';
+ }
static get N_ROOK() {
return 'g';
}
static get N_QUEEN() {
return 'l';
}
+ static get N_KING() {
+ return 'e';
+ }
+ static get N_PAWN() {
+ return 'v';
+ }
static get R_ROOK() {
return 's';
}
static get R_QUEEN() {
return 'o';
}
+ static get R_KING() {
+ return 'a';
+ }
+ static get R_PAWN() {
+ return 'u';
+ }
+
+ getPiece(x, y) {
+ const p = this.board[x][y][1];
+ if (['u', 'v', 'z'].includes(p)) return 'p';
+ if (['a', 'e', 'm'].includes(p)) return 'k';
+ return p;
+ }
static get PIECES() {
return ChessRules.PIECES.concat(
- [V.C_ROOK, V.C_KNIGHT, V.C_BISHOP, V.C_QUEEN]).concat(
- [V.N_ROOK, V.N_KNIGHT, V.N_BISHOP, V.N_QUEEN]).concat(
- [V.R_ROOK, V.R_KNIGHT, V.R_BISHOP, V.R_QUEEN]);
+ [
+ V.C_ROOK, V.C_KNIGHT, V.C_BISHOP, V.C_QUEEN, V.C_KING, V.C_PAWN,
+ V.N_ROOK, V.N_KNIGHT, V.N_BISHOP, V.N_QUEEN, V.N_KING, V.N_PAWN,
+ V.R_ROOK, V.R_KNIGHT, V.R_BISHOP, V.R_QUEEN, V.R_KING, V.R_PAWN
+ ]
+ );
+ }
+
+ getEpSquare(moveOrSquare) {
+ if (!moveOrSquare) return undefined; //TODO: necessary line?!
+ if (typeof moveOrSquare === "string") {
+ const square = moveOrSquare;
+ if (square == "-") return undefined;
+ return V.SquareToCoords(square);
+ }
+ // Argument is a move:
+ const move = moveOrSquare;
+ const s = move.start,
+ e = move.end;
+ if (
+ s.y == e.y &&
+ Math.abs(s.x - e.x) == 2 &&
+ ['p', 'u', 'v'].includes(move.appear[0].p)
+ ) {
+ return {
+ x: (s.x + e.x) / 2,
+ y: s.y
+ };
+ }
+ return undefined; //default
}
getPotentialMovesFrom(sq) {
}
getPotentialN_knightMoves(sq) {
- const backward = (this.turn == 'w' ? 1 : -1);
- const kingSteps = [
- [0, -1], [0, 1], [backward, -1], [backward, 0], [backward, 1]
- ];
return (
this.getSlideNJumpMoves(sq, V.steps.$n, 1).concat(
- this.getSlideNJumpMoves(sq, kingSteps, 1))
+ this.getSlideNJumpMoves(sq, V.steps.f, 1))
);
}
}
isAttackedByN_knight(sq, color) {
- const backward = (color == 'w' ? -1 : 1);
- const kingSteps = [
- [0, -1], [0, 1], [backward, -1], [backward, 0], [backward, 1]
- ];
return (
- this.isAttackedBySlideNJump(sq, color, V.N_KNIGHT, V.steps.$n) ||
- this.isAttackedBySlideNJump(sq, color, V.N_KNIGHT, kingSteps, 1)
+ this.isAttackedBySlideNJump(sq, color, V.N_KNIGHT, V.steps.$n, 1) ||
+ this.isAttackedBySlideNJump(sq, color, V.N_KNIGHT, V.steps.f, 1)
);
}
return super.isAttackedByQueen(sq, color);
}
+ postPlay(move) {
+ const c = V.GetOppCol(this.turn);
+ const piece = move.appear[0].p;
+ // Update king position + flags
+ if (['k', 'a', 'e', 'm'].includes(piece)) {
+ this.kingPos[c][0] = move.appear[0].x;
+ this.kingPos[c][1] = move.appear[0].y;
+ this.castleFlags[c] = [V.size.y, V.size.y];
+ }
+ // Next call is still required because the king may eat an opponent's rook
+ // TODO: castleFlags will be turned off twice then.
+ super.updateCastleFlags(move, piece);
+ }
+
+ postUndo(move) {
+ // (Potentially) Reset king position
+ const c = this.getColor(move.start.x, move.start.y);
+ const piece = move.appear[0].p;
+ if (['k', 'a', 'e', 'm'].includes(piece))
+ this.kingPos[c] = [move.start.x, move.start.y];
+ }
+
static get VALUES() {
return Object.assign(
{
return 2;
}
+ getNotation(move) {
+ let notation = super.getNotation(move);
+ if (['u', 'v', 'z'].includes(move.appear[0].p))
+ notation = notation.slice(0, -2);
+ return notation;
+ }
+
};