Growing the Doubly Marked Robinson Tiles in FTAM

Set up  (evaluate everything in this section)

A description of the data formats

tiles, tilings, and hierarchies

Tiles occur in different data structures depending on our precise meaning of the word:

a tiletype, as listed in TILETYPELIST is a unique identifier for each kind of prototile. (In the version being prepared now, this will be a string; currently it is an ad hoc data type.)

Various kinds of data is keyed off of these, for example, the 
possibleNeighbors[{(*of a*) tileType, (*in a particular*) orientation}, (*in a specific*) direction]


a {tiletype,orientation} is  useful once we don’t wish to  deal with having prototiles in different aspects. 

a {tiletype,{position, orientation}}, or even {tiletype,{address, level, position, orientation}} is an implementation of a tile within a particular  patch, configuration or hierarchy. 

A hierarchy of tiles consists of nested lists of the form:

form = { a single tile of a specific level of address }

or 

form = { a sequence of lists  of type form}

I will be filling in utilities for hierarchies in coming weeks.

markings and signals

In this code, markings are used to encode the tiles and matching rules. To each edge of a marked tile, there is a corresponding marking list of markings, each of the form

markingname
or
{markingname, {±1}} 
or
{markingname, {±1,±1}}
(potentially, etc)

Markings with parity {±1,±1} are shown as at right below. The basic construction of the doubly marked Robinson tiles uses markings with these parities. 

For  signalling we use markings with no parity (simply, do the colors match?) as at left below, or with a parity { ±1}, which might be interpreted as  either an outwardness or a sidedness, relative master markings with parity {±1,±1}

marking lists are the basic object compared between neighboring tiles; 
marking lists match iff they have corresponding pairs of matching markings; 
markings match iff they have the same marking name, and matching parities;
parities match if they are are of the same size and sum to 0.

the basic tile types

New tiletypes are defined off of a few base types: 

CO, UO, CR and VV -- As a foundational part of the matching rules, we enforce this particular arrangement: 




The markings on these types further fall into pairs. First:

"CO", "UO": 

Cornered Outward, Uncornered Outward, the corners of structures in the doubly marked Robinson tiling.  The CO tiles are at the 1st level of structure and the UO tiles are at all higher levels (and so play a greater role in the construction).



The markings of this base type, reading clockwise from north as usual, are:

{{Gg, {1, 1}}} (*Green*)
{{Rr, {-1, -1}}} (*Red*)
{{Bb, {1, -1}}} (*Blue*)
{{Rr, ±{-1, -1}}}
{{Bb, {1, 1}}}
{{Rr, {-1, 1}}}
{{Gg, {1, -1}}}
{{Rr, ±{1, 1}}}










