rnd-20070405-1-src
[rocksndiamonds.git] / src / game.c
index 17981be5ad1d002cd3d615a05896e6b5dc109c00..d159b46fdd1a5843cf2bd899252fb2048f7977e1 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_TEXT_XPOS(p))
 #define PANEL_YPOS(p)          (DY + ALIGNED_TEXT_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
 
 /* 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_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
-
-struct GameControlInfo
+#define GAME_PANEL_LEVEL_NUMBER                0
+#define GAME_PANEL_GEMS                        1
+#define GAME_PANEL_INVENTORY_COUNT             2
+#define GAME_PANEL_INVENTORY_FIRST_1           3
+#define GAME_PANEL_INVENTORY_FIRST_2           4
+#define GAME_PANEL_INVENTORY_FIRST_3           5
+#define GAME_PANEL_INVENTORY_FIRST_4           6
+#define GAME_PANEL_INVENTORY_FIRST_5           7
+#define GAME_PANEL_INVENTORY_FIRST_6           8
+#define GAME_PANEL_INVENTORY_FIRST_7           9
+#define GAME_PANEL_INVENTORY_FIRST_8           10
+#define GAME_PANEL_INVENTORY_LAST_1            11
+#define GAME_PANEL_INVENTORY_LAST_2            12
+#define GAME_PANEL_INVENTORY_LAST_3            13
+#define GAME_PANEL_INVENTORY_LAST_4            14
+#define GAME_PANEL_INVENTORY_LAST_5            15
+#define GAME_PANEL_INVENTORY_LAST_6            16
+#define GAME_PANEL_INVENTORY_LAST_7            17
+#define GAME_PANEL_INVENTORY_LAST_8            18
+#define GAME_PANEL_KEY_1                       19
+#define GAME_PANEL_KEY_2                       20
+#define GAME_PANEL_KEY_3                       21
+#define GAME_PANEL_KEY_4                       22
+#define GAME_PANEL_KEY_5                       23
+#define GAME_PANEL_KEY_6                       24
+#define GAME_PANEL_KEY_7                       25
+#define GAME_PANEL_KEY_8                       26
+#define GAME_PANEL_KEY_WHITE                   27
+#define GAME_PANEL_KEY_WHITE_COUNT             28
+#define GAME_PANEL_SCORE                       29
+#define GAME_PANEL_TIME                        30
+#define GAME_PANEL_TIME_HH                     31
+#define GAME_PANEL_TIME_MM                     32
+#define GAME_PANEL_TIME_SS                     33
+#define GAME_PANEL_SHIELD_NORMAL               34
+#define GAME_PANEL_SHIELD_NORMAL_TIME          35
+#define GAME_PANEL_SHIELD_DEADLY               36
+#define GAME_PANEL_SHIELD_DEADLY_TIME          37
+#define GAME_PANEL_EXIT                        38
+#define GAME_PANEL_EMC_MAGIC_BALL              39
+#define GAME_PANEL_EMC_MAGIC_BALL_SWITCH       40
+#define GAME_PANEL_LIGHT_SWITCH                41
+#define GAME_PANEL_LIGHT_SWITCH_TIME           42
+#define GAME_PANEL_TIMEGATE_SWITCH             43
+#define GAME_PANEL_TIMEGATE_SWITCH_TIME        44
+#define GAME_PANEL_SWITCHGATE_SWITCH           45
+#define GAME_PANEL_EMC_LENSES                  46
+#define GAME_PANEL_EMC_LENSES_TIME             47
+#define GAME_PANEL_EMC_MAGNIFIER               48
+#define GAME_PANEL_EMC_MAGNIFIER_TIME          49
+#define GAME_PANEL_BALLOON_SWITCH              50
+#define GAME_PANEL_DYNABOMB_NUMBER             51
+#define GAME_PANEL_DYNABOMB_SIZE               52
+#define GAME_PANEL_DYNABOMB_POWER              53
+#define GAME_PANEL_PENGUINS                    54
+#define GAME_PANEL_SOKOBAN_OBJECTS             55
+#define GAME_PANEL_SOKOBAN_FIELDS              56
+#define GAME_PANEL_ROBOT_WHEEL         57
+#define GAME_PANEL_CONVEYOR_BELT_1             58
+#define GAME_PANEL_CONVEYOR_BELT_1_SWITCH      59
+#define GAME_PANEL_CONVEYOR_BELT_2             60
+#define GAME_PANEL_CONVEYOR_BELT_2_SWITCH      61
+#define GAME_PANEL_CONVEYOR_BELT_3             62
+#define GAME_PANEL_CONVEYOR_BELT_3_SWITCH      63
+#define GAME_PANEL_CONVEYOR_BELT_4             64
+#define GAME_PANEL_CONVEYOR_BELT_4_SWITCH      65
+#define GAME_PANEL_MAGIC_WALL                  66
+#define GAME_PANEL_MAGIC_WALL_TIME             67
+#define GAME_PANEL_GRAVITY_STATE               68
+#define GAME_PANEL_PLAYER_NAME         69
+#define GAME_PANEL_LEVEL_NAME                  70
+#define GAME_PANEL_LEVEL_AUTHOR                71
+
+#define NUM_GAME_PANEL_CONTROLS                        72
+
+struct GamePanelControlInfo
 {
   int nr;
 
-  struct TextPosInfo *pos_text;
+  struct TextPosInfo *pos;
   int type;
-  void *ptr;
+
+  int value, last_value;
+  int frame, last_frame;
+  int gfx_frame;
 };
 
-static struct GameControlInfo game_controls[] =
+static struct GamePanelControlInfo game_panel_controls[] =
 {
   {
-    GAME_CONTROL_LEVEL,
-    &game.panel.level,
+    GAME_PANEL_LEVEL_NUMBER,
+    &game.panel.level_number,
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_GEMS,
+    GAME_PANEL_GEMS,
     &game.panel.gems,
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_INVENTORY,
-    &game.panel.inventory,
+    GAME_PANEL_INVENTORY_COUNT,
+    &game.panel.inventory_count,
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_KEYS,
-    &game.panel.keys,
-    TYPE_INTEGER,
+    GAME_PANEL_INVENTORY_FIRST_1,
+    &game.panel.inventory_first_1,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_SCORE,
-    &game.panel.score,
-    TYPE_INTEGER,
+    GAME_PANEL_INVENTORY_FIRST_2,
+    &game.panel.inventory_first_2,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_TIME,
-    &game.panel.time,
-    TYPE_INTEGER,
+    GAME_PANEL_INVENTORY_FIRST_3,
+    &game.panel.inventory_first_3,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_TIME_HH,
-    &game.panel.time_hh,
-    TYPE_INTEGER,
+    GAME_PANEL_INVENTORY_FIRST_4,
+    &game.panel.inventory_first_4,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_TIME_MM,
-    &game.panel.time_mm,
-    TYPE_INTEGER,
+    GAME_PANEL_INVENTORY_FIRST_5,
+    &game.panel.inventory_first_5,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_TIME_SS,
-    &game.panel.time_ss,
-    TYPE_INTEGER,
+    GAME_PANEL_INVENTORY_FIRST_6,
+    &game.panel.inventory_first_6,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DROP_NEXT_1,
-    &game.panel.drop_next_1,
-    TYPE_INTEGER,
+    GAME_PANEL_INVENTORY_FIRST_7,
+    &game.panel.inventory_first_7,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DROP_NEXT_2,
-    &game.panel.drop_next_2,
-    TYPE_INTEGER,
+    GAME_PANEL_INVENTORY_FIRST_8,
+    &game.panel.inventory_first_8,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DROP_NEXT_3,
-    &game.panel.drop_next_3,
-    TYPE_INTEGER,
+    GAME_PANEL_INVENTORY_LAST_1,
+    &game.panel.inventory_last_1,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DROP_NEXT_4,
-    &game.panel.drop_next_4,
-    TYPE_INTEGER,
+    GAME_PANEL_INVENTORY_LAST_2,
+    &game.panel.inventory_last_2,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DROP_NEXT_5,
-    &game.panel.drop_next_5,
-    TYPE_INTEGER,
+    GAME_PANEL_INVENTORY_LAST_3,
+    &game.panel.inventory_last_3,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DROP_NEXT_6,
-    &game.panel.drop_next_6,
-    TYPE_INTEGER,
+    GAME_PANEL_INVENTORY_LAST_4,
+    &game.panel.inventory_last_4,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DROP_NEXT_7,
-    &game.panel.drop_next_7,
-    TYPE_INTEGER,
+    GAME_PANEL_INVENTORY_LAST_5,
+    &game.panel.inventory_last_5,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DROP_NEXT_8,
-    &game.panel.drop_next_8,
-    TYPE_INTEGER,
+    GAME_PANEL_INVENTORY_LAST_6,
+    &game.panel.inventory_last_6,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_EMC_KEYS,
-    &game.panel.emc_keys,
-    TYPE_INTEGER,
+    GAME_PANEL_INVENTORY_LAST_7,
+    &game.panel.inventory_last_7,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_KEY_1,
-    &game.panel.key_1,
-    TYPE_INTEGER,
+    GAME_PANEL_INVENTORY_LAST_8,
+    &game.panel.inventory_last_8,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_KEY_2,
-    &game.panel.key_2,
-    TYPE_INTEGER,
+    GAME_PANEL_KEY_1,
+    &game.panel.key[0],
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_KEY_3,
-    &game.panel.key_3,
-    TYPE_INTEGER,
+    GAME_PANEL_KEY_2,
+    &game.panel.key[1],
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_KEY_4,
-    &game.panel.key_4,
-    TYPE_INTEGER,
+    GAME_PANEL_KEY_3,
+    &game.panel.key[2],
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_KEY_5,
-    &game.panel.key_5,
-    TYPE_INTEGER,
+    GAME_PANEL_KEY_4,
+    &game.panel.key[3],
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_KEY_6,
-    &game.panel.key_6,
-    TYPE_INTEGER,
+    GAME_PANEL_KEY_5,
+    &game.panel.key[4],
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_KEY_7,
-    &game.panel.key_7,
-    TYPE_INTEGER,
+    GAME_PANEL_KEY_6,
+    &game.panel.key[5],
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_KEY_8,
-    &game.panel.key_8,
-    TYPE_INTEGER,
+    GAME_PANEL_KEY_7,
+    &game.panel.key[6],
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_KEY_WHITE,
+    GAME_PANEL_KEY_8,
+    &game.panel.key[7],
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_KEY_WHITE,
     &game.panel.key_white,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_KEY_WHITE_COUNT,
+    GAME_PANEL_KEY_WHITE_COUNT,
     &game.panel.key_white_count,
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_SHIELD_NORMAL,
-    &game.panel.shield_normal,
+    GAME_PANEL_SCORE,
+    &game.panel.score,
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_SHIELD_NORMAL_TIME,
-    &game.panel.shield_normal_time,
+    GAME_PANEL_TIME,
+    &game.panel.time,
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_SHIELD_DEADLY,
-    &game.panel.shield_deadly,
+    GAME_PANEL_TIME_HH,
+    &game.panel.time_hh,
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_SHIELD_DEADLY_TIME,
-    &game.panel.shield_deadly_time,
+    GAME_PANEL_TIME_MM,
+    &game.panel.time_mm,
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_EXIT,
-    &game.panel.exit,
+    GAME_PANEL_TIME_SS,
+    &game.panel.time_ss,
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_EM_EXIT,
-    &game.panel.em_exit,
-    TYPE_INTEGER,
+    GAME_PANEL_SHIELD_NORMAL,
+    &game.panel.shield_normal,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_SP_EXIT,
-    &game.panel.sp_exit,
+    GAME_PANEL_SHIELD_NORMAL_TIME,
+    &game.panel.shield_normal_time,
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_STEEL_EXIT,
-    &game.panel.steel_exit,
-    TYPE_INTEGER,
+    GAME_PANEL_SHIELD_DEADLY,
+    &game.panel.shield_deadly,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_EM_STEEL_EXIT,
-    &game.panel.em_steel_exit,
+    GAME_PANEL_SHIELD_DEADLY_TIME,
+    &game.panel.shield_deadly_time,
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_EMC_MAGIC_BALL,
+    GAME_PANEL_EXIT,
+    &game.panel.exit,
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_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_PANEL_EMC_MAGIC_BALL_SWITCH,
+    &game.panel.emc_magic_ball_switch,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_LIGHT_SWITCH,
+    GAME_PANEL_LIGHT_SWITCH,
     &game.panel.light_switch,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_LIGHT_SWITCH_TIME,
+    GAME_PANEL_LIGHT_SWITCH_TIME,
     &game.panel.light_switch_time,
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_TIMEGATE_SWITCH,
+    GAME_PANEL_TIMEGATE_SWITCH,
     &game.panel.timegate_switch,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_TIMEGATE_SWITCH_TIME,
+    GAME_PANEL_TIMEGATE_SWITCH_TIME,
     &game.panel.timegate_switch_time,
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_SWITCHGATE_SWITCH,
+    GAME_PANEL_SWITCHGATE_SWITCH,
     &game.panel.switchgate_switch,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_EMC_LENSES,
+    GAME_PANEL_EMC_LENSES,
     &game.panel.emc_lenses,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_EMC_LENSES_TIME,
+    GAME_PANEL_EMC_LENSES_TIME,
     &game.panel.emc_lenses_time,
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_EMC_MAGNIFIER,
+    GAME_PANEL_EMC_MAGNIFIER,
     &game.panel.emc_magnifier,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_EMC_MAGNIFIER_TIME,
+    GAME_PANEL_EMC_MAGNIFIER_TIME,
     &game.panel.emc_magnifier_time,
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_BALLOON_SWITCH,
+    GAME_PANEL_BALLOON_SWITCH,
     &game.panel.balloon_switch,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DYNABOMB_NUMBER,
+    GAME_PANEL_DYNABOMB_NUMBER,
     &game.panel.dynabomb_number,
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_DYNABOMB_SIZE,
+    GAME_PANEL_DYNABOMB_SIZE,
     &game.panel.dynabomb_size,
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_DYNABOMB_POWER,
+    GAME_PANEL_DYNABOMB_POWER,
     &game.panel.dynabomb_power,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_PENGUINS,
+    GAME_PANEL_PENGUINS,
     &game.panel.penguins,
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_SOKOBAN_OBJECTS,
+    GAME_PANEL_SOKOBAN_OBJECTS,
     &game.panel.sokoban_objects,
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_SOKOBAN_FIELDS,
+    GAME_PANEL_SOKOBAN_FIELDS,
     &game.panel.sokoban_fields,
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_ROBOT_WHEEL,
+    GAME_PANEL_ROBOT_WHEEL,
     &game.panel.robot_wheel,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_CONVEYOR_BELT_1,
+    GAME_PANEL_CONVEYOR_BELT_1,
     &game.panel.conveyor_belt_1,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_CONVEYOR_BELT_1_SWITCH,
+    GAME_PANEL_CONVEYOR_BELT_1_SWITCH,
     &game.panel.conveyor_belt_1_switch,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_CONVEYOR_BELT_2,
+    GAME_PANEL_CONVEYOR_BELT_2,
     &game.panel.conveyor_belt_2,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_CONVEYOR_BELT_2_SWITCH,
+    GAME_PANEL_CONVEYOR_BELT_2_SWITCH,
     &game.panel.conveyor_belt_2_switch,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_CONVEYOR_BELT_3,
+    GAME_PANEL_CONVEYOR_BELT_3,
     &game.panel.conveyor_belt_3,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_CONVEYOR_BELT_3_SWITCH,
+    GAME_PANEL_CONVEYOR_BELT_3_SWITCH,
     &game.panel.conveyor_belt_3_switch,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_CONVEYOR_BELT_4,
+    GAME_PANEL_CONVEYOR_BELT_4,
     &game.panel.conveyor_belt_4,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_CONVEYOR_BELT_4_SWITCH,
+    GAME_PANEL_CONVEYOR_BELT_4_SWITCH,
     &game.panel.conveyor_belt_4_switch,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_MAGIC_WALL,
+    GAME_PANEL_MAGIC_WALL,
     &game.panel.magic_wall,
-    TYPE_INTEGER,
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_MAGIC_WALL_TIME,
+    GAME_PANEL_MAGIC_WALL_TIME,
     &game.panel.magic_wall_time,
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_BD_MAGIC_WALL,
-    &game.panel.bd_magic_wall,
-    TYPE_INTEGER,
-  },
-  {
-    GAME_CONTROL_DC_MAGIC_WALL,
-    &game.panel.dc_magic_wall,
-    TYPE_INTEGER,
+    GAME_PANEL_GRAVITY_STATE,
+    &game.panel.gravity_state,
+    TYPE_STRING,
   },
   {
-    GAME_CONTROL_PLAYER_NAME,
+    GAME_PANEL_PLAYER_NAME,
     &game.panel.player_name,
-    TYPE_INTEGER,
+    TYPE_STRING,
   },
   {
-    GAME_CONTROL_LEVEL_NAME,
+    GAME_PANEL_LEVEL_NAME,
     &game.panel.level_name,
-    TYPE_INTEGER,
+    TYPE_STRING,
   },
   {
-    GAME_CONTROL_LEVEL_AUTHOR,
+    GAME_PANEL_LEVEL_AUTHOR,
     &game.panel.level_author,
-    TYPE_INTEGER,
+    TYPE_STRING,
   },
 
   {
     -1,
     NULL,
     -1,
-    NULL
   }
 };
 #endif
@@ -1735,6 +1741,443 @@ 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_dropped_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_inventory_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 + 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 + player->index_nr :
+           player->inventory_size >= min_inventory_size ?
+           player->inventory_element[inventory_pos] :
+           EL_UNDEFINED);
+  }
+}
+
+void InitGameControlValues()
+{
+  int i;
+
+  for (i = 0; game_panel_controls[i].nr != -1; i++)
+  {
+    struct GamePanelControlInfo *gpc = &game_panel_controls[i];
+    int nr = gpc->nr;
+    int type = gpc->type;
+    struct TextPosInfo *pos = gpc->pos;
+
+    if (nr != i)
+    {
+      Error(ERR_INFO, "'game_panel_controls' structure corrupted");
+      Error(ERR_EXIT, "this should not happen -- please debug");
+    }
+
+    /* force update of game controls after initialization */
+    gpc->value = gpc->last_value = -1;
+    gpc->frame = gpc->last_frame = -1;
+    gpc->gfx_frame = -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);
+  int exit_closed = (local_player->gems_still_needed > 0 ||
+                    local_player->sokobanfields_still_needed > 0 ||
+                    local_player->lights_still_needed > 0);
+
+  game_panel_controls[GAME_PANEL_LEVEL_NUMBER].value = level_nr;
+  game_panel_controls[GAME_PANEL_GEMS].value =
+    local_player->gems_still_needed;
+
+  game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value = 0;
+  for (i = 0; i < MAX_NUM_KEYS; i++)
+    game_panel_controls[GAME_PANEL_KEY_1 + i].value = EL_EMPTY;
+  game_panel_controls[GAME_PANEL_KEY_WHITE].value = EL_EMPTY;
+  game_panel_controls[GAME_PANEL_KEY_WHITE_COUNT].value = 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_panel_controls[GAME_PANEL_KEY_1 + k].value =
+           get_key_element_from_nr(k);
+
+      game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
+       stored_player[i].inventory_size;
+
+      if (stored_player[i].num_white_keys > 0)
+       game_panel_controls[GAME_PANEL_KEY_WHITE].value =
+         EL_DC_KEY_WHITE;
+
+      game_panel_controls[GAME_PANEL_KEY_WHITE_COUNT].value +=
+       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_panel_controls[GAME_PANEL_KEY_1 + k].value =
+         get_key_element_from_nr(k);
+
+    game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
+      stored_player[player_nr].inventory_size;
+
+    if (stored_player[player_nr].num_white_keys > 0)
+      game_panel_controls[GAME_PANEL_KEY_WHITE].value = EL_DC_KEY_WHITE;
+
+    game_panel_controls[GAME_PANEL_KEY_WHITE_COUNT].value +=
+      stored_player[player_nr].num_white_keys;
+  }
+
+  for (i = 0; i < 8; i++)
+  {
+    game_panel_controls[GAME_PANEL_INVENTORY_FIRST_1 + i].value =
+      get_inventory_element_from_pos(local_player, i);
+    game_panel_controls[GAME_PANEL_INVENTORY_LAST_1 + i].value =
+      get_inventory_element_from_pos(local_player, -i - 1);
+  }
+
+  game_panel_controls[GAME_PANEL_SCORE].value = score;
+
+  game_panel_controls[GAME_PANEL_TIME].value = time;
+
+  game_panel_controls[GAME_PANEL_TIME_HH].value = time / 3600;
+  game_panel_controls[GAME_PANEL_TIME_MM].value = (time / 60) % 60;
+  game_panel_controls[GAME_PANEL_TIME_SS].value = time % 60;
+
+  game_panel_controls[GAME_PANEL_SHIELD_NORMAL].value =
+    (local_player->shield_normal_time_left > 0 ? EL_SHIELD_NORMAL_ACTIVE :
+     EL_EMPTY);
+  game_panel_controls[GAME_PANEL_SHIELD_NORMAL_TIME].value =
+    local_player->shield_normal_time_left;
+  game_panel_controls[GAME_PANEL_SHIELD_DEADLY].value =
+    (local_player->shield_deadly_time_left > 0 ? EL_SHIELD_DEADLY_ACTIVE :
+     EL_EMPTY);
+  game_panel_controls[GAME_PANEL_SHIELD_DEADLY_TIME].value =
+    local_player->shield_deadly_time_left;
+
+  game_panel_controls[GAME_PANEL_EXIT].value =
+    (exit_closed ? EL_EXIT_CLOSED : EL_EXIT_OPEN);
+
+  game_panel_controls[GAME_PANEL_EMC_MAGIC_BALL].value =
+    (game.ball_state ? EL_EMC_MAGIC_BALL_ACTIVE : EL_EMC_MAGIC_BALL);
+  game_panel_controls[GAME_PANEL_EMC_MAGIC_BALL_SWITCH].value =
+    (game.ball_state ? EL_EMC_MAGIC_BALL_SWITCH_ACTIVE :
+     EL_EMC_MAGIC_BALL_SWITCH);
+
+  game_panel_controls[GAME_PANEL_LIGHT_SWITCH].value =
+    (game.light_time_left > 0 ? EL_LIGHT_SWITCH_ACTIVE : EL_LIGHT_SWITCH);
+  game_panel_controls[GAME_PANEL_LIGHT_SWITCH_TIME].value =
+    game.light_time_left;
+
+  game_panel_controls[GAME_PANEL_TIMEGATE_SWITCH].value =
+    (game.timegate_time_left > 0 ? EL_TIMEGATE_OPEN : EL_TIMEGATE_CLOSED);
+  game_panel_controls[GAME_PANEL_TIMEGATE_SWITCH_TIME].value =
+    game.timegate_time_left;
+
+  game_panel_controls[GAME_PANEL_SWITCHGATE_SWITCH].value =
+    EL_SWITCHGATE_SWITCH_UP + game.switchgate_pos;
+
+  game_panel_controls[GAME_PANEL_EMC_LENSES].value =
+    (game.lenses_time_left > 0 ? EL_EMC_LENSES : EL_EMPTY);
+  game_panel_controls[GAME_PANEL_EMC_LENSES_TIME].value =
+    game.lenses_time_left;
+
+  game_panel_controls[GAME_PANEL_EMC_MAGNIFIER].value =
+    (game.magnify_time_left > 0 ? EL_EMC_MAGNIFIER : EL_EMPTY);
+  game_panel_controls[GAME_PANEL_EMC_MAGNIFIER_TIME].value =
+    game.magnify_time_left;
+
+  game_panel_controls[GAME_PANEL_BALLOON_SWITCH].value =
+    (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_panel_controls[GAME_PANEL_DYNABOMB_NUMBER].value =
+    local_player->dynabomb_count;
+  game_panel_controls[GAME_PANEL_DYNABOMB_SIZE].value =
+    local_player->dynabomb_size;
+  game_panel_controls[GAME_PANEL_DYNABOMB_POWER].value =
+    (local_player->dynabomb_xl ? EL_DYNABOMB_INCREASE_POWER : EL_EMPTY);
+
+  game_panel_controls[GAME_PANEL_PENGUINS].value =
+    local_player->friends_still_needed;
+
+  game_panel_controls[GAME_PANEL_SOKOBAN_OBJECTS].value =
+    local_player->sokobanfields_still_needed;
+  game_panel_controls[GAME_PANEL_SOKOBAN_FIELDS].value =
+    local_player->sokobanfields_still_needed;
+
+  game_panel_controls[GAME_PANEL_ROBOT_WHEEL].value =
+    (game.robot_wheel_active ? EL_ROBOT_WHEEL_ACTIVE : EL_ROBOT_WHEEL);
+
+  game_panel_controls[GAME_PANEL_CONVEYOR_BELT_1].value =
+    (game.belt_dir[0] != MV_NONE ? EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE :
+     EL_CONVEYOR_BELT_1_MIDDLE);
+  game_panel_controls[GAME_PANEL_CONVEYOR_BELT_1_SWITCH].value =
+    getBeltSwitchElementFromBeltNrAndBeltDir(0, game.belt_dir[0]);
+  game_panel_controls[GAME_PANEL_CONVEYOR_BELT_2].value =
+    (game.belt_dir[1] != MV_NONE ? EL_CONVEYOR_BELT_2_MIDDLE_ACTIVE :
+     EL_CONVEYOR_BELT_2_MIDDLE);
+  game_panel_controls[GAME_PANEL_CONVEYOR_BELT_2_SWITCH].value =
+    getBeltSwitchElementFromBeltNrAndBeltDir(1, game.belt_dir[1]);
+  game_panel_controls[GAME_PANEL_CONVEYOR_BELT_3].value =
+    (game.belt_dir[2] != MV_NONE ? EL_CONVEYOR_BELT_3_MIDDLE_ACTIVE :
+     EL_CONVEYOR_BELT_3_MIDDLE);
+  game_panel_controls[GAME_PANEL_CONVEYOR_BELT_3_SWITCH].value =
+    getBeltSwitchElementFromBeltNrAndBeltDir(2, game.belt_dir[2]);
+  game_panel_controls[GAME_PANEL_CONVEYOR_BELT_4].value =
+    (game.belt_dir[3] != MV_NONE ? EL_CONVEYOR_BELT_4_MIDDLE_ACTIVE :
+     EL_CONVEYOR_BELT_4_MIDDLE);
+  game_panel_controls[GAME_PANEL_CONVEYOR_BELT_4_SWITCH].value =
+    getBeltSwitchElementFromBeltNrAndBeltDir(3, game.belt_dir[3]);
+
+  game_panel_controls[GAME_PANEL_MAGIC_WALL].value =
+    (game.magic_wall_active ? EL_MAGIC_WALL_ACTIVE : EL_MAGIC_WALL);
+  game_panel_controls[GAME_PANEL_MAGIC_WALL_TIME].value =
+    game.magic_wall_time_left;
+
+#if USE_PLAYER_GRAVITY
+  game_panel_controls[GAME_PANEL_GRAVITY_STATE].value =
+    local_player->gravity;
+#else
+  game_panel_controls[GAME_PANEL_GRAVITY_STATE].value = game.gravity;
+#endif
+
+  game_panel_controls[GAME_PANEL_PLAYER_NAME].value = 0;
+  game_panel_controls[GAME_PANEL_LEVEL_NAME].value = 0;
+  game_panel_controls[GAME_PANEL_LEVEL_AUTHOR].value = 0;
+
+  for (i = 0; game_panel_controls[i].nr != -1; i++)
+  {
+    struct GamePanelControlInfo *gpc = &game_panel_controls[i];
+
+    if (gpc->type == TYPE_ELEMENT)
+    {
+      if (gpc->value != gpc->last_value)
+       gpc->gfx_frame = 0;
+      else
+       gpc->gfx_frame++;
+
+      gpc->frame = getGraphicAnimationFrame(el2panelimg(gpc->value),
+                                           gpc->gfx_frame);
+    }
+  }
+}
+
+void DisplayGameControlValues()
+{
+  int i;
+
+  game_status = GAME_MODE_PSEUDO_PANEL;
+
+  for (i = 0; game_panel_controls[i].nr != -1; i++)
+  {
+    struct GamePanelControlInfo *gpc = &game_panel_controls[i];
+    int nr = gpc->nr;
+    int type = gpc->type;
+    struct TextPosInfo *pos = gpc->pos;
+    int value = gpc->value;
+    int frame = gpc->frame;
+    int last_value = gpc->last_value;
+    int last_frame = gpc->last_frame;
+    int size = pos->size;
+    int font = pos->font;
+
+    if (value == last_value && frame == last_frame)
+      continue;
+
+    gpc->last_value = value;
+    gpc->last_frame = frame;
+
+#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_PANEL_LEVEL_NUMBER ||
+         nr == GAME_PANEL_TIME)
+      {
+       boolean use_dynamic_size = (size == -1 ? TRUE : FALSE);
+
+       if (use_dynamic_size)           /* use dynamic number of digits */
+       {
+         int value_change = (nr == GAME_PANEL_LEVEL_NUMBER ? 100 : 1000);
+         int size1 = (nr == GAME_PANEL_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 = el2panelimg(value);
+
+       DrawSizedGraphicExt(drawto, dst_x, dst_y, graphic, frame, size);
+      }
+    }
+    else if (type == TYPE_STRING)
+    {
+      boolean active = (value != 0);
+      char *state_normal = "off";
+      char *state_active = "on";
+      char *state = (active ? state_active : state_normal);
+      char *s = (nr == GAME_PANEL_GRAVITY_STATE ? state :
+                nr == GAME_PANEL_PLAYER_NAME   ? setup.player_name :
+                nr == GAME_PANEL_LEVEL_NAME    ? level.name :
+                nr == GAME_PANEL_LEVEL_AUTHOR  ? level.author : NULL);
+
+      if (nr == GAME_PANEL_GRAVITY_STATE)
+      {
+       int font1 = pos->font;          /* (used for normal state) */
+       int font2 = pos->font_alt;      /* (used for active state) */
+       int size1 = strlen(state_normal);
+       int size2 = strlen(state_active);
+       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;
+
+       /* clear background for values that may have changed its size */
+       ClearRectangleOnBackground(drawto, PANEL_XPOS(pos), PANEL_YPOS(pos),
+                                  max_width, max_height);
+
+       font = (active ? font2 : font1);
+      }
+
+#if 1
+      /* as with numbers, don't truncate output if "chars" is zero or less */
+      size = (size > 0 ? size : strlen(s));
+#endif
+
+      if (s != NULL)
+      {
+       char *s_cut = getStringCopyN(s, size);
+
+#if 0
+       /* (not needed anymore with above correction of "size" value) */
+       size = strlen(s_cut);   /* string size may be smaller than "chars" */
+#endif
+
+       pos->width = size * getFontWidth(font);
+
+       DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), s_cut, font);
+
+       free(s_cut);
+      }
+    }
+
+    redraw_mask |= REDRAW_DOOR_1;
+  }
+
+  game_status = GAME_MODE_PLAYING;
+}
+
 void DrawGameValue_Emeralds(int value)
 {
   struct TextPosInfo *pos = &game.panel.gems;
@@ -1744,7 +2187,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 +2203,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 +2233,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 +2253,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 +2264,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 +2303,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 +2314,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 +2342,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 +2370,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 +2451,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);
@@ -2094,7 +2561,17 @@ void DrawAllGameValues(int emeralds, int dynamite, int score, int time,
   DrawGameValue_Keys(key);
 }
 
+void UpdateGameDoorValues()
+{
+  UpdateGameControlValues();
+}
+
 void DrawGameDoorValues()
+{
+  DisplayGameControlValues();
+}
+
+void DrawGameDoorValues_OLD()
 {
   int time_value = (level.time == 0 ? TimePlayed : TimeLeft);
   int dynamite_value = 0;
@@ -2563,6 +3040,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 +3086,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);
@@ -2766,6 +3253,7 @@ void InitGame()
   AllPlayersGone = FALSE;
 
   game.yamyam_content_nr = 0;
+  game.robot_wheel_active = FALSE;
   game.magic_wall_active = FALSE;
   game.magic_wall_time_left = 0;
   game.light_time_left = 0;
@@ -3088,7 +3576,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 +3594,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 +3615,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;
@@ -3156,13 +3647,34 @@ void InitGame()
                local_player->jy - MIDPOSY);
   }
 
+  /* do not use PLAYING mask for fading out from main screen */
+  game_status = GAME_MODE_MAIN;
+
   StopAnimation();
 
   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
+
+  game_status = GAME_MODE_PLAYING;
 
   /* !!! FIX THIS (START) !!! */
   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
@@ -3189,10 +3701,14 @@ void InitGame()
   }
   /* !!! FIX THIS (END) !!! */
 
