rnd-20070312-4-src
[rocksndiamonds.git] / src / game.c
index a52780cbc7e63762ac4fc04c86c170a9984224cf..6b920a51ca2d40b9ca2f097e6d3fa865ff0f2c81 100644 (file)
 #define DX_TIME                        (DX + XX_TIME)
 #define DY_TIME                        (DY + YY_TIME)
 
+#if 0
+/* game panel display and control definitions */
+
+#define GAME_CONTROL_LEVEL                     0
+#define GAME_CONTROL_GEMS                      1
+#define GAME_CONTROL_INVENTORY                 2
+#define GAME_CONTROL_KEYS                      3
+#define GAME_CONTROL_SCORE                     4
+#define GAME_CONTROL_TIME                      5
+#define GAME_CONTROL_TIME_HH                   6
+#define GAME_CONTROL_TIME_MM                   7
+#define GAME_CONTROL_TIME_SS                   8
+#define GAME_CONTROL_DROP_NEXT_1               9
+#define GAME_CONTROL_DROP_NEXT_2               10
+#define GAME_CONTROL_DROP_NEXT_3               11
+#define GAME_CONTROL_DROP_NEXT_4               12
+#define GAME_CONTROL_DROP_NEXT_5               13
+#define GAME_CONTROL_DROP_NEXT_6               14
+#define GAME_CONTROL_DROP_NEXT_7               15
+#define GAME_CONTROL_DROP_NEXT_8               16
+#define GAME_CONTROL_EMC_KEYS                  17
+#define GAME_CONTROL_KEY_1                     18
+#define GAME_CONTROL_KEY_2                     19
+#define GAME_CONTROL_KEY_3                     20
+#define GAME_CONTROL_KEY_4                     21
+#define GAME_CONTROL_KEY_5                     22
+#define GAME_CONTROL_KEY_6                     23
+#define GAME_CONTROL_KEY_7                     24
+#define GAME_CONTROL_KEY_8                     25
+#define GAME_CONTROL_KEY_WHITE                 26
+#define GAME_CONTROL_KEY_WHITE_COUNT           27
+#define GAME_CONTROL_SHIELD_NORMAL             28
+#define GAME_CONTROL_SHIELD_NORMAL_TIME                29
+#define GAME_CONTROL_SHIELD_DEADLY             30
+#define GAME_CONTROL_SHIELD_DEADLY_TIME                31
+#define GAME_CONTROL_EXIT                      32
+#define GAME_CONTROL_EM_EXIT                   33
+#define GAME_CONTROL_SP_EXIT                   34
+#define GAME_CONTROL_STEEL_EXIT                        35
+#define GAME_CONTROL_EM_STEEL_EXIT             36
+#define GAME_CONTROL_EMC_MAGIC_BALL            37
+#define GAME_CONTROL_EMC_MAGIC_BALL_TIME       38
+#define GAME_CONTROL_LIGHT_SWITCH              39
+#define GAME_CONTROL_LIGHT_SWITCH_TIME         40
+#define GAME_CONTROL_TIMEGATE_SWITCH           41
+#define GAME_CONTROL_TIMEGATE_SWITCH_TIME      42
+#define GAME_CONTROL_SWITCHGATE_SWITCH         43
+#define GAME_CONTROL_EMC_LENSES                        44
+#define GAME_CONTROL_EMC_LENSES_TIME           45
+#define GAME_CONTROL_EMC_MAGNIFIER             46
+#define GAME_CONTROL_EMC_MAGNIFIER_TIME                47
+#define GAME_CONTROL_BALLOON_SWITCH            48
+#define GAME_CONTROL_DYNABOMB_NUMBER           49
+#define GAME_CONTROL_DYNABOMB_SIZE             50
+#define GAME_CONTROL_DYNABOMB_POWER            51
+#define GAME_CONTROL_PENGUINS                  52
+#define GAME_CONTROL_SOKOBAN_OBJECTS           53
+#define GAME_CONTROL_SOKOBAN_FIELDS            54
+#define GAME_CONTROL_ROBOT_WHEEL               55
+#define GAME_CONTROL_CONVEYOR_BELT_1           56
+#define GAME_CONTROL_CONVEYOR_BELT_1_SWITCH    57
+#define GAME_CONTROL_CONVEYOR_BELT_2           58
+#define GAME_CONTROL_CONVEYOR_BELT_2_SWITCH    59
+#define GAME_CONTROL_CONVEYOR_BELT_3           60
+#define GAME_CONTROL_CONVEYOR_BELT_3_SWITCH    61
+#define GAME_CONTROL_CONVEYOR_BELT_4           62
+#define GAME_CONTROL_CONVEYOR_BELT_4_SWITCH    63
+#define GAME_CONTROL_MAGIC_WALL                        64
+#define GAME_CONTROL_MAGIC_WALL_TIME           65
+#define GAME_CONTROL_BD_MAGIC_WALL             66
+#define GAME_CONTROL_DC_MAGIC_WALL             67
+#define GAME_CONTROL_PLAYER_NAME               68
+#define GAME_CONTROL_LEVEL_NAME                        69
+#define GAME_CONTROL_LEVEL_AUTHOR              70
+
+struct GameControlInfo
+{
+  int nr;
+
+  struct TextPosInfo *pos_text;
+  int type;
+  void *ptr;
+};
+
+static struct GameControlInfo game_controls[] =
+{
+  {
+    GAME_CONTROL_LEVEL,
+    &game.panel.level,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_GEMS,
+    &game.panel.gems,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_INVENTORY,
+    &game.panel.inventory,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_KEYS,
+    &game.panel.keys,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_SCORE,
+    &game.panel.score,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_TIME,
+    &game.panel.time,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_TIME_HH,
+    &game.panel.time_hh,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_TIME_MM,
+    &game.panel.time_mm,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_TIME_SS,
+    &game.panel.time_ss,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_DROP_NEXT_1,
+    &game.panel.drop_next_1,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_DROP_NEXT_2,
+    &game.panel.drop_next_2,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_DROP_NEXT_3,
+    &game.panel.drop_next_3,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_DROP_NEXT_4,
+    &game.panel.drop_next_4,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_DROP_NEXT_5,
+    &game.panel.drop_next_5,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_DROP_NEXT_6,
+    &game.panel.drop_next_6,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_DROP_NEXT_7,
+    &game.panel.drop_next_7,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_DROP_NEXT_8,
+    &game.panel.drop_next_8,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_EMC_KEYS,
+    &game.panel.emc_keys,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_KEY_1,
+    &game.panel.key_1,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_KEY_2,
+    &game.panel.key_2,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_KEY_3,
+    &game.panel.key_3,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_KEY_4,
+    &game.panel.key_4,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_KEY_5,
+    &game.panel.key_5,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_KEY_6,
+    &game.panel.key_6,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_KEY_7,
+    &game.panel.key_7,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_KEY_8,
+    &game.panel.key_8,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_KEY_WHITE,
+    &game.panel.key_white,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_KEY_WHITE_COUNT,
+    &game.panel.key_white_count,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_SHIELD_NORMAL,
+    &game.panel.shield_normal,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_SHIELD_NORMAL_TIME,
+    &game.panel.shield_normal_time,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_SHIELD_DEADLY,
+    &game.panel.shield_deadly,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_SHIELD_DEADLY_TIME,
+    &game.panel.shield_deadly_time,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_EXIT,
+    &game.panel.exit,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_EM_EXIT,
+    &game.panel.em_exit,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_SP_EXIT,
+    &game.panel.sp_exit,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_STEEL_EXIT,
+    &game.panel.steel_exit,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_EM_STEEL_EXIT,
+    &game.panel.em_steel_exit,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_EMC_MAGIC_BALL,
+    &game.panel.emc_magic_ball,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_EMC_MAGIC_BALL_TIME,
+    &game.panel.emc_magic_ball_time,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_LIGHT_SWITCH,
+    &game.panel.light_switch,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_LIGHT_SWITCH_TIME,
+    &game.panel.light_switch_time,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_TIMEGATE_SWITCH,
+    &game.panel.timegate_switch,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_TIMEGATE_SWITCH_TIME,
+    &game.panel.timegate_switch_time,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_SWITCHGATE_SWITCH,
+    &game.panel.switchgate_switch,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_EMC_LENSES,
+    &game.panel.emc_lenses,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_EMC_LENSES_TIME,
+    &game.panel.emc_lenses_time,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_EMC_MAGNIFIER,
+    &game.panel.emc_magnifier,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_EMC_MAGNIFIER_TIME,
+    &game.panel.emc_magnifier_time,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_BALLOON_SWITCH,
+    &game.panel.balloon_switch,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_DYNABOMB_NUMBER,
+    &game.panel.dynabomb_number,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_DYNABOMB_SIZE,
+    &game.panel.dynabomb_size,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_DYNABOMB_POWER,
+    &game.panel.dynabomb_power,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_PENGUINS,
+    &game.panel.penguins,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_SOKOBAN_OBJECTS,
+    &game.panel.sokoban_objects,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_SOKOBAN_FIELDS,
+    &game.panel.sokoban_fields,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_ROBOT_WHEEL,
+    &game.panel.robot_wheel,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_CONVEYOR_BELT_1,
+    &game.panel.conveyor_belt_1,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_CONVEYOR_BELT_1_SWITCH,
+    &game.panel.conveyor_belt_1_switch,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_CONVEYOR_BELT_2,
+    &game.panel.conveyor_belt_2,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_CONVEYOR_BELT_2_SWITCH,
+    &game.panel.conveyor_belt_2_switch,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_CONVEYOR_BELT_3,
+    &game.panel.conveyor_belt_3,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_CONVEYOR_BELT_3_SWITCH,
+    &game.panel.conveyor_belt_3_switch,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_CONVEYOR_BELT_4,
+    &game.panel.conveyor_belt_4,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_CONVEYOR_BELT_4_SWITCH,
+    &game.panel.conveyor_belt_4_switch,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_MAGIC_WALL,
+    &game.panel.magic_wall,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_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_CONTROL_PLAYER_NAME,
+    &game.panel.player_name,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_LEVEL_NAME,
+    &game.panel.level_name,
+    TYPE_INTEGER,
+  },
+  {
+    GAME_CONTROL_LEVEL_AUTHOR,
+    &game.panel.level_author,
+    TYPE_INTEGER,
+  },
+
+  {
+    -1,
+    NULL,
+    -1,
+    NULL
+  }
+};
+#endif
+
+
 /* values for delayed check of falling and moving elements and for collision */
 #define CHECK_DELAY_MOVING     3
 #define CHECK_DELAY_FALLING    CHECK_DELAY_MOVING
