Files
basic-computer-games/27_Civil_War/csharp/Program.cs
2022-01-17 08:19:24 +02:00

119 lines
3.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using CivilWar;
var options = GameOptions.Input();
var armies = new List<Army> { new Army(Side.Confederate), options.TwoPlayers ? new Army(Side.Union) : new ComputerArmy(Side.Union) };
Battle? battle = null;
while (OneBattle(ref battle)) { }
DisplayResult();
bool OneBattle(ref Battle? previous)
{
var (option, selected) = Battle.SelectBattle();
var (battle, isReplay, quit) = option switch
{
Option.Battle => (selected!, false, false),
Option.Replay when previous != null => (previous, true, false), // can't replay if no previous battle
_ => (null!, false, true),
};
if (quit)
return false;
if (!isReplay)
{
Console.WriteLine($"This is the battle of {battle.Name}.");
if (options.ShowDescriptions)
ConsoleUtils.WriteWordWrap(battle.Description);
armies.ForEach(a => a.PrepareBattle(battle.Men[(int)a.Side], battle.Casualties[(int)a.Side]));
}
ConsoleUtils.WriteTable(armies, new()
{
new("", a => a.Side),
new("Men", a => a.Men),
new("Money", a => a.Money, Before: "$"),
new("Inflation", a => a.InflationDisplay, After: "%")
});
armies.ForEach(a => a.AllocateResources());
armies.ForEach(a => a.DisplayMorale());
string offensive = battle.Offensive switch
{
Side.Confederate => "You are on the offensive",
Side.Union => "You are on the defensive",
_ => "Both sides are on the offensive"
};
Console.WriteLine($"Confederate general---{offensive}");
if (armies.Any(a => a.ChooseStrategy(isReplay)))
{
return false; // someone surrendered
}
armies[0].CalculateLosses(armies[1]);
armies[1].CalculateLosses(armies[0]);
ConsoleUtils.WriteTable(armies, new()
{
new("", a => a.Side),
new("Casualties", a => a.Casualties),
new("Desertions", a => a.Desertions),
});
if (options.TwoPlayers)
{
var oneDataCol = new[] { 1 };
Console.WriteLine($"Compared to the actual casualties at {battle.Name}");
ConsoleUtils.WriteTable(oneDataCol, armies.Select(a => new ConsoleUtils.TableRow<int>(
a.Side.ToString(),
_ => $"{(double)a.Casualties / battle.Casualties[(int)a.Side]}", After: "% of the original")
).ToList());
}
Side winner;
switch (armies[0].AllLost, armies[1].AllLost, armies[0].MenLost - armies[1].MenLost)
{
case (true, true, _) or (false, false, 0):
Console.WriteLine("Battle outcome unresolved");
winner = Side.Both; // Draw
break;
case (false, true, _) or (false, false, < 0):
Console.WriteLine($"The Confederacy wins {battle.Name}");
winner = Side.Confederate;
break;
case (true, false, _) or (false, false, > 0):
Console.WriteLine($"The Union wins {battle.Name}");
winner = Side.Union;
break;
}
if (!isReplay)
{
armies.ForEach(a => a.RecordResult(winner));
}
Console.WriteLine("---------------");
previous = battle;
return true;
}
void DisplayResult()
{
armies[0].DisplayWarResult(armies[1]);
int battles = armies[0].BattlesFought;
if (battles > 0)
{
Console.WriteLine($"For the {battles} battles fought (excluding reruns)");
ConsoleUtils.WriteTable(armies, new()
{
new("", a => a.Side),
new("Historical Losses", a => a.CumulativeHistoricCasualties),
new("Simulated Losses", a => a.CumulativeSimulatedCasualties),
new(" % of original", a => ((double)a.CumulativeSimulatedCasualties / a.CumulativeHistoricCasualties).ToString("p2"))
}, transpose: true);
armies[1].DisplayStrategies();
}
}