/// <summary> /// Finds a path. Throws PathNotFoundException when no path can be found. /// </summary> /// <returns>A finished path.</returns> private Dictionary <HashSet <KeyColor>, Dictionary <Point, PlayerAction> > FindPath() { Level = new AStarLevel(player.TileField); Level.SolveLevel(); if (Level.OptimalPath.Count == 0) { throw new PathNotFoundException(); } return(Level.OptimalPath); }
public AStarLevel(AStarLevel oldField, ColoredTile newKey, long score) { OpenTiles = new List <AStarTile>(); PotentialKeys = new HashSet <ColoredTile>(); ReachedKeys = new HashSet <ColoredTile>(); ClosedDoors = new HashSet <ColoredTile>(); obtainedKeys = new HashSet <KeyColor>(); OptimalPath = new Dictionary <HashSet <KeyColor>, Dictionary <Point, PlayerAction> >(); Field = new AStarTile[oldField.Field.GetLength(0), oldField.Field.GetLength(1)]; for (int x = 0; x < Field.GetLength(0); x++) { for (int y = 0; y < Field.GetLength(1); y++) { Field[x, y] = oldField.Field[x, y].Clone; } } Field[newKey.TileLocation.X, newKey.TileLocation.Y] = new AStarTile(newKey.TileLocation, AStarTileType.passable, score: score); Start = Field[newKey.TileLocation.X, newKey.TileLocation.Y]; OpenTiles.Add(Field[newKey.TileLocation.X, newKey.TileLocation.Y]); //Copy keys exept the reached key foreach (ColoredTile key in oldField.PotentialKeys) { if (key.Color != newKey.Color) { PotentialKeys.Add(key); } else { Field[key.TileLocation.X, key.TileLocation.Y].TileType = AStarTileType.passable; } } //Copy doors exept the doors of the color of the new key. foreach (ColoredTile door in oldField.ClosedDoors) { if (door.Color != newKey.Color) { PotentialKeys.Add(door); } else { Field[door.TileLocation.X, door.TileLocation.Y].TileType = AStarTileType.passable; } } foreach (KeyColor key in oldField.obtainedKeys) { obtainedKeys.Add(key); } obtainedKeys.Add(newKey.Color); }
/// <summary> /// Solves the level. /// </summary> public void SolveLevel() { while (OpenTiles.Count > 0) { OpenTiles.Sort((t1, t2) => t1.Score.CompareTo(t2.Score)); VisitTile(OpenTiles[0]); } HashSet <AStarLevel> innerFields = new HashSet <AStarLevel>(); AStarLevel optimalField = null; foreach (ColoredTile t in ReachedKeys) { AStarLevel newField = new AStarLevel(this, t, Field[t.TileLocation.X, t.TileLocation.Y].Score); innerFields.Add(newField); newField.SolveLevel(); if (newField.Finish?.Score < (Finish?.Score ?? long.MaxValue)) { Finish = newField.Finish; optimalField = newField; } } if (optimalField != null) { OptimalPath.Add(obtainedKeys, CreateOptimalPath(Start, Field[(int)optimalField?.Start.Location.X, (int)optimalField?.Start.Location.Y])); foreach (HashSet <KeyColor> keys in optimalField.OptimalPath.Keys) { OptimalPath.Add(keys, optimalField.OptimalPath[keys]); } } else if (Finish != null) { OptimalPath.Add(obtainedKeys, CreateOptimalPath(Start, Field[(int)Finish?.Location.X, (int)Finish?.Location.Y])); } }