Created
April 20, 2015 16:58
-
-
Save wavebeem/ca85f8a70e4701e7a476 to your computer and use it in GitHub Desktop.
99% mutation free, organic, non-GMO
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var freeze = Object.freeze; | |
function array() { | |
return freeze([].slice.call(arguments)); | |
} | |
function array_of_size(n) { | |
var xs = []; | |
while (n-- > 0) { | |
xs.push(null); | |
} | |
return freeze(xs); | |
} | |
function unary(f) { | |
return function(x) { | |
return f(x); | |
} | |
} | |
function binary(f) { | |
return function(x, y) { | |
return f(x, y); | |
} | |
} | |
function map(f, xs) { | |
return freeze(xs.map(unary(f))); | |
} | |
function mapi(f, xs) { | |
return freeze(xs.map(binary(f))); | |
} | |
var tiles = object( | |
'floor', '.', | |
'player', '@' | |
); | |
function K(k) { | |
return () => k; | |
} | |
function empty_matrix_2d(w, h) { | |
return map(function() { | |
return map(K(null), array_of_size(h)); | |
}, array_of_size(w)); | |
} | |
function object() { | |
var n = arguments.length; | |
if (n % 2 !== 0 || n < 2) { | |
throw new Error('object needs >= 2 even number of arguments'); | |
} | |
var o = {}; | |
for (var i = 0; i < n - 1; i += 2) { | |
o[arguments[i]] = arguments[i + 1]; | |
} | |
return freeze(o); | |
} | |
function escaped(c) { | |
return "\x1b[" + c; | |
} | |
var CLEAR = escaped("H") + escaped("2J"); | |
var W = 40; | |
var H = 20; | |
function world_initial() { | |
var w = empty_matrix_2d(H, W); | |
return map(partial(map, K(tiles.floor)), w); | |
} | |
function world_transform(f, w) { | |
return mapi((row, y) => | |
mapi((data, x) => | |
f(data, x, y), | |
row), | |
data); | |
} | |
function world_show(w) { | |
var s = ""; | |
w.forEach(row => { | |
row.forEach(data => { | |
s += data; | |
}); | |
s += "\n"; | |
}); | |
process.stdout.write(s); | |
} | |
function overlay_player(p) { | |
return (data, x, y) => | |
(x === p.x && y === p.y) | |
? tiles.player | |
: data; | |
} | |
function player(x, y) { | |
return object( | |
'x', x, | |
'y', y, | |
'move', (dx, dy) => player(x + dx, y + dy) | |
); | |
} | |
function get(key, fallback, obj) { | |
return key in obj | |
? obj[key] | |
: fallback; | |
} | |
function game_state(the_player, the_world) { | |
return object( | |
'player', the_player, | |
'world', the_world, | |
'tick', key => { | |
var dx = 10 * get(key, 0, { h: -1, l: 1 }); | |
var dy = 10 * get(key, 0, { k: -1, j: 1 }); | |
var new_player = the_player.move(dx, dy); | |
return game_state(new_player, the_world); | |
} | |
); | |
} | |
function partial(f) { | |
var args = [].slice.call(arguments, 1); | |
return f.bind.apply(f, [null].concat(args)); | |
} | |
function translate(x, y) { | |
x += 'px'; | |
y += 'px'; | |
return 'translate(' + [x, y] + ')'; | |
} | |
var GameView = React.createClass({ | |
getInitialState() { | |
return game_state(player(0, 0), world_initial()); | |
}, | |
render() { | |
return <div className="game"> | |
<PlayerView player={this.state.player} /> | |
</div>; | |
} | |
}); | |
var PlayerView = React.createClass({ | |
render() { | |
var p = this.props.player; | |
var style = { transform: translate(p.x, p.y) }; | |
return <div className="player" style={style} />; | |
} | |
}); | |
var the_root = React.render( | |
<GameView />, | |
document.getElementById('react') | |
); | |
setInterval(() => { | |
the_root.setState(the_root.state.tick('j')); | |
}, 300); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment