Tiling with placement rules for still life and p2 oscillators

For general discussion about Conway's Game of Life.
Post Reply
User avatar
pcallahan
Posts: 854
Joined: April 26th, 2013, 1:04 pm

Tiling with placement rules for still life and p2 oscillators

Post by pcallahan » January 25th, 2020, 11:11 pm

I'm starting a new thread to consolidate my posts on other threads and provide nicer pictures than before, which I made using python and imagemagick. (Scripts are added at the end.)

This follows up on the complicated still life tiling based on octagons by observing that you can reduce the number of tiles by quite a lot if you add placement rules. Note that adjacency can be enforced by jigsaw boundaries, and actually the internal rules can be enforced by further decomposing the patterns into octagonal tiles, but the idea here is that if people are going to place physical tiles (which is my goal), it's OK if they apply some visual constraints. (Yes, taking this to an extreme, you could just lay down black and white tiles for cells while inspecting the neighbors, but I believe the additional annotation bridges the gap between Life master and novice.)

First, here are the 6 still life tiles and an example of what an eater looks like composed of them.
still.png
still.png (33.39 KiB) Viewed 7960 times
There are 6 tiles in which the red marks ("petals") indicate live cells going two cells clockwise from each quadrant. When 4 tiles are placed incident to corners, matching colors to form a colored square, the number of petals is the number of live neighbors. So to build a still life with these tiles (using as many of each as needed and freely rotating them) we only require:
  • There are either 2 or 3 petals incident to the center of a black square.
  • There are never 3 petals incident to the center of a white square.
