mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-19 18:41:23 +01:00
feat: zones - generation fixes
This commit is contained in:
parent
fdf0d163a8
commit
c17be58efe
4 changed files with 116 additions and 105 deletions
|
|
@ -611,8 +611,7 @@ window.BurgsAndStates = (() => {
|
||||||
// generate Diplomatic Relationships
|
// generate Diplomatic Relationships
|
||||||
const generateDiplomacy = () => {
|
const generateDiplomacy = () => {
|
||||||
TIME && console.time("generateDiplomacy");
|
TIME && console.time("generateDiplomacy");
|
||||||
const cells = pack.cells,
|
const {cells, states} = pack;
|
||||||
states = pack.states;
|
|
||||||
const chronicle = (states[0].diplomacy = []);
|
const chronicle = (states[0].diplomacy = []);
|
||||||
const valid = states.filter(s => s.i && !states.removed);
|
const valid = states.filter(s => s.i && !states.removed);
|
||||||
|
|
||||||
|
|
@ -696,21 +695,23 @@ window.BurgsAndStates = (() => {
|
||||||
const defender = ra(
|
const defender = ra(
|
||||||
ad.map((r, d) => (r === "Rival" && !states[d].diplomacy.includes("Vassal") ? d : 0)).filter(d => d)
|
ad.map((r, d) => (r === "Rival" && !states[d].diplomacy.includes("Vassal") ? d : 0)).filter(d => d)
|
||||||
);
|
);
|
||||||
let ap = states[attacker].area * states[attacker].expansionism,
|
let ap = states[attacker].area * states[attacker].expansionism;
|
||||||
dp = states[defender].area * states[defender].expansionism;
|
let dp = states[defender].area * states[defender].expansionism;
|
||||||
if (ap < dp * gauss(1.6, 0.8, 0, 10, 2)) continue; // defender is too strong
|
if (ap < dp * gauss(1.6, 0.8, 0, 10, 2)) continue; // defender is too strong
|
||||||
const an = states[attacker].name,
|
|
||||||
dn = states[defender].name; // names
|
const an = states[attacker].name;
|
||||||
const attackers = [attacker],
|
const dn = states[defender].name; // names
|
||||||
defenders = [defender]; // attackers and defenders array
|
const attackers = [attacker];
|
||||||
|
const defenders = [defender]; // attackers and defenders array
|
||||||
const dd = states[defender].diplomacy; // defender relations;
|
const dd = states[defender].diplomacy; // defender relations;
|
||||||
|
|
||||||
// start a war
|
// start an ongoing war
|
||||||
const war = [`${an}-${trimVowels(dn)}ian War`, `${an} declared a war on its rival ${dn}`];
|
const name = `${an}-${trimVowels(dn)}ian War`;
|
||||||
const end = options.year;
|
const start = options.year - gauss(2, 3, 0, 10);
|
||||||
const start = end - gauss(2, 2, 0, 5);
|
const war = [name, `${an} declared a war on its rival ${dn}`];
|
||||||
states[attacker].campaigns.push({name: `${trimVowels(dn)}ian War`, start, end});
|
const campaign = {name, start, attacker, defender};
|
||||||
states[defender].campaigns.push({name: `${trimVowels(an)}ian War`, start, end});
|
states[attacker].campaigns.push(campaign);
|
||||||
|
states[defender].campaigns.push(campaign);
|
||||||
|
|
||||||
// attacker vassals join the war
|
// attacker vassals join the war
|
||||||
ad.forEach((r, d) => {
|
ad.forEach((r, d) => {
|
||||||
|
|
@ -790,7 +791,6 @@ window.BurgsAndStates = (() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
TIME && console.timeEnd("generateDiplomacy");
|
TIME && console.timeEnd("generateDiplomacy");
|
||||||
//console.table(states.map(s => s.diplomacy));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// select a forms for listed or all valid states
|
// select a forms for listed or all valid states
|
||||||
|
|
|
||||||
|
|
@ -503,7 +503,9 @@ window.Military = (function () {
|
||||||
: "";
|
: "";
|
||||||
|
|
||||||
const campaign = s.campaigns ? ra(s.campaigns) : null;
|
const campaign = s.campaigns ? ra(s.campaigns) : null;
|
||||||
const year = campaign ? rand(campaign.start, campaign.end) : gauss(options.year - 100, 150, 1, options.year - 6);
|
const year = campaign
|
||||||
|
? rand(campaign.start, campaign.end || options.year)
|
||||||
|
: gauss(options.year - 100, 150, 1, options.year - 6);
|
||||||
const conflict = campaign ? ` during the ${campaign.name}` : "";
|
const conflict = campaign ? ` during the ${campaign.name}` : "";
|
||||||
const legend = `Regiment was formed in ${year} ${options.era}${conflict}. ${station}${troops}`;
|
const legend = `Regiment was formed in ${year} ${options.era}${conflict}. ${station}${troops}`;
|
||||||
notes.push({id: `regiment${s.i}-${r.i}`, name: `${r.icon} ${r.name}`, legend});
|
notes.push({id: `regiment${s.i}-${r.i}`, name: `${r.icon} ${r.name}`, legend});
|
||||||
|
|
|
||||||
|
|
@ -233,6 +233,7 @@ function editZones() {
|
||||||
|
|
||||||
const zoneId = +body.querySelector("div.selected")?.dataset.id;
|
const zoneId = +body.querySelector("div.selected")?.dataset.id;
|
||||||
const zone = pack.zones.find(z => z.i === zoneId);
|
const zone = pack.zones.find(z => z.i === zoneId);
|
||||||
|
if (!zone) return;
|
||||||
|
|
||||||
if (eraseMode) {
|
if (eraseMode) {
|
||||||
const data = zones
|
const data = zones
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,14 @@
|
||||||
|
|
||||||
window.Zones = (function () {
|
window.Zones = (function () {
|
||||||
const config = {
|
const config = {
|
||||||
invasion: {quantity: 1.8, generate: addInvasion}, // invasion of enemy lands
|
invasion: {quantity: 2, generate: addInvasion}, // invasion of enemy lands
|
||||||
rebels: {quantity: 1.6, generate: addRebels}, // rebels along a state border
|
rebels: {quantity: 1.5, generate: addRebels}, // rebels along a state border
|
||||||
proselytism: {quantity: 1.6, generate: addProselytism}, // proselitism of organized religion
|
proselytism: {quantity: 1.6, generate: addProselytism}, // proselitism of organized religion
|
||||||
crusade: {quantity: 1.6, generate: addCrusade}, // crusade on heresy lands
|
crusade: {quantity: 1.6, generate: addCrusade}, // crusade on heresy lands
|
||||||
disease: {quantity: 1.8, generate: addDisease}, // disease starting in a random city
|
disease: {quantity: 1.8, generate: addDisease}, // disease starting in a random city
|
||||||
disaster: {quantity: 1.2, generate: addDisaster}, // disaster starting in a random city
|
disaster: {quantity: 1.2, generate: addDisaster}, // disaster starting in a random city
|
||||||
eruption: {quantity: 1.4, generate: addEruption}, // volcanic eruption aroung volcano
|
eruption: {quantity: 1.2, generate: addEruption}, // volcanic eruption aroung volcano
|
||||||
avalanche: {quantity: 1.0, generate: addAvalanche}, // avalanche impacting highland road
|
avalanche: {quantity: 0.8, generate: addAvalanche}, // avalanche impacting highland road
|
||||||
fault: {quantity: 1.4, generate: addFault}, // fault line in elevated areas
|
fault: {quantity: 1.4, generate: addFault}, // fault line in elevated areas
|
||||||
flood: {quantity: 1.4, generate: addFlood}, // flood on river banks
|
flood: {quantity: 1.4, generate: addFlood}, // flood on river banks
|
||||||
tsunami: {quantity: 1.2, generate: addTsunami} // tsunami starting near coast
|
tsunami: {quantity: 1.2, generate: addTsunami} // tsunami starting near coast
|
||||||
|
|
@ -21,152 +21,160 @@ window.Zones = (function () {
|
||||||
const usedCells = new Uint8Array(pack.cells.i.length);
|
const usedCells = new Uint8Array(pack.cells.i.length);
|
||||||
pack.zones = [];
|
pack.zones = [];
|
||||||
|
|
||||||
Object.values(config).forEach(type => {
|
Object.entries(config).forEach(([name, type]) => {
|
||||||
const count = rn(Math.random() * type.quantity * globalModifier);
|
const expectedNumber = type.quantity * globalModifier;
|
||||||
for (let i = 0; i < count; i++) {
|
let number = gauss(expectedNumber, expectedNumber / 2, 0, 100);
|
||||||
type.generate(usedCells);
|
console.log(name, number);
|
||||||
}
|
while (number--) type.generate(usedCells);
|
||||||
});
|
});
|
||||||
|
|
||||||
TIME && console.timeEnd("generateZones");
|
TIME && console.timeEnd("generateZones");
|
||||||
};
|
};
|
||||||
|
|
||||||
function addInvasion(usedCells) {
|
function addInvasion(usedCells) {
|
||||||
const atWar = pack.states.filter(s => s.diplomacy && s.diplomacy.some(d => d === "Enemy"));
|
const {cells, states} = pack;
|
||||||
if (!atWar.length) return;
|
|
||||||
|
|
||||||
const invader = ra(atWar);
|
const ongoingConflicts = states
|
||||||
const target = invader.diplomacy.find(d => d === "Enemy");
|
.filter(s => s.i && !s.removed && s.campaigns)
|
||||||
|
.map(s => s.campaigns)
|
||||||
|
.flat()
|
||||||
|
.filter(c => !c.end);
|
||||||
|
if (!ongoingConflicts.length) return;
|
||||||
|
const {defender, attacker} = ra(ongoingConflicts);
|
||||||
|
|
||||||
const cells = pack.cells;
|
const borderCells = cells.i.filter(cellId => {
|
||||||
const cell = ra(
|
if (usedCells[cellId]) return false;
|
||||||
cells.i.filter(i => cells.state[i] === target.i && cells.c[i].some(c => cells.state[c] === invader.i))
|
if (cells.state[cellId] !== defender) return false;
|
||||||
);
|
return cells.c[cellId].some(c => cells.state[c] === attacker);
|
||||||
if (!cell) return;
|
});
|
||||||
|
|
||||||
const cellsArray = [],
|
const startCell = ra(borderCells);
|
||||||
queue = [cell],
|
if (startCell === undefined) return;
|
||||||
power = rand(5, 30);
|
|
||||||
|
const invationCells = [];
|
||||||
|
const queue = [startCell];
|
||||||
|
const maxCells = rand(5, 30);
|
||||||
|
|
||||||
while (queue.length) {
|
while (queue.length) {
|
||||||
const q = P(0.4) ? queue.shift() : queue.pop();
|
const cellId = P(0.4) ? queue.shift() : queue.pop();
|
||||||
cellsArray.push(q);
|
invationCells.push(cellId);
|
||||||
if (cellsArray.length > power) break;
|
if (invationCells.length >= maxCells) break;
|
||||||
|
|
||||||
cells.c[q].forEach(e => {
|
cells.c[cellId].forEach(neibCellId => {
|
||||||
if (usedCells[e]) return;
|
if (usedCells[neibCellId]) return;
|
||||||
if (cells.state[e] !== target.i) return;
|
if (cells.state[neibCellId] !== defender) return;
|
||||||
usedCells[e] = 1;
|
usedCells[neibCellId] = 1;
|
||||||
queue.push(e);
|
queue.push(neibCellId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const invasion = rw({
|
const subtype = rw({
|
||||||
Invasion: 4,
|
Invasion: 5,
|
||||||
Occupation: 3,
|
Occupation: 4,
|
||||||
Raid: 2,
|
Conquest: 3,
|
||||||
Conquest: 2,
|
Incursion: 2,
|
||||||
|
Intervention: 2,
|
||||||
Subjugation: 1,
|
Subjugation: 1,
|
||||||
Foray: 1,
|
Foray: 1,
|
||||||
Skirmishes: 1,
|
Skirmishes: 1,
|
||||||
Incursion: 2,
|
|
||||||
Pillaging: 1,
|
Pillaging: 1,
|
||||||
Intervention: 1
|
Raid: 1
|
||||||
});
|
});
|
||||||
const name = getAdjective(invader.name) + " " + invasion;
|
const name = getAdjective(states[attacker].name) + " " + subtype;
|
||||||
pack.zones.push({i: pack.zones.length, name, type: "Invasion", cells: cellsArray, color: "url(#hatch1)"});
|
|
||||||
|
pack.zones.push({i: pack.zones.length, name, type: "Invasion", cells: invationCells, color: "url(#hatch1)"});
|
||||||
}
|
}
|
||||||
|
|
||||||
function addRebels(usedCells) {
|
function addRebels(usedCells) {
|
||||||
const {cells, states} = pack;
|
const {cells, states} = pack;
|
||||||
|
|
||||||
const state = ra(states.filter(s => s.i && !s.removed && s.neighbors.some(Boolean)));
|
const state = ra(states.filter(s => s.i && !s.removed && s.neighbors.some(Boolean)));
|
||||||
if (!state) return;
|
if (!state) return;
|
||||||
|
|
||||||
const neib = ra(state.neighbors.filter(n => n && !states[n].removed));
|
const neibStateId = ra(state.neighbors.filter(n => n && !states[n].removed));
|
||||||
if (!neib) return;
|
if (!neibStateId) return;
|
||||||
|
|
||||||
const cell = cells.i.find(
|
|
||||||
i => cells.state[i] === state.i && !state.removed && cells.c[i].some(c => cells.state[c] === neib)
|
|
||||||
);
|
|
||||||
const cellsArray = [];
|
const cellsArray = [];
|
||||||
const queue = [];
|
const queue = [];
|
||||||
if (cell) queue.push(cell);
|
const borderCellId = cells.i.find(
|
||||||
|
i => cells.state[i] === state.i && cells.c[i].some(c => cells.state[c] === neibStateId)
|
||||||
const power = rand(10, 30);
|
);
|
||||||
|
if (borderCellId) queue.push(borderCellId);
|
||||||
|
const maxCells = rand(10, 30);
|
||||||
|
|
||||||
while (queue.length) {
|
while (queue.length) {
|
||||||
const q = queue.shift();
|
const cellId = queue.shift();
|
||||||
cellsArray.push(q);
|
cellsArray.push(cellId);
|
||||||
if (cellsArray.length > power) break;
|
if (cellsArray.length >= maxCells) break;
|
||||||
|
|
||||||
cells.c[q].forEach(e => {
|
cells.c[cellId].forEach(neibCellId => {
|
||||||
if (usedCells[e]) return;
|
if (usedCells[neibCellId]) return;
|
||||||
if (cells.state[e] !== state.i) return;
|
if (cells.state[neibCellId] !== state.i) return;
|
||||||
usedCells[e] = 1;
|
usedCells[neibCellId] = 1;
|
||||||
if (e % 4 !== 0 && !cells.c[e].some(c => cells.state[c] === neib)) return;
|
if (neibCellId % 4 !== 0 && !cells.c[neibCellId].some(c => cells.state[c] === neibStateId)) return;
|
||||||
queue.push(e);
|
queue.push(neibCellId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const rebels = rw({
|
const rebels = rw({
|
||||||
Rebels: 5,
|
Rebels: 5,
|
||||||
Insurgents: 2,
|
Insurrection: 2,
|
||||||
Mutineers: 1,
|
Mutineers: 1,
|
||||||
|
Insurgents: 1,
|
||||||
Rioters: 1,
|
Rioters: 1,
|
||||||
Separatists: 1,
|
Separatists: 1,
|
||||||
Secessionists: 1,
|
Secessionists: 1,
|
||||||
Insurrection: 2,
|
|
||||||
Rebellion: 1,
|
Rebellion: 1,
|
||||||
Conspiracy: 2
|
Conspiracy: 1
|
||||||
});
|
});
|
||||||
|
|
||||||
const name = getAdjective(states[neib].name) + " " + rebels;
|
const name = getAdjective(states[neibStateId].name) + " " + rebels;
|
||||||
pack.zones.push({i: pack.zones.length, name, type: "Rebels", cells: cellsArray, color: "url(#hatch3)"});
|
pack.zones.push({i: pack.zones.length, name, type: "Rebels", cells: cellsArray, color: "url(#hatch3)"});
|
||||||
}
|
}
|
||||||
|
|
||||||
function addProselytism(usedCells) {
|
function addProselytism(usedCells) {
|
||||||
const organized = ra(pack.religions.filter(r => r.type === "Organized"));
|
const {cells, religions} = pack;
|
||||||
if (!organized) return;
|
|
||||||
|
|
||||||
const cells = pack.cells;
|
const organizedReligions = religions.filter(r => r.i && !r.removed && r.type === "Organized");
|
||||||
const cell = ra(
|
const religion = ra(organizedReligions);
|
||||||
cells.i.filter(
|
if (!religion) return;
|
||||||
i =>
|
|
||||||
cells.religion[i] &&
|
const targetBorderCells = cells.i.filter(
|
||||||
cells.religion[i] !== organized.i &&
|
i => cells.religion[i] !== religion.i && cells.c[i].some(c => cells.religion[c] === religion.i)
|
||||||
cells.c[i].some(c => cells.religion[c] === organized.i)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
if (!cell) return;
|
const startCell = ra(targetBorderCells);
|
||||||
const target = cells.religion[cell];
|
if (!startCell) return;
|
||||||
const cellsArray = [],
|
|
||||||
queue = [cell],
|
const targetReligionId = cells.religion[startCell];
|
||||||
power = rand(10, 30);
|
const proselytismCells = [];
|
||||||
|
const queue = [startCell];
|
||||||
|
const maxCells = rand(10, 30);
|
||||||
|
|
||||||
while (queue.length) {
|
while (queue.length) {
|
||||||
const q = queue.shift();
|
const cellId = queue.shift();
|
||||||
cellsArray.push(q);
|
proselytismCells.push(cellId);
|
||||||
if (cellsArray.length > power) break;
|
if (proselytismCells.length >= maxCells) break;
|
||||||
|
|
||||||
cells.c[q].forEach(e => {
|
cells.c[cellId].forEach(neibCellId => {
|
||||||
if (usedCells[e]) return;
|
if (usedCells[neibCellId]) return;
|
||||||
if (cells.religion[e] !== target) return;
|
if (cells.religion[neibCellId] !== targetReligionId) return;
|
||||||
if (cells.h[e] < 20) return;
|
if (cells.h[neibCellId] < 20) return;
|
||||||
usedCells[e] = 1;
|
usedCells[neibCellId] = 1;
|
||||||
//if (e%2 !== 0 && !cells.c[e].some(c => cells.state[c] === neib)) return;
|
queue.push(neibCellId);
|
||||||
queue.push(e);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const name = getAdjective(organized.name.split(" ")[0]) + " Proselytism";
|
const name = getAdjective(religion.name.split(" ")[0]) + " Proselytism";
|
||||||
pack.zones.push({i: pack.zones.length, name, type: "Proselytism", cells: cellsArray, color: "url(#hatch6)"});
|
pack.zones.push({i: pack.zones.length, name, type: "Proselytism", cells: proselytismCells, color: "url(#hatch6)"});
|
||||||
}
|
}
|
||||||
|
|
||||||
function addCrusade(usedCells) {
|
function addCrusade(usedCells) {
|
||||||
const heresy = ra(pack.religions.filter(r => r.type === "Heresy"));
|
const {cells, religions} = pack;
|
||||||
if (!heresy) return;
|
|
||||||
|
|
||||||
const cells = pack.cells;
|
const heresies = religions.filter(r => !r.removed && r.type === "Heresy");
|
||||||
|
if (!heresies.length) return;
|
||||||
|
|
||||||
|
const heresy = ra(heresies);
|
||||||
const crusadeCells = cells.i.filter(i => !usedCells[i] && cells.religion[i] === heresy.i);
|
const crusadeCells = cells.i.filter(i => !usedCells[i] && cells.religion[i] === heresy.i);
|
||||||
if (!crusadeCells.length) return;
|
if (!crusadeCells.length) return;
|
||||||
crusadeCells.forEach(i => (usedCells[i] = 1));
|
crusadeCells.forEach(i => (usedCells[i] = 1));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue