Day and Knight rule group

For discussion of other cellular automata.
Post Reply
User avatar
Goldtiger997
Posts: 764
Joined: June 21st, 2016, 8:00 am

Day and Knight rule group

Post by Goldtiger997 » August 12th, 2018, 7:49 am

This topic is about a specific type of rule first described by danny on the Discord.
These are the criteria a rule needs to satisfy to be a "Day and Knight" rule:
  • It must be self-complementary, just like Day and Night
  • It must have a (preferably natural) knightship or oblique ship.
  • It must not be explosive, just like Day and Night
So far 6 Day and Knight rules have been discovered. Some are more interesting than others. My favourites are 1, 5, and 6. Here they are in order of discovery:

Day and Knight 1, found by Saka:

Code: Select all

x = 35, y = 37, rule = B2ci3aenry4ekrz5acinq6eik78/S2acn3ejkry4-cknz5cijkq6-ci78
35o$35o$35o$35o$35o$35o$35o$13o3b19o$13o2b20o$13o4b18o$13o4b18o$13o3b
19o$9o4b22o$9o4b22o$9o4b22o$9o4b22o$35o$35o$35o$35o$35o$3obob29o$2o2bo
2b28o$2o5b28o$2o5b28o$2o5b28o$2o5b28o$2o5b28o$35o$35o$29o3b3o$4ob11ob
12o2b4o$3o3b6ob3obobob8o3b3o$4ob6o3b4o2b9o2b4o$11ob6o3b8o3b3o$35o$35o!
Day and Knight 2, found by Goldtiger997:

Code: Select all

x = 46, y = 46, rule = B2-ak3acikr4cikrz5-ekny6-ac78/S2ac3ekny4-ekntz5ejnqy6ak78
bo2b2o2b2o2b2o2b2o2b2o2b2o2b2o2b2o2b2o2b2o2bo$b44o$46o$46o$b2o3b39o$b
2o2b3o3bob32o$18ob2o2b2o2b2ob8ob7o$10obob5o12b7obob6o$b11ob4o14b7ob6o$
b11ob4o14b5o2bo2b4o$18o6bobo3b8ob7o$4ob2o2b9o12b7obob6o$b2ob4ob8o7bobo
4b7ob6o$b16o4bo9b14o$18o3bo8b16o$10obob5o3bo8b16o$b3o3b10o4bo9b7ob6o$b
9obob4o14b7ob6o$18o12b8ob7o$18ob2o2b2o2b2ob6obobob5o$b37ob6o$b37ob6o$
38ob7o$29obob14o$b28obob13o$b28obob6ob6o$38ob7o$29obob6ob7o$b28obob6ob
6o$b28obob13o$46o$46o$b39o3b2o$b39obob2o$41ob4o$7ob38o$b4o3b37o$b5o3b
4o2b30o$6ob4o6b29o$12o4b24ob5o$b11ob2ob23o3b3o$b40ob3o$46o$46o$b44o$bo
2b2o2b2o2b2o2b2o2b2o2b2o2b2o2b2o2b2o2b2o2bo!
Day and Knight 3, found by Goldtiger997:

Code: Select all

x = 4, y = 3, rule = B2i3ain4ertyz5acn6ak7e/S01c2-ak3-acn4-cijnz5-ain6-i78
bo$3o$ob2o!
Day and Knight 4, found by Goldtiger997:

Code: Select all

x = 4, y = 3, rule = B3ai4knry5knr6ace8/S12ikn3-knr4-jknr5-ai678
bo$3o$ob2o!
Day and Knight 5, found by Goldtiger997:

Code: Select all

x = 60, y = 46, rule = B2k3aiy4cejnrty5ackqy6k7e/S01c2-k3eijnr4akqtwz5-aiy6-k78
15bo2b2o2b2o2b2o2b2o2b2o2b2o2b2o2b2o2b2o2b2o2bo$15b44o$14b46o$14b46o$
15b44o$15b6o2b36o$14b6o3b12ob4ob2ob16o$bo12b5o4b10o2b6o2b8ob8o$b2o12b
4o3bo3b5o4b6o2b8o2b6o$bo13b7o4b3o7b5o2b8ob7o$2bo11b8o3b5o5b5ob2ob8ob7o
$14b8o2b6ob29o$15b14o2b28o$15b44o$14b46o$14b37o3b6o$15b6o2b36o$15b8ob
7ob27o$14b6o2bob7ob28o$14b7o3b6o3b27o$15b7o2b6o3b26o$15b37o2b5o$14b37o
3b6o$14b37o2b7o$15b44o$15b44o$14b46o$14b46o$ob2o11b35obo2b5o$3o12b35o
3b6o$bo12b37ob8o$14b46o$15b44o$15b44o$14b46o$14b46o$15b34ob2ob6o$15b4o
b2ob25o2b2o2b5o$14b5ob2ob26ob2ob7o$14b5ob2ob37o$15b4ob2ob36o$15b44o$
14b46o$14b46o$15b44o$15bo2b2o2b2o2b2o2b2o2b2o2b2o2b2o2b2o2b2o2b2o2bo!
Day and Knight 6, found by Goldtiger997:

Code: Select all

x = 110, y = 47, rule = B3aeinq4jrtyz5aen6ak7e/S01c2-ak3-aen4-ijnyz5cjkry678
57bo2bobobobobobobobobobobobobobobobobobobobobobobobo2bo$58b51o$58b51o
$57b11ob36ob4o$58b46ob4o$57b30ob15ob6o$58b51o$57b53o$58b51o$57b53o$58b
51o$57b53o$58b51o$57b53o$58b51o$57b53o$58b3ob4ob2o2b38o$57b4ob3o2b2o3b
38o$58b3ob3ob4o2b37o$57b53o$58b51o$57b53o$58b51o$57b53o$58b51o$57b21ob
31o$58b2ob8ob7o4b22o3b3o$57b5ob6o2b5o6b21o3b4o$22bob2obo30b4ob14o4b24o
b3o$2bo11bo8b4o8bo4bo16b5ob7o2b7ob24ob5o$3bo9b3o5b8o5b3o2b3o8b3o5b6ob
6ob37o$2bobo7b2obo6b6o7bo4bo9b3o4b53o$o4bo29bob2obo11bo5b46ob4o$36bo2b
o11bo5b46o3b4o$58b44o2bob3o$57b27ob25o$58b51o$57b15ob7ob2ob7ob18o$58b
3o4b5ob11ob7o2b10ob6o$57b6o2b7o2b3ob5ob6o2b11ob6o$58b4obob7o3b11ob3o2b
10obob4o$57b7ob7o2b16o2b8ob4ob4o$58b24ob7ob18o$57b15ob37o$58b51o$58b
51o$57bo2bobobobobobobobobobobobobobobobobobobobobobobobo2bo!
These were all found with scripts by myself modified from the rulesrc scripts. They can be used in a very similar manner to the equivalent regular rulesrc scripts. Here they are:

