00001
00006 #include "schemaGameGenerator.h"
00007
00008
00009
00010 bool generateSchema( const char *filename,
00011 unsigned int numRow,
00012 unsigned int numCol,
00013 unsigned int difficult
00014 )
00015 {
00016 D1(printf("\nSCHEMAGAMEGENERATOR.generateSchema() - START\n"));
00017
00018 FILE *newSchemaFile = fopen( filename , "w" );
00019
00020 if( ! check_generateSchema( newSchemaFile, difficult, numRow, numCol ) ){
00021 D1(printf("\nSCHEMAGAMEGENERATOR.generateSchema() - ERROR & END\n"));
00022 return false;
00023 }
00024
00025 assert( newSchemaFile != NULL );
00026 assert( !( (difficult < MIN_DIFFICULT) || (difficult > MAX_DIFFICULT) ) );
00027 assert( !( (numRow < MINR) || (numRow > MAXR) ) );
00028 assert( !( (numCol < MINC) || (numCol > MAXC) ) );
00029
00030 char **gameMap = gameMap_alloc_and_set( numRow, numCol );
00031
00032 srand((unsigned)time(0));
00033
00034 double execution_time = create_routes( difficult , numRow, numCol , gameMap );
00035
00036 if( execution_time < 0 ){
00037 D1(printf("\nSCHEMAGAMEGENERATOR.generateSchema() - ERROR & END\n"));
00038 free( gameMap );
00039 return false;
00040 }
00041
00042 increase_schema_difficult( gameMap , numRow, numCol );
00043
00044 D1(printf("\nWrite schema on file %s\n", filename));
00045
00046 save_schema_to_file( gameMap, numRow, numCol, newSchemaFile );
00047
00048 free( gameMap );
00049
00050 D1(printf("\nSCHEMAGAMEGENERATOR.generateSchema() - END\n"));
00051
00052 return true;
00053 }
00054
00055
00056
00057 bool check_generateSchema( const FILE *newSchemaFile,
00058 unsigned int difficult,
00059 unsigned int numRow,
00060 unsigned int numCol
00061 )
00062 {
00063
00064 D5(printf("\nSCHEMAGAMEGENERATOR.check_generateSchema - START\n"));
00065
00066 bool returnValue = true;
00067
00068 if( newSchemaFile == NULL )
00069 {
00070 D1(printf("\nERROR in FILE/s OPEN!\n"));
00071 returnValue = false;
00072 }
00073
00074 if( (difficult < MIN_DIFFICULT) || (difficult > MAX_DIFFICULT) )
00075 {
00076 D1(printf("\nParameter difficult out of range: %u not in [%u,%u]\n",
00077 difficult , MIN_DIFFICULT , MAX_DIFFICULT ));
00078 returnValue = false;
00079 }
00080
00081 if( (numRow < MINR) || (numRow > MAXR) )
00082 {
00083 D1(printf("\nParameter numRow out of range: %u not in [%u,%u]\n",
00084 numRow , MINR,MAXR ));
00085 returnValue = false;
00086 }
00087
00088 if( (numCol < MINC) || (numCol > MAXC) )
00089 {
00090 D1(printf("\nParameter numCol out of range: %u not in [%u,%u]\n",
00091 numCol , MINC,MAXC ));
00092 returnValue = false;
00093 }
00094
00095
00096 D5(printf("\nSCHEMAGAMEGENERATOR.check_generateSchema - END\n"));
00097
00098 return returnValue;
00099 }
00100
00101
00102
00103 char **gameMap_alloc_and_set( unsigned int numRow,
00104 unsigned int numCol
00105 )
00106 {
00107 D5(printf("\nSCHEMAGAMEGENERATOR.gameMap_alloc_and_set - START\n"));
00108
00109 char **gameMap = (char **) malloc( sizeof(char *) * numRow );
00110
00111 unsigned int i,j;
00112
00113 for(i=0; i<numRow; i++)
00114 {
00115 gameMap[i] = (char *) malloc( sizeof(char) * numCol );
00116
00117 for(j=0; j<numCol; j++)
00118 gameMap[i][j] = CLOSE;
00119 }
00120
00121 D5(printf("\nSCHEMAGAMEGENERATOR.gameMap_alloc_and_set - END\n"));
00122
00123 return gameMap;
00124 }
00125
00126
00127
00128 double create_routes( unsigned int difficult,
00129 unsigned int numRow,
00130 unsigned int numCol,
00131 char **gameMap
00132 )
00133 {
00134 D2(printf("\nSCHEMAGAMEGENERATOR.create_routes - START\n"));
00135
00136
00137 double elapsed = -1;
00138 clock_t tStart, tEnd;
00139 tStart = clock();
00140
00141
00142 coordinates start;
00143 start.row = 1 + floor ( rand() % ( numRow - 2 ) );
00144 start.col = 1 + floor ( rand() % ( numCol - 2 ) );
00145
00146 gameMap [ start.row ][ start.col ] = START;
00147
00148 D2(printf("\nStart in (Row,Col)=(%u,%u)\n",start.row,start.col));
00149
00150
00151 unsigned int numOfRoute = getRouteNumber( difficult, numRow, numCol );
00152
00153
00154 coordinates deny;
00155 deny.row = get_denyArea( difficult, numRow, start.row );
00156 deny.col = get_denyArea( difficult, numCol, start.col );
00157
00158
00159 directions avail;
00160 avail = set_number_of_available_cells( start, deny, numRow, numCol );
00161
00162
00163 const double LOW = 0.45;
00164
00165
00166 unsigned int it = 0;
00167 for(it = 0; it<numOfRoute ; it++)
00168 {
00169
00170
00171 struct direction_probabilities
00172 {
00173 double left;
00174 double up;
00175 } prob ;
00176
00177
00178 coordinates door;
00179 door.row = point_in_random_direction( avail.left , avail.right,
00180 start.row , deny.row,
00181 &(prob.left), LOW );
00182
00183 door.col = point_in_random_direction( avail.up , avail.down,
00184 start.col , deny.col,
00185 &(prob.up), LOW );
00186
00187
00188 gameMap[ door.row ][ door.col ] = DOOR;
00189
00190 D3(printf("\nDoor in (row,col)=(%u,%u)\n",door.row,door.col));
00191
00192 unsigned int routelen;
00193
00194 const unsigned int MAX_ROUTE_LEN = get_MaxRouteLen( numRow, numCol,
00195 start, door );
00196
00197 coordinates route[ MAX_ROUTE_LEN + 1 ];
00198
00199 do{
00200
00201 coordinates curr;
00202 curr.row = start.row;
00203 curr.col = start.col;
00204
00205 routelen = 0;
00206
00207
00208
00209 while( ( ( curr.row != door.row ) || ( curr.col != door.col ) ) &&
00210 ( routelen < MAX_ROUTE_LEN ) )
00211 {
00212
00213 get_direction_from_point( numRow , numCol,
00214 &curr.row , &curr.col,
00215 prob.left , prob.up );
00216
00217
00218 route[ routelen ].row = curr.row;
00219 route[ routelen ].col = curr.col;
00220
00221 routelen++;
00222 }
00223
00224 D3(printf("\nIters %u of %u%s\n", routelen, MAX_ROUTE_LEN,
00225 (routelen>=MAX_ROUTE_LEN)?" ROUTE STOPPED":"." ));
00226
00227 }while( routelen >= MAX_ROUTE_LEN );
00228
00229 unsigned int it = 0;
00230
00231 for(it=0; it<routelen; it++ )
00232 if( gameMap[ route[ it ].row ][ route[ it ].col ] == CLOSE )
00233 gameMap[ route[ it ].row ][ route[ it ].col ] = FREE ;
00234 }
00235
00236 tEnd = clock();
00237 elapsed = (double)(tEnd-tStart)/CLOCKS_PER_SEC;
00238
00239 D4(printf("\nSchema dimension (%uX%u):",numRow,numCol));
00240 D5(printf("\nClock at start: %lu",tStart));
00241 D5(printf("\nClock at end: %lu",tEnd));
00242 D5(printf("\nCPU clock per second: %lu",CLOCKS_PER_SEC));
00243 D4(printf("\nElapsed time: %lf second(s)\n",elapsed));
00244 D2(printf("\nSCHEMAGAMEGENERATOR.create_routes - END\n"));
00245
00246 return elapsed;
00247 }
00248
00249
00250
00251 unsigned int get_denyArea( unsigned int difficult,
00252 unsigned int numDir,
00253 unsigned int startDir
00254 )
00255 {
00256
00257 D5(printf("\nSCHEMAGAMEGENERATOR.get_denyArea - START\n"));
00258
00259
00260
00261
00262
00263
00264
00265 assert( MAX_DIFFICULT > 0 );
00266 assert( ( numDir - 1 - startDir ) > 0 );
00267
00268 const unsigned int deny_area = ceil(
00269 ( (double)difficult / MAX_DIFFICULT )
00270 *
00271 ( rand() % ( numDir - 1 - startDir ) )
00272 );
00273
00274
00275 assert( ( 0 <= deny_area ) && ( deny_area <= ( numDir - 1 - startDir ) ) );
00276
00277 D6(printf("\nNumber of deny cells in that direction = %u\n",deny_area));
00278
00279 D5(printf("\nSCHEMAGAMEGENERATOR.get_denyArea - END\n"));
00280
00281 return deny_area;
00282 }
00283
00284
00285
00286 unsigned int getRouteNumber( unsigned int difficult,
00287 unsigned int numRow,
00288 unsigned int numCol
00289 )
00290 {
00291 D5(printf("\nSCHEMAGAMEGENERATOR.getRouteNumber - START\n"));
00292
00293 assert( MAX_DIFFICULT >= MIN_DIFFICULT );
00294 assert( MIN_DIFFICULT > 0 );
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305 unsigned int numOfRoute =
00306 (
00307
00308 1
00309 +
00310 floor
00311 (
00312 ( (double)difficult
00313 /
00314 ( MAX_DIFFICULT - MIN_DIFFICULT )
00315 )
00316 *
00317 (
00318 sqrt( (double)(numRow * numCol)/( numRow + numCol ) )
00319 +
00320 rand() % (int) floor (
00321 sqrt(
00322 (double)(numRow * numCol)
00323 /
00324 ( numRow + numCol )
00325 )
00326 )
00327 )
00328 )
00329 );
00330
00331 assert( ( numOfRoute > 0 ) && ( numOfRoute < ( numRow * numCol ) ) );
00332
00333 D2(printf("\nNumber of way = %u\n",numOfRoute));
00334
00335 D5(printf("\nSCHEMAGAMEGENERATOR.getRouteNumber - END\n"));
00336
00337 return numOfRoute;
00338 }
00339
00340
00341
00342 directions set_number_of_available_cells( coordinates start,
00343 coordinates deny,
00344 unsigned int numRow,
00345 unsigned int numCol
00346 )
00347
00348 {
00349 D5(printf("\nSCHEMAGAMEGENERATOR.set_number_of_available_cells - START\n"));
00350
00351 directions avail;
00352
00353
00354 avail.left = ( start.row > deny.row ) ? ( start.row - deny.row ) : 0;
00355
00356 avail.right = ( numRow > ( 1 + start.row + deny.row ) ) ?
00357 ( numRow - ( 1 + start.row + deny.row ) ) : 0;
00358
00359 avail.up = (start.col > deny.col) ? ( start.col - deny.col ) : 0;
00360
00361 avail.down = ( numCol > ( 1 + start.col + deny.col ) ) ?
00362 ( numCol - ( 1 + start.col + deny.col ) ) : 0;
00363
00364 D3(printf("\nAvailable cells: Left %u, Right %u, Up %u, Down %u",
00365 avail.left,avail.right,avail.up,avail.down ));
00366
00367 D5(printf("\nSCHEMAGAMEGENERATOR.set_number_of_available_cells - END\n"));
00368
00369 return avail;
00370 }
00371
00372
00373
00374 unsigned int get_MaxRouteLen( unsigned int numRow,
00375 unsigned int numCol,
00376 coordinates start,
00377 coordinates door
00378 )
00379 {
00380 D5(printf("\nSCHEMAGAMEGENERATOR.get_MaxRouteLen - START\n"));
00381
00382
00383
00384
00385
00386
00387
00388
00389 const unsigned int bestParam = 3;
00390
00391 unsigned int optimal = ( ( numRow * numCol ) / bestParam );
00392
00393 const unsigned int minimum = (unsigned int)
00394 (
00395 bestParam +
00396 abs( start.row - door.row ) +
00397 abs( start.col - door.col )
00398 );
00399
00400 if( optimal < minimum )
00401 optimal = minimum;
00402
00403 D5(printf("\nSCHEMAGAMEGENERATOR.get_MaxRouteLen - END\n"));
00404
00405 return optimal;
00406 }
00407
00408
00409
00410 unsigned int point_in_random_direction( unsigned int avail_dir1,
00411 unsigned int avail_dir2,
00412 unsigned int start_dir ,
00413 unsigned int deny_area ,
00414 double *probability,
00415 const double LOW
00416 )
00417 {
00418 D5(printf("\nSCHEMAGAMEGENERATOR.point_in_random_direction - START\n"));
00419
00420
00421
00422
00423 if( rand() % 2 )
00424 {
00425
00426 if(avail_dir1 > 0)
00427 {
00428 ( *probability ) = 1 - LOW;
00429
00430 const unsigned int returnValue = ( rand() % avail_dir1 );
00431
00432 D8(printf("\nProbability: %lf Point coordinate: %u",
00433 (*probability) , returnValue ));
00434
00435 D5(printf("\nSCHEMAGAMEGENERATOR.point_in_random_direction - END\n"));
00436
00437 return returnValue;
00438 }
00439
00440
00441 ( *probability ) = LOW;
00442
00443 const unsigned int returnValue = ( 1 +
00444 start_dir +
00445 deny_area +
00446 rand() % avail_dir2 );
00447
00448 D8(printf("\nProbability: %lf Point coordinate: %u",
00449 (*probability) , returnValue ));
00450
00451 D5(printf("\nSCHEMAGAMEGENERATOR.point_in_random_direction - END\n"));
00452
00453 return returnValue;
00454 }
00455
00456
00457
00458
00459 if(avail_dir2 > 0)
00460 {
00461 ( *probability ) = LOW;
00462
00463 const unsigned int returnValue = ( 1 +
00464 start_dir +
00465 deny_area +
00466 rand() % avail_dir2 );
00467
00468 D8(printf("\nProbability: %lf Point coordinate: %u",
00469 (*probability) , returnValue ));
00470
00471 D5(printf("\nSCHEMAGAMEGENERATOR.point_in_random_direction - END\n"));
00472
00473 return returnValue;
00474 }
00475
00476
00477 ( *probability ) = 1 - LOW;
00478
00479 const unsigned int returnValue = ( rand() % avail_dir1 );
00480
00481 D8(printf("\nProbability: %lf Point coordinate: %u",
00482 (*probability) , returnValue ));
00483
00484 D5(printf("\nSCHEMAGAMEGENERATOR.point_in_random_direction - END\n"));
00485
00486 return returnValue;
00487 }
00488
00489
00490
00491 void get_direction_from_point( unsigned int numRow,
00492 unsigned int numCol,
00493 unsigned int *currentRow,
00494 unsigned int *currentCol,
00495 double probabilityLeft,
00496 double probabilityUp
00497 )
00498 {
00499
00500 D5(printf("\nSCHEMAGAMEGENERATOR.get_direction_from_point - START\n"));
00501
00502
00503 const double currentProbability = (double)(rand() % 1001)/1000;
00504
00505 assert( ( 0 <= currentProbability ) && ( currentProbability <= 1 ) );
00506
00507
00508
00509
00510
00511 if( rand() % 2)
00512 {
00513 if( currentProbability < probabilityLeft )
00514 {
00515 if( (*currentRow) > 0 )
00516 (*currentRow) = (*currentRow) - 1;
00517 else
00518 (*currentRow) = (*currentRow) + 1;
00519 }
00520 else
00521 {
00522 if( ((*currentRow) + 1) < numRow )
00523 (*currentRow) = (*currentRow) + 1;
00524 else
00525 (*currentRow) = (*currentRow) - 1;
00526 }
00527 }
00528 else
00529 {
00530 if( currentProbability < probabilityUp )
00531 {
00532 if( (*currentCol) > 0 )
00533 (*currentCol) = (*currentCol) - 1;
00534 else
00535 (*currentCol) = (*currentCol) + 1;
00536 }
00537 else
00538 {
00539 if( ((*currentCol) + 1) < numCol )
00540 (*currentCol) = (*currentCol) + 1;
00541 else
00542 (*currentCol) = (*currentCol) - 1;
00543 }
00544 }
00545
00546 D8(printf("\nCurrent position (%u,%u) Probability %.3lf (>LOW?)",
00547 (*currentRow),(*currentCol),currentProbability ));
00548
00549 D5(printf("\nSCHEMAGAMEGENERATOR.get_direction_from_point - END\n"));
00550 }
00551
00552
00553
00554 void increase_schema_difficult( char **Map,
00555 unsigned int numRow,
00556 unsigned int numCol
00557 )
00558 {
00559 D5(printf("\nSCHEMAGAMEGENERATOR.increase_schema_difficult - START\n"));
00560
00561
00562 unsigned int i = 0, j = 0;
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572 for(i=1; i<(numRow-1); i++)
00573 for(j=1; j<(numCol-1); j++)
00574 if(
00575 (
00576 Map[i-1][j-1] & Map[i-1][j] & Map[i-1][j+1] &
00577 Map[i][j-1] & Map[i][j] & Map[i][j+1] &
00578 Map[i+1][j-1] & Map[i+1][j] & Map[i+1][j+1]
00579 )
00580 == FREE
00581 )
00582 Map[ i ][ j ] = CLOSE;
00583
00584
00585
00586
00587
00588
00589
00590 for(i=1; i<numRow; i++)
00591 for(j=1; j<numCol; j++)
00592 if( (Map[i-1][j-1]==CLOSE) && (Map[i-1][j]==CLOSE) &&
00593 (Map[i][j-1] ==CLOSE) && (Map[i][j] ==CLOSE)
00594 )
00595 Map[ i - rand()%2 ][ j - rand()%2 ] = FREE;
00596
00597 D5(printf("\nSCHEMAGAMEGENERATOR.increase_schema_difficult - END\n"));
00598 }
00599
00600
00601
00602 void save_schema_to_file( char **gameMap,
00603 unsigned int numRow,
00604 unsigned int numCol,
00605 FILE *newSchemaFile
00606 )
00607 {
00608 D5(printf("\nSCHEMAGAMEGENERATOR.save_schema_to_file - START\n"));
00609
00610 assert( newSchemaFile != NULL );
00611
00612 fprintf(newSchemaFile , "#Built by: %s v%s\n",PRGNAME,PRGVERS);
00613 fprintf(newSchemaFile , "#Rows %u, Columns %u\n" ,numRow,numCol);
00614 fprintf(newSchemaFile , "#Schema:\n");
00615
00616
00617 unsigned int i = 0, j = 0;
00618
00619 D4(printf("\n"));
00620 for(i=0; i<numRow; i++){
00621
00622 for(j=0; j<numCol; j++){
00623
00624 fprintf(newSchemaFile,"%c",gameMap[i][j]);
00625
00626 D4(printf("%c",gameMap[i][j]));
00627 }
00628
00629 fprintf(newSchemaFile,"\n");
00630
00631 D4(printf("\n"));
00632 }
00633
00634 assert( newSchemaFile != NULL );
00635
00636 fclose(newSchemaFile);
00637
00638 D5(printf("\nSCHEMAGAMEGENERATOR.save_schema_to_file - END\n"));
00639 }
00640
00641