From f7d2fb71a0968d07a7f425ab864fa6befef5dcf3 Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Sun, 11 Feb 2024 03:05:56 +0100 Subject: [PATCH] added code to convert native Boulder Dash tapes --- src/files.c | 81 ++++++++++++++++++++++++++++++++++++++--- src/game_bd/export_bd.h | 5 +++ src/game_bd/main_bd.c | 18 +++++++++ src/tape.c | 24 ++++++++++++ src/tape.h | 4 ++ 5 files changed, 126 insertions(+), 6 deletions(-) diff --git a/src/files.c b/src/files.c index c56fc69e..269a749b 100644 --- a/src/files.c +++ b/src/files.c @@ -3713,6 +3713,72 @@ static void CopyNativeLevel_BD_to_RND(struct LevelInfo *level) level->field[x][y] = map_element_BD_to_RND(cave->map[y][x]); } +static void setTapeInfoToDefaults(void); + +static void CopyNativeTape_BD_to_RND(struct LevelInfo *level) +{ + struct LevelInfo_BD *level_bd = level->native_bd_level; + GdCave *cave = level_bd->cave; + GdReplay *replay = level_bd->replay; + int i; + + if (replay == NULL) + return; + + // always start with reliable default values + setTapeInfoToDefaults(); + + tape.level_nr = level_nr; // (currently not used) + tape.random_seed = replay->seed; + + TapeSetDateFromIsoDateString(replay->date); + + tape.counter = 0; + tape.pos[tape.counter].delay = 0; + + tape.bd_replay = TRUE; + + // all time calculations only used to display approximate tape time + int cave_speed = cave->speed; + int milliseconds_game = 0; + int milliseconds_elapsed = 20; + + for (i = 0; i < replay->movements->len; i++) + { + int replay_action = replay->movements->data[i]; + int tape_action = map_action_BD_to_RND(replay_action); + byte action[MAX_TAPE_ACTIONS] = { tape_action }; + boolean success = 0; + + while (1) + { + success = TapeAddAction(action); + + milliseconds_game += milliseconds_elapsed; + + if (milliseconds_game >= cave_speed) + { + milliseconds_game -= cave_speed; + + break; + } + } + + tape.counter++; + tape.pos[tape.counter].delay = 0; + tape.pos[tape.counter].action[0] = 0; + + if (!success) + { + Warn("BD replay truncated: size exceeds maximum tape size %d", MAX_TAPE_LEN); + + break; + } + } + + TapeHaltRecording(); +} + // ---------------------------------------------------------------------------- // functions for loading EM level @@ -4172,8 +4238,6 @@ static void CopyNativeTape_RND_to_SP(struct LevelInfo *level) demo->is_available = TRUE; } -static void setTapeInfoToDefaults(void); - static void CopyNativeTape_SP_to_RND(struct LevelInfo *level) { struct LevelInfo_SP *level_sp = level->native_sp_level; @@ -8493,10 +8557,15 @@ void LoadSolutionTape(int nr) LoadTapeFromFilename(filename); - if (TAPE_IS_EMPTY(tape) && - level.game_engine_type == GAME_ENGINE_TYPE_SP && - level.native_sp_level->demo.is_available) - CopyNativeTape_SP_to_RND(&level); + if (TAPE_IS_EMPTY(tape)) + { + if (level.game_engine_type == GAME_ENGINE_TYPE_BD && + level.native_bd_level->replay != NULL) + CopyNativeTape_BD_to_RND(&level); + else if (level.game_engine_type == GAME_ENGINE_TYPE_SP && + level.native_sp_level->demo.is_available) + CopyNativeTape_SP_to_RND(&level); + } } void LoadScoreTape(char *score_tape_basename, int nr) diff --git a/src/game_bd/export_bd.h b/src/game_bd/export_bd.h index eaf511f6..2053c922 100644 --- a/src/game_bd/export_bd.h +++ b/src/game_bd/export_bd.h @@ -34,8 +34,11 @@ struct GameInfo_BD { + unsigned int random_seed; + boolean level_solved; boolean game_over; + boolean cover_screen; // needed for updating panel int time_played; @@ -67,6 +70,8 @@ extern struct GameInfo_BD game_bd; extern struct LevelInfo_BD native_bd_level; extern struct EngineSnapshotInfo_BD engine_snapshot_bd; +int map_action_BD_to_RND(int); + void setLevelInfoToDefaults_BD_Ext(int, int); void setLevelInfoToDefaults_BD(void); diff --git a/src/game_bd/main_bd.c b/src/game_bd/main_bd.c index 1c18117b..d40b76e4 100644 --- a/src/game_bd/main_bd.c +++ b/src/game_bd/main_bd.c @@ -21,6 +21,24 @@ struct EngineSnapshotInfo_BD engine_snapshot_bd; // level file functions // ============================================================================ +int map_action_BD_to_RND(int action) +{ + GdDirection player_move = action & GD_REPLAY_MOVE_MASK; + boolean player_fire = action & GD_REPLAY_FIRE_MASK; + + int action_move = (player_move == GD_MV_UP ? JOY_UP : + player_move == GD_MV_UP_RIGHT ? JOY_UP | JOY_RIGHT : + player_move == GD_MV_RIGHT ? JOY_RIGHT : + player_move == GD_MV_DOWN_RIGHT ? JOY_DOWN | JOY_RIGHT : + player_move == GD_MV_DOWN ? JOY_DOWN : + player_move == GD_MV_DOWN_LEFT ? JOY_DOWN | JOY_LEFT : + player_move == GD_MV_LEFT ? JOY_LEFT : + player_move == GD_MV_UP_LEFT ? JOY_UP | JOY_LEFT : JOY_NO_ACTION); + int action_fire = (player_fire ? JOY_BUTTON_1 : JOY_NO_ACTION); + + return (action_move | action_fire); +} + void setLevelInfoToDefaults_BD_Ext(int width, int height) { // ... diff --git a/src/tape.c b/src/tape.c index f16e7ec9..f9c56d1a 100644 --- a/src/tape.c +++ b/src/tape.c @@ -629,6 +629,30 @@ static void CloseTapeLogfile(void) // tape control functions // ============================================================================ +void TapeSetDateFromIsoDateString(char *date) +{ + int i; + + // check ISO date string for correct length + if (strlen(date) != 10) + return; + + // check ISO date string for correct format + for (i = 0; i < strlen(date); i++) + if (((i != 4 && i != 7) && (date[i] < '0' || date[i] > '9')) || + ((i == 4 || i == 7) && (date[i] != '-'))) + return; + + int yy = (date[2] - '0') * 10 + (date[3] - '0'); + int mm = (date[5] - '0') * 10 + (date[6] - '0'); + int dd = (date[8] - '0') * 10 + (date[9] - '0'); + + if (mm < 1 || mm > 12 || dd < 1 || dd > 31) + return; + + tape.date = 10000 * yy + 100 * (mm - 1) + dd; +} + void TapeSetDateFromEpochSeconds(time_t epoch_seconds) { struct tm *lt = localtime(&epoch_seconds); diff --git a/src/tape.h b/src/tape.h index 8b375ede..cfd67be2 100644 --- a/src/tape.h +++ b/src/tape.h @@ -223,6 +223,9 @@ struct TapeInfo // bits to indicate which tape properties are stored in this tape byte property_bits; + // special game_engine_flags; + boolean bd_replay; + // visible playfield size when recording this tape (for team mode) int scr_fieldx; int scr_fieldy; @@ -251,6 +254,7 @@ void DrawCompleteVideoDisplay(void); void TapeDeactivateDisplayOn(void); void TapeDeactivateDisplayOff(boolean); +void TapeSetDateFromIsoDateString(char *); void TapeSetDateFromEpochSeconds(time_t); void TapeSetDateFromNow(void); -- 2.34.1