[Tux4kids-commits] [SCM] tuxhistory - Educational history game branch, master, updated. f0b0d00e71233d5597746899321ab1e525418e74

julio (none) julio at julio-desktop.
Wed May 26 01:30:01 UTC 2010


The following commit has been merged in the master branch:
commit f0b0d00e71233d5597746899321ab1e525418e74
Author: julio <julio at julio-desktop.(none)>
Date:   Tue May 25 20:28:13 2010 -0500

    Cleaning TuxMath sources, deleting TuxMath sepsific code... v1

diff --git a/data/menus/main_menu.xml b/data/menus/main_menu.xml
index 2188d84..9170b90 100644
--- a/data/menus/main_menu.xml
+++ b/data/menus/main_menu.xml
@@ -1,4 +1,4 @@
-<menu title="Main Menu" entries="7">
+<menu title="Main Menu" entries="6">
     <menu title="Play Alone" sprite="alone" entries="5">
         <item title="Math Command Training Academy" sprite="lesson" run="RUN_ACADEMY">
         <item title="Math Command Fleet Missions" sprite="fleet" run="RUN_CAMPAIGN">
@@ -14,11 +14,6 @@
         <item title="Play Custom Game" sprite="tux_config_brown" run="RUN_CUSTOM">
         <item title="Main Menu" sprite="main" run="RUN_MAIN_MENU">
     </menu>
-    <menu title="Network Game" sprite="lan" entries="3">
-        <item title="Run Server" sprite="lan" run="RUN_LAN_HOST">
-        <item title="Join Game" sprite="lan" run="RUN_LAN_JOIN">
-        <item title="Main Menu" sprite="main" run="RUN_MAIN_MENU">
-    </menu>
     <menu title="Play With Friends" sprite="friends" entries="3">
         <menu title="Score Sweep" sprite="nums" entries="6">
             <item title="Space Cadet" sprite="tux_helmet_yellow" run="RUN_SCORE_SWEEP" param="0">
diff --git a/src/Makefile.am b/src/Makefile.am
index 276ae91..5216419 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -30,7 +30,6 @@ tuxhistory_SOURCES = tuxhistory.c \
 	titlescreen.c	\
 	menu.c		\
 	game.c 		\
-	factoroids.c    \
 	fileops_media.c \
 	options.c	\
 	credits.c	\
@@ -38,15 +37,10 @@ tuxhistory_SOURCES = tuxhistory.c \
 	linewrap.c	\
 	loaders.c	\
 	audio.c 	\
-        network.c       \
-	mathcards.c	\
-	campaign.c	\
-	multiplayer.c	\
 	fileops.c	\
 	convert_utf.c	\
 	SDL_extras.c	\
 	SDL_rotozoom.c	\
-	lessons.c	\
 	scandir.c	\
 	pixels.c	\
 	server.c	\
@@ -58,7 +52,6 @@ TuxHistory_SOURCES  = $(tuxhistory_SOURCES) tuxmathrc.rc
 
 
 EXTRA_DIST = 	credits.h 	\
-	factoroids.h	\
 	fileops.h 	\
 	game.h		\
 	menu.h		\
@@ -66,25 +59,18 @@ EXTRA_DIST = 	credits.h 	\
 	highscore.h 	\
 	linewrap.h	\
 	loaders.h	\
-        network.h       \
 	titlescreen.h   \
 	menu.h		\
 	options.h	\
 	setup.h		\
-	mathcards.h 	\
-	campaign.h	\
-	multiplayer.h	\
 	tuxhistory.h	\
 	convert_utf.h	\
 	SDL_extras.h	\
 	SDL_rotozoom.h	\
-	lessons.h	\
 	gettext.h	\
 	scandir.h	\
 	pixels.h	\
 	compiler.h	\
-	server.h	\
-	testclient.h	\
 	transtruct.h	\
 	throttle.h
         
diff --git a/src/fileops.c b/src/fileops.c
index b62428c..343da91 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -34,10 +34,8 @@
 #include "globals.h"
 #include "fileops.h"
 #include "setup.h"
-#include "mathcards.h"
 #include "options.h"
 #include "highscore.h"
-#include "lessons.h"
 #include "scandir.h"
 
 /* OS includes - NOTE: these may not be very portable */
@@ -194,7 +192,7 @@ char *GetDefaultSaveDir(const char *suffix)
 #else
 
 # define get_home getenv("HOME")
-#define OPTIONS_SUBDIR "/.tuxmath"
+#define OPTIONS_SUBDIR "/.tuxhistory"
 #define OPTIONS_FILENAME "options"
 #define HIGHSCORE_FILENAME "highscores"
 #define GOLDSTAR_FILENAME "goldstars"
@@ -1331,22 +1329,7 @@ int read_config_file(FILE *fp, int file_type)
     free(parameter);
   }
   //handle min > max by disallowing operation
-  if (MC_GetOpt(MIN_AUGEND) > MC_GetOpt(MAX_AUGEND) || 
-      MC_GetOpt(MIN_ADDEND) > MC_GetOpt(MAX_ADDEND) )
-      MC_SetOpt(ADDITION_ALLOWED, 0);
-  if (MC_GetOpt(MIN_MINUEND) > MC_GetOpt(MAX_MINUEND) || 
-      MC_GetOpt(MIN_SUBTRAHEND) > MC_GetOpt(MAX_SUBTRAHEND) )
-      MC_SetOpt(SUBTRACTION_ALLOWED, 0);
-  if (MC_GetOpt(MIN_MULTIPLICAND) > MC_GetOpt(MAX_MULTIPLICAND) || 
-      MC_GetOpt(MIN_MULTIPLIER) > MC_GetOpt(MAX_MULTIPLIER) )
-      MC_SetOpt(MULTIPLICATION_ALLOWED, 0);
-  if (MC_GetOpt(MIN_DIVISOR) > MC_GetOpt(MAX_DIVISOR) || 
-      MC_GetOpt(MIN_QUOTIENT) > MC_GetOpt(MAX_QUOTIENT) )
-      MC_SetOpt(DIVISION_ALLOWED, 0);
-  if (MC_GetOpt(MIN_TYPING_NUM) > MC_GetOpt(MAX_TYPING_NUM) )
-      MC_SetOpt(TYPING_PRACTICE_ALLOWED, 0);
-
-  DEBUGMSG(debug_fileops, "After file read in:\n");
+    DEBUGMSG(debug_fileops, "After file read in:\n");
   DEBUGCODE(debug_fileops)
     write_config_file(stdout, 0);
   DEBUGMSG(debug_fileops, "Leaving read_config_file()\n");
