Tutorials/slsparse: Difference between revisions

From LifeWiki
Jump to navigation Jump to search
first single-channel snippet (the 44hd block push)
m link to oncoming glider gun construction arm as more efficient alternative
 
(11 intermediate revisions by 4 users not shown)
Line 1: Line 1:
==Overview==
Adam P. Goucher's single-channel compiler program for sparse constellations of still lifes, [[slsparse]], is a very powerful tool for helping to construct a large number of self-constructing Life circuitry designs.
Adam P. Goucher's single-channel compiler program for sparse constellations of still lifes, slsparse, is a very powerful tool for helping to construct a large number of self-constructing Life circuitry designs. This walkthrough describes the current process for piecing together one of the simplest types of self-constructing spaceship, a [[Demonoid]] (diagonal Geminoid).  Compiling a different self-constructing structure is mostly a matter of building a blueprint for it, and feeding the required still-life constellations into slsparse via an infile.mc.  The content of infile.mc can actually be in either [[macrocell]] format or standard RLE, but the name must be "infile.mc".
 
This walkthrough describes the current process for piecing together one of the simplest types of self-constructing spaceship, a [[Demonoid]] (diagonal Geminoid).  Compiling a different self-constructing structure is mostly a matter of building a blueprint for it, and feeding the required still-life constellations into slsparse via an {{filename|infile.mc}}.  The content of {{filename|infile.mc}} can actually be in either [[macrocell]] format, standard [[RLE]], or {{rl|LifeHistory}} (see below), but the name must be "infile.mc".
 
SIDE NOTE:  slmake/slsparse/pslmake is no longer the most efficient method of constructing a Demonoid. [[Oncoming glider gun construction arm]] technology has now produced Demonoids that [https://conwaylife.com/forums/viewtopic.php?p=232523#p232523 fit inside a LifeViewer grid].


==Installation==
==Installation==
Line 9: Line 12:
<pre>git clone https://gitlab.com/apgoucher/slmake.git
<pre>git clone https://gitlab.com/apgoucher/slmake.git


cd slmake</pre>
cd slmake
 
./slsparse.cpp</pre>
 
(Yes, you compile slsparse by running the {{filename|.cpp}} file as if it were an executable file.  This is an excessive piece of cleverness, not the way that {{filename|.cpp}} files normally work, but the early lines of the {{filename|.cpp}} file are arranged so that the file can be interpreted as a valid bash script that produces a compiled slsparse executable, and then runs it.)
 
==A First Trial Run==
Before we get into building a Demonoid, here's a simple example of a construction that you should be able to compile using slsparse:
 
{{EmbedViewer
|rle          = x = 90, y = 103, rule = B3/S23
31b2o$31b2o5b2o$38b2o3$7b2o8b2o17b2o$7b2o9bo17b2o$18bobo21b2o$19b2o21b
2o$b2o$b2o$5b2o21b2o$5b2o20bo2bo$28bobo$23b2o4bo$24bo$2o19b3o$2o19bo
21bo$41b3o$40bo$40b2o7$14b2o$7b2o5b2o$8bo$5b3o$5bo41b2o$10b2o35b2o$10b
2o3$42b2o$42b2o$46b2o$46b2o$5b2o21b2o$5b2o21bobo$11b2o17bo9b2o$11b2o
17b2o8b2o3$9b2o$9b2o5b2o$16b2o24$52b3o$52bo$53bo24$88bo$87bobo$83b2obo
2bo$83b2obobo$87bo!
|viewerconfig = #C [[ HEIGHT 640 WIDTH 640 THUMBSIZE 2 ZOOM 4 THEME 6 ]]
|position    = center
|caption      = infile pattern for slsparse, for a p256 oscillator
|style        = width:300px;
}}
 
There are three parts to this slsparse input file:
* the actual constellation to be constructed, in the northwest in this case;
* the optional [[slow salvo]] of gliders to be constructed after the constellation is complete -- in this case, just one glider to activate the [[seed]];
* the location and orientation of the initial [[single-channel]] [[elbow]] that will produce all the slow-salvo construction gliders.
 
The location of the elbow block is signalled by the placement of a [[pseudo]] [[still life]], a block placed one cell away from a [[mango]].  The location and orientation of the mango specify where the single-channel glider stream will strike the block.  Note that the diagonal width of the mango matches the diagonal width of a single-channel glider lane aimed to hit the block correctly (where the first glider will create a [[pi-heptomino]]).
 
Save the above RLE from LifeViewer, as '''{{filename|infile.mc}}''' in the slmake root directory.  There's no need to actually convert the pattern into macrocell format, though that will work too.
 
Once you've supplied the input file, simply run slsparse -- no command-line options are needed:
 
<pre>./slsparse</pre>
 
When the compilation is complete, open {{filename|outfile.mc}} in Golly.  You should see a very long stream of single-channel gliders aimed at a block in the southwest corner.  When you run the pattern, the single-channel stream will compile the p256 oscillator seed and trigger it with the specified glider.
 
===Variations===
 
As described in more detail below, by default slsparse will create a target block using a specialized initial slow salvo, and will then push it to whatever location it needs to complete the requested construction.  Sometimes you may instead want to start a construction with a pre-placed initial target block.  This can be signaled in infile.mc with a specific complex still life, outlining the exact position of the block:
 
{{EmbedViewer
|rle          = x = 113, y = 134, rule = B3/S23
3b2o$2bo2bo$bob2obo$obo2bobo$obo2bobo$bob2obo$2bo2bo$3b2o24$54b2o$54b
2o5b2o$61b2o3$30b2o8b2o17b2o$30b2o9bo17b2o$41bobo21b2o$42b2o21b2o$24b
2o$24b2o$28b2o21b2o$28b2o20bo2bo$51bobo$46b2o4bo$47bo$23b2o19b3o$23b2o
19bo21bo$64b3o$63bo$63b2o7$37b2o$30b2o5b2o$31bo$28b3o$28bo41b2o$33b2o
35b2o$33b2o3$65b2o$65b2o$69b2o$69b2o$28b2o21b2o$28b2o21bobo$34b2o17bo
9b2o$34b2o17b2o8b2o3$32b2o$32b2o5b2o$39b2o24$75b3o$75bo$76bo24$111bo$
110bobo$106b2obo2bo$106b2obobo$110bo!
|viewerconfig = #C [[ HEIGHT 640 WIDTH 640 THUMBSIZE 2 ZOOM 4 THEME 6 ]]
|position    = center
|caption      = infile pattern for slsparse, for a p256 oscillator -- starting block location specified by 24-bit [[PS4B]] still life (far NW)
|style        = width:300px;
}}
 
If the block's starting position is too close to some of the objects being constructed, or even partially or completely overlaps them, then an alternate method of specifying the starting block location can be used.  Convert the starting pattern into LifeHistory format, then mark the block location with red state-4 cells.  Use white state-3 cells for any cells in the starting target block that overlap a live cell in the pattern-to-construct.  Example:
 
{{EmbedViewer
|rle          = x = 91, y = 103, rule = LifeHistory
32.2A$32.2A5.2A$39.2A3$8.2A8.2A17.2A$8.2A9.A17.2A$19.A.A21.2A$20.2A
21.2A$2.2A$2.2A$6.2A21.2A$6.2A20.A2.A$29.A.A$24.2A4.A$25.A$.2A19.3A$D
CA19.A21.A$2D40.3A$41.A$41.2A7$15.2A$8.2A5.2A$9.A$6.3A$6.A41.2A$11.2A
35.2A$11.2A3$43.2A$43.2A$47.2A$47.2A$6.2A21.2A$6.2A21.A.A$12.2A17.A9.
2A$12.2A17.2A8.2A3$10.2A$10.2A5.2A$17.2A24$53.3A$53.A$54.A24$89.A$88.
A.A$84.2A.A2.A$84.2A.A.A$88.A!
|viewerconfig = #C [[ HEIGHT 640 WIDTH 640 THUMBSIZE 2 ZOOM 4 THEME 6 ]]
|position    = center
|caption      = infile pattern for slsparse, for a p256 oscillator -- LifeHistory format
|style        = width:300px;
}}


==Demonoid specifics==
==Demonoid specifics==
Let's assign names to the various widely separated parts of our planned Demonoid.  ''(Need diagram here)''
Let's assign names to the various widely separated parts of our planned Demonoid.  ''(TBD:  Need diagram here)''


"Circuit A":  a signal splitter consisting of a syringe plus a dependent Herschel-to-2-gliders converter.  Glider in, two gliders out in different direction -- one to run the construction arm, and one to make a copy of the recipe stream and send it to Circuit B.
"Circuit A":  a signal splitter consisting of a syringe plus a dependent Herschel-to-2-gliders converter.  Glider in, two gliders out in different direction -- one to run the construction arm, and one to make a copy of the recipe stream and send it to Circuit B.
Line 20: Line 94:
Each time the recipe glider stream goes through one of the universal constructors, it has to accomplish several tasks:
Each time the recipe glider stream goes through one of the universal constructors, it has to accomplish several tasks:


1) Create a new child copy of the universal constructor at a (4096,-4096) offset (in Golly coordinates, not Cartesian coordinates -- inverted Y axis).  This means starting with the existing elbow near the parent's Circuit B, and pushing an elbow 2048 cells out to build the child's Circuit A.  There are recipes available for pushing any specific distance, but we'll mostly make use of the most efficient known long-distance move, a 44[[hd]] elbow push:
'''1)''' Create a new child copy of the universal constructor at a (4096,-4096) offset (in Golly coordinates, not Cartesian coordinates -- inverted Y axis).  This means starting with the existing elbow near the parent's Circuit B, and pushing an elbow 2048 cells out to build the child's Circuit A.  There are recipes available for pushing any specific distance, but we'll mostly make use of the most efficient known long-distance move, a 44[[hd]] elbow push:


