Exemple #1
0
static void
savetrapchn(struct memfile *mf, struct trap *trap, struct level *lev)
{
    struct trap *trap2;
    unsigned short tflags;
    int count = 0;

    mfmagic_set(mf, TRAPCHAIN_MAGIC);
    for (trap2 = trap; trap2; trap2 = trap2->ntrap)
        count++;
    mwrite32(mf, count);

    for (; trap; trap = trap->ntrap) {
        /* To distinguish traps from each other in tags, we use x/y/z coords */
        mtag(mf,
             ledger_no(&lev->z) + ((int)trap->tx << 8) + ((int)trap->ty << 16),
             MTAG_TRAP);
        mwrite8(mf, trap->tx);
        mwrite8(mf, trap->ty);
        mwrite8(mf, trap->dst.dnum);
        mwrite8(mf, trap->dst.dlevel);
        mwrite8(mf, trap->launch.x);
        mwrite8(mf, trap->launch.y);
        tflags = (trap->ttyp << 11) | (trap->tseen << 10) |
            (trap->once << 9) | (trap->madeby_u << 8);
        mwrite16(mf, tflags);
        mwrite16(mf, trap->vl.v_launch_otyp);
    }
}
Exemple #2
0
/* extract a shopkeeper name for the given shop type */
static void nameshk (struct monst *shk, const char *const *nlp) {
    int i, trycnt, names_avail;
    const char *shname = 0;
    struct monst *mtmp;
    int name_wanted;
    s_level *sptr;

    if (nlp == shklight && In_mines(&u.uz)
            && (sptr = Is_special(&u.uz)) != 0 && sptr->flags.town) {
        /* special-case minetown lighting shk */
        shname = "Izchak";
        shk->female = false;
    } else {
        /* We want variation from game to game, without needing the save
           and restore support which would be necessary for randomization;
           try not to make too many assumptions about time_t's internals;
           use ledger_no rather than depth to keep mine town distinct. */
        int nseed = (int)((long)u.ubirthday / 257L);

        name_wanted = ledger_no(&u.uz) + (nseed % 13) - (nseed % 5);
        if (name_wanted < 0) name_wanted += (13 + 5);
        shk->female = name_wanted & 1;

        for (names_avail = 0; nlp[names_avail]; names_avail++)
            continue;

        for (trycnt = 0; trycnt < 50; trycnt++) {
            if (nlp == shktools) {
                shname = shktools[rn2(names_avail)];
                shk->female = (*shname == '_');
                if (shk->female) shname++;
            } else if (name_wanted < names_avail) {
                shname = nlp[name_wanted];
            } else if ((i = rn2(names_avail)) != 0) {
                shname = nlp[i - 1];
            } else if (nlp != shkgeneral) {
                nlp = shkgeneral;   /* try general names */
                for (names_avail = 0; nlp[names_avail]; names_avail++)
                    continue;
                continue;           /* next `trycnt' iteration */
            } else {
                shname = shk->female ? "Lucrezia" : "Dirk";
            }

            /* is name already in use on this level? */
            for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
                if (DEADMONSTER(mtmp) || (mtmp == shk) || !mtmp->isshk) continue;
                if (strcmp(ESHK(mtmp)->shknam, shname)) continue;
                break;
            }
            if (!mtmp) break;       /* new name */
        }
    }
    (void) strncpy(ESHK(shk)->shknam, shname, PL_NSIZ);
    ESHK(shk)->shknam[PL_NSIZ-1] = 0;
}
/**
 * save_regions :
 */
