Script request thread

For scripts to aid with computation or simulation in cellular automata.
User avatar
KittyTac
Posts: 533
Joined: December 21st, 2017, 9:58 am

Re: Script request thread

Post by KittyTac » September 27th, 2018, 8:29 am

dvgrn wrote:
Gamedziner wrote:I would like a script that searches for a glider synthesis for a given input pattern, to try to find a synthesis for Sir Robin.
So would I. Actually, I'd like a script that actually finds a synthesis, rather than just searching for it. While I'm wishing, I'd like it to be guaranteed that the synthesis is the most efficient one possible.
Reminds me of http://bash.org/?605501.

Also, even an inefficient synthesis would be fine for a Sir Robin gun. We can optimize it later, but we need the gun ASAP. Why? For science, of course!

User avatar
danny
Posts: 968
Joined: October 27th, 2017, 3:43 pm
Location: New Jersey, USA
Contact:

Re: Script request thread

Post by danny » September 27th, 2018, 3:08 pm

KittyTac wrote: Also, even an inefficient synthesis would be fine for a Sir Robin gun. We can optimize it later, but we need the gun ASAP. Why? For science, of course!
All I'll say is that you are severely underestimating the difficulty of finding a glider synthesis of Sir Robin.
she/they // Please stop using my full name. Refer to me as dani.

"I'm always on duty, even when I'm off duty." -Cody Kolodziejzyk, Ph.D.

User avatar
cordership3
Posts: 127
Joined: August 23rd, 2016, 8:53 am
Location: haha long boy

Re: Script request thread

Post by cordership3 » October 5th, 2018, 10:37 am

A "rule roulette" script that randomly selects transitions for an isotropic two-state rule.
fg

User avatar
dvgrn
Moderator
Posts: 5888
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Script request thread

Post by dvgrn » October 5th, 2018, 12:24 pm

cordership3 wrote:A "rule roulette" script that randomly selects transitions for an isotropic two-state rule.
How should it be different from change-random-isotropic-bit-v1.0.lua?

User avatar
KittyTac
Posts: 533
Joined: December 21st, 2017, 9:58 am

Re: Script request thread

Post by KittyTac » October 5th, 2018, 10:33 pm

dvgrn wrote:
cordership3 wrote:A "rule roulette" script that randomly selects transitions for an isotropic two-state rule.
How should it be different from change-random-isotropic-bit-v1.0.lua?
Yeah, just click it for about 5 minutes until you get a more-or-less-random rule.

User avatar
Goldtiger997
Posts: 546
Joined: June 21st, 2016, 8:00 am
Location: 11.329903°N 142.199305°E

Re: Script request thread

Post by Goldtiger997 » October 6th, 2018, 1:40 am

Does anyone have a script to convert an rle to a plaintext file? It would be very useful to make input files for programs like gencols. I've been searching for a while now and the only one I found was a c program by Mark Niemiec from 1997, which I couldn't get to work.

Thanks in advance!

chris_c
Posts: 907
Joined: June 28th, 2014, 7:15 am

Re: Script request thread

Post by chris_c » October 6th, 2018, 3:38 am

Goldtiger997 wrote:Does anyone have a script to convert an rle to a plaintext file? It would be very useful to make input files for programs like gencols. I've been searching for a while now and the only one I found was a c program by Mark Niemiec from 1997, which I couldn't get to work.

Thanks in advance!
Here's a python script that I use. I call it rle2col.py:

Code: Select all

import sys

d = { 'b': '.', 'o': '*', '$': '!' }

reps = 0
for line in sys.stdin:
    if not "=" in line:
        for x in line:
            if x.isdigit():
                reps = 10 * reps + int(x)
            elif x in d:
                sys.stdout.write(d[x] * max(reps, 1))
                reps = 0
            elif x == "!":
                sys.stdout.write("\n")
Usage: python rle2col.py > output.col, and then paste in your RLE and exit with Ctrl+D.

User avatar
dvgrn
Moderator
Posts: 5888
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Script request thread

Post by dvgrn » October 6th, 2018, 8:56 am

chris_c wrote:
Goldtiger997 wrote:Does anyone have a script to convert an rle to a plaintext file? It would be very useful to make input files for programs like gencols.
Here's a python script that I use. I call it rle2col.py:
...
Usage: python rle2col.py > output.col, and then paste in your RLE and exit with Ctrl+D.
I usually run my Python scripts from inside Golly. Here's my version -- works on the current selection, and copies to the clipboard:

Code: Select all

# makeASCIIforLexicon.py
import golly as g
r = g.getselrect()
s="        "
for y in range(r[3]):
  for x in range(r[2]):
    s+="*" if g.getcell(x+r[0],y+r[1]) == 1 else "."
  s+="\n        "
g.setclipstr(s)
You can get rid of the eight leading spaces if you don't need them, and/or replace the "\n" with "!" to get gencols-compatible output.

wildmyron
Posts: 1274
Joined: August 9th, 2013, 12:45 am

Re: Script request thread

Post by wildmyron » October 8th, 2018, 1:35 am

dvgrn wrote:
cordership3 wrote:A "rule roulette" script that randomly selects transitions for an isotropic two-state rule.
How should it be different from change-random-isotropic-bit-v1.0.lua?
An earlier Python script also written by dvgrn probably matches the request better than change-random-isotropic-bit-v1.0.lua:
http://conwaylife.com/forums/viewtopic. ... 545#p43545
The latest version of the 5S Project contains over 221,000 spaceships. Tabulated pages up to period 160 are available on the LifeWiki.

User avatar
Scorbie
Posts: 1389
Joined: December 7th, 2013, 1:05 am

Re: Script request thread

Post by Scorbie » October 8th, 2018, 10:06 pm

dvgrn wrote:
chris_c wrote:
Goldtiger997 wrote:Does anyone have a script to convert an rle to a plaintext file? It would be very useful to make input files for programs like gencols.
Here's a python script that I use. I call it rle2col.py:
...
Usage: python rle2col.py > output.col, and then paste in your RLE and exit with Ctrl+D.
I usually run my Python scripts from inside Golly. Here's my version -- works on the current selection, and copies to the clipboard:
...
You can get rid of the eight leading spaces if you don't need them, and/or replace the "\n" with "!" to get gencols-compatible output.
Well, sharing pattern2ascii scripts seems to be an interesting trend, so here's mine:

Code: Select all

import golly as g

MULTILINE = True
CR = '\n' if MULTILINE else '!'
CELL_TO_CHAR = ['.', '*']

# Get selection first
r=g.getselrect()
if len(r)==0:
    r=g.getrect()
    if len(r)==0: g.exit("No pattern, nothing to do.")
sel = g.getcells(r)
if len(sel)==0: g.exit("Nothing in selection.")

# And parse!
chars = []
for y in xrange(r[1],r[1]+r[3]):
    for x in xrange(r[0], r[0]+r[2]):
        chars.append(CELL_TO_CHAR[g.getcell(x, y)])
    chars.append(CR)
g.setclipstr(''.join(chars))
g.exit("Copied to clipboard.")
Two params are tweakable:
1. `MULTILINE = True or False` : changes the line seperator (`CR`)
2. `CELL_TO_CHAR`: useful for mapping other rules such as LifeHistory / LifeBellman etc...
Best wishes to you, Scorbie

Sarp
Posts: 203
Joined: March 1st, 2015, 1:28 pm

Re: Script request thread

Post by Sarp » October 9th, 2018, 1:26 am

Is there any script that when you give it a spaceship, it gives a rle of all possible collisions
WADUFI

User avatar
dvgrn
Moderator
Posts: 5888
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Script request thread

Post by dvgrn » October 9th, 2018, 4:40 am

Sarp wrote:Is there any script that when you give it a spaceship, it gives a rle of all possible collisions
Depends. gencols is a powerful tool, with filtering capabilities so you get only what you're looking for -- but it would need to be recompiled for non-Life rules, and isotropic rules aren't supported.

In Golly's Scripts folder, there's a sample script -- pd-glider.lua or pd-glider.py -- that shows how to generate all possible combinations of two objects. It may be worth learning how to adjust one of those to generate collisions between two spaceships of your choice.

In either case, you have to apply your knowledge of the specific spaceship(s) to make sure that you've enumerated all possible collisions. It would take a very sophisticated script to do that analysis for you and come up with all the unique collisions without any duplicates... that would be very nice to have, but nobody has written one because it's painfully difficult.

What rulespace are you asking about? Assumptions that work for Life don't work for other Life-like rules, or isotropic rules, and then if you want to support Larger than Life the details are different again.

User avatar
KittyTac
Posts: 533
Joined: December 21st, 2017, 9:58 am

Re: Script request thread

Post by KittyTac » October 10th, 2018, 10:25 am

Write me a script that selects an entire bounded grid and randomly fills it.

User avatar
dvgrn
Moderator
Posts: 5888
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Script request thread

Post by dvgrn » October 10th, 2018, 12:34 pm

KittyTac wrote:Write me a script that selects an entire bounded grid and randomly fills it.
Apple Bottom wrote:
KittyTac wrote:I can't write scripts.
Nobody was born with that ability, so your mission, should you choose to accept it, is: learn how to do it.
In this case, most of the work would be coming up with a detailed spec. What exactly does it mean, that the script "selects an entire bounded grid"? For the script to select (the contents of) a bounded grid, the bounded grid would have to exist already.

However, I'm guessing you might really mean something like
  • User makes a selection in Golly
  • User runs script
  • If there is no selection, script prints a helpful message and exits
  • Script creates a new layer (?) [maybe not, this is kind of annoying after you run the script several times]
  • Script sets rule for new layer to match current rule, altered to make a bounded grid the size of the existing selection. [Toroidal? Regular bounded plane? Sphere? User can choose what kind of bounds, maybe?]
  • Script uses g.randfill() to fill the entire bounded region with random cells. [50% filled? Random choice of states for multistate rules? Allow user to specify?]
It's hard to be sure enough of what's wanted, to actually start writing the script.

Once a detailed spec is available, the script is about four lines of Lua code, so if you can't figure out how to do it using Golly > Help > Lua Scripting, probably someone won't be able to resist helping to write it -- given a little encouragement in the form of leading questions like "I wrote these four lines, but I'm getting such-and-such mysterious error. What's going wrong?"

Sarp's and others' previous requests on this thread would also be much more likely to be completed if all the details were included.

Writing a spec like this will probably either make it clear exactly how to write the script, or it will make it clear that the request is too vague and it's actually impossible or very difficult to write the script.

User avatar
KittyTac
Posts: 533
Joined: December 21st, 2017, 9:58 am

Re: Script request thread

Post by KittyTac » October 10th, 2018, 9:42 pm

I meant that if the current universe is a bounded grid, it selects it in its entirety and randomly seeds it.

User avatar
dvgrn
Moderator
Posts: 5888
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Script request thread

Post by dvgrn » October 10th, 2018, 10:38 pm

KittyTac wrote:I meant that if the current universe is a bounded grid, it selects it in its entirety and randomly seeds it.
Okay, here you go. Save this in a "MyScripts" folder or some such, and map a key to it in File > Preferences > Keyboard:

Code: Select all

