Help this man decipher his cool creative code.
dl.dropbox.com
dl.dropbox.com
And the Fractint stone soup people included many "error" algorithms.
But this struck me as particularly weird for being so intricate being based on such a simple variation of the basic pixel-by-pixel floodfill formula.
In order to understand what is going on, lets first discount the conditions for a point not to be added to the last. Lets say they were added but ignored when popped. We would then iterate over every other point in the list, because for every step, we both increment our list index, AND remove one element. If the directions at index 0, and 2 were then non opposite (i.e. left - top), then we would flood fill in left-top direction. If the directions were opposite we would first fill a line. Anyway, we need not go deeper into what would happen after that, it was just to get a feel for it. Because we actually have those two conditions for not inserting a point into the list. This could probably be thought as giving rise to a pseudo random disturbance in our index picking.
If this approximation is accepted the algorithm looks like this
1. Choose an order for the four directions UP, DOWN, LEFT, RIGHT. 2. Choose a starting point and add to list, draw white. 3. Add all neighboring points to list in order chosen in step 1. 4. Let n be number of points drawn white, m number of points currently in list. Remove the point at list index Math.floor(n*(1+Math.random())%m. 5. Color said point white and goto 3.
From this we can get a feel for what is happening. The reason we proceed outwards is that we the points we color are more and more recently added (i.e. further out). The reason for the gaps is that we a) effectively increase our index by 2+a random small integer.
The reason that we start filling again from the beginning is not explained by the random model, but can be understood from the fact that in the original algorithm, when we reach the borders, n starts increasing faster than m. This is because there is a high chance that added points are illegal. Since n increases faster than m, n%m will wrap around, and we start drawing points with low indices again.
I am not completely sure about these points: I have not tested them, but they seem a likely explanation.
Thing is there is no per-step randomness. The small integer (pickOffset) only adds some variation to the algorithm, and is initialized only when you hit Space. I'm pretty sure that if pickOffset was changed on each step(), the magic would be lost.
What I'm wondering is why this simple change of the picking algorithm (open.pop(nStep % open.length) instead of open.pop(0) (simple radial outward fill)) causes this beautiful, organic sort of pattern to emerge.
With pop(0) you have a queue, you always take out the oldest thing in it, and so you get breadth-first search.
Instead you're doing pop(0) then pop(1) then pop(2), etc., which means you're taking out "every other" entry from the queue. (Until the popping overtakes the adding, which happens around about the time when a typical newly explored pixel generates fewer than 2 new neighbours to explore, by which time most of the interesting pattern generation has already happened.)
Now, when any pixel is processed its (not-yet-visited) neighbours get pushed consecutively. That means that when the exploration process reaches them it'll only explore one or two of them. In the usual "early" case there are three such neighbours; half the time one will get explored, half the time two will. The other neighbours get left behind until the exploration wraps (i.e., "step" passes the end of the queue), which doesn't happen for ages.
Hence the branching tree structure you see: right at the start we explore only two of the starting pixel's four neighbours, and the other two get left behind; so now we have two growing "tips", and when we process each one we either grow it one step further or split it two ways. And we don't return to the other neighbours for ages, so the tree grows basically until it fills the available space before the gaps start getting filled in.
(There are plenty of details not explained by the above. More thought required.)
http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
Also this link is referenced in the code:
You have a sticky pixel, and send it on a random walk. When it hits another pixel it sticks, and you generate another sticky pixel.
edit: Here's a video someone else created of a similar looking situation http://www.youtube.com/watch?v=j-1uotbxrcc
>This is a strange flood-fill algorithm I stumbled upon a while back and I have no idea why it does its thing like it does.
>...take a look, and if you know what's going on, let me know.
(yes I've read the book and mostly agree with that review)
But still he deserve some recognition, afterall he is the first bringing AI to the masses with Alfa, and helped some million researcher's life with Mathematica. And, 10 years after NKS, these are somehow good results -> http://blog.stephenwolfram.com/2012/05/its-been-10-years-wha... ...
You can judge people from many different perspectives, but when it comes to "getting things done", you should step back and congratulate him. again, IMHO
and
but when it comes to "getting things done", you should step back and congratulate him
My first words were "it's a great primer", followed with a suggestion for how to get the most from the work.
I'm not trying to downplay Wolfram's other work either, just pointing out that there are issues and grains of salt to take with this particular work.