public ExecutionResult Execute(SuperMetroidModel model, InGameState inGameState, int times = 1, bool usePreviousRoom = false) { // There may be up to 2 requirements. This StratObstacle may have some, and the RoomObstacle may also have some general requirements that apply to any strat. // Start with the RoomObstacle's requirements ExecutionResult result = StratObstacle.Obstacle.Requires.Execute(model, inGameState, times: times, usePreviousRoom: usePreviousRoom); // If we couldn't execute the RoomObstacle's requirements, give up if (result == null) { return(null); } // Add this specific StratObstacle's requirements result = result.AndThen(StratObstacle.Requires, model, times: times, usePreviousRoom: usePreviousRoom); // If that failed, give up if (result == null) { return(null); } // We have succeeded, but we must update the ExecutionResult and its InGameState to reflect any destroyed obstacles result.ApplyDestroyedObstacles(new[] { StratObstacle.Obstacle }.Concat(StratObstacle.AdditionalObstacles), usePreviousRoom); return(result); }
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); }