Beispiel #1
0
 static void AddAccessible(List <Point> walls, MazeTile tile, Point accesible)
 {
     if (!walls.Contains(accesible))
     {
         tile.AccessibleTiles.Add(accesible);
     }
 }
Beispiel #2
0
 void CalculateAccesiblePoints(MazeTile mazeTile, string[] currentData, string[] eastData, string[] southdata)
 {
     /* Accessible tiles can be:
      * north - if currentData doesn't contain "north"
      * west - if currentData doesn't contain "west"
      * east - if data + (1,0) doesn't contain "west"
      * south - if data + (0,width) doesn't contain "north"
      *
      */
     if (!currentData.Contains("north"))
     {
         mazeTile.AccessibleTiles.Add(new Point(mazeTile.Position.X, mazeTile.Position.Y - 1));
     }
     if (!currentData.Contains("west"))
     {
         mazeTile.AccessibleTiles.Add(new Point(mazeTile.Position.X - 1, mazeTile.Position.Y));
     }
     if (!southdata.Contains("north"))
     {
         mazeTile.AccessibleTiles.Add(new Point(mazeTile.Position.X, mazeTile.Position.Y + 1));
     }
     if (!eastData.Contains("west"))
     {
         mazeTile.AccessibleTiles.Add(new Point(mazeTile.Position.X + 1, mazeTile.Position.Y));
     }
 }
Beispiel #3
0
 public void SetNeighbors(MazeTile up, MazeTile left, MazeTile down, MazeTile right)
 {
     UpNeighbor    = up;
     LeftNeighbor  = left;
     DownNeighbor  = down;
     RightNeighbor = right;
 }
Beispiel #4
0
        MazeTile CreateTile()
        {
            MazeTile tile = Instantiate(mazeTile) as MazeTile;

            tile.transform.parent = transform;
            return(mazeTile);
        }
Beispiel #5
0
        /** <summary> Loads the specified maze into the editor. </summary> */
        public void LoadMaze(TrackDesign maze)
        {
            if (maze.TrackType == TrackTypes.HedgeMaze)
            {
                for (int x = 0; x < this.blocks.GetLength(0); x++)
                {
                    for (int y = 0; y < this.blocks.GetLength(1); y++)
                    {
                        this.blocks[x, y] = new MazeBlock();
                    }
                }

                Point offset = Point.Empty;
                for (int i = 0; i < maze.MazeTiles.Count; i++)
                {
                    MazeTile tile = maze.MazeTiles[i];
                    if (tile.X < 0 && -tile.X > offset.X)
                    {
                        offset.X = -tile.X;
                    }
                    if (tile.Y < 0 && -tile.Y > offset.Y)
                    {
                        offset.Y = -tile.Y;
                    }
                }

                for (int i = 0; i < maze.MazeTiles.Count; i++)
                {
                    MazeTile tile = maze.MazeTiles[i];
                    this.blocks[tile.X + offset.X, tile.Y + offset.Y] = new MazeBlock(tile.Walls, false);
                }
                this.wallStyle = (int)maze.TrackSupportColors[0];
                this.Invalidate();
            }
        }
