public override ExecutionResult Execute(SuperMetroidModel model, InGameState inGameState, int times = 1, bool usePreviousRoom = false) { IEnumerable <int> visitedNodeIds = inGameState.GetVisitedNodeIds(usePreviousRoom); // If the node at which we entered is not allowed, this is not fulfilled. if (!NodeIds.Contains(visitedNodeIds.First())) { return(null); } // If we have visited a node to avoid, this is not fulfilled. if (NodeIdsToAvoid.Intersect(visitedNodeIds).Any()) { return(null); } // If we were supposed to stay put but have visited more than the starting node, this is not fulfilled if (MustStayPut && visitedNodeIds.Count() > 1) { return(null); } // If we have destroyed an obstacle that needed to be preserved, this is not fulfilled if (ObstaclesIdsToAvoid.Intersect(inGameState.GetDestroyedObstacleIds(usePreviousRoom)).Any()) { return(null); } // We've avoided all pitfalls. This ResetRoom is fulfilled. Clone the InGameState to fulfill method contract return(new ExecutionResult(inGameState.Clone())); }
public AbstractNavigationAction(string intent, SuperMetroidModel model, InGameState initialInGameState, ExecutionResult executionResult) : this(intent) { Succeeded = true; // Initialize position change if (initialInGameState.GetCurrentNode() != executionResult.ResultingState.GetCurrentNode()) { PositionChange = (initialInGameState.GetCurrentNode(), executionResult.ResultingState.GetCurrentNode()); } // Initialize gained and lost items ItemInventory gainedInventory = executionResult.ResultingState.GetInventoryExceptWith(initialInGameState); ItemsGained = gainedInventory; // Cannot lose items, just create an empty inventory ItemsLost = new ItemInventory(model.StartConditions.BaseResourceMaximums); // Initialize enabled and disabled items ItemsDisabledNames = executionResult.ResultingState.GetDisabledItemNames().Except(initialInGameState.GetDisabledItemNames()); ItemsEnabledNames = initialInGameState.GetDisabledItemNames().Except(executionResult.ResultingState.GetDisabledItemNames()); // Initialize flags gained GameFlagsGained = GameFlagsGained.Concat(executionResult.ResultingState.GetActiveGameFlagsExceptWith(initialInGameState).Values); // Initialize locks opened LocksOpened = LocksOpened.Concat(executionResult.ResultingState.GetOpenedNodeLocksExceptWith(initialInGameState).Values); // Initialize item locations taken ItemLocationsTaken = ItemLocationsTaken.Concat(executionResult.ResultingState.GetTakenItemLocationsExceptWith(initialInGameState).Values); // Initialize resources before and after ResourcesBefore = initialInGameState.GetCurrentResources(); ResourcesAfter = executionResult.ResultingState.GetCurrentResources(); // Initialize destroyed obstacles, but that's only relevant if we didn't change rooms if (executionResult.ResultingState.GetCurrentRoom() == initialInGameState.GetCurrentRoom()) { ObstaclesDestroyed = ObstaclesDestroyed.Concat( executionResult.ResultingState.GetDestroyedObstacleIds() .Except(initialInGameState.GetDestroyedObstacleIds()) .Select(obstacleId => executionResult.ResultingState.GetCurrentRoom().Obstacles[obstacleId]) ); } // Transfer information data from the ExecutionResult. // No need to copy since they are IEnumerable and not supposed to be mutated. RunwaysUsed = executionResult.RunwaysUsed; CanLeaveChargedExecuted = executionResult.CanLeaveChargedExecuted; OpenedLocks = executionResult.OpenedLocks; BypassedLocks = executionResult.BypassedLocks; KilledEnemies = executionResult.KilledEnemies; // Since the set of items is mutable, do not transfer the instance ItemsInvolved.UnionWith(executionResult.ItemsInvolved); DamageReducingItemsInvolved.UnionWith(executionResult.DamageReducingItemsInvolved); }
public ExecutionResult Execute(SuperMetroidModel model, InGameState inGameState, int times = 1, bool usePreviousRoom = false) { times = times * model.LogicalOptions.NumberOfTries(this); ExecutionResult result = Requires.Execute(model, inGameState, times: times, usePreviousRoom: usePreviousRoom); if (result == null) { return(null); } // Iterate over intact obstacles that need to be dealt with foreach (StratObstacle obstacle in Obstacles.Where(o => !inGameState.GetDestroyedObstacleIds(usePreviousRoom).Contains(o.ObstacleId))) { // Try destroying the obstacle first ExecutionResult destroyResult = result.AndThen(obstacle.DestroyExecution, model, times: times, usePreviousRoom: usePreviousRoom); // If destruction fails, try to bypass instead if (destroyResult == null) { result = result.AndThen(obstacle.BypassExecution, model, times: times, usePreviousRoom: usePreviousRoom); // If bypass also fails, we cannot get past this obstacle. Give up. if (result == null) { return(null); } } // If destruction succeeded, carry on with the result of that else { result = destroyResult; } } return(result); }