From: Benjamin Auder <benjamin.auder@somewhere>
Date: Tue, 20 Nov 2018 21:01:22 +0000 (+0100)
Subject: Finish Magnetic chess
X-Git-Url: https://git.auder.net/%7B%7B%20asset%28%27mixstore/css/img/doc/current/gitweb.css?a=commitdiff_plain;h=7f0711a8515a199efe66ab903a2e710d77b1ce76;p=vchess.git

Finish Magnetic chess
---

diff --git a/public/javascripts/variants/Magnetic.js b/public/javascripts/variants/Magnetic.js
index e9415322..2d576e1b 100644
--- a/public/javascripts/variants/Magnetic.js
+++ b/public/javascripts/variants/Magnetic.js
@@ -1,4 +1,4 @@
-class MagneticRules
+class MagneticRules extends ChessRules
 {
 	getEpSquare(move)
 	{
@@ -8,7 +8,86 @@ class MagneticRules
 	// Complete a move with magnetic actions
 	applyMagneticLaws([x,y], move)
 	{
-		// TODO
+		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)
+			{
+				if (this.board[i][j] != VariantRules.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)
+						{
+							move.vanish.push(
+								new PiPo({
+									p:this.getPiece(i,j),
+									c:this.getColor(i,j),
+									x:i,
+									y:j
+								})
+							);
+							move.appear.push(
+								new PiPo({
+									p:this.getPiece(i,j),
+									c:this.getColor(i,j),
+									x:x+step[0],
+									y:y+step[1]
+								})
+							);
+						}
+					}
+					else
+					{
+						// Repulsion
+						if (this.getPiece(i,j) != VariantRules.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)
+							{
+								if (this.board[ii][jj] != VariantRules.EMPTY)
+									break;
+								ii += step[0];
+								jj += step[1];
+							}
+							ii -= step[0];
+							jj -= step[1];
+							if (Math.abs(ii-i)>=1 || Math.abs(jj-j)>=1)
+							{
+								move.vanish.push(
+									new PiPo({
+										p:this.getPiece(i,j),
+										c:this.getColor(i,j),
+										x:i,
+										y:j
+									})
+								);
+								move.appear.push(
+									new PiPo({
+										p:this.getPiece(i,j),
+										c:this.getColor(i,j),
+										x:ii,
+										y:jj
+									})
+								);
+							}
+						}
+					}
+					break;
+				}
+				i += step[0];
+				j += step[1];
+			}
+		}
+		this.undo(standardMove);
 	}
 
 	getBasicMove([sx,sy], [ex,ey], tr)
@@ -47,6 +126,57 @@ class MagneticRules
 		return mv;
 	}
 
+	getPotentialPawnMoves([x,y])
+	{
+		const color = this.getColor(x,y);
+		var moves = [];
+		var V = VariantRules;
+		const [sizeX,sizeY] = VariantRules.size;
+		let shift = (color == "w" ? -1 : 1);
+		let startRank = (color == "w" ? sizeY-2 : 1);
+		let firstRank = (color == 'w' ? sizeY-1 : 0);
+		let lastRank = (color == "w" ? 0 : sizeY-1);
+
+		if (x+shift >= 0 && x+shift < sizeX && 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]));
+				}
+			}
+			// Captures
+			if (y>0 && this.canTake([x,y], [x+shift,y-1]) && this.board[x+shift][y-1] != V.EMPTY)
+				moves.push(this.getBasicMove([x,y], [x+shift,y-1]));
+			if (y<sizeY-1 && this.canTake([x,y], [x+shift,y+1]) && this.board[x+shift][y+1] != V.EMPTY)
+				moves.push(this.getBasicMove([x,y], [x+shift,y+1]));
+		}
+
+		if (x+shift == lastRank)
+		{
+			// 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}));
+				// Captures
+				if (y>0 && this.canTake([x,y], [x+shift,y-1]) && this.board[x+shift][y-1] != V.EMPTY)
+					moves.push(this.getBasicMove([x,y], [x+shift,y-1], {c:color,p:p}));
+				if (y<sizeY-1 && this.canTake([x,y], [x+shift,y+1]) && this.board[x+shift][y+1] != V.EMPTY)
+					moves.push(this.getBasicMove([x,y], [x+shift,y+1], {c:color,p:p}));
+			});
+		}
+
+		// No en passant
+
+		return moves;
+	}
+
 	getCastleMoves([x,y])
 	{
 		const c = this.getColor(x,y);
@@ -135,7 +265,7 @@ class MagneticRules
 		const saveKingPos = this.kingPos[c]; //king might be taken
 		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;
+		let res = this.kingPos[c][0] < 0
 			? [ JSON.parse(JSON.stringify(saveKingPos)) ]
 			: [ ];
 		this.undo(move);
diff --git a/views/rules/Magnetic.pug b/views/rules/Magnetic.pug
new file mode 100644
index 00000000..6c8002f6
--- /dev/null
+++ b/views/rules/Magnetic.pug
@@ -0,0 +1,32 @@
+p.boxed
+	| Each piece has a charge generating a magnetic field, attracting enemy pieces while repelling others.
+
+h3 Specifications
+
+ul
+	li Chessboard: standard.
+	li Material: standard.
+	li Non-capturing moves: standard + magnetic.
+	li Special moves: standard + magnetic.
+	li Captures: standard + magnetic.
+	li End of game: capture the king.
+
+h3 Basics
+
+p
+	| TODO: use diagram from chessvariants.com
+
+figure.diagram-container
+	.diagram
+		| fen:rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR:
+	figcaption TODO
+
+h3 End of the game
+
+p Win by capturing opponent's king. Thee is no notion of check or stalemate here.
+
+h3 Credits
+
+p
+	a(href="https://www.chessvariants.com/other.dir/magnetic.html") Magnetic chess 
+	| on chessvariants.com.