rnd-19990920-1-src
authorHolger Schemel <info@artsoft.org>
Mon, 20 Sep 1999 19:35:48 +0000 (21:35 +0200)
committerHolger Schemel <info@artsoft.org>
Sat, 30 Aug 2014 08:34:15 +0000 (10:34 +0200)
src/Makefile
src/files.c
src/files.h
src/game.c
src/init.c
src/main.c
src/main.h
src/misc.c
src/screens.c

index 6c81021d1d52593d85be593b34749ec419741788..c27e4c54f5fc2e7dc256b17af1a04c1d34f94566 100644 (file)
@@ -31,8 +31,8 @@ XLIB_PATH = /usr/X11/lib
 # choose if you want to allow many global score file entries for one player
 # when installing the game in a multi user environment, choose this
 # SCORE_ENTRIES = ONE_PER_NAME
-# when installing the game in a single user environment, choose this
-SCORE_ENTRIES = MANY_PER_NAME
+# when installing the game in a single user environment, choose this (default)
+SCORE_ENTRIES = MANY_PER_NAME
 
 # The XPM-Library is no longer needed to build this program,
 # but is used to load graphics if XPM_INCLUDE_FILE is defined,
@@ -73,7 +73,9 @@ ifdef RW_GAME_DIR
 CONFIG_RW_GAME_DIR = -DRW_GAME_DIR="\"$(RW_GAME_DIR)\""
 endif
 
+ifdef SCORE_ENTRIES
 CONFIG_SCORE_ENTRIES = -D$(SCORE_ENTRIES)
+endif
 
 CONFIG_GAME_DIR = $(CONFIG_RO_GAME_DIR) $(CONFIG_RW_GAME_DIR)
 
index 364a04620f9fb015ea7653d91d7f0496525fd659..67f0168c42fbf64e068c11cb09a53017662a500f 100644 (file)
@@ -48,6 +48,7 @@
 /* file names and filename extensions */
 #ifndef MSDOS
 #define USERDATA_DIRECTORY     ".rocksndiamonds"
+#define LEVELSETUP_DIRECTORY   "levelsetup"
 #define SETUP_FILENAME         "setup.conf"
 #define LEVELSETUP_FILENAME    "levelsetup.conf"
 #define LEVELINFO_FILENAME     "levelinfo.conf"
@@ -56,6 +57,7 @@
 #define SCOREFILE_EXTENSION    "score"
 #else
 #define USERDATA_DIRECTORY     "userdata"
+#define LEVELSETUP_DIRECTORY   "lvlsetup"
 #define SETUP_FILENAME         "setup.cnf"
 #define LEVELSETUP_FILENAME    "lvlsetup.cnf"
 #define LEVELINFO_FILENAME     "lvlinfo.cnf"
@@ -256,6 +258,23 @@ static char *getScoreDir(char *level_subdir)
   return score_dir;
 }
 
+static char *getLevelSetupDir(char *level_subdir)
+{
+  static char *levelsetup_dir = NULL;
+  char *data_dir = getUserDataDir();
+  char *levelsetup_subdir = LEVELSETUP_DIRECTORY;
+
+  if (levelsetup_dir)
+    free(levelsetup_dir);
+
+  if (strlen(level_subdir) > 0)
+    levelsetup_dir = getPath3(data_dir, levelsetup_subdir, level_subdir);
+  else
+    levelsetup_dir = getPath2(data_dir, levelsetup_subdir);
+
+  return levelsetup_dir;
+}
+
 static char *getLevelFilename(int nr)
 {
   static char *filename = NULL;
@@ -339,6 +358,13 @@ static void InitUserLevelDirectory(char *level_subdir)
   }
 }
 
+static void InitLevelSetupDirectory(char *level_subdir)
+{
+  createDirectory(getUserDataDir(), "user data");
+  createDirectory(getLevelSetupDir(""), "main level setup");
+  createDirectory(getLevelSetupDir(level_subdir), "level setup");
+}
+
 static void setLevelInfoToDefaults()
 {
   int i, x, y;
@@ -987,6 +1013,8 @@ void SaveScore(int level_nr)
 
 #define TOKEN_STR_FILE_IDENTIFIER      "file_identifier"
 #define TOKEN_STR_LAST_LEVEL_SERIES    "last_level_series"
+#define TOKEN_STR_LAST_PLAYED_LEVEL    "last_played_level"
+#define TOKEN_STR_HANDICAP_LEVEL       "handicap_level"
 #define TOKEN_STR_PLAYER_PREFIX                "player_"
 
 #define TOKEN_VALUE_POSITION           30
@@ -997,14 +1025,20 @@ void SaveScore(int level_nr)
 #define SETUP_TOKEN_SOUND_LOOPS                2
 #define SETUP_TOKEN_SOUND_MUSIC                3
 #define SETUP_TOKEN_SOUND_SIMPLE       4
+
+#if 0
 #define SETUP_TOKEN_TOONS              5
 #define SETUP_TOKEN_DOUBLE_BUFFERING   6
-#define SETUP_TOKEN_SCROLL_DELAY       7
-#define SETUP_TOKEN_SOFT_SCROLLING     8
-#define SETUP_TOKEN_FADING             9
-#define SETUP_TOKEN_AUTORECORD         10
-#define SETUP_TOKEN_QUICK_DOORS                11
-#define SETUP_TOKEN_TEAM_MODE          12
+#endif
+
+#define SETUP_TOKEN_SCROLL_DELAY       5
+#define SETUP_TOKEN_SOFT_SCROLLING     6
+#define SETUP_TOKEN_FADING             7
+#define SETUP_TOKEN_AUTORECORD         8
+#define SETUP_TOKEN_QUICK_DOORS                9
+#define SETUP_TOKEN_TEAM_MODE          10
+#define SETUP_TOKEN_HANDICAP           11
+#define SETUP_TOKEN_TIME_LIMIT         12
 
 /* player setup */
 #define SETUP_TOKEN_USE_JOYSTICK       13
@@ -1035,7 +1069,7 @@ void SaveScore(int level_nr)
 #define LEVELINFO_TOKEN_READONLY       36
 
 #define FIRST_GLOBAL_SETUP_TOKEN       SETUP_TOKEN_PLAYER_NAME
-#define LAST_GLOBAL_SETUP_TOKEN                SETUP_TOKEN_TEAM_MODE
+#define LAST_GLOBAL_SETUP_TOKEN                SETUP_TOKEN_TIME_LIMIT
 
 #define FIRST_PLAYER_SETUP_TOKEN       SETUP_TOKEN_USE_JOYSTICK
 #define LAST_PLAYER_SETUP_TOKEN                SETUP_TOKEN_KEY_BOMB
@@ -1065,14 +1099,20 @@ static struct
   { TYPE_SWITCH,  &si.sound_loops,     "repeating_sound_loops"         },
   { TYPE_SWITCH,  &si.sound_music,     "background_music"              },
   { TYPE_SWITCH,  &si.sound_simple,    "simple_sound_effects"          },
+
+#if 0
   { TYPE_SWITCH,  &si.toons,           "toons"                         },
   { TYPE_SWITCH,  &si.double_buffering,        "double_buffering"              },
+#endif
+
   { TYPE_SWITCH,  &si.scroll_delay,    "scroll_delay"                  },
   { TYPE_SWITCH,  &si.soft_scrolling,  "soft_scrolling"                },
   { TYPE_SWITCH,  &si.fading,          "screen_fading"                 },
   { TYPE_SWITCH,  &si.autorecord,      "automatic_tape_recording"      },
   { TYPE_SWITCH,  &si.quick_doors,     "quick_doors"                   },
   { TYPE_SWITCH,  &si.team_mode,       "team_mode"                     },
+  { TYPE_SWITCH,  &si.handicap,                "handicap"                      },
+  { TYPE_SWITCH,  &si.time_limit,      "time_limit"                    },
 
   /* player setup */
   { TYPE_BOOLEAN, &sii.use_joystick,   ".use_joystick"                 },
@@ -1360,14 +1400,20 @@ static void checkSetupFileListIdentifier(struct SetupFileList *setup_file_list,
 
 static void setLevelDirInfoToDefaults(struct LevelDirInfo *ldi)
 {
+  ldi->filename = NULL;
   ldi->name = getStringCopy(ANONYMOUS_NAME);
   ldi->name_short = NULL;
   ldi->author = getStringCopy(ANONYMOUS_NAME);
   ldi->imported_from = NULL;
   ldi->levels = 0;
   ldi->first_level = 0;
+  ldi->last_level = 0;
   ldi->sort_priority = LEVELCLASS_UNDEFINED;   /* default: least priority */
   ldi->readonly = TRUE;
+  ldi->user_defined = FALSE;
+  ldi->color = 0;
+  ldi->class_desc = NULL;
+  ldi->handicap_level = 0;
 }
 
 static void setSetupInfoToDefaults(struct SetupInfo *si)
@@ -1388,6 +1434,9 @@ static void setSetupInfoToDefaults(struct SetupInfo *si)
   si->fading = FALSE;
   si->autorecord = TRUE;
   si->quick_doors = FALSE;
+  si->team_mode = FALSE;
+  si->handicap = TRUE;
+  si->time_limit = TRUE;
 
   for (i=0; i<MAX_PLAYERS; i++)
   {
@@ -1491,30 +1540,6 @@ int getLevelSeriesNrFromLevelSeriesName(char *level_series_name)
   return 0;
 }
 
-int getLastPlayedLevelOfLevelSeries(char *level_series_name)
-{
-  char *token_value;
-  int level_series_nr = getLevelSeriesNrFromLevelSeriesName(level_series_name);
-  int last_level_nr = leveldir[level_series_nr].first_level;
-
-  if (!level_series_name)
-    return 0;
-
-  token_value = getTokenValue(level_setup_list, level_series_name);
-
-  if (token_value)
-  {
-    last_level_nr = atoi(token_value);
-
-    if (last_level_nr < leveldir[level_series_nr].first_level)
-      last_level_nr = leveldir[level_series_nr].first_level;
-    if (last_level_nr > leveldir[level_series_nr].last_level)
-      last_level_nr = leveldir[level_series_nr].last_level;
-  }
-
-  return last_level_nr;
-}
-
 static int compareLevelDirInfoEntries(const void *object1, const void *object2)
 {
   const struct LevelDirInfo *entry1 = object1;
@@ -1835,54 +1860,48 @@ void SaveSetup()
   chmod(filename, SETUP_PERMS);
 }
 
-void LoadLevelSetup()
+void LoadLevelSetup_LastSeries()
 {
   char *filename;
+  struct SetupFileList *level_setup_list = NULL;
 
   /* always start with reliable default values */
   leveldir_nr = 0;
-  level_nr = 0;
-
-  filename = getPath2(getSetupDir(), LEVELSETUP_FILENAME);
 
-  if (level_setup_list)
-    freeSetupFileList(level_setup_list);
+  /* ----------------------------------------------------------------------- */
+  /* ~/.rocksndiamonds/levelsetup.conf                                       */
+  /* ----------------------------------------------------------------------- */
 
-  level_setup_list = loadSetupFileList(filename);
+  filename = getPath2(getSetupDir(), LEVELSETUP_FILENAME);
 
-  if (level_setup_list)
+  if ((level_setup_list = loadSetupFileList(filename)))
   {
     char *last_level_series =
       getTokenValue(level_setup_list, TOKEN_STR_LAST_LEVEL_SERIES);
 
     leveldir_nr = getLevelSeriesNrFromLevelSeriesName(last_level_series);
-    level_nr = getLastPlayedLevelOfLevelSeries(last_level_series);
 
     checkSetupFileListIdentifier(level_setup_list, LEVELSETUP_COOKIE);
+
+    freeSetupFileList(level_setup_list);
   }
   else
-  {
-    level_setup_list = newSetupFileList(TOKEN_STR_FILE_IDENTIFIER,
-                                       LEVELSETUP_COOKIE);
     Error(ERR_WARN, "using default setup values");
-  }
 
   free(filename);
 }
 
-void SaveLevelSetup()
+void SaveLevelSetup_LastSeries()
 {
   char *filename;
-  struct SetupFileList *list_entry = level_setup_list;
+  char *level_subdir = leveldir[leveldir_nr].filename;
   FILE *file;
 
-  InitUserDataDirectory();
-
-  setTokenValue(level_setup_list,
-               TOKEN_STR_LAST_LEVEL_SERIES, leveldir[leveldir_nr].filename);
+  /* ----------------------------------------------------------------------- */
+  /* ~/.rocksndiamonds/levelsetup.conf                                       */
+  /* ----------------------------------------------------------------------- */
 
-  setTokenValue(level_setup_list,
-               leveldir[leveldir_nr].filename, int2str(level_nr, 0));
+  InitUserDataDirectory();
 
   filename = getPath2(getSetupDir(), LEVELSETUP_FILENAME);
 
@@ -1895,19 +1914,103 @@ void SaveLevelSetup()
 
   fprintf(file, "%s\n\n", getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER,
                                                 LEVELSETUP_COOKIE));
-  while (list_entry)
+  fprintf(file, "%s\n", getFormattedSetupEntry(TOKEN_STR_LAST_LEVEL_SERIES,
+                                              level_subdir));
+
+  fclose(file);
+  free(filename);
+
+  chmod(filename, SETUP_PERMS);
+}
+
+void LoadLevelSetup_SeriesInfo(int leveldir_nr)
+{
+  char *filename;
+  struct SetupFileList *level_setup_list = NULL;
+  char *level_subdir = leveldir[leveldir_nr].filename;
+
+  /* always start with reliable default values */
+  level_nr = 0;
+  leveldir[leveldir_nr].handicap_level = 0;
+
+  /* ----------------------------------------------------------------------- */
+  /* ~/.rocksndiamonds/levelsetup/<level series>/levelsetup.conf             */
+  /* ----------------------------------------------------------------------- */
+
+  level_subdir = leveldir[leveldir_nr].filename;
+
+  filename = getPath2(getLevelSetupDir(level_subdir), LEVELSETUP_FILENAME);
+
+  if ((level_setup_list = loadSetupFileList(filename)))
   {
-    if (strcmp(list_entry->token, TOKEN_STR_FILE_IDENTIFIER) != 0)
-      fprintf(file, "%s\n",
-             getFormattedSetupEntry(list_entry->token, list_entry->value));
+    char *token_value;
 
-    /* just to make things nicer :) */
-    if (strcmp(list_entry->token, TOKEN_STR_LAST_LEVEL_SERIES) == 0)
-      fprintf(file, "\n");
+    token_value = getTokenValue(level_setup_list, TOKEN_STR_LAST_PLAYED_LEVEL);
+
+    if (token_value)
+    {
+      level_nr = atoi(token_value);
+
+      if (level_nr < leveldir[leveldir_nr].first_level)
+       level_nr = leveldir[leveldir_nr].first_level;
+      if (level_nr > leveldir[leveldir_nr].last_level)
+       level_nr = leveldir[leveldir_nr].last_level;
+    }
+
+    token_value = getTokenValue(level_setup_list, TOKEN_STR_HANDICAP_LEVEL);
+
+    if (token_value)
+    {
+      int level_nr = atoi(token_value);
+
+      if (level_nr < leveldir[leveldir_nr].first_level)
+       level_nr = leveldir[leveldir_nr].first_level;
+      if (level_nr > leveldir[leveldir_nr].last_level + 1)
+       level_nr = leveldir[leveldir_nr].last_level;
+
+      leveldir[leveldir_nr].handicap_level = level_nr;
+    }
+
+    checkSetupFileListIdentifier(level_setup_list, LEVELSETUP_COOKIE);
+
+    freeSetupFileList(level_setup_list);
+  }
+  else
+    Error(ERR_WARN, "using default setup values");
+
+  free(filename);
+}
+
+void SaveLevelSetup_SeriesInfo(int leveldir_nr)
+{
+  char *filename;
+  char *level_subdir = leveldir[leveldir_nr].filename;
+  char *level_nr_str = int2str(level_nr, 0);
+  char *handicap_level_str = int2str(leveldir[leveldir_nr].handicap_level, 0);
+  FILE *file;
+
+  /* ----------------------------------------------------------------------- */
+  /* ~/.rocksndiamonds/levelsetup/<level series>/levelsetup.conf             */
+  /* ----------------------------------------------------------------------- */
+
+  InitLevelSetupDirectory(level_subdir);
 
-    list_entry = list_entry->next;
+  filename = getPath2(getLevelSetupDir(level_subdir), LEVELSETUP_FILENAME);
+
+  if (!(file = fopen(filename, "w")))
+  {
+    Error(ERR_WARN, "cannot write setup file '%s'", filename);
+    free(filename);
+    return;
   }
 
+  fprintf(file, "%s\n\n", getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER,
+                                                LEVELSETUP_COOKIE));
+  fprintf(file, "%s\n", getFormattedSetupEntry(TOKEN_STR_LAST_PLAYED_LEVEL,
+                                              level_nr_str));
+  fprintf(file, "%s\n", getFormattedSetupEntry(TOKEN_STR_HANDICAP_LEVEL,
+                                              handicap_level_str));
+
   fclose(file);
   free(filename);
 
index d95cce18fc76076f732c2ee7d3333e9684a45ab6..ae27e21e6baafaa269aca37644cfbe7bbe00dcf8 100644 (file)
@@ -30,8 +30,10 @@ int getLastPlayedLevelOfLevelSeries(char *);
 void LoadLevelInfo(void);
 void LoadSetup(void);
 void SaveSetup(void);
-void LoadLevelSetup(void);
-void SaveLevelSetup(void);
+void LoadLevelSetup_LastSeries(void);
+void SaveLevelSetup_LastSeries(void);
+void LoadLevelSetup_SeriesInfo(int);
+void SaveLevelSetup_SeriesInfo(int);
 
 #ifdef MSDOS
 FILE *openErrorFile();
index e3fc38ba736906daf1b8440a5405bf9e6ee105d7..70febf6328c8ce86b4f8c9049a72d96e6b90f435 100644 (file)
@@ -894,7 +894,7 @@ void InitAmoebaNr(int x, int y)
 void GameWon()
 {
   int hi_pos;
-  int bumplevel = FALSE;
+  boolean raise_level = FALSE;
 
   if (local_player->MovPos)
     return;
@@ -965,17 +965,26 @@ void GameWon()
     SaveTape(tape.level_nr);           /* Ask to save tape */
   }
 
+  if (level_nr == leveldir[leveldir_nr].handicap_level)
+  {
+    leveldir[leveldir_nr].handicap_level++;
+    SaveLevelSetup_SeriesInfo(leveldir_nr);
+
+    if (level_nr < leveldir[leveldir_nr].last_level)
+      raise_level = TRUE;
+  }
+
   if ((hi_pos = NewHiScore()) >= 0) 
   {
     game_status = HALLOFFAME;
     DrawHallOfFame(hi_pos);
-    if (bumplevel && TAPE_IS_EMPTY(tape))
+    if (raise_level)
       level_nr++;
   }
   else
   {
     game_status = MAINMENU;
-    if (bumplevel && TAPE_IS_EMPTY(tape))
+    if (raise_level)
       level_nr++;
     DrawMainMenu();
   }
@@ -2803,6 +2812,8 @@ void StartMoving(int x, int y)
       else if (element == EL_SP_ELECTRON)
        DrawGraphicAnimation(x, y, GFX2_SP_ELECTRON, 8, 2, ANIM_NORMAL);
 
+      TestIfBadThingHitsHero(x, y);
+
       return;
     }
 
