From 26c1e3bd4d3e9fb7c86e25c0f423bea57b977111 Mon Sep 17 00:00:00 2001
From: Benjamin Auder <benjamin.auder@somewhere>
Date: Tue, 25 Dec 2018 09:14:11 +0100
Subject: [PATCH] Various fixes, additions...

---
 .../images/pieces/{Ultima => Baroque}/bm.svg  |  0
 .../images/pieces/{Ultima => Baroque}/wm.svg  |  0
 public/javascripts/base_rules.js              | 84 ++++++++++++-------
 public/javascripts/utils/printDiagram.js      |  5 +-
 public/javascripts/variants/Alice.js          |  2 +-
 .../variants/{Ultima.js => Baroque.js}        |  0
 public/javascripts/variants/Berolina.js       | 60 ++++++++++---
 public/javascripts/variants/Checkered.js      |  2 +-
 .../variants/{Loser.js => Losers.js}          |  4 +-
 public/javascripts/variants/Switching.js      |  6 +-
 public/javascripts/variants/Upsidedown.js     | 49 ++++++-----
 public/stylesheets/layout.sass                |  3 +
 views/rules/{Ultima => Baroque}/en.pug        |  7 ++
 views/rules/{Ultima => Baroque}/fr.pug        |  7 ++
 views/rules/Checkered/en.pug                  | 24 ++++++
 views/rules/Checkered/fr.pug                  | 31 ++++++-
 views/rules/{Loser => Losers}/en.pug          |  0
 views/rules/{Loser => Losers}/fr.pug          |  0
 18 files changed, 206 insertions(+), 78 deletions(-)
 rename public/images/pieces/{Ultima => Baroque}/bm.svg (100%)
 rename public/images/pieces/{Ultima => Baroque}/wm.svg (100%)
 rename public/javascripts/variants/{Ultima.js => Baroque.js} (100%)
 rename public/javascripts/variants/{Loser.js => Losers.js} (98%)
 rename views/rules/{Ultima => Baroque}/en.pug (96%)
 rename views/rules/{Ultima => Baroque}/fr.pug (96%)
 rename views/rules/{Loser => Losers}/en.pug (100%)
 rename views/rules/{Loser => Losers}/fr.pug (100%)

diff --git a/public/images/pieces/Ultima/bm.svg b/public/images/pieces/Baroque/bm.svg
similarity index 100%
rename from public/images/pieces/Ultima/bm.svg
rename to public/images/pieces/Baroque/bm.svg
diff --git a/public/images/pieces/Ultima/wm.svg b/public/images/pieces/Baroque/wm.svg
similarity index 100%
rename from public/images/pieces/Ultima/wm.svg
rename to public/images/pieces/Baroque/wm.svg
diff --git a/public/javascripts/base_rules.js b/public/javascripts/base_rules.js
index 0bf5114a..8b8165a0 100644
--- a/public/javascripts/base_rules.js
+++ b/public/javascripts/base_rules.js
@@ -77,7 +77,7 @@ class ChessRules
 			if (fenParsed.enpassant != "-")
 			{
 				const ep = V.SquareToCoords(fenParsed.enpassant);
-				if (ep.y < 0 || ep.y > V.size.y || isNaN(ep.x) || ep.x < 0 || ep.x > V.size.x)
+				if (isNaN(ep.x) || !V.OnBoard(ep))
 					return false;
 			}
 		}
@@ -119,8 +119,14 @@ class ChessRules
 		return !!flags.match(/^[01]{4,4}$/);
 	}
 
-	// 3 --> d (column letter from number)
-	static GetColumn(colnum)
+	// 3 --> d (column number to letter)
+	static CoordToColumn(colnum)
+	{
+		return String.fromCharCode(97 + colnum);
+	}
+
+	// d --> 3 (column letter to number)
+	static ColumnToCoord(colnum)
 	{
 		return String.fromCharCode(97 + colnum);
 	}
@@ -129,6 +135,8 @@ class ChessRules
 	static SquareToCoords(sq)
 	{
 		return {
+			// NOTE: column is always one char => max 26 columns
+			// row is counted from black side => subtraction
 			x: V.size.x - parseInt(sq.substr(1)),
 			y: sq[0].charCodeAt() - 97
 		};
@@ -137,7 +145,7 @@ class ChessRules
 	// {x:0,y:4} --> e8
 	static CoordsToSquare(coords)
 	{
-		return V.GetColumn(coords.y) + (V.size.x - coords.x);
+		return V.CoordToColumn(coords.y) + (V.size.x - coords.x);
 	}
 
 	// Aggregates flags into one object
@@ -217,31 +225,32 @@ class ChessRules
 
 			// Get random squares for bishops
 			let randIndex = 2 * _.random(3);
-			let bishop1Pos = positions[randIndex];
+			const bishop1Pos = positions[randIndex];
 			// The second bishop must be on a square of different color
 			let randIndex_tmp = 2 * _.random(3) + 1;
-			let bishop2Pos = positions[randIndex_tmp];
+			const bishop2Pos = positions[randIndex_tmp];
 			// Remove chosen squares
 			positions.splice(Math.max(randIndex,randIndex_tmp), 1);
 			positions.splice(Math.min(randIndex,randIndex_tmp), 1);
 
 			// Get random squares for knights
 			randIndex = _.random(5);
-			let knight1Pos = positions[randIndex];
+			const knight1Pos = positions[randIndex];
 			positions.splice(randIndex, 1);
 			randIndex = _.random(4);
-			let knight2Pos = positions[randIndex];
+			const knight2Pos = positions[randIndex];
 			positions.splice(randIndex, 1);
 
 			// Get random square for queen
 			randIndex = _.random(3);
-			let queenPos = positions[randIndex];
+			const queenPos = positions[randIndex];
 			positions.splice(randIndex, 1);
 
-			// Rooks and king positions are now fixed, because of the ordering rook-king-rook
-			let rook1Pos = positions[0];
-			let kingPos = positions[1];
-			let rook2Pos = positions[2];
+			// Rooks and king positions are now fixed,
+			// because of the ordering rook-king-rook
+			const rook1Pos = positions[0];
+			const kingPos = positions[1];
+			const rook2Pos = positions[2];
 
 			// Finally put the shuffled pieces in the board array
 			pieces[c][rook1Pos] = 'r';
@@ -528,7 +537,8 @@ class ChessRules
 		}
 	}
 
-	// Build a regular move from its initial and destination squares; tr: transformation
+	// Build a regular move from its initial and destination squares.
+	// tr: transformation
 	getBasicMove([sx,sy], [ex,ey], tr)
 	{
 		let mv = new Move({
@@ -565,7 +575,8 @@ class ChessRules
 		return mv;
 	}
 
-	// Generic method to find possible moves of non-pawn pieces ("sliding or jumping")
+	// Generic method to find possible moves of non-pawn pieces:
+	// "sliding or jumping"
 	getSlideNJumpMoves([x,y], steps, oneStep)
 	{
 		const color = this.getColor(x,y);
@@ -680,7 +691,8 @@ class ChessRules
 	// What are the queen moves from square x,y ?
 	getPotentialQueenMoves(sq)
 	{
-		return this.getSlideNJumpMoves(sq, V.steps[V.ROOK].concat(V.steps[V.BISHOP]));
+		return this.getSlideNJumpMoves(sq,
+			V.steps[V.ROOK].concat(V.steps[V.BISHOP]));
 	}
 
 	// What are the king moves from square x,y ?
@@ -710,13 +722,15 @@ class ChessRules
 				continue;
 			// If this code is reached, rooks and king are on initial position
 
-			// Nothing on the path of the king (and no checks; OK also if y==finalSquare)?
+			// Nothing on the path of the king ?
+			// (And no checks; OK also if y==finalSquare)
 			let step = finalSquares[castleSide][0] < y ? -1 : 1;
 			for (i=y; i!=finalSquares[castleSide][0]; i+=step)
 			{
 				if (this.isAttacked([x,i], [oppCol]) || (this.board[x][i] != V.EMPTY &&
 					// NOTE: next check is enough, because of chessboard constraints
-					(this.getColor(x,i) != c || ![V.KING,V.ROOK].includes(this.getPiece(x,i)))))
+					(this.getColor(x,i) != c
+						|| ![V.KING,V.ROOK].includes(this.getPiece(x,i)))))
 				{
 					continue castlingCheck;
 				}
@@ -782,7 +796,8 @@ class ChessRules
 		});
 	}
 
-	// Search for all valid moves considering current turn (for engine and game end)
+	// Search for all valid moves considering current turn
+	// (for engine and game end)
 	getAllValidMoves()
 	{
 		const color = this.turn;
@@ -792,13 +807,14 @@ class ChessRules
 		{
 			for (let j=0; j<V.size.y; j++)
 			{
-				// Next condition "!= oppCol" = harmless hack to work with checkered variant
+				// Next condition "!= oppCol" to work with checkered variant
 				if (this.board[i][j] != V.EMPTY && this.getColor(i,j) != oppCol)
-					Array.prototype.push.apply(potentialMoves, this.getPotentialMovesFrom([i,j]));
+				{
+					Array.prototype.push.apply(potentialMoves,
+						this.getPotentialMovesFrom([i,j]));
+				}
 			}
 		}
-		// NOTE: prefer lazy undercheck tests, letting the king being taken?
-		// No: if happen on last 1/2 move, could lead to forbidden moves, wrong evals
 		return this.filterValid(potentialMoves);
 	}
 
@@ -828,7 +844,7 @@ class ChessRules
 		return false;
 	}
 
-	// Check if pieces of color in array 'colors' are attacking (king) on square x,y
+	// Check if pieces of color in 'colors' are attacking (king) on square x,y
 	isAttacked(sq, colors)
 	{
 		return (this.isAttackedByPawn(sq, colors)
@@ -984,7 +1000,6 @@ class ChessRules
 	play(move, ingame)
 	{
 		// DEBUG:
-//		console.log("DO");
 //		if (!this.states) this.states = [];
 //		if (!ingame) this.states.push(this.getFen());
 
@@ -1019,7 +1034,6 @@ class ChessRules
 		this.unupdateVariables(move);
 
 		// DEBUG:
-//		console.log("UNDO "+this.getNotation(move));
 //		if (this.getFen() != this.states[this.states.length-1])
 //			debugger;
 //		this.states.pop();
@@ -1127,12 +1141,14 @@ class ChessRules
 		// Rank moves using a min-max at depth 2
 		for (let i=0; i<moves1.length; i++)
 		{
-			moves1[i].eval = (color=="w" ? -1 : 1) * maxeval; //very low, I'm checkmated
+			// Initial self evaluation is very low: "I'm checkmated"
+			moves1[i].eval = (color=="w" ? -1 : 1) * maxeval;
 			this.play(moves1[i]);
 			let eval2 = undefined;
 			if (this.atLeastOneMove())
 			{
-				eval2 = (color=="w" ? 1 : -1) * maxeval; //initialized with checkmate value
+				// Initial enemy evaluation is very low too, for him
+				eval2 = (color=="w" ? 1 : -1) * maxeval;
 				// Second half-move:
 				let moves2 = this.getAllValidMoves("computer");
 				for (let j=0; j<moves2.length; j++)
@@ -1147,8 +1163,11 @@ class ChessRules
 						const score = this.checkGameEnd();
 						evalPos = (score=="1/2" ? 0 : (score=="1-0" ? 1 : -1) * maxeval);
 					}
-					if ((color == "w" && evalPos < eval2) || (color=="b" && evalPos > eval2))
+					if ((color == "w" && evalPos < eval2)
+						|| (color=="b" && evalPos > eval2))
+					{
 						eval2 = evalPos;
+					}
 					this.undo(moves2[j]);
 				}
 			}
@@ -1187,7 +1206,8 @@ class ChessRules
 					this.alphabeta(V.SEARCH_DEPTH-1, -maxeval, maxeval);
 				this.undo(moves1[i]);
 			}
-			moves1.sort( (a,b) => { return (color=="w" ? 1 : -1) * (b.eval - a.eval); });
+			moves1.sort( (a,b) => {
+				return (color=="w" ? 1 : -1) * (b.eval - a.eval); });
 		}
 		else
 			return currentBest;
@@ -1284,12 +1304,12 @@ class ChessRules
 			if (move.vanish.length > move.appear.length)
 			{
 				// Capture
-				const startColumn = String.fromCharCode(97 + move.start.y);
+				const startColumn = V.CoordToColumn(move.start.y);
 				notation = startColumn + "x" + finalSquare;
 			}
 			else //no capture
 				notation = finalSquare;
-			if (move.appear.length > 0 && piece != move.appear[0].p) //promotion
+			if (move.appear.length > 0 && move.appear[0].p != V.PAWN) //promotion
 				notation += "=" + move.appear[0].p.toUpperCase();
 			return notation;
 		}
diff --git a/public/javascripts/utils/printDiagram.js b/public/javascripts/utils/printDiagram.js
index ef750490..61c726eb 100644
--- a/public/javascripts/utils/printDiagram.js
+++ b/public/javascripts/utils/printDiagram.js
@@ -15,9 +15,8 @@ function getDiagram(args)
 		for (let i=0; i<squares.length; i++)
 		{
 			const res = /^([a-z]+)([0-9]+)$/i.exec(squares[i]);
-			const x = sizeX - parseInt(res[2]); //white at bottom, so counting is reversed
-			const y = res[1].charCodeAt(0)-97; //always one char: max 26, big enough
-			markArray[x][y] = true;
+			const coords = V.SquareToCoords(res);
+			markArray[coords.x][coords.y] = true;
 		}
 	}
 	let boardDiv = "";
diff --git a/public/javascripts/variants/Alice.js b/public/javascripts/variants/Alice.js
index 2be714f0..2788e210 100644
--- a/public/javascripts/variants/Alice.js
+++ b/public/javascripts/variants/Alice.js
@@ -324,7 +324,7 @@ class AliceRules extends ChessRules
 		const captureMark = (move.vanish.length > move.appear.length ? "x" : "");
 		let pawnMark = "";
 		if (["p","s"].includes(piece) && captureMark.length == 1)
-			pawnMark = V.GetColumn(move.start.y); //start column
+			pawnMark = V.CoordToColumn(move.start.y); //start column
 
 		// Piece or pawn movement
 		let notation = piece.toUpperCase() + pawnMark + captureMark + finalSquare;
diff --git a/public/javascripts/variants/Ultima.js b/public/javascripts/variants/Baroque.js
similarity index 100%
rename from public/javascripts/variants/Ultima.js
rename to public/javascripts/variants/Baroque.js
diff --git a/public/javascripts/variants/Berolina.js b/public/javascripts/variants/Berolina.js
index dc9e2574..be72e2d5 100644
--- a/public/javascripts/variants/Berolina.js
+++ b/public/javascripts/variants/Berolina.js
@@ -10,17 +10,26 @@ class BerolinaRules extends ChessRules
 			const square = moveOrSquare;
 			if (square == "-")
 				return undefined;
