replace old iife by a simpler ones

This commit is contained in:
Azgaar 2021-08-04 23:49:02 +03:00
parent 37e5b803bc
commit 460bb29e49
15 changed files with 2430 additions and 1313 deletions

View file

@ -1,163 +1,157 @@
(function (global, factory) { "use strict";
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.Pell = factory());
}(this, (function () { 'use strict';
const defaultParagraphSeparatorString = 'defaultParagraphSeparator' window.Pell = (function () {
const formatBlock = 'formatBlock' const defaultParagraphSeparatorString = "defaultParagraphSeparator";
const addEventListener = (parent, type, listener) => parent.addEventListener(type, listener) const formatBlock = "formatBlock";
const appendChild = (parent, child) => parent.appendChild(child) const addEventListener = (parent, type, listener) => parent.addEventListener(type, listener);
const createElement = tag => document.createElement(tag) const appendChild = (parent, child) => parent.appendChild(child);
const queryCommandState = command => document.queryCommandState(command) const createElement = tag => document.createElement(tag);
const queryCommandValue = command => document.queryCommandValue(command) const queryCommandState = command => document.queryCommandState(command);
const exec = (command, value = null) => document.execCommand(command, false, value) const queryCommandValue = command => document.queryCommandValue(command);
const exec = (command, value = null) => document.execCommand(command, false, value);
const defaultActions = { const defaultActions = {
bold: { bold: {
icon: '<b>B</b>', icon: "<b>B</b>",
title: 'Bold', title: "Bold",
state: () => queryCommandState('bold'), state: () => queryCommandState("bold"),
result: () => exec('bold') result: () => exec("bold")
}, },
italic: { italic: {
icon: '<i>I</i>', icon: "<i>I</i>",
title: 'Italic', title: "Italic",
state: () => queryCommandState('italic'), state: () => queryCommandState("italic"),
result: () => exec('italic') result: () => exec("italic")
}, },
underline: { underline: {
icon: '<u>U</u>', icon: "<u>U</u>",
title: 'Underline', title: "Underline",
state: () => queryCommandState('underline'), state: () => queryCommandState("underline"),
result: () => exec('underline') result: () => exec("underline")
}, },
strikethrough: { strikethrough: {
icon: '<strike>S</strike>', icon: "<strike>S</strike>",
title: 'Strike-through', title: "Strike-through",
state: () => queryCommandState('strikeThrough'), state: () => queryCommandState("strikeThrough"),
result: () => exec('strikeThrough') result: () => exec("strikeThrough")
}, },
heading1: { heading1: {
icon: '<b>H<sub>1</sub></b>', icon: "<b>H<sub>1</sub></b>",
title: 'Heading 1', title: "Heading 1",
result: () => exec(formatBlock, '<h1>') result: () => exec(formatBlock, "<h1>")
}, },
heading2: { heading2: {
icon: '<b>H<sub>2</sub></b>', icon: "<b>H<sub>2</sub></b>",
title: 'Heading 2', title: "Heading 2",
result: () => exec(formatBlock, '<h2>') result: () => exec(formatBlock, "<h2>")
}, },
paragraph: { paragraph: {
icon: '&#182;', icon: "&#182;",
title: 'Paragraph', title: "Paragraph",
result: () => exec(formatBlock, '<p>') result: () => exec(formatBlock, "<p>")
}, },
quote: { quote: {
icon: '&#8220; &#8221;', icon: "&#8220; &#8221;",
title: 'Quote', title: "Quote",
result: () => exec(formatBlock, '<blockquote>') result: () => exec(formatBlock, "<blockquote>")
}, },
olist: { olist: {
icon: '&#35;', icon: "&#35;",
title: 'Ordered List', title: "Ordered List",
result: () => exec('insertOrderedList') result: () => exec("insertOrderedList")
}, },
ulist: { ulist: {
icon: '&#8226;', icon: "&#8226;",
title: 'Unordered List', title: "Unordered List",
result: () => exec('insertUnorderedList') result: () => exec("insertUnorderedList")
}, },
code: { code: {
icon: '&lt;/&gt;', icon: "&lt;/&gt;",
title: 'Code', title: "Code",
result: () => exec(formatBlock, '<pre>') result: () => exec(formatBlock, "<pre>")
}, },
line: { line: {
icon: '&#8213;', icon: "&#8213;",
title: 'Horizontal Line', title: "Horizontal Line",
result: () => exec('insertHorizontalRule') result: () => exec("insertHorizontalRule")
}, },
link: { link: {
icon: '&#128279;', icon: "&#128279;",
title: 'Link', title: "Link",
result: () => navigator.clipboard.readText().then(url => exec('createLink', url)) result: () => navigator.clipboard.readText().then(url => exec("createLink", url))
}, },
image: { image: {
icon: '&#128247;', icon: "&#128247;",
title: 'Image', title: "Image",
result: () => { result: () => {
navigator.clipboard.readText().then(url => exec('insertImage', url)) navigator.clipboard.readText().then(url => exec("insertImage", url));
exec('enableObjectResizing') exec("enableObjectResizing");
}
} }
} }
};
const defaultClasses = { const defaultClasses = {
actionbar: 'pell-actionbar', actionbar: "pell-actionbar",
button: 'pell-button', button: "pell-button",
content: 'pell-content', content: "pell-content",
selected: 'pell-button-selected' selected: "pell-button-selected"
} };
const init = settings => { const init = settings => {
const actions = settings.actions const actions = settings.actions
? ( ? settings.actions.map(action => {
settings.actions.map(action => { if (typeof action === "string") return defaultActions[action];
if (typeof action === 'string') return defaultActions[action] else if (defaultActions[action.name]) return {...defaultActions[action.name], ...action};
else if (defaultActions[action.name]) return { ...defaultActions[action.name], ...action } return action;
return action
}) })
) : Object.keys(defaultActions).map(action => defaultActions[action]);
: Object.keys(defaultActions).map(action => defaultActions[action])
const classes = { ...defaultClasses, ...settings.classes } const classes = {...defaultClasses, ...settings.classes};
const defaultParagraphSeparator = settings[defaultParagraphSeparatorString] || 'div' const defaultParagraphSeparator = settings[defaultParagraphSeparatorString] || "div";
const actionbar = createElement('div') const actionbar = createElement("div");
actionbar.className = classes.actionbar actionbar.className = classes.actionbar;
appendChild(settings.element, actionbar) appendChild(settings.element, actionbar);
const content = settings.element.content = createElement('div') const content = (settings.element.content = createElement("div"));
content.contentEditable = true content.contentEditable = true;
content.className = classes.content content.className = classes.content;
content.oninput = ({target: {firstChild}}) => { content.oninput = ({target: {firstChild}}) => {
if (firstChild && firstChild.nodeType === 3) exec(formatBlock, `<${defaultParagraphSeparator}>`) if (firstChild && firstChild.nodeType === 3) exec(formatBlock, `<${defaultParagraphSeparator}>`);
else if (content.innerHTML === '<br>') content.innerHTML = '' else if (content.innerHTML === "<br>") content.innerHTML = "";
settings.onChange(content.innerHTML) settings.onChange(content.innerHTML);
} };
content.onkeydown = event => { content.onkeydown = event => {
if (event.key === 'Enter' && queryCommandValue(formatBlock) === 'blockquote') { if (event.key === "Enter" && queryCommandValue(formatBlock) === "blockquote") {
setTimeout(() => exec(formatBlock, `<${defaultParagraphSeparator}>`), 0) setTimeout(() => exec(formatBlock, `<${defaultParagraphSeparator}>`), 0);
} }
} };
appendChild(settings.element, content) appendChild(settings.element, content);
actions.forEach(action => { actions.forEach(action => {
const button = createElement('button') const button = createElement("button");
button.className = classes.button button.className = classes.button;
button.innerHTML = action.icon button.innerHTML = action.icon;
button.title = action.title button.title = action.title;
button.setAttribute('type', 'button') button.setAttribute("type", "button");
button.onclick = () => action.result() && content.focus() button.onclick = () => action.result() && content.focus();
if (action.state) { if (action.state) {
const handler = () => button.classList[action.state() ? 'add' : 'remove'](classes.selected) const handler = () => button.classList[action.state() ? "add" : "remove"](classes.selected);
addEventListener(content, 'keyup', handler) addEventListener(content, "keyup", handler);
addEventListener(content, 'mouseup', handler) addEventListener(content, "mouseup", handler);
addEventListener(button, 'click', handler) addEventListener(button, "click", handler);
} }
appendChild(actionbar, button) appendChild(actionbar, button);
}) });
if (settings.styleWithCSS) exec('styleWithCSS') if (settings.styleWithCSS) exec("styleWithCSS");
exec(defaultParagraphSeparatorString, defaultParagraphSeparator) exec(defaultParagraphSeparatorString, defaultParagraphSeparator);
return settings.element return settings.element;
} };
return {exec, init} return {exec, init};
})();
})));

View file

@ -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 generate = function () {
const cells = pack.cells, const {cells, cultures} = pack;
cultures = pack.cultures, const n = cells.i.length;
n = cells.i.length;
cells.burg = new Uint16Array(n); // cell burg cells.burg = new Uint16Array(n); // cell burg
cells.road = new Uint16Array(n); // cell road power cells.road = new Uint16Array(n); // cell road power
@ -1224,4 +1221,4 @@
}; };
return {generate, expandStates, normalizeStates, assignColors, drawBurgs, specifyBurgs, defineBurgFeatures, getType, drawStateLabels, collectStatistics, generateCampaigns, generateDiplomacy, defineStateForms, getFullName, generateProvinces, updateCultures}; return {generate, expandStates, normalizeStates, assignColors, drawBurgs, specifyBurgs, defineBurgFeatures, getType, drawStateLabels, collectStatistics, generateCampaigns, generateDiplomacy, defineStateForms, getFullName, generateProvinces, updateCultures};
}); })();

View file