{{EmbedViewer
{{EmbedViewer
|viewerconfig = #C [[ THEME 6 WIDTH 1000 HEIGHT 1000 STEP 1 PAUSE 2 X 260 Y -260 Z 6 PAUSE 0 STEP 25 PAUSE 2 T 2000 STEP 5 T 2195 PAUSE 2 LOOP 2196 ]]
|rle          = x = 530, y = 533, rule = B3/S23
|caption      = 44hd elbow push recipe<br />
|position    = center
|rle          =  
x = 530, y = 533, rule = B3/S23
528b2o$528b2o3$527b3o$529bo$528bo25$500b2o$501b2o$500bo20$478bo$478b2o
528b2o$528b2o3$527b3o$529bo$528bo25$500b2o$501b2o$500bo20$478bo$478b2o
$477bobo22$454b3o$456bo$455bo20$432bo$432b2o$431bobo21$409b2o$410b2o$
$477bobo22$454b3o$456bo$455bo20$432bo$432b2o$431bobo21$409b2o$410b2o$
Line 35: Line 105:
22$143bo$143b2o$142bobo25$116b2o$115bobo$117bo21$93b3o$95bo$94bo20$71b
22$143bo$143b2o$142bobo25$116b2o$115bobo$117bo21$93b3o$95bo$94bo20$71b
2o$70bobo$72bo21$48bo$48b2o$47bobo45$bo$b2o$obo!
2o$70bobo$72bo21$48bo$48b2o$47bobo45$bo$b2o$obo!
|viewerconfig = #C [[ THEME 6 WIDTH 1000 HEIGHT 1000 STEP 1 PAUSE 2 X 260 Y -260 Z 6 PAUSE 0 STEP 25 PAUSE 2 T 2000 STEP 5 T 2195 PAUSE 2 LOOP 2196 ]]
|position    = center
|caption      = 44hd elbow push recipe
|style        = width:300px;
}}
}}


2) The elbow is pushed out another 2048 cells, then builds the child's Circuit B (Snark).
'''2)''' The elbow is pushed out another 2048 cells, then builds the child's Circuit B (Snark).
 
'''3)''' Make a 180-degree return glider on a lane 3hd from the single-channel lane, leaving an elbow block next to child Circuit B.  The child U.C. will start construction from this elbow location.
 
'''4)''' Wait until the return glider is passing Circuit A, then hit it with a glider in the channel to make a honeyfarm, then an additional 23-glider salvo to produce a clean new elbow block near Circuit A.
 
'''5)''' Hit the new elbow block with a 22-glider "elbow duplicator" salvo to produce two elbows in series on the channel.
 
