/* evolving snails */ /* (c) 1993 Timewasters Online Magazine / Koen Holtman */ #include #include #include #include #include #include #include #include /* 1 maken als je systeem een usleep heeft */ #define USLEEP 0 /* verander dan ook eventueel de usleep call hieronder zodat het argument het juiste type heeft. Op Linux is het unsigned long. */ void die(); char *genefile=NULL; char *dea_genefile="genepool"; char *genelog; FILE *logfile; int makelog=1; int seed=-1; int sleeptime=2; int mutafactor=8; int updatefac=1; int musleeptime=0; /* playfield characteristics */ int begindist=10; /* xsize and ysize must be multiples of begindist */ int xsize=80; int ysize=30; /* screen dimensions , -1 = set to current terminal size */ int scrxdimen=-1; int scrydimen=-1; const char food='+'; const char visitedfood='*'; const char nofood=' '; /* gene pool */ int poolsize=24; struct genom { char table[45]; }; struct genom *genepool; struct ranking { int score; int number; }; struct ranking *genescore; /* slak control */ struct slakstate { int emote0; int emote1; int hungercount; int x,y; /* position */ int orient; struct genom* genes; int score; char looks; int playerno; }; int acemote0=1; int acemote1=1; int ackoffie=1; int acMTV=1; int htresh0=4; int htresh1=10; /* round playing stuff */ int months=1; int tijdfactor=3; struct slakstate *players; int *playernumbers; char *playfield; int numplayers,numrow,fieldsize; int day,offset,month; int year=0; /* options */ struct optstruct { int *var; const int minv; const int maxv; const char *swi; const char *meaning; }; #define INF -1 struct optstruct options[]= { { NULL,0,0,NULL,"---Options--- (default in brackets)" }, { NULL,0,0,NULL,"Playfield" }, { &begindist, 1, 256, "d", "Initial distance between snails" }, { &xsize, 1, INF, "x", "X dimension of playfield (must be multiple of -d)" }, { &ysize, 1, INF, "y", "Y dimension of playfield (must be multiple of -d)" }, { &months, 1, INF, "mon", "Number of months in a year" }, { &tijdfactor, 1, INF, "day", "Month has -day * -d * -d days" }, { NULL,0,0,NULL,"Evolution" }, { &poolsize, 3, INF, "g", "Gene pool size" }, { &mutafactor, 1, 100, "ms", "Mutation speed" }, { &seed, 0, INF, "rnd", "Random number seed" }, { NULL,0,0,NULL,"Presentation" }, { &scrxdimen, 1, INF, "sx", "X dimension of screen" }, { &scrydimen, 1, INF, "sy", "Y dimension of screen" }, { &updatefac, 1, INF, "u", "Days between a screen update" }, #if USLEEP { &musleeptime, 0, INF, "sle", "1/100 seconds to sleep between screen updates" }, #endif { &sleeptime, 0, 60, "pau", "Seconds to pause between years" }, { &makelog, 0, 1, "log", "Make a .log file" }, { NULL,0,0,NULL,"Snail brain" }, { &acemote0, 0, 1, "e0", "Activate emotion 0" }, { &acemote1, 0, 1, "e1", "Activate emotion 1" }, { &ackoffie, 0, 1, "cof", "Activate coffee" }, { &acMTV, 0, 1, "MTV", "Activate MTV" }, { &htresh0, 0, 1000, "h0", "Hunger treshhold 0" }, { &htresh1, 0, 1000, "h1", "Hunger treshhold 1" }, { NULL, 0, 0, NULL, NULL } }; /**************/ void waitkey(void) { move(scrydimen+1,scrxdimen-15); printw("PRESS ENTER"); refresh(); noecho(); noraw(); if(getch()=='q') die(); refresh(); } /**************/ /* initialisation */ void initmove(void); void initvars() { genepool=(struct genom *)malloc(sizeof(struct genom)*poolsize); if(genepool==NULL) exit(1); genescore=(struct ranking *)malloc(sizeof(struct ranking)*poolsize); if(genescore==NULL) exit(1); playernumbers=(int *)malloc(sizeof(int)*poolsize); if(playernumbers==NULL) exit(1); numplayers=(xsize/begindist)*(ysize/begindist); numrow=xsize/begindist; players=(struct slakstate *)malloc(sizeof(struct slakstate)*numplayers); if(players==NULL) exit(1); fieldsize=xsize*ysize; playfield=(char *)malloc(sizeof(char)*fieldsize); if(playfield==NULL) exit(1); initmove(); } /**************/ /* gene pool management */ void randompool() { int i,j; for(i=0; i99) val=50; genepool[i].table[j]=(char)(val%100); } fclose(f); } void genewrite(char *fnam) { FILE *f; int i,j; f=fopen(fnam,"w"); if(f==NULL) { fprintf(stderr,"WRITE ERROR!!\n"); sleep(1); return; } for(i=0; i=scrxdimen) return; if(y>=scrydimen) return; mvaddch(y,x,c); } void slakupd(int x, int y,char c) { if(x>=scrxdimen) return; if(y>=scrydimen) return; standout(); mvaddch(y,x,c); standend(); } /**************/ /* slak movement */ int movetab[16][2]= { /* x y*/ {-1, 0},{-1,-1},{ 0,-1},{ 1,-1}, { 1, 0},{ 1, 1},{ 0, 1},{-1, 1}, {-1, 0},{-1,-1},{ 0,-1},{ 1,-1}, { 1, 0},{ 1, 1},{ 0, 1},{-1, 1}, }; int seearray[16]; void initmove() { int i; for(i=0; i<16; i++) { seearray[i]= ( movetab[i][1]*xsize+ movetab[i][0]+ fieldsize )%fieldsize; } } void moveslak(struct slakstate *slak) { int a,i,dx,dy,myplace,side; int see; int *view; int s[5],t[5],u[5],v[5]; char *g; myplace=slak->y*xsize+slak->x; /* calculate vision */ see=0; view=&seearray[(slak->orient+6)&7]; for(i=0; i<5; i++) { s[i]= ( playfield[(myplace+view[i])%fieldsize] &1); } /* neural net */ g=slak->genes->table; /* calc t */ side=slak->hungercount>=htresh0 ? 1 : 0; for(i=1; i<=3; i++) { a= side ? *g : 50; g++; a+=s[i-1] ? *g : 50; g++; a+=s[i ] ? *g : 50; g++; a+=s[i+1] ? *g : 50; g++; t[i]= a < (*g++)*4 ? 0 : 1; } if(acemote0) t[0]=slak->emote0; else t[0]=0; if(acemote1) t[4]=slak->emote1; else t[4]=0; /* calc u */ side=slak->hungercount>htresh1 ? 1 : 0; for(i=1; i<=3; i++) { a= side ? *g : 50; g++; a+=t[i-1] ? *g : 50; g++; a+=t[i ] ? *g : 50; g++; a+=t[i+1] ? *g : 50; g++; u[i]= a < (*g++)*4 ? 0 : 1; } /* koffie emotie */ if(ackoffie) u[0]=day%30>25 ? 1 : 0; else u[0]=0; /* MTV emotie */ if(acMTV) u[4]=rand()&1; else u[4]=0; /* calc v */ side=(playfield[myplace]&1) ? 1 : 0; for(i=1; i<=3; i++) { a= side ? *g : 50; g++; a+=u[i-1] ? *g : 50; g++; a+=u[i ] ? *g : 50; g++; a+=u[i+1] ? *g : 50; g++; v[i]= a < (*g++)*4 ? 0 : 1; } slak->emote0=v[2]; slak->emote1=u[1]; slak->hungercount++; /* if(slak->looks=='A') { move(scrydimen,8); printw("s %d %d %d %d %d ",s[0],s[1],s[2],s[3],s[4]); printw("t %d %d %d %d %d ",t[0],t[1],t[2],t[3],t[4]); printw("u %d %d %d %d %d ",u[0],u[1],u[2],u[3],u[4]); printw("v %d %d %d ",v[1],v[2],v[3]); } */ /* perform command */ if(v[1]) slak->orient=(slak->orient+1)%8; if(v[3]) slak->orient=(slak->orient+7)%8; if(v[2]==0) { /* eat */ if(playfield[myplace]==1) { slak->score++; slak->hungercount=0; } playfield[myplace]=0; return; } /* move */ dx=movetab[slak->orient][0]; dy=movetab[slak->orient][1]; fieldupd(slak->x,slak->y, playfield[myplace]==0 ? nofood : visitedfood ); if(dx) slak->x=(slak->x+dx+xsize)%xsize; if(dy) slak->y=(slak->y+dy+ysize)%ysize; slakupd(slak->x,slak->y,slak->looks); } /**************/ /* playing a round */ void setupround() { int i,n; for(i=0; i=20) move(i,scrxdimen/2-10); else move(i,0); printw(" %4d. gene %3d scores %4d ", i,genescore[i].number,genescore[i].score); if(i=20) move(scrydimen-1,scrxdimen/2-10); else move(i,0); printw(" Average score is %d (%d%%) ",average,percent); refresh(); if(makelog) { fprintf(logfile,"year %-4d top %-4d avg %-4d perc %-3d\n", year,genescore[0].score,average,percent); fflush(logfile); } /* waitkey(); */ if(sleeptime!=0) sleep(sleeptime); } /* procreation based on genescore. */ int rankcompare(const void *a,const void *b) { return( ((struct ranking*)b)->score - ((struct ranking*)a)->score ); } void procreate() { int i,lastones,third,s,d; qsort(genescore,poolsize,sizeof(struct ranking),&rankcompare); third=poolsize/3; lastones=poolsize-third; printscores(third,lastones); for(i=0; imeaning!=NULL; o++) if(o->var!=NULL) { printf(" -%-3s : %s",o->swi,o->meaning); if(*(o->var)==-1) printf(".\n"); else printf(" (%d).\n",*(o->var)); } else printf("%s\n",o->meaning); printf(" -h or -? for help\n"); } void oneoption(char *opt) { struct optstruct *o,*p; int val; char *vs; p=NULL; for(o=options; o->meaning!=NULL; o++) if(o->var!=NULL) if(strncmp(&opt[1],o->swi,strlen(o->swi))==0) p=o; if(p==NULL) { fprintf(stderr," Unknown option %s\n",opt); exit(1); } vs=opt+1+strlen(p->swi); if(sscanf(vs,"%d",&val)!=1) { if(vs[0]=='\0') fprintf(stderr," Option %s: need an integer\n",p->swi); else fprintf(stderr," Option %s: `%s' is not an integer\n",p->swi,vs); exit(1); } if(valminv) { fprintf(stderr," Value too low in option %s\n",opt); exit(1); } if(p->maxv!=INF) if(val>p->maxv) { fprintf(stderr," Value too high in option %s\n",opt); exit(1); } *(p->var)=val; } void dooptions(int argc, char *argv[]) { int i; for(i=1; i