Hacker News new | ask | show | jobs
by bytex64 5303 days ago
If you're curious, the "readable" version is here: http://bytex64.net/code/datasnake/snake.html

I started out writing it as straightforward as possible, then applied functional tricks to slim it down. That was a lot of fun. I'm not sure how to post a code snippet here, but I'll try to illustrate one of my favorite portions.

In the original, I did key input with a switch statement. That got replaced by:

    { 37: P(-1,0), 38: P(0,-1), 39: P(1,0), 40: P(0,1) }[e.keyCode]
"But wait!" you're thinking, "What happens when e.keyCode is less than 37 or more than 40?" What happens is it evaluates to undefined, and it errors out in the M() function, effectively short-circuiting it. If you look in your browser's error log, it'll spew an error every time you hit another key. It's lazy, but it works. :]
2 comments

I think you have an extra two bytes (or a bug) here:

function blocks(l) { s.map(function(p) { c.fillRect(p.x << 3, p.y << 3, 8, 8); }); }

l is ignored, so you can remove it (and the part where you pass it in from the engine). This code still works because s has global scope, but that looks like an accident.

I guess the "right" thing to do would be to rename s to l here, but when you're trying to fit stuff into 4K that's not the main concern :)

Cool program by the way, I'm impressed with how clear the code remained.

Yep, that was an accident. I've removed the parameter entirely. Nice catch!
Little bug fix, apples can appear under the snake..

   --- snake.html	2011-12-09 08:03:47.000000000 +0000
   +++ snake.html.2	2011-12-09 11:40:54.414774460 +0000
   @@ -59,7 +59,7 @@
   	var n = AP(s[0],d);
   	(OB(n) || TC(n)) && fail();
   	s.unshift(n);
   -	EQ(s[0],a) && (a = RP()) || s.pop();
   +	EQ(s[0],a) && (function() {do {a = RP()} while (TC(a))}()) || s.pop();

   	c.clearRect(0,0,128,128);
   	blocks(s);
Whoops, I see someone below beat me to it.