ConwayLife.com - A community for Conway's Game of Life and related cellular automata
Home  •  LifeWiki  •  Forums  •  Download Golly

Script request thread

For scripts to aid with computation or simulation in cellular automata.

Re: Script request thread

Postby Entity Valkyrie » November 8th, 2018, 6:05 am

Can you give me a lua code that can convert rle to apgcode? I need lua, not python because I don't have python.
User avatar
Entity Valkyrie
 
Posts: 247
Joined: November 30th, 2017, 3:30 am

Re: Script request thread

Postby Saka » November 8th, 2018, 6:07 am

Entity Valkyrie wrote:I need lua, not python because I don't have python.

Why dont you install python then?
If you're the person that uploaded to Sakagolue illegally, please PM me.
x = 17, y = 10, rule = B3/S23
b2ob2obo5b2o$11b4obo$2bob3o2bo2b3o$bo3b2o4b2o$o2bo2bob2o3b4o$bob2obo5b
o2b2o$2b2o4bobo2b3o$bo3b5ob2obobo$2bo5bob2o$4bob2o2bobobo!

(Check gen 2)
User avatar
Saka
 
Posts: 2837
Joined: June 19th, 2015, 8:50 pm
Location: In the kingdom of Sultan Hamengkubuwono X

Re: Script request thread

Postby Entity Valkyrie » November 8th, 2018, 11:27 pm

Saka wrote:
Entity Valkyrie wrote:I need lua, not python because I don't have python.

Why dont you install python then?

I did install python 3.7, but it still did't wprk.
User avatar
Entity Valkyrie
 
Posts: 247
Joined: November 30th, 2017, 3:30 am

Re: Script request thread

Postby Ian07 » November 8th, 2018, 11:41 pm

Entity Valkyrie wrote:I did install python 3.7, but it still did't wprk.

If you're on Windows 10, try setting the file path to C:\Windows\SysWOW64\python37.dll when it asks you to locate a .dll file. If that doesn't work, try C:\Windows\System32\python37.dll

With the first one, I got it to work after having the same problem for months.
Ian07
 
Posts: 197
Joined: September 22nd, 2018, 8:48 am

Re: Script request thread

Postby dvgrn » November 9th, 2018, 12:07 am

Entity Valkyrie wrote:
Saka wrote:
Entity Valkyrie wrote:I need lua, not python because I don't have python.

Why dont you install python then?

I did install python 3.7, but it still did't wprk.

Only Python 2.7.x works with Golly. Try installing Python 2.7.15 -- and make sure it's 32-bit if you have 32-bit Golly, or 64-bit if you have 64-bit Golly.

Or if you prefer, work on your programming skills by porting whatever Python scripts you want to Lua -- it would definitely be good to have more people who have had some practice doing that.
User avatar
dvgrn
Moderator
 
Posts: 5557
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI

Re: Script request thread

Postby Ian07 » November 9th, 2018, 12:56 am

dvgrn wrote:Only Python 2.7.x works with Golly. Try installing Python 2.7.15 -- and make sure it's 32-bit if you have 32-bit Golly, or 64-bit if you have 64-bit Golly.

Yeah, forgot about that. Anyway, if it still gives an error, the thing I suggested above should still work - just replace Python37 with Python27.
Ian07
 
Posts: 197
Joined: September 22nd, 2018, 8:48 am

Re: Script request thread

Postby Entity Valkyrie » November 15th, 2018, 5:26 am

Ian07 wrote:
dvgrn wrote:Only Python 2.7.x works with Golly. Try installing Python 2.7.15 -- and make sure it's 32-bit if you have 32-bit Golly, or 64-bit if you have 64-bit Golly.

Yeah, forgot about that. Anyway, if it still gives an error, the thing I suggested above should still work - just replace Python37 with Python27.


I already have python 2.7.15.
User avatar
Entity Valkyrie
 
Posts: 247
Joined: November 30th, 2017, 3:30 am

Re: Script request thread

Postby danny » November 18th, 2018, 8:15 pm

No idea what's wrong with this script:
--This is a preliminary version. If sufficiently interesting behaviours show
--up, it would be nice to get a full simulating algorithm in better-written
--softawre like Golly. Speaking of Golly, make sure you have a version that
--supports Lua, so you can run this script. Stinky.

--TERMS TO KNOW:
--Heat - The number returned when the previous equation is ran on all of the
--       other cells in relation to the given cell (basically what count()
--       does)

