Пример #1
0
        /// <summary>
        /// 指定した小部屋を分割します。
        /// </summary>
        /// <param name="baseRoomIndex">分割する小部屋のインデックス</param>
        /// <param name="splRate">分割率 (0~100)</param>
        /// <returns>分割に成功しかどうか</returns>
        public bool RandomSplitArea(int baseRoomIndex, int splRate)
        {
            int splVector2Int;
            var newArea = new RectInt();
            var newLink = new RoomLink()
            {
                IsParentLink = true,
            };

            // 分割元の小部屋で辺の長い方を見て分割する: 極端に狭い部屋が生成されすぎないようにする
            if (this.Rooms[baseRoomIndex].AreaRange.width > this.Rooms[baseRoomIndex].AreaRange.height)
            {
                // 横長のときは左右分割
                newLink.SplitType = RoomLink.SplitDirection.Vertical;
            }
            else
            {
                // 縦長の時は上下分割
                newLink.SplitType = RoomLink.SplitDirection.Horizontal;
            }

            // 与えられた小部屋を分割する
            switch (newLink.SplitType)
            {
            case RoomLink.SplitDirection.Horizontal:
                // 上下分割: 横線

                // 分割線の設定
                splVector2Int = this.Rooms[baseRoomIndex].AreaRange.height * splRate / 100;
                if (splVector2Int < MapDataBySectionDivision.MinSplitHeight)
                {
                    // 細かすぎて分割できない場合は処理しない
                    return(false);
                }
                newLink.Start = new Vector2Int(
                    this.Rooms[baseRoomIndex].AreaRange.x,
                    this.Rooms[baseRoomIndex].AreaRange.y + splVector2Int
                    );
                newLink.End = new Vector2Int(
                    this.Rooms[baseRoomIndex].AreaRange.x + this.Rooms[baseRoomIndex].AreaRange.width - 1,
                    this.Rooms[baseRoomIndex].AreaRange.y + splVector2Int
                    );

                // 分割して新しくできた小部屋の設定
                newArea.position = new Vector2Int(
                    this.Rooms[baseRoomIndex].AreaRange.x,
                    this.Rooms[baseRoomIndex].AreaRange.y + splVector2Int + 1
                    );
                newArea.size = new Vector2Int(
                    this.Rooms[baseRoomIndex].AreaRange.width,
                    this.Rooms[baseRoomIndex].AreaRange.height - splVector2Int - 1
                    );

                // 分割元の小部屋の再設定
                this.Rooms[baseRoomIndex] = new RoomData(new RectInt(
                                                             this.Rooms[baseRoomIndex].AreaRange.position,
                                                             new Vector2Int(this.Rooms[baseRoomIndex].AreaRange.width, splVector2Int - 1)
                                                             ));
                break;

            case RoomLink.SplitDirection.Vertical:
                // 左右分割: 縦線

                // 分割線の設定
                splVector2Int = this.Rooms[baseRoomIndex].AreaRange.width * splRate / 100;
                if (splVector2Int < MapDataBySectionDivision.MinSplitWidth)
                {
                    // 細かすぎて分割できない場合は処理しない
                    return(false);
                }
                newLink.Start = new Vector2Int(
                    this.Rooms[baseRoomIndex].AreaRange.x + splVector2Int,
                    this.Rooms[baseRoomIndex].AreaRange.y
                    );
                newLink.End = new Vector2Int(
                    this.Rooms[baseRoomIndex].AreaRange.x + splVector2Int,
                    this.Rooms[baseRoomIndex].AreaRange.y + this.Rooms[baseRoomIndex].AreaRange.height - 1
                    );

                // 分割して新しくできた小部屋の設定
                newArea.position = new Vector2Int(this.Rooms[baseRoomIndex].AreaRange.x + splVector2Int + 1, this.Rooms[baseRoomIndex].AreaRange.y);
                newArea.size     = new Vector2Int(this.Rooms[baseRoomIndex].AreaRange.width - splVector2Int - 1, this.Rooms[baseRoomIndex].AreaRange.height);

                // 分割元の小部屋の再設定
                this.Rooms[baseRoomIndex] = new RoomData(new RectInt(
                                                             this.Rooms[baseRoomIndex].AreaRange.position,
                                                             new Vector2Int(splVector2Int - 1, this.Rooms[baseRoomIndex].AreaRange.height)
                                                             ));
                break;
            }

            // 分割して新しくできた小部屋を追加する
            this.Rooms.Add(new RoomData(newArea));

            // 分割線を追加する
            this.Links.Add(newLink);

            // 分割線の部分を暫定的に床にする
            switch (newLink.SplitType)
            {
            case RoomLink.SplitDirection.Horizontal:
                for (int x = newLink.Start.x; x <= newLink.End.x; x++)
                {
                    this.TileData[x, newLink.Start.y] = GeneratedMapTile.Aisle;
                }
                break;

            case RoomLink.SplitDirection.Vertical:
                for (int y = newLink.Start.y; y <= newLink.End.y; y++)
                {
                    this.TileData[newLink.Start.x, y] = GeneratedMapTile.Aisle;
                }
                break;
            }
            return(true);
        }
