changed code for more generic explosion for MM engine
[rocksndiamonds.git] / src / game_mm / mm_game.c
index 652f05a43f281770666dd6b63b7c4c7fb2246c42..cda5e6aee9db15eba2061ac419ba873fe2125ae9 100644 (file)
@@ -99,6 +99,22 @@ static void InitMovingField_MM(int, int, int);
 static void ContinueMoving_MM(int, int);
 static void Moving2Blocked_MM(int, int, int *, int *);
 
+static void AddLaserEdge(int, int);
+static void ScanLaser(void);
+static void DrawLaser(int, int);
+static boolean HitElement(int, int);
+static boolean HitOnlyAnEdge(int);
+static boolean HitPolarizer(int, int);
+static boolean HitBlock(int, int);
+static boolean HitLaserSource(int, int);
+static boolean HitLaserDestination(int, int);
+static boolean HitReflectingWalls(int, int);
+static boolean HitAbsorbingWalls(int, int);
+static void RotateMirror(int, int, int);
+static boolean ObjHit(int, int, int);
+static void DeletePacMan(int, int);
+static void MovePacMen(void);
+
 // bitmap for laser beam detection
 static Bitmap *laser_bitmap = NULL;
 
@@ -805,7 +821,7 @@ static void GameOver_MM(int game_over_cause)
   SetTileCursorActive(FALSE);
 }
 
-void AddLaserEdge(int lx, int ly)
+static void AddLaserEdge(int lx, int ly)
 {
   int clx = dSX + lx;
   int cly = dSY + ly;
@@ -824,7 +840,7 @@ void AddLaserEdge(int lx, int ly)
   laser.redraw = TRUE;
 }
 
-void AddDamagedField(int ex, int ey)
+static void AddDamagedField(int ex, int ey)
 {
   // prevent adding the same field position again
   if (laser.num_damages > 0 &&
@@ -969,7 +985,7 @@ static void DeactivateLaserTargetElement(void)
   }
 }
 
-void ScanLaser(void)
+static void ScanLaser(void)
 {
   int element = EL_EMPTY;
   int last_element = EL_EMPTY;
@@ -1485,7 +1501,7 @@ void DrawLaser_MM(void)
   DrawLaser(0, game_mm.laser_enabled);
 }
 
-boolean HitElement(int element, int hit_mask)
+static boolean HitElement(int element, int hit_mask)
 {
   if (HitOnlyAnEdge(hit_mask))
     return FALSE;
@@ -1675,6 +1691,8 @@ boolean HitElement(int element, int hit_mask)
                      element == EL_MINE ? EL_MINE_ACTIVE :
                      EL_GRAY_BALL_ACTIVE);
 
+    GfxFrame[ELX][ELY] = 0;            // restart animation
+
     laser.dest_element_last = Tile[ELX][ELY];
     laser.dest_element_last_x = ELX;
     laser.dest_element_last_y = ELY;
@@ -1833,7 +1851,7 @@ boolean HitElement(int element, int hit_mask)
   return TRUE;
 }
 
-boolean HitOnlyAnEdge(int hit_mask)
+static boolean HitOnlyAnEdge(int hit_mask)
 {
   // check if the laser hit only the edge of an element and, if so, go on
 
@@ -1890,7 +1908,7 @@ boolean HitOnlyAnEdge(int hit_mask)
   return FALSE;
 }
 
-boolean HitPolarizer(int element, int hit_mask)
+static boolean HitPolarizer(int element, int hit_mask)
 {
   if (HitOnlyAnEdge(hit_mask))
     return FALSE;
@@ -1967,7 +1985,7 @@ boolean HitPolarizer(int element, int hit_mask)
   return TRUE;
 }
 
-boolean HitBlock(int element, int hit_mask)
+static boolean HitBlock(int element, int hit_mask)
 {
   boolean check = FALSE;
 
@@ -2088,7 +2106,7 @@ boolean HitBlock(int element, int hit_mask)
   return TRUE;
 }
 
-boolean HitLaserSource(int element, int hit_mask)
+static boolean HitLaserSource(int element, int hit_mask)
 {
   if (HitOnlyAnEdge(hit_mask))
     return FALSE;
@@ -2100,7 +2118,7 @@ boolean HitLaserSource(int element, int hit_mask)
   return TRUE;
 }
 
-boolean HitLaserDestination(int element, int hit_mask)
+static boolean HitLaserDestination(int element, int hit_mask)
 {
   if (HitOnlyAnEdge(hit_mask))
     return FALSE;
@@ -2146,7 +2164,7 @@ boolean HitLaserDestination(int element, int hit_mask)
   return TRUE;
 }
 
