rnd-20070901-1-src
[rocksndiamonds.git] / src / game.c
index 4b4a44cfee1868d6113e12a2b17c9f947db8499d..7d83c63f8800dca7c19354af58e6c83de955348f 100644 (file)
 #if 1
 /* game panel display and control definitions */
 
-#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_SWITCH     36
-#define GAME_CONTROL_EMC_MAGIC_BALL_TIME       37
-#define GAME_CONTROL_LIGHT_SWITCH              38
-#define GAME_CONTROL_LIGHT_SWITCH_TIME         39
-#define GAME_CONTROL_TIMEGATE_SWITCH           40
-#define GAME_CONTROL_TIMEGATE_SWITCH_TIME      41
-#define GAME_CONTROL_SWITCHGATE_SWITCH         42
-#define GAME_CONTROL_EMC_LENSES                        43
-#define GAME_CONTROL_EMC_LENSES_TIME           44
-#define GAME_CONTROL_EMC_MAGNIFIER             45
-#define GAME_CONTROL_EMC_MAGNIFIER_TIME                46
-#define GAME_CONTROL_BALLOON_SWITCH            47
-#define GAME_CONTROL_DYNABOMB_NUMBER           48
-#define GAME_CONTROL_DYNABOMB_SIZE             49
-#define GAME_CONTROL_DYNABOMB_POWER            50
-#define GAME_CONTROL_PENGUINS                  51
-#define GAME_CONTROL_SOKOBAN_OBJECTS           52
-#define GAME_CONTROL_SOKOBAN_FIELDS            53
-#define GAME_CONTROL_ROBOT_WHEEL               54
-#define GAME_CONTROL_CONVEYOR_BELT_1           55
-#define GAME_CONTROL_CONVEYOR_BELT_1_SWITCH    56
-#define GAME_CONTROL_CONVEYOR_BELT_2           57
-#define GAME_CONTROL_CONVEYOR_BELT_2_SWITCH    58
-#define GAME_CONTROL_CONVEYOR_BELT_3           59
-#define GAME_CONTROL_CONVEYOR_BELT_3_SWITCH    60
-#define GAME_CONTROL_CONVEYOR_BELT_4           61
-#define GAME_CONTROL_CONVEYOR_BELT_4_SWITCH    62
-#define GAME_CONTROL_MAGIC_WALL                        63
-#define GAME_CONTROL_MAGIC_WALL_TIME           64
-#define GAME_CONTROL_BD_MAGIC_WALL             65
-#define GAME_CONTROL_DC_MAGIC_WALL             66
-#define GAME_CONTROL_PLAYER_NAME               67
-#define GAME_CONTROL_LEVEL_NAME                        68
-#define GAME_CONTROL_LEVEL_AUTHOR              69
-
-#define NUM_GAME_CONTROLS                      70
-
-int game_control_value[NUM_GAME_CONTROLS];
-int last_game_control_value[NUM_GAME_CONTROLS];
-
-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_2             59
+#define GAME_PANEL_CONVEYOR_BELT_3             60
+#define GAME_PANEL_CONVEYOR_BELT_4             61
+#define GAME_PANEL_CONVEYOR_BELT_1_SWITCH      62
+#define GAME_PANEL_CONVEYOR_BELT_2_SWITCH      63
+#define GAME_PANEL_CONVEYOR_BELT_3_SWITCH      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_GRAPHIC_1                   69
+#define GAME_PANEL_GRAPHIC_2                   70
+#define GAME_PANEL_GRAPHIC_3                   71
+#define GAME_PANEL_GRAPHIC_4                   72
+#define GAME_PANEL_GRAPHIC_5                   73
+#define GAME_PANEL_GRAPHIC_6                   74
+#define GAME_PANEL_GRAPHIC_7                   75
+#define GAME_PANEL_GRAPHIC_8                   76
+#define GAME_PANEL_ELEMENT_1                   77
+#define GAME_PANEL_ELEMENT_2                   78
+#define GAME_PANEL_ELEMENT_3                   79
+#define GAME_PANEL_ELEMENT_4                   80
+#define GAME_PANEL_ELEMENT_5                   81
+#define GAME_PANEL_ELEMENT_6                   82
+#define GAME_PANEL_ELEMENT_7                   83
+#define GAME_PANEL_ELEMENT_8                   84
+#define GAME_PANEL_ELEMENT_COUNT_1             85
+#define GAME_PANEL_ELEMENT_COUNT_2             86
+#define GAME_PANEL_ELEMENT_COUNT_3             87
+#define GAME_PANEL_ELEMENT_COUNT_4             88
+#define GAME_PANEL_ELEMENT_COUNT_5             89
+#define GAME_PANEL_ELEMENT_COUNT_6             90
+#define GAME_PANEL_ELEMENT_COUNT_7             91
+#define GAME_PANEL_ELEMENT_COUNT_8             92
+#define GAME_PANEL_CE_SCORE_1                  93
+#define GAME_PANEL_CE_SCORE_2                  94
+#define GAME_PANEL_CE_SCORE_3                  95
+#define GAME_PANEL_CE_SCORE_4                  96
+#define GAME_PANEL_CE_SCORE_5                  97
+#define GAME_PANEL_CE_SCORE_6                  98
+#define GAME_PANEL_CE_SCORE_7                  99
+#define GAME_PANEL_CE_SCORE_8                  100
+#define GAME_PANEL_CE_SCORE_1_ELEMENT          101
+#define GAME_PANEL_CE_SCORE_2_ELEMENT          102
+#define GAME_PANEL_CE_SCORE_3_ELEMENT          103
+#define GAME_PANEL_CE_SCORE_4_ELEMENT          104
+#define GAME_PANEL_CE_SCORE_5_ELEMENT          105
+#define GAME_PANEL_CE_SCORE_6_ELEMENT          106
+#define GAME_PANEL_CE_SCORE_7_ELEMENT          107
+#define GAME_PANEL_CE_SCORE_8_ELEMENT          108
+#define GAME_PANEL_PLAYER_NAME                 109
+#define GAME_PANEL_LEVEL_NAME                  110
+#define GAME_PANEL_LEVEL_AUTHOR                        111
+
+#define NUM_GAME_PANEL_CONTROLS                        112
+
+struct GamePanelOrderInfo
+{
+  int nr;
+  int sort_priority;
+};
+
+static struct GamePanelOrderInfo game_panel_order[NUM_GAME_PANEL_CONTROLS];
+
+struct GamePanelControlInfo
 {
   int nr;
 
   struct TextPosInfo *pos;
   int type;
+
+  int value, last_value;
+  int frame, last_frame;
+  int gfx_frame;
+  int gfx_random;
 };
 
