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); }
private bool AnnealStep() { _annealFit.OrderByDescending(placedObj => placedObj.PlacementScore); var numReplace = (_annealFit.Count * _percentReplaced) / 100; numReplace = Math.Max(2, numReplace); var stepLength = _annealFit.Count / numReplace; //UnityEngine.Debug.Log("Replacing " + numReplace + " of " + annealFit.Count); var placedObjsToBeReplacedWithIndex = new List <Selection>(); for (int i = 0; i < numReplace; i++) { // - i so we only select those which were not previously selected var objIndex = _rand.Next(0, i * stepLength - i); // skip one position if it was previously chosen (because we looked for total -i) // needs to be done in the correct order placedObjsToBeReplacedWithIndex = placedObjsToBeReplacedWithIndex.OrderBy(selected => selected.Index).ToList(); for (int j = 0; j < i; j++) { if (objIndex >= placedObjsToBeReplacedWithIndex[j].Index) { objIndex++; } } //UnityEngine.Debug.Log("Selecting object " + objIndex); var placedObj = _annealFit[objIndex]; placedObjsToBeReplacedWithIndex.Add(new Selection(objIndex, placedObj)); placedObj.RemoveFromRooms(); } var replacedPlacedObjs = new List <PlacedObject>(); foreach (var idObj in placedObjsToBeReplacedWithIndex) { var newPlaced = new RectanglePlacer(idObj.PlacedObj.Rooms) .Place(idObj.PlacedObj.PlaceableObject, PlacementScoreRequirement.PreferBest, true); if (newPlaced == null) { // first remove so that there is the original space for (int i = 0; i < replacedPlacedObjs.Count; i++) { replacedPlacedObjs[i].RemoveFromRooms(); } foreach (var beforePlaced in placedObjsToBeReplacedWithIndex) { beforePlaced.PlacedObj.AddToRooms(); } break; } replacedPlacedObjs.Add(newPlaced); } if (replacedPlacedObjs.Count != placedObjsToBeReplacedWithIndex.Count) { return(false); } _beforeStep = placedObjsToBeReplacedWithIndex.Select(sel => sel.PlacedObj).ToList(); _afterStep = replacedPlacedObjs; return(true); }