Beispiel #6
0
        /// <summary>
        /// Runs the example
        /// </summary>
        public static void Run()
        {
            var tiles = new MazeTile[10, 10];

            tiles[0, 0] = MazeTile.Agent;
            tiles[2, 4] = MazeTile.Wall;
            tiles[3, 4] = MazeTile.Wall;
            tiles[4, 4] = MazeTile.Wall;
            tiles[5, 4] = MazeTile.Wall;
            tiles[9, 9] = MazeTile.Goal;

            var environment = new MazeEnvironment(new Configuration(200), tiles);
            var agent       = new MazeAgent();

            environment.AddAgent(agent);
            environment.Initialize();

            for (int episode = 0; episode < environment.Config.MaxEpisodes; episode++)
            {
                environment.Reset(episode);

                for (int step = 0; step < 1000; step++)
                {
                    if (environment.Update(episode))
                    {
                        break;
                    }
                }

                Console.WriteLine(string.Format("Episode: {0} - {1} steps.", episode, agent.NumSteps));
            }

            PrintPath(environment, agent);
            Console.ReadLine();
        }
    private void HandlePlayerTileMarkerEnds(MazeTile tile)
    {
        foreach (KeyValuePair <ObjectDirection, Tile> item in tile.Neighbours)
        {
            MazeTile neighbour = item.Value as MazeTile;

            if (!neighbour)
            {
                continue;
            }

            MazeTilePath mazeTilePath = (MazeTilePath)neighbour.GetBackgrounds().FirstOrDefault(background => background is MazeTilePath);
            if (mazeTilePath == null)
            {
                continue;
            }

            if (neighbour.PlayerMark != null && neighbour.PlayerMark.Owner != PlayerMarkOwner.None)
            {
                continue;
            }

            TileConnectionScoreInfo neighbourConnectionScoreInfo = NeighbourTileCalculator.MapNeighbourPlayerMarkEndsOfTile(neighbour);
            neighbour.PlayerMarkEndsRenderer.sprite = MazeSpriteManager.Instance.PlayerTileMarkerEdge[neighbourConnectionScoreInfo.SpriteNumber - 1];
        }
    }
Beispiel #8
0
    public static TileConnectionScoreInfo MapNeighbourPlayerMarkEndsOfTile(MazeTile tile)
    {
        bool hasMarkRight = false;
        bool hasMarkDown  = false;
        bool hasMarkLeft  = false;
        bool hasMarkUp    = false;

        foreach (KeyValuePair <ObjectDirection, Tile> item in tile.Neighbours)
        {
            MazeTile neighbour = item.Value as MazeTile;
            if (neighbour == null || neighbour.PlayerMark == null || neighbour.PlayerMark.Owner == PlayerMarkOwner.None)
            {
                continue;
            }

            if (item.Key == ObjectDirection.Right)
            {
                hasMarkRight = true;
            }
            else if (item.Key == ObjectDirection.Down)
            {
                hasMarkDown = true;
            }
            else if (item.Key == ObjectDirection.Left)
            {
                hasMarkLeft = true;
            }
            else if (item.Key == ObjectDirection.Up)
            {
                hasMarkUp = true;
            }
        }
        return(Calculate16TileMapConnectionScore(hasMarkRight, hasMarkDown, hasMarkLeft, hasMarkUp));
    }
Beispiel #9
0
 private void Fill(MazeTile tile)
 {
     for (int i = 0; i < this.Width * this.Height; i++)
     {
         this.cells[i] = tile;
     }
 }
Beispiel #10
0
    /// <summary>
    /// Searches for a pellet object in the player's positions and consumes it
    /// </summary>
    private void ConsumePellet()
    {
        var actualTile = GetPelletAtLocation(transform.localPosition);

        if (_currentMazeTile != actualTile && actualTile != null)
        {
            _currentMazeTile = actualTile;
            _currentMazeTile.OnPlayerInteract.Invoke();
        }
    }
    private void HandleSpawnpointMarkability()
    {
        if (GameManager.Instance.CharacterManager.GetPlayerCount() < 2)
        {
            MazeTile spawnpoint1Tile = Level.PlayerCharacterSpawnpoints[PlayerNumber.Player1].Tile as MazeTile;
            spawnpoint1Tile.TryMakeMarkable(false);

            MazeTile spawnpoint2Tile = Level.PlayerCharacterSpawnpoints[PlayerNumber.Player2].Tile as MazeTile;
            spawnpoint2Tile.TryMakeMarkable(true);
        }
    }
    private void AddTileAreas(SerialisableTile serialisableTile, MazeTile tile)
    {
        for (int i = 0; i < serialisableTile.TileAreaIds?.Count; i++)
        {
            string tileAreaId = serialisableTile.TileAreaIds[i];

            if (TileAreas.TryGetValue(tileAreaId, out TileArea tileArea))
            {
                tile.AddTileArea(tileArea);
            }
        }
    }
Beispiel #13
0
            public AnalyzerStatus(MazeTile mazeTile, AnalyzerStatus analyzerStatus = null)
            {
                MazeTile = mazeTile;

                if (analyzerStatus is null)
                {
                    return;
                }

                Steps        = analyzerStatus.Steps + 1;
                PreviousStep = analyzerStatus;
            }
Beispiel #14
0
        public static Maze CreateMaze(int width, int height, int difficulty, Point ponyPosition, Point endPoint, Point monsterPosition = null, List <Point> walls = null)
        {
            Maze maze = new Maze
            {
                MazeId     = Guid.NewGuid(),
                Width      = width,
                Height     = height,
                Difficulty = difficulty,
                Tiles      = new MazeTile[width, height],
                Pony       = new Pony(ponyPosition),
                EndPoint   = endPoint,
                Domokun    = new Monster(monsterPosition ?? OUT_OF_BOUNDS)
            };

            if (walls is null)
            {
                walls = new List <Point>();
            }

            for (int row = 0; row < maze.Height; row++)
            {
                for (int column = 0; column < maze.Width; column++)
                {
                    MazeTile tile = new MazeTile(column, row);
                    maze.Tiles[column, row] = tile;

                    if (tile.Position.X != 0)
                    {
                        Point accesible = new Point(tile.Position.X - 1, tile.Position.Y);
                        AddAccessible(walls, tile, accesible);
                    }
                    if (tile.Position.Y != 0)
                    {
                        Point accesible = new Point(tile.Position.X, tile.Position.Y - 1);
                        AddAccessible(walls, tile, accesible);
                    }
                    if (tile.Position.X != maze.Width - 1)
                    {
                        Point accesible = new Point(tile.Position.X + 1, tile.Position.Y);
                        AddAccessible(walls, tile, accesible);
                    }
                    if (tile.Position.Y != maze.Height - 1)
                    {
                        Point accesible = new Point(tile.Position.X, tile.Position.Y + 1);
                        AddAccessible(walls, tile, accesible);
                    }
                }
            }
            return(maze);
        }
 private void HandlePlayerMarkerSprite(MazeTile tile, PlayerNumber playerNumber, PlayerMark playerMark)
 {
     if (playerNumber == PlayerNumber.Player1)
     {
         playerMark.SetOwner(PlayerMarkOwner.Player1);
         tile.PlayerMarkRenderer.sprite = MazeSpriteManager.Instance.Player1TileMarker[playerMark.ConnectionScore - 1];
         tile.PlayerMark = playerMark;
     }
     else
     {
         playerMark.SetOwner(PlayerMarkOwner.Player2);
         tile.PlayerMarkRenderer.sprite = MazeSpriteManager.Instance.Player2TileMarker[playerMark.ConnectionScore - 1];
         tile.PlayerMark = playerMark;
     }
 }
Beispiel #16
0
        private void CreateItem(MazeTile tile, int itemId)
        {
            var itemObj = Instantiate(
                ItemPrefabs[itemId],
                tile.transform.position,
                Quaternion.identity,
                maze.transform);


            var item = itemObj.GetComponent <Item>();

            tile.currentItem = item;
            item.CurrentTile = tile;
            itemManager.UnassignedItems.Add(item);
        }
Beispiel #17
0
    private void OnTriggerEnter(Collider other)
    {
        //Debug.Log("triggered");
        MazeTile mt = other.GetComponent <MazeTile>();

        if (mt)
        {
            if (!mt.discovered || !vision[mt.coord])
            {
                if (!VisTest(mt, -1))
                {
                    pending.Add(mt);
                }
            }
        }
    }
Beispiel #18
0
        public double FilledRatio()
        {
            int countFilled = 0;

            for (int x = 0; x < this.Width; x++)
            {
                for (int y = 0; y < this.Height; y++)
                {
                    MazeTile tile = this.Get(x, y);
                    if (tile == MazeTile.Wall)
                    {
                        countFilled++;
                    }
                }
            }
            return((double)countFilled / (Width * Height));
        }
Beispiel #19
0
    float TileScorer(MazeTile mt, Map2d map)
    {
        int   neighborFloor = -1;// CountTileNeighbors(mt.coord, _allDirs, c => map[c].letter == '#');//-1;
        Coord msize = map.GetSize();
        Coord min = -Coord.One, max = Coord.One;

        Coord.ForEachInclusive(min, max, off => {
            Coord c = mt.coord + off;
            if (c.IsWithin(msize) && map[c].letter == ' ')
            {
                ++neighborFloor;
            }
        });
        int   maxDist        = (msize.row + msize.col) / 2;
        float distFromCenter = Mathf.Abs((msize.row - 1) / 2f - mt.coord.row) + Mathf.Abs((msize.col - 1) / 2f - mt.coord.col);

        return(neighborFloor + distFromCenter / maxDist);
    }
