예제 #1
0
static void pre_move_tasks(boolean didmove)
{
    boolean is_on_elbereth = sengr_at("Elbereth", u.ux, u.uy);

    /* recalc attribute bonuses from items */
    calc_attr_bonus();
    find_ac();

    if (!flags.mv || Blind)
	special_vision_handling();

    /* update "Elbereth" status */
    if (was_on_elbereth != is_on_elbereth) {
	was_on_elbereth = is_on_elbereth;
	iflags.botl = 1;
    }

    if (iflags.botl)
	bot();

    if (didmove &&
	(u.uhave.amulet || Clairvoyant) &&
	!In_endgame(&u.uz) && !BClairvoyant &&
	!(moves % 15) && !rn2(2))
	    do_vicinity_map();

    u.umoved = FALSE;

    if (multi > 0) {
	lookaround();
	if (!multi) {
	    /* lookaround may clear multi */
	    flags.move = 0;
	    iflags.botl = 1;
	}
    }
    
    if (didmove && moves % 100 == 0)
	realtime_tasks();
    
    update_inventory();
    update_location(FALSE);

    if (didmove) {
	/* Mark the current square as stepped on unless blind,
	 * since that would imply that we had properly explored it. */
	struct rm *loc = &level->locations[u.ux][u.uy];
	if (!Blind && !loc->mem_stepped)
	    loc->mem_stepped = 1;
    }
}
예제 #2
0
boolean nh_start_game(int fd, const char *name, int irole, int irace, int igend,
		      int ialign, enum nh_game_modes playmode)
{
    unsigned int seed = 0;
    
    if (!api_entry_checkpoint())
	return FALSE; /* init failed; programmer error! */

    if (fd == -1 || !name || !*name)
	goto err_out;
    
    if (!program_state.restoring) {
	turntime = (unsigned long long)time(NULL);
	seed = turntime ^ get_seedval();
	/* initialize the random number generator */
	mt_srand(seed);
    } /* else: turntime and rng seeding are done in logreplay.c */
    
    startup_common(name, playmode);
    
    if (!validrole(irole) || !validrace(irole, irace) ||
	!validgend(irole, irace, igend) || !validalign(irole, irace, ialign))
	goto err_out;
    u.initrole = irole; u.initrace = irace;
    u.initgend = igend; u.initalign = ialign;

    /* write out a new logfile header "NHGAME ..." with all the initial details */
    log_init();
    log_newgame(fd, turntime, seed, playmode);

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

    api_exit();
    return TRUE;
    
err_out:
    api_exit();
    return FALSE;
}
예제 #3
0
/* Return number of acceptable neighbour positions */
int mfndpos(struct monst *mon, coord poss[9], int info[9], int flag)
{
    int x;
    int y;
    int nx;
    int ny;
    int cnt = 0;
    int tmp;
    struct monst *mtmp;

    x = mon->mx;
    y = mon->my;
    
    if(mon->mconf != 0) {
        flag |= ALLOW_ALL;
        flag &= ~NOTONL;
    }

    for(nx = x - 1; nx <= x + 1; ++nx) {
        for(ny = y - 1; ny <= y + 1; ++ny) {
            if((nx != x) || (ny != y)) {
                if(isok(nx, ny) != 0) {
                    tmp = levl[nx][ny].typ;
                    if(tmp >= DOOR) {
                        if((nx == x)
                           || (ny == y)
                           || ((levl[x][y].typ != DOOR) && (tmp != DOOR))) {
                            info[cnt] = 0;
                            
                            if((nx == u.ux) && (ny == u.uy)) {
                                if((flag & ALLOW_U) == 0) {
                                    continue;
                                }
                                
                                info[cnt] = ALLOW_U;
                            }
                            else {
                                mtmp = m_at(nx, ny);
                                if(mtmp != 0) {
                                    if((flag & ALLOW_M) == 0) {
                                        continue;
                                    }
                                    
                                    info[cnt] = ALLOW_M;
                                }
                                
                                if(mtmp->mtame != 0) {
                                    if((flag & ALLOW_TM) == 0) {
                                        continue;
                                    }
                                    
                                    info[cnt] |= ALLOW_TM;
                                }
                            }
                            
                            if(sobj_at(CLOVE_OF_GARLIC, nx, ny) != 0) {
                                if((flag & NOGARLIC) != 0) {
                                    continue;
                                }
                                
                                info[cnt] |= NOGARLIC;
                            }
                            
                            if((sobj_at(SCR_SCARE_MONSTER, nx, ny) != 0)
                               || ((mon->mpeaceful == 0)
                                   && (sengr_at("Elbereth", nx, ny) != 0))) {
                                if((flag & ALLOW_SSM) == 0) {
                                    continue;
                                }
                                
                                info[cnt] |= ALLOW_SSM;
                            }
                            
                            if(sobj_at(ENORMOUS_ROCK, nx, ny) != 0) {
                                if((flag & ALLOW_ROCK) == 0) {
                                    continue;
                                }
                                
                                info[cnt] |= ALLOW_ROCK;
                            }
                            
                            if((Invis == 0) && (online(nx, ny) != 0)) {
                                if((flag & NOTONL) != 0) {
                                    continue;
                                }
                                
                                info[cnt] |= NOTONL;
                            }
                            
                            /* We cannot avoid traps of an unknown kind */
                            struct gen *gtmp = g_at(nx, ny, ftrap);
                            int tt;
                            
                            if(gtmp != NULL) {
                                tt = 1 << (gtmp->gflag & ~SEEN);
                                
                                if((mon->mtrapseen & tt) != 0) {
                                    if((flag & tt) == 0) {
                                        continue;
                                    }
                                    
                                    info[cnt] |= tt;
                                }
                            }

                            poss[cnt].x = nx;
                            poss[cnt].y = ny;
                            ++cnt;
                        }
                    }
                }
            }
        }
    }

    return cnt;
}
예제 #4
0
/* Returns 1 if monster died moving, 0 otherwise */
int dochug(struct monst *mtmp)
{
    struct permonst *mdat;
    int tmp = 0;

    if((mtmp->cham != 0) && (rn2(6) == 0)) {
        newcham(mtmp, &mons[(dlevel + 14) + rn2((CMNUM - 14) - dlevel)]);
    }

    mdat = mtmp->data;

    if(mdat->mlevel < 0) {
        panic("bad monster %c (%d)", mdat->mlet, mdat->mlevel);
    }

    if((((moves % 20) == 0) || (index("ViT", mdat->mlet) != 0))
       && (mtmp->mhp < mtmp->orig_hp)) {
        /* Regenerate monsters. */
        ++mtmp->mhp;
    }

    if(mtmp->mfroz != 0) {
        /* Frozen monsters don't do anything. */
        return 0;
    }

    if(mtmp->msleep != 0) {
        /* Wake up a monster, or get out of here. */
        if((cansee(mtmp->mx, mtmp->my) != 0)
	   && (Stealth == 0)
	   && ((index("NL", mdat->mlet) == 0)
	       || (rn2(50) == 0))
	   && ((Aggravate_monster != 0) 
	       || ((rn2(7) == 0) && (mtmp->mimic == 0)))) {
            mtmp->msleep = 0;
        }
        else {
            return 0;
        }
    }

    /* Not frozen or sleeping: wipe out texts written in the dust */
    wipe_engr_at(mtmp->mx, mtmp->my, 1);

    /* Confused monsters get unconfused with small probability */
    if((mtmp->mconf != 0) && (rn2(50) == 0)) {
        mtmp->mconf = 0;
    }

    /* Some monsters teleport */
    if((mtmp->mflee != 0)
       && (index("tNL", mdat->mlet) != 0) 
       && (rn2(40) == 0)) {
        rloc(mtmp);

        return 0;
    }

    if(mdat->mmove < rnd(6)) {
        return 0;
    }

    if((mtmp->mflee != 0)
       || (mtmp->mconf != 0)
       || ((index("BIuy", mdat->mlet) != 0) && (rn2(4) == 0))
       || ((mdat->mlet == 'L') 
           && (u.ugold == 0)
           && ((mtmp->mgold != 0) || (rn2(2) != 0)))
       || (dist(mtmp->mx, mtmp->my) > 2)
       || ((mtmp->mcansee == 0) && (rn2(4) == 0))
       || (mtmp->mpeaceful != 0)) {
        tmp = m_move(mtmp, 0);
        if((tmp != 0) && (mdat->mmove < 12)) {
            if(tmp == 2) {
                return 1;
            }
            else {
                return 0;
            }
        }
    }

    if(tmp == 2) {
        /* Monster died moving */
        return 1;
    }

    if((index("Ea", mdat->mlet) == 0) 
       && (dist(mtmp->mx, mtmp->my) < 3)
       && (mtmp->mpeaceful == 0)
       && (u.uhp > 0)
       && (sengr_at("Elbereth", u.ux, u.uy) == 0)
       && (sobj_at(SCR_SCARE_MONSTER, u.ux, u.uy) == 0)) {
        if(mhitu(mtmp) != 0) {
            /* Monster died (e.g. 'y' or 'F') */
            return 1;
        }   
    }
        
    /* Extra movement for fast monsters */
    if((mdat->mmove - 12) > rnd(12)) {
        tmp = m_move(mtmp, 1);
    }

    if(tmp == 2) {
        return 1;
    }
    else {
        return 0;
    }
}
예제 #5
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;
}