rnd-20030926-1-src
authorHolger Schemel <info@artsoft.org>
Fri, 26 Sep 2003 01:45:50 +0000 (03:45 +0200)
committerHolger Schemel <info@artsoft.org>
Sat, 30 Aug 2014 08:43:57 +0000 (10:43 +0200)
16 files changed:
src/conf_e2s.c
src/conf_gfx.c
src/conf_gfx.h
src/conf_snd.c
src/conf_snd.h
src/conftime.h
src/editor.c
src/files.c
src/game.c
src/init.c
src/libgame/misc.c
src/libgame/misc.h
src/libgame/system.h
src/main.c
src/main.h
src/tools.c

index a986c3d33184edb4b28e157c94757d76ed9e1359..03dfbe980887a9966b710fe1bd00c320cfb5316f 100644 (file)
@@ -468,6 +468,14 @@ element_to_sound[] =
     EL_ENVELOPE_1, TRUE,                       ACTION_COLLECTING,
     SND_CLASS_ENVELOPE_COLLECTING
   },
+  {
+    EL_ENVELOPE_1, TRUE,                       ACTION_OPENING,
+    SND_CLASS_ENVELOPE_OPENING
+  },
+  {
+    EL_ENVELOPE_1, TRUE,                       ACTION_CLOSING,
+    SND_CLASS_ENVELOPE_CLOSING
+  },
   {
     EL_INVISIBLE_SAND, FALSE,                  ACTION_DIGGING,
     SND_INVISIBLE_SAND_DIGGING
index 2a129b4fad4c3f84018ba55af824c260f74faff7..72dd3bd17eb1296466f05ddddbe87fa1a0e82f99 100644 (file)
@@ -3455,11 +3455,18 @@ struct ConfigInfo image_config[] =
   { "editor.element_border_input.xpos",                "0"                     },
   { "editor.element_border_input.ypos",                "0"                     },
 
-  { "game.envelope_background",                        "RocksScreen.pcx"       },
-  { "game.envelope_background.x",              "0"                     },
-  { "game.envelope_background.y",              "0"                     },
-  { "game.envelope_background.width",          "560"                   },
-  { "game.envelope_background.height",         "560"                   },
+  { "game.envelope.background",                        "RocksScreen.pcx"       },
+  { "game.envelope.background.x",              "0"                     },
+  { "game.envelope.background.y",              "0"                     },
+  { "game.envelope.background.width",          "560"                   },
+  { "game.envelope.background.height",         "560"                   },
+  { "game.envelope.background.anim_mode",      "default"               },
+  { "game.envelope.background.draw_masked",    "false"                 },
+
+  { "game.envelope_1.background",              UNDEFINED_FILENAME      },
+  { "game.envelope_2.background",              UNDEFINED_FILENAME      },
+  { "game.envelope_3.background",              UNDEFINED_FILENAME      },
+  { "game.envelope_4.background",              UNDEFINED_FILENAME      },
 
   { "background",                              UNDEFINED_FILENAME      },
   { "background.MAIN",                         UNDEFINED_FILENAME      },
@@ -3497,11 +3504,12 @@ struct ConfigInfo image_config[] =
   { "menu.list_size.SCORES",                   "-1"                    },
   { "menu.list_size.INFO",                     "-1"                    },
 
-  { "door.step_offset",                                "2"                     },
-  { "door.step_delay",                         "10"                    },
-  { "door.anim_mode",                          "default"               },
-
-  { "game.envelope.anim_mode",                 "full"                  },
+  { "door_1.step_offset",                      "2"                     },
+  { "door_1.step_delay",                       "10"                    },
+  { "door_1.anim_mode",                                "default"               },
+  { "door_2.step_offset",                      "2"                     },
+  { "door_2.step_delay",                       "10"                    },
+  { "door_2.anim_mode",                                "default"               },
 
   { NULL,                                      NULL                    }
 };
index 2ba81c85f83db3b69b0ebe1c845249d8591b9174..cf51a444bf51302d5d683ef1af4c17ec22a14033 100644 (file)
 #define IMG_EDITOR_ELEMENT_BORDER                      1267
 #define IMG_EDITOR_ELEMENT_BORDER_INPUT                        1268
 #define IMG_GAME_ENVELOPE_BACKGROUND                   1269
-#define IMG_BACKGROUND                                 1270
-#define IMG_BACKGROUND_MAIN                            1271
-#define IMG_BACKGROUND_LEVELS                          1272
-#define IMG_BACKGROUND_SCORES                          1273
-#define IMG_BACKGROUND_EDITOR                          1274
-#define IMG_BACKGROUND_INFO                            1275
-#define IMG_BACKGROUND_SETUP                           1276
-#define IMG_BACKGROUND_DOOR                            1277
+#define IMG_GAME_ENVELOPE_1_BACKGROUND                 1270
+#define IMG_GAME_ENVELOPE_2_BACKGROUND                 1271
+#define IMG_GAME_ENVELOPE_3_BACKGROUND                 1272
+#define IMG_GAME_ENVELOPE_4_BACKGROUND                 1273
+#define IMG_BACKGROUND                                 1274
+#define IMG_BACKGROUND_MAIN                            1275
+#define IMG_BACKGROUND_LEVELS                          1276
+#define IMG_BACKGROUND_SCORES                          1277
+#define IMG_BACKGROUND_EDITOR                          1278
+#define IMG_BACKGROUND_INFO                            1279
+#define IMG_BACKGROUND_SETUP                           1280
+#define IMG_BACKGROUND_DOOR                            1281
 
-#define NUM_IMAGE_FILES                                        1278
+#define NUM_IMAGE_FILES                                        1282
 
 #endif /* CONF_GFX_H */
index 6597db53c3796a4532f3372c6aca4b0d66e8f7c8..4f1a8210e46b430d69c2920f989599c41ef5f392 100644 (file)
@@ -146,6 +146,8 @@ struct ConfigInfo sound_config[] =
   { "crystal.collecting",              "pong.wav"              },
   { "crystal.impact",                  "pling.wav"             },
   { "[envelope].collecting",           "pong.wav"              },
+  { "[envelope].opening",              UNDEFINED_FILENAME      },
+  { "[envelope].closing",              UNDEFINED_FILENAME      },
   { "invisible_sand.digging",          "schlurf.wav"           },
   { "shield_normal.collecting",                "pong.wav"              },
   { "shield_normal.active",            UNDEFINED_FILENAME      },
index c5b448bd0563fa1b105c1be2c99e30b88d5c2c00..ec2aa485f7f279042653295871823434f5c2b37b 100644 (file)
 #define SND_CRYSTAL_COLLECTING                         100
 #define SND_CRYSTAL_IMPACT                                     101
 #define SND_CLASS_ENVELOPE_COLLECTING                          102