local g = golly()
local gp = require "gplus"

local rulesB = {2, 3, 4, 5}
local rulesS = {2, 3, 4, 5}

function count(x1, y1) --determine cell's heat
   local pat
   local total = 0
   if g.getcell(x1, y1) == 1 then --ok i know it's ugly but it saves a lot of processing time than doing a conditional
      g.setcell(x1, y1, 0)
      pat = g.getcells(g.getrect())
      g.setcell(x1, y1, 1)
   else
      pat = g.getcells(g.getrect())
   end
   
   for i = 1, #pat, 2 do
      local x2 = pat[i]
      local y2 = pat[i+1] --ugly
      total = total+1 / ((x2-x1)^2+(y2-y1)^2) --i know i said i was using fourth powers, however the square root and fourth power cancel out leaving just a stray ^2
   end

   return total
end

function ring(r) --basically, it returns a 'outer moore birth ring' of the given size
   local pat = g.getcells(g.getrect())
   local x, y, w, h = table.unpack(r) --there a better way to do this?
   g.select({x-1, y-1, w+2, h+2})
   g.randfill(100)
   g.select({x, y, w, h})
   g.clear(0)
   local ring = g.getcells(g.getrect())
   g.putcells(pat)
   g.clear(1)
   g.select({})
   return ring
end

function step()
   --hoooo boy i hated writing this
   --don't read it if you don't want to get lost
   local pat = g.getcells(g.getrect())
   local rulesBclone = rulesB
   table.sort(rulesBclone)
   local minrulesB = rulesBclone[1] --math.min but with an array
   local lx, ly, lw, lh = table.unpack(g.getrect())
   while true do --this loop determines how far to check for births
      local localmax = 0
      local localring = ring({lx, ly, lw, lh})
      for i = 1, #localring, 2 do
         local localcount = count(localring[i], localring[i+1])
         if localcount > localmax then
            localmax = localcount
         end
      end
      if localmax < minrulesB then
         break
      end
      lx = lx - 1
      ly = ly - 1
      lw = lw + 2
      lh = lh + 2
   end
   --gosh that took me months to make, now onto processing
   g.select({lx, ly, lw, lh})
   g.randfill(100)
   g.putcells(pat, 0, 0, 1, 0, 0, 1, --[[ugh why]] "xor")
   local area = g.getcells(g.getrect())
   g.clear(0)
   g.putcells(pat)
   --NOW LET'S FINALLY PROCESS BIRTH, aka the reason that hellhole of lines above had to be done
   for i = 1, #area, 2 do
      g.setcell(area[i], area[i+1], 0)
      local localcount = count(area[i], area[i+1])
      for j = 1, #rulesB, 2 do
         if localcount >= rulesB[j] and localcount <= rulesB[j+1] then
            g.setcell(area[i], area[i+1], 1)
         end
      end
   end
   --and survival, the easy part
   for i = 1, #pat, 2 do
      g.setcell(pat[i], pat[i+1], 0)
      local localcount = count(pat[i], pat[i+1])
      for j = 1, #rulesS, 2 do
         if localcount >= rulesS[j] and localcount <= rulesS[j+1] then
            g.setcell(pat[i], pat[i+1], 1)
         end
      end
   end
end

while true do
   step()
   g.update()
end


This script is intended to simulate a type of CA-- that is, a CA that takes the euclidean distances from a base cell to every other cell, takes the reciprocal, and brings it to the fourth power, and adds them up, then checks if they're within a certain range, and if so, turns them on. This should be grid-symmetric.

