mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-22 12:01:23 +01:00
refactor(#902): regenerate states - update provinces
This commit is contained in:
parent
77d644afb1
commit
5f1c2adee0
4 changed files with 66 additions and 1495 deletions
|
|
@ -1150,20 +1150,26 @@ window.BurgsAndStates = (function () {
|
||||||
Math.random = aleaPRNG(localSeed);
|
Math.random = aleaPRNG(localSeed);
|
||||||
|
|
||||||
const {cells, states, burgs} = pack;
|
const {cells, states, burgs} = pack;
|
||||||
|
|
||||||
const provinces = [0];
|
const provinces = [0];
|
||||||
|
const provinceIds = new Uint16Array(cells.i.length);
|
||||||
|
|
||||||
regenerate &&
|
const isProvinceLocked = province => province.lock || (!regenerateInLockedStates && states[province.state]?.lock);
|
||||||
|
const isProvinceCellLocked = cell => provinceIds[cell] && isProvinceLocked(provinces[provinceIds[cell]]);
|
||||||
|
|
||||||
|
if (regenerate) {
|
||||||
pack.provinces.forEach(province => {
|
pack.provinces.forEach(province => {
|
||||||
if (!province.i || !province.removed) return;
|
if (!province.i || province.removed || !isProvinceLocked(province)) return;
|
||||||
const isLockedOnStateLevel = !regenerateInLockedStates && states[province.state].lock;
|
|
||||||
if (province.lock || isLockedOnStateLevel) {
|
const newId = provinces.length;
|
||||||
province.i = provinces.length; // update id
|
for (const i of cells.i) {
|
||||||
provinces.push(province);
|
if (cells.province[i] === province.i) provinceIds[i] = newId;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
province.i = newId;
|
||||||
|
provinces.push(province);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
cells.province = cells.province || new Uint16Array(cells.i.length);
|
|
||||||
const percentage = +provincesInput.value;
|
const percentage = +provincesInput.value;
|
||||||
|
|
||||||
const max = percentage == 100 ? 1000 : gauss(20, 5, 5, 100) * percentage ** 0.5; // max growth
|
const max = percentage == 100 ? 1000 : gauss(20, 5, 5, 100) * percentage ** 0.5; // max growth
|
||||||
|
|
@ -1179,12 +1185,13 @@ window.BurgsAndStates = (function () {
|
||||||
|
|
||||||
// generate provinces for selected burgs
|
// generate provinces for selected burgs
|
||||||
states.forEach(s => {
|
states.forEach(s => {
|
||||||
|
s.provinces = [];
|
||||||
if (!s.i || s.removed) return;
|
if (!s.i || s.removed) return;
|
||||||
s.provinces = provinces.filter(p => p.state === s.i).map(p => p.i); // locked provinces ids
|
if (provinces.length) s.provinces = provinces.filter(p => p.state === s.i).map(p => p.i); // locked provinces ids
|
||||||
if (s.lock && !regenerateInLockedStates) return; // don't regenerate provinces of a locked state
|
if (s.lock && !regenerateInLockedStates) return; // don't regenerate provinces of a locked state
|
||||||
|
|
||||||
const stateBurgs = burgs
|
const stateBurgs = burgs
|
||||||
.filter(b => b.state === s.i && !b.removed && !cells.province[b.cell])
|
.filter(b => b.state === s.i && !b.removed && !provinceIds[b.cell])
|
||||||
.sort((a, b) => b.population * gauss(1, 0.2, 0.5, 1.5, 3) - a.population)
|
.sort((a, b) => b.population * gauss(1, 0.2, 0.5, 1.5, 3) - a.population)
|
||||||
.sort((a, b) => b.capital - a.capital);
|
.sort((a, b) => b.capital - a.capital);
|
||||||
if (stateBurgs.length < 2) return; // at least 2 provinces are required
|
if (stateBurgs.length < 2) return; // at least 2 provinces are required
|
||||||
|
|
@ -1194,7 +1201,6 @@ window.BurgsAndStates = (function () {
|
||||||
|
|
||||||
for (let i = 0; i < provincesNumber; i++) {
|
for (let i = 0; i < provincesNumber; i++) {
|
||||||
const provinceId = provinces.length;
|
const provinceId = provinces.length;
|
||||||
s.provinces.push(provinceId);
|
|
||||||
const center = stateBurgs[i].cell;
|
const center = stateBurgs[i].cell;
|
||||||
const burg = stateBurgs[i].i;
|
const burg = stateBurgs[i].i;
|
||||||
const c = stateBurgs[i].culture;
|
const c = stateBurgs[i].culture;
|
||||||
|
|
@ -1208,6 +1214,8 @@ window.BurgsAndStates = (function () {
|
||||||
const type = getType(center, burg.port);
|
const type = getType(center, burg.port);
|
||||||
const coa = COA.generate(stateBurgs[i].coa, kinship, null, type);
|
const coa = COA.generate(stateBurgs[i].coa, kinship, null, type);
|
||||||
coa.shield = COA.getShield(c, s.i);
|
coa.shield = COA.getShield(c, s.i);
|
||||||
|
|
||||||
|
s.provinces.push(provinceId);
|
||||||
provinces.push({i: provinceId, state: s.i, center, burg, name, formName, fullName, color, coa});
|
provinces.push({i: provinceId, state: s.i, center, burg, name, formName, fullName, color, coa});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -1216,9 +1224,9 @@ window.BurgsAndStates = (function () {
|
||||||
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
|
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
|
||||||
const cost = [];
|
const cost = [];
|
||||||
|
|
||||||
provinces.forEach(function (p) {
|
provinces.forEach(p => {
|
||||||
if (!p.i || p.removed || p.lock) return;
|
if (!p.i || p.removed || isProvinceLocked(p)) return;
|
||||||
cells.province[p.center] = p.i;
|
provinceIds[p.center] = p.i;
|
||||||
queue.queue({e: p.center, p: 0, province: p.i, state: p.state});
|
queue.queue({e: p.center, p: 0, province: p.i, state: p.state});
|
||||||
cost[p.center] = 1;
|
cost[p.center] = 1;
|
||||||
});
|
});
|
||||||
|
|
@ -1226,8 +1234,8 @@ window.BurgsAndStates = (function () {
|
||||||
while (queue.length) {
|
while (queue.length) {
|
||||||
const {e, p, province, state} = queue.dequeue();
|
const {e, p, province, state} = queue.dequeue();
|
||||||
|
|
||||||
cells.c[e].forEach(function (e) {
|
cells.c[e].forEach(e => {
|
||||||
if (provinces[province].lock) return; // do not overwrite cell of locked provinces
|
if (isProvinceCellLocked(e)) return; // do not overwrite cell of locked provinces
|
||||||
|
|
||||||
const land = cells.h[e] >= 20;
|
const land = cells.h[e] >= 20;
|
||||||
if (!land && !cells.t[e]) return; // cannot pass deep ocean
|
if (!land && !cells.t[e]) return; // cannot pass deep ocean
|
||||||
|
|
@ -1237,7 +1245,7 @@ window.BurgsAndStates = (function () {
|
||||||
|
|
||||||
if (totalCost > max) return;
|
if (totalCost > max) return;
|
||||||
if (!cost[e] || totalCost < cost[e]) {
|
if (!cost[e] || totalCost < cost[e]) {
|
||||||
if (land) cells.province[e] = province; // assign province to a cell
|
if (land) provinceIds[e] = province; // assign province to a cell
|
||||||
cost[e] = totalCost;
|
cost[e] = totalCost;
|
||||||
queue.queue({e, p: totalCost, province, state});
|
queue.queue({e, p: totalCost, province, state});
|
||||||
}
|
}
|
||||||
|
|
@ -1247,23 +1255,26 @@ window.BurgsAndStates = (function () {
|
||||||
// justify provinces shapes a bit
|
// justify provinces shapes a bit
|
||||||
for (const i of cells.i) {
|
for (const i of cells.i) {
|
||||||
if (cells.burg[i]) continue; // do not overwrite burgs
|
if (cells.burg[i]) continue; // do not overwrite burgs
|
||||||
if (provinces[cells.province[i]].lock) return; // do not overwrite cell of locked provinces
|
if (isProvinceCellLocked(i)) continue; // do not overwrite cell of locked provinces
|
||||||
|
|
||||||
const neibs = cells.c[i]
|
const neibs = cells.c[i]
|
||||||
.filter(c => cells.state[c] === cells.state[i] && !provinces[cells.province[c]].lock)
|
.filter(c => cells.state[c] === cells.state[i] && !isProvinceCellLocked(c))
|
||||||
.map(c => cells.province[c]);
|
.map(c => provinceIds[c]);
|
||||||
const adversaries = neibs.filter(c => c !== cells.province[i]);
|
const adversaries = neibs.filter(c => c !== provinceIds[i]);
|
||||||
if (adversaries.length < 2) continue;
|
if (adversaries.length < 2) continue;
|
||||||
const buddies = neibs.filter(c => c === cells.province[i]).length;
|
|
||||||
|
const buddies = neibs.filter(c => c === provinceIds[i]).length;
|
||||||
if (buddies.length > 2) continue;
|
if (buddies.length > 2) continue;
|
||||||
|
|
||||||
const competitors = adversaries.map(p => adversaries.reduce((s, v) => (v === p ? s + 1 : s), 0));
|
const competitors = adversaries.map(p => adversaries.reduce((s, v) => (v === p ? s + 1 : s), 0));
|
||||||
const max = d3.max(competitors);
|
const max = d3.max(competitors);
|
||||||
if (buddies >= max) continue;
|
if (buddies >= max) continue;
|
||||||
cells.province[i] = adversaries[competitors.indexOf(max)];
|
|
||||||
|
provinceIds[i] = adversaries[competitors.indexOf(max)];
|
||||||
}
|
}
|
||||||
|
|
||||||
// add "wild" provinces if some cells don't have a province assigned
|
// add "wild" provinces if some cells don't have a province assigned
|
||||||
const noProvince = Array.from(cells.i).filter(i => cells.state[i] && !cells.province[i]); // cells without province assigned
|
const noProvince = Array.from(cells.i).filter(i => cells.state[i] && !provinceIds[i]); // cells without province assigned
|
||||||
states.forEach(s => {
|
states.forEach(s => {
|
||||||
if (!s.i || s.removed) return;
|
if (!s.i || s.removed) return;
|
||||||
if (s.lock && !regenerateInLockedStates) return;
|
if (s.lock && !regenerateInLockedStates) return;
|
||||||
|
|
@ -1279,36 +1290,34 @@ window.BurgsAndStates = (function () {
|
||||||
return spliced[0] ? `New ${spliced[0]}` : null;
|
return spliced[0] ? `New ${spliced[0]}` : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
let stateNoProvince = noProvince.filter(i => cells.state[i] === s.i && !cells.province[i]);
|
let stateNoProvince = noProvince.filter(i => cells.state[i] === s.i && !provinceIds[i]);
|
||||||
while (stateNoProvince.length) {
|
while (stateNoProvince.length) {
|
||||||
// add new province
|
// add new province
|
||||||
const province = provinces.length;
|
const provinceId = provinces.length;
|
||||||
const burgCell = stateNoProvince.find(i => cells.burg[i]);
|
const burgCell = stateNoProvince.find(i => cells.burg[i]);
|
||||||
const center = burgCell ? burgCell : stateNoProvince[0];
|
const center = burgCell ? burgCell : stateNoProvince[0];
|
||||||
const burg = burgCell ? cells.burg[burgCell] : 0;
|
const burg = burgCell ? cells.burg[burgCell] : 0;
|
||||||
cells.province[center] = province;
|
provinceIds[center] = provinceId;
|
||||||
|
|
||||||
// expand province
|
// expand province
|
||||||
const cost = [];
|
const cost = [];
|
||||||
cost[center] = 1;
|
cost[center] = 1;
|
||||||
queue.queue({e: center, p: 0});
|
queue.queue({e: center, p: 0});
|
||||||
while (queue.length) {
|
while (queue.length) {
|
||||||
const next = queue.dequeue(),
|
const {e, p} = queue.dequeue();
|
||||||
n = next.e,
|
|
||||||
p = next.p;
|
|
||||||
|
|
||||||
cells.c[n].forEach(function (e) {
|
cells.c[e].forEach(nextCellId => {
|
||||||
if (cells.province[e]) return;
|
if (provinceIds[nextCellId]) return;
|
||||||
const land = cells.h[e] >= 20;
|
const land = cells.h[nextCellId] >= 20;
|
||||||
if (cells.state[e] && cells.state[e] !== s.i) return;
|
if (cells.state[nextCellId] && cells.state[nextCellId] !== s.i) return;
|
||||||
const ter = land ? (cells.state[e] === s.i ? 3 : 20) : cells.t[e] ? 10 : 30;
|
const ter = land ? (cells.state[nextCellId] === s.i ? 3 : 20) : cells.t[nextCellId] ? 10 : 30;
|
||||||
const totalCost = p + ter;
|
const totalCost = p + ter;
|
||||||
|
|
||||||
if (totalCost > max) return;
|
if (totalCost > max) return;
|
||||||
if (!cost[e] || totalCost < cost[e]) {
|
if (!cost[nextCellId] || totalCost < cost[nextCellId]) {
|
||||||
if (land && cells.state[e] === s.i) cells.province[e] = province; // assign province to a cell
|
if (land && cells.state[nextCellId] === s.i) provinceIds[nextCellId] = provinceId; // assign province to a cell
|
||||||
cost[e] = totalCost;
|
cost[nextCellId] = totalCost;
|
||||||
queue.queue({e, p: totalCost});
|
queue.queue({e: nextCellId, p: totalCost});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -1318,7 +1327,7 @@ window.BurgsAndStates = (function () {
|
||||||
const f = pack.features[cells.f[center]];
|
const f = pack.features[cells.f[center]];
|
||||||
const color = getMixedColor(s.color);
|
const color = getMixedColor(s.color);
|
||||||
|
|
||||||
const provCells = stateNoProvince.filter(i => cells.province[i] === province);
|
const provCells = stateNoProvince.filter(i => provinceIds[i] === provinceId);
|
||||||
const singleIsle = provCells.length === f.cells && !provCells.find(i => cells.f[i] !== f.i);
|
const singleIsle = provCells.length === f.cells && !provCells.find(i => cells.f[i] !== f.i);
|
||||||
const isleGroup = !singleIsle && !provCells.find(i => pack.features[cells.f[i]].group !== "isle");
|
const isleGroup = !singleIsle && !provCells.find(i => pack.features[cells.f[i]].group !== "isle");
|
||||||
const colony = !singleIsle && !isleGroup && P(0.5) && !isPassable(s.center, center);
|
const colony = !singleIsle && !isleGroup && P(0.5) && !isPassable(s.center, center);
|
||||||
|
|
@ -1345,8 +1354,8 @@ window.BurgsAndStates = (function () {
|
||||||
const coa = COA.generate(s.coa, kinship, dominion, type);
|
const coa = COA.generate(s.coa, kinship, dominion, type);
|
||||||
coa.shield = COA.getShield(c, s.i);
|
coa.shield = COA.getShield(c, s.i);
|
||||||
|
|
||||||
provinces.push({i: province, state: s.i, center, burg, name, formName, fullName, color, coa});
|
provinces.push({i: provinceId, state: s.i, center, burg, name, formName, fullName, color, coa});
|
||||||
s.provinces.push(province);
|
s.provinces.push(provinceId);
|
||||||
|
|
||||||
// check if there is a land way within the same state between two cells
|
// check if there is a land way within the same state between two cells
|
||||||
function isPassable(from, to) {
|
function isPassable(from, to) {
|
||||||
|
|
@ -1367,10 +1376,11 @@ window.BurgsAndStates = (function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// re-check
|
// re-check
|
||||||
stateNoProvince = noProvince.filter(i => cells.state[i] === s.i && !cells.province[i]);
|
stateNoProvince = noProvince.filter(i => cells.state[i] === s.i && !provinceIds[i]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
cells.province = provinceIds;
|
||||||
pack.provinces = provinces;
|
pack.provinces = provinces;
|
||||||
|
|
||||||
TIME && console.timeEnd("generateProvinces");
|
TIME && console.timeEnd("generateProvinces");
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1132,6 +1132,7 @@ function drawBorders() {
|
||||||
const provToCell = cells.c[i].find(
|
const provToCell = cells.c[i].find(
|
||||||
n => cells.state[n] === s && p > cells.province[n] && pUsed[p][n] !== cells.province[n]
|
n => cells.state[n] === s && p > cells.province[n] && pUsed[p][n] !== cells.province[n]
|
||||||
);
|
);
|
||||||
|
|
||||||
if (provToCell) {
|
if (provToCell) {
|
||||||
const provTo = cells.province[provToCell];
|
const provTo = cells.province[provToCell];
|
||||||
pUsed[p][provToCell] = provTo;
|
pUsed[p][provToCell] = provTo;
|
||||||
|
|
|
||||||
|
|
@ -148,14 +148,14 @@ function regenerateStates() {
|
||||||
BurgsAndStates.generateDiplomacy();
|
BurgsAndStates.generateDiplomacy();
|
||||||
BurgsAndStates.defineStateForms();
|
BurgsAndStates.defineStateForms();
|
||||||
BurgsAndStates.generateProvinces(true);
|
BurgsAndStates.generateProvinces(true);
|
||||||
if (!layerIsOn("toggleStates")) toggleStates();
|
|
||||||
else drawStates();
|
layerIsOn("toggleStates") ? drawStates() : toggleStates();
|
||||||
if (!layerIsOn("toggleBorders")) toggleBorders();
|
layerIsOn("toggleBorders") ? drawBorders() : toggleBorders();
|
||||||
else drawBorders();
|
if (layerIsOn("toggleProvinces")) drawProvinces();
|
||||||
|
|
||||||
BurgsAndStates.drawStateLabels();
|
BurgsAndStates.drawStateLabels();
|
||||||
Military.generate();
|
Military.generate();
|
||||||
if (layerIsOn("toggleEmblems")) drawEmblems(); // redrawEmblems
|
if (layerIsOn("toggleEmblems")) drawEmblems();
|
||||||
|
|
||||||
if (document.getElementById("burgsOverviewRefresh")?.offsetParent) burgsOverviewRefresh.click();
|
if (document.getElementById("burgsOverviewRefresh")?.offsetParent) burgsOverviewRefresh.click();
|
||||||
if (document.getElementById("statesEditorRefresh")?.offsetParent) statesEditorRefresh.click();
|
if (document.getElementById("statesEditorRefresh")?.offsetParent) statesEditorRefresh.click();
|
||||||
|
|
@ -203,10 +203,11 @@ function recreateStates() {
|
||||||
byId(`stateCOA${state.i}`)?.remove();
|
byId(`stateCOA${state.i}`)?.remove();
|
||||||
document.querySelector(`#stateEmblems > use[data-i="${state.i}"]`)?.remove();
|
document.querySelector(`#stateEmblems > use[data-i="${state.i}"]`)?.remove();
|
||||||
|
|
||||||
// remove province emblems
|
// remove province data and emblems
|
||||||
for (const provinceId of state.provinces) {
|
for (const provinceId of state.provinces) {
|
||||||
byId(`provinceCOA${provinceId}`)?.remove();
|
byId(`provinceCOA${provinceId}`)?.remove();
|
||||||
document.querySelector(`#provinceEmblems > use[data-i="${provinceId}"]`)?.remove();
|
document.querySelector(`#provinceEmblems > use[data-i="${provinceId}"]`)?.remove();
|
||||||
|
pack.provinces[provinceId].removed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -246,9 +247,9 @@ function recreateStates() {
|
||||||
byId(`stateCOA${state.i}`)?.setAttribute("id", `stateCOA${newId}`);
|
byId(`stateCOA${state.i}`)?.setAttribute("id", `stateCOA${newId}`);
|
||||||
document.querySelector(`#stateEmblems > use[data-i="${state.i}"]`)?.setAttribute("data-i", newId);
|
document.querySelector(`#stateEmblems > use[data-i="${state.i}"]`)?.setAttribute("data-i", newId);
|
||||||
|
|
||||||
state.provinces.forEach(id => {
|
state.provinces.forEach(provinceId => {
|
||||||
if (!pack.provinces[id] || !pack.provinces[id].removed) return;
|
if (!pack.provinces[provinceId]) return;
|
||||||
pack.provinces[id].state = newId;
|
pack.provinces[provinceId].state = newId;
|
||||||
});
|
});
|
||||||
|
|
||||||
state.i = newId;
|
state.i = newId;
|
||||||
|
|
@ -260,8 +261,6 @@ function recreateStates() {
|
||||||
const lockedStateIndex = lockedStatesIds.indexOf(stateId) + 1;
|
const lockedStateIndex = lockedStatesIds.indexOf(stateId) + 1;
|
||||||
// lockedStateIndex is an index of locked state or 0 if state is not locked
|
// lockedStateIndex is an index of locked state or 0 if state is not locked
|
||||||
pack.cells.state[i] = lockedStateIndex;
|
pack.cells.state[i] = lockedStateIndex;
|
||||||
|
|
||||||
// TODO: update province id reference
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = newStates.length; i < count; i++) {
|
for (let i = newStates.length; i < count; i++) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue