

NAO FUNCIONA, MAS GUARDAR
-------------------------

   // define caixas que circunscrevem os objetos do cenario

   D3DRMBOX
      astCaixas [ MAX_OBJETOS ];  // conjunto de caixas dos objetos

   // cada cada objeto do cenario
   for ( int ncO = 0; ncO < MAX_OBJETOS; ncO ++ )

      // se existe objeto
      if ( m_lpFrObjetos [ ncO ] != NULL ) {

         // define quais partes visualizaveis existem nesse objeto
         LPDIRECT3DRMVISUALARRAY
            lplpVisuals;
         m_lpFrObjetos [ ncO ]->GetVisuals ( &lplpVisuals );

         // verifica se objeto tem algo visualizavel mesmo
         if ( lplpVisuals->GetSize () >= 1 ) {

            // define qual eh (usa o primeiro apenas)
            LPDIRECT3DRMVISUAL
               stVisual;
            lplpVisuals->GetElement ( 0, &stVisual );

            // define caixa que circunscreve essa parte visualizavel
            LPDIRECT3DRMMESHBUILDER
               lpMeshVis;
            if ( SUCCEEDED ( stVisual->QueryInterface ( IID_IDirect3DRMMeshBuilder,
                            (LPVOID*) &lpMeshVis ) ) ) {
               // caixa a partir da malha
               lpMeshVis->GetBox ( &astCaixas [ ncO ] );
               // libera malha
               lpMeshVis->Release ();
            }
         }
      }



FUNCIONA: APROXIMA DE OUTRO AGENTE SEMELHANTE
---------------------------------------------

BOOL CAproxima::mAtiva ( PTRVAL pDado1, PTRVAL pDado2 )
{
   // dados do agente que vai se aproximar
   CDadosFisicos
      *poDados = (CDadosFisicos*) m_poMeuAgente->m_poDados;

   // procura no cenario um agente que tenha o mesmo corpo
   for ( int ncA = 0; ncA < MAX_AGENTES; ncA ++ )

      // verifica se agente possuir dados fisicos
      if ( m_poMeuAgente->m_paoOsAgentes [ ncA ].m_poDados != NULL &&
           m_poMeuAgente->m_paoOsAgentes [ ncA ].m_poDados->m_dwTipoDado == TIPO_FISICO )

         // verifica se o dado fisico: tipo do corpo eh o mesmo
         if ( ( (CDadosFisicos*) m_poMeuAgente->m_paoOsAgentes [ ncA ].m_poDados )->m_dwTipoCorpo == poDados->m_dwTipoCorpo ) {

            // achou um agente da mesma especie (mesmo corpo), aproxima

            // indentificador do corpo do outro agente
            DWORD
               dwObjetoOutro = ( (CDadosFisicos*) m_poMeuAgente->m_paoOsAgentes [ ncA ].m_poDados )->m_dwNdxObjeto;

            // agente achou o seu corpo na tabela
            if ( dwObjetoOutro == poDados->m_dwNdxObjeto )

               // move aleatoriamente
               //m_poMeuAgente->mPreparaSubstituirPos ( m_dwNdxMeuEvento, ID_ACAO_MOVE_LIVRE, ID_ACAO_MUDA_DIRECAO );
               // parado:
               m_poMeuAgente->m_poCenario->mMudaDirecaoDeslocamentoObjeto ( poDados->m_dwNdxObjeto, 0, 0.1, 0 );

            else {     
               
               // se move para o local do outro

               // obtem a posicao do outro objeto
               float
                  fXO,
                  fYO,
                  fZO;
               m_poMeuAgente->m_poCenario->mPegaPosicaoObjeto ( dwObjetoOutro, fXO, fYO, fZO );

               // obtem a posicao do objeto desse agente
               float
                  fXM,
                  fYM,
                  fZM;
               m_poMeuAgente->m_poCenario->mPegaPosicaoObjeto ( poDados->m_dwNdxObjeto, fXM, fYM, fZM );

               // define nova direcao de deslocamento para o agente
               float
                  fDX = fXO - fXM,
                  fDY = fYO - fYM,
                  fDZ = fZO - fZM;

               // define distancia ateh o outro objeto
               float
                  fModulo = sqrt ( fDX * fDX + fDY * fDY + fDZ * fDZ );

               // se estiver bastante perto reproduz, senao continua
               if ( fModulo < 5 ) {

                  // reproduz
                  m_poMeuAgente->mTrataEvento ( NDX_EVENTO_REPRODUZIR, 0, 1 );
                  // apohs reproducao volta ao estado anterior
                  m_poMeuAgente->mPreparaSubstituirPos ( m_dwNdxMeuEvento, m_dwTipoSubs, m_dwTipoSubs );
               }
               else {

                  // normaliza vetor deslocamento
                  fDX /= fModulo;
                  fDY /= fModulo;
                  fDZ /= fModulo;

                  // altera trajetoria do agente para encontrar o outro
                  m_poMeuAgente->m_poCenario->mMudaDirecaoDeslocamentoObjeto ( poDados->m_dwNdxObjeto, fDX, fDY, fDZ );
               }
            }
         }

   return TRUE;
}