@@ -843,7 +1295,7 @@ static int playfield_scan_delta_y = 1;
                                     (y) += playfield_scan_delta_y)     \
                                for ((x) = playfield_scan_start_x;      \
                                     (x) >= 0 && (x) <= lev_fieldx - 1; \
-                                    (x) += playfield_scan_delta_x)     \
+                                    (x) += playfield_scan_delta_x)
 
 #ifdef DEBUG
 void DEBUG_SetMaximumDynamite()
@@ -942,7 +1394,7 @@ void GetPlayerConfig()
   InitJoysticks();
 }
 
-static int get_element_from_group_element(int element)
+int GetElementFromGroupElement(int element)
 {
   if (IS_GROUP_ELEMENT(element))
   {
@@ -1240,7 +1692,7 @@ static void InitField(int x, int y, boolean init_game)
       }
       else if (IS_GROUP_ELEMENT(element))
       {
-       Feld[x][y] = get_element_from_group_element(element);
+       Feld[x][y] = GetElementFromGroupElement(element);
 
        InitField(x, y, init_game);
       }
@@ -1288,74 +1740,91 @@ static inline void InitField_WithBug2(int x, int y, boolean init_game)
 void DrawGameValue_Emeralds(int value)
 {
   struct TextPosInfo *pos = &game.panel.gems;
+#if 1
+  int font_nr = pos->font;
+#else
   int font_nr = FONT_TEXT_2;
+#endif
   int font_width = getFontWidth(font_nr);
-  int digits = pos->chars;
+  int chars = pos->chars;
 
   if (PANEL_DEACTIVATED(pos))
     return;
 
-  pos->width = digits * font_width;
+  pos->width = chars * font_width;
 
-  DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, digits), font_nr);
+  DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, chars), font_nr);
 }
 
 void DrawGameValue_Dynamite(int value)
 {
   struct TextPosInfo *pos = &game.panel.inventory;
+#if 1
+  int font_nr = pos->font;
+#else
   int font_nr = FONT_TEXT_2;
+#endif
   int font_width = getFontWidth(font_nr);
-  int digits = pos->chars;
+  int chars = pos->chars;
 
   if (PANEL_DEACTIVATED(pos))
     return;
 
-  pos->width = digits * font_width;
+  pos->width = chars * font_width;
 
-  DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, digits), font_nr);
+  DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, chars), font_nr);
 }
 
 void DrawGameValue_Score(int value)
 {
   struct TextPosInfo *pos = &game.panel.score;
+#if 1
+  int font_nr = pos->font;
+#else
   int font_nr = FONT_TEXT_2;
+#endif
   int font_width = getFontWidth(font_nr);
-  int digits = pos->chars;
+  int chars = pos->chars;
 
   if (PANEL_DEACTIVATED(pos))
     return;
 
-  pos->width = digits * font_width;
+  pos->width = chars * font_width;
 
-  DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, digits), font_nr);
+  DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, chars), font_nr);
 }
 
 void DrawGameValue_Time(int value)
 {
   struct TextPosInfo *pos = &game.panel.time;
   static int last_value = -1;
-  int digits1 = 3;
-  int digits2 = 4;
-  int digits = pos->chars;
+  int chars1 = 3;
+  int chars2 = 4;
+  int chars = pos->chars;
+#if 1
+  int font1_nr = pos->font;
+  int font2_nr = pos->font_alt;
+#else
   int font1_nr = FONT_TEXT_2;
   int font2_nr = FONT_TEXT_1;
+#endif
   int font_nr = font1_nr;
-  boolean use_dynamic_digits = (digits == -1 ? TRUE : FALSE);
+  boolean use_dynamic_chars = (chars == -1 ? TRUE : FALSE);
 
   if (PANEL_DEACTIVATED(pos))
     return;
 
-  if (use_dynamic_digits)              /* use dynamic number of digits */
+  if (use_dynamic_chars)               /* use dynamic number of chars */
   {
-    digits  = (value < 1000 ? digits1  : digits2);
+    chars   = (value < 1000 ? chars1   : chars2);
     font_nr = (value < 1000 ? font1_nr : font2_nr);
   }
 
-  /* clear background if value just changed its size (dynamic digits only) */
-  if (use_dynamic_digits && (last_value < 1000) != (value < 1000))
+  /* clear background if value just changed its size (dynamic chars only) */
+  if (use_dynamic_chars && (last_value < 1000) != (value < 1000))
   {
-    int width1 = digits1 * getFontWidth(font1_nr);
-    int width2 = digits2 * getFontWidth(font2_nr);
+    int width1 = chars1 * getFontWidth(font1_nr);
+    int width2 = chars2 * getFontWidth(font2_nr);
     int max_width = MAX(width1, width2);
     int max_height = MAX(getFontHeight(font1_nr), getFontHeight(font2_nr));
 
@@ -1365,9 +1834,9 @@ void DrawGameValue_Time(int value)
                               max_width, max_height);
   }
 