-#define SND_INVISIBLE_SAND_DIGGING                             103
-#define SND_SHIELD_NORMAL_COLLECTING                   104
-#define SND_SHIELD_NORMAL_ACTIVE                               105
-#define SND_SHIELD_DEADLY_COLLECTING                   106
-#define SND_SHIELD_DEADLY_ACTIVE                               107
-#define SND_EXTRA_TIME_COLLECTING                              108
-#define SND_MOLE_MOVING                                        109
-#define SND_MOLE_WAITING                                       110
-#define SND_MOLE_DIGGING                                       111
-#define SND_CLASS_SWITCHGATE_SWITCH_ACTIVATING                 112
-#define SND_CLASS_SWITCHGATE_OPENING                           113
-#define SND_CLASS_SWITCHGATE_CLOSING                           114
-#define SND_CLASS_SWITCHGATE_PASSING                           115
-#define SND_TIMEGATE_SWITCH_ACTIVATING                 116
-#define SND_TIMEGATE_SWITCH_ACTIVE                             117
-#define SND_TIMEGATE_SWITCH_DEACTIVATING                       118
-#define SND_TIMEGATE_OPENING                           119
-#define SND_CLASS_TIMEGATE_CLOSING                             120
-#define SND_CLASS_TIMEGATE_PASSING                             121
-#define SND_CLASS_CONVEYOR_BELT_SWITCH_ACTIVATING              122
-#define SND_CLASS_CONVEYOR_BELT_ACTIVE                         123
-#define SND_CLASS_CONVEYOR_BELT_SWITCH_DEACTIVATING            124
-#define SND_LIGHT_SWITCH_ACTIVATING                            125
-#define SND_LIGHT_SWITCH_DEACTIVATING                  126
-#define SND_DX_SUPABOMB_PUSHING                                127
-#define SND_TRAP_DIGGING                                       128
-#define SND_TRAP_ACTIVATING                                    129
-#define SND_CLASS_TUBE_WALKING                                 130
-#define SND_AMOEBA_TURNING_TO_GEM                              131
-#define SND_AMOEBA_TURNING_TO_ROCK                             132
-#define SND_SPEED_PILL_COLLECTING                              133
-#define SND_DYNABOMB_INCREASE_NUMBER_COLLECTING                134
-#define SND_DYNABOMB_INCREASE_SIZE_COLLECTING          135
-#define SND_DYNABOMB_INCREASE_POWER_COLLECTING         136
-#define SND_CLASS_DYNABOMB_DROPPING                            137
-#define SND_CLASS_DYNABOMB_ACTIVE                              138
-#define SND_SATELLITE_MOVING                           139
-#define SND_SATELLITE_WAITING                          140
-#define SND_SATELLITE_PUSHING                          141
-#define SND_LAMP_ACTIVATING                                    142
-#define SND_LAMP_DEACTIVATING                          143
-#define SND_TIME_ORB_FULL_COLLECTING                   144
-#define SND_TIME_ORB_FULL_IMPACT                               145
-#define SND_TIME_ORB_EMPTY_PUSHING                             146
-#define SND_TIME_ORB_EMPTY_IMPACT                              147
-#define SND_GAME_OF_LIFE_WAITING                               148
-#define SND_GAME_OF_LIFE_GROWING                               149
-#define SND_BIOMAZE_WAITING                                    150
-#define SND_BIOMAZE_GROWING                                    151
-#define SND_PACMAN_MOVING                                      152
-#define SND_PACMAN_WAITING                                     153
-#define SND_PACMAN_DIGGING                                     154
-#define SND_DARK_YAMYAM_MOVING                         155
-#define SND_DARK_YAMYAM_WAITING                                156
-#define SND_DARK_YAMYAM_DIGGING                                157
-#define SND_PENGUIN_MOVING                                     158
-#define SND_PENGUIN_WAITING                                    159
-#define SND_PIG_MOVING                                 160
-#define SND_PIG_WAITING                                        161
-#define SND_PIG_DIGGING                                        162
-#define SND_DRAGON_MOVING                                      163
-#define SND_DRAGON_WAITING                                     164
-#define SND_DRAGON_ATTACKING                           165
-#define SND_GAME_STARTING                                      166
-#define SND_GAME_RUNNING_OUT_OF_TIME                   167
-#define SND_GAME_LEVELTIME_BONUS                               168
-#define SND_GAME_LOSING                                        169
-#define SND_GAME_WINNING                                       170
-#define SND_GAME_SOKOBAN_SOLVING                               171
-#define SND_DOOR_OPENING                                       172
-#define SND_DOOR_CLOSING                                       173
-#define SND_BACKGROUND_SCORES                          174
-#define SND_BACKGROUND_INFO                                    175
+#define SND_CLASS_ENVELOPE_OPENING                             103
+#define SND_CLASS_ENVELOPE_CLOSING                             104
+#define SND_INVISIBLE_SAND_DIGGING                             105
+#define SND_SHIELD_NORMAL_COLLECTING                   106
+#define SND_SHIELD_NORMAL_ACTIVE                               107
+#define SND_SHIELD_DEADLY_COLLECTING                   108
+#define SND_SHIELD_DEADLY_ACTIVE                               109
+#define SND_EXTRA_TIME_COLLECTING                              110
+#define SND_MOLE_MOVING                                        111
+#define SND_MOLE_WAITING                                       112
+#define SND_MOLE_DIGGING                                       113
+#define SND_CLASS_SWITCHGATE_SWITCH_ACTIVATING                 114
+#define SND_CLASS_SWITCHGATE_OPENING                           115
+#define SND_CLASS_SWITCHGATE_CLOSING                           116
+#define SND_CLASS_SWITCHGATE_PASSING                           117
+#define SND_TIMEGATE_SWITCH_ACTIVATING                 118
+#define SND_TIMEGATE_SWITCH_ACTIVE                             119
+#define SND_TIMEGATE_SWITCH_DEACTIVATING                       120
+#define SND_TIMEGATE_OPENING                           121
+#define SND_CLASS_TIMEGATE_CLOSING                             122
+#define SND_CLASS_TIMEGATE_PASSING                             123
+#define SND_CLASS_CONVEYOR_BELT_SWITCH_ACTIVATING              124
+#define SND_CLASS_CONVEYOR_BELT_ACTIVE                         125
+#define SND_CLASS_CONVEYOR_BELT_SWITCH_DEACTIVATING            126
+#define SND_LIGHT_SWITCH_ACTIVATING                            127
+#define SND_LIGHT_SWITCH_DEACTIVATING                  128
+#define SND_DX_SUPABOMB_PUSHING                                129
+#define SND_TRAP_DIGGING                                       130
+#define SND_TRAP_ACTIVATING                                    131
+#define SND_CLASS_TUBE_WALKING                                 132
+#define SND_AMOEBA_TURNING_TO_GEM                              133
+#define SND_AMOEBA_TURNING_TO_ROCK                             134
+#define SND_SPEED_PILL_COLLECTING                              135
+#define SND_DYNABOMB_INCREASE_NUMBER_COLLECTING                136
+#define SND_DYNABOMB_INCREASE_SIZE_COLLECTING          137
+#define SND_DYNABOMB_INCREASE_POWER_COLLECTING         138
+#define SND_CLASS_DYNABOMB_DROPPING                            139
+#define SND_CLASS_DYNABOMB_ACTIVE                              140
+#define SND_SATELLITE_MOVING                           141
+#define SND_SATELLITE_WAITING                          142
+#define SND_SATELLITE_PUSHING                          143
+#define SND_LAMP_ACTIVATING                                    144
+#define SND_LAMP_DEACTIVATING                          145
+#define SND_TIME_ORB_FULL_COLLECTING                   146
+#define SND_TIME_ORB_FULL_IMPACT                               147
+#define SND_TIME_ORB_EMPTY_PUSHING                             148
+#define SND_TIME_ORB_EMPTY_IMPACT                              149
+#define SND_GAME_OF_LIFE_WAITING                               150
+#define SND_GAME_OF_LIFE_GROWING                               151
+#define SND_BIOMAZE_WAITING                                    152
+#define SND_BIOMAZE_GROWING                                    153
+#define SND_PACMAN_MOVING                                      154
+#define SND_PACMAN_WAITING                                     155
+#define SND_PACMAN_DIGGING                                     156
+#define SND_DARK_YAMYAM_MOVING                         157
+#define SND_DARK_YAMYAM_WAITING                                158
+#define SND_DARK_YAMYAM_DIGGING                                159
+#define SND_PENGUIN_MOVING                                     160
+#define SND_PENGUIN_WAITING                                    161
+#define SND_PIG_MOVING                                 162
+#define SND_PIG_WAITING                                        163
+#define SND_PIG_DIGGING                                        164
+#define SND_DRAGON_MOVING                                      165
+#define SND_DRAGON_WAITING                                     166
+#define SND_DRAGON_ATTACKING                           167
+#define SND_GAME_STARTING                                      168
+#define SND_GAME_RUNNING_OUT_OF_TIME                   169
+#define SND_GAME_LEVELTIME_BONUS                               170
+#define SND_GAME_LOSING                                        171
+#define SND_GAME_WINNING                                       172
+#define SND_GAME_SOKOBAN_SOLVING                               173
+#define SND_DOOR_OPENING                                       174
+#define SND_DOOR_CLOSING                                       175
+#define SND_BACKGROUND_SCORES                          176
+#define SND_BACKGROUND_INFO                                    177
 
-#define NUM_SOUND_FILES                                176
+#define NUM_SOUND_FILES                                178
 
 #endif /* CONF_SND_H */
index 2c903252e3bbcfad2a10b0afe6c3533efc841974..bdd4d30ef9c4c365b716b9a913d04679243e8c46 100644 (file)
@@ -1 +1 @@
-#define COMPILE_DATE_STRING "[2003-09-24 21:26]"
+#define COMPILE_DATE_STRING "[2003-09-26 03:45]"
index 0fb85a1a7fdc0c710f15e71333b11cfafc1ee6a8..4a95e613b748ce615ed76126edf1b9c587ac3b21 100644 (file)
@@ -1114,8 +1114,8 @@ static struct ValueTextInfo options_change_direct_action[] =
   { CE_TOUCHED_BY_PLAYER,      "touched by player"             },
   { CE_PRESSED_BY_PLAYER,      "pressed by player"             },
   { CE_PUSHED_BY_PLAYER,       "pushed by player"              },
-  { CE_ENTERED_BY_PLAYER,      "entered by player"             },
-  { CE_LEFT_BY_PLAYER,         "left by player"                },
+  { CE_ENTERED_BY_PLAYER,      "entered by player ..."         },
+  { CE_LEFT_BY_PLAYER,         "left by player ..."            },
   { CE_DROPPED_BY_PLAYER,      "dropped by player"             },
   { CE_COLLISION,              "collision"                     },
   { CE_IMPACT,                 "impact"                        },
@@ -1128,8 +1128,8 @@ static struct ValueTextInfo options_change_other_action[] =
   { CE_OTHER_GETS_TOUCHED,     "player touches"                },
   { CE_OTHER_GETS_PRESSED,     "player presses"                },
   { CE_OTHER_GETS_PUSHED,      "player pushes"                 },
-  { CE_OTHER_GETS_ENTERED,     "player enters"                 },
-  { CE_OTHER_GETS_LEFT,                "player leaves"                 },
+  { CE_OTHER_GETS_ENTERED,     "player enters ..."             },
+  { CE_OTHER_GETS_LEFT,                "player leaves ..."             },
   { CE_OTHER_GETS_DIGGED,      "player digs"                   },
   { CE_OTHER_GETS_COLLECTED,   "player collects"               },
   { CE_OTHER_GETS_DROPPED,     "player drops"                  },
index ef7fa51f4792121c18f8290f180e698e75eacc57..3c26c22fd2f41cdcf9417e4349ba91b179a363d2 100644 (file)
@@ -2811,20 +2811,6 @@ void LoadCustomElementDescriptions()
   freeSetupFileHash(setup_file_hash);
 }
 
-static int get_special_integer_from_string(char *string_raw)
-{
-  char *string = getStringToLower(string_raw);
-  int value = (strcmp(string, "none")  == 0 ? 0 :
-              strcmp(string, "short") == 0 ? 1 :
-              strcmp(string, "full")  == 0 ? 2 :
-              strcmp(string, "default")  == 0 ? 0 :
-              strcmp(string, "curtain")  == 0 ? 1 : -1);
-
-  free(string);
-
-  return value;
-}
-
 void LoadSpecialMenuDesignSettings()
 {
   char *filename = getCustomArtworkConfigFilename(ARTWORK_TYPE_GRAPHICS);
@@ -2835,15 +2821,9 @@ void LoadSpecialMenuDesignSettings()
   for (i=0; image_config_vars[i].token != NULL; i++)
     for (j=0; image_config[j].token != NULL; j++)
       if (strcmp(image_config_vars[i].token, image_config[j].token) == 0)
-      {
-       if (strcmp(image_config_vars[i].token, "game.envelope.anim_mode") == 0
-           || strcmp(image_config_vars[i].token, "door.anim_mode") == 0)
-         *image_config_vars[i].value =
-           get_special_integer_from_string(image_config[j].value);
-       else
-         *image_config_vars[i].value =
-           get_integer_from_string(image_config[j].value);
-      }
+       *image_config_vars[i].value =
+         get_auto_parameter_value(image_config_vars[i].token,
+                                  image_config[j].value);
 
   if ((setup_file_hash = loadSetupFileHash(filename)) == NULL)
     return;
@@ -2869,13 +2849,8 @@ void LoadSpecialMenuDesignSettings()
     char *value = getHashEntry(setup_file_hash, image_config_vars[i].token);
 
     if (value != NULL)
-    {
-      if (strcmp(image_config_vars[i].token, "game.envelope.anim_mode") == 0
-         || strcmp(image_config_vars[i].token, "door.anim_mode") == 0)
-       *image_config_vars[i].value = get_special_integer_from_string(value);
-      else
-       *image_config_vars[i].value = get_integer_from_string(value);
-    }
+      *image_config_vars[i].value =
+       get_auto_parameter_value(image_config_vars[i].token, value);
   }
 
   freeSetupFileHash(setup_file_hash);
index e38715806ecbef9c6ff0d5ff7efbc689e41d6af2..17eaef58990f47d39e4de9920cbbdeedd94b64a0 100644 (file)
@@ -1085,6 +1085,8 @@ void InitGame()
   game.balloon_dir = MV_NO_MOVING;
   game.explosions_delayed = TRUE;
 