@@ -1360,11 +1343,8 @@ static int parse_option(const char* name, int val, int file_type)
 {
   int index = -1;
   
-  if ((index = MC_MapTextToIndex(name)) != -1) //is it a math opt?
-  {
-    MC_SetOpt(index, val);
-  }
-  else if ((index = Opts_MapTextToIndex(name)) != -1) //is it a global opt?
+  
+  if ((index = Opts_MapTextToIndex(name)) != -1) //is it a global opt?
   {
     if (file_type == GLOBAL_CONFIG_FILE)
       Opts_SetGlobalOpt(index, val);
@@ -1415,670 +1395,11 @@ int write_user_config_file(void)
 int write_config_file(FILE *fp, int verbose)
 {
   int i, vcommentsprimed = 0;
-  static char* vcomments[NOPTS]; //comments when writing out verbose
-  if (!vcommentsprimed) //we only want to initialize these once
-  {
-    vcommentsprimed = 1;
-    for (i = 0; i < NOPTS; ++i)
-      vcomments[i] = NULL;
-    vcomments[PLAY_THROUGH_LIST] =
-    "############################################################\n"
-    "#                                                          #\n"
-    "#              Tuxmath Configuration File                  #\n"
-    "#                                                          #\n"
-    "# The behavior of Tuxmath can be controlled to a great     #\n"
-    "# extent by editing this file with any and saving it in    #\n"
-    "# the default options location ($HOME/.tuxmath/options).   #\n"
-    "# The file consists of 'NAME = VALUE' pairs, one pair per  #\n"
-    "# line. Each option is one of the following types:         #\n"
-    "#                                                          #\n"
-    "#     boolean: 1 (synonyms 'true', 'T', 'yes', 'Y', 'on')  #\n"
-    "#              or                                          #\n"
-    "#              0 (synonyms 'false, 'F', 'no', 'N', 'off')  #\n"
-    "#     integer  (i.e. non-fractional numbers)               #\n"
-    "#     float    (i.e decimal fractions)                     #\n"
-    "#                                                          #\n"
-    "# Lines beginning with '#' or ';' are ignored as comments. #\n"
-    "# The synonyms for boolean '0' and '1' are accepted as     #\n"
-    "# input, but always written as '0' or '1' when Tuxmath     #\n"
-    "# writes a config file to disk.                            #\n"
-    "# The file is organized with the more important options    #\n"
-    "# first.                                                   #\n"
-    "############################################################\n"
-    "\n"
-    "############################################################\n"
-    "#                                                          #\n"
-    "#                       Game Mode                          #\n"
-    "#                                                          #\n"
-    "# Parameter: play_through_list (Boolean)                   #\n"
-    "# Default: 1                                               #\n"
-    "#                                                          #\n"
-    "# Tuxmath generates a list of math questions based on      #\n"
-    "# parameters set below.  By default, (play_through_list =  #\n"
-    "# 1) the questions are asked in a random order.            #\n"
-    "# Correctly answered questions are removed from the list.  #\n"
-    "# If the player fails to correctly answer a question       #\n"
-    "# before it hits a city, the question will be reinserted   #\n"
-    "# into the list in a random location.                      #\n"
-    "# The player wins if all questions are answered correctly  #\n"
-    "# before the cities are destroyed.                         #\n"
-    "#                                                          #\n"
-    "# Alternatively, Tuxmath can be played in 'Arcade Mode'    #\n"
-    "# by setting play_through_list = 0 (i.e. 'false'). If this #\n"
-    "# is done, all questions will be randomly reinserted into  #\n"
-    "# the list whether or not they are answered correctly, and #\n"
-    "# the game continues as long as there is a surviving city. #\n"
-    "############################################################\n"
-    "\n";                                                           
-    
-    vcomments[ADDITION_ALLOWED] = 
-    "\n############################################################\n"
-    "#                                                          #\n"
-    "#               Selecting Math Operations                  #\n"
-    "#                                                          #\n"
-    "# Parameter: addition_allowed (boolean)                    #\n"
-    "# Default: 1                                               #\n"
-    "# Parameter: subtraction_allowed (boolean)                 #\n"
-    "# Default: 1                                               #\n"
-    "# Parameter: multiplication_allowed (boolean)              #\n"
-    "# Default: 1                                               #\n"
-    "# Parameter: division_allowed (boolean)                    #\n"
-    "# Default: 1                                               #\n"
-    "#                                                          #\n"
-    "# These options enable questions for each of the four math #\n"
-    "# operations.  All are 1 (yes) by default.                 #\n"
-    "############################################################\n\n";
-    vcomments[TYPING_PRACTICE_ALLOWED] =
-    "\n############################################################\n"
-    "#                                                          #\n"
-    "#                    Typing Practice                       #\n"
-    "#                                                          #\n"
-    "# Parameter: typing_practice_allowed (boolean)             #\n"
-    "# Default: 0                                               #\n"
-    "#                                                          #\n"
-    "# This option simply displays numbers for the youngest     #\n"
-    "# players to type in to learn the keyboard.                #\n"
-    "############################################################\n\n";
-    vcomments[ALLOW_NEGATIVES] =
-    "\n############################################################\n"
-    "#                                                          #\n"
-    "#                 Negative Number Support                  #\n"
-    "#                                                          #\n"
-    "# Parameter: allow_negatives (boolean)                     #\n"
-    "# Default: 0                                               #\n"
-    "#                                                          #\n"
-    "# 'allow_negatives' allows or disallows use of negative    #\n"
-    "# numbers as both operands and answers.  Default is 0      #\n"
-    "# (no), which disallows questions like:                    #\n"
-    "#          2 - 4 = ?                                       #\n"
-    "# Note: this option must be enabled in order to set the    #\n"
-    "# operand ranges to include negatives. If it is changed    #\n"
-    "# from 1 (yes) to 0 (no), any negative operand limits will #\n"
-    "# be reset to 0.                                           #\n"
-    "############################################################\n\n";
-    vcomments[MIN_AUGEND] = 
-    "\n############################################################\n"
-    "#                                                          #\n"
-    "#      Minimum and Maximum Values for Operand Ranges       #\n"
-    "#                                                          #\n"
-    "# Parameters: (multiple - all integer type)                #\n"
-    "#                                                          #\n"
-    "# Operand limits can be set to any integer up to the       #\n"
-    "# value of 'max_answer'. Tuxmath will generate questions   #\n"
-    "# for every value in the specified range. The maximum must #\n"
-    "# be greater than or equal to the corresponding minimum    #\n"
-    "# for any questions to be generated for that operation.    #\n"
-    "# Defaults are 0 for minima and 12 for maxima.             #\n"
-    "#                                                          #\n"
-    "# Note: 'allow_negatives' must be set to 1 for negative    #\n"
-    "# values to be accepted (see 'Advanced Options').          #\n"
-    "############################################################\n"
-    "\n# Addition operands:\n"
-    "# augend + addend = sum\n\n";
-    vcomments[MIN_MINUEND] = 
-    "\n# Subtraction operands:\n"
-    "# minuend - subtrahend = difference\n\n";
-    vcomments[MIN_MULTIPLIER] = 
-    "\n# Multiplication operands:\n"
-    "# multiplier * multiplicand = product\n\n";
-    vcomments[MIN_DIVISOR] = 
-    "\n# Division operands:\n"
-    "# dividend / divisor = quotiend\n\n";
-    vcomments[MIN_TYPING_NUM] =
-    "\n# Typing practice:\n";
-    vcomments[QUESTION_COPIES] = 
-    "\n\n\n############################################################\n"
-    "#                                                          #\n"
-    "#                   Advanced Options                       #\n"
-    "#                                                          #\n"
-    "# The remaining settings further customize Tuxmath's       #\n"
-    "# behavior.  Most users will probably not change them.     #\n"
-    "############################################################\n\n"
-    
-    "\n############################################################\n"
-    "#                                                          #\n"
-    "#           Advanced Math Question List Options            #\n"
-    "#                                                          #\n"
-    "# Parameter: question_copies (integer)                     #\n"
-    "# Default: 1                                               #\n"
-    "# Parameter: repeat_wrongs (boolean)                       #\n"
-    "# Default: 1                                               #\n"
-    "# Parameter: copies_repeated_wrongs (integer)              #\n"
-    "# Default: 1                                               #\n"
-    "# Parameter: fraction_to_keep (float)                      #\n"
-    "# Default: 1                                               #\n"
-    "#                                                          #\n"
-    "# These settings offer further control over the question   #\n"
-    "# list and are generally only useful if 'play_through_list'#\n"
-    "# is enabled (as it is by default).                        #\n"
-    "#                                                          #\n"
-    "# 'question_copies' is the number of times each question   #\n"
-    "# is put into the initial list. It can be 1 to 10.         #\n"
-    "#                                                          #\n"
-    "# 'repeat_wrongs' determines whether questions the player  #\n"
-    "# failed to answer correctly will be asked again.          #\n"
-    "#                                                          #\n"
-    "# 'copies_repeated_wrongs' gives the number of times a     #\n"
-    "# missed question will reappear. This can be set anywhere  #\n"
-    "# from 1 to 10.                                            #\n"
-    "#                                                          #\n"
-    "# The defaults for these values result in a 'mission'      #\n" 
-    "# for Tux that is accomplished by answering all            #\n"
-    "# questions correctly with at least one surviving city.    #\n"
-    "############################################################\n\n";
-    vcomments[FORMAT_ADD_ANSWER_LAST] =
-    "\n############################################################\n"
-    "#                                                          #\n"
-    "#                 Math Question Formats                    #\n"
-    "#                                                          #\n"
-    "# The 'format_<op>_answer_<place>  options control         #\n"
-    "# generation of questions with the answer in different     #\n"
-    "# places in the equation.  i.e.:                           #\n"
-    "#                                                          #\n"
-    "#    format_add_answer_last:    2 + 2 = ?                  #\n"
-    "#    format_add_answer_first:   ? + 2 = 4                  #\n"
-    "#    format_add_answer_middle:  2 + ? = 4                  #\n"
-    "#                                                          #\n"
-    "# By default, 'format_answer_first' is enabled and the     #\n"
-    "# other two formats are disabled.  Note that the options   #\n"
-    "# are not mutually exclusive - the question list may       #\n"
-    "# contain questions with different formats.                #\n"
-    "#                                                          #\n"
-    "# The formats are set independently for each of the four   #\n"
-    "# math operations. All parameters are type 'boolean'.      #\n"
-    "############################################################\n\n";
-    vcomments[MAX_ANSWER] = 
-    "\n############################################################\n"
-    "#                                                          #\n"
-    "# Parameter: max_answer (integer)                          #\n"
-    "# Default: 999                                             #\n"
-    "#                                                          #\n"
-    "# 'max_answer' is the largest absolute value allowed in    #\n"
-    "# any value in a question (not only the answer). Default   #\n"
-    "# is 999, which is as high as it can be set. It can be set #\n"
-    "# lower to fine-tune the list for certain 'lessons'.       #\n"
-    "############################################################\n\n";
-    vcomments[MAX_QUESTIONS] = 
-    "\n############################################################\n"
-    "#                                                          #\n"
-    "# Parameter: max_questions (integer)                       #\n"
-    "# Default: 5000                                            #\n"
-    "#                                                          #\n"
-    "# 'max_questions' is limit of the length of the question   #\n"
-    "# list. Default is 5000 - only severe taskmasters will     #\n"
-    "# need to raise it!                                        #\n"
-    "############################################################\n\n";
-    vcomments[RANDOMIZE] = 
-    "\n############################################################\n"
-    "#                                                          #\n"
-    "# Parameter: randomize (boolean)                           #\n"
-    "# Default: 1                                               #\n"
-    "#                                                          #\n"
-    "# If 'randomize' selected, the list will be shuffled       #\n"
-    "# at the start of the game. Otherwise, the questions       #\n"
-    "# appear in the order the program generates them.          #\n"
-    "############################################################\n\n";
-    
-  }
-  DEBUGMSG(debug_fileops, "Entering write_config_file()\n");
-
-  /* get out if file pointer null */
-  if(!fp)
-  {
-    fprintf (stderr, "write_config_file() - file pointer invalid/n");
-    DEBUGMSG(debug_fileops, "Leaving write_config_file()\n");
-    return 0;
-  }
-  
-  for (i = 0; i < NOPTS; ++i) //for each option
-  {
-    if (verbose && vcomments[i]) //comment goes before
-      fprintf(fp, "%s", vcomments[i]);
-    fprintf(fp, "%s = %d\n", MC_OPTION_TEXT[i], MC_GetOpt(i) );
-  }
-  
-  if (verbose)
-  {
-    //allow_speedup comment
-  }
-  fprintf(fp, "allow_speedup = %d\n", Opts_AllowSpeedup() );
-  
-  if (verbose)
-  {
-    //use_sound comment
-  } 
-  fprintf(fp, "use_sound = %d\n", Opts_GetGlobalOpt(USE_SOUND) );
-  
-  if (verbose)
-  {
-    fprintf (fp, "\n############################################################\n" 
-                 "#                                                          #\n"
-                 "#                Advanced Comet Speed Options              #\n"
-                 "#                                                          #\n"
-                 "# Parameter: starting_comets (integer)                     #\n"
-                 "# Default: 2                                               #\n"
-                 "# Parameter: extra_comets_per_wave (integer)               #\n"
-                 "# Default: 2                                               #\n"
-                 "# Parameter: max_comets (integer)                          #\n"
-                 "# Default: 10                                              #\n"
-                 "# Parameter: speed (float)                                 #\n"
-                 "# Default: 1.00                                            #\n"
-                 "# Parameter: max_speed (float)                             #\n"
-                 "# Default: 10.00                                           #\n"
-                 "# Parameter: speedup_factor (float)                        #\n"
-                 "# Default: 1.20                                            #\n"
-                 "# Parameter: bonus_comet_interval (integer)                #\n"
-                 "# Default: 10                                              #\n"
-                 "# Parameter: bonus_speed_ratio (float)                     #\n"
-                 "# Default: 1.50                                            #\n"
-                 "# Parameter: slow_after_wrong (bool)                       #\n"
-                 "# Default: 0                                               #\n"
-                 "#                                                          #\n"
-                 "# (for 'feedback' speed control system):                   #\n"
-                 "# Parameter: danger_level (float)                          #\n"
-                 "# Default: 0.35                                            #\n"
-                 "# Parameter: danger_level_speedup (float)                  #\n"
-                 "# Default: 1.1                                             #\n"
-                 "# Parameter: danger_level_max (float)                      #\n"
-                 "# Default: 0.9                                             #\n"
-                 "# Parameter: city_explode_handicap (float)                 #\n"
-                 "# Default: 0                                               #\n"
-                 "#                                                          #\n"
-                 "# The comet number parameters and initial/max speed apply  #\n"
-                 "# whether or not the feedback system is activated.         #\n"
-                 "#                                                          #\n"
-                 "# 'speedup_factor' and 'slow_after_wrong' only apply if    #\n"
-                 "# feedback is not activated.                               #\n"
-                 "#                                                          #\n"
-                 "# The 'danger_level_*' and 'city_explode_handicap'         #\n"
-                 "# parameters are only used if feedback is activated.       #\n"
-                 "############################################################\n\n");
-  }
-
-  if(verbose)
-  {
-    fprintf (fp, "\n# Number of comets for first wave. Default is 2.\n");
-  }
-  fprintf(fp, "starting_comets = %d\n", Opts_StartingComets());
-
-  if(verbose)
-  {
-    fprintf (fp, "\n# Comets to add for each successive wave. Default is 2.\n");
-  }
-  fprintf(fp, "extra_comets_per_wave = %d\n", Opts_ExtraCometsPerWave());
-
-  if(verbose)
-  {
-    fprintf (fp, "\n# Maximum number of comets. Default is 10.\n");
-  }
-  fprintf(fp, "max_comets = %d\n", Opts_MaxComets());
-
-  if(verbose)
-  {
-    fprintf (fp, "\n# Starting comet speed. Default is 1.\n");
-  }
-  fprintf(fp, "speed = %.2f\n", Opts_Speed());
-
-  if(verbose)
-  {
-    fprintf (fp, "\n# Maximum speed. Default is 10.\n");
-  }
-  fprintf(fp, "max_speed = %.2f\n", Opts_MaxSpeed());
-
-  if(verbose)
-  {
-    fprintf (fp, "\n# 'speedup_factor': If feedback is not used but \n"
-                 "# 'allow_speedup' is enabled, the comet speed will be\n"
-                 "# multiplied by this factor with each new wave.\n"
-                 "# Values from 0.5 to 2 are accepted (note that a \n"
-                 "# value less than 1 causes the comets to be \n"
-                 "# slower with each wave!).\n"
-                 "# Default is 1.2 (i.e. 20 percent increase per wave)\n\n");
-  }
-  fprintf(fp, "speedup_factor = %.2f\n", Opts_SpeedupFactor());
-
-
-  if(verbose)
-  {
-    fprintf (fp, "\n# 'bonus_comet_interval' controls how frequently\n"
-                 "# special comets appear that cause a igloo to be  \n"
-                 "# rebuilt if answered correctly. The bonus comet  \n"
-                 "# appears after this number of regular comets (a  \n"
-                 "# value of 0 disables bonus comets). Default is 10. \n");
-  }
-  fprintf(fp, "bonus_comet_interval = %d\n", Opts_BonusCometInterval());
-
-
-  if(verbose)
-  {
-    fprintf (fp, "\n# 'bonus_speed_ratio' determines how fast the\n"
-                 "# bonus comets fall relative to the regular comets.\n"
-                 "# Range 1.0 - 3.0, default 1.5:\n");
-  }
-  fprintf(fp, "bonus_speed_ratio = %.2f\n", Opts_BonusSpeedRatio());
-
-
-  if(verbose)
-  {
-    fprintf (fp, "\n# 'slow_after_wrong' tells Tuxmath to go back to  \n"
-                 "# starting speed and number of comets if the player misses \n"
-                 "# a question. Useful for smaller kids. Default is 0.\n\n");
-  }
-
-  fprintf(fp, "slow_after_wrong = %d\n", Opts_SlowAfterWrong());
-
-
-  if(verbose)
-  {
-     fprintf (fp, "\n# (Feedback) Set the desired danger level.\n"
-             "# 0 = too safe, comets typically exploded at the very top\n"
-             "# 1 = too dangerous, comets typically exploded as they\n"
-             "# hit cities. Set it somewhere between these extremes. As\n"
-             "# a guideline, early elementary kids might prefer\n"
-             "# 0.2-0.3, older kids at around 0.4-0.6. Default 0.35.\n\n");
-  }
-  fprintf(fp, "danger_level = %.2f\n", Opts_DangerLevel());
-
-  if(verbose)
-  {
-     fprintf (fp, "\n# (Feedback) Set danger level speedup.\n"
-                  "# The margin of safety will decrease by this factor each\n"
-                  "# wave. Default 1.1. Note 1 = no increase in danger level.\n\n");
-  }
-  fprintf(fp, "danger_level_speedup = %.2f\n", Opts_DangerLevelSpeedup());
-
-  if(verbose)
-  {
-     fprintf (fp, "\n# (Feedback) Set the maximum danger level.\n"
-                  "# Default 0.9.\n");
-  }
-  fprintf(fp, "danger_level_max = %.2f\n", Opts_DangerLevelMax());
-
-  if (verbose)
-  { 
-     fprintf (fp, "\n# (Feedback) Set the handicap for hitting cities.\n"
-                  "# When bigger than 0, this causes the game to slow down\n"
-                  "# by an extra amount after a wave in which one or more\n"
-                  "# cities get hit. Note that this is similar to\n"
-                  "# 'slow_after_wrong', but allows for more gradual\n"
-                  "# changes. Default 0 (no extra handicap).\n\n");
-  }
-  fprintf(fp, "city_explode_handicap = %.2f\n", Opts_CityExplHandicap());
-
-  if(verbose)
-  {
-    fprintf (fp, "\n\n############################################################\n" 
-                 "#                                                          #\n"
-                 "#                  Managing User Settings                  #\n"
-                 "#                                                          #\n"
-                 "# Parameter: per_user_config (boolean)                     #\n"
-                 "# Default: 1                                               #\n"
-                 "# Parameter: homedir (string)                              #\n"
-                 "# Default: <none supplied>                                 #\n"
-                 "#                                                          #\n"
-                 "# 'per_user_config' determines whether Tuxmath will look   #\n"
-                 "# in the user's home directory for settings. Default is 1  #\n"
-                 "# (yes). If set to 0, the program will ignore the user's   #\n"
-                 "# .tuxmath file and use the the global settings in the     #\n"
-                 "# installation-wide config file.                           #\n"
-                 "#                                                          #\n"
-                 "# 'homedir' allows you to specify the location to look for #\n"
-                 "# user home directories. You probably do not want to       #\n"
-                 "# specify this unless all users share the same login       #\n"
-                 "# account. See the README for details on configuration.    #\n"
-                 "# To enable this feature, remove the '#' comment mark and  #\n"
-                 "# set the path as desired.                                 #\n"
-                 "#                                                          #\n"
-                 "# These settings cannot be changed by an ordinary user, as #\n"
-                 "# they are ignored unless the config file is Tuxmath's     #\n"
-                 "# global config file. Thus, users cannot 'lock themselves  #\n"
-                 "# out' by accidentally setting per_user_config to 0.       #\n"
-                 "############################################################\n\n");
-  }
-  fprintf(fp, "per_user_config = %d\n", Opts_GetGlobalOpt(PER_USER_CONFIG));
-  fprintf(fp, "# homedir = /servervolume/tuxmath_users\n");
-
-
-  /* print general game options (passing '1' as second arg causes */
-  /* "help" info for each option to be written to file as comments) */
-//  print_game_options(fp, 1);
-  /* print options pertaining to math questions from MathCards: */
-//  MC_PrintMathOptions(fp, 1);
-
   DEBUGMSG(debug_fileops, "Leaving write_config_file()\n");
 
   return 1;
 }
 
-
-/* write_pregame_summary() and write_postgame_summary() are used to */
-/* record data about the player's game to file for review (perhaps by */
-/* teacher). write_pregame_summary() is called at the start of each  */
-/* game and records the question list along with identifying data. It */
-/* also rotates old game summaries to successive filenames, keeping   */
-/* the last ten summaries for review. write_postgame_summary()       */
-/* the list of questions that were not answered correctly and         */
-/* calculates the percent correct.                                    */
-int write_pregame_summary(void)
-{
-  int i;
-  FILE* fp;
-  char filepath1[PATH_MAX];
-  char filepath2[PATH_MAX];
-
-  DEBUGMSG(debug_fileops,"Entering write_pregame_summary.\n")
-
-  /* Make sure tuxmath dir exists or can be created: */
-  if (!find_tuxmath_dir())
-  {
-    fprintf(stderr, "\nCould not find or create tuxmath dir\n");
-    return 0;
-  }
-
-
-
-  /* Rotate filenames of old summaries, oldest summary if present */
-  /* and leaving summary1 available for current game:             */
-
-  /* find $HOME and tack on file name: */
-  get_user_data_dir_with_subdir(filepath1);
-  strcat(filepath1, summary_filenames[NUM_SUMMARIES - 1]);
-
-  fp = fopen(filepath1, "r");
-  if (fp)
-  {
-    DEBUGMSG(debug_fileops,"\nIn write_pregame_summary() - removing oldest summary file\n")
-
-    fclose(fp);
-    remove(filepath1);
-  }
-
-  /* Now shift each old file back by one:       */
-  /* 'filepath1' is the old name for each file, */
-  /* 'filepath2' is the new name (i.e. we go from i - 1 to i). */
-  for (i = NUM_SUMMARIES - 1; i > 0; i--)
-  {
-    /* old filename: */
-    get_user_data_dir_with_subdir(filepath1);
-    strcpy(filepath2,filepath1);
-    strcat(filepath1, summary_filenames[i - 1]);
-    /* new filename: */
-    strcat(filepath2, summary_filenames[i]);
-    /* now change the name: */
-    rename(filepath1, filepath2);
-  } 
-
-  /* summary_filenames[0] (i.e. 'summary1') should now be vacant:     */
-  get_user_data_dir_with_subdir(filepath1);
-  strcat(filepath1, summary_filenames[0]);
-
-  fp = fopen(filepath1, "w"); /* "w" means start writing with empty file */
-  if (fp)
-  {
-    /* Write header and identifying data for summary file:       */
-    fprintf(fp, "************************\n"
-                "* Tuxmath Game Summary *\n"
-                "************************\n");
-    if (add_subdir)
-    {
-      /* Identify user by login if we're not in a multiuser configuration */
-      fprintf(fp, "\nPlayer: %s\n", getenv("USER"));
-    }
-    else {
-      /* Identify user by the directory name.*/
-      fprintf(fp, "\nPlayer: %s\n", get_user_name());
-    }
-
-    fprintf(fp, "\nMission: %s\n", last_config_file_name);
-
-    /* Write question list:  */
-    fprintf(fp, "\nStarting Question List:");
-    MC_PrintQuestionList(fp);
-    fprintf(fp, "\n\nNumber of Questions: %d", MC_StartingListLength());
-
-    fclose(fp);
-    DEBUGMSG(debug_fileops,"Leaving write_pregame_summary.\n")
-    return 1;
-  }
-  else /* Couldn't write file for some reason: */
-  {
-    DEBUGMSG(debug_fileops,"Can't write_pregame_summary.\n")
-    return 0;
-  }
-}
-
-int write_postgame_summary(void)
-{
-  FILE *fp;
-  char filepath1[PATH_MAX];
-  int total_answered;
-  float median_time;
-  int success = 1;
-  int write_column_names = 0;
-  time_t filetime;
-  struct stat filestat;
-  struct tm datetime;
-  char *mission_name;
-
-  get_user_data_dir_with_subdir(filepath1);
-  strcat(filepath1, summary_filenames[0]);
-
-  total_answered = MC_NumAnsweredCorrectly() + MC_NumNotAnsweredCorrectly();
-  median_time = MC_MedianTimePerQuestion();
-
-  fp = fopen(filepath1, "a"); /* "a" means append to end of file */
-  if (fp)
-  {
-    /* Write list of questions missed: */
-    fprintf(fp, "\n\n\nList Of Questions Not Answered Correctly:");
-                MC_PrintWrongList(fp);
-    fprintf(fp, "\n\nNumber Of Distinct Questions Not Answered Correctly: %d",
-                MC_WrongListLength());
-
-    /* Write post-game statistics:     */
-
-    fprintf(fp, "\n\nSummary:\n");
-    fprintf(fp, "Questions Answered:\t%d\n", total_answered);
-    fprintf(fp, "Questions Correct:\t%d\n",
-                MC_NumAnsweredCorrectly());
-    fprintf(fp, "Questions Missed:\t%d\n",
-                MC_NumNotAnsweredCorrectly());
-    /* Avoid divide-by-zero errror: */
-    if (total_answered)
-    {
-      fprintf(fp, "Percent Correct:\t%d %%\n", 
-              ((MC_NumAnsweredCorrectly() * 100)/ total_answered) );
-    }
-    else
-      fprintf(fp, "Percent Correct: (not applicable)\n");
-
-    fprintf(fp,"Median Time/Question:\t%g\n",median_time);
-
-    fprintf(fp, "Mission Accomplished:\t");
-    if (MC_MissionAccomplished())
-    {
-      fprintf(fp, "Yes!\n\n8^)\n");
-    }
-    else
-    {
-      fprintf(fp, "No.\n\n:^(\n");
-    }
-
-    fclose(fp);
-  }
-  else /* Couldn't write file for some reason: */
-  {
-    fprintf(stderr,"Summary not written.\n");
-    success = 0;
-  }
-
-  /* Append brief summary to log */
-  if (total_answered > 0) {
-    /* We're going to want to write the date.  Use the filetime  */
-    /* rather than calling "time" directly, because "time"       */
-    /* returns the time according to whatever computer is        */
-    /* running tuxmath, and in a server/client mode it's likely  */
-    /* that some of the clients' clocks may be wrong. Use      */
-    /* instead the time according to the server on which the     */
-    /* accounts are stored, which can be extracted from the      */
-    /* modification time of the summary we just wrote.           */
-    if (stat(filepath1,&filestat) == 0) {
-      filetime = filestat.st_mtime;
-    } else {
-      filetime = time(NULL);
-    }
-    localtime_r(&filetime,&datetime); /* generate broken-down time */
-
-    get_user_data_dir_with_subdir(filepath1);
-    strcat(filepath1, "log.csv");
-    /* See whether the log file already exists; if not, write */
-    /* the column names */
-    fp = fopen(filepath1, "r");
-    if (fp == NULL)
-      write_column_names = 1;
-    else
-      fclose(fp);
-    
-    fp = fopen(filepath1, "a"); /* "a" means append to end of file */
-    if (fp) {
-      if (write_column_names) {
-        fprintf(fp,"\"User\",\"Mission\",\"Date\",\"Completed?\",\"Number answered\",\"Percent correct\",\"Time per question\"\n");
-      }
-      if (last_config_file_name)
-        mission_name = strdup(last_config_file_name);
-      else
-        mission_name = strdup("[NONE]");
-      fprintf(fp,"\"%s\",\"%s\",%d/%d/%d,%d,%d,%d,%g\n", get_user_name(), get_file_name(mission_name), datetime.tm_year+1900, datetime.tm_mon+1, datetime.tm_mday, MC_MissionAccomplished(), total_answered, ((MC_NumAnsweredCorrectly() * 100)/ total_answered), median_time);
-      fclose(fp);
-      free(mission_name);
-    } else
-      success = 0;
-  }
-  return success;
-}
-
-
-
 /* Checks to see if user's .tuxmath directory exists and, if not, tries  */
 /* to create it. Returns 1 if .tuxmath dir found or successfully created */
 static int find_tuxmath_dir(void)
diff --git a/src/game.c b/src/game.c
index 287a851..05afa35 100644
--- a/src/game.c
+++ b/src/game.c
@@ -32,204 +32,28 @@
 #include "SDL_mixer.h"
 #endif
 
-/* Make sure we don't try to call network code if we built without */
-/* network support:                                                */
-#ifdef HAVE_LIBSDL_NET
-#include "network.h"
-#endif
-
 #include "transtruct.h"
 #include "game.h"
 #include "fileops.h"
 #include "setup.h"
 #include "loaders.h"
-#include "mathcards.h"
-#include "multiplayer.h"
 #include "titlescreen.h"
 #include "options.h"
 #include "SDL_extras.h"
 #include "pixels.h"
-#include "throttle.h"
 
 
 #define FPS 15                     /* 15 frames per second */
 #define MS_PER_FRAME (1000 / FPS)
 
-#define CITY_EXPL_START (3 * 5)  /* Must be mult. of 5 (number of expl frames) */
-#define ANIM_FRAME_START (4 * 2) /* Must be mult. of 2 (number of tux frames) */
-#define GAMEOVER_COUNTER_START 40
-#define LEVEL_START_WAIT_START 20
-#define LASER_START 5
-#define FLAPPING_START 12
-#define FLAPPING_INTERVAL 500
-#define STEAM_START 15
-#define IGLOO_SWITCH_START 8
-#define STANDING_COUNTER_START 8
-#define EVAPORATING_COUNTER_START 100
-
-#define PENGUIN_WALK_SPEED 3
-#define SNOWFLAKE_SPEED 6
-#define SNOWFLAKE_SEPARATION 3
-
-const int SND_IGLOO_SIZZLE = SND_SIZZLE;
-const int IMG_CITY_NONE = 0;
-
-typedef struct comet_type {
-  int alive;
-  int expl;
-  int city;
-  float x, y;
-  int answer;
-  int bonus;
-  int zapped;
-  MC_FlashCard flashcard;
-  Uint32 time_started;
-} comet_type;
-
-/* Local (to game.c) 'globals': */
-
-static int gameover_counter;
-static int game_status;
-static int user_quit_received;
-static int total_questions_left;
-static int paused;
-static int wave;
-static int score;
-static int pre_wave_score;
-static int prev_wave_comets;
-static int slowdown;
-static int num_attackers;
-static float speed;
-static int demo_countdown;
-static int tux_anim;
-static int tux_anim_frame;
-static int num_cities_alive;
-static int tux_img;
-static int old_tux_img;
-static int frame;
-static int neg_answer_picked;
-static int tux_pressing;
-static int doing_answer;
-static int level_start_wait;
-static int last_bkgd;
-static int igloo_vertical_offset;
-//static int extra_life_counter;
-static int bonus_comet_counter;
-static int extra_life_earned;
-static int key_pressed;
-static int game_over_other;
-static int game_over_won;
-
-/* Feedback-related variables */
-static int city_expl_height;
-static int comet_feedback_number;
-static float comet_feedback_height;
-static float danger_level;
-
-static int digits[MC_MAX_DIGITS];
-
-static comet_type* comets = NULL;
-static city_type* cities = NULL;
-static penguin_type* penguins = NULL;
-static steam_type* steam = NULL;
-
-static cloud_type cloud;
-static laser_type laser;
 static SDL_Surface* bkgd = NULL; //640x480 background (windowed)
 static SDL_Surface* scaled_bkgd = NULL; //native resolution (fullscreen)
 
-static SDL_Surface* current_bkgd()
-  { return screen->flags & SDL_FULLSCREEN ? scaled_bkgd : bkgd; }
-
-static game_message s1, s2, s3, s4, s5;
-static int start_message_chosen = 0;
-
-/*****************************************************************/
-MC_FlashCard quest_queue[QUEST_QUEUE_SIZE];    //current questions
-int remaining_quests = 0;
-static int comet_counter = 0;
-static int lan_players = 0;
-char lan_pnames[MAX_CLIENTS][NAME_SIZE];
-int lan_pscores[MAX_CLIENTS];
-/****************************************************************/
-
-typedef struct {
-  int x_is_blinking;
-  int extra_life_is_blinking;
-  int laser_enabled;
-} help_controls_type;
-static help_controls_type help_controls;
-
-/* Local function prototypes: */
-static int  game_initialize(void);
-static void game_cleanup(void);
-static void game_handle_help(void);
-static void game_handle_user_events(void);
-static void game_handle_demo(void);
-static void game_handle_answer(void);
-static void game_countdown(void);
-static void game_handle_tux(void);
-static void game_handle_comets(void);
-static void game_handle_cities(void);
-static void game_handle_penguins(void);
-static void game_handle_steam(void);
-static void game_handle_extra_life(void);
-static void game_draw(void);
-static void game_draw_background(void);
-static void game_draw_comets(void);
-static void game_draw_cities(void);
-static void game_draw_misc(void);
-
-static int check_extra_life(void);
-static int check_exit_conditions(void);
-
-static void game_set_message(game_message*, const char* ,int x, int y);
-static void game_clear_message(game_message*);
-static void game_clear_messages(void);
-void game_write_message(const game_message* msg);
-static void game_write_messages(void);
-static void draw_led_console(void);
-static void draw_question_counter(void);
-static void draw_console_image(int i);
-
-static void reset_level(void);
-static int add_comet(void);
-static void add_score(int inc);
-static void reset_comets(void);
-static int num_comets_alive(void);
-
-static void game_mouse_event(SDL_Event event);
-static void game_key_event(SDLKey key, SDLMod mod);
-static void free_on_exit(void);
-
-static void help_add_comet(const char* formula_str, const char* ans_str);
-static int help_renderframe_exit(void);
-static void game_recalc_positions(void);
-
-void putpixel(SDL_Surface* surface, int x, int y, Uint32 pixel);
-
-/*****************************************************/
-#ifdef HAVE_LIBSDL_NET
-void game_handle_net_messages(void);
-void game_handle_net_msg(char* buf);
-int add_quest_recvd(char* buf);
-int remove_quest_recvd(char* buf);
-int connected_players_recvd(char* buf);
-int update_score_recvd(char* buf);
-int erase_comet_on_screen(comet_type* comet_ques);
-MC_FlashCard* search_queue_by_id(int id);
-comet_type* search_comets_by_id(int id);
-/******************************************************/
-#endif
-
-void print_current_quests(void);
-
-static void print_exit_conditions(void);
-static void print_status(void);
-
-
-/* --- MAIN GAME FUNCTION!!! --- */
 
+static SDL_Surface* current_bkgd()
+  { 
+      return screen->flags & SDL_FULLSCREEN ? scaled_bkgd : bkgd; 
+  }
 
 int game(void)
 {
@@ -243,3714 +67,4 @@ int game(void)
     ;//SwitchScreenMode();  //Huh??
   }
 
-
-   /* most code moved into smaller functions (game_*()): */
-  if (!game_initialize())
-  {
-    fprintf(stderr, "\ngame_initialize() failed!");
-    return 0;
-  }
-
-
-  if (Opts_HelpMode()) {
-    game_handle_help();
-    game_cleanup();
-    return GAME_OVER_OTHER;
-  }
- 
-
-
-  /* --- MAIN GAME LOOP: --- */
-  do
-  {
-    /* reset or increment various things with each loop: */
-    frame++;
-    old_tux_img = tux_img;
-    tux_pressing = 0;
-
-    if (laser.alive > 0)
-    {
-      laser.alive--;
-    }
-
-    /* Check for server messages if we are playing a LAN game: */
-#ifdef HAVE_LIBSDL_NET
-    if(Opts_LanMode())
-    {
-      game_handle_net_messages();
-    }
-#endif
-    /* Most code now in smaller functions: */
-
-    // 1. Check for user input
-    game_handle_user_events();
-    // 2. Update state of various game elements
-    game_handle_demo();
-    game_handle_answer();
-    game_countdown();
-    game_handle_tux();
-    game_handle_comets();
-    game_handle_cities();
-    game_handle_penguins();
-    game_handle_steam();
-    game_handle_extra_life();
-    // 3. Redraw:
-    game_draw();
-    // 4. Figure out if we should leave loop:
-    game_status = check_exit_conditions(); 
-
-    /* If we're in "PAUSE" mode, pause! */
-    if (paused)
-    {
-      pause_game();
-      paused = 0;
-    }
-
-      /* Keep playing music: */
-
-#ifndef NOSOUND
-    if (Opts_UsingSound())
-    {
-      if (!Mix_PlayingMusic())
-      {
-            Mix_PlayMusic(musics[MUS_GAME + (rand() % 3)], 0);
-      }
-    }
-#endif
-
-
-    /* Pause (keep frame-rate event) */
-    Throttle(MS_PER_FRAME, &timer);
-
-  }
-  while(GAME_IN_PROGRESS == game_status);
-  /* END OF MAIN GAME LOOP! */
-
-
-  DEBUGCODE(debug_game) print_exit_conditions();
-
-  /* TODO: need better "victory" screen with animation, special music, etc., */
-  /* as well as options to review missed questions, play again using missed  */
-  /* questions as question list, etc.                                        */
-  switch (game_status)
-  {
-    SDL_Rect dest_message;
-    SDL_Rect dest_tux;
-    SDL_Event event;
-
-    case GAME_OVER_WON:
-    {
-      int looping = 1;
-      int tux_offset = 0;
-      int tux_step = -3;
-
-      /* set up victory message: */
-      dest_message.x = (screen->w - images[IMG_GAMEOVER_WON]->w) / 2;
-      dest_message.y = (screen->h - images[IMG_GAMEOVER_WON]->h) / 2;
-      dest_message.w = images[IMG_GAMEOVER_WON]->w;
-      dest_message.h = images[IMG_GAMEOVER_WON]->h;
-
-      do
-      {
-        frame++;
-
-        while (SDL_PollEvent(&event) > 0)
-        {
-          if  (event.type == SDL_QUIT
-            || event.type == SDL_KEYDOWN
-            || event.type == SDL_MOUSEBUTTONDOWN)
-          {
-            looping = 0;
-          }
-        }
-
-        if (current_bkgd() )
-          SDL_BlitSurface(current_bkgd(), NULL, screen, NULL);
-
-        /* draw flashing victory message: */
-        if (((frame / 2) % 4))
-        {
-          SDL_BlitSurface(images[IMG_GAMEOVER_WON], NULL, screen, &dest_message);
-        }
-
-        /* draw dancing tux: */
-        draw_console_image(IMG_CONSOLE_BASH);
-        /* walk tux back and forth */
-        tux_offset += tux_step;
-        /* select tux_egypt images according to which way tux is headed: */
-        if (tux_step < 0)
-          tux_img = IMG_TUX_EGYPT1 + ((frame / 3) % 2);
-        else
-          tux_img = IMG_TUX_EGYPT3 + ((frame / 3) % 2);
-
-        /* turn around if we go far enough: */
-        if (tux_offset >= (screen->w)/2
-         || tux_offset <= -(screen->w)/2)
-        {
-          tux_step = -tux_step;
-        }
-
-        dest_tux.x = ((screen->w - images[tux_img]->w) / 2) + tux_offset;
-        dest_tux.y = (screen->h - images[tux_img]->h);
-        dest_tux.w = images[tux_img]->w;
-        dest_tux.h = images[tux_img]->h;
-
-        SDL_BlitSurface(images[tux_img], NULL, screen, &dest_tux);
-
-/*        draw_console_image(tux_img);*/
-
-        SDL_Flip(screen);
-        Throttle(MS_PER_FRAME, &timer);
-      }
-      while (looping);
-      break;
-    }
-
-    case GAME_OVER_ERROR:
-      DEBUGMSG(debug_game, "game() exiting with error:\n");
-    case GAME_OVER_LOST:
-    case GAME_OVER_OTHER:
-    {
-      int looping = 1;
-
-      /* set up GAMEOVER message: */
-      dest_message.x = (screen->w - images[IMG_GAMEOVER]->w) / 2;
-      dest_message.y = (screen->h - images[IMG_GAMEOVER]->h) / 2;
-      dest_message.w = images[IMG_GAMEOVER]->w;
-      dest_message.h = images[IMG_GAMEOVER]->h;
-
-      do
-      {
-        frame++;
-
-        while (SDL_PollEvent(&event) > 0)
-        {
-          if  (event.type == SDL_QUIT
-            || event.type == SDL_KEYDOWN
-            || event.type == SDL_MOUSEBUTTONDOWN)
-          {
-            looping = 0;
-          }
-        }
-
-        SDL_BlitSurface(images[IMG_GAMEOVER], NULL, screen, &dest_message);
-        SDL_Flip(screen);
-
-        Throttle(MS_PER_FRAME, &timer);
-      }
-      while (looping);
-
-      break;
-    }
-
-    case GAME_OVER_ESCAPE:
-    {
-      break;
-    }
-
-    case GAME_OVER_WINDOW_CLOSE:
-    {
-      break;
-    }
-
-  }
-
-  game_cleanup();
-
-  /* Write post-game info to game summary file: */
-  if (Opts_SaveSummary())
-  {
-    write_postgame_summary();
-  }
-
-  /* Save score in case needed for high score table: */
-  Opts_SetLastScore(score);
-
-  /* Return the chosen command: */
-  if (GAME_OVER_WINDOW_CLOSE == game_status)
-  {
-    /* program exits: */
-    cleanup();
-    DEBUGMSG(debug_game, "Leaving game() from window close\n");
-    return 1;
-  }
-  else
-  {
-    /* return to title() screen: */
-    DEBUGMSG(debug_game, "Leaving game() normally\n");
-    return game_status;
-  }
-}
-
-
-
-
-
-
-#ifdef HAVE_LIBSDL_NET
-/*****************   Functions for LAN support  *****************/
-
-/*Examines the network messages from the buffer and calls
-  appropriate function accordingly*/
-
-void game_handle_net_messages(void)
-{
-  char buf[NET_BUF_LEN];
-  int done = 0;
-  while(!done)
-  {
-    switch(LAN_NextMsg(buf))
-    {
-      case 1:   //Message received (e.g. a new question):
-        game_handle_net_msg(buf);
-        break;
-      case 0:   //No more messages:
-        done = 1;
-        break;
-      case -1:  //Error in networking or server:
-        game_cleanup();
-        game_status = GAME_OVER_ERROR;
-      default:
-        {}
-    }
-  }
-}
-
-
-void game_handle_net_msg(char* buf)
-{
-  DEBUGMSG(debug_lan, "Received server message: %s\n", buf);
-
-  if(strncmp(buf, "PLAYER_MSG", strlen("PLAYER_MSG")) == 0)
-  {
-    DEBUGMSG(debug_lan, "buf is %s\n", buf);                                                  
-  }
-
-  else if(strncmp(buf, "ADD_QUESTION", strlen("ADD_QUESTION")) == 0)
-  {
-    if(!add_quest_recvd(buf))
-      printf("ADD_QUESTION received but could not add question\n");
-    else  
-      DEBUGCODE(debug_game) print_current_quests();
-  }
-
-  else if(strncmp(buf, "REMOVE_QUESTION", strlen("REMOVE_QUESTION")) == 0)
-  {
-    if(!remove_quest_recvd(buf)) //remove the question with id in buf
-      printf("REMOVE_QUESTION received but could not remove question\n");
-    else 
-      DEBUGCODE(debug_game) print_current_quests();
-  }
-
-  else if(strncmp(buf, "TOTAL_QUESTIONS", strlen("TOTAL_QUESTIONS")) == 0)
-  {
-    sscanf(buf,"%*s %d", &total_questions_left);
-    if(!total_questions_left)
-      game_over_other = 1;
-  }
-
-  else if(strncmp(buf, "CONNECTED_PLAYERS", strlen("CONNECTED_PLAYERS")) == 0)
-  {
-    connected_players_recvd(buf);
-  }
-
-  else if(strncmp(buf, "UPDATE_SCORE", strlen("UPDATE_SCORE")) == 0)
-  {
-    update_score_recvd(buf);
-  }
-
-  else if(strncmp(buf, "MISSION_ACCOMPLISHED", strlen("MISSION_ACCOMPLISHED")) == 0)
-  {
-    game_over_won = 1;
-  }
-  else
-  {
-    DEBUGMSG(debug_game, "Unrecognized message from server: %s\n", buf);
-  }  
-}
-
-
-int add_quest_recvd(char* buf)
-{
-  /* Empty slots indicated by question_id == -1 */
-  MC_FlashCard* fc = search_queue_by_id(-1);
-
-  DEBUGMSG(debug_game, "Enter add_quest_recvd(), buf is: %s\n", buf);
-
-  // if fc = NULL means no empty slot for question
-  if(!buf)
-  {
-    printf("NULL buf\n");
-    return 0;
-  }
-
-  if(!fc)
-  {
-    printf("NULL fc - no empty slot for question\n");
-    return 0;
-  }
-
-  /* function call to parse buffer and receive question */
-  if(!Make_Flashcard(buf, fc))
-  {
-    printf("Unable to parse buffer into FlashCard\n");
-    return 0;
-  }
-
-  DEBUGCODE(debug_game) print_current_quests();
-
-  /* If we have an open comet slot, put question in: */
-  
-  if(num_attackers > 0)
-    if(add_comet())
-      num_attackers--;
-
-  return 1;
-}
-
-
-int remove_quest_recvd(char* buf)
-{
-  int id = 0;
-  char* p = NULL;
-  MC_FlashCard* fc = NULL;
-  comet_type* comet_screen;
-
-  if(!buf)
-    return 0;
-
-  p = strchr(buf, '\t');
-  if(!p)
-    return 0;
-
-  p++;
-  id = atoi(p);
-
-  DEBUGMSG(debug_game, "remove_quest_recvd() for id = %d\n", id);
-
-  if(id < 1)  // The question_id can never be negative or zero
-    return 0;
-
-  comet_screen = search_comets_by_id(id);
-  fc = search_queue_by_id(id);
-  if(!comet_screen && !fc)
-    return 0;
-
-  if(comet_screen)
-  {
-    DEBUGMSG(debug_game, "comet on screen found with question_id = %d\n", id);
-    erase_comet_on_screen(comet_screen);
-  }
-
-  //NOTE: normally the question should no longer be in the queue,
-  //so the next statement should not get executed:
-  if(fc)
-  {
-    DEBUGMSG(debug_game,
-             "Note - request to erase question still in queue: %s\n",
-             fc->formula_string);
-    MC_ResetFlashCard(fc);
-  }
-
-  return 1;
-}
-
-
-/* Here we have been told how many LAN players are still    */
-/* in the game. This should always be followed by a series  */
-/* of UPDATE_SCORE messages, each with the name and score  */
-/* of a player. We clear out the array to get rid of anyone */
-/* who has disconnected.                                    */
-int connected_players_recvd(char* buf)
-{
-  int n = 0;
-  int i = 0;
-  char* p = NULL;
-
-  if(!buf)
-    return 0;
-
-  p = strchr(buf, '\t');
-  if(!p)
-    return 0;
-  p++;
-  n = atoi(p);
-
-  DEBUGMSG(debug_game, "connected_players_recvd() for n = %d\n", n);
-
-  if(n < 0 || n > MAX_CLIENTS)
-  {
-    fprintf(stderr, "connected_players_recvd() - illegal value: %d\n", n);
-    return -1;
-  }
-  lan_players = n;
-
-  /* Reset array - we should be getting new values in immediately */
-  /* following messages.                                          */
-  for(i = 0; i < MAX_CLIENTS; i++)
-  {
-    lan_pnames[i][0] = '\0';
-    lan_pscores[i] = -1;
-  }
-  return n;
-}
-
-/* Receive the name and current score of a currently-connected */
-/* LAN player.                                                 */
-int update_score_recvd(char* buf)
-{
-  int i = 0;
-  char* p = NULL;
-
-  if(buf == NULL)
-    return 0;
-  // get i:
-  p = strchr(buf, '\t');
-  if(!p)
-    return 0;
-  p++;
-  i = atoi(p);
-
-  //get name:
-  p = strchr(p, '\t');
-  if(!p)
-    return 0;
-  p++;
-  strncpy(lan_pnames[i], p, NAME_SIZE);
-  //This has most likely copied the score field as well, so replace the
-  //tab delimiter with a null to terminate the string:
-  {
-    char* p2 = strchr(lan_pnames[i], '\t');
-    if (p2)
-      *p2 = '\0';
-  }
-
-  //Now get score:
-  p = strchr(p, '\t');
-  if(p)
-    lan_pscores[i] = atoi(p);
-
-  DEBUGMSG(debug_lan, "update_score_recvd() - buf is: %s\n", buf);
-  DEBUGMSG(debug_lan, "i is: %d\tname is: %s\tscore is: %d\n", 
-           i, lan_pnames[i], lan_pscores[i]);
-
-  return 1;
-}
-
-/* Return a pointer to an empty comet slot, */
-/* returning NULL if no vacancy found:      */
-
-MC_FlashCard* search_queue_by_id(int id)
-{
-  int i = 0;
-  for(i = 0; i < QUEST_QUEUE_SIZE; i++)
-  {
-    if(quest_queue[i].question_id == id)
-      return &quest_queue[i];
-  }
-  //if we don't find a match:
-  return NULL;
-}
-
-
-comet_type* search_comets_by_id(int id)
-{
-  int i;
-  for (i = 0; i < Opts_MaxComets(); i++)
-  {
-    if (comets[i].flashcard.question_id == id)
-    {
-      DEBUGMSG(debug_lan, "the question id is in slot %d\n", i);
-      return &comets[i];
-    }
-  }
-  // Didn't find it:
-  return NULL;
-}
-
-
-
-int erase_comet_on_screen(comet_type* comet)
-{
-  if(!comet)
-    return 0;
-  //setting expl to 0 starts comet explosion animation
-  comet->expl = 0;
-
-  //TODO consider more elaborate sound or animation
-  playsound(SND_SIZZLE);
-
-  return 1;
-}
-
-#endif
-
-/* Print the current questions and the number of remaining questions: */
-void print_current_quests(void)
-{
-  int i;
-  printf("\n------------  Current Questions:  -----------\n");
-  for(i = 0; i < Opts_MaxComets(); i++)
-  { 
-    if(comets[i].alive == 1)
-     printf("Comet %d - question %d:\t%s\n", i, comets[i].flashcard.question_id, comets[i].flashcard.formula_string);
-
-  }
-  printf("--------------Question Queue-----------------\n");
-  for(i = 0; i < QUEST_QUEUE_SIZE; i++)
-  {
-    if(quest_queue[i].question_id != -1)
-      printf("quest_queue %d - question %d:\t%s\n", i, quest_queue[i].question_id, quest_queue[i].formula_string);
-    else
-      printf("quest_queue %d:\tEmpty\n", i);
-  }
-  printf("------------------------------------------\n");
-}
-
-
-
-
-/* 
-Set one to four lines of text to display at the game's start. Eventually
-this should stylishly fade out over the first few moments of the game.
-*/
-void game_set_start_message(const char* m1, const char* m2, 
-                            const char* m3, const char* m4)
-{
-  game_set_message(&s1, m1, -1, screen->h * 2 / 10);
-  game_set_message(&s2, m2, screen->w / 2 - 40, screen->h * 3 / 10);
-  game_set_message(&s3, m3, screen->w / 2 - 40, screen->h * 4 / 10);
-  game_set_message(&s4, m4, screen->w / 2 - 40, screen->h * 5 / 10);
-  start_message_chosen = 1;
-}
-
-
-
-int game_initialize(void)
-{
-  int i,img;
-  
-  DEBUGMSG(debug_game,"Entering game_initialize()\n");
-  
-  /* Clear window: */
-  SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
-  SDL_Flip(screen);
-
-  game_status = GAME_IN_PROGRESS;
-  gameover_counter = -1;
-  user_quit_received = 0;
-
-  /* Make sure we don't try to call network code if we built without  */
-  /* network support:                                                 */
-  /* NOTE with this check it should be safe to assume we have SDL_net */
-  /* for the rest of this file if Opts_LanMode() == 1                 */
-#ifndef HAVE_LIBSDL_NET
-  Opts_SetLanMode(0);
-#endif
-
-  /* Start MathCards backend, unless we are getting questions from network: */
-  /* FIXME may need to move this into tuxmath.c to accomodate option */
-  /* to use MC_StartUsingWrongs() */
-  /* NOTE MC_StartGame() will return 0 if the list length is zero due */
-  /* (for example) to all math operations being deselected */
-  /* NOTE if we are playing a network game, MC_StartGame() has already */
-  /* been called on the server by the time we get to here:             */
-
-  if(!Opts_LanMode())
-  {
-    if (!MC_StartGame())
-    {
-      fprintf(stderr, "\nMC_StartGame() failed!");
-      return 0;
-    } 
-    DEBUGMSG(debug_mathcards | debug_game,"MC_StartGame() finished.\n")
-  }
-  else  
-  {
-    /* Reset question queue and player name/score lists: */
-    int i;
-
-    for(i = 0; i < QUEST_QUEUE_SIZE; i ++)
-      MC_ResetFlashCard(&(quest_queue[i]));
-
-    for(i = 0; i < MAX_CLIENTS; i++)
-    {
-      lan_pnames[i][0] = '\0';
-      lan_pscores[i] = -1;
-    }
-  }
-
-  /* Allocate memory */
-  comets = NULL;  // set in case allocation fails partway through
-  cities = NULL;
-  penguins = NULL;
-  steam = NULL;
-  comets = (comet_type *) malloc(MAX_MAX_COMETS * sizeof(comet_type));
-  if (comets == NULL)
-  {
-    printf("Allocation of comets failed");
-    return 0;
-  }
-
-  cities = (city_type *) malloc(NUM_CITIES * sizeof(city_type));
-  if (cities == NULL)
-  {
-    printf("Allocation of cities failed");
-    return 0;
-  }
-
-  penguins = (penguin_type *) malloc(NUM_CITIES * sizeof(penguin_type));
-  if (penguins == NULL)
-  {
-    printf("Allocation of penguins failed");
-    return 0;
-  }
-
-  steam = (steam_type *) malloc(NUM_CITIES * sizeof(steam_type));
-  if (steam == NULL)
-  {
-    printf("Allocation of steam failed");
-    return 0;
-  }
-
- 
-  /* Write pre-game info to game summary file: */
-  if (Opts_SaveSummary())
-  {
-    write_pregame_summary();
-  }
-
-  /* Prepare to start the game: */
-  city_expl_height = screen->h - images[IMG_CITY_BLUE]->h;
-
-  /* Initialize feedback parameters */
-  comet_feedback_number = 0;
-  comet_feedback_height = 0;
-  danger_level = Opts_DangerLevel();
-
-  wave = 1;
-  num_attackers = 2;
-  prev_wave_comets = Opts_StartingComets();
-  speed = Opts_Speed();
-  slowdown = 0;
-  score = 0;
-  demo_countdown = 2000;
-  total_questions_left = 0;
-  level_start_wait = LEVEL_START_WAIT_START;
-  neg_answer_picked = 0;
-
-  /* (Create and position cities) */
-
-  if (Opts_GetGlobalOpt(USE_IGLOOS))
-    img = IMG_IGLOO_INTACT;
-  else
-    img = IMG_CITY_BLUE;
-  for (i = 0; i < NUM_CITIES; i++)
-  {
-    cities[i].hits_left = 2;
-    cities[i].status = CITY_PRESENT;
-    cities[i].counter = 0;
-    cities[i].threatened = 0;
-    cities[i].layer = 0;
-
-    /* Left vs. Right - makes room for Tux and the console */
-    if (i < NUM_CITIES / 2)
-    {
-      cities[i].x = (((screen->w / (NUM_CITIES + 1)) * i) +
-                     ((images[img] -> w) / 2));
-    }
-    else
-    {
-      cities[i].x = (screen->w -
-                 ((((screen->w / (NUM_CITIES + 1)) *
-                    (i - (NUM_CITIES / 2)) +
-                   ((images[img] -> w) / 2)))));
-    }
-  }
-
-  num_cities_alive = NUM_CITIES;
-
-  igloo_vertical_offset = images[IMG_CITY_BLUE]->h - images[IMG_IGLOO_INTACT]->h;
-
-  /* Create and position the penguins and steam */
-  for (i = 0; i < NUM_CITIES; i++)
-  {
-    penguins[i].status = PENGUIN_HAPPY;
-    penguins[i].counter = 0;
-    penguins[i].x = cities[i].x;
-    penguins[i].layer = 0;
-    steam[i].status = STEAM_OFF;
-    steam[i].layer = 0;
-    steam[i].counter = 0;
-  }
-
-  if (Opts_BonusCometInterval())
-  {
-    bonus_comet_counter = Opts_BonusCometInterval() + 1;
-    DEBUGMSG(debug_game,"\nInitializing with bonus_comet_counter = %d\n",bonus_comet_counter);
-  }
-
-  extra_life_earned = 0;
-  cloud.status = EXTRA_LIFE_OFF;
-
-  /* (Clear laser) */
-  laser.alive = 0;
-
-  /* Reset remaining stuff: */
-
-  bkgd = scaled_bkgd = NULL;
-  last_bkgd = -1;
-  reset_level();
-  reset_comets();
-
-  frame = 0;
-  paused = 0;
-  doing_answer = 0;
-  tux_pressing = 0;
-  tux_img = IMG_TUX_RELAX1;
-  tux_anim = -1;
-  tux_anim_frame = 0;
-
-  // Initialize the messages
-  game_clear_message(&s5);
-  if (!start_message_chosen)
-  {
-    game_clear_message(&s1);
-    game_clear_message(&s2);
-    game_clear_message(&s3);
-    game_clear_message(&s4);
-  }
-
-  help_controls.x_is_blinking = 0;
-  help_controls.extra_life_is_blinking = 0;
-  help_controls.laser_enabled = 1;
-
-  DEBUGMSG(debug_game,"Exiting game_initialize()\n");
-
-  return 1;
-}
-
-
-void game_cleanup(void)
-{
-#ifdef HAVE_LIBSDL_NET  
-  LAN_Cleanup();
-#endif
-
-  /* Free background: */
-  if (bkgd != NULL)
-  {
-    SDL_FreeSurface(bkgd);
-    bkgd = NULL;
-  }
-  if (scaled_bkgd != NULL)
-  {
-    SDL_FreeSurface(scaled_bkgd);
-    scaled_bkgd = NULL;
-  }
-  
-  /* clear start message */
-  start_message_chosen = 0;
-  
-  /* Free dynamically-allocated items */
-  free_on_exit();
-
-  /* Stop music: */
-#ifndef NOSOUND
-  if (Opts_UsingSound())
-  {
-    if (Mix_PlayingMusic())
-    {
-      Mix_HaltMusic();
-    }
-  }
-#endif
-
-  DEBUGMSG(debug_game, "Leaving game_cleanup():\n");
 }
-
-
-void game_handle_help(void)
-{
-  const int left_edge = 140;
-  int frame_start;
-  int quit_help = 0;
-
-  help_controls.laser_enabled = 0;
-  help_controls.x_is_blinking = 0;
-  help_controls.extra_life_is_blinking = 0;
-
-  // Here are some things that have to happen before we can safely
-  // draw the screen
-  tux_img = IMG_TUX_CONSOLE1;
-  old_tux_img = tux_img;
-  tux_pressing = 0;
-  frame = 0;
-
-  // Write the introductory text
-  game_set_message(&s1,_("Welcome to TuxMath!"),-1,50);
-
-#ifndef NOSOUND
-  if (Opts_UsingSound())
-  {
-    if (!Mix_PlayingMusic())
-    {
-      Mix_PlayMusic(musics[MUS_GAME], 0);
-    }
-  }
-#endif
-
-  // Wait 2 seconds while rendering frames
-  while (frame < 2*FPS && !(quit_help = help_renderframe_exit()));
-  if (quit_help)
-    return;
-
-  game_set_message(&s2,_("Your mission is to save your"), left_edge, 100);
-  game_set_message(&s3,_("penguins' igloos from the"), left_edge, 135);
-  game_set_message(&s4,_("falling comets."), left_edge, 170);
-
-  frame_start = frame;
-  while (frame-frame_start < 5*FPS && !(quit_help = help_renderframe_exit()));  // wait 5 more secs
-  if (quit_help)
-    return;
-
-  // Bring in a comet
-  speed = 2;
-  help_add_comet("2 + 1 = ?", "3");
-  help_controls.laser_enabled = 1;
-  level_start_wait = 0;
-
-  frame_start = frame;
-  while (comets[0].alive && frame-frame_start < 100 && !(quit_help = help_renderframe_exit())); // advance comet
-  if (quit_help)
-    return;
-
-  if (comets[0].alive == 1) {
-    game_set_message(&s1,_("Stop a comet by typing"),left_edge,100);
-    game_set_message(&s2,_("the answer to the math problem"),left_edge,135);
-    game_set_message(&s3,_("and hitting 'space' or 'enter'."),left_edge,170);
-    game_set_message(&s4,_("Try it now!"),left_edge,225);
-
-    speed = 0;
-    while (comets[0].alive && !(quit_help = help_renderframe_exit()));
-    if (quit_help)
-      return;
-  }
-
-  game_set_message(&s1,_("Good shot!"),left_edge,100);
-  game_clear_message(&s2);
-  game_clear_message(&s3);
-  game_clear_message(&s4);
-
-  help_controls.laser_enabled = 0;
-  frame_start = frame;
-  while (frame-frame_start < 3*FPS && !(quit_help = help_renderframe_exit()));  // wait 3 secs
-
-  speed = 2;
-  game_set_message(&s1,_("If an igloo gets hit by a comet,"),left_edge,100);
-  game_set_message(&s2,_("it melts. But don't worry: the"),left_edge,135);
-  game_set_message(&s3,_("penguin is OK!"),left_edge,170);
-  game_set_message(&s4,_("Just watch what happens:"),left_edge,225);
-  game_set_message(&s5,_("(Press a key to start)"),left_edge,260);
-
-  key_pressed = 0;
-  while (!key_pressed && !(quit_help = help_renderframe_exit()));
-  if (quit_help)
-    return;
-  game_clear_message(&s5);
-
-  help_add_comet("3 * 3 = ?", "9");
-  comets[0].y = 2*(screen->h)/3;   // start it low down
-  while ((comets[0].expl == -1) && !(quit_help = help_renderframe_exit()));  // wait 3 secs
-  if (quit_help)
-    return;
-  game_set_message(&s4,_("Notice the answer"),left_edge,comets[0].y-100);
-  help_renderframe_exit();
-  SDL_Delay(4000);
-  game_clear_message(&s4);
-
-  frame_start = frame;
-  while (frame-frame_start < 5*FPS && !(quit_help = help_renderframe_exit()));  // wait 5 secs
-  if (quit_help)
-    return;
-
-  game_set_message(&s1,_("If it gets hit again, the"),left_edge,100);
-  game_set_message(&s2,_("penguin leaves."),left_edge,135);
-  game_set_message(&s3,_("(Press a key when ready)"),left_edge,200);
-
-  key_pressed = 0;
-  while (!key_pressed && !(quit_help = help_renderframe_exit()));
-  if (quit_help)
-    return;
-  game_clear_message(&s3);
-
-  help_add_comet("56 / 8 = ?", "7");
-  comets[0].y = 2*(screen->h)/3;   // start it low down
-
-  while (comets[0].alive && !(quit_help = help_renderframe_exit()));
-
-  if (quit_help)
-    return;
-  frame_start = frame;
-
-  while ((frame-frame_start < 3*FPS) && !(quit_help = help_renderframe_exit()));
-
-  if (quit_help)
-    return;
-
-  help_controls.laser_enabled = 1;
-  game_set_message(&s1,_("You can fix the igloos"), left_edge,100);
-  game_set_message(&s2,_("by stopping bonus comets."), left_edge,135);
-  help_add_comet("2 + 2 = ?", "4");
-  comets[0].bonus = 1;
-  frame_start = frame;
-
-  while (comets[0].alive && (frame-frame_start < 50) && !(quit_help = help_renderframe_exit()));
-
-  if (quit_help)
-    return;
-  if (comets[0].alive)
-    speed = 0;
-  game_set_message(&s3,_("Zap it now!"),left_edge,225);
-
-  while (comets[0].alive && !(quit_help = help_renderframe_exit()));
-
-  if (quit_help)
-    return;
-  game_set_message(&s1,_("Great job!"),left_edge,100);
-  game_clear_message(&s2);
-  game_clear_message(&s3);
-  frame_start = frame;
-
-  while ((frame-frame_start < 2*FPS) && !(quit_help = help_renderframe_exit()));
-
-  if (quit_help)
-    return;
-  check_extra_life();
-  frame_start = frame;
-
-  while ((frame-frame_start < 10*FPS) && !(quit_help = help_renderframe_exit()));
-
-  if (quit_help)
-    return;
-
-
-  game_set_message(&s1,_("Quit at any time by pressing"),left_edge,100);
-  game_set_message(&s2,_("'Esc' or clicking the 'X'"),left_edge,135);
-  game_set_message(&s3,_("in the upper right corner."),left_edge,170);
-  game_set_message(&s4,_("Do it now, and then play!"),left_edge,225);
-
-  help_controls.x_is_blinking = 1;
-
-  while (!help_renderframe_exit());
-}
-
-// This function handles all the interactions expected during help
-// screens and renders a single frame. This function normally returns
-// 0, but returns 1 if the user chooses to exit help.
-int help_renderframe_exit(void)
-{
-  static Uint32 last_time = 0;
-  static Uint32 now_time;
-
-  if (last_time == 0)
-    last_time = SDL_GetTicks(); // Initialize...
-
-  tux_pressing = 0;
-  if (laser.alive > 0)
-      laser.alive--;
-  game_handle_user_events();
-  game_handle_answer();
-  game_handle_tux();
-  game_handle_comets();
-  game_handle_cities();
-  game_handle_penguins();
-  game_handle_steam();
-  game_handle_extra_life();
-  game_draw();
-  game_status = check_exit_conditions();
-
-  // Delay to keep frame rate constant. Do this in a way
-  // that won't cause a freeze if the timer wraps around.
-  now_time = SDL_GetTicks();
-  if (now_time >= last_time && now_time < last_time + MS_PER_FRAME)
-    SDL_Delay((last_time+MS_PER_FRAME) - now_time);
-  last_time = now_time;
-
-  frame++;
-
-  return (game_status != GAME_IN_PROGRESS);
-}
-
-/* explicitly create a comet with a hardcoded problem */
-void help_add_comet(const char* formula_str, const char* ans_str)
-{
-//  char probstr[MC_FORMULA_LEN];
-//  char ansstr[MC_ANSWER_LEN];
-
-  comets[0].alive = 1;
-  comets[0].expl = -1;
-  comets[0].answer = atoi(ans_str);
-//  num_comets_alive = 1;
-  comets[0].city = 0;
-  comets[0].x = cities[0].x;
-  comets[0].y = 0;
-  comets[0].zapped = 0;
-  comets[0].bonus = 0;
-
-  strncpy(comets[0].flashcard.formula_string,formula_str,MC_MaxFormulaSize() );
-  strncpy(comets[0].flashcard.answer_string,ans_str,MC_MaxAnswerSize() );
-}
-
-void game_set_message(game_message *msg,const char *txt,int x,int y)
-{
-  if (msg && txt)
-  {
-    msg->x = x;
-    msg->y = y;
-    msg->alpha = SDL_ALPHA_OPAQUE;
-    strncpy(msg->message,txt,GAME_MESSAGE_LENGTH);
-  }
-}
-
-void game_clear_message(game_message *msg)
-{
-  game_set_message(msg,"",0,0);
-}
-
-void game_clear_messages()
-{
-  game_clear_message(&s1);
-  game_clear_message(&s2);
-  game_clear_message(&s3);
-  game_clear_message(&s4);
-  game_clear_message(&s5);
-}
-
-void game_write_message(const game_message *msg)
-{
-  SDL_Surface* surf;
-  SDL_Rect rect;
-
-  if (strlen(msg->message) > 0)
-  {
-    surf = BlackOutline( _(msg->message), DEFAULT_HELP_FONT_SIZE, &white);
-    rect.w = surf->w;
-    rect.h = surf->h;
-    if (msg->x < 0)
-      rect.x = (screen->w/2) - (rect.w/2);   // centered
-    else
-      rect.x = msg->x;              // left justified
-    rect.y = msg->y;
-    //FIXME alpha blending doesn't seem to work properly
-    SDL_SetAlpha(surf, SDL_SRCALPHA, msg->alpha);
-    SDL_BlitSurface(surf, NULL, screen, &rect);
-    SDL_FreeSurface(surf);
-    //SDL_UpdateRect(screen, rect.x, rect.y, rect.w, rect.h);
-  }
-}
-
-void game_write_messages(void)
-{
-  game_write_message(&s1);
-  game_write_message(&s2);
-  game_write_message(&s3);
-  game_write_message(&s4);
-  game_write_message(&s5);
-}
-
-void game_handle_user_events(void)
-{
-  SDL_Event event;
-  SDLKey key;
-  SDLMod mod;
-
-  while (SDL_PollEvent(&event) > 0)
-  {
-    if (event.type == SDL_QUIT)
-    {
-      user_quit_received = GAME_OVER_WINDOW_CLOSE;
-    }
-    else if (event.type == SDL_KEYDOWN)
-    {
-      key = event.key.keysym.sym;
-      mod = event.key.keysym.mod;
-      game_key_event(key, mod);
-    }
-    else if (event.type == SDL_MOUSEBUTTONDOWN)
-    {
-      game_mouse_event(event);
-    }
-  }
-}
-
-void game_handle_demo(void)
-{
-  /* If not in demo mode get out: */
-  if (!Opts_DemoMode())
-  {
-    return;
-  }
-
-  /* Demo mode! */
-  {
-    static int demo_answer = 0;
-    static int answer_digit = 0;
-    static int picked_comet=-1;
-
-    if (picked_comet == -1 && (rand() % 10) < 3)
-    {
-      /* Demo mode!  Randomly pick a comet to destroy: */
-      picked_comet = (rand() % Opts_MaxComets());
-
-      if (!(comets[picked_comet].alive &&
-            comets[picked_comet].expl == -1)
-          || comets[picked_comet].y < 80)
-      {
-        picked_comet = -1;
-      }
-      else
-      {
-        /* found a comet to blow up! */
-        demo_answer = comets[picked_comet].answer;
-        if ((rand() % 3) < 1)
-          demo_answer--;  // sometimes get it wrong on purpose
-
-        DEBUGMSG(debug_game, "Demo mode, comet %d attacked with answer %d\n", picked_comet,demo_answer);
-
-        /* handle negative answer: */
-        if (demo_answer < 0)
-        {
-          demo_answer = -demo_answer;
-          neg_answer_picked = 1;
-        }
-        if (demo_answer >= 100)
-          answer_digit = 0;
-        else if (demo_answer >= 10)
-          answer_digit = 1;
-        else
-          answer_digit = 2;
-      }
-    }
-
-    /* Add a digit: */
-    if (picked_comet != -1 && (frame % 5) == 0 && (rand() % 10) < 8)
-    {
-      tux_pressing = 1;
-
-      if (answer_digit < 3)
-      {
-        digits[0] = digits[1];
-        digits[1] = digits[2];
-
-        if (answer_digit == 0)
-        {
-          digits[2] = demo_answer / 100;
-        }
-        else if (answer_digit == 1)
-        {
-          digits[2] = (demo_answer % 100) / 10;
-        }
-        else if (answer_digit == 2)
-        {
-          digits[2] = (demo_answer % 10);
-        }
-
-        answer_digit++;
-      }
-      else
-      {
-        /* "Press Return" */
-        DEBUGMSG(debug_game, "Demo mode firing with these digits: %d%d%d\n",
-                 digits[0], digits[1], digits[2]);
-        doing_answer = 1;
-        picked_comet = -1;
-      }
-    }
-
-    /* Count down counter: */
-    demo_countdown--;
-  }
-}
-
-void game_handle_answer(void)
-{
-  int i, j, lowest, lowest_y;
-  char ans[MC_MAX_DIGITS + 2]; //extra space for negative, and for final '\0'
-  Uint32 ctime;
-
-  if (!doing_answer)
-  {
-    return;
-  }
-
-  doing_answer = 0;
-
-  /* negative answer support DSB */
-  
-  ans[0] = '-'; //for math questions only, this is just replaced.
-  for (i = 0; i < MC_MAX_DIGITS - 1 && !digits[i]; ++i); //skip leading 0s
-  for (j = neg_answer_picked ? 1 : 0; i < MC_MAX_DIGITS; ++i, ++j)
-    ans[j] = digits[i] + '0';
-  ans[j] = '\0';
-  
-
-
-  /*  Pick the lowest comet which has the right answer: */
-  /*  FIXME: do we want it to prefer bonus comets to regular comets? */
-  lowest_y = 0;
-  lowest = -1;
-
-  for (i = 0; i < Opts_MaxComets(); i++)
-  {
-    if (comets[i].alive &&
-        comets[i].expl == -1 &&
-        //comets[i].answer == num &&
-        0 == strncmp(comets[i].flashcard.answer_string, ans, MC_MAX_DIGITS+1) &&
-        comets[i].y > lowest_y)
-    {
-      lowest = i;
-      lowest_y = comets[i].y;
-    }
-  }
-
-  /* If there was a comet with this answer, destroy it! */
-  if (lowest != -1)  /* -1 means no comet had this answer */
-  {
-    float t;
-    /* Store the time the question was present on screen (do this */
-    /* in a way that avoids storing it if the time wrapped around */
-    ctime = SDL_GetTicks();
-    if (ctime > comets[lowest].time_started)
-      t = ((float)(ctime - comets[lowest].time_started)/1000);
-    else
-      t = -1;   //Mathcards will ignore t == -1
-    /* Tell Mathcards or the server that we answered correctly: */
-    if(Opts_LanMode())
-#ifdef HAVE_LIBSDL_NET
-      LAN_AnsweredCorrectly(comets[lowest].flashcard.question_id, t);
-#else
-      {}  // Needed for compiler, even though this path can't occur
-#endif      
-    else
-      MC_AnsweredCorrectly(comets[lowest].flashcard.question_id, t);
-
-
-    /* Destroy comet: */
-    comets[lowest].expl = 0;
-    comets[lowest].zapped = 1;
-    /* Fire laser: */
-    laser.alive = LASER_START;
-    laser.x1 = screen->w / 2;
-    laser.y1 = screen->h;
-    laser.x2 = comets[lowest].x;
-    laser.y2 = comets[lowest].y;
-    playsound(SND_LASER);
-    playsound(SND_SIZZLE);
-
-    /* Record data for feedback */
-    if (Opts_UseFeedback())
-    {
-      comet_feedback_number++;
-      comet_feedback_height += comets[lowest].y/city_expl_height;
-
-#ifdef FEEDBACK_DEBUG
-      printf("Added comet feedback with height %g\n",comets[lowest].y/city_expl_height);
-#endif
-    }
-
-    /* Pick Tux animation: */
-    /* 50% of the time.. */
-    if ((rand() % 10) < 5)
-    {
-      /* ... pick an animation to play: */
-      if ((rand() % 10) < 5)
-        tux_anim = IMG_TUX_YES1;
-      else
-        tux_anim = IMG_TUX_YAY1;
-      tux_anim_frame = ANIM_FRAME_START;
-    }
-
-    /* Increment score: */
-
-    /* [ add = 25, sub = 50, mul = 75, div = 100 ] */
-    /* [ the higher the better ] */
-    /* FIXME looks like it might score a bit differently based on screen mode? */
-    add_score(25 * comets[lowest].flashcard.difficulty *
-              (screen->h - comets[lowest].y + 1) /
-               screen->h);
-  }
-  else
-  {
-    /* Didn't hit anything! */
-    laser.alive = LASER_START;
-    laser.x1 = screen->w / 2;
-    laser.y1 = screen->h;
-    laser.x2 = laser.x1;
-    laser.y2 = 0;
-    playsound(SND_LASER);
-    playsound(SND_BUZZ);
-
-    if ((rand() % 10) < 5)
-      tux_img = IMG_TUX_DRAT;
-    else
-      tux_img = IMG_TUX_YIPE;
-  }
-
-  /* Clear digits: */
-  for (i = 0; i < MC_MAX_DIGITS; ++i)
-    digits[i] = 0;
-  neg_answer_picked = 0;
-}
-
-void game_countdown(void)
-{
-  if (level_start_wait <= 0)
-  {
-    game_clear_messages();
-    return;
-  }
-
-  //dim start messages
-  s1.alpha -= SDL_ALPHA_OPAQUE / LEVEL_START_WAIT_START;
-  s2.alpha -= SDL_ALPHA_OPAQUE / LEVEL_START_WAIT_START;
-  s3.alpha -= SDL_ALPHA_OPAQUE / LEVEL_START_WAIT_START;
-  s4.alpha -= SDL_ALPHA_OPAQUE / LEVEL_START_WAIT_START;
-  DEBUGMSG(debug_game, "alpha = %d\n", s1.alpha);
-
-  level_start_wait--;
-  if (level_start_wait > LEVEL_START_WAIT_START / 4)
-    tux_img = IMG_TUX_RELAX1;
-  else if (level_start_wait > 0)
-    tux_img = IMG_TUX_RELAX2;
-  else
-    tux_img = IMG_TUX_SIT;
-
-  if (level_start_wait == LEVEL_START_WAIT_START / 4)
-  {
-    playsound(SND_ALARM);
-  }
-}
-
-void game_handle_tux(void)
-{
-  static int tux_same_counter;
-  /* If Tux pressed a button, pick a new (different!) stance: */
-  if (tux_pressing)
-  {
-    do { tux_img = IMG_TUX_CONSOLE1 + (rand() % 4); }
-    while (tux_img == old_tux_img);
-    playsound(SND_TOCK);
-  }
-
-  /* If Tux is being animated, show the animation: */
-  if (tux_anim != -1)
-  {
-    tux_anim_frame--;
-    if (tux_anim_frame < 0)
-      tux_anim = -1;
-    else
-      tux_img = tux_anim + 1 - (tux_anim_frame / (ANIM_FRAME_START / 2));
-  }
-
-  /* Reset Tux to sitting if he's been doing nothing for a while: */
-  if (old_tux_img == tux_img)
-  {
-    tux_same_counter++;
-    if (tux_same_counter >= 20)
-    {
-      tux_img = IMG_TUX_SIT;
-    }
-  }
-  else
-    tux_same_counter = 0;
-}
-
-//FIXME might be simpler to store vertical position (and speed) in terms of time
-//rather than absolute position, and determine the latter in game_draw_comets()
-void game_handle_comets(void)
-{
-  /* Handle comets. Since the comets also are the things that trigger
-     changes in the cities, we set some flags in them, too. */
-  int i, this_city;
-  Uint32 ctime;
-
-//  num_comets_alive = 0;
-
-  /* Clear the threatened flag on each city */
-  for (i = 0; i < NUM_CITIES; i++)
-    cities[i].threatened = 0;
-
-  for (i = 0; i < Opts_MaxComets(); i++)
-  {
-    if (comets[i].alive)
-    {
-//     num_comets_alive++;
-      this_city = comets[i].city;
-
-      /* Update comet position */
-      comets[i].x = comets[i].x + 0; /* no lateral motion for now! */
-      /* Make bonus comet move faster at chosen ratio: */
-      /* NOTE y increment scaled to make game play similar at any resolution */
-      if (comets[i].bonus)
-      {
-        comets[i].y += speed * Opts_BonusSpeedRatio() *
-                       city_expl_height / (screen->h - images[IMG_CITY_BLUE]->h);
-      }
-      else /* Regular comet: */
-      {
-        comets[i].y += speed *
-                       city_expl_height / (screen->h - images[IMG_CITY_BLUE]->h);
-      }
-
-      /* Does it threaten a city? */
-      if (comets[i].y > 3 * screen->h / 4)
-        cities[this_city].threatened = 1;
-
-      /* Did it hit a city? */
-      if (comets[i].y >= city_expl_height &&
-          comets[i].expl == -1)
-      {
-        /* Tell MathCards about it - question not answered correctly: */
-        if(Opts_LanMode())
-#ifdef HAVE_LIBSDL_NET
-          LAN_NotAnsweredCorrectly(comets[i].flashcard.question_id);
-#else
-          {}
-#endif
-        else
-          MC_NotAnsweredCorrectly(comets[i].flashcard.question_id);
-
-        /* Store the time the question was present on screen (do this */
-        /* in a way that avoids storing it if the time wrapped around */
-        ctime = SDL_GetTicks();
-        if (ctime > comets[i].time_started) {
-          MC_AddTimeToList((float)(ctime - comets[i].time_started)/1000);
-        }
-
-        /* Record data for speed feedback */
-        /* Do this only for cities that are alive; dead cities */
-        /* might not get much protection from the player */
-        if (Opts_UseFeedback() && cities[this_city].hits_left) {
-          comet_feedback_number++;
-          comet_feedback_height += 1.0 + Opts_CityExplHandicap();
-
-#ifdef FEEDBACK_DEBUG
-           printf("Added comet feedback with height %g\n",
-                  1.0 + Opts_CityExplHandicap());
-#endif
-         }
-
-        /* Disable shields/destroy city/create steam cloud: */
-        if (cities[this_city].hits_left)
-        {
-          cities[this_city].status = CITY_EXPLODING;
-          if (Opts_GetGlobalOpt(USE_IGLOOS)) {
-            playsound(SND_IGLOO_SIZZLE);
-            cities[this_city].counter = IGLOO_SWITCH_START;
-            steam[this_city].status = STEAM_ON;
-            steam[this_city].counter = STEAM_START;
-          }
-          else {
-            if (cities[comets[i].city].hits_left == 2) {
-              playsound(SND_SHIELDSDOWN);
-              cities[this_city].counter = 1;  /* Will act immediately */
-            }
-            else {
-              playsound(SND_EXPLOSION);
-              cities[this_city].counter = CITY_EXPL_START;
-            }
-          }
-          cities[this_city].hits_left--;
-        }
-
-        /* If this was a bonus comet, restart the counter */
-        if (comets[i].bonus)
-          bonus_comet_counter = Opts_BonusCometInterval()+1;
-
-       /* If slow_after_wrong selected, set flag to go back to starting speed and */
-        /* number of attacking comets: */
-        if (Opts_SlowAfterWrong())
-        {
-          speed = Opts_Speed();
-          slowdown = 1;
-        }
-
-        tux_anim = IMG_TUX_FIST1;
-        tux_anim_frame = ANIM_FRAME_START;
-
-        /* Destroy comet: */
-        comets[i].expl = 0;
-      }
-
-      /* Handle comet explosion animation: */
-      if (comets[i].expl >= 0)
-      {
-        comets[i].expl++;
-        if (comets[i].expl >= sprites[IMG_COMET_EXPL]->num_frames * 2) {
-          comets[i].alive = 0;
-          comets[i].expl = -1;
-          if (bonus_comet_counter > 1 && comets[i].zapped) {
-            bonus_comet_counter--;
-            DEBUGMSG(debug_game, "bonus_comet_counter is now %d\n",bonus_comet_counter);
-          }
-          if (comets[i].bonus && comets[i].zapped) {
-            playsound(SND_EXTRA_LIFE);
-            extra_life_earned = 1;
-            DEBUGMSG(debug_game, "Extra life earned!");
-          }
-        }
-      }
-    }
-  }
-
-  /* FIXME for the LAN game, the adding of comets needs to take place in  */
-  /* check_messages() when new questions come in from the server.  For    */
-  /* ease of understanding, we should do it at the same place in the game */
-  /* loop for the non-LAN (i.e. local MC_*() functions) game - DSB        */
-  /* add more comets if needed: */
-  if (!Opts_HelpMode() && level_start_wait == 0) //&&
-     // (frame % 20) == 0)
-  {
-    /* num_attackers is how many comets are left in wave */
-    if (num_attackers > 0)
-    {
-//      if ((rand() % 2) == 0 || num_comets_alive() == 0)  NOTE also caused timing issue
-      {
-        if (add_comet())
-        {
-          num_attackers--;
-        }
-      }
-    }
-    else
-    {
-      if (num_comets_alive() == 0)
-      {
-        if (!check_extra_life())
-        {
-          /* Time for the next wave! */
-          wave++;
-          reset_level();
-        }
-      }
-    }
-  }
-}
-
-
-
-void game_handle_cities(void)
-{
-  /* Update the status of the cities. These also determine the changes
-     in the penguins. */
-  int i;
-  num_cities_alive = 0;
-
-  for (i = 0; i < NUM_CITIES; i++)
-  {
-    /* Note: when status is CITY_REBUILDING, status and image
-       selection is handled by the extra_life code */
-    if (cities[i].status == CITY_REBUILDING)
-      continue;
-    if (cities[i].hits_left)
-      num_cities_alive++;
-    /* Handle counter for animated explosion: */
-    if (cities[i].status == CITY_EXPLODING)
-    {
-      cities[i].counter--;
-      if (cities[i].counter == 0) {
-        if (cities[i].hits_left)
-          cities[i].status = CITY_PRESENT;
-        else {
-          if (Opts_GetGlobalOpt(USE_IGLOOS)) {
-            cities[i].status = CITY_EVAPORATING;
-            cities[i].counter = EVAPORATING_COUNTER_START;
-            cities[i].img = IMG_IGLOO_MELTED1;
-          } else {
-            cities[i].status = CITY_GONE;
-            cities[i].img = IMG_CITY_NONE;
-          }
-        }
-      }
-    }
-    /* Choose the correct city/igloo image */
-    if (Opts_GetGlobalOpt(USE_IGLOOS)) {
-      if (cities[i].status == CITY_EVAPORATING) {
-        /* Handle the evaporation animation */
-        cities[i].layer = 0;  /* these have to be drawn below the penguin */
-        cities[i].counter--;
-        if (cities[i].counter == 0) {
-          cities[i].img--;
-          if (cities[i].img < IMG_IGLOO_MELTED3) {
-            cities[i].img = IMG_CITY_NONE;
-            cities[i].status = CITY_GONE;
-          }
-          else
-            cities[i].counter = EVAPORATING_COUNTER_START;
-        }
-      }        else {
-        if (cities[i].status != CITY_GONE) {
-          cities[i].layer = 1;  /* these have to be drawn above the penguin */
-          cities[i].img = IMG_IGLOO_MELTED1 + cities[i].hits_left;
-          /* If we're in the middle of an "explosion," don't switch to the
-             new igloo. Note the steam may have a different counter than
-             the igloo on this matter; the switch is designed to occur
-             halfway through the steam cloud. */
-          if (cities[i].status == CITY_EXPLODING)
-            cities[i].img++;
-        }
-      }
-    }
-    else {
-      /* We're using the original "city" graphics */
-      cities[i].layer = 0;   /* No layering needed */
-      if (cities[i].hits_left)
-        cities[i].img = IMG_CITY_BLUE;
-      else if (cities[i].status == CITY_EXPLODING)
-        cities[i].img = (IMG_CITY_BLUE_EXPL5 - (cities[i].counter / (CITY_EXPL_START / 5)));
-      else
-        cities[i].img = IMG_CITY_BLUE_DEAD;
-
-      /* Change image to appropriate color: */
-      cities[i].img = cities[i].img + ((wave % MAX_CITY_COLORS) *
-                   (IMG_CITY_GREEN - IMG_CITY_BLUE));
-
-    }
-  }
-}
-
-
-void game_handle_penguins(void)
-{
-  int i,direction,walk_counter;
-
-  if (!Opts_GetGlobalOpt(USE_IGLOOS))
-    return;
-  for (i = 0; i < NUM_CITIES; i++) {
-    penguins[i].layer = 0;
-    if (cities[i].status == CITY_EVAPORATING)
-      penguins[i].layer = 1;  /* will go higher in certain cases */
-    /* Handle interaction with comets & city status (ducking) */
-    if (cities[i].threatened && penguins[i].status < PENGUIN_WALKING_OFF
-        && penguins[i].status != PENGUIN_OFFSCREEN)
-      penguins[i].status = PENGUIN_DUCKING;
-    else if (!cities[i].threatened && penguins[i].status == PENGUIN_DUCKING) {
-      if (cities[i].hits_left == 2)
-        penguins[i].status = PENGUIN_HAPPY;
-      else
-        penguins[i].status = PENGUIN_GRUMPY;
-    }
-    switch (penguins[i].status) {
-    case PENGUIN_HAPPY:
-      penguins[i].img = IMG_PENGUIN_FLAPDOWN;
-      if (rand() % FLAPPING_INTERVAL == 0) {
-        penguins[i].status = PENGUIN_FLAPPING;
-        penguins[i].counter = FLAPPING_START;
-      }
-      break;
-    case PENGUIN_FLAPPING:
-      if (penguins[i].counter % 4 >= 2)
-        penguins[i].img = IMG_PENGUIN_FLAPUP;
-      else
-        penguins[i].img = IMG_PENGUIN_FLAPDOWN;
-      penguins[i].counter--;
-      if (penguins[i].counter == 0)
-        penguins[i].status = PENGUIN_HAPPY;
-      break;
-    case PENGUIN_DUCKING:
-      penguins[i].img = IMG_PENGUIN_INCOMING;
-      break;
-    case PENGUIN_GRUMPY:
-      penguins[i].img = IMG_PENGUIN_GRUMPY;
-      if (rand() % FLAPPING_INTERVAL == 0) {
-        penguins[i].status = PENGUIN_WORRIED;
-        penguins[i].counter = FLAPPING_START;
-      }
-      break;
-    case PENGUIN_WORRIED:
-      penguins[i].img = IMG_PENGUIN_WORRIED;
-      penguins[i].counter--;
-      if (penguins[i].counter == 0)
-        penguins[i].status = PENGUIN_GRUMPY;
-      break;
-    case PENGUIN_STANDING_UP:
-      penguins[i].img = IMG_PENGUIN_STANDING_UP;
-      penguins[i].counter--;
-      if (penguins[i].counter == 0)
-        penguins[i].status = PENGUIN_WALKING_OFF;
-      break;
-    case PENGUIN_SITTING_DOWN:
-      penguins[i].img = IMG_PENGUIN_SITTING_DOWN;
-      penguins[i].counter--;
-      if (penguins[i].counter == 0) {
-        penguins[i].status = PENGUIN_FLAPPING;
-        penguins[i].counter = FLAPPING_START;
-      }
-      break;
-    case PENGUIN_WALKING_ON:
-      walk_counter = (penguins[i].counter % 8)/2;
-      if (walk_counter == 3)
-        walk_counter = 1;
-      penguins[i].img = IMG_PENGUIN_WALK_ON1 + walk_counter;
-      penguins[i].counter++;
-      direction = 2*(i < NUM_CITIES/2)-1;  /* +1 for walk right, -1 for left */
-      penguins[i].x += direction*PENGUIN_WALK_SPEED;
-      if (direction*penguins[i].x >= direction*cities[i].x) {
-        penguins[i].status = PENGUIN_SITTING_DOWN;
-        penguins[i].counter = STANDING_COUNTER_START;
-        penguins[i].x = cities[i].x;
-      }
-      penguins[i].layer = 3;  /* Stand in front of steam */
-      break;
-    case PENGUIN_WALKING_OFF:
-      walk_counter = (penguins[i].counter % 8)/2;
-      if (walk_counter == 3)
-        walk_counter = 1;
-      penguins[i].img = IMG_PENGUIN_WALK_OFF1 + walk_counter;
-      penguins[i].counter++;
-      direction = 1-2*(i < NUM_CITIES/2);
-      penguins[i].x += direction*PENGUIN_WALK_SPEED;
-      if (direction < 0) {
-        if (penguins[i].x + images[IMG_PENGUIN_WALK_OFF1]->w/2 < 0)
-          penguins[i].status = PENGUIN_OFFSCREEN;
-      } else {
-        if (penguins[i].x - images[IMG_PENGUIN_WALK_OFF1]->w/2 > screen->w)
-          penguins[i].status = PENGUIN_OFFSCREEN;
-      }
-      penguins[i].layer = 3;
-      break;
-    case PENGUIN_OFFSCREEN:
-      penguins[i].img = -1;
-      break;
-    }
-  }
-}
-
-void game_handle_steam(void)
-{
-  int i;
-
-  if (!Opts_GetGlobalOpt(USE_IGLOOS))
-    return;
-  for (i = 0; i < NUM_CITIES; i++) {
-    if (steam[i].counter) {
-      steam[i].counter--;
-      if (!steam[i].counter) {
-        steam[i].status = STEAM_OFF;
-        if (cloud.status != EXTRA_LIFE_ON || cloud.city != i) {
-          /* The penguin was ducking, now we can stop */
-          if (cities[i].hits_left)
-            penguins[i].status = PENGUIN_GRUMPY;
-          else {
-            penguins[i].status = PENGUIN_STANDING_UP;
-            penguins[i].counter = STANDING_COUNTER_START;
-          }
-        }
-      }
-    }
-    if (steam[i].status == STEAM_OFF)
-      steam[i].img = -1;
-    else {
-      steam[i].img = IMG_STEAM5 - steam[i].counter/3;
-      steam[i].layer = 2;
-    }
-  }
-}
-
-int check_extra_life(void)
-{
-  /* This is called at the end of a wave. Returns 1 if we're in the
-     middle of handling an extra life, otherwise 0 */
-  int i,fewest_hits_left,fewest_index,snow_width;
-
-  if (cloud.status == EXTRA_LIFE_ON)
-    return 1;
-  DEBUGCODE(debug_game)
-    print_status();
-    
-  if (extra_life_earned) {
-    /* Check to see if any ingloo has been hit */
-    fewest_hits_left = 2;
-    fewest_index = -1;
-    for (i = 0; i < NUM_CITIES; i++) {
-      if (cities[i].hits_left < fewest_hits_left) {
-        fewest_hits_left = cities[i].hits_left;
-        fewest_index = i;
-      }
-    }
-    if (fewest_hits_left == 2)
-      return 0;   /* Don't need an extra life, there's no damage */
-    /* Begin the extra life sequence */
-    extra_life_earned = 0;
-    cloud.status = EXTRA_LIFE_ON;
-    cloud.y = screen->h/3;
-    cloud.city = fewest_index;
-    bonus_comet_counter = Opts_BonusCometInterval()+1;
-    
-    DEBUGMSG(debug_game, "Bonus comet counter restored to %d\n",bonus_comet_counter);
-
-    if (cloud.city < NUM_CITIES/2)
-      cloud.x = -images[IMG_CLOUD]->w/2;  /* come in from the left */
-    else
-      cloud.x = screen->w + images[IMG_CLOUD]->w/2; /* come from the right */
-    penguins[cloud.city].status = PENGUIN_WALKING_ON;
-    /* initialize the snowflakes */
-    snow_width = images[IMG_CLOUD]->w - images[IMG_SNOW1]->w;
-    for (i = 0; i < NUM_SNOWFLAKES; i++) {
-      cloud.snowflake_y[i] = cloud.y - i*SNOWFLAKE_SEPARATION;
-      cloud.snowflake_x[i] = - snow_width/2  + (rand() % snow_width);
-      cloud.snowflake_size[i] = rand() % 3;
-    }
-    DEBUGCODE(debug_game)
-      print_status();
-    return 1;
-  }
-  else
-    return 0;
-}
-
-
-void game_handle_extra_life(void)
-{
-  // This handles the animation sequence during the rebuilding of an igloo
-  int i, igloo_top, num_below_igloo, direction;
-
-  if (cloud.status == EXTRA_LIFE_ON) {
-
-    DEBUGCODE(debug_game)
-    {
-      if (penguins[cloud.city].status == PENGUIN_WALKING_OFF) {
-        print_status();
-        pause_game();
-      }
-    }
-
-    // Get the cloud moving in the right direction, if not yet "parked"
-    direction = 2*(cloud.city < NUM_CITIES/2) - 1;
-    if (direction*cloud.x < direction*cities[cloud.city].x) {
-      cloud.x += direction*PENGUIN_WALK_SPEED;
-    }
-    else {
-      // Cloud is "parked," handle the snowfall and igloo rebuilding
-      cities[cloud.city].status = CITY_REBUILDING;
-      igloo_top = screen->h - igloo_vertical_offset
-        - images[IMG_IGLOO_INTACT]->h;
-      for (i = 0, num_below_igloo = 0; i < NUM_SNOWFLAKES; i++) {
-        cloud.snowflake_y[i] += SNOWFLAKE_SPEED;
-        if (cloud.snowflake_y[i] > igloo_top)
-          num_below_igloo++;
-      }
-      if (cloud.snowflake_y[NUM_SNOWFLAKES-1] > igloo_top) {
-        cities[cloud.city].hits_left = 2;
-        cities[cloud.city].img = IMG_IGLOO_INTACT; // completely rebuilt
-      } else if (cities[cloud.city].hits_left == 0) {
-        // We're going to draw one of the blended igloos
-        // FIXME: It's a hack to encode a blended igloo with a negative number!
-        penguins[cloud.city].layer = 0;
-        cities[cloud.city].layer = 1;
-        if (num_below_igloo < 3)
-          num_below_igloo = 0;   // Don't show progress until a few have fallen
-        cities[cloud.city].img = -((float) (num_below_igloo)/NUM_SNOWFLAKES) * NUM_BLENDED_IGLOOS;
-      }
-      if (cloud.snowflake_y[NUM_SNOWFLAKES-1] > screen->h - igloo_vertical_offset) {
-        /* exit rebuilding when last snowflake at igloo bottom */
-        cloud.status = EXTRA_LIFE_OFF;
-        cities[cloud.city].status = CITY_PRESENT;
-      }
-    }
-  }
-}
-
-void game_draw(void)
-{
-  SDL_Rect dest;
-
-  /* Clear screen: */
-  game_draw_background();
-
-  /* Draw miscellaneous informational items */
-  game_draw_misc();
-
-  /* Draw cities/igloos and (if applicable) penguins: */
-  game_draw_cities();
-
-  /* Draw normal comets first, then bonus comets */
-  game_draw_comets();
-
-
-  /* Draw laser: */
-  if (laser.alive)
-  {
-    draw_line(laser.x1, laser.y1, laser.x2, laser.y2,
-                  255 / ((LASER_START + 1) - laser.alive),
-                  192 / ((LASER_START + 1) - laser.alive),
-                  64);
-  }
-
-  /* Draw numeric keypad: */
-  if (Opts_GetGlobalOpt(USE_KEYPAD))
-  {
-    /* pick image to draw: */
-    int keypad_image;
-    if (MC_GetOpt(ALLOW_NEGATIVES) )
-    {
-      /* draw regular keypad */
-      keypad_image = IMG_KEYPAD;
-    }
-    else
-    {
-      /* draw keypad with with grayed-out '+' and '-' */
-      keypad_image = IMG_KEYPAD_NO_NEG;
-    }
-
-    /* now draw it: */
-    dest.x = (screen->w - images[keypad_image]->w) / 2;
-    dest.y = (screen->h - images[keypad_image]->h) / 2;
-    dest.w = images[keypad_image]->w;
-    dest.h = images[keypad_image]->h;
-    SDL_BlitSurface(images[keypad_image], NULL, screen, &dest);
-  }
-
-  /* Draw console, LED numbers, & tux: */
-  draw_led_console();
-  draw_console_image(tux_img);
-
-  /* Draw any messages on the screen (used for the help mode) */
-  game_write_messages();
-
-  /* Swap buffers: */
-  SDL_Flip(screen);
-}
-
-void game_draw_background(void)
-{
-  static int old_wave = 0; //update wave immediately
-  static Uint32 bgcolor, fgcolor = 0;
-  SDL_Rect dest;
-
-  if (fgcolor == 0)
-    fgcolor = SDL_MapRGB(screen->format, 64, 96, 64);
-  if (old_wave != wave)
-  {
-    DEBUGMSG(debug_game,"Wave %d\n", wave);
-    old_wave = wave;
-    bgcolor = SDL_MapRGB(screen->format,
-                         64,
-                         64 + ((wave * 32) % 192),
-                         128 - ((wave * 16) % 128) );
-    DEBUGMSG(debug_game,"Filling screen with color %d\n", bgcolor);
-  }
-
-  if (current_bkgd() == NULL || (current_bkgd()->w != screen->w && 
-                                 current_bkgd()->h != screen->h) )
-  {
-    dest.x = 0;
-    dest.y = 0;
-    dest.w = screen->w;
-    dest.h = ((screen->h) / 4) * 3;
-
-    SDL_FillRect(screen, &dest, bgcolor);
-
-
-    dest.y = ((screen->h) / 4) * 3;
-    dest.h = (screen->h) / 4;
-
-    SDL_FillRect(screen, &dest, fgcolor);
-  }
-
-  if (current_bkgd())
-  {
-    dest.x = (screen->w - current_bkgd()->w) / 2;
-    dest.y = (screen->h - current_bkgd()->h) / 2;
-    SDL_BlitSurface(current_bkgd(), NULL, screen, &dest);
-  }
-}
-
-/* Draw comets: */
-/* NOTE bonus comets split into separate pass to make them */
-/* draw last (i.e. in front), as they can overlap          */
-void game_draw_comets(void)
-{
-
-  int i;
-  SDL_Surface* img = NULL;
-  SDL_Rect dest;
-  char* comet_str;
-
-   /* First draw regular comets: */
-  for (i = 0; i < Opts_MaxComets(); i++)
-  {
-    if (comets[i].alive && !comets[i].bonus)
-    {
-      if (comets[i].expl == -1)
-      {
-        /* Decide which image to display: */
-        img = sprites[IMG_COMET]->frame[(frame + i) % sprites[IMG_COMET]->num_frames];
-        /* Display the formula (flashing, in the bottom half
-                   of the screen) */
-        if (comets[i].y < screen->h / 2 || frame % 8 < 6)
-        {
-          comet_str = comets[i].flashcard.formula_string;
-        }
-        else
-        {
-          comet_str = NULL;
-        }
-      }
-      else
-      {
-        /* show each frame of explosion twice */
-        img = sprites[IMG_COMET_EXPL]->frame[comets[i].expl / 2];
-        comet_str = comets[i].flashcard.answer_string;
-      }
-
-      /* Draw it! */
-      dest.x = comets[i].x - (img->w / 2);
-      dest.y = comets[i].y - img->h;
-      dest.w = img->w;
-      dest.h = img->h;
-
-      SDL_BlitSurface(img, NULL, screen, &dest);
-      if (comet_str != NULL)
-      {
-        draw_nums(comet_str, comets[i].x, comets[i].y);
-      }
-    }
-  }
-
-  /* Now draw any bonus comets: */
-  for (i = 0; i < Opts_MaxComets(); i++)
-  {
-    if (comets[i].alive && comets[i].bonus)
-    {
-      if (comets[i].expl == -1)
-      {
-        /* Decide which image to display: */
-        img = sprites[IMG_BONUS_COMET]->frame[(frame + i) % sprites[IMG_BONUS_COMET]->num_frames];
-        /* Display the formula (flashing, in the bottom half
-                   of the screen) */
-        if (comets[i].y < screen->h / 2 || frame % 8 < 6)
-        {
-          comet_str = comets[i].flashcard.formula_string;
-        }
-        else
-        {
-          comet_str = NULL;
-        }
-      }
-      else
-      {
-        img = sprites[IMG_BONUS_COMET_EXPL]->frame[comets[i].expl / 2];
-        comet_str = comets[i].flashcard.answer_string;
-      }
-
-      /* Draw it! */
-      dest.x = comets[i].x - (img->w / 2);
-      dest.y = comets[i].y - img->h;
-      dest.w = img->w;
-      dest.h = img->h;
-      SDL_BlitSurface(img, NULL, screen, &dest);
-      if (comet_str != NULL)
-      {
-        draw_nums(comet_str, comets[i].x, comets[i].y);
-      }
-    }
-  }
-}
-
-
-
-void game_draw_cities(void)
-{
-  int i, j, current_layer, max_layer;
-  SDL_Rect src, dest;
-  SDL_Surface* this_image;
-
-  if (Opts_GetGlobalOpt(USE_IGLOOS)) {
-    /* We have to draw respecting layering */
-    current_layer = 0;
-    max_layer = 0;
-    do {
-      for (i = 0; i < NUM_CITIES; i++) {
-        if (cities[i].status != CITY_GONE && cities[i].layer > max_layer)
-          max_layer = cities[i].layer;
-        if (penguins[i].status != PENGUIN_OFFSCREEN && penguins[i].layer > max_layer)
-          max_layer = penguins[i].layer;
-        if (steam[i].status == STEAM_ON && steam[i].layer > max_layer)
-          max_layer = steam[i].layer;
-        if (cities[i].layer == current_layer &&
-            cities[i].img != IMG_CITY_NONE) {
-          // Handle the blended igloo images, which are encoded
-          // (FIXME) with a negative image number
-          if (cities[i].img <= 0)
-            this_image = blended_igloos[-cities[i].img];
-          else
-            this_image = images[cities[i].img];
-          //this_image = blended_igloos[frame % NUM_BLENDED_IGLOOS];
-          dest.x = cities[i].x - (this_image->w / 2);
-          dest.y = (screen->h) - (this_image->h) - igloo_vertical_offset;
-          if (cities[i].img == IMG_IGLOO_MELTED3 ||
-              cities[i].img == IMG_IGLOO_MELTED2)
-            dest.y -= (images[IMG_IGLOO_MELTED1]->h - this_image->h)/2;
-          dest.w = (this_image->w);
-          dest.h = (this_image->h);
-          SDL_BlitSurface(this_image, NULL, screen, &dest);
-        }
-        if (penguins[i].layer == current_layer &&
-            penguins[i].status != PENGUIN_OFFSCREEN) {
-          this_image = images[penguins[i].img];
-          if (penguins[i].status == PENGUIN_WALKING_OFF ||
-              penguins[i].status == PENGUIN_WALKING_ON) {
-            /* With walking penguins, we have to use flipped images
-               when it's walking left. The other issue is that the
-               images are of different widths, so aligning on the
-               center produces weird forward-backward walking. The
-               reliable way is the align them all on the tip of the
-               beak (the right border of the unflipped image) */
-            dest.x = penguins[i].x - (this_image->w / 2);
-            dest.y = (screen->h) - (this_image->h);
-            if ((i<NUM_CITIES/2 && penguins[i].status==PENGUIN_WALKING_OFF) ||
-                (i>=NUM_CITIES/2 && penguins[i].status==PENGUIN_WALKING_ON)) {
-              /* walking left */
-              this_image = flipped_images[flipped_img_lookup[penguins[i].img]];
-              dest.x = penguins[i].x - images[IMG_PENGUIN_WALK_OFF2]->w/2;
-            } else
-              dest.x = penguins[i].x - this_image->w
-                + images[IMG_PENGUIN_WALK_OFF2]->w/2;   /* walking right */
-          }
-          else {
-            dest.x = penguins[i].x - (this_image->w / 2);
-            dest.y = (screen->h) - (5*(this_image->h))/4 - igloo_vertical_offset;
-          }
-          dest.w = (this_image->w);
-          dest.h = (this_image->h);
-          SDL_BlitSurface(this_image, NULL, screen, &dest);
-        }
-        if (steam[i].layer == current_layer &&
-            steam[i].status == STEAM_ON) {
-          this_image = images[steam[i].img];
-          dest.x = cities[i].x - (this_image->w / 2);
-          dest.y = (screen->h) - this_image->h - ((4 * images[IMG_IGLOO_INTACT]->h) / 7);
-          dest.w = (this_image->w);
-          dest.h = (this_image->h);
-          SDL_BlitSurface(this_image, NULL, screen, &dest);
-        }
-      }
-      current_layer++;
-    } while (current_layer <= max_layer);
-    if (cloud.status == EXTRA_LIFE_ON) {
-      /* Render cloud & snowflakes */
-      for (i = 0; i < NUM_SNOWFLAKES; i++) {
-        if (cloud.snowflake_y[i] > cloud.y &&
-            cloud.snowflake_y[i] < screen->h - igloo_vertical_offset) {
-          this_image = images[IMG_SNOW1+cloud.snowflake_size[i]];
-          dest.x = cloud.snowflake_x[i] - this_image->w/2 + cloud.x;
-          dest.y = cloud.snowflake_y[i] - this_image->h/2;
-          dest.w = this_image->w;
-          dest.h = this_image->h;
-          SDL_BlitSurface(this_image, NULL, screen, &dest);
-        }
-      }
-      this_image = images[IMG_CLOUD];
-      dest.x = cloud.x - this_image->w/2;
-      dest.y = cloud.y - this_image->h/2;
-      dest.w = this_image->w;
-      dest.h = this_image->h;
-      SDL_BlitSurface(this_image, NULL, screen, &dest);
-    }
-  }
-  else {
-    /* We're drawing original city graphics, for which there are no
-       layering issues, but has special handling for the shields */
-    for (i = 0; i < NUM_CITIES; i++) {
-      this_image = images[cities[i].img];
-      dest.x = cities[i].x - (this_image->w / 2);
-      dest.y = (screen->h) - (this_image->h);
-      dest.w = (this_image->w);
-      dest.h = (this_image->h);
-      SDL_BlitSurface(this_image, NULL, screen, &dest);
-
-      /* Draw sheilds: */
-      if (cities[i].hits_left > 1) {
-        for (j = (frame % 3); j < images[IMG_SHIELDS]->h; j = j + 3) {
-          src.x = 0;
-          src.y = j;
-          src.w = images[IMG_SHIELDS]->w;
-          src.h = 1;
-
-          dest.x = cities[i].x - (images[IMG_SHIELDS]->w / 2);
-          dest.y = (screen->h) - (images[IMG_SHIELDS]->h) + j;
-          dest.w = src.w;
-          dest.h = src.h;
-
-          SDL_BlitSurface(images[IMG_SHIELDS], &src, screen, &dest);
-        }
-      }
-    }
-  }
-
-
-}
-void game_draw_misc(void)
-{
-  int i;
-  int offset;
-  SDL_Rect dest;
-  char str[64];
-
-  /* Draw "Demo" */
-  if (Opts_DemoMode())
-  {
-    dest.x = (screen->w - images[IMG_DEMO]->w) / 2;
-    dest.y = (screen->h - images[IMG_DEMO]->h) / 2;
-    dest.w = images[IMG_DEMO]->w;
-    dest.h = images[IMG_DEMO]->h;
-
-    SDL_BlitSurface(images[IMG_DEMO], NULL, screen, &dest);
-  }
-
-  /* If we are playing through a defined list of questions */
-  /* without "recycling", display number of remaining questions: */
-  if (MC_GetOpt(PLAY_THROUGH_LIST) )
-  {
-    draw_question_counter();
-  }
-
-  if (extra_life_earned) {
-    /* Draw extra life earned icon */
-    dest.x = 0;
-    dest.y = 0;
-    dest.w = images[IMG_EXTRA_LIFE]->w;
-    dest.h = images[IMG_EXTRA_LIFE]->h;
-    SDL_BlitSurface(images[IMG_EXTRA_LIFE], NULL, screen, &dest);
-  } else if (bonus_comet_counter) {
-    /* Draw extra life progress bar */
-    dest.x = 0;
-    dest.y = images[IMG_EXTRA_LIFE]->h/4;
-    dest.h = images[IMG_EXTRA_LIFE]->h/2;
-    dest.w = ((Opts_BonusCometInterval() + 1 - bonus_comet_counter)
-              * images[IMG_EXTRA_LIFE]->w) / Opts_BonusCometInterval();
-    SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 0, 255, 0));
-  }
-
-  /* Draw wave: */
-  if (Opts_BonusCometInterval())
-    offset = images[IMG_EXTRA_LIFE]->w + 5;
-  else
-    offset = 0;
-
-  dest.x = offset;
-  dest.y = glyph_offset;
-  dest.w = images[IMG_WAVE]->w;
-  dest.h = images[IMG_WAVE]->h;
-
-  SDL_BlitSurface(images[IMG_WAVE], NULL, screen, &dest);
-
-  sprintf(str, "%d", wave);
-  draw_numbers(str, offset+images[IMG_WAVE]->w + (images[IMG_NUMBERS]->w / 10), 0);
-
-  /* In LAN mode, we show the server-generated score: */
-  if (Opts_KeepScore() && !Opts_LanMode())
-  {
-    /* Draw "score" label: */
-    dest.x = (screen->w - ((images[IMG_NUMBERS]->w / 10) * 7) -
-                  images[IMG_SCORE]->w -
-                  images[IMG_STOP]->w - 5);
-    dest.y = glyph_offset;
-    dest.w = images[IMG_SCORE]->w;
-    dest.h = images[IMG_SCORE]->h;
-    SDL_BlitSurface(images[IMG_SCORE], NULL, screen, &dest);
-  
-    /* Draw score numbers: */
-    sprintf(str, "%.6d", score);
-    draw_numbers(str,
-                 screen->w - ((images[IMG_NUMBERS]->w / 10) * 6) - images[IMG_STOP]->w - 5,
-                 0);
-  }
-
-  /* Draw other players' scores (turn-based single machine multiplayer) */
-  if (mp_get_parameter(PLAYERS) && mp_get_parameter(MODE) == SCORE_SWEEP )
-  {
-    int i;
-    for (i = 0; i < mp_get_parameter(PLAYERS); ++i)
-    {
-      SDL_Surface* score;
-      snprintf(str, 64, "%s: %d", mp_get_player_name(i),mp_get_player_score(i));
-      score = BlackOutline(str, DEFAULT_MENU_FONT_SIZE, &white);
-      if(score)
-      {
-        SDL_Rect loc;
-        loc.w = screen->w - score->w;
-        loc.h = score->h * (i + 2);
-        loc.x = 0;
-        loc.y = 0;
-        SDL_BlitSurface(score, NULL, screen, &loc);
-      }
-    }
-  }
-
-   /* Draw other players' scores (LAN game) */
-  if (Opts_LanMode())
-  {
-    int entries = 0;
-    for (i = 0; i < MAX_CLIENTS; i++)
-    {
-      if(lan_pscores[i] >= 0)
-      {
-        SDL_Surface* score;
-        snprintf(str, 64, "%s: %d", lan_pnames[i], lan_pscores[i]);
-        score = BlackOutline(str, DEFAULT_MENU_FONT_SIZE, &white);
-        if(score)
-        {
-          SDL_Rect loc;
-          loc.w = score->w;
-          loc.h = score->h;
-          loc.x = 0;
-          loc.y = score->h * (entries + 2);
-          SDL_BlitSurface(score, NULL, screen, &loc);
-          entries++;
-        }
-      }
-    }
-  }
-  
-  /* Draw stop button: */
-  if (!help_controls.x_is_blinking || (frame % 10 < 5)) {
-    dest.x = (screen->w - images[IMG_STOP]->w);
-    dest.y = 0;
-    dest.w = images[IMG_STOP]->w;
-    dest.h = images[IMG_STOP]->h;
-
-    SDL_BlitSurface(images[IMG_STOP], NULL, screen, &dest);
-  }
-}
-
-int check_exit_conditions(void)
-{
-//  int x;
-
-  if (user_quit_received)
-  {
-    if (user_quit_received != GAME_OVER_WINDOW_CLOSE &&
-        user_quit_received != GAME_OVER_ESCAPE &&
-        user_quit_received != GAME_OVER_CHEATER)
-    {
-      fprintf(stderr, "Unexpected value %d for user_quit_received\n", user_quit_received);
-      return GAME_OVER_OTHER;
-    }
-    return user_quit_received;    
-  }
-
-  /* determine if game lost (i.e. all igloos melted): */
-  if (!num_cities_alive)
-  {
-    if (gameover_counter < 0)
-      gameover_counter = GAMEOVER_COUNTER_START;
-    gameover_counter--;
-    if (gameover_counter == 0)
-      return GAME_OVER_LOST;
-  }
-
-  /* determine if game won (i.e. all questions in mission answered correctly): */
-  if(Opts_LanMode())
-  {
-    if(game_over_won)
-       return GAME_OVER_WON;
-  }
-  else
-  {
-    if (MC_MissionAccomplished())
-    {
-      DEBUGMSG(debug_game,"Mission accomplished!\n");
-      return GAME_OVER_WON;
-    }
-  }
-
-  
-  /* Could have situation where mathcards doesn't have more questions */
-  /* even though not all questions answered correctly:                */
-  if(Opts_LanMode())
-  {
-    if(game_over_other)
-       return GAME_OVER_OTHER;
-  }
-  else
-  {
-    if(!MC_TotalQuestionsLeft())
-      return GAME_OVER_OTHER;
-  }
-
-
-  //NOTE can't use this check in LAN mode because we don't know if the server has 
-  //questions left
- 
-  /* Need to get out if no comets alive and MathCards has no questions left in list, */
-  /* even though MathCards thinks there are still questions "in play".  */
-  /* This SHOULD NOT HAPPEN and means we have a bug somewhere. */
-  if (!Opts_LanMode())
-  {
-    if (!MC_ListQuestionsLeft() && !num_comets_alive())
-    {
-      fprintf(stderr, "Error - no questions left but game not over\n");
-      DEBUGMSG(debug_game, "ListQuestionsLeft() = %d ", MC_ListQuestionsLeft());
-      DEBUGMSG(debug_game, "num_comets_alive() = %d", num_comets_alive());
-      return GAME_OVER_ERROR;
-    }
-  } 
-
-   /* If using demo mode, see if counter has run out: */
-  if (Opts_DemoMode())
-  {
-    if (demo_countdown <= 0 )
-      return GAME_OVER_OTHER;
-  }
-
-  /* if we made it to here, the game goes on! */
-  return GAME_IN_PROGRESS;
-}
-
-
-void print_exit_conditions(void)
-{
-  printf("\ngame_status:\t");
-  switch (game_status)
-  {
-    case GAME_IN_PROGRESS:
-    {
-      printf("GAME_IN_PROGRESS\n");
-      break;
-    }
-
-    case GAME_OVER_WON:
-    {
-      printf("GAME_OVER_WON\n");
-      break;
-    }
-    case GAME_OVER_LOST:
-    {
-      printf("GAME_OVER_LOST\n");
-      break;
-    }
-    case GAME_OVER_OTHER:
-    {
-      printf("GAME_OVER_OTHER\n");
-      break;
-    }
-    case GAME_OVER_ESCAPE:
-    {
-      printf("GAME_OVER_ESCAPE\n");
-      print_status();
-      break;
-    }
-    case GAME_OVER_WINDOW_CLOSE:
-    {
-      printf("GAME_OVER_WINDOW_CLOSE\n");
-      break;
-    }
-    case GAME_OVER_ERROR:
-    {
-      printf("GAME_OVER_ERROR\n");
-      break;
-    }
-    default:
-    {
-      printf("Unrecognized value\n");
-      break;
-    }
-  }
-}
-
-
-/* Reset stuff for the next level! */
-void reset_level(void)
-{
-  char fname[1024];
-  int i;
-  int next_wave_comets;
-  int use_feedback;
-  float comet_avg_height, height_differential;
-
-
-  /* Clear all comets: */
-
-  for (i = 0; i < Opts_MaxComets(); i++)
-  {
-    DEBUGCODE(debug_game)
-    {
-      if(comets[i].alive)
-        printf("Warning - resetting comets but comet[%d| still alive\n", i);
-    }
-    comets[i].alive = 0;
-  }
-
-  /* Clear LED F: */
-
-  for (i = 0; i < MC_MAX_DIGITS; ++i)
-    digits[i] = 0;
-  neg_answer_picked = 0;
-
-  /* Load random background image, but ensure it's different from this one: */
-  for (i = last_bkgd; i == last_bkgd; i = rand() % NUM_BKGDS);
-
-  last_bkgd = i;
-
-  sprintf(fname, "backgrounds/%d.jpg", i);
-
-  if (bkgd != NULL)
-  {
-    SDL_FreeSurface(bkgd);
-    bkgd = NULL;
-  }
-  if (scaled_bkgd != NULL)
-  {
-    SDL_FreeSurface(scaled_bkgd);
-    scaled_bkgd = NULL;
-  }
-
-  if (Opts_UseBkgd())
-  {
-    LoadBothBkgds(fname, &scaled_bkgd, &bkgd);
-    if (bkgd == NULL || scaled_bkgd == NULL)
-    {
-      fprintf(stderr,
-              "\nWarning: Could not load background image:\n"
-              "%s\n"
-              "The Simple DirectMedia error that ocurred was: %s\n",
-              fname, SDL_GetError());
-      Opts_SetUseBkgd(0);
-    }
-  }
-
-
-
-  /* Record score before this wave: */
-
-  pre_wave_score = score;
-
-  /* Set number of attackers for this wave: */
-
-  /* On first wave or if slowdown flagged due to wrong answer: */
-  if (wave == 1 || slowdown)
-  {
-    next_wave_comets = Opts_StartingComets();
-    speed = Opts_Speed();
-    slowdown = 0;
-  }
-
-  else /* Otherwise increase comets and speed if selected, not to */
-       /* exceed maximum:                                         */
-  {
-    next_wave_comets = prev_wave_comets;
-    if (Opts_AllowSpeedup())
-    {
-      next_wave_comets += Opts_ExtraCometsPerWave();
-      if (next_wave_comets > Opts_MaxComets())
-      {
-        next_wave_comets = Opts_MaxComets();
-      }
-
-      use_feedback = Opts_UseFeedback();
-
-      if (use_feedback)
-      {
-        #ifdef FEEDBACK_DEBUG
-        printf("Evaluating feedback...\n  old danger level = %g,",danger_level);
-        #endif
-
-        /* Update our danger level, i.e., the target height */
-        danger_level = 1 - (1-danger_level) /
-                           Opts_DangerLevelSpeedup();
-        if (danger_level > Opts_DangerLevelMax())
-          danger_level = Opts_DangerLevelMax();
-
-        #ifdef FEEDBACK_DEBUG
-        printf(" new danger level = %g.\n",danger_level);
-        #endif
-
-        /* Check to see whether we have any feedback data. If not, skip it. */
-        if (comet_feedback_number == 0)
-        {
-          use_feedback = 0;  /* No comets above living cities, skip feedback */
-
-          #ifdef FEEDBACK_DEBUG
-          printf("No feedback data available, aborting.\n\n");
-          #endif
-        }
-        else
-        {
-          /* Compute the average height of comet destruction. */
-          comet_avg_height = comet_feedback_height/comet_feedback_number;
-
-          /* Determine how this average height compares with target. */
-          height_differential = comet_avg_height - danger_level;
-
-          /* Set the speed so that we move halfway towards the target */
-          /* height. That makes the changes a bit more conservative. */
-
-          #ifdef FEEDBACK_DEBUG
-          printf("  comet average height = %g, height differential = %g.\n",
-                 comet_avg_height, height_differential);
-          printf("  old speed = %g,",speed);
-          #endif
-
-          speed *= (1 - height_differential/danger_level/2);
-
-          /* Enforce bounds on speed */
-          if (speed < MINIMUM_SPEED)
-            speed = MINIMUM_SPEED;
-          if (speed > Opts_MaxSpeed())
-            speed = Opts_MaxSpeed();
-
-          #ifdef FEEDBACK_DEBUG
-          printf(" new speed = %g.\n",speed);
-          printf("Feedback evaluation complete.\n\n");
-          #endif
-        }
-      }
-
-      if (!use_feedback)
-      {
-        /* This is not an "else" because we might skip feedback */
-        /* when comet_feedback_number == 0 */
-        speed = speed * Opts_SpeedupFactor();
-        if (speed > Opts_MaxSpeed())
-        {
-          speed = Opts_MaxSpeed();
-        }
-      }
-    }
-  }
-
-  comet_feedback_number = 0;
-  comet_feedback_height = 0;
-
-  prev_wave_comets = next_wave_comets;
-  num_attackers = prev_wave_comets;
-}
-
-
-
-/* Add a comet to the game (if there's room): */
-int add_comet(void)
-{
-  static int prev_city = -1;
-  int i;
-  float y_spacing;
-
-  int com_found = -1;
-  int q_found = -1;  
-
-  y_spacing = (images[IMG_NUMS]->h) * 1.5;
-
-  /* Return if any previous comet too high up to create another one yet: */
-  for (i = 0; i < Opts_MaxComets(); i++)
-  {
-    if (comets[i].alive)
-      if (comets[i].y < y_spacing)
-      {
-        DEBUGMSG(debug_game,
-                 "add_comet() - returning because comet[%d] not"
-                 " far enough down: %f\n", i, comets[i].y);
-        return 0;
-      }
-  }  
-    
-  /* Now look for a free comet slot: */
-  for (i = 0; i < Opts_MaxComets(); i++)
-  {
-    if (!comets[i].alive)
-    {
-      com_found = i;
-      break;
-    }
-  }
- 
-  if (-1 == com_found)
-  {
-    /* free comet slot not found - no comet added: */
-    DEBUGMSG(debug_game, "add_comet() called but no free comet slot\n");
-    DEBUGCODE(debug_game) print_current_quests();
-    return 0;
-  }
-
-
-  /* If playing in LAN mode, see if we have a question ready  in  */
-  /* our local queue:                                             */
-   
-  if(Opts_LanMode())
-  {
-    DEBUGCODE(debug_game) print_current_quests();
-    for (i = 0; i < QUEST_QUEUE_SIZE; i++)
-    {
-      if(quest_queue[i].question_id != -1)
-      {
-        DEBUGMSG(debug_game, "Found question_id %d, %s\n", 
-                  quest_queue[i].question_id,
-                  quest_queue[i].formula_string);
-        q_found = i;
-        break;
-      }
-    }
-
-    if(q_found == -1)
-    {
-      DEBUGMSG(debug_game, "add_comet() called but no question available in queue\n");
-      DEBUGCODE(debug_game) print_current_quests();
-      return 0;
-    } 
-  }
-
-  /* Now we have a vacant comet slot at com_found and (if in LAN mode) */
-  /* a question for it at q_found.  Now just copy:                     */
-
-  if(Opts_LanMode())
-  {
-    MC_CopyCard(&(quest_queue[q_found]), &(comets[com_found].flashcard));
-    MC_ResetFlashCard(&(quest_queue[q_found]));
-  }
-  else // Not LAN mode - just get question with direct call:
-  {
-    if (!MC_NextQuestion(&(comets[com_found].flashcard)))
-    {
-      /* no more questions available - cannot create comet.  */
-      return 0;
-    }
-  }
-
-  DEBUGCODE(debug_game)
-  {
-    printf("In add_comet(), card is\n");
-    print_card(comets[com_found].flashcard);
-  }
-  
-  /* Make sure question is "sane" before we add it: */
-  if( (comets[com_found].flashcard.answer > 999)
-    ||(comets[com_found].flashcard.answer < -999))
-  {
-    printf("Warning, card with invalid answer encountered: %d\n",
-           comets[com_found].flashcard.answer);
-    MC_ResetFlashCard(&(comets[com_found].flashcard));
-    return 0;
-  }
-
-  /* If we make it to here, create a new comet!*/
-  comets[com_found].answer = comets[com_found].flashcard.answer;
-  comets[com_found].alive = 1;
-//  num_comets_alive++;
-
-  /* Pick a city to attack that was not attacked last time */
-  /* (so formulas are less likely to overlap). */
-  do
-  {
-    i = rand() % NUM_CITIES;
-  }
-  while (i == prev_city);
-
-  prev_city = i;
-
-  /* Set in to attack that city: */
-  comets[com_found].city = i;
-  /* Start at the top, above the city in question: */
-  comets[com_found].x = cities[i].x;
-  comets[com_found].y = 0;
-  comets[com_found].zapped = 0;
-  /* Should it be a bonus comet? */
-  comets[com_found].bonus = 0;
-
-  DEBUGMSG(debug_game, "bonus_comet_counter is %d\n",bonus_comet_counter);
-
-  if (bonus_comet_counter == 1)
-  {
-    bonus_comet_counter = 0;
-    comets[com_found].bonus = 1;
-    playsound(SND_BONUS_COMET);
-    DEBUGMSG(debug_game, "Created bonus comet");
-  }
-
-  DEBUGMSG(debug_game, "add_comet(): formula string is: %s\n", comets[com_found].flashcard.formula_string);
-  
-  /* Record the time at which this comet was created */
-  comets[com_found].time_started = SDL_GetTicks();
-   
-  /* comet slot found and question found so return successfully: */
-  return 1;
-}
-
-
-
-/* Draw numbers/symbols over the attacker: */
-/* This draws the numbers related to the comets */
-void draw_nums(const char* str, int x, int y)
-{
-  int i, j, cur_x, c;
-  int str_length, char_width, image_length;
-
-  SDL_Rect src, dest;
-
-  /* avoid some recalculation and repeated function calls: */
-  str_length = strlen(str);
-  /* IMG_NUMS now consists of 10 digit graphics, NUM_OPERS (i.e. 4) */
-  /* operation symbols, and the '=' and '?' symbols, all side by side. */
-  /* char_width is the width of a single symbol.                     */
-  char_width = (images[IMG_NUMS]->w / (16));
-  /* Calculate image_length, taking into account that the string will */
-  /* usually have four empty spaces that are only half as wide:       */
-  image_length = str_length * char_width - (char_width * 0.5 * 4);
-  /* Center around the shape */
-  cur_x = x - (image_length) / 2;
-
-  /* the following code keeps the formula at least 8 pixels inside the window: */
-  if (cur_x < 8)
-    cur_x = 8;
-  if (cur_x + (image_length) >= (screen->w - 8))
-    cur_x = ((screen->w - 8) - (image_length));
-
-  /* Draw each character: */
-  for (i = 0; i < str_length; i++)
-  {
-    c = -1;
-
-    /* Determine which character to display: */
-
-    if (str[i] >= '0' && str[i] <= '9')
-    {
-      c = str[i] - '0';
-    }
-    else if ('=' == str[i])
-    {
-      c = 14;  /* determined by layout of nums.png image */
-    }
-    else if ('?' == str[i])
-    {
-      c = 15;  /* determined by layout of nums.png image */
-    }
-    else  /* [ THIS COULD CAUSE SLOWNESS... ] */
-    {
-      for (j = 0; j < 4; j++)
-      {
-        if (str[i] == operchars[j])
-        {
-          c = 10 + j;
-        }
-      }
-    }
-
-    /* Display this character! */
-    if (c != -1)
-    {
-      src.x = c * char_width;
-      src.y = 0;
-      src.w = char_width;
-      src.h = images[IMG_NUMS]->h;
-
-      dest.x = cur_x;
-      dest.y = y - images[IMG_NUMS]->h;
-      dest.w = src.w;
-      dest.h = src.h;
-
-      SDL_BlitSurface(images[IMG_NUMS], &src,
-                          screen, &dest);
-      /* Move the 'cursor' one character width: */
-      cur_x = cur_x + char_width;
-    }
-    /* If char is a blank, no drawing to do but still move the cursor: */
-    /* NOTE: making spaces only half as wide seems to look better.     */
-    if (' ' == str[i])
-    {
-      cur_x = cur_x + (char_width * 0.5);
-    }
-  }
-}
-
-
-/* Draw status numbers: */
-void draw_numbers(const char* str, int x, int y)
-{
-  int i, cur_x, c;
-  SDL_Rect src, dest;
-
-  cur_x = x;
-
-  /* Draw each character: */
-
-  for (i = 0; i < strlen(str); i++)
-  {
-    c = -1;
-
-    /* Determine which character to display: */
-    if (str[i] >= '0' && str[i] <= '9')
-      c = str[i] - '0';
-
-    /* Display this character! */
-    if (c != -1)
-    {
-      src.x = c * (images[IMG_NUMBERS]->w / 10);
-      src.y = 0;
-      src.w = (images[IMG_NUMBERS]->w / 10);
-      src.h = images[IMG_NUMBERS]->h;
-
-      dest.x = cur_x;
-      dest.y = y;
-      dest.w = src.w;
-      dest.h = src.h;
-
-      SDL_BlitSurface(images[IMG_NUMBERS], &src,
-                          screen, &dest);
-
-      /* Move the 'cursor' one character width: */
-      cur_x = cur_x + (images[IMG_NUMBERS]->w / 10);
-    }
-  }
-}
-
-
-/* Pause loop: */
-
-int pause_game(void)
-{
-  /* NOTE - done and quit changed to pause_done and pause_quit */
-  /* due to potentially confusing name collision */
-  int pause_done, pause_quit;
-  SDL_Event event;
-  SDL_Rect dest;
-
-  /* Only pause if pause allowed: */
-  if (!Opts_AllowPause())
-  {
-    fprintf(stderr, "Pause requested but not allowed by Opts!\n");
-    return 0;
-  }
-
-  pause_done = 0;
-  pause_quit = 0;
-
-  dest.x = (screen->w - images[IMG_PAUSED]->w) / 2;
-  dest.y = (screen->h - images[IMG_PAUSED]->h) / 2;
-  dest.w = images[IMG_PAUSED]->w;
-  dest.h = images[IMG_PAUSED]->h;
-
-  DarkenScreen(1);  // cut all channels by half
-  SDL_BlitSurface(images[IMG_PAUSED], NULL, screen, &dest);
-  SDL_UpdateRect(screen, 0, 0, 0, 0);
-
-#ifndef NOSOUND
-  if (Opts_UsingSound())
-    Mix_PauseMusic();
-#endif
-
-  do
-  {
-    while (SDL_PollEvent(&event))
-    {
-      if (event.type == SDL_KEYDOWN)
-        pause_done = 1;
-      else if (event.type == SDL_QUIT)
-      {
-        user_quit_received = GAME_OVER_WINDOW_CLOSE;
-        pause_quit = 1;
-      }
-    }
-
-    SDL_Delay(100);
-  }
-  while (!pause_done && !pause_quit);
-
-#ifndef NOSOUND
-  if (Opts_UsingSound())
-    Mix_ResumeMusic();
-#endif
-
-  return (pause_quit);
-}
-
-
-
-/* FIXME these ought to be in SDL_extras - DSB */
-
-/* Draw a line: */
-void draw_line(int x1, int y1, int x2, int y2, int red, int grn, int blu)
-{
-  int dx, dy, tmp;
-  float m, b;
-  Uint32 pixel;
-  SDL_Rect dest;
-
-  pixel = SDL_MapRGB(screen->format, red, grn, blu);
-
-  dx = x2 - x1;
-  dy = y2 - y1;
-
-  putpixel(screen, x1, y1, pixel);
-
-  if (dx != 0)
-  {
-    m = ((float) dy) / ((float) dx);
-    b = y1 - m * x1;
-
-    if (x2 > x1)
-      dx = 1;
-    else
-      dx = -1;
-
-    while (x1 != x2)
-    {
-      x1 = x1 + dx;
-      y1 = m * x1 + b;
-
-      putpixel(screen, x1, y1, pixel);
-    }
-  }
-  else
-  {
-    if (y1 > y2)
-    {
-      tmp = y1;
-      y1 = y2;
-      y2 = tmp;
-    }
-
-    dest.x = x1;
-    dest.y = y1;
-    dest.w = 3;
-    dest.h = y2 - y1;
-
-    SDL_FillRect(screen, &dest, pixel);
-  }
-}
-
-
-/* Draw a single pixel into the surface: */
-
-void putpixel(SDL_Surface* surface, int x, int y, Uint32 pixel)
-{
-#ifdef PUTPIXEL_RAW
-  int bpp;
-  Uint8* p;
-
-  /* Determine bytes-per-pixel for the surface in question: */
-
-  bpp = surface->format->BytesPerPixel;
-
-
-  /* Set a pointer to the exact location in memory of the pixel
-     in question: */
-
-  p = (Uint8 *) (surface->pixels +       /* Start at beginning of RAM */
-                 (y * surface->pitch) +  /* Go down Y lines */
-                 (x * bpp));             /* Go in X pixels */
-
-
-  /* Assuming the X/Y values are within the bounds of this surface... */
-
-  if (x >= 0 && y >= 0 && x < surface->w && y < surface->h)
-  {
-      /* Set the (correctly-sized) piece of data in the surface's RAM
-         to the pixel value sent in: */
-
-    if (bpp == 1)
-      *p = pixel;
-    else if (bpp == 2)
-      *(Uint16 *)p = pixel;
-    else if (bpp == 3)
-    {
-      if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
-      {
-        p[0] = (pixel >> 16) & 0xff;
-        p[1] = (pixel >> 8) & 0xff;
-        p[2] = pixel & 0xff;
-      }
-      else
-      {
-        p[0] = pixel & 0xff;
-        p[1] = (pixel >> 8) & 0xff;
-        p[2] = (pixel >> 16) & 0xff;
-      }
-    }
-    else if (bpp == 4)
-    {
-      *(Uint32 *)p = pixel;
-    }
-  }
-#else
-  SDL_Rect dest;
-
-  dest.x = x;
-  dest.y = y;
-  dest.w = 3;
-  dest.h = 4;
-
-  SDL_FillRect(surface, &dest, pixel);
-#endif
-}
-
-
-/* Draw image at lower center of screen: */
-void draw_console_image(int i)
-{
-  SDL_Rect dest;
-
-  dest.x = (screen->w - images[i]->w) / 2;
-  dest.y = (screen->h - images[i]->h);
-  dest.w = images[i]->w;
-  dest.h = images[i]->h;
-
-  SDL_BlitSurface(images[i], NULL, screen, &dest);
-}
-
-
-void draw_question_counter(void)
-{
-  int questions_left;
-  int comet_img;
-  int nums_width;
-  int nums_x;
-  int comet_width;
-  int comet_x;
-
-  char str[64];
-  SDL_Rect dest;
-
-  /* Calculate placement based on image widths: */
-  nums_width = (images[IMG_NUMBERS]->w / 10) * 4; /* displaying 4 digits */
-  comet_width = images[IMG_MINI_COMET1]->w;
-  comet_x = (screen->w)/2 - (comet_width + nums_width)/2;
-  nums_x = comet_x + comet_width;
-
-  /* Draw mini comet symbol:            */
-  /* Decide which image to display: */
-  comet_img = IMG_MINI_COMET1 + (frame % 3);
-  /* Draw it! */
-  dest.x = comet_x;
-  dest.y = 0;
-  dest.w = comet_width;
-  dest.h = images[comet_img]->h;
-
-  SDL_BlitSurface(images[comet_img], NULL, screen, &dest);
-
-  /* draw number of remaining questions: */
-  if(Opts_LanMode())
-    questions_left = total_questions_left;
-  else
-    questions_left = MC_TotalQuestionsLeft();
-
-  sprintf(str, "%.4d", questions_left);
-  draw_numbers(str, nums_x, 0);
-}
-
-/* FIXME very confusing having this function draw console */
-void draw_led_console(void)
-{
-  int i;
-  SDL_Rect src, dest;
-  int y;
-
-  /* draw new console image with "monitor" for LED numbers: */
-  draw_console_image(IMG_CONSOLE_LED);
-  /* set y to draw LED numbers into Tux's "monitor": */
-  y = (screen->h
-     - images[IMG_CONSOLE_LED]->h
-     + 4);  /* "monitor" has 4 pixel margin */
-
-  /* begin drawing so as to center display depending on whether minus */
-  /* sign needed (4 digit slots) or not (3 digit slots) DSB */
-  if (MC_GetOpt(ALLOW_NEGATIVES) )
-    dest.x = ((screen->w - ((images[IMG_LEDNUMS]->w) / 10) * 4) / 2);
-  else
-    dest.x = ((screen->w - ((images[IMG_LEDNUMS]->w) / 10) * 3) / 2);
-
-  for (i = -1; i < MC_MAX_DIGITS; i++) /* -1 is special case to allow minus sign */
-                              /* with minimal modification of existing code DSB */
-  {
-    if (-1 == i)
-    {
-      if (MC_GetOpt(ALLOW_NEGATIVES))
-      {
-        if (neg_answer_picked)
-          src.x =  (images[IMG_LED_NEG_SIGN]->w) / 2;
-        else
-          src.x = 0;
-
-        src.y = 0;
-        src.w = (images[IMG_LED_NEG_SIGN]->w) / 2;
-        src.h = images[IMG_LED_NEG_SIGN]->h;
-
-        dest.y = y;
-        dest.w = src.w;
-        dest.h = src.h;
-
-        SDL_BlitSurface(images[IMG_LED_NEG_SIGN], &src, screen, &dest);
-        /* move "cursor" */
-        dest.x += src.w;
-      }
-    }
-    else
-    {
-      src.x = digits[i] * ((images[IMG_LEDNUMS]->w) / 10);
-      src.y = 0;
-      src.w = (images[IMG_LEDNUMS]->w) / 10;
-      src.h = images[IMG_LEDNUMS]->h;
-
-      /* dest.x already set */
-      dest.y = y;
-      dest.w = src.w;
-      dest.h = src.h;
-
-      SDL_BlitSurface(images[IMG_LEDNUMS], &src, screen, &dest);
-      /* move "cursor" */
-      dest.x += src.w;
-    }
-  }
-}
-
-/* Translates mouse events into keyboard events when on-screen keypad used */
-/* or when exit button clicked.                                            */
-void game_mouse_event(SDL_Event event)
-{
-  int keypad_w, keypad_h, x, y, row, column;
-  SDLKey key = SDLK_UNKNOWN;
-  SDLMod mod = event.key.keysym.mod;
-  keypad_w = 0;
-  keypad_h = 0;
-
-  /* Check to see if user clicked exit button: */
-  /* The exit button is in the upper right corner of the screen: */
-  if ((event.button.x >= (screen->w - images[IMG_STOP]->w))
-    &&(event.button.y <= images[IMG_STOP]->h))
-  {
-    key = SDLK_ESCAPE;
-    game_key_event(key, mod);
-    return;
-  }
-
-  /* get out unless we really are using keypad */
-  if ( level_start_wait
-    || Opts_DemoMode()
-    || !Opts_GetGlobalOpt(USE_KEYPAD))
-  {
-    return;
-  }
-
-
-  /* make sure keypad image is valid and has non-zero dimensions: */
-  /* FIXME maybe this checking should be done once at the start */
-  /* of game() rather than with every mouse click */
-  if (MC_GetOpt(ALLOW_NEGATIVES))
-  {
-    if (!images[IMG_KEYPAD])
-      return;
-    else
-    {
-      keypad_w = images[IMG_KEYPAD]->w;
-      keypad_h = images[IMG_KEYPAD]->h;
-    }
-  }
-  else
-  {
-    if (!images[IMG_KEYPAD_NO_NEG])
-      return;
-    else
-    {
-      keypad_w = images[IMG_KEYPAD]->w;
-      keypad_h = images[IMG_KEYPAD]->h;
-    }
-  }
-
-  if (!keypad_w || !keypad_h)
-  {
-    return;
-  }
-
-
-  /* only proceed if click falls within keypad: */
-  if (!((event.button.x >=
-        (screen->w / 2) - (keypad_w / 2) &&
-        event.button.x <=
-        (screen->w / 2) + (keypad_w / 2) &&
-        event.button.y >=
-        (screen->h / 2) - (keypad_h / 2) &&
-        event.button.y <=
-        (screen->h / 2) + (keypad_h / 2))))
-  /* click outside of keypad - do nothing */
-  {
-    return;
-  }
-
-  else /* click was within keypad */
-  {
-    x = (event.button.x - ((screen->w / 2) - (keypad_w / 2)));
-    y = (event.button.y - ((screen->h / 2) - (keypad_h / 2)));
-
-  /* Now determine what onscreen key was pressed */
-  /*                                             */
-  /* The on-screen keypad has a 4 x 4 layout:    */
-  /*                                             */
-  /*    *********************************        */
-  /*    *       *       *       *       *        */
-  /*    *   7   *   8   *   9   *   -   *        */
-  /*    *       *       *       *       *        */
-  /*    *********************************        */
-  /*    *       *       *       *       *        */
-  /*    *   4   *   5   *   6   *       *        */
-  /*    *       *       *       *       *        */
-  /*    *************************   +   *        */
-  /*    *       *       *       *       *        */
-  /*    *   1   *   2   *   3   *       *        */
-  /*    *       *       *       *       *        */
-  /*    *********************************        */
-  /*    *       *                       *        */
-  /*    *   0   *         Enter         *        */
-  /*    *       *                       *        */
-  /*    *********************************        */
-  /*                                             */
-  /*  The following code simply figures out the  */
-  /*  row and column based on x and y and looks  */
-  /*  up the SDlKey accordingly.                 */
-
-    column = x/((keypad_w)/4);
-    row    = y/((keypad_h)/4);
-
-    /* make sure row and column are sane */
-    if (column < 0
-     || column > 3
-     || row    < 0
-     || row    > 3)
-    {
-      printf("\nIllegal row or column value!\n");
-      return;
-    }
-
-    /* simple but tedious - I am sure this could be done more elegantly */
-
-    if (0 == row)
-    {
-      if (0 == column)
-        key = SDLK_7;
-      if (1 == column)
-        key = SDLK_8;
-      if (2 == column)
-        key = SDLK_9;
-      if (3 == column)
-        key = SDLK_MINUS;
-    }
-    if (1 == row)
-    {
-      if (0 == column)
-        key = SDLK_4;
-      if (1 == column)
-        key = SDLK_5;
-      if (2 == column)
-        key = SDLK_6;
-      if (3 == column)
-        key = SDLK_PLUS;
-    }
-    if (2 == row)
-    {
-      if (0 == column)
-        key = SDLK_1;
-      if (1 == column)
-        key = SDLK_2;
-      if (2 == column)
-        key = SDLK_3;
-      if (3 == column)
-        key = SDLK_PLUS;
-    }
-    if (3 == row)
-    {
-      if (0 == column)
-        key = SDLK_0;
-      if (1 == column)
-        key = SDLK_RETURN;
-      if (2 == column)
-        key = SDLK_RETURN;
-      if (3 == column)
-        key = SDLK_RETURN;
-    }
-
-    if (key == SDLK_UNKNOWN)
-    {
-      return;
-    }
-
-    /* now can proceed as if keyboard was used */
-    game_key_event(key, mod);
-  }
-}
-
-/* called by either key presses or mouse clicks on */
-/* on-screen keypad */
-void game_key_event(SDLKey key, SDLMod mod)
-{
-  int i;
-  key_pressed = 1;   // Signal back in cases where waiting on any key
-
-  if (key == SDLK_ESCAPE)
-  {
-    /* Escape key - quit! */
-    user_quit_received = GAME_OVER_ESCAPE;
-  }
-  DEBUGCODE(debug_game)
-  {
-    if (key == SDLK_LEFTBRACKET) //a nice nonobvious/unused key
-    {
-      user_quit_received = GAME_OVER_CHEATER;
-    }
-  }
-  else if (key == SDLK_TAB
-        || key == SDLK_p)
-  {
-    /* [TAB] or [P]: Pause! (if settings allow) */
-    if (Opts_AllowPause())
-    {
-      paused = 1;
-    }
-  }
-
-  /* Adjust speed if settings allow: */
-  else if (key == SDLK_UP)
-  {
-    if (Opts_AllowPause())
-    {
-      speed *= 1.2;
-    }
-  }
-
-  else if (key == SDLK_DOWN)
-  {
-    if (Opts_AllowPause())
-    {
-      speed /= 1.2;
-    }
-  }
-
-
-  /* Toggle screen mode: */
-  else if (key == SDLK_F10)
-  {
-    Opts_SetGlobalOpt(FULLSCREEN, !Opts_GetGlobalOpt(FULLSCREEN) );
-    SwitchScreenMode();
-    game_recalc_positions();
-  }
-
-  /* Toggle music: */
-#ifndef NOSOUND
-  else if (key == SDLK_F11)
-  {
-    if (Opts_UsingSound())
-    {
-      if (Mix_PlayingMusic())
-      {
-        Mix_HaltMusic();
-      }
-      else
-      {
-        Mix_PlayMusic(musics[MUS_GAME + (rand() % 3)], 0);
-      }
-    }
-  }
-#endif
-
-
-  if (level_start_wait > 0 || Opts_DemoMode() || !help_controls.laser_enabled)
-  {
-    /* Eat other keys until level start wait has passed,
-    or if game is in demo mode: */
-    key = SDLK_UNKNOWN;
-  }
-
-
-  /* The rest of the keys control the numeric answer console: */
-
-  if (key >= SDLK_0 && key <= SDLK_9)
-  {
-    /* [0]-[9]: Add a new digit: */
-    for (i = 0; i < MC_MAX_DIGITS-1; ++i)
-      digits[i] = digits[i+1];
-    digits[MC_MAX_DIGITS-1] = key - SDLK_0;
-    
-//    digits[0] = digits[1];
-//    digits[1] = digits[2];
-//    digits[2] = key - SDLK_0;
-    tux_pressing = 1;
-  }
-  else if (key >= SDLK_KP0 && key <= SDLK_KP9)
-  {
-    /* Keypad [0]-[9]: Add a new digit: */
-    for (i = 0; i < MC_MAX_DIGITS-1; ++i)
-      digits[i] = digits[i+1];
-    digits[MC_MAX_DIGITS-1] = key - SDLK_KP0;
-    
-//    digits[0] = digits[1];
-//    digits[1] = digits[2];
-//    digits[2] = key - SDLK_KP0;
-    tux_pressing = 1;
-  }
-  /* support for negative answer input DSB */
-  else if ((key == SDLK_MINUS || key == SDLK_KP_MINUS)
-        && MC_GetOpt(ALLOW_NEGATIVES) )  /* do nothing unless neg answers allowed */
-  {
-    /* allow player to make answer negative: */
-    neg_answer_picked = 1;
-    tux_pressing = 1;
-  }
-  else if (     /* Effort to make logical operators clear: */
-            (
-      	      ( /* HACK this hard-codes the plus sign to the US layout: */
-	        (key == SDLK_EQUALS) && (mod & KMOD_SHIFT)
-	      ) 
-	      ||
-	      (
-	        key == SDLK_KP_PLUS
-	      )
-	    )
-            &&
-	    MC_GetOpt(ALLOW_NEGATIVES)
-          )  /* do nothing unless neg answers allowed */
-  {
-    /* allow player to make answer positive: */
-	  printf("SDKL_PLUS received\n");
-    neg_answer_picked = 0;
-    tux_pressing = 1;
-  }
-  else if (key == SDLK_BACKSPACE ||
-           key == SDLK_CLEAR ||
-           key == SDLK_DELETE)
-  {
-    /* [BKSP]: Clear digits! */
-    for (i = 0; i < MC_MAX_DIGITS; ++i)
-      digits[i] = 0;
-    tux_pressing = 1;
-  }
-  else if (key == SDLK_RETURN ||
-           key == SDLK_KP_ENTER ||
-           key == SDLK_SPACE)
-  {
-    /* [ENTER]: Accept digits! */
-    doing_answer = 1;
-  }
-}
-
-/* Increment score: */
-
-void add_score(int inc)
-{
-  score += inc;
-  DEBUGMSG(debug_game,"Score is now: %d\n", score);
-}
-
-
-
-void reset_comets(void)
-{
-  int i = 0;
-  comet_counter = 0;
-
-  for (i = 0; i < Opts_MaxComets(); i++)
-  {
-    comets[i].alive = 0;
-    comets[i].expl = -1;
-    comets[i].city = 0;
-    comets[i].x = 0;
-    comets[i].y = 0;
-    comets[i].answer = 0;
-    MC_ResetFlashCard(&(comets[i].flashcard) );
-    comets[i].bonus = 0;
-  }
-}
-
-
-void print_status(void)
-{
-  int i;
-
-  printf("\nCities:");
-  printf("\nHits left: ");
-  for (i = 0; i < NUM_CITIES; i++)
-    printf("%02d ",cities[i].hits_left);
-  printf("\nStatus:    ");
-  for (i = 0; i < NUM_CITIES; i++)
-    printf("%02d ",cities[i].status);
-
-  printf("\nPenguins:");
-  printf("\nStatus:    ");
-  for (i = 0; i < NUM_CITIES; i++)
-    printf("%02d ",penguins[i].status);
-
-  printf("\nCloud:");
-  printf("\nStatus:    %d",cloud.status);
-  printf("\nCity:      %d",cloud.city);
-  printf("\n");
-}
-
-
-void free_on_exit(void)
-{
-  int i;
-  for (i = 0; i < MAX_MAX_COMETS; ++i)
-    MC_FreeFlashcard(&(comets[i].flashcard));
-  free(comets);
-  free(cities);
-  free(penguins);
-  free(steam);
-}
-
-/* Recalculate on-screen city & comet locations when screen dimensions change */
-void game_recalc_positions(void)
-{
-  int i, img;
-  int old_city_expl_height = city_expl_height;
-
-  DEBUGMSG(debug_game,"Recalculating positions\n");
-  
-  if (Opts_GetGlobalOpt(USE_IGLOOS))
-    img = IMG_IGLOO_INTACT;
-  else
-    img = IMG_CITY_BLUE;
-
-  for (i = 0; i < NUM_CITIES; ++i)
-  {
-    /* Left vs. Right - makes room for Tux and the console */
-    if (i < NUM_CITIES / 2)
-    {
-      cities[i].x = (((screen->w / (NUM_CITIES + 1)) * i) +
-                     ((images[img] -> w) / 2));
-      DEBUGMSG(debug_game,"%d,", cities[i].x);
-    }
-    else
-    {
-      cities[i].x = screen->w -
-                   (screen->w / (NUM_CITIES + 1) *
-                   (i - NUM_CITIES / 2) +
-                    images[img]->w / 2);
-      DEBUGMSG(debug_game,"%d,", cities[i].x);
-    }
-
-    penguins[i].x = cities[i].x;
-  }
-
-  city_expl_height = screen->h - images[IMG_CITY_BLUE]->h;
-  //move comets to a location 'equivalent' to where they were
-  //i.e. with the same amount of time left before impact
-  for (i = 0; i < Opts_MaxComets(); ++i)
-  {
-    if (!comets[i].alive)
-      continue;
-
-    comets[i].x = cities[comets[i].city].x;
-    //if (Opts_GetGlobalOpt(FULLSCREEN) )
-      comets[i].y = comets[i].y * city_expl_height / old_city_expl_height;
-    //else
-    //  comets[i].y = comets[i].y * RES_Y / screen->h;
-  }
-}
-
-static int num_comets_alive()
-{
-  int i = 0;
-  int living = 0;
-  for(i = 0; i < Opts_MaxComets(); i++)
-    if(comets[i].alive)
-      living++;
-  return living;
-}
-
diff --git a/src/highscore.c b/src/highscore.c
index 94e7e27..f844544 100644
--- a/src/highscore.c
+++ b/src/highscore.c
@@ -21,7 +21,6 @@
 #include "SDL_extras.h"
 #include "convert_utf.h"
 #include "transtruct.h"
