[Tux4kids-commits] r55 - in tuxmath/trunk: . docs src

dbruce at alioth.debian.org dbruce at alioth.debian.org
Thu Mar 8 21:21:12 CET 2007


Author: dbruce
Date: 2006-10-30 16:44:31 +0000 (Mon, 30 Oct 2006)
New Revision: 55

Modified:
   tuxmath/trunk/Makefile.am
   tuxmath/trunk/configure.in
   tuxmath/trunk/docs/changelog
   tuxmath/trunk/src/Makefile.am
   tuxmath/trunk/src/fileops.c
   tuxmath/trunk/src/fileops.h
   tuxmath/trunk/src/game.c
   tuxmath/trunk/src/mathcards.c
   tuxmath/trunk/src/options.c
   tuxmath/trunk/src/options.h
   tuxmath/trunk/src/playsound.c
   tuxmath/trunk/src/setup.c
   tuxmath/trunk/src/setup.h
   tuxmath/trunk/src/title.c
   tuxmath/trunk/src/tuxmath.c
   tuxmath/trunk/src/tuxmath.h
Log:
game_options struct now protected with 'get/set' style accessor functions. 


Modified: tuxmath/trunk/Makefile.am
===================================================================
--- tuxmath/trunk/Makefile.am	2006-10-17 20:36:09 UTC (rev 54)
+++ tuxmath/trunk/Makefile.am	2006-10-30 16:44:31 UTC (rev 55)
@@ -4,35 +4,8 @@
 
 NSI_INSTALL_DIR=@NSI_INSTALL_DIR@
 NSI_DLL_DIR=@NSI_DLL_DIR@
+NSI_TUXMATH_CONF_DIR=@NSI_TUXMATH_CONF_DIR@
 
-MY_RECURSIVE_TARGETS = install-nsi
-
-$(MY_RECURSIVE_TARGETS):
-	@failcom='exit 1'; \
-	for f in x $$MAKEFLAGS; do \
-	  case $$f in \
-	    *=* | --[!k]*);; \
-	    *k*) failcom='fail=yes';; \
-	  esac; \
-	done; \
-	dot_seen=no; \
-	target=`echo $@ | sed s/-recursive//`; \
-	list='$(SUBDIRS)'; for subdir in $$list; do \
-	  echo "Making $$target in $$subdir"; \
-	  if test "$$subdir" = "."; then \
-	    dot_seen=yes; \
-	    local_target="$$target-am"; \
-	  else \
-	    local_target="$$target"; \
-	  fi; \
-	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
-	  || eval $$failcom; \
-	done; \
-	if test "$$dot_seen" = "no"; then \
-	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
-	fi; test -z "$$fail"
-
-
 install-data-local:
 	@$(NORMAL_INSTALL)
 	if test -d $(srcdir)/$(PACKAGE_DATA_DIR); then \
@@ -47,15 +20,23 @@
          | ( cd $(top_srcdir)/$(NSI_INSTALL_DIR)/$(PACKAGE_DATA_DIR) ; tar xf -) ; \
 	cp $(NSI_DLL_DIR)/*.dll $(top_srcdir)/$(NSI_INSTALL_DIR) ; \
         cp $(SUBDIRS)/*.exe $(top_srcdir)/$(NSI_INSTALL_DIR) ;
+if NSI_USE_TUXMATH_CONF
+	$(INSTALL) -d $(top_srcdir)/$(NSI_INSTALL_DIR)/TuxMathConfig ;
+	cp $(NSI_TUXMATH_CONF_DIR)/*.*  $(top_srcdir)/$(NSI_INSTALL_DIR)/TuxMathConfig ;
+endif 
 
 install-nsi-am: install-nsi-local
 
 nsis: install-nsi-local
+if NSI_USE_TUXMATH_CONF
+	$(MAKENSIS) -NOCD nsis/tuxmath_with_conf.nsi
+else
 	$(MAKENSIS) -NOCD nsis/tuxmath.nsi
+endif
 
 clean-local:
 	@$(NORMAL_CLEAN)
 	if test -d $(NSI_INSTALL_DIR); then \
 	  rm -fr $(NSI_INSTALL_DIR); \
 	fi
-	-rm tuxmath- at VERSION@-win32-installer.exe
+#	-rm tuxmath- at VERSION@-win32-installer.exe

Modified: tuxmath/trunk/configure.in
===================================================================
--- tuxmath/trunk/configure.in	2006-10-17 20:36:09 UTC (rev 54)
+++ tuxmath/trunk/configure.in	2006-10-30 16:44:31 UTC (rev 55)
@@ -98,21 +98,33 @@
 AC_SUBST(PACKAGE_DATA_DIR)
 
 NSI_INSTALL_DIR=mingw32
+AC_SUBST(NSI_INSTALL_DIR)
+
 NSI_DLL_DIR=~/tuxmath_dll
-
 AC_ARG_WITH(dll-directory,AC_HELP_STRING(
     [--with-dll-directory=path],
     [set the path where dll for TuxMath are [$(NSI_DLL_DIR)]]), dll_path=$withval, dll_path=no)
 
 AM_CONDITIONAL(NSI_BUILD, test "$dll_path" = no)
 
-AC_SUBST(NSI_INSTALL_DIR)
-AC_SUBST(NSI_DLL_DIR)
-
 if test $dll_path != no; then
 NSI_DLL_DIR=$dll_path
 fi
+AC_SUBST(NSI_DLL_DIR)
 
+NSI_TUXMATH_CONF_DIR=no
+AC_ARG_WITH(tuxmath_config-directory,AC_HELP_STRING(
+    [--with-tuxmath_config-directory=path],
+    [set the path where dll for TuxMath are [$(NSI_TUXMATH_CONF_DIR)]]), tuxmath_config_path=$withval, tuxmath_config_path=no)
+
+AM_CONDITIONAL(NSI_USE_TUXMATH_CONF, test "$tuxmath_config_path" != no)
+
+if test $tuxmath_config_path != no; then
+NSI_TUXMATH_CONF_DIR=$tuxmath_config_path
+fi
+
+AC_SUBST(NSI_TUXMATH_CONF_DIR)
+
 AC_PATH_PROG(NSIS, makensis, no, [$PATH])
 
 #AC_CONFIG_FILES([Makefile])
@@ -121,4 +133,5 @@
 Makefile
 src/Makefile
 nsis/tuxmath.nsi
-])
\ No newline at end of file
+nsis/tuxmath_with_conf.nsi
+])

Modified: tuxmath/trunk/docs/changelog
===================================================================
--- tuxmath/trunk/docs/changelog	2006-10-17 20:36:09 UTC (rev 54)
+++ tuxmath/trunk/docs/changelog	2006-10-30 16:44:31 UTC (rev 55)
@@ -1,5 +1,29 @@
 changelog for "tuxmath"
 
+2006.Oct.30 (https://svn.tux4kids.net/tuxmath/ - revision 53)
+  Version 0.98
+
+  Code:
+    * Minor bug fix to prevent the game from asking questions
+      with an indeterminate answer (i.e. 0 / ? = 0).
+      David Bruce <dbruce at tampabay.rr.com>
+
+2006.Oct.20
+
+  Build:
+    * More support for Windows crossbuild under linux added
+      to svn, including cross-configure.sh and cross-make.sh 
+      scripts and minor changes to configure.in and Makefile.am
+      when building for Windows.
+  Code:
+    * game_options struct now has complete set of accessor
+      functions with sanity checks to keep impossible values
+      from getting read in from config files.  This is in
+      options.c. This fixes several ways in which the program
+      could previously be crashed, and also cleans up 
+      read_config_file() as it no longer needs to do any
+      sanity testing.
+
 2006.Oct.07 (https://svn.tux4kids.net/tuxmath/ - revision 48)
   Version 0.97 final
 

Modified: tuxmath/trunk/src/Makefile.am
===================================================================
--- tuxmath/trunk/src/Makefile.am	2006-10-17 20:36:09 UTC (rev 54)
+++ tuxmath/trunk/src/Makefile.am	2006-10-30 16:44:31 UTC (rev 55)
@@ -1,7 +1,21 @@
+if BUILD_MINGW32
+bin_PROGRAMS = TuxMath
+else
+TUXMATHRC =
 bin_PROGRAMS = tuxmath
+endif
+
+TuxMath_SOURCES = tuxmath.c setup.c title.c game.c \
+		options.c credits.c playsound.c \
+                mathcards.c fileops.c tuxmathrc.c
+
 tuxmath_SOURCES = tuxmath.c setup.c title.c game.c \
 		options.c credits.c playsound.c \
                 mathcards.c fileops.c
+
+
+WINDRES=@WINDRES@
+
 if BUILD_MINGW32
   DATA_PREFIX=@PACKAGE_DATA_DIR@
 else
@@ -11,3 +25,7 @@
 AM_CFLAGS=-Wall -g -DDATA_PREFIX=\"${DATA_PREFIX}\" -DDEBUG \
 	-DVERSION=\"@NAME_VERSION@\" -D$(SOUND)SOUND
 
+# How to make an RC file
+tuxmathrc.o: tuxmathrc.rc
+	$(WINDRES) -i $< -o $@
+

Modified: tuxmath/trunk/src/fileops.c
===================================================================
--- tuxmath/trunk/src/fileops.c	2006-10-17 20:36:09 UTC (rev 54)
+++ tuxmath/trunk/src/fileops.c	2006-10-30 16:44:31 UTC (rev 55)
@@ -54,6 +54,7 @@
 #include "fileops.h"
 #include "setup.h"
 #include "mathcards.h"
+#include "options.h"
 
 /* Used by both write_pregame_summary() and */
 /* write_postgame_summary() so defined with */
