Exemple #1
0
		public bool HasAdjacentCellInDirection(Vector2I location, Direction direction)
		{
			// Check that the location falls within the bounds of the map:
			if (!Bounds.Contains(location))
			{
				return false;
			}

			// Check if there is an adjacent cell in the direction:
			if (direction.Equals(Direction.North))
			{
				return location.Y > 0;
			}
			else if (direction.Equals(Direction.South))
			{
				return location.Y < (Rows - 1);
			}
			else if (direction.Equals(Direction.West))
			{
				return location.X > 0;
			}
			else if (direction.Equals(Direction.East))
			{
				return location.X < (Columns - 1);
			}
			else
			{
				return false;
			}
		}
Exemple #2
0
		public void SetLocation(Vector2I location)
		{
			var bounds = Bounds;
			bounds.X = location.X;
			bounds.Y = location.Y;
			Bounds = bounds;
		}
Exemple #3
0
		/// <summary>
		/// Is this given point in one of the room's corners?
		/// </summary>
		/// <remarks>
		/// A corner cannot be walked to, so it is a bad place to put a door.
		/// </remarks>
		public bool IsPointInCorner(Vector2I point)
		{
			return
				(point == Bounds.TopLeft) ||
				(point == Bounds.TopRight) ||
				(point == Bounds.BottomLeft) ||
				(point == Bounds.BottomRight);
		}
Exemple #4
0
		/// <summary>
		/// Is this given point on this room's boundary?
		/// </summary>
		/// <remarks>
		/// The room will generate walls on it's boundary,
		/// so if this returns true it may be a good place to put a door.
		/// </remarks>
		public bool IsPointOnBounds(Vector2I point)
		{
			return
				(point.X == Bounds.Left) ||
				(point.X == Bounds.Right) ||
				(point.Y == Bounds.Top) ||
				(point.Y == Bounds.Bottom);
		}
Exemple #5
0
		public Cell this[Vector2I location]
		{
			get
			{
				return this[location.Row, location.Column];
			}
			set
			{
				this[location.Row, location.Column] = value;
			}
		}
		private void PlaceDoors(LabyrinthDungeon dungeon)
		{
			foreach (var room in dungeon.Rooms)
			{
				var hasNorthDoor = false;
				var hasSouthDoor = false;
				var hasWestDoor = false;
				var hasEastDoor = false;

				// TODO: Convert this into 4 loops on the sides of the room.
				for (var row = 0; row < room.Rows; row++)
				{
					for (var column = 0; column < room.Columns; column++)
					{
						var cellLocation = new Vector2I(column, row);

						// Translate the room cell location to its location in the dungeon:
						var dungeonLocation = new Vector2I(room.Bounds.X, room.Bounds.Y) + cellLocation;

						// Check if we are on the west boundary of our roomand if there is a corridor to the west:
						if (!hasWestDoor && (cellLocation.X == 0) &&
							dungeon.AdjacentCellInDirectionIsCorridor(dungeonLocation, Direction.West))
						{
							dungeon.CreateDoor(dungeonLocation, Direction.West);
							hasWestDoor = true;
						}

						// Check if we are on the east boundary of our room and if there is a corridor to the east
						if (!hasEastDoor && (cellLocation.X == room.Columns - 1) &&
							dungeon.AdjacentCellInDirectionIsCorridor(dungeonLocation, Direction.East))
						{
							dungeon.CreateDoor(dungeonLocation, Direction.East);
							hasEastDoor = true;
						}

						// Check if we are on the north boundary of our room and if there is a corridor to the north
						if (!hasNorthDoor && (cellLocation.Y == 0) &&
							dungeon.AdjacentCellInDirectionIsCorridor(dungeonLocation, Direction.North))
						{
							dungeon.CreateDoor(dungeonLocation, Direction.North);
							hasNorthDoor = true;
						}

						// Check if we are on the south boundary of our room and if there is a corridor to the south
						if (!hasSouthDoor && (cellLocation.Y == room.Rows - 1) &&
							dungeon.AdjacentCellInDirectionIsCorridor(dungeonLocation, Direction.South))
						{
							dungeon.CreateDoor(dungeonLocation, Direction.South);
							hasSouthDoor = true;
						}
					}
				}
			}
		}
		private int CalculateRoomPlacementScore(Vector2I location, LabyrinthDungeon dungeon, Room room)
		{
			// Check if the room at the given location will fit inside the bounds of the map.
			if (Contains(dungeon.Bounds, location, room))
			{
				var roomPlacementScore = 0;

				// Loop for each cell in the room.
				for (var column = 0; column < room.Columns; column++)
				{
					for (var row = 0; row < room.Rows; row++)
					{
						// Translate the room cell location to its location in the dungeon.
						var dungeonLocation = location + new Vector2I(column, row);

						// Add 1 point for each adjacent corridor to the cell.
						if (dungeon.AdjacentCellInDirectionIsCorridor(dungeonLocation, Direction.North))
						{
							roomPlacementScore++;
						}
						if (dungeon.AdjacentCellInDirectionIsCorridor(dungeonLocation, Direction.South))
						{
							roomPlacementScore++;
						}
						if (dungeon.AdjacentCellInDirectionIsCorridor(dungeonLocation, Direction.West))
						{
							roomPlacementScore++;
						}
						if (dungeon.AdjacentCellInDirectionIsCorridor(dungeonLocation, Direction.East))
						{
							roomPlacementScore++;
						}

						// Add 3 points if the cell overlaps an existing corridor.
						if (dungeon[dungeonLocation].IsCorridor)
						{
							roomPlacementScore += 3;
						}

						// Add 100 points if the cell overlaps any existing room cells.
						foreach (var dungeonRoom in dungeon.Rooms)
						{
							if (dungeonRoom.Bounds.Contains(dungeonLocation))
							{
								roomPlacementScore += 100;
							}
						}
					}
				}

				return roomPlacementScore;
			}
			else
			{
				return int.MaxValue;
			}
		}
		private bool Contains(RectI bounds, Vector2I roomLocation, Room room)
		{
			return
				bounds.Contains(roomLocation.X, roomLocation.Y) &&
				bounds.Contains(roomLocation.X + room.Columns - 1, roomLocation.Y) &&
				bounds.Contains(roomLocation.X + room.Columns - 1, roomLocation.Y + room.Rows - 1) &&
				bounds.Contains(roomLocation.X, roomLocation.Y + room.Rows - 1);
		}
Exemple #9
0
		public static Direction FromVector(Vector2I v)
		{
			v = v.Normalized;
			if (v.Equals(-Vector2I.UnitY))
			{
				return North;
			}
			if (v.Equals(Vector2I.UnitY))
			{
				return South;
			}
			if (v.Equals(Vector2I.UnitX))
			{
				return East;
			}
			if (v.Equals(-Vector2I.UnitX))
			{
				return West;
			}

			return North;
		}
		private Chunk ExcavateRooms(Chunk chunk, LabyrinthDungeon dungeon, IProgress<string> progress)
		{
			progress.Report("Excavating room...");
			progress.Report($"Room count: {dungeon.Rooms.Count}");
			// Fill tiles with corridor values for each room in dungeon.
			foreach (var room in dungeon.Rooms)
			{
				// Get the room min and max location in tile coordinates.
				var right = room.Bounds.X + room.Bounds.Width - 1;
				var bottom = room.Bounds.Y + room.Bounds.Height - 1;
				var minPoint = new Vector2I(room.Bounds.X * 2 + 1, room.Bounds.Y * 2 + 1);
				var maxPoint = new Vector2I(right * 2, bottom * 2);

				// Fill the room in tile space with an empty value.
				for (var row = minPoint.Y; row <= maxPoint.Y; row++)
				{
					for (var column = minPoint.X; column <= maxPoint.X; column++)
					{
						ExcavateChunkPoint(chunk, new Vector2I(column, row));
					}
				}
			}
			progress.Report("Room complete!");

			return chunk;
		}
		private void ExcavateChunkPoint(Chunk chunk, Vector2I chunkPoint)
		{
			chunk[ChunkLayer.Blocking, chunkPoint.X, chunkPoint.Y] = 0;
		}
Exemple #12
0
		protected Vector2I GetTargetLocation(Vector2I location, Direction direction)
		{
			if (!HasAdjacentCellInDirection(location, direction))
			{
				throw new InvalidOperationException("No adjacent cell exists for the location and direction provided.");
			}

			if (direction.Equals(Direction.North))
			{
				return location - Vector2I.UnitY;
			}
			else if (direction.Equals(Direction.South))
			{
				return location + Vector2I.UnitY;
			}
			else if (direction.Equals(Direction.West))
			{
				return location - Vector2I.UnitX;
			}
			else if (direction.Equals(Direction.East))
			{
				return location + Vector2I.UnitX;
			}
			else
			{
				throw new InvalidOperationException("No adjacent cell exists for the location and direction provided.");
			}
		}
		public Vector2I CreateWall(Vector2I location, Direction direction)
		{
			return CreateSide(location, direction, SideType.Wall);
		}
		public Vector2I CreateCorridor(Vector2I location, Direction direction)
		{
			return CreateSide(location, direction, SideType.Empty);
		}
		public Vector2I GetRandomVisitedCell(Vector2I location, Random random)
		{
			if (!_visitedCells.Any())
			{
				throw new InvalidOperationException("There are no visited cells to return.");
			}

			var index = random.Next(_visitedCells.Count);

			// Loop while the current cell is the visited cell:
			while (_visitedCells[index] == location)
			{
				index = random.Next(_visitedCells.Count);
			}

			return _visitedCells[index];
		}
		private bool LocationIsOutsideBounds(Vector2I location)
		{
			return ((location.X < 0) || (location.X >= Columns) || (location.Y < 0) || (location.Y >= Rows));
		}
		public void FlagCellAsVisited(Vector2I location)
		{
			if (LocationIsOutsideBounds(location))
			{
				throw new Exception("Location is outside of map bounds.");
			}
			if (this[location].Visited)
			{
				throw new Exception("Location is already visited.");
			}
			else
			{
				this[location].Visited = true;
				_visitedCells.Add(location);
			}
		}
		public bool AdjacentCellInDirectionIsCorridor(Vector2I location, Direction direction)
		{
			if (!HasAdjacentCellInDirection(location, direction))
			{
				return false;
			}
			var target = GetTargetLocation(location, direction);
			return this[target].IsCorridor;
		}
		public bool AdjacentCellInDirectionIsVisited(Vector2I location, Direction direction)
		{
			if (!HasAdjacentCellInDirection(location, direction))
			{
				throw new InvalidOperationException("No adjacent cell exists for the location and direction provided.");
			}
			return this[location + direction.ToVector2I()].Visited;
		}
		private bool InBounds(Vector2I v)
		{
			return this.InBounds(v.X, v.Y);
		}
		public Vector2I CreateDoor(Vector2I location, Direction direction)
		{
			return CreateSide(location, direction, SideType.Door);
		}
		private Chunk ExcavateCorridors(Chunk chunk, LabyrinthDungeon dungeon)
		{
			// Loop for each corridor cell and expand it.
			foreach (var cellLocation in dungeon.CorridorCellLocations)
			{
				var tileLocation = new Vector2I(cellLocation.X * 2 + 1, cellLocation.Y * 2 + 1);
				ExcavateChunkPoint(chunk, new Vector2I(tileLocation.X, tileLocation.Y));

				if (dungeon[cellLocation].NorthSide == SideType.Empty)
				{
					ExcavateChunkPoint(chunk, new Vector2I(tileLocation.X, tileLocation.Y - 1));
				}
				else if (dungeon[cellLocation].NorthSide == SideType.Door)
				{
					ExcavateChunkPoint(chunk, new Vector2I(tileLocation.X, tileLocation.Y - 1));
					chunk[ChunkLayer.Blocking, tileLocation.X, tileLocation.Y - 1] = _doorId;
				}

				if (dungeon[cellLocation].SouthSide == SideType.Empty)
				{
					ExcavateChunkPoint(chunk, new Vector2I(tileLocation.X, tileLocation.Y + 1));
				}
				else if (dungeon[cellLocation].SouthSide == SideType.Door)
				{
					ExcavateChunkPoint(chunk, new Vector2I(tileLocation.X, tileLocation.Y + 1));
					chunk[ChunkLayer.Blocking, tileLocation.X, tileLocation.Y + 1] = _doorId;
				}

				if (dungeon[cellLocation].WestSide == SideType.Empty)
				{
					ExcavateChunkPoint(chunk, new Vector2I(tileLocation.X - 1, tileLocation.Y));
				}
				else if (dungeon[cellLocation].WestSide == SideType.Door)
				{
					ExcavateChunkPoint(chunk, new Vector2I(tileLocation.X - 1, tileLocation.Y));
					chunk[ChunkLayer.Blocking, tileLocation.X - 1, tileLocation.Y] = _doorId;
				}

				if (dungeon[cellLocation].EastSide == SideType.Empty)
				{
					ExcavateChunkPoint(chunk, new Vector2I(tileLocation.X + 1, tileLocation.Y));
				}
				else if (dungeon[cellLocation].EastSide == SideType.Door)
				{
					ExcavateChunkPoint(chunk, new Vector2I(tileLocation.X + 1, tileLocation.Y));
					chunk[ChunkLayer.Blocking, tileLocation.X + 1, tileLocation.Y] = _doorId;
				}
			}

			return chunk;
		}
		private IEnumerable<Tuple<Vector2I, Direction, Tile>> GetSurroundings(Vector2I v)
		{
			return
				this.GetSurroundingPoints(v)
					.Select(r => Tuple.Create(r.Item1, r.Item2, this.GetCellType(r.Item1.X, r.Item1.Y)));
		}
		private bool IsDoorAdjacent(Chunk chunk, Vector2I chunkPoint)
		{
			var north = chunk[ChunkLayer.Blocking, chunkPoint.X, chunkPoint.Y - 1];
			var south = chunk[ChunkLayer.Blocking, chunkPoint.X, chunkPoint.Y + 1];
			var east = chunk[ChunkLayer.Blocking, chunkPoint.X + 1, chunkPoint.Y];
			var west = chunk[ChunkLayer.Blocking, chunkPoint.X - 1, chunkPoint.Y];

			return (north == _doorId) || (south == _doorId) || (east == _doorId) || (west == _doorId);
		}
		private void PlaceRoom(Vector2I location, LabyrinthDungeon dungeon, Room room)
		{
			// Offset the room origin to the new location.
			room.SetLocation(location);

			// Loop for each cell in the room
			for (var row = 0; row < room.Rows; row++)
			{
				for (var column = 0; column < room.Columns; column++)
				{
					// Translate the room cell location to its location in the dungeon.
					var dungeonLocation = location + new Vector2I(column, row);
					dungeon[dungeonLocation].NorthSide = room[row, column].NorthSide;
					dungeon[dungeonLocation].SouthSide = room[row, column].SouthSide;
					dungeon[dungeonLocation].WestSide = room[row, column].WestSide;
					dungeon[dungeonLocation].EastSide = room[row, column].EastSide;

					// TODO: This part may be unnecessary.
					// Create room walls on map (either side of the wall)
					if ((column == 0) && (dungeon.HasAdjacentCellInDirection(dungeonLocation, Direction.West)))
					{
						dungeon.CreateWall(dungeonLocation, Direction.West);
					}
					if ((column == room.Columns - 1) && (dungeon.HasAdjacentCellInDirection(dungeonLocation, Direction.East)))
					{
						dungeon.CreateWall(dungeonLocation, Direction.East);
					}
					if ((row == 0) && (dungeon.HasAdjacentCellInDirection(dungeonLocation, Direction.North)))
					{
						dungeon.CreateWall(dungeonLocation, Direction.North);
					}
					if ((row == room.Rows - 1) && (dungeon.HasAdjacentCellInDirection(dungeonLocation, Direction.South)))
					{
						dungeon.CreateWall(dungeonLocation, Direction.South);
					}
				}
			}

			dungeon.Rooms.Add(room);
		}
		private Vector2I CreateSide(Vector2I location, Direction direction, SideType sideType)
		{
			var target = GetTargetLocation(location, direction);

			if (direction.Equals(Direction.North))
			{
				this[location].NorthSide = sideType;
				this[target].SouthSide = sideType;
			}
			else if (direction.Equals(Direction.South))
			{
				this[location].SouthSide = sideType;
				this[target].NorthSide = sideType;
			}
			else if (direction.Equals(Direction.West))
			{
				this[location].WestSide = sideType;
				this[target].EastSide = sideType;
			}
			else if (direction.Equals(Direction.East))
			{
				this[location].EastSide = sideType;
				this[target].WestSide = sideType;
			}

			return target;
		}
Exemple #27
0
		private Direction(Vector2I v)
		{
			_vector = v.Normalized;
		}
		public Vector2I PickRandomCellAndMarkItVisited(Random random)
		{
			var pnt = new Vector2I(random.Next(Columns), random.Next(Rows));
			FlagCellAsVisited(pnt);
			return pnt;
		}
		private IEnumerable<Tuple<Vector2I, Direction>> GetSurroundingPoints(Vector2I v)
		{
			var points = new[]
							 {
								 Tuple.Create(new Vector2I(v.X, v.Y + 1), Direction.North),
								 Tuple.Create(new Vector2I(v.X - 1, v.Y), Direction.East),
								 Tuple.Create(new Vector2I(v.X , v.Y-1), Direction.South),
								 Tuple.Create(new Vector2I(v.X +1, v.Y), Direction.West),

							 };
			return points.Where(p => InBounds(p.Item1));
		}