' Cellular Automata — 1D cellular automaton (Rule 30, 90, 110, etc.)
#COMPILE EXE
#DIM ALL

FUNCTION PBMAIN() AS LONG
    LOCAL grid(10000) AS LONG
    LOCAL nextGrid(10000) AS LONG
    LOCAL width AS LONG
    LOCAL generations AS LONG
    LOCAL i AS LONG
    LOCAL j AS LONG
    LOCAL left AS LONG
    LOCAL center AS LONG
    LOCAL right AS LONG
    LOCAL rule AS LONG
    LOCAL patternIdx AS LONG
    LOCAL ruleVal AS LONG
    LOCAL lineStr AS STRING
    LOCAL genStr AS STRING
    LOCAL onesCount AS LONG
    width = 79
    generations = 40
    PRINT "============================================"
    PRINT "      1D CELLULAR AUTOMATA"
    PRINT "============================================"
    PRINT ""
    PRINT "Rule 30 (chaotic pattern):"
    PRINT ""
    rule = 30
    FOR i = 0 TO width - 1
        grid(i) = 0
    NEXT i
    grid(width / 2) = 1
    FOR j = 0 TO generations
        lineStr = ""
        onesCount = 0
        FOR i = 0 TO width - 1
            IF grid(i) = 1 THEN
                lineStr = lineStr + "#"
                onesCount = onesCount + 1
            ELSE
                lineStr = lineStr + "."
            END IF
        NEXT i
        PRINT lineStr
        FOR i = 0 TO width - 1
            left = 0
            center = grid(i)
            right = 0
            IF i > 0 THEN
                left = grid(i - 1)
            END IF
            IF i < width - 1 THEN
                right = grid(i + 1)
            END IF
            patternIdx = left * 4 + center * 2 + right
            ruleVal = 0
            IF patternIdx = 7 THEN
                ruleVal = (rule AND 1)
            END IF
            IF patternIdx = 6 THEN
                ruleVal = (rule AND 2) / 2
            END IF
            IF patternIdx = 5 THEN
                ruleVal = (rule AND 4) / 4
            END IF
            IF patternIdx = 4 THEN
                ruleVal = (rule AND 8) / 8
            END IF
            IF patternIdx = 3 THEN
                ruleVal = (rule AND 16) / 16
            END IF
            IF patternIdx = 2 THEN
                ruleVal = (rule AND 32) / 32
            END IF
            IF patternIdx = 1 THEN
                ruleVal = (rule AND 64) / 64
            END IF
            IF patternIdx = 0 THEN
                ruleVal = (rule AND 128) / 128
            END IF
            nextGrid(i) = ruleVal
        NEXT i
        FOR i = 0 TO width - 1
            grid(i) = nextGrid(i)
        NEXT i
    NEXT j
    PRINT ""
    PRINT "============================================"
    PRINT "     RULE 90 (Sierpinski triangle)"
    PRINT "============================================"
    PRINT ""
    rule = 90
    FOR i = 0 TO width - 1
        grid(i) = 0
    NEXT i
    grid(width / 2) = 1
    FOR j = 0 TO generations
        lineStr = ""
        FOR i = 0 TO width - 1
            IF grid(i) = 1 THEN
                lineStr = lineStr + "#"
            ELSE
                lineStr = lineStr + " "
            END IF
        NEXT i
        PRINT lineStr
        FOR i = 0 TO width - 1
            left = 0
            center = grid(i)
            right = 0
            IF i > 0 THEN
                left = grid(i - 1)
            END IF
            IF i < width - 1 THEN
                right = grid(i + 1)
            END IF
            patternIdx = left * 4 + center * 2 + right
            ruleVal = 0
            IF patternIdx = 7 THEN
                ruleVal = (rule AND 1)
            END IF
            IF patternIdx = 6 THEN
                ruleVal = (rule AND 2) / 2
            END IF
            IF patternIdx = 5 THEN
                ruleVal = (rule AND 4) / 4
            END IF
            IF patternIdx = 4 THEN
                ruleVal = (rule AND 8) / 8
            END IF
            IF patternIdx = 3 THEN
                ruleVal = (rule AND 16) / 16
            END IF
            IF patternIdx = 2 THEN
                ruleVal = (rule AND 32) / 32
            END IF
            IF patternIdx = 1 THEN
                ruleVal = (rule AND 64) / 64
            END IF
            IF patternIdx = 0 THEN
                ruleVal = (rule AND 128) / 128
            END IF
            nextGrid(i) = ruleVal
        NEXT i
        FOR i = 0 TO width - 1
            grid(i) = nextGrid(i)
        NEXT i
    NEXT j
    PRINT ""
    PRINT "============================================"
    PRINT "     RULE 110 (Turing complete)"
    PRINT "============================================"
    PRINT ""
    rule = 110
    FOR i = 0 TO width - 1
        grid(i) = 0
    NEXT i
    grid(width / 2) = 1
    grid(width / 2 + 1) = 1
    grid(width / 2 + 2) = 1
    FOR j = 0 TO generations
        lineStr = ""
        FOR i = 0 TO width - 1
            IF grid(i) = 1 THEN
                lineStr = lineStr + "#"
            ELSE
                lineStr = lineStr + "."
            END IF
        NEXT i
        PRINT lineStr
        FOR i = 0 TO width - 1
            left = 0
            center = grid(i)
            right = 0
            IF i > 0 THEN
                left = grid(i - 1)
            END IF
            IF i < width - 1 THEN
                right = grid(i + 1)
            END IF
            patternIdx = left * 4 + center * 2 + right
            ruleVal = 0
            IF patternIdx = 7 THEN
                ruleVal = (rule AND 1)
            END IF
            IF patternIdx = 6 THEN
                ruleVal = (rule AND 2) / 2
            END IF
            IF patternIdx = 5 THEN
                ruleVal = (rule AND 4) / 4
            END IF
            IF patternIdx = 4 THEN
                ruleVal = (rule AND 8) / 8
            END IF
            IF patternIdx = 3 THEN
                ruleVal = (rule AND 16) / 16
            END IF
            IF patternIdx = 2 THEN
                ruleVal = (rule AND 32) / 32
            END IF
            IF patternIdx = 1 THEN
                ruleVal = (rule AND 64) / 64
            END IF
            IF patternIdx = 0 THEN
                ruleVal = (rule AND 128) / 128
            END IF
            nextGrid(i) = ruleVal
        NEXT i
        FOR i = 0 TO width - 1
            grid(i) = nextGrid(i)
        NEXT i
    NEXT j
    PRINT ""
    PRINT "============================================"
    PRINT "     RANDOM INITIAL CONDITION (Rule 30)"
    PRINT "============================================"
    PRINT ""
    rule = 30
    FOR i = 0 TO width - 1
        grid(i) = (i * 7 + 3) MOD 2
    NEXT i
    FOR j = 0 TO 20
        lineStr = ""
        FOR i = 0 TO width - 1
            IF grid(i) = 1 THEN
                lineStr = lineStr + "#"
            ELSE
                lineStr = lineStr + " "
            END IF
        NEXT i
        PRINT lineStr
        FOR i = 0 TO width - 1
            left = 0
            center = grid(i)
            right = 0
            IF i > 0 THEN
                left = grid(i - 1)
            END IF
            IF i < width - 1 THEN
                right = grid(i + 1)
            END IF
            patternIdx = left * 4 + center * 2 + right
            ruleVal = 0
            IF patternIdx = 7 THEN
                ruleVal = (rule AND 1)
            END IF
            IF patternIdx = 6 THEN
                ruleVal = (rule AND 2) / 2
            END IF
            IF patternIdx = 5 THEN
                ruleVal = (rule AND 4) / 4
            END IF
            IF patternIdx = 4 THEN
                ruleVal = (rule AND 8) / 8
            END IF
            IF patternIdx = 3 THEN
                ruleVal = (rule AND 16) / 16
            END IF
            IF patternIdx = 2 THEN
                ruleVal = (rule AND 32) / 32
            END IF
            IF patternIdx = 1 THEN
                ruleVal = (rule AND 64) / 64
            END IF
            IF patternIdx = 0 THEN
                ruleVal = (rule AND 128) / 128
            END IF
            nextGrid(i) = ruleVal
        NEXT i
        FOR i = 0 TO width - 1
            grid(i) = nextGrid(i)
        NEXT i
    NEXT j
    PRINT ""
    PRINT "Cellular automata demonstration complete"
    FUNCTION = 0
END FUNCTION