@ -1,25 +1,47 @@
(function (global, factory) { "use strict";
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.COA = factory());
}(this, (function () {'use strict';
window.COA = (function () {
const tinctures = { const tinctures = {
field: { metals: 3, colours: 4, stains: +P(.03), patterns: 1 }, field: {metals: 3, colours: 4, stains: +P(0.03), patterns: 1},
division: { metals: 5, colours: 8, stains: +P(.03), patterns: 1 }, division: {metals: 5, colours: 8, stains: +P(0.03), patterns: 1},
charge: { metals: 2, colours: 3, stains: +P(.05), patterns: 0 }, charge: {metals: 2, colours: 3, stains: +P(0.05), patterns: 0},
metals: {argent: 3, or: 2}, metals: {argent: 3, or: 2},
colours: {gules: 5, azure: 4, sable: 3, purpure: 3, vert: 2}, colours: {gules: 5, azure: 4, sable: 3, purpure: 3, vert: 2},
stains: {murrey: 1, sanguine: 1, tenné: 1}, stains: {murrey: 1, sanguine: 1, tenné: 1},
patterns: { patterns: {
semy: 8, ermine: 6, semy: 8,
vair: 4, counterVair: 1, vairInPale: 1, vairEnPointe: 2, vairAncien: 2, ermine: 6,
potent: 2, counterPotent: 1, potentInPale: 1, potentEnPointe: 1, vair: 4,
chequy: 8, lozengy: 5, fusily: 2, pally: 8, barry: 10, gemelles: 1, counterVair: 1,
bendy: 8, bendySinister: 4, palyBendy: 2, barryBendy: 1, vairInPale: 1,
pappellony: 2, pappellony2: 3, scaly: 1, plumetty: 1, vairEnPointe: 2,
masoned: 6, fretty: 3, grillage: 1, chainy: 1, maily: 2, honeycombed: 1 } vairAncien: 2,
potent: 2,
counterPotent: 1,
potentInPale: 1,
potentEnPointe: 1,
chequy: 8,
lozengy: 5,
fusily: 2,
pally: 8,
barry: 10,
gemelles: 1,
bendy: 8,
bendySinister: 4,
palyBendy: 2,
barryBendy: 1,
pappellony: 2,
pappellony2: 3,
scaly: 1,
plumetty: 1,
masoned: 6,
fretty: 3,
grillage: 1,
chainy: 1,
maily: 2,
honeycombed: 1
} }
};
const charges = { const charges = {
// categories selection // categories selection
@ -28,21 +50,102 @@
semy: {conventional: 12, crosses: 3, plants: 1}, semy: {conventional: 12, crosses: 3, plants: 1},
// generic categories // generic categories
conventional: { conventional: {
lozenge: 2, fusil: 4, mascle: 4, rustre: 2, lozengeFaceted: 3, lozengePloye: 1, roundel: 4, roundel2: 3, annulet: 4, lozenge: 2,
mullet: 5, mulletPierced: 1, mulletFaceted: 1, mullet4: 3, mullet6: 4, mullet6Pierced: 1, mullet6Faceted: 1, mullet7: 1, mullet8: 1, mullet10: 1, fusil: 4,
estoile: 1, compassRose: 1, billet: 5, delf: 0, triangle: 3, trianglePierced: 1, goutte: 4, heart: 4, pique: 2, carreau: 1, trefle: 2, mascle: 4,
fleurDeLis: 6, sun: 3, sunInSplendour: 1, crescent: 5, fountain: 1 rustre: 2,
lozengeFaceted: 3,
lozengePloye: 1,
roundel: 4,
roundel2: 3,
annulet: 4,
mullet: 5,
mulletPierced: 1,
mulletFaceted: 1,
mullet4: 3,
mullet6: 4,
mullet6Pierced: 1,
mullet6Faceted: 1,
mullet7: 1,
mullet8: 1,
mullet10: 1,
estoile: 1,
compassRose: 1,
billet: 5,
delf: 0,
triangle: 3,
trianglePierced: 1,
goutte: 4,
heart: 4,
pique: 2,
carreau: 1,
trefle: 2,
fleurDeLis: 6,
sun: 3,
sunInSplendour: 1,
crescent: 5,
fountain: 1
}, },
crosses: { crosses: {
crossHummetty: 15, crossVoided: 1, crossPattee: 2, crossPatteeAlisee: 1, crossFormee: 1, crossFormee2: 2, crossPotent: 2, crossJerusalem:1, crossHummetty: 15,
crosslet: 1, crossClechy: 3, crossBottony: 1, crossFleury: 3, crossPatonce: 1, crossPommy: 1, crossGamma: 1, crossArrowed: 1, crossFitchy: 1, crossVoided: 1,
crossCercelee: 1, crossMoline: 2, crossFourchy: 1, crossAvellane: 1, crossErminee: 1, crossBiparted: 1, crossMaltese: 3, crossTemplar: 2, crossPattee: 2,
crossCeltic: 1, crossCeltic2: 1, crossTriquetra: 1, crossCarolingian: 1, crossOccitan: 1, crossSaltire: 3, crossBurgundy: 1, crossPatteeAlisee: 1,
crossLatin: 3, crossPatriarchal: 1, crossOrthodox: 1, crossCalvary: 1, crossDouble: 1, crossTau: 1, crossSantiago: 1, crossAnkh: 1 crossFormee: 1,
crossFormee2: 2,
crossPotent: 2,
crossJerusalem: 1,
crosslet: 1,
crossClechy: 3,
crossBottony: 1,
crossFleury: 3,
crossPatonce: 1,
crossPommy: 1,
crossGamma: 1,
crossArrowed: 1,
crossFitchy: 1,
crossCercelee: 1,
crossMoline: 2,
crossFourchy: 1,
crossAvellane: 1,
crossErminee: 1,
crossBiparted: 1,
crossMaltese: 3,
crossTemplar: 2,
crossCeltic: 1,
crossCeltic2: 1,
crossTriquetra: 1,
crossCarolingian: 1,
crossOccitan: 1,
crossSaltire: 3,
crossBurgundy: 1,
crossLatin: 3,
crossPatriarchal: 1,
crossOrthodox: 1,
crossCalvary: 1,
crossDouble: 1,
crossTau: 1,
crossSantiago: 1,
crossAnkh: 1
}, },
animals: { animals: {
lionRampant: 5, lionPassant: 2, lionPassantGuardant: 1, wolfRampant: 1, wolfPassant: 1, wolfStatant: 1, greyhoundCourant: 1, boarRampant: 1, lionRampant: 5,
horseRampant: 2, horseSalient: 1, bearRampant: 2, bearPassant: 1, bullPassant: 1, goat: 1, lamb: 1, elephant: 1, camel: 1 lionPassant: 2,
lionPassantGuardant: 1,
wolfRampant: 1,
wolfPassant: 1,
wolfStatant: 1,
greyhoundCourant: 1,
boarRampant: 1,
horseRampant: 2,
horseSalient: 1,
bearRampant: 2,
bearPassant: 1,
bullPassant: 1,
goat: 1,
lamb: 1,
elephant: 1,
camel: 1
}, },
animalHeads: {wolfHeadErased: 1, bullHeadCaboshed: 1, deerHeadCaboshed: 1, lionHeadCaboshed: 2}, animalHeads: {wolfHeadErased: 1, bullHeadCaboshed: 1, deerHeadCaboshed: 1, lionHeadCaboshed: 2},
fantastic: {dragonPassant: 2, dragonRampant: 2, wyvern: 1, wyvernWithWingsDisplayed: 1, griffinPassant: 1, griffinRampant: 1, eagleTwoHeards: 2, unicornRampant: 1, pegasus: 1, serpent: 1}, fantastic: {dragonPassant: 2, dragonRampant: 2, wyvern: 1, wyvernWithWingsDisplayed: 1, griffinPassant: 1, griffinRampant: 1, eagleTwoHeards: 2, unicornRampant: 1, pegasus: 1, serpent: 1},
@ -54,8 +157,29 @@
people: {cavalier: 3, monk: 1, angel: 2}, people: {cavalier: 3, monk: 1, angel: 2},
architecture: {tower: 1, castle: 1}, architecture: {tower: 1, castle: 1},
miscellaneous: { miscellaneous: {
crown: 3, orb: 1, chalice: 1, key: 1, buckle: 1, bugleHorn: 1, bugleHorn2: 1, bell: 2, pot: 1, bucket: 1, horseshoe: 3, crown: 3,
attire: 1, stagsAttires: 1, ramsHorn: 1, cowHorns: 2, wing: 1, wingSword: 1, lute: 1, harp: 1, wheel: 2, crosier: 1, fasces: 1, log: 1 orb: 1,
chalice: 1,
key: 1,
buckle: 1,
bugleHorn: 1,
bugleHorn2: 1,
bell: 2,
pot: 1,
bucket: 1,
horseshoe: 3,
attire: 1,
stagsAttires: 1,
ramsHorn: 1,
cowHorns: 2,
wing: 1,
wingSword: 1,
lute: 1,
harp: 1,
wheel: 2,
crosier: 1,
fasces: 1,
log: 1
}, },
// selection based on culture type: // selection based on culture type:
Naval: {anchor: 3, boat: 1, lymphad: 2, armillarySphere: 1, escallop: 1, dolphin: 1}, Naval: {anchor: 3, boat: 1, lymphad: 2, armillarySphere: 1, escallop: 1, dolphin: 1},
@ -70,17 +194,87 @@
Сathedra: {chalice: 1, orb: 1, crosier: 2, lamb: 1, monk: 2, angel: 3, crossLatin: 2, crossPatriarchal: 1, crossOrthodox: 1, crossCalvary: 1}, Сathedra: {chalice: 1, orb: 1, crosier: 2, lamb: 1, monk: 2, angel: 3, crossLatin: 2, crossPatriarchal: 1, crossOrthodox: 1, crossCalvary: 1},
// specific cases // specific cases
natural: {fountain: "azure", garb: "or", raven: "sable"}, // charges to mainly use predefined colours natural: {fountain: "azure", garb: "or", raven: "sable"}, // charges to mainly use predefined colours
sinister: [ // charges that can be sinister sinister: [
"crossGamma", "lionRampant", "lionPassant", "wolfRampant", "wolfPassant", "wolfStatant", "wolfHeadErased", "greyhoundСourant", "boarRampant", // charges that can be sinister
"horseRampant", "horseSalient", "bullPassant", "bearRampant", "bearPassant", "goat", "lamb", "elephant", "eagle", "raven", "cock", "parrot", "crossGamma",
"swan", "swanErased", "heron", "pike", "dragonPassant", "dragonRampant", "wyvern", "wyvernWithWingsDisplayed", "griffinPassant", "griffinRampant", "lionRampant",
"unicornRampant", "pegasus", "serpent", "hatchet", "lochaberAxe", "hand", "wing", "wingSword", "lute", "harp", "bow", "head", "headWreathed", "lionPassant",
"knight", "lymphad", "log", "crosier", "dolphin", "sabre", "monk", "owl", "axe", "camel", "fasces", "lionPassantGuardant", "helmet"], "wolfRampant",
reversed: [ // charges that can be reversed "wolfPassant",
"goutte", "mullet", "mullet7", "crescent", "crossTau", "cancer", "sword", "sabresCrossed", "hand", "wolfStatant",
"horseshoe", "bowWithArrow", "arrow", "arrowsSheaf", "rake", "crossTriquetra", "crossLatin", "crossTau" "wolfHeadErased",
"greyhoundСourant",
"boarRampant",
"horseRampant",
"horseSalient",
"bullPassant",
"bearRampant",
"bearPassant",
"goat",
"lamb",
"elephant",
"eagle",
"raven",
"cock",
"parrot",
"swan",
"swanErased",
"heron",
"pike",
"dragonPassant",
"dragonRampant",
"wyvern",
"wyvernWithWingsDisplayed",
"griffinPassant",
"griffinRampant",
"unicornRampant",
"pegasus",
"serpent",
"hatchet",
"lochaberAxe",
"hand",
"wing",
"wingSword",
"lute",
"harp",
"bow",
"head",
"headWreathed",
"knight",
"lymphad",
"log",
"crosier",
"dolphin",
"sabre",
"monk",
"owl",
"axe",
"camel",
"fasces",
"lionPassantGuardant",
"helmet"
],
reversed: [
// charges that can be reversed
"goutte",
"mullet",
"mullet7",
"crescent",
"crossTau",
"cancer",
"sword",
"sabresCrossed",
"hand",
"horseshoe",
"bowWithArrow",
"arrow",
"arrowsSheaf",
"rake",
"crossTriquetra",
"crossLatin",
"crossTau"
] ]
} };
const positions = { const positions = {
conventional: {e: 20, abcdefgzi: 3, beh: 3, behdf: 2, acegi: 1, kn: 3, bhdf: 1, jeo: 1, abc: 3, jln: 6, jlh: 3, kmo: 2, jleh: 1, def: 3, abcpqh: 4, ABCDEFGHIJKL: 1}, conventional: {e: 20, abcdefgzi: 3, beh: 3, behdf: 2, acegi: 1, kn: 3, bhdf: 1, jeo: 1, abc: 3, jln: 6, jlh: 3, kmo: 2, jleh: 1, def: 3, abcpqh: 4, ABCDEFGHIJKL: 1},
@ -175,10 +369,39 @@
}; };
const lines = { const lines = {
straight: 50, wavy: 8, engrailed: 4, invecked: 3, rayonne: 3, embattled: 1, raguly: 1, urdy: 1, dancetty: 1, indented: 2, straight: 50,
dentilly: 1, bevilled: 1, angled: 1, flechy: 1, barby: 1, enclavy: 1, escartely: 1, arched: 2, archedReversed: 1, nowy: 1, nowyReversed: 1, wavy: 8,
embattledGhibellin: 1, embattledNotched: 1, embattledGrady: 1, dovetailedIndented: 1, dovetailed: 1, engrailed: 4,
potenty: 1, potentyDexter: 1, potentySinister: 1, nebuly: 2, seaWaves: 1, dragonTeeth: 1, firTrees: 1 invecked: 3,
rayonne: 3,
embattled: 1,
raguly: 1,
urdy: 1,
dancetty: 1,
indented: 2,
dentilly: 1,
bevilled: 1,
angled: 1,
flechy: 1,
barby: 1,
enclavy: 1,
escartely: 1,
arched: 2,
archedReversed: 1,
nowy: 1,
nowyReversed: 1,
embattledGhibellin: 1,
embattledNotched: 1,
embattledGrady: 1,
dovetailedIndented: 1,
dovetailed: 1,
potenty: 1,
potentyDexter: 1,
potentySinister: 1,
nebuly: 2,
seaWaves: 1,
dragonTeeth: 1,
firTrees: 1
}; };
const divisions = { const divisions = {
@ -195,13 +418,43 @@
const ordinaries = { const ordinaries = {
lined: { lined: {
pale: 7, fess: 5, bend: 3, bendSinister: 2, chief: 5, bar: 2, gemelle: 1, fessCotissed: 1, fessDoubleCotissed: 1, pale: 7,
bendlet: 2, bendletSinister: 1, terrace: 3, cross: 6, crossParted: 1, saltire: 2, saltireParted: 1 fess: 5,
bend: 3,
bendSinister: 2,
chief: 5,
bar: 2,
gemelle: 1,
fessCotissed: 1,
fessDoubleCotissed: 1,
bendlet: 2,
bendletSinister: 1,
terrace: 3,
cross: 6,
crossParted: 1,
saltire: 2,
saltireParted: 1
}, },
straight: { straight: {
bordure: 8, orle: 4, mount: 1, point: 2, flaunches: 1, gore: 1, bordure: 8,
gyron: 1, quarter: 1, canton: 2, pall: 3, pallReversed: 2, chevron: 4, chevronReversed: 3, orle: 4,
pile: 2, pileInBend: 2, pileInBendSinister: 1, piles: 1, pilesInPoint: 2, label: 1 mount: 1,
point: 2,
flaunches: 1,
gore: 1,
gyron: 1,
quarter: 1,
canton: 2,
pall: 3,
pallReversed: 2,
chevron: 4,
chevronReversed: 3,
pile: 2,
pileInBend: 2,
pileInBendSinister: 1,
piles: 1,
pilesInPoint: 2,
label: 1
} }
}; };
@ -215,7 +468,7 @@
simple: {round: 12, oval: 6, vesicaPiscis: 1, square: 1, diamond: 2, no: 0}, simple: {round: 12, oval: 6, vesicaPiscis: 1, square: 1, diamond: 2, no: 0},
fantasy: {fantasy1: 2, fantasy2: 2, fantasy3: 1, fantasy4: 1, fantasy5: 3}, fantasy: {fantasy1: 2, fantasy2: 2, fantasy3: 1, fantasy4: 1, fantasy5: 3},
middleEarth: {noldor: 1, gondor: 1, easterling: 1, erebor: 1, ironHills: 1, urukHai: 1, moriaOrc: 1} middleEarth: {noldor: 1, gondor: 1, easterling: 1, erebor: 1, ironHills: 1, urukHai: 1, moriaOrc: 1}
} };
const generate = function (parent, kinship, dominion, type) { const generate = function (parent, kinship, dominion, type) {
if (!parent || parent === "custom") { if (!parent || parent === "custom") {
@ -223,52 +476,53 @@
kinship = 0; kinship = 0;
dominion = 0; dominion = 0;
} }
let usedPattern = null, usedTinctures = []; let usedPattern = null,
usedTinctures = [];
const t1 = P(kinship) ? parent.t1 : getTincture("field"); const t1 = P(kinship) ? parent.t1 : getTincture("field");
if (t1.includes("-")) usedPattern = t1; if (t1.includes("-")) usedPattern = t1;
const coa = {t1}; const coa = {t1};
let charge = P(usedPattern ? .5 : .93) ? true : false; // 80% for charge let charge = P(usedPattern ? 0.5 : 0.93) ? true : false; // 80% for charge
const linedOrdinary = charge && P(.3) || P(.5) ? parent?.ordinaries && P(kinship) ? parent.ordinaries[0].ordinary : rw(ordinaries.lined) : null; const linedOrdinary = (charge && P(0.3)) || P(0.5) ? (parent?.ordinaries && P(kinship) ? parent.ordinaries[0].ordinary : rw(ordinaries.lined)) : null;
const ordinary = !charge && P(.65) || P(.3) ? linedOrdinary ? linedOrdinary : rw(ordinaries.straight) : null; // 36% for ordinary const ordinary = (!charge && P(0.65)) || P(0.3) ? (linedOrdinary ? linedOrdinary : rw(ordinaries.straight)) : null; // 36% for ordinary
const rareDivided = ["chief", "terrace", "chevron", "quarter", "flaunches"].includes(ordinary); const rareDivided = ["chief", "terrace", "chevron", "quarter", "flaunches"].includes(ordinary);
const divisioned = rareDivided ? P(.03) : charge && ordinary ? P(.03) : charge ? P(.3) : ordinary ? P(.7) : P(.995); // 33% for division const divisioned = rareDivided ? P(0.03) : charge && ordinary ? P(0.03) : charge ? P(0.3) : ordinary ? P(0.7) : P(0.995); // 33% for division
const division = divisioned ? parent?.division && P(kinship - .1) ? parent.division.division : rw(divisions.variants) : null; const division = divisioned ? (parent?.division && P(kinship - 0.1) ? parent.division.division : rw(divisions.variants)) : null;
if (charge) charge = if (charge) charge = parent?.charges && P(kinship - 0.1) ? parent.charges[0].charge : type && type !== "Generic" && P(0.2) ? rw(charges[type]) : selectCharge();
parent?.charges && P(kinship - .1) ? parent.charges[0].charge :
type && type !== "Generic" && P(.2) ? rw(charges[type]) :
selectCharge();
if (division) { if (division) {
const t = getTincture("division", usedTinctures, P(.98) ? coa.t1 : null); const t = getTincture("division", usedTinctures, P(0.98) ? coa.t1 : null);
coa.division = {division, t}; coa.division = {division, t};
if (divisions[division]) coa.division.line = usedPattern || (ordinary && P(.7)) ? "straight" : rw(divisions[division]); if (divisions[division]) coa.division.line = usedPattern || (ordinary && P(0.7)) ? "straight" : rw(divisions[division]);
} }
if (ordinary) { if (ordinary) {
coa.ordinaries = [{ordinary, t: getTincture("charge", usedTinctures, coa.t1)}]; coa.ordinaries = [{ordinary, t: getTincture("charge", usedTinctures, coa.t1)}];
if (linedOrdinary) coa.ordinaries[0].line = usedPattern || (division && P(.7)) ? "straight" : rw(lines); if (linedOrdinary) coa.ordinaries[0].line = usedPattern || (division && P(0.7)) ? "straight" : rw(lines);
if (division && !charge && !usedPattern && P(.5) && ordinary !== "bordure" && ordinary !== "orle") { if (division && !charge && !usedPattern && P(0.5) && ordinary !== "bordure" && ordinary !== "orle") {
if (P(.8)) coa.ordinaries[0].divided = "counter"; // 40% if (P(0.8)) coa.ordinaries[0].divided = "counter";
else if (P(.6)) coa.ordinaries[0].divided = "field"; // 6% // 40%
else if (P(0.6)) coa.ordinaries[0].divided = "field";
// 6%
else coa.ordinaries[0].divided = "division"; // 4% else coa.ordinaries[0].divided = "division"; // 4%
} }
} }
if (charge) { if (charge) {
let p = "e", t = "gules"; let p = "e",
t = "gules";
const ordinaryT = coa.ordinaries ? coa.ordinaries[0].t : null; const ordinaryT = coa.ordinaries ? coa.ordinaries[0].t : null;
if (positions.ordinariesOn[ordinary] && P(.8)) { if (positions.ordinariesOn[ordinary] && P(0.8)) {
// place charge over ordinary (use tincture of field type) // place charge over ordinary (use tincture of field type)
p = rw(positions.ordinariesOn[ordinary]); p = rw(positions.ordinariesOn[ordinary]);
while (charges.natural[charge] === ordinaryT) charge = selectCharge(); while (charges.natural[charge] === ordinaryT) charge = selectCharge();
t = !usedPattern && P(.3) ? coa.t1 : getTincture("charge", [], ordinaryT); t = !usedPattern && P(0.3) ? coa.t1 : getTincture("charge", [], ordinaryT);
} else if (positions.ordinariesOff[ordinary] && P(.95)) { } else if (positions.ordinariesOff[ordinary] && P(0.95)) {
// place charge out of ordinary (use tincture of ordinary type) // place charge out of ordinary (use tincture of ordinary type)
p = rw(positions.ordinariesOff[ordinary]); p = rw(positions.ordinariesOff[ordinary]);
while (charges.natural[charge] === coa.t1) charge = selectCharge(); while (charges.natural[charge] === coa.t1) charge = selectCharge();
t = !usedPattern && P(.3) ? ordinaryT : getTincture("charge", usedTinctures, coa.t1); t = !usedPattern && P(0.3) ? ordinaryT : getTincture("charge", usedTinctures, coa.t1);
} else if (positions.divisions[division]) { } else if (positions.divisions[division]) {
// place charge in fields made by division // place charge in fields made by division
p = rw(positions.divisions[division]); p = rw(positions.divisions[division]);
@ -289,43 +543,41 @@
if (charges.natural[charge]) t = charges.natural[charge]; // natural tincture if (charges.natural[charge]) t = charges.natural[charge]; // natural tincture
coa.charges = [{charge, t, p}]; coa.charges = [{charge, t, p}];
if (p === "ABCDEFGHIKL" && P(.95)) { if (p === "ABCDEFGHIKL" && P(0.95)) {
// add central charge if charge is in bordure // add central charge if charge is in bordure
coa.charges[0].charge = rw(charges.conventional); coa.charges[0].charge = rw(charges.conventional);
const charge = selectCharge(charges.single); const charge = selectCharge(charges.single);
const t = getTincture("charge", usedTinctures, coa.t1); const t = getTincture("charge", usedTinctures, coa.t1);
coa.charges.push({charge, t, p: "e"}); coa.charges.push({charge, t, p: "e"});
} else if (P(.8) && charge === "inescutcheon") { } else if (P(0.8) && charge === "inescutcheon") {
// add charge to inescutcheon // add charge to inescutcheon
const charge = selectCharge(charges.types); const charge = selectCharge(charges.types);
const t2 = getTincture("charge", [], t); const t2 = getTincture("charge", [], t);
coa.charges.push({charge, t: t2, p, size:.5}); coa.charges.push({charge, t: t2, p, size: 0.5});
} else if (division && !ordinary) { } else if (division && !ordinary) {
const allowCounter = !usedPattern && (!coa.line || coa.line === "straight"); const allowCounter = !usedPattern && (!coa.line || coa.line === "straight");
// dimidiation: second charge at division basic positons // dimidiation: second charge at division basic positons
if (P(.3) && ["perPale", "perFess"].includes(division) && coa.line === "straight") { if (P(0.3) && ["perPale", "perFess"].includes(division) && coa.line === "straight") {
coa.charges[0].divided = "field"; coa.charges[0].divided = "field";
if (P(.95)) { if (P(0.95)) {
const p2 = p === "e" || P(.5) ? "e" : rw(positions.divisions[division]); const p2 = p === "e" || P(0.5) ? "e" : rw(positions.divisions[division]);
const charge = selectCharge(charges.single); const charge = selectCharge(charges.single);
const t = getTincture("charge", usedTinctures, coa.division.t); const t = getTincture("charge", usedTinctures, coa.division.t);
coa.charges.push({charge, t, p: p2, divided: "division"}); coa.charges.push({charge, t, p: p2, divided: "division"});
} }
} } else if (allowCounter && P(0.4)) coa.charges[0].divided = "counter";
else if (allowCounter && P(.4)) coa.charges[0].divided = "counter"; // counterchanged, 40% // counterchanged, 40%
else if (["perPale", "perFess", "perBend", "perBendSinister"].includes(division) && P(.8)) { // place 2 charges in division standard positions else if (["perPale", "perFess", "perBend", "perBendSinister"].includes(division) && P(0.8)) {
const [p1, p2] = division === "perPale" ? ["p", "q"] : // place 2 charges in division standard positions
division === "perFess" ? ["k", "n"] : const [p1, p2] = division === "perPale" ? ["p", "q"] : division === "perFess" ? ["k", "n"] : division === "perBend" ? ["l", "m"] : ["j", "o"]; // perBendSinister
division === "perBend" ? ["l", "m"] :
["j", "o"]; // perBendSinister
coa.charges[0].p = p1; coa.charges[0].p = p1;
const charge = selectCharge(charges.single); const charge = selectCharge(charges.single);
const t = getTincture("charge", usedTinctures, coa.division.t); const t = getTincture("charge", usedTinctures, coa.division.t);
coa.charges.push({charge, t, p: p2}); coa.charges.push({charge, t, p: p2});
} } else if (["perCross", "perSaltire"].includes(division) && P(0.5)) {
else if (["perCross", "perSaltire"].includes(division) && P(.5)) { // place 4 charges in division standard positions // place 4 charges in division standard positions
const [p1, p2, p3, p4] = division === "perCross" ? ["j", "l", "m", "o"] : ["b", "d", "f", "h"]; const [p1, p2, p3, p4] = division === "perCross" ? ["j", "l", "m", "o"] : ["b", "d", "f", "h"];
coa.charges[0].p = p1; coa.charges[0].p = p1;
@ -338,8 +590,7 @@
const c4 = selectCharge(charges.single); const c4 = selectCharge(charges.single);
const t4 = getTincture("charge", [], coa.t1); const t4 = getTincture("charge", [], coa.t1);
coa.charges.push({charge: c2, t: t2, p: p2}, {charge: c3, t: t3, p: p3}, {charge: c4, t: t4, p: p4}); coa.charges.push({charge: c2, t: t2, p: p2}, {charge: c3, t: t3, p: p3}, {charge: c4, t: t4, p: p4});
} } else if (allowCounter && p.length > 1) coa.charges[0].divided = "counter"; // counterchanged, 40%
else if (allowCounter && p.length > 1) coa.charges[0].divided = "counter"; // counterchanged, 40%
} }
coa.charges.forEach(c => defineChargeAttributes(c)); coa.charges.forEach(c => defineChargeAttributes(c));
@ -351,8 +602,8 @@
c.p = [...new Set(c.p)].join(""); c.p = [...new Set(c.p)].join("");
// define orientation // define orientation
if (P(.02) && charges.sinister.includes(c.charge)) c.sinister = 1; if (P(0.02) && charges.sinister.includes(c.charge)) c.sinister = 1;
if (P(.02) && charges.reversed.includes(c.charge)) c.reversed = 1; if (P(0.02) && charges.reversed.includes(c.charge)) c.reversed = 1;
} }
} }
@ -380,7 +631,7 @@
if (!coa.charges) coa.charges = []; if (!coa.charges) coa.charges = [];
coa.charges.push({charge, t: t2, p: "y", size: 0.5}); coa.charges.push({charge, t: t2, p: "y", size: 0.5});
coa.ordinaries ? coa.ordinaries.push(canton) : coa.ordinaries = [canton]; coa.ordinaries ? coa.ordinaries.push(canton) : (coa.ordinaries = [canton]);
} }
function selectCharge(set) { function selectCharge(set) {
@ -390,14 +641,16 @@
// select tincture: element type (field, division, charge), used field tinctures, field type to follow RoT // select tincture: element type (field, division, charge), used field tinctures, field type to follow RoT
function getTincture(element, fields = [], RoT) { function getTincture(element, fields = [], RoT) {
const base = RoT ? RoT.includes("-") ? RoT.split("-")[1] : RoT : null; const base = RoT ? (RoT.includes("-") ? RoT.split("-")[1] : RoT) : null;
let type = rw(tinctures[element]); // metals, colours, stains, patterns let type = rw(tinctures[element]); // metals, colours, stains, patterns
if (RoT && type !== "patterns") type = getType(base) === "metals" ? "colours" : "metals"; // follow RoT if (RoT && type !== "patterns") type = getType(base) === "metals" ? "colours" : "metals"; // follow RoT
if (type === "metals" && fields.includes("or") && fields.includes("argent")) type = "colours"; // exclude metals overuse if (type === "metals" && fields.includes("or") && fields.includes("argent")) type = "colours"; // exclude metals overuse
let tincture = rw(tinctures[type]); let tincture = rw(tinctures[type]);
while (tincture === base || fields.includes(tincture)) {tincture = rw(tinctures[type]);} // follow RoT while (tincture === base || fields.includes(tincture)) {
tincture = rw(tinctures[type]);
} // follow RoT
if (type !== "patterns" && element !== "charge") usedTinctures.push(tincture); // add field tincture if (type !== "patterns" && element !== "charge") usedTinctures.push(tincture); // add field tincture
@ -425,39 +678,60 @@
if (Object.keys(tinctures.stains).includes(tincture)) return "stains"; if (Object.keys(tinctures.stains).includes(tincture)) return "stains";
else return "pattern"; else return "pattern";
} }
} }
function definePattern(pattern, element, size = "") { function definePattern(pattern, element, size = "") {
let t1 = null, t2 = null; let t1 = null,
if (P(.1)) size = "-small"; t2 = null;
else if (P(.1)) size = "-smaller"; if (P(0.1)) size = "-small";
else if (P(.01)) size = "-big"; else if (P(0.1)) size = "-smaller";
else if (P(.005)) size = "-smallest"; else if (P(0.01)) size = "-big";
else if (P(0.005)) size = "-smallest";
// apply standard tinctures // apply standard tinctures
if (P(.5) && ["vair", "vairInPale", "vairEnPointe"].includes(pattern)) {t1 = "azure"; t2 = "argent";} if (P(0.5) && ["vair", "vairInPale", "vairEnPointe"].includes(pattern)) {
else if (P(.8) && pattern === "ermine") {t1 = "argent"; t2 = "sable";} t1 = "azure";
else if (pattern === "pappellony") { t2 = "argent";
if (P(.2)) {t1 = "gules"; t2 = "or";} } else if (P(0.8) && pattern === "ermine") {
else if (P(.2)) {t1 = "argent"; t2 = "sable";} t1 = "argent";
else if (P(.2)) {t1 = "azure"; t2 = "argent";} t2 = "sable";
} else if (pattern === "pappellony") {
if (P(0.2)) {
t1 = "gules";
t2 = "or";
} else if (P(0.2)) {
t1 = "argent";
t2 = "sable";
} else if (P(0.2)) {
t1 = "azure";
t2 = "argent";
} }
else if (pattern === "masoned") { } else if (pattern === "masoned") {
if (P(.3)) {t1 = "gules"; t2 = "argent";} if (P(0.3)) {
else if (P(.3)) {t1 = "argent"; t2 = "sable";} t1 = "gules";
else if (P(.1)) {t1 = "or"; t2 = "sable";} t2 = "argent";
} else if (P(0.3)) {
t1 = "argent";
t2 = "sable";
} else if (P(0.1)) {
t1 = "or";
t2 = "sable";
} }
else if (pattern === "fretty") { } else if (pattern === "fretty") {
if (t2 === "sable" || P(.35)) {t1 = "argent"; t2 = "gules";} if (t2 === "sable" || P(0.35)) {
else if (P(.25)) {t1 = "sable"; t2 = "or";} t1 = "argent";
else if (P(.15)) {t1 = "gules"; t2 = "argent";} t2 = "gules";
} else if (P(0.25)) {
t1 = "sable";
t2 = "or";
} else if (P(0.15)) {
t1 = "gules";
t2 = "argent";
} }
else if (pattern === "semy") pattern += "_of_" + selectCharge(charges.semy); } else if (pattern === "semy") pattern += "_of_" + selectCharge(charges.semy);
if (!t1 || !t2) { if (!t1 || !t2) {
const startWithMetal = P(.7); const startWithMetal = P(0.7);
t1 = startWithMetal ? rw(tinctures.metals) : rw(tinctures.colours); t1 = startWithMetal ? rw(tinctures.metals) : rw(tinctures.colours);
t2 = startWithMetal ? rw(tinctures.colours) : rw(tinctures.metals); t2 = startWithMetal ? rw(tinctures.colours) : rw(tinctures.metals);
} }
@ -474,26 +748,28 @@
function replaceTincture(t, n) { function replaceTincture(t, n) {
const type = getType(t); const type = getType(t);
while (!n || n === t) {n = rw(tinctures[type]);} while (!n || n === t) {
n = rw(tinctures[type]);
}
return n; return n;
} }
function getSize(p, o = null, d = null) { function getSize(p, o = null, d = null) {
if (p === "e" && (o === "bordure" || o === "orle")) return 1.1; if (p === "e" && (o === "bordure" || o === "orle")) return 1.1;
if (p === "e") return 1.5; if (p === "e") return 1.5;
if (p === "jln" || p === "jlh") return .7; if (p === "jln" || p === "jlh") return 0.7;
if (p === "abcpqh" || p === "ez" || p === "be") return .5; if (p === "abcpqh" || p === "ez" || p === "be") return 0.5;
if (["a", "b", "c", "d", "f", "g", "h", "i", "bh", "df"].includes(p)) return .5; if (["a", "b", "c", "d", "f", "g", "h", "i", "bh", "df"].includes(p)) return 0.5;
if (["j", "l", "m", "o", "jlmo"].includes(p) && d === "perCross") return .6; if (["j", "l", "m", "o", "jlmo"].includes(p) && d === "perCross") return 0.6;
if (p.length > 10) return .18; // >10 (bordure) if (p.length > 10) return 0.18; // >10 (bordure)
if (p.length > 7) return .3; // 8, 9, 10 if (p.length > 7) return 0.3; // 8, 9, 10
if (p.length > 4) return .4; // 5, 6, 7 if (p.length > 4) return 0.4; // 5, 6, 7
if (p.length > 2) return .5; // 3, 4 if (p.length > 2) return 0.5; // 3, 4
return .7; // 1, 2 return 0.7; // 1, 2
} }
return coa; return coa;
} };
const getShield = function (culture, state) { const getShield = function (culture, state) {
const emblemShape = document.getElementById("emblemShape"); const emblemShape = document.getElementById("emblemShape");
@ -504,11 +780,10 @@
if (pack.cultures[culture].shield) return pack.cultures[culture].shield; if (pack.cultures[culture].shield) return pack.cultures[culture].shield;
console.error("Shield shape is not defined on culture level", pack.cultures[culture]); console.error("Shield shape is not defined on culture level", pack.cultures[culture]);
return "heater"; return "heater";
} };
const toString = coa => JSON.stringify(coa).replaceAll("#", "%23"); const toString = coa => JSON.stringify(coa).replaceAll("#", "%23");
const copy = coa => JSON.parse(JSON.stringify(coa)); const copy = coa => JSON.parse(JSON.stringify(coa));
return {generate, toString, copy, getShield, shields}; return {generate, toString, copy, getShield, shields};
})();
})));

