Settings

Theme

Show HN: URL Snake

github.com

114 points by lbatchelor 3 years ago · 35 comments · 1 min read

Reader

Just a little demo I made of a fully functioning game of snake encoded entirely within a valid url (around 1033 bytes of code encoded into a 1464 byte url).

danielgjackson 3 years ago

Nice! I made a 250-byte Snake game (265 as a URL) a few years ago after spending far too long code-golfing it:

https://danielgjackson.github.io/tinyjs#snake

...and even a 224 byte version (240 as a URL), but with a few too many sacrifices.

lbatchelorOP 3 years ago

Can't update the post now, but I've actually got it down to 713 bytes, which I'm pretty happy with! I could remove features/colors/styles at this point, but I think I'll leave it there for now.

If anyone's interested, I've tried to annotate a fair amount of the tricks I've used so far: https://github.com/lukebatchelor/url-snake/blob/main/golf/de...

let e=document.body,t="Space: start/reset. Arrows: Move<div><canvas id=a><style>#a{border:solid}{background:tan}</style>",r=40,n=400,o,d=[[4,3]],s=d[0],c="#000",p=(e="red",t=n,a=0,l=a)=>{C[f="fillStyle"]=e,C.fillRect(ar,lr,t,t)},h=(e,t=n/2,a=t,l="center")=>{C[f]=c,C.textAlign=l,C.fillText(e,t,a)};e.innerHTML=t,C=a.getContext`2d`,a.height=a.width=n,C.font="30px f",e.onkeyup=({which:e})=>{36<e&&e<41?H=e-38:32!=e||o||(o=1,d=[[4,3]],H=2,S=0)},setInterval(i=>{if(o){let[e,t]=d[0],a=e+H%2,l=t+(H-1)%2,n=([e,t])=>e==a&&t==l;if(d.pop(),a<0||9<a||l<0||9<l||d.some(n))return o=0,p(),h`:(`;d=[[a,l],...d],n(s)&&(d[++S]=d[S-1],s=[(D=new Date)%10,DS%10]),p`tan`,d.map(e=>p(c,r,...e)),p(i,r,...s),h(S,9,30,"left")}},n);

  • Retr0id 3 years ago

    Golfed to 697 bytes using a self-extracting webp/html polyglot:

        data:text/html;base64,UklGRhgCAABXRUJQVlA4TAwCAAAvygIAAIU019bbNspSFKWR9hdFZaqtb3rvM84/Q4AZ8bMlhCEF6nODpdXLmTVE9J9A0qbBtj+FIQ4ItSvXD2Q5unN6D4zhrFElTYKWlecbTy1xFLz13m3bSfDTbSjX9eZVXiq7UW1Qa1Sv8pb3hl6dqcOd85r8pHWm1v3ocKfK+5V3a6snrGyf3xwDhuDxSQwWn8QxONA4nz+BrCigRT2PCygxPIvjOIQGBWHoSYfAaEFhDAaVxFeH9/MlhsvamNlgEhZI8D4aOP5RyUKNPJiRBwaWPVQoaOC+SUEhg8GwJMvkw0cCBZbwPmLa8VtTryyaRwq3tOOBGJTspxTV1pL/cvvzBzK8RxWtiN87O+AuUr0AFVVUrypGFW1rzRXaAd9ZxjCLm12wDIEiZ+9pv25QHLZVXVYT6gf37FlOl5eUP0lef0G6zl5MsvQUqetc1wmHyX+X+YIpzDCWPbTEX4d6G2VEja8O9VI4eTDEcwIujgdUSOMvFykY5LH4cp3IixQsiiMyia8IUV1eMqKZ1kuho8Y1QoLK4657mauuM8cEput01LoHElZKT7z2NnAYwwBZLSZiMR26KDAFRFGkC7CilZeXQs/H49lQYHadDJ+aiw9oaRt8UEzyIonhw2h2kcSFhGbByi5ARw+qEYSvGlGCHyRISmhEfQzRSqjEDF5CFkNoaMmh7HuwcnpyAjxjYW52YXMgaWQ9Yz48aW1nIG9ubG9hZD13aXRoKGMuZ2V0Q29udGV4dGAyZGApZm9yKHA9ZT0nJztkcmF3SW1hZ2UodGhpcyxwLS0sMCksdD1nZXRJbWFnZURhdGEoMCwwLDEsMSkuZGF0YVswXTspZSs9U3RyaW5nLmZyb21DaGFyQ29kZSh0KTtldmFsKGUpIHNyYz0jPg==
    
    (954 bytes of encoded URL)

    Based on the technique used here: https://gist.github.com/gasman/2560551

    Edit: hm, at some point in my golfing I appear to have broken the apple placement randomisation logic... I'm too lazy to debug it right now (probably)

  • joering2 3 years ago

    But sometimes the new red element to eat is being placed on the snake. Easier to spot after level 25.