USAR TIMER como HERT-BIT
------------------------
  
/* Executa agentes e desenha cenario
**********************************************************/
void CApl::mExecInteracao ()
{
   // verifica se estah exibindo abertura
   if ( m_yEstadoExecucao == 0 )
      return;

   // conta tempo, qual o tempo atual em milisegundos
   //DWORD
      //dwTempo = ::GetTickCount ();

   // roda agentes
   if ( m_yEstadoExecucao == 1 ) {
      // executa comunicacao entre agentes
      m_oAgencia.mDisparaEvento ( NDX_EVENTO_ATIVIDADE_1, 0, 0 );
      m_oAgencia.mDisparaEvento ( NDX_EVENTO_ATIVIDADE_2, 0, 0 );
   }

   // exibe o ecometro
   mExibeEcometro ();
      
   // exibe cenario
   m_oJanPrincipal.mProcessaCenario ( m_yEstadoExecucao == 1 );
 
   // testa se transcorreu pouco tempo, se sim espera
   //mCongelaTempo ( dwTempo );
}



/* Executa algum evento da fase, definido no arquivo de fase.
bIniciar - TRUE - reinicia o processamento de eventos (como do
inicio), FALSE - continua do ultimo evento tratado.
**********************************************************/
void CApl::mExecEventosFase ( BOOL bIniciar )
{
   // inicia cursor que define qual evento executar
   static DWORD
      dwNumEventoExec = 0;

   // qual posicao no array de agentes usar na alocacao de um elemento
   // interventor
   static int
      nNumInterventor = 0;

   // quantas interacoes de jogo jah se passaram desdo inicio
   static DWORD
      dwInteracoesJogo = 0;

   // se eh apenas para iniciar variaveis
   if ( bIniciar ) {
      dwNumEventoExec = 0;
      nNumInterventor = 0;
      dwInteracoesJogo = 0;

      // remove o timer
      KillTimer ( m_oJanPrincipal.m_hWnd, 1 );

      // programa timer
      // controle das interacoes do jogo (100 ms)
      SetTimer ( m_oJanPrincipal.m_hWnd, 1, m_dwVeloc, NULL );

      return;
   }

   // verifica se partida esta bloqueada ou terminada,
   // nao executa mais
   if ( m_yEstadoExecucao == 2 || m_yEstadoExecucao == 3 )
      return;

   // executa uma interacao
   mExecInteracao ();

   dwInteracoesJogo ++;

   // verifica nao se deve executar algum evento da fase
   if ( dwInteracoesJogo * ( 1000 / m_dwVeloc ) != 1000 * m_astEventosFase [ dwNumEventoExec ].dwTempo )
      return;

   // define qual agente interventor criar (se for usar, jah tem valor)
   DWORD
      dwQualCriar = rand () % 9;
   if ( m_astEventosFase [ dwNumEventoExec ].dwEvento >= NUM_EVENTOS_TMP ) {
      dwQualCriar = m_astEventosFase [ dwNumEventoExec ].dwEvento - NUM_EVENTOS_TMP;
      m_astEventosFase [ dwNumEventoExec ].dwEvento = EVENTO_TMP_CRIA_INTERVENTOR;
   }

   // executa a procedimento indicado nos eventos da fase
   switch ( m_astEventosFase [ dwNumEventoExec ].dwEvento ) {

      case EVENTO_TMP_NULO:
         break;

      case EVENTO_TMP_CRIA_INTERVENTOR:  // cria agente interventor
         {
            m_oSons.mToca ( 7 );

            // dados para criacao do agente
            DWORD
               *padwAgente = NULL,
               adwDrag [] = CONFIG_AGENTE_DRAGA,
               adwAgro [] = CONFIG_AGENTE_AGROTOXICO,
               adwRede [] = CONFIG_AGENTE_REDE,
               adwLixo [] = CONFIG_AGENTE_LIXO,
               adwJets [] = CONFIG_AGENTE_JETSKI,
               adwPesc [] = CONFIG_AGENTE_PESCA_PREDATORIA,
               adwEplu [] = CONFIG_AGENTE_ESGOTO_PLUVIAL,
               adwEind [] = CONFIG_AGENTE_ESGOTO_INDUSTRIAL,
               adwGaso [] = CONFIG_AGENTE_GASOLINA;

            // coordenadas limitrofes do cenario
            float
               fSup,
               fInf,
               fDir,
               fEsq;
            m_oCen.mRetLimiteJanVis ( fSup, fInf, fDir, fEsq ); 

            // coordenadas do agente no cenario (x,y,z)
            float
               afCoord [ 3 ];
            afCoord [ 2 ] = 0;      // z eh sempre 0
            
            // inicia dados especificos para cada agente interventor
            switch ( dwQualCriar ) {

               case 0:           // cria draga
                  afCoord [ 0 ] = fEsq;
                  afCoord [ 1 ] = fSup - ( fSup * (float) LIMSUP * 0.92 );
                  padwAgente = adwDrag;
                  break;

               case 1:           // cria agrotoxico
                  afCoord [ 0 ] = fDir;
                  afCoord [ 1 ] = fSup - ( fSup * (float) LIMSUP * 0.2 );
                  padwAgente = adwAgro;
                  break;

               case 2:           // cria rede de arrastao
                  afCoord [ 0 ] = fDir;
                  afCoord [ 1 ] = fSup - ( fSup * (float) LIMSUP * 0.92 );
                  padwAgente = adwRede;
                  break;

               case 3:           // cria lixo urbano
                  afCoord [ 0 ] = fEsq - fEsq * (float) 0.7;
                  afCoord [ 1 ] = fSup - ( fSup * (float) LIMSUP * 0.92 );
                  padwAgente = adwLixo;
                  break;

               case 4:           // cria jetski
                  afCoord [ 0 ] = fDir;
                  afCoord [ 1 ] = fSup - ( fSup * (float) LIMSUP * 0.92 );
                  padwAgente = adwJets;
                  break;

               case 5:           // cria pesca predatoria
                  afCoord [ 0 ] = fEsq;
                  afCoord [ 1 ] = fSup - ( fSup * (float) LIMSUP * 0.92 );
                  padwAgente = adwPesc;
                  break;

               case 6:           // cria esgoto pluvial
                  afCoord [ 0 ] = fEsq;
                  afCoord [ 1 ] = fSup - ( fSup * (float) LIMSUP * 0.92 );
                  padwAgente = adwEplu;
                  break;

               case 7:           // cria esgoto industrial
                  afCoord [ 0 ] = fDir;
                  afCoord [ 1 ] = fSup - ( fSup * (float) LIMSUP * 0.92 );
                  padwAgente = adwEind;
                  break;

               case 8:           // cria posto de gasolina
                  afCoord [ 0 ] = fEsq;
                  afCoord [ 1 ] = fSup - ( fSup * (float) LIMSUP * 0.92 );
                  padwAgente = adwGaso;
                  break;

               default:
                  MSGSTR ( "BUG: interventor com esse numero nao existe, CApl::mExecEventosFase" );
                  break;
            }

            // qual posicao usar no array de agentes para proximo
            // interventor
            if ( nNumInterventor > MAX_AGENTES_INTERVENTORES )
               nNumInterventor = 0;
            else
               nNumInterventor ++;

            // adiciona agente
            m_oAgencia.m_aoAgentes [ MAX_AGENTES - NDX_AGENTE_INTERVENTOR - nNumInterventor ].mTrataEvento ( NDX_EVENTO_NASCE, (PTRVAL) padwAgente, (PTRVAL) afCoord );
         }
         break;

      case EVENTO_TMP_TERMINA_PARTIDA:
         mTerminaPartida ();
         break;

      default:
         MSGSTR ( "BUG: evento no existe, CApl::mExecEventosFase" );
         break;
   }

   // se nao terminou partida
   if ( m_astEventosFase [ dwNumEventoExec ].dwEvento != EVENTO_TMP_TERMINA_PARTIDA )
      // evento jah disparado
      dwNumEventoExec ++;
}





apl.cpp - durante mCria                         
-----------------------
  usar rede DirectPLay?
   /* so caixa de mensagem simples para selecao - com/sem rede DP
   int
      nResp = MessageBox ( NULL, STR_JOGAR_EM_REDE, STR_NOMEPEQ, MB_YESNOCANCEL | MB_ICONQUESTION );
   // analisa resposta
   if ( nResp == IDCANCEL )                   // sair CANCELAR
      return FALSE;
   // usar rede?
   if ( nResp == IDYES ) {
      TentaConectar ( m_hInstancia );
      if ( ! bUSANDO_REDEDP ) {                  // erro?
         MSGSTR ( STR_TERMINAR_SEM_CONECXAO );
         return FALSE;
      }
      // verifica se foi conectado como servidor, se sim espera por cliente
      if ( DPInfo.bIsHost )
         // espera conexao, se cancelar, o programa termina
         if ( ! Espera ( m_hInstancia, STR_ESPERA_CLIENTE, &bCLIENTE_CONECTOU ) ) {
            MSGSTR ( STR_TERMINAR_SEM_CONECXAO );
            return FALSE;
         }
      // Se foi conectado como cliente, o sistema envia automaticamente
      // mensagem para servidor avisando que cliente estah disponivel.
   }*/




  usar rede sockerts com kernel cognitivo?   
  -----------------------------------------
   // verifica se deve jogar com/sem rede e com/sem tutor
   /* DESABILITADO
   // pergunta
   BOOL
      bRedeDp = FALSE,
      bContinuar = FazDialogo_ModoJogo ( NULL, bRedeDp, bUSANDO_SOCKETS );
                                                         // bRede - DirectPlay?
                                                         // bUSAR_SOCK - tutor?
   
   // terminar jogo
   if ( ! bContinuar )
      return FALSE;

   // usar rede?
   if ( bRedeDp ) {

      TentaConectar ( m_hInstancia );
      
      if ( ! bUSANDO_REDEDP ) {                  // erro?
         MSGSTR ( STR_TERMINAR_SEM_CONECXAO );
         return FALSE;
      }
      
      // verifica se foi conectado como servidor, se sim espera por cliente
      if ( DPInfo.bIsHost )
      
         // espera conexao, se cancelar, o programa termina
         if ( ! FazDialogo_Espera ( m_hInstancia, STR_ESPERA_CLIENTE, &bCLIENTE_CONECTOU ) ) {
            MSGSTR ( STR_TERMINAR_SEM_CONECXAO );
            return FALSE;
         }
      // Se foi conectado como cliente, o sistema envia automaticamente
      // mensagem para servidor avisando que cliente estah disponivel.
   }
   */
