Probably should have clarified: this would only apply to rules already invariant under black-white reversal.
Script request thread
Re: Script request thread
Help wanted: How can we accurately notate any 1D replicator?
-
- Posts: 130
- Joined: January 26th, 2021, 12:19 am
Re: Script request thread
Would anyone mind writing a spaceship collision stdin script for INT rules? It would take an RLE, a rule, the number of spaceships to collide, and maybe a symmetry as inputs, preferably upon compilation, and would generate a random (preferably valid) n-spaceship soup when run. It should at least be able to determine whether a ship's slope is orthogonal or diagonal (oblique slopes would be nice as well), but having the slope as input is acceptable as well.
I wrote a stdin script that generates random soups of a provided number of a given spaceship. It works for all (non-B0) spaceships in the INT rulespace!
A Multistate INT notation + script.
A Multistate INT notation + script.
Re: Script request thread
gencols, if that's what you're asking for.Cyclotrons wrote: ↑August 25th, 2021, 12:12 pmWould anyone mind writing a spaceship collision stdin script for INT rules?
\sum_{n=1}^\infty H_n/n^2 = \zeta(3)
How much of current CA technology can I redevelop "on a desert island"?
How much of current CA technology can I redevelop "on a desert island"?
Re: Script request thread
I think Paul Tooke once posted about changing gencols' rule.
\sum_{n=1}^\infty H_n/n^2 = \zeta(3)
How much of current CA technology can I redevelop "on a desert island"?
How much of current CA technology can I redevelop "on a desert island"?
Re: Script request thread
Indeed, Paul Tooke's modification allows INT rules using Hensel notation. You don't need to follow the steps in the first post. Just download the attached .zip file.
After compiling, I tested it with tlife (B3/S2-i34q). I tried collisions between a T-ship and a glider with a few filter options to look for collisions that resulted in one of the three small spaceships. Here's what I did:
First I added two files:
t-W.life:
Code: Select all
.*
**
.*
Code: Select all
*!*.*!**!
..*!*.*!.**!
Code: Select all
./gencols -rule B3/S2-i34q -pat t-W.life g-SW-SE.list -nph 4 -tc 10 14 -gen 300 -leq 8 -filt ag | ./makematrix > gt.life
Code: Select all
x = 459, y = 60, rule = B3/S2-i34q
5bo52bo42bo51bo52bo44bo54bobo41bo50bo49bo$5bobo48b2o42bo51bo52bo44bo
55b2o43b2o49bo49bo$5b2o50b2o41b3o49b3o50b3o42b3o54bo42b2o48b3o47b3o$
360bo$359b2o$51bo308bo$bo48b2o149bo99bo$2o49bo49bo49bo48b2o98b2o104bo$
bo98b2o48b2o49bo49bo49bo103b2o51bo$101bo49bo98b2o154bo50b2o$251bo206bo
40$obo47bobo$b2o48b2o$bo49bo$10bo$9b2o$10bo2$59bo$58b2o$59bo!
To get at least some sense of what the arguments do, consult the Arguments.Explanation file from the original release of gencols. I have copied this file here for convenience:
Code: Select all
The life collision search program "gencols" takes all of its input from
command-line arguments and from files specified in this arguments.
For examples of its use, see the file "Examples", which is also an
executable C-shell script that will produce files suitable for viewing
with Xlife.
Arguments for basic two-object collisions:
-----------------------------------------
The term "product" denotes the pattern that exists after the collision.
-pat <file1> <file2> :
file1 contains a pattern or a list of patterns to try as pattern 1
file2 contains a pattern or a list of patterns to try as pattern 2
The format of a single pattern is either a simple character map in
which '.' is dead and '*' is alive, or else a list of cell coordinates.
A list of patterns contains one pattern per line, stored as character
maps in which '!' is equivalent to a carriage return.
-nph #phases :
Try phase differences of 0,...,#phases-1.
A phase difference of k means that pattern 2 has been generated
k steps, while pattern 1 has been left in its initial form.
-tc #gen1 #gen2:
First collision occurs in range generation #gen1 to generation #gen2.
Note: the patterns are considered to be in generation 1 initially.
(A "collision" is an event such that there exists a single cell with
neighbors both in pattern 1 and in pattern 2. Thus, there are instances
in which patterns "collide" but do not affect each other. These can
be selected for output, and are actually useful for finding objects that
pass close to each other.)
-gen #gen :
Simulate collision to find product at generation #gen.
Pattern-deletion options:
------------------------
-del1 :
Attempt to delete pattern 1 from product. Either it will be
removed from the product or failure will be flagged.
-del2 :
Attempt to delete pattern 2 from product. Either it will be
removed from the product or failure will be flagged.
Special-purpose options:
-----------------------
The options below require some analysis of the patterns that will be collided.
-test1 <file>:
Attempt to delete pattern in file from product. Either it will be
removed from the product or failure will be flagged. See example:
"# lwss spark converts b-heptomino into p20 puffer engine"
-test2 <file>:
Attempt to delete pattern in file from product. Also match the phase of
this pattern with pattern 2. Either it will be removed from the
product or failure will be flagged.
Note: -test1 and -test2 will only succeed if test pattern is located at
the same translation position given in specified file.
-nosynch :
Normally when a pattern is to be deleted with -del1, -del2, -test1,
or -test2, it is generated alone to match the final generation of
the product to be tested. The -nosynch option eliminates this
synchronization step, which can destroy an unstablized oscillator
such as a queenbee shuttle. As a result, the number given for the
-gen option must be 1+p, where p is the period of the resulting
stabilized oscillator. (Used in examples that stabilize one end of a
shuttle.)
-genafter #steps :
Generate product for #steps steps after attempting deletions.
The result will be the product tested in the output filters.
May sometimes help to eliminate sparks and allow idenitification
of gliders, spaceships, etc.
Output filters:
--------------
-leq #cells
Only output products with population <= #cells
-geq #cells
Only output products with population >= #cells
-filt <filterstring>
Select products according to filter string, as follows:
A particular selection criterion is activated by including the
corresponding character from the table below:
p: PERIODIC (low-period oscillator or spaceship)
a: APERIODIC (no periodicity or too high to detect)
1: PERIOD1 (still-life)
2: PERIOD2 (period-2 oscillator)
3: PERIOD3 (period-3 oscillator)
4: PERIOD4 (period-4 oscillator or spaceship)
g: GLIDER (glider or several in same direction)
s: SPACESHIP (spaceship or several in same direction)
n: NOINTERACTION (patterns do not affect each other)
f: FAILURE (deletion failed assumes -del# or -test#)
For example:
-filt p (output periodic products)
-filt a (output aperiodic products)
-filt 12 (output still-life and period-2 products)
-filt gs (output gliders and spaceships)
-filt n (output collisions that come close and pass by)
-filt ap (output collisions in which the patterns
affect each other, and deletions succeed)
-Matthias Merzenich
Re: Script request thread
You mean one of (two small spaceships and a big p160 RRO) right?
\sum_{n=1}^\infty H_n/n^2 = \zeta(3)
How much of current CA technology can I redevelop "on a desert island"?
How much of current CA technology can I redevelop "on a desert island"?
Re: Script request thread
No, I was looking for any of the 3 small ships, and I was not looking for the p160 oscillator. The "-leq 8" filter was meant to catch the non-glider c/4 diagonal ship, as its maximum population is 8. the "-filt ag" filter was meant to eliminate low-period (less than or equal to 4) constellations. I don't see an easy way to avoid finding the p160 without also potentially missing some collisions that produce a small spaceship.
-Matthias Merzenich
Re: Script request thread
Here's a Lua script that determines the apgcode of a given pattern. No support for linear growth yet, and I don't plan on it because I'm planning a bigger script involving these functions soon. Let me know if there are any obvious improvements or glaringly obvious bugs, I tried it out on the 7 engine Cordership and it was admittedly quite slow for that, but for general purpose small patterns it shouldn't be too bad.
EDIT: Added further comments, switched to getstring to allow user to copy output easier.
EDIT: Added further comments, switched to getstring to allow user to copy output easier.
Code: Select all
--Script by dani, Aug 31 2021
--This script determines the canonical apgcode of a pattern. To use, create a blank layer with the object you want to get the apgcode of and run the script.
--Make sure the object you are running is in a fully evolved form and not a predecessor.
--You can copy the output by hitting Ctrl-C on the message box.
--There is currently a bug where if you undo after running the script, the selection used by the script reappears. You can fix this by deselecting after running the script.
local g = golly()
function pattern_to_apgcode() --Generates an apgcode of a pattern in its current orientation
local box = g.getrect()
local letters = "0123456789abcdefghijklmnopqrstuvwxyz"
local apgcode = ""
local count = 0
for y = box[2], box[2] + box[4] - 1, 5 do
for x = box[1], box[1] + box[3] - 1 do
total = 1
for cell = 0, 4 do
total = total + 2^cell * g.getcell(x, y + cell)
end
if total ~= 1 then
if count > 0 then
for space = count, 1, -39 do
if space == 1 then
apgcode = apgcode .. "0"
elseif space == 2 then
apgcode = apgcode .. "w"
elseif space == 3 then
apgcode = apgcode .. "x"
elseif space > 38 then
apgcode = apgcode .. "yz"
else
apgcode = apgcode .. "y" .. string.sub(letters, space - 3, space - 3)
end
end
count = 0
end
apgcode = apgcode .. string.sub(letters, total, total)
else
count = count + 1
end
end
apgcode = apgcode .. "z"
count = 0
end
return string.sub(apgcode, 1, -2) --Remove final z
end
function canonicalize_apgcode() --Generates a "canonical" apgcode using pattern_to_apgcode; having the shortest length and alphabetically earliest string. Also adds header
local header
local old = g.getcells(g.getrect())
local hashes = {}
local period = 0
--Determine period
while true do
local hash = g.hash(g.getrect())
if hashes[hash] then
break
end
hashes[hash] = true
period = period + 1
g.run(1)
end
g.putcells(old, 0, 0, 1, 0, 0, 1, "xor") --XOR pattern to see if it moved
--Determine header
if period == 1 then
header = "xs" .. #old // 2
elseif tonumber(g.getpop()) == 0 then
header = "xp" .. period
else
header = "xq" .. period
end
g.reset()
--Determine canonical apgcode. This might actually be able to be combined with the determine period loop but I don't see an obvious way to do that
local apgcodes = {}
local minimum_length = string.len(pattern_to_apgcode())
for step = 0, period - 1 do
g.select(g.getrect())
for flip = 0, 1 do
for rot = 0, 3 do
local apgcode = pattern_to_apgcode()
local length = string.len(apgcode)
if length == minimum_length then
table.insert(apgcodes, apgcode)
elseif length < minimum_length then
apgcodes = {apgcode}
minimum_length = length
end
g.rotate(0)
end
g.flip(0)
end
g.run(1)
end
table.sort(apgcodes)
g.reset()
g.select({})
return header .. "_" .. apgcodes[1]
end
if g.empty() then
g.exit("No pattern provided.")
end
g.getstring("Canonical apgcode:", canonicalize_apgcode())
-
- Posts: 130
- Joined: January 26th, 2021, 12:19 am
Re: Script request thread
I decided to do it myself instead.Cyclotrons wrote: ↑August 25th, 2021, 12:12 pmWould anyone mind writing a spaceship collision stdin script for INT rules? It would take an RLE, a rule, the number of spaceships to collide, and maybe a symmetry as inputs, preferably upon compilation, and would generate a random (preferably valid) n-spaceship soup when run. It should at least be able to determine whether a ship's slope is orthogonal or diagonal (oblique slopes would be nice as well), but having the slope as input is acceptable as well.
Compile it with the line g++ -o shipcolls shipcolls.cpp -std=c++11 -O3 -Ofast -flto -march=native
Pipe it into apgluxe by running it like so:
./shipcolls -g '(insert RLE of your spaceship here)' -r (insert rule the spaceship is from here) -n (number of ships to collide here) -t 0 | ./apgluxe <normal provided arguments> --symmetry (symmetry name containing 'stdin' here) -t 0 - L 0
Notes:
- For shipcolls, -t is the argument that sets how many soups to generate. Setting it to 0 runs it indefinitely.
- For apgluxe, -t is the argument that sets whether or not testing mode is enabled. If it is, the haul won't be uploaded to catagolue. If logging (-L) is enabled, a log file for the haul will be created locally. For stdin searches, both are enabled by default. Note that older and/or hacked versions of apgsearch may fail to provide sample soup RLEs for a stdin haul, so it is recommended that you run a small test (by setting -t 1 and -L 1 or not including the arguments at all) to be sure that a sample soup is actually being provided before uploading to catagolue.
- The | symbol indicates that console output from the program preceding it is being redirected to the program following it. Run standalone, shipcolls will print directly to the console.
- Make sure that the RLE is enclosed by single quotes (' '). The RLE will not be interpreted correctly if you don't.
- You may notice that the output RLE headers are incorrect. While the headers need to be there for apgsearch to interpret them correctly, it doesn't actually care about what they say, so a standard template header can be used.
Code: Select all
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <new>
#include <string.h>
#include <string>
#include <vector>
#include <time.h>
#include <random>
using namespace std;
string intlookup[51][11] = { {"0","f","f", "00000000", "00000000", "00000000", "00000000", "00000000", "00000000", "00000000", "00000000"},{"1c","f","f", "10000000", "00000100", "00000001", "00100000", "00000001", "10000000", "00100000", "00000100"},{"1e","f","f", "00010000", "00000010", "00001000", "01000000", "00000010", "01000000", "00001000", "00010000"},{"2c","f","f", "10000100", "00000101", "00100001", "10100000", "00000101", "10100000", "00100001", "10000100"},{"2e","f","f", "01010000", "00010010", "00001010", "01001000", "00001010", "01010000", "01001000", "00010010"},{"2k","f","f", "10000010", "00001100", "01000001", "00110000", "00010001", "10001000", "00100010", "01000100"},{"2a","f","f", "10010000", "00000110", "00001001", "01100000", "00000011", "11000000", "00101000", "00010100"},{"2i","f","f","01000010","00011000","01000010","00011000","01000010","00011000","01000010","00011000"},{"2n","f","f", "10000001", "00100100", "10000001", "00100100", "10000001", "10000001", "00100100", "00100100"},{"3c","f","f", "10100100", "10000101", "00100101", "10100001", "00100101", "10100100", "10100001", "10000101"},{"3e","f","f", "01010010", "00011010", "01001010", "01011000", "00011010", "01011000", "01001010", "01010010"},{"3k","f","f", "10001010", "01001100", "01010001", "00110010", "01010001", "10001010", "00110010", "01001100"},{"3a","f","f", "11010000", "00010110", "00001011", "01101000", "00001011", "11010000", "01101000", "00010110"},{"3i","f","f", "11100000", "10010100", "00000111", "00101001", "00101001", "10010100", "11100000", "00000111"},{"3n","f","f", "11000100", "00010101", "00100011", "10101000", "00001101", "10110000", "01100001", "10000110"},{"3y","f","f", "10001100", "01000101", "00110001", "10100010", "01000101", "10100010", "00110001", "10001100"},{"3q","f","f", "10010001", "00100110", "10001001", "01100100", "10000011", "11000001", "00101100", "00110100"},{"3j","f","f", "11001000", "01010100", "00010011", "00101010", "01001001", "10010010", "01110000", "00001110"},{"3r","f","f", "11000010", "00011100", "01000011", "00111000", "00011001", "10011000", "01100010", "01000110"},{"4c","f","f", "10100101", "10100101", "10100101", "10100101", "10100101", "10100101", "10100101", "10100101"},{"4e","f","f", "01011010", "01011010", "01011010", "01011010", "01011010", "01011010", "01011010", "01011010"},{"4k","f","f", "10110010", "10001110", "01001101", "01110001", "00110011", "11001100", "10101010", "01010101"},{"4a","f","f", "11110000", "10010110", "00001111", "01101001", "00101011", "11010100", "11101000", "00010111"},{"4i","f","f", "11000110", "00011101", "01100011", "10111000", "00011101", "10111000", "01100011", "11000110"},{"4n","f","f", "11100100", "10010101", "00100111", "10101001", "00101101", "10110100", "11100001", "10000111"},{"4y","f","f", "10101100", "11000101", "00110101", "10100011", "01100101", "10100110", "10110001", "10001101"},{"4q","f","f", "11010001", "00110110", "10001011", "01101100", "10001011", "11010001", "01101100", "00110110"},{"4j","f","f", "11001010", "01011100", "01010011", "00111010", "01011001", "10011010", "01110010", "01001110"},{"4r","f","f", "11010010", "00011110", "01001011", "01111000", "00011011", "11011000", "01101010", "01010110"},{"4t","f","f", "11100010", "10011100", "01000111", "00111001", "00111001", "10011100", "11100010", "01000111"},{"4w","f","f", "11001001", "01110100", "10010011", "00101110", "11001001", "10010011", "01110100", "00101110"},{"4z","f","f", "10011001", "01100110", "10011001", "01100110", "11000011", "11000011", "00111100", "00111100"},{"5c","f","f", "01111010", "11011010", "01011110", "01011011", "01111010", "01011110", "11011010", "01011011"},{"5e","f","f", "10101101", "11100101", "10110101", "10100111", "11100101", "10100111", "10110101", "10101101"},{"5k","f","f", "01110101", "10110011", "10101110", "11001101", "10101110", "01110101", "11001101", "10110011"},{"5a","f","f", "00101111", "11101001", "11110100", "10010111", "11110100", "00101111", "10010111", "11101001"},{"5i","f","f", "00011111", "01101011", "11111000", "11010110", "11010110", "01101011", "00011111", "11111000"},{"5n","f","f", "00111011", "11101010", "11011100", "01010111", "11110010", "01001111", "10011110", "01111001"},{"5y","f","f", "01110011", "10111010", "11001110", "01011101", "10111010", "01011101", "11001110", "01110011"},{"5q","f","f", "01101110", "11011001", "01110110", "10011011", "01111100", "00111110", "11010011", "11001011"},{"5j","f","f", "00110111", "10101011", "11101100", "11010101", "10110110", "01101101", "10001111", "11110001"},{"5r","f","f", "00111101", "11100011", "10111100", "11000111", "11100110", "01100111", "10011101", "10111001"},{"6c","f","f", "01111011", "11111010", "11011110", "01011111", "11111010", "01011111", "11011110", "01111011"},{"6e","f","f", "10101111", "11101101", "11110101", "10110111", "11110101", "10101111", "10110111", "11101101"},{"6k","f","f", "01111101", "11110011", "10111110", "11001111", "11101110", "01110111", "11011101", "10111011"},{"6a","f","f", "01101111", "11111001", "11110110", "10011111", "11111100", "00111111", "11010111", "11101011"},{"6i","f","f", "11100111", "10111101", "11100111", "10111101", "10111101", "10111101", "11100111", "11100111"},{"6n","f","f", "01111110", "11011011", "01111110", "11011011", "01111110", "01111110", "11011011", "11011011"},{"7c","f","f", "01111111", "11111011", "11111110", "11011111", "11111110", "01111111", "11011111", "11111011"},{"7e","f","f", "11101111", "11111101", "11110111", "10111111", "11111101", "10111111", "11110111", "11101111"},{"8","f","f", "11111111", "11111111", "11111111", "11111111", "11111111", "11111111", "11111111", "11111111"} };
mt19937 rng;
//sets the rule by parsing the provided rulestring and updating intlookup
void set_rule(string rulestring)
{
int bors = 1; //birth is 1, survival is 2
string currentNum = "";
string currentChar = "";
bool setToFalse = false;
string nums = "012345678";
string chars = "cekainyqjrtwz";
for (int i = 0; i < rulestring.length(); i++)
{
if (rulestring[i] == '8')
{
intlookup[50][bors] = "t";
}
else if (nums.find(rulestring[i]) >= 0 && nums.find(rulestring[i]) < 9)
{
currentNum = rulestring.substr(i, 1);
setToFalse = false;
if (rulestring[i + 1] == '-')
{
setToFalse = true;
for (int j = 0; j < 51; j++)
{
if (intlookup[j][0][0] == currentNum[0])
{
intlookup[j][bors] = "t";
}
}
}
else if ((nums.find(rulestring[i + 1]) > 0 && nums.find(rulestring[i + 1]) < 9) || rulestring[i+1] == '/' || rulestring[i+1] == 's' || rulestring[i + 1] == 'S' || rulestring[i + 1] == '\0')
{
for (int j = 0; j < 51; j++)
{
if (intlookup[j][0][0] == currentNum[0])
{
intlookup[j][bors] = "t";
}
}
}
}
else if (chars.find(rulestring[i]) >= 0 && chars.find(rulestring[i]) < 13)
{
currentChar = rulestring.substr(i, 1);
for (int j = 0; j < 51; j++)
{
if (strcmp(intlookup[j][0].c_str(), (currentNum + currentChar).c_str()) == 0)
{
if (setToFalse)
{
intlookup[j][bors] = "f";
}
else
{
intlookup[j][bors] = "t";
}
}
}
}
else if (rulestring[i] == 'S' || rulestring[i] == 's')
{
bors = 2;
}
}
}
//converts a provided rle to a cell list (note: cell list format is {x0,y0,x1,y1...})
void rle_to_clist(vector<int>& target, string rle)
{
int xpos = 0;
int ypos = 0;
int begin = 0;
int end = 0;
string currentstr = "";
int len = 0;
while (end != -1)
{
end = rle.find_first_of("bo$", begin) + 1;
if (end == 0)
{
end = -1;
}
if (end != -1)
{
currentstr = rle.substr(begin, end - begin);
len = currentstr.length();
begin = end;
}
if (len > 1 && end != -1)
{
if (strcmp(currentstr.substr(len - 1, len).c_str(), "o") == 0)
{
for (int i = 0; i < atoi(currentstr.substr(0, len - 1).c_str()); i++)
{
target.push_back(xpos + i);
target.push_back(ypos);
}
}
if (strcmp(currentstr.substr(len - 1, len).c_str(), "$") == 0)
{
ypos = ypos + atoi(currentstr.substr(0, len - 1).c_str());
xpos = 0;
}
else
{
xpos = xpos + atoi(currentstr.substr(0, len - 1).c_str());
}
}
else if (end != -1)
{
if (strcmp(currentstr.c_str(), "o") == 0)
{
target.push_back(xpos);
target.push_back(ypos);
}
if (strcmp(currentstr.c_str(), "$") == 0)
{
ypos++;
xpos = 0;
}
else
{
xpos++;
}
}
}
}
//checks if the cell at the provided coordinates is in a cell list
string get_state(int xpos, int ypos, vector<int>& clist)
{
for (int i = 0; i < clist.size(); i = i + 2)
{
if (clist[i] == xpos && clist[i + 1] == ypos)
{
return "1";
}
}
return "0";
}
//takes a cell list as an argument and returns another cell list advanced by one generation in the rule
vector<int> evolve_clist(vector<int> current)
{
vector<int> newclist;
int minx = current[0];
int miny = current[1];
int maxx = current[0];
int maxy = current[1];
string currentNeighborhood = "";
for (int i = 0; i < current.size(); i = i + 2)
{
if (current[i] < minx)
{
minx = current[i];
}
else if (current[i] > maxx)
{
maxx = current[i];
}
if (current[i + 1] < miny)
{
miny = current[i + 1];
}
else if (current[i + 1] > maxy)
{
maxy = current[i + 1];
}
}
for (int y = miny - 1; y <= maxy + 1; y++)
{
for (int x = minx - 1; x <= maxx + 1; x++)
{
currentNeighborhood = get_state(x - 1, y - 1, current) + get_state(x, y - 1, current) + get_state(x + 1, y - 1, current) + get_state(x - 1, y, current) + get_state(x + 1, y, current) + get_state(x - 1, y + 1, current) + get_state(x, y + 1, current) + get_state(x + 1, y + 1, current);
for (int i = 0; i < 51; i++)
{
if (strcmp(get_state(x, y, current).c_str(), "0") == 0 && strcmp(intlookup[i][1].c_str(), "t") == 0)
{
for (int j = 3; j < 11; j++)
{
if (strcmp(currentNeighborhood.c_str(), intlookup[i][j].c_str()) == 0)
{
newclist.push_back(x);
newclist.push_back(y);
break;
}
}
}
else if (strcmp(get_state(x, y, current).c_str(), "1") == 0 && strcmp(intlookup[i][2].c_str(), "t") == 0)
{
for (int j = 3; j < 11; j++)
{
if (strcmp(currentNeighborhood.c_str(), intlookup[i][j].c_str()) == 0)
{
newclist.push_back(x);
newclist.push_back(y);
break;
}
}
}
}
}
}
return newclist;
}
//checks if two cell lists are equivalent
bool equivalent(vector<int> current, vector<int> base, int &dx, int &dy)
{
if (current.size() != base.size())
{
return false;
}
vector<int> translated;
int diffx = current[0] - base[0];
int diffy = current[1] - base[1];
for (int i = 0; i < current.size(); i = i + 2)
{
translated.push_back(current[i] - diffx);
translated.push_back(current[i + 1] - diffy);
}
for (int i = 0; i < translated.size(); i++)
{
if (translated[i] != base[i])
{
return false;
}
}
dx = diffx;
dy = diffy;
return true;
}
//alters the provided cell list so that it's center is at (0,0)
void normalize(vector<int> &target)
{
int minx = target[0];
int miny = target[1];
int maxx = target[0];
int maxy = target[1];
for (int i = 0; i < target.size(); i = i + 2)
{
if (target[i] < minx)
{
minx = target[i];
}
else if (target[i] > maxx)
{
maxx = target[i];
}
if (target[i + 1] < miny)
{
miny = target[i + 1];
}
else if (target[i + 1] > maxy)
{
maxy = target[i + 1];
}
}
int centerx = (minx + maxx) / 2;
int centery = (miny + maxy) / 2;
for (int i = 0; i < target.size(); i = i + 2)
{
target[i] = target[i] - centerx;
target[i + 1] = target[i + 1] - centery;
}
}
//rotates a target cell list 90 degrees clockwise around (0,0)
void crot(vector<vector<int>> &target, int numRots)
{
int currentx = 0;
int currenty = 0;
for (int r = 0; r < numRots % 4; r++)
{
for (int j = 0; j < target.size(); j++)
{
for (int i = 0; i < target[j].size(); i = i + 2)
{
currentx = target[j][i];
currenty = target[j][i + 1];
target[j][i] = 0 - currenty;
target[j][i + 1] = currentx;
}
}
}
}
//reflects a target cell list either over the y-axis or over the x-axis
void refl(vector<vector<int>> &target, bool horizontal, bool vertical)
{
int h = 1;
int v = 1;
if (horizontal)
{
h = -1;
}
if (vertical)
{
v = -1;
}
for (int j = 0; j < target.size(); j++)
{
for (int i = 0; i < target[j].size(); i = i + 2)
{
target[j][i] = target[j][i] * h;
target[j][i + 1] = target[j][i + 1] * v;
}
}
}
//gets a range between 2 numbers (inclusive)
int rand_range(int minNum, int maxNum)
{
if (minNum == maxNum)
{
return minNum;
}
return rng() % (maxNum - minNum) + minNum;
}
//generates the parameters needed to place a glider
void generate_glider(int* target, int minDistance, int maxDistance, int displacementScale, int maxOffset, int gens, int dx, int dy)
{
//format: {x,y,xoffset,yoffset,gen}
int displacement;
int temp;
target[0] = rand_range(minDistance, maxDistance);
if (dx == 0 || dy == 0)
{
target[1] = rand_range(0 - (target[0] / displacementScale), target[0] / displacementScale);
}
else if (dx == dy)
{
target[1] = target[0];
displacement = rand_range(0 - (target[0] / displacementScale), target[0] / displacementScale);
target[0] = target[0] + displacement;
target[1] = target[1] - displacement;
}
else
{
target[1] = target[0] * 2;
displacement = rand_range(0 - (target[0] / displacementScale), target[0] / displacementScale);
target[0] = target[0] + displacement;
target[1] = target[1] - displacement * 2;
if (target[1] > maxDistance || target[1] < 0 - maxDistance)
{
target[0] = target[0] / 2;
target[1] = target[1] / 2;
}
}
if (target[0] > maxDistance || target[0] < 0 - maxDistance)
{
target[0] = maxDistance;
}
if (target[1] > maxDistance || target[1] < 0 - maxDistance)
{
target[1] = maxDistance;
}
if (rng() % 2 == 0)
{
target[0] = 0 - target[0];
}
if (rng() % 2 == 0)
{
target[1] = 0 - target[1];
}
for (int i = 0; i < rng() % 4; i++)
{
temp = target[0];
target[0] = 0 - target[1];
target[1] = temp;
}
target[2] = rand_range(0 - maxOffset, maxOffset);
target[3] = rand_range(0 - maxOffset, maxOffset);
target[4] = rng() % gens;
}
void glider_coords(int* glider, int* coords)
{
//format: {x0,y0,x1,y1...}
int currentpos = 0;
coords[0] = glider[0];
coords[1] = glider[1];
coords[2] = 0; coords[3] = 0; coords[4] = 0; coords[5] = 0; coords[6] = 0; coords[7] = 0;
currentpos = 2;
if (glider[2] > 0)
{
coords[currentpos] = glider[0] + 1;
coords[currentpos + 1] = glider[1];
currentpos = currentpos + 2;
}
else if (glider[2] < 0)
{
coords[currentpos] = glider[0] - 1;
coords[currentpos + 1] = glider[1];
currentpos = currentpos + 2;
}
if (glider[3] > 0)
{
coords[currentpos] = glider[0];
coords[currentpos + 1] = glider[1] + 1;
currentpos = currentpos + 2;
}
else if (glider[3] < 0)
{
coords[currentpos] = glider[0];
coords[currentpos + 1] = glider[1] - 1;
currentpos = currentpos + 2;
}
if (glider[2] > 0 && glider[3] > 0)
{
coords[currentpos] = glider[0] + 1;
coords[currentpos + 1] = glider[1] + 1;
}
else if (glider[2] > 0 && glider[3] < 0)
{
coords[currentpos] = glider[0] + 1;
coords[currentpos + 1] = glider[1] - 1;
}
else if (glider[2] < 0 && glider[3] < 0)
{
coords[currentpos] = glider[0] - 1;
coords[currentpos + 1] = glider[1] - 1;
}
else if (glider[2] < 0 && glider[3] > 0)
{
coords[currentpos] = glider[0] - 1;
coords[currentpos + 1] = glider[1] + 1;
}
}
int main(int argc, char* argv[])
{
rng.seed(time(NULL));
string gliderRLE = "null";
string rulestring = "null";
int numSoups = -1;
int minDistanceFromCenter = 1;
int maxDistanceFromCenter = 5;
int displacementScale = 2;
int numGliders = -1;
int maxGen = 1000;
bool displayHelp = false;
//parsing provided arguments
for (int i = 1; i < argc - 1; i++)
{
if (strcmp(argv[i], "-g") == 0)
{
gliderRLE = argv[i + 1];
}
else if (strcmp(argv[i], "-r") == 0)
{
rulestring = argv[i + 1];
}
else if (strcmp(argv[i], "-n") == 0)
{
numGliders = atoi(argv[i + 1]);
}
else if (strcmp(argv[i], "-t") == 0)
{
numSoups = atoi(argv[i + 1]);
}
else if (strcmp(argv[i], "-dmin") == 0)
{
minDistanceFromCenter = atoi(argv[i + 1]);
}
else if (strcmp(argv[i], "-dmax") == 0)
{
maxDistanceFromCenter = atoi(argv[i + 1]);
}
else if (strcmp(argv[i], "-dscale") == 0)
{
displacementScale = atoi(argv[i + 1]);
}
else if (strcmp(argv[i], "-gmax") == 0)
{
maxGen = atoi(argv[i + 1]);
}
else if (strcmp(argv[i], "-h") == 0)
{
cout << "This program generates soups composed of a provided spaceship and outputs an RLE of said soup." << endl;
cout << "Required arguments:" << endl;
cout << "\t-g: The RLE of the spaceship on every generation. The RLE must be headerless." << endl;
cout << "\t-r: The rule the spaceship is from. Make sure the input RLE is actually a glider in the input rule!" << endl;
cout << "\t-n: The number of spaceships to be in each soup." << endl;
cout << "\t-t: How many soups to output. If you're piping the output into apgsearch, you'll want to set this to 0, which will generate soups indefinitely." << endl;
cout << "Other arguments:" << endl;
cout << "\t-dmin: The minimum distance (measured in spaceships) from the center a ship can be. The default is 2, and it is recommended that it be left unchanged." << endl;
cout << "\t-dmax: The minimum distance (measured in spaceships) from the center a ship can be. The default is 5. Set this higher if you are testing a lot of spaceships." << endl;
cout << "\t-dscale: Used to calculate a spaceships displacement from the line all ships going in the same direction are placed on. Set this higher if you want ships to be less displaced. The default is 2." << endl;
cout << "\t-gmax: The number of generations the given pattern will be run to check periodicity before this program gives up and terminates. Only change this if your ship has a very high period! The default is 1000." << endl;
cout << "\t-h: Prints this message, then exits." << endl;
return 0;
}
}
//checking that all required arguments are passed
if (strcmp(gliderRLE.c_str(), "null") == 0)
{
cout << "You must enter an RLE! Bring up the help message using the argument '-h 1' for more information." << endl;
return 0;
return 0;
}
if (strcmp(rulestring.c_str(), "null") == 0)
{
cout << "You must enter a rule! Bring up the help message using the argument '-h 1' for more information." << endl;
return 0;
}
if (numGliders == -1)
{
cout << "You must enter the number of gliders to include in a soup! Bring up the help message using the argument '-h 1' for more information." << endl;
return 0;
}
if (numSoups == -1)
{
cout << "You must enter a number of soups to generate! Bring up the help message using the argument '-h 1' for more information." << endl;
return 0;
}
//some more input filtering
if (numGliders < -1)
{
cout << "You entered a negative value!" << endl;
return 0;
}
if (numSoups < -1)
{
cout << "You entered a negative value!" << endl;
return 0;
}
if (minDistanceFromCenter < 0)
{
cout << "You entered a negative value!" << endl;
return 0;
}
if (maxDistanceFromCenter < 0)
{
cout << "You entered a negative value!" << endl;
return 0;
}
if (displacementScale < 0)
{
cout << "You entered a negative value!" << endl;
return 0;
}
if (maxGen < 0)
{
cout << "You entered a negative value!" << endl;
return 0;
}
set_rule(rulestring);
//stuff to fully characterize the glider
vector<int> initClist;
vector<vector<int>> initGlider;
rle_to_clist(initClist, gliderRLE);
initGlider.push_back(initClist);
int dx;
int dy;
int tempcount = 0;
while (!equivalent(evolve_clist(initGlider.back()), initClist, dx, dy))
{
initGlider.push_back(evolve_clist(initGlider.back()));
tempcount++;
if (tempcount > maxGen)
{
cout << "Failed to detect periodicity in " << maxGen << " generations. This is (probably) not a spaceship." << endl;
return 0;
}
}
for (int i = 0; i < initGlider.size(); i++)
{
normalize(initGlider[i]);
}
if (dx == 0 && dy == 0)
{
cout << "This is not a spaceship!" << endl;
return 0;
}
//gets all rotations + reflections of glider
vector<vector<int>> nNW; //-1,-2 x>y,x<0,y<0,ax<ay
vector<vector<int>> nne; //1,-2 x>y,x>0,y<0,ax<ay
vector<vector<int>> NEe; //2,-1 x>y,x>0,y<0,ax>ay
vector<vector<int>> see; //2,1 x>y,x>0,y>0,ax>ay
vector<vector<int>> sSE; //1,2 x<y,x>0,y>0,ax<ay
vector<vector<int>> ssw; //-1,2 x<y,x<0,y>0,ax<ay
vector<vector<int>> SWw; //-2,1 x<y,x<0,y>0,ax>ay
vector<vector<int>> nww; //-2,-1 x<y,x<0,y<0,ax>ay
if (dx >= 0 && dy >= 0)
{
if (dx >= dy)
{
see = initGlider;
nNW = see;
crot(nNW, 1);
refl(nNW, false, true);
}
else if (dx < dy)
{
sSE = initGlider;
nNW = sSE;
crot(nNW, 2);
}
}
else if (dx >= 0 && dy < 0)
{
if (dx >= 0 - dy)
{
NEe = initGlider;
nNW = NEe;
crot(nNW, 3);
}
else if (dx < 0 - dy)
{
nne = initGlider;
nNW = nne;
refl(nNW, true, false);
}
}
else if (dx < 0 && dy < 0)
{
if (0 - dx >= 0 - dy)
{
nww = initGlider;
nNW = nww;
crot(nNW, 1);
refl(nNW, true, false);
}
else if (0 - dx < 0 - dy)
{
nNW = initGlider;
}
}
else if (dx < 0 && dy >= 0)
{
if (0 - dx >= dy)
{
SWw = initGlider;
nNW = SWw;
crot(nNW, 1);
}
else if (0 - dx < dy)
{
ssw = initGlider;
nNW = ssw;
refl(nNW, false, true);
}
}
NEe = nNW;
crot(NEe, 1);
sSE = nNW;
crot(sSE, 2);
SWw = nNW;
crot(SWw, 3);
nne = nNW;
refl(nne, true, false);
see = nne;
crot(see, 1);
ssw = nne;
crot(ssw, 2);
nww = nne;
crot(nww, 3);
//getting the glider's max span
int minx;
int miny;
int maxx;
int maxy;
int bigx = 0;
int bigy = 0;
for (int j = 0; j < initGlider.size(); j++)
{
minx = initGlider[j][0];
miny = initGlider[j][1];
maxx = initGlider[j][0];
maxy = initGlider[j][1];
for (int i = 0; i < initGlider[j].size(); i = i + 2)
{
if (initGlider[j][i] < minx)
{
minx = initGlider[j][i];
}
else if (initGlider[j][i] > maxx)
{
maxx = initGlider[j][i];
}
if (initGlider[j][i + 1] < miny)
{
miny = initGlider[j][i + 1];
}
else if (initGlider[j][i + 1] > maxy)
{
maxy = initGlider[j][i + 1];
}
}
if (maxx - minx > bigx)
{
bigx = maxx - minx;
}
if (maxy - miny > bigy)
{
bigy = maxy - miny;
}
}
int gliderSize = 0;
if (bigx > bigy)
{
gliderSize = bigx + 1;
}
else
{
gliderSize = bigy + 1;
}
//getting absolute values of dx and dy
if (dx < 0)
{
dx = 0 - dx;
}
if (dy < 0)
{
dy = 0 - dy;
}
//some final initialization before the main loop
bool** mainSoup = new bool* [(gliderSize + 2) * 2 * maxDistanceFromCenter + 2 * (gliderSize + 2)];
for (int i = 0; i < (gliderSize + 2) * 2 * maxDistanceFromCenter + 2 * (gliderSize + 2); i++)
{
mainSoup[i] = new bool[(gliderSize + 2) * 2 * maxDistanceFromCenter + 2 * (gliderSize + 2)];
}
int* takenCoords = new int[numGliders * 4 * 2];
int* gliderList = new int[numGliders * 5];
int tempGlider[5];
int tempCoords[8];
int offset = gliderSize / 2;
int gliderGens = initGlider.size();
int gliderCount;
bool isTaken;
vector<vector<int>>* gptr = &nNW;
string rle;
string temprle;
int currentNum;
char currentChar;
int minxsoup;
bool hasHit;
int zeroPoint = ((gliderSize + 2) * 2 * maxDistanceFromCenter + 2 * (gliderSize + 2)) / 2;
int soupCount = 0;
while (soupCount < numSoups || numSoups == 0)
{
//resetting some values...
for (int y = 0; y < (gliderSize + 2) * 2 * maxDistanceFromCenter + 2 * (gliderSize + 2); y++)
{
for (int x = 0; x < (gliderSize + 2) * 2 * maxDistanceFromCenter + 2 * (gliderSize + 2); x++)
{
mainSoup[y][x] = false;
}
}
for (int i = 0; i < numGliders * 4 * 2; i++)
{
takenCoords[i] = 0;
}
for (int i = 0; i < numGliders * 5; i++)
{
gliderList[i] = 0;
}
//generates glider positions, does basic validation
gliderCount = 0;
while (gliderCount < numGliders)
{
isTaken = false;
generate_glider(tempGlider, minDistanceFromCenter, maxDistanceFromCenter, displacementScale, offset, gliderGens, dx, dy);
glider_coords(tempGlider, tempCoords);
for (int i = 0; i < numGliders * 4 * 2; i = i + 2)
{
if (tempCoords[0] == takenCoords[i] && tempCoords[1] == takenCoords[i + 1])
{
isTaken = true;
break;
}
}
if (isTaken)
{
continue;
}
for (int i = 0; i < 8; i++)
{
takenCoords[gliderCount * 2 * 4 + i] = tempCoords[i];
}
for (int i = 0; i < 5; i++)
{
gliderList[gliderCount * 5 + i] = tempGlider[i];
}
gliderCount++;
}
//places gliders on a grid
for (int i = 0; i < numGliders * 5; i = i + 5)
{
if (gliderList[i] >= 0 && gliderList[i + 1] >= 0)
{
if (gliderList[i] >= gliderList[i + 1])
{
gptr = &nww;
//cout << gliderList[i] << " " << gliderList[i + 1] << endl;
}
else if (gliderList[i] < gliderList[i + 1])
{
gptr = &nNW;
//cout << gliderList[i] << " " << gliderList[i + 1] << endl;
}
}
else if (gliderList[i] >= 0 && gliderList[i + 1] < 0)
{
if (gliderList[i] >= 0 - gliderList[i + 1])
{
gptr = &SWw;
//cout << gliderList[i] << " " << gliderList[i + 1] << endl;
}
else if (gliderList[i] < 0 - gliderList[i + 1])
{
gptr = &ssw;
//cout << gliderList[i] << " " << gliderList[i + 1] << endl;
}
}
else if (gliderList[i] < 0 && gliderList[i + 1] < 0)
{
if (0 - gliderList[i] >= 0 - gliderList[i + 1])
{
gptr = &see;
//cout << gliderList[i] << " " << gliderList[i + 1] << endl;
}
else if (0 - gliderList[i] < 0 - gliderList[i + 1])
{
gptr = &sSE;
//cout << gliderList[i] << " " << gliderList[i + 1] << endl;
}
}
else if (gliderList[i] < 0 && gliderList[i + 1] >= 0)
{
if (0 - gliderList[i] >= gliderList[i + 1])
{
gptr = &NEe;
//cout << gliderList[i] << " " << gliderList[i + 1] << endl;
}
else if (0 - gliderList[i] < gliderList[i + 1])
{
gptr = &nne;
//cout << gliderList[i] << " " << gliderList[i + 1] << endl;
}
}
for (int j = 0; j < gptr[0][gliderList[i + 4]].size(); j = j + 2)
{
//ypos = cell y on gen gliderList[i+4] in position [j+1] + gliderbox * glider y pos + y offset
mainSoup[(gptr[0][gliderList[i + 4]][j + 1] + (gliderSize + 2) * gliderList[i + 1] + gliderList[i + 3]) + zeroPoint][(gptr[0][gliderList[i + 4]][j] + (gliderSize + 2) * gliderList[i] + gliderList[i + 2]) + zeroPoint] = true;
}
}
temprle = "";
rle = "";
minxsoup = (gliderSize + 2) * 2 * maxDistanceFromCenter + 2 * (gliderSize + 2);
for (int y = 0; y < (gliderSize + 2) * 2 * maxDistanceFromCenter + 2 * (gliderSize + 2); y++)
{
for (int x = 0; x < (gliderSize + 2) * 2 * maxDistanceFromCenter + 2 * (gliderSize + 2); x++)
{
if (mainSoup[y][x] && x < minxsoup)
{
minxsoup = x;
}
}
}
for (int y = (gliderSize + 2) * 2 * maxDistanceFromCenter + 2 * (gliderSize + 2) - 1; y >= 0; y--)
{
hasHit = false;
temprle = "$" + temprle;
for (int x = (gliderSize + 2) * 2 * maxDistanceFromCenter + 2 * (gliderSize + 2) - 1; x >= minxsoup; x--)
{
if (mainSoup[y][x])
{
hasHit = true;
temprle = "o" + temprle;
}
else if (hasHit)
{
temprle = "b" + temprle;
}
}
}
currentChar = 'h';
currentNum = 1;
for (int i = 0; i <= temprle.length(); i++)
{
if (temprle[i] == currentChar)
{
currentNum++;
}
else
{
if (currentNum != 1)
{
rle = rle + to_string(currentNum);
}
if (currentChar != 'h')
{
rle = rle + currentChar;
}
currentChar = temprle[i];
currentNum = 1;
}
}
cout << "x = 0, y = 0, rule = B3/S23\n" << rle << "!" << endl;
soupCount++;
}
//cleanup
for (int i = 0; i < (gliderSize + 2) * 2 * maxDistanceFromCenter + 2 * (gliderSize + 2); i++)
{
delete[] mainSoup[i];
}
delete[] mainSoup;
delete[] takenCoords;
delete[] gliderList;
}
I wrote a stdin script that generates random soups of a provided number of a given spaceship. It works for all (non-B0) spaceships in the INT rulespace!
A Multistate INT notation + script.
A Multistate INT notation + script.
-
- Posts: 2200
- Joined: August 5th, 2016, 10:27 am
- Location: 拆哪!I repeat, CHINA! (a.k.a. 种花家)
- Contact:
Re: Script request thread
A rookie question: how is the compiling done for that modification? On the regular Windows Command Prompt with both gcc and g++, the following command as I would expect threw a lot of errors about undefined reference to various names.Sokwe wrote: ↑August 27th, 2021, 9:37 pmIndeed, Paul Tooke's modification allows INT rules using Hensel notation. You don't need to follow the steps in the first post. Just download the attached .zip file.
After compiling...
Code: Select all
gcc -o gencols gencols.c -O3 -Ofast -flto -march=native
熠熠种花 - Glimmering Garden
Harvest Moon
2-engine p45 gliderless HWSS gun
Small p2070 glider gun
Forgive me if I withhold my enthusiasm.
Harvest Moon
2-engine p45 gliderless HWSS gun
Small p2070 glider gun
Forgive me if I withhold my enthusiasm.
-
- Posts: 130
- Joined: January 26th, 2021, 12:19 am
Re: Script request thread
I was using Ubuntu for compilation. Try compiling it without the flags and see if it works (note that it will run a lot slower without them).GUYTU6J wrote: ↑September 3rd, 2021, 5:24 amA rookie question: how is the compiling done for that modification? On the regular Windows Command Prompt with both gcc and g++, the following command as I would expect threw a lot of errors about undefined reference to various names.Sokwe wrote: ↑August 27th, 2021, 9:37 pmIndeed, Paul Tooke's modification allows INT rules using Hensel notation. You don't need to follow the steps in the first post. Just download the attached .zip file.
After compiling...Code: Select all
gcc -o gencols gencols.c -O3 -Ofast -flto -march=native
I wrote a stdin script that generates random soups of a provided number of a given spaceship. It works for all (non-B0) spaceships in the INT rulespace!
A Multistate INT notation + script.
A Multistate INT notation + script.
-
- Posts: 2200
- Joined: August 5th, 2016, 10:27 am
- Location: 拆哪!I repeat, CHINA! (a.k.a. 种花家)
- Contact:
Re: Script request thread
I have installed Ubuntu 16.04 LTS as my WSL, but I'm not familiar with it and I cannot either 1) find the default location of files downloaded by git clone (such as apgmera) or 2) access other locations apart from default (such as the gencols file on disk D:; it won't even find D: if I input it directly). So I used Command Prompt instead of that Ubuntu for compiling.Cyclotrons wrote: ↑September 3rd, 2021, 12:09 pmI was using Ubuntu for compilation. Try compiling it without the flags and see if it works (note that it will run a lot slower without them).GUYTU6J wrote: ↑September 3rd, 2021, 5:24 amA rookie question: how is the compiling done for that [gencols] modification? On the regular Windows Command Prompt with both gcc and g++, the following command as I would expect threw a lot of errors about undefined reference to various names.Code: Select all
gcc -o gencols gencols.c -O3 -Ofast -flto -march=native
Note that my original question was for the gencols — which has a mysterious Makefile that I don't know how to run — and not your new program, but I may ask a relevant question to you by the way: when generating spaceship collisions, will the script attempt to reduce the number of wasted spaceships? For instance, a Life glider heading SE is more likely to fly away from the collision region if it is put in the SE corner of the bounding box — cases like these should be taken into consideration in my opinion.
熠熠种花 - Glimmering Garden
Harvest Moon
2-engine p45 gliderless HWSS gun
Small p2070 glider gun
Forgive me if I withhold my enthusiasm.
Harvest Moon
2-engine p45 gliderless HWSS gun
Small p2070 glider gun
Forgive me if I withhold my enthusiasm.
Re: Script request thread
Are you using Mingw-w64? I suspect so, since this seems to be the standard Windows port of GCC. In that case, you can compile by simply running mingw32-make.
-Matthias Merzenich
- Extrementhusiast
- Posts: 1966
- Joined: June 16th, 2009, 11:24 pm
- Location: USA
Re: Script request thread
This seems like the sort of thing that should already exist, but is there a script that takes an object and pastes in all Catagolue soups that create that object? It sure would beat having to copy/paste tens or hundreds of soups every time I want to perform a detailed investigation into how a particular object forms.
I Like My Heisenburps! (and others)
Re: Script request thread
Yes! There's an even more user-friendly version of this called findpreds, which downloads the soups, looks for the ones that take at least 50 generations to produce the object, advances the soups to generation T-50, and prunes the soup (by deleting any clusters that aren't involved in producing the desired object).Extrementhusiast wrote: ↑September 7th, 2021, 5:00 pmThis seems like the sort of thing that should already exist, but is there a script that takes an object and pastes in all Catagolue soups that create that object? It sure would beat having to copy/paste tens or hundreds of soups every time I want to perform a detailed investigation into how a particular object forms.
Here's the link to a version that you can save as a (non-Golly) Python script and run in a terminal:
viewtopic.php?p=75522#p75522
For example, you can run:
python findpreds.py xs21_08e1dagz259d11 C1 100
to get the following output:
Code: Select all
#C soup 0 gives birth at time 177
#C soup 1 gives birth at time 1834
#CLL state-numbering golly
x = 49, y = 165, rule = B3/S23
15b2o$14bob2o$14bobo$18b2o$12b2obo4b2obo$11bo3bo4bo3bo$13b2o5b3obo
$13b3o3bo2b2o$6bo8b3o2bo$5bobo7b2o2bo$5bob2o3b2obobo$6bob3obo2b2o$
8bo3b2o3bo$2bo5bo$2ob2o4bob2o$2o6bo2bo$2obo6bobobo$3b2o9bo$3b3o4$
18b3o3$21b2o$21b2o112$45b2o$44bo2bo$44bobo$30b2o5b3o5bo$29bo2bo$
29bobo3bo$30bo4bo9b3o$35bo9b3o$44bo3bo$42bobo2bo$11bo29bo2bo$10bob
o20b2o5b3o2bo$10bobo20b2o11b2o$11bo12b2o21bo$22b2o2bo$22b2o6b2o$
25bo6bo$31b3o6b2o$31b3o5bo2bo$33b2o5b2o$31b2o$27b4o$22bo3b2o3bo$
21b2o6b2o$20bo5bo3bo$21b2o3b4o$22bo5bo!
What do you do with ill crystallographers? Take them to the mono-clinic!
Re: Script request thread
This requested script will take a hassler/shuttle/etc. and determine how likely it is to occur naturally.
Gosper glider gun:
Queen bee (the first object isn't pinned to a location or timing)
Queen bee, exact location and and orientation, timed correctly
Block in one of two positions
Block in one of two positions
Vicinity is clear
p24 pi-heptomino hassler, assuming symmetry:
Figure eight at exact location and orientation (with symmetry, location must be exact for the first object, but not timing)
Figure eight at exact location and orientation, timed correctly
Pi-heptomino at exact location and orientation, timed correctly
Vicinity is clear
p32 honey farm hassler:
Figure eight
Figure eight at exact location and orientation, timed correctly
Block at exact location
Fishhook at exact location and orientation
Honey farm or LOM at exact location and orientation, timed correctly
Vicinity is clear
This can be tested with objects that have been found, such as these:
(Gabriel's p138 simply requires an octomino II in the correct orientation and location and no interference, and that's it)
Note that objects that must be far from the soup, such as the four-fold p54 shuttle, should be penalized, although blocks and ships less so because of B-heptominoes. Also note constellations; e.g. bi-blocks are more common than two blocks individually.
Code: Select all
x = 36, y = 9, rule = B3/S23
26bo$26bobo$9bo17bobo$9b2o16bo2bo3b2o$4b2o4b2o15bobo4b2o$2o2b2o4b3o13b
obo$2o2b2o4b2o7bobo4bo$9b2o9b2o$9bo10bo!
Queen bee (the first object isn't pinned to a location or timing)
Queen bee, exact location and and orientation, timed correctly
Block in one of two positions
Block in one of two positions
Vicinity is clear
Code: Select all
x = 26, y = 33, rule = B3/S23
17b3o$17b3o$17b3o$14b3o$14b3o$14b3o2$3o$3o$3o$3b3o$3b3o$3b3o5b3o$11bo$
11b3o4$12b3o$14bo$12b3o5b3o$20b3o$20b3o$23b3o$23b3o$23b3o2$9b3o$9b3o$
9b3o$6b3o$6b3o$6b3o!
Figure eight at exact location and orientation (with symmetry, location must be exact for the first object, but not timing)
Figure eight at exact location and orientation, timed correctly
Pi-heptomino at exact location and orientation, timed correctly
Vicinity is clear
Code: Select all
x = 32, y = 17, rule = B3/S23
22bo$20b3o$19bo8b2o$19b2o$27bo3bo$16b3o7bo4bo$15bo3bo5bobobo$14bo5bo3b
obobo$14bo5bobo4bo$5bo8bo5bobo3bo$15bo3bo$3b3obo8b3o5b2o$2bob2o$2b2obo
$ob3o5b2o$10b2o$2bo!
Figure eight
Figure eight at exact location and orientation, timed correctly
Block at exact location
Fishhook at exact location and orientation
Honey farm or LOM at exact location and orientation, timed correctly
Vicinity is clear
This can be tested with objects that have been found, such as these:
Code: Select all
x = 73, y = 54, rule = B3/S23
62b3o$62bo2bo$6b3o18b3o32bo2bo$5bo3bo16bo3bo33b2o$4bo5bo2b3o4b3o2bo5bo
$13bobo4bobo$3bo7bob3o4b3obo7bo$3bo7bo12bo7bo20b3o$52bo2bo$4bo5bo14bo
5bo20bo$5bo3bo16bo3bo21b3o15b3o$6b3o18b3o42bo$69bo2bo$69b3o4$59b2o$59b
o2bo$59bo2bo$60b3o5$10bo$10b3o$13bo$12b2o5$14b2o$14bob2o$2o12b4o$bo13b
2ob2o$bobo13b3o$2b2o13b2obo$8b3o7b3o$8bob2o13b2o27bo6b2o$9b3o13bobo26b
o6b2obo$9b2ob2o13bo25bobo9bo$11b4o12b2o25bo7bo$11b2obo39bo8bob2o$13b2o
39bo10b2o$54bo$53bobo$54bo$54bo$15b2o$15bo$16b3o$18bo!
Note that objects that must be far from the soup, such as the four-fold p54 shuttle, should be penalized, although blocks and ships less so because of B-heptominoes. Also note constellations; e.g. bi-blocks are more common than two blocks individually.
User:HotdogPi/My discoveries
Periods discovered: 5-16,⑱,⑳G,㉑G,㉒㉔㉕,㉗-㉛,㉜SG,㉞㉟㊱㊳㊵㊷㊹㊺㊽㊿,54G,55G,56,57G,60,62-66,68,70,73,74S,75,76S,80,84,88,90,96
100,02S,06,08,10,12,14G,16,17G,20,26G,28,38,47,48,54,56,72,74,80,92,96S
217,486,576
S: SKOP
G: gun
Periods discovered: 5-16,⑱,⑳G,㉑G,㉒㉔㉕,㉗-㉛,㉜SG,㉞㉟㊱㊳㊵㊷㊹㊺㊽㊿,54G,55G,56,57G,60,62-66,68,70,73,74S,75,76S,80,84,88,90,96
100,02S,06,08,10,12,14G,16,17G,20,26G,28,38,47,48,54,56,72,74,80,92,96S
217,486,576
S: SKOP
G: gun
Re: Script request thread
Sorry for double posting, but the test case done by hand on Discord was very accurate to the real numbers. A script could definitely be written.
The test: 22P36
C2_4 soups: 140 billion
Fishhook frequency (we're looking for exact fishhooks, so no integrals): 1 in 473×(5756/3.094)×8 = 1 in 7 million (http://conwaylife.com/ref/mniemiec/p1.htm) (473 is the block in specific location frequency; 8 because fishhooks are asymmetric)
Divide the two: 20000 soups will have the fishhooks in the correct place. 22P36 is only C2 symmetric, so multiply by 4: 80000.
2/3 of blinkers are from traffic lights, and blinkers are approximately as common as blocks, so 80000/(473×4×1.5) = 28.
The actual number found in C2_4? 25. Extremely close. There are two potentially canceling factors we haven't considered yet. One is that the 22P36 has to survive. The other is that a phi spark placed correctly also works. If the first is a greater factor, we would expect fewer than 28, and this is the case; we have 25, not 28.
(If you read the Discord, these steps were done in a slightly different order, but since it's all multiplication and division, it works out the same.)
The test: 22P36
C2_4 soups: 140 billion
Fishhook frequency (we're looking for exact fishhooks, so no integrals): 1 in 473×(5756/3.094)×8 = 1 in 7 million (http://conwaylife.com/ref/mniemiec/p1.htm) (473 is the block in specific location frequency; 8 because fishhooks are asymmetric)
Divide the two: 20000 soups will have the fishhooks in the correct place. 22P36 is only C2 symmetric, so multiply by 4: 80000.
2/3 of blinkers are from traffic lights, and blinkers are approximately as common as blocks, so 80000/(473×4×1.5) = 28.
The actual number found in C2_4? 25. Extremely close. There are two potentially canceling factors we haven't considered yet. One is that the 22P36 has to survive. The other is that a phi spark placed correctly also works. If the first is a greater factor, we would expect fewer than 28, and this is the case; we have 25, not 28.
(If you read the Discord, these steps were done in a slightly different order, but since it's all multiplication and division, it works out the same.)
User:HotdogPi/My discoveries
Periods discovered: 5-16,⑱,⑳G,㉑G,㉒㉔㉕,㉗-㉛,㉜SG,㉞㉟㊱㊳㊵㊷㊹㊺㊽㊿,54G,55G,56,57G,60,62-66,68,70,73,74S,75,76S,80,84,88,90,96
100,02S,06,08,10,12,14G,16,17G,20,26G,28,38,47,48,54,56,72,74,80,92,96S
217,486,576
S: SKOP
G: gun
Periods discovered: 5-16,⑱,⑳G,㉑G,㉒㉔㉕,㉗-㉛,㉜SG,㉞㉟㊱㊳㊵㊷㊹㊺㊽㊿,54G,55G,56,57G,60,62-66,68,70,73,74S,75,76S,80,84,88,90,96
100,02S,06,08,10,12,14G,16,17G,20,26G,28,38,47,48,54,56,72,74,80,92,96S
217,486,576
S: SKOP
G: gun
-
- Posts: 1268
- Joined: January 28th, 2022, 7:18 pm
- Location: Planet Z
Re: Script request thread
Can someone make a syringe finder?
I would really like to see a g-to-pi or g-to-r.
I would really like to see a g-to-pi or g-to-r.
- yujh
- Posts: 3068
- Joined: February 27th, 2020, 11:23 pm
- Location: I'm not sure where I am, so please tell me if you know
- Contact:
Re: Script request thread
first you will need to find a base reaction yourself. Then you might want to use bellman. but actually it's hard to find a new stable glider converter because people have tried so much.AlbertArmStain wrote: ↑February 3rd, 2022, 4:19 pmCan someone make a syringe finder?
I would really like to see a g-to-pi or g-to-r.
Rule modifier
B34kz5e7c8/S23-a4ityz5k
b2n3-q5y6cn7s23-k4c8
B3-kq6cn8/S2-i3-a4ciyz8
B3-kq4z5e7c8/S2-ci3-a4ciq5ek6eik7
Bored of Conway's Game of Life? Try Pedestrian Life -- not pedestrian at all!
B34kz5e7c8/S23-a4ityz5k
b2n3-q5y6cn7s23-k4c8
B3-kq6cn8/S2-i3-a4ciyz8
B3-kq4z5e7c8/S2-ci3-a4ciq5ek6eik7
Bored of Conway's Game of Life? Try Pedestrian Life -- not pedestrian at all!
Re: Script request thread
1) git clone clones the repo to the current directory you're in. E.g. if you're in ~ (the home directory) and you do git clone https://gitlab.com/apgoucher/apgmera.git it clones apgsearch to ~/apgmera.GUYTU6J wrote: ↑September 3rd, 2021, 12:36 pmI have installed Ubuntu 16.04 LTS as my WSL, but I'm not familiar with it and I cannot either 1) find the default location of files downloaded by git clone (such as apgmera) or 2) access other locations apart from default (such as the gencols file on disk D:; it won't even find D: if I input it directly). So I used Command Prompt instead of that Ubuntu for compiling.
Note that my original question was for the gencols — which has a mysterious Makefile that I don't know how to run — and not your new program, but I may ask a relevant question to you by the way: when generating spaceship collisions, will the script attempt to reduce the number of wasted spaceships? For instance, a Life glider heading SE is more likely to fly away from the collision region if it is put in the SE corner of the bounding box — cases like these should be taken into consideration in my opinion.
2)To access Windows files, e.g. D:/some/path/to/file, use /mnt/d/some/path/to/file.
The makefile is a special file that contains information about how to compile the code. The Linux make utility understands the format, and running make directly compiles the program for you.
\sum_{n=1}^\infty H_n/n^2 = \zeta(3)
How much of current CA technology can I redevelop "on a desert island"?
How much of current CA technology can I redevelop "on a desert island"?
- ClippyCosmologist
- Posts: 22
- Joined: May 7th, 2022, 5:24 pm
Re: Script request thread
Thank you for the useful script!Cyclotrons wrote: ↑September 1st, 2021, 3:15 pmI decided to do it myself instead.[...]Cyclotrons wrote: ↑August 25th, 2021, 12:12 pmWould anyone mind writing a spaceship collision stdin script for INT rules? It would take an RLE, a rule, the number of spaceships to collide, and maybe a symmetry as inputs, preferably upon compilation, and would generate a random (preferably valid) n-spaceship soup when run. It should at least be able to determine whether a ship's slope is orthogonal or diagonal (oblique slopes would be nice as well), but having the slope as input is acceptable as well.
However, it seems to sometimes place parallel LWSSs close enough to destroy each other before colliding with anything else.
For example, in this soup:
Code: Select all
x = 0, y = 0, rule = B3/S238
10$37bobo$40bo$40bo$37bo2bo$38b3o12$37b2o$36b3o$36b2obo$37b3o$38bo2$81bobo2bobo$80bo8bo$80bo8bo$80bo2bo2bo2bo$80b3o4b3o3$51b2o60bo2bo$4b2o11b4o30b3o58bo$3b4o9bo3bo29bob2o58bo3bo$3b2ob2o12bo29b3o47b4o8b4o$5b2o9bo2bo31bo48bo3bo$100bo$101bo2bo4$29b4o$28bo3bo$32bo$28bo2bo4$11b2o$9b2ob2o$9b4o$10b2o9$31bo2bo$22b4o9bo$21bo3bo5bo3bo$25bo6b4o$21bo2bo3$123b2o$122b2ob2o$123b4o$124b2o2$115b2o$14bo2bo96b4o$18bo94b2ob2o$14bo3bo95b2o$15b4o4$102b2o$10b2o89b2ob2o$8b2ob2o89b4o$8b4o91b2o$9b2o2$30b2o76b2o$28b2ob2o74b2ob2o$28b4o76b4o$29b2o78b2o2bo2bo$112bo$112bo3bo$112b4o9$2b2o$2ob2o$4o$b2o6$9bo2bo$13bo$9bo3bo$10b4o3$11b2o$10b4o$10b2ob2o$12b2o2$33bo$32b3o$32bob2o44b3o$33b3o44bo2bo$33b2o45bo$80bo$81bobo$10bo54bo$9b3o52b3o$8b2obo51b2obo$8b3o44bo7b3o56bo$9b2o43b3o7b2o55b3o$53b2obo63b2obo$53b3o64b3o$54b2o65b2o11$!
This was generated with the parameters
Code: Select all
./shipcolls -g 'b2o$3o$2obo$b3o$2bo!' -n 30 -dmin 5 -dmax 10 -dscale 1 -r b3s238 -t 0
"Human beings, five hundred years after the Scientific Revolution, are only just starting to match their wits against the billion-year heritage of biology." -- E. Yudkowsky
-
- Posts: 49
- Joined: April 14th, 2022, 3:09 pm
Re: Script request thread
multistate-apgsearch, i;e apgsearch but the starting soup contains all possible states
- yujh
- Posts: 3068
- Joined: February 27th, 2020, 11:23 pm
- Location: I'm not sure where I am, so please tell me if you know
- Contact:
Re: Script request thread
you can make a rule where state1 can turn into any states depending on its neighbour cells, but that is pretty annoying and that is the only way i know.atavoidirc wrote: ↑July 13th, 2022, 7:03 pmmultistate-apgsearch, i;e apgsearch but the starting soup contains all possible states
Re: Script request thread
Alternatively, you can use an stdin script to generate soups with all states in them — see the LifeWiki tutorial.yujh wrote: ↑July 15th, 2022, 2:54 pmyou can make a rule where state1 can turn into any states depending on its neighbour cells, but that is pretty annoying and that is the only way i know.atavoidirc wrote: ↑July 13th, 2022, 7:03 pmmultistate-apgsearch, i;e apgsearch but the starting soup contains all possible states
\sum_{n=1}^\infty H_n/n^2 = \zeta(3)
How much of current CA technology can I redevelop "on a desert island"?
How much of current CA technology can I redevelop "on a desert island"?