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); }