added using setup option for displaying overlay touch buttons
[rocksndiamonds.git] / src / game.c
index 0c8184698768b0831f1c2b7dc6b8cacd25b59cad..abf350ce93311d668bc344cc1301affb90fa0a1e 100644 (file)
@@ -1837,15 +1837,15 @@ static void InitField(int x, int y, boolean init_game)
       break;
 
     case EL_STONEBLOCK:
-      if (x < lev_fieldx-1 && Tile[x+1][y] == EL_ACID)
+      if (x < lev_fieldx - 1 && Tile[x + 1][y] == EL_ACID)
        Tile[x][y] = EL_ACID_POOL_TOPLEFT;
-      else if (x > 0 && Tile[x-1][y] == EL_ACID)
+      else if (x > 0 && Tile[x - 1][y] == EL_ACID)
        Tile[x][y] = EL_ACID_POOL_TOPRIGHT;
-      else if (y > 0 && Tile[x][y-1] == EL_ACID_POOL_TOPLEFT)
+      else if (y > 0 && Tile[x][y - 1] == EL_ACID_POOL_TOPLEFT)
        Tile[x][y] = EL_ACID_POOL_BOTTOMLEFT;
-      else if (y > 0 && Tile[x][y-1] == EL_ACID)
+      else if (y > 0 && Tile[x][y - 1] == EL_ACID)
        Tile[x][y] = EL_ACID_POOL_BOTTOM;
-      else if (y > 0 && Tile[x][y-1] == EL_ACID_POOL_TOPRIGHT)
+      else if (y > 0 && Tile[x][y - 1] == EL_ACID_POOL_TOPRIGHT)
        Tile[x][y] = EL_ACID_POOL_BOTTOMRIGHT;
       break;
 
@@ -4997,7 +4997,7 @@ void GameEnd(void)
 
   game.LevelSolved_GameEnd = TRUE;
 
-  if (game.LevelSolved_SaveTape)
+  if (game.LevelSolved_SaveTape && !score_info_tape_play)
   {
     // make sure that request dialog to save tape does not open door again
     if (!global.use_envelope_request)
@@ -5013,7 +5013,7 @@ void GameEnd(void)
   // if no tape is to be saved, close both doors simultaneously
   CloseDoor(DOOR_CLOSE_ALL);
 
-  if (level_editor_test_game)
+  if (level_editor_test_game || score_info_tape_play)
   {
     SetGameStatus(GAME_MODE_MAIN);
 
@@ -5050,6 +5050,9 @@ void GameEnd(void)
 
     if (setup.auto_play_next_level)
     {
+      scores.continue_playing = TRUE;
+      scores.next_level_nr = level_nr;
+
       LoadLevel(level_nr);
 
       SaveLevelSetup_SeriesInfo();
@@ -5062,9 +5065,7 @@ void GameEnd(void)
 
     DrawHallOfFame(last_level_nr);
   }
-  else if (setup.auto_play_next_level && setup.increment_levels &&
-          last_level_nr < leveldir_current->last_level &&
-          !network_playing)
+  else if (scores.continue_playing)
   {
     StartGameActions(network.enabled, setup.autorecord, level.random_seed);
   }
@@ -5151,7 +5152,8 @@ static int addScoreEntry(struct ScoreInfo *list, struct ScoreEntry *new_entry,
     }
   }
 
-  return -1;
+  // special case: new score is beyond the last high score list position
+  return MAX_SCORE_ENTRIES;
 }
 
 void NewHighScore(int level_nr, boolean tape_saved)
@@ -5169,6 +5171,19 @@ void NewHighScore(int level_nr, boolean tape_saved)
 
   scores.last_added = addScoreEntry(&scores, &new_entry, one_per_name);
 
+  if (scores.last_added >= MAX_SCORE_ENTRIES)
+  {
+    scores.last_added = MAX_SCORE_ENTRIES - 1;
+    scores.force_last_added = TRUE;
+
+    scores.entry[scores.last_added] = new_entry;
+
+    // store last added local score entry (before merging server scores)
+    scores.last_added_local = scores.last_added;
+
+    return;
+  }
+
   if (scores.last_added < 0)
     return;
 
