public virtual void Init(TilePropagator propagator) { changeTracker = propagator.CreateChangeTracker(); var p = propagator; var topology = propagator.Topology; // Ban any tiles which don't have a symmetry foreach (var i in topology.GetIndices()) { if (TryMapIndex(p, i, out var i2)) { topology.GetCoord(i, out var x, out var y, out var z); propagator.Select(x, y, z, propagator.TileModel.Tiles .Where(tile => TryMapTile(tile, out var _))); } } // Ban tiles that interact badly with their own symmetry foreach (var i in topology.GetIndices()) { if (TryMapIndex(p, i, out var i2)) { topology.GetCoord(i, out var x, out var y, out var z); if (i2 == i) { // index maps to itself, so only allow tiles that map to themselves var allowedTiles = propagator.TileModel.Tiles .Where(tile => TryMapTile(tile, out var tile2) && tile == tile2); propagator.Select(x, y, z, allowedTiles); continue; } // TODO: Support overlapped model? if (propagator.TileModel is AdjacentModel adjacentModel) { for (var d = 0; d < topology.DirectionsCount; d++) { if (topology.TryMove(i, (Direction)d, out var dest) && dest == i2) { // index maps adjacent to itself, so only allow tiles that can be placed adjacent to themselves var allowedTiles = propagator.TileModel.Tiles .Where(tile => TryMapTile(tile, out var tile2) && adjacentModel.IsAdjacent(tile, tile2, (Direction)d)) .ToList(); propagator.Select(x, y, z, allowedTiles); continue; } } } if (propagator.TileModel is GraphAdjacentModel graphAdjacentModel) { var sentinel = new Tile(new object()); for (var d = 0; d < topology.DirectionsCount; d++) { if (topology.TryMove(i, (Direction)d, out var dest, out var _, out var edgeLabel) && dest == i2) { // index maps adjacent to itself, so only allow tiles that can be placed adjacent to themselves var allowedTiles = propagator.TileModel.Tiles .Where(tile => TryMapTile(tile, out var tile2) && graphAdjacentModel.IsAdjacent(tile, tile2, edgeLabel)); propagator.Select(x, y, z, allowedTiles); continue; } } } topology.GetCoord(i2, out var x2, out var y2, out var z2); } } }