// game panel display and control definitions
#define GAME_PANEL_LEVEL_NUMBER 0
#define GAME_PANEL_GEMS 1
-#define GAME_PANEL_GEMS_TOTAL 2
+#define GAME_PANEL_GEMS_NEEDED 2
#define GAME_PANEL_GEMS_COLLECTED 3
#define GAME_PANEL_GEMS_SCORE 4
#define GAME_PANEL_INVENTORY_COUNT 5
TYPE_INTEGER,
},
{
- GAME_PANEL_GEMS_TOTAL,
- &game.panel.gems_total,
+ GAME_PANEL_GEMS_NEEDED,
+ &game.panel.gems_needed,
TYPE_INTEGER,
},
{
}
}
+static void InitFieldForEngine_RND(int x, int y)
+{
+ int element = Tile[x][y];
+
+ // convert BD engine elements to corresponding R'n'D engine elements
+ element = (element == EL_BD_EMPTY ? EL_EMPTY :
+ element == EL_BD_PLAYER ? EL_PLAYER_1 :
+ element == EL_BD_INBOX ? EL_PLAYER_1 :
+ element == EL_BD_SAND ? EL_SAND :
+ element == EL_BD_STEELWALL ? EL_STEELWALL :
+ element == EL_BD_EXIT_CLOSED ? EL_EXIT_CLOSED :
+ element == EL_BD_EXIT_OPEN ? EL_EXIT_OPEN :
+ element);
+
+ Tile[x][y] = element;
+}
+
+static void InitFieldForEngine(int x, int y)
+{
+ if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
+ InitFieldForEngine_RND(x, y);
+}
+
static void InitField(int x, int y, boolean init_game)
{
int element = Tile[x][y];
level.game_engine_type == GAME_ENGINE_TYPE_MM ?
game_mm.kettles_still_needed :
game.gems_still_needed);
- int gems_total = level.gems_needed;
+ int gems_needed = level.gems_needed;
int gems_collected = (level.game_engine_type == GAME_ENGINE_TYPE_BD ?
game_bd.game->cave->diamonds_collected :
- gems_total - gems);
+ gems_needed - gems);
int gems_score = (level.game_engine_type == GAME_ENGINE_TYPE_BD ?
game_bd.game->cave->diamond_value :
level.score[SC_EMERALD]);
// used instead of "level_nr" (for network games)
game_panel_controls[GAME_PANEL_LEVEL_NUMBER].value = levelset.level_nr;
game_panel_controls[GAME_PANEL_GEMS].value = gems;
- game_panel_controls[GAME_PANEL_GEMS_TOTAL].value = gems_total;
+ game_panel_controls[GAME_PANEL_GEMS_NEEDED].value = gems_needed;
game_panel_controls[GAME_PANEL_GEMS_COLLECTED].value = gems_collected;
game_panel_controls[GAME_PANEL_GEMS_SCORE].value = gems_score;
if (PANEL_DEACTIVATED(pos))
continue;
- if (pos->class == get_hash_from_key("extra_panel_items") &&
+ if (pos->class == get_hash_from_string("extra_panel_items") &&
!setup.prefer_extra_panel_items)
continue;
int width, height;
int dst_x = PANEL_XPOS(pos);
int dst_y = PANEL_YPOS(pos);
- boolean skip = (pos->class == get_hash_from_key("mm_engine_only") &&
+ boolean skip = (pos->class == get_hash_from_string("mm_engine_only") &&
level.game_engine_type != GAME_ENGINE_TYPE_MM);
if (graphic != IMG_UNDEFINED && !skip)
game.explosions_delayed = TRUE;
- game.envelope_active = FALSE;
-
// special case: set custom artwork setting to initial value
game.use_masked_elements = game.use_masked_elements_initial;
SCAN_PLAYFIELD(x, y)
{
+ InitFieldForEngine(x, y);
+
if (emulate_bd && !IS_BD_ELEMENT(Tile[x][y]))
emulate_bd = FALSE;
if (emulate_sp && !IS_SP_ELEMENT(Tile[x][y]))
game.restart_level = FALSE;
game.request_active = FALSE;
+ game.envelope_active = FALSE;
+ game.any_door_active = FALSE;
if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
InitGameActions_MM();
LevelSolved_SetFinalGameValues();
}
+static boolean AdvanceToNextLevel(void)
+{
+ if (setup.increment_levels &&
+ level_nr < leveldir_current->last_level &&
+ !network_playing)
+ {
+ level_nr++; // advance to next level
+ TapeErase(); // start with empty tape
+
+ if (setup.auto_play_next_level)
+ {
+ scores.continue_playing = TRUE;
+ scores.next_level_nr = level_nr;
+
+ LoadLevel(level_nr);
+
+ SaveLevelSetup_SeriesInfo();
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
void GameWon(void)
{
static int time_count_steps;
// used instead of "level_nr" (needed for network games)
int last_level_nr = levelset.level_nr;
boolean tape_saved = FALSE;
+ boolean game_over = checkGameFailed();
+
+ // Important note: This function is not only called after "GameWon()", but also after
+ // "game over" (if automatically asking for restarting the game is disabled in setup)
+
+ // do not handle game end if game over and automatically asking for game restart
+ if (game_over && setup.ask_on_game_over)
+ return;
+
+ // do not handle game end if request dialog is already active
+ if (checkRequestActive())
+ return;
- game.LevelSolved_GameEnd = TRUE;
+ if (game.LevelSolved)
+ game.LevelSolved_GameEnd = TRUE;
if (game.LevelSolved_SaveTape && !score_info_tape_play)
{
return;
}
- if (!game.LevelSolved_SaveScore)
+ if (!game.GamePlayed || (!game.LevelSolved_SaveScore && !level.bd_intermission))
{
SetGameStatus(GAME_MODE_MAIN);
}
// save score and score tape before potentially erasing tape below
- NewHighScore(last_level_nr, tape_saved);
-
- if (setup.increment_levels &&
- level_nr < leveldir_current->last_level &&
- !network_playing)
- {
- level_nr++; // advance to next level
- TapeErase(); // start with empty tape
-
- if (setup.auto_play_next_level)
- {
- scores.continue_playing = TRUE;
- scores.next_level_nr = level_nr;
+ if (game.LevelSolved_SaveScore)
+ NewHighScore(last_level_nr, tape_saved);
- LoadLevel(level_nr);
-
- SaveLevelSetup_SeriesInfo();
- }
- }
+ // increment and load next level (if possible and not configured otherwise)
+ AdvanceToNextLevel();
- if (scores.last_added >= 0 && setup.show_scores_after_game)
+ if (game.LevelSolved_SaveScore && scores.last_added >= 0 && setup.show_scores_after_game)
{
SetGameStatus(GAME_MODE_SCORES);
void PlayLevelSound_BD(int xx, int yy, int element_bd, int sample)
{
- int element = (element_bd > -1 ? map_element_BD_to_RND(element_bd) : 0);
+ int element = (element_bd > -1 ? map_element_BD_to_RND_game(element_bd) : 0);
int sound_effect = getSoundEffect_BD(element, sample);
int sound_action = getSoundAction_BD(sample);
boolean is_loop_sound = IS_LOOP_SOUND(sound_effect);
void StopSound_BD(int element_bd, int sample)
{
- int element = (element_bd > -1 ? map_element_BD_to_RND(element_bd) : 0);
+ int element = (element_bd > -1 ? map_element_BD_to_RND_game(element_bd) : 0);
int sound_effect = getSoundEffect_BD(element, sample);
if (sound_effect != SND_UNDEFINED)
boolean isSoundPlaying_BD(int element_bd, int sample)
{
- int element = (element_bd > -1 ? map_element_BD_to_RND(element_bd) : 0);
+ int element = (element_bd > -1 ? map_element_BD_to_RND_game(element_bd) : 0);
int sound_effect = getSoundEffect_BD(element, sample);
if (sound_effect != SND_UNDEFINED)
int request_mode = (has_started_game ? REQ_ASK : REQ_CONFIRM);
int door_state = DOOR_CLOSE_1;
- if (Request(message, request_mode | REQ_STAY_OPEN) && has_started_game)
+ boolean restart_wanted = (Request(message, request_mode | REQ_STAY_OPEN) && has_started_game);
+
+ // if no restart wanted, continue with next level for BD style intermission levels
+ if (!restart_wanted && !level_editor_test_game && level.bd_intermission)
+ {
+ boolean success = AdvanceToNextLevel();
+
+ restart_wanted = (success && setup.auto_play_next_level);
+ }
+
+ if (restart_wanted)
{
CloseDoor(door_state);
}
// do not ask to play again if request dialog is already active
- if (game.request_active)
+ if (checkRequestActive())
return FALSE;
// do not ask to play again if request dialog already handled
return (checkGameSolved() || checkGameFailed());
}
+boolean checkRequestActive(void)
+{
+ return (game.request_active || game.envelope_active || game.any_door_active);
+}
+
// ----------------------------------------------------------------------------
// random generator functions