rnd-20060812-2-src
[rocksndiamonds.git] / src / game.c
index 20491136b82b53a4a802c5b6acd4d64a0447ee89..40cffd8f40b6ac0d9b991ac7e5a23a9a307aeb77 100644 (file)
@@ -49,6 +49,9 @@
 
 #define USE_QUICKSAND_IMPACT_BUGFIX    (USE_NEW_STUFF          * 0)
 
+#define USE_CODE_THAT_BREAKS_SNAKE_BITE        (USE_NEW_STUFF          * 1)
+
+
 /* for DigField() */
 #define DF_NO_PUSH             0
 #define DF_DIG                 1
 #define EX_TYPE_DYNA           (1 << 4)
 #define EX_TYPE_SINGLE_TILE    (EX_TYPE_CENTER | EX_TYPE_BORDER)
 
+#if 1
+
+#define        PANEL_DEACTIVATED(p)    ((p).x < 0 || (p).y < 0)
+
+/* special positions in the game control window (relative to control window) */
+#define XX_LEVEL1              (game.panel.level.x)
+#define XX_LEVEL2              (game.panel.level.x - 1)
+#define YY_LEVEL               (game.panel.level.y)
+#define XX_EMERALDS            (game.panel.gems.x)
+#define YY_EMERALDS            (game.panel.gems.y)
+#define XX_DYNAMITE            (game.panel.inventory.x)
+#define YY_DYNAMITE            (game.panel.inventory.y)
+#define XX_KEYS                        (game.panel.keys.x)
+#define YY_KEYS                        (game.panel.keys.y)
+#define XX_SCORE               (game.panel.score.x)
+#define YY_SCORE               (game.panel.score.y)
+#define XX_TIME1               (game.panel.time.x)
+#define XX_TIME2               (game.panel.time.x + 1)
+#define YY_TIME                        (game.panel.time.y)
+
+#else
+
 /* special positions in the game control window (relative to control window) */
 #define XX_LEVEL               37
 #define YY_LEVEL               20
 #define XX_TIME2               30
 #define YY_TIME                        194
 
+#endif
+
 /* special positions in the game control window (relative to main window) */
-#define DX_LEVEL               (DX + XX_LEVEL)
+#define DX_LEVEL1              (DX + XX_LEVEL1)
+#define DX_LEVEL2              (DX + XX_LEVEL2)
 #define DY_LEVEL               (DY + YY_LEVEL)
 #define DX_EMERALDS            (DX + XX_EMERALDS)
 #define DY_EMERALDS            (DY + YY_EMERALDS)
        ((e) >= NUM_FILE_ELEMENTS ? EL_UNKNOWN : (e))
 #endif
 
-#define GET_TARGET_ELEMENT(e, ch, cv, cs)                              \
+#define RESOLVED_REFERENCE_ELEMENT(be, e)                              \
+       ((be) + (e) - EL_SELF < EL_CUSTOM_START ? EL_CUSTOM_START :     \
+        (be) + (e) - EL_SELF > EL_CUSTOM_END   ? EL_CUSTOM_END :       \
+        (be) + (e) - EL_SELF)
+
+#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   :  \
         (e) == EL_TRIGGER_CE_VALUE ? (ch)->actual_trigger_ce_value  :  \
         (e) == EL_TRIGGER_CE_SCORE ? (ch)->actual_trigger_ce_score  :  \
         (e) == EL_CURRENT_CE_VALUE ? (cv) :                            \
-        (e) == EL_CURRENT_CE_SCORE ? (cs) : (e))
+        (e) == EL_CURRENT_CE_SCORE ? (cs) :                            \
+        (e) >= EL_LAST_CE_8 && (e) <= EL_NEXT_CE_8 ?                   \
+        RESOLVED_REFERENCE_ELEMENT(be, e) :                            \
+        (e))
 
 #define CAN_GROW_INTO(e)                                               \
        ((e) == EL_SAND || (IS_DIGGABLE(e) && level.grow_into_diggable))
@@ -1198,6 +1234,7 @@ static void InitField(int x, int y, boolean init_game)
        InitField(x, y, init_game);
 #endif
       }
+
       break;
   }
 
@@ -1256,6 +1293,9 @@ inline void DrawGameValue_Emeralds(int value)
 {
   int xpos = (3 * 14 - 3 * getFontWidth(FONT_TEXT_2)) / 2;
 
+  if (PANEL_DEACTIVATED(game.panel.gems))
+    return;
+
   DrawText(DX_EMERALDS + xpos, DY_EMERALDS, int2str(value, 3), FONT_TEXT_2);
 }
 
