//TODO: We could probably get a significant speedup by doing our processing in //bulk via a lookup table - i.e., running all life cycle ops on a 3x3 or 3x4 //by turning it into binary, using that as a hash table entry for a //pre-computed calculation for that combination. 3x3 is no problem. 3x4 will //take 2 gig normally, so we'd have to do some "cheats", taking advantage of //symmetry to reduce it, since we don't have that much ram and don't want to //swap out. #define USE_ZLIB #define X_RES 40000 //X-res must be divisible by 8 (for ease in saving/loading) #define Y_RES 40000 #define VERSION 0.1 #define STEPS_PER_SAVE 100 #define ENERGY_PER_TIME 5000 #define ENERGY_MULT 0.3 #define ENERGY_EXP 0.5 #define MAX_PATH 4096 #ifdef USE_ZLIB #define OUTFILE "mc.sav.gz" #else #define OUTFILE "mc.sav" #endif #define VIEW_WIDTH 75 #define VIEW_HEIGHT 35 #define VIEW_CHANGE 400 #define TRUE 1 #define FALSE 0 #define NULL 0 #include #include #include #include #ifdef USE_ZLIB #include #endif const unsigned char ON_BIT[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; const unsigned char OFF_BIT[] = { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F }; float version=VERSION; unsigned long x_res=X_RES; unsigned long y_res=Y_RES; unsigned long x_resB; unsigned char* world=NULL; unsigned char* buffer=NULL; unsigned long long steps=0; unsigned long view_x,view_y; float frand() //Returns a random number from 0 to 1. { return (((float)random())/((float)RAND_MAX)); } double drand() //Returns a random number from 0 to 1. { return (((double)random())/(double)RAND_MAX*0.99999)+ (((double)random())/(double)RAND_MAX*0.00001); } double curve_rand(double center) //Returns a random number on a centered exponential distribution curve { return center * -log(drand()); } int main(int argc, char** argv) { unsigned long x,y,x2,y2,x3,y3; unsigned long i; float f1,f2; char neighbors[8]; printf("Initializing...\n"); srand(time(0)); view_x=(int)(frand()*X_RES); view_y=(int)(frand()*Y_RES); printf("Setting view to: (%d,%d)-(%d,%d)\n",view_x,view_y,view_x+VIEW_WIDTH,view_y+VIEW_WIDTH); if (argc==2) { #ifdef USE_ZLIB gzFile* fp; if (!(fp=gzopen(argv[1],"r"))) { printf("Unable to open file %s\n",argv[1]); return 1; } printf("Loading file %s\n",argv[1]); gzread(fp,&version,4); gzread(fp,&x_res,4); gzread(fp,&y_res,4); gzread(fp,&steps,8); x_resB = x_res/8; world=malloc(x_resB*y_res); buffer=malloc(x_resB*2); for (y=0; y>8; if (rnd==0) rnd=random(); } } } } //Process using Conway's rules. for (y=0; y0) y2=y-1; else y2=y_res-1; if (y!=y_res-1) y3=y+1; else y3=0; //Fill in a row of the buffer. for (x=0; x0) x2=x-1; else x2=x_resB-1; if (x!=x_resB-1) x3=x+1; else x3=0; neighbors[0]=((world[x2+y2*x_resB]&ON_BIT[7])>0)+ ((world[x+y2*x_resB]&ON_BIT[0])>0)+ ((world[x+y2*x_resB]&ON_BIT[1])>0)+ ((world[x2+y*x_resB]&ON_BIT[7])>0)+ ((world[x+y*x_resB]&ON_BIT[1])>0)+ ((world[x2+y3*x_resB]&ON_BIT[7])>0)+ ((world[x+y3*x_resB]&ON_BIT[0])>0)+ ((world[x+y3*x_resB]&ON_BIT[1])>0); for (i=1; i<7; i++) { neighbors[i]=((world[x+y2*x_resB]&ON_BIT[i-1])>0)+ ((world[x+y2*x_resB]&ON_BIT[i])>0)+ ((world[x+y2*x_resB]&ON_BIT[i+1])>0)+ ((world[x+y*x_resB]&ON_BIT[i-1])>0)+ ((world[x+y*x_resB]&ON_BIT[i+1])>0)+ ((world[x+y3*x_resB]&ON_BIT[i-1])>0)+ ((world[x+y3*x_resB]&ON_BIT[i])>0)+ ((world[x+y3*x_resB]&ON_BIT[i+1])>0); } neighbors[7]=((world[x+y2*x_resB]&ON_BIT[6])>0)+ ((world[x+y2*x_resB]&ON_BIT[7])>0)+ ((world[x3+y2*x_resB]&ON_BIT[0])>0)+ ((world[x+y*x_resB]&ON_BIT[6])>0)+ ((world[x3+y*x_resB]&ON_BIT[0])>0)+ ((world[x+y3*x_resB]&ON_BIT[6])>0)+ ((world[x+y3*x_resB]&ON_BIT[7])>0)+ ((world[x3+y3*x_resB]&ON_BIT[0])>0); buffer[x+x_resB]=0; //Set them all dead for (i=0; i<8; i++) { if (neighbors[i]==3) //Create it no matter what buffer[x+x_resB]|=1<=1) { for (x=0; x