[Tux4kids-commits] r11 - in tuxmath/trunk: . data/images/comets data/images/status data/images/tux docs src

dbruce at alioth.debian.org dbruce at alioth.debian.org
Thu Mar 8 20:59:02 CET 2007


Author: dbruce
Date: 2006-06-12 20:14:08 +0000 (Mon, 12 Jun 2006)
New Revision: 11

Added:
   tuxmath/trunk/data/images/comets/mini_comet1.png
   tuxmath/trunk/data/images/comets/mini_comet2.png
   tuxmath/trunk/data/images/comets/mini_comet3.png
   tuxmath/trunk/data/images/status/gameover_won.png
   tuxmath/trunk/data/images/status/nums.png
   tuxmath/trunk/data/images/tux/console_led.png
   tuxmath/trunk/data/images/tux/tux-egypt3.png
   tuxmath/trunk/data/images/tux/tux-egypt4.png
Removed:
   tuxmath/trunk/data/images/status/nums.png
Modified:
   tuxmath/trunk/Makefile
   tuxmath/trunk/docs/CHANGES.txt
   tuxmath/trunk/docs/README.txt
   tuxmath/trunk/src/game.c
   tuxmath/trunk/src/images.h
   tuxmath/trunk/src/mathcards.c
   tuxmath/trunk/src/mathcards.h
   tuxmath/trunk/src/setup.c
   tuxmath/trunk/src/tuxmath.h
Log:
added question formats, question counter, victory screen


Modified: tuxmath/trunk/Makefile
===================================================================
--- tuxmath/trunk/Makefile	2006-05-16 17:05:20 UTC (rev 10)
+++ tuxmath/trunk/Makefile	2006-06-12 20:14:08 UTC (rev 11)
@@ -5,9 +5,12 @@
 # bill at newbreedsoftware.com
 # http://www.newbreedsoftware.com/tuxmath/
 
-# 2001.Aug.26 - 2005.Jan.03
+# Modified by David Bruce
+# dbruce at tampabay.rr.com
 
+# 2001.Aug.26 - 2006.Jun.12
 
+
 CFLAGS=-Wall -g $(SDL_CFLAGS) -DDATA_PREFIX=\"$(DATA_PREFIX)\" -DDEBUG \
 	-DVERSION=\"$(VERSION)\" -D$(SOUND)SOUND
 
@@ -27,7 +30,7 @@
 OWNER=$(shell if `groups root | grep root > /dev/null` ; then echo root:root ; else echo root:wheel ; fi)
 
 
-VERSION=2005.01.03
+VERSION=2006.06.12
 
 all:	tuxmath
 

Added: tuxmath/trunk/data/images/comets/mini_comet1.png
===================================================================
(Binary files differ)


Property changes on: tuxmath/trunk/data/images/comets/mini_comet1.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: tuxmath/trunk/data/images/comets/mini_comet2.png
===================================================================
(Binary files differ)


Property changes on: tuxmath/trunk/data/images/comets/mini_comet2.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: tuxmath/trunk/data/images/comets/mini_comet3.png
===================================================================
(Binary files differ)


Property changes on: tuxmath/trunk/data/images/comets/mini_comet3.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: tuxmath/trunk/data/images/status/gameover_won.png
===================================================================
(Binary files differ)


Property changes on: tuxmath/trunk/data/images/status/gameover_won.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Deleted: tuxmath/trunk/data/images/status/nums.png
===================================================================
(Binary files differ)

Added: tuxmath/trunk/data/images/status/nums.png
===================================================================
(Binary files differ)


Property changes on: tuxmath/trunk/data/images/status/nums.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: tuxmath/trunk/data/images/tux/console_led.png
===================================================================
(Binary files differ)


Property changes on: tuxmath/trunk/data/images/tux/console_led.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: tuxmath/trunk/data/images/tux/tux-egypt3.png
===================================================================
(Binary files differ)


Property changes on: tuxmath/trunk/data/images/tux/tux-egypt3.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: tuxmath/trunk/data/images/tux/tux-egypt4.png
===================================================================
(Binary files differ)


Property changes on: tuxmath/trunk/data/images/tux/tux-egypt4.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: tuxmath/trunk/docs/CHANGES.txt
===================================================================
--- tuxmath/trunk/docs/CHANGES.txt	2006-05-16 17:05:20 UTC (rev 10)
+++ tuxmath/trunk/docs/CHANGES.txt	2006-06-12 20:14:08 UTC (rev 11)
@@ -1,5 +1,24 @@
 CHANGES.txt for "tuxmath"
 
