Golly 3.0b1

For general discussion about Conway's Game of Life.
User avatar
Andrew
Moderator
Posts: 919
Joined: June 2nd, 2009, 2:08 am
Location: Melbourne, Australia
Contact:

Golly 3.0b1

Post by Andrew » June 29th, 2017, 10:05 pm

EDIT: Golly 3.0b2 has been released so the links to version 3.0b1 have been removed.

Major changes since version 2.9b1:

- Golly has a new algorithm to support Larger than Life rules. See Help > Algorithms > Larger than Life.

- Support for MAP rules.

- Significant improvements to the overlay, including a number of new commands: ellipse, lineoption, optimize, replace, scale, target.

As always, see Help > Changes for the full list of changes.
Use Glu to explore CA rules on non-periodic tilings: DominoLife and HatLife

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

Re: Golly 3.0b1

Post by gameoflifeboy » June 30th, 2017, 1:13 am

This is cool! Having never downloaded Golly 2.9 I don't know how much is really new, but I'm already loving some of the overlay features! Nice job! I'm sure it will take me quite a while to explore all of the features available.

I also like how the default file folder is now the main Golly folder, so that the sidebar includes both the patterns and scripts folders again. It was getting annoying to go into the file menu whenever I wanted to open a pattern.

I did notice a few issues, however. For one, mousing over a file in the file list in a way that causes alt text to appear seems to cause other Golly windows (like the pattern information window), if open, to hide behind the main window. Also, the descriptions for many of the Larger than Life patterns (which are super cool, and remind me of SmoothLife), seem to be taken straight from Mcell, which sometimes results in wrong descriptions of things like the colors of the cells.
Further updates if I discover more issues.

Nevertheless, this is a very exciting update and I look forward to see what new things will be discovered in Larger than Life rules!

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

Re: Golly 3.0b1

Post by Saka » June 30th, 2017, 1:51 am

Why does LTL have to be on a torus?

User avatar
Andrew
Moderator
Posts: 919
Joined: June 2nd, 2009, 2:08 am
Location: Melbourne, Australia
Contact:

Re: Golly 3.0b1

Post by Andrew » June 30th, 2017, 4:36 am

gameoflifeboy wrote:Having never downloaded Golly 2.9 I don't know how much is really new
See Help > Changes for the list of changes since version 2.8.
I did notice a few issues, however. For one, mousing over a file in the file list in a way that causes alt text to appear seems to cause other Golly windows (like the pattern information window), if open, to hide behind the main window.
Is this on Windows? If so, which version? I don't see any such problems on my Win XP/7 systems, but I don't really know what you mean by "mousing over a file in the file list in a way that causes alt text to appear". What text exactly? Maybe post a screenshot.
Also, the descriptions for many of the Larger than Life patterns (which are super cool, and remind me of SmoothLife), seem to be taken straight from Mcell, which sometimes results in wrong descriptions of things like the colors of the cells.
Yep, I wasn't too sure what to do about some of those comments. The .mcl files were included to show that Golly can read MCell files, but I should probably convert them to .rle with updated comments.
Use Glu to explore CA rules on non-periodic tilings: DominoLife and HatLife

User avatar
Andrew
Moderator
Posts: 919
Joined: June 2nd, 2009, 2:08 am
Location: Melbourne, Australia
Contact:

Re: Golly 3.0b1

Post by Andrew » June 30th, 2017, 4:41 am

Saka wrote:Why does LTL have to be on a torus?
A bounded plane is also supported. If you're asking why the LtL algo only supports a bounded universe then the main reason is simplicity. This was my first foray into writing a new algorithm for Golly, so I wanted to keep things pretty simple, at least initially. The final 3.0 version may well allow an unbounded universe, but no promises.
Use Glu to explore CA rules on non-periodic tilings: DominoLife and HatLife

User avatar
rowett
Moderator
Posts: 3776
Joined: January 31st, 2013, 2:34 am
Location: UK
Contact:

Re: Golly 3.0b1

Post by rowett » June 30th, 2017, 4:52 am

Andrew wrote:Yep, I wasn't too sure what to do about some of those comments. The .mcl files were included to show that Golly can read MCell files, but I should probably convert them to .rle with updated comments.
Yes please do! A future build of LifeViewer may support LTL rules but it won't support .mcl format files.

Naszvadi
Posts: 1244
Joined: May 7th, 2016, 8:53 am
Contact:

Re: Golly 3.0b1

Post by Naszvadi » June 30th, 2017, 7:14 am

Please provide OSX panther/tiger/leopard powerpc versions of beta builds! I am a volunteer for testing on these platforms.

Thanks in advance!

User avatar
Andrew
Moderator
Posts: 919
Joined: June 2nd, 2009, 2:08 am
Location: Melbourne, Australia
Contact:

Re: Golly 3.0b1

Post by Andrew » June 30th, 2017, 8:31 am

Naszvadi wrote:Please provide OSX panther/tiger/leopard powerpc versions of beta builds!
Sorry, but 10.6 is the oldest Mac OS I can support.
Use Glu to explore CA rules on non-periodic tilings: DominoLife and HatLife

bprentice
Posts: 920
Joined: September 10th, 2009, 6:20 pm
Location: Coos Bay, Oregon

Re: Golly 3.0b1

Post by bprentice » June 30th, 2017, 3:26 pm

oscar.py doesn't report this knight ship correctly:

Code: Select all

x = 11, y = 19, rule = R5,C4,M0,S83..98,B10..108,NN:T1000,1000
$4.C$5.CB$5.2CBA$5.2C2BA$5.2C2B2A$5.2C2B2A$5.2C2B2A$5.2C2B2A$4.3C2B2A
$4.2C3B2A$3.3C2B3A$2.3C3B2A$.3C3B3A$2.C3B3A$4.B3A$6.A!
I am running the Mac OS 10.6+ version of Golly 3.0b1.

Brian Prentice

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

Re: Golly 3.0b1

Post by dvgrn » June 30th, 2017, 3:30 pm

bprentice wrote:oscar.py doesn't report this knight ship correctly...
Heh, that's because when oscar.py was written, faster-than-light travel was impossible:

Code: Select all

    # we found a moving oscillator
    if period == 1:
        g.show("Spaceship detected (speed = c)")
How times have changed, all of a sudden. Looks like a fairly simple fix.

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

Re: Golly 3.0b1

Post by dvgrn » June 30th, 2017, 5:24 pm

Copying in a useful question from another thread:
gameoflifeboy wrote:It seems that MAP patterns run upside-down and backwards when run in HashLife instead of QuickLife. Is this a known bug?
... "upside down and backwards" meaning that in Hashlife the neighborhoods are all reflected across the X axis, from the neighborhoods used in QuickLife. A simple example:

Code: Select all

x = 22, y = 3, rule = MAPERYXfhZofugWaH7oaIDogBZofuhogOiAaIDogIAAgAAWaH7oaIDogGiA6ICAAIAAaIDogIAAgAAAAAAAAAAAAA
2o18b2o$bo18bo$b2o16b2o!
#C [[ AUTOFIT ]]
In the Hashlife algo, the right-hand polyplet survives instead of the left-hand one, and it moves SW instead of NW.

An even simpler example:

Code: Select all

#C Minimal anisotropic rule where the neighbor to the northeast (only)
#C   triggers a birth, so patterns appear to move southwest.
#C Just the 64 bit is ON in the MAP bitstring
#C   -- see http://www.conwaylife.com/wiki/Rule_integer
#C 00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
x = 34, y = 22, rule = MAPAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
o9bo9bo9bo$bo9bo9bo$2bo9bo$3bo$4bo15bo$5bo13bo$6bo11bo5bo$7bo9bo5bo$8b
o7bo5bo4bo$9bo5bo5bo4bo$o13bo5bo4bo4bo$13bo15bo$33bo2$5bo8bo$4b3o$3b5o
$4b3o12b2o$5bo13b2o$27b3o$o9bo16b3o$27b3o!
The algorithm defaults to Quicklife when this pattern is opened, and the dots move southwest like they're supposed to. But if you switch to Hashlife the dots start moving northwest.

User avatar
rowett
Moderator
Posts: 3776
Joined: January 31st, 2013, 2:34 am
Location: UK
Contact:

Re: Golly 3.0b1

Post by rowett » June 30th, 2017, 8:59 pm

dvgrn wrote:Copying in a useful question from another thread:
gameoflifeboy wrote:It seems that MAP patterns run upside-down and backwards when run in HashLife instead of QuickLife. Is this a known bug?
Thanks for reporting! This has been fixed.

User avatar
Andrew
Moderator
Posts: 919
Joined: June 2nd, 2009, 2:08 am
Location: Melbourne, Australia
Contact:

Re: Golly 3.0b1