@@ -541,157 +542,127 @@
     {
       int v = str_to_bool(value);
       if (v != -1)
-        game_options->per_user_config = v;
+        Opts_SetPerUserConfig(v);
     }
 
     if(0 == strcasecmp(parameter, "use_sound"))
     {
       int v = str_to_bool(value);
       if (v != -1)
-        game_options->use_sound = v;
+        Opts_SetUseSound(v);
     }
 
     else if(0 == strcasecmp(parameter, "fullscreen"))
     {
       int v = str_to_bool(value);
       if (v != -1)
-        game_options->fullscreen = v;
+        Opts_SetFullscreen(v);
     }
 
     else if(0 == strcasecmp(parameter, "use_bkgd"))
     {
       int v = str_to_bool(value);
       if (v != -1)
-        game_options->use_bkgd = v;
+        Opts_SetUseBkgd(v);
     }
 
     else if(0 == strcasecmp(parameter, "demo_mode"))
     {
       int v = str_to_bool(value);
       if (v != -1)
-        game_options->demo_mode = v;
+        Opts_SetDemoMode(v);
     }
 
     else if(0 == strcasecmp(parameter, "oper_override"))
     {
       int v = str_to_bool(value);
       if (v != -1)
-        game_options->oper_override = v;
+        Opts_SetOperOverride(v);
     }
 
     else if(0 == strcasecmp(parameter, "use_keypad"))
     {
       int v = str_to_bool(value);
       if (v != -1)
-        game_options->use_keypad = v;
+        Opts_SetUseKeypad(v);
     }
 
     else if(0 == strcasecmp(parameter, "save_summary"))
     {
       int v = str_to_bool(value);
       if (v != -1)
-        game_options->save_summary = v;
+        Opts_SetSaveSummary(v);
     }
 
     else if(0 == strcasecmp(parameter, "speed"))
     {
-      game_options->speed = atof(value);
-      if (game_options->speed < MINIMUM_SPEED)
-      {
-        game_options->speed = MINIMUM_SPEED;
-        fprintf(stderr,"Warning: speed set below minimum, setting to %g.\n",MINIMUM_SPEED);
-      }
+      Opts_SetSpeed(atof(value));
     }
 
     else if(0 == strcasecmp(parameter, "use_feedback"))
     {
       int v = str_to_bool(value);
       if (v != -1)
-        game_options->use_feedback = v;
+        Opts_SetUseFeedback(v);
     }
 
     else if(0 == strcasecmp(parameter, "danger_level"))
     {
-      game_options->danger_level = atof(value);
-      if (game_options->danger_level < 0)
-      {
-        game_options->danger_level = 0;
-	fprintf(stderr,"Warning: danger level set below minimum, setting to 0.\n");
-      }
-      if (game_options->danger_level > 1)
-      {
-        game_options->danger_level = 1;
-        fprintf(stderr,"Warning: danger level set above maximum, setting to 1.\n");
-      }
+      Opts_SetDangerLevel(atof(value));
     }
- 
+
     else if(0 == strcasecmp(parameter, "danger_level_speedup"))
     {
-      game_options->danger_level_speedup = atof(value);
-      if (game_options->danger_level_speedup < 1)
-      {
-        game_options->danger_level_speedup = 1;
-        fprintf(stderr,"Warning: danger_level_speedup set below minimum, setting to 1.\n");
-      }
+      Opts_SetDangerLevelSpeedup(atof(value));
     }
 
     else if(0 == strcasecmp(parameter, "danger_level_max"))
     {
-      game_options->danger_level_max = atof(value);
-      if (game_options->danger_level_max > 1)
-      {
-        game_options->danger_level_max = 1;
-        fprintf(stderr,"Warning: danger_level_max set above maximum, setting to 1.\n");
-      }
+      Opts_SetDangerLevelMax(atof(value));
     }
 
     else if(0 == strcasecmp(parameter, "city_explode_handicap"))
     {
-      game_options->city_expl_handicap = atof(value);
-      if (game_options->city_expl_handicap < 0)
-      {
-        game_options->city_expl_handicap = 0;
-        fprintf(stderr,"Warning: city_explode_handicap leve set below minimum, setting to 0.\n");
-      }
+      Opts_SetCityExplHandicap(atof(value));
     }
 
     else if(0 == strcasecmp(parameter, "allow_speedup"))
     {
       int v = str_to_bool(value);
       if (v != -1)
-        game_options->allow_speedup = v;
+        Opts_SetAllowSpeedup(v);
     }
 
     else if(0 == strcasecmp(parameter, "speedup_factor"))
     {
-      game_options->speedup_factor = atof(value);
+      Opts_SetSpeedupFactor(atof(value));
     }
 
     else if(0 == strcasecmp(parameter, "max_speed"))
     {
-      game_options->max_speed = atof(value);
+      Opts_SetMaxSpeed(atof(value));
     }
 
     else if(0 == strcasecmp(parameter, "slow_after_wrong"))
     {
       int v = str_to_bool(value);
       if (v != -1)
-        game_options->slow_after_wrong = v;
+        Opts_SetSlowAfterWrong(v);
     }
 
     else if(0 == strcasecmp(parameter, "starting_comets"))
     {
-      game_options->starting_comets = atoi(value);
+      Opts_SetStartingComets(atoi(value));
     }
 
     else if(0 == strcasecmp(parameter, "extra_comets_per_wave"))
     {
-      game_options->extra_comets_per_wave = atoi(value);
+      Opts_SetExtraCometsPerWave(atoi(value));
     }
 
     else if(0 == strcasecmp(parameter, "max_comets"))
     {
-      game_options->max_comets = atoi(value);
+      Opts_SetMaxComets(atoi(value));
     }
 
 
@@ -1146,8 +1117,8 @@
                  "############################################################\n\n");
   }
 
-  fprintf(fp, "allow_speedup = %d\n", game_options->allow_speedup);
-  fprintf(fp, "use_feedback = %d\n", game_options->use_feedback);
+  fprintf(fp, "allow_speedup = %d\n", Opts_AllowSpeedup());
+  fprintf(fp, "use_feedback = %d\n", Opts_UseFeedback());
 
 
   if (verbose)
@@ -1284,7 +1255,7 @@
   {
     fprintf (fp, "\n# Use game sounds and background music if possible:\n");
   }
-  fprintf(fp, "use_sound = %d\n", game_options->use_sound);
+  fprintf(fp, "use_sound = %d\n", Opts_UseSound());
 
   if (verbose)
   {
@@ -1292,26 +1263,26 @@
                  "# 640x480 window. Change to 0 if SDL has trouble with\n"
                  "# fullscreen on your system:\n");
   }
-  fprintf(fp, "fullscreen = %d\n", game_options->fullscreen);
+  fprintf(fp, "fullscreen = %d\n", Opts_Fullscreen());
 
   if (verbose)
   {
     fprintf (fp, "\n# Display jpg images for background:\n");
   }
-  fprintf(fp, "use_bkgd = %d\n", game_options->use_bkgd);
+  fprintf(fp, "use_bkgd = %d\n", Opts_UseBkgd());
 
   if (verbose)
   {
     fprintf (fp, "\n# Run Tuxmath as demo (i.e. without user input):\n");
   }
-  fprintf(fp, "demo_mode = %d\n", game_options->demo_mode);
+  fprintf(fp, "demo_mode = %d\n", Opts_DemoMode());
 
   if (verbose)
   {
     fprintf (fp, "\n# Display onscreen numeric keypad - allows mouse-only\n"
                "# gameplay or use with touchscreens:\n");
   }
-  fprintf(fp, "use_keypad = %d\n", game_options->use_keypad);
+  fprintf(fp, "use_keypad = %d\n", Opts_UseKeypad());
 
   if (verbose)
   {
@@ -1319,7 +1290,7 @@
                "# ten games in the user's .tuxmath directory. Set\n"
                "# this parameter to '0' to turn off.\n");
   }
-  fprintf(fp, "save_summary = %d\n", game_options->save_summary);
+  fprintf(fp, "save_summary = %d\n", Opts_SaveSummary());
 
   if (verbose)
   {
@@ -1499,40 +1470,43 @@
   {
     fprintf (fp, "\n# Number of comets for first wave. Default is 2.\n");
   }
-  fprintf(fp, "starting_comets = %d\n", game_options->starting_comets);
+  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", game_options->extra_comets_per_wave);
+  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", game_options->max_comets);
+  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", game_options->speed);
+  fprintf(fp, "speed = %.2f\n", Opts_Speed());
 
   if(verbose)
   {
     fprintf (fp, "\n# Maximum speed. Default is 10.\n");
   }
-  fprintf(fp, "max_speed = %.2f\n", game_options->max_speed);
+  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", game_options->speedup_factor);
+  fprintf(fp, "speedup_factor = %.2f\n", Opts_SpeedupFactor());
 
   if(verbose)
   {
@@ -1541,7 +1515,7 @@
                  "# a question. Useful for smaller kids. Default is 0.\n\n");
   }
 
-  fprintf(fp, "slow_after_wrong = %d\n", game_options->slow_after_wrong);
+  fprintf(fp, "slow_after_wrong = %d\n", Opts_SlowAfterWrong());
 
 
   if(verbose)
@@ -1553,7 +1527,7 @@
              "# 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", game_options->danger_level);
+  fprintf(fp, "danger_level = %.2f\n", Opts_DangerLevel());
 
   if(verbose)
   {
@@ -1561,14 +1535,14 @@
                   "# 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", game_options->danger_level_speedup);
+  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", game_options->danger_level_max);
+  fprintf(fp, "danger_level_max = %.2f\n", Opts_DangerLevelMax());
 
   if (verbose)
   { 
@@ -1579,7 +1553,7 @@
                   "# 'slow_after_wrong', but allows for more gradual\n"
                   "# changes. Default 0 (no extra handicap).\n\n");
   }
-  fprintf(fp, "city_explode_handicap = %.2f\n", game_options->city_expl_handicap);
+  fprintf(fp, "city_explode_handicap = %.2f\n", Opts_CityExplHandicap());
 
   if(verbose)
   {
@@ -1602,7 +1576,7 @@
                  "# by accidentally setting this to 0.                       #\n"
                  "############################################################\n\n");
   }
-  fprintf(fp, "per_user_config = %d\n", game_options->per_user_config);
+  fprintf(fp, "per_user_config = %d\n", Opts_PerUserConfig());
 
 
   /* print general game options (passing '1' as second arg causes */
@@ -1761,213 +1735,8 @@
   }
 }
 
