예제 #1
0
        /// <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;
 }
예제 #3
0
        /// <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));
        }
예제 #4
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);
            }
        }
예제 #5
0
 /// <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;
 }
예제 #6
0
        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;
        }
예제 #7
0
        /// <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));
        }
예제 #8
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);
        }
예제 #9
0
        /// <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));
        }
예제 #10
0
        /// <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.");
        }
예제 #12
0
        /// <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));
        }
예제 #13
0
        /// <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));
        }
예제 #14
0
        /// <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="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;
        }
예제 #17
0
 /// <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;
 }
예제 #18
0
 /// <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);
 }
예제 #19
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);
        }
예제 #20
0
 /// <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);
예제 #21
0
 /// <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);
 }
예제 #22
0
 /// <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;
 }
예제 #23
0
        /// <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));
        }
예제 #24
0
 /// <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);
예제 #25
0
        /// <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);
        }
예제 #26
0
        /// <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));
        }
예제 #27
0
        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);
        }
예제 #28
0
 /// <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;
 }
예제 #29
0
        /// <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);
        }
예제 #30
0
        /// <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));
        }