đŸ„â€â™€ïž 1KB QUINE FLUID SIMULATION

715 words ~ 3-7 minsMathieu 'p01' Henri on January 25th, 2022

đŸ„â€â™€ïž 1kb Quine Fluid Simulation

Homage to the Fluid Simulation by Yusuke Endoh for IOCCC 2012, in 1kb of HTML, CSS and Javascript quine, code-golfed by Xem , Aemkei, RReverser and Irratix and myself

Click the screenshot to open the 1KB QUINE FLUID SIMULATION

What's a quine ?

Simply put, a "quine" is a program that output its own source code

Code golfing ?

Code golfing is the practice/art of writing code in the shortest program possible. This is a fun challenge

The initial commit of the Fluid Simulation clocked at 4025 bytes raw, and 1367 bytes minified using Terser. Looking at this code, my first call was 350 bytes. Maybe even further down to 300-320 bytes with the help of all the most talented Javascript code golfers

Eventually, with a smaller team, we reached 358 bytes for a fluid simulation showing its input as particles. Very close to my first call. The next step was to turn it into a quine and shape the code to spell the word "FLUID" just like the Fluid Simulation from Yusuke Endoh

Code

Here's the code of the quine, which you can of course see in action in the fluid simulation

<body id="b" style="font-size:6vw;width:29ch"><tt><b>1kb Fluid
Simulation Quine</b><p>Click to restart / <a href="https://github.com/xem/
miniFluid/">github</a></p><canvas width="512" height="192" id="c"
style="width:99%;background:#9cf"><script>M=o=>//<3
a.map(p         =>{   p.t=.1   ;p.s   =0;   o||(       p.D=p.w)
;a.map(  q=>(g=Math   .hypot   (e=p   .x-   q.x,  f=    p.y-q.y
)/2-1)<       0?o?(   g/=p.D   ,p.t   +=(   f*(z  =3-   p.D-q.D
)+p.v-q   .v)*g,p.s   +=(e*z   +p.u   -q.   u)*g  ):    p.D+=g*
g:1)});   ;;;;;;;;;       ;G=        b.outerHTML  .    slice/*#
#*/(0,-22);Q=o=>{_=a=[];for(C of G)_++,C!=" "&&a.push({x:_%/*.#
#*/64+4,y:5+_/64|0,C,w:"#"==C,u:0,v:0})};setInterval(`R-->0/*;#
#*/&&Q();M(c.width^=M());for(p of a)with(p)c.getContext(/*Vida#
#*/"2d").fillText(C,7*x,8*y),w||(y+=v+=t/4,x+=u+=s/8)`,R=19)/*#
#*/;onclick=o=>R=1;/*                                        ##
##                                                 ########### 
 ###################################################*/</script>

This code is formatted to fit 64 characters wide, and 16 lines tall. Follow the history of the code golfing on github

How it works

General markup and style

First there are 246 bytes of markup, with some HTML some make the page look clean, a canvas to render the fluid simulation, and a SCRIPT element to hold the code of the simulation

The simulation

The first part of the code is the function M=o=>a.map(...) which computes the density of the particles based on their neighbours when o is truthy, or the acceleration of the particles based on their neighbours and their density when o is falsy

The quine particles

We retrieve the whole source code of the page using G=b.outerHTML.slice(0,-22) to display the quine. The element b is the BODY of the page, and -22 is the length of the markup for the closing elements we ommitted.

To reset the particles, we create a function Q=o=>{...}, that goes through every character C of the source code G to create an array of particles, specify some x, y coordinates, but also whether C is wall ( represented by the # characters ) and the initial velocity u, v of 0

Render loop

The animation part is the setInterval(...,R=19) that first decreases R ( the counter of still frames ) to reset the particles using R-->0&&Q(). Then comes the simulation M(c.width^=M()); which also resets the canvas, and finally the rendering of the particles and update of their position and velocity

Restart on click

Finally onclick=o=>R=1 will reset the counter of still frames to 1 to restart the simulation on click

FLUID logo

You can see how the code spells the word "FLUID" in the negative space of the 64x16 characters long source code

<body ██████ ████████████████████████████████><tt><b>███ ██████
██████████ █████</b><p>█████ ██ ███████ / <a ██████████████████
██████████████████████>██████</a></p><canvas ███████████ ██████
██████ ██████████████████████████████████#████><script>████//██
███████         ███   ██████   ████   ███   ████       ████████
███████  ██████████   ██████   ████   ███   ████  ██    ███████
███████       █████   ██████   ████   ███   ████  ███   ███████
███████   █████████   ██████   ████   ███   ████  ██    ███████
███████   █████████       ███        ███████████  █    █████/*#
#*/██████████████████████████ ██ ██████████ ███████████████/*█#
#*/█████████████████████#██████████████████████████████████/*█#
#*/███████████████████████████ ██ ██████████████████████/*████#
#*/█████████████████████████████████████████████████████████/*#
#*/████████████████/*                                        ##
##                                                 ########### 
 ###################################################*/</script>

This was probably the most challenging part

Kudos

All in all this was a really fun challenge, and I hope you appreciate the end result.

Thank you to Xem for starting this, to my fellow code golfers: Aemkei, RReverser and Irratix, and to Yusuke Endoh for the inspiration.