-  pos->width = digits * getFontWidth(font_nr);
+  pos->width = chars * getFontWidth(font_nr);
 
-  DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, digits), font_nr);
+  DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, chars), font_nr);
 
   last_value = value;
 }
@@ -1375,26 +1844,31 @@ void DrawGameValue_Time(int value)
 void DrawGameValue_Level(int value)
 {
   struct TextPosInfo *pos = &game.panel.level;
-  int digits1 = 2;
-  int digits2 = 3;
-  int digits = pos->chars;
+  int chars1 = 2;
+  int chars2 = 3;
+  int chars = pos->chars;
+#if 1
+  int font1_nr = pos->font;
+  int font2_nr = pos->font_alt;
+#else
   int font1_nr = FONT_TEXT_2;
   int font2_nr = FONT_TEXT_1;
+#endif
   int font_nr = font1_nr;
-  boolean use_dynamic_digits = (digits == -1 ? TRUE : FALSE);
+  boolean use_dynamic_chars = (chars == -1 ? TRUE : FALSE);
 
   if (PANEL_DEACTIVATED(pos))
     return;
 
-  if (use_dynamic_digits)              /* use dynamic number of digits */
+  if (use_dynamic_chars)               /* use dynamic number of chars */
   {
-    digits  = (level_nr < 100 ? digits1  : digits2);
+    chars   = (level_nr < 100 ? chars1   : chars2);
     font_nr = (level_nr < 100 ? font1_nr : font2_nr);
   }
 
-  pos->width = digits * getFontWidth(font_nr);
+  pos->width = chars * getFontWidth(font_nr);
 
-  DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, digits), font_nr);
+  DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, chars), font_nr);
 }
 
 void DrawGameValue_Keys(int key[MAX_NUM_KEYS])
