+Debug Alapo
+Add links to complete variants rules (Ambiguous...)
+
add variants :
-Ambiguous
-Refusal
Dark Racing Kings ? Checkered-Teleport ?
Otage, Emergo, Pacosako : fonction "buildPiece(arg1, arg2)" returns HTML element with 2 SVG or SVG + number
// Compare window ratio width / height to aspectRatio:
const windowRatio = window.innerWidth / window.innerHeight;
let cbWidth, cbHeight;
- if (windowRatio <= this.size.ratio) {
+ const vRatio = this.size.ratio || 1;
+ if (windowRatio <= vRatio) {
// Limiting dimension is width:
cbWidth = Math.min(window.innerWidth, 767);
- cbHeight = cbWidth / this.size.ratio;
+ cbHeight = cbWidth / vRatio;
}
else {
// Limiting dimension is height:
cbHeight = Math.min(window.innerHeight, 767);
- cbWidth = cbHeight * this.size.ratio;
+ cbWidth = cbHeight * vRatio;
}
if (this.hasReserve) {
const sqSize = cbWidth / this.size.y;
// Cannot use getReserveSquareSize() here, but sqSize is an upper bound.
if ((window.innerHeight - cbHeight) / 2 < sqSize + 5) {
cbHeight = window.innerHeight - 2 * (sqSize + 5);
- cbWidth = cbHeight * this.size.ratio;
+ cbWidth = cbHeight * vRatio;
}
}
chessboard.style.width = cbWidth + "px";
const flipped = (this.playerColor == 'b');
let board = `
<svg
- viewBox="0 0 80 80"
+ viewBox="0 0 ${10*this.size.y} ${10*this.size.x}"
class="chessboard_SVG">`;
for (let i=0; i < this.size.x; i++) {
for (let j=0; j < this.size.y; j++) {
const multFact = (mode == "up" ? 1.05 : 0.95);
let [newWidth, newHeight] = [multFact * r.width, multFact * r.height];
// Stay in window:
+ const vRatio = this.size.ratio || 1;
if (newWidth > window.innerWidth) {
newWidth = window.innerWidth;
- newHeight = newWidth / this.size.ratio;
+ newHeight = newWidth / vRatio;
}
if (newHeight > window.innerHeight) {
newHeight = window.innerHeight;
- newWidth = newHeight * this.size.ratio;
+ newWidth = newHeight * vRatio;
}
chessboard.style.width = newWidth + "px";
chessboard.style.height = newHeight + "px";
return {
x: 8,
y: 8,
- ratio: 1 //for rectangular board = y / x
+ ratio: 1 //for rectangular board = y / x (optional, 1 = default)
};
}
this.afterPlay(move); //user method
}
- getMaxDistance(rwidth) {
+ getMaxDistance(r) {
// Works for all rectangular boards:
- return Math.sqrt(rwidth ** 2 + (rwidth / this.size.ratio) ** 2);
+ return Math.sqrt(r.width ** 2 + r.height ** 2);
}
getDomPiece(x, y) {
movingPiece.style.width = pieceWidth + "px";
movingPiece.style.height = pieceWidth + "px";
}
- const maxDist = this.getMaxDistance(r.width);
+ const maxDist = this.getMaxDistance(r);
const pieces = this.pieces();
if (move.drag) {
const startCode = this.getPiece(move.start.x, move.start.y);
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>\r
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\r
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">\r
+ <circle cx="50" cy="50" r="40" fill="darkslategray" stroke="none"/>\r
+</svg>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>\r
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\r
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">\r
+ <polygon points="10,10 10,90, 90,90 90,10 10,10" fill="darkslategray" stroke="none"/>\r
+</svg>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>\r
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\r
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">\r
+ <polygon points="50,10 90,90 10,90 50,10" fill="darkslategray" stroke="none"/>\r
+</svg>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>\r
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\r
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">\r
+ <polygon points="50,90 10,10 90,10 50,90" fill="darkslategray" stroke="none"/>\r
+</svg>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>\r
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\r
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">\r
+ <circle cx="50" cy="50" r="25" fill="darkslategray" stroke="none"/>\r
+</svg>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>\r
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\r
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">\r
+ <polygon points="25,25 25,75, 75,75 75,25 25,25" fill="darkslategray" stroke="none"/>\r
+</svg>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>\r
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\r
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">\r
+ <polygon points="50,25 75,75 25,75 50,25" fill="darkslategray" stroke="none"/>\r
+</svg>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>\r
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\r
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">\r
+ <polygon points="50,75 25,25 75,25 50,75" fill="darkslategray" stroke="none"/>\r
+</svg>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>\r
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\r
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">\r
+ <circle cx="50" cy="50" r="40" fill="whitesmoke" stroke="black" stroke-width="1.2"/>\r
+</svg>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>\r
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\r
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">\r
+ <polygon points="10,10 10,90, 90,90 90,10 10,10" fill="whitesmoke" stroke="black" stroke-width="1.2"/>\r
+</svg>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>\r
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\r
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">\r
+ <polygon points="50,10 90,90 10,90 50,10" fill="whitesmoke" stroke="black" stroke-width="1.2"/>\r
+</svg>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>\r
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\r
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">\r
+ <polygon points="50,90 10,10 90,10 50,90" fill="whitesmoke" stroke="black" stroke-width="1.2"/>\r
+</svg>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>\r
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\r
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">\r
+ <circle cx="50" cy="50" r="25" fill="whitesmoke" stroke="black" stroke-width="1.2"/>\r
+</svg>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>\r
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\r
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">\r
+ <polygon points="25,25 25,75, 75,75 75,25 25,25" fill="whitesmoke" stroke="black" stroke-width="1.2"/>\r
+</svg>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>\r
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\r
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">\r
+ <polygon points="50,25 75,75 25,75 50,25" fill="whitesmoke" stroke="black" stroke-width="1.2"/>\r
+</svg>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>\r
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\r
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">\r
+ <polygon points="50,75 25,25 75,25 50,75" fill="whitesmoke" stroke="black" stroke-width="1.2"/>\r
+</svg>\r
const variants = [
// TODO: https://mancala.fandom.com/wiki/William_Daniel_Troyka Cleopatra chess
{name: 'Absorption', desc: 'Absorb powers'},
-// {name: 'Alapo', desc: 'Geometric Chess'},
+ {name: 'Alapo', desc: 'Geometric Chess'},
// {name: 'Alice', desc: 'Both sides of the mirror'},
// {name: 'Align4', desc: 'Align four pawns'},
// {name: 'Allmate', desc: 'Mate any piece'},
--- /dev/null
+import ChessRules from "/base_rules.js";
+import { ArrayFun } from "/utils/array.js";
+import { Random } from "/utils/alea.js";
+
+export default class AlapoRules extends ChessRules {
+
+ get hasFlags() {
+ return false;
+ }
+ get hasEnpassant() {
+ return false;
+ }
+
+ getSvgChessboard() {
+ let board = super.getSvgChessboard().slice(0, -6);
+ // Add lines to delimitate goals
+ board += `
+ <line x1="0" y1="10" x2="60" y2="10" stroke="black" stroke-width="0.1"/>
+ <line x1="0" y1="50" x2="60" y2="50" stroke="black" stroke-width="0.1"/>
+ </svg>`;
+ return board;
+ }
+
+ genRandInitFen(seed) {
+ if (this.options["randomness"] == 0)
+ return "rbqqbr/tcssct/6/6/TCSSCT/RBQQBR w 0";
+
+ Random.setSeed(seed);
+
+ const piece2pawn = {
+ r: 't',
+ q: 's',
+ b: 'c'
+ };
+
+ let pieces = { w: new Array(6), b: new Array(6) };
+ // Shuffle pieces on first (and last rank if randomness == 2)
+ for (let c of ["w", "b"]) {
+ if (c == 'b' && this.options["randomness"] == 1) {
+ pieces['b'] = pieces['w'];
+ break;
+ }
+
+ let positions = ArrayFun.range(6);
+
+ // Get random squares for bishops
+ let randIndex = 2 * Random.randInt(3);
+ const bishop1Pos = positions[randIndex];
+ let randIndex_tmp = 2 * Random.randInt(3) + 1;
+ const bishop2Pos = positions[randIndex_tmp];
+ positions.splice(Math.max(randIndex, randIndex_tmp), 1);
+ positions.splice(Math.min(randIndex, randIndex_tmp), 1);
+
+ // Get random square for queens
+ randIndex = Random.randInt(4);
+ const queen1Pos = positions[randIndex];
+ positions.splice(randIndex, 1);
+ randIndex = Random.randInt(3);
+ const queen2Pos = positions[randIndex];
+ positions.splice(randIndex, 1);
+
+ // Rooks positions are now fixed,
+ const rook1Pos = positions[0];
+ const rook2Pos = positions[1];
+
+ pieces[c][rook1Pos] = "r";
+ pieces[c][bishop1Pos] = "b";
+ pieces[c][queen1Pos] = "q";
+ pieces[c][queen2Pos] = "q";
+ pieces[c][bishop2Pos] = "b";
+ pieces[c][rook2Pos] = "r";
+ }
+
+ return (
+ pieces["b"].join("") + "/" +
+ pieces["b"].map(p => piece2pawn[p]).join("") +
+ "/6/6/" +
+ pieces["w"].map(p => piece2pawn[p].toUpperCase()).join("") + "/" +
+ pieces["w"].join("").toUpperCase() +
+ " w 0"
+ );
+ }
+
+ pieces(color, x, y) {
+ return {
+ 'r': super.pieces(color, x, y)['r'],
+ 'q': super.pieces(color, x, y)['q'],
+ 'b': {
+ // Triangle is rotated from opponent viewpoint
+ "class": "bishop" + (this.playerColor != color ? "_inv" : ""),
+ moves: [ { steps: [[1, 1], [1, -1], [-1, 1], [-1, -1]] } ]
+ },
+ 's': { //"square"
+ "class": "babyrook",
+ moves: [
+ {
+ steps: [[0, 1], [0, -1], [1, 0], [-1, 0]],
+ range: 1
+ }
+ ]
+ },
+ 'c': { //"circle"
+ "class": "babyqueen",
+ moves: [
+ {
+ steps: [
+ [0, 1], [0, -1], [1, 0], [-1, 0],
+ [1, 1], [1, -1], [-1, 1], [-1, -1]
+ ],
+ range: 1
+ }
+ ]
+ },
+ 't': { //"triangle"
+ "class": "babybishop" + (this.playerColor != color ? "_inv" : ""),
+ moves: [
+ {
+ steps: [[1, 1], [1, -1], [-1, 1], [-1, -1]],
+ range: 1
+ }
+ ]
+ }
+ };
+ }
+
+ get size() {
+ return {
+ x: 6,
+ y: 6
+ };
+ }
+
+ filterValid(moves) {
+ return moves;
+ }
+
+ getCurrentScore() {
+ // Try both colors (to detect potential suicides)
+ let won = {};
+ for (let c of ['w', 'b']) {
+ const oppCol = C.GetOppCol(c);
+ const goal = (c == 'w' ? 0 : 5);
+ won[c] = this.board[goal].some((b,j) => {
+ return (
+ this.getColor(goal, j) == c &&
+ this.findCapturesOn(
+ [goal, j], {one: true, oppCol: oppCol}).length == 0
+ );
+ });
+ }
+ if (won['w'] && won['b'])
+ return "?"; //no idea who won, not relevant anyway :)
+ return (won['w'] ? "1-0" : (won['b'] ? "0-1" : "*"));
+ }
+
+};
--- /dev/null
+<p>Pieces move like rook, bishop and queen. Small ones by one square only.</p>
+
+<p>Goal: bring a piece safely on the last rank.</p>
+
+<a href="https://www.chessvariants.com/small.dir/alapo.html">
+ chessvariants page.
+</a>
--- /dev/null
+piece.black.rook {
+ background-image: url('/pieces/Alapo/black_SQUARE.svg');
+}
+piece.black.bishop {
+ background-image: url('/pieces/Alapo/black_TRIANGLE.svg');
+}
+piece.black.bishop_inv {
+ background-image: url('/pieces/Alapo/black_TRIANGLE_inv.svg');
+}
+piece.black.queen {
+ background-image: url('/pieces/Alapo/black_CIRCLE.svg');
+}
+piece.black.babyrook {
+ background-image: url('/pieces/Alapo/black_square.svg');
+}
+piece.black.babybishop {
+ background-image: url('/pieces/Alapo/black_triangle.svg');
+}
+piece.black.babybishop {
+ background-image: url('/pieces/Alapo/black_triangle_inv.svg');
+}
+piece.black.babyqueen {
+ background-image: url('/pieces/Alapo/black_circle.svg');
+}
+
+piece.white.rook {
+ background-image: url('/pieces/Alapo/white_SQUARE.svg');
+}
+piece.white.bishop {
+ background-image: url('/pieces/Alapo/white_TRIANGLE.svg');
+}
+piece.white.bishop {
+ background-image: url('/pieces/Alapo/white_TRIANGLE_inv.svg');
+}
+piece.white.queen {
+ background-image: url('/pieces/Alapo/white_CIRCLE.svg');
+}
+piece.white.babyrook {
+ background-image: url('/pieces/Alapo/white_square.svg');
+}
+piece.white.babybishop {
+ background-image: url('/pieces/Alapo/white_triangle.svg');
+}
+piece.white.babybishop {
+ background-image: url('/pieces/Alapo/white_triangle_inv.svg');
+}
+piece.white.babyqueen {
+ background-image: url('/pieces/Alapo/white_circle.svg');
+}
--- /dev/null
+Images:
+
+https://freesvg.org/black-target
@import url("/base_pieces.css");
piece.target {
- background-image: url('/pieces/ambiguous_target.svg');
+ background-image: url('/pieces/Ambiguous/target.svg');
}
piece.white.target-pawn {
@import url("/base_pieces.css");
piece.egg {
- background-image: url('/pieces/chakart_egg.svg');
+ background-image: url('/pieces/Chakart/egg.svg');
}
piece.mushroom {
- background-image: url('/pieces/chakart_mushroom.svg');
+ background-image: url('/pieces/Chakart/mushroom.svg');
}
piece.banana {
- background-image: url('/pieces/chakart_banana.svg');
+ background-image: url('/pieces/Chakart/banana.svg');
}
piece.bomb {
- background-image: url('/pieces/chakart_bomb.svg');
+ background-image: url('/pieces/Chakart/bomb.svg');
}
piece.white.invisible {
}
piece.remote-capture {
- background-image: url('/pieces/chakart_shell.svg');
+ background-image: url('/pieces/Chakart/shell.svg');
}
piece.mystery.white {
- background-image: url('/pieces/chakart_mystery_white.svg');
+ background-image: url('/pieces/Chakart/mystery_white.svg');
}
piece.mystery.black {
- background-image: url('/pieces/chakart_mystery_black.svg');
+ background-image: url('/pieces/Chakart/mystery_black.svg');
}
div.bonus-text {