Print("Number of levels: %d\n", autoplay->leveldir->levels);
PrintLine("=", 79);
Print("\n");
+
+ DrawInitTextItem(autoplay->leveldir->name);
}
static void PrintTapeReplayProgress(boolean replay_finished)
if (tape.pause_before_end) // stop some seconds before end of tape
{
- if (TapeTime > tape.length_seconds - TAPE_PAUSE_SECONDS_BEFORE_DEATH)
+ if (TapeTime > (int)tape.length_seconds - TAPE_PAUSE_SECONDS_BEFORE_DEATH)
{
TapeStopWarpForward();
TapeTogglePause(TAPE_TOGGLE_MANUAL);
}
}
+static boolean checkRestartGame(char *message)
+{
+ if (game_status == GAME_MODE_MAIN)
+ return TRUE;
+
+ if (!hasStartedNetworkGame())
+ return FALSE;
+
+ if (level_editor_test_game)
+ return TRUE;
+
+ if (game.all_players_gone)
+ return TRUE;
+
+ if (!setup.ask_on_quit_game)
+ return TRUE;
+
+ if (Request(message, REQ_ASK | REQ_STAY_CLOSED))
+ return TRUE;
+
+ OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
+
+ return FALSE;
+}
+
+void TapeRestartGame(void)
+{
+ if (!checkRestartGame("Restart game?"))
+ return;
+
+ StartGameActions(network.enabled, setup.autorecord, level.random_seed);
+}
+
+void TapeReplayAndPauseBeforeEnd(void)
+{
+ if (TAPE_IS_EMPTY(tape) && !tape.recording)
+ {
+ Request("No tape for this level!", REQ_CONFIRM);
+
+ return;
+ }
+
+ if (!checkRestartGame("Replay game and pause before end?"))
+ return;
+
+ TapeStop();
+ TapeStartGamePlaying();
+ TapeStartWarpForward(AUTOPLAY_MODE_WARP_NO_DISPLAY);
+
+ tape.pause_before_end = TRUE;
+ tape.quick_resume = TRUE;
+}
+
boolean hasSolutionTape(void)
{
boolean tape_file_exists = fileExists(getSolutionTapeFilename(level_nr));
// tape autoplay functions
// ----------------------------------------------------------------------------
+static TreeInfo *getNextValidAutoPlayEntry(TreeInfo *node)
+{
+ node = getNextValidTreeInfoEntry(node);
+
+ while (node && node->is_copy)
+ node = getNextValidTreeInfoEntry(node);
+
+ return node;
+}
+
+static TreeInfo *getFirstValidAutoPlayEntry(TreeInfo *node)
+{
+ node = getFirstValidTreeInfoEntry(node);
+
+ if (node && node->is_copy)
+ return getNextValidAutoPlayEntry(node);
+
+ return node;
+}
+
static void AutoPlayTapes_SetScoreEntry(int score, int time)
{
+ char *name = (options.mytapes ? setup.player_name : options.player_name);
+
// set unique basename for score tape (for uploading to score server)
- strcpy(tape.score_tape_basename, getScoreTapeBasename(setup.player_name));
+ strcpy(tape.score_tape_basename, getScoreTapeBasename(name));
// store score in first score entry
scores.last_added = 0;
server_scores.uploaded = FALSE;
}
-static void AutoPlayTapes_WaitForUpload(void)
+static boolean AutoPlayTapes_WaitForUpload(void)
{
unsigned int upload_delay = 0;
unsigned int upload_delay_value = 10000;
PrintNoLog("\r");
Print("- uploading score tape to score server - TIMEOUT.\n");
- Fail("cannot upload score tape to score server");
+ if (program.headless)
+ Fail("cannot upload score tape to score server");
+
+ return FALSE;
}
+ UPDATE_BUSY_STATE();
+
Delay(20);
}
PrintNoLog("\r");
Print("- uploading score tape to score server - uploaded.\n");
+
+ return TRUE;
}
-static void AutoPlayTapesExt(boolean initialize)
+static int AutoPlayTapesExt(boolean initialize)
{
static struct AutoPlayInfo autoplay;
+ static int num_tapes = 0;
static int patch_nr = 0;
static char *patch_name[] =
{
-1
};
+ LevelDirTree *leveldir_current_last = leveldir_current;
boolean init_level_set = FALSE;
+ int level_nr_last = level_nr;
int i;
if (!initialize)
// save score tape to upload to server; may be required for some reasons:
// * level set identifier in solution tapes may differ from level set
+ // * level set identifier is missing (old-style tape without INFO chunk)
// * solution tape may have native format (like Supaplex solution files)
SaveScoreTape(level_nr);
- SaveServerScore(level_nr);
+ SaveServerScore(level_nr, TRUE);
AutoPlayTapes_WaitForUpload();
}
Fail("specify player name when uploading solution tapes");
}
- DrawCompleteVideoDisplay();
+ if (global.autoplay_mode != AUTOPLAY_MODE_UPLOAD)
+ DrawCompleteVideoDisplay();
- audio.sound_enabled = FALSE;
- setup.engine_snapshot_mode = getStringCopy(STR_SNAPSHOT_MODE_OFF);
+ if (program.headless)
+ {
+ audio.sound_enabled = FALSE;
+ setup.engine_snapshot_mode = getStringCopy(STR_SNAPSHOT_MODE_OFF);
+ }
if (strSuffix(global.autoplay_leveldir, ".tape"))
{
autoplay.tape_filename = global.autoplay_leveldir;
+ if (!fileExists(autoplay.tape_filename))
+ Fail("tape file '%s' does not exist", autoplay.tape_filename);
+
LoadTapeFromFilename(autoplay.tape_filename);
if (tape.no_valid_file)
- {
- if (!fileExists(autoplay.tape_filename))
- Fail("tape file '%s' does not exist", autoplay.tape_filename);
- else
- Fail("cannot load tape file '%s'", autoplay.tape_filename);
- }
+ Fail("cannot load tape file '%s'", autoplay.tape_filename);
+
+ if (tape.no_info_chunk && !options.identifier)
+ Fail("cannot get levelset from tape file '%s'", autoplay.tape_filename);
+
+ if (tape.no_info_chunk && !options.level_nr)
+ Fail("cannot get level nr from tape file '%s'", autoplay.tape_filename);
global.autoplay_leveldir = tape.level_identifier;
+ if (options.identifier != NULL)
+ global.autoplay_leveldir = options.identifier;
+
+ if (options.level_nr != NULL)
+ tape.level_nr = atoi(options.level_nr);
+
if (tape.level_nr >= 0 && tape.level_nr < MAX_TAPES_PER_SET)
global.autoplay_level[tape.level_nr] = TRUE;
global.autoplay_all = FALSE;
+ options.mytapes = FALSE;
}
if (autoplay.all_levelsets)
{
// start auto-playing first level set
- autoplay.leveldir = getFirstValidTreeInfoEntry(leveldir_first);
+ autoplay.leveldir = getFirstValidAutoPlayEntry(leveldir_first);
}
else
{
if (global.autoplay_mode == AUTOPLAY_MODE_FIX)
options.mytapes = TRUE;
+ // set timestamp for batch tape upload
+ global.autoplay_time = time(NULL);
+
+ num_tapes = 0;
+
init_level_set = TRUE;
}
init_level_set = FALSE;
}
+ if (autoplay.all_levelsets && global.autoplay_mode == AUTOPLAY_MODE_UPLOAD)
+ {
+ boolean skip_levelset = FALSE;
+
+ if (!directoryExists(getTapeDir(autoplay.leveldir->subdir)))
+ {
+ Print("No tape directory for this level set found -- skipping.\n");
+
+ skip_levelset = TRUE;
+ }
+
+ if (CheckTapeDirectoryUploadsComplete(autoplay.leveldir->subdir))
+ {
+ Print("All tapes for this level set already uploaded -- skipping.\n");
+
+ skip_levelset = TRUE;
+ }
+
+ if (skip_levelset)
+ {
+ PrintTapeReplaySummary(&autoplay);
+
+ // continue with next level set
+ autoplay.leveldir = getNextValidAutoPlayEntry(autoplay.leveldir);
+
+ // all level sets processed
+ if (autoplay.leveldir == NULL)
+ break;
+
+ init_level_set = TRUE;
+
+ continue;
+ }
+ }
+
if (global.autoplay_mode != AUTOPLAY_MODE_FIX || patch_nr == 0)
level_nr = autoplay.level_nr++;
+ UPDATE_BUSY_STATE();
+
// check if all tapes for this level set have been processed
if (level_nr > autoplay.leveldir->last_level)
{
if (!autoplay.all_levelsets)
break;
+ if (global.autoplay_mode == AUTOPLAY_MODE_UPLOAD)
+ MarkTapeDirectoryUploadsAsComplete(autoplay.leveldir->subdir);
+
// continue with next level set
- autoplay.leveldir = getNextValidTreeInfoEntry(autoplay.leveldir);
+ autoplay.leveldir = getNextValidAutoPlayEntry(autoplay.leveldir);
// all level sets processed
if (autoplay.leveldir == NULL)
if (!global.autoplay_all && !global.autoplay_level[level_nr])
continue;
+ // speed things up in case of missing private tapes (skip loading level)
+ if (options.mytapes && !fileExists(getTapeFilename(level_nr)))
+ {
+ autoplay.num_tape_missing++;
+
+ Print("Tape %03d: (no tape found)\n", level_nr);
+
+ continue;
+ }
+
TapeErase();
TapeRewind(); // needed to reset "tape.auto_play_level_solved"
}
}
+ num_tapes++;
+
if (global.autoplay_mode == AUTOPLAY_MODE_UPLOAD)
{
boolean use_temporary_tape_file = FALSE;
if (!fileExists(autoplay.tape_filename))
{
- // non-standard solution tape -- save to temporary file
+ // non-standard or incorrect solution tape -- save to temporary file
autoplay.tape_filename = getTemporaryTapeFilename();
SaveTapeToFilename(autoplay.tape_filename);
}
}
- SaveServerScoreFromFile(level_nr, autoplay.tape_filename);
+ SaveServerScoreFromFile(level_nr, TRUE, autoplay.tape_filename);
- AutoPlayTapes_WaitForUpload();
+ boolean success = AutoPlayTapes_WaitForUpload();
if (use_temporary_tape_file)
unlink(autoplay.tape_filename);
// required for uploading multiple tapes
autoplay.tape_filename = NULL;
+ if (!success)
+ {
+ num_tapes = -num_tapes;
+
+ break;
+ }
+
continue;
}
autoplay.last_level_nr = level_nr;
- return;
+ return num_tapes;
}
- CloseAllAndExit(0);
+ if (global.autoplay_mode == AUTOPLAY_MODE_UPLOAD)
+ {
+ Print("\n");
+ PrintLine("=", 79);
+
+ if (num_tapes >= 0)
+ Print("SUMMARY: %d tapes uploaded.\n", num_tapes);
+ else
+ Print("SUMMARY: Uploading tapes failed.\n");
+
+ PrintLine("=", 79);
+ }
+
+ // clear timestamp for batch tape upload (required after interactive upload)
+ global.autoplay_time = 0;
+
+ // exit if running headless or if visually auto-playing tapes
+ if (program.headless || global.autoplay_mode != AUTOPLAY_MODE_UPLOAD)
+ CloseAllAndExit(0);
+
+ // when running interactively, restore last selected level set and number
+ leveldir_current = leveldir_current_last;
+ level_nr = level_nr_last;
+
+ return num_tapes;
}
-void AutoPlayTapes(void)
+int AutoPlayTapes(void)
{
- AutoPlayTapesExt(TRUE);
+ return AutoPlayTapesExt(TRUE);
}
-void AutoPlayTapesContinue(void)
+int AutoPlayTapesContinue(void)
{
- AutoPlayTapesExt(FALSE);
+ return AutoPlayTapesExt(FALSE);
}