private (int score, bool isVictory) SimulateCombatAndGetScore(string input, int maxRoundsLogged, int immuneSystemBoost = 0)
        {
            var combat = new Combat {
                Squads = ParseSquadsFromInput(input, immuneSystemBoost)
            };
            var round = 0;

            while (!combat.IsOver())
            {
                var deadlocked = true;

                if (round++ < maxRoundsLogged)
                {
                    output.WriteLine("");
                    output.WriteLine($"---------------------------- round {round} -----------------------------");
                    foreach (var squad in combat.Squads)
                    {
                        output.WriteLine(squad.ToString());
                    }
                    output.WriteLine("");
                }

                // Target selection
                var targets          = new Dictionary <Squad, Squad>();
                var potentialTargets = combat.GetLivingSquads().ToHashSet();
                var squadsInOrder    = combat.GetLivingSquads()
                                       .OrderByDescending(s => s.EffectivePower)
                                       .ThenByDescending(s => s.Initiative)
                                       .ToArray();

                foreach (var squad in squadsInOrder)
                {
                    var enemy = potentialTargets
                                .Where(s => squad.IsEnemeyFor(s))
                                .Where(s => squad.PotentialDamageTo(s) > 0)
                                .OrderByDescending(s => squad.PotentialDamageTo(s))
                                .ThenByDescending(s => s.EffectivePower)
                                .ThenByDescending(s => s.Initiative)
                                .FirstOrDefault();

                    targets[squad] = enemy;

                    if (enemy == null)
                    {
                        continue;
                    }

                    potentialTargets.Remove(enemy);

                    if (round < maxRoundsLogged)
                    {
                        output.WriteLine($"{squad.Type} {squad.Id} would deal squad {enemy.Id} {squad.PotentialDamageTo(enemy)} damage");
                    }
                }

                if (round < maxRoundsLogged)
                {
                    output.WriteLine("");
                }

                // Attacking
                squadsInOrder = combat.GetLivingSquads()
                                .OrderByDescending(s => s.Initiative)
                                .ToArray();

                foreach (var squad in squadsInOrder)
                {
                    if (squad.Units <= 0)
                    {
                        continue;
                    }
                    if (targets[squad] == null)
                    {
                        continue;
                    }

                    var result = squad.Fight(targets[squad]);
                    deadlocked = false;

                    if (round < maxRoundsLogged)
                    {
                        output.WriteLine($"{squad.Type} {squad.Id} attacks {targets[squad].Id} killing {result.UnitsKilled} units ({result.Damage} damage) {(result.IsElimination ? "ELIMINATION!" : "")}");
                    }
                }

                if (deadlocked)
                {
                    throw new NoSolutionFoundException("Deadlocked!");
                }
            }

            return(combat.CalculateScore(), !combat.GetLivingSquads().Any(s => s.IsInfection));
        }