public int DoTurn(IPirateGame game) { int movesConsumed = 0; var pirates = game.MyPirates().Where(pirate => pirate.Id % 2 == 0).ToArray(); var firingPirates = new HashSet<Pirate>(); var firedUponTargets = new HashSet<Pirate>(); var shootingTuples = from pirate in pirates from enemy in game.EnemyPiratesWithTreasures() where pirate.ReloadTurns == 0 where pirate.TurnsToSober == 0 where enemy.TurnsToSober == 0 where game.Distance(pirate, enemy) <= 4 select new { Pirate = pirate, Target = enemy }; if (shootingTuples.Any()) { foreach (var shootingTuple in shootingTuples) { if (!firingPirates.Contains(shootingTuple.Pirate) && !firedUponTargets.Contains(shootingTuple.Target)) { firingPirates.Add(shootingTuple.Pirate); firedUponTargets.Add(shootingTuple.Target); game.Attack(shootingTuple.Pirate, shootingTuple.Target); movesConsumed++; } } } var piratesAndEnemies = pirates.Except(firingPirates).Select(pirate => Tuple.Create(pirate, game.GetEnemyPirate(pirate.Id))).ToList(); if (piratesAndEnemies.Any()) { // if any pirate needs to move, move only the first pirate var movingTuple = piratesAndEnemies.Where(pair => game.Distance(pair.Item1, pair.Item2.InitialLocation) > 2).FirstOrDefault(); if (movingTuple != null) { var movingPirate = movingTuple.Item1; var enemyHomeBase = movingTuple.Item2.InitialLocation; int distance = Math.Min(4, game.Distance(movingPirate, enemyHomeBase) - 2); var sailOptions = game.GetSailOptions(movingPirate, enemyHomeBase, distance); game.SetSail(movingPirate, sailOptions[random.Next(sailOptions.Count)]); movesConsumed += distance; } } return movesConsumed; }