'''6)''' Hit the nearer, southwest, duplicated elbow block with a stream of 17 gliders to produce a Snark-destroying return glider directly in the channel.
 
'''7)''' Meet the Snark-destroying return glider with two more gliders to settle the resulting explosion and produce a clean single elbow block, lined up correctly with the glider channel *before* the turn that the Snark has been facilitating (until now).
 
'''8)''' Now we're back to something slmake can do!  This time we just need to ask slmake to build a Snark reflector.
 
'''9)''' Add the resulting slmake glider stream to the end of the single-channel recipe so far.  Measure how far the first northeastward output glider is from where it needs to be, to strike our adjusted hand block and begin the Snark construction.
 
'''10)''' Find a workable sequence of block-move recipes from {{filename|pp.txt}} to correct for the measured distance, and patch this in just before the slmake Snark construction recipe.
 
'''11)''' The result will be that a new temporary lossless elbow Snark will be created at a (4096, -4096) offset from the old one, so it will be ready for use immediately when the glider recipe stream arrives at the child constructor.  ''This has to be done as a separate step from #1, by the way, because the single-channel stream passes through this location during the construction of the rest of the U.C.''
 
'''12)''' Now the construction stage is complete. Again using block-move recipes from {{filename|pp.txt}}, push the elbow block outward until it lines up with the Snark reflector from the previous (grandparent) universal constructor, and shoot it down with an LWSS.
 
'''13)''' Push the elbow block outward until it lines up with the syringe and H-to-2G, and shoot it down with six more *WSSes.


3) Make a 180-degree return glider on a lane 3hd from the single-channel lane, leaving an elbow block next to child Circuit B.  The child U.C. will start construction from this elbow location.
'''14)''' Now the destruction stage is complete.  Send an elbow-destroy recipe to delete the elbow block, since it's no longer needed.
4) Wait until the return glider is passing Circuit A, then hit it with a glider in the channel to make a honeyfarm, then an additional 23-glider salvo to produce a clean new elbow block near Circuit A.
5) Hit the new elbow block with a 22-glider "elbow duplicator" salvo to produce two elbows in series on the channel.
6) Hit the nearer, southwest, duplicated elbow block with a stream of 17 gliders to produce a Snark-destroying return glider directly in the channel.
7) Meet the Snark-destroying return glider with two more gliders to settle the resulting explosion and produce a clean single elbow block, lined up correctly with the glider channel *before* the turn that the Snark has been facilitating (until now).
8) Use the new elbow block to move the northeast duplicated elbow block -- now a hand block -- into a position where a standard slmake recipe can use it to build a new temporary lossless elbow Snark at the child's Circuit A. ''Note: Steps 5, 6, and 8 could be optimized somewhat.  We really only need to produce one elbow, plus an extra "hand" block that doesn't have to be on the channel.  In fact, instead of cleaning up any leftover junk from the collision in #4, we could use it as a starting target to build the Snark -- all we really need from that collision is a usable elbow block, or even better a single Snark-destroy return glider on the single-channel lane.''
9) Now we're back to something slmake can do!  This time we just need to ask slmake to build a Snark reflector.
10) Add the resulting slmake glider stream to the end of the single-channel recipe so far.  Measure how far the first northeastward output glider is from where it needs to be, to strike our adjusted hand block and begin the Snark construction.
11) Find a workable sequence of block-move recipes from pp.txt to correct for the measured distance, and patch this in just before the slmake Snark construction recipe.
12) The result will be that a new temporary lossless elbow Snark will be created at a (4096, -4096) offset from the old one, so it will be ready for use immediately when the glider recipe stream arrives at the child constructor.  [i]This has to be done as a separate step from #1, by the way, because the single-channel stream passes through this location during the construction of the rest of the U.C.[/i]
13) Now the construction stage is complete. Again using block-move recipes from pp.txt, push the elbow block outward until it lines up with the Snark reflector from the previous (grandparent) universal constructor, and shoot it down with an LWSS.
14) Push the elbow block outward until it lines up with the syringe and H-to-2G, and shoot it down with six more *WSSes.
15) Now the destruction stage is complete.  Send an elbow-destroy recipe to delete the elbow block, since it's no longer needed.


==Where slsparse comes in==
==Where slsparse comes in==


You can get help from slsparse at two points in this recipe -- Step 1 and Step 9.
You can get help from slsparse at two points in this recipe -- Step 1 and Step 8.


Start out by setting up your infile.mc to do the Step 1 construction.  There's a sample infile.mc in the slsparse package:
Start out by setting up your {{filename|infile.mc}} to do the Step 1 construction.  There's a sample {{filename|infile.mc}} in the slsparse package:


''{your Cygwin install directory}''\home\{your username}\repos\slmake\infile.mc
{{filename|''{your Cygwin install directory}''\home\{your username}\repos\slmake\infile.mc}}


Open it in Golly and edit it until it matches what you want to build, and where you want to build it relative to the initial elbow block.  The block-on-mango marks both the elbow location and the orientation of the input glider stream.  Always save the file as infile.mc.
Open it in Golly and edit it until it matches what you want to build, and where you want to build it relative to the initial elbow block.  The block-on-mango marks both the elbow location and the orientation of the input glider stream.  Always save the file as {{filename|infile.mc}}.


We're going to build a Demonoid with a long step size -- a long distance between reflectors -- so slsparse's long-distance compilation abilities will come in handy.
We're going to build a Demonoid with a long step size -- a long distance between reflectors -- so slsparse's long-distance compilation abilities will come in handy.


Here's the input RLE file.  ''Captions to be added later...''
Here's the input RLE file:
 
