Separate client and server codes. Keep everything in one git repo for simplicity
[vchess.git] / client / client_OLD / javascripts / variants / Zen.js
diff --git a/client/client_OLD/javascripts/variants/Zen.js b/client/client_OLD/javascripts/variants/Zen.js
new file mode 100644 (file)
index 0000000..6a568db
--- /dev/null
@@ -0,0 +1,227 @@
+class ZenRules extends ChessRules
+{
+       // NOTE: enPassant, if enabled, would need to redefine carefully getEpSquare
+       static get HasEnpassant() { return false; }
+
+       // TODO(?): some duplicated code in 2 next functions
+       getSlideNJumpMoves([x,y], steps, oneStep)
+       {
+               const color = this.getColor(x,y);
+               let moves = [];
+               outerLoop:
+               for (let loop=0; loop<steps.length; loop++)
+               {
+                       const step = steps[loop];
+                       let i = x + step[0];
+                       let j = y + step[1];
+                       while (V.OnBoard(i,j) && this.board[i][j] == V.EMPTY)
+                       {
+                               moves.push(this.getBasicMove([x,y], [i,j]));
+                               if (!!oneStep)
+                                       continue outerLoop;
+                               i += step[0];
+                               j += step[1];
+                       }
+                       // No capture check: handled elsewhere (next method)
+               }
+               return moves;
+       }
+
+       // follow steps from x,y until something is met.
+       // if met piece is opponent and same movement (asA): eat it!
+       findCaptures_aux([x,y], asA)
+       {
+               const color = this.getColor(x,y);
+               var moves = [];
+               const steps = asA != V.PAWN
+                       ? (asA==V.QUEEN ? V.steps[V.ROOK].concat(V.steps[V.BISHOP]) : V.steps[asA])
+                       : color=='w' ? [[-1,-1],[-1,1]] : [[1,-1],[1,1]];
+               const oneStep = (asA==V.KNIGHT || asA==V.PAWN); //we don't capture king
+               const lastRank = (color == 'w' ? 0 : V.size.x-1);
+               const promotionPieces = [V.ROOK,V.KNIGHT,V.BISHOP,V.QUEEN];
+               outerLoop:
+               for (let loop=0; loop<steps.length; loop++)
+               {
+                       const step = steps[loop];
+                       let i = x + step[0];
+                       let j = y + step[1];
+                       while (V.OnBoard(i,j) && this.board[i][j] == V.EMPTY)
+                       {
+                               if (oneStep)
+                                       continue outerLoop;
+                               i += step[0];
+                               j += step[1];
+                       }
+                       if (V.OnBoard(i,j) && this.getColor(i,j) == V.GetOppCol(color)
+                               && this.getPiece(i,j) == asA)
+                       {
+                               // eat!
+                               if (this.getPiece(x,y) == V.PAWN && i == lastRank)
+                               {
+                                       // Special case of promotion:
+                                       promotionPieces.forEach(p => {
+                                               moves.push(this.getBasicMove([x,y], [i,j], {c:color,p:p}));
+                                       });
+                               }
+                               else
+                               {
+                                       // All other cases
+                                       moves.push(this.getBasicMove([x,y], [i,j]));
+                               }
+                       }
+               }
+               return moves;
+       }
+
+       // Find possible captures from a square: look in every direction!
+       findCaptures(sq)
+       {
+               let moves = [];
+
+               Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.PAWN));
+               Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.ROOK));
+               Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.KNIGHT));
+               Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.BISHOP));
+               Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.QUEEN));
+
+               return moves;
+       }
+
+       getPotentialPawnMoves([x,y])
+       {
+               const color = this.getColor(x,y);
+               let moves = [];
+               const [sizeX,sizeY] = [V.size.x,V.size.y];
+               const shift = (color == 'w' ? -1 : 1);
+               const startRank = (color == 'w' ? sizeY-2 : 1);
+               const firstRank = (color == 'w' ? sizeY-1 : 0);
+               const lastRank = (color == "w" ? 0 : sizeY-1);
+
+               if (x+shift != lastRank)
+               {
+                       // Normal moves
+                       if (this.board[x+shift][y] == V.EMPTY)
+                       {
+                               moves.push(this.getBasicMove([x,y], [x+shift,y]));
+                               if ([startRank,firstRank].includes(x) && this.board[x+2*shift][y] == V.EMPTY)
+                               {
+                                       //two squares jump
+                                       moves.push(this.getBasicMove([x,y], [x+2*shift,y]));
+                               }
+                       }
+               }
+
+               else //promotion
+               {
+                       let promotionPieces = [V.ROOK,V.KNIGHT,V.BISHOP,V.QUEEN];
+                       promotionPieces.forEach(p => {
+                               // Normal move
+                               if (this.board[x+shift][y] == V.EMPTY)
+                                       moves.push(this.getBasicMove([x,y], [x+shift,y], {c:color,p:p}));
+                       });
+               }
+
+               // No en passant here
+
+               // Add "zen" captures
+               Array.prototype.push.apply(moves, this.findCaptures([x,y]));
+
+               return moves;
+       }
+
+       getPotentialRookMoves(sq)
+       {
+               let noCaptures = this.getSlideNJumpMoves(sq, V.steps[V.ROOK]);
+               let captures = this.findCaptures(sq);
+               return noCaptures.concat(captures);
+       }
+
+       getPotentialKnightMoves(sq)
+       {
+               let noCaptures = this.getSlideNJumpMoves(sq, V.steps[V.KNIGHT], "oneStep");
+               let captures = this.findCaptures(sq);
+               return noCaptures.concat(captures);
+       }
+
+       getPotentialBishopMoves(sq)
+       {
+               let noCaptures = this.getSlideNJumpMoves(sq, V.steps[V.BISHOP]);
+               let captures = this.findCaptures(sq);
+               return noCaptures.concat(captures);
+       }
+
+       getPotentialQueenMoves(sq)
+       {
+               let noCaptures = this.getSlideNJumpMoves(
+                       sq, V.steps[V.ROOK].concat(V.steps[V.BISHOP]));
+               let captures = this.findCaptures(sq);
+               return noCaptures.concat(captures);
+       }
+
+       getPotentialKingMoves(sq)
+       {
+               // Initialize with normal moves
+               let noCaptures = this.getSlideNJumpMoves(sq,
+                       V.steps[V.ROOK].concat(V.steps[V.BISHOP]), "oneStep");
+               let captures = this.findCaptures(sq);
+               return noCaptures.concat(captures).concat(this.getCastleMoves(sq));
+       }
+
+       getNotation(move)
+       {
+               // Recognize special moves first
+               if (move.appear.length == 2)
+               {
+                       // castle
+                       if (move.end.y < move.start.y)
+                               return "0-0-0";
+                       else
+                               return "0-0";
+               }
+
+               // Translate initial square (because pieces may fly unusually in this variant!)
+               const initialSquare = V.CoordsToSquare(move.start);
+
+               // Translate final square
+               const finalSquare = V.CoordsToSquare(move.end);
+
+               let notation = "";
+               const piece = this.getPiece(move.start.x, move.start.y);
+               if (piece == V.PAWN)
+               {
+                       // pawn move (TODO: enPassant indication)
+                       if (move.vanish.length > 1)
+                       {
+                               // capture
+                               notation = initialSquare + "x" + finalSquare;
+                       }
+                       else //no capture
+                               notation = finalSquare;
+                       if (piece != move.appear[0].p) //promotion
+                               notation += "=" + move.appear[0].p.toUpperCase();
+               }
+
+               else
+               {
+                       // Piece movement
+                       notation = piece.toUpperCase();
+                       if (move.vanish.length > 1)
+                               notation += initialSquare + "x";
+                       notation += finalSquare;
+               }
+               return notation;
+       }
+
+       static get VALUES()
+       {
+               // TODO: experimental
+               return {
+                       'p': 1,
+                       'r': 3,
+                       'n': 2,
+                       'b': 2,
+                       'q': 5,
+                       'k': 1000
+               }
+       }
+}