Add some more variants; TODO: Doublemove options
authorBenjamin Auder <benjamin.auder@somewhere>
Thu, 21 Apr 2022 06:32:51 +0000 (08:32 +0200)
committerBenjamin Auder <benjamin.auder@somewhere>
Thu, 21 Apr 2022 06:32:51 +0000 (08:32 +0200)
29 files changed:
server.js
variants.js
variants/Atomic/class.js [new file with mode: 0644]
variants/Atomic/rules.html [new file with mode: 0644]
variants/Atomic/style.css [new file with mode: 0644]
variants/Balanced/class.js [new file with mode: 0644]
variants/Balanced/rules.html [new file with mode: 0644]
variants/Balanced/style.css [new file with mode: 0644]
variants/Cannibal/class.js [new file with mode: 0644]
variants/Cannibal/rules.html [new file with mode: 0644]
variants/Cannibal/style.css [new file with mode: 0644]
variants/Capture/class.js [new file with mode: 0644]
variants/Capture/rules.html [new file with mode: 0644]
variants/Capture/style.css [new file with mode: 0644]
variants/Chakart/class.js [moved from variants/Chakart/Chakart.js with 100% similarity]
variants/Chakart/rules.html
variants/Crazyhouse/class.js [new file with mode: 0644]
variants/Crazyhouse/rules.html [new file with mode: 0644]
variants/Crazyhouse/style.css [new file with mode: 0644]
variants/Cylinder/class.js [new file with mode: 0644]
variants/Cylinder/rules.html [new file with mode: 0644]
variants/Cylinder/style.css [new file with mode: 0644]
variants/Dark/class.js [new file with mode: 0644]
variants/Dark/rules.html [new file with mode: 0644]
variants/Dark/style.css [new file with mode: 0644]
variants/Doublemove/class.js [new file with mode: 0644]
variants/Doublemove/rules.html [new file with mode: 0644]
variants/Doublemove/style.css [new file with mode: 0644]
variants/Zen/class.js

