def HexagonalTransitionsToRuleTree(neighborhood,n_states,transitions,rule_name):
    '''Convert a set of hexagonal neighborhood transitions to a Moore neighborhood rule tree.'''
    tree = RuleTree(n_states,8)
    for t in transitions:
        # C,S,E,W,N,SE,(SW),(NE),NW
        tree.add_rule([t[0],t[4],t[2],t[5],t[1],t[3],range(n_states),range(n_states),t[6]],t[7][0])
    tree.write( golly.getdir('rules')+rule_name+".tree" )
def EmulateOneDimensional(neighborhood,n_states,transitions,input_filename):
    '''Emulate a oneDimensional neighborhood rule table with a vonNeumann neighborhood rule tree.'''
    rule_name = os.path.splitext(os.path.split(input_filename)[1])[0]
    tree = RuleTree(n_states,4)
    for t in transitions:
        tree.add_rule([t[0],range(n_states),t[2],t[1],range(n_states)],t[3][0]) # C,S,E,W,N,C'
    tree.write( golly.getdir('rules')+rule_name+".tree" )
    return rule_name
def TriangularTransitionsToRuleTree_CheckerboardMethod(neighborhood, n_states,
                                                       transitions, rule_name):

    # Background state 0 has no checkerboard, we infer it from its neighboring cells.
    def encode_lower(s):
        return s

    def encode_upper(s):
        ### AKT: this code causes syntax error in Python 2.3:
        ### return [0 if se==0 else n_states+se-1 for se in s]
        temp = []
        for se in s:
            if se == 0:
                temp.append(0)
            else:
                temp.append(n_states + se - 1)
        return temp

    total_states = n_states * 2 - 1
    if total_states > 256:
        golly.warn("Number of states exceeds Golly's limit of 256!")
        golly.exit()

    tree = RuleTree(total_states, 4)
    for t in transitions:
        # as lower
        tree.add_rule(
            [
                encode_lower(t[0]),  # C
                encode_upper(t[2]),  # S
                encode_upper(t[1]),  # E
                encode_upper(t[3]),  # W
                range(total_states)
            ],  # N
            encode_lower(t[4])[0])  # C'
        # as upper
        tree.add_rule(
            [
                encode_upper(t[0]),  # C
                range(total_states),  # S
                encode_lower(t[3]),  # E
                encode_lower(t[1]),  # W
                encode_lower(t[2])
            ],  # N
            encode_upper(t[4])[0])  # C'

    # output the rule tree
    golly.show("Compressing rule tree and saving to file...")
    tree.write(golly.getdir('rules') + rule_name + '.tree')
Example #4
0
def EmulateOneDimensional(neighborhood, n_states, transitions, input_filename):
    '''Emulate a oneDimensional neighborhood rule table with a vonNeumann neighborhood rule tree.'''
    rule_name = os.path.splitext(os.path.split(input_filename)[1])[0]
    tree = RuleTree(n_states, 4)
    for t in transitions:
        tree.add_rule(
            [t[0], range(n_states), t[2], t[1],
             range(n_states)], t[3][0])  # C,S,E,W,N,C'
    tree.write(golly.getdir('rules') + rule_name + ".tree")
    return rule_name
Example #5
0
def HexagonalTransitionsToRuleTree(neighborhood, n_states, transitions,
                                   rule_name):
    '''Convert a set of hexagonal neighborhood transitions to a Moore neighborhood rule tree.'''
    tree = RuleTree(n_states, 8)
    for t in transitions:
        # C,S,E,W,N,SE,(SW),(NE),NW
        tree.add_rule([
            t[0], t[4], t[2], t[5], t[1], t[3],
            range(n_states),
            range(n_states), t[6]
        ], t[7][0])
    tree.write(golly.getdir('rules') + rule_name + ".tree")