+  game.envelope_active = FALSE;
+
   for (i=0; i<4; i++)
   {
     game.belt_dir[i] = MV_NO_MOVING;
@@ -2377,7 +2379,7 @@ void Explode(int ex, int ey, int phase, int mode)
 
     TestIfElementTouchesCustomElement(x, y);
 
-    if (CAN_BE_CRUMBLED(element))
+    if (GFX_CRUMBLED(element))
       DrawLevelFieldCrumbledSandNeighbours(x, y);
 
     if (IS_PLAYER(x, y) && !PLAYERINFO(x,y)->present)
@@ -3830,6 +3832,7 @@ void StartMoving(int x, int y)
 #if 1
 
 #if 0
+    /* TEST: bug where player gets not killed by falling rock ... */
     else if (CAN_SMASH(element) &&
             (Feld[x][y + 1] == EL_BLOCKED ||
              IS_PLAYER(x, y + 1)) &&
@@ -5423,7 +5426,7 @@ static void ChangeElementNowExt(int x, int y, int target_element)
 
   DrawLevelField(x, y);
 
-  if (CAN_BE_CRUMBLED(Feld[x][y]))
+  if (GFX_CRUMBLED(Feld[x][y]))
     DrawLevelFieldCrumbledSandNeighbours(x, y);
 
   TestIfBadThingTouchesHero(x, y);
@@ -7637,7 +7640,7 @@ int DigField(struct PlayerInfo *player,
          GfxElement[x][y] = GFX_ELEMENT(element);
 #else
          GfxElement[x][y] =
-           (CAN_BE_CRUMBLED(element) ? EL_SAND : GFX_ELEMENT(element));
+           (GFX_CRUMBLED(element) ? EL_SAND : GFX_ELEMENT(element));
 #endif
          player->is_digging = TRUE;
        }
index 3c91f4f53752b15706c0b0a49958382eef3ef4ae..1af2f48ee58f11b1eeb9b9126c2353df3efee9fa 100644 (file)
@@ -748,11 +748,16 @@ static int get_element_from_token(char *token)
 static void set_graphic_parameters(int graphic, char **parameter_raw)
 {
   Bitmap *src_bitmap = getBitmapFromImageID(graphic);
+  boolean special_envelope_graphic;
   int parameter[NUM_GFX_ARGS];
   int anim_frames_per_row = 1, anim_frames_per_col = 1;
   int anim_frames_per_line = 1;
   int i;
 
+  special_envelope_graphic = (graphic == IMG_GAME_ENVELOPE_BACKGROUND ||
+                             (graphic >= IMG_GAME_ENVELOPE_1_BACKGROUND &&
+                              graphic <= IMG_GAME_ENVELOPE_4_BACKGROUND));
+
   /* get integer values from string parameters */
   for (i=0; i < NUM_GFX_ARGS; i++)
   {
@@ -842,7 +847,7 @@ static void set_graphic_parameters(int graphic, char **parameter_raw)
     graphic_info[graphic].anim_delay = 1;
 
   graphic_info[graphic].anim_mode = parameter[GFX_ARG_ANIM_MODE];
-  if (graphic_info[graphic].anim_frames == 1)
+  if (graphic_info[graphic].anim_frames == 1 && !special_envelope_graphic)
     graphic_info[graphic].anim_mode = ANIM_NONE;
 
   /* automatically determine correct start frame, if not defined */
@@ -879,6 +884,10 @@ static void set_graphic_parameters(int graphic, char **parameter_raw)
 
   /* this is only used for drawing envelope graphics */
   graphic_info[graphic].draw_masked = parameter[GFX_ARG_DRAW_MASKED];
+
+  /* global envelope settings override specific settings, if undefined */
+  if (special_envelope_graphic && graphic_info[graphic].bitmap == NULL)
+    graphic_info[graphic] = graphic_info[IMG_GAME_ENVELOPE_BACKGROUND];
 }
 
 static void InitGraphicInfo()
@@ -1393,9 +1402,9 @@ void InitElementPropertiesStatic()
 
     /* !!! maybe this should better be handled by 'ep_diggable' !!! */
 #if 1
-    EL_SP_BUGGY_BASE_ACTIVE,
-    EL_TRAP_ACTIVE,
     EL_LANDMINE,
+    EL_TRAP_ACTIVE,
+    EL_SP_BUGGY_BASE_ACTIVE,
 #endif
     -1
   };
@@ -1794,6 +1803,16 @@ void InitElementPropertiesStatic()
     -1
   };
 
+  static int ep_droppable[] =
+  {
+    -1
+  };
+
+  static int ep_can_explode_1x1[] =
+  {
+    -1
+  };
+
   static int ep_pushable[] =
   {
     EL_ROCK,
@@ -1813,15 +1832,6 @@ void InitElementPropertiesStatic()
     -1
   };
 
-  static int ep_can_be_crumbled[] =
-  {
-    EL_SAND,
-    EL_LANDMINE,
-    EL_TRAP,
-    EL_TRAP_ACTIVE,
-    -1
-  };
-
   static int ep_player[] =
   {
     EL_PLAYER_1,
@@ -2546,6 +2556,20 @@ void InitElementPropertiesStatic()
     -1
   };
 
+  static int ep_em_slippery_wall[] =
+  {
+    -1
+  };
+
+  static int ep_gfx_crumbled[] =
+  {
+    EL_SAND,
+    EL_LANDMINE,
+    EL_TRAP,
+    EL_TRAP_ACTIVE,
+    -1
+  };
+
   static struct
   {
     int *elements;
@@ -2574,10 +2598,10 @@ void InitElementPropertiesStatic()
     { ep_passable_over,                EP_PASSABLE_OVER        },
     { ep_passable_inside,      EP_PASSABLE_INSIDE      },
     { ep_passable_under,       EP_PASSABLE_UNDER       },
+    { ep_droppable,            EP_DROPPABLE            },
+    { ep_can_explode_1x1,      EP_CAN_EXPLODE_1X1      },
     { ep_pushable,             EP_PUSHABLE             },
 
-    { ep_can_be_crumbled,      EP_CAN_BE_CRUMBLED      },
-
     { ep_player,               EP_PLAYER               },
     { ep_can_pass_magic_wall,  EP_CAN_PASS_MAGIC_WALL  },
     { ep_switchable,           EP_SWITCHABLE           },
@@ -2602,6 +2626,10 @@ void InitElementPropertiesStatic()
     { ep_active_bomb,          EP_ACTIVE_BOMB          },
     { ep_inactive,             EP_INACTIVE             },
 
+    { ep_em_slippery_wall,     EP_EM_SLIPPERY_WALL     },
+
+    { ep_gfx_crumbled,         EP_GFX_CRUMBLED         },
+
     { NULL,                    -1                      }
   };
 
@@ -2690,7 +2718,6 @@ void InitElementPropertiesEngine(int engine_version)
     EP_BELT_SWITCH,
     EP_WALKABLE_UNDER,
     EP_EM_SLIPPERY_WALL,
-    EP_CAN_BE_CRUMBLED,
   };
 #endif
 
@@ -2707,8 +2734,6 @@ void InitElementPropertiesEngine(int engine_version)
     EP_CAN_SMASH_EVERYTHING,
     EP_PUSHABLE,
 
-    EP_CAN_BE_CRUMBLED,
-
     EP_PLAYER,
     EP_GEM,
     EP_FOOD_DARK_YAMYAM,
@@ -2839,22 +2864,15 @@ void InitElementPropertiesEngine(int engine_version)
     SET_PROPERTY(i, EP_CAN_EXPLODE_3X3, (CAN_EXPLODE(i) &&
                                         !CAN_EXPLODE_1X1(i)));
 
