rnd-20060207-1-src
[rocksndiamonds.git] / src / tools.c
index 27c2a9f8c155b36e4c0a165eae93e180fe2c2f78..4711961d04144b313957294b5e84ec4d215b90d7 100644 (file)
@@ -2450,6 +2450,15 @@ unsigned int MoveDoor(unsigned int door_state)
   unsigned long door_delay_value;
   int stepsize = 1;
 
+  if (door_1.width < 0 || door_1.width > DXSIZE)
+    door_1.width = DXSIZE;
+  if (door_1.height < 0 || door_1.height > DYSIZE)
+    door_1.height = DYSIZE;
+  if (door_2.width < 0 || door_2.width > VXSIZE)
+    door_2.width = VXSIZE;
+  if (door_2.height < 0 || door_2.height > VYSIZE)
+    door_2.height = VYSIZE;
+
   if (door_state == DOOR_GET_STATE)
     return(door1 | door2);
 
@@ -2489,12 +2498,31 @@ unsigned int MoveDoor(unsigned int door_state)
 
   if (door_state & DOOR_ACTION)
   {
-    boolean door_1_done = !(door_state & DOOR_ACTION_1);
-    boolean door_2_done = !(door_state & DOOR_ACTION_2);
-    int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
+    boolean handle_door_1 = (door_state & DOOR_ACTION_1);
+    boolean handle_door_2 = (door_state & DOOR_ACTION_2);
+    boolean door_1_done = (!handle_door_1);
+    boolean door_2_done = (!handle_door_2);
+    boolean door_1_vertical = (door_1.anim_mode & ANIM_VERTICAL);
+    boolean door_2_vertical = (door_2.anim_mode & ANIM_VERTICAL);
+    int door_size_1 = (door_1_vertical ? door_1.height : door_1.width);
+    int door_size_2 = (door_2_vertical ? door_2.height : door_2.width);
+    int max_door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
+    int max_door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
+    int door_size     = (handle_door_1 ? door_size_1     : door_size_2);
+    int max_door_size = (handle_door_1 ? max_door_size_1 : max_door_size_2);
+    int door_skip = max_door_size - door_size;
+#if 1
+    int end = door_size;
+#else
     int end = (door_state & DOOR_ACTION_1 &&
-              door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
-    int x;
+              door_1.anim_mode & ANIM_VERTICAL ? DYSIZE : DXSIZE);
+#endif
+#if 1
+    int start = ((door_state & DOOR_NO_DELAY) ? end : 0);
+#else
+    int start = ((door_state & DOOR_NO_DELAY) ? end : offset_skip);
+#endif
+    int k;
 
     if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
     {
@@ -2505,26 +2533,34 @@ unsigned int MoveDoor(unsigned int door_state)
        PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
     }
 
-    for (x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
+    for (k = start; k <= end && !(door_1_done && door_2_done); k += stepsize)
     {
+      int x = k;
       Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
       GC gc = bitmap->stored_clip_gc;
 
       if (door_state & DOOR_ACTION_1)
       {
        int a = MIN(x * door_1.step_offset, end);
-       int i = (door_state & DOOR_OPEN_1 ? end - a : a);
+       int p = (door_state & DOOR_OPEN_1 ? end - a : a);
+       int i = p + door_skip;
 
-       if (x <= a)
+       if (door_1.anim_mode & ANIM_STATIC_PANEL)
        {
          BlitBitmap(bitmap_db_door, drawto,
-                    DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
-                    DXSIZE, DYSIZE - i / 2, DX, DY);
+                    DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1,
+                    DXSIZE, DYSIZE, DX, DY);
+       }
+       else if (x <= a)
+       {
+         BlitBitmap(bitmap_db_door, drawto,
+                    DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + p / 2,
+                    DXSIZE, DYSIZE - p / 2, DX, DY);
 
-         ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
+         ClearRectangle(drawto, DX, DY + DYSIZE - p / 2, DXSIZE, p / 2);
        }
 
-       if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
+       if (door_1.anim_mode & ANIM_HORIZONTAL && x <= DXSIZE)
        {
          int src1_x = DXSIZE,          src1_y = DOOR_GFX_PAGEY1;
          int dst1_x = DX + DXSIZE - i, dst1_y = DY;
@@ -2540,7 +2576,7 @@ unsigned int MoveDoor(unsigned int door_state)
          BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
                           dst2_x, dst2_y);
        }
-       else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
+       else if (door_1.anim_mode & ANIM_VERTICAL && x <= DYSIZE)
        {
          int src1_x = DXSIZE,          src1_y = DOOR_GFX_PAGEY1;
          int dst1_x = DX,              dst1_y = DY + DYSIZE - i;
@@ -2597,19 +2633,26 @@ unsigned int MoveDoor(unsigned int door_state)
 
       if (door_state & DOOR_ACTION_2)
       {
-       int a = MIN(x * door_2.step_offset, VXSIZE);
-       int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
+       int a = MIN(x * door_2.step_offset, door_size_2);
+       int p = (door_state & DOOR_OPEN_2 ? door_size_2 - a : a);
+       int i = p + door_skip;
 
-       if (x <= VYSIZE)
+       if (door_2.anim_mode & ANIM_STATIC_PANEL)
        {
          BlitBitmap(bitmap_db_door, drawto,
-                    DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
-                    VXSIZE, VYSIZE - i / 2, VX, VY);
+                    DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2,
+                    VXSIZE, VYSIZE, VX, VY);
+       }
+       else if (x <= VYSIZE)
+       {
+         BlitBitmap(bitmap_db_door, drawto,
+                    DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + p / 2,
+                    VXSIZE, VYSIZE - p / 2, VX, VY);
 
-         ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
+         ClearRectangle(drawto, VX, VY + VYSIZE - p / 2, VXSIZE, p / 2);
        }
 
-       if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
+       if (door_2.anim_mode & ANIM_HORIZONTAL && x <= VXSIZE)
        {
          int src1_x = VXSIZE,          src1_y = DOOR_GFX_PAGEY2;
          int dst1_x = VX + VXSIZE - i, dst1_y = VY;
@@ -2625,7 +2668,7 @@ unsigned int MoveDoor(unsigned int door_state)
          BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
                           dst2_x, dst2_y);
        }
-       else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
+       else if (door_2.anim_mode & ANIM_VERTICAL && x <= VYSIZE)
        {
          int src1_x = VXSIZE,          src1_y = DOOR_GFX_PAGEY2;
          int dst1_x = VX,              dst1_y = VY + VYSIZE - i;
@@ -2694,8 +2737,8 @@ void DrawSpecialEditorDoor()
             DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
             EX - 4, EY - 12);
   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
-            EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
-            EX - 4, EY - 4);
+            EX - 6, VY - 4, EXSIZE + 12, EYSIZE - VYSIZE + 4,
+            EX - 6, EY - 4);
 
   redraw_mask |= REDRAW_ALL;
 }
