遺傳算法

爲了hollow遊戲 各個關卡通關。需要一種算法找到block move路徑。開始考慮A*算法,以及相關的深度優先搜索或者廣度優先搜索,可是這種搜索算法需要do one move,back one move兩種過程,hollow遊戲中back one move需要記錄n多信息。最後決定用遺傳學算法,不需做back one move處理。以下內容來自 百度百科 ''遺傳算法" 

 遺傳算法是基於生物學的,理解或編程都不太難。下面是遺傳算法的一般算法:

創建一個隨機的初始狀態
初始種羣是從解中隨機選擇出來的,將這些解比喻爲染色體或基因,該種羣被稱爲第一代,這和符號人工智能系統的情況不一樣,在那裏問題的初始狀態已經給定了。

評估適應度
對每一個解(染色體)指定一個適應度的值,根據問題求解的實際接近程度來指定(以便逼近求解問題的答案)。不要把這些“解”與問題的“答案”混爲一談,可以把它理解成爲要得到答案,系統可能需要利用的那些特性。

繁殖(包括子代突變)
帶有較高適應度值的那些染色體更可能產生後代(後代產生後也將發生突變)。後代是父母的產物,他們由來自父母的基因結合而成,這個過程被稱爲“雜交”。

下一代
如果新的一代包含一個解,能產生一個充分接近或等於期望答案的輸出,那麼問題就已經解決了。如果情況並非如此,新的一代將重複他們父母所進行的繁衍過程,一代一代演化下去,直到達到期望的解爲止。

並行計算
非常容易將遺傳算法用到並行計算和羣集環境中。一種方法是直接把每個節點當成一個並行的種羣看待。然後有機體根據不同的繁殖方法從一個節點遷移到另一個節點。另一種方法是“農場主/勞工”體系結構,指定一個節點爲“農場主”節點,負責選擇有機體和分派適應度的值,另外的節點作爲“勞工”節點,負責重新組合、變異和適應度函數的評估。

一個遺傳學編程實例

---------來個例子,大家好理解------------
                               基於遺傳算法的人工生命模擬
#include<stdio.h>
#include<stdlib.h>
#include<graphics.h>
#include<math.h>
#include<time.h>
#include<string.h>
#include "graph.c"
/* 宏定義 */
#define TL1      20          /* 植物性食物限制時間 */
#define TL2      5           /* 動物性食物限制時間 */
#define NEWFOODS 3           /* 植物性食物每代生成數目  */
#define MUTATION 0.05        /* 變異概率     */
#define G_LENGTH  32         /* 個體染色體長度  */
#define MAX_POP  100         /* 個體總數的最大值  */
#define MAX_FOOD 100         /* 食物總數的最大值  */
#define MAX_WX    60         /* 虛擬環境的長度最大值 */
#define MAX_WY    32         /* 虛擬環境的寬度最大值 */
#define SX1      330         /* 虛擬環境圖左上角點x座標  */
#define SY1      40          /* 虛擬環境圖左上角點y座標  */
#define GX       360         /* 個體數進化圖形窗口的左上角點X座標  */
#define GY       257         /* 個體數進化圖形窗口的左上角點Y座標  */
#define GXR      250         /* 個體數進化圖形窗口的長度    */
#define GYR      100         /* 個體數進化圖形窗口的寬度    */
#define GSTEP     2          /* 個體數進化圖形窗口的X方向步長    */
#define R_LIFE  0.05         /* 初期產生生物數的環境比率 */
#define R_FOOD  0.02         /* 初期產生食物數的環境比率 */
#define SL_MIN    10         /* 個體壽命最小值   */
/* 全局變量 */
unsigned  char  gene[MAX_POP][G_LENGTH];     /* 遺傳基因      */
unsigned  char  iflg[MAX_POP];               /* 個體死活狀態標誌變量  */
unsigned  char  fflg[MAX_FOOD];              /* 食物有無狀態標誌變量  */
unsigned  char  world[MAX_WX][MAX_WY];       /* 虛擬環境的數據    */
unsigned char                                /* 各中行爲模式數據 */
life1[5][5]={{0,0,1,0,0},{0,1,0,1,0},{1,0,0,0,1},{0,1,0,1,0},{0,0,1,0,0}};
unsigned char
life2[5][5]={{1,1,1,1,1},{1,0,0,0,1},{1,0,0,0,1},{1,0,0,0,1},{1,1,1,1,1}};
unsigned char
food1[5][5]={{0,0,0,1,0},{0,0,1,1,0},{0,1,0,1,0},{0,0,1,1,0},{0,0,0,1,0}};
unsigned char
food2[5][5]={{0,0,0,1,0},{0,0,1,1,0},{0,1,1,1,0},{0,0,1,1,0},{0,0,0,1,0}};
int pop_size;                   /* 個體總數   */
int iatr[MAX_POP][4];           /* 個體屬性   */
                                /* iatr[][0]  個體當前位置x座標  */
                                /* iatr[][1]  個體當前位置y座標  */
                                /* iatr[][2]  內部能量  */
                                /* iatr[][3]  年齡屬性  */
int food_size;                  /* 食物總數  */
int fatr[MAX_FOOD][4];          /* 食物屬性  */
                                /* fatr[][0]  食物當前位置x座標  */
                                /* fatr[][1]  食物當前位置y座標  */
                                /* fatr[][2]=0 : 植物性 =1:動物性 */
                                /* fatr[][3]  新鮮程度    */
int wx,wy;                      /* 虛擬環境的長寬度  */

void uni_crossover(gene,g1,g2,g3,ratio1,g_length)    /* 均勻交叉 */
unsigned char *gene;                                 /* 遺傳基因 */
int g1,g2,g3;                                        /* g1 g2 父個體編號  g3 子個體編號  */
double ratio1;                                       /*  父個體g1被選中的概率  */
int g_length;                                        /* 個體遺傳基因的位長  */
{
   unsigned char *gene1;        /*  父1遺傳基因的指針 */
   unsigned char *gene2;        /*  父2遺傳基因的指針 */
   unsigned char *gene3;        /*  子遺傳基因的指針 */
   double rnd,r1;
   int i;
   gene1=gene+g_length*g1;
   gene2=gene+g_length*g2;
   gene3=gene+g_length*g3;
   r1=(int)(10000.0*ratio1);
   for(i=0;i<g_length;i++)
   {  rnd=random(10000);
      if(rnd<=r1)    *(gene3+i)=*(gene1+i);
      else           *(gene3+i)=*(gene2+i);
   }
}

void g_disp_unit(x,y,n)
/* 繪製虛擬環境的一個單元  */
int x,y;        /* x=0,1,2....,wx-1;   y=0,1,2,....,wy-1  */
int n;          /* n=0: =1: 生物1  =2:生物2   =3:植物性食物  =4:障礙物  =5:動物性食物 */
{
   int gx,gy,i,j;
   unsigned char col;
   gx=SX1+5*x;gy=SY1+5*y;
   for(i=0;i<5;i++)
     for(j=0;j<5;j++)
     {  switch(n)
   { case 0: col=0;             break;
     case 1: col=life1[j]  [ i]*2; break;
     case 2: col=life2[j]  [ i]*4; break;
     case 3: col=food1[j]  [ i]*6; break;
     case 4: col=7;             break;
     case 5: col=food2[j]  [ i]*11;
    }
  g_pset(gx+j,gy+i,col);
       }
   }

void g_draw_world()         /* 顯示虛擬環境畫面  */
{
int i,j;
for(i=0;i<wy;i++)
  for(j=0;j<wx;j++)
  g_disp_unit(j,i,world[j] [ i]);
}

void g_draw_frame(x1,y1,x2,y2,c1,c2,c3,c4,text)
int x1,y1,x2,y2,c1,c2,c3,c4;
char *text;
{  int n,x3;
   g_rectangle(x1,y1,x2,y2,c1,1);
   g_rectangle(x1,y1,x2,y2,c2,0);
   g_rectangle(x1,y1,x2,y1+16,c3,1);
   g_rectangle(x1,y1,x2,y1+16,c2,0);
   n=strlen(text);
   x3=x1+((x2-x1-n*8)/2);
   disp_hz16(text,x3,y1,c4);
}

void g_init_frames()      /*  初始化畫面  */
{
  int i,j,cx,cy,x,y;
  char text[17];
  g_draw_frame(0,0,639,399,15,0,4,15,
      "基於遺傳算法的人工生命模擬");
  g_draw_frame(0,16,320,170,7,0,8,15,"設定參數");
  y=48;
   setcolor(9);
  disp_hz16("植物食物限制時間",16,y,15);
  sprintf(text,"%d",TL1);
  g_text(200,y+8,4,text);
  y=y+24;
   setcolor(9);
  disp_hz16("動物食物限制時間",16,y,15);
  sprintf(text,"%d",TL2);
  g_text(200,y+8,4,text);
  y=y+24;
   setcolor(9);
  disp_hz16("植物食物每代生成個數",16,y,15);
  sprintf(text,"%d",NEWFOODS);
  g_text(200,y+8,4,text);
  y=y+24;
   setcolor(9);
  disp_hz16("變異概率",16,y,15);
  i=(int)(MUTATION*100.0);
  sprintf(text,"%d",i);
  g_text(152,y+8,4,text);
  g_draw_frame(0,170,320,399,7,0,8,15,"最佳基因型");
  x=16;y=194;
   setcolor(9);
  disp_hz16("SP:物種號........",x,y,15);y=y+16;
  disp_hz16("SL:壽命..........",x,y,15);y=y+16;
  disp_hz16("VF:視野..........",x,y,15);y=y+16;
  disp_hz16("TM:基本移動模式..",x,y,15);y=y+16;
  disp_hz16("CM:移動特點......",x,y,15);y=y+16;
  disp_hz16("LM:移動能耗......",x,y,15);y=y+16;
  disp_hz16("CA:行動特點......",x,y,15);y=y+16;
  disp_hz16("CR:善變性........",x,y,15);y=y+16;
  disp_hz16("SA:攻擊速度......",x,y,15);y=y+16;
  disp_hz16("DA:防禦能力......",x,y,15);y=y+16;
  disp_hz16("LA:攻擊能耗......",x,y,15);y=y+16;
  disp_hz16("EF:食物吸取效率..",x,y,15);y=y+16;
  g_draw_frame(320,16,639,207,7,0,8,15,"虛擬世界");
  g_draw_frame(320,207,639,399,7,0,8,15,"世代個體數目變化");
  }