@@ -4390,12 +4401,12 @@ void GameActions()
     {
       TimeLeft--;
 
-      if (TimeLeft <= 10)
+      if (TimeLeft <= 10 && setup.time_limit)
        PlaySoundStereo(SND_GONG, PSND_MAX_RIGHT);
 
       DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW);
 
-      if (!TimeLeft)
+      if (!TimeLeft && setup.time_limit)
        for (i=0; i<MAX_PLAYERS; i++)
          KillHero(&stored_player[i]);
     }
@@ -4892,6 +4903,9 @@ void TestIfBadThingHitsGoodThing(int badx, int bady)
     MV_DOWN
   };
 
+  if (Feld[badx][bady] == EL_EXPLODING)        /* skip just exploding bad things */
+    return;
+
   for (i=0; i<4; i++)
   {
     int x, y, element;
index c41f8c7626545b1c2c7ab7ca01178417a5734f8b..daac63969d198c445b8bc923ab1acfac8c8d20d3 100644 (file)
@@ -104,9 +104,10 @@ void InitLevelAndPlayerInfo()
 
   local_player->connected = TRUE;
 
-  LoadLevelInfo();                     /* global level info */
-  LoadSetup();                         /* global setup info */
-  LoadLevelSetup();                    /* info about last played level */
+  LoadLevelInfo();                             /* global level info */
+  LoadSetup();                                 /* global setup info */
+  LoadLevelSetup_LastSeries();                 /* last played series info */
+  LoadLevelSetup_SeriesInfo(leveldir_nr);      /* last played level info */
 }
 
 void InitNetworkServer()