-boolean HitReflectingWalls(int element, int hit_mask)
+static boolean HitReflectingWalls(int element, int hit_mask)
 {
   // check if laser hits side of a wall with an angle that is not 90°
   if (!IS_90_ANGLE(laser.current_angle) && (hit_mask == HIT_MASK_TOP ||
@@ -2348,7 +2366,7 @@ boolean HitReflectingWalls(int element, int hit_mask)
   return FALSE;
 }
 
-boolean HitAbsorbingWalls(int element, int hit_mask)
+static boolean HitAbsorbingWalls(int element, int hit_mask)
 {
   if (HitOnlyAnEdge(hit_mask))
     return FALSE;
@@ -2442,7 +2460,7 @@ boolean HitAbsorbingWalls(int element, int hit_mask)
     if (IS_90_ANGLE(laser.current_angle))
       mask += mask * (2 + IS_HORIZ_ANGLE(laser.current_angle) * 2);
 
-    laser.dest_element = element2 | EL_WALL_AMOEBA;
+    laser.dest_element = element2 | EL_WALL_AMOEBA_BASE;
 
     laser.wall_mask = mask;
   }
@@ -2589,7 +2607,7 @@ static void MeltIce(int x, int y)
   {
     int phase;
     int wall_mask = Store2[x][y];
-    int real_element = Tile[x][y] - EL_WALL_CHANGING + EL_WALL_ICE;
+    int real_element = Tile[x][y] - EL_WALL_CHANGING_BASE + EL_WALL_ICE_BASE;
 
     MovDelay[x][y]--;
     phase = frames - MovDelay[x][y] / delay - 1;
@@ -2601,7 +2619,7 @@ static void MeltIce(int x, int y)
 
       DrawWalls_MM(x, y, Tile[x][y]);
 
-      if (Tile[x][y] == EL_WALL_ICE)
+      if (Tile[x][y] == EL_WALL_ICE_BASE)
        Tile[x][y] = EL_EMPTY;
 
       ScanLaser_FromLastMirror();
@@ -2627,7 +2645,7 @@ static void GrowAmoeba(int x, int y)
   {
     int phase;
     int wall_mask = Store2[x][y];
-    int real_element = Tile[x][y] - EL_WALL_CHANGING + EL_WALL_AMOEBA;
+    int real_element = Tile[x][y] - EL_WALL_CHANGING_BASE + EL_WALL_AMOEBA_BASE;
 
     MovDelay[x][y]--;
     phase = MovDelay[x][y] / delay;
@@ -2692,12 +2710,13 @@ static void Explode_MM(int x, int y, int phase, int mode)
   int num_phase = 9, delay = 2;
   int last_phase = num_phase * delay;
   int half_phase = (num_phase / 2) * delay;
+  int center_element;
 
   laser.redraw = TRUE;
 
   if (phase == EX_PHASE_START)         // initialize 'Store[][]' field
   {
-    int center_element = Tile[x][y];
+    center_element = Tile[x][y];
 
     if (IS_MOVING(x, y) || IS_BLOCKED(x, y))
     {
@@ -2708,8 +2727,8 @@ static void Explode_MM(int x, int y, int phase, int mode)
       Tile[x][y] = center_element;
     }
 
-    Store[x][y] = center_element;
-    Store2[x][y] = mode;
+    Store[x][y] = EL_EMPTY;
+    Store2[x][y] = center_element;
 
     Tile[x][y] = EL_EXPLODING_OPAQUE;
 
@@ -2729,7 +2748,9 @@ static void Explode_MM(int x, int y, int phase, int mode)
 
   ExplodePhase[x][y] = (phase < last_phase ? phase + 1 : 0);
 
-  if (phase == half_phase)
+  center_element = Store2[x][y];
+
+  if (phase == half_phase && Store[x][y] == EL_EMPTY)
   {
     Tile[x][y] = EL_EXPLODING_TRANSP;
 
@@ -2739,7 +2760,7 @@ static void Explode_MM(int x, int y, int phase, int mode)
 
   if (phase == last_phase)
   {
-    if (Store[x][y] == EL_BOMB_ACTIVE)
+    if (center_element == EL_BOMB_ACTIVE)
     {
       DrawLaser(0, DL_LASER_DISABLED);
       InitLaser();
@@ -2750,12 +2771,12 @@ static void Explode_MM(int x, int y, int phase, int mode)
 
       laser.overloaded = FALSE;
     }
-    else if (IS_MCDUFFIN(Store[x][y]))
+    else if (IS_MCDUFFIN(center_element))
     {
       GameOver_MM(GAME_OVER_BOMB);
     }
 
-    Tile[x][y] = EL_EMPTY;
+    Tile[x][y] = Store[x][y];
 
     Store[x][y] = Store2[x][y] = 0;
     MovDir[x][y] = MovPos[x][y] = MovDelay[x][y] = 0;
@@ -2790,7 +2811,7 @@ static void Bang_MM(int x, int y)
   Explode_MM(x, y, EX_PHASE_START, EX_TYPE_NORMAL);
 }
 
-void TurnRound(int x, int y)
+static void TurnRound(int x, int y)
 {
   static struct
   {
@@ -3073,7 +3094,7 @@ boolean ClickElement(int x, int y, int button)
   return element_clicked;
 }
 
-void RotateMirror(int x, int y, int button)
+static void RotateMirror(int x, int y, int button)
 {
   if (button == MB_RELEASED)
   {
@@ -3195,7 +3216,7 @@ static void AutoRotateMirrors(void)
   }
 }
 
-boolean ObjHit(int obx, int oby, int bits)
+static boolean ObjHit(int obx, int oby, int bits)
 {
   int i;
 
@@ -3228,7 +3249,7 @@ boolean ObjHit(int obx, int oby, int bits)
   return FALSE;
 }
 
-void DeletePacMan(int px, int py)
+static void DeletePacMan(int px, int py)
 {
   int i, j;
 
@@ -3280,9 +3301,9 @@ static void GameActions_MM_Ext(void)
       OpenGrayBall(x, y);
     else if (IS_ENVELOPE_OPENING(element))
       OpenEnvelope(x, y);
-    else if (IS_WALL_CHANGING(element) && Store[x][y] == EL_WALL_ICE)
+    else if (IS_WALL_CHANGING(element) && Store[x][y] == EL_WALL_ICE_BASE)
       MeltIce(x, y);
-    else if (IS_WALL_CHANGING(element) && Store[x][y] == EL_WALL_AMOEBA)
+    else if (IS_WALL_CHANGING(element) && Store[x][y] == EL_WALL_AMOEBA_BASE)
       GrowAmoeba(x, y);
     else if (IS_MIRROR(element) ||
             IS_MIRROR_FIXED(element) ||
@@ -3458,12 +3479,12 @@ static void GameActions_MM_Ext(void)
       game_mm.ball_choice_pos++;
 
       int new_element = native_mm_level.ball_content[element_pos];
-      int new_element_unmapped = unmap_element(new_element);
+      int new_element_base = map_wall_to_base_element(new_element);
 
-      if (IS_WALL(new_element_unmapped))
+      if (IS_WALL(new_element_base))
       {
        // always use completely filled wall element
-       new_element = new_element_unmapped | 0x000f;
+       new_element = new_element_base | 0x000f;
       }
       else if (native_mm_level.rotate_ball_content &&
               get_num_elements(new_element) > 1)
@@ -3487,8 +3508,8 @@ static void GameActions_MM_Ext(void)
   {
     PlayLevelSound_MM(ELX, ELY, element, MM_ACTION_SHRINKING);
 
-    Tile[ELX][ELY] = Tile[ELX][ELY] - EL_WALL_ICE + EL_WALL_CHANGING;
-    Store[ELX][ELY] = EL_WALL_ICE;
+    Tile[ELX][ELY] = Tile[ELX][ELY] - EL_WALL_ICE_BASE + EL_WALL_CHANGING_BASE;
+    Store[ELX][ELY] = EL_WALL_ICE_BASE;
     Store2[ELX][ELY] = laser.wall_mask;
 
     laser.dest_element = Tile[ELX][ELY];
@@ -3577,8 +3598,8 @@ static void GameActions_MM_Ext(void)
 
     PlayLevelSound_MM(x, y, element, MM_ACTION_GROWING);
 
-    Tile[x][y] = Tile[x][y] - EL_WALL_AMOEBA + EL_WALL_CHANGING;
-    Store[x][y] = EL_WALL_AMOEBA;
+    Tile[x][y] = Tile[x][y] - EL_WALL_AMOEBA_BASE + EL_WALL_CHANGING_BASE;
+    Store[x][y] = EL_WALL_AMOEBA_BASE;
     Store2[x][y] = wall_mask;
 
     return;
@@ -3683,7 +3704,7 @@ void GameActions_MM(struct MouseActionInfo action)
   CheckSingleStepMode_MM(element_clicked, button_released);
 }
 
-void MovePacMen(void)
+static void MovePacMen(void)
 {
   int mx, my, ox, oy, nx, ny;
   int element;