move things around for no reason :3

This commit is contained in:
Crispy 2024-08-29 21:19:07 +02:00
parent 100f94cf43
commit 14e753c327
16 changed files with 30 additions and 37 deletions

View file

@ -29,7 +29,7 @@ this means it is<br>
- <a href="/awful_software/unity-on-linux">unity on linux sucks</a><br>
- <a href="/vent/dead-trees">dead trees</a><br>
- <a href="/horological-crimes">horological crimes</a><br>
- <a href="/cellthing">snad (cell thing)</a><br>
- <a href="/snad">snad</a><br>
- <a href="/keyboards-are-fun">keyboar</a><br>
- <a href="/vent/distracting">distracting</a><br>
- <a href="/blender">blender</a><br>

View file

Before

Width:  |  Height:  |  Size: 462 B

After

Width:  |  Height:  |  Size: 462 B

View file

Before

Width:  |  Height:  |  Size: 984 B

After

Width:  |  Height:  |  Size: 984 B

View file

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View file

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -4,7 +4,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>something silly - cellthing</title>
<title>something silly - snad</title>
<link rel="stylesheet" href="/style.css">
<link rel="icon" type="image/x-icon" href="/creacher.png">
</head>
@ -20,18 +20,16 @@ I made/am making some kind of asynchronous cellular automata or cell-based spati
The world consists of a grid of cells, and you can create new cell types and assign them names and colours. You can create rules, which are like the chemistry of this world. You make a pattern on the left and a pattern on the right.<br>
The engine randomly finds places where the one of your rules' <em>input (left)</em> picture matches a place in the world, and replaces it with the <em>output (right)</em> picture.<br>
</p>
<p>
<video src="snad/snake_in_maze.mp4" controls></video>
</p>
<video loading="lazy" src="/media/snad/snake_in_maze.mp4" alt="" title="" controls ></video>
<h2 id="groups">groups</h2>
<p>
A rule can also have cells containing a <em>group</em>. On the input side, that cell will match anything in the group, and on the output side it will become a random cell from the group. A diagonal line through the group icon means that it can also match on positions outside the world, where there are no cells.<br>
<img src="snad/group_example.png" alt="">
<img loading="lazy" src="/media/snad/group_example.png" alt="" title=""></img>
</p>
<h2 id="copy-cells">copy cells</h2>
<p>
On the output side, a cell can be set to <em>copy</em> the contents of one cell from the input side, this is useful for applying the same rule to several cell types without randomly swapping between them on the output<br>
<img src="snad/copy_example.png" alt="">
<img loading="lazy" src="/media/snad/copy_example.png" alt="" title=""></img>
</p>
<h1 id="random-is-easy-right">random is easy, right?</h1>
<p>
@ -43,9 +41,11 @@ A rule can have <em>blank</em> cells. On the input side, this means it will matc
<h2 id="worm">worm</h2>
<p>
Let's say I make a rule for a little worm that moves to the right, this works fine. Its head disappears out of the world because the cell in front of the head in the <em>input</em> pattern is blank, which matches anything, including out of bounds. To make it stop just before the edge, you could set that rule cell to air.<br>
<video src="snad/worm_right.mp4" controls></video>
<video loading="lazy" src="/media/snad/worm_right.mp4" alt="" title="" controls ></video>
Now if I want it to do the same thing in but to the left, I can simply draw the rule and worm in the other direction, right?<br>
<video src="snad/worm_left.mp4" controls></video><br>
<video loading="lazy" src="/media/snad/worm_left.mp4" alt="" title="" controls ></video>
</p>
<p>
Almost. It no longer moves past the edge.<br>
</p>
<p>
@ -65,9 +65,7 @@ Once at the start, the engine checks every possible position and every rule, and
<p>
Now, how should it even use that information? The first thing I tried was to randomly pick one of all the matches. This kind of works but leads to the simulation speed being dependent on the number of matches, so for example sand falls slower if there is a lot of sand that hasn't landed yet.<br>
</p>
<p>
<video src="snad/sand_fall_faster.mp4" controls></video>
</p>
<video loading="lazy" src="/media/snad/sand_fall_faster.mp4" alt="" title="" controls ></video>
<p>
I got a slightly more even result by multiplying the speed (number of rule executions per frame) by the total number of matches, but this is not a perfect solution as it does not take into account overlapping matches. A cell contained in several rule matches would be more likely to be affected, which in some cases can lead to weird bias (see <a href="#just-one-more-implementation">just one more implementation</a>)<br>
</p>
@ -79,9 +77,7 @@ So now the engine picks a random position, then checks the cache and picks a ran
<p>
I want to simulate a swarm of bees, so I create a rule for a bee moving by one cell, and enable <code>rotate</code> so it works in all directions. That was easy,<br>
</p>
<p>
<video src="snad/bees_biased.mp4" controls></video>
</p>
<video loading="lazy" src="/media/snad/bees_biased.mp4" alt="" title="" controls ></video>
<p>
Oh no, the swarm is moving toward the top left instead of spreading equally. But I can see that the bees move in all four directions, so the rule seems to be rotated correctly.<br>
</p>
@ -90,12 +86,12 @@ I was stuck on this problem for quite a while, and it only happened with the new
</p>
<p>
The movement rule has these variants:<br>
<img src="snad/bee_rules_rotated.png" alt="">
<img loading="lazy" src="/media/snad/bee_rules_rotated.png" alt="" title=""></img>
</p>
<p>
Each rule has its origin point in the top-left cell.<br>
In the diagram below, the bee would move left when the left (purple) cell is picked by the engine, and up when the top (green) cell is picked.<br>
<img src="snad/bee_movement_pattern.png" alt="">
<img loading="lazy" src="/media/snad/bee_movement_pattern.png" alt="" title=""></img>
</p>
<p>
But to move right or down, it needs the bees own position to be picked by the engine, since the rules always extend right-down. That means when the engine picks the bee's position, there are <em>two</em> possible rules to execute. Therefore, moving right and down both have half the probability overall compared to moving up or left.<br>
@ -107,9 +103,7 @@ In this version, the cache is not only searched for matches <em>at</em> the chos
<p>
Since the root issue was caused by asymmetry, I thought this implementation should be correct. This one was actually my first instinct when I created the cache, but as a <a href="https://gaussian.dev/">friend</a> suggested, an absolute-position based checker seemed (and indeed was) more performant and simpler, so I did that one first.<br>
</p>
<p>
<video src="snad/bees.mp4" controls></video>
</p>
<video loading="lazy" src="/media/snad/bees.mp4" alt="" title="" controls ></video>
<p>
Now the bees are evenly distributed, just like real bees!<sup>(false)</sup><br>
</p>
@ -117,9 +111,7 @@ Now the bees are evenly distributed, just like real bees!<sup>(false)</sup><br>
<p>
While I was trying to figure out the reason for the directional bias in the previous implementation, I realised that the overlap checker also has biases. The probability of any given cached match to be executed is dependent on its area, which is not very intuitive. Two objects of different mass fall at different speeds, and adding empty padding to a rule makes it run faster.<br>
</p>
<p>
<video src="snad/rule_size_bias.mp4" controls></video>
</p>
<video loading="lazy" src="/media/snad/rule_size_bias.mp4" alt="" title="" controls ></video>
<p>
Ideally the red, pink and blue cells should all fall at around the same rate, but the red sand always lands first and the pink last.<br>
</p>
@ -129,7 +121,7 @@ Alright, the Final (I <em>hope</em>) implementation stores an origin offset for
<h2 id="fin">fin</h2>
<p>
If you somehow read through all that, congratulations I think? Now enjoy this fire:<br>
<video src="snad/fire.mp4" controls></video>
<video loading="lazy" src="/media/snad/fire.mp4" alt="" title="" controls ></video>
</p>
<p>
Download the thing and make something fun: <a href="https://git.crispypin.cc/CrispyPin/snad">git.crispypin.cc/CrispyPin/snad</a><br>

