x = 17, y = 10, rule = B3/S23
b2ob2obo5b2o$11b4obo$2bob3o2bo2b3o$bo3b2o4b2o$o2bo2bob2o3b4o$bob2obo5b
o2b2o$2b2o4bobo2b3o$bo3b5ob2obobo$2bo5bob2o$4bob2o2bobobo!
gameoflifeboy wrote:Having never downloaded Golly 2.9 I don't know how much is really new
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.
Saka wrote:Why does LTL have to be on a torus?
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.
Naszvadi wrote:Please provide OSX panther/tiger/leopard powerpc versions of beta builds!
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!
bprentice wrote:oscar.py doesn't report this knight ship correctly...
# we found a moving oscillator
if period == 1:
g.show("Spaceship detected (speed = c)")
gameoflifeboy wrote:It seems that MAP patterns run upside-down and backwards when run in HashLife instead of QuickLife. Is this a known bug?
x = 22, y = 3, rule = MAPERYXfhZofugWaH7oaIDogBZofuhogOiAaIDogIAAgAAWaH7oaIDogGiA6ICAAIAAaIDogIAAgAAAAAAAAAAAAA
2o18b2o$bo18bo$b2o16b2o!
#C [[ AUTOFIT ]]
#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!
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?
bprentice wrote:oscar.py doesn't report this knight ship correctly:
-- 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()
# 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()
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.
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?
dvgrn wrote:Is there any prior art for Larger than Life patterns with these extended neighborhoods?
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?
@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
@NEIGHBORHOOD
1.2.3
.456.
78O9A
.BCD.
E.F.G
23 24 9 10 11
22 8 1 2 12
21 7 3 13
20 6 5 4 14
19 18 17 16 15
I have designed some neighborhood formats. Just have to find them...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.
x = 17, y = 10, rule = B3/S23
b2ob2obo5b2o$11b4obo$2bob3o2bo2b3o$bo3b2o4b2o$o2bo2bob2o3b4o$bob2obo5b
o2b2o$2b2o4bobo2b3o$bo3b5ob2obobo$2bo5bob2o$4bob2o2bobobo!
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.
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;
}
Saka wrote: I have designed some neighborhood formats. Just have to find them...
@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
x = 17, y = 10, rule = B3/S23
b2ob2obo5b2o$11b4obo$2bob3o2bo2b3o$bo3b2o4b2o$o2bo2bob2o3b4o$bob2obo5b
o2b2o$2b2o4bobo2b3o$bo3b5ob2obobo$2bo5bob2o$4bob2o2bobobo!
bprentice wrote:Here is the Square Cell step code for all five neighborhoods:
If this is too much trouble then so be it.
My priority is still better rule management in Golly. See the following post:
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.
Users browsing this forum: Electro_blob and 2 guests