{{EmbedViewer
{{EmbedViewer
|viewerconfig = #C [[ THEME 6 THUMBNAIL THUMBSIZE 2 ZOOM -12 ]]
|rle          = x = 4188, y = 4069, rule = B3/S23
|caption      = Southwest to northeast:<br />block-on-mango marking start location for construction-arm elbow,<br />Circuit A ([[syringe]] and H-to-2G,<br />Circuit B ([[Snark]])<br />
|position    = center
|rle          =  
x = 4188, y = 4069, rule = B3/S23
4177b2o$4177bobo$4179bo4b2o$4175b4ob2o2bo2bo$4175bo2bobobobob2o$4178bo
4177b2o$4177bobo$4179bo4b2o$4175b4ob2o2bo2bo$4175bo2bobobobob2o$4178bo
bobobo$4179b2obobo$4183bo2$4169b2o$4170bo7b2o$4170bobo5b2o$4171b2o7$
bobobo$4179b2obobo$4183bo2$4169b2o$4170bo7b2o$4170bobo5b2o$4171b2o7$
Line 79: Line 160:
2168b2o$2153b2o$2154bo$2126b2o23b3o$2126bo24bo$2127b3o$2120b2o7bo$
2168b2o$2153b2o$2154bo$2126b2o23b3o$2126bo24bo$2127b3o$2120b2o7bo$
2120bo$2121b3o$2123bo1970$2bo$bobob2o$o2bob2o$obo$bo!
2120bo$2121b3o$2123bo1970$2bo$bobob2o$o2bob2o$obo$bo!
|viewerconfig = #C [[ HEIGHT 600 WIDTH 600 THUMBNAIL THUMBSIZE 2 ZOOM -12 THEME 6 ]]
|position    = center
|caption      = <div style="text-align:left;">Southwest to northeast:
* block-on-mango where construction-arm elbow starts,
* Circuit A ([[syringe]] and H-to-2G),
* Circuit B ([[Snark]])</div>
|style        = width:300px;
}}
}}


When you run slsparse, if the compilation process is successful, a single-channel recipe pattern is created in outfile.mc, with the outfile.txt listing the timing offsets between gliders.
Run slsparse the first time with
 
<pre>./slsparse.cpp</pre>
 
This creates an slsparse.exe file and automatically runs it.  For future runs you can get away with just
 
<pre>./slsparse</pre>
 
until there's an update to the slsparse GitLabs repository, at which point you'll want to download and re-compile:
 
<pre>rm infile.mc
git pull
./slsparse.cpp</pre>
 
All of these commands are run directly from the slmake root folder.
 
When you run slsparse, if the program finds a way to build the contents of {{filename|infile.mc}}, a single-channel recipe pattern is created in {{filename|outfile.mc}}, with the {{filename|outfile.txt}} listing the timing offsets between gliders.


The program currently appends lots of elbow block moves to the end of the recipe, to get the elbow back to where it started  We don't want to go back that far, so we'll have to identify the exact point where the recipe produces a clean elbow block again after sending the final sideways glider.  Remove all the gliders after that to get the useful part of the recipe.
The program currently appends lots of elbow block moves to the end of the recipe, to get the elbow back to where it started  We don't want to go back that far, so we'll have to identify the exact point where the recipe produces a clean elbow block again after sending the final sideways glider.  Remove all the gliders after that to get the useful part of the recipe.


You can do this by running the pattern until the first useless glider is about to hit the elbow.  Then copy all the remaining useless recipe gliders, go back to T=0, paste in at a 100-cell horizontal offset or so lined up exactly with the end of the full recipe, then select the doubled area and delete everything.  An XOR paste would work if the gliders happened to be in the right phase, but it's much much slower.
You can do this by running the pattern until the first useless glider is about to hit the elbow.  Then copy all the remaining useless recipe gliders, go back to {{eq|T|0}}, paste in at a 100-cell horizontal offset or so lined up exactly with the end of the full recipe, then select the doubled area and delete everything.  An XOR paste would work if the gliders happened to be in the right phase, but it's much much slower.


(Or there's a sneaky trick:  make a copy of progress.txt when the compiler reaches exactly the right point -- or arrange the requested construction so the compilation will fail at the last step and the final gliders are never added!)
(Or there's a sneaky trick:  make a copy of progress.txt when the compiler reaches exactly the right point -- or arrange the requested construction so the compilation will fail at the last step and the final gliders are never added!)


In Step 9 we have to build the lossless-elbow Snark.  Here's the input pattern.  This time it's small enough to be a little easier to understand:
In Step 8 we have to build the lossless-elbow Snark.  Here's the input pattern.  This time it's small enough to be a little easier to understand:


{{EmbedViewer
{{EmbedViewer
|viewerconfig = #C [[ THEME 6 HEIGHT 1000 WIDTH 1000 ]]
|rle          = x = 68, y = 72, rule = B3/S23
|caption      = block-on-mango marking start location for construction-arm elbow,<br />and the side where the glider stream will strike.<br />The [[Snark]] is the target pattern to be constructed.<br />
63b2o$62bo2bo$61bob2obo$60bobo2bobo$60bobo2bobo$61bob2obo$62bo2bo$63b
2o5$48b2o$49bo$47bo$47b5o14b2o$52bo13bo$49b3o12bobo$48bo15b2o$48b4o$
46b2o3bo3b2o$45bo2b3o4b2o$45b2obo$48bo$48b2o3$56b2o$57bo$54b3o$54bo37$
4bo$2obobo$2obo2bo$4bobo$5bo!
|viewerconfig = #C [[ HEIGHT 720 WIDTH 720 THUMBSIZE 2 ZOOM 8 THEME 6 ]]
|position    = center
|position    = center
|rle          =  
|caption      = block-on-mango marking start location for construction-arm elbow, and the side where the glider stream will strike. The [[Snark]] is the target pattern to be constructed. Starting block location marked by large PS4B still life.
x = 68, y = 60, rule = B3/S23
|style        = width:300px;
48b2o$49bo$47bo$47b5o14b2o$52bo13bo$49b3o12bobo$48bo15b2o$48b4o$46b2o
3bo3b2o$45bo2b3o4b2o$45b2obo$48bo$48b2o3$56b2o$57bo$54b3o$54bo37$4bo$
2obobo$2obo2bo$4bobo$5bo!
}}
}}
Giving this to slsparse by saving it as infile.mc is essentially asking for a single-channel recipe starting with a block at the block-and-mango location, with gliders aimed to strike the right side of the block.  If compilation is successful, the result will be a Snark placed in that precise location relative to the elbow block.


One detail not mentioned in the Demonoid details above: starting from just the elbow, slsparse first automatically creates a target "hand" block and moves it to the correct location to start construction.  For the Demonoid we're in an awkward situation:  the new temporary lossless-elbow Snark has to be built a very long distance from the actual construction elbow block.  So we really don't want to create a hand block and push it all the way to the Snark's location... we're going to have to find that initial part of the recipe, remove it, then adjust the starting location of the block so that the remaining slow salvo of gliders lines up with the faraway block target that we left in place in Step 8 above.
Giving this to slsparse by saving it as infile.mc is essentially asking for a single-channel recipe starting with a block at the mango-on-block location, with gliders aimed to strike the right side of the block.  If compilation is successful, the result will be a Snark placed in that precise location relative to the elbow block.
 
As described in the '''Variations''' section above, the large 24-bit 'PS4B' still life (pond siamese four beehives) in the above pattern marks the location of an existing target block. This tells slsparse to start with a block in this location, along with the mango-on-block elbow.
 
If the PS4B marker is not present, slsparse first automatically creates a target "hand" block and moves it to the correct location to start construction.  In a multi-cluster constellation there may be several PS4Bs, and also several clusters with no PS4Bs; slsparse will automatically create new hand blocks when they're needed, and use existing ones if they have been marked.


==Miscellaneous Notes To Explain Better==
For this last part of the Demonoid construction we have an awkward situation that needs a PS4B marker.  The new temporary lossless-elbow Snark has to be built a very long distance from the actual construction elbow block.  So we really don't want to create a hand block and push it all the way to the lossless-elbow Snark's intended location, way out at Circuit A.  Instead we just mark the location of the leftover northeastern elbow block (from Step 5) relative to where we want the Snark to be, and slsparse does the rest.
I ended up doing Step 8 with a separate Python script, editing in the additional lanes needed to pull the hand block into the correct start position.


The actual Snark recipe starts at "E-1 E1 O-27.  Everything before that is the patch needed to move the northeastmost duplicated elbow into the position where the recipe generated by slmake expects it to be.  This is not an efficient way to get the target block to the right place -- but it's very simple, it works, and the number of extra gliders is fairly negligible given the scale of the entire project.
==More Features==
# If {{filename|infile.mc}} contains still lifes with a population of 32 cells or more, slsparse will not attempt to construct them -- but it will assume that they exist in the Life universe, and will attempt to find construction recipes for the remaining objects that do not damage the &ge;32-bit obstacles.  This can be very useful if you need to build a new structure in close proximity to an existing one.  Replace the existing structures with equivalent large obstacles, and slsparse will obey the additional constraints.
# If a partition of the construction is sufficiently far away that it's cheaper for slsparse to build a [[Cordership]] [[seed]], trigger it, wait until the Cordership has traveled sufficiently far away, shoot down the Cordership, clean up the debris except for a single block, and proceed with the construction from there... then slsparse will do this automatically.
# If an elbow has to be moved closer to the single-channel source by a long distance, such that it is cheaper for slsparse to generate a 180-degree return glider, wait until the glider is close to the elbow, hit it with another glider, and clean up the debris to regenerate an elbow, slsparse will do this automatically.  This is accomplished with an elbow duplication recipe similar to the one used in the Demonoid above.  If it is necessary to jump back and forth between two distant points, an elbow will be left behind at the more distant location.  The recipes involved are called "left parenthesis" (duplicate the elbow, convert the nearer elbow to a glider, convert the glider back to an elbow at the right distance) and "right parenthesis" (delete the near elbow, and send a cleanup salvo to standardize the far elbow.  The current recipe leaves the far elbow in the form of a random-looking junk constellation.)
# If a metacluster is in the construction "danger zone" -- i.e., if it overlaps the construction lane, so that some of the final structure would interfere with the elbow-operation reactions necessary to construct it -- then slsparse will send two Snarkmaker recipes, to bend the construction arm to one side of the construction area so that the structure can be put in place safely.  When the construction is done, slsparse will add two Snarkbreaker recipes to remove the temporary lossless elbows.
# If a ''sufficiently narrow'' metacluster is in the construction danger zone, with the required construction gliders no farther to the side than +/-107hd from the single-channel lane, then slsparse will automatically generate a 0-degree elbow and produce the required gliders directly instead of using Snarkmaker / Snarkbreaker pairs.
# If an {{filename|infile.mc}} pattern contains a block-on-mango plus a set of unidirectional gliders on appropriate lanes that they can be generated by the designated elbow, then slsparse will create a single-channel recipe that generates gliders on those lanes in the specified order.  This allows for the color of an entire salvo to be changed easily:  moving the block-on-mango by one cell orthogonally and recompiling will produce an opposite-color salvo. The assumption is that the gliders constitute a p2 slow-salvo recipe, so only the parities of the gliders will be preserved.  In other words, the resulting output recipe will only be useful if no synchronization is needed between the unidirectional gliders.


Snark:E23 E21 E19 E17 E15 E13 E11 E9 E7 E5 E3 E1 E-1 E-3 E-5 E15 E17 E-1 E1 O-27 O3 E11 O9 O15 O29 O15 O-1 E19 O7 O33 E11 O21 E-33 E-15 E-21 E-21 O-43 E25 E15 E27 E25 O31 E33 E27 E37 E43 O21 O23 E-9 E-17 E-29 O-19 E3 O-11 O87 O95 O101 E101 E111 O117 O73 O77 E83 E79 E71 O59 E79 E71 E81 O81 O67 O81 O97 E71 E63 O55 E39 O39 O39 O45 O69 E75 O41 O45 O57 O49 O65 O63 O67 E67 O43 E61 E35 E39 E27 O37 O-3 E1 E1 E33 E109 E95 E129 E131 E119 O99 E107 E107
{{Tutorial}}

Latest revision as of 07:58, 1 October 2026

Adam P. Goucher's single-channel compiler program for sparse constellations of still lifes, slsparse, is a very powerful tool for helping to construct a large number of self-constructing Life circuitry designs.

This walkthrough describes the current process for piecing together one of the simplest types of self-constructing spaceship, a Demonoid (diagonal Geminoid). Compiling a different self-constructing structure is mostly a matter of building a blueprint for it, and feeding the required still-life constellations into slsparse via an infile.mc. The content of infile.mc can actually be in either macrocell format, standard RLE, or LifeHistory (see below), but the name must be "infile.mc".

SIDE NOTE: slmake/slsparse/pslmake is no longer the most efficient method of constructing a Demonoid. Oncoming glider gun construction arm technology has now produced Demonoids that fit inside a LifeViewer grid.

Installation

This 'slsparse' walkthrough is written for running via Cygwin on Windows. Linux folks will probably be clever enough to adjust the instructions to leave out the Cygwin-related details that they don't need.

To get slsparse working, follow the initial setup instructions for apgmera -- https://gitlab.com/apgoucher/apgmera -- but then run this clone command instead:

git clone https://gitlab.com/apgoucher/slmake.git

cd slmake

./slsparse.cpp

(Yes, you compile slsparse by running the .cpp file as if it were an executable file. This is an excessive piece of cleverness, not the way that .cpp files normally work, but the early lines of the .cpp file are arranged so that the file can be interpreted as a valid bash script that produces a compiled slsparse executable, and then runs it.)

A First Trial Run

Before we get into building a Demonoid, here's a simple example of a construction that you should be able to compile using slsparse:

x = 90, y = 103, rule = B3/S23 31b2o$31b2o5b2o$38b2o3$7b2o8b2o17b2o$7b2o9bo17b2o$18bobo21b2o$19b2o21b 2o$b2o$b2o$5b2o21b2o$5b2o20bo2bo$28bobo$23b2o4bo$24bo$2o19b3o$2o19bo 21bo$41b3o$40bo$40b2o7$14b2o$7b2o5b2o$8bo$5b3o$5bo41b2o$10b2o35b2o$10b 2o3$42b2o$42b2o$46b2o$46b2o$5b2o21b2o$5b2o21bobo$11b2o17bo9b2o$11b2o 17b2o8b2o3$9b2o$9b2o5b2o$16b2o24$52b3o$52bo$53bo24$88bo$87bobo$83b2obo 2bo$83b2obobo$87bo! #C [[ THUMBSIZE 2 THEME 6 GRID GRIDMAJOR 0 SUPPRESS THUMBLAUNCH ]] #C [[ HEIGHT 640 WIDTH 640 THUMBSIZE 2 ZOOM 4 THEME 6 ]]
infile pattern for slsparse, for a p256 oscillator
(click above to open LifeViewer)

There are three parts to this slsparse input file:

  • the actual constellation to be constructed, in the northwest in this case;
  • the optional slow salvo of gliders to be constructed after the constellation is complete -- in this case, just one glider to activate the seed;
  • the location and orientation of the initial single-channel elbow that will produce all the slow-salvo construction gliders.

The location of the elbow block is signalled by the placement of a pseudo still life, a block placed one cell away from a mango. The location and orientation of the mango specify where the single-channel glider stream will strike the block. Note that the diagonal width of the mango matches the diagonal width of a single-channel glider lane aimed to hit the block correctly (where the first glider will create a pi-heptomino).

Save the above RLE from LifeViewer, as infile.mc in the slmake root directory. There's no need to actually convert the pattern into macrocell format, though that will work too.

Once you've supplied the input file, simply run slsparse -- no command-line options are needed:

./slsparse

When the compilation is complete, open outfile.mc in Golly. You should see a very long stream of single-channel gliders aimed at a block in the southwest corner. When you run the pattern, the single-channel stream will compile the p256 oscillator seed and trigger it with the specified glider.

Variations

As described in more detail below, by default slsparse will create a target block using a specialized initial slow salvo, and will then push it to whatever location it needs to complete the requested construction. Sometimes you may instead want to start a construction with a pre-placed initial target block. This can be signaled in infile.mc with a specific complex still life, outlining the exact position of the block:

x = 113, y = 134, rule = B3/S23 3b2o$2bo2bo$bob2obo$obo2bobo$obo2bobo$bob2obo$2bo2bo$3b2o24$54b2o$54b 2o5b2o$61b2o3$30b2o8b2o17b2o$30b2o9bo17b2o$41bobo21b2o$42b2o21b2o$24b 2o$24b2o$28b2o21b2o$28b2o20bo2bo$51bobo$46b2o4bo$47bo$23b2o19b3o$23b2o 19bo21bo$64b3o$63bo$63b2o7$37b2o$30b2o5b2o$31bo$28b3o$28bo41b2o$33b2o 35b2o$33b2o3$65b2o$65b2o$69b2o$69b2o$28b2o21b2o$28b2o21bobo$34b2o17bo 9b2o$34b2o17b2o8b2o3$32b2o$32b2o5b2o$39b2o24$75b3o$75bo$76bo24$111bo$ 110bobo$106b2obo2bo$106b2obobo$110bo! #C [[ THUMBSIZE 2 THEME 6 GRID GRIDMAJOR 0 SUPPRESS THUMBLAUNCH ]] #C [[ HEIGHT 640 WIDTH 640 THUMBSIZE 2 ZOOM 4 THEME 6 ]]
infile pattern for slsparse, for a p256 oscillator -- starting block location specified by 24-bit PS4B still life (far NW)
(click above to open LifeViewer)

If the block's starting position is too close to some of the objects being constructed, or even partially or completely overlaps them, then an alternate method of specifying the starting block location can be used. Convert the starting pattern into LifeHistory format, then mark the block location with red state-4 cells. Use white state-3 cells for any cells in the starting target block that overlap a live cell in the pattern-to-construct. Example:

x = 91, y = 103, rule = LifeHistory 32.2A$32.2A5.2A$39.2A3$8.2A8.2A17.2A$8.2A9.A17.2A$19.A.A21.2A$20.2A 21.2A$2.2A$2.2A$6.2A21.2A$6.2A20.A2.A$29.A.A$24.2A4.A$25.A$.2A19.3A$D CA19.A21.A$2D40.3A$41.A$41.2A7$15.2A$8.2A5.2A$9.A$6.3A$6.A41.2A$11.2A 35.2A$11.2A3$43.2A$43.2A$47.2A$47.2A$6.2A21.2A$6.2A21.A.A$12.2A17.A9. 2A$12.2A17.2A8.2A3$10.2A$10.2A5.2A$17.2A24$53.3A$53.A$54.A24$89.A$88. A.A$84.2A.A2.A$84.2A.A.A$88.A! #C [[ THUMBSIZE 2 THEME 6 GRID GRIDMAJOR 0 SUPPRESS THUMBLAUNCH ]] #C [[ HEIGHT 640 WIDTH 640 THUMBSIZE 2 ZOOM 4 THEME 6 ]]
infile pattern for slsparse, for a p256 oscillator -- LifeHistory format
(click above to open LifeViewer)

Demonoid specifics

Let's assign names to the various widely separated parts of our planned Demonoid. (TBD: Need diagram here)

"Circuit A": a signal splitter consisting of a syringe plus a dependent Herschel-to-2-gliders converter. Glider in, two gliders out in different direction -- one to run the construction arm, and one to make a copy of the recipe stream and send it to Circuit B.

"Circuit B": a simple Snark reflector, which sends the recipe stream copy to a copy of Circuit A at the other end of the spaceship.

Each time the recipe glider stream goes through one of the universal constructors, it has to accomplish several tasks:

1) Create a new child copy of the universal constructor at a (4096,-4096) offset (in Golly coordinates, not Cartesian coordinates -- inverted Y axis). This means starting with the existing elbow near the parent's Circuit B, and pushing an elbow 2048 cells out to build the child's Circuit A. There are recipes available for pushing any specific distance, but we'll mostly make use of the most efficient known long-distance move, a 44hd elbow push:

x = 530, y = 533, rule = B3/S23 528b2o$528b2o3$527b3o$529bo$528bo25$500b2o$501b2o$500bo20$478bo$478b2o $477bobo22$454b3o$456bo$455bo20$432bo$432b2o$431bobo21$409b2o$410b2o$ 409bo22$385b3o$387bo$386bo20$363bo$363b2o$362bobo21$340b2o$339bobo$ 341bo33$305b3o$307bo$306bo37$266b2o$267b2o$266bo22$242b2o$243b2o$242bo 20$220bo$220b2o$219bobo28$190bo$190b2o$189bobo21$167b2o$166bobo$168bo 22$143bo$143b2o$142bobo25$116b2o$115bobo$117bo21$93b3o$95bo$94bo20$71b 2o$70bobo$72bo21$48bo$48b2o$47bobo45$bo$b2o$obo! #C [[ THUMBSIZE 2 THEME 6 GRID GRIDMAJOR 0 SUPPRESS THUMBLAUNCH ]] #C [[ THEME 6 WIDTH 1000 HEIGHT 1000 STEP 1 PAUSE 2 X 260 Y -260 Z 6 PAUSE 0 STEP 25 PAUSE 2 T 2000 STEP 5 T 2195 PAUSE 2 LOOP 2196 ]]
44hd elbow push recipe
(click above to open LifeViewer)

2) The elbow is pushed out another 2048 cells, then builds the child's Circuit B (Snark).

3) Make a 180-degree return glider on a lane 3hd from the single-channel lane, leaving an elbow block next to child Circuit B. The child U.C. will start construction from this elbow location.

