Hacking apgsearch

For scripts to aid with computation or simulation in cellular automata.
Post Reply
User avatar
Scorbie
Posts: 1693
Joined: December 7th, 2013, 1:05 am

Re: Hacking apgsearch

Post by Scorbie » December 17th, 2015, 6:46 pm

drc wrote:I still get the error:

line 37 in <module>
from glife import rect, pattern
ImportError: No module named glife
That's related to python's importing system. As a permanent fix, copy the glife folder (and its files) to where your script is in. Like this:

Code: Select all

My_Script_Directory
ㄴapgsearch
ㄴglife
  ㄴ__init__.py
  ㄴ....

User avatar
Saka
Posts: 3627
Joined: June 19th, 2015, 8:50 pm
Location: Indonesia
Contact:

Re: Hacking apgsearch

Post by Saka » December 18th, 2015, 1:49 am

A for awesome wrote:Hello everyone,

I made a hacked version of apgsearch that works on all 2-state isotropic Moore-neighborhood cellular automata (tlife, SansDomino rules, etc.). Here it is:(attachment)
MAN that is useful! Does it upload the haul to the server?
EDIT: It renders this:

Code: Select all

x = 38, y = 87, rule = tlife
16bo$6b2o7bobo$5bo2bo6bobo$5bobo8bo$6bo7$28b2o$28b2o6$b2o13b3o17bo$o2b
o13bo17bobo$b2o32bobo$9b2o25bo$9b2o7$25b2o$25b2o55$17b3o$18bo!
As "oversized"

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

Re: Hacking apgsearch

Post by Scorbie » December 18th, 2015, 10:03 am

A for awesome wrote:Hello everyone,

I made a hacked version of apgsearch that works on all 2-state isotropic Moore-neighborhood cellular automata (tlife, SansDomino rules, etc.). Here it is:
Glad to see this :) Thanks for your work! (I think wildmyron worked on somthing similar too...?)
For some reason, x-rule-pre is REALLY slow... (0 soups/second, took about two hours to process 600 soups.) Is it just my really old computer? Some strange things:
1 )Most of the time apgsearch behaves just like normal apgsearch (I mean flickering), but the screen is empty. (pop=0)
2) There were a whole lot of beehives in the unidentified objects page that shows up after the search is finished.
3) There's xq1_0 that is saved as the following:

Code: Select all

x = 40, y = 40, rule = x-rule-pre
b$
b$
b$
b$
b$
!
Which comes out empty when opened in golly.

EDIT: More things to note:
No gliders marked as xq
No oscilators noted other than the blinker, which itself is unstable.

User avatar
praosylen
Posts: 2449
Joined: September 13th, 2014, 5:36 pm
Location: Pembina University, Home of the Gliders
Contact:

Re: Hacking apgsearch

Post by praosylen » December 18th, 2015, 10:21 am

Scorbie wrote: For some reason, x-rule-pre is REALLY slow... (0 soups/second, took about two hours to process 600 soups.) Is it just my really old computer? Some strange things:
1 )Most of the time apgsearch behaves just like normal apgsearch (I mean flickering), but the screen is empty. (pop=0)
2) There were a whole lot of beehives in the unidentified objects page that shows up after the search is finished.
3) There's xq1_0 that is saved as the following:

Code: Select all

x = 40, y = 40, rule = x-rule-pre
b$
b$
b$
b$
b$
!
Which comes out empty when opened in golly.
1. Wow, that's weird... Maybe I should include a rule to expunge dominoes and duoplets in the next version (maybe also the common x-pre gliders)?
2. No idea what that's about; will try to figure out what's going on.
3. What does the sample soup produce? Is there an unusual oscillator produced? If so, it probably got separated improperly.

Would you check whether the rule table is correct? (Same as the one in your Rules folder; no lines starting with variables.) There might be an error pertaining to the ClassifyObjects or ContagiousLife rules; either of those issues could cause that error.
former username: A for Awesome
praosylen#5847 (Discord)

The only decision I made was made
of flowers, to jump universes to one of springtime in
a land of former winter, where no invisible walls stood,
or could stand for more than a few hours at most...

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

Re: Hacking apgsearch

Post by Scorbie » December 18th, 2015, 10:29 am

Before any diagnosis, I may have done something wrong when I made that profile thingy. I'll get a new version and run it again... Please wait for a moment...
A for awesome wrote:Would you check whether the rule table is correct? (Same as the one in your Rules folder; no lines starting with variables.) There might be an error pertaining to the ClassifyObjects or ContagiousLife rules; either of those issues could cause that erro
Yikes. Didn't know that a rule file should not have a line starting with variables... But any variable declaration should start with a variable isn't it? Do you mean that the rule file should have no variables?

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

Re: Hacking apgsearch

Post by Scorbie » December 18th, 2015, 10:34 am

Stripped the last post for clarity.
Moved x-rule-pre to Golly's Rules folder instead of my custom rule folder, used vanilla apgsearch hack and umm...

Code: Select all

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/scorbie/Apps/golly/Scripts/Perl/apgsearch-2015-12-17-v0.54+0.1i.py", line 11807, in <module>
    soup.rg.saveAllRules()
  File "/home/scorbie/Apps/golly/Scripts/Perl/apgsearch-2015-12-17-v0.54+0.1i.py", line 602, in saveAllRules
    self.saveClassifyObjects()
  File "/home/scorbie/Apps/golly/Scripts/Perl/apgsearch-2015-12-17-v0.54+0.1i.py", line 1225, in saveClassifyObjects
    i = lines1[q]
IndexError: list index out of range
Whoops...

User avatar
praosylen
Posts: 2449
Joined: September 13th, 2014, 5:36 pm
Location: Pembina University, Home of the Gliders
Contact:

Re: Hacking apgsearch

Post by praosylen » December 18th, 2015, 10:43 am

Scorbie wrote:Yikes. Didn't know that a rule file should not have a line starting with variables... But any variable declaration should start with a variable isn't it? Do you mean that the rule file should have no variables?
Variable declarations are allowed; and they start with "var", not a variable name. Transitions in the rule table were too hard to implement (I may allow them in the next version).
Scorbie wrote:Stripped the last post for clarity.
Moved x-rule-pre to Golly's Rules folder instead of my custom rule folder, used vanilla apgsearch hack and umm...

Code: Select all

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/scorbie/Apps/golly/Scripts/Perl/apgsearch-2015-12-17-v0.54+0.1i.py", line 11807, in <module>
    soup.rg.saveAllRules()
  File "/home/scorbie/Apps/golly/Scripts/Perl/apgsearch-2015-12-17-v0.54+0.1i.py", line 602, in saveAllRules
    self.saveClassifyObjects()
  File "/home/scorbie/Apps/golly/Scripts/Perl/apgsearch-2015-12-17-v0.54+0.1i.py", line 1225, in saveClassifyObjects
    i = lines1[q]
IndexError: list index out of range
Whoops...
No idea what that's about; could you post your .rule file? I will get on it as soon as I have access to a non-school computer; probably about 4 hours from now.

P.S. Why did you put it in your Perl scripts folder? It's a Python script! (I don't think it makes any real difference, though.)
former username: A for Awesome
praosylen#5847 (Discord)

