Catagolue Discussion Thread

For general discussion about Conway's Game of Life.
vilc
Posts: 288
Joined: March 20th, 2024, 4:36 pm

Re: Catagolue Discussion Thread

Post by vilc » September 4th, 2025, 5:41 pm

The Gitlab job "shinjuku" has been timing out every time for five days : https://gitlab.com/hatsya/open-source/c ... kind=BUILD
The RLE responsible for this situation is the following :

Code: Select all

x = 0, y = 0, rule = B3/S23
obo$b2o14bobo$bo16b2o$18bo14$17bobo$18b2o$18bo270$289bo$289bobo16bo$289b
2o17bobo$273bobo10bo21b2o$274b2o11b2o$274bo11b2o3$283b2o20b2o$284b2o19b
obo9b3o$283bo21bo11bo$300bo17bo$300b2o$299bobo!
The far gliders start interacting after time 1000, which has confused (as expected) split_synthesis into thinking that there were two parts. The fact that the resulting pattern when those gliders are removed is a gun made things worse, since encode_comp doesn't know about guns.

Adding this after line 130 in initialise/constrsynth.py should allow the script to detect this problem and skip the RLE.

Code: Select all

elif dst[:2] == 'xg':
	print('# dst is a gun; skipping...')
To everyone submitting syntheses to Catagolue, please always check your pattern against the requirements specified above the nonmagical box and according the rules of common sense. Submitting a large (and suboptimal) synthesis of a boring glider flotilla using a well-known technique is not only harmful for the internals of Catagolue, but also utterly pointless.

User avatar
apg
Moderator
Posts: 3005
Joined: June 1st, 2009, 4:32 pm

Re: Catagolue Discussion Thread

Post by apg » September 10th, 2025, 5:08 am

vilc wrote:
September 4th, 2025, 5:41 pm
Adding this after line 130 in initialise/constrsynth.py should allow the script to detect this problem and skip the RLE.

Code: Select all

elif dst[:2] == 'xg':
	print('# dst is a gun; skipping...')
Apologies for the delay; I was in France until now. I've applied your patch so Catagolue will hopefully repair itself now.
What do you do with ill crystallographers? Take them to the mono-clinic!

User avatar
Resu
Posts: 774
Joined: May 23rd, 2025, 10:47 am
Location: In an age of macro-spaceships
Contact:

Re: Catagolue Discussion Thread

Post by Resu » September 11th, 2025, 4:04 pm

What is ror_stdin_test?

Code: Select all

x = 31, y = 13, rule = C
8.2X2.3X.3X.X.X$8.X.X.X3.X3.X.X$8.X.X.3X.3X.X.X$8.2X2.X5.X.X.X$8.X.X.
3X.3X.3X$M2.M$4.M$M3.M$.4M$27.2M$27.M.M$29.M$29.2M! [[ AUTOSTART GPS 10 ]]

WhiteHawk
Posts: 1198
Joined: July 10th, 2024, 5:34 pm

Re: Catagolue Discussion Thread

Post by WhiteHawk » September 11th, 2025, 4:09 pm

Resu wrote:
September 11th, 2025, 4:04 pm
What is ror_stdin_test?
I think it's an analysis of life-compatible patterns which work in a given rule and Life without failing.

It's not universally applied to life-like rules, nor are they updated regularly (e.g. I have asked for several Ror_Stdin_Tests/updated versions for several near-life rules without success) - perhaps they were someone's personal project that they ultimately abandoned.
Currently working to improve Life's guns and work on updating SKOPs and Isotropic rules most similar to B3/S23 to Life standards. Will get software to begin searches eventually.

Pseudastur albicollis

User avatar
PK22
Posts: 564
Joined: January 25th, 2025, 11:38 am
Location: United Kingdom

Re: Catagolue Discussion Thread

Post by PK22 » October 23rd, 2025, 4:44 pm

The update process for syntheses (and smaller guns) has broken again. This time, the issue occurs during 'staging', and always happens shortly after the Google Cloud SDK repository is not found and has to be installed, and this causes the subsequent Shinjuku job to be skipped.

I looked through the code which handles the update process and the log output, and I have no idea what the problem is, but if it helps, the error occurs during this line:

Code: Select all

$ apt-get install -y maven openjdk-17-jdk make mingw-w64 mingw-w64-x86-64-dev
Successful staging:

Code: Select all

Google Cloud SDK directory does not exist; installing...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   443  100   443    0     0   5928      0 --:--:-- --:--:-- --:--:--  5986
Activated service account credentials for: [[email protected]]
Compared to unsuccessful staging:

Code: Select all

Google Cloud SDK directory does not exist; installing...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   443  100   443    0     0   5935      0 --:--:-- --:--:-- --:--:--  5986
Cleaning up project directory and file based variables
00:01
ERROR: Job failed: exit code 1
User:PK22
Currently taking exams; unlikely to be active until mid June.
17/25 exams completed.

WhiteHawk
Posts: 1198
Joined: July 10th, 2024, 5:34 pm

Re: Catagolue Discussion Thread

Post by WhiteHawk » October 23rd, 2025, 8:52 pm

Just wanted to remind everyone that, in addition to the brief Catagolue shutdown, there are still two problems resulting in erroneous gun submissions in catagolue which have still not been resolved and probably require clearing that data outright and replacing it with corrected versions.

To demonstrate a new effect caused by wrongly-calculated guns being accepted during the bounding box glitch, here is the current submission for guntrue_432, which shows a glider that doesn't even escape the actual bounding box, which means this gun exist in the database in the outright wrong form. (Even funnier is guntrue_520, which doesn't even show an escaping glider, just the end of the transparent beehive reaction - the glider escapes a full 97 generations later)

Code: Select all

