fixed bug causing access to negative array index
[rocksndiamonds.git] / src / editor.c
index c6d85e3139926a01dfb3510757639d7af277193a..093b229083d6f4e3539ebfd28ccd0559718e21c2 100644 (file)
@@ -9752,10 +9752,43 @@ static void SetAutomaticNumberOfGemsNeeded(void)
     {
       int element = Feld[x][y];
 
-      if (IS_GEM(element) ||
-         element == EL_MM_KETTLE ||
-         element == EL_DF_CELL)
-       level.gems_needed++;
+      switch (element)
+      {
+       case EL_EMERALD:
+       case EL_EMERALD_YELLOW:
+       case EL_EMERALD_RED:
+       case EL_EMERALD_PURPLE:
+       case EL_BD_DIAMOND:
+       case EL_WALL_EMERALD:
+       case EL_WALL_EMERALD_YELLOW:
+       case EL_WALL_EMERALD_RED:
+       case EL_WALL_EMERALD_PURPLE:
+       case EL_WALL_BD_DIAMOND:
+       case EL_NUT:
+       case EL_SP_INFOTRON:
+       case EL_MM_KETTLE:
+       case EL_DF_CELL:
+         level.gems_needed++;
+         break;
+
+       case EL_DIAMOND:
+       case EL_WALL_DIAMOND:
+         level.gems_needed += 3;
+         break;
+
+       case EL_PEARL:
+       case EL_WALL_PEARL:
+         level.gems_needed += 5;
+         break;
+
+       case EL_CRYSTAL:
+       case EL_WALL_CRYSTAL:
+         level.gems_needed += 8;
+         break;
+
+       default:
+         break;
+      }
     }
   }
 
@@ -10843,7 +10876,6 @@ static void SetElementIntelliDraw(int x, int y, int new_element,
   };
   static int last_x = -1;
   static int last_y = -1;
-  int old_element = IntelliDrawBuffer[x][y];
 
   if (new_element == EL_UNDEFINED)
   {
@@ -10853,6 +10885,8 @@ static void SetElementIntelliDraw(int x, int y, int new_element,
     return;
   }
 
+  int old_element = IntelliDrawBuffer[x][y];
+
   if (IS_TUBE(new_element))
   {
     int last_element_new = EL_UNDEFINED;
@@ -11627,11 +11661,21 @@ static void ResetIntelliDraw(void)
 
 static boolean draw_mode_hires = FALSE;
 
+static boolean isHiresTileElement(int element)
+{
+  return (IS_MM_WALL(element)        || element == EL_EMPTY);
+}
+
+static boolean isHiresDrawElement(int element)
+{
+  return (IS_MM_WALL_EDITOR(element) || element == EL_EMPTY);
+}
+
 static void SetDrawModeHiRes(int element)
 {
   draw_mode_hires =
     (level.game_engine_type == GAME_ENGINE_TYPE_MM &&
-     (IS_MM_WALL_EDITOR(element) || element == EL_EMPTY));
+     isHiresDrawElement(element));
 }
 
 static boolean getDrawModeHiRes(void)
@@ -12672,9 +12716,13 @@ static void HandleDrawingAreas(struct GadgetInfo *gi)
   }
   else if (!button_press_event)
   {
+    int old_element = (IN_LEV_FIELD(lx, ly) ? Feld[lx][ly] : EL_UNDEFINED);
+    boolean hires_drawing = (level.game_engine_type == GAME_ENGINE_TYPE_MM &&
+                            isHiresTileElement(old_element) &&
+                            isHiresDrawElement(new_element));
+
     // prevent handling events for every pixel position when moving mouse
-    if ((sx == last_sx && sy == last_sy &&
-        !IS_MM_WALL_EDITOR(new_element) && new_element != EL_EMPTY) ||
+    if ((sx == last_sx && sy == last_sy && !hires_drawing) ||
        (sx2 == last_sx2 && sy2 == last_sy2))
       return;
   }
@@ -12744,13 +12792,37 @@ static void HandleDrawingAreas(struct GadgetInfo *gi)
        {
          SetDrawModeHiRes(new_element);
 
-         if (new_element == EL_PLAYER_1)
+         if (ELEM_IS_PLAYER(new_element))
          {
            // remove player at old position
            for (y = 0; y < lev_fieldy; y++)
+           {
              for (x = 0; x < lev_fieldx; x++)
-               if (Feld[x][y] == EL_PLAYER_1)
-                 SetElement(x, y, EL_EMPTY);
+             {
+               int old_element = Feld[x][y];
+
+               if (ELEM_IS_PLAYER(old_element))
+               {
+                 int replaced_with_element =
+                   (old_element == EL_SOKOBAN_FIELD_PLAYER &&
+                    new_element == EL_PLAYER_1 ? EL_SOKOBAN_FIELD_EMPTY :
+
+                    old_element == EL_SOKOBAN_FIELD_PLAYER &&
+                    new_element == old_element ? EL_SOKOBAN_FIELD_EMPTY :
+
+                    new_element == EL_SOKOBAN_FIELD_PLAYER &&
+                    old_element == EL_PLAYER_1 ? EL_EMPTY :
+
+                    new_element >= EL_PLAYER_1 &&
+                    new_element <= EL_PLAYER_4 &&
+                    new_element == old_element ? EL_EMPTY :
+
+                    old_element);
+
+                 SetElement(x, y, replaced_with_element);
+               }
+             }
+           }
          }
 
          SetElementButton(lx, ly, dx, dy, new_element, button);