When running a symmetric pattern, it turns asymmetric, and always seems to have the same shape. To the left is a starting pattern, to the right is it after 16 generations:
x = 105, y = 46, rule = B3/S23
o71bobobobobobobob12o2bob3o$o65bobo2bobobobobobobobo12bo4b2o$b2o60bo2b
o2bo12bo4bo2bobobobo2bo4bo$59bob2o2bo5bo4bo16bobobo$56bo2bo4bo3bo3bobo
3bobobobo3bobobo5b2o3b2o$54bobo3bo4bo3bo3bobo9bobo6bo5bo3bo$52bobo3bo
2bo2bobo4bo6bo2bobo7bo6bo5bo$51b2o7bobo2bo3bo3bo6bo4bo2bo5bobo7bo$50b
2o2bo4bo3bo2bo4bo2bobobo4bo3bobobobo3bo6bo$51bo6bo5bo2bobo25bo3bo2bobo
$56bo2bobo3bo4bo2bobobobobobobobobo3bo10bo$50b2o5bo8bobo2bo8bo11bo4bob
o4bo$51bo3bo5bo2bo8bobo7bobo4bo3bo4bo4bo$51bo4bo2bo6bo2bobo5bobobo4bob
o4bobobobo4bo$51bo3bobo2bobo2bo17bobo3bo2bo7bo3bo$51bo7bo4bo2bobobo2bo
bobo2bo9bo3bobobo4bo$51bo4bobo3bo12bo6bo4bobo4bo5bo3bo$51bo8bo4bobobob
obo6bo4bo5bo4bo7bo$51bo6bo3bo12bobobo2bobo2bobo3bo5bo4bo$51bobo6bo3bob
obo2bo2bo16bo2bobo3bo3bo$51bo6bo3bo6bo3bo5bobo2bobo3bo6bo6bo$51bo8bo3b
obo9bobo3bo5bo4bo5bo4bo$51bo3bo2bo3bo5bobobobo5bo3bo9bo5bo3bo$51bo4bo
3bo3bobo15bo2bobo2bobo4bo6bo$51bo3bo6bo5bobobo3bobobo2bo9bobo3bo4bo$
51bo6bobo12bo12bobobo9bo3bo$51bo3bo6bo2bo2bo2bo3bo2bo2bo7bo3bobobo6bo$
51bo4bobobo3bobo2bo6bo5bobo14bo4bo$51bo10bo8bo2bo3bobo5bobo3bo3bo3bo3b
o$51bo3bobo2bo2bobobo2bo2bobo7bobo3bobo2bo2bo6bo$51bo9bo6bo3bo7bobo9bo
6bo4bo$51bo5bo4bo2bobo2bo4bobobo7bo9bo6bo$51bobobo3bo3bo9bo8bobo3bobob
obo5bo3bo$51bo4bo11bo2bo8bo5bo10bobo4bo$51bo3bo2bobo2bobobo6bo4bo2bo
10bo2bo7bo$53bo15bobo3bobo7bobobobo8bo3bo$50bobo2bo2bobobo2bobo5bo5bo
2bo10bo4bo5bo$57bo19bo6bo3bo3bobobo3bobobo$50b2o2bo3bobobobobobobo2bob
o2bo2bo3bobobobo3bo2bo4b2o$53bobo5bo5bo6bobo5bo13bo2bo3bo$50b2o4bo22bo
5bo3bo3bo9b2o$53bo18bo31bo$50b2o5bobobobobobobo6bo2bobobo3bo3bobobobo
6bo$51bobo16bobobo11bo11bo2bob2o$50b2ob2obobobobobobobobobob3obobobobo
bobobobobobobobo2bo$51b2obobobobobobobobobobo3bobobobobobobobobobobobo
b2ob2o!
she/they // Please stop using my full name. Refer to me as dani.

"I'm always on duty, even when I'm off duty." -Cody Kolodziejzyk, Ph.D.
User avatar
danny
 
Posts: 935
Joined: October 27th, 2017, 3:43 pm
Location: New Jersey, USA

Re: Script request thread

Postby wildmyron » November 18th, 2018, 9:35 pm

danny wrote:No idea what's wrong with this script:
<snip>


This looks like your updating during the processing loop, so the neighbourhood for each cell is changing whilst you are processing the results.
wildmyron
 
Posts: 1072
Joined: August 9th, 2013, 12:45 am

Re: Script request thread

Postby dvgrn » November 18th, 2018, 9:42 pm

wildmyron wrote:
danny wrote:No idea what's wrong with this script:
<snip>


This looks like your updating during the processing loop, so the neighbourhood for each cell is changing whilst you are processing the results.

Yup, it's the old NaiveLife problem. Just adjust count() to work off of a different layer -- i.e., alternate between two layers -- or use a saved in-memory copy of the previous generation, instead of the current universe.
User avatar
dvgrn
Moderator
 
Posts: 5557
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI

Re: Script request thread

Postby danny » November 18th, 2018, 10:01 pm

Would it work if I instead stored the coordinates of each on cell in a cell list and then placed that after the fact?
she/they // Please stop using my full name. Refer to me as dani.

