public void FloodFill() { Bitmap map = new Bitmap(new string[] { "111111111111111111", "100000000000001001", "100000000000001001", "100001111111001001", "100001010001001001", "100001000101001001", "100001111111000001", "111011000000001111", "100000001000010001", "100000001000010001", "111111111111111111" }); Debug.WriteLine(map.ToString()); Evaluator<LocationNode> eval = new Evaluator<LocationNode>(); FloodFillStrategy strategy = new FloodFillStrategy(map, new VectorInt(2, 2)); eval.Evaluate(strategy); Debug.WriteLine(strategy.Result.ToString()); List<LocationNode> path = strategy.GetShortestPath(new VectorInt(9, 9)); Assert.IsNotNull(path); Debug.WriteLine(StringHelper.Join(path, delegate(LocationNode node) { return node.Location.ToString(); }, ", ")); Debug.WriteLine(map.ToString()); // Expected value Assert.AreEqual(new VectorInt(9, 9), path[path.Count - 1].Location); }
/// <summary> /// Generate a static move map, ie. all positions for which a player could move to in the course of a puzzle /// </summary> /// <param name="Map"></param> /// <returns></returns> public static Bitmap GenerateStaticMoveMap(SokobanMap Map) { Bitmap boundry = GenerateBoundryMap(Map); // Flood fill from player position to remove any unreachable positions FloodFillStrategy floodFill = new FloodFillStrategy(boundry, Map.Player); Evaluator<LocationNode> eval = new Evaluator<LocationNode>(); eval.Evaluate(floodFill); return floodFill.Result; }
/// <summary> /// Generate the move map for a current position /// </summary> /// <param name="boundryMap"></param> /// <param name="crateMap">May be null, assumes boundryMap is constraintmap</param> /// <param name="playerPosition"></param> /// <returns></returns> public static Bitmap GenerateMoveMap(Bitmap boundryMap, Bitmap crateMap, VectorInt playerPosition) { Bitmap constraints = boundryMap; if (crateMap != null) constraints = boundryMap.BitwiseOR(crateMap); // Flood fill from player position to remove any unreachable positions FloodFillStrategy floodFill = new FloodFillStrategy(constraints, playerPosition); Evaluator<LocationNode> eval = new Evaluator<LocationNode>(); eval.Evaluate(floodFill); return floodFill.Result; }
/// <summary> /// Find the shortest path from the player position to a destination position /// </summary> /// <param name="Map">Map</param> /// <param name="Destination">Destination goal position</param> /// <returns>NULL if no path is found</returns> public static List<VectorInt> FindPlayerPath(SokobanMap Map, VectorInt Destination) { Bitmap boundry = MapAnalysis.GenerateBoundryMap(Map); boundry = boundry.BitwiseOR(MapAnalysis.GenerateCrateMap(Map)); // Find all positble moves for the player FloodFillStrategy floodFill = new FloodFillStrategy(boundry, Map.Player); Evaluator<LocationNode> eval = new Evaluator<LocationNode>(); eval.Evaluate(floodFill); List<LocationNode> result = floodFill.GetShortestPath(Destination); if (result == null) return null; // Path found, convert to VectoInt return result.ConvertAll<VectorInt>(delegate(LocationNode item) { return item.Location; }); }
/// <summary> /// Find Rooms based on door positions /// </summary> private void AnalyseRooms() { int roomID = 0; foreach (Door door in doors) { foreach (VectorInt exit in door.Exits) { // Does this belong to a room already? if (FindRooms(exit.X, exit.Y) == null) { roomID++; Room newRoom = new Room("R" + roomID.ToString(), controller.Map.Size); newRoom.Doors.Add(door); // Set Room region Bitmap boundry = controller.StaticAnalysis.BoundryMap.BitwiseOR(doorBitmap); FloodFillStrategy floodfill = new FloodFillStrategy(boundry, exit); Evaluator<LocationNode> eval = new Evaluator<LocationNode>(); eval.Evaluate(floodfill); // Set region from floodfill newRoom.Set(floodfill.Result); newRoom[exit] = true; // Make sure the exit is also in the room newRoom.Goals = newRoom.BitwiseAND(controller.StaticAnalysis.GoalMap).Count; if (newRoom.Goals == 0) { newRoom.Roomtype = Room.RoomTypes.StorageRoom; } else { newRoom.Roomtype = Room.RoomTypes.GoalRoom; } // Human Readable name newRoom.Name = newRoom.Description; // Link to other doors LinkDoors(newRoom); // Add it the size if more than one floor space if (newRoom.Count > 1) { rooms.Add(newRoom); controller.DebugReport.AppendHeading(3,"{0} Room ({1}) found with {2} goals:", newRoom.Roomtype, newRoom.Name, newRoom.Goals); controller.DebugReport.Append("Doors: {0}", StringHelper.Join(newRoom.Doors, delegate(Door item) { return string.Format("{0}({2})@{1}", item.Type, item.Position, item.DoorID); }, ", ")); controller.DebugReport.Append(newRoom.ToString()); controller.DebugReport.CompleteSection(); } } } } controller.DebugReport.CompleteSection(); }