-#include "network.h"
 #include "throttle.h"
 
 
diff --git a/src/lessons.c b/src/lessons.c
deleted file mode 100644
index 12359ae..0000000
--- a/src/lessons.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
-*  C Implementation: lessons
-*
-* Description: 
-*
-*
-* Author: David Bruce <davidstuartbruce at gmail.com>, (C) 2007
-*
-* Copyright: See COPYING file that comes with this distribution
-*
-*/
-#include <stdio.h>
-//for strtok()
-#include <string.h>
-#include "lessons.h"
-//for basename(), if available
-#ifdef HAVE_LIBGEN_H
-#include <libgen.h>
-#endif
-
-// extern unsigned char **lesson_list_titles;
-// extern unsigned char **lesson_list_filenames;
-int* lesson_list_goldstars = NULL;
-// extern int num_lessons;
-
-/* local function prototypes: */
-static int filename_comp(const char* s1, const char* s2);
-
-/* Reads the file pointed to by the arg and sets */
-/* lesson_list_goldstars* accordingly:           */
-int read_goldstars_fp(FILE* fp)
-{
-  char buf[PATH_MAX];
-  char* token;
-  const char delimiters[] = "\t\n\r"; /* this will keep newline chars out of string */
-  int i;
-
-  DEBUGMSG(debug_lessons, "Entering read_goldstars_fp()\n");
-
-  /* get out if file pointer invalid: */
-  if(!fp)
-  {
-    fprintf(stderr, "In read_goldstars_fp(), file pointer invalid!\n");
-    return 0;
-  }
-
-  if (num_lessons <= 0)
-  {
-    perror("no lessons - returning");
-    num_lessons = 0;
-    return 0;
-  }
-
-
-
-  /* make sure we start at beginning: */
-  rewind(fp);
-
-  /* read in a line at a time: */
-  while (fgets (buf, PATH_MAX, fp))
-  { 
-    /* Ignore comment lines: */
-    if ((buf[0] == ';') || (buf[0] == '#'))
-    {
-      continue;
-    }
-
-    /* Split up line with strtok()to get needed values -    */ 
-    /* for now, each line just contains a lesson file name, */
-    /* but eventually there may be more fields (e.g date, % correct) */
-    token = strtok(buf, delimiters);
-    if (!token)
-      continue;
-
-    /* Now set "goldstar" to 1 if we find a matching lesson: */
-    for (i = 0; i < num_lessons; i++)
-    {
-      /* compare basenames only, not entire path (see below): */
-      if (0 == filename_comp(token, lesson_list_filenames[i]))
-      {
-        lesson_list_goldstars[i] = 1;
-        break; //should not have to worry about duplicates
-      }
-    }
-  }
-  return 1;
-}
-
-
-/* Write lessons gold star list to the provided FILE* in format  */
-/* compatible with read_goldstars_fp () above.            */
-
-void write_goldstars_fp(FILE* fp)
-{
-  int i = 0;
-
-  DEBUGMSG(debug_lessons, "Entering write_goldstars_fp()\n");
-
-  /* get out if file pointer invalid: */
-  if(!fp)
-  {
-    fprintf(stderr, "In write_goldstars_fp(), file pointer invalid!\n");
-    return;
-  }
-
-  /* make sure we start at beginning: */
-  rewind(fp);
-
-  for (i = 0; i < num_lessons; i++)
-  {
-    DEBUGMSG(debug_lessons, "i = %d\nfilename = %s\ngoldstar = %d\n",
-             i, lesson_list_filenames[i],
-             lesson_list_goldstars[i]);
-
-    if(lesson_list_goldstars[i] == 1)
-    {
-      fprintf(fp, "%s\n", lesson_list_filenames[i]);
-    }
-  }
-  return;
-}
-
-
-/* Perform a strcasecmp() on two path strings, stripping away all the */
-/* dirs in the path and just comparing the filenames themselves:      */
-/* FIXME: basename() may not be available on all platforms.           */
-/* If not available, just compare the full paths. Consider including  */
-/* our own implementation at some point. Note that the docs say       */
-/* basename() takes a const char*, but the actual header is char*,    */
-/* hence the casts to reassure the compiler.                          */
-static int filename_comp(const char* s1, const char* s2)
-{
-#ifdef HAVE_BASENAME
-  return strcasecmp(basename((char*)s1), basename((char*)s2));
-#else
-  return strcasecmp(s1, s2);
-#endif
-}
-
diff --git a/src/lessons.h b/src/lessons.h
deleted file mode 100644
index dc9473b..0000000
--- a/src/lessons.h
+++ /dev/null
@@ -1,21 +0,0 @@
-//
-// C Interface: lessons
-//
-// Description: Code for reading and parsing the lessons directory,
-//              as well as keeping track of the player's progress
-//
-//
-// Author: David Bruce <davidstuartbruce at gmail.com>, (C) 2007
-//
-// Copyright: See COPYING file that comes with this distribution
-// (Briefly, GNU GPL version 2 or greater).
-//
-#ifndef LESSONS_H
-#define LESSONS_H
-
-#include "globals.h"
-
-int read_goldstars_fp(FILE* fp);
-void write_goldstars_fp(FILE* fp);
-
-#endif
diff --git a/src/menu.c b/src/menu.c
index 5771e4b..173586f 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -18,27 +18,17 @@
 #include "SDL_extras.h"
 #include "titlescreen.h"
 #include "highscore.h"