"I'm always on duty, even when I'm off duty." -Cody Kolodziejzyk, Ph.D.
User avatar
danny
 
Posts: 935
Joined: October 27th, 2017, 3:43 pm
Location: New Jersey, USA

Re: Script request thread

Postby dvgrn » November 18th, 2018, 10:56 pm

danny wrote:Would it work if I instead stored the coordinates of each on cell in a cell list and then placed that after the fact?

Yeah, was just about to edit my last message to suggest that. Probably that's simpler than the layer-switching trick, and about the same as putting the previous generation into a cell list.
User avatar
dvgrn
Moderator
 
Posts: 5557
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI

Re: Script request thread

Postby danny » November 19th, 2018, 2:30 am

I don't think I did it right...
--This is a preliminary version. If sufficiently interesting behaviours show
--up, it would be nice to get a full simulating algorithm in better-written
--softawre like Golly. Speaking of Golly, make sure you have a version that
--supports Lua, so you can run this script. Stinky.

--TERMS TO KNOW:
--Heat - The number returned when the previous equation is ran on all of the
--       other cells in relation to the given cell (basically what count()
--       does)

local g = golly()
local gp = require "gplus"

local rulesB = {2, 3, 4, 5}
local rulesS = {2, 3, 4, 5}

function count(x1, y1) --determine cell's heat
   local pat
   local total = 0
   if g.getcell(x1, y1) == 1 then --ok i know it's ugly but it saves a lot of processing time than doing a conditional
      g.setcell(x1, y1, 0)
      pat = g.getcells(g.getrect())
      g.setcell(x1, y1, 1)
   else
      pat = g.getcells(g.getrect())
   end
   
   for i = 1, #pat, 2 do
      local x2 = pat[i]
      local y2 = pat[i+1] --ugly
      total = total+1 / ((x2-x1)^2+(y2-y1)^2) --i know i said i was using fourth powers, however the square root and fourth power cancel out leaving just a stray ^2
   end

   return total
end

function ring(r) --basically, it returns a 'outer moore birth ring' of the given size
   local pat = g.getcells(g.getrect())
   local x, y, w, h = table.unpack(r) --there a better way to do this?
   g.select({x-1, y-1, w+2, h+2})
   g.randfill(100)
   g.select({x, y, w, h})
   g.clear(0)
   local ring = g.getcells(g.getrect())
   g.putcells(pat)
   g.clear(1)
   g.select({})
   return ring
end

function step()
   --hoooo boy i hated writing this
   --don't read it if you don't want to get lost
   local pat = g.getcells(g.getrect())
   if pat == {} then
      g.exit("All cells are dead.")
   end
   local rulesBclone = rulesB
   table.sort(rulesBclone)
   local minrulesB = rulesBclone[1] --math.min but with an array
   local lx, ly, lw, lh = table.unpack(g.getrect())
   while true do --this loop determines how far to check for births
      local localmax = 0
      local localring = ring({lx, ly, lw, lh})
      for i = 1, #localring, 2 do
         local localcount = count(localring[i], localring[i+1])
         if localcount > localmax then
            localmax = localcount
         end
      end
      if localmax < minrulesB then
         break
      end
      lx = lx - 1
      ly = ly - 1
      lw = lw + 2
      lh = lh + 2
   end
   --gosh that took me months to make, now onto processing
   g.select({lx, ly, lw, lh})
   g.randfill(100)
   g.putcells(pat, 0, 0, 1, 0, 0, 1, --[[ugh why]] "xor")
   local area = g.getcells(g.getrect())
   g.clear(0)
   g.putcells(pat)
   --NOW LET'S FINALLY PROCESS BIRTH, aka the reason that hellhole of lines above had to be done
   local localcells = {}
   for i = 1, #area, 2 do
      local localcount = count(area[i], area[i+1])
      for j = 1, #rulesB, 2 do
         if localcount >= rulesB[j] and localcount <= rulesB[j+1] then
            table.insert(localcells, pat[i])
            table.insert(localcells, pat[i+1]) --can't think of a way to insert two at once
         end
      end
   end
   --and survival, the easy part
   for i = 1, #pat, 2 do
      local localcount = count(pat[i], pat[i+1])
      for j = 1, #rulesS, 2 do
         if localcount >= rulesS[j] and localcount <= rulesS[j+1] then
            table.insert(localcells, pat[i])
            table.insert(localcells, pat[i+1])
         end
      end
   end
   g.select(g.getrect())
   g.clear(0)
   g.putcells(localcells)
   g.select({})
   g.setgen(tonumber(g.getgen()) + 1)