-static struct GameControlInfo game_controls[] =
+static struct GamePanelControlInfo game_panel_controls[] =
 {
   {
-    GAME_CONTROL_LEVEL_NUMBER,
+    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_KEY_1,
-    &game.panel.key[0],
+    GAME_PANEL_INVENTORY_FIRST_1,
+    &game.panel.inventory_first[0],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_KEY_2,
-    &game.panel.key[1],
+    GAME_PANEL_INVENTORY_FIRST_2,
+    &game.panel.inventory_first[1],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_KEY_3,
-    &game.panel.key[2],
+    GAME_PANEL_INVENTORY_FIRST_3,
+    &game.panel.inventory_first[2],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_KEY_4,
-    &game.panel.key[3],
+    GAME_PANEL_INVENTORY_FIRST_4,
+    &game.panel.inventory_first[3],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_KEY_5,
-    &game.panel.key[4],
+    GAME_PANEL_INVENTORY_FIRST_5,
+    &game.panel.inventory_first[4],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_KEY_6,
-    &game.panel.key[5],
+    GAME_PANEL_INVENTORY_FIRST_6,
+    &game.panel.inventory_first[5],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_KEY_7,
-    &game.panel.key[6],
+    GAME_PANEL_INVENTORY_FIRST_7,
+    &game.panel.inventory_first[6],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_KEY_8,
-    &game.panel.key[7],
+    GAME_PANEL_INVENTORY_FIRST_8,
+    &game.panel.inventory_first[7],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_KEY_WHITE,
-    &game.panel.key_white,
+    GAME_PANEL_INVENTORY_LAST_1,
+    &game.panel.inventory_last[0],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_KEY_WHITE_COUNT,
-    &game.panel.key_white_count,
-    TYPE_INTEGER,
+    GAME_PANEL_INVENTORY_LAST_2,
+    &game.panel.inventory_last[1],
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_SCORE,
-    &game.panel.score,
-    TYPE_INTEGER,
+    GAME_PANEL_INVENTORY_LAST_3,
+    &game.panel.inventory_last[2],
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_TIME,
-    &game.panel.time,
-    TYPE_INTEGER,
+    GAME_PANEL_INVENTORY_LAST_4,
+    &game.panel.inventory_last[3],
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_TIME_HH,
-    &game.panel.time_hh,
-    TYPE_INTEGER,
+    GAME_PANEL_INVENTORY_LAST_5,
+    &game.panel.inventory_last[4],
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_TIME_MM,
-    &game.panel.time_mm,
-    TYPE_INTEGER,
+    GAME_PANEL_INVENTORY_LAST_6,
+    &game.panel.inventory_last[5],
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_TIME_SS,
-    &game.panel.time_ss,
-    TYPE_INTEGER,
+    GAME_PANEL_INVENTORY_LAST_7,
+    &game.panel.inventory_last[6],
+    TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DROP_NEXT_1,
-    &game.panel.drop_next_1,
+    GAME_PANEL_INVENTORY_LAST_8,
+    &game.panel.inventory_last[7],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DROP_NEXT_2,
-    &game.panel.drop_next_2,
+    GAME_PANEL_KEY_1,
+    &game.panel.key[0],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DROP_NEXT_3,
-    &game.panel.drop_next_3,
+    GAME_PANEL_KEY_2,
+    &game.panel.key[1],
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_KEY_3,
+    &game.panel.key[2],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DROP_NEXT_4,
-    &game.panel.drop_next_4,
+    GAME_PANEL_KEY_4,
+    &game.panel.key[3],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DROP_NEXT_5,
-    &game.panel.drop_next_5,
+    GAME_PANEL_KEY_5,
+    &game.panel.key[4],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DROP_NEXT_6,
-    &game.panel.drop_next_6,
+    GAME_PANEL_KEY_6,
+    &game.panel.key[5],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DROP_NEXT_7,
-    &game.panel.drop_next_7,
+    GAME_PANEL_KEY_7,
+    &game.panel.key[6],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DROP_NEXT_8,
-    &game.panel.drop_next_8,
+    GAME_PANEL_KEY_8,
+    &game.panel.key[7],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_SHIELD_NORMAL,
-    &game.panel.shield_normal,
+    GAME_PANEL_KEY_WHITE,
+    &game.panel.key_white,
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_SHIELD_NORMAL_TIME,
-    &game.panel.shield_normal_time,
+    GAME_PANEL_KEY_WHITE_COUNT,
+    &game.panel.key_white_count,
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_SHIELD_DEADLY,
-    &game.panel.shield_deadly,
-    TYPE_ELEMENT,
+    GAME_PANEL_SCORE,
+    &game.panel.score,
+    TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_SHIELD_DEADLY_TIME,
-    &game.panel.shield_deadly_time,
+    GAME_PANEL_TIME,
+    &game.panel.time,
     TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_EXIT,
-    &game.panel.exit,
-    TYPE_ELEMENT,
+    GAME_PANEL_TIME_HH,
+    &game.panel.time_hh,
+    TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_EM_EXIT,
-    &game.panel.em_exit,
-    TYPE_ELEMENT,
+    GAME_PANEL_TIME_MM,
+    &game.panel.time_mm,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_PANEL_TIME_SS,
+    &game.panel.time_ss,
+    TYPE_INTEGER,
   },
   {
-    GAME_CONTROL_SP_EXIT,
-    &game.panel.sp_exit,
+    GAME_PANEL_SHIELD_NORMAL,
+    &game.panel.shield_normal,
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_STEEL_EXIT,
-    &game.panel.steel_exit,
+    GAME_PANEL_SHIELD_NORMAL_TIME,
+    &game.panel.shield_normal_time,
+    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_PANEL_EXIT,
+    &game.panel.exit,
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_EMC_MAGIC_BALL,
+    GAME_PANEL_EMC_MAGIC_BALL,
     &game.panel.emc_magic_ball,
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_EMC_MAGIC_BALL_SWITCH,
+    GAME_PANEL_EMC_MAGIC_BALL_SWITCH,
     &game.panel.emc_magic_ball_switch,
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_EMC_MAGIC_BALL_TIME,
-    &game.panel.emc_magic_ball_time,
-    TYPE_INTEGER,
-  },
-  {
-    GAME_CONTROL_LIGHT_SWITCH,
+    GAME_PANEL_LIGHT_SWITCH,
     &game.panel.light_switch,
     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_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_ELEMENT,
   },
   {
-    GAME_CONTROL_EMC_LENSES,
+    GAME_PANEL_EMC_LENSES,
     &game.panel.emc_lenses,
     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_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_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_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_ELEMENT,
   },
   {
-    GAME_CONTROL_CONVEYOR_BELT_1,
-    &game.panel.conveyor_belt_1,
+    GAME_PANEL_CONVEYOR_BELT_1,
+    &game.panel.conveyor_belt[0],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_CONVEYOR_BELT_1_SWITCH,
-    &game.panel.conveyor_belt_1_switch,
+    GAME_PANEL_CONVEYOR_BELT_2,
+    &game.panel.conveyor_belt[1],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_CONVEYOR_BELT_2,
-    &game.panel.conveyor_belt_2,
+    GAME_PANEL_CONVEYOR_BELT_3,
+    &game.panel.conveyor_belt[2],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_CONVEYOR_BELT_2_SWITCH,
-    &game.panel.conveyor_belt_2_switch,
+    GAME_PANEL_CONVEYOR_BELT_4,
+    &game.panel.conveyor_belt[3],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_CONVEYOR_BELT_3,
-    &game.panel.conveyor_belt_3,
+    GAME_PANEL_CONVEYOR_BELT_1_SWITCH,
+    &game.panel.conveyor_belt_switch[0],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_CONVEYOR_BELT_3_SWITCH,
-    &game.panel.conveyor_belt_3_switch,
+    GAME_PANEL_CONVEYOR_BELT_2_SWITCH,
+    &game.panel.conveyor_belt_switch[1],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_CONVEYOR_BELT_4,
-    &game.panel.conveyor_belt_4,
+    GAME_PANEL_CONVEYOR_BELT_3_SWITCH,
+    &game.panel.conveyor_belt_switch[2],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_CONVEYOR_BELT_4_SWITCH,
-    &game.panel.conveyor_belt_4_switch,
+    GAME_PANEL_CONVEYOR_BELT_4_SWITCH,
+    &game.panel.conveyor_belt_switch[3],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_MAGIC_WALL,
+    GAME_PANEL_MAGIC_WALL,
     &game.panel.magic_wall,
     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,
+    GAME_PANEL_GRAVITY_STATE,
+    &game.panel.gravity_state,
+    TYPE_STRING,
+  },
+  {
+    GAME_PANEL_GRAPHIC_1,
+    &game.panel.graphic[0],
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_GRAPHIC_2,
+    &game.panel.graphic[1],
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_GRAPHIC_3,
+    &game.panel.graphic[2],
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_GRAPHIC_4,
+    &game.panel.graphic[3],
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_GRAPHIC_5,
+    &game.panel.graphic[4],
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_GRAPHIC_6,
+    &game.panel.graphic[5],
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_GRAPHIC_7,
+    &game.panel.graphic[6],
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_GRAPHIC_8,
+    &game.panel.graphic[7],
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_ELEMENT_1,
+    &game.panel.element[0],
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_ELEMENT_2,
+    &game.panel.element[1],
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_ELEMENT_3,
+    &game.panel.element[2],
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_ELEMENT_4,
+    &game.panel.element[3],
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_ELEMENT_5,
+    &game.panel.element[4],
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_ELEMENT_6,
+    &game.panel.element[5],
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_ELEMENT_7,
+    &game.panel.element[6],
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_ELEMENT_8,
+    &game.panel.element[7],
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_ELEMENT_COUNT_1,
+    &game.panel.element_count[0],
+    TYPE_INTEGER,
+  },
+  {
+    GAME_PANEL_ELEMENT_COUNT_2,
+    &game.panel.element_count[1],
+    TYPE_INTEGER,
+  },
+  {
+    GAME_PANEL_ELEMENT_COUNT_3,
+    &game.panel.element_count[2],
+    TYPE_INTEGER,
+  },
+  {
+    GAME_PANEL_ELEMENT_COUNT_4,
+    &game.panel.element_count[3],
+    TYPE_INTEGER,
+  },
+  {
+    GAME_PANEL_ELEMENT_COUNT_5,
+    &game.panel.element_count[4],
+    TYPE_INTEGER,
+  },
+  {
+    GAME_PANEL_ELEMENT_COUNT_6,
+    &game.panel.element_count[5],
+    TYPE_INTEGER,
+  },
+  {
+    GAME_PANEL_ELEMENT_COUNT_7,
+    &game.panel.element_count[6],
+    TYPE_INTEGER,
+  },
+  {
+    GAME_PANEL_ELEMENT_COUNT_8,
+    &game.panel.element_count[7],
+    TYPE_INTEGER,
+  },
+  {
+    GAME_PANEL_CE_SCORE_1,
+    &game.panel.ce_score[0],
+    TYPE_INTEGER,
+  },
+  {
+    GAME_PANEL_CE_SCORE_2,
+    &game.panel.ce_score[1],
+    TYPE_INTEGER,
+  },
+  {
+    GAME_PANEL_CE_SCORE_3,
+    &game.panel.ce_score[2],
+    TYPE_INTEGER,
+  },
+  {
+    GAME_PANEL_CE_SCORE_4,
+    &game.panel.ce_score[3],
+    TYPE_INTEGER,
+  },
+  {
+    GAME_PANEL_CE_SCORE_5,
+    &game.panel.ce_score[4],
+    TYPE_INTEGER,
+  },
+  {
+    GAME_PANEL_CE_SCORE_6,
+    &game.panel.ce_score[5],
+    TYPE_INTEGER,
+  },
+  {
+    GAME_PANEL_CE_SCORE_7,
+    &game.panel.ce_score[6],
+    TYPE_INTEGER,
+  },
+  {
+    GAME_PANEL_CE_SCORE_8,
+    &game.panel.ce_score[7],
+    TYPE_INTEGER,
+  },
+  {
+    GAME_PANEL_CE_SCORE_1_ELEMENT,
+    &game.panel.ce_score_element[0],
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_CE_SCORE_2_ELEMENT,
+    &game.panel.ce_score_element[1],
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_CE_SCORE_3_ELEMENT,
+    &game.panel.ce_score_element[2],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_DC_MAGIC_WALL,
-    &game.panel.dc_magic_wall,
+    GAME_PANEL_CE_SCORE_4_ELEMENT,
+    &game.panel.ce_score_element[3],
     TYPE_ELEMENT,
   },
   {
-    GAME_CONTROL_PLAYER_NAME,
+    GAME_PANEL_CE_SCORE_5_ELEMENT,
+    &game.panel.ce_score_element[4],
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_CE_SCORE_6_ELEMENT,
+    &game.panel.ce_score_element[5],
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_CE_SCORE_7_ELEMENT,
+    &game.panel.ce_score_element[6],
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_CE_SCORE_8_ELEMENT,
+    &game.panel.ce_score_element[7],
+    TYPE_ELEMENT,
+  },
+  {
+    GAME_PANEL_PLAYER_NAME,
     &game.panel.player_name,
     TYPE_STRING,
   },
   {
-    GAME_CONTROL_LEVEL_NAME,
+    GAME_PANEL_LEVEL_NAME,
     &game.panel.level_name,
     TYPE_STRING,
   },
   {
-    GAME_CONTROL_LEVEL_AUTHOR,
+    GAME_PANEL_LEVEL_AUTHOR,
     &game.panel.level_author,
     TYPE_STRING,
   },
@@ -634,6 +896,9 @@ static struct GameControlInfo game_controls[] =
         (be) + (e) - EL_SELF > EL_CUSTOM_END   ? EL_CUSTOM_END :       \
         (be) + (e) - EL_SELF)
 
