mundo.cpp

Ir para a documentação deste ficheiro.
00001 
00005 #include "mundo.h"
00006 
00007 #include <stdlib.h>
00008 #include <math.h>
00009 #include <time.h>
00010 
00011 #include <QStringList>
00012 #include <QFile>
00013 
00014 /******************************************************************************/
00015 
00016 /* Operacoes com graos */
00018 void Mundo::inserirGrao(Vetor<float> posicao)
00019 {
00020     struct NohGrao *novoNohGrao = new NohGrao;
00021 
00022     /* Percorre lista de paredes */
00023     for (struct NohParede *percorre = nohCabecaParedes.proximo;
00024     percorre != NULL;
00025     percorre = percorre->proximo)
00026     {
00027         Vetor<float> u = posicao - percorre->inicio;
00028         Vetor<float> v = percorre->fim - percorre->inicio;
00029         Vetor<float> proj = (v.modulo () == 0)? posicao : (
00030         (v / v.modulo ()) *
00031         (((u.X * v.X)+(u.Y * v.Y)) / v.modulo()) );
00032 
00033         proj += percorre->inicio;
00034 
00035         /* Corrige limites da parede */
00036         if (proj.X > percorre->inicio.X && proj.X > percorre->fim.X)
00037             proj = (percorre->inicio.X > percorre->fim.X)? percorre->inicio : percorre->fim;
00038         else if (proj.X < percorre->inicio.X && proj.X < percorre->fim.X)
00039             proj = (percorre->inicio.X < percorre->fim.X)? percorre->inicio : percorre->fim;
00040         else if (proj.Y > percorre->inicio.Y && proj.Y > percorre->fim.Y)
00041             proj = (percorre->inicio.Y > percorre->fim.Y)? percorre->inicio : percorre->fim;
00042         else if (proj.Y < percorre->inicio.Y && proj.Y < percorre->fim.Y)
00043             proj = (percorre->inicio.Y < percorre->fim.Y)? percorre->inicio : percorre->fim;
00044 
00045         /* Testa distancia */
00046         if (posicao.distancia(proj) < GROSSURA_PAREDE + RAIO_GRAO)
00047         {
00048             /* Altera posicao do grao */
00049             /* Calcula angulo de "colisao" */
00050             float ang = (posicao.Y - proj.Y == 0 && posicao.X - proj.X == 0)? 0.0f :
00051             atan2(posicao.Y - proj.Y, posicao.X - proj.X);
00052 
00053             /* Reajusta posicao */
00054             posicao += Vetor<float>(cos(ang),sin(ang)) *
00055             ((GROSSURA_PAREDE + RAIO_GRAO) - posicao.distancia(proj));
00056         }
00057     }
00058 
00059     novoNohGrao->posicao = posicao;
00060     novoNohGrao->proximo = NULL;
00061 
00062     finalGraos->proximo = novoNohGrao;
00063     finalGraos = novoNohGrao;
00064 
00065     estatisticas.numero_graos++;
00066 }
00067 
00068 /******************************************************************************/
00069 
00071 bool Mundo::removerGrao()
00072 {
00073     if (nohCabecaGraos.proximo == NULL)
00074         return false;
00075 
00076     struct NohGrao *remover = nohCabecaGraos.proximo;
00077     nohCabecaGraos.proximo = nohCabecaGraos.proximo->proximo;
00078 
00079     /* Corrige caso se tente remover o fim da lista */
00080     if (remover == finalGraos)
00081         finalGraos = &nohCabecaGraos;
00082 
00083     /* Corrige caso seja selecionado */
00084     if (remover == grao_selecionado)
00085         grao_selecionado = NULL;
00086 
00087     delete remover;
00088 
00089     estatisticas.numero_graos--;
00090 
00091     return true;
00092 }
00093 
00094 /******************************************************************************/
00095 
00097 Mundo::Mundo()
00098 {
00099     srand(time(NULL));
00100 
00101     propriedades.teto_energetico = 30000;
00102     propriedades.energia_grao = 200;
00103     propriedades.probabilidade_mutacao = 10;
00104     propriedades.intensidade_mutacao = 1;
00105     propriedades.tamanho_x = 800;
00106     propriedades.tamanho_y = 600;
00107 
00108     estatisticas.numero_biotas = 0;
00109     estatisticas.numero_graos = 0;
00110     estatisticas.ciclos = 0;
00111     estatisticas.nascimentos = 0;
00112     estatisticas.mortes = 0;
00113 
00114     selecionado = NULL;
00115     grao_selecionado = NULL;
00116     nohCabecaBiotas.proximo = NULL;
00117     nohCabecaGraos.proximo = NULL;
00118     nohCabecaParedes.proximo = NULL;
00119     finalGraos = &nohCabecaGraos;
00120 }
00121 
00122 /******************************************************************************/
00123 
00125 Mundo::Mundo(unsigned int tx, unsigned int ty)
00126 {
00127     Mundo();
00128     propriedades.tamanho_x = tx;
00129     propriedades.tamanho_y = ty;
00130 }
00131 
00132 /******************************************************************************/
00133 
00135 Mundo::Mundo(unsigned int numero_de_biotas)
00136 {
00137     Mundo();
00138     for (unsigned int c = 0; c < numero_de_biotas; c++)
00139     {
00140         inserirBiota(Biota(this));
00141     }
00142 }
00143 
00144 /******************************************************************************/
00145 
00147 Mundo::Mundo(unsigned int tx, unsigned int ty, unsigned int numero_de_biotas)
00148 {
00149     Mundo();
00150     propriedades.tamanho_x = tx;
00151     propriedades.tamanho_y = ty;
00152     for (unsigned int c = 0; c < numero_de_biotas; c++)
00153     {
00154         inserirBiota(Biota(this));
00155     }
00156 }
00157 
00158 /******************************************************************************/
00159 
00161 void Mundo::destroy()
00162 {
00163     /* Remove todos biotas */
00164     while (nohCabecaBiotas.proximo != NULL)
00165     {
00166         struct NohBiota *remover = nohCabecaBiotas.proximo;
00167         nohCabecaBiotas.proximo = nohCabecaBiotas.proximo->proximo;
00168 
00169         /* Libera memoria */
00170         remover->biota.destroy();
00171         delete remover;
00172     }
00173 
00174     /* Remove todas as paredes */
00175     while (nohCabecaParedes.proximo != NULL)
00176     {
00177         struct NohParede *remover = nohCabecaParedes.proximo;
00178         nohCabecaParedes.proximo = nohCabecaParedes.proximo->proximo;
00179 
00180         /* Libera memoria */
00181         delete remover;
00182     }
00183 
00184     /* Remove todos graos */
00185     while (removerGrao());
00186 
00187     /* Zera estatisticas */
00188     estatisticas.numero_biotas = 0;
00189     estatisticas.numero_graos = 0;
00190     estatisticas.ciclos = 0;
00191     estatisticas.mortes = 0;
00192     estatisticas.nascimentos = 0;
00193 }
00194 
00195 /******************************************************************************/
00196 
00198 void Mundo::inserirBiota(Biota biota)
00199 {
00200     struct NohBiota *novoNohBiota = new NohBiota;
00201 
00202     biota.mundo = this;
00203 
00204     novoNohBiota->biota = biota;
00205     novoNohBiota->proximo = nohCabecaBiotas.proximo;
00206 
00207     nohCabecaBiotas.proximo = novoNohBiota;
00208     estatisticas.numero_biotas++;
00209 }
00210 
00211 /******************************************************************************/
00212 
00214 void Mundo::atualizar()
00215 {
00216     /* Contador de energia total dos biotas */
00217     float energia_biotas = 0;
00218 
00219     /* Percorre a lista de biotas */
00220     struct NohBiota *percorre = &nohCabecaBiotas;
00221     while(percorre->proximo != NULL)
00222     {
00223         Biota *novoBiota;
00224 
00225         /* Acrescenta energia ao contador */
00226         energia_biotas += percorre->proximo->biota.estado.energia;
00227 
00228         /* Atualiza biota e trata resultado */
00229         switch (percorre->proximo->biota.atualizar((void*)percorre->proximo))
00230         {
00231             case REPRODUCAO:
00232                 /* Cria biota */
00233                 novoBiota = new Biota(percorre->proximo->biota);
00234                 /* Distribui energia */
00235                 novoBiota->estado.energia =
00236                 percorre->proximo->biota.estado.energia *
00237                 percorre->proximo->biota.genes.distribuicao_energia;
00238                 percorre->proximo->biota.estado.energia -=
00239                 novoBiota->estado.energia;
00240                 /* Modifica angulo de reproducao */
00241                 novoBiota->estado.angulo +=
00242                 percorre->proximo->biota.genes.angulo_reproducao;
00243                 /* Seta geracao  e idade*/
00244                 novoBiota->estado.geracao++;
00245                 novoBiota->estado.idade = 0;
00246                 /* Seta numero de filhos de cada um */
00247                 novoBiota->estado.filhos = 0;
00248                 if (percorre->proximo->biota.estado.filhos++ % 2 == 0)
00249                     novoBiota->refletir();
00250                 /* Aplica provavel mutacao */
00251                 if ((unsigned int)(rand() % 100) <= propriedades.probabilidade_mutacao)
00252                     novoBiota->mutacao();
00253                 /* Insere biota na lista */
00254                 inserirBiota(*novoBiota);
00255                 /* Corrige atualizacao imediata do recem-criado */
00256                 if (percorre == &nohCabecaBiotas)
00257                     percorre = percorre->proximo;
00258                 /* Atualiza estatistica */
00259                 estatisticas.nascimentos++;
00260                 /* NAO POSSUI BREAK : entra no normal */
00261             case NORMAL:
00262                 /*
00263                     Ambas reproducao e normal devem andar
00264                     na lista, morte nao, porque retira.
00265                  */
00266                 percorre = percorre->proximo;
00267                  break;
00268             case MORTE:
00269                 /* Remove biota da lista */
00270                 struct NohBiota *remover = percorre->proximo;
00271                 percorre->proximo = percorre->proximo->proximo;
00272                 /* Verifica se biota esta selecionado */
00273                 if (selecionado == remover)
00274                     selecionado = NULL;
00275                 /* Determina estatisticas de morte */
00276                 estatisticas.mortes++;
00277                 /* Libera memoria */
00278                 remover->biota.destroy();
00279                 delete remover;
00280                 /* Decrementa contador de biotas */
00281                 estatisticas.numero_biotas--;
00282                 break;
00283         }
00284     }
00285 
00286     /* Incrementa ciclos */
00287     estatisticas.ciclos++;
00288 
00289     /* Move grao aleatoriamente, se maior que limiar */
00290     if (estatisticas.numero_graos > (propriedades.teto_energetico + propriedades.energia_grao)/2)
00291     {
00292         removerGrao();
00293         inserirGrao(Vetor<float>((GROSSURA_PAREDE + RAIO_GRAO) + (rand() % (propriedades.tamanho_x-(2*(GROSSURA_PAREDE + RAIO_GRAO)))),
00294          (GROSSURA_PAREDE + RAIO_GRAO) + (rand() % (propriedades.tamanho_y-(2*(GROSSURA_PAREDE + RAIO_GRAO))))));
00295     }
00296 
00297     /* Trata incremento ou decremento de graos do sistema */
00298     if (energia_biotas + (estatisticas.numero_graos * propriedades.energia_grao) >
00299     propriedades.teto_energetico + propriedades.energia_grao)
00300         removerGrao();
00301     else if (energia_biotas + (estatisticas.numero_graos * propriedades.energia_grao) <
00302     propriedades.teto_energetico - propriedades.energia_grao)
00303         inserirGrao(Vetor<float>((GROSSURA_PAREDE + RAIO_GRAO) + (rand() % (propriedades.tamanho_x-(2*(GROSSURA_PAREDE + RAIO_GRAO)))),
00304          (GROSSURA_PAREDE + RAIO_GRAO) + (rand() % (propriedades.tamanho_y-(2*(GROSSURA_PAREDE + RAIO_GRAO))))));
00305 }
00306 
00307 /******************************************************************************/
00308 
00310 bool Mundo::selecionarBiota(Vetor<float> posicao)
00311 {
00312     /* Percorre a lista de biotas */
00313     for (struct NohBiota *percorre = nohCabecaBiotas.proximo;
00314     percorre != NULL;
00315     percorre = percorre->proximo)
00316     {
00317         if (percorre->biota.selecionar(posicao))
00318         {
00319             selecionado = percorre;
00320             return true;
00321         }
00322     }
00323 
00324     return false;
00325 }
00326 
00327 /******************************************************************************/
00328 
00330 void Mundo::descelecionarBiota()
00331 {
00332     selecionado = NULL;
00333 }
00334 
00335 /******************************************************************************/
00336 /* OPERACOES COM GRAOS */
00337 /******************************************************************************/
00338 
00340 void Mundo::removerGraoSelecionado()
00341 {
00342     if (grao_selecionado == NULL)
00343         return;
00344 
00345     /* Percorre a lista de graos */
00346     for (struct NohGrao *percorre = &nohCabecaGraos;
00347     percorre->proximo != NULL;
00348     percorre = percorre->proximo)
00349     {
00350         if (percorre->proximo == grao_selecionado)
00351         {
00352             struct NohGrao *remove = percorre->proximo;
00353             percorre->proximo = percorre->proximo->proximo;
00354             delete remove;
00355             grao_selecionado = NULL;
00356 
00357             return;
00358         }
00359     }
00360 }
00361 
00362 /******************************************************************************/
00363 
00365 void Mundo::descelecionarGrao()
00366 {
00367     grao_selecionado = NULL;
00368 }
00369 
00370 /******************************************************************************/
00371 
00373 bool Mundo::selecionarGrao(Vetor<float> posicao)
00374 {
00375     /* Percorre a lista de graos */
00376     for (struct NohGrao *percorre = nohCabecaGraos.proximo;
00377     percorre != NULL;
00378     percorre = percorre->proximo)
00379     {
00380         if (percorre->posicao.distancia(posicao) < RAIO_GRAO)
00381         {
00382             grao_selecionado = percorre;
00383             return true;
00384         }
00385     }
00386 
00387     return false;
00388 }
00389 
00390 /******************************************************************************/
00391 
00393 void Mundo::posicionarGrao(Vetor<float> posicao)
00394 {
00395     if (grao_selecionado != NULL)
00396     {
00397         grao_selecionado->posicao = posicao;
00398     }
00399 }
00400 
00401 /******************************************************************************/
00402 
00404 bool Mundo::graoSelecionado()
00405 {
00406     return (grao_selecionado != NULL);
00407 }
00408 
00409 /******************************************************************************/
00410 
00412 void Mundo::salvarMundo(FILE *arq)
00413 {
00414     fprintf(arq, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
00415     fprintf(arq, "<!DOCTYPE simulation SYSTEM \"http://simvida.sourceforge.net/simvida.simulation.dtd\">\n");
00416     fprintf(arq, "<simulation cicles=\"%ld\" borns=\"%ld\" deaths=\"%ld\"\n",
00417         estatisticas.ciclos, estatisticas.nascimentos, estatisticas.mortes);
00418 
00419     /* salva propriedades */
00420     fprintf(arq, " energyceil=\"%d\" grainenergy=\"%d\" mutationprobability=\"%d\"\n",
00421         propriedades.teto_energetico, propriedades.energia_grao, propriedades.probabilidade_mutacao);
00422     fprintf(arq, " mutationintensity=\"%d\" size=\"%d;%d\">\n",
00423         propriedades.intensidade_mutacao, propriedades.tamanho_x, propriedades.tamanho_y);
00424 
00425     /* Salvar biotas */
00426     for (struct NohBiota *percorre = nohCabecaBiotas.proximo;
00427     percorre != NULL;
00428     percorre = percorre->proximo)
00429     {
00430         /* salva biota */
00431         percorre->biota.salvar(arq, true, 1);
00432     }
00433 
00434     /* Salva graos */
00435     for (struct NohGrao *percorre = nohCabecaGraos.proximo;
00436     percorre != NULL;
00437     percorre = percorre->proximo)
00438     {
00439         fprintf(arq, "\t<grain position=\"%d;%d\"/>\n", (int)percorre->posicao.X, (int)percorre->posicao.Y);
00440     }
00441 
00442     /* Salvar paredes */
00443     /* Percorre lista de paredes */
00444     for (struct NohParede *percorre = nohCabecaParedes.proximo;
00445     percorre != NULL;
00446     percorre = percorre->proximo)
00447     {
00448         fprintf(arq, "\t<wall geometry=\"%d;%d;%d;%d\"/>\n",
00449             (int)percorre->inicio.X, (int)percorre->inicio.Y, (int)percorre->fim.X, (int)percorre->fim.Y);
00450     }
00451 
00452     /* separador */
00453     fprintf(arq, "</simulation>\n");
00454 }
00455 
00456 /******************************************************************************/
00457 
00459 void Mundo::abrirMundo(FILE *arq)
00460 {
00461     /* limpa mundo */
00462     destroy();
00463 
00464     QDomDocument xmlDocument;
00465     QFile file;
00466     file.open(arq, QIODevice::ReadOnly);
00467     if (!xmlDocument.setContent(&file))
00468         fprintf(stderr, "XML Parser error.\n");
00469     file.close();
00470 
00471     QDomNodeList children = xmlDocument.childNodes();
00472     for (int i=0; i < children.count(); i++)
00473     {
00474         /* try to convert the node to an element. */
00475         QDomElement element = children.at(i).toElement();
00476         if (!element.isNull() && element.tagName() == "simulation")
00477         {
00478 
00479             propriedades.teto_energetico = element.attribute("energyceil",
00480                 QString::number(propriedades.teto_energetico)).toInt();
00481             propriedades.energia_grao = element.attribute("grainenergy",
00482                 QString::number(propriedades.energia_grao)).toInt();
00483             propriedades.probabilidade_mutacao = element.attribute("mutationprobability",
00484                 QString::number(propriedades.probabilidade_mutacao)).toInt();
00485             propriedades.intensidade_mutacao = element.attribute("mutationintensity",
00486                 QString::number(propriedades.intensidade_mutacao)).toInt();
00487 
00488             QStringList size = element.attribute("size",
00489                 QString::number(propriedades.tamanho_x) + ";" + QString::number(propriedades.tamanho_y)).split(";");
00490             propriedades.tamanho_x = size.at(0).toInt();
00491             propriedades.tamanho_y = size.at(1).toInt();
00492 
00493             estatisticas.ciclos = element.attribute("cicles", "0").toInt();
00494             estatisticas.mortes = element.attribute("deaths", "0").toInt();
00495             estatisticas.nascimentos = element.attribute("borns", "0").toInt();
00496 
00497             QDomNodeList simChildren = element.childNodes();
00498             for (int j=0; j < simChildren.count(); j++)
00499             {
00500                 /* try to convert the node to an element. */
00501                 QDomElement simElement = simChildren.at(j).toElement();
00502                 if (!simElement.isNull() && simElement.tagName() == "biot")
00503                 {
00504                     Biota biota;
00505                     biota.abrir(simElement);
00506                     inserirBiota(biota);
00507                 }
00508                 else if (!simElement.isNull() && simElement.tagName() == "grain")
00509                 {
00510                     QStringList position = simElement.attribute("position").split(";");
00511                     inserirGrao(Vetor<float>(position.at(0).toFloat(),position.at(1).toFloat()));
00512                 }
00513                 else if (!simElement.isNull() && simElement.tagName() == "wall")
00514                 {
00515                     QStringList geometry = simElement.attribute("geometry").split(";");
00516                     int ax = geometry.at(0).toInt();
00517                     int ay = geometry.at(1).toInt();
00518                     int bx = geometry.at(2).toInt();
00519                     int by = geometry.at(3).toInt();
00520 
00521                     if (ax > -(signed int)propriedades.tamanho_x && ax < (signed int)propriedades.tamanho_x*2 &&
00522                     bx > -(signed int)propriedades.tamanho_x && bx < (signed int)propriedades.tamanho_x*2 &&
00523                     ay > -(signed int)propriedades.tamanho_y && ay < (signed int)propriedades.tamanho_y*2 &&
00524                     ay > -(signed int)propriedades.tamanho_x && ay < (signed int)propriedades.tamanho_y*2)
00525                     {
00526                         /* Insere nova parede */
00527                         struct NohParede *novaParede = new struct NohParede;
00528 
00529                         novaParede->inicio = Vetor<float>(ax,ay);
00530                         novaParede->fim = Vetor<float>(bx,by);
00531                         novaParede->proximo = nohCabecaParedes.proximo;
00532                         nohCabecaParedes.proximo = novaParede;
00533                     }
00534                 }
00535             }
00536         }
00537     }
00538     xmlDocument.clear();
00539 }
00540 
00541 /******************************************************************************/

Gerado em Mon May 4 14:52:59 2009 para Simvida por  doxygen 1.5.8