void GenerateBranch(out int length, out AP_Room lastRoom)
    {                   // out above used to return length and lastRoom of branch to GenerateBranchPaths() for making connections at the end
        int branchLength = Random.Range(mBranchLength.minimum, mBranchLength.maximum + 1);

        length   = 0;
        lastRoom = null;
        for (int i = 0; i < branchLength; i++)
        {
            length++;
            AP_Room newBranchRoom = ExpandRoom();
            newBranchRoom.SetRoomType(AP_Room.RoomType.branch);
            if (i < branchLength - 1)
            {
                if (!ExpandBranchDoors(newBranchRoom))
                {
                    lastRoom = newBranchRoom;
                    break;
                }
            }
            else
            {
                lastRoom = newBranchRoom;
            }
        }
    }
    void GenerateDungeon()
    {
        int dungeonSpan = Random.Range(mMainPath.minimum, mMainPath.maximum + 1);
        int minDist     = Mathf.CeilToInt(minMainPathPortion * dungeonSpan);
        int countToMid  = Random.Range(minDist, dungeonSpan - minDist);
        int countToEnd  = dungeonSpan - countToMid;

        AP_Room startRoom = CreateRoom(Vector2.zero);                       //create starting room, add it to dungeon rooms list

        startRoom.SetRoomType(AP_Room.RoomType.start);
        ExpandMainPathDoors(startRoom);                                                         // add doors to start room, then call expand making sure rooms only expand 'away' from start room

        for (int i = 0; i < countToMid; i++)                                                    // builds path between start room and mid room
        {
            AP_Room newRoom = ExpandRoom();
            newRoom.SetRoomType(AP_Room.RoomType.mainPath);
            if (i != countToMid - 1)                                                                            // I only main path to continue expanding until the next room is the middle room
            {
                ExpandMainPathDoors(newRoom);
            }
        }

        BuildBigRoom(false);                                                // passing false tells method this is the middle room

        for (int i = 0; i < countToEnd; i++)                                // expand main path from mid room to end room
        {
            AP_Room newRoom = ExpandRoom();
            newRoom.SetRoomType(AP_Room.RoomType.mainPath);
            if (i != countToEnd - 1)                                                                            // no more main path when the  next room is the end room
            {
                ExpandMainPathDoors(newRoom);
            }
        }

        BuildBigRoom(true);                                                                                             // passing true tells method this is the end room

        GenerateBranchPaths();

        // go through dungeon rooms to % change merge some together.
        // go through mainPath and branch room types for change to convert them to trap rooms
    }
    void GenerateBranchPaths()
    {
        ShuffleDoors();
        List <AP_Room> branchEndRooms = new List <AP_Room> ();
        List <int>     branchLengths  = new List <int> ();
        int            branchCount    = Random.Range(mBranches.minimum, mBranches.maximum + 1);                                 // get random number of branches to be created

        //		print ("Branch Count = " + branchCount);
        for (int i = 0; i < branchCount; i++)
        {
            if (ExpandingDoors.Count == 0)                                                                                                                              // can't branch if there are no available doors
            {
                break;
            }
            Vector2 pos = ExpandingDoors [0].newPos;                                                                                                            // get proposed new room position
            if (isSpaceAvailable(pos))
            {
                int     length;
                AP_Room lastRoom;
                GenerateBranch(out length, out lastRoom);                                                                                                       // generate branch starting from that door
                if (length > 0)
                {
                    branchEndRooms.Add(lastRoom);
                    branchLengths.Add(length);
                }
            }
            else
            {
                ExpandingDoors.RemoveAt(0);                                                                                                                                     // remove bad door and decrement i so branch count is preserved
                i--;
            }
        }
        // for each room in branchEndRooms
        for (int i = 0; i < branchEndRooms.Count; i++)
        {               // turn the last room in long branches into treasure rooms
            if (branchLengths[i] > (mBranchLength.minimum + mBranchLength.maximum) / 2)
            {
                AP_Room r = branchEndRooms [i];
                r.SetRoomType(AP_Room.RoomType.treasure);
            }
        }

        /*for(int i = 0; i < branchEndRooms.Count; i++)
         * {
         *      AP_Room r = branchEndRooms [i];
         *      // check to see if end room can connect to another room and isn't already connected to more than one other room
         *      // connect it to another room if possible
         *      Vector2[] dirs = GetRandomDirections();
         *      int connectionsMade = 0;
         *      for(int j = 0; j < 4; j++)
         *      {
         *              if (!r.IsRoomConnectedInDir(dirs[j])
         *                      && !isSpaceAvailable (r.GetUnitPos () + dirs [j])
         *                      && GetRoomAtPos (r.GetUnitPos () + dirs [j]).GetRoomType () != AP_Room.RoomType.end)
         *              {
         *                      //					print ("Connect rooms");
         *                      //r.ConnectRoom (GetRoomAtPos (r.GetUnitPos () + dirs[j]));
         *                      connectionsMade++;
         *              }
         *
         *      }
         *      if (connectionsMade == 0 && branchLengths[i] > (mBranchLength.minimum + mBranchLength.maximum) /2) // if no connection was made on last room and length is greater than a certain value
         *              // % chance to change room into treasure room
         *      {
         *              //				print ("TREASURE ROOM MADE AT INDEX" + DungeonRooms.IndexOf(r));
         *              r.SetRoomType(AP_Room.RoomType.treasure);
         *      }
         *
         * }*/
    }
    void BuildBigRoom(bool isEndRoom)
    {
        Vector2 origin = DungeonRooms[DungeonRooms.Count - 1].GetUnitPos();             // get unit position of last room in dungeon room list to know the previous room to big room

        Vector2[] dirs             = GetRandomDirections();
        Vector2[] sectionOffsets   = { Vector2.zero, Vector2.right, new Vector2(1, 1), Vector2.up };    // offsets of four rooms composing the big room with 0,0 as the bottom left room section
        Vector2[] sectionPositions = new Vector2[4];
        bool      isValid          = true;
        int       curDirIndex      = 0;
        int       offset           = 0;                     // stores random offset of big room from origin room

        offset = (Random.value > 0.5) ? 0 : -1;             // for now as big rooms are 2x2, either no offset, or -1 offset are possible
        int attempts = 0;                                   // used to track attempt iterations to place big room, to use both possible offsets

        do
        {
            isValid = true;
            Vector2 curDir = dirs[curDirIndex];

            if (dirs[curDirIndex] == mNorth)
            {
                sectionPositions[0] = origin + curDir + new Vector2(offset, 0);
            }
            else if (dirs[curDirIndex] == mEast)
            {
                sectionPositions[0] = origin + curDir + new Vector2(0, offset);
            }
            else if (dirs[curDirIndex] == mSouth)
            {
                sectionPositions[0] = origin + curDir + new Vector2(offset, -1);
            }
            else             // dir[curDirIndex] must equal mWest
            {
                sectionPositions[0] = origin + curDir + new Vector2(-1, offset);
            }
            for (int i = 1; i < 4; i++)                                                     // using 0,0 as bottom left, setup other section positions
            {
                sectionPositions[i] = sectionPositions[0] + sectionOffsets[i];
            }
            // iterate through vector2 array. if all positions are free space, continue
            for (int r = 0; r < 4; r++)
            {
                if (!isSpaceAvailable(sectionPositions[r]))
                {
                    isValid = false;
                    curDirIndex++;
                    if (attempts == 0)                                                              // swap the offset and try again
                    {
                        curDirIndex = 0;
                        attempts    = 1;
                        offset      = (offset == 0) ? -1 : 0;
                    }
                }
            }
        } while (!isValid && curDirIndex < 4);                                           // repeat trying different positioning of big room until valid position is found

        if (curDirIndex > 3)                                                             //reload level if big room fails to generate in current conditions
        {
            SceneManager.LoadScene(SceneManager.GetActiveScene().name);

            //            Application.LoadLevel(Application.loadedLevelName);
            print("RELOAD LEVEL " + ((isEndRoom) ? "END ROOM" : "MID ROOM") + " FAILED");
//			do {
//			} while(Application.isLoadingLevel);

            return;             // return from this function so no other lines in this function run, this should theoretically be unnecessary?
        }

        for (int i = 0; i < 4; i++)                                                 // iterate through array again, generating a room at each chosen unit position
        {
            AP_Room r = CreateRoom(sectionPositions[i]);
            r.SetRoomType(((isEndRoom) ? AP_Room.RoomType.end : AP_Room.RoomType.mid));
            // consider expanding rooms of big room using add door to end, to enable potential branching from big room
        }
        // merge the four created rooms

        AP_Room[] otherRooms = new AP_Room[3];
        for (int i = 0; i < 3; i++)
        {
            otherRooms [i] = GetRoomAtPos(sectionPositions [i + 1]);
        }
        GetRoomAtPos(sectionPositions [0]).MergeRoom(otherRooms);
        //GetRoomAtPos (sectionPositions [0]).MergeRoom (	GetRoomAtPos (sectionPositions [1]),
        //												GetRoomAtPos (sectionPositions [2]),
        //												GetRoomAtPos (sectionPositions [3]));

        /*GetRoomAtPos(sectionPositions[0]).MergeRoom(GetRoomAtPos(sectionPositions[1]));
         * GetRoomAtPos(sectionPositions[0]).MergeRoom(GetRoomAtPos(sectionPositions[3]));
         * GetRoomAtPos(sectionPositions[2]).MergeRoom(GetRoomAtPos(sectionPositions[1]));
         * GetRoomAtPos(sectionPositions[2]).MergeRoom(GetRoomAtPos(sectionPositions[3]));
         */
        AP_Room entryRoom   = GetRoomAtPos(origin);
        AP_Room midRoomNode = GetRoomAtPos(origin + dirs[curDirIndex]);

        entryRoom.ConnectRoom(midRoomNode);                                                                             // connect this big room with the last main path room generated

        if (!isEndRoom)
        {
            // choose a valid direction and room for the main path to continue on from
            int entryDoor = 0;
            int exitDoor  = 0;
            for (int i = 0; i < 4; i++)
            {
                if (Vector2.Distance(origin, sectionPositions[i]) == 1)
                {
                    entryDoor = i;
                }
            }
            exitDoor = (entryDoor + 2 > 3) ? (entryDoor + 1) % 3 : entryDoor + 2;
            //            print("entry door = " + entryDoor + "   exit door = " + exitDoor);
            for (int i = 0; i < 4; i++)
            {
                if (i != exitDoor)
                {
                    ExpandMainPathDoors(GetRoomAtPos(sectionPositions[i]));
                }
            }
            ExpandMainPathDoors(GetRoomAtPos(sectionPositions[exitDoor]));
        }
    }