From 94a4d590a3d3b74db0ad643189409fa4847288f9 Mon Sep 17 00:00:00 2001 From: Benjamin Auder Date: Thu, 7 May 2026 03:03:34 +0200 Subject: [PATCH] Few fixes + improve 8-pieces; last TODOs --- css/common.css | 19 +++-- js/app.js | 6 +- js/base_rules.js | 1 + variants/Eightpieces/class.js | 132 ++++++++++++++++++++-------------- 4 files changed, 95 insertions(+), 63 deletions(-) diff --git a/css/common.css b/css/common.css index eabf641..38d0f95 100644 --- a/css/common.css +++ b/css/common.css @@ -305,7 +305,7 @@ piece.mark.transparent { } .option-input { display: inline-block; - margin-right: 10px; + margin-right: 15px; } .option-input input[type=number] { width: 64px; @@ -546,11 +546,14 @@ select:focus + .focus { width: 100%; } +label.input-checkbox { + cursor: pointer; +} /* https://dev.to/kallmanation/styling-a-checkbox-with-only-css-3o3p */ -label.checkbox > input[type="checkbox"] { +label.input-checkbox > input[type="checkbox"] { display: none; } -label.checkbox > input[type="checkbox"] + *::before { +label.input-checkbox > input[type="checkbox"] + *::before { content: ""; display: inline-block; vertical-align: bottom; @@ -562,22 +565,24 @@ label.checkbox > input[type="checkbox"] + *::before { border-width: 0.1rem; border-color: gray; } -label.checkbox > input[type="checkbox"]:checked + *::before { +label.input-checkbox > input[type="checkbox"]:checked + *::before { content: "✓"; font-size: 1.1rem; - /*padding:10px;*/ color: white; text-align: center; background: teal; border-color: teal; } -label.checkbox > input[type="checkbox"]:checked + * { +label.input-checkbox > input[type="checkbox"]:checked + * { color: teal; } -label.checkbox > span.spacer { +label.input-checkbox > span.spacer { width: 10px; content: " "; } +label.input-checkbox > span.after-spacer { + padding-left: 5px; +} /* https://theanam.github.io/css-only-loaders/ ("hour-glass") */ :root{ diff --git a/js/app.js b/js/app.js index 7d30a32..016a1c3 100644 --- a/js/app.js +++ b/js/app.js @@ -211,10 +211,10 @@ function prepareOptions() { inputAttrs.value = input.defaut; container.append( h('div', { class: 'option-input' }, [ - h('label', { class: 'input' }, [ + h('label', { class: "input-" + input.type }, [ h('input', inputAttrs), h('span', { class: 'spacer' }), - h('span', { textContent: input.label }) + h('span', { class: 'after-spacer', textContent: input.label }) ]) ]) ); @@ -315,7 +315,7 @@ async function fillGameInfos(gameInfos, oppIndex) { // Final assembling container.append( playerDiv, - //activeOptions.length > 0 ? optionsInfos : null, + optionsInfos, rulesDiv, btnWrap ); diff --git a/js/base_rules.js b/js/base_rules.js index 84cf1ea..4fc46ac 100644 --- a/js/base_rules.js +++ b/js/base_rules.js @@ -1470,6 +1470,7 @@ export default class ChessRules { return false; } + // Check if it's possible to go from x1,y1 to x2,y2 with 'range' steps compatibleStep([x1, y1], [x2, y2], step, range) { const epsilon = 1e-7; //arbitrary small value let shifts = [0]; diff --git a/variants/Eightpieces/class.js b/variants/Eightpieces/class.js index 676ae90..62e718f 100644 --- a/variants/Eightpieces/class.js +++ b/variants/Eightpieces/class.js @@ -13,6 +13,10 @@ export default class EightpiecesRules extends ChessRules { }; } + static get LANCERS() { + return ['c', 'd', 'e', 'f', 'g', 'h', 'm', 'o']; + } + getLancerOptions(x, y) { let options = []; if (y > 0) @@ -63,10 +67,6 @@ export default class EightpiecesRules extends ChessRules { }; } - static get LANCERS() { - return ['c', 'd', 'e', 'f', 'g', 'h', 'm', 'o']; - } - // obj == "-", {-1,-1} or ["]{x,y}["] static convertPush(obj) { if (typeof obj === "string") @@ -159,11 +159,6 @@ export default class EightpiecesRules extends ChessRules { }, super.pieces(color, x, y)); } - canStepOver(i, j, p, c) { - const colIJ = this.getColor(i, j); - return this.board[i][j] == "" || (V.LANCERS.includes(p) && c == colIJ); - } - canIplay(x, y) { if ( this.pushFrom.x == x && this.pushFrom.y == y && @@ -174,6 +169,11 @@ export default class EightpiecesRules extends ChessRules { return super.canIplay(x, y); } + canStepOver(i, j, p, c) { + const colIJ = this.getColor(i, j); + return this.board[i][j] == "" || (V.LANCERS.includes(p) && c == colIJ); + } + isImmobilized([x, y]) { const color = this.getColor(x, y); const oppCol = C.GetOppTurn(color); @@ -215,18 +215,33 @@ export default class EightpiecesRules extends ChessRules { return res; } +// TODO: sentry nudge + + // after pushedTo, if lancer : allow reorient + move, or just reorient (move to king) if stuck + + // later, if stuck, allow reorient only (just click) + // doClick(coords) { TODO + getPotentialMovesFrom([x, y], color) { if (this.pushFrom.x < 0 || this.pushedTo.x >= 0) { let smoves = super.getPotentialMovesFrom([x, y], color); // Forbid direction x,y --> pushFrom if x,y == pushedTo if (x == this.pushedTo.x && y == this.pushedTo.y) { smoves = smoves.filter(m => { + let sx = this.pushFrom.x - x, + sy = this.pushFrom.y - y; + let divideBy = sx != 0 && sy != 0 && Math.abs(sx) != Math.abs(sy) + ? 1 + : Math.max(sx, sy); return ( !super.compatibleStep( [x, y], [m.end.x, m.end.y], - [this.pushFrom.x - x, this.pushFrom.y - y] + [sx / divideBy, sy / divideBy] ) ); }); } + + // TODO: lancer special case, move as a queen after push + return smoves.concat(this.getPassMoves(x, y)); } // pushFrom.x >= 0 && pushedTo.x < 0 @@ -242,39 +257,7 @@ export default class EightpiecesRules extends ChessRules { m.appear[0].c = m.vanish[0].c = oppCol; m.appear.push( new PiPo({x:x, y:y, p:'s', c:this.turn}) ); }); - -console.log(pmoves); - return pmoves; - - - - } - - postPlay(move) { - if ( - move.vanish.length > 0 && - move.vanish[0].p == 's' && - move.appear[0].c != move.vanish[0].c - ) { - // Sentry push ("capturing" part) - this.pushFrom = {x: move.end.x, y: move.end.y}; - this.pushedTo = {x: -1, y: -1}; - } - else if (move.vanish.length > 0 && move.vanish[0].c != this.turn) - this.pushedTo = {x: move.end.x, y: move.end.y}; - else { - // All other cases: just reset both push variables - this.pushFrom = {x: -1, y: -1}; - this.pushedTo = {x: -1, y: -1}; - } - super.postPlay(move); - } - - isLastMove(move) { - if (move.vanish[0].p == 's' && move.appear[0].c != move.vanish[0].c) - return false; - return super.isLastMove(move); } postProcessPotentialMoves(moves) { @@ -287,7 +270,7 @@ console.log(pmoves); ( (m.vanish.length > 0 && V.LANCERS.includes(m.vanish[0].p)) && // Next line test checks that the lancer wasn't just pushed away - (m.start.x != this.pushFrom.x || m.start.y != this.pushFrom.y) + (m.start.x != this.pushedTo.x || m.start.y != this.pushedTo.y) ) ) { this.getLancerOptions(m.end.x, m.end.y).forEach(o => { @@ -297,25 +280,68 @@ console.log(pmoves); }) ); }); } - else if (m.vanish.length == m.appear.length || m.vanish[0].p != 's') - finalMoves.push(m); - else { + else if (m.vanish.length == 2 && m.vanish[0].p == 's') { // Sentry "capture" --> remove sentry from final square (TODO: blink?) - const [x, y] = [m.end.x, m.end.y] - const p = this.getPiece(x, y); - const c = this.getColor(x, y); finalMoves.push( new Move({ - appear: [new PiPo({x:m.end.x,y:m.end.y,c:c,p:p})], - vanish: [ m.vanish[0] ] + appear: [], + vanish: [ m.vanish[0] ], + end: m.end }) ); } + else + finalMoves.push(m); } return finalMoves; } + postPlay(move) { + if ( + move.appear.length == 0 && + move.vanish.length > 0 && + move.vanish[0].p == 's' + ) { + // Sentry push ("capturing" part) + this.pushFrom = {x: move.end.x, y: move.end.y}; + this.pushedTo = {x: -1, y: -1}; + } + else if (move.vanish.length > 0 && move.vanish[0].c != this.turn) + this.pushedTo = {x: move.end.x, y: move.end.y}; + else { + // All other cases: just reset both push variables + this.pushFrom = {x: -1, y: -1}; + this.pushedTo = {x: -1, y: -1}; + } + super.postPlay(move); + } + + isLastMove(move) { + if (move.appear.length == 0) //move.vanish[0].p == 's' + return false; + return super.isLastMove(move); + } + underAttack([x, y], oppCols) { + if (super.underAttack([x, y], oppCols)) + return true; // TODO: check enemy sentry(ies), for each, check all of our own pieces which attack the square (if belonging to opponent!). Then, call : - return super.underAttack([x, y], oppCols); + const oppCol = oppCols[0]; + for (let i=0; i < this.size.x; i++) { + for (let j=0; j < this.size.y; j++) { + if ( + this.board[i][j] != "" && + this.getPiece(i, j) == 's' && + this.getColor(i, j) == oppCol + ) { + this.pieces()['s'].both[0].steps.forEach(s => { + let ii = i + s[0]; + // TODO......... + if (true) + return true; + }); + } + } + } + return false; } // Lazy sentry attacks check: after push move @@ -334,7 +360,7 @@ console.log(pmoves); updateReserve(color, piece, count) { if (V.LANCERS.includes(piece)) // Show only one lancer orientation, and reorient when drop: - piece = color == 'w' ? 'c' : 'g'; + piece = (color == 'w' ? 'c' : 'g'); super.updateReserve(color, piece, count); } -- 2.53.0