#include #include #include "gene.h" unsigned char MessageStdout = 0; unsigned char FullScreen = 0; unsigned char AutoDemo = 0; unsigned char WireFrameMode = 0; unsigned char BlackBackground = 0; int ICellSize = 100; int PopulationSize = 36; int MutationRateI = 5; int GenerationLength = 40; int SeedForRandom = 0; int MaxGeneration = 0; int MaxCells = 4096; int IScale = 100; char *Geometry = "800x800"; char *DisplayName = NULL; char *FontName = /* "-b&h-*-bold-r-*-24-*" */ "variable"; char *DataFileName = "Genes"; char *DumpFileName = "L3.fd"; int WorldWidth, WorldHeight; double CellSize; unsigned long PopSize, Generation, Step, BestScore; Individual *Population; struct optb_rec { char *str, *help; unsigned char *flag; } options_b[] = { {"-stdout", "Display messages to standard output device", &MessageStdout}, {"-fullscreen", "Full screen mode", &FullScreen}, {"-demo", "Auto demonstration mode", &AutoDemo}, {"-frame", "Wireframe mode", &WireFrameMode}, {"-black", "Black background", &BlackBackground}, { NULL, NULL, NULL } }; struct opti_rec { char *str, *help; int *var; } options_i[] = { {"-size", "Size of cell", &ICellSize}, {"-ps", "Population size", &PopulationSize}, {"-mut", "Number of mutation bits", &MutationRateI}, {"-gl", "Maximum steps in one generation", &GenerationLength}, {"-seed", "Seed for random numbers", &SeedForRandom}, {"-maxnc", "Maximum number of cells in one individual",&MaxCells}, {"-maxng", "Maximum number of generations of one run", &MaxGeneration}, {"-scale", "Display scale for cells", &IScale}, { NULL, NULL, NULL } }; struct opts_rec { char *str, *help, **var; } options_s[] = { {"-geom", "\tGeometry of the world", &Geometry}, {"-data", " Data file name", &DataFileName}, {"-dump", " Screen dump file name", &DumpFileName}, {"-fn", " Font name", &FontName}, {"-disp", " Display name", &DisplayName}, { NULL, NULL, NULL } }; arg_error(cn,option) char *cn, *option; { union { struct optb_rec *b; struct opti_rec *i; struct opts_rec *s; } p; fprintf(stderr,"%s: illegal option %s.\noptions:\n",cn,option); for (p.i = options_i; p.i->str; p.i++) fprintf(stderr,"%s%s%s. (default %d)\n",p.i->str, ((strlen(p.i->str)<5)?"\t\t":"\t"),p.i->help,*(p.i->var)); for (p.s = options_s; p.s->str; p.s++) fprintf(stderr,"%s %s. (default %s)\n",p.s->str,p.s->help, ((*(p.s->var))?*(p.s->var):"NULL")); for (p.b = options_b; p.b->str; p.b++) fprintf(stderr,"%s%s%s.\n",p.b->str, ((strlen(p.b->str)<8)?"\t\t":"\t"),p.b->help); exit(1); } main(argc, argv) int argc; char **argv; { int i; union { struct optb_rec *b; struct opti_rec *i; struct opts_rec *s; } p; for (i = 1; i < argc; i++) { for (p.b = options_b; p.b->str; p.b ++) if (!strcmp(argv[i],p.b->str)) { *(p.b->flag) = 1; goto nextop; } for (p.i = options_i; p.i->str; p.i ++) if (!strncmp(argv[i],p.i->str,strlen(p.i->str))) { *(p.i->var) = atoi(argv[i]+strlen(p.i->str)); goto nextop; } if (!p.i->str && i < argc-1) for (p.s = options_s; p.s->str; p.s++) if (!strncmp(argv[i],p.s->str,strlen(p.s->str))) { *(p.s->var) = argv[++i]; goto nextop; } if (!p.s->str && !strcmp(argv[i],"-stdout")) MessageStdout = 1; else arg_error(argv[0],argv[i]); nextop: continue; } CellSize = ICellSize * 0.001; if (GenerationLength < 1) GenerationLength = 1; parse_geom(Geometry); srand48(SeedForRandom?SeedForRandom:time(0)); mem_init(); gr_init(argc,argv); world_reset(); data_init(); if (AutoDemo) demo_loop(); else event_loop(); } Gene *random_gene() { static Gene gene; unsigned long r = lrand48(); gene.state = r & 0xff; gene.alpha = (r >> 8) & 0xff; gene.beta = (r >> 16) & 0xff; gene.gamma = (r >> 24) & 0xff; return &gene; } world_reset() { int i, j; for (i = 0; i < PopulationSize; i ++) for (j = 0; j < GeneLen; j ++) Population[i].gene[j] = *random_gene(); Generation = 0; new_generation(); } new_generation() { int i; Individual *ind; static double ax[4][4] = {{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}}; mem_reset(); PopSize = Step = 0; for (i = 0, ind = Population; i < PopulationSize; i++, ind++) { ind->score = ind->size = 0; new_cell(ind,ax,0,NULL); } Generation ++; redraw_world(); draw_info(); } exec_one_step() { int i; Individual *ind; Cell *c; Step ++; for (i = 0, ind = Population; i < PopulationSize; i ++, ind ++) { if (ind->size < MaxCells) for (c = ind->cells; c; c = c->next) cell_step(ind,c); } redraw_world(); if (Step == GenerationLength) { BestScore = 0; for (i = 0, ind = Population; i < PopulationSize; i++, ind++) { ind->score = fitness(ind); if (ind->score > BestScore) BestScore = ind->score; } printf("%d:%d\n",Generation,BestScore); } draw_info(); return (Step < GenerationLength); } fitness(ind) Individual *ind; { Cell *c; int n = 0; double dmax = 0, d; for (c = ind->cells; c; c = c->next) { if ((c->state & 0xf8) == 0) return 0; else n ++; d = c->x*c->x + c->y*c->y + c->z*c->z; if (d > dmax) dmax = d; } return n / (0.1 * dmax + 0.2 * sqrt(dmax) + 0.7 * pow(dmax,0.25)); } static int work_comp(x,y) Individual *x, *y; { return (y->score - x->score); } selection() { int i, j, k, mask, m; Individual *p, *c; qsort((char *)Population,PopulationSize,sizeof(Individual),work_comp); k = PopulationSize/3; for (i = 0, p = Population, c = Population + k; i < k; i++, p++, c++) { mask = lrand48(); for (j = 0, m = 1; j < GeneLen; j ++, m <<= 1) if (m & mask) c->gene[j] = p->gene[j]; } m = PopulationSize - k * 2; for (i = 0; i < m; i ++) mutation(Population[i].gene,Population[k*2+i].gene); new_generation(); } mutation(gs,gd) Gene *gs, *gd; { int i, k; Gene *gp; bcopy(gs,gd,GeneLen*sizeof(Gene)); for (i = 0; i < MutationRateI; i ++) { k = lrand48() % (GeneLen*sizeof(Gene)*8); gp = gd + k/sizeof(Gene)/8; k %= sizeof(Gene)*8; if (k < 8) gp->state ^= (1 << k); else if (k < 16) gp->alpha ^= (1 << (k - 8)); else if (k < 24) gp->beta ^= (1 << (k - 16)); else if (k < 32) gp->gamma ^= (1 << (k - 24)); } }