Beispiel #20
0
        public void InstantiateMazeTiles(Grid grid, bool colorByDistance)
        {
            for (int i = _liveMazeTiles.Count - 1; i >= 0; --i)
            {
                Destroy(_liveMazeTiles[i].gameObject);
            }

            _liveMazeTiles.Clear();
            //var djikstraDistances = Maze.CalculateDistancesFromRoot(grid, grid.Cells[0]);
            //var path = Maze.CalculateLongestPath(grid);
            //var path = Maze.CalculatePath(grid, grid.Cells[0], grid.Cells[grid.Cells.Length - 1]);

            var middleCell  = grid.GetCell(grid.Columns / 2, grid.Rows / 2);
            var distances   = Maze.CalculateDistancesFromRoot(grid, middleCell);
            var maxDistance = distances.Values.Max();

            foreach (var cell in grid.Cells)
            {
                if (cell == null)
                {
                    continue;
                }

                MazeTile tile     = GetTilePrefab(cell);
                Vector3  position = new Vector3(cell.Column * 2, 0, cell.Row * 2);
                MazeTile mazeTile = Instantiate(tile, position, tile.transform.rotation);
                _liveMazeTiles.Add(mazeTile);

                if (colorByDistance)
                {
                    var   tileMaterialPropertyBlock = new MaterialPropertyBlock();
                    var   distance = distances[cell];
                    float h, s, v;
                    Color.RGBToHSV(_mazeColor, out h, out s, out v);
                    s = 1 - ((maxDistance - distance) / (float)maxDistance);

                    tileMaterialPropertyBlock.SetColor("_Color", Color.HSVToRGB(h, s, v));

                    var tileRenderer = mazeTile.GetComponent <MeshRenderer>();
                    tileRenderer.SetPropertyBlock(tileMaterialPropertyBlock);
                }
            }
        }
Beispiel #21
0
    // Every time we access a different tile, check if there is an enemy spawnpoint on it
    public void CheckForEnemySpawnpointOnTile()
    {
        MazeTile        selectedTile    = EditorTileSelector.Instance.CurrentlySelectedTile as MazeTile;
        EnemySpawnpoint enemySpawnpoint = selectedTile?.TryGetEnemySpawnpoint();

        if (enemySpawnpoint == null)
        {
            _tileAreaNamesDropdown.gameObject.SetActive(false);
            _assignedAreasText.gameObject.SetActive(false);
        }
        else
        {
            _tileAreaNamesDropdown.gameObject.SetActive(true);
            _assignedAreasText.gameObject.SetActive(true);

            RedrawAssignedAreasTest(enemySpawnpoint);
            RedrawDropdownOptions();
        }
    }
Beispiel #22
0
 public void Draw(IOutputMazeTileGrid tileGrid)
 {
     for (int x = 0; x < this.Width; x++)
     {
         for (int y = 0; y < this.Height; y++)
         {
             MazeTile tile = this.Get(x, y);
             if (tile == MazeTile.Open)
             {
                 tileGrid.MarkOpen(x, y);
             }
             else if (tile == MazeTile.Wall)
             {
                 tileGrid.MarkWall(x, y);
             }
         }
     }
     tileGrid.Draw();
 }
Beispiel #23
0
    private void RedrawDropdownOptions()
    {
        MazeTile        selectedTile    = EditorTileSelector.Instance.CurrentlySelectedTile as MazeTile;
        EnemySpawnpoint enemySpawnpoint = selectedTile?.TryGetEnemySpawnpoint();

        for (int i = 1; i < _tileAreaNamesDropdown.options.Count; i++)
        {
            string   areaId           = _tileAreaIdByDropdownOption[_tileAreaNamesDropdown.options[i]];
            TileArea tileArea         = GameManager.Instance.CurrentEditorLevel.TileAreas[areaId];
            string   originalAreaName = tileArea.Name;
            if (enemySpawnpoint.TileAreas.Contains(tileArea))
            {
                _tileAreaNamesDropdown.options[i].text = $"(X) {originalAreaName}";
            }
            else
            {
                _tileAreaNamesDropdown.options[i].text = originalAreaName;
            }
        }
    }
