merge completed... now to fix all the bugs...

This commit is contained in:
howlingsails 2021-12-12 23:02:38 -08:00
commit 87c4d80fbc
3472 changed files with 466748 additions and 6517 deletions

View file

@ -415,7 +415,7 @@ window.BurgsAndStates = (function () {
function getRiverCost(r, i, type) {
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 Math.min(Math.max(cells.fl[i] / 10, 20), 100); // river penalty from 20 to 100 based on flux
return minmax(cells.fl[i] / 10, 20, 100); // river penalty from 20 to 100 based on flux
}
function getTypeCost(t, type) {
@ -479,6 +479,7 @@ window.BurgsAndStates = (function () {
const {cells, features, states} = pack;
const paths = []; // text paths
lineGen.curve(d3.curveBundle.beta(1));
const mode = options.stateLabelsMode || "auto";
for (const s of states) {
if (!s.i || s.removed || !s.cells || (list && !list.includes(s.i))) continue;
@ -585,7 +586,8 @@ window.BurgsAndStates = (function () {
paths.forEach((p) => {
const id = p[0];
const s = states[p[0]];
const state = states[p[0]];
const {name, fullName} = state;
if (list) {
t.select('#textPath_stateLabel' + id).remove();
@ -599,22 +601,7 @@ window.BurgsAndStates = (function () {
.attr('id', 'textPath_stateLabel' + id);
const pathLength = p[1].length > 1 ? textPath.node().getTotalLength() / letterLength : 0; // path length in letters
let lines = [];
let ratio = 100;
if (pathLength < s.name.length) {
// only short name will fit
lines = splitInTwo(s.name);
ratio = Math.max(Math.min(rn((pathLength / lines[0].length) * 60), 150), 50);
} else if (pathLength > s.fullName.length * 2.5) {
// full name will fit in one line
lines = [s.fullName];
ratio = Math.max(Math.min(rn((pathLength / lines[0].length) * 70), 170), 70);
} else {
// try miltilined label
lines = splitInTwo(s.fullName);
ratio = Math.max(Math.min(rn((pathLength / lines[0].length) * 60), 150), 70);
}
const [lines, ratio] = getLines(mode, name, fullName, pathLength);
// prolongate path if it's too short
if (pathLength && pathLength < lines[0].length) {
@ -646,7 +633,7 @@ window.BurgsAndStates = (function () {
.node();
el.insertAdjacentHTML('afterbegin', spans.join(''));
if (lines.length < 2) return;
if (mode === "full" || lines.length === 1) return;
// check whether multilined label is generally inside the state. If no, replace with short name label
const cs = pack.cells.state;
@ -657,14 +644,14 @@ window.BurgsAndStates = (function () {
const c4 = () => +cs[findCell(b.x + b.width, b.y + b.height)] === id;
const c5 = () => +cs[findCell(b.x + b.width / 2, b.y + b.height)] === id;
const c6 = () => +cs[findCell(b.x, b.y + b.height)] === id;
if (c1() + c2() + c3() + c4() + c5() + c6() > 3) return; // generally inside
if (c1() + c2() + c3() + c4() + c5() + c6() > 3) return; // generally inside => exit
// use one-line name
const name = pathLength > s.fullName.length * 1.8 ? s.fullName : s.name;
example.text(name);
// move to one-line name
const text = pathLength > fullName.length * 1.8 ? fullName : name;
example.text(text);
const left = example.node().getBBox().width / -2; // x offset
el.innerHTML = `<tspan x="${left}px">${name}</tspan>`;
ratio = Math.max(Math.min(rn((pathLength / name.length) * 60), 130), 40);
el.innerHTML = `<tspan x="${left}px">${text}</tspan>`;
el.setAttribute('font-size', ratio + '%');
});
@ -673,13 +660,34 @@ window.BurgsAndStates = (function () {
})();
TIME && console.timeEnd('drawStateLabels');
function getLines(mode, name, fullName, pathLength) {
// short name
if (mode === "short" || (mode === "auto" && pathLength < name.length)) {
const lines = splitInTwo(name);
const ratio = pathLength / lines[0].length;
return [lines, minmax(rn(ratio * 60), 50, 150)];
}
// full name: one line
if (pathLength > fullName.length * 2.5) {
const lines = [fullName];
const ratio = pathLength / lines[0].length;
return [lines, minmax(rn(ratio * 70), 70, 170)];
}
// full name: two lines
const lines = splitInTwo(fullName);
const ratio = pathLength / lines[0].length;
return [lines, minmax(rn(ratio * 60), 70, 150)];
}
};
// calculate states data like area, population etc.
const collectStatistics = function () {
TIME && console.time('collectStatistics');
const cells = pack.cells,
states = pack.states;
const {cells, states} = pack;
states.forEach((s) => {
if (s.removed) return;
s.cells = s.area = s.burgs = s.rural = s.urban = 0;
@ -737,21 +745,28 @@ window.BurgsAndStates = (function () {
TIME && console.timeEnd('assignColors');
};
// generate historical conflicts of each state
const generateCampaigns = function () {
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];
pack.states.forEach((s) => {
if (!s.i || s.removed) return;
const n = s.neighbors.length ? s.neighbors : [0];
s.campaigns = n
return neighbors
.map((i) => {
const name = i && P(0.8) ? pack.states[i].name : Names.getCultureShort(s.culture);
const start = gauss(options.year - 100, 150, 1, options.year - 6);
const end = start + gauss(4, 5, 1, options.year - start - 1);
return {name: getAdjective(name) + ' ' + rw(wars), start, end};
})
.sort((a, b) => a.start - b.start);
const name = i && P(0.8) ? pack.states[i].name : Names.getCultureShort(state.culture);
const start = gauss(options.year - 100, 150, 1, options.year - 6);
const end = start + gauss(4, 5, 1, options.year - start - 1);
return {name: getAdjective(name) + " " + rw(wars), start, end};
})
.sort((a, b) => a.start - b.start);
};
// generate historical conflicts of each state
const generateCampaigns = function () {
pack.states.forEach(s => {
if (!s.i || s.removed) return;
s.campaigns = generateCampaign(s);
});
};
@ -950,6 +965,13 @@ window.BurgsAndStates = (function () {
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};
"Most Serene Republic": 2,
Tetrarchy: 1,
Triumvirate: 1,
Diarchy: 1,
"Trade Company": 4,
Junta: 1
}; // weighted random
for (const s of states) {
if (list && !list.includes(s.i)) continue;
@ -974,6 +996,7 @@ window.BurgsAndStates = (function () {
// 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 dutchies 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
}
@ -1078,16 +1101,16 @@ window.BurgsAndStates = (function () {
const localSeed = regenerate ? Math.floor(Math.random() * 1e9).toString() : seed;
Math.random = aleaPRNG(localSeed);
const cells = pack.cells,
states = pack.states,
burgs = pack.burgs;
const {cells, states, burgs} = pack;
const provinces = (pack.provinces = [0]);
cells.province = new Uint16Array(cells.i.length); // cell state
const percentage = +provincesInput.value;
if (states.length < 2 || !percentage) {
states.forEach((s) => (s.provinces = []));
return;
} // no provinces
const max = percentage == 100 ? 1000 : gauss(20, 5, 5, 100) * percentage ** 0.5; // max growth
const forms = {
@ -1100,7 +1123,6 @@ window.BurgsAndStates = (function () {
};
// generate provinces for a selected burgs
Math.random = aleaPRNG(localSeed);
states.forEach((s) => {
s.provinces = [];
if (!s.i || s.removed) return;