+#define GET_PLAYER_FROM_BITS(p)                                                \
+       (EL_PLAYER_1 + ((p) != PLAYER_BITS_ANY ? log_2(p) : 0))
+
 #define GET_TARGET_ELEMENT(be, e, ch, cv, cs)                          \
        ((e) == EL_TRIGGER_PLAYER   ? (ch)->actual_trigger_player    :  \
         (e) == EL_TRIGGER_ELEMENT  ? (ch)->actual_trigger_element   :  \
@@ -752,6 +1017,8 @@ static struct GameControlInfo game_controls[] =
 
 static void CreateField(int, int, int);
 
+static void ResetGfxAnimation(int, int);
+
 static void SetPlayerWaiting(struct PlayerInfo *, boolean);
 static void AdvanceFrameAndPlayerCounters(int);
 
@@ -1728,55 +1995,203 @@ 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);
+  }
+}
+
+static int compareGamePanelOrderInfo(const void *object1, const void *object2)
+{
+  const struct GamePanelOrderInfo *gpo1 = (struct GamePanelOrderInfo *)object1;
+  const struct GamePanelOrderInfo *gpo2 = (struct GamePanelOrderInfo *)object2;
+  int compare_result;
+
+  if (gpo1->sort_priority != gpo2->sort_priority)
+    compare_result = gpo1->sort_priority - gpo2->sort_priority;
+  else
+    compare_result = gpo1->nr - gpo2->nr;
+
+  return compare_result;
+}
+
 void InitGameControlValues()
 {
   int i;
 
-  for (i = 0; i < NUM_GAME_CONTROLS; i++)
-    game_control_value[i] = last_game_control_value[i] = -1;
-
-  for (i = 0; game_controls[i].nr != -1; i++)
+  for (i = 0; game_panel_controls[i].nr != -1; i++)
   {
-    int nr = game_controls[i].nr;
-    int type = game_controls[i].type;
-    struct TextPosInfo *pos = game_controls[i].pos;
+    struct GamePanelControlInfo *gpc = &game_panel_controls[i];
+    struct GamePanelOrderInfo *gpo = &game_panel_order[i];
+    struct TextPosInfo *pos = gpc->pos;
+    int nr = gpc->nr;
+    int type = gpc->type;
 
-    game_control_value[nr] = last_game_control_value[nr] = -1;
+    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->chars * getFontWidth(pos->font);
+    {
+      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;
+    }
+
+    /* fill structure for game panel draw order */
+    gpo->nr = gpc->nr;
+    gpo->sort_priority = pos->sort_priority;
   }
+
+  /* sort game panel controls according to sort_priority and control number */
+  qsort(game_panel_order, NUM_GAME_PANEL_CONTROLS,
+       sizeof(struct GamePanelOrderInfo), compareGamePanelOrderInfo);
 }
 