-    /* ---------- CAN_BE_CRUMBLED ------------------------------------------ */
-    SET_PROPERTY(i, EP_CAN_BE_CRUMBLED,
-                element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
-
-#if 0
-    if (CAN_BE_CRUMBLED(i))
-      printf("::: '%s' can be crumbled [%d]\n",
-            element_info[i].token_name,
-            element_info[i].crumbled[ACTION_DEFAULT]);
-#endif
-
     /* ---------- CAN_CHANGE ----------------------------------------------- */
     SET_PROPERTY(i, EP_CAN_CHANGE, FALSE);     /* default: cannot change */
     for (j=0; j < element_info[i].num_change_pages; j++)
       if (element_info[i].change_page[j].can_change)
        SET_PROPERTY(i, EP_CAN_CHANGE, TRUE);
+
+    /* ---------- GFX_CRUMBLED --------------------------------------------- */
+    SET_PROPERTY(i, EP_GFX_CRUMBLED,
+                element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
   }
 
 #if 0
index 0d5a658e848b0bfef7f41385c9392a8a77ae4e3e..50a713f456be8c011b279044121e088516d57042 100644 (file)
@@ -1376,32 +1376,41 @@ int get_integer_from_string(char *s)
 {
   static char *number_text[][3] =
   {
-    { "0", "zero", "null", },
-    { "1", "one", "first" },
-    { "2", "two", "second" },
-    { "3", "three", "third" },
-    { "4", "four", "fourth" },
-    { "5", "five", "fifth" },
-    { "6", "six", "sixth" },
-    { "7", "seven", "seventh" },
-    { "8", "eight", "eighth" },
-    { "9", "nine", "ninth" },
-    { "10", "ten", "tenth" },
-    { "11", "eleven", "eleventh" },
-    { "12", "twelve", "twelfth" },
+    { "0",     "zero",         "null",         },
+    { "1",     "one",          "first"         },
+    { "2",     "two",          "second"        },
+    { "3",     "three",        "third"         },
+    { "4",     "four",         "fourth"        },
+    { "5",     "five",         "fifth"         },
+    { "6",     "six",          "sixth"         },
+    { "7",     "seven",        "seventh"       },
+    { "8",     "eight",        "eighth"        },
+    { "9",     "nine",         "ninth"         },
+    { "10",    "ten",          "tenth"         },
+    { "11",    "eleven",       "eleventh"      },
+    { "12",    "twelve",       "twelfth"       },
+
+    { NULL,    NULL,           NULL            },
   };
 
   int i, j;
   char *s_lower = getStringToLower(s);
   int result = -1;
 
-  for (i=0; i<13; i++)
-    for (j=0; j<3; j++)
+  for (i=0; number_text[i][0] != NULL; i++)
+    for (j=0; j < 3; j++)
       if (strcmp(s_lower, number_text[i][j]) == 0)
        result = i;
 
   if (result == -1)
-    result = atoi(s);
+  {
+    if (strcmp(s_lower, "false") == 0)
+      result = 0;
+    else if (strcmp(s_lower, "true") == 0)
+      result = 1;
+    else
+      result = atoi(s);
+  }
 
   free(s_lower);
 
@@ -1646,27 +1655,29 @@ static boolean string_has_parameter(char *s, char *s_contained)
   return string_has_parameter(substring, s_contained);
 }
 
-int get_parameter_value(char *token, char *value_raw, int type)
+int get_parameter_value(char *suffix, char *value_raw, int type)
 {
   char *value = getStringToLower(value_raw);
   int result = 0;      /* probably a save default value */
 
-  if (strcmp(token, ".direction") == 0)
+  if (strcmp(suffix, ".direction") == 0)
   {
     result = (strcmp(value, "left")  == 0 ? MV_LEFT :
              strcmp(value, "right") == 0 ? MV_RIGHT :
              strcmp(value, "up")    == 0 ? MV_UP :
              strcmp(value, "down")  == 0 ? MV_DOWN : MV_NO_MOVING);
   }
-  else if (strcmp(token, ".anim_mode") == 0)
-  {
-    result = (string_has_parameter(value, "loop")      ? ANIM_LOOP :
-             string_has_parameter(value, "linear")    ? ANIM_LINEAR :
-             string_has_parameter(value, "pingpong")  ? ANIM_PINGPONG :
-             string_has_parameter(value, "pingpong2") ? ANIM_PINGPONG2 :
-             string_has_parameter(value, "random")    ? ANIM_RANDOM :
-             string_has_parameter(value, "none")      ? ANIM_NONE :
-             ANIM_LOOP);
+  else if (strcmp(suffix, ".anim_mode") == 0)
+  {
+    result = (string_has_parameter(value, "none")       ? ANIM_NONE :
+             string_has_parameter(value, "loop")       ? ANIM_LOOP :
+             string_has_parameter(value, "linear")     ? ANIM_LINEAR :
+             string_has_parameter(value, "pingpong")   ? ANIM_PINGPONG :
+             string_has_parameter(value, "pingpong2")  ? ANIM_PINGPONG2 :
+             string_has_parameter(value, "random")     ? ANIM_RANDOM :
+             string_has_parameter(value, "horizontal") ? ANIM_HORIZONTAL :
+             string_has_parameter(value, "vertical")   ? ANIM_VERTICAL :
+             ANIM_DEFAULT);
 
     if (string_has_parameter(value, "reverse"))
       result |= ANIM_REVERSE;
@@ -1684,6 +1695,20 @@ int get_parameter_value(char *token, char *value_raw, int type)
   return result;
 }
 
+int get_auto_parameter_value(char *token, char *value_raw)
+{
+  char *suffix;
+
+  if (token == NULL || value_raw == NULL)
+    return ARG_UNDEFINED_VALUE;
+
+  suffix = strrchr(token, '.');
+  if (suffix == NULL)
+    suffix = token;
+
+  return get_parameter_value(suffix, value_raw, TYPE_INTEGER);
+}
+
 static void FreeCustomArtworkList(struct ArtworkListInfo *,
                                  struct ListNodeInfo ***, int *);
 
index 7fd0a1a5b83e25c9df3860f1fbf6d7b72beed304..71c0d7fe171ffcfb47a7e85a91089676191703e3 100644 (file)
@@ -160,6 +160,7 @@ boolean FileIsMusic(char *);
 boolean FileIsArtworkType(char *, int);
 
 int get_parameter_value(char *, char *, int);
+int get_auto_parameter_value(char *, char *);
 
 struct FileInfo *getFileListFromConfigList(struct ConfigInfo *,
                                           struct ConfigInfo *, char **, int);
index a48ccf05551863bd0c278f9abf88d81286793f74..007e02d3542f7583735f555a5889b0f71a839e30 100644 (file)
 #define ANIM_RANDOM            (1 << 4)
 #define ANIM_REVERSE           (1 << 5)
 
-#if 0
-/* values for special animation modes */
-#define ANIM_DEFAULT           (1 << 6)
-#define ANIM_QUICK             (1 << 7)
-#define ANIM_SPECIAL1          (1 << 8)
-#endif
+/* values for special (non game element) animation modes */
+#define ANIM_HORIZONTAL                (1 << 6)
+#define ANIM_VERTICAL          (1 << 7)
+
+#define ANIM_DEFAULT           ANIM_LOOP
 
 /* values for redraw_mask */
 #define REDRAW_NONE            (0)
index f3c946f44685bbf0876bbef8fde7dd05ef0a3c60..309f1ec97db488f9fd2f13ed69044e51ea4f2b18 100644 (file)
@@ -96,7 +96,7 @@ struct SetupInfo      setup;
 struct GameInfo                game;
 struct GlobalInfo      global;
 struct MenuInfo                menu;
-struct DoorInfo                door;
+struct DoorInfo                door_1, door_2;
 struct GraphicInfo     *graphic_info = NULL;
 struct SoundInfo       *sound_info = NULL;
 
@@ -3747,11 +3747,12 @@ struct TokenIntPtrInfo image_config_vars[] =
   { "menu.list_size.SCORES",   &menu.list_size[GFX_SPECIAL_ARG_SCORES]    },
   { "menu.list_size.INFO",     &menu.list_size[GFX_SPECIAL_ARG_INFO]      },
 
-  { "door.step_offset",                &door.step_offset                          },
-  { "door.step_delay",         &door.step_delay                           },
-  { "door.anim_mode",          &door.anim_mode                            },
-
-  { "game.envelope.anim_mode", &game.envelope.anim_mode                   },
+  { "door_1.step_offset",      &door_1.step_offset                        },
+  { "door_1.step_delay",       &door_1.step_delay                         },
+  { "door_1.anim_mode",                &door_1.anim_mode                          },
+  { "door_2.step_offset",      &door_2.step_offset                        },
+  { "door_2.step_delay",       &door_2.step_delay                         },
+  { "door_2.anim_mode",                &door_2.anim_mode                          },
 
   { NULL,                      NULL,                                      }
 };
index 9739a87cbb032590ee8ded85d20107f2b36c7a12..8557db58c7b776715ebe91893e0b9f2b3158ce11 100644 (file)
 #define EP_CAN_EXPLODE_1X1     23
 #define EP_PUSHABLE            24
 
+/* values for pre-defined properties */
+#define EP_PLAYER              32
+#define EP_CAN_PASS_MAGIC_WALL 33
+#define EP_SWITCHABLE          34
+#define EP_BD_ELEMENT          35
+#define EP_SP_ELEMENT          36
+#define EP_SB_ELEMENT          37
+#define EP_GEM                 38
+#define EP_FOOD_DARK_YAMYAM    39
+#define EP_FOOD_PENGUIN                40
+#define EP_FOOD_PIG            41
+#define EP_HISTORIC_WALL       42
+#define EP_HISTORIC_SOLID      43
+#define EP_CLASSIC_ENEMY       44
+#define EP_BELT                        45
+#define EP_BELT_ACTIVE         46
+#define EP_BELT_SWITCH         47
+#define EP_TUBE                        48
+#define EP_KEYGATE             49
+#define EP_AMOEBOID            50
+#define EP_AMOEBALIVE          51
+#define EP_HAS_CONTENT         52
+#define EP_ACTIVE_BOMB         53
+#define EP_INACTIVE            54
+
 /* values for special configurable properties (depending on level settings) */
-#define EP_EM_SLIPPERY_WALL    32
+#define EP_EM_SLIPPERY_WALL    35
 
 /* values for special graphics properties (no effect on game engine) */
-#define EP_CAN_BE_CRUMBLED     33
-
-/* values for pre-defined properties */
-#define EP_PLAYER              34
-#define EP_CAN_PASS_MAGIC_WALL 35
-#define EP_SWITCHABLE          36
-#define EP_BD_ELEMENT          37
-#define EP_SP_ELEMENT          38
-#define EP_SB_ELEMENT          39
-#define EP_GEM                 40
-#define EP_FOOD_DARK_YAMYAM    41
-#define EP_FOOD_PENGUIN                42
-#define EP_FOOD_PIG            43
-#define EP_HISTORIC_WALL       44
-#define EP_HISTORIC_SOLID      45
-#define EP_CLASSIC_ENEMY       46
-#define EP_BELT                        47
-#define EP_BELT_ACTIVE         48
-#define EP_BELT_SWITCH         49
-#define EP_TUBE                        50
-#define EP_KEYGATE             51
-#define EP_AMOEBOID            52
-#define EP_AMOEBALIVE          53
-#define EP_HAS_CONTENT         54
-#define EP_ACTIVE_BOMB         55
-#define EP_INACTIVE            56
+#define EP_GFX_CRUMBLED                56
 
 /* values for derived properties (determined from properties above) */
 #define EP_ACCESSIBLE_OVER     57
 #define IS_EM_SLIPPERY_WALL(e) HAS_PROPERTY(e, EP_EM_SLIPPERY_WALL)
 
 /* macros for special graphics properties */
-#define CAN_BE_CRUMBLED(e)     HAS_PROPERTY(GFX_ELEMENT(e),EP_CAN_BE_CRUMBLED)
+#define GFX_CRUMBLED(e)                HAS_PROPERTY(GFX_ELEMENT(e), EP_GFX_CRUMBLED)
 
 /* macros for pre-defined properties */
 #define ELEM_IS_PLAYER(e)      HAS_PROPERTY(e, EP_PLAYER)
@@ -1100,11 +1100,6 @@ struct DoorInfo
   int anim_mode;
 };
 
-struct EnvelopeInfo
-{
-  int anim_mode;
-};
-
 struct HiScore
 {
   char Name[MAX_PLAYER_NAME_LEN + 1];
@@ -1247,7 +1242,7 @@ struct GameInfo
   int initial_move_delay;
   int initial_move_delay_value;
 
-  struct EnvelopeInfo envelope;
+  boolean envelope_active;
 
   /* variable within running game */
   int yamyam_content_nr;
@@ -1527,7 +1522,7 @@ extern struct TapeInfo            tape;
 extern struct GameInfo         game;
 extern struct GlobalInfo       global;
 extern struct MenuInfo         menu;
-extern struct DoorInfo         door;
+extern struct DoorInfo         door_1, door_2;
 extern struct ElementInfo      element_info[];
 extern struct ElementActionInfo        element_action_info[];
 extern struct ElementDirectionInfo element_direction_info[];
index 61210a5a6ebcba0af91af8766cf0047d935975bb..4fdb41205329838f3a0a77c71bfb87cb173223d5 100644 (file)
@@ -72,7 +72,7 @@ void SetDrawtoField(int mode)
 
 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
 {
-  if (game_status == GAME_MODE_PLAYING)
+  if (game_status == GAME_MODE_PLAYING && !game.envelope_active)
   {
     if (force_redraw)
     {
@@ -506,7 +506,7 @@ inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
 
   DrawGraphicAnimation(sx, sy, graphic);
 
-  if (CAN_BE_CRUMBLED(Feld[x][y]))
+  if (GFX_CRUMBLED(Feld[x][y]))
     DrawLevelFieldCrumbledSand(x, y);
 }
 
@@ -525,7 +525,7 @@ void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
 
   DrawGraphicAnimation(sx, sy, graphic);
 
-  if (CAN_BE_CRUMBLED(element))
+  if (GFX_CRUMBLED(element))
     DrawLevelFieldCrumbledSand(x, y);
 }
 
@@ -671,7 +671,7 @@ void DrawPlayer(struct PlayerInfo *player)
     if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
     {
 #if 1
-      if (CAN_BE_CRUMBLED(GfxElement[jx][jy]))
+      if (GFX_CRUMBLED(GfxElement[jx][jy]))
        DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
 #else
       if (GfxElement[jx][jy] == EL_SAND)
@@ -688,13 +688,6 @@ void DrawPlayer(struct PlayerInfo *player)
     }
     else
     {
-#if 0
-      if (player->is_collecting && GfxElement[jx][jy] == EL_ENVELOPE)
-      {
-       ShowEnvelope();
-      }
-#endif
-
       GfxElement[jx][jy] = EL_UNDEFINED;
 
       DrawLevelField(jx, jy);
@@ -1238,7 +1231,7 @@ static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
             GfxElement[x][y] : Feld[x][y]);
 
   /* crumble field itself */
-  if (CAN_BE_CRUMBLED(element) && !IS_MOVING(x, y))
+  if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
   {
     if (!IN_SCR_FIELD(sx, sy))
       return;
@@ -1253,14 +1246,14 @@ static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
       element = (IN_LEV_FIELD(xx, yy) ? Feld[xx][yy] : BorderElement);
 
       /* check if neighbour field is of same type */
-      if (CAN_BE_CRUMBLED(element) && !IS_MOVING(xx, yy))
+      if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
        continue;
 
 #if 0
       if (Feld[x][y] == EL_CUSTOM_START + 123)
        printf("::: crumble [%d] THE CHAOS ENGINE (%d, %d): %d, %d\n",
               i, Feld[x][y], element,
-              CAN_BE_CRUMBLED(element), IS_MOVING(x, y));
+              GFX_CRUMBLED(element), IS_MOVING(x, y));
 #endif
 
       if (i == 1 || i == 2)
@@ -1299,7 +1292,7 @@ static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
 
       if (!IN_LEV_FIELD(xx, yy) ||
          !IN_SCR_FIELD(sxx, syy) ||
-         !CAN_BE_CRUMBLED(Feld[xx][yy]) ||
+         !GFX_CRUMBLED(Feld[xx][yy]) ||
          IS_MOVING(xx, yy))
        continue;
 
@@ -1388,7 +1381,7 @@ void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
 
     if (!IN_LEV_FIELD(xx, yy) ||
        !IN_SCR_FIELD(sxx, syy) ||
-       !CAN_BE_CRUMBLED(Feld[xx][yy]) ||
+       !GFX_CRUMBLED(Feld[xx][yy]) ||
        IS_MOVING(xx, yy))
       continue;
 
@@ -1563,13 +1556,12 @@ void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
     DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
 }
 
-#if 1
-void DrawEnvelopeBackground(int startx, int starty, int x, int y,
-                           int xsize, int ysize, int font_nr)
+void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
+                           int x, int y, int xsize, int ysize, int font_nr)
 {
   int font_width  = getFontWidth(font_nr);
   int font_height = getFontHeight(font_nr);
-  int graphic = IMG_GAME_ENVELOPE_BACKGROUND;
+  int graphic = IMG_GAME_ENVELOPE_1_BACKGROUND + envelope_nr;
   Bitmap *src_bitmap;
   int src_x, src_y;
   int dst_x = SX + startx + x * font_width;
@@ -1607,58 +1599,31 @@ void DrawEnvelopeBackground(int startx, int starty, int x, int y,
               dst_x, dst_y);
 }
 
-#else
-
-void DrawEnvelopeBackground(int dst_x, int dst_y, int ex, int ey, int font_nr)
-{
-  int font_width = getFontWidth(font_nr);
-  int font_height = getFontHeight(font_nr);
-  int graphic = IMG_GAME_ENVELOPE_BACKGROUND;
-  Bitmap *src_bitmap;
-  int src_x, src_y;
-  int width = graphic_info[graphic].width;
-  int height = graphic_info[graphic].height;
-  boolean draw_masked = graphic_info[graphic].draw_masked;
-
-  getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
-
-  if (src_bitmap == NULL)
-  {
-    ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
-    return;
-  }
-
-  src_x += (ex == -1 ? 0 : ex == +1 ? width  - font_width  : font_width);
-  src_y += (ey == -1 ? 0 : ey == +1 ? height - font_height : font_height);
-
-  if (draw_masked)
-  {
-    SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
-                 dst_x - src_x, dst_y - src_y);
-    BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
-                    dst_x, dst_y);
-  }
-  else
-    BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
-              dst_x, dst_y);
-}
-#endif
-
 void ShowEnvelope(int envelope_nr)
 {
-  int graphic = IMG_GAME_ENVELOPE_BACKGROUND;
+  int element = EL_ENVELOPE_1 + envelope_nr;
+  int graphic = IMG_GAME_ENVELOPE_1_BACKGROUND + envelope_nr;
+  int sound_opening = element_info[element].sound[ACTION_OPENING];
+  int sound_closing = element_info[element].sound[ACTION_CLOSING];
   boolean draw_masked = graphic_info[graphic].draw_masked;
+  int anim_mode = graphic_info[graphic].anim_mode;
   int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_ON_BACKGROUND);
   int font_nr = FONT_TEXT_1;
   int font_width = getFontWidth(font_nr);
   int font_height = getFontHeight(font_nr);
   boolean ffwd_delay = (tape.playing && tape.fast_forward);
