int dotalk(const struct nh_cmd_arg *arg) { struct monst *mtmp; int tx, ty; struct obj *otmp; schar dx; schar dy; schar dz; if (!getargdir(arg, NULL, &dx, &dy, &dz)) { /* decided not to chat */ return 0; } if (is_silent(youmonst.data)) { pline("As %s, you cannot speak.", an(youmonst.data->mname)); return 0; } if (Strangled) { pline("You can't speak. You're choking!"); return 0; } if (Engulfed) { pline("They won't hear you out there."); return 0; } if (Underwater) { pline("Your speech is unintelligible underwater."); return 0; } if (!Blind && (otmp = shop_object(u.ux, u.uy)) != NULL) { /* standing on something in a shop and chatting causes the shopkeeper to describe the price(s). This can inhibit other chatting inside a shop, but that shouldn't matter much. shop_object() returns an object iff inside a shop and the shopkeeper is present and willing (not angry) and able (not asleep) to speak and the position contains any objects other than just gold. */ price_quote(otmp); return 1; } if (u.usteed && dz > 0) { if (!u.usteed->mcanmove || u.usteed->msleeping) { pline("Your steed remains silent..."); return 0; } return domonnoise(u.usteed); } if (dz) { pline("They won't hear you %s there.", dz < 0 ? "up" : "down"); return 0; } if (dx == 0 && dy == 0) { if (u.umonnum == PM_ETTIN) { pline("You discover that your other head makes boring conversation."); return 0; } pline("Talking to yourself is a bad habit for a dungeoneer."); return 0; } tx = u.ux + dx; ty = u.uy + dy; if (!isok(tx, ty)) { pline("You call out into the abyss, but nobody hears you."); return 0; } mtmp = m_at(level, tx, ty); /* Do we try to close a door on the square? We do if a) the square is known by the player to be a doorway, b) there's no invisible-I marker there, c) there's no monster in a chattable state there. */ if (!mtmp || mtmp->mundetected || mtmp->m_ap_type == M_AP_FURNITURE || mtmp->m_ap_type == M_AP_OBJECT) { int membg = level->locations[tx][ty].mem_bg; if (membg == S_vodoor || membg == S_vcdoor || membg == S_ndoor || membg == S_hodoor || membg == S_hcdoor) { if (!level->locations[tx][ty].mem_invis) { struct nh_cmd_arg newarg; arg_from_delta(dx, dy, dz, &newarg); return doclose(&newarg); } } pline("You start talking, but nobody seems to hear you."); return 0; } /* sleeping monsters won't talk, except priests (who wake up) */ if ((!mtmp->mcanmove || mtmp->msleeping) && !mtmp->ispriest) { /* If it is unseen, the player can't tell the difference between not noticing him and just not existing, so skip the message. */ if (canspotmon(mtmp)) pline("%s seems not to notice you.", Monnam(mtmp)); else pline("You start talking, but nobody seems to hear you."); return 0; } /* if this monster is waiting for something, prod it into action */ mtmp->mstrategy &= ~STRAT_WAITMASK; if (mtmp->mtame && mtmp->meating) { if (!canspotmon(mtmp)) map_invisible(mtmp->mx, mtmp->my); pline("%s is eating noisily.", Monnam(mtmp)); return 0; } return domonnoise(mtmp); }
/* try to open a door */ int doopen(const struct nh_cmd_arg *arg) { coord cc; struct rm *door; struct monst *mtmp; schar dx, dy, dz; if (nohands(youmonst.data)) { pline(msgc_cancelled, "You can't open, close, or unlock anything " "-- you have no hands!"); return 0; } if (u.utrap && u.utraptype == TT_PIT) { pline(msgc_cancelled, "You can't reach over the edge of the pit."); return 0; } 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; if ((cc.x == youmonst.mx) && (cc.y == youmonst.my)) return 0; if ((mtmp = m_at(level, cc.x, cc.y)) && mtmp->m_ap_type == M_AP_FURNITURE && (mtmp->mappearance == S_hcdoor || mtmp->mappearance == S_vcdoor) && !Protection_from_shape_changers) { stumble_onto_mimic(mtmp, cc.x - youmonst.mx, cc.y - youmonst.my); return 1; } door = &level->locations[cc.x][cc.y]; if (!IS_DOOR(door->typ)) { if (is_db_wall(cc.x, cc.y)) { pline(msgc_cancelled, "There is no obvious way to open the drawbridge."); return 0; } pline(msgc_mispaste, "You %s no door there.", Blind ? "feel" : "see"); return 0; } if (door->doormask == D_ISOPEN) { struct nh_cmd_arg newarg; arg_from_delta(dx, dy, dz, &newarg); return doclose(&newarg); } if (!(door->doormask & D_CLOSED)) { const char *mesg; switch (door->doormask) { case D_BROKEN: mesg = " is broken"; break; case D_NODOOR: mesg = "way has no door"; break; case D_ISOPEN: mesg = " is already open"; break; default: if (last_command_was("open") && door->mem_door_l) { /* With the "open" command given explicitly (rather than implicitly via doorbumping), unlock the door. */ struct obj *bestpick = get_current_unlock_tool(); struct nh_cmd_arg newarg; arg_from_delta(dx, dy, dz, &newarg); if (!bestpick) pline(msgc_cancelled, "You have nothing to unlock that with."); else if (!bestpick->lastused) /* not msgc_controlhelp, or many players would get no message */ pline(msgc_hint, "Use an unlocking tool manually so I know " "which one you want to use."); else return pick_lock(bestpick, &newarg); } door->mem_door_l = 1; map_background(cc.x, cc.y, TRUE); mesg = " is locked"; break; } pline(msgc_cancelled, "This door%s.", mesg); if (Blind) feel_location(cc.x, cc.y); return 0; } if (verysmall(youmonst.data)) { pline(msgc_cancelled, "You're too small to pull the door open."); return 0; } /* door is known to be CLOSED */ if (rnl(20) < (ACURRSTR + ACURR(A_DEX) + ACURR(A_CON)) / 3) { pline(msgc_actionok, "The door opens."); if (door->doormask & D_TRAPPED) { b_trapped("door", FINGER); door->doormask = D_NODOOR; if (*in_rooms(level, cc.x, cc.y, SHOPBASE)) add_damage(cc.x, cc.y, 0L); } else door->doormask = D_ISOPEN; if (Blind) feel_location(cc.x, cc.y); /* the hero knows she opened it */ else newsym(cc.x, cc.y); unblock_point(cc.x, cc.y); /* vision: new see through there */ } else { exercise(A_STR, TRUE); door->mem_door_l = 1; map_background(cc.x, cc.y, TRUE); pline(msgc_failrandom, "The door resists!"); } return 1; }