File diff suppressed because it is too large Load diff

View file

@ -1,13 +1,10 @@
(function (global, factory) { "use strict";
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.Cultures = factory());
}(this, (function () {'use strict';
window.Cultures = (function () {
let cells; let cells;
const generate = function () { const generate = function () {
TIME && console.time('generateCultures'); TIME && console.time("generateCultures");
cells = pack.cells; cells = pack.cells;
cells.culture = new Uint16Array(cells.i.length); // cell cultures cells.culture = new Uint16Array(cells.i.length); // cell cultures
let count = Math.min(+culturesInput.value, +culturesSet.selectedOptions[0].dataset.max); let count = Math.min(+culturesInput.value, +culturesSet.selectedOptions[0].dataset.max);
@ -22,8 +19,14 @@
The climate is harsh and people cannot live in this world.<br> The climate is harsh and people cannot live in this world.<br>
No cultures, states and burgs will be created.<br> No cultures, states and burgs will be created.<br>
Please consider changing climate settings in the World Configurator`; Please consider changing climate settings in the World Configurator`;
$("#alert").dialog({resizable: false, title: "Extreme climate warning", $("#alert").dialog({
buttons: {Ok: function() {$(this).dialog("close");}} resizable: false,
title: "Extreme climate warning",
buttons: {
Ok: function () {
$(this).dialog("close");
}
}
}); });
return; return;
} else { } else {
@ -32,20 +35,26 @@
There are only ${populated.length} populated cells and it's insufficient livable area.<br> There are only ${populated.length} populated cells and it's insufficient livable area.<br>
Only ${count} out of ${culturesInput.value} requested cultures will be generated.<br> Only ${count} out of ${culturesInput.value} requested cultures will be generated.<br>
Please consider changing climate settings in the World Configurator`; Please consider changing climate settings in the World Configurator`;
$("#alert").dialog({resizable: false, title: "Extreme climate warning", $("#alert").dialog({
buttons: {Ok: function() {$(this).dialog("close");}} resizable: false,
title: "Extreme climate warning",
buttons: {
Ok: function () {
$(this).dialog("close");
}
}
}); });
} }
} }
const cultures = pack.cultures = selectCultures(count); const cultures = (pack.cultures = selectCultures(count));
const centers = d3.quadtree(); const centers = d3.quadtree();
const colors = getColors(count); const colors = getColors(count);
const emblemShape = document.getElementById("emblemShape").value; const emblemShape = document.getElementById("emblemShape").value;
const codes = []; const codes = [];
cultures.forEach(function (c, i) { cultures.forEach(function (c, i) {
const cell = c.center = placeCenter(c.sort ? c.sort : (i) => cells.s[i]); const cell = (c.center = placeCenter(c.sort ? c.sort : i => cells.s[i]));
centers.add(cells.p[cell]); centers.add(cells.p[cell]);
c.i = i + 1; c.i = i + 1;
delete c.odd; delete c.odd;
@ -61,10 +70,14 @@
}); });
function placeCenter(v) { function placeCenter(v) {
let c, spacing = (graphWidth + graphHeight) / 2 / count; let c,
const sorted = [...populated].sort((a, b) => v(b) - v(a)), max = Math.floor(sorted.length / 2); spacing = (graphWidth + graphHeight) / 2 / count;
do {c = sorted[biased(0, max, 5)]; spacing *= .9;} const sorted = [...populated].sort((a, b) => v(b) - v(a)),
while (centers.find(cells.p[c][0], cells.p[c][1], spacing) !== undefined); max = Math.floor(sorted.length / 2);
do {
c = sorted[biased(0, max, 5)];
spacing *= 0.9;
} while (centers.find(cells.p[c][0], cells.p[c][1], spacing) !== undefined);
return c; return c;
} }
@ -77,7 +90,7 @@
nameBases = Names.getNameBases(); nameBases = Names.getNameBases();
} }
cultures.forEach(c => c.base = c.base % nameBases.length); cultures.forEach(c => (c.base = c.base % nameBases.length));
function selectCultures(c) { function selectCultures(c) {
let def = getDefault(c); let def = getDefault(c);
@ -91,7 +104,7 @@
do { do {
rnd = rand(def.length - 1); rnd = rand(def.length - 1);
culture = def[rnd]; culture = def[rnd];
} while (!P(culture.odd)) } while (!P(culture.odd));
cultures.push(culture); cultures.push(culture);
def.splice(rnd, 1); def.splice(rnd, 1);
} }
@ -103,8 +116,8 @@
if (cells.h[i] < 70 && [1, 2, 4].includes(cells.biome[i])) return "Nomadic"; // high penalty in forest biomes and near coastline if (cells.h[i] < 70 && [1, 2, 4].includes(cells.biome[i])) return "Nomadic"; // high penalty in forest biomes and near coastline
if (cells.h[i] > 50) return "Highland"; // no penalty for hills and moutains, high for other elevations if (cells.h[i] > 50) return "Highland"; // no penalty for hills and moutains, high for other elevations
const f = pack.features[cells.f[cells.haven[i]]]; // opposite feature const f = pack.features[cells.f[cells.haven[i]]]; // opposite feature
if (f.type === "lake" && f.cells > 5) return "Lake" // low water cross penalty and high for growth not along coastline if (f.type === "lake" && f.cells > 5) return "Lake"; // low water cross penalty and high for growth not along coastline
if (cells.harbor[i] && f.type !== "lake" && P(.1) || (cells.harbor[i] === 1 && P(.6)) || (pack.features[cells.f[i]].group === "isle" && P(.4))) return "Naval"; // low water cross penalty and high for non-along-coastline growth if ((cells.harbor[i] && f.type !== "lake" && P(0.1)) || (cells.harbor[i] === 1 && P(0.6)) || (pack.features[cells.f[i]].group === "isle" && P(0.4))) return "Naval"; // low water cross penalty and high for non-along-coastline growth
if (cells.r[i] && cells.fl[i] > 100) return "River"; // no River cross penalty, penalty for non-River growth if (cells.r[i] && cells.fl[i] > 100) return "River"; // no River cross penalty, penalty for non-River growth
if (cells.t[i] > 2 && [3, 7, 8, 9, 10, 12].includes(cells.biome[i])) return "Hunting"; // high penalty in non-native biomes if (cells.t[i] > 2 && [3, 7, 8, 9, 10, 12].includes(cells.biome[i])) return "Hunting"; // high penalty in non-native biomes
return "Generic"; return "Generic";
@ -112,17 +125,17 @@
function defineCultureExpansionism(type) { function defineCultureExpansionism(type) {
let base = 1; // Generic let base = 1; // Generic
if (type === "Lake") base = .8; else if (type === "Lake") base = 0.8;
if (type === "Naval") base = 1.5; else else if (type === "Naval") base = 1.5;
if (type === "River") base = .9; else else if (type === "River") base = 0.9;
if (type === "Nomadic") base = 1.5; else else if (type === "Nomadic") base = 1.5;
if (type === "Hunting") base = .7; else else if (type === "Hunting") base = 0.7;
if (type === "Highland") base = 1.2; else if (type === "Highland") base = 1.2;
return rn((Math.random() * powerInput.value / 2 + 1) * base, 1); return rn(((Math.random() * powerInput.value) / 2 + 1) * base, 1);
} }
TIME && console.timeEnd('generateCultures'); TIME && console.timeEnd("generateCultures");
} };
const add = function (center) { const add = function (center) {
const defaultCultures = getDefault(); const defaultCultures = getDefault();
@ -139,7 +152,10 @@
name = Names.getCulture(culture, 5, 8, ""); name = Names.getCulture(culture, 5, 8, "");
base = pack.cultures[culture].base; base = pack.cultures[culture].base;
} }
const code = abbreviate(name, pack.cultures.map(c => c.code)); const code = abbreviate(
name,
pack.cultures.map(c => c.code)
);
const i = pack.cultures.length; const i = pack.cultures.length;
const color = d3.color(d3.scaleSequential(d3.interpolateRainbow)(Math.random())).hex(); const color = d3.color(d3.scaleSequential(d3.interpolateRainbow)(Math.random())).hex();
@ -149,15 +165,23 @@
if (emblemShape === "random") shield = getRandomShield(); if (emblemShape === "random") shield = getRandomShield();
pack.cultures.push({name, color, base, center, i, expansionism: 1, type: "Generic", cells: 0, area: 0, rural: 0, urban: 0, origin: 0, code, shield}); pack.cultures.push({name, color, base, center, i, expansionism: 1, type: "Generic", cells: 0, area: 0, rural: 0, urban: 0, origin: 0, code, shield});
} };
const getDefault = function (count) { const getDefault = function (count) {
// generic sorting functions // generic sorting functions
const cells = pack.cells, s = cells.s, sMax = d3.max(s), t = cells.t, h = cells.h, temp = grid.cells.temp; const cells = pack.cells,
const n = cell => Math.ceil(s[cell] / sMax * 3) // normalized cell score s = cells.s,
const td = (cell, goal) => {const d = Math.abs(temp[cells.g[cell]] - goal); return d ? d+1 : 1;} // temperature difference fee sMax = d3.max(s),
const bd = (cell, biomes, fee = 4) => biomes.includes(cells.biome[cell]) ? 1 : fee; // biome difference fee t = cells.t,
const sf = (cell, fee = 4) => cells.haven[cell] && pack.features[cells.f[cells.haven[cell]]].type !== "lake" ? 1 : fee; // not on sea coast fee h = cells.h,
temp = grid.cells.temp;
const n = cell => Math.ceil((s[cell] / sMax) * 3); // normalized cell score
const td = (cell, goal) => {
const d = Math.abs(temp[cells.g[cell]] - goal);
return d ? d + 1 : 1;
}; // temperature difference fee
const bd = (cell, biomes, fee = 4) => (biomes.includes(cells.biome[cell]) ? 1 : fee); // biome difference fee
const sf = (cell, fee = 4) => (cells.haven[cell] && pack.features[cells.f[cells.haven[cell]]].type !== "lake" ? 1 : fee); // not on sea coast fee
if (culturesSet.value === "european") { if (culturesSet.value === "european") {
return [ return [
@ -166,16 +190,16 @@
{name: "Luari", base: 2, odd: 1, sort: i => n(i) / td(i, 12) / bd(i, [6, 8]), shield: "french"}, {name: "Luari", base: 2, odd: 1, sort: i => n(i) / td(i, 12) / bd(i, [6, 8]), shield: "french"},
{name: "Tallian", base: 3, odd: 1, sort: i => n(i) / td(i, 15), shield: "horsehead"}, {name: "Tallian", base: 3, odd: 1, sort: i => n(i) / td(i, 15), shield: "horsehead"},
{name: "Astellian", base: 4, odd: 1, sort: i => n(i) / td(i, 16), shield: "spanish"}, {name: "Astellian", base: 4, odd: 1, sort: i => n(i) / td(i, 16), shield: "spanish"},
{name:"Slovan", base:5, odd:1, sort: i => n(i) / td(i, 6) * t[i], shield:"polish"}, {name: "Slovan", base: 5, odd: 1, sort: i => (n(i) / td(i, 6)) * t[i], shield: "polish"},
{name: "Norse", base: 6, odd: 1, sort: i => n(i) / td(i, 5), shield: "heater"}, {name: "Norse", base: 6, odd: 1, sort: i => n(i) / td(i, 5), shield: "heater"},
{name:"Elladan", base:7, odd:1, sort: i => n(i) / td(i, 18) * h[i], shield:"boeotian"}, {name: "Elladan", base: 7, odd: 1, sort: i => (n(i) / td(i, 18)) * h[i], shield: "boeotian"},
{name:"Romian", base:8, odd:.2, sort: i => n(i) / td(i, 15) / t[i], shield:"roman"}, {name: "Romian", base: 8, odd: 0.2, sort: i => n(i) / td(i, 15) / t[i], shield: "roman"},
{name:"Soumi", base:9, odd:1, sort: i => n(i) / td(i, 5) / bd(i, [9]) * t[i], shield:"pavise"}, {name: "Soumi", base: 9, odd: 1, sort: i => (n(i) / td(i, 5) / bd(i, [9])) * t[i], shield: "pavise"},
{name: "Portuzian", base: 13, odd: 1, sort: i => n(i) / td(i, 17) / sf(i), shield: "renaissance"}, {name: "Portuzian", base: 13, odd: 1, sort: i => n(i) / td(i, 17) / sf(i), shield: "renaissance"},
{name:"Vengrian", base: 15, odd:1, sort: i => n(i) / td(i, 11) / bd(i, [4]) * t[i], shield:"horsehead2"}, {name: "Vengrian", base: 15, odd: 1, sort: i => (n(i) / td(i, 11) / bd(i, [4])) * t[i], shield: "horsehead2"},
{name:"Turchian", base: 16, odd:.05, sort: i => n(i) / td(i, 14), shield:"round"}, {name: "Turchian", base: 16, odd: 0.05, sort: i => n(i) / td(i, 14), shield: "round"},
{name:"Euskati", base: 20, odd:.05, sort: i => n(i) / td(i, 15) * h[i], shield:"oldFrench"}, {name: "Euskati", base: 20, odd: 0.05, sort: i => (n(i) / td(i, 15)) * h[i], shield: "oldFrench"},
{name:"Keltan", base: 22, odd:.05, sort: i => n(i) / td(i, 11) / bd(i, [6, 8]) * t[i], shield:"oval"} {name: "Keltan", base: 22, odd: 0.05, sort: i => (n(i) / td(i, 11) / bd(i, [6, 8])) * t[i], shield: "oval"}
]; ];
} }
@ -185,15 +209,15 @@
{name: "Hantzu", base: 11, odd: 1, sort: i => n(i) / td(i, 13), shield: "banner"}, {name: "Hantzu", base: 11, odd: 1, sort: i => n(i) / td(i, 13), shield: "banner"},
{name: "Yamoto", base: 12, odd: 1, sort: i => n(i) / td(i, 15) / t[i], shield: "round"}, {name: "Yamoto", base: 12, odd: 1, sort: i => n(i) / td(i, 15) / t[i], shield: "round"},
{name: "Turchian", base: 16, odd: 1, sort: i => n(i) / td(i, 12), shield: "round"}, {name: "Turchian", base: 16, odd: 1, sort: i => n(i) / td(i, 12), shield: "round"},
{name:"Berberan", base: 17, odd:.2, sort: i => n(i) / td(i, 19) / bd(i, [1, 2, 3], 7) * t[i], shield:"oval"}, {name: "Berberan", base: 17, odd: 0.2, sort: i => (n(i) / td(i, 19) / bd(i, [1, 2, 3], 7)) * t[i], shield: "oval"},
{name:"Eurabic", base: 18, odd:1, sort: i => n(i) / td(i, 26) / bd(i, [1, 2], 7) * t[i], shield:"oval"}, {name: "Eurabic", base: 18, odd: 1, sort: i => (n(i) / td(i, 26) / bd(i, [1, 2], 7)) * t[i], shield: "oval"},
{name:"Efratic", base: 23, odd:.1, sort: i => n(i) / td(i, 22) * t[i], shield:"round"}, {name: "Efratic", base: 23, odd: 0.1, sort: i => (n(i) / td(i, 22)) * t[i], shield: "round"},
{name:"Tehrani", base: 24, odd:1, sort: i => n(i) / td(i, 18) * h[i], shield:"round"}, {name: "Tehrani", base: 24, odd: 1, sort: i => (n(i) / td(i, 18)) * h[i], shield: "round"},
{name:"Maui", base: 25, odd:.2, sort: i => n(i) / td(i, 24) / sf(i) / t[i], shield:"vesicaPiscis"}, {name: "Maui", base: 25, odd: 0.2, sort: i => n(i) / td(i, 24) / sf(i) / t[i], shield: "vesicaPiscis"},
{name:"Carnatic", base: 26, odd:.5, sort: i => n(i) / td(i, 26), shield:"round"}, {name: "Carnatic", base: 26, odd: 0.5, sort: i => n(i) / td(i, 26), shield: "round"},
{name:"Vietic", base: 29, odd:.8, sort: i => n(i) / td(i, 25) / bd(i, [7], 7) / t[i], shield:"banner"}, {name: "Vietic", base: 29, odd: 0.8, sort: i => n(i) / td(i, 25) / bd(i, [7], 7) / t[i], shield: "banner"},
{name:"Guantzu", base:30, odd:.5, sort: i => n(i) / td(i, 17), shield:"banner"}, {name: "Guantzu", base: 30, odd: 0.5, sort: i => n(i) / td(i, 17), shield: "banner"},
{name:"Ulus", base:31, odd:1, sort: i => n(i) / td(i, 5) / bd(i, [2, 4, 10], 7) * t[i], shield:"banner"} {name: "Ulus", base: 31, odd: 1, sort: i => (n(i) / td(i, 5) / bd(i, [2, 4, 10], 7)) * t[i], shield: "banner"}
]; ];
} }
@ -219,41 +243,41 @@
{name: "Roman", base: 8, odd: 1, sort: i => n(i) / td(i, 15) / sf(i), shield: "roman"}, // Roman {name: "Roman", base: 8, odd: 1, sort: i => n(i) / td(i, 15) / sf(i), shield: "roman"}, // Roman
{name: "Roman", base: 8, odd: 1, sort: i => n(i) / td(i, 16) / sf(i), shield: "roman"}, // Roman {name: "Roman", base: 8, odd: 1, sort: i => n(i) / td(i, 16) / sf(i), shield: "roman"}, // Roman
{name: "Roman", base: 8, odd: 1, sort: i => n(i) / td(i, 17) / t[i], shield: "roman"}, // Roman {name: "Roman", base: 8, odd: 1, sort: i => n(i) / td(i, 17) / t[i], shield: "roman"}, // Roman
{name:"Hellenic", base:7, odd:1, sort: i => n(i) / td(i, 18) / sf(i) * h[i], shield:"boeotian"}, // Greek {name: "Hellenic", base: 7, odd: 1, sort: i => (n(i) / td(i, 18) / sf(i)) * h[i], shield: "boeotian"}, // Greek
{name:"Hellenic", base:7, odd:1, sort: i => n(i) / td(i, 19) / sf(i) * h[i], shield:"boeotian"}, // Greek {name: "Hellenic", base: 7, odd: 1, sort: i => (n(i) / td(i, 19) / sf(i)) * h[i], shield: "boeotian"}, // Greek
{name:"Macedonian", base:7, odd:.5, sort: i => n(i) / td(i, 12) * h[i], shield:"round"}, // Greek {name: "Macedonian", base: 7, odd: 0.5, sort: i => (n(i) / td(i, 12)) * h[i], shield: "round"}, // Greek
{name:"Celtic", base:22, odd:1, sort: i => n(i) / td(i, 11) ** .5 / bd(i, [6, 8]), shield:"round"}, {name: "Celtic", base: 22, odd: 1, sort: i => n(i) / td(i, 11) ** 0.5 / bd(i, [6, 8]), shield: "round"},
{name:"Germanic", base:0, odd:1, sort: i => n(i) / td(i, 10) ** .5 / bd(i, [6, 8]), shield:"round"}, {name: "Germanic", base: 0, odd: 1, sort: i => n(i) / td(i, 10) ** 0.5 / bd(i, [6, 8]), shield: "round"},
{name:"Persian", base:24, odd:.8, sort: i => n(i) / td(i, 18) * h[i], shield:"oval"}, // Iranian {name: "Persian", base: 24, odd: 0.8, sort: i => (n(i) / td(i, 18)) * h[i], shield: "oval"}, // Iranian
{name:"Scythian", base:24, odd:.5, sort: i => n(i) / td(i, 11) ** .5 / bd(i, [4]), shield:"round"}, // Iranian {name: "Scythian", base: 24, odd: 0.5, sort: i => n(i) / td(i, 11) ** 0.5 / bd(i, [4]), shield: "round"}, // Iranian
{name:"Cantabrian", base: 20, odd:.5, sort: i => n(i) / td(i, 16) * h[i], shield:"oval"}, // Basque {name: "Cantabrian", base: 20, odd: 0.5, sort: i => (n(i) / td(i, 16)) * h[i], shield: "oval"}, // Basque
{name:"Estian", base: 9, odd:.2, sort: i => n(i) / td(i, 5) * t[i], shield:"pavise"}, // Finnic {name: "Estian", base: 9, odd: 0.2, sort: i => (n(i) / td(i, 5)) * t[i], shield: "pavise"}, // Finnic
{name:"Carthaginian", base: 17, odd:.3, sort: i => n(i) / td(i, 19) / sf(i), shield:"oval"}, // Berber {name: "Carthaginian", base: 17, odd: 0.3, sort: i => n(i) / td(i, 19) / sf(i), shield: "oval"}, // Berber
{name:"Mesopotamian", base: 23, odd:.2, sort: i => n(i) / td(i, 22) / bd(i, [1, 2, 3]), shield:"oval"} // Mesopotamian {name: "Mesopotamian", base: 23, odd: 0.2, sort: i => n(i) / td(i, 22) / bd(i, [1, 2, 3]), shield: "oval"} // Mesopotamian
]; ];
} }
if (culturesSet.value === "highFantasy") { if (culturesSet.value === "highFantasy") {
return [ return [
// fantasy races // fantasy races
{name:"Quenian (Elfish)", base: 33, odd:1, sort: i => n(i) / bd(i, [6,7,8,9], 10) * t[i], shield:"gondor"}, // Elves {name: "Quenian (Elfish)", base: 33, odd: 1, sort: i => (n(i) / bd(i, [6, 7, 8, 9], 10)) * t[i], shield: "gondor"}, // Elves
{name:"Eldar (Elfish)", base: 33, odd:1, sort: i => n(i) / bd(i, [6,7,8,9], 10) * t[i], shield:"noldor"}, // Elves {name: "Eldar (Elfish)", base: 33, odd: 1, sort: i => (n(i) / bd(i, [6, 7, 8, 9], 10)) * t[i], shield: "noldor"}, // Elves
{name:"Trow (Dark Elfish)", base: 34, odd:.9, sort: i => n(i) / bd(i, [7,8,9,12], 10) * t[i], shield:"hessen"}, // Dark Elves {name: "Trow (Dark Elfish)", base: 34, odd: 0.9, sort: i => (n(i) / bd(i, [7, 8, 9, 12], 10)) * t[i], shield: "hessen"}, // Dark Elves
{name:"Lothian (Dark Elfish)", base: 34, odd:.3, sort: i => n(i) / bd(i, [7,8,9,12], 10) * t[i], shield:"wedged"}, // Dark Elves {name: "Lothian (Dark Elfish)", base: 34, odd: 0.3, sort: i => (n(i) / bd(i, [7, 8, 9, 12], 10)) * t[i], shield: "wedged"}, // Dark Elves
{name: "Dunirr (Dwarven)", base: 35, odd: 1, sort: i => n(i) + h[i], shield: "ironHills"}, // Dwarfs {name: "Dunirr (Dwarven)", base: 35, odd: 1, sort: i => n(i) + h[i], shield: "ironHills"}, // Dwarfs
{name: "Khazadur (Dwarven)", base: 35, odd: 1, sort: i => n(i) + h[i], shield: "erebor"}, // Dwarfs {name: "Khazadur (Dwarven)", base: 35, odd: 1, sort: i => n(i) + h[i], shield: "erebor"}, // Dwarfs
{name: "Kobold (Goblin)", base: 36, odd: 1, sort: i => t[i] - s[i], shield: "moriaOrc"}, // Goblin {name: "Kobold (Goblin)", base: 36, odd: 1, sort: i => t[i] - s[i], shield: "moriaOrc"}, // Goblin
{name: "Uruk (Orkish)", base: 37, odd: 1, sort: i => h[i] * t[i], shield: "urukHai"}, // Orc {name: "Uruk (Orkish)", base: 37, odd: 1, sort: i => h[i] * t[i], shield: "urukHai"}, // Orc
{name:"Ugluk (Orkish)", base: 37, odd:.5, sort: i => h[i] * t[i] / bd(i, [1,2,10,11]), shield:"moriaOrc"}, // Orc {name: "Ugluk (Orkish)", base: 37, odd: 0.5, sort: i => (h[i] * t[i]) / bd(i, [1, 2, 10, 11]), shield: "moriaOrc"}, // Orc
{name:"Yotunn (Giants)", base: 38, odd:.7, sort: i => td(i, -10), shield:"pavise"}, // Giant {name: "Yotunn (Giants)", base: 38, odd: 0.7, sort: i => td(i, -10), shield: "pavise"}, // Giant
{name:"Rake (Drakonic)", base: 39, odd:.7, sort: i => -s[i], shield:"fantasy2"}, // Draconic {name: "Rake (Drakonic)", base: 39, odd: 0.7, sort: i => -s[i], shield: "fantasy2"}, // Draconic
{name:"Arago (Arachnid)", base: 40, odd:.7, sort: i => t[i] - s[i], shield:"horsehead2"}, // Arachnid {name: "Arago (Arachnid)", base: 40, odd: 0.7, sort: i => t[i] - s[i], shield: "horsehead2"}, // Arachnid
{name:"Aj'Snaga (Serpents)", base: 41, odd:.7, sort: i => n(i) / bd(i, [12], 10), shield:"fantasy1"}, // Serpents {name: "Aj'Snaga (Serpents)", base: 41, odd: 0.7, sort: i => n(i) / bd(i, [12], 10), shield: "fantasy1"}, // Serpents
// fantasy human // fantasy human
{name: "Anor (Human)", base: 32, odd: 1, sort: i => n(i) / td(i, 10), shield: "fantasy5"}, {name: "Anor (Human)", base: 32, odd: 1, sort: i => n(i) / td(i, 10), shield: "fantasy5"},
{name: "Dail (Human)", base: 32, odd: 1, sort: i => n(i) / td(i, 13), shield: "roman"}, {name: "Dail (Human)", base: 32, odd: 1, sort: i => n(i) / td(i, 13), shield: "roman"},
{name: "Rohand (Human)", base: 16, odd: 1, sort: i => n(i) / td(i, 16), shield: "round"}, {name: "Rohand (Human)", base: 16, odd: 1, sort: i => n(i) / td(i, 16), shield: "round"},
{name:"Dulandir (Human)", base:31, odd:1, sort: i => n(i) / td(i, 5) / bd(i, [2, 4, 10], 7) * t[i], shield:"easterling"}, {name: "Dulandir (Human)", base: 31, odd: 1, sort: i => (n(i) / td(i, 5) / bd(i, [2, 4, 10], 7)) * t[i], shield: "easterling"}
]; ];
} }
@ -267,87 +291,87 @@
{name: "Mercian", base: 1, odd: 1, sort: i => n(i) / td(i, 9), shield: "heater"}, {name: "Mercian", base: 1, odd: 1, sort: i => n(i) / td(i, 9), shield: "heater"},
{name: "Kentian", base: 1, odd: 1, sort: i => n(i) / td(i, 12), shield: "heater"}, {name: "Kentian", base: 1, odd: 1, sort: i => n(i) / td(i, 12), shield: "heater"},
// rare real-world western // rare real-world western
{name:"Norse", base:6, odd:.7, sort: i => n(i) / td(i, 5) / sf(i), shield:"oldFrench"}, {name: "Norse", base: 6, odd: 0.7, sort: i => n(i) / td(i, 5) / sf(i), shield: "oldFrench"},
{name:"Schwarzen", base:0, odd:.3, sort: i => n(i) / td(i, 10) / bd(i, [6, 8]), shield:"gonfalon"}, {name: "Schwarzen", base: 0, odd: 0.3, sort: i => n(i) / td(i, 10) / bd(i, [6, 8]), shield: "gonfalon"},
{name:"Luarian", base:2, odd:.3, sort: i => n(i) / td(i, 12) / bd(i, [6, 8]), shield:"oldFrench"}, {name: "Luarian", base: 2, odd: 0.3, sort: i => n(i) / td(i, 12) / bd(i, [6, 8]), shield: "oldFrench"},
{name:"Hetallian", base:3, odd:.3, sort: i => n(i) / td(i, 15), shield:"oval"}, {name: "Hetallian", base: 3, odd: 0.3, sort: i => n(i) / td(i, 15), shield: "oval"},
{name:"Astellian", base:4, odd:.3, sort: i => n(i) / td(i, 16), shield:"spanish"}, {name: "Astellian", base: 4, odd: 0.3, sort: i => n(i) / td(i, 16), shield: "spanish"},
// rare real-world exotic // rare real-world exotic
{name:"Kiswaili", base:28, odd:.05, sort: i => n(i) / td(i, 29) / bd(i, [1, 3, 5, 7]), shield:"vesicaPiscis"}, {name: "Kiswaili", base: 28, odd: 0.05, sort: i => n(i) / td(i, 29) / bd(i, [1, 3, 5, 7]), shield: "vesicaPiscis"},
{name:"Yoruba", base:21, odd:.05, sort: i => n(i) / td(i, 15) / bd(i, [5, 7]), shield:"vesicaPiscis"}, {name: "Yoruba", base: 21, odd: 0.05, sort: i => n(i) / td(i, 15) / bd(i, [5, 7]), shield: "vesicaPiscis"},
{name:"Koryo", base:10, odd:.05, sort: i => n(i) / td(i, 12) / t[i], shield:"round"}, {name: "Koryo", base: 10, odd: 0.05, sort: i => n(i) / td(i, 12) / t[i], shield: "round"},
{name:"Hantzu", base:11, odd:.05, sort: i => n(i) / td(i, 13), shield:"banner"}, {name: "Hantzu", base: 11, odd: 0.05, sort: i => n(i) / td(i, 13), shield: "banner"},
{name:"Yamoto", base:12, odd:.05, sort: i => n(i) / td(i, 15) / t[i], shield:"round"}, {name: "Yamoto", base: 12, odd: 0.05, sort: i => n(i) / td(i, 15) / t[i], shield: "round"},
{name:"Guantzu", base:30, odd:.05, sort: i => n(i) / td(i, 17), shield:"banner"}, {name: "Guantzu", base: 30, odd: 0.05, sort: i => n(i) / td(i, 17), shield: "banner"},
{name:"Ulus", base:31, odd:.05, sort: i => n(i) / td(i, 5) / bd(i, [2, 4, 10], 7) * t[i], shield:"banner"}, {name: "Ulus", base: 31, odd: 0.05, sort: i => (n(i) / td(i, 5) / bd(i, [2, 4, 10], 7)) * t[i], shield: "banner"},
{name:"Turan", base: 16, odd:.05, sort: i => n(i) / td(i, 12), shield:"round"}, {name: "Turan", base: 16, odd: 0.05, sort: i => n(i) / td(i, 12), shield: "round"},
{name:"Berberan", base: 17, odd:.05, sort: i => n(i) / td(i, 19) / bd(i, [1, 2, 3], 7) * t[i], shield:"round"}, {name: "Berberan", base: 17, odd: 0.05, sort: i => (n(i) / td(i, 19) / bd(i, [1, 2, 3], 7)) * t[i], shield: "round"},
{name:"Eurabic", base: 18, odd:.05, sort: i => n(i) / td(i, 26) / bd(i, [1, 2], 7) * t[i], shield:"round"}, {name: "Eurabic", base: 18, odd: 0.05, sort: i => (n(i) / td(i, 26) / bd(i, [1, 2], 7)) * t[i], shield: "round"},
{name:"Slovan", base:5, odd:.05, sort: i => n(i) / td(i, 6) * t[i], shield:"round"}, {name: "Slovan", base: 5, odd: 0.05, sort: i => (n(i) / td(i, 6)) * t[i], shield: "round"},
{name:"Keltan", base: 22, odd:.1, sort: i => n(i) / td(i, 11) ** .5 / bd(i, [6, 8]), shield:"vesicaPiscis"}, {name: "Keltan", base: 22, odd: 0.1, sort: i => n(i) / td(i, 11) ** 0.5 / bd(i, [6, 8]), shield: "vesicaPiscis"},
{name:"Elladan", base:7, odd:.2, sort: i => n(i) / td(i, 18) / sf(i) * h[i], shield:"boeotian"}, {name: "Elladan", base: 7, odd: 0.2, sort: i => (n(i) / td(i, 18) / sf(i)) * h[i], shield: "boeotian"},
{name:"Romian", base:8, odd:.2, sort: i => n(i) / td(i, 14) / t[i], shield:"roman"}, {name: "Romian", base: 8, odd: 0.2, sort: i => n(i) / td(i, 14) / t[i], shield: "roman"},
// fantasy races // fantasy races
{name:"Eldar", base: 33, odd:.5, sort: i => n(i) / bd(i, [6,7,8,9], 10) * t[i], shield:"fantasy5"}, // Elves {name: "Eldar", base: 33, odd: 0.5, sort: i => (n(i) / bd(i, [6, 7, 8, 9], 10)) * t[i], shield: "fantasy5"}, // Elves
{name:"Trow", base: 34, odd:.8, sort: i => n(i) / bd(i, [7,8,9,12], 10) * t[i], shield:"hessen"}, // Dark Elves {name: "Trow", base: 34, odd: 0.8, sort: i => (n(i) / bd(i, [7, 8, 9, 12], 10)) * t[i], shield: "hessen"}, // Dark Elves
{name:"Durinn", base: 35, odd:.8, sort: i => n(i) + h[i], shield:"erebor"}, // Dwarven {name: "Durinn", base: 35, odd: 0.8, sort: i => n(i) + h[i], shield: "erebor"}, // Dwarven
{name:"Kobblin", base: 36, odd:.8, sort: i => t[i] - s[i], shield:"moriaOrc"}, // Goblin {name: "Kobblin", base: 36, odd: 0.8, sort: i => t[i] - s[i], shield: "moriaOrc"}, // Goblin
{name:"Uruk", base: 37, odd:.8, sort: i => h[i] * t[i] / bd(i, [1,2,10,11]), shield:"urukHai"}, // Orc {name: "Uruk", base: 37, odd: 0.8, sort: i => (h[i] * t[i]) / bd(i, [1, 2, 10, 11]), shield: "urukHai"}, // Orc
{name:"Yotunn", base: 38, odd:.8, sort: i => td(i, -10), shield:"pavise"}, // Giant {name: "Yotunn", base: 38, odd: 0.8, sort: i => td(i, -10), shield: "pavise"}, // Giant
{name:"Drake", base: 39, odd:.9, sort: i => -s[i], shield:"fantasy2"}, // Draconic {name: "Drake", base: 39, odd: 0.9, sort: i => -s[i], shield: "fantasy2"}, // Draconic
{name:"Rakhnid", base: 40, odd:.9, sort: i => t[i] - s[i], shield:"horsehead2"}, // Arachnid {name: "Rakhnid", base: 40, odd: 0.9, sort: i => t[i] - s[i], shield: "horsehead2"}, // Arachnid
{name:"Aj'Snaga", base: 41, odd:.9, sort: i => n(i) / bd(i, [12], 10), shield:"fantasy1"}, // Serpents {name: "Aj'Snaga", base: 41, odd: 0.9, sort: i => n(i) / bd(i, [12], 10), shield: "fantasy1"} // Serpents
] ];
} }
if (culturesSet.value === "random") { if (culturesSet.value === "random") {
return d3.range(count).map(function () { return d3.range(count).map(function () {
const rnd = rand(nameBases.length - 1); const rnd = rand(nameBases.length - 1);
const name = Names.getBaseShort(rnd); const name = Names.getBaseShort(rnd);
return {name, base:rnd, odd:1, shield:getRandomShield()} return {name, base: rnd, odd: 1, shield: getRandomShield()};
}); });
} }
// all-world // all-world
return [ return [
{name:"Shwazen", base:0, odd:.7, sort: i => n(i) / td(i, 10) / bd(i, [6, 8]), shield:"hessen"}, {name: "Shwazen", base: 0, odd: 0.7, sort: i => n(i) / td(i, 10) / bd(i, [6, 8]), shield: "hessen"},
{name: "Angshire", base: 1, odd: 1, sort: i => n(i) / td(i, 10) / sf(i), shield: "heater"}, {name: "Angshire", base: 1, odd: 1, sort: i => n(i) / td(i, 10) / sf(i), shield: "heater"},
{name:"Luari", base:2, odd:.6, sort: i => n(i) / td(i, 12) / bd(i, [6, 8]), shield:"oldFrench"}, {name: "Luari", base: 2, odd: 0.6, sort: i => n(i) / td(i, 12) / bd(i, [6, 8]), shield: "oldFrench"},
{name:"Tallian", base:3, odd:.6, sort: i => n(i) / td(i, 15), shield:"horsehead2"}, {name: "Tallian", base: 3, odd: 0.6, sort: i => n(i) / td(i, 15), shield: "horsehead2"},
{name:"Astellian", base:4, odd:.6, sort: i => n(i) / td(i, 16), shield:"spanish"}, {name: "Astellian", base: 4, odd: 0.6, sort: i => n(i) / td(i, 16), shield: "spanish"},
{name:"Slovan", base:5, odd:.7, sort: i => n(i) / td(i, 6) * t[i], shield:"round"}, {name: "Slovan", base: 5, odd: 0.7, sort: i => (n(i) / td(i, 6)) * t[i], shield: "round"},
{name:"Norse", base:6, odd:.7, sort: i => n(i) / td(i, 5), shield:"heater"}, {name: "Norse", base: 6, odd: 0.7, sort: i => n(i) / td(i, 5), shield: "heater"},
{name:"Elladan", base:7, odd:.7, sort: i => n(i) / td(i, 18) * h[i], shield:"boeotian"}, {name: "Elladan", base: 7, odd: 0.7, sort: i => (n(i) / td(i, 18)) * h[i], shield: "boeotian"},
{name:"Romian", base:8, odd:.7, sort: i => n(i) / td(i, 15), shield:"roman"}, {name: "Romian", base: 8, odd: 0.7, sort: i => n(i) / td(i, 15), shield: "roman"},
{name:"Soumi", base:9, odd:.3, sort: i => n(i) / td(i, 5) / bd(i, [9]) * t[i], shield:"pavise"}, {name: "Soumi", base: 9, odd: 0.3, sort: i => (n(i) / td(i, 5) / bd(i, [9])) * t[i], shield: "pavise"},
{name:"Koryo", base:10, odd:.1, sort: i => n(i) / td(i, 12) / t[i], shield:"round"}, {name: "Koryo", base: 10, odd: 0.1, sort: i => n(i) / td(i, 12) / t[i], shield: "round"},
{name:"Hantzu", base:11, odd:.1, sort: i => n(i) / td(i, 13), shield:"banner"}, {name: "Hantzu", base: 11, odd: 0.1, sort: i => n(i) / td(i, 13), shield: "banner"},
{name:"Yamoto", base:12, odd:.1, sort: i => n(i) / td(i, 15) / t[i], shield:"round"}, {name: "Yamoto", base: 12, odd: 0.1, sort: i => n(i) / td(i, 15) / t[i], shield: "round"},
{name:"Portuzian", base:13, odd:.4, sort: i => n(i) / td(i, 17) / sf(i), shield:"spanish"}, {name: "Portuzian", base: 13, odd: 0.4, sort: i => n(i) / td(i, 17) / sf(i), shield: "spanish"},
{name:"Nawatli", base:14, odd:.1, sort: i => h[i] / td(i, 18) / bd(i, [7]), shield:"square"}, {name: "Nawatli", base: 14, odd: 0.1, sort: i => h[i] / td(i, 18) / bd(i, [7]), shield: "square"},
{name:"Vengrian", base: 15, odd:.2, sort: i => n(i) / td(i, 11) / bd(i, [4]) * t[i], shield:"wedged"}, {name: "Vengrian", base: 15, odd: 0.2, sort: i => (n(i) / td(i, 11) / bd(i, [4])) * t[i], shield: "wedged"},
{name:"Turchian", base: 16, odd:.2, sort: i => n(i) / td(i, 13), shield:"round"}, {name: "Turchian", base: 16, odd: 0.2, sort: i => n(i) / td(i, 13), shield: "round"},
{name:"Berberan", base: 17, odd:.1, sort: i => n(i) / td(i, 19) / bd(i, [1, 2, 3], 7) * t[i], shield:"round"}, {name: "Berberan", base: 17, odd: 0.1, sort: i => (n(i) / td(i, 19) / bd(i, [1, 2, 3], 7)) * t[i], shield: "round"},
{name:"Eurabic", base: 18, odd:.2, sort: i => n(i) / td(i, 26) / bd(i, [1, 2], 7) * t[i], shield:"round"}, {name: "Eurabic", base: 18, odd: 0.2, sort: i => (n(i) / td(i, 26) / bd(i, [1, 2], 7)) * t[i], shield: "round"},
{name:"Inuk", base: 19, odd:.05, sort: i => td(i, -1) / bd(i, [10, 11]) / sf(i), shield:"square"}, {name: "Inuk", base: 19, odd: 0.05, sort: i => td(i, -1) / bd(i, [10, 11]) / sf(i), shield: "square"},
{name:"Euskati", base: 20, odd:.05, sort: i => n(i) / td(i, 15) * h[i], shield:"spanish"}, {name: "Euskati", base: 20, odd: 0.05, sort: i => (n(i) / td(i, 15)) * h[i], shield: "spanish"},
{name:"Yoruba", base: 21, odd:.05, sort: i => n(i) / td(i, 15) / bd(i, [5, 7]), shield:"vesicaPiscis"}, {name: "Yoruba", base: 21, odd: 0.05, sort: i => n(i) / td(i, 15) / bd(i, [5, 7]), shield: "vesicaPiscis"},
{name:"Keltan", base: 22, odd:.05, sort: i => n(i) / td(i, 11) / bd(i, [6, 8]) * t[i], shield:"vesicaPiscis"}, {name: "Keltan", base: 22, odd: 0.05, sort: i => (n(i) / td(i, 11) / bd(i, [6, 8])) * t[i], shield: "vesicaPiscis"},
{name:"Efratic", base: 23, odd:.05, sort: i => n(i) / td(i, 22) * t[i], shield:"diamond"}, {name: "Efratic", base: 23, odd: 0.05, sort: i => (n(i) / td(i, 22)) * t[i], shield: "diamond"},
{name:"Tehrani", base: 24, odd:.1, sort: i => n(i) / td(i, 18) * h[i], shield:"round"}, {name: "Tehrani", base: 24, odd: 0.1, sort: i => (n(i) / td(i, 18)) * h[i], shield: "round"},
{name:"Maui", base: 25, odd:.05, sort: i => n(i) / td(i, 24) / sf(i) / t[i], shield:"round"}, {name: "Maui", base: 25, odd: 0.05, sort: i => n(i) / td(i, 24) / sf(i) / t[i], shield: "round"},
{name:"Carnatic", base: 26, odd:.05, sort: i => n(i) / td(i, 26), shield:"round"}, {name: "Carnatic", base: 26, odd: 0.05, sort: i => n(i) / td(i, 26), shield: "round"},
{name:"Inqan", base: 27, odd:.05, sort: i => h[i] / td(i, 13), shield:"square"}, {name: "Inqan", base: 27, odd: 0.05, sort: i => h[i] / td(i, 13), shield: "square"},
{name:"Kiswaili", base: 28, odd:.1, sort: i => n(i) / td(i, 29) / bd(i, [1, 3, 5, 7]), shield:"vesicaPiscis"}, {name: "Kiswaili", base: 28, odd: 0.1, sort: i => n(i) / td(i, 29) / bd(i, [1, 3, 5, 7]), shield: "vesicaPiscis"},
{name:"Vietic", base: 29, odd:.1, sort: i => n(i) / td(i, 25) / bd(i, [7], 7) / t[i], shield:"banner"}, {name: "Vietic", base: 29, odd: 0.1, sort: i => n(i) / td(i, 25) / bd(i, [7], 7) / t[i], shield: "banner"},
{name:"Guantzu", base:30, odd:.1, sort: i => n(i) / td(i, 17), shield:"banner"}, {name: "Guantzu", base: 30, odd: 0.1, sort: i => n(i) / td(i, 17), shield: "banner"},
{name:"Ulus", base:31, odd:.1, sort: i => n(i) / td(i, 5) / bd(i, [2, 4, 10], 7) * t[i], shield:"banner"} {name: "Ulus", base: 31, odd: 0.1, sort: i => (n(i) / td(i, 5) / bd(i, [2, 4, 10], 7)) * t[i], shield: "banner"}
]; ];
} };
// expand cultures across the map (Dijkstra-like algorithm) // expand cultures across the map (Dijkstra-like algorithm)
const expand = function () { const expand = function () {
TIME && console.time('expandCultures'); TIME && console.time("expandCultures");
cells = pack.cells; cells = pack.cells;
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p}); const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
@ -356,10 +380,13 @@
queue.queue({e: c.center, p: 0, c: c.i}); queue.queue({e: c.center, p: 0, c: c.i});
}); });
const neutral = cells.i.length / 5000 * 3000 * neutralInput.value; // limit cost for culture growth const neutral = (cells.i.length / 5000) * 3000 * neutralInput.value; // limit cost for culture growth
const cost = []; const cost = [];
while (queue.length) { while (queue.length) {
const next = queue.dequeue(), n = next.e, p = next.p, c = next.c; const next = queue.dequeue(),
n = next.e,
p = next.p,
c = next.c;
const type = pack.cultures[c].type; const type = pack.cultures[c].type;
cells.c[n].forEach(function (e) { cells.c[n].forEach(function (e) {
const biome = cells.biome[e]; const biome = cells.biome[e];
@ -380,8 +407,8 @@
}); });
} }
TIME && console.timeEnd('expandCultures'); TIME && console.timeEnd("expandCultures");
} };
function getBiomeCost(c, biome, type) { function getBiomeCost(c, biome, type) {
if (cells.biome[pack.cultures[c].center] === biome) return 10; // tiny penalty for native biome if (cells.biome[pack.cultures[c].center] === biome) return 10; // tiny penalty for native biome
@ -391,7 +418,8 @@
} }
function getHeightCost(i, h, type) { function getHeightCost(i, h, type) {
const f = pack.features[cells.f[i]], a = cells.area[i]; const f = pack.features[cells.f[i]],
a = cells.area[i];
if (type === "Lake" && f.type === "lake") return 10; // no lake crossing penalty for Lake cultures if (type === "Lake" && f.type === "lake") return 10; // no lake crossing penalty for Lake cultures
if (type === "Naval" && h < 20) return a * 2; // low sea/lake crossing penalty for Naval cultures if (type === "Naval" && h < 20) return a * 2; // low sea/lake crossing penalty for Naval cultures
if (type === "Nomadic" && h < 20) return a * 50; // giant sea/lake crossing penalty for Nomads if (type === "Nomadic" && h < 20) return a * 50; // giant sea/lake crossing penalty for Nomads
@ -407,7 +435,7 @@
function getRiverCost(r, i, type) { 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 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 Math.min(Math.max(cells.fl[i] / 10, 20), 100); // river penalty from 20 to 100 based on flux
} }
function getTypeCost(t, type) { function getTypeCost(t, type) {
@ -420,8 +448,7 @@
const getRandomShield = function () { const getRandomShield = function () {
const type = rw(COA.shields.types); const type = rw(COA.shields.types);
return rw(COA.shields[type]); return rw(COA.shields[type]);
} };
return {generate, add, expand, getDefault, getRandomShield}; return {generate, add, expand, getDefault, getRandomShield};
})();
})));