void g_init_graph()
/*  個體數進化圖初始化  */
{
   g_rectangle(GX,GY,GX+GXR,GY+GYR,0,1);
   g_rectangle(GX,GY,GX+GXR,GY+GYR,6,0);
   setcolor(1);
   disp_hz16( "生物 1",GX+5,GY-18,15);
   g_line(GX+90,GY-10,GX+110,GY-10,1);
   setcolor(4);
   disp_hz16( "生物 2",GX+120,GY-18,15);
   g_line(GX+205,GY-10,GX+225,GY-10,4);
   setcolor(0);
   disp_hz16("世代數",GX+168,GY+GYR+10,15);
   g_text(GX-25,GY,0,"100");
   g_text(GX-14,GY+GYR,0,"0");
}

void g_plot_population(gen_num,n1,n2,n1old,n2old)
int gen_num,n1,n2,n1old,n2old;
{
  int x,y,gx,gy,x_old,y_old;
  char text[8];
  if(gen_num%10==0)
  {
     x=GX+(gen_num-1)*GSTEP;
     g_line(x,GY+1,x,GY+GYR-1,1);
     sprintf(text,"%d",gen_num);
     if(gen_num<100||gen_num%20==0)
      g_text(x-8,GY+GYR+5,15,text);
  }
  x_old=GX+(gen_num-1)*GSTEP;
  x=x_old+GSTEP;
  y_old=GY+GYR-n1old;
  y=GY+GYR-n1;
  g_line(x_old,y_old,x,y,1);
  y_old=GY+GYR-n2old;
  y=GY+GYR-n2;
  g_line(x_old,y_old,x,y,4);
}

void g_disp_genotype()             /* 顯示最佳個體的遺傳基因型  */
{
  int i,j,n0,n1,x,y;
  unsigned char g[G_LENGTH];
  unsigned char bits[12][2]=
  { {0,0},{1,4},{5,6},{7,8},{9,11},{12,12},{13,15},
    {16,18},{19,21},{22,24},{25,27},{28,31}};
   /*  畫面消除  */
   g_rectangle(200,187,319,398,7,1);
    if(pop_size!=0)
    {
     /* 獲取各遺傳因子 */
      for(i=0;i<G_LENGTH;i++)
      {
n0=0;n1=0;
for(j=0;j<pop_size;j++)
  if(gene[j] [ i]==0) n0++;
  else  n1++;
  if(n0>=n1) g [ i]=0; else g [ i]=1;
      }
      x=220;
      for(i=0;i<12;i++)
      {
y=202+i*16;
for(j=bits [ i][0];j<=bits [ i][1];j++)
if(g[j]==0)
   g_text(x+(j-bits [ i][0])*16,y,4,"0");
   else
   g_text(x+(j-bits [ i][0])*16,y,4,"1");
   }
      }
  }

void g_disp_char(x,y,x1,y1,x2,y2,v)
int x,y,x1,y1,x2,y2;
unsigned char v;
{
   char c[10];
   if(x>=x1&& x<=x2-8 && y>=y1 && y<=y2-10)
   {
   switch(v)
    {
case 0: strcpy(c,"0/0");break;
case 1: strcpy(c,"+/0");break;
case 2: strcpy(c,"-/0");break;
case 3: strcpy(c,"x/0");
   }
   g_text(x,y,15,c);
   }
}
void remove_life(n)               /* 消除第n個個體  */
int n;
{
  iflg[n]=0;
  world[iatr[n][0]][iatr[n][1]]=0;
  g_disp_unit(iatr[n][0],iatr[n][1],0);
  if(food_size+1<=MAX_FOOD)
  {
  food_size++;
  fatr[food_size-1][0]=iatr[n][0];
  fatr[food_size-1][1]=iatr[n][1];
  fatr[food_size-1][2]=1;
  fatr[food_size-1][3]=0;
  fflg[food_size-1]=1;
  world[iatr[n][0]][iatr[n][1]]=5;
  g_disp_unit(iatr[n][0],iatr[n][1],5);
  }
}

