private void ConnectFarTaskNodesRooms(Room upperRoom, Room lowerRoom)
    {
        // Choose random cell in the lower part of the upper room
        int         random    = Random.Range(0, upperRoom.getTilesDownRow().Count - 1);
        DungeonCell firstCell = upperRoom.getTilesDownRow()[random].getCorrespondingDungeonCell();

        // Choose random cell in the upper part of the lower room
        random = Random.Range(0, lowerRoom.getTilesUpRow().Count - 1);
        DungeonCell lastCell = lowerRoom.getTilesUpRow()[random].getCorrespondingDungeonCell();

        // Check if both cells are aligned
        if (firstCell.getCellColumnPositionInGrid() == lastCell.getCellColumnPositionInGrid())
        {
            dungeon.getDungeonCorridors().Add(new Corridor(dungeon, firstCell, lastCell, Direction.Down, floorTileDimensions, floorMaterial, wallHeight, wallMaterial, false));
        }
        else
        {
            // Get first  middle point between both rooms
            int         middle          = (firstCell.getCellRowPositionInGrid() + lastCell.getCellRowPositionInGrid()) / 2;
            DungeonCell firstMiddleCell = dungeon.getDungeonGrid()[middle, firstCell.getCellColumnPositionInGrid()];
            // Get second middle point
            DungeonCell secondMiddleCell = dungeon.getDungeonGrid()[middle, lastCell.getCellColumnPositionInGrid()];
            // Calculate direction of middle corridor
            Direction middleDirection = Direction.Right;
            if (firstMiddleCell.getCellColumnPositionInGrid() > secondMiddleCell.getCellColumnPositionInGrid())
            {
                middleDirection = Direction.Left;
            }
            // Create corridors
            dungeon.getDungeonCorridors().Add(new Corridor(dungeon, firstCell, firstMiddleCell, Direction.Down, floorTileDimensions, floorMaterial, wallHeight, wallMaterial, true));
            dungeon.getDungeonCorridors().Add(new Corridor(dungeon, firstMiddleCell, secondMiddleCell, middleDirection, floorTileDimensions, floorMaterial, wallHeight, wallMaterial, true));
            dungeon.getDungeonCorridors().Add(new Corridor(dungeon, secondMiddleCell, lastCell, Direction.Down, floorTileDimensions, floorMaterial, wallHeight, wallMaterial, false));
        }
    }
    private void CreateRoomAndConnectNodes(Dictionary <AlphabetNode, Room> nodesWithRoom, List <AlphabetNode> nodesToVisit, AlphabetNode currentNode, Direction dir)
    {
        // Choose random corridor length to separate the rooms by that distance
        int randomCorridorLength = 1;

        if (dir == Direction.Right || dir == Direction.Left)
        {
            randomCorridorLength = Random.Range(minCorridorLengthWhenHorizontal, maxCorridorLengthWhenHorizontal);
        }
        else
        {
            randomCorridorLength = Random.Range(minCorridorLengthWhenVertical, maxCorridorLengthWhenVertical);
        }
        // Choose random room width
        int randomRoomWidth = Random.Range(roomMinTilesWidth, roomMaxTilesWidth);
        // Choose random room height
        int randomRoomHeight = Random.Range(roomMinTilesHeight, roomMaxTilesHeight);
        // Calculate top left corner column and row based on the direction and the middle cell of corresponding external side to align the rooms as much as possible
        int topLeftCornerColumn = 0;
        int topLeftCornerRow    = 0;

        switch (dir)
        {
        case Direction.Right:
            int         rigthColumnTilesNumber = nodesWithRoom[nodesToVisit[0]].getTilesRightColumn().Count;
            DungeonCell rightColumnMiddleCell  = nodesWithRoom[nodesToVisit[0]].getTilesRightColumn()[rigthColumnTilesNumber / 2].getCorrespondingDungeonCell();
            topLeftCornerColumn = rightColumnMiddleCell.getCellColumnPositionInGrid() + randomCorridorLength + 1;
            topLeftCornerRow    = rightColumnMiddleCell.getCellRowPositionInGrid() - (randomRoomHeight / 2);
            break;

        case Direction.Left:
            int         leftColumnTilesNumber = nodesWithRoom[nodesToVisit[0]].getTilesLeftColumn().Count;
            DungeonCell leftColumnMiddleCell  = nodesWithRoom[nodesToVisit[0]].getTilesLeftColumn()[leftColumnTilesNumber / 2].getCorrespondingDungeonCell();
            topLeftCornerColumn = leftColumnMiddleCell.getCellColumnPositionInGrid() - randomCorridorLength - randomRoomWidth;
            topLeftCornerRow    = leftColumnMiddleCell.getCellRowPositionInGrid() - (randomRoomHeight / 2);
            break;

        case Direction.Up:
            int         upRowTilesNumber = nodesWithRoom[nodesToVisit[0]].getTilesUpRow().Count;
            DungeonCell upRowMiddleCell  = nodesWithRoom[nodesToVisit[0]].getTilesUpRow()[upRowTilesNumber / 2].getCorrespondingDungeonCell();
            topLeftCornerColumn = upRowMiddleCell.getCellColumnPositionInGrid() - (randomRoomWidth / 2);
            topLeftCornerRow    = upRowMiddleCell.getCellRowPositionInGrid() - randomCorridorLength - randomRoomHeight;
            break;

        case Direction.Down:
            int         downRowTilesNumber = nodesWithRoom[nodesToVisit[0]].getTilesDownRow().Count;
            DungeonCell downRowMiddleCell  = nodesWithRoom[nodesToVisit[0]].getTilesDownRow()[downRowTilesNumber / 2].getCorrespondingDungeonCell();
            topLeftCornerColumn = downRowMiddleCell.getCellColumnPositionInGrid() - (randomRoomWidth / 2);
            topLeftCornerRow    = downRowMiddleCell.getCellRowPositionInGrid() + randomCorridorLength + 1;
            break;
        }
        // Create room
        dungeon.getDungeonRooms().Add(new Room(dungeon, topLeftCornerRow, topLeftCornerColumn, randomRoomHeight, randomRoomWidth, floorTileDimensions, floorMaterial, wallHeight, wallMaterial));
        // Add node to lists
        nodesWithRoom.Add(currentNode.getConnection(dir), dungeon.getDungeonRooms()[dungeon.getDungeonRooms().Count - 1]);
        nodesToVisit.Add(currentNode.getConnection(dir));
        // Connect rooms
        dungeon.getDungeonCorridors().Add(new Corridor(dungeon, nodesWithRoom[currentNode], nodesWithRoom[currentNode.getConnection(dir)], floorTileDimensions, floorMaterial, wallHeight, wallMaterial));
    }
        // Method that will try to build a corridor from of the outer tiles of the last room placed
        private void TryToBuildCorridorFromRoom(Vector3 tileDimensions, Material floorMaterial, float wallHeight, Material wallMaterial)
        {
            // Reset dirty corridors variables
            dirtyCorridors.Clear();
            lastTileUsedAsCorridorConnection = null;
            directionOfWallToRebuild         = Direction.Unknown;
            // Try to place a corridor from one of the four outter walls of a room
            while (lastRoomPlacedPossibleTiles.Count > 0)
            {
                // Choose random list
                int i = Random.Range(0, lastRoomPlacedPossibleTiles.Count - 1);
                // Choose random list
                Direction randomDirection = (Direction)Random.Range(0, System.Enum.GetValues(typeof(Direction)).Length);
                while (!lastRoomPlacedPossibleTiles.ContainsKey(randomDirection))
                {
                    randomDirection = (Direction)Random.Range(0, System.Enum.GetValues(typeof(Direction)).Length);
                }
                List <FloorTile> randomList = lastRoomPlacedPossibleTiles[randomDirection];
                // Choose random tile until all tiles have been checked
                while (randomList.Count > 0 && !corridorPlaced)
                {
                    // Randomly select tile
                    int       j          = Random.Range(0, randomList.Count - 1);
                    FloorTile randomTile = randomList[j];
                    currentCell = randomTile.getCorrespondingDungeonCell();
                    DungeonCell lastCell = randomTile.getCorrespondingDungeonCell();
                    // Check if corridor can be created from random tile
                    int emptyCells             = 0;
                    int rowLengthMultiplier    = 0;
                    int columnLengthMultiplier = 0;
                    switch (randomDirection)
                    {
                    case Direction.Up:
                        emptyCells          = CheckEmptyCellsUp();
                        rowLengthMultiplier = -1;
                        break;

                    case Direction.Down:
                        emptyCells          = CheckEmptyCellsDown();
                        rowLengthMultiplier = 1;
                        break;

                    case Direction.Left:
                        emptyCells             = CheckEmptyCellsLeft();
                        columnLengthMultiplier = -1;
                        break;

                    case Direction.Right:
                        emptyCells             = CheckEmptyCellsRight();
                        columnLengthMultiplier = 1;
                        break;
                    }
                    if (emptyCells > minCorridorsLength)
                    {
                        // Choose random length
                        int length = Random.Range(minCorridorsLength, emptyCells - 1);
                        length = Mathf.Min(length, maxCorridorsLength);
                        // Set last cell
                        lastCell = dungeon.getDungeonGrid()[currentCell.getCellRowPositionInGrid() + (rowLengthMultiplier * length), currentCell.getCellColumnPositionInGrid() + (columnLengthMultiplier * length)];
                        // Build corridor between first and last cell
                        dungeon.getDungeonCorridors().Add(new Corridor(dungeon, currentCell, lastCell, randomDirection, tileDimensions, floorMaterial, wallHeight, wallMaterial, true));
                        corridorPlaced = true;
                        // Add the corridor to the dirty corridors list
                        dirtyCorridors.Add(dungeon.getDungeonCorridors()[dungeon.getDungeonCorridors().Count - 1]);
                        // Set the current cell (outer room cell) as the last cell used as connection
                        lastTileUsedAsCorridorConnection = currentCell.getCellFloorTile();
                        // Set the direction of the tile wall that will need to be removed
                        directionOfWallToRebuild = randomDirection;
                        // Set direction to randomDirection
                        direction = randomDirection;
                        // Set current cell to the last cell of the corridor
                        currentCell = lastCell;
                    }
                    // Remove tile from list
                    randomList.Remove(randomTile);
                }
                // Exit loop if corridor was placed
                if (corridorPlaced)
                {
                    break;
                }
                // Remove list
                lastRoomPlacedPossibleTiles.Remove(randomDirection);
            }
            // Reset try again boolean
            tryAgain = false;
        }
