From 9c9862e5644fd08a27695c776412bb7a55491713 Mon Sep 17 00:00:00 2001
From: Tancre
Date: Sun, 12 Apr 2020 04:43:02 +0200
Subject: [PATCH] first setup map
---
code_base/mapGen/README.md | 37 +
code_base/mapGen/index.html | 71 +
code_base/mapGen/language.js | 486 +
code_base/mapGen/priority-queue.js | 387 +
code_base/mapGen/script.js | 21 +
code_base/mapGen/style.css | 11 +
code_base/mapGen/terrain.js | 1073 ++
main/img/grid1.png | Bin 0 -> 3287 bytes
main/img/grid2.png | Bin 0 -> 3282 bytes
main/img/grid3.png | Bin 0 -> 3253 bytes
main/index.html | 92 +-
main/map.html | 72 +
main/map2.html | 72 +
main/map2_files/d3.js | 18525 ++++++++++++++++++++++++
main/map2_files/language.js | 486 +
main/map2_files/priority-queue.js | 387 +
main/map2_files/script.js | 21 +
main/map2_files/terrain.js | 1073 ++
main/map3.html | 72 +
main/map3_files/d3.js | 18525 ++++++++++++++++++++++++
main/map3_files/language.js | 486 +
main/map3_files/priority-queue.js | 387 +
main/map3_files/script.js | 21 +
main/map3_files/terrain.js | 1073 ++
main/map_files/d3.js | 18525 ++++++++++++++++++++++++
main/map_files/language.js | 486 +
main/map_files/priority-queue.js | 387 +
main/map_files/script.js | 21 +
main/map_files/terrain.js | 1073 ++
main/scripts/mapGen/README.md | 37 +
main/scripts/mapGen/index.html | 71 +
main/scripts/mapGen/language.js | 486 +
main/scripts/mapGen/priority-queue.js | 387 +
main/scripts/mapGen/script.js | 21 +
main/scripts/mapGen/style.css | 11 +
main/scripts/mapGen/terrain.js | 1073 ++
main/style.css | 97 +-
notes_porj.md | 38 +
38 files changed, 66060 insertions(+), 31 deletions(-)
create mode 100644 code_base/mapGen/README.md
create mode 100644 code_base/mapGen/index.html
create mode 100644 code_base/mapGen/language.js
create mode 100644 code_base/mapGen/priority-queue.js
create mode 100644 code_base/mapGen/script.js
create mode 100644 code_base/mapGen/style.css
create mode 100644 code_base/mapGen/terrain.js
create mode 100644 main/img/grid1.png
create mode 100644 main/img/grid2.png
create mode 100644 main/img/grid3.png
create mode 100644 main/map.html
create mode 100644 main/map2.html
create mode 100644 main/map2_files/d3.js
create mode 100644 main/map2_files/language.js
create mode 100644 main/map2_files/priority-queue.js
create mode 100644 main/map2_files/script.js
create mode 100644 main/map2_files/terrain.js
create mode 100644 main/map3.html
create mode 100644 main/map3_files/d3.js
create mode 100644 main/map3_files/language.js
create mode 100644 main/map3_files/priority-queue.js
create mode 100644 main/map3_files/script.js
create mode 100644 main/map3_files/terrain.js
create mode 100644 main/map_files/d3.js
create mode 100644 main/map_files/language.js
create mode 100644 main/map_files/priority-queue.js
create mode 100644 main/map_files/script.js
create mode 100644 main/map_files/terrain.js
create mode 100644 main/scripts/mapGen/README.md
create mode 100644 main/scripts/mapGen/index.html
create mode 100644 main/scripts/mapGen/language.js
create mode 100644 main/scripts/mapGen/priority-queue.js
create mode 100644 main/scripts/mapGen/script.js
create mode 100644 main/scripts/mapGen/style.css
create mode 100644 main/scripts/mapGen/terrain.js
create mode 100644 notes_porj.md
diff --git a/code_base/mapGen/README.md b/code_base/mapGen/README.md
new file mode 100644
index 0000000..96036fb
--- /dev/null
+++ b/code_base/mapGen/README.md
@@ -0,0 +1,37 @@
+Welcome to Glitch
+=================
+
+Click `Show` in the header to see your app live. Updates to your code will instantly deploy and update live.
+
+**Glitch** is the friendly community where you'll build the app of your dreams. Glitch lets you instantly create, remix, edit, and host an app, bot or site, and you can invite collaborators or helpers to simultaneously edit code with you.
+
+Find out more [about Glitch](https://glitch.com/about).
+
+
+Your Project
+------------
+
+### ← README.md
+
+That's this file, where you can tell people what your cool website does and how you built it.
+
+### ← index.html
+
+Where you'll write the content of your website.
+
+### ← style.css
+
+CSS files add styling rules to your content.
+
+### ← script.js
+
+If you're feeling fancy you can add interactivity to your site with JavaScript.
+
+### ← assets
+
+Drag in `assets`, like images or music, to add them to your project
+
+Made by [Glitch](https://glitch.com/)
+-------------------
+
+\ ゜o゜)ノ
diff --git a/code_base/mapGen/index.html b/code_base/mapGen/index.html
new file mode 100644
index 0000000..629800b
--- /dev/null
+++ b/code_base/mapGen/index.html
@@ -0,0 +1,71 @@
+
+
+
+ Hello!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/code_base/mapGen/language.js b/code_base/mapGen/language.js
new file mode 100644
index 0000000..f82b6c3
--- /dev/null
+++ b/code_base/mapGen/language.js
@@ -0,0 +1,486 @@
+function shuffled(list) {
+ var newlist = [];
+ for (var i = 0; i < list.length; i++) {
+ newlist.push(list[i]);
+ }
+ for (var i = list.length - 1; i > 0; i--) {
+ var tmp = newlist[i];
+ var j = randrange(i);
+ newlist[i] = newlist[j];
+ newlist[j] = tmp;
+ }
+ return newlist;
+}
+
+function choose(list, exponent) {
+ exponent = exponent || 1;
+ return list[Math.floor(Math.pow(Math.random(), exponent) * list.length)];
+}
+
+function randrange(lo, hi) {
+ if (hi == undefined) {
+ hi = lo;
+ lo = 0;
+ }
+ return Math.floor(Math.random() * (hi - lo)) + lo;
+}
+
+function join(list, sep) {
+ if (list.length == 0) return '';
+ sep = sep || '';
+ var s = list[0];
+ for (var i = 1; i < list.length; i++) {
+ s += sep;
+ s += list[i];
+ }
+ return s;
+}
+
+function capitalize(word) {
+ return word[0].toUpperCase() + word.slice(1);
+}
+
+function spell(lang, syll) {
+ if (lang.noortho) return syll;
+ var s = '';
+ for (var i = 0; i < syll.length; i++) {
+ var c = syll[i];
+ s += lang.cortho[c] || lang.vortho[c] || defaultOrtho[c] || c;
+ }
+ return s;
+}
+
+function makeSyllable(lang) {
+ while (true) {
+ var syll = "";
+ for (var i = 0; i < lang.structure.length; i++) {
+ var ptype = lang.structure[i];
+ if (lang.structure[i+1] == '?') {
+ i++;
+ if (Math.random() < 0.5) {
+ continue;
+ }
+ }
+ syll += choose(lang.phonemes[ptype], lang.exponent);
+ }
+ var bad = false;
+ for (var i = 0; i < lang.restricts.length; i++) {
+ if (lang.restricts[i].test(syll)) {
+ bad = true;
+ break;
+ }
+ }
+ if (bad) continue;
+ return spell(lang, syll);
+ }
+}
+
+function getMorpheme(lang, key) {
+ if (lang.nomorph) {
+ return makeSyllable(lang);
+ }
+ key = key || '';
+ var list = lang.morphemes[key] || [];
+ var extras = 10;
+ if (key) extras = 1;
+ while (true) {
+ var n = randrange(list.length + extras);
+ if (list[n]) return list[n];
+ var morph = makeSyllable(lang);
+ var bad = false;
+ for (var k in lang.morphemes) {
+ if (lang.morphemes[k].includes(morph)) {
+ bad = true;
+ break;
+ }
+ }
+ if (bad) continue;
+ list.push(morph);
+ lang.morphemes[key] = list;
+ return morph;
+ }
+}
+
+function makeWord(lang, key) {
+ var nsylls = randrange(lang.minsyll, lang.maxsyll + 1);
+ var w = '';
+ var keys = [];
+ keys[randrange(nsylls)] = key;
+ for (var i = 0; i < nsylls; i++) {
+ w += getMorpheme(lang, keys[i]);
+ }
+ return w;
+}
+
+function getWord(lang, key) {
+ key = key || '';
+ var ws = lang.words[key] || [];
+ var extras = 3;
+ if (key) extras = 2;
+ while (true) {
+ var n = randrange(ws.length + extras);
+ var w = ws[n];
+ if (w) {
+ return w;
+ }
+ w = makeWord(lang, key);
+ var bad = false;
+ for (var k in lang.words) {
+ if (lang.words[k].includes(w)) {
+ bad = true;
+ break;
+ }
+ }
+ if (bad) continue;
+ ws.push(w);
+ lang.words[key] = ws;
+ return w;
+ }
+}
+function makeName(lang, key) {
+ key = key || '';
+ lang.genitive = lang.genitive || getMorpheme(lang, 'of');
+ lang.definite = lang.definite || getMorpheme(lang, 'the');
+ while (true) {
+ var name = null;
+ if (Math.random() < 0.5) {
+ name = capitalize(getWord(lang, key));
+ } else {
+ var w1 = capitalize(getWord(lang, Math.random() < 0.6 ? key : ''));
+ var w2 = capitalize(getWord(lang, Math.random() < 0.6 ? key : ''));
+ if (w1 == w2) continue;
+ if (Math.random() > 0.5) {
+ name = join([w1, w2], lang.joiner);
+ } else {
+ name = join([w1, lang.genitive, w2], lang.joiner);
+ }
+ }
+ if (Math.random() < 0.1) {
+ name = join([lang.definite, name], lang.joiner);
+ }
+
+ if ((name.length < lang.minchar) || (name.length > lang.maxchar)) continue;
+ var used = false;
+ for (var i = 0; i < lang.names.length; i++) {
+ var name2 = lang.names[i];
+ if ((name.indexOf(name2) != -1) || (name2.indexOf(name) != -1)) {
+ used = true;
+ break;
+ }
+ }
+ if (used) continue;
+ lang.names.push(name);
+ return name;
+ }
+}
+
+function makeBasicLanguage() {
+ return {
+ phonemes: {
+ C: "ptkmnls",
+ V: "aeiou",
+ S: "s",
+ F: "mn",
+ L: "rl"
+ },
+ structure: "CVC",
+ exponent: 2,
+ restricts: [],
+ cortho: {},
+ vortho: {},
+ noortho: true,
+ nomorph: true,
+ nowordpool: true,
+ minsyll: 1,
+ maxsyll: 1,
+ morphemes: {},
+ words: {},
+ names: [],
+ joiner: ' ',
+ maxchar: 12,
+ minchar: 5
+ };
+}
+
+function makeOrthoLanguage() {
+ var lang = makeBasicLanguage();
+ lang.noortho = false;
+ return lang;
+}
+
+function makeRandomLanguage() {
+ var lang = makeBasicLanguage();
+ lang.noortho = false;
+ lang.nomorph = false;
+ lang.nowordpool = false;
+ lang.phonemes.C = shuffled(choose(consets, 2).C);
+ lang.phonemes.V = shuffled(choose(vowsets, 2).V);
+ lang.phonemes.L = shuffled(choose(lsets, 2).L);
+ lang.phonemes.S = shuffled(choose(ssets, 2).S);
+ lang.phonemes.F = shuffled(choose(fsets, 2).F);
+ lang.structure = choose(syllstructs);
+ lang.restricts = ressets[2].res;
+ lang.cortho = choose(corthsets, 2).orth;
+ lang.vortho = choose(vorthsets, 2).orth;
+ lang.minsyll = randrange(1, 3);
+ if (lang.structure.length < 3) lang.minsyll++;
+ lang.maxsyll = randrange(lang.minsyll + 1, 7);
+ lang.joiner = choose(' -');
+ return lang;
+}
+var defaultOrtho = {
+ 'ʃ': 'sh',
+ 'ʒ': 'zh',
+ 'ʧ': 'ch',
+ 'ʤ': 'j',
+ 'ŋ': 'ng',
+ 'j': 'y',
+ 'x': 'kh',
+ 'ɣ': 'gh',
+ 'ʔ': '‘',
+ A: "á",
+ E: "é",
+ I: "í",
+ O: "ó",
+ U: "ú"
+};
+
+var corthsets = [
+ {
+ name: "Default",
+ orth: {}
+ },
+ {
+ name: "Slavic",
+ orth: {
+ 'ʃ': 'š',
+ 'ʒ': 'ž',
+ 'ʧ': 'č',
+ 'ʤ': 'ǧ',
+ 'j': 'j'
+ }
+ },
+ {
+ name: "German",
+ orth: {
+ 'ʃ': 'sch',
+ 'ʒ': 'zh',
+ 'ʧ': 'tsch',
+ 'ʤ': 'dz',
+ 'j': 'j',
+ 'x': 'ch'
+ }
+ },
+ {
+ name: "French",
+ orth: {
+ 'ʃ': 'ch',
+ 'ʒ': 'j',
+ 'ʧ': 'tch',
+ 'ʤ': 'dj',
+ 'x': 'kh'
+ }
+ },
+ {
+ name: "Chinese (pinyin)",
+ orth: {
+ 'ʃ': 'x',
+ 'ʧ': 'q',
+ 'ʤ': 'j',
+ }
+ }
+];
+
+var vorthsets = [
+ {
+ name: "Ácutes",
+ orth: {}
+ },
+ {
+ name: "Ümlauts",
+ orth: {
+ A: "ä",
+ E: "ë",
+ I: "ï",
+ O: "ö",
+ U: "ü"
+ }
+ },
+ {
+ name: "Welsh",
+ orth: {
+ A: "â",
+ E: "ê",
+ I: "y",
+ O: "ô",
+ U: "w"
+ }
+ },
+ {
+ name: "Diphthongs",
+ orth: {
+ A: "au",
+ E: "ei",
+ I: "ie",
+ O: "ou",
+ U: "oo"
+ }
+ },
+ {
+ name: "Doubles",
+ orth: {
+ A: "aa",
+ E: "ee",
+ I: "ii",
+ O: "oo",
+ U: "uu"
+ }
+ }
+];
+
+var consets = [
+ {
+ name: "Minimal",
+ C: "ptkmnls"
+ },
+ {
+ name: "English-ish",
+ C: "ptkbdgmnlrsʃzʒʧ"
+ },
+ {
+ name: "Pirahã (very simple)",
+ C: "ptkmnh"
+ },
+ {
+ name: "Hawaiian-ish",
+ C: "hklmnpwʔ"
+ },
+ {
+ name: "Greenlandic-ish",
+ C: "ptkqvsgrmnŋlj"
+ },
+ {
+ name: "Arabic-ish",
+ C: "tksʃdbqɣxmnlrwj"
+ },
+ {
+ name: "Arabic-lite",
+ C: "tkdgmnsʃ"
+ },
+ {
+ name: "English-lite",
+ C: "ptkbdgmnszʒʧhjw"
+ }
+];
+
+var ssets = [
+ {
+ name: "Just s",
+ S: "s"
+ },
+ {
+ name: "s ʃ",
+ S: "sʃ"
+ },
+ {
+ name: "s ʃ f",
+ S: "sʃf"
+ }
+];
+
+var lsets = [
+ {
+ name: "r l",
+ L: "rl"
+ },
+ {
+ name: "Just r",
+ L: "r"
+ },
+ {
+ name: "Just l",
+ L: "l"
+ },
+ {
+ name: "w j",
+ L: "wj"
+ },
+ {
+ name: "r l w j",
+ L: "rlwj"
+ }
+];
+
+var fsets = [
+ {
+ name: "m n",
+ F: "mn"
+ },
+ {
+ name: "s k",
+ F: "sk"
+ },
+ {
+ name: "m n ŋ",
+ F: "mnŋ"
+ },
+ {
+ name: "s ʃ z ʒ",
+ F: "sʃzʒ"
+ }
+];
+
+var vowsets = [
+ {
+ name: "Standard 5-vowel",
+ V: "aeiou"
+ },
+ {
+ name: "3-vowel a i u",
+ V: "aiu"
+ },
+ {
+ name: "Extra A E I",
+ V: "aeiouAEI"
+ },
+ {
+ name: "Extra U",
+ V: "aeiouU"
+ },
+ {
+ name: "5-vowel a i u A I",
+ V: "aiuAI"
+ },
+ {
+ name: "3-vowel e o u",
+ V: "eou"
+ },
+ {
+ name: "Extra A O U",
+ V: "aeiouAOU"
+ }
+];
+
+var syllstructs = [
+ "CVC",
+ "CVV?C",
+ "CVVC?", "CVC?", "CV", "VC", "CVF", "C?VC", "CVF?",
+ "CL?VC", "CL?VF", "S?CVC", "S?CVF", "S?CVC?",
+ "C?VF", "C?VC?", "C?VF?", "C?L?VC", "VC",
+ "CVL?C?", "C?VL?C", "C?VLC?"];
+
+var ressets = [
+ {
+ name: "None",
+ res: []
+ },
+ {
+ name: "Double sounds",
+ res: [/(.)\1/]
+ },
+ {
+ name: "Doubles and hard clusters",
+ res: [/[sʃf][sʃ]/, /(.)\1/, /[rl][rl]/]
+ }
+];
+
diff --git a/code_base/mapGen/priority-queue.js b/code_base/mapGen/priority-queue.js
new file mode 100644
index 0000000..f8f6b54
--- /dev/null
+++ b/code_base/mapGen/priority-queue.js
@@ -0,0 +1,387 @@
+(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.PriorityQueue = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o>> 1;
+ if (comparator(array[mid], value) >= 0) {
+ low = mid + 1;
+ } else {
+ high = mid;
+ }
+ }
+ return low;
+};
+
+module.exports = ArrayStrategy = (function() {
+ function ArrayStrategy(options) {
+ var ref;
+ this.options = options;
+ this.comparator = this.options.comparator;
+ this.data = ((ref = this.options.initialValues) != null ? ref.slice(0) : void 0) || [];
+ this.data.sort(this.comparator).reverse();
+ }
+
+ ArrayStrategy.prototype.queue = function(value) {
+ var pos;
+ pos = binarySearchForIndexReversed(this.data, value, this.comparator);
+ this.data.splice(pos, 0, value);
+ return void 0;
+ };
+
+ ArrayStrategy.prototype.dequeue = function() {
+ return this.data.pop();
+ };
+
+ ArrayStrategy.prototype.peek = function() {
+ return this.data[this.data.length - 1];
+ };
+
+ ArrayStrategy.prototype.clear = function() {
+ this.data.length = 0;
+ return void 0;
+ };
+
+ return ArrayStrategy;
+
+})();
+
+
+},{}],4:[function(_dereq_,module,exports){
+var BHeapStrategy;
+
+module.exports = BHeapStrategy = (function() {
+ function BHeapStrategy(options) {
+ var arr, i, j, k, len, ref, ref1, shift, value;
+ this.comparator = (options != null ? options.comparator : void 0) || function(a, b) {
+ return a - b;
+ };
+ this.pageSize = (options != null ? options.pageSize : void 0) || 512;
+ this.length = 0;
+ shift = 0;
+ while ((1 << shift) < this.pageSize) {
+ shift += 1;
+ }
+ if (1 << shift !== this.pageSize) {
+ throw 'pageSize must be a power of two';
+ }
+ this._shift = shift;
+ this._emptyMemoryPageTemplate = arr = [];
+ for (i = j = 0, ref = this.pageSize; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {
+ arr.push(null);
+ }
+ this._memory = [];
+ this._mask = this.pageSize - 1;
+ if (options.initialValues) {
+ ref1 = options.initialValues;
+ for (k = 0, len = ref1.length; k < len; k++) {
+ value = ref1[k];
+ this.queue(value);
+ }
+ }
+ }
+
+ BHeapStrategy.prototype.queue = function(value) {
+ this.length += 1;
+ this._write(this.length, value);
+ this._bubbleUp(this.length, value);
+ return void 0;
+ };
+
+ BHeapStrategy.prototype.dequeue = function() {
+ var ret, val;
+ ret = this._read(1);
+ val = this._read(this.length);
+ this.length -= 1;
+ if (this.length > 0) {
+ this._write(1, val);
+ this._bubbleDown(1, val);
+ }
+ return ret;
+ };
+
+ BHeapStrategy.prototype.peek = function() {
+ return this._read(1);
+ };
+
+ BHeapStrategy.prototype.clear = function() {
+ this.length = 0;
+ this._memory.length = 0;
+ return void 0;
+ };
+
+ BHeapStrategy.prototype._write = function(index, value) {
+ var page;
+ page = index >> this._shift;
+ while (page >= this._memory.length) {
+ this._memory.push(this._emptyMemoryPageTemplate.slice(0));
+ }
+ return this._memory[page][index & this._mask] = value;
+ };
+
+ BHeapStrategy.prototype._read = function(index) {
+ return this._memory[index >> this._shift][index & this._mask];
+ };
+
+ BHeapStrategy.prototype._bubbleUp = function(index, value) {
+ var compare, indexInPage, parentIndex, parentValue;
+ compare = this.comparator;
+ while (index > 1) {
+ indexInPage = index & this._mask;
+ if (index < this.pageSize || indexInPage > 3) {
+ parentIndex = (index & ~this._mask) | (indexInPage >> 1);
+ } else if (indexInPage < 2) {
+ parentIndex = (index - this.pageSize) >> this._shift;
+ parentIndex += parentIndex & ~(this._mask >> 1);
+ parentIndex |= this.pageSize >> 1;
+ } else {
+ parentIndex = index - 2;
+ }
+ parentValue = this._read(parentIndex);
+ if (compare(parentValue, value) < 0) {
+ break;
+ }
+ this._write(parentIndex, value);
+ this._write(index, parentValue);
+ index = parentIndex;
+ }
+ return void 0;
+ };
+
+ BHeapStrategy.prototype._bubbleDown = function(index, value) {
+ var childIndex1, childIndex2, childValue1, childValue2, compare;
+ compare = this.comparator;
+ while (index < this.length) {
+ if (index > this._mask && !(index & (this._mask - 1))) {
+ childIndex1 = childIndex2 = index + 2;
+ } else if (index & (this.pageSize >> 1)) {
+ childIndex1 = (index & ~this._mask) >> 1;
+ childIndex1 |= index & (this._mask >> 1);
+ childIndex1 = (childIndex1 + 1) << this._shift;
+ childIndex2 = childIndex1 + 1;
+ } else {
+ childIndex1 = index + (index & this._mask);
+ childIndex2 = childIndex1 + 1;
+ }
+ if (childIndex1 !== childIndex2 && childIndex2 <= this.length) {
+ childValue1 = this._read(childIndex1);
+ childValue2 = this._read(childIndex2);
+ if (compare(childValue1, value) < 0 && compare(childValue1, childValue2) <= 0) {
+ this._write(childIndex1, value);
+ this._write(index, childValue1);
+ index = childIndex1;
+ } else if (compare(childValue2, value) < 0) {
+ this._write(childIndex2, value);
+ this._write(index, childValue2);
+ index = childIndex2;
+ } else {
+ break;
+ }
+ } else if (childIndex1 <= this.length) {
+ childValue1 = this._read(childIndex1);
+ if (compare(childValue1, value) < 0) {
+ this._write(childIndex1, value);
+ this._write(index, childValue1);
+ index = childIndex1;
+ } else {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ return void 0;
+ };
+
+ return BHeapStrategy;
+
+})();
+
+
+},{}],5:[function(_dereq_,module,exports){
+var BinaryHeapStrategy;
+
+module.exports = BinaryHeapStrategy = (function() {
+ function BinaryHeapStrategy(options) {
+ var ref;
+ this.comparator = (options != null ? options.comparator : void 0) || function(a, b) {
+ return a - b;
+ };
+ this.length = 0;
+ this.data = ((ref = options.initialValues) != null ? ref.slice(0) : void 0) || [];
+ this._heapify();
+ }
+
+ BinaryHeapStrategy.prototype._heapify = function() {
+ var i, j, ref;
+ if (this.data.length > 0) {
+ for (i = j = 1, ref = this.data.length; 1 <= ref ? j < ref : j > ref; i = 1 <= ref ? ++j : --j) {
+ this._bubbleUp(i);
+ }
+ }
+ return void 0;
+ };
+
+ BinaryHeapStrategy.prototype.queue = function(value) {
+ this.data.push(value);
+ this._bubbleUp(this.data.length - 1);
+ return void 0;
+ };
+
+ BinaryHeapStrategy.prototype.dequeue = function() {
+ var last, ret;
+ ret = this.data[0];
+ last = this.data.pop();
+ if (this.data.length > 0) {
+ this.data[0] = last;
+ this._bubbleDown(0);
+ }
+ return ret;
+ };
+
+ BinaryHeapStrategy.prototype.peek = function() {
+ return this.data[0];
+ };
+
+ BinaryHeapStrategy.prototype.clear = function() {
+ this.length = 0;
+ this.data.length = 0;
+ return void 0;
+ };
+
+ BinaryHeapStrategy.prototype._bubbleUp = function(pos) {
+ var parent, x;
+ while (pos > 0) {
+ parent = (pos - 1) >>> 1;
+ if (this.comparator(this.data[pos], this.data[parent]) < 0) {
+ x = this.data[parent];
+ this.data[parent] = this.data[pos];
+ this.data[pos] = x;
+ pos = parent;
+ } else {
+ break;
+ }
+ }
+ return void 0;
+ };
+
+ BinaryHeapStrategy.prototype._bubbleDown = function(pos) {
+ var last, left, minIndex, right, x;
+ last = this.data.length - 1;
+ while (true) {
+ left = (pos << 1) + 1;
+ right = left + 1;
+ minIndex = pos;
+ if (left <= last && this.comparator(this.data[left], this.data[minIndex]) < 0) {
+ minIndex = left;
+ }
+ if (right <= last && this.comparator(this.data[right], this.data[minIndex]) < 0) {
+ minIndex = right;
+ }
+ if (minIndex !== pos) {
+ x = this.data[minIndex];
+ this.data[minIndex] = this.data[pos];
+ this.data[pos] = x;
+ pos = minIndex;
+ } else {
+ break;
+ }
+ }
+ return void 0;
+ };
+
+ return BinaryHeapStrategy;
+
+})();
+
+
+},{}]},{},[1])(1)
+});
\ No newline at end of file
diff --git a/code_base/mapGen/script.js b/code_base/mapGen/script.js
new file mode 100644
index 0000000..1a4334d
--- /dev/null
+++ b/code_base/mapGen/script.js
@@ -0,0 +1,21 @@
+/* If you're feeling fancy you can add interactivity
+ to your site with Javascript */
+
+// prints "hi" in the browser's dev tools console
+console.log("hi");
+var svg = d3.select("svg");
+
+var params = {
+ extent: defaultExtent,
+ generator: generateCoast,
+ npts: 1684,
+ ncities: 15,
+ nterrs: 5,
+ fontsizes: {
+ region: 40,
+ city: 25,
+ town: 20
+ }
+}
+
+doMap(svg, defaultParams);
diff --git a/code_base/mapGen/style.css b/code_base/mapGen/style.css
new file mode 100644
index 0000000..f013185
--- /dev/null
+++ b/code_base/mapGen/style.css
@@ -0,0 +1,11 @@
+/* CSS files add styling rules to your content */
+
+body {
+ font-family: helvetica, arial, sans-serif;
+ margin: 2em;
+}
+
+h1 {
+ font-style: italic;
+ color: #373fff;
+}
diff --git a/code_base/mapGen/terrain.js b/code_base/mapGen/terrain.js
new file mode 100644
index 0000000..49a624c
--- /dev/null
+++ b/code_base/mapGen/terrain.js
@@ -0,0 +1,1073 @@
+"use strict";
+
+function runif(lo, hi) {
+ return lo + Math.random() * (hi - lo);
+}
+
+var rnorm = (function () {
+ var z2 = null;
+ function rnorm() {
+ if (z2 != null) {
+ var tmp = z2;
+ z2 = null;
+ return tmp;
+ }
+ var x1 = 0;
+ var x2 = 0;
+ var w = 2.0;
+ while (w >= 1) {
+ x1 = runif(-1, 1);
+ x2 = runif(-1, 1);
+ w = x1 * x1 + x2 * x2;
+ }
+ w = Math.sqrt(-2 * Math.log(w) / w);
+ z2 = x2 * w;
+ return x1 * w;
+ }
+ return rnorm;
+})();
+
+function randomVector(scale) {
+ return [scale * rnorm(), scale * rnorm()];
+}
+
+var defaultExtent = {
+ width: 1,
+ height: 1
+};
+
+function generatePoints(n, extent) {
+ extent = extent || defaultExtent;
+ var pts = [];
+ for (var i = 0; i < n; i++) {
+ pts.push([(Math.random() - 0.5) * extent.width, (Math.random() - 0.5) * extent.height]);
+ }
+ return pts;
+}
+
+function centroid(pts) {
+ var x = 0;
+ var y = 0;
+ for (var i = 0; i < pts.length; i++) {
+ x += pts[i][0];
+ y += pts[i][1];
+ }
+ return [x/pts.length, y/pts.length];
+}
+
+function improvePoints(pts, n, extent) {
+ n = n || 1;
+ extent = extent || defaultExtent;
+ for (var i = 0; i < n; i++) {
+ pts = voronoi(pts, extent)
+ .polygons(pts)
+ .map(centroid);
+ }
+ return pts;
+}
+
+function generateGoodPoints(n, extent) {
+ extent = extent || defaultExtent;
+ var pts = generatePoints(n, extent);
+ pts = pts.sort(function (a, b) {
+ return a[0] - b[0];
+ });
+ return improvePoints(pts, 1, extent);
+}
+
+function voronoi(pts, extent) {
+ extent = extent || defaultExtent;
+ var w = extent.width/2;
+ var h = extent.height/2;
+ return d3.voronoi().extent([[-w, -h], [w, h]])(pts);
+}
+
+function makeMesh(pts, extent) {
+ extent = extent || defaultExtent;
+ var vor = voronoi(pts, extent);
+ var vxs = [];
+ var vxids = {};
+ var adj = [];
+ var edges = [];
+ var tris = [];
+ for (var i = 0; i < vor.edges.length; i++) {
+ var e = vor.edges[i];
+ if (e == undefined) continue;
+ var e0 = vxids[e[0]];
+ var e1 = vxids[e[1]];
+ if (e0 == undefined) {
+ e0 = vxs.length;
+ vxids[e[0]] = e0;
+ vxs.push(e[0]);
+ }
+ if (e1 == undefined) {
+ e1 = vxs.length;
+ vxids[e[1]] = e1;
+ vxs.push(e[1]);
+ }
+ adj[e0] = adj[e0] || [];
+ adj[e0].push(e1);
+ adj[e1] = adj[e1] || [];
+ adj[e1].push(e0);
+ edges.push([e0, e1, e.left, e.right]);
+ tris[e0] = tris[e0] || [];
+ if (!tris[e0].includes(e.left)) tris[e0].push(e.left);
+ if (e.right && !tris[e0].includes(e.right)) tris[e0].push(e.right);
+ tris[e1] = tris[e1] || [];
+ if (!tris[e1].includes(e.left)) tris[e1].push(e.left);
+ if (e.right && !tris[e1].includes(e.right)) tris[e1].push(e.right);
+ }
+
+ var mesh = {
+ pts: pts,
+ vor: vor,
+ vxs: vxs,
+ adj: adj,
+ tris: tris,
+ edges: edges,
+ extent: extent
+ }
+ mesh.map = function (f) {
+ var mapped = vxs.map(f);
+ mapped.mesh = mesh;
+ return mapped;
+ }
+ return mesh;
+}
+
+
+
+function generateGoodMesh(n, extent) {
+ extent = extent || defaultExtent;
+ var pts = generateGoodPoints(n, extent);
+ return makeMesh(pts, extent);
+}
+function isedge(mesh, i) {
+ return (mesh.adj[i].length < 3);
+}
+
+function isnearedge(mesh, i) {
+ var x = mesh.vxs[i][0];
+ var y = mesh.vxs[i][1];
+ var w = mesh.extent.width;
+ var h = mesh.extent.height;
+ return x < -0.45 * w || x > 0.45 * w || y < -0.45 * h || y > 0.45 * h;
+}
+
+function neighbours(mesh, i) {
+ var onbs = mesh.adj[i];
+ var nbs = [];
+ for (var i = 0; i < onbs.length; i++) {
+ nbs.push(onbs[i]);
+ }
+ return nbs;
+}
+
+function distance(mesh, i, j) {
+ var p = mesh.vxs[i];
+ var q = mesh.vxs[j];
+ return Math.sqrt((p[0] - q[0]) * (p[0] - q[0]) + (p[1] - q[1]) * (p[1] - q[1]));
+}
+
+function quantile(h, q) {
+ var sortedh = [];
+ for (var i = 0; i < h.length; i++) {
+ sortedh[i] = h[i];
+ }
+ sortedh.sort(d3.ascending);
+ return d3.quantile(sortedh, q);
+}
+
+function zero(mesh) {
+ var z = [];
+ for (var i = 0; i < mesh.vxs.length; i++) {
+ z[i] = 0;
+ }
+ z.mesh = mesh;
+ return z;
+}
+
+function slope(mesh, direction) {
+ return mesh.map(function (x) {
+ return x[0] * direction[0] + x[1] * direction[1];
+ });
+}
+
+function cone(mesh, slope) {
+ return mesh.map(function (x) {
+ return Math.pow(x[0] * x[0] + x[1] * x[1], 0.5) * slope;
+ });
+}
+
+function map(h, f) {
+ var newh = h.map(f);
+ newh.mesh = h.mesh;
+ return newh;
+}
+
+function normalize(h) {
+ var lo = d3.min(h);
+ var hi = d3.max(h);
+ return map(h, function (x) {return (x - lo) / (hi - lo)});
+}
+
+function peaky(h) {
+ return map(normalize(h), Math.sqrt);
+}
+
+function add() {
+ var n = arguments[0].length;
+ var newvals = zero(arguments[0].mesh);
+ for (var i = 0; i < n; i++) {
+ for (var j = 0; j < arguments.length; j++) {
+ newvals[i] += arguments[j][i];
+ }
+ }
+ return newvals;
+}
+
+function mountains(mesh, n, r) {
+ r = r || 0.05;
+ var mounts = [];
+ for (var i = 0; i < n; i++) {
+ mounts.push([mesh.extent.width * (Math.random() - 0.5), mesh.extent.height * (Math.random() - 0.5)]);
+ }
+ var newvals = zero(mesh);
+ for (var i = 0; i < mesh.vxs.length; i++) {
+ var p = mesh.vxs[i];
+ for (var j = 0; j < n; j++) {
+ var m = mounts[j];
+ newvals[i] += Math.pow(Math.exp(-((p[0] - m[0]) * (p[0] - m[0]) + (p[1] - m[1]) * (p[1] - m[1])) / (2 * r * r)), 2);
+ }
+ }
+ return newvals;
+}
+
+function relax(h) {
+ var newh = zero(h.mesh);
+ for (var i = 0; i < h.length; i++) {
+ var nbs = neighbours(h.mesh, i);
+ if (nbs.length < 3) {
+ newh[i] = 0;
+ continue;
+ }
+ newh[i] = d3.mean(nbs.map(function (j) {return h[j]}));
+ }
+ return newh;
+}
+
+function downhill(h) {
+ if (h.downhill) return h.downhill;
+ function downfrom(i) {
+ if (isedge(h.mesh, i)) return -2;
+ var best = -1;
+ var besth = h[i];
+ var nbs = neighbours(h.mesh, i);
+ for (var j = 0; j < nbs.length; j++) {
+ if (h[nbs[j]] < besth) {
+ besth = h[nbs[j]];
+ best = nbs[j];
+ }
+ }
+ return best;
+ }
+ var downs = [];
+ for (var i = 0; i < h.length; i++) {
+ downs[i] = downfrom(i);
+ }
+ h.downhill = downs;
+ return downs;
+}
+
+function findSinks(h) {
+ var dh = downhill(h);
+ var sinks = [];
+ for (var i = 0; i < dh.length; i++) {
+ var node = i;
+ while (true) {
+ if (isedge(h.mesh, node)) {
+ sinks[i] = -2;
+ break;
+ }
+ if (dh[node] == -1) {
+ sinks[i] = node;
+ break;
+ }
+ node = dh[node];
+ }
+ }
+}
+
+function fillSinks(h, epsilon) {
+ epsilon = epsilon || 1e-5;
+ var infinity = 999999;
+ var newh = zero(h.mesh);
+ for (var i = 0; i < h.length; i++) {
+ if (isnearedge(h.mesh, i)) {
+ newh[i] = h[i];
+ } else {
+ newh[i] = infinity;
+ }
+ }
+ while (true) {
+ var changed = false;
+ for (var i = 0; i < h.length; i++) {
+ if (newh[i] == h[i]) continue;
+ var nbs = neighbours(h.mesh, i);
+ for (var j = 0; j < nbs.length; j++) {
+ if (h[i] >= newh[nbs[j]] + epsilon) {
+ newh[i] = h[i];
+ changed = true;
+ break;
+ }
+ var oh = newh[nbs[j]] + epsilon;
+ if ((newh[i] > oh) && (oh > h[i])) {
+ newh[i] = oh;
+ changed = true;
+ }
+ }
+ }
+ if (!changed) return newh;
+ }
+}
+
+function getFlux(h) {
+ var dh = downhill(h);
+ var idxs = [];
+ var flux = zero(h.mesh);
+ for (var i = 0; i < h.length; i++) {
+ idxs[i] = i;
+ flux[i] = 1/h.length;
+ }
+ idxs.sort(function (a, b) {
+ return h[b] - h[a];
+ });
+ for (var i = 0; i < h.length; i++) {
+ var j = idxs[i];
+ if (dh[j] >= 0) {
+ flux[dh[j]] += flux[j];
+ }
+ }
+ return flux;
+}
+
+function getSlope(h) {
+ var dh = downhill(h);
+ var slope = zero(h.mesh);
+ for (var i = 0; i < h.length; i++) {
+ var s = trislope(h, i);
+ slope[i] = Math.sqrt(s[0] * s[0] + s[1] * s[1]);
+ continue;
+ if (dh[i] < 0) {
+ slope[i] = 0;
+ } else {
+ slope[i] = (h[i] - h[dh[i]]) / distance(h.mesh, i, dh[i]);
+ }
+ }
+ return slope;
+}
+
+function erosionRate(h) {
+ var flux = getFlux(h);
+ var slope = getSlope(h);
+ var newh = zero(h.mesh);
+ for (var i = 0; i < h.length; i++) {
+ var river = Math.sqrt(flux[i]) * slope[i];
+ var creep = slope[i] * slope[i];
+ var total = 1000 * river + creep;
+ total = total > 200 ? 200 : total;
+ newh[i] = total;
+ }
+ return newh;
+}
+
+function erode(h, amount) {
+ var er = erosionRate(h);
+ var newh = zero(h.mesh);
+ var maxr = d3.max(er);
+ for (var i = 0; i < h.length; i++) {
+ newh[i] = h[i] - amount * (er[i] / maxr);
+ }
+ return newh;
+}
+
+function doErosion(h, amount, n) {
+ n = n || 1;
+ h = fillSinks(h);
+ for (var i = 0; i < n; i++) {
+ h = erode(h, amount);
+ h = fillSinks(h);
+ }
+ return h;
+}
+
+function setSeaLevel(h, q) {
+ var newh = zero(h.mesh);
+ var delta = quantile(h, q);
+ for (var i = 0; i < h.length; i++) {
+ newh[i] = h[i] - delta;
+ }
+ return newh;
+}
+
+function cleanCoast(h, iters) {
+ for (var iter = 0; iter < iters; iter++) {
+ var changed = 0;
+ var newh = zero(h.mesh);
+ for (var i = 0; i < h.length; i++) {
+ newh[i] = h[i];
+ var nbs = neighbours(h.mesh, i);
+ if (h[i] <= 0 || nbs.length != 3) continue;
+ var count = 0;
+ var best = -999999;
+ for (var j = 0; j < nbs.length; j++) {
+ if (h[nbs[j]] > 0) {
+ count++;
+ } else if (h[nbs[j]] > best) {
+ best = h[nbs[j]];
+ }
+ }
+ if (count > 1) continue;
+ newh[i] = best / 2;
+ changed++;
+ }
+ h = newh;
+ newh = zero(h.mesh);
+ for (var i = 0; i < h.length; i++) {
+ newh[i] = h[i];
+ var nbs = neighbours(h.mesh, i);
+ if (h[i] > 0 || nbs.length != 3) continue;
+ var count = 0;
+ var best = 999999;
+ for (var j = 0; j < nbs.length; j++) {
+ if (h[nbs[j]] <= 0) {
+ count++;
+ } else if (h[nbs[j]] < best) {
+ best = h[nbs[j]];
+ }
+ }
+ if (count > 1) continue;
+ newh[i] = best / 2;
+ changed++;
+ }
+ h = newh;
+ }
+ return h;
+}
+
+function trislope(h, i) {
+ var nbs = neighbours(h.mesh, i);
+ if (nbs.length != 3) return [0,0];
+ var p0 = h.mesh.vxs[nbs[0]];
+ var p1 = h.mesh.vxs[nbs[1]];
+ var p2 = h.mesh.vxs[nbs[2]];
+
+ var x1 = p1[0] - p0[0];
+ var x2 = p2[0] - p0[0];
+ var y1 = p1[1] - p0[1];
+ var y2 = p2[1] - p0[1];
+
+ var det = x1 * y2 - x2 * y1;
+ var h1 = h[nbs[1]] - h[nbs[0]];
+ var h2 = h[nbs[2]] - h[nbs[0]];
+
+ return [(y2 * h1 - y1 * h2) / det,
+ (-x2 * h1 + x1 * h2) / det];
+}
+
+function cityScore(h, cities) {
+ var score = map(getFlux(h), Math.sqrt);
+ for (var i = 0; i < h.length; i++) {
+ if (h[i] <= 0 || isnearedge(h.mesh, i)) {
+ score[i] = -999999;
+ continue;
+ }
+ score[i] += 0.01 / (1e-9 + Math.abs(h.mesh.vxs[i][0]) - h.mesh.extent.width/2)
+ score[i] += 0.01 / (1e-9 + Math.abs(h.mesh.vxs[i][1]) - h.mesh.extent.height/2)
+ for (var j = 0; j < cities.length; j++) {
+ score[i] -= 0.02 / (distance(h.mesh, cities[j], i) + 1e-9);
+ }
+ }
+ return score;
+}
+function placeCity(render) {
+ render.cities = render.cities || [];
+ var score = cityScore(render.h, render.cities);
+ var newcity = d3.scan(score, d3.descending);
+ render.cities.push(newcity);
+}
+
+function placeCities(render) {
+ var params = render.params;
+ var h = render.h;
+ var n = params.ncities;
+ for (var i = 0; i < n; i++) {
+ placeCity(render);
+ }
+}
+
+function contour(h, level) {
+ level = level || 0;
+ var edges = [];
+ for (var i = 0; i < h.mesh.edges.length; i++) {
+ var e = h.mesh.edges[i];
+ if (e[3] == undefined) continue;
+ if (isnearedge(h.mesh, e[0]) || isnearedge(h.mesh, e[1])) continue;
+ if ((h[e[0]] > level && h[e[1]] <= level) ||
+ (h[e[1]] > level && h[e[0]] <= level)) {
+ edges.push([e[2], e[3]]);
+ }
+ }
+ return mergeSegments(edges);
+}
+
+function getRivers(h, limit) {
+ var dh = downhill(h);
+ var flux = getFlux(h);
+ var links = [];
+ var above = 0;
+ for (var i = 0; i < h.length; i++) {
+ if (h[i] > 0) above++;
+ }
+ limit *= above / h.length;
+ for (var i = 0; i < dh.length; i++) {
+ if (isnearedge(h.mesh, i)) continue;
+ if (flux[i] > limit && h[i] > 0 && dh[i] >= 0) {
+ var up = h.mesh.vxs[i];
+ var down = h.mesh.vxs[dh[i]];
+ if (h[dh[i]] > 0) {
+ links.push([up, down]);
+ } else {
+ links.push([up, [(up[0] + down[0])/2, (up[1] + down[1])/2]]);
+ }
+ }
+ }
+ return mergeSegments(links).map(relaxPath);
+}
+
+function getTerritories(render) {
+ var h = render.h;
+ var cities = render.cities;
+ var n = render.params.nterrs;
+ if (n > render.cities.length) n = render.cities.length;
+ var flux = getFlux(h);
+ var terr = [];
+ var queue = new PriorityQueue({comparator: function (a, b) {return a.score - b.score}});
+ function weight(u, v) {
+ var horiz = distance(h.mesh, u, v);
+ var vert = h[v] - h[u];
+ if (vert > 0) vert /= 10;
+ var diff = 1 + 0.25 * Math.pow(vert/horiz, 2);
+ diff += 100 * Math.sqrt(flux[u]);
+ if (h[u] <= 0) diff = 100;
+ if ((h[u] > 0) != (h[v] > 0)) return 1000;
+ return horiz * diff;
+ }
+ for (var i = 0; i < n; i++) {
+ terr[cities[i]] = cities[i];
+ var nbs = neighbours(h.mesh, cities[i]);
+ for (var j = 0; j < nbs.length; j++) {
+ queue.queue({
+ score: weight(cities[i], nbs[j]),
+ city: cities[i],
+ vx: nbs[j]
+ });
+ }
+ }
+ while (queue.length) {
+ var u = queue.dequeue();
+ if (terr[u.vx] != undefined) continue;
+ terr[u.vx] = u.city;
+ var nbs = neighbours(h.mesh, u.vx);
+ for (var i = 0; i < nbs.length; i++) {
+ var v = nbs[i];
+ if (terr[v] != undefined) continue;
+ var newdist = weight(u.vx, v);
+ queue.queue({
+ score: u.score + newdist,
+ city: u.city,
+ vx: v
+ });
+ }
+ }
+ terr.mesh = h.mesh;
+ return terr;
+}
+
+function getBorders(render) {
+ var terr = render.terr;
+ var h = render.h;
+ var edges = [];
+ for (var i = 0; i < terr.mesh.edges.length; i++) {
+ var e = terr.mesh.edges[i];
+ if (e[3] == undefined) continue;
+ if (isnearedge(terr.mesh, e[0]) || isnearedge(terr.mesh, e[1])) continue;
+ if (h[e[0]] < 0 || h[e[1]] < 0) continue;
+ if (terr[e[0]] != terr[e[1]]) {
+ edges.push([e[2], e[3]]);
+ }
+ }
+ return mergeSegments(edges).map(relaxPath);
+}
+
+function mergeSegments(segs) {
+ var adj = {};
+ for (var i = 0; i < segs.length; i++) {
+ var seg = segs[i];
+ var a0 = adj[seg[0]] || [];
+ var a1 = adj[seg[1]] || [];
+ a0.push(seg[1]);
+ a1.push(seg[0]);
+ adj[seg[0]] = a0;
+ adj[seg[1]] = a1;
+ }
+ var done = [];
+ var paths = [];
+ var path = null;
+ while (true) {
+ if (path == null) {
+ for (var i = 0; i < segs.length; i++) {
+ if (done[i]) continue;
+ done[i] = true;
+ path = [segs[i][0], segs[i][1]];
+ break;
+ }
+ if (path == null) break;
+ }
+ var changed = false;
+ for (var i = 0; i < segs.length; i++) {
+ if (done[i]) continue;
+ if (adj[path[0]].length == 2 && segs[i][0] == path[0]) {
+ path.unshift(segs[i][1]);
+ } else if (adj[path[0]].length == 2 && segs[i][1] == path[0]) {
+ path.unshift(segs[i][0]);
+ } else if (adj[path[path.length - 1]].length == 2 && segs[i][0] == path[path.length - 1]) {
+ path.push(segs[i][1]);
+ } else if (adj[path[path.length - 1]].length == 2 && segs[i][1] == path[path.length - 1]) {
+ path.push(segs[i][0]);
+ } else {
+ continue;
+ }
+ done[i] = true;
+ changed = true;
+ break;
+ }
+ if (!changed) {
+ paths.push(path);
+ path = null;
+ }
+ }
+ return paths;
+}
+
+function relaxPath(path) {
+ var newpath = [path[0]];
+ for (var i = 1; i < path.length - 1; i++) {
+ var newpt = [0.25 * path[i-1][0] + 0.5 * path[i][0] + 0.25 * path[i+1][0],
+ 0.25 * path[i-1][1] + 0.5 * path[i][1] + 0.25 * path[i+1][1]];
+ newpath.push(newpt);
+ }
+ newpath.push(path[path.length - 1]);
+ return newpath;
+}
+function visualizePoints(svg, pts) {
+ var circle = svg.selectAll('circle').data(pts);
+ circle.enter()
+ .append('circle');
+ circle.exit().remove();
+ d3.selectAll('circle')
+ .attr('cx', function (d) {return 1000*d[0]})
+ .attr('cy', function (d) {return 1000*d[1]})
+ .attr('r', 100 / Math.sqrt(pts.length));
+}
+
+function makeD3Path(path) {
+ var p = d3.path();
+ p.moveTo(1000*path[0][0], 1000*path[0][1]);
+ for (var i = 1; i < path.length; i++) {
+ p.lineTo(1000*path[i][0], 1000*path[i][1]);
+ }
+ return p.toString();
+}
+
+function visualizeVoronoi(svg, field, lo, hi) {
+ if (hi == undefined) hi = d3.max(field) + 1e-9;
+ if (lo == undefined) lo = d3.min(field) - 1e-9;
+ var mappedvals = field.map(function (x) {return x > hi ? 1 : x < lo ? 0 : (x - lo) / (hi - lo)});
+ var tris = svg.selectAll('path.field').data(field.mesh.tris)
+ tris.enter()
+ .append('path')
+ .classed('field', true);
+
+ tris.exit()
+ .remove();
+
+ svg.selectAll('path.field')
+ .attr('d', makeD3Path)
+ .style('fill', function (d, i) {
+ return d3.interpolateViridis(mappedvals[i]);
+ });
+}
+
+function visualizeDownhill(h) {
+ var links = getRivers(h, 0.01);
+ drawPaths('river', links);
+}
+
+function drawPaths(svg, cls, paths) {
+ var paths = svg.selectAll('path.' + cls).data(paths)
+ paths.enter()
+ .append('path')
+ .classed(cls, true)
+ paths.exit()
+ .remove();
+ svg.selectAll('path.' + cls)
+ .attr('d', makeD3Path);
+}
+
+function visualizeSlopes(svg, render) {
+ var h = render.h;
+ var strokes = [];
+ var r = 0.25 / Math.sqrt(h.length);
+ for (var i = 0; i < h.length; i++) {
+ if (h[i] <= 0 || isnearedge(h.mesh, i)) continue;
+ var nbs = neighbours(h.mesh, i);
+ nbs.push(i);
+ var s = 0;
+ var s2 = 0;
+ for (var j = 0; j < nbs.length; j++) {
+ var slopes = trislope(h, nbs[j]);
+ s += slopes[0] / 10;
+ s2 += slopes[1];
+ }
+ s /= nbs.length;
+ s2 /= nbs.length;
+ if (Math.abs(s) < runif(0.1, 0.4)) continue;
+ var l = r * runif(1, 2) * (1 - 0.2 * Math.pow(Math.atan(s), 2)) * Math.exp(s2/100);
+ var x = h.mesh.vxs[i][0];
+ var y = h.mesh.vxs[i][1];
+ if (Math.abs(l*s) > 2 * r) {
+ var n = Math.floor(Math.abs(l*s/r));
+ l /= n;
+ if (n > 4) n = 4;
+ for (var j = 0; j < n; j++) {
+ var u = rnorm() * r;
+ var v = rnorm() * r;
+ strokes.push([[x+u-l, y+v+l*s], [x+u+l, y+v-l*s]]);
+ }
+ } else {
+ strokes.push([[x-l, y+l*s], [x+l, y-l*s]]);
+ }
+ }
+ var lines = svg.selectAll('line.slope').data(strokes)
+ lines.enter()
+ .append('line')
+ .classed('slope', true);
+ lines.exit()
+ .remove();
+ svg.selectAll('line.slope')
+ .attr('x1', function (d) {return 1000*d[0][0]})
+ .attr('y1', function (d) {return 1000*d[0][1]})
+ .attr('x2', function (d) {return 1000*d[1][0]})
+ .attr('y2', function (d) {return 1000*d[1][1]})
+}
+
+
+function visualizeContour(h, level) {
+ level = level || 0;
+ var links = contour(h, level);
+ drawPaths('coast', links);
+}
+
+function visualizeBorders(h, cities, n) {
+ var links = getBorders(h, getTerritories(h, cities, n));
+ drawPaths('border', links);
+}
+
+
+function visualizeCities(svg, render) {
+ var cities = render.cities;
+ var h = render.h;
+ var n = render.params.nterrs;
+
+ var circs = svg.selectAll('circle.city').data(cities);
+ circs.enter()
+ .append('circle')
+ .classed('city', true);
+ circs.exit()
+ .remove();
+ svg.selectAll('circle.city')
+ .attr('cx', function (d) {return 1000*h.mesh.vxs[d][0]})
+ .attr('cy', function (d) {return 1000*h.mesh.vxs[d][1]})
+ .attr('r', function (d, i) {return i >= n ? 4 : 10})
+ .style('fill', 'white')
+ .style('stroke-width', 5)
+ .style('stroke-linecap', 'round')
+ .style('stroke', 'black')
+ .raise();
+}
+
+function dropEdge(h, p) {
+ p = p || 4
+ var newh = zero(h.mesh);
+ for (var i = 0; i < h.length; i++) {
+ var v = h.mesh.vxs[i];
+ var x = 2.4*v[0] / h.mesh.extent.width;
+ var y = 2.4*v[1] / h.mesh.extent.height;
+ newh[i] = h[i] - Math.exp(10*(Math.pow(Math.pow(x, p) + Math.pow(y, p), 1/p) - 1));
+ }
+ return newh;
+}
+
+function generateCoast(params) {
+ var mesh = generateGoodMesh(params.npts, params.extent);
+ var h = add(
+ slope(mesh, randomVector(6)),
+ cone(mesh, runif(-10, -10)),
+ mountains(mesh, 50)
+ );
+ for (var i = 0; i < 10; i++) {
+ h = relax(h);
+ }
+ h = peaky(h);
+ h = doErosion(h, runif(0, 0.1), 5);
+ h = setSeaLevel(h, runif(0.8, 0.7));
+ h = fillSinks(h);
+ h = cleanCoast(h, 3);
+ return h;
+}
+
+function terrCenter(h, terr, city, landOnly) {
+ var x = 0;
+ var y = 0;
+ var n = 0;
+ for (var i = 0; i < terr.length; i++) {
+ if (terr[i] != city) continue;
+ if (landOnly && h[i] <= 0) continue;
+ x += terr.mesh.vxs[i][0];
+ y += terr.mesh.vxs[i][1];
+ n++;
+ }
+ return [x/n, y/n];
+}
+
+function drawLabels(svg, render) {
+ var params = render.params;
+ var h = render.h;
+ var terr = render.terr;
+ var cities = render.cities;
+ var nterrs = render.params.nterrs;
+ var avoids = [render.rivers, render.coasts, render.borders];
+ var lang = makeRandomLanguage();
+ var citylabels = [];
+ function penalty(label) {
+ var pen = 0;
+ if (label.x0 < -0.45 * h.mesh.extent.width) pen += 100;
+ if (label.x1 > 0.45 * h.mesh.extent.width) pen += 100;
+ if (label.y0 < -0.45 * h.mesh.extent.height) pen += 100;
+ if (label.y1 > 0.45 * h.mesh.extent.height) pen += 100;
+ for (var i = 0; i < citylabels.length; i++) {
+ var olabel = citylabels[i];
+ if (label.x0 < olabel.x1 && label.x1 > olabel.x0 &&
+ label.y0 < olabel.y1 && label.y1 > olabel.y0) {
+ pen += 100;
+ }
+ }
+
+ for (var i = 0; i < cities.length; i++) {
+ var c = h.mesh.vxs[cities[i]];
+ if (label.x0 < c[0] && label.x1 > c[0] && label.y0 < c[1] && label.y1 > c[1]) {
+ pen += 100;
+ }
+ }
+ for (var i = 0; i < avoids.length; i++) {
+ var avoid = avoids[i];
+ for (var j = 0; j < avoid.length; j++) {
+ var avpath = avoid[j];
+ for (var k = 0; k < avpath.length; k++) {
+ var pt = avpath[k];
+ if (pt[0] > label.x0 && pt[0] < label.x1 && pt[1] > label.y0 && pt[1] < label.y1) {
+ pen++;
+ }
+ }
+ }
+ }
+ return pen;
+ }
+ for (var i = 0; i < cities.length; i++) {
+ var x = h.mesh.vxs[cities[i]][0];
+ var y = h.mesh.vxs[cities[i]][1];
+ var text = makeName(lang, 'city');
+ var size = i < nterrs ? params.fontsizes.city : params.fontsizes.town;
+ var sx = 0.65 * size/1000 * text.length;
+ var sy = size/1000;
+ var posslabels = [
+ {
+ x: x + 0.8 * sy,
+ y: y + 0.3 * sy,
+ align: 'start',
+ x0: x + 0.7 * sy,
+ y0: y - 0.6 * sy,
+ x1: x + 0.7 * sy + sx,
+ y1: y + 0.6 * sy
+ },
+ {
+ x: x - 0.8 * sy,
+ y: y + 0.3 * sy,
+ align: 'end',
+ x0: x - 0.9 * sy - sx,
+ y0: y - 0.7 * sy,
+ x1: x - 0.9 * sy,
+ y1: y + 0.7 * sy
+ },
+ {
+ x: x,
+ y: y - 0.8 * sy,
+ align: 'middle',
+ x0: x - sx/2,
+ y0: y - 1.9*sy,
+ x1: x + sx/2,
+ y1: y - 0.7 * sy
+ },
+ {
+ x: x,
+ y: y + 1.2 * sy,
+ align: 'middle',
+ x0: x - sx/2,
+ y0: y + 0.1*sy,
+ x1: x + sx/2,
+ y1: y + 1.3*sy
+ }
+ ];
+ var label = posslabels[d3.scan(posslabels, function (a, b) {return penalty(a) - penalty(b)})];
+ label.text = text;
+ label.size = size;
+ citylabels.push(label);
+ }
+ var texts = svg.selectAll('text.city').data(citylabels);
+ texts.enter()
+ .append('text')
+ .classed('city', true);
+ texts.exit()
+ .remove();
+ svg.selectAll('text.city')
+ .attr('x', function (d) {return 1000*d.x})
+ .attr('y', function (d) {return 1000*d.y})
+ .style('font-size', function (d) {return d.size})
+ .style('text-anchor', function (d) {return d.align})
+ .text(function (d) {return d.text})
+ .raise();
+
+ var reglabels = [];
+ for (var i = 0; i < nterrs; i++) {
+ var city = cities[i];
+ var text = makeName(lang, 'region');
+ var sy = params.fontsizes.region / 1000;
+ var sx = 0.6 * text.length * sy;
+ var lc = terrCenter(h, terr, city, true);
+ var oc = terrCenter(h, terr, city, false);
+ var best = 0;
+ var bestscore = -999999;
+ for (var j = 0; j < h.length; j++) {
+ var score = 0;
+ var v = h.mesh.vxs[j];
+ score -= 3000 * Math.sqrt((v[0] - lc[0]) * (v[0] - lc[0]) + (v[1] - lc[1]) * (v[1] - lc[1]));
+ score -= 1000 * Math.sqrt((v[0] - oc[0]) * (v[0] - oc[0]) + (v[1] - oc[1]) * (v[1] - oc[1]));
+ if (terr[j] != city) score -= 3000;
+ for (var k = 0; k < cities.length; k++) {
+ var u = h.mesh.vxs[cities[k]];
+ if (Math.abs(v[0] - u[0]) < sx &&
+ Math.abs(v[1] - sy/2 - u[1]) < sy) {
+ score -= k < nterrs ? 4000 : 500;
+ }
+ if (v[0] - sx/2 < citylabels[k].x1 &&
+ v[0] + sx/2 > citylabels[k].x0 &&
+ v[1] - sy < citylabels[k].y1 &&
+ v[1] > citylabels[k].y0) {
+ score -= 5000;
+ }
+ }
+ for (var k = 0; k < reglabels.length; k++) {
+ var label = reglabels[k];
+ if (v[0] - sx/2 < label.x + label.width/2 &&
+ v[0] + sx/2 > label.x - label.width/2 &&
+ v[1] - sy < label.y &&
+ v[1] > label.y - label.size) {
+ score -= 20000;
+ }
+ }
+ if (h[j] <= 0) score -= 500;
+ if (v[0] + sx/2 > 0.5 * h.mesh.extent.width) score -= 50000;
+ if (v[0] - sx/2 < -0.5 * h.mesh.extent.width) score -= 50000;
+ if (v[1] > 0.5 * h.mesh.extent.height) score -= 50000;
+ if (v[1] - sy < -0.5 * h.mesh.extent.height) score -= 50000;
+ if (score > bestscore) {
+ bestscore = score;
+ best = j;
+ }
+ }
+ reglabels.push({
+ text: text,
+ x: h.mesh.vxs[best][0],
+ y: h.mesh.vxs[best][1],
+ size:sy,
+ width:sx
+ });
+ }
+ texts = svg.selectAll('text.region').data(reglabels);
+ texts.enter()
+ .append('text')
+ .classed('region', true);
+ texts.exit()
+ .remove();
+ svg.selectAll('text.region')
+ .attr('x', function (d) {return 1000*d.x})
+ .attr('y', function (d) {return 1000*d.y})
+ .style('font-size', function (d) {return 1000*d.size})
+ .style('text-anchor', 'middle')
+ .text(function (d) {return d.text})
+ .raise();
+
+}
+function drawMap(svg, render) {
+ render.rivers = getRivers(render.h, 0.01);
+ render.coasts = contour(render.h, 0);
+ render.terr = getTerritories(render);
+ render.borders = getBorders(render);
+ drawPaths(svg, 'river', render.rivers);
+ drawPaths(svg, 'coast', render.coasts);
+ drawPaths(svg, 'border', render.borders);
+ visualizeSlopes(svg, render);
+ visualizeCities(svg, render);
+ drawLabels(svg, render);
+}
+
+function doMap(svg, params) {
+ var render = {
+ params: params
+ };
+ var width = svg.attr('width');
+ svg.attr('height', width * params.extent.height / params.extent.width);
+ svg.attr('viewBox', -1000 * params.extent.width/2 + ' ' +
+ -1000 * params.extent.height/2 + ' ' +
+ 1000 * params.extent.width + ' ' +
+ 1000 * params.extent.height);
+ svg.selectAll().remove();
+ render.h = params.generator(params);
+ placeCities(render);
+ drawMap(svg, render);
+}
+
+var defaultParams = {
+ extent: defaultExtent,
+ generator: generateCoast,
+ npts: 16384,
+ ncities: 15,
+ nterrs: 5,
+ fontsizes: {
+ region: 40,
+ city: 25,
+ town: 20
+ }
+}
+
diff --git a/main/img/grid1.png b/main/img/grid1.png
new file mode 100644
index 0000000000000000000000000000000000000000..4b915e3acfa8e844aee5152452dac6502474b59f
GIT binary patch
literal 3287
zcmeAS@N?(olHy`uVBq!ia0y~yU;#3j7&zE~l+0PVoj{5$$=lrpNCUx7=iT){inG8Y
zvY3H^TNs2H8D`Cq01C2~c>21sKVjh(WwI2Bi+sYsz?0(X;uunK>+S7@YncrNTrW=7
z|7;qQH07UkfxhFhiF-t!Ts9HdRP4w3`Nq^|hR^?itlqJ8no4p{`1`*_eOBM@9gljQ
zS^xX?{eR!K?_YgG{YH)|>m2mVB?9`}}9ww5V%Q8~6Wxn-5aq`lkQyMtjq5|BFE`
z-(k-PB*A`RZ~(CgGr<}Jz-kFG9l)wUt|e@^0K*)RI^q;NfRr*2vK~nRL<4b#6X!QN
z7*3pXk-SEV%Skbugn)(w3zZE2F?E_s_4~t`SwHXH`S-0{5SXmNsrUQ+|G->e!46CV
zcV>$NNd}DtswX8LU#;FhXK~-&?;EdG-2!KYzi;1beLMc|#(b&Y+f`ofjelObZ|>4*
zTf^RfvjWUW|K7iQL54UmGJz-#5YYf42s6PN6u@c;F&n_Dh%;P)!2%TK#3_atOvrj*
zSp@_NAff?85NWsqSS>;?k}=qs4PXt#xttWki8B$&c3K%uLRdgTh!mIOG5mwJuIIOV
z?ZH<*?cE7X*Giyt4Jzp0?f;*A?q?w%Fx+>T>jO!K00-|$hR0Taud{TQt$v@p_Ujf{
z;U5Yu{PR68RqsFdxyIUCH+$_3SXKcW3Ct?hptRS(1kS{Rph$6GC;$b^pl}H&c&Svl
zq5H=HWHyn8qw7VgjIc9lWjHBeLCy5^AUtZ)o4x$YS3IpQhBs<}IpR+J|KoE$Kb8T8
zWI=u$C_oo9P}WZR4$hLS;7qIlG7x*QhapO(T#s&L1H%JQIHC(
z0i+b48x_zLG=TZUxg1?DL3?OrIC0KJvYix{<1zfe`YkFqtL6OyPk(;~Z2xzIs|8?5
ozw`gUe#_^_Eg2XX9^CuKxJDs+bJ!8x^FS_xr>mdKI;Vst06ZghDF6Tf
literal 0
HcmV?d00001
diff --git a/main/img/grid2.png b/main/img/grid2.png
new file mode 100644
index 0000000000000000000000000000000000000000..7621bf6b81facd15dc4d90cbb368987e2b1b094f
GIT binary patch
literal 3282
zcmeAS@N?(olHy`uVBq!ia0y~yU;#3j7&zE~l+0PVoj{5$$=lrpNCUx7=iT){inG8Y
zvY3H^TNs2H8D`Cq01C2~c>21sKVjh(WtMQ%srb#nz!UH3;uunK>+S806Av5kxLo|&
zYb6k!@NU}8iN#0Gt&pl&DP5qnC!ERbw{gXqt#*t+L-O8wOtO5Q-BW1kE?@nA^Qw8@
zw(tM@HoyM&?ykQZ?Y}KQ{?C07-45Ct3ze#9$Q04Z$%5e&3&3DDREkl6!lI0>-=
z3qzor8$b>x>~azeC(=Zun4ps3e@;zQseXT1v+C!)JO93w3;s^7f71_4+~4p2-+1kp
z1v}86cV>%&yqocWqRdbY%1{k#EFhx?vs;+Ukk9FK_)!uwQiR?qjlc>4P@U`gJ6LmrYFcK-j@
zzxCR2OQ3Hb+}i{4vjemHq%)TB$vvknf8D5_ANq9*q+YmvKNOsMY`@u0O6e&)YkB|N
zCGXIqka{7%UL06y9RK&_#(i#(AtnkSvH?U8E=#~UUjeL^xSWqvR1jn`H2~|*!Qm2+
z4;4TJ(RCV7X#+?-;V>jF;1ob+HGl}hCL)C_jSN=+J7fS1-(RG1^4{-~uDE^Xz(!B(
zk$;ffaQ^T2dSL759HLb)HLI3`n@G3s|67*?s!LvO
z{6A48xhMPF&$4N8tF+)vs19foDh_1E0!DD5#sXqHfCvVHOq!K~bBMAY$$d0)3CJOX
zz;Gn5633)cdF%l4KXO7KAuJ%_Mx1jY_TVx6$5ds{Z}*l5fBCd`=ij%G_C2U>c(?z5
i^4hP3d_Y(3*k1p4X_m|h71gOAM|-;ZxvX21sKVjh(Wj2~MeWNY|1CNuZi(^Q|t+%%o`-e0{K(iPUvXwpG{jLiQwLWgSYxlJ%|KGRo
z|NFLm|KHf7|8B_tElyZ^{=a}PtSalUk{X3ebfJUqy4w^`g%X0exSpFKmkM$
zWHx|RaezpIOa+iCf+j)~5NBco*hH{e1u&C1my=>RaV8?!P9wt`!2TNqh9h~EI3_7B
zCurh_)e}|j#`+abdw=$Ae!Vy_(H;k->COND^;l{rPb~lHmaZ*_i;W-vML@
zI2$t%WD0=QGJ;5gOi;l<*hB}ADh9>_oIuh6#2jdsfSf?kZ%7JA@+R?yJAjlD85R(=
z#Kj8O#4)LA_>Y?&liukqw>bU%8L(XM24;ZddSDTLv;IG@3V19745AI@
z`aqJQpkboQ_uBodR?U4Zb2m17?ef3CTmz~O)+K>7SSJ6Us1kbhdge
zJj^4C&Adsx;iQBGSgixdY$9Dwis7V$1z0Ur4X-nsv}E^b&2yjj?gSR!
qN|53^x&GVz|Ax>1Sg-?q{N}BE!z1yGC5C^&7JIt-xvX
- @@@ilinx
+ @@@ilinχ
-
+
+
-
-
-
-
i
- l
- i
- n
- x
-
-
-
lemuria
+
-
mu
+
-
+
+
i
+ l
+ i
+ n
+ χ
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
diff --git a/main/map.html b/main/map.html
new file mode 100644
index 0000000..89d8c86
--- /dev/null
+++ b/main/map.html
@@ -0,0 +1,72 @@
+
+