From: Benjamin Auder <benjamin.auder@somewhere>
Date: Tue, 21 Jun 2022 14:30:44 +0000 (+0200)
Subject: Add Alapo (unfinished). Reorganise pieces folder
X-Git-Url: https://git.auder.net/variants/Chakart/pieces/current/doc/html/packages.html?a=commitdiff_plain;h=f55a0a6753a62257c7caa62ae49c8a5673769065;p=xogo.git

Add Alapo (unfinished). Reorganise pieces folder
---

diff --git a/TODO b/TODO
index d879b34..73b76b0 100644
--- a/TODO
+++ b/TODO
@@ -1,6 +1,7 @@
+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
diff --git a/base_rules.js b/base_rules.js
index 1b22ae5..c19ee64 100644
--- a/base_rules.js
+++ b/base_rules.js
@@ -569,15 +569,16 @@ export default class ChessRules {
     // 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;
@@ -585,7 +586,7 @@ export default class ChessRules {
       // 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";
@@ -610,7 +611,7 @@ export default class ChessRules {
     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++) {
@@ -798,13 +799,14 @@ export default class ChessRules {
     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";
@@ -1051,7 +1053,7 @@ export default class ChessRules {
     return {
       x: 8,
       y: 8,
-      ratio: 1 //for rectangular board = y / x
+      ratio: 1 //for rectangular board = y / x (optional, 1 = default)
     };
   }
 
@@ -2210,9 +2212,9 @@ export default class ChessRules {
     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) {
@@ -2237,7 +2239,7 @@ export default class ChessRules {
       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);
diff --git a/pieces/Alapo/black_CIRCLE.svg b/pieces/Alapo/black_CIRCLE.svg
new file mode 100644
index 0000000..7948061
--- /dev/null
+++ b/pieces/Alapo/black_CIRCLE.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">
+  <circle cx="50" cy="50" r="40" fill="darkslategray" stroke="none"/>
+</svg>
diff --git a/pieces/Alapo/black_SQUARE.svg b/pieces/Alapo/black_SQUARE.svg
new file mode 100644
index 0000000..fdd9921
--- /dev/null
+++ b/pieces/Alapo/black_SQUARE.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">
+  <polygon points="10,10 10,90, 90,90 90,10 10,10" fill="darkslategray" stroke="none"/>
+</svg>
diff --git a/pieces/Alapo/black_TRIANGLE.svg b/pieces/Alapo/black_TRIANGLE.svg
new file mode 100644
index 0000000..939ba3a
--- /dev/null
+++ b/pieces/Alapo/black_TRIANGLE.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">
+  <polygon points="50,10 90,90 10,90 50,10" fill="darkslategray" stroke="none"/>
+</svg>
diff --git a/pieces/Alapo/black_TRIANGLE_inv.svg b/pieces/Alapo/black_TRIANGLE_inv.svg
new file mode 100644
index 0000000..fb3c955
--- /dev/null
+++ b/pieces/Alapo/black_TRIANGLE_inv.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">
+  <polygon points="50,90 10,10 90,10 50,90" fill="darkslategray" stroke="none"/>
+</svg>
diff --git a/pieces/Alapo/black_circle.svg b/pieces/Alapo/black_circle.svg
new file mode 100644
index 0000000..8cd85d9
--- /dev/null
+++ b/pieces/Alapo/black_circle.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">
+  <circle cx="50" cy="50" r="25" fill="darkslategray" stroke="none"/>
+</svg>
diff --git a/pieces/Alapo/black_square.svg b/pieces/Alapo/black_square.svg
new file mode 100644
index 0000000..3e86c70
--- /dev/null
+++ b/pieces/Alapo/black_square.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">
+  <polygon points="25,25 25,75, 75,75 75,25 25,25" fill="darkslategray" stroke="none"/>
+</svg>
diff --git a/pieces/Alapo/black_triangle.svg b/pieces/Alapo/black_triangle.svg
new file mode 100644
index 0000000..8c531b5
--- /dev/null
+++ b/pieces/Alapo/black_triangle.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">
+  <polygon points="50,25 75,75 25,75 50,25" fill="darkslategray" stroke="none"/>
+</svg>
diff --git a/pieces/Alapo/black_triangle_inv.svg b/pieces/Alapo/black_triangle_inv.svg
new file mode 100644
index 0000000..e9afcea
--- /dev/null
+++ b/pieces/Alapo/black_triangle_inv.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">
+  <polygon points="50,75 25,25 75,25 50,75" fill="darkslategray" stroke="none"/>
+</svg>
diff --git a/pieces/Alapo/white_CIRCLE.svg b/pieces/Alapo/white_CIRCLE.svg
new file mode 100644
index 0000000..af99afa
--- /dev/null
+++ b/pieces/Alapo/white_CIRCLE.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">
+  <circle cx="50" cy="50" r="40" fill="whitesmoke" stroke="black" stroke-width="1.2"/>
+</svg>
diff --git a/pieces/Alapo/white_SQUARE.svg b/pieces/Alapo/white_SQUARE.svg
new file mode 100644
index 0000000..716a8e5
--- /dev/null
+++ b/pieces/Alapo/white_SQUARE.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">
+  <polygon points="10,10 10,90, 90,90 90,10 10,10" fill="whitesmoke" stroke="black" stroke-width="1.2"/>
+</svg>
diff --git a/pieces/Alapo/white_TRIANGLE.svg b/pieces/Alapo/white_TRIANGLE.svg
new file mode 100644
index 0000000..411ec2f
--- /dev/null
+++ b/pieces/Alapo/white_TRIANGLE.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">
+  <polygon points="50,10 90,90 10,90 50,10" fill="whitesmoke" stroke="black" stroke-width="1.2"/>
+</svg>
diff --git a/pieces/Alapo/white_TRIANGLE_inv.svg b/pieces/Alapo/white_TRIANGLE_inv.svg
new file mode 100644
index 0000000..61733b1
--- /dev/null
+++ b/pieces/Alapo/white_TRIANGLE_inv.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">
+  <polygon points="50,90 10,10 90,10 50,90" fill="whitesmoke" stroke="black" stroke-width="1.2"/>
+</svg>
diff --git a/pieces/Alapo/white_circle.svg b/pieces/Alapo/white_circle.svg
new file mode 100644
index 0000000..f5f19cf
--- /dev/null
+++ b/pieces/Alapo/white_circle.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">
+  <circle cx="50" cy="50" r="25" fill="whitesmoke" stroke="black" stroke-width="1.2"/>
+</svg>
diff --git a/pieces/Alapo/white_square.svg b/pieces/Alapo/white_square.svg
new file mode 100644
index 0000000..9c7e4e7
--- /dev/null
+++ b/pieces/Alapo/white_square.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">
+  <polygon points="25,25 25,75, 75,75 75,25 25,25" fill="whitesmoke" stroke="black" stroke-width="1.2"/>
+</svg>
diff --git a/pieces/Alapo/white_triangle.svg b/pieces/Alapo/white_triangle.svg
new file mode 100644
index 0000000..abad0f9
--- /dev/null
+++ b/pieces/Alapo/white_triangle.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">
+  <polygon points="50,25 75,75 25,75 50,25" fill="whitesmoke" stroke="black" stroke-width="1.2"/>
+</svg>
diff --git a/pieces/Alapo/white_triangle_inv.svg b/pieces/Alapo/white_triangle_inv.svg
new file mode 100644
index 0000000..4791916
--- /dev/null
+++ b/pieces/Alapo/white_triangle_inv.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="100" height="100">
+  <polygon points="50,75 25,25 75,25 50,75" fill="whitesmoke" stroke="black" stroke-width="1.2"/>
+</svg>
diff --git a/pieces/ambiguous_target.svg b/pieces/Ambiguous/target.svg
similarity index 100%
rename from pieces/ambiguous_target.svg
rename to pieces/Ambiguous/target.svg
diff --git a/pieces/chakart_banana.svg b/pieces/Chakart/banana.svg
similarity index 100%
rename from pieces/chakart_banana.svg
rename to pieces/Chakart/banana.svg
diff --git a/pieces/chakart_bomb.svg b/pieces/Chakart/bomb.svg
similarity index 100%
rename from pieces/chakart_bomb.svg
rename to pieces/Chakart/bomb.svg
diff --git a/pieces/chakart_egg.svg b/pieces/Chakart/egg.svg
similarity index 100%
rename from pieces/chakart_egg.svg
rename to pieces/Chakart/egg.svg
diff --git a/pieces/chakart_mushroom.svg b/pieces/Chakart/mushroom.svg
similarity index 100%
rename from pieces/chakart_mushroom.svg
rename to pieces/Chakart/mushroom.svg
diff --git a/pieces/chakart_mystery_black.svg b/pieces/Chakart/mystery_black.svg
similarity index 100%
rename from pieces/chakart_mystery_black.svg
rename to pieces/Chakart/mystery_black.svg
diff --git a/pieces/chakart_mystery_white.svg b/pieces/Chakart/mystery_white.svg
similarity index 100%
rename from pieces/chakart_mystery_white.svg
rename to pieces/Chakart/mystery_white.svg
diff --git a/pieces/chakart_shell.svg b/pieces/Chakart/shell.svg
similarity index 100%
rename from pieces/chakart_shell.svg
rename to pieces/Chakart/shell.svg
diff --git a/variants.js b/variants.js
index c9af9e4..90e9244 100644
--- a/variants.js
+++ b/variants.js
@@ -1,7 +1,7 @@
 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'},
diff --git a/variants/Alapo/class.js b/variants/Alapo/class.js
new file mode 100644
index 0000000..eb0e73f
--- /dev/null
+++ b/variants/Alapo/class.js
@@ -0,0 +1,156 @@
+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" : "*"));
+  }
+
+};
diff --git a/variants/Alapo/rules.html b/variants/Alapo/rules.html
new file mode 100644
index 0000000..252699c
--- /dev/null
+++ b/variants/Alapo/rules.html
@@ -0,0 +1,7 @@
+<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>
diff --git a/variants/Alapo/style.css b/variants/Alapo/style.css
new file mode 100644
index 0000000..942f9f4
--- /dev/null
+++ b/variants/Alapo/style.css
@@ -0,0 +1,49 @@
+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');
+}
diff --git a/variants/Ambiguous/CREDITS b/variants/Ambiguous/CREDITS
new file mode 100644
index 0000000..68ab598
--- /dev/null
+++ b/variants/Ambiguous/CREDITS
@@ -0,0 +1,3 @@
+Images:
+
+https://freesvg.org/black-target
diff --git a/variants/Ambiguous/style.css b/variants/Ambiguous/style.css
index e31d810..db300f7 100644
--- a/variants/Ambiguous/style.css
+++ b/variants/Ambiguous/style.css
@@ -1,7 +1,7 @@
 @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 {
diff --git a/variants/Chakart/style.css b/variants/Chakart/style.css
index b3687ce..91ad633 100644
--- a/variants/Chakart/style.css
+++ b/variants/Chakart/style.css
@@ -1,19 +1,19 @@
 @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 {
@@ -29,14 +29,14 @@ piece.immobilized {
 }
 
 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 {