diff --git a/53_King/csharp/Country.cs b/53_King/csharp/Country.cs index 1e94e821..5b47c50a 100644 --- a/53_King/csharp/Country.cs +++ b/53_King/csharp/Country.cs @@ -2,6 +2,7 @@ namespace King; internal class Country { + private readonly IReadWrite _io; private readonly IRandom _random; private float _rallods; private float _countrymen; @@ -10,8 +11,9 @@ internal class Country private float _plantingCost; private float _landValue; - public Country(IRandom random) + public Country(IReadWrite io, IRandom random) : this( + io, random, (int)(60000 + random.NextFloat(1000) - random.NextFloat(1000)), (int)(500 + random.NextFloat(10) - random.NextFloat(10)), @@ -20,8 +22,9 @@ internal class Country { } - public Country(IRandom random, float rallods, float countrymen, float foreigners, float land) + public Country(IReadWrite io, IRandom random, float rallods, float countrymen, float foreigners, float land) { + _io = io; _random = random; _rallods = rallods; _countrymen = countrymen; @@ -31,4 +34,68 @@ internal class Country _plantingCost = random.Next(10, 15); _landValue = random.Next(95, 105); } + + public string Status => Resource.Status(_rallods, _countrymen, _foreigners, _land, _landValue, _plantingCost); + private float FarmLand => _land - 1000; + + public bool SellLand() + { + if (_io.TryReadValue( + SellLandPrompt, + out var landSold, + new ValidityTest(v => v <= FarmLand, () => SellLandError(FarmLand)))) + { + _land = (int)(_land - landSold); + _rallods = (int)(_rallods + landSold * _landValue); + return true; + } + + return false; + } + + public bool DistributeRallods() + { + if (_io.TryReadValue( + GiveRallodsPrompt, + out var rallodsGiven, + new ValidityTest(v => v <= _rallods, () => GiveRallodsError(_rallods)))) + { + _rallods = (int)(_rallods - rallodsGiven); + return true; + } + + return false; + } + + public bool PlantLand() + { + if (_rallods > 0 && + _io.TryReadValue( + PlantLandPrompt, + out var landPlanted, + new ValidityTest(v => v <= _countrymen * 2, PlantLandError1), + new ValidityTest(v => v <= FarmLand, PlantLandError2(FarmLand)), + new ValidityTest(v => v * _plantingCost <= _rallods, PlantLandError3(_rallods)))) + { + _rallods -= (int)(landPlanted * _plantingCost); + return true; + } + + return false; + } + + public bool ControlPollution() + { + if (_rallods > 0 && + _io.TryReadValue( + PollutionPrompt, + out var rallodsGiven, + new ValidityTest(v => v <= _rallods, () => PollutionError(_rallods)))) + { + _rallods = (int)(_rallods - rallodsGiven); + return true; + } + + return false; + } } diff --git a/53_King/csharp/Game.cs b/53_King/csharp/Game.cs index c8a44a8c..198ff14f 100644 --- a/53_King/csharp/Game.cs +++ b/53_King/csharp/Game.cs @@ -19,7 +19,7 @@ internal class Game if (SetUpReign() is Reign reign) { - _io.Write(reign); + reign.PlayYear(); } _io.WriteLine(); diff --git a/53_King/csharp/IOExtensions.cs b/53_King/csharp/IOExtensions.cs index 183621ca..c2707c0d 100644 --- a/53_King/csharp/IOExtensions.cs +++ b/53_King/csharp/IOExtensions.cs @@ -13,7 +13,7 @@ internal static class IOExtensions io.TryReadValue(SavedWorkersPrompt, out var workers) && io.TryReadValue(SavedLandPrompt, v => v is > 1000 and <= 2000, SavedLandError, out var land)) { - reign = new Reign(io, new Country(random, rallods, countrymen, workers, land), years + 1); + reign = new Reign(io, new Country(io, random, rallods, countrymen, workers, land), years + 1); return true; } @@ -21,15 +21,33 @@ internal static class IOExtensions return false; } - private static bool TryReadValue(this IReadWrite io, string prompt, out float value) + internal static bool TryReadValue(this IReadWrite io, string prompt, out float value, params ValidityTest[] tests) + { + while (true) + { + var response = value = io.ReadNumber(prompt); + if (response < 0) { return false; } + if (tests.All(test => test.IsValid(response, io))) { return true; } + } + } + + internal static bool TryReadValue(this IReadWrite io, string prompt, out float value) => io.TryReadValue(prompt, _ => true, "", out value); - private static bool TryReadValue( + internal static bool TryReadValue( this IReadWrite io, string prompt, Predicate isValid, string error, out float value) + => io.TryReadValue(prompt, isValid, () => error, out value); + + internal static bool TryReadValue( + this IReadWrite io, + string prompt, + Predicate isValid, + Func getError, + out float value) { while (true) { @@ -37,7 +55,7 @@ internal static class IOExtensions if (value < 0) { return false; } if (isValid(value)) { return true; } - io.Write(error); + io.Write(getError()); } } -} \ No newline at end of file +} diff --git a/53_King/csharp/Program.cs b/53_King/csharp/Program.cs index 6eb4c50e..5aae4ccb 100644 --- a/53_King/csharp/Program.cs +++ b/53_King/csharp/Program.cs @@ -1,6 +1,7 @@ global using Games.Common.IO; global using Games.Common.Randomness; global using King.Resources; +global using static King.Resources.Resource; using King; new Game(new ConsoleIO(), new RandomNumberGenerator()).Play(); diff --git a/53_King/csharp/Reign.cs b/53_King/csharp/Reign.cs index 4e6c45c5..58e89b66 100644 --- a/53_King/csharp/Reign.cs +++ b/53_King/csharp/Reign.cs @@ -9,9 +9,8 @@ internal class Reign private readonly float _year; public Reign(IReadWrite io, IRandom random) - : this(io, new Country(random), 0) + : this(io, new Country(io, random), 0) { - } public Reign(IReadWrite io, Country country, float year) @@ -20,4 +19,15 @@ internal class Reign _country = country; _year = year; } + + public void PlayYear() + { + _io.Write(_country.Status); + + var playerSoldLand = _country.SellLand(); + var playerDistributedRallods = _country.DistributeRallods(); + var playerPlantedLand = _country.PlantLand(); + var playerControlledPollution = _country.ControlPollution(); + + } } diff --git a/53_King/csharp/Resources/GiveRallodsError.txt b/53_King/csharp/Resources/GiveRallodsError.txt new file mode 100644 index 00000000..df0d7cc0 --- /dev/null +++ b/53_King/csharp/Resources/GiveRallodsError.txt @@ -0,0 +1 @@ + Think again. You've only got {0} rallods in the treasury. diff --git a/53_King/csharp/Resources/GiveRallodsPrompt.txt b/53_King/csharp/Resources/GiveRallodsPrompt.txt new file mode 100644 index 00000000..e8bd345b --- /dev/null +++ b/53_King/csharp/Resources/GiveRallodsPrompt.txt @@ -0,0 +1 @@ +How many rallods will you distribute among your countrymen \ No newline at end of file diff --git a/53_King/csharp/Resources/PlantLandError1.txt b/53_King/csharp/Resources/PlantLandError1.txt new file mode 100644 index 00000000..ef959f9f --- /dev/null +++ b/53_King/csharp/Resources/PlantLandError1.txt @@ -0,0 +1 @@ + Sorry, but each countryman can only plant 2 sq. miles. \ No newline at end of file diff --git a/53_King/csharp/Resources/PlantLandError2.txt b/53_King/csharp/Resources/PlantLandError2.txt new file mode 100644 index 00000000..e5844aa1 --- /dev/null +++ b/53_King/csharp/Resources/PlantLandError2.txt @@ -0,0 +1 @@ + Sorry, but you've only {0} sq. miles of farm land. \ No newline at end of file diff --git a/53_King/csharp/Resources/PlantLandError3.txt b/53_King/csharp/Resources/PlantLandError3.txt new file mode 100644 index 00000000..38264442 --- /dev/null +++ b/53_King/csharp/Resources/PlantLandError3.txt @@ -0,0 +1 @@ + Think again, You've only {0} rallods left in the treasury. diff --git a/53_King/csharp/Resources/PlantLandPrompt.txt b/53_King/csharp/Resources/PlantLandPrompt.txt new file mode 100644 index 00000000..f2fe448e --- /dev/null +++ b/53_King/csharp/Resources/PlantLandPrompt.txt @@ -0,0 +1 @@ +How many square miles do you wish to plant \ No newline at end of file diff --git a/53_King/csharp/Resources/PollutionError.txt b/53_King/csharp/Resources/PollutionError.txt new file mode 100644 index 00000000..f99644e3 --- /dev/null +++ b/53_King/csharp/Resources/PollutionError.txt @@ -0,0 +1 @@ + Think again. You only have {0} rallods remaining. diff --git a/53_King/csharp/Resources/PollutionPrompt.txt b/53_King/csharp/Resources/PollutionPrompt.txt new file mode 100644 index 00000000..252fb333 --- /dev/null +++ b/53_King/csharp/Resources/PollutionPrompt.txt @@ -0,0 +1 @@ +How many rallods do you wish to spend on pollution control \ No newline at end of file diff --git a/53_King/csharp/Resources/Resource.cs b/53_King/csharp/Resources/Resource.cs index 6626a3dd..37ff09eb 100644 --- a/53_King/csharp/Resources/Resource.cs +++ b/53_King/csharp/Resources/Resource.cs @@ -5,11 +5,52 @@ namespace King.Resources; internal static class Resource { + private static bool _sellLandErrorShown; + public static Stream Title => GetStream(); public static string InstructionsPrompt => GetString(); public static string InstructionsText(int years) => string.Format(GetString(), years); + public static string Status( + float rallods, + float countrymen, + float workers, + float land, + float landValue, + float plantingCost) + => string.Format( + workers == 0 ? StatusWithWorkers : StatusSansWorkers, + rallods, + (int)countrymen, + (int)workers, + (int)land, + landValue, + plantingCost); + + private static string StatusWithWorkers => GetString(); + private static string StatusSansWorkers => GetString(); + + public static string SellLandPrompt => GetString(); + public static string SellLandError(float farmLand) + { + var error = string.Format(GetString(), farmLand, _sellLandErrorShown ? "" : SellLandErrorReason); + _sellLandErrorShown = true; + return error; + } + private static string SellLandErrorReason => GetString(); + + public static string GiveRallodsPrompt => GetString(); + public static string GiveRallodsError(float rallods) => string.Format(GetString(), rallods); + + public static string PlantLandPrompt => GetString(); + public static string PlantLandError1 => GetString(); + public static string PlantLandError2(float farmLand) => string.Format(GetString(), farmLand); + public static string PlantLandError3(float rallods) => string.Format(GetString(), rallods); + + public static string PollutionPrompt => GetString(); + public static string PollutionError(float rallods) => string.Format(GetString(), rallods); + public static string SavedYearsPrompt => GetString(); public static string SavedYearsError(int years) => string.Format(GetString(), years); public static string SavedTreasuryPrompt => GetString(); @@ -17,27 +58,6 @@ internal static class Resource public static string SavedWorkersPrompt => GetString(); public static string SavedLandPrompt => GetString(); public static string SavedLandError => GetString(); - - internal static class Formats - { - public static string Player => GetString(); - public static string YouLose => GetString(); - } - - internal static class Prompts - { - public static string WantInstructions => GetString(); - public static string HowManyPlayers => GetString(); - public static string HowManyRows => GetString(); - public static string HowManyColumns => GetString(); - public static string TooManyColumns => GetString(); - } - - internal static class Strings - { - public static string TooManyColumns => GetString(); - public static string TooManyRows => GetString(); - } private static string GetString([CallerMemberName] string? name = null) { diff --git a/53_King/csharp/Resources/SellLandError.txt b/53_King/csharp/Resources/SellLandError.txt new file mode 100644 index 00000000..83e0266c --- /dev/null +++ b/53_King/csharp/Resources/SellLandError.txt @@ -0,0 +1,2 @@ +*** Think again. You only have {0} square miles of farm land. +{1} \ No newline at end of file diff --git a/53_King/csharp/Resources/SellLandErrorReason.txt b/53_King/csharp/Resources/SellLandErrorReason.txt new file mode 100644 index 00000000..836352bb --- /dev/null +++ b/53_King/csharp/Resources/SellLandErrorReason.txt @@ -0,0 +1,4 @@ + +(Foreign industry will only buy farm land because +forest land is uneconomical to strip mine due to trees, +thicker top soil, etc.) diff --git a/53_King/csharp/Resources/SellLandPrompt.txt b/53_King/csharp/Resources/SellLandPrompt.txt new file mode 100644 index 00000000..8d01c2c2 --- /dev/null +++ b/53_King/csharp/Resources/SellLandPrompt.txt @@ -0,0 +1 @@ +How many square miles do you wish to sell to industry \ No newline at end of file diff --git a/53_King/csharp/Resources/StatusSansWorkers.txt b/53_King/csharp/Resources/StatusSansWorkers.txt new file mode 100644 index 00000000..7efb84e7 --- /dev/null +++ b/53_King/csharp/Resources/StatusSansWorkers.txt @@ -0,0 +1,6 @@ + +You now have {0} rallods in the treasury. + {1} countrymen, and {3} sq. miles of land. +This year industry will buy land for {4} rallods per square mile. +Land currently costs {5} rallods per square mile to plant. + diff --git a/53_King/csharp/Resources/StatusWithWorkers.txt b/53_King/csharp/Resources/StatusWithWorkers.txt new file mode 100644 index 00000000..e7bc5c4a --- /dev/null +++ b/53_King/csharp/Resources/StatusWithWorkers.txt @@ -0,0 +1,6 @@ + +You now have {0} rallods in the treasury. + {1} countrymen, {2} foreign workers and {3} sq. miles of land. +This year industry will buy land for {4} rallods per square mile. +Land currently costs {5} rallods per square mile to plant. + diff --git a/53_King/csharp/ValidityTest.cs b/53_King/csharp/ValidityTest.cs new file mode 100644 index 00000000..f1aeb5ec --- /dev/null +++ b/53_King/csharp/ValidityTest.cs @@ -0,0 +1,26 @@ +namespace King; + +internal class ValidityTest +{ + private readonly Predicate _isValid; + private readonly Func _getError; + + public ValidityTest(Predicate isValid, string error) + : this(isValid, () => error) + { + } + + public ValidityTest(Predicate isValid, Func getError) + { + _isValid = isValid; + _getError = getError; + } + + public bool IsValid(float value, IReadWrite io) + { + if (_isValid(value)) { return true; } + + io.Write(_getError()); + return false; + } +} \ No newline at end of file diff --git a/53_King/king.bas b/53_King/king.bas index 7352fa58..5e9ae163 100644 --- a/53_King/king.bas +++ b/53_King/king.bas @@ -99,6 +99,7 @@ 1000 GOTO 600 1002 PRINT 1003 PRINT +1005 PRINT A 1010 A=INT(A-K) 1020 A4=A 1100 IF INT(I/100-B)>=0 THEN 1120