using System; using System.Collections.Generic; using System.Linq; using CivilWar; var options = GameOptions.Input(); var armies = new List { 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( 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(); } }