index f94664ab3a2f0d577cb60b69b072d1b33ce71998..266ad65c7a8e75793a4109b965b11f278828b524 100644 (file)
@@ -110,8 +110,6 @@ struct SoundInfo    Sound[NUM_SOUNDS];
 struct TapeInfo                tape;
 struct OptionInfo      options;
 struct SetupInfo       setup;
-struct SetupFileList   *setup_list = NULL;
-struct SetupFileList   *level_setup_list = NULL;
 struct GameInfo                game;
 struct GlobalInfo      global;
 
index d177897aaff098d49ed4569284178ff3883546e2..1dff3be74dff8872e0ed6ef5e3b9b8405564af80 100644 (file)
@@ -297,6 +297,8 @@ struct SetupInfo
   boolean autorecord;
   boolean quick_doors;
   boolean team_mode;
+  boolean handicap;
+  boolean time_limit;
 
   struct SetupInputInfo input[MAX_PLAYERS];
 };
@@ -394,6 +396,7 @@ struct LevelDirInfo
   boolean readonly;    /* readonly levels can not be changed with editor */
   int color;           /* color to use on selection screen for this level */
   char *class_desc;    /* description of level series class */
+  int handicap_level;  /* number of the lowest unsolved level */
 };
 
 struct TapeInfo
