From 535c464b0543306a0ea36c66f07dcfad7a951efc Mon Sep 17 00:00:00 2001 From: Benjamin Auder <benjamin.auder@somewhere> Date: Wed, 1 Jun 2022 17:21:20 +0200 Subject: [PATCH] Add Hex: almost fine, still some issues with SVG + rescaling --- app.js | 35 ++--- base_rules.js | 79 ++++++----- common.css | 8 +- variants.js | 2 +- variants/Absorption/class.js | 1 - variants/Atomic/class.js | 12 +- variants/Balanced/class.js | 2 +- variants/Benedict/class.js | 1 - variants/Cannibal/class.js | 2 +- variants/Capture/class.js | 2 +- variants/Crazyhouse/class.js | 2 +- variants/Cylinder/class.js | 2 +- variants/Dark/class.js | 2 +- variants/Doublemove/class.js | 2 +- variants/Hex/Hex_board_centered.svg | 28 ---- variants/Hex/Regular_hexagon.svg | 9 -- variants/Hex/class.js | 202 +++++++++++++++++++--------- variants/Hex/rules.html | 5 + variants/Hex/style.css | 7 + variants/Madrasi/class.js | 9 +- variants/Progressive/class.js | 9 +- variants/Recycle/class.js | 12 +- variants/Rifle/class.js | 2 +- variants/Teleport/class.js | 2 +- variants/Zen/class.js | 2 +- 25 files changed, 246 insertions(+), 193 deletions(-) delete mode 100644 variants/Hex/Hex_board_centered.svg delete mode 100644 variants/Hex/Regular_hexagon.svg create mode 100644 variants/Hex/rules.html diff --git a/app.js b/app.js index 17fe770..c0c74c0 100644 --- a/app.js +++ b/app.js @@ -136,7 +136,7 @@ function prepareOptions() { <div class="option-select"> <label for="var_${select.variable}">${select.label}</label> <div class="select"> - <select id="var_${select.variable}" data-numeric="1">` + + <select id="var_${select.variable}">` + select.options.map(option => { return ` <option value="${option.value}" @@ -151,25 +151,16 @@ function prepareOptions() { </div>`; }).join(""); } - if (V.Options.check) { - optHtml += V.Options.check.map(check => { return ` - <div class="option-check"> - <label class="checkbox"> - <input id="var_${check.variable}" - type="checkbox"${check.defaut ? " checked" : ""}/> - <span class="spacer"></span> - <span>${check.label}</span> - </label> - </div>`; - }).join(""); - } if (V.Options.input) { optHtml += V.Options.input.map(input => { return ` <div class="option-input"> <label class="input"> <input id="var_${input.variable}" type="${input.type}" - content="${input.defaut}"/> + ${input.type == "checkbox" && input.defaut + ? "checked" + : 'value="' + input.defaut + '"'} + /> <span class="spacer"></span> <span>${input.label}</span> </label> @@ -200,15 +191,15 @@ function getGameLink() { const vname = $.getElementById("selectVariant").value; const color = $.getElementById("selectColor").value; for (const select of $.querySelectorAll("#gameOptions select")) { - let value = select.value; - if (select.attributes["data-numeric"]) - value = parseInt(value, 10); - if (value) - options[ select.id.split("_")[1] ] = value; + const value = parseInt(select.value, 10) || select.value; + options[ select.id.split("_")[1] ] = value; } - for (const check of $.querySelectorAll("#gameOptions input")) { - if (check.checked) - options[ check.id.split("_")[1] ] = check.checked; + for (const input of $.querySelectorAll("#gameOptions input")) { + const variable = input.id.split("_")[1]; + if (input.type == "number") + options[variable] = parseInt(input.value, 10); //TODO: real numbers? + else if (input.type == "checkbox") + options[variable] = input.checked; } send("creategame", { vname: vname, diff --git a/base_rules.js b/base_rules.js index 20ff25e..33411f0 100644 --- a/base_rules.js +++ b/base_rules.js @@ -372,6 +372,11 @@ export default class ChessRules { constructor(o) { this.options = o.options; + // Fill missing options (always the case if random challenge) + (V.Options.select || []).concat(V.Options.input || []).forEach(opt => { + if (this.options[opt.variable] === undefined) + this.options[opt.variable] = opt.defaut; + }); this.playerColor = o.color; this.afterPlay = o.afterPlay; //trigger some actions after playing a move @@ -528,7 +533,8 @@ export default class ChessRules { this.initMouseEvents(); const chessboard = document.getElementById(this.containerId).querySelector(".chessboard"); - new ResizeObserver(this.rescale).observe(chessboard); + // TODO: calling with "this" seems required by Hex. Understand why... + new ResizeObserver(() => this.rescale(this)).observe(chessboard); } re_drawBoardElements() { @@ -583,8 +589,7 @@ export default class ChessRules { let board = ` <svg viewBox="0 0 80 80" - class="chessboard_SVG"> - <g>`; + class="chessboard_SVG">`; for (let i=0; i < this.size.x; i++) { for (let j=0; j < this.size.y; j++) { const ii = (flipped ? this.size.x - 1 - i : i); @@ -593,16 +598,18 @@ export default class ChessRules { if (this.enlightened && !this.enlightened[ii][jj]) classes += " in-shadow"; // NOTE: x / y reversed because coordinates system is reversed. - board += `<rect - class="${classes}" - id="${this.coordsToId({x: ii, y: jj})}" - width="10" - height="10" - x="${10*j}" - y="${10*i}" />`; + board += ` + <rect + class="${classes}" + id="${this.coordsToId({x: ii, y: jj})}" + width="10" + height="10" + x="${10*j}" + y="${10*i}" + />`; } } - board += "</g></svg>"; + board += "</svg>"; return board; } @@ -767,48 +774,50 @@ export default class ChessRules { } // After resize event: no need to destroy/recreate pieces - rescale() { - const container = document.getElementById(this.containerId); + rescale(self) { + const container = document.getElementById(self.containerId); if (!container) return; //useful at initial loading let chessboard = container.querySelector(".chessboard"); - const r = chessboard.getBoundingClientRect(); - const newRatio = r.width / r.height; - let newWidth = r.width, - newHeight = r.height; - if (newRatio > this.size.ratio) { - newWidth = r.height * this.size.ratio; - chessboard.style.width = newWidth + "px"; - } - else if (newRatio < this.size.ratio) { - newHeight = r.width / this.size.ratio; - chessboard.style.height = newHeight + "px"; - } + let r = chessboard.getBoundingClientRect(); + let [newWidth, newHeight] = [r.width, r.height]; + // Stay in window: + if (newWidth > window.innerWidth) + newWidth = window.innerWidth; + if (newHeight > window.innerHeight) + newHeight = window.innerHeight; + const newRatio = newWidth / newHeight; + if (newRatio > self.size.ratio) + newWidth = newHeight * self.size.ratio; + else if (newRatio < self.size.ratio) + newHeight = newWidth / self.size.ratio; + chessboard.style.width = newWidth + "px"; + chessboard.style.height = newHeight + "px"; const newX = (window.innerWidth - newWidth) / 2; chessboard.style.left = newX + "px"; const newY = (window.innerHeight - newHeight) / 2; chessboard.style.top = newY + "px"; const newR = {x: newX, y: newY, width: newWidth, height: newHeight}; - const pieceWidth = this.getPieceWidth(newWidth); + const pieceWidth = self.getPieceWidth(newWidth); // NOTE: next "if" for variants which use squares filling // instead of "physical", moving pieces if (this.g_pieces) { - for (let i=0; i < this.size.x; i++) { - for (let j=0; j < this.size.y; j++) { - if (this.g_pieces[i][j]) { + for (let i=0; i < self.size.x; i++) { + for (let j=0; j < self.size.y; j++) { + if (self.g_pieces[i][j]) { // NOTE: could also use CSS transform "scale" - this.g_pieces[i][j].style.width = pieceWidth + "px"; - this.g_pieces[i][j].style.height = pieceWidth + "px"; - const [ip, jp] = this.getPixelPosition(i, j, newR); + self.g_pieces[i][j].style.width = pieceWidth + "px"; + self.g_pieces[i][j].style.height = pieceWidth + "px"; + const [ip, jp] = self.getPixelPosition(i, j, newR); // Translate coordinates to use chessboard as reference: - this.g_pieces[i][j].style.transform = + self.g_pieces[i][j].style.transform = `translate(${ip - newX}px,${jp - newY}px)`; } } } } - if (this.hasReserve) - this.rescaleReserve(newR); + if (self.hasReserve) + self.rescaleReserve(newR); } rescaleReserve(r) { diff --git a/common.css b/common.css index 7096ff8..e359955 100644 --- a/common.css +++ b/common.css @@ -231,15 +231,19 @@ button.cancel-something { text-align: center; } -.option-select, .option-check { +.option-select, .option-input { margin: 15px 0 0 0; } -.option-check { +.option-input { display: inline-block; margin-right: 10px; } +.option-input input[type=number] { + width: 64px; +} + .btn-wrap { text-align: center; } diff --git a/variants.js b/variants.js index f543d3f..3fced3d 100644 --- a/variants.js +++ b/variants.js @@ -67,7 +67,7 @@ const variants = [ // {name: 'Grasshopper', desc: 'Long jumps over pieces'}, // {name: 'Gridolina', desc: 'Jump the borders'}, // {name: 'Hamilton', desc: 'Walk on a graph'}, - {names: 'Hex', desc: 'Connect sides'}, + {name: 'Hex', desc: 'Connect sides'}, // {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'}, diff --git a/variants/Absorption/class.js b/variants/Absorption/class.js index 9fe43aa..3e8d391 100644 --- a/variants/Absorption/class.js +++ b/variants/Absorption/class.js @@ -5,7 +5,6 @@ export default class AbsorptionRules extends ChessRules { static get Options() { return { select: C.Options.select, - check: [], styles: [ "balance", "capture", diff --git a/variants/Atomic/class.js b/variants/Atomic/class.js index 924d222..cc339ff 100644 --- a/variants/Atomic/class.js +++ b/variants/Atomic/class.js @@ -7,16 +7,18 @@ export default class AtomicRules extends ChessRules { static get Options() { return { select: C.Options.select, - check: [ + input: [ { label: "Balanced", - defaut: false, - variable: "rempawn" + variable: "rempawn", + type: "checkbox", + defaut: false }, { label: "Falling pawn", - defaut: false, - variable: "pawnfall" + variable: "pawnfall", + type: "checkbox", + defaut: false } ], styles: C.Options.styles.filter(s => s != "atomic") diff --git a/variants/Balanced/class.js b/variants/Balanced/class.js index 5550b0d..a8294bc 100644 --- a/variants/Balanced/class.js +++ b/variants/Balanced/class.js @@ -5,7 +5,7 @@ export default class BalancedRules extends ChessRules { static get Options() { return { select: C.Options.select, - check: C.Options.check, + input: C.Options.input, styles: C.Options.styles.filter(s => s != "balance") }; } diff --git a/variants/Benedict/class.js b/variants/Benedict/class.js index 68667e1..bbaf8e9 100644 --- a/variants/Benedict/class.js +++ b/variants/Benedict/class.js @@ -6,7 +6,6 @@ export default class BenedictRules extends ChessRules { static get Options() { return { select: C.Options.select, - check: [], styles: [ "balance", "cylinder", diff --git a/variants/Cannibal/class.js b/variants/Cannibal/class.js index e75aa20..8d8cef3 100644 --- a/variants/Cannibal/class.js +++ b/variants/Cannibal/class.js @@ -5,7 +5,7 @@ export default class CannibalRules extends ChessRules { static get Options() { return { select: C.Options.select, - check: C.Options.check, + input: C.Options.input, styles: C.Options.styles.filter(s => s != "cannibal") }; } diff --git a/variants/Capture/class.js b/variants/Capture/class.js index 31264a1..3a0a22e 100644 --- a/variants/Capture/class.js +++ b/variants/Capture/class.js @@ -5,7 +5,7 @@ export default class CaptureRules extends ChessRules { static get Options() { return { select: C.Options.select, - check: C.Options.check, + input: C.Options.input, styles: C.Options.styles.filter(s => s != "capture") }; } diff --git a/variants/Crazyhouse/class.js b/variants/Crazyhouse/class.js index f01bd0c..41503dd 100644 --- a/variants/Crazyhouse/class.js +++ b/variants/Crazyhouse/class.js @@ -5,7 +5,7 @@ export default class CrazyhouseRules extends ChessRules { static get Options() { return { select: C.Options.select, - check: C.Options.check, + input: C.Options.input, styles: C.Options.styles.filter(s => s != "crazyhouse") }; } diff --git a/variants/Cylinder/class.js b/variants/Cylinder/class.js index c35c346..998453e 100644 --- a/variants/Cylinder/class.js +++ b/variants/Cylinder/class.js @@ -5,7 +5,7 @@ export default class CylinderRules extends ChessRules { static get Options() { return { select: C.Options.select, - check: C.Options.check, + input: C.Options.input, styles: C.Options.styles.filter(s => s != "cylinder") }; } diff --git a/variants/Dark/class.js b/variants/Dark/class.js index ad23cbc..65679fe 100644 --- a/variants/Dark/class.js +++ b/variants/Dark/class.js @@ -5,7 +5,7 @@ export default class DarkRules extends ChessRules { static get Options() { return { select: C.Options.select, - check: C.Options.check, + input: C.Options.input, styles: C.Options.styles.filter(s => s != "dark") }; } diff --git a/variants/Doublemove/class.js b/variants/Doublemove/class.js index 551ae09..2606d4f 100644 --- a/variants/Doublemove/class.js +++ b/variants/Doublemove/class.js @@ -5,7 +5,7 @@ export default class DoublemoveRules extends ChessRules { static get Options() { return { select: C.Options.select, - check: C.Options.check, + input: C.Options.input, styles: C.Options.styles.filter(s => s != "doublemove") }; } diff --git a/variants/Hex/Hex_board_centered.svg b/variants/Hex/Hex_board_centered.svg deleted file mode 100644 index ee5d40b..0000000 --- a/variants/Hex/Hex_board_centered.svg +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - viewBox="0 0 860 1340" - height="1340" - width="860" - xml:space="preserve" - version="1.1" - id="svg2"><metadata - id="metadata8"><rdf:RDF><cc:Work - rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs - id="defs6" /><g - transform="matrix(1.25,0,0,-1.25,0,1340)" - id="g10"><path - id="path12" - style="fill:none;stroke:#000000;stroke-width:0.72000003;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1" - d="m -42.969999,1134.05 773.939999,0 0,-1196.100005 -773.939998,0 0,1196.100005 z M 643.07,505.55 l -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.42 35.22,0 17.58,30.42 z m 0,60.96 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.64,30.42 -35.16,0 -17.58,-30.48 17.58,-30.42 35.22,0 17.58,30.48 z m 0,60.9 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.64,30.48 -35.16,-0.06 -17.58,-30.42 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.42 35.22,0 17.58,30.42 z m 0,60.96 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m -105.54,-548.4 -17.64,30.42 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.64,30.48 z m 0,60.9 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.64,30.48 z m 0,60.96 -17.64,30.42 -35.16,0 -17.58,-30.42 17.58,-30.48 35.16,0 17.64,30.48 z m 0,60.9 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.64,30.48 z m 0,60.96 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.64,30.48 z m 0,60.9 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.64,30.42 z m 0,60.96 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.64,30.48 z m 0,60.96 -17.64,30.42 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.64,30.48 z m 0,60.9 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.64,30.48 z m 52.74,-457.02 -17.58,30.48 -35.22,0 -17.58,-30.48 17.64,-30.42 35.16,0 17.58,30.42 z m 0,60.96 -17.58,30.48 -35.22,0 -17.58,-30.48 17.64,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.22,0 -17.58,-30.48 17.64,-30.42 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.64,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.48 -35.22,-0.06 -17.58,-30.42 17.64,-30.48 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.64,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.48 -35.22,0 -17.58,-30.48 17.64,-30.48 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.64,-30.42 35.16,0 17.58,30.42 z m 0,60.96 -17.58,30.48 -35.22,0 -17.58,-30.48 17.64,-30.48 35.16,0 17.58,30.48 z m -158.34,-578.88 -17.58,30.48 -35.16,-0.06 -17.58,-30.42 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.58,30.42 z m 0,60.96 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.16,0 -17.58,-30.42 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.58,30.42 z m 52.8,-456.96 -17.58,30.42 -35.22,0 -17.58,-30.42 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.22,0 -17.58,-30.42 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.42 35.22,0 17.58,30.42 z m 0,60.96 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.22,0 -17.58,-30.48 17.58,-30.42 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m -158.34,-578.88 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.58,30.42 z m 0,60.96 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.16,0 -17.58,-30.42 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.58,30.48 z m 52.8,-457.02 -17.58,30.48 -35.22,-0.06 -17.58,-30.42 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.42 35.22,0 17.58,30.42 z m 0,60.96 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.22,0 -17.58,-30.48 17.58,-30.42 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.22,0 -17.58,-30.42 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.42 35.22,0 17.58,30.42 z m -158.34,-578.88 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.16,0 -17.58,-30.42 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.58,30.42 z m 0,60.96 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.16,0 -17.58,-30.42 17.58,-30.48 35.16,0 17.58,30.48 z m 52.8,-457.02 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.42 35.22,0 17.58,30.42 z m 0,60.96 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.22,0 -17.58,-30.48 17.58,-30.42 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.22,0 -17.58,-30.42 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.22,0 -17.58,-30.48 17.58,-30.42 35.22,0 17.58,30.48 z m -158.34,-578.94 -17.579998,30.48 -35.16,0 -17.64,-30.48 17.64,-30.48 35.16,0 17.579998,30.48 z m 0,60.96 -17.579998,30.42 -35.16,0 -17.64,-30.42 17.64,-30.48 35.16,0 17.579998,30.48 z m 0,60.9 -17.579998,30.48 -35.16,0 -17.64,-30.48 17.64,-30.48 35.16,0 17.579998,30.48 z m 0,60.96 -17.579998,30.48 -35.16,0 -17.64,-30.48 17.64,-30.48 35.16,0 17.579998,30.48 z m 0,60.9 -17.579998,30.48 -35.16,0 -17.64,-30.48 17.64,-30.42 35.16,0 17.579998,30.42 z m 0,60.96 -17.579998,30.48 -35.16,0 -17.64,-30.48 17.64,-30.48 35.16,0 17.579998,30.48 z m 0,60.96 -17.579998,30.42 -35.16,0 -17.64,-30.48 17.64,-30.42 35.16,0 17.579998,30.48 z m 0,60.9 -17.579998,30.48 -35.16,0 -17.64,-30.48 17.64,-30.48 35.16,0 17.579998,30.48 z m 0,60.96 -17.579998,30.48 -35.16,0 -17.64,-30.48 17.64,-30.48 35.16,0 17.579998,30.48 z m 52.8,-457.02 -17.58,30.48 -35.22,0 -17.579998,-30.48 17.579998,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.22,0 -17.579998,-30.48 17.579998,-30.42 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.579998,-30.48 17.579998,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.22,0 -17.579998,-30.42 17.579998,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.579998,-30.48 17.579998,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.48 -35.22,0 -17.579998,-30.48 17.579998,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.579998,-30.48 17.579998,-30.42 35.22,0 17.58,30.42 z m 0,60.96 -17.58,30.48 -35.22,0 -17.579998,-30.48 17.579998,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.22,0 -17.579998,-30.42 17.579998,-30.48 35.22,0 17.58,30.48 z m 474.96,-335.1 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m -52.8,-91.44 -17.58,30.48 -35.16,0 -17.64,-30.48 17.64,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.48 -35.16,0 -17.64,-30.48 17.64,-30.48 35.16,0 17.58,30.48 z m -52.74,-91.44 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.64,30.48 z m 0,60.96 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.64,30.48 z m -52.8,-91.44 -17.58,30.48 -35.22,0 -17.58,-30.48 17.64,-30.42 35.16,0 17.58,30.42 z m 0,60.96 -17.58,30.48 -35.22,0 -17.58,-30.48 17.64,-30.48 35.16,0 17.58,30.48 z m -52.8,-91.44 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.58,30.42 z m 0,60.96 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m -52.74,-91.38 -17.58,30.42 -35.22,0 -17.58,-30.48 17.58,-30.42 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m -52.8,-91.38 -17.58,30.42 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m -52.74,-91.38 -17.58,30.42 -35.22,0 -17.58,-30.42 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m -52.8,-91.38 -17.58,30.42 -35.16,0 -17.58,-30.42 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m -52.74,-91.38 -17.58,30.48 -35.22,0 L 97.730001,109.43 115.31,78.949995 l 35.22,0 17.58,30.480005 z m 0,60.9 -17.58,30.48 -35.22,0 -17.579999,-30.48 17.579999,-30.42 35.22,0 17.58,30.42 z M 115.31,78.949995 97.730001,109.43 l -35.16,0 -17.58,-30.480005 17.58,-30.48 35.16,0 17.579999,30.48 z m 0,60.960005 -17.579999,30.42 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.579999,30.48 z" /><path - id="path14" - style="fill:none;stroke:#003fff;stroke-width:5.63999987;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1" - d="m 625.43,1023.53 -35.16,0 -17.58,-30.48 -35.22,0 -17.58,-30.48 -35.16,0 -17.58,-30.48 -35.22,0 -17.58,-30.48 -35.16,0 -17.58,-30.48 -35.22,0 -17.58,-30.48 -35.16,0 -17.58,-30.48 -35.22,0 -17.58,-30.48 -35.16,0 -17.58,-30.42 -35.22,-0.06 -17.579998,-30.42 -35.16,0 M 625.49,353.21 l -35.22,0 -17.58,-30.48 -35.16,0 -17.64,-30.48 -35.16,0 -17.58,-30.42 -35.22,-0.06 -17.58,-30.42 -35.16,0 -17.58,-30.48 -35.22,0 -17.58,-30.48 -35.16,0 -17.58,-30.48 -35.22,0 -17.58,-30.48 -35.16,0 -17.58,-30.480005 -35.22,0 -17.579998,-30.480001 -35.16,0" /><path - id="path16" - style="fill:none;stroke:#dd0000;stroke-width:5.63999987;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1" - d="m 625.43,1023.53 17.64,-30.48 -17.58,-30.48 17.58,-30.48 -17.58,-30.42 17.58,-30.48 -17.64,-30.48 17.64,-30.48 -17.58,-30.48 17.58,-30.42 -17.58,-30.48 17.58,-30.48 -17.64,-30.48 17.64,-30.42 -17.58,-30.48 17.58,-30.48 -17.58,-30.48 17.58,-30.48 -17.58,-30.42 17.58,-30.48 -17.64,-30.48 17.64,-30.48 -17.64,-30.48 m -562.859999,365.58 -17.64,-30.48 17.64,-30.48 -17.64,-30.48 17.64,-30.48 -17.64,-30.48 17.64,-30.42 -17.64,-30.48 17.64,-30.48 -17.64,-30.48 17.64,-30.42 -17.64,-30.48 17.64,-30.48 -17.64,-30.48 17.64,-30.48 -17.64,-30.42 17.64,-30.48 -17.64,-30.48 17.64,-30.48 -17.58,-30.48 17.58,-30.42 -17.58,-30.480006 17.58,-30.48" /></g></svg> diff --git a/variants/Hex/Regular_hexagon.svg b/variants/Hex/Regular_hexagon.svg deleted file mode 100644 index fc47b04..0000000 --- a/variants/Hex/Regular_hexagon.svg +++ /dev/null @@ -1,9 +0,0 @@ -<svg width="173.2px" height="400.0px" viewBox="-86.6 -100.0 173.2 400.0"> - <defs> - <g id="hexa"> - <polygon style="fill:none;stroke:#000000;stroke-width:1px" points="0,-100.0 86.6,-50.0 86.6,50.0 0,100.0 -86.6,50.0 -86.6,-50.0"/> - </g> - </defs> - <use href="#hexa" x="0" y="0"/> - <use href="#hexa" x="0" y="200"/> -</svg> diff --git a/variants/Hex/class.js b/variants/Hex/class.js index ec14a06..37bd53c 100644 --- a/variants/Hex/class.js +++ b/variants/Hex/class.js @@ -1,4 +1,7 @@ -// https://www.boardspace.net/hex/english/Rules%20-%20HexWiki.htm +import ChessRules from "/base_rules.js"; +import PiPo from "/utils/PiPo.js"; +import Move from "/utils/Move.js"; + export default class HexRules extends ChessRules { static get Options() { @@ -6,21 +9,26 @@ export default class HexRules extends ChessRules { input: [ { label: "Board size", + variable: "bsize", type: "number", - defaut: 11, - variable: "bsize" - } - ], - check: [ + defaut: 11 + }, { label: "Swap", - defaut: true, - variable: "swap" + variable: "swap", + type: "checkbox", + defaut: true } ] }; } + get hasFlags() { + return false; + } + get hasEnpassant() { + return false; + } get hasReserve() { return false; } @@ -31,8 +39,11 @@ export default class HexRules extends ChessRules { doClick(coords) { if ( - this.board[coords.x][coords.y] != "" && - (!this.swap || this.movesCount >= 2) + this.playerColor != this.turn || + ( + this.board[coords.x][coords.y] != "" && + (!this.options["swap"] || this.movesCount >= 2) + ) ) { return null; } @@ -63,58 +74,89 @@ export default class HexRules extends ChessRules { genRandInitFen() { // NOTE: size.x == size.y (square boards) - const emptyCount = C.FenEmptySquares(this.size.x.repeat); - return (emptyCount + "/").repeat(this.size.x).slice(0, -1); + const emptyCount = C.FenEmptySquares(this.size.x); + return (emptyCount + "/").repeat(this.size.x).slice(0, -1) + " w 0"; } - getPieceWidth(rwidth) { - return (rwidth / this.size.y); //TODO - } - - // TODO + // TODO: re-enable rotation getSvgChessboard() { + // NOTE: with small margin seems nicer + let width = 173.2 * this.size.y + 173.2 * (this.size.y-1) / 2 + 30, + height = 50 + Math.floor(150 * this.size.x) + 30, + min_x = -86.6 - 15, + min_y = -100 - 15; +// if (this.size.rotate) { +// [width, height] = [height, width]; +// [min_x, min_y] = [min_y, min_x]; +// } let board = ` <svg - width="2771.2px" height="1700px" - class="chessboard_SVG"> + viewBox="${min_x} ${min_y} ${width} ${height}" + class="chessboard_SVG"`; +// if (this.size.rotate) +// board += ` transform="rotate(90 ${min_x} ${min_y})"` + board += `> <defs> <g id="hexa"> <polygon - style="fill:none;stroke:#000000;stroke-width:1px" + style="stroke:#000000;stroke-width:1" points="0,-100.0 86.6,-50.0 86.6,50.0 0,100.0 -86.6,50.0 -86.6,-50.0" /> </g> </defs>`; + board += "<g>"; for (let i=0; i < this.size.x; i++) { for (let j=0; j < this.size.y; j++) { - let classes = this.getSquareColorClass(i, j); - board += `<rect - class="neutral-square" - id="${this.coordsToId([i, j])}" - width="10" - height="10" - x="${10*j}" ///////////// + resize ! ratio - y="${10*i}" />`; + board += ` + <use + href="#hexa" + class="neutral-square" + id="${this.coordsToId({x: i, y: j})}" + x="${173.2*j + 86.6*i}" + y="${150*i}" + />`; } } - board += "</g></svg>"; + board += `</g><g style="fill:none;stroke-width:10">`; + // Goals: up/down/left/right + board += `<polyline style="stroke:red" points="` + for (let i=0; i<=2*this.size.y; i++) + board += ((i-1)*86.6) + ',' + (i % 2 == 0 ? -50 : -100) + ' '; + board += `"/><polyline style="stroke:red" points="`; + for (let i=1; i<=2*this.size.y; i++) { + const jShift = 200 * Math.floor((this.size.y+1)/2) + + 100 * (Math.floor(this.size.y/2) - 1) + + (i % 2 == 0 ? -50 : 0) + + (this.size.y % 2 == 0 ? 50 : 0); + board += ((i+this.size.y-2)*86.6) + ',' + jShift + ' '; + } + board += `"/><polyline style="stroke:blue" points="`; + let sumY = -100; + for (let i=0; i<=2*this.size.x; i++) { + board += ((Math.floor(i/2)-1) * 86.6) + ',' + + (sumY += (i % 2 == 0 ? 50 : 100)) + ' '; + } + board += `"/><polyline style="stroke:blue" points="`; + sumY = -100; + for (let i=0; i<2*this.size.x; i++) { + board += (173.2*this.size.x + (Math.floor(i/2)-1) * 86.6) + ',' + + (sumY += (i % 2 == 0 ? 50 : 100)) + ' '; + } + board += `"/></g></svg>`; return board; } setupPieces() { - // TODO: just scan board and get IDs, and addClass "bg-white" or "bg-black" - } - - // TODO (NOTE: no flip here, always same view) - getPixelPosition(i, j, r) { - if (i < 0 || j < 0) - return [0, 0]; //piece vanishes - let x, y; - const sqSize = r.width / this.size.y; - const flipped = (this.playerColor == 'b'); - const x = (flipped ? this.size.y - 1 - j : j) * sqSize, - y = (flipped ? this.size.x - 1 - i : i) * sqSize; - return [r.x + x, r.y + y]; + for (let i=0; i<this.size.x; i++) { + for (let j=0; j<this.size.y; j++) { + if (this.board[i][j] != "") { + const sqColor = (this.getColor(i, j) == 'w' ? "white" : "black"); + const elt = document.getElementById(this.coordsToId({x: i, y: j})); + elt.classList.remove("neutral-square"); + elt.classList.add("bg-" + sqColor); + } + } + } } initMouseEvents() { @@ -136,46 +178,74 @@ export default class HexRules extends ChessRules { } get size() { + const baseRatio = 1.619191; // 2801.2 / 1730, "widescreen" + const rotate = window.innerWidth < window.innerHeight; //"vertical screen" return { - x: this.bsize, - y: this.bsize, - ratio: 1.630118 - }; - } - - pieces() { - return { - 'p': { - "class": "pawn", - } + x: this.options["bsize"], + y: this.options["bsize"], + ratio: rotate ? 1 / baseRatio : baseRatio, + rotate: rotate }; } play(move) { - super.playOnBoard(move); + this.playOnBoard(move); + this.movesCount++; + this.turn = C.GetOppCol(this.turn); } - // TODO: getCurrentScore(move) { const oppCol = C.GetOppCol(this.turn); - // Search for connecting path of opp color: TODO - // ... - if (path found) - return (oppCol == "w" ? "1-0" : "0-1"); + // Search for connecting path of opp color: + let explored = {}, component; + let min, max; + const getIndex = (x, y) => x + "." + y; + // Explore one connected component: + const neighborsSearch = ([x, y], index) => { + // Let's say "white" connects on x and "black" on y + const z = (oppCol == 'w' ? x : y); + if (z < min) + min = z; + if (z > max) + max = z; + explored[index] = true; + component[index] = true; + for (let [dx, dy] of super.pieces()['k'].moves[0].steps) { + const [nx, ny] = [x + dx, y + dy]; + const nidx = getIndex(nx, ny); + if ( + this.onBoard(nx, ny) && + this.getColor(nx, ny) == oppCol && + !component[nidx] + ) { + neighborsSearch([nx, ny], nidx); + } + } + }; + // Explore all components: + for (let i=0; i<this.size.x; i++) { + for (let j=0; j<this.size.y; j++) { + const index = getIndex(i, j); + if (this.getColor(i, j) == oppCol && !explored[index]) { + component = {}; + [min, max] = [this.size.x, 0]; + neighborsSearch([i, j], index); + if (max - min == this.size.x - 1) + return (oppCol == "w" ? "1-0" : "0-1"); + } + } + } return "*"; } playVisual(move) { move.vanish.forEach(v => { -// TODO: just get ID, and remClass "bg-white" or "bg-black" (in CSS: TODO) + let elt = document.getElementById(this.coordsToId({x: v.x, y: v.y})); + elt.classList.remove("bg-" + (v.c == 'w' ? "white" : "black")); }); move.appear.forEach(a => { -// TODO: just get ID, and addClass "bg-white" or "bg-black" (in CSS: TODO) -// this.g_pieces[a.x][a.y] = document.createElement("piece"); -// this.g_pieces[a.x][a.y].classList.add(this.pieces()[a.p]["class"]); -// this.g_pieces[a.x][a.y].classList.add(a.c == "w" ? "white" : "black"); -// this.g_pieces[a.x][a.y].style.width = pieceWidth + "px"; -// this.g_pieces[a.x][a.y].style.height = pieceWidth + "px"; + let elt = document.getElementById(this.coordsToId({x: a.x, y: a.y})); + elt.classList.add("bg-" + (a.c == 'w' ? "white" : "black")); }); } diff --git a/variants/Hex/rules.html b/variants/Hex/rules.html new file mode 100644 index 0000000..33be5a2 --- /dev/null +++ b/variants/Hex/rules.html @@ -0,0 +1,5 @@ +<p>Win by connecting both edges of your color.</p> + +<a href="https://www.maths.ed.ac.uk/~csangwin/hex/index.html">Detailed rules.</a> + +<p class="author">Piet Hein (1942).</p> diff --git a/variants/Hex/style.css b/variants/Hex/style.css index 91ea8fd..a1c41b4 100644 --- a/variants/Hex/style.css +++ b/variants/Hex/style.css @@ -1,3 +1,10 @@ .neutral-square { fill: #eaeded; } + +.bg-white { + fill: red; +} +.bg-black { + fill: blue; +} diff --git a/variants/Madrasi/class.js b/variants/Madrasi/class.js index eaabf07..bbec80a 100644 --- a/variants/Madrasi/class.js +++ b/variants/Madrasi/class.js @@ -5,13 +5,14 @@ export default class MadrasiRules extends ChessRules { static get Options() { return { select: C.Options.select, - check: [ + input: [ { label: "Rex Incl.", - defaut: false, - variable: "rexincl" + variable: "rexincl", + type: "checkbox", + defaut: false } - ].concat(C.Options.check), + ].concat(C.Options.input), styles: C.Options.styles.filter(s => s != "madrasi") }; } diff --git a/variants/Progressive/class.js b/variants/Progressive/class.js index c209821..90bb998 100644 --- a/variants/Progressive/class.js +++ b/variants/Progressive/class.js @@ -5,13 +5,14 @@ export default class ProgressiveRules extends ChessRules { static get Options() { return { select: C.Options.select, - check: [ + input: [ { label: "Logical", - defaut: false, - variable: "logical" + variable: "logical", + type: "checkbox", + defaut: false } - ].concat(C.Options.check), + ].concat(C.Options.input), styles: C.Options.styles.filter(s => s != "progressive") }; } diff --git a/variants/Recycle/class.js b/variants/Recycle/class.js index 82458a9..d8c78e9 100644 --- a/variants/Recycle/class.js +++ b/variants/Recycle/class.js @@ -5,16 +5,18 @@ export default class RecycleRules extends ChessRules { static get Options() { return { select: C.Options.select, - check: [ + input: [ { label: "Capture king", - defaut: false, - variable: "taking" + variable: "taking", + type: "checkbox", + defaut: false }, { label: "Falling pawn", - defaut: true, - variable: "pawnfall" + variable: "pawnfall", + type: "checkbox", + defaut: true } ], styles: C.Options.styles.filter(s => s != "recycle") diff --git a/variants/Rifle/class.js b/variants/Rifle/class.js index 01b4d00..58b3d23 100644 --- a/variants/Rifle/class.js +++ b/variants/Rifle/class.js @@ -5,7 +5,7 @@ export default class RifleRules extends ChessRules { static get Options() { return { select: C.Options.select, - check: C.Options.check, + input: C.Options.input, styles: C.Options.styles.filter(s => s != "rifle") }; } diff --git a/variants/Teleport/class.js b/variants/Teleport/class.js index 5e52252..2698eaf 100644 --- a/variants/Teleport/class.js +++ b/variants/Teleport/class.js @@ -6,7 +6,7 @@ export default class TeleportRules extends ChessRules { return { select: C.Options.select, // TODO? option "teleport king"? - check: C.Options.check, + input: C.Options.input, styles: C.Options.styles.filter(s => s != "teleport") }; } diff --git a/variants/Zen/class.js b/variants/Zen/class.js index 424452d..5bb8c52 100644 --- a/variants/Zen/class.js +++ b/variants/Zen/class.js @@ -5,7 +5,7 @@ export default class ZenRules extends ChessRules { static get Options() { return { select: C.Options.select, - check: C.Options.check, + input: C.Options.input, styles: C.Options.styles.filter(s => s != "zen") }; } -- 2.44.0