end

while true do
   step()
   g.update()
end


I hate my spaghetti code ;;
she/they // Please stop using my full name. Refer to me as dani.

"I'm always on duty, even when I'm off duty." -Cody Kolodziejzyk, Ph.D.
User avatar
danny
 
Posts: 935
Joined: October 27th, 2017, 3:43 pm
Location: New Jersey, USA

Re: Script request thread

Postby wildmyron » November 19th, 2018, 5:04 am

danny wrote:I don't think I did it right...

There's a bug in the birth loop - you are adding cells from the 'pat' table to 'localcells' instead of using the 'area' table.
With that bug fixed, symmetric patterns stay symmetric, but there seems to be another bug in the heat calculation.
total = total+1 / ((x2-x1)^2+(y2-y1)^2) --i know i said i was using fourth powers, however the square root and fourth power cancel out leaving just a stray ^2
The leftover ^2 appears to have been lost. I think you meant
total = total+1 / ((x2-x1)^2+(y2-y1)^2)^2


danny wrote:I hate my spaghetti code ;;

Hey, don't worry about it too much - it's not really spaghetti code in my opinion. Some of the calculations you are doing are perhaps a bit convoluted, but once you have a working reference implementation you can clean parts of it up and easily check that it's still working correctly.
wildmyron
 
Posts: 1072
Joined: August 9th, 2013, 12:45 am

Re: Script request thread

Postby danny » November 19th, 2018, 8:59 am

"The leftover 2 appears to have been lost"

No idea how that happened, it's a good thing I comment out my while thought process. I'll give the script a go during my spare time when I have computer access
she/they // Please stop using my full name. Refer to me as dani.

"I'm always on duty, even when I'm off duty." -Cody Kolodziejzyk, Ph.D.
User avatar
danny
 
Posts: 935
Joined: October 27th, 2017, 3:43 pm
Location: New Jersey, USA

Re: Script request thread

Postby calcyman » November 19th, 2018, 9:03 am

wildmyron wrote:
danny wrote:I hate my spaghetti code ;;

Hey, don't worry about it too much - it's not really spaghetti code in my opinion. Some of the calculations you are doing are perhaps a bit convoluted, but once you have a working reference implementation you can clean parts of it up and easily check that it's still working correctly.


I agree. Spaghetti code (where the control flow is difficult to determine from looking at the code) is actually quite difficult to write without using jump statements.
What do you do with ill crystallographers? Take them to the mono-clinic!
User avatar
calcyman
 
Posts: 2009
Joined: June 1st, 2009, 4:32 pm

Re: Script request thread

Postby danny » November 19th, 2018, 10:58 am

The main optimization I want to make is to make it instead run a tick in B12345678/S012345678, AND it with the pattern (or previous ring), and store that instead, so that a pattern like this doesn't kill the memory:

x = 0, y = 0, rule = B/S
o100$100bo!
she/they // Please stop using my full name. Refer to me as dani.

"I'm always on duty, even when I'm off duty." -Cody Kolodziejzyk, Ph.D.
User avatar
danny
 
Posts: 935
Joined: October 27th, 2017, 3:43 pm
Location: New Jersey, USA

Re: Script request thread

Postby dvgrn » November 19th, 2018, 11:38 am

danny wrote:The main optimization I want to make is to make it instead run a tick in B12345678/S012345678, AND it with the pattern (or previous ring), and store that instead...

To get the list of cells that might be relevant for the next tick, you mean? What if you ran B12345678/S to get the "possible-birth" cells, and just kept the original pattern's cell list for the "possible-survival" cells?
User avatar
dvgrn
Moderator
 
Posts: 5557
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI

Re: Script request thread

Postby danny » November 19th, 2018, 12:02 pm

dvgrn wrote:
danny wrote:The main optimization I want to make is to make it instead run a tick in B12345678/S012345678, AND it with the pattern (or previous ring), and store that instead...

To get the list of cells that might be relevant for the next tick, you mean? What if you ran B12345678/S to get the "possible-birth" cells, and just kept the original pattern's cell list for the "possible-survival" cells?

