-/* NetHack 3.6 pager.c $NHDT-Date: 1448482543 2015/11/25 20:15:43 $ $NHDT-Branch: master $:$NHDT-Revision: 1.86 $ */
+/* NetHack 3.6 pager.c $NHDT-Date: 1555627307 2019/04/18 22:41:47 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.151 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2018. */
/* NetHack may be freely redistributed. See license for details. */
/* JNetHack Copyright */
/* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
-/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016 */
+/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2019 */
/* JNetHack may be freely redistributed. See license for details. */
/* This file contains the command routines dowhatis() and dohelp() and */
struct monst *, int, int));
STATIC_DCL struct permonst *FDECL(lookat, (int, int, char *, char *));
STATIC_DCL void FDECL(checkfile, (char *, struct permonst *,
- BOOLEAN_P, BOOLEAN_P));
+ BOOLEAN_P, BOOLEAN_P, char *));
STATIC_DCL void FDECL(look_all, (BOOLEAN_P,BOOLEAN_P));
-STATIC_DCL boolean FDECL(help_menu, (int *));
+STATIC_DCL void FDECL(do_supplemental_info, (char *, struct permonst *,
+ BOOLEAN_P));
+STATIC_DCL void NDECL(whatdoes_help);
STATIC_DCL void NDECL(docontact);
+STATIC_DCL void NDECL(dispfile_help);
+STATIC_DCL void NDECL(dispfile_shelp);
+STATIC_DCL void NDECL(dispfile_optionfile);
+STATIC_DCL void NDECL(dispfile_license);
+STATIC_DCL void NDECL(dispfile_debughelp);
+STATIC_DCL void NDECL(hmenu_doextversion);
+STATIC_DCL void NDECL(hmenu_dohistory);
+STATIC_DCL void NDECL(hmenu_dowhatis);
+STATIC_DCL void NDECL(hmenu_dowhatdoes);
+STATIC_DCL void NDECL(hmenu_doextlist);
#ifdef PORT_HELP
extern void NDECL(port_help);
#endif
return 0;
space_left = BUFSZ - strlen(buf) - 1;
+ if (space_left < 1)
+ return 0;
#if 0 /*JP*/
(void) strncat(buf, " or ", space_left);
(void) strncat(buf, new_str, space_left - 4);
Sprintf(eos(outbuf), ", mounted on %s", y_monnam(u.usteed));
*/
Sprintf(eos(outbuf), "\81C%s\82É\8fæ\82Á\82Ä\82¢\82é", y_monnam(u.usteed));
+ if (u.uundetected || (Upolyd && U_AP_TYPE))
+ mhidden_description(&youmonst, FALSE, eos(outbuf));
return outbuf;
}
+/* describe a hidden monster; used for look_at during extended monster
+ detection and for probing; also when looking at self */
+void
+mhidden_description(mon, altmon, outbuf)
+struct monst *mon;
+boolean altmon; /* for probing: if mimicking a monster, say so */
+char *outbuf;
+{
+ struct obj *otmp;
+ boolean fakeobj, isyou = (mon == &youmonst);
+ int x = isyou ? u.ux : mon->mx, y = isyou ? u.uy : mon->my,
+ glyph = (level.flags.hero_memory && !isyou) ? levl[x][y].glyph
+ : glyph_at(x, y);
+#if 1 /*JP*/
+ char suffixbuf[QBUFSZ];
+#endif
+
+ *outbuf = '\0';
+#if 1 /*JP*/
+ suffixbuf[0] = '\0';
+#endif
+ if (M_AP_TYPE(mon) == M_AP_FURNITURE
+ || M_AP_TYPE(mon) == M_AP_OBJECT) {
+#if 0 /*JP*/
+ Strcpy(outbuf, ", mimicking ");
+#else /*\8cã\82Å\92Ç\89Á\82·\82é*/
+ Strcpy(suffixbuf, "\82Ì\82Ó\82è\82ð\82µ\82Ä\82¢\82é");
+#endif
+ if (M_AP_TYPE(mon) == M_AP_FURNITURE) {
+ Strcat(outbuf, an(defsyms[mon->mappearance].explanation));
+ } else if (M_AP_TYPE(mon) == M_AP_OBJECT
+ /* remembered glyph, not glyph_at() which is 'mon' */
+ && glyph_is_object(glyph)) {
+ objfrommap:
+ otmp = (struct obj *) 0;
+ fakeobj = object_from_map(glyph, x, y, &otmp);
+ Strcat(outbuf, (otmp && otmp->otyp != STRANGE_OBJECT)
+ ? ansimpleoname(otmp)
+ : an(obj_descr[STRANGE_OBJECT].oc_name));
+ if (fakeobj) {
+ otmp->where = OBJ_FREE; /* object_from_map set to OBJ_FLOOR */
+ dealloc_obj(otmp);
+ }
+ } else {
+ Strcat(outbuf, something);
+ }
+#if 1 /*JP*/
+ Strcat(outbuf, suffixbuf);
+#endif
+ } else if (M_AP_TYPE(mon) == M_AP_MONSTER) {
+ if (altmon)
+#if 0 /*JP*/
+ Sprintf(outbuf, ", masquerading as %s",
+ an(mons[mon->mappearance].mname));
+#else
+ Sprintf(outbuf, "%s\82É\82È\82è\82·\82Ü\82µ\82Ä\82¢\82é",
+ mons[mon->mappearance].mname);
+#endif
+ } else if (isyou ? u.uundetected : mon->mundetected) {
+#if 0 /*JP*/
+ Strcpy(outbuf, ", hiding");
+#else
+ Strcpy(suffixbuf, "\82É\89B\82ê\82Ä\82¢\82é");
+#endif
+ if (hides_under(mon->data)) {
+#if 0 /*JP*//*\92n\8c`\82Ì\8fê\8d\87\81u\82Ì\89º\82É\81v\82È\82Ç\82Í\95s\8e©\91R\82È\82Ì\82Å\81A\92P\82É\8fÈ\97ª\82µ\82Ä\82¨\82*/
+ Strcat(outbuf, " under ");
+#endif
+ /* remembered glyph, not glyph_at() which is 'mon' */
+ if (glyph_is_object(glyph))
+ goto objfrommap;
+ Strcat(outbuf, something);
+ } else if (is_hider(mon->data)) {
+#if 0 /*JP*/
+ Sprintf(eos(outbuf), " on the %s",
+ (is_flyer(mon->data) || mon->data->mlet == S_PIERCER)
+ ? "ceiling"
+ : surface(x, y)); /* trapper */
+#else
+ Sprintf(eos(outbuf), "%s",
+ (is_flyer(mon->data) || mon->data->mlet == S_PIERCER)
+ ? "\93V\88ä"
+ : surface(x, y)); /* trapper */
+#endif
+ } else {
+ if (mon->data->mlet == S_EEL && is_pool(x, y))
+#if 0 /*JP*/
+ Strcat(outbuf, " in murky water");
+#else
+ Strcat(outbuf, "\82É\82²\82Á\82½\90\85\82Ì\92\86");
+#endif
+ }
+#if 1 /*JP*/
+ Strcat(outbuf, suffixbuf);
+#endif
+ }
+}
+
/* extracted from lookat(); also used by namefloorobj() */
boolean
object_from_map(glyph, x, y, obj_p)
int glyph, x, y;
struct obj **obj_p;
{
- boolean fakeobj = FALSE;
+ boolean fakeobj = FALSE, mimic_obj = FALSE;
struct monst *mtmp;
- struct obj *otmp = vobj_at(x, y);
+ struct obj *otmp;
int glyphotyp = glyph_to_obj(glyph);
*obj_p = (struct obj *) 0;
+ /* TODO: check inside containers in case glyph came from detection */
+ if ((otmp = sobj_at(glyphotyp, x, y)) == 0)
+ for (otmp = level.buriedobjlist; otmp; otmp = otmp->nobj)
+ if (otmp->ox == x && otmp->oy == y && otmp->otyp == glyphotyp)
+ break;
+
/* there might be a mimic here posing as an object */
mtmp = m_at(x, y);
- if (mtmp && is_obj_mappear(mtmp, (unsigned) glyphotyp))
+ if (mtmp && is_obj_mappear(mtmp, (unsigned) glyphotyp)) {
otmp = 0;
- else
+ mimic_obj = TRUE;
+ } else
mtmp = 0;
if (!otmp || otmp->otyp != glyphotyp) {
otmp->spe = context.current_fruit; /* give it a type */
if (mtmp && has_mcorpsenm(mtmp)) /* mimic as corpse/statue */
otmp->corpsenm = MCORPSENM(mtmp);
+ else if (otmp->otyp == CORPSE && glyph_is_body(glyph))
+ otmp->corpsenm = glyph - GLYPH_BODY_OFF;
+ else if (otmp->otyp == STATUE && glyph_is_statue(glyph))
+ otmp->corpsenm = glyph - GLYPH_STATUE_OFF;
+ if (otmp->otyp == LEASH)
+ otmp->leashmon = 0;
+ /* extra fields needed for shop price with doname() formatting */
+ otmp->where = OBJ_FLOOR;
+ otmp->ox = x, otmp->oy = y;
+ otmp->no_charge = (otmp->otyp == STRANGE_OBJECT && costly_spot(x, y));
+ }
+ /* if located at adjacent spot, mark it as having been seen up close
+ (corpse type will be known even if dknown is 0, so we don't need a
+ touch check for cockatrice corpse--we're looking without touching) */
+ if (otmp && distu(x, y) <= 2 && !Blind && !Hallucination
+ /* redundant: we only look for an object which matches current
+ glyph among floor and buried objects; when !Blind, any buried
+ object's glyph will have been replaced by whatever is present
+ on the surface as soon as we moved next to its spot */
+ && (fakeobj || otmp->where == OBJ_FLOOR) /* not buried */
+ /* terrain mode views what's already known, doesn't learn new stuff */
+ && !iflags.terrainmode) /* so don't set dknown when in terrain mode */
+ otmp->dknown = 1; /* if a pile, clearly see the top item only */
+ if (fakeobj && mtmp && mimic_obj &&
+ (otmp->dknown || (M_AP_FLAG(mtmp) & M_AP_F_DKNOWN))) {
+ mtmp->m_ap_type |= M_AP_F_DKNOWN;
+ otmp->dknown = 1;
}
- /* if located at adjacent spot, mark it as having been seen up close */
- if (otmp && distu(x, y) <= 2 && !Blind && !Hallucination)
- otmp->dknown = 1;
-
*obj_p = otmp;
return fakeobj; /* when True, caller needs to dealloc *obj_p */
}
if (otmp) {
Strcpy(buf, (otmp->otyp != STRANGE_OBJECT)
- ? distant_name(otmp, xname)
+ ? distant_name(otmp, otmp->dknown ? doname_with_price
+ : doname_vague_quan)
: obj_descr[STRANGE_OBJECT].oc_name);
- if (fakeobj)
+ if (fakeobj) {
+ otmp->where = OBJ_FREE; /* object_from_map set it to OBJ_FLOOR */
dealloc_obj(otmp), otmp = 0;
+ }
} else
Strcpy(buf, something); /* sanity precaution */
- if (levl[x][y].typ == STONE || levl[x][y].typ == SCORR)
+ if (otmp && otmp->where == OBJ_BURIED)
+/*JP
+ Strcat(buf, " (buried)");
+*/
+ Strcat(buf, " (\96\84\82Ü\82Á\82Ä\82¢\82é)");
+ else if (levl[x][y].typ == STONE || levl[x][y].typ == SCORR)
/*JP
Strcat(buf, " embedded in stone");
*/
char *name, monnambuf[BUFSZ];
boolean accurate = !Hallucination;
- if (mtmp->data == &mons[PM_COYOTE] && accurate)
- name = coyotename(mtmp, monnambuf);
- else
- name = distant_monnam(mtmp, ARTICLE_NONE, monnambuf);
-
+ name = (mtmp->data == &mons[PM_COYOTE] && accurate)
+ ? coyotename(mtmp, monnambuf)
+ : distant_monnam(mtmp, ARTICLE_NONE, monnambuf);
#if 0 /*JP*/
Sprintf(buf, "%s%s%s",
(mtmp->mx != x || mtmp->my != y)
name);
#else
Sprintf(buf, "%s%s%s",
- (mtmp->mtame && accurate) ? "\8eè\82È\82¸\82¯\82ç\82ê\82½" :
- (mtmp->mpeaceful && accurate) ? "\97F\8dD\93I\82È" : "",
+ (mtmp->mtame && accurate)
+ ? "\8eè\82È\82¸\82¯\82ç\82ê\82½"
+ : (mtmp->mpeaceful && accurate)
+ ? "\97F\8dD\93I\82È"
+ : "",
name,
- (mtmp->mx != x || mtmp->my != y) ?
- ((mtmp->isshk && accurate)
- ? "\82Ì\90K\94ö" : "\82Ì\90K\94ö") : "");
+ (mtmp->mx != x || mtmp->my != y)
+ ? ((mtmp->isshk && accurate) ? "\82Ì\90K\94ö" : "\82Ì\90K\94ö")
+ : "");
+#endif
+ if (u.ustuck == mtmp) {
+ if (u.uswallow || iflags.save_uswallow) /* monster detection */
+#if 0 /*JP*/
+ Strcat(buf, is_animal(mtmp->data)
+ ? ", swallowing you" : ", engulfing you");
+#else
+ Strcat(buf, ", \82 \82È\82½\82ð\88ù\82Ý\8d\9e\82ñ\82Å\82¢\82é");
#endif
- if (u.ustuck == mtmp)
- Strcat(buf, (Upolyd && sticks(youmonst.data))
+ else
+ Strcat(buf, (Upolyd && sticks(youmonst.data))
/*JP
? ", being held" : ", holding you");
*/
? "\81C\82 \82È\82½\82ª\92Í\82Ü\82¦\82Ä\82¢\82é" : "\81C\82 \82È\82½\82ð\92Í\82Ü\82¦\82Ä\82¢\82é");
+ }
if (mtmp->mleashed)
/*JP
Strcat(buf, ", leashed to you");
int tt = t ? t->ttyp : NO_TRAP;
/* newsym lets you know of the trap, so mention it here */
- if (tt == BEAR_TRAP || tt == PIT || tt == SPIKED_PIT || tt == WEB)
+ if (tt == BEAR_TRAP || is_pit(tt) || tt == WEB)
/*JP
Sprintf(eos(buf), ", trapped in %s",
*/
an(defsyms[trap_to_defsym(tt)].explanation));
}
+ /* we know the hero sees a monster at this location, but if it's shown
+ due to persistant monster detection he might remember something else */
+ if (mtmp->mundetected || M_AP_TYPE(mtmp))
+ mhidden_description(mtmp, FALSE, eos(buf));
+
if (monbuf) {
unsigned how_seen = howmonseen(mtmp);
Strcat(monbuf, ", ");
}
if (how_seen & MONSEEN_WARNMON) {
- if (Hallucination)
+ if (Hallucination) {
/*JP
Strcat(monbuf, "paranoid delusion");
*/
Strcat(monbuf, "\95Î\8e·\93I\96Ï\91z");
- else
+ } else {
+ unsigned long mW = (context.warntype.obj
+ | context.warntype.polyd),
+ m2 = mtmp->data->mflags2;
+#if 0 /*JP*/
+ const char *whom = ((mW & M2_HUMAN & m2) ? "human"
+ : (mW & M2_ELF & m2) ? "elf"
+ : (mW & M2_ORC & m2) ? "orc"
+ : (mW & M2_DEMON & m2) ? "demon"
+ : mtmp->data->mname);
+#else
+ const char *whom = ((mW & M2_HUMAN & m2) ? "\90l\8aÔ"
+ : (mW & M2_ELF & m2) ? "\83G\83\8b\83t"
+ : (mW & M2_ORC & m2) ? "\83I\81[\83N"
+ : (mW & M2_DEMON & m2) ? "\88«\96\82"
+ : mtmp->data->mname);
+#endif
+
/*JP
- Sprintf(eos(monbuf), "warned of %s",
+ Sprintf(eos(monbuf), "warned of %s", makeplural(whom));
*/
- Sprintf(eos(monbuf), "%s\82ð\8cx\8d\90\82µ\82Ä\82¢\82é",
- makeplural(mtmp->data->mname));
+ Sprintf(eos(monbuf), "%s\82ð\8cx\8d\90\82µ\82Ä\82¢\82é", whom);
+ }
how_seen &= ~MONSEEN_WARNMON;
if (how_seen)
Strcat(monbuf, ", ");
buf[0] = monbuf[0] = '\0';
glyph = glyph_at(x, y);
- if (u.ux == x && u.uy == y && canspotself()) {
+ if (u.ux == x && u.uy == y && canspotself()
+ && !(iflags.save_uswallow &&
+ glyph == mon_to_glyph(u.ustuck, rn2_on_display_rng))
+ && (!iflags.terrainmode || (iflags.terrainmode & TER_MON) != 0)) {
/* fill in buf[] */
(void) self_lookat(buf);
(even if you could also see yourself via other means).
Sensing self while blind or swallowed is treated as if it
were by normal vision (cf canseeself()). */
- if ((Invisible || u.uundetected) && !Blind && !u.uswallow) {
+ if ((Invisible || u.uundetected) && !Blind
+ && !(u.uswallow || iflags.save_uswallow)) {
unsigned how = 0;
if (Infravision)
if (how)
#if 0 /*JP*/
- Sprintf(
- eos(buf), " [seen: %s%s%s%s%s]",
- (how & 1) ? "infravision" : "",
- /* add comma if telep and infrav */
- ((how & 3) > 2) ? ", " : "", (how & 2) ? "telepathy" : "",
- /* add comma if detect and (infrav or telep or both) */
- ((how & 7) > 4) ? ", " : "",
- (how & 4) ? "monster detection" : "");
+ Sprintf(eos(buf), " [seen: %s%s%s%s%s]",
+ (how & 1) ? "infravision" : "",
+ /* add comma if telep and infrav */
+ ((how & 3) > 2) ? ", " : "",
+ (how & 2) ? "telepathy" : "",
+ /* add comma if detect and (infrav or telep or both) */
+ ((how & 7) > 4) ? ", " : "",
+ (how & 4) ? "monster detection" : "");
#else
- Sprintf(
- eos(buf), " [\8a´\92m: %s%s%s%s%s]",
- (how & 1) ? "\90Ô\8aO\90ü" : "",
- /* add comma if telep and infrav */
- ((how & 3) > 2) ? ", " : "", (how & 2) ? "\83e\83\8c\83p\83V\81[" : "",
- /* add comma if detect and (infrav or telep or both) */
- ((how & 7) > 4) ? ", " : "",
- (how & 4) ? "\89ö\95¨\8a´\92m" : "");
+ Sprintf(eos(buf), " [\8a´\92m: %s%s%s%s%s]",
+ (how & 1) ? "\90Ô\8aO\90ü" : "",
+ /* add comma if telep and infrav */
+ ((how & 3) > 2) ? ", " : "",
+ (how & 2) ? "\83e\83\8c\83p\83V\81[" : "",
+ /* add comma if detect and (infrav or telep or both) */
+ ((how & 7) > 4) ? ", " : "",
+ (how & 4) ? "\89ö\95¨\8a´\92m" : "");
#endif
}
} else if (u.uswallow) {
- /* all locations when swallowed other than the hero are the monster */
-#if 0 /*JP*/
- Sprintf(buf, "interior of %s",
- Blind ? "a monster" : a_monnam(u.ustuck));
-#else
- Sprintf(buf, "%s\82Ì\93à\95\94",
- Blind ? "\89ö\95¨" : a_monnam(u.ustuck));
-#endif
+ /* when swallowed, we're only called for spots adjacent to hero,
+ and blindness doesn't prevent hero from feeling what holds him */
+/*JP
+ Sprintf(buf, "interior of %s", a_monnam(u.ustuck));
+*/
+ Sprintf(buf, "%s\82Ì\93à\95\94", a_monnam(u.ustuck));
pm = u.ustuck->data;
} else if (glyph_is_monster(glyph)) {
bhitpos.x = x;
if ((mtmp = m_at(x, y)) != 0) {
look_at_monster(buf, monbuf, mtmp, x, y);
pm = mtmp->data;
+ } else if (Hallucination) {
+ /* 'monster' must actually be a statue */
+ Strcpy(buf, rndmonnam((char *) 0));
}
} else if (glyph_is_object(glyph)) {
look_at_object(buf, x, y, glyph); /* fill in buf[] */
} else if (glyph_is_trap(glyph)) {
- int tnum = what_trap(glyph_to_trap(glyph));
+ int tnum = what_trap(glyph_to_trap(glyph), rn2_on_display_rng);
+
+ /* Trap detection displays a bear trap at locations having
+ * a trapped door or trapped container or both.
+ * TODO: we should create actual trap types for doors and
+ * chests so that they can have their own glyphs and tiles.
+ */
+ if (trapped_chest_at(tnum, x, y))
+#if 0 /*JP*/
+ Strcpy(buf, "trapped chest"); /* might actually be a large box */
+#else
+ Strcpy(buf, "ã©\82Ì\8ed\8a|\82¯\82ç\82ê\82½\94 "); /* might actually be a large box */
+#endif
+ else if (trapped_door_at(tnum, x, y))
+#if 0 /*JP*/
+ Strcpy(buf, "trapped door"); /* not "trap door"... */
+#else
+ Strcpy(buf, "ã©\82Ì\8ed\8a|\82¯\82ç\82ê\82½\94à"); /* not "trap door"... */
+#endif
+ else
+ Strcpy(buf, defsyms[trap_to_defsym(tnum)].explanation);
+ } else if (glyph_is_warning(glyph)) {
+ int warnindx = glyph_to_warning(glyph);
- Strcpy(buf, defsyms[trap_to_defsym(tnum)].explanation);
+ Strcpy(buf, def_warnsyms[warnindx].explanation);
} else if (!glyph_is_cmap(glyph)) {
/*JP
Strcpy(buf, "unexplored area");
*/
Strcpy(buf, "\96¢\92T\8dõ");
break;
+ } else if (Underwater && !Is_waterlevel(&u.uz)) {
+ /* "unknown" == previously mapped but not visible when
+ submerged; better terminology appreciated... */
+ Strcpy(buf, (distu(x, y) <= 2) ? "land" : "unknown");
+ break;
} else if (levl[x][y].typ == STONE || levl[x][y].typ == SCORR) {
/*JP
Strcpy(buf, "stone");
Strcpy(buf, "\8aâ\94Õ");
break;
}
- /*else FALLTHRU*/
+ /*FALLTHRU*/
default:
Strcpy(buf, defsyms[glyph_to_cmap(glyph)].explanation);
break;
* Therefore, we create a copy of inp _just_ for data.base lookup.
*/
STATIC_OVL void
-checkfile(inp, pm, user_typed_name, without_asking)
+checkfile(inp, pm, user_typed_name, without_asking, supplemental_name)
char *inp;
struct permonst *pm;
boolean user_typed_name, without_asking;
+char *supplemental_name;
{
dlb *fp;
- char buf[BUFSZ], newstr[BUFSZ];
+ char buf[BUFSZ], newstr[BUFSZ], givenname[BUFSZ];
char *ep, *dbase_str;
unsigned long txt_offset = 0L;
- int chk_skip;
- boolean found_in_file = FALSE, skipping_entry = FALSE;
winid datawin = WIN_ERR;
fp = dlb_fopen(DATAFILE, "r");
if (!fp) {
-#if 0 /*JP*/
- pline("Cannot open data file!");
-#else
+/*JP
+ pline("Cannot open 'data' file!");
+*/
pline("\83f\81[\83^\83t\83@\83C\83\8b\82ð\8aJ\82¯\82È\82¢\81I");
-#endif
return;
}
-
- /*
- * If someone passed us garbage, prevent fault.
- */
- if (!inp || (inp && strlen(inp) > (BUFSZ - 1))) {
- pline("bad do_look buffer passed!");
- return;
+ /* If someone passed us garbage, prevent fault. */
+ if (!inp || strlen(inp) > (BUFSZ - 1)) {
+ impossible("bad do_look buffer passed (%s)!",
+ !inp ? "null" : "too long");
+ goto checkfile_done;
}
/* To prevent the need for entries in data.base like *ngel to account
dbase_str = strcpy(newstr, inp);
(void) lcase(dbase_str);
+ /*JP:TODO:\83f\81[\83^\83x\81[\83X\8c\9f\8dõ\82Í\93®\82¢\82Ä\82¢\82È\82¢\82Ì\82Å\97v\8fC\90³*/
+ /*
+ * TODO:
+ * The switch from xname() to doname_vague_quan() in look_at_obj()
+ * had the unintendded side-effect of making names picked from
+ * pointing at map objects become harder to simplify for lookup.
+ * We should split the prefix and suffix handling used by wish
+ * parsing and also wizmode monster generation out into separate
+ * routines and use those routines here. This currently lacks
+ * erosion handling and probably lots of other bits and pieces
+ * that wishing already understands and most of this duplicates
+ * stuff already done for wish handling or monster generation.
+ */
if (!strncmp(dbase_str, "interior of ", 12))
dbase_str += 12;
if (!strncmp(dbase_str, "a ", 2))
dbase_str += 3;
else if (!strncmp(dbase_str, "the ", 4))
dbase_str += 4;
+ else if (!strncmp(dbase_str, "some ", 5))
+ dbase_str += 5;
+ else if (digit(*dbase_str)) {
+ /* remove count prefix ("2 ya") which can come from looking at map */
+ while (digit(*dbase_str))
+ ++dbase_str;
+ if (*dbase_str == ' ')
+ ++dbase_str;
+ }
+ if (!strncmp(dbase_str, "pair of ", 8))
+ dbase_str += 8;
if (!strncmp(dbase_str, "tame ", 5))
dbase_str += 5;
else if (!strncmp(dbase_str, "peaceful ", 9))
dbase_str += 10;
if (!strncmp(dbase_str, "saddled ", 8))
dbase_str += 8;
+ if (!strncmp(dbase_str, "blessed ", 8))
+ dbase_str += 8;
+ else if (!strncmp(dbase_str, "uncursed ", 9))
+ dbase_str += 9;
+ else if (!strncmp(dbase_str, "cursed ", 7))
+ dbase_str += 7;
+ if (!strncmp(dbase_str, "empty ", 6))
+ dbase_str += 6;
+ if (!strncmp(dbase_str, "partly used ", 12))
+ dbase_str += 12;
+ else if (!strncmp(dbase_str, "partly eaten ", 13))
+ dbase_str += 13;
if (!strncmp(dbase_str, "statue of ", 10))
dbase_str[6] = '\0';
else if (!strncmp(dbase_str, "figurine of ", 12))
dbase_str[8] = '\0';
+ /* remove enchantment ("+0 aklys"); [for 3.6.0 and earlier, this wasn't
+ needed because looking at items on the map used xname() rather than
+ doname() hence known enchantment was implicitly suppressed] */
+ if (*dbase_str && index("+-", dbase_str[0]) && digit(dbase_str[1])) {
+ ++dbase_str; /* skip sign */
+ while (digit(*dbase_str))
+ ++dbase_str;
+ if (*dbase_str == ' ')
+ ++dbase_str;
+ }
+ /* "towel", "wet towel", and "moist towel" share one data.base entry;
+ for "wet towel", we keep prefix so that the prompt will ask about
+ "wet towel"; for "moist towel", we also want to ask about "wet towel".
+ (note: strncpy() only terminates output string if the specified
+ count is bigger than the length of the substring being copied) */
+ if (!strncmp(dbase_str, "moist towel", 11))
+ (void) strncpy(dbase_str += 2, "wet", 3); /* skip "mo" replace "ist" */
/* Make sure the name is non-empty. */
if (*dbase_str) {
- /* adjust the input to remove "named " and convert to lower case */
- char *alt = 0; /* alternate description */
-
- if ((ep = strstri(dbase_str, " named ")) != 0)
+ long pass1offset = -1L;
+ int chk_skip, pass = 1;
+ boolean yes_to_moreinfo, found_in_file, pass1found_in_file,
+ skipping_entry;
+ char *sp, *ap, *alt = 0; /* alternate description */
+
+ /* adjust the input to remove "named " and "called " */
+ if ((ep = strstri(dbase_str, " named ")) != 0) {
alt = ep + 7;
- else
- ep = strstri(dbase_str, " called ");
- if (!ep)
+ if ((ap = strstri(dbase_str, " called ")) != 0 && ap < ep)
+ ep = ap; /* "named" is alt but truncate at "called" */
+ } else if ((ep = strstri(dbase_str, " called ")) != 0) {
+ copynchars(givenname, ep + 8, BUFSZ - 1);
+ alt = givenname;
+ if (supplemental_name && (sp = strstri(inp, " called ")) != 0)
+ copynchars(supplemental_name, sp + 8, BUFSZ - 1);
+ } else
ep = strstri(dbase_str, ", ");
if (ep && ep > dbase_str)
*ep = '\0';
+ /* remove article from 'alt' name ("a pair of lenses named
+ The Eyes of the Overworld" simplified above to "lenses named
+ The Eyes of the Overworld", now reduced to "The Eyes of the
+ Overworld", skip "The" as with base name processing) */
+ if (alt && (!strncmpi(alt, "a ", 2)
+ || !strncmpi(alt, "an ", 3)
+ || !strncmpi(alt, "the ", 4)))
+ alt = index(alt, ' ') + 1;
+ /* remove charges or "(lit)" or wizmode "(N aum)" */
+ if ((ep = strstri(dbase_str, " (")) != 0 && ep > dbase_str)
+ *ep = '\0';
+ if (alt && (ap = strstri(alt, " (")) != 0 && ap > alt)
+ *ap = '\0';
/*
* If the object is named, then the name is the alternate description;
* otherwise, the result of makesingular() applied to the name is.
- * This
- * isn't strictly optimal, but named objects of interest to the user
- * will usually be found under their name, rather than under their
- * object type, so looking for a singular form is pointless.
+ * This isn't strictly optimal, but named objects of interest to the
+ * user will usually be found under their name, rather than under
+ * their object type, so looking for a singular form is pointless.
*/
if (!alt)
alt = makesingular(dbase_str);
- /* skip first record; read second */
- txt_offset = 0L;
- if (!dlb_fgets(buf, BUFSZ, fp) || !dlb_fgets(buf, BUFSZ, fp)) {
- impossible("can't read 'data' file");
- (void) dlb_fclose(fp);
- return;
- } else if (sscanf(buf, "%8lx\n", &txt_offset) < 1 || txt_offset == 0L)
- goto bad_data_file;
-
- /* look for the appropriate entry */
- while (dlb_fgets(buf, BUFSZ, fp)) {
- if (*buf == '.')
- break; /* we passed last entry without success */
-
- if (digit(*buf)) {
- /* a number indicates the end of current entry */
- skipping_entry = FALSE;
- } else if (!skipping_entry) {
- if (!(ep = index(buf, '\n')))
- goto bad_data_file;
- *ep = 0;
- /* if we match a key that begins with "~", skip this entry */
- chk_skip = (*buf == '~') ? 1 : 0;
- if (pmatch(&buf[chk_skip], dbase_str)
- || (alt && pmatch(&buf[chk_skip], alt))) {
- if (chk_skip) {
- skipping_entry = TRUE;
- continue;
- } else {
- found_in_file = TRUE;
- break;
+ pass1found_in_file = FALSE;
+ for (pass = !strcmp(alt, dbase_str) ? 0 : 1; pass >= 0; --pass) {
+ found_in_file = skipping_entry = FALSE;
+ txt_offset = 0L;
+ if (dlb_fseek(fp, txt_offset, SEEK_SET) < 0 ) {
+ impossible("can't get to start of 'data' file");
+ goto checkfile_done;
+ }
+ /* skip first record; read second */
+ if (!dlb_fgets(buf, BUFSZ, fp) || !dlb_fgets(buf, BUFSZ, fp)) {
+ impossible("can't read 'data' file");
+ goto checkfile_done;
+ } else if (sscanf(buf, "%8lx\n", &txt_offset) < 1
+ || txt_offset == 0L)
+ goto bad_data_file;
+
+ /* look for the appropriate entry */
+ while (dlb_fgets(buf, BUFSZ, fp)) {
+ if (*buf == '.')
+ break; /* we passed last entry without success */
+
+ if (digit(*buf)) {
+ /* a number indicates the end of current entry */
+ skipping_entry = FALSE;
+ } else if (!skipping_entry) {
+ if (!(ep = index(buf, '\n')))
+ goto bad_data_file;
+ (void) strip_newline((ep > buf) ? ep - 1 : ep);
+ /* if we match a key that begins with "~", skip
+ this entry */
+ chk_skip = (*buf == '~') ? 1 : 0;
+ if ((pass == 0 && pmatch(&buf[chk_skip], dbase_str))
+ || (pass == 1 && alt && pmatch(&buf[chk_skip], alt))) {
+ if (chk_skip) {
+ skipping_entry = TRUE;
+ continue;
+ } else {
+ found_in_file = TRUE;
+ if (pass == 1)
+ pass1found_in_file = TRUE;
+ break;
+ }
}
}
}
- }
- }
+ if (found_in_file) {
+ long entry_offset, fseekoffset;
+ int entry_count;
+ int i;
+
+ /* skip over other possible matches for the info */
+ do {
+ if (!dlb_fgets(buf, BUFSZ, fp))
+ goto bad_data_file;
+ } while (!digit(*buf));
+ if (sscanf(buf, "%ld,%d\n", &entry_offset, &entry_count) < 2)
+ goto bad_data_file;
+ fseekoffset = (long) txt_offset + entry_offset;
+ if (pass == 1)
+ pass1offset = fseekoffset;
+ else if (fseekoffset == pass1offset)
+ goto checkfile_done;
- if (found_in_file) {
- long entry_offset;
- int entry_count;
- int i;
+ yes_to_moreinfo = FALSE;
+ if (!user_typed_name && !without_asking) {
+ char *entrytext = pass ? alt : dbase_str;
+ char question[QBUFSZ];
- /* skip over other possible matches for the info */
- do {
- if (!dlb_fgets(buf, BUFSZ, fp))
- goto bad_data_file;
- } while (!digit(*buf));
- if (sscanf(buf, "%ld,%d\n", &entry_offset, &entry_count) < 2) {
- bad_data_file:
- impossible("'data' file in wrong format or corrupted");
- /* window will exist if we came here from below via 'goto' */
- if (datawin != WIN_ERR)
- destroy_nhwindow(datawin);
- (void) dlb_fclose(fp);
- return;
- }
+#if 0 /*JP*/
+ Strcpy(question, "More info about \"");
+ /* +2 => length of "\"?" */
+ copynchars(eos(question), entrytext,
+ (int) (sizeof question - 1
+ - (strlen(question) + 2)));
+ Strcat(question, "\"?");
+#else
+ Strcpy(question, "\81u");
+ /* +16 => "\81v\82Ì\8fÚ\8d×\82ð\8c©\82é\81H"\82Ì\92·\82³ */
+ copynchars(eos(question), entrytext,
+ (int) (sizeof question - 1
+ - (strlen(question) + 16)));
+ Strcat(question, "\81v\82Ì\8fÚ\8d×\82ð\8c©\82é\81H");
+#endif
+ if (yn(question) == 'y')
+ yes_to_moreinfo = TRUE;
+ }
-/*JP
- if (user_typed_name || without_asking || yn("More info?") == 'y') {
-*/
- if (user_typed_name || without_asking || yn("\8fÚ\8d×\82ð\8c©\82é\81H") == 'y') {
- if (dlb_fseek(fp, (long) txt_offset + entry_offset, SEEK_SET)
- < 0) {
+ if (user_typed_name || without_asking || yes_to_moreinfo) {
+ if (dlb_fseek(fp, fseekoffset, SEEK_SET) < 0) {
/*JP
pline("? Seek error on 'data' file!");
*/
pline("'data'\83t\83@\83C\83\8b\82Ì\83V\81[\83N\83G\83\89\81[\81I");
- (void) dlb_fclose(fp);
- return;
- }
- datawin = create_nhwindow(NHW_MENU);
- for (i = 0; i < entry_count; i++) {
- if (!dlb_fgets(buf, BUFSZ, fp))
- goto bad_data_file;
- if ((ep = index(buf, '\n')) != 0)
- *ep = 0;
- if (index(buf + 1, '\t') != 0)
- (void) tabexpand(buf + 1);
- putstr(datawin, 0, buf + 1);
- }
- display_nhwindow(datawin, FALSE);
- destroy_nhwindow(datawin);
- }
- } else if (user_typed_name)
+ goto checkfile_done;
+ }
+ datawin = create_nhwindow(NHW_MENU);
+ for (i = 0; i < entry_count; i++) {
+ if (!dlb_fgets(buf, BUFSZ, fp))
+ goto bad_data_file;
+ (void) strip_newline(buf);
+ if (index(buf + 1, '\t') != 0)
+ (void) tabexpand(buf + 1);
+ putstr(datawin, 0, buf + 1);
+ }
+ display_nhwindow(datawin, FALSE);
+ destroy_nhwindow(datawin), datawin = WIN_ERR;
+ }
+ } else if (user_typed_name && pass == 0 && !pass1found_in_file)
/*JP
pline("I don't have any information on those things.");
*/
pline("\82»\82ñ\82È\96¼\91O\82Í\95·\82¢\82½\82±\82Æ\82ª\82È\82¢\81D");
+ }
+ }
+ goto checkfile_done; /* skip error feedback */
+ bad_data_file:
+ impossible("'data' file in wrong format or corrupted");
+ checkfile_done:
+ if (datawin != WIN_ERR)
+ destroy_nhwindow(datawin);
(void) dlb_fclose(fp);
+ return;
}
int
-do_screen_description(cc, looked, sym, out_str, firstmatch)
+do_screen_description(cc, looked, sym, out_str, firstmatch, for_supplement)
coord cc;
boolean looked;
int sym;
char *out_str;
const char **firstmatch;
+struct permonst **for_supplement;
{
- boolean need_to_look = FALSE;
- int glyph = NO_GLYPH;
+/*JP
+ static const char mon_interior[] = "the interior of a monster",
+*/
+ static const char mon_interior[] = "\89ö\95¨\82Ì\93à\95\94",
+/*JP
+ unreconnoitered[] = "unreconnoitered";
+*/
+ unreconnoitered[] = "\96¢\8aÏ\8e@";
static char look_buf[BUFSZ];
char prefix[BUFSZ];
- int found = 0; /* count of matching syms found */
- int i, alt_i;
- int skipped_venom = 0;
- boolean hit_trap;
+ int i, alt_i, glyph = NO_GLYPH,
+ skipped_venom = 0, found = 0; /* count of matching syms found */
+ boolean hit_trap, need_to_look = FALSE,
+ submerged = (Underwater && !Is_waterlevel(&u.uz));
const char *x_str;
-/*JP
- static const char *mon_interior = "the interior of a monster";
-*/
- static const char *mon_interior = "\89ö\95¨\82Ì\93à\95\94";
if (looked) {
int oc;
*/
/*
- * Special case: if identifying from the screen, and we're swallowed,
- * and looking at something other than our own symbol, then just say
- * "the interior of a monster".
+ * Handle restricted vision range (limited to adjacent spots when
+ * swallowed or underwater) cases first.
+ *
+ * 3.6.0 listed anywhere on map, other than self, as "interior
+ * of a monster" when swallowed, and non-adjacent water or
+ * non-water anywhere as "dark part of a room" when underwater.
+ * "unreconnoitered" is an attempt to convey "even if you knew
+ * what was there earlier, you don't know what is there in the
+ * current circumstance".
+ *
+ * (Note: 'self' will always be visible when swallowed so we don't
+ * need special swallow handling for <ux,uy>.
+ * Another note: for '#terrain' without monsters, u.uswallow and
+ * submerged will always both be False and skip this code.)
*/
- if (u.uswallow && looked
- && (is_swallow_sym(sym) || (int) showsyms[S_stone] == sym)) {
+ x_str = 0;
+ if (!looked) {
+ ; /* skip special handling */
+ } else if (((u.uswallow || submerged) && distu(cc.x, cc.y) > 2)
+ /* detection showing some category, so mostly background */
+ || ((iflags.terrainmode & (TER_DETECT | TER_MAP)) == TER_DETECT
+ && glyph == cmap_to_glyph(S_stone))) {
+ x_str = unreconnoitered;
+ need_to_look = FALSE;
+ } else if (is_swallow_sym(sym)) {
+ x_str = mon_interior;
+ need_to_look = TRUE; /* for specific monster type */
+ }
+ if (x_str) {
+ /* we know 'found' is zero here, but guard against some other
+ special case being inserted ahead of us someday */
if (!found) {
- Sprintf(out_str, "%s%s", prefix, mon_interior);
- *firstmatch = mon_interior;
+ Sprintf(out_str, "%s%s", prefix, x_str);
+ *firstmatch = x_str;
+ found++;
} else {
- found += append_str(out_str, mon_interior);
+ found += append_str(out_str, x_str); /* not 'an(x_str)' */
}
- need_to_look = TRUE;
- goto didlook;
+ /* for is_swallow_sym(), we want to list the current symbol's
+ other possibilities (wand for '/', throne for '\\', &c) so
+ don't jump to the end for the x_str==mon_interior case */
+ if (x_str == unreconnoitered)
+ goto didlook;
}
/* Check for monsters */
- for (i = 0; i < MAXMCLASSES; i++) {
- if (sym == (looked ? showsyms[i + SYM_OFF_M] : def_monsyms[i].sym)
- && def_monsyms[i].explain) {
- need_to_look = TRUE;
- if (!found) {
- Sprintf(out_str, "%s%s", prefix, an(def_monsyms[i].explain));
- *firstmatch = def_monsyms[i].explain;
- found++;
- } else {
- found += append_str(out_str, an(def_monsyms[i].explain));
+ if (!iflags.terrainmode || (iflags.terrainmode & TER_MON) != 0) {
+ for (i = 1; i < MAXMCLASSES; i++) {
+ if (sym == (looked ? showsyms[i + SYM_OFF_M] : def_monsyms[i].sym)
+ && def_monsyms[i].explain && *def_monsyms[i].explain) {
+ need_to_look = TRUE;
+ if (!found) {
+ Sprintf(out_str, "%s%s",
+ prefix, an(def_monsyms[i].explain));
+ *firstmatch = def_monsyms[i].explain;
+ found++;
+ } else {
+ found += append_str(out_str, an(def_monsyms[i].explain));
+ }
}
}
- }
- /* handle '@' as a special case if it refers to you and you're
- playing a character which isn't normally displayed by that
- symbol; firstmatch is assumed to already be set for '@' */
- if ((looked ? (sym == showsyms[S_HUMAN + SYM_OFF_M]
- && cc.x == u.ux && cc.y == u.uy)
- : (sym == def_monsyms[S_HUMAN].sym && !flags.showrace))
- && !(Race_if(PM_HUMAN) || Race_if(PM_ELF)) && !Upolyd)
-#if 0 /*JP*/
- found += append_str(out_str, "you"); /* tack on "or you" */
+ /* handle '@' as a special case if it refers to you and you're
+ playing a character which isn't normally displayed by that
+ symbol; firstmatch is assumed to already be set for '@' */
+ if ((looked ? (sym == showsyms[S_HUMAN + SYM_OFF_M]
+ && cc.x == u.ux && cc.y == u.uy)
+ : (sym == def_monsyms[S_HUMAN].sym && !flags.showrace))
+ && !(Race_if(PM_HUMAN) || Race_if(PM_ELF)) && !Upolyd)
+#if 0 /*JP:T*/
+ found += append_str(out_str, "you"); /* tack on "or you" */
#else
- found += append_str(out_str, "\82 \82È\82½"); /* tack on "or you" */
+ found += append_str(out_str, "\82 \82È\82½"); /* tack on "or you" */
#endif
+ }
/* Now check for objects */
- for (i = 1; i < MAXOCLASSES; i++) {
- if (sym == (looked ? showsyms[i + SYM_OFF_O] : def_oc_syms[i].sym)) {
- need_to_look = TRUE;
- if (looked && i == VENOM_CLASS) {
- skipped_venom++;
- continue;
- }
- if (!found) {
- Sprintf(out_str, "%s%s", prefix, an(def_oc_syms[i].explain));
- *firstmatch = def_oc_syms[i].explain;
- found++;
- } else {
- found += append_str(out_str, an(def_oc_syms[i].explain));
+ if (!iflags.terrainmode || (iflags.terrainmode & TER_OBJ) != 0) {
+ for (i = 1; i < MAXOCLASSES; i++) {
+ if (sym == (looked ? showsyms[i + SYM_OFF_O]
+ : def_oc_syms[i].sym)
+ || (looked && i == ROCK_CLASS && glyph_is_statue(glyph))) {
+ need_to_look = TRUE;
+ if (looked && i == VENOM_CLASS) {
+ skipped_venom++;
+ continue;
+ }
+ if (!found) {
+ Sprintf(out_str, "%s%s",
+ prefix, an(def_oc_syms[i].explain));
+ *firstmatch = def_oc_syms[i].explain;
+ found++;
+ } else {
+ found += append_str(out_str, an(def_oc_syms[i].explain));
+ }
}
}
}
if (sym == DEF_INVISIBLE) {
+ extern const char altinvisexplain[]; /* drawing.c */
+ /* for active clairvoyance, use alternate "unseen creature" */
+ boolean usealt = (EDetect_monsters & I_SPECIAL) != 0L;
+ const char *unseen_explain = !usealt ? invisexplain : altinvisexplain;
+
if (!found) {
- Sprintf(out_str, "%s%s", prefix, an(invisexplain));
- *firstmatch = invisexplain;
+ Sprintf(out_str, "%s%s", prefix, an(unseen_explain));
+ *firstmatch = unseen_explain;
found++;
} else {
- found += append_str(out_str, an(invisexplain));
+ found += append_str(out_str, an(unseen_explain));
}
}
-#define is_cmap_trap(i) ((i) >= S_arrow_trap && (i) <= S_polymorph_trap)
-#define is_cmap_drawbridge(i) ((i) >= S_vodbridge && (i) <= S_hcdbridge)
-
/* Now check for graphics symbols */
alt_i = (sym == (looked ? showsyms[0] : defsyms[0].sym)) ? 0 : (2 + 1);
for (hit_trap = FALSE, i = 0; i < MAXPCHARS; i++) {
i == 0 three times: unexplored, stone, dark part of a room */
if (alt_i < 2) {
/*JP
- x_str = !alt_i++ ? "unexplored" : "stone";
+ x_str = !alt_i++ ? "unexplored" : submerged ? "unknown" : "stone";
*/
- x_str = !alt_i++ ? "\96¢\92T\8dõ" : "\8aâ\94Õ";
+ x_str = !alt_i++ ? "\96¢\92T\8dõ" : submerged ? "\96¢\92m" : "\8aâ\94Õ";
i = 0; /* for second iteration, undo loop increment */
/* alt_i is now 1 or 2 */
} else {
if (alt_i++ == 2)
i = 0; /* undo loop increment */
x_str = defsyms[i].explanation;
+ if (submerged && !strcmp(x_str, defsyms[0].explanation))
+#if 0 /*JP*/
+ x_str = "land"; /* replace "dark part of a room" */
+#else
+ x_str = "\92n\96Ê"; /* replace "dark part of a room" */
+#endif
/* alt_i is now 3 or more and no longer of interest */
}
if (sym == (looked ? showsyms[i] : defsyms[i].sym) && *x_str) {
int article = strstri(x_str, " of a room") ? 2
: !(alt_i <= 2
|| strcmp(x_str, "air") == 0
+ || strcmp(x_str, "land") == 0
|| strcmp(x_str, "water") == 0);
#endif
}
*firstmatch = x_str;
found++;
- } else if (!u.uswallow && !(hit_trap && is_cmap_trap(i))
+ } else if (!(hit_trap && is_cmap_trap(i))
&& !(found >= 3 && is_cmap_drawbridge(i))
/* don't mention vibrating square outside of Gehennom
unless this happens to be one (hallucination?) */
/* Kludge: warning trumps boulders on the display.
Reveal the boulder too or player can get confused */
if (looked && sobj_at(BOULDER, cc.x, cc.y))
+/*JP
Strcat(out_str, " co-located with a boulder");
+*/
+ Strcat(out_str, "(\8b\90\8aâ\82Æ\93¯\82¶\88Ê\92u\82É\82 \82é)");
break; /* out of for loop*/
}
}
* If we are looking at the screen, follow multiple possibilities or
* an ambiguous explanation by something more detailed.
*/
+
+ if (found > 4)
+/*JP
+ Sprintf(out_str, "%s", "That can be many things");
+*/
+ Sprintf(out_str, "%s", "\82±\82±\82É\82Í\91½\82\82Ì\82à\82Ì\82ª\82 \82é");
+
didlook:
if (looked) {
+ struct permonst *pm = (struct permonst *)0;
+
if (found > 1 || need_to_look) {
char monbuf[BUFSZ];
char temp_buf[BUFSZ];
- (void) lookat(cc.x, cc.y, look_buf, monbuf);
+ pm = lookat(cc.x, cc.y, look_buf, monbuf);
+ if (pm && for_supplement)
+ *for_supplement = pm;
*firstmatch = look_buf;
if (*(*firstmatch)) {
Sprintf(temp_buf, " (%s)", *firstmatch);
found = 1; /* we have something to look up */
}
if (monbuf[0]) {
+/*JP
Sprintf(temp_buf, " [seen: %s]", monbuf);
+*/
+ Sprintf(temp_buf, " [\8e\8b\8ao: %s]", monbuf);
(void) strncat(out_str, temp_buf,
BUFSZ - strlen(out_str) - 1);
}
return found;
}
-/* getpos() return values */
-#define LOOK_TRADITIONAL 0 /* '.' -- ask about "more info?" */
-#define LOOK_QUICK 1 /* ',' -- skip "more info?" */
-#define LOOK_ONCE 2 /* ';' -- skip and stop looping */
-#define LOOK_VERBOSE 3 /* ':' -- show more info w/o asking */
-
/* also used by getpos hack in do_name.c */
/*JP
const char what_is_an_unknown_object[] = "an unknown object";
{
boolean quick = (mode == 1); /* use cursor; don't search for "more info" */
boolean clicklook = (mode == 2); /* right mouse-click method */
- char out_str[BUFSZ];
+ char out_str[BUFSZ] = DUMMY;
const char *firstmatch = 0;
- struct permonst *pm = 0;
+ struct permonst *pm = 0, *supplemental_pm = 0;
int i = '\0', ans = 0;
int sym; /* typed symbol or converted glyph */
int found; /* count of matching syms found */
boolean save_verbose; /* saved value of flags.verbose */
boolean from_screen; /* question from the screen */
+ cc.x = 0;
+ cc.y = 0;
+
if (!clicklook) {
if (quick) {
from_screen = TRUE; /* yes, we want to use the cursor */
i = 'y';
- }
-
- if (i != 'y') {
+ } else {
menu_item *pick_list = (menu_item *) 0;
winid win;
anything any;
break;
}
if (*out_str)
- checkfile(out_str, pm, TRUE, TRUE);
+ checkfile(out_str, pm, TRUE, TRUE, (char *) 0);
return 0;
}
case '?':
getlin("Specify what? (type the word)", out_str);
*/
getlin("\89½\82ð\92²\82×\82é\81H(\95¶\8e\9a\82ð\93ü\82ê\82Ä\82Ë)", out_str);
+ if (strcmp(out_str, " ")) /* keep single space as-is */
+ /* remove leading and trailing whitespace and
+ condense consecutive internal whitespace */
+ mungspaces(out_str);
if (out_str[0] == '\0' || out_str[0] == '\033')
return 0;
if (out_str[1]) { /* user typed in a complete string */
- checkfile(out_str, pm, TRUE, TRUE);
+ checkfile(out_str, pm, TRUE, TRUE, (char *) 0);
return 0;
}
sym = out_str[0];
pline("\95¨\91Ì\82ð\8ew\92è\82µ\82Ä\82\82¾\82³\82¢\81D");
ans = getpos(&cc, quick, what_is_an_unknown_object);
- if (ans < 0 || cc.x < 0) {
- flags.verbose = save_verbose;
- return 0; /* done */
- }
+ if (ans < 0 || cc.x < 0)
+ break; /* done */
flags.verbose = FALSE; /* only print long question once */
}
}
found = do_screen_description(cc, (from_screen || clicklook), sym,
- out_str, &firstmatch);
+ out_str, &firstmatch, &supplemental_pm);
/* Finally, print out our explanation. */
if (found) {
- /* Used putmixed() because there may be an encoded glyph present
- */
+ /* use putmixed() because there may be an encoded glyph present */
putmixed(WIN_MESSAGE, 0, out_str);
+#ifdef DUMPLOG
+ {
+ char dmpbuf[BUFSZ];
+
+ /* putmixed() bypasses pline() so doesn't write to DUMPLOG;
+ tty puts it into ^P recall, so it ought to be there;
+ DUMPLOG is plain text, so override graphics character;
+ at present, force space, but we ought to use defsyms[]
+ value for the glyph the graphics character came from */
+ (void) decode_mixed(dmpbuf, out_str);
+ if (dmpbuf[0] < ' ' || dmpbuf[0] >= 127) /* ASCII isprint() */
+ dmpbuf[0] = ' ';
+ dumplogmsg(dmpbuf);
+ }
+#endif
/* check the data file for information about this thing */
if (found == 1 && ans != LOOK_QUICK && ans != LOOK_ONCE
&& (ans == LOOK_VERBOSE || (flags.help && !quick))
&& !clicklook) {
- char temp_buf[BUFSZ];
+ char temp_buf[BUFSZ], supplemental_name[BUFSZ];
+ supplemental_name[0] = '\0';
Strcpy(temp_buf, firstmatch);
checkfile(temp_buf, pm, FALSE,
- (boolean) (ans == LOOK_VERBOSE));
+ (boolean) (ans == LOOK_VERBOSE), supplemental_name);
+ if (supplemental_pm)
+ do_supplemental_info(supplemental_name, supplemental_pm,
+ (boolean) (ans == LOOK_VERBOSE));
}
} else {
/*JP
*/
pline("\82»\82ñ\82È\96¼\91O\82Í\95·\82¢\82½\82±\82Æ\82ª\82È\82¢\81D");
}
-
} while (from_screen && !quick && ans != LOOK_ONCE && !clicklook);
flags.verbose = save_verbose;
{
winid win;
int x, y, lo_x, lo_y, hi_x, hi_y, glyph, count = 0;
- char buf[BUFSZ], outbuf[BUFSZ], coordbuf[12], fmt[12]; /* "%02d,%02d" */
-
- /* row,column orientation rather than cartesian x,y */
- Sprintf(fmt, "%%%sd,%%%sd",
- (ROWNO <= 100) ? "02" : (ROWNO <= 1000) ? "03" : "",
- (COLNO <= 100) ? "02" : (COLNO <= 1000) ? "03" : "");
+ char lookbuf[BUFSZ], outbuf[BUFSZ];
win = create_nhwindow(NHW_TEXT);
lo_y = nearby ? max(u.uy - BOLT_LIM, 0) : 0;
hi_x = nearby ? min(u.ux + BOLT_LIM, COLNO - 1) : COLNO - 1;
for (y = lo_y; y <= hi_y; y++) {
for (x = lo_x; x <= hi_x; x++) {
- buf[0] = '\0';
+ lookbuf[0] = '\0';
glyph = glyph_at(x, y);
if (do_mons) {
if (glyph_is_monster(glyph)) {
bhitpos.x = x; /* [is this actually necessary?] */
bhitpos.y = y;
if (x == u.ux && y == u.uy && canspotself()) {
- (void) self_lookat(buf);
+ (void) self_lookat(lookbuf);
++count;
} else if ((mtmp = m_at(x, y)) != 0) {
- look_at_monster(buf, (char *) 0, mtmp, x, y);
+ look_at_monster(lookbuf, (char *) 0, mtmp, x, y);
++count;
}
} else if (glyph_is_invisible(glyph)) {
/* remembered, unseen, creature */
- Strcpy(buf, invisexplain);
+ Strcpy(lookbuf, invisexplain);
++count;
} else if (glyph_is_warning(glyph)) {
int warnindx = glyph_to_warning(glyph);
- Strcpy(buf, def_warnsyms[warnindx].explanation);
+ Strcpy(lookbuf, def_warnsyms[warnindx].explanation);
++count;
}
} else { /* !do_mons */
if (glyph_is_object(glyph)) {
- look_at_object(buf, x, y, glyph);
+ look_at_object(lookbuf, x, y, glyph);
++count;
}
}
- if (*buf) {
- if (count == 1) {
- char which[12];
+ if (*lookbuf) {
+ char coordbuf[20], which[12], cmode;
+ cmode = (iflags.getpos_coords != GPCOORDS_NONE)
+ ? iflags.getpos_coords : GPCOORDS_MAP;
+ if (count == 1) {
Strcpy(which, do_mons ? "monsters" : "objects");
- if (nearby) {
- Sprintf(coordbuf, fmt, u.uy, u.ux);
+ if (nearby)
Sprintf(outbuf, "%s currently shown near %s:",
- upstart(which), coordbuf);
- } else
+ upstart(which),
+ (cmode != GPCOORDS_COMPASS)
+ ? coord_desc(u.ux, u.uy, coordbuf, cmode)
+ : !canspotself() ? "your position" : "you");
+ else
Sprintf(outbuf, "All %s currently shown on the map:",
which);
putstr(win, 0, outbuf);
putstr(win, 0, "");
}
- Sprintf(coordbuf, fmt, y, x);
- /* prefix: "C row,column " */
- Sprintf(outbuf, "%s %s ", encglyph(glyph), coordbuf);
+ /* prefix: "coords C " where 'C' is mon or obj symbol */
+ Sprintf(outbuf, (cmode == GPCOORDS_SCREEN) ? "%s "
+ : (cmode == GPCOORDS_MAP) ? "%8s "
+ : "%12s ",
+ coord_desc(x, y, coordbuf, cmode));
+ Sprintf(eos(outbuf), "%s ", encglyph(glyph));
/* guard against potential overflow */
- buf[sizeof buf - 1 - strlen(outbuf)] = '\0';
- Strcat(outbuf, buf);
+ lookbuf[sizeof lookbuf - 1 - strlen(outbuf)] = '\0';
+ Strcat(outbuf, lookbuf);
putmixed(win, 0, outbuf);
}
}
destroy_nhwindow(win);
}
+static const char *suptext1[] = {
+#if 0 /*JP:T*/
+ "%s is a member of a marauding horde of orcs",
+ "rumored to have brutally attacked and plundered",
+ "the ordinarily sheltered town that is located ",
+ "deep within The Gnomish Mines.",
+ "",
+ "The members of that vicious horde proudly and ",
+ "defiantly acclaim their allegiance to their",
+ "leader %s in their names.",
+ (char *) 0,
+#else
+ "%s\82Í\81C\83m\81[\83\80\82Ì\8dz\8eR\82Ì\89\9c\82É\88Ê\92u\82µ\82Ä\82¢\82é",
+ "\92Ê\8fí\92Ê\82è\96h\8cä\82µ\82Ä\82¢\82½\8aX\82ð\97e\8eÍ\82È\82\8dU\8c\82\82µ\82Ä",
+ "\97ª\92D\82µ\82½\82Æ\89\\82³\82ê\82é\81C\83I\81[\83N\82Ì\8fP\8c\82\8fW\92c\82Ì\88ê\88õ\82Å\82 \82é\81D",
+ "",
+ "\82»\82Ì\88«\8e¿\82È\8fW\92c\82Ì\83\81\83\93\83o\81[\82Í\81C\82»\82Ì\83\8a\81[\83_\81[\82Å\82 \82é%s\82Ì\96¼\82Ì\89º\82É",
+ "\8cÖ\82ç\82µ\82°\82©\82Â\92§\90í\93I\82É\82»\82Ì\92\89\90½\82ð\8fÌ\8e^\82µ\82Ä\82¢\82é\81D",
+ (char *) 0,
+#endif
+};
+
+static const char *suptext2[] = {
+#if 0 /*JP:T*/
+ "\"%s\" is the common dungeon name of",
+ "a nefarious orc who is known to acquire property",
+ "from thieves and sell it off for profit.",
+ "",
+ "The perpetrator was last seen hanging around the",
+ "stairs leading to the Gnomish Mines.",
+ (char *) 0,
+#else
+ "\"%s\" \82Í\81C\93\90\91¯\82©\82ç\95¨\95i\82ð\93ü\8eè\82µ\82Ä",
+ "\97\98\89v\82ð\93¾\82é\82½\82ß\82É\94\84\82è\82³\82Î\82\82±\82Æ\82Å\92m\82ç\82ê\82Ä\82¢\82é",
+ "\96³\96@\82È\83I\81[\83N\82Ì\88ê\94Ê\93I\82È\96À\8b{\96¼\82Å\82 \82é\81D",
+ "",
+ "\94Æ\90l\82ª\8dÅ\8cã\82É\96Ú\8c\82\82³\82ê\82½\82Ì\82Í",
+ "\83m\81[\83\80\82Ì\92Y\8dz\82Ö\91±\82\8aK\92i\82Ì\8bß\82\82Å\82 \82é\81D",
+ (char *) 0,
+#endif
+};
+
+void
+do_supplemental_info(name, pm, without_asking)
+char *name;
+struct permonst *pm;
+boolean without_asking;
+{
+ const char **textp;
+ winid datawin = WIN_ERR;
+ char *entrytext = name, *bp = (char *) 0, *bp2 = (char *) 0;
+ char question[QBUFSZ];
+ boolean yes_to_moreinfo = FALSE;
+ boolean is_marauder = (name && pm && is_orc(pm));
+
+ /*
+ * Provide some info on some specific things
+ * meant to support in-game mythology, and not
+ * available from data.base or other sources.
+ */
+ if (is_marauder && (strlen(name) < (BUFSZ - 1))) {
+ char fullname[BUFSZ];
+
+ bp = strstri(name, " of ");
+ bp2 = strstri(name, " the Fence");
+
+ if (bp || bp2) {
+ Strcpy(fullname, name);
+ if (!without_asking) {
+ Strcpy(question, "More info about \"");
+ /* +2 => length of "\"?" */
+ copynchars(eos(question), entrytext,
+ (int) (sizeof question - 1 - (strlen(question) + 2)));
+ Strcat(question, "\"?");
+ if (yn(question) == 'y')
+ yes_to_moreinfo = TRUE;
+ }
+ if (yes_to_moreinfo) {
+ int i, subs = 0;
+ const char *gang = (char *) 0;
+
+ if (bp) {
+ textp = suptext1;
+ gang = bp + 4;
+ *bp = '\0';
+ } else {
+ textp = suptext2;
+ gang = "";
+ }
+ datawin = create_nhwindow(NHW_MENU);
+ for (i = 0; textp[i]; i++) {
+ char buf[BUFSZ];
+ const char *txt;
+
+ if (strstri(textp[i], "%s") != 0) {
+ Sprintf(buf, textp[i], subs++ ? gang : fullname);
+ txt = buf;
+ } else
+ txt = textp[i];
+ putstr(datawin, 0, txt);
+ }
+ display_nhwindow(datawin, FALSE);
+ destroy_nhwindow(datawin), datawin = WIN_ERR;
+ }
+ }
+ }
+}
+
/* the '/' command */
int
dowhatis()
doidtrap()
{
register struct trap *trap;
- int x, y, tt;
+ int x, y, tt, glyph;
if (!getdir("^"))
return 0;
x = u.ux + u.dx;
y = u.uy + u.dy;
+
+ /* check fake bear trap from confused gold detection */
+ glyph = glyph_at(x, y);
+ if (glyph_is_trap(glyph) && (tt = glyph_to_trap(glyph)) == BEAR_TRAP) {
+ boolean chesttrap = trapped_chest_at(tt, x, y);
+
+ if (chesttrap || trapped_door_at(tt, x, y)) {
+/*JP
+ pline("That is a trapped %s.", chesttrap ? "chest" : "door");
+*/
+ pline("\82»\82ê\82Íã©\82ª\8ed\8a|\82¯\82ç\82ê\82½%s\82¾\81D", chesttrap ? "\94 " : "\94à");
+ return 0; /* trap ID'd, but no time elapses */
+ }
+ }
+
for (trap = ftrap; trap; trap = trap->ntrap)
if (trap->tx == x && trap->ty == y) {
if (!trap->tseen)
break;
tt = trap->ttyp;
if (u.dz) {
- if (u.dz < 0 ? (tt == TRAPDOOR || tt == HOLE)
- : tt == ROCKTRAP)
+ if (u.dz < 0 ? is_hole(tt) : tt == ROCKTRAP)
break;
}
- tt = what_trap(tt);
+ tt = what_trap(tt, rn2_on_display_rng);
#if 0 /*JP*/
pline("That is %s%s%s.",
an(defsyms[trap_to_defsym(tt)].explanation),
return 0;
}
+/*
+ Implements a rudimentary if/elif/else/endif interpretor and use
+ conditionals in dat/cmdhelp to describe what command each keystroke
+ currently invokes, so that there isn't a lot of "(debug mode only)"
+ and "(if number_pad is off)" cluttering the feedback that the user
+ sees. (The conditionals add quite a bit of clutter to the raw data
+ but users don't see that. number_pad produces a lot of conditional
+ commands: basic letters vs digits, 'g' vs 'G' for '5', phone
+ keypad vs normal layout of digits, and QWERTZ keyboard swap between
+ y/Y/^Y/M-y/M-Y/M-^Y and z/Z/^Z/M-z/M-Z/M-^Z.)
+
+ The interpretor understands
+ '&#' for comment,
+ '&? option' for 'if' (also '&? !option'
+ or '&? option=value[,value2,...]'
+ or '&? !option=value[,value2,...]'),
+ '&: option' for 'elif' (with argument variations same as 'if';
+ any number of instances for each 'if'),
+ '&:' for 'else' (also '&: #comment';
+ 0 or 1 instance for a given 'if'), and
+ '&.' for 'endif' (also '&. #comment'; required for each 'if').
+
+ The option handling is a bit of a mess, with no generality for
+ which options to deal with and only a comma separated list of
+ integer values for the '=value' part. number_pad is the only
+ supported option that has a value; the few others (wizard/debug,
+ rest_on_space, #if SHELL, #if SUSPEND) are booleans.
+*/
+
+STATIC_DCL void
+whatdoes_help()
+{
+ dlb *fp;
+ char *p, buf[BUFSZ];
+ winid tmpwin = create_nhwindow(NHW_TEXT);
+
+ fp = dlb_fopen(KEYHELP, "r");
+ if (!fp) {
+/*JP
+ pline("Cannot open \"%s\" data file!", KEYHELP);
+*/
+ pline("\83f\81[\83^\83t\83@\83C\83\8b\"%s\"\82ð\8aJ\82¯\82È\82¢\81I", KEYHELP);
+ display_nhwindow(WIN_MESSAGE, TRUE);
+ return;
+ }
+ while (dlb_fgets(buf, (int) sizeof buf, fp)) {
+ if (*buf == '#')
+ continue;
+ for (p = buf; *p; p++)
+ if (*p != ' ' && *p != '\t')
+ break;
+ putstr(tmpwin, 0, p);
+ }
+ (void) dlb_fclose(fp);
+ display_nhwindow(tmpwin, TRUE);
+ destroy_nhwindow(tmpwin);
+}
+
+#if 0
+#define WD_STACKLIMIT 5
+struct wd_stack_frame {
+ Bitfield(active, 1);
+ Bitfield(been_true, 1);
+ Bitfield(else_seen, 1);
+};
+
+STATIC_DCL boolean FDECL(whatdoes_cond, (char *, struct wd_stack_frame *,
+ int *, int));
+
+STATIC_OVL boolean
+whatdoes_cond(buf, stack, depth, lnum)
+char *buf;
+struct wd_stack_frame *stack;
+int *depth, lnum;
+{
+ const char badstackfmt[] = "cmdhlp: too many &%c directives at line %d.";
+ boolean newcond, neg, gotopt;
+ char *p, *q, act = buf[1];
+ int np = 0;
+
+ newcond = (act == '?' || !stack[*depth].been_true);
+ buf += 2;
+ mungspaces(buf);
+ if (act == '#' || *buf == '#' || !*buf || !newcond) {
+ gotopt = (*buf && *buf != '#');
+ *buf = '\0';
+ neg = FALSE; /* lint suppression */
+ p = q = (char *) 0;
+ } else {
+ gotopt = TRUE;
+ if ((neg = (*buf == '!')) != 0)
+ if (*++buf == ' ')
+ ++buf;
+ p = index(buf, '='), q = index(buf, ':');
+ if (!p || (q && q < p))
+ p = q;
+ if (p) { /* we have a value specified */
+ /* handle a space before or after (or both) '=' (or ':') */
+ if (p > buf && p[-1] == ' ')
+ p[-1] = '\0'; /* end of keyword in buf[] */
+ *p++ = '\0'; /* terminate keyword, advance to start of value */
+ if (*p == ' ')
+ p++;
+ }
+ }
+ if (*buf && (act == '?' || act == ':')) {
+ if (!strcmpi(buf, "number_pad")) {
+ if (!p) {
+ newcond = iflags.num_pad;
+ } else {
+ /* convert internal encoding (separate yes/no and 0..3)
+ back to user-visible one (-1..4) */
+ np = iflags.num_pad ? (1 + iflags.num_pad_mode) /* 1..4 */
+ : (-1 * iflags.num_pad_mode); /* -1..0 */
+ newcond = FALSE;
+ for (; p; p = q) {
+ q = index(p, ',');
+ if (q)
+ *q++ = '\0';
+ if (atoi(p) == np) {
+ newcond = TRUE;
+ break;
+ }
+ }
+ }
+ } else if (!strcmpi(buf, "rest_on_space")) {
+ newcond = flags.rest_on_space;
+ } else if (!strcmpi(buf, "debug") || !strcmpi(buf, "wizard")) {
+ newcond = flags.debug; /* == wizard */
+ } else if (!strcmpi(buf, "shell")) {
+#ifdef SHELL
+ /* should we also check sysopt.shellers? */
+ newcond = TRUE;
+#else
+ newcond = FALSE;
+#endif
+ } else if (!strcmpi(buf, "suspend")) {
+#ifdef SUSPEND
+ /* sysopt.shellers is also used for dosuspend()... */
+ newcond = TRUE;
+#else
+ newcond = FALSE;
+#endif
+ } else {
+ impossible(
+ "cmdhelp: unrecognized &%c conditional at line %d: \"%.20s\"",
+ act, lnum, buf);
+ neg = FALSE;
+ }
+ /* this works for number_pad too: &? !number_pad:-1,0
+ would be true for 1..4 after negation */
+ if (neg)
+ newcond = !newcond;
+ }
+ switch (act) {
+ default:
+ case '#': /* comment */
+ break;
+ case '.': /* endif */
+ if (--*depth < 0) {
+ impossible(badstackfmt, '.', lnum);
+ *depth = 0;
+ }
+ break;
+ case ':': /* else or elif */
+ if (*depth == 0 || stack[*depth].else_seen) {
+ impossible(badstackfmt, ':', lnum);
+ *depth = 1; /* so that stack[*depth - 1] is a valid access */
+ }
+ if (stack[*depth].active || stack[*depth].been_true
+ || !stack[*depth - 1].active)
+ stack[*depth].active = 0;
+ else if (newcond)
+ stack[*depth].active = stack[*depth].been_true = 1;
+ if (!gotopt)
+ stack[*depth].else_seen = 1;
+ break;
+ case '?': /* if */
+ if (++*depth >= WD_STACKLIMIT) {
+ impossible(badstackfmt, '?', lnum);
+ *depth = WD_STACKLIMIT - 1;
+ }
+ stack[*depth].active = (newcond && stack[*depth - 1].active) ? 1 : 0;
+ stack[*depth].been_true = stack[*depth].active;
+ stack[*depth].else_seen = 0;
+ break;
+ }
+ return stack[*depth].active ? TRUE : FALSE;
+}
+#endif /* 0 */
+
char *
dowhatdoes_core(q, cbuf)
char q;
char *cbuf;
{
+ char buf[BUFSZ];
+#if 0
dlb *fp;
- char bufr[BUFSZ];
- register char *buf = &bufr[6], *ep, ctrl, meta;
-
+ struct wd_stack_frame stack[WD_STACKLIMIT];
+ boolean cond;
+ int ctrl, meta, depth = 0, lnum = 0;
+#endif /* 0 */
+ const char *ec_desc;
+
+ if ((ec_desc = key2extcmddesc(q)) != NULL) {
+ char keybuf[QBUFSZ];
+
+ Sprintf(buf, "%-8s%s.", key2txt(q, keybuf), ec_desc);
+ Strcpy(cbuf, buf);
+ return cbuf;
+ }
+ return 0;
+#if 0
fp = dlb_fopen(CMDHELPFILE, "r");
if (!fp) {
-#if 0 /*JP*/
- pline("Cannot open data file!");
-#else
- pline("\83f\81[\83^\83t\83@\83C\83\8b\82ð\8aJ\82¯\82È\82¢\81I");
-#endif
+ pline("Cannot open \"%s\" data file!", CMDHELPFILE);
return 0;
}
- ctrl = ((q <= '\033') ? (q - 1 + 'A') : 0);
- meta = ((0x80 & q) ? (0x7f & q) : 0);
- while (dlb_fgets(buf, BUFSZ - 6, fp)) {
- if ((ctrl && *buf == '^' && *(buf + 1) == ctrl)
- || (meta && *buf == 'M' && *(buf + 1) == '-'
- && *(buf + 2) == meta) || *buf == q) {
- ep = index(buf, '\n');
- if (ep)
- *ep = 0;
- if (ctrl && buf[2] == '\t') {
- buf = bufr + 1;
- (void) strncpy(buf, "^? ", 8);
- buf[1] = ctrl;
- } else if (meta && buf[3] == '\t') {
- buf = bufr + 2;
+ meta = (0x80 & (uchar) q) != 0;
+ if (meta)
+ q &= 0x7f;
+ ctrl = (0x1f & (uchar) q) == (uchar) q;
+ if (ctrl)
+ q |= 0x40; /* NUL -> '@', ^A -> 'A', ... ^Z -> 'Z', ^[ -> '[', ... */
+ else if (q == 0x7f)
+ ctrl = 1, q = '?';
+
+ (void) memset((genericptr_t) stack, 0, sizeof stack);
+ cond = stack[0].active = 1;
+ while (dlb_fgets(buf, sizeof buf, fp)) {
+ ++lnum;
+ if (buf[0] == '&' && buf[1] && index("?:.#", buf[1])) {
+ cond = whatdoes_cond(buf, stack, &depth, lnum);
+ continue;
+ }
+ if (!cond)
+ continue;
+ if (meta ? (buf[0] == 'M' && buf[1] == '-'
+ && (ctrl ? buf[2] == '^' && highc(buf[3]) == q
+ : buf[2] == q))
+ : (ctrl ? buf[0] == '^' && highc(buf[1]) == q
+ : buf[0] == q)) {
+ (void) strip_newline(buf);
+ if (index(buf, '\t'))
+ (void) tabexpand(buf);
+ if (meta && ctrl && buf[4] == ' ') {
+ (void) strncpy(buf, "M-^? ", 8);
+ buf[3] = q;
+ } else if (meta && buf[3] == ' ') {
(void) strncpy(buf, "M-? ", 8);
- buf[2] = meta;
- } else if (buf[1] == '\t') {
- buf = bufr;
+ buf[2] = q;
+ } else if (ctrl && buf[2] == ' ') {
+ (void) strncpy(buf, "^? ", 8);
+ buf[1] = q;
+ } else if (buf[1] == ' ') {
+ (void) strncpy(buf, "? ", 8);
buf[0] = q;
- (void) strncpy(buf + 1, " ", 7);
}
(void) dlb_fclose(fp);
Strcpy(cbuf, buf);
}
}
(void) dlb_fclose(fp);
+ if (depth != 0)
+ impossible("cmdhelp: mismatched &? &: &. conditionals.");
return (char *) 0;
+#endif /* 0 */
}
int
dowhatdoes()
{
+ static boolean once = FALSE;
char bufr[BUFSZ];
char q, *reslt;
+ if (!once) {
+#if 0 /*JP*/
+ pline("Ask about '&' or '?' to get more info.%s",
+#ifdef ALTMETA
+ iflags.altmeta ? " (For ESC, type it twice.)" :
+#endif
+ "");
+#else
+ pline("\82³\82ç\82È\82é\8fî\95ñ\82É\82Â\82¢\82Ä\82Í '&' \82© '?' \82É\82Â\82¢\82Ä\82½\82¸\82Ë\82Ü\82·\81D%s",
+#ifdef ALTMETA
+ iflags.altmeta ? " (ESC\82É\82Â\82¢\82Ä\82Í\81C2\89ñ\83^\83C\83v\82µ\82Ü\82·\81D)" :
+#endif
+ "");
+#endif
+ once = TRUE;
+ }
#if defined(UNIX) || defined(VMS)
- introff();
+ introff(); /* disables ^C but not ^\ */
#endif
/*JP
q = yn_function("What command?", (char *) 0, '\0');
*/
q = yn_function("\82Ç\82¤\82¢\82¤\83R\83}\83\93\83h\81H", (char *) 0, '\0');
+#ifdef ALTMETA
+ if (q == '\033' && iflags.altmeta) {
+ /* in an ideal world, we would know whether another keystroke
+ was already pending, but this is not an ideal world...
+ if user typed ESC, we'll essentially hang until another
+ character is typed */
+ q = yn_function("]", (char *) 0, '\0');
+ if (q != '\033')
+ q = (char) ((uchar) q | 0200);
+ }
+#endif /*ALTMETA*/
#if defined(UNIX) || defined(VMS)
- intron();
+ intron(); /* reenables ^C */
#endif
reslt = dowhatdoes_core(q, bufr);
- if (reslt)
- pline1(reslt);
- else
-/*JP
- pline("I've never heard of such commands.");
-*/
- pline("\82»\82ñ\82È\83R\83}\83\93\83h\82Í\95·\82¢\82½\82±\82Æ\82ª\82È\82¢\81D");
+ if (reslt) {
+ if (q == '&' || q == '?')
+ whatdoes_help();
+ pline("%s", reslt);
+ } else {
+#if 0 /*JP*/
+ pline("No such command '%s', char code %d (0%03o or 0x%02x).",
+ visctrl(q), (uchar) q, (uchar) q, (uchar) q);
+#else
+ pline("\82»\82ñ\82È\83R\83}\83\93\83h'%s'\81C\95¶\8e\9a\83R\81[\83h%d(0%03o \82Ü\82½\82Í 0x%02x)\82Í\82È\82¢\81D",
+ visctrl(q), (uchar) q, (uchar) q, (uchar) q);
+#endif
+ }
return 0;
}
-void
-docontact()
+STATIC_OVL void
+docontact(VOID_ARGS)
{
winid cwin = create_nhwindow(NHW_TEXT);
char buf[BUFSZ];
destroy_nhwindow(cwin);
}
-/* data for help_menu() */
-static const char *help_menu_items[] = {
-#if 0 /*JP*/
- /* 0*/ "About NetHack (version information).",
- /* 1*/ "Long description of the game and commands.",
- /* 2*/ "List of game commands.",
- /* 3*/ "Concise history of NetHack.",
- /* 4*/ "Info on a character in the game display.",
- /* 5*/ "Info on what a given key does.",
- /* 6*/ "List of game options.",
- /* 7*/ "Longer explanation of game options.",
- /* 8*/ "List of extended commands.",
- /* 9*/ "The NetHack license.",
- /* 10*/ "Support information.",
-#ifdef PORT_HELP
- "%s-specific help and commands.",
-#define PORT_HELP_ID 100
-#define WIZHLP_SLOT 12
-#else
-#define WIZHLP_SLOT 11
-#endif
- "List of wizard-mode commands.", "", (char *) 0
-#else /*JP*/
- /* 0*/ "NetHack\82É\82Â\82¢\82Ä(\83o\81[\83W\83\87\83\93\8fî\95ñ)",
- /* 1*/ "\83Q\81[\83\80\82¨\82æ\82Ñ\83R\83}\83\93\83h\82Ì\89ð\90à(\92·\95¶)",
- /* 2*/ "\83R\83}\83\93\83h\88ê\97\97",
- /* 3*/ "NetHack\82Ì\8aÈ\92P\82È\97ð\8ej",
- /* 4*/ "\89æ\96Ê\82É\95\\8e¦\82³\82ê\82é\95¶\8e\9a\82Ì\90à\96¾",
- /* 5*/ "\82±\82Ì\83L\81[\82ª\89½\82ð\88Ó\96¡\82·\82é\82©\82Ì\90à\96¾",
- /* 6*/ "\83Q\81[\83\80\82Ì\83I\83v\83V\83\87\83\93\88ê\97\97",
- /* 7*/ "\83Q\81[\83\80\82Ì\83I\83v\83V\83\87\83\93\88ê\97\97(\92·\95¶)",
- /* 8*/ "\8ag\92£\83R\83}\83\93\83h\88ê\97\97",
- /* 9*/ "NetHack\82Ì\83\89\83C\83Z\83\93\83X",
- /* 10*/ "\83T\83|\81[\83g\8fî\95ñ",
+void
+dispfile_help(VOID_ARGS)
+{
+ display_file(HELP, TRUE);
+}
+
+void
+dispfile_shelp(VOID_ARGS)
+{
+ display_file(SHELP, TRUE);
+}
+
+void
+dispfile_optionfile(VOID_ARGS)
+{
+ display_file(OPTIONFILE, TRUE);
+}
+
+void
+dispfile_license(VOID_ARGS)
+{
+ display_file(LICENSE, TRUE);
+}
+
+void
+dispfile_debughelp(VOID_ARGS)
+{
+ display_file(DEBUGHELP, TRUE);
+}
+
+void
+hmenu_doextversion(VOID_ARGS)
+{
+ (void) doextversion();
+}
+
+void
+hmenu_dohistory(VOID_ARGS)
+{
+ (void) dohistory();
+}
+
+void
+hmenu_dowhatis(VOID_ARGS)
+{
+ (void) dowhatis();
+}
+
+void
+hmenu_dowhatdoes(VOID_ARGS)
+{
+ (void) dowhatdoes();
+}
+
+void
+hmenu_doextlist(VOID_ARGS)
+{
+ (void) doextlist();
+}
+
+void
+domenucontrols(VOID_ARGS)
+{
+ winid cwin = create_nhwindow(NHW_TEXT);
+ show_menu_controls(cwin, FALSE);
+ display_nhwindow(cwin, FALSE);
+ destroy_nhwindow(cwin);
+}
+
+/* data for dohelp() */
+static struct {
+ void NDECL((*f));
+ const char *text;
+} help_menu_items[] = {
+/*JP
+ { hmenu_doextversion, "About NetHack (version information)." },
+*/
+ { hmenu_doextversion, "NetHack\82É\82Â\82¢\82Ä(\83o\81[\83W\83\87\83\93\8fî\95ñ)" },
+/*JP
+ { dispfile_help, "Long description of the game and commands." },
+*/
+ { dispfile_help, "\83Q\81[\83\80\82¨\82æ\82Ñ\83R\83}\83\93\83h\82Ì\89ð\90à(\92·\95¶)" },
+/*JP
+ { dispfile_shelp, "List of game commands." },
+*/
+ { dispfile_shelp, "\83R\83}\83\93\83h\88ê\97\97" },
+/*JP
+ { hmenu_dohistory, "Concise history of NetHack." },
+*/
+ { hmenu_dohistory, "NetHack\82Ì\8aÈ\92P\82È\97ð\8ej" },
+/*JP
+ { hmenu_dowhatis, "Info on a character in the game display." },
+*/
+ { hmenu_dowhatis, "\89æ\96Ê\82É\95\\8e¦\82³\82ê\82é\95¶\8e\9a\82Ì\90à\96¾" },
+/*JP
+ { hmenu_dowhatdoes, "Info on what a given key does." },
+*/
+ { hmenu_dowhatdoes, "\82±\82Ì\83L\81[\82ª\89½\82ð\88Ó\96¡\82·\82é\82©\82Ì\90à\96¾" },
+/*JP
+ { option_help, "List of game options." },
+*/
+ { option_help, "\83Q\81[\83\80\82Ì\83I\83v\83V\83\87\83\93\88ê\97\97" },
+/*JP
+ { dispfile_optionfile, "Longer explanation of game options." },
+*/
+ { dispfile_optionfile, "\83Q\81[\83\80\82Ì\83I\83v\83V\83\87\83\93\88ê\97\97(\92·\95¶)" },
+/*JP
+ { dokeylist, "Full list of keyboard commands" },
+*/
+ { dokeylist, "\83L\81[\83{\81[\83h\83R\83}\83\93\83h\82Ì\8a®\91S\82È\88ê\97\97" },
+/*JP
+ { hmenu_doextlist, "List of extended commands." },
+*/
+ { hmenu_doextlist, "\8ag\92£\83R\83}\83\93\83h\88ê\97\97" },
+/*JP
+ { domenucontrols, "List menu control keys" },
+*/
+ { domenucontrols, "\83\81\83j\83\85\81[\90§\8cä\83L\81[\88ê\97\97s" },
+/*JP
+ { dispfile_license, "The NetHack license." },
+*/
+ { dispfile_license, "NetHack\82Ì\83\89\83C\83Z\83\93\83X" },
+/*JP
+ { docontact, "Support information." },
+*/
+ { docontact, "\83T\83|\81[\83g\8fî\95ñ" },
#ifdef PORT_HELP
- "%s\82É\93Á\97L\82Ì\83w\83\8b\83v\82¨\82æ\82Ñ\83R\83}\83\93\83h",
-#define PORT_HELP_ID 100
-#define WIZHLP_SLOT 12
-#else
-#define WIZHLP_SLOT 11
+/*JP
+ { port_help, "%s-specific help and commands." },
+*/
+ { port_help, "%s\82É\93Á\97L\82Ì\83w\83\8b\83v\82Æ\83R\83}\83\93\83h" },
#endif
- "\83E\83B\83U\81[\83h\83\82\81[\83h\82Ì\83R\83}\83\93\83h\88ê\97\97", "", (char *) 0
-#endif /*JP*/
+/*JP
+ { dispfile_debughelp, "List of wizard-mode commands." },
+*/
+ { dispfile_debughelp, "\83E\83B\83U\81[\83h\83\82\81[\83h\82Ì\83R\83}\83\93\83h\88ê\97\97" },
+ { (void NDECL((*))) 0, (char *) 0 }
};
-STATIC_OVL boolean
-help_menu(sel)
-int *sel;
+/* the '?' command */
+int
+dohelp()
{
winid tmpwin = create_nhwindow(NHW_MENU);
-#ifdef PORT_HELP
char helpbuf[QBUFSZ];
-#endif
int i, n;
menu_item *selected;
anything any;
+ int sel;
any = zeroany; /* zero all bits */
start_menu(tmpwin);
- if (!wizard)
- help_menu_items[WIZHLP_SLOT] = "",
- help_menu_items[WIZHLP_SLOT + 1] = (char *) 0;
- for (i = 0; help_menu_items[i]; i++)
-#ifdef PORT_HELP
- /* port-specific line has a %s in it for the PORT_ID */
- if (help_menu_items[i][0] == '%') {
- Sprintf(helpbuf, help_menu_items[i], PORT_ID);
- any.a_int = PORT_HELP_ID + 1;
- add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, helpbuf,
- MENU_UNSELECTED);
- } else
-#endif
- {
- any.a_int = (*help_menu_items[i]) ? i + 1 : 0;
- add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
- help_menu_items[i], MENU_UNSELECTED);
+
+ for (i = 0; help_menu_items[i].text; i++) {
+ if (!wizard && help_menu_items[i].f == dispfile_debughelp)
+ continue;
+ if (help_menu_items[i].text[0] == '%') {
+ Sprintf(helpbuf, help_menu_items[i].text, PORT_ID);
+ } else {
+ Strcpy(helpbuf, help_menu_items[i].text);
}
+ any.a_int = i + 1;
+ add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
+ helpbuf, MENU_UNSELECTED);
+ }
/*JP
end_menu(tmpwin, "Select one item:");
*/
n = select_menu(tmpwin, PICK_ONE, &selected);
destroy_nhwindow(tmpwin);
if (n > 0) {
- *sel = selected[0].item.a_int - 1;
+ sel = selected[0].item.a_int - 1;
free((genericptr_t) selected);
- return TRUE;
- }
- return FALSE;
-}
-
-/* the '?' command */
-int
-dohelp()
-{
- int sel = 0;
-
- if (help_menu(&sel)) {
- switch (sel) {
- case 0:
- (void) doextversion();
- break;
- case 1:
- display_file(HELP, TRUE);
- break;
- case 2:
- display_file(SHELP, TRUE);
- break;
- case 3:
- (void) dohistory();
- break;
- case 4:
- (void) dowhatis();
- break;
- case 5:
- (void) dowhatdoes();
- break;
- case 6:
- option_help();
- break;
- case 7:
- display_file(OPTIONFILE, TRUE);
- break;
- case 8:
- (void) doextlist();
- break;
- case 9:
- display_file(LICENSE, TRUE);
- break;
- case 10:
- (void) docontact();
- break;
-#ifdef PORT_HELP
- case PORT_HELP_ID:
- port_help();
- break;
-#endif
- default:
- /* handle slot 11 or 12 */
- display_file(DEBUGHELP, TRUE);
- break;
- }
+ (void) (*help_menu_items[sel].f)();
}
return 0;
}