mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-23 04:21: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;
|
stroke-width: 0.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
#controlCells > .occupied {
|
|
||||||
fill: #ff828240;
|
|
||||||
stroke: #ff8282;
|
|
||||||
stroke-width: 0.4;
|
|
||||||
}
|
|
||||||
|
|
||||||
#vertices > circle {
|
#vertices > circle {
|
||||||
fill: #ff0000;
|
fill: #ff0000;
|
||||||
stroke: #841f1f;
|
stroke: #841f1f;
|
||||||
|
|
@ -1285,17 +1279,26 @@ div.slider .ui-slider-handle {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.burgs-table {
|
|
||||||
max-height: 75vh;
|
|
||||||
overflow-x: hidden;
|
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table {
|
.table {
|
||||||
max-height: 75vh;
|
max-height: 75vh;
|
||||||
max-width: 75vw;
|
max-width: 75vw;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: auto;
|
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 {
|
.overflow {
|
||||||
|
|
|
||||||
62
index.html
62
index.html
|
|
@ -910,6 +910,13 @@
|
||||||
<label for="hideLabels" class="checkbox-label">Toggle visibility automatically</label>
|
<label for="hideLabels" class="checkbox-label">Toggle visibility automatically</label>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</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>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
@ -1000,17 +1007,18 @@
|
||||||
<td>Map template</td>
|
<td>Map template</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="templateInput" data-stored="template">
|
<select id="templateInput" data-stored="template">
|
||||||
<option value="Volcano">Volcano</option>
|
<option value="volcano">Volcano</option>
|
||||||
<option value="High Island">High Island</option>
|
<option value="highIsland">High Island</option>
|
||||||
<option value="Low Island">Low Island</option>
|
<option value="lowIsland">Low Island</option>
|
||||||
<option value="Continents">Two Continents</option>
|
<option value="continents">Two Continents</option>
|
||||||
<option value="Archipelago">Archipelago</option>
|
<option value="archipelago">Archipelago</option>
|
||||||
<option value="Atoll">Atoll</option>
|
<option value="atoll">Atoll</option>
|
||||||
<option value="Mediterranean">Mediterranean</option>
|
<option value="mediterranean">Mediterranean</option>
|
||||||
<option value="Peninsula">Peninsula</option>
|
<option value="peninsula">Peninsula</option>
|
||||||
<option value="Pangea">Pangea</option>
|
<option value="pangea">Pangea</option>
|
||||||
<option value="Isthmus">Isthmus</option>
|
<option value="isthmus">Isthmus</option>
|
||||||
<option value="Shattered">Shattered</option>
|
<option value="shattered">Shattered</option>
|
||||||
|
<option value="taklamakan">Taklamakan</option>
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
|
|
@ -1665,7 +1673,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="riverCreator" class="dialog" style="display: none">
|
<div id="riverCreator" class="dialog" style="display: none">
|
||||||
<div id="riverCreatorBody"></div>
|
<div id="riverCreatorBody" class="table"></div>
|
||||||
<div id="riverCreatorBottom">
|
<div id="riverCreatorBottom">
|
||||||
<button id="riverCreatorComplete" data-tip="Complete river creation" class="icon-check"></button>
|
<button id="riverCreatorComplete" data-tip="Complete river creation" class="icon-check"></button>
|
||||||
<button id="riverCreatorCancel" data-tip="Cancel the creation" class="icon-cancel"></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="templateEditor" class="dialog stable" style="display: none">
|
||||||
<div id="templateTop">
|
<div id="templateTop">
|
||||||
<i>Select template: </i><select id="templateSelect" style="width:16em" data-prev="templateCustom" data-tip="Select base template">
|
<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="custom" selected>Custom</option>
|
||||||
<option value="templateVolcano">Volcano</option>
|
<option value="volcano">Volcano</option>
|
||||||
<option value="templateHighIsland">High Island</option>
|
<option value="highIsland">High Island</option>
|
||||||
<option value="templateLowIsland">Low Island</option>
|
<option value="lowIsland">Low Island</option>
|
||||||
<option value="templateContinents">Two Continents</option>
|
<option value="continents">Two Continents</option>
|
||||||
<option value="templateArchipelago">Archipelago</option>
|
<option value="archipelago">Archipelago</option>
|
||||||
<option value="templateAtoll">Atoll</option>
|
<option value="atoll">Atoll</option>
|
||||||
<option value="templateMediterranean">Mediterranean</option>
|
<option value="mediterranean">Mediterranean</option>
|
||||||
<option value="templatePeninsula">Peninsula</option>
|
<option value="peninsula">Peninsula</option>
|
||||||
<option value="templatePangea">Pangea</option>
|
<option value="pangea">Pangea</option>
|
||||||
<option value="templateIsthmus">Isthmus</option>
|
<option value="isthmus">Isthmus</option>
|
||||||
<option value="templateShattered">Shattered</option>
|
<option value="shattered">Shattered</option>
|
||||||
|
<option value="taklamakan">Taklamakan</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div id="templateTools">
|
<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 style="left:31.2em" data-tip="Click to sort by burg type" class="sortable alphabetically" data-sortby="type">Type </div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="burgsBody" class="burgs-table"></div>
|
<div id="burgsBody" class="table"></div>
|
||||||
|
|
||||||
<div id="burgsFilters" data-tip="Apply a filter">
|
<div id="burgsFilters" data-tip="Apply a filter">
|
||||||
<span>State: </span>
|
<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 style="left:30em" data-tip="Click to sort by river basin" class="sortable alphabetically" data-sortby="basin">Basin </div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="riversBody" class="burgs-table"></div>
|
<div id="riversBody" class="table"></div>
|
||||||
|
|
||||||
<div id="riversFooter" class="totalLine">
|
<div id="riversFooter" class="totalLine">
|
||||||
<div data-tip="Rivers number" style="margin-left: 4px">Rivers: <span id="riversFooterNumber">0</span></div>
|
<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="libs/delaunator.min.js"></script>
|
||||||
<script src="modules/utils.js"></script>
|
<script src="modules/utils.js"></script>
|
||||||
<script src="modules/voronoi.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/heightmap-generator.js"></script>
|
||||||
<script src="modules/ocean-layers.js"></script>
|
<script src="modules/ocean-layers.js"></script>
|
||||||
<script src="modules/river-generator.js"></script>
|
<script src="modules/river-generator.js"></script>
|
||||||
|
|
|
||||||
210
libs/pell.js
210
libs/pell.js
|
|
@ -1,163 +1,157 @@
|
||||||
(function (global, factory) {
|
"use strict";
|
||||||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
|
||||||
typeof define === 'function' && define.amd ? define(factory) :
|
|
||||||
(global.Pell = factory());
|
|
||||||
}(this, (function () { 'use strict';
|
|
||||||
|
|
||||||
const defaultParagraphSeparatorString = 'defaultParagraphSeparator'
|
window.Pell = (function () {
|
||||||
const formatBlock = 'formatBlock'
|
const defaultParagraphSeparatorString = "defaultParagraphSeparator";
|
||||||
const addEventListener = (parent, type, listener) => parent.addEventListener(type, listener)
|
const formatBlock = "formatBlock";
|
||||||
const appendChild = (parent, child) => parent.appendChild(child)
|
const addEventListener = (parent, type, listener) => parent.addEventListener(type, listener);
|
||||||
const createElement = tag => document.createElement(tag)
|
const appendChild = (parent, child) => parent.appendChild(child);
|
||||||
const queryCommandState = command => document.queryCommandState(command)
|
const createElement = tag => document.createElement(tag);
|
||||||
const queryCommandValue = command => document.queryCommandValue(command)
|
const queryCommandState = command => document.queryCommandState(command);
|
||||||
const exec = (command, value = null) => document.execCommand(command, false, value)
|
const queryCommandValue = command => document.queryCommandValue(command);
|
||||||
|
const exec = (command, value = null) => document.execCommand(command, false, value);
|
||||||
|
|
||||||
const defaultActions = {
|
const defaultActions = {
|
||||||
bold: {
|
bold: {
|
||||||
icon: '<b>B</b>',
|
icon: "<b>B</b>",
|
||||||
title: 'Bold',
|
title: "Bold",
|
||||||
state: () => queryCommandState('bold'),
|
state: () => queryCommandState("bold"),
|
||||||
result: () => exec('bold')
|
result: () => exec("bold")
|
||||||
},
|
},
|
||||||
italic: {
|
italic: {
|
||||||
icon: '<i>I</i>',
|
icon: "<i>I</i>",
|
||||||
title: 'Italic',
|
title: "Italic",
|
||||||
state: () => queryCommandState('italic'),
|
state: () => queryCommandState("italic"),
|
||||||
result: () => exec('italic')
|
result: () => exec("italic")
|
||||||
},
|
},
|
||||||
underline: {
|
underline: {
|
||||||
icon: '<u>U</u>',
|
icon: "<u>U</u>",
|
||||||
title: 'Underline',
|
title: "Underline",
|
||||||
state: () => queryCommandState('underline'),
|
state: () => queryCommandState("underline"),
|
||||||
result: () => exec('underline')
|
result: () => exec("underline")
|
||||||
},
|
},
|
||||||
strikethrough: {
|
strikethrough: {
|
||||||
icon: '<strike>S</strike>',
|
icon: "<strike>S</strike>",
|
||||||
title: 'Strike-through',
|
title: "Strike-through",
|
||||||
state: () => queryCommandState('strikeThrough'),
|
state: () => queryCommandState("strikeThrough"),
|
||||||
result: () => exec('strikeThrough')
|
result: () => exec("strikeThrough")
|
||||||
},
|
},
|
||||||
heading1: {
|
heading1: {
|
||||||
icon: '<b>H<sub>1</sub></b>',
|
icon: "<b>H<sub>1</sub></b>",
|
||||||
title: 'Heading 1',
|
title: "Heading 1",
|
||||||
result: () => exec(formatBlock, '<h1>')
|
result: () => exec(formatBlock, "<h1>")
|
||||||
},
|
},
|
||||||
heading2: {
|
heading2: {
|
||||||
icon: '<b>H<sub>2</sub></b>',
|
icon: "<b>H<sub>2</sub></b>",
|
||||||
title: 'Heading 2',
|
title: "Heading 2",
|
||||||
result: () => exec(formatBlock, '<h2>')
|
result: () => exec(formatBlock, "<h2>")
|
||||||
},
|
},
|
||||||
paragraph: {
|
paragraph: {
|
||||||
icon: '¶',
|
icon: "¶",
|
||||||
title: 'Paragraph',
|
title: "Paragraph",
|
||||||
result: () => exec(formatBlock, '<p>')
|
result: () => exec(formatBlock, "<p>")
|
||||||
},
|
},
|
||||||
quote: {
|
quote: {
|
||||||
icon: '“ ”',
|
icon: "“ ”",
|
||||||
title: 'Quote',
|
title: "Quote",
|
||||||
result: () => exec(formatBlock, '<blockquote>')
|
result: () => exec(formatBlock, "<blockquote>")
|
||||||
},
|
},
|
||||||
olist: {
|
olist: {
|
||||||
icon: '#',
|
icon: "#",
|
||||||
title: 'Ordered List',
|
title: "Ordered List",
|
||||||
result: () => exec('insertOrderedList')
|
result: () => exec("insertOrderedList")
|
||||||
},
|
},
|
||||||
ulist: {
|
ulist: {
|
||||||
icon: '•',
|
icon: "•",
|
||||||
title: 'Unordered List',
|
title: "Unordered List",
|
||||||
result: () => exec('insertUnorderedList')
|
result: () => exec("insertUnorderedList")
|
||||||
},
|
},
|
||||||
code: {
|
code: {
|
||||||
icon: '</>',
|
icon: "</>",
|
||||||
title: 'Code',
|
title: "Code",
|
||||||
result: () => exec(formatBlock, '<pre>')
|
result: () => exec(formatBlock, "<pre>")
|
||||||
},
|
},
|
||||||
line: {
|
line: {
|
||||||
icon: '―',
|
icon: "―",
|
||||||
title: 'Horizontal Line',
|
title: "Horizontal Line",
|
||||||
result: () => exec('insertHorizontalRule')
|
result: () => exec("insertHorizontalRule")
|
||||||
},
|
},
|
||||||
link: {
|
link: {
|
||||||
icon: '🔗',
|
icon: "🔗",
|
||||||
title: 'Link',
|
title: "Link",
|
||||||
result: () => navigator.clipboard.readText().then(url => exec('createLink', url))
|
result: () => navigator.clipboard.readText().then(url => exec("createLink", url))
|
||||||
},
|
},
|
||||||
image: {
|
image: {
|
||||||
icon: '📷',
|
icon: "📷",
|
||||||
title: 'Image',
|
title: "Image",
|
||||||
result: () => {
|
result: () => {
|
||||||
navigator.clipboard.readText().then(url => exec('insertImage', url))
|
navigator.clipboard.readText().then(url => exec("insertImage", url));
|
||||||
exec('enableObjectResizing')
|
exec("enableObjectResizing");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const defaultClasses = {
|
const defaultClasses = {
|
||||||
actionbar: 'pell-actionbar',
|
actionbar: "pell-actionbar",
|
||||||
button: 'pell-button',
|
button: "pell-button",
|
||||||
content: 'pell-content',
|
content: "pell-content",
|
||||||
selected: 'pell-button-selected'
|
selected: "pell-button-selected"
|
||||||
}
|
};
|
||||||
|
|
||||||
const init = settings => {
|
const init = settings => {
|
||||||
const actions = settings.actions
|
const actions = settings.actions
|
||||||
? (
|
? settings.actions.map(action => {
|
||||||
settings.actions.map(action => {
|
if (typeof action === "string") return defaultActions[action];
|
||||||
if (typeof action === 'string') return defaultActions[action]
|
else if (defaultActions[action.name]) return {...defaultActions[action.name], ...action};
|
||||||
else if (defaultActions[action.name]) return { ...defaultActions[action.name], ...action }
|
return action;
|
||||||
return action
|
|
||||||
})
|
})
|
||||||
)
|
: Object.keys(defaultActions).map(action => defaultActions[action]);
|
||||||
: Object.keys(defaultActions).map(action => defaultActions[action])
|
|
||||||
|
|
||||||
const classes = { ...defaultClasses, ...settings.classes }
|
const classes = {...defaultClasses, ...settings.classes};
|
||||||
|
|
||||||
const defaultParagraphSeparator = settings[defaultParagraphSeparatorString] || 'div'
|
const defaultParagraphSeparator = settings[defaultParagraphSeparatorString] || "div";
|
||||||
|
|
||||||
const actionbar = createElement('div')
|
const actionbar = createElement("div");
|
||||||
actionbar.className = classes.actionbar
|
actionbar.className = classes.actionbar;
|
||||||
appendChild(settings.element, actionbar)
|
appendChild(settings.element, actionbar);
|
||||||
|
|
||||||
const content = settings.element.content = createElement('div')
|
const content = (settings.element.content = createElement("div"));
|
||||||
content.contentEditable = true
|
content.contentEditable = true;
|
||||||
content.className = classes.content
|
content.className = classes.content;
|
||||||
content.oninput = ({target: {firstChild}}) => {
|
content.oninput = ({target: {firstChild}}) => {
|
||||||
if (firstChild && firstChild.nodeType === 3) exec(formatBlock, `<${defaultParagraphSeparator}>`)
|
if (firstChild && firstChild.nodeType === 3) exec(formatBlock, `<${defaultParagraphSeparator}>`);
|
||||||
else if (content.innerHTML === '<br>') content.innerHTML = ''
|
else if (content.innerHTML === "<br>") content.innerHTML = "";
|
||||||
settings.onChange(content.innerHTML)
|
settings.onChange(content.innerHTML);
|
||||||
}
|
};
|
||||||
content.onkeydown = event => {
|
content.onkeydown = event => {
|
||||||
if (event.key === 'Enter' && queryCommandValue(formatBlock) === 'blockquote') {
|
if (event.key === "Enter" && queryCommandValue(formatBlock) === "blockquote") {
|
||||||
setTimeout(() => exec(formatBlock, `<${defaultParagraphSeparator}>`), 0)
|
setTimeout(() => exec(formatBlock, `<${defaultParagraphSeparator}>`), 0);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
appendChild(settings.element, content)
|
appendChild(settings.element, content);
|
||||||
|
|
||||||
actions.forEach(action => {
|
actions.forEach(action => {
|
||||||
const button = createElement('button')
|
const button = createElement("button");
|
||||||
button.className = classes.button
|
button.className = classes.button;
|
||||||
button.innerHTML = action.icon
|
button.innerHTML = action.icon;
|
||||||
button.title = action.title
|
button.title = action.title;
|
||||||
button.setAttribute('type', 'button')
|
button.setAttribute("type", "button");
|
||||||
button.onclick = () => action.result() && content.focus()
|
button.onclick = () => action.result() && content.focus();
|
||||||
|
|
||||||
if (action.state) {
|
if (action.state) {
|
||||||
const handler = () => button.classList[action.state() ? 'add' : 'remove'](classes.selected)
|
const handler = () => button.classList[action.state() ? "add" : "remove"](classes.selected);
|
||||||
addEventListener(content, 'keyup', handler)
|
addEventListener(content, "keyup", handler);
|
||||||
addEventListener(content, 'mouseup', handler)
|
addEventListener(content, "mouseup", handler);
|
||||||
addEventListener(button, 'click', handler)
|
addEventListener(button, "click", handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
appendChild(actionbar, button)
|
appendChild(actionbar, button);
|
||||||
})
|
});
|
||||||
|
|
||||||
if (settings.styleWithCSS) exec('styleWithCSS')
|
if (settings.styleWithCSS) exec("styleWithCSS");
|
||||||
exec(defaultParagraphSeparatorString, defaultParagraphSeparator)
|
exec(defaultParagraphSeparatorString, defaultParagraphSeparator);
|
||||||
|
|
||||||
return settings.element
|
return settings.element;
|
||||||
}
|
};
|
||||||
|
|
||||||
return {exec, init}
|
return {exec, init};
|
||||||
|
})();
|
||||||
})));
|
|
||||||
|
|
|
||||||
5
main.js
5
main.js
|
|
@ -2,7 +2,7 @@
|
||||||
// https://github.com/Azgaar/Fantasy-Map-Generator
|
// https://github.com/Azgaar/Fantasy-Map-Generator
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
const version = "1.651"; // generator version1
|
const version = "1.652"; // generator version1
|
||||||
document.title += " v" + version;
|
document.title += " v" + version;
|
||||||
|
|
||||||
// Switches to disable/enable logging features
|
// Switches to disable/enable logging features
|
||||||
|
|
@ -479,7 +479,8 @@ function invokeActiveZooming() {
|
||||||
if (this.id === "burgLabels") return;
|
if (this.id === "burgLabels") return;
|
||||||
const desired = +this.dataset.size;
|
const desired = +this.dataset.size;
|
||||||
const relative = Math.max(rn((desired + desired / scale) / 2, 2), 1);
|
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);
|
const hidden = hideLabels.checked && (relative * scale < 6 || relative * scale > 60);
|
||||||
if (hidden) this.classList.add("hidden");
|
if (hidden) this.classList.add("hidden");
|
||||||
else this.classList.remove("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 generate = function () {
|
||||||
const cells = pack.cells,
|
const {cells, cultures} = pack;
|
||||||
cultures = pack.cultures,
|
const n = cells.i.length;
|
||||||
n = cells.i.length;
|
|
||||||
|
|
||||||
cells.burg = new Uint16Array(n); // cell burg
|
cells.burg = new Uint16Array(n); // cell burg
|
||||||
cells.road = new Uint16Array(n); // cell road power
|
cells.road = new Uint16Array(n); // cell road power
|
||||||
|
|
@ -37,7 +34,8 @@
|
||||||
let count = +regionsInput.value;
|
let count = +regionsInput.value;
|
||||||
let burgs = [0];
|
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
|
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) {
|
if (sorted.length < count * 10) {
|
||||||
|
|
@ -54,9 +52,8 @@
|
||||||
let spacing = (graphWidth + graphHeight) / 2 / count; // min distance between capitals
|
let spacing = (graphWidth + graphHeight) / 2 / count; // min distance between capitals
|
||||||
|
|
||||||
for (let i = 0; burgs.length <= count; i++) {
|
for (let i = 0; burgs.length <= count; i++) {
|
||||||
const cell = sorted[i],
|
const cell = sorted[i];
|
||||||
x = cells.p[cell][0],
|
const [x, y] = cells.p[cell];
|
||||||
y = cells.p[cell][1];
|
|
||||||
|
|
||||||
if (burgsTree.find(x, y, spacing) === undefined) {
|
if (burgsTree.find(x, y, spacing) === undefined) {
|
||||||
burgs.push({cell, x, y});
|
burgs.push({cell, x, y});
|
||||||
|
|
@ -66,7 +63,9 @@
|
||||||
if (i === sorted.length - 1) {
|
if (i === sorted.length - 1) {
|
||||||
WARN && console.warn("Cannot place capitals with current spacing. Trying again with reduced spacing");
|
WARN && console.warn("Cannot place capitals with current spacing. Trying again with reduced spacing");
|
||||||
burgsTree = d3.quadtree();
|
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};
|
return {generate, expandStates, normalizeStates, assignColors, drawBurgs, specifyBurgs, defineBurgFeatures, getType, drawStateLabels, collectStatistics, generateCampaigns, generateDiplomacy, defineStateForms, getFullName, generateProvinces, updateCultures};
|
||||||
});
|
})();
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,47 @@
|
||||||
(function (global, factory) {
|
"use strict";
|
||||||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
|
||||||
typeof define === 'function' && define.amd ? define(factory) :
|
|
||||||
(global.COA = factory());
|
|
||||||
}(this, (function () {'use strict';
|
|
||||||
|
|
||||||
|
window.COA = (function () {
|
||||||
const tinctures = {
|
const tinctures = {
|
||||||
field: { metals: 3, colours: 4, stains: +P(.03), patterns: 1 },
|
field: {metals: 3, colours: 4, stains: +P(0.03), patterns: 1},
|
||||||
division: { metals: 5, colours: 8, stains: +P(.03), patterns: 1 },
|
division: {metals: 5, colours: 8, stains: +P(0.03), patterns: 1},
|
||||||
charge: { metals: 2, colours: 3, stains: +P(.05), patterns: 0 },
|
charge: {metals: 2, colours: 3, stains: +P(0.05), patterns: 0},
|
||||||
metals: {argent: 3, or: 2},
|
metals: {argent: 3, or: 2},
|
||||||
colours: {gules: 5, azure: 4, sable: 3, purpure: 3, vert: 2},
|
colours: {gules: 5, azure: 4, sable: 3, purpure: 3, vert: 2},
|
||||||
stains: {murrey: 1, sanguine: 1, tenné: 1},
|
stains: {murrey: 1, sanguine: 1, tenné: 1},
|
||||||
patterns: {
|
patterns: {
|
||||||
semy: 8, ermine: 6,
|
semy: 8,
|
||||||
vair: 4, counterVair: 1, vairInPale: 1, vairEnPointe: 2, vairAncien: 2,
|
ermine: 6,
|
||||||
potent: 2, counterPotent: 1, potentInPale: 1, potentEnPointe: 1,
|
vair: 4,
|
||||||
chequy: 8, lozengy: 5, fusily: 2, pally: 8, barry: 10, gemelles: 1,
|
counterVair: 1,
|
||||||
bendy: 8, bendySinister: 4, palyBendy: 2, barryBendy: 1,
|
vairInPale: 1,
|
||||||
pappellony: 2, pappellony2: 3, scaly: 1, plumetty: 1,
|
vairEnPointe: 2,
|
||||||
masoned: 6, fretty: 3, grillage: 1, chainy: 1, maily: 2, honeycombed: 1 }
|
vairAncien: 2,
|
||||||
|
potent: 2,
|
||||||
|
counterPotent: 1,
|
||||||
|
potentInPale: 1,
|
||||||
|
potentEnPointe: 1,
|
||||||
|
chequy: 8,
|
||||||
|
lozengy: 5,
|
||||||
|
fusily: 2,
|
||||||
|
pally: 8,
|
||||||
|
barry: 10,
|
||||||
|
gemelles: 1,
|
||||||
|
bendy: 8,
|
||||||
|
bendySinister: 4,
|
||||||
|
palyBendy: 2,
|
||||||
|
barryBendy: 1,
|
||||||
|
pappellony: 2,
|
||||||
|
pappellony2: 3,
|
||||||
|
scaly: 1,
|
||||||
|
plumetty: 1,
|
||||||
|
masoned: 6,
|
||||||
|
fretty: 3,
|
||||||
|
grillage: 1,
|
||||||
|
chainy: 1,
|
||||||
|
maily: 2,
|
||||||
|
honeycombed: 1
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const charges = {
|
const charges = {
|
||||||
// categories selection
|
// categories selection
|
||||||
|
|
@ -28,21 +50,102 @@
|
||||||
semy: {conventional: 12, crosses: 3, plants: 1},
|
semy: {conventional: 12, crosses: 3, plants: 1},
|
||||||
// generic categories
|
// generic categories
|
||||||
conventional: {
|
conventional: {
|
||||||
lozenge: 2, fusil: 4, mascle: 4, rustre: 2, lozengeFaceted: 3, lozengePloye: 1, roundel: 4, roundel2: 3, annulet: 4,
|
lozenge: 2,
|
||||||
mullet: 5, mulletPierced: 1, mulletFaceted: 1, mullet4: 3, mullet6: 4, mullet6Pierced: 1, mullet6Faceted: 1, mullet7: 1, mullet8: 1, mullet10: 1,
|
fusil: 4,
|
||||||
estoile: 1, compassRose: 1, billet: 5, delf: 0, triangle: 3, trianglePierced: 1, goutte: 4, heart: 4, pique: 2, carreau: 1, trefle: 2,
|
mascle: 4,
|
||||||
fleurDeLis: 6, sun: 3, sunInSplendour: 1, crescent: 5, fountain: 1
|
rustre: 2,
|
||||||
|
lozengeFaceted: 3,
|
||||||
|
lozengePloye: 1,
|
||||||
|
roundel: 4,
|
||||||
|
roundel2: 3,
|
||||||
|
annulet: 4,
|
||||||
|
mullet: 5,
|
||||||
|
mulletPierced: 1,
|
||||||
|
mulletFaceted: 1,
|
||||||
|
mullet4: 3,
|
||||||
|
mullet6: 4,
|
||||||
|
mullet6Pierced: 1,
|
||||||
|
mullet6Faceted: 1,
|
||||||
|
mullet7: 1,
|
||||||
|
mullet8: 1,
|
||||||
|
mullet10: 1,
|
||||||
|
estoile: 1,
|
||||||
|
compassRose: 1,
|
||||||
|
billet: 5,
|
||||||
|
delf: 0,
|
||||||
|
triangle: 3,
|
||||||
|
trianglePierced: 1,
|
||||||
|
goutte: 4,
|
||||||
|
heart: 4,
|
||||||
|
pique: 2,
|
||||||
|
carreau: 1,
|
||||||
|
trefle: 2,
|
||||||
|
fleurDeLis: 6,
|
||||||
|
sun: 3,
|
||||||
|
sunInSplendour: 1,
|
||||||
|
crescent: 5,
|
||||||
|
fountain: 1
|
||||||
},
|
},
|
||||||
crosses: {
|
crosses: {
|
||||||
crossHummetty: 15, crossVoided: 1, crossPattee: 2, crossPatteeAlisee: 1, crossFormee: 1, crossFormee2: 2, crossPotent: 2, crossJerusalem:1,
|
crossHummetty: 15,
|
||||||
crosslet: 1, crossClechy: 3, crossBottony: 1, crossFleury: 3, crossPatonce: 1, crossPommy: 1, crossGamma: 1, crossArrowed: 1, crossFitchy: 1,
|
crossVoided: 1,
|
||||||
crossCercelee: 1, crossMoline: 2, crossFourchy: 1, crossAvellane: 1, crossErminee: 1, crossBiparted: 1, crossMaltese: 3, crossTemplar: 2,
|
crossPattee: 2,
|
||||||
crossCeltic: 1, crossCeltic2: 1, crossTriquetra: 1, crossCarolingian: 1, crossOccitan: 1, crossSaltire: 3, crossBurgundy: 1,
|
crossPatteeAlisee: 1,
|
||||||
crossLatin: 3, crossPatriarchal: 1, crossOrthodox: 1, crossCalvary: 1, crossDouble: 1, crossTau: 1, crossSantiago: 1, crossAnkh: 1
|
crossFormee: 1,
|
||||||
|
crossFormee2: 2,
|
||||||
|
crossPotent: 2,
|
||||||
|
crossJerusalem: 1,
|
||||||
|
crosslet: 1,
|
||||||
|
crossClechy: 3,
|
||||||
|
crossBottony: 1,
|
||||||
|
crossFleury: 3,
|
||||||
|
crossPatonce: 1,
|
||||||
|
crossPommy: 1,
|
||||||
|
crossGamma: 1,
|
||||||
|
crossArrowed: 1,
|
||||||
|
crossFitchy: 1,
|
||||||
|
crossCercelee: 1,
|
||||||
|
crossMoline: 2,
|
||||||
|
crossFourchy: 1,
|
||||||
|
crossAvellane: 1,
|
||||||
|
crossErminee: 1,
|
||||||
|
crossBiparted: 1,
|
||||||
|
crossMaltese: 3,
|
||||||
|
crossTemplar: 2,
|
||||||
|
crossCeltic: 1,
|
||||||
|
crossCeltic2: 1,
|
||||||
|
crossTriquetra: 1,
|
||||||
|
crossCarolingian: 1,
|
||||||
|
crossOccitan: 1,
|
||||||
|
crossSaltire: 3,
|
||||||
|
crossBurgundy: 1,
|
||||||
|
crossLatin: 3,
|
||||||
|
crossPatriarchal: 1,
|
||||||
|
crossOrthodox: 1,
|
||||||
|
crossCalvary: 1,
|
||||||
|
crossDouble: 1,
|
||||||
|
crossTau: 1,
|
||||||
|
crossSantiago: 1,
|
||||||
|
crossAnkh: 1
|
||||||
},
|
},
|
||||||
animals: {
|
animals: {
|
||||||
lionRampant: 5, lionPassant: 2, lionPassantGuardant: 1, wolfRampant: 1, wolfPassant: 1, wolfStatant: 1, greyhoundCourant: 1, boarRampant: 1,
|
lionRampant: 5,
|
||||||
horseRampant: 2, horseSalient: 1, bearRampant: 2, bearPassant: 1, bullPassant: 1, goat: 1, lamb: 1, elephant: 1, camel: 1
|
lionPassant: 2,
|
||||||
|
lionPassantGuardant: 1,
|
||||||
|
wolfRampant: 1,
|
||||||
|
wolfPassant: 1,
|
||||||
|
wolfStatant: 1,
|
||||||
|
greyhoundCourant: 1,
|
||||||
|
boarRampant: 1,
|
||||||
|
horseRampant: 2,
|
||||||
|
horseSalient: 1,
|
||||||
|
bearRampant: 2,
|
||||||
|
bearPassant: 1,
|
||||||
|
bullPassant: 1,
|
||||||
|
goat: 1,
|
||||||
|
lamb: 1,
|
||||||
|
elephant: 1,
|
||||||
|
camel: 1
|
||||||
},
|
},
|
||||||
animalHeads: {wolfHeadErased: 1, bullHeadCaboshed: 1, deerHeadCaboshed: 1, lionHeadCaboshed: 2},
|
animalHeads: {wolfHeadErased: 1, bullHeadCaboshed: 1, deerHeadCaboshed: 1, lionHeadCaboshed: 2},
|
||||||
fantastic: {dragonPassant: 2, dragonRampant: 2, wyvern: 1, wyvernWithWingsDisplayed: 1, griffinPassant: 1, griffinRampant: 1, eagleTwoHeards: 2, unicornRampant: 1, pegasus: 1, serpent: 1},
|
fantastic: {dragonPassant: 2, dragonRampant: 2, wyvern: 1, wyvernWithWingsDisplayed: 1, griffinPassant: 1, griffinRampant: 1, eagleTwoHeards: 2, unicornRampant: 1, pegasus: 1, serpent: 1},
|
||||||
|
|
@ -54,8 +157,29 @@
|
||||||
people: {cavalier: 3, monk: 1, angel: 2},
|
people: {cavalier: 3, monk: 1, angel: 2},
|
||||||
architecture: {tower: 1, castle: 1},
|
architecture: {tower: 1, castle: 1},
|
||||||
miscellaneous: {
|
miscellaneous: {
|
||||||
crown: 3, orb: 1, chalice: 1, key: 1, buckle: 1, bugleHorn: 1, bugleHorn2: 1, bell: 2, pot: 1, bucket: 1, horseshoe: 3,
|
crown: 3,
|
||||||
attire: 1, stagsAttires: 1, ramsHorn: 1, cowHorns: 2, wing: 1, wingSword: 1, lute: 1, harp: 1, wheel: 2, crosier: 1, fasces: 1, log: 1
|
orb: 1,
|
||||||
|
chalice: 1,
|
||||||
|
key: 1,
|
||||||
|
buckle: 1,
|
||||||
|
bugleHorn: 1,
|
||||||
|
bugleHorn2: 1,
|
||||||
|
bell: 2,
|
||||||
|
pot: 1,
|
||||||
|
bucket: 1,
|
||||||
|
horseshoe: 3,
|
||||||
|
attire: 1,
|
||||||
|
stagsAttires: 1,
|
||||||
|
ramsHorn: 1,
|
||||||
|
cowHorns: 2,
|
||||||
|
wing: 1,
|
||||||
|
wingSword: 1,
|
||||||
|
lute: 1,
|
||||||
|
harp: 1,
|
||||||
|
wheel: 2,
|
||||||
|
crosier: 1,
|
||||||
|
fasces: 1,
|
||||||
|
log: 1
|
||||||
},
|
},
|
||||||
// selection based on culture type:
|
// selection based on culture type:
|
||||||
Naval: {anchor: 3, boat: 1, lymphad: 2, armillarySphere: 1, escallop: 1, dolphin: 1},
|
Naval: {anchor: 3, boat: 1, lymphad: 2, armillarySphere: 1, escallop: 1, dolphin: 1},
|
||||||
|
|
@ -70,17 +194,87 @@
|
||||||
Сathedra: {chalice: 1, orb: 1, crosier: 2, lamb: 1, monk: 2, angel: 3, crossLatin: 2, crossPatriarchal: 1, crossOrthodox: 1, crossCalvary: 1},
|
Сathedra: {chalice: 1, orb: 1, crosier: 2, lamb: 1, monk: 2, angel: 3, crossLatin: 2, crossPatriarchal: 1, crossOrthodox: 1, crossCalvary: 1},
|
||||||
// specific cases
|
// specific cases
|
||||||
natural: {fountain: "azure", garb: "or", raven: "sable"}, // charges to mainly use predefined colours
|
natural: {fountain: "azure", garb: "or", raven: "sable"}, // charges to mainly use predefined colours
|
||||||
sinister: [ // charges that can be sinister
|
sinister: [
|
||||||
"crossGamma", "lionRampant", "lionPassant", "wolfRampant", "wolfPassant", "wolfStatant", "wolfHeadErased", "greyhoundСourant", "boarRampant",
|
// charges that can be sinister
|
||||||
"horseRampant", "horseSalient", "bullPassant", "bearRampant", "bearPassant", "goat", "lamb", "elephant", "eagle", "raven", "cock", "parrot",
|
"crossGamma",
|
||||||
"swan", "swanErased", "heron", "pike", "dragonPassant", "dragonRampant", "wyvern", "wyvernWithWingsDisplayed", "griffinPassant", "griffinRampant",
|
"lionRampant",
|
||||||
"unicornRampant", "pegasus", "serpent", "hatchet", "lochaberAxe", "hand", "wing", "wingSword", "lute", "harp", "bow", "head", "headWreathed",
|
"lionPassant",
|
||||||
"knight", "lymphad", "log", "crosier", "dolphin", "sabre", "monk", "owl", "axe", "camel", "fasces", "lionPassantGuardant", "helmet"],
|
"wolfRampant",
|
||||||
reversed: [ // charges that can be reversed
|
"wolfPassant",
|
||||||
"goutte", "mullet", "mullet7", "crescent", "crossTau", "cancer", "sword", "sabresCrossed", "hand",
|
"wolfStatant",
|
||||||
"horseshoe", "bowWithArrow", "arrow", "arrowsSheaf", "rake", "crossTriquetra", "crossLatin", "crossTau"
|
"wolfHeadErased",
|
||||||
|
"greyhoundСourant",
|
||||||
|
"boarRampant",
|
||||||
|
"horseRampant",
|
||||||
|
"horseSalient",
|
||||||
|
"bullPassant",
|
||||||
|
"bearRampant",
|
||||||
|
"bearPassant",
|
||||||
|
"goat",
|
||||||
|
"lamb",
|
||||||
|
"elephant",
|
||||||
|
"eagle",
|
||||||
|
"raven",
|
||||||
|
"cock",
|
||||||
|
"parrot",
|
||||||
|
"swan",
|
||||||
|
"swanErased",
|
||||||
|
"heron",
|
||||||
|
"pike",
|
||||||
|
"dragonPassant",
|
||||||
|
"dragonRampant",
|
||||||
|
"wyvern",
|
||||||
|
"wyvernWithWingsDisplayed",
|
||||||
|
"griffinPassant",
|
||||||
|
"griffinRampant",
|
||||||
|
"unicornRampant",
|
||||||
|
"pegasus",
|
||||||
|
"serpent",
|
||||||
|
"hatchet",
|
||||||
|
"lochaberAxe",
|
||||||
|
"hand",
|
||||||
|
"wing",
|
||||||
|
"wingSword",
|
||||||
|
"lute",
|
||||||
|
"harp",
|
||||||
|
"bow",
|
||||||
|
"head",
|
||||||
|
"headWreathed",
|
||||||
|
"knight",
|
||||||
|
"lymphad",
|
||||||
|
"log",
|
||||||
|
"crosier",
|
||||||
|
"dolphin",
|
||||||
|
"sabre",
|
||||||
|
"monk",
|
||||||
|
"owl",
|
||||||
|
"axe",
|
||||||
|
"camel",
|
||||||
|
"fasces",
|
||||||
|
"lionPassantGuardant",
|
||||||
|
"helmet"
|
||||||
|
],
|
||||||
|
reversed: [
|
||||||
|
// charges that can be reversed
|
||||||
|
"goutte",
|
||||||
|
"mullet",
|
||||||
|
"mullet7",
|
||||||
|
"crescent",
|
||||||
|
"crossTau",
|
||||||
|
"cancer",
|
||||||
|
"sword",
|
||||||
|
"sabresCrossed",
|
||||||
|
"hand",
|
||||||
|
"horseshoe",
|
||||||
|
"bowWithArrow",
|
||||||
|
"arrow",
|
||||||
|
"arrowsSheaf",
|
||||||
|
"rake",
|
||||||
|
"crossTriquetra",
|
||||||
|
"crossLatin",
|
||||||
|
"crossTau"
|
||||||
]
|
]
|
||||||
}
|
};
|
||||||
|
|
||||||
const positions = {
|
const positions = {
|
||||||
conventional: {e: 20, abcdefgzi: 3, beh: 3, behdf: 2, acegi: 1, kn: 3, bhdf: 1, jeo: 1, abc: 3, jln: 6, jlh: 3, kmo: 2, jleh: 1, def: 3, abcpqh: 4, ABCDEFGHIJKL: 1},
|
conventional: {e: 20, abcdefgzi: 3, beh: 3, behdf: 2, acegi: 1, kn: 3, bhdf: 1, jeo: 1, abc: 3, jln: 6, jlh: 3, kmo: 2, jleh: 1, def: 3, abcpqh: 4, ABCDEFGHIJKL: 1},
|
||||||
|
|
@ -175,10 +369,39 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
const lines = {
|
const lines = {
|
||||||
straight: 50, wavy: 8, engrailed: 4, invecked: 3, rayonne: 3, embattled: 1, raguly: 1, urdy: 1, dancetty: 1, indented: 2,
|
straight: 50,
|
||||||
dentilly: 1, bevilled: 1, angled: 1, flechy: 1, barby: 1, enclavy: 1, escartely: 1, arched: 2, archedReversed: 1, nowy: 1, nowyReversed: 1,
|
wavy: 8,
|
||||||
embattledGhibellin: 1, embattledNotched: 1, embattledGrady: 1, dovetailedIndented: 1, dovetailed: 1,
|
engrailed: 4,
|
||||||
potenty: 1, potentyDexter: 1, potentySinister: 1, nebuly: 2, seaWaves: 1, dragonTeeth: 1, firTrees: 1
|
invecked: 3,
|
||||||
|
rayonne: 3,
|
||||||
|
embattled: 1,
|
||||||
|
raguly: 1,
|
||||||
|
urdy: 1,
|
||||||
|
dancetty: 1,
|
||||||
|
indented: 2,
|
||||||
|
dentilly: 1,
|
||||||
|
bevilled: 1,
|
||||||
|
angled: 1,
|
||||||
|
flechy: 1,
|
||||||
|
barby: 1,
|
||||||
|
enclavy: 1,
|
||||||
|
escartely: 1,
|
||||||
|
arched: 2,
|
||||||
|
archedReversed: 1,
|
||||||
|
nowy: 1,
|
||||||
|
nowyReversed: 1,
|
||||||
|
embattledGhibellin: 1,
|
||||||
|
embattledNotched: 1,
|
||||||
|
embattledGrady: 1,
|
||||||
|
dovetailedIndented: 1,
|
||||||
|
dovetailed: 1,
|
||||||
|
potenty: 1,
|
||||||
|
potentyDexter: 1,
|
||||||
|
potentySinister: 1,
|
||||||
|
nebuly: 2,
|
||||||
|
seaWaves: 1,
|
||||||
|
dragonTeeth: 1,
|
||||||
|
firTrees: 1
|
||||||
};
|
};
|
||||||
|
|
||||||
const divisions = {
|
const divisions = {
|
||||||
|
|
@ -195,13 +418,43 @@
|
||||||
|
|
||||||
const ordinaries = {
|
const ordinaries = {
|
||||||
lined: {
|
lined: {
|
||||||
pale: 7, fess: 5, bend: 3, bendSinister: 2, chief: 5, bar: 2, gemelle: 1, fessCotissed: 1, fessDoubleCotissed: 1,
|
pale: 7,
|
||||||
bendlet: 2, bendletSinister: 1, terrace: 3, cross: 6, crossParted: 1, saltire: 2, saltireParted: 1
|
fess: 5,
|
||||||
|
bend: 3,
|
||||||
|
bendSinister: 2,
|
||||||
|
chief: 5,
|
||||||
|
bar: 2,
|
||||||
|
gemelle: 1,
|
||||||
|
fessCotissed: 1,
|
||||||
|
fessDoubleCotissed: 1,
|
||||||
|
bendlet: 2,
|
||||||
|
bendletSinister: 1,
|
||||||
|
terrace: 3,
|
||||||
|
cross: 6,
|
||||||
|
crossParted: 1,
|
||||||
|
saltire: 2,
|
||||||
|
saltireParted: 1
|
||||||
},
|
},
|
||||||
straight: {
|
straight: {
|
||||||
bordure: 8, orle: 4, mount: 1, point: 2, flaunches: 1, gore: 1,
|
bordure: 8,
|
||||||
gyron: 1, quarter: 1, canton: 2, pall: 3, pallReversed: 2, chevron: 4, chevronReversed: 3,
|
orle: 4,
|
||||||
pile: 2, pileInBend: 2, pileInBendSinister: 1, piles: 1, pilesInPoint: 2, label: 1
|
mount: 1,
|
||||||
|
point: 2,
|
||||||
|
flaunches: 1,
|
||||||
|
gore: 1,
|
||||||
|
gyron: 1,
|
||||||
|
quarter: 1,
|
||||||
|
canton: 2,
|
||||||
|
pall: 3,
|
||||||
|
pallReversed: 2,
|
||||||
|
chevron: 4,
|
||||||
|
chevronReversed: 3,
|
||||||
|
pile: 2,
|
||||||
|
pileInBend: 2,
|
||||||
|
pileInBendSinister: 1,
|
||||||
|
piles: 1,
|
||||||
|
pilesInPoint: 2,
|
||||||
|
label: 1
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -215,7 +468,7 @@
|
||||||
simple: {round: 12, oval: 6, vesicaPiscis: 1, square: 1, diamond: 2, no: 0},
|
simple: {round: 12, oval: 6, vesicaPiscis: 1, square: 1, diamond: 2, no: 0},
|
||||||
fantasy: {fantasy1: 2, fantasy2: 2, fantasy3: 1, fantasy4: 1, fantasy5: 3},
|
fantasy: {fantasy1: 2, fantasy2: 2, fantasy3: 1, fantasy4: 1, fantasy5: 3},
|
||||||
middleEarth: {noldor: 1, gondor: 1, easterling: 1, erebor: 1, ironHills: 1, urukHai: 1, moriaOrc: 1}
|
middleEarth: {noldor: 1, gondor: 1, easterling: 1, erebor: 1, ironHills: 1, urukHai: 1, moriaOrc: 1}
|
||||||
}
|
};
|
||||||
|
|
||||||
const generate = function (parent, kinship, dominion, type) {
|
const generate = function (parent, kinship, dominion, type) {
|
||||||
if (!parent || parent === "custom") {
|
if (!parent || parent === "custom") {
|
||||||
|
|
@ -223,52 +476,53 @@
|
||||||
kinship = 0;
|
kinship = 0;
|
||||||
dominion = 0;
|
dominion = 0;
|
||||||
}
|
}
|
||||||
let usedPattern = null, usedTinctures = [];
|
let usedPattern = null,
|
||||||
|
usedTinctures = [];
|
||||||
|
|
||||||
const t1 = P(kinship) ? parent.t1 : getTincture("field");
|
const t1 = P(kinship) ? parent.t1 : getTincture("field");
|
||||||
if (t1.includes("-")) usedPattern = t1;
|
if (t1.includes("-")) usedPattern = t1;
|
||||||
const coa = {t1};
|
const coa = {t1};
|
||||||
|
|
||||||
let charge = P(usedPattern ? .5 : .93) ? true : false; // 80% for charge
|
let charge = P(usedPattern ? 0.5 : 0.93) ? true : false; // 80% for charge
|
||||||
const linedOrdinary = charge && P(.3) || P(.5) ? parent?.ordinaries && P(kinship) ? parent.ordinaries[0].ordinary : rw(ordinaries.lined) : null;
|
const linedOrdinary = (charge && P(0.3)) || P(0.5) ? (parent?.ordinaries && P(kinship) ? parent.ordinaries[0].ordinary : rw(ordinaries.lined)) : null;
|
||||||
const ordinary = !charge && P(.65) || P(.3) ? linedOrdinary ? linedOrdinary : rw(ordinaries.straight) : null; // 36% for ordinary
|
const ordinary = (!charge && P(0.65)) || P(0.3) ? (linedOrdinary ? linedOrdinary : rw(ordinaries.straight)) : null; // 36% for ordinary
|
||||||
const rareDivided = ["chief", "terrace", "chevron", "quarter", "flaunches"].includes(ordinary);
|
const rareDivided = ["chief", "terrace", "chevron", "quarter", "flaunches"].includes(ordinary);
|
||||||
const divisioned = rareDivided ? P(.03) : charge && ordinary ? P(.03) : charge ? P(.3) : ordinary ? P(.7) : P(.995); // 33% for division
|
const divisioned = rareDivided ? P(0.03) : charge && ordinary ? P(0.03) : charge ? P(0.3) : ordinary ? P(0.7) : P(0.995); // 33% for division
|
||||||
const division = divisioned ? parent?.division && P(kinship - .1) ? parent.division.division : rw(divisions.variants) : null;
|
const division = divisioned ? (parent?.division && P(kinship - 0.1) ? parent.division.division : rw(divisions.variants)) : null;
|
||||||
if (charge) charge =
|
if (charge) charge = parent?.charges && P(kinship - 0.1) ? parent.charges[0].charge : type && type !== "Generic" && P(0.2) ? rw(charges[type]) : selectCharge();
|
||||||
parent?.charges && P(kinship - .1) ? parent.charges[0].charge :
|
|
||||||
type && type !== "Generic" && P(.2) ? rw(charges[type]) :
|
|
||||||
selectCharge();
|
|
||||||
|
|
||||||
if (division) {
|
if (division) {
|
||||||
const t = getTincture("division", usedTinctures, P(.98) ? coa.t1 : null);
|
const t = getTincture("division", usedTinctures, P(0.98) ? coa.t1 : null);
|
||||||
coa.division = {division, t};
|
coa.division = {division, t};
|
||||||
if (divisions[division]) coa.division.line = usedPattern || (ordinary && P(.7)) ? "straight" : rw(divisions[division]);
|
if (divisions[division]) coa.division.line = usedPattern || (ordinary && P(0.7)) ? "straight" : rw(divisions[division]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ordinary) {
|
if (ordinary) {
|
||||||
coa.ordinaries = [{ordinary, t: getTincture("charge", usedTinctures, coa.t1)}];
|
coa.ordinaries = [{ordinary, t: getTincture("charge", usedTinctures, coa.t1)}];
|
||||||
if (linedOrdinary) coa.ordinaries[0].line = usedPattern || (division && P(.7)) ? "straight" : rw(lines);
|
if (linedOrdinary) coa.ordinaries[0].line = usedPattern || (division && P(0.7)) ? "straight" : rw(lines);
|
||||||
if (division && !charge && !usedPattern && P(.5) && ordinary !== "bordure" && ordinary !== "orle") {
|
if (division && !charge && !usedPattern && P(0.5) && ordinary !== "bordure" && ordinary !== "orle") {
|
||||||
if (P(.8)) coa.ordinaries[0].divided = "counter"; // 40%
|
if (P(0.8)) coa.ordinaries[0].divided = "counter";
|
||||||
else if (P(.6)) coa.ordinaries[0].divided = "field"; // 6%
|
// 40%
|
||||||
|
else if (P(0.6)) coa.ordinaries[0].divided = "field";
|
||||||
|
// 6%
|
||||||
else coa.ordinaries[0].divided = "division"; // 4%
|
else coa.ordinaries[0].divided = "division"; // 4%
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (charge) {
|
if (charge) {
|
||||||
let p = "e", t = "gules";
|
let p = "e",
|
||||||
|
t = "gules";
|
||||||
const ordinaryT = coa.ordinaries ? coa.ordinaries[0].t : null;
|
const ordinaryT = coa.ordinaries ? coa.ordinaries[0].t : null;
|
||||||
if (positions.ordinariesOn[ordinary] && P(.8)) {
|
if (positions.ordinariesOn[ordinary] && P(0.8)) {
|
||||||
// place charge over ordinary (use tincture of field type)
|
// place charge over ordinary (use tincture of field type)
|
||||||
p = rw(positions.ordinariesOn[ordinary]);
|
p = rw(positions.ordinariesOn[ordinary]);
|
||||||
while (charges.natural[charge] === ordinaryT) charge = selectCharge();
|
while (charges.natural[charge] === ordinaryT) charge = selectCharge();
|
||||||
t = !usedPattern && P(.3) ? coa.t1 : getTincture("charge", [], ordinaryT);
|
t = !usedPattern && P(0.3) ? coa.t1 : getTincture("charge", [], ordinaryT);
|
||||||
} else if (positions.ordinariesOff[ordinary] && P(.95)) {
|
} else if (positions.ordinariesOff[ordinary] && P(0.95)) {
|
||||||
// place charge out of ordinary (use tincture of ordinary type)
|
// place charge out of ordinary (use tincture of ordinary type)
|
||||||
p = rw(positions.ordinariesOff[ordinary]);
|
p = rw(positions.ordinariesOff[ordinary]);
|
||||||
while (charges.natural[charge] === coa.t1) charge = selectCharge();
|
while (charges.natural[charge] === coa.t1) charge = selectCharge();
|
||||||
t = !usedPattern && P(.3) ? ordinaryT : getTincture("charge", usedTinctures, coa.t1);
|
t = !usedPattern && P(0.3) ? ordinaryT : getTincture("charge", usedTinctures, coa.t1);
|
||||||
} else if (positions.divisions[division]) {
|
} else if (positions.divisions[division]) {
|
||||||
// place charge in fields made by division
|
// place charge in fields made by division
|
||||||
p = rw(positions.divisions[division]);
|
p = rw(positions.divisions[division]);
|
||||||
|
|
@ -289,43 +543,41 @@
|
||||||
if (charges.natural[charge]) t = charges.natural[charge]; // natural tincture
|
if (charges.natural[charge]) t = charges.natural[charge]; // natural tincture
|
||||||
coa.charges = [{charge, t, p}];
|
coa.charges = [{charge, t, p}];
|
||||||
|
|
||||||
if (p === "ABCDEFGHIKL" && P(.95)) {
|
if (p === "ABCDEFGHIKL" && P(0.95)) {
|
||||||
// add central charge if charge is in bordure
|
// add central charge if charge is in bordure
|
||||||
coa.charges[0].charge = rw(charges.conventional);
|
coa.charges[0].charge = rw(charges.conventional);
|
||||||
const charge = selectCharge(charges.single);
|
const charge = selectCharge(charges.single);
|
||||||
const t = getTincture("charge", usedTinctures, coa.t1);
|
const t = getTincture("charge", usedTinctures, coa.t1);
|
||||||
coa.charges.push({charge, t, p: "e"});
|
coa.charges.push({charge, t, p: "e"});
|
||||||
} else if (P(.8) && charge === "inescutcheon") {
|
} else if (P(0.8) && charge === "inescutcheon") {
|
||||||
// add charge to inescutcheon
|
// add charge to inescutcheon
|
||||||
const charge = selectCharge(charges.types);
|
const charge = selectCharge(charges.types);
|
||||||
const t2 = getTincture("charge", [], t);
|
const t2 = getTincture("charge", [], t);
|
||||||
coa.charges.push({charge, t: t2, p, size:.5});
|
coa.charges.push({charge, t: t2, p, size: 0.5});
|
||||||
} else if (division && !ordinary) {
|
} else if (division && !ordinary) {
|
||||||
const allowCounter = !usedPattern && (!coa.line || coa.line === "straight");
|
const allowCounter = !usedPattern && (!coa.line || coa.line === "straight");
|
||||||
|
|
||||||
// dimidiation: second charge at division basic positons
|
// dimidiation: second charge at division basic positons
|
||||||
if (P(.3) && ["perPale", "perFess"].includes(division) && coa.line === "straight") {
|
if (P(0.3) && ["perPale", "perFess"].includes(division) && coa.line === "straight") {
|
||||||
coa.charges[0].divided = "field";
|
coa.charges[0].divided = "field";
|
||||||
if (P(.95)) {
|
if (P(0.95)) {
|
||||||
const p2 = p === "e" || P(.5) ? "e" : rw(positions.divisions[division]);
|
const p2 = p === "e" || P(0.5) ? "e" : rw(positions.divisions[division]);
|
||||||
const charge = selectCharge(charges.single);
|
const charge = selectCharge(charges.single);
|
||||||
const t = getTincture("charge", usedTinctures, coa.division.t);
|
const t = getTincture("charge", usedTinctures, coa.division.t);
|
||||||
coa.charges.push({charge, t, p: p2, divided: "division"});
|
coa.charges.push({charge, t, p: p2, divided: "division"});
|
||||||
}
|
}
|
||||||
}
|
} else if (allowCounter && P(0.4)) coa.charges[0].divided = "counter";
|
||||||
else if (allowCounter && P(.4)) coa.charges[0].divided = "counter"; // counterchanged, 40%
|
// counterchanged, 40%
|
||||||
else if (["perPale", "perFess", "perBend", "perBendSinister"].includes(division) && P(.8)) { // place 2 charges in division standard positions
|
else if (["perPale", "perFess", "perBend", "perBendSinister"].includes(division) && P(0.8)) {
|
||||||
const [p1, p2] = division === "perPale" ? ["p", "q"] :
|
// place 2 charges in division standard positions
|
||||||
division === "perFess" ? ["k", "n"] :
|
const [p1, p2] = division === "perPale" ? ["p", "q"] : division === "perFess" ? ["k", "n"] : division === "perBend" ? ["l", "m"] : ["j", "o"]; // perBendSinister
|
||||||
division === "perBend" ? ["l", "m"] :
|
|
||||||
["j", "o"]; // perBendSinister
|
|
||||||
coa.charges[0].p = p1;
|
coa.charges[0].p = p1;
|
||||||
|
|
||||||
const charge = selectCharge(charges.single);
|
const charge = selectCharge(charges.single);
|
||||||
const t = getTincture("charge", usedTinctures, coa.division.t);
|
const t = getTincture("charge", usedTinctures, coa.division.t);
|
||||||
coa.charges.push({charge, t, p: p2});
|
coa.charges.push({charge, t, p: p2});
|
||||||
}
|
} else if (["perCross", "perSaltire"].includes(division) && P(0.5)) {
|
||||||
else if (["perCross", "perSaltire"].includes(division) && P(.5)) { // place 4 charges in division standard positions
|
// place 4 charges in division standard positions
|
||||||
const [p1, p2, p3, p4] = division === "perCross" ? ["j", "l", "m", "o"] : ["b", "d", "f", "h"];
|
const [p1, p2, p3, p4] = division === "perCross" ? ["j", "l", "m", "o"] : ["b", "d", "f", "h"];
|
||||||
coa.charges[0].p = p1;
|
coa.charges[0].p = p1;
|
||||||
|
|
||||||
|
|
@ -338,8 +590,7 @@
|
||||||
const c4 = selectCharge(charges.single);
|
const c4 = selectCharge(charges.single);
|
||||||
const t4 = getTincture("charge", [], coa.t1);
|
const t4 = getTincture("charge", [], coa.t1);
|
||||||
coa.charges.push({charge: c2, t: t2, p: p2}, {charge: c3, t: t3, p: p3}, {charge: c4, t: t4, p: p4});
|
coa.charges.push({charge: c2, t: t2, p: p2}, {charge: c3, t: t3, p: p3}, {charge: c4, t: t4, p: p4});
|
||||||
}
|
} else if (allowCounter && p.length > 1) coa.charges[0].divided = "counter"; // counterchanged, 40%
|
||||||
else if (allowCounter && p.length > 1) coa.charges[0].divided = "counter"; // counterchanged, 40%
|
|
||||||
}
|
}
|
||||||
|
|
||||||
coa.charges.forEach(c => defineChargeAttributes(c));
|
coa.charges.forEach(c => defineChargeAttributes(c));
|
||||||
|
|
@ -351,8 +602,8 @@
|
||||||
c.p = [...new Set(c.p)].join("");
|
c.p = [...new Set(c.p)].join("");
|
||||||
|
|
||||||
// define orientation
|
// define orientation
|
||||||
if (P(.02) && charges.sinister.includes(c.charge)) c.sinister = 1;
|
if (P(0.02) && charges.sinister.includes(c.charge)) c.sinister = 1;
|
||||||
if (P(.02) && charges.reversed.includes(c.charge)) c.reversed = 1;
|
if (P(0.02) && charges.reversed.includes(c.charge)) c.reversed = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -380,7 +631,7 @@
|
||||||
if (!coa.charges) coa.charges = [];
|
if (!coa.charges) coa.charges = [];
|
||||||
coa.charges.push({charge, t: t2, p: "y", size: 0.5});
|
coa.charges.push({charge, t: t2, p: "y", size: 0.5});
|
||||||
|
|
||||||
coa.ordinaries ? coa.ordinaries.push(canton) : coa.ordinaries = [canton];
|
coa.ordinaries ? coa.ordinaries.push(canton) : (coa.ordinaries = [canton]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectCharge(set) {
|
function selectCharge(set) {
|
||||||
|
|
@ -390,14 +641,16 @@
|
||||||
|
|
||||||
// select tincture: element type (field, division, charge), used field tinctures, field type to follow RoT
|
// select tincture: element type (field, division, charge), used field tinctures, field type to follow RoT
|
||||||
function getTincture(element, fields = [], RoT) {
|
function getTincture(element, fields = [], RoT) {
|
||||||
const base = RoT ? RoT.includes("-") ? RoT.split("-")[1] : RoT : null;
|
const base = RoT ? (RoT.includes("-") ? RoT.split("-")[1] : RoT) : null;
|
||||||
|
|
||||||
let type = rw(tinctures[element]); // metals, colours, stains, patterns
|
let type = rw(tinctures[element]); // metals, colours, stains, patterns
|
||||||
if (RoT && type !== "patterns") type = getType(base) === "metals" ? "colours" : "metals"; // follow RoT
|
if (RoT && type !== "patterns") type = getType(base) === "metals" ? "colours" : "metals"; // follow RoT
|
||||||
if (type === "metals" && fields.includes("or") && fields.includes("argent")) type = "colours"; // exclude metals overuse
|
if (type === "metals" && fields.includes("or") && fields.includes("argent")) type = "colours"; // exclude metals overuse
|
||||||
let tincture = rw(tinctures[type]);
|
let tincture = rw(tinctures[type]);
|
||||||
|
|
||||||
while (tincture === base || fields.includes(tincture)) {tincture = rw(tinctures[type]);} // follow RoT
|
while (tincture === base || fields.includes(tincture)) {
|
||||||
|
tincture = rw(tinctures[type]);
|
||||||
|
} // follow RoT
|
||||||
|
|
||||||
if (type !== "patterns" && element !== "charge") usedTinctures.push(tincture); // add field tincture
|
if (type !== "patterns" && element !== "charge") usedTinctures.push(tincture); // add field tincture
|
||||||
|
|
||||||
|
|
@ -425,39 +678,60 @@
|
||||||
if (Object.keys(tinctures.stains).includes(tincture)) return "stains";
|
if (Object.keys(tinctures.stains).includes(tincture)) return "stains";
|
||||||
else return "pattern";
|
else return "pattern";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function definePattern(pattern, element, size = "") {
|
function definePattern(pattern, element, size = "") {
|
||||||
let t1 = null, t2 = null;
|
let t1 = null,
|
||||||
if (P(.1)) size = "-small";
|
t2 = null;
|
||||||
else if (P(.1)) size = "-smaller";
|
if (P(0.1)) size = "-small";
|
||||||
else if (P(.01)) size = "-big";
|
else if (P(0.1)) size = "-smaller";
|
||||||
else if (P(.005)) size = "-smallest";
|
else if (P(0.01)) size = "-big";
|
||||||
|
else if (P(0.005)) size = "-smallest";
|
||||||
|
|
||||||
// apply standard tinctures
|
// apply standard tinctures
|
||||||
if (P(.5) && ["vair", "vairInPale", "vairEnPointe"].includes(pattern)) {t1 = "azure"; t2 = "argent";}
|
if (P(0.5) && ["vair", "vairInPale", "vairEnPointe"].includes(pattern)) {
|
||||||
else if (P(.8) && pattern === "ermine") {t1 = "argent"; t2 = "sable";}
|
t1 = "azure";
|
||||||
else if (pattern === "pappellony") {
|
t2 = "argent";
|
||||||
if (P(.2)) {t1 = "gules"; t2 = "or";}
|
} else if (P(0.8) && pattern === "ermine") {
|
||||||
else if (P(.2)) {t1 = "argent"; t2 = "sable";}
|
t1 = "argent";
|
||||||
else if (P(.2)) {t1 = "azure"; t2 = "argent";}
|
t2 = "sable";
|
||||||
|
} else if (pattern === "pappellony") {
|
||||||
|
if (P(0.2)) {
|
||||||
|
t1 = "gules";
|
||||||
|
t2 = "or";
|
||||||
|
} else if (P(0.2)) {
|
||||||
|
t1 = "argent";
|
||||||
|
t2 = "sable";
|
||||||
|
} else if (P(0.2)) {
|
||||||
|
t1 = "azure";
|
||||||
|
t2 = "argent";
|
||||||
}
|
}
|
||||||
else if (pattern === "masoned") {
|
} else if (pattern === "masoned") {
|
||||||
if (P(.3)) {t1 = "gules"; t2 = "argent";}
|
if (P(0.3)) {
|
||||||
else if (P(.3)) {t1 = "argent"; t2 = "sable";}
|
t1 = "gules";
|
||||||
else if (P(.1)) {t1 = "or"; t2 = "sable";}
|
t2 = "argent";
|
||||||
|
} else if (P(0.3)) {
|
||||||
|
t1 = "argent";
|
||||||
|
t2 = "sable";
|
||||||
|
} else if (P(0.1)) {
|
||||||
|
t1 = "or";
|
||||||
|
t2 = "sable";
|
||||||
}
|
}
|
||||||
else if (pattern === "fretty") {
|
} else if (pattern === "fretty") {
|
||||||
if (t2 === "sable" || P(.35)) {t1 = "argent"; t2 = "gules";}
|
if (t2 === "sable" || P(0.35)) {
|
||||||
else if (P(.25)) {t1 = "sable"; t2 = "or";}
|
t1 = "argent";
|
||||||
else if (P(.15)) {t1 = "gules"; t2 = "argent";}
|
t2 = "gules";
|
||||||
|
} else if (P(0.25)) {
|
||||||
|
t1 = "sable";
|
||||||
|
t2 = "or";
|
||||||
|
} else if (P(0.15)) {
|
||||||
|
t1 = "gules";
|
||||||
|
t2 = "argent";
|
||||||
}
|
}
|
||||||
else if (pattern === "semy") pattern += "_of_" + selectCharge(charges.semy);
|
} else if (pattern === "semy") pattern += "_of_" + selectCharge(charges.semy);
|
||||||
|
|
||||||
|
|
||||||
if (!t1 || !t2) {
|
if (!t1 || !t2) {
|
||||||
const startWithMetal = P(.7);
|
const startWithMetal = P(0.7);
|
||||||
t1 = startWithMetal ? rw(tinctures.metals) : rw(tinctures.colours);
|
t1 = startWithMetal ? rw(tinctures.metals) : rw(tinctures.colours);
|
||||||
t2 = startWithMetal ? rw(tinctures.colours) : rw(tinctures.metals);
|
t2 = startWithMetal ? rw(tinctures.colours) : rw(tinctures.metals);
|
||||||
}
|
}
|
||||||
|
|
@ -474,26 +748,28 @@
|
||||||
|
|
||||||
function replaceTincture(t, n) {
|
function replaceTincture(t, n) {
|
||||||
const type = getType(t);
|
const type = getType(t);
|
||||||
while (!n || n === t) {n = rw(tinctures[type]);}
|
while (!n || n === t) {
|
||||||
|
n = rw(tinctures[type]);
|
||||||
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSize(p, o = null, d = null) {
|
function getSize(p, o = null, d = null) {
|
||||||
if (p === "e" && (o === "bordure" || o === "orle")) return 1.1;
|
if (p === "e" && (o === "bordure" || o === "orle")) return 1.1;
|
||||||
if (p === "e") return 1.5;
|
if (p === "e") return 1.5;
|
||||||
if (p === "jln" || p === "jlh") return .7;
|
if (p === "jln" || p === "jlh") return 0.7;
|
||||||
if (p === "abcpqh" || p === "ez" || p === "be") return .5;
|
if (p === "abcpqh" || p === "ez" || p === "be") return 0.5;
|
||||||
if (["a", "b", "c", "d", "f", "g", "h", "i", "bh", "df"].includes(p)) return .5;
|
if (["a", "b", "c", "d", "f", "g", "h", "i", "bh", "df"].includes(p)) return 0.5;
|
||||||
if (["j", "l", "m", "o", "jlmo"].includes(p) && d === "perCross") return .6;
|
if (["j", "l", "m", "o", "jlmo"].includes(p) && d === "perCross") return 0.6;
|
||||||
if (p.length > 10) return .18; // >10 (bordure)
|
if (p.length > 10) return 0.18; // >10 (bordure)
|
||||||
if (p.length > 7) return .3; // 8, 9, 10
|
if (p.length > 7) return 0.3; // 8, 9, 10
|
||||||
if (p.length > 4) return .4; // 5, 6, 7
|
if (p.length > 4) return 0.4; // 5, 6, 7
|
||||||
if (p.length > 2) return .5; // 3, 4
|
if (p.length > 2) return 0.5; // 3, 4
|
||||||
return .7; // 1, 2
|
return 0.7; // 1, 2
|
||||||
}
|
}
|
||||||
|
|
||||||
return coa;
|
return coa;
|
||||||
}
|
};
|
||||||
|
|
||||||
const getShield = function (culture, state) {
|
const getShield = function (culture, state) {
|
||||||
const emblemShape = document.getElementById("emblemShape");
|
const emblemShape = document.getElementById("emblemShape");
|
||||||
|
|
@ -504,11 +780,10 @@
|
||||||
if (pack.cultures[culture].shield) return pack.cultures[culture].shield;
|
if (pack.cultures[culture].shield) return pack.cultures[culture].shield;
|
||||||
console.error("Shield shape is not defined on culture level", pack.cultures[culture]);
|
console.error("Shield shape is not defined on culture level", pack.cultures[culture]);
|
||||||
return "heater";
|
return "heater";
|
||||||
}
|
};
|
||||||
|
|
||||||
const toString = coa => JSON.stringify(coa).replaceAll("#", "%23");
|
const toString = coa => JSON.stringify(coa).replaceAll("#", "%23");
|
||||||
const copy = coa => JSON.parse(JSON.stringify(coa));
|
const copy = coa => JSON.parse(JSON.stringify(coa));
|
||||||
|
|
||||||
return {generate, toString, copy, getShield, shields};
|
return {generate, toString, copy, getShield, shields};
|
||||||
|
})();
|
||||||
})));
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,13 +1,10 @@
|
||||||
(function (global, factory) {
|
"use strict";
|
||||||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
|
||||||
typeof define === 'function' && define.amd ? define(factory) :
|
|
||||||
(global.Cultures = factory());
|
|
||||||
}(this, (function () {'use strict';
|
|
||||||
|
|
||||||
|
window.Cultures = (function () {
|
||||||
let cells;
|
let cells;
|
||||||
|
|
||||||
const generate = function () {
|
const generate = function () {
|
||||||
TIME && console.time('generateCultures');
|
TIME && console.time("generateCultures");
|
||||||
cells = pack.cells;
|
cells = pack.cells;
|
||||||
cells.culture = new Uint16Array(cells.i.length); // cell cultures
|
cells.culture = new Uint16Array(cells.i.length); // cell cultures
|
||||||
let count = Math.min(+culturesInput.value, +culturesSet.selectedOptions[0].dataset.max);
|
let count = Math.min(+culturesInput.value, +culturesSet.selectedOptions[0].dataset.max);
|
||||||
|
|
@ -22,8 +19,14 @@
|
||||||
The climate is harsh and people cannot live in this world.<br>
|
The climate is harsh and people cannot live in this world.<br>
|
||||||
No cultures, states and burgs will be created.<br>
|
No cultures, states and burgs will be created.<br>
|
||||||
Please consider changing climate settings in the World Configurator`;
|
Please consider changing climate settings in the World Configurator`;
|
||||||
$("#alert").dialog({resizable: false, title: "Extreme climate warning",
|
$("#alert").dialog({
|
||||||
buttons: {Ok: function() {$(this).dialog("close");}}
|
resizable: false,
|
||||||
|
title: "Extreme climate warning",
|
||||||
|
buttons: {
|
||||||
|
Ok: function () {
|
||||||
|
$(this).dialog("close");
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -32,20 +35,26 @@
|
||||||
There are only ${populated.length} populated cells and it's insufficient livable area.<br>
|
There are only ${populated.length} populated cells and it's insufficient livable area.<br>
|
||||||
Only ${count} out of ${culturesInput.value} requested cultures will be generated.<br>
|
Only ${count} out of ${culturesInput.value} requested cultures will be generated.<br>
|
||||||
Please consider changing climate settings in the World Configurator`;
|
Please consider changing climate settings in the World Configurator`;
|
||||||
$("#alert").dialog({resizable: false, title: "Extreme climate warning",
|
$("#alert").dialog({
|
||||||
buttons: {Ok: function() {$(this).dialog("close");}}
|
resizable: false,
|
||||||
|
title: "Extreme climate warning",
|
||||||
|
buttons: {
|
||||||
|
Ok: function () {
|
||||||
|
$(this).dialog("close");
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const cultures = pack.cultures = selectCultures(count);
|
const cultures = (pack.cultures = selectCultures(count));
|
||||||
const centers = d3.quadtree();
|
const centers = d3.quadtree();
|
||||||
const colors = getColors(count);
|
const colors = getColors(count);
|
||||||
const emblemShape = document.getElementById("emblemShape").value;
|
const emblemShape = document.getElementById("emblemShape").value;
|
||||||
|
|
||||||
const codes = [];
|
const codes = [];
|
||||||
cultures.forEach(function (c, i) {
|
cultures.forEach(function (c, i) {
|
||||||
const cell = c.center = placeCenter(c.sort ? c.sort : (i) => cells.s[i]);
|
const cell = (c.center = placeCenter(c.sort ? c.sort : i => cells.s[i]));
|
||||||
centers.add(cells.p[cell]);
|
centers.add(cells.p[cell]);
|
||||||
c.i = i + 1;
|
c.i = i + 1;
|
||||||
delete c.odd;
|
delete c.odd;
|
||||||
|
|
@ -61,10 +70,14 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
function placeCenter(v) {
|
function placeCenter(v) {
|
||||||
let c, spacing = (graphWidth + graphHeight) / 2 / count;
|
let c,
|
||||||
const sorted = [...populated].sort((a, b) => v(b) - v(a)), max = Math.floor(sorted.length / 2);
|
spacing = (graphWidth + graphHeight) / 2 / count;
|
||||||
do {c = sorted[biased(0, max, 5)]; spacing *= .9;}
|
const sorted = [...populated].sort((a, b) => v(b) - v(a)),
|
||||||
while (centers.find(cells.p[c][0], cells.p[c][1], spacing) !== undefined);
|
max = Math.floor(sorted.length / 2);
|
||||||
|
do {
|
||||||
|
c = sorted[biased(0, max, 5)];
|
||||||
|
spacing *= 0.9;
|
||||||
|
} while (centers.find(cells.p[c][0], cells.p[c][1], spacing) !== undefined);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -77,7 +90,7 @@
|
||||||
nameBases = Names.getNameBases();
|
nameBases = Names.getNameBases();
|
||||||
}
|
}
|
||||||
|
|
||||||
cultures.forEach(c => c.base = c.base % nameBases.length);
|
cultures.forEach(c => (c.base = c.base % nameBases.length));
|
||||||
|
|
||||||
function selectCultures(c) {
|
function selectCultures(c) {
|
||||||
let def = getDefault(c);
|
let def = getDefault(c);
|
||||||
|
|
@ -91,7 +104,7 @@
|
||||||
do {
|
do {
|
||||||
rnd = rand(def.length - 1);
|
rnd = rand(def.length - 1);
|
||||||
culture = def[rnd];
|
culture = def[rnd];
|
||||||
} while (!P(culture.odd))
|
} while (!P(culture.odd));
|
||||||
cultures.push(culture);
|
cultures.push(culture);
|
||||||
def.splice(rnd, 1);
|
def.splice(rnd, 1);
|
||||||
}
|
}
|
||||||
|
|
@ -103,8 +116,8 @@
|
||||||
if (cells.h[i] < 70 && [1, 2, 4].includes(cells.biome[i])) return "Nomadic"; // high penalty in forest biomes and near coastline
|
if (cells.h[i] < 70 && [1, 2, 4].includes(cells.biome[i])) return "Nomadic"; // high penalty in forest biomes and near coastline
|
||||||
if (cells.h[i] > 50) return "Highland"; // no penalty for hills and moutains, high for other elevations
|
if (cells.h[i] > 50) return "Highland"; // no penalty for hills and moutains, high for other elevations
|
||||||
const f = pack.features[cells.f[cells.haven[i]]]; // opposite feature
|
const f = pack.features[cells.f[cells.haven[i]]]; // opposite feature
|
||||||
if (f.type === "lake" && f.cells > 5) return "Lake" // low water cross penalty and high for growth not along coastline
|
if (f.type === "lake" && f.cells > 5) return "Lake"; // low water cross penalty and high for growth not along coastline
|
||||||
if (cells.harbor[i] && f.type !== "lake" && P(.1) || (cells.harbor[i] === 1 && P(.6)) || (pack.features[cells.f[i]].group === "isle" && P(.4))) return "Naval"; // low water cross penalty and high for non-along-coastline growth
|
if ((cells.harbor[i] && f.type !== "lake" && P(0.1)) || (cells.harbor[i] === 1 && P(0.6)) || (pack.features[cells.f[i]].group === "isle" && P(0.4))) return "Naval"; // low water cross penalty and high for non-along-coastline growth
|
||||||
if (cells.r[i] && cells.fl[i] > 100) return "River"; // no River cross penalty, penalty for non-River growth
|
if (cells.r[i] && cells.fl[i] > 100) return "River"; // no River cross penalty, penalty for non-River growth
|
||||||
if (cells.t[i] > 2 && [3, 7, 8, 9, 10, 12].includes(cells.biome[i])) return "Hunting"; // high penalty in non-native biomes
|
if (cells.t[i] > 2 && [3, 7, 8, 9, 10, 12].includes(cells.biome[i])) return "Hunting"; // high penalty in non-native biomes
|
||||||
return "Generic";
|
return "Generic";
|
||||||
|
|
@ -112,17 +125,17 @@
|
||||||
|
|
||||||
function defineCultureExpansionism(type) {
|
function defineCultureExpansionism(type) {
|
||||||
let base = 1; // Generic
|
let base = 1; // Generic
|
||||||
if (type === "Lake") base = .8; else
|
if (type === "Lake") base = 0.8;
|
||||||
if (type === "Naval") base = 1.5; else
|
else if (type === "Naval") base = 1.5;
|
||||||
if (type === "River") base = .9; else
|
else if (type === "River") base = 0.9;
|
||||||
if (type === "Nomadic") base = 1.5; else
|
else if (type === "Nomadic") base = 1.5;
|
||||||
if (type === "Hunting") base = .7; else
|
else if (type === "Hunting") base = 0.7;
|
||||||
if (type === "Highland") base = 1.2;
|
else if (type === "Highland") base = 1.2;
|
||||||
return rn((Math.random() * powerInput.value / 2 + 1) * base, 1);
|
return rn(((Math.random() * powerInput.value) / 2 + 1) * base, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TIME && console.timeEnd('generateCultures');
|
TIME && console.timeEnd("generateCultures");
|
||||||
}
|
};
|
||||||
|
|
||||||
const add = function (center) {
|
const add = function (center) {
|
||||||
const defaultCultures = getDefault();
|
const defaultCultures = getDefault();
|
||||||
|
|
@ -139,7 +152,10 @@
|
||||||
name = Names.getCulture(culture, 5, 8, "");
|
name = Names.getCulture(culture, 5, 8, "");
|
||||||
base = pack.cultures[culture].base;
|
base = pack.cultures[culture].base;
|
||||||
}
|
}
|
||||||
const code = abbreviate(name, pack.cultures.map(c => c.code));
|
const code = abbreviate(
|
||||||
|
name,
|
||||||
|
pack.cultures.map(c => c.code)
|
||||||
|
);
|
||||||
const i = pack.cultures.length;
|
const i = pack.cultures.length;
|
||||||
const color = d3.color(d3.scaleSequential(d3.interpolateRainbow)(Math.random())).hex();
|
const color = d3.color(d3.scaleSequential(d3.interpolateRainbow)(Math.random())).hex();
|
||||||
|
|
||||||
|
|
@ -149,15 +165,23 @@
|
||||||
if (emblemShape === "random") shield = getRandomShield();
|
if (emblemShape === "random") shield = getRandomShield();
|
||||||
|
|
||||||
pack.cultures.push({name, color, base, center, i, expansionism: 1, type: "Generic", cells: 0, area: 0, rural: 0, urban: 0, origin: 0, code, shield});
|
pack.cultures.push({name, color, base, center, i, expansionism: 1, type: "Generic", cells: 0, area: 0, rural: 0, urban: 0, origin: 0, code, shield});
|
||||||
}
|
};
|
||||||
|
|
||||||
const getDefault = function (count) {
|
const getDefault = function (count) {
|
||||||
// generic sorting functions
|
// generic sorting functions
|
||||||
const cells = pack.cells, s = cells.s, sMax = d3.max(s), t = cells.t, h = cells.h, temp = grid.cells.temp;
|
const cells = pack.cells,
|
||||||
const n = cell => Math.ceil(s[cell] / sMax * 3) // normalized cell score
|
s = cells.s,
|
||||||
const td = (cell, goal) => {const d = Math.abs(temp[cells.g[cell]] - goal); return d ? d+1 : 1;} // temperature difference fee
|
sMax = d3.max(s),
|
||||||
const bd = (cell, biomes, fee = 4) => biomes.includes(cells.biome[cell]) ? 1 : fee; // biome difference fee
|
t = cells.t,
|
||||||
const sf = (cell, fee = 4) => cells.haven[cell] && pack.features[cells.f[cells.haven[cell]]].type !== "lake" ? 1 : fee; // not on sea coast fee
|
h = cells.h,
|
||||||
|
temp = grid.cells.temp;
|
||||||
|
const n = cell => Math.ceil((s[cell] / sMax) * 3); // normalized cell score
|
||||||
|
const td = (cell, goal) => {
|
||||||
|
const d = Math.abs(temp[cells.g[cell]] - goal);
|
||||||
|
return d ? d + 1 : 1;
|
||||||
|
}; // temperature difference fee
|
||||||
|
const bd = (cell, biomes, fee = 4) => (biomes.includes(cells.biome[cell]) ? 1 : fee); // biome difference fee
|
||||||
|
const sf = (cell, fee = 4) => (cells.haven[cell] && pack.features[cells.f[cells.haven[cell]]].type !== "lake" ? 1 : fee); // not on sea coast fee
|
||||||
|
|
||||||
if (culturesSet.value === "european") {
|
if (culturesSet.value === "european") {
|
||||||
return [
|
return [
|
||||||
|
|
@ -166,16 +190,16 @@
|
||||||
{name: "Luari", base: 2, odd: 1, sort: i => n(i) / td(i, 12) / bd(i, [6, 8]), shield: "french"},
|
{name: "Luari", base: 2, odd: 1, sort: i => n(i) / td(i, 12) / bd(i, [6, 8]), shield: "french"},
|
||||||
{name: "Tallian", base: 3, odd: 1, sort: i => n(i) / td(i, 15), shield: "horsehead"},
|
{name: "Tallian", base: 3, odd: 1, sort: i => n(i) / td(i, 15), shield: "horsehead"},
|
||||||
{name: "Astellian", base: 4, odd: 1, sort: i => n(i) / td(i, 16), shield: "spanish"},
|
{name: "Astellian", base: 4, odd: 1, sort: i => n(i) / td(i, 16), shield: "spanish"},
|
||||||
{name:"Slovan", base:5, odd:1, sort: i => n(i) / td(i, 6) * t[i], shield:"polish"},
|
{name: "Slovan", base: 5, odd: 1, sort: i => (n(i) / td(i, 6)) * t[i], shield: "polish"},
|
||||||
{name: "Norse", base: 6, odd: 1, sort: i => n(i) / td(i, 5), shield: "heater"},
|
{name: "Norse", base: 6, odd: 1, sort: i => n(i) / td(i, 5), shield: "heater"},
|
||||||
{name:"Elladan", base:7, odd:1, sort: i => n(i) / td(i, 18) * h[i], shield:"boeotian"},
|
{name: "Elladan", base: 7, odd: 1, sort: i => (n(i) / td(i, 18)) * h[i], shield: "boeotian"},
|
||||||
{name:"Romian", base:8, odd:.2, sort: i => n(i) / td(i, 15) / t[i], shield:"roman"},
|
{name: "Romian", base: 8, odd: 0.2, sort: i => n(i) / td(i, 15) / t[i], shield: "roman"},
|
||||||
{name:"Soumi", base:9, odd:1, sort: i => n(i) / td(i, 5) / bd(i, [9]) * t[i], shield:"pavise"},
|
{name: "Soumi", base: 9, odd: 1, sort: i => (n(i) / td(i, 5) / bd(i, [9])) * t[i], shield: "pavise"},
|
||||||
{name: "Portuzian", base: 13, odd: 1, sort: i => n(i) / td(i, 17) / sf(i), shield: "renaissance"},
|
{name: "Portuzian", base: 13, odd: 1, sort: i => n(i) / td(i, 17) / sf(i), shield: "renaissance"},
|
||||||
{name:"Vengrian", base: 15, odd:1, sort: i => n(i) / td(i, 11) / bd(i, [4]) * t[i], shield:"horsehead2"},
|
{name: "Vengrian", base: 15, odd: 1, sort: i => (n(i) / td(i, 11) / bd(i, [4])) * t[i], shield: "horsehead2"},
|
||||||
{name:"Turchian", base: 16, odd:.05, sort: i => n(i) / td(i, 14), shield:"round"},
|
{name: "Turchian", base: 16, odd: 0.05, sort: i => n(i) / td(i, 14), shield: "round"},
|
||||||
{name:"Euskati", base: 20, odd:.05, sort: i => n(i) / td(i, 15) * h[i], shield:"oldFrench"},
|
{name: "Euskati", base: 20, odd: 0.05, sort: i => (n(i) / td(i, 15)) * h[i], shield: "oldFrench"},
|
||||||
{name:"Keltan", base: 22, odd:.05, sort: i => n(i) / td(i, 11) / bd(i, [6, 8]) * t[i], shield:"oval"}
|
{name: "Keltan", base: 22, odd: 0.05, sort: i => (n(i) / td(i, 11) / bd(i, [6, 8])) * t[i], shield: "oval"}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -185,15 +209,15 @@
|
||||||
{name: "Hantzu", base: 11, odd: 1, sort: i => n(i) / td(i, 13), shield: "banner"},
|
{name: "Hantzu", base: 11, odd: 1, sort: i => n(i) / td(i, 13), shield: "banner"},
|
||||||
{name: "Yamoto", base: 12, odd: 1, sort: i => n(i) / td(i, 15) / t[i], shield: "round"},
|
{name: "Yamoto", base: 12, odd: 1, sort: i => n(i) / td(i, 15) / t[i], shield: "round"},
|
||||||
{name: "Turchian", base: 16, odd: 1, sort: i => n(i) / td(i, 12), shield: "round"},
|
{name: "Turchian", base: 16, odd: 1, sort: i => n(i) / td(i, 12), shield: "round"},
|
||||||
{name:"Berberan", base: 17, odd:.2, sort: i => n(i) / td(i, 19) / bd(i, [1, 2, 3], 7) * t[i], shield:"oval"},
|
{name: "Berberan", base: 17, odd: 0.2, sort: i => (n(i) / td(i, 19) / bd(i, [1, 2, 3], 7)) * t[i], shield: "oval"},
|
||||||
{name:"Eurabic", base: 18, odd:1, sort: i => n(i) / td(i, 26) / bd(i, [1, 2], 7) * t[i], shield:"oval"},
|
{name: "Eurabic", base: 18, odd: 1, sort: i => (n(i) / td(i, 26) / bd(i, [1, 2], 7)) * t[i], shield: "oval"},
|
||||||
{name:"Efratic", base: 23, odd:.1, sort: i => n(i) / td(i, 22) * t[i], shield:"round"},
|
{name: "Efratic", base: 23, odd: 0.1, sort: i => (n(i) / td(i, 22)) * t[i], shield: "round"},
|
||||||
{name:"Tehrani", base: 24, odd:1, sort: i => n(i) / td(i, 18) * h[i], shield:"round"},
|
{name: "Tehrani", base: 24, odd: 1, sort: i => (n(i) / td(i, 18)) * h[i], shield: "round"},
|
||||||
{name:"Maui", base: 25, odd:.2, sort: i => n(i) / td(i, 24) / sf(i) / t[i], shield:"vesicaPiscis"},
|
{name: "Maui", base: 25, odd: 0.2, sort: i => n(i) / td(i, 24) / sf(i) / t[i], shield: "vesicaPiscis"},
|
||||||
{name:"Carnatic", base: 26, odd:.5, sort: i => n(i) / td(i, 26), shield:"round"},
|
{name: "Carnatic", base: 26, odd: 0.5, sort: i => n(i) / td(i, 26), shield: "round"},
|
||||||
{name:"Vietic", base: 29, odd:.8, sort: i => n(i) / td(i, 25) / bd(i, [7], 7) / t[i], shield:"banner"},
|
{name: "Vietic", base: 29, odd: 0.8, sort: i => n(i) / td(i, 25) / bd(i, [7], 7) / t[i], shield: "banner"},
|
||||||
{name:"Guantzu", base:30, odd:.5, sort: i => n(i) / td(i, 17), shield:"banner"},
|
{name: "Guantzu", base: 30, odd: 0.5, sort: i => n(i) / td(i, 17), shield: "banner"},
|
||||||
{name:"Ulus", base:31, odd:1, sort: i => n(i) / td(i, 5) / bd(i, [2, 4, 10], 7) * t[i], shield:"banner"}
|
{name: "Ulus", base: 31, odd: 1, sort: i => (n(i) / td(i, 5) / bd(i, [2, 4, 10], 7)) * t[i], shield: "banner"}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -219,41 +243,41 @@
|
||||||
{name: "Roman", base: 8, odd: 1, sort: i => n(i) / td(i, 15) / sf(i), shield: "roman"}, // Roman
|
{name: "Roman", base: 8, odd: 1, sort: i => n(i) / td(i, 15) / sf(i), shield: "roman"}, // Roman
|
||||||
{name: "Roman", base: 8, odd: 1, sort: i => n(i) / td(i, 16) / sf(i), shield: "roman"}, // Roman
|
{name: "Roman", base: 8, odd: 1, sort: i => n(i) / td(i, 16) / sf(i), shield: "roman"}, // Roman
|
||||||
{name: "Roman", base: 8, odd: 1, sort: i => n(i) / td(i, 17) / t[i], shield: "roman"}, // Roman
|
{name: "Roman", base: 8, odd: 1, sort: i => n(i) / td(i, 17) / t[i], shield: "roman"}, // Roman
|
||||||
{name:"Hellenic", base:7, odd:1, sort: i => n(i) / td(i, 18) / sf(i) * h[i], shield:"boeotian"}, // Greek
|
{name: "Hellenic", base: 7, odd: 1, sort: i => (n(i) / td(i, 18) / sf(i)) * h[i], shield: "boeotian"}, // Greek
|
||||||
{name:"Hellenic", base:7, odd:1, sort: i => n(i) / td(i, 19) / sf(i) * h[i], shield:"boeotian"}, // Greek
|
{name: "Hellenic", base: 7, odd: 1, sort: i => (n(i) / td(i, 19) / sf(i)) * h[i], shield: "boeotian"}, // Greek
|
||||||
{name:"Macedonian", base:7, odd:.5, sort: i => n(i) / td(i, 12) * h[i], shield:"round"}, // Greek
|
{name: "Macedonian", base: 7, odd: 0.5, sort: i => (n(i) / td(i, 12)) * h[i], shield: "round"}, // Greek
|
||||||
{name:"Celtic", base:22, odd:1, sort: i => n(i) / td(i, 11) ** .5 / bd(i, [6, 8]), shield:"round"},
|
{name: "Celtic", base: 22, odd: 1, sort: i => n(i) / td(i, 11) ** 0.5 / bd(i, [6, 8]), shield: "round"},
|
||||||
{name:"Germanic", base:0, odd:1, sort: i => n(i) / td(i, 10) ** .5 / bd(i, [6, 8]), shield:"round"},
|
{name: "Germanic", base: 0, odd: 1, sort: i => n(i) / td(i, 10) ** 0.5 / bd(i, [6, 8]), shield: "round"},
|
||||||
{name:"Persian", base:24, odd:.8, sort: i => n(i) / td(i, 18) * h[i], shield:"oval"}, // Iranian
|
{name: "Persian", base: 24, odd: 0.8, sort: i => (n(i) / td(i, 18)) * h[i], shield: "oval"}, // Iranian
|
||||||
{name:"Scythian", base:24, odd:.5, sort: i => n(i) / td(i, 11) ** .5 / bd(i, [4]), shield:"round"}, // Iranian
|
{name: "Scythian", base: 24, odd: 0.5, sort: i => n(i) / td(i, 11) ** 0.5 / bd(i, [4]), shield: "round"}, // Iranian
|
||||||
{name:"Cantabrian", base: 20, odd:.5, sort: i => n(i) / td(i, 16) * h[i], shield:"oval"}, // Basque
|
{name: "Cantabrian", base: 20, odd: 0.5, sort: i => (n(i) / td(i, 16)) * h[i], shield: "oval"}, // Basque
|
||||||
{name:"Estian", base: 9, odd:.2, sort: i => n(i) / td(i, 5) * t[i], shield:"pavise"}, // Finnic
|
{name: "Estian", base: 9, odd: 0.2, sort: i => (n(i) / td(i, 5)) * t[i], shield: "pavise"}, // Finnic
|
||||||
{name:"Carthaginian", base: 17, odd:.3, sort: i => n(i) / td(i, 19) / sf(i), shield:"oval"}, // Berber
|
{name: "Carthaginian", base: 17, odd: 0.3, sort: i => n(i) / td(i, 19) / sf(i), shield: "oval"}, // Berber
|
||||||
{name:"Mesopotamian", base: 23, odd:.2, sort: i => n(i) / td(i, 22) / bd(i, [1, 2, 3]), shield:"oval"} // Mesopotamian
|
{name: "Mesopotamian", base: 23, odd: 0.2, sort: i => n(i) / td(i, 22) / bd(i, [1, 2, 3]), shield: "oval"} // Mesopotamian
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (culturesSet.value === "highFantasy") {
|
if (culturesSet.value === "highFantasy") {
|
||||||
return [
|
return [
|
||||||
// fantasy races
|
// fantasy races
|
||||||
{name:"Quenian (Elfish)", base: 33, odd:1, sort: i => n(i) / bd(i, [6,7,8,9], 10) * t[i], shield:"gondor"}, // Elves
|
{name: "Quenian (Elfish)", base: 33, odd: 1, sort: i => (n(i) / bd(i, [6, 7, 8, 9], 10)) * t[i], shield: "gondor"}, // Elves
|
||||||
{name:"Eldar (Elfish)", base: 33, odd:1, sort: i => n(i) / bd(i, [6,7,8,9], 10) * t[i], shield:"noldor"}, // Elves
|
{name: "Eldar (Elfish)", base: 33, odd: 1, sort: i => (n(i) / bd(i, [6, 7, 8, 9], 10)) * t[i], shield: "noldor"}, // Elves
|
||||||
{name:"Trow (Dark Elfish)", base: 34, odd:.9, sort: i => n(i) / bd(i, [7,8,9,12], 10) * t[i], shield:"hessen"}, // Dark Elves
|
{name: "Trow (Dark Elfish)", base: 34, odd: 0.9, sort: i => (n(i) / bd(i, [7, 8, 9, 12], 10)) * t[i], shield: "hessen"}, // Dark Elves
|
||||||
{name:"Lothian (Dark Elfish)", base: 34, odd:.3, sort: i => n(i) / bd(i, [7,8,9,12], 10) * t[i], shield:"wedged"}, // Dark Elves
|
{name: "Lothian (Dark Elfish)", base: 34, odd: 0.3, sort: i => (n(i) / bd(i, [7, 8, 9, 12], 10)) * t[i], shield: "wedged"}, // Dark Elves
|
||||||
{name: "Dunirr (Dwarven)", base: 35, odd: 1, sort: i => n(i) + h[i], shield: "ironHills"}, // Dwarfs
|
{name: "Dunirr (Dwarven)", base: 35, odd: 1, sort: i => n(i) + h[i], shield: "ironHills"}, // Dwarfs
|
||||||
{name: "Khazadur (Dwarven)", base: 35, odd: 1, sort: i => n(i) + h[i], shield: "erebor"}, // Dwarfs
|
{name: "Khazadur (Dwarven)", base: 35, odd: 1, sort: i => n(i) + h[i], shield: "erebor"}, // Dwarfs
|
||||||
{name: "Kobold (Goblin)", base: 36, odd: 1, sort: i => t[i] - s[i], shield: "moriaOrc"}, // Goblin
|
{name: "Kobold (Goblin)", base: 36, odd: 1, sort: i => t[i] - s[i], shield: "moriaOrc"}, // Goblin
|
||||||
{name: "Uruk (Orkish)", base: 37, odd: 1, sort: i => h[i] * t[i], shield: "urukHai"}, // Orc
|
{name: "Uruk (Orkish)", base: 37, odd: 1, sort: i => h[i] * t[i], shield: "urukHai"}, // Orc
|
||||||
{name:"Ugluk (Orkish)", base: 37, odd:.5, sort: i => h[i] * t[i] / bd(i, [1,2,10,11]), shield:"moriaOrc"}, // Orc
|
{name: "Ugluk (Orkish)", base: 37, odd: 0.5, sort: i => (h[i] * t[i]) / bd(i, [1, 2, 10, 11]), shield: "moriaOrc"}, // Orc
|
||||||
{name:"Yotunn (Giants)", base: 38, odd:.7, sort: i => td(i, -10), shield:"pavise"}, // Giant
|
{name: "Yotunn (Giants)", base: 38, odd: 0.7, sort: i => td(i, -10), shield: "pavise"}, // Giant
|
||||||
{name:"Rake (Drakonic)", base: 39, odd:.7, sort: i => -s[i], shield:"fantasy2"}, // Draconic
|
{name: "Rake (Drakonic)", base: 39, odd: 0.7, sort: i => -s[i], shield: "fantasy2"}, // Draconic
|
||||||
{name:"Arago (Arachnid)", base: 40, odd:.7, sort: i => t[i] - s[i], shield:"horsehead2"}, // Arachnid
|
{name: "Arago (Arachnid)", base: 40, odd: 0.7, sort: i => t[i] - s[i], shield: "horsehead2"}, // Arachnid
|
||||||
{name:"Aj'Snaga (Serpents)", base: 41, odd:.7, sort: i => n(i) / bd(i, [12], 10), shield:"fantasy1"}, // Serpents
|
{name: "Aj'Snaga (Serpents)", base: 41, odd: 0.7, sort: i => n(i) / bd(i, [12], 10), shield: "fantasy1"}, // Serpents
|
||||||
// fantasy human
|
// fantasy human
|
||||||
{name: "Anor (Human)", base: 32, odd: 1, sort: i => n(i) / td(i, 10), shield: "fantasy5"},
|
{name: "Anor (Human)", base: 32, odd: 1, sort: i => n(i) / td(i, 10), shield: "fantasy5"},
|
||||||
{name: "Dail (Human)", base: 32, odd: 1, sort: i => n(i) / td(i, 13), shield: "roman"},
|
{name: "Dail (Human)", base: 32, odd: 1, sort: i => n(i) / td(i, 13), shield: "roman"},
|
||||||
{name: "Rohand (Human)", base: 16, odd: 1, sort: i => n(i) / td(i, 16), shield: "round"},
|
{name: "Rohand (Human)", base: 16, odd: 1, sort: i => n(i) / td(i, 16), shield: "round"},
|
||||||
{name:"Dulandir (Human)", base:31, odd:1, sort: i => n(i) / td(i, 5) / bd(i, [2, 4, 10], 7) * t[i], shield:"easterling"},
|
{name: "Dulandir (Human)", base: 31, odd: 1, sort: i => (n(i) / td(i, 5) / bd(i, [2, 4, 10], 7)) * t[i], shield: "easterling"}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -267,87 +291,87 @@
|
||||||
{name: "Mercian", base: 1, odd: 1, sort: i => n(i) / td(i, 9), shield: "heater"},
|
{name: "Mercian", base: 1, odd: 1, sort: i => n(i) / td(i, 9), shield: "heater"},
|
||||||
{name: "Kentian", base: 1, odd: 1, sort: i => n(i) / td(i, 12), shield: "heater"},
|
{name: "Kentian", base: 1, odd: 1, sort: i => n(i) / td(i, 12), shield: "heater"},
|
||||||
// rare real-world western
|
// rare real-world western
|
||||||
{name:"Norse", base:6, odd:.7, sort: i => n(i) / td(i, 5) / sf(i), shield:"oldFrench"},
|
{name: "Norse", base: 6, odd: 0.7, sort: i => n(i) / td(i, 5) / sf(i), shield: "oldFrench"},
|
||||||
{name:"Schwarzen", base:0, odd:.3, sort: i => n(i) / td(i, 10) / bd(i, [6, 8]), shield:"gonfalon"},
|
{name: "Schwarzen", base: 0, odd: 0.3, sort: i => n(i) / td(i, 10) / bd(i, [6, 8]), shield: "gonfalon"},
|
||||||
{name:"Luarian", base:2, odd:.3, sort: i => n(i) / td(i, 12) / bd(i, [6, 8]), shield:"oldFrench"},
|
{name: "Luarian", base: 2, odd: 0.3, sort: i => n(i) / td(i, 12) / bd(i, [6, 8]), shield: "oldFrench"},
|
||||||
{name:"Hetallian", base:3, odd:.3, sort: i => n(i) / td(i, 15), shield:"oval"},
|
{name: "Hetallian", base: 3, odd: 0.3, sort: i => n(i) / td(i, 15), shield: "oval"},
|
||||||
{name:"Astellian", base:4, odd:.3, sort: i => n(i) / td(i, 16), shield:"spanish"},
|
{name: "Astellian", base: 4, odd: 0.3, sort: i => n(i) / td(i, 16), shield: "spanish"},
|
||||||
// rare real-world exotic
|
// rare real-world exotic
|
||||||
{name:"Kiswaili", base:28, odd:.05, sort: i => n(i) / td(i, 29) / bd(i, [1, 3, 5, 7]), shield:"vesicaPiscis"},
|
{name: "Kiswaili", base: 28, odd: 0.05, sort: i => n(i) / td(i, 29) / bd(i, [1, 3, 5, 7]), shield: "vesicaPiscis"},
|
||||||
{name:"Yoruba", base:21, odd:.05, sort: i => n(i) / td(i, 15) / bd(i, [5, 7]), shield:"vesicaPiscis"},
|
{name: "Yoruba", base: 21, odd: 0.05, sort: i => n(i) / td(i, 15) / bd(i, [5, 7]), shield: "vesicaPiscis"},
|
||||||
{name:"Koryo", base:10, odd:.05, sort: i => n(i) / td(i, 12) / t[i], shield:"round"},
|
{name: "Koryo", base: 10, odd: 0.05, sort: i => n(i) / td(i, 12) / t[i], shield: "round"},
|
||||||
{name:"Hantzu", base:11, odd:.05, sort: i => n(i) / td(i, 13), shield:"banner"},
|
{name: "Hantzu", base: 11, odd: 0.05, sort: i => n(i) / td(i, 13), shield: "banner"},
|
||||||
{name:"Yamoto", base:12, odd:.05, sort: i => n(i) / td(i, 15) / t[i], shield:"round"},
|
{name: "Yamoto", base: 12, odd: 0.05, sort: i => n(i) / td(i, 15) / t[i], shield: "round"},
|
||||||
{name:"Guantzu", base:30, odd:.05, sort: i => n(i) / td(i, 17), shield:"banner"},
|
{name: "Guantzu", base: 30, odd: 0.05, sort: i => n(i) / td(i, 17), shield: "banner"},
|
||||||
{name:"Ulus", base:31, odd:.05, sort: i => n(i) / td(i, 5) / bd(i, [2, 4, 10], 7) * t[i], shield:"banner"},
|
{name: "Ulus", base: 31, odd: 0.05, sort: i => (n(i) / td(i, 5) / bd(i, [2, 4, 10], 7)) * t[i], shield: "banner"},
|
||||||
{name:"Turan", base: 16, odd:.05, sort: i => n(i) / td(i, 12), shield:"round"},
|
{name: "Turan", base: 16, odd: 0.05, sort: i => n(i) / td(i, 12), shield: "round"},
|
||||||
{name:"Berberan", base: 17, odd:.05, sort: i => n(i) / td(i, 19) / bd(i, [1, 2, 3], 7) * t[i], shield:"round"},
|
{name: "Berberan", base: 17, odd: 0.05, sort: i => (n(i) / td(i, 19) / bd(i, [1, 2, 3], 7)) * t[i], shield: "round"},
|
||||||
{name:"Eurabic", base: 18, odd:.05, sort: i => n(i) / td(i, 26) / bd(i, [1, 2], 7) * t[i], shield:"round"},
|
{name: "Eurabic", base: 18, odd: 0.05, sort: i => (n(i) / td(i, 26) / bd(i, [1, 2], 7)) * t[i], shield: "round"},
|
||||||
{name:"Slovan", base:5, odd:.05, sort: i => n(i) / td(i, 6) * t[i], shield:"round"},
|
{name: "Slovan", base: 5, odd: 0.05, sort: i => (n(i) / td(i, 6)) * t[i], shield: "round"},
|
||||||
{name:"Keltan", base: 22, odd:.1, sort: i => n(i) / td(i, 11) ** .5 / bd(i, [6, 8]), shield:"vesicaPiscis"},
|
{name: "Keltan", base: 22, odd: 0.1, sort: i => n(i) / td(i, 11) ** 0.5 / bd(i, [6, 8]), shield: "vesicaPiscis"},
|
||||||
{name:"Elladan", base:7, odd:.2, sort: i => n(i) / td(i, 18) / sf(i) * h[i], shield:"boeotian"},
|
{name: "Elladan", base: 7, odd: 0.2, sort: i => (n(i) / td(i, 18) / sf(i)) * h[i], shield: "boeotian"},
|
||||||
{name:"Romian", base:8, odd:.2, sort: i => n(i) / td(i, 14) / t[i], shield:"roman"},
|
{name: "Romian", base: 8, odd: 0.2, sort: i => n(i) / td(i, 14) / t[i], shield: "roman"},
|
||||||
// fantasy races
|
// fantasy races
|
||||||
{name:"Eldar", base: 33, odd:.5, sort: i => n(i) / bd(i, [6,7,8,9], 10) * t[i], shield:"fantasy5"}, // Elves
|
{name: "Eldar", base: 33, odd: 0.5, sort: i => (n(i) / bd(i, [6, 7, 8, 9], 10)) * t[i], shield: "fantasy5"}, // Elves
|
||||||
{name:"Trow", base: 34, odd:.8, sort: i => n(i) / bd(i, [7,8,9,12], 10) * t[i], shield:"hessen"}, // Dark Elves
|
{name: "Trow", base: 34, odd: 0.8, sort: i => (n(i) / bd(i, [7, 8, 9, 12], 10)) * t[i], shield: "hessen"}, // Dark Elves
|
||||||
{name:"Durinn", base: 35, odd:.8, sort: i => n(i) + h[i], shield:"erebor"}, // Dwarven
|
{name: "Durinn", base: 35, odd: 0.8, sort: i => n(i) + h[i], shield: "erebor"}, // Dwarven
|
||||||
{name:"Kobblin", base: 36, odd:.8, sort: i => t[i] - s[i], shield:"moriaOrc"}, // Goblin
|
{name: "Kobblin", base: 36, odd: 0.8, sort: i => t[i] - s[i], shield: "moriaOrc"}, // Goblin
|
||||||
{name:"Uruk", base: 37, odd:.8, sort: i => h[i] * t[i] / bd(i, [1,2,10,11]), shield:"urukHai"}, // Orc
|
{name: "Uruk", base: 37, odd: 0.8, sort: i => (h[i] * t[i]) / bd(i, [1, 2, 10, 11]), shield: "urukHai"}, // Orc
|
||||||
{name:"Yotunn", base: 38, odd:.8, sort: i => td(i, -10), shield:"pavise"}, // Giant
|
{name: "Yotunn", base: 38, odd: 0.8, sort: i => td(i, -10), shield: "pavise"}, // Giant
|
||||||
{name:"Drake", base: 39, odd:.9, sort: i => -s[i], shield:"fantasy2"}, // Draconic
|
{name: "Drake", base: 39, odd: 0.9, sort: i => -s[i], shield: "fantasy2"}, // Draconic
|
||||||
{name:"Rakhnid", base: 40, odd:.9, sort: i => t[i] - s[i], shield:"horsehead2"}, // Arachnid
|
{name: "Rakhnid", base: 40, odd: 0.9, sort: i => t[i] - s[i], shield: "horsehead2"}, // Arachnid
|
||||||
{name:"Aj'Snaga", base: 41, odd:.9, sort: i => n(i) / bd(i, [12], 10), shield:"fantasy1"}, // Serpents
|
{name: "Aj'Snaga", base: 41, odd: 0.9, sort: i => n(i) / bd(i, [12], 10), shield: "fantasy1"} // Serpents
|
||||||
]
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (culturesSet.value === "random") {
|
if (culturesSet.value === "random") {
|
||||||
return d3.range(count).map(function () {
|
return d3.range(count).map(function () {
|
||||||
const rnd = rand(nameBases.length - 1);
|
const rnd = rand(nameBases.length - 1);
|
||||||
const name = Names.getBaseShort(rnd);
|
const name = Names.getBaseShort(rnd);
|
||||||
return {name, base:rnd, odd:1, shield:getRandomShield()}
|
return {name, base: rnd, odd: 1, shield: getRandomShield()};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// all-world
|
// all-world
|
||||||
return [
|
return [
|
||||||
{name:"Shwazen", base:0, odd:.7, sort: i => n(i) / td(i, 10) / bd(i, [6, 8]), shield:"hessen"},
|
{name: "Shwazen", base: 0, odd: 0.7, sort: i => n(i) / td(i, 10) / bd(i, [6, 8]), shield: "hessen"},
|
||||||
{name: "Angshire", base: 1, odd: 1, sort: i => n(i) / td(i, 10) / sf(i), shield: "heater"},
|
{name: "Angshire", base: 1, odd: 1, sort: i => n(i) / td(i, 10) / sf(i), shield: "heater"},
|
||||||
{name:"Luari", base:2, odd:.6, sort: i => n(i) / td(i, 12) / bd(i, [6, 8]), shield:"oldFrench"},
|
{name: "Luari", base: 2, odd: 0.6, sort: i => n(i) / td(i, 12) / bd(i, [6, 8]), shield: "oldFrench"},
|
||||||
{name:"Tallian", base:3, odd:.6, sort: i => n(i) / td(i, 15), shield:"horsehead2"},
|
{name: "Tallian", base: 3, odd: 0.6, sort: i => n(i) / td(i, 15), shield: "horsehead2"},
|
||||||
{name:"Astellian", base:4, odd:.6, sort: i => n(i) / td(i, 16), shield:"spanish"},
|
{name: "Astellian", base: 4, odd: 0.6, sort: i => n(i) / td(i, 16), shield: "spanish"},
|
||||||
{name:"Slovan", base:5, odd:.7, sort: i => n(i) / td(i, 6) * t[i], shield:"round"},
|
{name: "Slovan", base: 5, odd: 0.7, sort: i => (n(i) / td(i, 6)) * t[i], shield: "round"},
|
||||||
{name:"Norse", base:6, odd:.7, sort: i => n(i) / td(i, 5), shield:"heater"},
|
{name: "Norse", base: 6, odd: 0.7, sort: i => n(i) / td(i, 5), shield: "heater"},
|
||||||
{name:"Elladan", base:7, odd:.7, sort: i => n(i) / td(i, 18) * h[i], shield:"boeotian"},
|
{name: "Elladan", base: 7, odd: 0.7, sort: i => (n(i) / td(i, 18)) * h[i], shield: "boeotian"},
|
||||||
{name:"Romian", base:8, odd:.7, sort: i => n(i) / td(i, 15), shield:"roman"},
|
{name: "Romian", base: 8, odd: 0.7, sort: i => n(i) / td(i, 15), shield: "roman"},
|
||||||
{name:"Soumi", base:9, odd:.3, sort: i => n(i) / td(i, 5) / bd(i, [9]) * t[i], shield:"pavise"},
|
{name: "Soumi", base: 9, odd: 0.3, sort: i => (n(i) / td(i, 5) / bd(i, [9])) * t[i], shield: "pavise"},
|
||||||
{name:"Koryo", base:10, odd:.1, sort: i => n(i) / td(i, 12) / t[i], shield:"round"},
|
{name: "Koryo", base: 10, odd: 0.1, sort: i => n(i) / td(i, 12) / t[i], shield: "round"},
|
||||||
{name:"Hantzu", base:11, odd:.1, sort: i => n(i) / td(i, 13), shield:"banner"},
|
{name: "Hantzu", base: 11, odd: 0.1, sort: i => n(i) / td(i, 13), shield: "banner"},
|
||||||
{name:"Yamoto", base:12, odd:.1, sort: i => n(i) / td(i, 15) / t[i], shield:"round"},
|
{name: "Yamoto", base: 12, odd: 0.1, sort: i => n(i) / td(i, 15) / t[i], shield: "round"},
|
||||||
{name:"Portuzian", base:13, odd:.4, sort: i => n(i) / td(i, 17) / sf(i), shield:"spanish"},
|
{name: "Portuzian", base: 13, odd: 0.4, sort: i => n(i) / td(i, 17) / sf(i), shield: "spanish"},
|
||||||
{name:"Nawatli", base:14, odd:.1, sort: i => h[i] / td(i, 18) / bd(i, [7]), shield:"square"},
|
{name: "Nawatli", base: 14, odd: 0.1, sort: i => h[i] / td(i, 18) / bd(i, [7]), shield: "square"},
|
||||||
{name:"Vengrian", base: 15, odd:.2, sort: i => n(i) / td(i, 11) / bd(i, [4]) * t[i], shield:"wedged"},
|
{name: "Vengrian", base: 15, odd: 0.2, sort: i => (n(i) / td(i, 11) / bd(i, [4])) * t[i], shield: "wedged"},
|
||||||
{name:"Turchian", base: 16, odd:.2, sort: i => n(i) / td(i, 13), shield:"round"},
|
{name: "Turchian", base: 16, odd: 0.2, sort: i => n(i) / td(i, 13), shield: "round"},
|
||||||
{name:"Berberan", base: 17, odd:.1, sort: i => n(i) / td(i, 19) / bd(i, [1, 2, 3], 7) * t[i], shield:"round"},
|
{name: "Berberan", base: 17, odd: 0.1, sort: i => (n(i) / td(i, 19) / bd(i, [1, 2, 3], 7)) * t[i], shield: "round"},
|
||||||
{name:"Eurabic", base: 18, odd:.2, sort: i => n(i) / td(i, 26) / bd(i, [1, 2], 7) * t[i], shield:"round"},
|
{name: "Eurabic", base: 18, odd: 0.2, sort: i => (n(i) / td(i, 26) / bd(i, [1, 2], 7)) * t[i], shield: "round"},
|
||||||
{name:"Inuk", base: 19, odd:.05, sort: i => td(i, -1) / bd(i, [10, 11]) / sf(i), shield:"square"},
|
{name: "Inuk", base: 19, odd: 0.05, sort: i => td(i, -1) / bd(i, [10, 11]) / sf(i), shield: "square"},
|
||||||
{name:"Euskati", base: 20, odd:.05, sort: i => n(i) / td(i, 15) * h[i], shield:"spanish"},
|
{name: "Euskati", base: 20, odd: 0.05, sort: i => (n(i) / td(i, 15)) * h[i], shield: "spanish"},
|
||||||
{name:"Yoruba", base: 21, odd:.05, sort: i => n(i) / td(i, 15) / bd(i, [5, 7]), shield:"vesicaPiscis"},
|
{name: "Yoruba", base: 21, odd: 0.05, sort: i => n(i) / td(i, 15) / bd(i, [5, 7]), shield: "vesicaPiscis"},
|
||||||
{name:"Keltan", base: 22, odd:.05, sort: i => n(i) / td(i, 11) / bd(i, [6, 8]) * t[i], shield:"vesicaPiscis"},
|
{name: "Keltan", base: 22, odd: 0.05, sort: i => (n(i) / td(i, 11) / bd(i, [6, 8])) * t[i], shield: "vesicaPiscis"},
|
||||||
{name:"Efratic", base: 23, odd:.05, sort: i => n(i) / td(i, 22) * t[i], shield:"diamond"},
|
{name: "Efratic", base: 23, odd: 0.05, sort: i => (n(i) / td(i, 22)) * t[i], shield: "diamond"},
|
||||||
{name:"Tehrani", base: 24, odd:.1, sort: i => n(i) / td(i, 18) * h[i], shield:"round"},
|
{name: "Tehrani", base: 24, odd: 0.1, sort: i => (n(i) / td(i, 18)) * h[i], shield: "round"},
|
||||||
{name:"Maui", base: 25, odd:.05, sort: i => n(i) / td(i, 24) / sf(i) / t[i], shield:"round"},
|
{name: "Maui", base: 25, odd: 0.05, sort: i => n(i) / td(i, 24) / sf(i) / t[i], shield: "round"},
|
||||||
{name:"Carnatic", base: 26, odd:.05, sort: i => n(i) / td(i, 26), shield:"round"},
|
{name: "Carnatic", base: 26, odd: 0.05, sort: i => n(i) / td(i, 26), shield: "round"},
|
||||||
{name:"Inqan", base: 27, odd:.05, sort: i => h[i] / td(i, 13), shield:"square"},
|
{name: "Inqan", base: 27, odd: 0.05, sort: i => h[i] / td(i, 13), shield: "square"},
|
||||||
{name:"Kiswaili", base: 28, odd:.1, sort: i => n(i) / td(i, 29) / bd(i, [1, 3, 5, 7]), shield:"vesicaPiscis"},
|
{name: "Kiswaili", base: 28, odd: 0.1, sort: i => n(i) / td(i, 29) / bd(i, [1, 3, 5, 7]), shield: "vesicaPiscis"},
|
||||||
{name:"Vietic", base: 29, odd:.1, sort: i => n(i) / td(i, 25) / bd(i, [7], 7) / t[i], shield:"banner"},
|
{name: "Vietic", base: 29, odd: 0.1, sort: i => n(i) / td(i, 25) / bd(i, [7], 7) / t[i], shield: "banner"},
|
||||||
{name:"Guantzu", base:30, odd:.1, sort: i => n(i) / td(i, 17), shield:"banner"},
|
{name: "Guantzu", base: 30, odd: 0.1, sort: i => n(i) / td(i, 17), shield: "banner"},
|
||||||
{name:"Ulus", base:31, odd:.1, sort: i => n(i) / td(i, 5) / bd(i, [2, 4, 10], 7) * t[i], shield:"banner"}
|
{name: "Ulus", base: 31, odd: 0.1, sort: i => (n(i) / td(i, 5) / bd(i, [2, 4, 10], 7)) * t[i], shield: "banner"}
|
||||||
];
|
];
|
||||||
}
|
};
|
||||||
|
|
||||||
// expand cultures across the map (Dijkstra-like algorithm)
|
// expand cultures across the map (Dijkstra-like algorithm)
|
||||||
const expand = function () {
|
const expand = function () {
|
||||||
TIME && console.time('expandCultures');
|
TIME && console.time("expandCultures");
|
||||||
cells = pack.cells;
|
cells = pack.cells;
|
||||||
|
|
||||||
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
|
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
|
||||||
|
|
@ -356,10 +380,13 @@
|
||||||
queue.queue({e: c.center, p: 0, c: c.i});
|
queue.queue({e: c.center, p: 0, c: c.i});
|
||||||
});
|
});
|
||||||
|
|
||||||
const neutral = cells.i.length / 5000 * 3000 * neutralInput.value; // limit cost for culture growth
|
const neutral = (cells.i.length / 5000) * 3000 * neutralInput.value; // limit cost for culture growth
|
||||||
const cost = [];
|
const cost = [];
|
||||||
while (queue.length) {
|
while (queue.length) {
|
||||||
const next = queue.dequeue(), n = next.e, p = next.p, c = next.c;
|
const next = queue.dequeue(),
|
||||||
|
n = next.e,
|
||||||
|
p = next.p,
|
||||||
|
c = next.c;
|
||||||
const type = pack.cultures[c].type;
|
const type = pack.cultures[c].type;
|
||||||
cells.c[n].forEach(function (e) {
|
cells.c[n].forEach(function (e) {
|
||||||
const biome = cells.biome[e];
|
const biome = cells.biome[e];
|
||||||
|
|
@ -380,8 +407,8 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
TIME && console.timeEnd('expandCultures');
|
TIME && console.timeEnd("expandCultures");
|
||||||
}
|
};
|
||||||
|
|
||||||
function getBiomeCost(c, biome, type) {
|
function getBiomeCost(c, biome, type) {
|
||||||
if (cells.biome[pack.cultures[c].center] === biome) return 10; // tiny penalty for native biome
|
if (cells.biome[pack.cultures[c].center] === biome) return 10; // tiny penalty for native biome
|
||||||
|
|
@ -391,7 +418,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function getHeightCost(i, h, type) {
|
function getHeightCost(i, h, type) {
|
||||||
const f = pack.features[cells.f[i]], a = cells.area[i];
|
const f = pack.features[cells.f[i]],
|
||||||
|
a = cells.area[i];
|
||||||
if (type === "Lake" && f.type === "lake") return 10; // no lake crossing penalty for Lake cultures
|
if (type === "Lake" && f.type === "lake") return 10; // no lake crossing penalty for Lake cultures
|
||||||
if (type === "Naval" && h < 20) return a * 2; // low sea/lake crossing penalty for Naval cultures
|
if (type === "Naval" && h < 20) return a * 2; // low sea/lake crossing penalty for Naval cultures
|
||||||
if (type === "Nomadic" && h < 20) return a * 50; // giant sea/lake crossing penalty for Nomads
|
if (type === "Nomadic" && h < 20) return a * 50; // giant sea/lake crossing penalty for Nomads
|
||||||
|
|
@ -407,7 +435,7 @@
|
||||||
function getRiverCost(r, i, type) {
|
function getRiverCost(r, i, type) {
|
||||||
if (type === "River") return r ? 0 : 100; // penalty for river cultures
|
if (type === "River") return r ? 0 : 100; // penalty for river cultures
|
||||||
if (!r) return 0; // no penalty for others if there is no river
|
if (!r) return 0; // no penalty for others if there is no river
|
||||||
return Math.min(Math.max(cells.fl[i] / 10, 20), 100) // river penalty from 20 to 100 based on flux
|
return Math.min(Math.max(cells.fl[i] / 10, 20), 100); // river penalty from 20 to 100 based on flux
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTypeCost(t, type) {
|
function getTypeCost(t, type) {
|
||||||
|
|
@ -420,8 +448,7 @@
|
||||||
const getRandomShield = function () {
|
const getRandomShield = function () {
|
||||||
const type = rw(COA.shields.types);
|
const type = rw(COA.shields.types);
|
||||||
return rw(COA.shields[type]);
|
return rw(COA.shields[type]);
|
||||||
}
|
};
|
||||||
|
|
||||||
return {generate, add, expand, getDefault, getRandomShield};
|
return {generate, add, expand, getDefault, getRandomShield};
|
||||||
|
})();
|
||||||
})));
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
let cells, p;
|
||||||
|
|
||||||
const generate = function () {
|
const generate = function () {
|
||||||
|
|
@ -12,262 +10,63 @@
|
||||||
cells.h = new Uint8Array(grid.points.length);
|
cells.h = new Uint8Array(grid.points.length);
|
||||||
|
|
||||||
const template = document.getElementById("templateInput").value;
|
const template = document.getElementById("templateInput").value;
|
||||||
switch (template) {
|
const templateString = HeightmapTemplates[template];
|
||||||
case "Volcano":
|
const steps = templateString.split("\n");
|
||||||
templateVolcano();
|
|
||||||
break;
|
if (!steps.length) throw new Error(`Heightmap template: no steps. Template: ${template}. Steps: ${steps}`);
|
||||||
case "High Island":
|
|
||||||
templateHighIsland();
|
for (const step of steps) {
|
||||||
break;
|
const elements = step.trim().split(" ");
|
||||||
case "Low Island":
|
if (elements.length < 2) throw new Error(`Heightmap template: steps < 2. Template: ${template}. Step: ${elements}`);
|
||||||
templateLowIsland();
|
addStep(...elements);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TIME && console.timeEnd("generateHeightmap");
|
TIME && console.timeEnd("generateHeightmap");
|
||||||
};
|
};
|
||||||
|
|
||||||
// parse template step
|
|
||||||
function addStep(a1, a2, a3, a4, a5) {
|
function addStep(a1, a2, a3, a4, a5) {
|
||||||
if (a1 === "Hill") return addHill(a2, a3, a4, a5);
|
if (a1 === "Hill") return addHill(a2, a3, a4, a5);
|
||||||
if (a1 === "Pit") return addPit(a2, a3, a4, a5);
|
if (a1 === "Pit") return addPit(a2, a3, a4, a5);
|
||||||
if (a1 === "Range") return addRange(a2, a3, a4, a5);
|
if (a1 === "Range") return addRange(a2, a3, a4, a5);
|
||||||
if (a1 === "Trough") return addTrough(a2, a3, a4, a5);
|
if (a1 === "Trough") return addTrough(a2, a3, a4, a5);
|
||||||
if (a1 === "Strait") return addStrait(a2, a3);
|
if (a1 === "Strait") return addStrait(a2, a3);
|
||||||
if (a1 === "Add") return modify(a3, a2, 1);
|
if (a1 === "Add") return modify(a3, +a2, 1);
|
||||||
if (a1 === "Multiply") return modify(a3, 0, a2);
|
if (a1 === "Multiply") return modify(a3, 0, +a2);
|
||||||
if (a1 === "Smooth") return smooth(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() {
|
function getBlobPower() {
|
||||||
switch (+pointsInput.dataset.cells) {
|
const cells = +pointsInput.dataset.cells;
|
||||||
case 1000:
|
if (cells === 1000) return 0.93;
|
||||||
return 0.93;
|
if (cells === 2000) return 0.95;
|
||||||
case 2000:
|
if (cells === 5000) return 0.96;
|
||||||
return 0.95;
|
if (cells === 10000) return 0.98;
|
||||||
case 5000:
|
if (cells === 20000) return 0.985;
|
||||||
return 0.96;
|
if (cells === 30000) return 0.987;
|
||||||
case 10000:
|
if (cells === 40000) return 0.9892;
|
||||||
return 0.98;
|
if (cells === 50000) return 0.9911;
|
||||||
case 20000:
|
if (cells === 60000) return 0.9921;
|
||||||
return 0.985;
|
if (cells === 70000) return 0.9934;
|
||||||
case 30000:
|
if (cells === 80000) return 0.9942;
|
||||||
return 0.987;
|
if (cells === 90000) return 0.9946;
|
||||||
case 40000:
|
if (cells === 100000) return 0.995;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getLinePower() {
|
function getLinePower() {
|
||||||
switch (+pointsInput.dataset.cells) {
|
const cells = +pointsInput.dataset.cells;
|
||||||
case 1000:
|
if (cells === 1000) return 0.74;
|
||||||
return 0.74;
|
if (cells === 2000) return 0.75;
|
||||||
case 2000:
|
if (cells === 5000) return 0.78;
|
||||||
return 0.75;
|
if (cells === 10000) return 0.81;
|
||||||
case 5000:
|
if (cells === 20000) return 0.82;
|
||||||
return 0.78;
|
if (cells === 30000) return 0.83;
|
||||||
case 10000:
|
if (cells === 40000) return 0.84;
|
||||||
return 0.81;
|
if (cells === 50000) return 0.855;
|
||||||
case 20000:
|
if (cells === 60000) return 0.87;
|
||||||
return 0.82;
|
if (cells === 70000) return 0.885;
|
||||||
case 30000:
|
if (cells === 80000) return 0.91;
|
||||||
return 0.83;
|
if (cells === 90000) return 0.92;
|
||||||
case 40000:
|
if (cells === 100000) return 0.93;
|
||||||
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 addHill = function (count, height, rangeX, rangeY) {
|
const addHill = function (count, height, rangeX, rangeY) {
|
||||||
|
|
@ -610,4 +409,4 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
return {generate, addHill, addRange, addTrough, addStrait, addPit, smooth, modify};
|
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 setClimateData = function (h) {
|
||||||
const cells = pack.cells;
|
const cells = pack.cells;
|
||||||
const lakeOutCells = new Uint16Array(cells.i.length);
|
const lakeOutCells = new Uint16Array(cells.i.length);
|
||||||
|
|
@ -149,4 +147,4 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
return {setClimateData, cleanupLakeData, prepareLakeData, defineGroup, generateName, getName, getShoreline};
|
return {setClimateData, cleanupLakeData, prepareLakeData, defineGroup, generateName, getName, getShoreline};
|
||||||
});
|
})();
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,7 @@ function parseLoadedData(data) {
|
||||||
if (settings[20]) mapName.value = settings[20];
|
if (settings[20]) mapName.value = settings[20];
|
||||||
if (settings[21]) hideLabels.checked = +settings[21];
|
if (settings[21]) hideLabels.checked = +settings[21];
|
||||||
if (settings[22]) stylePreset.value = settings[22];
|
if (settings[22]) stylePreset.value = settings[22];
|
||||||
|
if (settings[23]) rescaleLabels.checked = settings[23];
|
||||||
})();
|
})();
|
||||||
|
|
||||||
void (function parseConfiguration() {
|
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 () {
|
const generate = function () {
|
||||||
TIME && console.time("generateMilitaryForces");
|
TIME && console.time("generateMilitaryForces");
|
||||||
const cells = pack.cells,
|
const cells = pack.cells,
|
||||||
|
|
@ -371,4 +369,4 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
return {generate, getDefaultOptions, getName, generateNote, drawRegiments, drawRegiment, moveRegiment, getTotal, getEmblem};
|
return {generate, getDefaultOptions, getName, generateNote, drawRegiments, drawRegiment, moveRegiment, getTotal, getEmblem};
|
||||||
});
|
})();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
(function (global, factory) {
|
|
||||||
typeof exports === "object" && typeof module !== "undefined" ? (module.exports = factory()) : typeof define === "function" && define.amd ? define(factory) : (global.Names = factory());
|
|
||||||
})(this, function () {
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
window.Names = (function () {
|
||||||
let chains = [];
|
let chains = [];
|
||||||
|
|
||||||
// calculate Markov chain for a namesbase
|
// calculate Markov chain for a namesbase
|
||||||
|
|
@ -294,4 +293,4 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
return {getBase, getCulture, getCultureShort, getBaseShort, getState, updateChain, clearChains, getNameBases, getMapName, calculateChain};
|
return {getBase, getCulture, getCultureShort, getBaseShort, getState, updateChain, clearChains, getNameBases, getMapName, calculateChain};
|
||||||
});
|
})();
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
(function (global, factory) {
|
|
||||||
typeof exports === "object" && typeof module !== "undefined" ? (module.exports = factory()) : typeof define === "function" && define.amd ? define(factory) : (global.OceanLayers = factory());
|
|
||||||
})(this, function () {
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
window.OceanLayers = (function () {
|
||||||
let cells, vertices, pointsN, used;
|
let cells, vertices, pointsN, used;
|
||||||
|
|
||||||
const OceanLayers = function OceanLayers() {
|
const OceanLayers = function OceanLayers() {
|
||||||
|
|
@ -91,4 +89,4 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
return OceanLayers;
|
return OceanLayers;
|
||||||
});
|
})();
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
(function (global, factory) {
|
|
||||||
typeof exports === "object" && typeof module !== "undefined" ? (module.exports = factory()) : typeof define === "function" && define.amd ? define(factory) : (global.ReliefIcons = factory());
|
|
||||||
})(this, function () {
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
window.ReliefIcons = (function () {
|
||||||
const ReliefIcons = function () {
|
const ReliefIcons = function () {
|
||||||
TIME && console.time("drawRelief");
|
TIME && console.time("drawRelief");
|
||||||
terrain.selectAll("*").remove();
|
terrain.selectAll("*").remove();
|
||||||
|
|
@ -127,4 +125,4 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
return ReliefIcons;
|
return ReliefIcons;
|
||||||
});
|
})();
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,8 @@
|
||||||
(function (global, factory) {
|
"use strict";
|
||||||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
|
||||||
typeof define === 'function' && define.amd ? define(factory) :
|
|
||||||
(global.Religions = factory());
|
|
||||||
}(this, (function () {'use strict';
|
|
||||||
|
|
||||||
|
window.Religions = (function () {
|
||||||
// name generation approach and relative chance to be selected
|
// name generation approach and relative chance to be selected
|
||||||
const approach = {"Number":1, "Being":3, "Adjective":5, "Color + Animal":5,
|
const approach = {Number: 1, Being: 3, Adjective: 5, "Color + Animal": 5, "Adjective + Animal": 5, "Adjective + Being": 5, "Adjective + Genitive": 1, "Color + Being": 3, "Color + Genitive": 3, "Being + of + Genitive": 2, "Being + of the + Genitive": 1, "Animal + of + Genitive": 1, "Adjective + Being + of + Genitive": 2, "Adjective + Animal + of + Genitive": 2};
|
||||||
"Adjective + Animal":5, "Adjective + Being":5, "Adjective + Genitive":1,
|
|
||||||
"Color + Being":3, "Color + Genitive":3, "Being + of + Genitive":2, "Being + of the + Genitive":1,
|
|
||||||
"Animal + of + Genitive":1, "Adjective + Being + of + Genitive":2, "Adjective + Animal + of + Genitive":2};
|
|
||||||
|
|
||||||
// turn weighted array into simple array
|
// turn weighted array into simple array
|
||||||
const approaches = [];
|
const approaches = [];
|
||||||
|
|
@ -29,59 +23,65 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
const forms = {
|
const forms = {
|
||||||
Folk:{"Shamanism":2, "Animism":2, "Ancestor worship":1, "Polytheism":2},
|
Folk: {Shamanism: 2, Animism: 2, "Ancestor worship": 1, Polytheism: 2},
|
||||||
Organized:{"Polytheism":5, "Dualism":1, "Monotheism":4, "Non-theism":1},
|
Organized: {Polytheism: 5, Dualism: 1, Monotheism: 4, "Non-theism": 1},
|
||||||
Cult:{"Cult":1, "Dark Cult":1},
|
Cult: {Cult: 1, "Dark Cult": 1},
|
||||||
Heresy:{"Heresy":1}
|
Heresy: {Heresy: 1}
|
||||||
};
|
};
|
||||||
|
|
||||||
const methods = {"Random + type": 3, "Random + ism": 1, "Supreme + ism": 5, "Faith of + Supreme": 5, "Place + ism": 1, "Culture + ism": 2, "Place + ian + type": 6, "Culture + type": 4};
|
const methods = {"Random + type": 3, "Random + ism": 1, "Supreme + ism": 5, "Faith of + Supreme": 5, "Place + ism": 1, "Culture + ism": 2, "Place + ian + type": 6, "Culture + type": 4};
|
||||||
|
|
||||||
const types = {
|
const types = {
|
||||||
"Shamanism":{"Beliefs":3, "Shamanism":2, "Spirits":1},
|
Shamanism: {Beliefs: 3, Shamanism: 2, Spirits: 1},
|
||||||
"Animism":{"Spirits":1, "Beliefs":1},
|
Animism: {Spirits: 1, Beliefs: 1},
|
||||||
"Ancestor worship":{"Beliefs":1, "Forefathers":2, "Ancestors":2},
|
"Ancestor worship": {Beliefs: 1, Forefathers: 2, Ancestors: 2},
|
||||||
"Polytheism":{"Deities":3, "Faith":1, "Gods":1, "Pantheon":1},
|
Polytheism: {Deities: 3, Faith: 1, Gods: 1, Pantheon: 1},
|
||||||
|
|
||||||
"Dualism":{"Religion":3, "Faith":1, "Cult":1},
|
Dualism: {Religion: 3, Faith: 1, Cult: 1},
|
||||||
"Monotheism":{"Religion":1, "Church":1},
|
Monotheism: {Religion: 1, Church: 1},
|
||||||
"Non-theism":{"Beliefs":3, "Spirits":1},
|
"Non-theism": {Beliefs: 3, Spirits: 1},
|
||||||
|
|
||||||
"Cult":{"Cult":4, "Sect":4, "Worship":1, "Orden":1, "Coterie":1, "Arcanum":1},
|
Cult: {Cult: 4, Sect: 4, Worship: 1, Orden: 1, Coterie: 1, Arcanum: 1},
|
||||||
"Dark Cult":{"Cult":2, "Sect":2, "Occultism":1, "Idols":1, "Coven":1, "Circle":1, "Blasphemy":1},
|
"Dark Cult": {Cult: 2, Sect: 2, Occultism: 1, Idols: 1, Coven: 1, Circle: 1, Blasphemy: 1},
|
||||||
|
|
||||||
"Heresy":{"Heresy":3, "Sect":2, "Schism":1, "Dissenters":1, "Circle":1, "Brotherhood":1, "Society":1, "Iconoclasm":1, "Dissent":1, "Apostates":1}
|
Heresy: {Heresy: 3, Sect: 2, Schism: 1, Dissenters: 1, Circle: 1, Brotherhood: 1, Society: 1, Iconoclasm: 1, Dissent: 1, Apostates: 1}
|
||||||
};
|
};
|
||||||
|
|
||||||
const generate = function () {
|
const generate = function () {
|
||||||
TIME && console.time('generateReligions');
|
TIME && console.time("generateReligions");
|
||||||
const cells = pack.cells, states = pack.states, cultures = pack.cultures;
|
const cells = pack.cells,
|
||||||
const religions = pack.religions = [];
|
states = pack.states,
|
||||||
|
cultures = pack.cultures;
|
||||||
|
const religions = (pack.religions = []);
|
||||||
cells.religion = new Uint16Array(cells.culture); // cell religion; initially based on culture
|
cells.religion = new Uint16Array(cells.culture); // cell religion; initially based on culture
|
||||||
|
|
||||||
// add folk religions
|
// add folk religions
|
||||||
pack.cultures.forEach(c => {
|
pack.cultures.forEach(c => {
|
||||||
if (!c.i) {religions.push({i: 0, name: "No religion"}); return;}
|
if (!c.i) {
|
||||||
if (c.removed) {religions.push({i: c.i, name: "Extinct religion for "+c.name, color:getMixedColor(c.color, .1, 0), removed:true}); return;}
|
religions.push({i: 0, name: "No religion"});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (c.removed) {
|
||||||
|
religions.push({i: c.i, name: "Extinct religion for " + c.name, color: getMixedColor(c.color, 0.1, 0), removed: true});
|
||||||
|
return;
|
||||||
|
}
|
||||||
const form = rw(forms.Folk);
|
const form = rw(forms.Folk);
|
||||||
const name = c.name + " " + rw(types[form]);
|
const name = c.name + " " + rw(types[form]);
|
||||||
const deity = form === "Animism" ? null : getDeityName(c.i);
|
const deity = form === "Animism" ? null : getDeityName(c.i);
|
||||||
const color = getMixedColor(c.color, .1, 0); // `url(#hatch${rand(8,13)})`;
|
const color = getMixedColor(c.color, 0.1, 0); // `url(#hatch${rand(8,13)})`;
|
||||||
religions.push({i: c.i, name, color, culture: c.i, type: "Folk", form, deity, center: c.center, origin: 0});
|
religions.push({i: c.i, name, color, culture: c.i, type: "Folk", form, deity, center: c.center, origin: 0});
|
||||||
});
|
});
|
||||||
|
|
||||||
if (religionsInput.value == 0 || pack.cultures.length < 2) {
|
if (religionsInput.value == 0 || pack.cultures.length < 2) {
|
||||||
religions.filter(r => r.i).forEach(r => r.code = abbreviate(r.name));
|
religions.filter(r => r.i).forEach(r => (r.code = abbreviate(r.name)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const burgs = pack.burgs.filter(b => b.i && !b.removed);
|
const burgs = pack.burgs.filter(b => b.i && !b.removed);
|
||||||
const sorted = burgs.length > +religionsInput.value
|
const sorted = burgs.length > +religionsInput.value ? burgs.sort((a, b) => b.population - a.population).map(b => b.cell) : cells.i.filter(i => cells.s[i] > 2).sort((a, b) => cells.s[b] - cells.s[a]);
|
||||||
? burgs.sort((a, b) => b.population - a.population).map(b => b.cell)
|
|
||||||
: cells.i.filter(i => cells.s[i] > 2).sort((a, b) => cells.s[b] - cells.s[a]);
|
|
||||||
const religionsTree = d3.quadtree();
|
const religionsTree = d3.quadtree();
|
||||||
const spacing = (graphWidth + graphHeight) / 6 / religionsInput.value; // base min distance between towns
|
const spacing = (graphWidth + graphHeight) / 6 / religionsInput.value; // base min distance between towns
|
||||||
const cultsCount = Math.floor(rand(10, 40) / 100 * religionsInput.value);
|
const cultsCount = Math.floor((rand(10, 40) / 100) * religionsInput.value);
|
||||||
const count = +religionsInput.value - cultsCount + religions.length;
|
const count = +religionsInput.value - cultsCount + religions.length;
|
||||||
|
|
||||||
// generate organized religions
|
// generate organized religions
|
||||||
|
|
@ -96,13 +96,14 @@
|
||||||
if (expansion === "state" && !state) expansion = "global";
|
if (expansion === "state" && !state) expansion = "global";
|
||||||
if (expansion === "culture" && !culture) expansion = "global";
|
if (expansion === "culture" && !culture) expansion = "global";
|
||||||
|
|
||||||
if (expansion === "state" && Math.random() > .5) center = states[state].center;
|
if (expansion === "state" && Math.random() > 0.5) center = states[state].center;
|
||||||
if (expansion === "culture" && Math.random() > .5) center = cultures[culture].center;
|
if (expansion === "culture" && Math.random() > 0.5) center = cultures[culture].center;
|
||||||
|
|
||||||
if (!cells.burg[center] && cells.c[center].some(c => cells.burg[c])) center = cells.c[center].find(c => cells.burg[c]);
|
if (!cells.burg[center] && cells.c[center].some(c => cells.burg[c])) center = cells.c[center].find(c => cells.burg[c]);
|
||||||
const x = cells.p[center][0], y = cells.p[center][1];
|
const x = cells.p[center][0],
|
||||||
|
y = cells.p[center][1];
|
||||||
|
|
||||||
const s = spacing * gauss(1, .3, .2, 2, 2); // randomize to make the placement not uniform
|
const s = spacing * gauss(1, 0.3, 0.2, 2, 2); // randomize to make the placement not uniform
|
||||||
if (religionsTree.find(x, y, s) !== undefined) continue; // to close to existing religion
|
if (religionsTree.find(x, y, s) !== undefined) continue; // to close to existing religion
|
||||||
|
|
||||||
// add "Old" to name of the folk religion on this culture
|
// add "Old" to name of the folk religion on this culture
|
||||||
|
|
@ -111,7 +112,7 @@
|
||||||
const origin = folk ? folk.i : 0;
|
const origin = folk ? folk.i : 0;
|
||||||
|
|
||||||
const expansionism = rand(3, 8);
|
const expansionism = rand(3, 8);
|
||||||
const color = getMixedColor(religions[origin].color, .3, 0); // `url(#hatch${rand(0,5)})`;
|
const color = getMixedColor(religions[origin].color, 0.3, 0); // `url(#hatch${rand(0,5)})`;
|
||||||
religions.push({i: religions.length, name, color, culture, type: "Organized", form, deity, expansion, expansionism, center, origin});
|
religions.push({i: religions.length, name, color, culture, type: "Organized", form, deity, expansion, expansionism, center, origin});
|
||||||
religionsTree.add([x, y]);
|
religionsTree.add([x, y]);
|
||||||
}
|
}
|
||||||
|
|
@ -121,9 +122,10 @@
|
||||||
const form = rw(forms.Cult);
|
const form = rw(forms.Cult);
|
||||||
let center = sorted[biased(0, sorted.length - 1, 1)]; // religion center
|
let center = sorted[biased(0, sorted.length - 1, 1)]; // religion center
|
||||||
if (!cells.burg[center] && cells.c[center].some(c => cells.burg[c])) center = cells.c[center].find(c => cells.burg[c]);
|
if (!cells.burg[center] && cells.c[center].some(c => cells.burg[c])) center = cells.c[center].find(c => cells.burg[c]);
|
||||||
const x = cells.p[center][0], y = cells.p[center][1];
|
const x = cells.p[center][0],
|
||||||
|
y = cells.p[center][1];
|
||||||
|
|
||||||
const s = spacing * gauss(2, .3, 1, 3, 2); // randomize to make the placement not uniform
|
const s = spacing * gauss(2, 0.3, 1, 3, 2); // randomize to make the placement not uniform
|
||||||
if (religionsTree.find(x, y, s) !== undefined) continue; // to close to existing religion
|
if (religionsTree.find(x, y, s) !== undefined) continue; // to close to existing religion
|
||||||
|
|
||||||
const culture = cells.culture[center];
|
const culture = cells.culture[center];
|
||||||
|
|
@ -131,8 +133,8 @@
|
||||||
const origin = folk ? folk.i : 0;
|
const origin = folk ? folk.i : 0;
|
||||||
const deity = getDeityName(culture);
|
const deity = getDeityName(culture);
|
||||||
const name = getCultName(form, center);
|
const name = getCultName(form, center);
|
||||||
const expansionism = gauss(1.1, .5, 0, 5);
|
const expansionism = gauss(1.1, 0.5, 0, 5);
|
||||||
const color = getMixedColor(cultures[culture].color, .5, 0); // "url(#hatch7)";
|
const color = getMixedColor(cultures[culture].color, 0.5, 0); // "url(#hatch7)";
|
||||||
religions.push({i: religions.length, name, color, culture, type: "Cult", form, deity, expansion: "global", expansionism, center, origin});
|
religions.push({i: religions.length, name, color, culture, type: "Cult", form, deity, expansion: "global", expansionism, center, origin});
|
||||||
religionsTree.add([x, y]);
|
religionsTree.add([x, y]);
|
||||||
//debug.append("circle").attr("cx", x).attr("cy", y).attr("r", 2).attr("fill", "red");
|
//debug.append("circle").attr("cx", x).attr("cy", y).attr("r", 2).attr("fill", "red");
|
||||||
|
|
@ -141,20 +143,23 @@
|
||||||
expandReligions();
|
expandReligions();
|
||||||
|
|
||||||
// generate heresies
|
// generate heresies
|
||||||
religions.filter(r => r.type === "Organized").forEach(r => {
|
religions
|
||||||
|
.filter(r => r.type === "Organized")
|
||||||
|
.forEach(r => {
|
||||||
if (r.expansionism < 3) return;
|
if (r.expansionism < 3) return;
|
||||||
const count = gauss(0, 1, 0, 3);
|
const count = gauss(0, 1, 0, 3);
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
let center = ra(cells.i.filter(i => cells.religion[i] === r.i && cells.c[i].some(c => cells.religion[c] !== r.i)));
|
let center = ra(cells.i.filter(i => cells.religion[i] === r.i && cells.c[i].some(c => cells.religion[c] !== r.i)));
|
||||||
if (!center) continue;
|
if (!center) continue;
|
||||||
if (!cells.burg[center] && cells.c[center].some(c => cells.burg[c])) center = cells.c[center].find(c => cells.burg[c]);
|
if (!cells.burg[center] && cells.c[center].some(c => cells.burg[c])) center = cells.c[center].find(c => cells.burg[c]);
|
||||||
const x = cells.p[center][0], y = cells.p[center][1];
|
const x = cells.p[center][0],
|
||||||
|
y = cells.p[center][1];
|
||||||
if (religionsTree.find(x, y, spacing / 10) !== undefined) continue; // to close to other
|
if (religionsTree.find(x, y, spacing / 10) !== undefined) continue; // to close to other
|
||||||
|
|
||||||
const culture = cells.culture[center];
|
const culture = cells.culture[center];
|
||||||
const name = getCultName("Heresy", center);
|
const name = getCultName("Heresy", center);
|
||||||
const expansionism = gauss(1.2, .5, 0, 5);
|
const expansionism = gauss(1.2, 0.5, 0, 5);
|
||||||
const color = getMixedColor(r.color, .4, .2); // "url(#hatch6)";
|
const color = getMixedColor(r.color, 0.4, 0.2); // "url(#hatch6)";
|
||||||
religions.push({i: religions.length, name, color, culture, type: "Heresy", form: r.form, deity: r.deity, expansion: "global", expansionism, center, origin: r.i});
|
religions.push({i: religions.length, name, color, culture, type: "Heresy", form: r.form, deity: r.deity, expansion: "global", expansionism, center, origin: r.i});
|
||||||
religionsTree.add([x, y]);
|
religionsTree.add([x, y]);
|
||||||
//debug.append("circle").attr("cx", x).attr("cy", y).attr("r", 2).attr("fill", "green");
|
//debug.append("circle").attr("cx", x).attr("cy", y).attr("r", 2).attr("fill", "green");
|
||||||
|
|
@ -164,46 +169,61 @@
|
||||||
expandHeresies();
|
expandHeresies();
|
||||||
checkCenters();
|
checkCenters();
|
||||||
|
|
||||||
TIME && console.timeEnd('generateReligions');
|
TIME && console.timeEnd("generateReligions");
|
||||||
}
|
};
|
||||||
|
|
||||||
const add = function (center) {
|
const add = function (center) {
|
||||||
const cells = pack.cells, religions = pack.religions;
|
const cells = pack.cells,
|
||||||
|
religions = pack.religions;
|
||||||
const r = cells.religion[center];
|
const r = cells.religion[center];
|
||||||
const i = religions.length;
|
const i = religions.length;
|
||||||
const culture = cells.culture[center];
|
const culture = cells.culture[center];
|
||||||
const color = getMixedColor(religions[r].color, .3, 0);
|
const color = getMixedColor(religions[r].color, 0.3, 0);
|
||||||
|
|
||||||
const type = religions[r].type === "Organized" ? rw({Organized: 4, Cult: 1, Heresy: 2}) : rw({Organized: 5, Cult: 2});
|
const type = religions[r].type === "Organized" ? rw({Organized: 4, Cult: 1, Heresy: 2}) : rw({Organized: 5, Cult: 2});
|
||||||
const form = rw(forms[type]);
|
const form = rw(forms[type]);
|
||||||
const deity = type === "Heresy" ? religions[r].deity : form === "Non-theism" ? null : getDeityName(culture);
|
const deity = type === "Heresy" ? religions[r].deity : form === "Non-theism" ? null : getDeityName(culture);
|
||||||
|
|
||||||
let name, expansion;
|
let name, expansion;
|
||||||
if (type === "Organized") [name, expansion] = getReligionName(form, deity, center)
|
if (type === "Organized") [name, expansion] = getReligionName(form, deity, center);
|
||||||
else {name = getCultName(form, center); expansion = "global";}
|
else {
|
||||||
|
name = getCultName(form, center);
|
||||||
|
expansion = "global";
|
||||||
|
}
|
||||||
const formName = type === "Heresy" ? religions[r].form : form;
|
const formName = type === "Heresy" ? religions[r].form : form;
|
||||||
const code = abbreviate(name, religions.map(r => r.code));
|
const code = abbreviate(
|
||||||
|
name,
|
||||||
|
religions.map(r => r.code)
|
||||||
|
);
|
||||||
religions.push({i, name, color, culture, type, form: formName, deity, expansion, expansionism: 0, center, cells: 0, area: 0, rural: 0, urban: 0, origin: r, code});
|
religions.push({i, name, color, culture, type, form: formName, deity, expansion, expansionism: 0, center, cells: 0, area: 0, rural: 0, urban: 0, origin: r, code});
|
||||||
cells.religion[center] = i;
|
cells.religion[center] = i;
|
||||||
}
|
};
|
||||||
|
|
||||||
// growth algorithm to assign cells to religions
|
// growth algorithm to assign cells to religions
|
||||||
const expandReligions = function () {
|
const expandReligions = function () {
|
||||||
const cells = pack.cells, religions = pack.religions;
|
const cells = pack.cells,
|
||||||
|
religions = pack.religions;
|
||||||
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
|
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
|
||||||
const cost = [];
|
const cost = [];
|
||||||
|
|
||||||
religions.filter(r => r.type === "Organized" || r.type === "Cult").forEach(r => {
|
religions
|
||||||
|
.filter(r => r.type === "Organized" || r.type === "Cult")
|
||||||
|
.forEach(r => {
|
||||||
cells.religion[r.center] = r.i;
|
cells.religion[r.center] = r.i;
|
||||||
queue.queue({e: r.center, p: 0, r: r.i, s: cells.state[r.center], c: r.culture});
|
queue.queue({e: r.center, p: 0, r: r.i, s: cells.state[r.center], c: r.culture});
|
||||||
cost[r.center] = 1;
|
cost[r.center] = 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
const neutral = cells.i.length / 5000 * 200 * gauss(1, .3, .2, 2, 2) * neutralInput.value; // limit cost for organized religions growth
|
const neutral = (cells.i.length / 5000) * 200 * gauss(1, 0.3, 0.2, 2, 2) * neutralInput.value; // limit cost for organized religions growth
|
||||||
const popCost = d3.max(cells.pop) / 3; // enougth population to spered religion without penalty
|
const popCost = d3.max(cells.pop) / 3; // enougth population to spered religion without penalty
|
||||||
|
|
||||||
while (queue.length) {
|
while (queue.length) {
|
||||||
const next = queue.dequeue(), n = next.e, p = next.p, r = next.r, c = next.c, s = next.s;
|
const next = queue.dequeue(),
|
||||||
|
n = next.e,
|
||||||
|
p = next.p,
|
||||||
|
r = next.r,
|
||||||
|
c = next.c,
|
||||||
|
s = next.s;
|
||||||
const expansion = religions[r].expansion;
|
const expansion = religions[r].expansion;
|
||||||
|
|
||||||
cells.c[n].forEach(function (e) {
|
cells.c[n].forEach(function (e) {
|
||||||
|
|
@ -215,7 +235,7 @@
|
||||||
const biomeCost = cells.road[e] ? 1 : biomesData.cost[cells.biome[e]];
|
const biomeCost = cells.road[e] ? 1 : biomesData.cost[cells.biome[e]];
|
||||||
const populationCost = Math.max(rn(popCost - cells.pop[e]), 0);
|
const populationCost = Math.max(rn(popCost - cells.pop[e]), 0);
|
||||||
const heightCost = Math.max(cells.h[e], 20) - 20;
|
const heightCost = Math.max(cells.h[e], 20) - 20;
|
||||||
const waterCost = cells.h[e] < 20 ? cells.road[e] ? 50 : 1000 : 0;
|
const waterCost = cells.h[e] < 20 ? (cells.road[e] ? 50 : 1000) : 0;
|
||||||
const totalCost = p + (cultureCost + stateCost + biomeCost + populationCost + heightCost + waterCost) / religions[r].expansionism;
|
const totalCost = p + (cultureCost + stateCost + biomeCost + populationCost + heightCost + waterCost) / religions[r].expansionism;
|
||||||
if (totalCost > neutral) return;
|
if (totalCost > neutral) return;
|
||||||
|
|
||||||
|
|
@ -226,32 +246,39 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// growth algorithm to assign cells to heresies
|
// growth algorithm to assign cells to heresies
|
||||||
const expandHeresies = function () {
|
const expandHeresies = function () {
|
||||||
const cells = pack.cells, religions = pack.religions;
|
const cells = pack.cells,
|
||||||
|
religions = pack.religions;
|
||||||
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
|
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
|
||||||
const cost = [];
|
const cost = [];
|
||||||
|
|
||||||
religions.filter(r => r.type === "Heresy").forEach(r => {
|
religions
|
||||||
|
.filter(r => r.type === "Heresy")
|
||||||
|
.forEach(r => {
|
||||||
const b = cells.religion[r.center]; // "base" religion id
|
const b = cells.religion[r.center]; // "base" religion id
|
||||||
cells.religion[r.center] = r.i; // heresy id
|
cells.religion[r.center] = r.i; // heresy id
|
||||||
queue.queue({e: r.center, p: 0, r: r.i, b});
|
queue.queue({e: r.center, p: 0, r: r.i, b});
|
||||||
cost[r.center] = 1;
|
cost[r.center] = 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
const neutral = cells.i.length / 5000 * 500 * neutralInput.value; // limit cost for heresies growth
|
const neutral = (cells.i.length / 5000) * 500 * neutralInput.value; // limit cost for heresies growth
|
||||||
|
|
||||||
while (queue.length) {
|
while (queue.length) {
|
||||||
const next = queue.dequeue(), n = next.e, p = next.p, r = next.r, b = next.b;
|
const next = queue.dequeue(),
|
||||||
|
n = next.e,
|
||||||
|
p = next.p,
|
||||||
|
r = next.r,
|
||||||
|
b = next.b;
|
||||||
|
|
||||||
cells.c[n].forEach(function (e) {
|
cells.c[n].forEach(function (e) {
|
||||||
const religionCost = cells.religion[e] === b ? 0 : 2000;
|
const religionCost = cells.religion[e] === b ? 0 : 2000;
|
||||||
const biomeCost = cells.road[e] ? 0 : biomesData.cost[cells.biome[e]];
|
const biomeCost = cells.road[e] ? 0 : biomesData.cost[cells.biome[e]];
|
||||||
const heightCost = Math.max(cells.h[e], 20) - 20;
|
const heightCost = Math.max(cells.h[e], 20) - 20;
|
||||||
const waterCost = cells.h[e] < 20 ? cells.road[e] ? 50 : 1000 : 0;
|
const waterCost = cells.h[e] < 20 ? (cells.road[e] ? 50 : 1000) : 0;
|
||||||
const totalCost = p + (religionCost + biomeCost + heightCost + waterCost) / Math.max(religions[r].expansionism, .1);
|
const totalCost = p + (religionCost + biomeCost + heightCost + waterCost) / Math.max(religions[r].expansionism, 0.1);
|
||||||
|
|
||||||
if (totalCost > neutral) return;
|
if (totalCost > neutral) return;
|
||||||
|
|
||||||
|
|
@ -262,13 +289,16 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
function checkCenters() {
|
function checkCenters() {
|
||||||
const cells = pack.cells, religions = pack.religions;
|
const cells = pack.cells,
|
||||||
|
religions = pack.religions;
|
||||||
|
|
||||||
const codes = religions.map(r => r.code);
|
const codes = religions.map(r => r.code);
|
||||||
religions.filter(r => r.i).forEach(r => {
|
religions
|
||||||
|
.filter(r => r.i)
|
||||||
|
.forEach(r => {
|
||||||
r.code = abbreviate(r.name, codes);
|
r.code = abbreviate(r.name, codes);
|
||||||
|
|
||||||
// move religion center if it's not within religion area after expansion
|
// move religion center if it's not within religion area after expansion
|
||||||
|
|
@ -280,23 +310,26 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateCultures() {
|
function updateCultures() {
|
||||||
TIME && console.time('updateCulturesForReligions');
|
TIME && console.time("updateCulturesForReligions");
|
||||||
pack.religions = pack.religions.map((religion, index) => {
|
pack.religions = pack.religions.map((religion, index) => {
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
return religion;
|
return religion;
|
||||||
}
|
}
|
||||||
return {...religion, culture: pack.cells.culture[religion.center]};
|
return {...religion, culture: pack.cells.culture[religion.center]};
|
||||||
});
|
});
|
||||||
TIME && console.timeEnd('updateCulturesForReligions');
|
TIME && console.timeEnd("updateCulturesForReligions");
|
||||||
}
|
}
|
||||||
|
|
||||||
// get supreme deity name
|
// get supreme deity name
|
||||||
const getDeityName = function (culture) {
|
const getDeityName = function (culture) {
|
||||||
if (culture === undefined) {ERROR && console.error("Please define a culture"); return;}
|
if (culture === undefined) {
|
||||||
const meaning = generateMeaning();
|
ERROR && console.error("Please define a culture");
|
||||||
const cultureName = Names.getCulture(culture, null, null, "", .8);
|
return;
|
||||||
return cultureName + ", The " + meaning;
|
|
||||||
}
|
}
|
||||||
|
const meaning = generateMeaning();
|
||||||
|
const cultureName = Names.getCulture(culture, null, null, "", 0.8);
|
||||||
|
return cultureName + ", The " + meaning;
|
||||||
|
};
|
||||||
|
|
||||||
function generateMeaning() {
|
function generateMeaning() {
|
||||||
const a = ra(approaches); // select generation approach
|
const a = ra(approaches); // select generation approach
|
||||||
|
|
@ -318,21 +351,29 @@
|
||||||
|
|
||||||
function getReligionName(form, deity, center) {
|
function getReligionName(form, deity, center) {
|
||||||
const cells = pack.cells;
|
const cells = pack.cells;
|
||||||
const random = function() {return Names.getCulture(cells.culture[center], null, null, "", 0);}
|
const random = function () {
|
||||||
const type = function() {return rw(types[form]);}
|
return Names.getCulture(cells.culture[center], null, null, "", 0);
|
||||||
const supreme = function() {return deity.split(/[ ,]+/)[0];}
|
};
|
||||||
|
const type = function () {
|
||||||
|
return rw(types[form]);
|
||||||
|
};
|
||||||
|
const supreme = function () {
|
||||||
|
return deity.split(/[ ,]+/)[0];
|
||||||
|
};
|
||||||
const place = function (adj) {
|
const place = function (adj) {
|
||||||
const base = cells.burg[center] ? pack.burgs[cells.burg[center]].name : pack.states[cells.state[center]].name;
|
const base = cells.burg[center] ? pack.burgs[cells.burg[center]].name : pack.states[cells.state[center]].name;
|
||||||
let name = trimVowels(base.split(/[ ,]+/)[0]);
|
let name = trimVowels(base.split(/[ ,]+/)[0]);
|
||||||
return adj ? getAdjective(name) : name;
|
return adj ? getAdjective(name) : name;
|
||||||
}
|
};
|
||||||
const culture = function() {return pack.cultures[cells.culture[center]].name;}
|
const culture = function () {
|
||||||
|
return pack.cultures[cells.culture[center]].name;
|
||||||
|
};
|
||||||
|
|
||||||
const m = rw(methods);
|
const m = rw(methods);
|
||||||
if (m === "Random + type") return [random() + " " + type(), "global"];
|
if (m === "Random + type") return [random() + " " + type(), "global"];
|
||||||
if (m === "Random + ism") return [trimVowels(random()) + "ism", "global"];
|
if (m === "Random + ism") return [trimVowels(random()) + "ism", "global"];
|
||||||
if (m === "Supreme + ism" && deity) return [trimVowels(supreme()) + "ism", "global"];
|
if (m === "Supreme + ism" && deity) return [trimVowels(supreme()) + "ism", "global"];
|
||||||
if (m === "Faith of + Supreme" && deity) return [ra(['Faith', 'Way', 'Path', 'Word', 'Witnesses']) + " of " + supreme(), "global"];
|
if (m === "Faith of + Supreme" && deity) return [ra(["Faith", "Way", "Path", "Word", "Witnesses"]) + " of " + supreme(), "global"];
|
||||||
if (m === "Place + ism") return [place() + "ism", "state"];
|
if (m === "Place + ism") return [place() + "ism", "state"];
|
||||||
if (m === "Culture + ism") return [trimVowels(culture()) + "ism", "culture"];
|
if (m === "Culture + ism") return [trimVowels(culture()) + "ism", "culture"];
|
||||||
if (m === "Place + ian + type") return [place("adj") + " " + type(), "state"];
|
if (m === "Place + ian + type") return [place("adj") + " " + type(), "state"];
|
||||||
|
|
@ -342,14 +383,19 @@
|
||||||
|
|
||||||
function getCultName(form, center) {
|
function getCultName(form, center) {
|
||||||
const cells = pack.cells;
|
const cells = pack.cells;
|
||||||
const type = function() {return rw(types[form]);}
|
const type = function () {
|
||||||
const random = function() {return trimVowels(Names.getCulture(cells.culture[center], null, null, "", 0).split(/[ ,]+/)[0]);}
|
return rw(types[form]);
|
||||||
const burg = function() {return trimVowels(pack.burgs[cells.burg[center]].name.split(/[ ,]+/)[0]);}
|
|
||||||
if (cells.burg[center]) return burg() + "ian " + type();
|
|
||||||
if (Math.random() > .5) return random() + "ian " + type();
|
|
||||||
return type() + " of the " + generateMeaning();
|
|
||||||
};
|
};
|
||||||
|
const random = function () {
|
||||||
|
return trimVowels(Names.getCulture(cells.culture[center], null, null, "", 0).split(/[ ,]+/)[0]);
|
||||||
|
};
|
||||||
|
const burg = function () {
|
||||||
|
return trimVowels(pack.burgs[cells.burg[center]].name.split(/[ ,]+/)[0]);
|
||||||
|
};
|
||||||
|
if (cells.burg[center]) return burg() + "ian " + type();
|
||||||
|
if (Math.random() > 0.5) return random() + "ian " + type();
|
||||||
|
return type() + " of the " + generateMeaning();
|
||||||
|
}
|
||||||
|
|
||||||
return {generate, add, getDeityName, expandReligions, updateCultures};
|
return {generate, add, getDeityName, expandReligions, updateCultures};
|
||||||
|
})();
|
||||||
})));
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
(function (global, factory) {
|
|
||||||
typeof exports === "object" && typeof module !== "undefined" ? (module.exports = factory()) : typeof define === "function" && define.amd ? define(factory) : (global.Rivers = factory());
|
|
||||||
})(this, function () {
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
window.Rivers = (function () {
|
||||||
const generate = function (allowErosion = true) {
|
const generate = function (allowErosion = true) {
|
||||||
TIME && console.time("generateRivers");
|
TIME && console.time("generateRivers");
|
||||||
Math.random = aleaPRNG(seed);
|
Math.random = aleaPRNG(seed);
|
||||||
|
|
@ -442,4 +440,4 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
return {generate, alterHeights, resolveDepressions, addMeandering, getRiverPath, specify, getName, getType, getBasin, getWidth, getOffset, getApproximateLength, getRiverPoints, remove};
|
return {generate, alterHeights, resolveDepressions, addMeandering, getRiverPath, specify, getName, getType, getBasin, getWidth, getOffset, getApproximateLength, getRiverPoints, remove};
|
||||||
});
|
})();
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,9 @@
|
||||||
(function (global, factory) {
|
window.Routes = (function () {
|
||||||
typeof exports === "object" && typeof module !== "undefined" ? (module.exports = factory()) : typeof define === "function" && define.amd ? define(factory) : (global.Routes = factory());
|
|
||||||
})(this, function () {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const getRoads = function () {
|
const getRoads = function () {
|
||||||
TIME && console.time("generateMainRoads");
|
TIME && console.time("generateMainRoads");
|
||||||
const cells = pack.cells;
|
const cells = pack.cells;
|
||||||
const burgs = pack.burgs.filter(b => b.i && !b.removed);
|
const burgs = pack.burgs.filter(b => b.i && !b.removed);
|
||||||
const capitals = burgs.filter(b => b.capital)
|
const capitals = burgs.filter(b => b.capital).sort((a, b) => a.population - b.population);
|
||||||
.sort((a,b) => a.population - b.population);
|
|
||||||
|
|
||||||
if (capitals.length < 2) return []; // not enough capitals to build main roads
|
if (capitals.length < 2) return []; // not enough capitals to build main roads
|
||||||
const paths = []; // array to store path segments
|
const paths = []; // array to store path segments
|
||||||
|
|
@ -271,4 +266,4 @@
|
||||||
}
|
}
|
||||||
return [from, exit, false];
|
return [from, exit, false];
|
||||||
}
|
}
|
||||||
});
|
})();
|
||||||
|
|
|
||||||
|
|
@ -374,7 +374,7 @@ function getMapData() {
|
||||||
const dateString = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
|
const dateString = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
|
||||||
const license = "File can be loaded in azgaar.github.io/Fantasy-Map-Generator";
|
const license = "File can be loaded in azgaar.github.io/Fantasy-Map-Generator";
|
||||||
const params = [version, license, dateString, seed, graphWidth, graphHeight, mapId].join("|");
|
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 coords = JSON.stringify(mapCoordinates);
|
||||||
const biomes = [biomesData.color, biomesData.habitability, biomesData.name].join("|");
|
const biomes = [biomesData.color, biomesData.habitability, biomesData.name].join("|");
|
||||||
const notesData = JSON.stringify(notes);
|
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
|
// set default options
|
||||||
const options = {scale: 50, lightness: 0.7, shadow: 0.5, sun: {x: 100, y: 600, z: 1000}, rotateMesh: 0, rotateGlobe: 0.5, skyColor: "#9ecef5", waterColor: "#466eab", extendedWater: 0, labels3d: 0, resolution: 2};
|
const options = {scale: 50, lightness: 0.7, shadow: 0.5, sun: {x: 100, y: 600, z: 1000}, rotateMesh: 0, rotateGlobe: 0.5, skyColor: "#9ecef5", waterColor: "#466eab", extendedWater: 0, labels3d: 0, resolution: 2};
|
||||||
|
|
||||||
|
|
@ -581,4 +579,4 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
return {create, redraw, update, stop, options, setScale, setLightness, setSun, setRotation, toggleLabels, toggleSky, setResolution, setColors, saveScreenshot, saveOBJ};
|
return {create, redraw, update, stop, options, setScale, setLightness, setSun, setRotation, toggleLabels, toggleSky, setResolution, setColors, saveScreenshot, saveOBJ};
|
||||||
});
|
})();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
// heightmap-editor module. To be added to window as for now
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
function editHeightmap() {
|
function editHeightmap() {
|
||||||
|
|
@ -821,118 +820,15 @@ function editHeightmap() {
|
||||||
body.setAttribute("data-changed", 0);
|
body.setAttribute("data-changed", 0);
|
||||||
body.innerHTML = "";
|
body.innerHTML = "";
|
||||||
|
|
||||||
if (template === "templateVolcano") {
|
const templateString = HeightmapTemplates[template];
|
||||||
addStep("Hill", "1", "90-100", "44-56", "40-60");
|
if (!templateString) return;
|
||||||
addStep("Multiply", 0.8, "50-100");
|
|
||||||
addStep("Range", "1.5", "30-55", "45-55", "40-60");
|
const steps = templateString.split("\n");
|
||||||
addStep("Smooth", 2);
|
if (!steps.length) return tip(`Heightmap template: no steps defined`, false, "error");
|
||||||
addStep("Hill", "1.5", "25-35", "25-30", "20-75");
|
|
||||||
addStep("Hill", "1", "25-35", "75-80", "25-75");
|
for (const step of steps) {
|
||||||
addStep("Hill", "0.5", "20-25", "10-15", "20-25");
|
const elements = step.trim().split(" ");
|
||||||
} else if (template === "templateHighIsland") {
|
addStep(...elements);
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -122,9 +122,10 @@ function restoreLayers() {
|
||||||
if (layerIsOn("toggleIce")) drawIce();
|
if (layerIsOn("toggleIce")) drawIce();
|
||||||
if (layerIsOn("toggleEmblems")) drawEmblems();
|
if (layerIsOn("toggleEmblems")) drawEmblems();
|
||||||
|
|
||||||
// states are getting rendered each time, if it's not required than layers should be hidden
|
// some layers are rendered each time, remove them if they are not on
|
||||||
if (!layerIsOn("toggleBorders")) $("#borders").fadeOut();
|
if (!layerIsOn("toggleBorders")) borders.selectAll("path").remove();
|
||||||
if (!layerIsOn("toggleStates")) regions.style("display", "none").selectAll("path").remove();
|
if (!layerIsOn("toggleStates")) regions.selectAll("path").remove();
|
||||||
|
if (!layerIsOn("toggleRivers")) rivers.selectAll("*").remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleHeight(event) {
|
function toggleHeight(event) {
|
||||||
|
|
@ -1034,13 +1035,14 @@ function drawBorders() {
|
||||||
TIME && console.time("drawBorders");
|
TIME && console.time("drawBorders");
|
||||||
borders.selectAll("path").remove();
|
borders.selectAll("path").remove();
|
||||||
|
|
||||||
const cells = pack.cells,
|
const {cells, vertices} = pack;
|
||||||
vertices = pack.vertices,
|
const n = cells.i.length;
|
||||||
n = cells.i.length;
|
|
||||||
const sPath = [],
|
const sPath = [];
|
||||||
pPath = [];
|
const pPath = [];
|
||||||
const sUsed = new Array(pack.states.length).fill("").map(a => []);
|
|
||||||
const pUsed = new Array(pack.provinces.length).fill("").map(a => []);
|
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++) {
|
for (let i = 0; i < cells.i.length; i++) {
|
||||||
if (!cells.state[i]) continue;
|
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,
|
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,
|
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,
|
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
|
const array = supporters
|
||||||
.replace(/(?:\r\n|\r|\n)/g, "")
|
.replace(/(?:\r\n|\r|\n)/g, "")
|
||||||
|
|
@ -541,17 +542,18 @@ function randomizeOptions() {
|
||||||
// select heightmap template pseudo-randomly
|
// select heightmap template pseudo-randomly
|
||||||
function randomizeHeightmapTemplate() {
|
function randomizeHeightmapTemplate() {
|
||||||
const templates = {
|
const templates = {
|
||||||
Volcano: 3,
|
volcano: 3,
|
||||||
"High Island": 22,
|
highIsland: 22,
|
||||||
"Low Island": 9,
|
lowIsland: 9,
|
||||||
Continents: 20,
|
continents: 19,
|
||||||
Archipelago: 25,
|
archipelago: 23,
|
||||||
Mediterranean: 3,
|
mediterranean: 5,
|
||||||
Peninsula: 3,
|
peninsula: 3,
|
||||||
Pangea: 5,
|
pangea: 5,
|
||||||
Isthmus: 2,
|
isthmus: 2,
|
||||||
Atoll: 1,
|
atoll: 1,
|
||||||
Shattered: 7
|
shattered: 7,
|
||||||
|
taklamakan: 1
|
||||||
};
|
};
|
||||||
document.getElementById("templateInput").value = rw(templates);
|
document.getElementById("templateInput").value = rw(templates);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ function createRiver() {
|
||||||
const riverCells = createRiver.cells;
|
const riverCells = createRiver.cells;
|
||||||
if (riverCells.length < 2) return tip("Add at least 2 cells", false, "error");
|
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;
|
const parent = cells.r[last(riverCells)] || riverId;
|
||||||
|
|
||||||
riverCells.forEach(cell => {
|
riverCells.forEach(cell => {
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ function editRiver(id) {
|
||||||
debug
|
debug
|
||||||
.select("#controlCells")
|
.select("#controlCells")
|
||||||
.selectAll(`polygon.${type}`)
|
.selectAll(`polygon.${type}`)
|
||||||
.data(cells)
|
.data(cells.filter(i => pack.cells.i[i]))
|
||||||
.join("polygon")
|
.join("polygon")
|
||||||
.attr("points", d => getPackPolygon(d))
|
.attr("points", d => getPackPolygon(d))
|
||||||
.attr("class", type);
|
.attr("class", type);
|
||||||
|
|
@ -124,18 +124,13 @@ function editRiver(id) {
|
||||||
const initCell = +this.dataset.cell;
|
const initCell = +this.dataset.cell;
|
||||||
const index = +this.dataset.i;
|
const index = +this.dataset.i;
|
||||||
|
|
||||||
const occupiedCells = i.filter(i => r[i] && !river.cells.includes(i));
|
|
||||||
drawCells(occupiedCells, "occupied");
|
|
||||||
let movedToCell = null;
|
let movedToCell = null;
|
||||||
|
|
||||||
d3.event.on("drag", function () {
|
d3.event.on("drag", function () {
|
||||||
const {x, y} = d3.event;
|
const {x, y} = d3.event;
|
||||||
const currentCell = findCell(x, y);
|
const currentCell = findCell(x, y);
|
||||||
|
|
||||||
if (initCell !== currentCell) {
|
movedToCell = initCell !== currentCell ? currentCell : null;
|
||||||
if (occupiedCells.includes(currentCell)) return;
|
|
||||||
movedToCell = currentCell;
|
|
||||||
} else movedToCell = null;
|
|
||||||
|
|
||||||
this.setAttribute("cx", x);
|
this.setAttribute("cx", x);
|
||||||
this.setAttribute("cy", y);
|
this.setAttribute("cy", y);
|
||||||
|
|
@ -149,6 +144,7 @@ function editRiver(id) {
|
||||||
river.cells[index] = movedToCell;
|
river.cells[index] = movedToCell;
|
||||||
drawCells(river.cells, "current");
|
drawCells(river.cells, "current");
|
||||||
|
|
||||||
|
if (!r[movedToCell]) {
|
||||||
// swap river data
|
// swap river data
|
||||||
r[initCell] = 0;
|
r[initCell] = 0;
|
||||||
r[movedToCell] = river.i;
|
r[movedToCell] = river.i;
|
||||||
|
|
@ -156,8 +152,7 @@ function editRiver(id) {
|
||||||
fl[initCell] = fl[movedToCell];
|
fl[initCell] = fl[movedToCell];
|
||||||
fl[movedToCell] = sourceFlux;
|
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 {alterHeights, resolveDepressions, addMeandering, getRiverPath, getBasin, getName, getType, getWidth, getOffset, getApproximateLength} = Rivers;
|
||||||
const riverCells = [];
|
const riverCells = [];
|
||||||
let riverId = last(rivers).i + 1;
|
let riverId = rivers.length ? last(rivers).i + 1 : 1;
|
||||||
let parent = riverId;
|
let parent = riverId;
|
||||||
|
|
||||||
const initialFlux = grid.cells.prec[cells.g[i]];
|
const initialFlux = grid.cells.prec[cells.g[i]];
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
function editZones() {
|
function editZones() {
|
||||||
closeDialogs();
|
closeDialogs();
|
||||||
if (!layerIsOn("toggleZones")) toggleZones();
|
if (!layerIsOn("toggleZones")) toggleZones();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue