mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 17:51:24 +01:00
Merge branch 'master' of https://github.com/Azgaar/Fantasy-Map-Generator into dev-economics
This commit is contained in:
commit
1180a3c67b
41 changed files with 5185 additions and 3469 deletions
|
|
@ -1,12 +1,9 @@
|
|||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? (module.exports = factory()) : typeof define === 'function' && define.amd ? define(factory) : (global.BurgsAndStates = factory());
|
||||
})(this, function () {
|
||||
'use strict';
|
||||
'use strict';
|
||||
|
||||
window.BurgsAndStates = (function () {
|
||||
const generate = function () {
|
||||
const cells = pack.cells,
|
||||
cultures = pack.cultures,
|
||||
n = cells.i.length;
|
||||
const {cells, cultures} = pack;
|
||||
const n = cells.i.length;
|
||||
|
||||
cells.burg = new Uint16Array(n); // cell burg
|
||||
cells.road = new Uint16Array(n); // cell road power
|
||||
|
|
@ -80,6 +77,7 @@
|
|||
TIME && console.time('createStates');
|
||||
const states = [{i: 0, name: 'Neutrals'}];
|
||||
const colors = getColors(burgs.length - 1);
|
||||
const each5th = each(5);
|
||||
|
||||
burgs.forEach(function (b, i) {
|
||||
if (!i) return; // skip first element
|
||||
|
|
@ -93,7 +91,7 @@
|
|||
|
||||
// states data
|
||||
const expansionism = rn(Math.random() * powerInput.value + 1, 1);
|
||||
const basename = b.name.length < 9 && b.cell % 5 === 0 ? b.name : Names.getCultureShort(b.culture);
|
||||
const basename = b.name.length < 9 && each5th(b.cell) ? b.name : Names.getCultureShort(b.culture);
|
||||
const name = Names.getState(basename, b.culture);
|
||||
const type = cultures[b.culture].type;
|
||||
|
||||
|
|
@ -110,10 +108,10 @@
|
|||
// place secondary settlements based on geo and economical evaluation
|
||||
function placeTowns() {
|
||||
TIME && console.time('placeTowns');
|
||||
const score = new Int16Array(cells.s.map((s) => s * Math.random())); // a bit randomized cell score for towns placement
|
||||
const sorted = cells.i.filter((i) => score[i] > 0 && cells.culture[i] && !cells.burg[i]).sort((a, b) => score[b] - score[a]); // filtered and sorted array of indexes
|
||||
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 desiredNumber = manorsInput.value == 1000 ? rn(sorted.length / 6 / (grid.points.length / 10000) ** 0.8) : +manorsInput.value;
|
||||
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;
|
||||
|
||||
|
|
@ -175,9 +173,9 @@
|
|||
|
||||
if (b.port) {
|
||||
b.population = b.population * 1.3; // increase port population
|
||||
const e = cells.v[i].filter((v) => vertices.c[v].some((c) => c === cells.haven[i])); // vertices of common edge
|
||||
b.x = rn((vertices.p[e[0]][0] + vertices.p[e[1]][0]) / 2, 2);
|
||||
b.y = rn((vertices.p[e[0]][1] + vertices.p[e[1]][1]) / 2, 2);
|
||||
const [x, y] = getMiddlePoint(i, haven);
|
||||
b.x = x;
|
||||
b.y = y;
|
||||
}
|
||||
|
||||
// add random factor
|
||||
|
|
@ -477,9 +475,7 @@
|
|||
// calculate and draw curved state labels for a list of states
|
||||
const drawStateLabels = function (list) {
|
||||
TIME && console.time('drawStateLabels');
|
||||
const cells = pack.cells,
|
||||
features = pack.features,
|
||||
states = pack.states;
|
||||
const {cells, features, states} = pack;
|
||||
const paths = []; // text paths
|
||||
lineGen.curve(d3.curveBundle.beta(1));
|
||||
|
||||
|
|
@ -572,8 +568,8 @@
|
|||
}
|
||||
|
||||
void (function drawLabels() {
|
||||
const g = labels.select('#states'),
|
||||
t = defs.select('#textPaths');
|
||||
const g = labels.select('#states');
|
||||
const t = defs.select('#textPaths');
|
||||
const displayed = layerIsOn('toggleLabels');
|
||||
if (!displayed) toggleLabels();
|
||||
|
||||
|
|
@ -602,8 +598,8 @@
|
|||
.attr('id', 'textPath_stateLabel' + id);
|
||||
const pathLength = p[1].length > 1 ? textPath.node().getTotalLength() / letterLength : 0; // path length in letters
|
||||
|
||||
let lines = [],
|
||||
ratio = 100;
|
||||
let lines = [];
|
||||
let ratio = 100;
|
||||
|
||||
if (pathLength < s.name.length) {
|
||||
// only short name will fit
|
||||
|
|
@ -622,10 +618,9 @@
|
|||
// prolongate path if it's too short
|
||||
if (pathLength && pathLength < lines[0].length) {
|
||||
const points = p[1];
|
||||
const f = points[0],
|
||||
l = points[points.length - 1];
|
||||
const dx = l[0] - f[0],
|
||||
dy = l[1] - f[1];
|
||||
const f = points[0];
|
||||
const l = points[points.length - 1];
|
||||
const [dx, dy] = [l[0] - f[0], l[1] - f[1]];
|
||||
const mod = Math.abs((letterLength * lines[0].length) / dx) / 2;
|
||||
points[0] = [rn(f[0] - dx * mod), rn(f[1] - dy * mod)];
|
||||
points[points.length - 1] = [rn(l[0] + dx * mod), rn(l[1] + dy * mod)];
|
||||
|
|
@ -653,8 +648,8 @@
|
|||
if (lines.length < 2) return;
|
||||
|
||||
// check whether multilined label is generally inside the state. If no, replace with short name label
|
||||
const cs = pack.cells.state,
|
||||
b = el.parentNode.getBBox();
|
||||
const cs = pack.cells.state;
|
||||
const b = el.parentNode.getBBox();
|
||||
const c1 = () => +cs[findCell(b.x, b.y)] === id;
|
||||
const c2 = () => +cs[findCell(b.x + b.width / 2, b.y)] === id;
|
||||
const c3 = () => +cs[findCell(b.x + b.width, b.y)] === id;
|
||||
|
|
@ -950,30 +945,31 @@
|
|||
});
|
||||
|
||||
const monarchy = ['Duchy', 'Grand Duchy', 'Principality', 'Kingdom', 'Empire']; // per expansionism tier
|
||||
const republic = {Republic: 75, Federation: 4, Oligarchy: 2, Tetrarchy: 1, Triumvirate: 1, Diarchy: 1, 'Trade Company': 4, Junta: 1}; // weighted random
|
||||
const republic = {Republic: 75, Federation: 4, Oligarchy: 2, 'Most Serene Republic': 2, Tetrarchy: 1, Triumvirate: 1, Diarchy: 1, 'Trade Company': 4, 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 theocracy = {Theocracy: 20, Brotherhood: 1, Thearchy: 2, See: 1};
|
||||
const theocracy = {Theocracy: 20, Brotherhood: 1, Thearchy: 2, See: 1, 'Holy State': 1};
|
||||
const anarchy = {'Free Territory': 2, Council: 3, Commune: 1, Community: 1};
|
||||
|
||||
for (const s of states) {
|
||||
if (list && !list.includes(s.i)) continue;
|
||||
const tier = expTiers[s.i];
|
||||
|
||||
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));
|
||||
const isAnarchy = P(0.01 - expTiers[s.i] / 500);
|
||||
const isAnarchy = P(0.01 - tier / 500);
|
||||
|
||||
if (isTheocracy) s.form = 'Theocracy';
|
||||
else if (isAnarchy) s.form = 'Anarchy';
|
||||
else s.form = s.type === 'Naval' ? rw(naval) : rw(generic);
|
||||
s.formName = selectForm(s);
|
||||
s.formName = selectForm(s, tier);
|
||||
s.fullName = getFullName(s);
|
||||
}
|
||||
|
||||
function selectForm(s) {
|
||||
function selectForm(s, tier) {
|
||||
const base = pack.cultures[s.culture].base;
|
||||
|
||||
if (s.form === 'Monarchy') {
|
||||
const form = monarchy[expTiers[s.i]];
|
||||
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 dutchies on borderland
|
||||
|
|
@ -995,7 +991,7 @@
|
|||
|
||||
if (s.form === 'Republic') {
|
||||
// Default name is from weighted array, special case for small states with only 1 burg
|
||||
if (expTiers[s.i] < 2 && s.burgs === 1) {
|
||||
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';
|
||||
|
|
@ -1009,10 +1005,15 @@
|
|||
if (s.form === 'Anarchy') return rw(anarchy);
|
||||
|
||||
if (s.form === 'Theocracy') {
|
||||
if (P(0.5) && [0, 1, 2, 3, 4, 6, 8, 9, 13, 15, 20].includes(base)) return 'Diocese'; // Euporean
|
||||
if (P(0.9) && [7, 5].includes(base)) return 'Eparchy'; // Greek, Ruthenian
|
||||
// European
|
||||
if ([0, 1, 2, 3, 4, 6, 8, 9, 13, 15, 20].includes(base)) {
|
||||
if (P(0.1)) return 'Divine ' + monarchy[tier];
|
||||
if (tier < 2 && P(0.5)) return 'Diocese';
|
||||
if (tier < 2 && P(0.5)) return 'Bishopric';
|
||||
}
|
||||
if (tier < 2 && P(0.9) && [7, 5].includes(base)) return 'Eparchy'; // Greek, Ruthenian
|
||||
if (P(0.9) && [21, 16].includes(base)) return 'Imamah'; // Nigerian, Turkish
|
||||
if (P(0.8) && [18, 17, 28].includes(base)) return 'Caliphate'; // Arabic, Berber, Swahili
|
||||
if (tier > 2 && P(0.8) && [18, 17, 28].includes(base)) return 'Caliphate'; // Arabic, Berber, Swahili
|
||||
return rw(theocracy);
|
||||
}
|
||||
}
|
||||
|
|
@ -1255,4 +1256,4 @@
|
|||
generateProvinces,
|
||||
updateCultures
|
||||
};
|
||||
});
|
||||
})();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue