ConwayLife.com - A community for Conway's Game of Life and related cellular automata
Home  •  LifeWiki  •  Forums  •  Download Golly

Script request thread

For scripts to aid with computation or simulation in cellular automata.

Script request thread

Postby Saka » February 4th, 2016, 8:52 am

This thread is for requesting python scripts, I would like to request a apgcode to rle and if possible rle to apgcode
Everyone, please stop posting B/S about CA
The Bugs Range 1 to 100 Project
User avatar
Saka
 
Posts: 2070
Joined: June 19th, 2015, 8:50 pm
Location: In the kingdom of Sultan Hamengkubuwono X

Re: Script request thread

Postby dvgrn » February 4th, 2016, 11:28 am

Saka wrote:This thread is for requesting python scripts, I would like to request a apgcode to rle and if possible rle to apgcode

The necessary pieces are already available, but kind of scattered around in several threads. Here's a quick-and-dirty attempt to put the apgcode-to-cell-list and cell-list-to-RLE functions together:

apgcode-to-clipboard-RLE.py:
# apgcode-to-clipboard-RLE:
#   takes an input apgcode, and copies equivalent RLE (with a header line)
#   into the clipboard, ready to be pasted into Golly.
#
# decodeCanon function:  creates a pattern cell list from a canonical apgcode,
#   an alphanumeric representation used in apgsearch by Adam P. Goucher
#
# By Arie Paap
# Sept. 2014
#
# ord2() from apgsearch, by Adam P. Goucher

import golly as g

g.setrule("Life")

def decodeCanon(canonPatt):
    chars = "0123456789abcdefghijklmnopqrstuvwxyz"
   
    ox = 0
    x = 0
    y = 0
    clist = []
   
    ii = 0
   
    while ii < len(canonPatt):
        c = canonPatt[ii]
        if (c == 'y'):
            ii += 1
            x += 4 + ord2(canonPatt[ii])
           
        elif (c == 'x'):
            x += 3
       
        elif (c == 'w'):
            x += 2
       
        elif (c == '0'):
            x += 1
       
        elif (c == 'z'):
            x = ox
            y += 5
           
        else:
            u = ord2(c)
            v = 1
            for jj in xrange(0,5):
                if (u & v):
                    clist += [x, y+jj]
                v = v << 1
            x += 1
           
        ii += 1
   
    return clist

# Converts a base-36 case-insensitive alphanumeric character into a
# numerical value.
def ord2(char):

    x = ord(char)

    if ((x >= 48) & (x < 58)):
        return x - 48

    if ((x >= 65) & (x < 91)):
        return x - 55

    if ((x >= 97) & (x < 123)):
        return x - 87

    return -1

# Python function to convert a cell list to RLE
# Author: Nathaniel Johnston (nathaniel@nathanieljohnston.com), June 2009.
#          DMG: Refactored slightly so that the function input is a simple cell list.
#               No error checking added.
#               TBD:  check for multistate rule, show appropriate warning.
# --------------------------------------------------------------------

def chunks(l, n):
    for i in range(0, len(l), n):
        yield l[i:i+n]

# --------------------------------------------------------------------

def giveRLE(clist):
   clist_chunks = list (chunks (g.evolve(clist,0), 2))
   mcc = min(clist_chunks)
   rl_list = [[x[0]-mcc[0],x[1]-mcc[1]] for x in clist_chunks]
   rle_res = ""
   rle_len = 1
   rl_y = rl_list[0][1] - 1
   rl_x = 0
   for rl_i in rl_list:
      if rl_i[1] == rl_y:
         if rl_i[0] == rl_x + 1:
            rle_len += 1
         else:
            if rle_len == 1: rle_strA = ""
            else: rle_strA = str (rle_len)
            if rl_i[0] - rl_x - 1 == 1: rle_strB = ""
            else: rle_strB = str (rl_i[0] - rl_x - 1)

            rle_res = rle_res + rle_strA + "o" + rle_strB + "b"
            rle_len = 1
      else:
         if rle_len == 1: rle_strA = ""
         else: rle_strA = str (rle_len)
         if rl_i[1] - rl_y == 1: rle_strB = ""
         else: rle_strB = str (rl_i[1] - rl_y)
         if rl_i[0] == 1: rle_strC = "b"
         elif rl_i[0] == 0: rle_strC = ""
         else: rle_strC = str (rl_i[0]) + "b"
         
         rle_res = rle_res + rle_strA + "o" + rle_strB + "$" + rle_strC
         rle_len = 1

      rl_x = rl_i[0]
      rl_y = rl_i[1]
   
   if rle_len == 1: rle_strA = ""
   else: rle_strA = str (rle_len)
   rle_res = rle_res[2:] + rle_strA + "o"
   
   return rle_res+"!"

canonPatt = g.getstring('Enter apgcode','xp2_31e8gzoo1vg54','')
canonPatt = canonPatt.strip().lower()
canonPatt = canonPatt.split('_')[-1]

if not canonPatt:
    g.exit('Pattern is empty')

patt = decodeCanon(canonPatt)

RLE = giveRLE(patt)
header="x = " + str(max(patt[0::2])-min(patt[0::2])+1)+", y = " + str(max(patt[1::2])-min(patt[1::2])+1)+", rule = B3/S23\n"
g.setclipstr(header + RLE)
g.show(RLE)

In this implementation, the input is a Golly dialog box, and the output goes to the clipboard. It would be easy to change it so that the input comes from the clipboard also.

It would probably be good to add some error checking in that case -- make sure that what's on the clipboard really looks like an apgcode, before you go trying to convert it. This version should work okay (based on my very minimal testing so far) as long as the input really is a valid apgcode.

The conversion in the other direction is somewhat simpler. You can dig most of it straight out of the old Python version of apgsearch. Can someone else throw that one together?
dvgrn
Moderator
 
Posts: 3938
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI

Re: Script request thread

Postby biggiemac » February 4th, 2016, 7:11 pm

This'll probably work. I tested it for spaceships, still lives and oscillators. Just select a rectangle in golly containing only the pattern you care about (plus any amount of empty space) and the apgcode of the object will go to your clipboard. As a side effect, the script makes a new layer.

You can certainly get nonsense out of it, by selecting an active object or multiple disjoint objects. But if you use it well it'll do the right thing.

import golly as g

# Golly selection to apgcode (in clipboard)
# stolen shamelessly from apgsearch.  Thanks Adam!

def bijoscar(maxsteps):

    initpop = int(g.getpop())
    initrect = g.getrect()
    if (len(initrect) == 0):
        return 0
    inithash = g.hash(initrect)

    for i in xrange(maxsteps):

        g.run(1)

        if (int(g.getpop()) == initpop):

            prect = g.getrect()
            phash = g.hash(prect)

            if (phash == inithash):

                period = i + 1

                if (prect == initrect):
                    return period
                else:
                    return -period
    return -1


def canonise():
   
    p = bijoscar(1000)

    representation = "#"
    for i in range(abs(p)):
        rect = g.getrect()
        representation = compare_representations(representation, canonise_orientation(rect[2], rect[3], rect[0], rect[1], 1, 0, 0, 1))
        representation = compare_representations(representation, canonise_orientation(rect[2], rect[3], rect[0]+rect[2]-1, rect[1], -1, 0, 0, 1))
        representation = compare_representations(representation, canonise_orientation(rect[2], rect[3], rect[0], rect[1]+rect[3]-1, 1, 0, 0, -1))
        representation = compare_representations(representation, canonise_orientation(rect[2], rect[3], rect[0]+rect[2]-1, rect[1]+rect[3]-1, -1, 0, 0, -1))
        representation = compare_representations(representation, canonise_orientation(rect[3], rect[2], rect[0], rect[1], 0, 1, 1, 0))
        representation = compare_representations(representation, canonise_orientation(rect[3], rect[2], rect[0]+rect[2]-1, rect[1], 0, -1, 1, 0))
        representation = compare_representations(representation, canonise_orientation(rect[3], rect[2], rect[0], rect[1]+rect[3]-1, 0, 1, -1, 0))
        representation = compare_representations(representation, canonise_orientation(rect[3], rect[2], rect[0]+rect[2]-1, rect[1]+rect[3]-1, 0, -1, -1, 0))
        g.run(1)
   
    if (p<0):
        prefix = "q"+str(abs(p))
    elif (p==1):
        prefix = "s"+str(g.getpop())
    else:
        prefix = "p"+str(p)

    g.setclipstr("x"+prefix+"_"+representation)

# A subroutine used by canonise:
def canonise_orientation(length, breadth, ox, oy, a, b, c, d):

    representation = ""

    chars = "0123456789abcdefghijklmnopqrstuvwxyz"

    for v in xrange(int((breadth-1)/5)+1):
        zeroes = 0
        if (v != 0):
            representation += "z"
        for u in xrange(length):
            baudot = 0
            for w in xrange(5):
                x = ox + a*u + b*(5*v + w)
                y = oy + c*u + d*(5*v + w)
                baudot = (baudot >> 1) + 16*g.getcell(x, y)
            if (baudot == 0):
                zeroes += 1
            else:
                if (zeroes > 0):
                    if (zeroes == 1):
                        representation += "0"
                    elif (zeroes == 2):
                        representation += "w"
                    elif (zeroes == 3):
                        representation += "x"
                    else:
                        representation += "y"
                        representation += chars[zeroes - 4]
                zeroes = 0
                representation += chars[baudot]
    return representation

# Compares strings first by length, then by lexicographical ordering.
# A hash character is worse than anything else.
def compare_representations(a, b):

    if (a == "#"):
        return b
    elif (b == "#"):
        return a
    elif (len(a) < len(b)):
        return a
    elif (len(b) < len(a)):
        return b
    elif (a < b):
        return a
    else:
        return b

g.duplicate()
g.clear(1)
canonise()



Or, for the extra lazy, a script that will take you directly to the catagolue page.
import golly as g
import webbrowser

# Golly selection directly to catagolue page
# stolen shamelessly from apgsearch.  Thanks Adam!

def bijoscar(maxsteps):

    initpop = int(g.getpop())
    initrect = g.getrect()
    if (len(initrect) == 0):
        return 0
    inithash = g.hash(initrect)

    for i in xrange(maxsteps):

        g.run(1)

        if (int(g.getpop()) == initpop):

            prect = g.getrect()
            phash = g.hash(prect)

            if (phash == inithash):

                period = i + 1

                if (prect == initrect):
                    return period
                else:
                    return -period
    return -1


def canonise():

    p = bijoscar(1000)

    representation = "#"
    for i in range(abs(p)):
        rect = g.getrect()
        representation = compare_representations(representation, canonise_orientation(rect[2], rect[3], rect[0], rect[1], 1, 0, 0, 1))
        representation = compare_representations(representation, canonise_orientation(rect[2], rect[3], rect[0]+rect[2]-1, rect[1], -1, 0, 0, 1))
        representation = compare_representations(representation, canonise_orientation(rect[2], rect[3], rect[0], rect[1]+rect[3]-1, 1, 0, 0, -1))
        representation = compare_representations(representation, canonise_orientation(rect[2], rect[3], rect[0]+rect[2]-1, rect[1]+rect[3]-1, -1, 0, 0, -1))
        representation = compare_representations(representation, canonise_orientation(rect[3], rect[2], rect[0], rect[1], 0, 1, 1, 0))
        representation = compare_representations(representation, canonise_orientation(rect[3], rect[2], rect[0]+rect[2]-1, rect[1], 0, -1, 1, 0))
        representation = compare_representations(representation, canonise_orientation(rect[3], rect[2], rect[0], rect[1]+rect[3]-1, 0, 1, -1, 0))
        representation = compare_representations(representation, canonise_orientation(rect[3], rect[2], rect[0]+rect[2]-1, rect[1]+rect[3]-1, 0, -1, -1, 0))
        g.run(1)
   
    if (p<0):
        prefix = "q"+str(abs(p))
    elif (p==1):
        prefix = "s"+str(g.getpop())
    else:
        prefix = "p"+str(p)

    rule = str.replace(g.getrule(),"/","").lower()
   
    webbrowser.open_new("http://catagolue.appspot.com/object?apgcode=x"+prefix+"_"+representation+"&rule="+rule)

# A subroutine used by canonise:
def canonise_orientation(length, breadth, ox, oy, a, b, c, d):

    representation = ""

    chars = "0123456789abcdefghijklmnopqrstuvwxyz"

    for v in xrange(int((breadth-1)/5)+1):
        zeroes = 0
        if (v != 0):
            representation += "z"
        for u in xrange(length):
            baudot = 0
            for w in xrange(5):
                x = ox + a*u + b*(5*v + w)
                y = oy + c*u + d*(5*v + w)
                baudot = (baudot >> 1) + 16*g.getcell(x, y)
            if (baudot == 0):
                zeroes += 1
            else:
                if (zeroes > 0):
                    if (zeroes == 1):
                        representation += "0"
                    elif (zeroes == 2):
                        representation += "w"
                    elif (zeroes == 3):
                        representation += "x"
                    else:
                        representation += "y"
                        representation += chars[zeroes - 4]
                zeroes = 0
                representation += chars[baudot]
    return representation

# Compares strings first by length, then by lexicographical ordering.
# A hash character is worse than anything else.
def compare_representations(a, b):

    if (a == "#"):
        return b
    elif (b == "#"):
        return a
    elif (len(a) < len(b)):
        return a
    elif (len(b) < len(a)):
        return b
    elif (a < b):
        return a
    else:
        return b

g.duplicate()
g.clear(1)
canonise()
Physics: sophistication from simplicity.
User avatar
biggiemac
 
Posts: 502
Joined: September 17th, 2014, 12:21 am
Location: California, USA

Re: Script request thread

Postby drc » February 6th, 2016, 2:37 pm

Period determiner (the pattern to catalogue script only counts to 4500)?
This post was brought to you by the letter D, for dishes that Andrew J. Wade won't do. (Also Daniel, which happens to be me.)

B2-ac3i4a/S12
User avatar
drc
 
Posts: 1645
Joined: December 3rd, 2015, 4:11 pm
Location: creating useless things in OCA

Re: Script request thread

Postby dvgrn » February 6th, 2016, 5:07 pm

drc wrote:Period determiner (the pattern to catalogue script only counts to 4500)?

What about oscar.py, in Golly's Scripts/Python folder? Should work for any rule you have defined in Golly, for any reasonable period, as long as you're sufficiently patient. Are there other requirements that I'm not understanding?
dvgrn
Moderator
 
Posts: 3938
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI

Re: Script request thread

Postby drc » February 6th, 2016, 5:19 pm

dvgrn wrote:
drc wrote:Period determiner (the pattern to catalogue script only counts to 4500)?

What about oscar.py, in Golly's Scripts/Python folder? Should work for any rule you have defined in Golly, for any reasonable period, as long as you're sufficiently patient. Are there other requirements that I'm not understanding?

Ok, that's a very confusing name, which is why I didn't notice it.
This post was brought to you by the letter D, for dishes that Andrew J. Wade won't do. (Also Daniel, which happens to be me.)

B2-ac3i4a/S12
User avatar
drc
 
Posts: 1645
Joined: December 3rd, 2015, 4:11 pm
Location: creating useless things in OCA

Re: Script request thread

Postby drc » March 6th, 2016, 1:12 pm

A script that tallies the current objects on screen and outputs them apgsearch-style
This post was brought to you by the letter D, for dishes that Andrew J. Wade won't do. (Also Daniel, which happens to be me.)

B2-ac3i4a/S12
User avatar
drc
 
Posts: 1645
Joined: December 3rd, 2015, 4:11 pm
Location: creating useless things in OCA

Re: Script request thread

Postby drc » March 13th, 2016, 9:17 pm

Is there a script that gives out push-pull reactions for replicators? preferrably python please people
This post was brought to you by the letter D, for dishes that Andrew J. Wade won't do. (Also Daniel, which happens to be me.)

B2-ac3i4a/S12
User avatar
drc
 
Posts: 1645
Joined: December 3rd, 2015, 4:11 pm
Location: creating useless things in OCA

Re: Script request thread

Postby dvgrn » March 13th, 2016, 11:33 pm

drc wrote:Is there a script that gives out push-pull reactions for replicators? preferrably python please people

Yes, chris_c has written a Python search script (I think this is a vaguely relevant link, anyway -- looks like there's semi-official code in GitHub also) to enumerate elbow INC and DEC reactions, for 10hd and 0hd construction arms. Paul Chapman did something similar back in 2010 to produce the 9hd construction toolkit used in the linear propagator.

The current single-channel construction arm is still a work in progress -- last I heard, simeks was working on a fast C search program to generate elbow operations. Single-channel seems like the place where searches are most needed. I'm not sure anyone will ever even go back to the very recent 0hd toolkit (pairs of gliders following each other closely on a single lane) -- because you still need two edge-shooting inserters to build those pairs -- or at least one glider stream and one inserter, I suppose.

With the single-channel toolkit, any glider output can be a construction arm -- you don't need any inserters at all. The actual elbow operations are significantly more expensive in terms of the total number of gliders needed, but it looks like that will be more than made up for by not needing to build complex circuitry to synchronize two separate streams of gliders.
dvgrn
Moderator
 
Posts: 3938
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI

Re: Script request thread

Postby drc » March 14th, 2016, 3:52 pm

That's cool, but not what I meant. I meant like the second image on this page:

http://pentadecathlon.com/lifeNews/2013/01/new_highlife_velocities.html

x = 189, y = 197, rule = B36/S23
7bo5bo$6bobo3bobo$6b2o5b2o2$6b2o5b2o$6bobo3bobo$7bo5bo14bo$27b3o$5bo
20b3obo$4b3o18b2o2b3o$3b3obo16b2o3b2o$2b2o2b3o14b3o2b2o$b2o3b2o16bob3o
$3o2b2o18b3o$bob3o20bo$2b3o$3bo9bo$12b3o$11b3obo$10b2o2b3o$9b2o3b2o$8b
3o2b2o$9bob3o30bo$10b3o30b3o$11bo9bo20b3obo$20b3o18b2o2b3o$19b3obo16b
2o3b2obo$18b2o2b3o14b3o2b2ob3o$17b2o3b2obo14bob3ob3obo$16b3o2b2ob3o14b
3ob2o2b3o$17bob3ob3obo14bob2o3b2obo$18b3ob2o2b3o14b3o2b2ob3o$19bob2o3b
2o16bob3ob3obo$20b3o2b2o18b3ob2o2b3o$21bob3o20bob2o3b2obo$22b3o22b3o2b
2ob3o$23bo24bob3ob3obo$49b3ob2o2b3o$50bob2o3b2o$51b3o2b2o$37bo14bob3o$
36b3o14b3o$35b3obo14bo$34b2o2b3o$33b2o3b2obo$32b3o2b2ob3o$33bob3ob3obo
24bo$34b3ob2o2b3o22b3o$35bob2o3b2obo20b3obo$36b3o2b2ob3o18b2o2b3o$37bo
b3ob3obo16b2o3b2obo$38b3ob2o2b3o14b3o2b2ob3o$39bob2o3b2obo14bob3ob3obo
$40b3o2b2ob3o14b3ob2o2b3o$41bob3ob3obo14bob2o3b2o$42b3ob2o2b3o14b3o2b
2o$43bob2o3b2obo14bob3o$44b3o2b2ob3o14b3o$45bob3ob3obo14bo$46b3ob2o2b
3o$47bob2o3b2obo$48b3o2b2ob3o$49bob3ob3obo$50b3ob2o2b3o$51bob2o3b2o$
52b3o2b2o$53bob3o$54b3o$55bo2$92bo$91b3o$69bo20b3obo$68b3o18b2o2b3o$
67b3obo16b2o3b2o$66b2o2b3o14b3o2b2o$65b2o3b2o16bob3o$64b3o2b2o18b3o$
65bob3o20bo9bo$66b3o30b3o$67bo30b3obo$97b2o2b3o$96b2o3b2o$95b3o2b2o$
96bob3o$97b3o$98bo9bo$107b3o$106b3obo$105b2o2b3o$104b2o3b2obo$103b3o2b
2ob3o$89bo14bob3ob3obo$88b3o14b3ob2o2b3o$87b3obo14bob2o3b2obo$86b2o2b
3o14b3o2b2ob3o$85b2o3b2o16bob3ob3obo$84b3o2b2o18b3ob2o2b3o$85bob3o20bo
b2o3b2obo$86b3o22b3o2b2ob3o$87bo24bob3ob3obo$113b3ob2o2b3o$114bob2o3b
2o$115b3o2b2o$101bo14bob3o$100b3o14b3o$99b3obo14bo9bo$98b2o2b3o22b3o$
97b2o3b2o22b3obo$96b3o2b2o22b2o2b3o$97bob3o22b2o3b2o$98b3o22b3o2b2o$
99bo24bob3o$125b3o$126bo2$113bo$112b3o$111b3obo$110b2o2b3o$109b2o3b2o$
108b3o2b2o$109bob3o30bo$110b3o30b3o$111bo9bo20b3obo$120b3o18b2o2b3o$
119b3obo16b2o3b2obo$118b2o2b3o14b3o2b2ob3o$117b2o3b2obo14bob3ob3obo$
116b3o2b2ob3o14b3ob2o2b3o$117bob3ob3obo14bob2o3b2obo$118b3ob2o2b3o14b
3o2b2ob3o$119bob2o3b2o16bob3ob3obo$120b3o2b2o18b3ob2o2b3o$121bob3o20bo
b2o3b2o$122b3o22b3o2b2o$123bo9bo14bob3o$132b3o14b3o$131b3obo14bo9bo$
130b2o2b3o22b3o$129b2o3b2o22b3obo$128b3o2b2o22b2o2b3o$129bob3o22b2o3b
2obo$130b3o22b3o2b2ob3o$131bo9bo14bob3ob3obo$140b3o14b3ob2o2b3o$139b3o
bo14bob2o3b2obo$138b2o2b3o14b3o2b2ob3o$137b2o3b2o16bob3ob3obo$136b3o2b
2o18b3ob2o2b3o$137bob3o20bob2o3b2obo$138b3o22b3o2b2ob3o$139bo24bob3ob
3obo$165b3ob2o2b3o$166bob2o3b2o$167b3o2b2o$153bo14bob3o$152b3o14b3o$
151b3obo14bo9bo$150b2o2b3o22b3o$149b2o3b2o22b3obo$148b3o2b2o22b2o2b3o$
149bob3o22b2o3b2obo$150b3o22b3o2b2ob3o$151bo9bo14bob3ob3obo$160b3o14b
3ob2o2b3o$159b3obo14bob2o3b2o$158b2o2b3o14b3o2b2o$157b2o3b2obo14bob3o$
156b3o2b2ob3o14b3o$157bob3ob3obo14bo$158b3ob2o2b3o$159bob2o3b2obo$160b
3o2b2ob3o$161bob3ob3obo$162b3ob2o2b3o$163bob2o3b2obo$164b3o2b2ob3o$
165bob3ob3obo$166b3ob2o2b3o$167bob2o3b2o$168b3o2b2o$169bob3o$170b3o$
171bo4$185bo$184b3o$183b3obo$182b2o2b3o$181b2o3b2o$180b3o2b2o$181bob3o
$182b3o$183bo!
This post was brought to you by the letter D, for dishes that Andrew J. Wade won't do. (Also Daniel, which happens to be me.)

B2-ac3i4a/S12
User avatar
drc
 
Posts: 1645
Joined: December 3rd, 2015, 4:11 pm
Location: creating useless things in OCA

Re: Script request thread

Postby Sokwe » March 14th, 2016, 7:47 pm

drc wrote:I meant like the second image on this page

I actually found this particular reaction by hand (amazingly). I did write a script for searching for pushes in highlife, but I can't find it right now. The script was extremely simple. Basically, it took an input stationary object and then formed all binary sequences (that start with '1') up to a certain length. The binary sequence represented the placement of the replicator units, so the sequence "111011001" would give
x = 37, y = 37, rule = B36/S23
2b3o$bo2bo$o3bo$o2bo$3o3b3o$5bo2bo$4bo3bo$4bo2bo$4b3o3b3o$9bo2bo$8bo3b
o$8bo2bo$8b3o4$18b3o$17bo2bo$16bo3bo$16bo2bo$16b3o3b3o$21bo2bo$20bo3bo
$20bo2bo$20b3o8$34b3o$33bo2bo$32bo3bo$32bo2bo$32b3o!

It would then test every collision of this sequence with the stationary object and would check to see if the stationary object had moved diagonally after a certain fixed number of generations. It also checked to see if the the stationary object moved, but also flipped over the center diagonal (to find glide-symmetric pushes with two replicators, like Hickerson's (8,8) push).

As I recall, all my search managed to do was rediscover the above push, and find a few block pushes that flipped the block over the center diagonal, but left a bunch of extra debris which interacted too heavily with the replicators, making any clean push reaction difficult. It might have been possible to create a very long sequence of replicators that would slowly clear this debris, but it would probably have been difficult to do without destroying the front block.

I suppose this method could be applied to other rules with replicators, but the code would need to be reworked to match that rule. Anyway, my code wasn't great, and certainly could have missed some things. It might be better if someone just wrote a new script.

I never looked for pull reactions, since we already had such a nice one, but the method would essentially be the same. However, with pull reactions, I think one would have less of an ability to clean up trailing debris, because the pulled object would get in the way of the replicators, not allowing them to clear any debris behind them.
-Matthias Merzenich
Sokwe
Moderator
 
Posts: 1140
Joined: July 9th, 2009, 2:44 pm

Re: Script request thread

Postby Apple Bottom » March 17th, 2016, 8:01 am

biggiemac wrote:This'll probably work. I tested it for spaceships, still lives and oscillators. Just select a rectangle in golly containing only the pattern you care about (plus any amount of empty space) and the apgcode of the object will go to your clipboard. As a side effect, the script makes a new layer.

You can certainly get nonsense out of it, by selecting an active object or multiple disjoint objects. But if you use it well it'll do the right thing.


It's not working for me. No matter what object I'm trying this one (except for the block, that's working somehow), I'm getting the following error:

Traceback (most recent call last):
    File "<string>", line 1, in <module>
    File "apgcode-to-clipboard.py", line 113, in <module>
        canonise()
    File "apgcode-to-clipboard.py", line 41, in canonise
        representation = compare_representations(representation, canonise_orientation(rect[2], rect[3], rect[0], rect[1], 1, 0, 0, 1))
IndexError: list index out of range


Any ideas?
Living proof that a little knowledge is a dangerous thing.

Catagolue: Apple Bottom • Life Wiki: Apple Bottom • Twitter: @_AppleBottom_

Proud member of the Pattern Raiders!
User avatar
Apple Bottom
 
Posts: 713
Joined: July 27th, 2015, 2:06 pm

Re: Script request thread

Postby dvgrn » March 17th, 2016, 9:15 am

Apple Bottom wrote:IndexError: list index out of range...
Any ideas?

Is it possible that you selected the block, but did not select the other objects?

The only way I can think of that that line of code could return a list index out of range error, is if the selection list comes back as [] (no selection) instead of [x,y,w,h].
dvgrn
Moderator
 
Posts: 3938
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI

Re: Script request thread

Postby Apple Bottom » March 17th, 2016, 6:09 pm

dvgrn wrote:Is it possible that you selected the block, but did not select the other objects?

The only way I can think of that that line of code could return a list index out of range error, is if the selection list comes back as [] (no selection) instead of [x,y,w,h].


Ah, no, I found it; Golly was still set to a different rule, one in which the block happened to exist as a still life but where other objects didn't behave as in CGoL.

Thanks for the help, and sorry for the fuss. ;)
Living proof that a little knowledge is a dangerous thing.

Catagolue: Apple Bottom • Life Wiki: Apple Bottom • Twitter: @_AppleBottom_

Proud member of the Pattern Raiders!
User avatar
Apple Bottom
 
Posts: 713
Joined: July 27th, 2015, 2:06 pm

Re: Script request thread

Postby drc » April 7th, 2016, 6:11 pm

drc wrote:A script that tallies the current objects on screen and outputs them apgsearch-style

anybody have this? sorry for being annoying
This post was brought to you by the letter D, for dishes that Andrew J. Wade won't do. (Also Daniel, which happens to be me.)

B2-ac3i4a/S12
User avatar
drc
 
Posts: 1645
Joined: December 3rd, 2015, 4:11 pm
Location: creating useless things in OCA

Re: Script request thread

Postby gameoflifeboy » April 8th, 2016, 11:51 pm

Here's a script I made for that based on Nathaniel's pre-soup-search census program. It'll be improved later, but for now it opens a text file containing a list of all the distinct patterns displayed of period less than 47. It isn't good at separating objects yet.

import golly as g
cens_list = []
clist = []
axx = [1,1,-1,-1,0,0,0,0]
ayy = [1,-1,1,-1,0,0,0,0]
axy = [0,0,0,0,1,1,-1,-1]
ayx = [0,0,0,0,1,-1,1,-1]

census_path = g.getdir('temp') + "census.txt"

# --------------------------------------------------------------------

def getRLE(rl_list):
   rle_res = ""
   rle_len = 1
   rl_list.sort(cmp = lambda x,y: (x[0]-y[0])+500*(x[1]-y[1]))
   rl_y = rl_list[0][1] - 1
   rl_x = 0
   for rl_i in rl_list:
      if rl_i[1] == rl_y:
         if rl_i[0] == rl_x + 1:
            rle_len += 1
         else:
            if rle_len == 1: rle_strA = ""
            else: rle_strA = str (rle_len)
            if rl_i[0] - rl_x - 1 == 1: rle_strB = ""
            else: rle_strB = str (rl_i[0] - rl_x - 1)

            rle_res = rle_res + rle_strA + "o" + rle_strB + "b"
            rle_len = 1
      else:
         if rle_len == 1: rle_strA = ""
         else: rle_strA = str (rle_len)
         if rl_i[1] - rl_y == 1: rle_strB = ""
         else: rle_strB = str (rl_i[1] - rl_y)
         if rl_i[0] == 1: rle_strC = "b"
         elif rl_i[0] == 0: rle_strC = ""
         else: rle_strC = str (rl_i[0]) + "b"
         
         rle_res = rle_res + rle_strA + "o" + rle_strB + "$" + rle_strC
         rle_len = 1

      rl_x = rl_i[0]
      rl_y = rl_i[1]
   
   if rle_len == 1: rle_strA = ""
   else: rle_strA = str (rle_len)
   rle_res = rle_res[2:] + rle_strA + "o"
   
   return rle_res

# --------------------------------------------------------------------

def chunks(l, n):
    for i in range(0, len(l), n):
        yield tuple(l[i:i+n])

# --------------------------------------------------------------------

def census():
   keylist = []

   # Set cct_limit to the maximum number of generations that you want to look for oscillation
   # when building the census. Can be made precise in conjunction with Golly's included oscar.py script
   cct_limit = 46
   
   cct = 1
   cens = {}
   clist = list (chunks (g.getcells (g.getrect()), 2))
   
   cens_list = set(clist[:])
   while cct <= cct_limit:
      g.run(1)
      clist = list (chunks (g.getcells (g.getrect()), 2))
      cens_list = cens_list | set (clist)
      cct += 1
   cens_list = list(cens_list)
   
   while len(cens_list) > 0:
      wt = {}
      curcells = [cens_list.pop(0)]
      for j in curcells:
         g.dokey( g.getkey() )            # allow keyboard interaction
         wu = {}
         tlist=cens_list[:]
         for i in tlist:
            c_dist = [abs(i[0] - j[0]), abs(i[1] - j[1])]
            if (max(c_dist) == 2):
               try:
                  if(wt[i] == 1):
                     curcells.append (i)
                     cens_list.remove (i)
               except:
                  wt[i] = 1
               wu[i] = 1
            elif (max(c_dist) <= 1):         
               curcells.append (i)
               cens_list.remove (i)
         if(len(wu) >= 2):
            for i in wu:
               if not i in curcells:
                  curcells.append (i)
                  cens_list.remove (i)
         
      tccells = curcells[:]
      for j in tccells:
         if not j in clist:
            curcells.remove(j)
     
      if len(curcells) > 0:
         pllist = []
         rlelist = []
         for i in range(0,len(curcells)):
            pllist.append(curcells[i][0])
            pllist.append(curcells[i][1])

         for i in range(0,8):
            rotlist = list (chunks (g.transform(pllist,0,0,axx[i],axy[i],ayx[i],ayy[i]), 2))
            mcc = min(rotlist)
            rotlist = [[x[0]-mcc[0],x[1]-mcc[1]] for x in rotlist]
            curRLE = getRLE(rotlist)
            rlelist.append(curRLE)

         intlist = list(set(keylist) & set(rlelist))
         
         if(len(intlist) > 0):
            cens[intlist[0]] += 1
         else:
            keylist.append(curRLE)
            cens[curRLE] = 1
     
   return cens

censdict = census()

cens = []

for rle in censdict:
   cens.append((rle, censdict[rle]))

cens.sort(key=lambda tup: tup[1])

cens.reverse()

f = open(census_path, 'w')

for tup in cens:
   f.write("%s\t%d\n" % (tup[0], tup[1]))

f.close()

g.open(census_path)
User avatar
gameoflifeboy
 
Posts: 456
Joined: January 15th, 2015, 2:08 am
Location: New Mexico Tech

Re: Script request thread

Postby shouldsee » April 9th, 2016, 9:33 pm

Is there any script capable of searching under 3-state totalistic rules?

Sample patterns of my interest: flashbf7
shouldsee
 
Posts: 368
Joined: April 8th, 2016, 8:29 am

Re: Script request thread

Postby drc » April 13th, 2016, 8:52 pm

Is there a non-totalistic explosive rule oscillator search? (and link if available)
This post was brought to you by the letter D, for dishes that Andrew J. Wade won't do. (Also Daniel, which happens to be me.)

B2-ac3i4a/S12
User avatar
drc
 
Posts: 1645
Joined: December 3rd, 2015, 4:11 pm
Location: creating useless things in OCA

Re: Script request thread

Postby shouldsee » April 24th, 2016, 7:00 am

How do I measure cleanness (of puffers) in multi-state rules?

Update:
I also need a script to generate reactions between objects. At the moment I am thinking about reacting a engine with itself. But I am stuck in varying the phases of the engine.

My current script for such function:
# ship=g.parse(g.getstring("RLE string for your seed","3bo$2b4o$b9o$6ob2ob2o$b9o$2b4o$3bo!"))
def add_ship(x,y):
   g.putcells(ship, x, y, 1, 0, 0, 1, "or")
   

def add_ships(x_1,y_1,x_2,y_2):
   g.select([-10,10,20,20])
   g.clear(1)
   g.clear(0)
   add_ship(0,0)
   add_ship(x_1,y_1)
   add_ship(x_1+x_2,y_1+y_2)

shouldsee
 
Posts: 368
Joined: April 8th, 2016, 8:29 am

Re: Script request thread

Postby shouldsee » May 4th, 2016, 12:40 pm

I would like a script that output a video as a .mc file according to a series of cellist.
shouldsee
 
Posts: 368
Joined: April 8th, 2016, 8:29 am

Re: Script request thread

Postby drc » June 5th, 2016, 11:37 am

n-cell Spatially connected pattern search.
This post was brought to you by the letter D, for dishes that Andrew J. Wade won't do. (Also Daniel, which happens to be me.)

B2-ac3i4a/S12
User avatar
drc
 
Posts: 1645
Joined: December 3rd, 2015, 4:11 pm
Location: creating useless things in OCA

Re: Script request thread

Postby dvgrn » June 5th, 2016, 11:51 am

drc wrote:n-cell Spatially connected pattern search.

Meaning, a script that exhaustively enumerates all n-cell polyplets?

Or will you want to do something with the polpylets once you have them, like run them through apgsearch and see what comes out?
dvgrn
Moderator
 
Posts: 3938
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI

Re: Script request thread

Postby drc » June 5th, 2016, 12:17 pm

dvgrn wrote:
drc wrote:n-cell Spatially connected pattern search.

Meaning, a script that exhaustively enumerates all n-cell polyplets?

Or will you want to do something with the polpylets once you have them, like run them through apgsearch and see what comes out?

Not exactly polyplets, for example:
x = 3, y = 2, rule = B3/S23
o$2bo!

That is not a polyplet, but it is spatially connected. Pretty much, search every pattern of n cells, but throw away the ones that have a cell that is isolated by 2 neighbours, to prevent it searching things like this forever:
x = 192, y = 47, rule = B3/S23
191bo46$o!
This post was brought to you by the letter D, for dishes that Andrew J. Wade won't do. (Also Daniel, which happens to be me.)

B2-ac3i4a/S12
User avatar
drc
 
Posts: 1645
Joined: December 3rd, 2015, 4:11 pm
Location: creating useless things in OCA

Re: Script request thread

Postby dvgrn » June 5th, 2016, 2:43 pm

drc wrote:
dvgrn wrote:
drc wrote:n-cell Spatially connected pattern search.

Meaning, a script that exhaustively enumerates all n-cell polyplets?

Not exactly polyplets... Pretty much, search every pattern of n cells, but throw away the ones that have a cell that is isolated by 2 neighbours...

Does that apply to sufficiently separated groups of cells? Maybe a pattern with isolated groups of two cells should also be thrown away, since it's bound to be equivalent to the same pattern without the domino or diagonal spark... but isolated groups of three or more cells we have to keep, unless it can be shown that they disappear quickly without interacting with anything (?).

What about orientation? It's pretty easy to throw out seven out of eight orientations of most spatially connected patterns, on the grounds that it's equivalent to another pattern that sorts lower on a list (according to some arbitrary sort criteria.)

And again, is the idea to run each of these through apgsearch, or something else?
dvgrn
Moderator
 
Posts: 3938
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI

Re: Script request thread

Postby drc » June 5th, 2016, 2:51 pm

No for the two cell, yes for the symmetry discarding, and yes for apgsearch. Sorry if I wasn't clear
This post was brought to you by the letter D, for dishes that Andrew J. Wade won't do. (Also Daniel, which happens to be me.)

B2-ac3i4a/S12
User avatar
drc
 
Posts: 1645
Joined: December 3rd, 2015, 4:11 pm
Location: creating useless things in OCA

Next

Return to Scripts

Who is online

Users browsing this forum: No registered users and 3 guests