def TriangularTransitionsToRuleTree_CheckerboardMethod(neighborhood,n_states,transitions,rule_name):

    # Background state 0 has no checkerboard, we infer it from its neighboring cells.
    def encode_lower(s):
        return s
    def encode_upper(s):
        ### AKT: this code causes syntax error in Python 2.3:
        ### return [0 if se==0 else n_states+se-1 for se in s]
        temp = []
        for se in s:
            if se==0:
                temp.append(0)
            else:
                temp.append(n_states+se-1)
        return temp

    total_states = n_states*2 - 1
    if total_states>256:
        golly.warn("Number of states exceeds Golly's limit of 256!")
        golly.exit()
    
    tree = RuleTree(total_states,4)
    for t in transitions:
        # as lower
        tree.add_rule([encode_lower(t[0]),   # C
                       encode_upper(t[2]),   # S
                       encode_upper(t[1]),   # E
                       encode_upper(t[3]),   # W
                       range(total_states)],   # N
                      encode_lower(t[4])[0]) # C'
        # as upper
        tree.add_rule([encode_upper(t[0]),   # C
                       range(total_states),    # S
                       encode_lower(t[3]),   # E
                       encode_lower(t[1]),   # W
                       encode_lower(t[2])],  # N
                      encode_upper(t[4])[0]) # C'
        
    # output the rule tree
    golly.show("Compressing rule tree and saving to file...")
    tree.write(golly.getdir('rules') + rule_name + '.tree')
def EmulateMargolus(neighborhood,n_states,transitions,input_filename):
    '''Emulate a Margolus or square4_* neighborhood rule table with a Moore neighborhood rule tree.'''
    rule_name = os.path.splitext(os.path.split(input_filename)[1])[0]+'_emulated'
    total_states = 1+2*n_states
    tree = RuleTree(total_states,8)
    # now work through the transitions
    for tr in transitions:
        for iOutput,background_output in enumerate(BackgroundOutputs[neighborhood]):
            bg_inputs = BackgroundInputs[iOutput]
            iEntry = iOutput % 4  # (0=top-left, 1=top-right, 2=bottom-left, 3=bottom-right)
            rule_inputs = []
            for i in range(9):
                if ForegroundInputs[iEntry][i]==-1:
                    rule_inputs.append(encode( range(n_states), bg_inputs[i] ) + [0]) # wildcard
                else:
                    rule_inputs.append(encode( tr[ForegroundInputs[iEntry][i]], bg_inputs[i] ))
            tree.add_rule( rule_inputs, encode( tr[iEntry+4], background_output )[0] )
    # supply default behaviour: background still changes even if the state doesn't
    for iState in range(n_states):
        for iOutput,background_output in enumerate(BackgroundOutputs[neighborhood]):
            bg_inputs = BackgroundInputs[iOutput]
            tree.add_rule( [ encode( [iState], bg_inputs[0] ) ] +
                           [ encode( range(n_states), bg_inputs[i] )+[0] for i in range(1,9) ], # wildcard
                           encode( [iState], background_output )[0] )
            
    # output the rule tree
    golly.show("Compressing rule tree and saving to file...")
    tree.write(golly.getdir('rules') + rule_name + '.tree')
    
    # also save a .colors file
    golly.show("Generating colors...")

    # read rule_name+'.colors' file if it exists
    cfn = os.path.split(input_filename)[0] + '/' + os.path.splitext(os.path.split(input_filename)[1])[0] + ".colors"
    try:
        cf = open(cfn,'r')
    except IOError:
        # use Golly's default random colours
        random_colors=[[90,90,90],[0,255,127],[127,0,255],[148,148,148],[128,255,0],[255,0,128],[0,128,255],[1,159,0],
            [159,0,1],[255,254,96],[0,1,159],[96,255,254],[254,96,255],[126,125,21],[21,126,125],[125,21,126],
            [255,116,116],[116,255,116],[116,116,255],[228,227,0],[28,255,27],[255,27,28],[0,228,227],
            [227,0,228],[27,28,255],[59,59,59],[234,195,176],[175,196,255],[171,194,68],[194,68,171],
            [68,171,194],[72,184,71],[184,71,72],[71,72,184],[169,255,188],[252,179,63],[63,252,179],
            [179,63,252],[80,9,0],[0,80,9],[9,0,80],[255,175,250],[199,134,213],[115,100,95],[188,163,0],
            [0,188,163],[163,0,188],[203,73,0],[0,203,73],[73,0,203],[94,189,0],[189,0,94]]
        colors = dict(zip(range(len(random_colors)),random_colors))
    else:
        # read from the .colors file
        colors = {}
        for line in cf:
            if line[0:5]=='color':
                entries = map(int,line[5:].replace('=',' ').replace('\n',' ').split())
                if len(entries)<4:
                    continue # too few entries, ignore
                colors.update({entries[0]:[entries[1],entries[2],entries[3]]})
        # (TODO: support gradients in .colors)
        
    # provide a deep blue background if none provided
    if not 0 in colors:
        colors.update({0:[0,0,120]})

    c = open(golly.getdir('rules')+rule_name+".colors",'w')
    for col in colors.items()[:n_states]:
        c.write('color='+str(col[0]*2+1)+' '+' '.join(map(str,col[1]))+'\n')
        c.write('color='+str(col[0]*2+2)+' '+' '.join([ str(int(x*0.7)) for x in col[1] ])+'\n')  # (darken slightly)
    c.flush()
    c.close()
    
    return rule_name
