diff --git a/main.js b/main.js
index e2ac094e..f2672a16 100644
--- a/main.js
+++ b/main.js
@@ -77,8 +77,6 @@ let prec = viewbox.append("g").attr("id", "prec").style("display", "none");
let population = viewbox.append("g").attr("id", "population");
let goods = viewbox.append('g').attr('id', 'goods');
let emblems = viewbox.append("g").attr("id", "emblems").style("display", "none");
-let goods = viewbox.append("g").attr("id", "goods");
-let emblems = viewbox.append("g").attr("id", "emblems").style("display", "none");
let labels = viewbox.append("g").attr("id", "labels");
let icons = viewbox.append("g").attr("id", "icons");
let burgIcons = icons.append("g").attr("id", "burgIcons");
@@ -1540,15 +1538,15 @@ function getBiomeId(moisture, temperature, height) {
return biomesData.biomesMartix[moistureBand][temperatureBand];
}
-// assess cells suitability to calculate population and rand cells for culture center and burgs placement
+// assess cells suitability to calculate population and rang cells for culture center and burgs placement
function rankCells() {
TIME && console.time('rankCells');
const {cells, features} = pack;
cells.s = new Int16Array(cells.i.length); // cell suitability array
cells.pop = new Float32Array(cells.i.length); // cell population array
- const flMean = d3.median(cells.fl.filter((f) => f)) || 0,
- flMax = d3.max(cells.fl) + d3.max(cells.conf); // to normalize flux
+ const flMean = d3.median(cells.fl.filter((f) => f)) || 0;
+ const flMax = d3.max(cells.fl) + d3.max(cells.conf); // to normalize flux
const areaMean = d3.mean(cells.area); // to adjust population by cell area
const getResValue = (i) => (cells.resource[i] ? Resources.get(cells.resource[i])?.value : 0); // get bonus resource scope
const POP_BALANCER = 1.5; // to ballance population to desired number
@@ -1556,24 +1554,24 @@ function rankCells() {
for (const i of cells.i) {
// if (cells.b[i]) continue; // avoid adding burgs on map border
if (cells.h[i] < 20) continue; // no population in water
- let s = +biomesData.habitability[cells.biome[i]]; // base suitability derived from biome habitability
+ let s = biomesData.habitability[cells.biome[i]] / 10; // base suitability derived from biome habitability
if (!s) continue; // uninhabitable biomes has 0 suitability
- if (flMean) s += normalize(cells.fl[i] + cells.conf[i], flMean, flMax) * 250; // big rivers and confluences are valued
- s -= (cells.h[i] - 50) / 5; // low elevation is valued, high is not;
+
+ if (flMean) s += normalize(cells.fl[i] + cells.conf[i], flMean, flMax) * 50; // big rivers and confluences are valued
+ s -= (cells.h[i] - 50) / 25; // low elevation is valued, high is not;
if (cells.t[i] === 1) {
- if (cells.r[i]) s += 15; // estuary is valued
- const feature = features[cells.f[cells.haven[i]]];
- if (feature.type === 'lake') {
- if (feature.group === 'freshwater') s += 30;
- else if (feature.group == 'salt') s += 10;
- else if (feature.group == 'frozen') s += 1;
- else if (feature.group == 'dry') s -= 5;
- else if (feature.group == 'sinkhole') s -= 5;
- else if (feature.group == 'lava') s -= 30;
+ if (cells.r[i]) s += 3; // estuary is valued
+ const {type, group} = features[cells.f[cells.haven[i]]];
+ if (type === 'lake') {
+ if (group === 'freshwater') s += 5;
+ else if (group == 'salt') s += 2;
+ else if (group == 'dry') s -= 1;
+ else if (group == 'sinkhole') s -= 1;
+ else if (group == 'lava') s -= 6;
} else {
- s += 5; // ocean coast is valued
- if (cells.harbor[i] === 1) s += 20; // safe sea harbor is valued
+ s += 1; // ocean coast is valued
+ if (cells.harbor[i] === 1) s += 4; // safe sea harbor is valued
}
}
@@ -1584,9 +1582,17 @@ function rankCells() {
const resBonus = (cellRes ? cellRes + 10 : 0) + neibRes;
// cell rural population is suitability adjusted by cell area
- cells.pop[i] = cells.s[i] > 0 ? (cells.s[i] * cells.area[i]) / areaMean : 0;
+ cells.pop[i] = s > 0 ? (s * POP_BALANCER * cells.area[i]) / areaMean : 0;
+ cells.s[i] = s + resBonus;
+
+ debug.append('text').attr('x', cells.p[i][0]).attr('y', cells.p[i][1]).text(cells.s[i]);
}
+ console.log(resBonuses);
+ console.log(d3.max(resBonuses));
+ console.log(d3.mean(resBonuses));
+ console.log(d3.median(resBonuses.map((v) => rn(v))));
+
TIME && console.timeEnd('rankCells');
}
diff --git a/modules/burgs-and-states.js b/modules/burgs-and-states.js
index bfa84e44..83810b0e 100644
--- a/modules/burgs-and-states.js
+++ b/modules/burgs-and-states.js
@@ -61,7 +61,7 @@ window.BurgsAndStates = (function () {
}
if (i === sorted.length - 1) {
- WARN && console.warn("Cannot place capitals with current spacing. Trying again with reduced spacing");
+ WARN && console.warn('Cannot place capitals with current spacing. Trying again with reduced spacing');
burgsTree = d3.quadtree();
i = -1;
burgs = [0];
@@ -221,10 +221,10 @@ window.BurgsAndStates = (function () {
}
// de-assign port status if it's the only one on feature
- const ports = pack.burgs.filter(b => !b.removed && b.port > 0);
+ const ports = pack.burgs.filter((b) => !b.removed && b.port > 0);
for (const f of features) {
if (!f.i || f.land || f.border) continue;
- const featurePorts = ports.filter(b => b.port === f.i);
+ const featurePorts = ports.filter((b) => b.port === f.i);
if (featurePorts.length === 1) featurePorts[0].port = 0;
}
@@ -233,14 +233,14 @@ window.BurgsAndStates = (function () {
const getType = function (i, port) {
const cells = pack.cells;
- if (port) return "Naval";
- if (cells.haven[i] && pack.features[cells.f[cells.haven[i]]].type === "lake") return "Lake";
- if (cells.h[i] > 60) return "Highland";
- if (cells.r[i] && cells.r[i].length > 100 && cells.r[i].length >= pack.rivers[0].length) return "River";
+ if (port) return 'Naval';
+ if (cells.haven[i] && pack.features[cells.f[cells.haven[i]]].type === 'lake') return 'Lake';
+ if (cells.h[i] > 60) return 'Highland';
+ if (cells.r[i] && cells.r[i].length > 100 && cells.r[i].length >= pack.rivers[0].length) return 'River';
if (!cells.burg[i] || pack.burgs[cells.burg[i]].population < 6) {
- if (population < 5 && [1, 2, 3, 4].includes(cells.biome[i])) return "Nomadic";
- if (cells.biome[i] > 4 && cells.biome[i] < 10) return "Hunting";
+ if (population < 5 && [1, 2, 3, 4].includes(cells.biome[i])) return 'Nomadic';
+ if (cells.biome[i] > 4 && cells.biome[i] < 10) return 'Hunting';
}
return "Generic";
@@ -266,9 +266,9 @@ window.BurgsAndStates = (function () {
TIME && console.time("drawBurgs");
// remove old data
- burgIcons.selectAll("circle").remove();
- burgLabels.selectAll("text").remove();
- icons.selectAll("use").remove();
+ burgIcons.selectAll('circle').remove();
+ burgLabels.selectAll('text').remove();
+ icons.selectAll('use').remove();
// capitals
const capitals = pack.burgs.filter(b => b.capital && !b.removed);
@@ -385,7 +385,7 @@ window.BurgsAndStates = (function () {
const {e, p, s, b} = next;
const {type, culture} = states[s];
- cells.c[e].forEach(e => {
+ cells.c[e].forEach((e) => {
if (cells.state[e] && e === states[cells.state[e]].center) return; // do not overwrite capital cells
const cultureCost = culture === cells.culture[e] ? -9 : 100;
@@ -411,33 +411,33 @@ window.BurgsAndStates = (function () {
function getBiomeCost(b, biome, type) {
if (b === biome) return 10; // tiny penalty for native biome
- if (type === "Hunting") return biomesData.cost[biome] * 2; // non-native biome penalty for hunters
- if (type === "Nomadic" && biome > 4 && biome < 10) return biomesData.cost[biome] * 3; // forest biome penalty for nomads
+ if (type === 'Hunting') return biomesData.cost[biome] * 2; // non-native biome penalty for hunters
+ if (type === 'Nomadic' && biome > 4 && biome < 10) return biomesData.cost[biome] * 3; // forest biome penalty for nomads
return biomesData.cost[biome]; // general non-native biome penalty
}
function getHeightCost(f, h, type) {
- if (type === "Lake" && f.type === "lake") return 10; // low lake crossing penalty for Lake cultures
- if (type === "Naval" && h < 20) return 300; // low sea crossing penalty for Navals
- if (type === "Nomadic" && h < 20) return 10000; // giant sea crossing penalty for Nomads
+ if (type === 'Lake' && f.type === 'lake') return 10; // low lake crossing penalty for Lake cultures
+ if (type === 'Naval' && h < 20) return 300; // low sea crossing penalty for Navals
+ if (type === 'Nomadic' && h < 20) return 10000; // giant sea crossing penalty for Nomads
if (h < 20) return 1000; // general sea crossing penalty
- if (type === "Highland" && h < 62) return 1100; // penalty for highlanders on lowlands
- if (type === "Highland") return 0; // no penalty for highlanders on highlands
+ if (type === 'Highland' && h < 62) return 1100; // penalty for highlanders on lowlands
+ if (type === 'Highland') return 0; // no penalty for highlanders on highlands
if (h >= 67) return 2200; // general mountains crossing penalty
if (h >= 44) return 300; // general hills crossing penalty
return 0;
}
function getRiverCost(r, i, type) {
- if (type === "River") return r ? 0 : 100; // penalty for river cultures
+ if (type === 'River') return r ? 0 : 100; // penalty for river cultures
if (!r) return 0; // no penalty for others if there is no river
return minmax(cells.fl[i] / 10, 20, 100); // river penalty from 20 to 100 based on flux
}
function getTypeCost(t, type) {
- if (t === 1) return type === "Naval" || type === "Lake" ? 0 : type === "Nomadic" ? 60 : 20; // penalty for coastline
- if (t === 2) return type === "Naval" || type === "Nomadic" ? 30 : 0; // low penalty for land level 2 for Navals and nomads
- if (t !== -1) return type === "Naval" || type === "Lake" ? 100 : 0; // penalty for mainland for navals
+ if (t === 1) return type === 'Naval' || type === 'Lake' ? 0 : type === 'Nomadic' ? 60 : 20; // penalty for coastline
+ if (t === 2) return type === 'Naval' || type === 'Nomadic' ? 30 : 0; // low penalty for land level 2 for Navals and nomads
+ if (t !== -1) return type === 'Naval' || type === 'Lake' ? 100 : 0; // penalty for mainland for navals
return 0;
}
@@ -451,11 +451,11 @@ window.BurgsAndStates = (function () {
for (const i of cells.i) {
if (cells.h[i] < 20 || cells.burg[i]) continue; // do not overwrite burgs
- if (cells.c[i].some(c => burgs[cells.burg[c]].capital)) continue; // do not overwrite near capital
- const neibs = cells.c[i].filter(c => cells.h[c] >= 20);
- const adversaries = neibs.filter(c => cells.state[c] !== cells.state[i]);
+ if (cells.c[i].some((c) => burgs[cells.burg[c]].capital)) continue; // do not overwrite near capital
+ const neibs = cells.c[i].filter((c) => cells.h[c] >= 20);
+ const adversaries = neibs.filter((c) => cells.state[c] !== cells.state[i]);
if (adversaries.length < 2) continue;
- const buddies = neibs.filter(c => cells.state[c] === cells.state[i]);
+ const buddies = neibs.filter((c) => cells.state[c] === cells.state[i]);
if (buddies.length > 2) continue;
if (adversaries.length <= buddies.length) continue;
cells.state[i] = cells.state[adversaries[0]];
@@ -503,7 +503,7 @@ window.BurgsAndStates = (function () {
const visualCenter = findCell(s.pole[0], s.pole[1]);
const start = cells.state[visualCenter] === s.i ? visualCenter : s.center;
const hull = getHull(start, s.i, s.cells / 10);
- const points = [...hull].map(v => pack.vertices.p[v]);
+ const points = [...hull].map((v) => pack.vertices.p[v]);
const delaunay = Delaunator.from(points);
const voronoi = new Voronoi(delaunay, points, points.length);
const chain = connectCenters(voronoi.vertices, s.pole[1]);
@@ -541,7 +541,7 @@ window.BurgsAndStates = (function () {
return used[findCell(p[0], p[1])];
});
- const pointsInside = d3.range(c.p.length).filter(i => inside[i]);
+ 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 =
@@ -600,14 +600,14 @@ window.BurgsAndStates = (function () {
if (!list) {
// remove all labels and textpaths
- g.selectAll("text").remove();
+ g.selectAll('text').remove();
t.selectAll("path[id*='stateLabel']").remove();
}
- const example = g.append("text").attr("x", 0).attr("x", 0).text("Average");
+ const example = g.append('text').attr('x', 0).attr('x', 0).text('Average');
const letterLength = example.node().getComputedTextLength() / 7; // average length of 1 letter
- paths.forEach(p => {
+ paths.forEach((p) => {
const id = p[0];
const state = states[p[0]];
const {name, fullName} = state;
@@ -738,7 +738,7 @@ window.BurgsAndStates = (function () {
}
// convert neighbors Set object into array
- states.forEach(s => {
+ states.forEach((s) => {
if (!s.neighbors) return;
s.neighbors = Array.from(s.neighbors);
});
@@ -754,14 +754,14 @@ window.BurgsAndStates = (function () {
pack.states.forEach(s => {
if (!s.i || s.removed) return;
const neibs = s.neighbors;
- s.color = colors.find(c => neibs.every(n => pack.states[n].color !== c));
+ s.color = colors.find((c) => neibs.every((n) => pack.states[n].color !== c));
if (!s.color) s.color = getRandomColor();
colors.push(colors.shift());
});
// randomize each already used color a bit
- colors.forEach(c => {
- const sameColored = pack.states.filter(s => s.color === c);
+ colors.forEach((c) => {
+ const sameColored = pack.states.filter((s) => s.color === c);
sameColored.forEach((s, d) => {
if (!d) return;
s.color = getMixedColor(s.color);
@@ -823,9 +823,9 @@ window.BurgsAndStates = (function () {
for (let f = 1; f < states.length; f++) {
if (states[f].removed) continue;
- if (states[f].diplomacy.includes("Vassal")) {
+ if (states[f].diplomacy.includes('Vassal')) {
// Vassals copy relations from their Suzerains
- const suzerain = states[f].diplomacy.indexOf("Vassal");
+ const suzerain = states[f].diplomacy.indexOf('Vassal');
for (let i = 1; i < states.length; i++) {
if (i === f || i === suzerain) continue;
@@ -833,7 +833,7 @@ window.BurgsAndStates = (function () {
if (states[suzerain].diplomacy[i] === "Suzerain") states[f].diplomacy[i] = "Ally";
for (let e = 1; e < states.length; e++) {
if (e === f || e === suzerain) continue;
- if (states[e].diplomacy[suzerain] === "Suzerain" || states[e].diplomacy[suzerain] === "Vassal") continue;
+ if (states[e].diplomacy[suzerain] === 'Suzerain' || states[e].diplomacy[suzerain] === 'Vassal') continue;
states[e].diplomacy[f] = states[e].diplomacy[suzerain];
}
}
@@ -843,8 +843,8 @@ window.BurgsAndStates = (function () {
for (let t = f + 1; t < states.length; t++) {
if (states[t].removed) continue;
- if (states[t].diplomacy.includes("Vassal")) {
- const suzerain = states[t].diplomacy.indexOf("Vassal");
+ if (states[t].diplomacy.includes('Vassal')) {
+ const suzerain = states[t].diplomacy.indexOf('Vassal');
states[f].diplomacy[t] = states[f].diplomacy[suzerain];
continue;
}
@@ -882,9 +882,9 @@ window.BurgsAndStates = (function () {
for (let attacker = 1; attacker < states.length; attacker++) {
const ad = states[attacker].diplomacy; // attacker relations;
if (states[attacker].removed) continue;
- if (!ad.includes("Rival")) continue; // no rivals to attack
- if (ad.includes("Vassal")) continue; // not independent
- if (ad.includes("Enemy")) continue; // already at war
+ if (!ad.includes('Rival')) continue; // no rivals to attack
+ if (ad.includes('Vassal')) continue; // not independent
+ if (ad.includes('Enemy')) continue; // already at war
// random independent rival
const defender = ra(
@@ -922,8 +922,8 @@ window.BurgsAndStates = (function () {
}
});
- ap = d3.sum(attackers.map(a => states[a].area * states[a].expansionism)); // attackers joined power
- dp = d3.sum(defenders.map(d => states[d].area * states[d].expansionism)); // defender joined power
+ ap = d3.sum(attackers.map((a) => states[a].area * states[a].expansionism)); // attackers joined power
+ dp = d3.sum(defenders.map((d) => states[d].area * states[d].expansionism)); // defender joined power
// defender allies join
dd.forEach((r, d) => {
@@ -931,7 +931,7 @@ window.BurgsAndStates = (function () {
if (states[d].diplomacy[attacker] !== "Rival" && ap / dp > 2 * gauss(1.6, 0.8, 0, 10, 2)) {
const reason = states[d].diplomacy.includes("Enemy") ? "Being already at war," : `Frightened by ${an},`;
war.push(`${reason} ${states[d].name} severed the defense pact with ${dn}`);
- dd[d] = states[d].diplomacy[defender] = "Suspicion";
+ dd[d] = states[d].diplomacy[defender] = 'Suspicion';
return;
}
defenders.push(d);
@@ -951,7 +951,7 @@ window.BurgsAndStates = (function () {
// attacker allies join if the defender is their rival or joined power > defenders power and defender is not an ally
ad.forEach((r, d) => {
- if (r !== "Ally" || states[d].diplomacy.includes("Vassal") || defenders.includes(d)) return;
+ if (r !== 'Ally' || states[d].diplomacy.includes('Vassal') || defenders.includes(d)) return;
const name = states[d].name;
if (states[d].diplomacy[defender] !== "Rival" && (P(0.2) || ap <= dp * 1.2)) {
war.push(`${an}'s ally ${name} avoided entering the war`);
@@ -983,7 +983,7 @@ window.BurgsAndStates = (function () {
chronicle.push(war); // add a record to diplomatical history
}
- TIME && console.timeEnd("generateDiplomacy");
+ TIME && console.timeEnd('generateDiplomacy');
//console.table(states.map(s => s.diplomacy));
};
@@ -1064,33 +1064,33 @@ window.BurgsAndStates = (function () {
if (P(0.3) && s.diplomacy.includes("Vassal")) return "Protectorate"; // some vassals
}
- if (base === 16 && (form === "Empire" || form === "Kingdom")) return "Sultanate"; // Turkic
- if (base === 5 && (form === "Empire" || form === "Kingdom")) return "Tsardom"; // Ruthenian
- if ([16, 31].includes(base) && (form === "Empire" || form === "Kingdom")) return "Khaganate"; // Turkic, Mongolian
- if (base === 12 && (form === "Kingdom" || form === "Grand Duchy")) return "Shogunate"; // Japanese
- if ([18, 17].includes(base) && form === "Empire") return "Caliphate"; // Arabic, Berber
- if (base === 18 && (form === "Grand Duchy" || form === "Duchy")) return "Emirate"; // Arabic
- if (base === 7 && (form === "Grand Duchy" || form === "Duchy")) return "Despotate"; // Greek
- if (base === 31 && (form === "Grand Duchy" || form === "Duchy")) return "Ulus"; // Mongolian
- if (base === 16 && (form === "Grand Duchy" || form === "Duchy")) return "Horde"; // Turkic
- if (base === 24 && (form === "Grand Duchy" || form === "Duchy")) return "Satrapy"; // Iranian
+ if (base === 16 && (form === 'Empire' || form === 'Kingdom')) return 'Sultanate'; // Turkic
+ if (base === 5 && (form === 'Empire' || form === 'Kingdom')) return 'Tsardom'; // Ruthenian
+ if ([16, 31].includes(base) && (form === 'Empire' || form === 'Kingdom')) return 'Khaganate'; // Turkic, Mongolian
+ if (base === 12 && (form === 'Kingdom' || form === 'Grand Duchy')) return 'Shogunate'; // Japanese
+ if ([18, 17].includes(base) && form === 'Empire') return 'Caliphate'; // Arabic, Berber
+ if (base === 18 && (form === 'Grand Duchy' || form === 'Duchy')) return 'Emirate'; // Arabic
+ if (base === 7 && (form === 'Grand Duchy' || form === 'Duchy')) return 'Despotate'; // Greek
+ if (base === 31 && (form === 'Grand Duchy' || form === 'Duchy')) return 'Ulus'; // Mongolian
+ if (base === 16 && (form === 'Grand Duchy' || form === 'Duchy')) return 'Horde'; // Turkic
+ if (base === 24 && (form === 'Grand Duchy' || form === 'Duchy')) return 'Satrapy'; // Iranian
return form;
}
- if (s.form === "Republic") {
+ if (s.form === 'Republic') {
// Default name is from weighted array, special case for small states with only 1 burg
if (tier < 2 && s.burgs === 1) {
if (trimVowels(s.name) === trimVowels(pack.burgs[s.capital].name)) {
s.name = pack.burgs[s.capital].name;
- return "Free City";
+ return 'Free City';
}
if (P(0.3)) return "City-state";
}
return rw(republic);
}
- if (s.form === "Union") return rw(union);
- if (s.form === "Anarchy") return rw(anarchy);
+ if (s.form === 'Union') return rw(union);
+ if (s.form === 'Anarchy') return rw(anarchy);
if (s.form === "Theocracy") {
// European
@@ -1213,7 +1213,7 @@ window.BurgsAndStates = (function () {
const name = nameByBurg ? stateBurgs[i].name : Names.getState(Names.getCultureShort(c), c);
const formName = rw(form);
form[formName] += 10;
- const fullName = name + " " + formName;
+ const fullName = name + ' ' + formName;
const color = getMixedColor(s.color);
const kinship = nameByBurg ? 0.8 : 0.4;
const type = getType(center, burg.port);
@@ -1258,10 +1258,10 @@ window.BurgsAndStates = (function () {
// justify provinces shapes a bit
for (const i of cells.i) {
if (cells.burg[i]) continue; // do not overwrite burgs
- const neibs = cells.c[i].filter(c => cells.state[c] === cells.state[i]).map(c => cells.province[c]);
- const adversaries = neibs.filter(c => c !== cells.province[i]);
+ const neibs = cells.c[i].filter((c) => cells.state[c] === cells.state[i]).map((c) => cells.province[c]);
+ const adversaries = neibs.filter((c) => c !== cells.province[i]);
if (adversaries.length < 2) continue;
- const buddies = neibs.filter(c => c === cells.province[i]).length;
+ const buddies = neibs.filter((c) => c === cells.province[i]).length;
if (buddies.length > 2) continue;
const competitors = adversaries.map(p => adversaries.reduce((s, v) => (v === p ? s + 1 : s), 0));
const max = d3.max(competitors);
@@ -1270,8 +1270,8 @@ window.BurgsAndStates = (function () {
}
// 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
- states.forEach(s => {
+ 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);
@@ -1288,7 +1288,7 @@ window.BurgsAndStates = (function () {
while (stateNoProvince.length) {
// add new province
const province = 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 burg = burgCell ? cells.burg[burgCell] : 0;
cells.province[center] = province;
@@ -1349,7 +1349,6 @@ window.BurgsAndStates = (function () {
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);
@@ -1362,7 +1361,7 @@ window.BurgsAndStates = (function () {
while (queue.length) {
const current = queue.pop();
if (current === to) return true; // way is found
- cells.c[current].forEach(c => {
+ cells.c[current].forEach((c) => {
if (used[c] || cells.h[c] < 20 || cells.state[c] !== state) return;
queue.push(c);
used[c] = 1;
@@ -1372,7 +1371,7 @@ window.BurgsAndStates = (function () {
}
// re-check
- stateNoProvince = noProvince.filter(i => cells.state[i] === s.i && !cells.province[i]);
+ stateNoProvince = noProvince.filter((i) => cells.state[i] === s.i && !cells.province[i]);
}
});
diff --git a/modules/resources-generator.js b/modules/resources-generator.js
index 162922bc..138f3be0 100644
--- a/modules/resources-generator.js
+++ b/modules/resources-generator.js
@@ -529,9 +529,6 @@ window.Resources = (function () {
const temp = i => grid.cells.temp[pack.cells.g[i]];
const group = i => pack.features[cells.f[i]].group;
- const temp = i => grid.cells.temp[pack.cells.g[i]];
- const group = i => pack.features[cells.f[i]].group;
-
const models = {
forest: i => [6, 7, 8].includes(cells.biome[i]),
forestAndTaiga: i => [5, 6, 7, 8, 9].includes(cells.biome[i]),
diff --git a/modules/ui/layers.js b/modules/ui/layers.js
index 70132e5b..0e49127a 100644
--- a/modules/ui/layers.js
+++ b/modules/ui/layers.js
@@ -1951,11 +1951,17 @@ function drawResources() {
const [x, y] = pack.cells.p[i];
const stroke = Resources.getStroke(resource.color);
+ if (!drawCircle) {
+ resourcesHTML += ``;
+ continue;
+ }
+
resourcesHTML += `
`;
}
+
goods.html(resourcesHTML);
console.timeEnd('drawResources');
}
diff --git a/modules/ui/style.js b/modules/ui/style.js
index ff2dc690..fd94c8f0 100644
--- a/modules/ui/style.js
+++ b/modules/ui/style.js
@@ -727,6 +727,12 @@ styleResourcesCircle.addEventListener("change", function () {
drawResources();
});
+styleResourcesCircle.addEventListener('change', function () {
+ goods.attr('data-circle', +this.checked);
+ goods.selectAll('*').remove();
+ drawResources();
+});
+
// request a URL to image to be used as a texture
function textureProvideURL() {
alertMessage.innerHTML = /* html */ `Provide an image URL to be used as a texture: