diff --git a/index.html b/index.html
index 6deb8c38..01717609 100644
--- a/index.html
+++ b/index.html
@@ -7801,7 +7801,7 @@
-
+
diff --git a/modules/burgs-and-states.js b/modules/burgs-and-states.js
index 10a71148..e9f942e5 100644
--- a/modules/burgs-and-states.js
+++ b/modules/burgs-and-states.js
@@ -99,7 +99,17 @@ window.BurgsAndStates = (function () {
const coa = COA.generate(null, null, null, type);
coa.shield = COA.getShield(b.culture, null);
- states.push({i, color: colors[i - 1], name, expansionism, capital: i, type, center: b.cell, culture: b.culture, coa});
+ states.push({
+ i,
+ color: colors[i - 1],
+ name,
+ expansionism,
+ capital: i,
+ type,
+ center: b.cell,
+ culture: b.culture,
+ coa
+ });
cells.burg[b.cell] = i;
});
@@ -111,9 +121,14 @@ window.BurgsAndStates = (function () {
function placeTowns() {
TIME && console.time("placeTowns");
const score = new Int16Array(cells.s.map(s => s * gauss(1, 3, 0, 20, 3))); // a bit randomized cell score for towns placement
- const sorted = cells.i.filter(i => !cells.burg[i] && score[i] > 0 && cells.culture[i]).sort((a, b) => score[b] - score[a]); // filtered and sorted array of indexes
+ const sorted = cells.i
+ .filter(i => !cells.burg[i] && score[i] > 0 && cells.culture[i])
+ .sort((a, b) => score[b] - score[a]); // filtered and sorted array of indexes
- const desiredNumber = manorsInput.value == 1000 ? rn(sorted.length / 5 / (grid.points.length / 10000) ** 0.8) : manorsInput.valueAsNumber;
+ const desiredNumber =
+ manorsInput.value == 1000
+ ? rn(sorted.length / 5 / (grid.points.length / 10000) ** 0.8)
+ : manorsInput.valueAsNumber;
const burgsNumber = Math.min(desiredNumber, sorted.length); // towns to generate
let burgsAdded = 0;
@@ -529,8 +544,20 @@ window.BurgsAndStates = (function () {
const pointsInside = d3.range(c.p.length).filter(i => inside[i]);
if (!pointsInside.length) return [0];
const h = c.p.length < 200 ? 0 : c.p.length < 600 ? 0.5 : 1; // power of horyzontality shift
- const end = pointsInside[d3.scan(pointsInside, (a, b) => c.p[a][0] - c.p[b][0] + (Math.abs(c.p[a][1] - y) - Math.abs(c.p[b][1] - y)) * h)]; // left point
- const start = pointsInside[d3.scan(pointsInside, (a, b) => c.p[b][0] - c.p[a][0] - (Math.abs(c.p[b][1] - y) - Math.abs(c.p[a][1] - y)) * h)]; // right point
+ const end =
+ pointsInside[
+ d3.scan(
+ pointsInside,
+ (a, b) => c.p[a][0] - c.p[b][0] + (Math.abs(c.p[a][1] - y) - Math.abs(c.p[b][1] - y)) * h
+ )
+ ]; // left point
+ const start =
+ pointsInside[
+ d3.scan(
+ pointsInside,
+ (a, b) => c.p[b][0] - c.p[a][0] - (Math.abs(c.p[b][1] - y) - Math.abs(c.p[a][1] - y)) * h
+ )
+ ]; // right point
// connect leftmost and rightmost points with shortest path
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
@@ -696,7 +723,9 @@ window.BurgsAndStates = (function () {
const s = cells.state[i];
// check for neighboring states
- cells.c[i].filter(c => cells.h[c] >= 20 && cells.state[c] !== s).forEach(c => states[s].neighbors.add(cells.state[c]));
+ cells.c[i]
+ .filter(c => cells.h[c] >= 20 && cells.state[c] !== s)
+ .forEach(c => states[s].neighbors.add(cells.state[c]));
// collect stats
states[s].cells += 1;
@@ -742,7 +771,17 @@ window.BurgsAndStates = (function () {
TIME && console.timeEnd("assignColors");
};
- const wars = {War: 6, Conflict: 2, Campaign: 4, Invasion: 2, Rebellion: 2, Conquest: 2, Intervention: 1, Expedition: 1, Crusade: 1};
+ const wars = {
+ War: 6,
+ Conflict: 2,
+ Campaign: 4,
+ Invasion: 2,
+ Rebellion: 2,
+ Conquest: 2,
+ Intervention: 1,
+ Expedition: 1,
+ Crusade: 1
+ };
const generateCampaign = state => {
const neighbors = state.neighbors.length ? state.neighbors : [0];
return neighbors
@@ -810,7 +849,10 @@ window.BurgsAndStates = (function () {
continue;
}
- const naval = states[f].type === "Naval" && states[t].type === "Naval" && cells.f[states[f].center] !== cells.f[states[t].center];
+ const naval =
+ states[f].type === "Naval" &&
+ states[t].type === "Naval" &&
+ cells.f[states[f].center] !== cells.f[states[t].center];
const neib = naval ? false : states[f].neighbors.includes(t);
const neibOfNeib =
naval || neib
@@ -823,7 +865,14 @@ window.BurgsAndStates = (function () {
let status = naval ? rw(navals) : neib ? rw(neibs) : neibOfNeib ? rw(neibsOfNeibs) : rw(far);
// add Vassal
- if (neib && P(0.8) && states[f].area > areaMean && states[t].area < areaMean && states[f].area / states[t].area > 2) status = "Vassal";
+ if (
+ neib &&
+ P(0.8) &&
+ states[f].area > areaMean &&
+ states[t].area < areaMean &&
+ states[f].area / states[t].area > 2
+ )
+ status = "Vassal";
states[f].diplomacy[t] = status === "Vassal" ? "Suzerain" : status;
states[t].diplomacy[f] = status;
}
@@ -838,7 +887,9 @@ window.BurgsAndStates = (function () {
if (ad.includes("Enemy")) continue; // already at war
// random independent rival
- const defender = ra(ad.map((r, d) => (r === "Rival" && !states[d].diplomacy.includes("Vassal") ? d : 0)).filter(d => d));
+ const defender = ra(
+ ad.map((r, d) => (r === "Rival" && !states[d].diplomacy.includes("Vassal") ? d : 0)).filter(d => d)
+ );
let ap = states[attacker].area * states[attacker].expansionism,
dp = states[defender].area * states[defender].expansionism;
if (ap < dp * gauss(1.6, 0.8, 0, 10, 2)) continue; // defender is too strong
@@ -965,7 +1016,16 @@ window.BurgsAndStates = (function () {
Diarchy: 1,
Junta: 1
}; // weighted random
- const union = {Union: 3, League: 4, Confederation: 1, "United Kingdom": 1, "United Republic": 1, "United Provinces": 2, Commonwealth: 1, Heptarchy: 1}; // weighted random
+ const union = {
+ Union: 3,
+ League: 4,
+ Confederation: 1,
+ "United Kingdom": 1,
+ "United Republic": 1,
+ "United Provinces": 2,
+ Commonwealth: 1,
+ Heptarchy: 1
+ }; // weighted random
const theocracy = {Theocracy: 20, Brotherhood: 1, Thearchy: 2, See: 1, "Holy State": 1};
const anarchy = {"Free Territory": 2, Council: 3, Commune: 1, Community: 1};
@@ -975,7 +1035,8 @@ window.BurgsAndStates = (function () {
const religion = pack.cells.religion[s.center];
const isTheocracy =
- (religion && pack.religions[religion].expansion === "state") || (P(0.1) && ["Organized", "Cult"].includes(pack.religions[religion].type));
+ (religion && pack.religions[religion].expansion === "state") ||
+ (P(0.1) && ["Organized", "Cult"].includes(pack.religions[religion].type));
const isAnarchy = P(0.01 - tier / 500);
if (isTheocracy) s.form = "Theocracy";
@@ -992,7 +1053,13 @@ window.BurgsAndStates = (function () {
const form = monarchy[tier];
// Default name depends on exponent tier, some culture bases have special names for tiers
if (s.diplomacy) {
- if (form === "Duchy" && s.neighbors.length > 1 && rand(6) < s.neighbors.length && s.diplomacy.includes("Vassal")) return "Marches"; // some vassal duchies on borderland
+ if (
+ form === "Duchy" &&
+ s.neighbors.length > 1 &&
+ rand(6) < s.neighbors.length &&
+ s.diplomacy.includes("Vassal")
+ )
+ return "Marches"; // some vassal duchies on borderland
if (base === 1 && P(0.3) && s.diplomacy.includes("Vassal")) return "Dominion"; // English vassals
if (P(0.3) && s.diplomacy.includes("Vassal")) return "Protectorate"; // some vassals
}
@@ -1183,6 +1250,17 @@ window.BurgsAndStates = (function () {
const noProvince = Array.from(cells.i).filter(i => cells.state[i] && !cells.province[i]); // cells without province assigned
states.forEach(s => {
if (!s.provinces.length) return;
+
+ const coreProvinceNames = s.provinces.map(p => provinces[p]?.name);
+ const colonyNamePool = [s.name, ...coreProvinceNames].filter(name => name && !/new/i.test(name));
+ const getColonyName = () => {
+ if (colonyNamePool.length < 1) return null;
+
+ const index = rand(colonyNamePool.length - 1);
+ const spliced = colonyNamePool.splice(index, 1);
+ return spliced[0] ? `New ${spliced[0]}` : null;
+ };
+
let stateNoProvince = noProvince.filter(i => cells.state[i] === s.i && !cells.province[i]);
while (stateNoProvince.length) {
// add new province
@@ -1219,21 +1297,36 @@ window.BurgsAndStates = (function () {
// generate "wild" province name
const c = cells.culture[center];
- const nameByBurg = burgCell && P(0.5);
- const name = nameByBurg ? burgs[burg].name : Names.getState(Names.getCultureShort(c), c);
const f = pack.features[cells.f[center]];
+ const color = getMixedColor(s.color);
+
const provCells = stateNoProvince.filter(i => cells.province[i] === province);
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 colony = !singleIsle && !isleGroup && P(0.5) && !isPassable(s.center, center);
- const formName = singleIsle ? "Island" : isleGroup ? "Islands" : colony ? "Colony" : rw(forms["Wild"]);
+
+ const name = (function () {
+ const colonyName = colony && P(0.8) && getColonyName();
+ if (colonyName) return colonyName;
+ if (burgCell && P(0.5)) return burgs[burg].name;
+ return Names.getState(Names.getCultureShort(c), c);
+ })();
+
+ const formName = (function () {
+ if (singleIsle) return "Island";
+ if (isleGroup) return "Islands";
+ if (colony) return "Colony";
+ return rw(forms["Wild"]);
+ })();
+
const fullName = name + " " + formName;
- const color = getMixedColor(s.color);
+
const dominion = colony ? P(0.95) : singleIsle || isleGroup ? P(0.7) : P(0.3);
const kinship = dominion ? 0 : 0.4;
const type = getType(center, burgs[burg]?.port);
const coa = COA.generate(s.coa, kinship, dominion, type);
coa.shield = COA.getShield(c, s.i);
+
provinces.push({i: province, state: s.i, center, burg, name, formName, fullName, color, coa});
s.provinces.push(province);
diff --git a/versioning.js b/versioning.js
index a7af0975..bf19a4e5 100644
--- a/versioning.js
+++ b/versioning.js
@@ -1,7 +1,7 @@
"use strict";
-// version and caching control
-const version = "1.87.03"; // generator version, update each time
+// version and caching control
+const version = "1.87.04"; // generator version, update each time
{
document.title += " v" + version;