This is a very simple snake clone, left to turn left, right to turn right, collect the apples. If you hit your tail the game crashes (on purpose) and the score is shown.
I really wanna get it under 280 characters but I'm not sure I can really get it any further, so if you're up for it, I'd love to hear from you about how I can go further :)
265 chars (with a lot of help from remcode and jadelombax!)
d={}u,w,x,y=0,0,4,4 d={}u=0w=0y=4x=4 cls()::_::b=btn()w+=(b%2-b%4\2)/50 x+=1.5*cos(w)y+=sin(w)*1.5if(2<pget(x,y)or u<1)u+=1circ(l,m,2,0)l=rnd(99)m=rnd(99) if(pget(x,y)>1)print(u)() add(d,{x,y,2,u})for e in all(d)do e[4]-=.1pset(unpack(e)) if(e[4]<0)e[3]=1 end circ(l,m,2,3)flip()goto _ |
Property descriptions
d = tail table u = score w = snake direction x = snake x pos y = snake y pos l = apple x m = apple y |
For one line if statements, pico-8 allows a shorter method, by putting the condition in brackets, then and end can be omitted, such that:
if b(x,y)>5 then print(u)_()end |
could be:
if (b(x,y)>5) print(u)_() |
and there are a few other if statements on one line that could also use this.
(Deleted another comment because it was no longer a saving. =/ )
If you can use v, z, and n directly, rather than as variables, you can save a few characters (because the commas increase the amount of characters it takes to use them as variables). I think all 3 of them would benefit from this, but check it (and if you did want them to change, this wouldn't be suitable).
And .02 can be used instead of 0.02
By not using b=pget, but using pget directly you can save a single character. =/
I did try that actually, but it seemed to mess about with the way the drawing works, it seems to be drawing over some of the tail parts early.
I wondered if nilling confused the for loop in a way a del call doesn't?
And another single character with the first line as: d={}a,c,u,w,x,y,l,m=circ,pset,0,0,9,9,9,9
Beyond that, I think you're looking at rejigging how your code works. =/ I'm going to have to leave that to you.
Re: I did try that
Shame that doesn't work; I wasn't sure with that one. Yes, you're probably right about it confusing the for loop. del will remove the element and shift the later items down, which is a nice clean way of doing it.
A few more small savings:
- I think circ doesn't have to be a variable
- l,m=rnd(99),rnd(99) can be
l=rnd(99)m=rnd(99)
- I said one line if, but it doesn't have to start at the start of the line (just, it goes to the end of the line, so use cautiously)
d={}u,w,x,y=0,0,4,4 cls()::_:: if(btn(0))w+=.02 if(btn(1))w-=.02 x+=cos(w)*1.5 y+=sin(w)*1.5if(2<pget(x,y)or u<1)u+=1circ(l,m,2,0)l=rnd(99)m=rnd(99)circ(l,m,2,3) if(pget(x,y)>1)print(u)() for e in all(d)do e[3]-=.1if(e[3]<0)pset(e[1],e[2],1)del(d,e) end pset(x,y,2)add(d,{x,y,u})flip()goto _ |
A long ugly line (taking advantage of the ) after cos(w) to save another character: x+=1.5*cos(w)y+=sin(w)*1.5if(2<pget(x,y)or u<1)u+=1circ(l,m,2,0)l=rnd(99)m=rnd(99)circ(l,m,2,3)
Got it! 278
d={}u,w,x,y=0,0,4,4 cls()::_:: if(btn(0))w+=.02 if(btn(1))w-=.02 x+=1.5*cos(w)y+=sin(w)*1.5if(2<pget(x,y)or u<1)u+=1circ(l,m,2,0)l=rnd(99)m=rnd(99) if(pget(x,y)>1)print(u)() add(d,{x,y,2,u})for e in all(d)do e[4]-=.1pset(unpack(e)) if(e[4]<0)e[3]=1 end circ(l,m,2,3)flip()goto _ |
Incorporated the pset of the head at x and y into the array, dropped the del, a little rearranging, use of unpack while counting on a fourth argument to be ignored.
I'm not sure how robust it is with the omitted del and some of the other changes. =/ But it is sub 280.
How very cool, thank you for your input. I was at about 450 characters yesterday and couldn't imagine getting close.
Cool, that's a neat take on snake, I haven't seen one that actually, well, moves like a snake =).
If you're interested, there's a couple things you can do to cut out a few more characters.
The first is that while declaring variables with commas and a single equals sign saves tokens, it can actually use a few more characters. There's also room to cut down the L/R controls a bit more:
d={}x=0y=0u=0w=0 cls()::_::b=btn()w+=(b%2-b%4\2)/50 |
These couple of changes get you down to 266.
Haha wow that's impressive! I was hoping to improve the turning code but couldn't think how, that's a really clever take on it, down to 265 chars
Just because, here's a version that's 280 chars that updates the score in super modern real time and also outputs it at the end, thanks to Jade for the extra savings!
d={}u=0w=0y=4x=4p=print cls()::_::b=btn()w+=(b%2-b%4\2)/50 x+=cos(w)/.7y+=sin(w)/.7if(2<pget(x,y)or u<1)p(u,0)u+=1circ(l,m,2,0)l=rnd(99)m=rnd(99) if(pget(x,y)>1)p(u)() add(d,{x,y,2,u})for e in all(d)do e[4]-=.1pset(unpack(e)) if(e[4]<0)e[3]=1 end circ(l,m,2,3) ?u,0,0 flip()goto _ |
Not quite sure if it might cause any issues if the value isn't exactly 1.5, but you can also save 2 characters by using this approximation (equal to x1.43)
x+=cos(w)/.7y+=sin(w)/.7 |
also, you can use this print shortcut for the score, as long as nothing else is on the same line:
?u,0,0 |
(super cryptic, yet really helpful)
Oh that's clever too, no particular reason for 1.5 other than I needed it to be fast enough to not instantly overlap with a tail piece.
@ChrisM It still felt wrong that I had removed del - it didn't change the graphic effects when I did, but it did mean the table kept growing.
I performed a quick test plus estimate of how long it would take to fill the pico-8 memory, and estimated about 12 minutes - in practice (I left it running while I did other stuff) it crashed after 27 minutes - either a bad quick estimate or the performance suffered leading to slowdown as the table grew.
If you want the game to last longer, see if you can add del back in. If 27 minutes is fine, don't worry about this comment.
Separate from that, another thing - that you might already know - is that screen wraps can be written concisely with code such as x%=128 y%=128
Wrapping the screen would increase the probability of a snake crashing into itself, thus shortening the game - with the proviso that the user is trying to eat apples and thus lengthening the snake (otherwise the snake stays small and the probability it crashes into itself may be 0).
If you did include screen wraps, then 128 could be assigned to a variable, which would allow it to be used for generation of apple position as well. In characters, there is an increase of about 13 characters for the screen wrap and changing the apple position generation code to use the same variable.
@JadeLombax good improvements!
[Please log in to post a comment]