public int Pack(out List <PlacedObject> placedObjs, List <PlaceableObject> objectsToPlace, bool[,] roomLayout, PlacementScoreRequirement scoreReq = PlacementScoreRequirement.DontCare, bool includeDistance = false, float acceptProbability = 1f) { var templateRoom = new Room(roomLayout, _freeBoolValue); var roomIds = objectsToPlace.SelectMany(obj => obj.RoomsIn).Distinct(); var rooms = new Dictionary <int, Room>(); foreach (var r in roomIds) { var room = templateRoom.CloneBase(); room.Id = r; rooms[r] = room; } // sort objectsByScore var objectsToPlaceSorted = objectsToPlace.OrderBy( obj => - obj.TilesNeeded * obj.RoomsIn.Count ); // pack objects placedObjs = new List <PlacedObject>(); foreach (var obj in objectsToPlaceSorted) { IRoom objRooms = new RoomCollection(obj.RoomsIn.Select(roomId => rooms[roomId])); RectanglePlacer placer = new RectanglePlacer(objRooms); var placedObj = placer.Place(obj, scoreReq, includeDistance, acceptProbability); if (placedObj == null) { placedObjs = null; return(int.MaxValue); } placedObjs.Add(placedObj); } Debug.Assert(placedObjs.Count == objectsToPlace.Count); var score = placedObjs.Sum(placedObj => placedObj.WallScore); //UnityEngine.Debug.Log("[RectPlacer] Finished First Fit"); //UnityEngine.Debug.Log("[RectPlacer] WallScore: " + score); //Helper.PrintToConsole(placedObjs); return(score); }
public PlacedObject Place(PlaceableObject obj, PlacementScoreRequirement scoreReq) { if (scoreReq != PlacementScoreRequirement.DontCare) { throw new NotImplementedException(); } var tilesNotAvailable = Helper.Copy(_templateRoom.RoomLayout); foreach (var tileIndex in _templateRoom.AvailableTileIndices()) { if (!_room.TileAvailable(tileIndex.X, tileIndex.Y)) { tilesNotAvailable[tileIndex.X, tileIndex.Y] = true; } } PlacedObject placedObj = null; for (var w = 0; placedObj == null && w < _room.Width; w++) { for (var h = 0; placedObj == null && h < _room.Height; h++) { if (Fits(tilesNotAvailable, w, h, obj.Dimensions.X, obj.Dimensions.Y)) { placedObj = new PlacedObject(obj, new Vector(w, h), false); } if (placedObj == null && obj.Dimensions.X != obj.Dimensions.Y && Fits(tilesNotAvailable, w, h, obj.Dimensions.Y, obj.Dimensions.X)) { placedObj = new PlacedObject(obj, new Vector(w, h), true); } } } return(placedObj); }
public PlacedObject Place(PlaceableObject obj, PlacementScoreRequirement scoreReq, bool includeDistance, float acceptProbability = 1f) { _includeDistance = includeDistance; _scoreReq = scoreReq; _bestPlacementSoFar = null; _acceptProbability = acceptProbability; var maxObjectSize = new List <Vector> [_room.Width, _room.Height]; // dynamic algorithm for determining fit // first row for (int w = 0, maxWidth = 0; w < _room.Width; w++) { if (_room.TileAvailable(w, 0)) { maxWidth++; _addSingle(maxObjectSize, w, 0, maxWidth, 1); } else { maxWidth = 0; } var placed = _tryPlaceObject(maxObjectSize, w, 0, obj); if (placed != null) { placed.AddToRooms(); return(placed); } } // first column for (int h = 0, maxHeight = 0; h < _room.Height; h++) { if (_room.TileAvailable(0, h)) { maxHeight++; _addSingle(maxObjectSize, 0, h, 1, maxHeight); } else { maxHeight = 0; } var placed = _tryPlaceObject(maxObjectSize, 0, h, obj); if (placed != null) { placed.AddToRooms(); return(placed); } } // rest of the 2d array for (int h = 1; h < _room.Height; h++) { for (int w = 1, lastSmallestWidth = _room.TileAvailable(0, h) ? 1 : 0; w < _room.Width; w++) { if (_room.TileAvailable(w, h)) { lastSmallestWidth++; _addBasedOnNeighborsForAllDirections(maxObjectSize, w, h, lastSmallestWidth); var placed = _tryPlaceObject(maxObjectSize, w, h, obj); if (placed != null) { placed.AddToRooms(); return(placed); } } else { lastSmallestWidth = 0; } } } if (_bestPlacementSoFar != null) { _bestPlacementSoFar.AddToRooms(); return(_bestPlacementSoFar); } return(null); }
public void GivenPlacementScoreRequirement(PlacementScoreRequirement scoreReq) { _placementScoreReq = scoreReq; }