That would make further rings have cells in the middle;
x = 0, y = 0, rule = B12345678/S
o!
she/they // Please stop using my full name. Refer to me as dani.

"I'm always on duty, even when I'm off duty." -Cody Kolodziejzyk, Ph.D.
User avatar
danny
 
Posts: 935
Joined: October 27th, 2017, 3:43 pm
Location: New Jersey, USA

Re: Script request thread

Postby danny » November 19th, 2018, 1:22 pm

Alright I fixed a few things. But, how would I improve the birth process? It seems really slow.
--This is a preliminary version. If sufficiently interesting behaviours show
--up, it would be nice to get a full simulating algorithm in better-written
--softawre like Golly. Speaking of Golly, make sure you have a version that
--supports Lua, so you can run this script. Stinky.

--TERMS TO KNOW:
--Heat - The number returned when the previous equation is ran on all of the
--       other cells in relation to the given cell (basically what count()
--       does)

local g = golly()
local gp = require "gplus"

local rulesB = {1.33, 1.7}
local rulesS = {2.5, 5.1}

function count(x1, y1) --determine cell's heat
   local pat
   local total = 0
   if g.getcell(x1, y1) == 1 then --ok i know it's ugly but it saves a lot of processing time than doing a conditional
      g.setcell(x1, y1, 0)
      pat = g.getcells(g.getrect())
      g.setcell(x1, y1, 1)
   else
      pat = g.getcells(g.getrect())
   end
   
   for i = 1, #pat, 2 do
      local x2 = pat[i]
      local y2 = pat[i+1] --ugly
      total = total+1 / ((x2-x1)^2+(y2-y1)^2)^2 --i know i said i was using fourth powers, however the square root and fourth power cancel out leaving just a stray ^2
   end

   return total
end

function ring(r) --basically, it returns a 'outer moore birth ring' of the given size
   local pat = g.getcells(g.getrect())
   local x, y, w, h = table.unpack(r) --there a better way to do this?
   g.select({x-1, y-1, w+2, h+2})
   g.randfill(100)
   g.select({x, y, w, h})
   g.clear(0)
   local nring = g.getcells(g.getrect())
   g.putcells(pat)
   g.clear(1)
   g.select({})
   return nring
end

function step()
   --hoooo boy i hated writing this
   --don't read it if you don't want to get lost
   local pat = g.getcells(g.getrect())
   if g.getpop() == "0" then
     g.exit("All cells are dead.")
     return
   end
   local rulesBclone = rulesB
   table.sort(rulesBclone)
   local minrulesB = rulesBclone[1] --math.min but with an array
   local lx, ly, lw, lh = table.unpack(g.getrect())
   while true do --this loop determines how far to check for births
      local localmax = 0
      local localring = ring({lx, ly, lw, lh})
      for i = 1, #localring, 2 do
         local localcount = count(localring[i], localring[i+1])
         if localcount > localmax then
            localmax = localcount
         end
      end
      if localmax < minrulesB then
         break
      end
      lx = lx - 1
      ly = ly - 1
      lw = lw + 2
      lh = lh + 2
   end
   --gosh that took me months to make, now onto processing
   g.select({lx, ly, lw, lh})
   g.randfill(100)
   g.putcells(pat, 0, 0, 1, 0, 0, 1, --[[ugh why]] "xor")
   local area = g.getcells(g.getrect())
   g.clear(0)
   g.putcells(pat)
   --NOW LET'S FINALLY PROCESS BIRTH, aka the reason that hellhole of lines above had to be done
   local localcells = {}
   for i = 1, #area, 2 do
      local localcount = count(area[i], area[i+1])
      for j = 1, #rulesB, 2 do
         if localcount >= rulesB[j] and localcount <= rulesB[j+1] then
            table.insert(localcells, area[i])
            table.insert(localcells, area[i+1]) --can't think of a way to insert two at once
         end
      end
   end
   --and survival, the easy part
   for i = 1, #pat, 2 do
      local localcount = count(pat[i], pat[i+1])
      for j = 1, #rulesS, 2 do
         if localcount >= rulesS[j] and localcount <= rulesS[j+1] then
            table.insert(localcells, pat[i])
            table.insert(localcells, pat[i+1])
         end
      end
   end
   g.select(g.getrect())
   g.clear(0)
   g.putcells(localcells)
   g.select({})
   g.setgen(tonumber(g.getgen())+1)
end

