Prepare some more variants (unfinished)
[vchess.git] / public / javascripts / variants / Magnetic.js
index d5731a6..8480d79 100644 (file)
@@ -1,44 +1,45 @@
 class MagneticRules extends ChessRules
 {
-       getEpSquare(move)
-       {
-               return undefined; //no en-passant
-       }
+       static get HasEnpassant() { return false; }
 
        getPotentialMovesFrom([x,y])
        {
-               const standardMoves = super.getPotentialMovesFrom([x,y]);
+               let standardMoves = super.getPotentialMovesFrom([x,y]);
                let moves = [];
                standardMoves.forEach(m => {
                        let newMove_s = this.applyMagneticLaws(m);
                        if (newMove_s.length == 1)
                                moves.push(newMove_s[0]);
                        else //promotion
-                               moves = moves.concat(moves, newMove_s);
+                               moves = moves.concat(newMove_s);
                });
+               return moves;
        }
 
        // Complete a move with magnetic actions
-       applyMagneticLaws(standardMove)
+       // TODO: job is done multiple times for (normal) promotions.
+       applyMagneticLaws(move)
        {
-               const [x,y] = [moves.start.x, move.start.y];
-               let move = JSON.parse(JSON.stringify(standardMove));
+               if (move.appear[0].p == V.KING && move.appear.length==1)
+                       return [move]; //kings are not charged
+               const aIdx = (move.appear[0].p != V.KING ? 0 : 1); //if castling, rook is charged
+               const [x,y] = [move.appear[aIdx].x, move.appear[aIdx].y];
+               const color = this.turn;
+               const lastRank = (color=="w" ? 0 : 7);
+               const standardMove = JSON.parse(JSON.stringify(move));
                this.play(standardMove);
-               const color = this.getColor(x,y);
-               const [sizeX,sizeY] = VariantRules.size;
                for (let step of [[-1,0],[1,0],[0,-1],[0,1]])
                {
                        let [i,j] = [x+step[0],y+step[1]];
-                       while (i>=0 && i<sizeX && j>=0 && j<sizeY)
+                       while (V.OnBoard(i,j))
                        {
-                               if (this.board[i][j] != VariantRules.EMPTY)
+                               if (this.board[i][j] != V.EMPTY)
                                {
                                        // Found something. Same color or not?
                                        if (this.getColor(i,j) != color)
                                        {
                                                // Attraction
-                                               if ((Math.abs(i-x)>=2 || Math.abs(j-y)>=2)
-                                                       && this.getPiece(i,j) != VariantRules.KING)
+                                               if ((Math.abs(i-x)>=2 || Math.abs(j-y)>=2) && this.getPiece(i,j) != V.KING)
                                                {
                                                        move.vanish.push(
                                                                new PiPo({
@@ -61,13 +62,13 @@ class MagneticRules extends ChessRules
                                        else
                                        {
                                                // Repulsion
-                                               if (this.getPiece(i,j) != VariantRules.KING)
+                                               if (this.getPiece(i,j) != V.KING)
                                                {
                                                        // Push it until we meet an obstacle or edge of the board
                                                        let [ii,jj] = [i+step[0],j+step[1]];
-                                                       while (ii>=0 && ii<sizeX && jj>=0 && jj<sizeY)
+                                                       while (V.OnBoard(ii,jj))
                                                        {
-                                                               if (this.board[ii][jj] != VariantRules.EMPTY)
+                                                               if (this.board[ii][jj] != V.EMPTY)
                                                                        break;
                                                                ii += step[0];
                                                                jj += step[1];
@@ -103,20 +104,39 @@ class MagneticRules extends ChessRules
                }
                this.undo(standardMove);
                let moves = [];
-               if (..condition pawn promote)
+               // Scan move for pawn (max 1) on 8th rank
+               for (let i=1; i<move.appear.length; i++)
                {
-                       move. ... = ... //loop
-                       moves.push(...);
+                       if (move.appear[i].p==V.PAWN && move.appear[i].c==color
+                               && move.appear[i].x==lastRank)
+                       {
+                               move.appear[i].p = V.ROOK;
+                               moves.push(move);
+                               for (let piece of [V.KNIGHT, V.BISHOP, V.QUEEN])
+                               {
+                                       let cmove = JSON.parse(JSON.stringify(move));
+                                       cmove.appear[i].p = piece;
+                                       moves.push(cmove);
+                               }
+                               // Swap appear[i] and appear[0] for moves presentation (TODO: this is awkward)
+                               moves.forEach(m => {
+                                       let tmp = m.appear[0];
+                                       m.appear[0] = m.appear[i];
+                                       m.appear[i] = tmp;
+                               });
+                               break;
+                       }
                }
-               else
+               if (moves.length == 0) //no pawn on 8th rank
                        moves.push(move);
                return moves;
        }
 
-       // TODO: verify this assertion
        atLeastOneMove()
        {
-               return true; //always at least one possible move
+               if (this.kingPos[this.turn][0] < 0)
+                       return false;
+               return true; //TODO: is it right?
        }
 
        underCheck(move)
@@ -131,8 +151,8 @@ class MagneticRules extends ChessRules
                this.play(move);
                // The only way to be "under check" is to have lost the king (thus game over)
                let res = this.kingPos[c][0] < 0
-                       ? [ JSON.parse(JSON.stringify(saveKingPos)) ]
-                       : [ ];
+                       ? [JSON.parse(JSON.stringify(saveKingPos))]
+                       : [];
                this.undo(move);
                return res;
        }
@@ -141,15 +161,25 @@ class MagneticRules extends ChessRules
        {
                super.updateVariables(move);
                const c = this.getColor(move.start.x,move.start.y);
-               if (c != this.getColor(move.end.x,move.end.y)
-                       && this.board[move.end.x][move.end.y] != VariantRules.EMPTY
-                       && this.getPiece(move.end.x,move.end.y) == VariantRules.KING)
+               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)
                {
                        // We took opponent king !
                        const oppCol = this.getOppCol(c);
                        this.kingPos[oppCol] = [-1,-1];
                        this.castleFlags[oppCol] = [false,false];
                }
+               // Did we magnetically move our (init) rooks or opponents' ones ?
+               const firstRank = (c == "w" ? 7 : 0);
+               const oppFirstRank = 7 - firstRank;
+               const oppCol = this.getOppCol(c);
+               move.vanish.forEach(psq => {
+                       if (psq.x == firstRank && this.INIT_COL_ROOK[c].includes(psq.y))
+                               this.castleFlags[c][psq.y==this.INIT_COL_ROOK[c][0] ? 0 : 1] = false;
+                       else if (psq.x == oppFirstRank && this.INIT_COL_ROOK[oppCol].includes(psq.y))
+                               this.castleFlags[oppCol][psq.y==this.INIT_COL_ROOK[oppCol][0] ? 0 : 1] = false;
+               });
        }
 
        unupdateVariables(move)
@@ -171,22 +201,16 @@ class MagneticRules extends ChessRules
                }
        }
 
-       checkGameOver()
-       {
-               if (this.checkRepetition())
-                       return "1/2";
-
-               const color = this.turn;
-               // TODO: do we need "atLeastOneMove()"?
-               if (this.atLeastOneMove() && this.kingPos[color][0] >= 0)
-                       return "*";
-
-               return this.checkGameEnd();
-       }
-
        checkGameEnd()
        {
                // No valid move: our king disappeared
                return this.turn == "w" ? "0-1" : "1-0";
        }
+
+       static get THRESHOLD_MATE()
+       {
+               return 500; //checkmates evals may be slightly below 1000
+       }
 }
+
+const VariantRules = MagneticRules;