public void Process_Health50BesideATavern_1Paths() { var map = MapTest.Map10Mines8; var state = State.Create(0, new Hero(50, 1, 0, 0, 0), new Hero(100, 8, 0, 0, 0), new Hero(100, 8, 9, 0, 0), new Hero(100, 1, 9, 0, 0), MineOwnership.Create(map)); var source = map[state.Hero1]; var mines = state.Mines; var collection = SafePathCollection.Create(map, state); var processor = new DrinkBeerProcessor(); processor.Initialize(map, state); var path = PotentialPath.Initial(source, map, state); processor.Process(path, collection); var act = collection.GetPotentialPaths(); Assert.AreEqual(1, act.Count); PotentialPathAssert.AreEqual(1, source, 99, mines, MoveDirections.E, -2, act[0]); }
/// <summary>Processes the potential path.</summary> public override void Process(PotentialPath potentialPath, SafePathCollection collection) { var source = potentialPath.Source; if (source.Neighbors.Any(n => n.IsTaverne)) { var directions = new MoveDirections(source.Directions.Where(direction => source[direction].IsTaverne)); var turns = 0; var health = potentialPath.Health; var profit = 0; var mines = potentialPath.Mines.Count(this.PlayerToMove); while (health < Hero.HealthMax) { turns++; health = Math.Min(health + Hero.HealthTavern, Hero.HealthMax); profit += mines - Hero.CostsTavern; var followUp = potentialPath.CreateFollowUp( source, health - 1, potentialPath.Mines, directions, turns, profit); collection.Enqueue(followUp); } } }
/// <summary> /// Creates a new Potential Path which is a copy of an existing Path /// </summary> /// <param name="p">Potentuak Path</param> public PotentialPath(PotentialPath p) { this._start = p.Start; this._current = p.Current; this._complete = p.IsComplete; this._deadend = p.IsDeadEnd; this._partial = p.IsPartial; this._length = p.Length; }
/// <summary> /// Creates a new Potential Path which is a copy of an existing Path /// </summary> /// <param name="p">Potentuak Path</param> public PotentialPath(PotentialPath p) { _start = p.Start; _current = p.Current; _complete = p.IsComplete; _deadend = p.IsDeadEnd; _partial = p.IsPartial; _length = p.Length; }
public override void Process(PotentialPath potentialPath, SafePathCollection collection) { foreach (var mine in this.Map.Mines.Where(m => potentialPath.Mines[m.MineIndex] != this.PlayerToMove)) { foreach (var target in mine.Neighbors.Where(n => n.IsPassable)) { ProcessToMine(potentialPath, target, mine.MineIndex, collection); } } }
public override void Process(PotentialPath potentialPath, SafePathCollection collection) { foreach (var Tavern in this.Map.Taverns) { foreach (var target in Tavern.Neighbors.Where(n => n.IsPassable)) { ProcessToTavern(potentialPath, target, collection); } } }
public static void AddPotential(PotentialPath potential_path, int parent_cell, NavType parent_nav_type, int cost, int underwater_cost, int transition_id, PotentialList potentials, PathGrid path_grid, ref Cell cell_data) { cell_data.cost = cost; cell_data.underwaterCost = (byte)Math.Min(underwater_cost, 255); cell_data.parent = parent_cell; cell_data.navType = potential_path.navType; cell_data.parentNavType = parent_nav_type; cell_data.transitionId = transition_id; potentials.Add(cost, potential_path); path_grid.SetCell(potential_path, ref cell_data); }
public static void Run(NavGrid nav_grid, PathFinderAbilities abilities, PotentialPath potential_path, PathFinderQuery query, ref Path path) { Run(nav_grid, abilities, potential_path, query); if (query.GetResultCell() != InvalidCell) { BuildResultPath(query.GetResultCell(), query.GetResultNavType(), ref path); } else { path.Clear(); } }
/// <summary> /// Checks whether the other object is an equivalent potential path /// </summary> /// <param name="obj">Object to test</param> /// <returns></returns> public override bool Equals(object obj) { if (obj is PotentialPath) { PotentialPath other = (PotentialPath)obj; return(this._start.Equals(other.Start) && this._current.Equals(other.Current)); } else { return(false); } }
public static void Run(NavGrid nav_grid, PathFinderAbilities abilities, PotentialPath potential_path, PathFinderQuery query) { int result_cell = InvalidCell; NavType result_nav_type = NavType.NumNavTypes; query.ClearResult(); if (Grid.IsValidCell(potential_path.cell)) { FindPaths(nav_grid, ref abilities, potential_path, query, Temp.Potentials, ref result_cell, ref result_nav_type); if (result_cell != InvalidCell) { bool is_cell_in_range = false; Cell cell = PathGrid.GetCell(result_cell, result_nav_type, out is_cell_in_range); query.SetResult(result_cell, cell.cost, result_nav_type); } } }
public static void AreEqual( int expTurns, Tile expSource, int expHealth, IMineOwnership expMines, MoveDirections expDirections, int expProfit, PotentialPath actual) { Assert.IsNotNull(actual); Assert.AreEqual(expTurns, actual.Turns, "Turns, {0}", actual.DebuggerDisplay); Assert.AreEqual(expSource, actual.Source, "Sources, {0}", actual.DebuggerDisplay); Assert.AreEqual(expHealth, actual.Health, "Health, {0}", actual.DebuggerDisplay); Assert.AreEqual(expMines, actual.Mines, "Mines, {0}", actual.DebuggerDisplay); Assert.AreEqual(expDirections, actual.Directions, "Directions, {0}", actual.DebuggerDisplay); Assert.AreEqual(expProfit, actual.Profit, "Profit, {0}", actual.DebuggerDisplay); //public List<PotentialOpponent> Opponents { get; set; } }
private static void FindPaths(NavGrid nav_grid, ref PathFinderAbilities abilities, PotentialPath potential_path, PathFinderQuery query, PotentialList potentials, ref int result_cell, ref NavType result_nav_type) { potentials.Clear(); PathGrid.ResetUpdate(); PathGrid.BeginUpdate(potential_path.cell, false); bool is_cell_in_range; Cell cell_data = PathGrid.GetCell(potential_path, out is_cell_in_range); AddPotential(potential_path, Grid.InvalidCell, NavType.NumNavTypes, 0, 0, -1, potentials, PathGrid, ref cell_data); int num = 2147483647; while (potentials.Count > 0) { KeyValuePair <int, PotentialPath> keyValuePair = potentials.Next(); cell_data = PathGrid.GetCell(keyValuePair.Value, out is_cell_in_range); if (cell_data.cost != keyValuePair.Key) { continue; } int num2; if (cell_data.navType != NavType.Tube) { PotentialPath value = keyValuePair.Value; if (query.IsMatch(value.cell, cell_data.parent, cell_data.cost)) { num2 = ((cell_data.cost < num) ? 1 : 0); goto IL_00cc; } } num2 = 0; goto IL_00cc; IL_00cc: if (num2 != 0) { PotentialPath value2 = keyValuePair.Value; result_cell = value2.cell; num = cell_data.cost; result_nav_type = cell_data.navType; break; } AddPotentials(nav_grid.potentialScratchPad, keyValuePair.Value, cell_data.cost, cell_data.underwaterCost, ref abilities, query, nav_grid.maxLinksPerCell, nav_grid.Links, potentials, PathGrid, cell_data.parent, cell_data.parentNavType); } PathGrid.EndUpdate(true); }
public Path FindPath(Coordinates departure, Coordinates arrival) { CheckCellIsOnMap(nameof(departure), departure); CheckCellIsOnMap(nameof(arrival), arrival); CheckCellIsNotBlock(nameof(departure), departure); CheckCellIsNotBlock(nameof(arrival), arrival); Dictionary<Coordinates, PotentialPath> potentialPaths = new Dictionary<Coordinates, PotentialPath>(); foreach(var keyValue in _cells.Where(kv => kv.Value.Type != CellType.Block)) { potentialPaths[keyValue.Key] = keyValue.Key == departure ? new PotentialPath() { Path = Path.Create(Step.Create(departure)), Explored = false } : null; } while (potentialPaths[arrival] == null) { var nextCellsToExplore = potentialPaths.Where(p => p.Value != null && !p.Value.Explored); if (!nextCellsToExplore.Any()) { break; } var minPathWeight = nextCellsToExplore.Min(c => c.Value.Path.Weight); var nextCellToExplore = nextCellsToExplore.First(c => c.Value.Path.Weight == minPathWeight); nextCellToExplore.Value.Explored = true; foreach (var neighbor in _cells[nextCellToExplore.Key].Coordinates.Surrounding) { if (potentialPaths.ContainsKey(neighbor) && potentialPaths[neighbor] == null) { potentialPaths[neighbor] = new PotentialPath() { Path = nextCellToExplore.Value.Path.AddStep(Step.Create(neighbor, _cells[neighbor].Weight)), Explored = false }; } } } return potentialPaths[arrival]?.Path; }
public void Process_Health99BesideATavern_NoPaths() { var map = MapTest.Map10Mines8; var state = State.Create(0, new Hero(100, 1, 0, 0, 0), new Hero(100, 8, 0, 0, 0), new Hero(100, 8, 9, 0, 0), new Hero(100, 1, 9, 0, 0), MineOwnership.Create(map)); var collection = SafePathCollection.Create(map, state); var processor = new DrinkBeerProcessor(); processor.Initialize(map, state); var path = PotentialPath.Initial(map[state.Hero1], map, state); processor.Process(path, collection); var act = collection.GetPotentialPaths(); Assert.AreEqual(0, act.Count); }
public static bool ValidatePath(NavGrid nav_grid, PathFinderAbilities abilities, ref Path path) { if (!path.IsValid()) { return(false); } for (int i = 0; i < path.nodes.Count; i++) { Path.Node node = path.nodes[i]; if (i < path.nodes.Count - 1) { Path.Node node2 = path.nodes[i + 1]; int num = node.cell * nav_grid.maxLinksPerCell; bool flag = false; NavGrid.Link link = nav_grid.Links[num]; while (link.link != InvalidHandle) { if (link.link == node2.cell && node2.navType == link.endNavType && node.navType == link.startNavType) { PotentialPath path2 = new PotentialPath(node.cell, node.navType, PotentialPath.Flags.None); flag = abilities.TraversePath(ref path2, node.cell, node.navType, 0, link.transitionId, 0); if (flag) { break; } } num++; link = nav_grid.Links[num]; } if (!flag) { return(false); } } } return(true); }
public abstract void Process(PotentialPath potentialPath, SafePathCollection collection);
public void ProcessToMine(PotentialPath potentialPath, Tile target, int mineIndex, SafePathCollection collection) { var source = potentialPath.Source; var distances = GetEmptyDistances(); var distancesToTarget = this.Map.GetDistances(target); var startDistance = distancesToTarget.Get(source); var distance = startDistance; var health = potentialPath.Health; var turns = potentialPath.Turns; var queue = new Queue <Tile>(); distances.Set(source, distance); queue.Enqueue(source); while (distance > Distance.Zero) { var options = queue.Count; // No options available. if (options == 0) { return; } distance--; health = Math.Max(Hero.HealthMin, health - 1); turns++; for (int option = 0; option < options; option++) { var tile = queue.Dequeue(); foreach (var neighbor in tile.Neighbors) { //if (ShouldEnqueue(distances, distancesToTarget, distance, turns, health, neighbor)) //{ // queue.Enqueue(neighbor); //} } } } var isSafe = false; // It takes another turn to get the mine. turns++; while (!isSafe && queue.Count > 0) { var tile = queue.Dequeue(); isSafe = health > Hero.HealthBattle || potentialPath.Opponents.All(oppo => !oppo.StrongerAtLocationAndTime(this.Map, tile, health, turns)); } if (isSafe) { var directions = potentialPath.Directions; if (directions.IsEmpty()) { directions = new MoveDirections(source.Directions.Where(dir => distances.Get(source[dir]) < startDistance)); if (directions.Length == 0) { // we are already standing beside a mine. if (startDistance == Distance.Zero) { directions = new MoveDirections(source.Directions.Where(dir => source[dir].MineIndex == mineIndex)); } if (directions.Length == 0) { #if DEBUG throw new Exception("No directions found."); #else return; #endif } } } var mines = potentialPath.Mines.Set(mineIndex, this.PlayerToMove); health -= Hero.HealthBattle; var profit = potentialPath.Profit; profit += (mines.Count(this.PlayerToMove) - 1) * (turns - potentialPath.Turns) + 1; var followUp = potentialPath.CreateFollowUp(target, health, mines, directions, turns, profit); collection.Enqueue(followUp); } }
public void ProcessToTavern(PotentialPath potentialPath, Tile target, SafePathCollection collection) { var source = potentialPath.Source; var distances = GetEmptyDistances(); var distancesToTarget = this.Map.GetDistances(target); var startDistance = distancesToTarget.Get(source); var distance = startDistance; var health = potentialPath.Health; var turns = potentialPath.Turns; // We don't consider it a safe path (yet) when we are already beside a Tavern. if (potentialPath.Turns == 0 && startDistance == Distance.Zero) { return; } var queue = new Queue <Tile>(); distances.Set(source, distance); queue.Enqueue(source); while (distance > Distance.Zero) { var options = queue.Count; // No options available. if (options == 0) { return; } distance--; health = Math.Max(Hero.HealthMin, health - 1); turns++; for (int option = 0; option < options; option++) { var tile = queue.Dequeue(); foreach (var neighbor in tile.Neighbors) { //if (ShouldEnqueue(distances, distancesToTarget, distance, potentialPath.Turns, health, neighbor)) //{ // queue.Enqueue(neighbor); //} } } } var isSafe = false; while (!isSafe && queue.Count > 0) { var tile = queue.Dequeue(); isSafe = health > Hero.HealthBattle || potentialPath.Opponents.All(oppo => !oppo.StrongerAtLocationAndTime(this.Map, tile, health, turns)); } if (isSafe) { var profit = potentialPath.Profit; profit += potentialPath.Mines.Count(this.PlayerToMove) * (int)startDistance; if (potentialPath.Directions.IsEmpty()) { var directions = source.Directions .Where(dir => distances.Get(source[dir]) < startDistance) .ToArray(); // We just found a direct safe paht to a Tavern. collection.Add(new SafePath(potentialPath.Mines.Count(this.PlayerToMove), turns, profit, directions)); } else { collection.Add(potentialPath.ToSafePath(this.PlayerToMove, turns, profit)); } } }
public void Add(int cost, PotentialPath path) { queue.Enqueue(cost, path); }
public static void UpdatePath(NavGrid nav_grid, PathFinderAbilities abilities, PotentialPath potential_path, PathFinderQuery query, ref Path path) { Run(nav_grid, abilities, potential_path, query, ref path); }
public static void AddPotentials(PotentialScratchPad potential_scratch_pad, PotentialPath potential, int cost, int underwater_cost, ref PathFinderAbilities abilities, PathFinderQuery query, int max_links_per_cell, NavGrid.Link[] links, PotentialList potentials, PathGrid path_grid, int parent_cell, NavType parent_nav_type) { int num = 0; NavGrid.Link[] linksWithCorrectNavType = potential_scratch_pad.linksWithCorrectNavType; int num2 = potential.cell * max_links_per_cell; NavGrid.Link link = links[num2]; for (int link2 = link.link; link2 != InvalidHandle; link2 = link.link) { if (link.startNavType == potential.navType && (parent_cell != link2 || parent_nav_type != link.startNavType)) { linksWithCorrectNavType[num++] = link; } num2++; link = links[num2]; } int num4 = 0; PotentialScratchPad.PathGridCellData[] linksInCellRange = potential_scratch_pad.linksInCellRange; for (int i = 0; i < num; i++) { NavGrid.Link link3 = linksWithCorrectNavType[i]; int link4 = link3.link; bool is_cell_in_range = false; Cell cell = path_grid.GetCell(link4, link3.endNavType, out is_cell_in_range); if (is_cell_in_range) { int num5 = cost + link3.cost; bool flag = cell.cost == -1; bool flag2 = num5 < cell.cost; if (flag || flag2) { linksInCellRange[num4++] = new PotentialScratchPad.PathGridCellData { pathGridCell = cell, link = link3 }; } } } for (int j = 0; j < num4; j++) { PotentialScratchPad.PathGridCellData pathGridCellData = linksInCellRange[j]; NavGrid.Link link5 = pathGridCellData.link; int link6 = link5.link; pathGridCellData.isSubmerged = IsSubmerged(link6); linksInCellRange[j] = pathGridCellData; } for (int k = 0; k < num4; k++) { PotentialScratchPad.PathGridCellData pathGridCellData2 = linksInCellRange[k]; NavGrid.Link link7 = pathGridCellData2.link; int link8 = link7.link; Cell cell_data = pathGridCellData2.pathGridCell; int num7 = cost + link7.cost; PotentialPath path = potential; path.cell = link8; path.navType = link7.endNavType; int underwater_cost2; if (pathGridCellData2.isSubmerged) { underwater_cost2 = underwater_cost + 1; int submergedPathCostPenalty = abilities.GetSubmergedPathCostPenalty(path, link7); num7 += submergedPathCostPenalty; } else { underwater_cost2 = 0; } PotentialPath.Flags flags = path.flags; bool flag3 = abilities.TraversePath(ref path, potential.cell, potential.navType, num7, link7.transitionId, underwater_cost2); if (path.flags != flags) { KProfiler.AddEvent("NavChange"); } if (flag3) { AddPotential(path, potential.cell, potential.navType, num7, underwater_cost2, link7.transitionId, potentials, path_grid, ref cell_data); } } }