rnd-20050115-1-src
[rocksndiamonds.git] / src / tools.c
index 3c341ec59a524266babaf0c094954dff4339206a..15841b17a993c0c85060d5d0ab64fd5203bb3801 100644 (file)
@@ -123,7 +123,12 @@ void SetDrawtoField(int mode)
 
 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
 {
-  if (game_status == GAME_MODE_PLAYING && !game.envelope_active)
+  if (game_status == GAME_MODE_PLAYING &&
+      level.game_engine_type == GAME_ENGINE_TYPE_EM)
+  {
+    BlitScreenToBitmap_EM(backbuffer);
+  }
+  else if (game_status == GAME_MODE_PLAYING && !game.envelope_active)
   {
     if (force_redraw)
     {
@@ -2219,6 +2224,12 @@ boolean Request(char *text, unsigned int req_state)
     }
   }
 
+#if 1
+  if (game_status == GAME_MODE_PLAYING &&
+      level.game_engine_type == GAME_ENGINE_TYPE_EM)
+    BlitScreenToBitmap_EM(backbuffer);
+#endif
+
 #if 1
   /* disable deactivated drawing when quick-loading level tape recording */
   if (tape.playing && tape.deactivate_display)
@@ -4035,7 +4046,7 @@ em_object_mapping_list[] =
     EL_AMOEBA_DRY,                     ACTION_OTHER, -1
   },
   {
-    Xamoeba_5,                         FALSE,  FALSE,
+    Xamoeba_5,                         TRUE,   FALSE,
     EL_AMOEBA_WET,                     ACTION_OTHER, -1
   },
   {
@@ -5495,21 +5506,51 @@ int get_next_element(int element)
   }
 }
 
+#if 0
+int el_act_dir2img(int element, int action, int direction)
+{
+  element = GFX_ELEMENT(element);
+
+  if (direction == MV_NO_MOVING)
+    return element_info[element].graphic[action];
+
+  direction = MV_DIR_BIT(direction);
+
+  return element_info[element].direction_graphic[action][direction];
+}
+#else
 int el_act_dir2img(int element, int action, int direction)
 {
   element = GFX_ELEMENT(element);
   direction = MV_DIR_BIT(direction);   /* default: MV_NO_MOVING => MV_DOWN */
 
+  /* direction_graphic[][] == graphic[] for undefined direction graphics */
   return element_info[element].direction_graphic[action][direction];
 }
+#endif
 
+#if 0
+static int el_act_dir2crm(int element, int action, int direction)
+{
+  element = GFX_ELEMENT(element);
+
+  if (direction == MV_NO_MOVING)
+    return element_info[element].crumbled[action];
+
+  direction = MV_DIR_BIT(direction);
+
+  return element_info[element].direction_crumbled[action][direction];
+}
+#else
 static int el_act_dir2crm(int element, int action, int direction)
 {
   element = GFX_ELEMENT(element);
   direction = MV_DIR_BIT(direction);   /* default: MV_NO_MOVING => MV_DOWN */
 
+  /* direction_graphic[][] == graphic[] for undefined direction graphics */
   return element_info[element].direction_crumbled[action][direction];
 }
+#endif
 
 int el_act2img(int element, int action)
 {
@@ -5560,8 +5601,17 @@ int el2preimg(int element)
 
 int getGameFrameDelay_EM(int native_em_game_frame_delay)
 {
-  return (GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
-         GameFrameDelay);
+  int game_frame_delay_value;
+
+  game_frame_delay_value =
+    (tape.playing && tape.fast_forward ? FfwdFrameDelay :
+     GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
+     GameFrameDelay);
+
+  if (tape.playing && tape.warp_forward && !tape.pausing)
+    game_frame_delay_value = 0;
+
+  return game_frame_delay_value;
 }
 
 unsigned int InitRND(long seed)
@@ -5659,7 +5709,6 @@ void InitGraphicInfo_EM(void)
       int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
                               j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
                               j < 7 ? element :
-                              i == Ynut_sB ? element :
                               i == Xdrip_stretch ? element :
                               i == Xdrip_stretchB ? element :
                               i == Ydrip_s1 ? element :
@@ -5684,11 +5733,12 @@ void InitGraphicInfo_EM(void)
                               i == Yspring_kill_w ? EL_SPRING :
                               i == Yemerald_stone ? EL_EMERALD :
                               i == Ydiamond_stone ? EL_ROCK :
+                              i == Xsand_stonein_4 ? EL_EMPTY :
+                              i == Xsand_stoneout_2 ? EL_ROCK :
                               is_backside ? EL_EMPTY :
                               action_removing ? EL_EMPTY :
                               element);
       int effective_action = (j < 7 ? action :
-                             i == Ynut_sB ? action :
                              i == Xdrip_stretch ? action :
                              i == Xdrip_stretchB ? action :
                              i == Ydrip_s1 ? action :
@@ -5720,14 +5770,22 @@ void InitGraphicInfo_EM(void)
                              action_active ? action :
                              action_other ? action :
                              ACTION_DEFAULT);
