Skip to content

Commit

Permalink
refactor turn controller, time advancement controller and advance time
Browse files Browse the repository at this point in the history
  • Loading branch information
Konrad Jamrozik committed Jun 12, 2024
1 parent 0892a3c commit 6e83240
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 58 deletions.
2 changes: 1 addition & 1 deletion src/api/PlayerActionPayload.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ private Func<PlayerActionEvent> TranslatePlayerActionToControllerAction(GameSess
// https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/patterns#positional-pattern
=> ActionName switch
{
GameEventName.AdvanceTimePlayerAction => controller.AdvanceTimeNoWorldEvents,
GameEventName.AdvanceTimePlayerAction => () => controller.AdvanceTime().advaceTimeEvent,
nameof(BuyTransportCapacityPlayerAction) => () => controller.CurrentTurnController.BuyTransportCapacity(TargetId!.Value),
nameof(HireAgentsPlayerAction) => () => controller.CurrentTurnController.HireAgents(TargetId!.Value),
nameof(SackAgentsPlayerAction) => () => controller.CurrentTurnController.SackAgents(Ids!),
Expand Down
1 change: 0 additions & 1 deletion src/game-cli/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ private static void Main(string[] args)

private static void InvokeAdvanceTime(GameSessionController controller)
{

controller.AdvanceTime();
Console.WriteLine("Time advanced.");
}
Expand Down
30 changes: 15 additions & 15 deletions src/game-lib-tests/GameSessionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ public void BasicHappyPathGameSessionWorks()

// Act
turnController.HireAgents(count: 3);
controller.AdvanceTime(state);
controller.AdvanceTime(state);
controller.AdvanceTime();
controller.AdvanceTime();
MissionSite site = controller.CurrentGameStatePlayerView.MissionSites.First();
turnController.LaunchMission(site, agentCount: 3);
controller.AdvanceTime(state);
controller.AdvanceTime();

GameState finalState = session.CurrentGameState;

Expand Down Expand Up @@ -123,7 +123,7 @@ public void LoadingPreviousGameStateOverridesCurrentState()
controller.SaveCurrentGameStateToFile();

// Act 2: Advance time, thus modifying the current game state
controller.AdvanceTime(session.CurrentGameState);
controller.AdvanceTime();

// Assert that advancing time didn't modify reference to the current game state
Assert.That(stateView.StateReferenceEquals(controller.CurrentGameStatePlayerView));
Expand Down Expand Up @@ -161,25 +161,25 @@ public void RoundTrippingSavingAndLoadingGameStateBehavesCorrectly()
var controller = new GameSessionController(_config, _log, session);
var turnController = controller.CurrentTurnController;

controller.AdvanceTime(session.CurrentGameState);
controller.AdvanceTime(session.CurrentGameState);
controller.AdvanceTime();
controller.AdvanceTime();
turnController.HireAgents(5);
// Need to advance time here so that hired agents are no longer InTransit and can be
// sent on a mission.
controller.AdvanceTime(session.CurrentGameState);
controller.AdvanceTime();
turnController.SackAgents(agentsIds: [0]);

GameStatePlayerView state = controller.CurrentGameStatePlayerView;
turnController.LaunchMission(
state.MissionSites.Active.First(),
agentCount: state.Assets.CurrentTransportCapacity);

controller.AdvanceTime(session.CurrentGameState);
controller.AdvanceTime(session.CurrentGameState);
controller.AdvanceTime(session.CurrentGameState);
controller.AdvanceTime(session.CurrentGameState);
controller.AdvanceTime(session.CurrentGameState);
controller.AdvanceTime(session.CurrentGameState);
controller.AdvanceTime();
controller.AdvanceTime();
controller.AdvanceTime();
controller.AdvanceTime();
controller.AdvanceTime();
controller.AdvanceTime();

Assert.Multiple(
() =>
Expand Down Expand Up @@ -225,11 +225,11 @@ public void RoundTrippingSavingAndLoadingGameStateWithActiveMissionBehavesCorrec
var turnController = controller.CurrentTurnController;
GameStatePlayerView state = controller.CurrentGameStatePlayerView;

controller.AdvanceTime(session.CurrentGameState);
controller.AdvanceTime();
turnController.HireAgents(5);
// Need to advance time here so that hired agents are no longer InTransit and can be
// sent on a mission.
controller.AdvanceTime(session.CurrentGameState);
controller.AdvanceTime();

Assert.That(state.MissionSites.Active.Any(), Is.True);

Expand Down
32 changes: 5 additions & 27 deletions src/game-lib/Controller/GameSessionController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ public class GameSessionController
protected readonly GameSession GameSession;
private readonly Configuration _config;
private readonly ILog _log;
public GameTurnController CurrentTurnController { get; private set; }
private TimeAdvancementController _timeAdvancementController;
public GameTurnController CurrentTurnController { get; }
private readonly TimeAdvancementController _timeAdvancementController;

public GameSessionController(Configuration config, ILog log, GameSession gameSession)
{
Expand All @@ -55,12 +55,11 @@ public GameSessionController(Configuration config, ILog log, GameSession gameSes
_log,
GameSession.RandomGen,
GameSession.EventIdGen,
GameSession.CurrentGameState);
() => GameSession.CurrentGameState);
_timeAdvancementController = new TimeAdvancementController(
_log,
GameSession.RandomGen,
GameSession.EventIdGen,
GameSession.CurrentGameState);
GameSession.EventIdGen);
}

public GameStatePlayerView CurrentGameStatePlayerView
Expand Down Expand Up @@ -164,31 +163,10 @@ private void NewTurn(List<WorldEvent> worldEvents, GameState nextTurnStartState)
eventsUntilStartState: worldEvents,
startState: nextTurnStartState,
nextEventId: GameSession.EventIdGen.Value));
// kja I need to revisit this idea of re-constructing GameTurnControllers.
// Maybe really it is better just to update the CurrentGameState and use NextEventIdGen class.
CurrentTurnController = new GameTurnController(
_log,
GameSession.RandomGen,
GameSession.EventIdGen,
GameSession.CurrentGameState);
_timeAdvancementController = new TimeAdvancementController(
_log,
GameSession.RandomGen,
GameSession.EventIdGen,
GameSession.CurrentGameState);
}