+2006.Jun.12 (https://svn.tux4kids.net/tuxmath/ - revision 9)
+  Game:
+    * Command-line argument added to allow ending the game with
+      "victory" when all questions in the defined list have been
+      successfully answered.
+    * Counter of remaining questions added to upper center of screen
+      when operating in "defined list" mode.
+    * LED numbers now display in "monitor" added to Tux's console
+      when "defined list" mode selected".
+    * Drawing of math question formulas overhauled, with support
+      for display of negatives (e.g. 2 x -3 = ?). The program supports
+      negative numbers for limits of question ranges, but for now
+      this must be selected at compile time.
+    * Support for questions formatted like ? + 2 = 4 and 2 + ? = 4, 
+      in addition to default format (2 + 2 = ?).
+    * Command-line options to select from the three question formats.
+
+      David Bruce <dbruce at tampabay.rr.com>
+
 2006.May.16 (https://svn.tux4kids.net/tuxmath/ - revision 8)
   Code:
     * Major changes to internal workings of program. Everything 

Modified: tuxmath/trunk/docs/README.txt
===================================================================
--- tuxmath/trunk/docs/README.txt	2006-05-16 17:05:20 UTC (rev 10)
+++ tuxmath/trunk/docs/README.txt	2006-06-12 20:14:08 UTC (rev 11)
@@ -2,7 +2,7 @@
 An educational math tutorial game starring Tux, the Linux Penguin
 -----------------------------------------------------------------
 
-February 21, 2003
+May 18, 2006
 
 
 Objective
@@ -50,7 +50,21 @@
   --------------------
     The following command-line options can be sent to the program.
 
-      --fullscreen    -  Run the game in full screen, instead of in a window,
+     --norepeats      -  Game consists of working through a list of questions
+      -r                 generated based on the selected options (or defaults).
+                         If a comet strikes a city without being shot down by
+                         the player, the question is reinserted into the list
+                         in a random location. If the player answers all questions
+                         correctly before the cities are destroyed, he/she wins.
+                         If all cities get destroyed, the game ends in defeat.
+
+     --answersfirst   -  to ask questions in format: ? + num2 = num3 instead of 
+                         default format: num1 + num2 = ?.
+
+     --answersmiddle  -  to ask questions in format: num1 + ? = num3 instead of
+                         default format: num1 + num2 = ?.
+
+     --fullscreen     -  Run the game in full screen, instead of in a window,
       -f                 if possible.
 
       --nosound       -  Do not play any sounds or music.
@@ -123,7 +137,7 @@
   --------------
     On this screen, you can select some of the gameplay options or return to 
     the Title Screen.  Currently, the four math operations can be enabled
-    or disenabled, as well as the speed setting and ranges of numbers to use. 
+    or disabled, as well as the speed setting and ranges of numbers to use. 
 
     Use the [UP] and [DOWN] arrow keys to select what you wish to do,
     and then press [ENTER / RETURN /SPACEBAR].  Or, use the mouse to click the
@@ -151,10 +165,13 @@
     To destroy it:
     --------------
       First, figure out the answer to the equation.
-      For example, "3 x 4" would be "12"
+      For example, "3 x 4 = ?" would be "12"
 
       Second, type in the answer.  As you type numbers on the keyboard, they
       will appear in the "LED"-style display at the top center of the screen.
+      If negative answers are enabled, there will be a fourth place in the
+      LED display for the minus sign.  The '-' and '+' keys will toggle the
+      minus sign on and off, respectively.
 
       Finally, press [ENTER / RETURN].
 
@@ -199,9 +216,22 @@
     destroyed.  If the city is hit by another comet, it will be
     completely destroyed.
 
-    Once you lose all of your cities, the game will end.
+  Ending The Game
+  ---------------
+    By default, the game operates in an arcade-style manner, continuing
+    until you lose all of your cities.  A GAME OVER screen is displayed.
+    By pressing any key or clicking the mouse, you return to the title
+    screen.
 
+    It is now possible to play through a defined list of questions. This
+    mode is selected via the "--norepeats" command line argument. By
+    default, the questions are asked in a random order.  If answered
+    correctly, they are removed.  A question that is not answered correctly
+    (allowing the comet to destroy its target) will reappear in random
+    order.  If all questions are successfully answered before the cities
+    have been destroyed, the player wins and a "victory" screen is displayed.
 
+
   Regaining Cities
   ----------------
     [ Rules will go here ]
@@ -215,9 +245,32 @@
 Setting Game Options
 --------------------
   [ UNDER CONSTRUCTION ]
+  This is still under construction, but many things can be set.  For now,
+  there are three ways to set game options.
 
+  1. Many command-line options are supported (see above).
 
+  2. The "Options" screen allows several parameters to be set at run-time,
+  or reset between individual games while the program is still running.
+  Currently supported settings include the math operations to be used for
+  questions, the starting speed, the maximum value of answers (for division
+  questions, this is the maximum size of the dividend, not actually the 
+  answer), and ranges of numbers to be used to generate questions.
 
+  3. Editing the default values in tuxmath.h and mathcards.h and recompiling.
+  The default settings for general game options are contained in tuxmath.h, and
+  the defaults for math question settings are in mathcards.h.  Very fine-grained
+  control over game behavior is offered, but this isn't exactly a user-friendly
+  method of controlling the program.
+
+  Two main improvements are planned.  First, the program should read
+  and write the settings to disk in a human-readable fashion, where they
+  could be modified with a text editor.  This also would allow creation of
+  a series of "lessons" that could be played in a planned order.
+  Second, the "Options" screen needs to be overhauled to give access to all
+  settings from within the program.
+
+
 Setting Administrative Options
 ------------------------------
   "Tux, of Math Command" allows parents/teachers to adjust which parts
@@ -231,7 +284,7 @@
   On the other hand, you may wish to lock-in the other three kinds
   of equations, so that the players cannot disable any of them.
   All games will always have addition, subtraction and multiplication
-  problems, but will never had division problems.
+  problems, but will never have division problems.
 
   [ UNDER CONSTRUCTION ]
 
@@ -260,3 +313,6 @@
 
   The GIMP
     http://www.gimp.org/
+
+  KDevelop
+    http://www.kdevelop.org/

Modified: tuxmath/trunk/src/game.c
===================================================================
--- tuxmath/trunk/src/game.c	2006-05-16 17:05:20 UTC (rev 10)
+++ tuxmath/trunk/src/game.c	2006-06-12 20:14:08 UTC (rev 11)
@@ -60,13 +60,13 @@
 
 
 #define ANSWER_LEN 5
-#define FORMULA_LEN 8
+#define FORMULA_LEN 14
+
 typedef struct comet_type {
   int alive;
   int expl;
   int city;
   float x, y;
-  int eq1, oper, eq2;
   char formula[FORMULA_LEN];
   int answer;
   char answer_str[ANSWER_LEN];
@@ -75,9 +75,7 @@
 
 /* Local (to game.c) 'globals': */
 
-static int quit;
-static int done;
-static int gameover;
+//static int gameover;
 static int game_status;
 static int SDL_quit_received;
 static int escape_received;
@@ -86,6 +84,7 @@
 static int score;
 static int pre_wave_score;
 static int num_attackers;
+static float speed;
 static int demo_countdown;
 static int tux_anim;
 static int tux_anim_frame;
@@ -100,8 +99,6 @@
 static int level_start_wait;
 static int last_bkgd;
 
-static  Uint32 last_time, now_time;
-
 static int digits[3];
 static comet_type comets[MAX_COMETS];
 static city_type cities[NUM_CITIES];
@@ -119,38 +116,41 @@
 static void game_handle_cities(void);
 static void game_draw(void);
 static int check_exit_conditions(void);
-static void print_exit_conditions(void);
 
+static void draw_numbers(char* str, int x, int y);
+static void draw_led_nums(void);
+static void draw_question_counter(void);
+static void draw_console_image(int i);
+static void draw_line(int x1, int y1, int x2, int y2, int r, int g, int b);
+static void putpixel(SDL_Surface * surface, int x, int y, Uint32 pixel);
+
 static void reset_level(void);
 static int add_comet(void);
-static void draw_numbers(char* str, int x);
 static int  pause_game(void);
-static void draw_line(int x1, int y1, int x2, int y2, int r, int g, int b);
-static void putpixel(SDL_Surface * surface, int x, int y, Uint32 pixel);
-static void draw_console_image(int i);
 static void add_score(int inc);
-static int  pick_operand(int min);
-static int  in_range(int n);
 static void reset_comets(void);
 
-static void draw_led_nums(void);
 static void game_mouse_event(SDL_Event event);
 static void game_key_event(SDLKey key);
 
+#ifdef TUXMATH_DEBUG
+static void print_exit_conditions(void);
+#endif
+
 /* --- MAIN GAME FUNCTION!!! --- */
 
 
 int game(void)
 {
+  Uint32 last_time, now_time;
 
    /* most code moved into smaller functions (game_*()): */
   if (!game_initialize())
   {
     printf("\ngame_initialize() failed!");
     fprintf(stderr, "\ngame_initialze() failed!");
-    done = 1;
-    return 0;
-    /*exit(1);*/    
+    /* return 1 so program exits: */
+    return 1;
   } 
 
   /* --- MAIN GAME LOOP: --- */ 
@@ -162,46 +162,34 @@
     old_tux_img = tux_img;
     tux_pressing = 0;
 
-    game_handle_user_events();
-     
-    if (doing_answer)
-    {
-      game_handle_answer();
-    }
-
     if (laser.alive > 0)
     {
       laser.alive--;
-    }      
+    }   
 
-    if (level_start_wait > 0)
-    {
-      game_countdown();
-    }
-     
+    /* Most code now in smaller functions: */
+    game_handle_user_events();
+    game_handle_answer();
+    game_countdown();
     game_handle_tux();
     game_handle_comets();
     game_handle_cities();
+    game_handle_demo(); 
+    game_draw();
+    /* figure out if we should leave loop: */
+    game_status = check_exit_conditions(); 
 
-
-    if (game_options->demo_mode)
-    {
-      game_handle_demo(); 
-    }     
-    /* drawing code moved into own function: */
-    game_draw();
-    
    
     /* If we're in "PAUSE" mode, pause! */
     if (paused)
     {
-      /*quit = */pause_game();
+      pause_game();
       paused = 0;
     }
       
       /* Keep playing music: */
       
-#ifndef NOSOUND
+    #ifndef NOSOUND
     if (game_options->use_sound)
     {
       if (!Mix_PlayingMusic())
@@ -209,9 +197,7 @@
 	    Mix_PlayMusic(musics[MUS_GAME + (rand() % 3)], 0);
       }  
     }
-#endif
-    /* figure out if we should leave loop: */
-    game_status = check_exit_conditions(); 
+    #endif
  
     /* Pause (keep frame-rate event) */
     now_time = SDL_GetTicks();
@@ -223,18 +209,90 @@
   while(GAME_IN_PROGRESS == game_status);
   /* END OF MAIN GAME LOOP! */
 
- #ifdef TUXMATH_DEBUG
-   print_exit_conditions();
+  #ifdef TUXMATH_DEBUG
+  print_exit_conditions();
   #endif
 
-  /* TODO: handle various end of game scenarios based on value of game_status */
+  /* 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;
+    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++;
+        last_time = SDL_GetTicks();
+
+        while (SDL_PollEvent(&event) > 0)
+        {
+          if  (event.type == SDL_QUIT
+            || event.type == SDL_KEYDOWN
+            || event.type == SDL_MOUSEBUTTONDOWN)
+          {
+            looping = 0;
+          }   
+        }
+        if (bkgd)
+          SDL_BlitSurface(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_LED);
+        /* 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);
+
+        now_time = SDL_GetTicks();
+
+        if (now_time < last_time + FPS)
+	  SDL_Delay(last_time + FPS - now_time);
+      }
+      while (looping);
       break;
     }
 
@@ -247,9 +305,18 @@
     case GAME_OVER_LOST: 
     case GAME_OVER_OTHER:
     {
-      gameover = 1;
+      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++;
+        last_time = SDL_GetTicks();
 
         while (SDL_PollEvent(&event) > 0)
         {
@@ -257,16 +324,11 @@
             || event.type == SDL_KEYDOWN
             || event.type == SDL_MOUSEBUTTONDOWN)
           {
-            gameover = 0;
+            looping = 0;
           }   
         }
 
-        dest.x = (screen->w - images[IMG_GAMEOVER]->w) / 2;
-        dest.y = (screen->h - images[IMG_GAMEOVER]->h) / 2;
-        dest.w = images[IMG_GAMEOVER]->w;
-        dest.h = images[IMG_GAMEOVER]->h;
-	
-        SDL_BlitSurface(images[IMG_GAMEOVER], NULL, screen, &dest);
+        SDL_BlitSurface(images[IMG_GAMEOVER], NULL, screen, &dest_message);
         SDL_Flip(screen);
 
         now_time = SDL_GetTicks();
@@ -274,7 +336,7 @@
         if (now_time < last_time + FPS)
 	  SDL_Delay(last_time + FPS - now_time);     
       }
-      while (gameover);
+      while (looping);
 
       break;
     }
@@ -309,7 +371,16 @@
 #endif
   
   /* Return the chosen command: */
-  return quit;
+  if (GAME_OVER_WINDOW_CLOSE == game_status) 
+  {
+    /* program exits: */
+    return 1;
+  }
+  else
+  {
+    /* return to title() screen: */
+    return 0;
+  }
 }
 
 
@@ -322,32 +393,28 @@
   SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
   SDL_Flip(screen);
 
-  /* FIXME done and quit will be superseded by game_status */
-  done = 0;
-  quit = 0;
-  
   game_status = GAME_IN_PROGRESS;  
   SDL_quit_received = 0;
   escape_received = 0;
 
   /* Start MathCards backend: */
   /* FIXME may need to move this into tuxmath.c to accomodate option */
-  /* to us MC_StartUsingWrongs() */
+  /* to use MC_StartUsingWrongs() */
   if (!MC_StartGame())
   {
+    #ifdef TUXMATH_DEBUG
     printf("\nMC_StartGame() failed!");
+    #endif
     fprintf(stderr, "\nMC_StartGame() failed!");
-    done = 1;
     return 0;
-    /*exit(1);*/
   }  
   
   /* Prepare to start the game: */
   
   wave = 1;
   num_attackers = 2;
+  speed = game_options->speed;
   score = 0;
-  gameover = 0;
   demo_countdown = 1000;
   level_start_wait = LEVEL_START_WAIT_START;
   neg_answer_picked = 0;
@@ -355,32 +422,29 @@
   /* (Create and position cities) */
   
   for (i = 0; i < NUM_CITIES; i++)
+  {
+    cities[i].alive = 1;
+    cities[i].expl = 0;
+    cities[i].shields = 1;
+     
+    /* Left vs. Right - makes room for Tux and the console */
+    if (i < NUM_CITIES / 2)
     {
-      cities[i].alive = 1;
-      cities[i].expl = 0;
-      cities[i].shields = 1;
-     
-
-      /* 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_CITY_BLUE] -> w) / 2));
-	}
-      else
-	{
-	  cities[i].x = (screen->w -
-			 ((((screen->w / (NUM_CITIES + 1)) *
-			    (i - (NUM_CITIES / 2)) +
-			    ((images[IMG_CITY_BLUE] -> w) / 2)))));
-	}
+      cities[i].x = (((screen->w / (NUM_CITIES + 1)) * i) +
+                     ((images[IMG_CITY_BLUE] -> w) / 2));
     }
+    else
+    {
+      cities[i].x = (screen->w -
+                 ((((screen->w / (NUM_CITIES + 1)) *
+                    (i - (NUM_CITIES / 2)) +
+                   ((images[IMG_CITY_BLUE] -> w) / 2)))));
+    }
+  }
 
   num_cities_alive = NUM_CITIES;
   num_comets_alive = 0;
 
-
   /* (Clear laser) */
   laser.alive = 0;
   
@@ -412,10 +476,6 @@
     if (event.type == SDL_QUIT)
     {
       SDL_quit_received = 1;
-      /* FIXME quit and done flags will be superseded */
-      /* Window close event - quit! */
-      quit = 1;
-      done = 1;
     }
     else if (event.type == SDL_KEYDOWN)
     {
@@ -431,6 +491,12 @@
 
 void game_handle_demo(void)
 {
+  /* If not in demo mode get out: */
+  if (!game_options->demo_mode)
+  {
+    return;
+  }
+
   /* Demo mode! */
   int demo_answer, answer_digit;
   static int picked_comet;
@@ -497,15 +563,18 @@
 
   /* Count down counter: */
   demo_countdown--;
-  if (demo_countdown <= 0 || num_cities_alive == 0)
-    done = 1;
 }
 
-/* FIXME need to end game if no more questions left */
+
 void game_handle_answer(void)
 {
   int i, num, lowest, lowest_y;
 
+  if (!doing_answer)
+  {
+    return;
+  }
+
   doing_answer = 0;
 
   num = (digits[0] * 100 +
@@ -565,7 +634,7 @@
 
     /* [ add = 25, sub = 50, mul = 75, div = 100 ] */
     /* [ the higher the better ] */
-    add_score(((25 * (comets[lowest].oper + 1)) *
+    add_score(((25 * (comets[lowest].flashcard.operation + 1)) *
               (screen->h - comets[lowest].y + 1)) /
 	       screen->h);
   }
@@ -595,6 +664,9 @@
 
 void game_countdown(void)
 {
+  if (level_start_wait <= 0)
+    return;
+
   level_start_wait--;
   if (level_start_wait > LEVEL_START_WAIT_START / 4)
     tux_img = IMG_TUX_RELAX1;
@@ -661,23 +733,20 @@
       num_comets_alive++;
       /* update comet position */
       comets[i].x = comets[i].x + 0; /* no lateral motion for now! */
-      comets[i].y = comets[i].y + (game_options->speed);
+      comets[i].y = comets[i].y + (speed);
 	      
       if (comets[i].y >= (screen->h - images[IMG_CITY_BLUE]->h) &&
 	  comets[i].expl < COMET_EXPL_END)
       {
-        printf("\nAbout to disable shields or destroy city!\n");
         /* Disable shields or destroy city: */
         MC_AnsweredIncorrectly(&(comets[i].flashcard));
         if (cities[comets[i].city].shields)
 	{
-          printf("\nDisabling shields!\n");
 	  cities[comets[i].city].shields = 0;
 	  playsound(SND_SHIELDSDOWN);
 	}
         else
         {
-          printf("\nDestroying city!\n");
           cities[comets[i].city].expl = CITY_EXPL_START;
           playsound(SND_EXPLOSION);
         }
@@ -701,8 +770,7 @@
 
   /* add more comets if needed: */
   if (level_start_wait == 0 &&
-      (frame % 20) == 0 &&
-      gameover == 0)
+      (frame % 20) == 0)
   {
     /* num_attackers is how many comets are left in wave */
     if (num_attackers > 0)
@@ -720,29 +788,18 @@
       if (num_comets_alive == 0)
       {
         /* Time for the next wave! */
-
-	/* FIXME: End of level stuff goes here */
-        /* FIXME this belongs in game_handle_cities(), I think */
-        if (num_cities_alive > 0)
-	{
-          /* Go on to the next wave: */
 	  wave++;
 	  reset_level();
-	}
-	else
-	{
-          /* No more cities!  Game over! */
-          gameover = GAMEOVER_COUNTER_START;
-	}
       }
     }
   }
 }
 
+
+
 void game_handle_cities(void)
 {
   int i;
-  /* FIXME does the following variable do anything? */
   num_cities_alive = 0;
 
   for (i = 0; i < NUM_CITIES; i++)
@@ -761,6 +818,8 @@
   }
 }
 
+
+/* FIXME consider splitting this into smaller functions e.g. draw_comets(), etc. */
 void game_draw(void)
 {
   int i,j, img;
@@ -805,6 +864,13 @@
     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_RecycleCorrects())
+  {
+    draw_question_counter();
+  }
+
   /* Draw wave: */
   dest.x = 0;
   dest.y = 0;
@@ -814,7 +880,7 @@
   SDL_BlitSurface(images[IMG_WAVE], NULL, screen, &dest);
 
   sprintf(str, "%d", wave);
-  draw_numbers(str, images[IMG_WAVE]->w + (images[IMG_NUMBERS]->w / 10));
+  draw_numbers(str, images[IMG_WAVE]->w + (images[IMG_NUMBERS]->w / 10), 0);
 
   /* Draw score: */
   dest.x = (screen->w - ((images[IMG_NUMBERS]->w / 10) * 7) -
@@ -826,7 +892,7 @@
   SDL_BlitSurface(images[IMG_SCORE], NULL, screen, &dest);
       
   sprintf(str, "%.6d", score);
-  draw_numbers(str, screen->w - ((images[IMG_NUMBERS]->w / 10) * 6));
+  draw_numbers(str, screen->w - ((images[IMG_NUMBERS]->w / 10) * 6), 0);
       
   /* Draw cities: */
   for (i = 0; i < NUM_CITIES; i++)
@@ -920,8 +986,8 @@
   if (laser.alive)
   {
     draw_line(laser.x1, laser.y1, laser.x2, laser.y2,
-		  255 / (LASER_START - laser.alive),
-		  192 / (LASER_START - laser.alive),
+		  255 / ((LASER_START + 1) - laser.alive),
+		  192 / ((LASER_START + 1) - laser.alive),
 		  64);
   }
 
@@ -950,28 +1016,11 @@
   }
 
   /* Draw console & tux: */
-  /* FIXME add counter for remaining questions */
-  draw_console_image(IMG_CONSOLE);
-
-  if (gameover > 0)
-  {
-    tux_img = IMG_TUX_FIST1 + ((frame / 2) % 2);
-  }
-  draw_console_image(tux_img);
-
   /* LED code moved into separate function by DSB */
+  /* this also draws the console                   */
   draw_led_nums();
 
-  /* Draw "Game Over" */
-  if (gameover > 0)
-  {
-    dest.x = (screen->w - images[IMG_GAMEOVER]->w) / 2;
-    dest.y = (screen->h - images[IMG_GAMEOVER]->h) / 2;
-    dest.w = images[IMG_GAMEOVER]->w;
-    dest.h = images[IMG_GAMEOVER]->h;
-	
-    SDL_BlitSurface(images[IMG_GAMEOVER], NULL, screen, &dest);
-   }
+  draw_console_image(tux_img);
  
   /* Swap buffers: */
   SDL_Flip(screen);
@@ -990,24 +1039,11 @@
   }
 
   /* determine if game lost (i.e. all cities blown up): */
+  if (!num_cities_alive)
   {
-    int i;
-    int surviving_cities = 0;
-
-    for (i = 0; i < NUM_CITIES; i++)
-    {
-      if (cities[i].alive)
-      {
-        surviving_cities++;
-      }
-    }
-
-    if (!surviving_cities)
-    {
-      return GAME_OVER_LOST;
-    }
+    return GAME_OVER_LOST;
   }
-
+  
   /* determine if game won (i.e. all questions in mission answered correctly): */
   if (MC_MissionAccomplished())
   {
@@ -1016,38 +1052,35 @@
 
   /* Could have situation where mathcards doesn't have more questions */
   /* even though not all questions answered correctly:                */
-  if (MC_GameOver())
+  if (!MC_TotalQuestionsLeft())
   {
     return GAME_OVER_OTHER;
   }
 
-  /* Need to get out if no comets alive and MathCards out of unanswered questions, */
+  /* 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 (!MC_ListQuestionsLeft() && !num_comets_alive)
   {
-//     int i;
-//     int living_comets = 0;
-// 
-//     for (i = 0; i < MAX_COMETS; i++)
-//     {
-//       living_comets += comets[i].alive;
-//     }
-
-    if (MC_NoQuestionsLeft() && !num_comets_alive)
-    {
-      #ifdef TUXMATH_DEBUG
-      printf("\nNoQuestionsLeft() = %d", MC_NoQuestionsLeft());
-      printf("\nnum_comets_alive = %d", num_comets_alive);
-      #endif 
-      return GAME_OVER_ERROR;
-    }
+    #ifdef TUXMATH_DEBUG
+    printf("\nListQuestionsLeft() = %d", MC_ListQuestionsLeft());
+    printf("\nnum_comets_alive = %d", num_comets_alive);
+    #endif 
+    return GAME_OVER_ERROR;
   }
+  
+  /* If using demo mode, see if counter has run out: */ 
+  if (game_options->demo_mode)
+  {
+    if (demo_countdown <= 0 )
+      return GAME_OVER_OTHER;
+  }
 
   /* if we made it to here, the game goes on! */
   return GAME_IN_PROGRESS;
 }
 
+#ifdef TUXMATH_DEBUG
 void print_exit_conditions(void)
 {
   printf("\ngame_status:\t");
@@ -1096,6 +1129,7 @@
     }
   }
 }
+#endif
 
 /* Reset stuff for the next level! */
 void reset_level(void)
@@ -1164,11 +1198,11 @@
   if (game_options->allow_speedup)
   {
     num_attackers = wave * game_options->extra_comets;
-    game_options->speed = (game_options->speed) * game_options->speedup_factor;
+    speed = speed * game_options->speedup_factor;
 
-    if (game_options->speed > game_options->max_speed)
+    if (speed > game_options->max_speed)
     {
-      game_options->speed = game_options->max_speed;
+      speed = game_options->max_speed;
     } 
   }
   else
@@ -1180,151 +1214,219 @@
 
 
 /* Add a comet to the game (if there's room): */
-
 int add_comet(void)
 {
   static int prev_city = -1;
   int i, found;
-  
+  float y_spacing;
 
-  /* Look for a free comet slot: */
-  
+  /* Look for a free comet slot and see if all live comets are far */
+  /* enough down to avoid overlap and keep formulas legible:       */
   found = -1;
-  
+  y_spacing = (images[IMG_NUMS]->h) * 1.5;
+
   for (i = 0; i < MAX_COMETS && found == -1; i++)
   {
-    if (comets[i].alive == 0)
+    if (comets[i].alive)
     {
+      if (comets[i].y < y_spacing)
+      {
+        /* previous comet too high up to create another one yet: */
+        return 0;
+      }
+    }
+    else  /* non-living comet so we found a free slot: */
+    {
       found = i;
     }
   }
   
+  if (-1 == found)
+  {
+    /* free comet slot not found - no comet added: */
+    return 0;
+  }
+
   
-  if (found != -1)
+  /* Get math question for new comet - the following function fills in */
+  /* the flashcard struct that is part of the comet struct:            */
+  if (!MC_NextQuestion(&(comets[found].flashcard)))
   {
-    /* Get math question for new comet: */
-    if (!MC_NextQuestion(&(comets[found].flashcard)))
-    /* no more questions - cannot create comet.  */ 
+    /* no more questions available - cannot create comet.  */ 
+    return 0;
+  }
+
+  /* If we make it to here, create a new comet!                  */
+
+  /* The answer may be num1, num2, or num3, depending on format. */
+  /* Also, the formula string needs to be set accordingly:       */
+  switch (comets[found].flashcard.format)
+  {
+    case MC_FORMAT_ANS_LAST:  /* e.g. num1 + num2 = ? */
     {
-      return 0;
+      comets[found].answer = comets[found].flashcard.num3;
+
+      snprintf(comets[found].formula, FORMULA_LEN,"%d %c %d = ?",
+	       comets[found].flashcard.num1,
+	       operchars[comets[found].flashcard.operation],
+	       comets[found].flashcard.num2);
+      break;
     }
 
-    /* FIXME streamline comet struct - for now assign to old variables */
-    /* FIXME also need to handle question formats */
-    comets[found].eq1 = comets[found].flashcard.num1;
-    comets[found].oper = comets[found].flashcard.operation;
-    comets[found].eq2 = comets[found].flashcard.num2;
-    comets[found].answer = comets[found].flashcard.num3;
+    case MC_FORMAT_ANS_MIDDLE:  /* e.g. num1 + ? = num3 */
+    {
+      comets[found].answer = comets[found].flashcard.num2;
 
-    comets[found].alive = 1;
-    num_comets_alive++;      
+      snprintf(comets[found].formula, FORMULA_LEN,"%d %c ? = %d",
+	       comets[found].flashcard.num1,
+	       operchars[comets[found].flashcard.operation],
+	       comets[found].flashcard.num3);
+      break;
+    }
 
-    /* Pick a city to attack that was not attacked last time */
-    /* (so formulas are less likely to overlap). */
-    do 
+    case MC_FORMAT_ANS_FIRST:  /* e.g. ? + num2 = num3 */
     {
-      i = rand() % NUM_CITIES;
+      comets[found].answer = comets[found].flashcard.num1;
+
+      snprintf(comets[found].formula, FORMULA_LEN,"? %c %d = %d",
+	       operchars[comets[found].flashcard.operation],
+               comets[found].flashcard.num2,
+               comets[found].flashcard.num3);
+      break;
     }
-    while (i == prev_city);
 
-    prev_city = i;
+    default:  /* should not get to here if MathCards behaves correctly */
+    {
+      #ifdef TUXMATH_DEBUG
+      printf("\nadd_comet() - invalid question format");
+      #endif
+      fprintf(stderr, "\nadd_comet() - invalid question format");
+      return 0;
+    }
+  }
+
+  /* set answer string: */
+  snprintf(comets[found].answer_str, ANSWER_LEN, "%d",
+           comets[found].answer);
+
+
+  comets[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[found].city = i; 
-    /* Start at the top, above the city in question: */
-    comets[found].x = cities[i].x;
-    comets[found].y = 0;
+  /* Set in to attack that city: */
+  comets[found].city = i; 
+  /* Start at the top, above the city in question: */
+  comets[found].x = cities[i].x;
+  comets[found].y = 0;
 
-    snprintf(comets[found].formula, FORMULA_LEN,"%d%c%d",
-	     comets[found].eq1,
-	     operchars[comets[found].oper],
-	     comets[found].eq2);
-    snprintf(comets[found].answer_str, ANSWER_LEN, "%d",
-	     comets[found].answer);
+  /* comet slot found and question found so return successfully: */
+  return 1;
+  
 
-    /* comet slot found and question found so return successfully: */
-    return 1;
-  }
-  /* free comet slot not found - no comet added: */
-  return 0;
 }
 
-
 /* Draw numbers/symbols over the attacker: */
-/* This draw the numbers related to the comets */
+/* This draws the numbers related to the comets */
 void draw_nums(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 / (10 + NUM_OPERS + 2));
+  /* 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 - ((strlen(str) * (images[IMG_NUMS]->w / (10 + NUM_OPERS)))) / 2;
+  cur_x = x - (image_length) / 2;
 
-  if (cur_x < 0)
-    cur_x = 0;
+  /* 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));
 
-  if (cur_x + (strlen(str) * (images[IMG_NUMS]->w / (10 + NUM_OPERS))) >=
-      screen->w)
-    cur_x = ((screen->w) -
-             (strlen(str) * (images[IMG_NUMS]->w / (10 + NUM_OPERS))));
 
-
   /* Draw each character: */
   
-  for (i = 0; i < strlen(str); i++)
-    {
-      c = -1;
+  for (i = 0; i < str_length; i++)
+  {
+    c = -1;
 
 
-      /* Determine which character to display: */
+    /* Determine which character to display: */
       
-      if (str[i] >= '0' && str[i] <= '9')
-	c = str[i] - '0';
-      else
-	{
-	  /* [ THIS COULD CAUSE SLOWNESS... ] */
-		
-	  for (j = 0; j < NUM_OPERS; j++)
-	    {
-	      if (str[i] == operchars[j])
-		{
-		  c = 10 + j;
-		}
-	    }
+    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 < NUM_OPERS; j++)
+      {
+        if (str[i] == operchars[j])
+ 	{
+	  c = 10 + j;
 	}
+      }
+    }
       
-
-      /* Display this character! */
-      
-      if (c != -1)
-	{
-	  src.x = c * (images[IMG_NUMS]->w / (10 + NUM_OPERS));
-	  src.y = 0;
-	  src.w = (images[IMG_NUMS]->w / (10 + NUM_OPERS));
-	  src.h = images[IMG_NUMS]->h;
+    /* 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;
+      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,
+      SDL_BlitSurface(images[IMG_NUMS], &src,
 			  screen, &dest);
-
-
-          /* Move the 'cursor' one character width: */
-
-	  cur_x = cur_x + (images[IMG_NUMS]->w / (10 + NUM_OPERS));
-	}
+      /* 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(char * str, int x)
+void draw_numbers(char * str, int x, int y)
 {
   int i, cur_x, c;
   SDL_Rect src, dest;
@@ -1356,7 +1458,7 @@
 	  src.h = images[IMG_NUMBERS]->h;
 	  
 	  dest.x = cur_x;
-	  dest.y = 0;
+	  dest.y = y;
 	  dest.w = src.w;
 	  dest.h = src.h;
 	  
@@ -1409,7 +1511,6 @@
       else if (event.type == SDL_QUIT)
       {
         SDL_quit_received = 1;
-        /* FIXME quit is being superseded */
  	pause_quit = 1;
       }
     }
@@ -1548,7 +1649,6 @@
 
 
 /* Draw image at lower center of screen: */
-
 void draw_console_image(int i)
 {
   SDL_Rect dest;
@@ -1560,14 +1660,72 @@
 
   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: */
+  questions_left = MC_TotalQuestionsLeft();
+  sprintf(str, "%.4d", questions_left);
+  draw_numbers(str, nums_x, 0);
+}
+
+/* FIXME consider always using new image for simplicity */
+/* FIXME very confusing having this function draw console */
 /* Draw LED digits at the top of the screen: */
 /* Modified by DSB to display minus sign */
-
 void draw_led_nums(void)
 {
   int i;
   SDL_Rect src, dest;
+  int y;
 
+  /* draw either just above console or at top of screen: */
+  if (MC_RecycleCorrects())
+  {
+    /* draw traditional console: */
+    draw_console_image(IMG_CONSOLE);
+    /* LEDs go at top in traditional TuxMath: */
+    y = 4;
+
+  }
+  else
+  {
+    /* draw new console image with "monitor" for LED numbers: */
+    draw_console_image(IMG_CONSOLE_LED);
+    /* draw LED numbers into "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_AllowNegAnswer())
@@ -1591,7 +1749,7 @@
         src.w = (images[IMG_LED_NEG_SIGN]->w) / 2;
         src.h = images[IMG_LED_NEG_SIGN]->h;
 	  
-        dest.y = 4;
+        dest.y = y;
         dest.w = src.w;
         dest.h = src.h;
 	  
@@ -1608,7 +1766,7 @@
       src.h = images[IMG_LEDNUMS]->h;
 	  
       /* dest.x already set */
-      dest.y = 4;
+      dest.y = y;
       dest.w = src.w;
       dest.h = src.h;
 	  
@@ -1658,13 +1816,13 @@
       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) &&
@@ -1788,8 +1946,6 @@
   {
     /* Escape key - quit! */
     escape_received = 1;
-    /* FIXME done will be superseded */
-    done = 1;
   }
   else if (key == SDLK_TAB
         || key == SDLK_p)
@@ -1863,42 +2019,7 @@
 }
 
 
-/* Pick a suitable operand: */
 
-int pick_operand(int min)
-{
-  int i;
-
-  do
-  {
-    i = (rand() % 50) + min;
-  }
-  while (!in_range(i));
-
-  return i;
-}
-
-
-/* Is the value with available operand ranges? */
-
-int in_range(int n)
-{
-  int ok, i;
-  
-  ok = 0;
-  
-  for (i = 0; i < NUM_Q_RANGES && ok == 0; i++)
-  {
-    if (range_enabled[i])
-    {
-      if (n >= ranges[i].min && n <= ranges[i].max)
-	ok = 1;
-    }
-  }
-  
-  return ok;
-}
-
 void reset_comets(void)
 {
   int i =0;
@@ -1909,11 +2030,8 @@
     comets[i].city = 0;
     comets[i].x = 0;
     comets[i].y = 0;
-    comets[i].eq1 = 0;
-    comets[i].oper = 0;
-    comets[i].eq2 = 0;
-    comets[i].formula[FORMULA_LEN] = "";
     comets[i].answer = 0;
-    comets[i].answer_str[ANSWER_LEN] = "";
+    strncpy(comets[i].formula, " ", FORMULA_LEN); 
+    strncpy(comets[i].answer_str, " ", ANSWER_LEN); 
   }
 }