void
save_regions(struct memfile *mf, struct level *lev)
{
    int i, j;
    unsigned len1, len2;
    struct region *r;

    mfmagic_set(mf, REGION_MAGIC);
    mtag(mf, ledger_no(&lev->z), MTAG_REGION);
    mwrite32(mf, save_encode_32(moves, moves, moves));    /* timestamp */
    mwrite32(mf, lev->n_regions);

    /* Note: level regions don't have ID numbers, so we can't tag individual
       regions; instead, diff efficiency depends on the fact that regions tend
       to stay in the order and are typically inserted or deleted near the end
       of the list */
    for (i = 0; i < lev->n_regions; i++) {
        r = lev->regions[i];

        save_rect(mf, r->bounding_box);
        mwrite32(mf, r->attach_2_m);
        mwrite32(mf, r->effect_id);
        mwrite32(mf, r->arg);
        mwrite16(mf, r->nrects);
        for (j = 0; j < r->nrects; j++)
            save_rect(mf, r->rects[j]);
        mwrite16(mf, r->ttl);
        mwrite16(mf, r->expire_f);
        mwrite16(mf, r->can_enter_f);
        mwrite16(mf, r->enter_f);
        mwrite16(mf, r->can_leave_f);
        mwrite16(mf, r->leave_f);
        mwrite16(mf, r->inside_f);
        mwrite16(mf, r->n_monst);
        mwrite8(mf, r->player_flags);
        mwrite8(mf, r->attach_2_u);
        mwrite8(mf, r->visible);

        for (j = 0; j < r->n_monst; j++)
            mwrite32(mf, r->monsters[j]);

        len1 = r->enter_msg ? strlen(r->enter_msg) + 1 : 0;
        mwrite16(mf, len1);
        len2 = r->leave_msg ? strlen(r->leave_msg) + 1 : 0;
        mwrite16(mf, len2);

        if (len1 > 0)
            mwrite(mf, r->enter_msg, len1);

        if (len2 > 0)
            mwrite(mf, r->leave_msg, len2);
    }
}
/*
 * save_rooms : Save all the rooms on disk!
 */
void
save_rooms(struct memfile *mf, struct level *lev)
{
    short i;

    mfmagic_set(mf, ROOMS_MAGIC);       /* "RDAT" */
    mtag(mf, ledger_no(&lev->z), MTAG_ROOMS);
    /* First, write the number of rooms */
    mwrite32(mf, lev->nroom);
    for (i = 0; i < lev->nroom; i++)
        save_room(mf, &lev->rooms[i]);
}
/* Save all light sources of the given range. */
void
save_light_sources(struct memfile *mf, struct level *lev, int range)
{
    int count, actual;

    mtag(mf, 2 * (int)ledger_no(&lev->z) + range, MTAG_LIGHTS);
    count = maybe_write_ls(mf, lev, range, FALSE);
    mwrite32(mf, count);

    actual = maybe_write_ls(mf, lev, range, TRUE);
    if (actual != count)
        panic("counted %d light sources, wrote %d! [range=%d]", count, actual,
              range);
}
Exemple #6
0
STATIC_OVL boolean
uz_no_bones_level()
{
    extern d_level save_dlevel; /* in do.c */
    s_level *sptr;

    if (ledger_no(&save_dlevel))
        assign_level(&u.uz, &save_dlevel);

    return (boolean) (((sptr = uz_is_special()) != 0 && !sptr->boneid)
                      || !dungeons[u.uz.dnum].boneid
                      /* no bones on the last or multiway branch levels
                         in any dungeon (level 1 isn't multiway) */
                      || uz_is_botlevel()
                      || (uz_is_branchlev() && u.uz.dlevel > 1)
                      /* no bones in the invocation level */
                      || (uz_in_hell()
                          && u.uz.dlevel == dunlevs_in_uz_dungeon() - 1));
}
Exemple #7
0
static void
savedamage(struct memfile *mf, struct level *lev)
{
    struct damage *damageptr;
    unsigned int xl = 0;

    mtag(mf, ledger_no(&lev->z), MTAG_DAMAGE);

    for (damageptr = lev->damagelist; damageptr; damageptr = damageptr->next)
        xl++;
    mwrite32(mf, xl);

    for (damageptr = lev->damagelist; damageptr; damageptr = damageptr->next) {
        mtag(mf, damageptr->when, MTAG_DAMAGEVALUE);
        mwrite32(mf, damageptr->when);
        mwrite32(mf, damageptr->cost);
        mwrite8(mf, damageptr->place.x);
        mwrite8(mf, damageptr->place.y);
        mwrite8(mf, damageptr->typ);
    }
}
Exemple #8
0
/*
 *  save_worm()
 *
 *  Save the worm information for later use.  The count is the number
 *  of segments, including the dummy.  Called from save.c.
 */