Post by Andrew » June 30th, 2017, 11:59 pm

bprentice wrote:oscar.py doesn't report this knight ship correctly:
Thanks -- I've now fixed this.

Here is the fixed oscar.lua:

Code: Select all

-- Oscar is an OSCillation AnalyzeR for use with Golly.
-- Author: Andrew Trevorrow (andrew@trevorrow.com), Mar 2016.
-- 
-- This script uses Gabriel Nivasch's "keep minima" algorithm.
-- For each generation, calculate a hash value for the pattern.  Keep all of
-- the record-breaking minimal hashes in a list, with the oldest first.
-- For example, after 5 generations the saved hash values might be:
-- 
--   8 12 16 24 25,
-- 
-- If the next hash goes down to 13 then the list can be shortened:
-- 
--   8 12 13.
-- 
-- If the current hash matches one of the saved hashes, it is highly likely
-- the pattern is oscillating.  By keeping a corresponding list of generation
-- counts we can calculate the period.  We also keep lists of population
-- counts and bounding boxes to reduce the chance of spurious oscillator
-- detection due to hash collisions.  The bounding box info also allows us
-- to detect moving oscillators (spaceships/knightships).

local g = golly()

-- initialize lists
local hashlist = {}     -- for pattern hash values
local genlist = {}      -- corresponding generation counts
local poplist = {}      -- corresponding population counts
local boxlist = {}      -- corresponding bounding boxes

-- check if outer-totalistic rule has B0 but not S8
local r = g.getrule()
r = string.match(r, "^(.+):") or r
local hasB0notS8 = r:find("B0") == 1 and r:find("/") > 1 and r:sub(-1,-1) ~= "8"

----------------------------------------------------------------------

local function show_spaceship_speed(period, deltax, deltay)
    -- we found a moving oscillator
    if deltax == deltay or deltax == 0 or deltay == 0 then
        local speed = ""
        if deltax == 0 or deltay == 0 then
            -- orthogonal spaceship
            if deltax > 1 or deltay > 1 then
                speed = speed..(deltax + deltay)
            end
        else
            -- diagonal spaceship (deltax == deltay)
            if deltax > 1 then
                speed = speed..deltax
            end
        end
        if period == 1 then
            g.show("Spaceship detected (speed = "..speed.."c)")
        else
            g.show("Spaceship detected (speed = "..speed.."c/"..period..")")
        end
    else
        -- deltax != deltay and both > 0
        local speed = deltay..","..deltax
        if period == 1 then
            g.show("Knightship detected (speed = "..speed.."c)")
        else
            g.show("Knightship detected (speed = "..speed.."c/"..period..")")
        end
    end
end

----------------------------------------------------------------------

local function oscillating()
    -- return true if the pattern is empty, stable or oscillating
    
    -- first get current pattern's bounding box
    local pbox = g.getrect()
    if #pbox == 0 then
        g.show("The pattern is empty.")
        return true
    end
    
    local h = g.hash(pbox)
    
    -- determine where to insert h into hashlist
    local pos = 1
    local listlen = #hashlist
    while pos <= listlen do
        if h > hashlist[pos] then
            pos = pos + 1
        elseif h < hashlist[pos] then
            -- shorten lists and append info below
            for i = 1, listlen - pos + 1 do
                table.remove(hashlist)
                table.remove(genlist)
                table.remove(poplist)
                table.remove(boxlist)
            end
            break
        else
            -- h == hashlist[pos] so pattern is probably oscillating, but just in
            -- case this is a hash collision we also compare pop count and box size
            local rect = boxlist[pos]
            if tonumber(g.getpop()) == poplist[pos] and pbox[3] == rect[3] and pbox[4] == rect[4] then
                local period = tonumber(g.getgen()) - genlist[pos]
                
                if hasB0notS8 and (period % 2) > 0 and
                   pbox[1] == rect[1] and pbox[2] == rect[2] and
                   pbox[3] == rect[3] and pbox[4] == rect[4] then
                    -- ignore this hash value because B0-and-not-S8 rules are
                    -- emulated by using different rules for odd and even gens,
                    -- so it's possible to have identical patterns at gen G and
                    -- gen G+p if p is odd
                    return false
                end
                
                if pbox[1] == rect[1] and pbox[2] == rect[2] and
                   pbox[3] == rect[3] and pbox[4] == rect[4] then
                    -- pattern hasn't moved
                    if period == 1 then
                        g.show("The pattern is stable.")
                    else
                        g.show("Oscillator detected (period = "..period..")")
                    end
                else
                    local deltax = math.abs(rect[1] - pbox[1])
                    local deltay = math.abs(rect[2] - pbox[2])
                    show_spaceship_speed(period, deltax, deltay)
                end
                return true
            else
                -- look at next matching hash value or insert if no more
                pos = pos + 1
            end
        end
    end
    
    -- store hash/gen/pop/box info at same position in various lists
    table.insert(hashlist, pos, h)
    table.insert(genlist, pos, tonumber(g.getgen()))
    table.insert(poplist, pos, tonumber(g.getpop()))
    table.insert(boxlist, pos, pbox)
    
    return false
