void AddNextRoomNode(IsaacRoomFactory roomFactory,
                             Queue <LevelGrowthNode> queue, HashSet <IntVector> visited, int maxRooms,
                             IsaacRoom parentRoom, int direction, float probability)
        {
            if (random.NextFloat() > probability)
            {
                return;
            }
            if (rooms.Count >= maxRooms)
            {
                return;
            }

            var nextPosition = parentRoom.position + directions[direction];

            if (!visited.Contains(nextPosition))
            {
                var nextRoom = roomFactory.CreateRoom(nextPosition);
                rooms.Add(nextRoom);
                var nextNode = new LevelGrowthNode();
                nextNode.room          = nextRoom;
                nextNode.moveDirection = direction;
                queue.Enqueue(nextNode);
                visited.Add(nextPosition);

                // Create a door between the two rooms
                ConnectRoomsWithDoors(parentRoom, nextRoom);
            }
            else
            {
                // See if we can connect to the other room
                // first make sure we don't already have a connection between the two
                var nextRoom = GetRoomAt(nextPosition);
                if (!ContainsDoorBetween(parentRoom.roomId, nextRoom.roomId))
                {
                    float loopTest = random.NextFloat();
                    if (loopTest < isaacConfig.cycleProbability)
                    {
                        // Connect the two rooms together
                        if (nextRoom != null)
                        {
                            // Create a door between the two rooms
                            ConnectRoomsWithDoors(parentRoom, nextRoom);
                        }
                    }
                }
            }
        }
        void GenerateLevelLayout()
        {
            var queue   = new Queue <LevelGrowthNode>();
            var visited = new HashSet <IntVector>();

            var roomFactory = new IsaacRoomFactory();

            rooms.Clear();
            doors.Clear();

            var start = new LevelGrowthNode();

            start.room          = roomFactory.CreateRoom(IntVector.Zero);
            start.moveDirection = 0;
            rooms.Add(start.room);

            queue.Enqueue(start);
            visited.Add(start.room.position);

            var  numRooms    = random.Range(isaacConfig.minRooms, isaacConfig.maxRooms);
            bool isSpawnRoom = true;

            while (queue.Count > 0)
            {
                var top = queue.Dequeue();
                if (isSpawnRoom)
                {
                    // in the spawn room.  Spawn on all 4 sides
                    for (int d = 0; d < 4; d++)
                    {
                        AddNextRoomNode(roomFactory, queue, visited, numRooms, top.room, d, isaacConfig.spawnRoomBranchProbablity);
                    }
                    isSpawnRoom = false;
                }
                else
                {
                    // Grow forward
                    AddNextRoomNode(roomFactory, queue, visited, numRooms, top.room, top.moveDirection, isaacConfig.growForwardProbablity);

                    // Grow sideways
                    AddNextRoomNode(roomFactory, queue, visited, numRooms, top.room, (top.moveDirection + 1) % 4, isaacConfig.growSidewaysProbablity);
                    AddNextRoomNode(roomFactory, queue, visited, numRooms, top.room, (top.moveDirection + 3) % 4, isaacConfig.growSidewaysProbablity);
                }

                if (rooms.Count >= numRooms)
                {
                    break;
                }
            }

            // Generate the tile layout of the rooms
            var layoutBuilder = GetComponent <IsaacRoomLayoutBuilder>();

            foreach (var room in rooms)
            {
                GenerateRoomLayout(layoutBuilder, room);
            }

            isaacModel.rooms = rooms.ToArray();
            isaacModel.doors = doors.ToArray();
            rooms.Clear();
            doors.Clear();
        }