diff --git a/script.js b/script.js index 9e98f96..5220fe9 100644 --- a/script.js +++ b/script.js @@ -739,11 +739,10 @@ class Board { this.buttons.undo = addButton(x0, y0 + ysp*2, 'Undo', 'disabled'); this.buttons.working = addButton(x0, y0 + ysp*3, 'Working…', 'working'); - const cfgy0 = 10; + const cfgy0 = 10.5; this.buttons.optFancy = addButton(x0, cfgy0, 'Effects:', 'config'); this.buttons.optBlockedEffect = addButton(x0, cfgy0+ysp2, 'Dim Blocked:', 'config'); - this.buttons.optSloppy = addButton(x0, cfgy0+ysp2*2, 'Sloppy Mode:', 'config'); this.buttons.toggleFullscreen = addButton(x0, cfgy0+ysp2*-1.5, 'Fullscreen', 'config'); this.buttons.btnAbout = addButton(x0, cfgy0+ysp2*-2.5, 'Help', 'config'); @@ -761,7 +760,6 @@ class Board { updateSettingsGUI(cfg) { this.buttons.optFancy.textContent = 'Effects: '+(cfg.svgEffects ? 'On' : 'Off'); this.buttons.optBlockedEffect.textContent = 'Dim Blocked: '+(cfg.dimBlocked ? 'On' : 'Off'); - this.buttons.optSloppy.textContent = 'Sloppy Mode: '+(cfg.allowTemplateAugmenting ? 'On' : 'Off'); } } @@ -876,10 +874,8 @@ class SettingsStorage { this.defaults = { version: 1, log: 'info', - allowTemplateAugmenting: false, - retryTemplate: 120, + retryTemplate: 70, attemptTemplates: 20, - difficulty: 35, svgEffects: false, dimBlocked: true, logSolution: false, @@ -1238,7 +1234,6 @@ class Game { } placeOrbs(template) { - // let placer = new RadialOrbPlacer(this, template); let placer = new RecursiveOrbPlacer(this, template); return placer.place(); } @@ -1431,7 +1426,9 @@ class Game { installButtonHandlers() { this.board.buttons.restart.addEventListener('click', () => { this.info("New Game with the same seed"); - this.newGameWithLoader(this.rng.seed); + while (this.undoStack.length) { + this.undo(); + } }); this.board.buttons.randomize.addEventListener('click', () => { @@ -1467,13 +1464,6 @@ class Game { }) }); - this.board.buttons.optSloppy.addEventListener('click', () => { - this.info("Toggle sloppy placement mode"); - this.setCfg({ - allowTemplateAugmenting: !this.cfg.allowTemplateAugmenting, - }) - }); - this.board.buttons.toggleFullscreen.addEventListener('click', () => { this.info("Toggle Fullscreen"); if (document.fullscreenElement) { @@ -1833,150 +1823,6 @@ class BaseOrbPlacer { } } -/** - * Orb placement algorithm that starts in the center and places orbs in rings, with some - * small jitter allowed. - */ -class RadialOrbPlacer extends BaseOrbPlacer { - /** - * Find a candidate cell - * - * @param {number[]|null} except - indices to exclude - * @return {number} - */ - findBestCandidate(except = null) { - let candidates = []; - for (let n of this.template) { - if (except && except.includes(n)) continue; - - if (!this.board.grid[n]) { - // is free - const neigh = this.getCellInfo(n); - if (neigh.freeSequence >= 3) { - candidates.push({ - n, - cw: neigh.centerWeight - }); - } - } - } - - candidates.sort((a, b) => a.cw - b.cw); - - if (candidates.length) { - // return candidates[0].n; - let top = []; - let topw = candidates[0].cw; - for(let cand of candidates) { - if (cand.cw <= topw + this.cfg.difficulty) { // TODO this could vary by template - top.push(cand); - } - } - - //the neighbor count is not used for anything anymore, oops - - // console.log('Got a choice of '+top.length+' tiles'); - - return this.rng.arrayChoose(top).n; - } - - return false; - } - - /** - * Find index for next placement - * - * @param {number[]|null} except - indices to exclude - * @return {number} - index - */ - findAvailableIndex(except = null) { - const n = this.findBestCandidate(except); - if (n !== false) return n; - - // this corrupts the template, but makes the likelihood of quickly finding a valid solution much higher. - if (this.template.length !== BOARD_SIZE && this.cfg.allowTemplateAugmenting) { - // Prefer tile with more neighbours to make the game harder - let candidates = []; - this.outsideTemplate.forEach((n) => { - if (!this.templateMap[n] && this.isAvailable(n)) { - const neigh = this.getCellInfo(n); - if (!candidates[neigh.neighbours]) { - candidates[neigh.neighbours] = [n]; - } else { - candidates[neigh.neighbours].push(n); - } - } - }); - - for (let i = 6; i >= 0; i--) { - if (!candidates[i]) continue; - let toAdd = this.rng.arrayChoose(candidates[i]); - this.templateMap[toAdd] = true; - this.outsideTemplate.splice(this.outsideTemplate.indexOf(toAdd), 1); - - this.template.push(toAdd); - this.tilesAdded++; - - this.warn(`Adding extra tile to template: ${toAdd}`); - return toAdd; - } - } - - throw Error("Failed to find available board tile."); - } - - doPlace(toPlace) { - this.tilesAdded = 0; - - while (toPlace.length > 0) { - this.trace('placing a pair.'); - - let symbol1 = toPlace.pop(); - let index1 = this.findAvailableIndex(); - this.placeOrb(index1, symbol1); - this.solution.push([symbol1, index1]); - - let symbol2 = toPlace.pop(); - let index2 = this.findAvailableIndex(); - this.placeOrb(index2, symbol2); - - if (!this.isAvailable(index1)) { - this.debug(`Deadlock, trying to work around it - ${index1}, ${index2}`); - - this.removeOrb(index2); - let except = [index2]; - - let suc = false; - for (let i = 0; i < 5; i++) { - this.trace(`try #${i + 1}`); - let index = this.findAvailableIndex(except); - this.placeOrb(index, symbol2); - - if (this.isAvailable(index1)) { - suc = true; - index2 = index; - break; - } else { - this.removeOrb(index); - except.push(index); - } - } - - if (!suc) { - throw new Error("Solution contains a deadlock."); - } - } - - // index2 is updated in the fixing loop - this.solution.push([symbol2, index2]); - } - - return { - tilesAdded: this.tilesAdded, - }; - } -} - class RecursiveOrbPlacer extends BaseOrbPlacer { doPlace(toPlace) { this.toPlace = toPlace;