void  remove_food(n)              /* 消除第n個食物 */
int n;
{
  fflg[n]=0;
  world[fatr[n][0]][fatr[n][1]]=0;
  g_disp_unit(fatr[n][0],fatr[n][1],0);
  }

void make_lives_and_foods()         /* 設置虛擬環境中生物與食物  */
{
  int x,y,i,j;
  pop_size=0;
  food_size=0;
  for(y=0;y<wy;y++)
    for(x=0;x<wx;x++)
    {
      if(world[x][y]==1||world[x][y]==2)
      {
       if(pop_size+1<=MAX_POP)
       {
  pop_size++;
/* 生成遺傳因子 */
           gene[pop_size-1][0]=world[x][y]-1;
    for(i=1;i<G_LENGTH;i++)
      gene[pop_size-1] [ i]=random(2);
           /*  設定屬性  */
     iatr[pop_size-1][0]=x;
     iatr[pop_size-1][1]=y;
     iatr[pop_size-1][2]=70+random(30);
     iatr[pop_size-1][3]=random(SL_MIN);
     }
       }
       if(world[x][y]==3||world[x][y]==5)
       {
  if(food_size+1<=MAX_FOOD)
  {
  food_size++;
         /* 設定屬性  */
  fatr[food_size-1][0]=x;
  fatr[food_size-1][1]=y;
  if(world[x][y]==3)
       fatr[food_size-1][2]=0;
  else
       fatr[food_size-1][2]=1;
fatr[food_size-1][3]=random(TL1-1)+1;
}
      }
    }
}

void find_empty(x,y)              /* 尋找虛擬環境中的空處,返回座標  */
  int *x,*y;
  {
  int ok;
  ok=0;
  while(ok==0)
  {
   *x=random(wx);*y=random(wy);
   if(world[*x][*y]==0) ok=1;
   }
  }

void make_world()                 /* 隨機設定人工環境  */
{
int i,j,k,num,x,y;
int ok,overlap;
char choice[3];
double size;
wx=0;
while(wx<10||wx>MAX_WX)
{
     setcolor(15);
     disp_hz16("虛擬環境長度(10-60)",10,210,20);
     gscanf(300,210,4,0,3,"%s",choice);
     wx=atoi(choice);
  }
wy=0;
while(wy<10||wy>MAX_WY)
{
     setcolor(15);
     disp_hz16("虛擬環境寬度(10-32)",10,240,20);
     gscanf(300,240,4,0,3,"%s",choice);
     wy=atoi(choice);
  }
for(i=0;i<wy;i++)
  for(j=0;j<wx;j++)
   if(i==0||i==wy-1||j==0||j==wx-1)
    world[j] [ i]=4;
    else    world[j] [ i]=0;
/* 設定障礙物  */
size=(double)(wx*wy);
num=(int)(size/40.0);
if(num>MAX_POP)  num=MAX_POP;
for(i=0;i<num;i++)
{
   find_empty(&x,&y);
   world[x][y]=4;
   }
num=(int)(size/5.0);
if(num>MAX_FOOD) num=MAX_FOOD;
for(i=0;i<num;i++)
{
ok=0;
while(ok==0)
{
    x=random(wx);y=random(wy);
    if((world[x][y]!=4) &&
       (world[x][y-1]==4 || world[x][y+1]==4 ||
        world[x-1][y]==4 || world[x+1][y]==4))
{  world[x][y]=4;
    ok=1;
    }
    }
}

  for(y=0;y<wy;y++)
  for(x=0;x<wx;x++)
    if(world[x][y]==0)
    {
    num=0;
    for(i=-1;i<=1;i++)
     for(j=-1;j<=1;j++)
       if(get_world(x+j,y+i)==4)
       num++;
       if(num>=6) world[x][y]=4;
       }
  /*  設定生物  */
  num=(int)(size*R_LIFE);
  for(i=0;i<num;i++)
  {  find_empty(&x,&y);
     world[x][y]=random(2)+1;
     }
  /* 設定食物  */
  num=(int)(size*R_FOOD);
  for(i=0;i<num;i++)
     {
     find_empty(&x,&y);
     world[x][y]=3;
}
}

void load_world_file()         /* 讀取虛擬環境數據文件設定  */
{
FILE *fopen(),*fpt;
char st[100],c;
int i,j;
if((fpt=fopen("//ga//world","r"))==NULL) exit(-1);
else
{
   fscanf(fpt,"%d",&wx);
   fscanf(fpt,"%d",&wy);
   for(i=0;i<wy;i++)
    for(j=0;j<wx;j++)
    fscanf(fpt,"%d",&world[j] [ i]);
    fclose(fpt);
    }
}

int get_world(x,y)             /*座標(x,y)處環境值  */
int x,y;
{
   if(x>=0 && x<wx && y>=0 && y<wy)
   return(world[x][y]);
  else
  return(-1);
}

int  decode_gene(n,sb,bw)               /* 第n個個體基因型解碼  */
int  n,sb,bw;                           /*  sb開始位  bw位長 */
{
  int i,sum;
  sum=0;
  for(i=sb;i<sb+bw;i++)
  sum=sum*2+gene[n] [ i];
  return(sum);
  }

void  move_pos(n,x1,y1,x2,y2)          /* 個體n從(x1,y1)移動到(x2,y2)   */
int n,x1,y1,x2,y2;
{
  int sp,loss;
  loss=decode_gene(n,12,1)+1;          /* 移動消耗 */
  iatr[n][2]=iatr[n][2]-loss;          /*  內部能量更新 */
  if(iatr[n][2]<=0)  remove_life(n);
  else
  {
    /* 個體屬性更新 */
    iatr[n][0]=x2;iatr[n][1]=y2;       /* x,y座標更新 */
    /* 顯示更新 */
    sp=gene[n][0]+1;
    g_disp_unit(x1,y1,0);              /*  當前位置(x,y)圖形消除 */
    world[x1][y1]=0;
    g_disp_unit(x2,y2,sp);             /*  新位置圖形表示 */
    world[x2][y2]=sp;
  }
}

void  move_randomly(n)                /*  個體n按照移動模式隨機移動 */
int n;
{
  
/* 基本移動模式1  */
int  pat1[8][2]={{1,0},{1,1},{0,1},{-1,1},
    {-1,0},{-1,-1},{0,-1},{1,-1}};
  /* 基本移動模式2與3  */
int pat2_3[2][4][2]={{{1,0},{0,1},{-1,0},{0,-1}},
    {{1,1},{-1,1},{-1,-1},{1,-1}}};
int pat,x1,y1,x2,y2,rndnum;
pat=decode_gene(n,7,2);
                              /* pat(0,1,2,3): 表示基本移動模式  */
x1=iatr[n][0];               /* 當前x座標 */
y1=iatr[n][1];               /* 當前y座標 */
if(pat<=1)                   /* 基本移動模式1  */
{
   rndnum=random(8);
   x2=x1+pat1[rndnum][0];     /* 移動目的點x座標 */
   y2=y1+pat1[rndnum][1];     /* 移動目的點y座標 */
   }
else                         /* 基本移動模式2與3  */
{
   rndnum=random(4);
   x2=x1+pat2_3[pat-2][rndnum][0];
   y2=y1+pat2_3[pat-2][rndnum][1];
   }
   if(x2>=0 && x2<wx && y2>=0 && y2<wy)
    if(get_world(x2,y2)==0)
      move_pos(n,x1,y1,x2,y2);
   /* 非法目的點的場合不作移動 */
}

void  move_individual(n)      /* 個體n移動 */
int n;
{
int cx,cy,dx,dy,sp,vf,sumx,sumy;
int i,j,a,sgn[3],num;
double  vect[8][2]={{1,0},{1,1},{0,1},{-1,1},
    {-1,0},{-1,-1},{0,-1},{1,-1}};
double vx,vy,d1,d2;
double _cos,cos_max;
cx=iatr[n][0];                /* 當前x座標 */
cy=iatr[n][1];                /* 當前y座標 */
sp=decode_gene(n,0,1)+1;      /* 生物種1和2 */
for(i=0;i<3;i++)              /* 移動特點CM */
{
sgn [ i]=decode_gene(n,9+i,1);
if(sgn [ i]==0)  sgn [ i]=-1;
}
sumx=0;sumy=0;num=0;
vf=decode_gene(n,5,2)+1;        /* 視野  */
  for(i=-vf;i<=vf;i++)
   for(j=-vf;j<=vf;j++)
   {
   if(i!=0||j!=0)
   {
     a=get_world(cx+j,cy+i);
     if(a==1||a==2)            /* 生物 1和2  */
     {   num++;
     if(a==sp)                 /* 同種生物 */
     {
     sumx=sumx+sgn[0]*j;
     sumy=sumy+sgn[0]*i;
     }
     else                      /* 異種生物 */
     {
     sumx=sumx+sgn[1]*j;
     sumy=sumy+sgn[1]*i;
     }
  } else
  if(a==3||a==5)               /*  食物  */
    {
    num++;
    sumx=sumx+sgn[2]*j;
    sumy=sumy+sgn[2]*i;
    }
   }
  }
if(num!=0)                     /* 視野內有其他生物和食物時 */
{
vx=(double)sumx/(double)num;
vy=(double)sumy/(double)num;
if(vx!=0||vy!=0)
{
      cos_max=-1.0;
      j=0;
      for(i=0;i<8;i++)
      {
d1=sqrt(vx*vx+vy*vy);
d2=sqrt(vect [ i][0]*vect [ i][0]+vect [ i][1]*vect [ i][1]);
_cos=(vx*vect [ i][0]+vy*vect [ i][1])/d1/d2;
if(_cos>cos_max)
{
  cos_max=_cos;j=i;
  }
      }
  dx=cx+(int)vect[j][0];
  dy=cy+(int)vect[j][1];
  if(dx>=0 && dx<wx && dy>=0 && dy<wy)
    if(world[dx][dy]==0)
      move_pos(n,cx,cy,dx,dy);
  }
  else  move_randomly(n);
}
else  move_randomly(n);
/* 視野內有其他生物和食物時 */
}