@@ -2704,8 +2747,8 @@ void UndrawSpecialEditorDoor()
 {
   /* draw normal tape recorder window */
   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
-            EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
-            EX - 4, EY - 12);
+            EX - 6, EY - 12, EXSIZE + 12, EYSIZE - VYSIZE + 12,
+            EX - 6, EY - 12);
 
   redraw_mask |= REDRAW_ALL;
 }
@@ -3293,11 +3336,11 @@ em_object_mapping_list[] =
   },
   {
     Yandroid_ne,                       FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
+    EL_EMC_ANDROID,                    ACTION_GROWING, MV_BIT_UPRIGHT
   },
   {
     Yandroid_neB,                      FALSE,  TRUE,
-    EL_EMC_ANDROID,                    ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
+    EL_EMC_ANDROID,                    ACTION_SHRINKING, MV_BIT_UPRIGHT
   },
   {
     Yandroid_e,                                FALSE,  FALSE,
@@ -3309,11 +3352,11 @@ em_object_mapping_list[] =
   },
   {
     Yandroid_se,                       FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
+    EL_EMC_ANDROID,                    ACTION_GROWING, MV_BIT_DOWNRIGHT
   },
   {
     Yandroid_seB,                      FALSE,  TRUE,
-    EL_EMC_ANDROID,                    ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
+    EL_EMC_ANDROID,                    ACTION_SHRINKING, MV_BIT_DOWNRIGHT
   },
   {
     Yandroid_s,                                FALSE,  FALSE,
@@ -3325,11 +3368,11 @@ em_object_mapping_list[] =
   },
   {
     Yandroid_sw,                       FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
+    EL_EMC_ANDROID,                    ACTION_GROWING, MV_BIT_DOWNLEFT
   },
   {
     Yandroid_swB,                      FALSE,  TRUE,
-    EL_EMC_ANDROID,                    ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
+    EL_EMC_ANDROID,                    ACTION_SHRINKING, MV_BIT_DOWNLEFT
   },
   {
     Yandroid_w,                                FALSE,  FALSE,
@@ -3341,11 +3384,11 @@ em_object_mapping_list[] =
   },
   {
     Yandroid_nw,                       FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_TURNING_FROM_UP, MV_BIT_LEFT
+    EL_EMC_ANDROID,                    ACTION_GROWING, MV_BIT_UPLEFT
   },
   {
     Yandroid_nwB,                      FALSE,  TRUE,
-    EL_EMC_ANDROID,                    ACTION_TURNING_FROM_UP, MV_BIT_LEFT
+    EL_EMC_ANDROID,                    ACTION_SHRINKING, MV_BIT_UPLEFT
   },
   {
     Xspring,                           TRUE,   FALSE,
@@ -4694,6 +4737,110 @@ em_player_mapping_list[] =
     SPR_still,                         1,
     EL_PLAYER_2,                       ACTION_DEFAULT, -1,
   },