tsukurimashou 3 years ago

Here is one I did a while ago, this is the colored version (so not the smallest) Still under 1024bits which was my goal

<pre style="letter-spacing:8"id="A"><script>Y=200;P='o';J=' ';N=15;C='#';E='+';m=[];X=C.repeat(N+2);for(T in X)m[T]=C+J.repeat(N)+C;m[0]=m[0].slice(0,-2)+E+C;m.unshift(X);m.push(X);function s(a,b,c){return a.substring(0,b)+c+a.substring(b+1)}function f(){e=setInterval(function w(){if(!z){R=p.length-1;if(h=p[R][0],j=p[R][1],h=1==d?h-1:h,h=-1==d?h+1:h,j=2==d?j-1:j,j=-2==d?j+1:j,p.push([h,j]),g=p.length-1,l=m[h][j],r){if(J!=l)if(E==l){x=y=0;for(t++,k=1;J!=m[x][y];)with(Math)x=~~(random()N+2),y=~~(random()N+2);m[x]=s(m[x],y,E);Y-=5}else z=1,P='x';!k&&t<g&&(b=p[g-t],m[b[0]]=s(m[b[0]],b[1],J)),k=0}for(a='',i=0;i<t;i++)i<g+1&&(b=p[g-i],m[b[0]]=s(m[b[0]],b[1],P));for(b in m){for(K in m[b])H=m[b][K],a+=H.fontcolor(/\#/.test(H)&&"#03B"||/\w/.test(H)&&"#2B2");a+="\n"}A.innerHTML=a}return w}(),Y)}t=3,p=[[1,1]];var i,z,r,k,d;f(),window.addEventListener("keydown",function(k){if(c=k.keyCode,-1!=[37,38,39,40].indexOf(c))with(Math)D=1==abs(39-c)?39-c:2*(38-c),z||abs(D)!=abs(d)&&(d=D,clearInterval(e),f(),r=1)});</script>

hgsgm 3 years ago

HN doesn't linkify data: URLs

data:text/html;charset=utf-8,%3Cbody%3E%3Cscript%3Eeval(atob(%22bGV0IGU9ZG9jdW1lbnQsdD1lLmJvZHkscj1NYXRoLGw9J1ByZXNzIHNwYWNlIHRvIHN0YXJ0L3BhdXNlL3Jlc2V0LCBhcnJvdyBrZXlzIHRvIG1vdmU8YnI+PGJyPjxjYW52YXMgaWQ9ImEiPjxzdHlsZT5jYW52YXN7Ym9yZGVyOiAxcHggc29saWQgYmxhY2s7fWJvZHl7YmFja2dyb3VuZDojY2NjO308L3N0eWxlPicsaT00MCxvPTQwMCxuPW8scz0wLGY9MSxkPTAsYz0xLGg9MCxwPVtbMywzXSxbNCwzXSxbNSwzXV0sdT1wLHk9WzUsNV0sYj0iIzAwMCIsZz0oZSx0LHI9YixsPWksbz1pKT0+e1MuZmlsbFN0eWxlPXIsUy5maWxsUmVjdChlLHQsbCxvKX0sdj0oZSx0LHIsbD0iY2VudGVyIik9PntTLmZpbGxTdHlsZT1iLFMudGV4dEFsaWduPWwsUy5maWxsVGV4dChlLHQscil9LHg9ZT0+ci5mbG9vcihyLnJhbmRvbSgpKmUpLGs9KCk9PntpZighZCYmIWMpe2xldFtlLHRdPXAucG9wKCkscj1wWzBdWzBdK3MsbD1wWzBdWzFdK2Y7aWYocjwwfHw5PHJ8fGw8MHx8OTxsfHxwLnNvbWUoKFtlLHRdKT0+cj09ZSYmbD09dCkpcmV0dXJuIG0oKTtyPT15WzBdJiZsPT15WzFdJiYoaCsrLHAucHVzaChbLi4ucFtwLmxlbmd0aC0xXV0pLHk9W3goOSkseCg5KV0pLHAudW5zaGlmdChbcixsXSksZygwLDAsIiNmZmYiLG4sbyk7Zm9yKFtlLHRdb2YgcClnKGUqaSx0KmkpO2coeVswXSppLHlbMV0qaSwiIzBmMCIpLHYoIlNjb3JlOiAiK2gsbi05LDMwLCJyaWdodCIpfX0sbT0oKT0+e2M9MSxnKDAsMCwiI2YwMCIsbixvKSx2KCJZb3UgZGllZCA6KCIsbi8yLG8vMil9LHc9KCk9PntjPTAscD1bLi4udV0scz0wLGg9MCxmPTF9LFM9KHQuaW5uZXJIVE1MPWwsYS5nZXRDb250ZXh0KCIyZCIpKTthLmhlaWdodD1vLGEud2lkdGg9bixTLmZvbnQ9IjMwcHggQXJpYWwiLGUuYWRkRXZlbnRMaXN0ZW5lcigia2V5dXAiLGU9PntlPWUud2hpY2g7Mzc9PWUmJihzPS0xLGY9MCksMzg9PWUmJihzPTAsZj0tMSksMzk9PWUmJihzPTEsZj0wKSw0MD09ZSYmKHM9MCxmPTEpLDMyPT1lJiYoYz93KCk6ZD1kPzA6MSl9KSxzZXRJbnRlcnZhbChrLG4pOw==%22))%3C%2Fscript%3E

  • bmacho 3 years ago

    https://news.ycombinator.com/formatdoc says that between angles it should work, but it does not. Or i don't know how to use it, it doesn't seem to do anything.

    <data:text/html;charset=utf-8,%3Cbody%3E%3Cscript%3Eeval(atob("bGV0IGU9ZG9jdW1lbnQuYm9keSx0PSJTcGFjZTogc3RhcnQvcmVzZXQuIEFycm93czogTW92ZTxkaXY+PGNhbnZhcyBpZD1hPjxzdHlsZT4jYXtib3JkZXI6c29saWR9KntiYWNrZ3JvdW5kOnRhbn08L3N0eWxlPiIscj00MCxuPTQwMCxvLGQ9W1s0LDNdXSxzPWRbMF0sYz0iIzAwMCIscD0oZT0icmVkIix0PW4sYT0wLGw9YSk9PntDW2Y9ImZpbGxTdHlsZSJdPWUsQy5maWxsUmVjdChhKnIsbCpyLHQsdCl9LGg9KGUsdD1uLzIsYT10LGw9ImNlbnRlciIpPT57Q1tmXT1jLEMudGV4dEFsaWduPWwsQy5maWxsVGV4dChlLHQsYSl9O2UuaW5uZXJIVE1MPXQsQz1hLmdldENvbnRleHRgMmRgLGEuaGVpZ2h0PWEud2lkdGg9bixDLmZvbnQ9IjMwcHggZiIsZS5vbmtleXVwPSh7d2hpY2g6ZX0pPT57MzY8ZSYmZTw0MT9IPWUtMzg6MzIhPWV8fG98fChvPTEsZD1bWzQsM11dLEg9MixTPTApfSxzZXRJbnRlcnZhbChpPT57aWYobyl7bGV0W2UsdF09ZFswXSxhPWUrSCUyLGw9dCsoSC0xKSUyLG49KFtlLHRdKT0+ZT09YSYmdD09bDtpZihkLnBvcCgpLGE8MHx8OTxhfHxsPDB8fDk8bHx8ZC5zb21lKG4pKXJldHVybiBvPTAscCgpLGhgOihgO2Q9W1thLGxdLC4uLmRdLG4ocykmJihkWysrU109ZFtTLTFdLHM9WyhEPW5ldyBEYXRlKSUxMCxEKlMlMTBdKSxwYHRhbmAsZC5tYXAoZT0+cChjLHIsLi4uZSkpLHAoaSxyLC4uLnMpLGgoUyw5LDMwLCJsZWZ0Iil9fSxuKTs="))%3C%2Fscript%3E>

nathell 3 years ago

My initial interpretation of the title was something that _displays_ the game inside the URL, using Unicode block characters.

neontomo 3 years ago

I love these types of projects. A suggestion to take this a step further is to encode it inside a QR code.

  • lbatchelorOP 3 years ago

    That was actually the original plan! But unfortunately it seems like my phone's qr code reader won't open it in a browser automatically. I then tried using a url shortener to link to it but absolutely no shortener that I could find would take a data: url.

    I could host my own shortener to do it, but it feels like that is cheating the spirit of the challenge.

    I'll keep playing with it though, add touch device controls, maybe a site to allow generating different versions of the url (different colours, sizes, game over messages, etc).

planede 3 years ago

Some interesting features of this snake game:

1. You can change directions multiple times within a tick, making the last direction to be effective.

2. You can change to any directions, including the opposite direction of your current movement, which usually results in :( as the snakes head bumps into its body...

3. Except when the snake has length 1 or 2, then it's OK, as the snake either does not have a body yet, or its body and head switch places at the next tick.

As a combination of 1 and 2, quickly turning around is a risky move.

lbatchelorOP 3 years ago

Edit: I've actually managed to get the javascript down to a measly 859 bytes now. Pretty happy with some of the code golfing techniques I came up with

jstrieb 3 years ago

If you want to make clickable links with this code, you can use URL Pages.

https://github.com/jstrieb/urlpages

It's a small JavaScript application to store entire web pages in URLs. I made it after learning that links with data URLs are no longer clickable.

dang 3 years ago

Related ongoing thread:

How to store your app's entire state in the url - https://news.ycombinator.com/item?id=34312546 - Jan 2023 (88 comments)

gabrielsroka 3 years ago

Can't you just put the whole thing in a JavaScript URL without using base64? Eg

  JavaScript:alert(1)
It would be shorter than 1464. I'm not at my computer right now to try it...

Edit: It seems to work. Also, the original can be golfed some more.

gernb 3 years ago

very cool!

here's several games in 280 characters or less

https://www.dwitter.net/h/game

rpastuszak 3 years ago

Hey I think you might like my Pong in a tweet then!

https://twitter.com/rafalpast/status/1316836397903474688?s=4...

Still waiting for VCs to invest in my Twitter as a CDN:

https://twitter.com/rafalpast/status/1316841669451558913?s=4...

The article from the tweet: https://laconic-mu.vercel.app/index.html?c=eJylWOuS27YV%2Fu%...

realYitzi 3 years ago

And ChatGPT can tell that it's a game of Snake from the URL. https://www.tiktok.com/@y.i.t.z.i/video/7186055378977803521

"When decoded, the script appears to be a Snake game implemented using JavaScript and the HTML5 canvas element. The script creates an HTML page with a canvas element and adds event listeners for arrow keys and space bar to control the game."

  • lbatchelorOP 3 years ago

    Wow, that's actually impressive. Any idea how chat gpt would know that? Surely it's not making the request for it and surely it's not actually decoding any base64 right?

    • UweSchmidt 3 years ago

      ChatGPT has probably seen plenty of half-baked excercise/homework snake implementations on Github to tell that this is another one of those.

      (Yes, this is moving the goalposts and implying that true AI is just over the horizon...)

    • londons_explore 3 years ago

      You'd be right a good chunk of the time if you said it was a snake game just by seeing that it was a data URL and had the word 'canvas' in.

    • realYitzi 3 years ago

      I can venture a guess, but gonna wait until I know what I'm talking about.

      Over here it decodes a js animated SVG https://vt.tiktok.com/ZS8rcjhgg/ but made a few slight mistakes.

    • kevinwang 3 years ago

      I recall seeing that it's actually quite fluent in base64

  • IAmGraydon 3 years ago

    Wow that's impressive. Is ChatGPT updating its model fast enough that this repo could have been included or is it really figuring out what this is from the code itself?

    • londons_explore 3 years ago

      ChatGPT had it's last update on 15th Dec 2022, but the main scrape of the web for training data was ~2020.

      Try asking it about someone famous from 2021 and it usually doesn't know.

Keyboard Shortcuts

j
Next item
k
Previous item
o / Enter
Open selected item
?
Show this help
Esc
Close modal / clear selection