void  act1_attack(n)                /*  個體 n攻擊行動範圍內的其他生物個體 */
int n;
{
  int sft[8][2]={{1,0},{1,1},{0,1},{-1,1},
    {-1,0},{-1,-1},{0,-1},{1,-1}};
  int x1,y1,x2,y2,n2;
  int found,rndnum;
  double attack1,attack2,sa1,sa2,da1,da2,rnd1,rnd2,La1,La2;
  x1=iatr[n][0];y1=iatr[n][1];
  /* 獲得攻擊對象的座標(x2,y2) */
  found=0;
  while(found==0)
  {
   rndnum=random(8);
   x2=x1+sft[rndnum][0];
   y2=y1+sft[rndnum][1];
   if(get_world(x2,y2)==1||get_world(x2,y2)==2)
   found=1;
   }
   /* 檢查攻擊對象個體號n2  */
   found=0;n2=0;
   while(found==0)
   {
     if(iatr[n2][0]==x2 && iatr[n2][1]==y2 && iflg[n2]==1)
     found=1;  else n2++;
   }
   /* 計算雙方的 Attack量 */
   sa1=(double)decode_gene(n,19,3);
   da1=(double)decode_gene(n,22,3);
   sa2=(double)decode_gene(n2,19,3);
   da2=(double)decode_gene(n2,22,3);
   rnd1=(double)random(1001)/1000.0;
   rnd2=(double)random(1001)/1000.0;
   attack1=(double)iatr[n][2]+sa1*20.0/7.0*rnd1+da1*20.0/7.0*rnd2;
   rnd1=(double)random(1001)/1000.0;
   rnd2=(double)random(1001)/1000.0;
   attack2=(double)iatr[n2][2]+sa2*20.0/7.0*rnd1+da2*20.0/7.0*rnd2;
   /* 減少內部能量 */
   La1=decode_gene(n,25,3);
   La2=decode_gene(n2,25,3);
   rnd1=(double)random(1001)/1000.0;
   iatr[n][2]=iatr[n][2]-(int)((double)La1*rnd1);
   rnd2=(double)random(1001)/1000.0;
   iatr[n2][2]=iatr[n2][2]-(int)((double)La2*rnd2);
   if(attack1>=attack2)                         /* 勝者: n 敗者:n2 */
     iatr[n2][2]=iatr[n2][2]-40;
   else                                         /* 勝者: n2 敗者:n */
     iatr[n][2]=iatr[n][2]-40;
   if(iatr[n][2]<=0) remove_life(n);
   if(iatr[n2][2]<=0) remove_life(n2);
   }

  void  act2_eat(n)                            /* 個體n獲取行動範圍內的食物 */
  int n;
  {
    int sft[8][2]={{1,0},{1,1},{0,1},{-1,1},
    {-1,0},{-1,-1},{0,-1},{1,-1}};
  int x1,y1,x2,y2,n2,ef;
  int found,rndnum;
  x1=iatr[n][0];y1=iatr[n][1];
/*  獲取食物位置(x2,y2)  */
  found=0;
  while(found==0)
  {
   rndnum=random(8);
   x2=x1+sft[rndnum][0];
   y2=y1+sft[rndnum][1];
   if(get_world(x2,y2)==3||get_world(x2,y2)==5)
   found=1;
   }
   /* 增加內部能量 */
   ef=decode_gene(n,28,4);  /* 食物吸取效率 */
   iatr[n][2]=iatr[n][2]+(int)(40.0*(50.0+(double)ef*50.0/15.0)/100.0);
   if(iatr[n][2]>100)  iatr[n][2]=100;
   /* 檢查食物號n2  */
   found=0;n2=0;
   while(found==0)
   {
     if(fatr[n2][0]==x2 && fatr[n2][1]==y2 && fflg[n2]==1)
     found=1;  else n2++;
   }
   remove_food(n2);
   }

