filename="listc.txt" #include #include #include #include #include #include #include #include #include #include #include #include #define PI 3.141592654 #define MAX_NEURAL 40 #define FITNESS_STEPS 400 #define POPULATION 500 #define WORLDSIZE 50 #define GENERATIONS 20000 typedef enum { SUM_THRESHOLD, FSENSOR, TSENSOR, TURN} functions; typedef enum { NONE, FOOD, VISITED } spotstates; Display *theDisplay; int screen; Window theRoot, theWindow; GC gc; Colormap theCmap; Pixmap bitmap; XColor black, white, brown; XtAppContext app_context; XmString text; Widget topLevel, mainWindow, menuBar, frame, sketchpad; Widget fileButton, fileMenu, run, quit; struct neuralnode { functions function; double weights[3]; int inpointers[3], numinputs; int constants[3], numconstants; int connected, computed, used; double outputvalue; }; struct animal { int living; double fitness, oldfitness, direction, x, y, turn; }; struct neuralnode brains[POPULATION+1][MAX_NEURAL+1]; struct neuralnode parent1b[MAX_NEURAL+1], parent2b[MAX_NEURAL+1]; struct animal animals[POPULATION+1]; struct animal parent1a, parent2a; char world[WORLDSIZE+1][WORLDSIZE+1]; void RestoreWin(w, client, call) Widget w; XtPointer client, call; { XCopyArea(theDisplay, bitmap, XtWindow(sketchpad), DefaultGCOfScreen(XtScreen(sketchpad)), 0, 0, 810, 860, 0, 0); } /* Set up the food patches */ void init_world(void) { int i, j, k; double xaxis, yaxis, x, y, xp, yp; for (i=0; i<=WORLDSIZE; i++) for (j=0; j<=WORLDSIZE; j++) world[i][j]=NONE; for (k=0; k<3; k++) { xaxis=rand()/65536.+0.1; yaxis=rand()/65536.+0.1; xp=rand()/16384.-1.; yp=rand()/16384.-1.; for (i=0; i<=WORLDSIZE; i++) { for (j=0; j<=WORLDSIZE; j++) { x=((double)i/WORLDSIZE-0.5)*2.; y=((double)j/WORLDSIZE-0.5)*2.; if ((x-xp)*(x-xp)*xaxis+(y-yp)*(y-yp)*yaxis<.06) world[i][j]=FOOD; } } } } /* Recursively compute the output of a node based upon its inputs */ void compute_node(int animal, int node) { int i; double inputs[3], constants[3], outval=0.; if (brains[animal][node].computed) return; brains[animal][node].computed=1; for (i=0; i-1) { compute_node(animal, brains[animal][node].inpointers[i]); inputs[i]=brains[animal][node].weights[i]* brains[animal][brains[animal][node].inpointers[i]].outputvalue; } else inputs[i]=brains[animal][node].weights[i]; } for (i=0; i0.99999) x=0.99999; if (y<0.) y=0.; if (y>0.99999) y=0.99999; xp=(int)(x*WORLDSIZE); yp=(int)(y*WORLDSIZE); if (world[xp][yp]==FOOD) break; outval*=0.25; } }; break; case TSENSOR: { double angle=(animals[animal].direction+inputs[0])*PI+PI/2.; double x, y; int xp, yp, i; outval=1.; for (i=1; i<3; i++) { x=animals[animal].x+cos(angle)/WORLDSIZE; y=animals[animal].y+sin(angle)/WORLDSIZE; if (x<0.) x=0.; if (x>0.99999) x=0.99999; if (y<0.) y=0.; if (y>0.99999) y=0.99999; xp=(int)(x*WORLDSIZE); yp=(int)(y*WORLDSIZE); if (world[xp][yp]==VISITED) break; outval*=0.25; } }; break; case TURN: outval=inputs[0]-inputs[1]; if (outval<-1.) outval=-1.; if (outval>1.) outval=1.; animals[animal].turn=outval; break; } brains[animal][node].outputvalue=outval*(0.95+rand()/327680.); } /* Evaluate an animal in a newly generated world */ double fitness(int which, int graph) { int i, j, xp, yp; double xpd, ypd, xold, yold; double score=0., angle, box=800./WORLDSIZE; char str[100]; init_world(); animals[which].direction=0.; animals[which].x=0.5; xold=0.5*800.; animals[which].y=0.; yold=0.; animals[which].turn=0.; if (graph) { XSetForeground(theDisplay, gc, white.pixel); XFillRectangle(theDisplay, bitmap, gc, 0, 0, 850, 850); for (i=0; i1.) animals[which].direction-=2.; angle=animals[which].direction*PI+PI/2.; animals[which].x+=cos(angle)/WORLDSIZE; animals[which].y+=sin(angle)/WORLDSIZE; if (animals[which].x<0.) animals[which].x=0.; if (animals[which].x>.99999) animals[which].x=.99999; if (animals[which].y<0.) animals[which].y=0.; if (animals[which].y>.99999) animals[which].y=.99999; /* EAT */ xpd=animals[which].x*800.; xp=(int)(animals[which].x*WORLDSIZE); ypd=animals[which].y*800.; yp=(int)(animals[which].y*WORLDSIZE); if (world[xp][yp]==FOOD) score++; if (world[xp][yp]==VISITED) score-=0.; world[xp][yp]=VISITED; if (graph) { XDrawLine(theDisplay, bitmap, gc, yold, xold, ypd, xpd); } xold=xpd; yold=ypd; } if (graph) { XSetLineAttributes(theDisplay, gc, 0, LineSolid, CapRound, JoinMiter); for (i=0; i5000) type=SUM_THRESHOLD; else type=(functions)((int)(rand()%3)); which[pos].function=type; switch(type) { case SUM_THRESHOLD: numinputs=3; numconstants=1; break; case FSENSOR: numinputs=1; numconstants=0; break; case TSENSOR: numinputs=1; numconstants=0; break; } which[pos].numinputs=numinputs; which[pos].numconstants=numconstants; } void remove_link(struct neuralnode which[]) { int node, input, fromnode; while (1) { node=(int)(MAX_NEURAL*rand()/32768.); if (which[node].used) break; } input=(int)(which[node].numinputs*rand()/32768.); which[node].inpointers[input]=-1; } void add_link(struct neuralnode which[]) { int node, input, fromnode; while (1) { node=(int)(MAX_NEURAL*rand()/32768.); if (which[node].used) break; } input=(int)(which[node].numinputs*rand()/32768.); while (1) { fromnode=(int)(MAX_NEURAL*rand()/32768.); if (which[fromnode].used) break; } which[node].inpointers[input]=fromnode; } /* Recursively mark connected nodes to protect from garbage collection */ void connected_node(struct neuralnode which[], int node) { int i; if (which[node].connected==1) return; which[node].connected=1; for (i=0; i-1) connected_node(which, which[node].inpointers[i]); } /* Mark unconnected nodes as not used */ void garbage_collect(struct neuralnode which[]) { int j; for (j=0; j-1) connect_node(parent1, parent2, pos, i, parent1[pos].inpointers[i]); } void init_population(void) { int i, j; for (i=0; imaxfit) maxfit=animals[i].fitness; } for (i=0; i=POPULATION) parent-=POPULATION; if ((animals[parent].living) && (animals[parent].fitness/maxfit>rand()/32768.)) break; } parent2=i; if (maxfit<=0.) parent2=(int)(POPULATION*rand()/32768.); else while (1) { for (j=0; j<3; j++) parent2+=(int)(POPULATION*(rand()/327680.-0.05)); if (rand()<10000) parent2=rand()%POPULATION; while (parent2<0) parent2+=POPULATION; while (parent2>=POPULATION) parent2-=POPULATION; if ((animals[parent2].living) && (animals[parent2].fitness/maxfit>rand()/32768.)) break; } for (j=0; jmaxfitness) { maxfitness=animals[animal].fitness; maxnum=animal; } } fitness(maxnum,1); survival_of_the_fittest(); make_children(); } } void Quit(w, client, call) Widget w; XtPointer client, call; { exit(0); } void main(int argc, char **argv) { /* INITIALIZE X */ topLevel=XtVaAppInitialize( &app_context,"Dino",NULL,0,&argc,argv,NULL,NULL); /* CREATE MAIN WINDOW & IMMEDIATE CHILDREN */ mainWindow=XtVaCreateManagedWidget( "mainWindow",xmMainWindowWidgetClass,topLevel,NULL); menuBar=XmCreateMenuBar(mainWindow,"menuBar",NULL,0); XtManageChild(menuBar); frame=XtVaCreateManagedWidget( "frame",xmFrameWidgetClass,mainWindow,NULL); XmMainWindowSetAreas(mainWindow, menuBar, NULL, NULL, NULL, frame); XtVaSetValues(mainWindow,XmNwidth,810,XmNheight,860,NULL); /* CREATE GRAPHICS */ sketchpad = XtVaCreateManagedWidget( "sketchpad",xmDrawingAreaWidgetClass, frame, XmNwidth,810,XmNheight,860,NULL); theDisplay = XtDisplay(sketchpad); theWindow = XtWindow(sketchpad); screen = DefaultScreen(theDisplay); theRoot = RootWindowOfScreen(XtScreen(sketchpad)); theCmap = DefaultColormap( theDisplay, DefaultScreen(theDisplay) ); bitmap = XCreatePixmap(XtDisplay(sketchpad),theRoot,810,860, DefaultDepthOfScreen(XtScreen(sketchpad))); gc = XCreateGC( theDisplay, bitmap, 0, 0 ); XtAddCallback(sketchpad,XmNexposeCallback,RestoreWin,0); XParseColor(theDisplay,theCmap,"black",&black); XAllocColor(theDisplay, theCmap,&black); XParseColor(theDisplay,theCmap,"white",&white); XAllocColor(theDisplay, theCmap,&white); XParseColor(theDisplay,theCmap,"brown",&brown); XAllocColor(theDisplay, theCmap,&brown); /* CREATE FILE MENU */ fileButton=XtVaCreateManagedWidget( "fileButton",xmCascadeButtonWidgetClass,menuBar,NULL); text=XmStringCreateLocalized("File"); XtVaSetValues(fileButton,XmNlabelString,text,NULL); fileMenu=XmCreatePulldownMenu(menuBar,"fileMenu",NULL,0); XtVaSetValues(fileButton,XmNsubMenuId,fileMenu,NULL); /* CREATE RUN BUTTON */ run=XtVaCreateManagedWidget( "run",xmPushButtonWidgetClass,fileMenu,NULL); text=XmStringCreateLocalized("Run"); XtVaSetValues(run,XmNlabelString,text,NULL); XtAddCallback(run,XmNactivateCallback,Run,NULL); /* CREATE QUIT BUTTON */ quit=XtVaCreateManagedWidget( "quit",xmPushButtonWidgetClass,fileMenu,NULL); text=XmStringCreateLocalized("Quit"); XtVaSetValues(quit,XmNlabelString,text,NULL); XtAddCallback(quit,XmNactivateCallback,Quit,NULL); XtRealizeWidget(topLevel); XSetForeground(theDisplay, gc, white.pixel); XFillRectangle(theDisplay, bitmap, gc, 0, 0, 810, 860); XtAppMainLoop(app_context); }