index 72d285c..5661136 100644 (file)
--- a/server.js
+++ b/server.js
@@ -17,7 +17,7 @@ function send(sid, code, data) {
   // If a player deletes local infos and then tries to resume a game,
   // sockets[oppSid] will probably not exist anymore:
   if (socket)
-    socket.send(JSON.stringify(Object.assign({ code: code }, data)));
+    socket.send(JSON.stringify(Object.assign({code: code}, data)));
 }
 
 function initializeGame(vname, players, options) {
index fb77f1d..6daa94b 100644 (file)
 const variants = [
-/*  { name: 'Absorption', desc: 'Absorb powers' },
-  { 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' },
-  { name: 'Ambiguous', desc: "Play opponent's pieces" },
-  { name: 'Antiking1', desc: 'Keep antiking in check', disp: 'Anti-King' },
-  { name: 'Antimatter', desc: 'Dangerous collisions', disp: 'Antimatter' },
-  { name: 'Apocalypse', desc: 'The end of the world' },
-  { name: 'Arena', desc: 'Middle battle' },
-  { name: 'Atarigo', desc: 'First capture wins', disp: 'Atari-Go' },
-  { name: 'Atomic', desc: 'Explosive captures' },
-  { name: 'Avalam', desc: 'Build towers' },
-  { name: 'Avalanche', desc: 'Pawnfalls' },
-  { name: 'Ball', desc: 'Score a goal' },
-  { name: 'Balaklava', desc: 'Meet the Mammoth' },
-  { name: 'Bario', desc: 'A quantum story' },
-  { name: 'Baroque', desc: 'Exotic captures' },*/
-  { name: "Benedict", desc: "Change colors" },
-/*  { name: 'Berolina', desc: 'Pawns move diagonally' },
-  { name: 'Bicolour', desc: 'Harassed kings' },
-  { name: 'Bishopawns', desc: 'Bishop versus pawns', disp: 'Bishop-Pawns' },
-  { name: 'Brotherhood', desc: 'Friendly pieces' },
+//  { name: 'Absorption', desc: 'Absorb powers' },
+//  { 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' },
+//  { name: 'Ambiguous', desc: "Play opponent's pieces" },
+//  { name: 'Antiking1', desc: 'Keep antiking in check', disp: 'Anti-King' },
+//  { name: 'Antimatter', desc: 'Dangerous collisions', disp: 'Antimatter' },
+//  { name: 'Apocalypse', desc: 'The end of the world' },
+//  { name: 'Arena', desc: 'Middle battle' },
+//  { name: 'Atarigo', desc: 'First capture wins', disp: 'Atari-Go' },
+  {name: 'Atomic', desc: 'Explosive captures'},
+//  { name: 'Avalam', desc: 'Build towers' },
+//  { name: 'Avalanche', desc: 'Pawnfalls' },
+//  { name: 'Ball', desc: 'Score a goal' },
+//  { name: 'Balaklava', desc: 'Meet the Mammoth' },
+//  { name: 'Bario', desc: 'A quantum story' },
+  {name: "Balanced", desc: "balanced chess"},
+//  { name: 'Baroque', desc: 'Exotic captures' },*/
+//  { name: "Benedict", desc: "Change colors" },
+//  { name: 'Berolina', desc: 'Pawns move diagonally' },
+//  { name: 'Bicolour', desc: 'Harassed kings' },
+//  { name: 'Bishopawns', desc: 'Bishop versus pawns', disp: 'Bishop-Pawns' },
+//  { name: 'Brotherhood', desc: 'Friendly pieces' },
   { name: 'Cannibal', desc: 'Capture powers' },
-  { name: 'Capablanca', desc: 'Capablanca Chess', disp: 'Capablanca Chess' },
+//  { name: 'Capablanca', desc: 'Capablanca Chess', disp: 'Capablanca Chess' },
   { name: 'Capture', desc: 'Mandatory captures' },
-  { name: 'Castle', desc: 'Win by castling long' },
-  { name: 'Chakart', desc: 'Capture the princess' },
-  { name: 'Checkered', desc: 'Shared pieces' },
-  { name: 'Checkless', desc: 'No-check mode' },
-*/  { name: 'Chess960', disp: "Chess 960", desc: "Standard rules" },
-/*  { name: 'Circular', desc: 'Run forward' },
-  { name: 'Clorange', desc: 'A Clockwork Orange', disp: 'Clockwork Orange' },
-  { name: 'Convert', desc: 'Convert enemy pieces' },
-  { name: 'Copycat', desc: 'Borrow powers' },
-  { name: 'Coregal', desc: 'Two royal pieces' },
-  { name: 'Coronation', desc: 'Long live the Queen' },
+//  { name: 'Castle', desc: 'Win by castling long' },
+//  { name: 'Chakart', desc: 'Capture the princess' },
+//  { name: 'Checkered', desc: 'Shared pieces' },
+//  { name: 'Checkless', desc: 'No-check mode' },
+  { name: 'Chess960', disp: "Chess 960", desc: "Standard rules" },
+//  { name: 'Circular', desc: 'Run forward' },
+//  { name: 'Clorange', desc: 'A Clockwork Orange', disp: 'Clockwork Orange' },
+//  { name: 'Convert', desc: 'Convert enemy pieces' },
+//  { name: 'Copycat', desc: 'Borrow powers' },
+//  { name: 'Coregal', desc: 'Two royal pieces' },
+//  { name: 'Coronation', desc: 'Long live the Queen' },
   { name: 'Crazyhouse', desc: 'Captures reborn' },
-  { name: 'Crossing', desc: 'Cross the river' },
+//  { name: 'Crossing', desc: 'Cross the river' },
   { name: 'Cylinder', desc: 'Neverending rows' },
-  { name: 'Cwda', desc: 'New teams', disp: 'Different armies' },
+//  { name: 'Cwda', desc: 'New teams', disp: 'Different armies' },
   { name: 'Dark', desc: 'In the shadow' },
-  { name: 'Diamond', desc: 'Rotating board' },
-  { name: 'Dice', desc: 'Roll the dice' },
-  { name: 'Discoduel', desc: 'Enter the disco', disp: 'Disco Duel' },
-  { name: 'Dobutsu', desc: "Let's catch the Lion!" },
-  { name: 'Doublearmy', desc: '64 pieces on the board', disp: 'Double Army' },
+//  { name: 'Diamond', desc: 'Rotating board' },
+//  { name: 'Dice', desc: 'Roll the dice' },
+//  { name: 'Discoduel', desc: 'Enter the disco', disp: 'Disco Duel' },
+//  { name: 'Dobutsu', desc: "Let's catch the Lion!" },
+//  { name: 'Doublearmy', desc: '64 pieces on the board', disp: 'Double Army' },
   { name: 'Doublemove', desc: 'Double moves' },
-  { name: 'Dynamo', desc: 'Push and pull' },
-  { name: 'Eightpieces', desc: 'Each piece is unique', disp: '8-Pieces' },
-  { name: 'Emergo', desc: 'Stacking Checkers variant' },
-  { name: 'Empire', desc: 'Empire versus Kingdom' },
-  { name: 'Enpassant', desc: 'Capture en passant', disp: 'En-passant' },
-  { name: 'Evolution', desc: 'Faster development' },
-  { name: 'Extinction', desc: 'Capture all of a kind' },
-  { name: 'Fanorona', desc: 'Malagasy Draughts' },
-  { name: 'Football', desc: 'Score a goal' },
-  { name: 'Forward', desc: 'Moving forward' },
-  { name: 'Freecapture', desc: 'Capture both colors', disp: 'Free Capture' },
-  { name: 'Fugue', desc: 'Baroque Music' },
-  { name: 'Fullcavalry', desc: 'Lancers everywhere', disp: 'Full Cavalry' },
-  { name: 'Fusion', desc: 'Fusion pieces (v1)' },
-  { name: 'Gomoku', desc: 'Align five stones' },
-  { name: 'Grand', desc: 'Big board' },
-  { name: 'Grasshopper', desc: 'Long jumps over pieces' },
-  { name: 'Gridolina', desc: 'Jump the borders' },
-  { name: 'Hamilton', desc: 'Walk on a graph' },
-  { name: 'Hidden', desc: 'Unidentified pieces', disp: 'Strate-Go' },
-  { name: 'Hiddenqueen', desc: 'Queen disguised as a pawn', disp: 'Hidden Queen' },
-  { name: 'Hoppelpoppel', desc: 'Knibis and Bisknis', disp: 'Hoppel-Poppel' },
-  { name: 'Horde', desc: 'A pawns cloud' },
-  { name: 'Hypnotic', desc: 'Mind control (v1)' },
-  { name: 'Iceage', desc: 'Ice Age is coming!', disp: 'Ice Age' },
-  { name: 'Interweave', desc: 'Interweaved colorbound teams' },
-  { name: 'Isardam', desc: 'No paralyzed pieces' },
-  { name: 'Janggi', desc: 'Korean Chess' },
-  { name: 'Joker', desc: 'Replace pieces' },
-  { name: 'Karouk', desc: 'Thai Chess (v3)', disp: 'Kar-Ouk' },
-  { name: 'Kinglet', desc: 'Protect your pawns' },
-  { name: 'Kingsmaker', desc: 'Promote into kings' },
-  { name: 'Knightmate', desc: 'Mate the knight' },
-  { name: 'Knightpawns', desc: 'Knight versus pawns', disp: 'Knight-Pawns' },
-  { name: 'Knightrelay', desc: 'Move like a knight' },
-  { name: 'Konane', desc: 'Hawaiian Checkers' },
-  { name: 'Koopa', desc: 'Stun & kick pieces' },
-  { name: 'Koth', desc: 'King of the Hill', disp:'King of the Hill' },
-  { name: 'Losers', desc: 'Get strong at self-mate' },
-  { name: 'Madhouse', desc: 'Rearrange enemy pieces' },
-  { name: 'Madrasi', desc: 'Paralyzed pieces' },
-  { name: 'Magnetic', desc: 'Laws of attraction' },
-  { name: 'Maharajah', desc: 'Augmented Queens' },
-  { name: 'Makpong', desc: 'Thai Chess (v2)' },
-  { name: 'Makruk', desc: 'Thai Chess (v1)' },
-  { name: 'Maxima', desc: 'Occupy the enemy palace' },
-  { name: 'Mesmer', desc: 'Mind control (v2)' },
-  { name: 'Minishogi', desc: 'Shogi 5 x 5' },
-  { name: 'Minixiangqi', desc: 'Xiangqi 7 x 7' },
-  { name: 'Monocolor', desc: 'All of the same color' },
-  { name: 'Monster', desc: 'White move twice' },
-  { name: 'Musketeer', desc: 'New fairy pieces' },
-  { name: 'Newzealand', desc: 'Kniros and Rosknis', disp: 'New-Zealand' },
-  { name: 'Omega', desc: 'A wizard in the corner' },
-  { name: 'Orda', desc: 'Mongolian Horde (v1)' },
-  { name: 'Ordamirror', desc: 'Mongolian Horde (v2)', disp: 'Orda Mirror' },
-  { name: 'Otage', desc: 'Capture and release hostages' },
-  { name: 'Pacifist', desc: 'Convert & support' },
-  { name: 'Pacosako', desc: 'Dance with the King', disp: 'Paco-Sako' },
-  { name: 'Pandemonium', desc: 'Noise and confusion' },
-  { name: 'Parachute', desc: 'Landing on the board' },
-  { name: 'Pawnmassacre', desc: 'Pieces upside down', disp: 'Pawn Massacre' },
-  { name: 'Pawns', desc: 'Reach the last rank (v1)' },
-  { name: 'Pawnsking', desc: 'Reach the last rank (v2)', disp: 'Pawns & King' },
-  { name: 'Perfect', desc: 'Powerful pieces' },
-  { name: 'Pocketknight', desc: 'Knight in pocket', disp: 'Pocket Knight' },
-  { name: 'Progressive', desc: 'Play more and more moves' },
-  { name: 'Queenpawns', desc: 'Queen versus pawns', disp: 'Queen-Pawns' },
-  { name: 'Racingkings', desc: 'Kings cross the 8x8 board', disp: 'Racing Kings' },
-  { name: 'Rampage', desc: 'Move under cover' },
-  { name: 'Relayup', desc: 'Upgrade pieces', disp: 'Relay-up' },
-  { name: 'Rifle', desc: 'Shoot pieces' },
+//  { name: 'Dynamo', desc: 'Push and pull' },
+//  { name: 'Eightpieces', desc: 'Each piece is unique', disp: '8-Pieces' },
+//  { name: 'Emergo', desc: 'Stacking Checkers variant' },
+//  { name: 'Empire', desc: 'Empire versus Kingdom' },
+//  { name: 'Enpassant', desc: 'Capture en passant', disp: 'En-passant' },
+//  { name: 'Evolution', desc: 'Faster development' },
+//  { name: 'Extinction', desc: 'Capture all of a kind' },
+//  { name: 'Fanorona', desc: 'Malagasy Draughts' },
+//  { name: 'Football', desc: 'Score a goal' },
+//  { name: 'Forward', desc: 'Moving forward' },
+//  { name: 'Freecapture', desc: 'Capture both colors', disp: 'Free Capture' },
+//  { name: 'Fugue', desc: 'Baroque Music' },
+//  { name: 'Fullcavalry', desc: 'Lancers everywhere', disp: 'Full Cavalry' },
+//  { name: 'Fusion', desc: 'Fusion pieces (v1)' },
+//  { name: 'Gomoku', desc: 'Align five stones' },
+//  { name: 'Grand', desc: 'Big board' },
+//  { name: 'Grasshopper', desc: 'Long jumps over pieces' },
+//  { name: 'Gridolina', desc: 'Jump the borders' },
+//  { name: 'Hamilton', desc: 'Walk on a graph' },
+//  { name: 'Hidden', desc: 'Unidentified pieces', disp: 'Strate-Go' },
+//  { name: 'Hiddenqueen', desc: 'Queen disguised as a pawn', disp: 'Hidden Queen' },
+//  { name: 'Hoppelpoppel', desc: 'Knibis and Bisknis', disp: 'Hoppel-Poppel' },
+//  { name: 'Horde', desc: 'A pawns cloud' },
+//  { name: 'Hypnotic', desc: 'Mind control (v1)' },
+//  { name: 'Iceage', desc: 'Ice Age is coming!', disp: 'Ice Age' },
+//  { name: 'Interweave', desc: 'Interweaved colorbound teams' },
+//  { name: 'Isardam', desc: 'No paralyzed pieces' },
+//  { name: 'Janggi', desc: 'Korean Chess' },
+//  { name: 'Joker', desc: 'Replace pieces' },
+//  { name: 'Karouk', desc: 'Thai Chess (v3)', disp: 'Kar-Ouk' },
+//  { name: 'Kinglet', desc: 'Protect your pawns' },
+//  { name: 'Kingsmaker', desc: 'Promote into kings' },
+//  { name: 'Knightmate', desc: 'Mate the knight' },
+//  { name: 'Knightpawns', desc: 'Knight versus pawns', disp: 'Knight-Pawns' },
+//  { name: 'Knightrelay', desc: 'Move like a knight' },
+//  { name: 'Konane', desc: 'Hawaiian Checkers' },
+//  { name: 'Koopa', desc: 'Stun & kick pieces' },
+//  { name: 'Koth', desc: 'King of the Hill', disp:'King of the Hill' },
+//  { name: 'Losers', desc: 'Get strong at self-mate' },
+//  { name: 'Madhouse', desc: 'Rearrange enemy pieces' },
+//  { name: 'Madrasi', desc: 'Paralyzed pieces' },
+//  { name: 'Magnetic', desc: 'Laws of attraction' },
+//  { name: 'Maharajah', desc: 'Augmented Queens' },
+//  { name: 'Makpong', desc: 'Thai Chess (v2)' },
+//  { name: 'Makruk', desc: 'Thai Chess (v1)' },
+//  { name: 'Maxima', desc: 'Occupy the enemy palace' },
+//  { name: 'Mesmer', desc: 'Mind control (v2)' },
+//  { name: 'Minishogi', desc: 'Shogi 5 x 5' },
+//  { name: 'Minixiangqi', desc: 'Xiangqi 7 x 7' },
+//  { name: 'Monocolor', desc: 'All of the same color' },
+//  { name: 'Monster', desc: 'White move twice' },
+//  { name: 'Musketeer', desc: 'New fairy pieces' },
+//  { name: 'Newzealand', desc: 'Kniros and Rosknis', disp: 'New-Zealand' },
+//  { name: 'Omega', desc: 'A wizard in the corner' },
+//  { name: 'Orda', desc: 'Mongolian Horde (v1)' },
+//  { name: 'Ordamirror', desc: 'Mongolian Horde (v2)', disp: 'Orda Mirror' },
+//  { name: 'Otage', desc: 'Capture and release hostages' },
+//  { name: 'Pacifist', desc: 'Convert & support' },
+//  { name: 'Pacosako', desc: 'Dance with the King', disp: 'Paco-Sako' },
+//  { name: 'Pandemonium', desc: 'Noise and confusion' },
+//  { name: 'Parachute', desc: 'Landing on the board' },
+//  { name: 'Pawnmassacre', desc: 'Pieces upside down', disp: 'Pawn Massacre' },
+//  { name: 'Pawns', desc: 'Reach the last rank (v1)' },
+//  { name: 'Pawnsking', desc: 'Reach the last rank (v2)', disp: 'Pawns & King' },
+//  { name: 'Perfect', desc: 'Powerful pieces' },
+//  { name: 'Pocketknight', desc: 'Knight in pocket', disp: 'Pocket Knight' },
+//  { name: 'Progressive', desc: 'Play more and more moves' },
+//  { name: 'Queenpawns', desc: 'Queen versus pawns', disp: 'Queen-Pawns' },
+//  { name: 'Racingkings', desc: 'Kings cross the 8x8 board', disp: 'Racing Kings' },
+//  { name: 'Rampage', desc: 'Move under cover' },
+//  { name: 'Relayup', desc: 'Upgrade pieces', disp: 'Relay-up' },
+//  { name: 'Rifle', desc: 'Shoot pieces' },
   { name: 'Recycle', desc: 'Reuse pieces' },
-  { name: 'Refusal', desc: 'Do not play that!' },
-  { name: 'Rollerball', desc: 'As in the movie' },
-  { name: 'Rococo', desc: 'Capture on the edge' },
-  { name: 'Rookpawns', desc: 'Rook versus pawns', disp: 'Rook-Pawns' },
-  { name: 'Royalrace', desc: 'Kings cross the 11x11 board', disp: 'Royal Race' },
-  { name: 'Rugby', desc: 'Transform an essay' },
-  { name: 'Schess', desc: 'Seirawan-Harper Chess', disp: 'Seirawan-Harper Chess' },
-  { name: 'Screen', desc: 'Free initial setup' },
-  { name: 'Selfabsorb', desc: 'Fusion pieces (v2)', disp: 'Self-Absorption' },
-  { name: 'Shako', desc: 'Non-conformism and utopia' },
-  { name: 'Shatranj', desc: 'Ancient rules' },
-  { name: 'Shinobi', desc: 'A story of invasion' },
-  { name: 'Shogi', desc: 'Japanese Chess' },
-  { name: 'Shogun', desc: "General's Chess" },
-  { name: 'Sittuyin', desc: 'Burmese Chess' },
-  { name: 'Spartan', desc: 'Spartan versus Persians' },
-  { name: 'Squatter', desc: 'Squat last rank' },
-  { name: 'Stealthbomb', desc: 'Beware the bomb', disp: 'Stealth Bomb' },
-  { name: 'Suicide', desc: 'Lose all pieces' },
-  { name: 'Suction', desc: 'Attract opposite king' },
-  { name: 'Swap', desc: 'Dangerous captures' },
-  { name: 'Switching', desc: "Exchange pieces' positions" },
-  { name: 'Synchrone', desc: 'Play at the same time' },
-  { name: 'Synochess', desc: 'Dynasty versus Kingdom' },
-  { name: 'Takenmake', desc: 'Prolongated captures', disp: 'Take and make' },
+//  { name: 'Refusal', desc: 'Do not play that!' },
+//  { name: 'Rollerball', desc: 'As in the movie' },
+//  { name: 'Rococo', desc: 'Capture on the edge' },
+//  { name: 'Rookpawns', desc: 'Rook versus pawns', disp: 'Rook-Pawns' },
+//  { name: 'Royalrace', desc: 'Kings cross the 11x11 board', disp: 'Royal Race' },
+//  { name: 'Rugby', desc: 'Transform an essay' },
+//  { name: 'Schess', desc: 'Seirawan-Harper Chess', disp: 'Seirawan-Harper Chess' },
+//  { name: 'Screen', desc: 'Free initial setup' },
+//  { name: 'Selfabsorb', desc: 'Fusion pieces (v2)', disp: 'Self-Absorption' },
+//  { name: 'Shako', desc: 'Non-conformism and utopia' },
+//  { name: 'Shatranj', desc: 'Ancient rules' },
+//  { name: 'Shinobi', desc: 'A story of invasion' },
+//  { name: 'Shogi', desc: 'Japanese Chess' },
+//  { name: 'Shogun', desc: "General's Chess" },
+//  { name: 'Sittuyin', desc: 'Burmese Chess' },
+//  { name: 'Spartan', desc: 'Spartan versus Persians' },
+//  { name: 'Squatter', desc: 'Squat last rank' },
+//  { name: 'Stealthbomb', desc: 'Beware the bomb', disp: 'Stealth Bomb' },
+//  { name: 'Suicide', desc: 'Lose all pieces' },
+//  { name: 'Suction', desc: 'Attract opposite king' },
+//  { name: 'Swap', desc: 'Dangerous captures' },
+//  { name: 'Switching', desc: "Exchange pieces' positions" },
+//  { name: 'Synchrone', desc: 'Play at the same time' },
+//  { name: 'Synochess', desc: 'Dynasty versus Kingdom' },
+//  { name: 'Takenmake', desc: 'Prolongated captures', disp: 'Take and make' },
   { name: 'Teleport', desc: 'Reposition pieces' },
-  { name: 'Tencubed', desc: 'Four new pieces' },
-  { name: 'Threechecks', desc: 'Give three checks', disp: 'Three Checks' },
-  { name: 'Titan', desc: 'Extra bishops and knights' },
-  { name: 'Twokings', desc: 'Two kings', disp: 'Two Kings' },
-  { name: 'Upsidedown', desc: 'Board upside down', disp: 'Upside-down' },
-  { name: 'Vchess', desc: 'Pawns capture backward', disp: 'Victor Chess' },
-  { name: 'Wildebeest', desc: 'Balanced sliders & leapers' },
-  { name: 'Wormhole', desc: 'Squares disappear' },
-  { name: 'Xiangqi', desc: 'Chinese Chess' },
-  { name: 'Yote', desc: 'African Draughts' },*/
+//  { name: 'Tencubed', desc: 'Four new pieces' },
+//  { name: 'Threechecks', desc: 'Give three checks', disp: 'Three Checks' },
+//  { name: 'Titan', desc: 'Extra bishops and knights' },
+//  { name: 'Twokings', desc: 'Two kings', disp: 'Two Kings' },
+//  { name: 'Upsidedown', desc: 'Board upside down', disp: 'Upside-down' },
+//  { name: 'Vchess', desc: 'Pawns capture backward', disp: 'Victor Chess' },
+//  { name: 'Wildebeest', desc: 'Balanced sliders & leapers' },
+//  { name: 'Wormhole', desc: 'Squares disappear' },
+//  { name: 'Xiangqi', desc: 'Chinese Chess' },
+//  { name: 'Yote', desc: 'African Draughts' },
   { name: "Zen", disp: "Zen Chess", desc: "Reverse captures" }
 ];
 
diff --git a/variants/Atomic/class.js b/variants/Atomic/class.js
new file mode 100644 (file)
index 0000000..7cac4e5
--- /dev/null
@@ -0,0 +1,85 @@
+import ChessRules from "/base_rules.js";
+import PiPo from "/utils/PiPo.js";
+import Move from "/utils/Move.js";
+
+export default class AtomicRules extends ChessRules {
+
+  static get Options() {
+    return {
+      select: C.Options.select,
+      check: [
+        {
+          label: "Balanced",
+          defaut: false,
+          variable: "rempawn"
+        },
+        {
+          label: "Falling pawn",
+          defaut: false,
+          variable: "pawnfall"
+        }
+      ],
+      styles: C.Options.styles.filter(s => s != "atomic")
+    };
+  }
+
+  constructor(o) {
+    super(o);
+    this.options.atomic = true;
+  }
+
+  genRandInitFen(seed) {
+    return super.genRandInitFen(seed).slice(0, -1) + ',"rempawn":' + (this.options.rempawn ? "1" : "0") + "}";
+  }
+
+  // TODO: capture king option doesn't make sense
+
+  setOtherVariables(fenParsed) {
+    super.setOtherVariables(fenParsed);
+    this.options["rempawn"] = (fenParsed.rempawn == 1);
+  }
+
+  getFen() {
+    return super.getFen().slice(0, -1) + ',"rempawn":' + (this.options["rempawn"] ? "1" : "0") + "}";
+  }
+
+  canIplay(x, y) {
+    if (this.options["rempawn"] && this.movesCount == 0)
+      return (this.turn == side && this.getPiece(x, y) == "p");
+    return super.canIplay(x, y);
+  }
+
+  getPotentialMovesFrom([x, y], color) {
+    if (this.options["rempawn"] && this.movesCount == 0) {
+      if ([1, 6].includes(x)) {
+        const c = this.getColor(x, y);
+        return [
+          new Move({
+            appear: [],
+            vanish: [
+              new PiPo({
+                x: x,
+                y: y,
+                p: "p",
+                c: c
+              })
+            ],
+            start: { x: x, y: y },
+            end: { x: x, y: y }
+          })
+        ];
+      }
+      return [];
+    }
+    return super.getPotentialMovesFrom([x, y], color);
+  }
+
+  doClick(square) {
+    if (!this.options["rempawn"] || this.movesCount >= 1)
+      return super.doClick(square);
+    const [x, y] = [square[0], square[1]];
+    const moves = this.getPotentialMovesFrom([x, y]);
+    return (moves.length >= 1 ? moves[0] : null);
+  }
+
+};
diff --git a/variants/Atomic/rules.html b/variants/Atomic/rules.html
new file mode 100644 (file)
index 0000000..05829a5
--- /dev/null
@@ -0,0 +1,3 @@
+<p>The capturer explodes after each capture, as well as all pieces standing on the adjacent squares - pawns excepted.</p>
+
+<p>Win by checkmate or by exploding the enemy king.</p>
diff --git a/variants/Atomic/style.css b/variants/Atomic/style.css
new file mode 100644 (file)
index 0000000..9378e29
--- /dev/null
@@ -0,0 +1 @@
+@import "../../base_pieces.css"
diff --git a/variants/Balanced/class.js b/variants/Balanced/class.js
new file mode 100644 (file)
index 0000000..f466f08
--- /dev/null
@@ -0,0 +1,18 @@
+import ChessRules from "/base_rules.js";
+
+export default class BalancedRules extends ChessRules {
+
+  static get Options() {
+    return {
+      select: C.Options.select,
+      check: C.Options.check,
+      styles: C.Options.styles.filter(s => s != "balance")
+    };
+  }
+
+  constructor(o) {
+    super(o);
+    this.options.balance = true;
+  }
+
+};
diff --git a/variants/Balanced/rules.html b/variants/Balanced/rules.html
new file mode 100644 (file)
index 0000000..e7bb01e
--- /dev/null
@@ -0,0 +1,3 @@
+<p>White plays first, thenn Black plays two moves, then White plays two moves, and after that the game proceeds normally.</p>
+
+<p>See <a href="https://arxiv.org/abs/2108.02547">the (draft) article</a>.</p>
diff --git a/variants/Balanced/style.css b/variants/Balanced/style.css
new file mode 100644 (file)
index 0000000..9378e29
--- /dev/null
@@ -0,0 +1 @@
+@import "../../base_pieces.css"
diff --git a/variants/Cannibal/class.js b/variants/Cannibal/class.js
new file mode 100644 (file)
index 0000000..9ac2161
--- /dev/null
@@ -0,0 +1,18 @@
+import ChessRules from "/base_rules.js";
+
+export default class CannibalRules extends ChessRules {
+
+  static get Options() {
+    return {
+      select: C.Options.select,
+      check: C.Options.check,
+      styles: C.Options.styles.filter(s => s != "cannibal")
+    };
+  }
+
+  constructor(o) {
+    super(o);
+    this.options.cannibal = true;
+  }
+
+};
diff --git a/variants/Cannibal/rules.html b/variants/Cannibal/rules.html
new file mode 100644 (file)
index 0000000..b9791a2
--- /dev/null
@@ -0,0 +1 @@
+<p>After each capture, the capturer transforms into the captured piece.</p>
diff --git a/variants/Cannibal/style.css b/variants/Cannibal/style.css
new file mode 100644 (file)
index 0000000..9378e29
--- /dev/null
@@ -0,0 +1 @@
+@import "../../base_pieces.css"
diff --git a/variants/Capture/class.js b/variants/Capture/class.js
new file mode 100644 (file)
index 0000000..5e69452
--- /dev/null
@@ -0,0 +1,18 @@
+import ChessRules from "/base_rules.js";
+
+export default class CaptureRules extends ChessRules {
+
+  static get Options() {
+    return {
+      select: C.Options.select,
+      check: C.Options.check,
+      styles: C.Options.styles.filter(s => s != "capture")
+    };
+  }
+
+  constructor(o) {
+    super(o);
+    this.options.capture = true;
+  }
+
+};
diff --git a/variants/Capture/rules.html b/variants/Capture/rules.html
new file mode 100644 (file)
index 0000000..cb49403
--- /dev/null
@@ -0,0 +1 @@
+<p>Captures are mandatory.</p>
diff --git a/variants/Capture/style.css b/variants/Capture/style.css
new file mode 100644 (file)
index 0000000..9378e29
--- /dev/null
@@ -0,0 +1 @@
+@import "../../base_pieces.css"
index a1bae2a..7d3681f 100644 (file)
@@ -1,5 +1,8 @@
 <p>Pawn, Knight, Bishop and Rook add an object on the board every time they move...</p>
 
-<p>Exception: the king is attacked as usual.</p>
-
-TODO: revenir à diag == image
+<ul>
+  <li>Mushrooms speed-up your pieces.</li>
+  <li>Bananas redirect by one square orthogonally.</li>
+  <li>Bombs redirect by one square diagonally.</li>
+  <li>Eggs hide either a bonus or malus, as indicated...</li>
+</ul>
diff --git a/variants/Crazyhouse/class.js b/variants/Crazyhouse/class.js
new file mode 100644 (file)
index 0000000..0e1b14c
--- /dev/null
@@ -0,0 +1,18 @@
+import ChessRules from "/base_rules.js";
+
+export default class CrazyhouseRules extends ChessRules {
+
+  static get Options() {
+    return {
+      select: C.Options.select,
+      check: C.Options.check,
+      styles: C.Options.styles.filter(s => s != "crazyhouse")
+    };
+  }
+
+  constructor(o) {
+    super(o);
+    this.options.crazyhouse = true;
+  }
+
+};
diff --git a/variants/Crazyhouse/rules.html b/variants/Crazyhouse/rules.html
new file mode 100644 (file)
index 0000000..ecb0837
--- /dev/null
@@ -0,0 +1,3 @@
+<p>Captured pieces can be landed on the board in place of a normal turn.</p>
+
+<p>Promoted pawns return on the board as pawns.</p>
diff --git a/variants/Crazyhouse/style.css b/variants/Crazyhouse/style.css
new file mode 100644 (file)
index 0000000..9378e29
--- /dev/null
@@ -0,0 +1 @@
+@import "../../base_pieces.css"
diff --git a/variants/Cylinder/class.js b/variants/Cylinder/class.js
new file mode 100644 (file)
index 0000000..cc86084
--- /dev/null
@@ -0,0 +1,18 @@
+import ChessRules from "/base_rules.js";
+
+export default class CylinderRules extends ChessRules {
+
+  static get Options() {
+    return {
+      select: C.Options.select,
+      check: C.Options.check,
+      styles: C.Options.styles.filter(s => s != "cylinder")
+    };
+  }
+
+  constructor(o) {
+    super(o);
+    this.options.cylinder = true;
+  }
+
+};
diff --git a/variants/Cylinder/rules.html b/variants/Cylinder/rules.html
new file mode 100644 (file)
index 0000000..6a9db5b
--- /dev/null
@@ -0,0 +1 @@
+<p>Columns 'a' and 'h' communicate: a king on h3 can also go to a2, a3 and a4.</p>
diff --git a/variants/Cylinder/style.css b/variants/Cylinder/style.css
new file mode 100644 (file)
index 0000000..9378e29
--- /dev/null
@@ -0,0 +1 @@
+@import "../../base_pieces.css"
diff --git a/variants/Dark/class.js b/variants/Dark/class.js
new file mode 100644 (file)
index 0000000..fb27c44
--- /dev/null
@@ -0,0 +1,18 @@
+import ChessRules from "/base_rules.js";
+
+export default class DarkRules extends ChessRules {
+
+  static get Options() {
+    return {
+      select: C.Options.select,
+      check: C.Options.check,
+      styles: C.Options.styles.filter(s => s != "dark")
+    };
+  }
+
+  constructor(o) {
+    super(o);
+    this.options.dark = true;
+  }
+
+};
diff --git a/variants/Dark/rules.html b/variants/Dark/rules.html
new file mode 100644 (file)
index 0000000..4fefa83
--- /dev/null
@@ -0,0 +1,3 @@
+<p>You only see what your pieces can reach and capture.</p>
+
+<p>Win by capturing the enemy king.</p>
diff --git a/variants/Dark/style.css b/variants/Dark/style.css
new file mode 100644 (file)
index 0000000..9378e29
--- /dev/null
@@ -0,0 +1 @@
+@import "../../base_pieces.css"
diff --git a/variants/Doublemove/class.js b/variants/Doublemove/class.js
new file mode 100644 (file)
index 0000000..fed88d8
--- /dev/null
@@ -0,0 +1,18 @@
+import ChessRules from "/base_rules.js";
+
+export default class DoublemoveRules extends ChessRules {
+
+  static get Options() {
+    return {
+      select: C.Options.select,
+      check: C.Options.check,
+      styles: C.Options.styles.filter(s => s != "doublemove")
+    };
+  }
+
+  constructor(o) {
+    super(o);
+    this.options.doublemove = true;
+  }
+
+};
diff --git a/variants/Doublemove/rules.html b/variants/Doublemove/rules.html
new file mode 100644 (file)
index 0000000..569f213
--- /dev/null
@@ -0,0 +1,3 @@
+<p>Pieces capture enemy units which threaten them (normal captures are disabled).</p>
+
+<p>Exception: the king is attacked as usual.</p>
diff --git a/variants/Doublemove/style.css b/variants/Doublemove/style.css
new file mode 100644 (file)
index 0000000..9378e29
--- /dev/null
@@ -0,0 +1 @@
+@import "../../base_pieces.css"
index 6d0420a..b5c2bab 100644 (file)
@@ -12,7 +12,7 @@ export default class ZenRules extends ChessRules {
 
   constructor(o) {
     super(o);
-    o.options.zen = true;
+    this.options.zen = true;
   }
 
 };