@@ -6080,11 +6095,11 @@ static void Explode(int ex, int ey, int phase, int mode)
     }
     else if (IS_WALKABLE_UNDER(Back[x][y]))
     {
-      DrawScreenGraphic(SCREENX(x), SCREENY(y), graphic, frame);
+      DrawLevelGraphic(x, y, graphic, frame);
       DrawLevelElementThruMask(x, y, Back[x][y]);
     }
     else if (!IS_WALKABLE_INSIDE(Back[x][y]))
-      DrawScreenGraphic(SCREENX(x), SCREENY(y), graphic, frame);
+      DrawLevelGraphic(x, y, graphic, frame);
   }
 }
 
@@ -9145,7 +9160,7 @@ static void AmoebaGrowing(int x, int y)
       int frame = getGraphicAnimationFrame(IMG_AMOEBA_GROWING,
                                           6 - MovDelay[x][y]);
 
-      DrawScreenGraphic(SCREENX(x), SCREENY(y), IMG_AMOEBA_GROWING, frame);
+      DrawLevelGraphic(x, y, IMG_AMOEBA_GROWING, frame);
     }
 
     if (!MovDelay[x][y])
@@ -9178,7 +9193,7 @@ static void AmoebaShrinking(int x, int y)
       int frame = getGraphicAnimationFrame(IMG_AMOEBA_SHRINKING,
                                           6 - MovDelay[x][y]);
 
-      DrawScreenGraphic(SCREENX(x), SCREENY(y), IMG_AMOEBA_SHRINKING, frame);
+      DrawLevelGraphic(x, y, IMG_AMOEBA_SHRINKING, frame);
     }
 
     if (!MovDelay[x][y])
@@ -9432,7 +9447,7 @@ static void Life(int ax, int ay)
          num_neighbours <= life_parameter[3])
       {
        Tile[xx][yy] = element;
-       MovDelay[xx][yy] = (element == EL_GAME_OF_LIFE ? 0 : life_time-1);
+       MovDelay[xx][yy] = (element == EL_GAME_OF_LIFE ? 0 : life_time - 1);
        if (Tile[xx][yy] != old_element)
          TEST_DrawLevelField(xx, yy);
        Stop[xx][yy] = TRUE;
@@ -9696,7 +9711,7 @@ static void MauerWaechst(int x, int y)
       int graphic = el_dir2img(Tile[x][y], GfxDir[x][y]);
       int frame = getGraphicAnimationFrame(graphic, 17 - MovDelay[x][y]);
 
-      DrawScreenGraphic(SCREENX(x), SCREENY(y), graphic, frame);
+      DrawLevelGraphic(x, y, graphic, frame);
     }
 
     if (!MovDelay[x][y])
@@ -9753,13 +9768,13 @@ static void MauerAbleger(int ax, int ay)
       return;
   }
 
-  if (IN_LEV_FIELD(ax, ay-1) && IS_FREE(ax, ay-1))
+  if (IN_LEV_FIELD(ax, ay - 1) && IS_FREE(ax, ay - 1))
     oben_frei = TRUE;
-  if (IN_LEV_FIELD(ax, ay+1) && IS_FREE(ax, ay+1))
+  if (IN_LEV_FIELD(ax, ay + 1) && IS_FREE(ax, ay + 1))
     unten_frei = TRUE;
-  if (IN_LEV_FIELD(ax-1, ay) && IS_FREE(ax-1, ay))
+  if (IN_LEV_FIELD(ax - 1, ay) && IS_FREE(ax - 1, ay))
     links_frei = TRUE;
