rnd-20070403-1-src
[rocksndiamonds.git] / src / game.c
index 297efe8502254ba09972f195dbea379219e08713..9fb95c23bad7af9d5302e0e2acf891aea88d86df 100644 (file)
 #define EX_TYPE_DYNA           (1 << 4)
 #define EX_TYPE_SINGLE_TILE    (EX_TYPE_CENTER | EX_TYPE_BORDER)
 
-#if 1
 #define PANEL_OFF()            (local_player->LevelSolved_PanelOff)
 #define        PANEL_DEACTIVATED(p)    ((p)->x < 0 || (p)->y < 0 || PANEL_OFF())
-#define PANEL_XPOS(p)          (DX + ALIGNED_MENU_XPOS(p))
-#define PANEL_YPOS(p)          (DY + ALIGNED_MENU_YPOS(p))
-#else
-#define        PANEL_DEACTIVATED(p)    ((p).x < 0 || (p).y < 0)
-#define PANEL_XPOS(p)          (ALIGNED_XPOS((p).x, (p).width, (p).align))
-#define PANEL_YPOS(p)          ((p).y)
-#endif
+#define PANEL_XPOS(p)          (DX + ALIGNED_TEXT_XPOS(p))
+#define PANEL_YPOS(p)          (DY + ALIGNED_TEXT_YPOS(p))
 
 /* special positions in the game control window (relative to control window) */
 #define XX_LEVEL1              (PANEL_XPOS(game.panel.level))
 #define DX_TIME                        (DX + XX_TIME)
 #define DY_TIME                        (DY + YY_TIME)
 
-#if 0
+#if 1
 /* game panel display and control definitions */
 
-#define GAME_CONTROL_LEVEL                     0
+#define GAME_CONTROL_LEVEL_NUMBER              0
 #define GAME_CONTROL_GEMS                      1
