From 15952ada1d73262371654351ab8a4471f64010fd Mon Sep 17 00:00:00 2001
From: Benjamin Auder <benjamin.auder@somewhere>
Date: Sat, 8 Dec 2018 01:39:20 +0100
Subject: [PATCH] Improve Switching chess: avoid duplicate moves for analysis,
 better notation

---
 TODO                                     |  1 +
 public/javascripts/base_rules.js         | 18 ++++------
 public/javascripts/variants/Switching.js | 43 ++++++++++++++++++++++--
 3 files changed, 48 insertions(+), 14 deletions(-)

diff --git a/TODO b/TODO
index 1aae2fb1..26aabd51 100644
--- a/TODO
+++ b/TODO
@@ -1,3 +1,4 @@
+Allow to navigate in game after it's over (back/play)
 For animation, moves should contains "moving" and "fading" maybe...
 (But it's really just for Magnetic chess)
 setInterval "CRON" task in sockets.js to check connected clients
diff --git a/public/javascripts/base_rules.js b/public/javascripts/base_rules.js
index 48a5602c..ee5ddd02 100644
--- a/public/javascripts/base_rules.js
+++ b/public/javascripts/base_rules.js
@@ -821,7 +821,9 @@ class ChessRules
 		this.shouldReturn = false;
 		const maxeval = VariantRules.INFINITY;
 		const color = this.turn;
-		let moves1 = this.getAllValidMoves();
+		// Some variants may show a bigger moves list to the human (Switching),
+		// thus the argument "computer" below (which is generally ignored)
+		let moves1 = this.getAllValidMoves("computer");
 
 		// Can I mate in 1 ? (for Magnetic & Extinction)
 		for (let i of _.shuffle(_.range(moves1.length)))
@@ -843,7 +845,7 @@ class ChessRules
 			{
 				eval2 = (color=="w" ? 1 : -1) * maxeval; //initialized with checkmate value
 				// Second half-move:
-				let moves2 = this.getAllValidMoves();
+				let moves2 = this.getAllValidMoves("computer");
 				for (let j=0; j<moves2.length; j++)
 				{
 					this.play(moves2[j]);
@@ -921,7 +923,7 @@ class ChessRules
 		}
 		if (depth == 0)
       return this.evalPosition();
-		const moves = this.getAllValidMoves();
+		const moves = this.getAllValidMoves("computer");
     let v = color=="w" ? -maxeval : maxeval;
 		if (color == "w")
 		{
@@ -1082,14 +1084,8 @@ class ChessRules
 	// Context: just before move is played, turn hasn't changed
 	getNotation(move)
 	{
-		if (move.appear.length == 2 && move.appear[0].p == VariantRules.KING)
-		{
-			// Castle
-			if (move.end.y < move.start.y)
-				return "0-0-0";
-			else
-				return "0-0";
-		}
+		if (move.appear.length == 2 && move.appear[0].p == VariantRules.KING) //castle
+			return (move.end.y < move.start.y ? "0-0-0" : "0-0");
 
 		// Translate final square
 		const finalSquare =
diff --git a/public/javascripts/variants/Switching.js b/public/javascripts/variants/Switching.js
index af934f32..cedba3db 100644
--- a/public/javascripts/variants/Switching.js
+++ b/public/javascripts/variants/Switching.js
@@ -51,10 +51,10 @@ class SwitchingRules extends ChessRules
 		return moves;
 	}
 
-	getPotentialMovesFrom([x,y])
+	getPotentialMovesFrom([x,y], computer)
 	{
 		let moves = super.getPotentialMovesFrom([x,y]);
-		// Add switches:
+		// Add switches: respecting chessboard ordering if "computer" is on
 		const V = VariantRules;
 		const color = this.turn;
 		const piece = this.getPiece(x,y);
@@ -65,6 +65,8 @@ class SwitchingRules extends ChessRules
 		for (let step of steps)
 		{
 			let [i,j] = [x+step[0],y+step[1]];
+			if (!!computer && (i<x || (i==x && j<y)))
+				continue; //only switch with superior indices
 			if (i>=0 && i<sizeX && j>=0 && j<sizeY && this.board[i][j]!=V.EMPTY
 				&& this.getColor(i,j)==color && this.getPiece(i,j)!=piece
 				// No switching under check (theoretically non-king pieces could, but not)
@@ -80,6 +82,26 @@ class SwitchingRules extends ChessRules
 		return moves;
 	}
 
+	getAllValidMoves(computer)
+	{
+		const color = this.turn;
+		const oppCol = this.getOppCol(color);
+		let potentialMoves = [];
+		const [sizeX,sizeY] = VariantRules.size;
+		for (let i=0; i<sizeX; i++)
+		{
+			for (let j=0; j<sizeY; j++)
+			{
+				if (this.board[i][j] != VariantRules.EMPTY && this.getColor(i,j) == color)
+				{
+					Array.prototype.push.apply(potentialMoves,
+						this.getPotentialMovesFrom([i,j], computer));
+				}
+			}
+		}
+		return this.filterValid(potentialMoves);
+	}
+
 	updateVariables(move)
 	{
 		super.updateVariables(move);
@@ -103,5 +125,20 @@ class SwitchingRules extends ChessRules
 		}
 	}
 
-	static get SEARCH_DEPTH() { return 2; } //branching factor is quite high
+	static get SEARCH_DEPTH() { return 2; } //high branching factor
+
+	getNotation(move)
+	{
+		if (move.appear.length == 1)
+			return super.getNotation(move); //no switch
+		// Switch or castle
+		if (move.appear[0].p == VariantRules.KING && move.appear[1].p == VariantRules.ROOK)
+			return (move.end.y < move.start.y ? "0-0-0" : "0-0");
+		// Switch:
+		const startSquare =
+			String.fromCharCode(97 + move.start.y) + (VariantRules.size[0]-move.start.x);
+		const finalSquare =
+			String.fromCharCode(97 + move.end.y) + (VariantRules.size[0]-move.end.x);
+		return "S" + startSquare + finalSquare;
+	}
 }
-- 
2.44.0