예제 #1
0
/* Returns an absolute depth */
int
random_teleport_level(void)
{
    int nlev, max_depth, min_depth, cur_depth = (int)depth(&u.uz);

    if (!rn2(5) || Is_knox(&u.uz))
        return cur_depth;

    if (In_endgame(&u.uz))      /* only happens in wizmode */
        return cur_depth;

    /* What I really want to do is as follows: -- If in a dungeon that goes
       down, the new level is to be restricted to [top of parent, bottom of
       current dungeon] -- If in a dungeon that goes up, the new level is to be 
       restricted to [top of current dungeon, bottom of parent] -- If in a
       quest dungeon or similar dungeon entered by portals, the new level is to 
       be restricted to [top of current dungeon, bottom of current dungeon] The 
       current behavior is not as sophisticated as that ideal, but is still
       better what we used to do, which was like this for players but different 
       for monsters for no obvious reason.  Currently, we must explicitly check 
       for special dungeons.  We check for Knox above; endgame is handled in
       the caller due to its different message ("disoriented"). --KAA 3.4.2:
       explicitly handle quest here too, to fix the problem of monsters
       sometimes level teleporting out of it into main dungeon. Also prevent
       monsters reaching the Sanctum prior to invocation. */
    min_depth = In_quest(&u.uz) ? dungeons[u.uz.dnum].depth_start : 1;
    max_depth =
        dunlevs_in_dungeon(&u.uz) + (dungeons[u.uz.dnum].depth_start - 1);
    /* can't reach the Sanctum if the invocation hasn't been performed */
    if (Inhell && !u.uevent.invoked)
        max_depth -= 1;

    /* Get a random value relative to the current dungeon */
    /* Range is 1 to current+3, current not counting */
    nlev = rn2(cur_depth + 3 - min_depth) + min_depth;
    if (nlev >= cur_depth)
        nlev++;

    if (nlev > max_depth) {
        nlev = max_depth;
        /* teleport up if already on bottom */
        if (Is_botlevel(&u.uz))
            nlev -= rnd(3);
    }
    if (nlev < min_depth) {
        nlev = min_depth;
        if (nlev == cur_depth) {
            nlev += rnd(3);
            if (nlev > max_depth)
                nlev = max_depth;
        }
    }
    return nlev;
}
예제 #2
0
/* 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;
}
예제 #3
0
파일: teleport.c 프로젝트: FredrIQ/nhfourk
/* Returns an absolute depth */
int
random_teleport_level(void)
{
    int nlev, max_depth, min_depth, cur_depth = (int)depth(&u.uz);

    if (Is_knox(&u.uz) || !rn2_on_rng(5, rng_levport_results))
        return cur_depth;

    if (In_endgame(&u.uz))      /* only happens in wizmode */
        return cur_depth;

    /*
     * What I really want to do is as follows:
     * -- If in a dungeon that goes down, the new level is to be restricted to
     *    [top of parent, bottom of current dungeon]
     * -- If in a dungeon that goes up, the new level is to be restricted to
     *    [top of current dungeon, bottom of parent]
     * -- If in a quest dungeon or similar dungeon entered by portals, the new
     *    level is to be restricted to [top of current dungeon, bottom of current
     *    dungeon]
     *
     * The current behavior is not as sophisticated as that ideal, but is still
     * better what we used to do, which was like this for players but different
     * for monsters for no obvious reason.  Currently, we must explicitly check
     * for special dungeons.  We check for Knox above; endgame is handled in the
     * caller due to its different message ("disoriented").
     *
     * -- KAA 3.4.2: explicitly handle quest here too, to fix the problem of
     * monsters sometimes level teleporting out of it into main dungeon. Also
     * prevent monsters reaching the Sanctum prior to invocation.
     */
    if (In_quest(&u.uz)) {
        int bottom = dunlevs_in_dungeon(&u.uz),
            qlocate_depth = qlocate_level.dlevel;
        /* if hero hasn't reached the middle locate level yet,
           no one can randomly teleport past it */
        if (dunlev_reached(&u.uz) < qlocate_depth)
            bottom = qlocate_depth;
        min_depth = find_dungeon(&u.uz).depth_start;
        max_depth = bottom + (find_dungeon(&u.uz).depth_start - 1);
    } else {
        min_depth = 1;
        max_depth = dunlevs_in_dungeon(&u.uz) +
            (find_dungeon(&u.uz).depth_start - 1);
        /* can't reach the Sanctum if the invocation hasn't been performed */
        if (Inhell && !u.uevent.invoked)
            max_depth -= 1;
    }

    /* Get a random value relative to the current dungeon */
    /* Range is 1 to current+3, current not counting */
    nlev = rn2_on_rng(cur_depth + 3 - min_depth, rng_levport_results) +
        min_depth;
    if (nlev >= cur_depth)
        nlev++;

    if (nlev > max_depth) {
        nlev = max_depth;
        /* teleport up if already on bottom */
        if (Is_botlevel(&u.uz))
            nlev -= rnd(3);
    }
    if (nlev < min_depth) {
        nlev = min_depth;
        if (nlev == cur_depth) {
            nlev += rnd(3);
            if (nlev > max_depth)
                nlev = max_depth;
        }
    }
    return nlev;
}