end

----------------------------------------------------------------------

local function fit_if_not_visible()
    -- fit pattern in viewport if not empty and not completely visible
    local r = g.getrect()
    if #r > 0 and not g.visrect(r) then g.fit() end
end

----------------------------------------------------------------------

g.show("Checking for oscillation... (hit escape to abort)")

local oldsecs = os.clock()
while not oscillating() do
    g.run(1)
    local newsecs = os.clock()
    if newsecs - oldsecs >= 1.0 then   -- show pattern every second
        oldsecs = newsecs
        fit_if_not_visible()
        g.update()
    end
end
fit_if_not_visible()
And for all you dinosaurs still using Python, here's the fixed oscar.py:

Code: Select all

# Oscar is an OSCillation AnalyzeR for use with Golly.
# Author: Andrew Trevorrow (andrew@trevorrow.com), March 2006.
# Modified to handle B0-and-not-S8 rules, August 2009.

# This script uses Gabriel Nivasch's "keep minima" algorithm.
# For each generation, calculate a hash value for the pattern.  Keep all of
# the record-breaking minimal hashes in a list, with the oldest first.
# For example, after 5 generations the saved hash values might be:
#
#   8 12 16 24 25,
#
# If the next hash goes down to 13 then the list can be shortened:
#
#   8 12 13.
#
# When the current hash matches one of the saved hashes, it is highly likely
# the pattern is oscillating.  By keeping a corresponding list of generation
# counts we can calculate the period.  We also keep lists of population
# counts and bounding boxes; they are used to reduce the chance of spurious
# oscillator detection due to hash collisions.  The bounding box info also
# allows us to detect moving oscillators (spaceships/knightships).

import golly as g
from glife import rect, pattern
from time import time

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

# initialize lists
hashlist = []        # for pattern hash values
genlist = []         # corresponding generation counts
poplist = []         # corresponding population counts
boxlist = []         # corresponding bounding boxes

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

def show_spaceship_speed(period, deltax, deltay):
    # we found a moving oscillator
    if (deltax == deltay) or (deltax == 0) or (deltay == 0):
        speed = ""
        if (deltax == 0) or (deltay == 0):
            # orthogonal spaceship
            if (deltax > 1) or (deltay > 1):
                speed += str(deltax + deltay)
        else:
            # diagonal spaceship (deltax == deltay)
            if deltax > 1:
                speed += str(deltax)
        if period == 1:
            g.show("Spaceship detected (speed = " + speed + "c)")
        else:
            g.show("Spaceship detected (speed = " + speed + "c/" +str(period) + ")")
    else:
        # deltax != deltay and both > 0
        speed = str(deltay) + "," + str(deltax)
        if period == 1:
            g.show("Knightship detected (speed = " + speed + "c)")
        else:
            g.show("Knightship detected (speed = " + speed + "c/" + str(period) + ")")

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

