void PlaceShopRoom()
        {
            List <Type> pools = generateConfig.shopRoomPools;
            RoomNode    room  = null;

            HashSet <RoomType> avoidConnectTo = new HashSet <RoomType>()
            {
                RoomType.Init,
                RoomType.Reward,
                RoomType.Shop,
                RoomType.Boss,
            };

            for (int cnt = 0; cnt < generateConfig.shopRoomCount; ++cnt)
            {
                int rnd = UnityEngine.Random.Range(0, pools.Count);
                room          = (RoomNode)Activator.CreateInstance(pools[rnd]);
                room.roomType = RoomType.Shop;

                List <Grid> connectableGrids = GetConnectableGrids();
                for (int i = 0; i < connectableGrids.Count; ++i)
                {
                    var gridIndex = connectableGrids[i].index;
                    if (room.Place(gridIndex.x, gridIndex.y, this, true, avoidConnectTo))
                    {
                        ++curGenerateInfo.shopRoomCount;
                        usedGrid += room.gridList.Count;
                        roomList.Add(room);
                        room.SetPosition(room.gridList[0].position);
                        room.RepositionDoors();
                        room.CalculateTransportPos();
                    }

                    if (generateConfig.shopRoomCount <= curGenerateInfo.shopRoomCount)
                    {
                        break;
                    }
                }
            }

            if (generateConfig.shopRoomCount > curGenerateInfo.shopRoomCount)
            {
                Debug.LogError("Generate Shop Room less than " + generateConfig.shopRoomCount);
            }
        }
        int GenerateAt(int x, int y, int depth)
        {
            if (!IsValidIndex(x, y))
            {
                return(0);
            }

            if (usedGrid >= maxUseGrid)
            {
                return(0);
            }

            //if too deep
            if (depth > generateConfig.randomCutAtDeep && Random(1, depth) < generateConfig.cutParam)
            {
                return(1);
            }

            Grid grid = grids[x, y];

            if (grid.steped)
            {
                return(0);
            }
            grid.steped = true;

            if (grid.owner == null)
            {
                RoomGenerateInfo info = RandomFightRoom();
                if (info.ty != null)
                {
                    RoomNode room = (RoomNode)Activator.CreateInstance(info.ty);
                    room.roomType = info.roomType;
                    if (room.Place(x, y, this))
                    {
                        ++curGenerateInfo.normalRoomCount;
                        usedGrid += room.gridList.Count;
                        roomList.Add(room);
                        room.SetPosition(room.gridList[0].position);
                        room.RepositionDoors();
                        room.CalculateTransportPos();
                    }
                }
            }

            //4 direction
            var dirOffset = GenDirList();

            if (1 == GenerateAt(x + dirOffset[0].x, y + dirOffset[0].y, depth + 1))
            {
                return(1);
            }
            if (1 == GenerateAt(x + dirOffset[1].x, y + dirOffset[1].y, depth + 1))
            {
                return(1);
            }
            if (1 == GenerateAt(x + dirOffset[2].x, y + dirOffset[2].y, depth + 1))
            {
                return(1);
            }
            if (1 == GenerateAt(x + dirOffset[3].x, y + dirOffset[3].y, depth + 1))
            {
                return(1);
            }

            return(0);
        }