Modified: tuxmath/trunk/src/images.h
===================================================================
--- tuxmath/trunk/src/images.h	2006-05-16 17:05:20 UTC (rev 10)
+++ tuxmath/trunk/src/images.h	2006-06-12 20:14:08 UTC (rev 11)
@@ -88,6 +88,9 @@
   IMG_COMETEX2,
   IMG_COMETEX1,
   COMET_EXPL_START = IMG_COMETEX1,
+  IMG_MINI_COMET1,
+  IMG_MINI_COMET2,
+  IMG_MINI_COMET3,
   IMG_NUMS,
   IMG_LEDNUMS,
   IMG_LED_NEG_SIGN,
@@ -97,12 +100,17 @@
   IMG_KEYPAD,
   IMG_KEYPAD_NO_NEG,
   IMG_CONSOLE,
+  IMG_CONSOLE_LED,
   IMG_TUX_CONSOLE1,
   IMG_TUX_CONSOLE2,
   IMG_TUX_CONSOLE3,
   IMG_TUX_CONSOLE4,
   IMG_TUX_RELAX1,
   IMG_TUX_RELAX2,
+  IMG_TUX_EGYPT1,
+  IMG_TUX_EGYPT2,
+  IMG_TUX_EGYPT3,
+  IMG_TUX_EGYPT4,
   IMG_TUX_DRAT,
   IMG_TUX_YIPE,
   IMG_TUX_YAY1,
