Sorry for doublepost, but... the script is done! if a bit clunky.
Don't worry about the warning, that was just a debug and is kind of handy for canceling if you forgot a transition.
Code: Select all
local g = golly()
local hensel_masks = {
["0"] = "b1,b2,b3,b4,b5,b6,b7,b8",
["1c"] = "b1,1,b2,b3,b4,b5,b6,b7",
["1e"] = "1,b1,b2,b3,b4,b5,b6,b7",
["2c"] = "b1,1,b2,1,b3,b4,b5,b6",
["2e"] = "1,b1,1,b2,b3,b4,b5,b6",
["2k"] = "1,b1,b2,1,b3,b4,b5,b6",
["2a"] = "1,1,b2,b3,b4,b5,b6,b7",
["2i"] = "1,b1,b2,b3,1,b4,b5,b6",
["2n"] = "b1,1,b2,b3,b4,1,b5,b6",
["3c"] = "b1,1,b2,1,b3,1,b4,b5",
["3e"] = "1,b1,1,b2,1,b3,b4,b5",
["3k"] = "1,b1,1,b2,b3,1,b4,b5",
["3a"] = "1,1,1,b2,b3,b4,b5,b6",
["3i"] = "b1,1,1,1,b2,b3,b4,b5",
["3n"] = "1,1,b1,1,b2,b3,b4,b5",
["3y"] = "1,b1,b2,1,b3,1,b4,b5",
["3q"] = "1,1,b1,b2,b3,1,b4,b5",
["3j"] = "1,b1,1,1,b2,b3,b4,b5",
["3r"] = "1,b1,b2,1,1,b3,b4,b5",
["4c"] = "b1,1,b2,1,b3,1,b4,1",
["4e"] = "1,b1,1,b2,1,b3,1,b4",
["4k"] = "1,b1,1,1,b2,1,b3,b4",
["4a"] = "1,1,1,1,b2,b3,b4,b5",
["4i"] = "1,1,b1,1,1,b2,b3,b4",
["4n"] = "b1,1,1,1,b2,1,b3,b4",
["4y"] = "1,1,b1,1,b2,1,b3,b4",
["4q"] = "1,1,1,b1,b2,1,b3,b4",
["4j"] = "1,b1,1,b2,1,1,b3,b4",
["4r"] = "1,1,1,b1,1,b2,b3,b4",
["4t"] = "1,b1,b2,1,1,1,b3,b4",
["4w"] = "b1,1,1,b2,1,1,b3,b4",
["4z"] = "1,1,b1,b2,1,1,b3,b4",
["5c"] = "1,b1,1,b2,1,b3,1,1",
["5e"] = "b1,1,b2,1,b3,1,1,1",
["5k"] = "b1,1,b2,1,1,b3,1,1",
["5a"] = "b2,b3,b4,1,1,1,1,1",
["5i"] = "1,b1,b2,b3,1,1,1,1",
["5n"] = "b1,b2,1,b3,1,1,1,1",
["5y"] = "b1,1,1,b2,1,b3,1,1",
["5q"] = "b1,b2,1,1,1,b3,1,1",
["5j"] = "b1,1,b2,b3,1,1,1,1",
["5r"] = "b1,1,1,b2,b3,1,1,1",
["6c"] = "1,b1,1,b2,1,1,1,1",
["6e"] = "b1,1,b2,1,1,1,1,1",
["6k"] = "b1,1,1,b2,1,1,1,1",
["6a"] = "b2,b3,1,1,1,1,1,1",
["6i"] = "b1,1,1,1,b2,1,1,1",
["6n"] = "1,b1,1,1,1,b2,1,1",
["7c"] = "1,b1,1,1,1,1,1,1",
["7e"] = "b1,1,1,1,1,1,1,1",
["8"] = "1,1,1,1,1,1,1,1",
}
local expansions = {
["0"] = {"0"},
["1"] = {"1c","1e"},
["2"] = {"2c","2e","2k","2a","2i","2n"},
["3"] = {"3c","3e","3k","3a","3i","3n","3y","3q","3j","3r"},
["4"] = {"4c","4e","4k","4a","4i","4n","4y","4q","4j","4r","4t","4w","4z"},
["5"] = {"5c","5e","5k","5a","5i","5n","5y","5q","5j","5r"},
["6"] = {"6c","6e","6k","6a","6i","6n"},
["7"] = {"7c","7e"},
["8"] = {"8"},
}
-- Utils
local function get_states(prefix)
if prefix == "B" then
return 2,1
elseif prefix == "S" then
return 1,1
elseif prefix == "A" then
return 0,2
elseif prefix == "R" then
return 2,2
else
error("Unknown prefix: "..tostring(prefix))
end
end
local function make_line(prefix, submask)
local begin_state, end_state = get_states(prefix)
local neighbors = hensel_masks[submask]
if not neighbors then
return "???"
end
return begin_state..","..neighbors..","..end_state
end
local function expand_token(prefix, num, letters, exclude)
local result = {}
local exclude_set = {}
if exclude and exclude ~= "" then
for i = 1,#exclude do
exclude_set[exclude:sub(i,i)] = true
end
end
if letters == "" then
if expansions[num] then
for _, sm in ipairs(expansions[num]) do
local last = sm:match("%a")
if not exclude_set[last] then
table.insert(result, prefix..sm)
end
end
else
table.insert(result, prefix..num)
end
else
local any_added = false
for i = 1,#letters do
local l = letters:sub(i,i)
if not exclude_set[l] then
table.insert(result, prefix..num..l)
any_added = true
end
end
if not any_added then
table.insert(result, prefix..num)
end
end
if #result == 0 then
table.insert(result, prefix..num)
end
return result
end
-- Collect all hensel transitions from rulestring
local function collect_tokens(rs)
local tokens = {}
local pos = 1
local last_prefix = nil
while pos <= #rs do
local char = rs:sub(pos,pos)
if char:match("[A-Z]") then
last_prefix = char
pos = pos + 1
elseif char:match("%d") then
local prefix = last_prefix
local digit = char
local letters = ""
local exclude = ""
local i = pos + 1
while i <= #rs do
local c = rs:sub(i,i)
if c:match("%d") or c:match("[A-Z]") or c == "/" then
break
elseif c == "-" then
local j = i+1
while j <= #rs do
local ec = rs:sub(j,j)
if ec:match("[A-Z%d/]") then
break
end
exclude = exclude .. ec
j = j + 1
i = j-1
end
break
else
letters = letters .. c
end
i = i + 1
end
local expanded_tokens = expand_token(prefix, digit, letters, exclude)
for _, t in ipairs(expanded_tokens) do
table.insert(tokens, t)
end
pos = i
else
pos = pos + 1
end
end
return tokens
end
-- Convert hensel transitions to ruletable lines
local function tokens_to_binaries(tokens)
local grouped = { B={}, S={}, A={}, R={} }
for _, token in ipairs(tokens) do
local pfx, sub = token:match("([A-Z])(.+)")
if pfx and sub then
local line = make_line(pfx, sub)
if grouped[pfx] then
table.insert(grouped[pfx], line)
end
end
end
local all_lines = {}
for _, pfx in ipairs({"B","S","A","R"}) do
if #grouped[pfx] > 0 then
local header = "###"..(
pfx=="B" and "Birth" or
pfx=="S" and "Survival" or
pfx=="A" and "Activate" or
pfx=="R" and "Remain"
).."###"
table.insert(all_lines, header)
for _, l in ipairs(grouped[pfx]) do table.insert(all_lines, l) end
end
end
return all_lines
end
-- Main
local rulestring = g.getclipstr()
if not rulestring or rulestring == "" then
g.show("Clipboard is empty!")
return
end
local tokens = collect_tokens(rulestring)
local debug_grouped = { B={}, S={}, A={}, R={} }
for _, token in ipairs(tokens) do
local pfx = token:sub(1,1)
if debug_grouped[pfx] then
table.insert(debug_grouped[pfx], token)
end
end
local debug_msg = {}
for _, pfx in ipairs({"B","S","A","R"}) do
if #debug_grouped[pfx] > 0 then
table.insert(debug_msg, "###"..(
pfx=="B" and "Birth" or
pfx=="S" and "Survival" or
pfx=="A" and "Activate" or
pfx=="R" and "Remain"
).."###")
table.insert(debug_msg, table.concat(debug_grouped[pfx], ", "))
end
end
g.warn("Expanded tokens:\n"..table.concat(debug_msg,"\n"))
local result_lines = tokens_to_binaries(tokens)
local header = "@RULE "..rulestring.."\n\n@TABLE\nn_states: 3\nneighborhood: Moore\nsymmetries: rotate4reflect\n"
header = header .. "var a = {0,1,2}\n"
for i = 1,8 do
header = header .. "var a"..i.." = a\n"
end
header = header .. "var b = {0,2}\n"
for i = 1,8 do
header = header .. "var b"..i.." = b\n"
end
local decompose_line = "1, a1, a2, a3, a4, a5, a6, a7, a8, 2"
local die_line = "a, a1, a2, a3, a4, a5, a6, a7, a8, 0"
local out = header..table.concat(result_lines,"\n").."\n"..decompose_line.."\n"..die_line
g.setclipstr(out)
g.show("Ruletable copied to clipboard!\nTotal tokens: "..#tokens.."\nTotal lines: "..#result_lines)
Code: Select all
x = 11, y = 46, rule = B2cei3eijy4cejkqrw5-ai6-a7c/S1c2ae3eijnr4-acqt5cenry6-ae7e8/A12ca4t5i/R1234t5i
3.3A$3.A.A$3.3A13$3.3A$3.A.A$3.3A5$9.B$8.A.A$8.3A$8.3A17$.B$A.A$3A$3A
!
@RULE B2cei3eijy4cejkqrw5-ai6-a7c/S1c2ae3eijnr4-acqt5cenry6-ae7e8/A12ca4t5i/R1234t5i
@TABLE
n_states: 3
neighborhood: Moore
symmetries: rotate4reflect
var a = {0,1,2}
var a1 = a
var a2 = a
var a3 = a
var a4 = a
var a5 = a
var a6 = a
var a7 = a
var a8 = a
var b = {0,2}
var b1 = b
var b2 = b
var b3 = b
var b4 = b
var b5 = b
var b6 = b
var b7 = b
var b8 = b
###Birth###
2,b1,1,b2,1,b3,b4,b5,b6,1
2,1,b1,1,b2,b3,b4,b5,b6,1
2,1,b1,b2,b3,1,b4,b5,b6,1
2,1,b1,1,b2,1,b3,b4,b5,1
2,b1,1,1,1,b2,b3,b4,b5,1
2,1,b1,1,1,b2,b3,b4,b5,1
2,1,b1,b2,1,b3,1,b4,b5,1
2,b1,1,b2,1,b3,1,b4,1,1
2,1,b1,1,b2,1,b3,1,b4,1
2,1,b1,1,b2,1,1,b3,b4,1
2,1,b1,1,1,b2,1,b3,b4,1
2,1,1,1,b1,b2,1,b3,b4,1
2,1,1,1,b1,1,b2,b3,b4,1
2,b1,1,1,b2,1,1,b3,b4,1
2,1,b1,1,b2,1,b3,1,1,1
2,b1,1,b2,1,b3,1,1,1,1
2,b1,1,b2,1,1,b3,1,1,1
2,b1,b2,1,b3,1,1,1,1,1
2,b1,1,1,b2,1,b3,1,1,1
2,b1,b2,1,1,1,b3,1,1,1
2,b1,1,b2,b3,1,1,1,1,1
2,b1,1,1,b2,b3,1,1,1,1
2,1,b1,1,b2,1,1,1,1,1
2,b1,1,b2,1,1,1,1,1,1
2,b1,1,1,b2,1,1,1,1,1
2,b1,1,1,1,b2,1,1,1,1
2,1,b1,1,1,1,b2,1,1,1
2,1,b1,1,1,1,1,1,1,1
###Survival###
1,b1,1,b2,b3,b4,b5,b6,b7,1
1,1,1,b2,b3,b4,b5,b6,b7,1
1,1,b1,1,b2,b3,b4,b5,b6,1
1,1,b1,1,b2,1,b3,b4,b5,1
1,b1,1,1,1,b2,b3,b4,b5,1
1,1,b1,1,1,b2,b3,b4,b5,1
1,1,1,b1,1,b2,b3,b4,b5,1
1,1,b1,b2,1,1,b3,b4,b5,1
1,1,b1,1,b2,1,b3,1,b4,1
1,1,b1,1,1,b2,1,b3,b4,1
1,1,1,b1,1,1,b2,b3,b4,1
1,b1,1,1,1,b2,1,b3,b4,1
1,1,1,b1,1,b2,1,b3,b4,1
1,1,b1,1,b2,1,1,b3,b4,1
1,1,1,1,b1,1,b2,b3,b4,1
1,b1,1,1,b2,1,1,b3,b4,1
1,1,1,b1,b2,1,1,b3,b4,1
1,1,b1,1,b2,1,b3,1,1,1
1,b1,1,b2,1,b3,1,1,1,1
1,b1,b2,1,b3,1,1,1,1,1
1,b1,1,1,b2,b3,1,1,1,1
1,b1,1,1,b2,1,b3,1,1,1
1,1,b1,1,b2,1,1,1,1,1
1,b1,1,1,b2,1,1,1,1,1
1,b1,1,1,1,b2,1,1,1,1
1,1,b1,1,1,1,b2,1,1,1
1,b1,1,1,1,1,1,1,1,1
1,1,1,1,1,1,1,1,1,1
###Activate###
0,b1,1,b2,b3,b4,b5,b6,b7,2
0,1,b1,b2,b3,b4,b5,b6,b7,2
0,b1,1,b2,1,b3,b4,b5,b6,2
0,1,1,b2,b3,b4,b5,b6,b7,2
0,1,b1,b2,1,1,1,b3,b4,2
0,1,b1,b2,b3,1,1,1,1,2
###Remain###
2,b1,1,b2,b3,b4,b5,b6,b7,2
2,1,b1,b2,b3,b4,b5,b6,b7,2
2,b1,1,b2,1,b3,b4,b5,b6,2
2,1,b1,1,b2,b3,b4,b5,b6,2
2,1,b1,b2,1,b3,b4,b5,b6,2
2,1,1,b2,b3,b4,b5,b6,b7,2
2,1,b1,b2,b3,1,b4,b5,b6,2
2,b1,1,b2,b3,b4,1,b5,b6,2
2,b1,1,b2,1,b3,1,b4,b5,2
2,1,b1,1,b2,1,b3,b4,b5,2
2,1,b1,1,b2,b3,1,b4,b5,2
2,1,1,1,b2,b3,b4,b5,b6,2
2,b1,1,1,1,b2,b3,b4,b5,2
2,1,1,b1,1,b2,b3,b4,b5,2
2,1,b1,b2,1,b3,1,b4,b5,2
2,1,1,b1,b2,b3,1,b4,b5,2
2,1,b1,1,1,b2,b3,b4,b5,2
2,1,b1,b2,1,1,b3,b4,b5,2
2,1,b1,b2,1,1,1,b3,b4,2
2,1,b1,b2,b3,1,1,1,1,2
a, a1, a2, a3, a4, a5, a6, a7, a8, 0
Edit: If you want 1 to die to state 0 as it did in previous versions, just delete the next to last line of the output.
Edit 2: 7 and 2 c and e were wrong parity. Fixed.