-/* prints struct to stream: */
-void print_game_options(FILE* fp, int verbose)
-{
- /* bail out if no struct */
-  if (!game_options)
-  {
-    fprintf(stderr, "print_game_options(): invalid game_option_type struct");
-    return;
-  }
 
-  if(verbose)
-  {
-    fprintf (fp, "\n############################################################\n" 
-                 "#                                                          #\n"
-                 "#                 General Game Options                     #\n"
-                 "#                                                          #\n"
-                 "# The following options are boolean (true/false) variables #\n"
-                 "# that control various aspects of Tuxmath's behavior.      #\n"
-                 "# The program writes the values to the file as either '0'  #\n"
-                 "# or '1'. However, the program accepts 'n', 'no', 'f', and #\n"
-                 "# 'false' as synonyms for '0', and similarly accepts 'y',  #\n"
-                 "# 'yes', 't', and 'true' as synonyms for '1' (all case-    #\n"
-                 "# insensitive).                                            #\n"
-                 "############################################################\n\n");
-  }
 
-  if(verbose)
-  {
-    fprintf (fp, "############################################################\n" 
-                 "# 'per_user_config' determines whether Tuxmath will look   #\n"
-                 "# in the user's home directory for settings. Default is 1  #\n"
-                 "# (yes). If deselected, the program will ignore the user's #\n"
-                 "# .tuxmath file and use the the global settings in the     #\n"
-                 "# installation-wide config file.                           #\n"
-                 "# This setting cannot be changed by an ordinary user.      #\n"
-                 "############################################################\n");
-  }
-  fprintf(fp, "per_user_config = %d\n", game_options->per_user_config);
-
-  if(verbose)
-  {
-    fprintf (fp, "\n# Self-explanatory, default is 1:\n");
-  }
-  fprintf(fp, "use_sound = %d\n", game_options->use_sound);
-
-  if(verbose)
-  {
-    fprintf (fp, "\n# Use fullscreen at 640x480 resolution instead of\n"
-                 "640x480 window. Default is 1 (fullscreen). Change to 0\n"
-                 "if SDL has trouble with fullscreen on your system.\n");
-  } 
-  fprintf(fp, "fullscreen = %d\n", game_options->fullscreen);
-
-  if(verbose)
-  {
-    fprintf (fp, "\n# Use 640x480 jpg image for background; default is 1.\n");
-  }
-  fprintf(fp, "use_bkgd = %d\n", game_options->use_bkgd);
-
-  if(verbose)
-  {
-    fprintf (fp, "\n# Program runs as demo; default is 0.\n");
-  }
-  fprintf(fp, "demo_mode = %d\n", game_options->demo_mode);
-
-  if(verbose)
-  {
-    fprintf (fp, "\n# Use operator selection from command line; default is 0.\n");
-  }
-  fprintf(fp, "oper_override = %d\n", game_options->oper_override);
-
-  if(verbose)
-  {
-    fprintf (fp, "\n# Display onscreen numeric keypad; default is 0.\n");
-  }
-  fprintf(fp, "use_keypad = %d\n", game_options->use_keypad);
-
-  if(verbose)
-  {
-    fprintf (fp, "\n############################################################\n" 
-                 "# The next settings determine the speed and number         #\n"
-                 "# of comets.  The speed settings are float numbers (mean-  #\n"
-                 "# ing decimals allowed). The comet settings are integers.  #\n"
-                 "#                                                          #\n"
-                 "# Starting comet speed and max comet speed are generally   #\n"
-                 "# applicable. The main choice is whether you want to use   #\n"
-                 "# feedback, i.e., to adjust the speed automatically based  #\n"
-                 "# on the player's performance.                             #\n"
-                 "#                                                          #\n"
-                 "# Without feedback, the speed increases by a user-         #\n"
-                 "# settable factor ('speedup_factor'), with an option       #\n"
-                 "# ('slow_after_wrong') to go back to the starting speed    #\n"
-                 "# when a city gets hit.                                    #\n"
-                 "#                                                          #\n"
-                 "# With feedback, you set a desired 'danger level,' which   #\n"
-                 "# determines how close the comets should typically         #\n"
-                 "# approach the cities before the player succeeds in        #\n"
-                 "# destroying them.  The game will adjust its speed         #\n"
-                 "# accordingly, getting faster when the player is easily    #\n"
-                 "# stopping the comets, and slowing down when there are     #\n"
-                 "# too many close calls or hits. You can also have the      #\n"
-                 "# danger level increase with each wave.                    #\n"
-                 "############################################################\n");
-  }
-
-  if(verbose)
-  {
-    fprintf (fp, "\n# Whether to increase speed and number of comets with \n"
-                 "# each wave.  May want to turn this off for smaller kids.\n"
-                 "# Default is 1 (allow game to speed up)\n");
-  }
-  fprintf(fp, "allow_speedup = %d\n", game_options->allow_speedup);
-
-
-  fprintf(fp, "slow_after_wrong = %d\n", game_options->slow_after_wrong);
-
-  if(verbose)
-  {
-    fprintf (fp, "\n# Starting comet speed. Default is 1.\n");
-  }
-  fprintf(fp, "speed = %f\n", game_options->speed);
-
-  if(verbose)
-  {
-    fprintf (fp, "\n# If feedback is not used but 'allow_speedup' is\n"
-                 "# enabled, the comet speed will be\n"
-                 "# multiplied by this factor with each new wave.\n"
-                 "# Default is 1.2 (i.e. 20 percent increase per wave)\n");
-  }
-  fprintf(fp, "speedup_factor = %f\n", game_options->speedup_factor);
-
-  if(verbose)
-  {
-    fprintf (fp, "\n# Maximum speed. Default is 10.\n");
-  }
-  fprintf(fp, "max_speed = %f\n", game_options->max_speed);
-
-  if(verbose)
-  {
-    fprintf (fp, "\n# Number of comets for first wave. Default is 2.\n");
-  }
-  fprintf(fp, "starting_comets = %d\n", game_options->starting_comets);
-
-  if(verbose)
-  {
-    fprintf (fp, "\n# Comets to add for each successive wave. Default is 2.\n");
-  }
-  fprintf(fp, "extra_comets_per_wave = %d\n", game_options->extra_comets_per_wave);
-
-  if(verbose)
-  {
-    fprintf (fp, "\n# Maximum number of comets. Default is 10.\n");
-  }
-  fprintf(fp, "max_comets = %d\n", game_options->max_comets);
-
-  if(verbose)
-  {
-     fprintf (fp, "\n# Use feedback? Default (for now) is false, 0.\n");
-  }
-  fprintf(fp, "use_feedback = %d\n", game_options->use_feedback);
-
-
-   if(verbose)
-   {
-     fprintf (fp, "\n# (Feedback) Set the desired danger level.\n"
-             "# 0 = too safe, comets typically exploded right at the very top\n"
-             "# 1 = too dangerous, comets typically exploded at the moment they hit cities\n"
-             "# Set it somewhere between these extremes. As a guideline, early\n"
-             "# elementary kids might feel comfortable around 0.2-0.3, older kids\n"
-             "# at around 0.4-0.6. Default 0.35.\n");
-   }
-   fprintf(fp, "danger_level = %f\n", game_options->danger_level);
-
-   if(verbose)
-   {
-     fprintf (fp, "\n# (Feedback) Set danger level speedup.\n"
-                  "# The margin of safety will decrease by this factor each wave.\n"
-                  "# Default 1.1. Note 1 = no increase in danger level.\n");
-   }
-   fprintf(fp, "danger_level_speedup = %f\n", game_options->danger_level_speedup);
-
-   if(verbose)
-   {
-     fprintf (fp, "\n# (Feedback) Set the maximum danger level.\n"
-                  "# Default 0.9.\n");
-   }
-   fprintf(fp, "danger_level_max = %f\n", game_options->danger_level_max);
-
-   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 slow_after_wrong,\n"
-                  "# but allows for more gradual changes.\n"
-                  "# Default 0 (no extra handicap).\n");
-   }
-   fprintf(fp, "city_explode_handicap = %f\n", game_options->city_expl_handicap);
-
-/*
-  fprintf(fp, "num_cities = %d\n", game_options->num_cities);
-  fprintf(fp, "num_bkgds = %d\n", game_options->num_bkgds);
-  fprintf(fp, "max_city_colors = %d\n", game_options->max_city_colors);
-*/
-}
-
-
 /* 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)
@@ -2216,7 +1985,7 @@
   DATA_PREFIX "/images/status/gameover_won.png"
   };
 
-  if (opts_using_sound())
+  if (Opts_UsingSound())
     total_files = NUM_IMAGES + NUM_SOUNDS + NUM_MUSICS;
   else
     total_files = NUM_IMAGES;
@@ -2305,7 +2074,7 @@
   };
 
   /* skip loading sound files if sound system not available: */