Пример #2
0
        /// <summary>
        /// 指定した進行方向で通路を削ります。
        /// </summary>
        /// <param name="link">対象とする通路</param>
        /// <param name="trimDirection">削っていく方向 (東向きの場合は左端が削られます)</param>
        public void TrimLink(RoomLink link, Direction trimDirection)
        {
            // 始点・終点・固定軸を決定する
            int start = 0;
            int end   = 0;
            int pivot = 0;
            int step  = 0;

            switch (trimDirection)
            {
            case Direction.Right:
                start = link.Start.x;
                end   = link.End.x;
                pivot = link.Start.x;
                step  = 1;
                break;

            case Direction.Left:
                start = link.End.x;
                end   = link.Start.x;
                pivot = link.Start.y;
                step  = -1;
                break;

            case Direction.Bottom:
                start = link.Start.y;
                end   = link.End.y;
                pivot = link.Start.x;
                step  = 1;
                break;

            case Direction.Top:
                start = link.End.y;
                end   = link.Start.y;
                pivot = link.Start.x;
                step  = -1;
                break;
            }

            // 逐次削っていく
            for (int p = start; (0 < step) ? (start <= p && p <= end) : (end <= p && p <= start); p += step)
            {
                bool cutFlag = true;

                // 次のタイル位置をセットする
                Vector2Int checkTilePos = Vector2Int.zero;
                switch (trimDirection)
                {
                case Direction.Right:
                case Direction.Left:
                    checkTilePos = new Vector2Int(p, pivot);
                    break;

                case Direction.Bottom:
                case Direction.Top:
                    checkTilePos = new Vector2Int(pivot, p);
                    break;
                }

                // 3方向チェック
                for (int d = 0; d < RoomData.DirectionCount; d++)
                {
                    if (d == (int)trimDirection)
                    {
                        // 進行方向はチェックしない
                        continue;
                    }

                    Vector2Int checkTileNextPos = this.GetNextDirectionPosition(checkTilePos, (GeneratedMapBase.Direction)d);
                    if (this.TileData[checkTileNextPos.x, checkTileNextPos.y] == GeneratedMapTile.Floor ||
                        this.TileData[checkTileNextPos.x, checkTileNextPos.y] == GeneratedMapTile.Aisle)
                    {
                        cutFlag = false;
                        break;
                    }
                }
                if (cutFlag)
                {
                    // 現在のタイルを削る
                    this.TileData[checkTilePos.x, checkTilePos.y] = GeneratedMapTile.None;
                }
            }
        }
