From c1eea8a0f118c9e26e627d9f6a175861573c9853 Mon Sep 17 00:00:00 2001 From: Konrad Jamrozik Date: Fri, 14 Jun 2024 01:16:32 -0700 Subject: [PATCH] extract IRandomGen interface from RandomGen --- src/api/ApiUtils.cs | 4 ++-- src/api/WebApplicationRoutes.cs | 2 +- src/game-cli/Program.cs | 2 +- src/game-lib-tests/AIPlayerTests.cs | 4 ++-- src/game-lib-tests/FactionFixtures.cs | 2 +- src/game-lib-tests/GameSessionControllerTests.cs | 2 +- src/game-lib-tests/GameSessionTests.cs | 5 ++--- .../Controller/CheatingGameSessionController.cs | 2 +- src/game-lib/Controller/GameTurnController.cs | 4 ++-- .../Controller/TimeAdvancementController.cs | 4 ++-- src/game-lib/Lib/IRandomGen.cs | 13 +++++++++++++ src/game-lib/Lib/RandomGen.cs | 7 ++++--- src/game-lib/Model/AgentSurvivalRoll.cs | 2 +- src/game-lib/Model/Faction.cs | 6 +++--- src/game-lib/Model/Factions.cs | 2 +- src/game-lib/Model/Ruleset.cs | 6 +++--- src/game-lib/State/GameSession.cs | 4 ++-- src/game-lib/State/GameState.cs | 4 ++-- 18 files changed, 44 insertions(+), 31 deletions(-) create mode 100644 src/game-lib/Lib/IRandomGen.cs diff --git a/src/api/ApiUtils.cs b/src/api/ApiUtils.cs index 9b95c168..51702c71 100644 --- a/src/api/ApiUtils.cs +++ b/src/api/ApiUtils.cs @@ -118,14 +118,14 @@ private static bool EmptyJson(string requestBody) public static GameSession NewGameSession(GameState? initialGameState = null) { List? turnList = initialGameState != null ? [new GameSessionTurn(startState: initialGameState)] : null; - var gameSession = new GameSession(new RandomGen(new Random()), turnList); + var gameSession = new GameSession(new RandomGen(), turnList); return gameSession; } public static GameSession NewGameSessionFromTurn(GameSessionTurn? initialTurn = null) { List? turnList = initialTurn != null ? [initialTurn] : null; - var gameSession = new GameSession(new RandomGen(new Random()), turnList); + var gameSession = new GameSession(new RandomGen(), turnList); return gameSession; } diff --git a/src/api/WebApplicationRoutes.cs b/src/api/WebApplicationRoutes.cs index d0d52060..63be3a0b 100644 --- a/src/api/WebApplicationRoutes.cs +++ b/src/api/WebApplicationRoutes.cs @@ -33,7 +33,7 @@ public void Register(WebApplication app) private static string HelloCoinFlip() { - var randomGen = new RandomGen(new Random()); + var randomGen = new RandomGen(); return $"Hello World! Coin flip: {randomGen.FlipCoin()}"; } } \ No newline at end of file diff --git a/src/game-cli/Program.cs b/src/game-cli/Program.cs index ef3db941..dc78bd22 100644 --- a/src/game-cli/Program.cs +++ b/src/game-cli/Program.cs @@ -13,7 +13,7 @@ private static void Main(string[] args) { var config = new Configuration(new FileSystem()); using var log = new Log(config); - var randomGen = new RandomGen(new Random()); + var randomGen = new RandomGen(); var controller = new GameSessionController(config, log, new GameSession(randomGen)); diff --git a/src/game-lib-tests/AIPlayerTests.cs b/src/game-lib-tests/AIPlayerTests.cs index b6f86860..e228f070 100644 --- a/src/game-lib-tests/AIPlayerTests.cs +++ b/src/game-lib-tests/AIPlayerTests.cs @@ -10,7 +10,7 @@ public class AIPlayerTests { private Configuration _config = null!; private ILog _log = null!; - private readonly RandomGen _randomGen = new RandomGen(new Random()); + private readonly IRandomGen _randomGen = new RandomGen(); [SetUp] public void Setup() @@ -43,7 +43,7 @@ public void ExampleGameSessionForApi() { var config = new Configuration(new SimulatedFileSystem()); var log = new Log(config); - var randomGen = new RandomGen(new Random()); + var randomGen = new RandomGen(); var intellect = AIPlayer.Intellect.Basic; var controller = new GameSessionController(config, log, new GameSession(randomGen)); var aiPlayer = new AIPlayer(log, intellect); diff --git a/src/game-lib-tests/FactionFixtures.cs b/src/game-lib-tests/FactionFixtures.cs index 818f27f8..e58f9c73 100644 --- a/src/game-lib-tests/FactionFixtures.cs +++ b/src/game-lib-tests/FactionFixtures.cs @@ -5,7 +5,7 @@ namespace UfoGameLib.Tests; public static class FactionFixtures { - public static Factions SingleFaction(RandomGen randomGen) => new( + public static Factions SingleFaction(IRandomGen randomGen) => new( [ // Note: need to ensure here that IDs are consecutive, and from zero. Faction.Init(randomGen, id: 0, "Black Lotus cult", power: 200, powerIncrease: 5), diff --git a/src/game-lib-tests/GameSessionControllerTests.cs b/src/game-lib-tests/GameSessionControllerTests.cs index 62621197..103d9a23 100644 --- a/src/game-lib-tests/GameSessionControllerTests.cs +++ b/src/game-lib-tests/GameSessionControllerTests.cs @@ -11,7 +11,7 @@ public class GameSessionControllerTests { private Configuration _config = null!; private ILog _log = null!; - private readonly RandomGen _randomGen = new RandomGen(new Random()); + private readonly IRandomGen _randomGen = new RandomGen(); [SetUp] public void Setup() diff --git a/src/game-lib-tests/GameSessionTests.cs b/src/game-lib-tests/GameSessionTests.cs index 77d58394..8f966a1d 100644 --- a/src/game-lib-tests/GameSessionTests.cs +++ b/src/game-lib-tests/GameSessionTests.cs @@ -12,7 +12,7 @@ public class GameSessionTests // Using null! as these fields will be initialized in Setup() method. private Configuration _config = null!; private ILog _log = null!; - private RandomGen _randomGen = null!; + private IRandomGen _randomGen = null!; private Factions _factions = null!; [SetUp] @@ -20,7 +20,7 @@ public void Setup() { _config = new Configuration(new FileSystem()); _log = new Log(_config); - _randomGen = new RandomGen(new Random()); + _randomGen = new RandomGen(); _factions = FactionFixtures.SingleFaction(_randomGen); } @@ -88,7 +88,6 @@ public void BasicHappyPathGameSessionWorks() // // This way for testing I can say "the countdown is always 3" // - // 2. Allow to pass factions when initing game session MissionSite site = controller.CurrentGameStatePlayerView.MissionSites.First(); turnController.LaunchMission(site, agentCount: 3); controller.AdvanceTime(); diff --git a/src/game-lib/Controller/CheatingGameSessionController.cs b/src/game-lib/Controller/CheatingGameSessionController.cs index d7cdfd57..8cdb4534 100644 --- a/src/game-lib/Controller/CheatingGameSessionController.cs +++ b/src/game-lib/Controller/CheatingGameSessionController.cs @@ -10,7 +10,7 @@ namespace UfoGameLib.Controller; /// public class CheatingGameSessionController : GameSessionController { - public CheatingGameSessionController(Configuration config, ILog log, RandomGen randomGen, GameSession gameSession) + public CheatingGameSessionController(Configuration config, ILog log, IRandomGen randomGen, GameSession gameSession) : base( config, log, diff --git a/src/game-lib/Controller/GameTurnController.cs b/src/game-lib/Controller/GameTurnController.cs index 9dc8f3c7..a8ef7f5a 100644 --- a/src/game-lib/Controller/GameTurnController.cs +++ b/src/game-lib/Controller/GameTurnController.cs @@ -9,7 +9,7 @@ namespace UfoGameLib.Controller; public class GameTurnController { private readonly ILog _log; - public RandomGen RandomGen { get; } + public IRandomGen RandomGen { get; } private readonly EventIdGen _eventIdGen; private readonly AgentIdGen _agentIdGen; private readonly MissionIdGen _missionIdGen; @@ -19,7 +19,7 @@ public class GameTurnController public GameTurnController( ILog log, - RandomGen randomGen, + IRandomGen randomGen, EventIdGen eventIdGen, AgentIdGen agentIdGen, MissionIdGen missionIdGen, diff --git a/src/game-lib/Controller/TimeAdvancementController.cs b/src/game-lib/Controller/TimeAdvancementController.cs index e32f47e8..3308ee04 100644 --- a/src/game-lib/Controller/TimeAdvancementController.cs +++ b/src/game-lib/Controller/TimeAdvancementController.cs @@ -9,14 +9,14 @@ namespace UfoGameLib.Controller; public class TimeAdvancementController { private readonly ILog _log; - private readonly RandomGen _randomGen; + private readonly IRandomGen _randomGen; private readonly List _worldEvents; private readonly EventIdGen _eventIdGen; private readonly MissionSiteIdGen _missionSiteIdGen; public TimeAdvancementController( ILog log, - RandomGen randomGen, + IRandomGen randomGen, EventIdGen eventIdGen, MissionSiteIdGen missionSiteIdGen) { diff --git a/src/game-lib/Lib/IRandomGen.cs b/src/game-lib/Lib/IRandomGen.cs new file mode 100644 index 00000000..8bc27762 --- /dev/null +++ b/src/game-lib/Lib/IRandomGen.cs @@ -0,0 +1,13 @@ +namespace UfoGameLib.Lib; + +public interface IRandomGen +{ + int Roll1To(int n); + int Roll0To(int n); + int Roll(int min, int max); + int Roll(Range range); + T Pick(List items); + List Pick(List items, int count); + TValue Pick(IDictionary dict); + bool FlipCoin(); +} \ No newline at end of file diff --git a/src/game-lib/Lib/RandomGen.cs b/src/game-lib/Lib/RandomGen.cs index aaff23d0..c6c5f2fb 100644 --- a/src/game-lib/Lib/RandomGen.cs +++ b/src/game-lib/Lib/RandomGen.cs @@ -5,13 +5,14 @@ namespace UfoGameLib.Lib; // Note: currently upon save/load the random gets re-randomized. // To fix that, the Save file should include a seed used to recreate upon load. -public class RandomGen + +public class RandomGen : IRandomGen { private readonly Random _random; - public RandomGen(Random random) + public RandomGen(Random? random = null) { - _random = random; + _random = random ?? new Random(); } public int Roll1To(int n) diff --git a/src/game-lib/Model/AgentSurvivalRoll.cs b/src/game-lib/Model/AgentSurvivalRoll.cs index 8005a66c..56769ca6 100644 --- a/src/game-lib/Model/AgentSurvivalRoll.cs +++ b/src/game-lib/Model/AgentSurvivalRoll.cs @@ -17,7 +17,7 @@ public class AgentSurvivalRoll public const int MaxRecoversIn = 30; - public AgentSurvivalRoll(ILog log, RandomGen randomGen, Agent agent, Mission mission) + public AgentSurvivalRoll(ILog log, IRandomGen randomGen, Agent agent, Mission mission) { SurvivalChance = ComputeSurvivalChance(agent, mission.Site.Difficulty); Roll = randomGen.Roll(RollRange); diff --git a/src/game-lib/Model/Faction.cs b/src/game-lib/Model/Faction.cs index c76cd632..37b66b24 100644 --- a/src/game-lib/Model/Faction.cs +++ b/src/game-lib/Model/Faction.cs @@ -37,7 +37,7 @@ public Faction( } public static Faction Init( - RandomGen randomGen, + IRandomGen randomGen, int id, string name, int power, @@ -57,7 +57,7 @@ public Faction DeepClone() public List CreateMissionSites( ILog log, - RandomGen randomGen, + IRandomGen randomGen, MissionSiteIdGen missionSiteIdGen, GameState state) { @@ -98,6 +98,6 @@ public List CreateMissionSites( return sites; } - private static int RandomizeMissionSiteCountdown(RandomGen randomGen) + private static int RandomizeMissionSiteCountdown(IRandomGen randomGen) => randomGen.Roll(Ruleset.FactionMissionSiteCountdown); } \ No newline at end of file diff --git a/src/game-lib/Model/Factions.cs b/src/game-lib/Model/Factions.cs index d1900c8b..747534f8 100644 --- a/src/game-lib/Model/Factions.cs +++ b/src/game-lib/Model/Factions.cs @@ -19,7 +19,7 @@ public Factions DeepClone() public List CreateMissionSites( ILog log, - RandomGen randomGen, + IRandomGen randomGen, MissionSiteIdGen missionSiteIdGen, GameState state) => this.SelectMany(faction => faction.CreateMissionSites(log, randomGen, missionSiteIdGen, state)).ToList(); diff --git a/src/game-lib/Model/Ruleset.cs b/src/game-lib/Model/Ruleset.cs index ac70ae96..8ffb70ba 100644 --- a/src/game-lib/Model/Ruleset.cs +++ b/src/game-lib/Model/Ruleset.cs @@ -14,7 +14,7 @@ public static class Ruleset // For more example factions data, see: // https://github.com/konrad-jamrozik/game/blob/eccb44a1d5f074e95b07aebca2c6bc5bbfdfdda8/src/ufo-game/Model/Data/FactionsData.cs#L34 - public static Factions InitialFactions(RandomGen randomGen) => new( + public static Factions InitialFactions(IRandomGen randomGen) => new( [ // Note: need to ensure here that IDs are consecutive, and from zero. Faction.Init(randomGen, id: 0, "Black Lotus cult", power: 200, powerIncrease: 5), @@ -36,7 +36,7 @@ public static class Ruleset public static (bool survived, int? recoversIn) RollForAgentSurvival( ILog log, - RandomGen randomGen, + IRandomGen randomGen, Agent agent, Mission mission) { @@ -73,7 +73,7 @@ private static int SkillFromMissions(Agent agent) // based on faction data and possibly other factors. And faction will have power correlating with turn. public static (int difficulty, int difficultyFromTurn, int roll) RollMissionSiteDifficulty( int currentTurn, - RandomGen randomGen) + IRandomGen randomGen) { // Note that currently the only ways of increasing agents survivability of difficulty is: // - by surviving missions diff --git a/src/game-lib/State/GameSession.cs b/src/game-lib/State/GameSession.cs index 9230efe1..b862046d 100644 --- a/src/game-lib/State/GameSession.cs +++ b/src/game-lib/State/GameSession.cs @@ -16,7 +16,7 @@ namespace UfoGameLib.State; /// public class GameSession { - public readonly RandomGen RandomGen; + public readonly IRandomGen RandomGen; public readonly List Turns; @@ -34,7 +34,7 @@ public class GameSession public readonly MissionSiteIdGen MissionSiteIdGen; - public GameSession(RandomGen randomGen, List? turns = null, Factions? factions = null) + public GameSession(IRandomGen randomGen, List? turns = null, Factions? factions = null) { RandomGen = randomGen; Turns = turns ?? [new GameSessionTurn(startState: GameState.NewInitialGameState(randomGen, factions))]; diff --git a/src/game-lib/State/GameState.cs b/src/game-lib/State/GameState.cs index 4335c626..6ac046dc 100644 --- a/src/game-lib/State/GameState.cs +++ b/src/game-lib/State/GameState.cs @@ -40,9 +40,9 @@ public GameState( Factions = factions; } - public static GameState NewInitialGameState(RandomGen? randomGen = null, Factions? factions = null) + public static GameState NewInitialGameState(IRandomGen? randomGen = null, Factions? factions = null) { - randomGen ??= new RandomGen(new Random()); + randomGen ??= new RandomGen(); return new GameState( updateCount: 0, new Timeline(currentTurn: Timeline.InitialTurn),