-  if (opts_using_sound())
+  if (Opts_UsingSound())
   {
     total_files = NUM_IMAGES + NUM_SOUNDS + NUM_MUSICS;
 

Modified: tuxmath/trunk/src/fileops.h
===================================================================
--- tuxmath/trunk/src/fileops.h	2006-10-17 20:36:09 UTC (rev 54)
+++ tuxmath/trunk/src/fileops.h	2006-10-30 16:44:31 UTC (rev 55)
@@ -187,8 +187,8 @@
 /* FIXME these will probably become "local" functions: */
 int read_config_file(FILE* fp, int file_type);
 int write_config_file(FILE* fp, int verbose);
-void print_game_options(FILE* fp, int verbose);
 
+
 int load_image_data();
 #ifndef NOSOUND
 int load_sound_data();

Modified: tuxmath/trunk/src/game.c
===================================================================
--- tuxmath/trunk/src/game.c	2006-10-17 20:36:09 UTC (rev 54)
+++ tuxmath/trunk/src/game.c	2006-10-30 16:44:31 UTC (rev 55)
@@ -29,7 +29,8 @@
 #include "setup.h"
 #include "playsound.h"
 #include "tuxmath.h"
-#include "mathcards.h"  
+#include "mathcards.h"
+#include "options.h"  
 
 #define FPS (1000 / 15)   /* 15 fps max */
 
@@ -108,7 +109,7 @@
 
 
 static int digits[3];
-static comet_type comets[MAX_COMETS];
+static comet_type comets[MAX_MAX_COMETS];
 static city_type cities[NUM_CITIES];
 static laser_type laser;
 static SDL_Surface* bkgd;
@@ -198,7 +199,7 @@
       /* Keep playing music: */
       
     #ifndef NOSOUND
-    if (opts_using_sound())
+    if (Opts_UsingSound())
     {
       if (!Mix_PlayingMusic())
       {
@@ -371,7 +372,7 @@
 
   /* Stop music: */
 #ifndef NOSOUND
-  if (opts_using_sound())
+  if (Opts_UsingSound())
   {
     if (Mix_PlayingMusic())
     {
@@ -382,7 +383,7 @@
 
 
   /* Write post-game info to game summary file: */
-  if (game_options->save_summary)
+  if (Opts_SaveSummary())
   {
     write_postgame_summary();
   }  
@@ -430,7 +431,7 @@
   }  
   
   /* Write pre-game info to game summary file: */
-  if (game_options->save_summary)
+  if (Opts_SaveSummary())
   {
     write_pregame_summary();
   }
@@ -441,12 +442,12 @@
   /* Initialize feedback parameters */
   comet_feedback_number = 0;
   comet_feedback_height = 0;
-  danger_level = game_options->danger_level;
+  danger_level = Opts_DangerLevel();
   
   wave = 1;
   num_attackers = 2;
-  prev_wave_comets = game_options->starting_comets;
-  speed = game_options->speed;
+  prev_wave_comets = Opts_StartingComets();
+  speed = Opts_Speed();
   slowdown = 0;
   score = 0;
   demo_countdown = 1000;
@@ -526,7 +527,7 @@
 void game_handle_demo(void)
 {
   /* If not in demo mode get out: */
-  if (!game_options->demo_mode)
+  if (!Opts_DemoMode())
   {
     return;
   }
@@ -655,7 +656,7 @@
     playsound(SND_SIZZLE);
 
     /* Record data for feedback */
-    if (game_options->use_feedback)
+    if (Opts_UseFeedback())
     {
       comet_feedback_number++;
       comet_feedback_height += comets[lowest].y/city_expl_height;
@@ -805,20 +806,21 @@
         /* Record data for feedback */
 	/* Do this only for cities that are threatened; dead cities */
         /* might not get much protection from the player */
-	if (game_options->use_feedback && cities[comets[i].city].alive) {
+	if (Opts_UseFeedback() && cities[comets[i].city].alive) {
 	  comet_feedback_number++;
-          comet_feedback_height += 1.0 + game_options->city_expl_handicap;
+          comet_feedback_height += 1.0 + Opts_CityExplHandicap();
 
           #ifdef FEEDBACK_DEBUG
- 	  printf("Added comet feedback with height %g\n",1.0 + game_options->city_expl_handicap);
+ 	  printf("Added comet feedback with height %g\n",
+                  1.0 + Opts_CityExplHandicap());
  	  #endif
  	}
  
        /* If slow_after_wrong selected, set flag to go back to starting speed and */
         /* number of attacking comets: */
-        if (game_options->slow_after_wrong)
+        if (Opts_SlowAfterWrong())
         {
-          speed = game_options->speed;
+          speed = Opts_Speed();
           slowdown = 1;
         }
 
@@ -925,7 +927,7 @@
   }
 
   /* Draw "Demo" */
-  if (game_options->demo_mode)
+  if (Opts_DemoMode())
   {
     dest.x = (screen->w - images[IMG_DEMO]->w) / 2;
     dest.y = (screen->h - images[IMG_DEMO]->h) / 2;
@@ -1064,7 +1066,7 @@
   }
 
   /* Draw numeric keypad: */
-  if (game_options->use_keypad)
+  if (Opts_UseKeypad())
   {
     /* pick image to draw: */
     int keypad_image;
@@ -1139,7 +1141,7 @@
   }
   
   /* If using demo mode, see if counter has run out: */ 
-  if (game_options->demo_mode)
+  if (Opts_DemoMode())
   {
     if (demo_countdown <= 0 )
       return GAME_OVER_OTHER;
@@ -1245,7 +1247,7 @@
     bkgd = NULL;
   }
 
-  if (game_options->use_bkgd)
+  if (Opts_UseBkgd())
   {
     bkgd = IMG_Load(fname);
     if (bkgd == NULL)
@@ -1255,7 +1257,7 @@
 	      "%s\n"
 	      "The Simple DirectMedia error that ocurred was: %s\n",
 	      fname, SDL_GetError());
-      game_options->use_bkgd = 0;
+      Opts_SetUseBkgd(0);
     }
   }
 
@@ -1270,8 +1272,8 @@
   /* On first wave or if slowdown flagged due to wrong answer: */
   if (wave == 1 || slowdown)
   {
-    next_wave_comets = game_options->starting_comets;
-    speed = game_options->speed;
+    next_wave_comets = Opts_StartingComets();
+    speed = Opts_Speed();
     slowdown = 0;
   }
 
@@ -1279,15 +1281,15 @@
        /* exceed maximum:                                         */
   {
     next_wave_comets = prev_wave_comets;
-    if (game_options->allow_speedup)
+    if (Opts_AllowSpeedup())
     {
-      next_wave_comets += game_options->extra_comets_per_wave;
-      if (next_wave_comets > game_options->max_comets)
+      next_wave_comets += Opts_ExtraCometsPerWave();
+      if (next_wave_comets > Opts_MaxComets())
       {
-        next_wave_comets = game_options->max_comets;
+        next_wave_comets = Opts_MaxComets();
       }
       
-      use_feedback = game_options->use_feedback;
+      use_feedback = Opts_UseFeedback();
 
       if (use_feedback) 
       {
@@ -1297,9 +1299,9 @@
 	
         /* Update our danger level, i.e., the target height */
 	danger_level = 1 - (1-danger_level) / 
-	                   game_options->danger_level_speedup;
-	if (danger_level > game_options->danger_level_max)
-	  danger_level = game_options->danger_level_max;
+	                   Opts_DangerLevelSpeedup();
+	if (danger_level > Opts_DangerLevelMax())
+	  danger_level = Opts_DangerLevelMax();
 
 	#ifdef FEEDBACK_DEBUG
 	printf(" new danger level = %g.\n",danger_level);
@@ -1336,8 +1338,8 @@
 	  /* Enforce bounds on speed */
 	  if (speed < MINIMUM_SPEED)
 	    speed = MINIMUM_SPEED;
-	  if (speed > game_options->max_speed)
-	    speed = game_options->max_speed;
+	  if (speed > Opts_MaxSpeed())
+	    speed = Opts_MaxSpeed();
 
 	  #ifdef FEEDBACK_DEBUG
 	  printf(" new speed = %g.\n",speed);
@@ -1350,10 +1352,10 @@
       {
         /* This is not an "else" because we might skip feedback */
 	/* when comet_feedback_number == 0 */
-	speed = speed * game_options->speedup_factor;
-	if (speed > game_options->max_speed)
+	speed = speed * Opts_SpeedupFactor();
+	if (speed > Opts_MaxSpeed())
 	{
-	  speed = game_options->max_speed;
+	  speed = Opts_MaxSpeed();
 	}
       }
     }
@@ -1628,7 +1630,7 @@
 
 
 #ifndef NOSOUND
-  if (opts_using_sound())
+  if (Opts_UsingSound())
     Mix_PauseMusic();
 #endif
   
@@ -1652,7 +1654,7 @@
 
 
 #ifndef NOSOUND
-  if (opts_using_sound())
+  if (Opts_UsingSound())
     Mix_ResumeMusic();
 #endif
 
@@ -1904,8 +1906,8 @@
 
   /* get out unless we really are using keypad */
   if ( level_start_wait 
-    || game_options->demo_mode
-    || !game_options->use_keypad)
+    || Opts_DemoMode()
+    || !Opts_UseKeypad())
   {
     return;
   }
@@ -2070,7 +2072,7 @@
     paused = 1;
   }
       
-  if (level_start_wait > 0 || game_options->demo_mode)
+  if (level_start_wait > 0 || Opts_DemoMode())
   {
     /* Eat other keys until level start wait has passed,
     or if game is in demo mode: */

Modified: tuxmath/trunk/src/mathcards.c
===================================================================
--- tuxmath/trunk/src/mathcards.c	2006-10-17 20:36:09 UTC (rev 54)
+++ tuxmath/trunk/src/mathcards.c	2006-10-30 16:44:31 UTC (rev 55)
@@ -2151,7 +2151,8 @@
             }
 
             /* questions like num1 / ? = num3 */
-            if (math_opts->format_div_answer_middle)
+            if ((math_opts->format_div_answer_middle)
+               && (i))      /* This avoids creating indeterminate questions: 0/? = 0 */
             {
               /* make sure max_questions not exceeded */
               if (length < math_opts->max_questions)

Modified: tuxmath/trunk/src/options.c
===================================================================
--- tuxmath/trunk/src/options.c	2006-10-17 20:36:09 UTC (rev 54)
+++ tuxmath/trunk/src/options.c	2006-10-30 16:44:31 UTC (rev 55)
@@ -37,6 +37,7 @@
 int opers[NUM_OPERS], range_enabled[NUM_Q_RANGES];
 
 
+
 /* Local (to options.c) 'globals': */
 /* moved to file scope to allow update_selected_option() to use them DSB */
 static SDL_Rect dest;
@@ -44,6 +45,16 @@
 static unsigned char range_bits;
 static int i, j, x, y;
 
+/* file scope only now that accessor functions used: */
+static game_option_type* game_options;
+
+/*local function prototypes: */
+static void update_selected_option(int option);
+static int int_to_bool(int i);
+static void print_game_options(FILE* fp, int verbose);
+
+
+/* Main options() function - called from title(): */
 int options(void)
 {
   int opt, old_opt, done, quit, img, blinking;
@@ -311,10 +322,614 @@
   return quit;
 }
 
+/********************************************************************/
+/*  "Public Methods" for options struct:                            */
+/********************************************************************/
 
+int Opts_Initialize(void)
+{
+  game_options = malloc(sizeof(game_option_type));
+  /* bail out if no struct */
+  if (!game_options)
+    return 0;
+
+  /* set general game options */
+  game_options->per_user_config = DEFAULT_PER_USER_CONFIG;
+  game_options->use_sound = DEFAULT_USE_SOUND;
+  game_options->fullscreen = DEFAULT_FULLSCREEN;
+  game_options->use_bkgd = DEFAULT_USE_BKGD;
+  game_options->demo_mode = DEFAULT_DEMO_MODE;
+  game_options->oper_override = DEFAULT_OPER_OVERRIDE;
+  game_options->use_keypad = DEFAULT_USE_KEYPAD;
+  game_options->speed = DEFAULT_SPEED;
+  game_options->allow_speedup = DEFAULT_ALLOW_SPEEDUP;
+  game_options->speedup_factor = DEFAULT_SPEEDUP_FACTOR;
+  game_options->max_speed = DEFAULT_MAX_SPEED;
+  game_options->slow_after_wrong = DEFAULT_SLOW_AFTER_WRONG;
+  game_options->starting_comets = DEFAULT_STARTING_COMETS;
+  game_options->extra_comets_per_wave = DEFAULT_EXTRA_COMETS_PER_WAVE;
+  game_options->max_comets = DEFAULT_MAX_COMETS;
+  game_options->save_summary = DEFAULT_SAVE_SUMMARY;
+  game_options->sound_hw_available = DEFAULT_SOUND_HW_AVAILABLE;
+  game_options->use_feedback = DEFAULT_USE_FEEDBACK;
+  game_options->danger_level = DEFAULT_DANGER_LEVEL;
+  game_options->danger_level_speedup = DEFAULT_DANGER_LEVEL_SPEEDUP;
+  game_options->danger_level_max = DEFAULT_DANGER_LEVEL_MAX;
+  game_options->city_expl_handicap = DEFAULT_CITY_EXPL_HANDICAP;
+
+  game_options->num_cities = DEFAULT_NUM_CITIES;   /* MUST BE AN EVEN NUMBER! */
+  game_options->num_bkgds = DEFAULT_NUM_BKGDS;
+  game_options->max_city_colors = DEFAULT_MAX_CITY_COLORS;
+
+  #ifdef TUXMATH_DEBUG
+  print_game_options(stdout, 0);
+  #endif
+
+  return 1;
+}
+
+
+void Opts_Cleanup(void)
+{
+  if (game_options)
+  {
+    free(game_options);
+    game_options = 0;
+  }
+}
+
+
+/* "Set" functions for tuxmath options struct: */
+void Opts_SetPerUserConfig(int val)
+{
+  game_options->per_user_config = int_to_bool(val);
+}
+
+
+void Opts_SetUseSound(int val)
+{
+  game_options->use_sound = int_to_bool(val);
+}
+
+
+void Opts_SetFullscreen(int val)
+{
+  game_options->fullscreen = int_to_bool(val);
+}
+
+
+void Opts_SetUseBkgd(int val)
+{
+  game_options->use_bkgd = int_to_bool(val);
+}
+
+
+void Opts_SetDemoMode(int val)
+{
+  game_options->demo_mode = int_to_bool(val);
+}
+
+
+void Opts_SetOperOverride(int val)
+{
+  game_options->oper_override = int_to_bool(val);
+}
+
+
+void Opts_SetUseKeypad(int val)
+{
+  game_options->use_keypad = int_to_bool(val);
+}
+
+
+void Opts_SetSpeed(float val)
+{
+  if (val < MINIMUM_SPEED)
+  {
+    val = MINIMUM_SPEED;
+    fprintf(stderr,"Warning: requested speed below minimum, setting to %g.\n",MINIMUM_SPEED);
+  }
+  if (val > MAX_MAX_SPEED)
+  {
+    val = MAX_MAX_SPEED;
+    fprintf(stderr,"Warning: requested speed above Tuxmath's maximum, setting to %g.\n",MAX_MAX_SPEED);
+  }
+  if (val > Opts_MaxSpeed())
+  {
+    val = Opts_MaxSpeed();
+    fprintf(stderr,"Warning: requested speed above currently selected maximum, setting to %g.\n",
+            Opts_MaxSpeed());
+  }
+  game_options->speed = val;
+}
+
+
+void Opts_SetAllowSpeedup(int val)
+{
+  game_options->allow_speedup = int_to_bool(val);
+}
+
+
+void Opts_SetSpeedupFactor(float val)
+{
+  if (val < MIN_SPEEDUP_FACTOR)
+  {
+    val = MIN_SPEEDUP_FACTOR;
+    fprintf(stderr,"Warning: requested speedup factor below Tuxmath's minimum, setting to %g.\n",MIN_SPEEDUP_FACTOR);
+  }
+  if (val > MAX_SPEEDUP_FACTOR)
+  {
+    val = MAX_SPEEDUP_FACTOR;
+    fprintf(stderr,"Warning: requested speedup factor above Tuxmath's maximum, setting to %g.\n",MAX_SPEEDUP_FACTOR);
+  }
+  game_options->speedup_factor = val;
+}
+
+
+void Opts_SetMaxSpeed(float val)
+{
+  if (val < MINIMUM_SPEED)
+  {
+    val = MINIMUM_SPEED;
+    fprintf(stderr,"Warning: requested max speed below minimum, setting to %g.\n",
+            MINIMUM_SPEED);
+  }
+  if (val > MAX_MAX_SPEED)
+  {
+    val = MAX_MAX_SPEED;
+    fprintf(stderr,"Warning: requested max speed above Tuxmath's maximum, setting to %g.\n",
+            MAX_MAX_SPEED);
+  }
+  if (val < Opts_Speed())
+  {
+    val = Opts_Speed();
+    fprintf(stderr,"Warning: requested max speed less than current speed, setting to %g.\n",
+            Opts_MaxSpeed());
+  }
+  game_options->max_speed = val;
+}
+
+
+void Opts_SetSlowAfterWrong(int val)
+{
+  game_options->slow_after_wrong = int_to_bool(val);
+}
+
+
+void Opts_SetStartingComets(int val)
+{
+  if (val < MIN_COMETS)
+  {
+    val = MIN_COMETS;
+    fprintf(stderr,"Warning: requested starting comets below Tuxmath's minimum, setting to %d.\n",
+            MIN_COMETS);
+  }
+  if (val > MAX_MAX_COMETS)
+  {
+    val = MAX_MAX_COMETS;
+    fprintf(stderr,"Warning: requested starting comets above Tuxmath's maximum, setting to %d.\n",
+            MAX_MAX_COMETS);
+  }
+  if (val > Opts_MaxComets())
+  {
+    val = Opts_MaxComets();
+    fprintf(stderr,"Warning: requested starting comets above currently selected maximum, setting to %d.\n",
+            Opts_MaxComets());
+  }
+  game_options->starting_comets = val;
+}
+
+
+void Opts_SetExtraCometsPerWave(int val)
+{
+  if (val < 0)
+  {
+    val = 0;
+    fprintf(stderr,"Warning: requested extra comets below Tuxmath's minimum, setting to %d.\n",
+            0);
+  }
+  if (val > MAX_MAX_COMETS)
+  {
+    val = MAX_MAX_COMETS;
+    fprintf(stderr,"Warning: requested extra comets above Tuxmath's maximum, setting to %d.\n",
+            MAX_MAX_COMETS);
+  }
+  if (val > Opts_MaxComets())
+  {
+    val = Opts_MaxComets();
+    fprintf(stderr,"Warning: requested extra comets above currently selected maximum, setting to %d.\n",
+            Opts_MaxComets());
+  }
+  game_options->extra_comets_per_wave = val;
+}
+
+
+void Opts_SetMaxComets(int val)
+{
+  if (val < MIN_COMETS)
+  {
+    val = MIN_COMETS;
+    fprintf(stderr,"Warning: requested max comets below Tuxmath's minimum, setting to %d.\n",
+            MIN_COMETS);
+  }
+  if (val > MAX_MAX_COMETS)
+  {
+    val = MAX_MAX_COMETS;
+    fprintf(stderr,"Warning: requested max comets above Tuxmath's maximum, setting to %d.\n",
+            MAX_MAX_COMETS);
+  }
+  game_options->extra_comets_per_wave = val;
+}
+
+
+void Opts_SetNextMission(char* str)
+{
+  int len = strlen(str);
+  if (len < PATH_MAX)
+  {
+    strcpy(game_options->next_mission, str);
+  }
+  else
+  {
+    fprintf(stderr,"Warning: Opts_SetNextMission() - string invalid or overflow\n");
+  }
+}
+
+
+void Opts_SetSaveSummary(int val)
+{
+  game_options->save_summary = int_to_bool(val);
+}
+
+
+void Opts_SetUseFeedback(int val)
+{
+  game_options->use_feedback = int_to_bool(val);
+}
+
+
+void Opts_SetDangerLevel(float val)
+{
+  if (val < 0)
+  {
+    val = 0;
+    fprintf(stderr,"Warning: danger level must be between 0 and 1, setting to 0.\n");
+  }
+  if (val > 1)
+  {
+    val = 1;
+    fprintf(stderr,"Warning: danger level must be between 0 and 1, setting to 1.\n");
+  }
+  game_options->danger_level = val;
+}
+
+
+void Opts_SetDangerLevelSpeedup(float val)
+{
+      if (val < 1)
+      {
+        val = 1;
+        fprintf(stderr,"Warning: danger_level_speedup must be at least 1, setting to 1.\n");
+      }
+  game_options->danger_level_speedup = val;
+}
+
+
+void Opts_SetDangerLevelMax(float val)
+{
+  if (val < 0)
+  {
+    val = 0;
+    fprintf(stderr,"Warning: danger level max must be between 0 and 1, setting to 0.\n");
+  }
+  if (val > 1)
+  {
+    val = 1;
+    fprintf(stderr,"Warning: danger level max must be between 0 and 1, setting to 1.\n");
+  }
+  game_options->danger_level_max = val;
+}
+
+
+void Opts_SetCityExplHandicap(float val)
+{
+  if (val < 0)
+  {
+    val = 0;
+    fprintf(stderr,"Warning: city_explode_handicap level set below minimum, setting to 0.\n");
+  }
+  game_options->city_expl_handicap = val;
+}
+
+
+
+/* whether sound system is successfully initialized and sound files loaded: */
+/* this flag is set by the program, not the user, and is not in the config file. */
+void Opts_SetSoundHWAvailable(int val)
+{
+  game_options->sound_hw_available = int_to_bool(val);
+}
+
+
+
+/* "Get" functions for tuxmath options struct: */
+int Opts_PerUserConfig(void)
+{
+  if (!game_options)
+  {
+    fprintf(stderr, "\nOpts_PerUserConfig(): game_options not valid!\n");
+    return GAME_OPTS_INVALID;
+  }
+  return game_options->per_user_config;
+}
+
+
+int Opts_UseSound(void)
+{
+  if (!game_options)
+  {
+    fprintf(stderr, "\nOpts_UseSound(): game_options not valid!\n");
+    return GAME_OPTS_INVALID;
+  }
+  return game_options->use_sound;
+
+}
+
+
+int Opts_Fullscreen(void)
+{
+  if (!game_options)
+  {
+    fprintf(stderr, "\nOpts_Fullscreen(): game_options not valid!\n");
+    return GAME_OPTS_INVALID;
+  }
+  return game_options->fullscreen;
+}
+
+
+int Opts_UseBkgd(void)
+{
+  if (!game_options)
+  {
+    fprintf(stderr, "\nOpts_UserBkgd(): game_options not valid!\n");
+    return GAME_OPTS_INVALID;
+  }
+  return game_options->use_bkgd;
+}
+
+
+int Opts_DemoMode(void)
+{
+  if (!game_options)
+  {
+    fprintf(stderr, "\nOpts_DemoMode(): game_options not valid!\n");
+    return GAME_OPTS_INVALID;
+  }
+  return game_options->demo_mode;
+}
+
+
+int Opts_OperOverride(void)
+{
+  if (!game_options)
+  {
+    fprintf(stderr, "\nOpts_OperOverride(): game_options not valid!\n");
+    return GAME_OPTS_INVALID;
+  }
+  return game_options->oper_override;
+}
+
+
+int Opts_UseKeypad(void)
+{
+  if (!game_options)
+  {
+    fprintf(stderr, "\nOpts_UseKeypad(): game_options not valid!\n");
+    return GAME_OPTS_INVALID;
+  }
+  return game_options->use_keypad;
+}
+
+
+float Opts_Speed(void)
+{
+  if (!game_options)
+  {
+    fprintf(stderr, "\nOpts_Speed(): game_options not valid!\n");
+    return GAME_OPTS_INVALID;
+  }
+  return game_options->speed;
+}
+
+
+int Opts_AllowSpeedup(void)
+{
+  if (!game_options)
+  {
+    fprintf(stderr, "\nOpts_AllowSpeedup(): game_options not valid!\n");
+    return GAME_OPTS_INVALID;
+  }
+  return game_options->allow_speedup;
+}
+
+
+float Opts_SpeedupFactor(void)
+{
+  if (!game_options)
+  {
+    fprintf(stderr, "\nOpts_SpeedupFactor(): game_options not valid!\n");
+    return GAME_OPTS_INVALID;
+  }
+  return game_options->speedup_factor;
+}
+
+
+float Opts_MaxSpeed(void)
+{
+  if (!game_options)
+  {
+    fprintf(stderr, "\nOpts_MaxSpeed(): game_options not valid!\n");
+    return GAME_OPTS_INVALID;
+  }
+  return game_options->max_speed;
+}
+
+
+int Opts_SlowAfterWrong(void)
+{
+  if (!game_options)
+  {
+    fprintf(stderr, "\nOpts_SlowAfterWrong(): game_options not valid!\n");
+    return GAME_OPTS_INVALID;
+  }
+  return game_options->slow_after_wrong;
+}
+
+
+int Opts_StartingComets(void)
+{
+  if (!game_options)
+  {
+    fprintf(stderr, "\nOpts_StartingComets(): game_options not valid!\n");
+    return GAME_OPTS_INVALID;
+  }
+  return game_options->starting_comets;
+}
+
+
+int Opts_ExtraCometsPerWave(void)
+{
+  if (!game_options)
+  {
+    fprintf(stderr, "\nOpts_ExtraCometsPerWave(): game_options not valid!\n");
+    return GAME_OPTS_INVALID;
+  }
+  return game_options->extra_comets_per_wave;
+}
+
+
+int Opts_MaxComets(void)
+{
+  if (!game_options)
+  {
+    fprintf(stderr, "\nOpts_MaxComets(): game_options not valid!\n");
+    return GAME_OPTS_INVALID;
+  }
+  return game_options->max_comets;
+}
+
+
+char* Opts_NextMission(void)
+{
+  char* str;
+  int length;
+  length = strlen(game_options->next_mission);
+  str = malloc((length * sizeof(char)) + 1);
+  strcpy(str, game_options->next_mission);
+  return str;
+}
+
+
+int Opts_SaveSummary(void)
+{
+  if (!game_options)
+  {
+    fprintf(stderr, "\nOpts_SaveSummary(): game_options not valid!\n");
+    return GAME_OPTS_INVALID;
+  }
+  return game_options->save_summary;
+}
+
+
+int Opts_UseFeedback(void)
+{
+  if (!game_options)
+  {
+    fprintf(stderr, "\nOpts_UseFeedback(): game_options not valid!\n");
+    return GAME_OPTS_INVALID;
+  }
+  return game_options->use_feedback;
+}
+
+
+float Opts_DangerLevel(void)
+{
+  if (!game_options)
+  {
+    fprintf(stderr, "\nOpts_DangerLevel(): game_options not valid!\n");
+    return GAME_OPTS_INVALID;
+  }
+  return game_options->danger_level;
+}
+
+
+float Opts_DangerLevelSpeedup(void)
+{
+  if (!game_options)
+  {
+    fprintf(stderr, "\nOpts_DangerLevelSpeedup(): game_options not valid!\n");
+    return GAME_OPTS_INVALID;
+  }
+  return game_options->danger_level_speedup;
+}
+
+
+float Opts_DangerLevelMax(void)
+{
+  if (!game_options)
+  {
+    fprintf(stderr, "\nOpts_DangerLevelMax(): game_options not valid!\n");
+    return GAME_OPTS_INVALID;
+  }
+  return game_options->danger_level_max;
+}
+
+
+float Opts_CityExplHandicap(void)
+{
+  if (!game_options)
+  {
+    fprintf(stderr, "\nOpts_CityExplHandicap(): game_options not valid!\n");
+    return GAME_OPTS_INVALID;
+  }
+  return game_options->city_expl_handicap;
+}
+
+
+
+/* whether sound system is successfully initialized and sound files loaded: */
+/* this flag is set by the program, not the user, and is not in the config file. */
+int Opts_SoundHWAvailable(void)
+{
+  if (!game_options)
+  {
+    fprintf(stderr, "\nOpts_SoundHWAvailable(): game_options not valid!\n");
+    return GAME_OPTS_INVALID;
+  }
+  return game_options->sound_hw_available;
+}
+
+
+/* Returns true if only if the player wants to use sound */
+/* and the sound system is actually available:           */
+int Opts_UsingSound(void)
+{
+  if (!game_options)
+  {
+    fprintf(stderr, "\nOpts_UsingSound(): game_options not valid!\n");
+    return GAME_OPTS_INVALID;
+  }
+  return (game_options->use_sound && game_options->sound_hw_available);
+}
+
+/********************************************************************/
+/*  "private methods" (static functions only visible in options.c)  */
+/********************************************************************/
+
+
 /* can be called by either keystroke or mouse click - moved into */
 /* separate function to reduce code duplication - DSB */
-void update_selected_option(int option)
+static void update_selected_option(int option)
 {
   {
     if (option >= OPT_OP_ADD && option < OPT_OP_ADD + NUM_OPERS)
@@ -476,3 +1091,221 @@
     playsound(SND_LASER);
   }
 }
+
+
+/* to prevent option settings in math_opts from getting set to */
+/* values other than 0 or 1                                    */
+int int_to_bool(int i)
+{
+  if (i)
+    return 1;
+  else
+    return 0;
+}
+
+
+/* prints struct to stream: */
+void print_game_options(FILE* fp, int verbose)
+{
+ /* bail out if no struct */
+  if (!game_options)
+  {
+    fprintf(stderr, "print_game_options(): invalid game_option_type struct");
+    return;
+  }
+
+  if(verbose)
+  {
+    fprintf (fp, "\n############################################################\n" 
+                 "#                                                          #\n"
+                 "#                 General Game Options                     #\n"
+                 "#                                                          #\n"
+                 "# The following options are boolean (true/false) variables #\n"
+                 "# that control various aspects of Tuxmath's behavior.      #\n"
+                 "# The program writes the values to the file as either '0'  #\n"
+                 "# or '1'. However, the program accepts 'n', 'no', 'f', and #\n"
+                 "# 'false' as synonyms for '0', and similarly accepts 'y',  #\n"
+                 "# 'yes', 't', and 'true' as synonyms for '1' (all case-    #\n"
+                 "# insensitive).                                            #\n"
+                 "############################################################\n\n");
+  }
+
+  if(verbose)
+  {
+    fprintf (fp, "############################################################\n" 
+                 "# 'per_user_config' determines whether Tuxmath will look   #\n"
+                 "# in the user's home directory for settings. Default is 1  #\n"
+                 "# (yes). If deselected, the program will ignore the user's #\n"
+                 "# .tuxmath file and use the the global settings in the     #\n"
+                 "# installation-wide config file.                           #\n"
+                 "# This setting cannot be changed by an ordinary user.      #\n"
+                 "############################################################\n");
+  }
+  fprintf(fp, "per_user_config = %d\n", game_options->per_user_config);
+
+  if(verbose)
+  {
+    fprintf (fp, "\n# Self-explanatory, default is 1:\n");
+  }
+  fprintf(fp, "use_sound = %d\n", game_options->use_sound);
+
+  if(verbose)
+  {
+    fprintf (fp, "\n# Use fullscreen at 640x480 resolution instead of\n"
+                 "640x480 window. Default is 1 (fullscreen). Change to 0\n"
+                 "if SDL has trouble with fullscreen on your system.\n");
+  } 
+  fprintf(fp, "fullscreen = %d\n", game_options->fullscreen);
+
+  if(verbose)
+  {
+    fprintf (fp, "\n# Use 640x480 jpg image for background; default is 1.\n");
+  }
+  fprintf(fp, "use_bkgd = %d\n", game_options->use_bkgd);
+
+  if(verbose)
+  {
+    fprintf (fp, "\n# Program runs as demo; default is 0.\n");
+  }
+  fprintf(fp, "demo_mode = %d\n", game_options->demo_mode);
+
+  if(verbose)
+  {
+    fprintf (fp, "\n# Use operator selection from command line; default is 0.\n");
+  }
+  fprintf(fp, "oper_override = %d\n", game_options->oper_override);
+
+  if(verbose)
+  {
+    fprintf (fp, "\n# Display onscreen numeric keypad; default is 0.\n");
+  }
+  fprintf(fp, "use_keypad = %d\n", game_options->use_keypad);
+
+  if(verbose)
+  {
+    fprintf (fp, "\n############################################################\n" 
+                 "# The next settings determine the speed and number         #\n"
+                 "# of comets.  The speed settings are float numbers (mean-  #\n"
+                 "# ing decimals allowed). The comet settings are integers.  #\n"
+                 "#                                                          #\n"
+                 "# Starting comet speed and max comet speed are generally   #\n"
+                 "# applicable. The main choice is whether you want to use   #\n"
+                 "# feedback, i.e., to adjust the speed automatically based  #\n"
+                 "# on the player's performance.                             #\n"
+                 "#                                                          #\n"
+                 "# Without feedback, the speed increases by a user-         #\n"
+                 "# settable factor ('speedup_factor'), with an option       #\n"
+                 "# ('slow_after_wrong') to go back to the starting speed    #\n"
+                 "# when a city gets hit.                                    #\n"
+                 "#                                                          #\n"
+                 "# With feedback, you set a desired 'danger level,' which   #\n"
+                 "# determines how close the comets should typically         #\n"
+                 "# approach the cities before the player succeeds in        #\n"
+                 "# destroying them.  The game will adjust its speed         #\n"
+                 "# accordingly, getting faster when the player is easily    #\n"
+                 "# stopping the comets, and slowing down when there are     #\n"
+                 "# too many close calls or hits. You can also have the      #\n"
+                 "# danger level increase with each wave.                    #\n"
+                 "############################################################\n");
+  }
+
+  if(verbose)
+  {
+    fprintf (fp, "\n# Whether to increase speed and number of comets with \n"
+                 "# each wave.  May want to turn this off for smaller kids.\n"
+                 "# Default is 1 (allow game to speed up)\n");
+  }
+  fprintf(fp, "allow_speedup = %d\n", game_options->allow_speedup);
+
+
+  fprintf(fp, "slow_after_wrong = %d\n", game_options->slow_after_wrong);
+
+  if(verbose)
+  {
+    fprintf (fp, "\n# Starting comet speed. Default is 1.\n");
+  }
+  fprintf(fp, "speed = %f\n", game_options->speed);
+
+  if(verbose)
+  {
+    fprintf (fp, "\n# If feedback is not used but 'allow_speedup' is\n"
+                 "# enabled, the comet speed will be\n"
+                 "# multiplied by this factor with each new wave.\n"
+                 "# Default is 1.2 (i.e. 20 percent increase per wave)\n");
+  }
+  fprintf(fp, "speedup_factor = %f\n", game_options->speedup_factor);
+
+  if(verbose)
+  {
+    fprintf (fp, "\n# Maximum speed. Default is 10.\n");
+  }
+  fprintf(fp, "max_speed = %f\n", game_options->max_speed);
+
+  if(verbose)
+  {
+    fprintf (fp, "\n# Number of comets for first wave. Default is 2.\n");
+  }
+  fprintf(fp, "starting_comets = %d\n", game_options->starting_comets);
+
+  if(verbose)
+  {
+    fprintf (fp, "\n# Comets to add for each successive wave. Default is 2.\n");
+  }
+  fprintf(fp, "extra_comets_per_wave = %d\n", game_options->extra_comets_per_wave);
+
+  if(verbose)
+  {
+    fprintf (fp, "\n# Maximum number of comets. Default is 10.\n");
+  }
+  fprintf(fp, "max_comets = %d\n", game_options->max_comets);
+
+  if(verbose)
+  {
+     fprintf (fp, "\n# Use feedback? Default (for now) is false, 0.\n");
+  }
+  fprintf(fp, "use_feedback = %d\n", game_options->use_feedback);
+
+
+   if(verbose)
+   {
+     fprintf (fp, "\n# (Feedback) Set the desired danger level.\n"
+             "# 0 = too safe, comets typically exploded right at the very top\n"
+             "# 1 = too dangerous, comets typically exploded at the moment they hit cities\n"
+             "# Set it somewhere between these extremes. As a guideline, early\n"
+             "# elementary kids might feel comfortable around 0.2-0.3, older kids\n"
+             "# at around 0.4-0.6. Default 0.35.\n");
+   }
+   fprintf(fp, "danger_level = %f\n", game_options->danger_level);
+
+   if(verbose)
+   {
+     fprintf (fp, "\n# (Feedback) Set danger level speedup.\n"
+                  "# The margin of safety will decrease by this factor each wave.\n"
+                  "# Default 1.1. Note 1 = no increase in danger level.\n");
+   }
+   fprintf(fp, "danger_level_speedup = %f\n", game_options->danger_level_speedup);
+
+   if(verbose)
+   {
+     fprintf (fp, "\n# (Feedback) Set the maximum danger level.\n"
+                  "# Default 0.9.\n");
+   }
+   fprintf(fp, "danger_level_max = %f\n", game_options->danger_level_max);
+
+   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 slow_after_wrong,\n"
+                  "# but allows for more gradual changes.\n"
+                  "# Default 0 (no extra handicap).\n");
+   }
+   fprintf(fp, "city_explode_handicap = %f\n", game_options->city_expl_handicap);
+
+/*
+  fprintf(fp, "num_cities = %d\n", game_options->num_cities);
+  fprintf(fp, "num_bkgds = %d\n", game_options->num_bkgds);
+  fprintf(fp, "max_city_colors = %d\n", game_options->max_city_colors);
+*/
+}

Modified: tuxmath/trunk/src/options.h
===================================================================
--- tuxmath/trunk/src/options.h	2006-10-17 20:36:09 UTC (rev 54)
+++ tuxmath/trunk/src/options.h	2006-10-30 16:44:31 UTC (rev 55)
@@ -19,6 +19,45 @@
 #ifndef OPTIONS_H
 #define OPTIONS_H
 
+#include "tuxmath.h"  /* needed for PATH_MAX definition */
+
+/* this struct contains all options regarding general       */
+/* gameplay but not having to do with math questions per se */
+typedef struct game_option_type {
+  /* general game options */
+  int per_user_config;
+  int use_sound;
+  int fullscreen;
+  int use_bkgd;
+  int demo_mode;
+  int oper_override;
+  int use_keypad;
+  float speed;
+  int allow_speedup;
+  float speedup_factor;
+  float max_speed;
+  int slow_after_wrong;
+  int starting_comets;
+  int extra_comets_per_wave;
+  int max_comets;  
+  char next_mission[PATH_MAX];
+  int save_summary;
+  int use_feedback;
+  float danger_level;
+  float danger_level_speedup;
+  float danger_level_max;
+  float city_expl_handicap;
+
+  /* whether sound system is successfully initialized and sound files loaded: */
+  /* this flag is set by the program, not the user, and is not in the config file. */
+  int sound_hw_available;
+  /* not sure the rest of these belong in here */
+  int num_cities;  /* MUST BE AN EVEN NUMBER! */
+  int num_bkgds;
+  int max_city_colors;
+} game_option_type;
+
+
 enum {
   OPT_OP_ADD,
   OPT_OP_SUB,
@@ -30,6 +69,73 @@
   NUM_OPTS
 };
 
+/* global struct (until accessor functions completed) */
+//extern game_option_type* game_options; /* used by setup.c, options.c, game.c */
+
+/* main options function called from title(): */
 int options(void);
-void update_selected_option(int option);
+
+/* "Public methods" of game_option_type struct; program interacts with struct */
+/* through these simple functions (rather than directly) to allow for error   */
+/* checking, etc.                                                             */
+int Opts_Initialize(void);
+void Opts_Cleanup(void);
+
+/* "Set" functions for tuxmath options struct: */
+void Opts_SetPerUserConfig(int val);
+void Opts_SetUseSound(int val);
+void Opts_SetFullscreen(int val);
+void Opts_SetUseBkgd(int val);
+void Opts_SetDemoMode(int val);
+void Opts_SetOperOverride(int val);
+void Opts_SetUseKeypad(int val);
+void Opts_SetSpeed(float val);
+void Opts_SetAllowSpeedup(int val);
+void Opts_SetSpeedupFactor(float val);
+void Opts_SetMaxSpeed(float val);
+void Opts_SetSlowAfterWrong(int val);
+void Opts_SetStartingComets(int val);
+void Opts_SetExtraCometsPerWave(int val);
+void Opts_SetMaxComets(int val);
+void Opts_SetNextMission(char* str);
+void Opts_SetSaveSummary(int val);
+void Opts_SetUseFeedback(int val);
+void Opts_SetDangerLevel(float val);
+void Opts_SetDangerLevelSpeedup(float val);
+void Opts_SetDangerLevelMax(float val);
+void Opts_SetCityExplHandicap(float val);
+
+/* whether sound system is successfully initialized and sound files loaded: */
+/* this flag is set by the program, not the user, and is not in the config file. */
+void Opts_SetSoundHWAvailable(int val);
+
+/* "Get" functions for tuxmath options struct: */
+int Opts_PerUserConfig(void);
+int Opts_UseSound(void);
+int Opts_Fullscreen(void);
+int Opts_UseBkgd(void);
+int Opts_DemoMode(void);
+int Opts_OperOverride(void);
+int Opts_UseKeypad(void);
+float Opts_Speed(void);
+int Opts_AllowSpeedup(void);
+float Opts_SpeedupFactor(void);
+float Opts_MaxSpeed(void);
+int Opts_SlowAfterWrong(void);
+int Opts_StartingComets(void);
+int Opts_ExtraCometsPerWave(void);
+int Opts_MaxComets(void);
+char* Opts_NextMission(void);
+int Opts_SaveSummary(void);
+int Opts_UseFeedback(void);
+float Opts_DangerLevel(void);
+float Opts_DangerLevelSpeedup(void);
+float Opts_DangerLevelMax(void);
+float Opts_CityExplHandicap(void);
+
+/* whether sound system is successfully initialized and sound files loaded: */
+/* this flag is set by the program, not the user, and is not in the config file. */
+int Opts_SoundHWAvailable(void);
+/* this is the function that says if sound is both desired and actually available: */
+int Opts_UsingSound(void);
 #endif

Modified: tuxmath/trunk/src/playsound.c
===================================================================
--- tuxmath/trunk/src/playsound.c	2006-10-17 20:36:09 UTC (rev 54)
+++ tuxmath/trunk/src/playsound.c	2006-10-30 16:44:31 UTC (rev 55)
@@ -21,13 +21,13 @@
 #ifndef NOSOUND
 #include <SDL_mixer.h>
 #endif
-#include "setup.h"
+#include "options.h"
 #include "tuxmath.h"
 
 void playsound(int snd)
 {
 #ifndef NOSOUND
-  if (opts_using_sound())
+  if (Opts_UsingSound())
     Mix_PlayChannel(-1, sounds[snd], 0);
 #endif
 }

Modified: tuxmath/trunk/src/setup.c
===================================================================
--- tuxmath/trunk/src/setup.c	2006-10-17 20:36:09 UTC (rev 54)
+++ tuxmath/trunk/src/setup.c	2006-10-30 16:44:31 UTC (rev 55)
@@ -38,7 +38,7 @@
 
 #include <SDL_image.h>
 
-
+#include "options.h"
 #include "tuxmath.h"
 #include "mathcards.h"
 #include "setup.h"
@@ -104,8 +104,7 @@
   }
 
   /* initialize game_options struct with defaults DSB */
-  game_options = malloc(sizeof(game_option_type));
-  if (!initialize_game_options())
+  if (!Opts_Initialize())
   {
     printf("\nUnable to initialize game_options\n");
     fprintf(stderr, "\nUnable to initialize game_options\n");
@@ -125,7 +124,7 @@
   /* Now read in user-specific settings, if desired.  By    */
   /* default, this restores settings from the player's last */
   /* game:                                                  */
-  if (game_options->per_user_config)
+  if (Opts_PerUserConfig())
   {
     if (!read_user_config_file())
     {
@@ -247,19 +246,19 @@
     else if (strcmp(argv[i], "--fullscreen") == 0 ||
 	     strcmp(argv[i], "-f") == 0)
     {
-      game_options->fullscreen = 1;
+      Opts_SetFullscreen(1);
     }
     else if (strcmp(argv[i], "--windowed") == 0 ||
 	     strcmp(argv[i], "-w") == 0)
     {
-      game_options->fullscreen = 0;
+      Opts_SetFullscreen(0);
     }
     else if (strcmp(argv[i], "--nosound") == 0 ||
 	     strcmp(argv[i], "-s") == 0 ||
 	     strcmp(argv[i], "--quiet") == 0 ||
 	     strcmp(argv[i], "-q") == 0)
     {
-      game_options->use_sound = 0;
+      Opts_SetUseSound(0);
     }
     else if (strcmp(argv[i], "--version") == 0 ||
 	     strcmp(argv[i], "-v") == 0)
@@ -272,17 +271,17 @@
     else if (strcmp(argv[i], "--nobackground") == 0 ||
              strcmp(argv[i], "-b") == 0)
     {
-      game_options->use_bkgd = 0;
+      Opts_SetUseBkgd(0);
     }
     else if (strcmp(argv[i], "--demo") == 0 ||
 	     strcmp(argv[i], "-d") == 0)
     {
-      game_options->demo_mode = 1;
+      Opts_SetDemoMode(1);
     }
     else if (strcmp(argv[i], "--keypad") == 0 ||
              strcmp(argv[i], "-k") == 0)
     {
-      game_options->use_keypad = 1;
+      Opts_SetUseKeypad(1);
     }
     else if (strcmp(argv[i], "--allownegatives") == 0 ||
              strcmp(argv[i], "-n") == 0)
@@ -315,15 +314,7 @@
 	usage(1, argv[0]);
       }
 
-      game_options->speed = strtod(argv[i + 1], (char **) NULL);
-
-      if (game_options->speed <= 0)
-      {
-	fprintf(stderr, "Invalided argument to %s: %s\n",
-		argv[i], argv[i + 1]);
-	usage(1, argv[0]);
-      }
-
+      Opts_SetSpeed(strtod(argv[i + 1], (char **) NULL));
       i++;
     }
 
@@ -367,10 +358,10 @@
   }/* end of command-line args */
 
 
-  if (game_options->demo_mode && game_options->use_keypad)
+  if (Opts_DemoMode() && Opts_UseKeypad())
   {
     fprintf(stderr, "No use for keypad in demo mode!\n");
-    game_options->use_keypad = 0;
+    Opts_SetUseKeypad(0);
   }
 }
 
@@ -395,7 +386,7 @@
 
   #ifndef NOSOUND
   /* Init SDL Audio: */
-  if (game_options->use_sound)
+  if (Opts_UseSound())
   { 
     if (SDL_Init(SDL_INIT_AUDIO) < 0)
     {
@@ -403,12 +394,12 @@
             "\nWarning: I could not initialize audio!\n"
             "The Simple DirectMedia error that occured was:\n"
             "%s\n\n", SDL_GetError());
-      game_options->sound_available = 0;
+      Opts_SetSoundHWAvailable(0);
     }
   }
 
  