-  int anim_delay = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
-  int wait_delay = (ffwd_delay ? 500 : 1000);
+  unsigned long anim_delay = 0;
+  int anim_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
+  int wait_delay_value = (ffwd_delay ? 500 : 1000);
   int start_pos_vertically = 0;
   int i, x, y;
 
-  if (game.envelope.anim_mode > 1)
+  game.envelope_active = TRUE;
+
+  if (anim_mode != ANIM_NONE)
+    PlaySoundStereo(sound_opening, SOUND_MIDDLE);
+
+  if (anim_mode == ANIM_DEFAULT)
   {
     /* open envelope window horizontally */
     for (i = 0; i <= level.envelope_xsize[envelope_nr]; i++)
@@ -1674,29 +1639,18 @@ void ShowEnvelope(int envelope_nr)
 
       SetDrawtoField(DRAW_BACKBUFFER);
 
-#if 1
-      for (y=0; y < ysize; y++) for (x=0; x < xsize; x++)
-       DrawEnvelopeBackground(startx, starty, x, y, xsize, ysize, font_nr);
-#else
       for (y=0; y < ysize; y++) for (x=0; x < xsize; x++)
-      {
-       int sx = SX + startx + x * font_width;
-       int sy = SY + starty + y * font_height;
-       int ex = (x == 0 ? -1 : x == xsize - 1 ? +1 : 0);
-       int ey = (y == 0 ? -1 : y == ysize - 1 ? +1 : 0);
-
-       DrawEnvelopeBackground(sx, sy, ex, ey, font_nr);
-      }
-#endif
+       DrawEnvelopeBackground(envelope_nr, startx, starty, x, y, xsize, ysize,
+                              font_nr);
 
       redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
       BackToFront();
 
-      Delay(anim_delay / 2);
+      WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
     }
   }
 