@@ -116,6 +124,7 @@
   IMG_SCORE,
   IMG_NUMBERS,
   IMG_GAMEOVER,
+  IMG_GAMEOVER_WON,
   NUM_IMAGES
 };
 

Modified: tuxmath/trunk/src/mathcards.c
===================================================================
--- tuxmath/trunk/src/mathcards.c	2006-05-16 17:05:20 UTC (rev 10)
+++ tuxmath/trunk/src/mathcards.c	2006-06-12 20:14:08 UTC (rev 11)
@@ -36,6 +36,7 @@
 /* to give file scope rather than extern scope.          */
 
 static MC_MathQuestion* generate_list(void);
+static int validate_question(int n1, int n2, int n3);
 static MC_MathQuestion* create_node(int n1, int n2, int op, int ans, int f);
 static MC_MathQuestion* create_node_from_card(MC_FlashCard* card);
 static MC_FlashCard*    create_card_from_node(MC_MathQuestion* node);
@@ -317,7 +318,7 @@
        /* to set up list based on math_opts               */
   {
     #ifdef MC_DEBUG
-    printf("\nNo wrong questions to review!\n");
+    printf("\nNo wrong questions to review - generate list from math_opts\n");
     printf("\nLeaving MC_StartGameUsingWrongs()\n");
     #endif
 
@@ -416,7 +417,7 @@
   #endif
   
   answered_correctly++;
-questions_pending--;
+  questions_pending--;
 
   if (math_opts->recycle_corrects)
   /* reinsert question into question list at random location */
@@ -558,18 +559,18 @@
   }
 }
 