This one is modified from wildmyron's searchRules.py:

Code: Select all

# searchRules.py  Search for rules in which a given pattern is a spaceship
# Author: Arie Paap, Aug 2017
# Modified to only search self-complementary rules by Goldtiger997, Aug 2018
#
# Search for isotropic rules where a specified pattern is a spaceship or 
# oscillator. Optimised to search rules which are most likely to contain small
# ships. Search ends when a ship is found.

import golly as g
import itertools
import random

# Search parameters

# Stop if pattern is a ship with this minimum period
minShipP = 4
# Stop if pattern is an oscillator with this minimum period
minP = 1
# Maximum period to test the pattern for
maxGen = 50
# Maximum population in any phase
maxPop = 300
# Allow search for oscillators
bOsc = False
# Force a search for oblique ships
bKnight = False

# Generate a random isotropic rule which is likely to allow spaceships to exist
# Adaptation of a script by Dave Green http://conwaylife.com/forums/viewtopic.php?p=43545#p43545
# ----------------------------------------------------------

isotropiclistB = ["0",
                 "1c", "1e",
                 "2c", "2e", "2k", "2a", "2i", "2n",
                 "3c", "3e", "3k", "3a", "3i", "3n", "3y", "3q", "3j", "3r",
                 "4c", "4e", "4k", "4a", "4i", "4n", "4y", "4q", "4j", "4r", "4t", "4w", "4z",
                 "5c", "5e", "5k", "5a", "5i", "5n", "5y", "5q", "5j", "5r",
                 "6c", "6e", "6k", "6a", "6i", "6n",
                 "7c", "7e",
                 "8"]
isotropiclistS = ["0",
                 "1c", "1e",
                 "2c", "2e", "2k", "2a", "2i", "2n",
                 "3c", "3e", "3k", "3a", "3i", "3n", "3y", "3q", "3j", "3r",
                 "5c", "5e", "5k", "5a", "5i", "5n", "5y", "5q", "5j", "5r",
                 "6c", "6e", "6k", "6a", "6i", "6n",
                 "7c", "7e",
                 "8"]

fours = ["4c", "4e", "4k", "4a", "4i", "4n", "4y", "4q", "4j", "4r", "4t", "4w", "4z"]
reversefours = ["4e", "4c", "4k", "4a", "4t", "4r", "4j", "4w", "4y", "4n", "4i", "4q", "4z"]

# Remove B0 and B1 conditions
isotropiclistB.remove("0")
isotropiclistB.remove("1c")
isotropiclistB.remove("1e")

# Generate a random isotropic rule which is likely to allow spaceships to exist
def randIsoRule():
    # Birth conditions
    prob = random.random()*0.55+0.05 # Random number between 0.05 and 0.6
    rulestr = ""
    for elem in isotropiclistB:
        if random.random()<prob: rulestr+=elem
    # Ensure rule has a chance of supporting ships
    if len(rulestr) == 0:
        # Add a random rule element
        rulestr+=random.choice(isotropiclistB)
    if not rulestr[0] in '23':
        # Add two random 2x or 3x rule elements
        rulestr+=random.choice(isotropiclistB[:16])
        rulestr+=random.choice(isotropiclistB[:16])
    
    # Survival conditions (force S0 for dot survival)
    #prob = random.random()*0.55+0.05 # Random number between 0.05 and 0.6
    #rulestr+='/S'
    # S0 is best used when the test pattern is sparse / has a low population
    #if random.random()<0.5: rulestr+='0' 
    #for elem in isotropiclistS:
     #   if random.random()<prob: rulestr+=elem

    inverse = ""
    for trans in isotropiclistS:
        if trans not in rulestr:
            flipped = str(8-int(trans[0])) + trans[1:]
            inverse += flipped

    for i in range(0,len(fours)):
        if fours[i] not in rulestr:
            inverse += reversefours[i]
     
    return("B" + rulestr + "/S" + inverse)
    
# ----------------------------------------------------------

# Return the minimum and maximum of the absolute value of a list of numbers
def minmaxofabs(v):
    v = map(abs, v)
    return min(v), max(v)

# Test a pattern in the given rule to determine if it reappears
def testRule(rulestr):
    r = g.getrect()
    if r:
        g.select(r)
        g.clear(0)
    g.putcells(testPatt)
    g.setrule(rulestr)
    for ii in xrange(maxGen):
        g.run(1)
        pop = int(g.getpop())
        if (pop < minPop or pop > maxPop):
            break
        elif (pop == testPop):
            # Test for periodicity
            r = g.getrect()
            if testPatt == g.transform(g.getcells(r),-r[0],-r[1]):
                period = ii+1
                if (r[0] == 0 and r[1] == 0 ):
                    # Oscillator (reject if low period or bOsc is False)
                    if bOsc and period >= minP:
                        return (period, )
                elif ( period >= minShipP and (bKnight == False or (abs(r[0]) != abs(r[1]) and r[0] != 0 and r[1] != 0))):
                    # Spaceship (reject if low period)
                    return (r[0], r[1], period) 
                break # Pattern is a low period oscillator or spaceship
    return ()
    
# Set up the search with the current pattern
testRect = g.getrect()
testPop = int(g.getpop())
testPatt = g.transform(g.getcells(testRect),-testRect[0],-testRect[1])

if bOsc: minPop = 2 # Patterns with 0, or 1 cells can not be oscillators
else: minPop = 3 # Patterns with 0, 1, or 2 cells can not be ships

g.new('searchRules')

for ii in itertools.count(0,1):
    result = testRule(randIsoRule())
    if result:
        # Interesting pattern found
        break
    if (ii % 1000 == 0):
        g.select([])
        g.show('%d candidate rules tested for interesting patterns' % (ii))
        g.update()
        g.new("")
        