while true do
   step()
   g.update()
end
step()


Funnily, in the rule I gave above, this 47-generation methuselah exists:
x = 4, y = 4, rule = B/S012345678
3bo$2b2o$bobo$3o!

It has a lot of spaceships.

EDIT: In the rule B(1.32, 1.57)/S(2.3, 3)(4, 5), there is a sparky ship and what I'm pretty sure is either a gun or a chaotic replicator:
x = 3, y = 3, rule = B/S012345678
2o$3o$2bo!

x = 3, y = 7000, rule = B/S012345678
2o$3o$2bo2$2bo$3o$2o!
she/they // Please stop using my full name. Refer to me as dani.

"I'm always on duty, even when I'm off duty." -Cody Kolodziejzyk, Ph.D.
User avatar
danny
 
Posts: 935
Joined: October 27th, 2017, 3:43 pm
Location: New Jersey, USA

Re: Script request thread

Postby BlinkerSpawn » November 19th, 2018, 9:23 pm

Looks good, danny!

I hacked in a short segment which I definitely didn't rip from giffer.lua that prompts the user for a rule (no B/S tags yet, just two comma-delimited lists separated by a space, like it shows):
--This is a preliminary version. If sufficiently interesting behaviours show
--up, it would be nice to get a full simulating algorithm in better-written
--software like Golly. Speaking of Golly, make sure you have a version that
--supports Lua, so you can run this script. Stinky.

--TERMS TO KNOW:
--Heat - The number returned when the previous equation is ran on all of the
--       other cells in relation to the given cell (basically what count()
--       does)

local g = golly()
local gp = require "gplus"

local prompt = [[
Enter birth and survival (e.g. 2,3,4,5 2,3,4,5):
]]
local answer = g.getstring(prompt, "2,3,4,5 2,3,4,5", "Set Rule...")
local birth, survival = gp.split(answer)

local rulesB = {gp.split(birth, ",")}
local rulesS = {gp.split(survival, ",")}

for i = 1, #rulesB do
   rulesB[i] = tonumber(rulesB[i])
end
for j = 1, #rulesS do
   rulesS[j] = tonumber(rulesS[j])
end

function count(x1, y1) --determine cell's heat
   local pat
   local total = 0
   if g.getcell(x1, y1) == 1 then --ok i know it's ugly but it saves a lot of processing time than doing a conditional
      g.setcell(x1, y1, 0)
      pat = g.getcells(g.getrect())
      g.setcell(x1, y1, 1)
   else
      pat = g.getcells(g.getrect())
   end
   
   for i = 1, #pat, 2 do
      local x2 = pat[i]
      local y2 = pat[i+1] --ugly
      total = total+1 / ((x2-x1)^2+(y2-y1)^2)^2 --i know i said i was using fourth powers, however the square root and fourth power cancel out leaving just a stray ^2
   end

   return total
end

function ring(r) --basically, it returns a 'outer moore birth ring' of the given size
   local pat = g.getcells(g.getrect())
   local x, y, w, h = table.unpack(r) --there a better way to do this?
   g.select({x-1, y-1, w+2, h+2})
   g.randfill(100)
   g.select({x, y, w, h})
   g.clear(0)
   local nring = g.getcells(g.getrect())
   g.putcells(pat)
   g.clear(1)
   g.select({})
   return nring
end