-			return V.SquareToCoords(square);
+			// Enemy pawn initial column must be given too:
+			let res = [];
+			const epParts = square.split(",");
+			res.push(V.SquareToCoords(epParts[0]));
+			res.push(V.ColumnToCoord(epParts[1]));
+			return res;
 		}
 		// Argument is a move:
 		const move = moveOrSquare;
 		const [sx,ex,sy] = [move.start.x,move.end.x,move.start.y];
 		if (this.getPiece(sx,sy) == V.PAWN && Math.abs(sx - ex) == 2)
 		{
-			return {
-				x: (ex + sx)/2,
-				y: (move.end.y + sy)/2
-			};
+			return
+			[
+				{
+					x: (ex + sx)/2,
+					y: (move.end.y + sy)/2
+				},
+				move.end.y
+			];
 		}
 		return undefined; //default
 	}
@@ -47,7 +56,10 @@ class BerolinaRules extends ChessRules
 				if (this.board[x+shiftX][y+shiftY] == V.EMPTY)
 				{
 					for (let piece of finalPieces)
-						moves.push(this.getBasicMove([x,y], [x+shiftX,y+shiftY], {c:color,p:piece}));
+					{
+						moves.push(this.getBasicMove([x,y], [x+shiftX,y+shiftY],
+							{c:color,p:piece}));
+					}
 					if (x == startRank && y+2*shiftY>=0 && y+2*shiftY<sizeY
 						&& this.board[x+2*shiftX][y+2*shiftY] == V.EMPTY)
 					{
@@ -68,14 +80,15 @@ class BerolinaRules extends ChessRules
 		// En passant
 		const Lep = this.epSquares.length;
 		const epSquare = this.epSquares[Lep-1]; //always at least one element
-		if (!!epSquare && epSquare.x == x+shiftX && epSquare.y == y)
+		if (!!epSquare && epSquare[0].x == x+shiftX && epSquare[0].y == y
+			&& Math.abs(epSquare[1] - y) == 1)
 		{
 			let enpassantMove = this.getBasicMove([x,y], [x+shiftX,y]);
 			enpassantMove.vanish.push({
-				x: epSquare.x,
-				y: epSquare.y,
+				x: x,
+				y: epSquare[1],
 				p: 'p',
-				c: this.getColor(epSquare.x,epSquare.y)
+				c: this.getColor(x,epSquare[1])
 			});
 			moves.push(enpassantMove);
 		}
@@ -90,12 +103,37 @@ class BerolinaRules extends ChessRules
 			let pawnShift = (c=="w" ? 1 : -1);
 			if (x+pawnShift>=0 && x+pawnShift<V.size.x)
 			{
-				if (this.getPiece(x+pawnShift,y)==V.PAWN && this.getColor(x+pawnShift,y)==c)
+				if (this.getPiece(x+pawnShift,y)==V.PAWN
+					&& this.getColor(x+pawnShift,y)==c)
+				{
 					return true;
+				}
 			}
 		}
 		return false;
 	}
+
+	getNotation(move)
+	{
+		const piece = this.getPiece(move.start.x, move.start.y);
+		if (piece == V.PAWN)
+		{
+			// Pawn move
+			let notation = "";
+			if (move.vanish.length == 2) //capture
+				notation = finalSquare;
+			else
+			{
+				// No capture
+				const startColumn = V.CoordToColumn(move.start.y);
+				notation = startColumn + "x" + finalSquare;
+			}
+			if (move.appear[0].p != V.PAWN) //promotion
+				notation += "=" + move.appear[0].p.toUpperCase();
+			return notation;
+		}
+		return super.getNotation(move); //all other pieces are orthodox
+	}
 }
 
 const VariantRules = BerolinaRules;
diff --git a/public/javascripts/variants/Checkered.js b/public/javascripts/variants/Checkered.js
index eee21b82..4a9419a8 100644
--- a/public/javascripts/variants/Checkered.js
+++ b/public/javascripts/variants/Checkered.js
@@ -278,7 +278,7 @@ class CheckeredRules extends ChessRules
 			if (move.vanish.length > 1)
 			{
 				// Capture
-				const startColumn = V.GetColumn(move.start.y);
+				const startColumn = V.CoordToColumn(move.start.y);
 				notation = startColumn + "x" + finalSquare +
 					"=" + move.appear[0].p.toUpperCase();
 			}