g.new('Search result')
if result:
    g.putcells(testPatt)
    if (len(result) == 1):
        # Pattern is an oscillator
        description = 'Found oscillator with period = %d' % result
    elif (len(result) == 3):
        dx, dy, period = result
        dy, dx = minmaxofabs( (dx, dy) )
        if dy == 0:
            description = 'Found orthogonal spaceship with speed = %dc/%d' % (dx, period)
        elif dy == dx:
            description = 'Found diagonal spaceship with speed = %dc/%d' % (dx, period)
        else:
            description = 'Found knightship with speed = (%d, %d)c/%d' % (dx, dy, period)
    else:
        g.exit('Unrecognised pattern')
    g.show(description)
else:
    g.show('No results found')
This one is modified from Rhombic's iterulesrc.py:

Code: Select all

# iterRulesrc.py
#
# This version of Rulesrc (available: ConwayLife.com) aims to improve search efficiency for productive patterns+conditions.
# The results get listed to iterRulesrc_results.txt and the search is cancelled by pressing any key.

# Arie Paap, Aug 2017
# Nathaniel Johnston (nathaniel@nathanieljohnston.com), June 2009.
# Updated by: Peter, NASZVADI (), June 2017.
# Grafted by Rhombic, Aug 2017.
# Modified to only search self-complementary rules by Goldtiger997, Aug 2018

import golly as g
import itertools
from glife import validint
from string import replace
import random

if g.empty():
    g.note("This program needs you to paste in a pattern to work.\nThen you can run the script",False)
    g.setrule("B2ci3ai4c8/S02ae3eijkq4iz5ar6i7e")
    g.putcells(g.parse("obo!"))
    g.exit()

knight=g.getstring('Do you want to force knightships (y/n)?',"y")
if knight == "y":
    bKnight = True
else:
    bKnight = False

GENERATION_STRING=g.getstring('To stop this script, press any key at any point.\nHow many generations to remain unchanged:', '', 'Rules calculator')

birth_survival = g.getstring("Well actually for self-complementary rules you can't necessarily force the Generations to remain unchanged.\nSo this script supports keeping either the necessary birth conditions or the necessary survival conditions.\nWhich one would you like to keep (b/s)?","b")
if birth_survival == "b":
    bs = "birth"
if birth_survival == "praisecalcyman":
    g.setrule("b3/s23")
    g.new("praisecalcyman")
    g.putcells(g.parse("2bo$bobo$bobo$2ob3o$6bo$2ob3o$2obo!"))
    g.exit("Praise Calcyman")
else:
    bs = "survival"


def setminrule(RULE, DX, DY, PERIOD):
    # Rule computation script for use with Golly.
    # Author: Nathaniel Johnston (nathaniel@nathanieljohnston.com), June 2009.
    # Updated by: Peter, NASZVADI (), June 2017.

    # Gives the maximal family of rules that a still life, oscillator, or spaceship
    # works under. Must be called while the rule is set of one such family
    # For example, to find out what rules a glider works in, first set the rule
    # to Life or HighLife, not Seeds.
    # Handles nontotalistic rules, too, so it needs Golly 2.8 or newer.

    import golly as g

    g.setrule(RULE)

    Hensel = [
        ['0'],
        ['1c', '1e'],
        ['2a', '2c', '2e', '2i', '2k', '2n'],
        ['3a', '3c', '3e', '3i', '3j', '3k', '3n', '3q', '3r', '3y'],
        ['4a', '4c', '4e', '4i', '4j', '4k', '4n', '4q', '4r', '4t', '4w', '4y', '4z'],
        ['5a', '5c', '5e', '5i', '5j', '5k', '5n', '5q', '5r', '5y'],
        ['6a', '6c', '6e', '6i', '6k', '6n'],
        ['7c', '7e'],
        ['8']
    ]

    # Python versions < 2.4 don't have "sorted" built-in
    try:
        sorted
    except NameError:
        def sorted(inlist):
            outlist = list(inlist)
            outlist.sort()
            return outlist

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

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

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

    def rulestringopt(a):
        result = ''
        context = ''
        lastnum = ''
        lastcontext = ''
        for i in a:
            if i in 'BS':
                context = i
                result += i
            elif i in '012345678':
                if (i == lastnum) and (lastcontext == context):
                    pass
                else:
                    lastcontext = context
                    lastnum = i
                    result += i
            else:
                result += i
        result = replace(result, '4aceijknqrtwyz', '4')
        result = replace(result, '3aceijknqry', '3')
        result = replace(result, '5aceijknqry', '5')
        result = replace(result, '2aceikn', '2')
        result = replace(result, '6aceikn', '6')
        result = replace(result, '1ce', '1')
        result = replace(result, '7ce', '7')
        return result

    clist = []
    rule = g.getrule().split(':')[0]

    fuzzer = rule + '9'
    oldrule = rule
    rule = ''
    context = ''
    deletefrom = []
    for i in fuzzer:
        if i == '-':
            deletefrom = [x[1] for x in Hensel[int(context)]]
        elif i in '0123456789/S':
            if deletefrom:
                rule += ''.join(deletefrom)
                deletefrom = []
            context = i
        if len(deletefrom) == 0:
            rule += i
        elif i in deletefrom:
            deletefrom.remove(i)
    rule = rule.strip('9')

    if not (rule[0] == 'B' and '/S' in rule):
        g.exit('Please set Golly to a Life-like rule.')

    if g.empty():
        g.exit('The pattern is empty.')

    s = PERIOD
    numsteps = PERIOD
    if numsteps < 1:
        g.exit('Period must be at least 1.')

    g.select(g.getrect())
    g.copy()
    s = int(s)

    for i in range(0,s):
        g.run(1)
        clist.append(list(chunks(g.getcells(g.getrect()), 2)))
        mcc = min(clist[i])
        clist[i] = [[x[0] - mcc[0], x[1] - mcc[1]] for x in clist[i]]

    g.show('Processing...')

    ruleArr = rule.split('/')
    ruleArr[0] = ruleArr[0].lstrip('B')
    ruleArr[1] = ruleArr[1].lstrip('S')

    b_need = []
    b_OK = []
    s_need = []
    s_OK = []

    context = ''
    fuzzed = ruleArr[0] + '9'
    for i in fuzzed:
        if i in '0123456789':
            if len(context) == 1:
                b_need += Hensel[int(context)]
                b_OK += Hensel[int(context)]
            context = i
        elif context != '':
            b_need.append(context[0] + i)
            b_OK.append(context[0] + i)
            context += context[0]
    context = ''
    fuzzed = ruleArr[1] + '9'
    for i in fuzzed:
        if i in '0123456789':
            if len(context) == 1:
                s_need += Hensel[int(context)]
                s_OK += Hensel[int(context)]
            context = i
        elif context != '':
            s_need.append(context[0] + i)
            s_OK.append(context[0] + i)
            context += context[0]

    for i in [iter2 for iter1 in Hensel for iter2 in iter1]:
        if not i in b_OK:
            b_OK.append(i)
            execfor = 1
            # B0 and nontotalistic rulestrings are mutually exclusive
            try:
                g.setrule(rulestringopt('B' + ''.join(b_OK) + '/S' + ruleArr[1]))
            except:
                b_OK.remove(i)
                execfor = 0
            for j in range(0, s * execfor):
                g.run(1)
                try:
                    dlist = list(chunks(g.getcells(g.getrect()), 2))
                    mcc = min(dlist)
                    dlist = [[x[0] - mcc[0], x[1] - mcc[1]] for x in dlist]
                    if not(clist[j] == dlist):
                        b_OK.remove(i)
                        break
                except:
                    b_OK.remove(i)
                    break
            g.new('')
            g.paste(0, 0, 'or')
            g.select(g.getrect())
            b_OK.sort()

        if not i in s_OK:
            s_OK.append(i)
            execfor = 1
            # B0 and nontotalistic rulestrings are mutually exclusive
            try:
                g.setrule(rulestringopt('B' + ruleArr[0] + '/S' + ''.join(s_OK)))
            except:
                s_OK.remove(i)
                execfor = 0
            for j in range(0, s * execfor):
                g.run(1)
                try:
                    dlist = list(chunks(g.getcells(g.getrect()), 2))
                    mcc = min(dlist)
                    dlist = [[x[0] - mcc[0], x[1] - mcc[1]] for x in dlist]
                    if not(clist[j] == dlist):
                        s_OK.remove(i)
                        break
                except:
                    s_OK.remove(i)
                    break
            g.new('')
            g.paste(0, 0, 'or')
            g.select(g.getrect())
            s_OK.sort()

        if i in b_need:
            b_need.remove(i)
            g.setrule(rulestringopt('B' + ''.join(b_need) + '/S' + ruleArr[1]))
            for j in range(0, s):
                g.run(1)
                try:
                    dlist = list(chunks(g.getcells(g.getrect()), 2))
                    mcc = min(dlist)
                    dlist = [[x[0] - mcc[0], x[1] - mcc[1]] for x in dlist]
                    if not(clist[j] == dlist):
                        b_need.append(i)
                        break
                except:
                    b_need.append(i)
                    break
            g.new('')
            g.paste(0, 0, 'or')
            g.select(g.getrect())
            b_need.sort()

        if i in s_need:
            s_need.remove(i)
            g.setrule(rulestringopt('B' + ruleArr[0] + '/S' + ''.join(s_need)))
            for j in range(0, s):
                g.run(1)
                try:
                    dlist = list(chunks(g.getcells(g.getrect()), 2))
                    mcc = min(dlist)
                    dlist = [[x[0] - mcc[0], x[1] - mcc[1]] for x in dlist]
                    if not(clist[j] == dlist):
                        s_need.append(i)
                        break
                except:
                    s_need.append(i)
                    break
            g.new('')
            g.paste(0, 0, 'or')
            g.select(g.getrect())
            s_need.sort()

    g.setrule(oldrule)
    ruleres = 'B' + ''.join(sorted(b_need)) + '/S' + ''.join(sorted(s_need))
    ruleres = rulestringopt(ruleres)
    g.setrule(ruleres)
    RESULT = [ruleres, DX, DY, PERIOD]
    return RESULT


