private static bool IsLocationForAttack(LevelView levelView, Location location) { return(GetCountMonstersOnAttackRange(levelView, location) > 0 && levelView.Field[location] != CellType.Wall && levelView.Field[location] != CellType.Trap && !levelView.GetItemAt(location).HasValue); }
private int CalculateInfluence(Location location) { if (levelView.Field.IsOutOfRange(location)) { return(-1); } var cellType = Field[location]; if (cellType == CellType.Wall || cellType == CellType.Trap || cellType == CellType.Exit || levelView.GetItemAt(location).HasValue) { return(-1); } if (levelView.GetHealthPackAt(location).HasValue) { return(1 + CalculateMonstersInfluence(location, monsterInfluenceSeed)); } var seedForMonsters = levelView.Monsters.Count() == 1 ? arenaFighterInfluenceSeed : monsterInfluenceSeed; return(CalculeateBaseInfluence(location) + CalculateMonstersInfluence(location, seedForMonsters)); }
private static bool IsPassable(Location location, LevelView levelView) { var isObject = levelView.GetHealthPackAt(location).HasValue || levelView.GetMonsterAt(location).HasValue || levelView.GetItemAt(location).HasValue; var isEmpty = levelView.Field[location] == CellType.Empty || levelView.Field[location] == CellType.PlayerStart; return(!isObject && isEmpty); }
public static bool IsStepValid(this Location to, LevelView view) { if (to.X < 0 || to.X >= view.Field.Width || to.Y < 0 || to.Y >= view.Field.Height) { return(false); } return(view.Field[to] != CellType.Trap && view.Field[to] != CellType.Wall && view.Field[to] != CellType.Exit && !view.GetMonsterAt(to).HasValue && !view.GetItemAt(to).HasValue); }
private bool TryGetBestStepToItem(LevelView level, out Location locationToStep) { locationToStep = FindByDijkstra(level, IsToConsider, GetCost); return(locationToStep != default(Location)); bool IsToConsider(Location location) { level.Player.TryGetEquippedItem(out var item); return(level.GetItemAt(location).HasValue&& level.GetItemAt(location).AttackBonus > item.AttackBonus && level.GetItemAt(location).DefenceBonus > item.DefenceBonus); } int GetCost(Location location) { if (level.Field[location] == CellType.Wall || level.Field[location] == CellType.Trap || level.GetMonsterAt(location).HasValue) { return(100); } if (level.GetItemAt(location).HasValue) { level.Player.TryGetEquippedItem(out var item); if (level.GetItemAt(location).AttackBonus > item.AttackBonus && level.GetItemAt(location).DefenceBonus > item.DefenceBonus) { return(0); } return(100); } if (level.Field[location] == CellType.Exit) { return(0); } if (level.Field[location] == CellType.Empty || level.Field[location] == CellType.PlayerStart) { return(10 - GetNeighbours(location, NeighbourType.Eight) .Count(x => level.Field[x] == CellType.Trap || level.Field[x] == CellType.Wall)); } if (level.Field[location] == CellType.Hidden) { return(10); } throw new ArgumentOutOfRangeException(nameof(location)); } }
public static IEnumerable <Location> BFS(LevelView levelView, Func <Location, bool> isTarget, bool acceptPickup = false) { var queue = new Queue <Location>(); var start = levelView.Player.Location; queue.Enqueue(start); var visited = new HashSet <Location> { start }; var pred = new Dictionary <Location, Location>(); while (queue.Any()) { var current = queue.Dequeue(); if (isTarget(current)) { return(RevertPath(levelView, current, pred)); } foreach (var offset in Offset.StepOffsets) { var next = current + offset; if (!visited.Contains(next) && (levelView.Field[next] > CellType.Trap)) { if (levelView.GetHealthPackAt(next).HasValue || levelView.GetItemAt(next).HasValue) { if (!acceptPickup) { continue; } } queue.Enqueue(next); visited.Add(next); pred[next] = current; } } } var path = RevertPath(levelView, levelView.Player.Location, pred); if (!path.Any()) { path = BFS(levelView, isTarget, true); } return(path); }
private bool TryGetBestStepToHealth(LevelView level, out Location locationToStep) { locationToStep = FindByDijkstra(level, IsToConsider, GetCost); return(locationToStep != default(Location)); bool IsToConsider(Location location) { return(level.GetHealthPackAt(location).HasValue || location == _exit && _exit != default(Location) || GetNeighbours(location, NeighbourType.Four) .Any(y => level.Field[y] == CellType.Hidden && _hiddenYet.Contains(y))); } int GetCost(Location location) { if (level.Field[location] == CellType.Wall || level.Field[location] == CellType.Trap || level.GetMonsterAt(location).HasValue || level.GetItemAt(location).HasValue) { return(100); } if (level.Field[location] == CellType.Exit || level.GetHealthPackAt(location).HasValue) { return(0); } if (level.Field[location] == CellType.Empty || level.Field[location] == CellType.PlayerStart) { return(10 - GetNeighbours(location, NeighbourType.Eight) .Count(x => level.Field[x] == CellType.Trap || level.Field[x] == CellType.Wall)); } if (level.Field[location] == CellType.Hidden) { return(10); } throw new ArgumentOutOfRangeException(nameof(location)); } }
public static IEnumerable <Location> Dijkstra(LevelView levelView, Func <Location, bool> isTarget) { var costs = new InfluenceMap(levelView); var current = levelView.Player.Location; var dist = new Dictionary <Location, int> { [current] = 0 }; var prev = new Dictionary <Location, Location>(); var notOpened = new HashSet <Location> { current }; for (var y = 0; y < levelView.Field.Height; y++) { for (var x = 0; x < levelView.Field.Width; x++) { var location = new Location(x, y); var cellType = levelView.Field[location]; if ((cellType == CellType.Empty || cellType == CellType.PlayerStart) && (location != current) && !levelView.GetItemAt(location).HasValue) { notOpened.Add(location); dist[location] = int.MaxValue; } } } while (notOpened.Any()) { var toOpen = default(Location); var bestPrice = int.MaxValue; foreach (var node in notOpened) { if (dist.ContainsKey(node) && (dist[node] < bestPrice)) { bestPrice = dist[node]; toOpen = node; } } notOpened.Remove(toOpen); if (isTarget(toOpen)) { return(RevertPath(levelView, toOpen, prev)); } foreach (var stepOffset in Offset.StepOffsets) { var neighbour = toOpen + stepOffset; if (!notOpened.Contains(neighbour)) { continue; } var alt = dist[toOpen] + costs[neighbour]; if (alt < dist[neighbour]) { dist[neighbour] = alt; prev[neighbour] = toOpen; } } } return(RevertPath(levelView, current, prev)); }
private static Turn ExecuteFindMonster(LevelView levelView) { var pathToMonster = PathFinder.FindShortestPath(levelView, levelView.Player.Location, location => IsLocationForAttack(levelView, location)); if (pathToMonster != null) { return(PathFinder.GetFirstTurn(pathToMonster)); } var pathToHealthOrItem = PathFinder.FindShortestPath(levelView, levelView.Player.Location, location => levelView.GetHealthPackAt(location).HasValue || levelView.GetItemAt(location).HasValue); return(PathFinder.GetFirstTurn(pathToHealthOrItem)); }