def oscillating():
    # return True if the pattern is empty, stable or oscillating

    # first get current pattern's bounding box
    prect = g.getrect()
    pbox = rect(prect)
    if pbox.empty:
        g.show("The pattern is empty.")
        return True

    # get current pattern and create hash of "normalized" version -- ie. shift
    # its top left corner to 0,0 -- so we can detect spaceships and knightships
    ## currpatt = pattern( g.getcells(prect) )
    ## h = hash( tuple( currpatt(-pbox.left, -pbox.top) ) )

    # use Golly's hash command (3 times faster than above code)
    h = g.hash(prect)

    # check if outer-totalistic rule has B0 but not S8
    rule = g.getrule().split(":")[0]
    hasB0notS8 = rule.startswith("B0") and (rule.find("/") > 1) and not rule.endswith("8")

    # determine where to insert h into hashlist
    pos = 0
    listlen = len(hashlist)
    while pos < listlen:
        if h > hashlist[pos]:
            pos += 1
        elif h < hashlist[pos]:
            # shorten lists and append info below
            del hashlist[pos : listlen]
            del genlist[pos : listlen]
            del poplist[pos : listlen]
            del boxlist[pos : listlen]
            break
        else:
            # h == hashlist[pos] so pattern is probably oscillating, but just in
            # case this is a hash collision we also compare pop count and box size
            if (int(g.getpop()) == poplist[pos]) and \
               (pbox.wd == boxlist[pos].wd) and \
               (pbox.ht == boxlist[pos].ht):
                period = int(g.getgen()) - genlist[pos]

                if hasB0notS8 and (period % 2 > 0) and (pbox == boxlist[pos]):
                    # ignore this hash value because B0-and-not-S8 rules are
                    # emulated by using different rules for odd and even gens,
                    # so it's possible to have identical patterns at gen G and
                    # gen G+p if p is odd
                    return False

                if pbox == boxlist[pos]:
                    # pattern hasn't moved
                    if period == 1:
                        g.show("The pattern is stable.")
                    else:
                        g.show("Oscillator detected (period = " + str(period) + ")")
                else:
                    deltax = abs(boxlist[pos].x - pbox.x)
                    deltay = abs(boxlist[pos].y - pbox.y)
                    show_spaceship_speed(period, deltax, deltay)
                return True
            else:
                # look at next matching hash value or insert if no more
                pos += 1

    # store hash/gen/pop/box info at same position in various lists
    hashlist.insert(pos, h)
    genlist.insert(pos, int(g.getgen()))
    poplist.insert(pos, int(g.getpop()))
    boxlist.insert(pos, pbox)

    return False

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

def fit_if_not_visible():
    # fit pattern in viewport if not empty and not completely visible
    r = rect(g.getrect())
    if (not r.empty) and (not r.visible()): g.fit()

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

g.show("Checking for oscillation... (hit escape to abort)")

oldsecs = time()
while not oscillating():
    g.run(1)
    newsecs = time()
    if newsecs - oldsecs >= 1.0:     # show pattern every second
        oldsecs = newsecs
        fit_if_not_visible()
        g.update()

fit_if_not_visible()
Let me know if there are still any problems with those scripts.
Use Glu to explore CA rules on non-periodic tilings: DominoLife and HatLife

bprentice
Posts: 920
Joined: September 10th, 2009, 6:20 pm
Location: Coos Bay, Oregon

Re: Golly 3.0b1

Post by bprentice » July 1st, 2017, 4:57 pm

Please consider adding Cross, Saltire and Star neighborhoods to the Square and Diamond neighborhoods that are currently implemented in your 'Larger than Life' family of rules.

Brian Prentice

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

Re: Golly 3.0b1

Post by dvgrn » July 1st, 2017, 5:33 pm

bprentice wrote:Please consider adding Cross, Saltire and Star neighborhoods to the Square and Diamond neighborhoods that are currently implemented in your 'Larger than Life' family of rules.
Cross is the orthogonal "+" pattern that Andrew originally implemented, correct? And Saltire would be a diagonal "x", and Star would be Cross and Saltire superimposed? Is there any prior art for Larger than Life patterns with these extended neighborhoods?

If so, is there any standard for the "N" suffix used in the rule strng? "NN" for von Neumann, "NM" for Moore -- so presumably "NC" for cross, but the other two words both start with S. Maybe "NS" for Star, and then "NX" for the saltire?

bprentice
Posts: 920
Joined: September 10th, 2009, 6:20 pm
Location: Coos Bay, Oregon

Re: Golly 3.0b1

Post by bprentice » July 1st, 2017, 6:56 pm

dvgrn wrote:Cross is the orthogonal "+" pattern that Andrew originally implemented, correct? And Saltire would be a diagonal "x", and Star would be Cross and Saltire superimposed?
Yes.
dvgrn wrote:Is there any prior art for Larger than Life patterns with these extended neighborhoods?
Not that I am aware of. Square Cell implements all five neighborhood types. I have not found many interesting rules using the Cross, Saltire or Star neighborhoods, but finding interesting rules using the Square and Diamond neighborhoods is also difficult. Since we have just started experimenting with 'Larger than Life' using Golly, I was curious to see what the active members of the Forum find. For example in just a few hours of the 3.0b1 release of Golly drc posted this beauty.

viewtopic.php?f=11&t=2933#p45539