View file

@ -1,8 +1,6 @@
(function (global, factory) {
typeof exports === "object" && typeof module !== "undefined" ? (module.exports = factory()) : typeof define === "function" && define.amd ? define(factory) : (global.Lakes = factory());
})(this, function () {
"use strict"; "use strict";
window.Lakes = (function () {
const setClimateData = function (h) { const setClimateData = function (h) {
const cells = pack.cells; const cells = pack.cells;
const lakeOutCells = new Uint16Array(cells.i.length); const lakeOutCells = new Uint16Array(cells.i.length);
@ -149,4 +147,4 @@
} }
return {setClimateData, cleanupLakeData, prepareLakeData, defineGroup, generateName, getName, getShoreline}; return {setClimateData, cleanupLakeData, prepareLakeData, defineGroup, generateName, getName, getShoreline};
}); })();

View file

@ -1,8 +1,6 @@
(function (global, factory) {
typeof exports === "object" && typeof module !== "undefined" ? (module.exports = factory()) : typeof define === "function" && define.amd ? define(factory) : (global.Military = factory());
})(this, function () {
"use strict"; "use strict";
window.Military = (function () {
const generate = function () { const generate = function () {
TIME && console.time("generateMilitaryForces"); TIME && console.time("generateMilitaryForces");
const cells = pack.cells, const cells = pack.cells,
@ -371,4 +369,4 @@
}; };
return {generate, getDefaultOptions, getName, generateNote, drawRegiments, drawRegiment, moveRegiment, getTotal, getEmblem}; return {generate, getDefaultOptions, getName, generateNote, drawRegiments, drawRegiment, moveRegiment, getTotal, getEmblem};
}); })();