local g = golly()
w, h = g.getwidth(), g.getheight()
if w*h == 0 then g.exit("At least one dimension is not bounded.") end
g.select({-(w//2), -(h//2),w,h})
g.randfill(50)
You can definitely do this level of scripting yourself, by trial and error and looking things up in Golly Help and on Google. I do admit it can be a painful process, but that's basically what I have to do every time.

wildmyron
Posts: 1274
Joined: August 9th, 2013, 12:45 am

Re: Script request thread

Post by wildmyron » October 11th, 2018, 12:54 am

dvgrn wrote:
KittyTac wrote:I meant that if the current universe is a bounded grid, it selects it in its entirety and randomly seeds it.
Okay, here you go. Save this in a "MyScripts" folder or some such, and map a key to it in File > Preferences > Keyboard:

Code: Select all

local g = golly()
w, h = g.getwidth(), g.getheight()
if w*h == 0 then g.exit("At least one dimension is not bounded.") end
g.select({-(w//2), -(h//2),w,h})
g.randfill(50)
You can definitely do this level of scripting yourself, by trial and error and looking things up in Golly Help and on Google. I do admit it can be a painful process, but that's basically what I have to do every time.
It didn't take long for someone to be unable to resist. :D

For multistate rules the, Golly's randfill() can be annoying due to the inability to specify which states to fill with. One solution is to implement a custom random fill function, such as the one from apgsearch. For the case where a random fill with only M out of N states is desired I change the rule to a Generations rule ('//M'), do the fill, and then change it back again. This does have undesirable side effects if only part of the pattern is to be filled, and it changes some settings too, but most of the time they're not a problem. For this script the technique looks like this:

Code: Select all

-- Load Golly's lua interface
local g = golly()

-- Get the width and height of a bounded universe (0 if unbounded)
w, h = g.getwidth(), g.getheight()

-- Error checking
if w*h == 0 then g.exit("At least one dimension is not bounded.") end

-- The number of states to use in the random fill (including 0), stored as a string
fillstates = '3'

-- Store the current rule
rulestr = g.getrule()

-- Change rule to Generations with the desired number of states
-- The .. operator combines two strings into one string
g.setrule('//'..fillstates)

-- Select a bounding box specified in an array: {top_left_x, top_left_y, width, height}
g.select({-(w//2), -(h//2), w, h})

-- Do the fill with a specified probability for non-zero
-- Each non-zero state has equal probability
g.randfill(50)

-- Restore the rule
g.setrule(rulestr)

-- Remove the selection using an empty array
g.select({})
dvgrn wrote:You can definitely do this level of scripting yourself, by trial and error and looking things up in Golly Help and on Google. I do admit it can be a painful process, but that's basically what I have to do every time.
In the interests of fostering this process I've added comments to each line of the script. I hope they are helpful.
The latest version of the 5S Project contains over 221,000 spaceships. Tabulated pages up to period 160 are available on the LifeWiki.

User avatar
danny
Posts: 968
Joined: October 27th, 2017, 3:43 pm
Location: New Jersey, USA
Contact:

Re: Script request thread

Post by danny » October 27th, 2018, 7:16 pm

Someone should write an extension that checks a user's (most likely your) discoveries page every 30 minutes and reports anything new you've discovered.
she/they // Please stop using my full name. Refer to me as dani.

"I'm always on duty, even when I'm off duty." -Cody Kolodziejzyk, Ph.D.

User avatar
Senso
Posts: 18
Joined: November 1st, 2018, 11:36 am
Location: I call that one "shoving match"

Re: Script request thread

Post by Senso » November 1st, 2018, 2:35 pm

danny wrote:Someone should write an extension that checks a user's (most likely your) discoveries page every 30 minutes and reports anything new you've discovered.
I wrote a quick script that does just that and posts new discoveries of mine on a slack channel. It scrapes the /<user>/all#discoveries page and compares with a local copy. I'm not sure if it would impact the site if a lot of people scraped that rather heavy page constantly though. If it's frowned upon, I'll actually stop it.

User avatar
danny
Posts: 968
Joined: October 27th, 2017, 3:43 pm
Location: New Jersey, USA
Contact:

Re: Script request thread

Post by danny » November 1st, 2018, 11:57 pm

Senso wrote:
danny wrote:Someone should write an extension that checks a user's (most likely your) discoveries page every 30 minutes and reports anything new you've discovered.
I wrote a quick script that does just that and posts new discoveries of mine on a slack channel. It scrapes the /<user>/all#discoveries page and compares with a local copy. I'm not sure if it would impact the site if a lot of people scraped that rather heavy page constantly though. If it's frowned upon, I'll actually stop it.
Ooh. Sadly I don't have slack.
she/they // Please stop using my full name. Refer to me as dani.

"I'm always on duty, even when I'm off duty." -Cody Kolodziejzyk, Ph.D.

User avatar
Senso
Posts: 18
Joined: November 1st, 2018, 11:36 am
Location: I call that one "shoving match"

Re: Script request thread

Post by Senso » November 2nd, 2018, 12:55 pm

danny wrote:Ooh. Sadly I don't have slack.
You can basically just parse the HTML page and keep a copy of the objects you've found and print the difference when it finds a new one. A REST API on Catagolue would be awesome though. ;)

A quick and dirty script that checks Catagolue every 30 minutes is below. Be mindful not to hit the site too often/too quickly, removing the sleep() call would DOS it.

Code: Select all

import urllib2
import cPickle
import os
import re

USERNAME = 'your Catagolue username'

def parse_cata():
    try:
        url = 'https://catagolue.appspot.com/user/%s/all#discoveries' % USERNAME
        fd = urllib2.urlopen(url, timeout=10)
        data = fd.read()
    except urllib2.URLError:
        print "Couldn't connect to Catagolue"
        return

    try:
        with open('catagolue.data') as derp:
            all_finds = cPickle.load(derp)
    except:
        all_finds = {}

    pattern = re.compile('\<a href=\"\/object\/(.+)\/(.+)\"\>')

    objects = re.findall(pattern, data)
    if objects:
        for obj in objects:
            if obj not in all_finds:
                all_finds[obj] = True
                url = "https://catagolue.appspot.com/object/%s/%s" % (obj[0], obj[1])
                txt = "You found a new pattern: %s " % (url,)
                print txt

    with open('catagolue.data', 'wb') as derp:
        cPickle.dump(all_finds, derp)

if __name__ == '__main__':
    while True:
        parse_cata()
        os.sleep(1800) # sleep for 30 minutes

muzik
Posts: 3504
Joined: January 28th, 2016, 2:47 pm
Location: Scotland

Re: Script request thread

Post by muzik » November 2nd, 2018, 1:15 pm

Are there any search programs that can be used to find replicators? I'm thinking something like rulesrc.
Bored of using the Moore neighbourhood for everything? Introducing the Range-2 von Neumann isotropic non-totalistic rulespace!

Ian07
Posts: 351
Joined: September 22nd, 2018, 8:48 am

Re: Script request thread

Post by Ian07 » November 3rd, 2018, 12:50 pm

Does anyone know of a script which can convert RLEs into Heinrich Koenig's small object format?

EDIT: Just learned that Catagolue Reloaded does this, so I'll try using that for now.

EDIT 2: Got Opera and the extension, everything else works fine but the Pentadecathlon link doesn't. :?

wildmyron
Posts: 1274
Joined: August 9th, 2013, 12:45 am

Re: Script request thread

Post by wildmyron » November 4th, 2018, 11:30 pm

Ian07 wrote:Does anyone know of a script which can convert RLEs into Heinrich Koenig's small object format?

EDIT: Just learned that Catagolue Reloaded does this, so I'll try using that for now.

EDIT 2: Got Opera and the extension, everything else works fine but the Pentadecathlon link doesn't. :?
In case it might be useful to anyone, here is an almost complete Python implementation for Golly which I hacked up years ago. Unless there are other issues, the only thing missing is representing spaceships in the standard form according to the spec for direction traveled. It encodes the pattern in the current layer rather than converting rle and copies the sof representation of the pattern to the clipboard. If you want an rle converter it should be just a matter of inserting a few lines to place the pattern in a new layer.

Code: Select all

# Canonical small object format representation
# Representation for CGoL objects devised by Heinrich Koenig
# Format description at http://conwaylife.com/wiki/SOF
# Further information at http://www.pentadecathlon.com/objects/definitions/definitions.php
# Determine the canonical small object format representation of the current
# pattern using the comparison rules. Special case rules for spaceships are 
# not yet implemented.
#
# By Arie Paap
# Oct. 2014

import golly as g

# Obtains a canonical representation of the current pattern
# Uses algorithm by Adam P. Goucher
def sof_canonise(duration):

    sof = ""
    
    # We need to compare each phase to find the one used to determine the
    # pattern's standard form:
    for t in xrange(duration):

        if (duration > 1):
			g.run(1)
            
    rect = g.getrect()
    if (len(rect) == 0):
        return "0"

    ox = rect[0]
    oy = rect[1]
    x_length = rect[2]
    y_breadth = rect[3]
        
    # Choose the orientation which comes first according to sof comparison rules:
    sof = sof_representation(x_length, y_breadth, ox, oy, 1, 0, 0, 1)
    sof = sof_compare(sof, sof_representation(x_length, y_breadth, ox+x_length-1, oy, -1, 0, 0, 1)) # flip_x
    sof = sof_compare(sof, sof_representation(x_length, y_breadth, ox, oy+y_breadth-1, 1, 0, 0, -1)) # flip_y
    sof = sof_compare(sof, sof_representation(x_length, y_breadth, ox+x_length-1, oy+y_breadth-1, -1, 0, 0, -1)) # 180
    sof = sof_compare(sof, sof_representation(y_breadth, x_length, ox, oy, 0, 1, 1, 0)) # swap_xy
    sof = sof_compare(sof, sof_representation(y_breadth, x_length, ox+x_length-1, oy, 0, -1, 1, 0)) # cw 90
    sof = sof_compare(sof, sof_representation(y_breadth, x_length, ox, oy+y_breadth-1, 0, 1, -1, 0)) # ccw 90
    sof = sof_compare(sof, sof_representation(y_breadth, x_length, ox+x_length-1, oy+y_breadth-1, 0, -1, -1, 0)) # swap_xy_flip

    return sof

# Determine sof for current pattern in specified orientation:
def sof_representation(length, breadth, ox, oy, a, b, c, d):

    sof = ""
    
    for v in xrange(breadth):
        value = 1
        run = 0
        blank = True
        if (v != 0):
            sof += "-"
        for u in xrange(length+1):
            x = ox + a*u + b*v
            y = oy + c*u + d*v
            
            if (g.getcell(x,y) == value):
                # Continue the run
                run += 1
            else:
                # Encode the run, unless a run of zeros reaches the boundary
                if (u < length or value == 1):
                    while (run > 78):
                        run -= 78
                        sof += "~0"
                    sof += chr(run + ord('0'))
                run = 1
                value = 1 - value   # Toggle value
            if (value==1):
                blank = False
        if (blank == True):
            # Remove unnecessary '0'
            sof = sof[:-2] + '-'
    sof += "."
    return sof

# Compares two sof patterns according to sof comparison rules.
def sof_compare(a, b):
    
    alines = str.split(a, '-')
    blines = str.split(b, '-')
    aline = ''
    bline = ''
    
    # Find first line with different cell
    for line in xrange(0, len(a)):
        aline = alines[line]
        bline = blines[line]
        if not (aline == bline):
            break
    
    # Find first difference
    value = 1
    ii = 0
    for ii in xrange(0, min(len(aline), len(bline))):
        if not (aline[ii] == bline[ii]):
            break
        value = 1 - value
    
    if (value == 1):
        if int(aline[ii]) > int(bline[ii]):
            return a
        else:
            return b
    else:
        if int(aline[ii]) > int(bline[ii]):
            return b
        else:
            return a
    
    g.warn("Did not compare")
    
    return '#'

p = int(g.getstring("Enter period of pattern", "1"))
canonPatt = sof_canonise(p)
g.setclipstr(canonPatt)
g.show("SOF representation of pattern is: " + canonPatt + " (copied to clipboard).")
The latest version of the 5S Project contains over 221,000 spaceships. Tabulated pages up to period 160 are available on the LifeWiki.

User avatar
Apple Bottom
Posts: 1027
Joined: July 27th, 2015, 2:06 pm
Contact:

Re: Script request thread

Post by Apple Bottom » November 5th, 2018, 4:32 am

Ian07 wrote:EDIT: Just learned that Catagolue Reloaded does this, so I'll try using that for now.

EDIT 2: Got Opera and the extension, everything else works fine but the Pentadecathlon link doesn't. :?
The extension does it, but rather poorly I'm afraid.

I originally hacked something together to be able to do the same LifeWiki work you're doing now, but after being done with the still lifes (for which it did work), the benefit of fixing it to also work for other patterns did not meet the cost of doing so. :)

Patches to the extension are welcome of course, the extension code is on Github.
If you speak, your speech must be better than your silence would have been. — Arabian proverb

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

Proud member of the Pattern Raiders!

Post Reply