private PlacedObject _tryPlaceObject(List <Vector>[,] vec, int w, int h, PlaceableObject obj) { if (vec[w, h] == null) { return(null); } var numRectanglesCut = vec[w, h].Count; foreach (var maxDimensionInDirection in vec[w, h]) { PlacedObject placedObject = null; if (_placeIfFullfilsConstrainsRememberIfBetterScore( obj, false, new Vector(w - obj.Dimensions.X + 1, h - obj.Dimensions.Y + 1), maxDimensionInDirection, numRectanglesCut, out placedObject)) { return(placedObject); } if (_placeIfFullfilsConstrainsRememberIfBetterScore( obj, true, new Vector(w - obj.Dimensions.Y + 1, h - obj.Dimensions.X + 1), maxDimensionInDirection, numRectanglesCut, out placedObject)) { return(placedObject); } } return(null); }
public PlacedObject(PlaceableObject placeableObject, Vector position, bool flipped, bool shouldCalculateDistScore = false) { PlaceableObject = placeableObject; Position = position; Flipped = flipped; ShouldCalculateDistScore = shouldCalculateDistScore; Dimensions = !Flipped ? PlaceableObject.Dimensions : PlaceableObject.Dimensions.Reversed(); }
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); }
private bool _placeIfFullfilsConstrainsRememberIfBetterScore( PlaceableObject obj, bool flipped, Vector position, Vector maxDimensionsInDirection, int numRectanglesCut, out PlacedObject o) { var placedObject = new PlacedObject(obj, position, flipped, _includeDistance); placedObject.Rooms = _room; if (!placedObject.Fits(maxDimensionsInDirection)) { o = null; return(false); } if (_scoreReq == PlacementScoreRequirement.DontCare) { o = placedObject; return(true); } placedObject.CalculateWallScore(); placedObject.CalculateDistanceScore(); switch (_scoreReq) { case PlacementScoreRequirement.LeastDamageThenBestWall: if (_bestPlacementSoFar == null || placedObject.WallScore + 100 * numRectanglesCut < _bestPlacementSoFar.WallScore + 100 * _numCutsOfBestSoFar) { _bestPlacementSoFar = placedObject; _numCutsOfBestSoFar = numRectanglesCut; } break; case PlacementScoreRequirement.OnlyBestWall: if (placedObject.WallScore == 0) { if (_rand.NextDouble() <= _acceptProbability) { o = placedObject; return(true); } else { _bestPlacementSoFar = placedObject; } } break; case PlacementScoreRequirement.PreferBest: if (placedObject.PlacementScore == 0) { if (_rand.NextDouble() <= _acceptProbability) { o = placedObject; return(true); } else { _bestPlacementSoFar = placedObject; } } else if (_bestPlacementSoFar == null || placedObject.PlacementScore < _bestPlacementSoFar.PlacementScore) { _bestPlacementSoFar = placedObject; } break; } o = null; return(false); }