////////////////////////////////////////////////////////////////////////////////
// rd_ex_setup - Setup the Random Dungeons
// By Deva B. Winblood.   November 15th,  2008
////////////////////////////////////////////////////////////////////////////////

void fnCount(object oAreaWP)
{ // PURPOSE: Count Area Waypoints
    int nN=1;
    object oWP=GetNearestObjectByTag("RD_EXIT",oAreaWP,nN);
    while(GetIsObjectValid(oWP))
    { // count
        nN++;
        oWP=GetNearestObjectByTag("RD_EXIT",oAreaWP,nN);
    } // count
    SetLocalInt(oAreaWP,"nExitCount",nN-1);
} // fnCount()


object fnFindAnExit(object oAreaWP)
{ // PURPOSE: Find an exit
    int nCount=GetLocalInt(oAreaWP,"nExitCount");
    int nN=Random(nCount)+1;
    int nStart=nN;
    object oWP=GetNearestObjectByTag("RD_EXIT",oAreaWP,nN);
    while(GetIsObjectValid(GetLocalObject(oWP,"oDest")))
    { // keep looking
        nN++;
        if (nN>nCount) nN=1;
        if (nN==nStart) return OBJECT_INVALID;
        oWP=GetNearestObjectByTag("RD_EXIT",oAreaWP,nN);
    } // keep looking
    return oWP;
} // fnFindAnExit()


void fnDoorCount(object oArea)
{ // PURPOSE: Count the number of doors
    int nCount=0;
    int nN=1;
    object oOb=GetNearestObjectByTag("door_rd",oArea,nN);
    while (GetIsObjectValid(oOb))
    { // count doors
        nCount++;
        nN++;
        oOb=GetNearestObjectByTag("door_rd",oArea,nN);
    } // count doors
    oOb=GetNearestObjectByTag("rope_rd",oArea,1);
    if (GetIsObjectValid(oOb)) nCount++;
    SetLocalInt(oArea,"nDoorCount",nCount);
} // fnDoorCount()


void fnLinkAreas(int nSource,int nDestination)
{ // PURPOSE: Create a door between the areas
    int nDest=nDestination;
    object oSourceArea=GetWaypointByTag("AREA_RD"+IntToString(nSource));
    object oDestArea=GetWaypointByTag("AREA_RD"+IntToString(nDest));
    object oSourceExit=fnFindAnExit(oSourceArea);
    object oDestExit=fnFindAnExit(oDestArea);
    while(!GetIsObjectValid(oDestExit))
    { // find a different area
        nDest=nDest+1;
        if (nDest>10) nDest=1;
        oDestArea=GetWaypointByTag("AREA_RD"+IntToString(nDest));
        oDestExit=fnFindAnExit(oDestArea);
    } // find a different area
    object oSource=CreateObject(OBJECT_TYPE_PLACEABLE,"door_rd",GetLocation(oSourceExit));
    object oDest=CreateObject(OBJECT_TYPE_PLACEABLE,"door_rd",GetLocation(oDestExit));
    SetLocalObject(oSource,"oDest",oDest);
    SetLocalObject(oSourceExit,"oDest",oDest);
    SetLocalObject(oDest,"oDest",oSource);
    SetLocalObject(oDestExit,"oDest",oSource);
    int nDC=GetLocalInt(oDestArea,"nDoorCount");
    if (nDC==0)
    { // count
        fnDoorCount(oDestArea);
        nDC=GetLocalInt(oDestArea,"nDoorCount");
    } // count
    else { SetLocalInt(oDestArea,"nDoorCount",nDC+1); }
} // fnLinkAreas()


void fnProcessArea(int nArea)
{ // PURPOSE: Create Random door links from area
    object oArea=GetWaypointByTag("AREA_RD"+IntToString(nArea));
    int nCount=GetLocalInt(oArea,"nExitCount");
    int nDoorCount=GetLocalInt(oArea,"nDoorCount");
    if (nCount<1) { fnCount(oArea); nCount=GetLocalInt(oArea,"nExitCount"); }
    if (nDoorCount<1) { fnDoorCount(oArea); nDoorCount=GetLocalInt(oArea,"nDoorCount"); }
    if (nDoorCount<nCount)
    { // can create doors
        int nCreate=d2();
        if (nCreate+nDoorCount>nCount) nCreate=1;
        int nDest=d10();
        while (nCreate>0)
        { // link
            while (nDest==nArea) { nDest=d10(); }
            fnLinkAreas(nArea,nDest);
            nDoorCount++;
            SetLocalInt(oArea,"nDoorCount",nDoorCount);
            nCreate=nCreate-1;
        } // link
    } // can create doors
    if (nArea<10) DelayCommand(1.0,fnProcessArea(nArea+1));
} // fnProcessArea()



//////////////////////////////////////////////////////////////////[ MAIN ]//////
void main()
{
   object oArea;
   object oWP;
   object oDoor;
   object oDest;
   int nN;
   int nType;
   int nCount;
   object oChasm;
   object oCatacomb;
   object oMod=GetModule();
   // place chasm entrance
   nCount=0;
   nN=0;
   oWP=GetObjectByTag("RD_ENTRANCEC",nN);
   while(GetIsObjectValid(oWP))
   { // count chasm door spawn locations
       nCount++;
       nN++;
       oWP=GetObjectByTag("RD_ENTRANCEC",nN);
   } // count chasm door spawn locations
   nN=Random(nCount);
   oWP=GetObjectByTag("RD_ENTRANCEC",nN);
   oChasm=CreateObject(OBJECT_TYPE_PLACEABLE,"door_chasm",GetLocation(oWP));
   nN=d10();
   oArea=GetWaypointByTag("AREA_RD"+IntToString(nN));
   fnCount(oArea);
   oWP=fnFindAnExit(oArea);
   oDoor=CreateObject(OBJECT_TYPE_PLACEABLE,"door_rd",GetLocation(oWP));
   SetLocalObject(oDoor,"oDest",oChasm);
   SetLocalObject(oChasm,"oDest",oDoor);
   SetLocalObject(oWP,"oDest",oChasm);
   // place catacombs entrance
   nCount=0;
   nN=0;
   oWP=GetObjectByTag("RD_ENTRANCECAT",nN);
   while(GetIsObjectValid(oWP))
   { // count catacomb door spawn locations
       nCount++;
       nN++;
       oWP=GetObjectByTag("RD_ENTRANCECAT",nN);
   } // count catacomb door spawn locations
   nN=Random(nCount);
   oWP=GetObjectByTag("RD_ENTRANCECAT",nN);
   oCatacomb=CreateObject(OBJECT_TYPE_PLACEABLE,"door_cata",GetLocation(oWP));
   nN=d10();
   oArea=GetWaypointByTag("AREA_RD"+IntToString(nN));
   fnCount(oArea);
   while(GetArea(oArea)==GetArea(GetLocalObject(oChasm,"oDest")))
   { // chasm and catacomb doors should lead to different areas
       nN=d10();
       oArea=GetWaypointByTag("AREA_RD"+IntToString(nN));
       fnCount(oArea);
   } // chasm and catacomb doors should lead to different areas
   oWP=fnFindAnExit(oArea);
   oDoor=CreateObject(OBJECT_TYPE_PLACEABLE,"rope_rd",GetLocation(oWP));
   SetLocalObject(oDoor,"oDest",oCatacomb);
   SetLocalObject(oCatacomb,"oDest",oDoor);
   SetLocalObject(oWP,"oDest",oCatacomb);
   DelayCommand(1.0,fnProcessArea(1));
}
//////////////////////////////////////////////////////////////////[ MAIN ]//////