4) Wait until the return glider is passing Circuit A, then hit it with a glider in the channel to make a honeyfarm, then an additional 23-glider salvo to produce a clean new elbow block near Circuit A.

5) Hit the new elbow block with a 22-glider "elbow duplicator" salvo to produce two elbows in series on the channel.

6) Hit the nearer, southwest, duplicated elbow block with a stream of 17 gliders to produce a Snark-destroying return glider directly in the channel.

7) Meet the Snark-destroying return glider with two more gliders to settle the resulting explosion and produce a clean single elbow block, lined up correctly with the glider channel *before* the turn that the Snark has been facilitating (until now).

8) Now we're back to something slmake can do! This time we just need to ask slmake to build a Snark reflector.

9) Add the resulting slmake glider stream to the end of the single-channel recipe so far. Measure how far the first northeastward output glider is from where it needs to be, to strike our adjusted hand block and begin the Snark construction.

10) Find a workable sequence of block-move recipes from pp.txt to correct for the measured distance, and patch this in just before the slmake Snark construction recipe.

11) The result will be that a new temporary lossless elbow Snark will be created at a (4096, -4096) offset from the old one, so it will be ready for use immediately when the glider recipe stream arrives at the child constructor. This has to be done as a separate step from #1, by the way, because the single-channel stream passes through this location during the construction of the rest of the U.C.

