Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }