UNPKG

ts-hashlife

Version:

Efficient TypeScript implementation of HashLife, an optimized algorithm for simulating Conway's Game of Life with memoization and quadtree-based compression.

10 lines (9 loc) 27.4 kB
"use strict";var HashLife=(()=>{var S=Object.defineProperty,ee=Object.defineProperties,te=Object.getOwnPropertyDescriptor,ie=Object.getOwnPropertyDescriptors,re=Object.getOwnPropertyNames,$=Object.getOwnPropertySymbols;var B=Object.prototype.hasOwnProperty,se=Object.prototype.propertyIsEnumerable;var W=a=>{throw TypeError(a)};var K=(a,e,t)=>e in a?S(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,y=(a,e)=>{for(var t in e||(e={}))B.call(e,t)&&K(a,t,e[t]);if($)for(var t of $(e))se.call(e,t)&&K(a,t,e[t]);return a},R=(a,e)=>ee(a,ie(e));var ne=(a,e)=>{for(var t in e)S(a,t,{get:e[t],enumerable:!0})},oe=(a,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of re(e))!B.call(a,r)&&r!==t&&S(a,r,{get:()=>e[r],enumerable:!(i=te(e,r))||i.enumerable});return a};var ae=a=>oe(S({},"__esModule",{value:!0}),a);var j=(a,e,t)=>e.has(a)||W("Cannot "+t);var g=(a,e,t)=>(j(a,e,"read from private field"),t?t.call(a):e.get(a)),Z=(a,e,t)=>e.has(a)?W("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(a):e.set(a,t),G=(a,e,t,i)=>(j(a,e,"write to private field"),i?i.call(a,t):e.set(a,t),t);var Me={};ne(Me,{EventBus:()=>m,HashLife:()=>D,default:()=>Ne});var w,q=class{constructor(){Z(this,w,{})}emit(e,t){if(!g(this,w)[e])return;(g(this,w)[e]||[]).forEach(r=>r(t))}on(e,t){return g(this,w)[e]||(g(this,w)[e]=[]),g(this,w)[e].push(t),()=>this.off(e,t)}off(e,t){if(!g(this,w)[e])return;let i=g(this,w)[e].filter(r=>r!==t);g(this,w)[e]=i}clear(e){e?g(this,w)[e]=[]:G(this,w,{})}};w=new WeakMap;var he=new q,m=he;var X=.9,le=16,_e=24,I=1,k=2,A=4,E=8,v=class{constructor(e,t,i,r,s,n,o){this.nw=e||null,this.ne=t||null,this.sw=i||null,this.se=r||null,this.id=s,n!==void 0&&o!==void 0?(this.level=n,this.population=o):e!==null&&e.level!==void 0?(this.level=e.level+1,this.population=(e.population||0)+(t.population||0)+(i.population||0)+(r.population||0)):(this.level=0,this.population=0),this.cache=null,this.quick_cache=null,this.hashmap_next=void 0}},T=class{constructor(){this._step=0;this._generation=0;this.last_id=0,this.hashmap_size=0,this.max_load=0,this.hashmap=[],this.empty_tree_cache=[],this.level2_cache=[],this._powers=new Float64Array(1024),this._powers[0]=1;for(let e=1;e<1024;e++)this._powers[e]=this._powers[e-1]*2;this._bitcounts=new Int8Array(1880),this._bitcounts.set([0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4]);for(let e=16;e<1880;e++)this._bitcounts[e]=this._bitcounts[e&15]+this._bitcounts[e>>4&15]+this._bitcounts[e>>8];this.rule_b=8,this.rule_s=12,this.root=null,this.rewind_state=null,this.step=0,this.generation=0,this.false_leaf=new v(null,null,null,null,3,0,0),this.true_leaf=new v(null,null,null,null,2,0,1),this.clear_pattern()}get step(){return this._step}set step(e){this._step=e,m.emit("step",Math.pow(2,e))}get generation(){return this._generation}set generation(e){this._generation=e,m.emit("generation",e)}pow2(e){return e>=1024?1/0:this._powers[e]}save_rewind_state(){this.rewind_state=this.root}restore_rewind_state(){this.generation=0,this.root=this.rewind_state,this.garbage_collect()}eval_mask(e){return(e&32?this.rule_s:this.rule_b)>>this._bitcounts[e&1879]&1}level1_create(e){return this.create_tree(e&1?this.true_leaf:this.false_leaf,e&2?this.true_leaf:this.false_leaf,e&4?this.true_leaf:this.false_leaf,e&8?this.true_leaf:this.false_leaf)}set_bit(e,t,i){let r=this.get_level_from_bounds({x:e,y:t});if(this.root===null&&(this.root=this.empty_tree(r)),i)for(;r>this.root.level;)this.root=this.expand_universe(this.root);else if(r>this.root.level)return;this.root=this.node_set_bit(this.root,e,t,i)}get_bit(e,t){let i=this.get_level_from_bounds({x:e,y:t});return this.root===null||i>this.root.level?!1:this.node_get_bit(this.root,e,t)}get_root_bounds(){if(this.root===null||this.root.population===0)return{top:0,left:0,bottom:0,right:0};let e={top:1/0,left:1/0,bottom:-1/0,right:-1/0},t=this.pow2(this.root.level-1);return this.node_get_boundary(this.root,-t,-t,k|I|E|A,e),e}empty_tree(e){if(this.empty_tree_cache[e])return this.empty_tree_cache[e];let t;return e===1?t=this.false_leaf:t=this.empty_tree(e-1),this.empty_tree_cache[e]=this.create_tree(t,t,t,t)}expand_universe(e){let t=this.empty_tree(e.level-1);return this.create_tree(this.create_tree(t,t,t,e.nw),this.create_tree(t,t,e.ne,t),this.create_tree(t,e.sw,t,t),this.create_tree(e.se,t,t,t))}uncache(e){for(let t=0;t<=this.hashmap_size;t++){let i=this.hashmap[t];i!==void 0&&(i.cache=null,i.hashmap_next=void 0,e&&(i.quick_cache=null))}}in_hashmap(e){let t=this.calc_hash(e.nw.id,e.ne.id,e.sw.id,e.se.id)&this.hashmap_size,i=this.hashmap[t];for(;;){if(i===void 0)return!1;if(i===e)return!0;i=i.hashmap_next}}hashmap_insert(e){let t=this.calc_hash(e.nw.id,e.ne.id,e.sw.id,e.se.id)&this.hashmap_size,i=this.hashmap[t],r;for(;;){if(i===void 0){r!==void 0?r.hashmap_next=e:this.hashmap[t]=e;return}r=i,i=i.hashmap_next}}create_tree(e,t,i,r){let s=this.calc_hash(e.id,t.id,i.id,r.id)&this.hashmap_size,n=this.hashmap[s],o;for(;;){if(n===void 0){if(this.last_id>this.max_load)return this.garbage_collect(),this.create_tree(e,t,i,r);let h=new v(e,t,i,r,this.last_id++);return o!==void 0?o.hashmap_next=h:this.hashmap[s]=h,h}else if(n.nw===e&&n.ne===t&&n.sw===i&&n.se===r)return n;o=n,n=n.hashmap_next}}next_generation(e){let t=this.root;for(;e&&t.level<=this.step+2||t.nw.population!==t.nw.se.se.population||t.ne.population!==t.ne.sw.sw.population||t.sw.population!==t.sw.ne.ne.population||t.se.population!==t.se.nw.nw.population;)t=this.expand_universe(t);e?(this.generation+=this.pow2(this.step),t=this.node_next_generation(t)):(this.generation+=this.pow2(this.root.level-2),t=this.node_quick_next_generation(t)),this.root=t}garbage_collect(){this.hashmap_size<(1<<_e)-1&&(this.hashmap_size=this.hashmap_size<<1|1,this.hashmap=[]),this.max_load=this.hashmap_size*X|0;for(let e=0;e<=this.hashmap_size;e++)this.hashmap[e]=void 0;this.last_id=4,this.node_hash(this.root)}calc_hash(e,t,i,r){return(e*23^t)*23^i*23^r}clear_pattern(){this.last_id=4,this.hashmap_size=(1<<le)-1,this.max_load=this.hashmap_size*X|0,this.hashmap=[],this.empty_tree_cache=[],this.level2_cache=Array(65536);for(let e=0;e<=this.hashmap_size;e++)this.hashmap[e]=void 0;this.root=this.empty_tree(3),this.generation=0}get_bounds(e,t){if(!e.length)return{top:0,left:0,bottom:0,right:0};let i={top:t[0],left:e[0],bottom:t[0],right:e[0]},r=e.length;for(let s=1;s<r;s++){let n=e[s],o=t[s];n<i.left?i.left=n:n>i.right&&(i.right=n),o<i.top?i.top=o:o>i.bottom&&(i.bottom=o)}return i}get_level_from_bounds(e){let t=4,i=Object.keys(e);for(let r=0;r<i.length;r++){let s=e[i[r]];s+1>t?t=s+1:-s>t&&(t=-s)}return Math.ceil(Math.log(t)/Math.LN2)+1}make_center(e,t,i){let r=Math.round((i.left-i.right)/2)-i.left,s=Math.round((i.top-i.bottom)/2)-i.top;this.move_field(e,t,r,s),i.left+=r,i.right+=r,i.top+=s,i.bottom+=s}move_field(e,t,i,r){let s=e.length;for(let n=0;n<s;n++)e[n]+=i,t[n]+=r}setup_field(e,t,i){i===void 0&&(i=this.get_bounds(e,t));let r=this.get_level_from_bounds(i),s=this.pow2(r-1),n=e.length;this.move_field(e,t,s,s),this.root=this.setup_field_recurse(0,n-1,e,t,r)}partition(e,t,i,r,s){let n=e,o=t,h;for(;n<=o;){for(;n<=t&&(i[n]&s)===0;)n++;for(;o>e&&i[o]&s;)o--;if(n>=o)break;h=i[n],i[n]=i[o],i[o]=h,h=r[n],r[n]=r[o],r[o]=h,n++,o--}return n}setup_field_recurse(e,t,i,r,s){if(e>t)return this.empty_tree(s);if(s===2)return this.level2_setup(e,t,i,r);s--;let n=1<<s,o=this.partition(e,t,r,i,n),h=this.partition(e,o-1,i,r,n),l=this.partition(o,t,i,r,n);return this.create_tree(this.setup_field_recurse(e,h-1,i,r,s),this.setup_field_recurse(h,o-1,i,r,s),this.setup_field_recurse(o,l-1,i,r,s),this.setup_field_recurse(l,t,i,r,s))}level2_setup(e,t,i,r){let s=0,n,o;for(let h=e;h<=t;h++)n=i[h],o=r[h],s|=1<<(n&1|(o&1|n&2)<<1|(o&2)<<2);return this.level2_cache[s]?this.level2_cache[s]:this.level2_cache[s]=this.create_tree(this.level1_create(s),this.level1_create(s>>4),this.level1_create(s>>8),this.level1_create(s>>12))}set_step(e){e!==this.step&&(this.step=e,this.uncache(!1),this.empty_tree_cache=[],this.level2_cache=Array(65536))}set_rules(e,t){(this.rule_s!==e||this.rule_b!==t)&&(this.rule_s=e,this.rule_b=t,this.uncache(!0),this.empty_tree_cache=[],this.level2_cache=Array(65536))}node_set_bit(e,t,i,r){if(e.level===0)return r?this.true_leaf:this.false_leaf;let s=e.level===1?0:this.pow2(e.level-2),n=e.nw,o=e.ne,h=e.sw,l=e.se;return t<0?i<0?n=this.node_set_bit(n,t+s,i+s,r):h=this.node_set_bit(h,t+s,i-s,r):i<0?o=this.node_set_bit(o,t-s,i+s,r):l=this.node_set_bit(l,t-s,i-s,r),this.create_tree(n,o,h,l)}node_get_bit(e,t,i){if(e.population===0)return!1;if(e.level===0)return!0;let r=e.level===1?0:this.pow2(e.level-2);return t<0?i<0?this.node_get_bit(e.nw,t+r,i+r):this.node_get_bit(e.sw,t+r,i-r):i<0?this.node_get_bit(e.ne,t-r,i+r):this.node_get_bit(e.se,t-r,i-r)}node_get_field(e,t,i,r){if(e.population!==0)if(e.level===0)r.push({x:t,y:i});else{let s=this.pow2(e.level-1);this.node_get_field(e.nw,t,i,r),this.node_get_field(e.sw,t,i+s,r),this.node_get_field(e.ne,t+s,i,r),this.node_get_field(e.se,t+s,i+s,r)}}node_level2_next(e){let t=e.nw,i=e.ne,r=e.sw,s=e.se,n=t.nw.population<<15|t.ne.population<<14|i.nw.population<<13|i.ne.population<<12|t.sw.population<<11|t.se.population<<10|i.sw.population<<9|i.se.population<<8|r.nw.population<<7|r.ne.population<<6|s.nw.population<<5|s.ne.population<<4|r.sw.population<<3|r.se.population<<2|s.sw.population<<1|s.se.population;return this.level1_create(this.eval_mask(n>>5)|this.eval_mask(n>>4)<<1|this.eval_mask(n>>1)<<2|this.eval_mask(n)<<3)}node_next_generation(e){if(e.cache)return e.cache;if(this.step===e.level-2)return this.node_quick_next_generation(e);if(e.level===2)return e.quick_cache?e.quick_cache:e.quick_cache=this.node_level2_next(e);let t=e.nw,i=e.ne,r=e.sw,s=e.se,n=this.create_tree(t.nw.se,t.ne.sw,t.sw.ne,t.se.nw),o=this.create_tree(t.ne.se,i.nw.sw,t.se.ne,i.sw.nw),h=this.create_tree(i.nw.se,i.ne.sw,i.sw.ne,i.se.nw),l=this.create_tree(t.sw.se,t.se.sw,r.nw.ne,r.ne.nw),_=this.create_tree(t.se.se,i.sw.sw,r.ne.ne,s.nw.nw),f=this.create_tree(i.sw.se,i.se.sw,s.nw.ne,s.ne.nw),d=this.create_tree(r.nw.se,r.ne.sw,r.sw.ne,r.se.nw),c=this.create_tree(r.ne.se,s.nw.sw,r.se.ne,s.sw.nw),p=this.create_tree(s.nw.se,s.ne.sw,s.sw.ne,s.se.nw);return e.cache=this.create_tree(this.node_next_generation(this.create_tree(n,o,l,_)),this.node_next_generation(this.create_tree(o,h,_,f)),this.node_next_generation(this.create_tree(l,_,d,c)),this.node_next_generation(this.create_tree(_,f,c,p)))}node_quick_next_generation(e){if(e.quick_cache!==null)return e.quick_cache;if(e.level===2)return e.quick_cache=this.node_level2_next(e);let t=e.nw,i=e.ne,r=e.sw,s=e.se,n=this.node_quick_next_generation(t),o=this.node_quick_next_generation(this.create_tree(t.ne,i.nw,t.se,i.sw)),h=this.node_quick_next_generation(i),l=this.node_quick_next_generation(this.create_tree(t.sw,t.se,r.nw,r.ne)),_=this.node_quick_next_generation(this.create_tree(t.se,i.sw,r.ne,s.nw)),f=this.node_quick_next_generation(this.create_tree(i.sw,i.se,s.nw,s.ne)),d=this.node_quick_next_generation(r),c=this.node_quick_next_generation(this.create_tree(r.ne,s.nw,r.se,s.sw)),p=this.node_quick_next_generation(s);return e.quick_cache=this.create_tree(this.node_quick_next_generation(this.create_tree(n,o,l,_)),this.node_quick_next_generation(this.create_tree(o,h,_,f)),this.node_quick_next_generation(this.create_tree(l,_,d,c)),this.node_quick_next_generation(this.create_tree(_,f,c,p)))}node_hash(e){this.in_hashmap(e)||(e.id=this.last_id++,e.hashmap_next=void 0,e.level>1&&(this.node_hash(e.nw),this.node_hash(e.ne),this.node_hash(e.sw),this.node_hash(e.se),e.cache&&this.node_hash(e.cache),e.quick_cache&&this.node_hash(e.quick_cache)),this.hashmap_insert(e))}node_get_boundary(e,t,i,r,s){if(!(e.population===0||!r))if(e.level===0)t<s.left&&(s.left=t),t>s.right&&(s.right=t),i<s.top&&(s.top=i),i>s.bottom&&(s.bottom=i);else{let n=this.pow2(e.level-1);if(t>=s.left&&t+n*2<=s.right&&i>=s.top&&i+n*2<=s.bottom)return;let o=r,h=r,l=r,_=r;e.nw.population&&(h&=~k,l&=~I,_&=~k&~I),e.sw.population&&(_&=~I,o&=~E,l&=~E&~I),e.ne.population&&(o&=~A,_&=~k,h&=~k&~A),e.se.population&&(h&=~A,l&=~E,o&=~E&~A),this.node_get_boundary(e.nw,t,i,o,s),this.node_get_boundary(e.sw,t,i+n,h,s),this.node_get_boundary(e.ne,t+n,i,l,s),this.node_get_boundary(e.se,t+n,i+n,_,s)}}};var L=(a,e,t)=>Math.min(t,Math.max(e,a)),N=class{constructor(){this.pixel_ratio=1;this.canvas_width=0;this.canvas_height=0;this._canvas_offset_x=0;this._canvas_offset_y=0;this._cell_width=0;this._default_cell_width=0;this.border_width=0;this.background_color=null;this.cell_color=null;this.set_cell_width=e=>{let t=L(e,.01,500);return t===this.cell_width?!1:(this.cell_width=t,!0)}}get default_cell_width(){return this._default_cell_width}set default_cell_width(e){this._default_cell_width=e}get canvas_offset_x(){return this._canvas_offset_x}set canvas_offset_x(e){this._canvas_offset_x=e,m.emit("pan:x",e.toFixed(0))}get canvas_offset_y(){return this._canvas_offset_y}set canvas_offset_y(e){this._canvas_offset_y=e,m.emit("pan:y",e.toFixed(0))}get cell_width(){return this._cell_width}set cell_width(e){this._cell_width=e,this.border_width=Math.floor((e-5)/5)+1;let t=e/this._default_cell_width;m.emit("zoom",t>=1?`1:${Math.round(t)}`:`${Math.round(1/t)}:1`)}init(e){return this.canvas=e,e!=null&&e.getContext?(this.context=this.canvas.getContext("2d"),document.body.style.overscrollBehavior="none",!0):!1}set_size(e,t){if(e!==this.canvas_width||t!==this.canvas_height){let i=window.devicePixelRatio||1;this.pixel_ratio=i,this.canvas.width=Math.round(e*i),this.canvas.height=Math.round(t*i),this.canvas.style.width=`${e}px`,this.canvas.style.height=`${t}px`,this.canvas_width=this.canvas.width,this.canvas_height=this.canvas.height,this.image_data=this.context.createImageData(this.canvas_width,this.canvas_height),this.image_data_data=new Int32Array(this.image_data.data.buffer);for(let r=0;r<e*t;r++)this.image_data_data[r]=255<<24}}draw_node(e,t,i,r){if(e.population===0)return;let s=i+this.canvas_offset_x,n=r+this.canvas_offset_y,o=t;s+o<0||n+o<0||s>=this.canvas_width||n>=this.canvas_height||(e.level===0||o<=1?e.population&&this.fill_square(s,n,o):(t/=2,this.draw_node(e.nw,t,i,r),this.draw_node(e.ne,t,i+t,r),this.draw_node(e.sw,t,i,r+t),this.draw_node(e.se,t,i+t,r+t)))}fill_square(e,t,i){e=Math.round(e),t=Math.round(t),i=Math.round(i);let r=i-this.border_width,s=r;if(e<0&&(r+=e,e=0),e+r>this.canvas_width&&(r=this.canvas_width-e),t<0&&(s+=t,t=0),t+s>this.canvas_height&&(s=this.canvas_height-t),r<=0||s<=0)return;let n=e+t*this.canvas_width,o=this.canvas_width-r,h=this.cell_color_rgb.r|this.cell_color_rgb.g<<8|this.cell_color_rgb.b<<16|255<<24;for(let l=0;l<s;l++){for(let _=0;_<r;_++)this.image_data_data[n]=h,n++;n+=o}}redraw(e){let t=this.color2rgb(this.background_color||"#000"),i=t.r|t.g<<8|t.b<<16|255<<24;this.cell_color_rgb=this.color2rgb(this.cell_color||"#000");let r=this.canvas_width*this.canvas_height;for(let n=0;n<r;n++)this.image_data_data[n]=i;let s=Math.pow(2,e.level-1)*this.cell_width;this.draw_node(e,2*s,-s,-s),this.context.putImageData(this.image_data,0,0),this.cell_width>10&&this.draw_grid_lines()}draw_grid_lines(){let e=this.context;e.strokeStyle=`rgba(180, 180, 180, ${this.cell_width>15?.2:.4})`,e.lineWidth=Math.min((Math.floor((this.cell_width-10)/10)+1)/4,1);let t=this.canvas_offset_x%this.cell_width,i=this.canvas_offset_y%this.cell_width;for(let r=t;r<this.canvas_width;r+=this.cell_width)e.beginPath(),e.moveTo(r-this.border_width/2,0),e.lineTo(r-this.border_width/2,this.canvas_height),e.stroke();for(let r=i;r<this.canvas_height;r+=this.cell_width)e.beginPath(),e.moveTo(0,r-this.border_width/2),e.lineTo(this.canvas_width,r-this.border_width/2),e.stroke()}pan(e,t){this.canvas_offset_x-=e*this.pixel_ratio,this.canvas_offset_y-=t*this.pixel_ratio}center_view(){this.canvas_offset_x=this.canvas_width>>1,this.canvas_offset_y=this.canvas_height>>1}zoom(e,t,i){if(e){if(!this.set_cell_width(this.cell_width/2))return;this.canvas_offset_x-=Math.round((this.canvas_offset_x-t)/2),this.canvas_offset_y-=Math.round((this.canvas_offset_y-i)/2)}else{if(!this.set_cell_width(this.cell_width*2))return;this.canvas_offset_x+=Math.round(this.canvas_offset_x-t),this.canvas_offset_y+=Math.round(this.canvas_offset_y-i)}}zoom_at(e,t,i){let r=this.cell_width;if(!this.set_cell_width(this.cell_width*e))return;let o=this.cell_width/r;this.canvas_offset_x+=(1-o)*(t*this.pixel_ratio-this.canvas_offset_x),this.canvas_offset_y+=(1-o)*(i*this.pixel_ratio-this.canvas_offset_y)}zoom_centered(e){this.zoom(e,this.canvas_width>>1,this.canvas_height>>1)}zoom_to(e){for(;this.cell_width>e;)this.zoom_centered(!0);for(;this.cell_width*2<e;)this.zoom_centered(!1)}fit_bounds(e,t){let i=e.right-e.left,r=e.bottom-e.top,s={right:((t==null?void 0:t.right)||0)*this.pixel_ratio,left:((t==null?void 0:t.left)||0)*this.pixel_ratio,bottom:((t==null?void 0:t.bottom)||0)*this.pixel_ratio,top:((t==null?void 0:t.top)||0)*this.pixel_ratio};if(isFinite(i)&&isFinite(r)){let n=this.canvas_width-(s.left+s.right),o=this.canvas_height-(s.top+s.bottom),h=Math.min(16,n/i,o/r);this.zoom_to(h);let l=s.left+n/2,_=s.top+o/2;this.canvas_offset_x=Math.round(l-(e.left+i/2)*this.cell_width),this.canvas_offset_y=Math.round(_-(e.top+r/2)*this.cell_width)}else{this.zoom_to(16);let n=this.canvas_width-(s.left+s.right),o=this.canvas_height-(s.top+s.bottom);this.canvas_offset_x=s.left+(n>>1),this.canvas_offset_y=s.top+(o>>1)}}pixel2cell(e,t){return{x:Math.floor((e*this.pixel_ratio-this.canvas_offset_x+this.border_width/2)/this.cell_width),y:Math.floor((t*this.pixel_ratio-this.canvas_offset_y+this.border_width/2)/this.cell_width)}}color2rgb(e){return e.length===4?{r:parseInt(e[1]+e[1],16),g:parseInt(e[2]+e[2],16),b:parseInt(e[3]+e[3],16)}:{r:parseInt(e.slice(1,3),16),g:parseInt(e.slice(3,5),16),b:parseInt(e.slice(5,7),16)}}};function Q(a){let e=C(a,"#"),t=0,i=0,r=/([a-zA-Z]+) *= *([a-zA-Z0-9\/()]+)/g,s;a=e.pattern_string;let n=a.indexOf(` `);if(n===-1)return R(y({},e),{error:"RLE Syntax Error: No Header"});for(;s=r.exec(a.substr(0,n));)switch(s[1]){case"x":e.width=Number(s[2]);break;case"y":e.height=Number(s[2]);break;case"rule":e.rule_s=J(s[2],!0),e.rule_b=J(s[2],!1),e.rule=P(e.rule_s,e.rule_b);break;default:return R(y({},e),{error:"RLE Syntax Error: Invalid Header: "+s[1]})}let o=256;if(e.width&&e.height){let M=e.width*e.height;M>0&&(o=Math.max(o,Math.floor(M*.009)),o=Math.min(16777216,o))}let h=1,l=!1,_,f=new Int32Array(o),d=new Int32Array(o),c=0,p=a.length;for(;n<p;n++)if(_=a.charCodeAt(n),_>=48&&_<=57)l?(h*=10,h+=_^48):(h=_^48,l=!0);else{if(_===98)t+=h;else if(_>=65&&_<=90||_>=97&&_<122)for(c+h>f.length&&(f=Y(f),d=Y(d));h--;)f[c]=t++,d[c]=i,c++;else if(_===36)i+=h,t=0;else if(_===33)break;h=1,l=!1}return e.field_x=new Int32Array(f.buffer,0,c),e.field_y=new Int32Array(d.buffer,0,c),e}function Y(a){let e=new Int32Array(Math.floor(a.length*1.5));return e.set(a),e}function C(a,e){let t={comment:"",urls:[]},i,r,s=e==="#";for(;a[0]===e;){if(i=a.indexOf(` `),i===-1&&(i=a.length),r=a.substring(1,i).trim(),s&&a.length>1){let n=a[1];if(n==="N")t.title=r.substring(1).trim();else if(n==="O")t.author=r.substring(1).trim();else if(n==="R")t.rule=r.substring(1).trim();else if(n==="C"){let o=r.substring(1).trim();if(/^(?:https?:\/\/|www\.)[a-z0-9]/i.test(o)){let h=o;h.substring(0,4)!=="http"&&(h="http://"+h),t.urls.push(h)}else t.comment+=o+` `}}a=a.substring(i+1)}return t.pattern_string=a,t.comment=t.comment.trim(),t}function J(a,e){let t=a.split("/");return t[1]?Number(t[0])?F(t.join("/"),e):(t[0][0].toLowerCase()==="b"&&t.reverse(),F(t[0].substr(1)+"/"+t[1].substr(1),e)):0}function F(a,e){let t=0,i=a.split("/")[e?0:1];for(let r of i){let s=Number(r);if(isNaN(s)||t&1<<s)return 0;t|=1<<s}return t}function P(a,e){let t="";for(let i=0;a;a>>=1,i++)a&1&&(t+=i);t+="/";for(let i=0;e;e>>=1,i++)e&1&&(t+=i);return t}function ue(a,e){let i=P(a,e).split("/");return`B${i[1]}/S${i[0]}`}function*ce(a,e){function t(i,r){return i===0?"":(i>1?String(i):"")+(r?"b":"o")}for(let i=e.top;i<=e.bottom;i++){let r=!0,s=e.left;for(let n=e.left;n<=e.right;n++){let o=!a.get_bit(n,i),h=n-s;r!==o&&(yield t(h,r),s=n,r=o)}if(!r){let n=e.right+1-s;yield t(n,r)}i!==e.bottom&&(yield"$")}yield"!"}function fe(a,e,t){let i=[];if(e){let _=e.replace(/\.(rle|lif)$/i,"");i.push("#N "+_)}t.forEach(_=>i.push("#C "+_));let s=a.get_root_bounds(),n=s.right-s.left+1,o=s.bottom-s.top+1,h=ue(a.rule_s,a.rule_b);i.push(`x = ${n}, y = ${o}, rule = ${h}`);let l="";for(let _ of ce(a,s))l.length+_.length>70&&(i.push(l),l=""),l+=_;return i.push(l),i.join(` `)}function me(a){return a=a.replace(/\r/g,""),a[0]==="!"?de(a):/^(?:#[^\n]*\n)*\n*(?:(?:x|y|rule|color|alpha) *= *[a-z0-9\/(),]+,? *)+\s*\n/i.test(a)?Q(a):a.substr(0,10)==="#Life 1.06"?pe(a):{error:"Format detection failed."}}function de(a){let e=C(a,"!");a=e.pattern_string;let t=[],i=[],r=0,s=0,n=a.length;for(let o=0;o<n;o++)switch(a[o]){case".":r++;break;case"O":t.push(r++),i.push(s);break;case` `:s++,r=0;break;case"\r":case" ":break;default:return{error:"Plaintext: Syntax Error"}}return e.field_x=t,e.field_y=i,e}function pe(a){let e=/\s*(-?\d+)\s+(-?\d+)\s*(?:\n|$)/g,t=[],i=[],r;for(;r=e.exec(a);)t.push(Number(r[1])),i.push(Number(r[2]));return{field_x:t,field_y:i}}var x={parse_rle:Q,parse_pattern:me,rule2str:P,parse_rule:F,parse_comments:C,generate_rle:fe};function z(a,e){let t=e.split(` `);if(!t[0].startsWith("[M2]"))return;let i=0;for(let s=1;s<t.length;s++)if(t[s][0]!=="#"){i=s;break}if(!i)return;let r=[];r[0]=void 0;for(let s=i;s<t.length;s++){let n=t[s],o=n[0];if(o==="$"||o==="."||o==="*"){let h=[],l=[],_=0,f=0;for(let c=0;c<n.length;c++){let p=n[c];p==="$"?(_=0,f++,console.assert(f<=8,"x")):p==="."?(_++,console.assert(_<=8,"y")):p==="*"?(h.push(_),l.push(f),_++):p==="\r"||console.assert(!1,"Unexpected piece: '"+p+"'")}let d=a.setup_field_recurse(0,h.length-1,h,l,3);r.push(d)}else if(n!==""){let h=n.split(" ");console.assert(h.length===5,"length");let l=+h[0],_=+h[1],f=+h[2],d=+h[3],c=+h[4];console.assert(l>=4),console.assert(_>=0),console.assert(f>=0),console.assert(d>=0),console.assert(c>=0);let p=_===0?a.empty_tree(l-1):r[_],M=f===0?a.empty_tree(l-1):r[f],H=d===0?a.empty_tree(l-1):r[d],O=c===0?a.empty_tree(l-1):r[c];console.assert(p.level===l-1),console.assert(p),console.assert(M),console.assert(H),console.assert(O);let V=a.create_tree(p,M,H,O);r.push(V)}}return a.root=r[r.length-1],x.parse_comments(e.substr(e.indexOf(` `)+1),"#")}var b=new N,u=new T,be=2,we=10,ge="#f48c06",ve="#000814",xe=60,ye="/patterns",U=class{constructor(e={}){this._running=!1;this.onStop=null;this.pattern=null;this.handleStart=()=>{if(this.running)return;let e=0,t=Date.now(),i=1e3/this.max_fps,r=i,s=t-r;this.running=!0,u.generation===0&&u.save_rewind_state();let n=null;n=setInterval(()=>{m.emit("fps",(1e3/i).toFixed(1))},666);let o=()=>{var l;if(!this.running){n&&clearInterval(n),m.emit("fps","00.0"),this.onStop&&(this.onStop(),this.onStop=null);return}let h=Date.now();r*e<h-t&&(u.next_generation(!0),b.redraw(u.root),(l=u.root)!=null&&l.population&&u.root.population>0&&m.emit("population",u.root.population),e++,i+=(-s-i+(s=h))/15,i<.7*r&&(e=1,t=Date.now())),window.requestAnimationFrame(o)};o()};this.handleStop=e=>{this.running?(this.running=!1,e&&(this.onStop=e)):e&&e()};this.handleToggle=e=>{this.running?this.handleStop(e):this.handleStart()};this.handleReset=()=>{u.rewind_state&&this.handleStop(()=>{u.restore_rewind_state(),this.fit_pattern(),b.redraw(u.root)})};this.handleStep=()=>{this.step(!0)};this.handleSpeedUp=()=>{u.set_step(u.step+1)};this.handleSlowDown=()=>{u.step<=0||u.set_step(u.step-1)};this.handleFitPattern=()=>{this.fit_pattern(),this.lazy_redraw(u.root)};this.handleExport=(e="Untitled")=>{var t,i;return x.generate_rle(u,(i=(t=this.pattern)==null?void 0:t.title)!=null?i:e,["Generated by ts-hashlife"])};this.handleLoadExampleFromFile=({pattern_text:e,pattern_id:t,pattern_path:i,title:r})=>{let s=e.startsWith("[M2]"),n;if(s)n={comment:"",urls:[]};else{let o=x.parse_pattern(e.trim());if(o.error)throw new Error(o.error);n=o}this.handleStop(()=>{var h;if(u.clear_pattern(),s){let l=z(u,e);if(!l)throw new Error("Failed to load macrocell");n=l,u.set_step(15)}else{let l=u.get_bounds(n.field_x,n.field_y);u.make_center(n.field_x,n.field_y,l),u.setup_field(n.field_x,n.field_y,l)}u.save_rewind_state(),n.rule_s&&n.rule_b?u.set_rules(n.rule_s,n.rule_b):u.set_rules(12,8),this.fit_pattern(),b.redraw(u.root),(h=u.root)!=null&&h.population&&m.emit("population",u.root.population),t&&!n.title&&(n.title=t);let o={title:n.title||r||t||"Untitled",author:n.author,rule:n.rule,description:n.comment,source_url:ye+i,view_url:i!=null?i:"",urls:n.urls};this.pattern=o,m.emit("pattern:load",o)})};this.handleLoadRandomizedPattern=({density:e,width:t,height:i})=>{let r=L(e,0,1),s=L(t,100,1e3),n=L(i,100,1e3);this.handleStop(()=>{var d;u.clear_pattern();let o=Math.round(s*n*r),h=new Int32Array(o),l=new Int32Array(o);for(let c=0;c<o;c++)h[c]=Math.floor(Math.random()*s),l[c]=Math.floor(Math.random()*n);let _=u.get_bounds(h,l);u.make_center(h,l,_),u.setup_field(h,l,_),u.save_rewind_state(),this.fit_pattern(),b.redraw(u.root),(d=u.root)!=null&&d.population&&m.emit("population",u.root.population);let f={title:"Random pattern",author:"",rule:"",description:`Randomly generated pattern with density ${r.toFixed(2)}, width ${s}, height ${n}`,source_url:"",view_url:"",urls:[]};this.pattern=f,m.emit("pattern:load",f)})};this.handleWindowResize=()=>{b.set_size(window.innerWidth,document.body.offsetHeight||window.innerHeight),requestAnimationFrame(()=>this.lazy_redraw(u.root))};this.handlePan=(e,t)=>{b.pan(e,t),this.lazy_redraw(u.root)};this.handleZoom=(e,t,i)=>{b.zoom_at(e,t,i),this.lazy_redraw(u.root)};this.handleSetUiPadding=(e={})=>{this.ui_padding=y(y({},this.ui_padding),e),this.fit_pattern()};this.fit_pattern=()=>{let e=u.get_root_bounds();b.fit_bounds({top:e.top,bottom:e.bottom,left:e.left,right:e.right},{top:this.ui_padding.top,bottom:this.ui_padding.bottom,left:this.ui_padding.left,right:this.ui_padding.right})};this.step=(e=!1)=>{var i;let t=Date.now();u.generation===0&&u.save_rewind_state(),u.next_generation(e),b.redraw(u.root),m.emit("fps",(1e3/(Date.now()-t)).toFixed(1)),(i=u.root)!=null&&i.population&&m.emit("population",u.root.population)};this.reset_settings=()=>{b.background_color=this.background_color,b.cell_color=this.cell_color,b.default_cell_width=this.cell_width,b.cell_width=this.cell_width,b.border_width=this.border_width,b.center_view(),u.rule_b=8,u.rule_s=12,u.set_step(0)};this.lazy_redraw=e=>{(!this.running||this.max_fps<15)&&b.redraw(e)};var t,i,r,s,n,o,h,l,_,f,d,c,p;this.max_fps=(t=e.max_fps)!=null?t:xe,this.border_width=(i=e.border_width)!=null?i:be,this.cell_width=(r=e.cell_width)!=null?r:we,this.background_color=(s=e.background_color)!=null?s:ve,this.cell_color=(n=e.cell_color)!=null?n:ge,this.ui_padding={top:(h=(o=e.ui_padding)==null?void 0:o.top)!=null?h:0,right:(_=(l=e.ui_padding)==null?void 0:l.right)!=null?_:0,bottom:(d=(f=e.ui_padding)==null?void 0:f.bottom)!=null?d:0,left:(p=(c=e.ui_padding)==null?void 0:c.left)!=null?p:0}}get running(){return this._running}set running(e){this._running=e,m.emit(e?"start":"stop",e)}handleInit(e){return b.init(e)?(this.handleWindowResize(),this.reset_settings(),!0):!1}},D=U;var Te={EventBus:m,Game:D,LifeUniverse:T,TreeNode:v,LifeCanvasDrawer:N,formats:x,load_macrocell:z};var Ne=Te;return ae(Me);})(); //# sourceMappingURL=hashlife.min.js.map