-void UpdateGameControlValues()
+void UpdatePlayfieldElementCount()
 {
-  int i, j;
+  int i, j, x, y;
 
-  game_control_value[GAME_CONTROL_LEVEL_NUMBER] = level_nr;
-  game_control_value[GAME_CONTROL_GEMS] = local_player->gems_still_needed;
+  for (i = 0; i < MAX_NUM_ELEMENTS; i++)
+    element_info[i].element_count = 0;
 
-  game_control_value[GAME_CONTROL_INVENTORY] = 0;
+  SCAN_PLAYFIELD(x, y)
+  {
+    element_info[Feld[x][y]].element_count++;
+  }
+
+  for (i = 0; i < NUM_GROUP_ELEMENTS; i++)
+    for (j = 0; j < MAX_NUM_ELEMENTS; j++)
+      if (IS_IN_GROUP(j, i))
+       element_info[EL_GROUP_START + i].element_count +=
+         element_info[j].element_count;
+}
+
+void UpdateGameControlValues()
+{
+  int i, k;
+  int time = (local_player->LevelSolved ?
+             local_player->LevelSolved_CountingTime :
+             level.game_engine_type == GAME_ENGINE_TYPE_EM ?
+             level.native_em_level->lev->time :
+             level.time == 0 ? TimePlayed : TimeLeft);
+  int score = (local_player->LevelSolved ?
+              local_player->LevelSolved_CountingScore :
+              level.game_engine_type == GAME_ENGINE_TYPE_EM ?
+              level.native_em_level->lev->score :
+              local_player->score);
+  int gems = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
+             level.native_em_level->lev->required :
+             local_player->gems_still_needed);
+  int exit_closed = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
+                    level.native_em_level->lev->required > 0 :
+                    local_player->gems_still_needed > 0 ||
+                    local_player->sokobanfields_still_needed > 0 ||
+                    local_player->lights_still_needed > 0);
+
+  UpdatePlayfieldElementCount();
+
+  /* update game panel control values */
+
+  game_panel_controls[GAME_PANEL_LEVEL_NUMBER].value = level_nr;
+  game_panel_controls[GAME_PANEL_GEMS].value = gems;
+
+  game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value = 0;
   for (i = 0; i < MAX_NUM_KEYS; i++)
-    game_control_value[GAME_CONTROL_KEY_1 + i] = 0;
-  game_control_value[GAME_CONTROL_KEY_WHITE] = 0;
-  game_control_value[GAME_CONTROL_KEY_WHITE_COUNT] = 0;
+    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 (j = 0; j < MAX_NUM_KEYS; j++)
-       if (stored_player[i].key[j])
-         game_control_value[GAME_CONTROL_KEY_1 + j] = 1;
+      for (k = 0; k < MAX_NUM_KEYS; k++)
+      {
+       if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+       {
+         if (level.native_em_level->ply[i]->keys & (1 << k))
+           game_panel_controls[GAME_PANEL_KEY_1 + k].value =
+             get_key_element_from_nr(k);
+       }
+       else if (stored_player[i].key[k])
+         game_panel_controls[GAME_PANEL_KEY_1 + k].value =
+           get_key_element_from_nr(k);
+      }
 
-      game_control_value[GAME_CONTROL_INVENTORY] +=
-       stored_player[i].inventory_size;
+      if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+       game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
+         level.native_em_level->ply[i]->dynamite;
+      else
+       game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
+         stored_player[i].inventory_size;
 
       if (stored_player[i].num_white_keys > 0)
-       game_control_value[GAME_CONTROL_KEY_WHITE] = 1;
+       game_panel_controls[GAME_PANEL_KEY_WHITE].value =
+         EL_DC_KEY_WHITE;
 
-      game_control_value[GAME_CONTROL_KEY_WHITE_COUNT] +=
+      game_panel_controls[GAME_PANEL_KEY_WHITE_COUNT].value +=
        stored_player[i].num_white_keys;
     }
   }
@@ -1784,156 +2199,309 @@ void UpdateGameControlValues()
   {
     int player_nr = game.centered_player_nr;
 
-    for (i = 0; i < MAX_NUM_KEYS; i++)
-      if (stored_player[player_nr].key[i])
-       game_control_value[GAME_CONTROL_KEY_1 + i] = 1;
+    for (k = 0; k < MAX_NUM_KEYS; k++)
+    {
+      if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+      {
+       if (level.native_em_level->ply[player_nr]->keys & (1 << k))
+         game_panel_controls[GAME_PANEL_KEY_1 + k].value =
+           get_key_element_from_nr(k);
+      }
+      else if (stored_player[player_nr].key[k])
+       game_panel_controls[GAME_PANEL_KEY_1 + k].value =
+         get_key_element_from_nr(k);
+    }
 
-    game_control_value[GAME_CONTROL_INVENTORY] +=
-      stored_player[player_nr].inventory_size;
+    if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+      game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
+       level.native_em_level->ply[player_nr]->dynamite;
+    else
+      game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value +=
+       stored_player[player_nr].inventory_size;
 
     if (stored_player[player_nr].num_white_keys > 0)
-      game_control_value[GAME_CONTROL_KEY_WHITE] = 1;
+      game_panel_controls[GAME_PANEL_KEY_WHITE].value = EL_DC_KEY_WHITE;
 
-    game_control_value[GAME_CONTROL_KEY_WHITE_COUNT] +=
+    game_panel_controls[GAME_PANEL_KEY_WHITE_COUNT].value +=
       stored_player[player_nr].num_white_keys;
   }
 