-  if (IN_LEV_FIELD(ax+1, ay) && IS_FREE(ax+1, ay))
+  if (IN_LEV_FIELD(ax + 1, ay) && IS_FREE(ax + 1, ay))
     rechts_frei = TRUE;
 
   if (element == EL_EXPANDABLE_WALL_VERTICAL ||
@@ -9767,22 +9782,20 @@ static void MauerAbleger(int ax, int ay)
   {
     if (oben_frei)
     {
-      Tile[ax][ay-1] = EL_EXPANDABLE_WALL_GROWING;
-      Store[ax][ay-1] = element;
-      GfxDir[ax][ay-1] = MovDir[ax][ay-1] = MV_UP;
-      if (IN_SCR_FIELD(SCREENX(ax), SCREENY(ay-1)))
-       DrawScreenGraphic(SCREENX(ax), SCREENY(ay - 1),
-                          IMG_EXPANDABLE_WALL_GROWING_UP, 0);
+      Tile[ax][ay - 1] = EL_EXPANDABLE_WALL_GROWING;
+      Store[ax][ay - 1] = element;
+      GfxDir[ax][ay - 1] = MovDir[ax][ay - 1] = MV_UP;
+      if (IN_SCR_FIELD(SCREENX(ax), SCREENY(ay - 1)))
+       DrawLevelGraphic(ax, ay - 1, IMG_EXPANDABLE_WALL_GROWING_UP, 0);
       new_wall = TRUE;
     }
     if (unten_frei)
     {
-      Tile[ax][ay+1] = EL_EXPANDABLE_WALL_GROWING;
-      Store[ax][ay+1] = element;
-      GfxDir[ax][ay+1] = MovDir[ax][ay+1] = MV_DOWN;
-      if (IN_SCR_FIELD(SCREENX(ax), SCREENY(ay+1)))
-       DrawScreenGraphic(SCREENX(ax), SCREENY(ay + 1),
-                          IMG_EXPANDABLE_WALL_GROWING_DOWN, 0);
+      Tile[ax][ay + 1] = EL_EXPANDABLE_WALL_GROWING;
+      Store[ax][ay + 1] = element;
+      GfxDir[ax][ay + 1] = MovDir[ax][ay + 1] = MV_DOWN;
+      if (IN_SCR_FIELD(SCREENX(ax), SCREENY(ay + 1)))
+       DrawLevelGraphic(ax, ay + 1, IMG_EXPANDABLE_WALL_GROWING_DOWN, 0);
       new_wall = TRUE;
     }
   }
@@ -9794,23 +9807,21 @@ static void MauerAbleger(int ax, int ay)
   {
     if (links_frei)
     {
-      Tile[ax-1][ay] = EL_EXPANDABLE_WALL_GROWING;
-      Store[ax-1][ay] = element;
-      GfxDir[ax-1][ay] = MovDir[ax-1][ay] = MV_LEFT;
-      if (IN_SCR_FIELD(SCREENX(ax-1), SCREENY(ay)))
-       DrawScreenGraphic(SCREENX(ax - 1), SCREENY(ay),
-                          IMG_EXPANDABLE_WALL_GROWING_LEFT, 0);
+      Tile[ax - 1][ay] = EL_EXPANDABLE_WALL_GROWING;
+      Store[ax - 1][ay] = element;
+      GfxDir[ax - 1][ay] = MovDir[ax - 1][ay] = MV_LEFT;
+      if (IN_SCR_FIELD(SCREENX(ax - 1), SCREENY(ay)))
+       DrawLevelGraphic(ax - 1, ay, IMG_EXPANDABLE_WALL_GROWING_LEFT, 0);
       new_wall = TRUE;
     }
 
     if (rechts_frei)
     {
-      Tile[ax+1][ay] = EL_EXPANDABLE_WALL_GROWING;
-      Store[ax+1][ay] = element;
-      GfxDir[ax+1][ay] = MovDir[ax+1][ay] = MV_RIGHT;
-      if (IN_SCR_FIELD(SCREENX(ax+1), SCREENY(ay)))
-       DrawScreenGraphic(SCREENX(ax + 1), SCREENY(ay),
-                          IMG_EXPANDABLE_WALL_GROWING_RIGHT, 0);
+      Tile[ax + 1][ay] = EL_EXPANDABLE_WALL_GROWING;
+      Store[ax + 1][ay] = element;
+      GfxDir[ax + 1][ay] = MovDir[ax + 1][ay] = MV_RIGHT;
+      if (IN_SCR_FIELD(SCREENX(ax + 1), SCREENY(ay)))
+       DrawLevelGraphic(ax + 1, ay, IMG_EXPANDABLE_WALL_GROWING_RIGHT, 0);
       new_wall = TRUE;
     }
   }
@@ -9818,13 +9829,13 @@ static void MauerAbleger(int ax, int ay)
   if (element == EL_EXPANDABLE_WALL && (links_frei || rechts_frei))
     TEST_DrawLevelField(ax, ay);
 
-  if (!IN_LEV_FIELD(ax, ay-1) || IS_WALL(Tile[ax][ay-1]))
+  if (!IN_LEV_FIELD(ax, ay - 1) || IS_WALL(Tile[ax][ay - 1]))
     oben_massiv = TRUE;
-  if (!IN_LEV_FIELD(ax, ay+1) || IS_WALL(Tile[ax][ay+1]))
+  if (!IN_LEV_FIELD(ax, ay + 1) || IS_WALL(Tile[ax][ay + 1]))
     unten_massiv = TRUE;
-  if (!IN_LEV_FIELD(ax-1, ay) || IS_WALL(Tile[ax-1][ay]))
+  if (!IN_LEV_FIELD(ax - 1, ay) || IS_WALL(Tile[ax - 1][ay]))
     links_massiv = TRUE;
-  if (!IN_LEV_FIELD(ax+1, ay) || IS_WALL(Tile[ax+1][ay]))
+  if (!IN_LEV_FIELD(ax + 1, ay) || IS_WALL(Tile[ax + 1][ay]))
     rechts_massiv = TRUE;
 
   if (((oben_massiv && unten_massiv) ||
@@ -9861,13 +9872,13 @@ static void MauerAblegerStahl(int ax, int ay)
       return;
   }
 
-  if (IN_LEV_FIELD(ax, ay-1) && IS_FREE(ax, ay-1))
+  if (IN_LEV_FIELD(ax, ay - 1) && IS_FREE(ax, ay - 1))
     oben_frei = TRUE;
-  if (IN_LEV_FIELD(ax, ay+1) && IS_FREE(ax, ay+1))
+  if (IN_LEV_FIELD(ax, ay + 1) && IS_FREE(ax, ay + 1))
     unten_frei = TRUE;
-  if (IN_LEV_FIELD(ax-1, ay) && IS_FREE(ax-1, ay))
+  if (IN_LEV_FIELD(ax - 1, ay) && IS_FREE(ax - 1, ay))
     links_frei = TRUE;
-  if (IN_LEV_FIELD(ax+1, ay) && IS_FREE(ax+1, ay))
+  if (IN_LEV_FIELD(ax + 1, ay) && IS_FREE(ax + 1, ay))
     rechts_frei = TRUE;
 
   if (element == EL_EXPANDABLE_STEELWALL_VERTICAL ||
@@ -9875,22 +9886,20 @@ static void MauerAblegerStahl(int ax, int ay)
   {
     if (oben_frei)
     {
-      Tile[ax][ay-1] = EL_EXPANDABLE_STEELWALL_GROWING;
-      Store[ax][ay-1] = element;
-      GfxDir[ax][ay-1] = MovDir[ax][ay-1] = MV_UP;
-      if (IN_SCR_FIELD(SCREENX(ax), SCREENY(ay-1)))
-       DrawScreenGraphic(SCREENX(ax), SCREENY(ay - 1),
-                          IMG_EXPANDABLE_STEELWALL_GROWING_UP, 0);
+      Tile[ax][ay - 1] = EL_EXPANDABLE_STEELWALL_GROWING;
+      Store[ax][ay - 1] = element;
+      GfxDir[ax][ay - 1] = MovDir[ax][ay - 1] = MV_UP;
+      if (IN_SCR_FIELD(SCREENX(ax), SCREENY(ay - 1)))
+       DrawLevelGraphic(ax, ay - 1, IMG_EXPANDABLE_STEELWALL_GROWING_UP, 0);
       new_wall = TRUE;
     }
     if (unten_frei)
     {
-      Tile[ax][ay+1] = EL_EXPANDABLE_STEELWALL_GROWING;
-      Store[ax][ay+1] = element;
-      GfxDir[ax][ay+1] = MovDir[ax][ay+1] = MV_DOWN;
-      if (IN_SCR_FIELD(SCREENX(ax), SCREENY(ay+1)))
-       DrawScreenGraphic(SCREENX(ax), SCREENY(ay + 1),
-                          IMG_EXPANDABLE_STEELWALL_GROWING_DOWN, 0);
+      Tile[ax][ay + 1] = EL_EXPANDABLE_STEELWALL_GROWING;
+      Store[ax][ay + 1] = element;
+      GfxDir[ax][ay + 1] = MovDir[ax][ay + 1] = MV_DOWN;
+      if (IN_SCR_FIELD(SCREENX(ax), SCREENY(ay + 1)))
+       DrawLevelGraphic(ax, ay + 1, IMG_EXPANDABLE_STEELWALL_GROWING_DOWN, 0);
       new_wall = TRUE;
     }
   }
@@ -9900,34 +9909,32 @@ static void MauerAblegerStahl(int ax, int ay)
   {
     if (links_frei)
     {
-      Tile[ax-1][ay] = EL_EXPANDABLE_STEELWALL_GROWING;
-      Store[ax-1][ay] = element;
-      GfxDir[ax-1][ay] = MovDir[ax-1][ay] = MV_LEFT;
-      if (IN_SCR_FIELD(SCREENX(ax-1), SCREENY(ay)))
-       DrawScreenGraphic(SCREENX(ax - 1), SCREENY(ay),
-                          IMG_EXPANDABLE_STEELWALL_GROWING_LEFT, 0);
+      Tile[ax - 1][ay] = EL_EXPANDABLE_STEELWALL_GROWING;
+      Store[ax - 1][ay] = element;
+      GfxDir[ax - 1][ay] = MovDir[ax - 1][ay] = MV_LEFT;
+      if (IN_SCR_FIELD(SCREENX(ax - 1), SCREENY(ay)))
+       DrawLevelGraphic(ax - 1, ay, IMG_EXPANDABLE_STEELWALL_GROWING_LEFT, 0);
       new_wall = TRUE;
     }
 
     if (rechts_frei)
     {
-      Tile[ax+1][ay] = EL_EXPANDABLE_STEELWALL_GROWING;
-      Store[ax+1][ay] = element;
-      GfxDir[ax+1][ay] = MovDir[ax+1][ay] = MV_RIGHT;
-      if (IN_SCR_FIELD(SCREENX(ax+1), SCREENY(ay)))
-       DrawScreenGraphic(SCREENX(ax + 1), SCREENY(ay),
-                          IMG_EXPANDABLE_STEELWALL_GROWING_RIGHT, 0);
+      Tile[ax + 1][ay] = EL_EXPANDABLE_STEELWALL_GROWING;
+      Store[ax + 1][ay] = element;
+      GfxDir[ax + 1][ay] = MovDir[ax + 1][ay] = MV_RIGHT;
+      if (IN_SCR_FIELD(SCREENX(ax + 1), SCREENY(ay)))
+       DrawLevelGraphic(ax + 1, ay, IMG_EXPANDABLE_STEELWALL_GROWING_RIGHT, 0);
       new_wall = TRUE;
     }
   }
 
-  if (!IN_LEV_FIELD(ax, ay-1) || IS_WALL(Tile[ax][ay-1]))
+  if (!IN_LEV_FIELD(ax, ay - 1) || IS_WALL(Tile[ax][ay - 1]))
     oben_massiv = TRUE;
-  if (!IN_LEV_FIELD(ax, ay+1) || IS_WALL(Tile[ax][ay+1]))
+  if (!IN_LEV_FIELD(ax, ay + 1) || IS_WALL(Tile[ax][ay + 1]))
     unten_massiv = TRUE;
-  if (!IN_LEV_FIELD(ax-1, ay) || IS_WALL(Tile[ax-1][ay]))
+  if (!IN_LEV_FIELD(ax - 1, ay) || IS_WALL(Tile[ax - 1][ay]))
     links_massiv = TRUE;
-  if (!IN_LEV_FIELD(ax+1, ay) || IS_WALL(Tile[ax+1][ay]))
+  if (!IN_LEV_FIELD(ax + 1, ay) || IS_WALL(Tile[ax + 1][ay]))
     rechts_massiv = TRUE;
 
   if (((oben_massiv && unten_massiv) ||
@@ -12547,10 +12554,10 @@ void GameActions_RND(void)
           element == EL_ACID_SPLASH_LEFT ||
           element == EL_ACID_SPLASH_RIGHT))
       {
-       if ((IN_LEV_FIELD(x, y-1) && Tile[x][y-1] == EL_AMOEBA_WET) ||
-           (IN_LEV_FIELD(x-1, y) && Tile[x-1][y] == EL_AMOEBA_WET) ||
-           (IN_LEV_FIELD(x+1, y) && Tile[x+1][y] == EL_AMOEBA_WET) ||
-           (IN_LEV_FIELD(x, y+1) && Tile[x][y+1] == EL_AMOEBA_WET))
+       if ((IN_LEV_FIELD(x, y - 1) && Tile[x][y - 1] == EL_AMOEBA_WET) ||
+           (IN_LEV_FIELD(x - 1, y) && Tile[x - 1][y] == EL_AMOEBA_WET) ||
+           (IN_LEV_FIELD(x + 1, y) && Tile[x + 1][y] == EL_AMOEBA_WET) ||
+           (IN_LEV_FIELD(x, y + 1) && Tile[x][y + 1] == EL_AMOEBA_WET))
          Tile[x][y] = EL_AMOEBA_DROP;
       }
 
@@ -13246,9 +13253,6 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
       }
     }
 
-    player->last_jx = jx;
-    player->last_jy = jy;
-
     if (Tile[jx][jy] == EL_EXIT_OPEN ||
        Tile[jx][jy] == EL_EM_EXIT_OPEN ||
        Tile[jx][jy] == EL_EM_EXIT_OPENING ||
@@ -13266,6 +13270,9 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
        LevelSolved();
     }
 
+    player->last_jx = jx;
+    player->last_jy = jy;
+
     // this breaks one level: "machine", level 000
     {
       int move_direction = player->MovDir;
@@ -15685,9 +15692,10 @@ void RequestQuitGameExt(boolean skip_request, boolean quick_quit, char *message)
     {
       // prevent short reactivation of overlay buttons while closing door
       SetOverlayActive(FALSE);
+      UnmapGameButtons();
 
       // door may still be open due to skipped or envelope style request
-      CloseDoor(DOOR_CLOSE_1);
+      CloseDoor(score_info_tape_play ? DOOR_CLOSE_ALL : DOOR_CLOSE_1);
     }
 
     if (network.enabled)
@@ -15720,7 +15728,7 @@ void RequestQuitGame(boolean escape_key_pressed)
   boolean quick_quit = ((escape_key_pressed && !ask_on_escape) ||
                        level_editor_test_game);
   boolean skip_request = (game.all_players_gone || !setup.ask_on_quit_game ||
-                         quick_quit);
+                         quick_quit || score_info_tape_play);
 
   RequestQuitGameExt(skip_request, quick_quit,
                     "Do you really want to quit the game?");
@@ -16292,6 +16300,10 @@ void CreateGameButtons(void)
     int y = (is_touch_button ? pos->y : GDI_ACTIVE_POS(pos->y));
     int id = i;
 
+    // do not use touch buttons if overlay touch buttons are disabled
+    if (is_touch_button && !setup.touch.overlay_buttons)
+      continue;
+
     if (gfx->bitmap == NULL)
     {
       game_gadget[id] = NULL;
@@ -16585,13 +16597,7 @@ static void HandleGameButtonsExt(int id, int button)
     case GAME_CTRL_ID_STOP:
     case GAME_CTRL_ID_PANEL_STOP:
     case GAME_CTRL_ID_TOUCH_STOP:
-      if (game_status == GAME_MODE_MAIN)
-       break;
-
-      if (tape.playing)
-       TapeStop();
-      else
-       RequestQuitGame(FALSE);
+      TapeStopGame();
 
       break;