function step()
   --hoooo boy i hated writing this
   --don't read it if you don't want to get lost
   local pat = g.getcells(g.getrect())
   if g.getpop() == "0" then
     g.exit("All cells are dead.")
     return
   end
   local rulesBclone = rulesB
   table.sort(rulesBclone)
   local minrulesB = rulesBclone[1] --math.min but with an array
   local lx, ly, lw, lh = table.unpack(g.getrect())
   while true do --this loop determines how far to check for births
      local localmax = 0
      local localring = ring({lx, ly, lw, lh})
      for i = 1, #localring, 2 do
         local localcount = count(localring[i], localring[i+1])
         if localcount > localmax then
            localmax = localcount
         end
      end
      if localmax < minrulesB then
         break
      end
      lx = lx - 1
      ly = ly - 1
      lw = lw + 2
      lh = lh + 2
   end
   --gosh that took me months to make, now onto processing
   g.select({lx, ly, lw, lh})
   g.randfill(100)
   g.putcells(pat, 0, 0, 1, 0, 0, 1, --[[ugh why]] "xor")
   local area = g.getcells(g.getrect())
   g.clear(0)
   g.putcells(pat)
   --NOW LET'S FINALLY PROCESS BIRTH, aka the reason that hellhole of lines above had to be done
   local localcells = {}
   for i = 1, #area, 2 do
      local localcount = count(area[i], area[i+1])
      for j = 1, #rulesB, 2 do
         if localcount >= rulesB[j] and localcount <= rulesB[j+1] then
            table.insert(localcells, area[i])
            table.insert(localcells, area[i+1]) --can't think of a way to insert two at once
         end
      end
   end
   --and survival, the easy part
   for i = 1, #pat, 2 do
      local localcount = count(pat[i], pat[i+1])
      for j = 1, #rulesS, 2 do
         if localcount >= rulesS[j] and localcount <= rulesS[j+1] then
            table.insert(localcells, pat[i])
            table.insert(localcells, pat[i+1])
         end
      end
   end
   g.select(g.getrect())
   g.clear(0)
   g.putcells(localcells)
   g.select({})
   g.setgen(tonumber(g.getgen())+1)
end

while true do
   step()
   g.update()
end
step()
LifeWiki: Like Wikipedia but with more spaceships. [citation needed]

Image
User avatar
BlinkerSpawn
 
Posts: 1858
Joined: November 8th, 2014, 8:48 pm
Location: Getting a snacker from R-Bee's

Re: Script request thread

Postby muzik » December 3rd, 2018, 4:44 pm

The Fredkin rule generation script outputs rules rules that replicate similarly to this one:

x = 1, y = 1, rule = B1e2ak3einqy4jnry5einqy6ak7e/S1e2ak3einqy4jnry5einqy6ak7e
o!


Could it be modified to also be able to create (multi state generalisations of) rules similar to the following, where the center is preserved while still allowing replication overall (giving a core rule of 150 for 2-state versions)?

x = 1, y = 1, rule = B1e2ak3einqy4jnry5einqy6ak7e/S01c2-ak3acjkr4-jnry5acjkr6-ak7c8
o!
Bored of using the Moore neighbourhood for everything? Introducing the Range-2 von Neumann isotropic non-totalistic rulespace!
muzik
 
Posts: 3300
Joined: January 28th, 2016, 2:47 pm
Location: Scotland

Re: Script request thread

Postby dvgrn » December 3rd, 2018, 5:15 pm

muzik wrote:The Fredkin rule generation script outputs rules rules that replicate similarly to this one...

(replication of one dot into four increasingly widely separated dots)

Could it be modified to also be able to create (multi state generalisations of) rules similar to the following, where the center is preserved while still allowing replication overall (giving a core rule of 150 for 2-state versions)?

You mean Golly's Scripts/Python/Rule-Generators/FredkinModN-gen.py ? Funny, I had either totally forgotten that that was in there, or possibly I never knew.

The behavior you describe is generated for von Neumann (N) inputs, but for Moore neighborhood rules you get a similar pattern with eight cells in a ring and a missing cell in the center.

The only thing I know about this is that if you want the middle to be empty you use B1357/S1357:

x = 1, y = 1, rule = B1357/S1357
o!

whereas if you want the middle not to be empty you use the related totalistic rule 13579, a.k.a. Replicator 2, a.k.a. B1357/S02468:
x = 1, y = 1, rule = B1357/S02468
o!

It seems likely that this behavior also generalizes to multiple states, but I can't immediately see what to change in the script to change the survival states appropriately.
User avatar
dvgrn
Moderator
 
Posts: 5557
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI

Re: Script request thread

Postby muzik » December 3rd, 2018, 5:20 pm

It can be seen with hexagonal rules as well, as well as the TriLife script. I wouldn't be surprised if it also continued up the XOR rule trend past rules 90 and 150 as well.
Bored of using the Moore neighbourhood for everything? Introducing the Range-2 von Neumann isotropic non-totalistic rulespace!
muzik
 
Posts: 3300
Joined: January 28th, 2016, 2:47 pm
Location: Scotland

Re: Script request thread

Postby Entity Valkyrie » December 4th, 2018, 10:49 pm

User avatar
Entity Valkyrie
 
Posts: 247
Joined: November 30th, 2017, 3:30 am

PreviousNext

Return to Scripts

Who is online

Users browsing this forum: No registered users and 2 guests