There are multiple ways to fill in the Red marking from NW to SE. But as prototiles, we are careful to keep all of the arrows in order, which means that really there are only two possibilities for each, which we denote
"COPP", "UOPP" (cornered/uncornered outward tiles, with a `positive marking outward'), shown at left below, 
and "COMM", "UOMM", at right.  

Various other tiles will use these as a base, and have tile type names beginning with these strings.

COPP    UOPP     COMM    UOMM

CR and VV tiles convey and cross signals. The CR tiles are on the 1st level structure of the tiling, and the VV tiles for higher level structure. (We distinguish these by the tiles’ background color.)

VGG, shown at upper left below, for example, has these markings:

{{Gg,{1,1}}}
{{Rr,{1,1}}}
{{Gg,{-1,-1}}}
{{Rr,{1,-1}}}
{{Gg,{-1,-1}}}
{{Rr,{1,1}}}
{{Gg,{-1,1}}}
{{Rr,{1,-1}}}


The marking at N will be one of {Gg,{1,1}} or {Bb,{1,1}}, and is abbreviated B or G. 
The marking at S will be the complementary {Gg,{-1,-1}} or {Bb,{-1,-1}}.

The marking at W will be {Gg,{-1,1}}, {Bb,{-1,1}} or {Bb,{-1,-1}}, abbreviated G, Bp, Bm. 
The marking at W will be the reflected {Gg,{-1,-1}}, {Bb,{-1,-1}} or {Bb,{-1,1}}.



VGG	VBG	CGG	CBG
VGBm	VBBm	CGBm	CBBm
VGBp	VBBp	CGBp	CBBp

(*This code is always useful for retrieving  markings for a  tileType*)

Print["The tile's markings, clockwise from North:"]; Print[#] & /@ 
TileMarkings[
  {"UOPP"(*or whatever tileType you like*), 0}];

defining the tile name space

Protect[CO (*cornered outward*), UO (*uncornered outward*), CR (*crossing*),VV (*old vertex edge*), PP (*plus UL diagonal*), MM(*minus UL diagonal*),Gg (*green*),Bb (*blue*), Rr (*red*)
];

(*Changes to this need to be reflected in SubATile *)

(BASETILETYPELIST=Join[Join @@ 
Table[
{outward,pm,{}}, 
(*The outward tiles, cornered and uncornered, in two flavors*)
{outward,{CO,UO}},{pm,{PP,MM}}],

With[{edgelevel=CR},
Join @@Join @@ 
Table[Table[
{edgelevel, crossing,crossed,pm,{}},
(*The crossing tiles, of level 0 or 1+, with Bb or Gg dominant, Bb or Gg crossed, and whether crossed signal is flipped or not*)
{pm,Switch[crossed,Gg,{1},Ggg,{1},Bb,{1,-1},Bbb,{1,-1}]}],{crossing,{Gg,Bb}},{crossed,{Ggg,Bbb}}]],


With[{edgelevel=VV},
Join @@Join @@ 
Table[Table[
{edgelevel, crossing,crossed,pm,{}},
(*The crossing tiles, of level 0 or 1+, with Bb or Gg dominant, Bb or Gg crossed, and whether crossed signal is flipped or not*)
{pm,Switch[crossed,Gg,{1},Bb,{1,-1}]}],{crossing,{Gg,Bb}},{crossed,{Gg,Bb}}]]
];


TILETYPELIST=BASETILETYPELIST;



Clear[TileStringName];
Inner[(TileFullName[#1]=TileFileName[#1]=#2;TileFromFullName[#2]=#1;)&,BASETILETYPELIST,
{ "COPP","COMM","UOPP","UOMM",
"CGG","CGpB","CGmB",
"CBG","CBpB","CBmB",
(*"CGg","CGpb","CGmb","CBg","CBpb","CBmb",*)
"VGG","VGpB","VGmB",
"VBG","VBpB","VBmB"},List];


ResetTileMasterTypes:=(Clear[TileMasterTypes];
Module[{tempTileType},
(tempTileType =#;
TileMasterTypes[tempTileType]=  Select[TILETYPELIST,#[[1]]===tempTileType&])]&/@(Union@(#[[1]]&/@TILETYPELIST))
);

ResetTileMasterTypes;




reducedTiles=Join @@ Table[{types,orientations},{types,TILETYPELIST},{orientations,0,7}];);

TILETYPELIST

DIRECTIONS={{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};



Table[directionToIndex[DIRECTIONS[[ii]]]=ii,{ii,8}];

orienting the tiles

(* Each instance of tile has an orientation; these may be composed by multiplying on the right. Thus sequences of transformations are read left to right*) 

(*The code of a transformation can be read in  binary, right to left: *) 

Table[ transformMatrixTable[4x+2y+z]=
(*xyz perfoms*)

(* z: flip across vertical axis*) MatrixPower[{{-1,0},{0,1}},z].  

(* y: flip across horizontal axis*) MatrixPower[{{1,0},{0,-1}},y]. 

(* x: flip across diagonal (NW-SE) axis*) MatrixPower[ {{0,-1},{-1,0}},x] , 

{x,{0,1}},{y,{0,1}},{z,{0,1}}] ;  Table[ a⊕b=orientationPlusTable[a,b]=((transformMatrixTable[a].transformMatrixTable[b])// (Position[Table[transformMatrixTable[i],{i,0,7}],#][[1,1]]-1&)), {a,0,7},{b,0,7}];

x_⊙a_:=x.transformMatrixTable[a];

(invert[#]=#)&/@{0,1,2,3,4,7};
 
invert[5]=6;
 
invert[6]=5;

drawing tiles, patches and configurations
(change directory path!)

(*We load images of each individual tile, then assemble these*)

IMAGESIZEFORDRAWINGS=288;

ReloadDrawings:=(MasterTilePicture["CR"]=ImageResize[,IMAGESIZEFORDRAWINGS];
MasterTilePicture["UO"]=ImageResize[,IMAGESIZEFORDRAWINGS];
MasterTilePicture["CO"]=ImageResize[,IMAGESIZEFORDRAWINGS];)
ReloadDrawings

(*For older color scheme see ≤ 2017_11_keep_* *)
BASETILEOPACITY=40/255.;

ResetSignalColors:=(
Clear[signalColor];

SGO=BASETILEOPACITY;
SSGO=.6 SGO;

(signalColor[#[[1]]]=Round[(Append[#,120]&/@#[[2]])/255.,.01])&/@
{
{Gg,{{91,174,168},{55,116,112}}},
{Bb,{{68,128,178},{157,181,211}}},
{Rr,{{213,130,40},{246,233,195}}}
};


signalColor[x_,a_]:=signalColor[x,a]=(ReplacePart[#,4->a]&/@signalColor[x]);



boundinGColor={55,116,112};
blueColor={68,176,220};
boundBColor={68,110,170};
inColor={170,40,90};
upColor={200,45,144};
up0Color=(255-1(255-#))&@upColor;
up1Color=(255-.7(255-#))&@upColor;
up2Color=(255-.8(255-#))&@upColor;
up3Color=(255-.4(255-#))&@upColor;
greenColor={93, 162, 29};
boundGColor={0,130,120};
skelColor={255,242,0};
redColor={240,150,11};

rskelColor= {85,118,48};
diagColor={170,200,0};
dblDiagColor={200,22,90};
sglDiagColor={240,22,120};
boundColor2={170,40,90};
inColor={250,177,194};

greenColor2={226,110,178};
skelColor=redColor2={248,228,152};




((signalColor[#[[1]]]=Round[
(
If[Length[#]===3,Append[#/255.,1],Append[1-(255-Drop[#,-1]) #[[-1]]/255.^2,1]]&/@
#[[2]]),.01]
)&/@
{#,#/.{Bb->Bbb,Gg->Ggg}}
)&/@


{
{{Bb},{{68,128,178,255 SGO (*signal opacity*)},{157,181,211,255SGO}}},
{{Gg},{{55,116,112,255 1.2SGO},{91,174,168,255 SGO}}},
{{Rr},{{213,130,40,255 SGO},{246,233,195,255 SGO}}},

{{Bb,bound},{boundBColor,blueColor}},

{{bound,Gg},{boundGColor,greenColor}},

{{skel,Bb},{blueColor,skelColor}},

{{skel,Gg},{greenColor,skelColor}},

{{skel,Rr},{redColor,skelColor}},(*Is this incorrect?Is it used?*)
{{ddiag,Rr},{redColor2,rskelColor}}, 

{{dblDiag,Rr},{boundColor2,dblDiagColor}},
{{diag,Rr},{redColor2,diagColor}},
{{Rr,sglDiag},{boundColor2,sglDiagColor}},


{{up0,Gg},{greenColor2,up0Color}},
{{uP0,Gg},{greenColor2,up0Color}},
{{up1,Gg},{greenColor2,up1Color}},
{{up2,Gg},{greenColor2,up2Color}},
{{up3,Gg},{greenColor2,up3Color}},
{{upp,Gg},{greenColor2,up3Color}},
{{in,Bb,bound},{boundColor2,inColor}},
{{inp,Bb,bound},{boundColor2,inColor}},
{{in,bound,Gg},{boundColor2,inColor}},
{{inp,bound,Gg},{boundColor2,inColor}}, (*One of these isn't needed*)
{{skel,Bb,bound},{boundBColor,skelColor}},
{{skel,bound,Gg},{boundBColor,greenColor}},
{{up0,bound,Gg},{boundColor2,up0Color}},
{{uP0,bound,Gg},{boundColor2,up0Color}},
{{up1,bound,Gg},{boundColor2,up1Color}},
{{up2,bound,Gg},{boundColor2,up2Color}},
{{up3,bound,Gg},{boundColor2,up3Color}},
{{upp,bound,Gg},{boundColor2,up3Color}}};

);

ResetSignalColors;

ResetMakeTileImage:=(Clear[makeTileImage];

makeTileImage[tileType_]:=makeTileImage[tileType]=
Module[{markings},
(Which[

MemberQ[{CO,UO},tileType[[1]]],

markings=If[Length[#]>0,#[[1]],#]&/@#&/@TileMarkings[{tileType,0}];
ImageApply[Which[
#[[1]]<0.14,{0,0,0,.1} (*bold edge*),
#[[1]]<0.16,Append[1-(255-signalColor[{Rr}][[1]]) SSGO /255.^2,1],
#[[1]]<0.20,Append[1-(255-signalColor[{Rr}][[2]]) SSGO /255.^2,1],
#[[1]]<0.24,{#,#,#,1}&@If[tileType[[1]]===CO,.96,.67] (* center fill*),
#[[1]]<0.29,signalColor[markings[[8]]][[If[tileType[[2]]===PP,1,2]]],
#[[1]]<0.33,signalColor[markings[[8]]][[If[tileType[[2]]===PP,2,1]]],
#[[1]]<0.37,signalColor[markings[[7]]][[2]],
#[[1]]<0.40,signalColor[markings[[7]]][[1]],
#[[1]]<0.44,signalColor[markings[[6]]][[1]],
#[[1]]<0.48,signalColor[markings[[6]]][[2]],
#[[1]]<0.52,signalColor[markings[[5]]][[1]],
#[[1]]<0.56,signalColor[markings[[5]]][[2]],
#[[1]]<0.61,signalColor[markings[[4]]][[If[tileType[[2]]===PP,2,1]]],
#[[1]]<0.65,signalColor[markings[[4]]][[If[tileType[[2]]===PP,1,2]]],
#[[1]]<0.70,signalColor[markings[[3]]][[2]],
#[[1]]<0.75,signalColor[markings[[3]]][[1]],
#[[1]]<0.79,signalColor[markings[[2]]][[2]],
#[[1]]<0.82,{.9,.9,.9,1},(*soft edge*)
#[[1]]<0.84,signalColor[markings[[2]]][[1]],
#[[1]]<0.90,signalColor[markings[[1]]][[1]],(* 1 outside (R) *)
#[[1]]<0.95,signalColor[markings[[1]]][[2]],(* 1 inside (L) *)
#[[1]]<1.1,{0,0,0,0}
]&,

MasterTilePicture[ToString[tileType[[1]]]]],


MemberQ[{CR,VV},tileType[[1]]],

markings=(If[Length[#]>0,#[[1]],#]&/@#&/@TileMarkings[{tileType,0}])
//If[Take[tileType,{3,4}]==={Bb,-1},RotateRight[#,4],#]&;
ImageApply[Which[
#[[1]]<0.14,{0,0,0,.1} (*bold edge*),
#[[1]]<0.16,signalColor[{Rr}][[2]] ,
#[[1]]<0.20,signalColor[{Rr}][[1]] ,
#[[1]]<0.24,{#,#,#,1}&@If[tileType[[1]]===CO,.96,.67] (* center fill*),
#[[1]]<0.29,If[tileType[[1]]===CR,Append[1-(1-Drop[signalColor[{Rr}][[2]],-1]) SSGO /255,1],signalColor[markings[[8]]][[2]]],
#[[1]]<0.33,If[tileType[[1]]===CR,
Append[1-(1-Drop[signalColor[{Rr}][[1]],-1]) SSGO /255,1],signalColor[markings[[8]]][[1]]],
#[[1]]<0.37,signalColor[markings[[7]]][[1]],
#[[1]]<0.40,signalColor[markings[[7]]][[2]],
#[[1]]<0.44,If[tileType[[1]]===CR,
Append[1-(1-Drop[signalColor[{Rr}][[1]],-1]) SSGO /255,1],signalColor[markings[[6]]][[1]]],
#[[1]]<0.48,If[tileType[[1]]===CR,Append[1-(1-Drop[signalColor[{Rr}][[2]],-1]) SSGO /255,1],signalColor[markings[[6]]][[2]]],
#[[1]]<0.52,signalColor[markings[[5]]][[If[Take[tileType,{3,4}]==={Bb,-1},1,2]]],
#[[1]]<0.56,signalColor[markings[[5]]][[If[Take[tileType,{3,4}]==={Bb,-1},2,1]]],
#[[1]]<0.61,If[tileType[[1]]===CR,
Append[1-(1-Drop[signalColor[{Rr}][[2]],-1]) SSGO /255,1],signalColor[markings[[4]]][[2]]],
#[[1]]<0.65,If[tileType[[1]]===CR,
Append[1-(1-Drop[signalColor[{Rr}][[1]],-1]) SSGO /255,1],signalColor[markings[[4]]][[1]]],
#[[1]]<0.70,signalColor[markings[[3]]][[2]],
#[[1]]<0.75,signalColor[markings[[3]]][[1]],
#[[1]]<0.79,If[tileType[[1]]===CR,
Append[1-(1-Drop[signalColor[{Rr}][[1]],-1]) SSGO /255,1],signalColor[markings[[2]]][[1]]],
#[[1]]<0.82,{.9,.9,.9,1},(*soft edge*)
#[[1]]<0.84,If[tileType[[1]]===CR,
Append[1-(1-Drop[signalColor[{Rr}][[2]],-1]) SSGO /255,1],signalColor[markings[[2]]][[2]]],
#[[1]]<0.90,signalColor[markings[[1]]][[If[Take[tileType,{3,4}]==={Bb,-1},2,1]]],(* 1 outside (R) *)
#[[1]]<0.95,signalColor[markings[[1]]][[If[Take[tileType,{3,4}]==={Bb,-1},1,2]]],(* 1 inside (L) *)
#[[1]]<1.1,{0,0,0,0},True,{0,0,0,0}
]&,

MasterTilePicture["CR"]]//If[Take[tileType,{3,4}]==={Bb,-1},ImageRotate[#,Pi],#]&


]
//Which[

indexOfGroupOfTilesForFTAM[#]===10000,
#,

True,
#]&

)

]);

ResetMakeTileImage;


IMAGESIZEFORDRAWINGS=144;

ReloadDrawings:=(Clear[TilePicture];TilePicture[type_] :=TilePicture[type]=ImageResize[ makeTileImage[type],IMAGESIZEFORDRAWINGS];)

ReloadDrawings;

HALFPICTURESCALE=.5 (PICTURESCALE=1.6);  
 
Clear[orientationFunction];
 
orientationFunction[transformationIndex_]:= orientationFunction[transformationIndex]= {#&, Scale[#,{-1,1}]&, Scale[#,{1,-1}]&, Rotate[#,Pi]&, Rotate[Scale[#,{-1,1}],Pi/2]&, Rotate[#,Pi/2]&, Rotate[#,-Pi/2]&, Rotate[Scale[#,{-1,1}],-Pi/2]&}[[transformationIndex+1]]   
 
ImageDrawATile[{type_,{position_,orientation_}}]:= orientationFunction[orientation][Inset[TilePicture[type],-HALFPICTURESCALE{1,1}+position,{0,0},PICTURESCALE]];

(*ReloadDrawings;*)DrawATile=ImageDrawATile;


(*An alternative or supplementary method of drawing tiles as usual Graphics directives. *)

Clear[signalDrawing,DrawSignal,QuickDrawATile,sSignalColor];
signalDrawing[type_,index_]:=signalDrawing[type,index]=(#+If[Length[type]===2 && Length[type[[2]]]===2,
.2(type[[2,2]])(DIRECTIONS[[Mod[index+1,8]+1]]),{0,0}])&/@{{0,0},.5 DIRECTIONS[[index]]};

DrawSignal[type_,pos_,index_]:=
{sSignalColor[If[Length[type]===0,type,type[[1]]]],
Line[(pos+#)&/@signalDrawing[type,index]]}


DrawSignal[{Bb,_},pos_,index_]:={};
DrawSignal[{Rr,_},pos_,index_]:={};


(* these colors should be replaced with the colors set up above *)

Inner[(sSignalColor[#1]=#2)&,{Bb,bound,dblDiag,diag,Gg,in,Rr,sglDiag,skel,up0,up1,up2,up3},
{Blue,Gray,Orange,Yellow, Green,Purple,Red,Yellow, Yellow, Purple, Purple,Purple,Purple},List];

sSignalColor[other_]=Black;

(* for overlaying vertices *)

vertexDiskRadius =.5;

vertexDiskColor=RGBColor[229/255,45/255,12/255,.8];

vertexDiskColor2=RGBColor[.2,.2,.2,.6];

vertexDrawing[{type_,{pos_,or_}}]:=
Which[
(indexOfGroupOfTilesForFTAM[type]===10000),
{vertexDiskColor,Disk[pos,vertexDiskRadius]},
Length[Select[type[[-1]],!(#==={})&]]>2,
{vertexDiskColor2,Disk[pos,.7 vertexDiskRadius]},
True,{}];

ShowAConfigWVerts=(ShowAConfig[#,
{vertexDiskColor,Disk[{0,0},vertexDiskRadius],
vertexDrawing/@#[[1]]}])&;

QuickDrawATile[{type_,{position_,orientation_}}]:=

Table[DrawSignal[#,position,i]&/@#[[i]],{i,8}]&@

TileMarkings[{type,orientation}]

(*DrawATile=QuickDrawATile;*)

(* A patch is a list of instances of tiles*)


 
DRAWINGOFFSET = 2; 
PATCHRANGEOVERIDEminX=PATCHRANGEOVERIDEmaxX=PATCHRANGEOVERIDEminY=PATCHRANGEOVERIDEmaxY=0;
 
Clear[ShowAPatch]

ShowAPatch[patch_]:=ShowAPatch[patch,{}];

ShowAPatch[patch_,post_]:=Graphics[{Parallelize@Map[DrawATile,patch],post},PlotRange->{{Min[#[[-1,1,1]]&/@patch]-DRAWINGOFFSET,Max[#[[-1,1,1]]&/@patch]+DRAWINGOFFSET}, {Min[#[[-1,1,2]]&/@patch]-DRAWINGOFFSET,Max[#[[-1,1,2]]&/@patch]+DRAWINGOFFSET}}];


ShowAPatch[pre_,patch_,post_]:=Graphics[{pre, DrawATile/@patch,post},PlotRange->{{Min[Min[#[[-1,1,1]]&/@patch]-DRAWINGOFFSET,PATCHRANGEOVERIDEminX],Max[Max[#[[-1,1,1]]&/@patch]+DRAWINGOFFSET,PATCHRANGEOVERIDEmaxX]}, {Min[Min[#[[-1,1,2]]&/@patch]-DRAWINGOFFSET,PATCHRANGEOVERIDEminY], Max[Max[#[[-1,1,2]]&/@patch]+DRAWINGOFFSET,PATCHRANGEOVERIDEmaxY]}}]




Protect[RasterizeQ];
 
RASTERSIZE=1000;
 
IMAGESIZE=500; 
 

ShowAPatch[patch_,RasterizeQ->True]:=ShowAPatch[patch]//Rasterize[#,RasterSize->RASTERSIZE,ImageSize->IMAGESIZE]&


ShowAPatch[pre_,patch_,post_,RasterizeQ->True]:=ShowAPatch[pre,patch,post]//Rasterize[#,RasterSize->RASTERSIZE,ImageSize->IMAGESIZE]&

(*A configuration is the basic data structure for this notebook, and is a list of lists. 

Here the important thing is that a configuration's first sublist is a patch. ShowAConfig also illustrates neighboring sites (yellow) and of those which are active (green). *)

(*As with ShowAPatch, ShowAConfig has optional definitions that allow other graphics elements to be added below (pre) or above (post) the illustration.*)

TILESITEDISKRADIUS=.0;  
ACTIVESITEDISKRADIUS=.15;
SITEDISKRADIUS=ACTIVESITEDISKRADIUS;


ShowAConfig[config_]:=ShowAPatch[ config[[1]],Join[{Blue},Disk[#,TILESITEDISKRADIUS]&/@config[[2]], {Green},Disk[#+.5{.1,.2},ACTIVESITEDISKRADIUS]&/@config[[4]],{Yellow},Disk[#+.5{-.1,.2},ACTIVESITEDISKRADIUS]&/@config[[5]]]];   

ShowAConfig[config_,post_]:=ShowAPatch[ config[[1]],Join[{Blue},Disk[#,TILESITEDISKRADIUS]&/@config[[2]], {Green},Disk[#+.5{.1,.2},ACTIVESITEDISKRADIUS]&/@config[[4]],{Yellow},Disk[#+.5{-.1,.2},ACTIVESITEDISKRADIUS]&/@config[[5]],  post]]  

ShowAConfig[pre_,config_,post_]:=ShowAPatch[pre, config[[1]],Join[{Blue},Disk[#,TILESITEDISKRADIUS]&/@config[[2]], {Green},Disk[#+.5{.1,.2},ACTIVESITEDISKRADIUS]&/@config[[4]],{Yellow},Disk[#+.5{-.1,.2},ACTIVESITEDISKRADIUS]&/@config[[5]],  post]]



ShowAConfig[config_,RasterizeQ->True]:=ShowAConfig[config]//Rasterize[#,RasterSize->RASTERSIZE,ImageSize->IMAGESIZE]&


ShowAConfig[pre_,config_,post_,RasterizeQ->True]:=ShowAConfig[pre,config,post]//Rasterize[#,RasterSize->RASTERSIZE,ImageSize->IMAGESIZE]&

substitution rules on tiles

(*This is actually pretty straightforward for the basic tiles defined above. 

The definitions below allow substituting on any derivation from those, plugging in the new markings appropriately --- that's why the definitions are so lengthy*)

Clear[SubATile];







SubATile[{type_,{pos_,or_}}]:=  
(growthQ =StringTake[TileFullName@type,3]==="gro";
Which[ 

type[[1]]===CR,(*crossing, 1st level*)
{
{{CR,type[[2]],Bbb,-1,type[[-1]]},{2 pos+{0,1}⊙or,or}},
{ReplacePart[type,1->VV],{2pos,or}}/.{Bbb->Bb,Ggg->Gg},
{{CR,type[[2]],Bbb,1,type[[-1]]},{2pos+{0,-1}⊙or,or}}},

type[[1]]===CO,(*cornered outward*)
{
{{UO,type[[2]],type[[-1]]},{2pos,or}},

{{CR,Gg,Ggg,1,
If[type[[-1]]=={}||type[[-1]][[1]]==={},{},
{type[[-1]][[1]],{},{},{},type[[-1]][[1]],{},{},{}}]},{2pos+{0,1}⊙or,or}},
{{CR,Gg,Ggg,1,If[type[[-1]]=={}||type[[-1]][[7]]==={},{},
{type[[-1]][[7]],{},{},{},type[[-1]][[7]],{},{},{}}]},{2pos+{-1,0}⊙or,4⊕or}},
{{CR,Bb,Ggg,1,If[type[[-1]]=={}||type[[-1]][[3]]==={},{},
{type[[-1]][[3]],{},{},{},type[[-1]][[3]],{},{},{}}]},{2pos+{1,0}⊙or,7⊕or}},
{{CR,Bb,Ggg,1,If[type[[-1]]=={}||type[[-1]][[5]]==={},{},{type[[-1]][[5]],{},{},{},type[[-1]][[5]],{},{},{}}]},{2pos+{0,-1}⊙or,3⊕or}},

{{CO,type[[2]],If[type[[-1]]=={}||type[[-1]][[4]]==={},{},
{{},{},{},type[[-1]][[4]],{},{},{},type[[-1]][[4]]}]},{2pos+{1,-1}⊙or,or}}, 
{{CO,PP,If[type[[-1]]=={}||type[[-1]][[6]]==={},{},{{},{},{},type[[-1]][[6]],{},{},{},type[[-1]][[6]]}]},{2pos+{-1,-1}⊙or,1⊕or}},
{{CO,PP,If[type[[-1]]=={}||type[[-1]][[2]]==={},{},{{},{},{},type[[-1]][[2]],{},{},{},type[[-1]][[2]]}]},{2pos+{1,1}⊙or,5⊕or}},
{{CO,Switch[type[[2]],MM,PP,PP,MM],If[type[[-1]]=={}||type[[-1]][[8]]==={},{},{{},{},{},type[[-1]][[8]],{},{},{},type[[-1]][[8]]}]},{2pos+{-1,1}⊙or,3⊕or}}},  

True, { {type,{2 pos,or}} }  ]   
)


(*And defining supertiles, with various options*)
Clear[superTile]
superTile[type_,0]:=superTile[type,0]={{type,{{0,0},0}}};

superTile[type_,level_]:=superTile[type,level] = (Join @@(SubATile/@ superTile[type,level-1]));

superTile[type_,or_,0]={{type,{{0,0},or}}};

superTile[type_,or_,level_]:=superTile[type,or,level] = (Join @@(SubATile/@ superTile[type,or,level-1]));


(*For testing, these are useful*)
Clear[superAxes];
superAxes[type_,level_,axis_]:=superAxes[type,level,axis]=Select[superTile[type,level],(Sign/@#[[-1,1]]===Sign/@axis)||(#[[-1,1]]==={0,0})&]

(*so a basic level 1 supertile is 
superTile[{CO,PP,{}},1]*)

growth commands for configurations

(*A configuration is the basic data structure of this notebook and is of the form

{patch, 
filledSitePositions, 
activeSitePositionsAndTileList, 
activeSitePositions, 
inactiveNeighboringSitePositions}

patch is a list of tiles;

filledSitePositions is a list of positions of tiles (should be equal to #[[-1,1]]&/@patch)

activeSitePositionsAndTileList is a list 
{ {position, { {tiletype, or}, ...}}
 from which an eligible tile may be placed (this allows implementation of the forced tile assembly model)

activeSitePositions  is a list of the positions of the active sites. 

inactiveNeighboringSitePositions is a list {position,...*)

(*The particular model of assembly is determined by the definition of :

CollectionOKToBeActiveQ

The order in which sites are filled in is determined by the definition of

CHOICEFUNCTION*)

CompatibleTiles[patch_,site_]:=  (*Get the neighbors*) Select[patch, MemberQ[DIRECTIONS, #[[-1,1]]-site]&]// (( possibleNeighbors[ReplacePart[#,2->#[[2,2]]],site-#[[2,1]]]  )&/@#)&//If[#==={},{},Intersection@@ #]&//ReplacePart[#,2->{site,#[[2]]}]&/@#&

CollectionOKToBeActiveQ=(Length[#]===1)&; (*change as model changes*)

AddATileToConfig[{patch_,filledSitePositions_,activeSitePositionsAndTileList_,activeSitePositions_,inactiveNeighboringSitePositions_},newTile_]:=  Module[{newPatch,newFilledSitePositions,tempASL,tempASP,newActiveSitePositionsAndTileList,newActiveSitePositions,newImmediateNeighborPositionsToCheck,tTtemp,newInactiveSitePositions},

(newPatch=Append[patch,newTile];(*to save time, assume it is not on the list already!*)  newFilledSitePositions=Append[filledSitePositions,newTile[[-1,1]]];(*ditto*)  tempASL=newActiveSitePositionsAndTileList=Select[activeSitePositionsAndTileList,!(And@@((#≤1)&/@Abs[#[[1]]-newTile[[-1,1]]]))
&];(*old active sites other than the new tile and its immediate neighbors*) tempASP = newActiveSitePositions = Select[activeSitePositions,!(And@@((#≤1)&/@Abs[#-newTile[[-1,1]]]))
&]; (*old active site positions other than the position of the new tile and its immediate neighbors*)  

newImmediateNeighborPositionsToCheck = Complement[newTile[[-1,1]]+#&/@DIRECTIONS,newActiveSitePositions,newFilledSitePositions]; (*no need to check if already filled*)   tTtemp=Select[({#,(CompatibleTiles[newPatch,#]//If[CollectionOKToBeActiveQ[#],#//FTAMRESTRICTIONFUNCTION,{}]&)}&/@newImmediateNeighborPositionsToCheck ),!#[[2]]==={}&] (*tTemp is the newly active positions*);  newActiveSitePositionsAndTileList=Join[newActiveSitePositionsAndTileList,tTtemp]; newActiveSitePositions=Join[newActiveSitePositions,#[[1]]&/@tTtemp]; newInactiveSitePositions=Complement[Join[Select[inactiveNeighboringSitePositions,!#===newTile[[-1,1]]&],newImmediateNeighborPositionsToCheck],#[[1]]&/@tTtemp];   {newPatch,newFilledSitePositions,newActiveSitePositionsAndTileList,newActiveSitePositions,newInactiveSitePositions})]

AddTilesToConfig[Config_,{}]:=Config; 

AddTilesToConfig[Config_,TileList_]:=AddTilesToConfig[AddATileToConfig[Config,TileList[[1]]],Drop[TileList,1]]

(*Can swap out how the growth is handled*)

DEFAULTCHOICEFUNCTION=RANDOMCHOICEFUNCTION = RandomChoice[RandomChoice[#[[3]]][[2]]]&;

BULKCHOICEFUNCTION=#[[3,1,2,1]]&;

(*AnAlternativeChoiceFunction=(RandomChoice[#[[3]][[2]]]//If[Length[#]==1,#[[1]],*)

PRINTCHOICEFUNCTION = (RandomChoice[RandomChoice[#[[3]]][[2]]]//((
If[indexOfGroupOfTilesForFTAM[#[[1]]]===10000,
Print[TileFullName[#[[1]]]<>"\n"]];#)&))&;
CHOICEFUNCTION=PRINTCHOICEFUNCTION;

CHOICEFUNCTION=DEFAULTCHOICEFUNCTION;

GrowAConfig[config_]:=If[config[[3]]==={},config,  AddATileToConfig[config,CHOICEFUNCTION@config]];

BuildOutAConfig[config_]:= (Nest[GrowAConfig,config,Length[config[[3]]]]);

blankConfig=Table[{},{5}];

SeedRandom[];

resetGrowth:=(Clear[configs, saveConfigs];


configStops={0};
configs[0]= AddTilesToConfig[blankConfig,seedPatch];
numConfigs=0;)




goOutTo[nextStop_]:=
(AppendTo[configStops,nextStop];

FixedPoint[(If[numConfigs++<configStops[[-1]],GrowAConfig[#],#])&,configs[configStops[[-2]]]]//(configs[lastStop=configStops[[-1]]]=#)&
);

setting up for FTAM

(*

The additional tile types are based off of the original ones, indicated by all but the last list in the type. The last list is of the additional markings on the tile, of the form
{MARKING, ... } where each MARKING is of the form
{ID, parity} where ID is arbitrary and parity is a possibly empty list of integers. These lists can be expanded at will. 

Each tile type has a full name,  and a file namem

both keyed below. Different types may have the same file name if a drawing has not been especially prepared for that type. 

For FTAM to work, tiles are grouped into distinct sets: a site is active if and only tiles from at most one set are compatible at the site. Tiles from a given set have the same value of the function
indexOfGroupOfTilesForFTAM




*)
(*FTAM: redefining the boolean query  CollectionOKToBeActiveQ 
turns on the Forced Tile Assembly Model*)

(*give grouped tiles indices that are multiples of 10000 ---i.e. much greater than we could possibly need for individual tiles*)

MAXFTAMTILEINDEX=1;
Clear[indexOfGroupOfTilesForFTAM]
(indexOfGroupOfTilesForFTAM[#]=MAXFTAMTILEINDEX++)&/@TILETYPELIST;



(*Either we have only a single tile possible, or the indices of the possible tiles are all the same multiple of 10000*)

CollectionOKToBeActiveQ=
((Length[#]===1 )||
(Mod[Union@(indexOfGroupOfTilesForFTAM[#[[1]]]&/@#),10000]==={0}))&;

FTAMRESTRICTIONFUNCTION=DEFAULTFTAMTRESTRICTIONFUNCTION =#&;

(*For more exotic sequences*)
RESTRICTIONTO12=If[indexOfGroupOfTilesForFTAM[#[[1,1]]]===10000,(Print[(StringJoin@@(TileFullName[#[[1]]]<>"  "&/@#))<>"\n"]; Select[#,MemberQ[{"growth_1_1","growth_1_2","growth_2_1","growth_2_2"},TileFullName[#[[1]]]]&]//(Print[(StringJoin@@(TileFullName[#[[1]]]<>"  "&/@#))<>"\n"];#)&



),#]&;


FTAMRESTRICTIONFUNCTION=RESTRICTIONTO12;

GLOBALRESTRICTIONSEQUENCE={"growth_1_3d1","growth_3d1_3e1","growth_3e1_3p1","growth_3p1_1","growth_1_2", "growth_2_3e2","growth_3e2_3p2","growth_3p2_2","growth_2_1"}


RESTRICTIONTOGLOBALSEQUENCE:=
If[indexOfGroupOfTilesForFTAM[#[[1,1]]]===10000,(Print[(StringJoin@@(TileFullName[#[[1]]]<>"  "&/@#))<>"\n"]; 

GLOBALRESTRICTIONSEQUENCE=RotateLeft[GLOBALRESTRICTIONSEQUENCE,1];
Print[GLOBALRESTRICTIONSEQUENCE[[-1]]<>":\n"];

Select[#,MemberQ[{
GLOBALRESTRICTIONSEQUENCE[[-1]]},TileFullName[#[[1]]]]&]//(Print[(StringJoin@@(TileFullName[#[[1]]]<>"  "&/@#))<>"\n"];#)&



),#]&;


FTAMRESTRICTIONFUNCTION=RESTRICTIONTOGLOBALSEQUENCE;

overlaying new markings on top of previously defined tiles

(*This gives a fairly quick way to build new tiles out of old ones*)

AddMarkingsToTileType[oldMarkings_,newTileMarkingsList_]:=
Union @@#&/@Thread[List[
If[#=={},Table[{},{8}],#]&@oldMarkings,
ReplacePart[Table[{},{8}],newTileMarkingsList]]];

AddTileType[{baseTileName_,newTileMarkingsList_,newTileFullName_,newTileFileName_,newTileFTAMIndex_(*If desired*)}]:=
Module[{newTile,baseTile},
baseTile=TileFromFullName[baseTileName];
newTile=Append[
Drop[baseTile,-1],
AddMarkingsToTileType[baseTile[[-1]],newTileMarkingsList]];
(*merge the old and new additional markings, sorting for canonical form; presume that everything is appropriately well-formed*)
TileFromFullName[newTileFullName]=newTile;
TileFullName[newTile]=newTileFullName;
TileFileName[newTile]=newTileFileName;
indexOfGroupOfTilesForFTAM[newTile]=newTileFTAMIndex;
AppendTo[TILETYPELIST,newTile];
TileMasterTypes[newTile[[1]]]=Append[TileMasterTypes[newTile[[1]]],newTile];
newTile
]


(*If no index is specified*)
AddTileType[{baseTileName_,newTileMarkingsList_,newTileFullName_,newTileFileName_}]:=AddTileType[{baseTileName,newTileMarkingsList,newTileFullName,newTileFileName,MAXFTAMTILEINDEX++}];


AddTilesToTypeList[newTypeList_,resetBaseQ_]:=(

AddTileType[#]&/@newTypeList;
ResetTileMarkings;
ResetPossibleEdgeNeighbors;
ReloadDrawings;)

mergeIndexedLists=
Table[i->Union@@(#[[-1]]&/@
Select[Join@@#,#[[1]]==i&]),
{i,Union@@{(#[[1]]&/@(Join@@#))}}]&;

(*reflect markings across vertical*)
reflectIndexedList=Sort[
ReplacePart[#,1->Mod[7-#[[1]],8]+1]&/@#]&;

nameIndexedList[indexList_]:=signalStringReplace@({"x","x","x","x","x","x","x","x"}//ReplacePart[#,indexList]&)

(*signalStringReplace[indexList_]:=indexList/.SIGNALSHORTNAMEREPLACEMENTLIST*)





Clear[replaceSignalsWString];

((replaceSignalsWString[#[[1]]]=#[[2]])&/@
{{diag,"x"},
{ddiag,"Y"},
{in,"i"},
{inp,"P"},
{skel,"k"},
{up0,"0"},
{uP0,"o"},
{up1,"1"},
{up2,"2"},
{up3,"3"},
{upp,"p"},
{{Bb,{-1,-1}},""},
{{Bb,{-1,1}},""},
{{Bb,{1,-1}},""},
{{Bb,{1,1}},""},
{{Bbb,{-1,-1}},""},
{{Bbb,{-1,1}},""},
{{Bbb,{1,-1}},""},
{{Bbb,{1,1}},""},
{{bound,{-1}},"b"},
{{bound,{1}},"B"},
{{dblDiag,{-1}},"d"},
{{dblDiag,{1}},"E"},
{{Gg,{-1,-1}},""},
{{Gg,{-1,1}},""},
{{Gg,{1,-1}},""},
{{Gg,{1,1}},""},
{{Ggg,{-1,-1}},""},
{{Ggg,{-1,1}},""},
{{Ggg,{1,-1}},""},
{{Ggg,{1,1}},""},
{{Rr,{-1,-1}},""},
{{Rr,{-1,1}},""},
{{Rr,{1,-1}},""},
{{Rr,{1,1}},""},
{{Rr,{0,-1}},""},
{{Rr,{0,1}},""},
{{sglDiag,{-1}},"s"},
{{sglDiag,{1}},"T"}
}
;)


signalStringReplace[signal_]:=(replaceSignalsWString@signal)

(*SIGNALSHORTNAMEREPLACEMENTLIST={ up0->"0",up1->"1",up2->"2",up3->"3",in->"i",
{sglDiag,{1}}->"S",{sglDiag,{-1}}->"s",(*{{diag,{1}}}->"D",{{diag,{-1}}}->"d",*){dblDiag,{1}}->"B",{dblDiag,{-1}}->"b",skel->"k",diag->"D",{bound,{(*0,*)1}}->"",{bound,{0,1}} ->"",{bound,{(*0,*)-1}}->"",{bound,{0,-1}}->""};*)

TileSignalsName[{tile_,or_}]:=
(StringDrop[StringJoin @@((StringJoin[replaceSignalsWString/@#]<>"."&/@ TileMarkings[{tile,or}])/.{""->" "}),-1])

Protect[uP0,up0,up1,up2,up3,diag,dblDiag,sglDiag,dskel,ddiag,skel,bound];

helpful for debugging

grabNear[location_,patch_,distance_]:=
Select[patch,(And@@((#≤distance)&/@Abs[location-#[[2,1]]]))&]

grabNear[location_,patch_]:=grabNear[location,patch,1]

define the new tiles

wholeBunchaNewTiles = Join[


(*The uncornered outward tiles at the centers of growth:*)
(*These are the really important ones, and the language of possible hierarchies can 
be manipulated by modifying these collections*)

(*A.A*)
Join @@ Join @@ Table[{"UOPP",
upMarking=If[use0,up0,{up1,up2}[[B]]];
markingIndexList= If[B===2,reflectIndexedList,#&]@
{
{1->{upMarking},2->{ddiag},4->{ddiag},5->{{bound,{-1}}},
6->{{sglDiag,{-1}}},7->{in,{bound,{-1}}},8->{{sglDiag,{1}}}},

{1->{upMarking,{bound,{-1}}},2->{{sglDiag,{-1}}},3->{in,{bound,{-1}}},4->{ddiag},
6->{ddiag},7->{skel},8->{{sglDiag,{1}}}},

{1->{upMarking},2->{ddiag},3->{in,{bound,{1}}},4->{{sglDiag,{-1}}},5->{{bound,{1}}},
6->{ddiag},7->{skel},8->{{sglDiag,{1}}}}}[[caseIndex]],


"growth_"<>{"1","2","0"}[[caseIndex]]<>If[caseIndex==3,{"1","2"}[[B]],""]<>"_"<>If[use0,"0",""]<>{"1","2"}[[B]],
"UOPP"<>If[caseIndex==1,"G","B"]<>If[B===1,"","A"],10000

},
{caseIndex,3},{B,{1,2}},
{use0,{False,True}}
],

(*The tiles above exactly encode the language (0,1,2)* ofhierarchies. The commented out tiles allow (0,1,2,3)*, though there are a couple of tiles missing from the third block, and a new up0 signal (or some other mechanizm) is needed for the fourth of these blocks to work correctly*)

(*A.3d, A.3e, A.3p*)
(Join @@ Join @@Join @@ Table[
type = If[state==="e", "UOPP","UOMM"];
{type,
upMarking=If[use0,If[state=="p",uP0,up0],If[state=="p",upp,up3]];
markingIndexList= If[(*B===1*)(*2*)(*!!*)
(*MemberQ[{{2,"d"},{2,"p"},{2,"e"}},{B,state}]*)B===2,
reflectIndexedList,#&]@
Join[{1->Join[{upMarking},If[A===1,{},{{bound,{-1}}}]],
2->{{ddiag},{{sglDiag,{-1}}}}[[A]],
4->{{If[state==="p",sglDiag,dblDiag],{1}}},
6->{{{sglDiag,{-1}}},{ddiag}}[[A]],
7->{{in,{bound,{-1}}},{skel}}[[A]],
8->{{dblDiag,{1}}}
},
If[A===1,{5->{{bound,{-1}}}},{3->{in,{bound,{-1}}}}]
],


("growth_"<>{"1","2"}[[A]]<>"_"<>If[use0,"0",""]<>"3"<>state<>{"1","2"}[[B]])(*//(Print[#];#)&*),
type<>If[A===1,"G","B"]<>If[B===1,"","A"],10000

},
{state,{"d","e","p"}},{A,{1,2}},{B,{1,2}},
{use0,{False,True}}
]),

(* 3e.3p, 3p.A *)
(Join @@  Join @@ Table[
type = {"UOMM","UOPP"}[[state]];
{type,
upMarking=If[use0,If[state==1,uP0,up0],If[state===1,upp,{up1,up2}[[B]]]];
markingIndexList= If[(*B===1*)(*2*)(*!!*)
(*MemberQ[{{2,1},{2,2}},{B,state}]*)B===2,
reflectIndexedList,#&]@

{1->{upMarking,{bound,{1}}},
2->{ddiag},
4->{{{sglDiag,{1}},ddiag}[[state]]},
6->{ddiag},
7->{{in,inp}[[state]],{bound,{1}}},
8->{{dblDiag,{-1}}}
},


"growth_"<>{"3e","3p"}[[state]]<>{"1","2"}[[B]]<>"_"<>If[use0,"0",""]<>{"3p",""}[[state]]<>{"1","2"}[[B]],
type<>"G"<>If[B===1,"","A"],10000

},
{state,{1,2}},{B,{1,2}},
{use0,{False,True}}
]),


(*3d.3e, 3e.3d*)

Join @@ Join @@ Table[
type = {"UOPP","UOMM"}[[state]];
{type,
upMarking=If[use0,up0,up3];
markingIndexList= If[(*B===1*)(*2*)(*!!*)
(*MemberQ[{{1,2},{1,1},{2,e}},{B,state}]*)B===2,reflectIndexedList,#&]@

{1->{upMarking,{bound,{1}}},
2->{ddiag},
4->{{dblDiag,{1}}},
6->{ddiag},
7->{in,{bound,{1}}},
8->{{dblDiag,{-1}}}
},


"growth_"<>{"3d","3e"}[[state]]<>{"1","2"}[[B]]<>"_"<>If[use0,"0",""]<>"3"<>{"e","d"}[[state]]<>{"1","2"}[[B]],
type<>"G"<>If[B===1,"","A"],10000

},
{state,{1,2}},
{B,{1,2}},
{use0,{False,True}}
],

(* 03e.3e , 03d.3d, 03p.3p  *)
Join @@ Join @@ Table[
type = {"UOPP","UOMM","UOMM"}[[state]];
{type,
upMarking=If[use0,If[state===3,uP0, up0],If[state===3,upp, up3]];
markingIndexList= If[(*B===1*)(*2*)(*!!*)
(*MemberQ[{{2,2},{2,1}},{B,state}]*)B===2,reflectIndexedList,#&]@

{1->{upMarking},
2->{ddiag},
(*3->Join[If[state==2,{in},{}],{{bound,{1}}}],
4->{{dblDiag,{-1}}},
5->Join[If[state==1,{in},{}],{{bound,{1}}}],*)
3->Join[If[state==3,{inp},{in}],{{bound,{1}}}],
4->{{dblDiag,{-1}}},
5->{{bound,{1}}},
6->{ddiag},
7->{skel},
8->{{dblDiag,{1}}}
},


"growth_0"<>{"3e","3d","3p"}[[state]]<>{"1","2"}[[B]]<>"_"<>If[use0,"0",""]<>{"3e","3d","3p"}[[state]]<>{"1","2"}[[B]],
type<>"B"<>If[B===2,"","A"],10000

},
{state,{1,2,3}},
{B,{1,2}},
{use0,{False,True}}
],


(*the junctures of growth signals transferring from child to parent skeleton*)
Join @@ Table[bbound={{},{{bound,{1}}},{{bound,{-1}}}}[[index]];
suffix={"","p","m"}[[index]];
{
{"VGG",{6->{diag},8->{diag},7->Join[{up3},bbound],5->{in,{bound,{-1}}},1->{skel,{bound,{1}}},3->{skel}},"VGGup3s"<>suffix,"VGGup3s"},
{"VGG",{6->{diag},8->{diag},7->Join[{upp},bbound],5->{inp,{bound,{-1}}},1->{skel,{bound,{1}}},3->{skel}},"VGGuPp3s"<>suffix,"VGGuP3s"},
{"VGG",{2->{diag},4->{diag},3->Join[{up1},bbound],5->{in,{bound,{1}}},1->{skel,{bound,{-1}}},7->{skel}},"VGGup1s"<>suffix,"VGGup1s"},
{"VBG",{6->{diag},8->{diag},7->Join[{up0},bbound],1->{{bound,{1}}},5->{in,{bound,{-1}}},3->{skel}},"VBGup0s"<>suffix,"VBGup0s"},
{"VBG",{6->{diag},8->{diag},7->Join[{uP0},bbound],1->{{bound,{1}}},5->{inp,{bound,{-1}}},3->{skel}},"VBGuPp0s"<>suffix,"VBGuP0s"},
{"VBG",{2->{diag},4->{diag},3->Join[{up2},bbound],5->{in,{bound,{1}}},1->{{bound,{-1}}},7->{skel}},"VBGup2s"<>suffix,"VBGup2s"}},

{index,3}],


(*the outward tiles, cornered and uncornered, that transmit diagonal signals*) 
(*bound markings cannot ever meet an outward tile, except at a growth center*)

Join @@ Table[{outwardType,markingIndexList={8->{signalType},4->{If[Length[signalType]==2,ReplacePart[signalType,2->-signalType[[2]]],signalType]}},

outwardType<>"diag"<>replaceSignalsWString[signalType],outwardType<>"diag"

},

{outwardType,{"UOPP","UOMM","COPP","COMM"}},
{signalType,{{sglDiag,{1}},{sglDiag,{-1}},{dblDiag,{1}},{dblDiag,{-1}},diag, ddiag}}
],



(* the edge tiles that transmit horizontal signals*)

Join @@ Table[
{crossingType,
{1->{{inp,in,in}[[state]],{bound,{{1,1,-1}[[state]]}}},5->{{inp,in,in}[[state]],{bound,{-{1,1,-1}[[state]]}}}},
crossingType<>{"inp","in","in"}[[state]]<>
{"p","p","m"}[[state]],crossingType<>{"inp","in","in"}[[state]]},
{crossingType,{"CGG","CGpB","CGmB","CBG","CBpB","CBmB","VGG","VGpB","VGmB","VBG","VBpB","VBmB"}},
{state,3}],


Join @@Join @@ Table[
{crossingType,
{1->
Join[{signalType},{{},{{bound,{1}}},{{bound,{-1}}}}[[index]]],
5->Join[{signalType},{{},{{bound,{-1}}},{{bound,{1}}}}[[index]]]},
crossingType<>signalStringReplace[signalType]<>({"","p","m"}[[index]]),crossingType<>If[signalType===skel,"s","up"]

},
{crossingType,{"CGG","CGpB","CGmB","VGG","VGpB","VGmB"}},
{signalType,{uP0,up0,up1,up2,up3,upp,skel}},
{index,3}
],





Join @@ Table[
{crossingType,
{1->{{{bound,{1}}},{{bound,{-1}}}}[[index]],
5->{{{bound,{-1}}},{{bound,{1}}}}[[index]]},
crossingType<>({"bdp","bdm"}[[index]]),crossingType

},
{crossingType,{"CGG","CGpB","CGmB","CBG","CBpB","CBmB","VGG","VGpB","VGmB","VBG","VBpB","VBmB"}},
{index,2}
],




(*the outward tiles at the corners of a growth skeleton*)
(*diags on outside, ddiags on inside, transmitting sglDiags/dblDiags if present*)
(*don't have to worry about bound markings--- any skeleton corner these meet will be a growth center*)

Join@@ Table[{outwardType,
{8->{If[signalType===diag,ddiag,{signalType,{-1}}]},4->{If[signalType===diag,diag,{signalType,{1}}]},1->{skel},7->{skel},2->{diag},6->{diag}},
outwardType<>"d"<>Switch[signalType,sglDiag,"s",dblDiag,"b",diag,"D"]<>"d",
outwardType<>"ddd"},
{outwardType,{"UOPP","UOMM"}},
{signalType,{sglDiag,dblDiag,diag}}],



(* where skeleton markings might meet, either another skeleton, or an up signal*)

Join @@Table[
{"VGG",
markedIndex={
{1->{signal},3->{skel},5->{signal},7->{skel}},
{1->{signal,{bound,{(*0,*)-1}}},3->{skel},5->{signal,{bound,{(*0,*)1}}},7->{skel}},
{1->{signal,{bound,{(*0,*)-1}}},3->{skel,{bound,{(*0,*)1}}},5->{signal,{bound,{(*0,*)1}}},7->{skel}},
{1->{signal,{bound,{(*0,*)-1}}},3->{skel,{bound,{(*0,*)-1}}},5->{signal,{bound,{(*0,*)1}}},7->{skel}},
{1->{signal,{bound,{(*0,*)1}}},3->{skel},5->{signal,{bound,{(*0,*)-1}}},7->{skel}},
{1->{signal,{bound,{(*0,*)1}}},3->{skel},5->{signal,{bound,{(*0,*)-1}}},7->{skel,{bound,{(*0,*)1}}}},
{1->{signal,{bound,{(*0,*)1}}},3->{skel},5->{signal,{bound,{(*0,*)-1}}},7->{skel,{bound,{(*0,*)-1}}}}
}[[index]],
"VGG"<>(StringJoin @@(signalStringReplace[#]&/@{signal,skel}))<>ToString[index],"VGG"<>If[
signal===skel,"kk","upk"]
},
{signal,{uP0,up0,up1,up2,up3,upp,skel}},
{index,7}],

{{"VBG",{3->{skel}(*,5->{skel}*),7->{skel}},"VBGk","VBGk"}},



(*And the many miscellaneous ways that  diagonal skeleton markings can terminate at a VV tile*)


Join@@Join @@ Table[{crossingType,Join[
{{2,6}[[index]]->{diag},{4,8}[[index]]->{diag},
1->{{bound,{(*0,*){-1,1}[[index]]}}},5->{{bound,{(*0,*){1,-1}[[index]]}}}},
 {{},{{3,7}[[index]]->{{bound,{(*0,*)1}}}},{{3,7}[[index]]->{{bound,{(*0,*)-1}}}}}[[boundIndex]]
],
crossingType<>"_SS"<>ToString[index]<>ToString[boundIndex],crossingType},
{crossingType,{"VGG","VGpB","VGmB","VBG","VBpB","VBmB"}},
{index,2},
{boundIndex,3}],


(*Unknown if all necessary -- can filter by unmatched markings *)
Join@@Join@@Join @@ Table[{crossingType,Join[
{{2,6}[[index]]->{diag},{4,8}[[index]]->{diag},
1->{inning,{bound,{{-1,1}[[index]]}}},5->{inning,{bound,{{1,-1}[[index]]}}}},
 {{},{{3,7}[[index]]->{{bound,{1}}}},{{3,7}[[index]]->{{bound,{-1}}}}}[[boundIndex]]
],
crossingType<>ToString[inning]<>"_SS"<>ToString[index]<>ToString[boundIndex],crossingType},
{crossingType,{"VGG","VGpB","VGmB","VBG","VBpB","VBmB"}},
{index,2},
{inning,{in,inp}},
{boundIndex,3}],

Join@@Join @@ Table[{crossingType,Join[
{{2,6}[[index]]->{diag},{4,8}[[index]]->{diag},
1->{{bound,{{-1,1}[[index]]}}},5->{{bound,{{1,-1}[[index]]}}}},
 {{3->{skel},7->{skel}},{{3,7}[[index]]->{skel,{bound,{1}}},{7,3}[[index]]->{skel}},{{3,7}[[index]]->{skel,{bound,{-1}}},{7,3}[[index]]->{skel}}}[[boundIndex]]
],
crossingType<>"inn_SS"<>ToString[index]<>ToString[boundIndex],crossingType},
{crossingType,{"VGG","VGpB","VGmB","VBG","VBpB","VBmB"}},
{index,2},
{boundIndex,3}],

Join @@Join @@Join @@ Table[{crossingType,Join[
{1->{signalType,{bound,{(*0,*){-1,1}[[index]]}}},5->{signalType,{bound,{(*0,*){1,-1}[[index]]}}},{2,6}[[index]]->{diag},{4,8}[[index]]->{diag}},
{
{},
{{3,7}[[index]]->{{bound,{(*0,*)1}}}},
{{3,7}[[index]]->{{bound,{(*0,*)-1}}}},
{3->{skel},7->{skel}},
{{3,7}[[index]]->{skel,{bound,{(*0,*)1}}},{7,3}[[index]]->{skel}},
{{3,7}[[index]]->{skel,{bound,{(*0,*)-1}}},{7,3}[[index]]->{skel}}
}[[boundIndex]]
],
crossingType<>signalStringReplace[signalType]<>"_SS"<>ToString[index]<>ToString[boundIndex],crossingType<>If[signalType===skel,"s","up"]},
{crossingType,{"VGG","VGpB","VGmB"}},{signalType,{uP0,up0,up1,up2,up3,upp,skel}},
{index,2},
{boundIndex,6}],

{
{"COPP",{2->{diag},4->{diag},6->{diag},8->{ddiag}},"SeedP","COPP"},
{"COMM",{2->{diag},4->{{sglDiag,{1}}},6->{diag},8->{{sglDiag,{-1}}}},"SeedM","COMM"}


}]/.{dskel->diag};

wholeBunchaNewTiles=wholeBunchaNewTiles/.{dskel->diag};

(*wholeBunchaNewTiles=Select[
wholeBunchaNewTiles,
Length[Position[#,dblDiag]]==0&];*)

AddTilesToTypeList[#,True]&@
wholeBunchaNewTiles;

signal based matching rules

(*Each tile may match with another if and only if the lists of markings on the corresponding edges are compatible, and if the tiles are of the right types --- the tiles CO must form a lattice, with CR's between them, in the correct orientation, and alternating with UO/VV's in a checkerboard pattern. 

The matching rules are ultimately encoded in the precomputed lists of 

possibleEdgeNeighbors

This must be initialized each time tiles are newly defined, by 

resetPossibleEdgeNeighbors

*)

(*On an edge, a marking is a list of signals of the form

{ Name or {Name,parityList},...

where partityList is 
{}
{direction}
{direction,orientation}

*)

(*Markings match if and only if the list of names is the same, and the parities of each sum to a (possibly empty) well-defined zero-vector*)

TileMarkingsMatchQ=
((Length[#1]===Length[#2]&&
(And@@ (( 
((Length[#[[1]]]===0||Length[#[[1]]]===1) &&  #[[1]]===#[[2]])||
( Length[#[[1]]]>1&&Length[#[[2]]]===Length[#[[1]]]&&#[[1,1]]===#[[2,1]] &&
Length[#[[1,2]]]===Length[#[[2,2]]] &&
((Length[#[[1,2]]]===1 && #[[1,2]]+#[[2,2]]==={0})||
(And@@((#===0)&/@(#[[1,2]]+#[[2,2]]))))
 ))&/@Thread[List[#1,#2]]))))&;

(*These markings are clockwise from N*)

ResetTileMarkings:=(

Clear[TileMarkings];

TileMarkings[{type_/;
MemberQ[{CO,UO},type[[1]]],0}]:=
TileMarkings[{type,0}]=Module[{grM,bbM},
grM=Switch[type[[1]],CO,Ggg,UO,Gg];
bbM=Switch[type[[1]],CO,Bbb,UO,Bb];
(Sort/@
{
Join[{{grM,{1,1}}},#[[1]]],
Join[{{Rr,{-1,-1}}},#[[2]]],
Join[{{bbM,{1,-1}}},#[[3]]],
Join[{{Rr,Switch[type[[2]],PP,{-1,-1},MM,{1,1}]}},#[[4]]],
Join[{{bbM,{1,1}}},#[[5]]],
Join[{{Rr,{-1,1}}},#[[6]]],
Join[{{grM,{1,-1}}},#[[7]]],
Join[{{Rr,Switch[type[[2]],PP,{1,1},MM,{-1,-1}]}},#[[8]]]})&@If[type[[3]]=={},Table[{},{8}],type[[3]]]];

TileMarkings[{type_/;
MemberQ[{CR,VV},type[[1]]],0}]:=
TileMarkings[{type,0}]=With[
{outM=Switch[type[[1]],CR,0,VV,1]},
(Sort/@
{
Join[{{type[[2]],{1,1}}},#[[1]]],
Join[{{Rr,{outM,1}}},#[[2]]],
Join[{{type[[3]],{-1,-type[[4]]}}},#[[3]]],
Join[{{Rr,{outM,-1}}},#[[4]]],
Join[{{type[[2]],{-1,-1}}},#[[5]]],
Join[{{Rr,{outM,1}}},#[[6]]],
Join[{{type[[3]],{-1,type[[4]]}}},#[[7]]],
Join[{{Rr,{outM,-1}}},#[[8]]]
})&@If[type[[5]]=={},Table[{},{8}],type[[5]]]];


ReflectMarking = If[Length[#]==2,If[Length[#[[2]]]==2,ReplacePart[#,{2,2}->-#[[2,2]]],#],#]&/@#&;


TileMarkings[{type_,1}]:=TileMarkings[{type,1}]=
ReflectMarking/@
RotateRight[Reverse[TileMarkings[{type,0}]]];

TileMarkings[{type_,6}]:=TileMarkings[{type,6}]=RotateRight[TileMarkings[{type,0}],2];

TileMarkings[{type_,3}]:=TileMarkings[{type,3}]=RotateRight[TileMarkings[{type,0}],4];

TileMarkings[{type_,5}]:=TileMarkings[{type,5}]=RotateRight[TileMarkings[{type,0}],6];

TileMarkings[{type_,7}]:=TileMarkings[{type,7}]=RotateRight[TileMarkings[{type,1}],2];

TileMarkings[{type_,2}]:=TileMarkings[{type,2}]=RotateRight[TileMarkings[{type,1}],4];

TileMarkings[{type_,4}]:=TileMarkings[{type,4}]=RotateRight[TileMarkings[{type,1}],6];


TileMarkings[{type_,{pos_,or_}}]:=TileMarkings[{type,or}];
);

ResetTileMarkings;

ComplementaryMarking[markingList_]:=Sort[(If[
Length[#]===0 || Length[#]===1,#,
{#[[1]],-#[[2]]}])&/@markingList]

resetPossibleNeighbors:=Module[{marking},


markingList=Union@@ (Union@@({TileMarkings[{#,0}],TileMarkings[{#,1}]})&/@TILETYPELIST);

Clear[TilesWithMarkingsInDirection];

Table[
TilesWithMarkingsInDirection[marking,direction]={},
{marking,markingList},{direction,DIRECTIONS}];

Table[

marking=TileMarkings[{tileType,orientation}];

Table[
TilesWithMarkingsInDirection[marking[[directionIndex]],DIRECTIONS[[directionIndex]]]=
Append[
TilesWithMarkingsInDirection[marking[[directionIndex]],DIRECTIONS[[directionIndex]]],{tileType,orientation}],
{directionIndex,8}],


{tileType,TILETYPELIST},{orientation,0,7}];


Clear[PossibleNeighbors];

PossibleNeighbors[{tileType_,orientation_},direction_]:=PossibleNeighbors[{tileType,orientation},direction]=
TilesWithMarkingsInDirection[ComplementaryMarking[TileMarkings[{tileType,orientation}][[directionToIndex[direction]]]],
-direction]

];

resetPossibleNeighbors;

(*In case other kinds of matching rules are tested*)

possibleNeighbors[type_,dir_]:=PossibleNeighbors[type,dir];

eliminate some tiles and markings

reducedTILETYPELIST=TILETYPELIST[[#]]&@
(Complement[Table[i,{i,Length[TILETYPELIST]}],#]&@

(Select[TILETYPELIST,
!(Intersection[markingList[[



((Position[markingList,#][[1,1]])&/@
Select[markingList,!(MemberQ[markingList,ComplementaryMarking[#]])&])

]],
TileMarkings[{#,0}]]=={})&]//Position[TILETYPELIST,#][[1,1]]&/@#&));

reducedTileMarkings=Union@@ (Union@@({TileMarkings[{#,0}],TileMarkings[{#,1}]})&/@reducedTILETYPELIST);

utilities

a list of all the names of the tiles

(TileFullName/@TILETYPELIST)//Sort

drawing any tile by name

IMAGESIZEFORDRAWINGS=144;ReloadDrawings;

ShowAPatch[{{TileFromFullName["CBG"],{{0,0}(*position*),2(*orientation*)}}}]

Testing the set up:

more

basePatch[name_]:=Module[{tile,mp,pm,dd},
tile =( TileFromFullName@name)/. (*eliminate these, inbound markings*)((x_/;(MemberQ[{ddiag,in,{bound,{-1}},{bound,{1}},{dblDiag,{-1}},{dblDiag,{1}},{sglDiag,{-1}}},x]))->Sequence[]);
pm=tile[[2]];
mp=Complement[{PP,MM},{pm}][[1]];

dd=Position[tile,x_/;MemberQ[{up0,up1,up2,up3},x]][[1,2]]; (*1 or 7*)


{
{( TileFromFullName@name),{{0,0},0}},

{{CR,Gg,Ggg,1,{If[#=={},{skel},#]&@ tile[[-1,1]],{},{},{},If[#=={},{skel},#]&@ tile[[-1,1]],{},{},{}}},{{0,1},0}},

{{CR,Gg,Ggg,1,{If[#=={},{skel},#]&@tile[[-1,7]],{},{},{},If[#=={},{skel},#]&@tile[[-1,7]],{},{},{}}},{{-1,0},4}},

{{CR,Bb,Ggg,1,{tile[[-1,3]],{},{},{},tile[[-1,3]],{},{},{}}},{{1,0},7}},

{{CR,Bb,Ggg,1,{tile[[-1,5]],{},{},{},tile[[-1,5]],{},{},{}}},{{0,-1},3}},

{{CO,pm,{{},{diag},{},If[tile[[-1,4]]==={},{diag},tile[[-1,4]]],{},{diag},{},ComplementaryMarking @ If[tile[[-1,4]]==={},{ddiag},tile[[-1,4]]]}},{{1,-1},0}},


{{CO,PP,
{{},{diag},{},If[tile[[-1,6]]==={},{diag},tile[[-1,6]]],
{},{diag},{},ComplementaryMarking @ If[tile[[-1,6]]==={},{ddiag},tile[[-1,6]]]}},{{-1,-1},1}},



{{CO,PP,{{},{diag},{},If[#=={},{diag},#]&@tile[[-1,2]],{},{diag},{},If[#=={},{ddiag},#]&@ComplementaryMarking@tile[[-1,2]]}},{{1,1},5}},



{{CO,mp,
{{},{diag},{},If[#=={},{diag},#]&@tile[[-1,8]],{},{diag},{},ComplementaryMarking@tile[[-1,8]]}},{{-1,1},3}}}]

seedPatch=basePatch["growth_2_1"];

seedPatch={TileFromFullName[#[[1]]],#[[2]]}&/@{{"growth_2_1",{{0,0},0}},{"CGG1",{{0,1},0}},{"CGGk",{{-1,0},4}},{"CBG",{{1,0},7}},{"CBG",{{0,-1},3}},{"SeedP",{{1,-1},0}},{"SeedP",{{-1,-1},1}},{"SeedP",{{1,1},5}},{"SeedM",{{-1,1},3}}};

ShowAPatch[seedPatch]

resetGrowth;


(*this is a hand built set of directions for each stage of the growth*)
GLOBALRESTRICTIONSEQUENCE={"growth_1_3d1","growth_3d1_3e1","growth_3e1_3p1","growth_3p1_1","growth_1_2", "growth_2_3e2","growth_3e2_3p2","growth_3p2_2","growth_2_1"};
FTAMRESTRICTIONFUNCTION=RESTRICTIONTOGLOBALSEQUENCE;

initialConfig =configs[0];


goOutTo[20];


configs[lastStop]//ShowAConfigWVerts

goOutTo[100];


configs[lastStop]//ShowAConfigWVerts

goOutTo[150];


configs[lastStop]//ShowAConfigWVerts

goOutTo[600];


configs[lastStop]//ShowAConfigWVerts