cvojan wrote:There is a script included with it called "oscar" that can find a spaceship's or oscillator's period, so you don't have to do it yourself)
My version of oscar.lua:
Code: Select all
-- Oscar is an OSCillation AnalyzeR for use with Golly.
--
-- 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()
min = 2147483648
-- initialize lists
local hashlist = {} -- for pattern hash values
local genlist = {} -- corresponding generation counts
local poplist = {} -- corresponding population counts
local boxlist = {} -- corresponding bounding boxes
local t = {} -- corresponding not removing list of pops
local population = tonumber(g.getpop())
-- 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, smallestphase)
-- we found a moving oscillator
if deltax == deltay or deltax == 0 or deltay == 0 then
local speed = ""
local speed2 = ""
if deltax == 0 or deltay == 0 then
-- orthogonal spaceship
speed2 = speed2..(deltax + deltay)
if speed2 == "" then
speed2 = 1
end
else
-- diagonal spaceship (deltax == deltay)
speed2 = deltax
if speed2 == "" then
speed2 = 1
end
end
if deltax == deltay then
if period == 1 then
if smallestphase < 15 then
g.show("Diagonal spaceship detected (speed = (1, 1)/1, systematic name "..smallestphase.."P"..period.."H"..speed2.."V"..speed2..")")
else
g.show("Diagonal spaceship detected (speed = (1, 1)/1, systematic name "..smallestphase.."P"..period.."H"..speed2.."V"..speed2..")")
end
else
if smallestphase < 15 then
g.show("Diagonal spaceship detected (speed = ("..speed2..", "..speed2..")/"..period..", systematic name "..smallestphase.."P"..period.."H"..speed2.."V"..speed2..")")
else
g.show("Diagonal spaceship detected (speed = ("..speed2..", "..speed2..")/"..period..", systematic name "..smallestphase.."P"..period.."H"..speed2.."V"..speed2..")")
end
end
else
if period == 1 then
if smallestphase < 15 then
g.show("Orthogonal spaceship detected (speed = (1, 0)/1, systematic name "..smallestphase.."P"..period.."H"..speed2.."V0)")
else
g.show("Orthogonal spaceship detected (speed = (1, 0)/1, systematic name "..smallestphase.."P"..period.."H"..speed2.."V0)")
end
else
if smallestphase < 15 then
g.show("Orthogonal spaceship detected (speed = ("..speed2..", 0)/"..period..", systematic name "..smallestphase.."P"..period.."H"..speed2.."V0)")
else
g.show("Orthogonal spaceship detected (speed = ("..speed2..", 0)/"..period..", systematic name "..smallestphase.."P"..period.."H"..speed2.."V0)")
end
end
end
else
-- deltax != deltay and both > 0
local speed = deltay..", "..deltax
if deltay > deltax then
speed2 = deltay
speed3 = deltax
else
speed2 = deltax
speed3 = deltay
end
if 1 == 1 then
g.show("Knightship detected (speed = ("..speed..")/"..period..", systematic name "..smallestphase.."P"..period.."H"..speed2.."V"..speed3..")")
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("All cells are dead.")
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]
local population3
if tonumber(g.getpop()) == poplist[pos] and pbox[3] == rect[3] and pbox[4] == rect[4] then
local period = tonumber(g.getgen()) - genlist[pos]
local population3 = tonumber(g.getpop())
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
population2 = tonumber(g.getpop())
g.show("Still life detected (cells = "..population2..")")
else
g.show("Oscillator detected (period = "..period..", systematic name "..smallestphase.."P"..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, smallestphase)
return true
end
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(t, pos, tonumber(g.getpop()))
table.insert(boxlist, pos, pbox)
table.sort(t)
smallestphase = t[1]
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()
Difference:
RLE:
Code: Select all
x = 4, y = 4, rule = B3/S23
2b2o$3bo$3o$o!
PATTERN: Eater 1
ORIGINAL OSCAR OUTPUTS: The pattern is stable.
MY OSCAR OUTPUTS: Still life detected (cells = 7)
RLE:
Code: Select all
x = 15, y = 20, rule = B3/S23
4bo$4obo$3obobo$5bobo$6bo$5b2o$5b2o3bo$5b2o2bobob2o$13b2o3$7bo2bo$7bo$
6bo4bo$5bobo2b2o$3b2obo3$3bo2bo$5b2o!
#C [[ THEME 6 GRID GRIDMAJOR 0 SUPPRESS THUMBLAUNCH ]]
#C [[ AUTOSTART ]]
PATTERN: P18 bi-block hassler
ORIGINAL OSCAR OUTPUTS: Oscillator detected (period = 18)
MY OSCAR OUTPUTS: Oscillator detected (period = 8, systematic name 43P18)
RLE:
Code: Select all
x = 53, y = 127, rule = B3/S23
4b2o$4bo2bo$4bo3bo$6b3o$2b2o6b4o$2bob2o4b4o$bo4bo6b3o$2b4o4b2o3bo$o9b
2o$bo3bo$6b3o2b2o2bo$2b2o7bo4bo$13bob2o$10b2o6bo$11b2ob3obo$10b2o3bo2b
o$10bobo2b2o$10bo2bobobo$10b3o6bo$11bobobo3bo$14b2obobo$11bo6b3o2$11bo
9bo$11bo3bo6bo$12bo5b5o$12b3o$16b2o$13b3o2bo$11bob3obo$10bo3bo2bo$11bo
4b2ob3o$13b4obo4b2o$13bob4o4b2o$19bo$20bo2b2o$20b2o$21b5o$25b2o$19b3o
6bo$20bobo3bobo$19bo3bo3bo$19bo3b2o$18bo6bob3o$19b2o3bo3b2o$20b4o2bo2b
o$22b2o3bo$21bo$21b2obo$20bo$19b5o$19bo4bo$18b3ob3o$18bob5o$18bo$20bo$
16bo4b4o$20b4ob2o$17b3o4bo$24bobo$28bo$24bo2b2o$25b3o$22b2o$21b3o5bo$
24b2o2bobo$21bo2b3obobo$22b2obo2bo$24bobo2b2o$26b2o$22b3o4bo$22b3o4bo$
23b2o3b3o$24b2ob2o$25b2o$25bo2$24b2o3b3o$26bo2b2obo$28bo3b2o$29bo2b2o$
33bobo$30b2o2b2o$33b2o$33bobo$35b2o$33bob2o$33b3o3bo$32b2o4b2o$32b3o$
33bobo$34bobo3b3o$34bo6bob2o$38bo6bo$38bo3b2o$35b2o$39b3o$39b3o$39bo2$
39b3o$39b3o$39b3o$39b2o3bo$43b3o$43b2o2bo$44bo3bo$45bobo$44bo2bo2b3o$
43bo2b2o$42bo4b5o$42bo2bob3o$43bo$45bobo$46b2o$47bo$46b3o2$44b2o$47b3o
$43bo2bo$43bo2bo$43bo5bo$42b2ob2obobo$42b2ob2o3bo$43b2obo$44bob2obo!
PATTERN: Sir Robin with Minstrel 4 (A welded Minstrel 3 and 1)
ORIGINAL OSCAR OUTPUT: Knightship detected (speed = 2,1c/6)
MY OSCAR OUTPUTS: Knightship detected (speed = (2, 1)/6, systematic name 424P6H2V1)