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 / atanks.cpp < prev    next >
C/C++ Source or Header  |  2011-06-30  |  225KB  |  6,102 lines

  1. /*
  2.  * atanks - obliterate each other with oversize weapons
  3.  * Copyright (C) 2002,2003  Thomas Hudson,Juraj Michalek
  4.  *
  5.  * This program is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU General Public License
  7.  * as published by the Free Software Foundation; either version 2
  8.  * of the License, or (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  * */
  19.  
  20.  
  21. #include <dirent.h>
  22.  
  23. #include "globals.h"
  24. #include "menu.h"
  25. #include "button.h"
  26. #include "team.h"
  27. #include "files.h"
  28. #include "satellite.h"
  29. #include "update.h"
  30. #include "network.h"
  31. #include "land.h"
  32.  
  33. #include "floattext.h"
  34. #include "explosion.h"
  35. #include "beam.h"
  36. #include "missile.h"
  37. #include "decor.h"
  38. #include "teleport.h"
  39. #include "sky.h"
  40. #include "gameloop.h"
  41.  
  42. #ifdef THREADS
  43. #include <pthread.h>
  44. #endif
  45.  
  46. #ifdef NETWORK
  47. #include "client.h"
  48. #endif
  49.  
  50.  
  51. enum cmdTokens
  52. {
  53.   ARGV_NOTHING_EXPECTED,
  54.   ARGV_GFX_DEPTH,
  55.   ARGV_SCREEN_WIDTH,
  56.   ARGV_SCREEN_HEIGHT,
  57.   ARGV_DATA_DIR,
  58.   ARGV_CONFIG_DIR
  59. };
  60. #define SWITCH_HELP "-h"
  61. #define SWITCH_FULL_SCREEN "-fs"
  62. #define SWITCH_WINDOWED "--windowed"
  63. #define SWITCH_NOSOUND "--nosound"
  64. #define SWITCH_DATADIR "--datadir"
  65. #define SWITCH_CONFIGDIR "-c"
  66. #define SWITCH_NO_CONFIG "--noconfig"
  67.  
  68.  
  69. int screen_mode = GFX_AUTODETECT_WINDOWED;
  70.  
  71. // BITMAP *create_gradient_strip (const gradient *gradient, int length);
  72. // int draw_circlesBG (GLOBALDATA *global, BITMAP *dest, int x, int y, int width, int height, bool image);
  73.  
  74. using namespace std;
  75.  
  76. void fpsadd()
  77. {
  78.   fps = frames;
  79.   frames = 0;
  80. }
  81.  
  82. void clockadd()
  83. {
  84.   cclock++;
  85. }
  86. END_OF_FUNCTION(clockadd)
  87.  
  88.  
  89.  
  90.  
  91. /*****************************************************************************
  92. drawMenuBackground
  93.  
  94. Draws a 600x400 centered box, fills it with some random lines or circles.
  95. Someday, we should make this more generic; have it take the box dimensions
  96. as an input parameter.
  97. *****************************************************************************/
  98. void drawMenuBackground (GLOBALDATA *global, ENVIRONMENT *env, int itemType, int tOffset, int numItems)
  99. {
  100.   rectfill (env->db, global->halfWidth - 300, global->menuBeginY, // 100,
  101.             global->halfWidth + 300, global->menuEndY, // global->screenHeight - 100,
  102.             makecol (0,79,0));
  103.   rect     (env->db, global->halfWidth - 300, global->menuBeginY, // 100,
  104.             global->halfWidth + 300, global->menuEndY, // global->screenHeight - 100,
  105.             makecol (128,255,128));
  106.  
  107.   drawing_mode (DRAW_MODE_TRANS, NULL, 0, 0);
  108.   env->current_drawing_mode = DRAW_MODE_TRANS;
  109.   set_trans_blender (0, 0, 0, 15);
  110.   for (int tCount = 0; tCount < numItems; tCount++)
  111.     {
  112.       int radius, xpos, ypos;
  113.       switch (itemType)
  114.         {
  115.         case BACKGROUND_CIRCLE: // circles
  116.           radius = (int)((perlin1DPoint (1.0, 5, (tOffset * 0.02) + tCount + 423346, 0.5, 8) + 1) / 2 * 40);
  117.           xpos = global->halfWidth + (int)(perlin1DPoint (1.0, 3, (tOffset * 0.02) + tCount + 232662, 0.3, 6) * 250);
  118.           ypos = global->halfHeight + (int)(perlin1DPoint (1.0, 2, (tOffset * 0.02) + tCount + 42397, 0.3, 6) * (global->halfHeight - 100));
  119.           circlefill (env->db, xpos, ypos, radius,
  120.                       makecol (200,255,200));
  121.           break;
  122.         case BACKGROUND_LINE: // Horz lines
  123.           radius = (int)((perlin1DPoint (1.0, 5, (tOffset * 0.02) + tCount + 423346, 0.5, 8) + 1) / 2 * 40);
  124.           xpos = global->halfWidth + (int)(perlin1DPoint (1.0, 3, (tOffset * 0.02) + tCount + 232662, 0.3, 6) * 250);
  125.           rectfill (env->db, xpos - radius / 2, 101,
  126.                     xpos + radius / 2, global->screenHeight - 101,
  127.                     makecol (200,255,200));
  128.           break;
  129.         case BACKGROUND_BLANK:
  130.         default:
  131.           break;
  132.         }
  133.  
  134.     }
  135.   solid_mode ();
  136.   env->current_drawing_mode = DRAW_MODE_SOLID;
  137. }
  138.  
  139.  
  140. void initialisePlayers (GLOBALDATA *global)
  141. {
  142.   int z;
  143.  
  144.   for (z = 0; z < global->numPlayers; z++)
  145.     {
  146.       global->players[z]->money = (int)global->startmoney;
  147.       global->players[z]->score = 0;
  148.       // global->players[z]->initialise ();
  149.       // global->players[z]->type_saved = global->players[z]->type;
  150.       if (((int)global->players[z]->type != HUMAN_PLAYER) &&
  151.           (global->players[z]->preftype == PERPLAY_PREF))
  152.         {
  153.           global->players[z]->generatePreferences();
  154.         }
  155.       global->players[z]->initialise();
  156.       global->players[z]->type_saved = global->players[z]->type;
  157.     }
  158. }
  159.  
  160.  
  161.  
  162. void wait_for_input()
  163. {
  164.   do
  165.     {
  166.       LINUX_SLEEP;
  167.     }
  168.   while ((!keypressed()) && (!mouse_b));
  169.  
  170.   flush_inputs();
  171.  
  172. }
  173.  
  174. int pickColor (int left, int top, int width, int height, int x, int y)
  175. {
  176.   int r, g, b;
  177.   double value, saturation;
  178.   double hue = ((double)(x - left) / width) * 360;
  179.  
  180.   double hPos = (double)(y - top) / height;
  181.   if (hPos > 0.5)
  182.     {
  183.       value = 1.0 - ((hPos - 0.5) * 2);
  184.       saturation = 1.0;
  185.     }
  186.   else
  187.     {
  188.       value = 1.0;
  189.       saturation = hPos * 2;
  190.     }
  191.  
  192.   hsv_to_rgb (hue, saturation, value, &r, &g, &b);
  193.  
  194.   return (makecol (r, g, b));
  195. }
  196.  
  197. void colorBar (ENVIRONMENT *env, int left, int top, int width, int height)
  198. {
  199.   int right = left + width;
  200.   int bottom = top + height;
  201.  
  202.   for (int x = left; x < right; x++)
  203.     {
  204.       for (int y = top; y < bottom; y++)
  205.         {
  206.           putpixel (env->db, x, y, pickColor (left, top, width, height, x, y));
  207.         }
  208.     }
  209. }
  210.  
  211. int textEntryBox (GLOBALDATA *global, ENVIRONMENT *env, int modify, int x, int y, char *text, unsigned int textLength)
  212. {
  213.   int ke = 0;
  214.   int fontWidth = text_length (font, (char *)"Z");
  215.   int fontHeight = text_height (font);
  216.   int leftX = x - (fontWidth * textLength / 2);
  217.   int rightX = x + (fontWidth * textLength / 2);
  218.   int boxWidth = fontWidth * textLength;
  219. //  char tempText[textLength + 1];
  220.   char * tempText;
  221.   int flashCount = 0;
  222.   int lx = mouse_x, ly = mouse_y;
  223.  
  224.   tempText = (char *)calloc(textLength + 1, sizeof(char));
  225.  
  226.   if (!tempText)
  227.     {
  228.       // Die hard!
  229.       cerr << "ERROR: Unable to allocate " << (textLength + 1) << " bytes in textEntryBox() !!!" << endl;
  230.       // exit (1);
  231.     }
  232.  
  233.   if (! text) text = (char *)"";
  234.   rectfill (env->db, leftX, y - 2, rightX, y + fontHeight + 2, WHITE);
  235.   rect (env->db, leftX, y - 2, rightX, y + fontHeight + 2, BLACK);
  236.   if (!modify)
  237.     {
  238.       textout_centre_ex (env->db, font, text, x, y, BLACK, -1);
  239.     }
  240.   env->make_update (leftX - 2, y - 4, fontWidth * textLength + 4, fontHeight + 6);
  241.   env->do_updates ();
  242.  
  243.   if (!modify)
  244.     {
  245.       return (boxWidth);
  246.     }
  247.   strncpy (tempText, text, textLength + 1);
  248.  
  249.   while (((ke >> 8) != KEY_ENTER && (ke >> 8) != KEY_ESC && (ke >> 8) != KEY_ENTER_PAD)
  250.          || strlen (tempText) < 1)
  251.     {
  252.       int tWidth = text_length (font, tempText);
  253.  
  254.       LINUX_SLEEP;
  255.  
  256.       rectfill (env->db, leftX, y - 2, rightX, y + fontHeight + 2, WHITE);
  257.       rect (env->db, leftX, y - 2, rightX, y + fontHeight + 2, BLACK);
  258.       //rectfill (screen, x - (tWidth / 2), y, x + (tWidth / 2) + 10, y + text_height (font), (flashCount < 5)?WHITE:BLACK);
  259.       textout_centre_ex (env->db, font, tempText, x, y, BLACK, -1);
  260.       rectfill (env->db, x + (tWidth / 2) + 2, y, x + (tWidth / 2) + 10, y + text_height (font), (flashCount < 25)?WHITE:BLACK);
  261.       env->make_update (leftX - 2, y - 4, fontWidth * textLength + 4, fontHeight + 6);
  262.       env->make_update (mouse_x, mouse_y, ((BITMAP *) (global->misc[0]))->w, ((BITMAP *) (global->misc[0]))->h);
  263.       env->make_update (lx, ly, ((BITMAP *) (global->misc[0]))->w, ((BITMAP *) (global->misc[0]))->h);
  264.       lx = mouse_x;
  265.       ly = mouse_y;
  266.       if (! global->os_mouse) show_mouse (NULL);
  267.  
  268.       if (keypressed ())
  269.         {
  270.           ke = readkey ();
  271.         }
  272.       else
  273.         {
  274.           ke = 0;
  275.         }
  276.  
  277.       if ((ke >> 8) == KEY_BACKSPACE)
  278.         {
  279.           tempText[strlen (tempText) - 1] = 0;
  280.           rectfill (screen, x - (tWidth / 2), y, x + (tWidth / 2) + 10, y + text_height (font), WHITE);
  281.           env->make_update (x - (tWidth / 2) - 2, y - 2, tWidth + 14, text_height (font) + 4);
  282.         }
  283.       else if ((ke & 0xff) >= 32 && strlen (tempText) < textLength)
  284.         {
  285.           tempText[strlen (tempText)] = ke & 0xff;
  286.           tempText[strlen (tempText) + 1] = 0;
  287.           //textprintf (screen, font, x + text_length (font, tempText), y, WHITE, (char *)"%c", ke & 0xff);
  288.         }
  289.       else
  290.         env->do_updates ();
  291.       if (! global->os_mouse) show_mouse (screen);
  292.       rest (1);
  293.       flashCount++;
  294.       flashCount = flashCount % 50;
  295.     }
  296.   if ((ke >> 8) != KEY_ESC)
  297.     strncpy (text, tempText, textLength);
  298.  
  299.   flush_inputs ();
  300.  
  301.   free(tempText);
  302.  
  303.   return (boxWidth);
  304. }
  305.  
  306.  
  307. void credits (GLOBALDATA *global, ENVIRONMENT *env)
  308. {
  309.   char dataDir[2048];
  310.   TEXTBLOCK *my_text;
  311.  
  312.   sprintf (dataDir, "%s/credits.txt", global->dataDir);
  313.   my_text = new TEXTBLOCK(dataDir);
  314.   scrollTextList (global, env, my_text  );
  315.   delete my_text;
  316. }
  317.  
  318.  
  319. /*
  320.  * Save all players to a text file.
  321. */
  322. int savePlayers_Text(GLOBALDATA *global, FILE *my_file)
  323. {
  324.    int count = 0;
  325.   
  326.    while (count < global->numPermanentPlayers)
  327.    {
  328.       global->allPlayers[count]->saveToFile_Text(my_file);
  329.       count++;
  330.    } 
  331.    return TRUE;
  332. }
  333.  
  334.  
  335.  
  336.  
  337.  
  338. int loadPlayers_Text (GLOBALDATA *global, ENVIRONMENT *env, FILE *file)
  339. {
  340.   int count, max;
  341.   int status = TRUE;
  342.   PLAYER *new_player;
  343.  
  344.   max = global->numPermanentPlayers;
  345.   global->allPlayers = (PLAYER **) malloc (sizeof(PLAYER*) * max);
  346.   if (! global->allPlayers)
  347.     {
  348.       perror("atanks.cc: Failed to allocate memory for allPlayers in loadPlayers_Text");
  349.       return FALSE;
  350.     }
  351.  
  352.   count = 0;
  353.   while (status)
  354.     {
  355.       // global->allPlayers[count] = new PLAYER(global, env, file, true);
  356.       new_player = new PLAYER(global, env);
  357.       if (! new_player)
  358.         {
  359.           perror( (char *)"atanks.cc: Failed to allocate memory for players in loadPlayers_Text");
  360.           return FALSE;
  361.         }
  362.       status = new_player->loadFromFile_Text(file);
  363.       if (status)
  364.         {
  365.           global->allPlayers[count] = new_player;
  366.           count++;
  367.           if (count == max)
  368.             {
  369.               max += 5;
  370.               global->allPlayers = (PLAYER**) realloc(global->allPlayers, sizeof(PLAYER *) * max);
  371.             }
  372.         }
  373.       else
  374.         free(new_player);
  375.     }     // end of while status
  376.  
  377.   global->numPermanentPlayers = count;
  378.   return TRUE;
  379. }
  380.  
  381.  
  382. void newgame (GLOBALDATA *global, ENVIRONMENT *env)
  383. {
  384.   int objCount;
  385.   TANK *tank;
  386.  
  387.   env->initialise ();
  388.   global->initialise ();
  389.  
  390.   // if a game should be loaded, try it or deny loading of the game
  391.   if ( (global->load_game) && (!Load_Game(global, env)) )
  392.     global->load_game = false;
  393.  
  394.   // Now check back whether to load a game
  395.   if (!global->load_game)
  396.     initialisePlayers (global);
  397.  
  398.   // There must not be any tanks!
  399.   for (objCount = 0; (tank = (TANK*)env->getNextOfClass (TANK_CLASS, &objCount)) && tank; objCount++)
  400.     {
  401.       tank->player = NULL; // To avoid violent death!
  402.       delete(tank);
  403.     }
  404.  
  405.   // This is always true here, as a newly started game is handled like a loaded one:
  406.   global->bIsGameLoaded = true;
  407. }
  408.  
  409.  
  410.  
  411. // This function draws the background for most screens
  412. int draw_circlesBG (GLOBALDATA *global, BITMAP *dest, int x, int y, int width, int height, bool image)
  413. {
  414.   // int largestCircle, circleCount;
  415.   // BITMAP *drawTo = dest;
  416.  
  417.   // try to prevent crashes on 64-bit systems by avoiding this function
  418.   if (! global->draw_background)
  419.   {
  420.       rectfill(dest, 0, 0, global->screenWidth - 1, global->screenHeight - 1, BLACK);
  421.       return 0;
  422.   }
  423.  
  424.   if ( (image) && (global->misc[17]) )
  425.      stretch_blit(global->misc[17], dest, 0, 0, global->misc[17]->w, global->misc[17]->h, 0, 0,
  426.                   global->screenWidth, global->screenHeight);
  427.   else
  428.      rectfill(dest, 0, 0, global->screenWidth - 1, global->screenHeight - 1, DARK_GREEN);
  429.  
  430.   /*
  431.   if (global->cacheCirclesBG)
  432.     {
  433.       if (!global->gfxData.circlesBG)
  434.         {
  435.           global->gfxData.circlesBG = create_bitmap (width, height);
  436.           drawTo = global->gfxData.circlesBG;
  437.         }
  438.       else
  439.         {
  440.           blit (global->gfxData.circlesBG, dest, 0, 0, 0, 0, width, height);
  441.           return (0);
  442.         }
  443.     }
  444.   else
  445.     {
  446.       drawTo = dest;
  447.     }
  448.  
  449.   largestCircle = (int)(global->halfWidth * (4.0/3.0));
  450.   if (largestCircle > 1000) largestCircle = 1000;    // perhaps avoid crash on large screens
  451.   global->gfxData.circle_gradient_strip = create_gradient_strip (circles_gradient, largestCircle);
  452.   for (circleCount = largestCircle; circleCount > 0; circleCount -= 2)
  453.     circlefill (drawTo, width/2, height/2, circleCount, getpixel (global->gfxData.circle_gradient_strip, 0, largestCircle - circleCount));
  454.  
  455.   if (global->cacheCirclesBG)
  456.     draw_circlesBG (global, dest, x, y, width, height);
  457.   */
  458.   return (0);
  459. }
  460.  
  461. ENVIRONMENT *init_game_settings (GLOBALDATA *global)
  462. {
  463.   int count, x, y, z;
  464.   ENVIRONMENT *env;
  465.   double expSize, disperseSize;
  466.   // char dataDir[2048];
  467.   int colour_theme = (int) global->colour_theme;
  468.   int status;
  469.  
  470.   #ifdef WIN32
  471.   if (global->full_screen == FULL_SCREEN_TRUE)
  472.       global->os_mouse = FALSE;
  473.   #endif
  474.  
  475.   status = allegro_init ();
  476.   if (status)
  477.   {
  478.     printf("Unable to start Allegro.\n");
  479.     return NULL;
  480.   }
  481.  
  482.   set_window_title( "Atomic Tanks");
  483.   // before we get started, make sure if we are using
  484.   // full screen mode to ignore width and height settings
  485.   if (global->full_screen == FULL_SCREEN_TRUE)
  486.   {
  487.       status = get_desktop_resolution(& (global->screenWidth), & (global->screenHeight) );
  488.       if (status < 0)
  489.       {
  490.           global->screenWidth = 800;
  491.           global->screenHeight = 600;
  492.       }
  493.       screen_mode = GFX_AUTODETECT_FULLSCREEN;
  494.   }
  495.   // check for X pressed on the window bar
  496.   LOCK_FUNCTION(close_button_handler);
  497.   set_close_button_callback(close_button_handler);
  498.  
  499.   if (! global->colourDepth)
  500.     global->colourDepth = desktop_color_depth();
  501.  
  502.   if ( (global->colourDepth != 16) && (global->colourDepth != 32) )
  503.     global->colourDepth = 16;
  504.  
  505.   set_color_depth (global->colourDepth);
  506.   if (global->width_override)
  507.   {
  508.     global->screenWidth = global->width_override;
  509.     global->halfWidth = global->screenWidth / 2;
  510.   }
  511.   if (global->height_override)
  512.   {
  513.     global->screenHeight = global->height_override;
  514.     global->halfHeight = global->screenHeight / 2;
  515.   }
  516.   if (set_gfx_mode (screen_mode, global->screenWidth, global->screenHeight, 0, 0) < 0)
  517.     {
  518.       perror( "set_gfx_mode");
  519.       // exit (1);
  520.       status = set_gfx_mode(screen_mode, 800, 600, 0, 0);
  521.       if ( status < 0 ) exit(1);
  522.       global->screenWidth = 800;
  523.       global->screenHeight = 600;
  524.       global->halfWidth = 400;
  525.       global->halfHeight = 300;
  526.     }
  527.  
  528. #ifdef WIN32
  529.   if (global->full_screen == FULL_SCREEN_TRUE)
  530.     set_display_switch_mode(SWITCH_BACKAMNESIA);
  531.   else
  532.     set_display_switch_mode(SWITCH_BACKGROUND);
  533. #endif
  534.  
  535.   if (install_keyboard () < 0)
  536.     {
  537.       perror ( "install_keyboard failed");
  538.       exit (1);
  539.     }
  540.   if (install_timer () < 0)
  541.     {
  542.       perror ( "install_timer failed");
  543.       exit (1);
  544.     }
  545.   if (install_mouse () < 0)
  546.     {
  547.       perror ( "install_mouse failed");
  548.       // exit (1);
  549.     }
  550.  
  551.   // check to see if we want sound
  552.   if (global->sound > 0.0)
  553.   {
  554.     /*
  555.       // don't stop program if no sound since the game can be played without
  556.       if (install_sound (DIGI_AUTODETECT, MIDI_NONE, NULL) < 0)
  557.         fprintf (stderr, "install_sound: %s", allegro_error);
  558.     }
  559.     */
  560.         int sound_type = DIGI_AUTODETECT;
  561.         #ifdef LINUX
  562.         switch ( (int) global->sound_driver )
  563.         {
  564.         case SOUND_OSS: sound_type = DIGI_OSS; break;
  565.         case SOUND_ESD: sound_type = DIGI_ESD; break;
  566.         case SOUND_ARTS: sound_type = DIGI_ARTS; break;
  567.         case SOUND_ALSA: sound_type = DIGI_ALSA; break;
  568.         case SOUND_JACK: sound_type = DIGI_JACK; break;
  569.         default: sound_type = DIGI_AUTODETECT; break;
  570.         }
  571.     #endif
  572.         #ifdef UBUNTU
  573.         if (sound_type == DIGI_AUTODETECT)
  574.             sound_type = DIGI_OSS;
  575.         #endif
  576.         if (detect_digi_driver(sound_type)) 
  577.         {
  578.                if (install_sound (sound_type, MIDI_NONE, NULL) < 0)
  579.                {
  580.                fprintf (stderr, "install_sound: failed initialising sound\n");
  581.                    fprintf (stderr, "Please try selecting a different Sound Driver from the Options menu.\n");
  582.                }
  583.     } 
  584.         else 
  585.         fprintf (stderr, "detect_digi_driver detected no sound device\n");
  586.   }      // end of we want sound
  587.  
  588.   LOCK_VARIABLE(cclock);
  589.   LOCK_FUNCTION(clockadd);
  590.   // if (install_int_ex (clockadd, BPS_TO_TIMER (FRAMES_PER_SECOND)) < 0) {
  591.   if (install_int_ex (clockadd, BPS_TO_TIMER(global->frames_per_second)) < 0)
  592.     {
  593.       perror ( "install_int_ex");
  594.       exit (1);
  595.     }
  596.   if (install_int (fpsadd, 1000) < 0)
  597.     {
  598.       perror ( "install_int");
  599.       exit (1);
  600.     }
  601.  
  602.   srand (time (0));
  603.   WHITE = makecol (255, 255, 255);
  604.   BLACK = makecol (0, 0, 0);
  605.   PINK = makecol (255, 0, 255);
  606.   RED = makecol (255, 0, 0);
  607.   GREEN = makecol (0, 255, 0);
  608.   DARK_GREEN = makecol(0, 80, 0);
  609.   BLUE = makecol (0, 0, 255);
  610.   PURPLE = makecol (200, 0, 200);
  611.   YELLOW = makecol (255, 255, 0);
  612.  
  613.   global->Load_Bitmaps();
  614.   global->Load_Fonts();
  615.  
  616.   if (! global->os_mouse) show_mouse(NULL);
  617.   blit ((BITMAP *) global->title[0], screen, 0, 0, global->halfWidth - 320, global->halfHeight - 240, 640, 480);
  618.   if (! global->os_mouse) show_mouse (screen);
  619.  
  620.   global->Load_Sounds();
  621.  
  622.   for (count = 0; count < ALL_LANDS; count++)
  623.     global->gfxData.land_gradient_strips[count] = NULL;
  624.   for (count = 0; count < ALL_SKIES; count++)
  625.     global->gfxData.sky_gradient_strips[count] = NULL;
  626.  
  627.   global->gfxData.explosion_gradient_strip = create_gradient_strip (explosion_gradients[colour_theme], 200);
  628.   // for (count = 0; count < 2; count++)
  629.   //  global->gfxData.explosion_gradient_strips[count] = create_gradient_strip (explosion_gradients[count], 200);
  630.  
  631.   expSize = 0;
  632.   disperseSize = 0;
  633.   for (count = 0; count < EXPLOSIONFRAMES; count++)
  634.     {
  635.       global->gfxData.explosions[count] = create_bitmap (214, 214);
  636.       if (count == 0)
  637.         {
  638.           expSize = 25;
  639.           disperseSize = 0;
  640.         }
  641.       else if (count < EXPLODEFRAMES - 4)
  642.         expSize += (107 - expSize) / 3;
  643.       else if (count < EXPLODEFRAMES)
  644.         expSize--;
  645.       else if (count == EXPLODEFRAMES)
  646.         disperseSize = 25;
  647.       else
  648.         disperseSize += (107 - disperseSize) / 2;
  649.  
  650.       clear_to_color (global->gfxData.explosions[count], PINK);
  651.       for (y = (int)expSize; y > disperseSize; y--)
  652.         {
  653.           double value;
  654.           value = pow ((double)y / expSize, count / 4 + 1);
  655.           circlefill (global->gfxData.explosions[count], 107, 107, y, getpixel (global->gfxData.explosion_gradient_strip, 0, (int)(value * 200)));
  656.         }
  657.       if (disperseSize)
  658.         circlefill (global->gfxData.explosions[count], 107, 107, (int)disperseSize, PINK);
  659.     }
  660.  
  661.   expSize = 0;
  662.   disperseSize = 0;
  663.   for (count = 0; count < EXPLOSIONFRAMES; count++)
  664.     {
  665.       global->gfxData.flameFront[count] = create_bitmap (600, 30);
  666.       if (count == 0)
  667.         {
  668.           expSize = 10;
  669.           disperseSize = 0;
  670.         }
  671.       else if (count < EXPLODEFRAMES - 4)
  672.         expSize += (300 - expSize) / 3;
  673.       else if (count < EXPLODEFRAMES)
  674.         expSize--;
  675.       else if (count == EXPLODEFRAMES)
  676.         disperseSize = 10;
  677.       else
  678.         disperseSize += (300 - disperseSize) / 2;
  679.  
  680.       clear_to_color (global->gfxData.flameFront[count], PINK);
  681.       for (y = (int)expSize; y > disperseSize; y--)
  682.         {
  683.           double value;
  684.           value = pow ((double)y / expSize, count / 4 + 1);
  685.           ellipsefill (global->gfxData.flameFront[count], 300, 15, y, y / 20, getpixel (global->gfxData.explosion_gradient_strip, 0, (int)(value * 200)));
  686.         }
  687.       if (disperseSize)
  688.         ellipsefill (global->gfxData.flameFront[count], 300, 15, (int)disperseSize, (int)disperseSize / 16, PINK);
  689.     }
  690.  
  691.   global->gfxData.topbar = create_bitmap (global->screenWidth, MENUHEIGHT);
  692.   global->gfxData.topbar_gradient_strip = create_gradient_strip (topbar_gradient, 100);
  693.   if (!global->ditherGradients)
  694.     {
  695.       for (count = 0; count < MENUHEIGHT; count++)
  696.         {
  697.           float adjCount = (100.0 / MENUHEIGHT) * count;
  698.           line (global->gfxData.topbar, 0, count, global->screenWidth - 1, count, getpixel (global->gfxData.topbar_gradient_strip, 0, (int)adjCount));
  699.         }
  700.     }
  701.   else
  702.     {
  703.       for (x = 0; x < global->screenWidth; x++)
  704.         {
  705.           for (y = 0; y < MENUHEIGHT; y++)
  706.             {
  707.               float adjY = (100.0 / MENUHEIGHT) * y;
  708.               int offset;
  709.               if ((adjY < 2) || (adjY > 100 - 2))
  710.                 offset = 0;
  711.               else
  712.                 offset = rand () % 4 - 2;
  713.               putpixel (global->gfxData.topbar, x, y, getpixel (global->gfxData.topbar_gradient_strip, 0, (int)adjY + offset));
  714.             }
  715.         }
  716.     }
  717.  
  718.   global->gfxData.stuff_bar[0] = create_bitmap (STUFF_BAR_WIDTH, STUFF_BAR_HEIGHT);
  719.   global->gfxData.stuff_bar[1] = create_bitmap (STUFF_BAR_WIDTH, STUFF_BAR_HEIGHT);
  720.   global->gfxData.stuff_icon_base = create_bitmap (STUFF_BAR_WIDTH/10, STUFF_BAR_HEIGHT);
  721.   clear_to_color (global->gfxData.stuff_bar[0], PINK);
  722.   clear_to_color (global->gfxData.stuff_bar[1], PINK);
  723.   clear_to_color (global->gfxData.stuff_icon_base, PINK);
  724.   global->gfxData.stuff_bar_gradient_strip = create_gradient_strip (stuff_bar_gradient, STUFF_BAR_WIDTH);
  725.   for (x = 0; x < STUFF_BAR_WIDTH; x++)
  726.     {
  727.       for (y = 0; y < STUFF_BAR_HEIGHT; y++)
  728.         {
  729.           double sides_dist = 0.1, circle_dist;
  730.           circle_dist = vector_length_f ((float)x-(STUFF_BAR_WIDTH - 75), (float)y - (STUFF_BAR_HEIGHT/2 - 2), 0);
  731.           if (circle_dist < 75)
  732.             circle_dist = 1 - (circle_dist / 75.0);
  733.           else
  734.             circle_dist = 0;
  735.  
  736.           if (x < (STUFF_BAR_HEIGHT/2 - 2))
  737.             sides_dist -= 0.1 - ((float)x / 150.0);
  738.           else if (x > STUFF_BAR_WIDTH - (STUFF_BAR_HEIGHT/2 - 2))
  739.             sides_dist -= ((float)(x - (STUFF_BAR_WIDTH - (STUFF_BAR_HEIGHT/2 - 2))) / 150.0);
  740.  
  741.           if (y < STUFF_BAR_HEIGHT/2 - 2)
  742.             sides_dist -= 0.1 - ((float)(y) / 150.0);
  743.           else
  744.             sides_dist -= ((float)(y - (STUFF_BAR_HEIGHT/2 - 2)) / 150.0);
  745.  
  746.           sides_dist -= circle_dist * circle_dist;
  747.           if (sides_dist > ((double)x / 1000.0))
  748.             sides_dist = ((double)x / 1000.0);
  749.           if (sides_dist < 0)
  750.             sides_dist = 0;
  751.           if (circle_dist > 1)
  752.             circle_dist = 1;
  753.  
  754.           if (x < STUFF_BAR_WIDTH/10)
  755.             putpixel (global->gfxData.stuff_icon_base, x, y, getpixel (global->gfxData.stuff_bar_gradient_strip, 0, (int)((sides_dist + circle_dist) * (STUFF_BAR_WIDTH-1))));
  756.  
  757.           if (y < STUFF_BAR_HEIGHT - 5)
  758.             {
  759.               putpixel (global->gfxData.stuff_bar[0], x, y, getpixel (global->gfxData.stuff_bar_gradient_strip, 0, (int)((sides_dist + circle_dist) * (STUFF_BAR_WIDTH-1))));
  760.               putpixel (global->gfxData.stuff_bar[1], x, y, getpixel (global->gfxData.stuff_bar_gradient_strip, 0, (int)((sides_dist + circle_dist + 0.05) * (STUFF_BAR_WIDTH-1))));
  761.             }
  762.         }
  763.     }
  764.  
  765.   if (! global->os_mouse )
  766.     {
  767.       set_mouse_sprite ((BITMAP *) global->misc[0]);
  768.       set_mouse_sprite_focus (0, 0);
  769.     }
  770.  
  771.   global->window.x = 0;
  772.   global->window.y = 0;
  773.   global->window.w = 0;
  774.   global->window.h = 0;
  775.   for (z = 0; z < MAXUPDATES; z++)
  776.     {
  777.       global->updates[z].x = 0;
  778.       global->updates[z].y = 0;
  779.       global->updates[z].w = 0;
  780.       global->updates[z].h = 0;
  781.     }
  782.  
  783.   env = new ENVIRONMENT (global);
  784.   if (!env)
  785.     {
  786.       perror ( "atanks.cc: Allocating env in init_game_settings");
  787.       exit (1);
  788.     }
  789.  
  790.   clear_to_color (env->db, BLACK);
  791.   global->env = env;
  792.  
  793.   return (env);
  794. }
  795.  
  796. int options (GLOBALDATA *global, ENVIRONMENT *env, MENUDESC *menu);
  797.  
  798. int createNewPlayer (GLOBALDATA *global, ENVIRONMENT *env)
  799. {
  800.   PLAYER *newPlayer = global->createNewPlayer (env);
  801.   if (!newPlayer)
  802.     {
  803.       perror ( "atanks.cc: Failed allocating memory in createNewPlayer");
  804.       // exit (1);
  805.     }
  806.   options (global, env, (MENUDESC*)newPlayer->menudesc);
  807.   return (-1);
  808. }
  809.  
  810. int destroyPlayer (GLOBALDATA *global, ENVIRONMENT *env, void *data)
  811. {
  812.   int optionsRetVal;
  813.   char sureMessage[200];
  814.   PLAYER *tempPlayer = (PLAYER*)data;
  815.   MENUDESC areYouSureMenu = { "Are You Sure?", 0, NULL, TRUE, TRUE};
  816.  
  817.   sprintf (sureMessage, "This player (%s) will be permanently deleted", tempPlayer->getName ());
  818.   errorMessage = sureMessage;
  819.   errorX = global->halfWidth - text_length (font, errorMessage) / 2;
  820.   errorY = 170;
  821.   optionsRetVal = options (global, env, &areYouSureMenu);
  822.   if (optionsRetVal >> 8 != KEY_ESC)
  823.     {
  824.       global->destroyPlayer (tempPlayer);
  825.       return (-2);
  826.     }
  827.   return (KEY_SPACE << 8);
  828. }
  829.  
  830. int displayPlayerName (ENVIRONMENT *env, int x, int y, void *data)
  831. {
  832.   PLAYER *player = (PLAYER*)data;
  833.   char *name = player->getName ();
  834.   int textHeight = text_height (font);
  835.   int textLength = text_length (font, name);
  836.  
  837.   if ((int)player->type == HUMAN_PLAYER)
  838.     {
  839.       int radius = 5;
  840.       circlefill (env->db, x - textLength - textHeight / 2 - 2,
  841.                   y + textHeight / 2,
  842.                   radius, makecol (200, 100, 255));
  843.       circle (env->db, x - textLength - textHeight / 2 - 2,
  844.               y + textHeight / 2,
  845.               radius, BLACK);
  846.     }
  847.   else
  848.     {
  849.       rectfill (env->db,
  850.                 x - textLength - 2 - ((int)player->type * 3),
  851.                 y + textHeight - 10,
  852.                 x - textLength - 2,
  853.                 y + textHeight - 2,
  854.                 makecol (100, 255, 100));
  855.       rect (env->db,
  856.             x - textLength - 2 - ((int)player->type * 3),
  857.             y + textHeight - 10,
  858.             x - textLength - 2,
  859.             y + textHeight - 2,
  860.             BLACK);
  861.       for (int lineCount = 1; lineCount < player->type; lineCount++)
  862.         {
  863.           vline (env->db,
  864.                  x - textLength - 2 - (lineCount * 3),
  865.                  y + textHeight - 2,
  866.                  y + textHeight - 10,
  867.                  BLACK);
  868.         }
  869.     }
  870.   textout_ex (env->db, font, name, x - textLength, y, player->color, -1);
  871.  
  872.   return (0);
  873. }
  874.  
  875.  
  876. int options (GLOBALDATA *global, ENVIRONMENT *env, MENUDESC *menu)
  877. {
  878.   MENUENTRY *opts;
  879.   BUTTON *reset_button = NULL;
  880.   int selected_index = 0, my_key = 0;
  881.   int numEntries;
  882.   const char *title;
  883.   int ke, z;
  884.   int mouseLeftPressed;
  885.   char *reset_text, *back_text;
  886. #include "menucontent.h"
  887.  
  888.      if (global->language == LANGUAGE_GERMAN)
  889.      {
  890.            reset_text = "Alles zurucksetzen";
  891.            back_text = "Zuruck";
  892.      }
  893.      else
  894.      {
  895.            reset_text = "Rest All";
  896.            back_text = "Back";
  897.      }
  898.  
  899.   if (!menu)
  900.   {
  901.     menu = &mainMenu;
  902.     reset_button = new BUTTON(global, env, global->halfWidth - 5 - text_length (font, menu->title), global->menuBeginY + 70, // 170, 
  903.                     reset_text, (BITMAP *) global->misc[7], (BITMAP *) global->misc[7], 
  904.                     (BITMAP *) global->misc[8]);
  905.   }
  906.  
  907.   opts = menu->entries;
  908.   numEntries = menu->numEntries;
  909.   title = menu->title;
  910.  
  911.   char name_buff[64];
  912.   char format_buff[64];
  913.   int done, lb;
  914.   int stop = 0;
  915.  
  916.   int *updateoption;
  917.  
  918.   updateoption = (int *)calloc(numEntries, sizeof(int));
  919.   if (!updateoption)
  920.     {
  921.       // Die hard!
  922.       cerr << "ERROR: Unable to allocate " << numEntries << " bytes in options() !!!" << endl;
  923.       // exit (1);
  924.     }
  925.  
  926.   BUTTON *but_okay = NULL, *but_quit = NULL;
  927.   if (menu->okayButton)
  928.     {
  929.       int xpos = global->halfWidth - 80;
  930.       if (menu->quitButton)
  931.         xpos -= 80;
  932.       // but_okay = new BUTTON (global, env, xpos, global->halfHeight + 160, "Okay", (BITMAP*)global->misc[7], (BITMAP*)global->misc[7], (BITMAP*)global->misc[8]);
  933.       but_okay = new BUTTON (global, env, xpos, global->menuBeginY + 360 , "Okay", (BITMAP*)global->misc[7], (BITMAP*)global->misc[7], (BITMAP*)global->misc[8]);
  934.       if (!but_okay)
  935.         {
  936.           perror ( "atanks.cc: Failed allocating memory for but_okay in options");
  937.           // exit (1);
  938.         }
  939.     }
  940.   if (menu->quitButton)
  941.     {
  942.       int xpos = global->halfWidth - 80;
  943.       if (menu->okayButton)
  944.         xpos += 80;
  945.       but_quit = new BUTTON (global, env, xpos, global->menuBeginY + 360, back_text, (BITMAP*)global->misc[7], (BITMAP*)global->misc[7], (BITMAP*)global->misc[8]);
  946.       // but_quit = new BUTTON (global, env, xpos, global->halfHeight + 160, back_text, (BITMAP*)global->misc[7], (BITMAP*)global->misc[7], (BITMAP*)global->misc[8]);
  947.       if (!but_quit)
  948.         {
  949.           perror ( "atanks.cc: Failed allocating memory for but_quit in options");
  950.           // exit (1);
  951.         }
  952.     }
  953.  
  954.   mouseLeftPressed = done = lb = env->mouseclock = cclock = 0;
  955.   fi = 1;
  956.  
  957.   for (z = 0; z < numEntries; z++)
  958.     {
  959.       updateoption[z] = 1;
  960.     }
  961.  
  962.   flush_inputs ();
  963.  
  964.   do
  965.     {
  966.       LINUX_SLEEP;
  967.       while (cclock > 0)
  968.         {
  969.           cclock--;
  970.           my_key = 0;
  971.           if ( keypressed() )
  972.           {
  973.              my_key = readkey();
  974.              my_key = my_key >> 8;
  975.              if (my_key == KEY_DOWN)
  976.              {
  977.                 selected_index++;
  978.                 if (selected_index >= numEntries)
  979.                    selected_index = 0;
  980.                 my_key = 0;
  981.              }
  982.              else if (my_key == KEY_UP)
  983.              {
  984.                  selected_index--;
  985.                  if (selected_index < 0)
  986.                    selected_index = numEntries - 1;
  987.                  my_key = 0;
  988.              }
  989.              else if (my_key == KEY_ENTER_PAD)
  990.                   my_key = KEY_ENTER;
  991.  
  992.              for (z = 0; z < numEntries; z++)
  993.                 updateoption[z] = TRUE;
  994.              fi = TRUE;
  995.              
  996.           }     // end of a key was pressed
  997.  
  998.           if (!lb && mouse_b & 1)
  999.             {
  1000.               env->mouseclock = 0;
  1001.               mouseLeftPressed = 1;
  1002.             }
  1003.           else
  1004.             {
  1005.               mouseLeftPressed = 0;
  1006.             }
  1007.           lb = (mouse_b & 1) ? 1 : 0;
  1008.           if ( ((mouse_b & 1 || mouse_b & 2) && !env->mouseclock) || (my_key) )
  1009.             {
  1010.               for (z = 0; z < numEntries; z++)
  1011.                 {
  1012.                   int midX = opts[z].x;
  1013.                   int midY = opts[z].y;
  1014.                   if (opts[z].type == OPTION_MENUTYPE)
  1015.                     {
  1016.                       sprintf (name_buff, "-> %s", opts[z].name);
  1017.                       if ( ((!opts[z].viewonly) && mouse_x > midX - text_length (font, name_buff) && mouse_x < midX && mouse_y >= midY && mouse_y < midY + 10) || 
  1018.                          ( (my_key == KEY_SPACE) && (selected_index == z)) )
  1019.                         {
  1020.                           int optsRetVal = options (global, env, (MENUDESC*)opts[z].value);
  1021.                           if (optsRetVal < 0)
  1022.                             {
  1023.                               return (optsRetVal + 1);
  1024.                             }
  1025.                           fi = 1;
  1026.                           for (z = 0; z < numEntries; z++)
  1027.                             {
  1028.                               updateoption[z] = 1;
  1029.                             }
  1030.                           my_key = selected_index = 0;
  1031.                         }
  1032.                     }
  1033.                   else if (opts[z].type == OPTION_ACTIONTYPE)
  1034.                     {
  1035.                       sprintf (name_buff, "-> %s", opts[z].name);
  1036.                       if ( ((!opts[z].viewonly) && mouse_x > midX - text_length (font, name_buff) && mouse_x < midX && mouse_y >= midY && mouse_y < midY + 10) ||
  1037.                            ( (my_key == KEY_SPACE) && (selected_index == z) ) )
  1038.                         {
  1039.                           int (*action) (GLOBALDATA*, ENVIRONMENT*, void*)
  1040.                           = (int (*)(GLOBALDATA*, ENVIRONMENT*, void*))opts[z].value;
  1041.                           int actionRetVal = action (global, env, opts[z].data);
  1042.                           if (actionRetVal)
  1043.                             return (actionRetVal);
  1044.                         }
  1045.                     }
  1046.                   else if (opts[z].type == OPTION_TEXTTYPE)
  1047.                     {
  1048.                       int my_text_length;
  1049.                       strcmp(opts[z].name, "Name") ? my_text_length = 11 : my_text_length = NAME_LENGTH;
  1050.                       int boxWidth;
  1051.                       if (! strcmp(opts[z].name, "Server address") )
  1052.                          my_text_length = ADDRESS_LENGTH;
  1053.  
  1054.                       if (my_text_length == NAME_LENGTH)
  1055.                         boxWidth = textEntryBox (global, env, FALSE, midX + 100, midY, (char*)opts[z].value, my_text_length);
  1056.                       else if (my_text_length == ADDRESS_LENGTH)
  1057.                         boxWidth = textEntryBox(global, env, FALSE, midX + 70, midY, (char*) opts[z].value, my_text_length);
  1058.                       else
  1059.                         boxWidth = textEntryBox (global, env, FALSE, midX + 50, midY, (char*)opts[z].value, my_text_length);
  1060.                       if ( ((!opts[z].viewonly) && mouse_x > midX - text_length (font, name_buff) && mouse_x < midX + 50 + boxWidth && mouse_y >= midY && mouse_y < midY + 10) ||
  1061.                            ( (selected_index == z) && (my_key == KEY_SPACE) ) )
  1062.                         {
  1063.                           if (my_text_length == NAME_LENGTH)
  1064.                             textEntryBox (global, env, TRUE, midX + 100, midY, (char*)opts[z].value, my_text_length);
  1065.                           else if (my_text_length == ADDRESS_LENGTH)
  1066.                             textEntryBox(global, env, TRUE, midX + 70, midY, (char *)opts[z].value, my_text_length);
  1067.                           else
  1068.                             textEntryBox (global, env, TRUE, midX + 50, midY, (char*)opts[z].value, my_text_length);
  1069.                           updateoption[z] = 1;
  1070.                         }
  1071.                     }
  1072.                   else if (opts[z].type == OPTION_COLORTYPE)
  1073.                     {
  1074.                       if ((!opts[z].viewonly) && mouse_x > midX && mouse_x < midX + 100 && mouse_y >= midY && mouse_y < midY + 15)
  1075.                         {
  1076.                           *(int*)opts[z].value = pickColor (midX, midY, 100, 15, mouse_x, mouse_y);
  1077.                           updateoption[z] = 1;
  1078.                         }
  1079.                       colorBar (env, midX, midY, 100, 15);
  1080.                       rectfill (env->db, midX + 110, midY, midX + 130, midY + 10, *(int*)opts[z].value);
  1081.                       rect (env->db, midX + 110, midY, midX + 130, midY + 10, BLACK);
  1082.                     }
  1083.                   else if (opts[z].type == OPTION_TOGGLETYPE)
  1084.                     {
  1085.                       int tlen = text_length (font, name_buff);
  1086.                       int thgt = text_height (font);
  1087.                       int temp_counter;
  1088.                       if ( (mouseLeftPressed && (!opts[z].viewonly) && mouse_x > midX - tlen / 2 && mouse_x < midX + tlen / 2 && mouse_y >= midY && mouse_y < midY + thgt) ||
  1089.                          ( (my_key == KEY_SPACE) && (selected_index == z) ) )
  1090.                         {
  1091.                           if (*opts[z].value == 0)
  1092.                             *opts[z].value = 1;
  1093.                           else
  1094.                             *opts[z].value = 0;
  1095.                           mouseLeftPressed = 1;
  1096.                           // updateoption[z] = 1;
  1097.                           // Crude, but hopefulyl useful
  1098.                           for (temp_counter = 0; temp_counter < numEntries; temp_counter++)
  1099.                                updateoption[temp_counter] = 1;
  1100.                         }
  1101.                     }
  1102.                   else
  1103.                     {
  1104.                       if (!opts[z].viewonly)
  1105.                         {
  1106.                           if (mouse_x >= midX + 100 && mouse_x < midX + 110 && mouse_y >= midY && mouse_y < midY + 10)
  1107.                             {
  1108.                               if (mouse_b & 1)
  1109.                                 *opts[z].value -= opts[z].increment;
  1110.                               else if (mouse_b & 2)
  1111.                                 *opts[z].value -= opts[z].increment * 10;
  1112.                               updateoption[z] = 1;
  1113.                             }
  1114.                           if (mouse_x >= midX + 112 && mouse_x < midX + 122 && mouse_y >= midY && mouse_y < midY + 10)
  1115.                             {
  1116.                               if (mouse_b & 1)
  1117.                                 *opts[z].value += opts[z].increment;
  1118.                               else if (mouse_b & 2)
  1119.                                 *opts[z].value += opts[z].increment * 10;
  1120.                               updateoption[z] = 1;
  1121.                             }
  1122.  
  1123.                           if ( (my_key == KEY_RIGHT) && (selected_index == z) )
  1124.                           {
  1125.                               *opts[z].value += opts[z].increment;
  1126.                               updateoption[z] = 1;
  1127.                           }
  1128.                           else if ( (my_key == KEY_LEFT) && (selected_index == z) )
  1129.                           {
  1130.                               *opts[z].value -= opts[z].increment;
  1131.                               updateoption[z] = 1;
  1132.                           }
  1133.  
  1134.                           // This if block is a nasty hack to get the tank
  1135.                           // styles to redraw on the Players menu.
  1136.                           if (updateoption[z])
  1137.                           {
  1138.                               int my_counter;
  1139.                               for (my_counter = 0; my_counter < numEntries; my_counter++)
  1140.                                  updateoption[my_counter] = TRUE;
  1141.                               fi = TRUE;
  1142.                           }
  1143.                           /*if (mouse_x >= midX + 134 && mouse_x < midY + 154 && mouse_y >= midY && mouse_y < midY + 10) {
  1144.                               *opts[z].value = opts[z].defaultv;
  1145.                               updateoption[z] = 1;
  1146.                           }*/
  1147.                           if (*opts[z].value > opts[z].max)
  1148.                             {
  1149.                               *opts[z].value = opts[z].min;
  1150.                             }
  1151.                           if (*opts[z].value < opts[z].min)
  1152.                             {
  1153.                               *opts[z].value = opts[z].max;
  1154.                             }
  1155.                         }
  1156.                     }
  1157.                 }
  1158.             }
  1159.           env->mouseclock++;
  1160.           if (env->mouseclock > 10)
  1161.             {
  1162.               env->mouseclock = 0;
  1163.             }
  1164.         }
  1165.  
  1166.       env->make_update (mouse_x, mouse_y, ((BITMAP *) (global->misc[0]))->w, ((BITMAP *) (global->misc[0]))->h);
  1167.       env->make_update (lx, ly, ((BITMAP *) (global->misc[0]))->w, ((BITMAP *) (global->misc[0]))->h);
  1168.       lx = mouse_x;
  1169.       ly = mouse_y;
  1170.       if (! global->os_mouse) show_mouse (NULL);
  1171.  
  1172.       // draw menu stuff
  1173.       if (fi)
  1174.         {
  1175.           drawMenuBackground (global, env, BACKGROUND_BLANK, rand (), 400);
  1176.           textout_ex (env->db, font, title, global->halfWidth - 3 - text_length (font, title), global->menuBeginY + 50, BLACK, -1);
  1177.           textout_ex (env->db, font, title, global->halfWidth - 5 - text_length (font, title), global->menuBeginY + 50, WHITE, -1);
  1178.           for (z = 0; z < numEntries; z++)
  1179.             {
  1180.               int midX = opts[z].x;
  1181.               int midY = opts[z].y;
  1182.               char my_pointer[2];
  1183.  
  1184.               if (z == selected_index)
  1185.                   strcpy(my_pointer, "*");
  1186.               else
  1187.                   my_pointer[0] = '\0';
  1188.  
  1189.               if (opts[z].type == OPTION_TOGGLETYPE)
  1190.                 {
  1191.                   int color = (*opts[z].value)?WHITE:BLACK;
  1192.                   int radius = text_length(font, opts[z].name) / 2;
  1193.                   int y_radius = text_height(font);
  1194.                   if (y_radius > 8)
  1195.                       y_radius = 8;
  1196.                   ellipsefill (env->db, midX, midY + text_height (font) / 2, radius, y_radius, color);
  1197.                   textout_ex(env->db, font, my_pointer, (midX - radius) - 40 , midY, WHITE, -1);
  1198.                 }
  1199.  
  1200.               if (opts[z].displayFunc)
  1201.                 {
  1202.                   if (opts[z].type == OPTION_TOGGLETYPE)
  1203.                   {
  1204.                       opts[z].displayFunc (env,
  1205.                                            midX + text_length (font, opts[z].name) / 2, midY,
  1206.                                            opts[z].data);
  1207.                   }
  1208.                   else if (opts[z].type == OPTION_MENUTYPE)
  1209.                   {
  1210.                       opts[z].displayFunc (env,
  1211.                                            midX, midY,
  1212.                                            opts[z].data);
  1213.                       sprintf(name_buff, "%s", my_pointer);
  1214.                       textout_ex(env->db, font, name_buff, midX - 125, midY, WHITE, -1);
  1215.                   }
  1216.                   else if (opts[z].type == OPTION_SPECIALTYPE)
  1217.                   {
  1218.                       opts[z].displayFunc(env, 
  1219.                                           midX + text_length(font, opts[z].name) / 2, midY,
  1220.                                           opts[z].value );
  1221.                       sprintf (name_buff, "%s %s:", my_pointer, opts[z].name);
  1222.                       textout_ex (env->db, font, name_buff, midX - text_length (font, name_buff), 
  1223.                                   midY, opts[z].color, -1);
  1224.                       if (!opts[z].viewonly)
  1225.                       {
  1226.                           draw_sprite_v_flip (env->db, (BITMAP *) global->misc[6], midX + 100, midY);
  1227.                           draw_sprite (env->db, (BITMAP *) global->misc[6], midX + 112, midY);
  1228.                       }
  1229.                   }
  1230.                 }
  1231.               else if (opts[z].type == OPTION_MENUTYPE)
  1232.                 {
  1233.                   sprintf (name_buff, "%s -> %s", my_pointer, opts[z].name);
  1234.                   textout_ex (env->db, font, name_buff, midX - text_length (font, name_buff), midY, opts[z].color, -1);
  1235.                 }
  1236.               else if (opts[z].type == OPTION_ACTIONTYPE)
  1237.                 {
  1238.                   sprintf (name_buff, "%s -> %s", my_pointer, opts[z].name);
  1239.                   textout_ex (env->db, font, name_buff, midX - text_length (font, name_buff), midY, opts[z].color, -1);
  1240.                 }
  1241.               else if (opts[z].type == OPTION_TEXTTYPE)
  1242.                 {
  1243.                   sprintf (name_buff, "%s %s:", my_pointer, opts[z].name);
  1244.                   textout_ex (env->db, font, name_buff, midX - text_length (font, name_buff), midY, opts[z].color, -1);
  1245.                 }
  1246.               else if (opts[z].type == OPTION_COLORTYPE)
  1247.                 {
  1248.                   sprintf (name_buff, "%s %s:", my_pointer, opts[z].name);
  1249.                   textout_ex (env->db, font, name_buff, midX - text_length (font, name_buff), midY, opts[z].color, -1);
  1250.                 }
  1251.               else if (opts[z].type == OPTION_TOGGLETYPE)
  1252.                 {
  1253.                   sprintf (name_buff, "%s %s", my_pointer, opts[z].name);
  1254.                   textout_centre_ex (env->db, font, name_buff, midX, midY, opts[z].color, -1);
  1255.                 }
  1256.               else
  1257.                 {
  1258.                   sprintf (name_buff, "%s %s:", my_pointer, opts[z].name);
  1259.                   textout_ex (env->db, font, name_buff, midX - text_length (font, name_buff), midY, opts[z].color, -1);
  1260.                   if (!opts[z].viewonly)
  1261.                     {
  1262.                       draw_sprite_v_flip (env->db, (BITMAP *) global->misc[6], midX + 100, midY);
  1263.                       draw_sprite (env->db, (BITMAP *) global->misc[6], midX + 112, midY);
  1264.                     }
  1265.                 }
  1266.  
  1267.                 if (my_pointer[0])
  1268.                      env->make_update(midX - 200, midY - 20, 400, 40);
  1269.  
  1270.             }        // end of for loop
  1271.           if (but_okay) but_okay->draw (env->db);
  1272.           if (but_quit) but_quit->draw (env->db);
  1273.           if (reset_button) reset_button->draw(env->db);
  1274.         }      // end of if fi
  1275.  
  1276.       for (z = 0; z < numEntries; z++)
  1277.         {
  1278.           int midX = opts[z].x;
  1279.           int midY = opts[z].y;
  1280.           if (updateoption[z])
  1281.             {
  1282.               updateoption[z] = 0;
  1283.               if (opts[z].type == OPTION_TOGGLETYPE)
  1284.                 {
  1285.                   int color = (*opts[z].value)?WHITE:BLACK;
  1286.                   int text_tall = text_height(font);
  1287.                   if (text_tall > 8)
  1288.                       text_tall = 8;
  1289.                   ellipsefill (env->db, midX, midY + text_height (font) / 2, text_length (font, opts[z].name) / 2, text_tall, color);
  1290.                 }
  1291.               if (opts[z].displayFunc)
  1292.                 {
  1293.                   if (opts[z].type == OPTION_TOGGLETYPE)
  1294.                     {
  1295.                       opts[z].displayFunc (env,
  1296.                                            midX + text_length (font, opts[z].name) / 2, midY,
  1297.                                            opts[z].data);
  1298.                     }
  1299.                   else if (opts[z].type == OPTION_MENUTYPE)
  1300.                     {
  1301.                       opts[z].displayFunc (env,
  1302.                                            midX, midY,
  1303.                                            opts[z].data);
  1304.                     }
  1305.                   env->make_update (midX - 200, midY - text_height (font), 450, 50);
  1306.                   env->do_updates();
  1307.                 }
  1308.               else if (opts[z].type != OPTION_MENUTYPE && opts[z].type != OPTION_ACTIONTYPE)
  1309.                 {
  1310.                   if (opts[z].type == OPTION_DOUBLETYPE)
  1311.                     {
  1312.                       sprintf (format_buff, opts[z].format, *opts[z].value);
  1313.                       textEntryBox (global, env, FALSE, midX + 50, midY, format_buff, 11);
  1314.                     }
  1315.                   else if (opts[z].type == OPTION_TEXTTYPE)
  1316.                     {
  1317.                       textEntryBox (global, env, FALSE, midX + 100, midY, (char*)opts[z].value, NAME_LENGTH);
  1318.                     }
  1319.                   else if (opts[z].type == OPTION_COLORTYPE)
  1320.                     {
  1321.                       colorBar (env, midX, midY, 100, 15);
  1322.                       rectfill (env->db, midX + 110, midY, midX + 130, midY + 10, *(int*)opts[z].value);
  1323.                       rect (env->db, midX + 110, midY, midX + 130, midY + 10, BLACK);
  1324.                     }
  1325.                   else if (opts[z].type == OPTION_TOGGLETYPE)
  1326.                     {
  1327.                       sprintf (format_buff, "%s", opts[z].name);
  1328.                       textout_centre_ex (env->db, font, format_buff, midX, midY, opts[z].color, -1);
  1329.                     }
  1330.                   else if (opts[z].specialOpts)
  1331.                     {
  1332.                       textEntryBox (global, env, FALSE, midX + 50, midY, opts[z].specialOpts[(int) *opts[z].value], 11);
  1333.                     }
  1334.                   env->make_update (midX - 100, midY - 2, 250, 20);
  1335.                 }
  1336.             }
  1337.         }
  1338.  
  1339.       if (fi)
  1340.         {
  1341.           fi = 0;
  1342.           quickChange (global, env->db);
  1343.         }
  1344.  
  1345.       if ( (but_quit && but_quit->isPressed()) || (my_key == KEY_ESC) )
  1346.         {
  1347.           global->command = GLOBAL_COMMAND_MENU;
  1348.           stop = 1;
  1349.         }
  1350.       if ( (but_okay && but_okay->isPressed()) || (my_key == KEY_ENTER) )
  1351.         {
  1352.           stop = 2;
  1353.         }
  1354.  
  1355.       if ( (reset_button) && (reset_button->isPressed() ) )
  1356.       {
  1357.          // RESET all options!
  1358.          env->Reset_Options();
  1359.          global->Reset_Options();
  1360.       }
  1361.  
  1362.       if (but_okay) but_okay->draw (env->db);
  1363.       if (but_quit) but_quit->draw (env->db);
  1364.       if (reset_button) reset_button->draw(env->db);
  1365.  
  1366.       if (! global->os_mouse) show_mouse(env->db);
  1367.       if (global->close_button_pressed) stop = 1;
  1368.       env->do_updates ();
  1369.     }
  1370.   // while ((!keypressed ()) && (!stop) );
  1371.   while (! stop);
  1372.  
  1373.   if (!stop)
  1374.     ke = readkey ();
  1375.   else if (stop == 2)
  1376.     ke = KEY_ENTER << 8;
  1377.   else
  1378.     ke = KEY_ESC << 8;
  1379.  
  1380.   flush_inputs();
  1381.  
  1382.   if (but_quit)
  1383.     delete but_quit;
  1384.   if (but_okay)
  1385.     delete but_okay;
  1386.  
  1387.   if ( reset_button )
  1388.     delete reset_button;
  1389.  
  1390.   free(updateoption);
  1391.  
  1392.   return (ke);
  1393. }
  1394.  
  1395. int editPlayers (GLOBALDATA *global, ENVIRONMENT *env)
  1396. {
  1397.   int optionsRetVal;
  1398.   // int rows = (global->screenHeight - 400) / 15;
  1399.   int rows = (global->screenHeight - 2 * global->menuBeginY - 200) / 15;
  1400.   int columns = (global->numPermanentPlayers / rows) + 1;
  1401.   rows = (rows / columns) + 1;
  1402.  
  1403.   MENUENTRY *playersOpts;
  1404.   MENUDESC playersMenu;
  1405.   // playersOpts = new MENUENTRY[1 + global->numPermanentPlayers];
  1406.   playersOpts = (MENUENTRY *) calloc( global->numPermanentPlayers + 1, sizeof(MENUENTRY));
  1407.   if (!playersOpts)
  1408.     {
  1409.       perror ( "atanks.cc: Failed allocating memory for playersOpts in editPlayers");
  1410.       return 0;
  1411.       // exit (1);
  1412.     }
  1413.   playersOpts[0].name = "Create New";
  1414.   playersOpts[0].displayFunc = NULL;
  1415.   playersOpts[0].color = WHITE;
  1416.   playersOpts[0].value = (double*)createNewPlayer;
  1417.   playersOpts[0].data = NULL;
  1418.   playersOpts[0].type = OPTION_ACTIONTYPE;
  1419.   playersOpts[0].viewonly = FALSE;
  1420.   playersOpts[0].x = global->halfWidth - 3;
  1421.   // playersOpts[0].y = global->halfHeight - 68 - 15;
  1422.   playersOpts[0].y = global->menuBeginY + 117;
  1423.  
  1424.   playersMenu.title = "Players";
  1425.   playersMenu.numEntries = 1 + global->numPermanentPlayers;
  1426.   playersMenu.entries = playersOpts;
  1427.   playersMenu.quitButton = TRUE;
  1428.   playersMenu.okayButton = FALSE;
  1429.  
  1430.   for (int count = 0; count < global->numPermanentPlayers; count++)
  1431.     {
  1432.       MENUENTRY *opt = &playersOpts[1 + count];
  1433.  
  1434.       opt->name = global->allPlayers[count]->getName ();
  1435.       opt->displayFunc = displayPlayerName;
  1436.       opt->data = global->allPlayers[count];
  1437.       opt->color = global->allPlayers[count]->color;
  1438.       opt->value = (double*)global->allPlayers[count]->menudesc;
  1439.       opt->type = OPTION_MENUTYPE;
  1440.       opt->viewonly = FALSE;
  1441.       opt->x = global->halfWidth - (((count % columns) - (columns / 2)) * 90) - (((columns + 1) % 2) * 45);
  1442.       // opt->y = global->halfHeight - 68 + ((count / columns) * 15);
  1443.       opt->y = global->menuBeginY + 132 + ((count / columns) * 15);
  1444.     }
  1445.   optionsRetVal = options (global, env, &playersMenu);
  1446.  
  1447.   // delete playersOpts;
  1448.   free(playersOpts);
  1449.  
  1450.   return (optionsRetVal);
  1451. }
  1452.  
  1453. int selectPlayers (GLOBALDATA *global, ENVIRONMENT *env)
  1454. {
  1455.   MENUENTRY roundOpt = { global->ingame->complete_text[1], NULL, WHITE, (double*)&global->rounds, NULL, "%2.0f", 1, MAX_ROUNDS, 1, 5, NULL,
  1456.                          OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->menuBeginY + 82
  1457.                        };
  1458.   MENUENTRY gamename = { global->ingame->complete_text[2], NULL, WHITE, (double *) global->game_name, NULL, "%s", 0, 0, 0, 0, NULL,
  1459.                          OPTION_TEXTTYPE, FALSE, global->halfWidth - 3, global->menuBeginY + 100
  1460.                        };
  1461.   MENUENTRY loadgame, campaign;
  1462.   int save_game_exists;
  1463.  
  1464.   int optionsRetVal, z;
  1465.   // int rows = (global->screenHeight - 400) / 15;
  1466.   int rows = (global->screenHeight - 2 * global->menuBeginY - 200) / 15;
  1467.   int columns = (global->numPermanentPlayers / rows) + 1;
  1468.   int playerCount = 0;
  1469.  
  1470.   int number_saved_games = 0;
  1471.   struct dirent **saved_game_names;
  1472.   char **game_list = NULL;
  1473.   MENUENTRY *playersOpts;
  1474.   MENUDESC playersMenu;
  1475.   MENUENTRY load_game_entry;
  1476.  
  1477.   // find saved games
  1478.   saved_game_names = Find_Saved_Games(global, &number_saved_games);
  1479.   if ( (saved_game_names) && ( number_saved_games ) )
  1480.     {
  1481.       int count;
  1482.  
  1483.       // move the names into a char list
  1484.       game_list = (char **) calloc( number_saved_games, sizeof(char *) );
  1485.       for (count = 0; count < number_saved_games; count++)
  1486.         {
  1487.           game_list[count] = saved_game_names[count]->d_name;
  1488.           // clear trailign extension
  1489.           if ( strchr(game_list[count], '.') )
  1490.             strchr(game_list[count], '.')[0] = '\0';
  1491.         }
  1492.  
  1493.       global->saved_game_list = game_list;
  1494.       // set up menu for selecting saved games
  1495.       load_game_entry.name = global->ingame->complete_text[3];
  1496.       load_game_entry.displayFunc = NULL;
  1497.       load_game_entry.color = WHITE;
  1498.       load_game_entry.value = (double *) &global->saved_game_index;
  1499.       load_game_entry.data = NULL;
  1500.       load_game_entry.format = "%s";
  1501.       load_game_entry.min = 0;
  1502.       load_game_entry.max = number_saved_games - 1;
  1503.       load_game_entry.increment = 1;
  1504.       load_game_entry.defaultv = 0;
  1505.       load_game_entry.specialOpts = global->saved_game_list;
  1506.       load_game_entry.type = OPTION_SPECIALTYPE;
  1507.       load_game_entry.viewonly = FALSE;
  1508.       load_game_entry.x = global->halfWidth;
  1509.       load_game_entry.y = global->menuBeginY + 120;
  1510.     }
  1511.  
  1512.   rows = (rows / columns) + 1;
  1513.   // playersOpts = new MENUENTRY[global->numPermanentPlayers + 4];
  1514.   playersOpts = (MENUENTRY *) calloc( global->numPermanentPlayers + 5, sizeof(MENUENTRY) );
  1515.   if (!playersOpts)
  1516.     {
  1517.       perror ( "atanks.cc: Failed allocating memory for playersOpts in selectPlayers");
  1518.       // exit (1);
  1519.     }
  1520.  
  1521.   loadgame.name = global->ingame->complete_text[4];
  1522.   loadgame.displayFunc = NULL;
  1523.   loadgame.data = &global->load_game;
  1524.   loadgame.color = WHITE;
  1525.   loadgame.value = (double *) &global->load_game;
  1526.   loadgame.type = OPTION_TOGGLETYPE;
  1527.   loadgame.viewonly = FALSE;
  1528.   loadgame.x = global->halfWidth - 50;
  1529.   loadgame.y = global->menuBeginY + 140;
  1530.  
  1531.   campaign.name = global->ingame->complete_text[5];
  1532.   campaign.displayFunc = NULL;
  1533.   campaign.data = &global->campaign_mode;
  1534.   campaign.color = WHITE;
  1535.   campaign.value = (double *) &global->campaign_mode;
  1536.   campaign.type = OPTION_TOGGLETYPE;
  1537.   campaign.viewonly = FALSE;
  1538.   campaign.x = global->halfWidth + 50;
  1539.   campaign.y = global->menuBeginY + 140;
  1540.  
  1541.   playersMenu.title = global->ingame->complete_text[0];
  1542.   playersMenu.numEntries = global->numPermanentPlayers + 5;
  1543.   playersMenu.entries = playersOpts;
  1544.   playersMenu.quitButton = TRUE;
  1545.   playersMenu.okayButton = TRUE;
  1546.  
  1547.   for (int count = 0; count < global->numPermanentPlayers; count++)
  1548.     {
  1549.       MENUENTRY *opt = &playersOpts[count];
  1550.  
  1551.       opt->name = global->allPlayers[count]->getName ();
  1552.       opt->displayFunc = displayPlayerName;
  1553.       opt->data = global->allPlayers[count];
  1554.       opt->color = global->allPlayers[count]->color;
  1555.       opt->value = (double*)&global->allPlayers[count]->selected;
  1556.       opt->type = OPTION_TOGGLETYPE;
  1557.       opt->viewonly = FALSE;
  1558.       opt->x = global->halfWidth - (((count % columns) - (columns / 2)) * 90) - (((columns + 1) % 2) * 45);
  1559.       // opt->y = 265 + ( (count / columns) * 15 );
  1560.       opt->y = global->menuBeginY + 165 + ( (count / columns) * 15);
  1561.     }
  1562.   memcpy (&playersOpts[global->numPermanentPlayers], &roundOpt, sizeof (MENUENTRY));
  1563.   memcpy (&playersOpts[global->numPermanentPlayers + 1], &gamename, sizeof (MENUENTRY));
  1564.   memcpy (&playersOpts[global->numPermanentPlayers + 2], &loadgame, sizeof (MENUENTRY));
  1565.   memcpy (&playersOpts[global->numPermanentPlayers + 3], &campaign, sizeof (MENUENTRY));
  1566.   if ((number_saved_games) && (game_list) )
  1567.     memcpy (&playersOpts[global->numPermanentPlayers + 4], &load_game_entry, sizeof(MENUENTRY));
  1568.  
  1569.   do
  1570.     {
  1571.       optionsRetVal = options (global, env, &playersMenu);
  1572.       if ( global->load_game )
  1573.         {
  1574.           if ( ( global->saved_game_list) && ( global->saved_game_list[ (int) global->saved_game_index ][0] ) )
  1575.             {
  1576.               memset(global->game_name, '\0', GAME_NAME_LENGTH);
  1577.               strncpy(global->game_name, global->saved_game_list[ (int) global->saved_game_index ], 16);
  1578.             }
  1579.         }
  1580.  
  1581.       if (optionsRetVal >> 8 == KEY_ENTER)
  1582.         {
  1583.           if (! global->load_game )    // trying to play a game
  1584.             {
  1585.               playerCount = 0;
  1586.               global->numPlayers = 0;
  1587.               for (z = 0; z < global->numPermanentPlayers; z++)
  1588.                 {
  1589.                   if (global->allPlayers[z]->selected)
  1590.                     {
  1591.                       global->addPlayer (global->allPlayers[z]);
  1592.                       playerCount++;
  1593.                     }
  1594.                 }
  1595.               if ((playerCount < 2) || (playerCount > MAXPLAYERS))
  1596.                 {
  1597.                   if (playerCount < 2)
  1598.                     errorMessage = global->ingame->complete_text[8];
  1599.                   else if (playerCount > MAXPLAYERS)
  1600.                     errorMessage = global->ingame->complete_text[9];
  1601.                   errorX = global->halfWidth - text_length (font, errorMessage) / 2;
  1602.                   errorY = global->menuBeginY + 70;
  1603.                   optionsRetVal = 0;
  1604.                 }
  1605.               else
  1606.                 {
  1607.                   optionsRetVal = PLAY_GAME;
  1608.                 }
  1609.             }    // end of trying to start a new game
  1610.           else     // start to load an existing game
  1611.             {
  1612.               save_game_exists = Check_For_Saved_Game(global);
  1613.               if (save_game_exists)
  1614.                 optionsRetVal = LOAD_GAME;
  1615.               else
  1616.                 {
  1617.                   optionsRetVal = 0;
  1618.                   errorMessage = global->ingame->complete_text[39];
  1619.                   errorX  = global->halfWidth - text_length(font, errorMessage) / 2;
  1620.                   errorY = global->menuBeginY + 70;
  1621.                 }
  1622.             }
  1623.         }
  1624.       // zero means an error occured.
  1625.       // keep running the loop until ESC is pressed or a non-zero value appears
  1626.     }
  1627.   // while (optionsRetVal == 0);
  1628.   while ( (optionsRetVal >> 8 != KEY_ESC) && (optionsRetVal != PLAY_GAME) &&
  1629.           (optionsRetVal != LOAD_GAME) );
  1630.  
  1631.   // delete playersOpts;
  1632.   free(playersOpts);
  1633.   if (optionsRetVal >> 8 == KEY_ESC)
  1634.     optionsRetVal = ESC_MENU;
  1635.  
  1636.   if (saved_game_names) free(saved_game_names);
  1637.  
  1638.   return (optionsRetVal);
  1639. }
  1640.  
  1641. void title (GLOBALDATA *global)
  1642. {
  1643.   if (! global->os_mouse) show_mouse(NULL);
  1644.   blit ((BITMAP *) global->title[0], screen, 0, 0, global->halfWidth - 320, global->halfHeight - 240, 640, 480);
  1645.   if (! global->os_mouse) show_mouse (screen);
  1646.   clear_keybuf ();
  1647.  
  1648.   //wait_for_input();
  1649.  
  1650.   if (! global->os_mouse) show_mouse (NULL);
  1651. }
  1652.  
  1653.  
  1654.  
  1655.  
  1656. int menu (GLOBALDATA *global, ENVIRONMENT *env)
  1657. {
  1658.   int bf = 0, bfdd = 1, ban, anclock, lb, updateplayers, done, updaterounds, z, zz;
  1659.   int move_text;
  1660.   int seconds_idle = 0;
  1661.   int current_index = 0, max_index = 7;
  1662.   int my_key = 0;
  1663.   int bn = 0;        // button number
  1664.   int shift_menu = global->halfHeight - 240;
  1665.   if (shift_menu < 0) shift_menu = -shift_menu;
  1666.   else shift_menu = 0;
  1667.  
  1668.   move_text = 75;
  1669.   if (global->language == LANGUAGE_RUSSIAN)
  1670.       bn += MENUBUTTONS * 2;
  1671.  
  1672.   BUTTON but_play(global, env, global->halfWidth - move_text, global->halfHeight - 235 + shift_menu, NULL, (BITMAP*)global->button[bn], (BITMAP*)global->button[bn], (BITMAP*)global->button[bn+1]);
  1673.   bn += 2;
  1674.   BUTTON but_help(global, env, global->halfWidth - move_text, global->halfHeight - 185 + shift_menu, NULL, (BITMAP*)global->button[bn], (BITMAP*)global->button[bn], (BITMAP*)global->button[bn+1]);
  1675.   bn += 2;
  1676.   BUTTON but_options(global, env, global->halfWidth - move_text, global->halfHeight - 135 + shift_menu, NULL, (BITMAP*)global->button[bn], (BITMAP*)global->button[bn], (BITMAP*)global->button[bn+1]);
  1677.   bn += 2;
  1678.   BUTTON but_players(global, env, global->halfWidth - move_text, global->halfHeight - 85 + shift_menu, NULL, (BITMAP*)global->button[bn], (BITMAP*)global->button[bn], (BITMAP*)global->button[bn+1]);
  1679.   bn += 2;
  1680.   BUTTON but_credits(global, env, global->halfWidth - move_text, global->halfHeight - 35 + shift_menu, NULL, (BITMAP*)global->button[bn], (BITMAP*)global->button[bn], (BITMAP*)global->button[bn+1]);
  1681.   bn += 2;
  1682.   BUTTON but_quit(global, env, global->halfWidth - move_text, global->halfHeight + 65 + shift_menu, NULL, (BITMAP*)global->button[bn], (BITMAP*)global->button[bn], (BITMAP*)global->button[bn+1]);
  1683.   bn += 2;
  1684.   BUTTON but_network(global, env, global->halfWidth - move_text, global->halfHeight + 15 + shift_menu, NULL, (BITMAP*)global->button[bn], (BITMAP*)global->button[bn], (BITMAP*)global->button[bn+1]);
  1685.  
  1686.   BUTTON *button[MENUBUTTONS] = {&but_play, &but_help, &but_options,
  1687.                                  &but_players, &but_credits, &but_network, &but_quit
  1688.                                 };
  1689.  
  1690.   ban = -1;
  1691.   cclock = global->updateCount = lx = ly = anclock = env->mouseclock = 0;
  1692.   lb = updateplayers = done = updaterounds = 0;
  1693.   fi = global->stopwindow = 1;
  1694.   while (!done)
  1695.     {
  1696.       if ( global->Check_Time_Changed() )
  1697.       {
  1698.          seconds_idle++;
  1699.          if (seconds_idle > DEMO_WAIT_TIME)
  1700.          {
  1701.             done = 1;
  1702.             global->command = GLOBAL_COMMAND_DEMO;
  1703.          }
  1704.       }   
  1705.  
  1706.       // LINUX_SLEEP;
  1707.       LINUX_REST;
  1708.       while (cclock > 0)
  1709.         {
  1710.           cclock--;
  1711.           zz = 0;
  1712.           for (z = 0; z < MENUBUTTONS; z++)
  1713.             {
  1714.               if (button[z]->isMouseOver ())
  1715.                 {
  1716.                   if (ban > -1 && ban != z)
  1717.                     {
  1718.                       button[z]->draw (env->db);
  1719.                       //env->make_update (button[ban]->location.x, button[ban]->location.y, button[ban]->location.w, button[ban]->location.h);
  1720.                     }
  1721.                   ban = z;
  1722.                   zz = 1;
  1723.                   break;
  1724.                 }
  1725.             }
  1726.           if (!zz)
  1727.             {
  1728.               bf = 0;
  1729.               bfdd = 1;
  1730.             }
  1731.           if (!lb && mouse_b & 1)
  1732.             env->mouseclock = 0;
  1733.           lb = (mouse_b & 1) ? 1 : 0;
  1734.           if (mouse_b & 1)
  1735.             {
  1736.               for (z = 0; z < MENUBUTTONS; z++)
  1737.                 {
  1738.                   if (button[z]->isPressed ())
  1739.                     {
  1740.                       if (z == 0)
  1741.                         global->command = GLOBAL_COMMAND_PLAY;
  1742.                       else if (z == 1)
  1743.                         global->command = GLOBAL_COMMAND_HELP;
  1744.                       else if (z == 2)
  1745.                         global->command = GLOBAL_COMMAND_OPTIONS;
  1746.                       else if (z == 3)
  1747.                         global->command = GLOBAL_COMMAND_PLAYERS;
  1748.                       else if (z == 4)
  1749.                         global->command = GLOBAL_COMMAND_CREDITS;
  1750.                       else if (z == 5)
  1751.                         global->command = GLOBAL_COMMAND_NETWORK;
  1752.                       else if (z == 6)
  1753.                         global->command = GLOBAL_COMMAND_QUIT;
  1754.                       done = 1;
  1755.                     }
  1756.                 }
  1757.             }
  1758.           env->mouseclock++;
  1759.           if (env->mouseclock > 10)
  1760.             env->mouseclock = 0;
  1761.         }
  1762.       if (updaterounds)
  1763.         {
  1764.           updaterounds = 0;
  1765.           env->make_update (global->halfWidth + 27, global->halfHeight + 198, 32, 32);
  1766.         }
  1767.       if (! global->os_mouse) show_mouse (NULL);
  1768.       if (fi)
  1769.         {
  1770.           draw_circlesBG (global, env->db, 0, 0, global->screenWidth, global->screenHeight, true);
  1771.           //textout (env->db, font, (char *)"Rounds: ", global->halfWidth - 45, global->halfHeight + 200, BLACK);
  1772.           //draw_sprite_v_flip (env->db, (BITMAP *) global->gfxData.M[6].dat, global->halfWidth - 60, global->halfHeight + 199);
  1773.           //draw_sprite (env->db, (BITMAP *) global->gfxData.M[6].dat, global->halfWidth + 64, global->halfHeight + 199);
  1774.           for (z = 0; z < MENUBUTTONS; z++)
  1775.            {
  1776.               button[z]->draw (env->db);
  1777.               if (z == current_index)
  1778.               {
  1779.                 // int delta_width = (global->language == LANGUAGE_RUSSIAN) ? 20 : 0;
  1780.                 // if (global->language == LANGUAGE_GERMAN) delta_width = 20;
  1781.                 // draw rectangle around selected option
  1782.                 rect(env->db, global->halfWidth - move_text - 8, 
  1783.                      global->halfHeight - 240 + (50 * current_index) + shift_menu,
  1784.                      global->halfWidth + move_text + 8, // - delta_width, 
  1785.                      global->halfHeight - 190 + (50 * current_index) + shift_menu, YELLOW);
  1786.               }
  1787.            }
  1788.         }
  1789.       if (ban > -1)
  1790.         {
  1791.           button[ban]->draw (env->db);
  1792.           //env->make_update (button[ban]->location.x, button[ban]->location.y, button[ban]->location.w, button[ban]->location.h);
  1793.         }
  1794.       //rectfill (env->db, global->halfWidth + 27, global->halfHeight + 198, global->halfWidth + 59, global->halfHeight + 210, WHITE);
  1795.       //rect (env->db, global->halfWidth + 27, global->halfHeight + 198, global->halfWidth + 59, global->halfHeight + 210, BLACK);
  1796.       //textprintf_centre (env->db, font, global->halfWidth + 43, global->halfHeight + 200, BLACK, (char *)"%d", global->rounds);
  1797.       if (! global->os_mouse) show_mouse (env->db);
  1798.       env->make_update (mouse_x, mouse_y, ((BITMAP *) (global->misc[0]))->w, ((BITMAP *) (global->misc[0]))->h);
  1799.       env->make_update (lx, ly, ((BITMAP *) (global->misc[0]))->w, ((BITMAP *) (global->misc[0]))->h);
  1800.       lx = mouse_x;
  1801.       ly = mouse_y;
  1802.  
  1803.       // check for key press
  1804.       if ( keypressed() )
  1805.       {
  1806.           my_key = readkey();
  1807.           my_key = my_key >> 8;
  1808.           fi = 2;
  1809.       }
  1810.       
  1811.       if ( ( my_key == KEY_DOWN ) || (my_key == KEY_S) )
  1812.       {
  1813.          current_index++;
  1814.          if (current_index >= max_index)
  1815.             current_index = 0;
  1816.       }
  1817.       else if ( (my_key == KEY_UP) || (my_key == KEY_W) )
  1818.       {
  1819.          current_index--;
  1820.          if (current_index < 0)
  1821.            current_index = max_index - 1;
  1822.       }
  1823.       else if ( (my_key == KEY_ENTER) || 
  1824.                 (my_key == KEY_ENTER_PAD) ||
  1825.                 (my_key == KEY_SPACE) )
  1826.       {
  1827.                done = 1;
  1828.                if (current_index == 0)
  1829.                       global->command = GLOBAL_COMMAND_PLAY;
  1830.                else if (current_index == 1)
  1831.                         global->command = GLOBAL_COMMAND_HELP;
  1832.                else if (current_index == 2)
  1833.                         global->command = GLOBAL_COMMAND_OPTIONS;
  1834.                else if (current_index == 3)
  1835.                         global->command = GLOBAL_COMMAND_PLAYERS;
  1836.                else if (current_index == 4)
  1837.                         global->command = GLOBAL_COMMAND_CREDITS;
  1838.                else if (current_index == 5)
  1839.                         global->command = GLOBAL_COMMAND_NETWORK;
  1840.                else if (current_index == 6)
  1841.                         global->command = GLOBAL_COMMAND_QUIT;
  1842.  
  1843.       } 
  1844.       else if ( (my_key == KEY_Q) || (my_key == KEY_ESC))
  1845.       {
  1846.           return SIG_QUIT_GAME;
  1847.       }
  1848.       my_key = 0;
  1849.  
  1850.       if (fi > 0)
  1851.         {
  1852.           fi--;
  1853.           change (global, env->db);
  1854.         }
  1855.       if (global->close_button_pressed) return SIG_QUIT_GAME;
  1856.       if ( (global->update_string) && (global->update_string[0]) )
  1857.       {  
  1858.        textout_centre_ex (env->db, font, global->update_string, 
  1859.                           global->halfWidth - 20, 500, WHITE, -1);
  1860.        env->make_update(50, 450, 300, 50);
  1861.       }
  1862.       if (global->client_message)
  1863.       {
  1864.         textout_centre_ex(env->db, font, global->client_message,
  1865.                           global->halfWidth - 20, 520, WHITE, -1);
  1866.         env->make_update(50, 450, 300, 100);
  1867.       }
  1868.       env->do_updates ();
  1869.     }
  1870.   clear_keybuf ();
  1871.   return SIG_OK;
  1872. }
  1873.  
  1874. void draw_text_in_box (ENVIRONMENT *env, BOX *region, char *text)
  1875. {
  1876.   char buffer[1024];
  1877.   unsigned int lineBegin;
  1878.   int lastSpace = 0;
  1879.   int lineCount;
  1880.   int charCount;
  1881.   int buffCount ;
  1882.  
  1883.   rectfill (env->db, region->x, region->y, region->w, region->h,
  1884.             makecol (0,0,128));
  1885.   rect     (env->db, region->x, region->y, region->w, region->h,
  1886.             makecol (128,128,255));
  1887.  
  1888.   lineBegin = 0;
  1889.   lineCount = 0;
  1890.   while (lineBegin < strlen (text))
  1891.     {
  1892.       charCount = 0;
  1893.       buffCount = 0;
  1894.       do
  1895.         {
  1896.           buffer[buffCount] = text[lineBegin + charCount];
  1897.           buffer[buffCount+1] = 0;
  1898.           if (buffer[buffCount] == ' ')
  1899.             {
  1900.               lastSpace = 0;
  1901.             }
  1902.           else if (buffer[buffCount] == '\n')
  1903.             {
  1904.               lineCount++;
  1905.               charCount++;
  1906.               break;
  1907.             }
  1908.           lastSpace++;
  1909.           buffCount++;
  1910.           charCount++;
  1911.         }
  1912.       while (text[lineBegin + charCount] && (text_length (font, buffer) < region->w - 20));
  1913.       if ((lastSpace > 0) && (text_length (font, buffer) >= region->w - 20))
  1914.         {
  1915.           charCount -= lastSpace - 1;
  1916.           buffer[buffCount - lastSpace] = 0;
  1917.         }
  1918.       else
  1919.         {
  1920.           buffer[buffCount] = 0;
  1921.         }
  1922.       textout_ex (env->db, font, buffer, region->x + 5,
  1923.                   region->y + (lineCount * text_height (font)) + 5, WHITE, -1);
  1924.       lineBegin = lineBegin + charCount;
  1925.       charCount = 0;
  1926.       lineCount++;
  1927.     }
  1928.   env->make_update (region->x, region->y, region->w, region->h);
  1929. }
  1930.  
  1931. void draw_buystuff(GLOBALDATA *global, ENVIRONMENT *env, PLAYER *pl)
  1932. {
  1933.   int z;
  1934.   env->make_update (0, 0, global->screenWidth, global->screenHeight);
  1935.   if (! global->os_mouse) show_mouse (NULL);
  1936.  
  1937.   draw_circlesBG (global, env->db, 0, 0, global->screenWidth, global->screenHeight, false);
  1938.   draw_sprite (env->db, (BITMAP *) global->misc[DONE_IMAGE], global->halfWidth - 100, global->screenHeight - 50);
  1939.   draw_sprite (env->db, (BITMAP *) global->misc[FAST_UP_ARROW_IMAGE], global->screenWidth - STUFF_BAR_WIDTH - 30, global->halfHeight - 50);
  1940.   draw_sprite (env->db, (BITMAP *) global->misc[UP_ARROW_IMAGE], global->screenWidth - STUFF_BAR_WIDTH - 30, global->halfHeight - 25);
  1941.   draw_sprite (env->db, (BITMAP *) global->misc[DOWN_ARROW_IMAGE], global->screenWidth - STUFF_BAR_WIDTH - 30, global->halfHeight);
  1942.   draw_sprite (env->db, (BITMAP *) global->misc[FAST_DOWN_ARROW_IMAGE], global->screenWidth - STUFF_BAR_WIDTH - 30, global->halfHeight + 25);
  1943.   drawing_mode (DRAW_MODE_TRANS, NULL, 0, 0);
  1944.   env->current_drawing_mode = DRAW_MODE_TRANS;
  1945.  
  1946.   for (z = 0; z < global->halfWidth - 200; z++)
  1947.     {
  1948.       set_trans_blender (0, 0, 0, (int)((double)((double)z / (global->halfWidth - 200)) * 240) + 15);
  1949.       vline (env->db, z, 0, 29, pl->color);
  1950.     }
  1951.  
  1952.   for (z = 0; z < global->halfWidth - 200; z++)
  1953.     {
  1954.       set_trans_blender (0, 0, 0, (int)((double)((double)z / (global->halfWidth - 200)) * 240) + 15);
  1955.       vline (env->db, (global->screenWidth-1) - z, 0, 29, pl->color);
  1956.     }
  1957.  
  1958.   solid_mode ();
  1959.   env->current_drawing_mode = DRAW_MODE_SOLID;
  1960.   textout_ex (env->db, font, global->ingame->complete_text[14], 20, 420, WHITE, -1);
  1961.   textout_ex(env->db, font, global->ingame->complete_text[15], 20, 450, WHITE, -1);
  1962.   textout_ex(env->db, font, global->ingame->complete_text[16], 20, 465, WHITE, -1);
  1963.  
  1964. }
  1965.  
  1966. int btps;
  1967. void draw_weapon_list(GLOBALDATA *global, ENVIRONMENT *env, PLAYER *pl, int *trolley, int scroll, int pressed)
  1968. {
  1969.   int slot, zzz;
  1970.   double tempbtps = (global->screenHeight - 55) / STUFF_BAR_HEIGHT;
  1971.   int font_diff;
  1972.  
  1973.   (font == global->unicode) ? font_diff = 8 : font_diff = 0;
  1974.  
  1975.   // To be sure it rounds down
  1976.   btps = (int)tempbtps;
  1977.   if (tempbtps < btps)
  1978.     btps--;
  1979.  
  1980.  
  1981.   // go through all items and draw them on the screen with
  1982.   // the amount of items in the trolly
  1983.   for (slot = 1, zzz = scroll; (slot < btps) && (zzz < env->numAvailable); zzz++)
  1984.     {
  1985.       int itemNum = env->availableItems[zzz];
  1986.       draw_sprite (env->db, (BITMAP *)global->gfxData.stuff_bar[(pressed == itemNum)?1:0], global->screenWidth - STUFF_BAR_WIDTH, slot * STUFF_BAR_HEIGHT);
  1987.  
  1988.       draw_sprite(env->db, (BITMAP *) global->gfxData.stuff_icon_base, global->screenWidth - STUFF_BAR_WIDTH, (slot * STUFF_BAR_HEIGHT));
  1989.       draw_sprite(env->db, (BITMAP *) global->stock[itemNum], global->screenWidth - STUFF_BAR_WIDTH, (slot * STUFF_BAR_HEIGHT) - 5);
  1990.       env->make_update (global->screenWidth - STUFF_BAR_WIDTH, slot * STUFF_BAR_HEIGHT, STUFF_BAR_WIDTH, STUFF_BAR_HEIGHT + 5);
  1991.  
  1992.       if (itemNum >= WEAPONS)      /* Items part */
  1993.         {
  1994.  
  1995.           textout_ex (env->db, font,
  1996.                       item[itemNum - WEAPONS].name, global->screenWidth - STUFF_BAR_WIDTH + 45, (slot * STUFF_BAR_HEIGHT) + 5 - font_diff, BLACK, -1);
  1997.           // Amount in inventory
  1998.           textprintf_ex (env->db, font, global->screenWidth - STUFF_BAR_WIDTH + 45, (slot * STUFF_BAR_HEIGHT) + (STUFF_BAR_HEIGHT/2) - font_diff, BLACK, -1, "%s: %d", global->ingame->complete_text[40], pl->ni[itemNum - WEAPONS]);
  1999.           // Anything in the trolley
  2000.           if (trolley[itemNum] != 0)
  2001.             {
  2002.               int textCol;
  2003.               if (trolley[itemNum] > 0)
  2004.                 textCol = makecol (255,255,0);
  2005.               else
  2006.                 textCol = makecol (176,0,0);
  2007.               textprintf_ex (env->db, font, global->screenWidth - STUFF_BAR_WIDTH + 45 + text_length (font, "Qty. in inventory: ddd"), (slot * STUFF_BAR_HEIGHT) + (STUFF_BAR_HEIGHT/2) - font_diff, textCol, -1, "%+d", trolley[itemNum]);
  2008.             }
  2009.           sprintf (buf, "$%s", Add_Comma( item[itemNum - WEAPONS].cost ) );
  2010.           textout_ex (env->db, font, buf,
  2011.                       global->screenWidth - 45 - text_length (font, buf), (slot * STUFF_BAR_HEIGHT) + 5 - font_diff, BLACK, -1);
  2012.           sprintf (buf, "for %d", item[itemNum - WEAPONS].amt);
  2013.           textout_ex (env->db, font, buf,
  2014.                       global->screenWidth - 45 - text_length (font, buf), (slot * STUFF_BAR_HEIGHT) + (STUFF_BAR_HEIGHT/2) - font_diff, BLACK, -1);
  2015.         }
  2016.       else              /* Weapons part */
  2017.         {
  2018.  
  2019.           textout_ex (env->db, font, weapon[itemNum].name, global->screenWidth - STUFF_BAR_WIDTH + 45, (slot * STUFF_BAR_HEIGHT) + 5 - font_diff, BLACK, -1);
  2020.           textprintf_ex (env->db, font, global->screenWidth - STUFF_BAR_WIDTH + 45, (slot * STUFF_BAR_HEIGHT) + (STUFF_BAR_HEIGHT/2) - font_diff, BLACK, -1, "%s: %d", global->ingame->complete_text[40], pl->nm[itemNum]);
  2021.           // Anything in the trolley
  2022.           if (trolley[itemNum] != 0)
  2023.             {
  2024.               int textCol;
  2025.               if (trolley[itemNum] > 0)
  2026.                 textCol = makecol (255,255,0);
  2027.               else
  2028.                 textCol = makecol (176,0,0);
  2029.               textprintf_ex (env->db, font, global->screenWidth - STUFF_BAR_WIDTH + 45 + text_length (font, "Qty. in inventory: ddd"), (slot * STUFF_BAR_HEIGHT) + (STUFF_BAR_HEIGHT/2) - font_diff, textCol, -1, "%+d", weapon[itemNum].delay ? trolley[itemNum] / weapon[itemNum].delay : trolley[itemNum]);
  2030.             }
  2031.           sprintf (buf, "$%s", Add_Comma( weapon[itemNum].cost ));
  2032.           textout_ex (env->db, font, buf,
  2033.                       global->screenWidth - 45 - text_length (font, buf), (slot * STUFF_BAR_HEIGHT) + 5 - font_diff, BLACK, -1);
  2034.           sprintf (buf, "for %d", weapon[itemNum].amt);
  2035.           textout_ex (env->db, font, buf, global->screenWidth - 45 - text_length (font, buf), (slot * STUFF_BAR_HEIGHT) + (STUFF_BAR_HEIGHT/2) - font_diff, BLACK, -1);
  2036.         }
  2037.       slot++;
  2038.     }
  2039.  
  2040.  
  2041. }
  2042.  
  2043. bool buystuff (GLOBALDATA *global, ENVIRONMENT *env)
  2044. {
  2045.   int pl, done, updatew[THINGS], updatename, pressed, scroll, lb, lastMouse_b;
  2046.   int hoverOver = 0, z, zz, zzz;
  2047.   char buf[50];
  2048.   int mouse_wheel_previous, mouse_wheel_current;
  2049.   int performed_save_game = FALSE;
  2050.   char description[1024];
  2051.   BOX area = {20, 60, 300, 400};
  2052.   int my_cclock;
  2053.   int item_index = 1;
  2054.   int my_key = 0;
  2055.   int cost, amt, inInv;
  2056.   int buy_count = 0;
  2057.  
  2058.   strcpy(description, " ");
  2059.   //avoid compiler warning via initalize
  2060.   lastMouse_b = 0;
  2061.  
  2062.   // check starting position of the mouse wheel
  2063.   mouse_wheel_previous = mouse_z;
  2064.  
  2065.   global->updateCount = cclock = lb = env->mouseclock = 0;
  2066.   fi = global->stopwindow = updatename = scroll = 1;
  2067.  
  2068.   // before we do anything else, put a cap on money
  2069.   for (z = 0; z < global->numPlayers; z++)
  2070.   {
  2071.      if (global->players[z]->money > 1000000000)
  2072.             global->players[z]->money = 1000000000;
  2073.      if (global->players[z]->money < 0)
  2074.             global->players[z]->money = 0;
  2075.   }
  2076.  
  2077.  
  2078.   if (global->bIsGameLoaded)
  2079.     // after the first shopping loop the game isn't fresh anymore
  2080. #ifdef DEBUG
  2081.     {
  2082.       cout << endl << "===========================================" << endl;
  2083.       cout << "==          New or Loaded Game!          ==" << endl;
  2084.       cout << "===========================================" << endl << endl;
  2085. #endif // DEBUG
  2086.       global->bIsGameLoaded = false;
  2087. #ifdef DEBUG
  2088.     }
  2089. #endif // DEBUG
  2090.   else if (global->divide_money)
  2091.     {
  2092.       // This only applies if this is not a fresh/loaded game
  2093.       // And if players want to divide the money
  2094.       int iJediMoney = 0;
  2095.       int iJediCount = 0;
  2096.       int iSithMoney = 0;
  2097.       int iSithCount = 0;
  2098.       int iTeamFee     = 0;
  2099.       
  2100.       for (z = 0; z < global->numPlayers; z++)
  2101.         {
  2102.           /*
  2103.           if (global->players[z]->money > 1000000000)
  2104.             global->players[z]->money = 1000000000;
  2105.           if (global->players[z]->money < 0)
  2106.             global->players[z]->money = 0;
  2107.           */
  2108.           // Sum up team money:
  2109.           if (global->players[z]->team == TEAM_JEDI)
  2110.             {
  2111.               iTeamFee = (int)((double)global->players[z]->money * 0.25);
  2112.               if (iTeamFee > MAX_TEAM_AMOUNT)
  2113.                 iTeamFee    =    MAX_TEAM_AMOUNT;
  2114.               iJediMoney += iTeamFee;
  2115.               global->players[z]->money -= iTeamFee;
  2116.               iJediCount++;
  2117.             }
  2118.           if (global->players[z]->team == TEAM_SITH)
  2119.             {
  2120.               iTeamFee = (int)((double)global->players[z]->money * 0.25);
  2121.               if (iTeamFee > MAX_TEAM_AMOUNT)
  2122.                 iTeamFee    =    MAX_TEAM_AMOUNT;
  2123.               iSithMoney += iTeamFee;
  2124.               global->players[z]->money -= iTeamFee;
  2125.               iSithCount++;
  2126.             }
  2127.         }
  2128. #ifdef DEBUG
  2129.       cout << endl << "Jedi Count: " << iJediCount << " - SitH Count: " << iSithCount << endl;
  2130. #endif // DEBUG
  2131.       // Now apply the team money:
  2132.       if (iJediCount || iSithCount)
  2133.         {
  2134. #ifdef DEBUG
  2135.           if (iJediCount)
  2136.             printf( (char *)"The Jedi summed up a pool of %13d bucks!\n", iJediMoney);
  2137.           if (iSithCount)
  2138.             printf( (char *)"The Sith summed up a pool of %13d bucks!\n", iSithMoney);
  2139. #endif // DEBUG
  2140.           if (iJediCount)
  2141.             iJediMoney = (int)(((double)iJediMoney * 0.90) / (double)iJediCount);
  2142.           if (iSithCount)
  2143.             iSithMoney = (int)(((double)iSithMoney * 0.90) / (double)iSithCount);
  2144. #ifdef DEBUG
  2145.           if (iJediCount)
  2146.             printf( (char *)"Every Jedi will receive %10d credits out of the pool!\n", iJediMoney);
  2147.           if (iSithCount)
  2148.             printf( (char *)"Every Sith will receive %10d credits out of the pool!\n", iSithMoney);
  2149. #endif // DEBUG
  2150.           for (z = 0; z < global->numPlayers; z++)
  2151.             {
  2152.               if (global->players[z]->team == TEAM_JEDI)
  2153.                 global->players[z]->money    +=    iJediMoney;
  2154.               if (global->players[z]->team == TEAM_SITH)
  2155.                 global->players[z]->money    +=    iSithMoney;
  2156.             }
  2157.         }
  2158.     }
  2159.  
  2160.   env->generateAvailableItemsList ();
  2161.   int iMaxBoost = 0;
  2162.   int iMaxScore = 0; 
  2163.   for (pl = 0; pl < global->numPlayers; pl++)
  2164.     {
  2165.       int iCurrentBoostLevel =    global->players[pl]->getBoostValue();
  2166.       if (iCurrentBoostLevel > iMaxBoost)
  2167.         iMaxBoost    =    iCurrentBoostLevel;
  2168.       if (global->players[pl]->score > iMaxScore)
  2169.         iMaxScore = global->players[pl]->score;
  2170.     }
  2171.  
  2172.   for (pl = 0; pl < global->numPlayers; pl++)
  2173.     {
  2174.       int money = global->players[pl]->money;
  2175.       int trolley[THINGS];
  2176.       memset (trolley, 0, sizeof (int) * THINGS);
  2177.  
  2178.       //have computer players buy stuff
  2179.       if ( (int) global->players[pl]->type != HUMAN_PLAYER)
  2180.         {
  2181.           int pressed = 0;
  2182.           int moneyToSave = 0;    // How much money will the player save?
  2183.           int numDmgWeaps = 0;    // How many damage dealing weapons apart from small missiles do they have=
  2184.           int numPara            =    0;    // how many parachutes do we have?
  2185.           int numProj            =    0;    // How many slick/dimpled projectiles do we have?
  2186. #ifdef DEBUG
  2187.           cout << "(" << global->players[pl]->getName() << ") Starting to buy:" << endl;
  2188.           if (global->players[pl]->defensive < -0.9) cout << "(True Offensive)" << endl;
  2189.           if ((global->players[pl]->defensive >=-0.9) && (global->players[pl]->defensive < -0.75)) cout << "(Very Offensive)" << endl;
  2190.           if ((global->players[pl]->defensive >=-0.75) && (global->players[pl]->defensive < -0.25)) cout << "(Offensive)" << endl;
  2191.           if ((global->players[pl]->defensive >=-0.25) && (global->players[pl]->defensive < 0.00)) cout << "(Slightly Offensive)" << endl;
  2192.           if (global->players[pl]->defensive == 0.0)    cout << "(Neutral)" << endl;
  2193.           if ((global->players[pl]->defensive >0.0) && (global->players[pl]->defensive <= 0.25)) cout << "(Slightly Defensive)"<< endl;
  2194.           if ((global->players[pl]->defensive >0.25) && (global->players[pl]->defensive <= 0.75)) cout << "(Defensive)" << endl;
  2195.           if ((global->players[pl]->defensive >0.75) && (global->players[pl]->defensive <= 0.9)) cout << "(Very Defensive)" << endl;
  2196.           if (global->players[pl]->defensive > 0.9)    cout << "(True Defensive)" << endl;
  2197.           cout << "Inventory:" << endl <<  "----------" << endl;
  2198.           for (int i = 1; i < WEAPONS; i++)
  2199.             {
  2200.               if (global->players[pl]->nm[i])
  2201.                 cout << global->players[pl]->nm[i] << " x " << weapon[i].name << endl;
  2202.             }
  2203.           cout << " - - - - - - -" << endl;
  2204.           for (int i = 1; i < ITEMS; i++)
  2205.             {
  2206.               if (global->players[pl]->ni[i])
  2207.                 cout << global->players[pl]->ni[i] << " x " << item[i].name << endl;
  2208.             }
  2209.           cout << "----------" << endl;
  2210. #endif // DEBUG
  2211.           // moneysaving will be made possible when:
  2212.           // 1. It's not the first three rounds
  2213.           // 2. It's not the last 5 rounds
  2214.           // and, dynamically:
  2215.           // 3. We have at least 10 parachutes  or no gravity
  2216.           // 4. We have at least 5 damage dealing (not small missile) weapons
  2217.           // 5. We have a sum of 50 slick/dimpled projectiles
  2218.  
  2219.           if    ( (global->currentround > 5)
  2220.                && ( ( (int) global->rounds - global->currentround) > 3))
  2221.             {
  2222.               moneyToSave    =    global->players[pl]->getMoneyToSave();
  2223. #ifdef DEBUG
  2224.               cout << "Maximum Money to save: " << moneyToSave << " (I have: " << global->players[pl]->money << ")" << endl;
  2225. #endif //DEBUG
  2226.             }
  2227. #ifdef DEBUG
  2228.           else
  2229.             cout << "No money to save this round!!!" << endl;
  2230. #endif // DEBUG
  2231.           // Check for a minimum of damage dealing weapons and parachutes, then buy until moneyToSave is reached
  2232.           buy_count = 0;
  2233.           do
  2234.             {
  2235.               numPara            =    global->players[pl]->ni[ITEM_PARACHUTE];
  2236.               numProj            = global->players[pl]->ni[ITEM_SLICKP] + global->players[pl]->ni[ITEM_DIMPLEP];
  2237.               numDmgWeaps    =    0;
  2238.  
  2239.               for (int i = 1; i < WEAPONS; i++)
  2240.                 {
  2241.                   // start from 1, as 0 is the small missile
  2242.                   if (weapon[i].damage > 0)
  2243.                     numDmgWeaps += global->players[pl]->nm[i];
  2244.                 }
  2245.  
  2246.               if    ( (global->players[pl]->money > moneyToSave)
  2247.                    || ( (numPara            < 10) && (env->landSlideType > LANDSLIDE_NONE))
  2248.                    || (numDmgWeaps    <    8)
  2249.                    || (numProj            < 50))
  2250.                {
  2251.                 pressed = global->players[pl]->chooseItemToBuy (iMaxBoost);
  2252.                }
  2253.               else
  2254.                 pressed    =    -1;
  2255.  
  2256. #ifdef DEBUG
  2257.               if (pressed > -1)
  2258.                 {
  2259.                   cout << "I have bought: ";
  2260.                   if (pressed < WEAPONS)
  2261.                     cout << weapon[pressed].name;
  2262.                   else
  2263.                     cout << item[pressed - WEAPONS].name;
  2264.                   cout << " (" << global->players[pl]->money << " bucks left)" << endl;
  2265.                 }
  2266.               else
  2267.                 cout << "Finished, with " << global->players[pl]->money << " Credits left!" << endl;
  2268. #endif // DEBUG
  2269.             buy_count++;
  2270.             }
  2271.           while ( (pressed != -1) && (buy_count < 100) );
  2272.  
  2273. #ifdef DEBUG
  2274.           cout << "============================================" << endl << endl;
  2275. #endif //DEBUG
  2276.           continue;  //go to next player
  2277.         }        // end of AI player
  2278.  
  2279.       done = 0;
  2280.       updatename = scroll = 1;
  2281.       pressed = -1;
  2282.  
  2283.       draw_buystuff (global, env, global->players[pl]);
  2284.  
  2285.       for (z = 0; z < THINGS; z++)
  2286.         updatew[z] = 1;
  2287.       while (!done)
  2288.         {
  2289.  
  2290.           LINUX_SLEEP;
  2291.           my_cclock = CLOCK_MAX;
  2292.           while (my_cclock > 0)
  2293.             {
  2294.               LINUX_SLEEP;
  2295.               if (global->close_button_pressed)
  2296.                 {
  2297.                   clear_keybuf();
  2298.                   return false;
  2299.                 }
  2300.               my_cclock--;
  2301.               if (!lb && mouse_b & 1 && mouse_x >= global->halfWidth - 100 && mouse_x < global->halfWidth + 100 && mouse_y >= global->screenHeight - 50 && mouse_y < global->screenHeight - 25)
  2302.                 done = 1;
  2303.               if (!lb && mouse_b & 1)
  2304.                 env->mouseclock = 0;
  2305.               lb = (mouse_b & 1) ? 1 : 0;
  2306.  
  2307.               my_key = 0;
  2308.               //Keyboard control
  2309.               if ( keypressed() )
  2310.               {
  2311.                  my_key = readkey();
  2312.                  my_key = my_key >> 8;
  2313.               }
  2314.  
  2315.               if  ( my_key == KEY_UP || my_key == KEY_W) // && (scroll > 1) 
  2316.                 //  && (!env->mouseclock))
  2317.                 {
  2318.                   if (item_index > 1)
  2319.                      item_index--;
  2320.                   if (scroll > 1)
  2321.                      scroll--;
  2322.                   for (z = 0; z < THINGS; z++)
  2323.                     updatew[z] = 1;
  2324.                 }
  2325.               if (my_key == KEY_PGUP || my_key == KEY_R) // && (scroll > 1)
  2326.                   // && (!env->mouseclock))
  2327.                 {
  2328.                   item_index -= btps / 2;
  2329.                   if (item_index < 1)
  2330.                      item_index = 1;
  2331.                   scroll -= btps / 2;
  2332.                   if (scroll < 1)
  2333.                     scroll = 1;
  2334.                   for (z = 0; z < THINGS; z++)
  2335.                     updatew[z] = 1;
  2336.                 }
  2337.  
  2338.               if (my_key == KEY_DOWN || my_key == KEY_S)
  2339.               //    && (scroll <= env->numAvailable - btps)
  2340.               //    && (!env->mouseclock))
  2341.                 {
  2342.                   if (item_index < (env->numAvailable - 1))
  2343.                      item_index++;
  2344.                  if (scroll <= env->numAvailable - btps)
  2345.                      scroll++;
  2346.                   for (z = 0; z < THINGS; z++)
  2347.                     updatew[z] = 1;
  2348.                 }
  2349.               if ((my_key == KEY_PGDN || my_key == KEY_F)
  2350.                   && (scroll <= env->numAvailable - btps + 1) )
  2351.                 //  && (!env->mouseclock))
  2352.                 {
  2353.                   item_index += btps / 2;
  2354.                   if (item_index > env->numAvailable - btps)
  2355.                      item_index = env->numAvailable - btps;
  2356.                   scroll += btps / 2;
  2357.                   if (scroll > env->numAvailable - btps + 1)
  2358.                     scroll = env->numAvailable - btps + 1;
  2359.                   for (z = 0; z < THINGS; z++)
  2360.                     updatew[z] = 1;
  2361.                 }
  2362.  
  2363.               // make sure the selected item is on the visible screen
  2364.               if (item_index < scroll)
  2365.                  item_index = scroll;
  2366.               else if ( item_index > (scroll + btps + 3) )
  2367.                  item_index = scroll + btps + 3;
  2368.  
  2369.               // buy or sell an item
  2370.               if (my_key == KEY_RIGHT || my_key == KEY_D) 
  2371.               {
  2372.                     pressed = env->availableItems[item_index];
  2373.                     if (pressed >= WEAPONS)
  2374.                     {
  2375.                       cost = item[pressed - WEAPONS].cost;
  2376.                       amt = item[pressed - WEAPONS].amt;
  2377.                       inInv = global->players[pl]->ni[pressed - WEAPONS];
  2378.                     }
  2379.                   else
  2380.                     {
  2381.                       cost = weapon[pressed].cost;
  2382.                       amt = weapon[pressed].amt;
  2383.                       inInv = global->players[pl]->nm[pressed];
  2384.                     }
  2385.                      if ((money >= cost)
  2386.                           && ( (inInv + trolley[pressed]) < (999 - amt)))
  2387.                         {
  2388.                           if (trolley[pressed] <= -amt)
  2389.                             {
  2390.                               if (global->sellpercent > 0.01)
  2391.                                 {
  2392.                                   money -= (int)(cost * global->sellpercent);
  2393.                                   trolley[pressed] += amt;
  2394.                                   updatename = 1;
  2395.                                 }
  2396.                             }
  2397.                           else
  2398.                             {
  2399.                               money -= cost;
  2400.                               trolley[pressed] += amt;
  2401.                               updatename = 1;
  2402.                               if (inInv + trolley[pressed] > 999)
  2403.                                 trolley[pressed] = 999;
  2404.                             }
  2405.                         }
  2406.                    pressed = -1;
  2407.               }         // end of buying
  2408.  
  2409.               if ( my_key == KEY_LEFT || my_key == KEY_A)
  2410.               {
  2411.                   pressed = env->availableItems[item_index];
  2412.                     if (pressed >= WEAPONS)
  2413.                     {
  2414.                       cost = item[pressed - WEAPONS].cost;
  2415.                       amt = item[pressed - WEAPONS].amt;
  2416.                       inInv = global->players[pl]->ni[pressed - WEAPONS];
  2417.                     }
  2418.                   else
  2419.                     {
  2420.                       cost = weapon[pressed].cost;
  2421.                       amt = weapon[pressed].amt;
  2422.                       inInv = global->players[pl]->nm[pressed];
  2423.                     }
  2424.                     if (inInv + trolley[pressed] >= amt)
  2425.                     {
  2426.                           if (trolley[pressed] >= amt)
  2427.                           {
  2428.                               money += cost;
  2429.                               trolley[pressed] -= amt;
  2430.                               updatename = 1;
  2431.                           }
  2432.                           else
  2433.                           {
  2434.                               if (global->sellpercent > 0.01)
  2435.                                 {
  2436.                                   money += (int)(cost * global->sellpercent);
  2437.                                   trolley[pressed] -= amt;
  2438.                                   updatename = 1;
  2439.                                 }
  2440.                           }
  2441.                      }
  2442.                    pressed = -1;
  2443.               }           // end of selling
  2444.  
  2445.  
  2446.               // check for adding or removing rounds
  2447.               if ( (my_key == KEY_PLUS_PAD) || (my_key == KEY_EQUALS) )
  2448.                 {
  2449.                   if ( (global->rounds < 999) && (! env->mouseclock) )
  2450.                     {
  2451.                       global->rounds++;
  2452.                       global->currentround++;
  2453.                       updatename = 1;
  2454.                     }
  2455.                 }
  2456.               if ( (my_key == KEY_MINUS_PAD) || (my_key == KEY_MINUS) )
  2457.                 {
  2458.                   if ( (global->rounds > 1) && (global->currentround > 1)
  2459.                        && (! env->mouseclock) )
  2460.                     {
  2461.                       global->rounds--;
  2462.                       global->currentround--;
  2463.                       updatename = 1;
  2464.                     }
  2465.                 }
  2466.  
  2467.               // check for saving the game
  2468.               if ( my_key == KEY_F10 )
  2469.                 {
  2470.                   int status;
  2471.                   if (! performed_save_game)
  2472.                     {
  2473.                       status = Save_Game(global, env);
  2474.                       performed_save_game = TRUE;
  2475.                       if (status)
  2476.                         snprintf(description, 64, "%s \"%s\".", global->ingame->complete_text[17], global->game_name);
  2477.                       else
  2478.                         strcpy(description, global->ingame->complete_text[41]);
  2479.                       draw_text_in_box (env, &area, description);
  2480.                     }
  2481.                 }
  2482.  
  2483.               if ( my_key == KEY_ENTER)
  2484.                  done = TRUE;
  2485.  
  2486.               // Mouse control
  2487.  
  2488.               // check mouse wheel
  2489.               mouse_wheel_current = mouse_z;
  2490.               if (mouse_wheel_current < mouse_wheel_previous)
  2491.                 {
  2492.                   scroll++;
  2493.                   if (scroll > env->numAvailable - btps + 1)
  2494.                     scroll = env->numAvailable - btps + 1;
  2495.                   if (scroll > item_index)
  2496.                      item_index = scroll;
  2497.                   for (z = 0; z < THINGS; z++)
  2498.                     updatew[z] = 1;
  2499.                 }
  2500.               else if (mouse_wheel_current > mouse_wheel_previous)
  2501.                 {
  2502.                   scroll--;
  2503.                   if (scroll < 1)
  2504.                     scroll = 1;
  2505.                   if (item_index > scroll + btps)
  2506.                      item_index = scroll + btps - 3;
  2507.                   for (z = 0; z < THINGS; z++)
  2508.                     updatew[z] = 1;
  2509.                 }
  2510.               mouse_wheel_previous = mouse_wheel_current;
  2511.  
  2512.  
  2513.               if (mouse_x >= global->screenWidth - STUFF_BAR_WIDTH && mouse_x < global->screenWidth)
  2514.                 {
  2515.                   int newlyOver;
  2516.                   zz = 0;
  2517.                   for (z = 1, zzz = scroll; z < btps; z++, zzz++)
  2518.                     {
  2519.                       if (mouse_y >= z * STUFF_BAR_HEIGHT && mouse_y < (z * STUFF_BAR_HEIGHT) + 30)
  2520.                         {
  2521.                           zz = 1;
  2522.                           break;
  2523.                         }
  2524.                     }
  2525.                   if (zz)
  2526.                     newlyOver = env->availableItems[zzz];
  2527.                   else
  2528.                     newlyOver = -1;
  2529.                   if (hoverOver != newlyOver)
  2530.                     {
  2531.                       // char description[1024];
  2532.                       // BOX area = {20, 60, 300, 400};
  2533.  
  2534.                       if (newlyOver > -1)
  2535.                         {
  2536.                           if (newlyOver < WEAPONS)
  2537.                             {
  2538.                               WEAPON *weap = &weapon[newlyOver];
  2539.                               sprintf (description, "Radius: %d\nYield: %ld\n\n%s",
  2540.                                        weap->radius, calcTotalPotentialDamage (newlyOver) * weap->spread, weap->description);
  2541.                             }
  2542.                           else
  2543.                             {
  2544.                               int itemNum = newlyOver - WEAPONS;
  2545.                               ITEM *it = &item[itemNum];
  2546.                               if (itemNum >= ITEM_VENGEANCE && itemNum <= ITEM_FATAL_FURY)
  2547.                                 {
  2548.                                   sprintf (description, "Potential Damage: %ld\n\n%s",
  2549.                                            calcTotalPotentialDamage ((int)it->vals[0]) * (int)it->vals[1],
  2550.                                            it->description);
  2551.                                 }
  2552.                               else
  2553.                                 {
  2554.                                   sprintf (description, "%s", it->description);
  2555.                                 }
  2556.                             }
  2557.                         }
  2558.                       else
  2559.                         {
  2560.                           description[0] = 0;
  2561.                         }
  2562.                       hoverOver = newlyOver;
  2563.  
  2564.                       draw_text_in_box (env, &area, description);
  2565.                     }
  2566.                 }
  2567.               if (mouse_b & 1 && !env->mouseclock)
  2568.                 {
  2569.                   int scrollArrowPos = global->screenWidth - STUFF_BAR_WIDTH - 30;
  2570.                   if (mouse_x >= scrollArrowPos && mouse_x < scrollArrowPos + 24)
  2571.                     {
  2572.                       if ((mouse_y >= global->halfHeight - 50 && mouse_y < global->halfHeight - 25) && (scroll > 1))
  2573.                         {
  2574.                           scroll -= btps / 2;
  2575.                           if (scroll < 1)
  2576.                             scroll = 1;
  2577.                           for (z = 0; z < THINGS; z++)
  2578.                             updatew[z] = 1;
  2579.                         }
  2580.                       if ((mouse_y >= global->halfHeight - 24 && mouse_y < global->halfHeight) && (scroll > 1))
  2581.                         {
  2582.                           scroll--;
  2583.                           for (z = 0; z < THINGS; z++)
  2584.                             updatew[z] = 1;
  2585.                         }
  2586.                       if ((mouse_y >= global->halfHeight + 1 && mouse_y < global->halfHeight + 25) && (scroll <= env->numAvailable - btps))
  2587.                         {
  2588.                           scroll++;
  2589.                           for (z = 0; z < THINGS; z++)
  2590.                             updatew[z] = 1;
  2591.                         }
  2592.                       if ((mouse_y >= global->halfHeight + 25 && mouse_y < global->halfHeight + 50) && (scroll <= env->numAvailable - btps + 1))
  2593.                         {
  2594.                           scroll += btps / 2;
  2595.                           if (scroll > env->numAvailable - btps + 1)
  2596.                             scroll = env->numAvailable - btps + 1;
  2597.                           for (z = 0; z < THINGS; z++)
  2598.                             updatew[z] = 1;
  2599.                         }
  2600.                     }
  2601.                     if (item_index < scroll)
  2602.                        item_index = scroll;
  2603.                     else if ( item_index > (scroll + btps) )
  2604.                        item_index = scroll + btps - 3;
  2605.                 }
  2606.               if (mouse_b & 1 || mouse_b & 2)
  2607.                 {
  2608.                   int itemButtonClicked = 0;
  2609.                   for (int buttonCount = 1, currItem = scroll; buttonCount < btps; buttonCount++, currItem++)
  2610.                     {
  2611.                       if (mouse_x >= global->screenWidth - STUFF_BAR_WIDTH && mouse_x < global->screenWidth && mouse_y >= buttonCount * STUFF_BAR_HEIGHT && mouse_y < (buttonCount * STUFF_BAR_HEIGHT) + 30)
  2612.                         {
  2613.                           itemButtonClicked = 1;
  2614.                           // Remember which button was pressed
  2615.                           if (pressed > -1)
  2616.                             updatew[pressed] = 1;
  2617.                           pressed = env->availableItems[currItem];
  2618.                           updatew[env->availableItems[currItem]] = 1;
  2619.                         }
  2620.                     }
  2621.                   if (!itemButtonClicked)
  2622.                     {
  2623.                       if (pressed > -1)
  2624.                         updatew[pressed] = 1;
  2625.                       pressed = -1;
  2626.                     }
  2627.                 }
  2628.               if (pressed > -1 && !(mouse_b & 1 || mouse_b & 2))
  2629.                 {
  2630.                   // Cost, amount and in-inventory amount
  2631.                   // of pressed item
  2632.                   // int cost,amt,inInv;
  2633.                   bool control_key = false;
  2634.                   updatew[pressed] = 1;
  2635.  
  2636.                   if ( ( key[KEY_LCONTROL] ) || ( key[KEY_RCONTROL] ) )
  2637.                     control_key = true;
  2638.  
  2639.                   if (pressed > WEAPONS - 1)
  2640.                     {
  2641.                       cost = item[pressed - WEAPONS].cost;
  2642.                       amt = item[pressed - WEAPONS].amt;
  2643.                       inInv = global->players[pl]->ni[pressed - WEAPONS];
  2644.                     }
  2645.                   else
  2646.                     {
  2647.                       cost = weapon[pressed].cost;
  2648.                       amt = weapon[pressed].amt;
  2649.                       inInv = global->players[pl]->nm[pressed];
  2650.                     }
  2651.  
  2652.                   if (control_key)
  2653.                     {
  2654.                       cost *= 10;
  2655.                       amt *= 10;
  2656.                     }
  2657.  
  2658.                   if (lastMouse_b & 2)
  2659.                     {
  2660.                       if (inInv + trolley[pressed] >= amt)
  2661.                         {
  2662.                           if (trolley[pressed] >= amt)
  2663.                             {
  2664.                               money += cost;
  2665.                               trolley[pressed] -= amt;
  2666.                               updatename = 1;
  2667.                             }
  2668.                           else
  2669.                             {
  2670.                               if (global->sellpercent > 0.01)
  2671.                                 {
  2672.                                   money += (int)(cost * global->sellpercent);
  2673.                                   trolley[pressed] -= amt;
  2674.                                   updatename = 1;
  2675.                                 }
  2676.                             }
  2677.                         }
  2678.                     }
  2679.                   else
  2680.                     {
  2681.                       if ((money >= cost)
  2682.                           && ( (inInv + trolley[pressed]) < (999 - amt)))
  2683.                         {
  2684.                           if (trolley[pressed] <= -amt)
  2685.                             {
  2686.                               if (global->sellpercent > 0.01)
  2687.                                 {
  2688.                                   money -= (int)(cost * global->sellpercent);
  2689.                                   trolley[pressed] += amt;
  2690.                                   updatename = 1;
  2691.                                 }
  2692.                             }
  2693.                           else
  2694.                             {
  2695.                               money -= cost;
  2696.                               trolley[pressed] += amt;
  2697.                               updatename = 1;
  2698.                               if (inInv + trolley[pressed] > 999)
  2699.                                 trolley[pressed] = 999;
  2700.                             }
  2701.                         }
  2702.                     }
  2703.                   pressed = -1;
  2704.                 }
  2705.               env->mouseclock++;
  2706.               if (env->mouseclock > 5)
  2707.                 env->mouseclock = 0;
  2708.               lastMouse_b = mouse_b;
  2709.             }
  2710.           if (! global->os_mouse) show_mouse (NULL);
  2711.           if (fi)
  2712.             {
  2713.               for (int thing = 0; thing < THINGS; thing++)
  2714.                 updatew[thing] = 1;
  2715.             }
  2716.           if (updatename)
  2717.             {
  2718.               updatename = 0;
  2719.               // env->make_update (global->halfWidth - 315, 0, 400, 30);
  2720.               env->make_update (global->halfWidth - 315, 0, global->screenWidth - 1, 30);
  2721.               draw_sprite (env->db, (BITMAP *) global->gfxData.stuff_bar[0], global->halfWidth - 200, 0);
  2722.               textprintf_ex (env->db, font, global->halfWidth - 190, 5, BLACK, -1, "%s %d: %s", global->ingame->complete_text[10], pl + 1, global->players[pl]->getName ());
  2723.               // textprintf_ex (env->db, font, global->halfWidth - 190, 17, BLACK, -1, "Money: $%d", money);
  2724.               textprintf_ex(env->db, font, global->halfWidth - 190, 17, BLACK, -1, "%s: $%s", global->ingame->complete_text[11], Add_Comma(money));
  2725.               sprintf (buf, "%s: %d/%d", global->ingame->complete_text[12], (int)(global->rounds - global->currentround) + 1, (int)global->rounds);
  2726.               textout_ex (env->db, font, buf, global->halfWidth + 170 - text_length (font, buf), 5, BLACK, -1);
  2727.               sprintf (buf, "%s: %d", global->ingame->complete_text[13], global->players[pl]->score);
  2728.               textout_ex (env->db, font, buf, global->halfWidth + 155 - text_length (font, buf), 17, BLACK, -1);
  2729.             }
  2730.  
  2731.           draw_weapon_list(global, env, global->players[pl], trolley, scroll, (pressed < 0) ? env->availableItems[item_index] : pressed );
  2732.           env->make_update (mouse_x, mouse_y, ((BITMAP *) (global->misc[0]))->w, ((BITMAP *) (global->misc[0]))->h);
  2733.           env->make_update (lx, ly, ((BITMAP *) (global->misc[0]))->w, ((BITMAP *) (global->misc[0]))->h);
  2734.           lx = mouse_x;
  2735.           ly = mouse_y;
  2736.           if (! global->os_mouse) show_mouse (env->db);
  2737.           if (fi)
  2738.             {
  2739.               change (global, env->db);
  2740.               fi = 0;
  2741.             }
  2742.  
  2743.           else
  2744.             env->do_updates ();
  2745.         }
  2746.       for (int tItem = 0; tItem < WEAPONS; tItem++)
  2747.         global->players[pl]->nm[tItem] += trolley[tItem];
  2748.       for (int tItem = WEAPONS; tItem < THINGS; tItem++)
  2749.         global->players[pl]->ni[tItem - WEAPONS] += trolley[tItem];
  2750.       global->players[pl]->money = money;
  2751.     }
  2752.   // clear_keybuf ();
  2753.  
  2754.   for (z = 0; z < global->numPlayers; z++)
  2755.     {
  2756.       int iMoney        = global->players[z]->money;
  2757.       int iInterest = 0;
  2758.       float fIntPerc= 0.0;
  2759.       int iLevel        =    0;
  2760.       int iInterSum = 0; // The summed up interest
  2761. #ifdef DEBUG
  2762.       cout << endl << "======================================================" << endl;
  2763.       printf( (char *)"%2d.: %s enters the bank to get interest:\n", (z+1), global->players[z]->getName());
  2764.       printf( (char *)"     Starting Account: %10d\n", global->players[z]->money);
  2765.       cout << "------------------------------------------------------" << endl;
  2766. #endif // DEBUG
  2767.       while (iMoney && (iLevel < 5))
  2768.         {
  2769.           // Enter next level
  2770.           iLevel++;
  2771.           fIntPerc    =    (global->interest - 1.0) / iLevel;
  2772.           iInterest = (int)((float)iMoney * fIntPerc);
  2773.           // The limit is only applicable on the first four levels, in the fifth level interest is fully applied!
  2774.           if ((iInterest > MAX_INTEREST_AMOUNT) && (iLevel < 5))
  2775.             iInterest = MAX_INTEREST_AMOUNT;
  2776.           // Now sum the interest up and substract the counted money!
  2777.           iInterSum    +=    iInterest;
  2778.           iMoney        -=    (int)((float)iInterest / fIntPerc);
  2779. #ifdef DEBUG
  2780.           printf( (char *)"     Level %1d:  %8d credits are rated,\n", iLevel, (int)(iInterest / fIntPerc));
  2781.           printf( (char *)"     Interest: %8d credits. (%5.2f%%)\n", iInterest, (fIntPerc * 100));
  2782. #endif // DEBUG
  2783.           // To get rid of (possible) rounding errors, add a security check:
  2784.           if ((iMoney < (4 * iLevel)) || (iInterest < 1))
  2785.             iMoney = 0; // With less there won't be any more interest anyway!
  2786. #ifdef DEBUG
  2787.           printf( (char *)"     Unrated : %8d credits left.\n", iMoney);
  2788. #endif // DEBUG
  2789.         }
  2790.       // Now giv'em their money:
  2791. #ifdef DEBUG
  2792.       printf( (char *)"     Sum:      %8d credits.\n", iInterSum);
  2793.       cout << "------------------------------------------------------" << endl;
  2794. #endif // DEBUG
  2795.       global->players[z]->money += iInterSum;
  2796. #ifdef DEBUG
  2797.       printf( (char *)"     Final Account   : %10d\n", global->players[z]->money);
  2798.       cout << "======================================================" << endl;
  2799. #endif // DEBUG
  2800.     }
  2801.     return true;
  2802. }
  2803.  
  2804.  
  2805.  
  2806. #ifdef GETV_IS_EVER_USED
  2807. double getv (int color)
  2808. {
  2809.   float h, s, v;
  2810.   int r, g, b;
  2811.  
  2812.   r = getr (color);
  2813.   g = getg (color);
  2814.   b = getb (color);
  2815.   rgb_to_hsv (r, g, b, &h, &s, &v);
  2816.  
  2817.   return (v);
  2818. }
  2819. #endif //GETV_IS_EVER_USED
  2820.  
  2821.  
  2822.  
  2823. void set_level_settings (GLOBALDATA *global, ENVIRONMENT *env)
  2824. {
  2825.   int taken[MAXPLAYERS];
  2826.   BITMAP *sky_gradient_strip, *land_gradient_strip;
  2827.   int chosen = 0, chosenCount = 0, peak_height = 0;
  2828.   int z, zz; 
  2829.   int objCount;
  2830.   TANK *ltank;
  2831.   int xoffset;
  2832.  
  2833.   // srand (time (NULL));
  2834.  
  2835.   if (! global->os_mouse) show_mouse (NULL);
  2836.   draw_sprite (screen, (BITMAP *) global->misc[1], global->halfWidth - 120, global->halfHeight + 115);
  2837.   textout_centre_ex (screen, font, global->ingame->complete_text[42], global->halfWidth, global->halfHeight + 120, WHITE, -1);
  2838.  
  2839.   // Choose appropriate gradients for sky and land
  2840.   while ((chosenCount < 60) && !chosen)
  2841.     {
  2842.       global->curland = rand () % LANDS;
  2843.       if (global->colour_theme == COLOUR_THEME_CRISPY)
  2844.         global->curland += LANDS;
  2845.       if (!global->gfxData.land_gradient_strips[global->curland])
  2846.         global->gfxData.land_gradient_strips[global->curland] = create_gradient_strip (land_gradients[global->curland], (global->screenHeight - MENUHEIGHT));
  2847.       land_gradient_strip = global->gfxData.land_gradient_strips[global->curland];
  2848.  
  2849.       global->cursky = rand () % SKIES;
  2850.       if (global->colour_theme == COLOUR_THEME_CRISPY)
  2851.         global->cursky += SKIES;
  2852.       if (!global->gfxData.sky_gradient_strips[global->cursky])
  2853.         global->gfxData.sky_gradient_strips[global->cursky] = create_gradient_strip (sky_gradients[global->cursky], (global->screenHeight - MENUHEIGHT));
  2854.       sky_gradient_strip = global->gfxData.sky_gradient_strips[global->cursky];
  2855.  
  2856.       chosen = 1;
  2857.       for (z = 0; z < global->screenWidth; z++)
  2858.         if (peak_height < env->height[z])
  2859.           peak_height = (int)env->height[z];
  2860.       for (z = 0; z <= peak_height; z++)
  2861.         {
  2862.           int skyi, landi;
  2863.           double distance;
  2864.           skyi = getpixel (sky_gradient_strip, 0, (global->screenHeight - MENUHEIGHT - z));
  2865.           landi = getpixel (land_gradient_strip, 0, z);
  2866.  
  2867.           distance = colorDistance (skyi, landi);
  2868.           if (distance < 30)
  2869.             chosen = 0;
  2870.         }
  2871.       chosenCount++;
  2872.     }
  2873.  
  2874.   if (! global->os_mouse) show_mouse (NULL);
  2875.   draw_sprite (screen, (BITMAP *) global->misc[1], global->halfWidth - 120, global->halfHeight + 155);
  2876.   textout_centre_ex (screen, font, global->ingame->complete_text[43], global->halfWidth, global->halfHeight + 160, WHITE, -1);
  2877.   // It looks like we do not use this anymore  xoffset = rand ();
  2878.   //generate_sky (global, env, xoffset, 0, global->screenWidth, global->screenHeight);
  2879.  
  2880.   if (env->sky)
  2881.   {
  2882.      destroy_bitmap(env->sky);
  2883.      env->sky = NULL;
  2884.   } 
  2885.   // see if we want a custom background
  2886.   if ( (env->custom_background) && (env->bitmap_filenames) )
  2887.   {
  2888.      // if ( env->sky) destroy_bitmap(env->sky);
  2889.      env->sky = load_bitmap( env->bitmap_filenames[ rand() % env->number_of_bitmaps ], NULL);
  2890.   }
  2891.  
  2892.   // if we do not have a custom background (or do not want one) create a new background
  2893.   if ( (! env->custom_background) || (! env->sky) )
  2894.   {
  2895.       // if ( env->sky ) destroy_bitmap(env->sky);
  2896. #ifdef THREADS
  2897.       // On Linux we will have a thread creating a sky for us in the background
  2898.       // to avoid wait times. If there is not a pre-created sky waiting for us
  2899.       // then fall back to generating one the regular way.
  2900.       if (env->waiting_sky)
  2901.       {
  2902.            env->sky = env->waiting_sky;
  2903.            env->waiting_sky = NULL;
  2904.       }
  2905.       else
  2906.       {
  2907. #endif
  2908.       env->sky = create_bitmap( global->screenWidth, global->screenHeight - MENUHEIGHT);
  2909.       generate_sky (global, env->sky, sky_gradients[global->cursky],
  2910.                    (global->ditherGradients ? GENSKY_DITHERGRAD : 0 ) |
  2911.                    (global->detailedSky ? GENSKY_DETAILED : 0 )  );
  2912. #ifdef THREADS
  2913.       }
  2914. #endif
  2915.   }
  2916.  
  2917.   if (! global->os_mouse) show_mouse (NULL);
  2918.   draw_sprite (screen, (BITMAP *) global->misc[1], global->halfWidth - 120, global->halfHeight + 195);
  2919.   textout_centre_ex (screen, font, global->ingame->complete_text[44], global->halfWidth, global->halfHeight + 200, WHITE, -1);
  2920.  
  2921.   #ifdef THREADS
  2922.   // we have threads, so check for pre-main terrain
  2923.   if (env->waiting_terrain)
  2924.   {
  2925.       // we have one waiting, so destroy the current one
  2926.       if (env->terrain) destroy_bitmap(env->terrain);
  2927.       env->terrain = env->waiting_terrain;
  2928.       env->waiting_terrain = NULL;        // set this so a new one will be made
  2929.   }
  2930.   else      // one is not waiting, so we need to create one now
  2931.   {
  2932.   #endif
  2933.  
  2934.   clear_to_color (env->terrain, PINK);
  2935.  
  2936.   xoffset = rand ();
  2937.   generate_land (global, env, env->terrain, xoffset, 0, global->screenHeight);
  2938.   #ifdef THREADS
  2939.   }         // end of else
  2940.   #endif
  2941.  
  2942.   for (z = 0; z < global->numTanks; z++)
  2943.     {
  2944.       taken[z] = 0;
  2945.     }
  2946.   for (objCount = 0; (ltank = (TANK*)env->getNextOfClass (TANK_CLASS, &objCount)) && ltank; objCount++)
  2947.     {
  2948.       for (zz = rand () % global->numTanks; taken[zz]; zz = rand () % global->numTanks) { }
  2949.       taken[zz] = objCount + 1;
  2950.       ltank->x = (zz + 1) * (global->screenWidth / (global->numTanks + 1));
  2951.       ltank->y = (global->screenHeight - (int)env->height[(int) ltank->x]) - (TANKHEIGHT - TANKSAG);
  2952.       ltank->newRound ();
  2953.     }
  2954.   for (z = 0; z < MAXPLAYERS; z++)
  2955.     env->order[z] = NULL;
  2956.   global->maxNumTanks = global->numTanks;
  2957.   for (objCount = 0; (ltank = (TANK*)env->getNextOfClass (TANK_CLASS, &objCount)) && ltank; objCount++)
  2958.     {
  2959.       for (z = rand () % global->numTanks; env->order[z]; z = rand () % global->numTanks) { }
  2960.       env->order[z] = ltank;
  2961.     }
  2962.   // if (global->turntype != TURN_RANDOM) {
  2963.   if ( (global->turntype != TURN_RANDOM) &&
  2964.        (global->turntype != TURN_SIMUL))
  2965.     {
  2966.       for (int index = 0; index < global->maxNumTanks - 1; index++)
  2967.         {
  2968.           int swap = FALSE;
  2969.           if (global->turntype == TURN_HIGH)
  2970.             {
  2971.               if (env->order[index]->player->score <
  2972.                   env->order[index + 1]->player->score)
  2973.                 {
  2974.                   swap = TRUE;
  2975.                 }
  2976.             }
  2977.           else if (global->turntype == TURN_LOW)
  2978.             {
  2979.               if (env->order[index]->player->score >
  2980.                   env->order[index + 1]->player->score)
  2981.                 {
  2982.                   swap = TRUE;
  2983.                 }
  2984.             }
  2985.           if (swap)
  2986.             {
  2987.               TANK *tempTank = env->order[index];
  2988.               env->order[index] =
  2989.                 env->order[index + 1];
  2990.               env->order[index + 1] = tempTank;
  2991.               index = -1;
  2992.             }
  2993.         }
  2994.     }
  2995. }
  2996.  
  2997.  
  2998. char *do_winner (GLOBALDATA *global, ENVIRONMENT *env)
  2999. {
  3000.   int maxscore = -1;
  3001.   int winindex = -1;
  3002.   int i, index, *order;
  3003.   bool multiwinner = false;
  3004.   int fonthgt = text_height(font)+10;
  3005.   int jedi_index = -1, sith_index = -1, neutral_index = -1;
  3006.   // char *my_quote;
  3007.   char *return_string = NULL;
  3008.  
  3009.   return_string = (char *) calloc(256, sizeof(char));
  3010.   if (! return_string)
  3011.      return NULL;
  3012.  
  3013.   //find the maxscore and print out winner
  3014.   for (i=0;i<global->numPlayers;i++)
  3015.     {
  3016.       if (global->players[i]->score == maxscore)
  3017.         {
  3018.           multiwinner=true;
  3019.           if (global->players[i]->team == TEAM_NEUTRAL)
  3020.             neutral_index = i;
  3021.         }
  3022.  
  3023.       else if (global->players[i]->score > maxscore)
  3024.         {
  3025.           maxscore = global->players[i]->score;
  3026.           winindex=i;
  3027.           multiwinner=false;
  3028.           if (global->players[i]->team == TEAM_NEUTRAL)
  3029.             neutral_index = i;
  3030.         }
  3031.       if (global->players[i]->team == TEAM_JEDI)
  3032.         jedi_index = i;
  3033.       else if (global->players[i]->team == TEAM_SITH)
  3034.         sith_index = i;
  3035.     }
  3036.  
  3037.   //stop mouse during drawing
  3038.   if (! global->os_mouse) show_mouse (NULL);
  3039.  
  3040.   //draw background and winner bitmap
  3041.   draw_circlesBG (global, env->db, 0, 0, global->screenWidth, global->screenHeight, false);
  3042.   draw_sprite (env->db, (BITMAP *) global->misc[9], global->halfWidth - 150, global->halfHeight - 150);
  3043.  
  3044.   //draw winner names and info about all players
  3045.   int boxtop = global->halfHeight-40;
  3046.   int boxleft = global->halfWidth-200;
  3047.   int boxright = global->halfWidth+280;
  3048.   int boxbottom = boxtop +4+(fonthgt*2)+(fonthgt*global->numPlayers);
  3049.  
  3050.   rectfill (env->db, boxleft, boxtop, boxright, boxbottom, BLACK);
  3051.   rect (env->db, boxleft, boxtop, boxright, boxbottom, WHITE);
  3052.   if (multiwinner)
  3053.     {
  3054.       // check for team win
  3055.       if ( global->players[winindex]->team == TEAM_JEDI )
  3056.         {
  3057.           if ( (sith_index >= 0) && ( (global->players[sith_index]->score == global->players[winindex]->score)) )
  3058.             snprintf(return_string, 256, "%s", global->ingame->complete_text[48]);
  3059.           else if ( (neutral_index >= 0) && ( (global->players[neutral_index]->score == global->players[winindex]->score) ) )
  3060.             snprintf(return_string, 256, "%s", global->ingame->complete_text[48]);
  3061.           else
  3062.             snprintf(return_string, 256, "%s", global->ingame->complete_text[45]);
  3063.         }
  3064.       else if ( global->players[winindex]->team == TEAM_SITH )
  3065.         {
  3066.           if ((jedi_index >= 0) && ((global->players[jedi_index]->score == global->players[winindex]->score)))
  3067.             snprintf(return_string, 256, "%s", global->ingame->complete_text[48]);
  3068.           else if ( (neutral_index >= 0) && ( (global->players[neutral_index]->score == global->players[winindex]->score) ) )
  3069.             snprintf(return_string, 256, "%s", global->ingame->complete_text[48]);
  3070.           else
  3071.             snprintf(return_string, 256, "%s", global->ingame->complete_text[46]);
  3072.         }
  3073.       else
  3074.         snprintf(return_string, 256, "%s", global->ingame->complete_text[48]);
  3075.     }
  3076.   else
  3077.      snprintf(return_string, 256, "%s: %s", global->ingame->complete_text[47],
  3078.              global->players[winindex]->getName() );
  3079.  
  3080.   textprintf_centre_ex(env->db, font, global->halfWidth, boxtop + 4,
  3081.                        global->players[winindex]->color, -1,
  3082.                        "%s", return_string);
  3083.  
  3084.   textout_centre_ex (env->db, font, global->ingame->complete_text[49], global->halfWidth, boxtop+4+fonthgt, WHITE, -1);
  3085.   order = Sort_Scores(global);
  3086.   for (index = 0; index < global->numPlayers; index++)
  3087.     {
  3088.       int i = order[index];
  3089.       int textypos = (index * 10) + boxtop+4+(fonthgt*2);
  3090.       int money;
  3091.  
  3092.       textprintf_ex (env->db, font, boxleft+10, textypos , global->players[i]->color, -1, "%s:", global->players[i]->getName ());
  3093.  
  3094.       money = 0;
  3095.       for (int weapNum = 0; weapNum < WEAPONS; weapNum++)
  3096.         {
  3097.           int individValue;
  3098.           if (weapon[weapNum].amt)
  3099.             individValue = weapon[weapNum].cost / weapon[weapNum].amt;
  3100.           else
  3101.             individValue = 0;
  3102.           money += (int)(individValue * global->players[i]->nm[weapNum]);
  3103.         }
  3104.       for (int itemNum = 0; itemNum < ITEMS; itemNum++)
  3105.         {
  3106.           int individValue;
  3107.           if (item[itemNum].amt)
  3108.             individValue = item[itemNum].cost / item[itemNum].amt;
  3109.           else
  3110.             individValue = 0;
  3111.           money += (int)(individValue * global->players[i]->ni[itemNum]);
  3112.         }
  3113.       textprintf_ex (env->db, font, boxleft+190, textypos, WHITE, -1, "%3d  $%s   %10d :%2d", global->players[i]->score, Add_Comma(money), global->players[i]->kills, global->players[i]->killed);
  3114.     }
  3115.  
  3116.   /*
  3117.   my_quote = global->war_quotes->Get_Random_Line();
  3118.   if (my_quote)
  3119.   {
  3120.      char *little_string;
  3121.      int start_index = 0, to_index = 0;
  3122.      int total_length = strlen(my_quote);
  3123.      int quote_count = 1;
  3124.  
  3125.      little_string = (char *) calloc( total_length + 1, sizeof(char));
  3126.      if (little_string)
  3127.      {
  3128.         do
  3129.         {
  3130.            memset(little_string, '\0', total_length + 1);
  3131.            while ((( my_quote[start_index] != ' ' ) || (to_index < 50) ) && (start_index < total_length) )
  3132.            {
  3133.                little_string[to_index] = my_quote[start_index];
  3134.                to_index++;
  3135.                start_index++;
  3136.            }
  3137.           
  3138.            textprintf_ex(env->db,font,boxleft, boxbottom + (10 * quote_count), WHITE, -1,                          "%s", little_string);
  3139.            to_index = 0;
  3140.            quote_count++;
  3141.            while ( (start_index < total_length) && (my_quote[start_index] == ' ') )
  3142.                 start_index++;
  3143.         } while (start_index < total_length);
  3144.         free(little_string);
  3145.      }   
  3146.   }
  3147.   //do fade and wait for user keypress
  3148.   change (global, env->db);
  3149.   readkey ();
  3150.   // for (i = 0; i < global->numPlayers; i++)
  3151.   //  global->players[i]->type = global->players[i]->type_saved;
  3152.   */
  3153.   return return_string;
  3154. }
  3155.  
  3156.  
  3157.  
  3158. void do_quote(GLOBALDATA *global, ENVIRONMENT *env)
  3159. {
  3160.   char *my_quote;
  3161.   int fonthgt = text_height(font)+10;
  3162.   int boxleft = global->halfWidth-200;
  3163.   int boxtop = global->halfHeight-40;
  3164.   int boxbottom = boxtop +4+(fonthgt*2)+(fonthgt*global->numPlayers);
  3165.  
  3166.   my_quote = global->war_quotes->Get_Random_Line();
  3167.   if (my_quote)
  3168.   {
  3169.      char *little_string;
  3170.      int start_index = 0, to_index = 0;
  3171.      int total_length = strlen(my_quote);
  3172.      int quote_count = 1;
  3173.  
  3174.      little_string = (char *) calloc( total_length + 1, sizeof(char));
  3175.      if (little_string)
  3176.      {
  3177.         do
  3178.         {
  3179.            memset(little_string, '\0', total_length + 1);
  3180.            while ((( my_quote[start_index] != ' ' ) || (to_index < 50) ) && (start_index < total_length) )
  3181.            {
  3182.                little_string[to_index] = my_quote[start_index];
  3183.                to_index++;
  3184.                start_index++;
  3185.            }
  3186.  
  3187.            textprintf_ex(env->db,font,boxleft, boxbottom + (10 * quote_count), WHITE, -1,                          "%s", little_string);
  3188.            to_index = 0;
  3189.            quote_count++;
  3190.            while ( (start_index < total_length) && (my_quote[start_index] == ' ') )
  3191.                 start_index++;
  3192.         } while (start_index < total_length);
  3193.         free(little_string);
  3194.      }
  3195.   }
  3196.  
  3197.   //do fade and wait for user keypress
  3198.   change (global, env->db);
  3199.   readkey ();
  3200.   for (int i = 0; i < global->numPlayers; i++)
  3201.     global->players[i]->type = global->players[i]->type_saved;
  3202.  
  3203. }
  3204.  
  3205.  
  3206.  
  3207.  
  3208. //draws indicaation bar
  3209. void graph_bar (ENVIRONMENT *env, int x, int y, long int col, int actual, int max)
  3210. {
  3211.   rect (env->db, x, y, x + max + 2, y + 8, BLACK);
  3212.   rectfill (env->db, x + 1, y + 1, x + 1 + actual, y + 7, col);
  3213. }
  3214.  
  3215.  
  3216. //draws indication bar - centred
  3217. void graph_bar_center (ENVIRONMENT *env, int x, int y, long int col, int actual, int max)
  3218. {
  3219.   rect (env->db, x, y, x + max + 2, y + 8, BLACK);
  3220.   rectfill (env->db, x + 1 + max / 2, y + 1, x + 1 + actual + max / 2, y + 7, col);
  3221. }
  3222.  
  3223.  
  3224. //Some global parameters
  3225. int ord;
  3226. void loadshields (ENVIRONMENT *env)
  3227. {
  3228.   TANK *tank;
  3229.   int objCount;
  3230.  
  3231.   for (objCount = 0; (tank = (TANK*)env->getNextOfClass (TANK_CLASS, &objCount)) && tank; objCount++)
  3232.     tank->reactivate_shield ();
  3233. }
  3234.  
  3235. void change_wind_strength (ENVIRONMENT *env)
  3236. {
  3237.   if (env->windvariation == 0.0 || (int)env->windstrength == 0)
  3238.     {
  3239.       return;
  3240.     }
  3241.   else
  3242.     {
  3243.       env->wind = env->lastwind + (double)(rand () % (int)(env->windvariation * 100)) / 100 - (env->windvariation / 2);
  3244.       if (env->wind > (env->windstrength / 2))
  3245.         {
  3246.           env->wind = env->windstrength / 2;
  3247.         }
  3248.       else if (env->wind < (-env->windstrength / 2))
  3249.         {
  3250.           env->wind = -env->windstrength / 2;
  3251.         }
  3252.  
  3253.       env->lastwind = env->wind;
  3254.     }
  3255.  
  3256.    // make sure game clients have up to date wind data
  3257.    #ifdef NETWORK
  3258.    char buffer[64];
  3259.    sprintf(buffer, "WIND %f", env->wind);
  3260.    env->_global->Send_To_Clients(buffer);
  3261.    #endif
  3262. }
  3263.  
  3264. TANK *nextturn (GLOBALDATA *global, ENVIRONMENT *env, bool skippingComputerPlay)
  3265. {
  3266.   TANK *tank = NULL;
  3267.   int ordCurrently = ord;
  3268.   static int do_wind = 0;
  3269.   static int next_wind = 0;
  3270.   int index = 0, lowest_index = 0, lowest_shots = INT_MAX;
  3271.  
  3272.   // check whether there currently *are* active tanks first
  3273.   if (global->numTanks)
  3274.     {
  3275.       // find first tank with lowest number of shots fired
  3276.       while ( index < global->maxNumTanks )
  3277.         {
  3278.           if ( env->order[index] )    // make sure tank exists
  3279.             {
  3280.               if ( env->order[index]->shots_fired < lowest_shots )
  3281.                 {
  3282.                   lowest_shots = env->order[index]->shots_fired;
  3283.                   lowest_index = index;
  3284.                 }
  3285.             }
  3286.           index++;
  3287.         }     // end of looking for low index
  3288.  
  3289.  
  3290.       do
  3291.         {
  3292.           ord++;
  3293.           // coming around to the next turn
  3294.           if (ord >= global->maxNumTanks)
  3295.             {
  3296.               ord = 0;
  3297.               doLaunch(global, env);
  3298.               // launch before we change the wind
  3299.               next_wind = 1;
  3300.             }
  3301.  
  3302.         }
  3303.       while ((!env->order[ord]) && (ord != ordCurrently));
  3304.       tank = env->order[ord];
  3305.       global->currTank = tank;
  3306.  
  3307.       if ( tank->shots_fired > lowest_shots )
  3308.         {
  3309.           tank = env->order[lowest_index];
  3310.           global->currTank = tank;
  3311.         }
  3312.  
  3313.       // Wind is blowing :-)
  3314.       // change_wind_strength (env);
  3315.       if ( (global->turntype != TURN_SIMUL) || (do_wind) )
  3316.         {
  3317.           change_wind_strength(env);
  3318.           do_wind = next_wind = 0;
  3319.         }
  3320.       else
  3321.         {
  3322.           do_wind = next_wind;
  3323.           next_wind = 0;
  3324.         }
  3325.     }
  3326.  
  3327.   if (tank)
  3328.     {
  3329.       if (!skippingComputerPlay)
  3330.         {
  3331.           env->make_fullUpdate();
  3332.           env->do_updates();
  3333.         }
  3334.       tank->reactivate_shield ();
  3335.       clear_keybuf();
  3336.       if (global->max_fire_time)
  3337.         {
  3338.           tank->player->time_left_to_fire = global->max_fire_time;
  3339.           tank->player->skip_me = false;
  3340.         }
  3341.     }
  3342.  
  3343.   return tank;
  3344. }
  3345.  
  3346. void showRoundEndScoresAt (GLOBALDATA *global, ENVIRONMENT *env, BITMAP *bitmap, int x, int y, int winner)
  3347. {
  3348.   int z;
  3349.  
  3350.   env->make_update (x - 150, y - 100, 301, 301);
  3351.   rectfill (bitmap, x - 150, y - 100, x + 100, y + 100, BLACK);
  3352.   rect (bitmap, x - 150, y - 100, x + 100, y + 100, WHITE);
  3353.   if (winner == JEDI_WIN)
  3354.     textout_centre_ex (bitmap, font, "Jedi", x - 20, y - 90, WHITE, -1);
  3355.   else if (winner == SITH_WIN)
  3356.     textout_centre_ex (bitmap, font, "Sith", x - 20, y - 90, WHITE, -1);
  3357.   else if (winner == -2)
  3358.     textout_centre_ex (bitmap, font, "Draw", x - 20, y - 90, WHITE, -1);
  3359.   else
  3360.     textprintf_centre_ex (bitmap, font, x - 30, y - 90, global->players[winner]->color, -1, "%s: %s", global->ingame->complete_text[47], global->players[winner]->getName ());
  3361.  
  3362.   textout_centre_ex (bitmap, font, global->ingame->complete_text[50], x - 30, y - 70, WHITE, -1);
  3363.   for (z = 0; z < global->numPlayers; z++)
  3364.     {
  3365.       textprintf_ex (bitmap, font, x - 140, (z * 10) + y - 50, global->players[z]->color, -1, "%s:", global->players[z]->getName ());
  3366.       textprintf_ex (bitmap, font, x + 60, (z * 10) + y - 50, WHITE, -1, "%d", global->players[z]->score);
  3367.     }
  3368. }
  3369.  
  3370. int setSlideColumnDimensions (GLOBALDATA *global, ENVIRONMENT *env, int x, bool reset)
  3371. {
  3372.   int pixelHeight;
  3373.   char    *done    = env->done;
  3374.   int    *dropTo = env->dropTo;
  3375.   int    *h    = env->h;
  3376.   int    *fp    = env->fp;
  3377.   double    *velocity = env->velocity;
  3378.   double    *dropIncr = env->dropIncr;
  3379.  
  3380.   if (x < 0 || x > (global->screenWidth-1))
  3381.     {
  3382.       return (0);
  3383.     }
  3384.  
  3385.   if (reset)
  3386.     {
  3387.       h[x] = 0;
  3388.       fp[x] = 0;
  3389.       dropTo[x] = global->screenHeight - 1;
  3390.     }
  3391.   done[x] = 0;
  3392.  
  3393.   // Calc the top and bottom of the column to slide
  3394.  
  3395.   // Find top-most non-PINK pixel
  3396.   for (pixelHeight = h[x]; pixelHeight < dropTo[x]; pixelHeight++)
  3397.     if (getpixel (env->terrain, x, pixelHeight) != PINK)
  3398.       break;
  3399.   h[x] = pixelHeight;
  3400.   env->surface[x] = pixelHeight;
  3401.  
  3402.   // Find bottom-most PINK pixel
  3403.   for (pixelHeight = dropTo[x]; pixelHeight > h[x]; pixelHeight--)
  3404.     if (getpixel (env->terrain, x, pixelHeight) == PINK)
  3405.       break;
  3406.   dropTo[x] = pixelHeight;
  3407.  
  3408.   // Find bottom-most unsupported pixel
  3409.   for (; pixelHeight >= h[x]; pixelHeight--)
  3410.     if (getpixel (env->terrain, x, pixelHeight) != PINK)
  3411.       break;
  3412.  
  3413.   // If there's some processing to do
  3414.   if ((pixelHeight >= h[x]) && (h[x] < dropTo[x]))
  3415.     {
  3416.       fp[x] = pixelHeight - (int)h[x] + 1;
  3417.       return (0);
  3418.     }
  3419.   else
  3420.     {
  3421.       if (velocity[x])
  3422.         play_sample ((SAMPLE *) global->sounds[10], (int)((velocity[x] / 10) * 255), (int)((double)(x - global->halfWidth) / global->halfWidth * 128 + 128), 1000 - (int)((double)fp[x] / global->screenHeight) * 1000, 0);
  3423.       h[x] = 0;
  3424.       fp[x] = 0;
  3425.       done[x] = 1;
  3426.       velocity[x] = 0;
  3427.       dropIncr[x] = 0;
  3428.       dropTo[x] = global->screenHeight - 1;
  3429.       return (1);
  3430.     }
  3431.   return (0);
  3432. }
  3433.  
  3434.  
  3435. int drawFracture (GLOBALDATA *global, ENVIRONMENT *env, BITMAP *dest, BOX *updateArea, int x, int y, int angle, int width, int segmentLength, int maxRecurse, int recurseDepth)
  3436. {
  3437.   int branchCount;
  3438.   int x1, x2, x3;
  3439.   int y1, y2, y3;
  3440.  
  3441.   x1 = (int)(x + global->slope[angle][0] * width);
  3442.   y1 = (int)(y + global->slope[angle][1] * width);
  3443.   x2 = (int)(x - global->slope[angle][0] * width);
  3444.   y2 = (int)(y - global->slope[angle][1] * width);
  3445.   x3 = (int)(x + global->slope[angle][1] * segmentLength);
  3446.   y3 = (int)(y + global->slope[angle][0] * segmentLength);
  3447.   triangle (dest, x1, y1, x2, y2, x3, y3, PINK);
  3448.  
  3449.   if (recurseDepth == 0)
  3450.     {
  3451.       updateArea->x = x1;
  3452.       updateArea->y = y1;
  3453.       updateArea->w = x1;
  3454.       updateArea->h = y1;
  3455.     }
  3456.   updateArea->x = MIN (MIN (MIN (x1, x2), x3), updateArea->x);
  3457.   updateArea->y = MIN (MIN (MIN (y1, y2), y3), updateArea->y);
  3458.   updateArea->w = MAX (MAX (MAX (x1, x2), x3), updateArea->w);
  3459.   updateArea->h = MAX (MAX (MAX (y1, y2), y3), updateArea->h);
  3460.  
  3461.   if (recurseDepth < maxRecurse)
  3462.     {
  3463.       for (branchCount = 0; branchCount < 3; branchCount++)
  3464.         {
  3465.           if ((branchCount == 0) || (Noise (x + y + branchCount) < 0))
  3466.             {
  3467.               int newAngle, reduction;
  3468.               newAngle = (angle + (int)(Noise (x + y + 4) * 30));
  3469.               while (newAngle < 0)
  3470.                 newAngle += 360;
  3471.               newAngle %= 360;
  3472.  
  3473.               reduction = 2;
  3474.               if (branchCount == 1)
  3475.                 {
  3476.                   newAngle = (int)(angle + 90 +
  3477.                                    (Noise (x + y + 25 + branchCount) * 22.5)) % 360;
  3478.                   reduction = abs ((int)Noise (x + y + 1 + branchCount) * 4 + 3);
  3479.                 }
  3480.               else if (branchCount == 2)
  3481.                 {
  3482.                   newAngle = (int)(angle + 270 +
  3483.                                    (Noise (x + y + 32 + branchCount) * 22.5)) % 360;
  3484.                   reduction = abs ((int)Noise (x + y + 2 + branchCount) * 4 + 3);
  3485.                 }
  3486.               drawFracture (global, env, dest, updateArea, x3, y3, newAngle, width / reduction, segmentLength / reduction, maxRecurse, recurseDepth + 1);
  3487.             }
  3488.         }
  3489.     }
  3490.  
  3491.   // Calculate width and height, previously right and bottom
  3492.   if (recurseDepth == 0)
  3493.     {
  3494.       updateArea->w -= updateArea->x;
  3495.       updateArea->h -= updateArea->y;
  3496.     }
  3497.  
  3498.   return (0);
  3499. }
  3500.  
  3501. /*
  3502. void initSurface (GLOBALDATA *global, ENVIRONMENT *env)
  3503. {
  3504.   int pixelHeight;
  3505.   for (int x = 0; x < global->screenWidth; x++)
  3506.     {
  3507.       for (pixelHeight = 0; pixelHeight < global->screenHeight; pixelHeight++)
  3508.         if (getpixel (env->terrain, x, pixelHeight) != PINK)
  3509.           break;
  3510.       env->surface[x] = pixelHeight;
  3511.     }
  3512. }
  3513. */
  3514.  
  3515.  
  3516. int slideLand (GLOBALDATA *global, ENVIRONMENT *env)
  3517. {
  3518.   char    *done    = env->done;
  3519.   int    *dropTo = env->dropTo;
  3520.   int    *h    = env->h;
  3521.   int    *fp    = env->fp;
  3522.   double    *velocity = env->velocity;
  3523.   double    *dropIncr = env->dropIncr;
  3524.   int zz;
  3525.   double land_slide_type = LANDSLIDE_INSTANT;
  3526.  
  3527.   // land-slide, make it fall etc.
  3528.   int allDone = 1;
  3529.   if ( (env->landSlideType == LANDSLIDE_NONE) ||
  3530.        (env->landSlideType == LANDSLIDE_TANK_ONLY) )
  3531.     return (allDone);
  3532.  
  3533.   else if (env->landSlideType == LANDSLIDE_CARTOON)
  3534.     {
  3535.       if (env->time_to_fall > 0)
  3536.         land_slide_type = LANDSLIDE_CARTOON;
  3537.       else
  3538.         land_slide_type = LANDSLIDE_GRAVITY;
  3539.     }
  3540.  
  3541.   else if (env->landSlideType == LANDSLIDE_GRAVITY)
  3542.     land_slide_type = LANDSLIDE_GRAVITY;
  3543.  
  3544.   if (land_slide_type == LANDSLIDE_CARTOON)
  3545.     return (allDone);
  3546.  
  3547.   for (zz = 0; zz < global->screenWidth; zz++)
  3548.     {
  3549.       if (!done[zz])
  3550.         {
  3551.           allDone = 0;
  3552.           if (land_slide_type == LANDSLIDE_GRAVITY)
  3553.             {
  3554.               if (fp[zz] > 0)
  3555.                 {
  3556.                   velocity[zz] += env->gravity;
  3557.                   dropIncr[zz] += velocity[zz];
  3558.                   if (dropIncr[zz] >= 1)
  3559.                     {
  3560.                       if (dropIncr[zz] > dropTo[zz] - (h[zz] + fp[zz]))
  3561.                         {
  3562.                           dropIncr[zz] = dropTo[zz] - (h[zz] + fp[zz]) + 1;
  3563.                         }
  3564.                       blit (env->terrain, env->terrain, zz, h[zz] - (int)dropIncr[zz], zz, h[zz], 1, fp[zz] + (int)dropIncr[zz]);
  3565.                       env->make_bgupdate (zz, h[zz] - (int)dropIncr[zz], 1, fp[zz] + ((int)dropIncr[zz] * 2) + 1);
  3566.                       env->make_update (zz, h[zz] - (int)dropIncr[zz], 1, fp[zz] + ((int)dropIncr[zz] * 2) + 1);
  3567.                       h[zz] += (int)dropIncr[zz];
  3568.                       dropIncr[zz] -= (int)dropIncr[zz];
  3569.                     }
  3570.                   setSlideColumnDimensions (global, env, zz, FALSE);
  3571.                 }
  3572.               else
  3573.                 {
  3574.                   setSlideColumnDimensions (global, env, zz, FALSE);
  3575.                 }
  3576.             }
  3577.           else if (land_slide_type == LANDSLIDE_INSTANT)
  3578.             {
  3579.               if (fp[zz] > 0)
  3580.                 {
  3581.                   env->make_bgupdate (zz, h[zz], 1, dropTo[zz] - h[zz] + 1);
  3582.                   env->make_update (zz, h[zz], 1, dropTo[zz] - h[zz] + 1);
  3583.                   done[zz] = 1;
  3584.                   blit (env->terrain, env->terrain, zz, h[zz], zz, dropTo[zz] - fp[zz] + 1, 1, fp[zz]);
  3585.                   vline (env->terrain, zz, h[zz], dropTo[zz] - fp[zz], PINK);
  3586.                 }
  3587.               setSlideColumnDimensions (global, env, zz, FALSE);
  3588.             }
  3589.         }
  3590.     }
  3591.  
  3592.   return (allDone);
  3593. }
  3594.  
  3595. void drawTopBar (GLOBALDATA *global, ENVIRONMENT *env, BITMAP *dest)
  3596. {
  3597.   TANK *tank = global->currTank;
  3598.   char *name = "";
  3599.   int color = 0;
  3600.   int wind_col1 = 0, wind_col2 = 0;
  3601.   static int change_weapon_colour = RED;
  3602.   char *team_name = "";
  3603.   int time_to_fire = 0;
  3604.   int minus_font = (font == global->unicode) ? 9 : 0;
  3605.  
  3606.   if (tank)
  3607.     {
  3608.       name = global->currTank->player->getName ();
  3609.       color = global->currTank->player->color;
  3610.       team_name = global->currTank->player->Get_Team_Name();
  3611.       time_to_fire = tank->player->time_left_to_fire;
  3612.     }
  3613.  
  3614.   global->updateMenu = 0;
  3615.   blit (global->gfxData.topbar, dest, 0, 0, 0, 0, global->screenWidth, MENUHEIGHT);
  3616.  
  3617.   if (tank)
  3618.     {
  3619.       textout_ex (dest, font, name, 2, 2 - minus_font, BLACK, -1);
  3620.       textout_ex (dest, font, name, 1, 1 - minus_font, color, -1);
  3621.       textprintf_ex (dest, font, 1, 11 - minus_font, BLACK, -1, "%s", global->ingame->complete_text[18]);
  3622.       graph_bar_center (env, 50, 11, color, -(tank->a - 180) / 2, 180 / 2);
  3623.       // 0 is directly left, 180 points directly right
  3624.       textprintf_ex (dest, font, 150, 11 - minus_font, BLACK, -1, "%d", 180 - (tank->a - 90));
  3625.  
  3626.       textprintf_ex (dest, font, 1, 21 - minus_font, BLACK, -1, "%s", global->ingame->complete_text[19]);
  3627.       graph_bar (env, 50, 20, color, (tank->p) / (MAX_POWER/90), 90);
  3628.       textprintf_ex (dest, font, 150, 21 - minus_font, BLACK, -1, "%d", tank->p);
  3629.       textprintf_ex (dest, font, 200, 21 - minus_font, BLACK, -1, "%s: %s", global->ingame->complete_text[20], team_name);
  3630.       if (tank->cw < WEAPONS)
  3631.       {
  3632.           int weapon_amount;
  3633.  
  3634.           if (! weapon[tank->cw].delay )
  3635.               weapon_amount = tank->player->nm[tank->cw];
  3636.           else
  3637.               weapon_amount = tank->player->nm[tank->cw] / weapon[tank->cw].delay;
  3638.  
  3639.           if (tank->player->changed_weapon)
  3640.             {
  3641.               textprintf_ex (dest, font, 180, 1, change_weapon_colour, -1, "%s: %d",
  3642.                              weapon[tank->cw].name, weapon_amount);
  3643.               // tank->player->nm[tank->cw]);
  3644.               if (change_weapon_colour == RED)
  3645.                 change_weapon_colour = WHITE;
  3646.               else
  3647.                 change_weapon_colour = RED;
  3648.  
  3649.  
  3650.             }
  3651.  
  3652.           else
  3653.             textprintf_ex (dest, font, 180, 1, BLACK, -1,"%s: %d",
  3654.                            weapon[tank->cw].name, weapon_amount);
  3655.  
  3656.         }      // end of less than WEAPONS
  3657.       else
  3658.         {
  3659.           textprintf_ex (dest, font, 180, 1, BLACK, -1, "%s: %d",
  3660.                          item[tank->cw - WEAPONS].name, tank->player->ni[tank->cw - WEAPONS]);
  3661.         }
  3662.       draw_sprite (env->db, (BITMAP *) global->stock[ (tank->cw) ? tank->cw : 1], 700, 1);
  3663.       textprintf_ex (dest, font, 350, 1, BLACK, -1, "$%s", Add_Comma(tank->player->money));
  3664.       textprintf_ex (dest, font, 350, 12, BLACK, -1, "%s: %d", global->ingame->complete_text[21], tank->player->ni[ITEM_FUEL]);
  3665.     }
  3666.  
  3667.   textprintf_ex ( dest, font, 500,  1 - minus_font, BLACK, -1, "%s %d/%d", 
  3668.                   global->ingame->complete_text[12],
  3669.                   (int)(global->rounds - global->currentround) + 1, (int)global->rounds);
  3670.  
  3671.   if (global->tank_status[0])
  3672.     textprintf_ex(dest, font, 350, 21, global->tank_status_colour, -1, "%s",
  3673.                   global->tank_status);
  3674.  
  3675.   if (env->windstrength > 0)
  3676.     {
  3677.       textprintf_ex (dest, font, 500, 11 - minus_font, BLACK, -1, "%s", global->ingame->complete_text[22]);
  3678.       if (env->wind > 0)
  3679.         {
  3680.           wind_col1 = 1;
  3681.           wind_col2 = 0;
  3682.         }
  3683.       if (env->wind < 0)
  3684.         {
  3685.           wind_col1 = 0;
  3686.           wind_col2 = 1;
  3687.         }
  3688.       rect (dest, 540, 12, (int)(540 + env->windstrength * 4 + 2), 18, BLACK);
  3689.       rectfill (dest, (int)(541 + env->windstrength * 2), 13,
  3690.                 (int) (541 + env->wind * 4 + env->windstrength * 2), 17,
  3691.                 makecol (200 * wind_col1, 200 * wind_col2, 0));
  3692.     }
  3693.  
  3694.   if (global->max_fire_time)
  3695.     textprintf_ex( dest, font, 500, 20, BLACK, -1, "Time: %d", time_to_fire);
  3696.  
  3697.   global->stopwindow = 1;
  3698.   env->make_update (0, 0, global->screenWidth, MENUHEIGHT);
  3699.   global->stopwindow = 0;
  3700. }
  3701.  
  3702. /*
  3703.  *  Calculate the effective damage for a given weapon.
  3704.  *  Recursively add the damage of sub-munitions, factor in chaos
  3705.  *    and munition density.
  3706.  */
  3707. long int calcTotalEffectiveDamage (int weapNum)
  3708. {
  3709.   WEAPON *weap = &weapon[weapNum];
  3710.   long int total = 0;
  3711.  
  3712.   if (weap->submunition >= 0)
  3713.     {
  3714.       WEAPON *subm = &weapon[weap->submunition];
  3715.  
  3716.       // How chaotic is this weapon?
  3717.       double chaosVal=(weap->spreadVariation +
  3718.                        weap->speedVariation +
  3719.                        subm->countVariation) / 3;
  3720.       double coverage = (weap->numSubmunitions *
  3721.                          subm->radius) /
  3722.                         (double)weap->radius;
  3723.  
  3724.       total += calcTotalEffectiveDamage (weap->submunition) *
  3725.                weap->numSubmunitions;
  3726.       total = (long int)(total * coverage / weap->numSubmunitions);
  3727.       total -= (long int)((total / 2) * (1.0 - chaosVal));
  3728.     }
  3729.   else
  3730.     {
  3731.       total += weap->damage;
  3732.     }
  3733.  
  3734.   return (total);
  3735. }
  3736.  
  3737. /*
  3738.  *  Calculate the potential damage for a given weapon.
  3739.  *  Recursively add the damage of sub-munitions.
  3740.  */
  3741. long int calcTotalPotentialDamage (int weapNum)
  3742. {
  3743.   WEAPON *weap = &weapon[weapNum];
  3744.   long int total = 0;
  3745.  
  3746.   if ( (weap->submunition >= 0) && (weap->numSubmunitions > 0) )
  3747.     total += calcTotalPotentialDamage (weap->submunition) *
  3748.              weap->numSubmunitions;
  3749.   else
  3750.     total += weap->damage;
  3751.  
  3752.   return (total);
  3753. }
  3754.  
  3755. void doNaturals (GLOBALDATA *global, ENVIRONMENT *env)
  3756. {
  3757.   int chance;
  3758.  
  3759.   if (env->naturals_since_last_shot >= 5)
  3760.     return;
  3761.  
  3762.   if (env->lightning)
  3763.     {
  3764.       chance = (int)(600 / env->lightning) + 100;
  3765.       if (!(rand () % chance))
  3766.         {
  3767.           BEAM *newbeam;
  3768.           int ca = ((rand () % 160) + (360 - 80)) % 360;
  3769.  
  3770.           newbeam = new BEAM (global, env,
  3771.                               rand () % global->screenWidth, 0,
  3772.                               ca, SML_LIGHTNING + (rand () % (int)env->lightning));
  3773.           if (newbeam)
  3774.           {
  3775.             newbeam->player = NULL;
  3776.             env->naturals_since_last_shot++;
  3777.           }
  3778.           else
  3779.               perror ( "atanks.cc: Failed allocating memory for newbeam in doNaturals");
  3780.         }
  3781.     }      // end of lightning
  3782.  
  3783.   // only create meteors  if we are not in aim mode on simul turn type
  3784.   if ( (global->turntype == TURN_SIMUL) && (env->stage == STAGE_AIM) )
  3785.     return;
  3786.  
  3787.   if (env->meteors)
  3788.     {
  3789.       chance = (int)(600 / env->meteors) + 100;
  3790.       if (!(rand () % chance))
  3791.         {
  3792.           MISSILE *newmis;
  3793.           int ca = ((rand () % 160) + (360 - 80)) % 360;
  3794.           double mxv = global->slope[ca][0] * 5;
  3795.           double myv = global->slope[ca][1] * 5;
  3796.  
  3797.           newmis = new MISSILE(global, env,
  3798.                                rand () % global->screenWidth, 0,
  3799.                                mxv, myv, SML_METEOR + (rand () % (int)env->meteors));
  3800.           if (newmis)
  3801.           {
  3802.             newmis->player = NULL;
  3803.             env->naturals_since_last_shot++;
  3804.           }
  3805.           else
  3806.               perror ( "atanks.cc: Failed allocating memory for newmis in doNaturals");
  3807.         }
  3808.     }
  3809.  
  3810.   if (env->falling_dirt_balls)
  3811.     {
  3812.       chance = (int) (600 / env->falling_dirt_balls) + 100;
  3813.       if (! (rand() % chance) )
  3814.         {
  3815.           MISSILE *newmis;
  3816.           int ca = ((rand() % 100) + (360 - 80) ) % 360;
  3817.           double mxv = global->slope[ca][0] * 5;
  3818.           double myv = global->slope[ca][1] * 5;
  3819.  
  3820.           newmis = new MISSILE(global, env,
  3821.                                rand() % global->screenWidth, 0,
  3822.                                mxv, myv, DIRT_BALL + ( rand() % (int) env->falling_dirt_balls) );
  3823.           if (newmis)
  3824.           {
  3825.             newmis->player = NULL;
  3826.             env->naturals_since_last_shot++;
  3827.           }
  3828.           else
  3829.               perror( "atanks.cc: Failed to allocate memory for falling dirt ball in doNaturals");
  3830.         }
  3831.     }
  3832. }
  3833.  
  3834. #ifdef OLD_GAMELOOP
  3835. void game (GLOBALDATA *global, ENVIRONMENT *env)
  3836. {
  3837.   int tanksfall;
  3838.   int tanklife, tlt, dclock;
  3839.   int lb, ca;
  3840.   int allDone, anyExploding, anyTeleporting, anyLaserFiring;
  3841.   int roundEndCount = 0;
  3842.   bool nextTankSelected = false;
  3843.   int humanPlayers = 0;
  3844.   int skippingComputerPlay = FALSE;
  3845.   int team_won = NO_WIN;
  3846.   bool bWinnerIsCredited = false;
  3847.   int my_class;
  3848.   VIRTUAL_OBJECT *my_object;
  3849.  
  3850.   TANK **tank, *ltank;
  3851.   MISSILE *missile;
  3852.   TELEPORT *teleport;
  3853.   DECOR *decor;
  3854.   BEAM *beam;
  3855.   EXPLOSION *explosion;
  3856.   FLOATTEXT *floattext;
  3857.   static SATELLITE *satellite = NULL;
  3858.  
  3859.   int bCount;
  3860.   int z, zz, z4;
  3861.   int objCount, count;
  3862.   int AI_clock = 0;
  3863.  
  3864.   global->computerPlayersOnly = FALSE;
  3865.  
  3866.   tank = &global->currTank;
  3867.  
  3868.   for (int doneCount = 0; doneCount < global->screenWidth; doneCount++)
  3869.     env->done[doneCount] = 0;
  3870.   // initSurface (global, env); // init surface[]
  3871.  
  3872.   env->newRound ();
  3873.   // set wall colour
  3874.   switch (env->current_wallType)
  3875.     {
  3876.     case WALL_RUBBER:
  3877.       env->wallColour = GREEN;
  3878.       break;
  3879.     case WALL_STEEL:
  3880.       env->wallColour = RED;
  3881.       break;
  3882.     case WALL_SPRING:
  3883.       env->wallColour = BLUE;
  3884.       break;
  3885.     case WALL_WRAP:
  3886.       env->wallColour = YELLOW;
  3887.       break;
  3888.     }
  3889.   if (env->dBoxedMode == 2.0)
  3890.     {
  3891.       if (rand() % 2)
  3892.         global->bIsBoxed = true;
  3893.       else
  3894.         global->bIsBoxed = false;
  3895.     }
  3896.   else if (env->dBoxedMode == 1.0)
  3897.     global->bIsBoxed = true;
  3898.   else if (env->dBoxedMode == 0.0)
  3899.     global->bIsBoxed = false;
  3900.   // Set Max velocity
  3901.   global->dMaxVelocity = (double)MAX_POWER * (100.0 / (double)global->frames_per_second) / 100.0;
  3902.   if ((env->current_wallType == WALL_SPRING) && !global->bIsBoxed)
  3903.     // In non-boxed the Spring Wall is allowed to have at least twice the normal velocity
  3904.     global->dMaxVelocity *= 2.0;
  3905.   if (global->bIsBoxed)
  3906.     // In boxed Mode, there is four times the normal max velocity allowed (or it won't be fun!)
  3907.     global->dMaxVelocity *= 4.0;
  3908.   for (count = 0; count < global->numPlayers; count++)
  3909.     global->players[count]->newRound ();
  3910.  
  3911.   /* Unfortunately, ENVIRONMENT can't call uppon FLOATTEXT::newRound due to circular dependencies.
  3912.      Thus we have to do that here: */
  3913.  
  3914.   for (int objCount = 0; objCount < MAX_OBJECTS; objCount++)
  3915.     {
  3916.       if (env->objects[count] && (env->objects[count]->isSubClass(FLOATTEXT_CLASS)))
  3917.         ((FLOATTEXT *)env->objects[count])->newRound();
  3918.     }
  3919.  
  3920.   buystuff (global, env);
  3921.   if (global->close_button_pressed)
  3922.     {
  3923.       global->command = GLOBAL_COMMAND_QUIT;
  3924.       return;
  3925.     }
  3926.  
  3927.   for (count = 0; count < global->numPlayers; count++)
  3928.     global->players[count]->exitShop ();
  3929.  
  3930.   set_level_settings (global, env);
  3931.  
  3932.   for (objCount = 0; (ltank = (TANK*)env->getNextOfClass (TANK_CLASS, &objCount)) && ltank; objCount++)
  3933.     {
  3934.       ltank->newRound ();
  3935.       if ((int)ltank->player->type == HUMAN_PLAYER)
  3936.         {
  3937.           humanPlayers++;
  3938.         }
  3939.     }
  3940.   if (!humanPlayers)
  3941.     {
  3942.       global->computerPlayersOnly = TRUE;
  3943.       //if ((int)global->skipComputerPlay >= SKIP_AUTOPLAY)
  3944.       //    skippingComputerPlay = TRUE;
  3945.     }
  3946.   cclock = lx = ly = tanksfall = 0;
  3947.   env->stage = STAGE_AIM;
  3948.   tlt = global->updateCount = dclock = global->stopwindow = 0;
  3949.   env->realm = env->am = 0;
  3950.   ca = 0;
  3951.   lb = env->mouseclock = env->pclock = 0;
  3952.   ord = 0;
  3953.  
  3954.   *tank = env->order[0];
  3955.   for (objCount = 0; (ltank = (TANK*)env->getNextOfClass (TANK_CLASS, &objCount)) && ltank; objCount++)
  3956.     {
  3957.       ltank->flashdamage = 0;
  3958.       ltank->boost_up_shield ();
  3959.     }
  3960.   winner = tanklife = -1;
  3961.   fi = global->updateMenu = 1;
  3962.   global->window.x = 0;
  3963.   global->window.y = 0;
  3964.   global->window.w = (global->screenWidth-1);
  3965.   global->window.h = (global->screenHeight-1);
  3966.   bCount = 0;
  3967.   if ((int)env->windstrength != 0)
  3968.     env->wind = (float)(rand () % (int)env->windstrength) - (env->windstrength / 2);
  3969.   else
  3970.     env->wind = 0;
  3971.   env->lastwind = env->wind;
  3972.   if ( (env->satellite) && (! satellite) )
  3973.     satellite = new SATELLITE(global, env);
  3974.   if (satellite)
  3975.     satellite->Init();
  3976.  
  3977.   global->iHumanLessRounds = -1;
  3978. #ifdef DEBUG_AIM_SHOW
  3979.   global->bASD = false;
  3980. #endif
  3981.  
  3982.   global->background_music = global->Load_Background_Music();
  3983.   if (global->background_music)
  3984.      play_sample((SAMPLE *) global->background_music, 255, 128, 1000, TRUE);
  3985.  
  3986.   while (1)
  3987.     {
  3988.       LINUX_SLEEP;
  3989.       if (global->close_button_pressed)
  3990.         {
  3991.           global->command = GLOBAL_COMMAND_QUIT;
  3992.           return;
  3993.         }
  3994.  
  3995.       while (cclock > 0 || skippingComputerPlay)
  3996.         {
  3997.           cclock--;
  3998.           if (!lb && mouse_b & 1)
  3999.             env->mouseclock = 0;
  4000.           lb = (mouse_b & 1) ? 1 : 0;
  4001.           bCount += 360/32;
  4002.           z4 = 0;
  4003.           anyExploding    = 0;
  4004.           anyTeleporting  = 0;
  4005.           anyLaserFiring  = 0;
  4006.  
  4007.           env->am = 0;
  4008.           objCount = 0;
  4009.           my_object = env->objects[objCount];
  4010.           // keep track of how long we have been skipping AI
  4011.           if (skippingComputerPlay)
  4012.           {
  4013.              // advance clock
  4014.              if ( global->Check_Time_Changed() )
  4015.                 AI_clock++;
  4016.              if (AI_clock > MAX_AI_TIME)
  4017.              {
  4018.                  int player_index = 0;
  4019.                  // kill all remaining tanks
  4020.                  while (player_index < global->numPlayers)
  4021.                  {
  4022.                     if ( ( global->players[player_index] ) &&
  4023.                          ( global->players[player_index]->tank ) )
  4024.                        global->players[player_index]->tank->l = 0;
  4025.                     player_index++;
  4026.                  }
  4027.              }
  4028.           }       // end of AI clock code
  4029.  
  4030.           while (objCount < MAX_OBJECTS) 
  4031.           {
  4032.             if (my_object)
  4033.             {
  4034.             my_class = my_object->getClass();
  4035.             //for (objCount = 0; (decor = (DECOR*)env->getNextOfClass (DECOR_CLASS, &objCount)) && decor; objCount++)
  4036.             if (my_class == DECOR_CLASS)
  4037.             {
  4038.               decor = (DECOR *) my_object;
  4039.               decor->applyPhysics ();
  4040.               if (decor->destroy)
  4041.                 {
  4042.                   decor->requireUpdate ();
  4043.                   decor->update ();
  4044.                   delete decor;
  4045.                 }
  4046.             }
  4047.           // for (objCount = 0; (explosion = (EXPLOSION*)env->getNextOfClass (EXPLOSION_CLASS, &objCount)) && explosion; objCount++)
  4048.             else if (my_class == EXPLOSION_CLASS)
  4049.             {
  4050.               explosion = (EXPLOSION *) my_object;
  4051.               if (explosion->bIsWeaponExplosion)
  4052.                 anyExploding++;
  4053.               explosion->explode ();
  4054.               explosion->applyPhysics ();
  4055.               if (explosion->destroy)
  4056.                 {
  4057.                   explosion->requireUpdate ();
  4058.                   explosion->update ();
  4059.                   delete explosion;
  4060.                   anyExploding--;
  4061.                 }
  4062.             }
  4063.  
  4064.           // for (objCount = 0; (teleport = (TELEPORT*)env->getNextOfClass (TELEPORT_CLASS, &objCount)) && teleport; objCount++)
  4065.             else if (my_class == TELEPORT_CLASS)
  4066.             {
  4067.               teleport = (TELEPORT *) my_object;
  4068.               anyTeleporting++;
  4069.               teleport->applyPhysics ();
  4070.               if (teleport->destroy)
  4071.                 {
  4072.                   teleport->requireUpdate ();
  4073.                   teleport->update ();
  4074.                   delete teleport;
  4075.                   anyTeleporting--; // It's done!
  4076.                   tanksfall = 1;
  4077.                 }
  4078.             }
  4079.           // env->am = 0;
  4080.           // for (objCount = 0; (missile = (MISSILE*)env->getNextOfClass (MISSILE_CLASS, &objCount)) && missile; objCount++)
  4081.             else if (my_class == MISSILE_CLASS)
  4082.             {
  4083.               TANK *shooting_tank = NULL;
  4084.               BEAM *defense_beam = NULL;
  4085.               int angle_to_fire;
  4086.  
  4087.               missile = (MISSILE *) my_object;
  4088.               env->am++;
  4089.               missile->hitSomething = 0;
  4090.               missile->applyPhysics ();
  4091.               missile->triggerTest ();
  4092.               shooting_tank = missile->Check_SDI(global);
  4093.               if (shooting_tank)
  4094.               {
  4095.                   (shooting_tank->x < missile->x) ? angle_to_fire = 135 : angle_to_fire = 225;
  4096.                   defense_beam = new BEAM(global, env, shooting_tank->x, shooting_tank->y - 10, angle_to_fire, SML_LAZER);
  4097.                   missile->trigger();
  4098.               }
  4099.               if (missile->destroy)
  4100.                 {
  4101.                   missile->requireUpdate ();
  4102.                   missile->update ();
  4103.                   delete missile;
  4104.                   tanksfall = 1;
  4105.                 }
  4106.             }
  4107.           // for (objCount = 0; (beam = (BEAM*)env->getNextOfClass (BEAM_CLASS, &objCount)) && beam; objCount++)
  4108.             else if (my_class == BEAM_CLASS)
  4109.             {
  4110.               beam = (BEAM *) my_object;
  4111.               // As bots should not target while a laser is shot:
  4112.               anyLaserFiring ++;
  4113.               beam->applyPhysics ();
  4114.               if (beam->destroy)
  4115.                 {
  4116.                   beam->requireUpdate ();
  4117.                   beam->update ();
  4118.                   delete beam;
  4119.                   anyLaserFiring--; // It's done!
  4120.                   tanksfall = 1;
  4121.                 }
  4122.             }
  4123.           // for (objCount = 0; (floattext = (FLOATTEXT*)env->getNextOfClass (FLOATTEXT_CLASS, &objCount)) && floattext; objCount++)
  4124.             else if (my_class == FLOATTEXT_CLASS)
  4125.             {
  4126.               floattext = (FLOATTEXT *) my_object;
  4127.               floattext->applyPhysics ();
  4128.               if (floattext->destroy)
  4129.                 {
  4130.                   floattext->requireUpdate();
  4131.                   floattext->update();
  4132.                   delete floattext;
  4133.                   env->make_fullUpdate(); // ...kill remaining texts!
  4134.                 }
  4135.             }
  4136.             }        // end of if we have an object
  4137.             objCount++;
  4138.             my_object = env->objects[objCount];
  4139.           }   // end of going through virtual objects
  4140.  
  4141.  
  4142.           #ifdef NETWORK
  4143.           for (int counter = 0; counter < global->numPlayers; counter++)
  4144.           {
  4145.                if (global->players[counter]->type == NETWORK_CLIENT)
  4146.                {
  4147.                   global->players[counter]->Get_Network_Command();
  4148.                   global->players[counter]->Execute_Network_Command(FALSE);
  4149.                }
  4150.           }
  4151.           #endif
  4152.  
  4153.           if (satellite)
  4154.             satellite->Move();
  4155.  
  4156.           if (!anyExploding)
  4157.             {
  4158.               doNaturals (global, env);
  4159.               if (satellite)
  4160.                 satellite->Shoot();
  4161.             }
  4162.  
  4163.           allDone = slideLand (global, env);
  4164.           if (tanksfall && (env->stage != STAGE_ENDGAME))
  4165.             {
  4166.               for (objCount = 0; (ltank = (TANK*)env->getNextOfClass (TANK_CLASS, &objCount)) && ltank;
  4167.                    count--, objCount++)
  4168.                 {
  4169.                   ltank->pen = 0;
  4170.                   ltank->applyPhysics (global);
  4171.                   if (ltank->l <= 0 && !anyExploding)
  4172.                     {
  4173.                       ltank->explode ();
  4174.                       if (ltank->creditTo)
  4175.                         {
  4176.                           if (ltank->player != ltank->creditTo)      //enemy destroyed
  4177.                             {
  4178.                               ltank->creditTo->money += (int)global->scoreUnitDestroyBonus;
  4179.                             }
  4180.                           else      //self destroy - ugh foolish one :))
  4181.                             {
  4182.                               ltank->creditTo->money -= (int)global->scoreUnitSelfDestroy;
  4183.                               if (ltank->creditTo->money < 0)
  4184.                                 ltank->creditTo->money = 0;
  4185.                             }
  4186.                           ltank->creditTo = NULL;
  4187.                         }
  4188.                       if (ltank->destroy)
  4189.                         {
  4190.                           if ((int)ltank->player->type == HUMAN_PLAYER)
  4191.                             humanPlayers--;
  4192.                           
  4193.                           ltank->Destroy();
  4194.                           delete(ltank);
  4195.  
  4196.                           ltank = NULL; // should not be used anymore, setting NULL for later IF's to checks
  4197.                           if ((!skippingComputerPlay) || (global->numTanks <= 1))
  4198.                             env->make_fullUpdate();
  4199.                           if (!humanPlayers)
  4200.                             {
  4201.                               int iMostIntelligentPlayer = 0;
  4202.                               int iNumPlayers            = 0;
  4203.  
  4204.                               for (int i = 0; i < global->numPlayers; i++)
  4205.                                 {
  4206.                                   int iType = 0;
  4207.  
  4208.                                   if (global->players[i]->tank)
  4209.                                     {
  4210.                                       if (global->players[i]->tank->l > 0)
  4211.                                         {
  4212.                                           iType = (int) global->players[i]->type;
  4213.                                           iNumPlayers++;
  4214.                                         }
  4215.                                     }
  4216.                                   if (iType > iMostIntelligentPlayer)
  4217.                                     iMostIntelligentPlayer = iType;
  4218.                                 }
  4219.                               // If the most intelligent player is more stupid than deadly, raise them all!
  4220.                               if    ( (iMostIntelligentPlayer < (int) DEADLY_PLAYER)
  4221.                                    && (iMostIntelligentPlayer >= (int) USELESS_PLAYER)
  4222.                                    && (iNumPlayers > 1))
  4223.                                 for (int i = 0; i < global->numPlayers; i++)
  4224.                                   {
  4225.                                     if (global->players[i]->tank)
  4226.                                       {
  4227.                                         if (global->players[i]->tank->l > 0)
  4228.                                           global->players[i]->setComputerValues ( (int) DEADLY_PLAYER - iMostIntelligentPlayer);
  4229.                                       }
  4230.                                   }
  4231.  
  4232. #ifdef DEBUG
  4233.                               if ((iMostIntelligentPlayer >= (int)USELESS_PLAYER) && (iNumPlayers > 1))
  4234.                                 {
  4235.                                   cout << endl << "===========================================================" << endl;
  4236.                                   cout << "Round without human players!" << endl;
  4237.                                   cout << "Most intelligent player has Skill level " << iMostIntelligentPlayer << endl;
  4238.                                   cout << "Raised all players by " << ((int)DEADLY_PLAYER - iMostIntelligentPlayer) << " Skill Level(s)" << endl;
  4239.                                   cout << "===========================================================" << endl << endl;
  4240.                                 }
  4241. #endif //DEBUG
  4242.                               // Initialize iHumanLessRounds if not done already
  4243.                               if (global->iHumanLessRounds < 0)
  4244.                                 global->iHumanLessRounds = iNumPlayers * 16;
  4245.                             }
  4246.                           if (!*tank && global->numTanks)
  4247.                             {
  4248.                               *tank = nextturn (global, env, skippingComputerPlay);
  4249.                               while (! *tank)
  4250.                                 *tank = nextturn (global, env, skippingComputerPlay);
  4251.                               (*tank)->fs = 0;
  4252.                               nextTankSelected = true;
  4253.                             }
  4254.                           team_won = Team_Won(global);
  4255.                           if ( (global->numTanks <= 1) || ( team_won ) )
  4256.                             {
  4257.                               skippingComputerPlay = FALSE;
  4258.                               cclock = 0;
  4259.                               env->stage = STAGE_ENDGAME;
  4260.                               global->currTank = NULL;
  4261.                               fi = 1;
  4262.                               global->window.x = 0;
  4263.                               global->window.y = 0;
  4264.                               global->window.w = (global->screenWidth-1);
  4265.                               global->window.h = (global->screenHeight-1);
  4266.                               winner = -2;
  4267.                               if (team_won)
  4268.                                 winner = team_won;
  4269.                               else if (global->numTanks > 0)
  4270.                                 {
  4271.                                   for (z = 0; z < global->numPlayers; z++)
  4272.                                     {
  4273.                                       if (global->players[z]->tank)
  4274.                                         winner = z;
  4275.                                     }
  4276.                                 }
  4277.  
  4278.                               for (objCount = 0; (floattext = (FLOATTEXT*)env->getNextOfClass (FLOATTEXT_CLASS, &objCount)) && floattext; objCount++)
  4279.                                 {
  4280.                                   floattext->newRound();
  4281.                                 }
  4282.  
  4283.                               bCount = 0;
  4284.                               global->updateMenu = 1;
  4285.                               for (z = 0; z < global->numPlayers; z++)
  4286.                                 global->players[z]->played++;
  4287.                             }
  4288.                         }
  4289.                     }
  4290.  
  4291.                   // adjust chess style clock (only if tank wasn't destroyed)
  4292.                   if ( ( global->max_fire_time > 0.0 ) &&
  4293.                        ( ltank ) &&
  4294.                        ( ltank->player->type == HUMAN_PLAYER ) &&
  4295.                        (! env->stage ) )
  4296.                     {
  4297.                       if ( global->Check_Time_Changed() )
  4298.                         {
  4299.                           int ran_out_of_time;
  4300.                           ran_out_of_time = ltank->player->Reduce_Time_Clock();
  4301.                           if (ran_out_of_time && !nextTankSelected)
  4302.                             {
  4303.                               ltank->player->skip_me = true;
  4304.                               *tank = nextturn (global, env, skippingComputerPlay);
  4305.                               while (! *tank)
  4306.                                 *tank = nextturn (global, env, skippingComputerPlay);
  4307.                               (*tank)->fs = 0;
  4308.                               nextTankSelected = true;
  4309.                             }
  4310.                           global->updateMenu = 1;
  4311.                         }
  4312.                     }
  4313.  
  4314.                   if ( ( ltank ) && ( ltank->fire_another_shot ) )
  4315.                   {
  4316.                       if (! (ltank->fire_another_shot % VOLLY_DELAY))
  4317.                         ltank->activateCurrentSelection();
  4318.                       ltank->fire_another_shot--;
  4319.                       if (! ltank->fire_another_shot)
  4320.                          env->stage = 0;
  4321.                   }
  4322.  
  4323.                 }
  4324.             }
  4325.           if (env->stage == 1)
  4326.             {
  4327.               if ((env->am == 0) && allDone && !anyExploding)
  4328.                 {
  4329.                   tanksfall = 0;
  4330.                   env->stage = 2;
  4331.                 }
  4332.             }
  4333.           if (env->stage == 2)
  4334.             {
  4335.               zz = 0;
  4336.  
  4337.               for (objCount = 0; (ltank = (TANK*)env->getNextOfClass (TANK_CLASS, &objCount)) && ltank; count--, objCount++)
  4338.                 {
  4339.                   zz += ltank->applyPhysics (global);
  4340.                 }
  4341.               if (zz == global->numTanks)
  4342.                 {
  4343.                   tanksfall = 1;
  4344.                 }
  4345.               zz = 0;
  4346.               if (tanksfall)
  4347.                 {
  4348.                   for (objCount = 0; (ltank = (TANK*)env->getNextOfClass (TANK_CLASS, &objCount)) && ltank; objCount++)
  4349.                     {
  4350.                       ltank->pen = 0;
  4351.                       if (ltank->l > 0)
  4352.                         zz++;
  4353.                     }
  4354.                 }
  4355.               if (zz == global->numTanks)
  4356.                 {
  4357.                   if (((int)global->skipComputerPlay > SKIP_NONE) &&
  4358.                       (!humanPlayers) && (!global->computerPlayersOnly))
  4359.                     {
  4360.                         skippingComputerPlay = TRUE;
  4361.                         #ifdef NETWORK
  4362.                         int index = 0, network_clients = 0;
  4363.                         while ( (index < global->numPlayers) && (! network_clients) )
  4364.                         {
  4365.                             if (global->players[index]->type == NETWORK_CLIENT)
  4366.                                network_clients++;
  4367.                             else
  4368.                                index++;
  4369.                         }
  4370.                         if (network_clients)
  4371.                           skippingComputerPlay = FALSE;
  4372.                         #endif
  4373.                        if (skippingComputerPlay)
  4374.                        {
  4375.                          draw_sprite (env->db, (BITMAP *) global->misc[1], global->halfWidth - 120, global->halfHeight + 155);
  4376.                          textout_centre_ex (env->db, font, global->ingame->complete_text[51], global->halfWidth, global->halfHeight + 160, WHITE, -1);
  4377.                          draw_sprite (screen, (BITMAP *) global->misc[1], global->halfWidth - 120, global->halfHeight + 155);
  4378.                          textout_centre_ex (screen, font, global->ingame->complete_text[51], global->halfWidth, global->halfHeight + 160, WHITE, -1);
  4379.                        }
  4380.                     }
  4381.                     
  4382.                   env->stage = STAGE_AIM;
  4383.                   winner = -2;
  4384.                   for (z = 0; z < global->numPlayers; z++)
  4385.                     {
  4386.                       if (global->players[z]->tank && winner >= 0)
  4387.                         winner = -1;
  4388.                       if (global->players[z]->tank && winner == -2)
  4389.                         winner = z;
  4390.                     }
  4391.                   if (winner >= 0)
  4392.                     {
  4393.                       global->players[winner]->score++;
  4394.                     }
  4395.                   if (winner == -1)
  4396.                     {
  4397.                       if ((!nextTankSelected || !tank) && global->numTanks)
  4398.                         {
  4399.                           *tank = nextturn (global, env, skippingComputerPlay);
  4400.                           while (! *tank)
  4401.                             *tank = nextturn (global, env, skippingComputerPlay);
  4402.                           (*tank)->fs = 0;
  4403.                         }
  4404.                       nextTankSelected = false;
  4405.                     }
  4406.                   if ((!humanPlayers) && (!global->computerPlayersOnly))
  4407.                     {
  4408.                       global->iHumanLessRounds--;
  4409. #ifdef DEBUG
  4410.                       cout << endl << global->iHumanLessRounds << " Rounds left for the bots to play... " << endl;
  4411. #endif // DEBUG
  4412.                       if ((!global->iHumanLessRounds) && (winner < 1))
  4413.                         {
  4414. #ifdef DEBUG
  4415.                           cout << endl << "=======================" << endl;
  4416.                           cout << "Bots have FINISHED!... " << endl;
  4417.                           cout << "=======================" << endl << endl;
  4418. #endif // DEBUG
  4419.                           global->iHumanLessRounds = -1;
  4420.                           team_won = NO_WIN; // will be determined later
  4421.                           skippingComputerPlay = FALSE;
  4422.                           cclock = 0;
  4423.                           winner = -2;
  4424.                           if (global->numTanks > 0)
  4425.                             {
  4426.                               // The most healthy player wins
  4427.                               int iMaxHealth = 1;
  4428.                               int iHealth = 0;
  4429.                               for (z = 0; z < global->numPlayers; z++)
  4430.                                 {
  4431. #ifdef DEBUG
  4432.                                   cout << z << ".: \"" << global->players[z]->getName() << "\" ";
  4433. #endif // DEBUG
  4434.                                   if (global->players[z]->tank)
  4435.                                     {
  4436.                                       iHealth = global->players[z]->tank->l + global->players[z]->tank->sh;
  4437.                                       if (iHealth > iMaxHealth)
  4438.                                         {
  4439. #ifdef DEBUG
  4440.                                           cout << "has most health! (" << iHealth << ")" << endl;
  4441. #endif // DEBUG
  4442.                                           iMaxHealth = iHealth;
  4443.                                           winner = z;
  4444.                                         }
  4445.                                       else if (iHealth == iMaxHealth)
  4446.                                         winner = -2; // Equal Health == draw!
  4447. #ifdef DEBUG
  4448.                                       else
  4449.                                         cout << "is too weak! (" << iHealth << " max: " << iMaxHealth << ")" << endl;
  4450. #endif // DEBUG
  4451.                                     }
  4452. #ifdef DEBUG
  4453.                                   else
  4454.                                     cout << "has no tank!" << endl;
  4455. #endif //
  4456.                                 }
  4457. #ifdef DEBUG
  4458.                               cout << "winner is player " << winner << " - \"";
  4459.                               if (winner > 0)
  4460.                                 cout << global->players[winner]->getName();
  4461.                               else
  4462.                                 cout << "draw";
  4463.                               cout << "\"" << endl;
  4464. #endif // DEBUG
  4465.                               if (winner > -1)
  4466.                                 {
  4467.                                   if (global->players[winner]->team == TEAM_JEDI)
  4468.                                     {
  4469.                                       team_won = JEDI_WIN;
  4470.                                       winner = JEDI_WIN;
  4471.                                     }
  4472.                                   if (global->players[winner]->team == TEAM_SITH)
  4473.                                     {
  4474.                                       team_won = SITH_WIN;
  4475.                                       winner = SITH_WIN;
  4476.                                     }
  4477.                                 }
  4478.                             }
  4479. #ifdef DEBUG
  4480.                           cout << "Final Decision:" << endl;
  4481.                           if (winner > -1)
  4482.                             {
  4483.                               cout << "\"";
  4484.                               if (winner < 10)
  4485.                                 cout << global->players[winner]->getName();
  4486.                               if (winner == JEDI_WIN)
  4487.                                 cout << "Team Jedi";
  4488.                               if (winner == SITH_WIN)
  4489.                                 cout << "Team Sith";
  4490.                               cout << "\" has won!" << endl;
  4491.                             }
  4492.                           else
  4493.                             cout << "Round Draw!" << endl;
  4494. #endif // DEBUG
  4495.                         }
  4496.                     }
  4497.                   if (winner >= 0 || winner == -2)
  4498.                     {
  4499.                       env->stage = STAGE_ENDGAME;
  4500.                       global->currTank = NULL;
  4501.                       fi = 1;
  4502.                       global->window.x = 0;
  4503.                       global->window.y = 0;
  4504.                       global->window.w = (global->screenWidth-1);
  4505.                       global->window.h = (global->screenHeight-1);
  4506.                     }
  4507.                   bCount = 0;
  4508.                   global->updateMenu = 1;
  4509.                 }
  4510.             }
  4511.           dclock++;
  4512.           if (dclock > 2)
  4513.             {
  4514.               dclock = 0;
  4515.               for (objCount = 0; (ltank = (TANK*)env->getNextOfClass (TANK_CLASS, &objCount)) && ltank; objCount++)
  4516.                 {
  4517.                   if (ltank->flashdamage)
  4518.                     {
  4519.                       if (ltank->flashdamage > 25 || ltank->l < 1)
  4520.                         {
  4521.                           ltank->damage = 0;
  4522.                           ltank->flashdamage = 0;
  4523.                           ltank->requireUpdate ();
  4524.                         }
  4525.                     }
  4526.                 }
  4527.             }
  4528.           env->pclock++;
  4529.           if (env->pclock > 10)
  4530.             env->pclock = 0;
  4531.           if (*tank && !anyTeleporting && !anyLaserFiring)
  4532.             {
  4533.               // if ((*tank)->player->controlTank() == -1)
  4534.               int status = (*tank)->player->controlTank();
  4535.               if (status == -1)
  4536.                 return;
  4537.               else if ( (status == -2) && (!humanPlayers) )
  4538.               {
  4539.                 skippingComputerPlay = TRUE;
  4540.               }
  4541.             }
  4542.           else if (global->computerPlayersOnly &&
  4543.                    ((int)global->skipComputerPlay >= SKIP_HUMANS_DEAD))
  4544.             {
  4545.               if (env->stage == STAGE_ENDGAME)
  4546.                 return;
  4547.             }
  4548.           else if ((keypressed () || mouse_b) && !fi)
  4549.             {
  4550.               if (keypressed ())
  4551.                 k = readkey ();
  4552.               else
  4553.                 k = 0;
  4554.               if ((env->stage == STAGE_ENDGAME) && (roundEndCount >= WAIT_AT_END_OF_ROUND) &&
  4555.                   (mouse_b || k >> 8 == KEY_ENTER || k >> 8 == KEY_ESC || k >> 8 == KEY_SPACE))
  4556.                 return;
  4557.             }
  4558.           env->mouseclock++;
  4559.           if (env->mouseclock > 10)
  4560.             env->mouseclock = 0;
  4561.         }
  4562.       frames++;
  4563.       global->stopwindow = 1;
  4564.       env->make_update (mouse_x, mouse_y, ((BITMAP *) (global->misc[0]))->w, ((BITMAP *) (global->misc[0]))->h);
  4565.       env->make_update (lx, ly, ((BITMAP *) (global->misc[0]))->w, ((BITMAP *) (global->misc[0]))->h);
  4566.       global->stopwindow = 0;
  4567.       lx = mouse_x;
  4568.       ly = mouse_y;
  4569.       set_clip_rect (env->db, 0, 0, (global->screenWidth-1), (global->screenHeight-1));
  4570.       if (! global->os_mouse) show_mouse (NULL);
  4571.       if (global->updateMenu)
  4572.         {
  4573.           set_clip_rect (env->db, 0, 0, (global->screenWidth-1), MENUHEIGHT - 1);
  4574.           drawTopBar (global, env, env->db);
  4575.         }
  4576.       set_clip_rect (env->db, 0, MENUHEIGHT, (global->screenWidth-1), (global->screenHeight-1));
  4577.       if (fi)
  4578.         {
  4579.           blit (env->sky, env->db, global->window.x, global->window.y - MENUHEIGHT, global->window.x, global->window.y, (global->window.w - global->window.x) + 1, (global->window.h - global->window.y) + 1);
  4580.           masked_blit (env->terrain, env->db, global->window.x, global->window.y, global->window.x, global->window.y, (global->window.w - global->window.x) + 1, (global->window.h - global->window.y) + 2);
  4581.         }
  4582.       else
  4583.         {
  4584.           env->replaceCanvas ();
  4585.         }
  4586.  
  4587.       for (objCount = 0, count = 0; (ltank = (TANK*)env->getNextOfClass (TANK_CLASS, &objCount)) && ltank; count++, objCount++)
  4588.         {
  4589.           if (env->stage < STAGE_ENDGAME)
  4590.             {
  4591.               if (*tank == ltank)
  4592.                 {
  4593.                   ltank->draw (env->db, (int)(global->slope[bCount % 360][0] * 4));
  4594.                   ltank->requireUpdate ();
  4595.                 }
  4596.               else
  4597.                 {
  4598.                   ltank->draw (env->db, 0);
  4599.                 }
  4600.               ltank->update ();
  4601.             }
  4602.           ltank->framelyAccounting ();
  4603.         }
  4604.  
  4605.       objCount = 0;
  4606.       my_object = env->objects[objCount];
  4607.       while (objCount < MAX_OBJECTS)
  4608.       {
  4609.           if (my_object)
  4610.           {
  4611.           my_class = my_object->getClass();
  4612.       // for (objCount = 0; (missile = (MISSILE*)env->getNextOfClass (MISSILE_CLASS, &objCount)) && missile; objCount++)
  4613.         if (my_class == MISSILE_CLASS)
  4614.         {
  4615.           missile = (MISSILE *) my_object;
  4616.           missile->draw (env->db);
  4617.           missile->update ();
  4618.         }
  4619.       // for (objCount = 0; (beam = (BEAM*)env->getNextOfClass (BEAM_CLASS, &objCount)) && beam; objCount++)
  4620.         else if (my_class == BEAM_CLASS)
  4621.         {
  4622.           beam = (BEAM *) my_object;
  4623.           beam->draw (env->db);
  4624.           beam->update ();
  4625.         }
  4626.       // for (objCount = 0; (explosion = (EXPLOSION*)env->getNextOfClass (EXPLOSION_CLASS, &objCount)) && explosion; objCount++)
  4627.         else if (my_class == EXPLOSION_CLASS)
  4628.         {
  4629.           explosion = (EXPLOSION *) my_object;
  4630.           explosion->draw (env->db);
  4631.           explosion->update ();
  4632.         }
  4633.       // for (objCount = 0; (teleport = (TELEPORT*)env->getNextOfClass (TELEPORT_CLASS, &objCount)) && teleport; objCount++)
  4634.         else if (my_class == TELEPORT_CLASS)
  4635.         {
  4636.           teleport = (TELEPORT *) my_object;
  4637.           if (teleport->object)
  4638.             teleport->draw (env->db);
  4639.           teleport->update ();
  4640.         }
  4641.       // for (objCount = 0; (decor = (DECOR*)env->getNextOfClass (DECOR_CLASS, &objCount)) && decor; objCount++)
  4642.         else if (my_class == DECOR_CLASS)
  4643.         {
  4644.           decor = (DECOR *) my_object;
  4645.           decor->draw (env->db);
  4646.           decor->update ();
  4647.         }
  4648.       // for (objCount = 0; (floattext = (FLOATTEXT*)env->getNextOfClass (FLOATTEXT_CLASS, &objCount)) && floattext; objCount++)
  4649.         else if (my_class == FLOATTEXT_CLASS)
  4650.         {
  4651.           floattext = (FLOATTEXT *) my_object;
  4652.           floattext->draw (env->db);
  4653.           floattext->requireUpdate ();
  4654.           floattext->update ();
  4655.         }
  4656.         }        // end of if we have an object
  4657.         objCount++;
  4658.         my_object = env->objects[objCount];
  4659.       }      // end of going through objects
  4660.  
  4661.       if (satellite)
  4662.         satellite->Draw(env->db);
  4663.  
  4664.       if (env->stage == STAGE_ENDGAME)
  4665.         {
  4666.           if (roundEndCount < WAIT_AT_END_OF_ROUND + 1)
  4667.             roundEndCount++;
  4668.           if (roundEndCount >= WAIT_AT_END_OF_ROUND)
  4669.             {
  4670.               // check to see if the winner is still alive
  4671.               int tank_index = 0;
  4672.               int alive = false;
  4673.               while ( (! alive) && (tank_index < global->numPlayers) )
  4674.                 {
  4675.                   if ( ( global->players[tank_index]->tank )
  4676.                        &&( global->players[tank_index]->tank->l > 0) )
  4677.                   {
  4678.                     alive = true;
  4679.                   }
  4680.                   tank_index++;
  4681.                 }
  4682.  
  4683.                 // moving this below so dead players lose credit
  4684. //              if (! alive)
  4685. //              {
  4686. //                 winner = -2;
  4687. //              }
  4688.  
  4689.               if (! alive && bWinnerIsCredited)
  4690.                 {
  4691.                   // The score needs to be reduced, of course:
  4692.                   int count;
  4693.                   int iTeamCount = 0;
  4694.                   int iTeamBonus = 0;
  4695.                   if (winner == JEDI_WIN)   // de-credit jedi team
  4696.                     {
  4697.                       for (count = 0; count < global->numPlayers; count++)
  4698.                         {
  4699.                           if (global->players[count]->team == TEAM_JEDI)
  4700.                             {
  4701.                               global->players[count]->score--;
  4702.                               global->players[count]->won--;
  4703.                               iTeamCount++;
  4704.                             }
  4705.                         }
  4706.                     }
  4707.                   else if (winner == SITH_WIN) // de-credit sith team
  4708.                     {
  4709.                       for (count = 0; count < global->numPlayers; count++)
  4710.                         {
  4711.                           if (global->players[count]->team == TEAM_SITH)
  4712.                             {
  4713.                               global->players[count]->score--;
  4714.                               global->players[count]->won--;
  4715.                               iTeamCount++;
  4716.                             }
  4717.                         }
  4718.  
  4719.                     }
  4720.                   else if (winner >= 0)    // de-credit the (ex-)winner
  4721.                     {
  4722.                       global->players[winner]->score--;
  4723.                       global->players[winner]->won--;
  4724.                       global->players[winner]->money -= (int)global->scoreRoundWinBonus;
  4725.                     }
  4726.                   // If it's a team, take away their money now!
  4727.                   if (iTeamCount)
  4728.                     {
  4729.                       iTeamBonus = (int)(global->scoreRoundWinBonus / iTeamCount);
  4730.                       for (count = 0; count < global->numPlayers; count++)
  4731.                         if (    ((winner==JEDI_WIN) && (global->players[count]->team == TEAM_JEDI))
  4732.                              ||((winner==SITH_WIN) && (global->players[count]->team == TEAM_SITH))    )
  4733.                           global->players[count]->money -= iTeamBonus;
  4734.                     }
  4735.                   winner = -2;
  4736.                   bWinnerIsCredited = false; // Or it will be substracted on every loop...
  4737.                 }
  4738.  
  4739.               if (! alive)
  4740.               {
  4741.                  winner = -2;
  4742.               }
  4743.  
  4744.  
  4745.               // if we have a winner, give them credit
  4746.               if (alive && (winner >= 0) && (roundEndCount == WAIT_AT_END_OF_ROUND) && !bWinnerIsCredited)
  4747.                 {
  4748.                   int count;
  4749.                   int iTeamCount = 0;
  4750.                   int iTeamBonus = 0;
  4751.                   if (winner == JEDI_WIN)   // credit jedi team
  4752.                     {
  4753.                       for (count = 0; count < global->numPlayers; count++)
  4754.                         {
  4755.                           if (global->players[count]->team == TEAM_JEDI)
  4756.                             {
  4757.                               global->players[count]->score++;
  4758.                               global->players[count]->won++;
  4759.                               iTeamCount++;
  4760.                             }
  4761.                         }
  4762.                     }
  4763.                   else if (winner == SITH_WIN) // credit sith team
  4764.                     {
  4765.                       for (count = 0; count < global->numPlayers; count++)
  4766.                         {
  4767.                           if (global->players[count]->team == TEAM_SITH)
  4768.                             {
  4769.                               global->players[count]->score++;
  4770.                               global->players[count]->won++;
  4771.                               iTeamCount++;
  4772.                             }
  4773.                         }
  4774.  
  4775.                     }
  4776.                   else    // credit the winner
  4777.                     {
  4778.                       global->players[winner]->score++;
  4779.                       global->players[winner]->won++;
  4780.                       global->players[winner]->money += (int)global->scoreRoundWinBonus;
  4781.                     }
  4782.                   // If it's a team, do give them their money now!
  4783.                   if (iTeamCount)
  4784.                     {
  4785.                       iTeamBonus = (int)(global->scoreRoundWinBonus / iTeamCount);
  4786.                       for (count = 0; count < global->numPlayers; count++)
  4787.                         if (    ((winner==JEDI_WIN) && (global->players[count]->team == TEAM_JEDI))
  4788.                              ||((winner==SITH_WIN) && (global->players[count]->team == TEAM_SITH))    )
  4789.                           global->players[count]->money += iTeamBonus;
  4790.                     }
  4791.                   bWinnerIsCredited = true;
  4792.                 }
  4793.  
  4794.               if ( roundEndCount >= WAIT_AT_END_OF_ROUND )
  4795.                 showRoundEndScoresAt (global, env, env->db, global->screenWidth/2, global->screenHeight/2, winner);
  4796.                  // when we get here and it is a demo, we should bail out
  4797.                  if (global->demo_mode)
  4798.                     return;
  4799.             }
  4800.         }
  4801.       // This four values are used to reduce access to global and increase readability (Easier to debug this way!)
  4802.       int iLeft = 0;
  4803.       int iRight = global->screenWidth - 1;
  4804.       int iTop = MENUHEIGHT;
  4805.       int iBottom = global->screenHeight - 1;
  4806.       set_clip_rect (env->db, 0, 0, iRight, iBottom);
  4807.       vline(env->db, iLeft, iTop, iBottom, env->wallColour);    // Left edge
  4808.       vline(env->db, iRight, iTop, iBottom, env->wallColour);    // right edge
  4809.       hline(env->db, iLeft, iBottom, iRight, env->wallColour);// bottom edge
  4810.       if (global->bIsBoxed)
  4811.         hline(env->db, iLeft, iTop, iRight, env->wallColour);// top edge
  4812.       if (! global->os_mouse) show_mouse (env->db);
  4813.       if (fi)
  4814.         {
  4815.           while (keypressed ())
  4816.             {
  4817.               readkey ();
  4818.             }
  4819.           fi = 0;
  4820.  
  4821.           // if (env->fog) {
  4822.           //    clear_to_color (screen, makecol (128,128,128));
  4823.           // } else {
  4824.           quickChange (global, env->db);
  4825.           // }
  4826.         }
  4827.       else
  4828.         {
  4829.           env->do_updates ();
  4830.           global->window.x = global->screenWidth;
  4831.           global->window.y = global->screenHeight;
  4832.           global->window.w = -1;
  4833.           global->window.h = -1;
  4834.         }
  4835. #ifdef DEBUG_AIM_SHOW
  4836.       if (!global->bASD)
  4837.         global->bASD = true; // Now it is allowed to be true
  4838. #endif
  4839.     }
  4840. }
  4841. #endif // old gameloop
  4842.  
  4843.  
  4844. void print_text_help()
  4845. {
  4846.   cout    << "-h\tThis screen\n"
  4847.        << "-fs\tFull screen\n"
  4848.        << "--windowed\tRun in a window\n"
  4849.        << "-w <width> or --width <width>\tSpecify the screen width in pixels\n"
  4850.        << "-t <height> --tall <height>\tSpecify the screen height in pixels\n"
  4851.        << "\tAdjust the screen size at your own risk (default is 800x600)\n"
  4852.        << "-d <depth> or --depth <depth>\tCurrently either 16 or 32\n"
  4853.        << "--datadir <data directory>\t Path to the data directory\n"
  4854.        << "-c <config directory>\t Path to config and saved game directory\n"
  4855.        << "--noconfig\t Do not load game settings from the config file.\n"
  4856.        << "--nosound\t Disable sound\n"
  4857.        << "--noname\t Do not show player name above tank\n"
  4858.        << "--nonetwork\t Do not allow the game to accept network connection.\n"
  4859.        << "--nobackground\t Do not display the green menu background.\n"
  4860.        << "--nothread\t Do not use threads to perform background tasks.\n"
  4861.        << "--thread\t Do use threads to perform background tasks.\n";
  4862. }
  4863.  
  4864. void print_text_initmsg()
  4865. {
  4866.   printf ( "Atomic Tanks Version %s (-h for help)\n", VERSION);
  4867.   printf ( "Authors: \tTom Hudson (rewrite, additions, improvements)\n");
  4868.   printf ( "\t\tStevante Software (original design)\n");
  4869.   printf ( "\t\tKota543 Software (fixes and updates)\n");
  4870.   printf ( "\t\tJesse Smith (additions, fixes and updates)\n");
  4871.   printf ( "\t\tSven Eden (ai rewrite, additions, fixes and updates)\n\n");
  4872.  
  4873.   // putchar ('\n');
  4874. }
  4875.  
  4876. void endgame_cleanup (GLOBALDATA *global, ENVIRONMENT *env)
  4877. {
  4878.   while (global->numPlayers > 0)
  4879.     {
  4880.       if (global->players[0]->tank)
  4881.         delete(global->players[0]->tank);
  4882.       // make sure networked clients say good-bye and return to old AI level
  4883.       if (global->players[0]->type >= NETWORK_CLIENT)
  4884.          global->players[0]->type = global->players[0]->previous_type;
  4885.  
  4886.       global->players[0]->tank = NULL;
  4887.       global->removePlayer(global->players[0]);
  4888.     }
  4889.   for (int objCount = 0; objCount < MAX_OBJECTS; objCount++)
  4890.     {
  4891.       if (env->objects[objCount])
  4892.         {
  4893.           delete(env->objects[objCount]);
  4894.           env->objects[objCount] = NULL;
  4895.         }
  4896.     }
  4897. }
  4898.  
  4899.  
  4900. /*
  4901. This function calls the functions which save data to a text file.
  4902. The function requires the global data, environment and the path to
  4903. the config file name.
  4904. The function returns TRUE on success and FALSE on failure.
  4905. -- Jesse
  4906. */
  4907. int Save_Game_Settings_Text(GLOBALDATA *global, ENVIRONMENT *env, char *text_file)
  4908. {
  4909.   FILE *my_file;
  4910.  
  4911.   my_file = fopen(text_file, (char *)"w");
  4912.   if (! my_file)
  4913.   {
  4914.       perror ( "Error trying to open text file for writing.\n");
  4915.       return FALSE;
  4916.     }
  4917.  
  4918.   global->saveToFile_Text (my_file);
  4919.   env->saveToFile_Text (my_file);
  4920.   savePlayers_Text (global, my_file);
  4921.   fclose (my_file);
  4922.   return TRUE;
  4923. }
  4924.  
  4925. /*
  4926. This function detects changes to the global settings (mouse and sound)
  4927. and, if a change has happened, makes the required changes to the
  4928. game environment.
  4929. The function returns TRUE.
  4930. -- Jesse
  4931. */
  4932. int Change_Settings(double old_mouse, double old_sound, double new_mouse, double new_sound, void *mouse_image)
  4933. {
  4934.   BITMAP *my_mouse_image = (BITMAP *) mouse_image;
  4935.  
  4936.   // first, check for a change in the sound settings
  4937.   if (old_sound != new_sound)
  4938.     {
  4939.       if (new_sound > 0.0)    // we turned ON sound
  4940.       {
  4941.             if (detect_digi_driver(DIGI_AUTODETECT))
  4942.             {
  4943.                 if (install_sound (DIGI_AUTODETECT, MIDI_NONE, NULL) < 0)
  4944.                     fprintf (stderr, "install_sound: failed turning on sound\n");
  4945.             }
  4946.             else
  4947.                 fprintf (stderr, "detect_digi_driver found no sound device\n");
  4948.  
  4949. //          if (install_sound (DIGI_AUTODETECT, MIDI_NONE, NULL) < 0)
  4950. //            {
  4951. //              fprintf (stderr, "install_sound: %s", allegro_error);
  4952. //            }
  4953.       }
  4954.       else if (new_sound == 0.0)  // we turned OFF sound
  4955.         {
  4956.           remove_sound();
  4957.         }
  4958.     }
  4959.  
  4960.   // check for a change in mouse settings
  4961.   if (old_mouse != new_mouse)
  4962.     {
  4963.       if (new_mouse > 0.0)   // use OS cursor
  4964.         {
  4965.           set_mouse_sprite(NULL);
  4966.           show_os_cursor(MOUSE_CURSOR_ARROW);
  4967.         }
  4968.       else if (new_mouse == 0.0)     // use Allgero cursor
  4969.         {
  4970.           set_mouse_sprite (my_mouse_image);
  4971.           set_mouse_sprite_focus (0, 0);
  4972.         }
  4973.     }
  4974.   return TRUE;
  4975. }
  4976.  
  4977.  
  4978.  
  4979.  
  4980.  
  4981.  
  4982. /*
  4983. This function catches the close command, usually given by
  4984. the user pressing the close window button. We'll
  4985. try to clean-up.
  4986.  
  4987. Note: This function causes the app to hang in Windows.
  4988. Make this compile on non-Windows systems only.
  4989. */
  4990. void close_button_handler(void)
  4991. {
  4992.   // allegro_exit();
  4993.   // exit(0);
  4994.   my_global->close_button_pressed = true;
  4995. }
  4996.  
  4997. int main (int argc, char **argv)
  4998. {
  4999.   int signal;
  5000.   int status;
  5001.   string tmp;
  5002.   ENVIRONMENT *env = NULL;
  5003.   GLOBALDATA *global = NULL;
  5004.   ifstream configFile;
  5005.   char fullPath[2048];
  5006.   bool load_config_file = true;
  5007.   bool bLoadingSuccess = false;
  5008.   cmdTokens nextToken = ARGV_NOTHING_EXPECTED;
  5009.   double temp_mouse, temp_sound;       // I wish I was not using these
  5010.   int menu_action;
  5011.   int playerCount, player_index;
  5012.   #ifdef NETWORK
  5013.   SEND_RECEIVE_TYPE *send_receive = NULL;
  5014.   int client_socket = -1;
  5015.   #endif
  5016.   bool allow_network = true, allow_thread = false;
  5017.   double music_place_holder;
  5018.   double full_screen = FULL_SCREEN_EITHER;
  5019.  
  5020.   quit_right_now = false;
  5021.   global = new GLOBALDATA ();
  5022.   if (!global)
  5023.     {
  5024.       perror ( "Allocating global");
  5025.       exit (1);
  5026.     }
  5027.   my_global = global;
  5028.   print_text_initmsg();
  5029.  
  5030.   // try to find data dir
  5031.   if (! global->Find_Data_Dir() )
  5032.      printf("Could not find data dir.\n");
  5033.  
  5034.   if (argc >= 2)          /* Parse command-line switches */
  5035.     {
  5036.       for (int argument = 1; argument < argc; argument++)
  5037.         {
  5038.           tmp = argv[argument];
  5039.  
  5040.           if (nextToken == ARGV_GFX_DEPTH)
  5041.             {
  5042.               global->colourDepth = strtol (tmp.c_str(), NULL, 10);
  5043.               if (global->colourDepth != 16 &&
  5044.                   global->colourDepth != 32)
  5045.                 {
  5046.                   cout << "Invalid graphics depth, only 16 or 32 are valid\n";
  5047.                   print_text_help();
  5048.                   return 0;
  5049.                 }
  5050.               nextToken = ARGV_NOTHING_EXPECTED;
  5051.             }
  5052.           else if (nextToken == ARGV_SCREEN_WIDTH)
  5053.             {
  5054.               global->screenWidth = strtol (tmp.c_str(), NULL, 10);
  5055.               if (global->screenWidth < 512)
  5056.                 {
  5057.                   cout << "Width too small (minimum 512)\n";
  5058.                   return 0;
  5059.                 }
  5060.               global->width_override = global->screenWidth;
  5061.               global->halfWidth = global->screenWidth / 2;
  5062.               nextToken = ARGV_NOTHING_EXPECTED;
  5063.             }
  5064.           else if (nextToken == ARGV_SCREEN_HEIGHT)
  5065.             {
  5066.               global->screenHeight = strtol (tmp.c_str(), NULL, 10);
  5067.               if (global->screenHeight < 320)
  5068.                 {
  5069.                   cout << "Height too small (minimum 320)\n";
  5070.                   return 0;
  5071.                 }
  5072.               global->height_override = global->screenHeight;
  5073.               global->halfHeight = global->screenHeight / 2;
  5074.               nextToken = ARGV_NOTHING_EXPECTED;
  5075.             }
  5076.           else if (nextToken == ARGV_DATA_DIR)
  5077.             {
  5078.               // Would use strndup, but the win compiler
  5079.               //   doesn't know of it.
  5080.               if (strlen (tmp.c_str()) > 2048)
  5081.                 {
  5082.                   cout << "Datadir path too long:\n"
  5083.                        << "\"" << tmp
  5084.                        << "\"\n\n"
  5085.                        << "Maximum length 2048 characters\n";
  5086.                   return 0;
  5087.                 }
  5088.               global->dataDir = strdup (tmp.c_str());
  5089.               nextToken = ARGV_NOTHING_EXPECTED;
  5090.             }
  5091.           else if (nextToken == ARGV_CONFIG_DIR)
  5092.             {
  5093.               if (strlen (tmp.c_str()) > 2048)
  5094.                 {
  5095.                   cout << "Configdir path too long:\n"
  5096.                        << "\"" << tmp
  5097.                        << "\"\n\n"
  5098.                        << "Maximum length 2048 characters\n";
  5099.                   return 0;
  5100.                 }
  5101.               global->configDir = strdup ( tmp.c_str() );
  5102.               nextToken = ARGV_NOTHING_EXPECTED;
  5103.             }
  5104.           if ( (tmp == SWITCH_HELP) || (tmp == "--help") )
  5105.             {
  5106.               print_text_help();
  5107.               return 0;
  5108.             }
  5109.           else if (tmp == SWITCH_FULL_SCREEN)
  5110.             {
  5111.               screen_mode = GFX_AUTODETECT_FULLSCREEN;
  5112.               full_screen = FULL_SCREEN_TRUE;
  5113.             }
  5114.           else if (tmp == SWITCH_WINDOWED)
  5115.             {
  5116.               screen_mode = GFX_AUTODETECT_WINDOWED;
  5117.               full_screen = FULL_SCREEN_FALSE;
  5118.             }
  5119.           else if (tmp == "-d" || tmp == "--depth")
  5120.             {
  5121.               nextToken = ARGV_GFX_DEPTH;
  5122.             }
  5123.           else if (tmp == "-w" || tmp == "--width")
  5124.             {
  5125.               nextToken = ARGV_SCREEN_WIDTH;
  5126.             }
  5127.           else if (tmp == "-t" || tmp == "--tall")
  5128.             {
  5129.               nextToken = ARGV_SCREEN_HEIGHT;
  5130.             }
  5131.           else if (tmp == "--datadir")
  5132.             {
  5133.               nextToken = ARGV_DATA_DIR;
  5134.             }
  5135.           else if (tmp == "-c")
  5136.             {
  5137.               nextToken = ARGV_CONFIG_DIR;
  5138.             }
  5139.           else if (tmp == "--noconfig")
  5140.             {
  5141.               nextToken = ARGV_NOTHING_EXPECTED;
  5142.               load_config_file = false;
  5143.             }
  5144.           else if (tmp == "--nosound")
  5145.             {
  5146.               nextToken = ARGV_NOTHING_EXPECTED;
  5147.               global->sound = 0.0;
  5148.             }
  5149.           else if (tmp == "--noname")
  5150.             {
  5151.               nextToken = ARGV_NOTHING_EXPECTED;
  5152.               global->name_above_tank = FALSE;
  5153.             }
  5154.           else if (tmp == "--nonetwork")
  5155.           {
  5156.              allow_network = false;
  5157.              nextToken = ARGV_NOTHING_EXPECTED;
  5158.           }
  5159.           else if (tmp == "--nobackground")
  5160.           {
  5161.              global->draw_background = FALSE;
  5162.              nextToken = ARGV_NOTHING_EXPECTED;
  5163.           }
  5164.           else if (tmp == "--nothread")
  5165.           {
  5166.              allow_thread = false;
  5167.              nextToken = ARGV_NOTHING_EXPECTED;
  5168.           }
  5169.           else if (tmp == "--thread")
  5170.           {
  5171.              allow_thread = true;
  5172.              nextToken = ARGV_NOTHING_EXPECTED;
  5173.           }
  5174.  
  5175.         }
  5176.       if (nextToken != ARGV_NOTHING_EXPECTED)
  5177.         {
  5178.           cout << "Expecting an argument to follow " << tmp << endl;
  5179.           return 0;
  5180.         }
  5181.     }
  5182.  
  5183.   if (! global->configDir)
  5184.     {
  5185.       global->configDir = global->Get_Config_Path();
  5186.  
  5187.       // copy the file over, if we did not yet
  5188.       if (!Copy_Config_File(global))
  5189.         {
  5190.           // If it did not work, look whether the directory already exists:
  5191.           DIR * pDestDir;
  5192.           pDestDir = opendir(global->configDir);
  5193.           if (!pDestDir)
  5194.             printf( "An error has occured trying to set up Atomic Tank folders.\n");
  5195.           else
  5196.             {
  5197.               closedir(pDestDir);
  5198.               pDestDir = NULL;
  5199.             }
  5200.         }
  5201.     }       // end of no config file on the command line
  5202.  
  5203.  
  5204.  
  5205.   memset(fullPath, '\0', sizeof(fullPath));
  5206.   FILE *old_config_file = NULL;
  5207.   snprintf(fullPath, sizeof(fullPath) - 1, "%s/atanks-config.txt", global->configDir);
  5208.      old_config_file = fopen(fullPath, "r");
  5209.      if (old_config_file)
  5210.      {
  5211.          global->loadFromFile_Text(old_config_file);
  5212.          // over-ride full screen setting with command line
  5213.          if ( (full_screen == FULL_SCREEN_TRUE) || (full_screen == FULL_SCREEN_FALSE) )
  5214.             global->full_screen = full_screen;
  5215.          env = init_game_settings(global);
  5216.          if (global->os_mouse)
  5217.              show_os_cursor(MOUSE_CURSOR_ARROW); 
  5218.          global->Load_Text_Files();
  5219.          env->loadFromFile_Text(old_config_file);
  5220.          loadPlayers_Text(global, env, old_config_file); 
  5221.          fclose(old_config_file);
  5222.          bLoadingSuccess = true;
  5223.      }
  5224.      
  5225.  
  5226.   if (!bLoadingSuccess)         // no config file found or failed to load
  5227.     {
  5228.       global->numPermanentPlayers = 0;
  5229.       if ( (full_screen == FULL_SCREEN_TRUE) || (full_screen == FULL_SCREEN_FALSE) )
  5230.           global->full_screen = full_screen;
  5231.       env = init_game_settings (global);  
  5232.       global->Load_Text_Files();
  5233.       if (global->os_mouse) show_os_cursor(MOUSE_CURSOR_ARROW);
  5234.       char *defaultNames[] =
  5235.       {
  5236.         "Caesar",
  5237.         "Alex",
  5238.         "Hatshepsut",
  5239.         "Patton",
  5240.         "Napoleon",
  5241.         "Attila",
  5242.         "Catherine",
  5243.         "Hannibal",
  5244.         "Stalin",
  5245.         "Mao"
  5246.       };
  5247.       PLAYER *tempPlayer;
  5248.       tempPlayer = global->createNewPlayer (env);
  5249.       tempPlayer->setName ( global->ingame->complete_text[52] );
  5250.       options (global, env, (MENUDESC*)tempPlayer->menudesc);
  5251.       for (int count = 0; count < 10; count++)
  5252.         {
  5253.           tempPlayer = global->createNewPlayer (env);
  5254.           tempPlayer->type = rand () % (LAST_PLAYER_TYPE - 1) + 1;
  5255.           tempPlayer->setName (defaultNames[count]);
  5256.           tempPlayer->generatePreferences();
  5257.         }
  5258.     }
  5259.  
  5260.   status = Load_Weapons_Text(global);
  5261.   if (! status)
  5262.   {
  5263.       printf( "An error occured trying to read weapons file.\n");
  5264.       exit(1);
  5265.   }
  5266.  
  5267.   snprintf(fullPath, sizeof(fullPath) - 1, "%s/atanks-config.txt", global->configDir); 
  5268.   global->temp_screenWidth = global->screenWidth;
  5269.   global->temp_screenHeight = global->screenHeight;
  5270.   global->halfWidth = global->screenWidth / 2;
  5271.   global->halfHeight = global->screenHeight / 2;
  5272.   global->menuBeginY = (global->screenHeight - 400) / 2;
  5273.   if (global->menuBeginY < 0) global->menuBeginY = 0;
  5274.   global->menuEndY = global->screenHeight - global->menuBeginY;
  5275.  
  5276.   title (global);
  5277.   env->bitmap_filenames = Find_Bitmaps(global, & (env->number_of_bitmaps) );
  5278.   env->my_sky_gradients = (const gradient **) sky_gradients;
  5279.   env->my_land_gradients = (const gradient **) land_gradients;
  5280.   Create_Music_Folder(global);
  5281. #ifdef THREADS
  5282.   if (allow_thread)
  5283.   {
  5284.   pthread_t sky_thread, terrain_thread;
  5285.   pthread_create( &sky_thread, NULL, Generate_Sky_In_Background, (void *) env);
  5286.   pthread_create( &terrain_thread, NULL, Generate_Land_In_Background, (void *) env);
  5287.   }    // end of allowing threads
  5288. #endif
  5289.  
  5290.   // new networking area
  5291.   #ifdef THREADS
  5292.   #ifdef NETWORK
  5293.   pthread_t network_thread;
  5294.   if (global->check_for_updates)
  5295.   {
  5296.          global->update_string = Check_For_Update("projects.sourceforge.net",
  5297.                  "version.txt", "atanks.sourceforge.net", VERSION);
  5298.   }
  5299.  
  5300.   if ( (global->enable_network) && (allow_network) )
  5301.   {
  5302.       send_receive = (SEND_RECEIVE_TYPE *) calloc(1, sizeof(SEND_RECEIVE_TYPE));
  5303.       if (! send_receive)
  5304.          printf("Could not create networking data.\n");
  5305.   }
  5306.   else
  5307.       send_receive = NULL;
  5308.   if (send_receive)
  5309.   {
  5310.      send_receive->listening_port = (int) global->listen_port;
  5311.      send_receive->global = global;
  5312.      // quit option already cleared by calloc call
  5313.      pthread_create( &network_thread, NULL, Send_And_Receive, (void *) send_receive);
  5314.   }
  5315.   #endif
  5316.   #endif
  5317.    
  5318.   do
  5319.     {
  5320.       //show the main menu
  5321.       global->command = GLOBAL_COMMAND_MENU;
  5322.       signal = menu (global, env);
  5323.       if (global->client_message)
  5324.       {
  5325.          free(global->client_message);
  5326.          global->client_message = NULL;
  5327.       }
  5328.  
  5329.       // did the user signal to quit the game
  5330.       if (signal == SIG_QUIT_GAME) global->command = GLOBAL_COMMAND_QUIT;
  5331.  
  5332.       //determine which menu item is selected
  5333.       switch (global->command)
  5334.         {
  5335.         case GLOBAL_COMMAND_HELP:
  5336.           scrollTextList (global, env, global->instructions);
  5337.           break;
  5338.         case GLOBAL_COMMAND_OPTIONS:
  5339.           // save old settings
  5340.           temp_mouse = global->os_mouse;
  5341.           temp_sound = global->sound;
  5342.  
  5343.           options(global, env, NULL);
  5344.           if (! Save_Game_Settings_Text(global, env, fullPath))
  5345.           {
  5346.               perror ( "atanks.cpp: Failed to save game settings from atanks::main()!");
  5347.           }
  5348.  
  5349.           // check for changes to settings
  5350.           Change_Settings(temp_mouse, temp_sound, global->os_mouse, global->sound, global->misc[0]);
  5351.           global->Change_Font();
  5352.           global->Update_Player_Menu();
  5353.           break;
  5354.         case GLOBAL_COMMAND_PLAYERS:
  5355.           //loop until done editing players where return value is not ESC
  5356.           do
  5357.           {
  5358.              status = editPlayers(global, env);
  5359.           }
  5360.           while ( (status != KEY_ESC << 8) && (status != KEY_ENTER << 8) );
  5361.           break;
  5362.         case GLOBAL_COMMAND_CREDITS:
  5363.           credits(global, env);
  5364.           break;
  5365.         case GLOBAL_COMMAND_QUIT:
  5366.           break;
  5367.         case GLOBAL_COMMAND_NETWORK:
  5368.           #ifdef NETWORK
  5369.           client_socket = Setup_Client_Socket(global->server_name, global->server_port);
  5370.           if (client_socket >= 0)
  5371.           {
  5372.              int keep_playing = TRUE;
  5373.              printf("Ready to play networked\n");
  5374.              while (keep_playing)
  5375.              {
  5376.                  keep_playing = Game_Client(global, env, client_socket);
  5377.              }
  5378.              Clean_Up_Client_Socket(client_socket);
  5379.           }
  5380.           else
  5381.             printf("Unable to connect to server %s, port %s.\n", global->server_name, global->server_port);
  5382.           #else
  5383.             printf("This version of Atanks is not compiled to handle network games.\n");
  5384.           #endif
  5385.           break;
  5386.         case GLOBAL_COMMAND_DEMO:
  5387.            global->demo_mode = true;
  5388.            global->load_game = false;
  5389.            music_place_holder = global->play_music;
  5390.            global->play_music = 0.0;
  5391.  
  5392.            // set up a bunch of players (non-human, less than 10)
  5393.            playerCount = 0;
  5394.            global->numPlayers = 0;
  5395.            for (player_index = 0; player_index < global->numPermanentPlayers; player_index++)
  5396.            {
  5397.                if ( (global->allPlayers[player_index]->type > HUMAN_PLAYER) && (playerCount < MAXPLAYERS) )
  5398.                {
  5399.                   global->addPlayer (global->allPlayers[player_index]);
  5400.                   playerCount++;
  5401.                }
  5402.            }
  5403.  
  5404.            player_index = (int) global->skipComputerPlay;
  5405.            global->skipComputerPlay = SKIP_NONE;
  5406.            global->currentround = 1;      // might add more later
  5407.            while ( (global->currentround > 0) && (! global->close_button_pressed) )
  5408.            {
  5409.                 game(global, env);
  5410.                 if ((global->command == GLOBAL_COMMAND_QUIT) || (global->command == GLOBAL_COMMAND_MENU))
  5411.                       break;
  5412.                 global->currentround--;
  5413.                 // skipping winner screen for now
  5414.            }
  5415.            endgame_cleanup(global, env);
  5416.            global->demo_mode = false;
  5417.            global->skipComputerPlay = player_index;
  5418.            global->play_music = music_place_holder;
  5419.            break;
  5420.  
  5421.         default: //must have commanded to play game
  5422.           menu_action = selectPlayers(global, env);
  5423.           if (menu_action == ESC_MENU)
  5424.             break;
  5425.  
  5426.           //selected players, start new game
  5427.           else
  5428.             {
  5429.               // make sure the game has a name
  5430.               if (! global->game_name[0])
  5431.                 strcpy(global->game_name,global->ingame->complete_text[53] );
  5432.  
  5433.               newgame (global, env);
  5434.  
  5435.               // play the game for the selected number of rounds
  5436.               // for (global->currentround = (int)global->rounds; global->currentround > 0; global->currentround--)
  5437.               if (! global->load_game) global->currentround = (int) global->rounds;
  5438.               while ( (global->currentround > 0) && (! global->close_button_pressed) )
  5439.                 {
  5440.                   game (global, env);      // play a round
  5441.                   if (global->background_music)
  5442.                   {
  5443.                        stop_sample(global->background_music);
  5444.                        destroy_sample(global->background_music);
  5445.                        global->background_music = NULL;
  5446.                   }
  5447.                       
  5448.                   // if user selected to quit or return to main menu during game play
  5449.                   if ((global->command == GLOBAL_COMMAND_QUIT) || (global->command == GLOBAL_COMMAND_MENU))                 
  5450.                   {
  5451.                     #ifdef NETWORK
  5452.                     global->Send_To_Clients("CLOSE");
  5453.                     #endif
  5454.                     break;
  5455.                   }
  5456.                   global->currentround--;
  5457.                   #ifdef NETWORK
  5458.                   if (global->currentround != 0)    // end of the round
  5459.                      global->Send_To_Clients("ROUNDEND");
  5460.                   #endif
  5461.                 }
  5462.  
  5463.               // only show winner if finished all rounds
  5464.               if ( (global->currentround == 0) && (! global->close_button_pressed) )
  5465.               {
  5466.                   char buffer[256], *my_player;
  5467.                  
  5468.                   // strcpy(buffer, "GAMEEND"); 
  5469.                   // global->Send_To_Clients(buffer);
  5470.                   my_player = do_winner (global, env);
  5471.                   if (my_player)
  5472.                   {
  5473.                      snprintf(buffer, 256, "GAMEEND The game went to %s.", my_player);
  5474.                      free(my_player);
  5475.                   }
  5476.                   else
  5477.                      strcpy(buffer, "GAMEEND");
  5478.                   #ifdef NETWORK
  5479.                   global->Send_To_Clients(buffer);
  5480.                   #endif
  5481.                   do_quote(global, env);
  5482.               }
  5483.  
  5484.               endgame_cleanup (global, env);
  5485.             }    // end of start new game
  5486.  
  5487.           break;
  5488.  
  5489.         }      // end of menu switch
  5490.  
  5491.     }
  5492.   while ( (global->command != GLOBAL_COMMAND_QUIT) );
  5493.  
  5494.   // print out if there is an update
  5495.   if ( (global->update_string) && (global->update_string[0]) )
  5496.   {
  5497.       cout << global->update_string << endl;
  5498.       free(global->update_string);
  5499.       global->update_string = NULL;
  5500.   }
  5501.  
  5502.   #ifdef THREADS
  5503.   #ifdef NETWORK
  5504.   if (send_receive)
  5505.   {
  5506.      send_receive->shut_down = TRUE;
  5507.      // sleep(1);
  5508.      LINUX_REST;
  5509.      // we should probably wait and do a join here, but if the network thread does not
  5510.      // finish after a full second, then something has gone wrong anyway and we should move on....
  5511.      free(send_receive);
  5512.   }
  5513.   #endif
  5514.   #endif
  5515.  
  5516.   if (! Save_Game_Settings_Text(global, env, fullPath))
  5517.     {
  5518.       // This is a very critical issue, but as we are ending here, we just report it
  5519.       perror ( "atanks.cpp: Failed to save game settings from atanks::main()!");
  5520.       allegro_exit ();
  5521.       cout << "See http://atanks.sourceforge.net for the latest news and downloads." << endl;
  5522.  
  5523.       return(1);
  5524.     }
  5525.   else
  5526.     {
  5527.       Save_Game_Settings_Text(global, env, fullPath);
  5528.       allegro_exit ();
  5529.       cout << "See http://atanks.sourceforge.net for the latest news and downloads." << endl;
  5530.  
  5531.       return(0);
  5532.     }
  5533. }
  5534.  
  5535.  
  5536. END_OF_MAIN ()
  5537.  
  5538.  
  5539.  
  5540.  
  5541. /*
  5542. Adding function here to avoid patch incompatibilties.
  5543. This function should launch all items from all of
  5544. the living tanks.
  5545. */
  5546. void doLaunch(GLOBALDATA *global, ENVIRONMENT *env)
  5547. {
  5548.   // If we're in simultaneous mode, launch all selections
  5549.   int i;
  5550.   int savestage = env->stage;
  5551.   TANK *tank;
  5552.  
  5553.   if (global->turntype != TURN_SIMUL)
  5554.     return;
  5555.  
  5556.   for (i = 0; i < global->maxNumTanks; i++)
  5557.     {
  5558.        tank = env->order[i];
  5559.        if (tank)
  5560.         {
  5561.           if (! tank->player->skip_me)
  5562.             tank->activateCurrentSelection();
  5563.           else
  5564.             tank->player->skip_me = false;
  5565.           tank->player->time_left_to_fire = global->max_fire_time;
  5566.         }
  5567.     }
  5568.  
  5569.   env->stage = savestage;
  5570. }
  5571.  
  5572.  
  5573. // load a colour from a file
  5574. bool popColo(int &aData, ifstream &ifsFile)
  5575. {
  5576.   bool bResult = false;
  5577.   if (ifsFile.is_open())
  5578.   {
  5579.       int iColor = 0;
  5580.       ifsFile >> iColor; // reads the next found number
  5581.       if (ifsFile.good())
  5582.       {
  5583.           // Now transform to color:
  5584.           aData = makecol((iColor & 0x00ff0000) >> 16,
  5585.                           (iColor & 0x0000ff00) >>  8,
  5586.                            iColor & 0x000000ff       );
  5587.           bResult = true;
  5588.        }
  5589.   }
  5590.   return bResult;
  5591. }
  5592.  
  5593.  
  5594. int *Sort_Scores(GLOBALDATA *global)
  5595. {
  5596.   static int order[MAXPLAYERS];
  5597.   int counter;
  5598.   bool made_change = true;
  5599.   int temp;
  5600.  
  5601.   for (counter = 0; counter < global->numPlayers; counter++)
  5602.     order[counter] = counter;
  5603.  
  5604.   // bubble sort
  5605.   while (made_change)
  5606.     {
  5607.       made_change = false;
  5608.       counter = 0;
  5609.       // check for swap
  5610.       while (counter < (global->numPlayers - 1) )
  5611.         {
  5612.           if ( global->players[ order[counter] ]->score < global->players[ order[counter + 1] ]->score )
  5613.             {
  5614.               temp = order[counter];
  5615.               order[counter] = order[counter + 1];
  5616.               order[counter + 1] = temp;
  5617.               made_change = true;
  5618.             }
  5619.  
  5620.           counter++;
  5621.         }    // end of check for swaps
  5622.     }         // end of bubble sort
  5623.  
  5624.   return order;
  5625. }
  5626.  
  5627.  
  5628.  
  5629.  
  5630. // Client version of the game
  5631. // Really, this loop should do some basic things.
  5632. // 1. Find out what the landscape should look like from the server.
  5633. // 2. Place tanks on the battle field
  5634. // 3. Create missiles, beam weapons and such when the server asks us to
  5635. // 4. Get input from the player and forward it to the server.
  5636. // 5. Clean up at the end of the round.
  5637. //
  5638. // Function return TRUE if everything went well or FALSE
  5639. // if an error occured.
  5640. #ifdef NETWORK
  5641.  
  5642. int Game_Client(GLOBALDATA *global, ENVIRONMENT *env, int socket_number)
  5643. {
  5644.     int surface_x = 1, tank_position = 1, team_number = 1, name_number = 1;
  5645.     int weapon_number = 1, item_number = 1, tank_health = 1;
  5646.     int end_of_round = FALSE, keep_playing = FALSE;
  5647.     int game_stage = CLIENT_VERSION;
  5648.     char buffer[BUFFER_SIZE];
  5649.     int incoming;
  5650.     int my_key;
  5651.     int time_clock = 0;
  5652.     int screen_update = FALSE;
  5653.     int count;      // generic counter
  5654.     int stuff_going_down = FALSE;    // explosions, missiles etc on the screen
  5655.     VIRTUAL_OBJECT *my_object;
  5656.     BEAM *beam;
  5657.     EXPLOSION *explosion;
  5658.     MISSILE *missile;
  5659.     TELEPORT *teleport;
  5660.     FLOATTEXT *floattext;
  5661.     int my_class, object_count;
  5662.     bool fired = false;
  5663.     
  5664.  
  5665.     global->dMaxVelocity = (double)MAX_POWER * (100.0 / (double)global->frames_per_second) / 100.0;
  5666.     clear_to_color (env->terrain, PINK);    // get terrain ready
  5667.     clear_to_color(env->db, BLACK);
  5668.  
  5669.     // clean up old text
  5670.     for (count = 0; (floattext = (FLOATTEXT*)env->getNextOfClass (FLOATTEXT_CLASS, &count)) && floattext; count++)
  5671.     {
  5672.          floattext->newRound();
  5673.          delete floattext;
  5674.     }
  5675.  
  5676.     Create_Sky(env, global);     // so we have a background
  5677.     strcpy(buffer, "VERSION");
  5678.     write(socket_number, buffer, strlen(buffer));
  5679.  
  5680.     while (! end_of_round)
  5681.     {
  5682.         // check for waiting input from the server
  5683.         incoming = Check_For_Incoming_Data(socket_number);
  5684.         if (incoming)
  5685.         {
  5686.            int bytes_read;
  5687.  
  5688.            memset(buffer, '\0', BUFFER_SIZE);
  5689.            bytes_read = read(socket_number, buffer, BUFFER_SIZE);  
  5690.            if (bytes_read > 0)
  5691.            {
  5692.                 // do something with this input
  5693.                 if (! strncmp(buffer, "CLOSE", 5) )
  5694.                 {
  5695.                    end_of_round = TRUE;
  5696.                    keep_playing = FALSE;
  5697.                    printf("Got close message.\n");
  5698.                    global->client_message = global->ingame->complete_text[81];
  5699.                 }
  5700.                 else if (! strncmp(buffer, "NOROOM", 6) )
  5701.                 {
  5702.                    end_of_round = TRUE;
  5703.                    keep_playing = FALSE;
  5704.                    printf("The server is full or the game has not started. Please try again later.\n");
  5705.                    global->client_message = global->ingame->complete_text[80];
  5706.                 }
  5707.                 else if (! strncmp(buffer, "GAMEEND", 7) )
  5708.                 {
  5709.                     end_of_round = TRUE;
  5710.                     keep_playing = FALSE;
  5711.                     printf("The game is over.\n");
  5712.                     if ( strlen(buffer) > 7)
  5713.                         global->client_message = strdup(& (buffer[8])) ;
  5714.                     else
  5715.                         global->client_message = strdup(global->ingame->complete_text[82]);
  5716.                 }
  5717.                 else if (! strncmp(buffer, "ROUNDEND", 8) )
  5718.                 {
  5719.                    end_of_round = TRUE;
  5720.                    keep_playing = TRUE;
  5721.                    printf("Round is over.\n");
  5722.                 }
  5723.                    
  5724.                 else         // not a special command, parse it
  5725.                 {
  5726.                   if ( Parse_Client_Data(global, env, buffer) )
  5727.                   {
  5728.                       if (game_stage < CLIENT_PLAYING)
  5729.                          game_stage++;
  5730.                 
  5731.                       // Request more information
  5732.                       if (game_stage < CLIENT_PLAYING)
  5733.                       {
  5734.                          switch (game_stage)
  5735.                          {
  5736.                             case CLIENT_SCREEN: strcpy(buffer, "SCREEN"); break;
  5737.                             case CLIENT_WIND: strcpy(buffer, "WIND"); break;
  5738.                             case CLIENT_NUMPLAYERS: strcpy(buffer, "NUMPLAYERS"); break;
  5739.                             case CLIENT_TANK_POSITION: strcpy(buffer, "TANKPOSITION 0"); break;
  5740.                             case CLIENT_SURFACE: strcpy(buffer, "SURFACE 0"); break;
  5741.                             case CLIENT_WHOAMI: strcpy(buffer, "WHOAMI");
  5742.                                                 screen_update = TRUE; break;
  5743.                             case CLIENT_WEAPONS: strcpy(buffer, "WEAPON 0"); break;
  5744.                             case CLIENT_ITEMS:   strcpy(buffer, "ITEM 0"); break;
  5745.                             case CLIENT_ROUNDS: strcpy(buffer, "ROUNDS"); break;
  5746.                             case CLIENT_TEAMS: strcpy(buffer, "TEAMS 0"); 
  5747.                                                global->updateMenu = TRUE; break;
  5748.                             case CLIENT_WALL_TYPE: strcpy(buffer, "WALLTYPE"); break;
  5749.                             case CLIENT_BOXED: strcpy(buffer, "BOXED"); break;
  5750.                             case CLIENT_NAME: strcpy(buffer, "PLAYERNAME 0"); break;
  5751.                             case CLIENT_TANK_HEALTH: strcpy(buffer, "HEALTH 0"); break;
  5752.                             default: buffer[0] = '\0';
  5753.                          }
  5754.                          write(socket_number, buffer, strlen(buffer));
  5755.                        }   // end of getting more info
  5756.                    }    // our game stage went up
  5757.                    else  // we got data, but our game stage did not go up
  5758.                    {
  5759.                        if (fired)
  5760.                        {
  5761.                            if ( (global->client_player) && (global->client_player->tank) )
  5762.                            {
  5763.                                fired = false;
  5764.                                if (global->client_player->tank->cw < WEAPONS)
  5765.                                    sprintf(buffer, "WEAPON %d", global->client_player->tank->cw);
  5766.                                else
  5767.                                    sprintf(buffer, "ITEM %d", global->client_player->tank->cw - WEAPONS);
  5768.                                write(socket_number, buffer, strlen(buffer));
  5769.                            }
  5770.                        }
  5771.                        else if (game_stage == CLIENT_SURFACE)
  5772.                        {
  5773.                            sprintf(buffer, "SURFACE %d", surface_x);
  5774.                            write(socket_number, buffer, strlen(buffer));
  5775.                            surface_x++;
  5776.                        }
  5777.                        else if (game_stage == CLIENT_ITEMS)
  5778.                        {
  5779.                             sprintf(buffer, "ITEM %d", item_number);
  5780.                             write(socket_number, buffer, strlen(buffer));
  5781.                             item_number++;
  5782.                        }
  5783.                        else if (game_stage == CLIENT_TANK_POSITION)
  5784.                        {
  5785.                             sprintf(buffer, "TANKPOSITION %d", tank_position);
  5786.                             write(socket_number, buffer, strlen(buffer));
  5787.                             tank_position++;
  5788.                             if (tank_position >= global->numPlayers)
  5789.                               tank_position = 0;
  5790.                        }
  5791.                        else if (game_stage == CLIENT_TANK_HEALTH)
  5792.                        {
  5793.                             sprintf(buffer, "HEALTH %d", tank_health);
  5794.                             write(socket_number, buffer, strlen(buffer));
  5795.                             tank_health++;
  5796.                             if (tank_health >= global->numPlayers)
  5797.                                 tank_health = 0;
  5798.                        }
  5799.                        else if (game_stage == CLIENT_TEAMS)
  5800.                        {
  5801.                             sprintf(buffer, "TEAMS %d", team_number);
  5802.                             write(socket_number, buffer, strlen(buffer));
  5803.                             team_number++;
  5804.                        }
  5805.                        else if (game_stage == CLIENT_NAME)
  5806.                        {
  5807.                             sprintf(buffer, "PLAYERNAME %d", name_number);
  5808.                             write(socket_number, buffer, strlen(buffer));
  5809.                             name_number++;
  5810.                        }
  5811.                        else if (game_stage == CLIENT_WEAPONS)
  5812.                        {
  5813.                             sprintf(buffer, "WEAPON %d", weapon_number);
  5814.                             write(socket_number, buffer, strlen(buffer));
  5815.                             weapon_number++;
  5816.                        }
  5817.                        else if (game_stage == CLIENT_PLAYING)
  5818.                        {
  5819.                            time_clock++;
  5820.                            if (time_clock > 1)   // check positions every few inputs
  5821.                            {
  5822.                                time_clock = 0;
  5823.                                if (surface_x < global->screenWidth)
  5824.                                {
  5825.                                    game_stage = CLIENT_SURFACE;
  5826.                                    sprintf(buffer, "SURFACE %d", surface_x);
  5827.                                    write(socket_number, buffer, strlen(buffer));
  5828.                                    surface_x++;
  5829.                                }
  5830.                                else
  5831.                                {
  5832.                                  game_stage = CLIENT_TANK_POSITION;
  5833.                                  tank_position = 1;
  5834.                                  strcpy(buffer, "TANKPOSITION 0");
  5835.                                  write(socket_number, buffer, strlen(buffer));
  5836.                                }    // game stage stuff
  5837.                            }
  5838.                        }        // end of playing commands
  5839.                    }
  5840.  
  5841.                 }      // end of we got something besides the close command
  5842.  
  5843.            }
  5844.            else    // connection was broken
  5845.            {
  5846.               close(socket_number);
  5847.               printf("Server closed connection.\n");
  5848.               end_of_round = TRUE;
  5849.            }
  5850.         }
  5851.  
  5852.         object_count = 0;
  5853.         while (object_count < MAX_OBJECTS)
  5854.         {
  5855.             my_object = env->objects[object_count];
  5856.             if (my_object)
  5857.             {
  5858.             my_class = my_object->getClass();
  5859.             if (my_class == BEAM_CLASS)
  5860.             {
  5861.                 beam = (BEAM *) my_object;
  5862.                 beam->applyPhysics();
  5863.                 if (beam->destroy)
  5864.                 {
  5865.                     beam->requireUpdate();
  5866.                     beam->update();
  5867.                     delete beam;
  5868.                 }
  5869.                 stuff_going_down = TRUE;
  5870.             }
  5871.             else if (my_class == MISSILE_CLASS)
  5872.             {
  5873.                 missile = (MISSILE *) my_object;
  5874.                 missile->hitSomething = 0;
  5875.                 missile->applyPhysics();
  5876.                 missile->triggerTest();
  5877.                 if (missile->destroy)
  5878.                 {
  5879.                     missile->requireUpdate();
  5880.                     missile->update();
  5881.                     delete missile;
  5882.                 }
  5883.                 stuff_going_down = TRUE;
  5884.             }
  5885.             else if (my_class == EXPLOSION_CLASS)
  5886.             {
  5887.                 explosion = (EXPLOSION *) my_object;
  5888.                 explosion->explode ();
  5889.                 explosion->applyPhysics ();
  5890.                 if (explosion->destroy)
  5891.                 {
  5892.                   explosion->requireUpdate ();
  5893.                   explosion->update ();
  5894.                   delete explosion;
  5895.                 }
  5896.                 stuff_going_down = TRUE;
  5897.             }
  5898.             else if (my_class == TELEPORT_CLASS)
  5899.             {
  5900.                 teleport = (TELEPORT *) my_object;
  5901.                 teleport->applyPhysics ();
  5902.                 if (teleport->destroy)
  5903.                 {
  5904.                   teleport->requireUpdate ();
  5905.                   teleport->update ();
  5906.                   delete teleport;
  5907.                   time_clock = 2;
  5908.                 }
  5909.                 stuff_going_down = TRUE;
  5910.             }
  5911.             else if (my_class == FLOATTEXT_CLASS)
  5912.             {
  5913.                 floattext = (FLOATTEXT *) my_object;
  5914.                 floattext->applyPhysics ();
  5915.                 if (floattext->destroy)
  5916.                 {
  5917.                   floattext->requireUpdate();
  5918.                   floattext->update();
  5919.                   delete floattext;
  5920.                 }
  5921.             }
  5922.             else if (my_class == DECOR_CLASS)
  5923.             {
  5924.                  DECOR *decor = (DECOR *) my_object;
  5925.                  decor->applyPhysics ();
  5926.                  if (decor->destroy)
  5927.                  {
  5928.                     decor->requireUpdate ();
  5929.                     decor->update ();
  5930.                     delete decor;
  5931.                  }
  5932.             }
  5933.             }      // end of got valid object
  5934.             object_count++;
  5935.         }
  5936.  
  5937.         slideLand(global, env);
  5938.  
  5939.         // update everything on the screen
  5940.         if (global->updateMenu)
  5941.         {
  5942.           set_clip_rect (env->db, 0, 0, (global->screenWidth-1), MENUHEIGHT - 1);
  5943.           drawTopBar (global, env, env->db);
  5944.         }
  5945.  
  5946.         set_clip_rect (env->db, 0, MENUHEIGHT, (global->screenWidth-1), (global->screenHeight-1));
  5947.         if (screen_update)
  5948.         {
  5949.           blit (env->sky, env->db, global->window.x, global->window.y - MENUHEIGHT, global->window.x, global->window.y, (global->window.w - global->window.x) + 1, (global->window.h - global->window.y) + 1);
  5950.           masked_blit (env->terrain, env->db, global->window.x, global->window.y, global->window.x, global->window.y, (global->window.w - global->window.x) + 1, (global->window.h - global->window.y) + 2);
  5951.           drawTopBar(global, env, env->db);
  5952.           int iLeft = 0;
  5953.           int iRight = global->screenWidth - 1;
  5954.           int iTop = MENUHEIGHT;
  5955.           int iBottom = global->screenHeight - 1;
  5956.           set_clip_rect (env->db, 0, 0, iRight, iBottom);
  5957.           vline(env->db, iLeft, iTop, iBottom, env->wallColour);    // Left edge
  5958.           vline(env->db, iRight, iTop, iBottom, env->wallColour);   // right edge
  5959.           hline(env->db, iLeft, iBottom, iRight, env->wallColour);// bottom edge
  5960.           if (global->bIsBoxed)
  5961.               hline(env->db, iLeft, iTop, iRight, env->wallColour);// top edge
  5962.  
  5963.           env->make_update(0, 0, global->screenWidth, global->screenHeight);
  5964.         }
  5965.         else
  5966.         {
  5967.           env->replaceCanvas ();
  5968.         }
  5969.  
  5970.         for (count = 0; count < global->numPlayers; count++)
  5971.         {
  5972.              if ( (global->players[count]) && (global->players[count]->tank) )
  5973.              {
  5974.                 global->players[count]->tank->draw(env->db, 0);
  5975.                 global->players[count]->tank->update();
  5976.              }
  5977.         }
  5978.         // env->do_updates();
  5979.         screen_update = TRUE;
  5980.  
  5981.         object_count = 0;
  5982.         while (object_count < MAX_OBJECTS)
  5983.         {
  5984.             my_object = env->objects[object_count];
  5985.             if (my_object)
  5986.             {
  5987.                my_class = my_object->getClass();
  5988.  
  5989.                if (my_class == BEAM_CLASS)
  5990.                {
  5991.                   beam = (BEAM *) my_object;
  5992.                   beam->draw (env->db);
  5993.                   beam->update ();
  5994.                 }
  5995.                 else if (my_class == MISSILE_CLASS)
  5996.                 {
  5997.                     missile = (MISSILE *) my_object;
  5998.                     missile->draw(env->db);
  5999.                     missile->update();
  6000.                 }
  6001.                 else if (my_class == EXPLOSION_CLASS)
  6002.                 {
  6003.                    explosion = (EXPLOSION *) my_object;
  6004.                    explosion->draw (env->db);
  6005.                    explosion->update ();
  6006.                 }
  6007.                 else if (my_class == TELEPORT_CLASS)
  6008.                 {
  6009.                      teleport = (TELEPORT *) my_object;
  6010.                      if (teleport->object)
  6011.                         teleport->draw (env->db);
  6012.                      teleport->update ();
  6013.                 }
  6014.                 else if (my_class == DECOR_CLASS)
  6015.                 {
  6016.                      DECOR *decor = (DECOR *) my_object;
  6017.                      decor->draw(env->db);
  6018.                      decor->update();
  6019.                 }
  6020.                 else if (my_class == FLOATTEXT_CLASS)
  6021.                 {
  6022.                      floattext = (FLOATTEXT *) my_object;
  6023.                      floattext->draw (env->db);
  6024.                      floattext->requireUpdate ();
  6025.                      floattext->update ();
  6026.                }
  6027.             }       // end of valid object
  6028.             object_count++;
  6029.         }     // end of while updating objects
  6030.         env->do_updates();
  6031.  
  6032.         
  6033.         // check for input from the user
  6034.         if ( keypressed() )
  6035.         {
  6036.            my_key = readkey();
  6037.            my_key = my_key >> 8;
  6038.            if (my_key == KEY_SPACE)
  6039.            {
  6040.               Client_Fire(global->client_player, socket_number);
  6041.               fired = true;
  6042.            }
  6043.            else if (my_key == KEY_ESC)
  6044.            {
  6045.               end_of_round = TRUE;
  6046.               close(socket_number);
  6047.            }
  6048.            else if (my_key == KEY_UP)
  6049.            {
  6050.               Client_Power(global->client_player, CLIENT_UP);
  6051.            }
  6052.            else if (my_key == KEY_DOWN)
  6053.            {
  6054.               Client_Power(global->client_player, CLIENT_DOWN);
  6055.            }
  6056.            else if (my_key == KEY_LEFT)
  6057.            {
  6058.               Client_Angle(global->client_player, CLIENT_LEFT);
  6059.            }
  6060.            else if (my_key == KEY_RIGHT)
  6061.            {
  6062.               Client_Angle(global->client_player, CLIENT_RIGHT);
  6063.            }
  6064.            else if ( (my_key == KEY_Z) || (my_key == KEY_BACKSPACE) )
  6065.            {
  6066.                Client_Cycle_Weapon(global->client_player, CYCLE_BACK);
  6067.            }
  6068.            else if ( (my_key == KEY_C) || (my_key == KEY_TAB) )
  6069.            {
  6070.                Client_Cycle_Weapon(global->client_player, CYCLE_FORWARD);
  6071.                global->updateMenu = TRUE;
  6072.            }
  6073.  
  6074.            screen_update = FALSE;
  6075.            global->updateMenu = TRUE;
  6076.         }
  6077.  
  6078.         // pause for a moment
  6079.         // if (game_stage < CLIENT_PLAYING)
  6080.         if (stuff_going_down)
  6081.         {
  6082.             LINUX_SLEEP;
  6083.             stuff_going_down = FALSE;
  6084.         }
  6085.     }
  6086.  
  6087.     // we should clean up here
  6088.     for (count = 0; count < global->numPlayers; count++)
  6089.     {
  6090.        if (global->players[count]->tank)
  6091.        {
  6092.            delete global->players[count]->tank;
  6093.            global->players[count]->tank = NULL;
  6094.        }
  6095.     }
  6096.  
  6097.     return keep_playing;
  6098. }
  6099.  
  6100. #endif
  6101.  
  6102.