-#include "factoroids.h"
 #include "credits.h"
-#include "multiplayer.h"
-#include "mathcards.h"
-#include "campaign.h"
 #include "game.h"
 #include "options.h"
 #include "fileops.h"
 #include "setup.h"
 
-#ifdef HAVE_LIBSDL_NET
-#include "network.h"
-#include "server.h"
-#endif
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 
-
 /* create string array of activities' names */
 #define X(name) #name
 char* activities[] = { ACTIVITIES };
@@ -215,13 +205,15 @@ MenuNode* load_menu_from_file(FILE* xml_file, MenuNode* parent)
     read_attributes(xml_file, new_node);
     if(new_node->title == NULL)
     {
-      DEBUGMSG(debug_menu_parser, "load_menu_from_file(): no title attribute, exiting\n");
+
+     DEBUGMSG(debug_menu_parser, "load_menu_from_file(): no title attribute, exiting\n");
       return NULL;
     }
   }
   else
   {
     DEBUGMSG(debug_menu_parser, "load_menu_from_file(): unknown tag: %s\n, exiting\n", buffer);
+
     return NULL;
   }
 
@@ -302,66 +294,20 @@ int handle_activity(int act, int param)
 
   switch(act)
   {
-    case RUN_CAMPAIGN:
-      start_campaign();
-      break;
-
-    case RUN_ACADEMY:
-      if(run_academy() == QUIT)
-        return QUIT;
-      break;
-
     case RUN_ARCADE:
-      run_arcade(param);
-      break;
-
-    case RUN_CUSTOM:
-      run_custom_game();
+      game();
       break;
-
     case RUN_HALL_OF_FAME:
       DisplayHighScores(CADET_HIGH_SCORE);
       break;
 
-    case RUN_SCORE_SWEEP:
-      run_multiplayer(0, param);
-      break;
-
-    case RUN_ELIMINATION:
-      run_multiplayer(1, param);
-      break;
-
     case RUN_HELP:
-      Opts_SetHelpMode(1);
-      Opts_SetDemoMode(0);
-      if (Opts_GetGlobalOpt(MENU_MUSIC))  //Turn menu music off for game
-        {audioMusicUnload();}
       game();
-      if (Opts_GetGlobalOpt(MENU_MUSIC)) //Turn menu music back on
-        audioMusicLoad( "tuxi.ogg", -1 );
-      Opts_SetHelpMode(0);
-      break;
-
-    case RUN_FACTORS:
-      run_factoroids(0);
-      break;
-
-    case RUN_FRACTIONS:
-      run_factoroids(1);
       break;
 
     case RUN_DEMO:
-      if(read_named_config_file("demo"))
-      {
-        audioMusicUnload();
-        game();
-        if (Opts_GetGlobalOpt(MENU_MUSIC))
-          audioMusicLoad( "tuxi.ogg", -1 );
-      }
-      else
-        fprintf(stderr, "\nCould not find demo config file\n");
-      break;
-
+       game();
+       
     case RUN_INFO:
       ShowMessage(DEFAULT_MENU_FONT_SIZE,
                   _("TuxMath is free and open-source!"),
@@ -383,186 +329,7 @@ int handle_activity(int act, int param)
   return 0;
 }
 
-int run_academy(void)
-{
-  int chosen_lesson = -1;
-
-  chosen_lesson = run_menu(menus[MENU_LESSONS], true);
-  while (chosen_lesson >= 0)
-  {
-    if (Opts_GetGlobalOpt(MENU_SOUND))
-      playsound(SND_POP);
-
-    /* Re-read global settings first in case any settings were */
-    /* clobbered by other lesson or arcade games this session: */
-    read_global_config_file();
-    /* Now read the selected file and play the "mission": */
-    if (read_named_config_file(lesson_list_filenames[chosen_lesson]))
-    {
-      if (Opts_GetGlobalOpt(MENU_MUSIC))  //Turn menu music off for game
-        {audioMusicUnload();}
-
-      game();
-
-      /* If successful, display Gold Star for this lesson! */
-      if (MC_MissionAccomplished())
-      {
-        lesson_list_goldstars[chosen_lesson] = 1;
-       /* and save to disk: */
-        write_goldstars();
-      }
-
-      if (Opts_GetGlobalOpt(MENU_MUSIC)) //Turn menu music back on
-        {audioMusicLoad("tuxi.ogg", -1);}
-    }
-    else  // Something went wrong - could not read lesson config file:
-    {
-      fprintf(stderr, "\nCould not find file: %s\n", lesson_list_filenames[chosen_lesson]);
-      chosen_lesson = -1;
-    }
-    // Let the user choose another lesson; start with the screen and
-    // selection that we ended with
-    chosen_lesson = run_menu(menus[MENU_LESSONS], true);
-  }
-  return chosen_lesson;
-}
-
-int run_arcade(int choice)
-{
-  const char* arcade_config_files[5] =
-    {"arcade/space_cadet",
-     "arcade/scout",
-     "arcade/ranger",
-     "arcade/ace",
-     "arcade/commando"
-    };
-
-  const int arcade_high_score_tables[5] =
-    {CADET_HIGH_SCORE,
-     SCOUT_HIGH_SCORE,
-     RANGER_HIGH_SCORE,
-     ACE_HIGH_SCORE,
-     COMMANDO_HIGH_SCORE
-    };
-
-  int hs_table;
-
-  if (choice < NUM_MATH_COMMAND_LEVELS) {
-    // Play arcade game
-    if (read_named_config_file(arcade_config_files[choice]))
-    {
-      audioMusicUnload();
-      game();
-      RenderTitleScreen();
-      if (Opts_GetGlobalOpt(MENU_MUSIC))
-        audioMusicLoad( "tuxi.ogg", -1 );
-      /* See if player made high score list!                        */
-      read_high_scores();  /* Update, in case other users have added to it */
-      hs_table = arcade_high_score_tables[choice];
-      if (check_score_place(hs_table, Opts_LastScore()) < HIGH_SCORES_SAVED)
-      {
-        char player_name[HIGH_SCORE_NAME_LENGTH * 3];
-
-        /* Get name from player: */
-        HighScoreNameEntry(&player_name[0]);
-        insert_score(player_name, hs_table, Opts_LastScore());
-        /* Show the high scores. Note the user will see his/her */
-        /* achievement even if (in the meantime) another player */
-        /* has in fact already bumped this score off the table. */
-        DisplayHighScores(hs_table);
-        /* save to disk: */
-        /* See "On File Locking" in fileops.c */
-        append_high_score(choice,Opts_LastScore(),&player_name[0]);
-
-        DEBUGCODE(debug_titlescreen)
-          print_high_scores(stderr);
-      }
-    }
-    else {
-      fprintf(stderr, "\nCould not find %s config file\n",arcade_config_files[choice]);
-    }
-  }
-  return 0;
-}
-
-int run_custom_game(void)
-{
-  const char *s1, *s2, *s3, *s4;
-  s1 = _("Edit 'options' file in your home directory");
-  s2 = _("to create customized game!");
-  s3 = _("Press a key or click your mouse to start game.");
-  s4 = _("See README.txt for more information");
-  ShowMessage(DEFAULT_MENU_FONT_SIZE, s1, s2, s3, s4);
-
-  if (read_user_config_file()) {
-    if (Opts_GetGlobalOpt(MENU_MUSIC))
-      audioMusicUnload();
-
-    game();
-    write_user_config_file();
-
-    if (Opts_GetGlobalOpt(MENU_MUSIC))
-      audioMusicLoad( "tuxi.ogg", -1 );
-  }
 
-  return 0;
-}
-
-void run_multiplayer(int mode, int difficulty)
-{
-  int nplayers = 0;
-  char npstr[HIGH_SCORE_NAME_LENGTH * 3];
-
-  while (nplayers <= 0 || nplayers > MAX_PLAYERS)
-  {
-    NameEntry(npstr, _("How many kids are playing?"),
-                     _("(Between 2 and 4 players)"));
-    nplayers = atoi(npstr);
-  }
-
-  mp_set_parameter(PLAYERS, nplayers);
-  mp_set_parameter(MODE, mode);
-  mp_set_parameter(DIFFICULTY, difficulty);
-  mp_run_multiplayer();
-}
-
-int run_factoroids(int choice)
-{
-  const int factoroids_high_score_tables[2] =
-    {FACTORS_HIGH_SCORE, FRACTIONS_HIGH_SCORE};
-  int hs_table;
-
-  audioMusicUnload();
-  if(choice == 0)
-    factors();
-  else
-    fractions();
-
-  if (Opts_GetGlobalOpt(MENU_MUSIC))
-    audioMusicLoad( "tuxi.ogg", -1 );
-
-  hs_table = factoroids_high_score_tables[choice];
-  if (check_score_place(hs_table, Opts_LastScore()) < HIGH_SCORES_SAVED){
-    char player_name[HIGH_SCORE_NAME_LENGTH * 3];
-    /* Get name from player: */
-    HighScoreNameEntry(&player_name[0]);
-    insert_score(player_name, hs_table, Opts_LastScore());
-    /* Show the high scores. Note the user will see his/her */
-    /* achievement even if (in the meantime) another player */
-    /* has in fact already bumped this score off the table. */
-    DisplayHighScores(hs_table);
-    /* save to disk: */
-    /* See "On File Locking" in fileops.c */
-    append_high_score(hs_table,Opts_LastScore(),&player_name[0]);
-    DEBUGCODE(debug_titlescreen)
-    print_high_scores(stderr);
-  }
-  else {
-    fprintf(stderr, "\nCould not find config file\n");
-  }
-
-  return 0;
-}
 
 
 /* Display the menu and run the event loop.
diff --git a/src/menu.h b/src/menu.h
index 9dd2732..52d4a54 100644
--- a/src/menu.h
+++ b/src/menu.h
@@ -32,25 +32,14 @@
 
 #define ACTIVITIES \
   X( RUN_QUIT ),\
-  X( RUN_ACADEMY ),\
-  X( RUN_CAMPAIGN ),\
   X( RUN_ARCADE ),\
-  X( RUN_CUSTOM ),\
   X( RUN_MAIN_MENU ),\
   X( RUN_SCORE_SWEEP ),\
-  X( RUN_ELIMINATION ),\
-  X( RUN_FACTORS ),\
-  X( RUN_FRACTIONS ),\
   X( RUN_HELP ),\
   X( RUN_DEMO ),\
   X( RUN_INFO ),\
   X( RUN_CREDITS ),\
   X( RUN_HALL_OF_FAME ),\
-  X( RUN_SPACE_CADET ),\
-  X( RUN_SCOUT ),\
-  X( RUN_RANGER ),\
-  X( RUN_ACE ),\
-  X( RUN_COMMANDO ),\
   X( N_OF_ACTIVITIES )  /* this one has to be the last one */
 
 /* create enum */
diff --git a/src/options.c b/src/options.c
index 880c813..56ab43c 100644
--- a/src/options.c
+++ b/src/options.c
@@ -24,8 +24,6 @@
 
 //#include "SDL.h"
 
-#include "mathcards.h"
-
 #include "options.h"
 #include "fileops.h"
 #include "setup.h"
@@ -965,22 +963,6 @@ int int_to_bool(int i)
   else
     return 0;
 }