@@ -1263,6 +1303,9 @@ inline void DrawGameValue_Dynamite(int value)
 {
   int xpos = (3 * 14 - 3 * getFontWidth(FONT_TEXT_2)) / 2;
 
+  if (PANEL_DEACTIVATED(game.panel.inventory))
+    return;
+
   DrawText(DX_DYNAMITE + xpos, DY_DYNAMITE, int2str(value, 3), FONT_TEXT_2);
 }
 
@@ -1271,19 +1314,23 @@ inline void DrawGameValue_Keys(int key[MAX_NUM_KEYS])
   int base_key_graphic = EL_KEY_1;
   int i;
 
+  if (PANEL_DEACTIVATED(game.panel.keys))
+    return;
+
   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
     base_key_graphic = EL_EM_KEY_1;
 
   /* currently only 4 of 8 possible keys are displayed */
   for (i = 0; i < STD_NUM_KEYS; i++)
   {
+    int x = XX_KEYS + i * MINI_TILEX;
+    int y = YY_KEYS;
+
     if (key[i])
-      DrawMiniGraphicExt(drawto, DX_KEYS + i * MINI_TILEX, DY_KEYS,
-                        el2edimg(base_key_graphic + i));
+      DrawMiniGraphicExt(drawto, DX + x,DY + y, el2edimg(base_key_graphic + i));
     else
       BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
-                DOOR_GFX_PAGEX5 + XX_KEYS + i * MINI_TILEX, YY_KEYS,
-                MINI_TILEX, MINI_TILEY, DX_KEYS + i * MINI_TILEX, DY_KEYS);
+                DOOR_GFX_PAGEX5 + x, y, MINI_TILEX, MINI_TILEY, DX + x,DY + y);
   }
 }
 
@@ -1291,6 +1338,9 @@ inline void DrawGameValue_Score(int value)
 {
   int xpos = (5 * 14 - 5 * getFontWidth(FONT_TEXT_2)) / 2;
 
+  if (PANEL_DEACTIVATED(game.panel.score))
+    return;
+
   DrawText(DX_SCORE + xpos, DY_SCORE, int2str(value, 5), FONT_TEXT_2);
 }
 
@@ -1299,9 +1349,12 @@ inline void DrawGameValue_Time(int value)
   int xpos3 = (3 * 14 - 3 * getFontWidth(FONT_TEXT_2)) / 2;
   int xpos4 = (4 * 10 - 4 * getFontWidth(FONT_LEVEL_NUMBER)) / 2;
 
+  if (PANEL_DEACTIVATED(game.panel.time))
+    return;
+
   /* clear background if value just changed its size */
   if (value == 999 || value == 1000)
-    ClearRectangle(drawto, DX_TIME1, DY_TIME, 14 * 3, 14);
+    ClearRectangleOnBackground(drawto, DX_TIME1, DY_TIME, 14 * 3, 14);
 
   if (value < 1000)
     DrawText(DX_TIME1 + xpos3, DY_TIME, int2str(value, 3), FONT_TEXT_2);
@@ -1311,9 +1364,15 @@ inline void DrawGameValue_Time(int value)
 
 inline void DrawGameValue_Level(int value)
 {
+  if (PANEL_DEACTIVATED(game.panel.level))
+    return;
+
   if (level_nr < 100)
-    DrawText(DX_LEVEL, DY_LEVEL, int2str(value, 2), FONT_TEXT_2);
+    DrawText(DX_LEVEL1, DY_LEVEL, int2str(value, 2), FONT_TEXT_2);
   else
+#if 1
+    DrawText(DX_LEVEL2, DY_LEVEL, int2str(value, 3), FONT_LEVEL_NUMBER);
+#else
   {
     /* misuse area for displaying emeralds to draw bigger level number */
     DrawTextExt(drawto, DX_EMERALDS, DY_EMERALDS,
@@ -1331,6 +1390,7 @@ inline void DrawGameValue_Level(int value)
 
     /* yes, this is all really ugly :-) */
   }
+#endif
 }
 
 void DrawAllGameValues(int emeralds, int dynamite, int score, int time,
@@ -1354,6 +1414,7 @@ void DrawAllGameValues(int emeralds, int dynamite, int score, int time,
 
 void DrawGameDoorValues()
 {
+  int time_value = (level.time == 0 ? TimePlayed : TimeLeft);
   int dynamite_state = 0;
   int key_bits = 0;
   int i, j;
@@ -1402,7 +1463,7 @@ void DrawGameDoorValues()
   }
 
   DrawAllGameValues(local_player->gems_still_needed, dynamite_state,
-                   local_player->score, TimeLeft, key_bits);
+                   local_player->score, time_value, key_bits);
 #endif
 }
 
@@ -1452,6 +1513,18 @@ static void resolve_group_element(int group_element, int recursion_depth)
 }
 #endif
 
+#if 0
+static void replace_reference_element(int base_element, int *element)
+{
+  if (*element >= EL_LAST_CE_8 && *element <= EL_NEXT_CE_8)
+  {
+    *element = base_element + *element - EL_SELF;
+    *element = (*element < EL_CUSTOM_START ? EL_CUSTOM_START :
+               *element > EL_CUSTOM_END   ? EL_CUSTOM_END   : *element);
+  }
+}
+#endif
+
 /*
   =============================================================================
   InitGameEngine()
@@ -1754,6 +1827,11 @@ static void InitGameEngine()
              for (l = 0; l < group->num_elements_resolved; l++)
                trigger_events[group->element_resolved[l]][k] = TRUE;
            }
+#if 1
+           else if (trigger_element == EL_ANY_ELEMENT)
+             for (l = 0; l < MAX_NUM_ELEMENTS; l++)
+               trigger_events[l][k] = TRUE;
+#endif
            else
              trigger_events[trigger_element][k] = TRUE;
          }
@@ -1891,6 +1969,29 @@ static void InitGameEngine()
         EL_EMPTY);
     }
   }
+
+#if 0
+  /* ---------- initialize reference elements ------------------------------- */
+  for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+  {
+    int element = EL_CUSTOM_START + i;
+    struct ElementInfo *ei = &element_info[element];
+
+    for (y = 0; y < 3; y++) for (x = 0; x < 3; x++)
+      replace_reference_element(element, &ei->content.e[x][y]);
+
+    for (j = 0; j < ei->num_change_pages; j++)
+    {
+      struct ElementChangeInfo *change = &ei->change_page[j];
+
+      replace_reference_element(element, &change->target_element);
+      replace_reference_element(element, &change->trigger_element);
+
+      for (y = 0; y < 3; y++) for (x = 0; x < 3; x++)
+       replace_reference_element(element, &change->target_content.e[x][y]);
+    }
+  }
+#endif
 }
 
 int get_num_special_action(int element, int action_first, int action_last)
@@ -2553,6 +2654,11 @@ void InitGame()
               DOOR_GFX_PAGEX5, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, DX, DY);
   }
 
+#if 1
+  SetPanelBackground();
+  SetDrawBackgroundMask(REDRAW_DOOR_1);
+#endif
+
   DrawGameDoorValues();
 
   if (!game.restart_level)
@@ -8484,7 +8590,12 @@ static void CreateFieldExt(int x, int y, int element, boolean is_change)
 #endif
   boolean new_element_is_player = ELEM_IS_PLAYER(new_element);
   boolean add_player_onto_element = (new_element_is_player &&
+#if USE_CODE_THAT_BREAKS_SNAKE_BITE
+                                    /* this breaks SnakeBite when a snake is
+                                       halfway through a door that closes */
+                                    /* NOW FIXED AT LEVEL INIT IN files.c */
                                     new_element != EL_SOKOBAN_FIELD_PLAYER &&
+#endif
                                     IS_WALKABLE(old_element));
 
 #if 0
@@ -8711,7 +8822,7 @@ static boolean ChangeElement(int x, int y, int element, int page)
          ChangeEvent[ex][ey] = ChangeEvent[x][y];
 
          content_element = change->target_content.e[xx][yy];
-         target_element = GET_TARGET_ELEMENT(content_element, change,
+         target_element = GET_TARGET_ELEMENT(element, content_element, change,
                                              ce_value, ce_score);
 
          CreateElementFromChange(ex, ey, target_element);
@@ -8733,7 +8844,7 @@ static boolean ChangeElement(int x, int y, int element, int page)
   }
   else
   {
-    target_element = GET_TARGET_ELEMENT(change->target_element, change,
+    target_element = GET_TARGET_ELEMENT(element, change->target_element, change,
                                        ce_value, ce_score);
 
     if (element == EL_DIAGONAL_GROWING ||
@@ -9673,6 +9784,10 @@ void GameActions_EM_Main()
   for (i = 0; i < MAX_PLAYERS; i++)
     effective_action[i] = stored_player[i].effective_action;
 
+#if 0
+  printf("::: %04d: %08x\n", FrameCounter, effective_action[0]);
+#endif
+
   GameActions_EM(effective_action, warp_mode);
 
   CheckLevelTime();
@@ -10397,7 +10512,7 @@ static void CheckGravityMovement(struct PlayerInfo *player)
   {
     int move_dir_horizontal = player->effective_action & MV_HORIZONTAL;
     int move_dir_vertical   = player->effective_action & MV_VERTICAL;
-    boolean player_is_snapping = player->effective_action & JOY_BUTTON_1;
+    boolean player_is_snapping = (player->effective_action & JOY_BUTTON_1);
     int jx = player->jx, jy = player->jy;
     boolean player_is_moving_to_valid_field =
       (!player_is_snapping &&