diff --git a/53_King/csharp/Country.cs b/53_King/csharp/Country.cs index 5b47c50a..b1b473e7 100644 --- a/53_King/csharp/Country.cs +++ b/53_King/csharp/Country.cs @@ -2,14 +2,15 @@ namespace King; internal class Country { + private const int InitialLand = 1000; + private readonly IReadWrite _io; private readonly IRandom _random; private float _rallods; private float _countrymen; private float _foreigners; - private float _land; - private float _plantingCost; - private float _landValue; + private float _arableLand; + private float _industryLand; public Country(IReadWrite io, IRandom random) : this( @@ -18,7 +19,7 @@ internal class Country (int)(60000 + random.NextFloat(1000) - random.NextFloat(1000)), (int)(500 + random.NextFloat(10) - random.NextFloat(10)), 0, - 2000) + InitialLand) { } @@ -29,35 +30,38 @@ internal class Country _rallods = rallods; _countrymen = countrymen; _foreigners = foreigners; - _land = land; - - _plantingCost = random.Next(10, 15); - _landValue = random.Next(95, 105); + _arableLand = land; } - public string Status => Resource.Status(_rallods, _countrymen, _foreigners, _land, _landValue, _plantingCost); - private float FarmLand => _land - 1000; + public string GetStatus(int landValue, int plantingCost) + => Resource.Status(_rallods, _countrymen, _foreigners, _arableLand, landValue, plantingCost); + + public float Countrymen => _countrymen; + private float FarmLand => _arableLand; + public bool HasRallods => _rallods > 0; + public float Rallods => _rallods; + public float IndustryLand => InitialLand - _arableLand; - public bool SellLand() + public bool SellLand(int landValue, out float landSold) { if (_io.TryReadValue( SellLandPrompt, - out var landSold, + out landSold, new ValidityTest(v => v <= FarmLand, () => SellLandError(FarmLand)))) { - _land = (int)(_land - landSold); - _rallods = (int)(_rallods + landSold * _landValue); + _arableLand = (int)(_arableLand - landSold); + _rallods = (int)(_rallods + landSold * landValue); return true; } return false; } - public bool DistributeRallods() + public bool DistributeRallods(out float rallodsGiven) { if (_io.TryReadValue( GiveRallodsPrompt, - out var rallodsGiven, + out rallodsGiven, new ValidityTest(v => v <= _rallods, () => GiveRallodsError(_rallods)))) { _rallods = (int)(_rallods - rallodsGiven); @@ -67,35 +71,48 @@ internal class Country return false; } - public bool PlantLand() + public bool PlantLand(int plantingCost, out float landPlanted) { - if (_rallods > 0 && - _io.TryReadValue( + if (_io.TryReadValue( PlantLandPrompt, - out var landPlanted, + out landPlanted, new ValidityTest(v => v <= _countrymen * 2, PlantLandError1), new ValidityTest(v => v <= FarmLand, PlantLandError2(FarmLand)), - new ValidityTest(v => v * _plantingCost <= _rallods, PlantLandError3(_rallods)))) + new ValidityTest(v => v * plantingCost <= _rallods, PlantLandError3(_rallods)))) { - _rallods -= (int)(landPlanted * _plantingCost); + _rallods -= (int)(landPlanted * plantingCost); return true; } return false; } - public bool ControlPollution() + public bool ControlPollution(out float rallodsSpent) { - if (_rallods > 0 && - _io.TryReadValue( + if (_io.TryReadValue( PollutionPrompt, - out var rallodsGiven, + out rallodsSpent, new ValidityTest(v => v <= _rallods, () => PollutionError(_rallods)))) { - _rallods = (int)(_rallods - rallodsGiven); + _rallods = (int)(_rallods - rallodsSpent); return true; } return false; } + + public bool TrySpend(float amount, float landValue) + { + if (_rallods >= amount) + { + _rallods -= amount; + return true; + } + + _arableLand = (int)(_arableLand - (int)(amount - _rallods) / landValue); + _rallods = 0; + return false; + } + + public void RemoveTheDead(int deaths) => _countrymen = (int)(_countrymen - deaths); } diff --git a/53_King/csharp/IOExtensions.cs b/53_King/csharp/IOExtensions.cs index e59bf4c0..dbb3079a 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(io, random, rallods, countrymen, workers, land), years + 1); + reign = new Reign(io, random, new Country(io, random, rallods, countrymen, workers, land), years + 1); return true; } diff --git a/53_King/csharp/Reign.cs b/53_King/csharp/Reign.cs index 2bdc9b89..727f71d3 100644 --- a/53_King/csharp/Reign.cs +++ b/53_King/csharp/Reign.cs @@ -5,37 +5,40 @@ internal class Reign public const int MaxTerm = 8; private readonly IReadWrite _io; + private readonly IRandom _random; private readonly Country _country; - private float _year; + private float _yearNumber; public Reign(IReadWrite io, IRandom random) - : this(io, new Country(io, random), 1) + : this(io, random, new Country(io, random), 1) { } - public Reign(IReadWrite io, Country country, float year) + public Reign(IReadWrite io, IRandom random, Country country, float year) { _io = io; + _random = random; _country = country; - _year = year; + _yearNumber = year; } public bool PlayYear() { - _io.Write(_country.Status); + var year = new Year(_country, _random); - var playerSoldLand = _country.SellLand(); - var playerDistributedRallods = _country.DistributeRallods(); - var playerPlantedLand = _country.PlantLand(); - var playerControlledPollution = _country.ControlPollution(); + _io.Write(year.Status); - if (playerSoldLand || playerDistributedRallods || playerPlantedLand || playerControlledPollution) + if (year.GetPlayerActions()) { - _year++; + _io.WriteLine(); + _io.WriteLine(); + year.EvaluateResults(_io, _random); + _yearNumber++; return true; } else { + _io.WriteLine(); _io.Write(Goodbye); return false; } diff --git a/53_King/csharp/Resources/DeathsPollution.txt b/53_King/csharp/Resources/DeathsPollution.txt new file mode 100644 index 00000000..bf28d9a7 --- /dev/null +++ b/53_King/csharp/Resources/DeathsPollution.txt @@ -0,0 +1 @@ + {0} countrymen died of carbon-monoxide and dust inhalation \ No newline at end of file diff --git a/53_King/csharp/Resources/DeathsStarvation.txt b/53_King/csharp/Resources/DeathsStarvation.txt new file mode 100644 index 00000000..af275cf4 --- /dev/null +++ b/53_King/csharp/Resources/DeathsStarvation.txt @@ -0,0 +1 @@ + {0} countrymen died of starvation \ No newline at end of file diff --git a/53_King/csharp/Resources/EndAlso.txt b/53_King/csharp/Resources/EndAlso.txt new file mode 100644 index 00000000..084b9a82 --- /dev/null +++ b/53_King/csharp/Resources/EndAlso.txt @@ -0,0 +1,3 @@ +also had your left eye gouged out! +;have also gained a very bad reputation. +;have also been declared national fink. diff --git a/53_King/csharp/Resources/EndCongratulations.txt b/53_King/csharp/Resources/EndCongratulations.txt new file mode 100644 index 00000000..ef1ff203 --- /dev/null +++ b/53_King/csharp/Resources/EndCongratulations.txt @@ -0,0 +1,10 @@ + + +Congratulations!!!!!!!!!!!!!!!!!! +You have successfully completed your {0} year term +of office. You were, of course, extremely lucky, but +nevertheless, it's quite an achievement. Goodbye and good +luck - you'll probably need it if you're the type that +plays this game. + + diff --git a/53_King/csharp/Resources/EndConsequences.txt b/53_King/csharp/Resources/EndConsequences.txt new file mode 100644 index 00000000..61ebfd25 --- /dev/null +++ b/53_King/csharp/Resources/EndConsequences.txt @@ -0,0 +1,3 @@ +You have been thrown out of office and are now +residing in prison.; +You have been assassinated. diff --git a/53_King/csharp/Resources/EndForeignWorkers.txt b/53_King/csharp/Resources/EndForeignWorkers.txt new file mode 100644 index 00000000..76c04c3d --- /dev/null +++ b/53_King/csharp/Resources/EndForeignWorkers.txt @@ -0,0 +1,7 @@ + + +The number of foreign workers has exceeded the number +of countrymen. As a minority, they have revolted and +taken over the country. +{0} + diff --git a/53_King/csharp/Resources/EndManyDead.txt b/53_King/csharp/Resources/EndManyDead.txt new file mode 100644 index 00000000..70cd95f0 --- /dev/null +++ b/53_King/csharp/Resources/EndManyDead.txt @@ -0,0 +1,5 @@ +{0} countrymen died in one year!!!!! +due to this extreme mismanagement, you have not only +been impeached and thrown out of office, but you +{1} + diff --git a/53_King/csharp/Resources/EndMoneyLeftOver.txt b/53_King/csharp/Resources/EndMoneyLeftOver.txt new file mode 100644 index 00000000..e194a9fd --- /dev/null +++ b/53_King/csharp/Resources/EndMoneyLeftOver.txt @@ -0,0 +1,7 @@ + +Money was left over in the treasury which you did +not spend. As a result, some of your countrymen died +of starvation. The public is enraged and you have +been forced to resign. + + diff --git a/53_King/csharp/Resources/EndOneThirdDead.txt b/53_King/csharp/Resources/EndOneThirdDead.txt new file mode 100644 index 00000000..e1761dfe --- /dev/null +++ b/53_King/csharp/Resources/EndOneThirdDead.txt @@ -0,0 +1,7 @@ + + +Over one third of the population has died since you +were elected to office. The people (remaining) +hate your guts. +{0} + diff --git a/53_King/csharp/Resources/FuneralExpenses.txt b/53_King/csharp/Resources/FuneralExpenses.txt new file mode 100644 index 00000000..3aff58eb --- /dev/null +++ b/53_King/csharp/Resources/FuneralExpenses.txt @@ -0,0 +1 @@ + You were forced to spend {0} rallods on funeral expenses \ No newline at end of file diff --git a/53_King/csharp/Resources/Goodbye.txt b/53_King/csharp/Resources/Goodbye.txt index 325890a5..67543c04 100644 --- a/53_King/csharp/Resources/Goodbye.txt +++ b/53_King/csharp/Resources/Goodbye.txt @@ -1,4 +1,3 @@ - Goodbye. (If you wish to continue this game at a later date, answer 'again' when asked if you want instructions at the start diff --git a/53_King/csharp/Resources/InsufficientReserves.txt b/53_King/csharp/Resources/InsufficientReserves.txt new file mode 100644 index 00000000..e69de29b diff --git a/53_King/csharp/Resources/PollutionEffect.txt b/53_King/csharp/Resources/PollutionEffect.txt new file mode 100644 index 00000000..b3535c3d --- /dev/null +++ b/53_King/csharp/Resources/PollutionEffect.txt @@ -0,0 +1,5 @@ +fish population has dwindled due to water pollution. +;air pollution is killing game bird population. +;mineral baths are being ruined by water pollution. +;unpleasant smog is discouraging sun bathers. +;hotels are looking shabby due to smog grit. diff --git a/53_King/csharp/Resources/Resource.cs b/53_King/csharp/Resources/Resource.cs index cf555583..496bc250 100644 --- a/53_King/csharp/Resources/Resource.cs +++ b/53_King/csharp/Resources/Resource.cs @@ -51,6 +51,28 @@ internal static class Resource public static string PollutionPrompt => GetString(); public static string PollutionError(float rallods) => string.Format(GetString(), rallods); + public static string DeathsStarvation(float deaths) => string.Format(GetString(), (int)deaths); + public static string DeathsPollution(int deaths) => string.Format(GetString(), deaths); + public static string FuneralExpenses(int expenses) => string.Format(GetString(), expenses); + public static string InsufficientReserves => GetString(); + + private static string PollutionEffect(IRandom random) => GetStrings()[random.Next(5)]; + + private static string EndAlso(IRandom random) + => random.Next(10) switch + { + <= 3 => GetStrings()[0], + <= 6 => GetStrings()[1], + _ => GetStrings()[2] + }; + + public static string EndCongratulations(int termLength) => string.Format(GetString(), termLength); + private static string EndConsequences(IRandom random) => GetStrings()[random.Next(2)]; + public static string EndForeignWorkers(IRandom random) => string.Format(GetString(), EndConsequences(random)); + public static string EndManyDead(int deaths, IRandom random) => string.Format(GetString(), deaths, EndAlso(random)); + public static string EndMoneyLeftOver(int termLength) => string.Format(GetString(), termLength); + public static string EndOneThirdDead(IRandom random) => string.Format(GetString(), EndConsequences(random)); + public static string SavedYearsPrompt => GetString(); public static string SavedYearsError(int years) => string.Format(GetString(), years); public static string SavedTreasuryPrompt => GetString(); @@ -61,6 +83,8 @@ internal static class Resource public static string Goodbye => GetString(); + private static string[] GetStrings([CallerMemberName] string? name = null) => GetString(name).Split(';'); + private static string GetString([CallerMemberName] string? name = null) { using var stream = GetStream(name); diff --git a/53_King/csharp/Year.cs b/53_King/csharp/Year.cs new file mode 100644 index 00000000..18f208e4 --- /dev/null +++ b/53_King/csharp/Year.cs @@ -0,0 +1,93 @@ +using System.Text; + +namespace King; + +internal class Year +{ + private readonly Country _country; + private readonly IRandom _random; + private readonly int _plantingCost; + private readonly int _landValue; + + private float _landSold; + private float _rallodsDistributed; + private float _landPlanted; + private float _pollutionControlCost; + + public Year(Country country, IRandom random) + { + _country = country; + _random = random; + + _plantingCost = random.Next(10, 15); + _landValue = random.Next(95, 105); + } + + public string Status => _country.GetStatus(_landValue, _plantingCost); + + public bool GetPlayerActions() + { + var playerSoldLand = _country.SellLand(_landValue, out _landSold); + var playerDistributedRallods = _country.DistributeRallods(out _rallodsDistributed); + var playerPlantedLand = _country.HasRallods && _country.PlantLand(_plantingCost, out _landPlanted); + var playerControlledPollution = _country.HasRallods && _country.ControlPollution(out _pollutionControlCost); + + return playerSoldLand || playerDistributedRallods || playerPlantedLand || playerControlledPollution; + } + + public Result EvaluateResults(IReadWrite io) + { + var unspentRallods = _country.Rallods; + var statusUpdate = new StringBuilder(); + + var result = EvaluateDeaths(statusUpdate, out var deaths); + + io.Write(statusUpdate); + + return Result.Continue; + } + + public Result? EvaluateDeaths(StringBuilder statusUpdate, out int deaths) + { + deaths = default; + + var supportedCountrymen = _rallodsDistributed / 100; + var starvationDeaths = _country.Countrymen - supportedCountrymen; + if (starvationDeaths > 0) + { + if (supportedCountrymen < 50) { return Result.GameOver(EndOneThirdDead(_random)); } + statusUpdate.AppendLine(DeathsStarvation(starvationDeaths)); + } + + var pollutionControl = _pollutionControlCost >= 25 ? _pollutionControlCost / 25 : 1; + var pollutionDeaths = (int)(_random.Next((int)_country.IndustryLand) / pollutionControl); + if (pollutionDeaths > 0) + { + statusUpdate.AppendLine(DeathsPollution(pollutionDeaths)); + } + + deaths = (int)(starvationDeaths + pollutionDeaths); + if (deaths > 0) + { + var funeralCosts = deaths * 9; + statusUpdate.AppendLine(FuneralExpenses(funeralCosts)); + + if (!_country.TrySpend(funeralCosts, _landValue)) + { + statusUpdate.AppendLine(InsufficientReserves); + } + + _country.RemoveTheDead(deaths); + } + + return null; + } + + + internal record struct Result (bool IsGameOver, string Message) + { + internal static Result GameOver(string message) => new(true, message); + internal static Result Continue => new(false, ""); + } +} + diff --git a/53_King/king.bas b/53_King/king.bas index 5e9ae163..7352fa58 100644 --- a/53_King/king.bas +++ b/53_King/king.bas @@ -99,7 +99,6 @@ 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