-  if (game_options->use_sound)
+  if (Opts_UseSound())
   {
     if (Mix_OpenAudio(44100, AUDIO_S16SYS, 2, 2048) < 0)
     {
@@ -417,13 +408,13 @@
 	      "16-bit stereo.\n"
 	      "The Simple DirectMedia error that occured was:\n"
 	      "%s\n\n", SDL_GetError());
-      game_options->sound_available = 0;
+      Opts_SetSoundHWAvailable(0);
     }
   }
   #endif
 
 
-  if (game_options->fullscreen)
+  if (Opts_Fullscreen())
   {
     screen = SDL_SetVideoMode(640, 480, 16, SDL_FULLSCREEN | SDL_HWSURFACE);
 
@@ -433,11 +424,11 @@
               "\nWarning: I could not open the display in fullscreen mode.\n"
 	      "The Simple DirectMedia error that occured was:\n"
 	      "%s\n\n", SDL_GetError());
-      game_options->fullscreen = 0;
+      Opts_SetFullscreen(0);
     }
   }
 
-  if (!game_options->fullscreen)
+  if (!Opts_Fullscreen())
   {
     screen = SDL_SetVideoMode(640, 480, 16, SDL_HWSURFACE);
   }
@@ -471,7 +462,7 @@
   if (!load_sound_data())
   {
     fprintf(stderr, "\nCould not load sound file - attempting to proceed without sound.\n");
-    game_options->sound_available = 0;
+    Opts_SetSoundHWAvailable(0);
   }
 
   
