"use strict"; var patterns = { 'gospelgun': { x: 36, rle: "24bo11b22bobo11b12b2o6b2o12b2o11bo3bo4b2o12b2o2o8bo5bo3b2o14b2o8bo3bob2o4bobo11b10bo5bo7bo11b11bo3bo20b12b2o22b" }, 'diamond': { x: 12, rle: '4b4o4b12b2b8o2b12b12o12b2b8o2b12b4b4o4b' }, 'flammenkamp': { x: 13, rle: '7b2o4b7bobo3b2bo4bob2o2bb2o5bo4bo2bo9b3o10b23b3o9bo2bo4bo5b2ob2b2obo4bo2b3bobo7b4b2o7b' }, 'c2ship': { x: 13, rle: '1o12b4o9b2b2o9b5b1o7b6o7b6b1o1b1o4bobob6o3bob2o5b2o2b4b2o4b2ob5o4b2o2b13b5o4b2o2b4b2o4b2obob2o5b2o2bobob6o3b6b1o1b1o4b6o7b5b1o7b2b2o9b4o9bo12b' } }; function curry(fn) { return function(...args) { if(fn.length > args.length) { var arg = args; return function(...args) {return fn.apply(null, arg.concat(args));}; } return fn.apply(null, args); }; } function compose(f,g) { return function(x) { return f(g(x)); }; } function pipe(...fns) { return fns.reduce(compose); } var getEle = curry(function(ele) { return (document.querySelectorAll(ele).length === 1) ? document.querySelector(ele) : [...document.querySelectorAll(ele)]; }); var map = curry(function(fn,arr) { return Array.prototype.map.call(arr, fn); }); var get = curry(function(what,x) { return x[what]; }); var forEach = curry(function(fn,arr) { return Array.prototype.forEach.call(arr, fn); }); var log = function(x) { console.log(x); return x; }; var calcRules = function(ele, index, arr) { var gridLength = Math.sqrt(arr.length); var r = Math.floor(index/gridLength); var neighbours = arr[(index-1+arr.length)%arr.length]+ arr[(index - gridLength+arr.length)%arr.length]+ arr[(index + gridLength+arr.length)%arr.length]+ arr[(index+1+arr.length)%arr.length]+ arr[(index - gridLength - 1+arr.length)%arr.length]+ arr[(index - gridLength + 1+arr.length)%arr.length]+ arr[(index + gridLength - 1+arr.length)%arr.length]+ arr[(index + gridLength + 1+arr.length)%arr.length]; if((ele === 1 && neighbours < 2) || (ele === 1 && neighbours > 3)) { return 0; } if((ele === 1 && neighbours === 2) || (ele === 1 && neighbours === 3)) { return 1; } if(ele === 0 && neighbours === 3) { return 1; } else { return ele; } }; var getCanvas = curry(function(type, id) { return HTMLCanvasElement.prototype.getContext.call(getEle(id), type); }); var draw = curry(function(ctx, arr) { ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height); forEach((ele, index)=>{ if(ele === 1) { var gridLength = Math.sqrt(arr.length); var r = Math.floor(index/gridLength); ctx.fillStyle = "#000000"; ctx.fillRect(index%gridLength*ctx.canvas.width/gridLength+0.5, r*ctx.canvas.height/gridLength+0.5, ctx.canvas.width/gridLength-0.5, ctx.canvas.height/gridLength-0.5); ctx.fillStyle = "#cccccc"; ctx.fillRect(index%gridLength*ctx.canvas.width/gridLength+1.0, r*ctx.canvas.height/gridLength+1.0, ctx.canvas.width/gridLength-1.0, ctx.canvas.height/gridLength-1.0); } },arr); var fps = setTimeout(()=>{ clearTimeout(fps); newState(arr); },1000/60); }); var decodeRLE = function(str) { return str.replace(/(\d+)(\w)/g, function(m,n,c){ return new Array( parseInt(n,10)+1 ).join(c); }); }; var arrayPattern = function(ele) { return ele==="b"?0:1; }; var generateGrid = function(initPattern) { //var size = 512; var size = 256; var grid = []; while(grid.length < size*size) { if(initPattern.length && grid.length%size === (size/2) - Math.ceil(initPattern[0].length/2) && grid.length/size > (size/2) - Math.ceil(initPattern.length/2)) { grid.push(...initPattern.shift()); } else { grid.push(0); } } return grid; }; var rleArray = compose(map(arrayPattern), decodeRLE); var to2dArr = function(pattern) { var arr = rleArray(patterns[pattern].rle); var result = []; var chunk = patterns[pattern].x; while(arr.length !== 0) { result.push(arr.splice(0, chunk)); } return result; }; var newState = compose(draw(getCanvas('2d', '#board')), map(calcRules)); var setInitGrid = compose(generateGrid, to2dArr); var render = compose(newState, setInitGrid); render('gospelgun'); //render('diamond'); //render('flammenkamp'); //render('c2ship');