biota.cpp

Ir para a documentação deste ficheiro.
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 /* Construtores */
00071 Biota::Biota()
00072 {
00073     lineage = current_lineage++;
00074 
00075     mundo = NULL;
00076     numero_segmentos = 0;
00077 
00078     /* Zera estrutura de genes */
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     /* Zera estrutura do estado */
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     /* Cria genes aleatoriamente */
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     /* Seta estado inicial padrao */
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     /* Copia genes e estado */
00162     genes = copia.genes;
00163     estado = copia.estado;
00164 
00165     /* Copia numero de segmentos */
00166     numero_segmentos = copia.numero_segmentos;
00167     mundo = copia.mundo;
00168 
00169     /* Copia vetor de genes e estados */
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     /* Libera memoria */
00200     delete genes.segmentos;
00201     delete estado.posicaoSegmentos;
00202 }
00203 
00204 /******************************************************************************/
00205 
00206 /* Metodos */
00208 enum ResultadoAtualizacao Biota::atualizar(void *noh)
00209 {
00210     /* massa total */
00211     unsigned int massa_total = genes.massa_cabeca;
00212 
00213     /* Forca de movimentacao */
00214     Vetor<float> forca;
00215 
00216     /* Aceleracao angular */
00217     float aceleracao_angular = 0.0f;
00218 
00219     /* Atualiza estado do biota */
00220     for (unsigned int c = 0; c < numero_segmentos; c++)
00221     {
00222         float ang, vvetor;
00223 
00224         /* move segmento de acordo com a força */
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         /* Corrige angulo */
00235         estado.posicaoSegmentos[c] = CORRIGE(estado.posicaoSegmentos[c]);
00236 
00237         /* Calcula todo resto */
00238         if (cos(estado.posicaoSegmentos[c]) < 0)
00239         {
00240 
00241             /* Calcula forca da remada do segmento */
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             /* Calcula angulo da remada do segmento */
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             /* Acrecenta velocidade angular */
00251             aceleracao_angular += vvetor;
00252 
00253             /* Perde energia */
00254             estado.energia -= genes.segmentos[c].fa * vvetor * DISSIPACAO_ENERGETICA;
00255         }
00256         else
00257         {
00258             /* Calcula forca da remada do segmento */
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             /* Calcula angulo da remada do segmento */
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             /* Acrecenta velocidade angular */
00268             aceleracao_angular -= vvetor;
00269 
00270             /* Perde energia */
00271             estado.energia -= genes.segmentos[c].fb * vvetor * DISSIPACAO_ENERGETICA;
00272         }
00273 
00274         /* Soma a massa total */
00275         massa_total += genes.segmentos[c].massa;
00276 
00277         /* Soma s velocidade a aceleracao */
00278         forca += Vetor<float>(cos(ang), sin(ang)) * vvetor;
00279     }
00280 
00281     /* Atualiza velocidade */
00282     estado.velocidade += forca / massa_total;
00283     estado.velocidade_angular += aceleracao_angular / (VISCOSIDADE * massa_total);
00284 
00285     /* Atualiza posicao */
00286     estado.posicao += estado.velocidade;
00287 
00288     /* Atualiza angulo */
00289     estado.angulo += estado.velocidade_angular;
00290 
00291     /* Aplica atrito as velocidades */
00292     estado.velocidade *= ATRITO;
00293     estado.velocidade_angular *= ATRITO_ANGULAR;
00294 
00295     /* Incrementa idade do biota */
00296     estado.idade++;
00297 
00298     /* Perde energia de acordo com idade */
00299     estado.energia -= PERDA_ENERGETICA_IDADE * estado.idade;
00300 
00301     /**********************************************************************/
00302     /* Trata colisoes com os limites */
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     /* Trata colisao com as paredes */
00336     /**********************************************************************/
00337 
00338     /* Percorre lista de paredes */
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         /* Corrige limites da parede */
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         /* Testa distancia */
00362         if (estado.posicao.distancia(proj) <=
00363         genes.massa_cabeca + GROSSURA_PAREDE)
00364         {
00365             /* Colisao */
00366             /* Calcula angulo de colisao */
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             /* Reajusta posicao */
00371             estado.posicao += Vetor<float>(cos(ang),sin(ang)) *
00372             ((genes.massa_cabeca + GROSSURA_PAREDE) - estado.posicao.distancia(proj));
00373 
00374             /* Reajusta velocidade */
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             /* Muda angulo */
00389             estado.velocidade_angular += genes.angulo_colisao;
00390         }
00391     }
00392 
00393     /**********************************************************************/
00394     /* Trata colisao com outros biotas */
00395     /**********************************************************************/
00396 
00397     /* Percorre noh a partir do atual */
00398     for (struct Mundo::NohBiota *percorre = ((Mundo::NohBiota*)noh)->proximo;
00399     percorre != NULL;
00400     percorre = percorre->proximo)
00401     {
00402         /* calcula distancia */
00403         float distancia = estado.posicao.distancia(percorre->biota.estado.posicao);
00404 
00405         /* Verifica se distancia eh colisiva */
00406         if (distancia <= genes.massa_cabeca + percorre->biota.genes.massa_cabeca)
00407         {
00408             /* Modifica posicao */
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             /* Modifica velocidade */
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                 /* Aplica formulas de quantidade de movimento */
00436                 tA *= genes.massa_cabeca/percorre->biota.genes.massa_cabeca;
00437                 tB *= percorre->biota.genes.massa_cabeca/genes.massa_cabeca;
00438 
00439                 /* Transfere energias */
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             /* Troca velocidades angulares */
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     /* Verifica colisao com grao de comida ou perseguicao a grao de comida*/
00459     /**********************************************************************/
00460     unsigned int menor_distancia = ((Mundo*)mundo)->propriedades.tamanho_x;
00461     float angulo_grao = 0.0f;
00462 
00463     /* Percorre graos de comida */
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         /* Se tocou no grao */
00469         if (distancia <= (unsigned int)(genes.massa_cabeca + RAIO_GRAO))
00470         {
00471             /* Remove grao especifico da lista */
00472             struct NohGrao *remover = percorre->proximo;
00473             percorre->proximo = percorre->proximo->proximo;
00474 
00475             /* Corrige caso seja final da lista */
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             /* Acrescenta energia */
00486             estado.energia += ((Mundo*)mundo)->propriedades.energia_grao;
00487             break;
00488         }
00489         /* Se este eh o mais proximo encontrado, esta a vista e nao houve colisao */
00490         else if (distancia <= genes.massa_cabeca * FATOR_PERCEPCAO_GRAOS &&
00491         distancia < menor_distancia)
00492         {
00493             /* Verifica se nao ha nenhuma parede a vista */
00494             bool grao_visivel = true;
00495             /* Percorre lista de paredes */
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                     /* Intersecccao ! */
00505                     grao_visivel = false;
00506                     break;
00507                 }
00508 
00509             if (grao_visivel)
00510             {
00511                 /* Este eh o grao mais proximo */
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     /* Efetua correcao do angulo */
00521     estado.angulo = CORRIGE(estado.angulo);
00522 
00523     /* Se encontrou um grao proximo */
00524     if (menor_distancia < ((Mundo*)mundo)->propriedades.tamanho_x)
00525     {
00526         /* Efetua correcao do angulo */
00527         angulo_grao = CORRIGE(angulo_grao);
00528 
00529         /* Gira cabeca em direcao ao grao localizado */
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         /* Retira energia gasta por isso */
00555         estado.energia -= (genes.massa_cabeca * (estado.velocidade_angular/QPI)) * PERDA_ENERGIA_CABECA;
00556     }
00557 
00558     /* Corrige angulo */
00559     estado.velocidade_angular = CORRIGE2(estado.velocidade_angular);
00560 
00561     /* Retorna estado */
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         /* flag de mutacao para cor */
00576         int mutacao = CABECA; /* Mutacao na 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                 /* Decide se vai ganhar ou perder um segmento */
00601                 if (rand() % 1000 > (numero_segmentos-1) * 500.0f / MEDIA_SEGMENTOS)
00602                 {
00603                     /* Ganha segmento */
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                     /* Perde segmento */
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; /* Mutacao no segmento dado */
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         /* Muda cor */
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         /* try to convert the node to an element. */
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     /* Seta estado inicial */
00808     estado.energia = genes.limiar_reproducao-1;
00809 }
00810 
00811 /******************************************************************************/
00812 
00814 void Biota::abrir(QDomNode xmlNode)
00815 {
00816     /* try to convert the node to an element. */
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             /* try to convert the node to an element. */
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 /******************************************************************************/

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