x = 50, y = 32, rule = B3/S23
18bo$6bo5bo5b3o7b2o$5bobo3bobo7bo5bo2bo$4bo2bo3bobo6b2o6b2o$4bobob2ob
ob3o$5b2obob2o4bo20b2o$8bo3b3o9b3o10bo$5b2ob2obobo10bo10bobo$5bob2obo
7bo5bo10b2o$2b2obobobo2b3o10b2obo$3bo2bo2b2obo4bo10b2o$3bo5bo2bob2o$4b
4obob2obo$8b2obo3bo18bo$6bo5b2ob3o16b2o4b3o$6b6o2bo3bo15b2o3bo$12bobo
2b2o16bo3bo3bo$4b8obo25bo2bobo$4bo6bo7b3o19bobo2bo$6b2obo2bo29bo3bo$2b
4obob2obo4bo5bo22bo$bo5bo2bob2o3bo5bo19b3o$bo2b2o2bobo3bo2bo5bo$2obob
4obo3bo24bo$3bo2bo3bo3bo4b3o16bobo$3b2o3b2o4bo24bo3b2o3b2o$5b2o3b2ob2o
27b2o4b2o$3b2obob2o3bo13bo14b2o$2bobob2obob2o9b3ob2o2b2o10b3o$2bo2bo3b
obo10b4o4b2o7bo3b2o$3bobo3bobo14b2o12bo$4bo5bo27b3o!
Even worse, not only is guntrue_816 also in the wrong form in Catagolue according to the logic above, but the error with the BB causes a situation where the gun could be compacted more, but due to the BB glitch the reduction is rejected.

Code: Select all

x = 54, y = 43, rule = B3/S23
32bo$22bo7b3o$21bobo5bo$22bo6b2o$27b3o$25b4o$24b2o3bo18b2o$23bo3b2o19b
o$24b4o18bobo$18b2o5bo3b3o14b2o$17bobo23b2o$17bo10bobob2o8bobo$16b2o10b
obob2o10bo5b2o$20b2o10bo17bo$19bobo26bobo$12b2o5bo17bo10b2o$11b3o4b2o
5bo10b2obobo10b2o$10bob2o11bobo8b2obobo10bo$9bobo13b2o23bobo$9bo2bo25b
3o3bo5b2o$10b2o30b4o$4b2o35b2o3bo$3bobo34bo3b2o$3bo37b4o$2obo36b3o$bo
bob2o32b2o6bo$bobob2o33bo5bobo$2obo7b2o15b2o7b3o7bo$o2b4o3bo2bo7b2o5b
2obo5bo$b2o3bo4b2o8bobo8bo$3b2o18bo5bo$3bo19b2o5bob2o$5bo26b2o$4b2o2$
10b2o15bo$6b2o4b4o10bobo$6b2o2b2ob3o11bo4b6o$10bo20bo2b4o$30bo2b2o$26b
o4b2o$27bo$25b3o!
I could also rant about the pointless densification, but since I have already done that elsewhere (to the point where there is a full thread for it), I don't think it's constructive to continue ranting about that here. I will just link whatever monstrosity someone submitted for guntrue_660 - yes, that weld is real for some reason (is this the only gun below 1000 with this nasty of a problem?).

EDIT: And it turns out that the guntrue_660 also has an incorrect bounding box miscalculation (correct form with correct envelope below). This just drives home the point that the BB glitch is ultimately a very persistent and problematic issue that really needs to be fixed.

Code: Select all

x = 46, y = 43, rule = LifeHistory
3.2A.A4.2A18.2A7.A$3.A.4A.A.A14.2A.A.A5.3A$9.2A5.2A9.2A.A6.A$7.A4.A2.
A.3A10.BAB4.2A$6.A.8A4.A6.3ABA3B.2AB$6.A9.2AB.A6.A.3B.4A$4.2A.7ABA2BA
.2AB5.BA4B2ABA$5.A.B2.A2.B.A2.BA2.AB5.A4BAB2A$3.ABA.BA.BA2BAB2.B2AB2A
7.2A3.B$2.A5B2.BA2BA2BA.3B2AB4.3B8.A.A$3.2A.2A4.A2.B3A2B3A2B.4B9.2A.A
$14.BA.B2AB3A8B11.A$15.2A.A2.BAB.8B5.5A.2A$16.A.A.2A3.8B4.AB3.A.A$16.
A.A.A5.8B3.3B3A.A$11.3B3.A2.A6.8B3.2B2A2.2A$11.B3A3.2A5.4B3A3B3.2BA.B
A$10.A.3A9.4BA3BA5B2.2A.A$9.A.A.AB8.4BA5BA4B3.A.A.A$9.A2.A2.2B5.6BA3B
A4B4.A2.2A$10.2A3.3B3.4B2.2B3A4B4.2A$4.2A9.3B.5B5.6B$3.A.A8.9B4.5B$3.
A8.B.8B5.2A$2A.AB.B3.11B7.A$.A.A.2AB.12B4.3A$.A.A.2A14B4.A$2A.A2.5B2A
8B12.2B$A2.4A3BA2BA5B.B2A8.6B$.2A2.BAB.2B2A6B.BA.A5.10B$3.2A6.7B5.A3.
4BA4BA4B$3.A7.2B.4B5.2A.3B2AB4AB2A3B$5.A9.4B8.4BA4BA4B$4.2A10.4B9.10B
$17.4B10.6B$18.4B11.2B$19.4B7.3B2.3B$20.4B4.B3A4B3AB$21.5B.6A2B6A$22.
5BAB3A4B3AB$23.3B2AB.2B4.2B$24DABA19D$25D2A19D!
Currently working to improve Life's guns and work on updating SKOPs and Isotropic rules most similar to B3/S23 to Life standards. Will get software to begin searches eventually.

Pseudastur albicollis

User avatar
apg
Moderator
Posts: 3005
Joined: June 1st, 2009, 4:32 pm

Re: Catagolue Discussion Thread

Post by apg » October 24th, 2025, 6:14 am

PK22 wrote:
October 23rd, 2025, 4:44 pm
The update process for syntheses (and smaller guns) has broken again. This time, the issue occurs during 'staging', and always happens shortly after the Google Cloud SDK repository is not found and has to be installed, and this causes the subsequent Shinjuku job to be skipped.

