Add the ability to lock states, provinces, cultures, and religions (#902)

* Add the basis for locking everything, code and test the culture locking

* Got the religion generator working, but not the tree. There are cycles being generated

* Religions work now, including the tree view

* Got the states and provinces working as well, all good and ready

* Refresh the province editor when regenerating

* Implement the versioning steps

* Fix the state naming and color changing even when locked

* The fix did not work with loaded maps, fix that too

* Fix a few more bugs and address the PR feedback

* Fix the state expanding event when they're locked bug

* Implement some logic to ignore state being locked when regenerating provinces directly.
This commit is contained in:
Guillaume St-Pierre 2022-12-15 15:32:49 -05:00 committed by GitHub
parent 3883933385
commit 80b8bc89a1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 522 additions and 127 deletions

View file

@ -6,6 +6,12 @@ window.Cultures = (function () {
const generate = function () {
TIME && console.time("generateCultures");
cells = pack.cells;
const prevCultures = {};
if (cells.culture) {
cells.culture.forEach(function (cultureId, index) {
prevCultures[index] = cultureId;
})
}
cells.culture = new Uint16Array(cells.i.length); // cell cultures
let count = Math.min(+culturesInput.value, +culturesSet.selectedOptions[0].dataset.max);
@ -51,7 +57,29 @@ window.Cultures = (function () {
const emblemShape = document.getElementById("emblemShape").value;
const codes = [];
let unoccupied = [...populated];
cultures.forEach(function (c, i) {
if (c.lock) {
centers.add(c.center);
cells.culture[c.center] = i + 1;
codes.push(c.code);
const cultureCells = [];
Object.entries(prevCultures).forEach(function ([index, cultureId]) {
if (cultureId === c.i) {
cells.culture[index] = i + 1;
cultureCells.push(parseInt(index));
}
});
unoccupied = unoccupied.filter(function (cell) {
return !cultureCells.includes(cell);
});
c.i = i + 1;
return;
}
const cell = (c.center = placeCenter(c.sort ? c.sort : i => cells.s[i]));
centers.add(cells.p[cell]);
c.i = i + 1;
@ -70,12 +98,16 @@ window.Cultures = (function () {
function placeCenter(v) {
let c,
spacing = (graphWidth + graphHeight) / 2 / count;
const sorted = [...populated].sort((a, b) => v(b) - v(a)),
// Only use cells where there are no culture already on that cell, which may happen if a locked culture
// was restored. We can be sure that locked cultures will always be first in the list.
const sorted = [...unoccupied].sort((a, b) => v(b) - v(a)),
max = Math.floor(sorted.length / 2);
do {
c = sorted[biased(0, max, 5)];
spacing *= 0.9;
} while (centers.find(cells.p[c][0], cells.p[c][1], spacing) !== undefined);
} while (
centers.find(cells.p[c][0], cells.p[c][1], spacing) !== undefined
);
return c;
}
@ -98,6 +130,12 @@ window.Cultures = (function () {
const count = Math.min(c, def.length);
const cultures = [];
if (pack.cultures) {
pack.cultures.forEach(function (culture) {
if (culture.lock) cultures.push(culture);
});
}
for (let culture, rnd, i = 0; cultures.length < count && i < 200; i++) {
do {
rnd = rand(def.length - 1);
@ -481,7 +519,7 @@ window.Cultures = (function () {
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
pack.cultures.forEach(function (c) {
if (!c.i || c.removed) return;
if (!c.i || c.removed || c.lock) return;
queue.queue({e: c.center, p: 0, c: c.i});
});
@ -494,6 +532,8 @@ window.Cultures = (function () {
c = next.c;
const type = pack.cultures[c].type;
cells.c[n].forEach(function (e) {
if (pack.cultures[cells.culture[e]]?.lock) return;
const biome = cells.biome[e];
const biomeCost = getBiomeCost(c, biome, type);
const biomeChangeCost = biome === cells.biome[n] ? 0 : 20; // penalty on biome change