mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2026-01-10 04:07:28 -08:00
Add evaluation of deaths
This commit is contained in:
@@ -2,14 +2,15 @@ namespace King;
|
|||||||
|
|
||||||
internal class Country
|
internal class Country
|
||||||
{
|
{
|
||||||
|
private const int InitialLand = 1000;
|
||||||
|
|
||||||
private readonly IReadWrite _io;
|
private readonly IReadWrite _io;
|
||||||
private readonly IRandom _random;
|
private readonly IRandom _random;
|
||||||
private float _rallods;
|
private float _rallods;
|
||||||
private float _countrymen;
|
private float _countrymen;
|
||||||
private float _foreigners;
|
private float _foreigners;
|
||||||
private float _land;
|
private float _arableLand;
|
||||||
private float _plantingCost;
|
private float _industryLand;
|
||||||
private float _landValue;
|
|
||||||
|
|
||||||
public Country(IReadWrite io, IRandom random)
|
public Country(IReadWrite io, IRandom random)
|
||||||
: this(
|
: this(
|
||||||
@@ -18,7 +19,7 @@ internal class Country
|
|||||||
(int)(60000 + random.NextFloat(1000) - random.NextFloat(1000)),
|
(int)(60000 + random.NextFloat(1000) - random.NextFloat(1000)),
|
||||||
(int)(500 + random.NextFloat(10) - random.NextFloat(10)),
|
(int)(500 + random.NextFloat(10) - random.NextFloat(10)),
|
||||||
0,
|
0,
|
||||||
2000)
|
InitialLand)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,35 +30,38 @@ internal class Country
|
|||||||
_rallods = rallods;
|
_rallods = rallods;
|
||||||
_countrymen = countrymen;
|
_countrymen = countrymen;
|
||||||
_foreigners = foreigners;
|
_foreigners = foreigners;
|
||||||
_land = land;
|
_arableLand = land;
|
||||||
|
|
||||||
_plantingCost = random.Next(10, 15);
|
|
||||||
_landValue = random.Next(95, 105);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Status => Resource.Status(_rallods, _countrymen, _foreigners, _land, _landValue, _plantingCost);
|
public string GetStatus(int landValue, int plantingCost)
|
||||||
private float FarmLand => _land - 1000;
|
=> 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(
|
if (_io.TryReadValue(
|
||||||
SellLandPrompt,
|
SellLandPrompt,
|
||||||
out var landSold,
|
out landSold,
|
||||||
new ValidityTest(v => v <= FarmLand, () => SellLandError(FarmLand))))
|
new ValidityTest(v => v <= FarmLand, () => SellLandError(FarmLand))))
|
||||||
{
|
{
|
||||||
_land = (int)(_land - landSold);
|
_arableLand = (int)(_arableLand - landSold);
|
||||||
_rallods = (int)(_rallods + landSold * _landValue);
|
_rallods = (int)(_rallods + landSold * landValue);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DistributeRallods()
|
public bool DistributeRallods(out float rallodsGiven)
|
||||||
{
|
{
|
||||||
if (_io.TryReadValue(
|
if (_io.TryReadValue(
|
||||||
GiveRallodsPrompt,
|
GiveRallodsPrompt,
|
||||||
out var rallodsGiven,
|
out rallodsGiven,
|
||||||
new ValidityTest(v => v <= _rallods, () => GiveRallodsError(_rallods))))
|
new ValidityTest(v => v <= _rallods, () => GiveRallodsError(_rallods))))
|
||||||
{
|
{
|
||||||
_rallods = (int)(_rallods - rallodsGiven);
|
_rallods = (int)(_rallods - rallodsGiven);
|
||||||
@@ -67,35 +71,48 @@ internal class Country
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool PlantLand()
|
public bool PlantLand(int plantingCost, out float landPlanted)
|
||||||
{
|
{
|
||||||
if (_rallods > 0 &&
|
if (_io.TryReadValue(
|
||||||
_io.TryReadValue(
|
|
||||||
PlantLandPrompt,
|
PlantLandPrompt,
|
||||||
out var landPlanted,
|
out landPlanted,
|
||||||
new ValidityTest(v => v <= _countrymen * 2, PlantLandError1),
|
new ValidityTest(v => v <= _countrymen * 2, PlantLandError1),
|
||||||
new ValidityTest(v => v <= FarmLand, PlantLandError2(FarmLand)),
|
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 true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ControlPollution()
|
public bool ControlPollution(out float rallodsSpent)
|
||||||
{
|
{
|
||||||
if (_rallods > 0 &&
|
if (_io.TryReadValue(
|
||||||
_io.TryReadValue(
|
|
||||||
PollutionPrompt,
|
PollutionPrompt,
|
||||||
out var rallodsGiven,
|
out rallodsSpent,
|
||||||
new ValidityTest(v => v <= _rallods, () => PollutionError(_rallods))))
|
new ValidityTest(v => v <= _rallods, () => PollutionError(_rallods))))
|
||||||
{
|
{
|
||||||
_rallods = (int)(_rallods - rallodsGiven);
|
_rallods = (int)(_rallods - rallodsSpent);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ internal static class IOExtensions
|
|||||||
io.TryReadValue(SavedWorkersPrompt, out var workers) &&
|
io.TryReadValue(SavedWorkersPrompt, out var workers) &&
|
||||||
io.TryReadValue(SavedLandPrompt, v => v is > 1000 and <= 2000, SavedLandError, out var land))
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,37 +5,40 @@ internal class Reign
|
|||||||
public const int MaxTerm = 8;
|
public const int MaxTerm = 8;
|
||||||
|
|
||||||
private readonly IReadWrite _io;
|
private readonly IReadWrite _io;
|
||||||
|
private readonly IRandom _random;
|
||||||
private readonly Country _country;
|
private readonly Country _country;
|
||||||
private float _year;
|
private float _yearNumber;
|
||||||
|
|
||||||
public Reign(IReadWrite io, IRandom random)
|
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;
|
_io = io;
|
||||||
|
_random = random;
|
||||||
_country = country;
|
_country = country;
|
||||||
_year = year;
|
_yearNumber = year;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool PlayYear()
|
public bool PlayYear()
|
||||||
{
|
{
|
||||||
_io.Write(_country.Status);
|
var year = new Year(_country, _random);
|
||||||
|
|
||||||
var playerSoldLand = _country.SellLand();
|
_io.Write(year.Status);
|
||||||
var playerDistributedRallods = _country.DistributeRallods();
|
|
||||||
var playerPlantedLand = _country.PlantLand();
|
|
||||||
var playerControlledPollution = _country.ControlPollution();
|
|
||||||
|
|
||||||
if (playerSoldLand || playerDistributedRallods || playerPlantedLand || playerControlledPollution)
|
if (year.GetPlayerActions())
|
||||||
{
|
{
|
||||||
_year++;
|
_io.WriteLine();
|
||||||
|
_io.WriteLine();
|
||||||
|
year.EvaluateResults(_io, _random);
|
||||||
|
_yearNumber++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
_io.WriteLine();
|
||||||
_io.Write(Goodbye);
|
_io.Write(Goodbye);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
1
53_King/csharp/Resources/DeathsPollution.txt
Normal file
1
53_King/csharp/Resources/DeathsPollution.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{0} countrymen died of carbon-monoxide and dust inhalation
|
||||||
1
53_King/csharp/Resources/DeathsStarvation.txt
Normal file
1
53_King/csharp/Resources/DeathsStarvation.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{0} countrymen died of starvation
|
||||||
3
53_King/csharp/Resources/EndAlso.txt
Normal file
3
53_King/csharp/Resources/EndAlso.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
also had your left eye gouged out!
|
||||||
|
;have also gained a very bad reputation.
|
||||||
|
;have also been declared national fink.
|
||||||
10
53_King/csharp/Resources/EndCongratulations.txt
Normal file
10
53_King/csharp/Resources/EndCongratulations.txt
Normal file
@@ -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.
|
||||||
|
|
||||||
|
|
||||||
3
53_King/csharp/Resources/EndConsequences.txt
Normal file
3
53_King/csharp/Resources/EndConsequences.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
You have been thrown out of office and are now
|
||||||
|
residing in prison.;
|
||||||
|
You have been assassinated.
|
||||||
7
53_King/csharp/Resources/EndForeignWorkers.txt
Normal file
7
53_King/csharp/Resources/EndForeignWorkers.txt
Normal file
@@ -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}
|
||||||
|
|
||||||
5
53_King/csharp/Resources/EndManyDead.txt
Normal file
5
53_King/csharp/Resources/EndManyDead.txt
Normal file
@@ -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}
|
||||||
|
|
||||||
7
53_King/csharp/Resources/EndMoneyLeftOver.txt
Normal file
7
53_King/csharp/Resources/EndMoneyLeftOver.txt
Normal file
@@ -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.
|
||||||
|
|
||||||
|
|
||||||
7
53_King/csharp/Resources/EndOneThirdDead.txt
Normal file
7
53_King/csharp/Resources/EndOneThirdDead.txt
Normal file
@@ -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}
|
||||||
|
|
||||||
1
53_King/csharp/Resources/FuneralExpenses.txt
Normal file
1
53_King/csharp/Resources/FuneralExpenses.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
You were forced to spend {0} rallods on funeral expenses
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
Goodbye.
|
Goodbye.
|
||||||
(If you wish to continue this game at a later date, answer
|
(If you wish to continue this game at a later date, answer
|
||||||
'again' when asked if you want instructions at the start
|
'again' when asked if you want instructions at the start
|
||||||
|
|||||||
0
53_King/csharp/Resources/InsufficientReserves.txt
Normal file
0
53_King/csharp/Resources/InsufficientReserves.txt
Normal file
5
53_King/csharp/Resources/PollutionEffect.txt
Normal file
5
53_King/csharp/Resources/PollutionEffect.txt
Normal file
@@ -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.
|
||||||
@@ -51,6 +51,28 @@ internal static class Resource
|
|||||||
public static string PollutionPrompt => GetString();
|
public static string PollutionPrompt => GetString();
|
||||||
public static string PollutionError(float rallods) => string.Format(GetString(), rallods);
|
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 SavedYearsPrompt => GetString();
|
||||||
public static string SavedYearsError(int years) => string.Format(GetString(), years);
|
public static string SavedYearsError(int years) => string.Format(GetString(), years);
|
||||||
public static string SavedTreasuryPrompt => GetString();
|
public static string SavedTreasuryPrompt => GetString();
|
||||||
@@ -61,6 +83,8 @@ internal static class Resource
|
|||||||
|
|
||||||
public static string Goodbye => GetString();
|
public static string Goodbye => GetString();
|
||||||
|
|
||||||
|
private static string[] GetStrings([CallerMemberName] string? name = null) => GetString(name).Split(';');
|
||||||
|
|
||||||
private static string GetString([CallerMemberName] string? name = null)
|
private static string GetString([CallerMemberName] string? name = null)
|
||||||
{
|
{
|
||||||
using var stream = GetStream(name);
|
using var stream = GetStream(name);
|
||||||
|
|||||||
93
53_King/csharp/Year.cs
Normal file
93
53_King/csharp/Year.cs
Normal file
@@ -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, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -99,7 +99,6 @@
|
|||||||
1000 GOTO 600
|
1000 GOTO 600
|
||||||
1002 PRINT
|
1002 PRINT
|
||||||
1003 PRINT
|
1003 PRINT
|
||||||
1005 PRINT A
|
|
||||||
1010 A=INT(A-K)
|
1010 A=INT(A-K)
|
||||||
1020 A4=A
|
1020 A4=A
|
||||||
1100 IF INT(I/100-B)>=0 THEN 1120
|
1100 IF INT(I/100-B)>=0 THEN 1120
|
||||||
|
|||||||
Reference in New Issue
Block a user