void act3_makechild(n)              /* 個體n與行動範圍內的其他生物個體交配產生子個體 */
int n;
{
  int i,j,k,x,y,x2,y2,found,n2,trial;
  int x3,y3;
  double rnd;
  if(pop_size+1<=MAX_POP)
  {
    x=iatr[n][0];y=iatr[n][1];
    found=0;
    while(found==0)
    {
    x2=x+random(3)-1;
    y2=y+random(3)-1;
    if(x2!=x||y2!=y)
      if(get_world(x2,y2)==gene[n][0]+1);
      found=1;
    }
   /* 檢查交配對象個體號n2  */
   found=0; n2=0;
   while(found==0)
   {
    if((iatr[n2][0]==x2 || iatr[n2][1]==y2) && iflg[n2]==1)
     found=1;   else n2++;
     if(n2>=pop_size-1) return;
   }
   /* 確定產生個體位置 */
   found=0;trial=0;
   while(found==0 && trial<50)
   {
   i=random(3)-1;j=random(3)-1;
   k=random(2);
   if(k==0)  {  x3=x+i;y3=y+j;}
   else      { x3=x2+i;y3=y2+j;}
   if(get_world(x3,y3)==0) found=1;
   trial++;
   }
   if(found==1)
   {
   /* 個體 n與個體 n2產生子個體 */
   pop_size++;
   /*  均勻交叉 */
   uni_crossover(gene,n,n2,pop_size-1,0.5,G_LENGTH);
   /*  變異    */
   for(i=1;i<G_LENGTH;i++)
   {
rnd=random(10001)/10000.0;
if(rnd<=MUTATION)
  if(gene[pop_size-1] [ i]==1)
     gene[pop_size-1] [ i]=0;
  else  gene[pop_size-1] [ i]=1;
   }
   /* 交配後父個體能量減少  */
   iatr[n][2]=iatr[n][2]-45;
   if(iatr[n][2]<=0)  remove_life(n);
   iatr[n2][2]=iatr[n2][2]-45;
   if(iatr[n2][2]<=0)  remove_life(n2);
   /*  子個體屬性輸入  */
   iatr[pop_size-1][0]=x3;
   iatr[pop_size-1][1]=y3;
   iatr[pop_size-1][2]=100;
   iatr[pop_size-1][3]=0;
   iflg[pop_size-1]=1;
   /*  子個體畫面表示 */
   world[x3][y3]=gene[pop_size-1][0]+1;
   g_disp_unit(x3,y3,gene[pop_size-1][0]+1);
   }
  }
}

void act_individual(n)              /* 爲行動範圍內的其他生物和食物決定行動 */
int n;
{
   int i,j,k,pattern,action,cr,ca;
   int act[3];                      /* act[0]:攻擊 act[1]:獲取食物 act[2]:交配 */
   int pat[6][3]={{1,2,3},{1,3,2},{2,1,3},
    {3,1,2},{2,3,1},{3,2,1}};
                                    /*  pat:行動優先順序 {攻擊,獲取食物,交配}  */
   int sp;
   double rnd;
   sp=decode_gene(n,0,1)+1;
   for(i=0;i<3;i++) act [ i]=0;
   for(i=-1;i<=1;i++)
     for(j=-1;j<=1;j++)
     {
       if(i!=0||j!=0)
       {
  k=get_world(iatr[n][0]+j,iatr[n][1]+i);
  if(k==1||k==2)  act[0]=1;
  if(k==3||k==5)  act[1]=1;
  if(k==sp)       act[2]=1;
  }
       }
       cr=decode_gene(n,16,3);
       rnd=(double)random(10001)/10000.0;
       if(rnd<=(double)cr/7.0)
       {
  action=random(3);
  while(act[action]==0)
  action=random(3);
  }
       else
       {
       ca=decode_gene(n,13,3);                 /* ca行動特點 */
       if(ca<3)  pattern=0;else  pattern=ca-2;
       /* 基本行動模式pattern 0-5 */
       i=0;
       action=pat[pattern] [ i]-1;
       while( act[action]==0)
       {
  i++;
  action=pat[pattern] [ i]-1;
  }
}
     switch(action+1)
     {
case 1:  act1_attack(n);break;
case 2:  act2_eat(n);break;
case 3:  act3_makechild(n);
     }
   }

void init_flags()                      /* 狀態標誌初始化 */
   {
   int i;
     for(i=0;i<pop_size;i++)  iflg [ i]=1;
     for(i=0;i<food_size;i++)  fflg [ i]=1;
   }