diff --git a/public/javascripts/variants/Loser.js b/public/javascripts/variants/Losers.js
similarity index 98%
rename from public/javascripts/variants/Loser.js
rename to public/javascripts/variants/Losers.js
index dcc5c112..c9509c6f 100644
--- a/public/javascripts/variants/Loser.js
+++ b/public/javascripts/variants/Losers.js
@@ -1,4 +1,4 @@
-class LoserRules extends ChessRules
+class LosersRules extends ChessRules
 {
 	static get HasFlags() { return false; }
 
@@ -184,4 +184,4 @@ class LoserRules extends ChessRules
 	}
 }
 
-const VariantRules = LoserRules;
+const VariantRules = LosersRules;
diff --git a/public/javascripts/variants/Switching.js b/public/javascripts/variants/Switching.js
index 53b14d58..67078f53 100644
--- a/public/javascripts/variants/Switching.js
+++ b/public/javascripts/variants/Switching.js
@@ -130,11 +130,7 @@ class SwitchingRules extends ChessRules
 		if (move.appear[0].p == V.KING && move.appear[1].p == V.ROOK)
 			return (move.end.y < move.start.y ? "0-0-0" : "0-0");
 		// Switch:
-		const startSquare =
-			String.fromCharCode(97 + move.start.y) + (V.size.x-move.start.x);
-		const finalSquare =
-			String.fromCharCode(97 + move.end.y) + (V.size.x-move.end.x);
-		return "S" + startSquare + finalSquare;
+		return "S" + V.CoordsToSquare(move.start) + V.CoordsToSquare(move.end);
 	}
 }
 
