From 71ca7a11660b3ddf551360f2c446e150b5a32c03 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Sun, 14 Feb 2021 16:49:35 +0300 Subject: [PATCH] v1.5.276 - libs minification --- index.css | 5 - index.html | 10 +- libs/alea.min.js | 3 + libs/lineclip.js | 103 ---- libs/lineclip.min.js | 2 + libs/pell.js | 163 ------ libs/pell.min.js | 2 + libs/rgbquant.js | 935 ---------------------------------- libs/rgbquant.min.js | 2 + libs/seedrandom.min.js | 1 - main.js | 4 +- modules/burgs-and-states.js | 4 +- modules/cultures-generator.js | 5 - modules/river-generator.js | 4 +- modules/ui/layers.js | 2 +- modules/ui/options.js | 2 +- modules/ui/tools.js | 3 +- 17 files changed, 24 insertions(+), 1226 deletions(-) create mode 100644 libs/alea.min.js delete mode 100644 libs/lineclip.js create mode 100644 libs/lineclip.min.js delete mode 100644 libs/pell.js create mode 100644 libs/pell.min.js delete mode 100644 libs/rgbquant.js create mode 100644 libs/rgbquant.min.js delete mode 100644 libs/seedrandom.min.js diff --git a/index.css b/index.css index e04559db..2fff4e78 100644 --- a/index.css +++ b/index.css @@ -5,11 +5,6 @@ src: url(data:application/font-woff2;charset=utf-8;base64,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) format('woff2'); } -body { - border: 0; - height: 100%; -} - t { pointer-events: none; } diff --git a/index.html b/index.html index 82b6e64e..d1d2aff1 100644 --- a/index.html +++ b/index.html @@ -37,7 +37,7 @@ - + @@ -3985,9 +3985,9 @@ - + - + @@ -4030,7 +4030,7 @@ - + - + diff --git a/libs/alea.min.js b/libs/alea.min.js new file mode 100644 index 00000000..f4ecef67 --- /dev/null +++ b/libs/alea.min.js @@ -0,0 +1,3 @@ +/*https://github.com/macmcmeans/aleaPRNG/blob/master/aleaPRNG-1.1.js +©2010 Johannes Baagøe, MIT license; Derivative ©2017-2020 W. Mac" McMeans, BSD license.*/ +const aleaPRNG=function(){return function(n){"use strict";var r,t,e,o,a,u=new Uint32Array(3),i="";function c(n){var a=function(){var n=4022871197,r=function(r){r=r.toString();for(var t=0,e=r.length;t>>0,n=(o*=n)>>>0,n+=4294967296*(o-=n)}return 2.3283064365386963e-10*(n>>>0)};return r.version="Mash 0.9",r}();r=a(" "),t=a(" "),e=a(" "),o=1;for(var u=0;uarguments[1]&&(n=arguments[1],r=arguments[0]),f(n)&&f(r)?Math.floor(l()*(r-n+1))+n:l()*(r-n)+n},l.restart=function(){c(a)},l.seed=function(){c(Array.prototype.slice.call(arguments))},l.version=function(){return"aleaPRNG 1.1.0"},l.versions=function(){return"aleaPRNG 1.1.0, "+i},0===n.length&&(window.crypto.getRandomValues(u),n=[u[0],u[1],u[2]]),a=n,c(n),l}(Array.prototype.slice.call(arguments))}; \ No newline at end of file diff --git a/libs/lineclip.js b/libs/lineclip.js deleted file mode 100644 index b43da33b..00000000 --- a/libs/lineclip.js +++ /dev/null @@ -1,103 +0,0 @@ -'use strict'; -// lineclip by mourner, https://github.com/mapbox/lineclip -// Cohen-Sutherland line clippign algorithm, adapted to efficiently -// handle polylines rather than just segments -function lineclip(points, bbox, result) { - var len = points.length, - codeA = bitCode(points[0], bbox), - part = [], - i, a, b, codeB, lastCode; - if (!result) result = []; - - for (i = 1; i < len; i++) { - a = points[i - 1]; - b = points[i]; - codeB = lastCode = bitCode(b, bbox); - - while (true) { - if (!(codeA | codeB)) { // accept - part.push(a); - - if (codeB !== lastCode) { // segment went outside - part.push(b); - if (i < len - 1) { // start a new line - result.push(part); - part = []; - } - } else if (i === len - 1) { - part.push(b); - } - break; - - } else if (codeA & codeB) { // trivial reject - break; - } else if (codeA) { // a outside, intersect with clip edge - a = intersect(a, b, codeA, bbox); - codeA = bitCode(a, bbox); - } else { // b outside - b = intersect(a, b, codeB, bbox); - codeB = bitCode(b, bbox); - } - } - codeA = lastCode; - } - - if (part.length) result.push(part); - - return result; -} - -// Sutherland-Hodgeman polygon clipping algorithm -function polygonclip(points, bbox, secure = 0) { - var result, edge, prev, prevInside, inter, i, p, inside; - - // clip against each side of the clip rectangle - for (edge = 1; edge <= 8; edge *= 2) { - result = []; - prev = points[points.length-1]; - prevInside = !(bitCode(prev, bbox) & edge); - - for (i = 0; i < points.length; i++) { - p = points[i]; - inside = !(bitCode(p, bbox) & edge); - inter = inside !== prevInside; // segment goes through the clip window - - const pi = intersect(prev, p, edge, bbox); - if (inter) result.push(pi); // add an intersection point - if (secure && inter) result.push(pi, pi); // add additional intersection points to secure correct d3 curve - if (inside) result.push(p); // add a point if it's inside - - prev = p; - prevInside = inside; - } - points = result; - if (!points.length) break; - } - //result.forEach(p => debug.append("circle").attr("cx", p[0]).attr("cy", p[1]).attr("r", .6).attr("fill", "red")); - return result; -} - -// intersect a segment against one of the 4 lines that make up the bbox -function intersect(a, b, edge, bbox) { - return edge & 8 ? [a[0] + (b[0] - a[0]) * (bbox[3] - a[1]) / (b[1] - a[1]), bbox[3]] : // top - edge & 4 ? [a[0] + (b[0] - a[0]) * (bbox[1] - a[1]) / (b[1] - a[1]), bbox[1]] : // bottom - edge & 2 ? [bbox[2], a[1] + (b[1] - a[1]) * (bbox[2] - a[0]) / (b[0] - a[0])] : // right - edge & 1 ? [bbox[0], a[1] + (b[1] - a[1]) * (bbox[0] - a[0]) / (b[0] - a[0])] : null; // left -} - -// bit code reflects the point position relative to the bbox: -// left mid right -// top 1001 1000 1010 -// mid 0001 0000 0010 -// bottom 0101 0100 0110 -function bitCode(p, bbox) { - var code = 0; - - if (p[0] < bbox[0]) code |= 1; // left - else if (p[0] > bbox[2]) code |= 2; // right - - if (p[1] < bbox[1]) code |= 4; // bottom - else if (p[1] > bbox[3]) code |= 8; // top - - return code; -} \ No newline at end of file diff --git a/libs/lineclip.min.js b/libs/lineclip.min.js new file mode 100644 index 00000000..d1796476 --- /dev/null +++ b/libs/lineclip.min.js @@ -0,0 +1,2 @@ +// lineclip by mourner, https://github.com/mapbox/lineclip +"use strict";function lineclip(t,e,n){var r,i,u,o,s,h=t.length,c=bitCode(t[0],e),f=[];for(n=n||[],r=1;re[2]&&(n|=2),t[1]e[3]&&(n|=8),n} \ No newline at end of file diff --git a/libs/pell.js b/libs/pell.js deleted file mode 100644 index 9274f50d..00000000 --- a/libs/pell.js +++ /dev/null @@ -1,163 +0,0 @@ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global.Pell = factory()); -}(this, (function () { 'use strict'; - - const defaultParagraphSeparatorString = 'defaultParagraphSeparator' - const formatBlock = 'formatBlock' - const addEventListener = (parent, type, listener) => parent.addEventListener(type, listener) - const appendChild = (parent, child) => parent.appendChild(child) - const createElement = tag => document.createElement(tag) - const queryCommandState = command => document.queryCommandState(command) - const queryCommandValue = command => document.queryCommandValue(command) - const exec = (command, value = null) => document.execCommand(command, false, value) - - const defaultActions = { - bold: { - icon: 'B', - title: 'Bold', - state: () => queryCommandState('bold'), - result: () => exec('bold') - }, - italic: { - icon: 'I', - title: 'Italic', - state: () => queryCommandState('italic'), - result: () => exec('italic') - }, - underline: { - icon: 'U', - title: 'Underline', - state: () => queryCommandState('underline'), - result: () => exec('underline') - }, - strikethrough: { - icon: 'S', - title: 'Strike-through', - state: () => queryCommandState('strikeThrough'), - result: () => exec('strikeThrough') - }, - heading1: { - icon: 'H1', - title: 'Heading 1', - result: () => exec(formatBlock, '

') - }, - heading2: { - icon: 'H2', - title: 'Heading 2', - result: () => exec(formatBlock, '

') - }, - paragraph: { - icon: '¶', - title: 'Paragraph', - result: () => exec(formatBlock, '

') - }, - quote: { - icon: '“ ”', - title: 'Quote', - result: () => exec(formatBlock, '

') - }, - olist: { - icon: '#', - title: 'Ordered List', - result: () => exec('insertOrderedList') - }, - ulist: { - icon: '•', - title: 'Unordered List', - result: () => exec('insertUnorderedList') - }, - code: { - icon: '</>', - title: 'Code', - result: () => exec(formatBlock, '
')
-    },
-    line: {
-      icon: '―',
-      title: 'Horizontal Line',
-      result: () => exec('insertHorizontalRule')
-    },
-    link: {
-      icon: '🔗',
-      title: 'Link',
-      result: () => navigator.clipboard.readText().then(url => exec('createLink', url))
-    },
-    image: {
-      icon: '📷',
-      title: 'Image',
-      result: () => {
-        navigator.clipboard.readText().then(url => exec('insertImage', url))
-        exec('enableObjectResizing')
-      }
-    }
-  }
-  
-  const defaultClasses = {
-    actionbar: 'pell-actionbar',
-    button: 'pell-button',
-    content: 'pell-content',
-    selected: 'pell-button-selected'
-  }
-  
-  const init = settings => {
-    const actions = settings.actions
-      ? (
-        settings.actions.map(action => {
-          if (typeof action === 'string') return defaultActions[action]
-          else if (defaultActions[action.name]) return { ...defaultActions[action.name], ...action }
-          return action
-        })
-      )
-      : Object.keys(defaultActions).map(action => defaultActions[action])
-  
-    const classes = { ...defaultClasses, ...settings.classes }
-  
-    const defaultParagraphSeparator = settings[defaultParagraphSeparatorString] || 'div'
-  
-    const actionbar = createElement('div')
-    actionbar.className = classes.actionbar
-    appendChild(settings.element, actionbar)
-  
-    const content = settings.element.content = createElement('div')
-    content.contentEditable = true
-    content.className = classes.content
-    content.oninput = ({ target: { firstChild } }) => {
-      if (firstChild && firstChild.nodeType === 3) exec(formatBlock, `<${defaultParagraphSeparator}>`)
-      else if (content.innerHTML === '
') content.innerHTML = '' - settings.onChange(content.innerHTML) - } - content.onkeydown = event => { - if (event.key === 'Enter' && queryCommandValue(formatBlock) === 'blockquote') { - setTimeout(() => exec(formatBlock, `<${defaultParagraphSeparator}>`), 0) - } - } - appendChild(settings.element, content) - - actions.forEach(action => { - const button = createElement('button') - button.className = classes.button - button.innerHTML = action.icon - button.title = action.title - button.setAttribute('type', 'button') - button.onclick = () => action.result() && content.focus() - - if (action.state) { - const handler = () => button.classList[action.state() ? 'add' : 'remove'](classes.selected) - addEventListener(content, 'keyup', handler) - addEventListener(content, 'mouseup', handler) - addEventListener(button, 'click', handler) - } - - appendChild(actionbar, button) - }) - - if (settings.styleWithCSS) exec('styleWithCSS') - exec(defaultParagraphSeparatorString, defaultParagraphSeparator) - - return settings.element - } - - return {exec, init} - -}))); \ No newline at end of file diff --git a/libs/pell.min.js b/libs/pell.min.js new file mode 100644 index 00000000..c5be57e5 --- /dev/null +++ b/libs/pell.min.js @@ -0,0 +1,2 @@ +// https://github.com/jaredreich/pell, MIT License +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Pell=t()}(this,function(){"use strict";const e=(e,t,n)=>e.addEventListener(t,n),t=(e,t)=>e.appendChild(t),n=e=>document.createElement(e),i=e=>document.queryCommandState(e),o=(e,t=null)=>document.execCommand(e,!1,t),l={bold:{icon:"B",title:"Bold",state:()=>i("bold"),result:()=>o("bold")},italic:{icon:"I",title:"Italic",state:()=>i("italic"),result:()=>o("italic")},underline:{icon:"U",title:"Underline",state:()=>i("underline"),result:()=>o("underline")},strikethrough:{icon:"S",title:"Strike-through",state:()=>i("strikeThrough"),result:()=>o("strikeThrough")},heading1:{icon:"H1",title:"Heading 1",result:()=>o("formatBlock","

")},heading2:{icon:"H2",title:"Heading 2",result:()=>o("formatBlock","

")},paragraph:{icon:"¶",title:"Paragraph",result:()=>o("formatBlock","

")},quote:{icon:"“ ”",title:"Quote",result:()=>o("formatBlock","

")},olist:{icon:"#",title:"Ordered List",result:()=>o("insertOrderedList")},ulist:{icon:"•",title:"Unordered List",result:()=>o("insertUnorderedList")},code:{icon:"</>",title:"Code",result:()=>o("formatBlock","
")},line:{icon:"―",title:"Horizontal Line",result:()=>o("insertHorizontalRule")},link:{icon:"🔗",title:"Link",result:()=>navigator.clipboard.readText().then(e=>o("createLink",e))},image:{icon:"📷",title:"Image",result:()=>{navigator.clipboard.readText().then(e=>o("insertImage",e)),o("enableObjectResizing")}}},r={actionbar:"pell-actionbar",button:"pell-button",content:"pell-content",selected:"pell-button-selected"};return{exec:o,init:i=>{const a=i.actions?i.actions.map(e=>"string"==typeof e?l[e]:l[e.name]?{...l[e.name],...e}:e):Object.keys(l).map(e=>l[e]),s={...r,...i.classes},c=i.defaultParagraphSeparator||"div",u=n("div");u.className=s.actionbar,t(i.element,u);const d=i.element.content=n("div");return d.contentEditable=!0,d.className=s.content,d.oninput=(({target:{firstChild:e}})=>{e&&3===e.nodeType?o("formatBlock",`<${c}>`):"
"===d.innerHTML&&(d.innerHTML=""),i.onChange(d.innerHTML)}),d.onkeydown=(e=>{"Enter"===e.key&&"blockquote"===(e=>document.queryCommandValue(e))("formatBlock")&&setTimeout(()=>o("formatBlock",`<${c}>`),0)}),t(i.element,d),a.forEach(i=>{const o=n("button");if(o.className=s.button,o.innerHTML=i.icon,o.title=i.title,o.setAttribute("type","button"),o.onclick=(()=>i.result()&&d.focus()),i.state){const t=()=>o.classList[i.state()?"add":"remove"](s.selected);e(d,"keyup",t),e(d,"mouseup",t),e(o,"click",t)}t(u,o)}),i.styleWithCSS&&o("styleWithCSS"),o("defaultParagraphSeparator",c),i.element}}}); \ No newline at end of file diff --git a/libs/rgbquant.js b/libs/rgbquant.js deleted file mode 100644 index bc0bd1b9..00000000 --- a/libs/rgbquant.js +++ /dev/null @@ -1,935 +0,0 @@ -/* -* Copyright (c) 2015, Leon Sorokin -* All rights reserved. (MIT Licensed) -* -* RgbQuant.js - an image quantization lib -*/ - -(function(){ - function RgbQuant(opts) { - opts = opts || {}; - - // 1 = by global population, 2 = subregion population threshold - this.method = opts.method || 2; - // desired final palette size - this.colors = opts.colors || 256; - // # of highest-frequency colors to start with for palette reduction - this.initColors = opts.initColors || 4096; - // color-distance threshold for initial reduction pass - this.initDist = opts.initDist || 0.01; - // subsequent passes threshold - this.distIncr = opts.distIncr || 0.005; - // palette grouping - this.hueGroups = opts.hueGroups || 10; - this.satGroups = opts.satGroups || 10; - this.lumGroups = opts.lumGroups || 10; - // if > 0, enables hues stats and min-color retention per group - this.minHueCols = opts.minHueCols || 0; - // HueStats instance - this.hueStats = this.minHueCols ? new HueStats(this.hueGroups, this.minHueCols) : null; - - // subregion partitioning box size - this.boxSize = opts.boxSize || [64,64]; - // number of same pixels required within box for histogram inclusion - this.boxPxls = opts.boxPxls || 2; - // palette locked indicator - this.palLocked = false; - // palette sort order -// this.sortPal = ['hue-','lum-','sat-']; - - // dithering/error diffusion kernel name - this.dithKern = opts.dithKern || null; - // dither serpentine pattern - this.dithSerp = opts.dithSerp || false; - // minimum color difference (0-1) needed to dither - this.dithDelta = opts.dithDelta || 0; - - // accumulated histogram - this.histogram = {}; - // palette - rgb triplets - this.idxrgb = opts.palette ? opts.palette.slice(0) : []; - // palette - int32 vals - this.idxi32 = []; - // reverse lookup {i32:idx} - this.i32idx = {}; - // {i32:rgb} - this.i32rgb = {}; - // enable color caching (also incurs overhead of cache misses and cache building) - this.useCache = opts.useCache !== false; - // min color occurance count needed to qualify for caching - this.cacheFreq = opts.cacheFreq || 10; - // allows pre-defined palettes to be re-indexed (enabling palette compacting and sorting) - this.reIndex = opts.reIndex || this.idxrgb.length == 0; - // selection of color-distance equation - this.colorDist = opts.colorDist == "manhattan" ? distManhattan : distEuclidean; - - // if pre-defined palette, build lookups - if (this.idxrgb.length > 0) { - var self = this; - this.idxrgb.forEach(function(rgb, i) { - var i32 = ( - (255 << 24) | // alpha - (rgb[2] << 16) | // blue - (rgb[1] << 8) | // green - rgb[0] // red - ) >>> 0; - - self.idxi32[i] = i32; - self.i32idx[i32] = i; - self.i32rgb[i32] = rgb; - }); - } - } - - // gathers histogram info - RgbQuant.prototype.sample = function sample(img, width) { - if (this.palLocked) - throw "Cannot sample additional images, palette already assembled."; - - var data = getImageData(img, width); - - switch (this.method) { - case 1: this.colorStats1D(data.buf32); break; - case 2: this.colorStats2D(data.buf32, data.width); break; - } - }; - - // image quantizer - // todo: memoize colors here also - // @retType: 1 - Uint8Array (default), 2 - Indexed array, 3 - Match @img type (unimplemented, todo) - RgbQuant.prototype.reduce = function reduce(img, retType, dithKern, dithSerp) { - if (!this.palLocked) - this.buildPal(); - - dithKern = dithKern || this.dithKern; - dithSerp = typeof dithSerp != "undefined" ? dithSerp : this.dithSerp; - - retType = retType || 1; - - // reduce w/dither - if (dithKern) - var out32 = this.dither(img, dithKern, dithSerp); - else { - var data = getImageData(img), - buf32 = data.buf32, - len = buf32.length, - out32 = new Uint32Array(len); - - for (var i = 0; i < len; i++) { - var i32 = buf32[i]; - out32[i] = this.nearestColor(i32); - } - } - - if (retType == 1) - return new Uint8Array(out32.buffer); - - if (retType == 2) { - var out = [], - len = out32.length; - - for (var i = 0; i < len; i++) { - var i32 = out32[i]; - out[i] = this.i32idx[i32]; - } - - return out; - } - }; - - // adapted from http://jsbin.com/iXofIji/2/edit by PAEz - RgbQuant.prototype.dither = function(img, kernel, serpentine) { - // http://www.tannerhelland.com/4660/dithering-eleven-algorithms-source-code/ - var kernels = { - FloydSteinberg: [ - [7 / 16, 1, 0], - [3 / 16, -1, 1], - [5 / 16, 0, 1], - [1 / 16, 1, 1] - ], - FalseFloydSteinberg: [ - [3 / 8, 1, 0], - [3 / 8, 0, 1], - [2 / 8, 1, 1] - ], - Stucki: [ - [8 / 42, 1, 0], - [4 / 42, 2, 0], - [2 / 42, -2, 1], - [4 / 42, -1, 1], - [8 / 42, 0, 1], - [4 / 42, 1, 1], - [2 / 42, 2, 1], - [1 / 42, -2, 2], - [2 / 42, -1, 2], - [4 / 42, 0, 2], - [2 / 42, 1, 2], - [1 / 42, 2, 2] - ], - Atkinson: [ - [1 / 8, 1, 0], - [1 / 8, 2, 0], - [1 / 8, -1, 1], - [1 / 8, 0, 1], - [1 / 8, 1, 1], - [1 / 8, 0, 2] - ], - Jarvis: [ // Jarvis, Judice, and Ninke / JJN? - [7 / 48, 1, 0], - [5 / 48, 2, 0], - [3 / 48, -2, 1], - [5 / 48, -1, 1], - [7 / 48, 0, 1], - [5 / 48, 1, 1], - [3 / 48, 2, 1], - [1 / 48, -2, 2], - [3 / 48, -1, 2], - [5 / 48, 0, 2], - [3 / 48, 1, 2], - [1 / 48, 2, 2] - ], - Burkes: [ - [8 / 32, 1, 0], - [4 / 32, 2, 0], - [2 / 32, -2, 1], - [4 / 32, -1, 1], - [8 / 32, 0, 1], - [4 / 32, 1, 1], - [2 / 32, 2, 1], - ], - Sierra: [ - [5 / 32, 1, 0], - [3 / 32, 2, 0], - [2 / 32, -2, 1], - [4 / 32, -1, 1], - [5 / 32, 0, 1], - [4 / 32, 1, 1], - [2 / 32, 2, 1], - [2 / 32, -1, 2], - [3 / 32, 0, 2], - [2 / 32, 1, 2], - ], - TwoSierra: [ - [4 / 16, 1, 0], - [3 / 16, 2, 0], - [1 / 16, -2, 1], - [2 / 16, -1, 1], - [3 / 16, 0, 1], - [2 / 16, 1, 1], - [1 / 16, 2, 1], - ], - SierraLite: [ - [2 / 4, 1, 0], - [1 / 4, -1, 1], - [1 / 4, 0, 1], - ], - }; - - if (!kernel || !kernels[kernel]) { - throw 'Unknown dithering kernel: ' + kernel; - } - - var ds = kernels[kernel]; - - var data = getImageData(img), -// buf8 = data.buf8, - buf32 = data.buf32, - width = data.width, - height = data.height, - len = buf32.length; - - var dir = serpentine ? -1 : 1; - - for (var y = 0; y < height; y++) { - if (serpentine) - dir = dir * -1; - - var lni = y * width; - - for (var x = (dir == 1 ? 0 : width - 1), xend = (dir == 1 ? width : 0); x !== xend; x += dir) { - // Image pixel - var idx = lni + x, - i32 = buf32[idx], - r1 = (i32 & 0xff), - g1 = (i32 & 0xff00) >> 8, - b1 = (i32 & 0xff0000) >> 16; - - // Reduced pixel - var i32x = this.nearestColor(i32), - r2 = (i32x & 0xff), - g2 = (i32x & 0xff00) >> 8, - b2 = (i32x & 0xff0000) >> 16; - - buf32[idx] = - (255 << 24) | // alpha - (b2 << 16) | // blue - (g2 << 8) | // green - r2; - - // dithering strength - if (this.dithDelta) { - var dist = this.colorDist([r1, g1, b1], [r2, g2, b2]); - if (dist < this.dithDelta) - continue; - } - - // Component distance - var er = r1 - r2, - eg = g1 - g2, - eb = b1 - b2; - - for (var i = (dir == 1 ? 0 : ds.length - 1), end = (dir == 1 ? ds.length : 0); i !== end; i += dir) { - var x1 = ds[i][1] * dir, - y1 = ds[i][2]; - - var lni2 = y1 * width; - - if (x1 + x >= 0 && x1 + x < width && y1 + y >= 0 && y1 + y < height) { - var d = ds[i][0]; - var idx2 = idx + (lni2 + x1); - - var r3 = (buf32[idx2] & 0xff), - g3 = (buf32[idx2] & 0xff00) >> 8, - b3 = (buf32[idx2] & 0xff0000) >> 16; - - var r4 = Math.max(0, Math.min(255, r3 + er * d)), - g4 = Math.max(0, Math.min(255, g3 + eg * d)), - b4 = Math.max(0, Math.min(255, b3 + eb * d)); - - buf32[idx2] = - (255 << 24) | // alpha - (b4 << 16) | // blue - (g4 << 8) | // green - r4; // red - } - } - } - } - - return buf32; - }; - - // reduces histogram to palette, remaps & memoizes reduced colors - RgbQuant.prototype.buildPal = function buildPal(noSort) { - if (this.palLocked || this.idxrgb.length > 0 && this.idxrgb.length <= this.colors) return; - - var histG = this.histogram, - sorted = sortedHashKeys(histG, true); - - if (sorted.length == 0) - throw "Nothing has been sampled, palette cannot be built."; - - switch (this.method) { - case 1: - var cols = this.initColors, - last = sorted[cols - 1], - freq = histG[last]; - - var idxi32 = sorted.slice(0, cols); - - // add any cut off colors with same freq as last - var pos = cols, len = sorted.length; - while (pos < len && histG[sorted[pos]] == freq) - idxi32.push(sorted[pos++]); - - // inject min huegroup colors - if (this.hueStats) - this.hueStats.inject(idxi32); - - break; - case 2: - var idxi32 = sorted; - break; - } - - // int32-ify values - idxi32 = idxi32.map(function(v){return +v;}); - - this.reducePal(idxi32); - - if (!noSort && this.reIndex) - this.sortPal(); - - // build cache of top histogram colors - if (this.useCache) - this.cacheHistogram(idxi32); - - this.palLocked = true; - }; - - RgbQuant.prototype.palette = function palette(tuples, noSort) { - this.buildPal(noSort); - return tuples ? this.idxrgb : new Uint8Array((new Uint32Array(this.idxi32)).buffer); - }; - - RgbQuant.prototype.prunePal = function prunePal(keep) { - var i32; - - for (var j = 0; j < this.idxrgb.length; j++) { - if (!keep[j]) { - i32 = this.idxi32[j]; - this.idxrgb[j] = null; - this.idxi32[j] = null; - delete this.i32idx[i32]; - } - } - - // compact - if (this.reIndex) { - var idxrgb = [], - idxi32 = [], - i32idx = {}; - - for (var j = 0, i = 0; j < this.idxrgb.length; j++) { - if (this.idxrgb[j]) { - i32 = this.idxi32[j]; - idxrgb[i] = this.idxrgb[j]; - i32idx[i32] = i; - idxi32[i] = i32; - i++; - } - } - - this.idxrgb = idxrgb; - this.idxi32 = idxi32; - this.i32idx = i32idx; - } - }; - - // reduces similar colors from an importance-sorted Uint32 rgba array - RgbQuant.prototype.reducePal = function reducePal(idxi32) { - // if pre-defined palette's length exceeds target - if (this.idxrgb.length > this.colors) { - // quantize histogram to existing palette - var len = idxi32.length, keep = {}, uniques = 0, idx, pruned = false; - - for (var i = 0; i < len; i++) { - // palette length reached, unset all remaining colors (sparse palette) - if (uniques == this.colors && !pruned) { - this.prunePal(keep); - pruned = true; - } - - idx = this.nearestIndex(idxi32[i]); - - if (uniques < this.colors && !keep[idx]) { - keep[idx] = true; - uniques++; - } - } - - if (!pruned) { - this.prunePal(keep); - pruned = true; - } - } - // reduce histogram to create initial palette - else { - // build full rgb palette - var idxrgb = idxi32.map(function(i32) { - return [ - (i32 & 0xff), - (i32 & 0xff00) >> 8, - (i32 & 0xff0000) >> 16, - ]; - }); - - var len = idxrgb.length, - palLen = len, - thold = this.initDist; - - // palette already at or below desired length - if (palLen > this.colors) { - while (palLen > this.colors) { - var memDist = []; - - // iterate palette - for (var i = 0; i < len; i++) { - var pxi = idxrgb[i], i32i = idxi32[i]; - if (!pxi) continue; - - for (var j = i + 1; j < len; j++) { - var pxj = idxrgb[j], i32j = idxi32[j]; - if (!pxj) continue; - - var dist = this.colorDist(pxi, pxj); - - if (dist < thold) { - // store index,rgb,dist - memDist.push([j, pxj, i32j, dist]); - - // kill squashed value - delete(idxrgb[j]); - palLen--; - } - } - } - - // palette reduction pass - // console.log("palette length: " + palLen); - - // if palette is still much larger than target, increment by larger initDist - thold += (palLen > this.colors * 3) ? this.initDist : this.distIncr; - } - - // if palette is over-reduced, re-add removed colors with largest distances from last round - if (palLen < this.colors) { - // sort descending - sort.call(memDist, function(a,b) { - return b[3] - a[3]; - }); - - var k = 0; - while (palLen < this.colors) { - // re-inject rgb into final palette - idxrgb[memDist[k][0]] = memDist[k][1]; - - palLen++; - k++; - } - } - } - - var len = idxrgb.length; - for (var i = 0; i < len; i++) { - if (!idxrgb[i]) continue; - - this.idxrgb.push(idxrgb[i]); - this.idxi32.push(idxi32[i]); - - this.i32idx[idxi32[i]] = this.idxi32.length - 1; - this.i32rgb[idxi32[i]] = idxrgb[i]; - } - } - }; - - // global top-population - RgbQuant.prototype.colorStats1D = function colorStats1D(buf32) { - var histG = this.histogram, - num = 0, col, - len = buf32.length; - - for (var i = 0; i < len; i++) { - col = buf32[i]; - - // skip transparent - if ((col & 0xff000000) >> 24 == 0) continue; - - // collect hue stats - if (this.hueStats) - this.hueStats.check(col); - - if (col in histG) - histG[col]++; - else - histG[col] = 1; - } - }; - - // population threshold within subregions - // FIXME: this can over-reduce (few/no colors same?), need a way to keep - // important colors that dont ever reach local thresholds (gradients?) - RgbQuant.prototype.colorStats2D = function colorStats2D(buf32, width) { - var boxW = this.boxSize[0], - boxH = this.boxSize[1], - area = boxW * boxH, - boxes = makeBoxes(width, buf32.length / width, boxW, boxH), - histG = this.histogram, - self = this; - - boxes.forEach(function(box) { - var effc = Math.max(Math.round((box.w * box.h) / area) * self.boxPxls, 2), - histL = {}, col; - - iterBox(box, width, function(i) { - col = buf32[i]; - - // skip transparent - if ((col & 0xff000000) >> 24 == 0) return; - - // collect hue stats - if (self.hueStats) - self.hueStats.check(col); - - if (col in histG) - histG[col]++; - else if (col in histL) { - if (++histL[col] >= effc) - histG[col] = histL[col]; - } - else - histL[col] = 1; - }); - }); - - if (this.hueStats) - this.hueStats.inject(histG); - }; - - // TODO: group very low lum and very high lum colors - // TODO: pass custom sort order - RgbQuant.prototype.sortPal = function sortPal() { - var self = this; - - this.idxi32.sort(function(a,b) { - var idxA = self.i32idx[a], - idxB = self.i32idx[b], - rgbA = self.idxrgb[idxA], - rgbB = self.idxrgb[idxB]; - - var hslA = rgb2hsl(rgbA[0],rgbA[1],rgbA[2]), - hslB = rgb2hsl(rgbB[0],rgbB[1],rgbB[2]); - - // sort all grays + whites together - var hueA = (rgbA[0] == rgbA[1] && rgbA[1] == rgbA[2]) ? -1 : hueGroup(hslA.h, self.hueGroups); - var hueB = (rgbB[0] == rgbB[1] && rgbB[1] == rgbB[2]) ? -1 : hueGroup(hslB.h, self.hueGroups); - - var hueDiff = hueB - hueA; - if (hueDiff) return -hueDiff; - - var lumDiff = lumGroup(+hslB.l.toFixed(2)) - lumGroup(+hslA.l.toFixed(2)); - if (lumDiff) return -lumDiff; - - var satDiff = satGroup(+hslB.s.toFixed(2)) - satGroup(+hslA.s.toFixed(2)); - if (satDiff) return -satDiff; - }); - - // sync idxrgb & i32idx - this.idxi32.forEach(function(i32, i) { - self.idxrgb[i] = self.i32rgb[i32]; - self.i32idx[i32] = i; - }); - }; - - // TOTRY: use HUSL - http://boronine.com/husl/ - RgbQuant.prototype.nearestColor = function nearestColor(i32) { - var idx = this.nearestIndex(i32); - return idx === null ? 0 : this.idxi32[idx]; - }; - - // TOTRY: use HUSL - http://boronine.com/husl/ - RgbQuant.prototype.nearestIndex = function nearestIndex(i32) { - // alpha 0 returns null index - if ((i32 & 0xff000000) >> 24 == 0) - return null; - - if (this.useCache && (""+i32) in this.i32idx) - return this.i32idx[i32]; - - var min = 1000, - idx, - rgb = [ - (i32 & 0xff), - (i32 & 0xff00) >> 8, - (i32 & 0xff0000) >> 16, - ], - len = this.idxrgb.length; - - for (var i = 0; i < len; i++) { - if (!this.idxrgb[i]) continue; // sparse palettes - - var dist = this.colorDist(rgb, this.idxrgb[i]); - - if (dist < min) { - min = dist; - idx = i; - } - } - - return idx; - }; - - RgbQuant.prototype.cacheHistogram = function cacheHistogram(idxi32) { - for (var i = 0, i32 = idxi32[i]; i < idxi32.length && this.histogram[i32] >= this.cacheFreq; i32 = idxi32[i++]) - this.i32idx[i32] = this.nearestIndex(i32); - }; - - function HueStats(numGroups, minCols) { - this.numGroups = numGroups; - this.minCols = minCols; - this.stats = {}; - - for (var i = -1; i < numGroups; i++) - this.stats[i] = {num: 0, cols: []}; - - this.groupsFull = 0; - } - - HueStats.prototype.check = function checkHue(i32) { - if (this.groupsFull == this.numGroups + 1) - this.check = function() {return;}; - - var r = (i32 & 0xff), - g = (i32 & 0xff00) >> 8, - b = (i32 & 0xff0000) >> 16, - hg = (r == g && g == b) ? -1 : hueGroup(rgb2hsl(r,g,b).h, this.numGroups), - gr = this.stats[hg], - min = this.minCols; - - gr.num++; - - if (gr.num > min) - return; - if (gr.num == min) - this.groupsFull++; - - if (gr.num <= min) - this.stats[hg].cols.push(i32); - }; - - HueStats.prototype.inject = function injectHues(histG) { - for (var i = -1; i < this.numGroups; i++) { - if (this.stats[i].num <= this.minCols) { - switch (typeOf(histG)) { - case "Array": - this.stats[i].cols.forEach(function(col){ - if (histG.indexOf(col) == -1) - histG.push(col); - }); - break; - case "Object": - this.stats[i].cols.forEach(function(col){ - if (!histG[col]) - histG[col] = 1; - else - histG[col]++; - }); - break; - } - } - } - }; - - // Rec. 709 (sRGB) luma coef - var Pr = .2126, - Pg = .7152, - Pb = .0722; - - // http://alienryderflex.com/hsp.html - function rgb2lum(r,g,b) { - return Math.sqrt( - Pr * r*r + - Pg * g*g + - Pb * b*b - ); - } - - var rd = 255, - gd = 255, - bd = 255; - - var euclMax = Math.sqrt(Pr*rd*rd + Pg*gd*gd + Pb*bd*bd); - // perceptual Euclidean color distance - function distEuclidean(rgb0, rgb1) { - var rd = rgb1[0]-rgb0[0], - gd = rgb1[1]-rgb0[1], - bd = rgb1[2]-rgb0[2]; - - return Math.sqrt(Pr*rd*rd + Pg*gd*gd + Pb*bd*bd) / euclMax; - } - - var manhMax = Pr*rd + Pg*gd + Pb*bd; - // perceptual Manhattan color distance - function distManhattan(rgb0, rgb1) { - var rd = Math.abs(rgb1[0]-rgb0[0]), - gd = Math.abs(rgb1[1]-rgb0[1]), - bd = Math.abs(rgb1[2]-rgb0[2]); - - return (Pr*rd + Pg*gd + Pb*bd) / manhMax; - } - - // http://rgb2hsl.nichabi.com/javascript-function.php - function rgb2hsl(r, g, b) { - var max, min, h, s, l, d; - r /= 255; - g /= 255; - b /= 255; - max = Math.max(r, g, b); - min = Math.min(r, g, b); - l = (max + min) / 2; - if (max == min) { - h = s = 0; - } else { - d = max - min; - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - switch (max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break - } - h /= 6; - } -// h = Math.floor(h * 360) -// s = Math.floor(s * 100) -// l = Math.floor(l * 100) - return { - h: h, - s: s, - l: rgb2lum(r,g,b), - }; - } - - function hueGroup(hue, segs) { - var seg = 1/segs, - haf = seg/2; - - if (hue >= 1 - haf || hue <= haf) - return 0; - - for (var i = 1; i < segs; i++) { - var mid = i*seg; - if (hue >= mid - haf && hue <= mid + haf) - return i; - } - } - - function satGroup(sat) { - return sat; - } - - function lumGroup(lum) { - return lum; - } - - function typeOf(val) { - return Object.prototype.toString.call(val).slice(8,-1); - } - - var sort = isArrSortStable() ? Array.prototype.sort : stableSort; - - // must be used via stableSort.call(arr, fn) - function stableSort(fn) { - var type = typeOf(this[0]); - - if (type == "Number" || type == "String") { - var ord = {}, len = this.length, val; - - for (var i = 0; i < len; i++) { - val = this[i]; - if (ord[val] || ord[val] === 0) continue; - ord[val] = i; - } - - return this.sort(function(a,b) { - return fn(a,b) || ord[a] - ord[b]; - }); - } - else { - var ord = this.map(function(v){return v}); - - return this.sort(function(a,b) { - return fn(a,b) || ord.indexOf(a) - ord.indexOf(b); - }); - } - } - - // test if js engine's Array#sort implementation is stable - function isArrSortStable() { - var str = "abcdefghijklmnopqrstuvwxyz"; - - return "xyzvwtursopqmnklhijfgdeabc" == str.split("").sort(function(a,b) { - return ~~(str.indexOf(b)/2.3) - ~~(str.indexOf(a)/2.3); - }).join(""); - } - - // returns uniform pixel data from various img - // TODO?: if array is passed, createimagedata, createlement canvas? take a pxlen? - function getImageData(img, width) { - var can, ctx, imgd, buf8, buf32, height; - - switch (typeOf(img)) { - case "HTMLImageElement": - can = document.createElement("canvas"); - can.width = img.naturalWidth; - can.height = img.naturalHeight; - ctx = can.getContext("2d"); - ctx.drawImage(img,0,0); - case "Canvas": - case "HTMLCanvasElement": - can = can || img; - ctx = ctx || can.getContext("2d"); - case "CanvasRenderingContext2D": - ctx = ctx || img; - can = can || ctx.canvas; - imgd = ctx.getImageData(0, 0, can.width, can.height); - case "ImageData": - imgd = imgd || img; - width = imgd.width; - if (typeOf(imgd.data) == "CanvasPixelArray") - buf8 = new Uint8Array(imgd.data); - else - buf8 = imgd.data; - case "Array": - case "CanvasPixelArray": - buf8 = buf8 || new Uint8Array(img); - case "Uint8Array": - case "Uint8ClampedArray": - buf8 = buf8 || img; - buf32 = new Uint32Array(buf8.buffer); - case "Uint32Array": - buf32 = buf32 || img; - buf8 = buf8 || new Uint8Array(buf32.buffer); - width = width || buf32.length; - height = buf32.length / width; - } - - return { - can: can, - ctx: ctx, - imgd: imgd, - buf8: buf8, - buf32: buf32, - width: width, - height: height, - }; - } - - // partitions a rect of wid x hgt into - // array of bboxes of w0 x h0 (or less) - function makeBoxes(wid, hgt, w0, h0) { - var wnum = ~~(wid/w0), wrem = wid%w0, - hnum = ~~(hgt/h0), hrem = hgt%h0, - xend = wid-wrem, yend = hgt-hrem; - - var bxs = []; - for (var y = 0; y < hgt; y += h0) - for (var x = 0; x < wid; x += w0) - bxs.push({x:x, y:y, w:(x==xend?wrem:w0), h:(y==yend?hrem:h0)}); - - return bxs; - } - - // iterates @bbox within a parent rect of width @wid; calls @fn, passing index within parent - function iterBox(bbox, wid, fn) { - var b = bbox, - i0 = b.y * wid + b.x, - i1 = (b.y + b.h - 1) * wid + (b.x + b.w - 1), - cnt = 0, incr = wid - b.w + 1, i = i0; - - do { - fn.call(this, i); - i += (++cnt % b.w == 0) ? incr : 1; - } while (i <= i1); - } - - // returns array of hash keys sorted by their values - function sortedHashKeys(obj, desc) { - var keys = []; - - for (var key in obj) - keys.push(key); - - return sort.call(keys, function(a,b) { - return desc ? obj[b] - obj[a] : obj[a] - obj[b]; - }); - } - - // expose - this.RgbQuant = RgbQuant; - - // expose to commonJS - if (typeof module !== 'undefined' && module.exports) { - module.exports = RgbQuant; - } - -}).call(this); \ No newline at end of file diff --git a/libs/rgbquant.min.js b/libs/rgbquant.min.js new file mode 100644 index 00000000..1cc0104e --- /dev/null +++ b/libs/rgbquant.min.js @@ -0,0 +1,2 @@ +// © 2015, Leon Sorokin, MIT +(function(){function t(t){var s;t=t||{},this.method=t.method||2,this.colors=t.colors||256,this.initColors=t.initColors||4096,this.initDist=t.initDist||.01,this.distIncr=t.distIncr||.005,this.hueGroups=t.hueGroups||10,this.satGroups=t.satGroups||10,this.lumGroups=t.lumGroups||10,this.minHueCols=t.minHueCols||0,this.hueStats=this.minHueCols?new i(this.hueGroups,this.minHueCols):null,this.boxSize=t.boxSize||[64,64],this.boxPxls=t.boxPxls||2,this.palLocked=!1,this.dithKern=t.dithKern||null,this.dithSerp=t.dithSerp||!1,this.dithDelta=t.dithDelta||0,this.histogram={},this.idxrgb=t.palette?t.palette.slice(0):[],this.idxi32=[],this.i32idx={},this.i32rgb={},this.useCache=!1!==t.useCache,this.cacheFreq=t.cacheFreq||10,this.reIndex=t.reIndex||0==this.idxrgb.length,this.colorDist="manhattan"==t.colorDist?n:r,0>>0;s.idxi32[i]=r,s.i32idx[r]=i,s.i32rgb[r]=t})}function i(t,i){this.numGroups=t,this.minCols=i,this.stats={};for(var r=-1;r>8,b=(16711680&x)>>16,m=this.nearestColor(x),v=255&m,x=(65280&m)>>8,m=(16711680&m)>>16;if(h[f]=255<<24|m<<16|x<<8|v,this.dithDelta)if(this.colorDist([p,g,b],[v,x,m])>8,A=(16711680&h[D])>>16,I=Math.max(0,Math.min(255,I+y*M)),P=Math.max(0,Math.min(255,P+w*M)),M=Math.max(0,Math.min(255,A+S*M)),h[D]=255<<24|M<<16|P<<8|I)}}}return h},t.prototype.buildPal=function(t){if(!(this.palLocked||0this.colors){for(var i,r=t.length,s={},e=0,h=!1,n=0;n>8,(16711680&t)>>16]}),o=r=a.length,u=this.initDist;if(o>this.colors){for(;o>this.colors;){for(var l=[],n=0;n3*this.colors?this.initDist:this.distIncr}if(o>24!=0&&(this.hueStats&&this.hueStats.check(i),i in r?r[i]++:r[i]=1)},t.prototype.colorStats2D=function(e,h){var t=this.boxSize[0],i=this.boxSize[1],n=t*i,i=function(t,i,r,s){for(var e=t%r,h=i%s,n=t-e,a=i-h,o=[],u=0;u>24!=0&&(o.hueStats&&o.hueStats.check(i),i in a?a[i]++:i in s?++s[i]>=r&&(a[i]=s[i]):s[i]=1)})}),this.hueStats&&this.hueStats.inject(a)},t.prototype.sortPal=function(){var e=this;this.idxi32.sort(function(t,i){var r=e.i32idx[t],s=e.i32idx[i],t=e.idxrgb[r],i=e.idxrgb[s],r=a(t[0],t[1],t[2]),s=a(i[0],i[1],i[2]),t=t[0]==t[1]&&t[1]==t[2]?-1:c(r.h,e.hueGroups),t=(i[0]==i[1]&&i[1]==i[2]?-1:c(s.h,e.hueGroups))-t;if(t)return-t;t=+s.l.toFixed(2)-+r.l.toFixed(2);if(t)return-t;r=+s.s.toFixed(2)-+r.s.toFixed(2);return r?-r:void 0}),this.idxi32.forEach(function(t,i){e.idxrgb[i]=e.i32rgb[t],e.i32idx[t]=i})},t.prototype.nearestColor=function(t){t=this.nearestIndex(t);return null===t?0:this.idxi32[t]},t.prototype.nearestIndex=function(t){if((4278190080&t)>>24==0)return null;if(this.useCache&&""+t in this.i32idx)return this.i32idx[t];for(var i,r,s=1e3,e=[255&t,(65280&t)>>8,(16711680&t)>>16],h=this.idxrgb.length,n=0;n=this.cacheFreq;r=t[i++])this.i32idx[r]=this.nearestIndex(r)},i.prototype.check=function(t){this.groupsFull==this.numGroups+1&&(this.check=function(){});var i=255&t,r=(65280&t)>>8,s=(16711680&t)>>16,i=i==r&&r==s?-1:c(a(i,r,s).h,this.numGroups),r=this.stats[i],s=this.minCols;r.num++,r.num>s||(r.num==s&&this.groupsFull++,r.num<=s&&this.stats[i].cols.push(t))},i.prototype.inject=function(i){for(var t=-1;t>>=1;return(n+t)/r};return m.int32=function(){return 0|p.g(4)},m.quick=function(){return p.g(4)/4294967296},m.double=m,q(s(p.S),a),(t.pass||e||function(n,r,t,e){return e&&(e.S&&o(e,p),n.state=function(){return o(p,{})}),t?(b[g]=n,r):n})(m,f,"global"in t?t.global:this==b,t.state)}function n(n){var r,t=n.length,u=this,e=0,o=u.i=u.j=0,i=u.S=[];for(t||(n=[t++]);e { s.provinces = []; if (!s.i || s.removed) return; diff --git a/modules/cultures-generator.js b/modules/cultures-generator.js index c54ce994..3fcf8170 100644 --- a/modules/cultures-generator.js +++ b/modules/cultures-generator.js @@ -388,14 +388,9 @@ if (cells.s[e] > 0) cells.culture[e] = c; // assign culture to populated cell cost[e] = totalCost; queue.queue({e, p:totalCost, c}); - - //debug.append("text").attr("x", (cells.p[n][0]+cells.p[e][0])/2 - 1).attr("y", (cells.p[n][1]+cells.p[e][1])/2 - 1).text(rn(totalCost-p)).attr("font-size", .8); - //const points = [cells.p[n][0], cells.p[n][1], (cells.p[n][0]+cells.p[e][0])/2, (cells.p[n][1]+cells.p[e][1])/2, cells.p[e][0], cells.p[e][1]]; - //debug.append("polyline").attr("points", points.toString()).attr("marker-mid", "url(#arrow)").attr("opacity", .6); } }); } - //debug.selectAll(".text").data(cost).enter().append("text").attr("x", (d, e) => cells.p[e][0]-1).attr("y", (d, e) => cells.p[e][1]-1).text(d => d ? rn(d) : "").attr("font-size", 2); TIME && console.timeEnd('expandCultures'); } diff --git a/modules/river-generator.js b/modules/river-generator.js index 69e3c571..e0c5cdbe 100644 --- a/modules/river-generator.js +++ b/modules/river-generator.js @@ -6,7 +6,7 @@ const generate = function(changeHeights = true) { TIME && console.time('generateRivers'); - Math.seedrandom(seed); + Math.random = aleaPRNG(seed); const cells = pack.cells, p = cells.p, features = pack.features; // build distance field in cells from water (cells.t) @@ -250,7 +250,7 @@ const specify = function() { if (!pack.rivers.length) return; - Math.seedrandom(seed); + Math.random = aleaPRNG(seed); const smallLength = pack.rivers.map(r => r.length||0).sort((a,b) => a-b)[Math.ceil(pack.rivers.length * .15)]; const smallType = {"Creek":9, "River":3, "Brook":3, "Stream":1}; // weighted small river types diff --git a/modules/ui/layers.js b/modules/ui/layers.js index 1018e2b6..8cf4a2c4 100644 --- a/modules/ui/layers.js +++ b/modules/ui/layers.js @@ -475,7 +475,7 @@ function toggleIce(event) { function drawIce() { const cells = grid.cells, vertices = grid.vertices, n = cells.i.length, temp = cells.temp, h = cells.h; const used = new Uint8Array(cells.i.length); - Math.seedrandom(seed); + Math.random = aleaPRNG(seed); const shieldMin = -6; // max temp to form ice shield (glacier) const icebergMax = 2; // max temp to form an iceberg diff --git a/modules/ui/options.js b/modules/ui/options.js index 9efbfaa8..50473d62 100644 --- a/modules/ui/options.js +++ b/modules/ui/options.js @@ -389,7 +389,7 @@ function applyStoredOptions() { // randomize options if randomization is allowed (not locked or options='default') function randomizeOptions() { - Math.seedrandom(seed); // reset seed to initial one + Math.random = aleaPRNG(seed); // reset seed to initial one const randomize = new URL(window.location.href).searchParams.get("options") === "default"; // ignore stored options // 'Options' settings diff --git a/modules/ui/tools.js b/modules/ui/tools.js index 6c648024..d41fbc91 100644 --- a/modules/ui/tools.js +++ b/modules/ui/tools.js @@ -97,7 +97,8 @@ function recalculatePopulation() { } function regenerateStates() { - Math.seedrandom(Math.floor(Math.random() * 1e9)); // new random seed + const localSeed = Math.floor(Math.random() * 1e9); // new random seed + Math.random = aleaPRNG(localSeed); const burgs = pack.burgs.filter(b => b.i && !b.removed); if (!burgs.length) { tip("No burgs to generate states. Please create burgs first", false, "error");