public string ReportGroupState() => new StringBuilder() .AppendLine("Immune System:") .AppendLine(Join('\n', ImmuneGroups.Select(g => g.ToString()))) .AppendLine() .AppendLine("Infection:") .AppendLine(Join('\n', InfectionGroups.Select(g => g.ToString()))) .ToString();
// Part 1 - simulate the game // sign indicates winning side (- means infection, + means immune system) and value indicates number of units left public int PlayUntilEnd() { while (ImmuneGroups.Any(g => g.Units > 0) && InfectionGroups.Any(g => g.Units > 0)) { Round++; // Active groups for this phase var immuneGroups = ImmuneGroups.Where(g => g.Units > 0).ToList(); var infectionGroups = InfectionGroups.Where(g => g.Units > 0).ToList(); // TARGET SELECTION PHASE var targetsImmuneSystem = TargetSelection(immuneGroups, infectionGroups); var targetsInfection = TargetSelection(infectionGroups, immuneGroups); if (targetsImmuneSystem.Count == 0 && targetsInfection.Count == 0) { return(0); // draw! } // ATTACKING PHASE var totalUnitsCountBefore = ImmuneGroups.Sum(g => g.Units) + InfectionGroups.Sum(g => g.Units); var attackingSequence = targetsImmuneSystem.Union(targetsInfection).OrderByDescending(t => t.Item1.Initiative); foreach (var attack in attackingSequence) { var attacker = attack.Item1; var defender = attack.Item2; if (attacker.Units > 0) { var damages = ComputeAttackDamage(attacker, defender); defender.TakeDamage(damages); } } var totalUnitsCountAfter = ImmuneGroups.Sum(g => g.Units) + InfectionGroups.Sum(g => g.Units); if (totalUnitsCountAfter == totalUnitsCountBefore) { return(0); // draw } File.AppendAllText("game.log", $"\n\nAfter Round {Round}\n" + ReportGroupState()); //Debug.WriteLine($"After Round {Round}"); //Debug.WriteLine(ReportGroupState()); } // number of units left on winning side, with sign return(ImmuneGroups.Sum(g => g.Units) - InfectionGroups.Sum(g => g.Units)); }