I looked through the code which handles the update process and the log output, and I have no idea what the problem is, but if it helps, the error occurs during this line:
I've unblocked the problem. The issue was that the container image was using Python 3.8, and Google recently bumped the minimum version for their cloud SDK to Python 3.9. The error was being swallowed by the 2>/dev/null 1>/dev/null which I've replaced with a more precise way of suppressing the output from the tar command: https://gitlab.com/hatsya/open-source/c ... b961df9586
What do you do with ill crystallographers? Take them to the mono-clinic!

hotdogPi
Moderator
Posts: 2203
Joined: August 12th, 2020, 8:22 pm

Re: Catagolue Discussion Thread

Post by hotdogPi » October 24th, 2025, 11:25 am

Can someone please fix the verification backlogs in https://catagolue.hatsya.com/haul/b3s23 ... ommitted=1 and https://catagolue.hatsya.com/haul/b3s23 ... ommitted=1 ? They're only showing the most recent 100, but I have a feeling the first one in particular is larger than the number of completed hauls (currently 423 and increasing by only 3-5 per hour even though the backlog gets about 60 new hauls each hour).
User:HotdogPi/My discoveries

Periods discovered:

All evens ≤128 except 52,58,78,82,92,94,98,104,118,122

5-15,㉕-㉛,㉟㊺,51,63,65,73,75
1㊳㊵㊹㊼㊽,54,56,72,74,80,90,92
217,240,300,486,576

Guns: 20,21,32,54,55,57,114,117,124,126
SKOPs: 32,74,76,102,196

User avatar
PK22
Posts: 564
Joined: January 25th, 2025, 11:38 am
Location: United Kingdom

Re: Catagolue Discussion Thread

Post by PK22 » October 24th, 2025, 12:24 pm

hotdogPi wrote:
October 24th, 2025, 11:25 am
Can someone please fix the verification backlogs in https://catagolue.hatsya.com/haul/b3s23 ... ommitted=1 and https://catagolue.hatsya.com/haul/b3s23 ... ommitted=1 ? They're only showing the most recent 100, but I have a feeling the first one in particular is larger than the number of completed hauls (currently 423 and increasing by only 3-5 per hour even though the backlog gets about 60 new hauls each hour).
I’ve started trying. It takes a while, but configuring regular apgmera for b3s23/D8_1 and running it with -v 20 (or a large number) prompts it to start reviewing H8_1 hauls. I assume a similar method will work for the other clogged backlogs. I am not sure why the hacked version does not review hauls.

I should have access to my powerful desktop computer in an hour or two, and then I will start clearing the backlogs.

EDIT: It still takes a while, due to the size of the hauls, and I think that for H4_x1, they are being uploaded faster than I can verify them.

EDIT 2: ObjectServlet.java needs an update to allow Catagolue to properly 'officially' support the new GPU symmetries; here is the updated version:

Code: Select all

package com.cp4space.catagolue.servlets;

import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import com.cp4space.catagolue.census.Census;
import com.cp4space.catagolue.census.CommonNames;
import com.cp4space.catagolue.patterns.GolObject;
import com.cp4space.payosha256.PayoshaUtils;
import com.cp4space.catagolue.utils.SvgUtils;
import com.cp4space.catagolue.servlets.HashsoupServlet;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;

public class ObjectServlet extends ExampleServlet {

    public static boolean isExplicit(String apgcode) {

        return (apgcode.charAt(0) == 'x');

    }

    public static int isUnofficial(String symmetry) {

        if (symmetry.contains("/")) {
            // Combined rulesym. Take the final component:
            String[] symparts = symmetry.split("/");
            return isUnofficial(symparts[symparts.length - 1], symparts[0]);
        } else {
            return isUnofficial(symmetry, "");
        }

    }

    public static int isUnofficial(String symmetry, String rule) {

        int symstat = 2;

        if ((symmetry.length() <= 1) || (symmetry.length() > 50)) {
            // Placing this first prevents later recursion limit problems.
            symstat = 4;
        } else if (symmetry.contains("wwei") || symmetry.contains("nonymous") || symmetry.contains("replit")) {
            // Troll symmetry:
            symstat = 3;
        } else if (symmetry.equals("Uploads") || symmetry.equals("Saka_Test") || symmetry.equals("heavgolue") || symmetry.equals("yujhparty") || symmetry.equals("textarea")) {
            // More troll symmetries:
            symstat = 3;
        } else if (symmetry.charAt(0) == 'i') {
            // Inflated symmetry:
            symstat = isUnofficial(symmetry.substring(1), rule);
            if (symstat < 1) { symstat = 1; }
        } else if ((rule == null) || (rule.length() == 0)) {
            // Possible official symmetry on ANY grid:
            if(isOfficialSquare(symmetry) || isOfficialHex(symmetry)) { symstat = 0; }
        } else if (rule.charAt(rule.length() - 1) != 'h') {
            // Possible official symmetry on a square grid:
            if(isOfficialSquare(symmetry)) { symstat = 0; }
        } else {
            // Possible official symmetry on a hex grid:
            if(isOfficialHex(symmetry)) { symstat = 0; }
        }

        return symstat;

    }

    public static String[] getOfficialSquareSymmetries() {

        String[] offsyms = {"1x256", "2x128", "4x64", "8x32", "C1", // asymmetric;
            "C2_1", "C2_2", "C2_4", "C4_1", "C4_4", // cyclic;
            "D2_x", "D2_+1", "D2_+2", "D8_1", "D8_4", // dihedral;
            "D4_+1", "D4_+2", "D4_+4", "D4_x1", "D4_x4", // dihedral;
            // "D2_+1_gO1s0", "D2_+1_gO1s1", "D2_+1_gO1s2", // dihedral (w/ gutter);
            "G1", // asymmetric (GPU);
            "G2_1", "G2_2", "G2_4", "G4_1", "G4_4", // cyclic (GPU);
            "H2_+1", "H2_+2", "H2_x", "H8_1", "H8_4", // dihedral (GPU);
            "H4_+1", "H4_+2", "H4_+4", "H4_x1", "H4_x4"}; // dihedral (GPU).

        return offsyms;
    }

    public static boolean isOfficialSquare(String symmetry) {

        String[] offsyms = getOfficialSquareSymmetries();

        for (int i = 0; i < offsyms.length; i++) {
            if (symmetry.equals(offsyms[i])) { return true; }
        }

        return false;

    }

    public static boolean isOfficialHex(String symmetry) {

        String[] offsyms = {"1x256", "2x128", "4x64", "8x32", "C1", // asymmetric;
            "C2_1", "C2_4", "C3_1", "C3_3", "C6", // cyclic;
            "D2_x", "D2_xo", "D4_x1", "D4_x4", "D6_1", // dihedral;
            "D6_1o", "D6_3", "D12"}; //dihedral.

        for (int i = 0; i < offsyms.length; i++) {
            if (symmetry.equals(offsyms[i])) { return true; }
        }

        return false;

    }

    /**
     * Auto-generated by Eclipse:
     */
    private static final long serialVersionUID = 1L;

    @Override
    public String getTitle(HttpServletRequest req) {

        String apgcode = req.getParameter("apgcode");
        String pathinfo = req.getPathInfo();

        if (pathinfo != null) {
            String[] pathParts = pathinfo.split("/");
            if ((pathParts.length >= 2) && (apgcode == null)) {
                apgcode = pathParts[1];
            }
        }

        if (apgcode == null) {
            return "No object specified";
        } else {

            Map<String, String> namemap = new HashMap<String, String>();
            CommonNames.getNamemap("std", namemap, false);

            if (namemap.containsKey(apgcode)) {
                return " (" + apgcode + ")!" + namemap.get(apgcode);
            } else {           
                return apgcode;
            }
        }
    }

    @Override
    public void writeHead(PrintWriter writer, HttpServletRequest req) {

        String rulestring = req.getParameter("rule");
        String apgcode = req.getParameter("apgcode");
        String pathinfo = req.getPathInfo();
        if (pathinfo != null) {
            String[] pathParts = pathinfo.split("/");
            if ((pathParts.length >= 2) && (apgcode == null)) {
                apgcode = pathParts[1];
            }
            if ((pathParts.length >= 3) && (rulestring == null)) {
                rulestring = pathParts[2];
            }
        }

        if ((rulestring == null) || (apgcode == null)) { return; }
        if ((rulestring.equals("")) || (apgcode.equals(""))) { return; }

        String slashed = HashsoupServlet.gollifyRule(rulestring);
        writer.println("<script type='text/javascript' src='/js/rle_tools.js'></script>");
        writer.println("<script type='text/javascript' src='/js/codebox.js'></script>");
        writer.println("<script type='text/javascript'>");
        writer.println("function do_it() {");
        writer.println("    var rle = cells_to_rle(decodeCanon(\"" + apgcode + "\"), \"" + slashed + "\");");
        writer.println("    var prerle = \"#C [[ GRID THUMBLAUNCH THUMBSIZE 2 THEME Catagolue ]] <br>\\n\";");
        writer.println("    var code = document.getElementById('code0');");
        writer.println("    code.innerHTML = rle;");
        writer.println("    var code1 = document.getElementById('code1');");
        writer.println("    code1.innerHTML = prerle.concat(rle);");
        writer.println("  }");
        writer.println("</script>");
        writer.println("<style type='text/css'><!--");
        writer.println("div.codebox { padding: 3px; background-color: #FFFFFF; border: 1px solid #d8d8d8; font-size: 1em; }");
        writer.println("div.selall { text-transform: uppercase; border-bottom: 1px solid #CCCCCC; margin-bottom: 3px; font-size: 0.8em; font-weight: bold; display: block; }");
        writer.println("blockquote div.codebox { margin-left: 0; }");
        writer.println("div.codebox code { overflow: auto; display: block; height: auto; max-height: 200px; white-space: normal; padding-top: 5px;font: 0.9em Monaco, \"Andale Mono\",\"Courier New\", Courier, mono; line-height: 1.3em; color: #8b8b8b; margin: 2px 0; }");
        writer.println("--></style>");

    }

    @Override
    public void writeContent(PrintWriter writer, HttpServletRequest req) {

        String rulestring = req.getParameter("rule");
        String apgcode = req.getParameter("apgcode");

        String pathinfo = req.getPathInfo();
        if (pathinfo != null) {
            String[] pathParts = pathinfo.split("/");
            if ((pathParts.length >= 2) && (apgcode == null)) {
                apgcode = pathParts[1];
            }
            if ((pathParts.length >= 3) && (rulestring == null)) {
                rulestring = pathParts[2];
            }
        }

        if (apgcode == null || apgcode.length() == 0) {

            writer.println("<p>No object has been specified. Please provide a valid apgcode to describe the object.</p>");
            writer.println("<p>Sample objects:</p>");

            writer.println("<ul>");
            writer.println("<li><a href=\"/object/xp15_4r4z4r4/b3s23\">pentadecathlon (b3s23)</a></li>");
            writer.println("<li><a href=\"/object/xs15_354cgc453/b3s23\">moose antlers (b3s23)</a></li>");
            writer.println("<li><a href=\"/object/xq7_3nw17862z6952/b3s23\">loafer (b3s23)</a></li>");
            writer.println("<li><a href=\"/object/xq3_mhqkzarahh0heezdhb5/b3s23\">dart (b3s23)</a></li>");
            writer.println("<li><a href=\"/object/xp138_w8gw259r84z79431y1go4iszx42rik8w12/b3s23\">Gabriel's p138 (b3s23)</a></li>");
            writer.println("<li><a href=\"/object/xq48_07z8ca7zy1e531/b36s23\">bomber (b36s23)</a></li>");
            writer.println("</ul>");

            writeIdentifyBox(writer, req);

            writer.println("<p>Alternatively provide an apgcode and rulestring:</p>");

            writer.println("<form action=\"/object\" method=\"GET\">");
            writer.println("<table><tr><td><b>apgcode:</b></td><td colspan=\"2\"><input type=\"text\" name=\"apgcode\" size=\"40\"></td></tr>");
            writer.println("<tr><td><b>rule:</b></td><td><input type=\"text\" name=\"rule\" value=\"b3s23\"></td>");
            writer.println("<td><input type=\"submit\" value=\"Submit\"></td></tr></table>");
            writer.println("</form>");

        } else if (rulestring == null || rulestring.length() == 0) {

            writer.println("<p>No rule has been specified. Please specify a rule or choose the " +
                    "<a href=\"/object/" + apgcode + "/b3s23\">default (b3s23)</a>.</p>");

            writeComments(writer, req, "object_"+apgcode, CensusServlet.isAdmin());

        } else {

            GolObject golObject = new GolObject(rulestring, apgcode);

            if (golObject.validatePattern()) {

                writer.println("<table cellspacing=1>");
                writer.println("<tr><td>");
                if (isExplicit(apgcode)) {
                    writer.println("<script type='text/javascript' src='/js/lv-plugin.js'></script>");
                    writer.println("<div class=\"rle\"><div style=\"display:none;\">");
                    writer.println("<code id=\"code1\">#C [[ GRID THUMBLAUNCH THUMBSIZE 2 THEME Catagolue ]] <br>x = 1, y = 1, rule = B3/S23<br>b!</code></div>");
                    writer.println("<canvas width=\"240\" height=\"240\" style=\"margin-left:1px;\"></canvas></div>");
                } else {
                    SvgUtils.apgToSvg(writer, rulestring, apgcode, 320, 320, 20);
                }
                writer.println("</td><td style=\"vertical-align:top\">");
                /*
                writer.println("<p>");
                golObject.inlineDescription(writer);
                writer.println("</p>");
                */
                golObject.inlineAttributes(writer);
                writer.println("</td></tr>");
                writer.println("</table>");

                {
                    Map<String, String> namemap = new HashMap<String, String>();
                    CommonNames.getNamemap("nfts", namemap, false);

                    if (namemap.containsKey(apgcode)) {
                        String[] identifiers = namemap.get(apgcode).split("|");

                        writer.println("<h3>Non-fungible token</h3>");
                        writer.println("<table cellspacing=1><tr><td style=\"vertical-align:top\">");
                        writer.println("<p>A <b>non-fungible token</b> of this pattern");
                        if (identifiers[1].equals("unminted")) {
                            writer.println("will be");
                        } else {
                            writer.println("has been");
                        }
                        writer.println("minted by its discoverer, available <a href=\"/nfts/" + identifiers[0] + "\">here</a>.</p>");
                        writer.println("</td><td>");
                        writer.println("<img src=\"/autogen/nfts/" + identifiers[0] + ".gif\" />");
                        writer.println("</td></tr></table>");
                    }
                }

                if (isExplicit(apgcode)) {
                    writer.println("<h3>Pattern RLE</h3>");
                    writer.println("<div class=\"rle\"><div class=\"codebox\"><div class=\"selall\">");
                    writer.println("Code: <a href=\"\" onclick=\"selectCode(this); return false;\">Select all</a>");
                    writer.println("</div><div><code id=\"code0\"></code></div></div>");
                    writer.println("<img src=\"/images/Clear.gif\" onload=\"do_it()\" /></div>");

                }

                DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
                String synthesis = Census.getMetadatum(datastore, rulestring, apgcode, "synthesis");

                if (synthesis != null) {

                    writer.println("<h3>Glider synthesis</h3>");
                    writer.println("<script type='text/javascript' src='/js/lv-plugin.js'></script>");
                    writer.println("<div class=\"rle\"><div class=\"codebox\"><div class=\"selall\">");
                    writer.println("Code: <a href=\"\" onclick=\"selectCode(this); return false;\">Select all</a>");
                    writer.println("</div><div><code id=\"code2\">#C [[ GRID MAXGRIDSIZE 14 THEME Catagolue ]] <br>");
                    writer.println(synthesis.replace("\n", "<br>\n"));
                    writer.println("</code></div></div>");
                    writer.println("<canvas width=\"900\" height=\"480\" style=\"margin-left:1px;\"></canvas></div>");

                }

                writer.println("<h3>Sample occurrences</h3>");

                String occurrences = Census.getMetadatum(datastore, rulestring, apgcode, "samples");

                if (occurrences == null || occurrences.length() <= 1) {
                    writer.println("<p>There are no sample soups stored in the Catagolue.</p>");
                } else {
                    String[] parts = occurrences.split("\n");

                    Map<String, Collection<String> > map = new TreeMap<String, Collection<String>>();

                    int abstotal = 0;

                    for (String part : parts) {
                        String symmetry = part.split("/")[0];

                        if (isUnofficial(symmetry) >= 3) { continue; }

                        abstotal += 1;

                        Collection<String> values = map.get(symmetry);
                        if (values==null) {
                            values = new ArrayList<String>();
                            map.put(symmetry, values);
                        }
                        values.add(part.replaceAll("%", "pct"));
                    }

                    if (abstotal == 0) {
                        writer.println("<p>There are no sample soups stored in the Catagolue.</p>");
                    } else {
                        writer.println("<p>There are "+String.valueOf(abstotal)+" sample soups in the Catagolue:");
                    }

                    for (int i = 0; i < 3; i++) {

                        boolean used = false;

                        for (Map.Entry<String, Collection<String> > entry : map.entrySet()) {

                            String symmetry = entry.getKey();
                            String symmetry2 = symmetry;
                            if (symmetry2.charAt(0) == 'G') {
                                symmetry2 = "C" + symmetry2.substring(1);
                            } else if (symmetry2.charAt(0) == 'H') {
                                symmetry2 = "D" + symmetry2.substring(1);
                            }

                            int symstat = isUnofficial(symmetry2);
                            if (symstat != i) { continue; }
                            String linkcolour  = "blue";
                            try {

                                if (symmetry2.equals("C1")) {
                                    linkcolour  = "black";
                                } else {
                                    MessageDigest md = MessageDigest.getInstance("SHA-256");
                                    md.update(symmetry2.getBytes("UTF-8"));
                                    String hexbytes = PayoshaUtils.bytesToHex(md.digest());
                                    linkcolour  = "#" + hexbytes.substring(0,6);
                                }
                            } catch (UnsupportedEncodingException e) {

                            } catch (NoSuchAlgorithmException e) {

                            }

                            if (!used) {
                                used = true;
                                if (i == 0) { writer.println("<h4>Official symmetries</h4>"); }
                                if (i == 1) { writer.println("<h4>Inflated symmetries</h4>"); }
                                if (i == 2) { writer.println("<h4>Unofficial symmetries</h4>"); }
                                if (i == 3) { writer.println("<h4>Troll symmetries</h4>"); }

                                writer.println("<table style=\"background:#a0ddcc;border:2px solid;border-radius:10px;width:100%\">");
                                writer.println("<tr><th>Symmetry</th><th>Soups</th><th>Sample soup links</th></tr>");
                            }


                            writer.println("<tr><td colspan=\"3\" style=\"padding-top:0;padding-bottom:0;margin:0\"><hr style=\"margin:0\" /></td></tr><tr>");
                            writer.println("<td style=\"max-width:200px;width:200px;min-width:200px\"><a href=\"/census/" + rulestring + "/" + symmetry + "\">" + symmetry + "</a></td>");
                            writer.println("<td>" + entry.getValue().size() + "</td><td>");

                            int ii = 0;
                            for (String part : entry.getValue()) {

                                String elem = "&bull;";
                                String lcol = linkcolour;

                                writer.print("<a style=\"word-break:break-all;color:" + lcol + "\" href=\"/hashsoup/" + part + "/" + rulestring + "\">" + elem + "</a>&nbsp;");
                                ii += 1; if (ii % 5 == 0) { writer.println("&emsp;"); }
                            }

                            writer.println("</td></tr>");


                        }
                        if (used) { writer.println("</table>"); }
                    }

                    writer.println("</p>");
                }

                writeComments(writer, req, "object_"+apgcode, true);

            } else {

                writer.println("<p>The apgcode prefix does not accurately reflect the behaviour " +
                        "of the pattern encoded in the suffix under the specified rule. As such, the " +
                        "provided apgcode is invalid in this rule.</p>");

            }
        }
    }
}
User:PK22
Currently taking exams; unlikely to be active until mid June.
17/25 exams completed.

