ca/fp-rle/ca-fp.js

191 lines
4.3 KiB
JavaScript

"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');