added setup option for fast game start from level editor
[rocksndiamonds.git] / src / game_bd / bd_cave.c
index 8add2cca7b29af9250b0ad604ed635915d5f3b6b..6a22a6379556b13d962f2cd26f7eb293eeb8aa09 100644 (file)
@@ -1316,13 +1316,14 @@ void gd_cave_count_diamonds(GdCave *cave)
   if a cell is changed, it is flagged with GD_REDRAW; the flag can be cleared
   by the caller.
 */
-void gd_drawcave_game(const GdCave *cave, int **element_buffer, int **gfx_buffer,
+void gd_drawcave_game(const GdCave *cave,
+                     int **element_buffer, int **last_element_buffer, int **gfx_buffer,
                      boolean bonus_life_flash, int animcycle, boolean hate_invisible_outbox)
 {
   static int player_blinking = 0;
   static int player_tapping = 0;
-  int elemmapping[O_MAX];
-  int elemdrawing[O_MAX];
+  int elemmapping[O_MAX_ALL];
+  int elemdrawing[O_MAX_ALL];
   int x, y, map, draw;
 
   if (cave->last_direction)
@@ -1346,7 +1347,7 @@ void gd_drawcave_game(const GdCave *cave, int **element_buffer, int **gfx_buffer
     }
   }
 
-  for (x = 0; x < O_MAX; x++)
+  for (x = 0; x < O_MAX_ALL; x++)
   {
     elemmapping[x] = x;
     elemdrawing[x] = gd_elements[x].image_game;
@@ -1454,6 +1455,16 @@ void gd_drawcave_game(const GdCave *cave, int **element_buffer, int **gfx_buffer
       draw = gd_elements[O_PLAYER].image_game;
     }
   }
+  else if (cave->last_direction == GD_MV_UP && use_bd_up_down_graphics())
+  {
+    map = O_PLAYER_UP;
+    draw = gd_elements[O_PLAYER_UP].image_game;
+  }
+  else if (cave->last_direction == GD_MV_DOWN && use_bd_up_down_graphics())
+  {
+    map = O_PLAYER_DOWN;
+    draw = gd_elements[O_PLAYER_DOWN].image_game;
+  }
   else if (cave->last_horizontal_direction == GD_MV_LEFT)
   {
     map = O_PLAYER_LEFT;
@@ -1511,8 +1522,8 @@ void gd_drawcave_game(const GdCave *cave, int **element_buffer, int **gfx_buffer
   // change only graphically
   if (hate_invisible_outbox)
   {
-    elemmapping[O_PRE_INVIS_OUTBOX] = O_PRE_OUTBOX;
-    elemmapping[O_INVIS_OUTBOX] = O_OUTBOX;
+    elemmapping[O_PRE_INVIS_OUTBOX] = elemmapping[O_PRE_OUTBOX];
+    elemmapping[O_INVIS_OUTBOX] = elemmapping[O_OUTBOX];
   }
 
   if (hate_invisible_outbox)
@@ -1539,6 +1550,28 @@ void gd_drawcave_game(const GdCave *cave, int **element_buffer, int **gfx_buffer
       else
        draw = elemdrawing[actual];
 
+      // draw special graphics if player is pushing something
+      if (use_bd_pushing_graphics() &&
+         (cave->last_direction == GD_MV_LEFT || cave->last_direction == GD_MV_RIGHT) &&
+         is_player(cave, x, y) && can_be_pushed_dir(cave, x, y, cave->last_direction))
+      {
+       // special check needed when smooth game element movements selected in setup menu:
+       // last element must either be player (before pushing) or pushable element (while pushing)
+       // (extra check needed to prevent pushing animation when moving towards pushable element)
+       if (!use_bd_smooth_movements() || last_element_buffer[y][x] != O_SPACE)
+       {
+         if (cave->last_direction == GD_MV_LEFT)
+           map = O_PLAYER_PUSH_LEFT;
+         else
+           map = O_PLAYER_PUSH_RIGHT;
+
+         if (cave->last_direction == GD_MV_LEFT)
+           draw = elemdrawing[O_PLAYER_PUSH_LEFT];
+         else
+           draw = elemdrawing[O_PLAYER_PUSH_RIGHT];
+       }
+      }
+
       // if negative, animated.
       if (draw < 0)
        draw = -draw + animcycle;
@@ -1645,3 +1678,60 @@ unsigned int gd_cave_adler_checksum(GdCave *cave)
   gd_cave_adler_checksum_more(cave, &a, &b);
   return (b << 16) + a;
 }
+
+boolean gd_cave_has_levels(GdCave *cave)
+{
+  GdCave c = *cave;
+  int *cave_level_value[] =
+  {
+    c.level_diamonds,
+    c.level_speed,
+    c.level_ckdelay,
+    c.level_time,
+    c.level_magic_wall_time,
+    c.level_amoeba_time,
+    c.level_amoeba_threshold,
+    c.level_amoeba_2_time,
+    c.level_amoeba_2_threshold,
+    c.level_slime_permeability,
+    c.level_slime_permeability_c64,
+    c.level_slime_seed_c64,
+    c.level_hatching_delay_frame,
+    c.level_hatching_delay_time,
+    c.level_bonus_time,
+    c.level_penalty_time,
+
+    NULL
+  };
+  int i, j;
+
+  for (i = 0; cave_level_value[i] != NULL; i++)
+    for (j = 1; j < 5; j++)
+      if (cave_level_value[i][j] != cave_level_value[i][0])
+       return TRUE;
+
+  for (j = 1; j < 5; j++)
+    if (cave->level_rand[j] != j &&
+       cave->level_rand[j - 1] != j - 1 &&
+       cave->level_rand[j] != cave->level_rand[0])
+      return TRUE;
+
+  for (j = 1; j < 5; j++)
+    if (cave->level_timevalue[j] != j + 1 &&
+       cave->level_timevalue[j - 1] != j &&
+       cave->level_timevalue[j] != cave->level_timevalue[0])
+      return TRUE;
+
+  return FALSE;
+}
+
+boolean gd_caveset_has_levels(void)
+{
+  List *iter;
+
+  for (iter = gd_caveset; iter != NULL; iter = iter->next)
+    if (gd_cave_has_levels((GdCave *)iter->data))
+      return TRUE;
+
+  return FALSE;
+}