/* Autor: Leandro Bernsmuller
Reproduz o ser, cria um outro semelhante. */



#include <windows.h>
#include <windowsx.h>
#include <ddraw.h>
#include <d3drmwin.h>
#include "..\..\princip\defs.h"
#include "..\..\cenario\cenario.h"
#include "..\..\cenario\cenfis.h"
#include "acao.h"
#include "..\dados\dados.h"
#include "..\dados\dadosfis.h"
#include "..\agente.h"
#include "reproduz.h"



/* construtor
**********************************************************/
CReproduz::CReproduz ()
{
   m_dwTipoAcao = ID_ACAO_REPRODUZ;
}



/* Acao.
pDado1 - ignorado
pDado2 - numero de agentes que devem ser criados
return TRUE - certo / FALSE - erro (nao alocou objet-cenario cheio)
**********************************************************/
BOOL CReproduz::mAtiva ( PTRVAL pDado1, PTRVAL pDado2 )
{
   // converte parametros
   DWORD
      dwNumAgen = (DWORD) pDado2;

   // dados do agente que vai se reproduzir
   if ( m_poMeuAgente->m_poDados->m_dwTipoDado != TIPO_FISICO ) {
      MSGSTR ( "Nao eh tipo fisico (reproduz.cpp)." );
      return TRUE;
   }
   CDadosFisicos
      *poDados = (CDadosFisicos*) m_poMeuAgente->m_poDados;
   
   // verifica se nao existem muitos agentes do mesmo tipo

   // conta numero de agentes com mesmo corpo que o desse agente
   int
      nNumSemelhantes = 0;
   for ( int  ncA = 0; ncA < MAX_AGENTES; ncA ++ ) {

      // pega dados do agente
      CDados
         *poDadosAg = (CDados*) m_poMeuAgente->m_paoOsAgentes [ ncA ].m_poDados;

      // se nao tem informacoes fisicas, ignora ocorrencia
      if ( poDadosAg != NULL && poDadosAg->m_dwTipoDado == TIPO_FISICO ) {

         // tenta acessar dados fisicos
         CDadosFisicos
            *poDadosFisicosAg = (CDadosFisicos*) poDadosAg;

         // verifica se tem mesmo corpo
         if ( poDados->m_dwTipoCorpo == poDadosFisicosAg->m_dwTipoCorpo )
            // se sim conta como mais um
            nNumSemelhantes ++;
      }
   }

   // indica se conseguiu alocar um objeto
   BOOL
      bAchou = FALSE;

   // verifica se ainda pode ser alocado mais um agente, se sim aloca
   if ( nNumSemelhantes <= MAX_AGENTES_SEMELHANTES )

      // faz criacao de um agente
      for ( int ncN = 0; ncN < (int) dwNumAgen; ncN ++ )

         // acha um agente livre para alocar (nascivel)
         for ( int  ncA = 0; ncA < MAX_AGENTES; ncA ++ )

            // verifica se agente pode executar a acao de nascer
            if ( m_poMeuAgente->m_paoOsAgentes [ ncA ].m_apoAcoes [ NDX_EVENTO_NASCE ]->m_dwTipoAcao == ID_ACAO_NASCE ) {

               bAchou = TRUE;

               // coordenadas limitrofes do cenario
               float
                  fSup,
                  fInf,
                  fDir,
                  fEsq;
               m_poMeuAgente->m_poCenario->mRetLimiteJanVis ( fSup, fInf, fDir, fEsq ); 

               // coordenadas do agente
               float
                  afCoord [ 2 ];
               afCoord [ 2 ] = 0;

               // configuracao
               DWORD
                  adwAzul [] = CONFIG_AGENTE_PEIXE_AZUL,
                  adwList [] = CONFIG_AGENTE_PEIXE_LISTRADO,
                  adwGord [] = CONFIG_AGENTE_PEIXE_GORDO,
                  adwAlga [] = CONFIG_AGENTE_ALGA_VERDE,
                  adwMicr [] = CONFIG_AGENTE_MICROORGANISMO,
                  *padwUsar;

               // seleciona a configuracao correta
               switch ( poDados->m_dwTipoCorpo ) {

                  case NDX_MODELO_PEIXE_GORDO:
                     afCoord [ 0 ] = poDados->m_fLocalReproduzX + ( rand () % 20 ) - 10;
                     afCoord [ 1 ] = poDados->m_fLocalReproduzY + ( rand () % 20 ) - 10;
                     afCoord [ 2 ] = poDados->m_fLocalReproduzZ;
                     padwUsar = adwGord;
                     break;

                  case NDX_MODELO_PEIXE_AZUL:
                     afCoord [ 0 ] = poDados->m_fLocalReproduzX + ( rand () % 20 ) - 10;
                     afCoord [ 1 ] = poDados->m_fLocalReproduzY + ( rand () % 20 ) - 10;
                     afCoord [ 2 ] = poDados->m_fLocalReproduzZ;
                     padwUsar = adwAzul;
                     break;

                  case NDX_MODELO_PEIXE_LISTRADO:
                     afCoord [ 0 ] = poDados->m_fLocalReproduzX + ( rand () % 20 ) - 10;
                     afCoord [ 1 ] = poDados->m_fLocalReproduzY + ( rand () % 20 ) - 10;
                     afCoord [ 2 ] = poDados->m_fLocalReproduzZ;
                     padwUsar = adwList;
                     break;

                  case NDX_MODELO_ALGA_VERDE:
                     afCoord [ 0 ] = ( rand () % 240 ) - 240 / 2;
                     afCoord [ 1 ] = fInf + ( rand () % 4 ) + 2;
                     afCoord [ 2 ] = poDados->m_fLocalReproduzZ;
                     padwUsar = adwAlga;
                     break;

                  case NDX_MODELO_MICROORGANISMO:
                     afCoord [ 0 ] = ( rand () % 200 ) - 200 / 2;
                     afCoord [ 1 ] = ( rand () % 70 ) - 70 / 2 - 20;
                     afCoord [ 2 ] = poDados->m_fLocalReproduzZ;
                     padwUsar = adwMicr;
                     break;
               }

               // para os peixes,
               // o nivel de energia do novo ser eh o nivel do pai,
               if ( poDados->m_dwTipoCorpo == NDX_MODELO_PEIXE_LISTRADO ||
                    poDados->m_dwTipoCorpo == NDX_MODELO_PEIXE_AZUL     ||
                    poDados->m_dwTipoCorpo == NDX_MODELO_PEIXE_GORDO )
                  padwUsar [ NUM_EVENTOS * 2 + 9 ] = (int) poDados->m_fFome;
               
               // faz com que nasca 
               m_poMeuAgente->m_paoOsAgentes [ ncA ].mTrataEvento ( NDX_EVENTO_NASCE, (PTRVAL) padwUsar, (PTRVAL) afCoord );

               // sai do FOR mais interno
               break;
            }

   // fome
   ( (CDadosFisicos*) m_poMeuAgente->m_poDados )->m_fFome += 
     ( (CDadosFisicos*) m_poMeuAgente->m_poDados )->m_fPerdeReproduzindo;

   return bAchou;
}
