public ITiling <GameObject> BuildTiling(Portal[] prevPortals)
        {
            Tile[] layout = new Tile[width * height];
            List <Tuple <Direction, int> > edgeConstraints = new List <Tuple <Direction, int> >();

            #region maze generation

            for (int i = 0; i < height; i++)
            {
                for (int j = 0; j < width; j++)
                {
                    edgeConstraints.Clear();
                    if (i == 0)
                    {
                        Tuple <Direction, int> tp = new Tuple <Direction, int>(Direction.S, 0);
                        edgeConstraints.Add(tp);
                    }
                    if (j == 0)
                    {
                        Tuple <Direction, int> tp = new Tuple <Direction, int>(Direction.W, 0);
                        edgeConstraints.Add(tp);
                    }
                    if (i == height - 1)
                    {
                        Tuple <Direction, int> tp = new Tuple <Direction, int>(Direction.N, 0);
                        edgeConstraints.Add(tp);
                    }
                    if (j == width - 1)
                    {
                        Tuple <Direction, int> tp = new Tuple <Direction, int>(Direction.E, 0);
                        edgeConstraints.Add(tp);
                    }
                    if (i != 0)
                    {
                        Tile bottom = (Tile)layout[(i - 1) * width + j];
                        Tuple <Direction, int> tp = new Tuple <Direction, int>(Direction.S, bottom.GetEdgeColor(Direction.N));
                        edgeConstraints.Add(tp);
                    }
                    if (j != 0)
                    {
                        Tile left = (Tile)layout[i * width + j - 1];
                        Tuple <Direction, int> tp = new Tuple <Direction, int>(Direction.W, left.GetEdgeColor(Direction.E));
                        edgeConstraints.Add(tp);
                    }

                    TileSet truchetTileSet             = (TileSet)tileSet;
                    IEnumerable <PriorityTile> matched = truchetTileSet.MatchingTiles(edgeConstraints) as IEnumerable <PriorityTile>;
                    int  sum          = matched.Sum(x => x.priority);
                    int  idx          = UnityEngine.Random.Range(0, sum);
                    Tile selectedTile = null;
                    foreach (PriorityTile priorityTile in matched)
                    {
                        idx -= priorityTile.priority;
                        if (idx <= 0)
                        {
                            selectedTile = priorityTile.tile;
                            break;
                        }
                    }

                    if (selectedTile != null)
                    {
                        layout[i * width + j] = selectedTile;
                    }
                    else
                    {
                        throw new Exception("No suitable tile found");
                    }
                }
            }

            #endregion

            #region Up Portals

            int[] upIndex = new int[3];
            int   entry   = -1;
            if (prevPortals != null && prevPortals[0] != null)
            {
                int portalCount = prevPortals.Count(p => p != null);
                for (int i = 0; i < portalCount; i++)
                {
                    int portalY = UnityEngine.Random.Range(0, height);
                    int portalX = UnityEngine.Random.Range(0, width);

                    while (upIndex.Contains(portalY * width + portalX + 1) || !layout[portalY * width + portalX].hasEdgeColor(1))
                    {
                        portalY = UnityEngine.Random.Range(0, height);
                        portalX = UnityEngine.Random.Range(0, width);
                    }
                    upIndex[i] = portalY * width + portalX + 1;
                }
            }
            else
            {
                int portalY = UnityEngine.Random.Range(0, height);
                int portalX = UnityEngine.Random.Range(0, width);

                while (!layout[portalY * width + portalX].hasEdgeColor(1))
                {
                    portalY = UnityEngine.Random.Range(0, height);
                    portalX = UnityEngine.Random.Range(0, width);
                }
                entry = portalY * width + portalX + 1;
            }

            List <PriorityTile> tiling = new List <PriorityTile>();
            for (int i = 0; i < width * height; i++)
            {
                if (upIndex.Contains(i + 1))
                {
                    tiling.Add(new PriorityTile(layout[i], PortalType.Up));
                }
                else if (entry != -1 && entry - 1 == i)
                {
                    tiling.Add(new PriorityTile(layout[i], PortalType.Enter));
                }
                else
                {
                    tiling.Add(new PriorityTile(layout[i], PortalType.None));
                }
            }

            #endregion

            #region Eliminate disconnects

            List <int> connectedTiles = new List <int>();

            for (int i = 0; i < layout.Count(); i++)
            {
                if (!connectedTiles.Contains(i))
                {
                    exploredTiles = new List <int>();
                    DetermineIfConnected(tiling, i, null, ref connectedTiles);
                }
            }

            #endregion

            #region Down portals

            int[] downIndex = new int[3];

            int newPortalCount;

            if (tiling.Count(t => t.tile != FullTile) < 3)
            {
                newPortalCount = 1;
            }
            else
            {
                newPortalCount = UnityEngine.Random.Range(1, 3);
            }

            for (int i = 0; i < newPortalCount; i++)
            {
                List <int> indexes = tiling.Where(t => t.tile != FullTile).Select(x => tiling.IndexOf(x)).ToList();

                int index = indexes[UnityEngine.Random.Range(0, indexes.Count)];

                while (upIndex.Contains(index + 1) || downIndex.Contains(index + 1) || tiling[index].portalType == PortalType.Enter || !tiling[index].tile.hasEdgeColor(1))
                {
                    index = indexes[UnityEngine.Random.Range(0, indexes.Count)];
                }

                downIndex[i] = index + 1;
            }

            for (int i = 0; i < 3; i++)
            {
                if (downIndex[i] != 0)
                {
                    tiling[downIndex[i] - 1].portalType = PortalType.Down;
                }
            }

            #endregion

            Tiling truchetFinalTiling = new Tiling(tiling);
            return(truchetFinalTiling);
        }
        public ITileSet <GameObject> Build()
        {
            TileSet tileSet = new TileSet(tiles);

            return(tileSet);
        }
 public TilingBuilder(int width, int height, TileSet tileSet)
 {
     this.width   = width;
     this.height  = height;
     this.tileSet = tileSet;
 }