-  if (game.envelope.anim_mode < 1)
+  if (anim_mode == ANIM_NONE)
     start_pos_vertically = level.envelope_ysize[envelope_nr];
 
   /* open envelope window vertically */
@@ -1713,20 +1667,9 @@ void ShowEnvelope(int envelope_nr)
 
     SetDrawtoField(DRAW_BACKBUFFER);
 
-#if 1
-    for (y=0; y < ysize; y++) for (x=0; x < xsize; x++)
-      DrawEnvelopeBackground(startx, starty, x, y, xsize, ysize, font_nr);
-#else
     for (y=0; y < ysize; y++) for (x=0; x < xsize; x++)
-    {
-      int sx = SX + startx + x * font_width;
-      int sy = SY + starty + y * font_height;
-      int ex = (x == 0 ? -1 : x == xsize - 1 ? +1 : 0);
-      int ey = (y == 0 ? -1 : y == ysize - 1 ? +1 : 0);
-
-      DrawEnvelopeBackground(sx, sy, ex, ey, font_nr);
-    }
-#endif
+      DrawEnvelopeBackground(envelope_nr, startx, starty, x, y, xsize, ysize,
+                            font_nr);
 
     DrawTextToTextArea(SX + startx + font_width, SY + starty + font_height,
                       level.envelope_text[envelope_nr], FONT_TEXT_1,
@@ -1735,15 +1678,18 @@ void ShowEnvelope(int envelope_nr)
     redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
     BackToFront();
 
-    Delay(anim_delay);
+    WaitUntilDelayReached(&anim_delay, anim_delay_value);
   }
 
   if (tape.playing)
-    Delay(wait_delay);
+    Delay(wait_delay_value);
   else
     WaitForEventToContinue();
 
-  if (game.envelope.anim_mode > 0)
+  if (anim_mode != ANIM_NONE)
+    PlaySoundStereo(sound_closing, SOUND_MIDDLE);
+
+  if (anim_mode != ANIM_NONE)
   {
     /* close envelope window vertically */
     for (i = level.envelope_ysize[envelope_nr]; i >= 0; i--)
@@ -1759,20 +1705,9 @@ void ShowEnvelope(int envelope_nr)
 
       SetDrawtoField(DRAW_BACKBUFFER);
 
-#if 1
       for (y=0; y < ysize; y++) for (x=0; x < xsize; x++)
-       DrawEnvelopeBackground(startx, starty, x, y, xsize, ysize, font_nr);
-#else
-      for (y=0; y < ysize; y++) for (x=0; x < xsize; x++)
-      {
-       int sx = SX + startx + x * font_width;
-       int sy = SY + starty + y * font_height;
-       int ex = (x == 0 ? -1 : x == xsize - 1 ? +1 : 0);
-       int ey = (y == 0 ? -1 : y == ysize - 1 ? +1 : 0);
-
-       DrawEnvelopeBackground(sx, sy, ex, ey, font_nr);
-      }
-#endif
+       DrawEnvelopeBackground(envelope_nr, startx, starty, x, y, xsize, ysize,
+                              font_nr);
 
       DrawTextToTextArea(SX + startx + font_width, SY + starty + font_height,
                         level.envelope_text[envelope_nr], FONT_TEXT_1,
@@ -1781,11 +1716,11 @@ void ShowEnvelope(int envelope_nr)
       redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
       BackToFront();
 
-      Delay(anim_delay);
+      WaitUntilDelayReached(&anim_delay, anim_delay_value);
     }
   }
 
-  if (game.envelope.anim_mode > 1)
+  if (anim_mode == ANIM_DEFAULT)
   {
     /* close envelope window horizontally */
     for (i = level.envelope_xsize[envelope_nr]; i >= 0; i--)
@@ -1801,28 +1736,19 @@ void ShowEnvelope(int envelope_nr)
 
       SetDrawtoField(DRAW_BACKBUFFER);
 
-#if 1
       for (y=0; y < ysize; y++) for (x=0; x < xsize; x++)
-       DrawEnvelopeBackground(startx, starty, x, y, xsize, ysize, font_nr);
-#else
-      for (y=0; y < ysize; y++) for (x=0; x < xsize; x++)
-      {
-       int sx = SX + startx + x * font_width;
-       int sy = SY + starty + y * font_height;
-       int ex = (x == 0 ? -1 : x == xsize - 1 ? +1 : 0);
-       int ey = (y == 0 ? -1 : y == ysize - 1 ? +1 : 0);
-
-       DrawEnvelopeBackground(sx, sy, ex, ey, font_nr);
-      }
-#endif
+       DrawEnvelopeBackground(envelope_nr, startx, starty, x, y, xsize, ysize,
+                              font_nr);
 
       redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
       BackToFront();
 
-      Delay(anim_delay / 2);
+      WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
     }
   }
 
+  game.envelope_active = FALSE;
+
   SetDrawtoField(DRAW_BUFFERED);
 
   redraw_mask |= REDRAW_FIELD;
