Пример #1
0
/* build a level name for historic events
 * in_or_on = TRUE: "On T:12345 you killed Kenny ..."
 *   - in The Castle
 *   - on level 3 of Sokoban
 *   - on level 45 in Gehennom
 * in_or_on = FALSE: "On T:12345 you reached ..."
 *   - The Castle
 *   - level 3 of The Quest
 *   - level 12 in The Dungeons of Doom
 * */
const char *
hist_lev_name(const d_level * l, boolean in_or_on)
{
    const char *hlnbuf;

    if (Is_astralevel(l))
        hlnbuf = "on the Astral Plane";
    else if (Is_waterlevel(l))
        hlnbuf = "on the Plane of Water";
    else if (Is_firelevel(l))
        hlnbuf = "on the Plane of Fire";
    else if (Is_airlevel(l))
        hlnbuf = "on the Plane of Air";
    else if (Is_earthlevel(l))
        hlnbuf = "on the Plane of Earth";
    else if (Is_knox(l))
        hlnbuf = "in Fort Ludios";
    else if (Is_stronghold(l))
        hlnbuf = "in The Castle";
    else if (Is_valley(l))
        hlnbuf = "in The Valley of the Dead";
    else
        hlnbuf = msgprintf("on level %d of %s", l->dlevel,
                           find_dungeon(l).dname);

    if (!in_or_on)
        hlnbuf += 3;

    return hlnbuf;
}
Пример #2
0
/* provide the name of the current level */
int
describe_level(char *buf)
{
    int ret = 1;

    if (Is_knox(&u.uz))
        sprintf(buf, "%s", find_dungeon(&u.uz).dname);
    else if (In_quest(&u.uz))
        sprintf(buf, "Home:%d", dunlev(&u.uz));
    else if (In_endgame(&u.uz))
        sprintf(buf, Is_astralevel(&u.uz) ? "Astral Plane" : "End Game");
    else if (In_mines(&u.uz))
        sprintf(buf, "Mines:%d", depth(&u.uz));
    else if (In_sokoban(&u.uz))
        sprintf(buf, "Sokoban:%d", depth(&u.uz));
    else if (Is_valley(&u.uz))
        sprintf(buf, "Valley:%d", depth(&u.uz));
    else if (In_hell(&u.uz))
        sprintf(buf, "Gehennom:%d", depth(&u.uz));
    else if (In_V_tower(&u.uz))
        sprintf(buf, "Tower:%d", depth(&u.uz));
    else
        sprintf(buf, "Dungeons:%d", depth(&u.uz)), (ret = 0);
    return ret;
}
Пример #3
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;
}
Пример #4
0
void
level_tele_impl(boolean wizard_tele)
{
    int newlev;
    d_level newlevel;
    const char *escape_by_flying = 0;   /* when surviving dest of -N */
    boolean force_dest = FALSE;
    const char *buf, *killer = NULL;

    if ((Uhave_amulet || In_endgame(&u.uz) || In_sokoban(&u.uz))
        && !wizard_tele) {
        pline("You feel very disoriented for a moment.");
        return;
    }
    if ((Teleport_control && !Stunned) || wizard_tele) {
        int trycnt = 0;
        const char *qbuf = "To what level do you want to teleport?";
        do {
            if (++trycnt == 2) {
                if (wizard_tele)
                    qbuf = msgcat(qbuf, " [type a number or ? for a menu]");
                else
                    qbuf = msgcat(qbuf, " [type a number]");
            }
            buf = getlin(qbuf, FALSE);
            if (!strcmp(buf, "\033")) { /* cancelled */
                if (Confusion && rnl(5)) {
                    pline("Oops...");
                    goto random_levtport;
                }
                return;
            } else if (!strcmp(buf, "*")) {
                goto random_levtport;
            } else if (Confusion && rnl(5)) {
                pline("Oops...");
                goto random_levtport;
            }

            if (wizard_tele && !strcmp(buf, "?")) {
                schar destlev = 0;
                xchar destdnum = 0;

                if ((newlev = (int)print_dungeon(TRUE, &destlev, &destdnum))) {
                    newlevel.dnum = destdnum;
                    newlevel.dlevel = destlev;
                    if (In_endgame(&newlevel) && !In_endgame(&u.uz)) {
                        const char *dest = "Destination is earth level";
                        if (!Uhave_amulet) {
                            struct obj *obj;

                            obj = mksobj(level, AMULET_OF_YENDOR, TRUE, FALSE,
                                         rng_main);
                            if (obj) {
                                addinv(obj);
                                dest = msgcat(dest, " with the amulet");
                            }
                        }
                        assign_level(&newlevel, &earth_level);
                        pline("%s.", dest);
                    }
                    force_dest = TRUE;
                } else
                    return;
            } else if ((newlev = lev_by_name(buf)) == 0)
                newlev = atoi(buf);
        } while (!newlev && !digit(buf[0]) && (buf[0] != '-' || !digit(buf[1]))
                 && trycnt < 10);

        /* no dungeon escape via this route */
        if (newlev == 0) {
            if (trycnt >= 10)
                goto random_levtport;
            if (ynq("Go to Nowhere.  Are you sure?") != 'y')
                return;
            pline("You %s in agony as your body begins to warp...",
                  is_silent(youmonst.data) ? "writhe" : "scream");
            win_pause_output(P_MESSAGE);
            pline("You cease to exist.");
            if (invent)
                pline("Your possessions land on the %s with a thud.",
                      surface(u.ux, u.uy));
            done(DIED, "committed suicide");
            pline("An energized cloud of dust begins to coalesce.");
            pline("Your body rematerializes%s.",
                  invent ? ", and you gather up all your possessions" : "");
            return;
        }

        /* if in Knox and the requested level > 0, stay put. we let negative
           values requests fall into the "heaven" loop. */
        if (Is_knox(&u.uz) && newlev > 0) {
            pline("You shudder for a moment.");
            return;
        }
        /* if in Quest, the player sees "Home 1", etc., on the status line,
           instead of the logical depth of the level.  controlled level
           teleport request is likely to be relativized to the status line, and
           consequently it should be incremented to the value of the logical
           depth of the target level. we let negative values requests fall into
           the "heaven" loop. */
        if (In_quest(&u.uz) && newlev > 0)
            newlev = newlev + find_dungeon(&u.uz).depth_start - 1;
    } else {    /* involuntary level tele */
    random_levtport:
        newlev = random_teleport_level();
        if (newlev == depth(&u.uz)) {
            pline("You shudder for a moment.");
            return;
        }
    }

    if (!next_to_u()) {
        pline("You shudder for a moment.");
        return;
    }

    if (In_endgame(&u.uz)) {    /* must already be wizard */
        int llimit = dunlevs_in_dungeon(&u.uz);

        if (newlev >= 0 || newlev <= -llimit) {
            pline("You can't get there from here.");
            return;
        }
        newlevel.dnum = u.uz.dnum;
        newlevel.dlevel = llimit + newlev;
        schedule_goto(&newlevel, FALSE, FALSE, 0, NULL, NULL);
        return;
    }

    if (newlev < 0 && !force_dest) {
        if (*u.ushops0) {
            /* take unpaid inventory items off of shop bills */
            in_mklev = TRUE;    /* suppress map update */
            u_left_shop(u.ushops0, TRUE);
            /* you're now effectively out of the shop */
            *u.ushops0 = *u.ushops = '\0';
            in_mklev = FALSE;
        }
        if (newlev <= -10) {
            pline("You arrive in heaven.");
            verbalize("Thou art early, but we'll admit thee.");
            killer = "went to heaven prematurely";
        } else if (newlev == -9) {
            pline("You feel deliriously happy. ");
            pline("(In fact, you're on Cloud 9!) ");
            win_pause_output(P_MESSAGE);
        } else
            pline("You are now high above the clouds...");

        if (killer) {
            ;   /* arrival in heaven is pending */
        } else if (Levitation) {
            escape_by_flying = "float gently down to earth";
        } else if (Flying) {
            escape_by_flying = "fly down to the ground";
        } else {
            pline("Unfortunately, you don't know how to fly.");
            pline("You plummet a few thousand feet to your death.");
            killer = msgcat_many("teleported out of the dungeon and fell to ",
                                 uhis(), " death", NULL);
        }
    }

    if (killer) {       /* the chosen destination was not survivable */
        d_level lsav;

        /* set specific death location; this also suppresses bones */
        lsav = u.uz;    /* save current level, see below */
        u.uz.dnum = 0;  /* main dungeon */
        u.uz.dlevel = (newlev <= -10) ? -10 : 0;        /* heaven or surface */
        done(DIED, killer);
        /* can only get here via life-saving (or declining to die in
           explore|debug mode); the hero has now left the dungeon... */
        escape_by_flying = "find yourself back on the surface";
        u.uz = lsav;    /* restore u.uz so escape code works */
    }

    /* calls done(ESCAPED) if newlevel==0 */
    if (escape_by_flying) {
        pline("You %s.", escape_by_flying);
        done(ESCAPED, "teleported to safety");
    } else if (u.uz.dnum == medusa_level.dnum &&
               newlev >= (find_dungeon(&u.uz).depth_start +
                          dunlevs_in_dungeon(&u.uz))) {
        if (!(wizard_tele && force_dest))
            find_hell(&newlevel);
    } else {
        /* if invocation did not yet occur, teleporting into the last level of
           Gehennom is forbidden. */
        if (!wizard_tele)
            if (Inhell && !u.uevent.invoked &&
                newlev >= (find_dungeon(&u.uz).depth_start +
                           dunlevs_in_dungeon(&u.uz) - 1)) {
                newlev = (find_dungeon(&u.uz).depth_start +
                          dunlevs_in_dungeon(&u.uz) - 2);
                pline("Sorry...");
            }
        /* no teleporting out of quest dungeon */
        if (In_quest(&u.uz) && newlev < depth(&qstart_level))
            newlev = depth(&qstart_level);
        /* the player thinks of levels purely in logical terms, so we must
           translate newlev to a number relative to the current dungeon. */
        if (!(wizard_tele && force_dest))
            get_level(&newlevel, newlev);
    }
    schedule_goto(&newlevel, FALSE, FALSE, 0, NULL, NULL);
    /* in case player just read a scroll and is about to be asked to call it
       something, we can't defer until the end of the turn */
    if (!flags.mon_moving)
        deferred_goto();
}
Пример #5
0
/* 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;
}