'******************************************************************************
'Subject: Rudy Rucker's Laplacian rug rule:
' purple hazed bubbling lava.
'Author : Sjoerd.J.Schaper
'Date : 02-11-2006
'Code : all QBasic's, FreeBasic extendable
'Keys : [Esc] quit program
' [Enter] for a unicolor grid
' [Tab] break four-fold symmetry
' [Backspc] seed with random states
' [Space] freeze
' press any other key to shake the grid
'******************************************************************************
'This program is copyright (c) 2006 by the author. It is made available as is,
'and no warranty - about the program, its performance, or its conformity to any
'specification - is given or implied. It may be used, modified, and distributed
'freely, as long as the original author is credited as part of the final work.
'******************************************************************************
REM $STATIC
DEFINT A-Z
DECLARE SUB populate (t)
'display the automaton at time t
DECLARE SUB evaluate ()
'apply the rug rule
DECLARE FUNCTION mix ()
'mix 8-bit colours
DECLARE FUNCTION unigrid ()
'set a unicolor grid
DECLARE SUB mutate ()
'change a single cell
DECLARE FUNCTION rndstat ()
'seed with random states
CONST MODE = 13, dW = 320, dH = 200
' set screenmode, width, height
'CONST MODE = 18, dW = 640, dH = 480 ' FreeBasic only
CONST MAX = 127, nn = MAX * MAX - 1 ' Must be odd!
' maximum grid size 127 for QBasic 1.0
DIM SHARED c(0 TO nn, 1) ' cell indices
DIM SHARED LR, sw ' Laplacian/ generation switch
RANDOMIZE TIMER
LR = -1
t = 0
DO
populate t
t = t + 1
evaluate
LR = -1
g$ = INKEY$
IF g$ <> "" THEN
SELECT CASE ASC(g$)
CASE 8
t = rndstat ' scatter
CASE 9
mutate ' flip
CASE 13
t = unigrid ' reset
CASE 27
EXIT DO ' quit
CASE 32
LOCATE 4, 1: PRINT t;
LOCATE 8, 2: PRINT "0 ";
SLEEP ' freeze
CASE ELSE
LR = 0 ' shake
END SELECT
WHILE INKEY$ <> "": WEND
END IF
LOOP
SYSTEM
SUB evaluate STATIC
IF NOT fl THEN
DIM a(3), b(3): fl = -1
a(0) = 1: a(2) = -a(0) ' E,W
a(1) = MAX: a(3) = -a(1) ' S,N
b(0) = MAX + 1: b(2) = -b(0) ' SE,NW
b(1) = MAX - 1: b(3) = -b(1) ' SW,NE
END IF
FOR r = 1 TO MAX - 2
FOR k = r * MAX + 1 TO (r + 1) * MAX - 2
sa = 0: sb = 10 ' (round up)
FOR t = 0 TO 3 ' sum cell states
sa = sa + c(k + a(t), sw)
sb = sb + c(k + b(t), sw)
NEXT t
IF LR THEN
t = (sa * 4 + sb) \ 20 ' solution to Laplacian
ELSE
t = sa - 4 * c(k, sw) + 1023 ' disturb
END IF
c(k, 1 - sw) = (t + 1) AND 255 ' update cell
NEXT k
NEXT r
sw = 1 - sw ' switch generations
END SUB
FUNCTION mix
DIM col(255) AS LONG
DIM cmp(2, 1), df(2) AS SINGLE
pi! = 4 * ATN(1)
wo! = pi! / 255 * 9.618 ' velocity
'blue component ranges
cmp(0, 0) = 35
cmp(0, 1) = 45
df(0) = 0
'green
cmp(1, 0) = 0
cmp(1, 1) = 58
df(1) = wo! * .66
'red
cmp(2, 0) = 20
cmp(2, 1) = 63
df(2) = -wo!
col(0) = &HA0004
FOR t = 0 TO 2
c0 = cmp(t, 0)
dc = cmp(t, 1) - c0
FOR k = 1 TO 255 ' colour mixer
s! = SIN(df(t) + k * wo!)
c1 = c0 + CINT(s! * s! * dc)
col(k) = col(k) * 256 + c1
NEXT k
NEXT t
PALETTE USING col(0)
mix = CINT(pi! / (2 * wo!))
END FUNCTION
SUB mutate
x = (MAX - 1) \ 2 ' axial cell
y = 1 + INT(RND * (MAX - 2))
k = y * MAX + x
c(k, sw) = INT(RND * 256)
END SUB
SUB populate (gen)
STATIC fl, g0, t0!
IF gen = 0 THEN
IF NOT fl THEN
SCREEN MODE ' 8 bpp
sw = mix: COLOR sw
r = 1 + dW * .25 * .618
s = r + dW * .75 - 1: fl = -1
VIEW (r, 1)-(s, dH - 2), , sw
LOCATE 3, 2: PRINT "gen.";
LOCATE 7, 2: PRINT "v*10";
sw = unigrid ' initialize
END IF
LOCATE 4, 2: PRINT " ";
g0 = 0: t0! = TIMER: d! = .5
WINDOW SCREEN (d!, d!)-(MAX - 1 - d!, MAX - 1 - d!)
LINE (0, 0)-(MAX - 1, MAX - 1), 0, BF
END IF
d! = .491
WAIT &H3DA, 8
FOR k = 0 TO nn ' update CA
IF c(k, sw) XOR c(k, 1 - sw) THEN
y = k \ MAX
x = k - y * MAX
LINE (x - d!, y - d!)-(x + d!, y + d!), c(k, sw), BF
END IF
NEXT k
dt! = TIMER - t0!
IF dt! > 1 THEN
LOCATE 4, 1: PRINT gen;
LOCATE 8, 1: PRINT CINT(10 * (gen - g0) / dt!); " ";
g0 = gen: t0! = TIMER
END IF
END SUB
FUNCTION rndstat
k = unigrid ' for border bias
FOR r = 1 TO MAX - 2 ' primordial soup
FOR s = 1 TO MAX - 2
k = r * MAX + s
c(k, sw) = INT(RND * 256)
NEXT s
NEXT r
rndstat = 0
END FUNCTION
FUNCTION unigrid
col = INT(RND * 256)
FOR k = 0 TO nn ' clear
c(k, 0) = col: c(k, 1) = col
NEXT k
unigrid = 0
END FUNCTION