/// <summary> /// Adds the occupant to this instance. /// </summary> /// <param name="character">The character.</param> /// <exception cref="System.NullReferenceException">Attempted to add a null character to the Room.</exception> public void MoveOccupantToRoom(ICharacter character, DefaultRoom departingRoom) { // We don't allow the user to enter a disabled room. if (!this.IsEnabled) { // TODO: Need to do some kind of communication back to the caller that this can't be traveled to. throw new InvalidOperationException("The room is disabled and can not be traveled to."); } if (character == null) { throw new NullReferenceException("Attempted to add a null character to the Room."); } // Remove the character from their previous room. //Find the doorway that the character traveled through DefaultDoorway doorwayTraveledThrough = departingRoom?.Doorways.FirstOrDefault(door => door.ArrivalRoom == this); // Get the opposite direction of the doorways travel direction. This will be the direction that they entered from // within this instance's available entry points. ITravelDirection enteredDirection = doorwayTraveledThrough?.DepartureDirection.GetOppositeDirection(); // Handle removing the occupant from the previous room. The character might handle this for us // so our RemoveOccupantFromRoom implementation will try to remove safely. departingRoom?.TryRemoveOccupantFromRoom(character, doorwayTraveledThrough.DepartureDirection, this); this.Occupants.Add(character); character.Deleted += this.OnCharacterDeletingStarting; // Notify our event handles that the character has entered the room. this.OnEnteringRoom(character, enteredDirection, departingRoom); character.Move(enteredDirection, this); }
/// <summary> /// Initializes a new instance of the <see cref="OccupancyChangedEventArgs"/> class. /// </summary> /// <param name="occupant">The occupant.</param> /// <param name="departureRoom">The departure room.</param> /// <param name="arrivalRoom">The arrival room.</param> public OccupancyChangedEventArgs(ICharacter occupant, ITravelDirection travelDirection, DefaultRoom departureRoom, DefaultRoom arrivalRoom) { this.Occupant = occupant; this.DepartureRoom = departureRoom; this.ArrivalRoom = arrivalRoom; this.TravelDirection = travelDirection; }
/// <summary> /// Connects a departing room to a doorawy. /// </summary> /// <param name="departureDirection">The direction need to travel in order to leave the departure room.</param> /// <param name="departureRoom">The room that an IActor would be departing from.</param> /// <returns> /// Returns an awaitable Task /// </returns> public Task ConnectRoom(ITravelDirection departureDirection, IRoom departureRoom) { this.DepartureDirection = departureDirection; this.DepartureRoom = departureRoom; return(Task.FromResult(0)); }
/// <summary> /// Connects two rooms together. /// </summary> /// <param name="departureRoom">The departure room.</param> /// <param name="arrivalRoom">The arrival room.</param> /// <param name="createDoorwayForArrival">If set to <c>true</c>, a new doorway will be created for the arrival room that is linked back to the originating departure room. /// Otherwise, a one-way door will be created.</param> /// <exception cref="System.NullReferenceException"> /// Neither the departure room or arrival room can be null /// or /// Can not connect rooms when the DepartureDirection is null. /// or /// Can not connect rooms when the doorways collection is null. /// </exception> public virtual void ConnectRooms(DefaultRoom departureRoom, DefaultRoom arrivalRoom, bool createDoorwayForArrival = true) { ExceptionFactory .ThrowIf <ArgumentNullException>( departureRoom == null || arrivalRoom == null, "Neither the departure room or arrival room can be null") .Or <NullReferenceException>( this.DepartureDirection == null, "Can not connect rooms when the DepartureDirection is null.") .Or( departureRoom.Doorways == null, "Can not connect rooms when the doorways collection is null."); // Set up the departure room first. this.ArrivalRoom = arrivalRoom; this.DepartureRoom = departureRoom; departureRoom.Doorways.Add(this); // The opposite rooms arrival needs to be the departing room that this doorway is connected to. if (createDoorwayForArrival) { // Create a new doorway for the arrival room, so that you can leave the room once you are in it. ITravelDirection oppositeDirection = this.DepartureDirection.GetOppositeDirection(); // TODO: Create the doorway from a factory call. DefaultDoorway arrivalDoorway = new DefaultDoorway(oppositeDirection); arrivalDoorway.ConnectRooms(arrivalRoom, departureRoom, false); } }
public async Task<IDoorway> CreateDoor(string doorwayName, IRoom departureRoom, ITravelDirection travelDirection) { var doorway = new MudDoor(); await doorway.ConnectRoom(travelDirection, departureRoom); doorway.SetName(doorwayName); return doorway; }
/// <summary> /// Connects the departing room to the arrival room. /// </summary> /// <param name="departureDirection">The departure direction.</param> /// <param name="departureRoom">The room that an IActor would be departing from.</param> /// <param name="arrivalRoom">The room that an IActor would be arriving into during travel.</param> /// <returns> /// Returns an awaitable Task /// </returns> /// <para> /// This connection is one-way. Actors can not travel back to the departing room. /// </para> public Task ConnectRooms(ITravelDirection departureDirection, IRoom departureRoom, IRoom arrivalRoom) { this.ArrivalRoom = arrivalRoom; this.DepartureRoom = departureRoom; this.DepartureDirection = departureDirection; return(Task.FromResult(0)); }
/// <summary> /// Removes the occupant from room. /// </summary> /// <param name="character">The character.</param> /// <param name="arrivalRoom">The arrival room.</param> protected void TryRemoveOccupantFromRoom(ICharacter character, ITravelDirection leavingDirection, DefaultRoom arrivalRoom) { if (character == null) { return; } this.Occupants.Remove(character); this.OnLeavingRoom(character, leavingDirection, arrivalRoom); }
/// <summary> /// Called when a character enters this room. /// </summary> /// <param name="character">The character.</param> /// <param name="departingRoom">The departing room.</param> protected virtual void OnEnteringRoom(ICharacter character, ITravelDirection enteringDirection, DefaultRoom departingRoom) { EventHandler <OccupancyChangedEventArgs> handler = this.EnteredRoom; if (handler == null) { return; } handler(this, new OccupancyChangedEventArgs(character, enteringDirection, departingRoom, this)); }
/// <summary> /// Called when the character changes rooms. /// </summary> /// <param name="departingRoom">The departing room.</param> /// <param name="arrivalRoom">The arrival room.</param> protected virtual void OnRoomChanged(ITravelDirection direction, DefaultRoom departingRoom, DefaultRoom arrivalRoom) { EventHandler <OccupancyChangedEventArgs> handler = this.RoomChanged; if (handler == null) { return; } handler(this, new OccupancyChangedEventArgs(this, direction, departingRoom, arrivalRoom)); }
public void NorthDirection_has_correct_reverse_direction() { // Arrange var direction = new NorthDirection(); // Act ITravelDirection reverseDirection = direction.GetOppositeDirection(); // Assert Assert.AreEqual("South", reverseDirection.Direction, "The opposite travel direction was not correctly returned."); }
/// <summary> /// Called when a character leaves this room. /// </summary> /// <param name="character">The character.</param> /// <param name="arrivalRoom">The arrival room.</param> protected virtual void OnLeavingRoom(ICharacter character, ITravelDirection enteringDirection, DefaultRoom arrivalRoom) { EventHandler <OccupancyChangedEventArgs> handler = this.LeftRoom; if (handler == null) { return; } handler(this, new OccupancyChangedEventArgs(character, enteringDirection, this, arrivalRoom)); }
/// <summary> /// Removes the doorway associated with the travel direction given. /// </summary> /// <param name="travelDirection">The travel direction that must be removed from the room.</param> /// <returns>Returns an awaitable Task</returns> public Task RemoveDoorwayFromRoom(ITravelDirection travelDirection) { if (travelDirection == null) { return(Task.FromResult(0)); } IDoorway door = this.doorways.FirstOrDefault(d => d.DepartureDirection == travelDirection); if (door == null) { throw new InvalidOperationException($"The {travelDirection.Direction} travel direction does not have a door assigned to it in {this.Name}"); } return(this.RemoveDoorwayFromRoom(door)); }
/// <summary> /// Connects the departing room to the arrival room, allowing actors to travel between the two rooms. /// </summary> /// <param name="departureDirection">The departure direction.</param> /// <param name="departureRoom">The room that an IActor would be departing from.</param> /// <param name="arrivalRoom">The room that an IActor would be arriving into during travel.</param> /// <param name="autoCreateReverseDoorway">if set to <c>true</c> a doorway will be added to the arrival room so actors can travel back to the departing room.</param> /// <returns> /// Returns an awaitable Task /// </returns> /// <para> /// This connection can be set to either one-way or two way, allowing or disallowing /// Actors the ability to travel back to the departing room. /// </para> public async Task ConnectRooms(ITravelDirection departureDirection, IRoom departureRoom, IRoom arrivalRoom, bool autoCreateReverseDoorway) { this.DepartureDirection = departureDirection; this.ArrivalRoom = arrivalRoom; if (!autoCreateReverseDoorway) { return; } IDoorway oppositeDoorway = await arrivalRoom.CreateDoorway(departureDirection.GetOppositeDirection()); await oppositeDoorway.ConnectRoom(departureRoom); await arrivalRoom.AddDoorwayToRoom(oppositeDoorway); }
/// <summary> /// Initializes a new instance of the <see cref="RoomOccupancyChangedEventArgs" /> class. /// </summary> /// <param name="occupant">The occupant responsible for the change.</param> /// <param name="travelDirection">The direction of travel the occupant is going.</param> /// <param name="departureRoom">The room the occupant is departing from.</param> /// <param name="arrivalRoom">The room the occupant is arriving in.</param> /// <exception cref="System.ArgumentNullException"> /// A valid Occupant must be provided. /// or /// A valid travelDirection must be provided. /// or /// A valid departureRoom must be provided. /// or /// A valid arrivalRoom must be provided. /// </exception> public RoomOccupancyChangedEventArgs(ICharacter occupant, ITravelDirection travelDirection, IRoom departureRoom, IRoom arrivalRoom) { if (occupant == null) { throw new ArgumentNullException(nameof(occupant), "A valid Occupant must be provided."); } else if (travelDirection == null) { throw new ArgumentNullException(nameof(travelDirection), "A valid travelDirection must be provided."); } else if (departureRoom == null) { throw new ArgumentNullException(nameof(departureRoom), "A valid departureRoom must be provided."); } else if (arrivalRoom == null) { throw new ArgumentNullException(nameof(arrivalRoom), "A valid arrivalRoom must be provided."); } this.Occupant = occupant; this.DepartureRoom = departureRoom; this.ArrivalRoom = arrivalRoom; this.TravelDirection = travelDirection; }
/// <summary> /// Initializes a new instance of the <see cref="DefaultDoorway"/> class. /// </summary> /// <param name="departureDirection">The departure direction.</param> public DefaultDoorway(ITravelDirection departureDirection) { ExceptionFactory.ThrowIf<ArgumentNullException>(departureDirection == null); this.DepartureDirection = departureDirection; }
/// <summary> /// Moves this character to the given room going in the specified direction. /// </summary> /// <param name="directionEnteringFrom">The direction.</param> /// <param name="newRoom">The new room.</param> public void Move(ITravelDirection directionEnteringFrom, DefaultRoom newRoom) { this.CurrentRoom = newRoom; this.OnRoomChanged(directionEnteringFrom, this.CurrentRoom, newRoom); }
/// <summary> /// Creates a doorway that can be configured and be connected to any room. /// </summary> /// <param name="travelDirectionToReachDoor">The travel direction an actor must travel in order to reach the door.</param> /// <returns>Returns a valid instance of an IDoorway implementation</returns> public Task<IDoorway> CreateDoorway(ITravelDirection travelDirectionToReachDoor) => this.doorFactory.CreateDoor($"{this.Name} doorway for the {travelDirectionToReachDoor.ToString()} direction", this, travelDirectionToReachDoor);
/// <summary> /// Initializes a new instance of the <see cref="DefaultDoorway"/> class. /// </summary> /// <param name="departureDirection">The departure direction.</param> public DefaultDoorway(ITravelDirection departureDirection) { ExceptionFactory.ThrowIf <ArgumentNullException>(departureDirection == null); this.DepartureDirection = departureDirection; }
/// <summary> /// Called when the character changes rooms. /// </summary> /// <param name="departingRoom">The departing room.</param> /// <param name="arrivalRoom">The arrival room.</param> protected virtual void OnRoomChanged(ITravelDirection direction, DefaultRoom departingRoom, DefaultRoom arrivalRoom) { EventHandler<OccupancyChangedEventArgs> handler = this.RoomChanged; if (handler == null) { return; } handler(this, new OccupancyChangedEventArgs(this, direction, departingRoom, arrivalRoom)); }
/// <summary> /// Creates a doorway that can be configured and be connected to any room. /// </summary> /// <param name="travelDirectionToReachDoor">The travel direction an actor must travel in order to reach the door.</param> /// <returns>Returns a valid instance of an IDoorway implementation</returns> public Task <IDoorway> CreateDoorway(ITravelDirection travelDirectionToReachDoor) => this.doorFactory.CreateDoor($"{this.Name} doorway for the {travelDirectionToReachDoor.ToString()} direction", this, travelDirectionToReachDoor);
/// <summary> /// Removes the doorway associated with the travel direction given. /// </summary> /// <param name="travelDirection">The travel direction that must be removed from the room.</param> /// <returns>Returns an awaitable Task</returns> public Task RemoveDoorwayFromRoom(ITravelDirection travelDirection) { if (travelDirection == null) { return Task.FromResult(0); } IDoorway door = this.doorways.FirstOrDefault(d => d.DepartureDirection == travelDirection); if (door == null) { throw new InvalidOperationException($"The {travelDirection.Direction} travel direction does not have a door assigned to it in {this.Name}"); } return this.RemoveDoorwayFromRoom(door); }
/// <summary> /// Called when a character leaves this room. /// </summary> /// <param name="character">The character.</param> /// <param name="arrivalRoom">The arrival room.</param> protected virtual void OnLeavingRoom(ICharacter character, ITravelDirection enteringDirection, DefaultRoom arrivalRoom) { EventHandler<OccupancyChangedEventArgs> handler = this.LeftRoom; if (handler == null) { return; } handler(this, new OccupancyChangedEventArgs(character, enteringDirection, this, arrivalRoom)); }
public async Task <IDoorway> CreateDoor(string doorwayName, IRoom departureRoom, ITravelDirection travelDirection) { var doorway = new MudDoor(); await doorway.ConnectRoom(travelDirection, departureRoom); doorway.SetName(doorwayName); return(doorway); }
/// <summary> /// Creates an uninitialized instance of a doorway, connected to a departing and arrival room. /// A doorway will be created for both rooms, linking them together from both ends /// </summary> /// <param name="arrivalRoom">The room that an IActor would be arriving into during travel.</param> /// <param name="departureRoom">The room that an IActor would be departing from.</param> /// <param name="travelDirection">The direction need to travel in order to leave the departure room.</param> /// <returns>Returns an uninitialized doorway</returns> public async Task<IDoorway> CreateTwoWayDoor(string doorwayName, IRoom arrivalRoom, IRoom departureRoom, ITravelDirection travelDirection) { var doorway = new MudDoor(); await doorway.ConnectRooms(travelDirection, departureRoom, arrivalRoom, true); return doorway; }
/// <summary> /// Creates an uninitialized instance of a doorway, connected to a departing and arrival room. /// A doorway will be created for both rooms, linking them together from both ends /// </summary> /// <param name="arrivalRoom">The room that an IActor would be arriving into during travel.</param> /// <param name="departureRoom">The room that an IActor would be departing from.</param> /// <param name="travelDirection">The direction need to travel in order to leave the departure room.</param> /// <returns>Returns an uninitialized doorway</returns> public async Task <IDoorway> CreateTwoWayDoor(string doorwayName, IRoom arrivalRoom, IRoom departureRoom, ITravelDirection travelDirection) { var doorway = new MudDoor(); await doorway.ConnectRooms(travelDirection, departureRoom, arrivalRoom, true); return(doorway); }
/// <summary> /// Called when a character enters this room. /// </summary> /// <param name="character">The character.</param> /// <param name="departingRoom">The departing room.</param> protected virtual void OnEnteringRoom(ICharacter character, ITravelDirection enteringDirection, DefaultRoom departingRoom) { EventHandler<OccupancyChangedEventArgs> handler = this.EnteredRoom; if (handler == null) { return; } handler(this, new OccupancyChangedEventArgs(character, enteringDirection, departingRoom, this)); }