User avatar
muzik
Posts: 6558
Joined: January 28th, 2016, 2:47 pm
Location: Scotland

Re: Catagolue Discussion Thread

Post by muzik » December 6th, 2025, 6:47 am

Is it possible to increase the permitted apgcode length that Catagolue can display object pages for?:
https://catagolue.hatsya.com/object/xq6 ... 2431/b3s23
Parity Replicator Collection v1.6 is now live - please send all relevant discoveries here.

UnbihexiumFan
Posts: 114
Joined: December 14th, 2025, 5:29 pm
Location: I don't know, but my momentum is 119.61527592631098241526716413 m·kg/s
Contact:

Re: Catagolue Discussion Thread

Post by UnbihexiumFan » December 25th, 2025, 9:00 pm

What is going on with the Morley C1 census? It is claimed that gliders have appeared in Morley 33 million times, and stable dots have appeared in Morley 7 million times, but given the non-existence of gliders and stable dots in Morley I highly doubt this.

User avatar
PK22
Posts: 564
Joined: January 25th, 2025, 11:38 am
Location: United Kingdom

Re: Catagolue Discussion Thread

Post by PK22 » December 26th, 2025, 7:51 am

UnbihexiumFan wrote:
December 25th, 2025, 9:00 pm
What is going on with the Morley C1 census? It is claimed that gliders have appeared in Morley 33 million times, and stable dots have appeared in Morley 7 million times, but given the non-existence of gliders and stable dots in Morley I highly doubt this.
It was probably some error where someone searched an S0 rule (S0 can support gliders), but for whatever reason their version of apgsearch uploaded it under the rule b368s245. Here are some hauls that got rejected for containing dots and gliders.

On the topic of faulty censuses, there's a problem with b3s23/H2_x, which I unintentionally caused. On October 17th, 5 days before support for all GPU symmetries was implemented by mvr, I modified apgmera code so that it would search H2_x, but it turns out it only filtered soups seemingly at random, rather than filtering uninteresting soups. As a result, later H2_x hauls contain much higher proportions of oscillators such as figure eights and mazings, causing them to get rejected when reviewed by Catagolue.

I don't know the best way to fix the above, but the following could work:
  • Temporarily modifying Catagolue so that a 1B soup 'proper' haul can be uploaded, which should fix the statistical checks.
  • Wiping the H2_x census (probably the safest option).
  • Using a series of increasingly accurate hauls to correct the statistical checks. (A little dangerous)
Also, my merge requests to fix overdensification of guns and officially support GPU symmetries have been open for a while now - it would be great if they could be approved.
User:PK22
Currently taking exams; unlikely to be active until mid June.
17/25 exams completed.

WhiteHawk
Posts: 1198
Joined: July 10th, 2024, 5:34 pm

Re: Catagolue Discussion Thread

Post by WhiteHawk » December 26th, 2025, 7:00 pm

PK22 wrote:
December 26th, 2025, 7:51 am
Also, my merge requests to fix overdensification of guns and officially support GPU symmetries have been open for a while now - it would be great if they could be approved.
Is there a merge request for fixing faulty bounding boxes too?
Currently working to improve Life's guns and work on updating SKOPs and Isotropic rules most similar to B3/S23 to Life standards. Will get software to begin searches eventually.

Pseudastur albicollis

User avatar
PK22
Posts: 564
Joined: January 25th, 2025, 11:38 am
Location: United Kingdom

Re: Catagolue Discussion Thread