-  game_control_value[GAME_CONTROL_SCORE] = (local_player->LevelSolved ?
-                                           local_player->score_final :
-                                           local_player->score);
+  for (i = 0; i < NUM_PANEL_INVENTORY; 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_control_value[GAME_CONTROL_TIME] = (level.time == 0 ?
-                                          TimePlayed :
-                                          TimeLeft);
+  game_panel_controls[GAME_PANEL_SCORE].value = score;
 
-  game_control_value[GAME_CONTROL_TIME_HH] = TapeTime / 3600;
-  game_control_value[GAME_CONTROL_TIME_MM] = (TapeTime / 60) % 60;
-  game_control_value[GAME_CONTROL_TIME_SS] = TapeTime % 60;
+  game_panel_controls[GAME_PANEL_TIME].value = time;
 
-  for (i = 0; i < 8; i++)
-    game_control_value[GAME_CONTROL_DROP_NEXT_1 + i] = 0;
+  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_control_value[GAME_CONTROL_SHIELD_NORMAL] =
-    (local_player->shield_normal_time_left > 0 ? 1 : 0);
-  game_control_value[GAME_CONTROL_SHIELD_NORMAL_TIME] =
+  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_control_value[GAME_CONTROL_SHIELD_DEADLY] =
-    (local_player->shield_deadly_time_left > 0 ? 1 : 0);
-  game_control_value[GAME_CONTROL_SHIELD_DEADLY_TIME] =
+  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_control_value[GAME_CONTROL_EXIT] = 0;
-  game_control_value[GAME_CONTROL_EM_EXIT] = 0;
-  game_control_value[GAME_CONTROL_SP_EXIT] = 0;
-  game_control_value[GAME_CONTROL_STEEL_EXIT] = 0;
-  game_control_value[GAME_CONTROL_EM_STEEL_EXIT] = 0;
+  game_panel_controls[GAME_PANEL_EXIT].value =
+    (exit_closed ? EL_EXIT_CLOSED : EL_EXIT_OPEN);
 
-  game_control_value[GAME_CONTROL_EMC_MAGIC_BALL] = 0;
-  game_control_value[GAME_CONTROL_EMC_MAGIC_BALL_SWITCH] = 0;
-  game_control_value[GAME_CONTROL_EMC_MAGIC_BALL_TIME] = 0;
+  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_control_value[GAME_CONTROL_LIGHT_SWITCH] = 0;
-  game_control_value[GAME_CONTROL_LIGHT_SWITCH_TIME] = game.light_time_left;
+  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_control_value[GAME_CONTROL_TIMEGATE_SWITCH] = 0;
-  game_control_value[GAME_CONTROL_TIMEGATE_SWITCH_TIME] =
+  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_control_value[GAME_CONTROL_SWITCHGATE_SWITCH] = 0;
+  game_panel_controls[GAME_PANEL_SWITCHGATE_SWITCH].value =
+    EL_SWITCHGATE_SWITCH_UP + game.switchgate_pos;
 
-  game_control_value[GAME_CONTROL_EMC_LENSES] = 0;
-  game_control_value[GAME_CONTROL_EMC_LENSES_TIME] = game.lenses_time_left;
+  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_control_value[GAME_CONTROL_EMC_MAGNIFIER] = 0;
-  game_control_value[GAME_CONTROL_EMC_MAGNIFIER_TIME] = game.magnify_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_control_value[GAME_CONTROL_BALLOON_SWITCH] = 0;
+  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_control_value[GAME_CONTROL_DYNABOMB_NUMBER] =
+  game_panel_controls[GAME_PANEL_DYNABOMB_NUMBER].value =
     local_player->dynabomb_count;
-  game_control_value[GAME_CONTROL_DYNABOMB_SIZE] =
+  game_panel_controls[GAME_PANEL_DYNABOMB_SIZE].value =
     local_player->dynabomb_size;
-  game_control_value[GAME_CONTROL_DYNABOMB_POWER] =
-    local_player->dynabomb_xl;
+  game_panel_controls[GAME_PANEL_DYNABOMB_POWER].value =
+    (local_player->dynabomb_xl ? EL_DYNABOMB_INCREASE_POWER : EL_EMPTY);
 
-  game_control_value[GAME_CONTROL_PENGUINS] =
+  game_panel_controls[GAME_PANEL_PENGUINS].value =
     local_player->friends_still_needed;
 
-  game_control_value[GAME_CONTROL_SOKOBAN_OBJECTS] =
+  game_panel_controls[GAME_PANEL_SOKOBAN_OBJECTS].value =
     local_player->sokobanfields_still_needed;
-  game_control_value[GAME_CONTROL_SOKOBAN_FIELDS] =
+  game_panel_controls[GAME_PANEL_SOKOBAN_FIELDS].value =
     local_player->sokobanfields_still_needed;
 
-  game_control_value[GAME_CONTROL_ROBOT_WHEEL] = 0;
+  game_panel_controls[GAME_PANEL_ROBOT_WHEEL].value =
+    (game.robot_wheel_active ? EL_ROBOT_WHEEL_ACTIVE : EL_ROBOT_WHEEL);
 
-  game_control_value[GAME_CONTROL_CONVEYOR_BELT_1] = 0;
-  game_control_value[GAME_CONTROL_CONVEYOR_BELT_1_SWITCH] = 0;
-  game_control_value[GAME_CONTROL_CONVEYOR_BELT_2] = 0;
-  game_control_value[GAME_CONTROL_CONVEYOR_BELT_2_SWITCH] = 0;
-  game_control_value[GAME_CONTROL_CONVEYOR_BELT_3] = 0;
-  game_control_value[GAME_CONTROL_CONVEYOR_BELT_3_SWITCH] = 0;
-  game_control_value[GAME_CONTROL_CONVEYOR_BELT_4] = 0;
-  game_control_value[GAME_CONTROL_CONVEYOR_BELT_4_SWITCH] = 0;
+  for (i = 0; i < NUM_BELTS; i++)
+  {
+    game_panel_controls[GAME_PANEL_CONVEYOR_BELT_1 + i].value =
+      (game.belt_dir[i] != MV_NONE ? EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE :
+       EL_CONVEYOR_BELT_1_MIDDLE) + i;
+    game_panel_controls[GAME_PANEL_CONVEYOR_BELT_1_SWITCH + i].value =
+      getBeltSwitchElementFromBeltNrAndBeltDir(i, game.belt_dir[i]);
+  }
 
-  game_control_value[GAME_CONTROL_MAGIC_WALL] = 0;
-  game_control_value[GAME_CONTROL_MAGIC_WALL_TIME] =
+  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;
-  game_control_value[GAME_CONTROL_BD_MAGIC_WALL] = 0;
-  game_control_value[GAME_CONTROL_DC_MAGIC_WALL] = 0;
 
-  game_control_value[GAME_CONTROL_PLAYER_NAME] = 0;
-  game_control_value[GAME_CONTROL_LEVEL_NAME] = 0;
-  game_control_value[GAME_CONTROL_LEVEL_AUTHOR] = 0;
+#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
+
+  for (i = 0; i < NUM_PANEL_GRAPHICS; i++)
+    game_panel_controls[GAME_PANEL_GRAPHIC_1 + i].value = EL_GRAPHIC_1 + i;
+
+  for (i = 0; i < NUM_PANEL_ELEMENTS; i++)
+    game_panel_controls[GAME_PANEL_ELEMENT_1 + i].value =
+      (IS_DRAWABLE_ELEMENT(game.panel.element[i].id) ?
+       game.panel.element[i].id : EL_UNDEFINED);
+
+  for (i = 0; i < NUM_PANEL_ELEMENTS; i++)
+    game_panel_controls[GAME_PANEL_ELEMENT_COUNT_1 + i].value =
+      (IS_VALID_ELEMENT(game.panel.element_count[i].id) ?
+       element_info[game.panel.element_count[i].id].element_count :
+       EL_UNDEFINED);
+
+  for (i = 0; i < NUM_PANEL_CE_SCORE; i++)
+    game_panel_controls[GAME_PANEL_CE_SCORE_1 + i].value =
+      (IS_CUSTOM_ELEMENT(game.panel.ce_score[i].id) ?
+       element_info[game.panel.ce_score[i].id].collect_score : 0);
+
+  for (i = 0; i < NUM_PANEL_CE_SCORE; i++)
+    game_panel_controls[GAME_PANEL_CE_SCORE_1_ELEMENT + i].value =
+      (IS_CUSTOM_ELEMENT(game.panel.ce_score_element[i].id) ?
+       element_info[game.panel.ce_score_element[i].id].collect_score :
+       EL_UNDEFINED);
+
+  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;
+
+  /* update game panel control frames */
+
+  for (i = 0; game_panel_controls[i].nr != -1; i++)
+  {
+    struct GamePanelControlInfo *gpc = &game_panel_controls[i];
+
+    if (gpc->type == TYPE_ELEMENT)
+    {
+      int last_anim_random_frame = gfx.anim_random_frame;
+      int element = gpc->value;
+      int graphic = el2panelimg(element);
+
+      if (gpc->value != gpc->last_value)
+      {
+       gpc->gfx_frame = 0;
+       gpc->gfx_random = INIT_GFX_RANDOM();
+      }
+      else
+      {
+       gpc->gfx_frame++;
+
+       if (ANIM_MODE(graphic) == ANIM_RANDOM &&
+           IS_NEXT_FRAME(gpc->gfx_frame, graphic))
+         gpc->gfx_random = INIT_GFX_RANDOM();
+      }
+
+      if (ANIM_MODE(graphic) == ANIM_RANDOM)
+       gfx.anim_random_frame = gpc->gfx_random;
+
+      if (ANIM_MODE(graphic) == ANIM_CE_SCORE)
+       gpc->gfx_frame = element_info[element].collect_score;
+
+      gpc->frame = getGraphicAnimationFrame(el2panelimg(gpc->value),
+                                           gpc->gfx_frame);
+
+      if (ANIM_MODE(graphic) == ANIM_RANDOM)
+       gfx.anim_random_frame = last_anim_random_frame;
+    }
+  }
 }
 
 void DisplayGameControlValues()
 {
+  boolean redraw_panel = FALSE;
   int i;
 
-  for (i = 0; game_controls[i].nr != -1; i++)
+  for (i = 0; game_panel_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 chars = pos->chars;
-    int font = pos->font;
+    struct GamePanelControlInfo *gpc = &game_panel_controls[i];
 
-    if (value == last_value)
+    if (PANEL_DEACTIVATED(gpc->pos))
       continue;
 
-    last_game_control_value[nr] = value;
+    if (gpc->value == gpc->last_value &&
+       gpc->frame == gpc->last_frame)
+      continue;
+
+    redraw_panel = TRUE;
+  }
+
+  if (!redraw_panel)
+    return;
+
+  /* copy default game door content to main double buffer */
+  BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
+            DOOR_GFX_PAGEX5, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, DX, DY);
+
+  /* redraw game control buttons */
+#if 1
+  RedrawGameButtons();
+#else
+  UnmapGameButtons();
+  MapGameButtons();
+#endif
 
+  game_status = GAME_MODE_PSEUDO_PANEL;
+
+#if 1
+  for (i = 0; i < NUM_GAME_PANEL_CONTROLS; i++)
+#else
+  for (i = 0; game_panel_controls[i].nr != -1; i++)
+#endif
+  {
+#if 1
+    int nr = game_panel_order[i].nr;
+    struct GamePanelControlInfo *gpc = &game_panel_controls[nr];
+#else
+    struct GamePanelControlInfo *gpc = &game_panel_controls[i];
+    int nr = gpc->nr;
+#endif
+    struct TextPosInfo *pos = gpc->pos;
+    int type = gpc->type;
+    int value = gpc->value;
+    int frame = gpc->frame;
 #if 0
-    printf("::: value %d changed from %d to %d\n", nr, last_value, value);
+    int last_value = gpc->last_value;
+    int last_frame = gpc->last_frame;
 #endif
+    int size = pos->size;
+    int font = pos->font;
+    boolean draw_masked = pos->draw_masked;
+    int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_OPAQUE);
 
     if (PANEL_DEACTIVATED(pos))
       continue;
 
+#if 0
+    if (value == last_value && frame == last_frame)
+      continue;
+#endif
+
+    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 (type == TYPE_INTEGER)
     {
-      if (nr == GAME_CONTROL_LEVEL_NUMBER || nr == GAME_CONTROL_TIME)
+      if (nr == GAME_PANEL_LEVEL_NUMBER ||
+         nr == GAME_PANEL_TIME)
       {
-       boolean use_dynamic_chars = (pos->chars == -1 ? TRUE : FALSE);
+       boolean use_dynamic_size = (size == -1 ? TRUE : FALSE);
 
-       if (use_dynamic_chars)          /* use dynamic number of chars */
+       if (use_dynamic_size)           /* use dynamic number of digits */
        {
-         int value_change = (nr == GAME_CONTROL_LEVEL_NUMBER ? 100 : 1000);
-         int chars1 = (nr == GAME_CONTROL_LEVEL_NUMBER ? 2 : 3);
-         int chars2 = chars1 + 1;
+         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;
 
-         chars = (value < value_change ? chars1 : chars2);
-         font  = (value < value_change ? font1  : font2);
+         size = (value < value_change ? size1 : size2);
+         font = (value < value_change ? font1 : font2);
 
-         /* clear background if value just changed its size (dynamic chars) */
+#if 0
+         /* clear background if value just changed its size (dynamic digits) */
          if ((last_value < value_change) != (value < value_change))
          {
-           int width1 = chars1 * getFontWidth(font1);
-           int width2 = chars2 * getFontWidth(font2);
+           int width1 = size1 * getFontWidth(font1);
+           int width2 = size2 * getFontWidth(font2);
            int max_width = MAX(width1, width2);
            int max_height = MAX(getFontHeight(font1), getFontHeight(font2));
 
@@ -1942,50 +2510,148 @@ void DisplayGameControlValues()
            ClearRectangleOnBackground(drawto, PANEL_XPOS(pos), PANEL_YPOS(pos),
                                       max_width, max_height);
          }
+#endif
        }
-
-       pos->width = chars * getFontWidth(font);
       }
 
-      DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, chars), font);
+#if 1
+      /* correct text size if "digits" is zero or less */
+      if (size <= 0)
+       size = strlen(int2str(value, size));
+
+      /* dynamically correct text alignment */
+      pos->width = size * getFontWidth(font);
+#endif
+
+      DrawTextExt(drawto, PANEL_XPOS(pos), PANEL_YPOS(pos),
+                 int2str(value, size), font, mask_mode);
     }
     else if (type == TYPE_ELEMENT)
     {
-      if (nr >= GAME_CONTROL_KEY_1 && nr <= GAME_CONTROL_KEY_8)
+      int element, graphic;
+      Bitmap *src_bitmap;
+      int src_x, src_y;
+      int width, height;
+      int dst_x = PANEL_XPOS(pos);
+      int dst_y = PANEL_YPOS(pos);
+
+#if 1
+      if (value != EL_UNDEFINED && value != EL_EMPTY)
       {
-       int key_nr = nr - GAME_CONTROL_KEY_1;
-       int src_x = DOOR_GFX_PAGEX5 + 18 + (key_nr % STD_NUM_KEYS) * MINI_TILEX;
-       int src_y = DOOR_GFX_PAGEY1 + 123;
-       int dst_x = PANEL_XPOS(pos);
-       int dst_y = PANEL_YPOS(pos);
-       int 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) + key_nr;
-       int graphic = el2edimg(element);
+       element = value;
+       graphic = el2panelimg(value);
+
+       // printf("::: %d, '%s' [%d]\n", element, EL_NAME(element), size);
+
+#if 1
+       if (element >= EL_GRAPHIC_1 && element <= EL_GRAPHIC_8 && size == 0)
+         size = TILESIZE;
+#endif
+
+       getSizedGraphicSource(graphic, frame, size, &src_bitmap,
+                             &src_x, &src_y);
+
+       width  = graphic_info[graphic].width  * size / TILESIZE;
+       height = graphic_info[graphic].height * size / TILESIZE;
 
-       if (value)
-         DrawMiniGraphicExt(drawto, dst_x, dst_y, graphic);
+       if (draw_masked)
+       {
+         SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
+                       dst_x - src_x, dst_y - src_y);
+         BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, width, height,
+                          dst_x, dst_y);
+       }
        else
-         BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto, src_x, src_y,
-                    MINI_TILEX, MINI_TILEY, dst_x, dst_y);
+       {
+         BlitBitmap(src_bitmap, drawto, src_x, src_y, width, height,
+                    dst_x, dst_y);
+       }
       }
+#else
+      if (value == EL_UNDEFINED || value == EL_EMPTY)
+      {
+       element = (last_value == EL_UNDEFINED ? EL_EMPTY : last_value);
+       graphic = el2panelimg(element);
+
+       src_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
+       src_x = DOOR_GFX_PAGEX5 + ALIGNED_TEXT_XPOS(pos);
+       src_y = DOOR_GFX_PAGEY1 + ALIGNED_TEXT_YPOS(pos);
+      }
+      else
+      {
+       element = value;
+       graphic = el2panelimg(value);
+
+       getSizedGraphicSource(graphic, frame, size, &src_bitmap, &src_x,&src_y);
+      }
+
+      width  = graphic_info[graphic].width  * size / TILESIZE;
+      height = graphic_info[graphic].height * size / TILESIZE;
+
+      BlitBitmap(src_bitmap, drawto, src_x, src_y, width, height, dst_x, dst_y);
+#endif
     }
     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);
