NewCA.lua

For scripts to aid with computation or simulation in cellular automata.
User avatar
Andrew
Moderator
Posts: 928
Joined: June 2nd, 2009, 2:08 am
Location: Melbourne, Australia
Contact:

NewCA.lua

Post by Andrew » May 30th, 2019, 3:19 am

Golly 3.3 has a new module called NewCA.lua that makes it easy to explore lots of new CA rules. It should be possible to implement almost any CA that uses square cells with up to 256 states. To implement a new CA you need to create a .lua file that looks something like this:

Code: Select all

local g = golly()
require "gplus.NewCA"

SCRIPT_NAME = "MyCA"    -- must match the name of your .lua file
DEFAULT_RULE = "XXX"    -- must be a valid rule in your CA
RULE_HELP = "HTML code describing the rules allowed by your CA."

function ParseRule(newrule)
    -- Parse the given rule string.
    -- If valid then return nil, the canonical rule string,
    -- the width and height of the grid, and the number of states.
    -- If not valid then just return an appropriate error message.
    
    -- parsing code for your rule syntax goes here
    -- (and usually sets some global info for use in NextPattern,
    -- such as tables with birth/survival info)
    
    return nil, canonrule, wd, ht, numstates
    -- Note that wd and ht must be from 4 to 4000,
    -- and numstates must be from 2 to 256.
end

function NextPattern(currcells, minx, miny, maxx, maxy)
    -- Create the next pattern using the given parameters:
    -- currcells is a non-empty cell array containing the current pattern.
    -- minx, miny, maxx, maxy are the cell coordinates of the grid edges.
    -- This function must return the new pattern as a cell array.
    
    local newcells = {}
    
    -- code to create the next pattern goes here
    -- (typically uses the global info set in ParseRule to help
    -- determine which live cells survive and which empty cells
    -- become births)
    
    return newcells
    -- Note that currcells and newcells are one-state cell arrays if
    -- g.numstates() == 2, otherwise they are both multi-state.
end

StartNewCA()
NewCA.lua provides a lot of useful functionality:
  • Full Golly-like editing (cut/copy/paste/select/etc) including unlimited undo/redo. All of Golly's usual cursor modes are supported.
  • The interface is essentially the same as Golly. The only really new feature is a combined menu+tool bar that appears under the edit bar. It has some menus (File, Edit, View) on the left side and various buttons (Start, Reset, etc) on the right side, along with a slider for controlling the step size.
  • Patterns can be saved as .rle files. These files can be opened via the File menu's Open Pattern command. You can also open a pattern stored in the clipboard via the Open Clipboard command (or by typing shift-O).
  • Users can get help in various ways (type H or click the "?" button) and see documentation about the required rule syntax, the menu commands, a list of all the keyboard shortcuts, etc.
  • Your script can run other Lua scripts to do searches, build patterns, etc. In particular, users can specify a script to be run whenever your script starts up. A startup script can do lots of customizations (add/modify keyboard shortcuts, change the color scheme, specify a different DEFAULT_RULE, add aliases for specific rules, etc).
There is of course a price to pay for all this flexibility, and that's speed. Don't expect your CA to run at Golly-like speeds! It won't really be practical to write a CA that supports very large neighborhoods (7x7 is about the limit).

To implement a new CA you'll typically need to write a couple of hundred lines of Lua code to parse the rule strings allowed by your CA and to calculate the next pattern. To help with this task I've written a number of example scripts that you can download and examine (listed roughly in order of increasing complexity):

http://www.trevorrow.com/golly/RandomLife.lua
http://www.trevorrow.com/golly/BSFKL.lua
http://www.trevorrow.com/golly/CoordCA.lua

TIP: These scripts can be run from any location, but I strongly advise that you put each file in a separate folder.

Golly 3.3 also comes with a couple of examples in Scripts/Lua: 1D.lua and Margolus.lua. I'll discuss all the examples in later posts.
Use Glu to explore CA rules on non-periodic tilings: DominoLife and HatLife

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

Re: NewCA.lua

Post by Andrew » May 30th, 2019, 3:21 am

Before looking at the specifics of each example, I should mention a number of features they have in common:
  • Users can hit alt-R (option-R on a Mac) to create a random pattern with a random rule. This makes it easy to search for rules with interesting behavior.
  • NewCA.lua only supports finite bounded grids with dimensions from 4 to 4,000. All my example scripts use a toroidal grid with a default size of 500 x 500. For consistency with Golly, all rule strings can have an optional suffix like ":T400,300" or ":T400" to specify a desired grid size. (It's perfectly possible to support other topologies but you'd have to write a lot of messy code.)
  • The ParseRule code allows entering an empty string as a quick way to switch to the default rule.
  • Letters in a given rule can be entered in lower case, but the canonical version always uses upper case.
  • All the examples define a global aliases table so you can assign mnemonic names to specific rule strings. More on this later.
It's probably a good idea to support these features in any new CA you might write, but it's not compulsory.
Use Glu to explore CA rules on non-periodic tilings: DominoLife and HatLife

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

Re: NewCA.lua

Post by Andrew » May 30th, 2019, 3:24 am

RandomLife.lua

This script lets you explore non-deterministic rules. It supports Life-like rule strings with additional P parameters that specify the percentage probability of a birth or survival occurring. The rule syntax is

BbPp/SsPp

where b contains the birth counts (1 to 8 ), s contains the survival counts (0 to 8 ), and p is a number from 1 to 100. B3P100/S23P100 is equivalent to Life and the script defines an alias called "life" so you can easily switch to that rule.

The DEFAULT_RULE is B3P99/S23P99. Patterns using this rule quickly decay to blocks that then slowly die.

Most rules in this CA tend to be rather boring, but I wanted to keep it very simple so it can be used as a starting point for other non-deterministic rules that people might want to implement.
Use Glu to explore CA rules on non-periodic tilings: DominoLife and HatLife

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

Re: NewCA.lua

Post by Andrew » May 30th, 2019, 3:25 am

BSFKL.lua

This script lets you explore BSFKL rules as defined by Brian Prentice here. It should be able to run all the patterns and rules posted in that thread.

The default color scheme set by NewCA.lua uses a dark blue background with a gradient from white to pure blue for live cells. This is specified in a global function called SetColors. BSFKL.lua redefines SetColors to use a black background with yellow for state 1 and red for state 2.

Avoid the temptation to modify BSFKL.lua if you'd prefer a different color scheme. The best place to do that is in a startup script, as described later.
Use Glu to explore CA rules on non-periodic tilings: DominoLife and HatLife

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

Re: NewCA.lua

Post by Andrew » May 30th, 2019, 3:27 am

CoordCA.lua

This script is a Lua implementation of Saka's CoordCA Python code. CoordCA.lua only supports ranges from 1 to 3 (3 corresponds to a 7x7 neighborhood).

I've never been able to run Saka's version on either of my Macs so I hope I've implemented it correctly! I'd be curious to see a speed comparison.
Use Glu to explore CA rules on non-periodic tilings: DominoLife and HatLife

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

Re: NewCA.lua

Post by Andrew » May 30th, 2019, 3:29 am

1D.lua

This script lets you explore some one-dimensional rules. It supports all of Stephen Wolfram's 256 elementary rules (including the odd numbers), as well as totalistic rules with up to 4 states and a maximum range of 4.

The syntax for elementary rules is Wn where n is from 0 to 255. Totalistic rules are strings of the form CcKkRr where c is a code number from 0 to k^((2r+1)k-2r)-1, k is the number of states (2 to 4), and r is the range (1 to 4).

The ParseRule code sets NextPattern to either NextElementary or NextTotalistic, depending on the given rule. This is a useful technique that avoids the code in NextPattern becoming way too big and complicated.

1D.lua always generates from the bottom row of the current pattern. When it reaches the bottom row of the grid, it clears the grid, copies the bottom row to the top of the grid, and continues.

SetColors is redefined to use the same color scheme as in Wolfram's "A New Kind of Science". Not really my preferred scheme but it makes it easy to check that the script is working correctly! Note that the SetColors function uses g.setcolor commands to change the grid border and the status bar background to light blue.

1D.lua also redefines the RandomPattern function to create a single row of random cells at the top of the grid.
Use Glu to explore CA rules on non-periodic tilings: DominoLife and HatLife

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

Re: NewCA.lua

Post by Andrew » May 30th, 2019, 3:31 am

Margolus.lua

This script lets you explore rules using the Margolus neighborhood. Rule strings are of the form Mn,n,n,... where there must be 16 comma-separated numbers with values from 0 to 15. MCell's syntax (MS,Dn;n;n;...) is also allowed, as are these aliases:

bbm = M0,8,4,3,2,5,9,7,1,6,10,11,12,13,14,15 (this is the default rule)
critters = M15,14,13,3,11,5,6,1,7,9,10,2,12,4,8,0
tron = M15,1,2,3,4,5,6,7,8,9,10,11,12,13,14,0

The ParseRule code sets NextPattern to either FastPattern or SlowPattern, depending on the given rule. FastPattern is used if the rule starts with M0, or if it starts with M15 and ends with 0. To avoid ugly strobing effects in the latter case, two alternating rules will be used: one rule for even-numbered generations and another rule for odd-numbered generations (similar to how Golly handles B0 rules).
Use Glu to explore CA rules on non-periodic tilings: DominoLife and HatLife

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

Re: NewCA.lua

Post by Andrew » May 30th, 2019, 3:37 am

How to create a startup script

Let's look at a very simple startup script that changes the color scheme used by Margolus.lua.

STEP 1: Create a new file with the following contents:

Code: Select all

