private static Turn ExecuteFight(LevelView levelView) { var monsterInAttackRange = levelView.Monsters.First(m => levelView.Player.Location.IsInRange(m.Location, 1)); var attackOffset = monsterInAttackRange.Location - levelView.Player.Location; return(Turn.Attack(attackOffset)); }
public Turn Solve(LevelView level, Enviroment enviroment, out bool isAttack) { isAttack = false; if (level.Player.Health < MaxHp && level.HealthPacks.Any()) { enviroment.EnemyMap.Multiplyer = 2; var map = Map.Sum(enviroment.TravelMap, enviroment.EnemyMap); foreach (var hp in level.HealthPacks.OrderBy(h => h.Location.Distance(level.Player.Location))) { var path = map.FindPath(level.Player.Location, hp.Location); if (path == null) //бывают ситуации, когда полуживой монстр закрывает на проход к аптечкам. Добиваем его (раз нет других вариантов) { if (level.Monsters.Any(m => m.Location.IsInRange(level.Player.Location, 1))) { isAttack = true; return(Turn.Attack(level.Monsters.First(m => m.Location.IsInRange(level.Player.Location, 1)).Location - level.Player.Location)); } } else { return(Turn.Step(path[1] - path[0])); } } } return(null); }
public override Turn MakeTurn(LevelView levelView) { if (Bot.Health < panicHealth && levelView.HealthPacks.Any()) { GoToState(() => new StateHeal(Bot)); return(Bot.State.MakeTurn(levelView)); } if (!levelView.Monsters.Any()) { GoToState(() => new StateIdle(Bot)); return(Bot.State.MakeTurn(levelView)); } var nearbyMonster = levelView.Monsters. OrderBy(m => (m.Location - Bot.Location).Size()). ThenBy(m => m.Health). FirstOrDefault(); if (nearbyMonster.HasValue && IsInAttackRange(Bot.Location, nearbyMonster.Location)) { return(Turn.Attack(nearbyMonster.Location - Bot.Location)); } var path = Algorithm.BFS(levelView, location => location == nearbyMonster.Location); return(NextStep(levelView, path)); }
public Turn Solve(LevelView level, Enviroment enviroment, out bool isAttack) { isAttack = false; if (level.Monsters.Any(m => m.Location.IsInRange(level.Player.Location, 1))) { var monster = level.Monsters.Where(m => m.Location.IsInRange(level.Player.Location, 1)).OrderBy(m => m.Health).First(); isAttack = true; return(Turn.Attack(monster.Location - level.Player.Location)); } return(null); }
public Turn Iteration(LevelView level, IMessageReporter messageReporter, out bool isAttack) { isAttack = false; var monsterMap = new EnemyMap(level, 1); var trapMap = new TrapMap(level); var travelMap = Map.Sum(trapMap, WallMap); var pathMap = Map.Sum(monsterMap, travelMap); List <Location> path = null; if (level.Player.Health < 50 && level.HealthPacks.Any()) { path = pathMap.FindPath(level.Player.Location, level.HealthPacks.OrderBy(h => h.Location.Distance(level.Player.Location)).First().Location); messageReporter.ReportMessage("Healing"); } else if (level.Monsters.Any(m => m.Location.IsInRange(level.Player.Location, 1))) { messageReporter.ReportMessage("Attack"); isAttack = false; return(Turn.Attack(level.Monsters.First(m => m.Location.IsInRange(level.Player.Location, 1)).Location - level.Player.Location)); } else if (level.Monsters.Any()) { int i = 0; path = travelMap.FindPath(level.Player.Location, level .Monsters.OrderBy(h => h.Location.Distance(level.Player.Location)).First().Location); if (i > 10) { return(Turn.None); } messageReporter.ReportMessage("Far attack"); } else if (level.Player.Health < 100 && level.HealthPacks.Any()) { messageReporter.ReportMessage("100 Healing"); path = pathMap.FindPath(level.Player.Location, level.HealthPacks.OrderBy(h => h.Location.Distance(level.Player.Location)).First().Location); } else if (Math.Max(BestItem(level).AttackBonus, BestItem(level).DefenceBonus) > Math.Max(level.Player.TotalAttack - level.Player.Attack, level.Player.TotalDefence - level.Player.Defence)) { path = pathMap.FindPath(level.Player.Location, BestItem(level).Location); } else { messageReporter.ReportMessage("Leave"); var leaveMap = Map.Sum(travelMap, new BadObjectMap(level, (view, location) => level.Items.Any(i => i.Location.Equals(location)), view => level.Items.Select(i => i.Location), 1)); path = leaveMap.FindPath(level.Player.Location, Exit); } if (path != null) { return(Turn.Step(path[1] - path[0])); } return(Turn.None); }
private void FightForExit(IEnumerable <PawnView> localMonsters) { if (localMonsters.Any()) { var offset = localMonsters.First().Location - Self.playerLocation; Self.selectedTurn = Turn.Attack(offset); } else if (Self.level.Monsters.Any()) { Offset step = StepToMonsters(); Self.selectedTurn = Turn.Step(step); } }
private Turn SearchMonstersAround() { if (panicHealthValue > 50) { panicHealthValue = 50; } var nearbyMonsters = levelView.Monsters .Where(m => m.Location.IsInRange(levelView.Player.Location, 1)) .Select(m => new MonsterFightInfo(m, levelView.Player)); if (nearbyMonsters.Count() == 0) { return(Turn.None); } else if (nearbyMonsters.Count() == 1) { var monster = nearbyMonsters.Single(); if (monster.IsSaveToKill && levelView.Player.Health > panicHealthValue) { messageReporter.ReportMessage("-----Monster Health: " + monster.Info.Health); return(Turn.Attack(monster.Info.Location - levelView.Player.Location)); } else { return(Escape()); } } else if (nearbyMonsters.Count() == 2) { var totalDamage = nearbyMonsters.Sum(m => m.DamageToSlave); var saveToKill = nearbyMonsters .OrderBy(m => m.HitsToDeath) .Where(m => (m.HitsToDeath + 4 < levelView.Player.Health / totalDamage) || (levelView.Player.Health >= panicHealthValue * lvl && levelView.Player.Health > totalDamage)) .FirstOrDefault(); if (saveToKill != default(MonsterFightInfo)) { return(Turn.Attack(saveToKill.Info.Location - levelView.Player.Location)); } else { return(Escape()); } } else { return(Escape()); } }
public Turn MakeTurn(LevelView levelView, IMessageReporter messageReporter) { if (Ai == null || !levelView.Field.GetCellsOfType(CellType.Exit).First().Equals(Ai.Exit) || MonsterCount < levelView.Monsters.Count()) { LevelIndex++; if (IsLastLevel(levelView)) { Ai = new ArenaDestroyerAi(levelView); } else if (AiFactories.ContainsKey(LevelIndex)) { Ai = AiFactories[LevelIndex].CreateBot(levelView, LevelIndex); } else { Ai = AiFactories[AiFactories.Keys.OrderBy(k => Math.Abs(k - LevelIndex)).First()].CreateBot(levelView, LevelIndex); } history = new Queue <Location>(historySize); } MonsterCount = levelView.Monsters.Count(); var isAttack = false; var action = Ai.Iteration(levelView, messageReporter, out isAttack); if (!isAttack) { history.Enqueue(levelView.Player.Location); if (history.Count > historySize) { history.Dequeue(); if (new HashSet <Location>(history).Count < (historySize * Ai.CriticalPercentageInactivity / 100)) { messageReporter.ReportMessage("T"); history.Clear(); if (levelView.Monsters.Any(m => m.Location.IsInRange(levelView.Player.Location, 1))) { messageReporter.ReportMessage("A"); return(Turn.Attack(levelView.Monsters.First(m => m.Location.IsInRange(levelView.Player.Location, 1)).Location - levelView.Player.Location)); } var solve = Ai.HandleCycle(levelView); if (solve != null) { return(solve); } return(Turn.Step((StepDirection) new Random().Next(0, 4))); } } } return(action); }
public override void Tick() { var attackRoute = Self.pathFinder.FindPath(Self.targetMonster.Location); if (attackRoute.Count == 0) { GoToState(() => new StateEscape(Self)); return; } var monsters = MonstersInRange(attackRoute.Last()); if (monsters.Count() > 1) { GoToState(() => new StateEscape(Self)); return; } if (FightDecideFunction(Self.targetMonster)) { if (Self.IsInAttackRange(Self.targetMonster)) { var attackOffset = Self.targetMonster.Location - Self.playerLocation; Self.selectedTurn = Turn.Attack(attackOffset); return; } if (Offset.StepOffsets.Any(o => Self.level.GetItemAt(Self.playerLocation + o).HasValue)) { var item = Self.level.Items .Where(i => Offset.StepOffsets .Any(o => i.Location == Self.playerLocation + o)) .OrderByDescending(i => PlayerBot.ItemValue(i)) .First(); if (PlayerBot.ItemValue(item) > PlayerBot.ItemValue(Self.equippedItem)) { var itemStep = item.Location - Self.playerLocation; Self.selectedTurn = Turn.Step(itemStep); return; } } var attackStep = (attackRoute.First() - Self.playerLocation).SnapToStep(); Self.selectedTurn = Turn.Step(attackStep); return; } GoToState(() => new StateEscape(Self)); }
public Turn Solve(LevelView level, Enviroment enviroment, out bool isAttack) { isAttack = false; //если монстры атакуют более чем двумя - убегаем на другой конец карты if (level.Monsters.Count(m => m.Location.IsInRange(level.Player.Location, 1)) > 1 && level.Monsters.Count() > 2) { enviroment.EnemyMap.Multiplyer = 2; var map = Map.Sum(enviroment.TravelMap, enviroment.EnemyMap); var spot = new[] { enviroment.Exit, enviroment.Start }.OrderByDescending(s => s.Distance(level.Player.Location)).First(); var target = spot.Near().Where(p => enviroment.TravelMap.IsTravaible(p)).OrderBy(p => p.Distance(level.Player.Location)).First(); //эта клетка вроде всегда свободна var near = level.Player.Location.Near() .Where(p => map.IsTravaible(p) && enviroment.WallMap.GetWeight(p) < 2) .OrderBy(p => level.Monsters.Count(m => m.Location.IsInRange(p, 1))); foreach (var location in near)//new { if (level.Monsters.Count(m => m.Location.IsInRange(location, 1)) > 0) { break; } var p = map.FindPath(level.Player.Location, target); if (p != null && p.Count > 1) { return(Turn.Step(p[1] - p[0])); } } var path = map.FindPath(level.Player.Location, target); if (path == null) { if (level.Monsters.Any(m => m.Location.IsInRange(level.Player.Location, 1))) { isAttack = true; return (Turn.Attack( level.Monsters.First(m => m.Location.IsInRange(level.Player.Location, 1)).Location - level.Player.Location)); } else { return(Turn.None); } } return(Turn.Step(path[1] - path[0])); } return(null); }
private Turn Attack(LevelView levelView, PawnView monster) { if (monster.HasValue) { return(Turn.Attack(monster.Location - levelView.Player.Location)); } var nearbyMonster = GetNearbyMonster(levelView, monster.Location); if (nearbyMonster.HasValue) { return(Turn.Attack(nearbyMonster.Location - levelView.Player.Location)); } return(null); }
private Turn MakeYourselfStronger() { messageReporter.ReportMessage("-----MakeYourselfStronger-----"); var closestMonster = CheckOnAvailableExperience(); Turn turn; if (!isFinalRoom) { turn = SearchMonstersAround(); if (turn != Turn.None) { return(turn); } } turn = CheckEquipAndExp(); if (turn != Turn.None) { return(turn); } if (closestMonster != default(MonsterFightInfo)) { if (levelView.Player.Location.IsInRange(closestMonster.Info.Location, 1)) { // на финального босса if (levelView.Player.Health > 30) { return(Turn.Attack(closestMonster.Info.Location - levelView.Player.Location)); } else { return(Escape()); } } else { return(CreateMap(closestMonster.Info.Location, false)); } } else { return(ObjectiveDoneOrImpossible()); } }
public Turn MakeTurn(LevelView levelView, IMessageReporter messageReporter) { messageReporter.ReportMessage("Hey ho! I'm still breathing"); if (levelView.Random.NextDouble() < 0.1) { return(Turn.None); } var nearbyMonster = levelView.Monsters.FirstOrDefault(m => IsInAttackRange(levelView.Player.Location, m.Location)); if (nearbyMonster.HasValue) { return(Turn.Attack(nearbyMonster.Location - levelView.Player.Location)); } return(Turn.Step((StepDirection)levelView.Random.Next(4))); }
private Turn GoHealYourself() { messageReporter.ReportMessage("-----GoHealYourself-----"); // ежеходное обновление карты, чтобы быть совершенно точно уверенным в корректности данных, при хиле риск минимизируется map = new Map(ref levelView); var fruits = levelView.HealthPacks.ToList(); var closestFruit = GetClosestFruit(fruits); if (closestFruit.HasValue) { // перебор хилок, если ближайшая недоступна Turn turn = CreateMap(closestFruit.Location, true); while (turn == Turn.None || fruits.Count == 0) { fruits.Remove(closestFruit); turn = CreateMap(closestFruit.Location, true); } if (turn == Turn.None || fruits.Count == 0) { var closestMonster = levelView.Monsters.Where(m => m.Location.IsInRange(levelView.Player.Location, 1)).FirstOrDefault(); if (closestMonster.HasValue) { return(Turn.Attack(closestMonster.Location - levelView.Player.Location)); } else { return(CreateMap(levelView.Field.GetCellsOfType(CellType.Exit).Single(), false)); } } else { return(turn); } } else { return(ObjectiveDoneOrImpossible()); } }
public override void Tick() { if (objectiveRoute.Count == 0) { if (Self.level.Monsters.Any(Self.IsInAttackRange)) { var attackOffset = Self.level.Monsters .Where(Self.IsInAttackRange) .OrderBy(m => m.Health) .ThenBy(m => m.Attack) .ThenBy(m => m.Defence) .First() .Location - Self.playerLocation; Self.selectedTurn = Turn.Attack(attackOffset); } } else { var objectiveStep = (objectiveRoute.First() - Self.playerLocation).SnapToStep(); Self.selectedTurn = Turn.Step(objectiveStep); } }
//идем туда, куда будет проложен маршрут по карте public Turn AutomaticStep(Map map, Location target, LevelView level, out bool isAttack) { isAttack = false; var path = map.FindPath(level.Player.Location, target); if (path == null) { if (level.Monsters.Any(m => m.Location.IsInRange(level.Player.Location, 1))) { isAttack = true; return (Turn.Attack( level.Monsters.First(m => m.Location.IsInRange(level.Player.Location, 1)).Location - level.Player.Location)); } else { return(Turn.None); } } return(Turn.Step(path[1] - path[0])); }
public Turn Iteration(LevelView level, IMessageReporter reporter, out bool isAttack) { Enviroment.Update(level, 3); var bonusIgnore = new BadObjectMap(level, (view, location) => level.Items.Any(i => i.Location.Equals(location)), view => level.Items.Select(i => i.Location), 1); var attackMap = Map.Sum(Enviroment.WallMap, Enviroment.TrapMap, bonusIgnore); var travelMap = Map.Sum(attackMap, Enviroment.EnemyMap, bonusIgnore); if (level.Monsters.Any()) { var monster = level.Monsters.First(); var enemyHp = monster.Health; var healingHpLevel = 50; if (enemyHp < MonsterStartHp * 0.6) //если враг пытается отрегениться - забираем его аптечку)) { healingHpLevel = 60; } if (level.Player.Health < healingHpLevel && level.HealthPacks.Any()) { var path = travelMap.FindPath(level.Player.Location, level.HealthPacks.OrderBy(h => h.Location.Distance(level.Player.Location)).First().Location); isAttack = false; if (path != null && path.Count > 1) { return(Turn.Step(path[1] - path[0])); } return(Turn.None); } } if (level.Monsters.Any(m => m.Location.IsInRange(level.Player.Location, 1))) { var monster = level.Monsters.Where(m => m.Location.IsInRange(level.Player.Location, 1)).OrderBy(m => m.Health).First(); isAttack = true; return(Turn.Attack(monster.Location - level.Player.Location)); } if (level.Monsters.Any()) { var target = level.Monsters.First().Location; var targets = target .Near(3) .Where( p => p.X >= 0 && p.Y >= 0 && p.X < Enviroment.TravelMap.Width && p.Y < Enviroment.TravelMap.Height) .Where(p => Enviroment.TravelMap.IsTravaible(p)) .OrderBy(p => p.Distance(target)); foreach (var location in targets) { var path = attackMap.FindPath(level.Player.Location, location); isAttack = false; if (path != null && path.Count > 1) { return(Turn.Step(path[1] - path[0])); } } } if (!ExitIsClosed(level)) { Enviroment = new Enviroment(level, 2); var path = travelMap.FindPath(level.Player.Location, Exit); isAttack = false; if (path == null || path.Count < 2) { return(Turn.None); } return(Turn.Step(path[1] - path[0])); } isAttack = false; return(Turn.None); }
public Turn MakeTurn(LevelView level, IMessageReporter messageReporter) { if (_hiddenYet == default(HashSet <Location>) || level.Field[level.Player.Location] == CellType.PlayerStart) { _hiddenYet = new HashSet <Location>(level.Field.GetCellsOfType(CellType.Hidden)); } _hiddenYet.IntersectWith(level.Field.GetCellsOfType(CellType.Hidden)); if (_emptiesOnceWasVisible == default(HashSet <Location>) || level.Field[level.Player.Location] == CellType.PlayerStart) { _emptiesOnceWasVisible = new HashSet <Location>(level.Field.GetCellsOfType(CellType.Empty)); } _emptiesOnceWasVisible.UnionWith(level.Field.GetCellsOfType(CellType.Empty)); _emptiesOnceWasVisible.UnionWith(level.Field.GetCellsOfType(CellType.Exit)); _emptiesOnceWasVisible.UnionWith(level.Field.GetCellsOfType(CellType.PlayerStart)); if (_exit == default(Location) || level.Field[level.Player.Location] == CellType.PlayerStart) { _exit = level.Field.GetCellsOfType(CellType.Exit).SingleOrDefault(); } if (level.Player.Health <= CriticalHealth && TryGetBestStepToHealth(level, out var locationToStep)) { return(Turn.Step(locationToStep - level.Player.Location)); } var attackRangeMonsters = level.Monsters.Where(x => x.Location.IsInRange(level.Player.Location, 1)).ToArray(); if (attackRangeMonsters.Any()) { if (attackRangeMonsters.Length == 1 && level.Player.Health >= CriticalHealth) { return(Turn.Attack( attackRangeMonsters .Aggregate((result, current) => result.Health < current.Health ? result : current) .Location - level.Player.Location)); } if (TryGetBestStepAwayFromMonsters(level, out locationToStep)) { return(Turn.Step(locationToStep - level.Player.Location)); } } if (level.Monsters.Any() && TryGetBestStepToAttack(level, out locationToStep)) { return(Turn.Step(locationToStep - level.Player.Location)); } level.Player.TryGetEquippedItem(out var item); if (level.Items.Any(x => x.AttackBonus > item.AttackBonus && x.DefenceBonus > item.DefenceBonus) && TryGetBestStepToItem(level, out locationToStep)) { return(Turn.Step(locationToStep - level.Player.Location)); } return(Turn.Step(GetBestStepToExit(level) - level.Player.Location)); }
public Turn AskPlayerInput() { while (true) { var key = mouseDriver.WaitForInput(); Console.CancelKeyPress += (sender, args) => args.Cancel = true; switch (key.Key) { case ConsoleKey.Escape: return(null); case ConsoleKey.LeftArrow: MoveCursor(-1, 0); break; case ConsoleKey.UpArrow: MoveCursor(0, -1); break; case ConsoleKey.RightArrow: MoveCursor(1, 0); break; case ConsoleKey.DownArrow: MoveCursor(0, 1); break; case ConsoleKey.A: if (key.Modifiers.HasFlag(ConsoleModifiers.Alt)) { return(Turn.Attack(AttackDirection.West)); } return(Turn.Step(StepDirection.West)); case ConsoleKey.C: if (key.Modifiers.HasFlag(ConsoleModifiers.Alt)) { return(Turn.Attack(AttackDirection.SouthEast)); } break; case ConsoleKey.D: if (key.Modifiers.HasFlag(ConsoleModifiers.Alt)) { return(Turn.Attack(AttackDirection.East)); } return(Turn.Step(StepDirection.East)); case ConsoleKey.E: if (key.Modifiers.HasFlag(ConsoleModifiers.Alt)) { return(Turn.Attack(AttackDirection.NorthEast)); } break; case ConsoleKey.Q: if (key.Modifiers.HasFlag(ConsoleModifiers.Alt)) { return(Turn.Attack(AttackDirection.NorthWest)); } break; case ConsoleKey.S: if (key.Modifiers.HasFlag(ConsoleModifiers.Alt)) { return(Turn.Attack(AttackDirection.South)); } return(Turn.Step(StepDirection.South)); case ConsoleKey.W: if (key.Modifiers.HasFlag(ConsoleModifiers.Alt)) { return(Turn.Attack(AttackDirection.North)); } return(Turn.Step(StepDirection.North)); case ConsoleKey.X: if (key.Modifiers.HasFlag(ConsoleModifiers.Alt)) { return(Turn.Attack(AttackDirection.South)); } break; case ConsoleKey.Z: if (key.Modifiers.HasFlag(ConsoleModifiers.Alt)) { return(Turn.Attack(AttackDirection.SouthWest)); } break; case ConsoleKey.Spacebar: return(Turn.None); case ConsoleKey.F1: DisplayHelp(); break; } } }