You were definitely right about that. The reason I was having so many weird problems last time is because the lookahead value of 50 in the linear search phase was not enough to produce optimally packed syntheses. I have increased that to 100 and now the first synthesis is always likely to be good enough to repeat at the minimum rate.
The script now asks for the site separation and the rate at which to repeat the synthesis. Here is the output with repeat rate = 498. It is interesting to note that the first glider collision is actually between a pair of gliders from the 4th construction site!
Here is the code. It should now work with gliders and LWSS from all directions (EDIT: and now sends progress data to the GUI as suggested by dvgrn).
Code: Select all
import golly as g
def make_target(cells):
range_x = range(min(cells[::2]) - 1, max(cells[::2]) + 2)
range_y = range(min(cells[1::2]) - 1, max(cells[1::2]) + 2)
cells = zip(cells[::2], cells[1::2])
rect = set((x, y) for x in range_x for y in range_y)
for x, y in cells:
rect.remove((x, y))
for i, j in [(0,0), (0,-1), (-1,-1),(-1,0)]:
rect.remove((range_x[i], range_y[j]))
x0, y0 = cells[0]
return [(x-x0, y-y0) for x, y in cells], [(x-x0, y-y0) for x, y in rect]
def add_it(objs, s, dx, dy):
cells = g.parse(s)
for i in range(4):
objs.append((make_target(cells), dx, dy))
cells = g.evolve(cells, 1)
def delay_construction(obj_list, delay):
pat = []
phase = -delay % 4
n = (delay + phase) // 4
for cells, dx, dy in obj_list:
pat += g.transform(g.evolve(cells, phase), -n * dx, -n * dy)
return pat
def post_state(current_state, obj_list, delay):
new_state = delay_construction(obj_list, delay)
return g.evolve(current_state + new_state, delay + 256)
objs = []
add_it(objs, '3o$2bo$bo!', 1, -1)
add_it(objs, '3o$o$bo!', -1, -1)
add_it(objs, 'bo$2bo$3o!', 1, 1)
add_it(objs, 'bo$o$3o!', -1, 1)
add_it(objs, '3o$o2bo$o$o$bobo!', 0, -2)
add_it(objs, 'bobo$o$o$o2bo$3o!', 0, 2)
add_it(objs, 'o2bo$4bo$o3bo$b4o!', 2, 0)
add_it(objs, 'bo2bo$o$o3bo$4o!', -2, 0)
rect = g.getselrect()
if not rect:
g.exit("No selection")
site_step = int(g.getstring("Enter step between construction sites"))
delay2 = int(g.getstring("Enter delay for 2nd construction (only relevant for spaceships)", "0"))
offset = 100
cells = g.getcells(g.getselrect())
cells = zip(cells[::2], cells[1::2])
obj_lists = []
for x0, y0 in cells:
for ((wanted, unwanted), dx, dy) in objs:
if all(g.getcell(x0+x, y0+y) for x, y in wanted):
if not any(g.getcell(x0+x, y0+y) for x, y in unwanted):
n = (x0 - rect[0]) // site_step
for _ in range(n-len(obj_lists)+1):
obj_lists.append([])
out_cells = []
for x, y in wanted:
out_cells.append(x0 + x- n * site_step)
out_cells.append(y0 + y)
obj_lists[n].append((out_cells, dx, dy))
best_delay = 200
current_state = delay_construction(obj_lists[0], best_delay)
out_list = [(obj_lists[0], best_delay)]
count=len(obj_lists)
for obj_list in obj_lists[1:]:
count-=1
g.show(str(count))
delay_list = []
step = 512
delay = best_delay + step
delay_list.append(delay)
valid_state = post_state(current_state, obj_list, delay)
while step:
if post_state(current_state, obj_list, delay - step) == valid_state:
delay -= step
delay_list.append(delay)
step //= 2
best_delay = delay
for i in range(1, 100):
if post_state(current_state, obj_list, delay - i) == valid_state:
best_delay = delay - i
delay_list.append(best_delay)
# g.show(str(delay_list))
# while g.getkey() == '':
# pass
current_state += delay_construction(obj_list, best_delay)
out_list.append((obj_list, best_delay))
for obj_list, delay in out_list:
g.putcells(delay_construction(obj_list, delay), -2*offset, offset)
if delay2:
g.putcells(delay_construction(obj_list, delay + delay2), -2*offset, offset)