-/*  Returns 1 if no more questions left (either in list   */
-/*  or "in play"                                          */
-int MC_GameOver(void)
+/*  Returns number of questions left (either in list       */
+/*  or "in play")                                          */
+int MC_TotalQuestionsLeft(void)
 {
-  return !unanswered;
+  return unanswered;
 }
 
-/*  Returns 1 if no more questions left in list, NOT    */
+/*  Returns number of questions left in list, NOT       */
 /*  including questions currently "in play".            */
-int MC_NoQuestionsLeft(void)
+int MC_ListQuestionsLeft(void)
 {
-  return !quest_list_length;
+  return quest_list_length;
 }
 
 
@@ -1360,15 +1361,15 @@
 
 /* using parameters from the mission struct, create linked list of "flashcards" */
 /* FIXME should figure out how to proceed correctly if we run out of memory */
-/* FIXME implement question formats and question_copies flags */
-/* FIXME handle max_answer correctly, even if negative */
+/* FIXME very redundant code - figure out way to iterate through different */
+/* math operations and question formats                                    */
 MC_MathQuestion* generate_list(void)
 {
   MC_MathQuestion* top_of_list = 0;
   MC_MathQuestion* end_of_list = 0;
   MC_MathQuestion* tmp_ptr = 0;
 
-  int i, j;
+  int i, j, k;
   int length = 0;
 
   #ifdef MC_DEBUG
@@ -1377,23 +1378,62 @@
   #endif
  
   /* add nodes for each math operation allowed */
+
+
   if (math_opts->addition_allowed)
   {
     for (i = math_opts->min_augend; i <= math_opts->max_augend; i++)
     {
       for (j = math_opts->min_addend; j <= math_opts->max_addend; j++)
       {
-       /* prevent negative numbers if desired */
-        if (math_opts->allow_neg_answer || ((i >= 0) && (j >=0)))
+        /* check if max_answer exceeded or if question */
+        /* contains undesired negative values:         */
+        if (validate_question(i, j, i + j))
         {  
-          /* make sure max_questions not exceeded */
-          if (length < math_opts->max_questions)
+          /* put in the desired number of copies: */
+          for (k = 0; k < math_opts->question_copies; k++)
           {
-            tmp_ptr = create_node(i, j, MC_OPER_ADD, i + j, MC_FORMAT_ANS_LAST);
-            top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
-            end_of_list = tmp_ptr;
-            length++; 
-          } 
+            /* put in questions in each selected format: */
+
+            /* questions like num1 + num2 = ? */
+            if (math_opts->format_answer_last)
+            {
+              /* make sure max_questions not exceeded */
+              if (length < math_opts->max_questions)
+              {
+                tmp_ptr = create_node(i, j, MC_OPER_ADD, i + j, MC_FORMAT_ANS_LAST);
+                top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
+                end_of_list = tmp_ptr;
+                length++; 
+              } 
+            }
+
+            /* questions like num1 + ? = num3 */
+            if (math_opts->format_answer_middle)
+            {
+              /* make sure max_questions not exceeded */
+              if (length < math_opts->max_questions)
+              {
+                tmp_ptr = create_node(i, j, MC_OPER_ADD, i + j, MC_FORMAT_ANS_MIDDLE);
+                top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
+                end_of_list = tmp_ptr;
+                length++; 
+              } 
+            }
+
+            /* questions like ? + num2 = num3 */
+            if (math_opts->format_answer_first)
+            {
+              /* make sure max_questions not exceeded */
+              if (length < math_opts->max_questions)
+              {
+                tmp_ptr = create_node(i, j, MC_OPER_ADD, i + j, MC_FORMAT_ANS_FIRST);
+                top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
+                end_of_list = tmp_ptr;
+                length++; 
+              } 
+            }
+          }
         }
       }
     }
@@ -1405,17 +1445,54 @@
     {
       for (j = math_opts->min_subtrahend; j <= math_opts->max_subtrahend; j++)
       {
-        /* prevent negative numbers if desired */
-        if (math_opts->allow_neg_answer || (i >= j))
-        { 
-          /* make sure max_questions not exceeded */
-          if (length < math_opts->max_questions)
+        /* check if max_answer exceeded or if question */
+        /* contains undesired negative values:         */
+        if (validate_question(i, j, i - j))
+        {  
+          /* put in the desired number of copies: */
+          for (k = 0; k < math_opts->question_copies; k++)
           {
-            tmp_ptr = create_node(i, j, MC_OPER_SUB, i - j, MC_FORMAT_ANS_LAST);
-            top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
-            end_of_list = tmp_ptr;
-            length++;
-          } 
+            /* put in questions in each selected format: */
+
+            /* questions like num1 - num2 = ? */
+            if (math_opts->format_answer_last)
+            {
+              /* make sure max_questions not exceeded */
+              if (length < math_opts->max_questions)
+              {
+                tmp_ptr = create_node(i, j, MC_OPER_SUB, i - j, MC_FORMAT_ANS_LAST);
+                top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
+                end_of_list = tmp_ptr;
+                length++; 
+              } 
+            }
+
+            /* questions like num1 - ? = num3 */
+            if (math_opts->format_answer_middle)
+            {
+              /* make sure max_questions not exceeded */
+              if (length < math_opts->max_questions)
+              {
+                tmp_ptr = create_node(i, j, MC_OPER_SUB, i - j, MC_FORMAT_ANS_MIDDLE);
+                top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
+                end_of_list = tmp_ptr;
+                length++; 
+              } 
+            }
+
+            /* questions like ? - num2 = num3 */
+            if (math_opts->format_answer_first)
+            {
+              /* make sure max_questions not exceeded */
+              if (length < math_opts->max_questions)
+              {
+                tmp_ptr = create_node(i, j, MC_OPER_SUB, i - j, MC_FORMAT_ANS_FIRST);
+                top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
+                end_of_list = tmp_ptr;
+                length++; 
+              } 
+            }
+          }
         }
       }
     }
@@ -1426,17 +1503,58 @@
     for (i = math_opts->min_multiplier; i <= math_opts->max_multiplier; i++)
     {
       for (j = math_opts->min_multiplicand; j <= math_opts->max_multiplicand; j++)
-      { 
-       /* prevent negative numbers if desired */
-        if (math_opts->allow_neg_answer || ((i >= 0) && (j >=0)))
-        {
-          /* make sure max_questions not exceeded */
-          if (length < math_opts->max_questions)
+      {
+        /* check if max_answer exceeded or if question */
+        /* contains undesired negative values:         */
+        if (validate_question(i, j, i * j))
+        {  
+          /* put in the desired number of copies: */
+          for (k = 0; k < math_opts->question_copies; k++)
           {
-            tmp_ptr = create_node(i, j, MC_OPER_MULT, i * j, MC_FORMAT_ANS_LAST);
-            top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
-            end_of_list = tmp_ptr;
-            length++;
+            /* put in questions in each selected format: */
+
+            /* questions like num1 x num2 = ? */
+            if (math_opts->format_answer_last)
+            {
+              /* make sure max_questions not exceeded */
+              if (length < math_opts->max_questions)
+              {
+                tmp_ptr = create_node(i, j, MC_OPER_MULT, i * j, MC_FORMAT_ANS_LAST);
+                top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
+                end_of_list = tmp_ptr;
+                length++; 
+              } 
+            }
+
+            /* questions like num1 x ? = num3 */
+            /* (no questions like 0 x ? = 0) because answer indeterminate */
+            if ((math_opts->format_answer_middle)
+             && (i != 0)) 
+            {
+                 /* make sure max_questions not exceeded */
+              if (length < math_opts->max_questions)
+              {
+                tmp_ptr = create_node(i, j, MC_OPER_MULT, i * j, MC_FORMAT_ANS_MIDDLE);
+                top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
+                end_of_list = tmp_ptr;
+                length++; 
+              } 
+            }
+
+            /* questions like ? x num2 = num3 */
+            /* (no questions like ? X 0 = 0) because answer indeterminate */
+            if ((math_opts->format_answer_first)
+             && (j != 0))
+            {
+              /* make sure max_questions not exceeded */
+              if (length < math_opts->max_questions)
+              {
+                tmp_ptr = create_node(i, j, MC_OPER_MULT, i * j, MC_FORMAT_ANS_FIRST);
+                top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
+                end_of_list = tmp_ptr;
+                length++; 
+              } 
+            }
           }
         }
       }
@@ -1449,19 +1567,55 @@
     {
       for (j = math_opts->min_divisor; j <= math_opts->max_divisor; j++)
       {
-       /* prevent negative numbers if desired */
-        if (math_opts->allow_neg_answer || ((i >= 0) && (j >=0)))
-        {
-          if (j) /* prevent division by zero */
+        /* check if max_answer exceeded or if question */
+        /* contains undesired negative values:         */
+        if (j                                     /* must avoid division by zero: */      
+            &&
+            validate_question(i * j, j, i))       /* division problems are generated as multiplication */
+        {  
+          /* put in the desired number of copies: */
+          for (k = 0; k < math_opts->question_copies; k++)
           {
-            /* make sure max_questions not exceeded */
-            if (length < math_opts->max_questions)
+            /* put in questions in each selected format: */
+
+            /* questions like num1 / num2 = ? */
+            if (math_opts->format_answer_last)
             {
-              tmp_ptr = create_node(i * j, j, MC_OPER_DIV, i, MC_FORMAT_ANS_LAST);
-              top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
-              end_of_list = tmp_ptr;
-              length++;
+              /* make sure max_questions not exceeded */
+              if (length < math_opts->max_questions)
+              {
+                tmp_ptr = create_node(i * j, j, MC_OPER_DIV, i, MC_FORMAT_ANS_LAST);
+                top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
+                end_of_list = tmp_ptr;
+                length++; 
+              } 
             }
+
+            /* questions like num1 / ? = num3 */
+            if (math_opts->format_answer_middle)
+            {
+              /* make sure max_questions not exceeded */
+              if (length < math_opts->max_questions)
+              {
+                tmp_ptr = create_node(i * j, j, MC_OPER_DIV, i, MC_FORMAT_ANS_MIDDLE);
+                top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
+                end_of_list = tmp_ptr;
+                length++; 
+              } 
+            }
+
+            /* questions like ? / num2  = num3 */
+            if (math_opts->format_answer_first)
+            {
+              /* make sure max_questions not exceeded */
+              if (length < math_opts->max_questions)
+              {
+                tmp_ptr = create_node(i * j, j, MC_OPER_DIV, i, MC_FORMAT_ANS_FIRST);
+                top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
+                end_of_list = tmp_ptr;
+                length++; 
+              } 
+            }
           }
         }
       }
@@ -1489,8 +1643,29 @@
 }
 
 
+/* this is used by generate_list to see if a possible question */
+/* meets criteria to be added to the list or not:              */
+int validate_question(int n1, int n2, int n3)
+{
+  /* make sure none of values exceeds max_answer using absolute */
+  /* value comparison:                                          */
+  if (abs_value(n1) > abs_value(math_opts->max_answer)
+   || abs_value(n2) > abs_value(math_opts->max_answer)
+   || abs_value(n3) > abs_value(math_opts->max_answer))
+  {
+    return 0;
+  }
+  /* make sure none of values are negative if negatives not allowed: */
+  if (!math_opts->allow_neg_answer)
+  {
+    if (n1 < 0 || n2 < 0 || n3 < 0)
+    {
+      return 0;
+    }
+  }
+  return 1;  
+}
 
-
 /* create a new node and return a pointer to it */
 MC_MathQuestion* create_node(int n1, int n2, int op, int ans, int f)
 {
@@ -1675,6 +1850,7 @@
 
 
 
+
 /* prints struct to stdout for testing purposes */
 void print_math_options(void)
 {
@@ -1690,7 +1866,10 @@
   printf("\nGeneral math options:\n");
   printf("allow_neg_answer:\t%d\n", math_opts->allow_neg_answer);
   printf("max_answer:\t%d\n", math_opts->max_answer);
-  printf("max_questions:\t%d\n", math_opts->max_questions);
+  printf("max_questions:\t%d\n", math_opts->max_questions);  
+  printf("recycle_corrects:\t%d\n", math_opts->recycle_corrects);
+  printf("recycle_wrongs:\t%d\n", math_opts->recycle_wrongs);
+  printf("copies_recycled_wrongs:\t%d\n", math_opts->copies_recycled_wrongs);
   printf("format_answer_last:\t%d\n", math_opts->format_answer_last);
   printf("format_answer_first:\t%d\n", math_opts->format_answer_first);
   printf("format_answer_middle:\t%d\n", math_opts->format_answer_middle);

Modified: tuxmath/trunk/src/mathcards.h
===================================================================
--- tuxmath/trunk/src/mathcards.h	2006-05-16 17:05:20 UTC (rev 10)
+++ tuxmath/trunk/src/mathcards.h	2006-06-12 20:14:08 UTC (rev 11)
@@ -15,7 +15,7 @@
 #ifndef MATHCARDS_H
 #define MATHCARDS_H
 
-#undef MC_DEBUG
+#define MC_DEBUG
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -195,15 +195,13 @@
 /* 0 otherwise.                                           */
 int MC_MissionAccomplished(void);
 
-/*  Returns 1 if no more questions left (either in list   */
-/*  or "in play"                                          */
-/*  FIXME would be better to return number of questions   */
-/*  left so it can be displayed in a counter.             */
-int MC_GameOver(void);
+/*  Returns number of questions left (either in list      */
+/*  or "in play")                                         */
+int MC_TotalQuestionsLeft(void);
 
-/*  Returns 1 if no more questions left in list, NOT    */
-/*  including questions currently "in play".            */
-int MC_NoQuestionsLeft(void);
+/*  Returns questions left in list, NOT                   */
+/*  including questions currently "in play".              */
+int MC_ListQuestionsLeft(void);
 
 /*  Tells MathCards to clean up - should be called when   */
 /*  user interface program exits.                         */

Modified: tuxmath/trunk/src/setup.c
===================================================================
--- tuxmath/trunk/src/setup.c	2006-05-16 17:05:20 UTC (rev 10)
+++ tuxmath/trunk/src/setup.c	2006-06-12 20:14:08 UTC (rev 11)
@@ -107,6 +107,9 @@
   DATA_PREFIX "/images/comets/cometex1a.png",
   DATA_PREFIX "/images/comets/cometex1.png",
   DATA_PREFIX "/images/comets/cometex1.png",
+  DATA_PREFIX "/images/comets/mini_comet1.png",
+  DATA_PREFIX "/images/comets/mini_comet2.png",
+  DATA_PREFIX "/images/comets/mini_comet3.png",
   DATA_PREFIX "/images/status/nums.png",
   DATA_PREFIX "/images/status/lednums.png",
   DATA_PREFIX "/images/status/led_neg_sign.png",
@@ -116,12 +119,17 @@
   DATA_PREFIX "/images/status/keypad.png",
   DATA_PREFIX "/images/status/keypad_no_neg.png",
   DATA_PREFIX "/images/tux/console.png",
+  DATA_PREFIX "/images/tux/console_led.png",
   DATA_PREFIX "/images/tux/tux-console1.png",
   DATA_PREFIX "/images/tux/tux-console2.png",
   DATA_PREFIX "/images/tux/tux-console3.png",
   DATA_PREFIX "/images/tux/tux-console4.png",
   DATA_PREFIX "/images/tux/tux-relax1.png",
   DATA_PREFIX "/images/tux/tux-relax2.png",
+  DATA_PREFIX "/images/tux/tux-egypt1.png",
+  DATA_PREFIX "/images/tux/tux-egypt2.png",
+  DATA_PREFIX "/images/tux/tux-egypt3.png",
+  DATA_PREFIX "/images/tux/tux-egypt4.png",
   DATA_PREFIX "/images/tux/tux-drat.png",
   DATA_PREFIX "/images/tux/tux-yipe.png",
   DATA_PREFIX "/images/tux/tux-yay1.png",
@@ -134,7 +142,8 @@
   DATA_PREFIX "/images/status/wave.png",
   DATA_PREFIX "/images/status/score.png",
   DATA_PREFIX "/images/status/numbers.png",
-  DATA_PREFIX "/images/status/gameover.png"
+  DATA_PREFIX "/images/status/gameover.png",
+  DATA_PREFIX "/images/status/gameover_won.png"
 };
 
 
@@ -192,6 +201,7 @@
     exit(1);
   }
 
+
   /* initialize game_options struct with defaults DSB */
   game_options = malloc(sizeof(game_option_type));
   if (!initialize_game_options(game_options))
@@ -201,13 +211,7 @@
     exit(1);
   }
 
-/* FIXME will not need this when MathCards used */ 
-/* 
-  for (i = 0; i < NUM_OPERS; i++)
-  {
-    opers[i] = 1;
-  }
-*/
+
   for (i = 0; i < NUM_Q_RANGES; i++)
   { 
     range_enabled[i] = 1;
@@ -253,6 +257,12 @@
 	"When you lose all of your cities, the game ends.\n\n");
 
       printf("Run the game with:\n"
+        "--norepeats      - 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"
@@ -339,6 +349,23 @@
     {
       MC_SetAllowNegAnswer(1);
     }
+    else if (strcmp(argv[i], "--norepeats") == 0 ||
+             strcmp(argv[i], "-r") == 0)
+    {
+      MC_SetRecycleCorrects(0);
+    }
+    else if (strcmp(argv[i], "--answersfirst") == 0)
+    {
+      MC_SetFormatAnswerLast(0);
+      MC_SetFormatAnswerFirst(1);
+      MC_SetFormatAnswerMiddle(0);
+    }
+    else if (strcmp(argv[i], "--answersmiddle") == 0)
+    {
+      MC_SetFormatAnswerLast(0);
+      MC_SetFormatAnswerFirst(0);
+      MC_SetFormatAnswerMiddle(1);
+    }
     else if (strcmp(argv[i], "--speed") == 0 ||
 	     strcmp(argv[i], "-s") == 0)
     {
@@ -403,6 +430,7 @@
     game_options->use_keypad = 0;
   }
 
+
   
   /* Init SDL Video: */
 
@@ -414,7 +442,10 @@
 	      "%s\n\n", SDL_GetError());
       exit(1);
     }
-  
+
+  printf("before SDL Audio\n");
+
+
   /* Init SDL Audio: */
 
 #ifndef NOSOUND
@@ -430,11 +461,19 @@
 	  game_options->use_sound = 0;
         }
     }
-  
+
+   printf("middle of Audio\n");
+ 
   if (game_options->use_sound)
-    {
-      if (Mix_OpenAudio(44100, AUDIO_S16SYS, 2, 2048) < 0)
+  {
+    printf("using sound \n"); 
+       if (Mix_OpenAudio(44100, AUDIO_S16SYS, 2, 2048) < 0)
         {
+          printf( "\nWarning: I could not set up audio for 44100 Hz "
+	          "16-bit stereo.\n"
+	          "The Simple DirectMedia error that occured was:\n"
+	          "%s\n\n", SDL_GetError());
+
           fprintf(stderr,
 	          "\nWarning: I could not set up audio for 44100 Hz "
 	          "16-bit stereo.\n"
@@ -442,11 +481,13 @@
 	          "%s\n\n", SDL_GetError());
           game_options->use_sound = 0;
         }
-    }
+   }
 
 #endif
-  
 
+  printf("after SDL Audio\n");
+ 
+
   if (game_options->fullscreen)
   {
     screen = SDL_SetVideoMode(640, 480, 16, SDL_FULLSCREEN | SDL_HWSURFACE);
@@ -479,13 +520,13 @@
 
   SDL_WM_SetCaption("Tux, of Math Command", "TuxMath");
 
-
   if (game_options->use_sound)
     total_files = NUM_IMAGES + NUM_SOUNDS + NUM_MUSICS;
   else
     total_files = NUM_IMAGES;
+
+
   
-
   /* Load images: */
   for (i = 0; i < NUM_IMAGES; i++)
   {
@@ -542,6 +583,8 @@
     SDL_Flip(screen);
   }
 
+  printf("all images loaded\n");
+
 #ifndef NOSOUND
   if (game_options->use_sound)
   {
@@ -615,16 +658,12 @@
 {
   if (game_options)
     free(game_options);
+  /* frees any heap used by MathCards: */
   MC_EndGame();
 }
 
-/* Set up math_options struct with defaults from tuxmath.h, */
-/* with simple sanity check for negatives                   */
-/* FIXME Should there be more error checking here?          */
-/* FIXME move this to mathcards.c                           */
 
 
-
 int initialize_game_options(game_option_type* opts)
 {
   /* bail out if no struct */

Modified: tuxmath/trunk/src/tuxmath.h
===================================================================
--- tuxmath/trunk/src/tuxmath.h	2006-05-16 17:05:20 UTC (rev 10)
+++ tuxmath/trunk/src/tuxmath.h	2006-06-12 20:14:08 UTC (rev 11)
@@ -20,7 +20,8 @@
 #ifndef TUXMATH_H
 #define TUXMATH_H
 
-#undef TUXMATH_DEBUG   /* for conditional compilation of debugging output */
+//#define NOSOUND
+#define TUXMATH_DEBUG   /* for conditional compilation of debugging output */
 
 /* this struct contains all options regarding general       */
 /* gameplay but not having to do with math questions per se */
@@ -60,7 +61,7 @@
 #define DEFAULT_REUSE_QUESTIONS 0
 #define DEFAULT_SPEED 1
 #define DEFAULT_ALLOW_SPEEDUP 1
-#define DEFAULT_SPEEDUP_FACTOR 1
+#define DEFAULT_SPEEDUP_FACTOR 1.2
 #define DEFAULT_MAX_SPEED 10
 #define DEFAULT_SLOW_AFTER_WRONG 0
 #define DEFAULT_EXTRA_COMETS 2




More information about the Tux4kids-commits mailing list