+      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) */
+#if 0
+       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);
+#endif
+
+       font = (active ? font2 : font1);
+      }
 
       if (s != NULL)
       {
-       char *s_cut = getStringCopyN(s, pos->chars);
+       char *s_cut;
 
-       DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), s_cut, pos->font);
+#if 1
+       if (size <= 0)
+       {
+         /* don't truncate output if "chars" is zero or less */
+         size = strlen(s);
+
+         /* dynamically correct text alignment */
+         pos->width = size * getFontWidth(font);
+       }
+#endif
+
+       s_cut = getStringCopyN(s, size);
+
+       DrawTextExt(drawto, PANEL_XPOS(pos), PANEL_YPOS(pos),
+                   s_cut, font, mask_mode);
 
        free(s_cut);
       }
     }
+
+    redraw_mask |= REDRAW_DOOR_1;
   }
+
+  game_status = GAME_MODE_PLAYING;
 }
 
 void DrawGameValue_Emeralds(int value)
@@ -1997,7 +2663,7 @@ 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 !!! */
@@ -2013,14 +2679,14 @@ 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 !!! */
@@ -2043,7 +2709,7 @@ 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 !!! */
@@ -2063,7 +2729,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;
@@ -2113,7 +2779,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;
@@ -2261,7 +2927,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);
@@ -2371,9 +3037,13 @@ void DrawAllGameValues(int emeralds, int dynamite, int score, int time,
   DrawGameValue_Keys(key);
 }
 
-void DrawGameDoorValues()
+void UpdateGameDoorValues()
 {
   UpdateGameControlValues();
+}
+
+void DrawGameDoorValues()
+{
   DisplayGameControlValues();
 }
 
@@ -2667,6 +3337,7 @@ static void InitGameEngine()
     {
       ei->change_page[j].actual_trigger_element = EL_EMPTY;
       ei->change_page[j].actual_trigger_player = EL_PLAYER_1;
+      ei->change_page[j].actual_trigger_player_bits = CH_PLAYER_1;
       ei->change_page[j].actual_trigger_side = CH_SIDE_NONE;
       ei->change_page[j].actual_trigger_ce_value = 0;
       ei->change_page[j].actual_trigger_ce_score = 0;
@@ -2846,6 +3517,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)
@@ -3024,6 +3702,8 @@ void InitGame()
     player->LevelSolved_PanelOff = FALSE;
     player->LevelSolved_SaveTape = FALSE;
     player->LevelSolved_SaveScore = FALSE;
+    player->LevelSolved_CountingTime = 0;
+    player->LevelSolved_CountingScore = 0;
   }
 
   network_player_action_received = FALSE;
@@ -3052,6 +3732,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;
@@ -3138,6 +3819,8 @@ void InitGame()
       emulate_sp = FALSE;
 
     InitField(x, y, TRUE);
+
+    ResetGfxAnimation(x, y);
   }
 
   InitBeltMovement();
@@ -3374,7 +4057,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;
@@ -3391,7 +4075,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;
@@ -3411,7 +4096,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;
@@ -3442,6 +4128,11 @@ void InitGame()
                local_player->jy - MIDPOSY);
   }
 
+#if 0
+  /* do not use PLAYING mask for fading out from main screen */
+  game_status = GAME_MODE_MAIN;
+#endif
+
   StopAnimation();
 
   if (!game.restart_level)
@@ -3451,7 +4142,7 @@ void InitGame()
   if (level_editor_test_game)
     FadeSkipNextFadeIn();
   else
-    FadeSetStartItem();
+    FadeSetEnterScreen();
 #else
   if (level_editor_test_game)
     fading = fading_none;
@@ -3466,6 +4157,10 @@ void InitGame()
     FadeOut(REDRAW_FIELD);
 #endif
 
+#if 0
+  game_status = GAME_MODE_PLAYING;
+#endif
+
   /* !!! FIX THIS (START) !!! */
   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
   {
@@ -3510,6 +4205,7 @@ void InitGame()
   SetPanelBackground();
   SetDrawBackgroundMask(REDRAW_DOOR_1);
 
+  UpdateGameDoorValues();
   DrawGameDoorValues();
 
   if (!game.restart_level)
@@ -3767,6 +4463,9 @@ static void PlayerWins(struct PlayerInfo *player)
 
   player->score_final = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
                         level.native_em_level->lev->score : player->score);
+
+  player->LevelSolved_CountingTime = (level.time == 0 ? TimePlayed : TimeLeft);
+  player->LevelSolved_CountingScore = player->score_final;
 }
 
 void GameWon()
@@ -3822,8 +4521,11 @@ void GameWon()
       score = score_final;
 
 #if 1
-      game_control_value[GAME_CONTROL_TIME] = time;
-      game_control_value[GAME_CONTROL_SCORE] = score;
+      local_player->LevelSolved_CountingTime = time;
+      local_player->LevelSolved_CountingScore = score;
+
+      game_panel_controls[GAME_PANEL_TIME].value = time;
+      game_panel_controls[GAME_PANEL_SCORE].value = score;
 
       DisplayGameControlValues();
 #else
@@ -3904,8 +4606,11 @@ void GameWon()
     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;
+    local_player->LevelSolved_CountingTime = time;
+    local_player->LevelSolved_CountingScore = score;
+
+    game_panel_controls[GAME_PANEL_TIME].value = time;
+    game_panel_controls[GAME_PANEL_SCORE].value = score;
 
     DisplayGameControlValues();
 #else
@@ -4491,7 +5196,7 @@ 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)
     {
@@ -5254,12 +5959,19 @@ static void InitBeltMovement()
     for (j = 0; j < NUM_BELT_PARTS; j++)
     {
       int element = belt_base_active_element[belt_nr] + j;
-      int graphic = el2img(element);
+      int graphic_1 = el2img(element);
+      int graphic_2 = el2panelimg(element);
 
       if (game.belt_dir[i] == MV_LEFT)
-       graphic_info[graphic].anim_mode &= ~ANIM_REVERSE;
+      {
+       graphic_info[graphic_1].anim_mode &= ~ANIM_REVERSE;
+       graphic_info[graphic_2].anim_mode &= ~ANIM_REVERSE;
+      }
       else
-       graphic_info[graphic].anim_mode |=  ANIM_REVERSE;
+      {
+       graphic_info[graphic_1].anim_mode |=  ANIM_REVERSE;
+       graphic_info[graphic_2].anim_mode |=  ANIM_REVERSE;
+      }
     }
   }
 
@@ -5335,12 +6047,19 @@ static void ToggleBeltSwitch(int x, int y)
   for (i = 0; i < NUM_BELT_PARTS; i++)
   {
     int element = belt_base_active_element[belt_nr] + i;
-    int graphic = el2img(element);
+    int graphic_1 = el2img(element);
+    int graphic_2 = el2panelimg(element);
 
     if (belt_dir == MV_LEFT)
-      graphic_info[graphic].anim_mode &= ~ANIM_REVERSE;
+    {
+      graphic_info[graphic_1].anim_mode &= ~ANIM_REVERSE;
+      graphic_info[graphic_2].anim_mode &= ~ANIM_REVERSE;
+    }
     else
-      graphic_info[graphic].anim_mode |=  ANIM_REVERSE;
+    {
+      graphic_info[graphic_1].anim_mode |=  ANIM_REVERSE;
+      graphic_info[graphic_2].anim_mode |=  ANIM_REVERSE;
+    }
   }
 
   SCAN_PLAYFIELD(xx, yy)
