예제 #1
0
        /// <summary>
        /// 現在のルームに新しいアイテムを配置できるかを確認し、配置できる場合には現在のルームに新しいアイテムを配置したルームを返却する。
        /// </summary>
        /// <param name="newDisposition">配置するアイテムの情報</param>
        /// <param name="addedRoom">アイテムが追加されたルーム</param>
        /// <returns>アイテムが追加された場合はtrue、追加できなかった場合はfalse</returns>
        /// <remarks>
        /// このメソッドがtrueを返却した場合にも現在のルームは変更されない。
        /// 現在のルームに新しいアイテムが追加されたルームが作成され、addedRoomに返却される。
        /// </remarks>
        public bool TryAddItem(ItemDisposition newDisposition, out Room addedRoom)
        {
            var addPoint = newDisposition.Location;
            var newItem  = newDisposition.Item;

            var newFreeFloorList = new List <Point>(FreeFloors);
            var occupationPoints = newItem.Occupation.ToRoomCoordination(addPoint);

            foreach (var p in occupationPoints)
            {
                if (!newFreeFloorList.Remove(p))
                {
                    addedRoom = none;
                    return(false);
                }
            }
            var newFreeFloors = newFreeFloorList.ToArray();

            var newWidth  = Width;
            var newHeight = Height;

            var newDispositions = new ItemDisposition[Dispositions.Length + 1];

            Dispositions.CopyTo(newDispositions, 0);
            newDispositions[newDispositions.Length - 1] = newDisposition;

            var newFloorSummary = (int?[, ])FloorSummary.Clone();

            foreach (var p in occupationPoints)
            {
                newFloorSummary[p.X, p.Y] = newItem.ID;
            }

            addedRoom = new Room(newWidth, newHeight, newDispositions, newFreeFloors, newFloorSummary);
            return(true);
        }
예제 #2
0
        public Task FindRoomCoordinationAsync(Room startRoom, RoomItem[] items, IRoomReviewer[] reviewers, Action <Room> roomReceiver, Action <Room> halfwayReceiver, CancellationToken cancel)
        {
            //var taskCount = Math.Max(1, Environment.ProcessorCount - 1);
            var taskCount = Math.Max(1, Environment.ProcessorCount);
            var popCount  = 10;
            var wait      = TimeSpan.FromMilliseconds(100);

            var stack = new ConcurrentStack <Tuple <Room, RoomItem[]> >();

            stack.Push(Tuple.Create(startRoom, items));

            var waitingCount = 0;


            return(Task.Run(() => {
                var workers = new Task[taskCount];
                for (int i = 0; i < workers.Length; i++)
                {
                    workers[i] = Task.Factory.StartNew(() => {
                        var buffer = new Tuple <Room, RoomItem[]> [popCount];
                        var waiting = false;
                        int counter = 0;
                        Tuple <Room, RoomItem[]>[] newRooms = null;
                        while (true)
                        {
                            cancel.ThrowIfCancellationRequested();

                            var itemCount = stack.TryPopRange(buffer);
                            if (itemCount > 0)
                            {
                                if (waiting)
                                {
                                    Interlocked.Decrement(ref waitingCount);
                                    waiting = false;
                                }

                                counter++;
                                if (counter % 100 == 0)
                                {
                                    counter = 0;
                                    halfwayReceiver(buffer[0].Item1);
                                }

                                if (newRooms == null)
                                {
                                    var newRoomsLength = (buffer[0].Item1.Width + 2) * (buffer[0].Item1.Height + 2) * 2;
                                    newRooms = new Tuple <Room, RoomItem[]> [newRoomsLength];
                                }


                                for (var i = 0; i < itemCount; i++)
                                {
                                    var roomItemPair = buffer[i];
                                    var room = roomItemPair.Item1;
                                    var items = roomItemPair.Item2;
                                    if ((items.Length == 0))
                                    {
                                        roomReceiver(room);
                                    }
                                    else
                                    {
                                        var item = items[0];
                                        var flippedItem = item.Flip();
                                        var newItems = items[1..^ 0];

                                        var newRoomsCount = 0;

                                        for (var y = room.Height; y >= -1; y--)
                                        {
                                            for (var x = room.Width; x >= -1; x--)
                                            {
                                                var p = new Point(x, y);

                                                var disposition = new ItemDisposition(p, item);
                                                Room newRoom;
                                                if (room.TryAddItem(disposition, out newRoom))
                                                {
                                                    if (newRoom.IsAcceptableWith(reviewers))
                                                    {
                                                        newRooms[newRoomsCount] = Tuple.Create(newRoom, newItems);
                                                        newRoomsCount++;
                                                    }
                                                }

                                                var disposition2 = new ItemDisposition(p, flippedItem);
                                                Room newRoom2;
                                                if (room.TryAddItem(disposition2, out newRoom2))
                                                {
                                                    if (newRoom2.IsAcceptableWith(reviewers))
                                                    {
                                                        newRooms[newRoomsCount] = Tuple.Create(newRoom2, newItems);
                                                        newRoomsCount++;
                                                    }
                                                }
                                            }
                                        }
                                        if (newRoomsCount > 0)
                                        {
                                            stack.PushRange(newRooms, 0, newRoomsCount);
                                        }
                                    }
                                }
                            }