Exemplo n.º 1
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>	Complete walls around any off map sites next to floors. </summary>
        ///
        /// <remarks>	Darrellp, 9/26/2011. </remarks>
        ///
        /// <param name="map">	The map. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        private static void CompleteWalls(IRoomsMap map)
        {
            for (int iRow = 0; iRow < map.Height; iRow++)
            {
                // For each Column
                for (int iColumn = 0; iColumn < map.Width; iColumn++)
                {
                    // Is there a no floor here?
                    if (map[iColumn, iRow].Terrain != TerrainType.Floor)
                    {
                        continue;
                    }

                    // Get the neighboring off map locations
                    var offmapLocations = map.Neighbors(iColumn, iRow).Where(location => map[location].Terrain == TerrainType.OffMap);

                    // For each neighboring off map location
                    foreach (var location in offmapLocations)
                    {
                        // Turn it into stone wall
                        map[location].Terrain = TerrainType.Wall;
                    }
                }
            }
        }
Exemplo n.º 2
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>	Place the stairs. </summary>
        ///
        /// <remarks>	Darrellp, 9/26/2011. </remarks>
        ///
        /// <param name="map">	The map. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        private void PlaceStairs(IRoomsMap map)
        {
            RectangularRoom downRoom     = RoomAt(_connections.FirstRoomConnected);
            RectangularRoom upRoom       = RoomAt(_connections.LastRoomConnected);
            MapCoordinates  downLocation = downRoom.PickSpotInRoom(_rnd);
            MapCoordinates  upLocation   = upRoom.PickSpotInRoom(_rnd);

            map[downLocation].Terrain = TerrainType.StairsDown;
            map[upLocation].Terrain   = TerrainType.StairsUp;
        }
Exemplo n.º 3
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>	Post process. </summary>
        ///
        /// <remarks>
        /// Put in final walls, etc. based on the excavation that was done in the main part of the
        /// excavation process.  Darrellp, 9/25/2011.
        /// </remarks>
        ///
        /// <param name="map">	The map. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        private void PostProcess(IRoomsMap map)
        {
            // Complete all the walls
            CompleteWalls(map);

            // Place room info
            AssignRoomsToCells(map);

            // Place stairs
            PlaceStairs(map);
        }
Exemplo n.º 4
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>	Excavates the rooms for a level based on a text stream. </summary>
        ///
        /// <remarks>	Darrellp, 9/16/2011. </remarks>
        ///
        /// <param name="map">		The map to be excavated. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        public void Excavate(IRoomsMap map)
        {
            // For each line in the file
            for (int iRow = 0; iRow < _asciiLines.Count && iRow < map.Height; iRow++)
            {
                // Read the line
                string currentLine = _asciiLines[iRow];

                // Insert the line into the current row
                InsertRow(map, currentLine, iRow);
            }
        }
Exemplo n.º 5
0
 private static void AssignTilesInRoom(IRoomsMap map, GenericRoom groom)
 {
     // Is this room being newly added to the map?
     if (map.Rooms.Add(groom))
     {
         // For each tile in the room
         foreach (var tileLocation in groom.Tiles)
         {
             // Assign the room to that tile
             map[tileLocation].Room = groom;
         }
     }
 }
Exemplo n.º 6
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>	Excavate bend. </summary>
        ///
        /// <remarks>
        /// "Perpindicular" here refers to the coordinate perpindicular to the orientation of the two
        /// rooms.  If the rooms are oriented vertically then perpindicular refers to the horizontal (x)
        /// coordinate wo that startPerpindicular is the starting column. If they're oriented vertically,
        /// startPerpindicular is the starting row.  Parallel refers to the coordinate parallel to the
        /// orientation.  Bend is always in the perpindicular coordinate. Unidirectional but named as
        /// though dir was vertical.  Darrellp, 9/18/2011.
        /// </remarks>
        ///
        /// <param name="map">			The map to be excavated. </param>
        /// <param name="startColumn">	The start perpindicular. </param>
        /// <param name="endColumn">	The end perpindicular. </param>
        /// <param name="startRow">		The start parallel. </param>
        /// <param name="endRow">		The end parallel. </param>
        /// <param name="bend">			The bend coordinate. </param>
        /// <param name="groom">		The room being prepared for this corridor. </param>
        /// <param name="dir">			The direction the bend is supposed to run. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        private static void ExcavateBend(IRoomsMap map, int startColumn, int endColumn, int startRow, int endRow, int bend, GenericRoom groom, Dir dir)
        {
            Dir otherDir = MapCoordinates.OtherDirection(dir);

            // Create corridor to the bend
            ExcavateCorridorRun(map, startColumn, startRow, bend, groom, dir);

            // Create the cross corridor at the bend
            ExcavateCorridorRun(map, bend, startColumn, endColumn, groom, otherDir);

            // Create the corridor from the bend to the destination
            ExcavateCorridorRun(map, endColumn, bend, endRow, groom, dir);
        }
Exemplo n.º 7
0
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 /// <summary>	Excavate a room, putting walls on the border. </summary>
 ///
 /// <remarks>	Darrellp, 9/19/2011. </remarks>
 ///
 /// <param name="map">	The map to be excavated. </param>
 /// <param name="room">	The room to carve out of the map. </param>
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 private static void ExcavateRoom(IRoomsMap map, RectangularRoom room)
 {
     // For each column in the room
     for (var iColumn = room.Left + 1; iColumn < room.Right; iColumn++)
     {
         // For each row in the room
         for (var iRow = room.Top + 1; iRow < room.Bottom; iRow++)
         {
             // Place the appropriate terrain
             map[iColumn, iRow].Terrain = TerrainType.Floor;
         }
     }
 }
Exemplo n.º 8
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>	Excavate between connected rooms in a grid connection. </summary>
        ///
        /// <remarks>	Variables named from the perspective that dir is vertical Darrellp, 9/19/2011. </remarks>
        ///
        /// <param name="map">				The map to be excavated. </param>
        /// <param name="dir">				The direction the merge will take place in. </param>
        /// <param name="topEntrance">		The small coordinate entrance. </param>
        /// <param name="bottomEntrance">	The large coordinate entrance. </param>
        /// <param name="groom">			The room being prepared for this corridor. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        private void CreateBend(IRoomsMap map, Dir dir, MapCoordinates topEntrance, MapCoordinates bottomEntrance, GenericRoom groom)
        {
            // locals
            Dir otherDir    = MapCoordinates.OtherDirection(dir);
            int startRow    = topEntrance[dir];
            int endRow      = bottomEntrance[dir];
            int startColumn = topEntrance[otherDir];
            int endColumn   = bottomEntrance[otherDir];

            // Determine bend location
            int bendRow = _rnd.Next(startRow + 1, endRow);

            // Excavate the bend between the two rooms
            ExcavateBend(map, startColumn, endColumn, startRow, endRow, bendRow, groom, dir);
        }
