rnd-20070310-2-src
[rocksndiamonds.git] / src / game.c
index afa0f24f923f9cbcccfbe3ebcac1872545fe2b55..207be5f457a86e581b913aa095390bc803cc2381 100644 (file)
@@ -942,7 +942,7 @@ void GetPlayerConfig()
   InitJoysticks();
 }
 
-static int get_element_from_group_element(int element)
+int GetElementFromGroupElement(int element)
 {
   if (IS_GROUP_ELEMENT(element))
   {
@@ -1240,7 +1240,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);
       }
@@ -1290,14 +1290,14 @@ void DrawGameValue_Emeralds(int value)
   struct TextPosInfo *pos = &game.panel.gems;
   int font_nr = FONT_TEXT_2;
   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)
@@ -1305,14 +1305,14 @@ void DrawGameValue_Dynamite(int value)
   struct TextPosInfo *pos = &game.panel.inventory;
   int font_nr = FONT_TEXT_2;
   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)
@@ -1320,42 +1320,42 @@ void DrawGameValue_Score(int value)
   struct TextPosInfo *pos = &game.panel.score;
   int font_nr = FONT_TEXT_2;
   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;
   int font1_nr = FONT_TEXT_2;
   int font2_nr = FONT_TEXT_1;
   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 +1365,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 +1375,26 @@ 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;
   int font1_nr = FONT_TEXT_2;
   int font2_nr = FONT_TEXT_1;
   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])
@@ -8732,7 +8732,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 +9064,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);
@@ -10107,13 +10108,15 @@ void GameActions_RND()
 
        /* continue moving after pushing (this is actually a bug) */
        if (!IS_MOVING(x, y))
-       {
          Stop[x][y] = FALSE;
-       }
       }
     }
   }
 
+#if 0
+  debug_print_timestamp(0, "start main loop profiling");
+#endif
+
   SCAN_PLAYFIELD(x, y)
   {
     ChangeCount[x][y] = 0;
@@ -10188,6 +10191,63 @@ void GameActions_RND()
 #endif
   }
 
+#if 0
+  debug_print_timestamp(0, "- time for pre-main loop:");
+#endif
+
+#if 0  // -------------------- !!! TEST ONLY !!! --------------------
+  SCAN_PLAYFIELD(x, y)
+  {
+    element = Feld[x][y];
+    graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
+
+#if 1
+    {
+#if 1
+      int element2 = element;
+      int graphic2 = graphic;
+#else
+      int element2 = Feld[x][y];
+      int graphic2 = el_act_dir2img(element2, GfxAction[x][y], GfxDir[x][y]);
+#endif
+      int last_gfx_frame = GfxFrame[x][y];
+
+      if (graphic_info[graphic2].anim_global_sync)
+       GfxFrame[x][y] = FrameCounter;
+      else if (ANIM_MODE(graphic2) == ANIM_CE_VALUE)
+       GfxFrame[x][y] = CustomValue[x][y];
+      else if (ANIM_MODE(graphic2) == ANIM_CE_SCORE)
+       GfxFrame[x][y] = element_info[element2].collect_score;
+      else if (ANIM_MODE(graphic2) == ANIM_CE_DELAY)
+       GfxFrame[x][y] = ChangeDelay[x][y];
+
+      if (redraw && GfxFrame[x][y] != last_gfx_frame)
+       DrawLevelGraphicAnimation(x, y, graphic2);
+    }
+#else
+    ResetGfxFrame(x, y, TRUE);
+#endif
+
+#if 1
+    if (ANIM_MODE(graphic) == ANIM_RANDOM &&
+       IS_NEXT_FRAME(GfxFrame[x][y], graphic))
+      ResetRandomAnimationValue(x, y);
+#endif
+
+#if 1
+    SetRandomAnimationValue(x, y);
+#endif
+
+#if 1
+    PlayLevelSoundActionIfLoop(x, y, GfxAction[x][y]);
+#endif
+  }
+#endif // -------------------- !!! TEST ONLY !!! --------------------
+
+#if 0
+  debug_print_timestamp(0, "- time for TEST loop:     -->");
+#endif
+
   SCAN_PLAYFIELD(x, y)
   {
     element = Feld[x][y];
@@ -10231,6 +10291,143 @@ void GameActions_RND()
       graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
     }
 
+#if 0  // ---------------------------------------------------------------------
+
+    if (!IS_MOVING(x, y) && (CAN_FALL(element) || CAN_MOVE(element)))
+    {
+      StartMoving(x, y);
+
+      element = Feld[x][y];
+      graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
+
+      if (IS_ANIMATED(graphic) &&
+         !IS_MOVING(x, y) &&
+         !Stop[x][y])
+       DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
+
+      if (IS_GEM(element) || element == EL_SP_INFOTRON)
+       DrawTwinkleOnField(x, y);
+    }
+    else if (IS_MOVING(x, y))
+      ContinueMoving(x, y);
+    else
+    {
+      switch (element)
+      {
+        case EL_ACID:
+        case EL_EXIT_OPEN:
+        case EL_EM_EXIT_OPEN:
+        case EL_SP_EXIT_OPEN:
+        case EL_STEEL_EXIT_OPEN:
+        case EL_EM_STEEL_EXIT_OPEN:
+        case EL_SP_TERMINAL:
+        case EL_SP_TERMINAL_ACTIVE:
+        case EL_EXTRA_TIME:
+        case EL_SHIELD_NORMAL:
+        case EL_SHIELD_DEADLY:
+         if (IS_ANIMATED(graphic))
+           DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
+         break;
+
+        case EL_DYNAMITE_ACTIVE:
+        case EL_EM_DYNAMITE_ACTIVE:
+        case EL_DYNABOMB_PLAYER_1_ACTIVE:
+        case EL_DYNABOMB_PLAYER_2_ACTIVE:
+        case EL_DYNABOMB_PLAYER_3_ACTIVE:
+        case EL_DYNABOMB_PLAYER_4_ACTIVE:
+        case EL_SP_DISK_RED_ACTIVE:
+         CheckDynamite(x, y);
+         break;
+
+        case EL_AMOEBA_GROWING:
+         AmoebeWaechst(x, y);
+         break;
+
+        case EL_AMOEBA_SHRINKING:
+         AmoebaDisappearing(x, y);
+         break;
+
+#if !USE_NEW_AMOEBA_CODE
+        case EL_AMOEBA_WET:
+        case EL_AMOEBA_DRY:
+        case EL_AMOEBA_FULL:
+        case EL_BD_AMOEBA:
+        case EL_EMC_DRIPPER:
+         AmoebeAbleger(x, y);
+         break;
+#endif
+
+        case EL_GAME_OF_LIFE:
+        case EL_BIOMAZE:
+         Life(x, y);
+         break;
+
+        case EL_EXIT_CLOSED:
+         CheckExit(x, y);
+         break;
+
+        case EL_EM_EXIT_CLOSED:
+         CheckExitEM(x, y);
+         break;
+
+        case EL_STEEL_EXIT_CLOSED:
+         CheckExitSteel(x, y);
+         break;
+
+        case EL_EM_STEEL_EXIT_CLOSED:
+         CheckExitSteelEM(x, y);
+         break;
+
+        case EL_SP_EXIT_CLOSED:
+         CheckExitSP(x, y);
+         break;
+
+        case EL_EXPANDABLE_WALL_GROWING:
+        case EL_EXPANDABLE_STEELWALL_GROWING:
+         MauerWaechst(x, y);
+         break;
+
+        case EL_EXPANDABLE_WALL:
+        case EL_EXPANDABLE_WALL_HORIZONTAL:
+        case EL_EXPANDABLE_WALL_VERTICAL:
+        case EL_EXPANDABLE_WALL_ANY:
+        case EL_BD_EXPANDABLE_WALL:
+         MauerAbleger(x, y);
+         break;
+
+        case EL_EXPANDABLE_STEELWALL_HORIZONTAL:
+        case EL_EXPANDABLE_STEELWALL_VERTICAL:
+        case EL_EXPANDABLE_STEELWALL_ANY:
+         MauerAblegerStahl(x, y);
+         break;
+
+        case EL_FLAMES:
+         CheckForDragon(x, y);
+         break;
+
+        case EL_EXPLOSION:
+         break;
+
+        case EL_ELEMENT_SNAPPING:
+        case EL_DIAGONAL_SHRINKING:
+        case EL_DIAGONAL_GROWING:
+       {
+         graphic =
+           el_act_dir2img(GfxElement[x][y], GfxAction[x][y],GfxDir[x][y]);
+
+         DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
+         break;
+       }
+
+        default:
+         if (IS_ANIMATED(graphic) && !IS_CHANGING(x, y))
+           DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
+         break;
+      }
+    }
+
+#else  // ---------------------------------------------------------------------
+
     if (!IS_MOVING(x, y) && (CAN_FALL(element) || CAN_MOVE(element)))
     {
       StartMoving(x, y);
@@ -10313,6 +10510,8 @@ void GameActions_RND()
     else if (IS_ANIMATED(graphic) && !IS_CHANGING(x, y))
       DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
 
+#endif // ---------------------------------------------------------------------
+
     if (IS_BELT_ACTIVE(element))
       PlayLevelSoundAction(x, y, ACTION_ACTIVE);
 
@@ -10338,6 +10537,10 @@ void GameActions_RND()
     }
   }
 
+#if 0
+  debug_print_timestamp(0, "- time for MAIN loop:     -->");
+#endif
+
 #if USE_NEW_AMOEBA_CODE
   /* new experimental amoeba growth stuff */
   if (!(FrameCounter % 8))
@@ -10521,6 +10724,11 @@ void GameActions_RND()
     local_player->show_envelope = 0;
   }
 
+#if 0
+  debug_print_timestamp(0, "stop main loop profiling ");
+  printf("----------------------------------------------------------\n");
+#endif
+
   /* use random number generator in every frame to make it less predictable */
   if (game.engine_version >= VERSION_IDENT(3,1,1,0))
     RND(1);
@@ -10575,14 +10783,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,
@@ -10601,6 +10814,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));