12) Now the construction stage is complete. Again using block-move recipes from pp.txt, push the elbow block outward until it lines up with the Snark reflector from the previous (grandparent) universal constructor, and shoot it down with an LWSS.

13) Push the elbow block outward until it lines up with the syringe and H-to-2G, and shoot it down with six more *WSSes.

14) Now the destruction stage is complete. Send an elbow-destroy recipe to delete the elbow block, since it's no longer needed.

Where slsparse comes in

You can get help from slsparse at two points in this recipe -- Step 1 and Step 8.

Start out by setting up your infile.mc to do the Step 1 construction. There's a sample infile.mc in the slsparse package:

{your Cygwin install directory}\home\{your username}\repos\slmake\infile.mc

Open it in Golly and edit it until it matches what you want to build, and where you want to build it relative to the initial elbow block. The block-on-mango marks both the elbow location and the orientation of the input glider stream. Always save the file as infile.mc.

We're going to build a Demonoid with a long step size -- a long distance between reflectors -- so slsparse's long-distance compilation abilities will come in handy.

Here's the input RLE file:

x = 4188, y = 4069, rule = B3/S23 4177b2o$4177bobo$4179bo4b2o$4175b4ob2o2bo2bo$4175bo2bobobobob2o$4178bo bobobo$4179b2obobo$4183bo2$4169b2o$4170bo7b2o$4170bobo5b2o$4171b2o7$ 4181b2o$4181bo$4182b3o$4184bo2044$2146bo11b2o$2145bobo10b2o$2112b2o31b obo$2113bo25b2o2b3ob2o$2113bobo23bo2bo$2114b2o21bobo3b3ob2o$2137b2o6bo b2o7$2135b2o13b2o$2135b2o13b2o$2165b2o$2164bo2bo$2165b2obo$2168bo$ 2168b2o$2153b2o$2154bo$2126b2o23b3o$2126bo24bo$2127b3o$2120b2o7bo$ 2120bo$2121b3o$2123bo1970$2bo$bobob2o$o2bob2o$obo$bo! #C [[ THUMBSIZE 2 THEME 6 GRID GRIDMAJOR 0 SUPPRESS THUMBLAUNCH ]] #C [[ HEIGHT 600 WIDTH 600 THUMBNAIL THUMBSIZE 2 ZOOM -12 THEME 6 ]]
Southwest to northeast:
  • block-on-mango where construction-arm elbow starts,
  • Circuit A (syringe and H-to-2G),
  • Circuit B (Snark)

