00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <string.h>
00004 #include <sys/stat.h>
00005 #include <sys/types.h>
00006 #include <unistd.h>
00007
00008
00009 #define IMAGE_DIRECTORY "images.temp"
00010 #define PGM_FILE_PATTERN "step_%i.pgm"
00011 #define JPG_FILE_PATTERN "step_%i.jpg"
00012 #define VIDEO_FILENAME "CA.avi"
00013 #define CA_ITERATIONS 2000
00014
00015 typedef struct{
00016 int size;
00017 int*** grid;
00018 } CA;
00019
00020
00025 int removePGMs = 1;
00026
00027
00028 void createVideo( int width , int height );
00029 void simulate( CA* ca , int* rule );
00030 void outputImages( CA* ca , int nimage );
00031 int* getRule( char* file );
00032 CA* getInitCA( char* file , int size );
00033 void usage();
00034 CA* createCA( int size );
00035 void printInternalCA( CA* ca );
00036 void printCA( CA* ca );
00037 int step( CA* curr , CA* next , int* rule );
00038 void toPGM( CA* ca , char* file );
00039 int finished( CA* ca );
00040
00041
00042 int main( int argc , char** argv ){
00043
00044 if( argc != 4 && argc != 5 ){
00045 usage();
00046 }
00047 else if( argc == 5 ){
00048 removePGMs = 0;
00049 }
00050
00051
00052
00053 printf( "getting size...\n" );fflush( stdout );
00054 int size = atoi( argv[1] );
00055
00056
00057
00058 printf( "getting rule...\n" );fflush( stdout );
00059 int* rule = getRule( argv[2] );
00060
00061
00062
00063 printf( "getting initial CA...\n" );fflush( stdout );
00064 CA* ca = getInitCA( argv[3] , size );
00065
00066
00067
00068
00069
00070 mkdir( IMAGE_DIRECTORY , 0777 );
00071 char cwd[256];
00072 if( getcwd(cwd,256) == NULL )
00073 printf( "couldn't get working directory" );
00074 chdir( strcat(strcat(cwd,"/"),IMAGE_DIRECTORY) );
00075
00076
00077
00078 printf( "simulating...\n" );fflush( stdout );
00079 simulate( ca , rule );
00080
00081
00082
00083 printf( "creating video...\n" );fflush( stdout );
00084 createVideo( ca->size , ca->size );
00085
00086
00087
00088 free( rule );
00089 free( ca );
00090 return 0;
00091 }
00092
00093
00094 void
00095 simulate( CA* ca , int* rule ){
00096
00097 void* temp;
00098 int nones, nimages = 100000;
00099
00100 CA* nextca = createCA( ca->size );
00101
00102
00103 while( nones != 0 && nones != ca->size*ca->size ){
00104 outputImages( ca , nimages++ );
00105 nones = step( ca , nextca , rule );
00106 temp = ca;
00107 ca = nextca;
00108 nextca = temp;
00109 if( nimages-100000 == CA_ITERATIONS )
00110 break;
00111 }
00112 outputImages( ca , nimages );
00113
00114
00115 free( nextca );
00116 }
00117
00118
00119 void
00120 createVideo( int width , int height ){
00121
00122 char dimensions[256];
00123 sprintf( dimensions, "w=%i:h=%i:fps=4:type=jpg", width , height );
00124 char* mencoder_args[] = { "mencoder" , "mf://*.jpg" , "-mf" , dimensions
00125 , "-ovc" , "lavc" , "-lavcopts"
00126 , "vcodec=mpeg4:mbd=2:trell" , "-oac" , "copy"
00127 , "-o" , VIDEO_FILENAME , NULL };
00128
00129
00130 if( !fork() ){
00131 if( !fork() ){
00132 execvp( "mencoder" , mencoder_args );
00133 }
00134 wait(NULL);
00135 execlp( "mv" , "mv" , VIDEO_FILENAME , ".." , NULL );
00136 }
00137 wait(NULL);
00138 }
00139
00140
00141 void
00142 outputImages( CA* ca , int nimage ){
00143
00144 char pgm[256];
00145 sprintf( pgm , PGM_FILE_PATTERN , nimage );
00146 char jpg[256];
00147 sprintf( jpg , JPG_FILE_PATTERN , nimage );
00148
00149
00150 toPGM( ca , pgm );
00151 if( !fork() ){
00152 if( !fork() ){
00153 execlp( "convert" , "convert" , pgm , jpg , NULL );
00154 }
00155 wait(NULL);
00156 if( removePGMs ){
00157 execlp( "rm" , "rm" , pgm , NULL );
00158 }
00159 else{
00160 exit(0);
00161 }
00162 }
00163 }
00164
00165
00166 int*
00167 getRule( char* file ){
00168
00169 int* rule = (int*) calloc( 512 , sizeof(int) );
00170 char rawrule[512];
00171 FILE* rawrule_fp;
00172
00173
00174 if( (rawrule_fp = fopen(file,"r")) == NULL )
00175 perror( "fopen of raw rule file failed\n" );
00176 if( fgets(rawrule,513,rawrule_fp) == NULL )
00177 perror( "getline of raw rule failed\n" );
00178 fclose( rawrule_fp );
00179
00180
00181 int i;
00182 for( i=0 ; i<512 ; i++ ){
00183 rule[i] = rawrule[i] == '1';
00184 }
00185
00186
00187 return rule;
00188 }
00189
00190
00191 CA*
00192 getInitCA( char* file , int size ){
00193
00194 int length = size*size;
00195 char rawCA[length];
00196 CA* ca = createCA( size );
00197 FILE* rawCA_fp;
00198
00199
00200 if( (rawCA_fp = fopen(file,"r")) == NULL )
00201 perror( "getInitCA(): fopen of rawCA file failed" );
00202 if( fgets(rawCA,length+1,rawCA_fp) == NULL )
00203 perror( "getInitCA(): getline of rawCA file failed" );
00204 fclose( rawCA_fp );
00205
00206
00207 int r, c;
00208 for( r=1 ; r<=size ; r++ ){
00209 for( c=1 ; c<=size ; c++ ){
00210 *ca->grid[r][c] = rawCA[size*(r-1)+(c-1)] == '1';
00211 }
00212 }
00213
00214
00215 return ca;
00216 }
00217
00218
00219 void
00220 usage(){
00221 printf( "USAGE: mkvid SIZE RULE INITCA\n" );
00222 printf( " The function requires 3 arguments, where SIZE is the \n" );
00223 printf( " value of one of the sides of the CA, RULE is a file \n" );
00224 printf( " containing one line of ones and zeros that is the rule \n" );
00225 printf( " in question, and similarly, INITCA is a file that has \n" );
00226 printf( " one line that is the CA with which to start.\n" );
00227 exit(0);
00228 }
00229
00230
00231 int
00232 finished( CA* ca ){
00233 int r, c, sum = 0;
00234 for( r=1 ; r<=ca->size ; r++ ){
00235 for( c=1 ; c<=ca->size ; c++ ){
00236 sum += *ca->grid[r][c];
00237 }
00238 }
00239
00240 return sum == 0 || sum == ca->size*ca->size;
00241 }
00242
00243
00244 CA*
00245 createCA( int size ){
00246
00247 CA* ca = (CA*) malloc( sizeof(CA) );
00248 ca->size = size;
00249
00250
00251 int row, col;
00252 ca->grid = (int***) calloc( size+2 , sizeof(int**) );
00253 for( row = 0 ; row < size+2 ; row++ ){
00254 ca->grid[row] = (int**) calloc( size+2 , sizeof(int*) );
00255 for( col = 1 ; col <= size ; col++ ){
00256 ca->grid[row][col] = (int*) malloc( sizeof(int) );
00257 }
00258 }
00259
00260
00261 int i;
00262 for( i=1 ; i<=size ; i++ ){
00263 ca->grid[i][0] = ca->grid[i][size];
00264 ca->grid[i][size+1] = ca->grid[i][1];
00265 ca->grid[0][i] = ca->grid[size][i];
00266 ca->grid[size+1][i] = ca->grid[1][i];
00267 }
00268
00269
00270 ca->grid[0][0] = ca->grid[size][size];
00271 ca->grid[0][size+1] = ca->grid[size][1];
00272 ca->grid[size+1][0] = ca->grid[1][size];
00273 ca->grid[size+1][size+1] = ca->grid[1][1];
00274
00275 return ca;
00276 }
00277
00278
00279 void
00280 printInternalCA( CA* ca ){
00281 int r,c;
00282 for( r = 0 ; r < ca->size+2 ; r++ ){
00283 for( c = 0 ; c < ca->size+2 ; c++ ){
00284 printf( "%i " , *(ca->grid[r][c]) );
00285 }
00286 printf( "\n" );
00287 }
00288 printf( "\n" );
00289 }
00290
00291
00292 void
00293 printCA( CA* ca ){
00294 int r,c;
00295 for( r = 1 ; r <= ca->size ; r++ ){
00296 for( c = 1 ; c <= ca->size ; c++ ){
00297 printf( "%i " , *(ca->grid[r][c]) );
00298 }
00299 printf( "\n" );
00300 }
00301 printf( "\n" );
00302 }
00303
00304
00305
00306 int
00307 step( CA* curr , CA* next , int* rules ){
00308 int r, c, rule, sum = 0;
00309 for( r = 1 ; r <= curr->size ; r++ ){
00310 for( c = 1 ; c <= curr->size ; c++ ){
00311 rule = 1 * *curr->grid[r-1][c-1]
00312 + 2 * *curr->grid[r-1][ c ]
00313 + 4 * *curr->grid[r-1][c+1]
00314 + 8 * *curr->grid[ r ][c-1]
00315 + 16 * *curr->grid[ r ][ c ]
00316 + 32 * *curr->grid[ r ][c+1]
00317 + 64 * *curr->grid[r+1][c-1]
00318 + 128 * *curr->grid[r+1][ c ]
00319 + 256 * *curr->grid[r+1][c+1];
00320 *next->grid[r][c] = rules[rule];
00321 sum += rules[rule];
00322 }
00323 }
00324 next->size = curr->size;
00325 return sum;
00326 }
00327
00328
00329 void
00330 toPGM( CA* ca , char* file ){
00331 FILE* fp = fopen( file , "w" );
00332
00333
00334 fprintf( fp , "P2\n" );
00335 fprintf( fp , "%i %i\n" , ca->size , ca->size );
00336 fprintf( fp , "1\n" );
00337
00338
00339 int r, c;
00340 for( r=1 ; r<=ca->size ; r++ ){
00341 for( c=1 ; c<=ca->size ; c++ ){
00342 fprintf( fp , "%i " , *ca->grid[r][c] );
00343 }
00344 fprintf( fp , "\n" );
00345 }
00346
00347 fclose( fp );
00348 }