Exemplo n.º 9
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>	Excavates between two rooms. </summary>
        ///
        /// <remarks>	Variables named from the perspective of dir being vertical.  Darrellp, 9/18/2011. </remarks>
        ///
        /// <param name="map">			The map to be excavated. </param>
        /// <param name="roomTop">		The first room. </param>
        /// <param name="roomBottom">	The second room. </param>
        /// <param name="dir">			The direction to excavate in. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        private void ExcavateCorridor(IRoomsMap map, RectangularRoom roomTop, RectangularRoom roomBottom, Dir dir)
        {
            // Locals
            MapCoordinates bottomEntrance, topEntrance;

            // Get the entrances to each room
            GetEntrances(roomTop, roomBottom, dir, out topEntrance, out bottomEntrance);

            // Allocate the generic room
            int             genericWidth    = Math.Abs(topEntrance.Column - bottomEntrance.Column) + 1;
            int             genericHeight   = Math.Abs(topEntrance.Row - bottomEntrance.Row) + 1;
            int             genericLeft     = Math.Min(topEntrance.Column, bottomEntrance.Column);
            int             genericBottom   = Math.Min(topEntrance.Row, bottomEntrance.Row);
            MapCoordinates  genericLocation = new MapCoordinates(genericLeft, genericBottom);
            GenericCorridor corridor        = new GenericCorridor(genericWidth, genericHeight, genericLocation);

            // Excavate a connection between the two rooms
            CreateBend(map, dir, topEntrance, bottomEntrance, corridor);

            // Put the exits in the appropriate generic rooms
            GenericRoom groomTop    = _mapRoomToGenericRooms[roomTop];
            GenericRoom groomBottom = _mapRoomToGenericRooms[roomBottom];

            corridor.AddExit(groomTop, topEntrance);
            corridor.AddExit(groomBottom, bottomEntrance);
            groomTop.AddExit(corridor, topEntrance);
            groomBottom.AddExit(corridor, bottomEntrance);


            // Should we put a door in the top room?
            if (_rnd.Next(100) < _pctDoorChance)
            {
                // Place the door
                map[topEntrance].Terrain = TerrainType.Door;
            }

            // Should we put a door in the bottom room?
            if (_rnd.Next(100) < _pctDoorChance)
            {
                // Place the door
                map[bottomEntrance].Terrain = TerrainType.Door;
            }
        }
Exemplo n.º 10
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>	Excavate a straight corridor run either vertically or horizontally. </summary>
        ///
        /// <remarks>
        /// Excavates from (startParallel, perpindicular) to (endParallel, perpindicular) inclusive if
        /// fVertical.  If not fVertical, swap coordinates.  start and end parallel coordinates do not
        /// have to be in numerical order.  This is a unidirectional function but, as usual, names are
        /// named as though dir was vertical.  Darrellp, 9/19/2011.
        /// </remarks>
        ///
        /// <param name="map">		The map to be excavated. </param>
        /// <param name="column">	The perpindicular coordinate. </param>
        /// <param name="endRow1">	The starting parallel coordinate. </param>
        /// <param name="endRow2">	The ending parallel coordinate. </param>
        /// <param name="groom">	The room being prepared for this corridor. </param>
        /// <param name="dir">		The direction of the corridor. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        private static void ExcavateCorridorRun(IRoomsMap map, int column, int endRow1, int endRow2, GenericRoom groom, Dir dir)
        {
            // We work with small and large coords rather than start and end
            int  startRow  = Math.Min(endRow1, endRow2);
            int  endRow    = Math.Max(endRow1, endRow2);
            char floorChar = TerrainFactory.TerrainToChar(TerrainType.Floor);

            // Create the starting location
            MapCoordinates currentLocation = MapCoordinates.CreateUndirectional(startRow, column, dir);

            // For each row in the run
            for (int iRow = startRow; iRow <= endRow; iRow++)
            {
                // Place our terrain
                currentLocation[dir]         = iRow;
                map[currentLocation].Terrain = TerrainType.Floor;
                groom[currentLocation]       = floorChar;
            }
        }
Exemplo n.º 11
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>	Assigns a room to each floor spot on the map and adds all the rooms to the map. </summary>
        ///
        /// <remarks>	Darrellp, 9/29/2011. </remarks>
        ///
        /// <param name="map">	The map. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        private void AssignRoomsToCells(IRoomsMap map)
        {
            // For each room
            foreach (var groom in _mapRoomToGenericRooms.Values)
            {
                // Add in adjoining corridors
                // Corridors were never added to _mapRoomToGenericRooms so we have
                // to add them here

                // For each adjoining room/corridor
                foreach (var groomAdjoin in groom.NeighborRooms)
                {
                    // Add the corridor to the map
                    AssignTilesInRoom(map, groomAdjoin);
                }

                // Add the room to the map
                AssignTilesInRoom(map, groom);
            }
        }
