// Genesaver: copyright 2003 Sam Stafford. #include <stdio.h> #include "globals.h" #include "DNA.h" DNA::DNA(void) { } DNA::~DNA(void) { } DNA::DNA( DNA* d ) { hchr = d->hchr; for ( int i = 0 ; i < 6 ; i++ ) ichr[i] = d->ichr[i]; for ( int m = 0 ; m < D_M ; m++ ) Mutate(); } DNA::DNA( DNA* d, DNA* e ) { DNA* f; f = RandFloat() < 0.5 ? d : e; hchr = f->hchr; for ( int i = 0 ; i < 6 ; i++ ) { f = RandFloat() < 0.5 ? d : e; ichr[i] = f->ichr[i]; } for ( int m = 0 ; m < D_M ; m++ ) Mutate(); } void DNA::Dump( FILE* f ) { //Convert characters to ASCII hex and dump to file. int i, j, k; //write H-chromosome first // input dendrites for ( i = 0 ; i < 12 ; i++ ) PutChar( f, hchr.iden[i] ); fputc( '\n', f ); // input weights for ( i = 0 ; i < 12 ; i++ ) PutChar( f, hchr.iwgt[i] ); fputc( '\n', f ); // output weights for ( i = 0 ; i < 4 ; i++ ) { for ( j = 0 ; j < 24 ; j++ ) PutChar( f, hchr.owgt[i][j] ); fputc( '\n', f ); } // color for ( i = 0 ; i < 4 ; i++ ) PutChar( f, hchr.colr[i] ); fputc( '\n', f ); // diet for ( i = 0 ; i < 4 ; i++ ) PutChar( f, hchr.diet[i] ); fputc( '\n', f ); fputc( '/', f ); fputc( '\n', f ); //now the six I-chromosomes for ( i = 0 ; i < 6 ; i++ ) { // top level axons for ( j = 0 ; j < 4 ; j++ ) PutChar( f, ichr[i].ax0[j] ); fputc( '\n', f ); // weights for ( j = 0 ; j < 4 ; j++ ) { for ( k = 0 ; k < 4 ; k++ ) PutChar( f, ichr[i].wgt[j][k] ); fputc( '\n', f ); } // lower level axons for ( j = 0 ; j < 4 ; j++ ) PutChar( f, ichr[i].ax1[j] ); fputc( '\n', f ); // color PutChar( f, ichr[i].colr ); fputc( '\n', f ); // diet PutChar( f, ichr[i].diet ); fputc( '\n', f ); fputc( '/', f ); fputc( '\n', f ); } fputc( '%', f ); fputc( '\n', f ); } //load one DNA from a null- or EOF-terminated ASCII array. //return the position in the array reached. char* DNA::Load( char* file ) { char* f = file; char c; int i, j, k; //chomp '%' and '\n' delimiters while ( *f == '%' || *f == '\n' ) f++; //standard check for end of DNA strand, to be repeated. if ( *f == EOF || *f == 0x0 || *f == '%' ) return f; //H-chromosome time! // input dendrites for ( i = 0 ; i < 12 ; i++ ) { f = LoadChar( f, &c ); if ( *f == EOF || *f == 0x0 || *f == '%' ) return f; if ( *f == '/' ) break; hchr.iden[i] = c; f++; } // input weights for ( i = 0 ; i < 12 ; i++ ) { f = LoadChar( f, &c ); if ( *f == EOF || *f == 0x0 || *f == '%' ) return f; if ( *f == '/' ) break; hchr.iwgt[i] = c; f++; } // output weights for ( i = 0 ; i < 4 ; i++ ) { for ( j = 0 ; j < 24 ; j++ ) { f = LoadChar( f, &c ); if ( *f == EOF || *f == 0x0 || *f == '%' ) return f; if ( *f == '/' ) break; hchr.owgt[i][j] = c; f++; } } // color for ( i = 0 ; i < 4 ; i++ ) { f = LoadChar( f, &c ); if ( *f == EOF || *f == 0x0 || *f == '%' ) return f; if ( *f == '/' ) break; hchr.colr[i] = c; f++; } // diet for ( i = 0 ; i < 4 ; i++ ) { f = LoadChar( f, &c ); if ( *f == EOF || *f == 0x0 || *f == '%' ) return f; if ( *f == '/' ) break; hchr.diet[i] = c; f++; } //chomp next '/', bail if EOF or % while (!( *f == EOF || *f == 0x0 || *f == '%' || *f == '/') ) f++; if ( *f != '/' ) return f; f++; //now the six I-chromosomes for ( i = 0 ; i < 6 ; i++ ) { // top level axons for ( j = 0 ; j < 4 ; j++ ) { f = LoadChar( f, &c ); if ( *f == EOF || *f == 0x0 || *f == '%' ) return f; if ( *f == '/' ) break; ichr[i].ax0[j] = c; f++; } // weights for ( j = 0 ; j < 4 ; j++ ) { for ( k = 0 ; k < 4 ; k++ ) { f = LoadChar( f, &c ); if ( *f == EOF || *f == 0x0 || *f == '%' ) return f; if ( *f == '/' ) break; ichr[i].wgt[j][k] = c; f++; } } // lower level axons for ( j = 0 ; j < 4 ; j++ ) { f = LoadChar( f, &c ); if ( *f == EOF || *f == 0x0 || *f == '%' ) return f; if ( *f == '/' ) break; ichr[i].ax1[j] = c; f++; } // color f = LoadChar( f, &c ); if ( *f == EOF || *f == 0x0 || *f == '%' ) return f; if ( *f == '/' ) break; ichr[i].colr = c ; f++; // diet f = LoadChar( f, &c ); if ( *f == EOF || *f == 0x0 || *f == '%' ) return f; if ( *f == '/' ) break; ichr[i].diet = c; f++; //chomp next '/', bail if EOF or % while (!( *f == EOF || *f == 0x0 || *f == '%' || *f == '/') ) f++; if ( *f != '/' ) return f; f++; } while (!( *f == EOF || *f == 0x0 || *f == '%' || *f == '/') ) f++; while ( *f == '%' || *f == '/' ) f++; return f; } // grab one char from ASCII hex and return pointer to last thing read. char* DNA::LoadChar( char* f, char* c ) { char s, o; while ( *f != EOF && *f && *f != '/' && *f != '%' ) { if ( ( *f >= '0' && *f <= '9' ) || ( *f >= 'A' && *f <= 'F' ) ) { s = *f; break; } f++; } if ( *f == EOF || !*f || *f == '/' || *f == '%' ) return f; f++; while ( *f != EOF && *f && *f != '/' && *f != '%' ) { if ( ( *f >= '0' && *f <= '9' ) || ( *f >= 'A' && *f <= 'F' ) ) { o = *f; break; } f++; } if ( *f == EOF || !*f || *f == '/' || *f == '%' ) return f; *c = Squish( s, o ); return f; } // Thanks to Mandi for humoring me and talking about gene mutation. void DNA::Mutate() { char* m; char* d = NULL; if ( RandFloat() < 0.35 ) //mutate the H-chromosome { int r = RandInt( 127 ); if ( r < 4 ) m = & hchr.colr[ RandInt( 3 ) ]; else if ( r < 8 ) m = & hchr.diet[ RandInt( 3 ) ]; else if ( r < 20 ) m = & hchr.iden[ RandInt( 11 ) ]; else if ( r < 32 ) m = d = & hchr.iwgt[ RandInt( 11 ) ]; else m = d = & hchr.owgt[ RandInt( 3 ) ][ RandInt( 23 ) ]; } else //mutate a random I-chromosome //There is a disproportionately high chance of mutating a color //gene. This reduces the chance of one color overwhelming the //others and causing the genepool to grow stagnant. { int i = RandInt( 5 ); int r = RandInt( 31 ); if ( r < 4 ) m = & ichr[i].ax0[ RandInt( 3 ) ]; else if ( r < 8 ) m = & ichr[i].ax1[ RandInt( 3 ) ]; else if ( r < 15 ) m = & ichr[i].colr; else if ( r < 16 ) m = & ichr[i].diet; else m = d = & ichr[i].wgt[ RandInt( 3 ) ][ RandInt( 3 ) ]; } char v = *m; float r = RandFloat(); if ( r < 0.5 ) //decrease *m = char( v - RandInt( v + 128 ) ); else //increase *m = char( v + RandInt( 127 - v ) ); if ( d && RandFloat() < 0.5 ) *d = 0; //50% chance of pruning a synapse } void DNA::PutChar( FILE* f, char c ) { unsigned char u = c + 128; char o = u & 0x0f; char s = u >> 4; if ( o < 10 ) o += 48; else o += 55; if ( s < 10 ) s += 48; else s += 55; fputc( s, f ); fputc( o, f ); } void DNA::Randomize() { char random[2*128+1+(2*26+1)*6+3]; char r; int n = 0; //H-chromosome - 128 bytes for ( int i = 0 ; i < 128*2 ; i++ ) { r = char( RandInt( 15 ) ); if ( r < 10 ) r += 48; else r += 55; random[n] = r; n++; } random[n] = '/'; n++; //6 I-chromosomes - 26 bytes each for ( int j = 0 ; j < 6 ; j++ ) { for ( int k = 0 ; k < 26*2 ; k++ ) { r = char( RandInt( 15 ) ); if ( r < 10 ) r += 48; else r += 55; random[n] = r; n++; } random[n] = '/'; n++; } random[n] = '%'; n++; random[n] = EOF; Load( random ); } char DNA::Squish( char s, char o ) { if ( s < 'A' ) s -= 48; else s -= 55; if ( o < 'A' ) o -= 48; else o -= 55; unsigned char u = s * 16 + o; return u - 128; }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#4 | 5393 | Sam Stafford |
Integrate in Marc's porting changes, and merge my own relevant winmain.cpp changes into main.cpp. (Thanks Marc!!!) |
||
#3 | 3351 | Sam Stafford | Fixed a typo in change 3347 (increase odds of color mutation). | ||
#2 | 3347 | Sam Stafford | Increase likelihood of color mutation. | ||
#1 | 3052 | Sam Stafford |
Add Genesaver to the Public Depot. It's not in any way Perforce-related, but it does share a bit of code with Jamgraph, and it feels strange to have an open-source project that's not in the PD. |