public static (int fullyFinishedRounds, int totalHitpoints, bool anyElfDied) ProcessGame(string pathToInputFile, int elvesAttackPower = 3) { var lines = File.ReadAllLines(pathToInputFile); Day15Map game = new Day15Map(lines[0].Length, lines.Length); for (int y = 0; y < lines.Length; y++) { var line = lines[y]; for (int x = 0; x < line.Length; x++) { switch (line[x]) { case '#': game.Set(x, y); break; case 'G': game.AddUnit(new Day15Unit(Day15UnitType.Goblin, new Point(x, y), 3)); break; case 'E': game.AddUnit(new Day15Unit(Day15UnitType.Elf, new Point(x, y), elvesAttackPower)); break; } } } int elvesonTheBattleField = game.AllUnits.Where(x => x.Type == Day15UnitType.Elf).Count(); int roundCounter = 0; PrintAndWait(); while (!game.MakeARound()) { roundCounter++; PrintAndWait(); } PrintAndWait(); void PrintAndWait() { //game.Print(); //Console.WriteLine(roundCounter); //Console.ReadLine(); } return(roundCounter, game.AllUnits.Sum(x => x.hitPoints), elvesonTheBattleField != game.AllUnits.Where(x => x.Type == Day15UnitType.Elf).Count()); }
public bool TakeATurn(Day15Map map) { var allEnemyUnits = map.AllUnits.Where(x => x.IsTarget(Type)).ToList(); if (!allEnemyUnits.Any()) { return(false); } var costs = map.GetCosts(Position); (Point point, int cost)? GetCost(Day15Unit unit) { List <(Point point, int cost)> reachablePoints = new List <(Point point, int cost)>(); foreach (var offset in offsets) { var copy = unit.Position; copy.Offset(offset); if (costs.ContainsKey(copy)) { var value = costs[copy]; if (value > 0) { reachablePoints.Add((copy, value)); } } } if (reachablePoints.Any()) { return(reachablePoints.OrderBy(x => x.cost).ThenBy(x => x.point.Y).ThenBy(x => x.point.X).First()); } return(null); } List <Day15Unit> possibleAttackUnits = new List <Day15Unit>(); foreach (var offset in offsets) { var copy = Position; copy.Offset(offset); var enemy = allEnemyUnits.FirstOrDefault(x => x.Position.Equals(copy)); if (enemy != null && !enemy.IsDead) { possibleAttackUnits.Add(enemy); } } var unitToAttack = possibleAttackUnits.OrderBy(x => x.hitPoints).ThenBy(x => x.Position.Y).ThenBy(x => x.Position.X).FirstOrDefault(); if (unitToAttack == null) { var pointToReach = allEnemyUnits.Select(GetCost).Where(x => x != null).OrderBy(x => x.Value.cost).ThenBy(x => x.Value.point.Y).ThenBy(x => x.Value.point.X).FirstOrDefault(); if (pointToReach != null) { var newPoint = map.GetPath(Position, pointToReach.Value.point); if (newPoint == null) { throw new Exception(); } if (newPoint.Value.cost != pointToReach.Value.cost) { throw new Exception(); } Position = newPoint.Value.firstStep; } else { } } //var possibleTargets = map.GetAllTargets().ToList(); //if (possibleTargets.Where(x => x.unit.IsTarget(Type)).Count() == 0) // return false; //var possible = possibleTargets.Select(x => (x, map.GetPaths(Position, x.unit.Position))).Where(x => x.Item2 != null).OrderBy(x => x.Item2.Value.lenght).ThenBy(x => x.Item2.Value.firstStep.Y).ThenBy(x => x.Item2.Value.firstStep.X); //if (!possible.Where(x => x.Item1.unit.IsTarget(Type)).Any()) // return true; //var f = possible.Where(x => x.Item1.unit.IsTarget(Type) && x.Item2.Value.lenght < 1000); //if (f.Any() && f.Min(x => x.Item2.Value.lenght) > 1) //{ // var actual = f.Where(x => !possibleTargets.Select(y => y.unit.Position).Contains(x.Item2.Value.firstStep)).SkipWhile(x => !x.Item1.canBeTargeted).FirstOrDefault(); // if (actual.Item2 != null) // Position = actual.Item2.Value.firstStep; //} //attack //List<Day15Unit> possibleAttackUnits = new List<Day15Unit>(); foreach (var offset in offsets) { var copy = Position; copy.Offset(offset); var enemy = allEnemyUnits.FirstOrDefault(x => x.Position.Equals(copy)); if (enemy != null && !enemy.IsDead) { possibleAttackUnits.Add(enemy); } } unitToAttack = possibleAttackUnits.OrderBy(x => x.hitPoints).ThenBy(x => x.Position.Y).ThenBy(x => x.Position.X).FirstOrDefault(); if (unitToAttack != null) { unitToAttack.hitPoints -= attackPower; } return(true); }