mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-22 20:11:24 +01:00
Merge branch 'master' of github.com:goteguru/Fantasy-Map-Generator
This commit is contained in:
commit
07ff6d030f
28 changed files with 2705 additions and 1754 deletions
27
index.css
27
index.css
|
|
@ -997,12 +997,6 @@ body button.noicon {
|
|||
stroke-width: 0.4;
|
||||
}
|
||||
|
||||
#controlCells > .occupied {
|
||||
fill: #ff828240;
|
||||
stroke: #ff8282;
|
||||
stroke-width: 0.4;
|
||||
}
|
||||
|
||||
#vertices > circle {
|
||||
fill: #ff0000;
|
||||
stroke: #841f1f;
|
||||
|
|
@ -1285,17 +1279,26 @@ div.slider .ui-slider-handle {
|
|||
display: none !important;
|
||||
}
|
||||
|
||||
.burgs-table {
|
||||
max-height: 75vh;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.table {
|
||||
max-height: 75vh;
|
||||
max-width: 75vw;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
.table::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.table::-webkit-scrollbar-thumb {
|
||||
background-color: #aaa;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.table::-webkit-scrollbar-thumb:hover {
|
||||
background: #666;
|
||||
}
|
||||
|
||||
.overflow {
|
||||
|
|
|
|||
62
index.html
62
index.html
|
|
@ -910,6 +910,13 @@
|
|||
<label for="hideLabels" class="checkbox-label">Toggle visibility automatically</label>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr data-tip="Allow system to rescale labels on zoom">
|
||||
<td colspan=2>
|
||||
<input id="rescaleLabels" class="checkbox" type="checkbox" onchange="invokeActiveZooming()" checked>
|
||||
<label for="rescaleLabels" class="checkbox-label">Rescale on zoom</label>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
|
@ -1000,17 +1007,18 @@
|
|||
<td>Map template</td>
|
||||
<td>
|
||||
<select id="templateInput" data-stored="template">
|
||||
<option value="Volcano">Volcano</option>
|
||||
<option value="High Island">High Island</option>
|
||||
<option value="Low Island">Low Island</option>
|
||||
<option value="Continents">Two Continents</option>
|
||||
<option value="Archipelago">Archipelago</option>
|
||||
<option value="Atoll">Atoll</option>
|
||||
<option value="Mediterranean">Mediterranean</option>
|
||||
<option value="Peninsula">Peninsula</option>
|
||||
<option value="Pangea">Pangea</option>
|
||||
<option value="Isthmus">Isthmus</option>
|
||||
<option value="Shattered">Shattered</option>
|
||||
<option value="volcano">Volcano</option>
|
||||
<option value="highIsland">High Island</option>
|
||||
<option value="lowIsland">Low Island</option>
|
||||
<option value="continents">Two Continents</option>
|
||||
<option value="archipelago">Archipelago</option>
|
||||
<option value="atoll">Atoll</option>
|
||||
<option value="mediterranean">Mediterranean</option>
|
||||
<option value="peninsula">Peninsula</option>
|
||||
<option value="pangea">Pangea</option>
|
||||
<option value="isthmus">Isthmus</option>
|
||||
<option value="shattered">Shattered</option>
|
||||
<option value="taklamakan">Taklamakan</option>
|
||||
</select>
|
||||
</td>
|
||||
<td></td>
|
||||
|
|
@ -1665,7 +1673,7 @@
|
|||
</div>
|
||||
|
||||
<div id="riverCreator" class="dialog" style="display: none">
|
||||
<div id="riverCreatorBody"></div>
|
||||
<div id="riverCreatorBody" class="table"></div>
|
||||
<div id="riverCreatorBottom">
|
||||
<button id="riverCreatorComplete" data-tip="Complete river creation" class="icon-check"></button>
|
||||
<button id="riverCreatorCancel" data-tip="Cancel the creation" class="icon-cancel"></button>
|
||||
|
|
@ -2332,18 +2340,19 @@
|
|||
<div id="templateEditor" class="dialog stable" style="display: none">
|
||||
<div id="templateTop">
|
||||
<i>Select template: </i><select id="templateSelect" style="width:16em" data-prev="templateCustom" data-tip="Select base template">
|
||||
<option value="templateCustom" selected>Custom</option>
|
||||
<option value="templateVolcano">Volcano</option>
|
||||
<option value="templateHighIsland">High Island</option>
|
||||
<option value="templateLowIsland">Low Island</option>
|
||||
<option value="templateContinents">Two Continents</option>
|
||||
<option value="templateArchipelago">Archipelago</option>
|
||||
<option value="templateAtoll">Atoll</option>
|
||||
<option value="templateMediterranean">Mediterranean</option>
|
||||
<option value="templatePeninsula">Peninsula</option>
|
||||
<option value="templatePangea">Pangea</option>
|
||||
<option value="templateIsthmus">Isthmus</option>
|
||||
<option value="templateShattered">Shattered</option>
|
||||
<option value="custom" selected>Custom</option>
|
||||
<option value="volcano">Volcano</option>
|
||||
<option value="highIsland">High Island</option>
|
||||
<option value="lowIsland">Low Island</option>
|
||||
<option value="continents">Two Continents</option>
|
||||
<option value="archipelago">Archipelago</option>
|
||||
<option value="atoll">Atoll</option>
|
||||
<option value="mediterranean">Mediterranean</option>
|
||||
<option value="peninsula">Peninsula</option>
|
||||
<option value="pangea">Pangea</option>
|
||||
<option value="isthmus">Isthmus</option>
|
||||
<option value="shattered">Shattered</option>
|
||||
<option value="taklamakan">Taklamakan</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="templateTools">
|
||||
|
|
@ -3186,7 +3195,7 @@
|
|||
<div style="left:31.2em" data-tip="Click to sort by burg type" class="sortable alphabetically" data-sortby="type">Type </div>
|
||||
</div>
|
||||
|
||||
<div id="burgsBody" class="burgs-table"></div>
|
||||
<div id="burgsBody" class="table"></div>
|
||||
|
||||
<div id="burgsFilters" data-tip="Apply a filter">
|
||||
<span>State: </span>
|
||||
|
|
@ -3221,7 +3230,7 @@
|
|||
<div style="left:30em" data-tip="Click to sort by river basin" class="sortable alphabetically" data-sortby="basin">Basin </div>
|
||||
</div>
|
||||
|
||||
<div id="riversBody" class="burgs-table"></div>
|
||||
<div id="riversBody" class="table"></div>
|
||||
|
||||
<div id="riversFooter" class="totalLine">
|
||||
<div data-tip="Rivers number" style="margin-left: 4px">Rivers: <span id="riversFooterNumber">0</span></div>
|
||||
|
|
@ -4187,6 +4196,7 @@
|
|||
<script src="libs/delaunator.min.js"></script>
|
||||
<script src="modules/utils.js"></script>
|
||||
<script src="modules/voronoi.js"></script>
|
||||
<script src="modules/heightmap-templates.js"></script>
|
||||
<script src="modules/heightmap-generator.js"></script>
|
||||
<script src="modules/ocean-layers.js"></script>
|
||||
<script src="modules/river-generator.js"></script>
|
||||
|
|
|
|||
244
libs/pell.js
244
libs/pell.js
|
|
@ -1,163 +1,157 @@
|
|||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
||||
typeof define === 'function' && define.amd ? define(factory) :
|
||||
(global.Pell = factory());
|
||||
}(this, (function () { 'use strict';
|
||||
"use strict";
|
||||
|
||||
const defaultParagraphSeparatorString = 'defaultParagraphSeparator'
|
||||
const formatBlock = 'formatBlock'
|
||||
const addEventListener = (parent, type, listener) => parent.addEventListener(type, listener)
|
||||
const appendChild = (parent, child) => parent.appendChild(child)
|
||||
const createElement = tag => document.createElement(tag)
|
||||
const queryCommandState = command => document.queryCommandState(command)
|
||||
const queryCommandValue = command => document.queryCommandValue(command)
|
||||
const exec = (command, value = null) => document.execCommand(command, false, value)
|
||||
window.Pell = (function () {
|
||||
const defaultParagraphSeparatorString = "defaultParagraphSeparator";
|
||||
const formatBlock = "formatBlock";
|
||||
const addEventListener = (parent, type, listener) => parent.addEventListener(type, listener);
|
||||
const appendChild = (parent, child) => parent.appendChild(child);
|
||||
const createElement = tag => document.createElement(tag);
|
||||
const queryCommandState = command => document.queryCommandState(command);
|
||||
const queryCommandValue = command => document.queryCommandValue(command);
|
||||
const exec = (command, value = null) => document.execCommand(command, false, value);
|
||||
|
||||
const defaultActions = {
|
||||
bold: {
|
||||
icon: '<b>B</b>',
|
||||
title: 'Bold',
|
||||
state: () => queryCommandState('bold'),
|
||||
result: () => exec('bold')
|
||||
icon: "<b>B</b>",
|
||||
title: "Bold",
|
||||
state: () => queryCommandState("bold"),
|
||||
result: () => exec("bold")
|
||||
},
|
||||
italic: {
|
||||
icon: '<i>I</i>',
|
||||
title: 'Italic',
|
||||
state: () => queryCommandState('italic'),
|
||||
result: () => exec('italic')
|
||||
icon: "<i>I</i>",
|
||||
title: "Italic",
|
||||
state: () => queryCommandState("italic"),
|
||||
result: () => exec("italic")
|
||||
},
|
||||
underline: {
|
||||
icon: '<u>U</u>',
|
||||
title: 'Underline',
|
||||
state: () => queryCommandState('underline'),
|
||||
result: () => exec('underline')
|
||||
icon: "<u>U</u>",
|
||||
title: "Underline",
|
||||
state: () => queryCommandState("underline"),
|
||||
result: () => exec("underline")
|
||||
},
|
||||
strikethrough: {
|
||||
icon: '<strike>S</strike>',
|
||||
title: 'Strike-through',
|
||||
state: () => queryCommandState('strikeThrough'),
|
||||
result: () => exec('strikeThrough')
|
||||
icon: "<strike>S</strike>",
|
||||
title: "Strike-through",
|
||||
state: () => queryCommandState("strikeThrough"),
|
||||
result: () => exec("strikeThrough")
|
||||
},
|
||||
heading1: {
|
||||
icon: '<b>H<sub>1</sub></b>',
|
||||
title: 'Heading 1',
|
||||
result: () => exec(formatBlock, '<h1>')
|
||||
icon: "<b>H<sub>1</sub></b>",
|
||||
title: "Heading 1",
|
||||
result: () => exec(formatBlock, "<h1>")
|
||||
},
|
||||
heading2: {
|
||||
icon: '<b>H<sub>2</sub></b>',
|
||||
title: 'Heading 2',
|
||||
result: () => exec(formatBlock, '<h2>')
|
||||
icon: "<b>H<sub>2</sub></b>",
|
||||
title: "Heading 2",
|
||||
result: () => exec(formatBlock, "<h2>")
|
||||
},
|
||||
paragraph: {
|
||||
icon: '¶',
|
||||
title: 'Paragraph',
|
||||
result: () => exec(formatBlock, '<p>')
|
||||
icon: "¶",
|
||||
title: "Paragraph",
|
||||
result: () => exec(formatBlock, "<p>")
|
||||
},
|
||||
quote: {
|
||||
icon: '“ ”',
|
||||
title: 'Quote',
|
||||
result: () => exec(formatBlock, '<blockquote>')
|
||||
icon: "“ ”",
|
||||
title: "Quote",
|
||||
result: () => exec(formatBlock, "<blockquote>")
|
||||
},
|
||||
olist: {
|
||||
icon: '#',
|
||||
title: 'Ordered List',
|
||||
result: () => exec('insertOrderedList')
|
||||
icon: "#",
|
||||
title: "Ordered List",
|
||||
result: () => exec("insertOrderedList")
|
||||
},
|
||||
ulist: {
|
||||
icon: '•',
|
||||
title: 'Unordered List',
|
||||
result: () => exec('insertUnorderedList')
|
||||
icon: "•",
|
||||
title: "Unordered List",
|
||||
result: () => exec("insertUnorderedList")
|
||||
},
|
||||
code: {
|
||||
icon: '</>',
|
||||
title: 'Code',
|
||||
result: () => exec(formatBlock, '<pre>')
|
||||
icon: "</>",
|
||||
title: "Code",
|
||||
result: () => exec(formatBlock, "<pre>")
|
||||
},
|
||||
line: {
|
||||
icon: '―',
|
||||
title: 'Horizontal Line',
|
||||
result: () => exec('insertHorizontalRule')
|
||||
icon: "―",
|
||||
title: "Horizontal Line",
|
||||
result: () => exec("insertHorizontalRule")
|
||||
},
|
||||
link: {
|
||||
icon: '🔗',
|
||||
title: 'Link',
|
||||
result: () => navigator.clipboard.readText().then(url => exec('createLink', url))
|
||||
icon: "🔗",
|
||||
title: "Link",
|
||||
result: () => navigator.clipboard.readText().then(url => exec("createLink", url))
|
||||
},
|
||||
image: {
|
||||
icon: '📷',
|
||||
title: 'Image',
|
||||
icon: "📷",
|
||||
title: "Image",
|
||||
result: () => {
|
||||
navigator.clipboard.readText().then(url => exec('insertImage', url))
|
||||
exec('enableObjectResizing')
|
||||
navigator.clipboard.readText().then(url => exec("insertImage", url));
|
||||
exec("enableObjectResizing");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const defaultClasses = {
|
||||
actionbar: 'pell-actionbar',
|
||||
button: 'pell-button',
|
||||
content: 'pell-content',
|
||||
selected: 'pell-button-selected'
|
||||
}
|
||||
|
||||
actionbar: "pell-actionbar",
|
||||
button: "pell-button",
|
||||
content: "pell-content",
|
||||
selected: "pell-button-selected"
|
||||
};
|
||||
|
||||
const init = settings => {
|
||||
const actions = settings.actions
|
||||
? (
|
||||
settings.actions.map(action => {
|
||||
if (typeof action === 'string') return defaultActions[action]
|
||||
else if (defaultActions[action.name]) return { ...defaultActions[action.name], ...action }
|
||||
return action
|
||||
? settings.actions.map(action => {
|
||||
if (typeof action === "string") return defaultActions[action];
|
||||
else if (defaultActions[action.name]) return {...defaultActions[action.name], ...action};
|
||||
return action;
|
||||
})
|
||||
)
|
||||
: Object.keys(defaultActions).map(action => defaultActions[action])
|
||||
|
||||
const classes = { ...defaultClasses, ...settings.classes }
|
||||
|
||||
const defaultParagraphSeparator = settings[defaultParagraphSeparatorString] || 'div'
|
||||
|
||||
const actionbar = createElement('div')
|
||||
actionbar.className = classes.actionbar
|
||||
appendChild(settings.element, actionbar)
|
||||
|
||||
const content = settings.element.content = createElement('div')
|
||||
content.contentEditable = true
|
||||
content.className = classes.content
|
||||
content.oninput = ({ target: { firstChild } }) => {
|
||||
if (firstChild && firstChild.nodeType === 3) exec(formatBlock, `<${defaultParagraphSeparator}>`)
|
||||
else if (content.innerHTML === '<br>') content.innerHTML = ''
|
||||
settings.onChange(content.innerHTML)
|
||||
}
|
||||
content.onkeydown = event => {
|
||||
if (event.key === 'Enter' && queryCommandValue(formatBlock) === 'blockquote') {
|
||||
setTimeout(() => exec(formatBlock, `<${defaultParagraphSeparator}>`), 0)
|
||||
}
|
||||
}
|
||||
appendChild(settings.element, content)
|
||||
|
||||
actions.forEach(action => {
|
||||
const button = createElement('button')
|
||||
button.className = classes.button
|
||||
button.innerHTML = action.icon
|
||||
button.title = action.title
|
||||
button.setAttribute('type', 'button')
|
||||
button.onclick = () => action.result() && content.focus()
|
||||
|
||||
if (action.state) {
|
||||
const handler = () => button.classList[action.state() ? 'add' : 'remove'](classes.selected)
|
||||
addEventListener(content, 'keyup', handler)
|
||||
addEventListener(content, 'mouseup', handler)
|
||||
addEventListener(button, 'click', handler)
|
||||
}
|
||||
|
||||
appendChild(actionbar, button)
|
||||
})
|
||||
|
||||
if (settings.styleWithCSS) exec('styleWithCSS')
|
||||
exec(defaultParagraphSeparatorString, defaultParagraphSeparator)
|
||||
|
||||
return settings.element
|
||||
}
|
||||
|
||||
return {exec, init}
|
||||
: Object.keys(defaultActions).map(action => defaultActions[action]);
|
||||
|
||||
})));
|
||||
const classes = {...defaultClasses, ...settings.classes};
|
||||
|
||||
const defaultParagraphSeparator = settings[defaultParagraphSeparatorString] || "div";
|
||||
|
||||
const actionbar = createElement("div");
|
||||
actionbar.className = classes.actionbar;
|
||||
appendChild(settings.element, actionbar);
|
||||
|
||||
const content = (settings.element.content = createElement("div"));
|
||||
content.contentEditable = true;
|
||||
content.className = classes.content;
|
||||
content.oninput = ({target: {firstChild}}) => {
|
||||
if (firstChild && firstChild.nodeType === 3) exec(formatBlock, `<${defaultParagraphSeparator}>`);
|
||||
else if (content.innerHTML === "<br>") content.innerHTML = "";
|
||||
settings.onChange(content.innerHTML);
|
||||
};
|
||||
content.onkeydown = event => {
|
||||
if (event.key === "Enter" && queryCommandValue(formatBlock) === "blockquote") {
|
||||
setTimeout(() => exec(formatBlock, `<${defaultParagraphSeparator}>`), 0);
|
||||
}
|
||||
};
|
||||
appendChild(settings.element, content);
|
||||
|
||||
actions.forEach(action => {
|
||||
const button = createElement("button");
|
||||
button.className = classes.button;
|
||||
button.innerHTML = action.icon;
|
||||
button.title = action.title;
|
||||
button.setAttribute("type", "button");
|
||||
button.onclick = () => action.result() && content.focus();
|
||||
|
||||
if (action.state) {
|
||||
const handler = () => button.classList[action.state() ? "add" : "remove"](classes.selected);
|
||||
addEventListener(content, "keyup", handler);
|
||||
addEventListener(content, "mouseup", handler);
|
||||
addEventListener(button, "click", handler);
|
||||
}
|
||||
|
||||
appendChild(actionbar, button);
|
||||
});
|
||||
|
||||
if (settings.styleWithCSS) exec("styleWithCSS");
|
||||
exec(defaultParagraphSeparatorString, defaultParagraphSeparator);
|
||||
|
||||
return settings.element;
|
||||
};
|
||||
|
||||
return {exec, init};
|
||||
})();
|
||||
|
|
|
|||
5
main.js
5
main.js
|
|
@ -2,7 +2,7 @@
|
|||
// https://github.com/Azgaar/Fantasy-Map-Generator
|
||||
|
||||
"use strict";
|
||||
const version = "1.651"; // generator version1
|
||||
const version = "1.652"; // generator version1
|
||||
document.title += " v" + version;
|
||||
|
||||
// Switches to disable/enable logging features
|
||||
|
|
@ -479,7 +479,8 @@ function invokeActiveZooming() {
|
|||
if (this.id === "burgLabels") return;
|
||||
const desired = +this.dataset.size;
|
||||
const relative = Math.max(rn((desired + desired / scale) / 2, 2), 1);
|
||||
this.setAttribute("font-size", relative);
|
||||
if (rescaleLabels.checked) this.setAttribute("font-size", relative);
|
||||
|
||||
const hidden = hideLabels.checked && (relative * scale < 6 || relative * scale > 60);
|
||||
if (hidden) this.classList.add("hidden");
|
||||
else this.classList.remove("hidden");
|
||||
|
|
|
|||
|
|
@ -1,12 +1,9 @@
|
|||
(function (global, factory) {
|
||||
typeof exports === "object" && typeof module !== "undefined" ? (module.exports = factory()) : typeof define === "function" && define.amd ? define(factory) : (global.BurgsAndStates = factory());
|
||||
})(this, function () {
|
||||
"use strict";
|
||||
"use strict";
|
||||
|
||||
window.BurgsAndStates = (function () {
|
||||
const generate = function () {
|
||||
const cells = pack.cells,
|
||||
cultures = pack.cultures,
|
||||
n = cells.i.length;
|
||||
const {cells, cultures} = pack;
|
||||
const n = cells.i.length;
|
||||
|
||||
cells.burg = new Uint16Array(n); // cell burg
|
||||
cells.road = new Uint16Array(n); // cell road power
|
||||
|
|
@ -37,7 +34,8 @@
|
|||
let count = +regionsInput.value;
|
||||
let burgs = [0];
|
||||
|
||||
const score = new Int16Array(cells.s.map(s => s * Math.random())); // cell score for capitals placement
|
||||
const rand = () => 0.5 + Math.random() * 0.5;
|
||||
const score = new Int16Array(cells.s.map(s => s * rand())); // cell score for capitals placement
|
||||
const sorted = cells.i.filter(i => score[i] > 0 && cells.culture[i]).sort((a, b) => score[b] - score[a]); // filtered and sorted array of indexes
|
||||
|
||||
if (sorted.length < count * 10) {
|
||||
|
|
@ -54,9 +52,8 @@
|
|||
let spacing = (graphWidth + graphHeight) / 2 / count; // min distance between capitals
|
||||
|
||||
for (let i = 0; burgs.length <= count; i++) {
|
||||
const cell = sorted[i],
|
||||
x = cells.p[cell][0],
|
||||
y = cells.p[cell][1];
|
||||
const cell = sorted[i];
|
||||
const [x, y] = cells.p[cell];
|
||||
|
||||
if (burgsTree.find(x, y, spacing) === undefined) {
|
||||
burgs.push({cell, x, y});
|
||||
|
|
@ -66,7 +63,9 @@
|
|||
if (i === sorted.length - 1) {
|
||||
WARN && console.warn("Cannot place capitals with current spacing. Trying again with reduced spacing");
|
||||
burgsTree = d3.quadtree();
|
||||
(i = -1), (burgs = [0]), (spacing /= 1.2);
|
||||
i = -1;
|
||||
burgs = [0];
|
||||
spacing /= 1.2;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1224,4 +1223,4 @@
|
|||
};
|
||||
|
||||
return {generate, expandStates, normalizeStates, assignColors, drawBurgs, specifyBurgs, defineBurgFeatures, getType, drawStateLabels, collectStatistics, generateCampaigns, generateDiplomacy, defineStateForms, getFullName, generateProvinces, updateCultures};
|
||||
});
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -1,170 +1,364 @@
|
|||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
||||
typeof define === 'function' && define.amd ? define(factory) :
|
||||
(global.COA = factory());
|
||||
}(this, (function () {'use strict';
|
||||
"use strict";
|
||||
|
||||
window.COA = (function () {
|
||||
const tinctures = {
|
||||
field: { metals: 3, colours: 4, stains: +P(.03), patterns: 1 },
|
||||
division: { metals: 5, colours: 8, stains: +P(.03), patterns: 1 },
|
||||
charge: { metals: 2, colours: 3, stains: +P(.05), patterns: 0 },
|
||||
metals: { argent: 3, or: 2 },
|
||||
colours: { gules: 5, azure: 4, sable: 3, purpure: 3, vert: 2 },
|
||||
stains: { murrey: 1, sanguine: 1, tenné: 1 },
|
||||
field: {metals: 3, colours: 4, stains: +P(0.03), patterns: 1},
|
||||
division: {metals: 5, colours: 8, stains: +P(0.03), patterns: 1},
|
||||
charge: {metals: 2, colours: 3, stains: +P(0.05), patterns: 0},
|
||||
metals: {argent: 3, or: 2},
|
||||
colours: {gules: 5, azure: 4, sable: 3, purpure: 3, vert: 2},
|
||||
stains: {murrey: 1, sanguine: 1, tenné: 1},
|
||||
patterns: {
|
||||
semy: 8, ermine: 6,
|
||||
vair: 4, counterVair: 1, vairInPale: 1, vairEnPointe: 2, 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 }
|
||||
}
|
||||
semy: 8,
|
||||
ermine: 6,
|
||||
vair: 4,
|
||||
counterVair: 1,
|
||||
vairInPale: 1,
|
||||
vairEnPointe: 2,
|
||||
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 = {
|
||||
// categories selection
|
||||
types: { conventional: 30, crosses: 10, animals: 2, animalHeads: 1, birds: 2, fantastic: 3, plants: 1, agriculture: 1, arms: 3, bodyparts: 1, people: 1, architecture: 1, miscellaneous: 3, inescutcheon: 3 },
|
||||
single: { conventional: 12, crosses: 8, plants: 2, animals: 10, animalHeads: 2, birds: 4, fantastic: 7, agriculture: 1, arms: 6, bodyparts: 1, people: 2, architecture: 1, miscellaneous: 10, inescutcheon: 5 },
|
||||
semy: { conventional: 12, crosses: 3, plants: 1 },
|
||||
types: {conventional: 30, crosses: 10, animals: 2, animalHeads: 1, birds: 2, fantastic: 3, plants: 1, agriculture: 1, arms: 3, bodyparts: 1, people: 1, architecture: 1, miscellaneous: 3, inescutcheon: 3},
|
||||
single: {conventional: 12, crosses: 8, plants: 2, animals: 10, animalHeads: 2, birds: 4, fantastic: 7, agriculture: 1, arms: 6, bodyparts: 1, people: 2, architecture: 1, miscellaneous: 10, inescutcheon: 5},
|
||||
semy: {conventional: 12, crosses: 3, plants: 1},
|
||||
// generic categories
|
||||
conventional: {
|
||||
lozenge: 2, fusil: 4, mascle: 4, 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
|
||||
lozenge: 2,
|
||||
fusil: 4,
|
||||
mascle: 4,
|
||||
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: {
|
||||
crossHummetty: 15, crossVoided: 1, crossPattee: 2, crossPatteeAlisee: 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
|
||||
crossHummetty: 15,
|
||||
crossVoided: 1,
|
||||
crossPattee: 2,
|
||||
crossPatteeAlisee: 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: {
|
||||
lionRampant: 5, 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
|
||||
lionRampant: 5,
|
||||
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 },
|
||||
fantastic: { dragonPassant: 2, dragonRampant: 2, wyvern: 1, wyvernWithWingsDisplayed: 1, griffinPassant: 1, griffinRampant: 1, eagleTwoHeards: 2, unicornRampant: 1, pegasus: 1, serpent: 1 },
|
||||
birds: { eagle: 9, raven: 1, cock: 3, parrot: 1, swan: 2, swanErased: 1, heron: 1, owl: 1 },
|
||||
plants: { tree: 1, oak: 1, cinquefoil: 1, rose: 1 },
|
||||
agriculture: { garb: 1, rake: 1 },
|
||||
arms: { sword: 5, sabre: 1, sabresCrossed: 1, hatchet: 2, axe: 2, lochaberAxe: 1, mallet: 1, bowWithArrow: 2, bow: 1, arrow: 1, arrowsSheaf: 1, helmet: 2 },
|
||||
bodyparts: { hand: 4, head: 1, headWreathed: 1 },
|
||||
people: { cavalier: 3, monk: 1, angel: 2 },
|
||||
architecture: { tower: 1, castle: 1 },
|
||||
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},
|
||||
birds: {eagle: 9, raven: 1, cock: 3, parrot: 1, swan: 2, swanErased: 1, heron: 1, owl: 1},
|
||||
plants: {tree: 1, oak: 1, cinquefoil: 1, rose: 1},
|
||||
agriculture: {garb: 1, rake: 1},
|
||||
arms: {sword: 5, sabre: 1, sabresCrossed: 1, hatchet: 2, axe: 2, lochaberAxe: 1, mallet: 1, bowWithArrow: 2, bow: 1, arrow: 1, arrowsSheaf: 1, helmet: 2},
|
||||
bodyparts: {hand: 4, head: 1, headWreathed: 1},
|
||||
people: {cavalier: 3, monk: 1, angel: 2},
|
||||
architecture: {tower: 1, castle: 1},
|
||||
miscellaneous: {
|
||||
crown: 3, 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
|
||||
crown: 3,
|
||||
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:
|
||||
Naval: { anchor: 3, boat: 1, lymphad: 2, armillarySphere: 1, escallop: 1, dolphin: 1 },
|
||||
Highland: { tower: 1, raven: 1, wolfHeadErased: 1, wolfPassant: 1, goat: 1, axe: 1 },
|
||||
River: { tower: 1, garb: 1, rake: 1, boat: 1, pike: 2, bullHeadCaboshed: 1 },
|
||||
Lake: { cancer: 2, escallop: 1, pike: 2, heron: 1, boat: 1, boat2: 2 },
|
||||
Nomadic: { pot: 1, buckle: 1, wheel: 2, sabre: 2, sabresCrossed: 1, bow: 2, arrow: 1, horseRampant: 1, horseSalient: 1, crescent: 1, camel: 3 },
|
||||
Hunting: { bugleHorn: 2, bugleHorn2: 1, stagsAttires: 2, attire: 2, hatchet: 1, bowWithArrow: 1, arrowsSheaf: 1, deerHeadCaboshed: 1, wolfStatant: 1, oak: 1 },
|
||||
Naval: {anchor: 3, boat: 1, lymphad: 2, armillarySphere: 1, escallop: 1, dolphin: 1},
|
||||
Highland: {tower: 1, raven: 1, wolfHeadErased: 1, wolfPassant: 1, goat: 1, axe: 1},
|
||||
River: {tower: 1, garb: 1, rake: 1, boat: 1, pike: 2, bullHeadCaboshed: 1},
|
||||
Lake: {cancer: 2, escallop: 1, pike: 2, heron: 1, boat: 1, boat2: 2},
|
||||
Nomadic: {pot: 1, buckle: 1, wheel: 2, sabre: 2, sabresCrossed: 1, bow: 2, arrow: 1, horseRampant: 1, horseSalient: 1, crescent: 1, camel: 3},
|
||||
Hunting: {bugleHorn: 2, bugleHorn2: 1, stagsAttires: 2, attire: 2, hatchet: 1, bowWithArrow: 1, arrowsSheaf: 1, deerHeadCaboshed: 1, wolfStatant: 1, oak: 1},
|
||||
// selection based on type
|
||||
City: { key: 3, bell: 2, lute: 1, tower: 1, castle: 1, mallet: 1 },
|
||||
Capital: { crown: 4, orb: 1, lute: 1, castle: 3, tower: 1 },
|
||||
Сathedra: { chalice: 1, orb: 1, crosier: 2, lamb: 1, monk: 2, angel: 3, crossLatin: 2, crossPatriarchal: 1, crossOrthodox: 1, crossCalvary: 1 },
|
||||
City: {key: 3, bell: 2, lute: 1, tower: 1, castle: 1, mallet: 1},
|
||||
Capital: {crown: 4, orb: 1, lute: 1, castle: 3, tower: 1},
|
||||
Сathedra: {chalice: 1, orb: 1, crosier: 2, lamb: 1, monk: 2, angel: 3, crossLatin: 2, crossPatriarchal: 1, crossOrthodox: 1, crossCalvary: 1},
|
||||
// specific cases
|
||||
natural: { fountain: "azure", garb: "or", raven: "sable" }, // charges to mainly use predefined colours
|
||||
sinister: [ // charges that can be sinister
|
||||
"crossGamma", "lionRampant", "lionPassant", "wolfRampant", "wolfPassant", "wolfStatant", "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"
|
||||
natural: {fountain: "azure", garb: "or", raven: "sable"}, // charges to mainly use predefined colours
|
||||
sinister: [
|
||||
// charges that can be sinister
|
||||
"crossGamma",
|
||||
"lionRampant",
|
||||
"lionPassant",
|
||||
"wolfRampant",
|
||||
"wolfPassant",
|
||||
"wolfStatant",
|
||||
"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 = {
|
||||
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 },
|
||||
complex: { e: 40, beh: 1, kn: 1, jeo: 1, abc: 2, jln: 7, jlh: 2, def: 1, abcpqh: 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},
|
||||
complex: {e: 40, beh: 1, kn: 1, jeo: 1, abc: 2, jln: 7, jlh: 2, def: 1, abcpqh: 1},
|
||||
divisions: {
|
||||
perPale: { e: 15, pq: 5, jo: 2, jl: 2, ABCDEFGHIJKL: 1 },
|
||||
perFess: { e: 12, kn: 4, jkl: 2, gizgiz: 1, jlh: 3, kmo: 1, ABCDEFGHIJKL: 1 },
|
||||
perBend: { e: 5, lm: 5, bcfdgh: 1 },
|
||||
perBendSinister: { e: 1, jo: 1 },
|
||||
perCross: { e: 4, jlmo: 1, j: 1, jo: 2, jl: 1 },
|
||||
perChevron: { e: 1, jlh: 1, dfk: 1, dfbh: 2, bdefh: 1 },
|
||||
perChevronReversed: { e: 1, mok: 2, dfh: 2, dfbh: 1, bdefh: 1 },
|
||||
perSaltire: { bhdf: 8, e: 3, abcdefgzi: 1, bh: 1, df: 1, ABCDEFGHIJKL: 1 },
|
||||
perPile: { ee: 3, be: 2, abceh: 1, abcabc: 1, jleh: 1 }
|
||||
perPale: {e: 15, pq: 5, jo: 2, jl: 2, ABCDEFGHIJKL: 1},
|
||||
perFess: {e: 12, kn: 4, jkl: 2, gizgiz: 1, jlh: 3, kmo: 1, ABCDEFGHIJKL: 1},
|
||||
perBend: {e: 5, lm: 5, bcfdgh: 1},
|
||||
perBendSinister: {e: 1, jo: 1},
|
||||
perCross: {e: 4, jlmo: 1, j: 1, jo: 2, jl: 1},
|
||||
perChevron: {e: 1, jlh: 1, dfk: 1, dfbh: 2, bdefh: 1},
|
||||
perChevronReversed: {e: 1, mok: 2, dfh: 2, dfbh: 1, bdefh: 1},
|
||||
perSaltire: {bhdf: 8, e: 3, abcdefgzi: 1, bh: 1, df: 1, ABCDEFGHIJKL: 1},
|
||||
perPile: {ee: 3, be: 2, abceh: 1, abcabc: 1, jleh: 1}
|
||||
},
|
||||
ordinariesOn: {
|
||||
pale: { ee: 12, beh: 10, kn: 3, bb: 1 },
|
||||
fess: { ee: 1, def: 3 },
|
||||
bar: { defdefdef: 1 },
|
||||
fessCotissed: { ee: 1, def: 3 },
|
||||
fessDoubleCotissed: { ee: 1, defdef: 3 },
|
||||
bend: { ee: 2, jo: 1, joe: 1 },
|
||||
bendSinister: { ee: 1, lm: 1, lem: 4 },
|
||||
bendlet: { joejoejoe: 1 },
|
||||
bendletSinister: { lemlemlem: 1 },
|
||||
bordure: { ABCDEFGHIJKL: 1 },
|
||||
chief: { abc: 5, bbb: 1 },
|
||||
quarter: { jjj: 1 },
|
||||
canton: { yyyy: 1 },
|
||||
cross: { eeee: 1, behdfbehdf: 3, behbehbeh: 2 },
|
||||
crossParted: { e: 5, ee: 1 },
|
||||
saltire: { ee: 5, jlemo: 1 },
|
||||
saltireParted: { e: 5, ee: 1 },
|
||||
pall: { ee: 1, jleh: 5, jlhh: 3 },
|
||||
pallReversed: { ee: 1, bemo: 5 },
|
||||
pile: { bbb: 1 },
|
||||
pileInBend: { eeee: 1, eeoo: 1 },
|
||||
pileInBendSinister: { eeee: 1, eemm: 1 }
|
||||
pale: {ee: 12, beh: 10, kn: 3, bb: 1},
|
||||
fess: {ee: 1, def: 3},
|
||||
bar: {defdefdef: 1},
|
||||
fessCotissed: {ee: 1, def: 3},
|
||||
fessDoubleCotissed: {ee: 1, defdef: 3},
|
||||
bend: {ee: 2, jo: 1, joe: 1},
|
||||
bendSinister: {ee: 1, lm: 1, lem: 4},
|
||||
bendlet: {joejoejoe: 1},
|
||||
bendletSinister: {lemlemlem: 1},
|
||||
bordure: {ABCDEFGHIJKL: 1},
|
||||
chief: {abc: 5, bbb: 1},
|
||||
quarter: {jjj: 1},
|
||||
canton: {yyyy: 1},
|
||||
cross: {eeee: 1, behdfbehdf: 3, behbehbeh: 2},
|
||||
crossParted: {e: 5, ee: 1},
|
||||
saltire: {ee: 5, jlemo: 1},
|
||||
saltireParted: {e: 5, ee: 1},
|
||||
pall: {ee: 1, jleh: 5, jlhh: 3},
|
||||
pallReversed: {ee: 1, bemo: 5},
|
||||
pile: {bbb: 1},
|
||||
pileInBend: {eeee: 1, eeoo: 1},
|
||||
pileInBendSinister: {eeee: 1, eemm: 1}
|
||||
},
|
||||
ordinariesOff: {
|
||||
pale: { yyy: 1 },
|
||||
fess: { abc: 3, abcz: 1 },
|
||||
bar: { abc: 2, abcgzi: 1, jlh: 5, bgi: 2, ach: 1 },
|
||||
gemelle: { abc: 1 },
|
||||
bend: { ccg: 2, ccc: 1 },
|
||||
bendSinister: { aai: 2, aaa: 1 },
|
||||
bendlet: { ccg: 2, ccc: 1 },
|
||||
bendletSinister: { aai: 2, aaa: 1 },
|
||||
bordure: { e: 4, jleh:2, kenken: 1, peqpeq: 1 },
|
||||
orle: { e: 4, jleh: 1, kenken: 1, peqpeq: 1 },
|
||||
chief: { emo: 2, emoz: 1, ez: 2 },
|
||||
terrace: { e: 5, def: 1, bdf: 3 },
|
||||
mount: { e: 5, def: 1, bdf: 3 },
|
||||
point: { e: 2, def: 1, bdf: 3, acbdef: 1 },
|
||||
flaunches: { e: 3, kn: 1, beh: 3 },
|
||||
gyron: { bh: 1 },
|
||||
quarter: { e: 1 },
|
||||
canton: { e: 5, beh: 1, def: 1, bdefh: 1, kn: 1 },
|
||||
cross: { acgi: 1 },
|
||||
pall: { BCKFEILGJbdmfo: 1 },
|
||||
pallReversed: { aczac: 1 },
|
||||
chevron: { ach: 3, hhh: 1 },
|
||||
chevronReversed: { bbb: 1 },
|
||||
pile: { acdfgi: 1, acac: 1 },
|
||||
pileInBend: { cg: 1 },
|
||||
pileInBendSinister: { ai: 1 },
|
||||
label: { defgzi: 2, eh: 3, defdefhmo: 1, egiegi: 1, pqn: 5 }
|
||||
pale: {yyy: 1},
|
||||
fess: {abc: 3, abcz: 1},
|
||||
bar: {abc: 2, abcgzi: 1, jlh: 5, bgi: 2, ach: 1},
|
||||
gemelle: {abc: 1},
|
||||
bend: {ccg: 2, ccc: 1},
|
||||
bendSinister: {aai: 2, aaa: 1},
|
||||
bendlet: {ccg: 2, ccc: 1},
|
||||
bendletSinister: {aai: 2, aaa: 1},
|
||||
bordure: {e: 4, jleh: 2, kenken: 1, peqpeq: 1},
|
||||
orle: {e: 4, jleh: 1, kenken: 1, peqpeq: 1},
|
||||
chief: {emo: 2, emoz: 1, ez: 2},
|
||||
terrace: {e: 5, def: 1, bdf: 3},
|
||||
mount: {e: 5, def: 1, bdf: 3},
|
||||
point: {e: 2, def: 1, bdf: 3, acbdef: 1},
|
||||
flaunches: {e: 3, kn: 1, beh: 3},
|
||||
gyron: {bh: 1},
|
||||
quarter: {e: 1},
|
||||
canton: {e: 5, beh: 1, def: 1, bdefh: 1, kn: 1},
|
||||
cross: {acgi: 1},
|
||||
pall: {BCKFEILGJbdmfo: 1},
|
||||
pallReversed: {aczac: 1},
|
||||
chevron: {ach: 3, hhh: 1},
|
||||
chevronReversed: {bbb: 1},
|
||||
pile: {acdfgi: 1, acac: 1},
|
||||
pileInBend: {cg: 1},
|
||||
pileInBendSinister: {ai: 1},
|
||||
label: {defgzi: 2, eh: 3, defdefhmo: 1, egiegi: 1, pqn: 5}
|
||||
},
|
||||
// charges
|
||||
inescutcheon: { e: 4, jln: 1 },
|
||||
mascle: { e: 15, abcdefgzi: 3, beh: 3, bdefh: 4, acegi: 1, kn: 3, joe: 2, abc: 3, jlh: 8, jleh: 1, df: 3, abcpqh: 4, pqe: 3, eknpq: 3 },
|
||||
lionRampant: { e: 10, def: 2, abc: 2, bdefh: 1, kn: 1, jlh: 2, abcpqh: 1 },
|
||||
lionPassant: { e: 10, def: 1, abc: 1, bdefh: 1, jlh: 1, abcpqh: 1 },
|
||||
wolfPassant: { e: 10, def: 1, abc: 1, bdefh: 1, jlh: 1, abcpqh: 1 },
|
||||
greyhoundСourant: { e: 10, def: 1, abc: 1, bdefh: 1, jlh: 1, abcpqh: 1 },
|
||||
griffinRampant: { e: 10, def: 2, abc: 2, bdefh: 1, kn: 1, jlh: 2, abcpqh: 1 },
|
||||
griffinPassant: { e: 10, def: 1, abc: 1, bdefh: 1, jlh: 1, abcpqh: 1 },
|
||||
boarRampant: { e: 12, beh: 1, kn: 1, jln: 2 },
|
||||
eagle: { e: 15, beh: 1, kn: 1, abc: 1, jlh: 2, def: 2, pq: 1 },
|
||||
raven: { e: 15, beh: 1, kn: 1, jeo: 1, abc: 3, jln: 3, def: 1 },
|
||||
wyvern: { e: 10, jln: 1 },
|
||||
garb: { e: 1, def: 3, abc: 2, beh: 1, kn: 1, jln: 3, jleh: 1, abcpqh: 1, joe: 1, lme: 1 },
|
||||
crown: { e: 10, abcdefgzi: 1, beh: 3, behdf: 2, acegi: 1, kn: 1, pq: 2, abc: 1, jln: 4, jleh: 1, def: 2, abcpqh: 3 },
|
||||
hand: { e: 10, jln: 2, kn: 1, jeo: 1, abc: 2, pqe: 1 },
|
||||
inescutcheon: {e: 4, jln: 1},
|
||||
mascle: {e: 15, abcdefgzi: 3, beh: 3, bdefh: 4, acegi: 1, kn: 3, joe: 2, abc: 3, jlh: 8, jleh: 1, df: 3, abcpqh: 4, pqe: 3, eknpq: 3},
|
||||
lionRampant: {e: 10, def: 2, abc: 2, bdefh: 1, kn: 1, jlh: 2, abcpqh: 1},
|
||||
lionPassant: {e: 10, def: 1, abc: 1, bdefh: 1, jlh: 1, abcpqh: 1},
|
||||
wolfPassant: {e: 10, def: 1, abc: 1, bdefh: 1, jlh: 1, abcpqh: 1},
|
||||
greyhoundСourant: {e: 10, def: 1, abc: 1, bdefh: 1, jlh: 1, abcpqh: 1},
|
||||
griffinRampant: {e: 10, def: 2, abc: 2, bdefh: 1, kn: 1, jlh: 2, abcpqh: 1},
|
||||
griffinPassant: {e: 10, def: 1, abc: 1, bdefh: 1, jlh: 1, abcpqh: 1},
|
||||
boarRampant: {e: 12, beh: 1, kn: 1, jln: 2},
|
||||
eagle: {e: 15, beh: 1, kn: 1, abc: 1, jlh: 2, def: 2, pq: 1},
|
||||
raven: {e: 15, beh: 1, kn: 1, jeo: 1, abc: 3, jln: 3, def: 1},
|
||||
wyvern: {e: 10, jln: 1},
|
||||
garb: {e: 1, def: 3, abc: 2, beh: 1, kn: 1, jln: 3, jleh: 1, abcpqh: 1, joe: 1, lme: 1},
|
||||
crown: {e: 10, abcdefgzi: 1, beh: 3, behdf: 2, acegi: 1, kn: 1, pq: 2, abc: 1, jln: 4, jleh: 1, def: 2, abcpqh: 3},
|
||||
hand: {e: 10, jln: 2, kn: 1, jeo: 1, abc: 2, pqe: 1},
|
||||
armillarySphere: {e: 1},
|
||||
tree: {e: 1},
|
||||
lymphad: {e: 1},
|
||||
|
|
@ -175,33 +369,92 @@
|
|||
};
|
||||
|
||||
const lines = {
|
||||
straight: 50, wavy: 8, engrailed: 4, 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
|
||||
straight: 50,
|
||||
wavy: 8,
|
||||
engrailed: 4,
|
||||
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 = {
|
||||
variants: { perPale: 5, perFess: 5, perBend: 2, perBendSinister: 1, perChevron: 1, perChevronReversed: 1, perCross: 5, perPile: 1, perSaltire: 1, gyronny: 1, chevronny: 1 },
|
||||
variants: {perPale: 5, perFess: 5, perBend: 2, perBendSinister: 1, perChevron: 1, perChevronReversed: 1, perCross: 5, perPile: 1, perSaltire: 1, gyronny: 1, chevronny: 1},
|
||||
perPale: lines,
|
||||
perFess: lines,
|
||||
perBend: lines,
|
||||
perBendSinister: lines,
|
||||
perChevron: lines,
|
||||
perChevronReversed: lines,
|
||||
perCross: { straight: 20, wavy: 5, engrailed: 4, invecked: 3, rayonne: 1, embattled: 1, raguly: 1, urdy: 1, indented: 2, dentilly: 1, bevilled: 1, angled: 1, embattledGhibellin: 1, embattledGrady: 1, dovetailedIndented: 1, dovetailed: 1, potenty: 1, potentyDexter: 1, potentySinister: 1, nebuly: 1 },
|
||||
perCross: {straight: 20, wavy: 5, engrailed: 4, invecked: 3, rayonne: 1, embattled: 1, raguly: 1, urdy: 1, indented: 2, dentilly: 1, bevilled: 1, angled: 1, embattledGhibellin: 1, embattledGrady: 1, dovetailedIndented: 1, dovetailed: 1, potenty: 1, potentyDexter: 1, potentySinister: 1, nebuly: 1},
|
||||
perPile: lines
|
||||
};
|
||||
|
||||
const ordinaries = {
|
||||
lined: {
|
||||
pale: 7, 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
|
||||
pale: 7,
|
||||
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: {
|
||||
bordure: 8, orle: 4, 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
|
||||
bordure: 8,
|
||||
orle: 4,
|
||||
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,60 +468,61 @@
|
|||
simple: {round: 12, oval: 6, vesicaPiscis: 1, square: 1, diamond: 2, no: 0},
|
||||
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}
|
||||
}
|
||||
};
|
||||
|
||||
const generate = function(parent, kinship, dominion, type) {
|
||||
const generate = function (parent, kinship, dominion, type) {
|
||||
if (!parent || parent === "custom") {
|
||||
parent = null;
|
||||
kinship = 0;
|
||||
dominion = 0;
|
||||
}
|
||||
let usedPattern = null, usedTinctures = [];
|
||||
let usedPattern = null,
|
||||
usedTinctures = [];
|
||||
|
||||
const t1 = P(kinship) ? parent.t1 : getTincture("field");
|
||||
if (t1.includes("-")) usedPattern = t1;
|
||||
const coa = {t1};
|
||||
|
||||
let charge = P(usedPattern ? .5 : .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 ordinary = !charge && P(.65) || P(.3) ? linedOrdinary ? linedOrdinary : rw(ordinaries.straight) : null; // 36% for ordinary
|
||||
let charge = P(usedPattern ? 0.5 : 0.93) ? true : false; // 80% for charge
|
||||
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(0.65)) || P(0.3) ? (linedOrdinary ? linedOrdinary : rw(ordinaries.straight)) : null; // 36% for 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 division = divisioned ? parent?.division && P(kinship - .1) ? parent.division.division : rw(divisions.variants) : null;
|
||||
if (charge) charge =
|
||||
parent?.charges && P(kinship - .1) ? parent.charges[0].charge :
|
||||
type && type !== "Generic" && P(.2) ? rw(charges[type]) :
|
||||
selectCharge();
|
||||
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 - 0.1) ? parent.division.division : rw(divisions.variants)) : null;
|
||||
if (charge) charge = parent?.charges && P(kinship - 0.1) ? parent.charges[0].charge : type && type !== "Generic" && P(0.2) ? rw(charges[type]) : selectCharge();
|
||||
|
||||
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};
|
||||
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) {
|
||||
coa.ordinaries = [{ordinary, t: getTincture("charge", usedTinctures, coa.t1)}];
|
||||
if (linedOrdinary) coa.ordinaries[0].line = usedPattern || (division && P(.7)) ? "straight" : rw(lines);
|
||||
if (division && !charge && !usedPattern && P(.5) && ordinary !== "bordure" && ordinary !== "orle") {
|
||||
if (P(.8)) coa.ordinaries[0].divided = "counter"; // 40%
|
||||
else if (P(.6)) coa.ordinaries[0].divided = "field"; // 6%
|
||||
if (linedOrdinary) coa.ordinaries[0].line = usedPattern || (division && P(0.7)) ? "straight" : rw(lines);
|
||||
if (division && !charge && !usedPattern && P(0.5) && ordinary !== "bordure" && ordinary !== "orle") {
|
||||
if (P(0.8)) coa.ordinaries[0].divided = "counter";
|
||||
// 40%
|
||||
else if (P(0.6)) coa.ordinaries[0].divided = "field";
|
||||
// 6%
|
||||
else coa.ordinaries[0].divided = "division"; // 4%
|
||||
}
|
||||
}
|
||||
|
||||
if (charge) {
|
||||
let p = "e", t = "gules";
|
||||
let p = "e",
|
||||
t = "gules";
|
||||
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)
|
||||
p = rw(positions.ordinariesOn[ordinary]);
|
||||
while (charges.natural[charge] === ordinaryT) charge = selectCharge();
|
||||
t = !usedPattern && P(.3) ? coa.t1 : getTincture("charge", [], ordinaryT);
|
||||
} else if (positions.ordinariesOff[ordinary] && P(.95)) {
|
||||
t = !usedPattern && P(0.3) ? coa.t1 : getTincture("charge", [], ordinaryT);
|
||||
} else if (positions.ordinariesOff[ordinary] && P(0.95)) {
|
||||
// place charge out of ordinary (use tincture of ordinary type)
|
||||
p = rw(positions.ordinariesOff[ordinary]);
|
||||
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]) {
|
||||
// place charge in fields made by division
|
||||
p = rw(positions.divisions[division]);
|
||||
|
|
@ -289,43 +543,41 @@
|
|||
if (charges.natural[charge]) t = charges.natural[charge]; // natural tincture
|
||||
coa.charges = [{charge, t, p}];
|
||||
|
||||
if (p === "ABCDEFGHIKL" && P(.95)) {
|
||||
if (p === "ABCDEFGHIKL" && P(0.95)) {
|
||||
// add central charge if charge is in bordure
|
||||
coa.charges[0].charge = rw(charges.conventional);
|
||||
const charge = selectCharge(charges.single);
|
||||
const t = getTincture("charge", usedTinctures, coa.t1);
|
||||
coa.charges.push({charge, t, p: "e"});
|
||||
} else if (P(.8) && charge === "inescutcheon") {
|
||||
} else if (P(0.8) && charge === "inescutcheon") {
|
||||
// add charge to inescutcheon
|
||||
const charge = selectCharge(charges.types);
|
||||
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) {
|
||||
const allowCounter = !usedPattern && (!coa.line || coa.line === "straight");
|
||||
|
||||
// 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";
|
||||
if (P(.95)) {
|
||||
const p2 = p === "e" || P(.5) ? "e" : rw(positions.divisions[division]);
|
||||
if (P(0.95)) {
|
||||
const p2 = p === "e" || P(0.5) ? "e" : rw(positions.divisions[division]);
|
||||
const charge = selectCharge(charges.single);
|
||||
const t = getTincture("charge", usedTinctures, coa.division.t);
|
||||
coa.charges.push({charge, t, p: p2, divided: "division"});
|
||||
}
|
||||
}
|
||||
else if (allowCounter && P(.4)) coa.charges[0].divided = "counter"; // counterchanged, 40%
|
||||
else if (["perPale", "perFess", "perBend", "perBendSinister"].includes(division) && P(.8)) { // place 2 charges in division standard positions
|
||||
const [p1, p2] = division === "perPale" ? ["p", "q"] :
|
||||
division === "perFess" ? ["k", "n"] :
|
||||
division === "perBend" ? ["l", "m"] :
|
||||
["j", "o"]; // perBendSinister
|
||||
} else if (allowCounter && P(0.4)) coa.charges[0].divided = "counter";
|
||||
// counterchanged, 40%
|
||||
else if (["perPale", "perFess", "perBend", "perBendSinister"].includes(division) && P(0.8)) {
|
||||
// place 2 charges in division standard positions
|
||||
const [p1, p2] = division === "perPale" ? ["p", "q"] : division === "perFess" ? ["k", "n"] : division === "perBend" ? ["l", "m"] : ["j", "o"]; // perBendSinister
|
||||
coa.charges[0].p = p1;
|
||||
|
||||
const charge = selectCharge(charges.single);
|
||||
const t = getTincture("charge", usedTinctures, coa.division.t);
|
||||
coa.charges.push({charge, t, p: p2});
|
||||
}
|
||||
else if (["perCross", "perSaltire"].includes(division) && P(.5)) { // place 4 charges in division standard positions
|
||||
} else if (["perCross", "perSaltire"].includes(division) && P(0.5)) {
|
||||
// place 4 charges in division standard positions
|
||||
const [p1, p2, p3, p4] = division === "perCross" ? ["j", "l", "m", "o"] : ["b", "d", "f", "h"];
|
||||
coa.charges[0].p = p1;
|
||||
|
||||
|
|
@ -338,8 +590,7 @@
|
|||
const c4 = selectCharge(charges.single);
|
||||
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});
|
||||
}
|
||||
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));
|
||||
|
|
@ -351,8 +602,8 @@
|
|||
c.p = [...new Set(c.p)].join("");
|
||||
|
||||
// define orientation
|
||||
if (P(.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.sinister.includes(c.charge)) c.sinister = 1;
|
||||
if (P(0.02) && charges.reversed.includes(c.charge)) c.reversed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -380,24 +631,26 @@
|
|||
if (!coa.charges) coa.charges = [];
|
||||
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) {
|
||||
const type = set ? rw(set) : ordinary || divisioned ? rw(charges.types): rw(charges.single);
|
||||
const type = set ? rw(set) : ordinary || divisioned ? rw(charges.types) : rw(charges.single);
|
||||
return type === "inescutcheon" ? "inescutcheon" : rw(charges[type]);
|
||||
}
|
||||
|
||||
// select tincture: element type (field, division, charge), used field tinctures, field type to follow 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
|
||||
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
|
||||
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
|
||||
|
||||
|
|
@ -425,39 +678,60 @@
|
|||
if (Object.keys(tinctures.stains).includes(tincture)) return "stains";
|
||||
else return "pattern";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function definePattern(pattern, element, size = "") {
|
||||
let t1 = null, t2 = null;
|
||||
if (P(.1)) size = "-small";
|
||||
else if (P(.1)) size = "-smaller";
|
||||
else if (P(.01)) size = "-big";
|
||||
else if (P(.005)) size = "-smallest";
|
||||
let t1 = null,
|
||||
t2 = null;
|
||||
if (P(0.1)) size = "-small";
|
||||
else if (P(0.1)) size = "-smaller";
|
||||
else if (P(0.01)) size = "-big";
|
||||
else if (P(0.005)) size = "-smallest";
|
||||
|
||||
// apply standard tinctures
|
||||
if (P(.5) && ["vair", "vairInPale", "vairEnPointe"].includes(pattern)) {t1 = "azure"; t2 = "argent";}
|
||||
else if (P(.8) && pattern === "ermine") {t1 = "argent"; t2 = "sable";}
|
||||
else if (pattern === "pappellony") {
|
||||
if (P(.2)) {t1 = "gules"; t2 = "or";}
|
||||
else if (P(.2)) {t1 = "argent"; t2 = "sable";}
|
||||
else if (P(.2)) {t1 = "azure"; t2 = "argent";}
|
||||
}
|
||||
else if (pattern === "masoned") {
|
||||
if (P(.3)) {t1 = "gules"; t2 = "argent";}
|
||||
else if (P(.3)) {t1 = "argent"; t2 = "sable";}
|
||||
else if (P(.1)) {t1 = "or"; t2 = "sable";}
|
||||
}
|
||||
else if (pattern === "fretty") {
|
||||
if (t2 === "sable" || P(.35)) {t1 = "argent"; t2 = "gules";}
|
||||
else if (P(.25)) {t1 = "sable"; t2 = "or";}
|
||||
else if (P(.15)) {t1 = "gules"; t2 = "argent";}
|
||||
}
|
||||
else if (pattern === "semy") pattern += "_of_" + selectCharge(charges.semy);
|
||||
|
||||
if (P(0.5) && ["vair", "vairInPale", "vairEnPointe"].includes(pattern)) {
|
||||
t1 = "azure";
|
||||
t2 = "argent";
|
||||
} else if (P(0.8) && pattern === "ermine") {
|
||||
t1 = "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") {
|
||||
if (P(0.3)) {
|
||||
t1 = "gules";
|
||||
t2 = "argent";
|
||||
} else if (P(0.3)) {
|
||||
t1 = "argent";
|
||||
t2 = "sable";
|
||||
} else if (P(0.1)) {
|
||||
t1 = "or";
|
||||
t2 = "sable";
|
||||
}
|
||||
} else if (pattern === "fretty") {
|
||||
if (t2 === "sable" || P(0.35)) {
|
||||
t1 = "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);
|
||||
|
||||
if (!t1 || !t2) {
|
||||
const startWithMetal = P(.7);
|
||||
const startWithMetal = P(0.7);
|
||||
t1 = startWithMetal ? rw(tinctures.metals) : rw(tinctures.colours);
|
||||
t2 = startWithMetal ? rw(tinctures.colours) : rw(tinctures.metals);
|
||||
}
|
||||
|
|
@ -474,28 +748,30 @@
|
|||
|
||||
function replaceTincture(t, n) {
|
||||
const type = getType(t);
|
||||
while (!n || n === t) {n = rw(tinctures[type]);}
|
||||
while (!n || n === t) {
|
||||
n = rw(tinctures[type]);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
function getSize(p, o = null, d = null) {
|
||||
if (p === "e" && (o === "bordure" || o === "orle")) return 1.1;
|
||||
if (p === "e") return 1.5;
|
||||
if (p === "jln" || p === "jlh") return .7;
|
||||
if (p === "abcpqh" || p === "ez" || p === "be") return .5;
|
||||
if (["a", "b", "c", "d", "f", "g", "h", "i", "bh", "df"].includes(p)) return .5;
|
||||
if (["j", "l", "m", "o", "jlmo"].includes(p) && d === "perCross") return .6;
|
||||
if (p.length > 10) return .18; // >10 (bordure)
|
||||
if (p.length > 7) return .3; // 8, 9, 10
|
||||
if (p.length > 4) return .4; // 5, 6, 7
|
||||
if (p.length > 2) return .5; // 3, 4
|
||||
return .7; // 1, 2
|
||||
if (p === "jln" || p === "jlh") return 0.7;
|
||||
if (p === "abcpqh" || p === "ez" || p === "be") return 0.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 0.6;
|
||||
if (p.length > 10) return 0.18; // >10 (bordure)
|
||||
if (p.length > 7) return 0.3; // 8, 9, 10
|
||||
if (p.length > 4) return 0.4; // 5, 6, 7
|
||||
if (p.length > 2) return 0.5; // 3, 4
|
||||
return 0.7; // 1, 2
|
||||
}
|
||||
|
||||
return coa;
|
||||
}
|
||||
};
|
||||
|
||||
const getShield = function(culture, state) {
|
||||
const getShield = function (culture, state) {
|
||||
const emblemShape = document.getElementById("emblemShape");
|
||||
const shapeGroup = emblemShape.selectedOptions[0]?.parentNode.label || "Diversiform";
|
||||
if (shapeGroup !== "Diversiform") return emblemShape.value;
|
||||
|
|
@ -504,11 +780,10 @@
|
|||
if (pack.cultures[culture].shield) return pack.cultures[culture].shield;
|
||||
console.error("Shield shape is not defined on culture level", pack.cultures[culture]);
|
||||
return "heater";
|
||||
}
|
||||
};
|
||||
|
||||
const toString = coa => JSON.stringify(coa).replaceAll("#", "%23");
|
||||
const copy = coa => JSON.parse(JSON.stringify(coa));
|
||||
|
||||
return {generate, toString, copy, getShield, shields};
|
||||
|
||||
})));
|
||||
})();
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,13 +1,10 @@
|
|||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
||||
typeof define === 'function' && define.amd ? define(factory) :
|
||||
(global.Cultures = factory());
|
||||
}(this, (function () {'use strict';
|
||||
"use strict";
|
||||
|
||||
window.Cultures = (function () {
|
||||
let cells;
|
||||
|
||||
const generate = function() {
|
||||
TIME && console.time('generateCultures');
|
||||
const generate = function () {
|
||||
TIME && console.time("generateCultures");
|
||||
cells = pack.cells;
|
||||
cells.culture = new Uint16Array(cells.i.length); // cell cultures
|
||||
let count = Math.min(+culturesInput.value, +culturesSet.selectedOptions[0].dataset.max);
|
||||
|
|
@ -17,13 +14,19 @@
|
|||
count = Math.floor(populated.length / 50);
|
||||
if (!count) {
|
||||
WARN && console.warn(`There are no populated cells. Cannot generate cultures`);
|
||||
pack.cultures = [{name:"Wildlands", i:0, base:1, shield:"round"}];
|
||||
pack.cultures = [{name: "Wildlands", i: 0, base: 1, shield: "round"}];
|
||||
alertMessage.innerHTML = `
|
||||
The climate is harsh and people cannot live in this world.<br>
|
||||
No cultures, states and burgs will be created.<br>
|
||||
Please consider changing climate settings in the World Configurator`;
|
||||
$("#alert").dialog({resizable: false, title: "Extreme climate warning",
|
||||
buttons: {Ok: function() {$(this).dialog("close");}}
|
||||
$("#alert").dialog({
|
||||
resizable: false,
|
||||
title: "Extreme climate warning",
|
||||
buttons: {
|
||||
Ok: function () {
|
||||
$(this).dialog("close");
|
||||
}
|
||||
}
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
|
|
@ -32,22 +35,28 @@
|
|||
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>
|
||||
Please consider changing climate settings in the World Configurator`;
|
||||
$("#alert").dialog({resizable: false, title: "Extreme climate warning",
|
||||
buttons: {Ok: function() {$(this).dialog("close");}}
|
||||
$("#alert").dialog({
|
||||
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 colors = getColors(count);
|
||||
const emblemShape = document.getElementById("emblemShape").value;
|
||||
|
||||
const codes = [];
|
||||
cultures.forEach(function(c, i) {
|
||||
const cell = c.center = placeCenter(c.sort ? c.sort : (i) => cells.s[i]);
|
||||
cultures.forEach(function (c, i) {
|
||||
const cell = (c.center = placeCenter(c.sort ? c.sort : i => cells.s[i]));
|
||||
centers.add(cells.p[cell]);
|
||||
c.i = i+1;
|
||||
c.i = i + 1;
|
||||
delete c.odd;
|
||||
delete c.sort;
|
||||
c.color = colors[i];
|
||||
|
|
@ -56,20 +65,24 @@
|
|||
c.origin = 0;
|
||||
c.code = abbreviate(c.name, codes);
|
||||
codes.push(c.code);
|
||||
cells.culture[cell] = i+1;
|
||||
cells.culture[cell] = i + 1;
|
||||
if (emblemShape === "random") c.shield = getRandomShield();
|
||||
});
|
||||
|
||||
function placeCenter(v) {
|
||||
let c, spacing = (graphWidth + graphHeight) / 2 / count;
|
||||
const sorted = [...populated].sort((a, b) => v(b) - v(a)), max = Math.floor(sorted.length / 2);
|
||||
do {c = sorted[biased(0, max, 5)]; spacing *= .9;}
|
||||
while (centers.find(cells.p[c][0], cells.p[c][1], spacing) !== undefined);
|
||||
let c,
|
||||
spacing = (graphWidth + graphHeight) / 2 / count;
|
||||
const sorted = [...populated].sort((a, b) => v(b) - v(a)),
|
||||
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;
|
||||
}
|
||||
|
||||
// the first culture with id 0 is for wildlands
|
||||
cultures.unshift({name:"Wildlands", i:0, base:1, origin:null, shield:"round"});
|
||||
cultures.unshift({name: "Wildlands", i: 0, base: 1, origin: null, shield: "round"});
|
||||
|
||||
// make sure all bases exist in nameBases
|
||||
if (!nameBases.length) {
|
||||
|
|
@ -77,7 +90,7 @@
|
|||
nameBases = Names.getNameBases();
|
||||
}
|
||||
|
||||
cultures.forEach(c => c.base = c.base % nameBases.length);
|
||||
cultures.forEach(c => (c.base = c.base % nameBases.length));
|
||||
|
||||
function selectCultures(c) {
|
||||
let def = getDefault(c);
|
||||
|
|
@ -87,11 +100,11 @@
|
|||
const count = Math.min(c, def.length);
|
||||
const cultures = [];
|
||||
|
||||
for (let culture, rnd, i=0; cultures.length < count && i < 200; i++) {
|
||||
for (let culture, rnd, i = 0; cultures.length < count && i < 200; i++) {
|
||||
do {
|
||||
rnd = rand(def.length-1);
|
||||
rnd = rand(def.length - 1);
|
||||
culture = def[rnd];
|
||||
} while (!P(culture.odd))
|
||||
} while (!P(culture.odd));
|
||||
cultures.push(culture);
|
||||
def.splice(rnd, 1);
|
||||
}
|
||||
|
|
@ -100,31 +113,31 @@
|
|||
|
||||
// set culture type based on culture center position
|
||||
function defineCultureType(i) {
|
||||
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
|
||||
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 (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 (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(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.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";
|
||||
}
|
||||
|
||||
function defineCultureExpansionism(type) {
|
||||
let base = 1; // Generic
|
||||
if (type === "Lake") base = .8; else
|
||||
if (type === "Naval") base = 1.5; else
|
||||
if (type === "River") base = .9; else
|
||||
if (type === "Nomadic") base = 1.5; else
|
||||
if (type === "Hunting") base = .7; else
|
||||
if (type === "Highland") base = 1.2;
|
||||
return rn((Math.random() * powerInput.value / 2 + 1) * base, 1);
|
||||
if (type === "Lake") base = 0.8;
|
||||
else if (type === "Naval") base = 1.5;
|
||||
else if (type === "River") base = 0.9;
|
||||
else if (type === "Nomadic") base = 1.5;
|
||||
else if (type === "Hunting") base = 0.7;
|
||||
else if (type === "Highland") base = 1.2;
|
||||
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();
|
||||
let culture, base, name;
|
||||
|
||||
|
|
@ -139,7 +152,10 @@
|
|||
name = Names.getCulture(culture, 5, 8, "");
|
||||
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 color = d3.color(d3.scaleSequential(d3.interpolateRainbow)(Math.random())).hex();
|
||||
|
||||
|
|
@ -148,220 +164,231 @@
|
|||
const emblemShape = document.getElementById("emblemShape").value;
|
||||
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
|
||||
const cells = pack.cells, s = cells.s, sMax = d3.max(s), t = cells.t, 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
|
||||
const cells = pack.cells,
|
||||
s = cells.s,
|
||||
sMax = d3.max(s),
|
||||
t = cells.t,
|
||||
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") {
|
||||
return [
|
||||
{name:"Shwazen", base:0, odd:1, sort: i => n(i) / td(i, 10) / bd(i, [6, 8]), shield:"swiss"},
|
||||
{name:"Angshire", base:1, odd:1, sort: i => n(i) / td(i, 10) / sf(i), shield:"wedged"},
|
||||
{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:"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:"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:"Romian", base:8, odd:.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:"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:"Turchian", base: 16, odd:.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:"Keltan", base: 22, odd:.05, sort: i => n(i) / td(i, 11) / bd(i, [6, 8]) * t[i], shield:"oval"}
|
||||
{name: "Shwazen", base: 0, odd: 1, sort: i => n(i) / td(i, 10) / bd(i, [6, 8]), shield: "swiss"},
|
||||
{name: "Angshire", base: 1, odd: 1, sort: i => n(i) / td(i, 10) / sf(i), shield: "wedged"},
|
||||
{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: "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: "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: "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: "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: "Turchian", base: 16, odd: 0.05, sort: i => n(i) / td(i, 14), shield: "round"},
|
||||
{name: "Euskati", base: 20, odd: 0.05, sort: i => (n(i) / td(i, 15)) * h[i], shield: "oldFrench"},
|
||||
{name: "Keltan", base: 22, odd: 0.05, sort: i => (n(i) / td(i, 11) / bd(i, [6, 8])) * t[i], shield: "oval"}
|
||||
];
|
||||
}
|
||||
|
||||
if (culturesSet.value === "oriental") {
|
||||
return [
|
||||
{name:"Koryo", base:10, odd: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:"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:"Berberan", base: 17, odd:.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:"Efratic", base: 23, odd:.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:"Maui", base: 25, odd:.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:"Vietic", base: 29, odd:.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:"Ulus", base:31, odd:1, sort: i => n(i) / td(i, 5) / bd(i, [2, 4, 10], 7) * t[i], shield:"banner"}
|
||||
{name: "Koryo", base: 10, odd: 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: "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: "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: "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: "Maui", base: 25, odd: 0.2, sort: i => n(i) / td(i, 24) / sf(i) / t[i], shield: "vesicaPiscis"},
|
||||
{name: "Carnatic", base: 26, odd: 0.5, sort: i => n(i) / td(i, 26), shield: "round"},
|
||||
{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: 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"}
|
||||
];
|
||||
}
|
||||
|
||||
if (culturesSet.value === "english") {
|
||||
const getName = () => Names.getBase(1, 5, 9, "", 0);
|
||||
return [
|
||||
{name:getName(), base:1, odd:1, shield:"heater"},
|
||||
{name:getName(), base:1, odd:1, shield:"wedged"},
|
||||
{name:getName(), base:1, odd:1, shield:"swiss"},
|
||||
{name:getName(), base:1, odd:1, shield:"oldFrench"},
|
||||
{name:getName(), base:1, odd:1, shield:"swiss"},
|
||||
{name:getName(), base:1, odd:1, shield:"spanish"},
|
||||
{name:getName(), base:1, odd:1, shield:"hessen"},
|
||||
{name:getName(), base:1, odd:1, shield:"fantasy5"},
|
||||
{name:getName(), base:1, odd:1, shield:"fantasy4"},
|
||||
{name:getName(), base:1, odd:1, shield:"fantasy1"}
|
||||
{name: getName(), base: 1, odd: 1, shield: "heater"},
|
||||
{name: getName(), base: 1, odd: 1, shield: "wedged"},
|
||||
{name: getName(), base: 1, odd: 1, shield: "swiss"},
|
||||
{name: getName(), base: 1, odd: 1, shield: "oldFrench"},
|
||||
{name: getName(), base: 1, odd: 1, shield: "swiss"},
|
||||
{name: getName(), base: 1, odd: 1, shield: "spanish"},
|
||||
{name: getName(), base: 1, odd: 1, shield: "hessen"},
|
||||
{name: getName(), base: 1, odd: 1, shield: "fantasy5"},
|
||||
{name: getName(), base: 1, odd: 1, shield: "fantasy4"},
|
||||
{name: getName(), base: 1, odd: 1, shield: "fantasy1"}
|
||||
];
|
||||
}
|
||||
|
||||
if (culturesSet.value === "antique") {
|
||||
return [
|
||||
{name:"Roman", base:8, odd:1, sort: i => n(i) / td(i, 14) / t[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, 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, 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:"Celtic", base:22, odd:1, sort: i => n(i) / td(i, 11) ** .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:"Persian", base:24, odd:.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:"Cantabrian", base: 20, odd:.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:"Carthaginian", base: 17, odd:.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: "Roman", base: 8, odd: 1, sort: i => n(i) / td(i, 14) / t[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, 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, 19) / sf(i)) * h[i], shield: "boeotian"}, // 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) ** 0.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: 0.8, sort: i => (n(i) / td(i, 18)) * h[i], shield: "oval"}, // 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: 0.5, sort: i => (n(i) / td(i, 16)) * h[i], shield: "oval"}, // Basque
|
||||
{name: "Estian", base: 9, odd: 0.2, sort: i => (n(i) / td(i, 5)) * t[i], shield: "pavise"}, // Finnic
|
||||
{name: "Carthaginian", base: 17, odd: 0.3, sort: i => n(i) / td(i, 19) / sf(i), shield: "oval"}, // Berber
|
||||
{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") {
|
||||
return [
|
||||
// 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:"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:"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:"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:"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:"Ugluk (Orkish)", base: 37, odd:.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:"Rake (Drakonic)", base: 39, odd:.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:"Aj'Snaga (Serpents)", base: 41, odd:.7, sort: i => n(i) / bd(i, [12], 10), shield:"fantasy1"}, // Serpents
|
||||
{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: "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: 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: "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: "Uruk (Orkish)", base: 37, odd: 1, sort: i => h[i] * t[i], shield: "urukHai"}, // 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: 0.7, sort: i => td(i, -10), shield: "pavise"}, // Giant
|
||||
{name: "Rake (Drakonic)", base: 39, odd: 0.7, sort: i => -s[i], shield: "fantasy2"}, // Draconic
|
||||
{name: "Arago (Arachnid)", base: 40, odd: 0.7, sort: i => t[i] - s[i], shield: "horsehead2"}, // Arachnid
|
||||
{name: "Aj'Snaga (Serpents)", base: 41, odd: 0.7, sort: i => n(i) / bd(i, [12], 10), shield: "fantasy1"}, // Serpents
|
||||
// fantasy human
|
||||
{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:"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: "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: "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"}
|
||||
];
|
||||
}
|
||||
|
||||
if (culturesSet.value === "darkFantasy") {
|
||||
return [
|
||||
// common real-world English
|
||||
{name:"Angshire", base:1, odd:1, sort: i => n(i) / td(i, 10) / sf(i), shield:"heater"},
|
||||
{name:"Enlandic", base:1, odd:1, sort: i => n(i) / td(i, 12), shield:"heater"},
|
||||
{name:"Westen", base:1, odd:1, sort: i => n(i) / td(i, 10), shield:"heater"},
|
||||
{name:"Nortumbic", base:1, odd:1, sort: i => n(i) / td(i, 7), 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: "Angshire", base: 1, odd: 1, sort: i => n(i) / td(i, 10) / sf(i), shield: "heater"},
|
||||
{name: "Enlandic", base: 1, odd: 1, sort: i => n(i) / td(i, 12), shield: "heater"},
|
||||
{name: "Westen", base: 1, odd: 1, sort: i => n(i) / td(i, 10), shield: "heater"},
|
||||
{name: "Nortumbic", base: 1, odd: 1, sort: i => n(i) / td(i, 7), 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"},
|
||||
// rare real-world western
|
||||
{name:"Norse", base:6, odd:.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:"Luarian", base:2, odd:.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:"Astellian", base:4, odd:.3, sort: i => n(i) / td(i, 16), shield:"spanish"},
|
||||
{name: "Norse", base: 6, odd: 0.7, sort: i => n(i) / td(i, 5) / sf(i), shield: "oldFrench"},
|
||||
{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: 0.3, sort: i => n(i) / td(i, 12) / bd(i, [6, 8]), shield: "oldFrench"},
|
||||
{name: "Hetallian", base: 3, odd: 0.3, sort: i => n(i) / td(i, 15), shield: "oval"},
|
||||
{name: "Astellian", base: 4, odd: 0.3, sort: i => n(i) / td(i, 16), shield: "spanish"},
|
||||
// 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:"Yoruba", base:21, odd:.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:"Hantzu", base:11, odd:.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:"Guantzu", base:30, odd:.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:"Turan", base: 16, odd:.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:"Eurabic", base: 18, odd:.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:"Keltan", base: 22, odd:.1, sort: i => n(i) / td(i, 11) ** .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:"Romian", base:8, odd:.2, sort: i => n(i) / td(i, 14) / t[i], shield:"roman"},
|
||||
{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: 0.05, sort: i => n(i) / td(i, 15) / bd(i, [5, 7]), shield: "vesicaPiscis"},
|
||||
{name: "Koryo", base: 10, odd: 0.05, sort: i => n(i) / td(i, 12) / t[i], shield: "round"},
|
||||
{name: "Hantzu", base: 11, odd: 0.05, sort: i => n(i) / td(i, 13), shield: "banner"},
|
||||
{name: "Yamoto", base: 12, odd: 0.05, sort: i => n(i) / td(i, 15) / t[i], shield: "round"},
|
||||
{name: "Guantzu", base: 30, odd: 0.05, sort: i => n(i) / td(i, 17), 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: 0.05, sort: i => n(i) / td(i, 12), 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: 0.05, sort: i => (n(i) / td(i, 26) / bd(i, [1, 2], 7)) * 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: 0.1, sort: i => n(i) / td(i, 11) ** 0.5 / bd(i, [6, 8]), shield: "vesicaPiscis"},
|
||||
{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: 0.2, sort: i => n(i) / td(i, 14) / t[i], shield: "roman"},
|
||||
// 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:"Trow", base: 34, odd:.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:"Kobblin", base: 36, odd:.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:"Yotunn", base: 38, odd:.8, sort: i => td(i, -10), shield:"pavise"}, // Giant
|
||||
{name:"Drake", base: 39, odd:.9, sort: i => -s[i], shield:"fantasy2"}, // Draconic
|
||||
{name:"Rakhnid", base: 40, odd:.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: "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: 0.8, sort: i => (n(i) / bd(i, [7, 8, 9, 12], 10)) * t[i], shield: "hessen"}, // Dark Elves
|
||||
{name: "Durinn", base: 35, odd: 0.8, sort: i => n(i) + h[i], shield: "erebor"}, // Dwarven
|
||||
{name: "Kobblin", base: 36, odd: 0.8, sort: i => t[i] - s[i], shield: "moriaOrc"}, // Goblin
|
||||
{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: 0.8, sort: i => td(i, -10), shield: "pavise"}, // Giant
|
||||
{name: "Drake", base: 39, odd: 0.9, sort: i => -s[i], shield: "fantasy2"}, // Draconic
|
||||
{name: "Rakhnid", base: 40, odd: 0.9, sort: i => t[i] - s[i], shield: "horsehead2"}, // Arachnid
|
||||
{name: "Aj'Snaga", base: 41, odd: 0.9, sort: i => n(i) / bd(i, [12], 10), shield: "fantasy1"} // Serpents
|
||||
];
|
||||
}
|
||||
|
||||
if (culturesSet.value === "random") {
|
||||
return d3.range(count).map(function() {
|
||||
const rnd = rand(nameBases.length-1);
|
||||
return d3.range(count).map(function () {
|
||||
const rnd = rand(nameBases.length - 1);
|
||||
const name = Names.getBaseShort(rnd);
|
||||
return {name, base:rnd, odd:1, shield:getRandomShield()}
|
||||
return {name, base: rnd, odd: 1, shield: getRandomShield()};
|
||||
});
|
||||
}
|
||||
|
||||
// all-world
|
||||
return [
|
||||
{name:"Shwazen", base:0, odd:.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:"Luari", base:2, odd:.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:"Astellian", base:4, odd:.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:"Norse", base:6, odd:.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:"Romian", base:8, odd:.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:"Koryo", base:10, odd:.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:"Yamoto", base:12, odd:.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:"Nawatli", base:14, odd:.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:"Turchian", base: 16, odd:.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:"Eurabic", base: 18, odd:.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:"Euskati", base: 20, odd:.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:"Keltan", base: 22, odd:.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:"Tehrani", base: 24, odd:.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:"Carnatic", base: 26, odd:.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:"Kiswaili", base: 28, odd:.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:"Guantzu", base:30, odd:.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: "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: "Luari", base: 2, odd: 0.6, sort: i => n(i) / td(i, 12) / bd(i, [6, 8]), shield: "oldFrench"},
|
||||
{name: "Tallian", base: 3, odd: 0.6, sort: i => n(i) / td(i, 15), shield: "horsehead2"},
|
||||
{name: "Astellian", base: 4, odd: 0.6, sort: i => n(i) / td(i, 16), shield: "spanish"},
|
||||
{name: "Slovan", base: 5, odd: 0.7, sort: i => (n(i) / td(i, 6)) * t[i], shield: "round"},
|
||||
{name: "Norse", base: 6, odd: 0.7, sort: i => n(i) / td(i, 5), shield: "heater"},
|
||||
{name: "Elladan", base: 7, odd: 0.7, sort: i => (n(i) / td(i, 18)) * h[i], shield: "boeotian"},
|
||||
{name: "Romian", base: 8, odd: 0.7, sort: i => n(i) / td(i, 15), shield: "roman"},
|
||||
{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: 0.1, sort: i => n(i) / td(i, 12) / t[i], shield: "round"},
|
||||
{name: "Hantzu", base: 11, odd: 0.1, sort: i => n(i) / td(i, 13), shield: "banner"},
|
||||
{name: "Yamoto", base: 12, odd: 0.1, sort: i => n(i) / td(i, 15) / t[i], shield: "round"},
|
||||
{name: "Portuzian", base: 13, odd: 0.4, sort: i => n(i) / td(i, 17) / sf(i), shield: "spanish"},
|
||||
{name: "Nawatli", base: 14, odd: 0.1, sort: i => h[i] / td(i, 18) / bd(i, [7]), shield: "square"},
|
||||
{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: 0.2, sort: i => n(i) / td(i, 13), 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: 0.2, sort: i => (n(i) / td(i, 26) / bd(i, [1, 2], 7)) * t[i], shield: "round"},
|
||||
{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: 0.05, sort: i => (n(i) / td(i, 15)) * h[i], shield: "spanish"},
|
||||
{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: 0.05, sort: i => (n(i) / td(i, 11) / bd(i, [6, 8])) * t[i], shield: "vesicaPiscis"},
|
||||
{name: "Efratic", base: 23, odd: 0.05, sort: i => (n(i) / td(i, 22)) * t[i], shield: "diamond"},
|
||||
{name: "Tehrani", base: 24, odd: 0.1, sort: i => (n(i) / td(i, 18)) * h[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: 0.05, sort: i => n(i) / td(i, 26), shield: "round"},
|
||||
{name: "Inqan", base: 27, odd: 0.05, sort: i => h[i] / td(i, 13), shield: "square"},
|
||||
{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: 0.1, sort: i => n(i) / td(i, 25) / bd(i, [7], 7) / t[i], shield: "banner"},
|
||||
{name: "Guantzu", base: 30, odd: 0.1, sort: i => n(i) / td(i, 17), 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)
|
||||
const expand = function() {
|
||||
TIME && console.time('expandCultures');
|
||||
const expand = function () {
|
||||
TIME && console.time("expandCultures");
|
||||
cells = pack.cells;
|
||||
|
||||
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
|
||||
pack.cultures.forEach(function(c) {
|
||||
pack.cultures.forEach(function (c) {
|
||||
if (!c.i || c.removed) return;
|
||||
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 = [];
|
||||
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;
|
||||
cells.c[n].forEach(function(e) {
|
||||
cells.c[n].forEach(function (e) {
|
||||
const biome = cells.biome[e];
|
||||
const biomeCost = getBiomeCost(c, biome, type);
|
||||
const biomeChangeCost = biome === cells.biome[n] ? 0 : 20; // penalty on biome change
|
||||
|
|
@ -375,13 +402,13 @@
|
|||
if (!cost[e] || totalCost < cost[e]) {
|
||||
if (cells.s[e] > 0) cells.culture[e] = c; // assign culture to populated cell
|
||||
cost[e] = totalCost;
|
||||
queue.queue({e, p:totalCost, c});
|
||||
queue.queue({e, p: totalCost, c});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TIME && console.timeEnd('expandCultures');
|
||||
}
|
||||
TIME && console.timeEnd("expandCultures");
|
||||
};
|
||||
|
||||
function getBiomeCost(c, biome, type) {
|
||||
if (cells.biome[pack.cultures[c].center] === biome) return 10; // tiny penalty for native biome
|
||||
|
|
@ -391,7 +418,8 @@
|
|||
}
|
||||
|
||||
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 === "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
|
||||
|
|
@ -407,21 +435,20 @@
|
|||
function getRiverCost(r, i, type) {
|
||||
if (type === "River") return r ? 0 : 100; // penalty for river cultures
|
||||
if (!r) return 0; // no penalty for others if there is no river
|
||||
return Math.min(Math.max(cells.fl[i] / 10, 20), 100) // river penalty from 20 to 100 based on flux
|
||||
return Math.min(Math.max(cells.fl[i] / 10, 20), 100); // river penalty from 20 to 100 based on flux
|
||||
}
|
||||
|
||||
function getTypeCost(t, type) {
|
||||
if (t === 1) return type === "Naval" || type === "Lake" ? 0 : type === "Nomadic" ? 60 : 20; // penalty for coastline
|
||||
if (t === 2) return type === "Naval" || type === "Nomadic" ? 30 : 0; // low penalty for land level 2 for Navals and nomads
|
||||
if (t !== -1) return type === "Naval" || type === "Lake" ? 100 : 0; // penalty for mainland for navals
|
||||
if (t !== -1) return type === "Naval" || type === "Lake" ? 100 : 0; // penalty for mainland for navals
|
||||
return 0;
|
||||
}
|
||||
|
||||
const getRandomShield = function() {
|
||||
const getRandomShield = function () {
|
||||
const type = rw(COA.shields.types);
|
||||
return rw(COA.shields[type]);
|
||||
}
|
||||
};
|
||||
|
||||
return {generate, add, expand, getDefault, getRandomShield};
|
||||
|
||||
})));
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
(function (global, factory) {
|
||||
typeof exports === "object" && typeof module !== "undefined" ? (module.exports = factory()) : typeof define === "function" && define.amd ? define(factory) : (global.HeightmapGenerator = factory());
|
||||
})(this, function () {
|
||||
"use strict";
|
||||
"use strict";
|
||||
|
||||
window.HeightmapGenerator = (function () {
|
||||
let cells, p;
|
||||
|
||||
const generate = function () {
|
||||
|
|
@ -12,262 +10,63 @@
|
|||
cells.h = new Uint8Array(grid.points.length);
|
||||
|
||||
const template = document.getElementById("templateInput").value;
|
||||
switch (template) {
|
||||
case "Volcano":
|
||||
templateVolcano();
|
||||
break;
|
||||
case "High Island":
|
||||
templateHighIsland();
|
||||
break;
|
||||
case "Low Island":
|
||||
templateLowIsland();
|
||||
break;
|
||||
case "Continents":
|
||||
templateContinents();
|
||||
break;
|
||||
case "Archipelago":
|
||||
templateArchipelago();
|
||||
break;
|
||||
case "Atoll":
|
||||
templateAtoll();
|
||||
break;
|
||||
case "Mediterranean":
|
||||
templateMediterranean();
|
||||
break;
|
||||
case "Peninsula":
|
||||
templatePeninsula();
|
||||
break;
|
||||
case "Pangea":
|
||||
templatePangea();
|
||||
break;
|
||||
case "Isthmus":
|
||||
templateIsthmus();
|
||||
break;
|
||||
case "Shattered":
|
||||
templateShattered();
|
||||
break;
|
||||
const templateString = HeightmapTemplates[template];
|
||||
const steps = templateString.split("\n");
|
||||
|
||||
if (!steps.length) throw new Error(`Heightmap template: no steps. Template: ${template}. Steps: ${steps}`);
|
||||
|
||||
for (const step of steps) {
|
||||
const elements = step.trim().split(" ");
|
||||
if (elements.length < 2) throw new Error(`Heightmap template: steps < 2. Template: ${template}. Step: ${elements}`);
|
||||
addStep(...elements);
|
||||
}
|
||||
|
||||
TIME && console.timeEnd("generateHeightmap");
|
||||
};
|
||||
|
||||
// parse template step
|
||||
function addStep(a1, a2, a3, a4, a5) {
|
||||
if (a1 === "Hill") return addHill(a2, a3, a4, a5);
|
||||
if (a1 === "Pit") return addPit(a2, a3, a4, a5);
|
||||
if (a1 === "Range") return addRange(a2, a3, a4, a5);
|
||||
if (a1 === "Trough") return addTrough(a2, a3, a4, a5);
|
||||
if (a1 === "Strait") return addStrait(a2, a3);
|
||||
if (a1 === "Add") return modify(a3, a2, 1);
|
||||
if (a1 === "Multiply") return modify(a3, 0, a2);
|
||||
if (a1 === "Add") return modify(a3, +a2, 1);
|
||||
if (a1 === "Multiply") return modify(a3, 0, +a2);
|
||||
if (a1 === "Smooth") return smooth(a2);
|
||||
}
|
||||
|
||||
// Heighmap Template: Volcano
|
||||
function templateVolcano() {
|
||||
addStep("Hill", "1", "90-100", "44-56", "40-60");
|
||||
addStep("Multiply", 0.8, "50-100");
|
||||
addStep("Range", "1.5", "30-55", "45-55", "40-60");
|
||||
addStep("Smooth", 2);
|
||||
addStep("Hill", "1.5", "25-35", "25-30", "20-75");
|
||||
addStep("Hill", "1", "25-35", "75-80", "25-75");
|
||||
addStep("Hill", "0.5", "20-25", "10-15", "20-25");
|
||||
}
|
||||
|
||||
// Heighmap Template: High Island
|
||||
function templateHighIsland() {
|
||||
addStep("Hill", "1", "90-100", "65-75", "47-53");
|
||||
addStep("Add", 5, "all");
|
||||
addStep("Hill", "6", "20-23", "25-55", "45-55");
|
||||
addStep("Range", "1", "40-50", "45-55", "45-55");
|
||||
addStep("Smooth", 2);
|
||||
addStep("Trough", "2-3", "20-30", "20-30", "20-30");
|
||||
addStep("Trough", "2-3", "20-30", "60-80", "70-80");
|
||||
addStep("Hill", "1", "10-15", "60-60", "50-50");
|
||||
addStep("Hill", "1.5", "13-16", "15-20", "20-75");
|
||||
addStep("Multiply", 0.8, "20-100");
|
||||
addStep("Range", "1.5", "30-40", "15-85", "30-40");
|
||||
addStep("Range", "1.5", "30-40", "15-85", "60-70");
|
||||
addStep("Pit", "2-3", "10-15", "15-85", "20-80");
|
||||
}
|
||||
|
||||
// Heighmap Template: Low Island
|
||||
function templateLowIsland() {
|
||||
addStep("Hill", "1", "90-99", "60-80", "45-55");
|
||||
addStep("Hill", "4-5", "25-35", "20-65", "40-60");
|
||||
addStep("Range", "1", "40-50", "45-55", "45-55");
|
||||
addStep("Smooth", 3);
|
||||
addStep("Trough", "1.5", "20-30", "15-85", "20-30");
|
||||
addStep("Trough", "1.5", "20-30", "15-85", "70-80");
|
||||
addStep("Hill", "1.5", "10-15", "5-15", "20-80");
|
||||
addStep("Hill", "1", "10-15", "85-95", "70-80");
|
||||
addStep("Pit", "3-5", "10-15", "15-85", "20-80");
|
||||
addStep("Multiply", 0.4, "20-100");
|
||||
}
|
||||
|
||||
// Heighmap Template: Continents
|
||||
function templateContinents() {
|
||||
addStep("Hill", "1", "80-85", "75-80", "40-60");
|
||||
addStep("Hill", "1", "80-85", "20-25", "40-60");
|
||||
addStep("Multiply", 0.22, "20-100");
|
||||
addStep("Hill", "5-6", "15-20", "25-75", "20-82");
|
||||
addStep("Range", ".8", "30-60", "5-15", "20-45");
|
||||
addStep("Range", ".8", "30-60", "5-15", "55-80");
|
||||
addStep("Range", "0-3", "30-60", "80-90", "20-80");
|
||||
addStep("Trough", "3-4", "15-20", "15-85", "20-80");
|
||||
addStep("Strait", "2", "vertical");
|
||||
addStep("Smooth", 2);
|
||||
addStep("Trough", "1-2", "5-10", "45-55", "45-55");
|
||||
addStep("Pit", "3-4", "10-15", "15-85", "20-80");
|
||||
addStep("Hill", "1", "5-10", "40-60", "40-60");
|
||||
}
|
||||
|
||||
// Heighmap Template: Archipelago
|
||||
function templateArchipelago() {
|
||||
addStep("Add", 11, "all");
|
||||
addStep("Range", "2-3", "40-60", "20-80", "20-80");
|
||||
addStep("Hill", "5", "15-20", "10-90", "30-70");
|
||||
addStep("Hill", "2", "10-15", "10-30", "20-80");
|
||||
addStep("Hill", "2", "10-15", "60-90", "20-80");
|
||||
addStep("Smooth", 3);
|
||||
addStep("Trough", "10", "20-30", "5-95", "5-95");
|
||||
addStep("Strait", "2", "vertical");
|
||||
addStep("Strait", "2", "horizontal");
|
||||
}
|
||||
|
||||
// Heighmap Template: Atoll
|
||||
function templateAtoll() {
|
||||
addStep("Hill", "1", "75-80", "50-60", "45-55");
|
||||
addStep("Hill", "1.5", "30-50", "25-75", "30-70");
|
||||
addStep("Hill", ".5", "30-50", "25-35", "30-70");
|
||||
addStep("Smooth", 1);
|
||||
addStep("Multiply", 0.2, "25-100");
|
||||
addStep("Hill", ".5", "10-20", "50-55", "48-52");
|
||||
}
|
||||
|
||||
// Heighmap Template: Mediterranean
|
||||
function templateMediterranean() {
|
||||
addStep("Range", "3-4", "30-50", "0-100", "0-10");
|
||||
addStep("Range", "3-4", "30-50", "0-100", "90-100");
|
||||
addStep("Hill", "5-6", "30-70", "0-100", "0-5");
|
||||
addStep("Hill", "5-6", "30-70", "0-100", "95-100");
|
||||
addStep("Smooth", 1);
|
||||
addStep("Hill", "2-3", "30-70", "0-5", "20-80");
|
||||
addStep("Hill", "2-3", "30-70", "95-100", "20-80");
|
||||
addStep("Multiply", 0.8, "land");
|
||||
addStep("Trough", "3-5", "40-50", "0-100", "0-10");
|
||||
addStep("Trough", "3-5", "40-50", "0-100", "90-100");
|
||||
}
|
||||
|
||||
// Heighmap Template: Peninsula
|
||||
function templatePeninsula() {
|
||||
addStep("Range", "2-3", "20-35", "40-50", "0-15");
|
||||
addStep("Add", 5, "all");
|
||||
addStep("Hill", "1", "90-100", "10-90", "0-5");
|
||||
addStep("Add", 13, "all");
|
||||
addStep("Hill", "3-4", "3-5", "5-95", "80-100");
|
||||
addStep("Hill", "1-2", "3-5", "5-95", "40-60");
|
||||
addStep("Trough", "5-6", "10-25", "5-95", "5-95");
|
||||
addStep("Smooth", 3);
|
||||
}
|
||||
|
||||
// Heighmap Template: Pangea
|
||||
function templatePangea() {
|
||||
addStep("Hill", "1-2", "25-40", "15-50", "0-10");
|
||||
addStep("Hill", "1-2", "5-40", "50-85", "0-10");
|
||||
addStep("Hill", "1-2", "25-40", "50-85", "90-100");
|
||||
addStep("Hill", "1-2", "5-40", "15-50", "90-100");
|
||||
addStep("Hill", "8-12", "20-40", "20-80", "48-52");
|
||||
addStep("Smooth", 2);
|
||||
addStep("Multiply", 0.7, "land");
|
||||
addStep("Trough", "3-4", "25-35", "5-95", "10-20");
|
||||
addStep("Trough", "3-4", "25-35", "5-95", "80-90");
|
||||
addStep("Range", "5-6", "30-40", "10-90", "35-65");
|
||||
}
|
||||
|
||||
// Heighmap Template: Isthmus
|
||||
function templateIsthmus() {
|
||||
addStep("Hill", "5-10", "15-30", "0-30", "0-20");
|
||||
addStep("Hill", "5-10", "15-30", "10-50", "20-40");
|
||||
addStep("Hill", "5-10", "15-30", "30-70", "40-60");
|
||||
addStep("Hill", "5-10", "15-30", "50-90", "60-80");
|
||||
addStep("Hill", "5-10", "15-30", "70-100", "80-100");
|
||||
addStep("Smooth", 2);
|
||||
addStep("Trough", "4-8", "15-30", "0-30", "0-20");
|
||||
addStep("Trough", "4-8", "15-30", "10-50", "20-40");
|
||||
addStep("Trough", "4-8", "15-30", "30-70", "40-60");
|
||||
addStep("Trough", "4-8", "15-30", "50-90", "60-80");
|
||||
addStep("Trough", "4-8", "15-30", "70-100", "80-100");
|
||||
}
|
||||
|
||||
// Heighmap Template: Shattered
|
||||
function templateShattered() {
|
||||
addStep("Hill", "8", "35-40", "15-85", "30-70");
|
||||
addStep("Trough", "10-20", "40-50", "5-95", "5-95");
|
||||
addStep("Range", "5-7", "30-40", "10-90", "20-80");
|
||||
addStep("Pit", "12-20", "30-40", "15-85", "20-80");
|
||||
}
|
||||
|
||||
function getBlobPower() {
|
||||
switch (+pointsInput.dataset.cells) {
|
||||
case 1000:
|
||||
return 0.93;
|
||||
case 2000:
|
||||
return 0.95;
|
||||
case 5000:
|
||||
return 0.96;
|
||||
case 10000:
|
||||
return 0.98;
|
||||
case 20000:
|
||||
return 0.985;
|
||||
case 30000:
|
||||
return 0.987;
|
||||
case 40000:
|
||||
return 0.9892;
|
||||
case 50000:
|
||||
return 0.9911;
|
||||
case 60000:
|
||||
return 0.9921;
|
||||
case 70000:
|
||||
return 0.9934;
|
||||
case 80000:
|
||||
return 0.9942;
|
||||
case 90000:
|
||||
return 0.9946;
|
||||
case 100000:
|
||||
return 0.995;
|
||||
}
|
||||
const cells = +pointsInput.dataset.cells;
|
||||
if (cells === 1000) return 0.93;
|
||||
if (cells === 2000) return 0.95;
|
||||
if (cells === 5000) return 0.96;
|
||||
if (cells === 10000) return 0.98;
|
||||
if (cells === 20000) return 0.985;
|
||||
if (cells === 30000) return 0.987;
|
||||
if (cells === 40000) return 0.9892;
|
||||
if (cells === 50000) return 0.9911;
|
||||
if (cells === 60000) return 0.9921;
|
||||
if (cells === 70000) return 0.9934;
|
||||
if (cells === 80000) return 0.9942;
|
||||
if (cells === 90000) return 0.9946;
|
||||
if (cells === 100000) return 0.995;
|
||||
}
|
||||
|
||||
function getLinePower() {
|
||||
switch (+pointsInput.dataset.cells) {
|
||||
case 1000:
|
||||
return 0.74;
|
||||
case 2000:
|
||||
return 0.75;
|
||||
case 5000:
|
||||
return 0.78;
|
||||
case 10000:
|
||||
return 0.81;
|
||||
case 20000:
|
||||
return 0.82;
|
||||
case 30000:
|
||||
return 0.83;
|
||||
case 40000:
|
||||
return 0.84;
|
||||
case 50000:
|
||||
return 0.855;
|
||||
case 60000:
|
||||
return 0.87;
|
||||
case 70000:
|
||||
return 0.885;
|
||||
case 80000:
|
||||
return 0.91;
|
||||
case 90000:
|
||||
return 0.92;
|
||||
case 100000:
|
||||
return 0.93;
|
||||
}
|
||||
const cells = +pointsInput.dataset.cells;
|
||||
if (cells === 1000) return 0.74;
|
||||
if (cells === 2000) return 0.75;
|
||||
if (cells === 5000) return 0.78;
|
||||
if (cells === 10000) return 0.81;
|
||||
if (cells === 20000) return 0.82;
|
||||
if (cells === 30000) return 0.83;
|
||||
if (cells === 40000) return 0.84;
|
||||
if (cells === 50000) return 0.855;
|
||||
if (cells === 60000) return 0.87;
|
||||
if (cells === 70000) return 0.885;
|
||||
if (cells === 80000) return 0.91;
|
||||
if (cells === 90000) return 0.92;
|
||||
if (cells === 100000) return 0.93;
|
||||
}
|
||||
|
||||
const addHill = function (count, height, rangeX, rangeY) {
|
||||
|
|
@ -610,4 +409,4 @@
|
|||
}
|
||||
|
||||
return {generate, addHill, addRange, addTrough, addStrait, addPit, smooth, modify};
|
||||
});
|
||||
})();
|
||||
|
|
|
|||
123
modules/heightmap-templates.js
Normal file
123
modules/heightmap-templates.js
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
"use strict";
|
||||
|
||||
window.HeightmapTemplates = (function () {
|
||||
const volcano = `Hill 1 90-100 44-56 40-60
|
||||
Multiply 0.8 50-100 0 0
|
||||
Range 1.5 30-55 45-55 40-60
|
||||
Smooth 2 0 0 0
|
||||
Hill 1.5 25-35 25-30 20-75
|
||||
Hill 1 25-35 75-80 25-75
|
||||
Hill 0.5 20-25 10-15 20-25`;
|
||||
|
||||
const highIsland = `Hill 1 90-100 65-75 47-53
|
||||
Add 5 all 0 0
|
||||
Hill 6 20-23 25-55 45-55
|
||||
Range 1 40-50 45-55 45-55
|
||||
Smooth 2 0 0 0
|
||||
Trough 2-3 20-30 20-30 20-30
|
||||
Trough 2-3 20-30 60-80 70-80
|
||||
Hill 1 10-15 60-60 50-50
|
||||
Hill 1.5 13-16 15-20 20-75
|
||||
Multiply 0.8 20-100 0 0
|
||||
Range 1.5 30-40 15-85 30-40
|
||||
Range 1.5 30-40 15-85 60-70
|
||||
Pit 2-3 10-15 15-85 20-80`;
|
||||
|
||||
const lowIsland = `Hill 1 90-99 60-80 45-55
|
||||
Hill 4-5 25-35 20-65 40-60
|
||||
Range 1 40-50 45-55 45-55
|
||||
Smooth 3 0 0 0
|
||||
Trough 1.5 20-30 15-85 20-30
|
||||
Trough 1.5 20-30 15-85 70-80
|
||||
Hill 1.5 10-15 5-15 20-80
|
||||
Hill 1 10-15 85-95 70-80
|
||||
Pit 3-5 10-15 15-85 20-80
|
||||
Multiply 0.4 20-100 0 0`;
|
||||
|
||||
const continents = `Hill 1 80-85 75-80 40-60
|
||||
Hill 1 80-85 20-25 40-60
|
||||
Multiply 0.22 20-100 0 0
|
||||
Hill 5-6 15-20 25-75 20-82
|
||||
Range .8 30-60 5-15 20-45
|
||||
Range .8 30-60 5-15 55-80
|
||||
Range 0-3 30-60 80-90 20-80
|
||||
Trough 3-4 15-20 15-85 20-80
|
||||
Strait 2 vertical 0 0
|
||||
Smooth 2 0 0 0
|
||||
Trough 1-2 5-10 45-55 45-55
|
||||
Pit 3-4 10-15 15-85 20-80
|
||||
Hill 1 5-10 40-60 40-60`;
|
||||
|
||||
const archipelago = `Add 11 all 0 0
|
||||
Range 2-3 40-60 20-80 20-80
|
||||
Hill 5 15-20 10-90 30-70
|
||||
Hill 2 10-15 10-30 20-80
|
||||
Hill 2 10-15 60-90 20-80
|
||||
Smooth 3 0 0 0
|
||||
Trough 10 20-30 5-95 5-95
|
||||
Strait 2 vertical 0 0
|
||||
Strait 2 horizontal 0 0`;
|
||||
|
||||
const atoll = `Hill 1 75-80 50-60 45-55
|
||||
Hill 1.5 30-50 25-75 30-70
|
||||
Hill .5 30-50 25-35 30-70
|
||||
Smooth 1 0 0 0
|
||||
Multiply 0.2 25-100 0 0
|
||||
Hill .5 10-20 50-55 48-52`;
|
||||
|
||||
const mediterranean = `Range 3-4 30-50 0-100 0-10
|
||||
Range 3-4 30-50 0-100 90-100
|
||||
Hill 5-6 30-70 0-100 0-5
|
||||
Hill 5-6 30-70 0-100 95-100
|
||||
Smooth 1 0 0 0
|
||||
Hill 2-3 30-70 0-5 20-80
|
||||
Hill 2-3 30-70 95-100 20-80
|
||||
Multiply 0.8 land 0 0
|
||||
Trough 3-5 40-50 0-100 0-10
|
||||
Trough 3-5 40-50 0-100 90-100`;
|
||||
|
||||
const peninsula = `Range 2-3 20-35 40-50 0-15
|
||||
Add 5 all 0 0
|
||||
Hill 1 90-100 10-90 0-5
|
||||
Add 13 all 0 0
|
||||
Hill 3-4 3-5 5-95 80-100
|
||||
Hill 1-2 3-5 5-95 40-60
|
||||
Trough 5-6 10-25 5-95 5-95
|
||||
Smooth 3 0 0 0`;
|
||||
|
||||
const pangea = `Hill 1-2 25-40 15-50 0-10
|
||||
Hill 1-2 5-40 50-85 0-10
|
||||
Hill 1-2 25-40 50-85 90-100
|
||||
Hill 1-2 5-40 15-50 90-100
|
||||
Hill 8-12 20-40 20-80 48-52
|
||||
Smooth 2 0 0 0
|
||||
Multiply 0.7 land 0 0
|
||||
Trough 3-4 25-35 5-95 10-20
|
||||
Trough 3-4 25-35 5-95 80-90
|
||||
Range 5-6 30-40 10-90 35-65`;
|
||||
|
||||
const isthmus = `Hill 5-10 15-30 0-30 0-20
|
||||
Hill 5-10 15-30 10-50 20-40
|
||||
Hill 5-10 15-30 30-70 40-60
|
||||
Hill 5-10 15-30 50-90 60-80
|
||||
Hill 5-10 15-30 70-100 80-100
|
||||
Smooth 2 0 0 0
|
||||
Trough 4-8 15-30 0-30 0-20
|
||||
Trough 4-8 15-30 10-50 20-40
|
||||
Trough 4-8 15-30 30-70 40-60
|
||||
Trough 4-8 15-30 50-90 60-80
|
||||
Trough 4-8 15-30 70-100 80-100`;
|
||||
|
||||
const shattered = `Hill 8 35-40 15-85 30-70
|
||||
Trough 10-20 40-50 5-95 5-95
|
||||
Range 5-7 30-40 10-90 20-80
|
||||
Pit 12-20 30-40 15-85 20-80`;
|
||||
|
||||
const taklamakan = `Hill 1-3 20-30 30-70 30-70
|
||||
Hill 2-4 60-85 0-5 0-100
|
||||
Hill 2-4 60-85 95-100 0-100
|
||||
Hill 3-4 60-85 20-80 0-5
|
||||
Hill 3-4 60-85 20-80 95-100`;
|
||||
|
||||
return {volcano, highIsland, lowIsland, continents, archipelago, atoll, mediterranean, peninsula, peninsula, pangea, isthmus, shattered, taklamakan};
|
||||
})();
|
||||
|
|
@ -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 cells = pack.cells;
|
||||
const lakeOutCells = new Uint16Array(cells.i.length);
|
||||
|
|
@ -149,4 +147,4 @@
|
|||
}
|
||||
|
||||
return {setClimateData, cleanupLakeData, prepareLakeData, defineGroup, generateName, getName, getShoreline};
|
||||
});
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ function parseLoadedData(data) {
|
|||
if (settings[20]) mapName.value = settings[20];
|
||||
if (settings[21]) hideLabels.checked = +settings[21];
|
||||
if (settings[22]) stylePreset.value = settings[22];
|
||||
if (settings[23]) rescaleLabels.checked = settings[23];
|
||||
})();
|
||||
|
||||
void (function parseConfiguration() {
|
||||
|
|
|
|||
|
|
@ -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 () {
|
||||
TIME && console.time("generateMilitaryForces");
|
||||
const cells = pack.cells,
|
||||
|
|
@ -371,4 +369,4 @@
|
|||
};
|
||||
|
||||
return {generate, getDefaultOptions, getName, generateNote, drawRegiments, drawRegiment, moveRegiment, getTotal, getEmblem};
|
||||
});
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -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 = [];
|
||||
|
||||
// calculate Markov chain for a namesbase
|
||||
|
|
@ -294,4 +293,4 @@
|
|||
};
|
||||
|
||||
return {getBase, getCulture, getCultureShort, getBaseShort, getState, updateChain, clearChains, getNameBases, getMapName, calculateChain};
|
||||
});
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
const OceanLayers = function OceanLayers() {
|
||||
|
|
@ -91,4 +89,4 @@
|
|||
}
|
||||
|
||||
return OceanLayers;
|
||||
});
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -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 () {
|
||||
TIME && console.time("drawRelief");
|
||||
terrain.selectAll("*").remove();
|
||||
|
|
@ -127,4 +125,4 @@
|
|||
}
|
||||
|
||||
return ReliefIcons;
|
||||
});
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -1,19 +1,13 @@
|
|||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
||||
typeof define === 'function' && define.amd ? define(factory) :
|
||||
(global.Religions = factory());
|
||||
}(this, (function () {'use strict';
|
||||
"use strict";
|
||||
|
||||
window.Religions = (function () {
|
||||
// name generation approach and relative chance to be selected
|
||||
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};
|
||||
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};
|
||||
|
||||
// turn weighted array into simple array
|
||||
const approaches = [];
|
||||
for (const a in approach) {
|
||||
for (let j=0; j < approach[a]; j++) {
|
||||
for (let j = 0; j < approach[a]; j++) {
|
||||
approaches.push(a);
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +15,7 @@
|
|||
const base = {
|
||||
number: ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve"],
|
||||
being: ["God", "Goddess", "Lord", "Lady", "Deity", "Creator", "Maker", "Overlord", "Ruler", "Chief", "Master", "Spirit", "Ancestor", "Father", "Forebear", "Forefather", "Mother", "Brother", "Sister", "Elder", "Numen", "Ancient", "Virgin", "Giver", "Council", "Guardian", "Reaper"],
|
||||
animal: ["Dragon", "Wyvern", "Phoenix", "Unicorn", "Sphinx", "Centaur", "Pegasus", "Kraken", "Basilisk", "Chimera", "Cyclope", "Antelope", "Ape", "Badger", "Bear", "Beaver", "Bison", "Boar", "Buffalo", "Cat", "Cobra", "Crane", "Crocodile", "Crow", "Deer", "Dog", "Eagle", "Elk", "Fox", "Goat", "Goose", "Hare", "Hawk", "Heron", "Horse", "Hyena", "Ibis", "Jackal", "Jaguar", "Lark", "Leopard", "Lion", "Mantis", "Marten", "Moose", "Mule", "Narwhal", "Owl", "Panther", "Rat", "Raven", "Rook", "Scorpion", "Shark", "Sheep", "Snake", "Spider", "Swan", "Tiger", "Turtle", "Viper", "Vulture", "Walrus", "Wolf", "Wolverine", "Worm", "Camel", "Falcon", "Hound", "Ox", "Serpent"],
|
||||
animal: ["Dragon", "Wyvern", "Phoenix", "Unicorn", "Sphinx", "Centaur", "Pegasus", "Kraken", "Basilisk", "Chimera", "Cyclope", "Antelope", "Ape", "Badger", "Bear", "Beaver", "Bison", "Boar", "Buffalo", "Cat", "Cobra", "Crane", "Crocodile", "Crow", "Deer", "Dog", "Eagle", "Elk", "Fox", "Goat", "Goose", "Hare", "Hawk", "Heron", "Horse", "Hyena", "Ibis", "Jackal", "Jaguar", "Lark", "Leopard", "Lion", "Mantis", "Marten", "Moose", "Mule", "Narwhal", "Owl", "Panther", "Rat", "Raven", "Rook", "Scorpion", "Shark", "Sheep", "Snake", "Spider", "Swan", "Tiger", "Turtle", "Viper", "Vulture", "Walrus", "Wolf", "Wolverine", "Worm", "Camel", "Falcon", "Hound", "Ox", "Serpent"],
|
||||
adjective: ["New", "Good", "High", "Old", "Great", "Big", "Young", "Major", "Strong", "Happy", "Last", "Main", "Huge", "Far", "Beautiful", "Wild", "Fair", "Prime", "Crazy", "Ancient", "Proud", "Secret", "Lucky", "Sad", "Silent", "Latter", "Severe", "Fat", "Holy", "Pure", "Aggressive", "Honest", "Giant", "Mad", "Pregnant", "Distant", "Lost", "Broken", "Blind", "Friendly", "Unknown", "Sleeping", "Slumbering", "Loud", "Hungry", "Wise", "Worried", "Sacred", "Magical", "Superior", "Patient", "Dead", "Deadly", "Peaceful", "Grateful", "Frozen", "Evil", "Scary", "Burning", "Divine", "Bloody", "Dying", "Waking", "Brutal", "Unhappy", "Calm", "Cruel", "Favorable", "Blond", "Explicit", "Disturbing", "Devastating", "Brave", "Sunny", "Troubled", "Flying", "Sustainable", "Marine", "Fatal", "Inherent", "Selected", "Naval", "Cheerful", "Almighty", "Benevolent", "Eternal", "Immutable", "Infallible"],
|
||||
genitive: ["Day", "Life", "Death", "Night", "Home", "Fog", "Snow", "Winter", "Summer", "Cold", "Springs", "Gates", "Nature", "Thunder", "Lightning", "War", "Ice", "Frost", "Fire", "Doom", "Fate", "Pain", "Heaven", "Justice", "Light", "Love", "Time", "Victory"],
|
||||
theGenitive: ["World", "Word", "South", "West", "North", "East", "Sun", "Moon", "Peak", "Fall", "Dawn", "Eclipse", "Abyss", "Blood", "Tree", "Earth", "Harvest", "Rainbow", "Sea", "Sky", "Stars", "Storm", "Underworld", "Wild"],
|
||||
|
|
@ -29,64 +23,70 @@
|
|||
};
|
||||
|
||||
const forms = {
|
||||
Folk:{"Shamanism":2, "Animism":2, "Ancestor worship":1, "Polytheism":2},
|
||||
Organized:{"Polytheism":5, "Dualism":1, "Monotheism":4, "Non-theism":1},
|
||||
Cult:{"Cult":1, "Dark Cult":1},
|
||||
Heresy:{"Heresy":1}
|
||||
Folk: {Shamanism: 2, Animism: 2, "Ancestor worship": 1, Polytheism: 2},
|
||||
Organized: {Polytheism: 5, Dualism: 1, Monotheism: 4, "Non-theism": 1},
|
||||
Cult: {Cult: 1, "Dark Cult": 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 = {
|
||||
"Shamanism":{"Beliefs":3, "Shamanism":2, "Spirits":1},
|
||||
"Animism":{"Spirits":1, "Beliefs":1},
|
||||
"Ancestor worship":{"Beliefs":1, "Forefathers":2, "Ancestors":2},
|
||||
"Polytheism":{"Deities":3, "Faith":1, "Gods":1, "Pantheon":1},
|
||||
Shamanism: {Beliefs: 3, Shamanism: 2, Spirits: 1},
|
||||
Animism: {Spirits: 1, Beliefs: 1},
|
||||
"Ancestor worship": {Beliefs: 1, Forefathers: 2, Ancestors: 2},
|
||||
Polytheism: {Deities: 3, Faith: 1, Gods: 1, Pantheon: 1},
|
||||
|
||||
"Dualism":{"Religion":3, "Faith":1, "Cult":1},
|
||||
"Monotheism":{"Religion":1, "Church":1},
|
||||
"Non-theism":{"Beliefs":3, "Spirits":1},
|
||||
Dualism: {Religion: 3, Faith: 1, Cult: 1},
|
||||
Monotheism: {Religion: 1, Church: 1},
|
||||
"Non-theism": {Beliefs: 3, Spirits: 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},
|
||||
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},
|
||||
|
||||
"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() {
|
||||
TIME && console.time('generateReligions');
|
||||
const cells = pack.cells, states = pack.states, cultures = pack.cultures;
|
||||
const religions = pack.religions = [];
|
||||
const generate = function () {
|
||||
TIME && console.time("generateReligions");
|
||||
const cells = pack.cells,
|
||||
states = pack.states,
|
||||
cultures = pack.cultures;
|
||||
const religions = (pack.religions = []);
|
||||
cells.religion = new Uint16Array(cells.culture); // cell religion; initially based on culture
|
||||
|
||||
// add folk religions
|
||||
pack.cultures.forEach(c => {
|
||||
if (!c.i) {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, .1, 0), removed:true}); return;}
|
||||
if (!c.i) {
|
||||
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 name = c.name + " " + rw(types[form]);
|
||||
const deity = form === "Animism" ? null : getDeityName(c.i);
|
||||
const color = getMixedColor(c.color, .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});
|
||||
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});
|
||||
});
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
const burgs = pack.burgs.filter(b => b.i && !b.removed);
|
||||
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]);
|
||||
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]);
|
||||
const religionsTree = d3.quadtree();
|
||||
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;
|
||||
|
||||
// generate organized religions
|
||||
for (let i=0; religions.length < count && i < 1000; i++) {
|
||||
let center = sorted[biased(0, sorted.length-1, 5)]; // religion center
|
||||
for (let i = 0; religions.length < count && i < 1000; i++) {
|
||||
let center = sorted[biased(0, sorted.length - 1, 5)]; // religion center
|
||||
const form = rw(forms.Organized);
|
||||
const state = cells.state[center];
|
||||
const culture = cells.culture[center];
|
||||
|
|
@ -96,34 +96,36 @@
|
|||
if (expansion === "state" && !state) expansion = "global";
|
||||
if (expansion === "culture" && !culture) expansion = "global";
|
||||
|
||||
if (expansion === "state" && Math.random() > .5) center = states[state].center;
|
||||
if (expansion === "culture" && Math.random() > .5) center = cultures[culture].center;
|
||||
if (expansion === "state" && Math.random() > 0.5) center = states[state].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]);
|
||||
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
|
||||
|
||||
// add "Old" to name of the folk religion on this culture
|
||||
const folk = religions.find(r => r.culture === culture && r.type === "Folk");
|
||||
if (folk && expansion === "culture" && folk.name.slice(0,3) !== "Old") folk.name = "Old " + folk.name;
|
||||
if (folk && expansion === "culture" && folk.name.slice(0, 3) !== "Old") folk.name = "Old " + folk.name;
|
||||
const origin = folk ? folk.i : 0;
|
||||
|
||||
const expansionism = rand(3, 8);
|
||||
const color = getMixedColor(religions[origin].color, .3, 0); // `url(#hatch${rand(0,5)})`;
|
||||
religions.push({i: religions.length, name, color, culture, type:"Organized", form, deity, expansion, expansionism, center, origin});
|
||||
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});
|
||||
religionsTree.add([x, y]);
|
||||
}
|
||||
|
||||
// generate cults
|
||||
for (let i=0; religions.length < count + cultsCount && i < 1000; i++) {
|
||||
for (let i = 0; religions.length < count + cultsCount && i < 1000; i++) {
|
||||
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]);
|
||||
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
|
||||
|
||||
const culture = cells.culture[center];
|
||||
|
|
@ -131,9 +133,9 @@
|
|||
const origin = folk ? folk.i : 0;
|
||||
const deity = getDeityName(culture);
|
||||
const name = getCultName(form, center);
|
||||
const expansionism = gauss(1.1, .5, 0, 5);
|
||||
const color = getMixedColor(cultures[culture].color, .5, 0); // "url(#hatch7)";
|
||||
religions.push({i: religions.length, name, color, culture, type:"Cult", form, deity, expansion:"global", expansionism, center, origin});
|
||||
const expansionism = gauss(1.1, 0.5, 0, 5);
|
||||
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});
|
||||
religionsTree.add([x, y]);
|
||||
//debug.append("circle").attr("cx", x).attr("cy", y).attr("r", 2).attr("fill", "red");
|
||||
}
|
||||
|
|
@ -141,72 +143,90 @@
|
|||
expandReligions();
|
||||
|
||||
// generate heresies
|
||||
religions.filter(r => r.type === "Organized").forEach(r => {
|
||||
if (r.expansionism < 3) return;
|
||||
const count = gauss(0, 1, 0, 3);
|
||||
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)));
|
||||
if (!center) continue;
|
||||
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];
|
||||
if (religionsTree.find(x, y, spacing / 10) !== undefined) continue; // to close to other
|
||||
religions
|
||||
.filter(r => r.type === "Organized")
|
||||
.forEach(r => {
|
||||
if (r.expansionism < 3) return;
|
||||
const count = gauss(0, 1, 0, 3);
|
||||
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)));
|
||||
if (!center) continue;
|
||||
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];
|
||||
if (religionsTree.find(x, y, spacing / 10) !== undefined) continue; // to close to other
|
||||
|
||||
const culture = cells.culture[center];
|
||||
const name = getCultName("Heresy", center);
|
||||
const expansionism = gauss(1.2, .5, 0, 5);
|
||||
const color = getMixedColor(r.color, .4, .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});
|
||||
religionsTree.add([x, y]);
|
||||
//debug.append("circle").attr("cx", x).attr("cy", y).attr("r", 2).attr("fill", "green");
|
||||
}
|
||||
});
|
||||
const culture = cells.culture[center];
|
||||
const name = getCultName("Heresy", center);
|
||||
const expansionism = gauss(1.2, 0.5, 0, 5);
|
||||
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});
|
||||
religionsTree.add([x, y]);
|
||||
//debug.append("circle").attr("cx", x).attr("cy", y).attr("r", 2).attr("fill", "green");
|
||||
}
|
||||
});
|
||||
|
||||
expandHeresies();
|
||||
checkCenters();
|
||||
|
||||
TIME && console.timeEnd('generateReligions');
|
||||
}
|
||||
TIME && console.timeEnd("generateReligions");
|
||||
};
|
||||
|
||||
const add = function(center) {
|
||||
const cells = pack.cells, religions = pack.religions;
|
||||
const add = function (center) {
|
||||
const cells = pack.cells,
|
||||
religions = pack.religions;
|
||||
const r = cells.religion[center];
|
||||
const i = religions.length;
|
||||
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 deity = type === "Heresy" ? religions[r].deity : form === "Non-theism" ? null : getDeityName(culture);
|
||||
|
||||
let name, expansion;
|
||||
if (type === "Organized") [name, expansion] = getReligionName(form, deity, center)
|
||||
else {name = getCultName(form, center); expansion = "global";}
|
||||
if (type === "Organized") [name, expansion] = getReligionName(form, deity, center);
|
||||
else {
|
||||
name = getCultName(form, center);
|
||||
expansion = "global";
|
||||
}
|
||||
const formName = type === "Heresy" ? religions[r].form : form;
|
||||
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});
|
||||
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});
|
||||
cells.religion[center] = i;
|
||||
}
|
||||
};
|
||||
|
||||
// growth algorithm to assign cells to religions
|
||||
const expandReligions = function() {
|
||||
const cells = pack.cells, religions = pack.religions;
|
||||
const expandReligions = function () {
|
||||
const cells = pack.cells,
|
||||
religions = pack.religions;
|
||||
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
|
||||
const cost = [];
|
||||
|
||||
religions.filter(r => r.type === "Organized" || r.type === "Cult").forEach(r => {
|
||||
cells.religion[r.center] = r.i;
|
||||
queue.queue({e:r.center, p:0, r:r.i, s: cells.state[r.center], c:r.culture});
|
||||
cost[r.center] = 1;
|
||||
});
|
||||
religions
|
||||
.filter(r => r.type === "Organized" || r.type === "Cult")
|
||||
.forEach(r => {
|
||||
cells.religion[r.center] = r.i;
|
||||
queue.queue({e: r.center, p: 0, r: r.i, s: cells.state[r.center], c: r.culture});
|
||||
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
|
||||
|
||||
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;
|
||||
|
||||
cells.c[n].forEach(function(e) {
|
||||
cells.c[n].forEach(function (e) {
|
||||
if (expansion === "culture" && c !== cells.culture[e]) return;
|
||||
if (expansion === "state" && s !== cells.state[e]) return;
|
||||
|
||||
|
|
@ -215,88 +235,101 @@
|
|||
const biomeCost = cells.road[e] ? 1 : biomesData.cost[cells.biome[e]];
|
||||
const populationCost = Math.max(rn(popCost - cells.pop[e]), 0);
|
||||
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;
|
||||
if (totalCost > neutral) return;
|
||||
|
||||
if (!cost[e] || totalCost < cost[e]) {
|
||||
if (cells.h[e] >= 20 && cells.culture[e]) cells.religion[e] = r; // assign religion to cell
|
||||
cost[e] = totalCost;
|
||||
queue.queue({e, p:totalCost, r, c, s});
|
||||
queue.queue({e, p: totalCost, r, c, s});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// growth algorithm to assign cells to heresies
|
||||
const expandHeresies = function() {
|
||||
const cells = pack.cells, religions = pack.religions;
|
||||
const expandHeresies = function () {
|
||||
const cells = pack.cells,
|
||||
religions = pack.religions;
|
||||
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
|
||||
const cost = [];
|
||||
|
||||
religions.filter(r => r.type === "Heresy").forEach(r => {
|
||||
const b = cells.religion[r.center]; // "base" religion id
|
||||
cells.religion[r.center] = r.i; // heresy id
|
||||
queue.queue({e:r.center, p:0, r:r.i, b});
|
||||
cost[r.center] = 1;
|
||||
});
|
||||
religions
|
||||
.filter(r => r.type === "Heresy")
|
||||
.forEach(r => {
|
||||
const b = cells.religion[r.center]; // "base" religion id
|
||||
cells.religion[r.center] = r.i; // heresy id
|
||||
queue.queue({e: r.center, p: 0, r: r.i, b});
|
||||
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) {
|
||||
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 biomeCost = cells.road[e] ? 0 : biomesData.cost[cells.biome[e]];
|
||||
const heightCost = Math.max(cells.h[e], 20) - 20;
|
||||
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 waterCost = cells.h[e] < 20 ? (cells.road[e] ? 50 : 1000) : 0;
|
||||
const totalCost = p + (religionCost + biomeCost + heightCost + waterCost) / Math.max(religions[r].expansionism, 0.1);
|
||||
|
||||
if (totalCost > neutral) return;
|
||||
|
||||
if (!cost[e] || totalCost < cost[e]) {
|
||||
if (cells.h[e] >= 20 && cells.culture[e]) cells.religion[e] = r; // assign religion to cell
|
||||
cost[e] = totalCost;
|
||||
queue.queue({e, p:totalCost, r});
|
||||
queue.queue({e, p: totalCost, r});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function checkCenters() {
|
||||
const cells = pack.cells, religions = pack.religions;
|
||||
const cells = pack.cells,
|
||||
religions = pack.religions;
|
||||
|
||||
const codes = religions.map(r => r.code);
|
||||
religions.filter(r => r.i).forEach(r => {
|
||||
r.code = abbreviate(r.name, codes);
|
||||
religions
|
||||
.filter(r => r.i)
|
||||
.forEach(r => {
|
||||
r.code = abbreviate(r.name, codes);
|
||||
|
||||
// move religion center if it's not within religion area after expansion
|
||||
if (cells.religion[r.center] === r.i) return; // in area
|
||||
const religCells = cells.i.filter(i => cells.religion[i] === r.i);
|
||||
if (!religCells.length) return; // extinct religion
|
||||
r.center = religCells.sort((a,b) => b.pop - a.pop)[0];
|
||||
});
|
||||
// move religion center if it's not within religion area after expansion
|
||||
if (cells.religion[r.center] === r.i) return; // in area
|
||||
const religCells = cells.i.filter(i => cells.religion[i] === r.i);
|
||||
if (!religCells.length) return; // extinct religion
|
||||
r.center = religCells.sort((a, b) => b.pop - a.pop)[0];
|
||||
});
|
||||
}
|
||||
|
||||
function updateCultures() {
|
||||
TIME && console.time('updateCulturesForReligions');
|
||||
pack.religions = pack.religions.map( (religion, index) => {
|
||||
if(index === 0) {
|
||||
TIME && console.time("updateCulturesForReligions");
|
||||
pack.religions = pack.religions.map((religion, index) => {
|
||||
if (index === 0) {
|
||||
return religion;
|
||||
}
|
||||
return {...religion, culture: pack.cells.culture[religion.center]};
|
||||
});
|
||||
TIME && console.timeEnd('updateCulturesForReligions');
|
||||
TIME && console.timeEnd("updateCulturesForReligions");
|
||||
}
|
||||
|
||||
// get supreme deity name
|
||||
const getDeityName = function(culture) {
|
||||
if (culture === undefined) {ERROR && console.error("Please define a culture"); return;}
|
||||
const getDeityName = function (culture) {
|
||||
if (culture === undefined) {
|
||||
ERROR && console.error("Please define a culture");
|
||||
return;
|
||||
}
|
||||
const meaning = generateMeaning();
|
||||
const cultureName = Names.getCulture(culture, null, null, "", .8);
|
||||
const cultureName = Names.getCulture(culture, null, null, "", 0.8);
|
||||
return cultureName + ", The " + meaning;
|
||||
}
|
||||
};
|
||||
|
||||
function generateMeaning() {
|
||||
const a = ra(approaches); // select generation approach
|
||||
|
|
@ -318,21 +351,29 @@
|
|||
|
||||
function getReligionName(form, deity, center) {
|
||||
const cells = pack.cells;
|
||||
const random = function() {return Names.getCulture(cells.culture[center], null, null, "", 0);}
|
||||
const type = function() {return rw(types[form]);}
|
||||
const supreme = function() {return deity.split(/[ ,]+/)[0];}
|
||||
const place = function(adj) {
|
||||
const random = function () {
|
||||
return Names.getCulture(cells.culture[center], null, null, "", 0);
|
||||
};
|
||||
const type = function () {
|
||||
return rw(types[form]);
|
||||
};
|
||||
const supreme = function () {
|
||||
return deity.split(/[ ,]+/)[0];
|
||||
};
|
||||
const place = function (adj) {
|
||||
const base = cells.burg[center] ? pack.burgs[cells.burg[center]].name : pack.states[cells.state[center]].name;
|
||||
let name = trimVowels(base.split(/[ ,]+/)[0]);
|
||||
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);
|
||||
if (m === "Random + type") return [random() + " " + type(), "global"];
|
||||
if (m === "Random + ism") return [trimVowels(random()) + "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 === "Culture + ism") return [trimVowels(culture()) + "ism", "culture"];
|
||||
if (m === "Place + ian + type") return [place("adj") + " " + type(), "state"];
|
||||
|
|
@ -342,14 +383,19 @@
|
|||
|
||||
function getCultName(form, center) {
|
||||
const cells = pack.cells;
|
||||
const type = function() {return rw(types[form]);}
|
||||
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]);}
|
||||
const type = function () {
|
||||
return rw(types[form]);
|
||||
};
|
||||
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() > .5) return random() + "ian " + type();
|
||||
if (Math.random() > 0.5) return random() + "ian " + type();
|
||||
return type() + " of the " + generateMeaning();
|
||||
};
|
||||
}
|
||||
|
||||
return {generate, add, getDeityName, expandReligions, updateCultures};
|
||||
|
||||
})));
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
TIME && console.time("generateRivers");
|
||||
Math.random = aleaPRNG(seed);
|
||||
|
|
@ -442,4 +440,4 @@
|
|||
};
|
||||
|
||||
return {generate, alterHeights, resolveDepressions, addMeandering, getRiverPath, specify, getName, getType, getBasin, getWidth, getOffset, getApproximateLength, getRiverPoints, remove};
|
||||
});
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -1,14 +1,9 @@
|
|||
(function (global, factory) {
|
||||
typeof exports === "object" && typeof module !== "undefined" ? (module.exports = factory()) : typeof define === "function" && define.amd ? define(factory) : (global.Routes = factory());
|
||||
})(this, function () {
|
||||
"use strict";
|
||||
|
||||
window.Routes = (function () {
|
||||
const getRoads = function () {
|
||||
TIME && console.time("generateMainRoads");
|
||||
const cells = pack.cells;
|
||||
const burgs = pack.burgs.filter(b => b.i && !b.removed);
|
||||
const capitals = burgs.filter(b => b.capital)
|
||||
.sort((a,b) => a.population - b.population);
|
||||
const capitals = burgs.filter(b => b.capital).sort((a, b) => a.population - b.population);
|
||||
|
||||
if (capitals.length < 2) return []; // not enough capitals to build main roads
|
||||
const paths = []; // array to store path segments
|
||||
|
|
@ -271,4 +266,4 @@
|
|||
}
|
||||
return [from, exit, false];
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -374,7 +374,7 @@ function getMapData() {
|
|||
const dateString = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
|
||||
const license = "File can be loaded in azgaar.github.io/Fantasy-Map-Generator";
|
||||
const params = [version, license, dateString, seed, graphWidth, graphHeight, mapId].join("|");
|
||||
const settings = [distanceUnitInput.value, distanceScaleInput.value, areaUnit.value, heightUnit.value, heightExponentInput.value, temperatureScale.value, barSizeInput.value, barLabel.value, barBackOpacity.value, barBackColor.value, barPosX.value, barPosY.value, populationRate, urbanization, mapSizeOutput.value, latitudeOutput.value, temperatureEquatorOutput.value, temperaturePoleOutput.value, precOutput.value, JSON.stringify(options), mapName.value, +hideLabels.checked, stylePreset.value].join("|");
|
||||
const settings = [distanceUnitInput.value, distanceScaleInput.value, areaUnit.value, heightUnit.value, heightExponentInput.value, temperatureScale.value, barSizeInput.value, barLabel.value, barBackOpacity.value, barBackColor.value, barPosX.value, barPosY.value, populationRate, urbanization, mapSizeOutput.value, latitudeOutput.value, temperatureEquatorOutput.value, temperaturePoleOutput.value, precOutput.value, JSON.stringify(options), mapName.value, +hideLabels.checked, stylePreset.value, +rescaleLabels.checked].join("|");
|
||||
const coords = JSON.stringify(mapCoordinates);
|
||||
const biomes = [biomesData.color, biomesData.habitability, biomesData.name].join("|");
|
||||
const notesData = JSON.stringify(notes);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
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};
|
||||
});
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
// heightmap-editor module. To be added to window as for now
|
||||
"use strict";
|
||||
|
||||
function editHeightmap() {
|
||||
|
|
@ -821,118 +820,15 @@ function editHeightmap() {
|
|||
body.setAttribute("data-changed", 0);
|
||||
body.innerHTML = "";
|
||||
|
||||
if (template === "templateVolcano") {
|
||||
addStep("Hill", "1", "90-100", "44-56", "40-60");
|
||||
addStep("Multiply", 0.8, "50-100");
|
||||
addStep("Range", "1.5", "30-55", "45-55", "40-60");
|
||||
addStep("Smooth", 2);
|
||||
addStep("Hill", "1.5", "25-35", "25-30", "20-75");
|
||||
addStep("Hill", "1", "25-35", "75-80", "25-75");
|
||||
addStep("Hill", "0.5", "20-25", "10-15", "20-25");
|
||||
} else if (template === "templateHighIsland") {
|
||||
addStep("Hill", "1", "90-100", "65-75", "47-53");
|
||||
addStep("Add", 5, "all");
|
||||
addStep("Hill", "6", "20-23", "25-55", "45-55");
|
||||
addStep("Range", "1", "40-50", "45-55", "45-55");
|
||||
addStep("Smooth", 2);
|
||||
addStep("Trough", "2-3", "20-30", "20-30", "20-30");
|
||||
addStep("Trough", "2-3", "20-30", "60-80", "70-80");
|
||||
addStep("Hill", "1", "10-15", "60-60", "50-50");
|
||||
addStep("Hill", "1.5", "13-16", "15-20", "20-75");
|
||||
addStep("Multiply", 0.8, "20-100");
|
||||
addStep("Range", "1.5", "30-40", "15-85", "30-40");
|
||||
addStep("Range", "1.5", "30-40", "15-85", "60-70");
|
||||
addStep("Pit", "2-3", "10-15", "15-85", "20-80");
|
||||
} else if (template === "templateLowIsland") {
|
||||
addStep("Hill", "1", "90-99", "60-80", "45-55");
|
||||
addStep("Hill", "4-5", "25-35", "20-65", "40-60");
|
||||
addStep("Range", "1", "40-50", "45-55", "45-55");
|
||||
addStep("Smooth", 3);
|
||||
addStep("Trough", "1.5", "20-30", "15-85", "20-30");
|
||||
addStep("Trough", "1.5", "20-30", "15-85", "70-80");
|
||||
addStep("Hill", "1.5", "10-15", "5-15", "20-80");
|
||||
addStep("Hill", "1", "10-15", "85-95", "70-80");
|
||||
addStep("Pit", "3-5", "10-15", "15-85", "20-80");
|
||||
addStep("Multiply", 0.4, "20-100");
|
||||
} else if (template === "templateContinents") {
|
||||
addStep("Hill", "1", "80-85", "75-80", "40-60");
|
||||
addStep("Hill", "1", "80-85", "20-25", "40-60");
|
||||
addStep("Multiply", 0.22, "20-100");
|
||||
addStep("Hill", "5-6", "15-20", "25-75", "20-82");
|
||||
addStep("Range", ".8", "30-60", "5-15", "20-45");
|
||||
addStep("Range", ".8", "30-60", "5-15", "55-80");
|
||||
addStep("Range", "0-3", "30-60", "80-90", "20-80");
|
||||
addStep("Trough", "3-4", "15-20", "15-85", "20-80");
|
||||
addStep("Strait", "2", "vertical");
|
||||
addStep("Smooth", 2);
|
||||
addStep("Trough", "1-2", "5-10", "45-55", "45-55");
|
||||
addStep("Pit", "3-4", "10-15", "15-85", "20-80");
|
||||
addStep("Hill", "1", "5-10", "40-60", "40-60");
|
||||
} else if (template === "templateArchipelago") {
|
||||
addStep("Add", 11, "all");
|
||||
addStep("Range", "2-3", "40-60", "20-80", "20-80");
|
||||
addStep("Hill", "5", "15-20", "10-90", "30-70");
|
||||
addStep("Hill", "2", "10-15", "10-30", "20-80");
|
||||
addStep("Hill", "2", "10-15", "60-90", "20-80");
|
||||
addStep("Smooth", 3);
|
||||
addStep("Trough", "10", "20-30", "5-95", "5-95");
|
||||
addStep("Strait", "2", "vertical");
|
||||
addStep("Strait", "2", "horizontal");
|
||||
} else if (template === "templateAtoll") {
|
||||
addStep("Hill", "1", "75-80", "50-60", "45-55");
|
||||
addStep("Hill", "1.5", "30-50", "25-75", "30-70");
|
||||
addStep("Hill", ".5", "30-50", "25-35", "30-70");
|
||||
addStep("Smooth", 1);
|
||||
addStep("Multiply", 0.2, "25-100");
|
||||
addStep("Hill", ".5", "10-20", "50-55", "48-52");
|
||||
} else if (template === "templateMediterranean") {
|
||||
addStep("Range", "3-4", "30-50", "0-100", "0-10");
|
||||
addStep("Range", "3-4", "30-50", "0-100", "90-100");
|
||||
addStep("Hill", "5-6", "30-70", "0-100", "0-5");
|
||||
addStep("Hill", "5-6", "30-70", "0-100", "95-100");
|
||||
addStep("Smooth", 1);
|
||||
addStep("Hill", "2-3", "30-70", "0-5", "20-80");
|
||||
addStep("Hill", "2-3", "30-70", "95-100", "20-80");
|
||||
addStep("Multiply", 0.8, "land");
|
||||
addStep("Trough", "3-5", "40-50", "0-100", "0-10");
|
||||
addStep("Trough", "3-5", "40-50", "0-100", "90-100");
|
||||
} else if (template === "templatePeninsula") {
|
||||
addStep("Range", "2-3", "20-35", "40-50", "0-15");
|
||||
addStep("Add", 5, "all");
|
||||
addStep("Hill", "1", "90-100", "10-90", "0-5");
|
||||
addStep("Add", 13, "all");
|
||||
addStep("Hill", "3-4", "3-5", "5-95", "80-100");
|
||||
addStep("Hill", "1-2", "3-5", "5-95", "40-60");
|
||||
addStep("Trough", "5-6", "10-25", "5-95", "5-95");
|
||||
addStep("Smooth", 3);
|
||||
} else if (template === "templatePangea") {
|
||||
addStep("Hill", "1-2", "25-40", "15-50", "0-10");
|
||||
addStep("Hill", "1-2", "5-40", "50-85", "0-10");
|
||||
addStep("Hill", "1-2", "25-40", "50-85", "90-100");
|
||||
addStep("Hill", "1-2", "5-40", "15-50", "90-100");
|
||||
addStep("Hill", "8-12", "20-40", "20-80", "48-52");
|
||||
addStep("Smooth", 2);
|
||||
addStep("Multiply", 0.7, "land");
|
||||
addStep("Trough", "3-4", "25-35", "5-95", "10-20");
|
||||
addStep("Trough", "3-4", "25-35", "5-95", "80-90");
|
||||
addStep("Range", "5-6", "30-40", "10-90", "35-65");
|
||||
} else if (template === "templateIsthmus") {
|
||||
addStep("Hill", "5-10", "15-30", "0-30", "0-20");
|
||||
addStep("Hill", "5-10", "15-30", "10-50", "20-40");
|
||||
addStep("Hill", "5-10", "15-30", "30-70", "40-60");
|
||||
addStep("Hill", "5-10", "15-30", "50-90", "60-80");
|
||||
addStep("Hill", "5-10", "15-30", "70-100", "80-100");
|
||||
addStep("Smooth", 2);
|
||||
addStep("Trough", "4-8", "15-30", "0-30", "0-20");
|
||||
addStep("Trough", "4-8", "15-30", "10-50", "20-40");
|
||||
addStep("Trough", "4-8", "15-30", "30-70", "40-60");
|
||||
addStep("Trough", "4-8", "15-30", "50-90", "60-80");
|
||||
addStep("Trough", "4-8", "15-30", "70-100", "80-100");
|
||||
} else if (template === "templateShattered") {
|
||||
addStep("Hill", "8", "35-40", "15-85", "30-70");
|
||||
addStep("Trough", "10-20", "40-50", "5-95", "5-95");
|
||||
addStep("Range", "5-7", "30-40", "10-90", "20-80");
|
||||
addStep("Pit", "12-20", "30-40", "15-85", "20-80");
|
||||
const templateString = HeightmapTemplates[template];
|
||||
if (!templateString) return;
|
||||
|
||||
const steps = templateString.split("\n");
|
||||
if (!steps.length) return tip(`Heightmap template: no steps defined`, false, "error");
|
||||
|
||||
for (const step of steps) {
|
||||
const elements = step.trim().split(" ");
|
||||
addStep(...elements);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -122,9 +122,10 @@ function restoreLayers() {
|
|||
if (layerIsOn("toggleIce")) drawIce();
|
||||
if (layerIsOn("toggleEmblems")) drawEmblems();
|
||||
|
||||
// states are getting rendered each time, if it's not required than layers should be hidden
|
||||
if (!layerIsOn("toggleBorders")) $("#borders").fadeOut();
|
||||
if (!layerIsOn("toggleStates")) regions.style("display", "none").selectAll("path").remove();
|
||||
// some layers are rendered each time, remove them if they are not on
|
||||
if (!layerIsOn("toggleBorders")) borders.selectAll("path").remove();
|
||||
if (!layerIsOn("toggleStates")) regions.selectAll("path").remove();
|
||||
if (!layerIsOn("toggleRivers")) rivers.selectAll("*").remove();
|
||||
}
|
||||
|
||||
function toggleHeight(event) {
|
||||
|
|
@ -1034,13 +1035,14 @@ function drawBorders() {
|
|||
TIME && console.time("drawBorders");
|
||||
borders.selectAll("path").remove();
|
||||
|
||||
const cells = pack.cells,
|
||||
vertices = pack.vertices,
|
||||
n = cells.i.length;
|
||||
const sPath = [],
|
||||
pPath = [];
|
||||
const sUsed = new Array(pack.states.length).fill("").map(a => []);
|
||||
const pUsed = new Array(pack.provinces.length).fill("").map(a => []);
|
||||
const {cells, vertices} = pack;
|
||||
const n = cells.i.length;
|
||||
|
||||
const sPath = [];
|
||||
const pPath = [];
|
||||
|
||||
const sUsed = new Array(pack.states.length).fill("").map(_ => []);
|
||||
const pUsed = new Array(pack.provinces.length).fill("").map(_ => []);
|
||||
|
||||
for (let i = 0; i < cells.i.length; i++) {
|
||||
if (!cells.state[i]) continue;
|
||||
|
|
|
|||
|
|
@ -98,7 +98,8 @@ function showSupporters() {
|
|||
PlayByMail.Net,Brad Wardell,Lance Saba,Egoensis,Brea Richards,Tiber,Chris Bloom,Maxim Lowe,Aquelion,Page One Project,Spencer Morris,Paul Ingram,
|
||||
Dust Bunny,Adrian Wright,Eric Alexander Cartaya,GameNight,Thomas Mortensen Hansen,Zklaus,Drinarius,Ed Wright,Lon Varnadore,Crys Cain,Heaven N Lee,
|
||||
Jeffrey Henning,Lazer Elf,Jordan Bellah,Alex Beard,Kass Frisson,Petro Lombaard,Emanuel Pietri,Rox,PinkEvil,Gavin Madrigal,Martin Lorber,Prince of Morgoth,
|
||||
Jaryd Armstrong,Andrew Pirkola,ThyHolyDevil,Gary Smith,Tyshaun Wise,Ethan Cook,Jon Stroman,Nobody679,良义 金,Chris Gray,Phoenix Boatwright`;
|
||||
Jaryd Armstrong,Andrew Pirkola,ThyHolyDevil,Gary Smith,Tyshaun Wise,Ethan Cook,Jon Stroman,Nobody679,良义 金,Chris Gray,Phoenix Boatwright,Mackenzie,
|
||||
"Milo Cohen,Jason Matthew Wuerfel,Rasmus Legêne,Andrew Hines,Wexxler,Espen Sæverud,Binks,Dominick Ormsby,Linn Browning,Václav Švec,Alan Buehne,George J.Lekkas"`;
|
||||
|
||||
const array = supporters
|
||||
.replace(/(?:\r\n|\r|\n)/g, "")
|
||||
|
|
@ -541,17 +542,18 @@ function randomizeOptions() {
|
|||
// select heightmap template pseudo-randomly
|
||||
function randomizeHeightmapTemplate() {
|
||||
const templates = {
|
||||
Volcano: 3,
|
||||
"High Island": 22,
|
||||
"Low Island": 9,
|
||||
Continents: 20,
|
||||
Archipelago: 25,
|
||||
Mediterranean: 3,
|
||||
Peninsula: 3,
|
||||
Pangea: 5,
|
||||
Isthmus: 2,
|
||||
Atoll: 1,
|
||||
Shattered: 7
|
||||
volcano: 3,
|
||||
highIsland: 22,
|
||||
lowIsland: 9,
|
||||
continents: 19,
|
||||
archipelago: 23,
|
||||
mediterranean: 5,
|
||||
peninsula: 3,
|
||||
pangea: 5,
|
||||
isthmus: 2,
|
||||
atoll: 1,
|
||||
shattered: 7,
|
||||
taklamakan: 1
|
||||
};
|
||||
document.getElementById("templateInput").value = rw(templates);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ function createRiver() {
|
|||
const riverCells = createRiver.cells;
|
||||
if (riverCells.length < 2) return tip("Add at least 2 cells", false, "error");
|
||||
|
||||
const riverId = last(rivers).i + 1;
|
||||
const riverId = rivers.length ? last(rivers).i + 1 : 1;
|
||||
const parent = cells.r[last(riverCells)] || riverId;
|
||||
|
||||
riverCells.forEach(cell => {
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ function editRiver(id) {
|
|||
debug
|
||||
.select("#controlCells")
|
||||
.selectAll(`polygon.${type}`)
|
||||
.data(cells)
|
||||
.data(cells.filter(i => pack.cells.i[i]))
|
||||
.join("polygon")
|
||||
.attr("points", d => getPackPolygon(d))
|
||||
.attr("class", type);
|
||||
|
|
@ -124,18 +124,13 @@ function editRiver(id) {
|
|||
const initCell = +this.dataset.cell;
|
||||
const index = +this.dataset.i;
|
||||
|
||||
const occupiedCells = i.filter(i => r[i] && !river.cells.includes(i));
|
||||
drawCells(occupiedCells, "occupied");
|
||||
let movedToCell = null;
|
||||
|
||||
d3.event.on("drag", function () {
|
||||
const {x, y} = d3.event;
|
||||
const currentCell = findCell(x, y);
|
||||
|
||||
if (initCell !== currentCell) {
|
||||
if (occupiedCells.includes(currentCell)) return;
|
||||
movedToCell = currentCell;
|
||||
} else movedToCell = null;
|
||||
movedToCell = initCell !== currentCell ? currentCell : null;
|
||||
|
||||
this.setAttribute("cx", x);
|
||||
this.setAttribute("cy", y);
|
||||
|
|
@ -149,15 +144,15 @@ function editRiver(id) {
|
|||
river.cells[index] = movedToCell;
|
||||
drawCells(river.cells, "current");
|
||||
|
||||
// swap river data
|
||||
r[initCell] = 0;
|
||||
r[movedToCell] = river.i;
|
||||
const sourceFlux = fl[initCell];
|
||||
fl[initCell] = fl[movedToCell];
|
||||
fl[movedToCell] = sourceFlux;
|
||||
if (!r[movedToCell]) {
|
||||
// swap river data
|
||||
r[initCell] = 0;
|
||||
r[movedToCell] = river.i;
|
||||
const sourceFlux = fl[initCell];
|
||||
fl[initCell] = fl[movedToCell];
|
||||
fl[movedToCell] = sourceFlux;
|
||||
}
|
||||
}
|
||||
|
||||
debug.select("#controlCells").selectAll("polygon.available, polygon.occupied").remove();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -539,7 +539,7 @@ function addRiverOnClick() {
|
|||
|
||||
const {alterHeights, resolveDepressions, addMeandering, getRiverPath, getBasin, getName, getType, getWidth, getOffset, getApproximateLength} = Rivers;
|
||||
const riverCells = [];
|
||||
let riverId = last(rivers).i + 1;
|
||||
let riverId = rivers.length ? last(rivers).i + 1 : 1;
|
||||
let parent = riverId;
|
||||
|
||||
const initialFlux = grid.cells.prec[cells.g[i]];
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
"use strict";
|
||||
|
||||
function editZones() {
|
||||
closeDialogs();
|
||||
if (!layerIsOn("toggleZones")) toggleZones();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue