//---------------------------------------------------------------------------
#include "BBETest.h"

//---------------------------------------------------------------------------
char *GetStrDescr(ID idStrDef)
{
    StrategyDefNodeP pStrDef = GetStrategyNode(idStrDef);
    return (pStrDef == NULL ? "" : pStrDef->Name);
}

//---------------------------------------------------------------------------
int GetCharIndex(ID attId,Agent *AgArr,int nPopSize)
{
    int i;
    if(AgArr == NULL)
        return -1;
    for(i = 0; i < nPopSize; i++)
    {
        if(AgArr[i].GetCore().attId == attId)
            return i;
    }
    return -1;//nothing found
}

//---------------------------------------------------------------------------
int BBECALL DefaultFn(MyStruct *mpParam)
{
   if(mpParam == NULL)
      cout << "Executing an action... can't say more:-)\n";
   else
      cout << "\nAgent #" << mpParam->CharIndex
            << " executed "
            << mpParam->szAction << " on agent #"
            << GetCharIndex(mpParam->pCurrAction->GetObjective()->attId,
                mpParam->AgArr,mpParam->nPopSize) << "\n";
   return 1;
}

//---------------------------------------------------------------------------
char *GetActionDesc(Action *pAct)
{
   ActionDefNodeP adnp;
   if(pAct == NULL)
      return "";
   adnp = GetActionNode(pAct->GetID());
   if(adnp == NULL)
      return "";
   return adnp->Verb;
}

//---------------------------------------------------------------------------
//one character should attack another one
void SituationAttack()
{
   BOOL done,bRetVal = InitActionLib((int(BBECALL*)(void*))(DefaultFn));
   if(!bRetVal)
   {
      cout << "\nFailed to load Brainiac data files\n";
      return;
   }

   int i,j,nPopulationSize = 2;
   Agent *pAgent;
   MyStruct ActParam;
   pAgent = new Agent[nPopulationSize];

   cout << "\nSituation: attack\n";
   pAgent[0].Init(0,-75);//lawful neutral
   pAgent[0].SetImpression(9,9,9,9,0);
   pAgent[0].SetSolidScores(9,9);
   pAgent[1].Init(75,75);//chaotic evil
   pAgent[1].SetImpression(17,9,9,9,0);
   pAgent[1].SetSolidScores(9,9);
   //now set hostile attitude to agent[0]
   pAgent[1].SetAttitudeTo(pAgent[0].GetCore().attId,-90);
   for(i = 0; i < nPopulationSize; i++)
      for(j = 0; j < nPopulationSize; j++)
         if(pAgent[i].Scan(pAgent+j,NULL,0))
         {
            cout << "\nAgent #" << i << " plans " <<
                GetStrDescr(pAgent[i].CurrentStrategy.GetID()) << "...";
            break;
         }

   done = FALSE;
   do{
      for(i = 0; i < nPopulationSize; i++)
      {
         ActParam.CharIndex = i;
         ActParam.pCurrAction
            = pAgent[i].CurrentStrategy.GetNextAction();
         strcpy(ActParam.szAction,
            GetActionDesc(pAgent[i].CurrentStrategy.GetNextAction()));
         ActParam.AgArr = pAgent;
         ActParam.nPopSize = nPopulationSize;
         pAgent[i].ExecuteNextAction(&ActParam,NULL,
            (unsigned short)nPopulationSize);
      }
      cout << "Press Escape to exit, other key to continue...\n";
      cout.flush();
      if(getch() == ESC)
         done = TRUE;
   }while(!done);

   delete []pAgent;
   FreeLibLists();
}
//---------------------------------------------------------------------------
//Partially depicts conspiracy situation. To implement it fully,
//you must write handler function for statement and request actions.
//See examples from debugger sources how you do it.
void SituationConspiracy()
{
   BOOL bRetVal = InitActionLib((int(BBECALL*)(void*))DefaultFn),done;
   if(!bRetVal)
   {
      cout << "\nFailed to load Brainiac data files\n";
      return;
   }

   unsigned short i,j,nPopulationSize = 4;
   Agent *pAgent,**pPopulation;
   MyStruct ActParam;
   pAgent = new Agent[nPopulationSize];
   pPopulation = new Agent*[nPopulationSize];

   cout << "\nSituation: conspiracy\n";
   pAgent[0].Init(0,-75);//lawful neutral
   pAgent[0].SetImpression(9,9,9,9,0);
   pAgent[0].SetSolidScores(9,9);
   pPopulation[0] = pAgent;

   pAgent[1].Init(30,30);//true neutral with slight chaotic evil tendencies...
   pAgent[1].SetImpression(17,9,9,9,0);//...also strong like a bull
   pAgent[1].SetSolidScores(9,9);
   pAgent[1].SetAttitudeTo(pAgent[0].GetCore().attId,90);//also loves No. 0
   pPopulation[1] = pAgent + 1;

   pAgent[2].Init(30,30);//true neutral with chaotic evil tendencies...
   pAgent[2].SetImpression(15,9,9,9,0);//...also strong, but not like a bull:-)
   pAgent[2].SetSolidScores(9,9);
   pPopulation[2] = pAgent + 2;

   pAgent[3].Init(20,20);//true neutral with chaotic evil tendencies
   pAgent[3].SetImpression(9,9,9,9,0);
   pAgent[3].SetSolidScores(9,9);
   //ah, one more detail: absolutely hates No. 2
   pAgent[3].SetAttitudeTo(pAgent[2].GetCore().attId,-90);
   pPopulation[3] = pAgent + 3;

   SetSoloAssumptionMode(FALSE);
   SetHistoryUse(TRUE);
   SetDynamicTACAssumptionPopulation(pPopulation,
        nPopulationSize,NULL,NULL);
   for(i = 0; i < nPopulationSize; i++)
      for(j = 0; j < nPopulationSize; j++)
         if(pAgent[i].Scan(pAgent+j,NULL,0))
         {
            cout << "\nAgent #" << i << " plans " <<
                GetStrDescr(pAgent[i].CurrentStrategy.GetID()) << "...";
            break;
         }

   done = FALSE;
   do{
      for(i = 0; i < nPopulationSize; i++)
      {
         ActParam.CharIndex = i;
         ActParam.pCurrAction
            = pAgent[i].CurrentStrategy.GetNextAction();
         strcpy(ActParam.szAction,
            GetActionDesc(pAgent[i].CurrentStrategy.GetNextAction()));
         ActParam.AgArr = pAgent;
         ActParam.nPopSize = nPopulationSize;
         pAgent[i].ExecuteNextAction(&ActParam,pPopulation,
            (unsigned short)nPopulationSize);
      }
      cout << "\nPress Escape to exit, other key to continue...\n";
      cout.flush();
      if(getch() == ESC)
         done = TRUE;
   }while(!done);

   FreeLibLists();
   delete []pAgent;
}

//---------------------------------------------------------------------------
void SituationAcquisition()
{
   BOOL bRetVal = InitActionLib((int(BBECALL*)(void*))DefaultFn),done;
   if(!bRetVal)
   {
      cout << "\nFailed to load Brainiac data files\n";
      return;
   }

   unsigned short i,j,nPopulationSize = 2,*nItemsPerAgent;
   Agent *pAgent,**pPopulation;
   ItemPtrArr *ipapAllInv;
   MyStruct ActParam;
   pAgent = new Agent[nPopulationSize];
   pPopulation = new Agent*[nPopulationSize];
   ipapAllInv = new ItemPtrArr [nPopulationSize];
   nItemsPerAgent = new unsigned short[nPopulationSize];

   cout << "\nSituation: item acquisition\n";
   pAgent[0].Init(0,0);
   pAgent[0].SetImpression(9,9,9,9,9);
   pAgent[0].SetSolidScores(9,9);
   pPopulation[0] = pAgent;
   nItemsPerAgent[0] = 1;
   ipapAllInv[0] = new ItemScores*[nItemsPerAgent[0]];
   ipapAllInv[0][0] = new ItemScores;
   memset(ipapAllInv[0][0],0,sizeof(ItemScores)*nItemsPerAgent[0]);
   ipapAllInv[0][0]->ItemID      = 1;
   ipapAllInv[0][0]->Owner       = pAgent[0].GetCore().attId;
   ipapAllInv[0][0]->Meanness    = 9;
   ipapAllInv[0][0]->Foreignness = 9;
   ipapAllInv[0][0]->Wealth      = 14;
   ipapAllInv[0][0]->Beauty      = 11;
   ipapAllInv[0][0]->Influence   = 70;

   pAgent[1].Init(0,-75);
   pAgent[1].SetImpression(9,9,9,9,9);
   pAgent[1].SetSolidScores(9,9);
   pPopulation[1] = pAgent + 1;
   nItemsPerAgent[1] = 1;
   ipapAllInv[1] = new ItemScores*[nItemsPerAgent[1]];
   ipapAllInv[1][0] = new ItemScores;
   memset(ipapAllInv[1][0],0,sizeof(ItemScores)*nItemsPerAgent[1]);
   ipapAllInv[1][0]->ItemID      = 1;
   ipapAllInv[1][0]->Owner       = pAgent[1].GetCore().attId;
   ipapAllInv[1][0]->Meanness    = 9;
   ipapAllInv[1][0]->Foreignness = 9;
   ipapAllInv[1][0]->Wealth      = 9;
   ipapAllInv[1][0]->Beauty      = 11;
   ipapAllInv[1][0]->Influence   = 70;
   SetSoloAssumptionMode(FALSE);
   SetHistoryUse(TRUE);

   for(i = 0; i < nPopulationSize; i++)
      for(j = 0; j < nPopulationSize; j++)
         if(pAgent[i].Scan(pAgent+j,ipapAllInv[j],nItemsPerAgent[j]))
         {
            cout << "\nAgent #" << i << " plans " <<
                GetStrDescr(pAgent[i].CurrentStrategy.GetID()) << "...";
            break;
         }

   done = FALSE;
   do{
      for(i = 0; i < nPopulationSize; i++)
      {
         ActParam.CharIndex = i;
         ActParam.pCurrAction
            = pAgent[i].CurrentStrategy.GetNextAction();
         strcpy(ActParam.szAction,
            GetActionDesc(pAgent[i].CurrentStrategy.GetNextAction()));
         ActParam.AgArr = pAgent;
         ActParam.nPopSize = nPopulationSize;
         pAgent[i].ExecuteNextAction(&ActParam,pPopulation,
            (unsigned short)nPopulationSize,
            ipapAllInv,nItemsPerAgent);
      }
      cout << "\nPress Escape to exit, other key to continue...\n";
      cout.flush();
      if(getch() == ESC)
         done = TRUE;
   }while(!done);


   FreeLibLists();
   //free space taken by inventory...
   for(i = 0; i < nPopulationSize; i++)
   {
        for(j = 0; j < nItemsPerAgent[i]; j++)
            delete ipapAllInv[i][j];
        delete []ipapAllInv[i];
   }
   delete []ipapAllInv;
   //...and agents
   delete []pAgent;
}

//---------------------------------------------------------------------------
int main()
{
    SituationAttack();
    SituationConspiracy();
    SituationAcquisition();
    cout << "Press any key to exit this application...\n";
    cout.flush();
    getch();
    return 0;
}

//---------------------------------------------------------------------------
