From 270968d6f8b17065cfe18279d9ee7973107a1048 Mon Sep 17 00:00:00 2001
From: Benjamin Auder <benjamin.auder@somewhere>
Date: Thu, 22 Nov 2018 18:22:05 +0100
Subject: [PATCH] Alice rules implemented, but unfinished and with bugs...

---
 public/javascripts/base_rules.js      |   9 +-
 public/javascripts/components/game.js |   3 +-
 public/javascripts/variants/Alice.js  | 154 +++++++++++++++++++-------
 3 files changed, 119 insertions(+), 47 deletions(-)

diff --git a/public/javascripts/base_rules.js b/public/javascripts/base_rules.js
index e757f7ac..cb426f3f 100644
--- a/public/javascripts/base_rules.js
+++ b/public/javascripts/base_rules.js
@@ -699,6 +699,8 @@ class ChessRules
 
 	play(move, ingame)
 	{
+		console.log("play " + this.getNotation(move));
+		console.log(JSON.stringify(move));
 		if (!!ingame)
 			move.notation = this.getNotation(move);
 
@@ -716,6 +718,7 @@ class ChessRules
 		this.moves.pop();
 		this.unupdateVariables(move);
 		this.parseFlags(JSON.parse(move.flags));
+		console.log("undo " + this.getNotation(move));
 	}
 
 	//////////////
@@ -1011,10 +1014,10 @@ class ChessRules
 		}
 
 		// Translate final square
-		let finalSquare =
+		const finalSquare =
 			String.fromCharCode(97 + move.end.y) + (VariantRules.size[0]-move.end.x);
 