@@ -516,8 +519,6 @@ extern struct SoundInfo             Sound[];
 extern struct JoystickInfo     joystick[];
 extern struct OptionInfo       options;
 extern struct SetupInfo                setup;
-extern struct SetupFileList    *setup_list;
-extern struct SetupFileList    *level_setup_list;
 extern struct GameInfo         game;
 extern struct GlobalInfo       global;
 
index 7ff3a94781e0ed66ab23597f99b5a19935c9484c..33db03d76a76cc080df7fda89735e48008b6596d 100644 (file)
@@ -167,9 +167,20 @@ void WaitUntilDelayReached(unsigned long *counter_var, unsigned long delay)
   *counter_var = actual_counter;
 }
 
+/* int2str() returns a number converted to a string;
+   the used memory is static, but will be overwritten by later calls,
+   so if you want to save the result, copy it to a private string buffer;
+   there can be 10 local calls of int2str() without buffering the result --
+   the 11th call will then destroy the result from the first call and so on.
+*/
+
 char *int2str(int number, int size)
 {
-  static char s[40];
+  static char shift_array[10][40];
+  static int shift_counter = 0;
+  char *s = shift_array[shift_counter];
+
+  shift_counter = (shift_counter + 1) % 10;
 
   if (size > 20)
     size = 20;
index 347ae23c65af4f0d71ff06518854fb645f6a2a46..819e25dfb916328a0dfb7a84d3681bc3a20f0fa0 100644 (file)
@@ -76,6 +76,10 @@ void DrawMainMenu()
   /* map gadgets for main menu screen */
   MapTapeButtons();
 
+  /* level_nr may have set to value over handicap with level editor */
+  if (setup.handicap && level_nr > leveldir[leveldir_nr].handicap_level)
+    level_nr = leveldir[leveldir_nr].handicap_level;
+
   GetPlayerConfig();
   LoadLevel(level_nr);
 
@@ -196,6 +200,9 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
     if (new_level_nr > leveldir[leveldir_nr].last_level)
       new_level_nr = leveldir[leveldir_nr].last_level;
 
+    if (setup.handicap && new_level_nr > leveldir[leveldir_nr].handicap_level)
+      new_level_nr = leveldir[leveldir_nr].handicap_level;
+
     if (old_level_nr == new_level_nr ||
        !DelayReached(&level_delay, GADGET_FRAME_DELAY))
       goto out;
@@ -242,7 +249,8 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
        if (num_leveldirs)
        {
          game_status = CHOOSELEVEL;
-         SaveLevelSetup();
+         SaveLevelSetup_LastSeries();
+         SaveLevelSetup_SeriesInfo(leveldir_nr);
          DrawChooseLevel();
        }
       }
