Saka wrote:Ok what about a script that converts an none-symmetry rule table to MAP (and vice versa maybe)?
The following script uses the rule in the current Golly universe to test what happens in each of the 512 possible neighborhood cases, and builds a bitstring from that.
If anyone sees any problems with this script, let me know -- besides the item labeled KNOWN ISSUE in the comments, that is. Golly automatically emulates B0 rules to avoid flickering, and that means that this script sees a different rule when it runs the 512 neighborhood samples.
That problem is dealt with by checking for "B0" in the rule string that Golly reports... but that doesn't solve the case where it's already a MAP rulestring -- or a custom-named rule defined by a rule table, that is actually a Lifelike B0 rule in disguise. Luckily I don't think there are many custom-named B0 rules out there. If someone wants to contribute some code to check for that situation (and maybe just throw an error), I'd be grateful.
Code: Select all
-- make_MAP_rulestring_v1.0.lua
local g = golly()
local gp = require "gplus"
local split = gp.split
-- local pattern = gp.pattern
function fixrule(s)
return (gp.split(s,":")) -- remove bounded grid spec, if any
end
g.addlayer("temp") -- keep and test the current rule
fixedrule=fixrule(g.getrule())
g.setrule(fixedrule)
bitlist={{-1,-1,1},{0,-1,2},{1,-1,4},{-1,0,8},{0,0,16},{1,0,32},{-1,1,64},{0,1,128},{1,1,256}}
for j = 1, 9 do
x, y, bit = table.unpack(bitlist[j])
for i=0, 511 do
if i&bit>0 then g.setcell(i*5+x,y,1) end
end
end
g.run(1)
bits={}
ind=1
local rulestr, invstr, revinvstr="","",""
for k=0,2555,5 do
if g.getcell(k,0)==1 then
rulestr=rulestr.."1"
invstr=invstr.."0"
revinvstr="0"..revinvstr
else
rulestr=rulestr.."0"
invstr=invstr.."1"
revinvstr="1"..revinvstr
end
end
-- build base64 lookup table
local lookupstr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
bdict={}
for i=1,64 do
local w=""
for j=0,5 do
if (i-1)&2^j>0 then w="1"..w else w="0"..w end
end
bdict[w]=lookupstr:sub(i,i)
end
-- decide whether to use standard, inverted, or inverted-reversed bitstring, based on fixedrule
-- (assuming Golly is correctly simulating rules with B0, with or without S8, to avoid strobing)
---------------------- KNOWN ISSUE ---------------------------
-- the following won't work for anisotropic non-totalistic rules defined by MAP strings,
-- so we'll have to decode the MAP rulestring into a 512-bit string in that case, check first and last digits...
-- but in that case, we already know the string, so why are we running this script anyway?
if string.match(fixedrule,"B0") then rulestr = string.match(fixedrule,"S.*8") and revinstr or invstr end
local s = rulestr.."0000" -- pad so that len mod 6=0
base64="MAP"
for i=1,511,6 do base64=base64..bdict[s:sub(i,i+5)] end
g.setclipstr(rulestr.."\n"..base64)
g.show("Copied to clipboard: "..base64)
-- Life = 'MAPARYXfhZofugWaH7oaIDogBZofuhogOiAaIDogIAAgAAWaH7oaIDogGiA6ICAAIAAaIDogIAAgACAAIAAAAAAAA'
The vice-versa case is a little trickier, mostly because ninety-nine point I-don't-know-how-many-nines percent of possible MAP rules don't have a non-MAP equivalent.
However, I think it's not too hard a job to get an isotropic rule string out of a MAP string, using Golly and a modified version of the above script. Start by building a lookup table for each of the 51 neighborhoods, by running the script with "B0/S", "B1e/S", "B1c/S", and so on up to "B/S8", and retrieve the 512-byte contents of the "rulestr" variable instead of the base64 equivalent.
Then for each string, you check the (decoded) input MAP bitstring to see if it has 1's in all the same places. If so, subtract them from the input MAP bitstring, and add the appropriate isotropic bit to the output rule string. When you've checked all 51 isotropic neighborhoods, then if there are no 1's left in the input MAP bitstring, then the output rulestring is a correct translation. If there are any 1's left, then the MAP bitstring was anisotropic and no translation is possible.
Luckily Golly can do the rest, in terms of making a canonical isotropic or Life-like rule string out of the messy string generated by the above method. For example:
Code: Select all
import golly as g
g.setrule("B3c3e3k3a3i3n3y3q3j3r/S2c2e2k2a2i2n3c3e3k3a3i3n3y3q3j3r")
g.note(g.getrule())