Evo

A few days ago Mathies published two articles about a nice artistic screensaver called drug test on his website. In the second article explaining some details he attributed the basic inspiration for his work to an old QBasic program I wrote. I used this as an occasion to bring Evo, the script he referred to, back to life in a web browser.

Background

The Evo file I found was last changed on January 2nd, 2002. However, the relevant code is older, most likely few years older.

When looking at the inspiration for Evo, things come full circle: It came from Mathies, or from his inaccurate implementation of Conway’s Game of Life respectively. If I remember this correctly, his fault was to not render each generation completely based on the whole previous generation in the “game”. Instead he used just one grid and updated one pixel after the other, row by row and column by column, always based on the current state of the grid.

This didn’t work out so well, I thought, and Evo was my approach to doing something different yet similar then. A major difference is that pixels are chosen randomly to be updated in Evo, so it is non-deterministic – provided that a truly non-deterministic random number generator is used. Still, the rules lead to “stronger” and “weaker” colors and, although the development differs in details, the outcome is usually the same as long as the rules aren’t changed.

Evo has neither a notable artistic quality nor the intriguing fundamental mathematics to be found in Conway’s Game of Life. Nevertheless it’s interesting to see how larger structures form from a fine-grained random initial configuration, how the rules usually lead to red domination after many iterations, going through clearly distinguishable phases before, and how some colors grow well feeding on others, partially to be wiped out themselves when they have consumed all their nourishment.

Evo in the browser

Here is my new implementation: Evo in JavaScript. I recommend to zoom in using your browser’s build-in zoom function. Check the checkbox to run Evo and uncheck it to pause. … It doesn’t work? Well, it uses HTML5 code. Older browsers and current MS Internet Explorers might not yet be able to interpret it correctly. Current versions of Firefox, Opera and Safari should be able to display Evo though.

The source code is not beautiful and mostly not object-oriented (which some JavaScript coders might consider sinful). It’s modeled on the original BASIC code which I wrote without having attended many or even any programming lessons and without knowledge of technical documentation, standards etc. You are free to do whatever you want to do with the source code, I hereby release it into the public domain.

The original code

Here is the relevant part of the original code from the BASIC file I found. It is old. I was young. It wasn’t meant to be published. Please do not understand this as an example of good programming.

'DEKLARATION
'-----------

DECLARE FUNCTION NC% (FARBE AS INTEGER)
DIM E AS INTEGER, K AS INTEGER, N AS INTEGER, X AS INTEGER, Y AS INTEGER
DIM SHARED F(1 TO 8) AS INTEGER

'FARBEN (WERTE MÜSSEN GRÖßER ALS 8 SEIN)
'------

F(1) = 104
F(2) = 120
F(3) = 124
F(4) = 112
F(5) = 108
F(6) = 115
F(7) = 26
F(8) = 20

'START
'-----

RANDOMIZE TIMER

CLS
SCREEN 13
SLEEP .6

COLOR 11
LOCATE 1, 2
PRINT "INITIALISIERUNG ";

VIEW SCREEN (97, 37)-(222, 162)
FOR N = 1 TO 32000
 PSET (CINT(RND * 126) + 97, CINT(RND * 126) + 37), NC(CINT(RND * 7) + 1)
NEXT N: SOUND 1000, 1

LOCATE 24, 1
COLOR 9
PRINT "VIEL SPAß BEIM ZUSEHEN! <ESC> = BEENDEN.";
LOCATE 1, 2
PRINT STRING$(15, CHR$(0))

DO
 K = 0
 X = CINT(RND * 125) + 97
 Y = CINT(RND * 125) + 37
 E = NC(POINT(X, Y))
 IF NC(POINT(X - 1, Y)) < E THEN PSET (X - 1, Y), NC(E): K = K + 1
 IF NC(POINT(X - 1, Y - 1)) < E OR NC(POINT(X - 1, Y - 1)) = E + 1 THEN PSET (X - 1, Y - 1), NC(E): K = K + 1
 IF NC(POINT(X, Y - 1)) < E THEN PSET (X, Y - 1), NC(E): K = K + 1
 IF NC(POINT(X + 1, Y - 1)) < E OR NC(POINT(X + 1, Y - 1)) = E + 1 THEN PSET (X + 1, Y - 1), NC(E): K = K + 1
 IF NC(POINT(X + 1, Y)) < E THEN PSET (X + 1, Y), NC(E): K = K + 1
 IF NC(POINT(X + 1, Y + 1)) < E OR NC(POINT(X + 1, Y + 1)) = E + 1 THEN PSET (X + 1, Y + 1), NC(E): K = K + 1
 IF NC(POINT(X, Y + 1)) < E THEN PSET (X, Y + 1), NC(E): K = K + 1
 IF NC(POINT(X - 1, Y + 1)) < E OR NC(POINT(X - 1, Y + 1)) = E + 1 THEN PSET (X - 1, Y + 1), NC(E): K = K + 1
 IF E < 8 AND K = 0 THEN CIRCLE (X, Y), SQR(SQR((VAL(RIGHT$(TIME$, 1)) + 1) * E ^ 3)), NC(E)
 IF E = 8 AND K < 5 THEN LINE (X - K, Y - K)-(X + K, Y + K), NC(8), B: K = 8
 IF K < E - 1 THEN PSET (X, Y), NC(CINT(RND * (E + 1)) + 1)
LOOP UNTIL INKEY$ = CHR$(27)

FUNCTION NC% (FARBE AS INTEGER)

IF FARBE < 9 AND FARBE > 0 THEN NC = F(FARBE): EXIT FUNCTION

SELECT CASE FARBE
 CASE F(1): NC = 1
 CASE F(2): NC = 2
 CASE F(3): NC = 3
 CASE F(4): NC = 4
 CASE F(5): NC = 5
 CASE F(6): NC = 6
 CASE F(7): NC = 7
 CASE F(8): NC = 8
END SELECT

END FUNCTION

You might come to the conclusion that the function NC and the array F are rather confusing and not really necessary here, because they are used to map eight CGA colors to very similar looking colors from the VGA palette and back. Well, I wanted to be able to change the colors easily.