-
-///* determine which option class a name belongs to, and set it */
-///* accordingly. Returns 1 on success, 0 on failure            */
-//static int find_and_set_option(const char* name, int val)
-//{
-//  int index = -1;
-//  
-//  if ((index = MC_MapTextToIndex(name)) != -1) //is it a math opt?
-//    MC_SetOpt(index, val);
-//  else if ((index = Opts_MapTextToIndex(name)) != -1) //is it a global opt?
-//    Opts_SetGlobalOpt(index, val);
-//  else //no? oh well.
-//    return 0;
-//    
-//  return 1;
-//}
   
 /* prints struct to stream: */
 void print_game_options(FILE* fp, int verbose)
diff --git a/src/setup.c b/src/setup.c
index 1cfea86..341f9f8 100644
--- a/src/setup.c
+++ b/src/setup.c
@@ -40,7 +40,6 @@
 
 #include "options.h"
 #include "tuxhistory.h"
-#include "mathcards.h"
 #include "setup.h"
 #include "fileops.h"
 #include "loaders.h"
@@ -141,13 +140,6 @@ void setup(int argc, char * argv[])
 /* then read in global config file                                 */
 void initialize_options(void)
 {
-  /* Initialize MathCards backend for math questions: */
-  if (!MC_Initialize())
-  {
-    printf("\nUnable to initialize MathCards\n");
-    fprintf(stderr, "\nUnable to initialize MathCards\n");
-    exit(1);
-  }
 
   /* initialize game_options struct with defaults DSB */
   if (!Opts_Initialize())
@@ -249,13 +241,6 @@ void handle_command_args(int argc, char* argv[])
         "                         current working directory, the absolute path of the\n"
         "                         filename, tuxmath's missions directory, the user's\n"
         "                         tuxmath directory, and the user's home.\n"
-        "--playthroughlist      - to ask each question only once, allowing player to\n"
-        "                         win game if all questions successfully answered\n"
-
-        "--answersfirst   - to ask questions in format: ? + num2 = num3\n"
-        "                   instead of default format: num1 + num2 = ?\n"
-        "--answersmiddle  - to ask questions in format: num1 + ? = num3\n"
-        "                   instead of default format: num1 + num2 = ?\n"
         "--nosound        - to disable sound/music\n"
         "--nobackground   - to disable background photos (for slower systems)\n"
         "--fullscreen     - to run in fullscreen, if possible (vs. windowed)\n"
@@ -352,7 +337,7 @@ void handle_command_args(int argc, char* argv[])
     else if (strcmp(argv[i], "--version") == 0 ||
              strcmp(argv[i], "-v") == 0)
     {
-      printf("Tux, of Math Command (\"tuxmath\")\n"
+      printf("Tux History (\"tuxhistory\")\n"
              "Version " VERSION "\n");
       cleanup_on_error();
       exit(0);
@@ -372,28 +357,6 @@ void handle_command_args(int argc, char* argv[])
     {
       Opts_SetGlobalOpt(USE_KEYPAD, 1);
     }
-    else if (strcmp(argv[i], "--allownegatives") == 0 ||
-             strcmp(argv[i], "-n") == 0)
-    {
-      MC_SetOpt(ALLOW_NEGATIVES, 1);
-    }
-    else if (strcmp(argv[i], "--playthroughlist") == 0 ||
-             strcmp(argv[i], "-l") == 0)
-    {
-      MC_SetOpt(PLAY_THROUGH_LIST, 1);
-    }
-    else if (strcmp(argv[i], "--answersfirst") == 0)
-    {
-      MC_SetOpt(FORMAT_ANSWER_LAST, 0);
-      MC_SetOpt(FORMAT_ANSWER_FIRST, 1);
-      MC_SetOpt(FORMAT_ANSWER_MIDDLE, 0);
-    }
-    else if (strcmp(argv[i], "--answersmiddle") == 0)
-    {
-      MC_SetOpt(FORMAT_ANSWER_LAST, 0);
-      MC_SetOpt(FORMAT_ANSWER_FIRST, 0);
-      MC_SetOpt(FORMAT_ANSWER_MIDDLE, 1);
-    }
     else if (strcmp(argv[i], "--speed") == 0 ||
              strcmp(argv[i], "-s") == 0)
     {
@@ -787,9 +750,7 @@ void cleanup_memory(void)
 
   /* frees the game_options struct: */
   Opts_Cleanup();
-  /* frees any heap used by MathCards: */
-  MC_EndGame();
-}
+  }
 
 
 
diff --git a/src/throttle.c b/src/throttle.c
new file mode 100644
index 0000000..5052fc8
--- /dev/null
+++ b/src/throttle.c
@@ -0,0 +1,45 @@
+/*
+*  C Implementation: network.c
+*
+*         Description: A simple function that uses SDL_Delay() to keep 
+*                      loops from eating all available CPU.
+
+*
+* Author: David Bruce, and the TuxMath team, (C) 2009
+* Developers list: <tuxmath-devel at lists.sourceforge.net>
+*
+* Copyright: See COPYING file that comes with this distribution.  (Briefly, GNU GPL).
+*/
+
+
+#include "SDL.h"
+
+/* NOTE now store the time elsewhere to make function thread-safe                          */
+
+void Throttle(int loop_msec, Uint32* last_t)
+{
+  Uint32 now_t, wait_t;
+
+  if(!last_t)
+    return;
+
+  //Target loop time must be between 0 and 1000 msec:
+  if(loop_msec < 0)
+    loop_msec = 0;
+  if(loop_msec > 1000)
+    loop_msec = 1000;
+
+  //See if we need to wait:
+  now_t = SDL_GetTicks();
+  if (now_t < (*last_t + loop_msec))
+  {
+    wait_t = (*last_t + loop_msec) - now_t;
+    //Avoid problem if we somehow wrap past uint32 size (at 49.7 days!)
+    if(wait_t < 0)
+      wait_t = 0;
+    if(wait_t > loop_msec)
+      wait_t = loop_msec;
+    SDL_Delay(wait_t);
+  }
+  *last_t = SDL_GetTicks();
+}
diff --git a/src/throttle.h b/src/throttle.h
new file mode 100644
index 0000000..6d55501
--- /dev/null
+++ b/src/throttle.h
@@ -0,0 +1,24 @@
+/*
+
+        throttle.h
+
+        Description: A simple function that uses SDL_Delay() to keep loops from eating all available
+                     CPU
+        Author: David Bruce and the TuxMath team, (C) 2009
+
+        Copyright: See COPYING file that comes with this distribution (briefly, GNU GPL version 2 or later)
+
+*/
+
+#ifndef THROTTLE_H
+#define THROTTLE_H
+
+#include "SDL.h"
+
+// This simple function uses SDL_Delay() to wait to return until 'loop_msec'
+// milliseconds after it returned the last time. Per SDL docs, the granularity
+// is likely no better than 10 msec
+// NOTE Uint32* last_t arg added to make function thread-safe
+void Throttle(int loop_msec, Uint32* last_t);
+
+#endif
diff --git a/src/tuxhistory.h b/src/tuxhistory.h
index e59f28b..4dfca5c 100644
--- a/src/tuxhistory.h
+++ b/src/tuxhistory.h
@@ -75,7 +75,4 @@ extern Mix_Chunk* sounds[];    /* declared in setup.c; also used in fileops.c, p
 extern Mix_Music* musics[];    /* declared in setup.c; also used in fileops.c, game.c  */
 #endif
 
-
-/* NOTE: default values for math options are now in mathcards.h */
-
 #endif

-- 
tuxhistory - Educational history game



More information about the Tux4kids-commits mailing list