A script to simulate odd 1D Wolfram cellular automata
Posted: August 30th, 2017, 3:21 am
***EDIT: THIS SCRIPT IS OUTDATED, SEE SECOND POST FOR MUCH-IMPROVED VERSION***
I barely have any experience with Lua, so this no doubt contains a ton of inefficiencies and unnecessary nonsense, but I've attempted to create a script that can simulate any 1D Wolfram rule in a bounded universe in Golly, including odd-numbered ones:
The special quiescent state 1 is due to the fact that RuleLoader won't accurately simulate B0 in rule tables.
As I said, there are surely lots of ways this could be improved. One rather obvious thing is that when the script completes, it spits out a bunch of copies of this error message:I have no idea why this happens, especially since the script seems to successfully generate the correct pattern each time. It seems to happen completely at random: if I run it for only 5 generations, regardless of the rule used, it'll sometimes give no errors, sometimes give me 1, or sometimes give me 2 or 3, even running with the same parameters every time.
If anyone knows of any ways to fix that issue or improve on the script in general (for example, not requiring that stupid copy-paste-advance loop), please let me know.
(Also note that I've tested this on 3.0b2 on Windows 10, and haven't made any attempts to test it on other versions.)
I barely have any experience with Lua, so this no doubt contains a ton of inefficiencies and unnecessary nonsense, but I've attempted to create a script that can simulate any 1D Wolfram rule in a bounded universe in Golly, including odd-numbered ones:
Code: Select all
-- Creates a rule file for 1D elementary cellular automata, and then optionally runs
-- it for a given number of generations in a torus.
-- Note: This will create a .rule file in your Rules folder, specified in Preferences.
-- The rules can be run by themselves when the background is state 1, but the script
-- will run them closer to how Golly simulates even rules.
-- Also note that while this script does support even-numbered elementary rules, Golly
-- natively supports these, so it's mostly pointless to use it with even rules.
local g = golly()
local clipboard = g.getclipstr()
-- Decimal to binary converter function from http://bit.ly/2wQ9yqr because I have
-- absolutely no idea where to begin making my own
local function tobits(num,bits)
-- returns a table of bits, most significant first.
bits = bits or math.max(1, select(2, math.frexp(num)))
local t = {} -- will contain the bits
for b = bits, 1, -1 do
t[b] = math.fmod(num, 2)
num = math.floor((num - t[b]) / 2)
end
return t
end
local rule = tonumber(g.getstring("Enter 1D rule (0 to 255).\n\nRule \"W-<#>\" will be created, and overwritten\nif it exists.", "73", "Set rule"))
local rulename = "W-"..tostring(rule)
if rule == nil or rule < 0 or rule > 255 then
g.exit("Invalid rule specified.")
end
local rulestring = tobits(rule, 8)
local a, b, c, d, e, f, h, i = table.unpack(rulestring)
local function a1(x)
x = tostring(tonumber(x)+1)
return x
end
local trans = "1,1,1,"..a1(i).."\n1,1,2,"..a1(h).."\n2,1,1,"..a1(f).."\n2,1,2,"..a1(e).."\n1,2,1,"..a1(d).."\n1,2,2,"..a1(c).."\n2,2,1,"..a1(b).."\n2,2,2,"..a1(a).."\n"
local comment = "Automatically generated by a Lua script.\nThe rule will only work when the background state is 1."
local rulefile = "@RULE "..rulename.."\n\n"..comment.."\n\n@TABLE\n\nn_states:3\nneighborhood:oneDimensional\nsymmetries:none\n\n"..trans.."\n@COLORS\n1 0 0 0\n2 255 255 255"
local ruledir = g.getdir("rules")
file = io.open(ruledir..rulename..".rule", "w")
file:write(rulefile)
file:close()
g.show("Rule \""..rulename.."\" created.")
local patternrect = g.getrect()
local pattern
local usepattern = g.getstring("Enter 1 to run the current pattern; anything\nelse will start with a single cell.\n\nIf doing this, the pattern should be 1 cell high\nand roughly centered on the y-axis.\n\n(Note: Use state 0 as the background state for this.)", "", "Use current pattern?")
if usepattern == "1" then
local rect = g.getrect()
if rect[4] ~= 1 then
g.warn("Pattern is either empty or more than one cell high.\nDefaulting to single cell.")
pattern = {0, 0, 2}
else
pattern = g.getcells(g.getrect())
end
else
pattern = {0, 0, 2}
end
local width = tonumber(g.getstring("Set width of pattern generation:", "500", "Set width"))
local height = math.tointeger(g.getstring("Set number of generations to run:", "250") + 1) -- +1 because top is gen 0
g.setrule(rulename..":T"..tostring(width)..","..tostring(height))
g.new(rulename)
local rect = {math.ceil(-g.getwidth() / 2), math.ceil(-g.getheight() / 2), g.getwidth(), g.getheight()}
for j = rect[2], rect[2] + rect[4] - 1 do
for k = rect[1], rect[1] + rect[3] - 1 do
g.setcell(k, j, 1)
end
end
g.putcells(pattern, 0, rect[2] - pattern[2])
-- there has got to be a better way to do this absolute mess of a thing but i
-- can't think of anything right now
g.select({rect[1], rect[2], rect[3], 1})
for l = rect[2], rect[2]+rect[4] - 2 do
g.copy()
g.paste(rect[1], l+1, "or")
g.select({rect[1], l+1, rect[3], 1})
g.advance(0, 1)
end
g.select({})
g.fit()
g.setclipstr(clipboard)As I said, there are surely lots of ways this could be improved. One rather obvious thing is that when the script completes, it spits out a bunch of copies of this error message:
Code: Select all
Failed to get data from the clipboard (error -2147221040: openClipboard Failed)If anyone knows of any ways to fix that issue or improve on the script in general (for example, not requiring that stupid copy-paste-advance loop), please let me know.
(Also note that I've tested this on 3.0b2 on Windows 10, and haven't made any attempts to test it on other versions.)