View file

@ -1,7 +1,6 @@
(function (global, factory) {
typeof exports === "object" && typeof module !== "undefined" ? (module.exports = factory()) : typeof define === "function" && define.amd ? define(factory) : (global.Names = factory());
})(this, function () {
"use strict"; "use strict";
window.Names = (function () {
let chains = []; let chains = [];
// calculate Markov chain for a namesbase // calculate Markov chain for a namesbase
@ -294,4 +293,4 @@
}; };
return {getBase, getCulture, getCultureShort, getBaseShort, getState, updateChain, clearChains, getNameBases, getMapName, calculateChain}; return {getBase, getCulture, getCultureShort, getBaseShort, getState, updateChain, clearChains, getNameBases, getMapName, calculateChain};
}); })();

View file

@ -1,8 +1,6 @@
(function (global, factory) {
typeof exports === "object" && typeof module !== "undefined" ? (module.exports = factory()) : typeof define === "function" && define.amd ? define(factory) : (global.OceanLayers = factory());
})(this, function () {
"use strict"; "use strict";
window.OceanLayers = (function () {
let cells, vertices, pointsN, used; let cells, vertices, pointsN, used;
const OceanLayers = function OceanLayers() { const OceanLayers = function OceanLayers() {
@ -91,4 +89,4 @@
} }
return OceanLayers; return OceanLayers;
}); })();