@@ -276,6 +284,7 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
 #endif
        {
          game_status = PLAYING;
+         StopAnimation();
          InitGame();
        }
       }
@@ -286,7 +295,8 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
       }
       else if (y == 10)
       {
-       SaveLevelSetup();
+       SaveLevelSetup_LastSeries();
+       SaveLevelSetup_SeriesInfo(leveldir_nr);
         if (Request("Do you really want to quit ?", REQ_ASK | REQ_STAY_CLOSED))
          game_status = EXITGAME;
       }
@@ -964,10 +974,10 @@ void HandleChooseLevel(int mx, int my, int dx, int dy, int button)
     else
     {
       leveldir_nr = first_entry + y - 3;
-      level_nr =
-       getLastPlayedLevelOfLevelSeries(leveldir[leveldir_nr].filename);
+      LoadLevelSetup_SeriesInfo(leveldir_nr);
 
-      SaveLevelSetup();
+      SaveLevelSetup_LastSeries();
+      SaveLevelSetup_SeriesInfo(leveldir_nr);
       TapeErase();
 
       game_status = MAINMENU;
@@ -1040,14 +1050,18 @@ void DrawSetupScreen()
     { &setup.sound,            "Sound:",       },
     { &setup.sound_loops,      " Sound Loops:" },
     { &setup.sound_music,      " Game Music:"  },
+#if 0
     { &setup.toons,            "Toons:"        },
     { &setup.double_buffering, "Buffered gfx:" },
+#endif
     { &setup.scroll_delay,     "Scroll Delay:" },
     { &setup.soft_scrolling,   "Soft Scroll.:" },
     { &setup.fading,           "Fading:"       },
     { &setup.quick_doors,      "Quick Doors:"  },
     { &setup.autorecord,       "Auto-Record:"  },
     { &setup.team_mode,                "Team-Mode:"    },
+    { &setup.handicap,         "Handicap:"     },
+    { &setup.time_limit,       "Timelimit:"    },
     { NULL,                    "Input Devices" },
     { NULL,                    ""              },
     { NULL,                    "Exit"          },
@@ -1185,6 +1199,8 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
        }
        setup.sound_music = !setup.sound_music;
       }