def EmulateMargolus(neighborhood, n_states, transitions, input_filename):
    '''Emulate a Margolus or square4_* neighborhood rule table with a Moore neighborhood rule tree.'''
    rule_name = os.path.splitext(os.path.split(input_filename)[1])[0]
    total_states = 1 + 2 * n_states
    tree = RuleTree(total_states, 8)
    # now work through the transitions
    for tr in transitions:
        for iOutput, background_output in enumerate(
                BackgroundOutputs[neighborhood]):
            bg_inputs = BackgroundInputs[iOutput]
            iEntry = iOutput % 4  # (0=top-left, 1=top-right, 2=bottom-left, 3=bottom-right)
            rule_inputs = []
            for i in range(9):
                if ForegroundInputs[iEntry][i] == -1:
                    rule_inputs.append(
                        encode(range(n_states), bg_inputs[i]) +
                        [0])  # wildcard
                else:
                    rule_inputs.append(
                        encode(tr[ForegroundInputs[iEntry][i]], bg_inputs[i]))
            tree.add_rule(rule_inputs,
                          encode(tr[iEntry + 4], background_output)[0])
    # supply default behaviour: background still changes even if the state doesn't
    for iState in range(n_states):
        for iOutput, background_output in enumerate(
                BackgroundOutputs[neighborhood]):
            bg_inputs = BackgroundInputs[iOutput]
            tree.add_rule(
                [encode([iState], bg_inputs[0])] + [
                    encode(range(n_states), bg_inputs[i]) + [0]
                    for i in range(1, 9)
                ],  # wildcard
                encode([iState], background_output)[0])

    # output the rule tree
    golly.show("Compressing rule tree and saving to file...")
    tree.write(golly.getdir('rules') + rule_name + '.tree')

    # also save a .colors file
    golly.show("Generating colors...")

    # read rule_name+'.colors' file if it exists
    cfn = os.path.split(input_filename)[0] + '/' + os.path.splitext(
        os.path.split(input_filename)[1])[0] + ".colors"
    try:
        cf = open(cfn, 'r')
    except IOError:
        # use Golly's default random colours
        random_colors = [[90, 90, 90], [0, 255, 127], [127, 0, 255],
                         [148, 148, 148], [128, 255, 0], [255, 0,
                                                          128], [0, 128, 255],
                         [1, 159, 0], [159, 0, 1], [255, 254, 96], [0, 1, 159],
                         [96, 255, 254], [254, 96, 255], [126, 125, 21],
                         [21, 126, 125], [125, 21, 126], [255, 116, 116],
                         [116, 255, 116], [116, 116, 255], [228, 227, 0],
                         [28, 255, 27], [255, 27, 28], [0, 228, 227],
                         [227, 0, 228], [27, 28, 255], [59, 59, 59],
                         [234, 195, 176], [175, 196, 255], [171, 194, 68],
                         [194, 68, 171], [68, 171, 194], [72, 184, 71],
                         [184, 71, 72], [71, 72, 184], [169, 255, 188],
                         [252, 179, 63], [63, 252, 179], [179, 63, 252],
                         [80, 9, 0], [0, 80, 9], [9, 0, 80], [255, 175, 250],
                         [199, 134, 213], [115, 100, 95], [188, 163, 0],
                         [0, 188, 163], [163, 0, 188], [203, 73, 0],
                         [0, 203, 73], [73, 0, 203], [94, 189, 0],
                         [189, 0, 94]]
        colors = dict(zip(range(len(random_colors)), random_colors))
    else:
        # read from the .colors file
        colors = {}
        for line in cf:
            if line[0:5] == 'color':
                entries = map(
                    int, line[5:].replace('=', ' ').replace('\n', ' ').split())
                if len(entries) < 4:
                    continue  # too few entries, ignore
                colors.update(
                    {entries[0]: [entries[1], entries[2], entries[3]]})
        # (TODO: support gradients in .colors)

    # provide a deep blue background if none provided
    if not 0 in colors:
        colors.update({0: [0, 0, 120]})

    c = open(golly.getdir('rules') + rule_name + ".colors", 'w')
    for col in colors.items()[:n_states]:
        c.write('color=' + str(col[0] * 2 + 1) + ' ' +
                ' '.join(map(str, col[1])) + '\n')
        c.write('color=' + str(col[0] * 2 + 2) + ' ' +
                ' '.join([str(int(x * 0.7))
                          for x in col[1]]) + '\n')  # (darken slightly)
    c.flush()
    c.close()

    # use rule_name.tree and rule_name.colors to create rule_name.rule (no icon info)
    ConvertTreeToRule(rule_name, total_states, [])
    return rule_name
