('Crazyhouse', 'Captures reborn'),
('Switching', 'Exchange pieces positions'),
('Extinction', 'Capture all of a kind'),
+ ('Marseille', 'Move twice'),
+ ('Upsidedown', 'Walking on the hands'),
+ ('Dark', 'In the shadow'),
+ ('Berolina', 'Pawns move diagonally'),
('Ultima', 'Exotic captures');
create table Problems (
if (V.HasFlags)
move.flags = JSON.stringify(this.aggregateFlags()); //save flags (for undo)
- this.updateVariables(move);
- this.moves.push(move);
if (V.HasEnpassant)
this.epSquares.push( this.getEpSquare(move) );
- this.turn = this.getOppCol(this.turn);
V.PlayOnBoard(this.board, move);
+ this.turn = this.getOppCol(this.turn);
+ this.moves.push(move);
+ this.updateVariables(move);
if (!!ingame)
{
undo(move)
{
- V.UndoOnBoard(this.board, move);
- this.turn = this.getOppCol(this.turn);
if (V.HasEnpassant)
this.epSquares.pop();
- this.moves.pop();
- this.unupdateVariables(move);
if (V.HasFlags)
this.disaggregateFlags(JSON.parse(move.flags));
+ V.UndoOnBoard(this.board, move);
+ this.turn = this.getOppCol(this.turn);
+ this.moves.pop();
+ this.unupdateVariables(move);
// DEBUG:
// if (this.getFen() != this.states[this.states.length-1])
);
// Create board element (+ reserves if needed by variant or mode)
const lm = this.vr.lastMove;
- const showLight = this.hints &&
+ const showLight = this.hints && variant!="Dark" &&
(!["idle","chat"].includes(this.mode) || this.cursor==this.vr.moves.length);
const gameDiv = h('div',
{
let cj = (this.mycolor=='w' ? j : sizeY-j-1);
let elems = [];
if (this.vr.board[ci][cj] != VariantRules.EMPTY && (variant!="Dark"
- || this.score!="*" || this.vr.isEnlightened(ci,cj,this.mycolor)))
+ || this.score!="*" || this.vr.enlightened[this.mycolor][ci][cj]))
{
elems.push(
h(
'dark-square': (i+j)%2==1,
[this.color]: true,
'in-shadow': variant=="Dark" && this.score=="*"
- && !this.vr.isEnlightened(ci,cj,this.mycolor),
+ && !this.vr.enlightened[this.mycolor][ci][cj],
'highlight': showLight && !!lm && _.isMatch(lm.end, {x:ci,y:cj}),
'incheck': showLight && incheckSq[ci][cj],
},
this.newGame("human", data.fen, data.color, data.oppid);
break;
case "newmove": //..he played!
- this.play(data.move, "animate");
+ this.play(data.move, (variant!="Dark" ? "animate" : null));
break;
case "pong": //received if we sent a ping (game still alive on our side)
if (this.gameId != data.gameId)
updateVariables(move)
{
super.updateVariables(move); //standard king
- const piece = this.getPiece(move.start.x,move.start.y);
- const c = this.getColor(move.start.x,move.start.y);
+ const piece = move.vanish[0].p;
+ const c = move.vanish[0].c;
// "l" = Alice king
if (piece == "l")
{
unupdateVariables(move)
{
super.unupdateVariables(move);
- const c = this.getColor(move.start.x,move.start.y);
- if (this.getPiece(move.start.x,move.start.y) == "l")
+ const c = move.vanish[0].c;
+ if (move.vanish[0].p == "l")
this.kingPos[c] = [move.start.x, move.start.y];
}
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);
+ const piece = move.vanish[0].p;
+ const c = move.vanish[0].c;
// Update antiking position
if (piece == V.ANTIKING)
{
unupdateVariables(move)
{
super.unupdateVariables(move);
- const c = this.getColor(move.start.x,move.start.y);
- if (this.getPiece(move.start.x,move.start.y) == V.ANTIKING)
+ const c = move.vanish[0].c;
+ if (move.vanish[0].p == V.ANTIKING)
this.antikingPos[c] = [move.start.x, move.start.y];
}
updateVariables(move)
{
super.updateVariables(move);
- const color = this.getColor(move.start.x,move.start.y);
+ const color = move.vanish[0].c;
if (move.appear.length == 0) //capture
{
const firstRank = {"w": 7, "b": 0};
unupdateVariables(move)
{
super.unupdateVariables(move);
- const c = this.getColor(move.start.x,move.start.y);
+ const c = move.vanish[0].c;
const oppCol = this.getOppCol(c);
if ([this.kingPos[c][0],this.kingPos[oppCol][0]].some(e => { return e < 0; }))
{
super.updateVariables(move);
if (move.vanish.length == 2 && move.appear.length == 2)
return; //skip castle
- const color = this.turn;
+ const color = move.appear[0].c;
if (move.vanish.length == 0)
{
this.reserve[color][move.appear[0].p]--;
-class Chess960Rules extends ChessRules
+class DarkRules extends ChessRules
{
// Standard rules, in the shadow
setOtherVariables(fen)
{
super.setOtherVariables(fen);
- const [sizeX,sizeY] = {V.size.x,V.size.y};
+ const [sizeX,sizeY] = [V.size.x,V.size.y];
this.enlightened = {
- "w": doubleArray(sizeX,sizeY,false),
- "b": doubleArray(sizeX,sizeY,false)
+ "w": doubleArray(sizeX,sizeY),
+ "b": doubleArray(sizeX,sizeY)
};
- setup enlightened: squares reachable by each side (TODO: one side would be enough)
+ // Setup enlightened: squares reachable by each side
+ // (TODO: one side would be enough ?)
+ this.updateEnlightened();
}
- isEnlightened(x, y, color)
+ updateEnlightened()
{
- //TODO: artificlaly change turn
- }
-
- getAllPotentialMoves()
- {
- let moves = []; //TODO
+ // Initialize with pieces positions (which are seen)
+ for (let i=0; i<V.size.x; i++)
+ {
+ for (let j=0; j<V.size.y; j++)
+ {
+ this.enlightened["w"][i][j] = false;
+ this.enlightened["b"][i][j] = false;
+ if (this.board[i][j] != V.EMPTY)
+ this.enlightened[this.getColor(i,j)][i][j] = true;
+ }
+ }
+ const currentTurn = this.turn;
+ this.turn = "w";
+ const movesWhite = this.getAllValidMoves();
+ this.turn = "b";
+ const movesBlack = this.getAllValidMoves();
+ this.turn = currentTurn;
+ for (let move of movesWhite)
+ this.enlightened["w"][move.end.x][move.end.y] = true;
+ for (let move of movesBlack)
+ this.enlightened["b"][move.end.x][move.end.y] = true;
}
atLeastOneMove()
return res;
}
- // NOTE: no (un)updateVariables() because no computer mode
- // --> but isEnlightened() should have its variable updated
- // --> in fact an array is enough (no need for a function)
- // recomputed after every play/undo (although there are no undo here for now)
+ updateVariables(move)
+ {
+ // Update kings positions
+ const piece = move.vanish[0].p;
+ const c = move.vanish[0].c;
+ if (piece == V.KING && move.appear.length > 0)
+ {
+ this.kingPos[c][0] = move.appear[0].x;
+ this.kingPos[c][1] = move.appear[0].y;
+ }
+ if (move.vanish.length >= 2 && move.vanish[1].p == V.KING)
+ {
+ // We took opponent king !
+ const oppCol = this.getOppCol(c);
+ this.kingPos[oppCol] = [-1,-1];
+ }
+
+ // Update moves for both colors:
+ this.updateEnlightened();
+ }
+
+ unupdateVariables(move)
+ {
+ super.unupdateVariables(move);
+ const c = move.vanish[0].c;
+ const oppCol = this.getOppCol(c);
+ if (this.kingPos[oppCol][0] < 0)
+ {
+ // Last move took opponent's king
+ for (let psq of move.vanish)
+ {
+ if (psq.p == 'k')
+ {
+ this.kingPos[oppCol] = [psq.x, psq.y];
+ break;
+ }
+ }
+ }
+
+ // Update moves for both colors:
+ this.updateEnlightened();
+ }
checkGameEnd()
{
return [];
}
- // No variables update because no castling
+ // No variables update because no royal king + no castling
updateVariables(move) { }
unupdateVariables(move) { }
updateVariables(move)
{
super.updateVariables(move);
- const c = this.getColor(move.start.x,move.start.y);
- if (this.board[move.end.x][move.end.y] != V.EMPTY
- && c != this.getColor(move.end.x,move.end.y)
- && this.getPiece(move.end.x,move.end.y) == V.KING)
+ const c = move.vanish[0].c;
+ if (move.vanish.length >= 2 && move.vanish[1].p == V.KING)
{
// We took opponent king !
const oppCol = this.getOppCol(c);
unupdateVariables(move)
{
super.unupdateVariables(move);
- const c = this.getColor(move.start.x,move.start.y);
+ const c = move.vanish[0].c;
const oppCol = this.getOppCol(c);
if (this.kingPos[oppCol][0] < 0)
{
--- /dev/null
+//TODO: turn en fonction de la parité des coups...
+//adapter alphabeta (dans baserules ? --> basé sur turn OK)
+// le reste == standard
&& move.appear[1].p == V.KING)
{
// Switch with the king; not castle, and not handled by main class
- const color = this.getColor(move.start.x, move.start.y);
+ const color = move.vanish[0].c;
this.kingPos[color] = [move.appear[1].x, move.appear[1].y];
}
}
if (move.appear.length == 2 && move.vanish.length == 2
&& move.appear[1].p == V.KING)
{
- const color = this.getColor(move.start.x, move.start.y);
+ const color = move.vanish[0].c;
this.kingPos[color] = [move.appear[0].x, move.appear[0].y];
}
}
updateVariables(move)
{
// Just update king(s) position(s)
- const piece = this.getPiece(move.start.x,move.start.y);
- const c = this.getColor(move.start.x,move.start.y);
+ const piece = move.vanish[0].p;
+ const c = move.vanish[0].c;
if (piece == V.KING && move.appear.length > 0)
{
this.kingPos[c][0] = move.appear[0].x;
--- /dev/null
+class UpsidedownRules extends ChessRUles
+{
+ static HasFlags() { return false; }
+
+ getPotentialKingMoves(sq)
+ {
+ // No castle
+ return this.getSlideNJumpMoves(sq,
+ V.steps[V.ROOK].concat(V.steps[V.BISHOP]), "oneStep");
+ }
+
+ static GenRandInitFen()
+ {
+ let pieces = { "w": new Array(8), "b": new Array(8) };
+ for (let c of ["w","b"])
+ {
+ let positions = _.range(8);
+
+ let randIndex = 2 * _.random(3);
+ let bishop1Pos = positions[randIndex];
+ let randIndex_tmp = 2 * _.random(3) + 1;
+ let bishop2Pos = positions[randIndex_tmp];
+ positions.splice(Math.max(randIndex,randIndex_tmp), 1);
+ positions.splice(Math.min(randIndex,randIndex_tmp), 1);
+
+ randIndex = _.random(5);
+ let knight1Pos = positions[randIndex];
+ positions.splice(randIndex, 1);
+ randIndex = _.random(4);
+ let knight2Pos = positions[randIndex];
+ positions.splice(randIndex, 1);
+
+ randIndex = _.random(3);
+ let queenPos = positions[randIndex];
+ positions.splice(randIndex, 1);
+
+ let rook1Pos = positions[0];
+ let kingPos = positions[1];
+ let rook2Pos = positions[2];
+
+ pieces[c][rook1Pos] = 'r';
+ pieces[c][knight1Pos] = 'n';
+ pieces[c][bishop1Pos] = 'b';
+ pieces[c][queenPos] = 'q';
+ pieces[c][kingPos] = 'k';
+ pieces[c][bishop2Pos] = 'b';
+ pieces[c][knight2Pos] = 'n';
+ pieces[c][rook2Pos] = 'r';
+ }
+ return pieces["w"].join("") +
+ "/PPPPPPPP/8/8/8/8/pppppppp/" +
+ pieces["b"].join("").toUpperCase() +
+ " w 1111 -"; //add turn + flags + enpassant
+ }
+}
+
+const VariantRules = UpsidedownRules;
background-color: #00cc66 !important
.in-shadow
- opacity: 0.5
+ filter: brightness(50%)
.incheck
background-color: #cc3300 !important