File: make-Banks-IV-constructor.py

package info (click to toggle)
golly 3.2-2
  • links: PTS
  • area: main
  • in suites: buster
  • size: 19,516 kB
  • sloc: cpp: 69,819; ansic: 25,894; python: 7,921; sh: 4,267; objc: 3,721; java: 2,781; xml: 1,362; makefile: 530; perl: 69
file content (142 lines) | stat: -rw-r--r-- 4,737 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# Make a pattern from states 3 and 0, select it and then
# run this script to make a Banks-IV CA pattern that will then
# construct the pattern.
#
# The machine will attempt to activate the pattern by injecting
# a signal at a special trigger point.
# See: Patterns/Self-Rep/Banks/Banks-IV-constructor.rle.gz
#
# You may need to change trigger_row for your pattern, or disable
# triggering.
#
# Tim Hutton <tim.hutton@gmail.com>

from glife import rect
from time import time
import golly as g

r = rect( g.getselrect() )
if r.empty: g.exit("There is no selection.")

oldsecs = time()
maxstate = g.numstates() - 1

top_tape = '00'
bottom_tape = '00'

# write a state 3 to the required position, relative to the centre of the face
def write_cell(x,y):
    global top_tape
    global bottom_tape
    # delay one of the tapes, to select the correct row
    if y<0: top_tape += '00'*abs(y)
    elif y>0: bottom_tape += '00'*y
    # send out a write arm to the right length
    arm_length=2
    while arm_length < x:
        top_tape += '120' + '00'*arm_length + '12000'
        bottom_tape += '120' + '00'*arm_length + '12000'
        arm_length += 1
    # send an erasing wing down the arm, to write a cell at the end
    top_tape += '120' + '00'*(arm_length-3) + '120000'
    bottom_tape += '120' + '00'*(arm_length-3) + '120000'
    # undo the delay on the tapes (could just add the difference but this is simpler)
    if y<0: bottom_tape += '00'*abs(y)
    elif y>0: top_tape += '00'*y

# we first write the commands to 2 strings, and then to the grid
H_OFFSET = 10   # how far from the construction face should the new pattern be?

half_height = (r.height-(r.height%2))/2

# write the cells that are in state 1 (can ignore the zeros)
# (still plenty of room for optimisation here)
for col in xrange(r.left + r.width-1, r.left-1,-1):
    # if large selection then give some indication of progress
    newsecs = time()
    if newsecs - oldsecs >= 1.0:
        oldsecs = newsecs
        g.update()
    for row in xrange(r.top, r.top + r.height):
        if g.getcell(col,row)==3:
            write_cell(H_OFFSET + col-r.left,row - r.top - half_height)

# trigger
trigger_row = 3 # from the vertical middle
write_cell(H_OFFSET + 2,trigger_row)

# (optional) restore the trigger input
write_cell(H_OFFSET-3, trigger_row-1)
write_cell(H_OFFSET-2, trigger_row+2)
write_cell(H_OFFSET-2, trigger_row+1) # actually just sends an erasing wing
write_cell(H_OFFSET, trigger_row-2)
write_cell(H_OFFSET, trigger_row+2)

fx = r.left-20 # constructing face
fy = r.top+r.height*2 # centre of constructing face
half_height += 10

# draw the constructing face
for cy in range(fy-(half_height-6),fy+(half_height-6)+1):
    g.setcell(fx,cy,3)
# draw the top shoulder
g.setcell(fx,fy-half_height,3)
g.setcell(fx,fy-half_height-3,3)
g.setcell(fx-1,fy-half_height-3,3)
g.setcell(fx+1,fy-half_height-3,3)
g.setcell(fx-1,fy-half_height-2,3)
g.setcell(fx+1,fy-half_height-2,3)
g.setcell(fx+1,fy-half_height-1,3)
g.setcell(fx+1,fy-half_height+1,3)
g.setcell(fx+1,fy-half_height+2,3)
g.setcell(fx+1,fy-half_height+3,3)
g.setcell(fx+1,fy-half_height+4,3)
g.setcell(fx+1,fy-half_height+5,3)
g.setcell(fx-1,fy-half_height+2,3)
g.setcell(fx-1,fy-half_height+3,3)
g.setcell(fx-1,fy-half_height+4,3)
g.setcell(fx-1,fy-half_height+5,3)
g.setcell(fx+2,fy-half_height-1,3)
g.setcell(fx+3,fy-half_height-1,3)
g.setcell(fx+3,fy-half_height,3)
g.setcell(fx+2,fy-half_height+1,3)
g.setcell(fx+3,fy-half_height+1,3)
g.setcell(fx+2,fy-half_height+4,3)
g.setcell(fx-2,fy-half_height+5,3)
# draw the bottom shoulder
g.setcell(fx,fy+half_height,3)
g.setcell(fx,fy+half_height+3,3)
g.setcell(fx-1,fy+half_height+3,3)
g.setcell(fx+1,fy+half_height+3,3)
g.setcell(fx-1,fy+half_height+2,3)
g.setcell(fx+1,fy+half_height+2,3)
g.setcell(fx+1,fy+half_height+1,3)
g.setcell(fx+1,fy+half_height-1,3)
g.setcell(fx+1,fy+half_height-2,3)
g.setcell(fx+1,fy+half_height-3,3)
g.setcell(fx+1,fy+half_height-4,3)
g.setcell(fx+1,fy+half_height-5,3)
g.setcell(fx-1,fy+half_height-2,3)
g.setcell(fx-1,fy+half_height-3,3)
g.setcell(fx-1,fy+half_height-4,3)
g.setcell(fx-1,fy+half_height-5,3)
g.setcell(fx+2,fy+half_height-1,3)
g.setcell(fx+3,fy+half_height-1,3)
g.setcell(fx+3,fy+half_height,3)
g.setcell(fx+2,fy+half_height+1,3)
g.setcell(fx+3,fy+half_height+1,3)
g.setcell(fx+2,fy+half_height-4,3)
g.setcell(fx-2,fy+half_height-5,3)
# draw the tapes
x = fx-1
for c in range(0,len(top_tape)):
    g.setcell(x,fy-half_height-1,3)
    g.setcell(x,fy-half_height,int(top_tape[c]))
    g.setcell(x,fy-half_height+1,3)
    x -= 1
x = fx-1
for c in range(0,len(bottom_tape)):
    g.setcell(x,fy+half_height-1,3)
    g.setcell(x,fy+half_height,int(bottom_tape[c]))
    g.setcell(x,fy+half_height+1,3)
    x -= 1