void
save_worm(struct memfile *mf, struct level *lev)
{
    int i, count;
    struct wseg *curr;

    for (i = 1; i < MAX_NUM_WORMS; i++) {
        for (count = 0, curr = lev->wtails[i]; curr; curr = curr->nseg)
            count++;
        mtag(mf, (int)ledger_no(&lev->z) * MAX_NUM_WORMS + i, MTAG_WORMS);
        /* Save number of segments */
        mwrite32(mf, count);
        /* Save segment locations of the monster. */
        if (count) {
            for (curr = lev->wtails[i]; curr; curr = curr->nseg) {
                mwrite8(mf, curr->wx);
                mwrite8(mf, curr->wy);
            }
            mwrite32(mf, lev->wgrowtime[i]);
        }
    }
}
/* return 0 if still on level, 3 if not */
int
mlevel_tele_trap(struct monst *mtmp, struct trap *trap, boolean force_it,
                 int in_sight)
{
    int tt = trap->ttyp;
    const struct permonst *mptr = mtmp->data;

    if (mtmp == u.ustuck)       /* probably a vortex */
        return 0;       /* temporary? kludge */
    if (teleport_pet(mtmp, force_it)) {
        d_level tolevel;
        int migrate_typ = MIGR_RANDOM;

        if ((tt == HOLE || tt == TRAPDOOR)) {
            if (Is_stronghold(&u.uz)) {
                assign_level(&tolevel, &valley_level);
            } else if (Is_botlevel(&u.uz)) {
                if (in_sight && trap->tseen)
                    pline("%s avoids the %s.", Monnam(mtmp),
                          (tt == HOLE) ? "hole" : "trap");
                return 0;
            } else {
                get_level(&tolevel, depth(&u.uz) + 1);
            }
        } else if (tt == MAGIC_PORTAL) {
            if (In_endgame(&u.uz) &&
                (mon_has_amulet(mtmp) ||
                 is_home_elemental(&mtmp->dlevel->z, mptr))) {
                if (in_sight && mptr->mlet != S_ELEMENTAL) {
                    pline("%s seems to shimmer for a moment.", Monnam(mtmp));
                    seetrap(trap);
                }
                return 0;
            } else {
                assign_level(&tolevel, &trap->dst);
                migrate_typ = MIGR_PORTAL;
            }
        } else {        /* (tt == LEVEL_TELEP) */
            int nlev;

            if (mon_has_amulet(mtmp) || In_endgame(&u.uz)) {
                if (in_sight)
                    pline("%s seems very disoriented for a moment.",
                          Monnam(mtmp));
                return 0;
            }
            nlev = random_teleport_level();
            if (nlev == depth(&u.uz)) {
                if (in_sight)
                    pline("%s shudders for a moment.", Monnam(mtmp));
                return 0;
            }
            get_level(&tolevel, nlev);
        }

        if (in_sight) {
            pline("Suddenly, %s disappears out of sight.", mon_nam(mtmp));
            seetrap(trap);
        }
        migrate_to_level(mtmp, ledger_no(&tolevel), migrate_typ, NULL);
        return 3;       /* no longer on this level */
    }
    return 0;
}
Exemple #10
0
int
dosave()
{
#ifdef KEEP_SAVE
	/*WAC for reloading*/
	register int fd;
#endif

	clear_nhwindow(WIN_MESSAGE);
	if(yn("Really save?") == 'n') {
		clear_nhwindow(WIN_MESSAGE);
		if(multi > 0) nomul(0);
	} else {
		clear_nhwindow(WIN_MESSAGE);
		pline("Saving...");
#if defined(UNIX) || defined(VMS) || defined(__EMX__)
		program_state.done_hup = 0;
#endif
#ifdef KEEP_SAVE
                saverestore = FALSE;
                if (flags.keep_savefile)
                        if(yn("Really quit?") == 'n') saverestore = TRUE;
                if(dosave0() && !saverestore) {
#else
		if(dosave0()) {
#endif
			program_state.something_worth_saving = 0;
			u.uhp = -1;		/* universal game's over indicator */
			/* make sure they see the Saving message */
			display_nhwindow(WIN_MESSAGE, TRUE);
			exit_nhwindows("Be seeing you...");
			terminate(EXIT_SUCCESS);
	}
/*WAC redraw later
		else (void)doredraw();*/
	}
#ifdef KEEP_SAVE
	if (saverestore) {
/*WAC pulled this from pcmain.c - restore game from the file just saved*/
		fd = create_levelfile(0);
		if (fd < 0) {
			raw_print("Cannot create lock file");
		} else {
			hackpid = 1;
			write(fd, (genericptr_t) &hackpid, sizeof(hackpid));
			close(fd);
		}
#ifdef MFLOPPY
		level_info[0].where = ACTIVE;
#endif

		fd = restore_saved_game();
		if (fd >= 0) dorecover(fd);
		check_special_room(FALSE);
		flags.move = 0;
/*WAC correct these after restore*/
		if(flags.moonphase == FULL_MOON)
			change_luck(1);         
		if(flags.friday13)
			change_luck(-1);
		if(iflags.window_inited)
			clear_nhwindow(WIN_MESSAGE);
	}
	saverestore = FALSE;
#endif
	(void)doredraw();
	return 0;
}


#if defined(UNIX) || defined(VMS) || defined (__EMX__) || defined(WIN32)
/*ARGSUSED*/
void
hangup(sig_unused)  /* called as signal() handler, so sent at least one arg */
int sig_unused;
{
# ifdef NOSAVEONHANGUP
	(void) signal(SIGINT, SIG_IGN);
	clearlocks();
#  ifndef VMS
	terminate(EXIT_FAILURE);
#  endif
# else	/* SAVEONHANGUP */
	if (!program_state.done_hup++) {
	    if (program_state.something_worth_saving)
		(void) dosave0();
#  ifdef VMS
	    /* don't call exit when already within an exit handler;
	       that would cancel any other pending user-mode handlers */
	    if (!program_state.exiting)
#  endif
	    {
		clearlocks();
		terminate(EXIT_FAILURE);
	    }
	}
# endif
	return;
}
#endif

/* returns 1 if save successful */
int
dosave0()
{
	const char *fq_save;
	register int fd, ofd;
	xchar ltmp;
	d_level uz_save;
	char whynot[BUFSZ];

	if (!SAVEF[0])
		return 0;
	fq_save = fqname(SAVEF, SAVEPREFIX, 1);	/* level files take 0 */

#if defined(UNIX) || defined(VMS)
	(void) signal(SIGHUP, SIG_IGN);
#endif
#ifndef NO_SIGNAL
	(void) signal(SIGINT, SIG_IGN);
#endif

#if defined(MICRO) && defined(MFLOPPY)
	if (!saveDiskPrompt(0)) return 0;
#endif

	HUP if (iflags.window_inited) {
	    uncompress_area(fq_save, SAVEF);
	    fd = open_savefile();
	    if (fd > 0) {
		(void) close(fd);
		clear_nhwindow(WIN_MESSAGE);
		There("seems to be an old save file.");
		if (yn("Overwrite the old file?") == 'n') {
		    compress_area(fq_save, SAVEF);
#ifdef KEEP_SAVE
/*WAC don't restore if you didn't save*/
			saverestore = FALSE;
#endif
		    return 0;
		}
	    }
	}

	HUP mark_synch();	/* flush any buffered screen output */

	fd = create_savefile();
	if(fd < 0) {
		HUP pline("Cannot open save file.");
		(void) delete_savefile();	/* ab@unido */
		return(0);
	}

	vision_recalc(2);	/* shut down vision to prevent problems
				   in the event of an impossible() call */
	
	/* undo date-dependent luck adjustments made at startup time */
	if(flags.moonphase == FULL_MOON)	/* ut-sally!fletcher */
		change_luck(-1);		/* and unido!ab */
	if(flags.friday13)
		change_luck(1);
	if(iflags.window_inited)
	    HUP clear_nhwindow(WIN_MESSAGE);

#if defined(MICRO) && defined(TTY_GRAPHICS)
	if (!strncmpi("tty", windowprocs.name, 3)) {
	dotcnt = 0;
	dotrow = 2;
	curs(WIN_MAP, 1, 1);
	  putstr(WIN_MAP, 0, "Saving:");
	}
#endif
#ifdef MFLOPPY
	/* make sure there is enough disk space */
	if (iflags.checkspace) {
	    long fds, needed;

	    savelev(fd, ledger_no(&u.uz), COUNT_SAVE);
	    savegamestate(fd, COUNT_SAVE);
	    needed = bytes_counted;

	    for (ltmp = 1; ltmp <= maxledgerno(); ltmp++)
		if (ltmp != ledger_no(&u.uz) && level_info[ltmp].where)
		    needed += level_info[ltmp].size + (sizeof ltmp);
	    fds = freediskspace(fq_save);
	    if (needed > fds) {
		HUP {
		    There("is insufficient space on SAVE disk.");
		    pline("Require %ld bytes but only have %ld.", needed, fds);
		}
		flushout();
		(void) close(fd);
		(void) delete_savefile();
		return 0;
	    }

	    co_false();
	}
Exemple #11
0
	    }

	    co_false();
	}