View file

@ -1,8 +1,6 @@
(function (global, factory) {
typeof exports === "object" && typeof module !== "undefined" ? (module.exports = factory()) : typeof define === "function" && define.amd ? define(factory) : (global.ReliefIcons = factory());
})(this, function () {
"use strict"; "use strict";
window.ReliefIcons = (function () {
const ReliefIcons = function () { const ReliefIcons = function () {
TIME && console.time("drawRelief"); TIME && console.time("drawRelief");
terrain.selectAll("*").remove(); terrain.selectAll("*").remove();
@ -127,4 +125,4 @@
} }
return ReliefIcons; return ReliefIcons;
}); })();

View file

@ -1,14 +1,8 @@
(function (global, factory) { "use strict";
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.Religions = factory());
}(this, (function () {'use strict';
window.Religions = (function () {
// name generation approach and relative chance to be selected // name generation approach and relative chance to be selected
const approach = {"Number":1, "Being":3, "Adjective":5, "Color + Animal":5, const approach = {Number: 1, Being: 3, Adjective: 5, "Color + Animal": 5, "Adjective + Animal": 5, "Adjective + Being": 5, "Adjective + Genitive": 1, "Color + Being": 3, "Color + Genitive": 3, "Being + of + Genitive": 2, "Being + of the + Genitive": 1, "Animal + of + Genitive": 1, "Adjective + Being + of + Genitive": 2, "Adjective + Animal + of + Genitive": 2};
"Adjective + Animal":5, "Adjective + Being":5, "Adjective + Genitive":1,
"Color + Being":3, "Color + Genitive":3, "Being + of + Genitive":2, "Being + of the + Genitive":1,
"Animal + of + Genitive":1, "Adjective + Being + of + Genitive":2, "Adjective + Animal + of + Genitive":2};
// turn weighted array into simple array // turn weighted array into simple array
const approaches = []; const approaches = [];
@ -29,59 +23,65 @@
}; };
const forms = { const forms = {
Folk:{"Shamanism":2, "Animism":2, "Ancestor worship":1, "Polytheism":2}, Folk: {Shamanism: 2, Animism: 2, "Ancestor worship": 1, Polytheism: 2},
Organized:{"Polytheism":5, "Dualism":1, "Monotheism":4, "Non-theism":1}, Organized: {Polytheism: 5, Dualism: 1, Monotheism: 4, "Non-theism": 1},
Cult:{"Cult":1, "Dark Cult":1}, Cult: {Cult: 1, "Dark Cult": 1},
Heresy:{"Heresy":1} Heresy: {Heresy: 1}
}; };
const methods = {"Random + type": 3, "Random + ism": 1, "Supreme + ism": 5, "Faith of + Supreme": 5, "Place + ism": 1, "Culture + ism": 2, "Place + ian + type": 6, "Culture + type": 4}; const methods = {"Random + type": 3, "Random + ism": 1, "Supreme + ism": 5, "Faith of + Supreme": 5, "Place + ism": 1, "Culture + ism": 2, "Place + ian + type": 6, "Culture + type": 4};
const types = { const types = {
"Shamanism":{"Beliefs":3, "Shamanism":2, "Spirits":1}, Shamanism: {Beliefs: 3, Shamanism: 2, Spirits: 1},
"Animism":{"Spirits":1, "Beliefs":1}, Animism: {Spirits: 1, Beliefs: 1},
"Ancestor worship":{"Beliefs":1, "Forefathers":2, "Ancestors":2}, "Ancestor worship": {Beliefs: 1, Forefathers: 2, Ancestors: 2},
"Polytheism":{"Deities":3, "Faith":1, "Gods":1, "Pantheon":1}, Polytheism: {Deities: 3, Faith: 1, Gods: 1, Pantheon: 1},
"Dualism":{"Religion":3, "Faith":1, "Cult":1}, Dualism: {Religion: 3, Faith: 1, Cult: 1},
"Monotheism":{"Religion":1, "Church":1}, Monotheism: {Religion: 1, Church: 1},
"Non-theism":{"Beliefs":3, "Spirits":1}, "Non-theism": {Beliefs: 3, Spirits: 1},
"Cult":{"Cult":4, "Sect":4, "Worship":1, "Orden":1, "Coterie":1, "Arcanum":1}, Cult: {Cult: 4, Sect: 4, Worship: 1, Orden: 1, Coterie: 1, Arcanum: 1},
"Dark Cult":{"Cult":2, "Sect":2, "Occultism":1, "Idols":1, "Coven":1, "Circle":1, "Blasphemy":1}, "Dark Cult": {Cult: 2, Sect: 2, Occultism: 1, Idols: 1, Coven: 1, Circle: 1, Blasphemy: 1},
"Heresy":{"Heresy":3, "Sect":2, "Schism":1, "Dissenters":1, "Circle":1, "Brotherhood":1, "Society":1, "Iconoclasm":1, "Dissent":1, "Apostates":1} Heresy: {Heresy: 3, Sect: 2, Schism: 1, Dissenters: 1, Circle: 1, Brotherhood: 1, Society: 1, Iconoclasm: 1, Dissent: 1, Apostates: 1}
}; };
const generate = function () { const generate = function () {
TIME && console.time('generateReligions'); TIME && console.time("generateReligions");
const cells = pack.cells, states = pack.states, cultures = pack.cultures; const cells = pack.cells,
const religions = pack.religions = []; states = pack.states,
cultures = pack.cultures;
const religions = (pack.religions = []);
cells.religion = new Uint16Array(cells.culture); // cell religion; initially based on culture cells.religion = new Uint16Array(cells.culture); // cell religion; initially based on culture
// add folk religions // add folk religions
pack.cultures.forEach(c => { pack.cultures.forEach(c => {
if (!c.i) {religions.push({i: 0, name: "No religion"}); return;} if (!c.i) {
if (c.removed) {religions.push({i: c.i, name: "Extinct religion for "+c.name, color:getMixedColor(c.color, .1, 0), removed:true}); return;} religions.push({i: 0, name: "No religion"});
return;
}
if (c.removed) {
religions.push({i: c.i, name: "Extinct religion for " + c.name, color: getMixedColor(c.color, 0.1, 0), removed: true});
return;
}
const form = rw(forms.Folk); const form = rw(forms.Folk);
const name = c.name + " " + rw(types[form]); const name = c.name + " " + rw(types[form]);
const deity = form === "Animism" ? null : getDeityName(c.i); const deity = form === "Animism" ? null : getDeityName(c.i);
const color = getMixedColor(c.color, .1, 0); // `url(#hatch${rand(8,13)})`; const color = getMixedColor(c.color, 0.1, 0); // `url(#hatch${rand(8,13)})`;
religions.push({i: c.i, name, color, culture: c.i, type: "Folk", form, deity, center: c.center, origin: 0}); religions.push({i: c.i, name, color, culture: c.i, type: "Folk", form, deity, center: c.center, origin: 0});
}); });
if (religionsInput.value == 0 || pack.cultures.length < 2) { if (religionsInput.value == 0 || pack.cultures.length < 2) {
religions.filter(r => r.i).forEach(r => r.code = abbreviate(r.name)); religions.filter(r => r.i).forEach(r => (r.code = abbreviate(r.name)));
return; return;
} }
const burgs = pack.burgs.filter(b => b.i && !b.removed); const burgs = pack.burgs.filter(b => b.i && !b.removed);
const sorted = burgs.length > +religionsInput.value const sorted = burgs.length > +religionsInput.value ? burgs.sort((a, b) => b.population - a.population).map(b => b.cell) : cells.i.filter(i => cells.s[i] > 2).sort((a, b) => cells.s[b] - cells.s[a]);
? burgs.sort((a, b) => b.population - a.population).map(b => b.cell)
: cells.i.filter(i => cells.s[i] > 2).sort((a, b) => cells.s[b] - cells.s[a]);
const religionsTree = d3.quadtree(); const religionsTree = d3.quadtree();
const spacing = (graphWidth + graphHeight) / 6 / religionsInput.value; // base min distance between towns const spacing = (graphWidth + graphHeight) / 6 / religionsInput.value; // base min distance between towns
const cultsCount = Math.floor(rand(10, 40) / 100 * religionsInput.value); const cultsCount = Math.floor((rand(10, 40) / 100) * religionsInput.value);
const count = +religionsInput.value - cultsCount + religions.length; const count = +religionsInput.value - cultsCount + religions.length;
// generate organized religions // generate organized religions
@ -96,13 +96,14 @@
if (expansion === "state" && !state) expansion = "global"; if (expansion === "state" && !state) expansion = "global";
if (expansion === "culture" && !culture) expansion = "global"; if (expansion === "culture" && !culture) expansion = "global";
if (expansion === "state" && Math.random() > .5) center = states[state].center; if (expansion === "state" && Math.random() > 0.5) center = states[state].center;
if (expansion === "culture" && Math.random() > .5) center = cultures[culture].center; if (expansion === "culture" && Math.random() > 0.5) center = cultures[culture].center;
if (!cells.burg[center] && cells.c[center].some(c => cells.burg[c])) center = cells.c[center].find(c => cells.burg[c]); if (!cells.burg[center] && cells.c[center].some(c => cells.burg[c])) center = cells.c[center].find(c => cells.burg[c]);
const x = cells.p[center][0], y = cells.p[center][1]; const x = cells.p[center][0],
y = cells.p[center][1];
const s = spacing * gauss(1, .3, .2, 2, 2); // randomize to make the placement not uniform const s = spacing * gauss(1, 0.3, 0.2, 2, 2); // randomize to make the placement not uniform
if (religionsTree.find(x, y, s) !== undefined) continue; // to close to existing religion if (religionsTree.find(x, y, s) !== undefined) continue; // to close to existing religion
// add "Old" to name of the folk religion on this culture // add "Old" to name of the folk religion on this culture
@ -111,7 +112,7 @@
const origin = folk ? folk.i : 0; const origin = folk ? folk.i : 0;
const expansionism = rand(3, 8); const expansionism = rand(3, 8);
const color = getMixedColor(religions[origin].color, .3, 0); // `url(#hatch${rand(0,5)})`; const color = getMixedColor(religions[origin].color, 0.3, 0); // `url(#hatch${rand(0,5)})`;
religions.push({i: religions.length, name, color, culture, type: "Organized", form, deity, expansion, expansionism, center, origin}); religions.push({i: religions.length, name, color, culture, type: "Organized", form, deity, expansion, expansionism, center, origin});
religionsTree.add([x, y]); religionsTree.add([x, y]);
} }
@ -121,9 +122,10 @@
const form = rw(forms.Cult); const form = rw(forms.Cult);
let center = sorted[biased(0, sorted.length - 1, 1)]; // religion center let center = sorted[biased(0, sorted.length - 1, 1)]; // religion center
if (!cells.burg[center] && cells.c[center].some(c => cells.burg[c])) center = cells.c[center].find(c => cells.burg[c]); if (!cells.burg[center] && cells.c[center].some(c => cells.burg[c])) center = cells.c[center].find(c => cells.burg[c]);
const x = cells.p[center][0], y = cells.p[center][1]; const x = cells.p[center][0],
y = cells.p[center][1];
const s = spacing * gauss(2, .3, 1, 3, 2); // randomize to make the placement not uniform const s = spacing * gauss(2, 0.3, 1, 3, 2); // randomize to make the placement not uniform
if (religionsTree.find(x, y, s) !== undefined) continue; // to close to existing religion if (religionsTree.find(x, y, s) !== undefined) continue; // to close to existing religion
const culture = cells.culture[center]; const culture = cells.culture[center];
@ -131,8 +133,8 @@
const origin = folk ? folk.i : 0; const origin = folk ? folk.i : 0;
const deity = getDeityName(culture); const deity = getDeityName(culture);
const name = getCultName(form, center); const name = getCultName(form, center);
const expansionism = gauss(1.1, .5, 0, 5); const expansionism = gauss(1.1, 0.5, 0, 5);
const color = getMixedColor(cultures[culture].color, .5, 0); // "url(#hatch7)"; const color = getMixedColor(cultures[culture].color, 0.5, 0); // "url(#hatch7)";
religions.push({i: religions.length, name, color, culture, type: "Cult", form, deity, expansion: "global", expansionism, center, origin}); religions.push({i: religions.length, name, color, culture, type: "Cult", form, deity, expansion: "global", expansionism, center, origin});
religionsTree.add([x, y]); religionsTree.add([x, y]);
//debug.append("circle").attr("cx", x).attr("cy", y).attr("r", 2).attr("fill", "red"); //debug.append("circle").attr("cx", x).attr("cy", y).attr("r", 2).attr("fill", "red");
@ -141,20 +143,23 @@
expandReligions(); expandReligions();
// generate heresies // generate heresies
religions.filter(r => r.type === "Organized").forEach(r => { religions
.filter(r => r.type === "Organized")
.forEach(r => {
if (r.expansionism < 3) return; if (r.expansionism < 3) return;
const count = gauss(0, 1, 0, 3); const count = gauss(0, 1, 0, 3);
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
let center = ra(cells.i.filter(i => cells.religion[i] === r.i && cells.c[i].some(c => cells.religion[c] !== r.i))); let center = ra(cells.i.filter(i => cells.religion[i] === r.i && cells.c[i].some(c => cells.religion[c] !== r.i)));
if (!center) continue; if (!center) continue;
if (!cells.burg[center] && cells.c[center].some(c => cells.burg[c])) center = cells.c[center].find(c => cells.burg[c]); if (!cells.burg[center] && cells.c[center].some(c => cells.burg[c])) center = cells.c[center].find(c => cells.burg[c]);
const x = cells.p[center][0], y = cells.p[center][1]; const x = cells.p[center][0],
y = cells.p[center][1];
if (religionsTree.find(x, y, spacing / 10) !== undefined) continue; // to close to other if (religionsTree.find(x, y, spacing / 10) !== undefined) continue; // to close to other
const culture = cells.culture[center]; const culture = cells.culture[center];
const name = getCultName("Heresy", center); const name = getCultName("Heresy", center);
const expansionism = gauss(1.2, .5, 0, 5); const expansionism = gauss(1.2, 0.5, 0, 5);
const color = getMixedColor(r.color, .4, .2); // "url(#hatch6)"; const color = getMixedColor(r.color, 0.4, 0.2); // "url(#hatch6)";
religions.push({i: religions.length, name, color, culture, type: "Heresy", form: r.form, deity: r.deity, expansion: "global", expansionism, center, origin: r.i}); religions.push({i: religions.length, name, color, culture, type: "Heresy", form: r.form, deity: r.deity, expansion: "global", expansionism, center, origin: r.i});
religionsTree.add([x, y]); religionsTree.add([x, y]);
//debug.append("circle").attr("cx", x).attr("cy", y).attr("r", 2).attr("fill", "green"); //debug.append("circle").attr("cx", x).attr("cy", y).attr("r", 2).attr("fill", "green");
@ -164,46 +169,61 @@
expandHeresies(); expandHeresies();
checkCenters(); checkCenters();
TIME && console.timeEnd('generateReligions'); TIME && console.timeEnd("generateReligions");
} };
const add = function (center) { const add = function (center) {
const cells = pack.cells, religions = pack.religions; const cells = pack.cells,
religions = pack.religions;
const r = cells.religion[center]; const r = cells.religion[center];
const i = religions.length; const i = religions.length;
const culture = cells.culture[center]; const culture = cells.culture[center];
const color = getMixedColor(religions[r].color, .3, 0); const color = getMixedColor(religions[r].color, 0.3, 0);
const type = religions[r].type === "Organized" ? rw({Organized: 4, Cult: 1, Heresy: 2}) : rw({Organized: 5, Cult: 2}); const type = religions[r].type === "Organized" ? rw({Organized: 4, Cult: 1, Heresy: 2}) : rw({Organized: 5, Cult: 2});
const form = rw(forms[type]); const form = rw(forms[type]);
const deity = type === "Heresy" ? religions[r].deity : form === "Non-theism" ? null : getDeityName(culture); const deity = type === "Heresy" ? religions[r].deity : form === "Non-theism" ? null : getDeityName(culture);
let name, expansion; let name, expansion;
if (type === "Organized") [name, expansion] = getReligionName(form, deity, center) if (type === "Organized") [name, expansion] = getReligionName(form, deity, center);
else {name = getCultName(form, center); expansion = "global";} else {
name = getCultName(form, center);
expansion = "global";
}
const formName = type === "Heresy" ? religions[r].form : form; const formName = type === "Heresy" ? religions[r].form : form;
const code = abbreviate(name, religions.map(r => r.code)); const code = abbreviate(
name,
religions.map(r => r.code)
);
religions.push({i, name, color, culture, type, form: formName, deity, expansion, expansionism: 0, center, cells: 0, area: 0, rural: 0, urban: 0, origin: r, code}); religions.push({i, name, color, culture, type, form: formName, deity, expansion, expansionism: 0, center, cells: 0, area: 0, rural: 0, urban: 0, origin: r, code});
cells.religion[center] = i; cells.religion[center] = i;
} };
// growth algorithm to assign cells to religions // growth algorithm to assign cells to religions
const expandReligions = function () { const expandReligions = function () {
const cells = pack.cells, religions = pack.religions; const cells = pack.cells,
religions = pack.religions;
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p}); const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
const cost = []; const cost = [];
religions.filter(r => r.type === "Organized" || r.type === "Cult").forEach(r => { religions
.filter(r => r.type === "Organized" || r.type === "Cult")
.forEach(r => {
cells.religion[r.center] = r.i; cells.religion[r.center] = r.i;
queue.queue({e: r.center, p: 0, r: r.i, s: cells.state[r.center], c: r.culture}); queue.queue({e: r.center, p: 0, r: r.i, s: cells.state[r.center], c: r.culture});
cost[r.center] = 1; cost[r.center] = 1;
}); });
const neutral = cells.i.length / 5000 * 200 * gauss(1, .3, .2, 2, 2) * neutralInput.value; // limit cost for organized religions growth const neutral = (cells.i.length / 5000) * 200 * gauss(1, 0.3, 0.2, 2, 2) * neutralInput.value; // limit cost for organized religions growth
const popCost = d3.max(cells.pop) / 3; // enougth population to spered religion without penalty const popCost = d3.max(cells.pop) / 3; // enougth population to spered religion without penalty
while (queue.length) { while (queue.length) {
const next = queue.dequeue(), n = next.e, p = next.p, r = next.r, c = next.c, s = next.s; const next = queue.dequeue(),
n = next.e,
p = next.p,
r = next.r,
c = next.c,
s = next.s;
const expansion = religions[r].expansion; const expansion = religions[r].expansion;
cells.c[n].forEach(function (e) { cells.c[n].forEach(function (e) {
@ -215,7 +235,7 @@
const biomeCost = cells.road[e] ? 1 : biomesData.cost[cells.biome[e]]; const biomeCost = cells.road[e] ? 1 : biomesData.cost[cells.biome[e]];
const populationCost = Math.max(rn(popCost - cells.pop[e]), 0); const populationCost = Math.max(rn(popCost - cells.pop[e]), 0);
const heightCost = Math.max(cells.h[e], 20) - 20; const heightCost = Math.max(cells.h[e], 20) - 20;
const waterCost = cells.h[e] < 20 ? cells.road[e] ? 50 : 1000 : 0; const waterCost = cells.h[e] < 20 ? (cells.road[e] ? 50 : 1000) : 0;
const totalCost = p + (cultureCost + stateCost + biomeCost + populationCost + heightCost + waterCost) / religions[r].expansionism; const totalCost = p + (cultureCost + stateCost + biomeCost + populationCost + heightCost + waterCost) / religions[r].expansionism;
if (totalCost > neutral) return; if (totalCost > neutral) return;
@ -226,32 +246,39 @@
} }
}); });
} }
} };
// growth algorithm to assign cells to heresies // growth algorithm to assign cells to heresies
const expandHeresies = function () { const expandHeresies = function () {
const cells = pack.cells, religions = pack.religions; const cells = pack.cells,
religions = pack.religions;
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p}); const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
const cost = []; const cost = [];
religions.filter(r => r.type === "Heresy").forEach(r => { religions
.filter(r => r.type === "Heresy")
.forEach(r => {
const b = cells.religion[r.center]; // "base" religion id const b = cells.religion[r.center]; // "base" religion id
cells.religion[r.center] = r.i; // heresy id cells.religion[r.center] = r.i; // heresy id
queue.queue({e: r.center, p: 0, r: r.i, b}); queue.queue({e: r.center, p: 0, r: r.i, b});
cost[r.center] = 1; cost[r.center] = 1;
}); });
const neutral = cells.i.length / 5000 * 500 * neutralInput.value; // limit cost for heresies growth const neutral = (cells.i.length / 5000) * 500 * neutralInput.value; // limit cost for heresies growth
while (queue.length) { while (queue.length) {
const next = queue.dequeue(), n = next.e, p = next.p, r = next.r, b = next.b; const next = queue.dequeue(),
n = next.e,
p = next.p,
r = next.r,
b = next.b;
cells.c[n].forEach(function (e) { cells.c[n].forEach(function (e) {
const religionCost = cells.religion[e] === b ? 0 : 2000; const religionCost = cells.religion[e] === b ? 0 : 2000;
const biomeCost = cells.road[e] ? 0 : biomesData.cost[cells.biome[e]]; const biomeCost = cells.road[e] ? 0 : biomesData.cost[cells.biome[e]];
const heightCost = Math.max(cells.h[e], 20) - 20; const heightCost = Math.max(cells.h[e], 20) - 20;
const waterCost = cells.h[e] < 20 ? cells.road[e] ? 50 : 1000 : 0; const waterCost = cells.h[e] < 20 ? (cells.road[e] ? 50 : 1000) : 0;
const totalCost = p + (religionCost + biomeCost + heightCost + waterCost) / Math.max(religions[r].expansionism, .1); const totalCost = p + (religionCost + biomeCost + heightCost + waterCost) / Math.max(religions[r].expansionism, 0.1);
if (totalCost > neutral) return; if (totalCost > neutral) return;
@ -262,13 +289,16 @@
} }
}); });
} }
} };
function checkCenters() { function checkCenters() {
const cells = pack.cells, religions = pack.religions; const cells = pack.cells,
religions = pack.religions;
const codes = religions.map(r => r.code); const codes = religions.map(r => r.code);
religions.filter(r => r.i).forEach(r => { religions
.filter(r => r.i)
.forEach(r => {
r.code = abbreviate(r.name, codes); r.code = abbreviate(r.name, codes);
// move religion center if it's not within religion area after expansion // move religion center if it's not within religion area after expansion
@ -280,23 +310,26 @@
} }
function updateCultures() { function updateCultures() {
TIME && console.time('updateCulturesForReligions'); TIME && console.time("updateCulturesForReligions");
pack.religions = pack.religions.map((religion, index) => { pack.religions = pack.religions.map((religion, index) => {
if (index === 0) { if (index === 0) {
return religion; return religion;
} }
return {...religion, culture: pack.cells.culture[religion.center]}; return {...religion, culture: pack.cells.culture[religion.center]};
}); });
TIME && console.timeEnd('updateCulturesForReligions'); TIME && console.timeEnd("updateCulturesForReligions");
} }
// get supreme deity name // get supreme deity name
const getDeityName = function (culture) { const getDeityName = function (culture) {
if (culture === undefined) {ERROR && console.error("Please define a culture"); return;} if (culture === undefined) {
const meaning = generateMeaning(); ERROR && console.error("Please define a culture");
const cultureName = Names.getCulture(culture, null, null, "", .8); return;
return cultureName + ", The " + meaning;
} }
const meaning = generateMeaning();
const cultureName = Names.getCulture(culture, null, null, "", 0.8);
return cultureName + ", The " + meaning;
};
function generateMeaning() { function generateMeaning() {
const a = ra(approaches); // select generation approach const a = ra(approaches); // select generation approach
@ -318,21 +351,29 @@
function getReligionName(form, deity, center) { function getReligionName(form, deity, center) {
const cells = pack.cells; const cells = pack.cells;
const random = function() {return Names.getCulture(cells.culture[center], null, null, "", 0);} const random = function () {
const type = function() {return rw(types[form]);} return Names.getCulture(cells.culture[center], null, null, "", 0);
const supreme = function() {return deity.split(/[ ,]+/)[0];} };
const type = function () {
return rw(types[form]);
};
const supreme = function () {
return deity.split(/[ ,]+/)[0];
};
const place = function (adj) { const place = function (adj) {
const base = cells.burg[center] ? pack.burgs[cells.burg[center]].name : pack.states[cells.state[center]].name; const base = cells.burg[center] ? pack.burgs[cells.burg[center]].name : pack.states[cells.state[center]].name;
let name = trimVowels(base.split(/[ ,]+/)[0]); let name = trimVowels(base.split(/[ ,]+/)[0]);
return adj ? getAdjective(name) : name; return adj ? getAdjective(name) : name;
} };
const culture = function() {return pack.cultures[cells.culture[center]].name;} const culture = function () {
return pack.cultures[cells.culture[center]].name;
};
const m = rw(methods); const m = rw(methods);
if (m === "Random + type") return [random() + " " + type(), "global"]; if (m === "Random + type") return [random() + " " + type(), "global"];
if (m === "Random + ism") return [trimVowels(random()) + "ism", "global"]; if (m === "Random + ism") return [trimVowels(random()) + "ism", "global"];
if (m === "Supreme + ism" && deity) return [trimVowels(supreme()) + "ism", "global"]; if (m === "Supreme + ism" && deity) return [trimVowels(supreme()) + "ism", "global"];
if (m === "Faith of + Supreme" && deity) return [ra(['Faith', 'Way', 'Path', 'Word', 'Witnesses']) + " of " + supreme(), "global"]; if (m === "Faith of + Supreme" && deity) return [ra(["Faith", "Way", "Path", "Word", "Witnesses"]) + " of " + supreme(), "global"];
if (m === "Place + ism") return [place() + "ism", "state"]; if (m === "Place + ism") return [place() + "ism", "state"];
if (m === "Culture + ism") return [trimVowels(culture()) + "ism", "culture"]; if (m === "Culture + ism") return [trimVowels(culture()) + "ism", "culture"];
if (m === "Place + ian + type") return [place("adj") + " " + type(), "state"]; if (m === "Place + ian + type") return [place("adj") + " " + type(), "state"];
@ -342,14 +383,19 @@
function getCultName(form, center) { function getCultName(form, center) {
const cells = pack.cells; const cells = pack.cells;
const type = function() {return rw(types[form]);} const type = function () {
const random = function() {return trimVowels(Names.getCulture(cells.culture[center], null, null, "", 0).split(/[ ,]+/)[0]);} return rw(types[form]);
const burg = function() {return trimVowels(pack.burgs[cells.burg[center]].name.split(/[ ,]+/)[0]);}
if (cells.burg[center]) return burg() + "ian " + type();
if (Math.random() > .5) return random() + "ian " + type();
return type() + " of the " + generateMeaning();
}; };
const random = function () {
return trimVowels(Names.getCulture(cells.culture[center], null, null, "", 0).split(/[ ,]+/)[0]);
};
const burg = function () {
return trimVowels(pack.burgs[cells.burg[center]].name.split(/[ ,]+/)[0]);
};
if (cells.burg[center]) return burg() + "ian " + type();
if (Math.random() > 0.5) return random() + "ian " + type();
return type() + " of the " + generateMeaning();
}
return {generate, add, getDeityName, expandReligions, updateCultures}; return {generate, add, getDeityName, expandReligions, updateCultures};
})();
})));

View file

@ -1,8 +1,6 @@
(function (global, factory) {
typeof exports === "object" && typeof module !== "undefined" ? (module.exports = factory()) : typeof define === "function" && define.amd ? define(factory) : (global.Rivers = factory());
})(this, function () {
"use strict"; "use strict";
window.Rivers = (function () {
const generate = function (allowErosion = true) { const generate = function (allowErosion = true) {
TIME && console.time("generateRivers"); TIME && console.time("generateRivers");
Math.random = aleaPRNG(seed); Math.random = aleaPRNG(seed);
@ -442,4 +440,4 @@
}; };
return {generate, alterHeights, resolveDepressions, addMeandering, getRiverPath, specify, getName, getType, getBasin, getWidth, getOffset, getApproximateLength, getRiverPoints, remove}; return {generate, alterHeights, resolveDepressions, addMeandering, getRiverPath, specify, getName, getType, getBasin, getWidth, getOffset, getApproximateLength, getRiverPoints, remove};
}); })();

View file

@ -1,14 +1,9 @@
(function (global, factory) { window.Routes = (function () {
typeof exports === "object" && typeof module !== "undefined" ? (module.exports = factory()) : typeof define === "function" && define.amd ? define(factory) : (global.Routes = factory());
})(this, function () {
"use strict";
const getRoads = function () { const getRoads = function () {
TIME && console.time("generateMainRoads"); TIME && console.time("generateMainRoads");
const cells = pack.cells; const cells = pack.cells;
const burgs = pack.burgs.filter(b => b.i && !b.removed); const burgs = pack.burgs.filter(b => b.i && !b.removed);
const capitals = burgs.filter(b => b.capital) const capitals = burgs.filter(b => b.capital).sort((a, b) => a.population - b.population);
.sort((a,b) => a.population - b.population);
if (capitals.length < 2) return []; // not enough capitals to build main roads if (capitals.length < 2) return []; // not enough capitals to build main roads
const paths = []; // array to store path segments const paths = []; // array to store path segments
@ -271,4 +266,4 @@
} }
return [from, exit, false]; return [from, exit, false];
} }
}); })();