Пример #3
0
        /// <summary>
        /// このダンジョンのランダム生成を実行します。
        /// </summary>
        /// <param name="complexLevel">複雑度: 分割数に関与</param>
        /// <returns>正常に生成できたかどうか</returns>
        public bool DoGenerate(int complexLevel)
        {
            if (MapDataBySectionDivision.ComplexMaxLevel < complexLevel)
            {
                Debug.LogWarning($"複雑度は {MapDataBySectionDivision.ComplexMaxLevel} 以内で設定して下さい。");
                return(false);
            }

            // 何回分割するかを概算する
            int fy    = this.DungeonRect.width * this.DungeonRect.height;
            int count = 0;

            while (fy > RoomData.MinRoomWidth * RoomData.MinRoomHeight)
            {
                fy /= 2;
                count++;
            }

            // 1. 分割線を作る
            int splitCount = count * complexLevel / MapDataBySectionDivision.ComplexMaxLevel;
            int lastIndex  = 0;

            for (int n = 0; n < splitCount; n++)
            {
                if (this.RandomSplitArea(lastIndex, UnityEngine.Random.Range(MapDataBySectionDivision.MinSplitRate, MapDataBySectionDivision.MaxSplitRate)))
                {
                    // 分割に成功したら次の分割を試行する
                    lastIndex++;
                }
            }

            // 2. 分割してできた各小部屋について、分割線に向かう通路を生成する
            foreach (var room in this.Rooms)
            {
                // 小部屋内で通路の起点を作る
                room.LinkVector2Int = new Vector2Int(
                    room.RoomRange.x + UnityEngine.Random.Range(0, room.RoomRange.width),
                    room.RoomRange.y + UnityEngine.Random.Range(RoomData.WallHeight, room.RoomRange.height)
                    );

                // 起点から4方向に向かって分割線があるかどうかをチェックする: 範囲は分割線を含めた小部屋理論領域
                room.MaxGateCount = 0;
                var checkRange = new RectInt(
                    new Vector2Int(room.AreaRange.x - 1 /*境界線分*/, room.AreaRange.y - 1 /*境界線分*/),
                    new Vector2Int(room.AreaRange.width + 1 * 2 + 1 /*境界線分*/, room.AreaRange.height + 1 * 2 + 1 /*境界線分*/)
                    );
                for (int d = 0; d < (int)Direction.Count; d++)
                {
                    Vector2Int nextTile = room.LinkVector2Int;

                    while (true)
                    {
                        // 次の座標に進む
                        nextTile = this.GetNextDirectionPosition(nextTile, (Direction)d);
                        if (!checkRange.Contains(nextTile) || !this.DungeonRect.Contains(nextTile))
                        {
                            // 次の座標が範囲外になったら分割線がないと判断する
                            room.AllowLinks[d] = false;
                            break;
                        }
                        else if (this.TileData[nextTile.x, nextTile.y] == GeneratedMapTile.Aisle)
                        {
                            // 次の座標が通路になっている場合は分割線であると判断する
                            room.AllowLinks[d]       = true;
                            room.CrossVector2Ints[d] = nextTile;
                            room.MaxGateCount++;
                            break;
                        }
                    }
                }

                // 分割線に向かう通路をランダムに生成する
                room.GateCount = UnityEngine.Random.Range(1, room.MaxGateCount + 1);
                int generatedGateCount = 0;
                while (generatedGateCount < room.GateCount && room.GateCount <= room.MaxGateCount)
                {
                    // 方向をランダムに決定する
                    int dir = UnityEngine.Random.Range(0, (int)Direction.Count);
                    if (!room.AllowLinks[dir])
                    {
                        // その方向に分割線がなければやり直し
                        continue;
                    }
                    else if (room.LinkExists[dir])
                    {
                        // その方向の通路を既に作っていたらやり直し
                        continue;
                    }

                    // 分割線への接続本数を更新する
                    foreach (var link in this.Links)
                    {
                        if (link.Contains(room.CrossVector2Ints[dir]))
                        {
                            link.CrossCount++;
                            break;
                        }
                    }

                    // 通路生成: 起点から分割線との交点までをすべて床にする
                    generatedGateCount++;
                    room.LinkExists[dir] = true;
                    switch ((Direction)dir)
                    {
                    case Direction.Right:
                        for (int x = room.LinkVector2Int.x; x < room.CrossVector2Ints[dir].x; x++)
                        {
                            this.TileData[x, room.LinkVector2Int.y] = GeneratedMapTile.Aisle;
                        }

                        // 通路を追加
                        var linkRight = new RoomLink()
                        {
                            CrossCount   = 2,
                            Start        = new Vector2Int(room.LinkVector2Int.x, room.LinkVector2Int.y),
                            End          = new Vector2Int(room.CrossVector2Ints[dir].x + 1, room.LinkVector2Int.y),
                            SplitType    = RoomLink.SplitDirection.Vertical,
                            IsParentLink = false,
                        };
                        this.Links.Add(linkRight);
                        break;

                    case Direction.Left:
                        for (int x = room.LinkVector2Int.x; room.CrossVector2Ints[dir].x < x; x--)
                        {
                            this.TileData[x, room.LinkVector2Int.y] = GeneratedMapTile.Aisle;
                        }

                        // 通路を追加
                        var linkLeft = new RoomLink()
                        {
                            CrossCount   = 2,
                            Start        = new Vector2Int(room.CrossVector2Ints[dir].x, room.LinkVector2Int.y),
                            End          = new Vector2Int(room.LinkVector2Int.x, room.LinkVector2Int.y),
                            SplitType    = RoomLink.SplitDirection.Vertical,
                            IsParentLink = false,
                        };
                        this.Links.Add(linkLeft);
                        break;

                    case Direction.Bottom:
                        for (int y = room.LinkVector2Int.y; y < room.CrossVector2Ints[dir].y; y++)
                        {
                            this.TileData[room.LinkVector2Int.x, y] = GeneratedMapTile.Aisle;
                        }

                        // 通路を追加
                        var linkBottom = new RoomLink()
                        {
                            CrossCount   = 2,
                            Start        = new Vector2Int(room.LinkVector2Int.x, room.LinkVector2Int.y),
                            End          = new Vector2Int(room.LinkVector2Int.x, room.CrossVector2Ints[dir].y),
                            SplitType    = RoomLink.SplitDirection.Horizontal,
                            IsParentLink = false,
                        };
                        this.Links.Add(linkBottom);
                        break;

                    case Direction.Top:
                        for (int y = room.LinkVector2Int.y; room.CrossVector2Ints[dir].y < y; y--)
                        {
                            this.TileData[room.LinkVector2Int.x, y] = GeneratedMapTile.Aisle;
                        }

                        // 通路を追加
                        var linkTop = new RoomLink()
                        {
                            CrossCount   = 2,
                            Start        = new Vector2Int(room.LinkVector2Int.x, room.CrossVector2Ints[dir].y),
                            End          = new Vector2Int(room.LinkVector2Int.x, room.LinkVector2Int.y),
                            SplitType    = RoomLink.SplitDirection.Horizontal,
                            IsParentLink = false,
                        };
                        this.Links.Add(linkTop);
                        break;
                    }
                }
            }

            // 3. 分割線に正しく接続できているか調べる
            foreach (var link in this.Links)
            {
                if (link.CrossCount < 2)
                {
                    //if(link.CrossCount < 1) {
                    // 接続本数が2本未満だと、孤立した小部屋ができてしまうのでやり直し
                    this.Initialize(new Vector2Int(this.TileData.GetLength(0), this.TileData.GetLength(1)));
                    return(false);
                }
            }

            // 4. 分割線の両端を削る: 分割線の検証方向以外の方向に床がなければ逐次削っていく
            Debug.Log($"分割線: {this.Links.Count}");
            foreach (var link in this.Links)
            {
                switch (link.SplitType)
                {
                case RoomLink.SplitDirection.Horizontal:
                    // 上下分割: 横線
                    this.TrimLink(link, Direction.Right);
                    this.TrimLink(link, Direction.Left);
                    break;

                case RoomLink.SplitDirection.Vertical:
                    // 左右分割: 縦線
                    this.TrimLink(link, Direction.Bottom);
                    this.TrimLink(link, Direction.Top);
                    break;
                }
            }

            // 5. 各通路の上部を壁にする
            foreach (var link in this.Links)
            {
                switch (link.SplitType)
                {
                case RoomLink.SplitDirection.Horizontal:
                    // 横線は上部がすべて壁になる

                    for (int x = link.Start.x; x <= link.End.x; x++)
                    {
                        if (this.TileData[x, link.Start.y] != GeneratedMapTile.Aisle)
                        {
                            // 削られた通路部分は処理しない
                            continue;
                        }

                        // 壁にしようとしている部分が既に床にされていないか検証する
                        bool wallNG = false;
                        for (int n = 1; n <= RoomData.WallHeight; n++)
                        {
                            if (this.TileData[x, link.Start.y - n] == GeneratedMapTile.Floor ||
                                this.TileData[x, link.Start.y - n] == GeneratedMapTile.Aisle)
                            {
                                wallNG = true;
                                break;
                            }
                        }
                        if (wallNG)
                        {
                            // 既に床にされているときは塞がない
                            continue;
                        }

                        // 壁化実行
                        for (int n = 1; n <= RoomData.WallHeight; n++)
                        {
                            this.TileData[x, link.Start.y - n] = GeneratedMapTile.Wall;
                        }
                    }
                    break;

                case RoomLink.SplitDirection.Vertical:
                    // 縦線は一番上だけを壁にする

                    for (int y = link.Start.y; y <= link.End.y; y++)
                    {
                        if (this.TileData[link.Start.x, y] != GeneratedMapTile.Aisle)
                        {
                            // 削られた通路部分は処理しない
                            continue;
                        }

                        // 壁にしようとしている部分が既に床にされていないか検証する
                        bool wallNG = false;
                        for (int n = 1; n <= RoomData.WallHeight; n++)
                        {
                            if (this.TileData[link.Start.x, y - n] == GeneratedMapTile.Floor ||
                                this.TileData[link.Start.x, y - n] == GeneratedMapTile.Aisle)
                            {
                                wallNG = true;
                                break;
                            }
                        }
                        if (wallNG)
                        {
                            // 既に床にされているときは塞がない
                            break;
                        }

                        // 壁化実行
                        for (int n = 1; n <= RoomData.WallHeight; n++)
                        {
                            this.TileData[link.Start.x, y - n] = GeneratedMapTile.Wall;
                        }
                        break;
                    }
                    break;
                }
            }

            // 6. 各小部屋の床と壁を作る
            foreach (var room in this.Rooms)
            {
                // 6-1. 各小部屋内部の床と壁を作る
                for (int x = room.RoomRange.xMin; x < room.RoomRange.xMax; x++)
                {
                    for (int y = room.RoomRange.yMin, n = 0; y < room.RoomRange.yMax; y++, n++)
                    {
                        if (n < RoomData.WallHeight && (!room.LinkExists[(int)Direction.Top] || room.LinkVector2Int.x != x))
                        {
                            // 上2マスは壁にする: ただし通路は塞がない
                            this.TileData[x, y] = GeneratedMapTile.Wall;
                        }
                        else
                        {
                            this.TileData[x, y] = GeneratedMapTile.Floor;
                        }
                    }
                }

                // 6-2. 横線の通路に上部に壁を作る
                for (int d = 0; d < (int)Direction.Count; d++)
                {
                    if (!room.LinkExists[d])
                    {
                        // 通路がない場合は処理しない
                        continue;
                    }
                    switch ((Direction)d)
                    {
                    case Direction.Right:
                        for (int x = room.RoomRange.xMax; x <= room.AreaRange.xMax; x++)
                        {
                            for (int n = 1; n <= RoomData.WallHeight; n++)
                            {
                                this.TileData[x, room.LinkVector2Int.y - n] = GeneratedMapTile.Wall;
                            }
                        }
                        break;

                    case Direction.Left:
                        for (int x = room.AreaRange.xMin; x < room.RoomRange.xMin; x++)
                        {
                            for (int n = 1; n <= RoomData.WallHeight; n++)
                            {
                                this.TileData[x, room.LinkVector2Int.y - n] = GeneratedMapTile.Wall;
                            }
                        }
                        break;
                    }
                }
            }

            // 7. 各通路と各小部屋の外周に天井(=枠)を付ける
            // 小部屋の外周に天井を付ける
            foreach (var room in this.Rooms)
            {
                var rect = room.RoomRange;

                for (int x = rect.xMin - 1; x < rect.xMax + 1; x++)
                {
                    if (0 <= x && 0 <= rect.yMin - 1 && this.TileData[x, rect.yMin - 1] == GeneratedMapTile.None)
                    {
                        this.TileData[x, rect.yMin - 1] = GeneratedMapTile.Ceil;
                    }
                    if (0 <= x && rect.yMax < this.DungeonRect.height && this.TileData[x, rect.yMax] == GeneratedMapTile.None)
                    {
                        this.TileData[x, rect.yMax] = GeneratedMapTile.Ceil;
                    }
                }
                for (int y = rect.yMin - 1; y < rect.yMax + 1; y++)
                {
                    if (0 <= y && 0 <= rect.xMin - 1 && this.TileData[rect.xMin - 1, y] == GeneratedMapTile.None)
                    {
                        this.TileData[rect.xMin - 1, y] = GeneratedMapTile.Ceil;
                    }
                    if (0 <= y && rect.xMax < this.DungeonRect.width && this.TileData[rect.xMax, y] == GeneratedMapTile.None)
                    {
                        this.TileData[rect.xMax, y] = GeneratedMapTile.Ceil;
                    }
                }
            }
            // 通路の外周に天井を付ける
            foreach (var link in this.Links)
            {
                RectInt rect;
                int     baseX = -1;
                int     baseY = -1;

                if (link.IsParentLink)
                {
                    if (link.SplitType == RoomLink.SplitDirection.Horizontal)
                    {
                        baseY = link.Start.y;
                        rect  = new RectInt(
                            link.Start.x,
                            baseY - RoomData.WallHeight,
                            link.End.x - link.Start.x,
                            1 + RoomData.WallHeight
                            );

                        int maxX = rect.xMax;
                        int maxY = rect.yMax;
                        for (int x = rect.xMin - 1; x < rect.xMax + 1; x++)
                        {
                            bool isBreak = false;
                            if (0 < x && this.TileData[x, baseY] == GeneratedMapTile.None)
                            {
                                maxX    = x;
                                isBreak = true;
                            }

                            if (0 <= x && 0 <= rect.yMin - 1 && this.TileData[x, rect.yMin - 1] == GeneratedMapTile.None)
                            {
                                this.TileData[x, rect.yMin - 1] = GeneratedMapTile.Ceil;
                            }
                            if (0 <= x && rect.yMax < this.DungeonRect.height && this.TileData[x, rect.yMax] == GeneratedMapTile.None)
                            {
                                this.TileData[x, rect.yMax] = GeneratedMapTile.Ceil;
                            }

                            if (isBreak)
                            {
                                break;
                            }
                        }
                        for (int y = rect.yMin - 1; y < rect.yMax + 1; y++)
                        {
                            if (0 <= y && 0 <= rect.xMin - 1 && this.TileData[rect.xMin - 1, y] == GeneratedMapTile.None)
                            {
                                this.TileData[rect.xMin - 1, y] = GeneratedMapTile.Ceil;
                            }
                            if (0 <= y && maxX < this.DungeonRect.width && this.TileData[maxX, y] == GeneratedMapTile.None)
                            {
                                this.TileData[maxX, y] = GeneratedMapTile.Ceil;
                            }
                        }
                    }
                    else
                    {
                        baseX = link.Start.x;
                        rect  = new RectInt(
                            baseX,
                            link.Start.y,
                            link.End.x - link.Start.x + 1,
                            1 + link.End.y - link.Start.y
                            );

                        int maxX = rect.xMax;
                        int maxY = rect.yMax;
                        for (int y = rect.yMin - 1; y < rect.yMax + 1; y++)
                        {
                            bool isBreak = false;
                            if (0 < y && this.TileData[baseX, y] == GeneratedMapTile.None)
                            {
                                maxY    = y;
                                isBreak = true;
                            }

                            if (0 <= y && 0 <= rect.xMin - 1 && this.TileData[rect.xMin - 1, y] == GeneratedMapTile.None)
                            {
                                this.TileData[rect.xMin - 1, y] = GeneratedMapTile.Ceil;
                            }
                            if (0 <= y && maxX < this.DungeonRect.width && this.TileData[maxX, y] == GeneratedMapTile.None)
                            {
                                this.TileData[maxX, y] = GeneratedMapTile.Ceil;
                            }

                            if (isBreak)
                            {
                                break;
                            }
                        }
                        for (int x = rect.xMin - 1; x < rect.xMax + 1; x++)
                        {
                            if (0 <= x && 0 <= rect.yMin - 1 && this.TileData[x, rect.yMin - 1] == GeneratedMapTile.None)
                            {
                                this.TileData[x, rect.yMin - 1] = GeneratedMapTile.Ceil;
                            }
                            if (0 <= x && rect.yMax < this.DungeonRect.height && this.TileData[x, rect.yMax] == GeneratedMapTile.None)
                            {
                                this.TileData[x, maxY] = GeneratedMapTile.Ceil;
                            }
                        }
                    }
                }
                else
                {
                    if (link.SplitType == RoomLink.SplitDirection.Vertical)
                    {
                        baseY = link.Start.y;
                        rect  = new RectInt(
                            link.Start.x,
                            baseY - RoomData.WallHeight,
                            link.End.x - link.Start.x,
                            1 + RoomData.WallHeight
                            );

                        int maxX = rect.xMax;
                        int maxY = rect.yMax;
                        for (int x = rect.xMin - 1; x < rect.xMax + 1; x++)
                        {
                            bool isBreak = false;
                            if (0 < x && this.TileData[x, baseY] == GeneratedMapTile.None)
                            {
                                maxX    = x;
                                isBreak = true;
                            }

                            if (0 <= x && 0 <= rect.yMin - 1 && this.TileData[x, rect.yMin - 1] == GeneratedMapTile.None)
                            {
                                this.TileData[x, rect.yMin - 1] = GeneratedMapTile.Ceil;
                            }
                            if (0 <= x && rect.yMax < this.DungeonRect.height && this.TileData[x, rect.yMax] == GeneratedMapTile.None)
                            {
                                this.TileData[x, rect.yMax] = GeneratedMapTile.Ceil;
                            }

                            if (isBreak)
                            {
                                break;
                            }
                        }
                        for (int y = rect.yMin - 1; y < rect.yMax + 1; y++)
                        {
                            if (0 <= y && 0 <= rect.xMin - 1 && this.TileData[rect.xMin - 1, y] == GeneratedMapTile.None)
                            {
                                this.TileData[rect.xMin - 1, y] = GeneratedMapTile.Ceil;
                            }
                            if (0 <= y && maxX < this.DungeonRect.width && this.TileData[maxX, y] == GeneratedMapTile.None)
                            {
                                this.TileData[maxX, y] = GeneratedMapTile.Ceil;
                            }
                        }
                    }
                    else
                    {
                        baseX = link.Start.x;
                        rect  = new RectInt(
                            baseX,
                            link.Start.y,
                            link.End.x - link.Start.x + 1,
                            1 + link.End.y - link.Start.y
                            );

                        int maxX = rect.xMax;
                        int maxY = rect.yMax;
                        for (int y = rect.yMin - 1; y < rect.yMax + 1; y++)
                        {
                            bool isBreak = false;
                            if (0 < y && this.TileData[baseX, y] == GeneratedMapTile.None)
                            {
                                maxY    = y;
                                isBreak = true;
                            }

                            if (0 <= y && 0 <= rect.xMin - 1 && this.TileData[rect.xMin - 1, y] == GeneratedMapTile.None)
                            {
                                this.TileData[rect.xMin - 1, y] = GeneratedMapTile.Ceil;
                            }
                            if (0 <= y && maxX < this.DungeonRect.width && this.TileData[maxX, y] == GeneratedMapTile.None)
                            {
                                this.TileData[maxX, y] = GeneratedMapTile.Ceil;
                            }

                            if (isBreak)
                            {
                                break;
                            }
                        }
                        for (int x = rect.xMin - 1; x < rect.xMax + 1; x++)
                        {
                            if (0 <= x && 0 <= rect.yMin - 1 && this.TileData[x, rect.yMin - 1] == GeneratedMapTile.None)
                            {
                                this.TileData[x, rect.yMin - 1] = GeneratedMapTile.Ceil;
                            }
                            if (0 <= x && rect.yMax < this.DungeonRect.height && this.TileData[x, rect.yMax] == GeneratedMapTile.None)
                            {
                                this.TileData[x, maxY] = GeneratedMapTile.Ceil;
                            }
                        }
                    }
                }
            }

            // 8. プレイヤー1を配置
            this.SetAutoPlayerPosition();

            // 9. ゴールを配置
            this.generateGoalLink();

            // 正常に生成された
            return(true);
        }