#endif /* MFLOPPY */

	store_version(fd);
#ifdef STORE_PLNAME_IN_FILE
	bwrite(fd, (genericptr_t) plname, PL_NSIZ);
#endif
	ustuck_id = (u.ustuck ? u.ustuck->m_id : 0);
#ifdef STEED
	usteed_id = (u.usteed ? u.usteed->m_id : 0);
#endif

	savelev(fd, ledger_no(&u.uz), WRITE_SAVE | FREE_SAVE);
/*Keep things from beeing freed if not restoring*/
/*
#ifdef KEEP_SAVE
	if (saverestore) savegamestate(fd, WRITE_SAVE);
	else
#endif
*/
	savegamestate(fd, WRITE_SAVE | FREE_SAVE);

	/* While copying level files around, zero out u.uz to keep
	 * parts of the restore code from completely initializing all
	 * in-core data structures, since all we're doing is copying.
	 * This also avoids at least one nasty core dump.
	 */
	uz_save = u.uz;
Exemple #12
0
/* returns 1 if save successful */
int
dosave0(void)
{
    const char *fq_save;
    register int fd, ofd;
    xchar ltmp;
    d_level uz_save;
    char whynot[BUFSZ];

#ifdef WHEREIS_FILE
    delete_whereis();
#endif

    if (!SAVEF[0])
        return 0;
    fq_save = fqname(SAVEF, SAVEPREFIX, 1);	/* level files take 0 */

#if defined(UNIX) || defined(VMS)
    (void) signal(SIGHUP, SIG_IGN);
#endif
#ifndef NO_SIGNAL
    (void) signal(SIGINT, SIG_IGN);
#endif

#if defined(MICRO) && defined(MFLOPPY)
    if (!saveDiskPrompt(0)) return 0;
#endif

    HUP if (iflags.window_inited) {
        uncompress_area(fq_save, SAVEF);
        fd = open_savefile();
        if (fd > 0) {
            (void) close(fd);
            clear_nhwindow(WIN_MESSAGE);
            There("seems to be an old save file.");
            if (yn("Overwrite the old file?") == 'n') {
                compress_area(fq_save, SAVEF);
                return 0;
            }
        }
    }

    HUP mark_synch();	/* flush any buffered screen output */

    fd = create_savefile();
    if(fd < 0) {
        HUP pline("Cannot open save file.");
        (void) delete_savefile();	/* ab@unido */
        return(0);
    }

    vision_recalc(2);	/* shut down vision to prevent problems
				   in the event of an impossible() call */

    /* undo date-dependent luck adjustments made at startup time */
    if(flags.moonphase == FULL_MOON)	/* ut-sally!fletcher */
        change_luck(-1);		/* and unido!ab */
    if(flags.friday13)
        change_luck(1);
    if(iflags.window_inited)
        HUP clear_nhwindow(WIN_MESSAGE);

#ifdef MICRO
    dotcnt = 0;
    dotrow = 2;
    curs(WIN_MAP, 1, 1);
    if (strncmpi("X11", windowprocs.name, 3))
        putstr(WIN_MAP, 0, "Saving:");
#endif
#ifdef MFLOPPY
    /* make sure there is enough disk space */
    if (iflags.checkspace) {
        long fds, needed;

        savelev(fd, ledger_no(&u.uz), COUNT_SAVE);
        savegamestate(fd, COUNT_SAVE);
        needed = bytes_counted;

        for (ltmp = 1; ltmp <= maxledgerno(); ltmp++)
            if (ltmp != ledger_no(&u.uz) && level_info[ltmp].where)
                needed += level_info[ltmp].size + (sizeof ltmp);
        fds = freediskspace(fq_save);
        if (needed > fds) {
            HUP {
                There("is insufficient space on SAVE disk.");
                pline("Require %ld bytes but only have %ld.", needed, fds);
            }
            flushout();
            (void) close(fd);
            (void) delete_savefile();
            return 0;
        }
Exemple #13
0
void
savelev(struct memfile *mf, xchar levnum)
{
    int x, y;
    unsigned int lflags;
    struct level *lev = levels[levnum];

    /* The purge_monsters count refers to monsters on the current level. */
    if (iflags.purge_monsters && levnum == ledger_no(&u.uz)) {
        /* purge any dead monsters (necessary if we're starting a panic save
           rather than a normal one, or sometimes when changing levels without
           taking time -- e.g. create statue trap then immediately level
           teleport) */
        dmonsfree(lev);
    }

    /* mtagging for this already done in save_game */
    mfmagic_set(mf, LEVEL_MAGIC);

    mwrite8(mf, lev->z.dnum);
    mwrite8(mf, lev->z.dlevel);
    mwrite(mf, lev->levname, sizeof (lev->levname));

    for (x = 0; x < COLNO; x++)
        for (y = 0; y < ROWNO; y++)
            save_location(mf, &lev->locations[x][y]);

    mwrite32(mf, lev->lastmoves);
    mwrite(mf, &lev->upstair, sizeof (stairway));
    mwrite(mf, &lev->dnstair, sizeof (stairway));
    mwrite(mf, &lev->upladder, sizeof (stairway));
    mwrite(mf, &lev->dnladder, sizeof (stairway));
    mwrite(mf, &lev->sstairs, sizeof (stairway));
    mwrite(mf, &lev->updest, sizeof (dest_area));
    mwrite(mf, &lev->dndest, sizeof (dest_area));
    mwrite8(mf, lev->flags.nfountains);
    mwrite8(mf, lev->flags.nsinks);

    lflags =
        (lev->flags.has_shop << 31) | (lev->flags.has_vault << 30) |
        (lev->flags.has_zoo << 29) | (lev->flags.has_court << 28) |
        (lev->flags.has_morgue << 27) | (lev->flags.has_beehive << 26) |
        (lev->flags.has_barracks << 25) | (lev->flags.has_temple << 24) |
        (lev->flags.has_swamp << 23) | (lev->flags.noteleport << 22) |
        (lev->flags.hardfloor << 21) | (lev->flags.nommap << 20) |
        (lev->flags.hero_memory << 19) | (lev->flags.shortsighted << 18) |
        (lev->flags.graveyard << 17) | (lev->flags.is_maze_lev << 16) |
        (lev->flags.is_cavernous_lev << 15) | (lev->flags.arboreal << 14) |
        (lev->flags.forgotten << 13);
    mwrite32(mf, lflags);
    mwrite(mf, lev->doors, sizeof (lev->doors));
    save_rooms(mf, lev);        /* no dynamic memory to reclaim */

    /* must be saved before mons, objs, and buried objs */
    save_timers(mf, lev, RANGE_LEVEL);
    save_light_sources(mf, lev, RANGE_LEVEL);

    savemonchn(mf, lev->monlist);
    save_worm(mf, lev); /* save worm information */
    savetrapchn(mf, lev->lev_traps, lev);
    saveobjchn(mf, lev->objlist);
    saveobjchn(mf, lev->buriedobjlist);
    saveobjchn(mf, lev->billobjs);
    save_engravings(mf, lev);
    savedamage(mf, lev);
    save_regions(mf, lev);
}
Exemple #14
0
/* extract a shopkeeper name for the given shop type */
static void
nameshk(struct monst *shk, const char *const *nlp, struct level *lev)
{
    int i, trycnt, names_avail;
    const char *shname = 0;
    struct monst *mtmp;
    int name_wanted;
    s_level *sptr;

    if (nlp == shklight && In_mines(&lev->z)
        && (sptr = Is_special(&lev->z)) != 0 && sptr->flags.town) {
        /* special-case minetown lighting shk */
        shname = "Izchak";
        shk->female = FALSE;
    } else {
        /* We want variation from game to game, without needing the save and
           restore support which would be necessary for randomization; thus use
           ubirthday for deterministic random numbers, and use ledger_no rather
           than depth to keep mine town distinct. */
        int nseed = ((unsigned)u.ubirthday / 257U);

        name_wanted = ledger_no(&lev->z) + (nseed % 13) - (nseed % 5);
        if (name_wanted < 0)
            name_wanted += (13 + 5);
        shk->female = name_wanted & 1;

        for (names_avail = 0; nlp[names_avail]; names_avail++)
            continue;

        for (trycnt = 0; trycnt < 50; trycnt++) {
            if (nlp == shktools) {
                shname = shktools[rn2(names_avail)];
                shk->female = (*shname == '_');
                if (shk->female)
                    shname++;
            } else if (name_wanted < names_avail) {
                shname = nlp[name_wanted];
            } else if ((i = rn2(names_avail)) != 0) {
                shname = nlp[i - 1];
            } else if (nlp != shkgeneral) {
                nlp = shkgeneral;       /* try general names */
                for (names_avail = 0; nlp[names_avail]; names_avail++)
                    continue;
                continue;       /* next `trycnt' iteration */
            } else {
                shname = shk->female ? "Lucrezia" : "Dirk";
            }

            /* is name already in use on this level? */
            for (mtmp = lev->monlist; mtmp; mtmp = mtmp->nmon) {
                if (DEADMONSTER(mtmp) || (mtmp == shk) || !mx_eshk(mtmp))
                    continue;
                if (mx_name(mtmp) && strcmp(mx_name(mtmp), shname))
                    continue;
                break;
            }
            if (!mtmp)
                break;  /* new name */
        }
    }
    christen_monst(shk, shname);
}
Exemple #15
0
/* called when you move to another level
 * pets_only: true for ascension or final escape */
void
keepdogs(boolean pets_only)
{
    struct monst *mtmp, *mtmp2;
    struct obj *obj;
    int num_segs;
    boolean stay_behind;

    for (mtmp = level->monlist; mtmp; mtmp = mtmp2) {
        mtmp2 = mtmp->nmon;
        if (DEADMONSTER(mtmp))
            continue;
        if (pets_only && !mtmp->mtame)
            continue;
        if (((monnear(mtmp, u.ux, u.uy) && levl_follower(mtmp)) ||
             (mtmp == u.usteed) ||
             /* the wiz will level t-port from anywhere to chase the amulet; if
                you don't have it, will chase you only if in range. -3. */
             (Uhave_amulet && mtmp->iswiz))
            && ((!mtmp->msleeping && mtmp->mcanmove)
                /* eg if level teleport or new trap, steed has no control to
                   avoid following */
                || (mtmp == u.usteed))
            /* monster won't follow if it hasn't noticed you yet */
            && !(mtmp->mstrategy & STRAT_WAITFORU)) {
            stay_behind = FALSE;
            if (!pets_only && mtmp->mtame && mtmp->meating) {
                if (canseemon(mtmp))
                    pline("%s is still eating.", Monnam(mtmp));
                stay_behind = TRUE;
            } else if (mon_has_amulet(mtmp)) {
                if (canseemon(mtmp))
                    pline("%s seems very disoriented for a moment.",
                          Monnam(mtmp));
                stay_behind = TRUE;
            } else if (!pets_only && mtmp->mtame && mtmp->mtrapped) {
                if (canseemon(mtmp))
                    pline("%s is still trapped.", Monnam(mtmp));
                stay_behind = TRUE;
            }
            if (mtmp == u.usteed)
                stay_behind = FALSE;

            if (stay_behind) {
                if (mtmp->mleashed) {
                    pline("%s leash suddenly comes loose.", humanoid(mtmp->data)
                          ? (mtmp->female ? "Her" : "His")
                          : "Its");
                    m_unleash(mtmp, FALSE);
                }
                continue;
            }
            if (mtmp->isshk)
                set_residency(mtmp, TRUE);

            if (mtmp->wormno) {
                int cnt;

                /* NOTE: worm is truncated to # segs = max wormno size */
                cnt = count_wsegs(mtmp);
                num_segs = min(cnt, MAX_NUM_WORMS - 1);
                wormgone(mtmp);
            } else
                num_segs = 0;

            /* set minvent's obj->no_charge to 0 */
            for (obj = mtmp->minvent; obj; obj = obj->nobj) {
                if (Has_contents(obj))
                    picked_container(obj);      /* does the right thing */
                obj->no_charge = 0;
            }

            relmon(mtmp);
            newsym(mtmp->mx, mtmp->my);
            mtmp->mx = COLNO;    /* avoid mnexto()/MON_AT() problem */
            mtmp->my = ROWNO;
            mtmp->wormno = num_segs;
            mtmp->mlstmv = moves;
            mtmp->nmon = turnstate.migrating_pets;
            turnstate.migrating_pets = mtmp;
        } else if (mtmp->iswiz) {
            /* we want to be able to find him when his next resurrection chance
               comes up, but have him resume his present location if player
               returns to this level before that time */
            migrate_to_level(mtmp, ledger_no(&u.uz), MIGR_EXACT_XY, NULL);
        } else if (mtmp->mleashed) {
            /* this can happen if your quest leader ejects you from the "home"
               level while a leashed pet isn't next to you */
            pline("%s leash goes slack.", s_suffix(Monnam(mtmp)));
            m_unleash(mtmp, FALSE);
        }
    }
}