Exemplo n.º 12
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>	Excavate rooms into the map by grid. </summary>
        ///
        /// <remarks>	Darrellp, 9/18/2011. </remarks>
        ///
        /// <exception cref="RogueException">	Thrown when the map is too small. </exception>
        ///
        /// <param name="map">	The map to be excavated. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        public void Excavate(IRoomsMap map)
        {
            // Seed the random number generator properly
            _rnd = new Rnd(_seed);

            // Are we too small to make a map?);
            if (map.Width < _baseCellWidth || map.Height < _baseCellHeight)
            {
                // Throw an exception
                throw new RogueException("Attempting to excavate with too small a map");
            }

            // Locate the rooms in the map
            LocateRooms(map);

            // Create our connections objects
            _connections = new GridConnections(_rooms.Length, _rooms[0].Length);
            _merges      = new GridConnections(_rooms.Length, _rooms[0].Length);

            // Determine which rooms should be connected
            DetermineRoomConnections();

            // Determine which rooms should be merged and resize those rooms
            DetermineRoomMerges();

            // For each column in the grid
            foreach (var room in _rooms.SelectMany(roomRow => roomRow))
            {
                // Excavate the room
                ExcavateRoom(map, room);
            }

            // Excavate between the rooms
            ExcavateRoomConnections(map);

            // Do any cleanup
            PostProcess(map);
        }
Exemplo n.º 13
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>	Excavate all corridors on the map. </summary>
        ///
        /// <remarks>	Darrellp, 9/20/2011. </remarks>
        ///
        /// <param name="map">	The map to be excavated. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        private void ExcavateRoomConnections(IRoomsMap map)
        {
            // For every connection
            foreach (var info in _connections.Connections.Where(ci => ci.IsConnected))
            {
                // Get the pertinent information
                MapCoordinates  location1 = info.Location;
                MapCoordinates  location2 = info.Location.NextLarger(info.Dir);
                RectangularRoom room1     = RoomAt(location1);
                RectangularRoom room2     = RoomAt(location2);

                // Are the rooms to be merged?
                if (_merges.IsConnected(location1, location2))
                {
                    // merge them
                    ExcavateMerge(map, room1, room2, info.Dir);
                }
                else
                {
                    // Build a corridor between them
                    ExcavateCorridor(map, room1, room2, info.Dir);
                }
            }
        }
Exemplo n.º 14
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>	Locates the rooms on the map. </summary>
        ///
        /// <remarks>	Darrellp, 9/19/2011. </remarks>
        ///
        /// <param name="map">	The map to be excavated. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        private void LocateRooms(IRoomsMap map)
        {
            // Max number of cells we can fit with at least base cell size
            int gridWidth  = map.Width / _baseCellWidth;
            int gridHeight = map.Height / _baseCellHeight;

            // Size of cells we can manage total
            int baseRoomWidth  = map.Width / gridWidth;
            int baseRoomHeight = map.Height / gridHeight;

            // Remainders for Bresenham algorithm
            int widthRemainder  = map.Width % baseRoomWidth;
            int heightRemainder = map.Height % baseRoomHeight;

            // Tally for Bresenham
            int widthTally  = gridWidth / 2;
            int heightTally = gridHeight / 2;

            // First column is on the left
            int mapColumn = 0;

            // Array of rooms in the grid
            _rooms = new RectangularRoom[gridWidth][];

            // For each grid column
            for (int gridColumn = 0; gridColumn < gridWidth; gridColumn++)
            {
                // Reset the map row to 0
                int mapRow = 0;

                // Determine the current map column
                int currentWidth = baseRoomWidth;
                widthTally += widthRemainder;

                // Do we need to bump width ala Bresenham?
                if (widthTally >= gridWidth)
                {
                    // Bump width
                    currentWidth++;
                    widthTally -= gridWidth;
                }

                // Create the row of rooms for this column
                _rooms[gridColumn] = new RectangularRoom[gridHeight];

                // For each row of the grid
                for (int gridRow = 0; gridRow < gridHeight; gridRow++)
                {
                    // Determine the current map row
                    int currentHeight = baseRoomHeight;
                    heightTally += heightRemainder;

                    // Do we need to bump height ala Bresenham?
                    if (heightTally >= gridHeight)
                    {
                        // Bump height
                        currentHeight++;
                        heightTally -= gridHeight;
                    }

                    // Create a room in the grid cell
                    MapCoordinates  gridLocation = new MapCoordinates(gridColumn, gridRow);
                    MapCoordinates  cellLocation = new MapCoordinates(mapColumn, mapRow);
                    RectangularRoom room         = CreateRoomInCell(gridLocation, cellLocation, currentWidth, currentHeight);

                    // Place it in the grid
                    _rooms[gridColumn][gridRow] = room;

                    // Advance the map row
                    mapRow += currentHeight;
                }

                // Advance the map column
                mapColumn += currentWidth;
            }
        }