+#if 1
+  FadeIn(REDRAW_FIELD);
+#else
   if (do_fading)
     FadeIn(REDRAW_FIELD);
 
   BackToFront();
+#endif
 
   if (!game.restart_level)
   {
@@ -3204,6 +3720,7 @@ void InitGame()
   SetPanelBackground();
   SetDrawBackgroundMask(REDRAW_DOOR_1);
 
+  UpdateGameDoorValues();
   DrawGameDoorValues();
 
   if (!game.restart_level)
@@ -3515,8 +4032,15 @@ void GameWon()
       time = time_final;
       score = score_final;
 
+#if 1
+      game_panel_controls[GAME_PANEL_TIME].value = time;
+      game_panel_controls[GAME_PANEL_SCORE].value = score;
+
+      DisplayGameControlValues();
+#else
       DrawGameValue_Time(time);
       DrawGameValue_Score(score);
+#endif
     }
 
     if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
@@ -3590,8 +4114,15 @@ void GameWon()
     time  += time_count_steps * time_count_dir;
     score += time_count_steps * level.score[SC_TIME_BONUS];
 
+#if 1
+    game_panel_controls[GAME_PANEL_TIME].value = time;
+    game_panel_controls[GAME_PANEL_SCORE].value = score;
+
+    DisplayGameControlValues();
+#else
     DrawGameValue_Time(time);
     DrawGameValue_Score(score);
