From d9a0e7b03a5ff683707e830d90674a8ef5b220af Mon Sep 17 00:00:00 2001 From: Konrad Jamrozik Date: Sat, 8 Jun 2024 16:14:56 -0700 Subject: [PATCH] add Id to GameEvent --- .../Controller/GameSessionController.cs | 15 ++++++++++--- .../GameSessionControllerDeprecated.cs | 4 ++-- src/game-lib/Controller/GameTurnController.cs | 8 ++++--- src/game-lib/Controller/PlayerAction.cs | 4 ++-- src/game-lib/Events/GameEvent.cs | 4 +++- src/game-lib/Events/PlayerActionEvent.cs | 4 ++-- src/game-lib/Events/WorldEvent.cs | 5 +++-- src/game-lib/State/GameSession.cs | 7 +++++++ src/game-lib/State/GameSessionTurn.cs | 21 ++++++++++++++++++- 9 files changed, 56 insertions(+), 16 deletions(-) diff --git a/src/game-lib/Controller/GameSessionController.cs b/src/game-lib/Controller/GameSessionController.cs index 2f180536..a606240d 100644 --- a/src/game-lib/Controller/GameSessionController.cs +++ b/src/game-lib/Controller/GameSessionController.cs @@ -50,7 +50,11 @@ public GameSessionController(Configuration config, ILog log, GameSession gameSes _config = config; _log = log; GameSession = gameSession; - CurrentTurnController = new GameTurnController(_log, GameSession.RandomGen, GameSession.CurrentGameState); + CurrentTurnController = new GameTurnController( + _log, + GameSession.RandomGen, + GameSession.CurrentGameState, + GameSession.NextEventId); } public GameStatePlayerView CurrentGameStatePlayerView @@ -137,6 +141,7 @@ private void PlayGameUntilOver(IPlayer player, int turnLimit) // This state diff shows the result of advancing time. DiffGameStates(GameSession.CurrentGameState, nextTurnStartState); + GameSession.CurrentTurn.AssertInvariants(); NewTurn(worldEvents, nextTurnStartState); } } @@ -146,7 +151,11 @@ private void NewTurn(List worldEvents, GameState nextTurnStartState) GameSession.Turns.Add(new GameSessionTurn( eventsUntilStartState: worldEvents, startState: nextTurnStartState)); - CurrentTurnController = new GameTurnController(_log, GameSession.RandomGen, GameSession.CurrentGameState); + CurrentTurnController = new GameTurnController( + _log, + GameSession.RandomGen, + GameSession.CurrentGameState, + GameSession.NextEventId); } private List GetAndDeleteRecordedWorldEvents() @@ -156,7 +165,7 @@ private List GetAndDeleteRecordedWorldEvents() } public PlayerActionEvent AdvanceTime(GameState? state = null) - => new AdvanceTimePlayerAction(_log, GameSession.RandomGen).Apply(state ?? GameSession.CurrentGameState); + => new AdvanceTimePlayerAction(_log, GameSession.RandomGen).Apply(state ?? GameSession.CurrentGameState, GameSession.NextEventId); public GameState SaveCurrentGameStateToFile() { diff --git a/src/game-lib/Controller/GameSessionControllerDeprecated.cs b/src/game-lib/Controller/GameSessionControllerDeprecated.cs index 0ef6610e..576413ef 100644 --- a/src/game-lib/Controller/GameSessionControllerDeprecated.cs +++ b/src/game-lib/Controller/GameSessionControllerDeprecated.cs @@ -52,7 +52,7 @@ public GameSessionControllerDeprecated(Configuration config, ILog log, GameSessi _config = config; _log = log; GameSession = gameSession; - TurnController = new GameTurnController(_log, GameSession.RandomGen, GameSession.CurrentGameState); + TurnController = new GameTurnController(_log, GameSession.RandomGen, GameSession.CurrentGameState, 0); } public GameStatePlayerView CurrentGameStatePlayerView @@ -164,7 +164,7 @@ private List GetAndDeleteRecordedWorldEvents() } public PlayerActionEvent AdvanceTime() - => new AdvanceTimePlayerAction(_log, GameSession.RandomGen).Apply(GameSession.CurrentGameState); + => new AdvanceTimePlayerAction(_log, GameSession.RandomGen).Apply(GameSession.CurrentGameState, 0); public GameState SaveCurrentGameStateToFile() { diff --git a/src/game-lib/Controller/GameTurnController.cs b/src/game-lib/Controller/GameTurnController.cs index c6b3193b..eec2c657 100644 --- a/src/game-lib/Controller/GameTurnController.cs +++ b/src/game-lib/Controller/GameTurnController.cs @@ -10,13 +10,15 @@ public class GameTurnController { private readonly ILog _log; private readonly GameState _gameState; + private int _nextEventId; private readonly List _recordedPlayerActionEvents = new(); - public GameTurnController(ILog log, RandomGen randomGen, GameState gameState) + public GameTurnController(ILog log, RandomGen randomGen, GameState gameState, int nextEventId) { _log = log; RandomGen = randomGen; _gameState = gameState; + _nextEventId = nextEventId; } public RandomGen RandomGen { get; } @@ -97,9 +99,9 @@ private Agents GetAgentsByIds(int[] agentsIds) => private PlayerActionEvent ExecuteAndRecordAction(PlayerAction action) { - // This assertion is here to prevent the player of doing anything if they caused the game to be over. + // 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); + PlayerActionEvent playerActionEvent = action.Apply(_gameState, _nextEventId++); _recordedPlayerActionEvents.Add(playerActionEvent); return playerActionEvent; } diff --git a/src/game-lib/Controller/PlayerAction.cs b/src/game-lib/Controller/PlayerAction.cs index 278c3eb4..97e8345d 100644 --- a/src/game-lib/Controller/PlayerAction.cs +++ b/src/game-lib/Controller/PlayerAction.cs @@ -6,7 +6,7 @@ namespace UfoGameLib.Controller; public abstract class PlayerAction { - public PlayerActionEvent Apply(GameState state) + public PlayerActionEvent Apply(GameState state, int nextEventId) { Contract.Assert(!state.IsGameOver, $"money: {state.Assets.Money} " + @@ -28,7 +28,7 @@ public PlayerActionEvent Apply(GameState state) $"support: {state.Assets.Support}"); } - return new PlayerActionEvent(GetType().Name, applyResultDetails); + return new PlayerActionEvent(nextEventId, GetType().Name, applyResultDetails); } protected abstract string ApplyImpl(GameState state); diff --git a/src/game-lib/Events/GameEvent.cs b/src/game-lib/Events/GameEvent.cs index cee2ed67..957890aa 100644 --- a/src/game-lib/Events/GameEvent.cs +++ b/src/game-lib/Events/GameEvent.cs @@ -2,11 +2,13 @@ public abstract class GameEvent { + public readonly int Id; public readonly string Type; public readonly string Details; - public GameEvent(string type, string details) + public GameEvent(int id, string type, string details) { + Id = id; Type = type; Details = details; } diff --git a/src/game-lib/Events/PlayerActionEvent.cs b/src/game-lib/Events/PlayerActionEvent.cs index 97bcb68a..69efa49d 100644 --- a/src/game-lib/Events/PlayerActionEvent.cs +++ b/src/game-lib/Events/PlayerActionEvent.cs @@ -2,10 +2,10 @@ public class PlayerActionEvent : GameEvent { - public PlayerActionEvent(string type, string details) : base(type, details) + public PlayerActionEvent(int id, string type, string details) : base(id, type, details) { } public override PlayerActionEvent Clone() - => new(Type, Details); + => new(Id, Type, Details); } \ No newline at end of file diff --git a/src/game-lib/Events/WorldEvent.cs b/src/game-lib/Events/WorldEvent.cs index 9bebad29..bdd1bf45 100644 --- a/src/game-lib/Events/WorldEvent.cs +++ b/src/game-lib/Events/WorldEvent.cs @@ -2,9 +2,10 @@ public class WorldEvent : GameEvent { - public WorldEvent(string type, string details) : base(type, details) + public WorldEvent(int id, string type, string details) : base(id, type, details) { } + public override WorldEvent Clone() - => new(Type, Details); + => new(Id, Type, Details); } \ No newline at end of file diff --git a/src/game-lib/State/GameSession.cs b/src/game-lib/State/GameSession.cs index cdd43213..8f4abc90 100644 --- a/src/game-lib/State/GameSession.cs +++ b/src/game-lib/State/GameSession.cs @@ -20,6 +20,8 @@ public class GameSession public readonly List Turns; + public int NextEventId => GameEvents.Count; + public GameSessionTurn CurrentTurn => Turns.Last(); public GameState CurrentGameState => CurrentTurn.EndState; @@ -36,4 +38,9 @@ public IReadOnlyList GameStates => Turns.SelectMany(turn => [turn.StartState, turn.EndState]) .ToList() .AsReadOnly(); + + public IReadOnlyList GameEvents + => Turns.SelectMany(turn => turn.GameEvents) + .ToList() + .AsReadOnly(); } \ No newline at end of file diff --git a/src/game-lib/State/GameSessionTurn.cs b/src/game-lib/State/GameSessionTurn.cs index 6f53d7b6..f0f107b9 100644 --- a/src/game-lib/State/GameSessionTurn.cs +++ b/src/game-lib/State/GameSessionTurn.cs @@ -1,4 +1,5 @@ using Lib.Contracts; +using Lib.Primitives; using UfoGameLib.Controller; using UfoGameLib.Events; @@ -30,7 +31,7 @@ public GameSessionTurn( AssertInvariants(); } - private void AssertInvariants() + public void AssertInvariants() { Contract.Assert( StartState.Timeline.CurrentTurn == EndState.Timeline.CurrentTurn, @@ -55,8 +56,26 @@ private void AssertInvariants() Contract.Assert( EventsInTurn.Count == EndState.UpdateCount - StartState.UpdateCount, "Number of events in turn must match the number of updates between the game states."); + + IReadOnlyList events = GameEvents; + if (events.Any()) + { + int firstId = events[0].Id; + for (int i = 0; i < events.Count; i++) + { + int expectedId = firstId + i; + Contract.Assert( + events[i].Id == expectedId, + $"Event id {events[i].Id} is not equal to expected {expectedId}."); + } + } } + public IReadOnlyList GameEvents + => ((List) [..EventsUntilStartState, ..EventsInTurn]) + .Concat((AdvanceTimeEvent as GameEvent)?.WrapInList() ?? []) + .ToList().AsReadOnly(); + public GameSessionTurn Clone() => DeepClone();