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
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;
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)
// 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)
{
// ...
// 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);