diff --git a/public/javascripts/variants/Upsidedown.js b/public/javascripts/variants/Upsidedown.js
index f9668997..1a812887 100644
--- a/public/javascripts/variants/Upsidedown.js
+++ b/public/javascripts/variants/Upsidedown.js
@@ -2,13 +2,7 @@ class UpsidedownRules extends ChessRules
 {
 	static HasFlags() { return false; }
 
-	// Forbid two knights moves in a row at moves 1 and 2
-	getPotentialKnightMoves(sq)
-	{
-		// But this will also affect FEN for problems, and...
-		// does it really solve the problem ?
-		//if (this.moves. ...)
-	}
+	static HasEnpassant() { return false; }
 
 	getPotentialKingMoves(sq)
 	{
@@ -24,27 +18,40 @@ class UpsidedownRules extends ChessRules
 		{
 			let positions = _.range(8);
 
-			let randIndex = 2 * _.random(3);
-			let bishop1Pos = positions[randIndex];
-			let randIndex_tmp = 2 * _.random(3) + 1;
-			let bishop2Pos = positions[randIndex_tmp];
+			let randIndex = _.random(7);
+			const kingPos = positions[randIndex];
+			positions.splice(randIndex, 1);
+
+			// At least a knight must be next to the king:
+			let knight1Pos = undefined;
+			if (kingPos == 0)
+				knight1Pos = 1;
+			else if (kingPos == V.size.y-1)
+				knight1Pos = V.size.y-2;
+			else
+				knight1Pos = kingPos + (Math.random() < 0.5 ? 1 : -1);
+			// Search for knight1Pos index in positions and remove it
+			const knight1Index = positions.indexOf(knight1Pos);
+			positions.splice(knight1Index, 1);
+
+			// King+knight1 are on two consecutive squares: one light, one dark
+			randIndex = 2 * _.random(2);
+			const bishop1Pos = positions[randIndex];
+			let randIndex_tmp = 2 * _.random(2) + 1;
+			const bishop2Pos = positions[randIndex_tmp];
 			positions.splice(Math.max(randIndex,randIndex_tmp), 1);
 			positions.splice(Math.min(randIndex,randIndex_tmp), 1);
 
-			randIndex = _.random(5);
-			let knight1Pos = positions[randIndex];
-			positions.splice(randIndex, 1);
-			randIndex = _.random(4);
-			let knight2Pos = positions[randIndex];
+			randIndex = _.random(3);
+			const knight2Pos = positions[randIndex];
 			positions.splice(randIndex, 1);
 
-			randIndex = _.random(3);
-			let queenPos = positions[randIndex];
+			randIndex = _.random(2);
+			const queenPos = positions[randIndex];
 			positions.splice(randIndex, 1);
 
-			let rook1Pos = positions[0];
-			let kingPos = positions[1];
-			let rook2Pos = positions[2];
+			const rook1Pos = positions[0];
+			const rook2Pos = positions[1];
 
 			pieces[c][rook1Pos] = 'r';
 			pieces[c][knight1Pos] = 'n';
diff --git a/public/stylesheets/layout.sass b/public/stylesheets/layout.sass
index cb8f8018..e70d3fe4 100644
--- a/public/stylesheets/layout.sass
+++ b/public/stylesheets/layout.sass
@@ -59,6 +59,9 @@ a
 .bigfont
   font-size: 1.2em
 
+.bold
+  font-weight: bold
+
 [type="checkbox"].modal+div .card
   max-width: 767px
   max-height: 100vh
diff --git a/views/rules/Ultima/en.pug b/views/rules/Baroque/en.pug
similarity index 96%
rename from views/rules/Ultima/en.pug
rename to views/rules/Baroque/en.pug
index e2876fdf..fb781641 100644
--- a/views/rules/Ultima/en.pug
+++ b/views/rules/Baroque/en.pug
@@ -3,6 +3,13 @@ p.boxed
 	| They generally move like an orthodox queen,
 	| but capturing rules are complex.
 
+p
+	| Note: 'Baroque' is the initial name thought by the author,
+	| but 'Ultima' is also largely adopted.
+	a(href="https://www.chessvariants.com/people.dir/abbott.html")
+		| He prefers 'Baroque'
+	| , and I think me too.
+
 h3 Specifications
 
 ul
diff --git a/views/rules/Ultima/fr.pug b/views/rules/Baroque/fr.pug
similarity index 96%
rename from views/rules/Ultima/fr.pug
rename to views/rules/Baroque/fr.pug
index 006df693..b49a66b0 100644
--- a/views/rules/Ultima/fr.pug
+++ b/views/rules/Baroque/fr.pug
@@ -2,6 +2,13 @@ p.boxed
 	| La plupart des pièces sont connues mais se déplacent différemment ;
 	| en général comme une dame orthodoxe, mais les captures sont complexes.
 
+p
+	| Note : le nom initialement choisit par l'auteur est 'Baroque',
+	| mais 'Ultima' est également largement utilisé.
+	a(href="https://www.chessvariants.com/people.dir/abbott.html")
+		| Il préfère 'Baroque'
+	| , et moi aussi je crois.
+
 h3 Caractéristiques
 
 ul
diff --git a/views/rules/Checkered/en.pug b/views/rules/Checkered/en.pug
index ac78d65e..9ce4f10c 100644
--- a/views/rules/Checkered/en.pug
+++ b/views/rules/Checkered/en.pug
@@ -11,6 +11,8 @@ figure.showPieces.center-align
 	img(src="/images/tmp_checkered/no_ck.png")
 	figcaption Checkered pieces, born after captures.
 
+p Note: the initial French name for this variant is "l'Échiqueté".
+
 h3 Specifications
 
 ul
@@ -65,6 +67,28 @@ ul
 		Checkered pawns cannot capture en passant, because while the pawn was "passing"
 		they were of the same color.
 
+p.bold.bigfont If you wanna play, you can stop reading here.
+
+h3 Stalemate or checkmate?
+
+p.
+	The following diagram seems to show a mating pattern, but the king if
+	"attacked" by a checkered pawn &ndash; which still belongs to white.
+	Therefore, it can be considered that it's not really a check because
+	white is unable to "give back the turn".
+	Without the black bishop on a7 it would be mate (without debate), because
+	the king could virtually go to g1 before being captured by the pawn-chamaleon.
+
+figure.diagram-container
+	.diagram
+		| fen:7k/b5pp/8/8/8/8/6ss/7K:
+	figcaption After 1...g2+(#?)
+
+p.
+	The interface considers that it's mate in both cases, following the idea
+	"it's checkmate if we cannot move, and the opponent on its turn could
+	take the king" (maybe after an impossible move).
+
 h2.stageDelimiter Stage 2
 
 p.warn This stage is not (and probably will never be) implemented.
diff --git a/views/rules/Checkered/fr.pug b/views/rules/Checkered/fr.pug
index 65282489..ddc9a6f4 100644
--- a/views/rules/Checkered/fr.pug
+++ b/views/rules/Checkered/fr.pug
@@ -11,6 +11,11 @@ figure.showPieces.center-align
 	img(src="/images/tmp_checkered/no_ck.png")
 	figcaption Pièces échiquetées, nées suite aux captures.
 
+p.
+	Note : le (vrai) nom initial de cette variante est "l'Échiqueté".
+	"Checkered" en est la traduction anglaise, et ce dernier terme me paraît
+	plus lisible pour des non francophones.
+
 h3 Caractéristiques
 
 ul
@@ -67,6 +72,28 @@ ul
 		Les pions échiquetés ne peuvent capturer en passant, puisque pendant que
 		le pion adverse "passait" ils étaient dans le même camp.
 
+p.bold.bigfont Pour jouer, vous pouvez arrêter de lire ici.
+
+h3 Mat ou pat ?
+
+p.
+	La situation du diagramme suivant ressemble à un mat, mais le roi est
+	"attaqué" par un pion échiqueté : celui-ci appartient pour l'instant aux blancs.
+	On peut donc considérer qu'ils ne sont pas vraiment en échec
+	puisqu'incapables de "rendre le trait".
+	Sans le fou noir en a7 ce serait mat (indiscutable), car le roi pourrait
+	virtuellement aller en g1 avant de se faire capturer par le pion caméléon.
+
+figure.diagram-container
+	.diagram
+		| fen:7k/b5pp/8/8/8/8/6ss/7K:
+	figcaption Après 1...g2+(#?)
+
+p.
+	L'interface considère que c'est mat dans les deux cas, partant
+	du principe que "c'est mat si on ne peut pas bouger et que l'adversaire
+	au trait peut capturer le roi" (éventuellement après un coup interdit).
+
 h2.stageDelimiter Phase 2
 
 p.warn Cette étape n'est pas (et ne sera probablement jamais) implémentée ici.
@@ -102,5 +129,5 @@ ul
 		Les règles de l'Échiqueté ont été déterminées par Patrick Bernier, puis
 		développées avec l'aide de Benjamin Auder.
 	li.
-		Merci également à Olive Martin, Christian Poisson, Bevis Martin, Laurent Nouhaud
-		et Frédéric Fradet.
+		Merci également à Olive Martin, Christian Poisson, Bevis Martin,
+		Laurent Nouhaud et Frédéric Fradet.
diff --git a/views/rules/Loser/en.pug b/views/rules/Losers/en.pug
similarity index 100%
rename from views/rules/Loser/en.pug
rename to views/rules/Losers/en.pug
diff --git a/views/rules/Loser/fr.pug b/views/rules/Losers/fr.pug
similarity index 100%
rename from views/rules/Loser/fr.pug
rename to views/rules/Losers/fr.pug
-- 
2.44.0