Ejemplo n.º 1
0
enum nh_restore_status nh_restore_game(int fd, struct nh_window_procs *rwinprocs,
				       boolean force_replay)
{
    int playmode, irole, irace, igend, ialign;
    char namebuf[PL_NSIZ];
    
    /* some compilers can't cope with the fact that all subsequent stores to error
     * are not dead, but become important if the error handler longjumps back
     * volatile is required to prevent invalid optimization based on that wrong
     * assumption. */
    volatile enum nh_restore_status error = GAME_RESTORED;
    
    if (fd == -1)
	return ERR_BAD_ARGS;
    
    switch (nh_get_savegame_status(fd, NULL)) {
	case LS_INVALID:	return ERR_BAD_FILE;
	case LS_DONE:		return ERR_GAME_OVER;
	case LS_CRASHED:	force_replay = TRUE; break;
	case LS_IN_PROGRESS:	return ERR_IN_PROGRESS;
	case LS_SAVED:		break; /* default, everything is A-OK */
    }
    
    if (!api_entry_checkpoint())
	goto error_out;
    
    error = ERR_BAD_FILE;
    replay_set_logfile(fd); /* store the fd and try to get a lock or exit */
    replay_begin();

    program_state.restoring = TRUE;
    iflags.disable_log = TRUE; /* don't log any of the commands, they're already in the log */

    /* Read the log header for this game. */
    replay_read_newgame(&turntime, &playmode, namebuf,
			&irole, &irace, &igend, &ialign);

    /* set special windowprocs which will autofill requests for user input
     * with data from the log file */
    replay_setup_windowprocs(rwinprocs);

    startup_common(namebuf, playmode);
    u.initrole = irole;
    u.initrace = irace;
    u.initgend = igend;
    u.initalign = ialign;

    if (!force_replay) {
	error = ERR_RESTORE_FAILED;
	replay_run_cmdloop(TRUE, FALSE, TRUE);
	replay_jump_to_endpos();
	if (!dorecover_fd(fd)) {
	    replay_undo_jump_to_endpos();
	    goto error_out2;
	}
	replay_undo_jump_to_endpos();
	wd_message();
	program_state.game_running = 1;
	post_init_tasks();
    } else {
	replay_run_cmdloop(TRUE, TRUE, FALSE); /* option setup only */
	newgame();
	/* try replaying instead */
	error = ERR_REPLAY_FAILED;
	replay_run_cmdloop(FALSE, FALSE, TRUE);
	replay_sync_save();
    }
    
    /* restore standard window procs */
    replay_restore_windowprocs();
    program_state.restoring = FALSE;
    iflags.disable_log = FALSE;

    /* clean up data used for replay */
    replay_end();
    log_truncate();
    log_init(); /* must be called before we start writing to the log */

    /* info might not have reached the ui while alternate window procs were set */
    doredraw();

    /* nh_start_game() does this via newgame(), but since this function doesn't
     * call newgame(), we have to do it here instead. */
    notify_levelchange(NULL);

    bot();
    flush_screen();
    was_on_elbereth = !sengr_at("Elbereth", u.ux, u.uy); /* force botl update later */

    welcome(FALSE);
    realtime_messages(TRUE, TRUE);
    update_inventory();
    
    api_exit();
    return GAME_RESTORED;

error_out2:
    api_exit();
    
error_out:
    replay_restore_windowprocs();
    program_state.restoring = FALSE;
    iflags.disable_log = FALSE;
    replay_end();
    unlock_fd(fd);
    
    if (error == ERR_RESTORE_FAILED) {
	raw_printf("Restore failed. Attempting to replay instead.\n");
	error = nh_restore_game(fd, rwinprocs, TRUE);
    }
    
    return error;
}
Ejemplo n.º 2
0
static void newgame(void)
{
    int i;

    flags.ident = 1;

    for (i = 0; i < NUMMONS; i++)
	    mvitals[i].mvflags = mons[i].geno & G_NOCORPSE;

    init_objects();	/* must be before u_init() */

    flags.pantheon = -1;/* role_init() will reset this */
    role_init();	/* must be before init_dungeons(), u_init(),
			 * and init_artifacts() */

    init_dungeons();	/* must be before u_init() to avoid rndmonst()
			 * creating odd monsters for any tins and eggs
			 * in hero's initial inventory */
    init_artifacts();
    u_init();		/* struct you must have some basic data for mklev to work right */

    load_qtlist();	/* load up the quest text info */

    level = mklev(&u.uz);

    u_init_inv_skills();/* level must be valid to create items */
    u_on_upstairs();
    vision_reset();	/* set up internals for level (after mklev) */
    check_special_room(FALSE);

    iflags.botl = 1;

    /* Move the monster from under you or else
     * makedog() will fail when it calls makemon().
     *			- ucsfcgl!kneller
     */
    if (MON_AT(level, u.ux, u.uy)) mnexto(m_at(level, u.ux, u.uy));
    makedog();
    doredraw();

    if (Role_if(PM_CONVICT)) {
	setworn(mkobj(level, CHAIN_CLASS, TRUE), W_CHAIN);
	setworn(mkobj(level, BALL_CLASS, TRUE), W_BALL);
	uball->spe = 1;	/* attach the ball to the hero */
	placebc();
    }

    /* help the window port get it's display charset/tiles sorted out */
    notify_levelchange(NULL);

    if (flags.legacy) {
	    flush_screen();
	    com_pager(Role_if(PM_CONVICT) ? 199 : 1);
    }

    /* Stop autoexplore revisiting the entrance stairs (or position). */
    level->locations[u.ux][u.uy].mem_stepped = 1;

    program_state.something_worth_saving++;	/* useful data now exists */
    
    historic_event(FALSE, "entered the Dungeons of Doom to retrieve the Amulet of Yendor!");

    /* Success! */
    welcome(TRUE);
    maybe_tutorial();

    /* Prepare for the first move. */
    flags.move = 0;
    set_wear();
    pickup(1);

    log_command_result();

    program_state.game_running = TRUE;
    youmonst.movement = NORMAL_SPEED;	/* give the hero some movement points */
    realtime_tasks();
    post_init_tasks();

    return;
}