@@ -1419,11 +1893,34 @@ void DrawGameValue_Keys(int key[MAX_NUM_KEYS])
     int dst_x = PANEL_XPOS(pos) + i * MINI_TILEX;
     int dst_y = PANEL_YPOS(pos);
 
+#if 0
+    /* masked blit with tiles from half-size scaled bitmap does not work yet
+       (no mask bitmap created for these sizes after loading and scaling) --
+       solution: load without creating mask, scale, then create final mask */
+
+    BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto, src_x, src_y,
+              MINI_TILEX, MINI_TILEY, dst_x, dst_y);
+
+    if (key[i])
+    {
+      int graphic = el2edimg(base_key_graphic + i);
+      Bitmap *src_bitmap;
+      int src_x, src_y;
+
+      getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
+
+      SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
+                   dst_x - src_x, dst_y - src_y);
+      BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, MINI_TILEX, MINI_TILEY,
+                      dst_x, dst_y);
+    }
+#else
     if (key[i])
       DrawMiniGraphicExt(drawto, dst_x, dst_y, el2edimg(base_key_graphic + i));
     else
       BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto, src_x, src_y,
                 MINI_TILEX, MINI_TILEY, dst_x, dst_y);
+#endif
   }
 }
 
@@ -8732,7 +9229,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
 static void CreateFieldExt(int x, int y, int element, boolean is_change)
 {
   int old_element = Feld[x][y];
-  int new_element = get_element_from_group_element(element);
+  int new_element = GetElementFromGroupElement(element);
   int previous_move_direction = MovDir[x][y];
 #if USE_NEW_CUSTOM_VALUE
   int last_ce_value = CustomValue[x][y];
@@ -9064,12 +9561,13 @@ static void HandleElementChange(int x, int y, int page)
 
     if (change->can_change)
     {
-#if 0
+#if 1
       /* !!! not clear why graphic animation should be reset at all here !!! */
+      /* !!! UPDATE: but is needed for correct Snake Bite tail animation !!! */
 #if USE_GFX_RESET_WHEN_NOT_MOVING
       /* when a custom element is about to change (for example by change delay),
         do not reset graphic animation when the custom element is moving */
-      if (IS_MOVING(x, y))
+      if (!IS_MOVING(x, y))
 #endif
       {
        ResetGfxAnimation(x, y);
@@ -10782,14 +11280,19 @@ void ScrollLevel(int dx, int dy)
   int i, x, y;
 #endif
 
+#if 0
+  /* !!! THIS IS APPARENTLY WRONG FOR PLAYER RELOCATION !!! */
   /* only horizontal XOR vertical scroll direction allowed */
   if ((dx == 0 && dy == 0) || (dx != 0 && dy != 0))
     return;
+#endif
 
 #if 1
   if (bitmap_db_field2 == NULL)
     bitmap_db_field2 = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
 
+  /* needed when blitting directly to same bitmap -- should not be needed with
+     recent SDL libraries, but apparently does not work in 1.2.11 directly */
   BlitBitmap(drawto_field, bitmap_db_field2,
             FX + TILEX * (dx == -1) - softscroll_offset,
             FY + TILEY * (dy == -1) - softscroll_offset,
@@ -10808,6 +11311,7 @@ void ScrollLevel(int dx, int dy)
 #else
 
 #if 1
+  /* !!! DOES NOT WORK FOR DIAGONAL PLAYER RELOCATION !!! */
   int xsize = (BX2 - BX1 + 1);
   int ysize = (BY2 - BY1 + 1);
   int start = (dx != 0 ? (dx == -1 ? BX1 : BX2) : (dy == -1 ? BY1 : BY2));