00001
00006 #include "biota.h"
00007 #include "mundo.h"
00008 #include <math.h>
00009 #include <stdlib.h>
00010
00011 #include <QFile>
00012 #include <QDomDocument>
00013 #include <QDomElement>
00014 #include <QStringList>
00015
00016
00017
00019 unsigned int current_lineage = 0;
00020
00022 #define ABS(a) (((a) > 0)? (a) : -(a))
00023
00025 #define CORRIGE(a) (((a) < 0)? (a)+DPI : ((a) >= DPI)? (a) - DPI : (a))
00026 #define CORRIGE2(a) (((a) < -DPI)? (a)+DPI : ((a) > DPI)? (a) - DPI : (a))
00027
00029 #define XOR(a,b) (((a) && !(b)) || (!(a) && (b)))
00030
00032 #define ESQUERDA(a,b,c) (area_triangulo(a,b,c) > 0)
00033
00035 #define MEDIA_SEGMENTOS 8
00036
00037
00038
00043 float area_triangulo(Vetor<float> A, Vetor<float> B, Vetor<float> C)
00044 {
00045 return A.X * B.Y - A.Y * B.X +
00046 A.Y * C.X - A.X * C.Y +
00047 B.X * C.Y - C.X * B.Y;
00048 }
00049
00050
00051
00059 float normal()
00060 {
00061 float u1 = (rand() % 10000)/10000.;
00062 float u2 = (rand() % 10000)/10000.;
00063
00064 return sqrt(-2*log(u1))*cos(DPI*u2);
00065 }
00066
00067
00068
00069
00071 Biota::Biota()
00072 {
00073 lineage = current_lineage++;
00074
00075 mundo = NULL;
00076 numero_segmentos = 0;
00077
00078
00079 genes.cor_cabeca[0] = 0;
00080 genes.cor_cabeca[1] = 0;
00081 genes.cor_cabeca[2] = 0;
00082 genes.distribuicao_energia= 0;
00083 genes.limiar_reproducao = 0;
00084 genes.massa_cabeca = 0;
00085 genes.segmentos = NULL;
00086 genes.angulo_reproducao = 0.0f;
00087 genes.angulo_colisao = 0.0f;
00088
00089
00090 estado.energia = 0;
00091 estado.geracao = 1;
00092 estado.idade = 0;
00093 estado.posicao = Vetor<float>();
00094 estado.velocidade = Vetor<float>();
00095 estado.velocidade_angular = 0.0f;
00096 estado.posicaoSegmentos = NULL;
00097 estado.angulo = 0.0f;
00098 estado.filhos = 0;
00099 }
00100
00101
00102
00104 Biota::Biota(void *mundoPai)
00105 {
00106 lineage = current_lineage++;
00107
00108 mundo = mundoPai;
00109 numero_segmentos = 1 + (rand() % MEDIA_SEGMENTOS);
00110
00111
00112 genes.cor_cabeca[0] = rand() % 255;
00113 genes.cor_cabeca[1] = rand() % 255;
00114 genes.cor_cabeca[2] = rand() % 255;
00115 genes.distribuicao_energia= (10 + (rand() % 70)) / 100.0f;
00116 genes.limiar_reproducao = ((Mundo*)mundo)->propriedades.energia_grao;
00117 genes.massa_cabeca = RAIO_GRAO + (rand() % 10);
00118 genes.angulo_reproducao = (((rand() % 1000) * DPI) / 1000.0f) - PI;
00119 genes.angulo_colisao = (((rand() % 1000) * MPI) / 200000.0f) - (QPI/20.0f);
00120
00121 genes.segmentos = new struct GenesSegmento[numero_segmentos];
00122 for (unsigned int c = 0; c < numero_segmentos; c++)
00123 {
00124 genes.segmentos[c].arco = ((rand() % 1000)*QPI)/1000.0f;
00125 genes.segmentos[c].massa = 2 + (rand() % 12);
00126 genes.segmentos[c].comprimento = 10 + (rand() % 20);
00127 genes.segmentos[c].angulo = (QPI/2.0f) + (((rand() % 1000)*(PI+QPI))/1000.0f);
00128 genes.segmentos[c].cor[0] = rand() % 256;
00129 genes.segmentos[c].cor[1] = rand() % 256;
00130 genes.segmentos[c].cor[2] = rand() % 256;
00131 genes.segmentos[c].fa = 5 + (rand() % 95);
00132 genes.segmentos[c].fb = 5 + (rand() % 95);
00133 }
00134
00135
00136 estado.energia = genes.limiar_reproducao;
00137 estado.geracao = 1;
00138 estado.idade = 0;
00139 estado.posicao =
00140 Vetor<float>(rand() % ((Mundo*)mundo)->propriedades.tamanho_x,
00141 rand() % ((Mundo*)mundo)->propriedades.tamanho_y);
00142 estado.angulo = ((rand() % 1000) * DPI) / 1000.0f;
00143 estado.velocidade = Vetor<float>();
00144 estado.velocidade_angular = 0.0f;
00145 estado.filhos = 0;
00146
00147 estado.posicaoSegmentos = new float[numero_segmentos];
00148 for (unsigned int c = 0; c < numero_segmentos; c++)
00149 {
00150 estado.posicaoSegmentos[c] = 0.0f;
00151 }
00152 }
00153
00154
00155
00157 Biota::Biota(const Biota &copia)
00158 {
00159 lineage = copia.lineage;
00160
00161
00162 genes = copia.genes;
00163 estado = copia.estado;
00164
00165
00166 numero_segmentos = copia.numero_segmentos;
00167 mundo = copia.mundo;
00168
00169
00170 estado.posicaoSegmentos = new float[numero_segmentos];
00171 for (unsigned int c = 0; c < numero_segmentos; c++)
00172 {
00173 estado.posicaoSegmentos[c] = 0.0f;
00174 }
00175
00176 genes.segmentos = new struct GenesSegmento[numero_segmentos];
00177 for (unsigned int c = 0; c < numero_segmentos; c++)
00178 genes.segmentos[c] = copia.genes.segmentos[c];
00179 }
00180
00181
00182
00184 Biota::Biota(void *mundoPai, Vetor<float> posicao, FILE *arquivo)
00185 {
00186 Biota((void*)mundoPai);
00187
00188 lineage = current_lineage++;
00189 abrir(arquivo);
00190
00191 estado.posicao = posicao;
00192 }
00193
00194
00195
00197 void Biota::destroy()
00198 {
00199
00200 delete genes.segmentos;
00201 delete estado.posicaoSegmentos;
00202 }
00203
00204
00205
00206
00208 enum ResultadoAtualizacao Biota::atualizar(void *noh)
00209 {
00210
00211 unsigned int massa_total = genes.massa_cabeca;
00212
00213
00214 Vetor<float> forca;
00215
00216
00217 float aceleracao_angular = 0.0f;
00218
00219
00220 for (unsigned int c = 0; c < numero_segmentos; c++)
00221 {
00222 float ang, vvetor;
00223
00224
00225 if (cos(estado.posicaoSegmentos[c]) < 0)
00226 estado.posicaoSegmentos[c] +=
00227 ((genes.segmentos[c].fa / genes.segmentos[c].massa) / genes.segmentos[c].comprimento) *
00228 VEL_SEGMENTO;
00229 else
00230 estado.posicaoSegmentos[c] +=
00231 ((genes.segmentos[c].fb / genes.segmentos[c].massa) / genes.segmentos[c].comprimento) *
00232 VEL_SEGMENTO;
00233
00234
00235 estado.posicaoSegmentos[c] = CORRIGE(estado.posicaoSegmentos[c]);
00236
00237
00238 if (cos(estado.posicaoSegmentos[c]) < 0)
00239 {
00240
00241
00242 vvetor = ((genes.segmentos[c].massa * genes.segmentos[c].fa*
00243 genes.segmentos[c].comprimento) * FLUIDEZ) * genes.segmentos[c].arco
00244 * (1.5 - ABS(sin(estado.posicaoSegmentos[c])));
00245
00246
00247 ang = PI+estado.angulo+genes.segmentos[c].angulo+((genes.segmentos[c].fa * FREIO_IMPULSO)*
00248 genes.segmentos[c].arco)+(sin(estado.posicaoSegmentos[c]) * (genes.segmentos[c].arco / 2.0f));
00249
00250
00251 aceleracao_angular += vvetor;
00252
00253
00254 estado.energia -= genes.segmentos[c].fa * vvetor * DISSIPACAO_ENERGETICA;
00255 }
00256 else
00257 {
00258
00259 vvetor = ((genes.segmentos[c].massa * genes.segmentos[c].fb*
00260 genes.segmentos[c].comprimento) * FLUIDEZ) * genes.segmentos[c].arco
00261 * (1.5 - ABS(sin(estado.posicaoSegmentos[c])));
00262
00263
00264 ang = PI+estado.angulo+genes.segmentos[c].angulo+((genes.segmentos[c].fb * FREIO_IMPULSO)*
00265 genes.segmentos[c].arco)+(sin(estado.posicaoSegmentos[c]) * (genes.segmentos[c].arco / 2.0f));
00266
00267
00268 aceleracao_angular -= vvetor;
00269
00270
00271 estado.energia -= genes.segmentos[c].fb * vvetor * DISSIPACAO_ENERGETICA;
00272 }
00273
00274
00275 massa_total += genes.segmentos[c].massa;
00276
00277
00278 forca += Vetor<float>(cos(ang), sin(ang)) * vvetor;
00279 }
00280
00281
00282 estado.velocidade += forca / massa_total;
00283 estado.velocidade_angular += aceleracao_angular / (VISCOSIDADE * massa_total);
00284
00285
00286 estado.posicao += estado.velocidade;
00287
00288
00289 estado.angulo += estado.velocidade_angular;
00290
00291
00292 estado.velocidade *= ATRITO;
00293 estado.velocidade_angular *= ATRITO_ANGULAR;
00294
00295
00296 estado.idade++;
00297
00298
00299 estado.energia -= PERDA_ENERGETICA_IDADE * estado.idade;
00300
00301
00302
00303
00304
00305 if (estado.posicao.X < (signed int)(genes.massa_cabeca + GROSSURA_PAREDE))
00306 {
00307 estado.posicao.X = genes.massa_cabeca + GROSSURA_PAREDE;
00308 estado.velocidade.X *= -1.0f;
00309
00310 estado.velocidade_angular += genes.angulo_colisao;
00311 }
00312 else if (estado.posicao.X > (signed int)(((Mundo*)mundo)->propriedades.tamanho_x - genes.massa_cabeca - GROSSURA_PAREDE))
00313 {
00314 estado.posicao.X = ((Mundo*)mundo)->propriedades.tamanho_x - genes.massa_cabeca - GROSSURA_PAREDE;
00315 estado.velocidade.X *= -1.0f;
00316
00317 estado.velocidade_angular += genes.angulo_colisao;
00318 }
00319 if (estado.posicao.Y < (signed int)(genes.massa_cabeca + GROSSURA_PAREDE))
00320 {
00321 estado.posicao.Y = genes.massa_cabeca + GROSSURA_PAREDE;
00322 estado.velocidade.Y *= -1.0f;
00323
00324 estado.velocidade_angular += genes.angulo_colisao;
00325 }
00326 else if (estado.posicao.Y > (signed int)(((Mundo*)mundo)->propriedades.tamanho_y - genes.massa_cabeca - GROSSURA_PAREDE))
00327 {
00328 estado.posicao.Y = ((Mundo*)mundo)->propriedades.tamanho_y - genes.massa_cabeca - GROSSURA_PAREDE;
00329 estado.velocidade.Y *= -1.0f;
00330
00331 estado.velocidade_angular += genes.angulo_colisao;
00332 }
00333
00334
00335
00336
00337
00338
00339 for (struct NohParede *percorre = ((Mundo*)mundo)->nohCabecaParedes.proximo;
00340 percorre != NULL;
00341 percorre = percorre->proximo)
00342 {
00343 Vetor<float> u = estado.posicao - percorre->inicio;
00344 Vetor<float> v = percorre->fim - percorre->inicio;
00345 Vetor<float> proj = (v.modulo() == 0)? estado.posicao : (
00346 (v / v.modulo ()) *
00347 (((u.X * v.X)+(u.Y * v.Y)) / v.modulo()) );
00348
00349 proj += percorre->inicio;
00350
00351
00352 if (proj.X > percorre->inicio.X && proj.X > percorre->fim.X)
00353 proj = (percorre->inicio.X > percorre->fim.X)? percorre->inicio : percorre->fim;
00354 else if (proj.X < percorre->inicio.X && proj.X < percorre->fim.X)
00355 proj = (percorre->inicio.X < percorre->fim.X)? percorre->inicio : percorre->fim;
00356 else if (proj.Y > percorre->inicio.Y && proj.Y > percorre->fim.Y)
00357 proj = (percorre->inicio.Y > percorre->fim.Y)? percorre->inicio : percorre->fim;
00358 else if (proj.Y < percorre->inicio.Y && proj.Y < percorre->fim.Y)
00359 proj = (percorre->inicio.Y < percorre->fim.Y)? percorre->inicio : percorre->fim;
00360
00361
00362 if (estado.posicao.distancia(proj) <=
00363 genes.massa_cabeca + GROSSURA_PAREDE)
00364 {
00365
00366
00367 float ang = (estado.posicao.Y - proj.Y == 0 && estado.posicao.X - proj.X == 0)? 0.0f :
00368 atan2(estado.posicao.Y - proj.Y, estado.posicao.X - proj.X);
00369
00370
00371 estado.posicao += Vetor<float>(cos(ang),sin(ang)) *
00372 ((genes.massa_cabeca + GROSSURA_PAREDE) - estado.posicao.distancia(proj));
00373
00374
00375 float dist = estado.posicao.distancia(proj);
00376 Vetor<float> acel = (estado.posicao - proj) / dist;
00377
00378 u = (estado.posicao+estado.velocidade) - percorre->inicio;
00379 v = percorre->fim - percorre->inicio;
00380 Vetor<float> proj = (v.modulo() == 0)? estado.posicao : (
00381 (v / v.modulo ()) *
00382 (((u.X * v.X)+(u.Y * v.Y)) / v.modulo()) );
00383 proj += percorre->inicio;
00384
00385 acel *= (dist - (estado.posicao+estado.velocidade).distancia(proj))*2.0f;
00386 estado.velocidade += acel;
00387
00388
00389 estado.velocidade_angular += genes.angulo_colisao;
00390 }
00391 }
00392
00393
00394
00395
00396
00397
00398 for (struct Mundo::NohBiota *percorre = ((Mundo::NohBiota*)noh)->proximo;
00399 percorre != NULL;
00400 percorre = percorre->proximo)
00401 {
00402
00403 float distancia = estado.posicao.distancia(percorre->biota.estado.posicao);
00404
00405
00406 if (distancia <= genes.massa_cabeca + percorre->biota.genes.massa_cabeca)
00407 {
00408
00409 estado.posicao -= (estado.posicao - percorre->biota.estado.posicao).reduzir() *
00410 ((distancia - (genes.massa_cabeca + percorre->biota.genes.massa_cabeca))/2.0f);
00411 percorre->biota.estado.posicao += (estado.posicao - percorre->biota.estado.posicao).reduzir() *
00412 ((distancia - (genes.massa_cabeca + percorre->biota.genes.massa_cabeca))/2.0f);
00413
00414
00415 if (distancia > 0.0f)
00416 {
00417 Vetor<float> tA, tB;
00418
00419 if (estado.velocidade.Y != 0 || estado.velocidade.X != 0)
00420 tA = (estado.posicao - percorre->biota.estado.posicao).reduzir() *
00421 (cos(atan2(estado.posicao.Y - percorre->biota.estado.posicao.Y,
00422 estado.posicao.X - percorre->biota.estado.posicao.X) -
00423 atan2(estado.velocidade.Y, estado.velocidade.X)) *
00424 sqrt((estado.velocidade.X*estado.velocidade.X)+(estado.velocidade.Y*estado.velocidade.Y)));
00425
00426 if (percorre->biota.estado.velocidade.Y != 0 || percorre->biota.estado.velocidade.X != 0)
00427 tB = (estado.posicao - percorre->biota.estado.posicao).reduzir() *
00428 (cos(atan2(estado.posicao.Y - percorre->biota.estado.posicao.Y,
00429 estado.posicao.X - percorre->biota.estado.posicao.X) -
00430 atan2(percorre->biota.estado.velocidade.Y, percorre->biota.estado.velocidade.X)) *
00431 sqrt((percorre->biota.estado.velocidade.X*percorre->biota.estado.velocidade.X)+
00432 (percorre->biota.estado.velocidade.Y*percorre->biota.estado.velocidade.Y)));
00433
00434
00435
00436 tA *= genes.massa_cabeca/percorre->biota.genes.massa_cabeca;
00437 tB *= percorre->biota.genes.massa_cabeca/genes.massa_cabeca;
00438
00439
00440 estado.velocidade -= tA * 1.5f;
00441 percorre->biota.estado.velocidade -= tB * 1.5f;
00442
00443 percorre->biota.estado.velocidade += tA * 1.5f;
00444 estado.velocidade += tB * 1.5f;
00445 }
00446
00447
00448 float troca;
00449 troca = estado.velocidade_angular;
00450 estado.velocidade_angular = -percorre->biota.estado.velocidade_angular;
00451 percorre->biota.estado.velocidade_angular = -troca;
00452
00453 }
00454 }
00455
00456
00457
00458
00459
00460 unsigned int menor_distancia = ((Mundo*)mundo)->propriedades.tamanho_x;
00461 float angulo_grao = 0.0f;
00462
00463
00464 struct NohGrao *percorre = &(((Mundo*)mundo)->nohCabecaGraos);
00465 while(percorre->proximo != NULL)
00466 {
00467 unsigned int distancia = (unsigned int)percorre->proximo->posicao.distancia(estado.posicao);
00468
00469 if (distancia <= (unsigned int)(genes.massa_cabeca + RAIO_GRAO))
00470 {
00471
00472 struct NohGrao *remover = percorre->proximo;
00473 percorre->proximo = percorre->proximo->proximo;
00474
00475
00476 if (remover == ((Mundo*)mundo)->finalGraos)
00477 ((Mundo*)mundo)->finalGraos = percorre;
00478
00479 if (remover == ((Mundo*)mundo)->grao_selecionado)
00480 ((Mundo*)mundo)->grao_selecionado = NULL;
00481
00482 delete remover;
00483 ((Mundo*)mundo)->estatisticas.numero_graos--;
00484
00485
00486 estado.energia += ((Mundo*)mundo)->propriedades.energia_grao;
00487 break;
00488 }
00489
00490 else if (distancia <= genes.massa_cabeca * FATOR_PERCEPCAO_GRAOS &&
00491 distancia < menor_distancia)
00492 {
00493
00494 bool grao_visivel = true;
00495
00496 for (struct NohParede *percorre_par = ((Mundo*)mundo)->nohCabecaParedes.proximo;
00497 percorre_par != NULL;
00498 percorre_par = percorre_par->proximo)
00499 if (XOR(ESQUERDA(percorre_par->inicio,percorre_par->fim,percorre->proximo->posicao),
00500 ESQUERDA(percorre_par->inicio,percorre_par->fim,estado.posicao)) &&
00501 XOR(ESQUERDA(percorre->proximo->posicao,estado.posicao,percorre_par->inicio),
00502 ESQUERDA(percorre->proximo->posicao,estado.posicao,percorre_par->fim)))
00503 {
00504
00505 grao_visivel = false;
00506 break;
00507 }
00508
00509 if (grao_visivel)
00510 {
00511
00512 menor_distancia = distancia;
00513 angulo_grao = atan2(percorre->proximo->posicao.Y - estado.posicao.Y,
00514 percorre->proximo->posicao.X - estado.posicao.X);
00515 }
00516 }
00517 percorre = percorre->proximo;
00518 }
00519
00520
00521 estado.angulo = CORRIGE(estado.angulo);
00522
00523
00524 if (menor_distancia < ((Mundo*)mundo)->propriedades.tamanho_x)
00525 {
00526
00527 angulo_grao = CORRIGE(angulo_grao);
00528
00529
00530 if (ABS(estado.angulo - angulo_grao) < PI)
00531 {
00532 if (ABS(estado.angulo - angulo_grao) < ACEL_GIRO)
00533 estado.velocidade_angular -= estado.angulo - angulo_grao;
00534 else if (estado.angulo > angulo_grao)
00535 estado.velocidade_angular -= ACEL_GIRO;
00536 else
00537 estado.velocidade_angular += ACEL_GIRO;
00538 }
00539 else if (estado.angulo > angulo_grao)
00540 {
00541 if ((DPI - estado.angulo) + angulo_grao <= ACEL_GIRO)
00542 estado.velocidade_angular += (DPI - estado.angulo) + angulo_grao;
00543 else
00544 estado.velocidade_angular += ACEL_GIRO;
00545 }
00546 else
00547 {
00548 if ((DPI - angulo_grao) + estado.angulo <= ACEL_GIRO)
00549 estado.velocidade_angular -= (DPI - angulo_grao) + estado.angulo;
00550 else
00551 estado.velocidade_angular -= ACEL_GIRO;
00552 }
00553
00554
00555 estado.energia -= (genes.massa_cabeca * (estado.velocidade_angular/QPI)) * PERDA_ENERGIA_CABECA;
00556 }
00557
00558
00559 estado.velocidade_angular = CORRIGE2(estado.velocidade_angular);
00560
00561
00562 return (estado.energia < 0.0f)? MORTE :
00563 ((estado.energia > genes.limiar_reproducao)? REPRODUCAO : NORMAL);
00564 }
00565
00566
00567
00569 void Biota::mutacao()
00570 {
00571 #define CABECA -1
00572
00573 for (unsigned int x = 0; x < ((Mundo*)mundo)->propriedades.intensidade_mutacao; x++)
00574 {
00575
00576 int mutacao = CABECA;
00577 int tendencia = (rand() % 2 == 0)? -1 : 1;
00578 int indice = rand() % (7 + numero_segmentos);
00579
00580 switch (indice)
00581 {
00582 case 0:
00583 genes.massa_cabeca += normal();
00584 if (genes.massa_cabeca <= 0)
00585 genes.massa_cabeca = 1;
00586 break;
00587 case 1:
00588 genes.limiar_reproducao += normal();
00589 if (genes.limiar_reproducao <= 0)
00590 genes.limiar_reproducao = 1;
00591 break;
00592 case 2:
00593 genes.distribuicao_energia += normal() * 100.0f;
00594 if (genes.distribuicao_energia < 0.01f)
00595 genes.distribuicao_energia = 0.01f;
00596 else if (genes.distribuicao_energia > 1.0f)
00597 genes.distribuicao_energia = 1.0f;
00598 break;
00599 case 3:
00600
00601 if (rand() % 1000 > (numero_segmentos-1) * 500.0f / MEDIA_SEGMENTOS)
00602 {
00603
00604 struct GenesSegmento *novosSegmentos =
00605 new struct GenesSegmento[numero_segmentos+1];
00606 float *novosEstados = new float[numero_segmentos+1];
00607
00608 for (int s = 0; (unsigned int)s < numero_segmentos; s++)
00609 {
00610 novosSegmentos[s] = genes.segmentos[s];
00611 novosEstados[s] = 0.0f;
00612 }
00613
00614 novosSegmentos[numero_segmentos].arco = ((rand() % 1000)*(QPI/2.0f))/1000.0f;
00615 novosSegmentos[numero_segmentos].massa = 1 + (rand() % 11);
00616 novosSegmentos[numero_segmentos].comprimento = 10 + (rand() % 20);
00617 novosSegmentos[numero_segmentos].angulo = (QPI/2.0f) + (((rand() % 1000)*(PI+QPI))/1000.0f);
00618 novosSegmentos[numero_segmentos].cor[0] = rand() % 255;
00619 novosSegmentos[numero_segmentos].cor[1] = rand() % 255;
00620 novosSegmentos[numero_segmentos].cor[2] = rand() % 255;
00621 novosSegmentos[numero_segmentos].fa = 20 + (rand() % 100);
00622 novosSegmentos[numero_segmentos].fb = 20 + (rand() % 100);
00623
00624 numero_segmentos++;
00625
00626 delete genes.segmentos;
00627 genes.segmentos = novosSegmentos;
00628
00629 delete estado.posicaoSegmentos;
00630 estado.posicaoSegmentos = novosEstados;
00631 }
00632 else
00633 {
00634
00635 if (numero_segmentos == 1)
00636 break;
00637 struct GenesSegmento *novosSegmentos =
00638 new struct GenesSegmento[numero_segmentos-1];
00639 float *novosEstados = new float[numero_segmentos-1];
00640 unsigned int remover = rand() % numero_segmentos;
00641
00642 for (unsigned int s = 0, n = 0; s < numero_segmentos; s++)
00643 if (s != remover)
00644 {
00645 novosEstados[n] = 0.0f;
00646 novosSegmentos[n] = genes.segmentos[s];
00647 n++;
00648 }
00649
00650 numero_segmentos--;
00651
00652 delete genes.segmentos;
00653 genes.segmentos = novosSegmentos;
00654
00655 delete estado.posicaoSegmentos;
00656 estado.posicaoSegmentos = novosEstados;
00657 }
00658 break;
00659 case 5:
00660 genes.angulo_reproducao += normal() * 10.0f;
00661 genes.angulo_reproducao = CORRIGE2(genes.angulo_reproducao);
00662 break;
00663
00664 case 6:
00665 genes.angulo_colisao += normal() * 10.0f;
00666 genes.angulo_colisao = CORRIGE2(genes.angulo_colisao);
00667 break;
00668 default:
00669 unsigned int c = rand() % numero_segmentos;
00670 mutacao = c;
00671 switch (rand() % 6)
00672 {
00673 case 0:
00674 genes.segmentos[c].arco += normal() * 10.0f;
00675 if (genes.segmentos[c].arco < 0.0f)
00676 genes.segmentos[c].arco = 0.0f;
00677 break;
00678 case 1:
00679 genes.segmentos[c].comprimento += normal();
00680 if (genes.segmentos[c].comprimento <= 0)
00681 genes.segmentos[c].comprimento = 1;
00682 break;
00683 case 2:
00684 genes.segmentos[c].massa += normal();
00685 if (genes.segmentos[c].massa <= 0)
00686 genes.segmentos[c].massa = 1;
00687 break;
00688 case 3:
00689 genes.segmentos[c].angulo += normal() * 10.0f;
00690 if (genes.segmentos[c].angulo < 0.0f)
00691 genes.segmentos[c].angulo = 0.0f;
00692 break;
00693 case 4:
00694 genes.segmentos[c].fa += normal() * 10.0f;
00695 if (genes.segmentos[c].fa < 0.0f)
00696 genes.segmentos[c].fa = 0.0f;
00697 break;
00698 case 5:
00699 genes.segmentos[c].fb += normal() * 10.0f;
00700 if (genes.segmentos[c].fb < 0.0f)
00701 genes.segmentos[c].fb = 0.0f;
00702 break;
00703 }
00704 break;
00705 }
00706
00707 #define TAXA_COR 10
00708
00709 indice %= 3;
00710
00711
00712 if (mutacao == CABECA)
00713 {
00714 if (genes.cor_cabeca[indice] > TAXA_COR && tendencia < 0)
00715 genes.cor_cabeca[indice] -= TAXA_COR;
00716 else if (genes.cor_cabeca[indice] < 255-TAXA_COR)
00717 genes.cor_cabeca[indice] += TAXA_COR;
00718 }
00719 else
00720 {
00721 if (genes.segmentos[mutacao].cor[indice] > TAXA_COR && tendencia < 0)
00722 genes.segmentos[mutacao].cor[indice] -= TAXA_COR;
00723 else if (genes.segmentos[mutacao].cor[indice] < 255-TAXA_COR)
00724 genes.segmentos[mutacao].cor[indice] += TAXA_COR;
00725 }
00726
00727 }
00728 }
00729
00730
00731
00733 bool Biota::selecionar(Vetor<float> posicao)
00734 {
00735 return (posicao.distancia(estado.posicao) <= genes.massa_cabeca * FATOR_SELECAO);
00736 }
00737
00738
00739
00741 void Biota::salvar(FILE* arquivo, bool saveState, int ident)
00742 {
00743 if (ident == 0)
00744 {
00745 fprintf(arquivo, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
00746 fprintf(arquivo, "<!DOCTYPE biot SYSTEM \"http://simvida.sourceforge.net/simvida.biot.dtd\">\n");
00747 }
00748
00749 char *tab = new char[ident+1];
00750 for (int c = 0; c < ident; c++) tab[c] = '\t';
00751 tab[ident] = '\0';
00752
00753 fprintf(arquivo, "%s<biot headcolor=\"%d;%d;%d\" headmass=\"%d\" reproductionthreshold=\"%d\"\n", tab,
00754 genes.cor_cabeca[0],genes.cor_cabeca[1],genes.cor_cabeca[2], genes.massa_cabeca, genes.limiar_reproducao);
00755 fprintf(arquivo, "%s reproductionangle=\"%.4f\" energydistribution=\"%.4f\" colisionturnangle=\"%.4f\"", tab,
00756 genes.angulo_reproducao, genes.distribuicao_energia, genes.angulo_colisao);
00757
00758 if (saveState)
00759 {
00760 fprintf(arquivo, "\n%s position=\"%d;%d\" velocity=\"%.2f;%.2f\" angularvelocity=\"%.4f\" anglecicle=\"%.4f\"\n", tab,
00761 (int)estado.posicao.X, (int)estado.posicao.Y, estado.velocidade.X, estado.velocidade.Y, estado.velocidade_angular, estado.angulo);
00762 fprintf(arquivo, "%s energy=\"%.4f\" age=\"%d\" generation=\"%d\" offsprings=\"%d\"", tab,
00763 estado.energia, estado.idade, estado.geracao, estado.filhos);
00764 }
00765 fprintf(arquivo, ">\n");
00766
00767 for (unsigned int c = 0; c < numero_segmentos; c++)
00768 {
00769 fprintf(arquivo, "%s\t<segment color=\"%d;%d;%d\" mass=\"%d\" angle=\"%.4f\" length=\"%d\" arcangle=\"%.4f\" forces=\"%.4f;%.4f\"", tab,
00770 genes.segmentos[c].cor[0],genes.segmentos[c].cor[1],genes.segmentos[c].cor[2],
00771 genes.segmentos[c].massa, genes.segmentos[c].angulo, genes.segmentos[c].comprimento,
00772 genes.segmentos[c].arco, genes.segmentos[c].fa, genes.segmentos[c].fb);
00773 if (saveState)
00774 {
00775 fprintf(arquivo, " angleposition=\"%.4f\"", estado.posicaoSegmentos[c]);
00776 }
00777 fprintf(arquivo, "/>\n");
00778 }
00779 fprintf(arquivo, "%s</biot>\n", tab);
00780 }
00781
00782
00783
00785 void Biota::abrir(FILE* arquivo)
00786 {
00787 QDomDocument xmlDocument;
00788 QFile file;
00789 file.open(arquivo, QIODevice::ReadOnly);
00790 xmlDocument.setContent(&file);
00791 file.close();
00792
00793 QDomNodeList children = xmlDocument.childNodes();
00794 for (int i=0; i < children.count(); i++)
00795 {
00796
00797 QDomElement element = children.at(i).toElement();
00798 if (!element.isNull() && element.tagName() == "biot")
00799 {
00800 abrir(element);
00801 break;
00802 }
00803 }
00804
00805 xmlDocument.clear();
00806
00807
00808 estado.energia = genes.limiar_reproducao-1;
00809 }
00810
00811
00812
00814 void Biota::abrir(QDomNode xmlNode)
00815 {
00816
00817 QDomElement element = xmlNode.toElement();
00818 if (!element.isNull() && element.tagName() == "biot")
00819 {
00820 QStringList headcolor = element.attribute("headcolor").split(";");
00821 genes.cor_cabeca[0] = headcolor.at(0).toInt();
00822 genes.cor_cabeca[1] = headcolor.at(1).toInt();
00823 genes.cor_cabeca[2] = headcolor.at(2).toInt();
00824
00825 genes.massa_cabeca = element.attribute("headmass").toInt();
00826 genes.limiar_reproducao = element.attribute("reproductionthreshold").toInt();
00827 genes.distribuicao_energia = element.attribute("energydistribution").toFloat();
00828 genes.angulo_reproducao = element.attribute("reproductionangle").toFloat();
00829 genes.angulo_colisao = element.attribute("colisionturnangle").toFloat();
00830
00831 QStringList position = element.attribute("position", "0;0").split(";");
00832 estado.posicao.X = position.at(0).toFloat();
00833 estado.posicao.Y = position.at(1).toFloat();
00834
00835 QStringList velocity = element.attribute("velocity", "0;0").split(";");
00836 estado.velocidade.X = velocity.at(0).toFloat();
00837 estado.velocidade.Y = velocity.at(1).toFloat();
00838
00839 estado.velocidade_angular = element.attribute("angularvelocity", "0").toFloat();
00840 estado.angulo = element.attribute("anglecicle", "0").toFloat();
00841 estado.geracao = element.attribute("generation", "1").toInt();
00842 estado.filhos = element.attribute("offsprings", "0").toInt();
00843 estado.idade = element.attribute("age", "0").toInt();
00844 estado.energia = element.attribute("energy", QString::number(genes.limiar_reproducao-1)).toFloat();
00845
00846 QDomNodeList biotChildren = element.childNodes();
00847 numero_segmentos = biotChildren.count();
00848
00849 genes.segmentos = new struct GenesSegmento[numero_segmentos];
00850 estado.posicaoSegmentos = new float[numero_segmentos];
00851
00852 for (int j=0; j < biotChildren.count(); j++)
00853 {
00854
00855 QDomElement segment = biotChildren.at(j).toElement();
00856 if (!segment.isNull() && segment.tagName() == "segment")
00857 {
00858 genes.segmentos[j].arco = segment.attribute("arcangle").toFloat();
00859 genes.segmentos[j].comprimento = segment.attribute("length").toInt();
00860 genes.segmentos[j].massa = segment.attribute("mass").toInt();
00861 genes.segmentos[j].angulo = segment.attribute("angle").toFloat();
00862
00863 estado.posicaoSegmentos[j] = segment.attribute("angleposition").toFloat();
00864
00865 QStringList segcolor = segment.attribute("color").split(";");
00866 genes.segmentos[j].cor[0] = segcolor.at(0).toInt();
00867 genes.segmentos[j].cor[1] = segcolor.at(1).toInt();
00868 genes.segmentos[j].cor[2] = segcolor.at(2).toInt();
00869
00870 QStringList forces = segment.attribute("forces").split(";");
00871 genes.segmentos[j].fa = forces.at(0).toFloat();
00872 genes.segmentos[j].fb = forces.at(1).toFloat();
00873 }
00874 }
00875 }
00876 }
00877
00878
00879
00881 void Biota::posicionar(Vetor<float> posicao)
00882 {
00883 estado.posicao = posicao;
00884 }
00885
00886
00887
00889 void Biota::acelerar(Vetor<float> aceleracao)
00890 {
00891 estado.velocidade += aceleracao;
00892 }
00893
00894
00895
00897 void Biota::refletir()
00898 {
00899 genes.angulo_reproducao = -genes.angulo_reproducao;
00900 genes.angulo_colisao = -genes.angulo_colisao;
00901
00902 for (unsigned int c = 0; c < numero_segmentos; c++)
00903 {
00904 genes.segmentos[c].angulo = CORRIGE(-genes.segmentos[c].angulo);
00905
00906 float troca;
00907 troca = genes.segmentos[c].fa;
00908 genes.segmentos[c].fa = genes.segmentos[c].fb;
00909 genes.segmentos[c].fb = troca;
00910
00911 estado.posicaoSegmentos[c] += PI;
00912 }
00913 }
00914
00915