@@ -514,67 +505,18 @@
 void cleanup_memory(void)
 {
   SDL_Quit();
-  if (game_options)
-  {
-    free(game_options);
-    game_options = 0;
-  }
+  /* frees the game_options struct: */
+  Opts_Cleanup();
   /* frees any heap used by MathCards: */
   MC_EndGame();
 }
 
 
 
-int initialize_game_options(void)
-{
-  /* bail out if no struct */
-  if (!game_options)
-    return 0;
 
-  /* set general game options */
-  game_options->per_user_config = DEFAULT_PER_USER_CONFIG;
-  game_options->use_sound = DEFAULT_USE_SOUND;
-  game_options->fullscreen = DEFAULT_FULLSCREEN;
-  game_options->use_bkgd = DEFAULT_USE_BKGD;
-  game_options->demo_mode = DEFAULT_DEMO_MODE;
-  game_options->oper_override = DEFAULT_OPER_OVERRIDE;
-  game_options->use_keypad = DEFAULT_USE_KEYPAD;
-  game_options->speed = DEFAULT_SPEED;
-  game_options->allow_speedup = DEFAULT_ALLOW_SPEEDUP;
-  game_options->speedup_factor = DEFAULT_SPEEDUP_FACTOR;
-  game_options->max_speed = DEFAULT_MAX_SPEED;
-  game_options->slow_after_wrong = DEFAULT_SLOW_AFTER_WRONG;
-  game_options->starting_comets = DEFAULT_STARTING_COMETS;
-  game_options->extra_comets_per_wave = DEFAULT_EXTRA_COMETS_PER_WAVE;
-  game_options->max_comets = DEFAULT_MAX_COMETS;
-  game_options->save_summary = DEFAULT_SAVE_SUMMARY;
-  game_options->sound_available = DEFAULT_SOUND_AVAILABLE;
-  game_options->use_feedback = DEFAULT_USE_FEEDBACK;
-  game_options->danger_level = DEFAULT_DANGER_LEVEL;
-  game_options->danger_level_speedup = DEFAULT_DANGER_LEVEL_SPEEDUP;
-  game_options->danger_level_max = DEFAULT_DANGER_LEVEL_MAX;
-  game_options->city_expl_handicap = DEFAULT_CITY_EXPL_HANDICAP;
 
-  game_options->num_cities = DEFAULT_NUM_CITIES;   /* MUST BE AN EVEN NUMBER! */
-  game_options->num_bkgds = DEFAULT_NUM_BKGDS;
-  game_options->max_city_colors = DEFAULT_MAX_CITY_COLORS;
 
-  #ifdef TUXMATH_DEBUG
-  print_game_options(stdout, 0);
-  #endif
 
-  return 1;
-}
-
-/* Returns true if only if the player wants to use sound */
-/* and the sound system is actually available:           */
-int opts_using_sound(void)
-{
-  return (game_options->use_sound && game_options->sound_available);
-}
-
-
-
 /* Set the application's icon: */
 
 void seticon(void)

