calcyman wrote:It looks as if apgsearch isn't successfully separating two widely separated same-direction xq8_2je4 spaceships...

Correct: if two spaceships are sufficiently separated, they're too large to canonise so won't reach the pseudo_bangbang() routine (which is the only thing capable of separating them). Maybe I should modify canonise() to support larger objects (and just restrict the length of the resulting strings).

There's a similar issue here due to the large period involved (pseudo_bangbang() only deals with oscillators and low-period spaceships):

http://catagolue.appspot.com/census/b368s1258/C1/xq162

There seems to be a bit more than that going on:

In the first instance, those two spaceships are only treated as a single object because one of the 100 soups in which they are processed is detected as having infinite growth (or not stabilising for some other reason). Then during census(), the rear ship runs into the history envelope of the front ship during the APG_CoalesceObjects run. The resulting pattern is too large to be canonised - as mentioned - and no attempt is made to separate them.

However, even if the pattern is canonised, pseudo_bangbang only process still life and oscillators. Moving patterns are processed separately:

Code: Select all

```
# Code extract from enter_unid(...)
# Separate into pure components:
if (moving):
g.setrule("APG_CoalesceObjects_" + self.rg.alphanumeric)
g.setbase(2)
g.setstep(3)
g.step()
else:
pseudo_bangbang(self.rg.alphanumeric)
```

... and only if the period of the pattern is <= 9.

Code: Select all

```
# Code extract from teenager(...)
elif ((unidname[0] == 'x') & ((unidname[1] == 's') | (unidname[1] == 'p'))):
self.enter_unid(unidname, soupid, False)
else:
if ((unidname[0] == 'x') & (unidname[1] == 'q') & (unidname[3] == '_')):
# Separates low-period (<= 9) non-standard spaceships in medium proximity:
self.enter_unid(unidname, soupid, True)
else:
self.incobject(unidname, 1)
self.awardpoints2(soupid, unidname)
```

I think extending canonise to deal with larger objects is a good idea. I'm sure it can be done in a backward compatible way by allowing multiple "yX" sequences to represent regions of empty cells larger than 39x5 - in the same way that sequential "z" sequences are allowed.

However, I don't think this is necessary to solve this issue. If enter_unid() is allowed to attempt to process oversize objects, then patterns such as this one will be correctly resolved - just not cached. Any truly inseperable oversize objects can just be skipped by enter_unid(). I suppose this might also require modification to process_unid() so that patterns aren't added to superunid as well as being handled by enter_unid().

Additionally, the limit on period to less than 10 in attempting to separate spaceships has always seemed arbitrary to me - a result of the APG_CoalesceObjects rule being run for 8 gen. Seeing as the period is known, can it be passed to enter_unid() and used to determine how long to run the rule for? If I'm not mistaken the rule need only be run for p-1 gen to guarantee that any inseperable pattern remains connected

In a few instances, this would result in closely spaced spaceships in other rules being separated where currently they aren't. e.g. the c/7 glider in B36/S245. For some phases of the following closely spaced pairs, the two gliders remain separated for 7 gen, but not for 8. Even more remain separate if the rule is only run for 6 gen.

Code: Select all

```
x = 69, y = 99, rule = APG_CoalesceObjects_B36S245
2.2A7.4A7.2A7.2A8.A2.A8.A9.A$.4A6.A.2A6.3A6.2A.2A7.A.A7.A.A7.2A$.2A8.
2A7.2A.A6.A12.A7.A9.3A$2.A8.2A7.3A8.A9.2A9.A$31.A2$2.A9.A29.2A7.2A7.A
2.A$.A.A7.2A8.2A7.4A7.3A6.2A.2A6.A.A$A9.3A7.4A6.A.2A6.2A.A6.A11.A$.A
18.2A8.2A8.3A8.A8.2A$21.A8.2A19.A20$.2A7.4A8.2A7.2A7.A2.A8.A9.A$4A6.A
.2A7.3A6.2A.2A6.A.A7.A.A7.2A$2A8.2A8.2A.A6.A11.A7.A9.3A$.A8.2A8.3A8.A
8.2A9.A$31.A2$2.A9.A29.2A7.2A7.A2.A$.A.A7.2A9.2A7.4A6.3A6.2A.2A6.A.A$
A9.3A8.4A6.A.2A5.2A.A6.A11.A$.A19.2A8.2A7.3A8.A8.2A$22.A8.2A18.A20$.
2A7.4A8.2A7.2A7.A2.A8.A9.A$4A6.A.2A7.3A6.2A.2A6.A.A7.A.A7.2A$2A8.2A8.
2A.A6.A11.A7.A9.3A$.A8.2A8.3A8.A8.2A9.A$31.A$5.A9.A29.2A6.2A7.A2.A$4.
A.A7.2A9.2A7.4A6.3A5.2A.2A6.A.A$3.A9.3A8.4A6.A.2A5.2A.A5.A11.A$4.A19.
2A8.2A7.3A7.A8.2A$25.A8.2A17.A21$.2A7.4A8.2A7.2A7.A2.A9.A9.A$4A6.A.2A
7.3A6.2A.2A6.A.A8.A.A7.2A$2A8.2A8.2A.A6.A11.A8.A9.3A$.A8.2A8.3A8.A8.
2A10.A$6.A9.A14.A14.2A8.2A7.A2.A$5.A.A7.2A9.2A7.4A6.3A7.2A.2A6.A.A$4.
A9.3A8.4A6.A.2A5.2A.A7.A11.A$5.A19.2A8.2A7.3A9.A8.2A$26.A8.2A19.A!
```

For those following along, none of this affects Life as gliders are removed by the custom IdentifyGliders and RemoveGliders rules. Non-interacting *WSSes are separated by custom code in countxwsses()