#include #include #include "gene.h" unsigned char MessageStdout = 0; unsigned char ViscaOn = 0; unsigned char FullScreen = 0; unsigned char AutoDemo = 0; int ICellSize = 20; int PopulationSize = 36; int MutationRateI = 50; int GenerationLength = 40; int StepSkip = 1; int SeedForRandom = 0; int MaxGeneration = 0; char *Geometry = "800x800"; char *DisplayName = NULL; char *FontName = /* "-b&h-*-bold-r-*-24-*" */ "variable"; char *DataFileName = "Genes"; int WorldWidth, WorldHeight; double CellSize; unsigned long PopSize, Generation, Step; gene_type *GeneTable; struct optb_rec { char *str, *help; unsigned char *flag; } options_b[] = { {"-stdout", "Display messages to standard output device", &MessageStdout}, {"-visca", "Enable VISCA control", &ViscaOn }, {"-fullscreen", "Full screen mode", &FullScreen}, {"-demo", "Auto demonstration mode", &AutoDemo}, { NULL, NULL, NULL } }; struct opti_rec { char *str, *help; int *var; } options_i[] = { {"-size", "Size of cell", &ICellSize}, {"-ps", "Population size", &PopulationSize}, {"-mut", "Inverse number of mutation rate", &MutationRateI}, {"-gl", "Maximum steps in one generation", &GenerationLength}, {"-skip", "Display steps skipped", &StepSkip}, {"-seed", "Seed for random numbers", &SeedForRandom}, {"-maxng", "Maximum number of generations of one run", &MaxGeneration}, { NULL, NULL, NULL } }; struct opts_rec { char *str, *help, **var; } options_s[] = { {"-geom", "\tGeometry of the world", &Geometry}, {"-data", " Data file name", &DataFileName}, {"-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.0001; parse_geom(Geometry); srand48(SeedForRandom?SeedForRandom:time(0)); mem_init(); gr_init(argc,argv); if (ViscaOn) video_init(); world_reset(); data_init(); if (AutoDemo) demo_loop(); else event_loop(); } world_reset() { int i, j; for (i = 0; i < PopulationSize; i ++) for (j = 0; j < GeneLen; j ++) #ifdef SenseOnly GeneTable[i].gene[j] = lrand48() & 0xff; #else GeneTable[i].gene[j] = lrand48() & 0xffff; #endif Generation = 0; new_generation(); } new_generation() { int i, j, k, n = ceil(sqrt((double)PopulationSize)); double span = 1.0 / n; mem_reset(); PopSize = Step = 0; clear_world(); for (j = k = 0; j < n; j ++) for (i = 0; i < n && k < PopulationSize; i++, k++) { new_cell((i+0.5)*span,(j+0.5)*span,0,0,k); GeneTable[k].size = 1; } Generation ++; draw_info(); } int LiveCells; void cell_step_m(c) cell *c; { if (cell_step(c)) { LiveCells ++; GeneTable[c->gid].size ++; GeneTable[c->gid].flag = 1; } } exec_n_step() { int i, j, flag = 1; for (i = 0; i < StepSkip; i ++) { Step ++; LiveCells = 0; for (j = 0; j < PopulationSize; j ++) GeneTable[j].flag = 0; for_all_active_cells(cell_step_m); /* if (!LiveCells || LiveCells < PopulationSize /2 ) */ if (!LiveCells || Step >= GenerationLength) { flag = 0; break; } } draw_info(); return flag; } #ifdef SGA static int select_parent(g) gene_type *g; { int i, k; k = lrand48() % g[PopulationSize-1].size; for (i = 0; g[i].size < k && i < PopulationSize; i ++); return (i < PopulationSize)? i : PopulationSize - 1; } selection() { int i, j, k, l; gene_type *p; static gene_type *TmpGenes = NULL; if (!TmpGenes) { if (!(TmpGenes = (gene_type *) malloc(sizeof(gene_type)*PopulationSize))) { perror("TmpGenes"); exit(1); } } for (i = j = 0; i < PopulationSize; i ++) { if (!(TmpGenes[i].flag = GeneTable[i].flag)) TmpGenes[i].size = (j += GeneTable[i].size); else TmpGenes[i].size = j; } for (i = 0; i < PopulationSize; i += 2) { p = GeneTable + select_parent(TmpGenes); mutation(p->gene,TmpGenes[i].gene); if (i < PopulationSize - 1) { p = GeneTable + select_parent(TmpGenes); mutation(p->gene,TmpGenes[i+1].gene); k = (lrand48() % (GeneLen - 1)) + 1; for (j = 0; j < k; j ++) { l = TmpGenes[i].gene[j]; TmpGenes[i].gene[j] = TmpGenes[i+1].gene[j]; TmpGenes[i+1].gene[j] = l; } } } bcopy(TmpGenes, GeneTable, sizeof(gene_type)*PopulationSize); new_generation(); } #else static int work_comp(x,y) gene_type *x, *y; { if (x->flag && y->flag) return 0; else if (x->flag) return 1; else if (y->flag) return -1; else return (y->size - x->size); } selection() { int i, k, l; gene_type *p, *c; qsort((char *)GeneTable,PopulationSize,sizeof(gene_type),work_comp); k = PopulationSize/3; for (i = 0, p = GeneTable, c = GeneTable + k; i < k; i++, p++, c++) { l = lrand48() % (GeneLen - 1) + 1; if (lrand48() & 1) bcopy(p->gene,c->gene,l); else bcopy(p->gene+l,c->gene+l,GeneLen-l); } l = PopulationSize - k * 2; for (i = 0; i < l; i ++) mutation(GeneTable[i].gene,GeneTable[k*2+i].gene); new_generation(); } #endif mutation(gs,gd) #ifdef SenseOnly unsigned char *gs, *gd; { int i, mask; bcopy(gs,gd,GeneLen); if (MutationRateI == 0) return; for (i = 0; i < GeneLen; i ++) for (mask = 0x80; mask; mask >>= 1) if (lrand48() % MutationRateI == 0) gd[i] ^= mask; } #else unsigned short *gs, *gd; { int i, mask; bcopy(gs,gd,GeneLen*sizeof(short)); if (MutationRateI == 0) return; for (i = 0; i < GeneLen; i ++) for (mask = 0x8000; mask; mask >>= 1) if (lrand48() % MutationRateI == 0) gd[i] ^= mask; } #endif