Beispiel #24
0
    /// <summary>
    /// Removes extra walls in the maze tiles
    /// </summary>
    private void RemoveExtraWalls()
    {
        // check board pattern
        for (int x = 0; x < mazeSize; x++)
        {
            for (int z = 0; z < mazeSize; z++)
            {
                MazeTile tile = currentMaze.tilesArray[x, z];

                // perform for all walls
                for (int dir = 0; dir < 4; dir++)
                {
                    Coordinate coordDir = Coordinate.GetCoordinate(dir);
                    Coordinate coord    = tile.coord + coordDir;

                    // check if coordinate points out of bounds
                    if (OutOfBounds(coord))
                    {
                        continue;
                    }

                    // no wall to break;
                    if (tile.walls[dir] == null)
                    {
                        continue;
                    }

                    MazeTile neighbour = currentMaze.tilesArray[coord.x, coord.z];

                    // check other wall
                    if (neighbour.walls[(dir + 2) % 4] == null)
                    {
                        continue;
                    }

                    // remove one wall because there are two
                    tile.BreakWall(dir);
                }
            }
        }
    }
Beispiel #25
0
    private void AddTileAreaToSpawnpoint()
    {
        if (_tileAreaNamesDropdown.value == 0)
        {
            return;
        }

        MazeTile        selectedTile    = EditorTileSelector.Instance.CurrentlySelectedTile as MazeTile;
        EnemySpawnpoint enemySpawnpoint = selectedTile?.TryGetEnemySpawnpoint();

        if (enemySpawnpoint == null)
        {
            Logger.Log("could not find enemySpawnpoint on the selected tile");
            return;
        }

        string currentlySelectedTileAreaId = GetIdCurrentSelectedTileArea();

        TileArea tileAreaInList = enemySpawnpoint.TileAreas.FirstOrDefault(tileArea => tileArea.Id == currentlySelectedTileAreaId);
        TileArea tileArea       = GameManager.Instance.CurrentEditorLevel.TileAreas[currentlySelectedTileAreaId];

        if (tileAreaInList == null)
        {
            Logger.Log("did not find the area in the list, so we add it");

            enemySpawnpoint.AddTileArea(tileArea);
        }
        else
        {
            Logger.Log($"The currently selected tile area is {tileAreaInList.Name}");
            enemySpawnpoint.RemoveTileArea(tileArea);
        }

        _assignedAreasText.text = GenerateAssignedAreasText(enemySpawnpoint);

        RedrawDropdownOptions();

        _tileAreaNamesDropdown.value = 0;
    }
Beispiel #26
0
        Maze BuildMaze(APIMaze apiMaze)
        {
            int width  = apiMaze.size[0];
            int height = apiMaze.size[1];

            MazeTile[,] tiles = new MazeTile[width, height];
            for (int row = 0; row < height; row++)
            {
                for (int column = 0; column < width; column++)
                {
                    MazeTile mazeTile = new MazeTile(column, row);
                    mazeTile.AccessibleTiles = new List <Point>();
                    tiles[column, row]       = mazeTile;
                    CalculateAccessibilities(apiMaze, width, height, row, column, mazeTile);
                }
            }

            int ponyY = apiMaze.pony[0] / width;
            int ponyX = apiMaze.pony[0] % width;

            int domokunY = apiMaze.domokun[0] / width;
            int domokunX = apiMaze.domokun[0] % width;

            int endpointY = apiMaze.endPont[0] / width;
            int endpointX = apiMaze.endPont[0] % width;

            var maze = new Maze
            {
                Width      = width,
                Height     = height,
                Difficulty = apiMaze.difficulty,
                Tiles      = tiles,
                Pony       = new Pony(ponyX, ponyY),
                Domokun    = new Monster(domokunX, domokunY),
                EndPoint   = new Point(endpointX, endpointY)
            };

            return(maze);
        }