@@ -2425,9 +2351,9 @@ unsigned int MoveDoor(unsigned int door_state)
 {
   static int door1 = DOOR_OPEN_1;
   static int door2 = DOOR_CLOSE_2;
-  static unsigned long door_delay = 0;
-  int x, start, stepsize = door.step_offset;
-  unsigned long door_delay_value = door.step_delay;
+  unsigned long door_delay = 0;
+  unsigned long door_delay_value = door_1.step_delay;
+  int stepsize = 1;
 
   if (door_state == DOOR_GET_STATE)
     return(door1 | door2);
@@ -2453,7 +2379,7 @@ unsigned int MoveDoor(unsigned int door_state)
 
   if (setup.quick_doors)
   {
-    stepsize = 20;
+    stepsize = 20;             /* must be choosen to always draw last frame */
     door_delay_value = 0;
 
     StopSound(SND_DOOR_OPENING);
@@ -2468,6 +2394,13 @@ unsigned int MoveDoor(unsigned int door_state)
 
   if (door_state & DOOR_ACTION)
   {
+    boolean door_1_done = !(door_state & DOOR_ACTION_1);
+    boolean door_2_done = !(door_state & DOOR_ACTION_2);
+    int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
+    int end = (door_state & DOOR_ACTION_1 &&
+              door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
+    int x;
+
     if (!(door_state & DOOR_NO_DELAY))
     {
       /* opening door sound has priority over simultaneously closing door */
@@ -2477,29 +2410,61 @@ unsigned int MoveDoor(unsigned int door_state)
        PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
     }
 
-    start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
-
-    for(x=start; x<=DXSIZE; x+=stepsize)
+    for(x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
     {
       Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
       GC gc = bitmap->stored_clip_gc;
 
-      if (!(door_state & DOOR_NO_DELAY))
-       WaitUntilDelayReached(&door_delay, door_delay_value);
-
       if (door_state & DOOR_ACTION_1)
       {
-       int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
-       int j = (door.anim_mode == 0 ? (DXSIZE - i) / 3 : 0);
+       int a = MIN(x * door_1.step_offset, end);
+       int i = (door_state & DOOR_OPEN_1 ? end - a : a);
 
-       BlitBitmap(bitmap_db_door, drawto,
-                  DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
-                  DXSIZE,DYSIZE - i/2, DX, DY);
+       if (x <= a)
+       {
+         BlitBitmap(bitmap_db_door, drawto,
+                    DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
+                    DXSIZE,DYSIZE - i / 2, DX, DY);
 
-       ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
+         ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
+       }
 
-       if (door.anim_mode == 0)
+       if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
        {
+         int src1_x = DXSIZE,          src1_y = DOOR_GFX_PAGEY1;
+         int dst1_x = DX + DXSIZE - i, dst1_y = DY;
+         int src2_x = DXSIZE - i,      src2_y = DOOR_GFX_PAGEY1;
+         int dst2_x = DX,              dst2_y = DY;
+         int width = i, height = DYSIZE;
+
+         SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
+         BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
+                          dst1_x, dst1_y);
+
+         SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
+         BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
+                          dst2_x, dst2_y);
+       }
+       else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
+       {
+         int src1_x = DXSIZE,          src1_y = DOOR_GFX_PAGEY1;
+         int dst1_x = DX,              dst1_y = DY + DYSIZE - i;
+         int src2_x = 0,               src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
+         int dst2_x = DX,              dst2_y = DY;
+         int width = DXSIZE, height = i;
+
+         SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
+         BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
+                          dst1_x, dst1_y);
+
+         SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
+         BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
+                          dst2_x, dst2_y);
+       }
+       else if (x <= DXSIZE)   /* ANIM_DEFAULT */
+       {
+         int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
+
          SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
          BlitBitmapMasked(bitmap, drawto,
                           DXSIZE, DOOR_GFX_PAGEY1, i, 77,
@@ -2530,59 +2495,92 @@ unsigned int MoveDoor(unsigned int door_state)
                           DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
                           DX + DXSIZE - i, DY + 203 + j);
        }
-       else
-       {
-         SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
-         BlitBitmapMasked(bitmap, drawto,
-                          DXSIZE, DOOR_GFX_PAGEY1, i, DYSIZE,
-                          DX + DXSIZE - i, DY);
-
-         SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - DOOR_GFX_PAGEY1);
-         BlitBitmapMasked(bitmap, drawto,
-                          DXSIZE - i, DOOR_GFX_PAGEY1, i, DYSIZE,
-                          DX, DY);
-       }
 
        redraw_mask |= REDRAW_DOOR_1;
+       door_1_done = (a == end);
       }
 
       if (door_state & DOOR_ACTION_2)
       {
-       int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
-       int j = (VXSIZE - i) / 3;
-
-       BlitBitmap(bitmap_db_door, drawto,
-                  DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
-                  VXSIZE, VYSIZE - i/2, VX, VY);
-
-       ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
-
-       SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
-       BlitBitmapMasked(bitmap, drawto,
-                        VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
-                        VX + VXSIZE-i, VY+j);
-       SetClipOrigin(bitmap, gc,
-                     VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
-       BlitBitmapMasked(bitmap, drawto,
-                        VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
-                        VX, VY);
-
-       BlitBitmapMasked(bitmap, drawto,
-                        VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
-                        i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
-       SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
-       BlitBitmapMasked(bitmap, drawto,
-                        VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
-                        i, VYSIZE / 2 - j,
-                        VX + VXSIZE - i, VY + VYSIZE / 2 + j);
+       int a = MIN(x * door_2.step_offset, VXSIZE);
+       int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
+
+       if (x <= VYSIZE)
+       {
+         BlitBitmap(bitmap_db_door, drawto,
+                    DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
+                    VXSIZE, VYSIZE - i / 2, VX, VY);
+
+         ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
+       }
+
+       if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
+       {
+         int src1_x = VXSIZE,          src1_y = DOOR_GFX_PAGEY2;
+         int dst1_x = VX + VXSIZE - i, dst1_y = VY;
+         int src2_x = VXSIZE - i,      src2_y = DOOR_GFX_PAGEY2;
+         int dst2_x = VX,              dst2_y = VY;
+         int width = i, height = VYSIZE;
+
+         SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
+         BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
+                          dst1_x, dst1_y);
+
+         SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
+         BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
+                          dst2_x, dst2_y);
+       }
+       else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
+       {
+         int src1_x = VXSIZE,          src1_y = DOOR_GFX_PAGEY2;
+         int dst1_x = VX,              dst1_y = VY + VYSIZE - i;
+         int src2_x = 0,               src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
+         int dst2_x = VX,              dst2_y = VY;
+         int width = VXSIZE, height = i;
+
+         SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
+         BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
+                          dst1_x, dst1_y);
+
+         SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
+         BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
+                          dst2_x, dst2_y);
+       }
+       else if (x <= VXSIZE)   /* ANIM_DEFAULT */
+       {
+         int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
+
+         SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
+         BlitBitmapMasked(bitmap, drawto,
+                          VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
+                          VX + VXSIZE - i, VY + j);
+         SetClipOrigin(bitmap, gc,
+                       VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
+         BlitBitmapMasked(bitmap, drawto,
+                          VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
+                          VX, VY);
+
+         BlitBitmapMasked(bitmap, drawto,
+                          VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
+                          i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
+         SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
+         BlitBitmapMasked(bitmap, drawto,
+                          VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
+                          i, VYSIZE / 2 - j,
+                          VX + VXSIZE - i, VY + VYSIZE / 2 + j);
+       }
 
        redraw_mask |= REDRAW_DOOR_2;
+       door_2_done = (a == VXSIZE);
       }
 
       BackToFront();
 
       if (game_status == GAME_MODE_MAIN)
        DoAnimation();
+
+      if (!(door_state & DOOR_NO_DELAY))
+       WaitUntilDelayReached(&door_delay, door_delay_value);
     }
   }