Example #9
0
                    ]

#golly.warn(str(not_arriving_from_here))

# What states leave output_color behind?
leaving_color_behind = {}
for output_color in range(n_colors):
    leaving_color_behind[output_color] = [output_color]  # (no turmite present)
    for state in range(n_states):
        for color in range(n_colors):
            if action_table[state][color][0] == output_color:
                leaving_color_behind[output_color] += [
                    encode(color, state, d) for d in range(n_dirs)
                ]  # any direction

tree = RuleTree(total_states, 4)

# A single turmite is entering this square:
for s in range(n_states):
    # collect all the possibilities for a turmite to arrive in state s...
    inputs_sc = []
    for state in range(n_states):
        for color in range(n_colors):
            if action_table[state][color][2] == s:
                inputs_sc += [(state, color)]
    # ...from direction dir
    for dir in range(n_dirs):
        inputs = []
        for state, color in inputs_sc:
            turnset = action_table[state][color][1]  # sum of all turns
            inputs += [
Example #10
0
def TriangularTransitionsToRuleTree_SplittingMethod(neighborhood,n_states,transitions_list,rule_name):

    # each square cell is j*N+i where i is the lower triangle, j is the upper triangle
    # each i,j in (0,N]
    # (lower and upper are lists)
    def encode(lower,upper):
        return [ up*n_states+low for up in upper for low in lower ]

    # what neighbors of the lower triangle overlap neighbors of the upper triangle?
    lower2upper = {
        "triangularVonNeumann": [(0,1),(1,0)],
        "triangularMoore": [(0,1),(1,0),(2,12),(3,4),(4,3),(5,10),(6,11),(10,5),(11,6),(12,2)],
    }
    numNeighbors = { "triangularVonNeumann":4, "triangularMoore":8 }

    # convert transitions to list of list of sets for speed
    transitions = [[set(e) for e in t] for t in transitions_list]
    tree = RuleTree(n_states*n_states,numNeighbors[neighborhood])
    # for each transition pair, see if we can apply them both at once to a square
    for i,t1 in enumerate(transitions): # as lower
        golly.show("Building rule tree... (pass 1 of 2: "+str(100*i//len(transitions))+"%)")
        for t2 in transitions: # as upper
            # we can only apply both rules at once if they overlap to some extent
            ### AKT: any() and isdisjoint() are not available in Python 2.3:
            ### if any( t1[j].isdisjoint(t2[k]) for j,k in lower2upper[neighborhood] ):
            ###     continue
            any_disjoint = False
            for j,k in lower2upper[neighborhood]:
                if len(t1[j] & t2[k]) == 0:
                    any_disjoint = True
                    break
            if any_disjoint: continue
            # take the intersection of their inputs
            if neighborhood=="triangularVonNeumann":
                tree.add_rule( [ encode(t1[0]&t2[1],t1[1]&t2[0]), # C
                     encode(list(range(n_states)),t1[2]), # S
                     encode(t2[3],list(range(n_states))), # E
                     encode(list(range(n_states)),t1[3]), # W
                     encode(t2[2],list(range(n_states))) ], # N
                     encode(t1[4],t2[4])[0] ) # C'
            elif neighborhood=="triangularMoore":
                tree.add_rule( [ encode(t1[0]&t2[1],t1[1]&t2[0]), # C
                             encode(t1[7],t1[2]&t2[12]), # S
                             encode(t1[4]&t2[3],t2[9]), # E
                             encode(t1[9],t1[3]&t2[4]), # W
                             encode(t1[12]&t2[2],t2[7]), # N
                             encode(t1[6]&t2[11],t1[5]&t2[10]), # SE
                             encode(list(range(n_states)),t1[8]), # SW
                             encode(t2[8],list(range(n_states))), # NE
                             encode(t1[10]&t2[5],t1[11]&t2[6]) ], # NW
                           encode(t1[13],t2[13])[0] ) # C'
    # apply each transition to an individual triangle, leaving the other unchanged
    for i,t in enumerate(transitions):
        golly.show("Building rule tree... (pass 2 of 2: "+str(100*i//len(transitions))+"%)")
        for t_1 in t[1]:
            if neighborhood=="triangularVonNeumann":
                # as lower triangle:
                tree.add_rule( [ encode(t[0],[t_1]), # C
                                 encode(list(range(n_states)),t[2]), # S
                                 list(range(n_states*n_states)), # E
                                 encode(list(range(n_states)),t[3]), # W
                                 list(range(n_states*n_states)) ], # N
                                 encode(t[4],[t_1])[0] ) # C'
                # as upper triangle:
                tree.add_rule( [ encode([t_1],t[0]), # C
                                 list(range(n_states*n_states)), # S
                                 encode(t[3],list(range(n_states))), # E
                                 list(range(n_states*n_states)), # W
                                 encode(t[2],list(range(n_states))) ], # N
                                 encode([t_1],t[4])[0] ) # C'
            elif neighborhood=="triangularMoore":
                # as lower triangle:
                tree.add_rule( [encode(t[0],[t_1]), # C
                    encode(t[7],t[2]), # S
                    encode(t[4],list(range(n_states))), # E
                    encode(t[9],t[3]), # W
                    encode(t[12],list(range(n_states))), # N
                    encode(t[6],t[5]), # SE
                    encode(list(range(n_states)),t[8]), # SW
                    list(range(n_states*n_states)), # NE
                    encode(t[10],t[11]) ], # NW
                    encode(t[13],[t_1])[0] ) # C'
                # as upper triangle:
                tree.add_rule( [encode([t_1],t[0]),
                    encode(list(range(n_states)),t[12]), # S
                    encode(t[3],t[9]), # E
                    encode(list(range(n_states)),t[4]), # W
                    encode(t[2],t[7]), # N
                    encode(t[11],t[10]), # SE
                    list(range(n_states*n_states)), # SW
                    encode(t[8],list(range(n_states))), # NE
                    encode(t[5],t[6]) ], # NW
                    encode([t_1],t[13])[0] ) # C'

    # output the rule tree
    golly.show("Compressing rule tree and saving to file...")
    tree.write(golly.getdir('rules') + rule_name + '.tree')
Example #11
0
    for state in range(n_states):
        moveset = action_table[state][color][1]
        for iMove,move in enumerate(dirs):
            if not move in moveset:
                not_arriving_from_here[opposite_dirs[iMove]] += [encode(color,state)]

# What states leave output_color behind?
leaving_color_behind = {}
for output_color in range(n_colors):
    leaving_color_behind[output_color] = [output_color] # (no turmite present)
    for state in range(n_states):
        for color in range(n_colors):
            if action_table[state][color][0]==output_color:
                leaving_color_behind[output_color] += [encode(color,state)]

tree = RuleTree(total_states,4)

# A single turmite is entering this square:
for s in range(n_states):
    # collect all the possibilities for a turmite to arrive in state s...
    inputs_sc = []
    for state in range(n_states):
        for color in range(n_colors):
            if action_table[state][color][2]==s:
                inputs_sc += [(state,color)]
    # ...from direction dir
    for dir in range(n_dirs):
        inputs = []
        for state,color in inputs_sc:
            moveset = action_table[state][color][1]
            if dirs[opposite_dirs[dir]] in moveset: # e.g. is there one to the S about to move N
def TriangularTransitionsToRuleTree_SplittingMethod(neighborhood,n_states,transitions_list,rule_name):

    # each square cell is j*N+i where i is the lower triangle, j is the upper triangle
    # each i,j in (0,N]
    # (lower and upper are lists)
    def encode(lower,upper): 
        return [ up*n_states+low for up in upper for low in lower ]

    # what neighbors of the lower triangle overlap neighbors of the upper triangle?
    lower2upper = { 
        "triangularVonNeumann": [(0,1),(1,0)],
        "triangularMoore": [(0,1),(1,0),(2,12),(3,4),(4,3),(5,10),(6,11),(10,5),(11,6),(12,2)],
    }
    numNeighbors = { "triangularVonNeumann":4, "triangularMoore":8 }

    # convert transitions to list of list of sets for speed
    transitions = [[set(e) for e in t] for t in transitions_list]
    tree = RuleTree(n_states*n_states,numNeighbors[neighborhood])
    # for each transition pair, see if we can apply them both at once to a square
    for i,t1 in enumerate(transitions): # as lower
        golly.show("Building rule tree... (pass 1 of 2: "+str(100*i/len(transitions))+"%)") 
        for t2 in transitions: # as upper
            # we can only apply both rules at once if they overlap to some extent
            ### AKT: any() and isdisjoint() are not available in Python 2.3:
            ### if any( t1[j].isdisjoint(t2[k]) for j,k in lower2upper[neighborhood] ):
            ###     continue
            any_disjoint = False
            for j,k in lower2upper[neighborhood]:
                if len(t1[j] & t2[k]) == 0:
                    any_disjoint = True
                    break
            if any_disjoint: continue
            # take the intersection of their inputs
            if neighborhood=="triangularVonNeumann":
                tree.add_rule( [ encode(t1[0]&t2[1],t1[1]&t2[0]), # C
                     encode(range(n_states),t1[2]), # S
                     encode(t2[3],range(n_states)), # E
                     encode(range(n_states),t1[3]), # W
                     encode(t2[2],range(n_states)) ], # N
                     encode(t1[4],t2[4])[0] ) # C'
            elif neighborhood=="triangularMoore":
                tree.add_rule( [ encode(t1[0]&t2[1],t1[1]&t2[0]), # C
                             encode(t1[7],t1[2]&t2[12]), # S
                             encode(t1[4]&t2[3],t2[9]), # E
                             encode(t1[9],t1[3]&t2[4]), # W
                             encode(t1[12]&t2[2],t2[7]), # N
                             encode(t1[6]&t2[11],t1[5]&t2[10]), # SE
                             encode(range(n_states),t1[8]), # SW
                             encode(t2[8],range(n_states)), # NE
                             encode(t1[10]&t2[5],t1[11]&t2[6]) ], # NW
                           encode(t1[13],t2[13])[0] ) # C'
    # apply each transition to an individual triangle, leaving the other unchanged
    for i,t in enumerate(transitions):
        golly.show("Building rule tree... (pass 2 of 2: "+str(100*i/len(transitions))+"%)") 
        for t_1 in t[1]:
            if neighborhood=="triangularVonNeumann":
                # as lower triangle:
                tree.add_rule( [ encode(t[0],[t_1]), # C
                                 encode(range(n_states),t[2]), # S
                                 range(n_states*n_states), # E
                                 encode(range(n_states),t[3]), # W
                                 range(n_states*n_states) ], # N
                                 encode(t[4],[t_1])[0] ) # C'
                # as upper triangle:
                tree.add_rule( [ encode([t_1],t[0]), # C
                                 range(n_states*n_states), # S
                                 encode(t[3],range(n_states)), # E
                                 range(n_states*n_states), # W
                                 encode(t[2],range(n_states)) ], # N
                                 encode([t_1],t[4])[0] ) # C'
            elif neighborhood=="triangularMoore":
                # as lower triangle:
                tree.add_rule( [encode(t[0],[t_1]), # C
                    encode(t[7],t[2]), # S
                    encode(t[4],range(n_states)), # E
                    encode(t[9],t[3]), # W
                    encode(t[12],range(n_states)), # N
                    encode(t[6],t[5]), # SE
                    encode(range(n_states),t[8]), # SW
                    range(n_states*n_states), # NE
                    encode(t[10],t[11]) ], # NW
                    encode(t[13],[t_1])[0] ) # C'
                # as upper triangle:
                tree.add_rule( [encode([t_1],t[0]),
                    encode(range(n_states),t[12]), # S
                    encode(t[3],t[9]), # E
                    encode(range(n_states),t[4]), # W
                    encode(t[2],t[7]), # N
                    encode(t[11],t[10]), # SE
                    range(n_states*n_states), # SW
                    encode(t[8],range(n_states)), # NE
                    encode(t[5],t[6]) ], # NW
                    encode([t_1],t[13])[0] ) # C'
        
    # output the rule tree
    golly.show("Compressing rule tree and saving to file...")
    tree.write(golly.getdir('rules') + rule_name + '.tree')