(click above to open LifeViewer)

Run slsparse the first time with

./slsparse.cpp

This creates an slsparse.exe file and automatically runs it. For future runs you can get away with just

./slsparse

until there's an update to the slsparse GitLabs repository, at which point you'll want to download and re-compile:

rm infile.mc
git pull
./slsparse.cpp

All of these commands are run directly from the slmake root folder.

When you run slsparse, if the program finds a way to build the contents of infile.mc, a single-channel recipe pattern is created in outfile.mc, with the outfile.txt listing the timing offsets between gliders.

The program currently appends lots of elbow block moves to the end of the recipe, to get the elbow back to where it started We don't want to go back that far, so we'll have to identify the exact point where the recipe produces a clean elbow block again after sending the final sideways glider. Remove all the gliders after that to get the useful part of the recipe.

You can do this by running the pattern until the first useless glider is about to hit the elbow. Then copy all the remaining useless recipe gliders, go back to T = 0, paste in at a 100-cell horizontal offset or so lined up exactly with the end of the full recipe, then select the doubled area and delete everything. An XOR paste would work if the gliders happened to be in the right phase, but it's much much slower.

(Or there's a sneaky trick: make a copy of progress.txt when the compiler reaches exactly the right point -- or arrange the requested construction so the compilation will fail at the last step and the final gliders are never added!)

In Step 8 we have to build the lossless-elbow Snark. Here's the input pattern. This time it's small enough to be a little easier to understand:

x = 68, y = 72, rule = B3/S23 63b2o$62bo2bo$61bob2obo$60bobo2bobo$60bobo2bobo$61bob2obo$62bo2bo$63b 2o5$48b2o$49bo$47bo$47b5o14b2o$52bo13bo$49b3o12bobo$48bo15b2o$48b4o$ 46b2o3bo3b2o$45bo2b3o4b2o$45b2obo$48bo$48b2o3$56b2o$57bo$54b3o$54bo37$ 4bo$2obobo$2obo2bo$4bobo$5bo! #C [[ THUMBSIZE 2 THEME 6 GRID GRIDMAJOR 0 SUPPRESS THUMBLAUNCH ]] #C [[ HEIGHT 720 WIDTH 720 THUMBSIZE 2 ZOOM 8 THEME 6 ]]
block-on-mango marking start location for construction-arm elbow, and the side where the glider stream will strike. The Snark is the target pattern to be constructed. Starting block location marked by large PS4B still life.
(click above to open LifeViewer)

Giving this to slsparse by saving it as infile.mc is essentially asking for a single-channel recipe starting with a block at the mango-on-block location, with gliders aimed to strike the right side of the block. If compilation is successful, the result will be a Snark placed in that precise location relative to the elbow block.

As described in the Variations section above, the large 24-bit 'PS4B' still life (pond siamese four beehives) in the above pattern marks the location of an existing target block. This tells slsparse to start with a block in this location, along with the mango-on-block elbow.

If the PS4B marker is not present, slsparse first automatically creates a target "hand" block and moves it to the correct location to start construction. In a multi-cluster constellation there may be several PS4Bs, and also several clusters with no PS4Bs; slsparse will automatically create new hand blocks when they're needed, and use existing ones if they have been marked.

For this last part of the Demonoid construction we have an awkward situation that needs a PS4B marker. The new temporary lossless-elbow Snark has to be built a very long distance from the actual construction elbow block. So we really don't want to create a hand block and push it all the way to the lossless-elbow Snark's intended location, way out at Circuit A. Instead we just mark the location of the leftover northeastern elbow block (from Step 5) relative to where we want the Snark to be, and slsparse does the rest.

More Features

  1. If infile.mc contains still lifes with a population of 32 cells or more, slsparse will not attempt to construct them -- but it will assume that they exist in the Life universe, and will attempt to find construction recipes for the remaining objects that do not damage the ≥32-bit obstacles. This can be very useful if you need to build a new structure in close proximity to an existing one. Replace the existing structures with equivalent large obstacles, and slsparse will obey the additional constraints.
  2. If a partition of the construction is sufficiently far away that it's cheaper for slsparse to build a Cordership seed, trigger it, wait until the Cordership has traveled sufficiently far away, shoot down the Cordership, clean up the debris except for a single block, and proceed with the construction from there... then slsparse will do this automatically.
  3. If an elbow has to be moved closer to the single-channel source by a long distance, such that it is cheaper for slsparse to generate a 180-degree return glider, wait until the glider is close to the elbow, hit it with another glider, and clean up the debris to regenerate an elbow, slsparse will do this automatically. This is accomplished with an elbow duplication recipe similar to the one used in the Demonoid above. If it is necessary to jump back and forth between two distant points, an elbow will be left behind at the more distant location. The recipes involved are called "left parenthesis" (duplicate the elbow, convert the nearer elbow to a glider, convert the glider back to an elbow at the right distance) and "right parenthesis" (delete the near elbow, and send a cleanup salvo to standardize the far elbow. The current recipe leaves the far elbow in the form of a random-looking junk constellation.)
  4. If a metacluster is in the construction "danger zone" -- i.e., if it overlaps the construction lane, so that some of the final structure would interfere with the elbow-operation reactions necessary to construct it -- then slsparse will send two Snarkmaker recipes, to bend the construction arm to one side of the construction area so that the structure can be put in place safely. When the construction is done, slsparse will add two Snarkbreaker recipes to remove the temporary lossless elbows.
  5. If a sufficiently narrow metacluster is in the construction danger zone, with the required construction gliders no farther to the side than +/-107hd from the single-channel lane, then slsparse will automatically generate a 0-degree elbow and produce the required gliders directly instead of using Snarkmaker / Snarkbreaker pairs.
  6. If an infile.mc pattern contains a block-on-mango plus a set of unidirectional gliders on appropriate lanes that they can be generated by the designated elbow, then slsparse will create a single-channel recipe that generates gliders on those lanes in the specified order. This allows for the color of an entire salvo to be changed easily: moving the block-on-mango by one cell orthogonally and recompiling will produce an opposite-color salvo. The assumption is that the gliders constitute a p2 slow-salvo recipe, so only the parities of the gliders will be preserved. In other words, the resulting output recipe will only be useful if no synchronization is needed between the unidirectional gliders.