@@ -8583,7 +9302,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)
@@ -9298,11 +10021,15 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
                            action_mode, action_arg_number,
                            action_arg_number_min, action_arg_number_max);
 
+#if 1
+  int trigger_player_bits = change->actual_trigger_player_bits;
+#else
   int trigger_player_bits =
     (change->actual_trigger_player >= EL_PLAYER_1 &&
      change->actual_trigger_player <= EL_PLAYER_4 ?
      (1 << (change->actual_trigger_player - EL_PLAYER_1)) :
      PLAYER_BITS_ANY);
+#endif
 
   int action_arg_player_bits =
     (action_arg >= CA_ARG_PLAYER_1 &&
@@ -9346,7 +10073,7 @@ 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;
+       game_panel_controls[GAME_PANEL_TIME].value = TimeLeft;
 
        DisplayGameControlValues();
 #else
@@ -9366,7 +10093,7 @@ 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;
+      game_panel_controls[GAME_PANEL_SCORE].value = local_player->score;
 
       DisplayGameControlValues();
 #else
@@ -9381,7 +10108,7 @@ 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;
+      game_panel_controls[GAME_PANEL_GEMS].value = local_player->gems_still_needed;
 
       DisplayGameControlValues();
 #else
@@ -9808,6 +10535,7 @@ static boolean ChangeElement(int x, int y, int element, int page)
     /* reset actual trigger element, trigger player and action element */
     change->actual_trigger_element = EL_EMPTY;
     change->actual_trigger_player = EL_PLAYER_1;
+    change->actual_trigger_player_bits = CH_PLAYER_1;
     change->actual_trigger_side = CH_SIDE_NONE;
     change->actual_trigger_ce_value = 0;
     change->actual_trigger_ce_score = 0;
@@ -10188,7 +10916,8 @@ static boolean CheckTriggeredElementChangeExt(int trigger_x, int trigger_y,
          IS_EQUAL_OR_IN_GROUP(trigger_element, change->trigger_element))
       {
        change->actual_trigger_element = trigger_element;
-       change->actual_trigger_player = EL_PLAYER_1 + log_2(trigger_player);
+       change->actual_trigger_player = GET_PLAYER_FROM_BITS(trigger_player);
+       change->actual_trigger_player_bits = trigger_player;
        change->actual_trigger_side = trigger_side;
        change->actual_trigger_ce_value = CustomValue[trigger_x][trigger_y];
        change->actual_trigger_ce_score = GET_CE_SCORE(trigger_element);
@@ -10307,7 +11036,8 @@ static boolean CheckElementChangeExt(int x, int y,
         IS_EQUAL_OR_IN_GROUP(trigger_element, change->trigger_element)))
     {
       change->actual_trigger_element = trigger_element;
-      change->actual_trigger_player = EL_PLAYER_1 + log_2(trigger_player);
+      change->actual_trigger_player = GET_PLAYER_FROM_BITS(trigger_player);
+      change->actual_trigger_player_bits = trigger_player;
       change->actual_trigger_side = trigger_side;
       change->actual_trigger_ce_value = CustomValue[x][y];
       change->actual_trigger_ce_score = GET_CE_SCORE(trigger_element);
@@ -10662,7 +11392,7 @@ static void CheckLevelTime()
          PlaySound(SND_GAME_RUNNING_OUT_OF_TIME);
 
 #if 1
-       game_control_value[GAME_CONTROL_TIME] = TimeLeft;
+       game_panel_controls[GAME_PANEL_TIME].value = TimeLeft;
 
        DisplayGameControlValues();
 #else
@@ -10681,7 +11411,7 @@ static void CheckLevelTime()
 #if 1
       else if (level.time == 0 && !AllPlayersGone) /* level w/o time limit */
       {
-       game_control_value[GAME_CONTROL_TIME] = TimePlayed;
+       game_panel_controls[GAME_PANEL_TIME].value = TimePlayed;
 
        DisplayGameControlValues();
       }
@@ -10698,6 +11428,7 @@ static void CheckLevelTime()
       DrawVideoDisplay(VIDEO_STATE_TIME_ON, TapeTime);
   }
 
+  UpdateGameDoorValues();
   DrawGameDoorValues();
 }
 
@@ -11565,6 +12296,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)
@@ -12114,7 +12846,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)))
     {
@@ -12415,7 +13147,7 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
          PlaySound(SND_GAME_RUNNING_OUT_OF_TIME);
 
 #if 1
-       game_control_value[GAME_CONTROL_TIME] = TimeLeft;
+       game_panel_controls[GAME_PANEL_TIME].value = TimeLeft;
 
        DisplayGameControlValues();
 #else
@@ -12429,7 +13161,7 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
 #if 1
       else if (level.time == 0 && !AllPlayersGone) /* level w/o time limit */
       {
-       game_control_value[GAME_CONTROL_TIME] = TimePlayed;
+       game_panel_controls[GAME_PANEL_TIME].value = TimePlayed;
 
        DisplayGameControlValues();
       }
@@ -13487,7 +14219,7 @@ int DigField(struct PlayerInfo *player,
       TimeLeft += level.extra_time;
 
 #if 1
-      game_control_value[GAME_CONTROL_TIME] = TimeLeft;
+      game_panel_controls[GAME_PANEL_TIME].value = TimeLeft;
 
       DisplayGameControlValues();
 #else
@@ -13572,7 +14304,7 @@ int DigField(struct PlayerInfo *player,
        local_player->gems_still_needed = 0;
 
 #if 1
-      game_control_value[GAME_CONTROL_GEMS] = local_player->gems_still_needed;
+      game_panel_controls[GAME_PANEL_GEMS].value = local_player->gems_still_needed;
 
       DisplayGameControlValues();
 #else
@@ -13757,6 +14489,8 @@ int DigField(struct PlayerInfo *player,
       ZX = x;
       ZY = y;
 
+      game.robot_wheel_active = TRUE;
+
       DrawLevelField(x, y);
     }
     else if (element == EL_SP_TERMINAL)
@@ -13823,7 +14557,7 @@ int DigField(struct PlayerInfo *player,
        TimeLeft += level.time_orb_time;
 
 #if 1
-       game_control_value[GAME_CONTROL_TIME] = TimeLeft;
+       game_panel_controls[GAME_PANEL_TIME].value = TimeLeft;
 
        DisplayGameControlValues();
 #else
@@ -14000,6 +14734,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 ?
@@ -14007,6 +14744,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;
 
@@ -14451,7 +15189,7 @@ void RaiseScore(int value)
   local_player->score += value;
 
 #if 1
-  game_control_value[GAME_CONTROL_SCORE] = local_player->score;
+  game_panel_controls[GAME_PANEL_SCORE].value = local_player->score;
 
   DisplayGameControlValues();
 #else
@@ -15074,6 +15812,7 @@ void CreateGameButtons()
                      GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y1,
                      GDI_ALT_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y2,
                      GDI_ALT_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y2,
+                     GDI_DIRECT_DRAW, FALSE,
                      GDI_EVENT_MASK, event_mask,
                      GDI_CALLBACK_ACTION, HandleGameButtons,
                      GDI_END);
@@ -15109,6 +15848,14 @@ void UnmapGameButtons()
     UnmapGadget(game_gadget[i]);
 }
 
+void RedrawGameButtons()
+{
+  int i;
+
+  for (i = 0; i < NUM_GAME_BUTTONS; i++)
+    RedrawGadget(game_gadget[i]);
+}
+
 static void HandleGameButtons(struct GadgetInfo *gi)
 {
   int id = gi->custom_id;