The only decision I made was made
of flowers, to jump universes to one of springtime in
a land of former winter, where no invisible walls stood,
or could stand for more than a few hours at most...

wildmyron
Posts: 1547
Joined: August 9th, 2013, 12:45 am
Location: Western Australia

Re: Hacking apgsearch

Post by wildmyron » December 18th, 2015, 3:09 pm

Scorbie wrote:
A for awesome wrote:Hello everyone,

I made a hacked version of apgsearch that works on all 2-state isotropic Moore-neighborhood cellular automata (tlife, SansDomino rules, etc.). Here it is:
Glad to see this :) Thanks for your work! (I think wildmyron worked on somthing similar too...?)
Indeed, great to see some interest in this. I have indeed worked on something similar and despite much hesitation I'm just going to post it in it's current state in the hope that it can help further development. I took a different approach to the rule generating - it's quite interesting to see the way this version interprets an existing rule file and generates the auxillary rules from that. Instead I based the rule generator on EricG's rule table generating script for non-totalistic rules "Hensel-TableGen.py".

The rule generator class is actually in a separate file which makes it easier to use parts of it for other purposes (e.g. isotropicRulegen.py does basically the same as Hensel-TableGen.py but using the http://www.ibiblio.org/lifepatterns/neighbors2.html version of Hensel's notation. I had intended to seperate the soup generating and censusing code into a separate file as well and then have a totalistic and non-totalistic version of apgsearch with custom code for each and all the common code in separate files, but I'm not very good at finishing off such projects. I have a different version of APG_ExpungeObjects - named APG_ExpungeSmallSL - which handles dominoes and I-trominoes as well as blocks. This file has to be manually copied to the rules folder because it's not created by the rule generator. Another version of that identifies SL checkers instead of I-trominoes. Using the most appropriate expunge rule for the rule being searched is one of the stumbling blocks on my TODO list.

Another stumbling block was how to deal with rules with common puffers. As a stop gap I've reduced the maximum step that the auxillary rules run for which reduces the size of the puffers that need to be censused and disabled error correction. Additionally, I believe the stabilisation detection should also be customised for the rule being searched - particularly so that the common oscillator periods don't thwart the stabilisation detection. Those p160 oscillators in tlife are a real headache in that regard.

As far as object scoring goes - that's currently a real mess. I was very tempted to remove it completely and just focus on the census results rather than the soups. I've also tried to improve the non-interacting spaceship separation somewhat, but that's still unreliable.

As for performance - it's usable for butterfly. I see about 20-30 soups/sec with C1 soups and more for D8_4. Other rules / symmetries are variable in their performance depending on puffer frequency and common oscillator periods.
Attachments
apgsearch-isotropic-v0.2.zip
WIP
(20.65 KiB) Downloaded 943 times
The 5S project (Smallest Spaceships Supporting Specific Speeds) is now maintained by AforAmpere. The latest collection is hosted on GitHub and contains well over 1,000,000 spaceships.

Semi-active here - recovering from a severe case of LWTDS.

User avatar
praosylen
Posts: 2449
Joined: September 13th, 2014, 5:36 pm
Location: Pembina University, Home of the Gliders
Contact:

Re: Hacking apgsearch

Post by praosylen » December 18th, 2015, 5:18 pm

A for awesome wrote:
Scorbie wrote:Moved x-rule-pre to Golly's Rules folder instead of my custom rule folder, used vanilla apgsearch hack and umm...

Code: Select all

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/scorbie/Apps/golly/Scripts/Perl/apgsearch-2015-12-17-v0.54+0.1i.py", line 11807, in <module>
    soup.rg.saveAllRules()
  File "/home/scorbie/Apps/golly/Scripts/Perl/apgsearch-2015-12-17-v0.54+0.1i.py", line 602, in saveAllRules
    self.saveClassifyObjects()
  File "/home/scorbie/Apps/golly/Scripts/Perl/apgsearch-2015-12-17-v0.54+0.1i.py", line 1225, in saveClassifyObjects
    i = lines1[q]
IndexError: list index out of range
Whoops...
No idea what that's about; could you post your .rule file? I will get on it as soon as I have access to a non-school computer; probably about 4 hours from now.
Here's a dirty patch for the errors you are getting: Replace lines 1054 to the end of RuleGenerator.saveContagiousLife() with this:

Code: Select all

    def saveCoalesceObjects(self):

        comments = """
A variant of HistoricalLife which separates a field of ash into
distinct objects.

state 0:  vacuum
state 1:  ON
state 2:  OFF
"""
        table = "n_states:3\n"
        table += "neighborhood:Moore\n"
        
        if ruletype: #Outer-totalistic
            table += "symmetries:permute\n\n"
    
            table += self.newvars(["a","b","c","d","e","f","g","h","i"], [0, 1, 2])
            table += self.newvars(["da","db","dc","dd","de","df","dg","dh","di"], [0, 2])
            table += self.newvars(["la","lb","lc","ld","le","lf","lg","lh","li"], [1])
    
            minperc = 10
    
            for i in xrange(9):
                if (self.bee[i]):
                    if (minperc == 10):
                        minperc = i
                    table += self.scoline("l","d",0,1,i)
                    table += self.scoline("l","d",2,1,i)
                if (self.ess[i]):
                    table += self.scoline("l","d",1,1,i)
    
            table += "\n# Bridge inductors\n"
    
            for i in xrange(9):
                if (i >= minperc):
                    table += self.scoline("l","d",0,2,i)
    
            table += self.scoline("","",1,2,0)
        else: #Isotropic non-totalistic
            rule1 = open(g.getdir("app") + "Rules/" + self.slashed + ".rule", "r")
            lines1 = rule1.read().split("\n")
            rule1.close()
            for q in xrange(len(lines1)-1):
                if lines1[q].startswith("@TABLE"):
                    lines1 = lines1[q:]
                    break
            vars = []
            for q in xrange(len(lines1)-1): #Copy symmetries and vars
                i = lines1[q]
                if i[:2] == "sy" or i[:1] == "sy":
                    table += i + "\n\n"
                if i[:2] == "va" or i[:1] == "va":
                    table += self.newvar(i[4:5].replace("=", ""), [0, 1, 2])
                    vars.append(i[4:5].replace("=", ""))
                if i != "":
                    if i[0] == "0" or i[0] == "1":
                        break
            
            alpha = "abcdefghijklmnopqrstuvwxyz"
            vars2 = []
            for i in alpha: 
                if not i in [n[0] for n in vars]: #Create new set of vars for OFF cells
                    table += self.newvars([i + j for j in alpha[:9]], [0, 2])
                    vars2 = [i + j for j in alpha[:9]]
                    break
                    
            for i in alpha: 
                if not i in [n[0] for n in vars] and not i in [n[0] for n in vars2]:
                    for j in xrange(5-len(vars)):
                        table += self.newvar(i + alpha[j], [0, 1, 2])
                        vars.append(i + alpha[j])
                    break
            
            for i in lines1:
                q = i.split("#")[0].replace(" ", "").split(",")
                if len(q) > 1 and not i.startswith("var"):
                    vn = 0
                    vn2 = 0
                    for j in q[:-1]:
                        if j == "0":
                            table += vars2[vn2]
                            vn2 += 1
                        elif j == "1":
                            table += "1"
                        elif j != "#":
                            g.show(str(len(vars)))
                            table += vars[vn]
                            vn += 1
                        table += ","
                    table += str(2-int(q[len(q)-1]))
                    table += "\n"
                
            for i in xrange(256): #Get all B3+ rules
                ncells = 0
                for j in xrange(8):
                    if (i & 2**j) > 0:
                        ncells += 1
                if ncells == 3:
                    q = "0,"
                    vn = 0
                    for j in xrange(8):
                        if i & 2**j > 0:
                            q += str((i & 2**j)/2**j) + ","
                        else:
                            q += vars[vn] + ","
                            vn += 1
                    q += "2\n"
                    table += q
                
        colours = """
0    0    0    0
1  255  255  255
2  127  127  127
"""
        self.saverule("APG_CoalesceObjects_"+self.alphanumeric, comments, table, colours)
    
    def saveClassifyObjects(self):

        comments = """
This passively classifies objects as either still-lifes, p2 oscillators
or higher-period oscillators. It is mandatory that one first runs the
rule CoalesceObjects.

state 0:  vacuum
state 1:  input ON
state 2:  input OFF

state 3:  ON, will die
state 4:  OFF, will remain off
state 5:  ON, will survive
state 6:  OFF, will become alive

state 7:  ON, still-life
state 8:  OFF, still-life

state 9:  ON, p2 oscillator
state 10: OFF, p2 oscillator

state 11: ON, higher-period object
state 12: OFF, higher-period object
"""
        table = "n_states:17\n"
        table += "neighborhood:Moore\n"
        if ruletype: #Outer-totalistic
            table += "symmetries:permute\n\n"
    
            table += self.newvars(["a","b","c","d","e","f","g","h","i"], range(0, 17, 1))
            table += self.newvars(["la","lb","lc","ld","le","lf","lg","lh","li"], range(1, 17, 2))
            table += self.newvars(["da","db","dc","dd","de","df","dg","dh","di"], range(0, 17, 2))
            table += self.newvars(["pa","pb","pc","pd","pe","pf","pg","ph","pi"], [0, 3, 4])
            table += self.newvars(["qa","qb","qc","qd","qe","qf","qg","qh","qi"], [5, 6])
    #Serious modifications necessary:
            for i in xrange(9):
                if (self.bee[i]):
                    table += self.scoline("l","d",2,6,i)
                    table += self.scoline("q","p",3,9,i)
                    table += self.scoline("q","p",4,12,i)
                if (self.ess[i]):
                    table += self.scoline("l","d",1,5,i)
                    table += self.scoline("q","p",5,7,i)
                    table += self.scoline("q","p",6,12,i)
            table += self.scoline("","",2,4,0)
            table += self.scoline("","",1,3,0)
            table += self.scoline("","",5,11,0)
            table += self.scoline("","",3,11,0)
            table += self.scoline("","",4,8,0)
            table += self.scoline("","",6,10,0)
        
        else: #Isotropic non-totalistic
            rule1 = open(g.getdir("app") + "Rules/" + self.slashed + ".rule", "r")
            lines1 = rule1.read().split("\n")
            rule1.close()
            for q in xrange(len(lines1)-1):
                if lines1[q].startswith("@TABLE"):
                    lines1 = lines1[q:]
                    break
                if lines1[0].startswith("@TREE"):
                    g.warn("apgsearch v.0.54+0.1i does not support rule trees")
            vars = []
            for q in xrange(len(lines1)-1): #Copy symmetries and vars
                i = lines1[q]
                if i[:2] == "sy" or i[:1] == "sy":
                    table += i + "\n\n"
                if i[:2] == "va" or i[:1] == "va":
                    table += self.newvar(i[4:5].replace("=", ""), [0, 1, 2])
                    vars.append(i[4:5].replace("=", ""))
                if i != "":
                    if i[0] == "0" or i[0] == "1":
                        break
            alpha = "abcdefghijklmnopqrstuvwxyz"
            ovars = []
            for i in alpha: 
                if not i in [n[0] for n in vars]: #Create new set of vars for ON cells
                    table += self.newvars([i + j for j in alpha[:9]], [1, 5, 6])
                    ovars = [i + j for j in alpha[:9]]
                    break
            
            dvars = []
            for i in alpha: 
                if not i in [n[0] for n in vars] and not i in [n[0] for n in ovars]: #Create new set of vars for OFF cells
                    table += self.newvars([i + j for j in alpha[:9]], [0, 2, 3, 4])
                    dvars = [i + j for j in alpha[:9]]
                    break
                    
            for i in alpha: 
                if not i in [n[0] for n in vars] and not i in [n[0] for n in ovars] and not i in [n[0] for n in dvars]:
                    for j in xrange(8-len(vars)):
                        table += self.newvar(i + alpha[j], [0, 1, 2, 3, 4, 5, 6])
                        vars.append(i + alpha[j])
                    break
            
            for i in lines1:
                q = i.split("#")[0].replace(" ", "").split(",")
                if len(q) > 1:
                    vn = 0
                    ovn = 0
                    dvn = 0
                    if q[0] == "0" or q[0] == "1":
                        if q[0] == "0":
                            table += "2"
                        elif q[0] == "1":
                            table += "1"
                        elif q[0] != "#":
                            table += vars[vn]
                            vn += 1
                        table += ","
                        for j in q[1:-1]:
                            if j == "0":
                                table += dvars[dvn]
                                dvn += 1
                            elif j == "1":
                                table += "1"
                            elif j != "#":
                                table += vars[vn]
                                vn += 1
                            table += ","
                        table += str(4-int(q[0])+2*int(q[len(q)-1]))
                        table += "\n"
                    elif not i.startswith("var"): #Line starts with a variable.
                        table += vars[vn] + ","
                        vn += 1
                        for j in q[1:-1]:
                            if j == "0":
                                table += dvars[dvn]
                                dvn += 1
                            elif j == "1":
                                table += "1"
                            elif j != "#":
                                table += vars[vn]
                                vn += 1
                            table += ","
                        table += str(4+2*int(q[len(q)-1]))
                        table += "\n1,"
                        vn = 0
                        for j in q[1:-1]:
                            if j == "0":
                                table += "2"
                            elif j == "1":
                                table += "1"
                            elif j != "#":
                                table += vars[vn]
                                vn += 1
                            table += ","
                        table += str(3+2*int(q[len(q)-1]))
                        table += "\n"
            table += "2," + ",".join(vars[:8]) + ",4\n"
            table += "1," + ",".join(vars[:8]) + ",5\n"
                    
            for i in lines1:
                q = i.split("#")[0].replace(" ", "").split(",")
                if len(q) > 1:
                    vn = 0
                    ovn = 0
                    dvn = 0
                    if q[0] == "0" or q[0] == "1":
                        table += str(4+2*int(q[0])) + ","
                        for j in q[1:-1]:
                            if j == "0":
                                table += dvars[dvn]
                                dvn += 1
                            elif j == "1":
                                table += ovars[ovn]
                                ovn += 1
                            elif j != "#":
                                table += vars[vn]
                                vn += 1
                            table += ","
                        if q[0] == "0" and q[len(q)-1] == "0":
                            table += "8"
                        if q[0] == "1" and q[len(q)-1] == "0":
                            table += "10"
                        if q[0] == "0" and q[len(q)-1] == "1":
                            table += "12"
                        if q[0] == "1" and q[len(q)-1] == "1":
                            table += "12"
                        table += "\n"
                    elif not i.startswith("var"): #Line starts with a variable.
                        table += "5,"
                        for j in q[1:-1]:
                            if j == "0":
                                table += dvars[dvn]
                                dvn += 1
                            elif j == "1":
                                table += ovars[ovn]
                                ovn += 1
                            elif j != "#":
                                table += vars[vn]
                                vn += 1
                            table += ","
                        if q[len(q)-1] == "0":
                            table += "7"
                        if q[len(q)-1] == "1":
                            table += "11"
                        table += "\n3,"
                        for j in q[1:-1]:
                            if j == "0":
                                table += dvars[dvn]
                                dvn += 1
                            elif j == "1":
                                table += ovars[ovn]
                                ovn += 1
                            elif j != "#":
                                table += vars[vn]
                                vn += 1
                            table += ","
                        if q[len(q)-1] == "0":
                            table += "9"
                        if q[len(q)-1] == "1":
                            table += "11"
                        table += "\n"
                        
            for i in lines1:
                q = i.split("#")[0].replace(" ", "").split(",")
                if len(q) > 1:
                    vn = 0
                    ovn = 0
                    dvn = 0
                    if q[0] == "0" or q[0] == "1":
                        table += str(3+2*int(q[0])) + ","
                        for j in q[1:-1]:
                            if j == "0":
                                table += dvars[dvn]
                                dvn += 1
                            elif j == "1":
                                table += ovars[ovn]
                                ovn += 1
                            elif j != "#":
                                table += vars[vn]
                                vn += 1
                            table += ","
                        if q[0] == "0" and q[len(q)-1] == "0":
                            table += "11"
                        if q[0] == "1" and q[len(q)-1] == "0":
                            table += "11"
                        if q[0] == "0" and q[len(q)-1] == "1":
                            table += "9"
                        if q[0] == "1" and q[len(q)-1] == "1":
                            table += "7"
                        table += "\n"
                    elif not i.startswith("var"): #Line starts with a variable.
                        table += "6,"
                        for j in q[1:-1]:
                            if j == "0":
                                table += dvars[dvn]
                                dvn += 1
                            elif j == "1":
                                table += ovars[ovn]
                                ovn += 1
                            elif j != "#":
                                table += vars[vn]
                                vn += 1
                            table += ","
                        if q[len(q)-1] == "0":
                            table += "12"
                        if q[len(q)-1] == "1":
                            table += "10"
                        table += "\n4,"
                        for j in q[1:-1]:
                            if j == "0":
                                table += dvars[dvn]
                                dvn += 1
                            elif j == "1":
                                table += ovars[ovn]
                                ovn += 1
                            elif j != "#":
                                table += vars[vn]
                                vn += 1
                            table += ","
                        if q[len(q)-1] == "0":
                            table += "8"
                        if q[len(q)-1] == "1":
                            table += "12"
                        table += "\n"
            table += "4," + ",".join(vars[:8]) + ",8\n"
            table += "3," + ",".join(vars[:8]) + ",11\n"
            table += "6," + ",".join(vars[:8]) + ",12\n"
            table += "5," + ",".join(vars[:8]) + ",7\n"
                        
        colours = """
0    0    0    0
1  255  255  255
2  127  127  127
7    0    0  255
8    0    0  127
9  255    0    0
10 127    0    0
11   0  255    0
12   0  127    0
13 255  255    0
14 127  127    0
"""
        self.saverule("APG_ClassifyObjects_"+self.alphanumeric, comments, table, colours)

    def savePropagateClassifications(self):
        
        comments = """This propagates the result of running ClassifyObjects for two generations.
"""
        
        table = "n_states:17\n"
        table += "neighborhood:Moore\n"
        table += "symmetries:permute\n\n"
    
        table += self.newvars(["a","b","c","d","e","f","g","h","i"], range(0, 17, 1))
        
        table += """
7,11,b,c,d,e,f,g,h,11
7,12,b,c,d,e,f,g,h,11
7,9,b,c,d,e,f,g,h,9
7,10,b,c,d,e,f,g,h,9
8,11,b,c,d,e,f,g,h,12
8,12,b,c,d,e,f,g,h,12
8,9,b,c,d,e,f,g,h,10
8,10,b,c,d,e,f,g,h,10

7,13,b,c,d,e,f,g,h,11
7,14,b,c,d,e,f,g,h,11
8,13,b,c,d,e,f,g,h,14
8,14,b,c,d,e,f,g,h,14
9,13,b,c,d,e,f,g,h,11
9,14,b,c,d,e,f,g,h,11
10,13,b,c,d,e,f,g,h,14
10,14,b,c,d,e,f,g,h,14

9,11,b,c,d,e,f,g,h,11
9,12,b,c,d,e,f,g,h,11
10,11,b,c,d,e,f,g,h,12
10,12,b,c,d,e,f,g,h,12

13,11,b,c,d,e,f,g,h,11
13,12,b,c,d,e,f,g,h,11
14,11,b,c,d,e,f,g,h,12
14,12,b,c,d,e,f,g,h,12
13,9,b,c,d,e,f,g,h,11
14,9,b,c,d,e,f,g,h,12
"""
        colours = """
0    0    0    0
1  255  255  255
2  127  127  127
7    0    0  255
8    0    0  127
9  255    0    0
10 127    0    0
11   0  255    0
12   0  127    0
13 255  255    0
14 127  127    0
"""

        self.saverule("APG_PropagateClassification", comments, table, colours)
        #foo = "" + 2
    def saveContagiousLife(self):

        comments = """
A variant of HistoricalLife used for detecting dependencies between
islands.

state 0:  vacuum
state 1:  ON
state 2:  OFF
"""
        table = "n_states:7\n"
        table += "neighborhood:Moore\n"
        
        if ruletype:
            table += "symmetries:permute\n\n"

            table += self.newvars(["a","b","c","d","e","f","g","h","i"], range(0, 7, 1))
            table += self.newvars(["la","lb","lc","ld","le","lf","lg","lh","li"], range(1, 7, 2))
            table += self.newvars(["da","db","dc","dd","de","df","dg","dh","di"], range(0, 7, 2))
            table += self.newvar("p",[3, 4])
            table += self.newvars(["ta","tb","tc","td","te","tf","tg","th","ti"], [3])
            table += self.newvars(["qa","qb","qc","qd","qe","qf","qg","qh","qi"], [0, 1, 2, 4, 5, 6])

            for i in xrange(9):
                if (self.bee[i]):
                    table += self.scoline("l","d",4,3,i)
                    table += self.scoline("l","d",2,1,i)
                    table += self.scoline("l","d",0,1,i)
                    table += self.scoline("l","d",6,5,i)
                    table += self.scoline("t","q",0,4,i)
                if (self.ess[i]):
                    table += self.scoline("l","d",3,3,i)
                    table += self.scoline("l","d",5,5,i)
                    table += self.scoline("l","d",1,1,i)

            table += "# Default behaviour (death):\n"
            table += self.scoline("","",1,2,0)
            table += self.scoline("","",5,6,0)
            table += self.scoline("","",3,4,0)
        else:
            rule1 = open(g.getdir("app") + "Rules/" + self.slashed + ".rule", "r")
            lines1 = rule1.read().split("\n")
            rule1.close()
            for q in xrange(len(lines1)-1):
                if lines1[q].startswith("@TABLE"):
                    lines1 = lines1[q:]
                    break
            vars = []
            for q in xrange(len(lines1)-1): #Copy symmetries and vars
                i = lines1[q]
                if i[:2] == "sy" or i[:1] == "sy":
                    table += i + "\n\n"
                if i[:2] == "va" or i[:1] == "va":
                    table += self.newvar(i[4:5].replace("=", ""), [0, 1, 2])
                    vars.append(i[4:5].replace("=", ""))
                if i != "":
                    if i[0] == "0" or i[0] == "1":
                        break
            alpha = "abcdefghijklmnopqrstuvwxyz"
            ovars = []
            for i in alpha: 
                if not i in [n[0] for n in vars]: #Create new set of vars for ON cells
                    table += self.newvars([i + j for j in alpha[:9]], [1, 3, 5])
                    ovars = [i + j for j in alpha[:9]]
                    break
            dvars = []
            for i in alpha: 
                if not i in [n[0] for n in vars] and not i in [n[0] for n in ovars]: #Create new set of vars for OFF cells
                    table += self.newvars([i + j for j in alpha[:9]], [0, 2, 4, 6])
                    dvars = [i + j for j in alpha[:9]]
                    break
                    
            for i in alpha: 
                if not i in [n[0] for n in vars] and not i in [n[0] for n in ovars] and not i in [n[0] for n in dvars]:
                    for j in xrange(8-len(vars)):
                        table += self.newvar(i + alpha[j], [0, 1, 2, 3, 4, 5, 6])
                        vars.append(i + alpha[j])
                    break
            
            qvars = []
            for i in alpha:
                if not i in [n[0] for n in vars] and not i in [n[0] for n in ovars] and not i in [n[0] for n in dvars]:
                    table += self.newvars([i + j for j in alpha[:9]], [0, 1, 2, 4, 5, 6])
                    qvars = [i + j for j in alpha[:9]]
                    break
            
            for i in lines1:
                q = i.split("#")[0].replace(" ", "").split(",")
                if len(q) > 1 and not i.startswith("var"):
                    vn = 0
                    ovn = 0
                    dvn = 0
                    qvn = 0
                    table += str(2-int(q[0])) + ","
                    for j in q[1:-1]:
                        if j == "0":
                            table += dvars[dvn]
                            dvn += 1
                        elif j == "1":
                            table += ovars[ovn]
                            ovn += 1
                        elif j != "#":
                            table += vars[vn]
                            vn += 1
                        table += ","
                    if q[len(q)-1] == "0":
                        table += "2"
                    if q[len(q)-1] == "1":
                        table += "1"
                    table += "\n"
                    vn = 0
                    ovn = 0
                    dvn = 0
                    qvn = 0
                    table += str(4-int(q[0])) + ","
                    for j in q[1:-1]:
                        if j == "0":
                            table += dvars[dvn]
                            dvn += 1
                        elif j == "1":
                            table += ovars[ovn]
                            ovn += 1
                        elif j != "#":
                            table += vars[vn]
                            vn += 1
                        table += ","
                    if q[len(q)-1] == "0":
                        table += "4"
                    if q[len(q)-1] == "1":
                        table += "3"
                    table += "\n"
                    vn = 0
                    ovn = 0
                    dvn = 0
                    qvn = 0
                    table += str(6-int(q[0])) + ","
                    for j in q[1:-1]:
                        if j == "0":
                            table += dvars[dvn]
                            dvn += 1
                        elif j == "1":
                            table += ovars[ovn]
                            ovn += 1
                        elif j != "#":
                            table += vars[vn]
                            vn += 1
                        table += ","
                    if q[len(q)-1] == "0":
                        table += "6"
                    if q[len(q)-1] == "1":
                        table += "5"
                    table += "\n"
                    
            for i in lines1:
                q = i.split("#")[0].replace(" ", "").split(",")
                if len(q) > 1:
                    vn = 0
                    ovn = 0
                    dvn = 0
                    qvn = 0
                    if q[0] == "0":
                        table += "0,"
                        for j in q[1:-1]:
                            if j == "0":
                                table += dvars[dvn]
                                dvn += 1
                            elif j == "1":
                                table += ovars[ovn]
                                ovn += 1
                            elif j != "#":
                                table += vars[vn]
                                vn += 1
                            table += ","
                        if q[len(q)-1] == "1":
                            table += "1"
                        table += "\n"
                        
            for i in lines1:
                q = i.split("#")[0].replace(" ", "").split(",")
                if len(q) > 1:
                    vn = 0
                    ovn = 0
                    dvn = 0
                    qvn = 0
                    if q[0] == "0":
                        table += "0,"
                        for j in q[1:-1]:
                            if j == "0":
                                table += qvars[qvn]
                                qvn += 1
                            elif j == "1":
                                table += "3"
                            elif j != "#":
                                table += vars[vn]
                                vn += 1
                            table += ","
                        if q[len(q)-1] == "1":
                            table += "4"
                        table += "\n"

        colours = """
0    0    0    0
1    0    0  255
2    0    0  127
3  255    0    0
4  127    0    0
5    0  255    0
6    0  127    0
"""
        self.saverule("APG_ContagiousLife_"+self.alphanumeric, comments, table, colours)
Frankly, I don't know why that error only showed up in x-rule-pre. Still don't know what else is going on with x-rule-pre, too.
former username: A for Awesome
praosylen#5847 (Discord)

The only decision I made was made
of flowers, to jump universes to one of springtime in
a land of former winter, where no invisible walls stood,
or could stand for more than a few hours at most...

drc
Posts: 1664
Joined: December 3rd, 2015, 4:11 pm

Re: Hacking apgsearch

Post by drc » December 18th, 2015, 6:35 pm

Scorbie wrote:
drc wrote:I still get the error:

line 37 in <module>
from glife import rect, pattern
ImportError: No module named glife
That's related to python's importing system. As a permanent fix, copy the glife folder (and its files) to where your script is in. Like this:

Code: Select all

My_Script_Directory
ㄴapgsearch
ㄴglife
  ㄴ__init__.py
  ㄴ....
I don't have a glife folder. Mabye somebody can provide it?

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

Re: Hacking apgsearch

Post by Scorbie » December 18th, 2015, 7:49 pm

Whoops, my bad. it's in Scripts/Python/glife.

User avatar
Saka
Posts: 3627
Joined: June 19th, 2015, 8:50 pm
Location: Indonesia
Contact:

Re: Hacking apgsearch

Post by Saka » December 19th, 2015, 1:32 am

wildmyron wrote:
Scorbie wrote:
A for awesome wrote:Hello everyone,

I made a hacked version of apgsearch that works on all 2-state isotropic Moore-neighborhood cellular automata (tlife, SansDomino rules, etc.). Here it is:
Glad to see this :) Thanks for your work! (I think wildmyron worked on somthing similar too...?)
Indeed, great to see some interest in this. I have indeed worked on something similar and despite much hesitation I'm just going to post it in it's current state in the hope that it can help further development. I took a different approach to the rule generating - it's quite interesting to see the way this version interprets an existing rule file and generates the auxillary rules from that. Instead I based the rule generator on EricG's rule table generating script for non-totalistic rules "Hensel-TableGen.py".