+
+#if 0
       else if (y==6)
       {
        if (setup.toons)
@@ -1208,7 +1224,9 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
        setup.direct_draw = !setup.double_buffering;
 #endif
       }
-      else if (y==8)
+#endif
+
+      else if (y==6)
       {
        if (setup.scroll_delay)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1216,7 +1234,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.scroll_delay = !setup.scroll_delay;
       }
-      else if (y==9)
+      else if (y==7)
       {
        if (setup.soft_scrolling)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1224,7 +1242,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.soft_scrolling = !setup.soft_scrolling;
       }
-      else if (y==10)
+      else if (y==8)
       {
        if (setup.fading)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1232,7 +1250,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.fading = !setup.fading;
       }
-      else if (y==11)
+      else if (y==9)
       {
        if (setup.quick_doors)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1240,7 +1258,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.quick_doors = !setup.quick_doors;
       }
-      else if (y==12)
+      else if (y==10)
       {
        if (setup.autorecord)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1248,7 +1266,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.autorecord = !setup.autorecord;
       }
-      else if (y==13)
+      else if (y==11)
       {
        if (setup.team_mode)
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -1256,6 +1274,22 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        setup.team_mode = !setup.team_mode;
       }
+      else if (y==12)
+      {
+       if (setup.handicap)
+         DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+       else
+         DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+       setup.handicap = !setup.handicap;
+      }
+      else if (y==13)
+      {
+       if (setup.time_limit)
+         DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+       else
+         DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+       setup.time_limit = !setup.time_limit;
+      }
       else if (y==14)
       {
        game_status = SETUPINPUT;