summaryrefslogtreecommitdiff
path: root/eca.lua
blob: 6c49e8d376d3eeeb649a07c612c56938899d0f0b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
--
--------------------------------------------------------------------------------
--         FILE:  eca.lua
--        USAGE:  ./eca.lua 
--  DESCRIPTION:  drawing elementary cellular automata
--      OPTIONS:  ---
-- REQUIREMENTS:  ---
--         BUGS:  ---
--        NOTES:  ---
--       AUTHOR:  Philipp Gesang (Phg), <megas.kapaneus@gmail.com>
--      COMPANY:  
--      VERSION:  1.0
--      CREATED:  14/08/10 19:43:35 CEST
--     REVISION:  ---
--------------------------------------------------------------------------------
--

require "life"

local help = gol.helpers

local C, Cs, Ct, P, R, S, match = lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.P, lpeg.R, lpeg.S, lpeg.match


eca = {}


function eca.parse_file (fname)
    local f = assert(io.open(fname, "r"), "No such file: "..fname..".")
    local init = f:read("*all")
    f:close()

    return help.strip(init)
end

function eca.to_base(number, base)
    local alphabet, result, cnt, remainder = "0123456789abcdef", "", 0                   
    while number > 0 do
        cnt = cnt + 1 
        number, remainder = math.floor(number / base), (number % base) + 1 
        result = string.sub(alphabet, remainder, remainder) .. result
    end 
    return result
end

function eca.gen_rule(nr)
    local rules = {}
    local states = { "111", "110", "101", "100", "011", "010", "001", "000" }
    
    nr = string.format("%8s",eca.to_base(nr, 2)):gsub(" ", "0")

    local n = 1
    while n <= #states  do
        rules[states[n]] = nr:sub(n,n)
        n = n + 1
    end

    return rules
end

function eca.next_line(from, rule)
    local new = ""
    from = "0"..from.."0"  -- assume dead borders
    --from = string.format("0%s0", from)

    local cell = C(S"01")
    local cells= Ct(cell * #(cell * cell)) / function (t)
        local three = t[1]..t[2]..t[3]
        new = new .. rule[three]
    end
    lpeg.match(cells^1, from)
    return new
end

function eca.gen_frame(from, lines, rule)
    local new = { [1] = from }

    local cnt = 1
    local tmp
    repeat
        --print(cnt)
        tmp = eca.next_line(from, rule)
        table.insert( new, tmp )
        from = tmp
        cnt = cnt + 1
    until cnt == lines
    --for i,j in ipairs(new) do
        --print (string.format("%3s >> %s",i,j))
    --end
    return eca.next_line(tmp, rule), new
end

function eca.successive (current)
    --if not current then print("NOPE")return 1 end
    --local current = current or {}

    local thisframe
    current.from, thisframe = eca.gen_frame(current.from, current.framesize, current.rule)
    if not context then -- cli invocation
        for _,j in ipairs(thisframe) do 
            io.write(j:gsub("0","ยท"):gsub("1","O").."\n") 
        end
    else
        
    end
    return 0
end

return eca