added optional button to restart game (door, panel and touch variants)
[rocksndiamonds.git] / src / game_mm / mm_game.c
index 51ebf314c08f2f31aaa21ba2d72bd8f592b6d881..b258e374b7f0bbeb868be9b873e831e331394af0 100644 (file)
@@ -1692,6 +1692,9 @@ static boolean HitElement(int element, int hit_mask)
     // check if laser scan has crossed element boundaries (not just mini tiles)
     boolean cross_x = (getLevelFromLaserX(LX) != getLevelFromLaserX(LX + 2));
     boolean cross_y = (getLevelFromLaserY(LY) != getLevelFromLaserY(LY + 2));
+    int element_angle = get_element_angle(element);
+    int mirrored_angle = get_mirrored_angle(laser.current_angle, element_angle);
+    int opposite_angle = get_opposite_angle(laser.current_angle);
 
     // check if wall (horizontal or vertical) side of slope was hit
     if (hit_mask == HIT_MASK_LEFT ||
@@ -1699,7 +1702,26 @@ static boolean HitElement(int element, int hit_mask)
        hit_mask == HIT_MASK_TOP ||
        hit_mask == HIT_MASK_BOTTOM)
     {
-      return HitReflectingWalls(element, hit_mask);
+      boolean hit_slope_corner_in_laser_direction =
+       ((hit_mask == HIT_MASK_LEFT   && (element == EL_DF_SLOPE_01 ||
+                                         element == EL_DF_SLOPE_02)) ||
+        (hit_mask == HIT_MASK_RIGHT  && (element == EL_DF_SLOPE_00 ||
+                                         element == EL_DF_SLOPE_03)) ||
+        (hit_mask == HIT_MASK_TOP    && (element == EL_DF_SLOPE_02 ||
+                                         element == EL_DF_SLOPE_03)) ||
+        (hit_mask == HIT_MASK_BOTTOM && (element == EL_DF_SLOPE_00 ||
+                                         element == EL_DF_SLOPE_01)));
+
+      boolean hit_slope_corner_in_laser_direction_double_checked =
+       (cross_x && cross_y &&
+        laser.current_angle == mirrored_angle &&
+        hit_slope_corner_in_laser_direction);
+
+      // check special case of laser hitting the corner of a slope and another
+      // element (either wall or another slope), following the diagonal side
+      // of the slope which has the same angle as the direction of the laser
+      if (!hit_slope_corner_in_laser_direction_double_checked)
+       return HitReflectingWalls(element, hit_mask);
     }
 
     // check if an edge was hit while crossing element borders
@@ -1722,10 +1744,6 @@ static boolean HitElement(int element, int hit_mask)
       }
     }
 
-    int mirrored_angle = get_mirrored_angle(laser.current_angle,
-                                           get_element_angle(element));
-    int opposite_angle = get_opposite_angle(laser.current_angle);
-
     // check if laser is reflected by slope by 180°
     if (mirrored_angle == opposite_angle)
     {
@@ -1956,8 +1974,8 @@ static boolean HitElement(int element, int hit_mask)
       {
        int elx, ely;
 
-       elx = getLevelFromLaserX(LX);
-       ely = getLevelFromLaserY(LY);
+       elx = getLevelFromLaserX(LX + XS);
+       ely = getLevelFromLaserY(LY + YS);
 
        if (IN_LEV_FIELD(elx, ely))
        {
@@ -1970,8 +1988,8 @@ static boolean HitElement(int element, int hit_mask)
 
        int nr = element - EL_DF_SLOPE_START;
        int dx = (nr == 0 ? (XS > 0 ? TILEX - 1 : -1) :
-                 nr == 1 ? (XS > 0 ? TILEX     :  1) :
-                 nr == 2 ? (XS > 0 ? TILEX     :  1) :
+                 nr == 1 ? (XS > 0 ? TILEX     :  0) :
+                 nr == 2 ? (XS > 0 ? TILEX     :  0) :
                  nr == 3 ? (XS > 0 ? TILEX - 1 : -1) : 0);
        int dy = (nr == 0 ? (YS > 0 ? TILEY - 1 : -1) :
                  nr == 1 ? (YS > 0 ? TILEY - 1 : -1) :