Some of the pictures posted here:

viewtopic.php?f=12&t=2853#p43283

use the Cross, Saltire or Star neighborhoods and each of them exhibits unique characteristics.
dvgrn wrote:...is there any standard for the "N" suffix used in the rule strng? "NN" for von Neumann, "NM" for Moore -- so presumably "NC" for cross, but the other two words both start with S. Maybe "NS" for Star, and then "NX" for the saltire?
No, your suggestion would work.

Brian Prentice

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

Re: Golly 3.0b1

Post by drc » July 1st, 2017, 7:40 pm

What if we have rule tables with custom neighbourhoods? For example if I wanted this neighbourhood, I could specify it per:

Code: Select all

@RULE JackLife
Life simulated using a 16-cell neighbourhood seen below.
@NEIGHBORHOOD
X.X.X
.XXX
XXOXX
.XXX
X.X.X
@TABLE
n_states:2
symmetries: rotate4reflect
neighborhood:custom
X=Active cell
.=Passive cell
O=Center cell

Then, the transitions would be specified by going through each cell in each row, left-right, then advancing to the next row. Or maybe it could be customly specified like so?:

Code: Select all

@NEIGHBORHOOD
1.2.3
.456.
78O9A
.BCD.
E.F.G
That would have the downside of only allowing 36 neighbours unless symbols get involved. I dunno, maybe they could be optional.

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

Re: Golly 3.0b1

Post by AforAmpere » July 1st, 2017, 8:18 pm

I wan't to have a format for LtL rule tables, even just to do neighborhood 2, because then I can do stuff like create a true LogicLand ruletable, because the actual thing uses neighborhood 2 for a crossover. Some other things only possible in neighborhood 2 rules would be able to be done, and it would be really cool.

The neighborhood 2 table could be like this:

Code: Select all

23 24  9 10 11
22 8   1  2 12
21 7      3 13
20 6   5  4 14
19 18 17 16 15
And obviously after neighborhood 2, it would become even more insanely complicated, but it would really be able to show the variety of these rules, and just neighborhood 2 has some cool applications.
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.

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

Re: Golly 3.0b1

Post by Saka » July 1st, 2017, 8:21 pm

drc wrote:What if we have rule tables with custom neighbourhoods? For example if I wanted this neighbourhood, I could specify it per:

Code: Select all

@RULE JackLife
Life simulated using a 16-cell neighbourhood seen below.
@NEIGHBORHOOD
X.X.X
.XXX
XXOXX
.XXX
X.X.X
@TABLE
n_states:2
symmetries: rotate4reflect
neighborhood:custom
X=Active cell
.=Passive cell
O=Center cell

Then, the transitions would be specified by going through each cell in each row, left-right, then advancing to the next row. Or maybe it could be customly specified like so?:

Code: Select all

@NEIGHBORHOOD
1.2.3
.456.
78O9A
.BCD.
E.F.G
That would have the downside of only allowing 36 neighbours unless symbols get involved. I dunno, maybe they could be optional.
I have designed some neighborhood formats. Just have to find them...

User avatar
Andrew
Moderator
Posts: 919
Joined: June 2nd, 2009, 2:08 am
Location: Melbourne, Australia
Contact:

Re: Golly 3.0b1

Post by Andrew » July 1st, 2017, 10:13 pm

bprentice wrote:Please consider adding Cross, Saltire and Star neighborhoods to the Square and Diamond neighborhoods that are currently implemented in your 'Larger than Life' family of rules.
I'd have to say I'm unlikely to write the necessary code. Any chance you'd be willing to write it? Note that you could write and test it by building bgolly rather than Golly, so no need to install and build wxWidgets.

If you download Golly's current git repository from sourceforge the only changes needed are to ltlalgo.cpp in the gollybase folder. In that file we currently have these routines:

slow_torus_Moore
slow_torus_Neumann
slow_plane_Moore
slow_plane_Neumann
fast_Moore
fast_Neumann

So these new routines will be needed:

slow_torus_Cross
slow_torus_Saltire
slow_torus_Star
slow_plane_Cross
slow_plane_Saltire
slow_plane_Star
fast_Cross
fast_Saltire
fast_Star

The slow* routines are used to process rectangles near the grid edges. The fast* routines are used to process inner rectangles where no edge checking is needed.

Building bgolly is easy. Open Terminal.app, cd to golly/gui-wx, then run "make -f makefile-mac bgolly".