-- my startup script for Margolus.lua
local g = golly()
function SetColors()
    g.setcolors( {0,0,0,80} )       -- state 0 is dark blue
    g.setcolors( {1,255,255,255} )  -- state 1 is white
end
Call the file something like Margolus-startup.lua and put it anywhere you like. A good place would be the same folder where you put Margolus.lua. Note that the first line *must* contain "Margolus.lua" somewhere. Margolus.lua will only run scripts having such a line.

STEP 2: Switch to Golly and run Margolus.lua. Your startup script won't run just yet. You need to select the File menu's "Set Startup Script" command, then navigate to where you put your startup script and select it.

STEP 3: Exit Margolus.lua (hit the escape key or click the "X" button) and run it again. Now your startup script will be executed and you'll see the new color scheme. Note that NewCA.lua saves the full path to the startup script (along with other settings) in a file called Margolus.ini stored in your data directory (ie. g.getdir("data")), so if you change the name or location of the startup script then you'll need to use "Set Startup Script" to select it again.

Here's a more complicated startup script (note that it assumes your Margolus files are stored in the Golly folder in a sub-folder called My-scripts/Margolus/, so you might need to change those paths):

Code: Select all

-- my startup script for Margolus.lua
local g = golly()
local gp = require "gplus"

-- add a keyboard shortcut to run a script
local savedHandleKey = HandleKey
function HandleKey(event)
    local _, key, mods = gp.split(event)
    if key == "o" and mods == "alt" then
        RunScript(g.getdir("app").."My-scripts/Margolus/oscar.lua")
    else
        -- pass the event to the original HandleKey
        savedHandleKey(event)
    end
end

-- change the color scheme
function SetColors()
    g.setcolors( {0,0,0,80} )       -- state 0 is dark blue
    g.setcolors( {1,255,255,255} )  -- state 1 is white
end

-- change the default rule to Critters
DEFAULT_RULE = "M15,14,13,3,11,5,6,1,7,9,10,2,12,4,8,0"

-- change the default grid size (Margolus.lua will automatically adjust
-- the values to be multiples of 4 if necessary)
DEFWD, DEFHT = 400, 400

-- add more aliases that can be entered via the "Rule..." button
aliases.revtron = "M0,14,13,12,11,10,9,8,7,6,5,4,3,2,1,15"
aliases.bbm20 =   "M0,8,4,3,2,5,9,7,1,6,10,11,12,13,14,15:T20"

-- change the files directory to show my Margolus files
-- (NewCA.lua will restore the original directory when it exits)
g.setdir("files", g.getdir("app").."My-scripts/Margolus/")
g.setoption("showfiles", 1)
FitPattern()
Ok, that's enough posts for today! Questions, suggestions and bug reports are all welcome.
Use Glu to explore CA rules on non-periodic tilings: DominoLife and HatLife

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

Re: NewCA.lua

Post by rowett » May 30th, 2019, 9:15 am

Andrew wrote:IMPORTANT: Put NewCA.lua inside Golly's Scripts/Lua/oplus folder.
Based on the examples above it needs to go in the gplus folder and not the oplus folder.

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

Re: NewCA.lua

Post by Andrew » May 30th, 2019, 7:52 pm

rowett wrote:Based on the examples above it needs to go in the gplus folder and not the oplus folder.
Oops! I've edited the top post to say gplus. Sorry about that folks. Just move NewCA.lua out of the oplus folder and into the gplus folder. (At some point I changed my mind about where it should go, but obviously forgot to update the files on my website!)
Use Glu to explore CA rules on non-periodic tilings: DominoLife and HatLife

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

Re: NewCA.lua

Post by Saka » May 31st, 2019, 6:56 am

Andrew wrote: (Snip)

I've never been able to run Saka's version on either of my Macs so I hope I've implemented it correctly! I'd be curious to see a speed comparison.
As far as I can tell it works correctly.

It's much faster, and the interface is much better and comfortable, I might use this instead :lol:.

The Alt-R is very interesting, I like it!:

Code: Select all

x = 1, y = 3, rule = 16BC400-2_3-5-6-10-15-16-17-19-20-21-23_0-1-6-11-13-14-16-18-23:T500,500
o$o$o!

Code: Select all

1653000000000-3_3-4-5-6-7-8-9-10-11-12-14-18-22-23-25-26-27-28-29-31-34-35-36-37-39-40-41-42-46_4-6-7-8-10-13-16-17-20-22-23-25-27-28-29-35-36-39-41-43-44-45-46-48
is also cool
One thing I would like though is the ability to change the rule without changing the neigborhood for CoordCA.

EDIT:
I found one little "bug"(?): Asymmetric neighborhoods are flipped horizontally.

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

Re: NewCA.lua

Post by Andrew » June 1st, 2019, 3:36 am

Saka wrote:I found one little "bug"(?): Asymmetric neighborhoods are flipped horizontally.
Actually it was quite a serious bug. My logic for handling empty cells was completely wrong -- just luck that it looked like it worked for some rules! I've uploaded a new version of CoordCA.lua to my website:

http://www.trevorrow.com/golly/CoordCA.lua

It's a bit slower than the previous version, but I'm pretty sure it's now correct. I've also added the ability to hit alt-B to create a random pattern with a rule that keeps the same neighborhood but randomizes the birth and survival counts.
Use Glu to explore CA rules on non-periodic tilings: DominoLife and HatLife

User avatar
simsim314
Posts: 1823
Joined: February 10th, 2014, 1:27 pm

Re: NewCA.lua

Post by simsim314 » June 3rd, 2019, 5:37 am

Hey Andrew it looks great! I just wonder where to take it from here? Can we implement Lenia for example using it? Maybe we can explore some space of random rules... Maybe it's better to start with larger than life rules or some continuous rule.

Anyway I was playing a bit with the new script, and failed to make it work (not sure what went wrong):

Code: Select all

local g = golly()
require "gplus.NewCA"

SCRIPT_NAME = "ltl_test"    -- must match the name of your .lua file
DEFAULT_RULE = "B3/S23"    -- must be a valid rule in your CA
RULE_HELP = "HTML code describing the rules allowed by your CA."

function ParseRule(newrule)
    -- Parse the given rule string.
    -- If valid then return nil, the canonical rule string,
    -- the width and height of the grid, and the number of states.
    -- If not valid then just return an appropriate error message.

    return nil, "B3/S23", 1000, 1000, 256
    -- Note that wd and ht must be from 4 to 4000,
    -- and numstates must be from 2 to 256.
end

function NextVal(x, y)
	total = 0.0 

	for i = 1, 31 do
		for j = 1, 31 do 
			dx = i - 16 
			dy = j - 16 
			r2 = dx * dx + dy * dy 
			total = total + (4.0 / r2) * (g.getcell(x + dx, y + dy) / 255.0)
		end
	end  

	if total > 1 then 
		total = 1 
	end 

	return math.floor(255 * total) 
end 