def Rulesrc():
    # Search parameters

    # Stop if pattern is a ship with this minimum period
    minShipP = 1
    # Stop if pattern is an oscillator with this minimum period
    minP = 3
    # Maximum period to test the pattern for
    maxGen = 1000
    # Maximum population in any phase
    maxPop = 300
    # Allow search for oscillators
    bOsc = False


    import golly as g
    from glife import validint
    from string import replace

    Hensel = [
        ['0'],
        ['1c', '1e'],
        ['2a', '2c', '2e', '2i', '2k', '2n'],
        ['3a', '3c', '3e', '3i', '3j', '3k', '3n', '3q', '3r', '3y'],
        ['4a', '4c', '4e', '4i', '4j', '4k', '4n', '4q', '4r', '4t', '4w', '4y', '4z'],
        ['5a', '5c', '5e', '5i', '5j', '5k', '5n', '5q', '5r', '5y'],
        ['6a', '6c', '6e', '6i', '6k', '6n'],
        ['7c', '7e'],
        ['8']
    ]

    # Python versions < 2.4 don't have "sorted" built-in
    try:
        sorted
    except NameError:
        def sorted(inlist):
            outlist = list(inlist)
            outlist.sort()
            return outlist

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

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

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

    def rulestringopt(a):
        """result = ''
        context = ''
        lastnum = ''
        lastcontext = ''
        for i in a:
            if i in 'BS':
                context = i
                result += i
            elif i in '012345678':
                if (i == lastnum) and (lastcontext == context):
                    pass
                else:
                    lastcontext = context
                    lastnum = i
                    result += i
            else:
                result += i
        result = replace(result, '4aceijknqrtwyz', '4')
        result = replace(result, '3aceijknqry', '3')
        result = replace(result, '5aceijknqry', '5')
        result = replace(result, '2aceikn', '2')
        result = replace(result, '6aceikn', '6')
        result = replace(result, '1ce', '1')
        result = replace(result, '7ce', '7')
        return result"""
        return a

    clist = []
    rule = g.getrule().split(':')[0]

    fuzzer = rule + '9'
    oldrule = rule
    rule = ''
    context = ''
    deletefrom = []
    for i in fuzzer:
        if i == '-':
            deletefrom = [x[1] for x in Hensel[int(context)]]
        elif i in '0123456789/S':
            if deletefrom:
                rule += ''.join(deletefrom)
                deletefrom = []
            context = i
        if len(deletefrom) == 0:
            rule += i
        elif i in deletefrom:
            deletefrom.remove(i)
    rule = rule.strip('9')

    if not (rule[0] == 'B' and '/S' in rule):
        g.exit('Please set Golly to a Life-like rule.')

    if g.empty():
        g.exit('The pattern is empty.')

    s = GENERATION_STRING
    if not validint(s):
        g.exit('Bad number: %s' % s)

    numsteps = int(s)
    if numsteps < 1:
        g.exit('Period must be at least 1.')

    g.select(g.getrect())
    g.copy()
    s = int(s)

    for i in range(0,s):
        g.run(1)
        clist.append(list(chunks(g.getcells(g.getrect()), 2)))
        mcc = min(clist[i])
        clist[i] = [[x[0] - mcc[0], x[1] - mcc[1]] for x in clist[i]]

    g.show('Processing...')

    ruleArr = rule.split('/')
    ruleArr[0] = ruleArr[0].lstrip('B')
    ruleArr[1] = ruleArr[1].lstrip('S')

    b_need = []
    b_OK = []
    s_need = []
    s_OK = []

    context = ''
    fuzzed = ruleArr[0] + '9'
    for i in fuzzed:
        if i in '0123456789':
            if len(context) == 1:
                b_need += Hensel[int(context)]
                b_OK += Hensel[int(context)]
            context = i
        elif context != '':
            b_need.append(context[0] + i)
            b_OK.append(context[0] + i)
            context += context[0]
    context = ''
    fuzzed = ruleArr[1] + '9'
    for i in fuzzed:
        if i in '0123456789':
            if len(context) == 1:
                s_need += Hensel[int(context)]
                s_OK += Hensel[int(context)]
            context = i
        elif context != '':
            s_need.append(context[0] + i)
            s_OK.append(context[0] + i)
            context += context[0]

    for i in [iter2 for iter1 in Hensel for iter2 in iter1]:
        if not i in b_OK:
            b_OK.append(i)
            execfor = 1
            # B0 and nontotalistic rulestrings are mutually exclusive
            try:
                g.setrule(rulestringopt('B' + ''.join(b_OK) + '/S' + ruleArr[1]))
            except:
                b_OK.remove(i)
                execfor = 0
            for j in range(0, s * execfor):
                g.run(1)
                try:
                    dlist = list(chunks(g.getcells(g.getrect()), 2))
                    mcc = min(dlist)
                    dlist = [[x[0] - mcc[0], x[1] - mcc[1]] for x in dlist]
                    if not(clist[j] == dlist):
                        b_OK.remove(i)
                        break
                except:
                    b_OK.remove(i)
                    break
            g.new('')
            g.paste(0, 0, 'or')
            g.select(g.getrect())
            b_OK.sort()

        if not i in s_OK:
            s_OK.append(i)
            execfor = 1
            # B0 and nontotalistic rulestrings are mutually exclusive
            try:
                g.setrule(rulestringopt('B' + ruleArr[0] + '/S' + ''.join(s_OK)))
            except:
                s_OK.remove(i)
                execfor = 0
            for j in range(0, s * execfor):
                g.run(1)
                try:
                    dlist = list(chunks(g.getcells(g.getrect()), 2))
                    mcc = min(dlist)
                    dlist = [[x[0] - mcc[0], x[1] - mcc[1]] for x in dlist]
                    if not(clist[j] == dlist):
                        s_OK.remove(i)
                        break
                except:
                    s_OK.remove(i)
                    break
            g.new('')
            g.paste(0, 0, 'or')
            g.select(g.getrect())
            s_OK.sort()

        if i in b_need:
            b_need.remove(i)
            g.setrule(rulestringopt('B' + ''.join(b_need) + '/S' + ruleArr[1]))
            for j in range(0, s):
                g.run(1)
                try:
                    dlist = list(chunks(g.getcells(g.getrect()), 2))
                    mcc = min(dlist)
                    dlist = [[x[0] - mcc[0], x[1] - mcc[1]] for x in dlist]
                    if not(clist[j] == dlist):
                        b_need.append(i)
                        break
                except:
                    b_need.append(i)
                    break
            g.new('')
            g.paste(0, 0, 'or')
            g.select(g.getrect())
            b_need.sort()

        if i in s_need:
            s_need.remove(i)
            g.setrule(rulestringopt('B' + ruleArr[0] + '/S' + ''.join(s_need)))
            for j in range(0, s):
                g.run(1)
                try:
                    dlist = list(chunks(g.getcells(g.getrect()), 2))
                    mcc = min(dlist)
                    dlist = [[x[0] - mcc[0], x[1] - mcc[1]] for x in dlist]
                    if not(clist[j] == dlist):
                        s_need.append(i)
                        break
                except:
                    s_need.append(i)
                    break
            g.new('')
            g.paste(0, 0, 'or')
            g.select(g.getrect())
            s_need.sort()

    g.setrule(oldrule)
    ruleres = 'B' + ''.join(sorted(b_need)) + '/S' + ''.join(sorted(s_need)) + \
        ' - B' + ''.join(sorted(b_OK)) + '/S' + ''.join(sorted(s_OK))
    g.show(rulestringopt(ruleres))

    ruleB="B"+''.join(sorted(b_need))
    ruleS="S"+''.join(sorted(s_need))
    isotropiclistB = sorted(b_OK)
    isotropiclistS = sorted(s_OK)
    isotropiclist = ["0",
                 "1c", "1e",
                 "2c", "2e", "2k", "2a", "2i", "2n",
                 "3c", "3e", "3k", "3a", "3i", "3n", "3y", "3q", "3j", "3r",
                 "5c", "5e", "5k", "5a", "5i", "5n", "5y", "5q", "5j", "5r",
                 "6c", "6e", "6k", "6a", "6i", "6n",
                 "7c", "7e",
                 "8"]

    fours = ["4c", "4e", "4k", "4a", "4i", "4n", "4y", "4q", "4j", "4r", "4t", "4w", "4z"]
    reversefours = ["4e", "4c", "4k", "4a", "4t", "4r", "4j", "4w", "4y", "4n", "4i", "4q", "4z"]

    # Remove B0 and B1 conditions
    for wrongvalues in ["0","1c","1e"]:
        if wrongvalues in isotropiclistB:
            isotropiclistB.remove(wrongvalues)

    # Generate a random isotropic rule which is likely to allow spaceships to exist
    def randIsoRule():
        # Birth conditions
        prob = random.random()*0.55+0.05 # Random number between 0.05 and 0.6
        if bs == "birth":
            rulestr = ruleB
            for elem in isotropiclistB:
                if random.random()<prob: rulestr+=elem
            # Ensure rule has a chance of supporting ships
            if len(rulestr) == 1:
                # Add a random rule element
                rulestr+=random.choice(isotropiclistB)
            if not rulestr[1] in '23':
                # Add two random 2x or 3x rule elements
                rulestr+=random.choice(isotropiclistB[:16])
                rulestr+=random.choice(isotropiclistB[:16])

            inverse = ""
            for trans in isotropiclist:
                if trans not in rulestr:
                    flipped = str(8-int(trans[0])) + trans[1:]
                    inverse += flipped

            for i in range(0,len(fours)):
                if fours[i] not in rulestr:
                    inverse += reversefours[i]
                    
            return(rulestr + "/S" + inverse)
        else:
            rulestr = ruleS
            for elem in isotropiclistS:
                if random.random()<prob: rulestr+=elem
            
            inverse = ""
            for trans in isotropiclist:
                if trans not in rulestr:
                    flipped = str(8-int(trans[0])) + trans[1:]
                    inverse += flipped

            for i in range(0,len(fours)):
                if fours[i] not in rulestr:
                    inverse += reversefours[i]
            return("B" + inverse + rulestr)
            
    # ----------------------------------------------------------

    # Return the minimum and maximum of the absolute value of a list of numbers
    def minmaxofabs(v):
        v = map(abs, v)
        return min(v), max(v)

    # Stability check periodicity
    stabCheckP = 24

    # Test a pattern in the given rule to determine if it reappears
    def testRule(rulestr):
        r = g.getrect()
        if r:
            g.select(r)
            g.clear(0)
        g.putcells(testPatt)
        g.setrule(rulestr)
        stabPatt = testPatt
        stabPop = testPop
        for ii in xrange(maxGen):
            g.run(1)
            pop = int(g.getpop())
            if (pop < minPop or pop > maxPop):
                break
            elif (pop == testPop):
                # Test for periodicity
                r = g.getrect()
                if testPatt == g.transform(g.getcells(r),-r[0],-r[1]):
                    period = ii+1
                    if (r[0] == 0 and r[1] == 0 ):
                        # Oscillator (reject if low period or bOsc is False)
                        if bOsc and period >= minP:
                            return (period, )
                    elif ( period >= minShipP and (bKnight == False or (abs(r[0]) != abs(r[1]) and r[0] != 0 and r[1] != 0))):
                        # Spaceship (reject if low period)
                        return (r[0], r[1], period)
                    break # Pattern is a low period oscillator or spaceship
            # Stability check
            if (ii % stabCheckP == 0):
                r = g.getrect()
                currPatt = g.transform(g.getcells(r),-r[0],-r[1])
                if (pop == stabPop and currPatt == stabPatt):
                    # Pattern has stabilised 
                    return ()
                stabPop = pop
                stabPatt = currPatt[:]

        return ()
        
    # Set up the search with the current pattern
    testRect = g.getrect()
    testPop = int(g.getpop())
    testPatt = g.transform(g.getcells(testRect),-testRect[0],-testRect[1])

    if bOsc: minPop = 2 # Patterns with 0, or 1 cells can not be oscillators
    else: minPop = 3 # Patterns with 0, 1, or 2 cells can not be ships

    g.new('spRulesrc')

    for ii in itertools.count(0,1):
        if bOsc==False:
            while 1:
                j=randIsoRule()
                if "2a" in j: break
                if "2c" in j: break
                if "3i" in j: break
        else:
            j=randIsoRule()
        result = testRule(j)
        if result:
            # Interesting pattern found
            break
        if (ii % 1000 == 0):
            g.select([])
            g.show('%d candidate rules tested for interesting patterns' % (ii))
            g.update()
            g.new("")
            
    g.new('Search result')
    if result:
        g.putcells(testPatt)
        if (len(result) == 1):
            # Pattern is an oscillator
            description = 'Found oscillator with period = %d' % result
        elif (len(result) == 3):
            dx, dy, period = result
            dy, dx = minmaxofabs( (dx, dy) )
            if dy == 0:
                description = 'Found orthogonal spaceship with speed = %dc/%d' % (dx, period)
            elif dy == dx:
                description = 'Found diagonal spaceship with speed = %dc/%d' % (dx, period)
            else:
                description = 'Found knightship with speed = (%d, %d)c/%d' % (dx, dy, period)
        else:
            g.exit('Unrecognised pattern')
        g.show(description)
        Spaceship = str(g.getrule()), dx, dy, period
        return Spaceship
    else:
        g.show('No results found')