+  {
+    SPR_walk + 0,                      2,
+    EL_PLAYER_3,                       ACTION_MOVING, MV_BIT_UP,
+  },
+  {
+    SPR_walk + 1,                      2,
+    EL_PLAYER_3,                       ACTION_MOVING, MV_BIT_RIGHT,
+  },
+  {
+    SPR_walk + 2,                      2,
+    EL_PLAYER_3,                       ACTION_MOVING, MV_BIT_DOWN,
+  },
+  {
+    SPR_walk + 3,                      2,
+    EL_PLAYER_3,                       ACTION_MOVING, MV_BIT_LEFT,
+  },
+  {
+    SPR_push + 0,                      2,
+    EL_PLAYER_3,                       ACTION_PUSHING, MV_BIT_UP,
+  },
+  {
+    SPR_push + 1,                      2,
+    EL_PLAYER_3,                       ACTION_PUSHING, MV_BIT_RIGHT,
+  },
+  {
+    SPR_push + 2,                      2,
+    EL_PLAYER_3,                       ACTION_PUSHING, MV_BIT_DOWN,
+  },
+  {
+    SPR_push + 3,                      2,
+    EL_PLAYER_3,                       ACTION_PUSHING, MV_BIT_LEFT,
+  },
+  {
+    SPR_spray + 0,                     2,
+    EL_PLAYER_3,                       ACTION_SNAPPING, MV_BIT_UP,
+  },
+  {
+    SPR_spray + 1,                     2,
+    EL_PLAYER_3,                       ACTION_SNAPPING, MV_BIT_RIGHT,
+  },
+  {
+    SPR_spray + 2,                     2,
+    EL_PLAYER_3,                       ACTION_SNAPPING, MV_BIT_DOWN,
+  },
+  {
+    SPR_spray + 3,                     2,
+    EL_PLAYER_3,                       ACTION_SNAPPING, MV_BIT_LEFT,
+  },
+  {
+    SPR_walk + 0,                      3,
+    EL_PLAYER_4,                       ACTION_MOVING, MV_BIT_UP,
+  },
+  {
+    SPR_walk + 1,                      3,
+    EL_PLAYER_4,                       ACTION_MOVING, MV_BIT_RIGHT,
+  },
+  {
+    SPR_walk + 2,                      3,
+    EL_PLAYER_4,                       ACTION_MOVING, MV_BIT_DOWN,
+  },
+  {
+    SPR_walk + 3,                      3,
+    EL_PLAYER_4,                       ACTION_MOVING, MV_BIT_LEFT,
+  },
+  {
+    SPR_push + 0,                      3,
+    EL_PLAYER_4,                       ACTION_PUSHING, MV_BIT_UP,
+  },
+  {
+    SPR_push + 1,                      3,
+    EL_PLAYER_4,                       ACTION_PUSHING, MV_BIT_RIGHT,
+  },
+  {
+    SPR_push + 2,                      3,
+    EL_PLAYER_4,                       ACTION_PUSHING, MV_BIT_DOWN,
+  },
+  {
+    SPR_push + 3,                      3,
+    EL_PLAYER_4,                       ACTION_PUSHING, MV_BIT_LEFT,
+  },
+  {
+    SPR_spray + 0,                     3,
+    EL_PLAYER_4,                       ACTION_SNAPPING, MV_BIT_UP,
+  },
+  {
+    SPR_spray + 1,                     3,
+    EL_PLAYER_4,                       ACTION_SNAPPING, MV_BIT_RIGHT,
+  },
+  {
+    SPR_spray + 2,                     3,
+    EL_PLAYER_4,                       ACTION_SNAPPING, MV_BIT_DOWN,
+  },
+  {
+    SPR_spray + 3,                     3,
+    EL_PLAYER_4,                       ACTION_SNAPPING, MV_BIT_LEFT,
+  },
+  {
+    SPR_still,                         2,
+    EL_PLAYER_3,                       ACTION_DEFAULT, -1,
+  },
+  {
+    SPR_still,                         3,
+    EL_PLAYER_4,                       ACTION_DEFAULT, -1,
+  },
 
   {
     -1,                                        -1,
@@ -4764,6 +4911,9 @@ void map_android_clone_elements_RND_to_EM(struct LevelInfo *level)
   struct LEVEL *lev = level_em->lev;
   int i, j;
 
+  for (i = 0; i < TILE_MAX; i++)
+    lev->android_array[i] = Xblank;
+
   for (i = 0; i < level->num_android_clone_elements; i++)
   {
     int element_rnd = level->android_clone_element[i];
@@ -5491,7 +5641,7 @@ int el_act_dir2img(int element, int action, int direction)
   if (direction == MV_NONE)
     return element_info[element].graphic[action];
 
-  direction = MV_DIR_BIT(direction);
+  direction = MV_DIR_TO_BIT(direction);
 
   return element_info[element].direction_graphic[action][direction];
 }
@@ -5499,7 +5649,7 @@ int el_act_dir2img(int element, int action, int direction)
 int el_act_dir2img(int element, int action, int direction)
 {
   element = GFX_ELEMENT(element);
-  direction = MV_DIR_BIT(direction);   /* default: MV_NONE => MV_DOWN */
+  direction = MV_DIR_TO_BIT(direction);        /* default: MV_NONE => MV_DOWN */
 
   /* direction_graphic[][] == graphic[] for undefined direction graphics */
   return element_info[element].direction_graphic[action][direction];
@@ -5514,7 +5664,7 @@ static int el_act_dir2crm(int element, int action, int direction)
   if (direction == MV_NONE)
     return element_info[element].crumbled[action];
 
-  direction = MV_DIR_BIT(direction);
+  direction = MV_DIR_TO_BIT(direction);
 
   return element_info[element].direction_crumbled[action][direction];
 }
@@ -5522,7 +5672,7 @@ static int el_act_dir2crm(int element, int action, int direction)
 static int el_act_dir2crm(int element, int action, int direction)
 {
   element = GFX_ELEMENT(element);
-  direction = MV_DIR_BIT(direction);   /* default: MV_NONE => MV_DOWN */
+  direction = MV_DIR_TO_BIT(direction);        /* default: MV_NONE => MV_DOWN */
 
   /* direction_graphic[][] == graphic[] for undefined direction graphics */
   return element_info[element].direction_crumbled[action][direction];
@@ -5609,7 +5759,7 @@ unsigned int InitRND(long seed)
 void InitGraphicInfo_EM(void)
 {
   struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
-  struct Mapping_EM_to_RND_player player_mapping[2][SPR_MAX];
+  struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
   int i, j, p;
 
 #if DEBUG_EM_GFX
@@ -5631,7 +5781,7 @@ void InitGraphicInfo_EM(void)
   }
 
   /* always start with reliable default values */
-  for (p = 0; p < 2; p++)
+  for (p = 0; p < MAX_PLAYERS; p++)
   {
     for (i = 0; i < SPR_MAX; i++)
     {
@@ -5652,7 +5802,8 @@ void InitGraphicInfo_EM(void)
       object_mapping[e].action = em_object_mapping_list[i].action;
 
     if (em_object_mapping_list[i].direction != -1)
-      object_mapping[e].direction = (1 << em_object_mapping_list[i].direction);
+      object_mapping[e].direction =
+       MV_DIR_FROM_BIT(em_object_mapping_list[i].direction);
   }
 
   for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
@@ -5667,7 +5818,7 @@ void InitGraphicInfo_EM(void)
 
     if (em_player_mapping_list[i].direction != -1)
       player_mapping[p][a].direction =
-       (1 << em_player_mapping_list[i].direction);
+       MV_DIR_FROM_BIT(em_player_mapping_list[i].direction);
   }
 
   for (i = 0; i < TILE_MAX; i++)
@@ -5974,6 +6125,15 @@ void InitGraphicInfo_EM(void)
        g_em->height = TILEY - cy * step;
       }
 
+#if 1
+      /* create unique graphic identifier to decide if tile must be redrawn */
+      /* bit 31 - 16 (16 bit): EM style graphic
+        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 =
+       (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
+#else
       /* 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
@@ -5981,8 +6141,22 @@ void InitGraphicInfo_EM(void)
         bit  5 -  0 ( 6 bit): graphic height */
       g_em->unique_identifier =
        (i << 16) | (j << 12) | (g_em->width << 6) | g_em->height;
+#endif
+
+#if 0
+      if (effective_element == EL_ROCK)
+       printf("::: EL_ROCK(%d, %d): %d, %d => %d\n",
+              effective_action, j, graphic, frame, g_em->unique_identifier);
+#endif
 
 #if DEBUG_EM_GFX
+
+#if 1
+      /* skip check for EMC elements not contained in original EMC artwork */
+      if (element == EL_EMC_FAKE_ACID)
+       continue;
+#endif
+
       if (g_em->bitmap != debug_bitmap ||
          g_em->src_x != debug_src_x ||
          g_em->src_y != debug_src_y ||
@@ -6075,7 +6249,7 @@ void InitGraphicInfo_EM(void)
     }
   }
 
-  for (p = 0; p < 2; p++)
+  for (p = 0; p < MAX_PLAYERS; p++)
   {
     for (i = 0; i < SPR_MAX; i++)
     {