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
00018 void Mundo::inserirGrao(Vetor<float> posicao)
00019 {
00020 struct NohGrao *novoNohGrao = new NohGrao;
00021
00022
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
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
00046 if (posicao.distancia(proj) < GROSSURA_PAREDE + RAIO_GRAO)
00047 {
00048
00049
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
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
00080 if (remover == finalGraos)
00081 finalGraos = &nohCabecaGraos;
00082
00083
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
00164 while (nohCabecaBiotas.proximo != NULL)
00165 {
00166 struct NohBiota *remover = nohCabecaBiotas.proximo;
00167 nohCabecaBiotas.proximo = nohCabecaBiotas.proximo->proximo;
00168
00169
00170 remover->biota.destroy();
00171 delete remover;
00172 }
00173
00174
00175 while (nohCabecaParedes.proximo != NULL)
00176 {
00177 struct NohParede *remover = nohCabecaParedes.proximo;
00178 nohCabecaParedes.proximo = nohCabecaParedes.proximo->proximo;
00179
00180
00181 delete remover;
00182 }
00183
00184
00185 while (removerGrao());
00186
00187
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
00217 float energia_biotas = 0;
00218
00219
00220 struct NohBiota *percorre = &nohCabecaBiotas;
00221 while(percorre->proximo != NULL)
00222 {
00223 Biota *novoBiota;
00224
00225
00226 energia_biotas += percorre->proximo->biota.estado.energia;
00227
00228
00229 switch (percorre->proximo->biota.atualizar((void*)percorre->proximo))
00230 {
00231 case REPRODUCAO:
00232
00233 novoBiota = new Biota(percorre->proximo->biota);
00234
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
00241 novoBiota->estado.angulo +=
00242 percorre->proximo->biota.genes.angulo_reproducao;
00243
00244 novoBiota->estado.geracao++;
00245 novoBiota->estado.idade = 0;
00246
00247 novoBiota->estado.filhos = 0;
00248 if (percorre->proximo->biota.estado.filhos++ % 2 == 0)
00249 novoBiota->refletir();
00250
00251 if ((unsigned int)(rand() % 100) <= propriedades.probabilidade_mutacao)
00252 novoBiota->mutacao();
00253
00254 inserirBiota(*novoBiota);
00255
00256 if (percorre == &nohCabecaBiotas)
00257 percorre = percorre->proximo;
00258
00259 estatisticas.nascimentos++;
00260
00261 case NORMAL:
00262
00263
00264
00265
00266 percorre = percorre->proximo;
00267 break;
00268 case MORTE:
00269
00270 struct NohBiota *remover = percorre->proximo;
00271 percorre->proximo = percorre->proximo->proximo;
00272
00273 if (selecionado == remover)
00274 selecionado = NULL;
00275
00276 estatisticas.mortes++;
00277
00278 remover->biota.destroy();
00279 delete remover;
00280
00281 estatisticas.numero_biotas--;
00282 break;
00283 }
00284 }
00285
00286
00287 estatisticas.ciclos++;
00288
00289
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
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
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
00337
00338
00340 void Mundo::removerGraoSelecionado()
00341 {
00342 if (grao_selecionado == NULL)
00343 return;
00344
00345
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
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
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
00426 for (struct NohBiota *percorre = nohCabecaBiotas.proximo;
00427 percorre != NULL;
00428 percorre = percorre->proximo)
00429 {
00430
00431 percorre->biota.salvar(arq, true, 1);
00432 }
00433
00434
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
00443
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
00453 fprintf(arq, "</simulation>\n");
00454 }
00455
00456
00457
00459 void Mundo::abrirMundo(FILE *arq)
00460 {
00461
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
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
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
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