c0b0p0 , I'm glad to see people experimenting with rules related to Callahan's hex rule, and sharing their results!
Awhile back, I was interested in extending Callahan's non-totalistic hexagonal rule notation so that it applies to more than just two neighbors. I tried out the following:
Below I'm including a Golly script that will accept Callahan's notation (extended as shown above). The idea is to eliminate the need to create cumbersome rule tables for each new rule. You can simply enter "B2o4m6/S2o2p3o4" (or some such) and the script first converts your entry into Mcell's Weighted Life notation. You can stop there, or you can hit "OK", and the script will continue on, and create a Golly rule (in .rule format) for you to use in Golly. You can use the script to have fun exploring Callahan's notation!
Code: Select all
import golly
from glife.RuleTree import *
dialog_box_message = '''This script will convert Callhan's (extended) non-totalistic hexagonal notation into Weighted Life notation.'''
dummyvariable = '''
The following shows how this script extends Callahan's hexagaonl non-totalistic notation. Unfortunately, it may be scrambled a bit when I post it to the ConwayLife.com forum. Please refer to the ASCII art image I posted to the forum to help unscramble the following:
. .
0: . x .
. .
O .
1: . x .
. .
O O O . O .
2o: . x . 2m: . x O 2p: . x .
. . . . . O
O O O O O .
3o: O x . 3m: . x . 3p: . x O
. . . O O .
O O O O O O
4o: O x O 4m: . x O 4p: . x .
. . O . O O
O O
5: O x O
O .
O O
6: O x O
O O
'''
CR = chr(13)
LF = chr(10)
rulestring = golly.getstring(dialog_box_message, "B2o/S2m34")
rulestring = rulestring.replace(" ", "")
rulestring = rulestring.lower()
rulestring = rulestring.replace("b", "B")
rulestring = rulestring.replace("s", "S")
rulestring = rulestring.replace("c", "C")
rulestring = rulestring.replace("hex_", "")
rulestring = rulestring.replace("_", "/")
rulestring_parts = rulestring.split("/")
rulestring_firstpart = rulestring_parts[0]
rulestring_secondpart = rulestring_parts[1]
if len(rulestring_parts) == 3:
rulestring_thirdpart = rulestring_parts[2]
rulestring_thirdpart = rulestring_thirdpart.replace("C", "")
decaystates = int(rulestring_thirdpart)
else:
decaystates = 0
rule_name = rulestring.replace("/", "_")
rulestring = rulestring_firstpart + "/" + rulestring_secondpart
if rulestring.startswith("B") or rulestring.startswith("S"):
rulestring = rulestring.replace("/", "")
else:
rulestring = rulestring.replace("/", "B")
rulestring = rulestring + "\n"
Callahandict = {
"0": [0],
"1": [1, 2, 4, 8, 16, 32],
"2o": [3, 6, 12, 24, 48, 33],
"2m": [5, 10, 20, 40, 17, 34],
"2p": [9, 18, 36],
"3o": [7, 14, 28, 56, 49, 35],
"3m": [11, 22, 44, 25, 50, 37, 52, 26, 13, 38, 19, 41],
"3p": [21, 42],
"4o": [15, 30, 60, 57, 51, 39],
"4m": [23, 46, 29, 58, 53, 43],
"4p": [27, 54, 45],
"5": [62, 61, 31, 59, 47, 55],
"6": [63]
}
def create_rule_element(bs,totalistic_num, notation_letter, inverse_list):
result = ""
if notation_letter != "none":
for col in Callahandict[totalistic_num+notation_letter]:
result = result + bs + str(col) + ","
else:
for row in Callahandict:
if row.startswith(totalistic_num):
for col in Callahandict[row]:
result = result + bs + str(col) + ","
return result
bs = "RS"
totalistic_context = "none"
last_totalistic_context = "none"
notation_letter = "none"
finalrulestring = ""
for x in rulestring:
if x == "S" or x == "B" or x.isdigit() or x == "\n":
last_totalistic_context = totalistic_context
totalistic_context = x
if last_totalistic_context != "none" and notation_letter == "none":
finalrulestring = finalrulestring + create_rule_element(bs, last_totalistic_context, "none",[])
# Now lets get ready to move on to the next character.
notation_letter = "none"
if x == "S" or x == "B":
totalistic_context = "none"
if x == "S":
bs = "RS"
if x == "B":
bs = "RB"
elif x in ["o","m","p"] and totalistic_context != "none":
notation_letter = x
finalrulestring = finalrulestring + create_rule_element(bs, totalistic_context, notation_letter, [])
finalrulestring = "NW1,NN2,NE0,WW32,ME0,EE4,SW0,SS16,SE8," + "HI" + str(decaystates) + ", " + finalrulestring
golly.getstring('''
Here is the Weighted Life version - you can copy it below: .''', finalrulestring)
# Part 2: This is WeightedLife->RuleTree
from glife.RuleTree import *
# Default values
RS = []
RB = []
ME_weight = 0
NW_weight = 1
NN_weight = 1
NE_weight = 1
WW_weight = 1
EE_weight = 1
SW_weight = 1
SS_weight = 1
SE_weight = 1
CR = chr(13)
LF = chr(10)
#name = "Temporary-rule-name"
name = "Hex_" + rule_name
#WeightedRulestring = golly.getstring(dialog_box_message, "Name=Temporary-rule-name NW4,NN1,NE0,WW1, ME0,EE4,SW0,SS4, SE1,HI0,RS1,RS6,RS8,RB5,RB6")
WeightedRulestring = finalrulestring
#WeightedRulestring = WeightedRulestring.replace("ame = ", "ame=")
WeightedRulestring = WeightedRulestring.replace(" ", ",")
WeightedRulestring = WeightedRulestring.replace(CR, ",")
WeightedRulestring = WeightedRulestring.replace(LF, ",")
for x in WeightedRulestring.split(","):
if x.startswith("Name=") or x.startswith("name="):
name = x.split("ame=")[1]
else:
x = x.upper()
if x.startswith("NW"):
NW_weight = int(x.split("NW")[1])
elif x.startswith("NN"):
NN_weight = int(x.split("NN")[1])
elif x.startswith("NE"):
NE_weight = int(x.split("NE")[1])
elif x.startswith("WW"):
WW_weight = int(x.split("WW")[1])
elif x.startswith("EE"):
EE_weight = int(x.split("EE")[1])
elif x.startswith("SW"):
SW_weight = int(x.split("SW")[1])
elif x.startswith("SS"):
SS_weight = int(x.split("SS")[1])
elif x.startswith("SE"):
SE_weight = int(x.split("SE")[1])
elif x.startswith("ME"):
ME_weight = int(x.split("ME")[1])
elif x.startswith("RS"):
RS.append(int(x.split("RS")[1]))
elif x.startswith("RB"):
RB.append(int(x.split("RB")[1]))
elif x.startswith("HI"):
n_states = (int(x.split("HI")[1]))
if n_states < 3:
n_states = 2
if n_states > 256:
n_states = 256
if n_states > 8:
golly.getstring('''Ruletrees with more than 8 or so states can take a long time to compute.
Save your work before continuing. Once this script starts computing your rule,
if you want to stop the calculation, you may have to abort Golly itelf.
Choose the cancel option now to stop this script.''', "Proceed")
n_neighbors = 8
def transition_function(a):
# order for 8 neighbors is NW, NE, SW, SE, N, W, E, S, C
n = NW_weight*(a[0] == 1) + NE_weight*(a[1] == 1) + SW_weight*(a[2] == 1) + SE_weight*(a[3] == 1) + NN_weight*(a[4] == 1) + WW_weight*(a[5] == 1) + EE_weight*(a[6] == 1) + SS_weight*(a[7] == 1) + ME_weight*(a[8] == 1)
if a[8] == 1 and n in RS:
return 1
if a[8] == 0 and n in RB:
return 1
if a[8] > 0 and a[8] < (n_states - 1):
return a[8] + 1
return 0
golly.show("Please wait while a rule file is being created...")
# The code below this line is copied from make-ruletree.py
try:
MakeRuleTreeFromTransitionFunction( n_states, n_neighbors, transition_function,
golly.getdir("rules")+name+".tree" )
# use name.tree to create name.rule (with no icons);
# note that if name.rule already exists then we only replace the info in
# the @TREE section to avoid clobbering any other info added by the user
ConvertTreeToRule(name, n_states, [])
golly.setalgo("RuleLoader")
golly.setrule(name)
golly.show("Created "+golly.getdir("rules")+name+".rule and switched to that rule.")
except:
import sys
import traceback
exception, msg, tb = sys.exc_info()
golly.warn(\
'''A problem was encountered with the supplied rule:'''+ '\n'.join(traceback.format_exception(exception, msg, tb)))
golly.exit()
Edited Mar 3, 2014 to fix naming convention for rules with extra decay states.