#include "SDL/SDL.h" #include #include // adhoc changelog // 4.99 -> 4.99.99: saveall/loadall added. last 4.xx ever // 4.99 -> 4.99.9: changes to pull neuron/synapse reverted // 4.98 -> 4.99: operand limit changed from num_of_neurons to 255. save/load fixed for windows build // 4.97 -> 4.98: biteenergy quadrupled. import/export DNA IP // 4.96 -> 4.97: removeneuron now pulls first synapse // 4.95 -> 4.96: misc changes to neuron/synapse operations. windows version // 4.93 -> 4.95: motors actuated on unchanging energy value so order is neutral // 4.91 -> 4.93: give bonus raised from 1 to 3, fight difficulty raised to 1/8 // 4.?? -> 4.91: fixed a type/weight swap of low consequence // [type is 0 to 3, weight is 1 to 4] in add synapse; fight always used high // cell's energy, has been tweaked. // this is neural brainfuck version // pre-calculate potential decay... it'd be faster // they need a fifth directional sense, another 8 inputs, for neighbour temps // make temperature affect decay... [done] // gonna get in a tiled display of every view for the default view... // make a lost fight only take energy from the attacker not the defender // then remove this comment. well actually im not sure, i'll evolve longer // then decide. it's only an issue for the neural version, pretty sure // ok done it also removes more energy from the losing attacker than before, // biteAmount * 1 // check plasticity, is it working? [yes] theres some debug outputs to get before im sure // ok i looked at it they only went in one direction darn. should be better now // the host neuron firing sends it the opposite way... // maybe increment generation count by 1 on a mingle even without a mutation... // oh just if the generations are different is better // avggen is still wrong... wtf // i'm starting children at the parent's IP right now... search 'experiment' to // find what you should change... if I don't reboot the DNA and clear the brains // of children, i should save their brains when I save the DNA... which is kind // of not a hassle anyway... ok // recent fixes // firing thresholds minimum is 1 or you get an FPE on the module by it // which also makes neuron potentials over max carry over the remainder now // but only the remainder it won't fire repeatedly from a very high synapse // weight... or anything // plasticity now pulls both ways // synaps weight minimum is 1 // #define num_of_neurons 140U // max 254, but leaving space will make args over // num_of_neurons wrap to the first (cortical) // neurons #define num_of_synapses 26U // this is actually some weird constant which is // the size of each neuron. it has to be two plus // the number of synapses you want times four // max neurons is 254, minimum is 66 (65 are permanent cortical neurons) // thats 8 direction senses per 4 operations and one loud input out of // 32 that shows temperature/energy with granularity of 8... // 0 means unconnected so you get one less than that still #define cortical_neurons 70U // dont touch (2 for brainfuck program I/O) // fuck maybe when they flip over 255 (energy) i should breed them to a random square // keys to let user toggle: // dna phase // ca phase // breeding (opposed to splitting) // get DNA loading in! // CA is pretty hard so now gives add 1 energy, ok? // views: // actions (needs a new grid to store em) // age? (add lifetime array then, too) // sexiness (% operands > 8) * 2.55 < do this still // skip counters // generation count (highestgen-lowestgen)/((gen-lowestgen)+1) // dna IP // // read how to set the palette // why is avggen wrong // have cell selection and ip in the dna view // end old notes, start configurables #define gridrows 44U // #define gridcols 44U // weird plasma vortex w/ nature patterns // (maybe not in neural version) // you can go bigger but 80x80 fits into 1280x1024 real nice // also change float DNA_View_Cell_Size_Divisor way under this if you change the sizes very much // because cell sizes (when displayed) will also change... //define gridrows 170 //define gridcols 213 // big ropes //define gridrows 68U //define gridcols 105U // rope. nice ratio. bumping rows toward 70 makes the bands // more vertical int popsize = gridrows*gridcols; #define screenwidth 1280U #define screenheight 1024U #define biteAmount 7U // energy moved per bite. this is also how much a give transfers #define freeGiveBonus 5U // energy added on a give // see if this is enough they can generate among // relatives with gives if so #define freeEnergyToOffspring 3U // who knows. 5/7/8 here is also nice #define DNA_Length 16384U // hm #define mutantrate 10U // 1/n offspring will be mutated. minimum is 1 (100%) #define remutaterate 100U // 99/n chance of repeat mutations #define sexoperandpersistance 5U // frames of sim time (cumulative so 5 is high) // brains do this now not dna but i dunno #define max_breed_fairness 20U // number of allowed recursions, max 255 // many more configurables below... in main() /* * Set the pixel at (x, y) to the given value * NOTE: The surface must be locked before calling this! */ void putpixel(SDL_Surface *surface, int x, int y, Uint8 pixel) { // int bpp = surface->format->BytesPerPixel; /* Here p is the address to the pixel we want to set */ // Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * 1; // switch(1) { // case 1: *p = pixel; // break; return; /* case 2: *(Uint16 *)p = pixel; break; case 3: if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { p[0] = (pixel >> 16) & 0xff; p[1] = (pixel >> 8) & 0xff; p[2] = pixel & 0xff; } else { p[0] = pixel & 0xff; p[1] = (pixel >> 8) & 0xff; p[2] = (pixel >> 16) & 0xff; } break; case 4: *(Uint32 *)p = pixel; break; } */ } void drawline(SDL_Surface *surface, int x, int y, int x2, int y2, int color, int endcolor) { int j = 0; unsigned int k = 0; float xdiff = 0; float ydiff = 0; float xstep; unsigned int xstart = 0; unsigned int ystart = 0; unsigned int xend = 0; unsigned int yend = 0; unsigned int i = 0; /* if (x>x2) { xdiff = x2 - x; xstart = x; xend = x2; } else { xdiff = x - x2; xstart = x; xend = x2; } if (y>y2) { ydiff = y2 - y; ystart = y; yend = y2; } else { ydiff = y - y2; ystart = y; yend = y2; } */ if (x2>x) { xstep = 1; } else { xstep = -1; } xstart = x; xend = x2; xdiff = (float) x2 - (float) x; ydiff = (float) y2 - (float) y; ystart = y; yend = y2; float ystep; if (xdiff != 0) { ystep = (float) ydiff / (float) xdiff; if (ystep > 0 && ydiff < 0) { ystep = 0-ystep; } else if (ystep < 0 && ydiff > 0) { ystep = -1.0f*ystep; } } else { ystep = ydiff; } // if (!ystep) {ystep = 0;} // nan protection float realy = 0; realy = (float) ystart; float realcolor = color; float colorstep; float ack; ack = xdiff; if (ack < 0) { ack = -1.0f*ack; } if (ydiff < 0) { ack -= ydiff; } else { ack += ydiff; } if (ack > 0) { colorstep = ((float) (endcolor - color)) / ack; } else { colorstep = 0; } // printf("xstart %i \tystart %i \txend %i \tyend %i \txdiff %f \tydiff %f \tystep %f \txstep %f \trealy %f \tj %i \ti %i \n", \ // xstart, ystart, xend, yend, xdiff, ydiff, ystep, xstep, realy, j, i); float oldrealy = 0; unsigned int xctr = 0; if (xdiff < 0) { xdiff = -1.0f*xdiff; } for (j = xstart; xctr <= xdiff; j+=xstep) { xctr+=1; oldrealy = realy; realy = realy + ystep; int p = 0; if (realy > oldrealy) { for (p = (int) oldrealy; (int) p <= (int) realy; p++) { // printf("xstart %i \tystart %i \txend %i \tyend %i \txdiff %f \tydiff %f \tystep %f \txstep %f \trealy %f \tj %i \ti %i \tp %i \tcolorstep %f\trealcolor %f\n", \ // xstart, ystart, xend, yend, xdiff, ydiff, ystep, xstep, realy, j, i, p, colorstep, realcolor, 5); putpixel(surface, j, (unsigned int) p, (unsigned int) realcolor); realcolor += colorstep; if (p >= screenheight) {return;} } } else if (realy < oldrealy) { for (p = (int) oldrealy; (int) p >= (int) realy; p--) { // if (p < 958) { // printf("xstart %i \tystart %i \txend %i \tyend %i \txdiff %f \tydiff %f \txstep %f \tystep %f \trealy %f \tj %i \ti %i \tp %i \n", \ // xstart, ystart, xend, yend, xdiff, ydiff, xstep, ystep, realy, j, i, p, 5); // } putpixel(surface, j, (unsigned int) p, (unsigned int) realcolor); realcolor += colorstep; if (p <= 0) { return; } } } else { putpixel(surface, j, (unsigned int) realy, (unsigned int) realcolor); realcolor += colorstep; } } // if ( SDL_MUSTLOCK(surface) ) { // SDL_UnlockSurface(surface); // } // printf("drawline done\n"); } void fillcell(SDL_Surface *surface, int cellw, int cellh, int x, int y, int xspace, int yspace, int yoff, Uint8 color) { int xstart = (cellw+xspace)*x; int xend = (cellw+xspace)*(x+1)-xspace; int ystart = ((cellh+yspace)*y)+yoff; int yend = ((cellh+yspace)*(y+1)-yspace)+yoff; int j; int i; unsigned int randomdivisor = RAND_MAX>>8; // printf ("%i\n", color); for (j = ystart; j < yend; j++) { for (i = xstart; i < xend; i++) { putpixel(surface, i, j, color); } } if ( SDL_MUSTLOCK(surface) ) { SDL_UnlockSurface(surface); } } void drawgrid(SDL_Surface *surface, Uint8 **DNA, Uint8 neuroncount, Uint8 *didfire, Uint8 *grid, int drawgrid_gridrows, int drawgrid_gridcols, int cellw, int cellh, int xspace, int yspace, int drawgrid_screenwidth, int drawgrid_screenheight, float DNA_View_Cell_Size_Divisor, int drawgrid_DNA_Length, int view, int viewdata1, int viewdata2, int * viewdata3, Uint8 * viewdata4) { int i; int j; for (i = 0; i < drawgrid_gridrows; i++) { for (j = 0; j < drawgrid_gridcols; j++) { // printf ("draw %i,%i,%i",i,j,*grid); if (view == 0) { fillcell(surface, cellw, cellh, j, i, xspace, yspace, 0, *grid); grid += 1; } else if (view > 0) { // generations, stuns int c; if (view == 1 || view == 4) { // integer tables c = ((int) 255.0f*(((float)(*viewdata3)-(float)viewdata1)/(((float)viewdata2-(float)viewdata1)+1.0f))); viewdata3 += 1; } else if (view == 2 || view == 3 || (view >= 5 && view <= 13)) { // uint8 tables c = ((int) 255.0f*(((float)(*viewdata4)-(float)viewdata1)/(((float)viewdata2-(float)viewdata1)+1.0f))); viewdata4 += 1; } if (c > 255) { c = 255; } // if (view == 2 && c > 0) { printf ("graph individual of stun count %i as color %i. low = %i high = %i \n", *viewdata4, c, viewdata1, viewdata2); } fillcell(surface, cellw, cellh, j, i, xspace, yspace, 0, c); } } } // int t = drawgrid_DNA_Length/((drawgrid_gridcols*DNA_View_Cell_Size_Divisor)-3)+1; int t = num_of_neurons/((drawgrid_gridcols*DNA_View_Cell_Size_Divisor)-0)+1; // ^ 254 == num_of_neurons int dnactr = 1; for (i = drawgrid_gridrows; i < drawgrid_gridrows+t; i++) { for (j = 0; j < (drawgrid_gridcols*DNA_View_Cell_Size_Divisor)-0; j++) { fillcell(surface, ((float)(cellw/DNA_View_Cell_Size_Divisor))+xspace+1, ((float)(cellh/DNA_View_Cell_Size_Divisor))+yspace+1, j, i-drawgrid_gridrows, 0, 0, drawgrid_gridrows*(cellh+yspace), 0); dnactr += 1; } if (dnactr > num_of_neurons) { break; } // num_of_neurons } dnactr=1; Uint8 *somedna = *DNA; int coords[num_of_neurons][2]; for (i = drawgrid_gridrows; i < drawgrid_gridrows+t; i++) { // printf("drawgrid_gridcols=%i\nDNA_View_Cell_Size_Divisor=%f\ndrawgrid_gridcols*DNA_View_Cell_Size_Divisor=%f\n",drawgrid_gridcols,DNA_View_Cell_Size_Divisor,(float) ((float) drawgrid_gridcols* (float)DNA_View_Cell_Size_Divisor)); for (j = 0; j < (drawgrid_gridcols*DNA_View_Cell_Size_Divisor)-0; j++) { // printf("debug: draw dna %i,%i\n", j, i-drawgrid_gridrows); somedna+=num_of_synapses; // num_of_synapses // somedna += 1; coords[dnactr][0] = ((cellw/DNA_View_Cell_Size_Divisor+xspace)*j)+(cellw/DNA_View_Cell_Size_Divisor)/2; coords[dnactr][1] = ( (drawgrid_gridrows*(cellh+yspace)) + ( (i-drawgrid_gridrows) * ((cellh/DNA_View_Cell_Size_Divisor)+yspace) ) )+((cellh/DNA_View_Cell_Size_Divisor)/2); // if (dnactr < 3) { // printf("dnactr %i\ncoords[dnactr][0] set to %i\ncoords[dnactr][1] set to %i\n",dnactr,coords[dnactr][0],coords[dnactr][1]); // } if (dnactr < neuroncount && *(somedna+1) > 0 && *somedna > 0) { fillcell(surface, cellw/DNA_View_Cell_Size_Divisor, cellh/DNA_View_Cell_Size_Divisor, j, i-drawgrid_gridrows, xspace, yspace, drawgrid_gridrows*(cellh+yspace), 32*((*(somedna+1)) / *somedna)); // printf("cellw %i\ncellh %i\nDNA_View_Cell_Size_Divisor %i\ndrawgrid_gridrows %i\ni %i\nj %i\n",cellw,cellh,DNA_View_Cell_Size_Divisor,drawgrid_gridrows,i,j); } else { fillcell(surface, cellw/DNA_View_Cell_Size_Divisor, cellh/DNA_View_Cell_Size_Divisor, j, i-drawgrid_gridrows, xspace, yspace, drawgrid_gridrows*(cellh+yspace), 0); } dnactr++; // if (dnactr >= drawgrid_DNA_Length) { break; } if (dnactr > num_of_neurons) { break; } // num_of_neurons } // if (dnactr >= drawgrid_DNA_Length) { break; } if (dnactr > num_of_neurons) { break; } } dnactr = 1; Uint8 *abrain = *DNA; for (i = drawgrid_gridrows; i < drawgrid_gridrows+t; i++) { for (j = 0; j < (drawgrid_gridcols*DNA_View_Cell_Size_Divisor)-0; j++) { abrain += num_of_synapses; int neur_offs = 2; while (neur_offs < num_of_synapses) { // christ if (abrain[neur_offs] == 0) { break; } // end of neuron // printf("dna_ctr %i\nneur_offs %i\ncoords[dnactr][0] is %i\ncoords[dnactr][1] is %i\nabrain[neur_offs] = %i\ncoords[abrain[neur_offs]][0] is %i\ncoords[abrain[neur_offs]][1] is %i\n", dnactr, neur_offs, coords[dnactr][0], coords[dnactr][1], abrain[neur_offs], coords[abrain[neur_offs]][0], coords[abrain[neur_offs]][1] ); // printf("df = %i\n", didfire[abrain[neur_offs]]); if (didfire[abrain[neur_offs]]) { // if (didfire[0]) { // printf("novs\n"); drawline(surface, coords[dnactr][0], coords[dnactr][1], coords[abrain[neur_offs]][0], coords[abrain[neur_offs]][1], 0, 40); } neur_offs += 4; } dnactr++; if (dnactr >= num_of_neurons) { break; } // num_of_neurons } // if (dnactr >= drawgrid_DNA_Length) { break; } if (dnactr >= num_of_neurons) { break; } } /* Update just the part of the display that we've changed */ SDL_UpdateRect(surface, 0, 0, drawgrid_screenwidth-1, drawgrid_screenheight-1); } void loadcrit(int dnalength, int popsize, Uint8 **DNA, Uint8 **Brains, Uint8 *neuroncount, unsigned int *DNA_IP, unsigned int *generations, char *fn, char *brainfile) { // i should load their dna_ip too in neural version in case starting at // 0 mangles the brains although they should be able to deal with that // when evolved... (ok) int i; int j; int q = (random()/(RAND_MAX>>8))%4; Uint8 loaddna[dnalength]; Uint8 loadbrain[(num_of_neurons+1)*num_of_synapses]; printf("Attempting to load DNA from ./ca-ga.load.dna and brain from ./ca-ga.load.brain because this is neural version\n"); FILE*iff=fopen(fn,"rb"); if (iff == NULL) { printf("puke (no such dna file)\n"); return; } unsigned int loadedgeneration = 0; unsigned int loadeesdnaip = 0; loadedgeneration = (int) getc(iff)*256; loadedgeneration+= (int) getc(iff); loadeesdnaip = (int) getc(iff)*256; loadeesdnaip+= (int) getc(iff); for (i = 0; i < dnalength; i++) { loaddna[i] = getc(iff); } fclose(iff); Uint8 loadedneuroncount = 0; iff=fopen(brainfile,"rb"); if (iff == NULL) { printf("puke (no such brain file)\n"); return; } loadedneuroncount = getc(iff); for (i = 0; i < (num_of_neurons+1)*num_of_synapses; i++) { loadbrain[i] = getc(iff); } fclose(iff); printf( "DNA loaded\n"); int many = 0; for (i = 0; i < popsize; i++) { q++; if (q == 4) { // printf("Load one to pop offset #%i\n", i); q = 0; *generations = loadedgeneration; *DNA_IP = loadeesdnaip; Uint8 *somedna = *DNA; for (j=0;j 0; soughtgen--) { while (*generations != soughtgen && offs < popsize) { //printf("debug: skipping animal of gen %i not of %i\n", *generations, soughtgen); generations++; offs++; neuroncount++; DNA_IP++; } if (offs >= popsize) { generations-=popsize; neuroncount -= popsize; DNA_IP -= popsize; offs = 0; } else {break;}// hm } if (soughtgen>0) { // DNA+=(dnalength*offs); pre malloc? DNA+=offs; Uint8 *somedna = *DNA; Brains += offs; Uint8 *somebrain = *Brains; // hopefully it is the same brain printf ("Succeeds at population offset %i with critter of generation #%i\n", offs, soughtgen); int c; printf ("Write DNA ... "); FILE*of=fopen(fn,"wb"); putc((char) (*generations/ 256), of); putc((char) (*generations% 256), of); //or what putc((char) (*DNA_IP/ 256), of); putc((char) (*DNA_IP% 256), of); //or what for (c = 0; c < dnalength; c++) { putc((char) somedna[c], of); // DNA++; } fclose(of); printf ("succeeded\n"); printf ("Write brain ... "); of=fopen(brainfile,"wb"); putc((char) *neuroncount, of); for (c = 0; c < (num_of_neurons+1)*num_of_synapses; c++) { putc((char) somebrain[c], of); // DNA++; } fclose(of); printf ("succeeded\n"); } else { printf ("wtf i couldn't find any DNA over generation -1\n"); } } void loadall(int dnalength, int popsize, Uint8 **DNA, Uint8 **Brains, Uint8 *neuroncount, unsigned int *DNA_IP, unsigned int *generations, char *fn, char *brainfile) { // i should load their dna_ip too in neural version in case starting at // 0 mangles the brains although they should be able to deal with that // when evolved... (ok) int i; int j; Uint8 loaddna[dnalength]; Uint8 loadbrain[(num_of_neurons+1)*num_of_synapses]; int many = 0; printf("Attempting to load DNA from %s and brain from %s because this is neural version\n", fn, brainfile); FILE*iff=fopen(fn,"rb"); if (iff == NULL) { printf("puke (no such dna file)\n"); return; } FILE*biff=fopen(brainfile,"rb"); if (biff == NULL) { printf("puke (no such brain file)\n"); return; } unsigned int loadedgeneration = 0; unsigned int loadeesdnaip = 0; for (i = 0; i < popsize; i++) { loadedgeneration = (int) getc(iff)*256; loadedgeneration+= (int) getc(iff); loadeesdnaip = (int) getc(iff)*256; loadeesdnaip+= (int) getc(iff); for (j = 0; j < dnalength; j++) { loaddna[j] = getc(iff); } Uint8 loadedneuroncount = 0; loadedneuroncount = getc(biff); for (j = 0; j < (num_of_neurons+1)*num_of_synapses; j++) { loadbrain[j] = getc(biff); } printf("generation %i neuroncount %i DNA_IP %i pop offset #%i\n", loadedgeneration, loadedneuroncount, loadeesdnaip, i); *generations = loadedgeneration; *DNA_IP = loadeesdnaip; Uint8 *somedna = *DNA; for (j=0;j>8; unsigned int c; // Uint8 *somedna = DNA[source_x][source_y]; recurse += 1; // printf ("recursive_fair_breed(start)\n"); if (offspring[dest_x][dest_y][0] != 255) { // not safe to breed yet. recurse if (x_3 != 255 && (dest_x == x_3 && dest_y == y_3)) { // printf("recurse: Three cells trying to loop the recurser. Prioritizing the first\n"); } else if ((offspring[dest_x][dest_y][0] == source_x && offspring[dest_y][dest_x][1] == source_y) ) { // printf("recurse: Two cells trying to overwrite each other, prioritizing the first\n"); // would be better to do the swap they want rather than cancel the second or // third breeder in the loop... but how } else { // could still get stuck on loops of 3 or more cells so. use a // max recursion, max_breed_fairness ! if (recurse <= max_breed_fairness) { // printf("recurse: recursive_fair_breed(source_x=%i source_y=%i dest_x=%i dest_y=%i)\n", dest_x, dest_y, offspring[dest_x][dest_y][0], offspring[dest_x][dest_y][1]); recurse = recursive_fair_breed(dest_x, dest_y, offspring[dest_x][dest_y][0], offspring[dest_x][dest_y][1], source_x, source_y, offspring, DNA, Brains, neuroncount, generations, sexctr, skips, DNA_IP, dnarun_add, breeds, splits, maxIP, sex_on, recurse); // printf("recurse: comes back after recurse of %i\n", recurse); } else { } // printf("recurse: recursed too deep\n"); } } } // fall thru Uint8 *thisdna = (Uint8 *) DNA[source_x][source_y]; dnarun_add[dest_x][dest_y] += freeEnergyToOffspring; // recolor int lastip = DNA_IP[dest_x][dest_y]; if (lastip > *maxIP) { *maxIP = lastip; } // DNA_IP[dest_x][dest_y] = 0; // reboot DNA_IP[dest_x][dest_y] = DNA_IP[source_x][source_y]; // kickstart (experimental) sexctr[dest_x][dest_y] = 0; skips[dest_x][dest_y] = 0; int mutant = (random()/randomdivisor) % mutantrate; // n% are mutants // int mutant = 1000; //breedorsplit = (random()/randomdivisor) % 2; // half the time breed // half the time split if (sexctr[source_x][source_y]>0 && sex_on) { // mingle (slow!) // printf ("mingle\n"); if (generations[dest_x][dest_y] != generations[source_x][source_y]) { generations[dest_x][dest_y] = ((generations[source_x][source_y] + generations[dest_x][dest_y])>>1)+1; // same generation dont increment.. } *breeds += 1; int r = 0; char b = (random()/randomdivisor); // printf ("init newdna\n"); Uint8 *newdna = (Uint8 *) DNA[dest_x][dest_y]; // printf ("newdna init'd\n"); for (c = 0; c < DNA_Length; c++) { if (b&1) { // parent newdna[c] = thisdna[c]; // printf ("2\n"); } // else { // DNA[destx][desty][c] = thisdna[c]; // keeps its own byte // printf ("1\n"); // } } b>>1; r++; if (r == 8) { r = 0; b = (random()/randomdivisor); } } else { // split // printf ("3\n"); // printf ("split\n"); generations[dest_x][dest_y] = generations[source_x][source_y]; *splits += 1; // printf ("init newdna\n"); Uint8 *newdna = (Uint8 *) DNA[dest_x][dest_y]; // printf ("newdna init'd\n"); for (c = 0; c < DNA_Length; c++) { newdna[c] = thisdna[c]; } } if (mutant == 0) { // printf("mutate\n"); generations[dest_x][dest_y]++; int maxoffset; // if ((random())>(RAND_MAX>>1)) { // bias /* if (lastip>DNA_Length) {lastip=DNA_Length-4;} */ // use this for a mutation bias // when rebooting new cells at // DNA_IP 0... if you resume // at the parents IP in the // child like i'm experimenting // with, set lastip to DNA_Length // like the line below lastip = DNA_Length-4; maxoffset = (lastip>>2)+1; // last op // } else { // dont // maxoffset = (DNA_Length_div_two); // } // trying if i always bias. this is only bad when // IP's start hitting max and rolling over. using // a table of lifespans to decide what offset if // any to mutate under would be superior to this, // for when that happens. otherwise biasing half // the time i think is an expensive hack int first = 1; int oporarg = (random()/randomdivisor)%4; // damn a whole byte of randomness for this int limit; // ^ this is ok now if (oporarg > 0) { limit = 256; } else { limit = 6; } while (((random()/randomdivisor)%remutaterate < 99) || first) { first = 0; // int offset = ( ( ( (int)(random()/randomdivisor) )*256 )+(int)(random()/randomdivisor) ) % (DNA_Length/2); // as long as all mutations reboot you we can just mutate bytes up to the // highest IP this cell has reached yet and get more useful mutations in // cold parts of the world that way // it's not the destination's DNA we use after a kill // unless it was a breed. but i think collecting mutations // to under the IP of the dead cell about half the time // say, will make species faster and promote strategies // to live long to preserve early genetic material. only // problem is critters who live to the end of the genome // and loop will still only get mutated under the point // where they died in spite of having run the whole thing // unless i had a table for ones that had or an extra // check here so i'll just do it half the time instead // kind of a bias. well it looks good in practice tbh int offset = ( ( ( (int)(random()/randomdivisor) )<<8 )+(int)(random()/randomdivisor) ) % (maxoffset); int c = ((random()/randomdivisor)%limit); thisdna[offset*4 + oporarg] = c; } } Uint8 *oldbrainptr = (Uint8 *) Brains[source_x][source_y]; Uint8 *newbrainptr = (Uint8 *) Brains[dest_x][dest_y]; for (c = 0; c < (num_of_neurons+1)*num_of_synapses; c++) { // newbrainptr[c] = defaultbrain[c]; // reboot childs brain (have to add defaultbrain as an argument to the breed func) newbrainptr[c] = oldbrainptr[c]; // copy living brain (experimental) // this is associated with copying // the DNA_IP of the parent instead // of resetting it, above, too... // i dunno but it will let them // run the whole dna of any size // i choose at least... through // strain tiime } neuroncount[dest_x][dest_y] = neuroncount[source_x][source_y]; offspring[source_x][source_y][0] = 255; offspring[source_x][source_y][1] = 255; offspring[dest_x][dest_y][0] = 255; offspring[dest_x][dest_y][1] = 255; return recurse; } void showprog(Uint8 *prog, char *opcd, unsigned int proglen, unsigned int ip, unsigned int dp, Uint8 *data) { unsigned int i = 0; printf("\n\nProgram:\n"); for (i = 0; i>8; int drawevery = 3; int exitafter = 0; // int biteAmount = 7; // i evolved for a while at these settings but // int freeGiveBonus = 5; // i dont think they're enough // int biteAmount = 12; // // int freeGiveBonus = 7; // cells still don't live long at these values // int biteAmount = 5; // int freeGiveBonus = 3; // int freeEnergyToOffspring = 7; // int gridrows = 170; // int gridcols = 213; // you get weird ropes around this ratio // fuck with it, maybe smaller and they // knot up and shit // int gridrows = 70; // ok // int gridcols = 110; // int gridrows = 52; // also ok // int gridrows = 66; // int gridrows = 104; // int gridcols = 142; // int gridrows = 111; // int gridcols = 142; // make it fit (ropy) int minspacingx = 2; int minspacingy = 2; // int minspacingx = 1; // int minspacingy = 1; // maybe store a max IP per cell and only mutate offsets up to it would be // smart // int mutantrate = 9; // 1/n offspring will be mutated. minimum is 1 (100%) // int remutaterate = 4; // 2/n chance of repeat mutations // int DNA_Length = 16384; // even numbers only ok, over 256 is ok (offset takes 2 bytes randomness) // int DNA_Length = 4096; int DNA_Length_div_two = DNA_Length / 3; // remember only even dna lengths // sorry use multiples of 3 for // neural version float DNA_View_Cell_Size_Divisor = 1.0f; // or use 2 most of the time // it crashed for me at 3 one time printf("init dna\n"); Uint8 **DNA[gridcols][gridrows]; Uint8 **dnaptr = &DNA; Uint8 **Brains[gridcols][gridrows]; Uint8 did_fire[num_of_neurons+1]; Uint8 CellZero_did_fire[num_of_neurons+1]; Uint8 neuralzeroes[num_of_neurons+1]; Uint8 neuralones[num_of_neurons+1]; // Uint8 j = 0; // Uint8 i = 0; // for larger grid, use ints to loop int j = 0; int i = 0; for (j = 0; j <= num_of_neurons; j++) { did_fire[j] = 0;} for (j = 0; j <= num_of_neurons; j++) { CellZero_did_fire[j] = 0; neuralzeroes[j] = 0; neuralones[j] = 1; } Uint8 *defaultbrain[num_of_neurons+1][num_of_synapses]; // default brain (these synapses cant be removed) Uint8 neuroncount[gridcols][gridrows]; for (i = 0; i < gridrows; i++) { for (j = 0; j < gridcols; j++) { neuroncount[j][i] = cortical_neurons;// size of defaultbrain } } // int motor = 240; // int sensor = 8; // int sensorormotor = 0; int t = 0; defaultbrain[0][0] = 0; defaultbrain[0][1] = 0; for (t = 2; t < num_of_synapses; t+=4) { defaultbrain[0][t] = 0; defaultbrain[0][t+1] = 0; defaultbrain[0][t+2] = 1; defaultbrain[0][t+3] = 32; } for (j = 1; j <= cortical_neurons; j++) { // starts at 1... 0 is no neuron... 65 is temp sense int p = 0; int k = 0; if (j == 1) { p = cortical_neurons; } else { p = j-1; } if (j == cortical_neurons) { k = 1; } else { k = j+1; } defaultbrain[j][0] = 0; // potential defaultbrain[j][1] = 8; // threshold defaultbrain[j][2] = p; defaultbrain[j][3] = 0; // 0 = excit, 1 = inhib, 2 = excit plas, 3 = inhib plas defaultbrain[j][4] = 1; // weight (signal multiplier) defaultbrain[j][5] = 32; // plasticity modifier (reduced by inhibitory // firing on plastic neurons, increased by excit, // subtracted by 32 and multiplied by weight if plast) defaultbrain[j][6] = k; defaultbrain[j][7] = 1; // inhib defaultbrain[j][8] = 1; // weight defaultbrain[j][9] = 32; defaultbrain[j][10] = ((random()/(RAND_MAX>>8))%(cortical_neurons))+1; defaultbrain[j][11] = 0; // inhib defaultbrain[j][12] = 1; // weight defaultbrain[j][13] = 32; defaultbrain[j][14] = ((random()/(RAND_MAX>>8))%(cortical_neurons))+1; defaultbrain[j][15] = 1; // inhib defaultbrain[j][16] = 1; // weight defaultbrain[j][17] = 32; printf("wire cortical neuron %i to %i and %i\n", j, p, k); /* if (sensorormotor == 0) { defaultbrain[j][10] = sensor; sensor += 1; if (sensor > 32) { sensor = 1; } sensorormotor = 1; } else { defaultbrain[j][10] = motor; // no neurons with motors and sensors motor += 1; if (motor > 255) { motor = 224; } sensorormotor = 0; } /* defaultbrain[j][11] = 0; // inhib defaultbrain[j][12] = 1; // weight defaultbrain[j][13] = 0; */ // look... instead of using synapses for motor and sensor connections, // since i don't want them adding and removing those anyway just synapses // to and from neurons that are permanently wired to a motor or sensor, // just read them staggered from 0 to 62 as if those 32 neurons were // hooked up to the respective sensor, and from 1 to 63 as if they had // the respective motor... see in the brains run... this will be easy // and then i can have 256 neurons again int t = 18; for (t = 18; t < num_of_synapses; t+=4) { defaultbrain[j][t] = 0; defaultbrain[j][t+1] = 0; defaultbrain[j][t+2] = 1; defaultbrain[j][t+3] = 32; } } for (j = 69; j <= num_of_neurons; j++) { defaultbrain[j][0] = 0; defaultbrain[j][1] = 10; int t = 2; for (t = 2; t < num_of_synapses; t+=4) { defaultbrain[j][t] = 0; defaultbrain[j][t+1] = 0; defaultbrain[j][t+2] = 1; defaultbrain[j][t+3] = 32; } } unsigned int DNA_IP[gridcols][gridrows]; // maybe I can give them n heads a piece and when bumped, they can jmp // the head which some index i just increment to dnalength per frame is // closest to... rather than every head or something. then they can // have some parallel evaluation. just add [heads] here and a heads // loop to the dna run. later on // oh give them a head for each direction then pokes can jump the head // for the dir they came from, 8 heads unsigned int generations[gridcols][gridrows]; Uint8 skips[gridcols][gridrows]; Uint8 newskips[gridcols][gridrows]; Uint8 neurskipsandstuns[gridcols][gridrows]; // DNA: // 1 byte, 1 byte // byte 1: suck/give/wait // byte 2: direction // if sucking puts a cell under 0 copy dna to it // with mutations #define drawsbetweenscoreoutput 1000 #define dumplogevery 3000 int dumplogctr = 0; #define newprogevery 1024 int newprogctr= newprogevery ; int c = 0; j = 0; int lostfights = 0; int wonfights = 0; int nops = 0; int neuralnops = 0; int neuralskips = 0; int neuralstuns = 0; // not too sure... maybe a fight should be harder with a cell who is NOP'ing // ok. it is printf ("load dna\n"); for (i = 0; i < gridrows; i++) { // what if it was self-modifying? three new for (j = 0; j < gridcols; j++) { // opcodes could move a head and pop DNA_IP[j][i] = 0; // the cell's value or one from a stack. // hm skips[j][i] = 0; newskips[j][i] = 0; generations[j][i] = 0; printf ("Malloc DNA %i,%i\n",j,i); DNA[j][i] = malloc(DNA_Length+1); printf ("Malloc Brain %i,%i\n",j,i); Brains[j][i] = malloc((num_of_neurons+1)*(num_of_synapses)+1); // potential // threshold // then synapses int t = 0; int neur = 0; printf ("fill brain\n"); Uint8 *brainptr = Brains[j][i]; printf("pointer ok\n"); for (t = 0; t <= num_of_neurons; t++) { for (c = 0; c < num_of_synapses; c++) { *brainptr = (Uint8) defaultbrain[t][c]; brainptr++; } } // Uint8 *tempdna = malloc(DNA_Length); // wtf printf("fill dna\n"); Uint8 *thisdna = DNA[j][i]; // these should be bit packed (its only 6 bits information per opcode & operand atm) printf("pointer ok\n"); for (c = 0; c <= DNA_Length; c++) { thisdna[c] = (random()/randomdivisor)%6; c++; thisdna[c] = (random()/randomdivisor)%(num_of_neurons+1); c++; thisdna[c] = (random()/randomdivisor)%(num_of_neurons+1); c++; thisdna[c] = (random()/randomdivisor)%(num_of_neurons+1); } } } printf ("random dna ready... default brains built\n"); Uint8 *thisdna = &DNA; printf ("%i\n", (int) thisdna[0]); printf ("%i\n", (int) (random()/RAND_MAX)); int cellwidth = (screenwidth/gridcols)-minspacingx; // int cellheight = (screenheight/(gridrows+((DNA_Length/DNA_View_Cell_Size_Divisor)/(gridcols*DNA_View_Cell_Size_Divisor))+1))-minspacingy; int cellheight = ((screenheight/((gridrows)+((num_of_neurons/DNA_View_Cell_Size_Divisor)/(gridcols*DNA_View_Cell_Size_Divisor))-1))-minspacingy); int xspace = minspacingx+((screenwidth-(gridcols*(cellwidth+minspacingx))) / gridcols); // int yspace = minspacingy+((screenheight-((gridrows+((DNA_Length/DNA_View_Cell_Size_Divisor)/(gridcols*DNA_View_Cell_Size_Divisor))+1)*(cellheight+minspacingy))) / (gridrows+(DNA_Length/gridcols)+1)); int yspace = minspacingy+((screenheight-((gridrows+((num_of_neurons/DNA_View_Cell_Size_Divisor)/(gridcols*DNA_View_Cell_Size_Divisor))+1)*(cellheight+minspacingy))) / (gridrows+(num_of_neurons/gridcols)+1)); // ^^ 254 == num_of_neurons (done) printf ("screenwidth %i\nscreenheight %i\ngridX %i\ngridY %i\ncellwidth %i\ncellheight %i\nxspace %i\nyspace %i\n", screenwidth, screenheight, gridcols, gridrows, cellwidth, cellheight, xspace, yspace); Uint8 grid[gridcols][gridrows]; // int tctr=0; printf ("get grid\n"); for (i = 0; i < gridrows; i++) { for (j = 0; j < gridcols; j++) { // grid[j][i] = (j*i)*4; // interesting seed grid[j][i] = (random()/randomdivisor); // grid[j][i] = tctr; tctr++; if(tctr>255){tctr=0;} // printf ("grid[%i][%i] = %i\n", j, i, grid[j][i]); if (grid[j][i] > 256) { grid[j][i] = 0; } // grid[j][i] = 30; } } printf("Initializing SDL.\n"); /* Initialize defaults, Video and Audio */ if((SDL_Init(SDL_INIT_VIDEO)<0)) { printf("Could not initialize SDL: %s.\n", SDL_GetError()); exit(-1); } printf("SDL initialized.\n"); /* Clean up on exit */ atexit(SDL_Quit); SDL_Event event; /* * Initialize the display in a 640x480 8-bit palettized mode, * requesting a software surface */ SDL_Surface *screen; screen = SDL_SetVideoMode(screenwidth, screenheight, 8, SDL_SWSURFACE); if ( screen == NULL ) { fprintf(stderr, "Couldn't set %ix%ix8 video mode: %s\n", screenwidth, screenheight, SDL_GetError()); exit(1); } Uint8 tgrid[gridcols][gridrows]; for (i = 0; i < gridrows; i++) { for (j = 0; j < gridcols; j++) { tgrid[j][i] = grid[j][i]; } } Uint8 dnarun[gridcols][gridrows]; for (i = 0; i < gridrows; i++) { for (j = 0; j < gridcols; j++) { dnarun[j][i] = grid[j][i]; } } Uint8 dnarun_sub[gridcols][gridrows]; for (i = 0; i < gridrows; i++) { for (j = 0; j < gridcols; j++) { dnarun[j][i] = grid[j][i]; } } Uint8 dnarun_add[gridcols][gridrows]; for (i = 0; i < gridrows; i++) { for (j = 0; j < gridcols; j++) { dnarun[j][i] = grid[j][i]; } } Uint8 actions_view[gridcols][gridrows]; for (i = 0; i < gridrows; i++) { for (j = 0; j < gridcols; j++) { dnarun[j][i] = grid[j][i]; } } Uint8 offspring[gridcols][gridrows][2]; // to buffer reproduction for second run // NOTE if you need a grid larger than // 254x254, change Uint8 here to an int ! // and initialize offspring[] initial // values to -1 instead of 255 and // change the check in the breed run // accordingly and the set in the // dna run for (i = 0; i < gridrows; i++) { for (j = 0; j < gridcols; j++) { offspring[j][i][0] = 255; offspring[j][i][1] = 255; } } // int lastip[gridcols][gridrows]; // for better mutations // for (i = 0; i < gridrows; i++) { // for (j = 0; j < gridcols; j++) { // lastip[j][i]=1; // } // } // oh it only takes one int int maxIP = 0; // probably need a table for graphing actions // what about buffering the actions of low energy critters for n frames // and letting high energy critters act faster? int giveamount = biteAmount+freeGiveBonus; // careful Uint8 tstimuli[gridcols][gridrows][4][8]; Uint8 stimuli[gridcols][gridrows][4][8]; for (i=0;i>1; Uint8 y = gridrows>>1; Uint8 z2 = (Uint8) gridcols>>2; Uint8 y2 = gridrows>>2; Uint8 z3 = (Uint8) gridcols>>4; Uint8 y3 = gridrows>>4; Uint8 gridrowsminusy2 = gridrows - y2; Uint8 gridcolsminusz2 = gridcols - z2; // ^ move these inside the loop if you allow resizing the grid while(1) { // live Uint8 run; int i; int j; /* Poll for events. SDL_PollEvent() returns 0 when there are no */ /* more events on the event queue, our while loop will exit when */ /* that occurs. */ while( SDL_PollEvent( &event ) ){ /* We are only worried about SDL_KEYDOWN and SDL_KEYUP events */ switch( event.type ){ case SDL_KEYDOWN: /* Check the SDLKey values and move change the coords */ switch( event.key.keysym.sym ){ case SDLK_SLASH: printf(""); case SDLK_h: printf ("(( Key help\n\ (V) to toggle views\n\ (D) to toggle DNA\n\ (C) to toggle CA\n\ (S) to toggle sex\n\ (X) to export a DNA\n\ (L) to load some DNA\n\ (Y) to toggle synapse view\n\ PgDwn saves the whole population to files starting ca-ga.whole-pop.*\n\ PgUp loads the whole population from files starting ca-ga.whole-pop.*\n\n\ (Q) to export some strains & quit\n"); break; case SDLK_d: if (DNA_on) {DNA_on=0;printf("DNA run suspended! D to resume\n"); } else {DNA_on=1;printf("DNA run enabled. Thank you\n");} break; case SDLK_c: if (CA_on) {CA_on=0;printf("CA run suspended! C to resume\n"); } else {CA_on=1;printf("CA run enabled. Good luck\n");} break; case SDLK_s: if (sex_on) {sex_on=0;printf("Sex disallowed, S to resume\n"); } else {sex_on=1;printf("The reproductive suppression field has been disabled\n");} break; case SDLK_v: if (view == 0) {view=1;printf("Generation count view on, V to switch\n");} else if (view == 1) {view=2;printf("Stun view on, V to switch\n");} else if (view == 2) {view=3;printf("Breed mood view on, V to switch\n");} else if (view == 3) {view=4;printf("DNA IP view on, V to switch\n");} else if (view == 4) {view=5;printf("Give view on, V to switch\n");} else if (view == 5) {view=6;printf("Bite view on, V to switch\n");} else if (view == 6) {view=7;printf("Poke view on, V to switch\n");} else if (view == 7) {view=8;printf("Fight view on, V to switch\n");} else if (view == 8) {view=9;printf("NOP view on, V to switch\n");} else if (view == 9) {view=10;printf("Neuron count view on, V to switch\n");} else if (view == 10) {view=11;printf("Did Input view on, V to switch\n");} else if (view == 11) {view=12;printf("Output view on, V to switch\n");} else if (view == 12) {view=13;printf("Neural SKip/Stun of DNA view on (skips dark, stuns bright), V to switch\n");} else if (view == 13) {view=0;printf("Normal view on, V to switch\n");} break; case SDLK_x: savecrit(highgen, DNA_Length, popsize, DNA, Brains, neuroncount, &DNA_IP, &generations, "ca-ga.best.dna", "ca-ga.best.brain"); savecrit(avggen, DNA_Length, popsize, DNA, Brains, neuroncount, &DNA_IP, &generations, "ca-ga.average.dna", "ca-ga.average.brain"); savecrit(lowgen+1, DNA_Length, popsize, DNA, Brains, neuroncount, &DNA_IP, &generations, "ca-ga.low.dna", "ca-ga.low.brain"); break; case SDLK_q: savecrit(highgen, DNA_Length, popsize, DNA, Brains, neuroncount, &DNA_IP, &generations, "ca-ga.best.dna", "ca-ga.best.brain"); savecrit(avggen, DNA_Length, popsize, DNA, Brains, neuroncount, &DNA_IP, &generations, "ca-ga.average.dna", "ca-ga.average.brain"); savecrit(lowgen+1, DNA_Length, popsize, DNA, Brains, neuroncount, &DNA_IP, &generations, "ca-ga.low.dna", "ca-ga.low.brain"); printf("Free DNA\n"); for (i = 0; i < gridrows; i++) { for (j = 0; j < gridcols; j++) { Uint8 *temp = DNA[gridcols][gridrows]; // free(&temp); } } printf("Shutdown\n"); return 0; break; case SDLK_l: printf("Load ca-ga.load.dna\n"); loadcrit(DNA_Length, popsize, DNA, Brains, neuroncount, &DNA_IP, &generations, "ca-ga.load.dna", "ca-ga.load.brain"); break; case SDLK_y: printf("Synapse display toggled "); if (showsynapses == 0) { printf("(fired)\n"); showsynapses = 1; } else if (showsynapses == 1) { printf("(half)\n"); showsynapses = 2; } else if (showsynapses > 1 && showsynapses < 4) { printf ("(all)\n"); showsynapses = 5; } else if (showsynapses == 5) { printf ("(off)\n"); showsynapses = 0; } break; case SDLK_PAGEUP: printf("Load ca-ga.whole-pop.load.dna (make sure its exists)\n"); printf("Load ca-ga.whole-pop.load.brain (make sure its exists)\n"); loadall(DNA_Length, popsize, DNA, Brains, neuroncount, &DNA_IP, &generations, "ca-ga.whole-pop.load.dna", "ca-ga.whole-pop.load.brain"); break; case SDLK_PAGEDOWN: saveall(DNA_Length, popsize, DNA, Brains, neuroncount, &DNA_IP, &generations, "ca-ga.whole-pop.dna", "ca-ga.whole-pop.brain"); break; default: break; } break; case SDL_KEYUP: break; default: break; } } highgen = 0; avggen = 0; if (reverseEvaluation > 0) { startx = gridlastx; lastx = -1; inc = -1; starty = gridlasty; lasty = -1; // startx = gridlastx; lastx = 255; inc = -1; // set 255 to allow underflow // on Uint8 loop counters // its just faster // starty = gridlasty; lasty = 255; reverseEvaluation = 0; } else { startx = 0; lastx = gridlastx+1; inc = 1; starty = 0; lasty = gridlasty+1; reverseEvaluation = 1; } // i think the GA is so fair we don't need to do this anymore... // oh the recursive fair breeder will prioritize first comers on // the board eval order so we might as well still go both ways... // darn newprogctr += 1; if (newprogctr >= newprogevery) { for (j = 0; j < datalen;j++) { data[j] = 0; } newprogctr = 0; // unsigned int opcodes = 11; // char opcd[] = " v^<>-+,.[]"; unsigned int opcodes = 7; char opcd[] = " <>-+[]"; /* unsigned int p = 0; for (p = 0; p < wX*3; p++) { tape[p]=0; } */ // no tape... i'll remove . and , and let them guess bytes from the // data field instead printf("bf-ga.c.\n"); printf("%i opcodes: ' ' NOP < ++DP < --DP\n+ ++*DP - --*DP [ JZ/LOOP ] ENDLOOP\n", opcodes); printf("%i-byte program\n", proglen); printf("pipe urandom to stdin\n"); unsigned int i = 0; for (i = 0; i>8)); prog[i] = a%opcodes; } unsigned int ip = 0; unsigned int dp = 0; // printf("Sleep 3\n"); // system("sleep 3"); unsigned int nextip = 9999999; unsigned int progcycles = 2048; unsigned int progctr = 0; for (progctr = 0; progctr < progcycles; progctr++) { if (nextip != 9999999) { ip = nextip; nextip = 9999999; } else { ip++; } ip = ip % proglen; // dp++; // testing if (prog[ip] == 1) { //printf("<\n"); if (dp > 0) { dp--; } // } else { // dp = datalen - 1; // } } else if (prog[ip] == 2) { //printf(">\n"); if (dp < datalen - 1) { dp++; } // data pointer can stick at edge // } else if (prog[ip] == 1) { // dp+=wX; // } else if (prog[ip] == 2) { // if (dp < wX) { dp = (proglen - wX) + dp; } else { dp-=wX; } } else if (prog[ip] == 3) { //printf("-\n"); if (data[dp] > 0) { data[dp]--; } // else { data[dp] = 255; } } else if ( prog[ip] == 4) { if (data[dp] < 255) { // 10 = opcodes - 1 (11 - 1) //printf("+\n"); data[dp]++; } // else { data[dp] = 0; } /* } else if (prog[ip] == 5) { char r = (random()/(RAND_MAX>>8))%256; data[dp] = r; // ray_ctr = 0; // got randomness no rays } else if (prog[ip] == 6) { tape[tape_index] = data[dp]; tape_index++; if (tape_index == wX*3) { tape_index = 0; } */ } else if (prog[ip] == 5) { if (data[dp] == 0) { // jump to ] if 0 or >0 choose //printf("[\n"); unsigned int Tip = ip; Tip++; unsigned int opens = 1; while ((prog[Tip] != 6 || opens > 1) && Tip != (ip+1)%proglen) { if (prog[Tip] == 6) { if (opens > 1) { opens--; } else {break;} } if (prog[Tip] == 5) { opens++; } if (Tip = proglen) { Tip = 0; } else { Tip++; } } nextip = (Tip+1)%proglen; } } else if (prog[ip] == 6) { // jump to [ if !0 or 0 choose //printf("]\n"); if (data[dp] > 0) { unsigned int Tip = ip; if (ip > 0) { Tip--; } else { Tip = proglen - 1; } unsigned int closes = 1; while ((prog[Tip] != 5 || closes > 1) && Tip != (ip+1)%proglen) { if (prog[Tip] == 6) { closes++; } if (prog[Tip] == 5) { if (closes > 1) { closes--; } else {break;} } if (Tip == 0) { Tip = proglen; } Tip--; } nextip = (Tip+1)%proglen; } } } showprog(&prog, &opcd, proglen, ip, dp, &data); printf ("bf eval complete (debug)\n"); } // prog running part ends if (view >= 5 && view <= 9) { for (i = 0; i < gridrows; i++) { for (j = 0; j < gridcols; j++) { actions_view[j][i] = 0; } } } for (run = 0; run < 4; run++) { // eval in reverse half the time // to get rid of the 'wind' from // not using enough temp grids to // make all the actions fair // in both directions // all the time // printf("run %i\n", run); for (i = starty; i != lasty; i+=inc) { for (j = startx; j != lastx; j+=inc) { // for (i = 0; i < gridrows; i++) { // for (j = 0; j < gridcols; j++) { signed int newcell; if (run == 0) { // dna run offspring[j][i][0] = 255; offspring[j][i][1] = 255; // newskips[j][i] = 0; if (DNA_on) { // dnarun[j][i] = newcell; if (sexctr[j][i]>0) { sexctr[j][i]--; } if (skips[j][i] > 7) { // printf("skip"); skipsctr++; // skip makes goto's now, like direction sense sorta (no see below) //DNA_IP[j][i] += (skips[j][i]%8)*2; //while (DNA_IP[j][i] >= DNA_Length) {DNA_IP[j][i] -= DNA_Length;} // ^ since Pokes and Fights both push out a critter's IP, and NOP // doesn't except at this stage, and is a defense against Fight // ... this line would turn NOP's into JMP's... without it, they // could NOP twice to stun themselves into spending an extra // frame on the defensive NOP. newskips[j][i] = skips[j][i] - 8; } else { if (skips[j][i] > 0) { newskips[j][i] = 0; } Uint8 *thisdna = DNA[j][i]; Uint8 op = thisdna[DNA_IP[j][i]]; Uint8 arg = thisdna[DNA_IP[j][i]+1]; Uint8 arg2 = thisdna[DNA_IP[j][i]+2]; Uint8 arg3 = thisdna[DNA_IP[j][i]+3]; // while (arg3 > 4) { arg -= 4; sexctr[j][i] += sexoperandpersistance; } // op = 0; // no if (op != 0) { Uint8 *brainptr = Brains[j][i]; Uint8 syn; Uint8 freesynapse = 255; // look out if (op == 1) { // new synapse if (arg == 0) { arg = 1; } if (arg2 == 0) { arg2 = 1; } // 0 is no neuron for (syn = 2; syn < num_of_synapses; syn+=4) { if (brainptr[(num_of_synapses*(arg%(neuroncount[j][i]+1))) + syn] == 0) { freesynapse = syn; break; } } if (freesynapse < 255) { // room on the neuron for a synapse brainptr[(num_of_synapses*(arg%(neuroncount[j][i]+1)))+freesynapse] = (arg2%num_of_neurons)+1; // id of neuron new synapse signals firing of brainptr[(num_of_synapses*(arg%(neuroncount[j][i]+1)))+freesynapse+1] = arg3&3; // type of synapse (0 to 3) brainptr[(num_of_synapses*(arg%(neuroncount[j][i]+1)))+freesynapse+2] = (arg3>>5)+1; // weight of synapse (1 to 8) brainptr[(num_of_synapses*(arg%(neuroncount[j][i]+1)))+freesynapse+3] = 32; // reset plasticity } } else if (op == 2) { // new neuron if (neuroncount[j][i] < num_of_neurons) { neuroncount[j][i] += 1; brainptr[(num_of_synapses*neuroncount[j][i])] = arg2; // zero potential on 'new' neuron (or should it be arg3) Uint8 newthresh = arg; if (newthresh == 0) { newthresh = 1; } brainptr[(num_of_synapses*neuroncount[j][i])+1] = newthresh; // set threshold of 'new' neuron } } else if (op == 3) { // pull neuron //if (neuroncount[j][i] > cortical_neurons) { if (neuroncount[j][i] > 1) { neuroncount[j][i] -= 1; } } else if (op == 4) { // pull synapse Uint8 lastsynapse = 255; if (arg == 0) { arg = 1; } for (syn = 2; syn < num_of_synapses; syn+=4) { if (brainptr[(num_of_synapses*(arg%(neuroncount[j][i]+1))) + syn] == 0) { break; } lastsynapse = syn; } if (lastsynapse < 255) { // found a last synapse on that neuron (also not the first) brainptr[(num_of_synapses*(arg%(neuroncount[j][i]+1)))+lastsynapse] = 0; // deactivate it } } else if (op == 5) { // alter neuron if (arg == 0) {arg = 1;} // 0 is no neuron if (arg3 == 0) { arg3 = 1; } // 0 is no threshold brainptr[((num_of_synapses*(arg%(neuroncount[j][i]+1))))] = arg2; // arg 1 is neuron to change, arg2 is new potential brainptr[((num_of_synapses*(arg%(neuroncount[j][i]+1))))+1] = arg3; // arg 3 is new threshold } } else { // dna nop causes half a stall and helps defend in fights newskips[j][i] += arg3>>5; // well on average... // printf("%i, %i nops\n", j, i); nops += 1; if (view == 9 && t == drawevery-1) { actions_view[j][i] += 1; } } //if (dnarun[j][i] <= 0) { dnarun[j][i] = 1; } DNA_IP[j][i]+=4; // this should have been at the end all along or // i skip the first byte but it can be mutated // still. er while (DNA_IP[j][i] >= DNA_Length) { DNA_IP[j][i] -= DNA_Length; } // end DNA run } // end indented skip check } // else { } // if DNA_on is off *unindented } else if (run == 1) { // brains run if (DNA_on) { Uint8 destx = 0; // NOTE if you ever need a grid bigger than Uint8 desty = 0; // 254x254, make these ints! // and initialize offspring[] initial // values to -1 instead of 255 and // change the check in the breed run // accordingly... and the set in the // dna run... ok! newcell = grid[j][i]; newcell *= .95; // fade Uint8 acts = 0; Uint8 *brainptr = Brains[j][i]; Uint8 dir = 0; Uint8 op = 0; int idx = 0; if (inputs[j][i] > 0) { // flash brainfuck program on sense neurons if (inputs[j][i] < 4) { inputs[j][i] -= 1; } else { inputs[j][i] = 3; } // for 2 turns for (op=0;op<4;op++) { for (dir=0;dir<8;dir++) { idx += num_of_synapses; // start at neuron 1 (hardwired sensory) int amt = prog[(op*8)+dir]*2; stimuli[j][i][op][dir] = 0; // printf("sneur %i pot %i add amt %i", (op*4+dir)+1, brainptr[idx], amt); if ((int) brainptr[idx] + amt > 255) { brainptr[idx] = 255; } else { brainptr[idx] += (Uint8) amt; } idx += num_of_synapses; } } } else { for (op=0;op<4;op++) { for (dir=0;dir<8;dir++) { idx += num_of_synapses; // start at neuron 1 (hardwired sensory) int amt = stimuli[j][i][op][dir]; stimuli[j][i][op][dir] = 0; // printf("sneur %i pot %i add amt %i", (op*4+dir)+1, brainptr[idx], amt); if ((int) brainptr[idx] + amt > 255) { brainptr[idx] = 255; } else { brainptr[idx] += (Uint8) amt; } idx += num_of_synapses; } } // fastest way to load sensor neurons of defaultbrain // if you change its wiring change this too... to // look the right places } idx += num_of_synapses; Uint8 amt = (Uint8) newcell / (Uint8) 8; // printf("sneur %i pot %i add amt %i", (op*4+dir)+1, brainptr[idx], amt); if ((int) brainptr[idx] + amt > 255) { brainptr[idx] = 255; } else { brainptr[idx] += (Uint8) amt; } // temperature sense (annoying code duplication indicated) Uint8 neur; Uint8 syn; Uint8 pot; // Uint8 thresh; Uint8 thresh; idx = num_of_synapses; // printf("%i\n", neuroncount[j][i]); for (neur = 0; neur <= num_of_neurons; neur++) { did_fire[neur] = 0;} // ^ optimize this in every version only load and clear to // neuroncount if (i == 0 && j == 0) { for (neur = 0; neur <= num_of_neurons; neur++) { CellZero_did_fire[neur] = 0;} } for (neur = 1; neur <= neuroncount[j][i]; neur++) { if (brainptr[idx] >= brainptr[idx+1]) { // neuron over threshold did_fire[neur] = 1; // fire if (i == 0 && j == 0) { CellZero_did_fire[neur] = 1;} brainptr[idx] = brainptr[idx] % brainptr[idx+1]; // - brainptr[idx+1]; // ^ ... mod by threshold here i guess // if it's not already way too slow or // just use 0... or just use minus and let // potentials take time to clear out why not } // else { did_fire[neur] = 0; } // if (neur > 65 ) { printf ("pot on neur %i is %i\n",neur,brainptr[idx]);} // if (did_fire[neur] && neur > 65) { printf ("fired\n"); } idx += num_of_synapses; } idx = num_of_synapses; for (neur = 1; neur <= neuroncount[j][i]; neur++) { int neuridx = idx; pot = brainptr[idx]; // thresh = brainptr[idx+1]; if (pot > 0) { pot = (Uint8) ( (float) pot * (0.845f+((((float)newcell)/255.0f)/7.0f)) ); } // decay... // decay is adjusted by temperature... lower decay at more energy // at 0 temp, decay is 0.845f... at 255 temp, decay is 0.995 // printf("idx %i neuron #%i pot %i thresh %i\n", idx, neur, brainptr[idx], brainptr[idx+1]); if (brainptr[idx+2] == 0) { // brainptr[idx] = 0; // dont zero it if disconnected // this kills the potential addneuron adds brainptr[neuridx] = pot; // set new potential idx += num_of_synapses; // printf("no synapses to neuron %i (squash this printf after eventually seeing it ok)\n", neur); // break; // ok } else { // decide to decay potential on even disconnected // neurons just for display purposes idx += 2; for (syn = 2; syn < num_of_synapses; syn+=4) { // now brainptr is at the start of a synapse if (brainptr[idx] == 0) { //idx+=(num_of_synapses-syn); break; // making idx = neuridx+num_of_synapses below should handle realignment // synapses are ordered // with no spaces like // neurons ... so stop // looking when you hit // an unconnected one } if (brainptr[idx+1] > 1 && did_fire[neur]) { // types 2 and 3 are plastic if (brainptr[idx+1] & 1) { // inhib if (brainptr[idx+3] < 64) {brainptr[idx+3]++;} else {brainptr[idx+3]=64;} // plast } else { // excit if (brainptr[idx+3] > 0) {brainptr[idx+3]--;} else {brainptr[idx+3]=0;} // plast } } if (did_fire[brainptr[idx]]) { int amt; if (brainptr[idx+1] > 1) { // types 2 and 3 are plastic amt = ((int) brainptr[idx+2]*((int) brainptr[idx+3]-32)); if (brainptr[idx+1] & 1) { if (brainptr[idx+3] > 0) {brainptr[idx+3]--;} else {brainptr[idx+3]=0;} // plast // this is weird... i used plastic synapses not plastic // neurons sort of by accident, well with inhib/excit // neurons i could have normal plastic synapses or // vice versa. so i'll do plasticity the other way // when the host neuron fires too or it will only // drift to min or max depending if the synapse is // inhib or excit... we do this right above this block } else { if (brainptr[idx+3] < 64) {brainptr[idx+3]++;} else {brainptr[idx+3]=64;} // plast } } else { amt = (int) brainptr[idx+2]; } if (brainptr[idx+1] & 1) { amt *= -1; // types 1 and 3 are inhibitory... } if ((int) pot + amt < 0) { pot = 0; } else if ((int) pot + amt > 255) { pot = 255; } else { pot = (Uint8) ((int) pot + amt); } // need these casts or not } idx += 4; // next synapse } brainptr[neuridx] = pot; // set new potential idx = neuridx + num_of_synapses; } // decay potential even on disconnected neurons } // scan motor neurons for firing to set acts and actions[] dir = 0; Uint8 mneur; op = 0; for (mneur = 2; mneur < 65; mneur += 2) { // brainptr += num_of_synapses; if (did_fire[mneur] == 1) { acts = 1; actions[op][dir] = 1; } else { actions[op][dir] = 0; } dir += 1; if (dir == 8) { dir = 0; op += 1; } if (op == 4 && dir > 7) { printf("BORK?!\n"); // remove this block if not borking } } // fastest way to scan motor neurons of defaultbrain // if you change its wiring change this too... to // look the right places // breed mood output if (did_fire[66]) { sexctr[j][i] += sexoperandpersistance; } // I/O motors unsigned int wantstoinput = 0; unsigned int wantstooutput = 0; if (did_fire[67]) { wantstoinput=1; acts = 1; } //printf("wants to input debug\n");} if (did_fire[68]) { wantstooutput=1; acts = 1; } // printf("wants to output debug\n");} neurskipsandstuns[j][i] = 0; // damn slow for nothing. should move 4 bytes at a time, how if (did_fire[69]) { neuralskips += 1; neurskipsandstuns[j][i] += 1; DNA_IP[j][i] += 4; while (DNA_IP[j][i] >= DNA_Length) { DNA_IP[j][i] -= DNA_Length; } } if (did_fire[70]) { if (newcell > 4) { newcell -= 5; } else { newcell = 0; }neuralstuns += 1; neurskipsandstuns[j][i] += 4; newskips[j][i] += 2; } // ok you can stun it for 3/4 a turn the last 2 // skip and stun DNA if (acts) { int mod = 0; for (dir = 0; dir < 8; dir++) { if (i == 0) { up = gridlasty; } else { up = i-1; } if (i == gridlasty) { down = 0; } else { down = i+1; } if (j == 0) { left = gridlastx; } else { left = j-1; } if (j == gridlastx) { right = 0; } else { right = j+1; } if (dir == 0) { destx = left; desty = up; } else if (dir == 1) { destx = j; desty = up; } else if (dir == 2) { destx = right; desty = up; } else if (dir == 3) { destx = left; desty = i; } else if (dir == 4) { destx = right; desty = i; } else if (dir == 5) { destx = left; desty = down; } else if (dir == 6) { destx = j; desty = down; } else if (dir == 7) { destx = right; desty = down; } Uint8 wonafight = 0; if (actions[3][dir] == 1) { // fight // printf("fight\n"); tstimuli[destx][desty][3][dir] += 16; if (view == 8 && t == drawevery-1) { actions_view[destx][desty] += 1; } int high = grid[destx][desty]; int low = grid[j][i]; Uint8 *fighteedna = DNA[destx][desty]; Uint8 fighteeop = fighteedna[DNA_IP[destx][desty]]; if (fighteeop == 0) { low = low >> 1; // double fight difficulty // if victim is un busy // (NOP) which also // opens them to // poke skips and // communication... err if (view == 8 && t == drawevery-1) { actions_view[destx][desty] += 2; actions_view[j][i] += 2; } } // if (low > high) { int T = low; low = high; high = T; } // if ((random()/randomdivisor) % (high+1) <= (low>>4)) { // win fight (oops always uses high cell's odds) if ((random()/randomdivisor) % ((low>>3)+2) >= (random()/randomdivisor) % (high+1)) { // win fight (~ 1/4 chance against cell of equal energy, // ~ 1/2 chance against cell of half energy, // ~ 1/10 chance against cell of double energy, // 2.5% chance against cell of 10x energy) actions[1][dir] = 1; // suck too then, to breed et al wonafight = 1; wonfights += 1; if (view == 8 && t == drawevery-1) { actions_view[j][i] += 2; } //dnarun_add[destx][desty] += biteAmount; } else { // newcell -= biteAmount>>1; mod -= biteAmount; // they fight too much take off full biteAmount instead... // dnarun_sub[destx][desty] += biteAmount>>1; // both lose some energy for a lost fight lostfights += 1; if (fighteeop != 0) { DNA_IP[destx][desty] += (dir+1)<<3; // lost fight signals the winner // with a skip (up to // 32 bytes), if it // is not nopping while(DNA_IP[destx][desty] > DNA_Length) { DNA_IP[destx][desty] -= DNA_Length; } } else { // newskips[destx][desty] += (dir+1); // this was a direction // sense to let the DNA know which side // a fight came from. but it causes too // much stunning of the DNA in the neural // versions, letting them avoid interacting // with the DNA and keeping it from // evolving. so instead we'll just add 2 // and a stun will only result from four // fights, which will let it stay on a NOP // then, or some fights and neural nops... // the whole population will commensally // stun one another... i hope this helps // get that under control newskips[destx][desty] += (1); // don't stun attacker's dna anymore v they like that // newskips[j][i] += 2; // so defender can sit on a // NOP if it wants, stun both // instead... loser for longer // on average. actually 'skip' // refers to turns not operations // .. because neural version // fights so much it stalls their // dna bad so i changed dir+8 // to dir+1 here and dir+12 for // the attacker to 5... so // losing a fight in combination // with most nops, a poke or // a succesfully defended against // fight will probably stall but // otherwise this should result // in less of them and more dna // getting run. neuralstun also // adds 3 stun so 3*2 + 2 == // makes one, i have two neural // subruns so they can stun their // own dna twice, stunning twice // and losing a fight stalls your // dna but they enjoy that in // neural version mod -= biteAmount>>1; dnarun_add[destx][desty] += biteAmount>>1; // minimal energy transfer // to NOPper to help keep // mad energy dynamics // among the extra stunning } if (view == 8 && t == drawevery-1) { actions_view[destx][desty] += 2; actions_view[j][i] += 1; } } } if (actions[1][dir] == 1) { // suck tstimuli[destx][desty][1][dir] += 16; // printf("suck\n"); if (view == 6 && !wonafight && t == drawevery-1) { actions_view[destx][desty] += 1; } // signed int w = (signed int) dnarun[destx][desty]; signed int w = (signed int) grid[destx][desty]; w -= biteAmount; mod += biteAmount; if (w < 0 || wonafight) { // kill & breed offspring[j][i][0] = destx; offspring[j][i][1] = desty; // for neural version i should // have 8 offspring destinations // available per cell... or they // only get one child per frame // something for rev 5 with this // tiled view i want kills += 1; } else { // no kill just bite dnarun_sub[destx][desty] += biteAmount; } bites += 1; } else if (actions[0][dir] == 1) { // give tstimuli[destx][desty][0][dir] += 16; // printf("give\n"); dnarun_add[destx][desty] += giveamount; mod -= biteAmount; gives += 1; if (view == 5 && t == drawevery-1) { actions_view[destx][desty] += 1; } } else if (actions[2][dir] == 1) { // poke tstimuli[destx][desty][2][dir] += 16; // printf("poke\n"); newskips[destx][desty] += dir+12; // in neural versions pokes // now add 12+dir stun not // 1+dir, and fights add // 1+dir not 12+dir, because // they fight so much DNA_IP[destx][desty] += (dir+1)<<2; while(DNA_IP[destx][desty] > DNA_Length) { DNA_IP[destx][desty] -= DNA_Length; } pokes += 1; if (view == 7 && t == drawevery-1) { actions_view[destx][desty] += 1; } } } // dir loop ends if (wantstooutput == 1) { // output // printf("w %i", inputs[j][i]); // if (inputs[j][i] != 0) { // yeah only do this if they have input // no that sucks sorry // printf("o %i", inputs[j][i]); // fseek(dsp, soundptr,0); // int somechar = data[(random()/(RAND_MAX>>8))]; for (dataloop = 0; dataloop= DNA_Length) {DNA_IP[j][i] -= DNA_Length;} if (somechar > 0) { int high = somechar+2; int low; int highest = somechar + 4; int lowest; if (somechar > 1) { low = somechar-2; } else { low = 0; } //low = somechar; if (somechar > 3) { lowest = somechar - 4; } else { lowest = 0; } int reward = 0; if ((int) newcell <= high && (int) newcell >= low) { reward += good_output_reward; goods += 2; } else {reward -= outputpenalty;} if ((int) newcell <= highest && (int) newcell >= lowest) { reward += good_output_reward/3; goods += 1; } else {reward -= outputpenalty/3;} mod += reward; } } inputs[j][i] = 0; outputsctr += 1; //if (newcell > 0) { outputs[j][i] = newcell; // } // only for vis // } else { outputs[j][i] = 0; } } if (wantstoinput == 1) { // input mod -= inputscost; inputs[j][i] = data[(random()/(RAND_MAX>>8))%datalen]; // signals program will be loaded onto 32 sense // printf("wi %i\n",(unsigned int) inputs[j][i]); // neurons next turn // the colour it shows is just // from the bf data and for fun // DNA_IP[j][i] += inputs[j][i]; // darn // DNA_IP[j][i] += inputs[j][i]<<2; // no // while (DNA_IP[j][i] >= DNA_Length) {DNA_IP[j][i] -= DNA_Length;} progsgot += 1; mod-=inputcost; } newcell += mod; if (newcell < 0) { newcell = 0; } else if (newcell > 255) { newcell = 255;} } else { // acts check ends (no-op, vulnerable to poke, harder to fight) // how nop with brains // printf("nop\n"); // newskips[j][i] += 7; DNA_IP[j][i] += 4; // neural nop will jmp dna... neuralnops += 1; while(DNA_IP[j][i] > DNA_Length) { DNA_IP[j][i] -= DNA_Length; } if (view == 9 && t == drawevery-1) { actions_view[j][i] += 3; } // } // unindented poke skip check ends (no) } // acts check ends // newcell += (signed int) ((signed int) grid[j][i] - (signed int) dnarun[j][i]); while (newcell > 255) { newcell = 255; } if (newcell < 0) { newcell = 0; } // ok // if (newcell < 0) { newcell == 1; } dnarun[j][i] = newcell; } else { // if dna_run is off (at brains run) newcell = grid[j][i]; // newcell *= .97; // no fade dnarun[j][i] = newcell; } } else if (run == 2) { // breed run if (DNA_on) { if (offspring[j][i][0] != 255) { // change 255 to -1 here, // at the top of the DNA // run, and where we declare // offspring[] if you need // grids > 254x254... grr if (recursive_fair_breed(j, i, offspring[j][i][0], offspring[j][i][1], 255, 255, offspring, DNA, Brains, neuroncount, generations, sexctr, skips, DNA_IP, dnarun_add, &breeds, &splits, &maxIP, sex_on, 0) > max_breed_fairness) { maxrecursions += 1; } } // indent this, flamoot } else {// DNA_on off } // end breed run if (highgen < generations[j][i]) {highgen = generations[j][i];} avggen += generations[j][i]; if (lowgeninpop > generations[j][i]) {lowgeninpop = generations[j][i]; lowgen = generations[j][i];} } else { // CA run newcell = dnarun[j][i]; newcell += dnarun_add[j][i]; newcell -= dnarun_sub[j][i]; dnarun_add[j][i] = 0; dnarun_sub[j][i] = 0; skips[j][i] = newskips[j][i]; Uint8 dir = 0; Uint8 op = 0; for (op=0;op<4;op++) { for (dir=0;dir<8;dir++) { stimuli[j][i][op][dir] = tstimuli[j][i][op][dir]; } } // newskips[j][i] = 0; if (CA_on) { newcell *= .95; // fade if (newcell > 255) { newcell = 255; } // newcell += 5; // what is this rule /* newcell += 1-(abs((signed int)(i-y))/(gridrows/7)); newcell += 1-(abs((signed int)(j-z))/(gridcols/7)); */ /* newcell -= dnarun[z+1][y]>>4; newcell -= dnarun[z+1][y+1]>>4; newcell -= dnarun[z][y]>>4; newcell -= dnarun[z][y+1]>>4; newcell += dnarun[gridlastx][gridlasty]>>4; newcell += dnarun[0][0]>>4; newcell += dnarun[0][gridlasty]>>4; newcell += dnarun[gridlastx][0]>>4; newcell += dnarun[gridcolsminusz2][y2]>>4; newcell -= dnarun[z2][y2]>>4; newcell += dnarun[gridcolsminusz2][gridrowsminusy2]>>4; newcell -= dnarun[z2][gridrowsminusy2]>>4; */ // wilder if you use modulos not divides. but you can seek homeostasis instead, using the above code if you want // ... then the temperature changes in jumps as cell values enter // certain ranges... /64 means the granularity is only four, though. // newcell should be a float, then it would be better. what i want // with the %4 shit below is to get them to carefully tune the // values of hotspot neighbourhoods, cooperatively... eventually. // best way to hold a temperature is to hold a cell's value still // if possible then and if it jumps it should be by 4 // i can't decide which way is better yet // newcell += (-3)*(abs((signed int)(i-y))/(gridrows/5)); // newcell += (-3)*(abs((signed int)(j-z))/(gridcols/5)); // ^ five habitable bands, one really cold // newcell -= 2*(abs((signed int)(i-y))/(y2)); newcell -= 2*(abs((signed int)(j-z))/(z2)); // ^ three habitable bands out of a 4x4 grid... and faster math // if you modulo these by y2/z2 or some other value rather than // divide, you get a diamond grid with hot and coldspots // distributed across the neighbourhoods... kind of cool // newcell -= (abs((signed int)(i-y))/(y3)); // newcell -= (abs((signed int)(j-z))/(z3)); // ^ yet more bands, 8x8 grid, real nice but looks like goatse // newcell += 1; // then warming for the corners that always reboot newcell -= dnarun[(z)+1][(y)]%4; // far corners newcell -= dnarun[(z)+1][(y)+1]%4; newcell -= dnarun[(z)][(y)]%4; newcell -= dnarun[(z)][(y)+1]%4; newcell += dnarun[gridlastx][gridlasty]%4; // center newcell += dnarun[0][0]%4; newcell += dnarun[0][gridlasty]%4; newcell += dnarun[gridlastx][0]%4; newcell += dnarun[gridcolsminusz2][y2]%4; // middle corners newcell -= dnarun[z2][y2]%4; newcell += dnarun[gridcolsminusz2][gridrowsminusy2]%4; newcell -= dnarun[z2][gridrowsminusy2]%4; // end if (i == 0) { up = gridlasty; } else { up = i-1; } if (i == gridlasty) { down = 0; } else { down = i+1; } if (j == 0) { left = gridlastx; } else { left = j-1; } if (j == gridlastx) { right = 0; } else { right = j+1; } int mod = 0; if (dnarun[left][up] < newcell) { mod--; } else { mod++; } if (dnarun[left][i] < newcell) { mod--; } else { mod++; } if (dnarun[left][down] < newcell) { mod--; } else { mod++; } if (dnarun[right][up] < newcell) { mod--; } else { mod++; } if (dnarun[right][i] < newcell) { mod--; } else { mod++; } if (dnarun[right][down] < newcell) { mod--; } else { mod++; } if (dnarun[j][up] < newcell) { mod--; } else { mod++; } if (dnarun[j][down] < newcell) { mod--; } else { mod++; } newcell += mod; if (newcell > 255) { newcell = 255; } else if (newcell < 0) { // oops but cool // newcell = 255; newcell = 0; } } else {} // if CA off tgrid[j][i] = newcell; } } } } lowgeninpop = highgen; // eh for (i = 0; i < gridrows; i++) { for (j = 0; j < gridcols; j++) { grid[j][i] = tgrid[j][i]; } } if (highgen > highestgen) { highestgen = highgen; } avggen = avggen / (float) popsize; // whats wrong with this t++; if (t == drawevery) { if (view == 1) { viewdata1 = lowgen; viewdata2 = highgen; viewdata3 = &generations; viewdata4 = 0; } else if (view == 2) { viewdata1 = 0; viewdata2 = 255; viewdata3 = 0; viewdata4 = &skips; } else if (view == 3) { viewdata1 = 0; viewdata2 = sexoperandpersistance*6; viewdata3 = 0; viewdata4=&sexctr; } else if (view == 4) { viewdata1 = 0; viewdata2 = DNA_Length; viewdata3 = &DNA_IP; viewdata4=0; } else if (view >= 5 && view <= 9) { viewdata1 = 0; viewdata2 = 8+(view+4); viewdata4 = &actions_view; viewdata3=0; } else if (view == 10) {viewdata1 = cortical_neurons; viewdata2 = num_of_neurons; viewdata3 = 0; viewdata4 = &neuroncount; } else if (view == 11) {viewdata1 = 0; viewdata2 = 127; viewdata3 = 0; viewdata4 = &inputs; } else if (view == 12) {viewdata1 = 0; viewdata2 = 127; viewdata3 = 0; viewdata4 = &outputs; } else if (view == 13) {viewdata1 = 0; viewdata2 = 6; viewdata3 = 0; viewdata4 = &neurskipsandstuns; } else if (view == 0) { viewdata1 = 0; viewdata2 = 0; viewdata3 = 0; viewdata4=0; } if (showsynapses & 1) { if (showsynapses > 3) { drawgrid(screen, Brains, neuroncount[0][0], neuralones, *grid, gridrows, gridcols, cellwidth, cellheight, xspace, yspace, screenwidth, screenheight, DNA_View_Cell_Size_Divisor, DNA_Length, view, viewdata1, viewdata2, viewdata3, viewdata4); } else { drawgrid(screen, Brains, neuroncount[0][0], CellZero_did_fire, *grid, gridrows, gridcols, cellwidth, cellheight, xspace, yspace, screenwidth, screenheight, DNA_View_Cell_Size_Divisor, DNA_Length, view, viewdata1, viewdata2, viewdata3, viewdata4); } } else { drawgrid(screen, Brains, neuroncount[0][0], neuralzeroes, *grid, gridrows, gridcols, cellwidth, cellheight, xspace, yspace, screenwidth, screenheight, DNA_View_Cell_Size_Divisor, DNA_Length, view, viewdata1, viewdata2, viewdata3, viewdata4); } if (showsynapses == 2) { showsynapses = 3; } else if (showsynapses == 3) { showsynapses = 2; } t=0; tt++; if (tt == drawsbetweenscoreoutput) { int nonplastics = 0; int plastics = 0; int inhibs = 0; int excits = 0; int neurons = 0; for (i = 0; i < gridrows; i++) { for (j = 0; j < gridcols; j++) { Uint8 *brainptr = Brains[j][i]; for (c = 1; c <= neuroncount[j][i]; c++) { neurons += 1; Uint8 d; for (d = 2; d < num_of_synapses; d+=4) { if (brainptr[(c*num_of_synapses)+d] == 0) break; if (brainptr[(c*num_of_synapses)+d+1]>1) { //printf("%i,%i: synapse at %i of neuron %i is plastic\n",j,i,d,c); plastics += 1; } else { nonplastics += 1; } if (brainptr[(c*num_of_synapses)+d+1]&1) { inhibs += 1; } else { excits += 1; } } } } } char logbuf[600]; printf("in world high score %i, highest was %i, lowest is %i, average %f ", highgen, highestgen, lowgen, avggen); sprintf(logbuf,"in world high score %i, highest was %i, lowest is %i, average %f\n", highgen, highestgen, lowgen, avggen); fputs(logbuf, lf); if (view == 1) {printf ("(generation view)\n");} else if (view == 2) {printf ("(stunned view)\n");} else if (view == 3) {printf ("(breed mood view)\n");} else if (view == 4) {printf ("(DNA IP view)\n"); } else if (view == 5) {printf ("(Gives view)\n");} else if (view == 6) {printf("(Bites view)\n");} else if (view == 7) {printf("(Pokes view)\n");} else if (view == 8) {printf("(Fights view)\n");} else if (view == 9) {printf("(NOP view)\n");} else if (view == 10) {printf("(Neuron count view)\n");} else if (view == 11) {printf("(Did Input view)\n");} else if (view == 12) {printf("(Output view)\n");} else if (view == 13) {printf("(Neural Skips/Stuns view)\n");} else {printf("\n");} printf("%i gives, %i pokes, %i skips, %i bites, %i dnanops %i neuralnops %i max recursions %i progs got %i outputs %i good\n%i neurons %i plastic synapses %i non plastic synapses %i excitatory synapses %i inhibitory synapses %i total synapses\n%i lost fights, %i won fights, %i total fights, %i kills, %i breeds, %i splits. max IP %i\n", gives, pokes, skipsctr, bites, nops, neuralnops, maxrecursions, progsgot, outputsctr, goods, neurons, plastics, nonplastics, excits, inhibs, (excits+inhibs), lostfights, wonfights, (lostfights+wonfights), kills, breeds, splits, maxIP); char logbuf2[600]; sprintf(logbuf2, "%i gives, %i pokes, %i skips, %i bites, %i dnanops %i neuralnops %i max recursions %i progs got %i outputs %i good\n%i neurons %i plastic synapses %i non plastic synapses %i excitatory synapses %i inhibitory synapses %i total synapses\n%i lost fights, %i won fights, %i total fights, %i kills, %i breeds, %i splits. max IP %i\n", gives, pokes, skipsctr, bites, nops, neuralnops, maxrecursions, progsgot, outputsctr, goods, neurons, plastics, nonplastics, excits, inhibs, (excits+inhibs), lostfights, wonfights, (lostfights+wonfights), kills, breeds, splits, maxIP); fputs(logbuf2, lf); char logbuf3[600]; sprintf(logbuf3, "%i neural skips of dna, %i neural stuns of dna\n", neuralskips, neuralstuns ); fputs(logbuf3, lf); gives = 0; pokes = 0; skipsctr = 0; bites = 0; kills = 0; breeds = 0; splits = 0; maxIP = 0; lostfights = 0; wonfights = 0; nops = 0; maxrecursions = 0; neuralnops = 0; goods = 0; outputsctr = 0; progsgot = 0; neuralskips = 0; neuralstuns = 0; tt = 0; } } dumplogctr++; if (dumplogctr > dumplogevery) { dumplogctr = 0; fclose(lf); usleep(500); lf=fopen(logfile,"a"); } autosavectr++; if (autosavectr == autosaveevery) { printf("Autosaving\n"); savecrit(highgen, DNA_Length, popsize, DNA, Brains, neuroncount, &DNA_IP, &generations, "ca-ga.best.dna", "ca-ga.best.brain"); savecrit(avggen, DNA_Length, popsize, DNA, Brains, neuroncount, &DNA_IP, &generations, "ca-ga.average.dna", "ca-ga.average.brain"); savecrit(lowgen+1, DNA_Length, popsize, DNA, Brains, neuroncount, &DNA_IP, &generations, "ca-ga.low.dna", "ca-ga.low.brain"); // save lowest generation critter too they get generations necrophiling autosavectr = 0; } cycles++; if (cycles == exitafter) { return; } } printf("Quiting SDL.\n"); /* Shutdown all subsystems */ SDL_Quit(); printf("Quiting....\n"); fclose(lf); exit(0); }