Email me if you need more details.
Use Glu to explore CA rules on non-periodic tilings: DominoLife and HatLife

bprentice
Posts: 920
Joined: September 10th, 2009, 6:20 pm
Location: Coos Bay, Oregon

Re: Golly 3.0b1

Post by bprentice » July 1st, 2017, 11:13 pm

Andrew,

Here is the Square Cell step code for all five neighborhoods:

Code: Select all

  public int step(int row, int column, byte[][] cells, int rows, int columns)
  {
    int cell = cells[row][column];
    int neighborCount = 0;
    if (neighborhoodType == SQUARE)
    {
      if (((row - neighborhoodSize) >= 0) && ((row + neighborhoodSize) < rows) &&
          ((column - neighborhoodSize) >= 0) && ((column + neighborhoodSize) < columns))
      {
        for (int r = row - neighborhoodSize; r <= row + neighborhoodSize; r++)
          for (int c = column - neighborhoodSize; c <= column + neighborhoodSize; c++)
            if (cells[r][c] == 1)
              neighborCount++;
      }
      else
      {
        for (int r = row - neighborhoodSize; r <= row + neighborhoodSize; r++)
          for (int c = column - neighborhoodSize; c <= column + neighborhoodSize; c++)
            if (cells[(r + rows) % rows][(c + columns) % columns] == 1)
              neighborCount++;
      }
      if ((! includeCenter) && (cell == 1))
        neighborCount--;
    }
    else if (neighborhoodType == CROSS)
    {
      for (int i = 1; i <= neighborhoodSize; i++)
      {
        if (cells[(row + rows) % rows][(column - i + columns) % columns] == 1)
          neighborCount++;
        if (cells[(row + rows) % rows][(column + i + columns) % columns] == 1)
          neighborCount++;
        if (cells[(row - i + rows) % rows][(column + columns) % columns] == 1)
          neighborCount++;
        if (cells[(row + i + rows) % rows][(column + columns) % columns] == 1)
          neighborCount++;
      }
      if (includeCenter && (cell == 1))
        neighborCount++;
    }
    else if (neighborhoodType == SALTIRE)
    {
      for (int i = 1; i <= neighborhoodSize; i++)
      {
        if (cells[(row - i + rows) % rows][(column - i + columns) % columns] == 1)
          neighborCount++;
        if (cells[(row - i + rows) % rows][(column + i + columns) % columns] == 1)
          neighborCount++;
        if (cells[(row + i + rows) % rows][(column - i + columns) % columns] == 1)
          neighborCount++;
        if (cells[(row + i + rows) % rows][(column + i + columns) % columns] == 1)
          neighborCount++;
      }
      if (includeCenter && (cell == 1))
        neighborCount++;
    }
    else if (neighborhoodType == STAR)
    {
      for (int i = 1; i <= neighborhoodSize; i++)
      {
        if (cells[(row + rows) % rows][(column - i + columns) % columns] == 1)
          neighborCount++;
        if (cells[(row + rows) % rows][(column + i + columns) % columns] == 1)
          neighborCount++;
        if (cells[(row - i + rows) % rows][(column + columns) % columns] == 1)
          neighborCount++;
        if (cells[(row + i + rows) % rows][(column + columns) % columns] == 1)
          neighborCount++;
        if (cells[(row - i + rows) % rows][(column - i + columns) % columns] == 1)
          neighborCount++;
        if (cells[(row - i + rows) % rows][(column + i + columns) % columns] == 1)
          neighborCount++;
        if (cells[(row + i + rows) % rows][(column - i + columns) % columns] == 1)
          neighborCount++;
        if (cells[(row + i + rows) % rows][(column + i + columns) % columns] == 1)
          neighborCount++;
      }
      if (includeCenter && (cell == 1))
        neighborCount++;
    }
    else if (neighborhoodType == DIAMOND)
    {
      int columnSize = 0;
      if (((row - neighborhoodSize) >= 0) && ((row + neighborhoodSize) < rows) &&
          ((column - neighborhoodSize) >= 0) && ((column + neighborhoodSize) < columns))
      {
        for (int r = row - neighborhoodSize; r <= row + neighborhoodSize; r++)
        {
          for (int c = column - columnSize; c <= column + columnSize; c++)
            if (cells[r][c] == 1)
              neighborCount++;
          if (r < row)
            columnSize++;
          else
            columnSize--;
        }
      }
      else
      {
        for (int r = row - neighborhoodSize; r <= row + neighborhoodSize; r++)
        {
          for (int c = column - columnSize; c <= column + columnSize; c++)
            if (cells[(r + rows) % rows][(c + columns) % columns] == 1)
              neighborCount++;
          if (r < row)
            columnSize++;
          else
            columnSize--;
        }
      }
      if ((! includeCenter) && (cell == 1))
        neighborCount--;
    }
    if (cell == 0)
    {
      if ((neighborCount >= birthMin) && (neighborCount <= birthMax))
        return 1;
      else
        return 0;
    }
    else if (cell == 1)
    {
      if ((neighborCount >= survivalMin) && (neighborCount <= survivalMax))
        return 1;
    }
    if (noStates > 2)
      return (cell + 1) % noStates;
    else
      return 0;
  }