Beispiel #27
0
    private void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
        }

        _currentScore = PlayerPrefs.HasKey("CurrentScore")
            ? PlayerPrefs.GetInt("CurrentScore")
            : 0;

        _highScore = PlayerPrefs.HasKey("HighScore")
            ? PlayerPrefs.GetInt("HighScore")
            : 0;

        LevelScore.text = _currentScore.ToString("000000");
        HighScore.text  = _highScore.ToString("000000");

        _fruitTile   = MazeAssembler.Instance.FruitParent.GetComponentInChildren <MazeTile>();
        _fruitSprite = _fruitTile.GetComponentInChildren <SpriteRenderer>();

        _fruitSprite.sprite = GameController.Instance.GetFruitSpriteFromData(LevelController.Instance.GetCurrentLevel().BonusFruit);
        _fruitTile.gameObject.SetActive(false);
    }
Beispiel #28
0
    /// <summary>
    /// Places a door
    /// </summary>
    private void PlaceDoor()
    {
        bool placedWall = false;

        while (!placedWall)
        {
            // pick tile
            MazeTile doorTile = currentMaze.tilesList[random.Next(currentMaze.tilesList.Count)];

            // look for wall
            int        doorWallIndex = random.Next(4);
            GameObject doorWall      = null;
            int        attempts      = 0;

            while (doorWall == null && attempts < 5)
            {
                doorWallIndex = (doorWallIndex + 5) % 4;
                doorWall      = doorTile.walls[doorWallIndex];
                attempts++;
            }

            // didn't find a wall
            if (attempts == 5)
            {
                continue;
            }

            // found a wall

            GameObject door = GameObject.Instantiate(doorPrefab, doorTile.transform, false);

            door.transform.rotation = doorWall.transform.rotation;

            placedWall = true;
        }
    }
    /// <summary>
    /// Gets each ghost scatter tile from the maze
    /// </summary>
    private void GetScatterTile()
    {
        switch (GhostType)
        {
        case GhostType.Blinky:
            _scatterTile = MazeAssembler.Instance.MazeTiles.FirstOrDefault(m => m.TileX == 25 && m.TileY == 31);
            break;

        case GhostType.Pinky:
            _scatterTile = MazeAssembler.Instance.MazeTiles.FirstOrDefault(m => m.TileX == 2 && m.TileY == 31);
            break;

        case GhostType.Inky:
            _scatterTile = MazeAssembler.Instance.MazeTiles.FirstOrDefault(m => m.TileX == 25 && m.TileY == -1);
            break;

        case GhostType.Clyde:
            _scatterTile = MazeAssembler.Instance.MazeTiles.FirstOrDefault(m => m.TileX == 2 && m.TileY == -1);
            break;

        default:
            throw new ArgumentOutOfRangeException();
        }
    }