Modified: tuxmath/trunk/src/setup.h
===================================================================
--- tuxmath/trunk/src/setup.h	2006-10-17 20:36:09 UTC (rev 54)
+++ tuxmath/trunk/src/setup.h	2006-10-30 16:44:31 UTC (rev 55)
@@ -34,5 +34,4 @@
 void cleanup(void);
 void cleanup_on_error(void);
 
-int opts_using_sound(void);
 #endif

Modified: tuxmath/trunk/src/title.c
===================================================================
--- tuxmath/trunk/src/title.c	2006-10-17 20:36:09 UTC (rev 54)
+++ tuxmath/trunk/src/title.c	2006-10-30 16:44:31 UTC (rev 55)
@@ -27,8 +27,8 @@
 #include "fileops.h"
 #include "setup.h"
 #include "playsound.h"
+#include "options.h"
 
-
 #define START_DEMO_COUNTDOWN 150  /* Some time unit.. not sure yet :) */
 
 int title(void)
@@ -120,7 +120,7 @@
   SDL_BlitSurface(images[IMG_NBS], NULL, screen, &dest);
 
 
-  if (game_options->demo_mode)
+  if (Opts_DemoMode())
   {
     dest.x = (screen->w - images[IMG_DEMO_SMALL]->w) / 2;
     dest.y = (screen->h - images[IMG_DEMO_SMALL]->h);
@@ -294,7 +294,7 @@
 
       /* Handle demo countdown: */
 
-      if (game_options->demo_mode)
+      if (Opts_DemoMode())
       {
 	demo_countdown--;
 

Modified: tuxmath/trunk/src/tuxmath.c
===================================================================
--- tuxmath/trunk/src/tuxmath.c	2006-10-17 20:36:09 UTC (rev 54)
+++ tuxmath/trunk/src/tuxmath.c	2006-10-30 16:44:31 UTC (rev 55)
@@ -28,7 +28,6 @@
 
 
 /* global data: */
-game_option_type* game_options; /* used by setup.c, options.c, game.c */
 
 int main(int argc, char * argv[])
 {

Modified: tuxmath/trunk/src/tuxmath.h
===================================================================
--- tuxmath/trunk/src/tuxmath.h	2006-10-17 20:36:09 UTC (rev 54)
+++ tuxmath/trunk/src/tuxmath.h	2006-10-30 16:44:31 UTC (rev 55)
@@ -34,9 +34,14 @@
 
 //#define TUXMATH_VERSION 0.98 This is now done by autoheader and configure.in
 
+/* Maximum length of file path: */
 #define PATH_MAX 4096
 
-/* default values for game_options */
+/* Error code if game_options not valid: */
+#define GAME_OPTS_INVALID 9999
+
+/* Default values for game_options */
+/* They can be changed in the struct to other values at run-time */
 #define DEFAULT_PER_USER_CONFIG 1
 #define DEFAULT_USE_SOUND 1
 #define DEFAULT_FULLSCREEN 1
@@ -53,54 +58,27 @@
 #define DEFAULT_EXTRA_COMETS_PER_WAVE 2
 #define DEFAULT_MAX_COMETS 10
 #define DEFAULT_SAVE_SUMMARY 1	
-#define DEFAULT_SOUND_AVAILABLE 1
-#define DEFAULT_NUM_CITIES 4   /* MUST BE AN EVEN NUMBER! */
-#define DEFAULT_NUM_BKGDS 5
-#define DEFAULT_MAX_CITY_COLORS 4
+#define DEFAULT_SOUND_HW_AVAILABLE 1
 #define DEFAULT_USE_FEEDBACK 0
 #define DEFAULT_DANGER_LEVEL 0.35
 #define DEFAULT_DANGER_LEVEL_SPEEDUP 1.1
 #define DEFAULT_DANGER_LEVEL_MAX 0.9
 #define DEFAULT_CITY_EXPL_HANDICAP 0
 
+/* These values are hard-coded and used 'as is' by the program */
+/* (i.e. these behaviors require recompilation to change)   */ 
+#define DEFAULT_NUM_CITIES 4   /* MUST BE AN EVEN NUMBER! */
+#define DEFAULT_NUM_BKGDS 5
+#define DEFAULT_MAX_CITY_COLORS 4
+
 #define MINIMUM_SPEED 0.1
+#define MAX_MAX_SPEED 20.0
+#define MIN_SPEEDUP_FACTOR 0.5
+#define MAX_SPEEDUP_FACTOR 2.0
+#define MIN_COMETS 1
+#define MAX_MAX_COMETS 100
 
-/* this struct contains all options regarding general       */
-/* gameplay but not having to do with math questions per se */
-typedef struct game_option_type {
-  /* general game options */
-  int per_user_config;
-  int use_sound;
-  int fullscreen;
-  int use_bkgd;
-  int demo_mode;
-  int oper_override;
-  int use_keypad;
-  float speed;
-  int allow_speedup;
-  float speedup_factor;
-  float max_speed;
-  int slow_after_wrong;
-  int starting_comets;
-  int extra_comets_per_wave;
-  int max_comets;  
-  char next_mission[PATH_MAX];
-  int save_summary;
-  int use_feedback;
-  float danger_level;
-  float danger_level_speedup;
-  float danger_level_max;
-  float city_expl_handicap;
 
-  /* whether sound system is successfully initialized and sound files loaded: */
-  /* this flag is set by the program, not the user, and is not in the config file. */
-  int sound_available;
-  /* not sure the rest of these belong in here */
-  int num_cities;  /* MUST BE AN EVEN NUMBER! */
-  int num_bkgds;
-  int max_city_colors;
-} game_option_type;
-
 typedef struct range_type {
   int min;
   int max;
@@ -123,7 +101,6 @@
 
 
 /* Global data gets 'externed' here: */
-extern game_option_type* game_options; /* used by setup.c, options.c, game.c */
 
 extern SDL_Surface* screen; /* declared in setup.c; also used in game.c, options.c, fileops.c, credits.c, title.c */
 extern SDL_Surface* images[];    /* declared in setup.c, used in same files as screen */




More information about the Tux4kids-commits mailing list