View file

@ -1,8 +1,6 @@
(function (global, factory) {
typeof exports === "object" && typeof module !== "undefined" ? (module.exports = factory()) : typeof define === "function" && define.amd ? define(factory) : (global.ThreeD = factory());
})(this, function () {
"use strict"; "use strict";
window.ThreeD = (function () {
// set default options // set default options
const options = {scale: 50, lightness: 0.7, shadow: 0.5, sun: {x: 100, y: 600, z: 1000}, rotateMesh: 0, rotateGlobe: 0.5, skyColor: "#9ecef5", waterColor: "#466eab", extendedWater: 0, labels3d: 0, resolution: 2}; const options = {scale: 50, lightness: 0.7, shadow: 0.5, sun: {x: 100, y: 600, z: 1000}, rotateMesh: 0, rotateGlobe: 0.5, skyColor: "#9ecef5", waterColor: "#466eab", extendedWater: 0, labels3d: 0, resolution: 2};
@ -581,4 +579,4 @@
} }
return {create, redraw, update, stop, options, setScale, setLightness, setSun, setRotation, toggleLabels, toggleSky, setResolution, setColors, saveScreenshot, saveOBJ}; return {create, redraw, update, stop, options, setScale, setLightness, setSun, setRotation, toggleLabels, toggleSky, setResolution, setColors, saveScreenshot, saveOBJ};
}); })();

View file

@ -1,4 +1,5 @@
"use strict"; "use strict";
function editZones() { function editZones() {
closeDialogs(); closeDialogs();
if (!layerIsOn("toggleZones")) toggleZones(); if (!layerIsOn("toggleZones")) toggleZones();