added code to convert native Boulder Dash tapes
authorHolger Schemel <info@artsoft.org>
Sun, 11 Feb 2024 02:05:56 +0000 (03:05 +0100)
committerHolger Schemel <info@artsoft.org>
Sun, 18 Feb 2024 14:57:42 +0000 (15:57 +0100)
src/files.c
src/game_bd/export_bd.h
src/game_bd/main_bd.c
src/tape.c
src/tape.h

index c56fc69ee741c145fbaabe22b397042150011dc9..269a749b4c079accd068fb0186b31f5b51b9c103 100644 (file)
@@ -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)
index eaf511f629b6c3b71ece7e1e354a2ef26009ec42..2053c92235c11c6e96074bd87e4852f8ad233d5a 100644 (file)
 
 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);
 
index 1c18117bd42c79882f09eef6f76bef346e856d28..d40b76e47cdde8c2c4c3dbde9b97f133a9aebcc9 100644 (file)
@@ -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)
 {
   // ...
index f16e7ec9451a20ab68068add00155ed01870088a..f9c56d1ad12c2d4168522ee4b66c37abfc83a4cf 100644 (file)
@@ -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);
index 8b375edec55db00f69df8cb5aef264c5e70916e3..cfd67be2427e35f26f89462ef526f10dc632c652 100644 (file)
@@ -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);