Skip to content

Instantly share code, notes, and snippets.

@Azgaar
Last active January 15, 2023 18:30
Embed
What would you like to do?
Fantasy Map Generator
license: gpl-3.0
height: 570
border: no

Azgaar's Fantasy Map Generator demo, v. 0.52b. Based on D3 Voronoi diagram rendered to svg.

Project goal is a procedurally generated map for my Medieval Dynasty simulator. Map should be interactive, scalable, fast and plausible. There should be enought space to place at least 500 manors within 7 regions. The imagined area is about 200.000 km2.

Click on the arrow to open the Options. Click on New map to genarate a random map based on options setup. Check out the project wiki for guidance.

This is a demo version, some new cool features are developed, but not yet deployed. Details are covered in my blog Fantasy Maps for fun and glory. Comments and ideas are highly welcomed, kindly contact me via email. I would also like to see your completed or work in progress maps. For bug reports and change requests please use the main project issues page.

Inspiration:

@font-face {
font-family: 'fontello';
src: url('data:application/font-woff;base64,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') format('woff');
src: url('data:application/octet-stream;base64,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') format('woff2');
font-weight: normal;
font-style: normal;
}
[class^="icon-"]:before, [class*=" icon-"]:before {
font-family: "fontello";
font-style: normal;
font-weight: normal;
speak: none;
display: inline-block;
text-decoration: inherit;
width: 1em;
text-align: center;
font-size: 1em;
margin: -1px;
padding: 0;
/* For safety - reset parent styles, that can break glyph codes*/
font-variant: normal;
text-transform: none;
line-height: 1em;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
/* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
}
.icon-pencil:before { content: '\e800'; } /* '' */
.icon-font:before { content: '\e801'; } /* '' */
.icon-arrows-cw:before { content: '\e802'; } /* '' */
.icon-doc:before { content: '\e803'; } /* '' */
.icon-trash-empty:before { content: '\e804'; } /* '' */
.icon-ok:before { content: '\e805'; } /* '' */
.icon-ok-circled:before { content: '\e806'; } /* '' */
.icon-ok-circled2:before { content: '\e807'; } /* '' */
.icon-link:before { content: '\e808'; } /* '' */
.icon-globe:before { content: '\e809'; } /* '' */
.icon-plus:before { content: '\e80a'; } /* '' */
.icon-plus-circled:before { content: '\e80b'; } /* '' */
.icon-minus-circled:before { content: '\e80c'; } /* '' */
.icon-minus:before { content: '\e80d'; } /* '' */
.icon-text-height:before { content: '\e80e'; } /* '' */
.icon-adjust:before { content: '\e80f'; } /* '' */
.icon-tag:before { content: '\e810'; } /* '' */
.icon-tags:before { content: '\e811'; } /* '' */
.icon-logout:before { content: '\e812'; } /* '' */
.icon-download:before { content: '\e813'; } /* '' */
.icon-down-circled2:before { content: '\e814'; } /* '' */
.icon-upload:before { content: '\e815'; } /* '' */
.icon-up-circled2:before { content: '\e816'; } /* '' */
.icon-cancel-circled2:before { content: '\e817'; } /* '' */
.icon-cancel-circled:before { content: '\e818'; } /* '' */
.icon-cancel:before { content: '\e819'; } /* '' */
.icon-check:before { content: '\e81a'; } /* '' */
.icon-align-left:before { content: '\e81b'; } /* '' */
.icon-align-center:before { content: '\e81c'; } /* '' */
.icon-align-right:before { content: '\e81d'; } /* '' */
.icon-align-justify:before { content: '\e81e'; } /* '' */
.icon-star:before { content: '\e81f'; } /* '' */
.icon-star-empty:before { content: '\e820'; } /* '' */
.icon-search:before { content: '\e821'; } /* '' */
.icon-mail:before { content: '\e822'; } /* '' */
.icon-eye:before { content: '\e823'; } /* '' */
.icon-eye-off:before { content: '\e824'; } /* '' */
.icon-pin:before { content: '\e825'; } /* '' */
.icon-lock-open:before { content: '\e826'; } /* '' */
.icon-lock:before { content: '\e827'; } /* '' */
.icon-attach:before { content: '\e828'; } /* '' */
.icon-home:before { content: '\e829'; } /* '' */
.icon-info-circled:before { content: '\e82a'; } /* '' */
.icon-help-circled:before { content: '\e82b'; } /* '' */
.icon-shuffle:before { content: '\e82c'; } /* '' */
.icon-ccw:before { content: '\e82d'; } /* '' */
.icon-cw:before { content: '\e82e'; } /* '' */
.icon-play:before { content: '\e82f'; } /* '' */
.icon-play-circled2:before { content: '\e830'; } /* '' */
.icon-down-big:before { content: '\e831'; } /* '' */
.icon-left-big:before { content: '\e832'; } /* '' */
.icon-right-big:before { content: '\e833'; } /* '' */
.icon-up-big:before { content: '\e834'; } /* '' */
.icon-up-open:before { content: '\e835'; } /* '' */
.icon-right-open:before { content: '\e836'; } /* '' */
.icon-left-open:before { content: '\e837'; } /* '' */
.icon-down-open:before { content: '\e838'; } /* '' */
.icon-cloud:before { content: '\e839'; } /* '' */
.icon-text-width:before { content: '\e83a'; } /* '' */
.icon-italic:before { content: '\e83b'; } /* '' */
.icon-bold:before { content: '\e83c'; } /* '' */
.icon-move:before { content: '\f047'; } /* '' */
.icon-link-ext:before { content: '\f08e'; } /* '' */
.icon-check-empty:before { content: '\f096'; } /* '' */
.icon-docs:before { content: '\f0c5'; } /* '' */
.icon-list-bullet:before { content: '\f0ca'; } /* '' */
.icon-mail-alt:before { content: '\f0e0'; } /* '' */
.icon-sitemap:before { content: '\f0e8'; } /* '' */
.icon-exchange:before { content: '\f0ec'; } /* '' */
.icon-download-cloud:before { content: '\f0ed'; } /* '' */
.icon-upload-cloud:before { content: '\f0ee'; } /* '' */
.icon-plus-squared:before { content: '\f0fe'; } /* '' */
.icon-unlink:before { content: '\f127'; } /* '' */
.icon-help:before { content: '\f128'; } /* '' */
.icon-info:before { content: '\f129'; } /* '' */
.icon-eraser:before { content: '\f12d'; } /* '' */
.icon-rocket:before { content: '\f135'; } /* '' */
.icon-lock-open-alt:before { content: '\f13e'; } /* '' */
.icon-play-circled:before { content: '\f144'; } /* '' */
.icon-minus-squared:before { content: '\f146'; } /* '' */
.icon-minus-squared-alt:before { content: '\f147'; } /* '' */
.icon-level-up:before { content: '\f148'; } /* '' */
.icon-level-down:before { content: '\f149'; } /* '' */
.icon-ok-squared:before { content: '\f14a'; } /* '' */
.icon-expand:before { content: '\f150'; } /* '' */
.icon-collapse:before { content: '\f151'; } /* '' */
.icon-expand-right:before { content: '\f152'; } /* '' */
.icon-sort-alt-up:before { content: '\f160'; } /* '' */
.icon-sort-alt-down:before { content: '\f161'; } /* '' */
.icon-right-circled2:before { content: '\f18e'; } /* '' */
.icon-left-circled2:before { content: '\f190'; } /* '' */
.icon-collapse-left:before { content: '\f191'; } /* '' */
.icon-plus-squared-alt:before { content: '\f196'; } /* '' */
.icon-history:before { content: '\f1da'; } /* '' */
.icon-header:before { content: '\f1dc'; } /* '' */
.icon-trash:before { content: '\f1f8'; } /* '' */
.icon-brush:before { content: '\f1fc'; } /* '' */
.icon-clone:before { content: '\f24d'; } /* '' */
.icon-hourglass-1:before { content: '\f251'; } /* '' */
.icon-hand-grab-o:before { content: '\f255'; } /* '' */
.icon-hand-paper-o:before { content: '\f256'; } /* '' */
.icon-calendar-check-o:before { content: '\f274'; } /* '' */
.icon-map-pin:before { content: '\f276'; } /* '' */
@font-face {
font-family: 'Architects Daughter';
font-style: normal;
font-weight: 400;
src: local('Architects Daughter Regular'), local('ArchitectsDaughter-Regular'), url(https://fonts.gstatic.com/s/architectsdaughter/v8/RXTgOOQ9AAtaVOHxx0IUBM3t7GjCYufj5TXV5VnA2p8.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
@font-face {
font-family: 'Bangers';
font-style: normal;
font-weight: 400;
src: local('Bangers Regular'), local('Bangers-Regular'), url(https://fonts.gstatic.com/s/bangers/v10/yJQgrSMUoqRj-0SbnQsv4g.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
@font-face {
font-family: 'Bitter';
font-style: normal;
font-weight: 400;
src: local('Bitter Regular'), local('Bitter-Regular'), url(https://fonts.gstatic.com/s/bitter/v12/zfs6I-5mjWQ3nxqccMoL2A.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
@font-face {
font-family: 'Chewy';
font-style: normal;
font-weight: 400;
src: local('Chewy Regular'), local('Chewy-Regular'), url(https://fonts.gstatic.com/s/chewy/v9/rb3O4cUMVLYzfgbaJOdJHw.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
@font-face {
font-family: 'Cinzel';
font-style: normal;
font-weight: 400;
src: local('Cinzel Regular'), local('Cinzel-Regular'), url(https://fonts.gstatic.com/s/cinzel/v7/zOdksD_UUTk1LJF9z4tURA.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
@font-face {
font-family: 'Comfortaa';
font-style: normal;
font-weight: 700;
src: local('Comfortaa Bold'), local('Comfortaa-Bold'), url(https://fonts.gstatic.com/s/comfortaa/v12/fND5XPYKrF2tQDwwfWZJI-gdm0LZdjqr5-oayXSOefg.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
@font-face {
font-family: 'Dancing Script';
font-style: normal;
font-weight: 700;
src: local('Dancing Script Bold'), local('DancingScript-Bold'), url(https://fonts.gstatic.com/s/dancingscript/v9/KGBfwabt0ZRLA5W1ywjowUHdOuSHeh0r6jGTOGdAKHA.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
@font-face {
font-family: 'Gloria Hallelujah';
font-style: normal;
font-weight: 400;
src: local('Gloria Hallelujah'), local('GloriaHallelujah'), url(https://fonts.gstatic.com/s/gloriahallelujah/v9/CA1k7SlXcY5kvI81M_R28cNDay8z-hHR7F16xrcXsJw.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
@font-face {
font-family: 'Great Vibes';
font-style: normal;
font-weight: 400;
src: local('Great Vibes'), local('GreatVibes-Regular'), url(https://fonts.gstatic.com/s/greatvibes/v5/6q1c0ofG6NKsEhAc2eh-3Y4P5ICox8Kq3LLUNMylGO4.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
@font-face {
font-family: 'IM Fell English';
font-style: normal;
font-weight: 400;
src: local('IM FELL English Roman'), local('IM_FELL_English_Roman'), url(https://fonts.gstatic.com/s/imfellenglish/v7/xwIisCqGFi8pff-oa9uSVAkYLEKE0CJQa8tfZYc_plY.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
@font-face {
font-family: 'Josefin Sans';
font-style: normal;
font-weight: 400;
src: local('Josefin Sans Regular'), local('JosefinSans-Regular'), url(https://fonts.gstatic.com/s/josefinsans/v12/xgzbb53t8j-Mo-vYa23n5ugdm0LZdjqr5-oayXSOefg.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
@font-face {
font-family: 'Kaushan Script';
font-style: normal;
font-weight: 400;
src: local('Kaushan Script'), local('KaushanScript-Regular'), url(https://fonts.gstatic.com/s/kaushanscript/v6/qx1LSqts-NtiKcLw4N03IEd0sm1ffa_JvZxsF_BEwQk.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
@font-face {
font-family: 'Lobster';
font-style: normal;
font-weight: 400;
src: local('Lobster Regular'), local('Lobster-Regular'), url(https://fonts.gstatic.com/s/lobster/v20/cycBf3mfbGkh66G5NhszPQ.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
@font-face {
font-family: 'Montez';
font-style: normal;
font-weight: 400;
src: local('Montez Regular'), local('Montez-Regular'), url(https://fonts.gstatic.com/s/montez/v8/aq8el3-0osHIcFK6bXAPkw.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
@font-face {
font-family: 'Orbitron';
font-style: normal;
font-weight: 400;
src: local('Orbitron Regular'), local('Orbitron-Regular'), url(https://fonts.gstatic.com/s/orbitron/v9/HmnHiRzvcnQr8CjBje6GQvesZW2xOQ-xsNqO47m55DA.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
@font-face {
font-family: 'Satisfy';
font-style: normal;
font-weight: 400;
src: local('Satisfy Regular'), local('Satisfy-Regular'), url(https://fonts.gstatic.com/s/satisfy/v8/2OzALGYfHwQjkPYWELy-cw.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
@font-face {
font-family: 'Shadows Into Light';
font-style: normal;
font-weight: 400;
src: local('Shadows Into Light'), local('ShadowsIntoLight'), url(https://fonts.gstatic.com/s/shadowsintolight/v7/clhLqOv7MXn459PTh0gXYFK2TSYBz0eNcHnp4YqE4Ts.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
@font-face {
font-family: 'Yellowtail';
font-style: normal;
font-weight: 400;
src: local('Yellowtail Regular'), local('Yellowtail-Regular'), url(https://fonts.gstatic.com/s/yellowtail/v8/GcIHC9QEwVkrA19LJU1qlPk_vArhqVIZ0nv9q090hN8.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
@font-face {
font-family: 'Amatic SC';
font-style: normal;
font-weight: 700;
src: local('Amatic SC Bold'), local('AmaticSC-Bold'), url(https://fonts.gstatic.com/s/amaticsc/v11/IDnkRTPGcrSVo50UyYNK7-gdm0LZdjqr5-oayXSOefg.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
svg {
background-color: #5E4FA2;
border: 1px solid #5e4fa2;
position: absolute;
}
canvas {
position: absolute;
pointer-events: none;
}
button {
cursor: pointer;
}
#terrs {
stroke-width: 0.7;
stroke-linejoin: round;
mask: url(#shape);
}
#cults {
stroke-width: 0.7;
stroke-linejoin: round;
mask: url(#shape);
pointer-events: none;
}
#grid {
display: none;
fill: none;
}
#landmass {
fill-rule: evenodd;
stroke: none;
}
#lakes, #oceanLayers {
fill-rule: evenodd;
}
#coastline {
fill: none;
stroke-linejoin: round;
}
#regions {
stroke-width: 0;
fill-rule: evenodd;
stroke-linejoin: round;
mask: url(#shape);
pointer-events: none;
}
#rivers {
stroke: none;
mask: url(#shape);
cursor: pointer;
}
#burgs {
fill-opacity: 0.6;
cursor: pointer;
}
#terrain {
mask: url(#shape);
}
#hills {
stroke-width: 0.1px;
fill: #999999;
}
#mounts {
stroke-width: 0.1px;
fill: white;
}
#strokes {
stroke-width: 0.08px;
width: 2px;
stroke: #5c5c70;
stroke-dasharray: 0.5, 0.7;
stroke-linecap: round;
}
#routes, #borders {
fill: none;
}
#roads, #trails {
mask: url(#shape);
}
#swamps {
stroke-width: 0.05px;
fill: none;
stroke: #5c5c70;
}
#forests {
stroke-width: 0.1px;
stroke: #5c5c70;
}
#options .pressed {
background-color: #916e7f;
font-style: italic;
}
.editTrigger {
display: none;
position: relative;
width: 60px;
}
.editTrigger[type="number"] {
width: 44px;
height: 14px;
}
.editTrigger[type="range"] {
width: 132px;
cursor: pointer;
}
#editGroupSelect {
width: 165px;
}
#editGroupInput {
display: none;
width: 161px;
}
#editSizeIcon, #editOpacityIcon, #editShadowIcon {
display: none;
}
#editText {
width: 160px;
}
#editFontSelect {
width: 129px;
}
#editFontInput {
width: 125px;
}
#editColor {
height: 20px;
width: 50px;
padding: 0;
}
#riverAngle {
width: 60px;
}
#riverScale {
width: 43px;
}
.editButtonS {
display: none;
cursor: pointer;
}
i.dialog-icon {
display: none;
margin: 0 -1px 0 4px;
}
.editValue {
display: none;
cursor: default;
font-size: small;
width: 34px;
}
#labels {
text-anchor: middle;
dominant-baseline: alphabetic;
text-shadow: 0 0 4px white;
cursor: pointer;
}
#countries {
dominant-baseline: central;
}
.tag {
fill: #fffa90;
stroke: #333333;
stroke-width: 1.4px;
}
.line {
stroke: #666666;
stroke-width: 1px;
}
.drag {
text-shadow: 0 0 6px red;
}
.draggable {
cursor: move;
}
.ui-dialog, #optionsContainer {
user-select: none;
}
#options {
margin: 10px;
display: none;
font-size: smaller;
font-family: monospace;
position: absolute;
background-color: rgba(168, 130, 147, 0.85);
border: solid 1px #5e4fa2;
}
.tab {
overflow: hidden;
border-bottom: 1px solid #5d4651;;
}
button.options {
background-color: #997c89;
font-family: monospace;
font-weight: bold;
float: left;
border: none;
outline: none;
padding: 8px 16px;
transition: 0.1s;
font-size: 1em;
}
#options p {
font-style: italic;
font-weight: bold;
}
#options input[type="color"], #convertImageDialog input[type="color"] {
width: 38px;
padding: 0;
border: 0;
background: none;
cursor: pointer;
}
#options input[type="range"] {
outline: none;
width: 120px;
height: 2px;
background: #ffffff;
top: -2px;
position: relative;
-webkit-appearance: none;
appearance: none;
}
#options input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
border-radius: 15%;
width: 10px;
height: 10px;
background: #916e7f;
border: 1px solid #5d4651;
cursor: pointer;
}
#options input[type="range"]::-moz-range-thumb {
appearance: none;
border-radius: 15%;
width: 10px;
height: 10px;
background: #916e7f;
border: 1px solid #5d4651;
cursor: pointer;
}
#options select {
height: 14px;
width: 122px;
border: 0;
outline: none;
font-size: smaller;
font-family: monospace;
cursor: pointer;
}
#options .buttonoff {
background-color: #b6b4b440;
color: grey;
}
#sticked {
padding: 0 13px;
}
#sticked button {
background-color: rgba(153, 124, 137, 0);
padding: 0;
margin: 2px;
}
#collapsible {
padding: 10.5px;
position: absolute;
z-index: 2;
}
#optionsTrigger {
display: block;
padding: 5.5px 5.5px;
opacity: 0.6;
}
#regenerate {
display: none;
opacity: 0.9;
padding: 7px 10px;
}
button.options:hover {
background-color: #806070;
color: white;
}
button.active {
background-color: #916e7f;
color: white;
}
#layoutTab {
margin-left: 19px;
}
.tabcontent {
display: none;
padding: 0 6px 0 12px;
opacity: 0.8;
max-width: 290px;
}
.tabcontent button {
background-color: #997c89;
font-family: monospace;
border: none;
outline: none;
padding: 5px 8px;
margin: 4px 0;
transition: 0.1s;
font-size: 1em;
}
.tabcontent button:hover {
background-color: #a8879d;
}
#mapLayers {
display: inline-block;
}
.tabcontent li {
list-style-type: none;
background-color: #997c89;
cursor: pointer;
padding: 5px 8px;
margin: 4px;
transition: 0.1s;
float: left;
}
.tabcontent li:hover {
background-color: #a8879d;
}
.tabcontent li.solid {
color: #42383f;
}
p {
margin-bottom: 0;
}
#optionsContainer span {
cursor: default;
}
#statusbar {
display: block;
font-family: monospace;
position: absolute;
top: 548px;
}
table {
table-layout: fixed;
width: 288px;
}
table td:nth-of-type(1) {
text-decoration: underline dotted gray;
cursor: help;
width: 126px;
}
table td:nth-of-type(3) {
text-align: right;
}
#icons {
stroke: #0d0d0d;
fill: grey;
}
#fileToLoad {
display: none;
}
#customizationMenu {
display: none;
}
.setColors {
display: inline-block;
}
body button.noicon {
width: 24px;
height: 20px;
margin: 1px;
padding: 1px 6px;
float: left;
font-family: Copperplate, monospace;
}
#templateEditor > div {
margin: 2px 0;
}
#templateEditor #templateTools {
display: inline-block;
margin-bottom: -3px;
}
#templateBody > div {
border: 1px solid #949494;
border-radius: 1px;
background-image: linear-gradient(to right, #ffffff 0%, #fafafa 51%, #ebebeb 100%);
margin: 1px 1px;
width: 93%;
padding: 1px 2px;
font-size: 9px;
}
#templateBody > div:hover {
border-color: #808080;
background-image: linear-gradient(to right, #fcfcfc 0%, #ededed 51%, #dedede 100%);
}
#templateBody span {
display: inline-block;
margin: 0 1px;
float: right;
cursor: pointer;
}
#templateBody span:hover {
color: #297cb8;
}
#templateBody label {
float: right;
margin-right: 4px;
}
#templateBody label:first-of-type {
margin-right: 12px;
}
#templateBody input {
height: 4px;
width: 45px;
font-family: monospace;
height: 4px;
font-family: monospace;
}
#templateBody select {
border: 0;
background-color: rgba(255, 255, 255, 0);
width: 58px;
cursor: pointer;
}
.riverPoints {
fill: red;
stroke: none;
stroke-width: 0.1;
cursor: move;
}
.riverPoints circle:hover {
stroke: brown;
}
.drag-trigger{
border-left: 12px solid transparent;
border-right: 12px solid #916e7f;
border-top: 12px solid transparent;
position: absolute;
right: 0;
top: 100%;
margin-top: -12px;
}
.drag-trigger:hover{
cursor: move;
border-right-color: #5e4fa2;
}
#styleInputs div {
display: none;
line-height: 6px;
}
#styleInputs #styleOpacity, #styleInputs #styleFill, #styleInputs #styleFilter {
display: block;
}
#styleInputs button {
padding: 0 6px;
margin: 0 2px;
border: 1px #827c7f solid;
background-color: #ffffff;
}
.pureInput {
display: inline-block;
width: 50px;
height: 10px;
font-size: small;
font-size: smaller;
font-family: monospace;
}
.grayscale {
filter: grayscale(1);
}
.sepia {
filter: sepia(1) saturate(0.8);
}
.tint {
filter: sepia(1) hue-rotate(200deg);
}
.dingy {
filter: contrast(1) saturate(1.8) sepia(.6);
}
.color-div {
width: 32px;
height: 12px;
display: inline-block;
margin: 1px 2px;
border: 1px #c5c5c5 groove;
cursor: pointer;
}
#colorsSelect div {
height: 18px;
display: inline-block;
cursor: pointer;
}
.color-div:hover {
border-color: red;
}
.hoveredColor {
box-shadow: 0 0 1px 1px #717171;
}
.selectedColor {
border-color: red;
}
#colorScheme {
margin: 6px 1px 4px 1px;
}
#colorsSelectValue {
font-size: larger;
position: relative;
font-family: monospace;
font-weight: bold;
top: -3px;
}
.selectedCell {
stroke-width: 1;
stroke: #da3126;
}
body .ui-dialog {
padding: 1px;
font-size: 12px;
}
body .ui-dialog-titlebar {
font-size: 14px;
}
.ui-dialog input {
height: 14px;
}
.ui-dialog button.pressed {
box-shadow: inset 1px 1px 0 0 #ccc;
}
.ui-dialog input[type="range"] {
outline: none;
height: 2px;
background: #e9e9e9;
top: -4px;
position: relative;
-webkit-appearance: none;
appearance: none;
}
.ui-dialog input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
border-radius: 15%;
width: 10px;
height: 10px;
background: #e9e9e9;
border: 1px solid #9b9b9b;
cursor: pointer;
}
.ui-dialog input[type="range"]::-moz-range-thumb {
appearance: none;
border-radius: 15%;
width: 10px;
height: 10px;
background: #e9e9e9;
border: 1px solid #9b9b9b;
cursor: pointer;
}
<!DOCTYPE html>
<head>
<title>Azgaar's Fantasy Map Generator Demo</title>
<meta name="author" content="Azgaar (Max Ganiev)">
<meta charset="utf-8">
<meta name="description" content="Azgaar's Fantasy Map Generator demo. Based on D3 Voronoi diagram rendered to svg.">
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script src="https://mewo2.com/js/priority-queue.js"></script>
<script src="https://rawgit.com/LuisSevillano/9f6c9edd7f90ac6cca54ed744e28f3ee/raw/38f9774f83f00b286360db1ea97d851f79e594aa/polylabel.js"></script>
<script src="names.js"></script>
<link rel="stylesheet" type="text/css" href="index.css?version=0.52b"/>
<link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"/>
<link rel="stylesheet" type="text/css" href="fontello.css?version=0.52b"/>
<script src="quantize.js"></script>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" width="960" height="540">
<defs>
<filter id="blurFilter" x="-1" y="-1" width="100" height="100">
<feGaussianBlur in="SourceGraphic" stdDeviation="0.2"/>
</filter>
<filter id="dropShadow">
<feGaussianBlur in="SourceAlpha" stdDeviation="2"/>
<feOffset dx="1" dy="2"/>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<g id="deftemp">
<mask id="shape" x="0" y="0" width="100%" height="100%" fill="black"></mask>
</g>
<g id="defs-icons">
<symbol id="icon-anchor" viewBox="0 0 28 28">
<title>Anchor</title>
<path d="M15 4c0-0.547-0.453-1-1-1s-1 0.453-1 1 0.453 1 1 1 1-0.453 1-1zM28 18.5v5.5c0 0.203-0.125 0.391-0.313 0.469-0.063 0.016-0.125 0.031-0.187 0.031-0.125 0-0.25-0.047-0.359-0.141l-1.453-1.453c-2.453 2.953-6.859 4.844-11.688 4.844s-9.234-1.891-11.688-4.844l-1.453 1.453c-0.094 0.094-0.234 0.141-0.359 0.141-0.063 0-0.125-0.016-0.187-0.031-0.187-0.078-0.313-0.266-0.313-0.469v-5.5c0-0.281 0.219-0.5 0.5-0.5h5.5c0.203 0 0.391 0.125 0.469 0.313s0.031 0.391-0.109 0.547l-1.563 1.563c1.406 1.891 4.109 3.266 7.203 3.687v-10.109h-3c-0.547 0-1-0.453-1-1v-2c0-0.547 0.453-1 1-1h3v-2.547c-1.188-0.688-2-1.969-2-3.453 0-2.203 1.797-4 4-4s4 1.797 4 4c0 1.484-0.812 2.766-2 3.453v2.547h3c0.547 0 1 0.453 1 1v2c0 0.547-0.453 1-1 1h-3v10.109c3.094-0.422 5.797-1.797 7.203-3.687l-1.563-1.563c-0.141-0.156-0.187-0.359-0.109-0.547s0.266-0.313 0.469-0.313h5.5c0.281 0 0.5 0.219 0.5 0.5z"></path>
</symbol>
</g>
<pattern id="oceanPattern" width="100" height="100" patternUnits="userSpaceOnUse">
<filter id='image'>
<feImage x="0" y="0" width="100" height="100" xlink:href="data:image/png;base64,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">
</filter>
<rect width='100' height='100' filter="url(#image)" opacity='0.2'/>
</pattern>
<pattern id="mottling" width="16" height="9" patternUnits="userSpaceOnUse">
<filter id='turb'>
<feTurbulence type='fractalNoise' baseFrequency='.7' numOctaves='10' stitchTiles='stitch'/>
</filter>
<rect width='16' height='9' filter="url(#turb)"/>
</pattern>
</defs>
</svg>
<canvas id="canvas" width="960" height="540" style="opacity: 0;"></canvas>
<div id="optionsContainer">
<div id="collapsible">
<button id="optionsTrigger" class="options" title="Click to display Options">▶</button>
<button id="regenerate" class="options" title="Click to generate a new map">New Map!</button>
</div>
<div id="options">
<div class="drag-trigger"></div>
<div class="tab">
<button id="layoutTab" class="options">Layout</button>
<button id="styleTab" class="options">Style</button>
<button id="optionsTab" class="options">Options</button>
<button id="customizeTab" class="options">Customize</button>
</div>
<div id="layoutContent" class="tabcontent">
<p style="display: inline-block;">Select preset:</p>
<select id="layoutPreset">
<option value="layoutPolitical" selected>Political map</option>
<option value="layoutCultural">Cultural map</option>
<!-- <option value="layoutEconomical">Economical map</option> -->
<option value="layoutHeightmap">Heightmap</option>
<option value="layoutLandmass">Pure landmass</option>
</select>
<p>Displayed layers. Drag to move, click to toggle</p>
<div id="mapLayers">
<li title="Toggle Ocean, not movable" id="toggleOcean" onclick="$('#oceanPattern').fadeToggle()" class="solid">Ocean</li>
<li title="Toggle Landmass, not movable" id="toggleLandmass" onclick="$('#landmass').fadeToggle()" class="solid">Landmass</span></li>
<li title="Toggle Heightmap" id="toggleHeight" class="buttonoff">Heightmap</li>
<li title="Toggle Cultures map" id="toggleCultures" class="buttonoff">Cultures</li>
<li title="Toggle Routes" id="toggleRoutes" onclick="$('#routes').fadeToggle()">Routes</li>
<li title="Toggle Rivers" id="toggleRivers" onclick="$('#rivers').fadeToggle()">Rivers</li>
<li title="Toggle Countries" id="toggleCountries">Countries</li>
<li title="Toggle Borders" id="toggleBorders" onclick="$('#borders').fadeToggle()">Borders</li>
<li title="Toggle Relief icons" id="toggleRelief" onclick="$('#terrain').fadeToggle()">Relief</li>
<li title="Toggle Grid" id="toggleGrid" class="buttonoff" onclick="$('#grid').fadeToggle()">Grid</li>
<li title="Toggle Labels" id="toggleLabels" onclick="$('#labels').fadeToggle()">Labels</li>
<li title="Toggle Burg icons" id="toggleIcons" onclick="$('#burgs').fadeToggle()">Burgs</li>
</div>
</div>
<div id="styleContent" class="tabcontent">
<p style="display: inline-block;">Select element:</p>
<select id="styleElementSelect">
<option value="oceanBase" selected>Ocean</option>
<option value="landmass">Landmass</option>
<option value="terrs">Heightmap</option>
<option value="cults">Cultures</option>
<option value="roads">Roads</option>
<option value="trails">Trails</option>
<option value="searoutes">Searoutes</option>
<option value="rivers">Rivers</option>
<option value="terrain">Relief</option>
<option value="regions">Countries</option>
<option value="stateBorders">State Borders</option>
<option value="neutralBorders">Neutral Borders</option>
<option value="coastline">Coastline</option>
<option value="lakes">Lakes</option>
<option value="grid">Grid</option>
<option value="labels">Labels</option>
<option value="burgs">Burgs</option>
</select>
<div id="styleInputs">
<div id="styleFill">
Fill: <input id="styleFillInput" type="color" value="#5E4FA2"/>
<output id="styleFillOutput">#5E4FA2</output>
</div>
<div id="styleStroke">
Stroke: <input id="styleStrokeInput" type="color" value="#5E4FA2"/>
<output id="styleStrokeOutput">#5E4FA2</output>
</div>
<div id="styleMultiple">Colors:</div>
<div id="styleStrokeWidth">
<br>Stroke width: <input id="styleStrokeWidthInput" type="range" min="0" max="3" step="0.01" value="1">
<output id="styleStrokeWidthOutput">1</output>
</div>
<div id="styleStrokeDasharray">
<br>Stroke dasharray: <input id="styleStrokeDasharrayInput" class="pureInput" value="1 2">
</div>
<div id="styleStrokeLinecap">
<br>Stroke linecap: <select id="styleStrokeLinecapInput" class="pureInput">
<option value="inherit" selected>Inherit</option>
<option value="butt">Butt</option>
<option value="round">Round</option>
<option value="square">Square</option>
</select>
</div>
<div id="styleFontSize">
<br>Font size: <button title="Multiply all Fonts size by 1.1" id="styleFontPlus">+</button><button title="Multiply all Fonts size by 0.9" id="styleFontMinus">-</button>
</div>
<div id="styleSize">
<br>Radius: <button title="Multiply Radius by 1.1" id="styleFillPlus">+</button><button title="Multiply Radius by 0.9" id="styleFillMinus">-</button>
<span> Stroke: </span><button title="Multiply Stroke-width by 1.1" id="styleStrokePlus">+</button><button title="Multiply Stroke-width by 0.9" id="styleStrokeMinus">-</button>
</div>
<div id="styleOpacity">
<br>Opacity: <input id="styleOpacityInput" type="range" min="0" max="1" step="0.01" value="1">
<output id="styleOpacityOutput">1</output>
</div>
<div id="styleFilter">
<br>Filter: <select id="styleFilterInput" class="pureInput">
<option value="">None</option>
<option value="url(#blurFilter)" selected>Blur</option>
<option value="url(#dropShadow)" selected>Shadow</option>
</select>
</div>
<div id="styleScheme">
<br>Color scheme: <select id="styleSchemeInput" class="pureInput">
<option value="bright" selected>Bright</option>
<option value="light">Light</option>
<option value="green">Green</option>
<option value="monochrome">Monochrome</option>
</select>
</div>
</div>
<p>Toggle filters:</p>
<button onclick="$('svg').toggleClass('grayscale')" class="buttonoff">Grayscale</button>
<button onclick="$('svg').toggleClass('sepia')" class="buttonoff">Sepia</button>
<button onclick="$('svg').toggleClass('tint')" class="buttonoff">Tint</button>
<button onclick="$('svg').toggleClass('dingy')" class="buttonoff">Dingy</button>
</div>
<div id="optionsContent" class="tabcontent">
<p>Generate new map to apply the options!</p>
<table>
<tr>
<td title="Select template to be used for a Heightmap generation">Heightmap template</td>
<td>
<select id="templateInput">
<option value="Random" selected>Random</option>
<option value="Volcano">Volcano</option>
<option value="High Island">High Island</option>
<option value="Low Island">Low Island</option>
<option value="Continents">Continents</option>
<option value="Archipelago">Archipelago</option>
<option value="Atoll">Atoll</option>
</select>
</td>
<td></td>
</tr>
<tr>
<td title="Set the graph size. A non-default values are not properly tested yet! Works good with converted maps">Graph size</td>
<td>
<input id="sizeInput" type="range" min="0.8" max="4" step="0.1" value="1">
</td>
<td>
<output id="sizeOutput">1</output>
</td>
</tr>
<tr>
<td title="Define how many Settlements should be placed">Burgs count</td>
<td>
<input id="manorsInput" type="range" min="0" max="1000" value="500">
</td>
<td>
<output id="manorsOutput">500</output>
</td>
</tr>
<tr>
<td title="Define how many Countries should be created">Countries count</td>
<td>
<input id="regionsInput" type="range" min="0" max="100" value="13">
</td>
<td>
<output id="regionsOutput">13</output>
</td>
</tr>
<tr>
<td title="Define Countries size variety. Set to 0 to have all countries sized the same">Countries disbalance</td>
<td>
<input id="powerInput" type="range" min="0" max="10" step="0.2" value="5">
</td>
<td>
<output id="powerOutput">5</output><br>
</td>
</tr>
<tr>
<td title="Maximum distance to a closer manor to consider polygon as a Neutral Land">Burg influence radius</td>
<td>
<input id="neutralInput" type="range" min="1" max="100" step="1" value="100">
</td>
<td>
<output id="neutralOutput">100</output>
</td>
</tr>
<tr>
<td title="Define the land swampiness. Increase to see more marshes (turn on 'Relief' layer)">Swampness</td>
<td>
<input id="swampinessInput" type="range" min="0" max="100" value="10">
</td>
<td>
<output id="swampinessOutput">10</output>
</td>
</tr>
<tr>
<td title="Define the coastline sharpness. Decrease for a more round land shape">Coastline curvature</td>
<td>
<input id="sharpnessInput" type="range" min="0.1" max="0.2" value="0.2" step="0.05">
</td>
<td>
<output id="sharpnessOutput">0.2</output>
</td>
</tr>
<tr>
<td title="Define the Land outline layers scheme">Coast outline layers</td>
<td>
<select id="outlineLayers">
<option value="random">Random</option>
<option value="-6,-3,-1" selected>-6,-3,-1</option>
<option value="-9,-6,-3,-1">-9,-6,-3,-1</option>
<option value="-6,-5,-4,-3,-2,-1">-6,-5,-4,-3,-2,-1</option>
<option value="-9,-8,-7,-6,-5,-4,-3,-2,-1">-9,-8,-7,-6,-5,-4,-3,-2,-1</option>
<option value="-6,-4,-2">-6,-4,-2</option>
<option value="-8,-6,-4,-2">-8,-6,-4,-2</option>
</select>
</td>
<td></td>
</tr>
<tr>
<td title="Select the coastline rendering style">Coastline style</td>
<td>
<select id="curveType">
<option value="Catmull–Rom" selected>Catmull–Rom</option>
<option value="Linear">Linear</option>
<option value="Basis">Basis</option>
<option value="Cardinal">Cardinal</option>
<option value="Step">Step</option>
</select>
</td>
<td></td>
</tr>
</table>
</div>
<div id="customizeContent" class="tabcontent" style="display: block;">
<p title="Click &quot;Start&quot; to initiate customization, &quot;Complete&quot; to finalize the Heightmap">Heightmap customization:</p>
<div id="customizationMain">
<button title="Roll back to Heightmap customization" id="fromHeightmap">Roll back</button>
<button title="Start from scratch" id="fromScratch">Clear all</button>
<button class="buttonoff" title="Finalize the Heightmap. Not allowed if landmass area is insufficient" id="getMap" disabled="disabled">Complete</button>
</div>
<div id="customizationMenu" style="display: none;">
<div id="customizeTools">
<label title="Customization Tools">Tools:</label><br>
<button title="Open template editor" id="applyTemplate">Apply Template</button>
<button title="Open Image Convertion master" id="convertImage">Convert Image</button>
<button title="Rescale elevation" id="rescale">Rescale</button>
</div>
<div id="customizeBrushes">
<label title="Select brush and click on the map to use it">Free Draw brushes:</label><br>
<button id="brushElevate" title="Click and drag the map to increase cells elevation" class="radio">↥</button>
<button id="brushDepress" title="Click and drag the map to decrease cells elevation" class="radio">↧</button>
<button id="brushAlign" title="Click and drag the map to align cells elevation" class="radio">=</button>
<button id="brushSmooth" title="Click and drag the map to smooth cells elevation" class="radio">~</button>
<button id="brushHill" title="Click on the map to place a Hill" class="radio pressed">H</button>
<button id="brushPit" title="Click on the map to place a Pit" class="radio">P</button>
<button id="brushRange" title="Select two points to place a Range" class="radio">R</button>
<button id="brushTrough" title="Select two points to place a Trought" class="radio">T</button>
<button title="Smooth all heights" id="smoothHeights">≈</button>
<br><label title="Set the brush power">Brush power:</label>
<input id="brushPower" type="range" min="0.01" max="0.3" step="0.01" value="0.05">
<output id="brushPowerOutput">0.05</output><br>
</div><br>
<label title="Count of Land cells and Land-Map ratio">Landmass: <span id="landmassCounter">0</span></label><hr>
</div>
<p>Click to add a Label:</p>
<button id="addLabel" class="radio">Label</button>
<button id="addBurg" class="radio">Burg</button>
<div>
<p>Save / Load map:</p>
<button id="saveMap" title="Save in .map format to be loaded later as fully functional map">Save Map</button>
<button id="loadMap" title="Load fully functional map in a .map format">Load Map</button>
<button id="savePNG" title="Download the visible part of the map as .png image">Get PNG</button>
<button id="saveSVG" title="Download the map as .svg image for later use in vector graphics editors">Get SVG</button>
<input type="file" accept=".map" id="fileToLoad">
</div>
</div>
<div id="sticked">
<button id="randomMap" title="Generate new random map based on options being set" class="options">New Map</button>
<div style="float:right; margin-right:5px;">
<!-- Zoom should be smooth and centrified, to be fixed later
<button id="zoomMinus" title="Zoom out" class="options">-</button>
<button id="zoomPlus" title="Zoom in" class="options">+</button>
-->
<button id="zoomReset" title="Reset map zoom to default" class="options">Reset Zoom</button>
</div>
</div>
</div>
</div>
<div id="labelEditor" style="display: none">
<button id="editGroupButton" title="Edit label Group" class="editButton icon-list-bullet"></button>
<select id="editGroupSelect" title="Select Group for this label" class="editTrigger"/></select>
<input id="editGroupInput" placeholder="new name" title="Declare new Group for this label" class="editTrigger"/>
<span id="editGroupNew" title="Declare new Group for this label" class="editButtonS icon-plus-squared-alt"></span>
<span id="editGroupRemove" title="Remove the Group with all labels" class="editButtonS icon-trash-empty"></span>
<button id="editTextButton" title="Edit label Text" class="editButton icon-pencil"></button>
<input id="editText" class="editTrigger"/>
<span id="editTextRandom" title="Generate random name" class="editButtonS icon-shuffle"></span>
<button id="editFontButton" title="Select Font for the entire Group" class="editButton icon-font"></button>
<span id="editExternalFont" title="Fetch fonts by linking @font-face declaration" class="editButtonS icon-link"></span>
<select id="editFontSelect" class="editTrigger" title="Select one of the default Fonts"></select>
<input id="editFontInput" placeholder="link to @font-face" title="Fetch fonts by linking @font-face declaration" class="editTrigger"/>
<i id="editSizeIcon" class="icon-text-height"></i>
<input id="editSize" title="Change Font size for the entire Group" class="editTrigger" value="14" type="number" min="1" max="100" step=".5"/>
<button id="editStyleButton" title="Select Color for the entire Group" class="editButton icon-brush"></button>
<input id="editColor" type="color" class="editTrigger" value="#3e3e4b">
<i id="editOpacityIcon" class="icon-adjust"></i>
<input id="editOpacity" title="Change Opacity for the entire Group" class="editTrigger" value="1" type="number" min="0" max="1" step="0.02">
<i id="editShadowIcon" class="icon-clone"></i>
<input id="editShadow" title="Change Shadow for the entire Group" class="editTrigger" value="1" type="number" min="0" max="1" step="0.02" disabled="true">
<button id="editAngleButton" title="Rotate the label" class="editButton icon-ccw"></button>
<input id="editAngle" class="editTrigger" value="0" type="range" min="-180" max="180" step="0.2" oninput="editAngleValue.innerHTML = Math.abs(this.value)+'°'">
<span id="editAngleValue" class="editValue">0°</span>
<button id="editCopy" title="Copy the label" class="editButton icon-clone"></button>
<button id="editRemoveSingle" title="Remove the label" class="editButton icon-trash"></button>
</div>
<div id="riverEditor" style="display: none">
<button id="riverRisize" title="Resize (rotate, scale) river" class="editButton icon-arrows-cw"></button>
<i id="riverAngleIcon" title="Rotate river" class="dialog-icon icon-cw"></i>
<input id="riverAngle" class="editTrigger" value="0" type="range" min="-180" max="180" step="0.2">
<span id="riverAngleValue" class="editValue">0°</span>
<i id="riverScaleIcon" title="Change river scale" class="dialog-icon icon-link-ext"></i>
<input id="riverScale" class="editTrigger" value="1" type="number" min="0.1" max="3" step="0.01">
<span id="riverReset" title="Reset transformation" class="editButtonS icon-cancel-circled2"></span>
<button id="riverRenegerate" title="Regenerate river" class="editButton icon-shuffle"></button>
<button id="riverAddPoint" title="Click to add a river point" class="editButton icon-plus-squared-alt"></button>
<button id="riverRemovePoint" title="Click on red circle to remove river point" class="editButton icon-minus-squared-alt"></button>
<button id="riverCopy" title="Copy river" class="editButton icon-clone"></button>
<button id="riverNew" title="Create new river clicking on map" class="editButton icon-map-pin"></button>
<button id="riverRemove" title="Remove river" class="editButton icon-trash"></button>
</div>
<div id="templateEditor" style="display: none">
<div id="templateTop">
Base template: <select id="templateSelect" data-prev="templateNew" title="Select base template"/>
<option value="templateCustom" selected>Custom</option>
<option value="templateVolcano">Volcano</option>
<option value="templateHighIsland">High Island</option>
<option value="templateLowIsland">Low Island</option>
<option value="templateContinents">Continents</option>
<option value="templateArchipelago">Archipelago</option>
<option value="templateAtoll">Atoll</option>
</select>
</div>
<div id="templateTools">
<button id="templateMountain" title="Mountain: high big blob. Can be placed only once and only as a first step" class="noicon">M</button>
<button id="templateHill" title="Hill: small blob" class="noicon">H</button>
<button id="templatePit" title="Pit: round depression" class="noicon">P</button>
<button id="templateRange" title="Pit: elongated elevation" class="noicon">R</button>
<button id="templateTrough" title="Trough: elongated depression" class="noicon">T</button>
<button id="templateStrait" title="Strait: centered vertical depression" class="noicon">S</button>
<button id="templateAdd" title="Add or subtract value from all heights" class="noicon">+</button>
<button id="templateMultiply" title="Multiply all heights by factor" class="noicon">*</button>
<button id="templateSmooth" title="Smooth the map replacing cell heights by an average values of its neighbors" class="noicon">~</button>
</div>
<div id="templateBody" data-changed=0>
<div data-type="Mountain">Mountain
<span title="Remove step" class="icon-trash-empty" onclick="this.parentNode.parentNode.removeChild(this.parentNode)"></span>
</div>
</div>
<div id="templateBottom">
<button id="templateRun" title="Apply current template" class="icon-play"></button>
<button id="templateClear" title="Clear the map" class="icon-cancel-circled2"></button>
<button id="templateComplete" title="Finalize the Heightmap. Not allowed if insufficient land area available" class="icon-check"></button>
<button id="templateLoad" title="Open previously saved template" class="icon-upload"></button>
<input type="file" accept=".txt" id="templateToLoad" style="display: none;">
<button id="templateSave" title="Save template" class="icon-download"></button>
</div>
</div>
<div id="imageConverter" style="display: none">
<div id="convertImageButtons">
<input type="file" accept="image/*" id="imageToLoad" style="display: none;">
<button id="convertImageLoad" title="Load image to convert" class="icon-upload"></button>
<button id="convertAutoLum" title="Auto-assign colors based on liminosity" class="icon-adjust"></button>
<button id="convertAutoHue" title="Auto-assign colors based on hue" class="icon-brush"></button>
<button id="convertColorsMinus" title="Reduce the number of colors. Minimal number is 3" class="icon-minus-squared"></button>
<button id="convertColorsPlus" title="Increase the number of colors. Minimal number is 256" class="icon-plus-squared"></button>
<input id="convertColors" value="12" style="display: none;"/>
<button id="convertImageGrid" title="Toggle grid" class="icon-eye"></button>
<button id="convertOverlayButton" title="Change overlay opacity" class="icon-clone"></button>
<input id="convertOverlay" title="Change overlay opacity" type="range" min="0" max="1" step="0.01" value="0" style="display: none;">
<span id="convertOverlayValue" title="Overlay opacity" style="display: none;">0</span>
<button id="convertComplete" title="Complete conversion. All unassigned colors will be considered as ocean" class="icon-check"></button>
</div>
<div id="colorsSelect">
<div id="colorScheme"></div>
<span id="colorsSelectValue">0</span>
</div>
<div id="colorsAssigned" style="display: none">
<label>Assigned colors: </label><br>
</div>
<div id="colorsUnassigned" style="display: none">
<label>Unassigned colors: </label><br>
</div>
</div>
<div id="heightmapRescaler" style="display: none">
<div id="rescalerButtons">
<button id="rescaleMultiply" title="Multiply heights by value" class="icon-cancel-circled"></button>
<button id="rescaleAdd" title="Add value to heights" class="icon-plus-circled"></button>
<input id="rescaleModifier" class="pureInput" title="Set modifier value. Value may be positive, negative, fractional, '^2', '^3'" type="number" value="1.1" min="0" max="10" step="0.01">
<input id="rescaleSubject" class="pureInput" title="Select change subject: 'all', 'land' or interval with hyphen withount space, e.g. '0.17-0.2'" value="land">
</div>
</div>
<div id="alert" title="Warning!" style="display: none">
<p id="alertMessage">Warning!</p>
</div>
<div id="statusbar">
Coord: <span id="lx">0</span>/<span id="ly">0</span>;
Cell: <span id="cell">0</span>;
Height: <span id="height">0</span>;
Type: <span id="feature">no</span>;
Flux: <span id="flux">0</span>;
Region: <span id="region">no</span>;
Culture: <span id="culture">no</span>;
River: <span id="river">no</span>;
Path: <span id="path">no</span>;
Score: <span id="score">no</span>.
</div>
<script type="text/javascript" src="script.js?version=0.52b"></script>
</body>
// Names are getting procedurally generated based on Markov chain approach. Training data is below:
var cultures = ["Shwazen","Angshire","Luari","Latian","Toledi","Slovian","Varangian"];
var manorNames = [
["Achern","Aichhalden","Aitern","Albbruck","Alpirsbach","Altensteig","Althengstett","Appenweier","Auggen","Wildbad","Badenen","Badenweiler","Baiersbronn","Ballrechten","Bellingen","Berghaupten","Bernau","Biberach","Biederbach","Binzen","Birkendorf","Birkenfeld","Bischweier","Blumberg","Bollen","Bollschweil","Bonndorf","Bosingen","Braunlingen","Breisach","Breisgau","Breitnau","Brigachtal","Buchenbach","Buggingen","Buhl","Buhlertal","Calw","Dachsberg","Dobel","Donaueschingen","Dornhan","Dornstetten","Dottingen","Dunningen","Durbach","Durrheim","Ebhausen","Ebringen","Efringen","Egenhausen","Ehrenkirchen","Ehrsberg","Eimeldingen","Eisenbach","Elzach","Elztal","Emmendingen","Endingen","Engelsbrand","Enz","Enzklosterle","Eschbronn","Ettenheim","Ettlingen","Feldberg","Fischerbach","Fischingen","Fluorn","Forbach","Freiamt","Freiburg","Freudenstadt","Friedenweiler","Friesenheim","Frohnd","Furtwangen","Gaggenau","Geisingen","Gengenbach","Gernsbach","Glatt","Glatten","Glottertal","Gorwihl","Gottenheim","Grafenhausen","Grenzach","Griesbach","Gutach","Gutenbach","Hag","Haiterbach","Hardt","Harmersbach","Hasel","Haslach","Hausach","Hausen","Hausern","Heitersheim","Herbolzheim","Herrenalb","Herrischried","Hinterzarten","Hochenschwand","Hofen","Hofstetten","Hohberg","Horb","Horben","Hornberg","Hufingen","Ibach","Ihringen","Inzlingen","Kandern","Kappel","Kappelrodeck","Karlsbad","Karlsruhe","Kehl","Keltern","Kippenheim","Kirchzarten","Konigsfeld","Krozingen","Kuppenheim","Kussaberg","Lahr","Lauchringen","Lauf","Laufenburg","Lautenbach","Lauterbach","Lenzkirch","Liebenzell","Loffenau","Loffingen","Lorrach","Lossburg","Mahlberg","Malsburg","Malsch","March","Marxzell","Marzell","Maulburg","Monchweiler","Muhlenbach","Mullheim","Munstertal","Murg","Nagold","Neubulach","Neuenburg","Neuhausen","Neuried","Neuweiler","Niedereschach","Nordrach","Oberharmersbach","Oberkirch","Oberndorf","Oberbach","Oberried","Oberwolfach","Offenburg","Ohlsbach","Oppenau","Ortenberg","otigheim","Ottenhofen","Ottersweier","Peterstal","Pfaffenweiler","Pfalzgrafenweiler","Pforzheim","Rastatt","Renchen","Rheinau","Rheinfelden","Rheinmunster","Rickenbach","Rippoldsau","Rohrdorf","Rottweil","Rummingen","Rust","Sackingen","Sasbach","Sasbachwalden","Schallbach","Schallstadt","Schapbach","Schenkenzell","Schiltach","Schliengen","Schluchsee","Schomberg","Schonach","Schonau","Schonenberg","Schonwald","Schopfheim","Schopfloch","Schramberg","Schuttertal","Schwenningen","Schworstadt","Seebach","Seelbach","Seewald","Sexau","Simmersfeld","Simonswald","Sinzheim","Solden","Staufen","Stegen","Steinach","Steinen","Steinmauern","Straubenhardt","Stuhlingen","Sulz","Sulzburg","Teinach","Tiefenbronn","Tiengen","Titisee","Todtmoos","Todtnau","Todtnauberg","Triberg","Tunau","Tuningen","uhlingen","Unterkirnach","Reichenbach","Utzenfeld","Villingen","Villingendorf","Vogtsburg","Vohrenbach","Waldachtal","Waldbronn","Waldkirch","Waldshut","Wehr","Weil","Weilheim","Weisenbach","Wembach","Wieden","Wiesental","Wildberg","Winzeln","Wittlingen","Wittnau","Wolfach","Wutach","Wutoschingen","Wyhlen","Zavelstein"],
["Abingdon","Albrighton","Alcester","Almondbury","Altrincham","Amersham","Andover","Appleby","Ashboume","Atherstone","Aveton","Axbridge","Aylesbury","Baldock","Bamburgh","Barton","Basingstoke","Berden","Bere","Berkeley","Berwick","Betley","Bideford","Bingley","Birmingham","Blandford","Blechingley","Bodmin","Bolton","Bootham","Boroughbridge","Boscastle","Bossinney","Bramber","Brampton","Brasted","Bretford","Bridgetown","Bridlington","Bromyard","Bruton","Buckingham","Bungay","Burton","Calne","Cambridge","Canterbury","Carlisle","Castleton","Caus","Charmouth","Chawleigh","Chichester","Chillington","Chinnor","Chipping","Chisbury","Cleobury","Clifford","Clifton","Clitheroe","Cockermouth","Coleshill","Combe","Congleton","Crafthole","Crediton","Cuddenbeck","Dalton","Darlington","Dodbrooke","Drax","Dudley","Dunstable","Dunster","Dunwich","Durham","Dymock","Exeter","Exning","Faringdon","Felton","Fenny","Finedon","Flookburgh","Fowey","Frampton","Gateshead","Gatton","Godmanchester","Grampound","Grantham","Guildford","Halesowen","Halton","Harbottle","Harlow","Hatfield","Hatherleigh","Haydon","Helston","Henley","Hertford","Heytesbury","Hinckley","Hitchin","Holme","Hornby","Horsham","Kendal","Kenilworth","Kilkhampton","Kineton","Kington","Kinver","Kirby","Knaresborough","Knutsford","Launceston","Leighton","Lewes","Linton","Louth","Luton","Lyme","Lympstone","Macclesfield","Madeley","Malborough","Maldon","Manchester","Manningtree","Marazion","Marlborough","Marshfield","Mere","Merryfield","Middlewich","Midhurst","Milborne","Mitford","Modbury","Montacute","Mousehole","Newbiggin","Newborough","Newbury","Newenden","Newent","Norham","Northleach","Noss","Oakham","Olney","Orford","Ormskirk","Oswestry","Padstow","Paignton","Penkneth","Penrith","Penzance","Pershore","Petersfield","Pevensey","Pickering","Pilton","Pontefract","Portsmouth","Preston","Quatford","Reading","Redcliff","Retford","Rockingham","Romney","Rothbury","Rothwell","Salisbury","Saltash","Seaford","Seasalter","Sherston","Shifnal","Shoreham","Sidmouth","Skipsea","Skipton","Solihull","Somerton","Southam","Southwark","Standon","Stansted","Stapleton","Stottesdon","Sudbury","Swavesey","Tamerton","Tarporley","Tetbury","Thatcham","Thaxted","Thetford","Thornbury","Tintagel","Tiverton","Torksey","Totnes","Towcester","Tregoney","Trematon","Tutbury","Uxbridge","Wallingford","Wareham","Warenmouth","Wargrave","Warton","Watchet","Watford","Wendover","Westbury","Westcheap","Weymouth","Whitford","Wickwar","Wigan","Wigmore","Winchelsea","Winkleigh","Wiscombe","Witham","Witheridge","Wiveliscombe","Woodbury","Yeovil"],
["Adon","Aillant","Amilly","Andonville","Ardon","Artenay","Ascheres","Ascoux","Attray","Aubin","Audeville","Aulnay","Autruy","Auvilliers","Auxy","Aveyron","Baccon","Bardon","Barville","Batilly","Baule","Bazoches","Beauchamps","Beaugency","Beaulieu","Beaune","Bellegarde","Boesses","Boigny","Boiscommun","Boismorand","Boisseaux","Bondaroy","Bonnee","Bonny","Bordes","Bou","Bougy","Bouilly","Boulay","Bouzonville","Bouzy","Boynes","Bray","Breteau","Briare","Briarres","Bricy","Bromeilles","Bucy","Cepoy","Cercottes","Cerdon","Cernoy","Cesarville","Chailly","Chaingy","Chalette","Chambon","Champoulet","Chanteau","Chantecoq","Chapell","Charme","Charmont","Charsonville","Chateau","Chateauneuf","Chatel","Chatenoy","Chatillon","Chaussy","Checy","Chevannes","Chevillon","Chevilly","Chevry","Chilleurs","Choux","Chuelles","Clery","Coinces","Coligny","Combleux","Combreux","Conflans","Corbeilles","Corquilleroy","Cortrat","Coudroy","Coullons","Coulmiers","Courcelles","Courcy","Courtemaux","Courtempierre","Courtenay","Cravant","Crottes","Dadonville","Dammarie","Dampierre","Darvoy","Desmonts","Dimancheville","Donnery","Dordives","Dossainville","Douchy","Dry","Echilleuses","Egry","Engenville","Epieds","Erceville","Ervauville","Escrennes","Escrignelles","Estouy","Faverelles","Fay","Feins","Ferolles","Ferrieres","Fleury","Fontenay","Foret","Foucherolles","Freville","Gatinais","Gaubertin","Gemigny","Germigny","Gidy","Gien","Girolles","Givraines","Gondreville","Grangermont","Greneville","Griselles","Guigneville","Guilly","Gyleslonains","Huetre","Huisseau","Ingrannes","Ingre","Intville","Isdes","Jargeau","Jouy","Juranville","Bussiere","Laas","Ladon","Lailly","Langesse","Leouville","Ligny","Lombreuil","Lorcy","Lorris","Loury","Louzouer","Malesherbois","Marcilly","Mardie","Mareau","Marigny","Marsainvilliers","Melleroy","Menestreau","Merinville","Messas","Meung","Mezieres","Migneres","Mignerette","Mirabeau","Montargis","Montbarrois","Montbouy","Montcresson","Montereau","Montigny","Montliard","Mormant","Morville","Moulinet","Moulon","Nancray","Nargis","Nesploy","Neuville","Neuvy","Nevoy","Nibelle","Nogent","Noyers","Ocre","Oison","Olivet","Ondreville","Onzerain","Orleans","Ormes","Orville","Oussoy","Outarville","Ouzouer","Pannecieres","Pannes","Patay","Paucourt","Pers","Pierrefitte","Pithiverais","Pithiviers","Poilly","Potier","Prefontaines","Presnoy","Pressigny","Puiseaux","Quiers","Ramoulu","Rebrechien","Rouvray","Rozieres","Rozoy","Ruan","Sandillon","Santeau","Saran","Sceaux","Seichebrieres","Semoy","Sennely","Sermaises","Sigloy","Solterre","Sougy","Sully","Sury","Tavers","Thignonville","Thimory","Thorailles","Thou","Tigy","Tivernon","Tournoisis","Trainou","Treilles","Trigueres","Trinay","Vannes","Varennes","Vennecy","Vieilles","Vienne","Viglain","Vignes","Villamblain","Villemandeur","Villemoutiers","Villemurlin","Villeneuve","Villereau","Villevoques","Villorceau","Vimory","Vitry","Vrigny","Ivre"],
["Accumoli","Acquafondata","Acquapendente","Acuto","Affile","Agosta","Alatri","Albano","Allumiere","Alvito","Amaseno","Amatrice","Anagni","Anguillara","Anticoli","Antrodoco","Anzio","Aprilia","Aquino","Arce","Arcinazzo","Ardea","Ariccia","Arlena","Arnara","Arpino","Arsoli","Artena","Ascrea","Atina","Ausonia","Bagnoregio","Barbarano","Bassano","Bassiano","Bellegra","Belmonte","Blera","Bolsena","Bomarzo","Borbona","Borgo","Borgorose","Boville","Bracciano","Broccostella","Calcata","Camerata","Campagnano","Campodimele","Campoli","Canale","Canepina","Canino","Cantalice","Cantalupo","Canterano","Capena","Capodimonte","Capranica","Caprarola","Carbognano","Casalattico","Casalvieri","Casape","Casaprota","Casperia","Cassino","Castelforte","Castelliri","Castello","Castelnuovo","Castiglione","Castro","Castrocielo","Cave","Ceccano","Celleno","Cellere","Ceprano","Cerreto","Cervara","Cervaro","Cerveteri","Ciampino","Ciciliano","Cineto","Cisterna","Cittaducale","Cittareale","Civita","Civitavecchia","Civitella","Colfelice","Collalto","Colle","Colleferro","Collegiove","Collepardo","Collevecchio","Colli","Colonna","Concerviano","Configni","Contigliano","Corchiano","Coreno","Cori","Cottanello","Esperia","Fabrica","Faleria","Falvaterra","Fara","Farnese","Ferentino","Fiamignano","Fiano","Filacciano","Filettino","Fiuggi","Fiumicino","Fondi","Fontana","Fonte","Fontechiari","Forano","Formello","Formia","Frascati","Frasso","Frosinone","Fumone","Gaeta","Gallese","Gallicano","Gallinaro","Gavignano","Genazzano","Genzano","Gerano","Giuliano","Gorga","Gradoli","Graffignano","Greccio","Grottaferrata","Grotte","Guarcino","Guidonia","Ischia","Isola","Itri","Jenne","Labico","Labro","Ladispoli","Lanuvio","Lariano","Latera","Lenola","Leonessa","Licenza","Longone","Lubriano","Maenza","Magliano","Mandela","Manziana","Marano","Marcellina","Marcetelli","Marino","Marta","Mazzano","Mentana","Micigliano","Minturno","Mompeo","Montalto","Montasola","Monte","Montebuono","Montefiascone","Monteflavio","Montelanico","Monteleone","Montelibretti","Montenero","Monterosi","Monterotondo","Montopoli","Montorio","Moricone","Morlupo","Morolo","Morro","Nazzano","Nemi","Nepi","Nerola","Nespolo","Nettuno","Norma","Olevano","Onano","Oriolo","Orte","Orvinio","Paganico","Palestrina","Paliano","Palombara","Pastena","Patrica","Percile","Pescorocchiano","Pescosolido","Petrella","Piansano","Picinisco","Pico","Piedimonte","Piglio","Pignataro","Pisoniano","Pofi","Poggio","Poli","Pomezia","Pontecorvo","Pontinia","Ponza","Ponzano","Posta","Pozzaglia","Priverno","Proceno","Prossedi","Riano","Rieti","Rignano","Riofreddo","Ripi","Rivodutri","Rocca","Roccagiovine","Roccagorga","Roccantica","Roccasecca","Roiate","Ronciglione","Roviano","Sabaudia","Sacrofano","Salisano","Sambuci","Santa","Santi","Santopadre","Saracinesco","Scandriglia","Segni","Selci","Sermoneta","Serrone","Settefrati","Sezze","Sgurgola","Sonnino","Sora","Soriano","Sperlonga","Spigno","Stimigliano","Strangolagalli","Subiaco","Supino","Sutri","Tarano","Tarquinia","Terelle","Terracina","Tessennano","Tivoli","Toffia","Tolfa","Torre","Torri","Torrice","Torricella","Torrita","Trevi","Trevignano","Trivigliano","Turania","Tuscania","Vacone","Valentano","Vallecorsa","Vallemaio","Vallepietra","Vallerano","Vallerotonda","Vallinfreda","Valmontone","Varco","Vasanello","Vejano","Velletri","Ventotene","Veroli","Vetralla","Vicalvi","Vico","Vicovaro","Vignanello","Viterbo","Viticuso","Vitorchiano","Vivaro","Zagarolo"],
["Abanades","Ablanque","Adobes","Ajofrin","Alameda","Alaminos","Alarilla","Albalate","Albares","Albarreal","Albendiego","Alcabon","Alcanizo","Alcaudete","Alcocer","Alcolea","Alcoroches","Aldea","Aldeanueva","Algar","Algora","Alhondiga","Alique","Almadrones","Almendral","Almoguera","Almonacid","Almorox","Alocen","Alovera","Alustante","Angon","Anguita","Anover","Anquela","Arbancon","Arbeteta","Arcicollar","Argecilla","Arges","Armallones","Armuna","Arroyo","Atanzon","Atienza","Aunon","Azuqueca","Azutan","Baides","Banos","Banuelos","Barcience","Bargas","Barriopedro","Belvis","Berninches","Borox","Brihuega","Budia","Buenaventura","Bujalaro","Burguillos","Burujon","Bustares","Cabanas","Cabanillas","Calera","Caleruela","Calzada","Camarena","Campillo","Camunas","Canizar","Canredondo","Cantalojas","Cardiel","Carmena","Carranque","Carriches","Casa","Casarrubios","Casas","Casasbuenas","Caspuenas","Castejon","Castellar","Castilforte","Castillo","Castilnuevo","Cazalegas","Cebolla","Cedillo","Cendejas","Centenera","Cervera","Checa","Chequilla","Chillaron","Chiloeches","Chozas","Chueca","Cifuentes","Cincovillas","Ciruelas","Ciruelos","Cobeja","Cobeta","Cobisa","Cogollor","Cogolludo","Condemios","Congostrina","Consuegra","Copernal","Corduente","Corral","Cuerva","Domingo","Dosbarrios","Driebes","Duron","El","Embid","Erustes","Escalona","Escalonilla","Escamilla","Escariche","Escopete","Espinosa","Espinoso","Esplegares","Esquivias","Estables","Estriegana","Fontanar","Fuembellida","Fuensalida","Fuentelsaz","Gajanejos","Galve","Galvez","Garciotum","Gascuena","Gerindote","Guadamur","Henche","Heras","Herreria","Herreruela","Hijes","Hinojosa","Hita","Hombrados","Hontanar","Hontoba","Horche","Hormigos","Huecas","Huermeces","Huerta","Hueva","Humanes","Illan","Illana","Illescas","Iniestola","Irueste","Jadraque","Jirueque","Lagartera","Las","Layos","Ledanca","Lillo","Lominchar","Loranca","Los","Lucillos","Lupiana","Luzaga","Luzon","Madridejos","Magan","Majaelrayo","Malaga","Malaguilla","Malpica","Mandayona","Mantiel","Manzaneque","Maqueda","Maranchon","Marchamalo","Marjaliza","Marrupe","Mascaraque","Masegoso","Matarrubia","Matillas","Mazarete","Mazuecos","Medranda","Megina","Mejorada","Mentrida","Mesegar","Miedes","Miguel","Millana","Milmarcos","Mirabueno","Miralrio","Mocejon","Mochales","Mohedas","Molina","Monasterio","Mondejar","Montarron","Mora","Moratilla","Morenilla","Muduex","Nambroca","Navalcan","Negredo","Noblejas","Noez","Nombela","Noves","Numancia","Nuno","Ocana","Ocentejo","Olias","Olmeda","Ontigola","Orea","Orgaz","Oropesa","Otero","Palmaces","Palomeque","Pantoja","Pardos","Paredes","Pareja","Parrillas","Pastrana","Pelahustan","Penalen","Penalver","Pepino","Peralejos","Peralveche","Pinilla","Pioz","Piqueras","Polan","Portillo","Poveda","Pozo","Pradena","Prados","Puebla","Puerto","Pulgar","Quer","Quero","Quintanar","Quismondo","Rebollosa","Recas","Renera","Retamoso","Retiendas","Riba","Rielves","Rillo","Riofrio","Robledillo","Robledo","Romanillos","Romanones","Rueda","Sacecorbo","Sacedon","Saelices","Salmeron","San","Santa","Santiuste","Santo","Sartajada","Sauca","Sayaton","Segurilla","Selas","Semillas","Sesena","Setiles","Sevilleja","Sienes","Siguenza","Solanillos","Somolinos","Sonseca","Sotillo","Sotodosos","Talavera","Tamajon","Taragudo","Taravilla","Tartanedo","Tembleque","Tendilla","Terzaga","Tierzo","Tordellego","Tordelrabano","Tordesilos","Torija","Torralba","Torre","Torrecilla","Torrecuadrada","Torrejon","Torremocha","Torrico","Torrijos","Torrubia","Tortola","Tortuera","Tortuero","Totanes","Traid","Trijueque","Trillo","Turleque","Uceda","Ugena","Ujados","Urda","Utande","Valdarachas","Valdesotos","Valhermoso","Valtablado","Valverde","Velada","Viana","Vinuelas","Yebes","Yebra","Yelamos","Yeles","Yepes","Yuncler","Yunclillos","Yuncos","Yunquera","Zaorejas","Zarzuela","Zorita"],
["Belgorod","Beloberezhye","Belyi","Belz","Berestei","Berezhets","Berezovech","Berezutsk","Bobruisk","Bolonets","Borisov","Borovsk","Bozhesk","Bratslav","Bryansk","Brynsk","Buryn","Byhov","Chechersk","Chemesov","Cheremosh","Cherlen","Chern","Chernigov","Chernitsa","Chernobyl","Chernogorod","Chertoryesk","Chetvertnia","Demyansk","Derevesk","Devyagoresk","Dichin","Dmitrov","Dorogobuch","Dorogobuzh","Drestvin","Drokov","Drutsk","Dubechin","Dubichi","Dubki","Dubkov","Dveren","Galich","Glebovo","Glinsk","Goloty","Gomiy","Gorodets","Gorodische","Gorodno","Gorohovets","Goroshin","Gorval","Goryshon","Holm","Horobor","Hoten","Hotin","Hotmyzhsk","Ilovech","Ivan","Izborsk","Izheslavl","Kamenets","Kanev","Karachev","Karna","Kavarna","Klechesk","Klyapech","Kolomyya","Kolyvan","Kopyl","Korec","Kornik","Korochunov","Korshev","Korsun","Koshkin","Kotelno","Kovyla","Kozelsk","Kozelsk","Kremenets","Krichev","Krylatsk","Ksniatin","Kulatsk","Kursk","Kursk","Lebedev","Lida","Logosko","Lomihvost","Loshesk","Loshichi","Lubech","Lubno","Lubutsk","Lutsk","Luchin","Luki","Lukoml","Luzha","Lvov","Mtsensk","Mdin","Medniki","Melecha","Merech","Meretsk","Mescherskoe","Meshkovsk","Metlitsk","Mezetsk","Mglin","Mihailov","Mikitin","Mikulino","Miloslavichi","Mogilev","Mologa","Moreva","Mosalsk","Moschiny","Mozyr","Mstislav","Mstislavets","Muravin","Nemech","Nemiza","Nerinsk","Nichan","Novgorod","Novogorodok","Obolichi","Obolensk","Obolensk","Oleshsk","Olgov","Omelnik","Opoka","Opoki","Oreshek","Orlets","Osechen","Oster","Ostrog","Ostrov","Perelai","Peremil","Peremyshl","Pererov","Peresechen","Perevitsk","Pereyaslav","Pinsk","Ples","Polotsk","Pronsk","Proposhesk","Punia","Putivl","Rechitsa","Rodno","Rogachev","Romanov","Romny","Roslavl","Rostislavl","Rostovets","Rsha","Ruza","Rybchesk","Rylsk","Rzhavesk","Rzhev","Rzhischev","Sambor","Serensk","Serensk","Serpeysk","Shilov","Shuya","Sinech","Sizhka","Skala","Slovensk","Slutsk","Smedin","Sneporod","Snitin","Snovsk","Sochevo","Sokolec","Starica","Starodub","Stepan","Sterzh","Streshin","Sutesk","Svinetsk","Svisloch","Terebovl","Ternov","Teshilov","Teterin","Tiversk","Torchevsk","Toropets","Torzhok","Tripolye","Trubchevsk","Tur","Turov","Usvyaty","Uteshkov","Vasilkov","Velil","Velye","Venev","Venicha","Verderev","Vereya","Veveresk","Viazma","Vidbesk","Vidychev","Voino","Volodimer","Volok","Volyn","Vorobesk","Voronich","Voronok","Vorotynsk","Vrev","Vruchiy","Vselug","Vyatichsk","Vyatka","Vyshegorod","Vyshgorod","Vysokoe","Yagniatin","Yaropolch","Yasenets","Yuryev","Yuryevets","Zaraysk","Zhitomel","Zholvazh","Zizhech","Zubkov","Zudechev","Zvenigorod"],
["Akureyri","Aldra","Alftanes","Andenes","Austbo","Auvog","Bakkafjordur","Ballangen","Bardal","Beisfjord","Bifrost","Bildudalur","Bjerka","Bjerkvik","Bjorkosen","Bliksvaer","Blokken","Blonduos","Bolga","Bolungarvik","Borg","Borgarnes","Bosmoen","Bostad","Bostrand","Botsvika","Brautarholt","Breiddalsvik","Bringsli","Brunahlid","Budardalur","Byggdakjarni","Dalvik","Djupivogur","Donnes","Drageid","Drangsnes","Egilsstadir","Eiteroga","Elvenes","Engavogen","Ertenvog","Eskifjordur","Evenes","Eyrarbakki","Fagernes","Fallmoen","Fellabaer","Fenes","Finnoya","Fjaer","Fjelldal","Flakstad","Flateyri","Flostrand","Fludir","Gardabær","Gardur","Gimstad","Givaer","Gjeroy","Gladstad","Godoya","Godoynes","Granmoen","Gravdal","Grenivik","Grimsey","Grindavik","Grytting","Hafnir","Halsa","Hauganes","Haugland","Hauknes","Hella","Helland","Hellissandur","Hestad","Higrav","Hnifsdalur","Hofn","Hofsos","Holand","Holar","Holen","Holkestad","Holmavik","Hopen","Hovden","Hrafnagil","Hrisey","Husavik","Husvik","Hvammstangi","Hvanneyri","Hveragerdi","Hvolsvollur","Igeroy","Indre","Inndyr","Innhavet","Innnes","Isafjordur","Jarklaustur","Jarnsreykir","Junkerdal","Kaldvog","Kanstad","Karlsoy","Kavosen","Keflavik","Kjelde","Kjerstad","Klakk","Kopasker","Kopavogur","Korgen","Kristnes","Krutoga","Krystad","Kvina","Lande","Laugar","Laugaras","Laugarbakki","Laugarvatn","Laupstad","Leines","Leira","Leiren","Leland","Lenvika","Loding","Lodingen","Lonsbakki","Lopsmarka","Lovund","Luroy","Maela","Melahverfi","Meloy","Mevik","Misvaer","Mornes","Mosfellsbær","Moskenes","Myken","Naurstad","Nesberg","Nesjahverfi","Nesset","Nevernes","Obygda","Ofoten","Ogskardet","Okervika","Oknes","Olafsfjordur","Oldervika","Olstad","Onstad","Oppeid","Oresvika","Orsnes","Orsvog","Osmyra","Overdal","Prestoya","Raudalaekur","Raufarhofn","Reipo","Reykholar","Reykholt","Reykjahlid","Rif","Rinoya","Rodoy","Rognan","Rosvika","Rovika","Salhus","Sanden","Sandgerdi","Sandoker","Sandset","Sandvika","Saudarkrokur","Selfoss","Selsoya","Sennesvik","Setso","Siglufjordur","Silvalen","Skagastrond","Skjerstad","Skonland","Skorvogen","Skrova","Sleneset","Snubba","Softing","Solheim","Solheimar","Sorarnoy","Sorfugloy","Sorland","Sormela","Sorvaer","Sovika","Stamsund","Stamsvika","Stave","Stokka","Stokkseyri","Storjord","Storo","Storvika","Strand","Straumen","Strendene","Sudavik","Sudureyri","Sundoya","Sydalen","Thingeyri","Thorlakshofn","Thorshofn","Tjarnabyggd","Tjotta","Tosbotn","Traelnes","Trofors","Trones","Tverro","Ulvsvog","Unnstad","Utskor","Valla","Vandved","Varmahlid","Vassos","Vevelstad","Vidrek","Vik","Vikholmen","Vogar","Vogehamn","Vopnafjordur"]
];
// Forked from color-thief.js Copyright 2011 Lokesh Dhakar under MIT license
// var pixelArray = [[190,197,190], [202,204,200], [207,214,210]]; // ... etc;
// var cmap = MMCQ.quantize(pixelArray, colorCount);
// var palette = cmap ? cmap.palette() : null;
// Protovis. Copyright 2010 Stanford Visualization Group (http://mbostock.github.com/protovis/)
// Licensed under the BSD License: http://www.opensource.org/licenses/bsd-license.php
if (!pv) {
var pv = {
map: function(array, f) {
var o = {};
return f ? array.map(function(d, i) { o.index = i; return f.call(o, d); }) : array.slice();
},
naturalOrder: function(a, b) {
return (a < b) ? -1 : ((a > b) ? 1 : 0);
},
sum: function(array, f) {
var o = {};
return array.reduce(f ? function(p, d, i) { o.index = i; return p + f.call(o, d); } : function(p, d) { return p + d; }, 0);
},
max: function(array, f) {
return Math.max.apply(null, f ? pv.map(array, f) : array);
}
};
}
// MMCQ (Modified median cut quantization). Algorithm from the Leptonica library, modified by Nick Rabinowitz
// quantize.js Copyright 2008 Nick Rabinowitz under MIT license
var MMCQ = (function() {
// private constants
var sigbits = 5,
rshift = 8 - sigbits,
maxIterations = 1000,
fractByPopulations = 0.75;
// get reduced-space color index for a pixel
function getColorIndex(r, g, b) {
return (r << (2 * sigbits)) + (g << sigbits) + b;
}
// Simple priority queue
function PQueue(comparator) {
var contents = [],
sorted = false;
function sort() {
contents.sort(comparator);
sorted = true;
}
return {
push: function(o) {
contents.push(o);
sorted = false;
},
peek: function(index) {
if (!sorted) sort();
if (index===undefined) index = contents.length - 1;
return contents[index];
},
pop: function() {
if (!sorted) sort();
return contents.pop();
},
size: function() {
return contents.length;
},
map: function(f) {
return contents.map(f);
},
debug: function() {
if (!sorted) sort();
return contents;
}
};
}
// 3d color space box
function VBox(r1, r2, g1, g2, b1, b2, histo) {
var vbox = this;
vbox.r1 = r1;
vbox.r2 = r2;
vbox.g1 = g1;
vbox.g2 = g2;
vbox.b1 = b1;
vbox.b2 = b2;
vbox.histo = histo;
}
VBox.prototype = {
volume: function(force) {
var vbox = this;
if (!vbox._volume || force) {
vbox._volume = ((vbox.r2 - vbox.r1 + 1) * (vbox.g2 - vbox.g1 + 1) * (vbox.b2 - vbox.b1 + 1));
}
return vbox._volume;
},
count: function(force) {
var vbox = this,
histo = vbox.histo;
if (!vbox._count_set || force) {
var npix = 0,
index, i, j, k;
for (i = vbox.r1; i <= vbox.r2; i++) {
for (j = vbox.g1; j <= vbox.g2; j++) {
for (k = vbox.b1; k <= vbox.b2; k++) {
index = getColorIndex(i,j,k);
npix += (histo[index] || 0);
}
}
}
vbox._count = npix;
vbox._count_set = true;
}
return vbox._count;
},
copy: function() {
var vbox = this;
return new VBox(vbox.r1, vbox.r2, vbox.g1, vbox.g2, vbox.b1, vbox.b2, vbox.histo);
},
avg: function(force) {
var vbox = this,
histo = vbox.histo;
if (!vbox._avg || force) {
var ntot = 0,
mult = 1 << (8 - sigbits),
rsum = 0,
gsum = 0,
bsum = 0,
hval,
i, j, k, histoindex;
for (i = vbox.r1; i <= vbox.r2; i++) {
for (j = vbox.g1; j <= vbox.g2; j++) {
for (k = vbox.b1; k <= vbox.b2; k++) {
histoindex = getColorIndex(i,j,k);
hval = histo[histoindex] || 0;
ntot += hval;
rsum += (hval * (i + 0.5) * mult);
gsum += (hval * (j + 0.5) * mult);
bsum += (hval * (k + 0.5) * mult);
}
}
}
if (ntot) {
vbox._avg = [~~(rsum/ntot), ~~(gsum/ntot), ~~(bsum/ntot)];
} else {
// console.log('empty box');
vbox._avg = [
~~(mult * (vbox.r1 + vbox.r2 + 1) / 2),
~~(mult * (vbox.g1 + vbox.g2 + 1) / 2),
~~(mult * (vbox.b1 + vbox.b2 + 1) / 2)
];
}
}
return vbox._avg;
},
contains: function(pixel) {
var vbox = this,
rval = pixel[0] >> rshift;
gval = pixel[1] >> rshift;
bval = pixel[2] >> rshift;
return (rval >= vbox.r1 && rval <= vbox.r2 &&
gval >= vbox.g1 && gval <= vbox.g2 &&
bval >= vbox.b1 && bval <= vbox.b2);
}
};
// Color map
function CMap() {
this.vboxes = new PQueue(function(a,b) {
return pv.naturalOrder(
a.vbox.count()*a.vbox.volume(),
b.vbox.count()*b.vbox.volume()
);
});
}
CMap.prototype = {
push: function(vbox) {
this.vboxes.push({
vbox: vbox,
color: vbox.avg()
});
},
palette: function() {
return this.vboxes.map(function(vb) { return vb.color; });
},
size: function() {
return this.vboxes.size();
},
map: function(color) {
var vboxes = this.vboxes;
for (var i=0; i<vboxes.size(); i++) {
if (vboxes.peek(i).vbox.contains(color)) {
return vboxes.peek(i).color;
}
}
return this.nearest(color);
},
nearest: function(color) {
var vboxes = this.vboxes,
d1, d2, pColor;
for (var i=0; i<vboxes.size(); i++) {
d2 = Math.sqrt(
Math.pow(color[0] - vboxes.peek(i).color[0], 2) +
Math.pow(color[1] - vboxes.peek(i).color[1], 2) +
Math.pow(color[2] - vboxes.peek(i).color[2], 2)
);
if (d2 < d1 || d1 === undefined) {
d1 = d2;
pColor = vboxes.peek(i).color;
}
}
return pColor;
},
forcebw: function() {
// XXX: won't work yet
var vboxes = this.vboxes;
vboxes.sort(function(a,b) { return pv.naturalOrder(pv.sum(a.color), pv.sum(b.color));});
// force darkest color to black if everything < 5
var lowest = vboxes[0].color;
if (lowest[0] < 5 && lowest[1] < 5 && lowest[2] < 5)
vboxes[0].color = [0,0,0];
// force lightest color to white if everything > 251
var idx = vboxes.length-1,
highest = vboxes[idx].color;
if (highest[0] > 251 && highest[1] > 251 && highest[2] > 251)
vboxes[idx].color = [255,255,255];
}
};
// histo (1-d array, giving the number of pixels in
// each quantized region of color space), or null on error
function getHisto(pixels) {
var histosize = 1 << (3 * sigbits),
histo = new Array(histosize),
index, rval, gval, bval;
pixels.forEach(function(pixel) {
rval = pixel[0] >> rshift;
gval = pixel[1] >> rshift;
bval = pixel[2] >> rshift;
index = getColorIndex(rval, gval, bval);
histo[index] = (histo[index] || 0) + 1;
});
return histo;
}
function vboxFromPixels(pixels, histo) {
var rmin=1000000, rmax=0,
gmin=1000000, gmax=0,
bmin=1000000, bmax=0,
rval, gval, bval;
// find min/max
pixels.forEach(function(pixel) {
rval = pixel[0] >> rshift;
gval = pixel[1] >> rshift;
bval = pixel[2] >> rshift;
if (rval < rmin) rmin = rval;
else if (rval > rmax) rmax = rval;
if (gval < gmin) gmin = gval;
else if (gval > gmax) gmax = gval;
if (bval < bmin) bmin = bval;
else if (bval > bmax) bmax = bval;
});
return new VBox(rmin, rmax, gmin, gmax, bmin, bmax, histo);
}
function medianCutApply(histo, vbox) {
if (!vbox.count()) return;
var rw = vbox.r2 - vbox.r1 + 1,
gw = vbox.g2 - vbox.g1 + 1,
bw = vbox.b2 - vbox.b1 + 1,
maxw = pv.max([rw, gw, bw]);
// only one pixel, no split
if (vbox.count() == 1) {
return [vbox.copy()];
}
/* Find the partial sum arrays along the selected axis. */
var total = 0,
partialsum = [],
lookaheadsum = [],
i, j, k, sum, index;
if (maxw == rw) {
for (i = vbox.r1; i <= vbox.r2; i++) {
sum = 0;
for (j = vbox.g1; j <= vbox.g2; j++) {
for (k = vbox.b1; k <= vbox.b2; k++) {
index = getColorIndex(i,j,k);
sum += (histo[index] || 0);
}
}
total += sum;
partialsum[i] = total;
}
}
else if (maxw == gw) {
for (i = vbox.g1; i <= vbox.g2; i++) {
sum = 0;
for (j = vbox.r1; j <= vbox.r2; j++) {
for (k = vbox.b1; k <= vbox.b2; k++) {
index = getColorIndex(j,i,k);
sum += (histo[index] || 0);
}
}
total += sum;
partialsum[i] = total;
}
}
else { /* maxw == bw */
for (i = vbox.b1; i <= vbox.b2; i++) {
sum = 0;
for (j = vbox.r1; j <= vbox.r2; j++) {
for (k = vbox.g1; k <= vbox.g2; k++) {
index = getColorIndex(j,k,i);
sum += (histo[index] || 0);
}
}
total += sum;
partialsum[i] = total;
}
}
partialsum.forEach(function(d,i) {
lookaheadsum[i] = total-d;
});
function doCut(color) {
var dim1 = color + '1',
dim2 = color + '2',
left, right, vbox1, vbox2, d2, count2=0;
for (i = vbox[dim1]; i <= vbox[dim2]; i++) {
if (partialsum[i] > total / 2) {
vbox1 = vbox.copy();
vbox2 = vbox.copy();
left = i - vbox[dim1];
right = vbox[dim2] - i;
if (left <= right)
d2 = Math.min(vbox[dim2] - 1, ~~(i + right / 2));
else d2 = Math.max(vbox[dim1], ~~(i - 1 - left / 2));
// avoid 0-count boxes
while (!partialsum[d2]) d2++;
count2 = lookaheadsum[d2];
while (!count2 && partialsum[d2-1]) count2 = lookaheadsum[--d2];
// set dimensions
vbox1[dim2] = d2;
vbox2[dim1] = vbox1[dim2] + 1;
// console.log('vbox counts:', vbox.count(), vbox1.count(), vbox2.count());
return [vbox1, vbox2];
}
}
}
// determine the cut planes
return maxw == rw ? doCut('r') :
maxw == gw ? doCut('g') :
doCut('b');
}
function quantize(pixels, maxcolors) {
maxcolors++;
if (!pixels.length || maxcolors < 2 || maxcolors > 256) {return false;}
// XXX: check color content and convert to grayscale if insufficient
var histo = getHisto(pixels),
histosize = 1 << (3 * sigbits);
// check that we aren't below maxcolors already
var nColors = 0;
histo.forEach(function() { nColors++; });
if (nColors <= maxcolors) {
// XXX: generate the new colors from the histo and return
}
// get the beginning vbox from the colors
var vbox = vboxFromPixels(pixels, histo),
pq = new PQueue(function(a,b) { return pv.naturalOrder(a.count(), b.count()); });
pq.push(vbox);
// inner function to do the iteration
function iter(lh, target) {
var ncolors = 1,
niters = 0,
vbox;
while (niters < maxIterations) {
vbox = lh.pop();
if (!vbox.count()) { /* just put it back */
lh.push(vbox);
niters++;
continue;
}
// do the cut
var vboxes = medianCutApply(histo, vbox),
vbox1 = vboxes[0],
vbox2 = vboxes[1];
if (!vbox1) {
// console.log("vbox1 not defined; shouldn't happen!");
return;
}
lh.push(vbox1);
if (vbox2) { /* vbox2 can be null */
lh.push(vbox2);
ncolors++;
}
if (ncolors >= target) return;
if (niters++ > maxIterations) {
// console.log("infinite loop; perhaps too few pixels!");
return;
}
}
}
// first set of colors, sorted by population
iter(pq, fractByPopulations * maxcolors);
// Re-sort by the product of pixel occupancy times the size in color space.
var pq2 = new PQueue(function(a,b) {
return pv.naturalOrder(a.count()*a.volume(), b.count()*b.volume());
});
while (pq.size()) {
pq2.push(pq.pop());
}
// next set - generate the median cuts using the (npix * vol) sorting.
iter(pq2, maxcolors - pq2.size());
// calculate the actual colors
var cmap = new CMap();
while (pq2.size()) {cmap.push(pq2.pop());}
return cmap;
}
return {
quantize: quantize
};
})();
// Fantasy Map Generator main script (Azgaar 2018, licensed under GPL 3.0)
"use strict;"
fantasyMap();
function fantasyMap() {
// Declare variables
var svg = d3.select("svg"),
mapWidth = +svg.attr("width"),
mapHeight = +svg.attr("height"),
defs = svg.select("#deftemp"),
viewbox = svg.append("g").attr("id", "viewbox").on("touchmove mousemove", moved).on("click", clicked),
ocean = viewbox.append("g").attr("id", "ocean"),
oceanLayers = ocean.append("g").attr("id", "oceanLayers"),
oceanPattern = ocean.append("g").attr("id", "oceanPattern"),
landmass = viewbox.append("g").attr("id", "landmass"),
terrs = viewbox.append("g").attr("id", "terrs"),
cults = viewbox.append("g").attr("id", "cults"),
routes = viewbox.append("g").attr("id", "routes"),
roads = routes.append("g").attr("id", "roads"),
trails = routes.append("g").attr("id", "trails"),
rivers = viewbox.append("g").attr("id", "rivers"),
terrain = viewbox.append("g").attr("id", "terrain"),
regions = viewbox.append("g").attr("id", "regions"),
borders = viewbox.append("g").attr("id", "borders"),
stateBorders = borders.append("g").attr("id", "stateBorders"),
neutralBorders = borders.append("g").attr("id", "neutralBorders"),
coastline = viewbox.append("g").attr("id", "coastline"),
lakes = viewbox.append("g").attr("id", "lakes"),
grid = viewbox.append("g").attr("id", "grid"),
searoutes = routes.append("g").attr("id", "searoutes"),
labels = viewbox.append("g").attr("id", "labels"),
icons = viewbox.append("g").attr("id", "icons"),
burgs = icons.append("g").attr("id", "burgs"),
debug = viewbox.append("g").attr("id", "debug");
// Declare styles
landmass.attr("fill", "#eef6fb");
coastline.attr("opacity", .5).attr("stroke", "#1f3846").attr("stroke-width", .7).attr("filter", "url(#blurFilter)");
regions.attr("opacity", .55);
stateBorders.attr("opacity", .8).attr("stroke", "#56566d").attr("stroke-width", .5).attr("stroke-dasharray", "1.2 1.5").attr("stroke-linecap", "butt");
neutralBorders.attr("opacity", .8).attr("stroke", "#56566d").attr("stroke-width", .3).attr("stroke-dasharray", "1 1.5").attr("stroke-linecap", "butt");
cults.attr("opacity", .6);
rivers.attr("fill", "#5d97bb");
lakes.attr("fill", "#a6c1fd").attr("stroke", "#477794").attr("stroke-width", .3);
burgs.attr("fill", "#ffffff").attr("stroke", "#3e3e4b");
roads.attr("opacity", .8).attr("stroke", "#d06324").attr("stroke-width", .4).attr("stroke-dasharray", "1 2").attr("stroke-linecap", "round");
trails.attr("opacity", .8).attr("stroke", "#d06324").attr("stroke-width", .1).attr("stroke-dasharray", ".5 1").attr("stroke-linecap", "round");
searoutes.attr("opacity", .8).attr("stroke", "#ffffff").attr("stroke-width", .2).attr("stroke-dasharray", "1 2").attr("stroke-linecap", "round");
grid.attr("stroke", "#808080").attr("stroke-width", .1);
// canvas
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
// Color schemes
var color = d3.scaleSequential(d3.interpolateSpectral),
colors8 = d3.scaleOrdinal(d3.schemeSet2),
colors20 = d3.scaleOrdinal(d3.schemeCategory20);
// Version control
var version = "0.52b";
document.title = document.title + " v. " + version;
// Common variables
var customization, elSelected, cells = [], land = [], riversData = [], manors = [],
queue = [], chain = {}, island = 0, cultureTree, manorTree;
var graphSize = +sizeInput.value,
manorsCount = manorsInput.value,
capitalsCount = regionsInput.value,
power = powerInput.value,
neutral = neutralInput.value,
swampiness = swampinessInput.value,
sharpness = sharpnessInput.value;
if (neutral === "100") {neutral = "300";}
// Groups for labels
var fonts = ["Amatic+SC:700"],
capitals = labels.append("g").attr("id", "capitals").attr("fill", "#3e3e4b").attr("opacity", 1).attr("font-family", "Amatic SC").attr("data-font", "Amatic+SC:700").attr("font-size", Math.round(6 - capitalsCount / 20)),
towns = labels.append("g").attr("id", "towns").attr("fill", "#3e3e4b").attr("opacity", 1).attr("font-family", "Amatic SC").attr("data-font", "Amatic+SC:700").attr("font-size", 2),
countries = labels.append("g").attr("id", "countries").attr("fill", "#3e3e4b").attr("opacity", 1).attr("font-family", "Amatic SC").attr("data-font", "Amatic+SC:700").attr("font-size", Math.round(18 - capitalsCount / 6));
// append ocean pattern
oceanPattern.append("rect").attr("x", 0).attr("y", 0)
.attr("width", mapWidth).attr("height", mapHeight).attr("class", "pattern")
.attr("stroke", "none").attr("fill", "url(#oceanPattern)");
oceanLayers.append("rect").attr("x", 0).attr("y", 0)
.attr("width", mapWidth).attr("height", mapHeight).attr("id", "oceanBase").attr("fill", "#5167a9");
// D3 Line generator
var scX = d3.scaleLinear().domain([0, mapWidth]).range([0, mapWidth]),
scY = d3.scaleLinear().domain([0, mapHeight]).range([0, mapHeight]),
lineGen = d3.line().x(function(d) {return scX(d.scX);}).y(function(d) {return scY(d.scY);});
// main data variables
var voronoi = d3.voronoi().extent([[0, 0], [mapWidth, mapHeight]]);
var diagram, polygons, points = [], sample;
// D3 drag and zoom behavior
var scale = 1, viewX = 0, viewY = 0;
var zoom = d3.zoom().scaleExtent([1, 40]) // 40x is default max zoom
.translateExtent([[0, 0], [mapWidth, mapHeight]]) // 0,0 as default extent
.on("zoom", zoomed);
svg.call(zoom);
$("#optionsContainer").draggable({handle: ".drag-trigger", snap: "svg", snapMode: "both"});
$("#mapLayers").sortable({items: "li:not(.solid)", cancel: ".solid", update: moveLayer});
$("#templateBody").sortable({items: "div:not(div[data-type='Mountain'])"});
$("#mapLayers, #templateBody").disableSelection();
var drag = d3.drag()
.container(function() {return this;})
.subject(function() {var p=[d3.event.x, d3.event.y]; return [p, p];})
.on("start", dragstarted);
function zoomed() {
scale = d3.event.transform.k;
viewX = d3.event.transform.x;
viewY = d3.event.transform.y;
viewbox.attr("transform", d3.event.transform);
}
// Manually update viewbox
function zoomUpdate() {
var transform = d3.zoomIdentity.translate(viewX, viewY).scale(scale);
svg.call(zoom.transform, transform);
}
generate(); // genarate map on load
function generate() {
console.group("Random map");
console.time("TOTAL");
placePoints();
calculateVoronoi(points);
detectNeighbors();
defineHeightmap();
markFeatures();
drawOcean();
reGraph();
resolveDepressions();
flux();
drawRelief();
drawCoastline();
manorsAndRegions();
console.timeEnd("TOTAL");
console.groupEnd("Random map");
}
// Locate points to calculate Voronoi diagram
function placePoints() {
console.time("placePoints");
points = [];
var radius = 5.9 / graphSize; // 5.9 is a radius to get 8k cells
var sampler = poissonDiscSampler(mapWidth, mapHeight, radius);
while (sample = sampler()) {
var x = Math.round(sample[0] * 100) / 100;
var y = Math.round(sample[1] * 100) / 100;
points.push([x, y]);
}
console.timeEnd("placePoints");
}
// Calculate Voronoi Diagram
function calculateVoronoi(points) {
console.time("calculateVoronoi");
diagram = voronoi(points),
polygons = diagram.polygons();
console.log(" cells: " + points.length);
console.timeEnd("calculateVoronoi");
}
// Get cell info on mouse move (useful for debugging)
function moved() {
var point = d3.mouse(this);
var i = diagram.find(point[0], point[1]).index;
if (i) {
var p = cells[i]; // get cell
$("#lx").text(Math.round(point[0]));
$("#ly").text(Math.round(point[1]));
$("#cell").text(i);
$("#height").text(ifDefined(p.height, 2));
$("#flux").text(ifDefined(p.flux, 3));
$("#river").text(ifDefined(p.river));
$("#region").text(ifDefined(p.region));
$("#feature").text(ifDefined(p.feature) + "" + ifDefined(p.featureNumber));
$("#score").text(ifDefined(p.score));
$("#path").text(ifDefined(p.path));
$("#culture").text(ifDefined(cultures[p.culture]));
d3.select("body").on("keydown", function() {
if (d3.event.keyCode == 32) {console.table(p);} // hotkey -space for cell
if (d3.event.keyCode == 67) {console.log(cells);} // hotkey -c for cells
if (d3.event.keyCode == 77) {console.table(manors);} // hotkey -m for manors
});
}
// draw line for Customization range placing
icons.selectAll(".line").remove();
if (customization === 1 && icons.selectAll(".tag").size() === 1) {
var x = +icons.select(".tag").attr("cx");
var y = +icons.select(".tag").attr("cy");
icons.insert("line", ":first-child").attr("class", "line").attr("x1", x).attr("y1", y).attr("x2", point[0]).attr("y2", point[1]);
}
}
// return value (e) if defined with specified number of decimals (f)
function ifDefined(e, f) {
if (e == undefined) {return "no";}
if (f) {return e.toFixed(f);}
return e;
}
// Drag actions
function dragstarted() {
var x0 = d3.event.x,
y0 = d3.event.y,
c0 = diagram.find(x0, y0).index,
c1 = c0;
d3.event.on("drag", function() {
if (customization === 1) {
var x1 = d3.event.x,
y1 = d3.event.y,
c2 = diagram.find(x1, y1).index;
if (c2 !== c1) {
c1 = c2;
var brush = $("#options .pressed").attr("id");
var power = +brushPower.value;
if (brush === "brushElevate") {
if (cells[c2].height < 0.2) {cells[c2].height = 0.2} else {cells[c2].height += power;}
}
if (brush === "brushDepress") {cells[c2].height -= power;}
if (brush === "brushHill") {add(c2, "hill", power);}
if (brush === "brushPit") {addPit(1, power, c2);}
if (brush === "brushAlign") {cells[c2].height = cells[c0].height;}
if (brush === "brushSmooth") {
var heights = [cells[c2].height];
cells[c2].neighbors.forEach(function(e) {heights.push(cells[e].height);});
cells[c2].height = d3.mean(heights);
}
}
mockHeightmap();
} else {
viewbox.on(".drag", null);
}
});
}
// turn D3 polygons array into cell array, define neighbors for each cell
function detectNeighbors(withGrid) {
console.time("detectNeighbors");
var gridPath = ""; // store grid as huge single path string
polygons.map(function(i, d) {
var neighbors = [];
var type; // define type, -99 for map borders
if (withGrid) {gridPath += "M" + i.join("L") + "Z";} // grid path
diagram.cells[d].halfedges.forEach(function(e) {
var edge = diagram.edges[e], ea;
if (edge.left && edge.right) {
ea = edge.left.index;
if (ea === d) {ea = edge.right.index;}
neighbors.push(ea);
} else {
if (edge.left) {ea = edge.left.index;} else {ea = edge.right.index;}
type = -99; // polygon is on border if it has edge without opposite side polygon
}
})
cells.push({index: d, data: i.data, height: 0, type, neighbors});
});
if (withGrid) {grid.append("path").attr("d", round(gridPath));}
console.timeEnd("detectNeighbors");
}
// Generate Heigtmap routine
function defineHeightmap() {
console.time('defineHeightmap');
var mapTemplate = templateInput.value;
if (mapTemplate === "Random") {
var rnd = Math.random();
if (rnd > 0.98) {mapTemplate = "Volcano";}
if (rnd > 0.8 && rnd <= 0.98) {mapTemplate = "High Island";}
if (rnd > 0.62 && rnd <= 0.8) {mapTemplate = "Low Island";}
if (rnd > 0.35 && rnd <= 0.62) {mapTemplate = "Continents";}
if (rnd > 0.01 && rnd <= 0.35) {mapTemplate = "Archipelago";}
if (rnd <= 0.01) {mapTemplate = "Atoll";}
}
addMountain();
if (mapTemplate === "Volcano") {templateVolcano();}
if (mapTemplate === "High Island") {templateHighIsland();}
if (mapTemplate === "Low Island") {templateLowIsland();}
if (mapTemplate === "Continents") {templateContinents();}
if (mapTemplate === "Archipelago") {templateArchipelago();}
if (mapTemplate === "Atoll") {templateAtoll();}
console.log(mapTemplate + " template is applied");
console.timeEnd('defineHeightmap');
}
// Heighmap Template: Volcano
function templateVolcano() {
modifyHeights("all", 0.07, 1.1);
addHill(5, 0.4);
addHill(2, 0.15);
}
// Heighmap Template: High Island
function templateHighIsland() {
modifyHeights("all", 0.08, 0.9);
addRange(4);
addHill(12, 0.25);
addRange(-3);
modifyHeights("land", 0, 0.75);
addHill(3, 0.15);
}
// Heighmap Template: Low Island
function templateLowIsland() {
modifyHeights("all", 0.05, 1);
smoothHeights();
addHill(4, 0.4);
addHill(12, 0.2);
addRange(-3);
modifyHeights("land", 0, 0.3);
}
// Heighmap Template: Continents
function templateContinents() {
addHill(24, 0.25);
addRange(2);
addHill(3, 0.1);
modifyHeights("land", 0, 0.7);
var count = Math.ceil(Math.random() * 7 + 2);
addStrait(count);
smoothHeights();
addPit(5);
addRange(-3);
modifyHeights("land", 0, 0.8);
modifyHeights("all", 0.02, 1);
}
// Heighmap Template: Archipelago
function templateArchipelago() {
modifyHeights("land", -0.2, 1);
addHill(15, 0.15);
addRange(-2);
addPit(8);
modifyHeights("land", -0.05, 0.9);
}
// Heighmap Template: Atoll
function templateAtoll() {
addHill(2, 0.35);
addRange(1);
modifyHeights("all", 0.07, 1);
smoothHeights();
modifyHeights("0.27-10", 0, 0.1);
}
function addMountain() {
var x = Math.floor(Math.random() * mapWidth / 3 + mapWidth / 3);
var y = Math.floor(Math.random() * mapHeight * 0.2 + mapHeight * 0.4);