-      int graphic = (direction == MV_NO_MOVING ?
-                    el_act2img(effective_element, effective_action) :
-                    el_act_dir2img(effective_element, effective_action,
+      int graphic = (el_act_dir2img(effective_element, effective_action,
                                    direction));
+      int crumbled = (el_act_dir2crm(effective_element, effective_action,
+                                    direction));
+      int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
+      int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
+      boolean has_crumbled_graphics = (base_crumbled != base_graphic);
       struct GraphicInfo *g = &graphic_info[graphic];
       struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
       Bitmap *src_bitmap;
       int src_x, src_y;
+      /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
+      boolean special_animation = (action != ACTION_DEFAULT &&
+                                  g->anim_frames == 3 &&
+                                  g->anim_delay == 2 &&
+                                  g->anim_mode & ANIM_LINEAR);
       int sync_frame = (i == Xdrip_stretch ? 7 :
                        i == Xdrip_stretchB ? 7 :
                        i == Ydrip_s2 ? j + 8 :
@@ -5773,22 +5831,22 @@ void InitGraphicInfo_EM(void)
                        i == Xsand_stonein_2 ? j + 9 :
                        i == Xsand_stonein_3 ? j + 17 :
                        i == Xsand_stonein_4 ? j + 25 :
-                       i == Xsand_stoneout_1 && j == 0 ? 1 :
-                       i == Xsand_stoneout_1 && j == 1 ? 1 :
-                       i == Xsand_stoneout_1 && j == 2 ? 2 :
-                       i == Xsand_stoneout_1 && j == 3 ? 4 :
-                       i == Xsand_stoneout_1 && j == 4 ? 4 :
-                       i == Xsand_stoneout_1 && j == 5 ? 6 :
-                       i == Xsand_stoneout_1 && j == 6 ? 8 :
-                       i == Xsand_stoneout_1 && j == 7 ? 8 :
-                       i == Xsand_stoneout_2 && j == 0 ? 10 :
-                       i == Xsand_stoneout_2 && j == 1 ? 12 :
-                       i == Xsand_stoneout_2 && j == 2 ? 14 :
-                       i == Xsand_stoneout_2 && j == 3 ? 16 :
-                       i == Xsand_stoneout_2 && j == 4 ? 18 :
-                       i == Xsand_stoneout_2 && j == 5 ? 22 :
-                       i == Xsand_stoneout_2 && j == 6 ? 26 :
-                       i == Xsand_stoneout_2 && j == 7 ? 30 :
+                       i == Xsand_stoneout_1 && j == 0 ? 0 :
+                       i == Xsand_stoneout_1 && j == 1 ? 0 :
+                       i == Xsand_stoneout_1 && j == 2 ? 1 :
+                       i == Xsand_stoneout_1 && j == 3 ? 2 :
+                       i == Xsand_stoneout_1 && j == 4 ? 2 :
+                       i == Xsand_stoneout_1 && j == 5 ? 3 :
+                       i == Xsand_stoneout_1 && j == 6 ? 4 :
+                       i == Xsand_stoneout_1 && j == 7 ? 4 :
+                       i == Xsand_stoneout_2 && j == 0 ? 5 :
+                       i == Xsand_stoneout_2 && j == 1 ? 6 :
+                       i == Xsand_stoneout_2 && j == 2 ? 7 :
+                       i == Xsand_stoneout_2 && j == 3 ? 8 :
+                       i == Xsand_stoneout_2 && j == 4 ? 9 :
+                       i == Xsand_stoneout_2 && j == 5 ? 11 :
+                       i == Xsand_stoneout_2 && j == 6 ? 13 :
+                       i == Xsand_stoneout_2 && j == 7 ? 15 :
                        i == Xboom_bug && j == 1 ? 2 :
                        i == Xboom_bug && j == 2 ? 2 :
                        i == Xboom_bug && j == 3 ? 4 :
@@ -5819,6 +5877,7 @@ void InitGraphicInfo_EM(void)
                        i == Xboom_2 && j == 5 ? 12 :
                        i == Xboom_2 && j == 6 ? 12 :
                        i == Xboom_2 && j == 7 ? 12 :
+                       special_animation && j == 4 ? 3 :
                        effective_action != action ? 0 :
                        j);
 
@@ -5847,8 +5906,41 @@ void InitGraphicInfo_EM(void)
       g_em->dst_offset_y = 0;
       g_em->width  = TILEX;
       g_em->height = TILEY;
+
+      g_em->has_crumbled_graphics = FALSE;
+      g_em->crumbled_bitmap = NULL;
+      g_em->crumbled_src_x = 0;
+      g_em->crumbled_src_y = 0;
+      g_em->crumbled_border_size = 0;
 #endif
 
+#if 0
+      if (effective_element == EL_EMC_GRASS &&
+         effective_action == ACTION_DIGGING)
+       printf("::: %d\n", crumbled);
+#endif
+
+#if 0
+      if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
+       printf("::: empty crumbled: %d [%s], %d, %d\n",
+              effective_element, element_info[effective_element].token_name,
+              effective_action, direction);
+#endif
+
+      /* if element can be crumbled, but certain action graphics are just empty
+        space (like snapping sand with the original R'n'D graphics), do not
+        treat these empty space graphics as crumbled graphics in EMC engine */
+      if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
+      {
+       getGraphicSource(crumbled, frame, &src_bitmap, &src_x, &src_y);
+
+       g_em->has_crumbled_graphics = TRUE;
+       g_em->crumbled_bitmap = src_bitmap;
+       g_em->crumbled_src_x = src_x;
+       g_em->crumbled_src_y = src_y;
+       g_em->crumbled_border_size = graphic_info[crumbled].border_size;
+      }
+
 #if 1
       if (!g->double_movement && (effective_action == ACTION_FALLING ||
                                  effective_action == ACTION_MOVING ||
@@ -5861,7 +5953,7 @@ void InitGraphicInfo_EM(void)
        int cx = ABS(dx) * TILEX / 8;
        int cy = ABS(dy) * TILEY / 8;
 
-       if (is_backside)                /* tile where movement starts */
+       if (is_backside)        /* tile where movement starts */
        {
          if (dx < 0 || dy < 0)
          {
@@ -5897,8 +5989,12 @@ void InitGraphicInfo_EM(void)
 #endif
 
       /* create unique graphic identifier to decide if tile must be redrawn */
+      /* bit 31 - 16 (16 bit): EM style element
+        bit 15 - 12 ( 4 bit): EM style frame
+        bit 11 -  6 ( 6 bit): graphic width
+        bit  5 -  0 ( 6 bit): graphic height */
       g_em->unique_identifier =
-       (i << 16) | (frame << 8) | g_em->width | g_em->height;
+       (i << 16) | (j << 12) | (g_em->width << 6) | g_em->height;
 
 #if DEBUG_EM_GFX
       if (g_em->bitmap != debug_bitmap ||
@@ -5919,8 +6015,9 @@ void InitGraphicInfo_EM(void)
          last_i = i;
        }
 
-       printf("::: EMC GFX ERROR for element %d -> %d ('%s')",
-              i, element, element_info[element].token_name);
+       printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
+              i, element, element_info[element].token_name,
+              element_action_info[effective_action].suffix, direction);
 
        if (element != effective_element)
          printf(" [%d ('%s')]",