(An alternative coloring uses white petals on black squares and black petals on white squares; I'm not sure which is better.)

The ability to handle still lifes with 6 tiles emboldened me to move up to p2 oscillators. In this case, there are 70 possible tiles (though a few may not fit in any p2). There are 4 colors indicating always live, always dead, live on even steps, live on odd steps. Here is the complete set of tiles, and tilings for blinker, toad, and clock respectively.
period2.png
period2.png (230.79 KiB) Viewed 7960 times
When 4 tiles are placed incident to corners, matching colors to form a colored square, the number of petals of each color indicates the number of live neighbors in even or odd generations. So to build a still life with these tiles (using as many of each as needed and freely rotating them) we require:
  • There are 2 or 3 petals of each color incident to the center of a black (dark gray) square.
  • There are never exactly 3 petals of the same color incident to the center of a white square.
  • There are always 3 white petals incident to the center of any pink or blue square.
  • There are never 2 or 3 black petals incident to the center of any pink or blue square.
These are admittedly less practical for assembling oscillators by hand. However, it might make an interesting jigsaw puzzle to split up a larger oscillator into a tile set that uniquely assembles to it when following the rules (and it is relatively easy to add jigsaw boundaries to enforce the colors).

Finally, here is a repeating pattern that illustrates the still life tiles at all orientations. It is not a still life (as can be observed; it's a p2 houndtooth pattern in fact). By printing this and cutting at the gray lines (not cyan!) you can make a set of physical tiles.
tiling.png
tiling.png (82.16 KiB) Viewed 7957 times
Python code for generating the imagemagick command for the still life PNG.

Code: Select all

COLOR = ["white", "black"]

def petal(x, y, length, i, xf, thickness, angle):
  return ("-draw 'translate %d, %d rotate %d translate %d, %d rotate %s "
          "path \"M 0, 0 L %d, %d L %d %d L %d, %d Z\"'" %
          (length + x, length + y, i * 90, -length, -length, angle,
          xf, -thickness, xf + thickness, 0, xf, thickness))

def tile(x, y, length, quadrants):
  size = length * 2 + 1
  xf = length * 0.6
  thickness = length * 0.13
  lines = ["-fill '#70f5f6' -draw 'translate %d, %d rectangle 0, 0, %d, %d'" % (x, y, size - 1, size - 1),
           "-fill black"]
  for i in range(len(quadrants)):
      lines.append("-fill %s" % COLOR[quadrants[i]]) 
      lines.append("-draw 'translate %d, %d rotate %d translate %d, %d rectangle 0, 0, %d %d'" %
          (length + x, length + y, i * 90, -length, -length, length - 1, length - 1))
  for i in range(len(quadrants)):
      if quadrants[(i + 1) % 4]:
         lines.append("-fill red") 
         lines.append(petal(x, y, length, i, xf, thickness, 22.5))
      if quadrants[(i + 2) % 4]:
         lines.append("-fill red") 
         lines.append(petal(x, y, length, i, xf, thickness, 67.5))
  return lines

def pattern(x, y, length, grid, border):
  size = length * 2 + 1 + border
  lines = []
  for i in range(len(grid) - 1): 
    for j in range(len(grid[i]) - 1): 
      lines.extend(tile(x + j * size, y + i * size, length,
                   (grid[i][j], grid[i][j + 1], grid[i + 1][j + 1], grid[i + 1][j])))
  return lines
 
size = 800

lines = []
lines.append("magick -size %dx%d canvas:none -fill lightgray" % (size, size))
lines.append("-draw 'rectangle 0, 0, %s, %s'" % (size, size))
tilecolors = [(a, b, c, d)
              for a in range(2) for b in range(2) for c in range(2) for d in range(2)]

x = 60
for quadrant in tilecolors:
  if quadrant == min(quadrant[-i:] + quadrant[:-i] for i in range(len(quadrant))):
    lines.extend(tile(x, 80, 40, quadrant))
    x += 120

eater = [
  [0, 0, 0, 0, 0, 0],
  [0, 0, 0, 1, 1, 0],
  [0, 0, 0, 0, 1, 0],
  [0, 1, 1, 1, 0, 0],
  [0, 1, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0]]

lines.extend(pattern(150, 300, 40, eater, 0))

lines.append("still.png")

print " \\\n".join(lines)
Python code for generating the imagemagick command for the period-2 PNG.

Code: Select all

COLOR = ["white", "#ff7070", "#7070ff", "#606860"]

oddcolor = "#b00000"
evencolor = "#0000b0"
oldcolor = "#000000"
newcolor = "#ffffff"

color1 = [evencolor, oldcolor, newcolor, evencolor]
color2 = [oddcolor, newcolor, oldcolor, oddcolor]

def petal(x, y, length, i, xf, thickness, angle):
  return ("-draw 'translate %d, %d rotate %d translate %d, %d rotate %s "
          "path \"M 0, 0 L %d, %d L %d %d L %d, %d Z\"'" %
          (length + x, length + y, i * 90, -length, -length, angle,
          xf, -thickness, xf + thickness, 0, xf, thickness))

def tile(x, y, length, quadrants):
  size = length * 2 + 1
  xf = length * 0.6
  thickness = length * 0.1
  lines = ["-fill '#70f5f6' -draw 'translate %d, %d rectangle 0, 0, %d, %d'" % (x, y, size - 1, size - 1),
           "-fill black"]
  for i in range(len(quadrants)):
      lines.append("-fill '%s'" % COLOR[quadrants[i]]) 
      lines.append("-draw 'translate %d, %d rotate %d translate %d, %d rectangle 0, 0, %d %d'" %
          (length + x, length + y, i * 90, -length, -length, length - 1, length - 1))
  for i in range(len(quadrants)):
      state = quadrants[i]
      state1 = quadrants[(i + 1) % 4]
      if state1 & 1:
         lines.append("-fill '%s'" % color1[state]) 
         lines.append(petal(x, y, length, i, xf, thickness, 11.25))
      if state1 & 2:
         lines.append("-fill '%s'" % color2[state]) 
         lines.append(petal(x, y, length, i, xf, thickness, 33.75))
      state2 = quadrants[(i + 2) % 4]
      if state2 & 1:
         lines.append("-fill '%s'" % color1[state]) 
         lines.append(petal(x, y, length, i, xf, thickness, 56.25))
      if state2 & 2:
         lines.append("-fill '%s'" % color2[state]) 
         lines.append(petal(x, y, length, i, xf, thickness, 78.75))
      
  return lines

def pattern(x, y, length, grid, border):
  size = length * 2 + 1 + border
  lines = []
  for i in range(len(grid) - 1): 
    for j in range(len(grid[i]) - 1): 
      lines.extend(tile(x + j * size, y + i * size, length,
                   (grid[i][j], grid[i][j + 1], grid[i + 1][j + 1], grid[i + 1][j])))
  return lines
 
size = 1100

lines = []
lines.append("magick -size %dx%d canvas:none -fill '#559883'" % (size, size))
lines.append("-draw 'rectangle 0, 0, %s, %s'" % (size, size))
tilecolors = [(a, b, c, d)
              for a in range(4) for b in range(4) for c in range(4) for d in range(4)]

x = 0
y = 0
for quadrant in tilecolors:
  if quadrant == min(quadrant[-i:] + quadrant[:-i] for i in range(len(quadrant))):
    lines.extend(tile(x + 60, y + 60, 40, quadrant))
    x += 100
    if x > 900:
      x = 0
      y += 100

blinker = [
  [0, 0, 0, 0, 0],
  [0, 0, 1, 0, 0],
  [0, 2, 3, 2, 0],
  [0, 0, 1, 0, 0],
  [0, 0, 0, 0, 0]]
lines.extend(pattern(150, 800, 25, blinker, 0))

toad = [
  [0, 0, 0, 0, 0, 0],
  [0, 0, 2, 0, 0, 0],
  [0, 3, 1, 1, 2, 0],
  [0, 2, 1, 1, 3, 0],
  [0, 0, 0, 2, 0, 0],
  [0, 0, 0, 0, 0, 0]]
lines.extend(pattern(400, 800, 25, toad, 0))

clock = [
  [0, 0, 0, 0, 0, 0],
  [0, 0, 2, 1, 0, 0],
  [0, 1, 3, 0, 2, 0],
  [0, 2, 0, 3, 1, 0],
  [0, 0, 1, 2, 0, 0],
  [0, 0, 0, 0, 0, 0]]
lines.extend(pattern(700, 800, 25, clock, 0))

lines.append("period2.png")

print " \\\n".join(lines)
Python code for generating the imagemagick command for the houndstooth PNG.

Code: Select all

COLOR = ["white", "black"]

def petal(x, y, length, i, xf, thickness, angle):
  return ("-draw 'translate %d, %d rotate %d translate %d, %d rotate %s "
          "path \"M 0, 0 L %d, %d L %d %d L %d, %d Z\"'" %
          (length + x, length + y, i * 90, -length, -length, angle,
          xf, -thickness, xf + thickness, 0, xf, thickness))

def tile(x, y, length, quadrants):
  size = length * 2 + 1
  xf = length * 0.6
  thickness = length * 0.13
  lines = ["-fill '#70f5f6' -draw 'translate %d, %d rectangle 0, 0, %d, %d'" % (x, y, size - 1, size - 1),
           "-fill black"]
  for i in range(len(quadrants)):
      lines.append("-fill %s" % COLOR[quadrants[i]]) 
      lines.append("-draw 'translate %d, %d rotate %d translate %d, %d rectangle 0, 0, %d %d'" %
          (length + x, length + y, i * 90, -length, -length, length - 1, length - 1))
  for i in range(len(quadrants)):
      if quadrants[(i + 1) % 4]:
         lines.append("-fill red") 
         lines.append(petal(x, y, length, i, xf, thickness, 22.5))
      if quadrants[(i + 2) % 4]:
         lines.append("-fill red") 
         lines.append(petal(x, y, length, i, xf, thickness, 67.5))
  return lines

def pattern(x, y, length, grid, border):
  size = length * 2 + 1 + border
  lines = []
  for i in range(len(grid) - 1): 
    for j in range(len(grid[i]) - 1): 
      lines.extend(tile(x + j * size, y + i * size, length,
                   (grid[i][j], grid[i][j + 1], grid[i + 1][j + 1], grid[i + 1][j])))
  return lines
 
size = 984

lines = []
lines.append("magick -size %dx%d canvas:none -fill lightgray" % (size, size))
lines.append("-draw 'rectangle 0, 0, %s, %s'" % (size, size))
tilecolors = [(a, b, c, d)
              for a in range(2) for b in range(2) for c in range(2) for d in range(2)]

houndstooth = [
  [0, 0, 1, 0] * 3 + [0],
  [1, 1, 1, 0] * 3 + [1],
  [0, 1, 1, 1] * 3 + [0],
  [0, 1, 0, 0] * 3 + [0]]
houndstooth = houndstooth * 3 + [houndstooth[0]]

lines.extend(pattern(0, 0, 40, houndstooth, 1))

lines.append("tiling.png")

print " \\\n".join(lines)

User avatar
pcallahan
Posts: 854
Joined: April 26th, 2013, 1:04 pm

Re: Tiling with placement rules for still life and p2 oscillators

Post by pcallahan » January 27th, 2020, 12:48 am

Bridging the gap between visual placement rules and a pure tiling, we can replace the petals with toothed octagons, like the original tiling. In this case, any black octagon in a still life must have 2 or 3 teeth, and any white octagon must not have exactly 3 dents. Like the previous example, we can use 6 square tiles and check constraints visually.
octagons.png
octagons.png (75.41 KiB) Viewed 7914 times
But in addition, the octagons can be treated as tiles, so the placement could be forced without requiring a visual inspection. There are 37 possible octagons up to rotations, fewer with flips, and some ways of decomposing them discussed in another thread.

And here is the python script to use with imagemagick.

Code: Select all

import math

COLOR = ["white", "black"]

def petal(x, y, length, i, xf, thickness, angle, hasTooth, state):
  bump = thickness if state else -thickness * 0.5
  tooth = "L %d %d L %d %d L %d %d L %d %d" % (
    xf, -thickness * 0.3, xf + bump, -thickness * 0.5, xf + bump, thickness * 0.5, xf, thickness * 0.3) if hasTooth else "" 
  return ("-draw 'translate %d, %d rotate %d translate %d, %d rotate %s "
          "path \"M 0, 0 L %d, %d %s L %d, %d Z\"'" %
          (length + x, length + y, i * 90, -length, -length, angle,
          xf, -thickness, tooth, xf, thickness))

def tile(x, y, length, quadrants):
  size = length * 2 + 1
  xf = [length * 0.7, length * 0.6]
  thickness = [t * math.tan(math.radians(22.5)) * 1.04 for t in xf]
  lines = ["-fill 'lightgray' -draw 'translate %d, %d rectangle 0, 0, %d, %d'" % (x, y, size - 1, size - 1),
           "-fill black"]
  for i in range(len(quadrants)):
      lines.append("-fill lightgray") 
      lines.append("-draw 'translate %d, %d rotate %d translate %d, %d rectangle 0, 0, %d %d'" %
          (length + x, length + y, i * 90, -length, -length, length - 1, length - 1))
  for i in range(len(quadrants)):
      state = quadrants[i]
      lines.append("-fill %s" % COLOR[state]) 
      lines.append(petal(x, y, length, i, xf[state], thickness[state], 22.5, quadrants[(i + 1) % 4], state))
      lines.append("-fill %s" % COLOR[state]) 
      lines.append(petal(x, y, length, i, xf[state], thickness[state], 67.5, quadrants[(i + 2) % 4], state))
  return lines

def pattern(x, y, length, grid, border):
  size = length * 2 + 1 + border
  lines = []
  for i in range(len(grid) - 1): 
    for j in range(len(grid[i]) - 1): 
      lines.extend(tile(x + j * size, y + i * size, length,
                   (grid[i][j], grid[i][j + 1], grid[i + 1][j + 1], grid[i + 1][j])))
  return lines
 
size = 800

lines = []
lines.append("magick -size %dx%d canvas:none -fill skyblue" % (size, size))
lines.append("-draw 'rectangle 0, 0, %s, %s'" % (size, size))
tilecolors = [(a, b, c, d)
              for a in range(2) for b in range(2) for c in range(2) for d in range(2)]

x = 60
for quadrant in tilecolors:
  if quadrant == min(quadrant[-i:] + quadrant[:-i] for i in range(len(quadrant))):
    lines.extend(tile(x, 80, 40, quadrant))
    x += 120

eater = [
  [0, 0, 0, 0, 0, 0],
  [0, 0, 0, 1, 1, 0],
  [0, 0, 0, 0, 1, 0],
  [0, 1, 1, 1, 0, 0],
  [0, 1, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0]]

lines.extend(pattern(10, 250, 35, eater, 1))

block_on_table = [
  [0, 0, 0, 0, 0, 0],
  [0, 0, 0, 1, 1, 0],
  [0, 0, 0, 1, 1, 0],
  [0, 0, 0, 0, 0, 0],
  [0, 1, 1, 1, 1, 0],
  [0, 1, 0, 0, 1, 0],
  [0, 0, 0, 0, 0, 0]]

lines.extend(pattern(400, 250, 35, block_on_table, 1))

lines.append("octagons.png")

print " \\\n".join(lines)

User avatar
pcallahan
Posts: 854
Joined: April 26th, 2013, 1:04 pm

Re: Tiling with placement rules for still life and p2 oscillators

Post by pcallahan » February 4th, 2020, 1:30 pm

This is really just a slight tweak on the first split-dot approach (update 4 in this post: https://conwaylife.com/forums/viewtopic ... 100#p87584), though somehow I was most of the way done before realizing it. I think it makes for a better visualization. The main idea is to use circles instead of squares, and have quarter and half circles at the join points. I also use just two colors, omit any line boundaries, and invert the cell colors within live cells, because I think it is easier to see them and the rules can be explained in terms of "white dots" and "black dots" without additional context.
tiles.png
tiles.png (6.46 KiB) Viewed 7843 times
The reason I think circles are better is that without being told anything about the tiles, most people will understand that they are supposed to make complete circles, whereas it might seem reasonable to make checkerboards out of the squares. I also think they are more attractive designs, though this is clearly subjective.

As noted (https://conwaylife.com/forums/viewtopic ... 100#p88535), they are not "self-checking" but you can imagine using bumps and dents and adding plastic gadgets over the top to force a still life. I prefer to state a rule, e.g. in the case of B23/S3 still lifes, "white dots must be in clusters of 2 or 3, black dots must not be in clusters of 3." But just by changing the rules, you can handle any 1-step constraint on any 2-state Moore neighborhood CA--not limited to totalistic assuming you are willing to memorize neighborhood shapes.

Here's a constellation of two phases of glider, a blinker, and a block.
patterns.png
patterns.png (54.09 KiB) Viewed 7843 times
I think it is very easy to pick out the deaths and fairly easy to pick out the births. It would need to be tested along with other designs on someone who hasn't been playing around with Life for many years.

Finally, here's a big complicated still life that came out of lifesrc.
rand9x9.png
rand9x9.png (100.5 KiB) Viewed 7843 times
I think it is quite easy for anyone to convince themselves it's a still life (aside from those who already think it's trivial). This moves the fan-out work away from your brain or visual cortex and outsources it to the tiles but leaves constraint checking in your head.

So where am I going with this? Well, I think the whole idea of doing computation with tiling constraints is intrinsically interesting (even if they're not pure geometric constraints) but I have more specific (though it's a stretch to say practical) motives:
  • Can we make this a basis of puzzles and games?
    • E.g. a simple puzzle would be to build a still life out of a particular multi-set of tiles, such as the 9 tiles in a block. 4 corner pieces, 4 edge pieces, 1 interior piece.
    • Would a 2-player Scrabble-like game be playable where the goals is to build still lifes instead of words.
  • A tool for analyzing/developing intuition about Life or other 2-state CAs offline. Sometimes it helps to get away from a screen.
  • A decorative scheme along the lines of Truchet tiles. This is a stretch. E.g. the big still life may not seem pretty, but more symmetric patterns might be, and forcing them to be still lifes gives it a recognizable motif.
Here's a script to generate imagemagick commands for the tiles at all orientations.

Code: Select all

COLOR = ["white", "black"]

def tile(quadrants, x, y, side, scale):
  lines = []
  length = side * scale
  radius = side * (scale - 0.5)
  inner = length - radius
  dots = length - 1.7 * side
 
  lines.append("-stroke none") 
  for i in range(4):
    theta = 90 * i - 180

    (a, b, c, d) = quadrants[i:] + quadrants[:i]
    if a:
      lines.append("-fill %s -draw 'translate %5.3f %5.3f rotate %5.3f path \"M %5.3f %5.3f L %5.3f %5.3f A %5.3f %5.3f 0 0 0 %5.3f %5.3f\"'" %
                 (COLOR[a], x, y, theta, length, length, length, inner, radius, radius, inner, length))
    small = side * 0.65
    lines.append("-fill %s -draw 'translate %5.3f %5.3f rotate %5.3f path \"M %5.3f %5.3f A %5.3f %5.3f 0 0 0 %5.3f %5.3f\"'" %
                (COLOR[a ^ b], x, y, theta, dots + small, length, small, small, dots - small, length))
    lines.append("-fill %s -draw 'translate %5.3f %5.3f rotate %5.3f circle %5.3f %5.3f %5.3f %5.3f'" %
                (COLOR[a ^ c], x, y, theta, dots, dots, dots, dots + small))
    lines.append("-fill %s -draw 'translate %5.3f %5.3f rotate %5.3f path \"M %5.3f %5.3f A %5.3f %5.3f 0 0 0 %5.3f %5.3f\"'" %
                (COLOR[a ^ d], x, y, theta, length, dots - small, small, small, length, dots + small))
  return lines

for a in range(2):
  for b in range(2):
    for c in range(2):
      for d in range(2):
        quadrants = (a, b, c, d)
        side = 10
        scale = 5 
        dim = side * scale * 2 + 1
        lines = ["magick -size %dx%d canvas:%s" % (dim, dim, COLOR[0])]
        lines.extend(tile(quadrants, side * scale, side * scale, side, scale))
        lines.append("block_%d%d%d%d.png" % quadrants)
        print(" \\\n").join(lines)
And another that uses imagemagick montage to piece the tiles together into patterns.

Code: Select all

import math

def pattern(grid, name):
  tiles = []
  for i in range(len(grid) - 1): 
    for j in range(len(grid[i]) - 1): 
      quadrants = (grid[i][j], grid[i][j + 1], grid[i + 1][j + 1], grid[i + 1][j])
      tiles.append("block_%d%d%d%d.png" % quadrants)
  print("montage -tile %dx%d -geometry 100x100 %s %s.png" % (len(grid[0]) - 1, len(grid) - 1, " ".join(tiles), name))

eater = [
  [0, 0, 0, 0, 0, 0],
  [0, 0, 0, 1, 1, 0],
  [0, 0, 0, 0, 1, 0],
  [0, 1, 1, 1, 0, 0],
  [0, 1, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0]]
pattern(eater, "eater")

block_on_table = [
  [0, 0, 0, 0, 0, 0],
  [0, 0, 0, 1, 1, 0],
  [0, 0, 0, 1, 1, 0],
  [0, 0, 0, 0, 0, 0],
  [0, 1, 1, 1, 1, 0],
  [0, 1, 0, 0, 1, 0],
  [0, 0, 0, 0, 0, 0]]
pattern(block_on_table, "b_on_t")

rand9x9 = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0],
[0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0],
[0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0],
[0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0],
[0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0],
[0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0],
[0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0],
[0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0],
[0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
pattern(rand9x9, "rand9x9")

houndstooth = [
  [0, 0, 1, 0] * 3 + [0],
  [1, 1, 1, 0] * 3 + [1],
  [0, 1, 1, 1] * 3 + [0],
  [0, 1, 0, 0] * 3 + [0]]
houndstooth = houndstooth * 3 + [houndstooth[0]]
pattern(houndstooth, "houndstooth")

counter_example = [
  [1, 1, 0, 0, 1, 1, 0, 0, 0] * 2,
  [0, 0, 0, 1, 1, 0, 0, 1, 1] * 2,
  [0, 1, 1, 0, 0, 0, 1, 1, 0] * 2]
counter_example = counter_example * 4
pattern(counter_example, "ce")

gliders = [
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0],
  [0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0],
  [0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0], 
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
pattern(gliders, "gliders")

blinker = [
  [0, 0, 0, 0, 0],
  [0, 1, 1, 1, 0],
  [0, 0, 0, 0, 0]]
pattern(blinker, "blinker")

patterns = [
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0],
  [0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0],
  [0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0], 
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
pattern(patterns, "patterns")

print("montage -tile 6x1 -geometry 101x101+20+20 -background none block_0000.png block_0001.png block_0011.png block_0101.png block_0111.png block_1111.png tiles.png")

Update: Another thing I like about this visualization is that the black dots on white remind me of punch tape. I wasn't sure if that's right. The only punch things I ever worked with (briefly) were cards, which had rectangular holes, but here's a picture and as I believed, it uses round holes. http://pollockspark.com/wp-content/uplo ... H-TAPE.jpg

User avatar
pcallahan
Posts: 854
Joined: April 26th, 2013, 1:04 pm

Re: Tiling with placement rules for still life and p2 oscillators

Post by pcallahan » February 20th, 2020, 1:52 am

Here's a variation I haven't fully fleshed out. Suppose instead of half dots split across tiles, each tile or else its neighbor owns the dot. This is similar to counting the next two cells clockwise, but it can vary from tile to tile. We can indicate that a tile owns the dot by attaching the other half, creating a bulge. If its neighbor owns the dot, we leave a half circle gap instead of a dot.
Screen Shot 2020-02-19 at 9.42.00 PM.png
Screen Shot 2020-02-19 at 9.42.00 PM.png (31.45 KiB) Viewed 7716 times
Obviously, we need a lot more than 6 tiles to support all possibilities. If we stick to a single orientation like gap/bulge going clockwise around a corner then we can get by with 6 and we're back to the original counting. If we allow some variations and assign counts to corners, then we should be able to reduce the number of puzzle pieces needed to test the still-life condition.Can the total be reduced below the 27 tiles used in https://conwaylife.com/forums/viewtopic ... 100#p88361?

Update: One way to get more possibilities is simply to start with a set of 6 in which the dot is owned going clockwise and then allow the tiles to be flipped for the full set of counterclockwise tiles. I'm not sure how much flexibility there is in terms of mixing clockwise and counterclockwise tiles. Since many sides are flat, the placement of one tile does not define the orientation of all those that surround it.

Another thing, more related to the previous posting than this. I think these pictures are a little more interesting if the tiles are separated as below so they can be seen individually at the appropriate orientations.
rand9x9.png
rand9x9.png (376.48 KiB) Viewed 7684 times
This makes it clear there are just 6 distinct tiles and also shows how the dots are shared between tiles. (Note: this is not a still life, though it took me a while to notice. I think the petals are more obvious for spotting births, as much as I like the symmetry of the half dots.)

Update: after making tiles with card stock (too light but a prototype) I decided it is better to use larger dots or else the slightest slippage makes it hard to resolve paired halves. Anyone have a strong preference? I think the big dots are uglier but necessary if you are doing it with real tiles about an inch on a side. The small ones may be better for a decorative scheme with larger tiles.
rand9x9.png
rand9x9.png (448.25 KiB) Viewed 7638 times

User avatar
pcallahan
Posts: 854
Joined: April 26th, 2013, 1:04 pm

Re: Tiling with placement rules for still life and p2 oscillators

Post by pcallahan » February 29th, 2020, 12:05 pm

These tiles work pretty well after making them with printable magnet sheets using an inkjet printer. It's a cheap and effective solution that doesn't require 3D printing or a custom manufacturing order. The price was $7.34 for 5 sheets from Amazon. Cutting out the squares took around fifteen minutes for me, I think, using scissors. You could probably streamline some of that and get straighter edges with a paper cutter.

Here they are on a small whiteboard we have at home, mostly arranged into common still life patterns with some left over
20200229_073729.jpg
20200229_073729.jpg (267.88 KiB) Viewed 7555 times
I was able to print them at a reasonable size in a 9x12 grid containing 108 tiles in these proportions (cell values going clockwise around corners):

Code: Select all

(0, 0, 0, 1) 48
(0, 0, 1, 1) 36
(0, 1, 0, 1) 12
(0, 1, 1, 1) 10
(1, 1, 1, 1) 2
One concern I had was how much margin to leave. I know from experience that my printer does not print all the way up to the edge. I may have left more margin than necessary (I was thinking about using the extra strips as framing, but it's not much anyway.) The PDF file with margins is shared on Google drive.

User avatar
pcallahan
Posts: 854
Joined: April 26th, 2013, 1:04 pm

Re: Tiling with placement rules for still life and p2 oscillators

Post by pcallahan » April 25th, 2020, 11:51 pm

I was getting a little bored with the minimalist look of the tiles above and decided to try to do something with colors and a "petals and leaves" theme. Personally, I find it easier to spot triples (particularly unwanted ones) when they look like leaf clusters or flowers. I have made a number of mistakes using the "dot" tiles from the previous post in which there was a birth I missed in an intended still life.

Instead of trying to generate the base shapes, I drew them in Inkscape, but I used a Python script and imagemagick montage to tile them.

So without further introduction, here's a variation where we count the two adjacent cells in clockwise order. An advantage to this is that there are relatively few possible shapes realizing allowable neighbor counts. Instead of square tiles, we could create a jigsaw puzzle of 27 distinct shapes: flowers, leaf clusters, in-between space chosen so that only still lifes can be constructed.
Screen Shot 2020-04-24 at 9.32.38 PM.png
Screen Shot 2020-04-24 at 9.32.38 PM.png (537.53 KiB) Viewed 6358 times
Another advantage I have found is that when placing the square tiles you can be a little less careful.

The second variation splits the petals and leaves across tiles. The advantage is that it preserves the shape of Moore neighborhoods. The petals also act as a kind of skeleton for the still life.
Screen Shot 2020-04-25 at 8.18.10 PM.png
Screen Shot 2020-04-25 at 8.18.10 PM.png (532.12 KiB) Viewed 6358 times
I am not really sure which I like better. I don't want to waste a sheet of magnet paper unless I'm pretty sure I will be happy with the results.

User avatar
pcallahan
Posts: 854
Joined: April 26th, 2013, 1:04 pm

Re: Tiling with placement rules for still life and p2 oscillators

Post by pcallahan » April 26th, 2020, 4:14 pm

One more thought. Here's a tiling that presents a very direct view of the skeleton of connected dots. It's no-nonsense compared to the petals and leaves. However, I think it is still a lot harder to pick out births visually. Maybe I should not fully connect the blue lines.
Screen Shot 2020-04-26 at 1.18.03 PM.png
Screen Shot 2020-04-26 at 1.18.03 PM.png (559.67 KiB) Viewed 6330 times

hkoenig
Posts: 259
Joined: June 20th, 2009, 11:40 am

Re: Tiling with placement rules for still life and p2 oscillators

Post by hkoenig » April 26th, 2020, 4:41 pm

This latest image is too busy.

The second image of the earlier posting is better. The split petals give the impression of "magnetic lines of force", which the first petals image doesn't have, even though I understand what the petals are showing.

User avatar
pcallahan
Posts: 854
Joined: April 26th, 2013, 1:04 pm

Re: Tiling with placement rules for still life and p2 oscillators

Post by pcallahan » April 26th, 2020, 5:37 pm

hkoenig wrote:
April 26th, 2020, 4:41 pm
This latest image is too busy.

The second image of the earlier posting is better. The split petals give the impression of "magnetic lines of force", which the first petals image doesn't have, even though I understand what the petals are showing.
I agree with both points. I also like the petals, though I wonder if it is better to highlight the connectivity in a more conventional way. Just now, I was trying to cut down on some of the clutter, and here is a variation with shortened lines from dead to live.
Screen Shot 2020-04-26 at 2.29.09 PM.png
Screen Shot 2020-04-26 at 2.29.09 PM.png (516.21 KiB) Viewed 6321 times
One thing I find interesting about the skeletons that I'm surprised I never noticed before, is that the block is the only still life with a non-planar graph of connections between live cells. I cannot be the first to have noticed this.

Update: Making the blue lines even shorter and removing the gap between tiles gives a clearer visualization. Of course if you are using physical tiles, the gaps are inevitable so this is an idealized image.
rand9x9.png
rand9x9.png (2.03 MiB) Viewed 6307 times

User avatar
Kiran
Posts: 285
Joined: March 4th, 2015, 6:48 pm

Re: Tiling with placement rules for still life and p2 oscillators

Post by Kiran » April 26th, 2020, 10:04 pm

If there are no intersections between edges in a graph, it is clearly planar.
The only place this graph can have an intersection is at the vertex between four cells, and that can only happen if all four cells around that vertex are occupied.
Thus, any still-life with a non-planar graph must contain four live cells that form a block.
Each cell in a block already has the maximum number of neighbours for survival to be possible, so there cannot be any adjacent cells to the block.
Thus, the only still lives with non-planar graphs are ones that have a block and an empty row of cells around it.
Besides the block itself (the only polyplet still life with a non-planar graph), there are strict still lives like block-on-table and pseudo still lives like bi-block that have that property.
Kiran Linsuain

User avatar
pcallahan
Posts: 854
Joined: April 26th, 2013, 1:04 pm

Re: Tiling with placement rules for still life and p2 oscillators

Post by pcallahan » April 26th, 2020, 10:54 pm

Kiran wrote:
April 26th, 2020, 10:04 pm
The only place this graph can have an intersection is at the vertex between four cells, and that can only happen if all four cells around that vertex are occupied.
Yeah, I realize that. I had never given it much thought before.

User avatar
pcallahan
Posts: 854
Joined: April 26th, 2013, 1:04 pm

Re: Tiling with placement rules for still life and p2 oscillators

Post by pcallahan » April 29th, 2020, 11:21 am

Here's what the redesigned tiles (split petals) look like after printing on magnetic sheets and cutting. The split petals and leaves span a longer boundary than the the dots, and are, I think a little more forgiving in terms on placement.
20200429_073003.jpg
20200429_073003.jpg (369.02 KiB) Viewed 6246 times
I pu PDFs of both types of tiles in this public directory: https://drive.google.com/drive/folders/ ... sp=sharing I would advise testing that the printer is not cutting of boundaries before using a magnetic sheet. I got a little too ambitious the first time and lost all 38 tiles (9*12-7*10) around the boundary.

User avatar
Layz Boi
Posts: 265
Joined: October 25th, 2018, 3:57 pm

Re: Tiling with placement rules for still life and p2 oscillators

Post by Layz Boi » May 2nd, 2020, 8:13 pm

A while back, used to do something similar to this where I'd copy-paste-rotate-overlap tiles similar to these, and color-match parts in order to construct SLs.
Its super time-consuming and I don't know its applicability.
Image

User avatar
pcallahan
Posts: 854
Joined: April 26th, 2013, 1:04 pm

Re: Tiling with placement rules for still life and p2 oscillators

Post by pcallahan » May 4th, 2020, 6:07 pm

Layz Boi wrote:
May 2nd, 2020, 8:13 pm
A while back, used to do something similar to this where I'd copy-paste-rotate-overlap tiles similar to these, and color-match parts in order to construct SLs.
Its super time-consuming and I don't know its applicability.
Image
That's an interesting approach. I think the main "applicability" is to develop better mental intuition about SLs. But I also think it's fun. I find I enjoy working with the new set of tiles more than the other one that used split circles. I am also beginning to think it is useful to visualize the "backbone" diagrams (live cells that neighbor each other) since they are composed entirely of chains and 3-cell triangles (ignoring blocks). I believe it's easier to verify a "no death" pattern by eye than a "no death/no birth" pattern (i.e. an SL), but maybe it's not that hard.

--Paul

User avatar
Layz Boi
Posts: 265
Joined: October 25th, 2018, 3:57 pm

Re: Tiling with placement rules for still life and p2 oscillators

Post by Layz Boi » May 5th, 2020, 4:22 pm

That's understandable! :D I myself, enjoy manually finding things to kill time. And I find building P2s to be kind of relaxing. It's like doing a Sudoku puzzle.

User avatar
pcallahan
Posts: 854
Joined: April 26th, 2013, 1:04 pm

Re: Tiling with placement rules for still life and p2 oscillators

Post by pcallahan » May 11th, 2020, 2:00 pm

I have added a new printable tile sheet to https://drive.google.com/drive/folders/ ... sp=sharing (As always, I would advise testing that the printer is not cutting of boundaries before using a magnetic sheet.) I haven't printed them yet, but I will soon unless I think of an improvement first.

I think this variation moves the motif back to discrete mathematics (losing the goofy petals and leaves theme) but still makes the birth cells stand out very clearly. The red edges may introduce too much visual noise, but I like getting an explicit picture of the live-live connectivity graph.

Tiles:
Screen Shot 2020-05-11 at 10.08.50 AM.png
Screen Shot 2020-05-11 at 10.08.50 AM.png (51.24 KiB) Viewed 5684 times
Random still life:
rand9x9.png
rand9x9.png (2.52 MiB) Viewed 5699 times

Post Reply