-#define GAME_CONTROL_INVENTORY                 2
-#define GAME_CONTROL_KEY_1                     3
-#define GAME_CONTROL_KEY_2                     4
-#define GAME_CONTROL_KEY_3                     5
-#define GAME_CONTROL_KEY_4                     6
-#define GAME_CONTROL_KEY_5                     7
-#define GAME_CONTROL_KEY_6                     8
-#define GAME_CONTROL_KEY_7                     9
-#define GAME_CONTROL_KEY_8                     10
-#define GAME_CONTROL_KEY_WHITE                 11
-#define GAME_CONTROL_KEY_WHITE_COUNT           12
-#define GAME_CONTROL_SCORE                     13
-#define GAME_CONTROL_TIME                      14
-#define GAME_CONTROL_TIME_HH                   15
-#define GAME_CONTROL_TIME_MM                   16
-#define GAME_CONTROL_TIME_SS                   17
-#define GAME_CONTROL_DROP_NEXT_1               18
-#define GAME_CONTROL_DROP_NEXT_2               19
-#define GAME_CONTROL_DROP_NEXT_3               20
-#define GAME_CONTROL_DROP_NEXT_4               21
-#define GAME_CONTROL_DROP_NEXT_5               22
-#define GAME_CONTROL_DROP_NEXT_6               23
-#define GAME_CONTROL_DROP_NEXT_7               24
-#define GAME_CONTROL_DROP_NEXT_8               25
-#define GAME_CONTROL_SHIELD_NORMAL             26
-#define GAME_CONTROL_SHIELD_NORMAL_TIME                27
-#define GAME_CONTROL_SHIELD_DEADLY             28
-#define GAME_CONTROL_SHIELD_DEADLY_TIME                29
-#define GAME_CONTROL_EXIT                      30
-#define GAME_CONTROL_EM_EXIT                   31
-#define GAME_CONTROL_SP_EXIT                   32
-#define GAME_CONTROL_STEEL_EXIT                        33
-#define GAME_CONTROL_EM_STEEL_EXIT             34
-#define GAME_CONTROL_EMC_MAGIC_BALL            35
-#define GAME_CONTROL_EMC_MAGIC_BALL_TIME       36
-#define GAME_CONTROL_LIGHT_SWITCH              37
-#define GAME_CONTROL_LIGHT_SWITCH_TIME         38
-#define GAME_CONTROL_TIMEGATE_SWITCH           39
-#define GAME_CONTROL_TIMEGATE_SWITCH_TIME      40
-#define GAME_CONTROL_SWITCHGATE_SWITCH         41
-#define GAME_CONTROL_EMC_LENSES                        42
-#define GAME_CONTROL_EMC_LENSES_TIME           43
-#define GAME_CONTROL_EMC_MAGNIFIER             44
-#define GAME_CONTROL_EMC_MAGNIFIER_TIME                45
-#define GAME_CONTROL_BALLOON_SWITCH            46
-#define GAME_CONTROL_DYNABOMB_NUMBER           47
-#define GAME_CONTROL_DYNABOMB_SIZE             48
-#define GAME_CONTROL_DYNABOMB_POWER            49
-#define GAME_CONTROL_PENGUINS                  50
-#define GAME_CONTROL_SOKOBAN_OBJECTS           51
-#define GAME_CONTROL_SOKOBAN_FIELDS            52
-#define GAME_CONTROL_ROBOT_WHEEL               53
-#define GAME_CONTROL_CONVEYOR_BELT_1           54
-#define GAME_CONTROL_CONVEYOR_BELT_1_SWITCH    55
-#define GAME_CONTROL_CONVEYOR_BELT_2           56
-#define GAME_CONTROL_CONVEYOR_BELT_2_SWITCH    57
-#define GAME_CONTROL_CONVEYOR_BELT_3           58
-#define GAME_CONTROL_CONVEYOR_BELT_3_SWITCH    59
-#define GAME_CONTROL_CONVEYOR_BELT_4           60
-#define GAME_CONTROL_CONVEYOR_BELT_4_SWITCH    61
-#define GAME_CONTROL_MAGIC_WALL                        62
-#define GAME_CONTROL_MAGIC_WALL_TIME           63
-#define GAME_CONTROL_BD_MAGIC_WALL             64
-#define GAME_CONTROL_DC_MAGIC_WALL             65
-#define GAME_CONTROL_PLAYER_NAME               66
-#define GAME_CONTROL_LEVEL_NAME                        67
-#define GAME_CONTROL_LEVEL_AUTHOR              68
+#define GAME_CONTROL_INVENTORY_COUNT           2
+#define GAME_CONTROL_INVENTORY_FIRST_1         3
+#define GAME_CONTROL_INVENTORY_FIRST_2         4
+#define GAME_CONTROL_INVENTORY_FIRST_3         5
+#define GAME_CONTROL_INVENTORY_FIRST_4         6
+#define GAME_CONTROL_INVENTORY_FIRST_5         7
+#define GAME_CONTROL_INVENTORY_FIRST_6         8
+#define GAME_CONTROL_INVENTORY_FIRST_7         9
+#define GAME_CONTROL_INVENTORY_FIRST_8         10
+#define GAME_CONTROL_INVENTORY_LAST_1          11
+#define GAME_CONTROL_INVENTORY_LAST_2          12
+#define GAME_CONTROL_INVENTORY_LAST_3          13
+#define GAME_CONTROL_INVENTORY_LAST_4          14
+#define GAME_CONTROL_INVENTORY_LAST_5          15
+#define GAME_CONTROL_INVENTORY_LAST_6          16
+#define GAME_CONTROL_INVENTORY_LAST_7          17
+#define GAME_CONTROL_INVENTORY_LAST_8          18
+#define GAME_CONTROL_KEY_1                     19
+#define GAME_CONTROL_KEY_2                     20
+#define GAME_CONTROL_KEY_3                     21
+#define GAME_CONTROL_KEY_4                     22
+#define GAME_CONTROL_KEY_5                     23
+#define GAME_CONTROL_KEY_6                     24
+#define GAME_CONTROL_KEY_7                     25
+#define GAME_CONTROL_KEY_8                     26
+#define GAME_CONTROL_KEY_WHITE                 27
+#define GAME_CONTROL_KEY_WHITE_COUNT           28
+#define GAME_CONTROL_SCORE                     29
+#define GAME_CONTROL_TIME                      30
+#define GAME_CONTROL_TIME_HH                   31
+#define GAME_CONTROL_TIME_MM                   32
+#define GAME_CONTROL_TIME_SS                   33
+#define GAME_CONTROL_SHIELD_NORMAL             34
+#define GAME_CONTROL_SHIELD_NORMAL_TIME                35
+#define GAME_CONTROL_SHIELD_DEADLY             36
+#define GAME_CONTROL_SHIELD_DEADLY_TIME                37
+#define GAME_CONTROL_EXIT                      38
+#define GAME_CONTROL_EM_EXIT                   39
+#define GAME_CONTROL_SP_EXIT                   40
+#define GAME_CONTROL_STEEL_EXIT                        41
+#define GAME_CONTROL_EM_STEEL_EXIT             42
+#define GAME_CONTROL_EMC_MAGIC_BALL            43
+#define GAME_CONTROL_EMC_MAGIC_BALL_SWITCH     44
+#define GAME_CONTROL_LIGHT_SWITCH              45
+#define GAME_CONTROL_LIGHT_SWITCH_TIME         46
+#define GAME_CONTROL_TIMEGATE_SWITCH           47
+#define GAME_CONTROL_TIMEGATE_SWITCH_TIME      48
+#define GAME_CONTROL_SWITCHGATE_SWITCH         49
+#define GAME_CONTROL_EMC_LENSES                        50
+#define GAME_CONTROL_EMC_LENSES_TIME           51
+#define GAME_CONTROL_EMC_MAGNIFIER             52
+#define GAME_CONTROL_EMC_MAGNIFIER_TIME                53
+#define GAME_CONTROL_BALLOON_SWITCH            54
+#define GAME_CONTROL_DYNABOMB_NUMBER           55
+#define GAME_CONTROL_DYNABOMB_SIZE             56
+#define GAME_CONTROL_DYNABOMB_POWER            57
+#define GAME_CONTROL_PENGUINS                  58
+#define GAME_CONTROL_SOKOBAN_OBJECTS           59
+#define GAME_CONTROL_SOKOBAN_FIELDS            60
+#define GAME_CONTROL_ROBOT_WHEEL               61
+#define GAME_CONTROL_CONVEYOR_BELT_1           62
+#define GAME_CONTROL_CONVEYOR_BELT_1_SWITCH    63
+#define GAME_CONTROL_CONVEYOR_BELT_2           64
+#define GAME_CONTROL_CONVEYOR_BELT_2_SWITCH    65
+#define GAME_CONTROL_CONVEYOR_BELT_3           66
+#define GAME_CONTROL_CONVEYOR_BELT_3_SWITCH    67
+#define GAME_CONTROL_CONVEYOR_BELT_4           68
+#define GAME_CONTROL_CONVEYOR_BELT_4_SWITCH    69
+#define GAME_CONTROL_MAGIC_WALL                        70
+#define GAME_CONTROL_MAGIC_WALL_TIME           71
+#define GAME_CONTROL_BD_MAGIC_WALL             72
+#define GAME_CONTROL_DC_MAGIC_WALL             73
+#define GAME_CONTROL_PLAYER_NAME               74
+#define GAME_CONTROL_LEVEL_NAME                        75
+#define GAME_CONTROL_LEVEL_AUTHOR              76
+
+#define NUM_GAME_CONTROLS                      77
+
+int game_control_value[NUM_GAME_CONTROLS];
+int last_game_control_value[NUM_GAME_CONTROLS];
 
 struct GameControlInfo
 {
   int nr;
 
-  struct TextPosInfo *pos_text;
+  struct TextPosInfo *pos;
   int type;
-  void *ptr;
 };
 
 static struct GameControlInfo game_controls[] =
 {
   {
-    GAME_CONTROL_LEVEL,
-    &game.panel.level,
+    GAME_CONTROL_LEVEL_NUMBER,
+    &game.panel.level_number,
     TYPE_INTEGER,
   },
   {
@@ -229,139 +235,169 @@ static struct GameControlInfo game_controls[] =
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_INVENTORY,
-    &game.panel.inventory,
+    GAME_CONTROL_INVENTORY_COUNT,
+    &game.panel.inventory_count,
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_KEYS,
-    &game.panel.keys,
-    TYPE_INTEGER,
+    GAME_CONTROL_INVENTORY_FIRST_1,
+    &game.panel.inventory_first_1,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_SCORE,
-    &game.panel.score,
-    TYPE_INTEGER,
+    GAME_CONTROL_INVENTORY_FIRST_2,
+    &game.panel.inventory_first_2,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_TIME,
-    &game.panel.time,
-    TYPE_INTEGER,
+    GAME_CONTROL_INVENTORY_FIRST_3,
+    &game.panel.inventory_first_3,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_TIME_HH,
-    &game.panel.time_hh,
-    TYPE_INTEGER,
+    GAME_CONTROL_INVENTORY_FIRST_4,
+    &game.panel.inventory_first_4,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_TIME_MM,
-    &game.panel.time_mm,
-    TYPE_INTEGER,
+    GAME_CONTROL_INVENTORY_FIRST_5,
+    &game.panel.inventory_first_5,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_TIME_SS,
-    &game.panel.time_ss,
-    TYPE_INTEGER,
+    GAME_CONTROL_INVENTORY_FIRST_6,
+    &game.panel.inventory_first_6,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DROP_NEXT_1,
-    &game.panel.drop_next_1,
-    TYPE_INTEGER,
+    GAME_CONTROL_INVENTORY_FIRST_7,
+    &game.panel.inventory_first_7,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DROP_NEXT_2,
-    &game.panel.drop_next_2,
-    TYPE_INTEGER,
+    GAME_CONTROL_INVENTORY_FIRST_8,
+    &game.panel.inventory_first_8,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DROP_NEXT_3,
-    &game.panel.drop_next_3,
-    TYPE_INTEGER,
+    GAME_CONTROL_INVENTORY_LAST_1,
+    &game.panel.inventory_last_1,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DROP_NEXT_4,
-    &game.panel.drop_next_4,
-    TYPE_INTEGER,
+    GAME_CONTROL_INVENTORY_LAST_2,
+    &game.panel.inventory_last_2,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DROP_NEXT_5,
-    &game.panel.drop_next_5,
-    TYPE_INTEGER,
+    GAME_CONTROL_INVENTORY_LAST_3,
+    &game.panel.inventory_last_3,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DROP_NEXT_6,
-    &game.panel.drop_next_6,
-    TYPE_INTEGER,
+    GAME_CONTROL_INVENTORY_LAST_4,
+    &game.panel.inventory_last_4,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DROP_NEXT_7,
-    &game.panel.drop_next_7,
-    TYPE_INTEGER,
+    GAME_CONTROL_INVENTORY_LAST_5,
+    &game.panel.inventory_last_5,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DROP_NEXT_8,
-    &game.panel.drop_next_8,
-    TYPE_INTEGER,
+    GAME_CONTROL_INVENTORY_LAST_6,
+    &game.panel.inventory_last_6,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_EMC_KEYS,
-    &game.panel.emc_keys,
-    TYPE_INTEGER,
+    GAME_CONTROL_INVENTORY_LAST_7,
+    &game.panel.inventory_last_7,
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_CONTROL_INVENTORY_LAST_8,
+    &game.panel.inventory_last_8,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_KEY_1,
-    &game.panel.key_1,
-    TYPE_INTEGER,
+    &game.panel.key[0],
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_KEY_2,
-    &game.panel.key_2,
-    TYPE_INTEGER,
+    &game.panel.key[1],
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_KEY_3,
-    &game.panel.key_3,
-    TYPE_INTEGER,
+    &game.panel.key[2],
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_KEY_4,
-    &game.panel.key_4,
-    TYPE_INTEGER,
+    &game.panel.key[3],
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_KEY_5,
-    &game.panel.key_5,
-    TYPE_INTEGER,
+    &game.panel.key[4],
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_KEY_6,
-    &game.panel.key_6,
-    TYPE_INTEGER,
+    &game.panel.key[5],
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_KEY_7,
-    &game.panel.key_7,
-    TYPE_INTEGER,
+    &game.panel.key[6],
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_KEY_8,
-    &game.panel.key_8,
-    TYPE_INTEGER,
+    &game.panel.key[7],
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_KEY_WHITE,
     &game.panel.key_white,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_KEY_WHITE_COUNT,
     &game.panel.key_white_count,
     TYPE_INTEGER,
   },
+  {
+    GAME_CONTROL_SCORE,
+    &game.panel.score,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_TIME,
+    &game.panel.time,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_TIME_HH,
+    &game.panel.time_hh,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_TIME_MM,
+    &game.panel.time_mm,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_TIME_SS,
+    &game.panel.time_ss,
+    TYPE_INTEGER,
+  },
   {
     GAME_CONTROL_SHIELD_NORMAL,
     &game.panel.shield_normal,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_SHIELD_NORMAL_TIME,
@@ -371,7 +407,7 @@ static struct GameControlInfo game_controls[] =
   {
     GAME_CONTROL_SHIELD_DEADLY,
     &game.panel.shield_deadly,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_SHIELD_DEADLY_TIME,
@@ -381,42 +417,42 @@ static struct GameControlInfo game_controls[] =
   {
     GAME_CONTROL_EXIT,
     &game.panel.exit,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_EM_EXIT,
     &game.panel.em_exit,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_SP_EXIT,
     &game.panel.sp_exit,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_STEEL_EXIT,
     &game.panel.steel_exit,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_EM_STEEL_EXIT,
     &game.panel.em_steel_exit,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_EMC_MAGIC_BALL,
     &game.panel.emc_magic_ball,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_EMC_MAGIC_BALL_TIME,
-    &game.panel.emc_magic_ball_time,
-    TYPE_INTEGER,
+    GAME_CONTROL_EMC_MAGIC_BALL_SWITCH,
+    &game.panel.emc_magic_ball_switch,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_LIGHT_SWITCH,
     &game.panel.light_switch,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_LIGHT_SWITCH_TIME,
@@ -426,7 +462,7 @@ static struct GameControlInfo game_controls[] =
   {
     GAME_CONTROL_TIMEGATE_SWITCH,
     &game.panel.timegate_switch,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_TIMEGATE_SWITCH_TIME,
@@ -436,12 +472,12 @@ static struct GameControlInfo game_controls[] =
   {
     GAME_CONTROL_SWITCHGATE_SWITCH,
     &game.panel.switchgate_switch,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_EMC_LENSES,
     &game.panel.emc_lenses,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_EMC_LENSES_TIME,
@@ -451,7 +487,7 @@ static struct GameControlInfo game_controls[] =
   {
     GAME_CONTROL_EMC_MAGNIFIER,
     &game.panel.emc_magnifier,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_EMC_MAGNIFIER_TIME,
@@ -461,7 +497,7 @@ static struct GameControlInfo game_controls[] =
   {
     GAME_CONTROL_BALLOON_SWITCH,
     &game.panel.balloon_switch,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_DYNABOMB_NUMBER,
@@ -476,7 +512,7 @@ static struct GameControlInfo game_controls[] =
   {
     GAME_CONTROL_DYNABOMB_POWER,
     &game.panel.dynabomb_power,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_PENGUINS,
@@ -496,52 +532,52 @@ static struct GameControlInfo game_controls[] =
   {
     GAME_CONTROL_ROBOT_WHEEL,
     &game.panel.robot_wheel,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_CONVEYOR_BELT_1,
     &game.panel.conveyor_belt_1,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_CONVEYOR_BELT_1_SWITCH,
     &game.panel.conveyor_belt_1_switch,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_CONVEYOR_BELT_2,
     &game.panel.conveyor_belt_2,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_CONVEYOR_BELT_2_SWITCH,
     &game.panel.conveyor_belt_2_switch,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_CONVEYOR_BELT_3,
     &game.panel.conveyor_belt_3,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_CONVEYOR_BELT_3_SWITCH,
     &game.panel.conveyor_belt_3_switch,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_CONVEYOR_BELT_4,
     &game.panel.conveyor_belt_4,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_CONVEYOR_BELT_4_SWITCH,
     &game.panel.conveyor_belt_4_switch,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_MAGIC_WALL,
     &game.panel.magic_wall,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_MAGIC_WALL_TIME,
@@ -551,34 +587,33 @@ static struct GameControlInfo game_controls[] =
   {
     GAME_CONTROL_BD_MAGIC_WALL,
     &game.panel.bd_magic_wall,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_DC_MAGIC_WALL,
     &game.panel.dc_magic_wall,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
     GAME_CONTROL_PLAYER_NAME,
     &game.panel.player_name,
-    TYPE_INTEGER,
+    TYPE_STRING,
   },
   {
     GAME_CONTROL_LEVEL_NAME,
     &game.panel.level_name,
-    TYPE_INTEGER,
+    TYPE_STRING,
   },
   {
     GAME_CONTROL_LEVEL_AUTHOR,
     &game.panel.level_author,
-    TYPE_INTEGER,
+    TYPE_STRING,
   },
 
   {
     -1,
     NULL,
     -1,
-    NULL
   }
 };
 #endif
@@ -1735,6 +1770,362 @@ static inline void InitField_WithBug2(int x, int y, boolean init_game)
 
 #if 1
 
+static int get_key_element_from_nr(int key_nr)
+{
+  int key_base_element = (key_nr >= STD_NUM_KEYS ? EL_EMC_KEY_5 - STD_NUM_KEYS :
+                         level.game_engine_type == GAME_ENGINE_TYPE_EM ?
+                         EL_EM_KEY_1 : EL_KEY_1);
+
+  return key_base_element + key_nr;
+}
+
+static int get_next_drop_element(struct PlayerInfo *player)
+{
+  return (player->inventory_size > 0 ?
+         player->inventory_element[player->inventory_size - 1] :
+         player->inventory_infinite_element != EL_UNDEFINED ?
+         player->inventory_infinite_element :
+         player->dynabombs_left > 0 ?
+         EL_DYNABOMB_PLAYER_1_ACTIVE + player->index_nr :
+         EL_UNDEFINED);
+}
+
+static int get_drop_element_from_pos(struct PlayerInfo *player, int pos)
+{
+  /* pos >= 0: get element from bottom of the stack;
+     pos <  0: get element from top of the stack */
+
+  if (pos < 0)
+  {
+    int min_inventory_size = -pos;
+    int inventory_pos = player->inventory_size - min_inventory_size;
+    int min_dynabombs_left = min_inventory_size - player->inventory_size;
+
+    return (player->inventory_size >= min_inventory_size ?
+           player->inventory_element[inventory_pos] :
+           player->inventory_infinite_element != EL_UNDEFINED ?
+           player->inventory_infinite_element :
+           player->dynabombs_left >= min_dynabombs_left ?
+           EL_DYNABOMB_PLAYER_1_ACTIVE + player->index_nr :
+           EL_UNDEFINED);
+  }
+  else
+  {
+    int min_dynabombs_left = pos + 1;
+    int min_inventory_size = pos + 1 - player->dynabombs_left;
+    int inventory_pos = pos - player->dynabombs_left;
+
+    return (player->inventory_infinite_element != EL_UNDEFINED ?
+           player->inventory_infinite_element :
+           player->dynabombs_left >= min_dynabombs_left ?
+           EL_DYNABOMB_PLAYER_1_ACTIVE + player->index_nr :
+           player->inventory_size >= min_inventory_size ?
+           player->inventory_element[inventory_pos] :
+           EL_UNDEFINED);
+  }
+}
+
+void InitGameControlValues()
+{
+  int i;
+
+  for (i = 0; game_controls[i].nr != -1; i++)
+  {
+    int nr = game_controls[i].nr;
+    int type = game_controls[i].type;
+    struct TextPosInfo *pos = game_controls[i].pos;
+
+    /* force update of game controls after initialization */
+    game_control_value[nr] = last_game_control_value[nr] = -1;
+
+    /* determine panel value width for later calculation of alignment */
+    if (type == TYPE_INTEGER || type == TYPE_STRING)
+    {
+      pos->width = pos->size * getFontWidth(pos->font);
+      pos->height = getFontHeight(pos->font);
+    }
+    else if (type == TYPE_ELEMENT)
+    {
+      pos->width = pos->size;
+      pos->height = pos->size;
+    }
+  }
+}
+
+void UpdateGameControlValues()
+{
+  int i, k;
+  int time = (level.time == 0 ? TimePlayed : TimeLeft);
+  int score = (local_player->LevelSolved ? local_player->score_final :
+              local_player->score);
+
+  game_control_value[GAME_CONTROL_LEVEL_NUMBER] = level_nr;
+  game_control_value[GAME_CONTROL_GEMS] = local_player->gems_still_needed;
+
+  game_control_value[GAME_CONTROL_INVENTORY_COUNT] = 0;
+  for (i = 0; i < MAX_NUM_KEYS; i++)
+    game_control_value[GAME_CONTROL_KEY_1 + i] = EL_EMPTY;
+  game_control_value[GAME_CONTROL_KEY_WHITE] = EL_EMPTY;
+  game_control_value[GAME_CONTROL_KEY_WHITE_COUNT] = 0;
+
+  if (game.centered_player_nr == -1)
+  {
+    for (i = 0; i < MAX_PLAYERS; i++)
+    {
+      for (k = 0; k < MAX_NUM_KEYS; k++)
+       if (stored_player[i].key[k])
+         game_control_value[GAME_CONTROL_KEY_1 + k] =
+           get_key_element_from_nr(k);
+
+      game_control_value[GAME_CONTROL_INVENTORY_COUNT] +=
+       stored_player[i].inventory_size;
+
+      if (stored_player[i].num_white_keys > 0)
+       game_control_value[GAME_CONTROL_KEY_WHITE] = EL_DC_KEY_WHITE;
+
+      game_control_value[GAME_CONTROL_KEY_WHITE_COUNT] +=
+       stored_player[i].num_white_keys;
+    }
+  }
+  else
+  {
+    int player_nr = game.centered_player_nr;
+
+    for (k = 0; k < MAX_NUM_KEYS; k++)
+      if (stored_player[player_nr].key[k])
+       game_control_value[GAME_CONTROL_KEY_1 + k] =
+         get_key_element_from_nr(k);
+
+    game_control_value[GAME_CONTROL_INVENTORY_COUNT] +=
+      stored_player[player_nr].inventory_size;
+
+    if (stored_player[player_nr].num_white_keys > 0)
+      game_control_value[GAME_CONTROL_KEY_WHITE] = EL_DC_KEY_WHITE;
+
+    game_control_value[GAME_CONTROL_KEY_WHITE_COUNT] +=
+      stored_player[player_nr].num_white_keys;
+  }
+
+  for (i = 0; i < 8; i++)
+  {
+    game_control_value[GAME_CONTROL_INVENTORY_FIRST_1 + i] =
+      get_drop_element_from_pos(local_player, i);
+    game_control_value[GAME_CONTROL_INVENTORY_LAST_1 + i] =
+      get_drop_element_from_pos(local_player, -i - 1);
+  }
+
+  game_control_value[GAME_CONTROL_SCORE] = score;
+
+  game_control_value[GAME_CONTROL_TIME] = time;
+
+  game_control_value[GAME_CONTROL_TIME_HH] = time / 3600;
+  game_control_value[GAME_CONTROL_TIME_MM] = (time / 60) % 60;
+  game_control_value[GAME_CONTROL_TIME_SS] = time % 60;
+
+  game_control_value[GAME_CONTROL_SHIELD_NORMAL] =
+    (local_player->shield_normal_time_left > 0 ? EL_SHIELD_NORMAL_ACTIVE :
+     EL_EMPTY);
+  game_control_value[GAME_CONTROL_SHIELD_NORMAL_TIME] =
+    local_player->shield_normal_time_left;
+  game_control_value[GAME_CONTROL_SHIELD_DEADLY] =
+    (local_player->shield_deadly_time_left > 0 ? EL_SHIELD_DEADLY_ACTIVE :
+     EL_EMPTY);
+  game_control_value[GAME_CONTROL_SHIELD_DEADLY_TIME] =
+    local_player->shield_deadly_time_left;
+
+  if (local_player->gems_still_needed > 0 ||
+      local_player->sokobanfields_still_needed > 0 ||
+      local_player->lights_still_needed > 0)
+  {
+    game_control_value[GAME_CONTROL_EXIT]          = EL_EXIT_CLOSED;
+    game_control_value[GAME_CONTROL_EM_EXIT]       = EL_EM_EXIT_CLOSED;
+    game_control_value[GAME_CONTROL_SP_EXIT]       = EL_SP_EXIT_CLOSED;
+    game_control_value[GAME_CONTROL_STEEL_EXIT]    = EL_STEEL_EXIT_CLOSED;
+    game_control_value[GAME_CONTROL_EM_STEEL_EXIT] = EL_EM_STEEL_EXIT_CLOSED;
+  }
+  else
+  {
+    game_control_value[GAME_CONTROL_EXIT]          = EL_EXIT_OPEN;
+    game_control_value[GAME_CONTROL_EM_EXIT]       = EL_EM_EXIT_OPEN;
+    game_control_value[GAME_CONTROL_SP_EXIT]       = EL_SP_EXIT_OPEN;
+    game_control_value[GAME_CONTROL_STEEL_EXIT]    = EL_STEEL_EXIT_OPEN;
+    game_control_value[GAME_CONTROL_EM_STEEL_EXIT] = EL_EM_STEEL_EXIT_OPEN;
+  }
+
+  /* !!! TODO !!! */
+  game_control_value[GAME_CONTROL_EMC_MAGIC_BALL] = EL_UNDEFINED;
+  game_control_value[GAME_CONTROL_EMC_MAGIC_BALL_SWITCH] = EL_UNDEFINED;
+
+  game_control_value[GAME_CONTROL_LIGHT_SWITCH] =
+    (game.light_time_left > 0 ? EL_LIGHT_SWITCH_ACTIVE : EL_LIGHT_SWITCH);
+  game_control_value[GAME_CONTROL_LIGHT_SWITCH_TIME] = game.light_time_left;
+
+  game_control_value[GAME_CONTROL_TIMEGATE_SWITCH] =
+    (game.timegate_time_left > 0 ? EL_TIMEGATE_OPEN : EL_TIMEGATE_CLOSED);
+  game_control_value[GAME_CONTROL_TIMEGATE_SWITCH_TIME] =
+    game.timegate_time_left;
+
+  /* !!! TODO !!! */
+  game_control_value[GAME_CONTROL_SWITCHGATE_SWITCH] = EL_UNDEFINED;
+
+  game_control_value[GAME_CONTROL_EMC_LENSES] =
+    (game.lenses_time_left > 0 ? EL_EMC_LENSES : EL_EMPTY);
+  game_control_value[GAME_CONTROL_EMC_LENSES_TIME] = game.lenses_time_left;
+
+  game_control_value[GAME_CONTROL_EMC_MAGNIFIER] =
+    (game.magnify_time_left > 0 ? EL_EMC_MAGNIFIER : EL_EMPTY);
+  game_control_value[GAME_CONTROL_EMC_MAGNIFIER_TIME] = game.magnify_time_left;
+
+  game_control_value[GAME_CONTROL_BALLOON_SWITCH] =
+    (game.wind_direction == MV_LEFT  ? EL_BALLOON_SWITCH_LEFT  :
+     game.wind_direction == MV_RIGHT ? EL_BALLOON_SWITCH_RIGHT :
+     game.wind_direction == MV_UP    ? EL_BALLOON_SWITCH_UP    :
+     game.wind_direction == MV_DOWN  ? EL_BALLOON_SWITCH_DOWN  :
+     EL_BALLOON_SWITCH_NONE);
+
+  game_control_value[GAME_CONTROL_DYNABOMB_NUMBER] =
+    local_player->dynabomb_count;
+  game_control_value[GAME_CONTROL_DYNABOMB_SIZE] =
+    local_player->dynabomb_size;
+  game_control_value[GAME_CONTROL_DYNABOMB_POWER] =
+    (local_player->dynabomb_xl ? EL_DYNABOMB_INCREASE_POWER : EL_EMPTY);
+
+  game_control_value[GAME_CONTROL_PENGUINS] =
+    local_player->friends_still_needed;
+
+  game_control_value[GAME_CONTROL_SOKOBAN_OBJECTS] =
+    local_player->sokobanfields_still_needed;
+  game_control_value[GAME_CONTROL_SOKOBAN_FIELDS] =
+    local_player->sokobanfields_still_needed;
+
+  /* !!! TODO !!! */
+  game_control_value[GAME_CONTROL_ROBOT_WHEEL] = EL_UNDEFINED;
+
+  /* !!! TODO !!! */
+  game_control_value[GAME_CONTROL_CONVEYOR_BELT_1] = EL_UNDEFINED;
+  game_control_value[GAME_CONTROL_CONVEYOR_BELT_1_SWITCH] = EL_UNDEFINED;
+  game_control_value[GAME_CONTROL_CONVEYOR_BELT_2] = EL_UNDEFINED;
+  game_control_value[GAME_CONTROL_CONVEYOR_BELT_2_SWITCH] = EL_UNDEFINED;
+  game_control_value[GAME_CONTROL_CONVEYOR_BELT_3] = EL_UNDEFINED;
+  game_control_value[GAME_CONTROL_CONVEYOR_BELT_3_SWITCH] = EL_UNDEFINED;
+  game_control_value[GAME_CONTROL_CONVEYOR_BELT_4] = EL_UNDEFINED;
+  game_control_value[GAME_CONTROL_CONVEYOR_BELT_4_SWITCH] = EL_UNDEFINED;
+
+  /* !!! TODO !!! */
+  game_control_value[GAME_CONTROL_MAGIC_WALL] = EL_UNDEFINED;
+  game_control_value[GAME_CONTROL_MAGIC_WALL_TIME] =
+    game.magic_wall_time_left;
+  game_control_value[GAME_CONTROL_BD_MAGIC_WALL] = EL_UNDEFINED;
+  game_control_value[GAME_CONTROL_DC_MAGIC_WALL] = EL_UNDEFINED;
+
+  game_control_value[GAME_CONTROL_PLAYER_NAME] = 0;
+  game_control_value[GAME_CONTROL_LEVEL_NAME] = 0;
+  game_control_value[GAME_CONTROL_LEVEL_AUTHOR] = 0;
+}
+
+void DisplayGameControlValues()
+{
+  int i;
+
+  for (i = 0; game_controls[i].nr != -1; i++)
+  {
+    int nr = game_controls[i].nr;
+    int type = game_controls[i].type;
+    struct TextPosInfo *pos = game_controls[i].pos;
+    int value = game_control_value[nr];
+    int last_value = last_game_control_value[nr];
+    int size = pos->size;
+    int font = pos->font;
+
+    if (value == last_value)
+      continue;
+
+    last_game_control_value[nr] = value;
+
+#if 0
+    printf("::: value %d changed from %d to %d\n", nr, last_value, value);
+#endif
+
+    if (PANEL_DEACTIVATED(pos))
+      continue;
+
+    if (type == TYPE_INTEGER)
+    {
+      if (nr == GAME_CONTROL_LEVEL_NUMBER || nr == GAME_CONTROL_TIME)
+      {
+       boolean use_dynamic_size = (size == -1 ? TRUE : FALSE);
+
+       if (use_dynamic_size)           /* use dynamic number of digits */
+       {
+         int value_change = (nr == GAME_CONTROL_LEVEL_NUMBER ? 100 : 1000);
+         int size1 = (nr == GAME_CONTROL_LEVEL_NUMBER ? 2 : 3);
+         int size2 = size1 + 1;
+         int font1 = pos->font;
+         int font2 = pos->font_alt;
+
+         size = (value < value_change ? size1 : size2);
+         font = (value < value_change ? font1 : font2);
+
+         /* clear background if value just changed its size (dynamic digits) */
+         if ((last_value < value_change) != (value < value_change))
+         {
+           int width1 = size1 * getFontWidth(font1);
+           int width2 = size2 * getFontWidth(font2);
+           int max_width = MAX(width1, width2);
+           int max_height = MAX(getFontHeight(font1), getFontHeight(font2));
+
+           pos->width = max_width;
+
+           ClearRectangleOnBackground(drawto, PANEL_XPOS(pos), PANEL_YPOS(pos),
+                                      max_width, max_height);
+         }
+       }
+
+       pos->width = size * getFontWidth(font);
+      }
+
+      DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, size), font);
+    }
+    else if (type == TYPE_ELEMENT)
+    {
+      int dst_x = PANEL_XPOS(pos);
+      int dst_y = PANEL_YPOS(pos);
+
+      if (value == EL_UNDEFINED || value == EL_EMPTY)
+      {
+       int src_x = DOOR_GFX_PAGEX5 + ALIGNED_TEXT_XPOS(pos);
+       int src_y = DOOR_GFX_PAGEY1 + ALIGNED_TEXT_YPOS(pos);
+
+       BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto, src_x, src_y,
+                  size, size, dst_x, dst_y);
+      }
+      else
+      {
+       int graphic = el2doorimg(value);
+
+       DrawSizedGraphicExt(drawto, dst_x, dst_y, graphic, size);
+      }
+    }
+    else if (type == TYPE_STRING)
+    {
+      char *s = (nr == GAME_CONTROL_PLAYER_NAME  ? setup.player_name :
+                nr == GAME_CONTROL_LEVEL_NAME   ? level.name :
+                nr == GAME_CONTROL_LEVEL_AUTHOR ? level.author : NULL);
+
+      if (s != NULL)
+      {
+       char *s_cut = getStringCopyN(s, size);
+
+       DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), s_cut, font);
+
+       free(s_cut);
+      }
+    }
+
+    redraw_mask |= REDRAW_DOOR_1;
+  }
+}
+
 void DrawGameValue_Emeralds(int value)
 {
   struct TextPosInfo *pos = &game.panel.gems;
@@ -1744,7 +2135,11 @@ void DrawGameValue_Emeralds(int value)
   int font_nr = FONT_TEXT_2;
 #endif
   int font_width = getFontWidth(font_nr);
-  int chars = pos->chars;
+  int chars = pos->size;
+
+#if 1
+  return;      /* !!! USE NEW STUFF !!! */
+#endif
 
   if (PANEL_DEACTIVATED(pos))
     return;
@@ -1756,14 +2151,18 @@ void DrawGameValue_Emeralds(int value)
 
 void DrawGameValue_Dynamite(int value)
 {
-  struct TextPosInfo *pos = &game.panel.inventory;
+  struct TextPosInfo *pos = &game.panel.inventory_count;
 #if 1
   int font_nr = pos->font;
 #else
   int font_nr = FONT_TEXT_2;
 #endif
   int font_width = getFontWidth(font_nr);
-  int chars = pos->chars;
+  int chars = pos->size;
+
+#if 1
+  return;      /* !!! USE NEW STUFF !!! */
+#endif
 
   if (PANEL_DEACTIVATED(pos))
     return;
@@ -1782,7 +2181,11 @@ void DrawGameValue_Score(int value)
   int font_nr = FONT_TEXT_2;
 #endif
   int font_width = getFontWidth(font_nr);
-  int chars = pos->chars;
+  int chars = pos->size;
+
+#if 1
+  return;      /* !!! USE NEW STUFF !!! */
+#endif
 
   if (PANEL_DEACTIVATED(pos))
     return;
@@ -1798,7 +2201,7 @@ void DrawGameValue_Time(int value)
   static int last_value = -1;
   int chars1 = 3;
   int chars2 = 4;
-  int chars = pos->chars;
+  int chars = pos->size;
 #if 1
   int font1_nr = pos->font;
   int font2_nr = pos->font_alt;
@@ -1809,6 +2212,10 @@ void DrawGameValue_Time(int value)
   int font_nr = font1_nr;
   boolean use_dynamic_chars = (chars == -1 ? TRUE : FALSE);
 
+#if 1
+  return;      /* !!! USE NEW STUFF !!! */
+#endif
+
   if (PANEL_DEACTIVATED(pos))
     return;
 
@@ -1844,7 +2251,7 @@ void DrawGameValue_Level(int value)
   struct TextPosInfo *pos = &game.panel.level_number;
   int chars1 = 2;
   int chars2 = 3;
-  int chars = pos->chars;
+  int chars = pos->size;
 #if 1
   int font1_nr = pos->font;
   int font2_nr = pos->font_alt;
@@ -1855,6 +2262,10 @@ void DrawGameValue_Level(int value)
   int font_nr = font1_nr;
   boolean use_dynamic_chars = (chars == -1 ? TRUE : FALSE);
 
+#if 1
+  return;      /* !!! USE NEW STUFF !!! */
+#endif
+
   if (PANEL_DEACTIVATED(pos))
     return;
 
@@ -1879,6 +2290,10 @@ void DrawGameValue_Keys(int key[MAX_NUM_KEYS])
 #endif
   int i;
 
+#if 1
+  return;      /* !!! USE NEW STUFF !!! */
+#endif
+
 #if 0
   if (PANEL_DEACTIVATED(pos))
     return;
@@ -1903,7 +2318,7 @@ void DrawGameValue_Keys(int key[MAX_NUM_KEYS])
 #if 1
     struct TextPosInfo *pos = &game.panel.key[i];
 #endif
-    int src_x = DOOR_GFX_PAGEX5 + 18;
+    int src_x = DOOR_GFX_PAGEX5 + 18 + (i % 4) * MINI_TILEX;
     int src_y = DOOR_GFX_PAGEY1 + 123;
 #if 1
     int dst_x = PANEL_XPOS(pos);
@@ -1984,7 +2399,7 @@ void DrawGameValue_Dynamite(int value)
   int font_nr = FONT_TEXT_2;
   int xpos = (3 * 14 - 3 * getFontWidth(font_nr)) / 2;
 
-  if (PANEL_DEACTIVATED(game.panel.inventory))
+  if (PANEL_DEACTIVATED(game.panel.inventory_count))
     return;
 
   DrawText(DX_DYNAMITE + xpos, DY_DYNAMITE, int2str(value, 3), font_nr);
@@ -2095,6 +2510,12 @@ void DrawAllGameValues(int emeralds, int dynamite, int score, int time,
 }
 
 void DrawGameDoorValues()
+{
+  UpdateGameControlValues();
+  DisplayGameControlValues();
+}
+
+void DrawGameDoorValues_OLD()
 {
   int time_value = (level.time == 0 ? TimePlayed : TimeLeft);
   int dynamite_value = 0;
@@ -2563,6 +2984,13 @@ static void InitGameEngine()
   recursion_loop_depth = 0;
   recursion_loop_detected = FALSE;
   recursion_loop_element = EL_UNDEFINED;
+
+  /* ---------- initialize graphics engine ---------------------------------- */
+  game.scroll_delay_value =
+    (game.forced_scroll_delay_value != -1 ? game.forced_scroll_delay_value :
+     setup.scroll_delay                   ? setup.scroll_delay_value       : 0);
+  game.scroll_delay_value =
+    MIN(MAX(MIN_SCROLL_DELAY, game.scroll_delay_value), MAX_SCROLL_DELAY);
 }
 
 int get_num_special_action(int element, int action_first, int action_last)
@@ -2602,12 +3030,15 @@ void InitGame()
   boolean emulate_bd = TRUE;   /* unless non-BOULDERDASH elements found */
   boolean emulate_sb = TRUE;   /* unless non-SOKOBAN     elements found */
   boolean emulate_sp = TRUE;   /* unless non-SUPAPLEX    elements found */
+#if 0
   boolean do_fading = (game_status == GAME_MODE_MAIN);
+#endif
   int i, j, x, y;
 
   game_status = GAME_MODE_PLAYING;
 
   InitGameEngine();
+  InitGameControlValues();
 
   /* don't play tapes over network */
   network_playing = (options.network && !tape.playing);
@@ -3088,7 +3519,8 @@ void InitGame()
          content = element_info[element].change_page[i].target_element;
          is_player = ELEM_IS_PLAYER(content);
 
-         if (is_player && (found_rating < 3 || element < found_element))
+         if (is_player && (found_rating < 3 ||
+                           (found_rating == 3 && element < found_element)))
          {
            start_x = x;
            start_y = y;
@@ -3105,7 +3537,8 @@ void InitGame()
        content = element_info[element].content.e[xx][yy];
        is_player = ELEM_IS_PLAYER(content);
 
-       if (is_player && (found_rating < 2 || element < found_element))
+       if (is_player && (found_rating < 2 ||
+                         (found_rating == 2 && element < found_element)))
        {
          start_x = x + xx - 1;
          start_y = y + yy - 1;
@@ -3125,7 +3558,8 @@ void InitGame()
 
          is_player = ELEM_IS_PLAYER(content);
 
-         if (is_player && (found_rating < 1 || element < found_element))
+         if (is_player && (found_rating < 1 ||
+                           (found_rating == 1 && element < found_element)))
          {
            start_x = x + xx - 1;
            start_y = y + yy - 1;
@@ -3161,8 +3595,24 @@ void InitGame()
   if (!game.restart_level)
     CloseDoor(DOOR_CLOSE_1);
 
+#if 1
+  if (level_editor_test_game)
+    FadeSkipNextFadeIn();
+  else
+    FadeSetEnterScreen();
+#else
+  if (level_editor_test_game)
+    fading = fading_none;
+  else
+    fading = menu.destination;
+#endif
+
+#if 1
+  FadeOut(REDRAW_FIELD);
+#else
   if (do_fading)
     FadeOut(REDRAW_FIELD);
+#endif
 
   /* !!! FIX THIS (START) !!! */
   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
@@ -3189,10 +3639,14 @@ void InitGame()
   }
   /* !!! FIX THIS (END) !!! */
 
+#if 1
+  FadeIn(REDRAW_FIELD);
+#else
   if (do_fading)
     FadeIn(REDRAW_FIELD);
 
   BackToFront();
+#endif
 
   if (!game.restart_level)
   {
@@ -3515,8 +3969,15 @@ void GameWon()
       time = time_final;
       score = score_final;
 
+#if 1
+      game_control_value[GAME_CONTROL_TIME] = time;
+      game_control_value[GAME_CONTROL_SCORE] = score;
+
+      DisplayGameControlValues();
+#else
       DrawGameValue_Time(time);
       DrawGameValue_Score(score);
+#endif
     }
 
     if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
@@ -3590,8 +4051,15 @@ void GameWon()
     time  += time_count_steps * time_count_dir;
     score += time_count_steps * level.score[SC_TIME_BONUS];
 
+#if 1
+    game_control_value[GAME_CONTROL_TIME] = time;
+    game_control_value[GAME_CONTROL_SCORE] = score;
+
+    DisplayGameControlValues();
+#else
     DrawGameValue_Time(time);
     DrawGameValue_Score(score);
+#endif
 
     if (time == time_final)
       StopSound(SND_GAME_LEVELTIME_BONUS);
@@ -3643,14 +4111,20 @@ void GameEnd()
   {
     game_status = GAME_MODE_MAIN;
 
+#if 1
+    DrawAndFadeInMainMenu(REDRAW_FIELD);
+#else
     DrawMainMenu();
+#endif
 
     return;
   }
 
   if (!local_player->LevelSolved_SaveScore)
   {
+#if 1
     FadeOut(REDRAW_FIELD);
+#endif
 
     game_status = GAME_MODE_MAIN;
 
@@ -3682,7 +4156,9 @@ void GameEnd()
   }
   else
   {
+#if 1
     FadeOut(REDRAW_FIELD);
+#endif
 
     game_status = GAME_MODE_MAIN;
 
@@ -4163,12 +4639,14 @@ void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir,
 
   if (quick_relocation)
   {
-    int offset = (setup.scroll_delay ? 3 : 0);
+    int offset = game.scroll_delay_value;
 
     if (!IN_VIS_FIELD(SCREENX(x), SCREENY(y)) || center_screen)
     {
-      if (center_screen)
+      if (!level.shifted_relocation || center_screen)
       {
+       /* quick relocation (without scrolling), with centering of screen */
+
        scroll_x = (x < SBX_Left  + MIDPOSX ? SBX_Left :
                    x > SBX_Right + MIDPOSX ? SBX_Right :
                    x - MIDPOSX);
@@ -4203,6 +4681,8 @@ void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir,
     }
     else
     {
+      /* quick relocation (without scrolling), inside visible screen area */
+
       if ((move_dir == MV_LEFT  && scroll_x > x - MIDPOSX + offset) ||
          (move_dir == MV_RIGHT && scroll_x < x - MIDPOSX - offset))
        scroll_x = x - MIDPOSX + (scroll_x < x - MIDPOSX ? -offset : +offset);
@@ -4224,6 +4704,49 @@ void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir,
   }
   else
   {
+#if 1
+    int scroll_xx, scroll_yy;
+
+    if (!level.shifted_relocation || center_screen)
+    {
+      /* visible relocation (with scrolling), with centering of screen */
+
+      scroll_xx = (x < SBX_Left  + MIDPOSX ? SBX_Left :
+                  x > SBX_Right + MIDPOSX ? SBX_Right :
+                  x - MIDPOSX);
+
+      scroll_yy = (y < SBY_Upper + MIDPOSY ? SBY_Upper :
+                  y > SBY_Lower + MIDPOSY ? SBY_Lower :
+                  y - MIDPOSY);
+    }
+    else
+    {
+      /* visible relocation (with scrolling), but do not center screen */
+
+      int center_scroll_x = (old_x < SBX_Left  + MIDPOSX ? SBX_Left :
+                            old_x > SBX_Right + MIDPOSX ? SBX_Right :
+                            old_x - MIDPOSX);
+
+      int center_scroll_y = (old_y < SBY_Upper + MIDPOSY ? SBY_Upper :
+                            old_y > SBY_Lower + MIDPOSY ? SBY_Lower :
+                            old_y - MIDPOSY);
+
+      int offset_x = x + (scroll_x - center_scroll_x);
+      int offset_y = y + (scroll_y - center_scroll_y);
+
+      scroll_xx = (offset_x < SBX_Left  + MIDPOSX ? SBX_Left :
+                  offset_x > SBX_Right + MIDPOSX ? SBX_Right :
+                  offset_x - MIDPOSX);
+
+      scroll_yy = (offset_y < SBY_Upper + MIDPOSY ? SBY_Upper :
+                  offset_y > SBY_Lower + MIDPOSY ? SBY_Lower :
+                  offset_y - MIDPOSY);
+    }
+
+#else
+
+    /* visible relocation (with scrolling), with centering of screen */
+
     int scroll_xx = (x < SBX_Left  + MIDPOSX ? SBX_Left :
                     x > SBX_Right + MIDPOSX ? SBX_Right :
                     x - MIDPOSX);
@@ -4231,6 +4754,7 @@ void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir,
     int scroll_yy = (y < SBY_Upper + MIDPOSY ? SBY_Upper :
                     y > SBY_Lower + MIDPOSY ? SBY_Lower :
                     y - MIDPOSY);
+#endif
 
     ScrollScreen(NULL, SCROLL_GO_ON);  /* scroll last frame to full tile */
 
@@ -8969,7 +9493,13 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
       {
        TimeLeft = action_arg_number_new;
 
+#if 1
+       game_control_value[GAME_CONTROL_TIME] = TimeLeft;
+
+       DisplayGameControlValues();
+#else
        DrawGameValue_Time(TimeLeft);
+#endif
 
        if (!TimeLeft && setup.time_limit)
          for (i = 0; i < MAX_PLAYERS; i++)
@@ -8983,7 +9513,13 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
     {
       local_player->score = action_arg_number_new;
 
+#if 1
+      game_control_value[GAME_CONTROL_SCORE] = local_player->score;
+
+      DisplayGameControlValues();
+#else
       DrawGameValue_Score(local_player->score);
+#endif
 
       break;
     }
@@ -8992,7 +9528,13 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
     {
       local_player->gems_still_needed = action_arg_number_new;
 
+#if 1
+      game_control_value[GAME_CONTROL_GEMS] = local_player->gems_still_needed;
+
+      DisplayGameControlValues();
+#else
       DrawGameValue_Emeralds(local_player->gems_still_needed);
+#endif
 
       break;
     }
@@ -10267,7 +10809,13 @@ static void CheckLevelTime()
        if (TimeLeft <= 10 && setup.time_limit)
          PlaySound(SND_GAME_RUNNING_OUT_OF_TIME);
 
+#if 1
+       game_control_value[GAME_CONTROL_TIME] = TimeLeft;
+
+       DisplayGameControlValues();
+#else
        DrawGameValue_Time(TimeLeft);
+#endif
 
        if (!TimeLeft && setup.time_limit)
        {
@@ -10278,8 +10826,17 @@ static void CheckLevelTime()
              KillPlayer(&stored_player[i]);
        }
       }
+#if 1
+      else if (level.time == 0 && !AllPlayersGone) /* level w/o time limit */
+      {
+       game_control_value[GAME_CONTROL_TIME] = TimePlayed;
+
+       DisplayGameControlValues();
+      }
+#else
       else if (level.time == 0 && !AllPlayersGone) /* level w/o time limit */
        DrawGameValue_Time(TimePlayed);
+#endif
 
       level.native_em_level->lev->time =
        (level.time == 0 ? TimePlayed : TimeLeft);
@@ -10288,6 +10845,8 @@ static void CheckLevelTime()
     if (tape.recording || tape.playing)
       DrawVideoDisplay(VIDEO_STATE_TIME_ON, TapeTime);
   }
+
+  DrawGameDoorValues();
 }
 
 void AdvanceFrameAndPlayerCounters(int player_nr)
@@ -11703,7 +12262,7 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
 #endif
   {
     int old_scroll_x = scroll_x, old_scroll_y = scroll_y;
-    int offset = (setup.scroll_delay ? 3 : 0);
+    int offset = game.scroll_delay_value;
 
     if (!IN_VIS_FIELD(SCREENX(jx), SCREENY(jy)))
     {
@@ -12003,14 +12562,29 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
        if (TimeLeft <= 10 && setup.time_limit)
          PlaySound(SND_GAME_RUNNING_OUT_OF_TIME);
 
+#if 1
+       game_control_value[GAME_CONTROL_TIME] = TimeLeft;
+
+       DisplayGameControlValues();
+#else
        DrawGameValue_Time(TimeLeft);
+#endif
 
        if (!TimeLeft && setup.time_limit)
          for (i = 0; i < MAX_PLAYERS; i++)
            KillPlayer(&stored_player[i]);
       }
+#if 1
+      else if (level.time == 0 && !AllPlayersGone) /* level w/o time limit */
+      {
+       game_control_value[GAME_CONTROL_TIME] = TimePlayed;
+
+       DisplayGameControlValues();
+      }
+#else
       else if (level.time == 0 && !AllPlayersGone) /* level w/o time limit */
        DrawGameValue_Time(TimePlayed);
+#endif
     }
 
     if (tape.single_step && tape.recording && !tape.pausing &&
@@ -13059,7 +13633,14 @@ int DigField(struct PlayerInfo *player,
     else if (element == EL_EXTRA_TIME && level.time > 0)
     {
       TimeLeft += level.extra_time;
+
+#if 1
+      game_control_value[GAME_CONTROL_TIME] = TimeLeft;
+
+      DisplayGameControlValues();
+#else
       DrawGameValue_Time(TimeLeft);
+#endif
     }
     else if (element == EL_SHIELD_NORMAL || element == EL_SHIELD_DEADLY)
     {
@@ -13138,7 +13719,13 @@ int DigField(struct PlayerInfo *player,
       if (local_player->gems_still_needed < 0)
        local_player->gems_still_needed = 0;
 
+#if 1
+      game_control_value[GAME_CONTROL_GEMS] = local_player->gems_still_needed;
+
+      DisplayGameControlValues();
+#else
       DrawGameValue_Emeralds(local_player->gems_still_needed);
+#endif
     }
 
     RaiseScoreElement(element);
@@ -13382,7 +13969,14 @@ int DigField(struct PlayerInfo *player,
       if (level.time > 0 || level.use_time_orb_bug)
       {
        TimeLeft += level.time_orb_time;
+
+#if 1
+       game_control_value[GAME_CONTROL_TIME] = TimeLeft;
+
+       DisplayGameControlValues();
+#else
        DrawGameValue_Time(TimeLeft);
+#endif
       }
 
       ResetGfxAnimation(x, y);
@@ -13554,6 +14148,9 @@ boolean DropElement(struct PlayerInfo *player)
   int dropx = player->jx, dropy = player->jy;
   int drop_direction = player->MovDir;
   int drop_side = drop_direction;
+#if 1
+  int drop_element = get_next_drop_element(player);
+#else
   int drop_element = (player->inventory_size > 0 ?
                      player->inventory_element[player->inventory_size - 1] :
                      player->inventory_infinite_element != EL_UNDEFINED ?
@@ -13561,6 +14158,7 @@ boolean DropElement(struct PlayerInfo *player)
                      player->dynabombs_left > 0 ?
                      EL_DYNABOMB_PLAYER_1_ACTIVE + player->index_nr :
                      EL_UNDEFINED);
+#endif
 
   player->is_dropping_pressed = TRUE;
 
@@ -14004,7 +14602,13 @@ void RaiseScore(int value)
 {
   local_player->score += value;
 
+#if 1
+  game_control_value[GAME_CONTROL_SCORE] = local_player->score;
+
+  DisplayGameControlValues();
+#else
   DrawGameValue_Score(local_player->score);
+#endif
 }
 
 void RaiseScoreElement(int element)
@@ -14099,13 +14703,31 @@ void RequestQuitGameExt(boolean skip_request, boolean quick_quit, char *message)
     {
       if (quick_quit)
       {
+#if 1
+
+#if 1
+       FadeSkipNextFadeIn();
+#else
+       fading = fading_none;
+#endif
+
+#else
+       OpenDoor(DOOR_CLOSE_1);
+#endif
+
        game_status = GAME_MODE_MAIN;
 
+#if 1
+       DrawAndFadeInMainMenu(REDRAW_FIELD);
+#else
        DrawMainMenu();
+#endif
       }
       else
       {
+#if 0
        FadeOut(REDRAW_FIELD);
+#endif
 
        game_status = GAME_MODE_MAIN;