// kja AdvanceTime must accept state as param per PlayGameUntilOver.
// But I should reduce its usage in tests and rethink if _timeAdvancementController should get Current state
// as ctor input, given we really only ever want to get the clone as in PlayGameUntilOver.
// See also the todo on reconstructing controllers.
public (PlayerActionEvent advaceTimeEvent, List<WorldEvent> worldEvents) AdvanceTime(GameState? state = null)
{
return _timeAdvancementController.AdvanceTime(state);
}

public PlayerActionEvent AdvanceTimeNoWorldEvents()
=> _timeAdvancementController.AdvanceTime().advanceTimeEvent;
=> _timeAdvancementController.AdvanceTime(state ?? GameSession.CurrentGameState);

public GameState SaveCurrentGameStateToFile()
{
Expand Down
18 changes: 10 additions & 8 deletions src/game-lib/Controller/GameTurnController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ namespace UfoGameLib.Controller;
public class GameTurnController
{
private readonly ILog _log;
private readonly GameState _gameState;
private readonly Func<GameState> _gameState;
private GameState GameState => _gameState();
private readonly EventIdGen _eventIdGen;
private readonly List<PlayerActionEvent> _recordedPlayerActionEvents = new();

public GameTurnController(ILog log, RandomGen randomGen, EventIdGen eventIdGen, GameState gameState)
public GameTurnController(ILog log, RandomGen randomGen, EventIdGen eventIdGen, Func<GameState> gameState)
{
_log = log;
RandomGen = randomGen;
Expand All @@ -23,7 +24,7 @@ public GameTurnController(ILog log, RandomGen randomGen, EventIdGen eventIdGen,

public RandomGen RandomGen { get; }

public int CurrentTurn => _gameState.Timeline.CurrentTurn;
public int CurrentTurn => GameState.Timeline.CurrentTurn;

public PlayerActionEvent SackAgents(int[] agentsIds) => SackAgents(GetAgentsByIds(agentsIds));

Expand All @@ -32,6 +33,7 @@ public PlayerActionEvent SendAgentsToTraining(int[] agentsIds)

public PlayerActionEvent SendAgentsToGenerateIncome(int[] agentsIds)
=> SendAgentsToGenerateIncome(GetAgentsByIds(agentsIds));

public PlayerActionEvent SendAgentsToGatherIntel(int[] agentsIds)
=> SendAgentsToGatherIntel(GetAgentsByIds(agentsIds));

Expand All @@ -47,7 +49,7 @@ public PlayerActionEvent LaunchMission(int siteId, int[] agentsIds)
/// </summary>
public void LaunchMission(MissionSite site, int agentCount)
{
Agents agents = _gameState.Assets.Agents
Agents agents = GameState.Assets.Agents
.Where(agent => agent.CanBeSentOnMission)
.Take(agentCount)
.ToAgents();
Expand Down Expand Up @@ -89,16 +91,16 @@ public List<PlayerActionEvent> GetAndDeleteRecordedPlayerActionEvents()
}

private MissionSite GetMissionSiteById(int siteId) =>
_gameState.MissionSites.Single(site => site.Id == siteId);
GameState.MissionSites.Single(site => site.Id == siteId);

private Agents GetAgentsByIds(int[] agentsIds) =>
_gameState.Assets.Agents.GetByIds(agentsIds);
GameState.Assets.Agents.GetByIds(agentsIds);

private PlayerActionEvent ExecuteAndRecordAction(PlayerAction action)
{
// This assertion is here to prevent the player from doing anything if they caused the game to be over.
Contract.Assert(!_gameState.IsGameOver);
PlayerActionEvent playerActionEvent = action.Apply(_gameState, _eventIdGen.Generate);
Contract.Assert(!GameState.IsGameOver);
PlayerActionEvent playerActionEvent = action.Apply(GameState, _eventIdGen.Generate);
_recordedPlayerActionEvents.Add(playerActionEvent);
return playerActionEvent;
}
Expand Down
8 changes: 2 additions & 6 deletions src/game-lib/Controller/TimeAdvancementController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,21 @@ public class TimeAdvancementController
private readonly RandomGen _randomGen;
private readonly List<WorldEvent> _worldEvents;
private readonly EventIdGen _eventIdGen;
private readonly GameState _state;

public TimeAdvancementController(ILog log, RandomGen randomGen, EventIdGen eventIdGen, GameState state)
public TimeAdvancementController(ILog log, RandomGen randomGen, EventIdGen eventIdGen)
{
_log = log;
_randomGen = randomGen;
_eventIdGen = eventIdGen;
_state = state;
_worldEvents = new List<WorldEvent>();
}

public (PlayerActionEvent advanceTimeEvent, List<WorldEvent> worldEvents) AdvanceTime(GameState? inputState = null)
public (PlayerActionEvent advanceTimeEvent, List<WorldEvent> worldEvents) AdvanceTime(GameState state)
{
_log.Info("");
_log.Info("----- Advancing time");
_log.Info("");

GameState state = inputState ?? _state;

PlayerActionEvent advanceTimeEvent = new PlayerActionEvent(
_eventIdGen.Generate,
GameEventName.AdvanceTimePlayerAction,
Expand Down

0 comments on commit 6e83240

Please sign in to comment.