View file

@ -13,7 +13,7 @@ this means it is
- [unity on linux sucks](/awful_software/unity-on-linux)
- [dead trees](/vent/dead-trees)
- [horological crimes](/horological-crimes)
- [snad (cell thing)](/cellthing)
- [snad](/snad)
- [keyboar](/keyboards-are-fun)
- [distracting](/vent/distracting)
- [blender](/blender)

View file

@ -5,15 +5,15 @@ I made/am making some kind of asynchronous cellular automata or cell-based spati
The world consists of a grid of cells, and you can create new cell types and assign them names and colours. You can create rules, which are like the chemistry of this world. You make a pattern on the left and a pattern on the right.
The engine randomly finds places where the one of your rules' *input (left)* picture matches a place in the world, and replaces it with the *output (right)* picture.
<video src="snad/snake_in_maze.mp4" controls></video>
==video:"/media/snad/snake_in_maze.mp4"
## groups
A rule can also have cells containing a *group*. On the input side, that cell will match anything in the group, and on the output side it will become a random cell from the group. A diagonal line through the group icon means that it can also match on positions outside the world, where there are no cells.
<img src="snad/group_example.png" alt="">
==image:"/media/snad/group_example.png"
## copy cells
On the output side, a cell can be set to *copy* the contents of one cell from the input side, this is useful for applying the same rule to several cell types without randomly swapping between them on the output
<img src="snad/copy_example.png" alt="">
==image:"/media/snad/copy_example.png"
# random is easy, right?
@ -23,9 +23,10 @@ A rule can have *blank* cells. On the input side, this means it will match anyth
## worm
Let's say I make a rule for a little worm that moves to the right, this works fine. Its head disappears out of the world because the cell in front of the head in the *input* pattern is blank, which matches anything, including out of bounds. To make it stop just before the edge, you could set that rule cell to air.
<video src="snad/worm_right.mp4" controls></video>
==video:"/media/snad/worm_right.mp4"
Now if I want it to do the same thing in but to the left, I can simply draw the rule and worm in the other direction, right?
<video src="snad/worm_left.mp4" controls></video><br>
==video:"/media/snad/worm_left.mp4"
Almost. It no longer moves past the edge.
When a rule and position is chosen, the top-left of the rule is aligned with that position. In the example above, the rule would have to start from outside the world to make the worm continue one more step.
@ -40,7 +41,7 @@ Once at the start, the engine checks every possible position and every rule, and
Now, how should it even use that information? The first thing I tried was to randomly pick one of all the matches. This kind of works but leads to the simulation speed being dependent on the number of matches, so for example sand falls slower if there is a lot of sand that hasn't landed yet.
<video src="snad/sand_fall_faster.mp4" controls></video>
==video:"/media/snad/sand_fall_faster.mp4"
I got a slightly more even result by multiplying the speed (number of rule executions per frame) by the total number of matches, but this is not a perfect solution as it does not take into account overlapping matches. A cell contained in several rule matches would be more likely to be affected, which in some cases can lead to weird bias (see [just one more implementation](#just-one-more-implementation))
@ -50,18 +51,18 @@ So now the engine picks a random position, then checks the cache and picks a ran
## swarm
I want to simulate a swarm of bees, so I create a rule for a bee moving by one cell, and enable `rotate` so it works in all directions. That was easy,
<video src="snad/bees_biased.mp4" controls></video>
==video:"/media/snad/bees_biased.mp4"
Oh no, the swarm is moving toward the top left instead of spreading equally. But I can see that the bees move in all four directions, so the rule seems to be rotated correctly.
I was stuck on this problem for quite a while, and it only happened with the new cached executor.
The movement rule has these variants:
<img src="snad/bee_rules_rotated.png" alt="">
==image:"/media/snad/bee_rules_rotated.png"
Each rule has its origin point in the top-left cell.
In the diagram below, the bee would move left when the left (purple) cell is picked by the engine, and up when the top (green) cell is picked.
<img src="snad/bee_movement_pattern.png" alt="">
==image:"/media/snad/bee_movement_pattern.png"
But to move right or down, it needs the bees own position to be picked by the engine, since the rules always extend right-down. That means when the engine picks the bee's position, there are *two* possible rules to execute. Therefore, moving right and down both have half the probability overall compared to moving up or left.
@ -71,14 +72,14 @@ In this version, the cache is not only searched for matches *at* the chosen posi
Since the root issue was caused by asymmetry, I thought this implementation should be correct. This one was actually my first instinct when I created the cache, but as a [friend](https://gaussian.dev/) suggested, an absolute-position based checker seemed (and indeed was) more performant and simpler, so I did that one first.
<video src="snad/bees.mp4" controls></video>
==video:"/media/snad/bees.mp4"
Now the bees are evenly distributed, just like real bees!<sup>(false)</sup>
## just one more implementation
While I was trying to figure out the reason for the directional bias in the previous implementation, I realised that the overlap checker also has biases. The probability of any given cached match to be executed is dependent on its area, which is not very intuitive. Two objects of different mass fall at different speeds, and adding empty padding to a rule makes it run faster.
<video src="snad/rule_size_bias.mp4" controls></video>
==video:"/media/snad/rule_size_bias.mp4"
Ideally the red, pink and blue cells should all fall at around the same rate, but the red sand always lands first and the pink last.
@ -86,7 +87,7 @@ Alright, the Final (I *hope*) implementation stores an origin offset for rules.
## fin
If you somehow read through all that, congratulations I think? Now enjoy this fire:
<video src="snad/fire.mp4" controls></video>
==video:"/media/snad/fire.mp4"
Download the thing and make something fun: [git.crispypin.cc/CrispyPin/snad](https://git.crispypin.cc/CrispyPin/snad)