Exemplo n.º 15
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>	Excavate a merge between two rooms. </summary>
        ///
        /// <remarks>
        /// Names are named as though dir was vertical and dirOther horizontal. Darrellp, 9/22/2011.
        /// </remarks>
        ///
        /// <param name="map">			The map. </param>
        /// <param name="topRoom">		The top room. </param>
        /// <param name="bottomRoom">	The bottom room. </param>
        /// <param name="dir">			The dir. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        private void ExcavateMerge(IRoomsMap map, RectangularRoom topRoom, RectangularRoom bottomRoom, Dir dir)
        {
            // Get the opposite direction
            Dir dirOther = MapCoordinates.OtherDirection(dir);

            // Are the rooms unmergable?
            if (!CheckOverlap(topRoom, bottomRoom, dirOther))
            {
                // Should have caught this in MergeTwoRooms - throw exception
                throw new RogueException("Non-overlapping rooms made it to ExcavateMerge");
            }

            // Get the appropriate coordinates
            int topRoomsLeft     = topRoom.Location[dirOther];
            int topRoomsRight    = topRoomsLeft + topRoom.Size(dirOther) - 1;
            int bottomRoomsLeft  = bottomRoom.Location[dirOther];
            int bottomRoomsRight = bottomRoomsLeft + bottomRoom.Size(dirOther) - 1;

            // Get the high and low points of the overlap
            int overlapLeft  = Math.Max(topRoomsLeft, bottomRoomsLeft) + 1;
            int overlapRight = Math.Min(topRoomsRight, bottomRoomsRight) - 1;

            // Create our new merged generic room
            GenericRoom groomTop    = _mapRoomToGenericRooms[topRoom];
            GenericRoom groomBottom = _mapRoomToGenericRooms[bottomRoom];

            groomTop.CombineWith(groomBottom);

            // For each column in the grid
            foreach (RectangularRoom[] roomColumn in _rooms)
            {
                // For each row in the grid
                for (int iRow = 0; iRow < _rooms[0].Length; iRow++)
                {
                    // Get the rect room at that spot
                    RectangularRoom room = roomColumn[iRow];

                    // Is it mapped to our defunct bottom room?
                    if (_mapRoomToGenericRooms[room] == groomBottom)
                    {
                        // Map it to our shiny new top room
                        _mapRoomToGenericRooms[room] = groomTop;
                    }
                }
            }

            // Get the location we're going to start the clearing at
            int            topRoomsBottom  = topRoom.Location[dir] + topRoom.Size(dir) - 1;
            MapCoordinates currentLocation = MapCoordinates.CreateUndirectional(topRoomsBottom, overlapLeft, dir);
            char           floorChar       = TerrainFactory.TerrainToChar(TerrainType.Floor);

            // For each spot along the overlap
            for (int iCol = overlapLeft; iCol <= overlapRight; iCol++)
            {
                // Clear out the two walls of the abutting rooms
                currentLocation[dirOther]    = iCol;
                map[currentLocation].Terrain = TerrainType.Floor;
                groomTop[currentLocation]    = floorChar;
                currentLocation[dir]         = topRoomsBottom + 1;
                map[currentLocation].Terrain = TerrainType.Floor;
                groomTop[currentLocation]    = floorChar;
                currentLocation[dir]         = topRoomsBottom;
            }
            Debug.Assert(groomBottom == groomTop || !_mapRoomToGenericRooms.ContainsValue(groomBottom));
        }