[HN Gopher] Show HN: URL Snake
___________________________________________________________________
Show HN: URL Snake
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).
Author : lbatchelor
Score : 104 points
Date : 2023-01-07 15:02 UTC (2 days ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| neontomo wrote:
| I love these types of projects. A suggestion to take this a step
| further is to encode it inside a QR code.
| lbatchelor wrote:
| 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).
| jstrieb wrote:
| 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.
| calebegg wrote:
| Shameless plug: my (free, ad-free) side project does this too:
| https://codewich.com
| lbatchelor wrote:
| 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(a_r,l _r,t,t)},h=(e,t=n /2
| ,a=t,l="center")=>{C[f]=c,C.textAlign=l,C.fillText(e,t,a)};e.inne
| rHTML=t,C=a.getContext`2d`,a.height=a.width=n,C.font="30px f",e.o
| nkeyup=({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))re
| turn o=0,p(),h`:(`;d=[[a,l],...d],n(s)&&(d[++S]=d[S-1],s=[(D=new
| Date)%10,D_S%10]),p`tan`,d.map(e=>p(c,r,...e)),p(i,r,...s),h(S,9,
| 30,"left")}},n);
| Retr0id wrote:
| Golfed to 697 bytes using a self-extracting webp/html polyglot:
| data:text/html;base64,UklGRhgCAABXRUJQVlA4TAwCAAAvygIAAIU019bbN
| spSFKWR9hdFZaqtb3rvM84/Q4AZ8bMlhCEF6nODpdXLmTVE9J9A0qbBtj+FIQ4I
| tSvXD2Q5unN6D4zhrFElTYKWlecbTy1xFLz13m3bSfDTbSjX9eZVXiq7UW1Qa1S
| v8pb3hl6dqcOd85r8pHWm1v3ocKfK+5V3a6snrGyf3xwDhuDxSQwWn8QxONA4nz
| +BrCigRT2PCygxPIvjOIQGBWHoSYfAaEFhDAaVxFeH9/MlhsvamNlgEhZI8D4aO
| P5RyUKNPJiRBwaWPVQoaOC+SUEhg8GwJMvkw0cCBZbwPmLa8VtTryyaRwq3tOOB
| GJTspxTV1pL/cvvzBzK8RxWtiN87O+AuUr0AFVVUrypGFW1rzRXaAd9ZxjCLm12
| wDIEiZ+9pv25QHLZVXVYT6gf37FlOl5eUP0lef0G6zl5MsvQUqetc1wmHyX+X+Y
| IpzDCWPbTEX4d6G2VEja8O9VI4eTDEcwIujgdUSOMvFykY5LH4cp3IixQsiiMyi
| a8IUV1eMqKZ1kuho8Y1QoLK4657mauuM8cEput01LoHElZKT7z2NnAYwwBZLSZi
| MR26KDAFRFGkC7CilZeXQs/H49lQYHadDJ+aiw9oaRt8UEzyIonhw2h2kcSFhGb
| Byi5ARw+qEYSvGlGCHyRISmhEfQzRSqjEDF5CFkNoaMmh7HuwcnpyAjxjYW52YX
| MgaWQ9Yz48aW1nIG9ubG9hZD13aXRoKGMuZ2V0Q29udGV4dGAyZGApZm9yKHA9Z
| T0nJztkcmF3SW1hZ2UodGhpcyxwLS0sMCksdD1nZXRJbWFnZURhdGEoMCwwLDEs
| MSkuZGF0YVswXTspZSs9U3RyaW5nLmZyb21DaGFyQ29kZSh0KTtldmFsKGUpIHN
| yYz0jPg==
|
| (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 wrote:
| But sometimes the new red element to eat is being placed on the
| snake. Easier to spot after level 25.
| planede wrote:
| 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.
| gabrielsroka wrote:
| 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.
| [deleted]
| dang wrote:
| 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)
| [deleted]
| hgsgm wrote:
| HN doesn't linkify data: URLs
|
| data:text/html;charset=utf-8,%3Cbody%3E%3Cscript%3Eeval(atob(%22b
| GV0IGU9ZG9jdW1lbnQsdD1lLmJvZHkscj1NYXRoLGw9J1ByZXNzIHNwYWNlIHRvIH
| N0YXJ0L3BhdXNlL3Jlc2V0LCBhcnJvdyBrZXlzIHRvIG1vdmU8YnI+PGJyPjxjYW5
| 2YXMgaWQ9ImEiPjxzdHlsZT5jYW52YXN7Ym9yZGVyOiAxcHggc29saWQgYmxhY2s7
| fWJvZHl7YmFja2dyb3VuZDojY2NjO308L3N0eWxlPicsaT00MCxvPTQwMCxuPW8sc
| z0wLGY9MSxkPTAsYz0xLGg9MCxwPVtbMywzXSxbNCwzXSxbNSwzXV0sdT1wLHk9Wz
| UsNV0sYj0iIzAwMCIsZz0oZSx0LHI9YixsPWksbz1pKT0+e1MuZmlsbFN0eWxlPXI
| sUy5maWxsUmVjdChlLHQsbCxvKX0sdj0oZSx0LHIsbD0iY2VudGVyIik9PntTLmZp
| bGxTdHlsZT1iLFMudGV4dEFsaWduPWwsUy5maWxsVGV4dChlLHQscil9LHg9ZT0+c
| i5mbG9vcihyLnJhbmRvbSgpKmUpLGs9KCk9PntpZighZCYmIWMpe2xldFtlLHRdPX
| AucG9wKCkscj1wWzBdWzBdK3MsbD1wWzBdWzFdK2Y7aWYocjwwfHw5PHJ8fGw8MHx
| 8OTxsfHxwLnNvbWUoKFtlLHRdKT0+cj09ZSYmbD09dCkpcmV0dXJuIG0oKTtyPT15
| WzBdJiZsPT15WzFdJiYoaCsrLHAucHVzaChbLi4ucFtwLmxlbmd0aC0xXV0pLHk9W
| 3goOSkseCg5KV0pLHAudW5zaGlmdChbcixsXSksZygwLDAsIiNmZmYiLG4sbyk7Zm
| 9yKFtlLHRdb2YgcClnKGUqaSx0KmkpO2coeVswXSppLHlbMV0qaSwiIzBmMCIpLHY
| oIlNjb3JlOiAiK2gsbi05LDMwLCJyaWdodCIpfX0sbT0oKT0+e2M9MSxnKDAsMCwi
| I2YwMCIsbixvKSx2KCJZb3UgZGllZCA6KCIsbi8yLG8vMil9LHc9KCk9PntjPTAsc
| D1bLi4udV0scz0wLGg9MCxmPTF9LFM9KHQuaW5uZXJIVE1MPWwsYS5nZXRDb250ZX
| h0KCIyZCIpKTthLmhlaWdodD1vLGEud2lkdGg9bixTLmZvbnQ9IjMwcHggQXJpYWw
| iLGUuYWRkRXZlbnRMaXN0ZW5lcigia2V5dXAiLGU9PntlPWUud2hpY2g7Mzc9PWUm
| JihzPS0xLGY9MCksMzg9PWUmJihzPTAsZj0tMSksMzk9PWUmJihzPTEsZj0wKSw0M
| D09ZSYmKHM9MCxmPTEpLDMyPT1lJiYoYz93KCk6ZD1kPzA6MSl9KSxzZXRJbnRlcn
| ZhbChrLG4pOw==%22))%3C%2Fscript%3E
| bmacho wrote:
| 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("
| bGV0IGU9ZG9jdW1lbnQuYm9keSx0PSJTcGFjZTogc3RhcnQvcmVzZXQuIEFycm9
| 3czogTW92ZTxkaXY+PGNhbnZhcyBpZD1hPjxzdHlsZT4jYXtib3JkZXI6c29saW
| R9KntiYWNrZ3JvdW5kOnRhbn08L3N0eWxlPiIscj00MCxuPTQwMCxvLGQ9W1s0L
| DNdXSxzPWRbMF0sYz0iIzAwMCIscD0oZT0icmVkIix0PW4sYT0wLGw9YSk9PntD
| W2Y9ImZpbGxTdHlsZSJdPWUsQy5maWxsUmVjdChhKnIsbCpyLHQsdCl9LGg9KGU
| sdD1uLzIsYT10LGw9ImNlbnRlciIpPT57Q1tmXT1jLEMudGV4dEFsaWduPWwsQy
| 5maWxsVGV4dChlLHQsYSl9O2UuaW5uZXJIVE1MPXQsQz1hLmdldENvbnRleHRgM
| mRgLGEuaGVpZ2h0PWEud2lkdGg9bixDLmZvbnQ9IjMwcHggZiIsZS5vbmtleXVw
| PSh7d2hpY2g6ZX0pPT57MzY8ZSYmZTw0MT9IPWUtMzg6MzIhPWV8fG98fChvPTE
| sZD1bWzQsM11dLEg9MixTPTApfSxzZXRJbnRlcnZhbChpPT57aWYobyl7bGV0W2
| UsdF09ZFswXSxhPWUrSCUyLGw9dCsoSC0xKSUyLG49KFtlLHRdKT0+ZT09YSYmd
| D09bDtpZihkLnBvcCgpLGE8MHx8OTxhfHxsPDB8fDk8bHx8ZC5zb21lKG4pKXJl
| dHVybiBvPTAscCgpLGhgOihgO2Q9W1thLGxdLC4uLmRdLG4ocykmJihkWysrU10
| 9ZFtTLTFdLHM9WyhEPW5ldyBEYXRlKSUxMCxEKlMlMTBdKSxwYHRhbmAsZC5tYX
| AoZT0+cChjLHIsLi4uZSkpLHAoaSxyLC4uLnMpLGgoUyw5LDMwLCJsZWZ0Iil9f
| SxuKTs="))%3C%2Fscript%3E>
| rpastuszak wrote:
| 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%...
| lbatchelor wrote:
| 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
| gabrielsroka wrote:
| You should be able to change
| e.addEventListener("keyup"...
|
| to e.onkeyup=...
|
| but I haven't tested it.
| lbatchelor wrote:
| Ooh! Don't know how I missed that, I'll give it a go! Cheers!
| tsukurimashou wrote:
| 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.repea
| t(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(),win
| dow.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||a
| bs(D)!=abs(d)&&(d=D,clearInterval(e),f(),r=1)});</script>
| nathell wrote:
| My initial interpretation of the title was something that
| _displays_ the game inside the URL, using Unicode block
| characters.
| lbatchelor wrote:
| I think it was changed by mods unfortunately :/
| realYitzi wrote:
| 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."
| lbatchelor wrote:
| 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?
| realYitzi wrote:
| 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 wrote:
| I recall seeing that it's actually quite fluent in base64
| londons_explore wrote:
| 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.
| UweSchmidt wrote:
| 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...)
| [deleted]
| IAmGraydon wrote:
| 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 wrote:
| 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.
| danielgjackson wrote:
| 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.
| lbatchelor wrote:
| You are on a completely different level. Wow. I am going to
| spend absolutely too long tomorrow trying to work out how on
| earth you've done that. Cheers!
| danielgjackson wrote:
| It was spread over a long time, and quite painful to get
| there!
|
| If it's useful, I added an explanation of how it works at:
|
| https://github.com/danielgjackson/tinyjs/blob/master/mini-
| ex...
| gernb wrote:
| very cool!
|
| here's several games in 280 characters or less
|
| https://www.dwitter.net/h/game
___________________________________________________________________
(page generated 2023-01-09 23:01 UTC)