void  act_lives()                     /*  改變狀態(移動或行動)  */
{
   int i,j,k,x,y,move,a;
   for(i=0;i<pop_size;i++)
   {
     if(iflg [ i]==1)
     {
       move=1;
       for(j=-1;j<=1;j++)
for(k=-1;k<=1;k++)
{
   if(j!=0||k!=0)
   {
     a=get_world(iatr [ i][0]+k,iatr [ i][1]+j);
     if(a==1||a==2||a==3||a==5)
     move=0;
     }
}
       if(move==1)
  move_individual(i);
       else
  act_individual(i);
     }
   }
}

void  increase_age()              /* 個體年齡增1  */
{
  int i,j,s;
  for(i=0;i<pop_size;i++)
  {
    if(iflg [ i]==1)
    {
      j=decode_gene(i,1,4);
      s=SL_MIN+j;
      iatr [ i][3]++;
      if(iatr [ i][3]>s)
      remove_life(i);
      }
    }
  }

void  increase_frsh()            /* 食物新鮮度增1  */
{
  int i;
  for(i=0;i<food_size;i++)
    if(fflg [ i]==1)
    {
     fatr [ i][3]++;
     if((fatr [ i][2]==0 && fatr [ i][3]>TL1)||
(fatr [ i][2]==1 && fatr [ i][3]>TL2))
remove_food(i);
}
  }

void gabage_col()             /* 死去個體及消減食物清除*/
{
int i,j;
int new_pop,new_food;
   /* 檢查食物 */
new_food=0;
for(i=0;i<food_size;i++)
   if(fflg [ i]==1)
   {
   new_food++;
   for(j=0;j<4;j++)
      fatr[new_food-1][j]=fatr [ i][j];
   }
   food_size=new_food;
  /* 檢查個體 */
   new_pop=0;
   for(i=0;i<pop_size;i++)
     if(iflg [ i]==1)
     {
       new_pop++;
       /* 遺傳基因複製  */
       for(j=0;j<G_LENGTH;j++)
  gene[new_pop-1][j]=gene [ i][j];
       /* 屬性複製  */
       for(j=0;j<4;j++)
  iatr[new_pop-1][j]=iatr [ i][j];
      }
     pop_size=new_pop;
  }

  void  make_foods()                 /* 產生一代中植物性食物  */
  {
  int i,x,y;
  for(i=0;i<NEWFOODS;i++)
  {
    if(food_size+1<=MAX_FOOD)
    {
      food_size++;
      find_empty(&x,&y);
      fatr[food_size-1][0]=x;
      fatr[food_size-1][1]=y;
      fatr[food_size-1][2]=0;        /* 植物性 */
      fatr[food_size-1][3]=0;
      fflg[food_size-1]=1;
      world[x][y]=3;
      g_disp_unit(x,y,3);
     }
   }
  }

  void  calc_population(n1,n2)  /* 計算生物1和2 的個體數 */
  int *n1,*n2;
  {
    int i,p1,p2;
    p1=0;p2=0;
    if(pop_size>0)
      for(i=0;i<pop_size;i++)
if(gene [ i][0]==0)  p1++; else p2++;
*n1=p1;
*n2=p2;
  }

main()    /* 主程序  */
{
int i,work;
int n1,n2,n1old,n2old;
char choice[2];
randomize();
/* 圖形界面初始化 */
g_init();
settextstyle(0,0,4);
gprintf(220,20,4,0,"ALIFE");
setcolor(9);
disp_hz24("基於遺傳算法的人工生命模擬",150,60,25);
setcolor(15);
disp_hz16("人工環境及生物分佈",10,160,20);
disp_hz16("1:隨機產生  2: 讀文件產生 ==>",10,190,20);
gscanf(300,190,15,1,4,"%s",choice);
work=atoi(choice);
if(work==2)  load_world_file();else make_world();
make_lives_and_foods();
/*狀態初始化 */
init_flags();
/*計算個體數 */
calc_population(&n1old,&n2old);
/*生成初始畫面*/
g_init_frames();
/*虛擬世界畫面*/
g_draw_world();
/* 顯示初始圖形 */
g_init_graph();
for(i=1;i<121;i++)
{
  /*狀態初始化 */
  init_flags();
  /* 改變狀態(移動或行動)  */
  act_lives();
  /* 個體年齡增加  */
  increase_age();
  /* 食物新鮮度增加 */
  increase_frsh();
  /*死去個體及消減食物清除*/
  gabage_col();
  /*產生新的食物 */
  make_foods();
/* 求生物1和2 的個體數 */
  calc_population(&n1,&n2);
  /* 個體數變化的圖形更新  */
  g_plot_population(i,n1,n2,n1old,n2old);
  n1old=n1;n2old=n2;
/* 顯示最佳遺傳基因  */
  g_disp_genotype();
   }
  setcolor(9);
  disp_hz16("回車鍵結束",10,430,20);
  getch();
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章