Post by PK22 » December 26th, 2025, 7:21 pm

WhiteHawk wrote:
December 26th, 2025, 7:00 pm
Is there a merge request for fixing faulty bounding boxes too?
Not yet. The most recent accepted request prevents new erroneous entries, but my requests only fix overdensification of guns.

If I recall correctly, Catagolue uses lifelib to work out the bounding box of the submitted gun, but only uses the saved bounding box area (from synthesis-costs) for the current gun. The simple fix would be to download the current gun’s rle and work out the area using the current algorithm, but that’s more computing time and resources. (My overdensification fix only downloads the gun’s rle if the compared bounding boxes are the same, but this fix would require a download for every submitted gun.)
User:PK22
Currently taking exams; unlikely to be active until mid June.
17/25 exams completed.

User avatar
b-engine
Posts: 3746
Joined: October 26th, 2023, 4:11 am
Location: Somewhere on where Earth At
Contact:

Re: Catagolue Discussion Thread

Post by b-engine » January 14th, 2026, 5:48 pm

Catagolue is probleming [sic] again.
hotcrystal0 wrote:
January 14th, 2026, 4:26 pm
yyh_baboon wrote:
January 13th, 2026, 9:50 pm
hotcrystal0 wrote:
January 13th, 2026, 9:40 pm
Why do guns uploaded to Travelling_Ts_Collections_stdin always get cut off? For example, this is the P420 gun as shown on Catagolue:

Code: Select all

