added new placement rules to make games more challenging

recursive
Ondřej Hruška 5 years ago
parent 081f252e89
commit 98fc39027a
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 70
      script.js
  2. 20
      style.css

@ -737,6 +737,7 @@ class Board {
this.buttons.randomize = addButton(x0, y0, 'Randomize'); this.buttons.randomize = addButton(x0, y0, 'Randomize');
this.buttons.restart = addButton(x0, y0 + ysp, 'Try Again', 'disabled'); this.buttons.restart = addButton(x0, y0 + ysp, 'Try Again', 'disabled');
this.buttons.undo = addButton(x0, y0 + ysp*2, 'Undo', 'disabled'); 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;
@ -844,6 +845,29 @@ class Rng {
arrayChoose(array) { arrayChoose(array) {
return array[Math.floor(this.next() * array.length)]; return array[Math.floor(this.next() * array.length)];
} }
/**
* Sneak items in the given order into another array
*
* @param array - the modified array
* @param startKeepout - how many leading lements to leave untouched
* @param endKeepout - how many trailing elements to leave untouched
* @param items - items to sneak in
* @return the modified array
*/
arraySneak(array, startKeepout, endKeepout, items) {
let positions = [];
for (let i = 0; i < items.length; i++) {
positions.push(startKeepout + this.nextInt(array.length - startKeepout - endKeepout))
}
positions.sort((a, b) => a - b);
// inject them into the array
items.forEach((pair, i) => {
array.splice(positions[i] + i, 0, pair);
});
return array;
}
} }
class SettingsStorage { class SettingsStorage {
@ -1044,7 +1068,7 @@ class Game {
// Defer start to give browser time to render the background // Defer start to give browser time to render the background
setTimeout(() => { setTimeout(() => {
this.newGame(args.seed) this.newGameWithLoader(args.seed)
}, 50); }, 50);
} }
@ -1407,12 +1431,12 @@ class Game {
installButtonHandlers() { installButtonHandlers() {
this.board.buttons.restart.addEventListener('click', () => { this.board.buttons.restart.addEventListener('click', () => {
this.info("New Game with the same seed"); this.info("New Game with the same seed");
this.newGame(this.rng.seed); this.newGameWithLoader(this.rng.seed);
}); });
this.board.buttons.randomize.addEventListener('click', () => { this.board.buttons.randomize.addEventListener('click', () => {
this.info("New Game with a random seed"); this.info("New Game with a random seed");
this.newGame(+new Date); this.newGameWithLoader(+new Date);
}); });
this.board.buttons.btnAbout.addEventListener('click', () => { this.board.buttons.btnAbout.addEventListener('click', () => {
@ -1488,6 +1512,15 @@ class Game {
} }
} }
newGameWithLoader(seed) {
this.board.buttons.working.classList.add('show');
setTimeout(() => {
this.newGame(seed);
this.board.buttons.working.classList.remove('show');
}, 20);
}
newGame(seed) { newGame(seed) {
if (seed !== null) { if (seed !== null) {
this.rng.setSeed(seed); this.rng.setSeed(seed);
@ -1693,40 +1726,23 @@ class BaseOrbPlacer {
toPlace.push(['salt', 'salt']); toPlace.push(['salt', 'salt']);
} }
// these are always paired like this, and don't support salt // shuffle the pairs that have random order (i.e. not metals)
toPlace = toPlace.concat([ this.rng.arrayShuffle(toPlace);
this.rng.arraySneak(toPlace, 3, 0, [
['mors', 'vitae'], ['mors', 'vitae'],
['mors', 'vitae'], ['mors', 'vitae'],
['mors', 'vitae'], ['mors', 'vitae'],
['mors', 'vitae'], ['mors', 'vitae'],
]); ]);
// shuffle the pairs that have random order (i.e. not metals) this.rng.arraySneak(toPlace, 4, 0, [
this.rng.arrayShuffle(toPlace);
// the order here is actually significant, so let's pay attention...
const metals = [
['lead', 'mercury'], ['lead', 'mercury'],
['tin', 'mercury'], ['tin', 'mercury'],
['iron', 'mercury'], ['iron', 'mercury'],
['copper', 'mercury'], ['copper', 'mercury'],
['silver', 'mercury'], ['silver', 'mercury'],
]; ]);
let mPos = [];
for (let i = 0; i < metals.length; i++) {
let x;
// find a unique position
do {
x = this.rng.nextInt(toPlace.length + i);
} while (mPos.includes(x));
mPos.push(x)
}
mPos.sort((a, b) => a - b);
this.trace('Metal positions ', mPos);
// inject them into the array
metals.forEach((pair, i) => {
toPlace.splice(mPos[i] + i, 0, pair);
});
this.debug('Placement order (last first):', toPlace); this.debug('Placement order (last first):', toPlace);
@ -1973,7 +1989,7 @@ class RecursiveOrbPlacer extends BaseOrbPlacer {
placeOne() { placeOne() {
this.recDepth++; this.recDepth++;
if (this.recDepth > 2000) { if (this.recDepth > 1000) {
throw new Error("Too many backtracks"); throw new Error("Too many backtracks");
} }

@ -122,6 +122,24 @@ text {
stroke-width: 2px; stroke-width: 2px;
cursor: pointer; cursor: pointer;
} }
.button-text.working,
.button-text.working:hover {
fill: #8d7761;
font-size: 26px;
opacity: 0;
}
.button-text.working {
transition: opacity linear 0.2s;
}
.cfg-no-anim .button-text.working {
transition: none;
}
.button-text.working.show {
opacity: 1;
}
.you-win { .you-win {
font-size: 80px; font-size: 80px;
@ -160,6 +178,8 @@ text {
transform: translateY(1px); transform: translateY(1px);
} }
.button-text.disabled, .button-text.disabled,
.button-text.disabled:hover, .button-text.disabled:hover,
.button-text.disabled:active { .button-text.disabled:active {

Loading…
Cancel
Save