Esempio n. 4
0
    private void BuildCorridor(Dungeon dungeon, DungeonCell firstCell, DungeonCell lastCell, bool leaveLastCellWalls, Vector3 floorDimensions, Material floorMaterial,
                               float wallHeight, Material wallMaterial)
    {
        // Initialize list
        corridorTiles = new List <FloorTile>();
        // Initialize game object
        corridor      = new GameObject();
        corridor.name = "Corridor";
        // Set necessary variables
        DungeonCell startCell   = firstCell;
        DungeonCell currentCell = firstCell;
        DungeonCell nextCell    = firstCell;
        DungeonCell endCell     = lastCell;

        // Traverse columns until the end cell column is reached
        while (true)
        {
            // If grid cell is empty place floor tile normally
            if (currentCell.getCellFloorTile() == null && currentCell.getCellColumnPositionInGrid() != endCell.getCellColumnPositionInGrid())
            {
                // Create tile
                FloorTile tile = new FloorTile(currentCell, floorMaterial, floorDimensions, TileType.CorridorTile);
                // When traversing right or left the tile is going to need upper and down walls
                tile.placeWall(wallMaterial, wallHeight, Direction.Up);
                tile.placeWall(wallMaterial, wallHeight, Direction.Down);
                // Add tile to the list of corridor tiles
                corridorTiles.Add(tile);
                currentCell.setCellFloorTile(tile);
            }
            // Traverse right
            if (currentCell.getCellColumnPositionInGrid() < endCell.getCellColumnPositionInGrid())
            {
                // If the grid cell has a tile with walls remove the ones that are not needed
                if (currentCell.getCellFloorTile().getTileType() == TileType.RoomOuterTile || currentCell.getCellFloorTile().getTileType() == TileType.CorridorTile)
                {
                    // When traversing right always remove the right wall of current tile if there is one
                    currentCell.getCellFloorTile().removeWall(Direction.Right);
                }
                // Get next cell
                nextCell = dungeon.getDungeonGrid()[currentCell.getCellRowPositionInGrid(), currentCell.getCellColumnPositionInGrid() + 1];
                // Remove left wall of next cell if there is one
                if (nextCell.getCellFloorTile() != null)
                {
                    nextCell.getCellFloorTile().removeWall(Direction.Left);
                }
            }
            // Traverse left
            else if (currentCell.getCellColumnPositionInGrid() > endCell.getCellColumnPositionInGrid())
            {
                // If the grid cell has a tile with walls remove the ones that are not needed
                if (currentCell.getCellFloorTile().getTileType() == TileType.RoomOuterTile || currentCell.getCellFloorTile().getTileType() == TileType.CorridorTile)
                {
                    // When traversing left always remove the left wall of current tile if there is one
                    currentCell.getCellFloorTile().removeWall(Direction.Left);
                }
                nextCell = dungeon.getDungeonGrid()[currentCell.getCellRowPositionInGrid(), currentCell.getCellColumnPositionInGrid() - 1];
                // Remove right wall of next cell if there is one
                if (nextCell.getCellFloorTile() != null)
                {
                    nextCell.getCellFloorTile().removeWall(Direction.Right);
                }
            }
            // Current cell column and end cell column are the same
            else
            {
                // If grid cell is empty place floor tile with walls forming a corner
                if (currentCell.getCellFloorTile() == null)
                {
                    // Check in which row direction (up or down) the corridor will go next
                    Direction cornerWall1;
                    if (currentCell.getCellRowPositionInGrid() < endCell.getCellRowPositionInGrid())
                    {
                        // If the corridor needs to go down the corner wall needs to be placed up the current tile
                        cornerWall1 = Direction.Up;
                    }
                    else
                    {
                        // If the corridor needs to go up the corner wall needs to be placed down the current tile
                        cornerWall1 = Direction.Down;
                    }
                    // Check if the start cell is at the right or left of the current cell
                    Direction cornerWall2;
                    if (startCell.getCellColumnPositionInGrid() < currentCell.getCellColumnPositionInGrid())
                    {
                        // When coming from the left, the wall of the corner corridor cell needs to be placed on the right
                        cornerWall2 = Direction.Right;
                    }
                    else
                    {
                        // When coming from the right, the wall of the corner corridor cell needs to be placed on the left
                        cornerWall2 = Direction.Left;
                    }
                    // Create tile
                    FloorTile tile = new FloorTile(currentCell, floorMaterial, floorDimensions, TileType.CorridorTile);
                    // Place corner tile walls
                    if (!leaveLastCellWalls)
                    {
                        tile.placeWall(wallMaterial, wallHeight, cornerWall1);
                        tile.placeWall(wallMaterial, wallHeight, cornerWall2);
                    }
                    // Add tile to the list of corridor tiles
                    corridorTiles.Add(tile);
                    currentCell.setCellFloorTile(tile);
                }
                // Exit loop
                break;
            }
            // Set current cell to next cell
            currentCell = nextCell;
        }
        // Traverse rows until the end cell row is reached
        while (true)
        {
            // If grid cell is empty place floor tile normally
            if (currentCell.getCellFloorTile() == null)
            {
                // Create tile
                FloorTile tile = new FloorTile(currentCell, floorMaterial, floorDimensions, TileType.CorridorTile);
                // When traversing up or down the tile is going to need right and left walls
                tile.placeWall(wallMaterial, wallHeight, Direction.Right);
                tile.placeWall(wallMaterial, wallHeight, Direction.Left);
                // Add tile to the list of corridor tiles
                corridorTiles.Add(tile);
                currentCell.setCellFloorTile(tile);
            }
            // Traverse down
            if (currentCell.getCellRowPositionInGrid() < endCell.getCellRowPositionInGrid())
            {
                // If the grid cell has a tile with walls remove the ones that are not needed
                if (currentCell.getCellFloorTile().getTileType() == TileType.RoomOuterTile || currentCell.getCellFloorTile().getTileType() == TileType.CorridorTile)
                {
                    // When traversing down always remove the down wall of current tile if there is one
                    currentCell.getCellFloorTile().removeWall(Direction.Down);
                }
                // Get next cell
                nextCell = dungeon.getDungeonGrid()[currentCell.getCellRowPositionInGrid() + 1, currentCell.getCellColumnPositionInGrid()];
                // Remove upper wall of next cell if there is one
                if (nextCell.getCellFloorTile() != null)
                {
                    nextCell.getCellFloorTile().removeWall(Direction.Up);
                }
            }
            // Traverse up
            else if (currentCell.getCellRowPositionInGrid() > endCell.getCellRowPositionInGrid())
            {
                // If the grid cell has a tile with walls remove the ones that are not needed
                if (currentCell.getCellFloorTile().getTileType() == TileType.RoomOuterTile || currentCell.getCellFloorTile().getTileType() == TileType.CorridorTile)
                {
                    // When traversing up always remove the upper wall of current tile if there is one
                    currentCell.getCellFloorTile().removeWall(Direction.Up);
                }
                nextCell = dungeon.getDungeonGrid()[currentCell.getCellRowPositionInGrid() - 1, currentCell.getCellColumnPositionInGrid()];
                // Remove down wall of next cell if there is one
                if (nextCell.getCellFloorTile() != null)
                {
                    nextCell.getCellFloorTile().removeWall(Direction.Down);
                }
            }
            // Current cell column and end cell column are the same, as the up or down traversal is done after the right or left, at this point the start and end cells are connected and no corners are needed
            else
            {
                // Exit loop
                break;
            }
            // Set current cell to next cell
            currentCell = nextCell;
        }
        // Set corridor game object in the tile at the middle of the tiles list
        corridor.transform.position = corridorTiles[corridorTiles.Count / 2].getCorrespondingDungeonCell().getCellWorldPosition();
        // Set the tiles as children of the corridor game object
        foreach (FloorTile tile in corridorTiles)
        {
            tile.setParent(corridor, true);
        }
    }
        // Method that will try to build a room from the cell the digger is currently at
        private void TryToPlaceRoom(int roomMinWidth, int roomMaxWidth, int roomMinHeight, int roomMaxHeight, Vector3 tileDimensions, Material floorMaterial, float wallHeight, Material wallMaterial)
        {
            // If a corridor was placed in the previous iteration, the room needs to start from the next cell to the actual current cell based on the direcion the digger agent was going
            DungeonCell previousCurrent       = dungeon.getDungeonGrid()[currentCell.getCellRowPositionInGrid(), currentCell.getCellColumnPositionInGrid()];
            Direction   directionToRemoveWall = Direction.Unknown;

            if (corridorPlaced)
            {
                UpdateCurrentCellToNextCell(ref directionToRemoveWall);
            }
            // Check the number of empty tiles from the currentCell in the four directions
            int emptyCellsRight = CheckEmptyCellsRight();
            int emptyCellsLeft  = CheckEmptyCellsLeft();
            int emptyCellsUp    = CheckEmptyCellsUp();
            int emptyCellsDown  = CheckEmptyCellsDown();

            // Check if there is enough space to create a room from current cell
            if (emptyCellsRight + emptyCellsLeft > roomMinWidth && emptyCellsUp + emptyCellsDown > roomMinHeight)
            {
                // To make sure that one of the room tiles is placed in the current cell, the maximum distance to move the starting cell is the room minimum tiles height/width
                int maximumDistanceUp   = Mathf.Min(emptyCellsUp, roomMinHeight);
                int maximumDistanceLeft = Mathf.Min(emptyCellsLeft, roomMinWidth);
                // Rooms are created from the top left corner, meaning that the starting cell can be moved from the current cell up or left if there is space
                int topLeftCornerMinRow    = currentCell.getCellRowPositionInGrid() - maximumDistanceUp + 1;
                int topLeftCornerMinColumn = currentCell.getCellColumnPositionInGrid() - maximumDistanceLeft + 1;
                // The max column and row are going to depend on the available cells at the right and down of the current cell
                int maxRow = currentCell.getCellRowPositionInGrid() + emptyCellsDown - 1;
                int topLeftCornerMaxRow = maxRow - roomMinHeight + 1;
                topLeftCornerMaxRow = topLeftCornerMaxRow > currentCell.getCellRowPositionInGrid() ? currentCell.getCellRowPositionInGrid() : topLeftCornerMaxRow;
                int maxColumn = currentCell.getCellColumnPositionInGrid() + emptyCellsRight - 1;
                int topLeftCornerMaxColumn = maxColumn - roomMinWidth + 1;
                topLeftCornerMaxColumn = topLeftCornerMaxColumn > currentCell.getCellColumnPositionInGrid() ? currentCell.getCellColumnPositionInGrid() : topLeftCornerMaxColumn;
                // Choose random row and column for the top left corner of the room
                int topLeftCornerRandomRow    = Random.Range(topLeftCornerMinRow, topLeftCornerMaxRow);
                int topLeftCornerRandomColumn = Random.Range(topLeftCornerMinColumn, topLeftCornerMaxColumn);
                // Get max width and height from the row and column selected to be the top left corner of the room
                int maxWidth  = Mathf.Min(maxColumn - topLeftCornerRandomColumn + 1, roomMaxWidth);
                int maxHeight = Mathf.Min(maxRow - topLeftCornerRandomRow + 1, roomMaxHeight);
                // Get random width and height
                int randomRoomWidth  = Random.Range(roomMinWidth, maxWidth);
                int randomRoomHeight = Random.Range(roomMinHeight, maxHeight);
                // Given the top left corner, width and height, make sure that the room can still be placed
                if (AllTilesAreEmpty(topLeftCornerRandomRow, randomRoomHeight, topLeftCornerRandomColumn, randomRoomWidth))
                {
                    // Create new room
                    dungeon.getDungeonRooms().Add(new Room(dungeon, topLeftCornerRandomRow, topLeftCornerRandomColumn, randomRoomHeight, randomRoomWidth, tileDimensions, floorMaterial, wallHeight, wallMaterial));
                    roomPlaced = true;
                    // Get all possible tiles from which a corridor can be placed of the room currently added
                    lastRoomPlacedPossibleTiles.Clear();
                    lastRoomPlacedPossibleTiles.Add(Direction.Up, dungeon.getDungeonRooms()[dungeon.getDungeonRooms().Count - 1].getTilesUpRow());
                    lastRoomPlacedPossibleTiles.Add(Direction.Down, dungeon.getDungeonRooms()[dungeon.getDungeonRooms().Count - 1].getTilesDownRow());
                    lastRoomPlacedPossibleTiles.Add(Direction.Left, dungeon.getDungeonRooms()[dungeon.getDungeonRooms().Count - 1].getTilesLeftColumn());
                    lastRoomPlacedPossibleTiles.Add(Direction.Right, dungeon.getDungeonRooms()[dungeon.getDungeonRooms().Count - 1].getTilesRightColumn());
                    // Remove wall from the previous current cell to connect the room and the corridor, if a corridor was placed in the previous iteration
                    if (corridorPlaced)
                    {
                        previousCurrent.getCellFloorTile().removeWall(direction);
                        currentCell.getCellFloorTile().removeWall(directionToRemoveWall);
                    }
                }
            }
            // If room could not be placed, then set the current to be the previous current to properly connect a corridor with another corridor
            if (!roomPlaced)
            {
                currentCell = previousCurrent;
            }
        }