x = 0, y = 0, rule = B3/S23-a5
66bo$64b2ob2o$64bo2bo$64bo$64b2o$65bobo$66bo$49b2o$48b5o$48bo3bo$48b2o
I guess this is because the gun consists of sparse objects, and Catagolue automatically tries to split them into parts.
I think the RLEs somehow get cut off at newlines, as evident by the fact that there is no ! at the end of the RLE.
(Can't find the oddities thread, so I have to post here)

User avatar
PK22
Posts: 564
Joined: January 25th, 2025, 11:38 am
Location: United Kingdom

Re: Catagolue Discussion Thread

Post by PK22 » January 14th, 2026, 6:02 pm

b-engine wrote:
January 14th, 2026, 5:48 pm
Catagolue is probleming [sic] again.
hotcrystal0 wrote:
January 14th, 2026, 4:26 pm
I think the RLEs somehow get cut off at newlines, as evident by the fact that there is no ! at the end of the RLE.
(Can't find the oddities thread, so I have to post here)
This is a problem with apgsearch, not Catagolue. When there are newlines in the input RLEs used for stdin symmetries, apgsearch uses the headers (x = 0) to identify when an RLE starts and stops, but only uploads the first line of the RLE's actual content. Golly and lifelib add newlines to RLEs to keep them more human readable, but this can lead to problems as seen here.

For each RLE, just manually remove the newlines, or hack together a Python/Lua script to do it for you. As you can see, the full RLE of the p420 gun got uploaded in this haul.
User:PK22
Currently taking exams; unlikely to be active until mid June.
17/25 exams completed.

User avatar
R2INT
Posts: 775
Joined: July 2nd, 2024, 7:42 pm

Re: Catagolue Discussion Thread

Post by R2INT » January 24th, 2026, 10:35 pm

It seems like Catagolue is broken for B0 rules (there are uncommitted hauls from 1-2 years ago):
https://catagolue.hatsya.com/haul/b023- ... ommitted=0
Range-2 INT
R2INT's Rule Collection

Currently missing OCA catalyst search software and OCA conduit search software (the one I have is hardcoded to B3/S23-a5)

User avatar
Rhombic
Posts: 1099
Joined: June 1st, 2013, 5:41 pm

Re: Catagolue Discussion Thread

Post by Rhombic » March 5th, 2026, 3:16 pm

This gun (stabilised):

Code: Select all

x = 36, y = 36, rule = B3aikqy4acik5aknry6kn78/S2-in3-ay4cinrt5cejn6ck7c
28b2o$26b2obo$25b2ob2o$23b2o3b2o$22b2ob2obo$bo21b2o$obo22b4o3b4o$bo11b
o11b2ob2ob3obo$13b2obo9b2obo4bo$13bo13b3obob2o$28b2obobo$30bobo$21bo8b
3o$20bobo8bo$21bobo$22bo4$27bo2$27bo$26b3o11$29bo$28bobo$29bo!
Was found with apgsearch and is in haul b3aikqy4acik5aknry6kn78s2-in3-ay4cinrt5cejn6ck7c/D2_x/a2b1ee550c99051e3024472032f9f7d3
listed as yl52_2_24_ca3231387630bb506740a3f4883e0d7b

Code: Select all

x = 16, y = 16, rule = B3aikqy4acik5aknry6kn78/S2-in3-ay4cinrt5cejn6ck7c
bbbobobobbobbobb$
boobbbobooobobob$
bbbobboooooobbbo$
obboooobbbbobbob$
boobbooobboboobb$
oboobooboooobooo$
bbboooobbbobboob$
obbobboobbobboob$
bobbboobobbobobo$
booobbboooooooob$
ooboobboboooobbo$
bobobobbbobbobbb$
obbboooboooboobo$
obobbbobbboobbob$
bobboooobbbobbob$
oboobobbobobobbb!
However, it has not been listed as one of the objects after the other objects have been counted. Is this a bug I guess?


Perhaps related, the most common spaceship in this rule, endemic, shows no sample soups despite several thousand soups already been found:
xq99_15

----

EDIT: this gun is mistakenly listed as zz_REPLICATORs (found in D2_x symmetry):

Code: Select all

x = 192, y = 192, rule = B2ekn3aeij4aq6/S1c2ckn34nrw5
15b2o$14b2o3bo$15bob2obo$14bob2o3bo$20bo$16b2ob2o$15b3obo2bo$14b3o3b3o
$14b2o3bobo10b2o$32b2o5$bobo3b2o$3o3b3o$o2bob3o$2b2ob2o$2bo$bo3b2obo$
2bob2obo$3bo3b2o$6b2o2$27bo11bo$25b3o12b3o$25b2o10bob2obo$24b2obo10bo
2bobo$36b2o3b2ob2o$36b3ob2o3bo$38b2ob2o3bo$38bo4bobob2o$8b2o23b2o2b5ob
4obo$8b2o22bobo2bo2b2o2bo2b2o$32b3o3b2obobo3bobo$38b2ob4obo$28b2o10b2o
2b2obo$26bob2o2b2o10b2o$27bob4ob2o$24bobo3bobob2o3b3o$25b2o2bo2b2o2bo
2bobo19bo$25bob4ob5o2b2o21b2o$25b2obobo4bo25bo5b2o$27bo3b2ob2o22bo7b2o
$28bo3b2ob3o20bo4b5o$28b2ob2o3b2o19b2o5bo$30bobo2bo10bob2o7b4ob3ob2o$
31bob2obo10b2o11bobo2bo3bo3b3o$31b3o12b3o6b3ob2obo10bobo$34bo11bo3b3o
2bo3b4o2bobo5b2o$49b5o3bobobobo2bob2o$49b2o3bo3bobobob5o$49b2o5bobobob
3o$50bo5bo2bo3b4o$51bo2bob3o7bobobo$48b2o6b4o3b2o4b3o$48bo3b4o8b4obo$
45b2obobo3b2o7bo3bob2o$43b4o4b2ob2o4bobo4b2o$46bob3o2bobo3b4o3b2o$46b
4ob2o5b6o2bo$40bobo6b2o8b2o$41bo4b4ob2o5b3o$41bo2bobo3bob2obobo2bo$44b
3o4b3ob2o$44bo2bobobobo2bo$43b2obo3b2ob2obo2b2o$42b3obo2bobo4b4o$42bo
7b2o2bo3bo44b2o$47bo2bo4b3o45b2o$54b2obo12b2o$55bo14b2o2$47b3o$47bobo$
47b2o29b3o$78b3o$79bo$75b2o$75b3obo2bo$75b2o5bo$82bo2bo$79b8o2bo$82b3o
$82b2o2bo$81b2o3b2o7bo$82bob2o9b2o$85bo5bobobo26b2o$89bo3bob2o25b2o$
82bo5b2o3b6o2b2o$92b3ob3o2b2o$87bo5b3ob2o$90bo7b2o$87b5o2bo4b4o$89b3ob
o6b3o$85b5obo9b3obo$86bob3o9bob5o$89b3o6bob3o$89b4o4bo2b5o$92b2o7bo$
93b2ob3o5bo$89b2o2b3ob3o$89b2o2b6o3b2o5bo$68b2o25b2obo3bo$68b2o26bobob
o5bo$95b2o9b2obo$96bo7b2o3b2o$105bo2b2o$107b3o$102bo2b8o$106bo2bo$109b
o5b2o$109bo2bob3o$115b2o$112bo$111b3o$111b3o29b2o$142bobo$142b3o2$120b
2o14bo$120b2o12bob2o$87b2o45b3o4bo2bo$87b2o44bo3bo2b2o7bo$132b4o4bobo
2bob3o$131b2o2bob2ob2o3bob2o$135bo2bobobobo2bo$135b2ob3o4b3o$131bo2bob
ob2obo3bobo2bo$131b3o5b2ob4o4bo$131b2o8b2o6bobo$125bo2b6o5b2ob4o$124b
2o3b4o3bobo2b3obo$123b2o4bobo4b2ob2o4b4o$121b2obo3bo7b2o3bobob2o$122bo
b4o8b4o3bo$120b3o4b2o3b4o6b2o$121bobobo7b3obo2bo$125b4o3bo2bo5bo$127b
3obobobo5b2o$123b5obobobo3bo3b2o$122b2obo2bobobobo3b5o$117b2o5bobo2b4o
3bo2b3o3bo11bo$116bobo10bob2ob3o6b3o12b3o$116b3o3bo3bo2bobo11b2o10bob
2obo$124b2ob3ob4o7b2obo10bo2bobo$127bo5b2o19b2o3b2ob2o$124b5o4bo20b3ob
2o3bo$124b2o7bo22b2ob2o3bo$123b2o5bo25bo4bobob2o$128b2o21b2o2b5ob4obo$
130bo19bobo2bo2b2o2bo2b2o$150b3o3b2obobo3bobo$156b2ob4obo$146b2o10b2o
2b2obo$144bob2o2b2o10b2o$145bob4ob2o$142bobo3bobob2o3b3o$143b2o2bo2b2o
2bo2bobo22b2o$143bob4ob5o2b2o23b2o$143b2obobo4bo$145bo3b2ob2o$146bo3b
2ob3o$146b2ob2o3b2o$148bobo2bo10bob2o$149bob2obo10b2o$149b3o12b3o$152b
o11bo2$184b2o$183b2o3bo$184bob2obo$183bob2o3bo$189bo$185b2ob2o$184b3ob
o2bo$183b3o3b3o$183b2o3bobo5$158b2o$158b2o10bobo3b2o$169b3o3b3o$169bo
2bob3o$171b2ob2o$171bo$170bo3b2obo$171bob2obo$172bo3b2o$175b2o!
SoL : FreeElectronics : DeadlyEnemies : 6a-ite : Rule X3VI
what is “sesame oil”?

User avatar
Anivec
Posts: 1926
Joined: January 28th, 2022, 7:18 pm
Location: Somewhere I Belong

Re: Catagolue Discussion Thread

Post by Anivec » April 2nd, 2026, 7:50 pm

Can there be a feature that allows users to view the statistics for an individual census? It would show the amount of occurrences of an objects with a selected property on the Y axis and the selected property values of the objects on the X axis. These properties would include population, bounding box, period, and growth rate. It would also be lovely if soups could be plotted with the amount of occurrences on for soups that stabilize in a given generation on the Y axis, and the generation number it stabilizes being the X axis. (There may be too many soups to plot because of memory issues).

Post Reply