/// <summary> /// Returns a sequence of IDs of obstacles that have been destroyed in the current room since entering. /// May be empty if the in-room state is not being tracked. /// </summary> /// <param name="usePreviousRoom">If true, uses the last known room state at the previous room instead of the current room to answer.</param> /// <returns></returns> public IEnumerable <string> GetDestroyedObstacleIds(bool usePreviousRoom = false) { InRoomState roomState = usePreviousRoom ? PreviousRoomState : InRoomState; IEnumerable <string> returnValue = roomState?.DestroyedObstacleIds; return(returnValue == null?Enumerable.Empty <string>() : returnValue); }
/// <summary> /// Returns a sequence of IDs of nodes that have been visited in the current room since entering, in order, /// starting with the node through which the room was entered. May be empty if the in-room state is not being tracked. /// </summary> /// <param name="usePreviousRoom">If true, uses the last known room state at the previous room instead of the current room to answer.</param> /// <returns></returns> public IEnumerable <int> GetVisitedNodeIds(bool usePreviousRoom = false) { InRoomState roomState = usePreviousRoom ? PreviousRoomState : InRoomState; IEnumerable <int> returnValue = roomState?.VisitedRoomPath?.Select(pathNode => pathNode.node.Id); return(returnValue == null?Enumerable.Empty <int>() : returnValue); }
/// <summary> /// Returns a sequence of nodes that have been visited in this room since entering, in order, /// starting with the node through which the room was entered. May be empty if the in-room state is not being tracked. /// Each node ID is accompanied by the strat that was used to reach it, when applicable. /// This strat can be null since nodes are reached without using a strat when entering. /// </summary> /// <param name="usePreviousRoom">If true, uses the last known room state at the previous room instead of the current room to answer.</param> /// <returns></returns> public IEnumerable <(RoomNode node, Strat strat)> GetVisitedPath(bool usePreviousRoom = false) { InRoomState roomState = usePreviousRoom ? PreviousRoomState : InRoomState; var returnValue = roomState?.VisitedRoomPath; return(returnValue == null?Enumerable.Empty <(RoomNode, Strat)>() : returnValue); }
// STITCHME It might be valuable to eventually have InGameState be able to say which nodes are reachable? // STITCHME It could be nice to keep track of all canResets in the room and evaluate them as you move around? // Another option would be to have something in an initialization phase that converts canResets into just names, // and adds information on nodes and strats that they invalidate the canReset. // We'll see when we get to the step of reducing logical elements *shrug* /// <summary> /// Creates a new InGameState /// </summary> /// <param name="model">A SuperMetroidModel. Its rooms must have both been set and initialized. /// Its items and game flags must also have been set.</param> /// <param name="itemContainer">The result of reading the items.json file.</param> public InGameState(SuperMetroidModel model, ItemContainer itemContainer) { IEnumerable <ResourceCapacity> startingResources = itemContainer.StartingResources; Inventory = new ItemInventory(startingResources); Resources = new ResourceCount(); // Start the player at full foreach (ResourceCapacity capacity in startingResources) { Resources.ApplyAmountIncrease(capacity.Resource, capacity.MaxAmount); } // Initialize starting game flags foreach (string gameFlagName in itemContainer.StartingGameFlagNames) { ApplyAddGameFlag(model.GameFlags[gameFlagName]); } // Initialize starting items foreach (string itemName in itemContainer.StartingItemNames) { ApplyAddItem(model.Items[itemName]); } RoomNode startingNode = model.Rooms[itemContainer.StartingRoomName].Nodes[itemContainer.StartingNodeId]; InRoomState = new InRoomState(startingNode); }
public InRoomState(InRoomState other) { CurrentNode = other.CurrentNode; VisitedRoomPathList = new List <(RoomNode node, Strat strat)>(other.VisitedRoomPathList); DestroyedObstacleIdsSet = new HashSet <string>(other.DestroyedObstacleIdsSet); BypassedExitLock = other.BypassedExitLock; OpenedExitLock = other.OpenedExitLock; LastStrat = other.LastStrat; }
/// <summary> /// <para>Positions the in-game state as it would be after entering a room via the provided node. This may place the player at a different node immediately /// if the node calls for it.</para> /// <para>This method allows for leaving "remotely": leaving through a node the player is not at, by performing an action that must be initiated where the player is. /// A known example is using a CanLeaveCharged that initiates at a different node than the door it's on.</para> /// <para>Be aware that when leaving remotely, the exact action used is only determined retroactively once in the next room, and that leaving remotely is /// not considered valid if it's not made use of by a strat in the next room. /// </para> /// </summary> /// <param name="entryNode">The node (in the next room) through which the next room will be enteted.</param> /// <param name="bypassExitLock">Indicates whether the player is leaving the current room by bypassing a lock on the exit door.</param> /// <param name="openExitLock">Indicates whether the player is leaving the current room by opening a lock on the exit door.</param> public void ApplyEnterRoom(RoomNode entryNode, bool bypassExitLock, bool openExitLock) { // Finalize current room state with exit state InRoomState.ApplyExitRoom(bypassExitLock, openExitLock); // Copy current room state and remember it as previous PreviousRoomState = new InRoomState(InRoomState); // Enter next room InRoomState.ApplyEnterRoom(entryNode); }
/// <summary> /// A copy constructor that creates a new InGameState based on the provided one. /// This is a somewhat shallow copy; referenced objects whose inner state does not change with a game state (such as Room, GameFlag, etc.) will not be copied. /// The inner InRoomState and anything else that fully belongs to the InGameState does get copied. /// </summary> /// <param name="other">The InGameState to copy</param> public InGameState(InGameState other) { ActiveGameFlags = new Dictionary <string, GameFlag>(other.ActiveGameFlags); TakenItemLocations = new Dictionary <string, RoomNode>(other.TakenItemLocations); OpenedLocks = new Dictionary <String, NodeLock>(other.OpenedLocks); Inventory = other.Inventory.Clone(); Resources = other.Resources.Clone(); InRoomState = new InRoomState(other.InRoomState); if (other.PreviousRoomState != null) { PreviousRoomState = new InRoomState(other.PreviousRoomState); } }
/// <summary> /// Removes all in-room data from this InGameState. Useful if this has been initialized at a starting node but in-room state is not going to be maintained. /// </summary> public void ApplyClearRoomState() { InRoomState.ClearRoomState(); PreviousRoomState?.ClearRoomState(); }
/// <summary> /// Updates the in-room state to contain a mention of the destruction of the provided obstacle. /// This obstacle should be in the current room. /// </summary> /// <param name="obstacle">The obstacle to destroy.</param> public void ApplyDestroyedObstacle(RoomObstacle obstacle) { InRoomState.ApplyDestroyedObstacle(obstacle); }
/// <summary> /// Positions the in-game state at the provided node. This node should be inside the current room. /// </summary> /// <param name="nodeToVisit">The node to go to</param> /// <param name="strat">The strat through which the node is being reached. Can be null. If not null, only makes sense if /// it's on a link that connects previous node to new node.</param> public void ApplyVisitNode(RoomNode nodeToVisit, Strat strat) { InRoomState.ApplyVisitNode(nodeToVisit, strat); }
/// <summary> /// Returns the strat that was used to reach the current node, if any. Otherwise, returns null. /// </summary> /// <param name="usePreviousRoom">If true, uses the last known room state at the previous room instead of the current room to answer.</param> /// <returns></returns> public Strat GetLastStrat(bool usePreviousRoom = false) { InRoomState roomState = usePreviousRoom ? PreviousRoomState : InRoomState; return(roomState?.LastStrat); }
/// <summary> /// Returns the room the player is currently in. This can be null if in-room state isn't being tracked. /// </summary> /// <param name="usePreviousRoom">If true, uses the last known room state at the previous room instead of the current room to answer.</param> /// <returns></returns> public Room GetCurrentRoom(bool usePreviousRoom = false) { InRoomState roomState = usePreviousRoom ? PreviousRoomState : InRoomState; return(roomState?.CurrentRoom); }
/// <summary> /// Returns whether the player is exiting the room by opening a lock on the node they are exiting by. /// </summary> /// <param name="usePreviousRoom">If true, uses the last known room state at the previous room instead of the current room to answer.</param> /// <returns></returns> public bool OpeningExitLock(bool usePreviousRoom = false) { InRoomState roomState = usePreviousRoom ? PreviousRoomState : InRoomState; return(roomState?.OpenedExitLock ?? false); }
/// <summary> /// Returns whether the player is exiting the room by bypassing a lock on the node they are exiting by. /// </summary> /// <param name="usePreviousRoom">If true, uses the last known room state at the previous room instead of the current room to answer.</param> /// <returns></returns> public bool BypassingExitLock(bool usePreviousRoom = false) { InRoomState roomState = usePreviousRoom ? PreviousRoomState : InRoomState; return(roomState?.BypassedExitLock ?? false); }
/// <summary> /// Returns the node the player is currently at. This can be null if in-room state isn't being tracked. /// </summary> /// <param name="usePreviousRoom">If true, uses the last known room state at the previous room instead of the current room to answer.</param> /// <returns></returns> public RoomNode GetCurrentNode(bool usePreviousRoom = false) { InRoomState roomState = usePreviousRoom ? PreviousRoomState : InRoomState; return(roomState?.CurrentNode); }