public void TestDfsMaze() { int w = 50; int h = 50; int maxIter = 2 * (50 * 50) + 1; IMapGenerator simpleMapGenerator = new SimpleMapGenerator(); Map map = simpleMapGenerator.GenerateMap(w, h, IMapGeneratorConstants.NO_SEED); AbstractPlayer simpleAIPlayer = new SimpleAIPlayer("Simple maze solver", map.Grid[0, 0]) { IgnoreSpeed = true }; map.AddCreature(simpleAIPlayer); MapBlock finish = map.Grid[w - 1, h - 1]; bool finishReached = false; int iter = 0; int nullActions = 0; while (!finishReached && iter < maxIter) { simpleAIPlayer.Think(); AbstractAction action = simpleAIPlayer.NextAction; if (action == null) { nullActions++; } else { Assert.AreEqual(typeof(Move), action.GetType(), $"Wrong type of action in {iter} iteration!"); ((Move)action).Execute(); finishReached = finish.Equals(simpleAIPlayer.Position); } iter++; } Assert.IsTrue(finishReached, $"Finish not reached in {maxIter} iterations! Null actions: {nullActions}."); }
public List<PathBlock> AStarPath(MapBlock from, MapBlock to, bool willBreakThroughStuff) { if (!to.Passable) { //int closestH = 1000; foreach (MapBlock mb in to.SurroundingBlocks) { PathBlock p = new PathBlock(mb, null); p.CalculateH(from); } } List<PathBlock> pathToTake = new List<PathBlock>(); //final result List<PathBlock> openList = new List<PathBlock>(); //possible paths to check List<PathBlock> closedList = new List<PathBlock>(); //all spaces that have been checked PathBlock first = new PathBlock(from, null); first.G = 0; first.CalculateH(to); openList.Add(new PathBlock(from, null)); if (from.Equals(to)) { return pathToTake; } while (openList.Count > 0) { PathBlock blockToCheck = openList[0]; if (blockToCheck.AttachedBlock.Equals(to)) { //path found, work backwards from blockToCheck's parent. // PathBlock backtracker = blockToCheck; while (backtracker.Parent != null) { pathToTake.Insert(0, backtracker); backtracker = backtracker.Parent; } return pathToTake; } openList.Remove(blockToCheck); closedList.Add(blockToCheck); foreach (MapBlock mb in blockToCheck.AttachedBlock.SurroundingBlocks) { PathBlock p = new PathBlock(mb, blockToCheck); p.G = blockToCheck.G + 1; p.CalculateH(to); //ignore blocks in the closed list and those that aren't passable unless smashy smashy // if (!closedList.Contains(p)) { int gScore = blockToCheck.G + 1; if (!mb.Passable) //!passable means a prop is there. That means more time smashing. { gScore += 3; } if (!openList.Contains(p)) { bool inserted = false; for (int i = 0; i < openList.Count; i++) { if (openList[i].F > p.F) { openList.Insert(i, p); inserted = true; break; } } if (!inserted) { openList.Add(p); } } else { //if the block is already in the openList, take the one with the lowest G value. If needed, switch the parent and recalculate G. PathBlock blockInList = openList.Find((i) => i.Equals(p)); if (p.G < blockInList.G) { openList.Remove(blockInList); bool inserted = false; for (int i = 0; i < openList.Count; i++) { if (openList[i].F > p.F) { openList.Insert(i, p); inserted = true; break; } } if (!inserted) { openList.Add(p); } //blockInList.G = p.G; //blockInList.Parent = blockToCheck; } } } } } return pathToTake; }