Notice that it is 130 lines, 56 lines of which deal with the CROSS, SALTIRE and STAR neighborhoods.

If this is too much trouble then so be it. My priority is still better rule management in Golly. See the following post:

viewtopic.php?f=4&t=1669&p=20087#p18485

Brian Prentice

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

Re: Golly 3.0b1

Post by Saka » July 2nd, 2017, 12:02 am

Saka wrote: I have designed some neighborhood formats. Just have to find them...
Here:

Code: Select all

@NEIGHBORHOOD NeighborhoodName
#This will use the Moore+2 neighborhood
#All neighborhoods created will have "none" or "permute" symmetry only
#Specify the cells using 0 for out-of-neighborhood cell or 1 for inside-of-neighborhood cell
#Use a "o" for the "origin" cell

@NEIGHBORS
x:5 #Width
y:5 #Height
11111
11111
11o11
11111
11111

@ORDER
#Optional, this is for the order when creating rule tables
#Default is c, NNWW, NNW, NN... c' (AKA. top left to bottom right)
#o for origin
0,1,2,3,4
5,6,7,8,9
10,11,o,12,13
14,15,16,17,18
19,20,21,22,23
Once this neighborhood is installed you can use it in rule tables.

User avatar
Andrew
Moderator
Posts: 919
Joined: June 2nd, 2009, 2:08 am
Location: Melbourne, Australia
Contact:

Re: Golly 3.0b1

Post by Andrew » July 2nd, 2017, 12:10 am

bprentice wrote:Here is the Square Cell step code for all five neighborhoods:
That's the update code for *one* cell in a grid (and only a toroidal grid -- I don't see any code to handle a planar grid). That might be good enough for a simple Java app and small grid sizes but it's nowhere near fast enough for the large grid sizes we want to support in Golly.
If this is too much trouble then so be it.
Writing efficient code for those neighborhoods is quite a bit of work. It would be nice to have some help.
My priority is still better rule management in Golly. See the following post:
I've nothing to add to the reply I gave there.
Use Glu to explore CA rules on non-periodic tilings: DominoLife and HatLife

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

Re: Golly 3.0b1

Post by dvgrn » July 2nd, 2017, 11:41 am

Andrew wrote:
bprentice wrote:My priority is still better rule management in Golly. See the following post:
I've nothing to add to the reply I gave there.
One idea I thought of that seems worth adding:

@Brian, with your interests and methods I think you must be managing an order of magnitude more rules than any other CA experimenter, by this time! But that's not a reason for changes to Golly source code -- since nobody else seems to need this feature, you just need one additional helper script to customize your copy of Golly.

A script with just a dozen lines or so could empty an AllRules folder, then copy all the rule files in your subdirectory structure into it. That script could even be arranged to run when Golly starts, or assign a shortcut key to do a rule refresh. Then you'd do all your rule management in your subdirectories, as you do now... but Golly's Rules folder setting would always point to AllRules, and every rule would always be available to Golly with no fiddling around with settings.

That wouldn't work if you have competing rules with the same name in different subdirectories... but it seems like that would be a problem worth fixing anyway.

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

Re: Golly 3.0b1

Post by drc » July 2nd, 2017, 1:43 pm

Alright, I have a new question. Is it possible for, when pasting into Golly, LifeHistory rules (or any ###History rule although that's a different request considering Golly doesn't support them.) to be converted to Life patterns if the requirements aren't met for a rule change? (If the checkbox saying 'Change rule when empty universe' isn't checked, or when there's already cells on the board.) Then it would convert all odd-state cells to alive cells, and all even-state cells to dead cells.

(Still, the @NEIGHBORHOOD thingy I suggested would be pretty cool.)

Post Reply