-		let piece = this.getPiece(move.start.x, move.start.y);
+		const piece = this.getPiece(move.start.x, move.start.y);
 		if (piece == VariantRules.PAWN)
 		{
 			// Pawn move
@@ -1022,7 +1025,7 @@ class ChessRules
 			if (move.vanish.length > move.appear.length)
 			{
 				// Capture
-				let startColumn = String.fromCharCode(97 + move.start.y);
+				const startColumn = String.fromCharCode(97 + move.start.y);
 				notation = startColumn + "x" + finalSquare;
 			}
 			else //no capture
diff --git a/public/javascripts/components/game.js b/public/javascripts/components/game.js
index 5690eb14..e3cc6af0 100644
--- a/public/javascripts/components/game.js
+++ b/public/javascripts/components/game.js
@@ -672,10 +672,9 @@ Vue.component('my-game', {
 				this.selectedPiece.style.display = "inline-block";
 				this.selectedPiece.style.zIndex = 3000;
 				let startSquare = this.getSquareFromId(e.target.parentNode.id);
-				this.possibleMoves = this.mode!="idle" && this.vr.canIplay(this.mycolor,startSquare)
+				this.possibleMoves = true//this.mode!="idle" && this.vr.canIplay(this.mycolor,startSquare)
 					? this.vr.getPossibleMovesFrom(startSquare)
 					: [];
-				console.log(this.possibleMoves);
 				e.target.parentNode.appendChild(this.selectedPiece);
 			}
 		},
diff --git a/public/javascripts/variants/Alice.js b/public/javascripts/variants/Alice.js
index db0881e2..3cba8d02 100644
--- a/public/javascripts/variants/Alice.js
+++ b/public/javascripts/variants/Alice.js
@@ -1,86 +1,156 @@
-class AliceRules extends ChessRUles
+class AliceRules extends ChessRules
 {
-	// TODO: more general double correspondance normal <--> alice
 	static get ALICE_PIECES()
 	{
-		return ['s','t','u','c','o','l']; //king is 'l'
+		return {
+			's': 'p',
+			't': 'q',
+			'u': 'r',
+			'c': 'b',
+			'o': 'n',
+			'l': 'k',
+		};
+	}
+	static get ALICE_CODES()
+	{
+		return {
+			'p': 's',
+			'q': 't',
+			'r': 'u',
+			'b': 'c',
+			'n': 'o',
+			'k': 'l',
+		};
 	}
 
 	static getPpath(b)
 	{
-		return (this.ALICE_PIECES.includes(b[1]) ? "Alice/" : "") + b;
+		return (Object.keys(this.ALICE_PIECES).includes(b[1]) ? "Alice/" : "") + b;
 	}
 
-	getPotentialMovesFrom([x,y])
+	getBoardOfPiece([x,y])
 	{
-		// Build board1+board2 from complete board
-		let board1 = doubleArray(sizeX, sizeY, "");
-		let board2 = doubleArray(sizeX, sizeY, "");
-		const [sizeX,sizeY] = variantRules.size;
+		const V = VariantRules;
+		// Build board where the piece is
+		const mirrorSide = (Object.keys(V.ALICE_CODES).includes(this.getPiece(x,y)) ? 1 : 2);
+		// Build corresponding board from complete board
+		const [sizeX,sizeY] = V.size;
+		let sideBoard = doubleArray(sizeX, sizeY, "");
 		for (let i=0; i<sizeX; i++)
 		{
 			for (let j=0; j<sizeY; j++)
 			{
 				const piece = this.getPiece(i,j);
-				if (this.ALICE_PIECES.includes(piece))
-					board2[i][j] = this.board[i][j];
-				else
-					board1[i][j] = this.board[i][j];
+				if (mirrorSide==1 && Object.keys(V.ALICE_CODES).includes(piece))
+					sideBoard[i][j] = this.board[i][j];
+				else if (mirrorSide==2 && Object.keys(V.ALICE_PIECES).includes(piece))
+					sideBoard[i][j] = this.getColor(i,j) + V.ALICE_PIECES[piece];
 			}
 		}
-		let saveBoard = JSON.parse(JSON.stringify(this.board));
-
-		// Search valid moves on both boards
-		let moves = [];
-		this.board = board1;
-
+		return sideBoard;
+	}
 
-		this.board = board2;
+	// TODO: castle & enPassant https://www.chessvariants.com/other.dir/alice.html
+	// TODO: enPassant seulement si l'on est du même coté que le coté de départ du pion adverse
+	// (en passant en sortant du monde... : il faut donc ajouter des coups non trouvés)
+	// castle: check that all destination squares are not occupied
+	getPotentialMovesFrom([x,y])
+	{
+		let sideBoard = this.getBoardOfPiece([x,y]);
 
+		// Search valid moves on sideBoard
+		let saveBoard = this.board;
+		this.board = sideBoard;
+		let moves = super.getPotentialMovesFrom([x,y]);
 		this.board = saveBoard;
 
 		// Finally filter impossible moves
-
-		return moves;
+		const mirrorSide = (Object.keys(VariantRules.ALICE_CODES).includes(this.getPiece(x,y)) ? 1 : 2);
+		return moves.filter(m => {
+			if (this.board[m.end.x][m.end.y] != VariantRules.EMPTY)
+			{
+				const piece = this.getPiece(m.end.x,m.end.y);
+				if ((mirrorSide==1 && Object.keys(VariantRules.ALICE_PIECES).includes(piece))
+					|| (mirrorSide==2 && Object.keys(VariantRules.ALICE_CODES).includes(piece)))
+				{
+					return false;
+				}
+			}
+			m.appear.forEach(psq => {
+				if (Object.keys(VariantRules.ALICE_CODES).includes(psq.p))
+					psq.p = VariantRules.ALICE_CODES[psq.p]; //goto board2
+				else
+					psq.p = VariantRules.ALICE_PIECES[psq.p]; //goto board1
+			});
+			return true;
+		});
 	}
 
 	underCheck(move)
 	{
-		// 1 where is king ? if board1 then build it, if board2 then build it. then check.
 		const color = this.turn;
 		this.play(move);
+		let sideBoard = this.getBoardOfPiece(this.kingPos[color]);
+		let saveBoard = this.board;
+		this.board = sideBoard;
 		let res = this.isAttacked(this.kingPos[color], this.getOppCol(color));
+		this.board = saveBoard;
 		this.undo(move);
 		return res;
 	}
 
-	// TODO also:
-	//getCheckSquares(move)
-
-	// TODO: pieces change side!
-	static PlayOnBoard(board, move)
+	getCheckSquares(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;
+		this.play(move);
+		const color = this.turn; //opponent
+		let sideBoard = this.getBoardOfPiece(this.kingPos[color]);
+		let saveBoard = this.board;
+		this.board = sideBoard;
+		let res = this.isAttacked(this.kingPos[color], this.getOppCol(color))
+			? [ JSON.parse(JSON.stringify(this.kingPos[color])) ]
+			: [ ];
+		this.board = saveBoard;
+		this.undo(move);
+		return res;
 	}
-	static UndoOnBoard(board, move)
+
+	getNotation(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;
+		if (move.appear.length == 2 && move.appear[0].p == VariantRules.KING)
+		{
+			if (move.end.y < move.start.y)
+				return "0-0-0";
+			else
+				return "0-0";
+		}
+
+		const finalSquare =
+			String.fromCharCode(97 + move.end.y) + (VariantRules.size[0]-move.end.x);
+		const piece = this.getPiece(move.start.x, move.start.y);
+
+		// Piece or pawn movement
+		let notation = piece.toUpperCase() +
+			(move.vanish.length > move.appear.length ? "x" : "") + finalSquare;
+		if (['s','p'].includes(piece) && !['s','p'].includes(move.appear[0].p))
+		{
+			// Promotion
+			notation += "=" + move.appear[0].p.toUpperCase();
+		}
+		return notation;
 	}
 
 	checkGameEnd()
 	{
 		const color = this.turn;
-		// No valid move: stalemate or checkmate?
-		// TODO: here also, need to build the board with king on it
+		let sideBoard = this.getBoardOfPiece(this.kingPos[color]);
+		let saveBoard = this.board;
+		this.board = sideBoard;
+		let res = "*";
 		if (!this.isAttacked(this.kingPos[color], this.getOppCol(color)))
-			return "1/2";
-		// OK, checkmate
-		return color == "w" ? "0-1" : "1-0";
+			res = "1/2";
+		else
+			res = (color == "w" ? "0-1" : "1-0");
+		this.board = saveBoard;
+		return res;
 	}
 }
-- 
2.44.0