home *** CD-ROM | disk | FTP | other *** search
/ Chip 2011 November / CHIP_2011_11.iso / Programy / Inne / Gry / Atomic_Tanks / Atomic-Tanks-5.1.exe / src / files.cpp < prev    next >
C/C++ Source or Header  |  2011-03-23  |  33KB  |  1,107 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <dirent.h>
  5.  
  6. // basically all UNIX-like OSes should use stat
  7. #ifndef WIN32
  8. #include <sys/stat.h>
  9. #endif
  10.  
  11. #include "player.h"
  12. #include "files.h"
  13. #include "main.h"
  14. #include "text.h"
  15.  
  16. /*
  17. This function saves the game in progress.
  18. All data is saved in a text file for flexiblity.
  19. Returns TRUE on success and FALSE on failure.
  20. */
  21. int Save_Game(GLOBALDATA *global, ENVIRONMENT *env)
  22. {
  23.   FILE *game_file = NULL;
  24.   char *file_path = NULL;
  25.   int player_count = 0;
  26.   PLAYER *my_player = NULL;
  27.   int count;
  28.   int global_player_number;
  29.  
  30.   // figure out file name
  31.   file_path = (char *) calloc( strlen(global->configDir) +
  32.                                strlen(global->game_name) + 24,
  33.                                sizeof(char) );
  34.   if (! file_path)
  35.     return FALSE;
  36.  
  37.   sprintf(file_path, "%s/%s.sav", global->configDir, global->game_name);
  38.  
  39.   game_file = fopen(file_path, "w");
  40.   free(file_path);
  41.   if (!game_file)
  42.     return FALSE;
  43.  
  44.   // write global data
  45.   fprintf(game_file, "GLOBAL\n");
  46.   fprintf(game_file, "ROUNDS=%f\n", global->rounds);
  47.   fprintf(game_file, "CURRENTROUND=%d\n", global->currentround);
  48.   fprintf(game_file, "CAMPAIGNMODE=%f\n", global->campaign_mode);
  49.   fprintf(game_file, "***\n");
  50.  
  51.   // write envrionment data
  52.   fprintf(game_file, "ENVIRONMENT\n");
  53.   fprintf(game_file, "***\n");
  54.  
  55.   // write player data
  56.   fprintf(game_file, "PLAYERS\n");
  57.   while ( player_count < global->numPlayers )
  58.   {
  59.       my_player = global->players[player_count];
  60.       global_player_number = 0;
  61.       while ( strcmp(global->allPlayers[global_player_number]->getName(), my_player->getName() ) )
  62.         global_player_number++;
  63.       fprintf(game_file, "PLAYERNUMBER=%d\n", global_player_number);
  64.       fprintf(game_file, "SCORE=%d\n", my_player->score);
  65.       fprintf(game_file, "MONEY=%d\n", my_player->money);
  66.       fprintf(game_file, "TYPE=%f\n", my_player->type);
  67.       fprintf(game_file, "TYPESAVED=%f\n", my_player->type_saved);
  68.       for (count = 0; count < WEAPONS; count++)
  69.         fprintf(game_file, "WEAPON=%d %d\n", count, my_player->nm[count]);
  70.       for (count = 0; count < ITEMS; count++)
  71.         fprintf(game_file, "ITEM=%d %d\n", count, my_player->ni[count]);
  72.       fprintf(game_file, "***\n");
  73.       player_count++;
  74.     }
  75.  
  76.   fclose(game_file);
  77.  
  78.   // save the current config
  79.   file_path = (char *) calloc( strlen(global->configDir) +
  80.                                strlen(global->game_name) + 24,
  81.                                sizeof(char) );
  82.   if (! file_path)
  83.     return FALSE;
  84.   sprintf(file_path, "%s/%s.txt", global->configDir, global->game_name);
  85.   Save_Game_Settings_Text(global, env, file_path);
  86.   free(file_path);
  87.  
  88.   return TRUE;
  89. }
  90.  
  91.  
  92.  
  93. /*
  94. This function attempts to load a saved
  95. game.
  96. The function returns TRUE on success and
  97. FALSE is an error occures.
  98. -- Jesse
  99. */
  100. int Load_Game(GLOBALDATA *global, ENVIRONMENT *env)
  101. {
  102.   char line[512];
  103.   char *field, *value;
  104.   int index, amount, player_count = 0;
  105.   FILE *my_file;
  106.   char *file_path;
  107.   int stage = NO_STAGE;
  108.   char *got_line;
  109.   int global_player_number;
  110.  
  111.   // load config settings
  112.   /*
  113.   file_path = (char *) calloc( strlen(homedir) +
  114.                                strlen(global->game_name) + 24,
  115.                                sizeof(char) );
  116.   if (! file_path)
  117.     return FALSE;
  118.   sprintf(file_path, "%s/.atanks/%s.txt", homedir, global->game_name);
  119.   my_file = fopen(file_path, "r");
  120.   free(file_path);
  121.   if (! my_file)
  122.     return FALSE;
  123.   global->loadFromFile_Text(my_file);
  124.   env->loadFromFile_Text(my_file);
  125.   fclose(my_file);
  126.   */
  127.  
  128.   file_path = (char *) calloc( strlen(global->configDir) +
  129.                                strlen(global->game_name) + 24,
  130.                                sizeof(char) );
  131.   if (! file_path)
  132.     return FALSE;
  133.  
  134.   sprintf(file_path, "%s/%s.sav", global->configDir, global->game_name);
  135.  
  136.   my_file = fopen(file_path, "r");
  137.   free(file_path);
  138.   if (! my_file)
  139.     return FALSE;
  140.  
  141.   // read a line from the file
  142.   got_line = fgets(line, 512, my_file);
  143.   // keep reading until we hit EOF or error
  144.   while ( (got_line) && (player_count < MAXPLAYERS) )
  145.   {
  146.       // clear end of line
  147.       if ( strchr(line, '\n') )
  148.         strchr(line, '\n')[0] = '\0';
  149.       if ( strchr(line, '\r') )
  150.         strchr(line, '\r')[0] = '\0';
  151.  
  152.       // check to see if we found a new stage
  153.       if (! strcasecmp(line, "global") )
  154.         stage = GLOBAL_STAGE;
  155.       else if (! strcasecmp(line, "environment") )
  156.         stage = ENVIRONMENT_STAGE;
  157.       else if (! strcasecmp(line, "players") )
  158.         stage = PLAYER_STAGE;
  159.  
  160.       // not a new stage, seperate field and value
  161.       else
  162.         {
  163.           value = strchr(line, '=');
  164.           if (value)        // valid line
  165.             {
  166.               field = line;
  167.               value[0] = '\0';   // seperate field and value;
  168.               value++;           // go to first place after =
  169.               // interpret data
  170.               switch (stage)
  171.                 {
  172.                 case GLOBAL_STAGE:
  173.                   if (! strcasecmp(field, "rounds") )
  174.                     sscanf(value, "%lf", &global->rounds);
  175.                   else if (! strcasecmp(field, "currentround") )
  176.                     sscanf(value, "%d", &global->currentround);
  177.                   else if (! strcasecmp(field, "campaignmode") )
  178.                     sscanf(value, "%lf", &global->campaign_mode);
  179.  
  180.                   break;
  181.                 case ENVIRONMENT_STAGE:
  182.  
  183.                   break;
  184.                 case PLAYER_STAGE:
  185.                   if (! strcasecmp(field, "playernumber") )
  186.                     {
  187.                       sscanf(value, "%d", &global_player_number);
  188.                       global->addPlayer( global->allPlayers[global_player_number] );
  189.                       /*  the loading of the preferences is (unfortunately) disabled and I do not know why.
  190.                           As long as they *are* disabled, PerPlay-Config bots have to get a new config here,
  191.                           or they use the global config, rendering PerPlay-Config useless. */
  192.                       if    ( (global->players[player_count]->preftype    ==    PERPLAY_PREF)
  193.                            && (global->players[player_count]->type            !=    HUMAN_PLAYER))
  194.                         global->players[player_count]->generatePreferences();
  195.                       global->players[player_count]->initialise();
  196.                     }
  197.                   else if (! strcasecmp(field, "score") )
  198.                     sscanf(value, "%d", &(global->players[player_count]->score) );
  199.                   else if (! strcasecmp(field, "money") )
  200.                     sscanf(value, "%d", &(global->players[player_count]->money) );
  201.                   else if (! strcasecmp(field, "type") )
  202.                     sscanf(value, "%lf", &(global->players[player_count]->type) );
  203.                   else if (! strcasecmp(field, "typesaved") )
  204.                     sscanf(value, "%lf", &(global->players[player_count]->type_saved) );
  205.                   else if (! strcasecmp(field, "weapon") )
  206.                     {
  207.                       sscanf(value, "%d %d", &index, &amount);
  208.                       global->players[player_count]->nm[index] = amount;
  209.                     }
  210.                   else if (! strcasecmp(field, "item") )
  211.                     {
  212.                       sscanf(value, "%d %d", &index, &amount);
  213.                       global->players[player_count]->ni[index] = amount;
  214.                     }
  215.                   break;
  216.                 }    // end of stage
  217.  
  218.             }       //     end of valid line
  219.           else if ( (! strcmp(line, "***") ) && (stage == PLAYER_STAGE) )
  220.             player_count++;
  221.  
  222.         }     // end of field value area
  223.  
  224.       // read next line of file
  225.       got_line = fgets(line, 512, my_file);
  226.  
  227.     }    // end of reading file
  228.   fclose(my_file);
  229.   return TRUE;
  230. }
  231.  
  232.  
  233.  
  234. /*
  235. Check to see if a saved game exists with the given name.
  236. */
  237. int Check_For_Saved_Game(GLOBALDATA *global)
  238. {
  239.   FILE *my_file;
  240.   char *path_name;
  241.  
  242.   path_name = (char *) calloc( strlen(global->configDir) + strlen(global->game_name) + 24,
  243.                                sizeof(char) );
  244.   if (! path_name)
  245.     return FALSE;
  246.  
  247.   sprintf(path_name, "%s/%s.sav", global->configDir, global->game_name);
  248.  
  249.   my_file = fopen(path_name, "r");
  250.   free(path_name);
  251.   if (my_file)
  252.   {
  253.      fclose(my_file);
  254.      return TRUE;
  255.   }
  256.   else
  257.     return FALSE;
  258.  
  259. }
  260.  
  261.  
  262.  
  263. /*
  264. This function copies the atanks config file
  265. from the HOME_DIR folder to HOME_DIR/.atanks
  266. If the .atanks folder does not exist, this
  267. function will create it.
  268. Returns TRUE on success and FALSE on error.
  269. */
  270.  
  271. int Copy_Config_File(GLOBALDATA *global)
  272. {
  273.   FILE *source_file, *dest_file;
  274.   char source_path[1024], dest_path[1024];
  275.   char buffer[1024];
  276.   char *my_home_folder;
  277.   int status;
  278.  
  279.   // figure out where home is
  280.   my_home_folder = getenv(HOME_DIR);
  281.   if (! my_home_folder)
  282.     my_home_folder = (char *)".";
  283.  
  284.   // check to see if the config file has already been copied
  285.   snprintf(source_path, 1024, "%s/atanks-config.txt", global->configDir);
  286.   source_file = fopen(source_path, "r");
  287.   if (source_file)     // config file is in the right place
  288.     {
  289.       fclose(source_file);
  290.       return TRUE;
  291.     }
  292.  
  293.   /*
  294.   // check to make sure we have a source file
  295.   snprintf(source_path, 1024, "%s/.atanks-config.txt", my_home_folder);
  296.   source_file = fopen(source_path, "r");
  297.   if (! source_file)
  298.      return TRUE;
  299.   */
  300.  
  301.   // file not copied yet, create the required directory
  302.   snprintf(buffer, 1024, "%s/.atanks", my_home_folder);
  303. #ifdef WIN32
  304.   status = mkdir(buffer);
  305. #else
  306.   status = mkdir(buffer, 0700);
  307. #endif
  308.   if (status == -1)
  309.     {
  310.       printf( (char *)"Error occured. Unable to create sub directory.\n");
  311.       return FALSE;
  312.     }
  313.  
  314.   // check to make sure we have a source file
  315.   snprintf(source_path, 1024, "%s/.atanks-config.txt", my_home_folder);
  316.   source_file = fopen(source_path, "r");
  317.   if (! source_file)
  318.     return TRUE;
  319.  
  320.   // we already have an open source file, create destination file
  321.   snprintf(dest_path, 1024, "%s/atanks-config.txt", global->configDir);
  322.   dest_file = fopen(dest_path, "wb");
  323.   if (! dest_file)
  324.     {
  325.       printf( (char *)"Unable to create destination file.\n");
  326.       fclose(source_file);
  327.       return FALSE;
  328.     }
  329.  
  330.   // we have open files, let's copy
  331.   status = fread(buffer, 1, 1024, source_file);
  332.   while (status)
  333.     {
  334.       status = fwrite(buffer, 1, 1024, dest_file);
  335.       status = fread(buffer, 1, 1024, source_file);
  336.     }
  337.  
  338.   fclose(source_file);
  339.   fclose(dest_file);
  340.   return TRUE;
  341. }
  342.  
  343.  
  344.  
  345. // Make sure we have a music folder
  346. // Returns TRUE on success or FALSE
  347. // if an error occures.
  348. int Create_Music_Folder(GLOBALDATA *global)
  349. {
  350.    DIR *music_folder;
  351.    char *folder_path;
  352.    
  353.    folder_path = (char *) calloc( strlen(global->configDir) + 32, sizeof(char) );
  354.    if (! folder_path)
  355.       return FALSE;
  356.  
  357.    sprintf(folder_path, "%s/music", global->configDir);
  358.    music_folder = opendir(folder_path);
  359.    if (! music_folder)
  360.    {
  361.      #ifdef WIN32
  362.      mkdir(folder_path);
  363.      #else
  364.      mkdir(folder_path, 0700);
  365.      #endif
  366.    }
  367.    else    // it already exists
  368.      closedir(music_folder);
  369.  
  370.    free(folder_path);
  371.    return TRUE;
  372. }
  373.  
  374.  
  375.  
  376.  
  377.  
  378. /*
  379. Displays lines of text.
  380. */
  381. void renderTextLines (GLOBALDATA *global, ENVIRONMENT *env,
  382.                       TEXTBLOCK *lines, int scrollOffset,
  383.                       const FONT* fnt, const int spacing )
  384. {
  385.   const int textheight = text_height (fnt) ;
  386.   const int textheight_s = textheight * spacing ;
  387.   int yOffset = scrollOffset;
  388.   char *text;
  389.   int tLen, count;
  390.  
  391.   for (count = 0;
  392.        (count < lines->total_lines) && (yOffset < global->screenHeight);
  393.        count++)
  394.     {
  395.       text = lines->complete_text[count];
  396.       tLen = text_length (fnt, text);
  397.  
  398.           textout_centre_ex (env->db, fnt, text,
  399.                              global->halfWidth + 2, global->halfHeight + yOffset + 2, BLACK, -1);
  400.           textout_centre_ex (env->db, fnt, text,
  401.                              global->halfWidth, global->halfHeight + yOffset, WHITE, -1);
  402.       yOffset += textheight_s;
  403.     }
  404. }
  405.  
  406.  
  407.  
  408.  
  409. /*
  410. Scroll text in a box
  411. */
  412. void scrollTextList (GLOBALDATA *global, ENVIRONMENT *env,
  413.                      TEXTBLOCK *lines)
  414. {
  415.   /* Justin says: this function, along with renderTextLines, aren't
  416.   exactly efficient.  I think they could use rewrite. */
  417.   static const int numItemsSrc[] = { 100, 30 } ;
  418.  
  419.   // DATAFILE *dffont ;
  420.   const FONT* fnt = font;
  421.   int spacing = 2;
  422.   int tOffset = rand ();
  423.   int itemType = rand () / (RAND_MAX/2 + 1) ;
  424.   int numItems = numItemsSrc[itemType];
  425.   int my_key, done = FALSE;
  426.   int moving = TRUE;
  427.  
  428.   draw_circlesBG (global, env->db, 0, 0, global->screenWidth, global->screenHeight, false);
  429.   drawMenuBackground (global, env, BACKGROUND_BLANK, abs (tOffset), numItems);
  430.   quickChange (global, env->db);
  431.   //set_clip_rect (env->db, global->halfWidth - 300 + 1, 100 + 1,
  432.   //               global->halfWidth + 300 - 1, global->screenHeight - 100 - 1);
  433.   set_clip_rect(env->db, global->halfWidth - 300 + 1, global->menuBeginY + 1,
  434.                 global->halfWidth + 300 - 1, global->menuEndY - 1);
  435.   int scrollOffset = 0;
  436.   flush_inputs ();
  437.   if (! global->os_mouse) show_mouse (NULL);
  438.  
  439.   // lines->Display_All(TRUE);
  440.   do
  441.     {
  442.       drawMenuBackground (global, env, BACKGROUND_BLANK, abs (tOffset), numItems);
  443.  
  444.       renderTextLines (global, env, lines, scrollOffset,
  445.                        fnt, spacing );
  446.       //blit (env->db, screen, global->halfWidth - 300, 100, global->halfWidth - 300, 100,
  447.       //      601, global->screenHeight - 199);
  448.       blit(env->db, screen, global->halfWidth - 300, global->menuBeginY,
  449.            global->halfWidth - 300, global->menuBeginY, 601, 
  450.            global->screenHeight - 2 * global->menuBeginY);
  451.       LINUX_REST;
  452.       if (moving)
  453.       {
  454.          tOffset++;
  455.          scrollOffset--;
  456.       }
  457.  
  458.       if (scrollOffset < -(global->halfHeight - 100 + lines->total_lines * 30))
  459.         scrollOffset = global->halfHeight - 100;
  460.       if (global->close_button_pressed)
  461.         break;
  462.       if ( keypressed() )
  463.       {
  464.           my_key = (readkey()) >> 8;
  465.           switch (my_key)
  466.           {
  467.              case KEY_ESC: done = TRUE;
  468.                        break;
  469.              case KEY_SPACE: 
  470.                        moving = TRUE; 
  471.                        break;
  472.              case KEY_UP:
  473.                        tOffset--;
  474.                        scrollOffset++;
  475.                        moving = FALSE;
  476.                        break;
  477.              case KEY_DOWN:
  478.                        tOffset++;
  479.                        scrollOffset--;
  480.                        moving = FALSE;
  481.                        break;
  482.           }      // end of switch
  483.       }       // end of key pressed
  484.     }
  485.   while ( (! done) && (!mouse_b) );
  486.  
  487.   if (! global->os_mouse) show_mouse (screen);
  488.   set_clip_rect (env->db, 0, 0, (global->screenWidth-1), (global->screenHeight-1));
  489.   flush_inputs ();
  490. }
  491.  
  492.  
  493.  
  494. /* Flush key buffer and waits for button releases */
  495. void flush_inputs()
  496. {
  497.   do { }
  498.   while (mouse_b);
  499.   clear_keybuf();
  500. }
  501.  
  502.  
  503.  
  504. // This file loads weapons, naturals and items
  505. // from a text file
  506. // Returns TRUE on success and FALSE on failure
  507. int Load_Weapons_Text(GLOBALDATA *global)
  508. {
  509.   FILE *wfile;
  510.   char *path_to_file;
  511.   char *status;
  512.   char line[512];
  513.   int file_stage = 0;     // weapons, natruals, items
  514.   int data_stage = 0;         // name, descrption, data
  515.   int item_count = 0, weapon_count = 0, natural_count = 0;
  516.  
  517.   setlocale(LC_NUMERIC, "C");
  518.   // get path name
  519.   path_to_file = (char *) calloc( strlen(global->dataDir) + 64, sizeof(char) );
  520.   if (! path_to_file)
  521.     {
  522.       printf( "Memory error occured while loading weapons.\n");
  523.       return FALSE;
  524.     }
  525.  
  526.   if (global->language == LANGUAGE_ENGLISH)
  527.     sprintf(path_to_file, "%s/text/weapons.txt", global->dataDir);
  528.   else if (global->language == LANGUAGE_PORTUGUESE)
  529.     sprintf(path_to_file, "%s/text/weapons.pt_BR.txt", global->dataDir);
  530.   else if (global->language == LANGUAGE_FRENCH)
  531.     sprintf(path_to_file, "%s/text/weapons_fr.txt", global->dataDir);
  532.   else if (global->language == LANGUAGE_GERMAN)
  533.     sprintf(path_to_file, "%s/text/weapons_de.txt", global->dataDir);
  534.   else if (global->language == LANGUAGE_SLOVAK)
  535.     sprintf(path_to_file, "%s/text/weapons_sk.txt", global->dataDir);
  536.   else if (global->language == LANGUAGE_RUSSIAN)
  537.     sprintf(path_to_file, "%s/text/weapons_ru.txt", global->dataDir);
  538.   else if (global->language == LANGUAGE_SPANISH)
  539.     sprintf(path_to_file, "%s/text/weapons_ES.txt", global->dataDir);
  540.   else if (global->language == LANGUAGE_ITALIAN)
  541.     sprintf(path_to_file, "%s/text/weapons_it.txt", global->dataDir);
  542.  
  543.   // open file
  544.   wfile = fopen(path_to_file, "r");
  545.   // free memory
  546.   // free(path_to_file);
  547.   if (! wfile)
  548.     {
  549.       printf( "Unable to open weapons file. (%s)\n", path_to_file);
  550.       free(path_to_file);
  551.       return FALSE;
  552.     }
  553.   free(path_to_file);
  554.  
  555.   Clear_Weapons();            // make sure arrays are cleared before loading data
  556.   // read line
  557.   status = fgets(line, 512, wfile);
  558.   while (status)
  559.     {
  560.       // clear end of line
  561.       if ( strchr(line, '\n') )
  562.         strchr(line, '\n')[0] = '\0';
  563.       if ( strchr(line, '\r') )
  564.         strchr(line, '\r')[0] = '\0';
  565.  
  566.       // skip # and empty lines
  567.       if ( (! (line[0] == '#') ) && ( strlen(line) > 2 ) )
  568.         {
  569.           // check for header
  570.           if (! strcasecmp(line, "*WEAPONS*") )
  571.             {
  572.               file_stage = 0;
  573.               data_stage = 0;
  574.             }
  575.           else if (! strcasecmp(line, "*NATURALS*") )
  576.             {
  577.               file_stage = 1;
  578.               data_stage = 0;
  579.             }
  580.           else if (! strcasecmp(line, "*ITEMS*") )
  581.             {
  582.               file_stage = 2;
  583.               data_stage = 0;
  584.             }
  585.  
  586.           // not a special line, let's read some data
  587.           else
  588.             {
  589.               // weapon
  590.               if ( (file_stage == 0) && (weapon_count < WEAPONS) )
  591.                 {
  592.                   if (data_stage == 0)   // name
  593.                     strcpy(weapon[weapon_count].name, line);
  594.                   else if (data_stage == 1)
  595.                     strcpy(weapon[weapon_count].description, line);
  596.                   else if (data_stage == 2)
  597.                     {
  598.                       sscanf(line, "%d %d %lf %lf %d %d %d %d %d %d %d %d %d %d %d %d %d %lf %d %lf %lf %lf %d %lf",
  599.                              &(weapon[weapon_count].cost),
  600.                              &(weapon[weapon_count].amt),
  601.                              &(weapon[weapon_count].mass),
  602.                              &(weapon[weapon_count].drag),
  603.                              &(weapon[weapon_count].radius),
  604.                              &(weapon[weapon_count].sound),
  605.                              &(weapon[weapon_count].etime),
  606.                              &(weapon[weapon_count].damage),
  607.                              &(weapon[weapon_count].eframes),
  608.                              &(weapon[weapon_count].picpoint),
  609.                              &(weapon[weapon_count].spread),
  610.                              &(weapon[weapon_count].delay),
  611.                              &(weapon[weapon_count].noimpact),
  612.                              &(weapon[weapon_count].techLevel),
  613.                              &(weapon[weapon_count].warhead),
  614.                              &(weapon[weapon_count].numSubmunitions),
  615.                              &(weapon[weapon_count].submunition),
  616.                              &(weapon[weapon_count].impartVelocity),
  617.                              &(weapon[weapon_count].divergence),
  618.                              &(weapon[weapon_count].spreadVariation),
  619.                              &(weapon[weapon_count].launchSpeed),
  620.                              &(weapon[weapon_count].speedVariation),
  621.                              &(weapon[weapon_count].countdown),
  622.                              &(weapon[weapon_count].countVariation) );
  623.                     }
  624.                   data_stage++;
  625.                   if (data_stage > 2)
  626.                     {
  627.                       data_stage = 0;
  628.                       weapon_count++;
  629.                     }
  630.                 }       // end of weapon section
  631.  
  632.               // naturals
  633.               else if ( (file_stage == 1) && (natural_count < NATURALS) )
  634.                 {
  635.                   if (data_stage == 0)   // name
  636.                     strcpy(naturals[natural_count].name, line);
  637.                   else if (data_stage == 1)
  638.                     strcpy(naturals[natural_count].description, line);
  639.                   else if (data_stage == 2)
  640.                     {
  641.                       sscanf(line, "%d %d %lf %lf %d %d %d %d %d %d %d %d %d %d %d %d %d %lf %d %lf %lf %lf %d %lf",
  642.                              &(naturals[natural_count].cost),
  643.                              &(naturals[natural_count].amt),
  644.                              &(naturals[natural_count].mass),
  645.                              &(naturals[natural_count].drag),
  646.                              &(naturals[natural_count].radius),
  647.                              &(naturals[natural_count].sound),
  648.                              &(naturals[natural_count].etime),
  649.                              &(naturals[natural_count].damage),
  650.                              &(naturals[natural_count].eframes),
  651.                              &(naturals[natural_count].picpoint),
  652.                              &(naturals[natural_count].spread),
  653.                              &(naturals[natural_count].delay),
  654.                              &(naturals[natural_count].noimpact),
  655.                              &(naturals[natural_count].techLevel),
  656.                              &(naturals[natural_count].warhead),
  657.                              &(naturals[natural_count].numSubmunitions),
  658.                              &(naturals[natural_count].submunition),
  659.                              &(naturals[natural_count].impartVelocity),
  660.                              &(naturals[natural_count].divergence),
  661.                              &(naturals[natural_count].spreadVariation),
  662.                              &(naturals[natural_count].launchSpeed),
  663.                              &(naturals[natural_count].speedVariation),
  664.                              &(naturals[natural_count].countdown),
  665.                              &(naturals[natural_count].countVariation) );
  666.                     }
  667.  
  668.                   data_stage++;
  669.                   if (data_stage > 2)
  670.                     {
  671.                       data_stage = 0;
  672.                       natural_count++;
  673.                     }
  674.  
  675.                 }       // end of naturals
  676.  
  677.               // item section
  678.               else if ( (file_stage == 2) && (item_count < ITEMS) )
  679.                 {
  680.                   if (data_stage == 0)   // name
  681.                     strcpy(item[item_count].name, line);
  682.                   else if (data_stage == 1)
  683.                     strcpy(item[item_count].description, line);
  684.                   else if (data_stage == 2)
  685.                     {
  686.                       sscanf(line, "%d %d %d %d %d %lf %lf %lf %lf %lf %lf",
  687.                              &(item[item_count].cost),
  688.                              &(item[item_count].amt),
  689.                              &(item[item_count].selectable),
  690.                              &(item[item_count].techLevel),
  691.                              &(item[item_count].sound),
  692.                              &(item[item_count].vals[0]),
  693.                              &(item[item_count].vals[1]),
  694.                              &(item[item_count].vals[2]),
  695.                              &(item[item_count].vals[3]),
  696.                              &(item[item_count].vals[4]),
  697.                              &(item[item_count].vals[5]) );
  698.                     }
  699.  
  700.                   data_stage++;
  701.                   if (data_stage > 2)
  702.                     {
  703.                       data_stage = 0;
  704.                       item_count++;
  705.                     }
  706.                 }         // end of items
  707.  
  708.             }       // end of reading data from a valid line
  709.  
  710.         }     // end of valid line
  711.  
  712.       // read in data
  713.       status = fgets(line, 512, wfile);
  714.     }
  715.  
  716.   // close file
  717.   fclose(wfile);
  718.   // go home
  719.   return TRUE;
  720. }
  721.  
  722.  
  723.  
  724.  
  725. /*
  726. Filter out files that do not have .sav in the name.
  727. */
  728. #ifndef MACOSX
  729. int Filter_File( const struct dirent *my_file )
  730. #else
  731. int Filter_File( struct dirent *my_file )
  732. #endif
  733. {
  734.   if ( strstr(my_file->d_name, ".sav") )
  735.     return TRUE;
  736.   else
  737.     return FALSE;
  738. }
  739.  
  740. /*
  741. This function finds a list of saved games on your profile.
  742. On error, NULL is returned. If all goes well, a list of file names
  743. are returned.
  744. After use, the return value should be freed.
  745. */
  746. #ifndef WIN32
  747. struct dirent ** Find_Saved_Games(GLOBALDATA *global, int *num_files_found)
  748.   {
  749.     struct dirent **my_list;
  750.     int status;
  751.  
  752.     status = scandir(global->configDir, &my_list, Filter_File, alphasort);
  753.     if (status < 0)
  754.       {
  755.         printf( (char *)"Error trying to find saved games.\n");
  756.         return NULL;
  757.       }
  758.  
  759.     *num_files_found = status;
  760.     return my_list;
  761.   }
  762. #endif
  763.  
  764.  
  765.  
  766. /*
  767. This function hunts for saved games. If games are found, the
  768. function returns an array of filenames. If an error occures
  769. or no files are found, NULL is returned.
  770. */
  771. #ifdef WIN32
  772. struct dirent ** Find_Saved_Games(GLOBALDATA *global, int *num_files_found)
  773.   {
  774.     struct dirent **my_list;
  775.     struct dirent *one_file;
  776.     int file_count = 0;
  777.     DIR *game_dir;
  778.  
  779.     my_list = (struct dirent **) calloc(256, sizeof(struct dirent *));
  780.     if (! my_list)
  781.       return NULL;
  782.  
  783.     game_dir = opendir(global->configDir);
  784.     if (! game_dir)
  785.     {
  786.       free(my_list);
  787.       return NULL;
  788.     }
  789.  
  790.     one_file = readdir(game_dir);
  791.     while ( (one_file) && (file_count < 256) )
  792.       {
  793.         // check to see if this is a save game file
  794.         if ( strstr( one_file->d_name, ".sav" ) )
  795.           {
  796.             my_list[file_count] = (struct dirent *) calloc(1, sizeof(struct dirent) );
  797.             if ( my_list[file_count] )
  798.               {
  799.                 memcpy(my_list[file_count], one_file, sizeof(struct dirent) );
  800.                 file_count++;
  801.               }
  802.           }
  803.  
  804.         one_file = readdir(game_dir);
  805.       }
  806.  
  807.     closedir(game_dir);
  808.     *num_files_found = file_count;
  809.     return my_list;
  810.   }
  811. #endif
  812.  
  813.  
  814.  
  815.  
  816. /*
  817.  * This function grabs a random quote from the war_quotes.txt file.
  818.  * This file is held in the data directory (dataDir) and contains
  819.  * one-line quotes.
  820.  * The function returns a pointer to the quote on success and a NULL
  821.  * on failure. The line should be free()ed after use.
  822.  * -- Jesse
  823.  *  */
  824. /*
  825. char *Get_Random_Quote(GLOBALDATA *global)
  826. {
  827.     char *path_to_file = NULL;
  828.     char *line, *result;
  829.     FILE *quote_file = NULL;
  830.     int line_count = 0;
  831.     int index = 0;
  832.     int random_number;
  833.  
  834.     line = (char *) calloc(1024, sizeof(char));
  835.     if (! line)
  836.        return NULL;
  837.     path_to_file = (char *) calloc( strlen(global->dataDir) + 32, sizeof(char) );
  838.     if (! path_to_file)
  839.     {
  840.        free(line);
  841.        return NULL;
  842.     }
  843.  
  844.     if (global->language == LANGUAGE_RUSSIAN)
  845.        sprintf(path_to_file, "%s/war_quotes_ru.txt", global->dataDir);
  846.     else
  847.        sprintf(path_to_file, "%s/war_quotes.txt", global->dataDir);
  848.     quote_file = fopen(path_to_file, "r");
  849.     free(path_to_file);
  850.     if (! quote_file)
  851.     {
  852.        free(line);
  853.        return NULL;
  854.     }
  855.  
  856.     // search through file getting the number of lines
  857.     result = fgets(line, 1024, quote_file);
  858.     while (result)
  859.     {
  860.         line_count++;
  861.         result = fgets(line, 1024, quote_file);
  862.     }
  863.  
  864.     // return to the start of the file
  865.     rewind(quote_file);
  866.  
  867.     // generate a random number based on the size of the file
  868.     random_number = rand() % line_count;
  869.  
  870.     // search through and find the line we want
  871.     result = fgets(line, 1024, quote_file);
  872.     while ( (result) && (index < random_number) )
  873.     {
  874.         index++;
  875.         result = fgets(line, 1024, quote_file);
  876.     }
  877.  
  878.     fclose(quote_file);
  879.     if (! result)
  880.     {
  881.        free(line);
  882.        return NULL;
  883.     }
  884.  
  885.     // trim trailing newline character
  886.     if ( strchr(line, '\n') )
  887.        strchr(line, '\n')[0] = '\0';
  888.     return line;
  889. }
  890. */
  891.  
  892.  
  893.  
  894.  
  895. /*
  896.  * This function searches for bitmap files (.bmp) in the config folder.
  897.  * The function returns an array of bitmap file names. If no files
  898.  * are found, or an error occures, then NULL is returned.
  899.  * */
  900. char ** Find_Bitmaps(GLOBALDATA *global, int *bitmaps_found)
  901. {
  902.     char **my_list;
  903.     struct dirent *one_file;
  904.     int file_count = 0;
  905.     DIR *game_dir;
  906.  
  907.     my_list = (char **) calloc(256, sizeof(struct dirent *));
  908.     if (! my_list)
  909.       return NULL;
  910.  
  911.     
  912.     game_dir = opendir(global->configDir);
  913.     if (! game_dir)
  914.     {
  915.       free(my_list);
  916.       return NULL;
  917.     }
  918.  
  919.     one_file = readdir(game_dir);
  920.     while ( (one_file) && (file_count < 256) )
  921.     {
  922.          // check to see if this is a save game file
  923.          #ifdef LINUX
  924.          if ( strcasestr( one_file->d_name, ".bmp" ) )
  925.          #else
  926.          if ( (strstr(one_file->d_name, ".bmp")) || (strstr(one_file->d_name, ".BMP") ) )
  927.          #endif
  928.          {
  929.             my_list[file_count] = (char *) calloc( strlen(global->configDir) + strlen(one_file->d_name) + 16, sizeof(char) );
  930.             if ( my_list[file_count] )
  931.             {
  932.                sprintf(my_list[file_count], "%s/%s", global->configDir, one_file->d_name);
  933.                file_count++;
  934.             }
  935.          }
  936.  
  937.          one_file = readdir(game_dir);
  938.      }
  939.         
  940.      closedir(game_dir);
  941.      *bitmaps_found = file_count;
  942.      if (file_count < 1)
  943.      {
  944.          free(my_list);
  945.          my_list = NULL;
  946.      }
  947.      return my_list;
  948. }
  949.  
  950.  
  951.  
  952.  
  953.  
  954. BITMAP *create_gradient_strip (const gradient *grad, int length)
  955. {
  956.   BITMAP *strip;
  957.   int color;
  958.   int currLine;
  959.  
  960.   strip = create_bitmap (1, length);
  961.   if (! strip)
  962.      return NULL;
  963.  
  964.   clear_to_color (strip, BLACK);
  965.  
  966.   for (currLine = 0;currLine < length; currLine++)
  967.     {
  968.       color = gradientColorPoint (grad, length, currLine);
  969.       putpixel (strip, 0, currLine, color);
  970.     }
  971.  
  972.   return (strip);
  973. }
  974.  
  975.  
  976.  
  977.  
  978. int gradientColorPoint (const gradient *grad, double length, double line)
  979. {
  980.   int pointCount = 0;
  981.   double point = line / length;
  982.   int color;
  983.  
  984.   for (pointCount = 0; (point >= grad[pointCount].point) && (grad[pointCount].point != -1); pointCount++) { }
  985.   pointCount--;
  986.  
  987.   if (pointCount == -1)
  988.     {
  989.       color = makecol (grad[0].color.r, grad[0].color.g, grad[0].color.b);
  990.     }
  991.   else if (grad[pointCount + 1].point == -1)
  992.     {
  993.       color = makecol (grad[pointCount].color.r, grad[pointCount].color.g, grad[pointCount].color.b);
  994.     }
  995.   else
  996.     {
  997.       double i = (point - grad[pointCount].point) / (grad[pointCount + 1].point - grad[pointCount].point);
  998.       int r = (int)(interpolate (grad[pointCount].color.r, grad[pointCount + 1].color.r, i));
  999.       int g = (int)(interpolate (grad[pointCount].color.g, grad[pointCount + 1].color.g, i));
  1000.       int b = (int)(interpolate (grad[pointCount].color.b, grad[pointCount + 1].color.b, i));
  1001.  
  1002.       color = makecol (r, g, b);
  1003.     }
  1004.  
  1005.   return (color);
  1006. }
  1007.  
  1008.  
  1009.  
  1010.  
  1011.  
  1012. /*****************************************************************************
  1013.  * colorDistance
  1014.  *
  1015.  * Treat two color values as 3D vectors of the form <r,g,b>.
  1016.  * Compute the scalar size of the difference between the two vectors.
  1017.  * *****************************************************************************/
  1018. double colorDistance (int col1, int col2)
  1019. {
  1020.   double distance;
  1021.   int col1r, col1g, col1b;
  1022.   int col2r, col2g, col2b;
  1023.  
  1024.   col1r = getr (col1);
  1025.   col1g = getg (col1);
  1026.   col1b = getb (col1);
  1027.   col2r = getr (col2);
  1028.   col2g = getg (col2);
  1029.   col2b = getb (col2);
  1030.  
  1031.   // Treat the colour-cube as a space
  1032.   distance = vector_length_f ((float)(col1r - col2r), (float)(col1g - col2g), (float)(col1b - col2b));
  1033.   
  1034.   return (distance);
  1035. }
  1036.  
  1037.  
  1038.  
  1039.  
  1040. void Clear_Weapons()
  1041. {
  1042.     memset(weapon, 0, WEAPONS * sizeof(WEAPON));
  1043.     memset(naturals, 0, NATURALS * sizeof(WEAPON));
  1044.     memset(item, 0, ITEMS * sizeof(ITEM));   
  1045.  
  1046. }
  1047.  
  1048.  
  1049.  
  1050. int Display_Tank_Bitmap(ENVIRONMENT *env, int xpos, int ypos, void *image_number)
  1051. {
  1052.     double *temp_number = (double *) image_number;
  1053.     int my_number = (int) *temp_number;
  1054.     int use_tank_bitmap, use_turret_bitmap;
  1055.     BITMAP *dest = env->db;
  1056.     GLOBALDATA *global = env->_global;
  1057.  
  1058.     switch (my_number)
  1059.     {
  1060.          case CLASSIC_TANK:
  1061.           use_tank_bitmap = 8;
  1062.           use_turret_bitmap = 1;
  1063.           break;
  1064.         case BIGGREY_TANK:
  1065.           use_tank_bitmap = 9;
  1066.           use_turret_bitmap = 2;
  1067.           break;
  1068.         case T34_TANK:
  1069.           use_tank_bitmap = 10;
  1070.           use_turret_bitmap = 3;
  1071.           break;
  1072.         case HEAVY_TANK:
  1073.           use_tank_bitmap = 11;
  1074.           use_turret_bitmap = 4;
  1075.           break;
  1076.         case FUTURE_TANK:
  1077.           use_tank_bitmap = 12;
  1078.           use_turret_bitmap = 5;
  1079.           break;
  1080.         case UFO_TANK:
  1081.           use_tank_bitmap = 13;
  1082.           use_turret_bitmap = 6;
  1083.           break;
  1084.         case SPIDER_TANK:
  1085.           use_tank_bitmap = 14;
  1086.           use_turret_bitmap = 7;
  1087.           break;
  1088.         case BIGFOOT_TANK:
  1089.           use_tank_bitmap = 15;
  1090.           use_turret_bitmap = 8;
  1091.           break;
  1092.         default:
  1093.           use_tank_bitmap = 0;
  1094.           use_turret_bitmap = 0;
  1095.           break;
  1096.  
  1097.     }
  1098.  
  1099.     draw_sprite(dest, global->tank[use_tank_bitmap], xpos, ypos);
  1100.     draw_sprite(dest, global->tankgun[use_turret_bitmap], xpos, ypos - TANKHEIGHT + 5);
  1101.     
  1102.     return TRUE;
  1103.  
  1104.  
  1105. }
  1106.  
  1107.