function NextPattern(currcells, minx, miny, maxx, maxy)
    -- Create the next pattern using the given parameters:
    -- currcells is a non-empty cell array containing the current pattern.
    -- minx, miny, maxx, maxy are the cell coordinates of the grid edges.
    -- This function must return the new pattern as a cell array.
    
    local newcells = {}
    local get = g.getcell

    for i = 1, 1000 do 
	for j = 1, 1000 do 
	    newcells[#newcells + 1] = i 
	    newcells[#newcells + 1] = j
	    newcells[#newcells + 1] = NextVal(i, j)
	end 
    end
    
    return newcells
    -- Note that currcells and newcells are one-state cell arrays if
    -- g.numstates() == 2, otherwise they are both multi-state.
end

StartNewCA()


One small thing that bothered me is that we're still in CA reality. So we're probably local. We at least should have radius of influence and just the NextVal from the cells from inside the radius instead of newcells. I would suggest to have two interfaces of this sort (one is using newcells the other NextVal using local NxN neighbors).

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

Re: NewCA.lua

Post by Andrew » June 3rd, 2019, 10:37 pm

simsim314 wrote:Can we implement Lenia for example using it?
I doubt it would be practical. NewCA.lua struggles to handle neighborhood sizes beyond about 7x7. Ready would be the right tool to implement Lenia (the best place to start would be the SmoothLife examples in the Patterns/SmoothLife2011 folder).
Anyway I was playing a bit with the new script, and failed to make it work...
Below is a corrected version of your script. It runs without any errors but it probably doesn't do what your original script intended because I had to change quite a lot of code to see something happen. It also revealed a couple of bugs in NewCA.lua, so much thanks for having a go!

Here are the main changes I had to make:

* ParseRule has to return 255 for the number of states rather than 256. NewCA.lua creates a layer that uses the LtL algo and I forgot that LtL rules only allow a maximum of 255 for the C parameter. (This was done for compatibility with MCell but I'll have to check why the limit is 255 -- I can't really see why Golly's LtL algo can't use the full 256 states).

* ParseRule also has to return a canonical rule with a ":T..." suffix. This avoids a bug in NewCA's copy-and-paste code that I'll have to fix.

Your NextPattern function needed a number of changes:

* I moved the NextVal function into NextPattern and made it local. This made it a bit faster and also allowed easy access to the minx, miny, maxx, maxy parameters so I could do edge wrapping (without which g.getcell would fail when you tried to access a cell outside the grid). Note that local variables and functions are about 10% faster to access in Lua, so definitely worth doing, especially in inner loops.

* I had to reduce the size of the NextVal neighborhood to 7x7. Any bigger and generating speeds are way too slow. That's also why I reduced the grid size to 200x200.

* I added lines that ensure the length of newcells is odd (both newcells and currcells are multi-state cell arrays because your CA has more than 2 states).

* I added the lines near the end that delete the old pattern and add the new pattern.

Further optimization of NextPattern would be possible by using an agorithm that iterates thru the currcells array rather than looking at every cell in the grid (see CoordCA.lua for a good example) but I didn't want to change your code too much at this stage.

Code: Select all

local g = golly()
require "gplus.NewCA"

SCRIPT_NAME = "ltl_test"    -- must match the name of your .lua file
DEFAULT_RULE = "LTL"        -- must be a valid rule in your CA
RULE_HELP = "There is only one rule allowed in this CA (LTL)."

function ParseRule(newrule)
    -- Parse the given rule string.
    -- If valid then return nil, the canonical rule string,
    -- the width and height of the grid, and the number of states.
    -- If not valid then just return an appropriate error message.

    return nil, "LTL:T200,200", 200, 200, 255
    -- Note that wd and ht must be from 4 to 4000,
    -- and numstates must be from 2 to 255.
end

function NextPattern(currcells, minx, miny, maxx, maxy)
    -- Create the next pattern using the given parameters:
    -- currcells is a non-empty cell array containing the current pattern.
    -- minx, miny, maxx, maxy are the cell coordinates of the grid edges.
    -- This function must return the new pattern as a cell array.
    
    local function NextVal(x, y)
        local get = g.getcell
        local total = 0.0
        local range = 3     -- 7x7 neighborhood (any bigger is too slow)
        
        for dx = -range, range do
            local col = x + dx
            
            -- wrap left/right edges
            if col < minx then
                col = maxx - (minx - col - 1)
            elseif col > maxx then
                col = minx + (col - maxx - 1)
            end
            
            for dy = -range, range do
                local row = y + dy
                
                -- wrap top/bottom edges
                if row < miny then
                    row = maxy - (miny - row - 1)
                elseif row > maxy then
                    row = miny + (row - maxy - 1)
                end
    
                local r2 = dx * dx + dy * dy
                total = total + (r2 / 128.0) * (get(col, row) / 254.0)
            end
        end 
    
        if total > 1 then
            total = 1
        end
    
        return math.floor(254 * total)
    end
   
    -- Note that currcells and newcells are both multi-state in this CA.
    local newcells = {}
    
    for i = minx, maxx do
        for j = miny, maxy do
            local newstate = NextVal(i, j)
            if newstate > 0 then
                newcells[#newcells + 1] = i
                newcells[#newcells + 1] = j
                newcells[#newcells + 1] = newstate
            end
        end
    end
    
    if #newcells > 0 then
        -- newcells is a multi-state cell array so ensure length is odd
        if #newcells & 1 == 0 then newcells[#newcells + 1] = 0 end
    end

    -- delete the old pattern and add the new pattern
    g.putcells(currcells, 0, 0, 1, 0, 0, 1, "xor")
    g.putcells(newcells)

    return newcells
end

StartNewCA()

One small thing that bothered me is that we're still in CA reality. So we're probably local.
Sorry, but I don't understand what you mean.
I would suggest to have two interfaces of this sort (one is using newcells the other NextVal using local NxN neighbors).
I actually thought about requiring a NextState function along the lines of your NextVal but in the end opted to go for a NextPattern function, mainly because the resulting CA is faster and much more flexible (see for example 1D.lua which wraps a generating pattern to the top of the grid when it reaches the bottom row). It does impose more work on the script writer though.
Use Glu to explore CA rules on non-periodic tilings: DominoLife and HatLife

wildmyron
Posts: 1544
Joined: August 9th, 2013, 12:45 am
Location: Western Australia

Re: NewCA.lua

Post by wildmyron » June 4th, 2019, 6:23 am

Hi Andrew,

This is looking like a great system for exploring new CA.

I also wondered why the Step function acts on the whole pattern rather than a single cell, but I can see your point about efficiency and flexibility. Thinking about it further, I realised that it might be possible to port Dani's Euclidean CA to this system (latest version), though the bounded grids are a bit awkward. I never did get around to implementing either calyman's or Frewya's ideas for performance improvements - but using NextPattern instead of NextState means those techniques could still be used. Would the rule changes that script does to compute the next pattern be allowed here?

I found it a bit odd that after viewing the help in one of the NewCA that F1 in Golly took me to the help I'd previously viewed. But I see that's true also for 3D.lua and in general for the help system within Golly.

Also, it seems strange that you have to do an xor to delete the current pattern. I understand that the alternative is probably something like

Code: Select all

g.select({0, 0, 1, 1})
g.clear(1)
g.select({})
g.setcell(0, 0, 0)
which is four calls across the C <-> Lua divide. Could Golly's scripting interface be updated to allow a g.clear() call to clear everything?

I'm looking forward to seeing what everyone comes up with.
The 5S project (Smallest Spaceships Supporting Specific Speeds) is now maintained by AforAmpere. The latest collection is hosted on GitHub and contains well over 1,000,000 spaceships.

Semi-active here - recovering from a severe case of LWTDS.

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

Re: NewCA.lua

Post by Andrew » June 4th, 2019, 9:21 am

wildmyron wrote:Thinking about it further, I realised that it might be possible to port Dani's Euclidean CA to this system (latest version), though the bounded grids are a bit awkward.
That might not be a problem, if you can live with the fact that any cells outside the bounded area will be automatically clipped when you restore the saved rule. In fact, temporarily setting the LtL rule to an unbounded grid would be a useful technique for implementing a planar grid.
Would the rule changes that script does to compute the next pattern be allowed here?
I'm pretty sure they won't be a problem. Because NewCA.lua is also using LtL under the hood you won't have to worry about saving and restoring the algo. As long as NextPattern restores the original rule before it ends, all should be hunky dory.
Also, it seems strange that you have to do an xor to delete the current pattern. I understand that the alternative is probably something like

Code: Select all

g.select({0, 0, 1, 1})
g.clear(1)
g.select({})
g.setcell(0, 0, 0)
Note that a selection might exist so you'd need to save and restore it:

Code: Select all

    local savesel = g.getselrect()
    g.select({0, 0, 1, 1})
    g.clear(1)
    g.select(savesel)
    g.setcell(0, 0, 0)
I did some timing tests and found that the above method is slightly faster than the xor method for large populations but slightly slower for small populations (< 1000 cells). Ditto for this other alternative:

Code: Select all

    local savesel = g.getselrect()
    g.select(g.getrect())
    g.clear(0)
    g.select(savesel)
Could Golly's scripting interface be updated to allow a g.clear() call to clear everything?
Possibly. I'd have to do some tests to see if the speed improvements would make it worthwhile. At this stage I'm more interested in making sure NewCA.lua behaves correctly and is flexible enough to allow all sorts of weird and wonderful rules.
Use Glu to explore CA rules on non-periodic tilings: DominoLife and HatLife

wildmyron
Posts: 1544
Joined: August 9th, 2013, 12:45 am
Location: Western Australia

Re: NewCA.lua

Post by wildmyron » June 4th, 2019, 9:41 am

Thanks for your responses. I'll look into updating the implementation of EuclideanCA.
Andrew wrote:
Could Golly's scripting interface be updated to allow a g.clear() call to clear everything?
Possibly. I'd have to do some tests to see if the speed improvements would make it worthwhile. At this stage I'm more interested in making sure NewCA.lua behaves correctly and is flexible enough to allow all sorts of weird and wonderful rules.
Naturally. This was perhaps the wrong place - I mentioned it partly because I also find myself frequently doing this in my scripts when g.new("") is overkill for what I need.
The 5S project (Smallest Spaceships Supporting Specific Speeds) is now maintained by AforAmpere. The latest collection is hosted on GitHub and contains well over 1,000,000 spaceships.

Semi-active here - recovering from a severe case of LWTDS.

User avatar
simsim314
Posts: 1823
Joined: February 10th, 2014, 1:27 pm

Re: NewCA.lua

Post by simsim314 » June 5th, 2019, 10:41 am

Andrew wrote:I actually thought about requiring a NextState function along the lines of your NextVal...It does impose more work on the script writer though.
Yes i just wanted to have a template so that people could only modify the three relevant lines of the code:

Code: Select all

local r2 = dx * dx + dy * dy
total = total + (r2 / 128.0) * (get(col, row) / 254.0)
.
.
return math.floor(254 * total)
I think it would be nice to have overridable NextVal but if this is outside of the scope - to only have such vanilla template.

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

Re: NewCA.lua

Post by Andrew » June 6th, 2019, 1:32 am

Andrew wrote:As long as NextPattern restores the original rule before it ends, all should be hunky dory.
I think you'll also need to save and restore the color scheme. Golly restores the default colors after a g.setrule call changes the rule, so your NextPattern function will need to look something like this:

Code: Select all

function NextPattern(currcells, minx, miny, maxx, maxy)
    local newcells = {}
    local saverule = g.getrule()
    local savecolors = g.getcolors()

    ... code to create the next pattern with a g.setrule call ...
    
    g.setrule(saverule)
    g.setcolors(savecolors)
    return newcells
end
Use Glu to explore CA rules on non-periodic tilings: DominoLife and HatLife

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

Re: NewCA.lua

Post by Andrew » June 6th, 2019, 7:39 pm

simsim314 wrote:Yes i just wanted to have a template so that people could only modify the three relevant lines of the code:

Code: Select all

local r2 = dx * dx + dy * dy
total = total + (r2 / 128.0) * (get(col, row) / 254.0)
.
.
return math.floor(254 * total)
The following version of your script shows how you can do that. It defines two global functions, IncrementTotal and FinalState, that are called from NextVal. A user can then write a startup script that simply redefines those functions to do whatever they like.

Code: Select all

local g = golly()
require "gplus.NewCA"

SCRIPT_NAME = "ltl_test"    -- must match the name of your .lua file
DEFAULT_RULE = "LTL"        -- must be a valid rule in your CA
RULE_HELP = "There is only one rule allowed in this CA (LTL)."

function ParseRule(newrule)
    -- Parse the given rule string.
    -- If valid then return nil, the canonical rule string,
    -- the width and height of the grid, and the number of states.
    -- If not valid then just return an appropriate error message.

    return nil, "LTL:T200,200", 200, 200, 255
    -- Note that wd and ht must be from 4 to 4000,
    -- and numstates must be from 2 to 255.
end

-- IncrementTotal is a global function so a startup script can redefine it
function IncrementTotal(dx, dy, state)
    local r2 = dx * dx + dy * dy
    return (r2 / 128.0) * (state / 254.0)
end

-- FinalState is a global function so a startup script can redefine it
function FinalState(total)
    if total > 1 then
        return 0      -- more interesting than total = 1 ???!!!
    end
    return math.floor(254 * total)
end

function NextPattern(currcells, minx, miny, maxx, maxy)
    -- Create the next pattern using the given parameters:
    -- currcells is a non-empty cell array containing the current pattern.
    -- minx, miny, maxx, maxy are the cell coordinates of the grid edges.
    -- This function must return the new pattern as a cell array.
    
    local function NextVal(x, y)
        local get = g.getcell
        local total = 0.0
        local range = 3     -- 7x7 neighborhood (any bigger is too slow)
        
        for dx = -range, range do
            local col = x + dx
            
            -- wrap left/right edges
            if col < minx then
                col = maxx - (minx - col - 1)
            elseif col > maxx then
                col = minx + (col - maxx - 1)
            end
            
            for dy = -range, range do
                local row = y + dy
                
                -- wrap top/bottom edges
                if row < miny then
                    row = maxy - (miny - row - 1)
                elseif row > maxy then
                    row = miny + (row - maxy - 1)
                end
    
                total = total + IncrementTotal(dx, dy, get(col, row))
            end
        end 

        return FinalState(total)
    end
   
    -- Note that currcells and newcells are both multi-state in this CA.
    local newcells = {}
    
    for i = minx, maxx do
        for j = miny, maxy do
            local newstate = NextVal(i, j)
            if newstate > 0 then
                newcells[#newcells + 1] = i
                newcells[#newcells + 1] = j
                newcells[#newcells + 1] = newstate
            end
        end
    end
    
    if #newcells > 0 then
        -- newcells is a multi-state cell array so ensure length is odd
        if #newcells & 1 == 0 then newcells[#newcells + 1] = 0 end
    end

    -- delete the old pattern and add the new pattern
    g.putcells(currcells, 0, 0, 1, 0, 0, 1, "xor")
    g.putcells(newcells)

    return newcells
end

StartNewCA()
Use Glu to explore CA rules on non-periodic tilings: DominoLife and HatLife

wildmyron
Posts: 1544
Joined: August 9th, 2013, 12:45 am
Location: Western Australia

Re: NewCA.lua

Post by wildmyron » October 4th, 2019, 10:27 am

I posted a script using NewCA.lua in the thread for Partitioned Cellular Automata. I'm reasonably happy with the result and I found this a decent framework so far. Some comments from my experience:
  1. RandomPattern() creates a pattern using all states but RandomFill() uses only state 0/1. This seems to be because Golly's native "Random Fill" (used by NewCA.lua's RandomFill() behaves differently for the LtL algo than it does for the Generations and RuleLoader algos. Not sure whether this is intended, but in any case I suppose I can redefine RandomFill().
  2. Some of the PCA rules are reversible, and this is implemented in PCA.lua, but NewCA provides no means of decrementing the generation in place of incrementing. Although, even if it did I suppose this would be problematic because Golly doesn't allow negative values for generation.
  3. There's no nice way to support changing the icons, analogous to SetColors(). I thought about creating and removing the appropriate rule file from PCA.lua, but I'm not sure how to deal with pre-existing rule files for the same rule / cleaning up in the event of the script errors.
The 5S project (Smallest Spaceships Supporting Specific Speeds) is now maintained by AforAmpere. The latest collection is hosted on GitHub and contains well over 1,000,000 spaceships.

Semi-active here - recovering from a severe case of LWTDS.

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

Re: NewCA.lua

Post by Andrew » October 4th, 2019, 8:55 pm

wildmyron wrote:I posted a script using NewCA.lua in the thread for Partitioned Cellular Automata.
Nice job!
RandomPattern() creates a pattern using all states but RandomFill() uses only state 0/1. This seems to be because Golly's native "Random Fill" (used by NewCA.lua's RandomFill() behaves differently for the LtL algo than it does for the Generations and RuleLoader algos. Not sure whether this is intended, but in any case I suppose I can redefine RandomFill().
Yep, just redefine RandomFill to do whatever you want.
Some of the PCA rules are reversible, and this is implemented in PCA.lua, but NewCA provides no means of decrementing the generation in place of incrementing. Although, even if it did I suppose this would be problematic because Golly doesn't allow negative values for generation.
At this stage I don't see any safe way to reverse the generation count, especially if you want to allow negative values (that would require changes to the gollybase code and probably break a lot of stuff like the undo/redo logic).
There's no nice way to support changing the icons, analogous to SetColors(). I thought about creating and removing the appropriate rule file from PCA.lua, but I'm not sure how to deal with pre-existing rule files for the same rule / cleaning up in the event of the script errors.
I think it's safe enough to create a temporary .rule file. I tested the following code at the end of PCA.lua and it seems to work fine:

Code: Select all

function CreateIcons(iconfile)
    local icondata = [[
@RULE R1,C16,M0,S1..1,B1..1,NM
Icons for Partitioned Cellular Automata (PCA) rules which are simulated with
PCA.lua (and NewCA.lua which relies on the LtL Golly algo)
These icons are for 2 state PCA with 4 neighbours

@ICONS

XPM
/* width height num_colors chars_per_pixel */
"31 465 2 1"
/* colors */
". c #000000"
"B c #FFFFFF"
/* icon for state 1 */
"..............................."
"..............................."
"..............................."
"..............................."
"..............................."
"..............................."
"..............................."
"..............................."
"..............................."
"..............................."
"..............................."
"..............................."
"..............................."
"..............................."
"..............................."
"..............................."
"...............B..............."
"..............BBB.............."
".............BBBBB............."
"............BBBBBBB............"
"...........BBBBBBBBB..........."
"..........BBBBBBBBBBB.........."
".........BBBBBBBBBBBBB........."
"........BBBBBBBBBBBBBBB........"
".......BBBBBBBBBBBBBBBBB......."
"......BBBBBBBBBBBBBBBBBBB......"
".....BBBBBBBBBBBBBBBBBBBBB....."
"....BBBBBBBBBBBBBBBBBBBBBBB...."
"...BBBBBBBBBBBBBBBBBBBBBBBBB..."
"..BBBBBBBBBBBBBBBBBBBBBBBBBBB.."
".BBBBBBBBBBBBBBBBBBBBBBBBBBBBB."
/* icon for state 2 */
"..............................."
"B.............................."
"BB............................."
"BBB............................"
"BBBB..........................."
"BBBBB.........................."
"BBBBBB........................."
"BBBBBBB........................"
"BBBBBBBB......................."
"BBBBBBBBB......................"
"BBBBBBBBBB....................."
"BBBBBBBBBBB...................."
"BBBBBBBBBBBB..................."
"BBBBBBBBBBBBB.................."
"BBBBBBBBBBBBBB................."
"BBBBBBBBBBBBBBB................"
"BBBBBBBBBBBBBB................."
"BBBBBBBBBBBBB.................."
"BBBBBBBBBBBB..................."
"BBBBBBBBBBB...................."
"BBBBBBBBBB....................."
"BBBBBBBBB......................"
"BBBBBBBB......................."
"BBBBBBB........................"
"BBBBBB........................."
"BBBBB.........................."
"BBBB..........................."
"BBB............................"
"BB............................."
"B.............................."
"..............................."
/* icon for state 3 */
"..............................."
"B.............................."
"BB............................."
"BBB............................"
"BBBB..........................."
"BBBBB.........................."
"BBBBBB........................."
"BBBBBBB........................"
"BBBBBBBB......................."
"BBBBBBBBB......................"
"BBBBBBBBBB....................."
"BBBBBBBBBBB...................."
"BBBBBBBBBBBB..................."
"BBBBBBBBBBBBB.................."
"BBBBBBBBBBBBBB................."
"BBBBBBBBBBBBBBB................"
"BBBBBBBBBBBBBB.B..............."
"BBBBBBBBBBBBB.BBB.............."
"BBBBBBBBBBBB.BBBBB............."
"BBBBBBBBBBB.BBBBBBB............"
"BBBBBBBBBB.BBBBBBBBB..........."
"BBBBBBBBB.BBBBBBBBBBB.........."
"BBBBBBBB.BBBBBBBBBBBBB........."
"BBBBBBB.BBBBBBBBBBBBBBB........"
"BBBBBB.BBBBBBBBBBBBBBBBB......."
"BBBBB.BBBBBBBBBBBBBBBBBBB......"
"BBBB.BBBBBBBBBBBBBBBBBBBBB....."
"BBB.BBBBBBBBBBBBBBBBBBBBBBB...."
"BB.BBBBBBBBBBBBBBBBBBBBBBBBB..."
"B.BBBBBBBBBBBBBBBBBBBBBBBBBBB.."
".BBBBBBBBBBBBBBBBBBBBBBBBBBBBB."
/* icon for state 4 */
".BBBBBBBBBBBBBBBBBBBBBBBBBBBBB."
"..BBBBBBBBBBBBBBBBBBBBBBBBBBB.."
"...BBBBBBBBBBBBBBBBBBBBBBBBB..."
"....BBBBBBBBBBBBBBBBBBBBBBB...."
".....BBBBBBBBBBBBBBBBBBBBB....."
"......BBBBBBBBBBBBBBBBBBB......"
".......BBBBBBBBBBBBBBBBB......."
"........BBBBBBBBBBBBBBB........"
".........BBBBBBBBBBBBB........."
"..........BBBBBBBBBBB.........."
"...........BBBBBBBBB..........."
"............BBBBBBB............"
".............BBBBB............."
"..............BBB.............."
"...............B..............."
"..............................."
"..............................."
"..............................."
"..............................."
"..............................."
"..............................."
"..............................."
"..............................."
"..............................."
"..............................."
"..............................."
"..............................."
"..............................."
"..............................."
"..............................."
"..............................."
/* icon for state 5 */
".BBBBBBBBBBBBBBBBBBBBBBBBBBBBB."
"..BBBBBBBBBBBBBBBBBBBBBBBBBBB.."
"...BBBBBBBBBBBBBBBBBBBBBBBBB..."
"....BBBBBBBBBBBBBBBBBBBBBBB...."
".....BBBBBBBBBBBBBBBBBBBBB....."
"......BBBBBBBBBBBBBBBBBBB......"
".......BBBBBBBBBBBBBBBBB......."
"........BBBBBBBBBBBBBBB........"
".........BBBBBBBBBBBBB........."
"..........BBBBBBBBBBB.........."
"...........BBBBBBBBB..........."
"............BBBBBBB............"
".............BBBBB............."
"..............BBB.............."
"...............B..............."
"..............................."
"...............B..............."
"..............BBB.............."
".............BBBBB............."
"............BBBBBBB............"
"...........BBBBBBBBB..........."
"..........BBBBBBBBBBB.........."
".........BBBBBBBBBBBBB........."
"........BBBBBBBBBBBBBBB........"
".......BBBBBBBBBBBBBBBBB......."
"......BBBBBBBBBBBBBBBBBBB......"
".....BBBBBBBBBBBBBBBBBBBBB....."
"....BBBBBBBBBBBBBBBBBBBBBBB...."
"...BBBBBBBBBBBBBBBBBBBBBBBBB..."
"..BBBBBBBBBBBBBBBBBBBBBBBBBBB.."
".BBBBBBBBBBBBBBBBBBBBBBBBBBBBB."
/* icon for state 6 */
".BBBBBBBBBBBBBBBBBBBBBBBBBBBBB."
"B.BBBBBBBBBBBBBBBBBBBBBBBBBBB.."
"BB.BBBBBBBBBBBBBBBBBBBBBBBBB..."
"BBB.BBBBBBBBBBBBBBBBBBBBBBB...."
"BBBB.BBBBBBBBBBBBBBBBBBBBB....."
"BBBBB.BBBBBBBBBBBBBBBBBBB......"
"BBBBBB.BBBBBBBBBBBBBBBBB......."
"BBBBBBB.BBBBBBBBBBBBBBB........"
"BBBBBBBB.BBBBBBBBBBBBB........."
"BBBBBBBBB.BBBBBBBBBBB.........."
"BBBBBBBBBB.BBBBBBBBB..........."
"BBBBBBBBBBB.BBBBBBB............"
"BBBBBBBBBBBB.BBBBB............."
"BBBBBBBBBBBBB.BBB.............."
"BBBBBBBBBBBBBB.B..............."
"BBBBBBBBBBBBBBB................"
"BBBBBBBBBBBBBB................."
"BBBBBBBBBBBBB.................."
"BBBBBBBBBBBB..................."
"BBBBBBBBBBB...................."
"BBBBBBBBBB....................."
"BBBBBBBBB......................"
"BBBBBBBB......................."
"BBBBBBB........................"
"BBBBBB........................."
"BBBBB.........................."
"BBBB..........................."
"BBB............................"
"BB............................."
"B.............................."
"..............................."
/* icon for state 7 */
".BBBBBBBBBBBBBBBBBBBBBBBBBBBBB."
"B.BBBBBBBBBBBBBBBBBBBBBBBBBBB.."
"BB.BBBBBBBBBBBBBBBBBBBBBBBBB..."
"BBB.BBBBBBBBBBBBBBBBBBBBBBB...."
"BBBB.BBBBBBBBBBBBBBBBBBBBB....."
"BBBBB.BBBBBBBBBBBBBBBBBBB......"
"BBBBBB.BBBBBBBBBBBBBBBBB......."
"BBBBBBB.BBBBBBBBBBBBBBB........"
"BBBBBBBB.BBBBBBBBBBBBB........."
"BBBBBBBBB.BBBBBBBBBBB.........."
"BBBBBBBBBB.BBBBBBBBB..........."
"BBBBBBBBBBB.BBBBBBB............"
"BBBBBBBBBBBB.BBBBB............."
"BBBBBBBBBBBBB.BBB.............."
"BBBBBBBBBBBBBB.B..............."
"BBBBBBBBBBBBBBB................"
"BBBBBBBBBBBBBB.B..............."
"BBBBBBBBBBBBB.BBB.............."
"BBBBBBBBBBBB.BBBBB............."
"BBBBBBBBBBB.BBBBBBB............"
"BBBBBBBBBB.BBBBBBBBB..........."
"BBBBBBBBB.BBBBBBBBBBB.........."
"BBBBBBBB.BBBBBBBBBBBBB........."
"BBBBBBB.BBBBBBBBBBBBBBB........"
"BBBBBB.BBBBBBBBBBBBBBBBB......."
"BBBBB.BBBBBBBBBBBBBBBBBBB......"
"BBBB.BBBBBBBBBBBBBBBBBBBBB....."
"BBB.BBBBBBBBBBBBBBBBBBBBBBB...."
"BB.BBBBBBBBBBBBBBBBBBBBBBBBB..."
"B.BBBBBBBBBBBBBBBBBBBBBBBBBBB.."
".BBBBBBBBBBBBBBBBBBBBBBBBBBBBB."
/* icon for state 8 */
"..............................."
"..............................B"
".............................BB"
"............................BBB"
"...........................BBBB"
"..........................BBBBB"
".........................BBBBBB"
"........................BBBBBBB"
".......................BBBBBBBB"
"......................BBBBBBBBB"
".....................BBBBBBBBBB"
"....................BBBBBBBBBBB"
"...................BBBBBBBBBBBB"
"..................BBBBBBBBBBBBB"
".................BBBBBBBBBBBBBB"
"................BBBBBBBBBBBBBBB"
".................BBBBBBBBBBBBBB"
"..................BBBBBBBBBBBBB"
"...................BBBBBBBBBBBB"
"....................BBBBBBBBBBB"
".....................BBBBBBBBBB"
"......................BBBBBBBBB"
".......................BBBBBBBB"
"........................BBBBBBB"
".........................BBBBBB"
"..........................BBBBB"
"...........................BBBB"
"............................BBB"
".............................BB"
"..............................B"
"..............................."
/* icon for state 9 */
"..............................."
"..............................B"
".............................BB"
"............................BBB"
"...........................BBBB"
"..........................BBBBB"
".........................BBBBBB"
"........................BBBBBBB"
".......................BBBBBBBB"
"......................BBBBBBBBB"
".....................BBBBBBBBBB"
"....................BBBBBBBBBBB"
"...................BBBBBBBBBBBB"
"..................BBBBBBBBBBBBB"
".................BBBBBBBBBBBBBB"
"................BBBBBBBBBBBBBBB"
"...............B.BBBBBBBBBBBBBB"
"..............BBB.BBBBBBBBBBBBB"
".............BBBBB.BBBBBBBBBBBB"
"............BBBBBBB.BBBBBBBBBBB"
"...........BBBBBBBBB.BBBBBBBBBB"
"..........BBBBBBBBBBB.BBBBBBBBB"
".........BBBBBBBBBBBBB.BBBBBBBB"
"........BBBBBBBBBBBBBBB.BBBBBBB"
".......BBBBBBBBBBBBBBBBB.BBBBBB"
"......BBBBBBBBBBBBBBBBBBB.BBBBB"
".....BBBBBBBBBBBBBBBBBBBBB.BBBB"
"....BBBBBBBBBBBBBBBBBBBBBBB.BBB"
"...BBBBBBBBBBBBBBBBBBBBBBBBB.BB"
"..BBBBBBBBBBBBBBBBBBBBBBBBBBB.B"
".BBBBBBBBBBBBBBBBBBBBBBBBBBBBB."
/* icon for state 10 */
"..............................."
"B.............................B"
"BB...........................BB"
"BBB.........................BBB"
"BBBB.......................BBBB"
"BBBBB.....................BBBBB"
"BBBBBB...................BBBBBB"
"BBBBBBB.................BBBBBBB"
"BBBBBBBB...............BBBBBBBB"
"BBBBBBBBB.............BBBBBBBBB"
"BBBBBBBBBB...........BBBBBBBBBB"
"BBBBBBBBBBB.........BBBBBBBBBBB"
"BBBBBBBBBBBB.......BBBBBBBBBBBB"
"BBBBBBBBBBBBB.....BBBBBBBBBBBBB"
"BBBBBBBBBBBBBB...BBBBBBBBBBBBBB"
"BBBBBBBBBBBBBBB.BBBBBBBBBBBBBBB"
"BBBBBBBBBBBBBB...BBBBBBBBBBBBBB"
"BBBBBBBBBBBBB.....BBBBBBBBBBBBB"
"BBBBBBBBBBBB.......BBBBBBBBBBBB"
"BBBBBBBBBBB.........BBBBBBBBBBB"
"BBBBBBBBBB...........BBBBBBBBBB"
"BBBBBBBBB.............BBBBBBBBB"
"BBBBBBBB...............BBBBBBBB"
"BBBBBBB.................BBBBBBB"
"BBBBBB...................BBBBBB"
"BBBBB.....................BBBBB"
"BBBB.......................BBBB"
"BBB.........................BBB"
"BB...........................BB"
"B.............................B"
"..............................."
/* icon for state 11 */
"..............................."
"B.............................B"
"BB...........................BB"
"BBB.........................BBB"
"BBBB.......................BBBB"
"BBBBB.....................BBBBB"
"BBBBBB...................BBBBBB"
"BBBBBBB.................BBBBBBB"
"BBBBBBBB...............BBBBBBBB"
"BBBBBBBBB.............BBBBBBBBB"
"BBBBBBBBBB...........BBBBBBBBBB"
"BBBBBBBBBBB.........BBBBBBBBBBB"
"BBBBBBBBBBBB.......BBBBBBBBBBBB"
"BBBBBBBBBBBBB.....BBBBBBBBBBBBB"
"BBBBBBBBBBBBBB...BBBBBBBBBBBBBB"
"BBBBBBBBBBBBBBB.BBBBBBBBBBBBBBB"
"BBBBBBBBBBBBBB.B.BBBBBBBBBBBBBB"
"BBBBBBBBBBBBB.BBB.BBBBBBBBBBBBB"
"BBBBBBBBBBBB.BBBBB.BBBBBBBBBBBB"
"BBBBBBBBBBB.BBBBBBB.BBBBBBBBBBB"
"BBBBBBBBBB.BBBBBBBBB.BBBBBBBBBB"
"BBBBBBBBB.BBBBBBBBBBB.BBBBBBBBB"
"BBBBBBBB.BBBBBBBBBBBBB.BBBBBBBB"
"BBBBBBB.BBBBBBBBBBBBBBB.BBBBBBB"
"BBBBBB.BBBBBBBBBBBBBBBBB.BBBBBB"
"BBBBB.BBBBBBBBBBBBBBBBBBB.BBBBB"
"BBBB.BBBBBBBBBBBBBBBBBBBBB.BBBB"
"BBB.BBBBBBBBBBBBBBBBBBBBBBB.BBB"
"BB.BBBBBBBBBBBBBBBBBBBBBBBBB.BB"
"B.BBBBBBBBBBBBBBBBBBBBBBBBBBB.B"
".BBBBBBBBBBBBBBBBBBBBBBBBBBBBB."
/* icon for state 12 */
".BBBBBBBBBBBBBBBBBBBBBBBBBBBBB."
"..BBBBBBBBBBBBBBBBBBBBBBBBBBB.B"
"...BBBBBBBBBBBBBBBBBBBBBBBBB.BB"
"....BBBBBBBBBBBBBBBBBBBBBBB.BBB"
".....BBBBBBBBBBBBBBBBBBBBB.BBBB"
"......BBBBBBBBBBBBBBBBBBB.BBBBB"
".......BBBBBBBBBBBBBBBBB.BBBBBB"
"........BBBBBBBBBBBBBBB.BBBBBBB"
".........BBBBBBBBBBBBB.BBBBBBBB"
"..........BBBBBBBBBBB.BBBBBBBBB"
"...........BBBBBBBBB.BBBBBBBBBB"
"............BBBBBBB.BBBBBBBBBBB"
".............BBBBB.BBBBBBBBBBBB"
"..............BBB.BBBBBBBBBBBBB"
"...............B.BBBBBBBBBBBBBB"
"................BBBBBBBBBBBBBBB"
".................BBBBBBBBBBBBBB"
"..................BBBBBBBBBBBBB"
"...................BBBBBBBBBBBB"
"....................BBBBBBBBBBB"
".....................BBBBBBBBBB"
"......................BBBBBBBBB"
".......................BBBBBBBB"
"........................BBBBBBB"
".........................BBBBBB"
"..........................BBBBB"
"...........................BBBB"
"............................BBB"
".............................BB"
"..............................B"
"..............................."
/* icon for state 13 */
".BBBBBBBBBBBBBBBBBBBBBBBBBBBBB."
"..BBBBBBBBBBBBBBBBBBBBBBBBBBB.B"
"...BBBBBBBBBBBBBBBBBBBBBBBBB.BB"
"....BBBBBBBBBBBBBBBBBBBBBBB.BBB"
".....BBBBBBBBBBBBBBBBBBBBB.BBBB"
"......BBBBBBBBBBBBBBBBBBB.BBBBB"
".......BBBBBBBBBBBBBBBBB.BBBBBB"
"........BBBBBBBBBBBBBBB.BBBBBBB"
".........BBBBBBBBBBBBB.BBBBBBBB"
"..........BBBBBBBBBBB.BBBBBBBBB"
"...........BBBBBBBBB.BBBBBBBBBB"
"............BBBBBBB.BBBBBBBBBBB"
".............BBBBB.BBBBBBBBBBBB"
"..............BBB.BBBBBBBBBBBBB"
"...............B.BBBBBBBBBBBBBB"
"................BBBBBBBBBBBBBBB"
"...............B.BBBBBBBBBBBBBB"
"..............BBB.BBBBBBBBBBBBB"
".............BBBBB.BBBBBBBBBBBB"
"............BBBBBBB.BBBBBBBBBBB"
"...........BBBBBBBBB.BBBBBBBBBB"
"..........BBBBBBBBBBB.BBBBBBBBB"
".........BBBBBBBBBBBBB.BBBBBBBB"
"........BBBBBBBBBBBBBBB.BBBBBBB"
".......BBBBBBBBBBBBBBBBB.BBBBBB"
"......BBBBBBBBBBBBBBBBBBB.BBBBB"
".....BBBBBBBBBBBBBBBBBBBBB.BBBB"
"....BBBBBBBBBBBBBBBBBBBBBBB.BBB"
"...BBBBBBBBBBBBBBBBBBBBBBBBB.BB"
"..BBBBBBBBBBBBBBBBBBBBBBBBBBB.B"
".BBBBBBBBBBBBBBBBBBBBBBBBBBBBB."
/* icon for state 14 */
".BBBBBBBBBBBBBBBBBBBBBBBBBBBBB."
"B.BBBBBBBBBBBBBBBBBBBBBBBBBBB.B"
"BB.BBBBBBBBBBBBBBBBBBBBBBBBB.BB"
"BBB.BBBBBBBBBBBBBBBBBBBBBBB.BBB"
"BBBB.BBBBBBBBBBBBBBBBBBBBB.BBBB"
"BBBBB.BBBBBBBBBBBBBBBBBBB.BBBBB"
"BBBBBB.BBBBBBBBBBBBBBBBB.BBBBBB"
"BBBBBBB.BBBBBBBBBBBBBBB.BBBBBBB"
"BBBBBBBB.BBBBBBBBBBBBB.BBBBBBBB"
"BBBBBBBBB.BBBBBBBBBBB.BBBBBBBBB"
"BBBBBBBBBB.BBBBBBBBB.BBBBBBBBBB"
"BBBBBBBBBBB.BBBBBBB.BBBBBBBBBBB"
"BBBBBBBBBBBB.BBBBB.BBBBBBBBBBBB"
"BBBBBBBBBBBBB.BBB.BBBBBBBBBBBBB"
"BBBBBBBBBBBBBB.B.BBBBBBBBBBBBBB"
"BBBBBBBBBBBBBBB.BBBBBBBBBBBBBBB"
"BBBBBBBBBBBBBB...BBBBBBBBBBBBBB"
"BBBBBBBBBBBBB.....BBBBBBBBBBBBB"
"BBBBBBBBBBBB.......BBBBBBBBBBBB"
"BBBBBBBBBBB.........BBBBBBBBBBB"
"BBBBBBBBBB...........BBBBBBBBBB"
"BBBBBBBBB.............BBBBBBBBB"
"BBBBBBBB...............BBBBBBBB"
"BBBBBBB.................BBBBBBB"
"BBBBBB...................BBBBBB"
"BBBBB.....................BBBBB"
"BBBB.......................BBBB"
"BBB.........................BBB"
"BB...........................BB"
"B.............................B"
"..............................."
/* icon for state 15 */
".BBBBBBBBBBBBBBBBBBBBBBBBBBBBB."
"B.BBBBBBBBBBBBBBBBBBBBBBBBBBB.B"
"BB.BBBBBBBBBBBBBBBBBBBBBBBBB.BB"
"BBB.BBBBBBBBBBBBBBBBBBBBBBB.BBB"
"BBBB.BBBBBBBBBBBBBBBBBBBBB.BBBB"
"BBBBB.BBBBBBBBBBBBBBBBBBB.BBBBB"
"BBBBBB.BBBBBBBBBBBBBBBBB.BBBBBB"
"BBBBBBB.BBBBBBBBBBBBBBB.BBBBBBB"
"BBBBBBBB.BBBBBBBBBBBBB.BBBBBBBB"
"BBBBBBBBB.BBBBBBBBBBB.BBBBBBBBB"
"BBBBBBBBBB.BBBBBBBBB.BBBBBBBBBB"
"BBBBBBBBBBB.BBBBBBB.BBBBBBBBBBB"
"BBBBBBBBBBBB.BBBBB.BBBBBBBBBBBB"
"BBBBBBBBBBBBB.BBB.BBBBBBBBBBBBB"
"BBBBBBBBBBBBBB.B.BBBBBBBBBBBBBB"
"BBBBBBBBBBBBBBB.BBBBBBBBBBBBBBB"
"BBBBBBBBBBBBBB.B.BBBBBBBBBBBBBB"
"BBBBBBBBBBBBB.BBB.BBBBBBBBBBBBB"
"BBBBBBBBBBBB.BBBBB.BBBBBBBBBBBB"
"BBBBBBBBBBB.BBBBBBB.BBBBBBBBBBB"
"BBBBBBBBBB.BBBBBBBBB.BBBBBBBBBB"
"BBBBBBBBB.BBBBBBBBBBB.BBBBBBBBB"
"BBBBBBBB.BBBBBBBBBBBBB.BBBBBBBB"
"BBBBBBB.BBBBBBBBBBBBBBB.BBBBBBB"
"BBBBBB.BBBBBBBBBBBBBBBBB.BBBBBB"
"BBBBB.BBBBBBBBBBBBBBBBBBB.BBBBB"
"BBBB.BBBBBBBBBBBBBBBBBBBBB.BBBB"
"BBB.BBBBBBBBBBBBBBBBBBBBBBB.BBB"
"BB.BBBBBBBBBBBBBBBBBBBBBBBBB.BB"
"B.BBBBBBBBBBBBBBBBBBBBBBBBBBB.B"
".BBBBBBBBBBBBBBBBBBBBBBBBBBBBB."

XPM
/* width height num_colors chars_per_pixel */
"15 225 2 1"
/* colors */
". c #000000"
"B c #FFFFFF"
/* icon for state 1 */
"..............."
"..............."
"..............."
"..............."
"..............."
"..............."
"..............."
"..............."
".......B......."
"......BBB......"
".....BBBBB....."
"....BBBBBBB...."
"...BBBBBBBBB..."
"..BBBBBBBBBBB.."
".BBBBBBBBBBBBB."
/* icon for state 2 */
"..............."
"B.............."
"BB............."
"BBB............"
"BBBB..........."
"BBBBB.........."
"BBBBBB........."
"BBBBBBB........"
"BBBBBB........."
"BBBBB.........."
"BBBB..........."
"BBB............"
"BB............."
"B.............."
"..............."
/* icon for state 3 */
"..............."
"B.............."
"BB............."
"BBB............"
"BBBB..........."
"BBBBB.........."
"BBBBBB........."
"BBBBBBB........"
"BBBBBB.B......."
"BBBBB.BBB......"
"BBBB.BBBBB....."
"BBB.BBBBBBB...."
"BB.BBBBBBBBB..."
"B.BBBBBBBBBBB.."
".BBBBBBBBBBBBB."
/* icon for state 4 */
".BBBBBBBBBBBBB."
"..BBBBBBBBBBB.."
"...BBBBBBBBB..."
"....BBBBBBB...."
".....BBBBB....."
"......BBB......"
".......B......."
"..............."
"..............."
"..............."
"..............."
"..............."
"..............."
"..............."
"..............."
/* icon for state 5 */
".BBBBBBBBBBBBB."
"..BBBBBBBBBBB.."
"...BBBBBBBBB..."
"....BBBBBBB...."
".....BBBBB....."
"......BBB......"
".......B......."
"..............."
".......B......."
"......BBB......"
".....BBBBB....."
"....BBBBBBB...."
"...BBBBBBBBB..."
"..BBBBBBBBBBB.."
".BBBBBBBBBBBBB."
/* icon for state 6 */
".BBBBBBBBBBBBB."
"B.BBBBBBBBBBB.."
"BB.BBBBBBBBB..."
"BBB.BBBBBBB...."
"BBBB.BBBBB....."
"BBBBB.BBB......"
"BBBBBB.B......."
"BBBBBBB........"
"BBBBBB........."
"BBBBB.........."
"BBBB..........."
"BBB............"
"BB............."
"B.............."
"..............."
/* icon for state 7 */
".BBBBBBBBBBBBB."
"B.BBBBBBBBBBB.."
"BB.BBBBBBBBB..."
"BBB.BBBBBBB...."
"BBBB.BBBBB....."
"BBBBB.BBB......"
"BBBBBB.B......."
"BBBBBBB........"
"BBBBBB.B......."
"BBBBB.BBB......"
"BBBB.BBBBB....."
"BBB.BBBBBBB...."
"BB.BBBBBBBBB..."
"B.BBBBBBBBBBB.."
".BBBBBBBBBBBBB."
/* icon for state 8 */
"..............."
"..............B"
".............BB"
"............BBB"
"...........BBBB"
"..........BBBBB"
".........BBBBBB"
"........BBBBBBB"
".........BBBBBB"
"..........BBBBB"
"...........BBBB"
"............BBB"
".............BB"
"..............B"
"..............."
/* icon for state 9 */
"..............."
"..............B"
".............BB"
"............BBB"
"...........BBBB"
"..........BBBBB"
".........BBBBBB"
"........BBBBBBB"
".......B.BBBBBB"
"......BBB.BBBBB"
".....BBBBB.BBBB"
"....BBBBBBB.BBB"
"...BBBBBBBBB.BB"
"..BBBBBBBBBBB.B"
".BBBBBBBBBBBBB."
/* icon for state 10 */
"..............."
"B.............B"
"BB...........BB"
"BBB.........BBB"
"BBBB.......BBBB"
"BBBBB.....BBBBB"
"BBBBBB...BBBBBB"
"BBBBBBB.BBBBBBB"
"BBBBBB...BBBBBB"
"BBBBB.....BBBBB"
"BBBB.......BBBB"
"BBB.........BBB"
"BB...........BB"
"B.............B"
"..............."
/* icon for state 11 */
"..............."
"B.............B"
"BB...........BB"
"BBB.........BBB"
"BBBB.......BBBB"
"BBBBB.....BBBBB"
"BBBBBB...BBBBBB"
"BBBBBBB.BBBBBBB"
"BBBBBB.B.BBBBBB"
"BBBBB.BBB.BBBBB"
"BBBB.BBBBB.BBBB"
"BBB.BBBBBBB.BBB"
"BB.BBBBBBBBB.BB"
"B.BBBBBBBBBBB.B"
".BBBBBBBBBBBBB."
/* icon for state 12 */
".BBBBBBBBBBBBB."
"..BBBBBBBBBBB.B"
"...BBBBBBBBB.BB"
"....BBBBBBB.BBB"
".....BBBBB.BBBB"
"......BBB.BBBBB"
".......B.BBBBBB"
"........BBBBBBB"
".........BBBBBB"
"..........BBBBB"
"...........BBBB"
"............BBB"
".............BB"
"..............B"
"..............."
/* icon for state 13 */
".BBBBBBBBBBBBB."
"..BBBBBBBBBBB.B"
"...BBBBBBBBB.BB"
"....BBBBBBB.BBB"
".....BBBBB.BBBB"
"......BBB.BBBBB"
".......B.BBBBBB"
"........BBBBBBB"
".......B.BBBBBB"
"......BBB.BBBBB"
".....BBBBB.BBBB"
"....BBBBBBB.BBB"
"...BBBBBBBBB.BB"
"..BBBBBBBBBBB.B"
".BBBBBBBBBBBBB."
/* icon for state 14 */
".BBBBBBBBBBBBB."
"B.BBBBBBBBBBB.B"
"BB.BBBBBBBBB.BB"
"BBB.BBBBBBB.BBB"
"BBBB.BBBBB.BBBB"
"BBBBB.BBB.BBBBB"
"BBBBBB.B.BBBBBB"
"BBBBBBB.BBBBBBB"
"BBBBBB...BBBBBB"
"BBBBB.....BBBBB"
"BBBB.......BBBB"
"BBB.........BBB"
"BB...........BB"
"B.............B"
"..............."
/* icon for state 15 */
".BBBBBBBBBBBBB."
"B.BBBBBBBBBBB.B"
"BB.BBBBBBBBB.BB"
"BBB.BBBBBBB.BBB"
"BBBB.BBBBB.BBBB"
"BBBBB.BBB.BBBBB"
"BBBBBB.B.BBBBBB"
"BBBBBBB.BBBBBBB"
"BBBBBB.B.BBBBBB"
"BBBBB.BBB.BBBBB"
"BBBB.BBBBB.BBBB"
"BBB.BBBBBBB.BBB"
"BB.BBBBBBBBB.BB"
"B.BBBBBBBBBBB.B"
".BBBBBBBBBBBBB."

XPM
/* width height num_colors chars_per_pixel */
"7 105 3 1"
/* colors */
". c #000000"
"B c #FFFFFF"
"C c #A0A0A0"
/* icon for state 1 */
"......."
"......."
"......."
"...C..."
"..CBC.."
".CBBBC."
"CBBBBBC"
/* icon for state 2 */
"C......"
"BC....."
"BBC...."
"BBBC..."
"BBC...."
"BC....."
"C......"
/* icon for state 3 */
"C......"
"BC....."
"BBC...."
"BBBC..."
"BBBBC.."
"BBBBBC."
"BBBBBBC"
/* icon for state 4 */
"CBBBBBC"
".CBBBC."
"..CBC.."
"...C..."
"......."
"......."
"......."
/* icon for state 5 */
"CBBBBBC"
".CBBBC."
"..CBC.."
"...C..."
"..CBC.."
".CBBBC."
"CBBBBBC"
/* icon for state 6 */
"BBBBBBC"
"BBBBBC."
"BBBBC.."
"BBBC..."
"BBC...."
"BC....."
"C......"
/* icon for state 7 */
"BBBBBBC"
"BBBBBC."
"BBBBC.."
"BBBC..."
"BBBBC.."
"BBBBBC."
"BBBBBBC"
/* icon for state 8 */
"......C"
".....CB"
"....CBB"
"...CBBB"
"....CBB"
".....CB"
"......C"
/* icon for state 9 */
"......C"
".....CB"
"....CBB"
"...CBBB"
"..CBBBB"
".CBBBBB"
"CBBBBBB"
/* icon for state 10 */
"C.....C"
"BC...CB"
"BBC.CBB"
"BBBCBBB"
"BBC.CBB"
"BC...CB"
"C.....C"
/* icon for state 11 */
"C.....C"
"BC...CB"
"BBC.CBB"
"BBBCBBB"
"BBBBBBB"
"BBBBBBB"
"BBBBBBB"
/* icon for state 12 */
"CBBBBBB"
".CBBBBB"
"..CBBBB"
"...CBBB"
"....CBB"
".....CB"
"......C"
/* icon for state 13 */
"CBBBBBB"
".CBBBBB"
"..CBBBB"
"...CBBB"
"..CBBBB"
".CBBBBB"
"CBBBBBB"
/* icon for state 14 */
"BBBBBBB"
"BBBBBBB"
"BBBBBBB"
"BBBCBBB"
"BBC.CBB"
"BC...CB"
"C.....C"
/* icon for state 15 */
"BBBBBBB"
"BBBBBBB"
"BBBBBBB"
"BBBBBBB"
"BBBBBBB"
"BBBBBBB"
"BBBBBBB"
]]
    local f = io.open(iconfile, "w")
    if f then
        f:write(icondata)
        f:close()
    else
        g.exit("Failed to create "..iconfile)
    end
end

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

-- and away we go...
local iconfile = g.getdir("rules").."R1,C16,M0,S1..1,B1..1,NM.rule"
CreateIcons(iconfile)
StartNewCA()
os.remove(iconfile)
EDIT: If you wanted to change the icons depending on the rule you could do similar things in a SetColors function (it's called by NewCA.lua whenever the rule changes). Just keep track of all the .rule files you create and remove them at the end.
Use Glu to explore CA rules on non-periodic tilings: DominoLife and HatLife

wildmyron
Posts: 1544
Joined: August 9th, 2013, 12:45 am
Location: Western Australia

Re: NewCA.lua

Post by wildmyron » October 4th, 2019, 10:22 pm

Andrew wrote:
October 4th, 2019, 8:55 pm
Some of the PCA rules are reversible, and this is implemented in PCA.lua, but NewCA provides no means of decrementing the generation in place of incrementing. Although, even if it did I suppose this would be problematic because Golly doesn't allow negative values for generation.
At this stage I don't see any safe way to reverse the generation count, especially if you want to allow negative values (that would require changes to the gollybase code and probably break a lot of stuff like the undo/redo logic).
OK, I thought that might be problematic. I think I can do something like Lifeviewer and keep track of a separate "PCA generation" which can be displayed in the status bar along with the direction indicator.
Andrew wrote:
October 4th, 2019, 8:55 pm
There's no nice way to support changing the icons, analogous to SetColors(). I thought about creating and removing the appropriate rule file from PCA.lua, but I'm not sure how to deal with pre-existing rule files for the same rule / cleaning up in the event of the script errors.
I think it's safe enough to create a temporary .rule file. I tested the following code at the end of PCA.lua and it seems to work fine:

Code: Select all

<snip>
EDIT: If you wanted to change the icons depending on the rule you could do similar things in a SetColors function (it's called by NewCA.lua whenever the rule changes). Just keep track of all the .rule files you create and remove them at the end.
Yes, seems reasonable. Thanks for the SetColors tip, could be useful later on.
The 5S project (Smallest Spaceships Supporting Specific Speeds) is now maintained by AforAmpere. The latest collection is hosted on GitHub and contains well over 1,000,000 spaceships.

Semi-active here - recovering from a severe case of LWTDS.

wildmyron
Posts: 1544
Joined: August 9th, 2013, 12:45 am
Location: Western Australia

Re: NewCA.lua

Post by wildmyron » October 11th, 2019, 6:50 am

Slowly making some progress on PCA.lua, but first some comments on NewCA.lua

- There's a bug in the loop conditions within RandomPattern - odd values for the width and height result in the pattern being smaller than expected. Suggested fix:

Code: Select all

    for y = -(ht//2), (ht//2)+(ht%2)-1 do
        for x = -(wd//2), (wd//2)+(wd%2)-1 do
            if rand(0,99) < percentage then
                g.setcell(x, y, rand(1,g.numstates()-1))
            end
        end
    end
- ParseRule returning a float value (>2) for numstates causes an exception when golly.setrule is called (e.g. for numstates = 16, real_rule will contain "C16.0,"). I'm not sure if ParseRule or CheckRule should be responsible for ensuring this doesn't happen.

- Some of the functions under the heading "getters for user scripts" are not documented in the help under "Script functions". In particular: GetGenCount, GetStepSize, and GetDensity.

- In various places on the forum as well as in the NewCA help you've mentioned that using a startup script involves saving the file with whatever preferred name and then using "File -> Set Startup Script...". I've just noticed that SanityChecks sets the startup script by default to <SCRIPT_NAME>-start.lua, so if the startup script is saved with that name it will be automatically used (unless it's been changed). I don't think this is mentioned anywhere.

- The mechanism to change and show the Files directory via the startup script is nice, but when the user CA is quit and the original Files directory is restored the open/close state of all the subfolders is lost. This doesn't happen if the Files directory is not changed. I guess that would be quite tricky to restore though.

- Another nicety: In several places NewCA versions of oscar.lua are mentioned (e.g. in the advice about startup scripts). I know there can't be a universal NewCA version of oscar, but the BSFKL version on your website would work pretty well for most CA that have spatial and temporal homogeneity (i.e., not Margolus or 1D type CA). Changing the first line to contain NewCA.lua rather than BSFKL.lua allowed me to use it with PCA.lua, for example. It would be nice if this script was more readily available.

==========================================================

OK, onto PCA.lua
Andrew wrote:
October 4th, 2019, 8:55 pm
RandomPattern() creates a pattern using all states but RandomFill() uses only state 0/1. This seems to be because Golly's native "Random Fill" (used by NewCA.lua's RandomFill() behaves differently for the LtL algo than it does for the Generations and RuleLoader algos. Not sure whether this is intended, but in any case I suppose I can redefine RandomFill().
Yep, just redefine RandomFill to do whatever you want.
Here's what I've got so far:

Code: Select all

-- Random fill of selection should use all states
function RandomFill(percentage)
    percentage = percentage or GetDensity()
    local rand = math.random
    local setcell = g.setcell
    if percentage < 1 then percentage = 1 end
    if percentage > 100 then percentage = 100 end
    local sel = g.getselrect()
    if #sel > 0 then
        RememberCurrentState()
        g.clear(0)
        for y = sel[2], sel[2] + sel[4] - 1 do
            for x = sel[1], sel[1] + sel[3] - 1 do
                if rand(0,99) < percentage then
                    setcell(x, y, rand(1, maxstate))
                end
            end
        end
        Update()
    end
end
This is based on RandomFill and RandomPattern from NewCA.lua. I guess I'm not supposed to, but it calls RememberCurrentState because if it doesn't then there's no Undo history for successive random fills. What I can't do is set dirty = true, so there's no warning on Exit or New Pattern if the pattern is not already dirty for some other reason.

I've also been considering how to implement pattern rotation and flipping in a way that operates on the partitions of each cell (In the same way that Lifeviewer does). This seems doable for selections (with the same caveats as for RandomFill above) and it may even be possible to call the original editing functions and just update the states in PCA.lua. But for Copy and Paste I can't see how it will be possible to update states if the Paste is rotated/flipped because the pastecells table is inaccessible. Any ideas on how to make this work?

Thanks for taking the time to read through all this,

Arie.
The 5S project (Smallest Spaceships Supporting Specific Speeds) is now maintained by AforAmpere. The latest collection is hosted on GitHub and contains well over 1,000,000 spaceships.

Semi-active here - recovering from a severe case of LWTDS.

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

Re: NewCA.lua

Post by Andrew » October 12th, 2019, 7:22 pm

Thanks for the feedback Arie. I've uploaded a new version of NewCA.lua to my website:
http://www.trevorrow.com/golly/NewCA.lua

Replace the old version in Scripts/Lua/gplus and give it a try. It has the following changes:

* Fixes the bug in RandomPattern (using a slightly simpler solution).

* CheckRule converts wd, ht and numstates to integers.

* Documents more functions in the help: GetDensity, GetGenCount, GetStepSize, SetDensity, SetStepSize.

* Mentions that a startup script called appdir/My-scripts/SCRIPT_NAME-start.lua will be called automatically (e. no need to select it via "File -> Set Startup Script...").

* The biggest change is that *all* of the variables declared at the top are now global, so your RandomFill function can simply set dirty = true after calling RememberCurrentState(), and you now have access to pastecells, pasteht, pastewd, etc so you can redefine FlipPaste and RotatePaste to do whatever you like. This is a somewhat dangerous change so I've added a note of caution at the end of the "Script functions" section.

I've also uploaded a version of oscar.lua that works with most scripts based on NewCA.lua:
http://www.trevorrow.com/golly/NewCA-oscar.lua
The mechanism to change and show the Files directory via the startup script is nice, but when the user CA is quit and the original Files directory is restored the open/close state of all the subfolders is lost.
Unfortunately I can't find any way to avoid that. The best solution would be to just have g.setoption("showfiles",1) in your startup script but don't call g.setdir. That way NewCA.lua won't change the state of your files panel when it exits.
Use Glu to explore CA rules on non-periodic tilings: DominoLife and HatLife

Post Reply