The rule generator class is actually in a separate file which makes it easier to use parts of it for other purposes (e.g. isotropicRulegen.py does basically the same as Hensel-TableGen.py but using the http://www.ibiblio.org/lifepatterns/neighbors2.html version of Hensel's notation. I had intended to seperate the soup generating and censusing code into a separate file as well and then have a totalistic and non-totalistic version of apgsearch with custom code for each and all the common code in separate files, but I'm not very good at finishing off such projects. I have a different version of APG_ExpungeObjects - named APG_ExpungeSmallSL - which handles dominoes and I-trominoes as well as blocks. This file has to be manually copied to the rules folder because it's not created by the rule generator. Another version of that identifies SL checkers instead of I-trominoes. Using the most appropriate expunge rule for the rule being searched is one of the stumbling blocks on my TODO list.
I tried it and it said
err.png
err.png (233.44 KiB) Viewed 55650 times
Any fix?

wildmyron
Posts: 1547
Joined: August 9th, 2013, 12:45 am
Location: Western Australia

Re: Hacking apgsearch

Post by wildmyron » December 19th, 2015, 1:43 am

Saka wrote:I tried it and it said
Python Error msg wrote:...
g.setrule("APG_ExpungeSmallSL")
RuntimeError: Given rule is not valid in any algorithm.
Any fix?
Earlier, I wrote:...
I have a different version of APG_ExpungeObjects - named APG_ExpungeSmallSL - which handles dominoes and I-trominoes as well as blocks. This file has to be manually copied to the rules folder because it's not created by the rule generator.
...
The rule file is in the zip file. Copy it to your rules folder and try again.
The 5S project (Smallest Spaceships Supporting Specific Speeds) is now maintained by AforAmpere. The latest collection is hosted on GitHub and contains well over 1,000,000 spaceships.

Semi-active here - recovering from a severe case of LWTDS.

drc
Posts: 1664
Joined: December 3rd, 2015, 4:11 pm

Re: Hacking apgsearch

Post by drc » December 19th, 2015, 12:14 pm

Scorbie wrote:Whoops, my bad. it's in Scripts/Python/glife.
I actually didn't have the scripts, or patterns installed, so I reinstalled it and it works now.

drc
Posts: 1664
Joined: December 3rd, 2015, 4:11 pm

Re: Hacking apgsearch

Post by drc » December 19th, 2015, 1:01 pm

I'm having trouble with the A for awesome's version of apgnano.

In this rule:

Code: Select all

@RULE testlife
@TABLE
n_states:2
neighborhood:Moore
symmetries:rotate4reflect
0,1,1,1,0,0,0,0,0,1
0,1,1,0,1,0,0,0,0,1
0,1,1,0,0,1,0,0,0,1
0,1,1,0,0,0,1,0,0,1
0,1,1,0,0,0,0,1,0,1
0,1,1,0,0,0,0,0,1,1
0,1,0,1,0,1,0,0,0,1
0,1,0,1,0,0,1,0,0,1
0,1,0,0,1,0,1,0,0,1
0,0,1,0,1,0,1,0,0,1
0,1,1,1,1,1,1,0,0,1
1,0,0,0,0,0,0,0,0,0
1,1,0,0,0,0,0,0,0,0
1,0,1,0,0,0,0,0,0,0
1,1,1,1,1,0,0,0,0,0
1,1,1,1,0,1,0,0,0,0
1,1,1,1,0,0,1,0,0,0
1,1,1,0,1,1,0,0,0,0
1,1,1,0,1,0,1,0,0,0
1,1,1,0,1,0,0,1,0,0
1,1,1,0,1,0,0,0,1,0
1,1,1,0,0,1,1,0,0,0
1,1,1,0,0,1,0,1,0,0
1,1,1,0,0,1,0,0,1,0
1,1,1,0,0,0,1,1,0,0
1,1,0,1,0,1,0,1,0,0
1,0,1,0,1,0,1,0,1,0
1,0,0,0,1,1,1,1,1,0
1,0,0,1,0,1,1,1,1,0
1,0,0,1,1,0,1,1,1,0
1,0,0,1,1,1,0,1,1,0
1,0,0,1,1,1,1,0,1,0
1,0,0,1,1,1,1,1,0,0
1,0,1,0,1,0,1,1,1,0
1,0,1,0,1,1,0,1,1,0
1,0,1,1,0,1,0,1,1,0
1,1,0,1,0,1,0,1,1,0
1,0,0,1,1,1,1,1,1,0
1,0,1,0,1,1,1,1,1,0
1,0,1,1,0,1,1,1,1,0
1,0,1,1,1,0,1,1,1,0
1,1,0,1,0,1,1,1,1,0
1,1,0,1,1,1,0,1,1,0
1,0,1,1,1,1,1,1,1,0
1,1,0,1,1,1,1,1,1,0
1,1,1,1,1,1,1,1,1,0

@COLORS

0 0 0 0
1 255 255 255
It classifies this:

Code: Select all

x = 5, y = 4, rule = testlife
o2bo$4bo$o3bo$b4o!
As "pathological"

For those wondering it's a regular LWSS.

User avatar
praosylen
Posts: 2449
Joined: September 13th, 2014, 5:36 pm
Location: Pembina University, Home of the Gliders
Contact:

Re: Hacking apgsearch

Post by praosylen » December 19th, 2015, 7:37 pm

drc wrote: It classifies this:

Code: Select all

x = 5, y = 4, rule = testlife
o2bo$4bo$o3bo$b4o!
As "pathological"

For those wondering it's a regular LWSS.
That's weird; XWSS detection was working just fine in klife when I tested it.
former username: A for Awesome
praosylen#5847 (Discord)

The only decision I made was made
of flowers, to jump universes to one of springtime in
a land of former winter, where no invisible walls stood,
or could stand for more than a few hours at most...

User avatar
Saka
Posts: 3627
Joined: June 19th, 2015, 8:50 pm
Location: Indonesia
Contact:

Re: Hacking apgsearch

Post by Saka » December 20th, 2015, 2:31 am

I get an error every time I try to use dlife (from life variations thread):

Code: Select all

Error reading APG_ContagiousLife_dlife.rule on line 242: 0,aa,ab,ba,ac,bb,bc,bd,be, -too few entries
Not sure what's going on, the script works just fine for other rules (e.g. tlife, HeptaFish)

drc
Posts: 1664
Joined: December 3rd, 2015, 4:11 pm

Re: Hacking apgsearch

Post by drc » December 20th, 2015, 11:38 am

Saka wrote:I get an error every time I try to use dlife (from life variations thread):

Code: Select all

Error reading APG_ContagiousLife_dlife.rule on line 242: 0,aa,ab,ba,ac,bb,bc,bd,be, -too few entries
Not sure what's going on, the script works just fine for other rules (e.g. tlife, HeptaFish)
There's a typo on that line. There are 9 entries and an empty one after

User avatar
praosylen
Posts: 2449
Joined: September 13th, 2014, 5:36 pm
Location: Pembina University, Home of the Gliders
Contact:

Re: Hacking apgsearch

Post by praosylen » December 20th, 2015, 11:59 am

Saka wrote:I get an error every time I try to use dlife (from life variations thread):

Code: Select all

Error reading APG_ContagiousLife_dlife.rule on line 242: 0,aa,ab,ba,ac,bb,bc,bd,be, -too few entries
Not sure what's going on, the script works just fine for other rules (e.g. tlife, HeptaFish)
It's because I was stupid and didn't test the script enough before releasing it. The line 0,1,1,0,1,0,0,0,0,0 in the dlife rule table wasn't accounted for in the last two conditionals in the function that produces the ContagiousLife table. To fix it, just replace the RuleGenerator.saveContagiousLife() function with

Code: Select all

    def saveContagiousLife(self):

        comments = """
A variant of HistoricalLife used for detecting dependencies between
islands.

state 0:  vacuum
state 1:  ON
state 2:  OFF
"""
        table = "n_states:7\n"
        table += "neighborhood:Moore\n"
        
        if ruletype:
            table += "symmetries:permute\n\n"

            table += self.newvars(["a","b","c","d","e","f","g","h","i"], range(0, 7, 1))
            table += self.newvars(["la","lb","lc","ld","le","lf","lg","lh","li"], range(1, 7, 2))
            table += self.newvars(["da","db","dc","dd","de","df","dg","dh","di"], range(0, 7, 2))
            table += self.newvar("p",[3, 4])
            table += self.newvars(["ta","tb","tc","td","te","tf","tg","th","ti"], [3])
            table += self.newvars(["qa","qb","qc","qd","qe","qf","qg","qh","qi"], [0, 1, 2, 4, 5, 6])

            for i in xrange(9):
                if (self.bee[i]):
                    table += self.scoline("l","d",4,3,i)
                    table += self.scoline("l","d",2,1,i)
                    table += self.scoline("l","d",0,1,i)
                    table += self.scoline("l","d",6,5,i)
                    table += self.scoline("t","q",0,4,i)
                if (self.ess[i]):
                    table += self.scoline("l","d",3,3,i)
                    table += self.scoline("l","d",5,5,i)
                    table += self.scoline("l","d",1,1,i)

            table += "# Default behaviour (death):\n"
            table += self.scoline("","",1,2,0)
            table += self.scoline("","",5,6,0)
            table += self.scoline("","",3,4,0)
        else:
            rule1 = open(g.getdir("app") + "Rules/" + self.slashed + ".rule", "r")
            lines1 = rule1.read().split("\n")
            rule1.close()
            for q in xrange(len(lines1)-1):
                if lines1[q].startswith("@TABLE"):
                    lines1 = lines1[q:]
                    break
            vars = []
            for q in xrange(len(lines1)-1): #Copy symmetries and vars
                i = lines1[q]
                if i[:2] == "sy" or i[:1] == "sy":
                    table += i + "\n\n"
                if i[:2] == "va" or i[:1] == "va":
                    table += self.newvar(i[4:5].replace("=", ""), [0, 1, 2])
                    vars.append(i[4:5].replace("=", ""))
                if i != "":
                    if i[0] == "0" or i[0] == "1":
                        break
            alpha = "abcdefghijklmnopqrstuvwxyz"
            ovars = []
            for i in alpha: 
                if not i in [n[0] for n in vars]: #Create new set of vars for ON cells
                    table += self.newvars([i + j for j in alpha[:9]], [1, 3, 5])
                    ovars = [i + j for j in alpha[:9]]
                    break
            dvars = []
            for i in alpha: 
                if not i in [n[0] for n in vars] and not i in [n[0] for n in ovars]: #Create new set of vars for OFF cells
                    table += self.newvars([i + j for j in alpha[:9]], [0, 2, 4, 6])
                    dvars = [i + j for j in alpha[:9]]
                    break
                    
            for i in alpha: 
                if not i in [n[0] for n in vars] and not i in [n[0] for n in ovars] and not i in [n[0] for n in dvars]:
                    for j in xrange(8-len(vars)):
                        table += self.newvar(i + alpha[j], [0, 1, 2, 3, 4, 5, 6])
                        vars.append(i + alpha[j])
                    break
            
            qvars = []
            for i in alpha:
                if not i in [n[0] for n in vars] and not i in [n[0] for n in ovars] and not i in [n[0] for n in dvars]:
                    table += self.newvars([i + j for j in alpha[:9]], [0, 1, 2, 4, 5, 6])
                    qvars = [i + j for j in alpha[:9]]
                    break
            
            for i in lines1:
                q = i.split("#")[0].replace(" ", "").split(",")
                if len(q) > 1 and not i.startswith("var"):
                    vn = 0
                    ovn = 0
                    dvn = 0
                    qvn = 0
                    table += str(2-int(q[0])) + ","
                    for j in q[1:-1]:
                        if j == "0":
                            table += dvars[dvn]
                            dvn += 1
                        elif j == "1":
                            table += ovars[ovn]
                            ovn += 1
                        elif j != "#":
                            table += vars[vn]
                            vn += 1
                        table += ","
                    if q[len(q)-1] == "0":
                        table += "2"
                    if q[len(q)-1] == "1":
                        table += "1"
                    table += "\n"
                    vn = 0
                    ovn = 0
                    dvn = 0
                    qvn = 0
                    table += str(4-int(q[0])) + ","
                    for j in q[1:-1]:
                        if j == "0":
                            table += dvars[dvn]
                            dvn += 1
                        elif j == "1":
                            table += ovars[ovn]
                            ovn += 1
                        elif j != "#":
                            table += vars[vn]
                            vn += 1
                        table += ","
                    if q[len(q)-1] == "0":
                        table += "4"
                    if q[len(q)-1] == "1":
                        table += "3"
                    table += "\n"
                    vn = 0
                    ovn = 0
                    dvn = 0
                    qvn = 0
                    table += str(6-int(q[0])) + ","
                    for j in q[1:-1]:
                        if j == "0":
                            table += dvars[dvn]
                            dvn += 1
                        elif j == "1":
                            table += ovars[ovn]
                            ovn += 1
                        elif j != "#":
                            table += vars[vn]
                            vn += 1
                        table += ","
                    if q[len(q)-1] == "0":
                        table += "6"
                    if q[len(q)-1] == "1":
                        table += "5"
                    table += "\n"
                    
            for i in lines1:
                q = i.split("#")[0].replace(" ", "").split(",")
                if len(q) > 1:
                    vn = 0
                    ovn = 0
                    dvn = 0
                    qvn = 0
                    if q[0] == "0":
                        table += "0,"
                        for j in q[1:-1]:
                            if j == "0":
                                table += dvars[dvn]
                                dvn += 1
                            elif j == "1":
                                table += ovars[ovn]
                                ovn += 1
                            elif j != "#":
                                table += vars[vn]
                                vn += 1
                            table += ","
                        if q[len(q)-1] == "1":
                            table += "1"
                        else:
                            table += "0"
                        table += "\n"
                        
            for i in lines1:
                q = i.split("#")[0].replace(" ", "").split(",")
                if len(q) > 1:
                    vn = 0
                    ovn = 0
                    dvn = 0
                    qvn = 0
                    if q[0] == "0":
                        table += "0,"
                        for j in q[1:-1]:
                            if j == "0":
                                table += qvars[qvn]
                                qvn += 1
                            elif j == "1":
                                table += "3"
                            elif j != "#":
                                table += vars[vn]
                                vn += 1
                            table += ","
                        if q[len(q)-1] == "1":
                            table += "4"
                        else:
                            table += "0"
                        table += "\n"

        colours = """
0    0    0    0
1    0    0  255
2    0    0  127
3  255    0    0
4  127    0    0
5    0  255    0
6    0  127    0
"""
        self.saverule("APG_ContagiousLife_"+self.alphanumeric, comments, table, colours)
former username: A for Awesome
praosylen#5847 (Discord)

The only decision I made was made
of flowers, to jump universes to one of springtime in
a land of former winter, where no invisible walls stood,
or could stand for more than a few hours at most...

User avatar
gameoflifeboy
Posts: 474
Joined: January 15th, 2015, 2:08 am

Re: Hacking apgsearch

Post by gameoflifeboy » December 21st, 2015, 12:52 am

I just modified "A for awesome"'s version of apgsearch to read rule tables from your custom rules folder (g.getdata('rules')) instead of Golly's rules folder.

I call it "apgsearch-2015-12-20-v0.54+0.1i+0.1j.py":
Attachments
apgsearch-2015-12-20-v0.54+0.1i+0.1j.zip
(154.99 KiB) Downloaded 458 times

wildmyron
Posts: 1547
Joined: August 9th, 2013, 12:45 am
Location: Western Australia

Re: Hacking apgsearch

Post by wildmyron » December 21st, 2015, 1:29 am

drc wrote:I'm having trouble with the A for awesome's version of apgnano.

In this rule:

Code: Select all

@RULE testlife
@TABLE
[snip]
It classifies this:

Code: Select all

x = 5, y = 4, rule = testlife
o2bo$4bo$o3bo$b4o!
As "pathological"
I tried this out and it seems to work fine. Is every soup with an LWSS triggering the Pathological detection? It seems more likely to me that an LWSS is colliding with something after the soup was determined to be stable.
Can you provide the seed, symmetry and soup number where this occurs?
The 5S project (Smallest Spaceships Supporting Specific Speeds) is now maintained by AforAmpere. The latest collection is hosted on GitHub and contains well over 1,000,000 spaceships.

Semi-active here - recovering from a severe case of LWTDS.

User avatar
gameoflifeboy
Posts: 474
Joined: January 15th, 2015, 2:08 am

Re: Hacking apgsearch

Post by gameoflifeboy » December 23rd, 2015, 9:16 pm

In Move variants, apgsearch v0.54 + v0.1i reports gliders, even though the rule doesn't support them. I suspect the "gliders" it's reporting are actually "spinning gliders", a p4 oscillator in Move-like rules. In fact, the phase of the glider given by its apgcode is different from the spinning glider, which means apgsearch is recognizing the gliders by their wrong phase.
EDIT: I now think this is happening because glidersexist() doesn't get called on non-Life-like rules, but the gliders are getting detected anyway.
Attachments
Screenshot of move_rep census, with &quot;glider&quot; reported as a spaceship
Screenshot of move_rep census, with "glider" reported as a spaceship
apgsearch_error.png (12.47 KiB) Viewed 23228 times
Last edited by gameoflifeboy on December 23rd, 2015, 9:31 pm, edited 1 time in total.

drc
Posts: 1664
Joined: December 3rd, 2015, 4:11 pm

Re: Hacking apgsearch

Post by drc » December 23rd, 2015, 9:19 pm

gameoflifeboy wrote:In Move variants, apgsearch v0.54 + v0.1i reports gliders, even though the rule doesn't support them. I suspect the "gliders" it's reporting are actually "spinning gliders", a p4 oscillator in Move-like rules. In fact, the phase of the glider given by its apgcode is different from the spinning glider, which means apgsearch is recognizing the gliders by their wrong phase.
I noticed that too, its weird

User avatar
praosylen
Posts: 2449
Joined: September 13th, 2014, 5:36 pm
Location: Pembina University, Home of the Gliders
Contact:

Re: Hacking apgsearch

Post by praosylen » December 26th, 2015, 8:57 pm

drc wrote:
gameoflifeboy wrote:In Move variants, apgsearch v0.54 + v0.1i reports gliders, even though the rule doesn't support them. I suspect the "gliders" it's reporting are actually "spinning gliders", a p4 oscillator in Move-like rules. In fact, the phase of the glider given by its apgcode is different from the spinning glider, which means apgsearch is recognizing the gliders by their wrong phase.
I noticed that too, its weird
Sorry about that; that will be fixed in the next version.
former username: A for Awesome
praosylen#5847 (Discord)

The only decision I made was made
of flowers, to jump universes to one of springtime in
a land of former winter, where no invisible walls stood,
or could stand for more than a few hours at most...

User avatar
praosylen
Posts: 2449
Joined: September 13th, 2014, 5:36 pm
Location: Pembina University, Home of the Gliders
Contact:

Re: Hacking apgsearch

Post by praosylen » December 27th, 2015, 11:27 am

apgsearch-2015-12-27-v0.54+0.12i.py.zip
(152.24 KiB) Downloaded 468 times
Changes since the previous version:
  • Numerous bug fixes, including the ones for x-rule-pre and dlife.
  • Gliders are now tested on a rule-by-rule basis.
  • Added rules to identify and expunge T's.
  • Adapted Gameoflifeboy's modification to allow rules from your Rules folder.
  • Minor changes to object scores.
Changes (hopefully) coming (sometime) soon:
  • More accurate scores for a multitude of rules.
  • Rule to separate non-interacting combinations of high-period oscillators.
  • Modifications to countxwsses() that add support for other, rule-specific p4 spaceships.
Changes that are not coming soon, but hopefully I (or anyone else that wants to) can eventually figure out how to do:
  • Bounded grids (for exploding rules.)
  • Support for Generations, Plus-Minus, or custom 3-state rules.
former username: A for Awesome
praosylen#5847 (Discord)

The only decision I made was made
of flowers, to jump universes to one of springtime in
a land of former winter, where no invisible walls stood,
or could stand for more than a few hours at most...

Post Reply