Beispiel #30
0
    public void Generate(NonStandard.Data.Random.NumberGenerator random)
    {
        int width = ((stage + 2) * 2) + 1;

        mazeGenerationArguments.size = new Vector2(width, width);
        if (mazeSrc == null)
        {
            int seed = mazeGenerationArguments.seed;
            if (seed < 0)
            {
                seed = (int)GameClock.Time;
            }
            MazeGenerator mg = new MazeGenerator(random.Next);
            char[,] map = mg.Generate(mazeGenerationArguments.size, mazeGenerationArguments.start, mazeGenerationArguments.step, mazeGenerationArguments.wall);
            mg.Erode(map, mazeGenerationArguments.erosion);
            // generate ramps
            Coord          size = map.GetSize();
            List <Coord>[] ramp = new List <Coord> [4];
            for (int r = 0; r < ramp.Length; ++r)
            {
                ramp[r] = new List <Coord>();
            }
            const int W = 0, N = 1, E = 2, S = 3;// todo nwse
            size.ForEach(c => {
                if (c.row == 0 || c.row == size.row - 1 || c.col == 0 || c.col == size.col - 1)
                {
                    return;
                }
                char letter            = map.At(c);
                char n                 = map.At(c + Coord.Up), s = map.At(c + Coord.Down), e = map.At(c + Coord.Right), w = map.At(c + Coord.Left);
                bool createAtDeadEnds  = true;
                bool createAtPeninsula = true;
                if (n == s && e != w)
                {
                    if (letter == e && w == n)
                    {
                        if (letter == ' ' && createAtDeadEnds)
                        {
                            ramp[W].Add(c);
                        }
                        if (letter == '#' && createAtPeninsula)
                        {
                            ramp[E].Add(c);
                        }
                    }
                    if (letter == w && e == n)
                    {
                        if (letter == ' ' && createAtDeadEnds)
                        {
                            ramp[E].Add(c);
                        }
                        if (letter == '#' && createAtPeninsula)
                        {
                            ramp[W].Add(c);
                        }
                    }
                }
                if (e == w && n != s)
                {
                    if (letter == n && s == w)
                    {
                        if (letter == ' ' && createAtDeadEnds)
                        {
                            ramp[S].Add(c);
                        }
                        if (letter == '#' && createAtPeninsula)
                        {
                            ramp[N].Add(c);
                        }
                    }
                    if (letter == s && n == e)
                    {
                        if (letter == ' ' && createAtDeadEnds)
                        {
                            ramp[N].Add(c);
                        }
                        if (letter == '#' && createAtPeninsula)
                        {
                            ramp[S].Add(c);
                        }
                    }
                }
            });
            //ramp[W].ForEach(c => { map.SetAt(c, 'w'); });
            //ramp[N].ForEach(c => { map.SetAt(c, 'n'); });
            //ramp[E].ForEach(c => { map.SetAt(c, 'e'); });
            //ramp[S].ForEach(c => { map.SetAt(c, 's'); });
            int totalRamps = ramp.Sum(r => r.Count);
            for (int i = 0; i < totalRamps && i < stage + 1; ++i)
            {
                int[] r = ramp.GetNestedIndex(random.Next(totalRamps));
                //Debug.Log(r.JoinToString(", "));
                Coord loc = ramp[r[0]][r[1]];
                ramp[r[0]].RemoveAt(r[1]);
                char ch = "wnes"[r[0]];
                map.SetAt(loc, ch);
                --totalRamps;
            }
            this.map = new Map2d(map);
            //Debug.Log(this.map);
        }
        else
        {
            map.LoadFromString(mazeSrc.text);
        }
        seen.Reset();
        int count = map.Height * map.Width;

        while (mazeTiles.Count < count)
        {
            mazeTiles.Add(Instantiate(prefab_mazeTile.gameObject).GetComponent <MazeTile>());
        }
        //int index = 0;
        Vector3 off = new Vector3(map.Width / -2f * tileSize.x, 0, map.Height / -2f * tileSize.z);

        floorTiles = new List <MazeTile>();
        floorTileNeighborHistogram.SetEach(0);
        map.GetSize().ForEach(c => {
            MazeTile mt = GetTile(c);//mazeTiles[index++];
            mt.maze     = this;
            mt.coord    = c;
            Transform t = mt.transform;
            t.SetParent(_t);
            t.localPosition = mt.CalcLocalPosition();
            MazeTile.Kind k = MazeTile.Kind.None;
            switch (map[c])
            {
            case ' ': k = MazeTile.Kind.Floor; break;

            case '#': k = MazeTile.Kind.Wall; break;

            case 'w': k = MazeTile.Kind.RampWest; break;

            case 'n': k = MazeTile.Kind.RampNorth; break;

            case 's': k = MazeTile.Kind.RampSouth; break;

            case 'e': k = MazeTile.Kind.RampEast; break;
            }
            mt.kind = k;
            mt.SetDiscovered(false, null, this);
            if (mt.kind == MazeTile.Kind.Floor)
            {
                floorTiles.Add(mt);
                mt.goalScore = TileScorer(mt, map);
                int index    = (int)mt.goalScore;
                if (index >= floorTileNeighborHistogram.Length)
                {
                    Array.Resize(ref floorTileNeighborHistogram, index + 1);
                }
                ++floorTileNeighborHistogram[index];
            }
            else
            {
                mt.goalScore = float.PositiveInfinity;
            }
        });
        floorTiles.Sort((a, b) => a.goalScore.CompareTo(b.goalScore));
    }