Exemple #1
0
static void describe_bg(int x, int y, int bg, char *buf)
{
    if (!bg)
	return;
    
    switch(bg) {
	case S_altar:
	    if (!In_endgame(&u.uz))
		sprintf(buf, "%s altar",
		    align_str(Amask2align(level->locations[x][y].altarmask & ~AM_SHRINE)));
	    else
		sprintf(buf, "aligned altar");
	    break;
	    
	case S_ndoor:
	    if (is_drawbridge_wall(x, y) >= 0)
		strcpy(buf,"open drawbridge portcullis");
	    else if ((level->locations[x][y].doormask & ~D_TRAPPED) == D_BROKEN)
		strcpy(buf,"broken door");
	    else
		strcpy(buf,"doorway");
	    break;
	    
	case S_cloud:
	    strcpy(buf, Is_airlevel(&u.uz) ? "cloudy area" : "fog/vapor cloud");
	    break;
	    
	default:
	    strcpy(buf, defexplain[bg]);
	    break;
    }
}
Exemple #2
0
/*
 * Return true with x,y pointing to the drawbridge if x,y initially indicate
 * a drawbridge or drawbridge wall.
 */
boolean
find_drawbridge(int *x, int *y)
{
    int dir;

    if (IS_DRAWBRIDGE(levl[*x][*y].typ))
        return TRUE;
    dir = is_drawbridge_wall(*x,*y);
    if (dir >= 0) {
        switch(dir) {
        case DB_NORTH:
            (*y)++;
            break;
        case DB_SOUTH:
            (*y)--;
            break;
        case DB_EAST:
            (*x)--;
            break;
        case DB_WEST:
            (*x)++;
            break;
        }
        return TRUE;
    }
    return FALSE;
}
Exemple #3
0
/* pick a lock on a chest or door with a given object */
int
pick_lock(struct obj *pick, const struct nh_cmd_arg *arg)
{
    int picktyp, c;
    coord cc;
    schar dx, dy, dz;
    struct rm *door;
    struct obj *otmp;
    const char *qbuf;

    if (!getargdir(arg, NULL, &dx, &dy, &dz))
        return 0;
    cc.x = youmonst.mx + dx;
    cc.y = youmonst.my + dy;
    if (!isok(cc.x, cc.y))
        return 0;

    picktyp = pick->otyp;
    pick->lastused = moves;

    /* Check whether we're resuming an interrupted previous attempt.  For a
       floor pick, we have u.utracked[tos_lock] as a non-zeroobj and dx and dy
       as 0.  For a door, we have u.utracked_location[tl_lock] specifying the
       location and u.utracked[tos_lock] as &zeroobj. */
    if (u.uoccupation_progress[tos_lock] &&
        ((u.utracked_location[tl_lock].x == cc.x &&
          u.utracked_location[tl_lock].y == cc.y &&
          u.utracked[tos_lock] == &zeroobj) ||
         (dx == 0 && dy == 0 && u.utracked[tos_lock] != &zeroobj))) {
        static const char no_longer[] =
            "Unfortunately, you can no longer %s %s.";

        if (nohands(youmonst.data)) {
            const char *what = (picktyp == LOCK_PICK) ? "pick" : "key";

            if (picktyp == CREDIT_CARD)
                what = "card";
            pline(msgc_interrupted, no_longer, "hold the", what);
            return reset_pick();
        } else if (u.utracked[tos_lock] != &zeroobj && !can_reach_floor()) {
            pline(msgc_interrupted, no_longer, "reach the", "lock");
            return reset_pick();
        } else {
            const char *action = lock_action();

            if (turnstate.continue_message)
                pline(msgc_occstart, "You resume your attempt at %s.", action);

            one_occupation_turn(picklock, "picking the lock", occ_lock);
            return 1;
        }
    }

    if (nohands(youmonst.data)) {
        pline(msgc_cancelled, "You can't hold %s -- you have no hands!",
              doname(pick));
        return 0;
    }

    if ((picktyp != LOCK_PICK && picktyp != CREDIT_CARD &&
         picktyp != SKELETON_KEY)) {
        impossible("picking lock with object %d?", picktyp);
        return 0;
    }

    if (!dx && !dy) { /* pick lock on a container */
        const char *verb;
        boolean it;
        int count;

        if (dz < 0) {
            pline(msgc_cancelled, "There isn't any sort of lock up %s.",
                  Levitation ? "here" : "there");
            return 0;
        } else if (is_lava(level, youmonst.mx, youmonst.my)) {
            pline(msgc_cancelled, "Doing that would probably melt your %s.",
                  xname(pick));
            return 0;
        } else if (is_pool(level, youmonst.mx, youmonst.my) && !Underwater) {
            /* better YAFM - AIS */
            pline(msgc_cancelled,
                  "Canals might have locks, but this water doesn't.");
            return 0;
        }

        count = 0;
        c = 'n';        /* in case there are no boxes here */
        for (otmp = level->objects[cc.x][cc.y]; otmp; otmp = otmp->nexthere)
            if (Is_box(otmp)) {
                ++count;
                if (!can_reach_floor()) {
                    pline(msgc_cancelled, "You can't reach %s from up here.",
                          the(xname(otmp)));
                    return 0;
                }
                it = 0;
                if (otmp->obroken)
                    verb = "fix";
                else if (!otmp->olocked)
                    verb = "lock", it = 1;
                else if (picktyp != LOCK_PICK)
                    verb = "unlock", it = 1;
                else
                    verb = "pick";
                qbuf = msgprintf(
                    "There is %s here, %s %s?",
                    safe_qbuf("",
                              sizeof ("There is  here, unlock its lock?"),
                              doname(otmp), an(simple_typename(otmp->otyp)),
                              "a box"), verb, it ? "it" : "its lock");

                c = ynq(qbuf);
                if (c == 'q')
                    return 0;
                if (c == 'n')
                    continue;

                if (otmp->obroken) {
                    pline(msgc_cancelled,
                          "You can't fix its broken lock with %s.",
                          doname(pick));
                    return 0;
                } else if (picktyp == CREDIT_CARD && !otmp->olocked) {
                    /* credit cards are only good for unlocking */
                    pline(msgc_cancelled, "You can't do that with %s.",
                          doname(pick));
                    return 0;
                }

                u.utracked[tos_lock] = otmp;
                u.uoccupation_progress[tos_lock] = 0;
                break;
            }
        if (c != 'y') {
            if (!count)
                pline(msgc_cancelled,
                      "There doesn't seem to be any sort of lock here.");
            return 0;   /* decided against all boxes */
        }
    } else {    /* pick the lock in a door */
        struct monst *mtmp;

        if (u.utrap && u.utraptype == TT_PIT) {
            pline(msgc_cancelled,
                  "You can't reach over the edge of the pit.");
            return 0;
        }

        door = &level->locations[cc.x][cc.y];
        if ((mtmp = m_at(level, cc.x, cc.y)) && canseemon(mtmp)) {
            if (picktyp == CREDIT_CARD &&
                (mx_eshk(mtmp) || mtmp->data == &mons[PM_ORACLE]))
                verbalize(msgc_npcvoice, "No checks, no credit, no problem.");
            else
                pline(msgc_mispaste, "I don't think %s would appreciate that.",
                      mon_nam(mtmp));
            return 0;
        }
        if (mtmp && (mtmp->m_ap_type == M_AP_FURNITURE) &&
            (mtmp->mappearance == S_hcdoor || mtmp->mappearance == S_vcdoor) &&
            !Protection_from_shape_changers) {
            stumble_onto_mimic(mtmp, dx, dy);
            return 1;
        }
        if (!IS_DOOR(door->typ)) {
            if (is_drawbridge_wall(cc.x, cc.y) >= 0)
                pline(msgc_cancelled, "You %s no lock on the drawbridge.",
                      Blind ? "feel" : "see");
            else
                pline(msgc_mispaste, "You %s no door there.",
                      Blind ? "feel" : "see");
            return 0;
        }
        switch (door->doormask) {
        case D_NODOOR:
            pline(msgc_cancelled, "This doorway has no door.");
            return 0;
        case D_ISOPEN:
            pline(msgc_cancelled, "You cannot lock an open door.");
            return 0;
        case D_BROKEN:
            pline(msgc_cancelled, "This door is broken.");
            return 0;
        default:
            /* credit cards are only good for unlocking */
            if (picktyp == CREDIT_CARD && !(door->doormask & D_LOCKED)) {
                pline(msgc_cancelled,
                      "You can't lock a door with a credit card.");
                return 0;
            }

            /* At this point, the player knows that the door is a door, and
               whether it's locked, but not whether it's trapped; to do this,
               we set the mem_door_l flag and call map_background, which will
               clear it if necessary (i.e. not a door after all). */
            level->locations[cc.x][cc.y].mem_door_l = 1;
            map_background(cc.x, cc.y, TRUE);

            u.utracked[tos_lock] = &zeroobj;
            u.utracked_location[tl_lock] = cc;
            u.uoccupation_progress[tos_lock] = 0;
        }
    }

    one_occupation_turn(picklock, "picking the lock", occ_lock);
    return 1;
}
Exemple #4
0
/* So you want music... */
int
do_play_instrument(struct obj *instr, const struct nh_cmd_arg *arg)
{
    char c = 'y';
    const char *buf;
    int x, y;
    boolean ok;

    if (Underwater) {
        pline(msgc_cancelled, "You can't play music underwater!");
        return 0;
    }
    if (Upolyd && !can_blow_instrument(youmonst.data) &&
        (instr->otyp == BUGLE || instr->otyp == WOODEN_FLUTE ||
         instr->otyp == MAGIC_FLUTE || instr->otyp == TOOLED_HORN ||
         instr->otyp == FIRE_HORN || instr->otyp == FROST_HORN)) {
        pline(msgc_cancelled,
              "You are incapable of playing %s in your current form!",
              the(xname(instr)));
        return 0;
    }
    if (instr->otyp != LEATHER_DRUM && instr->otyp != DRUM_OF_EARTHQUAKE) {
        c = yn("Improvise?");
    }
    if (c == 'n') {
        if (u.uevent.uheard_tune == 2 && yn("Play the passtune?") == 'y') {
            buf = msg_from_string(gamestate.castle_tune);
        } else {
            /* Note: This is explicitly not getarglin(); we don't want
               command repeat to repeat the tune. */
            buf = getlin("What tune are you playing? [5 notes, A-G]", FALSE);
            if (*buf == '\033')
                buf = "";
            buf = msgmungspaces(buf);
            /* convert to uppercase and change any "H" to the expected "B" */
            buf = msgcaseconv(buf, highc_htob, highc_htob, highc_htob);
        }
        pline(msgc_occstart, "You extract a strange sound from %s!",
              the(xname(instr)));

        /* Check if there was the Stronghold drawbridge near and if the tune
           conforms to what we're waiting for. */
        if (Is_stronghold(&u.uz)) {
            exercise(A_WIS, TRUE);      /* just for trying */
            if (!strcmp(buf, gamestate.castle_tune)) {
                /* Search for the drawbridge */
                for (y = youmonst.my - 1; y <= youmonst.my + 1; y++)
                    for (x = youmonst.mx - 1; x <= youmonst.mx + 1; x++)
                        if (isok(x, y))
                            if (find_drawbridge(&x, &y)) {
                                /* tune now fully known */
                                u.uevent.uheard_tune = 2;
                                if (level->locations[x][y].typ ==
                                    DRAWBRIDGE_DOWN)
                                    close_drawbridge(x, y);
                                else
                                    open_drawbridge(x, y);
                                return 1;
                            }
            } else if (canhear()) {
                if (u.uevent.uheard_tune < 1)
                    u.uevent.uheard_tune = 1;
                /* Okay, it wasn't the right tune, but perhaps we can give the
                   player some hints like in the Mastermind game */
                ok = FALSE;
                for (y = youmonst.my - 1; y <= youmonst.my + 1 && !ok; y++)
                    for (x = youmonst.mx - 1; x <= youmonst.mx + 1 && !ok; x++)
                        if (isok(x, y))
                            if (IS_DRAWBRIDGE(level->locations[x][y].typ) ||
                                is_drawbridge_wall(x, y) >= 0)
                                ok = TRUE;
                if (ok) {       /* There is a drawbridge near */
                    int tumblers, gears;
                    boolean matched[5];

                    tumblers = gears = 0;
                    for (x = 0; x < 5; x++)
                        matched[x] = FALSE;

                    for (x = 0; x < (int)strlen(buf); x++)
                        if (x < 5) {
                            if (buf[x] == gamestate.castle_tune[x]) {
                                gears++;
                                matched[x] = TRUE;
                            } else
                                for (y = 0; y < 5; y++)
                                    if (!matched[y] &&
                                        buf[x] == gamestate.castle_tune[y] &&
                                        buf[y] != gamestate.castle_tune[y]) {
                                        tumblers++;
                                        matched[y] = TRUE;
                                        break;
                                    }
                        }
                    if (tumblers)
                        if (gears)
                            You_hear(msgc_hint,
                                     "%d tumbler%s click and %d gear%s turn.",
                                     tumblers, plur(tumblers), gears,
                                     plur(gears));
                        else
                            You_hear(msgc_hint, "%d tumbler%s click.", tumblers,
                                     plur(tumblers));
                    else if (gears) {
                        You_hear(msgc_hint, "%d gear%s turn.", gears,
                                 plur(gears));
                        /* could only get `gears == 5' by playing five correct
                           notes followed by excess; otherwise, tune would have 
                           matched above */
                        if (gears == 5)
                            u.uevent.uheard_tune = 2;
                    }
                }
            }
        }
        return 1;
    } else
        return do_improvisation(instr, arg);
}