mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-23 07:29:02 -08:00
@@ -1,10 +1,10 @@
|
||||
## King
|
||||
|
||||
This is one of the most comprehensive, difficult, and interesting games. (If you’ve never played one of these games, start with HAMMURABI.)
|
||||
This is one of the most comprehensive, difficult, and interesting games. (If you've never played one of these games, start with HAMMURABI.)
|
||||
|
||||
In this game, you are Premier of Setats Detinu, a small communist island 30 by 70 miles long. Your job is to decide upon the budget of your country and distribute money to your country from the communal treasury.
|
||||
|
||||
The money system is Rollods; each person needs 100 Rallods per year to survive. Your country’s income comes from farm produce and tourists visiting your magnificent forests, hunting, fishing, etc. Part of your land is farm land but it also has an excellent mineral content and may be sold to foreign industry for strip mining. Industry import and support their own workers. Crops cost between 10 and 15 Rallods per square mile to plant, cultivate, and harvest. Your goal is to complete an eight-year term of office without major mishap. A word of warning: it isn’t easy!
|
||||
The money system is Rollods; each person needs 100 Rallods per year to survive. Your country's income comes from farm produce and tourists visiting your magnificent forests, hunting, fishing, etc. Part of your land is farm land but it also has an excellent mineral content and may be sold to foreign industry for strip mining. Industry import and support their own workers. Crops cost between 10 and 15 Rallods per square mile to plant, cultivate, and harvest. Your goal is to complete an eight-year term of office without major mishap. A word of warning: it isn't easy!
|
||||
|
||||
The author of this program is James A. Storer who wrote it while a student at Lexington High School.
|
||||
|
||||
@@ -66,3 +66,15 @@ On basic line 1997 it is:
|
||||
but it should be:
|
||||
|
||||
1997 PRINT " AND 1,000 SQ. MILES OF FOREST LAND."
|
||||
|
||||
### Bug 4
|
||||
|
||||
On basic line 1310 we see this:
|
||||
|
||||
1310 IF C=0 THEN 1324
|
||||
1320 PRINT "OF ";INT(J);"SQ. MILES PLANTED,";
|
||||
1324 ...
|
||||
|
||||
but it should probably be:
|
||||
|
||||
1310 IF J=0 THEN 1324
|
||||
|
||||
133
53_King/csharp/Country.cs
Normal file
133
53_King/csharp/Country.cs
Normal file
@@ -0,0 +1,133 @@
|
||||
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 _arableLand;
|
||||
private float _industryLand;
|
||||
|
||||
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)),
|
||||
0,
|
||||
InitialLand)
|
||||
{
|
||||
}
|
||||
|
||||
public Country(IReadWrite io, IRandom random, float rallods, float countrymen, float foreigners, float land)
|
||||
{
|
||||
_io = io;
|
||||
_random = random;
|
||||
_rallods = rallods;
|
||||
_countrymen = countrymen;
|
||||
_foreigners = foreigners;
|
||||
_arableLand = land;
|
||||
}
|
||||
|
||||
public string GetStatus(int landValue, int plantingCost)
|
||||
=> Resource.Status(_rallods, _countrymen, _foreigners, _arableLand, landValue, plantingCost);
|
||||
|
||||
public float Countrymen => _countrymen;
|
||||
public float Workers => _foreigners;
|
||||
public bool HasWorkers => _foreigners > 0;
|
||||
private float FarmLand => _arableLand;
|
||||
public bool HasRallods => _rallods > 0;
|
||||
public float Rallods => _rallods;
|
||||
public float IndustryLand => InitialLand - _arableLand;
|
||||
public int PreviousTourismIncome { get; private set; }
|
||||
|
||||
public bool SellLand(int landValue, out float landSold)
|
||||
{
|
||||
if (_io.TryReadValue(
|
||||
SellLandPrompt,
|
||||
out landSold,
|
||||
new ValidityTest(v => v <= FarmLand, () => SellLandError(FarmLand))))
|
||||
{
|
||||
_arableLand = (int)(_arableLand - landSold);
|
||||
_rallods = (int)(_rallods + landSold * landValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool DistributeRallods(out float rallodsGiven)
|
||||
{
|
||||
if (_io.TryReadValue(
|
||||
GiveRallodsPrompt,
|
||||
out rallodsGiven,
|
||||
new ValidityTest(v => v <= _rallods, () => GiveRallodsError(_rallods))))
|
||||
{
|
||||
_rallods = (int)(_rallods - rallodsGiven);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool PlantLand(int plantingCost, out float landPlanted)
|
||||
{
|
||||
if (_io.TryReadValue(
|
||||
PlantLandPrompt,
|
||||
out 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(out float rallodsSpent)
|
||||
{
|
||||
if (_io.TryReadValue(
|
||||
PollutionPrompt,
|
||||
out rallodsSpent,
|
||||
new ValidityTest(v => v <= _rallods, () => PollutionError(_rallods))))
|
||||
{
|
||||
_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);
|
||||
|
||||
public void Migration(int migration) => _countrymen = (int)(_countrymen + migration);
|
||||
|
||||
public void AddWorkers(int newWorkers) => _foreigners = (int)(_foreigners + newWorkers);
|
||||
|
||||
public void SellCrops(int income) => _rallods = (int)(_rallods + income);
|
||||
|
||||
public void EntertainTourists(int income)
|
||||
{
|
||||
PreviousTourismIncome = income;
|
||||
_rallods = (int)(_rallods + income);
|
||||
}
|
||||
}
|
||||
47
53_King/csharp/Game.cs
Normal file
47
53_King/csharp/Game.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
namespace King;
|
||||
|
||||
internal class Game
|
||||
{
|
||||
const int TermOfOffice = 8;
|
||||
|
||||
private readonly IReadWrite _io;
|
||||
private readonly IRandom _random;
|
||||
|
||||
public Game(IReadWrite io, IRandom random)
|
||||
{
|
||||
_io = io;
|
||||
_random = random;
|
||||
}
|
||||
|
||||
public void Play()
|
||||
{
|
||||
_io.Write(Title);
|
||||
|
||||
var reign = SetUpReign();
|
||||
if (reign != null)
|
||||
{
|
||||
while (reign.PlayYear());
|
||||
}
|
||||
|
||||
_io.WriteLine();
|
||||
_io.WriteLine();
|
||||
}
|
||||
|
||||
private Reign? SetUpReign()
|
||||
{
|
||||
var response = _io.ReadString(InstructionsPrompt).ToUpper();
|
||||
|
||||
if (response.Equals("Again", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return _io.TryReadGameData(_random, out var reign) ? reign : null;
|
||||
}
|
||||
|
||||
if (!response.StartsWith("N", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
_io.Write(InstructionsText(TermOfOffice));
|
||||
}
|
||||
|
||||
_io.WriteLine();
|
||||
return new Reign(_io, _random);
|
||||
}
|
||||
}
|
||||
61
53_King/csharp/IOExtensions.cs
Normal file
61
53_King/csharp/IOExtensions.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using static King.Resources.Resource;
|
||||
|
||||
namespace King;
|
||||
|
||||
internal static class IOExtensions
|
||||
{
|
||||
internal static bool TryReadGameData(this IReadWrite io, IRandom random, [NotNullWhen(true)] out Reign? reign)
|
||||
{
|
||||
if (io.TryReadValue(SavedYearsPrompt, v => v < Reign.MaxTerm, SavedYearsError(Reign.MaxTerm), out var years) &&
|
||||
io.TryReadValue(SavedTreasuryPrompt, out var rallods) &&
|
||||
io.TryReadValue(SavedCountrymenPrompt, out var countrymen) &&
|
||||
io.TryReadValue(SavedWorkersPrompt, out var workers) &&
|
||||
io.TryReadValue(SavedLandPrompt, v => v is > 1000 and <= 2000, SavedLandError, out var land))
|
||||
{
|
||||
reign = new Reign(io, random, new Country(io, random, rallods, countrymen, workers, land), years + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
reign = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
internal static bool TryReadValue(
|
||||
this IReadWrite io,
|
||||
string prompt,
|
||||
Predicate<float> isValid,
|
||||
string error,
|
||||
out float value)
|
||||
=> io.TryReadValue(prompt, isValid, () => error, out value);
|
||||
|
||||
internal static bool TryReadValue(
|
||||
this IReadWrite io,
|
||||
string prompt,
|
||||
Predicate<float> isValid,
|
||||
Func<string> getError,
|
||||
out float value)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
value = io.ReadNumber(prompt);
|
||||
if (value < 0) { return false; }
|
||||
if (isValid(value)) { return true; }
|
||||
|
||||
io.Write(getError());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,4 +6,12 @@
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources/*.txt" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\00_Common\dotnet\Games.Common\Games.Common.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
7
53_King/csharp/Program.cs
Normal file
7
53_King/csharp/Program.cs
Normal file
@@ -0,0 +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();
|
||||
45
53_King/csharp/Reign.cs
Normal file
45
53_King/csharp/Reign.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
namespace King;
|
||||
|
||||
internal class Reign
|
||||
{
|
||||
public const int MaxTerm = 8;
|
||||
|
||||
private readonly IReadWrite _io;
|
||||
private readonly IRandom _random;
|
||||
private readonly Country _country;
|
||||
private float _yearNumber;
|
||||
|
||||
public Reign(IReadWrite io, IRandom random)
|
||||
: this(io, random, new Country(io, random), 1)
|
||||
{
|
||||
}
|
||||
|
||||
public Reign(IReadWrite io, IRandom random, Country country, float year)
|
||||
{
|
||||
_io = io;
|
||||
_random = random;
|
||||
_country = country;
|
||||
_yearNumber = year;
|
||||
}
|
||||
|
||||
public bool PlayYear()
|
||||
{
|
||||
var year = new Year(_country, _random, _io);
|
||||
|
||||
_io.Write(year.Status);
|
||||
|
||||
var result = year.GetPlayerActions() ?? year.EvaluateResults() ?? IsAtEndOfTerm();
|
||||
if (result.IsGameOver)
|
||||
{
|
||||
_io.WriteLine(result.Message);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private Result IsAtEndOfTerm()
|
||||
=> _yearNumber == MaxTerm
|
||||
? Result.GameOver(EndCongratulations(MaxTerm))
|
||||
: Result.Continue;
|
||||
}
|
||||
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
|
||||
1
53_King/csharp/Resources/Emigration.txt
Normal file
1
53_King/csharp/Resources/Emigration.txt
Normal file
@@ -0,0 +1 @@
|
||||
{0} countrymen left the island.
|
||||
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
53_King/csharp/Resources/GiveRallodsError.txt
Normal file
1
53_King/csharp/Resources/GiveRallodsError.txt
Normal file
@@ -0,0 +1 @@
|
||||
Think again. You've only got {0} rallods in the treasury.
|
||||
1
53_King/csharp/Resources/GiveRallodsPrompt.txt
Normal file
1
53_King/csharp/Resources/GiveRallodsPrompt.txt
Normal file
@@ -0,0 +1 @@
|
||||
How many rallods will you distribute among your countrymen
|
||||
4
53_King/csharp/Resources/Goodbye.txt
Normal file
4
53_King/csharp/Resources/Goodbye.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
Goodbye.
|
||||
(If you wish to continue this game at a later date, answer
|
||||
'again' when asked if you want instructions at the start
|
||||
of the game).
|
||||
2
53_King/csharp/Resources/Harvest.txt
Normal file
2
53_King/csharp/Resources/Harvest.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
you harvested {0} sq. miles of crops.
|
||||
{1}making {2} rallods.
|
||||
1
53_King/csharp/Resources/HarvestReason.txt
Normal file
1
53_King/csharp/Resources/HarvestReason.txt
Normal file
@@ -0,0 +1 @@
|
||||
(Due to increased air and water pollution from foreign industry.)
|
||||
1
53_King/csharp/Resources/Immigration.txt
Normal file
1
53_King/csharp/Resources/Immigration.txt
Normal file
@@ -0,0 +1 @@
|
||||
{0} countrymen came to the island.
|
||||
1
53_King/csharp/Resources/InstructionsPrompt.txt
Normal file
1
53_King/csharp/Resources/InstructionsPrompt.txt
Normal file
@@ -0,0 +1 @@
|
||||
Do you want instructions
|
||||
17
53_King/csharp/Resources/InstructionsText.txt
Normal file
17
53_King/csharp/Resources/InstructionsText.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
|
||||
|
||||
Congratulations! You've just been elected Premier of Setats
|
||||
Detinu, a small communist island 30 by 70 miles long. Your
|
||||
job is to decide upon the country's budget and distribute
|
||||
money to your countrymen from the communal treasury.
|
||||
The money system is rallods, and each person needs 100
|
||||
rallods per year to survive. Your country's income comes
|
||||
from farm produce and tourists visiting your magnificent
|
||||
forests, hunting, fishing, etc. Half your land if farm land
|
||||
which also has an excellent mineral content and may be sold
|
||||
to foreign industry (strip mining) who import and support
|
||||
their own workers. Crops cost between 10 and 15 rallods per
|
||||
square mile to plant.
|
||||
Your goal is to complete your {0} year term of office.
|
||||
Good luck!
|
||||
0
53_King/csharp/Resources/InsufficientReserves.txt
Normal file
0
53_King/csharp/Resources/InsufficientReserves.txt
Normal file
1
53_King/csharp/Resources/LandPlanted.txt
Normal file
1
53_King/csharp/Resources/LandPlanted.txt
Normal file
@@ -0,0 +1 @@
|
||||
Of {0} sq. miles planted,
|
||||
1
53_King/csharp/Resources/PlantLandError1.txt
Normal file
1
53_King/csharp/Resources/PlantLandError1.txt
Normal file
@@ -0,0 +1 @@
|
||||
Sorry, but each countryman can only plant 2 sq. miles.
|
||||
1
53_King/csharp/Resources/PlantLandError2.txt
Normal file
1
53_King/csharp/Resources/PlantLandError2.txt
Normal file
@@ -0,0 +1 @@
|
||||
Sorry, but you've only {0} sq. miles of farm land.
|
||||
1
53_King/csharp/Resources/PlantLandError3.txt
Normal file
1
53_King/csharp/Resources/PlantLandError3.txt
Normal file
@@ -0,0 +1 @@
|
||||
Think again, You've only {0} rallods left in the treasury.
|
||||
1
53_King/csharp/Resources/PlantLandPrompt.txt
Normal file
1
53_King/csharp/Resources/PlantLandPrompt.txt
Normal file
@@ -0,0 +1 @@
|
||||
How many square miles do you wish to plant
|
||||
1
53_King/csharp/Resources/PollutionError.txt
Normal file
1
53_King/csharp/Resources/PollutionError.txt
Normal file
@@ -0,0 +1 @@
|
||||
Think again. You only have {0} rallods remaining.
|
||||
1
53_King/csharp/Resources/PollutionPrompt.txt
Normal file
1
53_King/csharp/Resources/PollutionPrompt.txt
Normal file
@@ -0,0 +1 @@
|
||||
How many rallods do you wish to spend on pollution control
|
||||
112
53_King/csharp/Resources/Resource.cs
Normal file
112
53_King/csharp/Resources/Resource.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
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 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();
|
||||
|
||||
public static string WorkerMigration(int newWorkers) => string.Format(GetString(), newWorkers);
|
||||
public static string Migration(int migration)
|
||||
=> string.Format(migration < 0 ? Emigration : Immigration, Math.Abs(migration));
|
||||
public static string Emigration => GetString();
|
||||
public static string Immigration => GetString();
|
||||
|
||||
public static string LandPlanted(float landPlanted)
|
||||
=> landPlanted > 0 ? string.Format(GetString(), (int)landPlanted) : "";
|
||||
public static string Harvest(int yield, int income, bool hasIndustry)
|
||||
=> string.Format(GetString(), yield, HarvestReason(hasIndustry), income);
|
||||
private static string HarvestReason(bool hasIndustry) => hasIndustry ? GetString() : "";
|
||||
|
||||
public static string TourismEarnings(int income) => string.Format(GetString(), income);
|
||||
public static string TourismDecrease(IRandom random) => string.Format(GetString(), TourismReason(random));
|
||||
private static string TourismReason(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() => GetString();
|
||||
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();
|
||||
public static string SavedCountrymenPrompt => GetString();
|
||||
public static string SavedWorkersPrompt => GetString();
|
||||
public static string SavedLandPrompt => GetString();
|
||||
public static string SavedLandError => 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)
|
||||
{
|
||||
using var stream = GetStream(name);
|
||||
using var reader = new StreamReader(stream);
|
||||
return reader.ReadToEnd();
|
||||
}
|
||||
|
||||
private static Stream GetStream([CallerMemberName] string? name = null) =>
|
||||
Assembly.GetExecutingAssembly().GetManifestResourceStream($"{typeof(Resource).Namespace}.{name}.txt")
|
||||
?? throw new Exception($"Could not find embedded resource stream '{name}'.");
|
||||
}
|
||||
1
53_King/csharp/Resources/SavedCountrymenPrompt.txt
Normal file
1
53_King/csharp/Resources/SavedCountrymenPrompt.txt
Normal file
@@ -0,0 +1 @@
|
||||
How many countrymen
|
||||
2
53_King/csharp/Resources/SavedLandError.txt
Normal file
2
53_King/csharp/Resources/SavedLandError.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
Come on, you started with 1000 sq. miles of farm land
|
||||
and 10,000 sq. miles of forest land
|
||||
1
53_King/csharp/Resources/SavedLandPrompt.txt
Normal file
1
53_King/csharp/Resources/SavedLandPrompt.txt
Normal file
@@ -0,0 +1 @@
|
||||
How many square miles of land
|
||||
1
53_King/csharp/Resources/SavedTreasuryPrompt.txt
Normal file
1
53_King/csharp/Resources/SavedTreasuryPrompt.txt
Normal file
@@ -0,0 +1 @@
|
||||
How much did you have in the treasury
|
||||
1
53_King/csharp/Resources/SavedWorkersPrompt.txt
Normal file
1
53_King/csharp/Resources/SavedWorkersPrompt.txt
Normal file
@@ -0,0 +1 @@
|
||||
How many workers
|
||||
1
53_King/csharp/Resources/SavedYearsError.txt
Normal file
1
53_King/csharp/Resources/SavedYearsError.txt
Normal file
@@ -0,0 +1 @@
|
||||
Come on, your term in office is only {0} years.
|
||||
1
53_King/csharp/Resources/SavedYearsPrompt.txt
Normal file
1
53_King/csharp/Resources/SavedYearsPrompt.txt
Normal file
@@ -0,0 +1 @@
|
||||
How many years had you been in office when interrupted
|
||||
2
53_King/csharp/Resources/SellLandError.txt
Normal file
2
53_King/csharp/Resources/SellLandError.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
*** Think again. You only have {0} square miles of farm land.
|
||||
{1}
|
||||
4
53_King/csharp/Resources/SellLandErrorReason.txt
Normal file
4
53_King/csharp/Resources/SellLandErrorReason.txt
Normal file
@@ -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.)
|
||||
1
53_King/csharp/Resources/SellLandPrompt.txt
Normal file
1
53_King/csharp/Resources/SellLandPrompt.txt
Normal file
@@ -0,0 +1 @@
|
||||
How many square miles do you wish to sell to industry
|
||||
6
53_King/csharp/Resources/StatusSansWorkers.txt
Normal file
6
53_King/csharp/Resources/StatusSansWorkers.txt
Normal file
@@ -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.
|
||||
|
||||
6
53_King/csharp/Resources/StatusWithWorkers.txt
Normal file
6
53_King/csharp/Resources/StatusWithWorkers.txt
Normal file
@@ -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.
|
||||
|
||||
5
53_King/csharp/Resources/Title.txt
Normal file
5
53_King/csharp/Resources/Title.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
King
|
||||
Creative Computing Morristown, New Jersey
|
||||
|
||||
|
||||
|
||||
1
53_King/csharp/Resources/TourismDecrease.txt
Normal file
1
53_King/csharp/Resources/TourismDecrease.txt
Normal file
@@ -0,0 +1 @@
|
||||
Decrease because {0}
|
||||
1
53_King/csharp/Resources/TourismEarnings.txt
Normal file
1
53_King/csharp/Resources/TourismEarnings.txt
Normal file
@@ -0,0 +1 @@
|
||||
You made {0} rallods from tourist trade.
|
||||
5
53_King/csharp/Resources/TourismReason.txt
Normal file
5
53_King/csharp/Resources/TourismReason.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.
|
||||
1
53_King/csharp/Resources/WorkerMigration.txt
Normal file
1
53_King/csharp/Resources/WorkerMigration.txt
Normal file
@@ -0,0 +1 @@
|
||||
{0} workers came to the country and
|
||||
7
53_King/csharp/Result.cs
Normal file
7
53_King/csharp/Result.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace King;
|
||||
|
||||
internal record struct Result (bool IsGameOver, string Message)
|
||||
{
|
||||
internal static Result GameOver(string message) => new(true, message);
|
||||
internal static Result Continue => new(false, "");
|
||||
}
|
||||
26
53_King/csharp/ValidityTest.cs
Normal file
26
53_King/csharp/ValidityTest.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
namespace King;
|
||||
|
||||
internal class ValidityTest
|
||||
{
|
||||
private readonly Predicate<float> _isValid;
|
||||
private readonly Func<string> _getError;
|
||||
|
||||
public ValidityTest(Predicate<float> isValid, string error)
|
||||
: this(isValid, () => error)
|
||||
{
|
||||
}
|
||||
|
||||
public ValidityTest(Predicate<float> isValid, Func<string> getError)
|
||||
{
|
||||
_isValid = isValid;
|
||||
_getError = getError;
|
||||
}
|
||||
|
||||
public bool IsValid(float value, IReadWrite io)
|
||||
{
|
||||
if (_isValid(value)) { return true; }
|
||||
|
||||
io.Write(_getError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
154
53_King/csharp/Year.cs
Normal file
154
53_King/csharp/Year.cs
Normal file
@@ -0,0 +1,154 @@
|
||||
using System.Text;
|
||||
|
||||
namespace King;
|
||||
|
||||
internal class Year
|
||||
{
|
||||
private readonly Country _country;
|
||||
private readonly IRandom _random;
|
||||
private readonly IReadWrite _io;
|
||||
private readonly int _plantingCost;
|
||||
private readonly int _landValue;
|
||||
|
||||
private float _landSold;
|
||||
private float _rallodsDistributed;
|
||||
private float _landPlanted;
|
||||
private float _pollutionControlCost;
|
||||
|
||||
private float _citizenSupport;
|
||||
private int _deaths;
|
||||
private float _starvationDeaths;
|
||||
private int _pollutionDeaths;
|
||||
private int _migration;
|
||||
|
||||
public Year(Country country, IRandom random, IReadWrite io)
|
||||
{
|
||||
_country = country;
|
||||
_random = random;
|
||||
_io = io;
|
||||
|
||||
_plantingCost = random.Next(10, 15);
|
||||
_landValue = random.Next(95, 105);
|
||||
}
|
||||
|
||||
public string Status => _country.GetStatus(_landValue, _plantingCost);
|
||||
|
||||
public Result? 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
|
||||
? null
|
||||
: Result.GameOver(Goodbye);
|
||||
}
|
||||
|
||||
public Result? EvaluateResults()
|
||||
{
|
||||
var rallodsUnspent = _country.Rallods;
|
||||
|
||||
_io.WriteLine();
|
||||
_io.WriteLine();
|
||||
|
||||
return EvaluateDeaths()
|
||||
?? EvaluateMigration()
|
||||
?? EvaluateAgriculture()
|
||||
?? EvaluateTourism()
|
||||
?? DetermineResult(rallodsUnspent);
|
||||
}
|
||||
|
||||
public Result? EvaluateDeaths()
|
||||
{
|
||||
var supportedCountrymen = _rallodsDistributed / 100;
|
||||
_citizenSupport = supportedCountrymen - _country.Countrymen;
|
||||
_starvationDeaths = -_citizenSupport;
|
||||
if (_starvationDeaths > 0)
|
||||
{
|
||||
if (supportedCountrymen < 50) { return Result.GameOver(EndOneThirdDead(_random)); }
|
||||
_io.WriteLine(DeathsStarvation(_starvationDeaths));
|
||||
}
|
||||
|
||||
var pollutionControl = _pollutionControlCost >= 25 ? _pollutionControlCost / 25 : 1;
|
||||
_pollutionDeaths = (int)(_random.Next((int)_country.IndustryLand) / pollutionControl);
|
||||
if (_pollutionDeaths > 0)
|
||||
{
|
||||
_io.WriteLine(DeathsPollution(_pollutionDeaths));
|
||||
}
|
||||
|
||||
_deaths = (int)(_starvationDeaths + _pollutionDeaths);
|
||||
if (_deaths > 0)
|
||||
{
|
||||
var funeralCosts = _deaths * 9;
|
||||
_io.WriteLine(FuneralExpenses(funeralCosts));
|
||||
|
||||
if (!_country.TrySpend(funeralCosts, _landValue))
|
||||
{
|
||||
_io.WriteLine(InsufficientReserves);
|
||||
}
|
||||
|
||||
_country.RemoveTheDead(_deaths);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Result? EvaluateMigration()
|
||||
{
|
||||
if (_landSold > 0)
|
||||
{
|
||||
var newWorkers = (int)(_landSold + _random.NextFloat(10) - _random.NextFloat(20));
|
||||
if (!_country.HasWorkers) { newWorkers += 20; }
|
||||
_io.Write(WorkerMigration(newWorkers));
|
||||
_country.AddWorkers(newWorkers);
|
||||
}
|
||||
|
||||
_migration =
|
||||
(int)(_citizenSupport / 10 + _pollutionControlCost / 25 - _country.IndustryLand / 50 - _pollutionDeaths / 2);
|
||||
_io.WriteLine(Migration(_migration));
|
||||
_country.Migration(_migration);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Result? EvaluateAgriculture()
|
||||
{
|
||||
var ruinedCrops = (int)Math.Min(_country.IndustryLand * (_random.NextFloat() + 1.5f) / 2, _landPlanted);
|
||||
var yield = (int)(_landPlanted - ruinedCrops);
|
||||
var income = (int)(yield * _landValue / 2f);
|
||||
|
||||
_io.Write(LandPlanted(_landPlanted));
|
||||
_io.Write(Harvest(yield, income, _country.IndustryLand > 0));
|
||||
|
||||
_country.SellCrops(income);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Result? EvaluateTourism()
|
||||
{
|
||||
var reputationValue = (int)((_country.Countrymen - _migration) * 22 + _random.NextFloat(500));
|
||||
var industryAdjustment = (int)(_country.IndustryLand * 15);
|
||||
var tourismIncome = Math.Abs(reputationValue - industryAdjustment);
|
||||
|
||||
_io.WriteLine(TourismEarnings(tourismIncome));
|
||||
if (industryAdjustment > 0 && tourismIncome < _country.PreviousTourismIncome)
|
||||
{
|
||||
_io.Write(TourismDecrease(_random));
|
||||
}
|
||||
|
||||
_country.EntertainTourists(tourismIncome);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Result? DetermineResult(float rallodsUnspent)
|
||||
{
|
||||
if (_deaths > 200) { return Result.GameOver(EndManyDead(_deaths, _random)); }
|
||||
if (_country.Countrymen < 343) { return Result.GameOver(EndOneThirdDead(_random)); }
|
||||
if (rallodsUnspent / 100 > 5 && _starvationDeaths >= 2) { return Result.GameOver(EndMoneyLeftOver()); }
|
||||
if (_country.Workers > _country.Countrymen) { return Result.GameOver(EndForeignWorkers(_random)); }
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user