+#endif
 
     if (time == time_final)
       StopSound(SND_GAME_LEVELTIME_BONUS);
@@ -3643,14 +4174,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 +4219,9 @@ void GameEnd()
   }
   else
   {
+#if 1
     FadeOut(REDRAW_FIELD);
+#endif
 
     game_status = GAME_MODE_MAIN;
 
@@ -4163,12 +4702,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 +4744,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 +4767,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 +4817,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 */
 
@@ -8207,7 +8794,11 @@ static void RunRobotWheel(int x, int y)
 static void StopRobotWheel(int x, int y)
 {
   if (ZX == x && ZY == y)
+  {
     ZX = ZY = -1;
+
+    game.robot_wheel_active = FALSE;
+  }
 }
 
 static void InitTimegateWheel(int x, int y)
@@ -8969,7 +9560,13 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
       {
        TimeLeft = action_arg_number_new;
 
+#if 1
+       game_panel_controls[GAME_PANEL_TIME].value = TimeLeft;
+
+       DisplayGameControlValues();
+#else
        DrawGameValue_Time(TimeLeft);
+#endif
 
        if (!TimeLeft && setup.time_limit)
          for (i = 0; i < MAX_PLAYERS; i++)
@@ -8983,7 +9580,13 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
     {
       local_player->score = action_arg_number_new;
 
+#if 1
+      game_panel_controls[GAME_PANEL_SCORE].value = local_player->score;
+
+      DisplayGameControlValues();
+#else
       DrawGameValue_Score(local_player->score);
+#endif
 
       break;
     }
@@ -8992,7 +9595,13 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
     {
       local_player->gems_still_needed = action_arg_number_new;
 
+#if 1
+      game_panel_controls[GAME_PANEL_GEMS].value = local_player->gems_still_needed;
+
+      DisplayGameControlValues();
+#else
       DrawGameValue_Emeralds(local_player->gems_still_needed);
+#endif
 
       break;
     }
@@ -10267,7 +10876,13 @@ static void CheckLevelTime()
        if (TimeLeft <= 10 && setup.time_limit)
          PlaySound(SND_GAME_RUNNING_OUT_OF_TIME);
 
+#if 1
+       game_panel_controls[GAME_PANEL_TIME].value = TimeLeft;
+
+       DisplayGameControlValues();
+#else
        DrawGameValue_Time(TimeLeft);
+#endif
 
        if (!TimeLeft && setup.time_limit)
        {
@@ -10278,8 +10893,17 @@ static void CheckLevelTime()
              KillPlayer(&stored_player[i]);
        }
       }
+#if 1
+      else if (level.time == 0 && !AllPlayersGone) /* level w/o time limit */
+      {
+       game_panel_controls[GAME_PANEL_TIME].value = 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 +10912,9 @@ static void CheckLevelTime()
     if (tape.recording || tape.playing)
       DrawVideoDisplay(VIDEO_STATE_TIME_ON, TapeTime);
   }
+
+  UpdateGameDoorValues();
+  DrawGameDoorValues();
 }
 
 void AdvanceFrameAndPlayerCounters(int player_nr)