textfile=open("iterRulesrc_results.txt","w+")
g.select(g.getrect())
g.copy()
textfile.write("\n"+g.getclipstr()+"\n\n")
ListRules = set()
while 1:
    newrule=Rulesrc()
    event = g.getevent()
    if event.startswith("key"):
        break
    if newrule[0] not in ListRules:
        ListRules.add(newrule[0])
        textfile.write(newrule[0]+"\t("+str(newrule[1])+","+str(newrule[2])+")/\t"+str(newrule[3])+"\n")
textfile.close()
g.exit("We have found %d results, found in your rule folder as iterRulesrc_results.txt. Thank you for your patience." % len(ListRules))
Both scripts attempt to satisfy the first two conditions for a Day and Knight rule but make no attempt for the third. Perhaps I will try implementing that.

I hope you find this rule "group" interesting!

AforAmpere
Posts: 1334
Joined: July 1st, 2016, 3:58 pm

Re: Day and Knight rule group

Post by AforAmpere » August 14th, 2018, 11:23 am

After a long search for an interesting rule, this one stood out to me. It fits all the criteria, with this (2,1)c/16 being the knightship:

Code: Select all

x = 4, y = 5, rule = B2cik3aekry4ijnrwz5-jqr6ik7e8/S1c2-ik3jqr4aceijkw5cijnq6aen78
$b2o$bo$2bo!
However, it also has many other ships and wickstretchers:

Code: Select all

x = 485, y = 129, rule = B2cik3aekry4ijnrwz5-jqr6ik7e8/S1c2-ik3jqr4aceijkw5cijnq6aen78
100o$100o$100o$100o$100o$100o$100o$100o$100o$100o$100o$100o$100o$100o$
100o$100o$100o$100o$100o$100o$100o$100o$100o$100o$100o$100o$100o$100o$
100o$100o$37o2b8o2b51o49bo4bo8bo11bo14bo9bo6bo11bo10bo6bo13bo29b2o8b2o
37bo13bo9bo16bo9bo15bo9bo14bo6bo11bo7bo12bo16bo$38o2b8o2b50o48b3o2b3o
6b3o8b3ob2o9b5o5b3o6b3o9bo8b3o6b3o11bo29bo10b2o35b3o10b3ob2o3b2ob3o12b
3ob2o3b2ob3o12b3obo3bob3o12b2obo2bob2o9b2obo3bob2o11bo14bobobo$38ob10o
b50o48bo2bob2o7bo2bo6bob3obo9b5o5b3o6b3o6bob3obo5bob2o4b2obo9bobobo28b
o10bo35bo2bo9b4obo3bob4o12b4obo3bob4o11b2ob3o3b3ob2o13bo4bo11b2ob2ob2o
b2o11bo12b9o$46ob53o47b4ob3o5b7o5bobobobo10bobo6bo2b2o2b2o2bo8b3o8bo8b
o9bob3obo35bo36b7o8b2obobo3bobob2o12b2obobo3bobob2o15bo5bo17b6o15b3o
13b5o10bo2bobo2bo$100o48b7o6b5o6b2ob3o9bobobobo4bo10bo6b7o7bo6bo8b2ob
5ob2o71b5o9bo2b2o5b2o2bo12bo2b2o5b2o2bo12b2o9b2o13bob4obo13b2ob2o12bo
3bo11b2obob2o$100o48b5obo6bob3o10b2o10bo3bo5b2ob2o2b2ob2o5b3obob3o7b2o
2b2o10bob5obo72bob3o10bobo7bobo14bobo7bobo11b2o2bob2ob2obo2b2o13b4o15b
5o10b3obob3o9b2obob2o$100o48bob2obo7bo2b2o5bo5bobo7b2o3b2o7b2o2b2o8b3o
bob3o6bobo2bobo9b2ob3ob2o72bo2b2o9b3o2bobobo2b3o12b3o2bobobo2b3o11b2ob
2obobob2ob2o12b8o12bob3obo10b2obob2o12b3o$100o49b4o10b3o5bob2ob3o7b2ob
3ob2o8b2o9b2o2b3o2b2o105b3o9bo2bo7bo2bo12bo2bo7bo2bo12b2o2bo3bo2b2o13b
o6bo14b3o12b7o12b3o$100o63b3o6b4ob2o7bo3bo3bo7bo2bo24b3o2b3o9bo3bo3bo
74b3o10b3obo3bob3o14b3obo3bob3o13b3o2b3o2b3o16b2o16bobobo11b7o12b3o$
100o63b3o6b4ob2o7b4ob4o6b6o9b2obob2o8bo4bo9b2o3bo3b2o73b3o11bob3ob3obo
16bob3ob3obo16bobobobobo35b3ob3o10b7o11b5o$100o63b3o7bo2b3o7b9o3b12o9b
o26bobo2bo2bobo73b3o11bo2bo3bo2bo16bo2bo3bo2bo15bo3b3o3bo16b4o16b3o12b
7o10b7o$100o63b3o24bo7bob8obo8bobo10b6o8bob2o5b2obo72b3o11b3o5b3o16b3o
5b3o16bo7bo17bo2bo13b9o9b7o8b2ob5ob2o$100o63b3o8bo2bo22b2ob2ob2o11bo
11b6o8bob3o3b3obo71b4o10bo11bo14bo11bo13bo5bo5bo31b3o5b3o8b7o9b9o$100o
63b3o10bo12bobo9bob2obo12bo28b2o3b2o74b4o9bo5bobo5bo12bo5bobo5bo12bo3b
5o3bo15b4o12bobo2bo2bobo24b9o$100o63b3o33b2o6b2o21b2o4b2o9b2o5b2o73b4o
8bob2o2b2ob2o2b2obo10bob2o2b2ob2o2b2obo9b7obob7o13b4o14b2obob2o26b9o$
100o63b3o9bo23bo8bo20b2obo2bob2o9bo5bo87b4o3bo3b4o12b4o3bo3b4o11b2o2b
3ob3o2b2o14b4o13b3obob3o25b9o$100o63b3o9b2o21b3ob4ob3o21b6o10b3o3b3o
86b3o2bobobo2b3o12b3o2bobobo2b3o11b3o9b3o12bobo2bobo11b9o25b9o$100o63b
3o8bob2o20b2o2b4o2b2o21b6o8b4o5b4o84b7ob7o12b7ob7o11b5obobob5o11b2ob4o
b2o9b11o$100o63b3o9b3o21b2ob4ob2o22b6o9bo3bobo3bo85b15o12b15o11b6obob
6o12b2o4b2o12b7o$100o62b4o33bob6obo21b8o8bo2b2ob2o2bo85b4o7b4o12b4o7b
4o11b5o5b5o12b3o2b3o12bob3obo$100o61b2ob2o34b8o21b10o9bob3obo87b4o7b4o
12b4o7b4o11b5o2bo2b5o12bo6bo10bo3b3o3bo$100o60bobob2o35b6o23b2o4b2o7b
2obob3obob2o84b4ob2ob2ob4o12b4ob2ob2ob4o11b4ob5ob4o11b3o4b3o10b2ob3ob
2o$100o61b5o36b4o25bo4bo10bob5obo86b4o2b3o2b4o12b4o2b3o2b4o11b3o2bo3bo
2b3o11bobo4bobo12b2ob2o$100o62b4o35bob2obo23b3o2b3o8b4obob4o84b3o3bobo
bo3b3o10b3o3bobobo3b3o10bo3b2o3b2o3bo11bob2o2b2obo12b2ob2o$100o62b4o
65bo4bo12bobobo88bo5b3o5bo12bo5b3o5bo15b2o3b2o16bo2b2o2bo12b3ob3o$100o
60b2ob3o64b2o4b2o9b2ob3ob2o86bo3bo5bo3bo12bo3bo5bo3bo13b3o5b3o14b8o13b
2ob2o$100o61b4o64b3o4b3o7b2obobobob2o86bob2o5b2obo14bob2o5b2obo13b4o5b
4o13b8o13b5o$100o61bo2b3o62b3o4b3o9bo2bo2bo88b3o7b3o14b3o7b3o13bobobo
3bobobo15bo2bo15b5o$100o130bo6bo9b9o88b2obo3bob2o16b2obo3bob2o14bo11bo
14b6o14b5o$100o128b3obo2bob3o7bo7bo89bo7bo18bo7bo15bobo7bobo15b4o15b5o
$100o133b2o14b5o89bo11bo14bo11bo15bobo3bobo16b6o14b5o$100o130b8o7b5obo
b5o85bob2ob3ob2obo14bob2ob3ob2obo13bobob5obobo12b10o12b5o$100o133b2o
13bob3obo88b3ob5ob3o14b3ob5ob3o12b2o11b2o11b10o12b5o$100o148b2obob2o
86b4ob2obob2ob4o10b4ob2obob2ob4o11bo2b2o3b2o2bo12b10o12b5o$100o130b2ob
2ob2o10bob3obo88bo2bo2bo2bo2bo14bo2bo2bo2bo2bo38b10o$100o131b6o11b7o
87b2ob2o5b2ob2o12b2ob2o5b2ob2o11bobobo5bobobo$100o132b4o13bo3bo90bob2o
3b2obo16bob2o3b2obo$100o131bob2obo10bo7bo89b2o5b2o18b2o5b2o18b2o3b2o$
100o148bobobobo142bo9bo$100o133b2o14b5o90bo9bo16bo9bo$100o130b3o2b3o
12b3o91bo2bo3bo2bo16bo2bo3bo2bo15b2obo3bob2o$100o149b5o89b2obo5bob2o
14b2obo5bob2o13b4o5b4o$100o130b8o12b3o96bo26bo18b3obobobobob3o$100o
128bobob4obobo10b3o90b2obob3obob2o14b2obob3obob2o12b2ob4ob4ob2o$100o
128bo4b2o4bo8b7o87b2ob2ob3ob2ob2o12b2ob2ob3ob2ob2o10b3ob9ob3o$100o129b
2ob4ob2o12bo89b2o2b9o2b2o10b2o2b9o2b2o9b2o2b9o2b2o$100o130b8o10b7o86b
2obob7obob2o10b2obob7obob2o9b2o3b7o3b2o$100o130b8o11bo3bo87b17o10b17o
9b2obo2b5o2bob2o$100o128bob8obo101b3o2b7o2b3o10b3o2b7o2b3o9b3o2b7o2b3o
$100o129b10o102b4ob7ob4o10b4ob7ob4o9b4ob7ob4o$100o131b6o104b2o3b7o3b2o
10b2o3b7o3b2o9b3o2b7o2b3o$100o131b6o104b17o10b17o9b3o2b7o2b3o$100o129b
2ob4ob2o102b4o2b5o2b4o10b4o2b5o2b4o9b3o5bo5b3o$100o129b2o2b2o2b2o102b
3o4bobo4b3o10b3o4bobo4b3o9b3o3bo3bo3b3o$100o129bob6obo102b3o5bo5b3o10b
3o5bo5b3o9b3o11b3o$100o128b2o2b4o2b2o101b3o5bo5b3o10b3o5bo5b3o9b3o11b
3o$100o128b12o101b3o11b3o10b3o11b3o8b4o11b4o$100o131bob2obo104b3o4bobo
4b3o10b3o4bobo4b3o8b4o11b4o$100o132b4o105b3o3bo3bo3b3o10b3o3bo3bo3b3o
8b4o11b4o$100o132b4o105b3o5bo5b3o10b3o5bo5b3o$100o131b6o104b3o4b3o4b3o
10b3o4b3o4b3o$100o129bo2b4o2bo102b3o4bobo4b3o10b3o4bobo4b3o$100o129b3o
b2ob3o102b2o2bo7bo2b2o10b2o2bo7bo2b2o$100o129bo2b4o2bo102b3ob3o3b3ob3o
10b3ob3o3b3ob3o$100o128b2o2b4o2b2o101b3obob5obob3o10b3obob5obob3o$100o
129b10o102b3ob2o2bo2b2ob3o10b3ob2o2bo2b2ob3o$100o130b8o103b4obo5bob4o
10b4obo5bob4o$100o129b10o102b4o9b4o10b4o9b4o$100o128bob8obo101b2obo9bo
b2o10b2obo9bob2o$100o128b3ob4ob3o101b2obo9bob2o10b2obo9bob2o$233b2o
106b3obo7bob3o10b3obo7bob3o$229bo2b4o2bo102b4obo5bob4o10b4obo5bob4o$
230b2ob2ob2o103b2ob2o7b2ob2o10b2ob2o7b2ob2o$230b2o4b2o106bob2o3b2obo
16bob2o3b2obo$230b8o106bo2bo3bo2bo16bo2bo3bo2bo$231b6o107bob2o3b2obo
16bob2o3b2obo$232b4o107b2o9b2o14b2o9b2o$230b8o104bo6bo6bo12bo6bo6bo$
230bob4obo103b5o2b3o2b5o10b5o2b3o2b5o$231b6o105b3o2b5o2b3o12b3o2b5o2b
3o$342b15o12b15o$342b15o12b6obob6o$342b15o12b4o3bo3b4o$342b15o12b4obob
obob4o$342b15o12b2o4b3o4b2o$342b15o12b3o2b5o2b3o$342b15o12b3o2b5o2b3o$
342b15o12b3o2b5o2b3o$342b15o12b3o2b5o2b3o$342b15o12b3o2b5o2b3o$342b15o
12b3o2b5o2b3o$342b15o12b3o2b5o2b3o$342b15o12b3o2b5o2b3o$342b15o12b3o2b
5o2b3o$342b15o12b3o2b5o2b3o$342b15o12b3o2b5o2b3o$342b15o11b4o2b5o2b4o$
342b15o11b4o2b5o2b4o$342b15o11b4o2b5o2b4o!
Not many interesting oscillators that I can tell, maybe apgsearch will reveal more:

Code: Select all

x = 37, y = 21, rule = B2cik3aekry4ijnrwz5-jqr6ik7e8/S1c2-ik3jqr4aceijkw5cijnq6aen78
5$6b2o3b4o4bo4b2o6b3o$5b3o3b4o4bo4bo8b2o$5b2o5b2o4b3o5bo3bo2b2o$18bobo
9b5o$18bobo9b4o!
I manage the 5S project, which collects all known spaceship speeds in Isotropic Non-totalistic rules. I also wrote EPE, a tool for searching in the INT rulespace.

Things to work on:
- Find (7,1)c/8 and 9c/10 ships in non-B0 INT.
- EPE improvements.

Post Reply