-class AntikingRules
+class AntikingRules extends ChessRules
{
- // Path to pieces
static getPpath(b)
{
return b[1]=='a' ? "Antiking/"+b : b;
}
static get ANTIKING() { return 'a'; }
+
+ initVariables(fen)
+ {
+ super.initVariables(fen);
+ this.antikingPos = {'w':[-1,-1], 'b':[-1,-1]};
+ const position = fen.split(" ")[0].split("/");
+ for (let i=0; i<position.length; i++)
+ {
+ let k = 0;
+ for (let j=0; j<position[i].length; j++)
+ {
+ switch (position[i].charAt(j))
+ {
+ case 'a':
+ this.antikingPos['b'] = [i,k];
+ break;
+ case 'A':
+ this.antikingPos['w'] = [i,k];
+ break;
+ default:
+ let num = parseInt(position[i].charAt(j));
+ if (!isNaN(num))
+ k += (num-1);
+ }
+ k++;
+ }
+ }
+ }
- canTake(color1, color2, [x,y])
+ canTake([x1,y1], [x2,y2])
{
- const piece = this.getPiece(x,y);
- return (piece != "a" && color1 != color2) || (piece == "a" && color1 == color2);
+ const piece1 = this.getPiece(x1,y1);
+ const piece2 = this.getPiece(x2,y2);
+ const color1 = this.getColor(x1,y1);
+ const color2 = this.getColor(x2,y2);
+ return piece2 != "a" &&
+ ((piece1 != "a" && color1 != color2) || (piece1 == "a" && color1 == color2));
}
getPotentialMovesFrom([x,y])
{
- let c = this.getColor(x,y);
switch (this.getPiece(x,y))
{
- case VariantRules.ANTIKING:
- return this.getPotentialAntikingMoves(x,y,c);
+ case V.ANTIKING:
+ return this.getPotentialAntikingMoves([x,y]);
default:
- return super.getPotentielMovesFrom([x,y]);
+ return super.getPotentialMovesFrom([x,y]);
}
}
-// TODO: generaliser (à moindre coût) base_rules ? Ou spécialiser variantes ?
-
- getPotentialAntikingMoves(x, y, c)
+ getPotentialAntikingMoves(sq)
{
- // TODO
+ return this.getSlideNJumpMoves(sq,
+ V.steps[V.ROOK].concat(V.steps[V.BISHOP]), "oneStep");
}
-// TODO: need to re-think some logic, since antikings capture same color
+ isAttacked(sq, colors)
+ {
+ return (super.isAttacked(sq, colors) || this.isAttackedByAntiking(sq, colors));
+ }
- isAttacked(sq, color)
+ isAttackedByKing([x,y], colors)
{
- return (this.isAttackedByPawn(sq, color)
- || this.isAttackedByRook(sq, color)
- || this.isAttackedByKnight(sq, color)
- || this.isAttackedByBishop(sq, color)
- || this.isAttackedByQueen(sq, color)
- || this.isAttackedByKing(sq, color)); //...
+ if (this.getPiece(x,y) == V.ANTIKING)
+ return false; //antiking is not attacked by king
+ return this.isAttackedBySlideNJump([x,y], colors, V.KING,
+ V.steps[V.ROOK].concat(V.steps[V.BISHOP]), "oneStep");
}
- isAttackedByAntiking(sq, color)
+ isAttackedByAntiking([x,y], colors)
{
- // TODO
+ if ([V.KING,V.ANTIKING].includes(this.getPiece(x,y)))
+ return false; //(anti)king is not attacked by antiking
+ return this.isAttackedBySlideNJump([x,y], colors, V.ANTIKING,
+ V.steps[V.ROOK].concat(V.steps[V.BISHOP]), "oneStep");
}
- underCheck(move, c)
+ underCheck(move)
{
- this.play(move);
- let res = this.isAttacked(this.kingPos[c], this.getOppCol(c));
- // TODO: also check that antiking is still in check
+ const c = this.turn;
+ const oppCol = this.getOppCol(c);
+ this.play(move)
+ let res = this.isAttacked(this.kingPos[c], [oppCol])
+ || !this.isAttacked(this.antikingPos[c], [oppCol]);
this.undo(move);
return res;
}
- getCheckSquares(move, c)
+ getCheckSquares(move)
{
+ let res = super.getCheckSquares(move);
this.play(move);
- // TODO
- let res = this.isAttacked(this.kingPos[c], this.getOppCol(c))
- ? [ JSON.parse(JSON.stringify(this.kingPos[c])) ] //need to duplicate!
- : [ ];
+ const c = this.turn;
+ if (!this.isAttacked(this.antikingPos[c], [this.getOppCol(c)]))
+ res.push(JSON.parse(JSON.stringify(this.antikingPos[c])));
this.undo(move);
return res;
}
- // Apply a move on board
- static PlayOnBoard(board, move)
- {
- for (let psq of move.vanish)
- board[psq.x][psq.y] = VariantRules.EMPTY;
- for (let psq of move.appear)
- board[psq.x][psq.y] = psq.c + psq.p;
- }
- // Un-apply the played move
- static UndoOnBoard(board, move)
- {
- for (let psq of move.appear)
- board[psq.x][psq.y] = VariantRules.EMPTY;
- for (let psq of move.vanish)
- board[psq.x][psq.y] = psq.c + psq.p;
- }
-
- // TODO: need antikingPos as well
updateVariables(move)
{
- // ...
+ super.updateVariables(move);
+ const piece = this.getPiece(move.start.x,move.start.y);
+ const c = this.getColor(move.start.x,move.start.y);
+ // Update antiking position
+ if (piece == V.ANTIKING)
+ {
+ this.antikingPos[c][0] = move.appear[0].x;
+ this.antikingPos[c][1] = move.appear[0].y;
+ }
}
unupdateVariables(move)
{
- // TODO
+ super.unupdateVariables(move);
+ const c = this.getColor(move.start.x,move.start.y);
+ if (this.getPiece(move.start.x,move.start.y) == V.ANTIKING)
+ this.antikingPos[c] = [move.start.x, move.start.y];
}
- checkGameEnd(color)
+ checkGameEnd()
{
- // TODO
- if (!this.isAttacked(this.kingPos[color], this.getOppCol(color)))
+ const color = this.turn;
+ const oppCol = this.getOppCol(color);
+ if (!this.isAttacked(this.kingPos[color], [oppCol])
+ && this.isAttacked(this.antikingPos[color], [oppCol]))
+ {
return "1/2";
+ }
return color == "w" ? "0-1" : "1-0";
}
- // Pieces values
static get VALUES() {
- return {
- 'p': 1,
- 'r': 5,
- 'n': 3,
- 'b': 3,
- 'q': 9,
- 'k': 1000,
- 'a': 1000
- };
+ return Object.assign(
+ ChessRules.VALUES,
+ { 'a': 1000 }
+ );
}
static GenRandInitFen()
{
- // TODO: no need all code, just add an antiking at rondom on 3rd ranks
- let pieces = [new Array(8), new Array(8)];
- // Shuffle pieces on first and last rank
- for (let c = 0; c <= 1; c++)
+ let pieces = { "w": new Array(8), "b": new Array(8) };
+ let antikingPos = { "w": -1, "b": -1 };
+ for (let c of ["w","b"])
{
let positions = _.range(8);
- // Get random squares for bishops
- let randIndex = 2 * _.random(3);
- let bishop1Pos = positions[randIndex];
- // The second bishop must be on a square of different color
- let randIndex_tmp = 2 * _.random(3) + 1;
- let bishop2Pos = positions[randIndex_tmp];
- // Remove chosen squares
+ // Get random squares for bishops, but avoid corners; because,
+ // if an antiking blocks a cornered bishop, it can never be checkmated
+ let randIndex = 2 * _.random(1,3);
+ const bishop1Pos = positions[randIndex];
+ let randIndex_tmp = 2 * _.random(2) + 1;
+ const bishop2Pos = positions[randIndex_tmp];
positions.splice(Math.max(randIndex,randIndex_tmp), 1);
positions.splice(Math.min(randIndex,randIndex_tmp), 1);
- // Get random squares for knights
randIndex = _.random(5);
- let knight1Pos = positions[randIndex];
+ const knight1Pos = positions[randIndex];
positions.splice(randIndex, 1);
randIndex = _.random(4);
- let knight2Pos = positions[randIndex];
+ const knight2Pos = positions[randIndex];
positions.splice(randIndex, 1);
- // Get random square for queen
randIndex = _.random(3);
- let queenPos = positions[randIndex];
+ const queenPos = positions[randIndex];
positions.splice(randIndex, 1);
- // Rooks and king positions are now fixed, because of the ordering rook-king-rook
- let rook1Pos = positions[0];
- let kingPos = positions[1];
- let rook2Pos = positions[2];
+ const rook1Pos = positions[0];
+ const kingPos = positions[1];
+ const rook2Pos = positions[2];
+
+ // Random squares for antikings
+ antikingPos[c] = _.random(7);
- // Finally put the shuffled pieces in the board array
pieces[c][rook1Pos] = 'r';
pieces[c][knight1Pos] = 'n';
pieces[c][bishop1Pos] = 'b';
pieces[c][knight2Pos] = 'n';
pieces[c][rook2Pos] = 'r';
}
- let fen = pieces[0].join("") +
- "/pppppppp/8/8/8/8/PPPPPPPP/" +
- pieces[1].join("").toUpperCase() +
- " 1111"; //add flags
+ const ranks23_black = "pppppppp/" + (antikingPos["w"]>0?antikingPos["w"]:"")
+ + "A" + (antikingPos["w"]<7?7-antikingPos["w"]:"");
+ const ranks23_white = (antikingPos["b"]>0?antikingPos["b"]:"") + "a"
+ + (antikingPos["b"]<7?7-antikingPos["b"]:"") + "/PPPPPPPP";
+ let fen = pieces["b"].join("") + "/" + ranks23_black +
+ "/8/8/" +
+ ranks23_white + "/" + pieces["w"].join("").toUpperCase() +
+ " 1111";
return fen;
}
}