@@ -11154,6 +11781,7 @@ void GameActions_RND()
     if (game.magic_wall_time_left > 0)
     {
       game.magic_wall_time_left--;
+
       if (!game.magic_wall_time_left)
       {
        SCAN_PLAYFIELD(x, y)
@@ -11703,7 +12331,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 +12631,29 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
        if (TimeLeft <= 10 && setup.time_limit)
          PlaySound(SND_GAME_RUNNING_OUT_OF_TIME);
 
+#if 1
+       game_panel_controls[GAME_PANEL_TIME].value = 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_panel_controls[GAME_PANEL_TIME].value = 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 +13702,14 @@ int DigField(struct PlayerInfo *player,
     else if (element == EL_EXTRA_TIME && level.time > 0)
     {
       TimeLeft += level.extra_time;
+
+#if 1
+      game_panel_controls[GAME_PANEL_TIME].value = TimeLeft;
+
+      DisplayGameControlValues();
+#else
       DrawGameValue_Time(TimeLeft);
+#endif
     }
     else if (element == EL_SHIELD_NORMAL || element == EL_SHIELD_DEADLY)
     {
@@ -13138,7 +13788,13 @@ int DigField(struct PlayerInfo *player,
       if (local_player->gems_still_needed < 0)
        local_player->gems_still_needed = 0;
 
+#if 1
+      game_panel_controls[GAME_PANEL_GEMS].value = local_player->gems_still_needed;
+
+      DisplayGameControlValues();
+#else
       DrawGameValue_Emeralds(local_player->gems_still_needed);
+#endif
     }
 
     RaiseScoreElement(element);
@@ -13318,6 +13974,8 @@ int DigField(struct PlayerInfo *player,
       ZX = x;
       ZY = y;
 
+      game.robot_wheel_active = TRUE;
+
       DrawLevelField(x, y);
     }
     else if (element == EL_SP_TERMINAL)
@@ -13382,7 +14040,14 @@ int DigField(struct PlayerInfo *player,
       if (level.time > 0 || level.use_time_orb_bug)
       {
        TimeLeft += level.time_orb_time;
+
+#if 1
+       game_panel_controls[GAME_PANEL_TIME].value = TimeLeft;
+
+       DisplayGameControlValues();
+#else
        DrawGameValue_Time(TimeLeft);
+#endif
       }
 
       ResetGfxAnimation(x, y);
@@ -13554,6 +14219,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_dropped_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 +14229,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 +14673,13 @@ void RaiseScore(int value)
 {
   local_player->score += value;
 
+#if 1
+  game_panel_controls[GAME_PANEL_SCORE].value = local_player->score;
+
+  DisplayGameControlValues();
+#else
   DrawGameValue_Score(local_player->score);
+#endif
 }
 
 void RaiseScoreElement(int element)
@@ -14099,13 +14774,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;