/* try to force a chest with your weapon */ int doforce(const struct nh_cmd_arg *arg) { struct obj *otmp; int c; const char *qbuf; if (!uwep_can_force()) return 0; if (u.utracked[tos_lock] && u.uoccupation_progress[tos_lock]) { if (turnstate.continue_message) pline(msgc_occstart, "You resume your attempt to force the lock."); one_occupation_turn(forcelock, "forcing the lock", occ_lock); return 1; } /* A lock is made only for the honest man, the thief will break it. */ u.utracked[tos_lock] = NULL; u.uoccupation_progress[tos_lock] = 0; for (otmp = level->objects[youmonst.mx][youmonst.my]; otmp; otmp = otmp->nexthere) if (Is_box(otmp)) { if (otmp->obroken || !otmp->olocked) { pline(msgc_cancelled, "There is %s here, but its lock is already %s.", doname(otmp), otmp->obroken ? "broken" : "unlocked"); continue; } qbuf = msgprintf( "There is %s here, force its lock?", safe_qbuf("", sizeof ("There is here, force its lock?"), doname(otmp), an(simple_typename(otmp->otyp)), "a box")); c = ynq(qbuf); if (c == 'q') return 0; if (c == 'n') continue; if (is_blade(uwep)) pline(msgc_occstart, "You force your %s into a crack and pry.", xname(uwep)); else pline(msgc_occstart, "You start bashing it with your %s.", xname(uwep)); u.utracked[tos_lock] = otmp; break; } if (u.utracked[tos_lock]) { one_occupation_turn(forcelock, "forcing the lock", occ_lock); return 1; } else { pline(msgc_cancelled, "You decide not to force the issue."); return 0; } }
/* * This routine changes the address of obj. Be careful not to call it * when there might be pointers around in unknown places. For now: only * when obj is in the inventory. */ int do_oname(const struct nh_cmd_arg *arg) { const char *qbuf, *buf; const char *aname; short objtyp; struct obj *obj; obj = getargobj(arg, nameable, "name"); if (!obj) return 0; qbuf = msgprintf("What do you want to name %s %s?", is_plural(obj) ? "these" : "this", safe_qbuf("", sizeof("What do you want to name these ?"), xname(obj), simple_typename(obj->otyp), is_plural(obj) ? "things" : "thing")); buf = getarglin(arg, qbuf); if (!*buf || *buf == '\033') return 0; /* strip leading and trailing spaces; unnames item if all spaces */ buf = msgmungspaces(buf); /* relax restrictions over proper capitalization for artifacts */ if ((aname = artifact_name(buf, &objtyp)) != 0 && objtyp == obj->otyp) buf = aname; char slipbuf[strlen(buf) + 1]; if (obj->oartifact) { pline("The artifact seems to resist the attempt."); return 0; } else if (restrict_name(obj, buf) || exist_artifact(obj->otyp, buf)) { int n = rn2((int)strlen(buf)); char c1, c2; strcpy(slipbuf, buf); c1 = lowc(buf[n]); do c2 = 'a' + rn2('z' - 'a' + 1); while (c1 == c2); slipbuf[n] = (slipbuf[n] == c1) ? c2 : highc(c2); /* keep same case */ pline("While engraving your %s slips.", body_part(HAND)); win_pause_output(P_MESSAGE); pline("You engrave: \"%s\".", slipbuf); buf = slipbuf; } oname(obj, buf); return 0; }
/* display a list of discovered artifacts; return their count */ int disp_artifact_discoveries( struct menulist *menu /* supplied by dodiscover() */ ) { int i, m, otyp; char buf[BUFSZ]; for (i = 0; i < NROFARTIFACTS; i++) { if (artidisco[i] == 0) break; /* empty slot implies end of list */ if (i == 0) add_menuheading(menu, "Artifacts"); m = artidisco[i]; otyp = artilist[m].otyp; sprintf(buf, " %s [%s %s]", artiname(m), align_str(artilist[m].alignment), simple_typename(otyp)); add_menutext(menu, buf); } return i; }
/* quick: use cursor && don't search for "more info" */ static int do_look(boolean quick, const struct nh_cmd_arg *arg) { const char *out_str; const char *firstmatch; int i, ans = 0, objplur = 0, is_in; coord cc; /* screen pos of unknown glyph */ boolean save_verbose; /* saved value of flags.verbose */ boolean from_screen; /* question from the screen */ struct nh_desc_buf descbuf; struct obj *otmp; if (arg->argtype & CMD_ARG_OBJ) { from_screen = FALSE; } else if (quick || (arg->argtype & CMD_ARG_POS)) { from_screen = TRUE; /* yes, we want to use the cursor */ } else { i = ynq("Specify unknown object by cursor?"); if (i == 'q') return 0; from_screen = (i == 'y'); } if (from_screen) { cc.x = u.ux; cc.y = u.uy; } else { if (arg->argtype & CMD_ARG_OBJ) { static const char allowall[] = { ALL_CLASSES, 0 }; out_str = simple_typename(getargobj(arg, allowall, "explain")->otyp); } else { out_str = getarglin(arg, "Specify what? (type the word)"); if (out_str[0] == '\0' || out_str[0] == '\033') return 0; } /* the ability to specify symbols is gone: it is simply impossible to know how the window port is displaying things (tiles?) and even if charaters are used it may not be possible to type them (utf8) */ checkfile(out_str, NULL, !(arg->argtype & CMD_ARG_OBJ), TRUE); return 0; } /* Save the verbose flag, we change it later. */ save_verbose = flags.verbose; flags.verbose = flags.verbose && !quick; /* * we're identifying from the screen. */ do { /* Reset some variables. */ firstmatch = NULL; objplur = 0; if (flags.verbose) pline("Please move the cursor to %s.", what_is_an_unknown_object); else pline("Pick an object."); ans = getargpos(arg, &cc, FALSE, what_is_an_unknown_object); if (ans == NHCR_CLIENT_CANCEL || cc.x < 0) { flags.verbose = save_verbose; if (flags.verbose) pline(quick ? "Never mind." : "Done."); return 0; /* done */ } flags.verbose = FALSE; /* only print long question once */ nh_describe_pos(cc.x, cc.y, &descbuf, &is_in); otmp = vobj_at(cc.x, cc.y); if (otmp && is_plural(otmp)) objplur = 1; out_str = ""; if (append_str(&out_str, descbuf.effectdesc, 0, 0)) if (!firstmatch) firstmatch = descbuf.effectdesc; if (append_str(&out_str, descbuf.invisdesc, 0, 0)) if (!firstmatch) firstmatch = descbuf.invisdesc; /* We already have a/an added by describe_mon; don't add it again, because that'll fail in cases like "Dudley's ghost" */ if (append_str(&out_str, descbuf.mondesc, 1, 0)) if (!firstmatch) firstmatch = descbuf.mondesc; if (append_str(&out_str, descbuf.objdesc, objplur, 0)) if (!firstmatch) firstmatch = descbuf.objdesc; if (append_str(&out_str, descbuf.trapdesc, 0, 0)) if (!firstmatch) firstmatch = descbuf.trapdesc; if (!descbuf.feature_described && append_str(&out_str, descbuf.bgdesc, 0, is_in)) if (!firstmatch) firstmatch = descbuf.bgdesc; /* Finally, print out our explanation. */ if (firstmatch) { pline("%s.", msgupcasefirst(out_str)); /* check the data file for information about this thing */ if (firstmatch && ans != NHCR_CONTINUE && (ans == NHCR_MOREINFO || ans == NHCR_MOREINFO_CONTINUE || !quick)) { checkfile(firstmatch, NULL, FALSE, ans == NHCR_MOREINFO || ans == NHCR_MOREINFO_CONTINUE); } } else { pline("I've never heard of such things."); } } while (ans == NHCR_CONTINUE || ans == NHCR_MOREINFO_CONTINUE); flags.verbose = save_verbose; if (!quick && flags.verbose) pline("Done."); return 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; }