From 926d9833d3d62e593471b064117e08bee7b1c40c Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Mon, 21 Jan 2008 19:07:33 +0000 Subject: [PATCH] enlightenment revamp, part II (trunk only) Split enlightenment output into two sections: Status and Attributes. Status began life as the set of bottom line status conditions and steadily grew to include many things which ought to be such conditions but aren't because of lack of space there. It also adds a few missing enlightenment entries for Underwater (separate from magical breathing), Punished, trapped, and stuck to cursed saddle. Most of the lesser status conditions with bottom line tags (Confusion, Hallucination, &c) used to be shown only for end-of-game disclosure but now get included all the time. They aren't necessarily redundant if/when a very long bottom line is being truncated. The ^X changes are still to come. --- src/attrib.c | 19 ++- src/cmd.c | 344 +++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 279 insertions(+), 84 deletions(-) diff --git a/src/attrib.c b/src/attrib.c index 12604141c..138b3f2ac 100644 --- a/src/attrib.c +++ b/src/attrib.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)attrib.c 3.5 2007/03/19 */ +/* SCCS Id: @(#)attrib.c 3.5 2008/01/21 */ /* Copyright 1988, 1989, 1990, 1992, M. Stephenson */ /* NetHack may be freely redistributed. See license for details. */ @@ -687,6 +687,7 @@ int propidx; /* special cases can have negative values */ static NEARDATA const char because_of[] = " because of %s"; if (propidx >= 0) { + char *p; struct obj *obj = (struct obj *)0; int innate = is_innate(propidx); @@ -696,9 +697,17 @@ int propidx; /* special cases can have negative values */ Strcpy(buf, " innately"); else if (wizard && (obj = what_gives(&u.uprops[propidx].extrinsic))) Sprintf(buf, because_of, - (obj->oartifact) ? bare_artifactname(obj) : yname(obj)); + obj->oartifact ? bare_artifactname(obj) : + ysimple_name(obj)); else if (propidx == BLINDED && Blindfolded_only) - Sprintf(buf, because_of, yname(ublindf)); + Sprintf(buf, because_of, ysimple_name(ublindf)); + + /* remove some verbosity and/or redundancy */ + if ((p = strstri(buf, " pair of ")) != 0) + do ++p; while ((*p = *(p + 8)) != '\0'); + else if (propidx == STRANGLED && + (p = strstri(buf, " of strangulation")) != 0) + *p = '\0'; } else { /* negative property index */ /* if more blocking capabilities get implemented we'll need to @@ -710,11 +719,11 @@ int propidx; /* special cases can have negative values */ break; case INVIS: if (u.uprops[INVIS].blocked & W_ARMC) - Sprintf(buf, because_of, yname(uarmc)); /* mummy wrapping */ + Sprintf(buf, because_of, ysimple_name(uarmc)); /* mummy wrapping */ break; case CLAIRVOYANT: if (wizard && (u.uprops[CLAIRVOYANT].blocked & W_ARMH)) - Sprintf(buf, because_of, yname(uarmh)); /* cornuthaum */ + Sprintf(buf, because_of, ysimple_name(uarmh)); /* cornuthaum */ break; } } diff --git a/src/cmd.c b/src/cmd.c index b63a529b8..2017978cf 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -8,6 +8,9 @@ struct cmd Cmd = { 0 }; /* flag.h */ +extern const char *hu_stat[]; /* hunger status from eat.c */ +extern const char *enc_stat[]; /* encumbrance status from botl.c */ + #ifdef UNIX /* * Some systems may have getchar() return EOF for various reasons, and @@ -161,6 +164,8 @@ STATIC_PTR boolean NDECL(minimal_enlightenment); STATIC_DCL void FDECL(enlght_line, (const char *,const char *,const char *,char *)); STATIC_DCL char *FDECL(enlght_combatinc, (const char *,int,int,char *)); STATIC_DCL void FDECL(enlght_halfdmg, (int,int)); +STATIC_DCL boolean NDECL(walking_on_water); +STATIC_DCL boolean FDECL(cause_known, (int)); static const char* readchar_queue=""; static coord clicklook_cc; @@ -1045,17 +1050,262 @@ int final; enl_msg(You_, "take", "took", buf, from_what(category)); } +/* is hero actively using water walking capability on water (or lava)? */ +STATIC_OVL boolean +walking_on_water() +{ + if (u.uinwater || Levitation || Flying) return FALSE; + return (Wwalking && (is_pool(u.ux, u.uy) || is_lava(u.ux, u.uy))); +} + +/* check whether hero is wearing something that player definitely knows + confers the target property; item must have been seen and its type + discovered but it doesn't necessarily have to be fully identified */ +STATIC_OVL boolean +cause_known(propindx) +int propindx; /* index of a property which can be conveyed by worn item */ +{ + register struct obj *o; + long mask = W_ARMOR | W_AMUL | W_RING | W_TOOL; + + /* simpler than from_what()/what_gives(); we don't attempt to + handle artifacts and we deliberately ignore wielded items */ + for (o = invent; o; o = o->nobj) { + if (!(o->owornmask & mask)) continue; + if ((int)objects[o->otyp].oc_oprop == propindx && + objects[o->otyp].oc_name_known && o->dknown) + return TRUE; + } + return FALSE; +} + void enlightenment(mode, final) int mode; /* BASICENLIGHTENMENT | MAGICENLIGHTENMENT (| both) */ int final; /* ENL_GAMEINPROGRESS:0, ENL_GAVEOVERALIVE, ENL_GAMEOVERDEAD */ { - int ltmp, armpro; - char buf[BUFSZ]; + boolean magic = (mode & MAGICENLIGHTENMENT) ? TRUE : FALSE; + int cap, armpro, ltmp; + char buf[BUFSZ], youtoo[BUFSZ]; +#ifdef STEED + boolean Riding = (u.usteed && + /* if hero dies while dismounting, u.usteed will still + be set; we want to ignore steed in that situation */ + !(final == ENL_GAMEOVERDEAD && + !strcmp(killer.name, "riding accident"))); + const char *steedname = !Riding ? (char *)0 : + x_monnam(u.usteed, + u.usteed->mtame ? ARTICLE_YOUR : ARTICLE_THE, + (char *)0, + (SUPPRESS_SADDLE | SUPPRESS_HALLUCINATION), + FALSE); +#endif en_win = create_nhwindow(NHW_MENU); - putstr(en_win, 0, final ? "Final Attributes:" : "Current Attributes:"); + + /*\ + * Status (many are abbreviated on bottom line; others are or + * should be discernible to the hero hence to the player) + \*/ + putstr(en_win, 0, final ? "Final Status:" : "Current Status:"); + + Strcpy(youtoo, You_); + /* not a traditional status but inherently obvious to player; + more detail provided below for magic enlightenment */ + if (Upolyd) you_are("transformed", ""); +#ifdef STEED + /* not a trouble, but we want to display riding status before maybe + reporting steed as trapped or hero stuck to cursed saddle */ + if (Riding) { + Sprintf(buf, "riding %s", steedname); + you_are(buf, ""); + Sprintf(eos(youtoo), "and %s ", steedname); + } +#endif /*STEED*/ + /* other movement situations that hero should always know */ + if (Levitation) { + if (Lev_at_will && magic) + you_are("levitating, at will", ""); + else + enl_msg(youtoo, are, were, "levitating", from_what(LEVITATION)); + } + if (Flying) { + if (Levitation) + you_can("also fly", from_what(FLYING)); + else + enl_msg(youtoo, are, were, "flying", from_what(FLYING)); + } + if (Underwater) { + you_are("underwater", ""); + } else if (u.uinwater) { + you_are(Swimming ? "swimming" : "in water", from_what(SWIMMING)); + } else if (walking_on_water()) { + /* show active Wwalking here, potential Wwalking elsewhere */ + Sprintf(buf, "walking on %s", + is_pool(u.ux, u.uy) ? "water" : + is_lava(u.ux, u.uy) ? "lava" : + surface(u.ux, u.uy)); /* catchall; shouldn't happen */ + you_are(buf, from_what(WWALKING)); + } + /* internal troubles, mostly in the order that prayer ranks them */ + if (Stoned) you_are("turning to stone", ""); + if (Slimed) you_are("turning into slime", ""); + if (Strangled) { + if (u.uburied) { + you_are("buried", ""); + } else { + Strcpy(buf, "being strangled"); +#ifdef WIZARD + if (wizard) Sprintf(eos(buf), " (%ld)", (Strangled & TIMEOUT)); +#endif + you_are(buf, from_what(STRANGLED)); + } + } + if (Sick) { + /* prayer lumps these together; botl puts Ill before FoodPois */ + if (u.usick_type & SICK_NONVOMITABLE) + you_are("terminally sick from illness", ""); + if (u.usick_type & SICK_VOMITABLE) + you_are("terminally sick from food poisoning", ""); + } + if (Vomiting) you_are("nauseated", ""); + if (Stunned) you_are("stunned", ""); + if (Confusion) you_are("confused", ""); + if (Hallucination) you_are("hallucinating", ""); + if (Blind) you_are("blind", from_what(BLINDED)); + if (Deaf) you_are("deaf", from_what(DEAF)); + /* external troubles, more or less */ + if (Punished) { + if (uball) { + Sprintf(buf, "chained to %s", ansimpleoname(uball)); + } else { + impossible("Punished without uball?"); + Strcpy(buf, "punished"); + } + you_are(buf, ""); + } + if (u.utrap) { + char predicament[BUFSZ]; + struct trap *t; + boolean anchored = (u.utraptype == TT_BURIEDBALL); + + if (anchored) { + Strcpy(predicament, "tethered to something buried"); + } else if (u.utraptype == TT_INFLOOR || u.utraptype == TT_LAVA) { + Sprintf(predicament, "stuck in %s", the(surface(u.ux, u.uy))); + } else { + Strcpy(predicament, "trapped"); + if ((t = t_at(u.ux, u.uy)) != 0) + Sprintf(eos(predicament), " in %s", + an(defsyms[trap_to_defsym(t->ttyp)].explanation)); + } +#ifdef STEED + if (u.usteed) { /* not `Riding' here */ + Sprintf(buf, "%s%s ", anchored ? "you and " : "", steedname); + *buf = highc(*buf); + enl_msg(buf, (anchored ? "are " : "is "), + (anchored ? "were " : "was "), predicament, ""); + } else +#endif /*STEED*/ + you_are(predicament, ""); + } /* (u.utrap) */ + if (u.uswallow) { + Sprintf(buf, "swallowed by %s", a_monnam(u.ustuck)); +#ifdef WIZARD + if (wizard) Sprintf(eos(buf), " (%u)", u.uswldtim); +#endif + you_are(buf, ""); + } else if (u.ustuck) { + Sprintf(buf, "%s %s", + (Upolyd && sticks(youmonst.data)) ? "holding" : "held by", + a_monnam(u.ustuck)); + you_are(buf, ""); + } +#ifdef STEED + if (Riding) { + struct obj *saddle = which_armor(u.usteed, W_SADDLE); + + if (saddle && saddle->cursed) { + Sprintf(buf, "stuck to %s %s", + s_suffix(steedname), simpleonames(saddle)); + you_are(buf, ""); + } + } +#endif /*STEED*/ + if (Wounded_legs) { +#ifdef STEED + /* when mounted, Wounded_legs applies to steed rather than to + hero; we only report steed's wounded legs in wizard mode */ + if (u.usteed) { /* not `Riding' here */ +# ifdef WIZARD + if (wizard) { + Strcpy(buf, steedname); + *buf = highc(*buf); + enl_msg(buf, " has", " had", " wounded legs", ""); + } +# endif + } else +#endif /*STEED*/ + { + Sprintf(buf, "wounded %s", makeplural(body_part(LEG))); + you_have(buf, ""); + } + } + if (Glib) { + Sprintf(buf, "slippery %s", makeplural(body_part(FINGER))); + you_have(buf, ""); + } + if (Fumbling) { + if (magic || cause_known(FUMBLING)) + enl_msg(You_, "fumble", "fumbled", "", from_what(FUMBLING)); + } + if (Sleeping) { + if (magic || cause_known(SLEEPING)) + enl_msg("You ", "fall", "fell", " asleep uncontrollably", + from_what(SLEEPING)); + } + /* hunger/nutrition */ + if (Hunger) { + if (magic || cause_known(HUNGER)) + enl_msg(You_, "hunger", "hungered", " rapidly", + from_what(HUNGER)); + } + Strcpy(buf, hu_stat[u.uhs]); /* hunger status; omitted if "normal" */ + mungspaces(buf); /* strip trailing spaces */ + if (*buf) { + *buf = lowc(*buf); /* override capitalization */ + if (!strcmp(buf, "weak")) + Strcat(buf, " from severe hunger"); + else if (!strncmp(buf, "faint", 5)) /* fainting, fainted */ + Strcat(buf, " due to starvation"); + you_are(buf, ""); + } + /* encumbrance */ + if ((cap = near_capacity()) > UNENCUMBERED) { + const char *adj = "?_?"; /* (should always get overridden) */ + + Strcpy(buf, enc_stat[cap]); + *buf = lowc(*buf); + switch (cap) { + case SLT_ENCUMBER: adj = "slightly"; break; /* burdened */ + case MOD_ENCUMBER: adj = "moderately"; break; /* stressed */ + case HVY_ENCUMBER: adj = "very"; break; /* strained */ + case EXT_ENCUMBER: adj = "extremely"; break; /* overtaxed */ + case OVERLOADED: adj = "not possible"; break; + } + Sprintf(eos(buf), "; movement %s %s%s", !final ? "is" : "was", + adj, (cap < OVERLOADED) ? " slowed" : ""); + you_are(buf, ""); + } else { + /* last resort entry, guarantees Status section is non-empty */ + you_are("unencumbered", ""); + } + + /*\ + * Attributes + \*/ putstr(en_win, 0, ""); + putstr(en_win, 0, final ? "Final Attributes:" : "Current Attributes:"); #ifdef ELBERETH if (u.uevent.uhand_of_elbereth) { @@ -1087,6 +1337,8 @@ int final; /* ENL_GAMEINPROGRESS:0, ENL_GAVEOVERALIVE, ENL_GAMEOVERDEAD */ #endif /*** Resistances to troubles ***/ + if (Invulnerable) you_are("invulnerable",from_what(INVULNERABLE)); + if (Antimagic) you_are("magic-protected",from_what(ANTIMAGIC)); if (Fire_resistance) you_are("fire resistant",from_what(FIRE_RES)); if (Cold_resistance) you_are("cold resistant",from_what(COLD_RES)); if (Sleep_resistance) you_are("sleep resistant",from_what(SLEEP_RES)); @@ -1094,61 +1346,16 @@ int final; /* ENL_GAMEINPROGRESS:0, ENL_GAVEOVERALIVE, ENL_GAMEOVERDEAD */ you_are("disintegration-resistant",from_what(DISINT_RES)); if (Shock_resistance) you_are("shock resistant",from_what(SHOCK_RES)); if (Poison_resistance) you_are("poison resistant",from_what(POISON_RES)); + if (Acid_resistance) you_are("acid resistant",from_what(ACID_RES)); if (Drain_resistance) you_are("level-drain resistant",from_what(DRAIN_RES)); if (Sick_resistance) you_are("immune to sickness",from_what(SICK_RES)); - if (Antimagic) you_are("magic-protected",from_what(ANTIMAGIC)); - if (Acid_resistance) you_are("acid resistant",from_what(ACID_RES)); if (Stone_resistance) you_are("petrification resistant",from_what(STONE_RES)); - if (Invulnerable) you_are("invulnerable",from_what(INVULNERABLE)); - if (u.uedibility) you_can("recognize detrimental food",""); - - /*** Troubles ***/ if (Halluc_resistance) - enl_msg("You resist", "", "ed", " hallucinations", + enl_msg(You_, "resist", "resisted", " hallucinations", from_what(HALLUC_RES)); - if (final) { - if (Hallucination) you_are("hallucinating",""); - if (Stunned) you_are("stunned",""); - if (Confusion) you_are("confused",""); - if (Blind) you_are("blind",from_what(BLINDED)); - if (Deaf) you_are("deaf",from_what(DEAF)); - if (Sick) { - if (u.usick_type & SICK_VOMITABLE) - you_are("sick from food poisoning",""); - if (u.usick_type & SICK_NONVOMITABLE) - you_are("sick from illness",""); - } - } - if (Stoned) you_are("turning to stone",""); - if (Slimed) you_are("turning into slime",""); - if (Strangled) you_are((u.uburied) ? "buried" : "being strangled",""); - if (Vomiting) you_are("nauseated",""); - if (Glib) { - Sprintf(buf, "slippery %s", makeplural(body_part(FINGER))); - you_have(buf,""); - } - if (Fumbling) enl_msg("You fumble", "", "d", "",from_what(FUMBLING)); - if (Wounded_legs -#ifdef STEED - && !u.usteed -#endif - ) { - Sprintf(buf, "wounded %s", makeplural(body_part(LEG))); - you_have(buf,""); - } -#if defined(WIZARD) && defined(STEED) - if (Wounded_legs && u.usteed && wizard) { - Strcpy(buf, x_monnam(u.usteed, ARTICLE_YOUR, (char *)0, - SUPPRESS_SADDLE | SUPPRESS_HALLUCINATION, FALSE)); - *buf = highc(*buf); - enl_msg(buf, " has", " had", " wounded legs", ""); - } -#endif - if (Sleeping) enl_msg("You ", "fall", "fell", " asleep", ""); - if (Hunger) enl_msg("You hunger", "", "ed", " rapidly", ""); - if (Hate_silver) you_are("harmed by silver",""); + if (u.uedibility) you_can("recognize detrimental food",""); /*** Vision and senses ***/ if (!Blind && (Blinded || !haseyes(youmonst.data))) @@ -1230,36 +1437,15 @@ int final; /* ENL_GAMEINPROGRESS:0, ENL_GAVEOVERALIVE, ENL_GAMEOVERDEAD */ if (Teleportation) you_can("teleport",from_what(TELEPORT)); if (Teleport_control) you_have("teleport control",from_what(TELEPORT_CONTROL)); - if (Lev_at_will) you_are("levitating, at will", ""); - else if (Levitation) - you_are("levitating",from_what(LEVITATION)); /* without control */ - else if (Flying) you_can("fly",from_what(FLYING)); - if (Wwalking) you_can("walk on water",from_what(WWALKING)); - if (Swimming) you_can("swim",from_what(SWIMMING)); + /* actively walking on water handled earlier as a status condition */ + if (Wwalking && !walking_on_water()) + you_can("walk on water",from_what(WWALKING)); + /* actively swimming (in water but not under it) handled earlier */ + if (Swimming && (Underwater || !u.uinwater)) + you_can("swim",from_what(SWIMMING)); if (Breathless) you_can("survive without air",from_what(MAGICAL_BREATHING)); else if (Amphibious) you_can("breathe water",from_what(MAGICAL_BREATHING)); if (Passes_walls) you_can("walk through walls",from_what(PASSES_WALLS)); -#ifdef STEED - /* If you die while dismounting, u.usteed is still set. Since several - * places in the done() sequence depend on u.usteed, just detect this - * special case. */ - if (u.usteed && (final < 2 || strcmp(killer.name, "riding accident"))) { - Sprintf(buf, "riding %s", y_monnam(u.usteed)); - you_are(buf,""); - } -#endif - if (u.uswallow) { - Sprintf(buf, "swallowed by %s", a_monnam(u.ustuck)); -#ifdef WIZARD - if (wizard) Sprintf(eos(buf), " (%u)", u.uswldtim); -#endif - you_are(buf,""); - } else if (u.ustuck) { - Sprintf(buf, "%s %s", - (Upolyd && sticks(youmonst.data)) ? "holding" : "held by", - a_monnam(u.ustuck)); - you_are(buf,""); - } /*** Physical attributes ***/ if (Regeneration) @@ -1309,6 +1495,7 @@ int final; /* ENL_GAMEINPROGRESS:0, ENL_GAVEOVERALIVE, ENL_GAMEOVERDEAD */ you_are(buf,""); } if (Unchanging) you_can("not change from your current form",""); + if (Hate_silver) you_are("harmed by silver",""); if (Fast) you_are(Very_fast ? "very fast" : "fast",from_what(FAST)); if (Reflecting) you_have("reflection",from_what(REFLECTING)); if (Free_action) you_have("free action",from_what(FREE_ACTION)); @@ -1316,7 +1503,6 @@ int final; /* ENL_GAMEINPROGRESS:0, ENL_GAVEOVERALIVE, ENL_GAMEOVERDEAD */ if (Lifesaved) enl_msg("Your life ", "will be", "would have been", " saved",""); if (u.twoweap) you_are("wielding two weapons at once",""); - if (u.utraptype == TT_BURIEDBALL) you_are("fastened to a buried ball",""); /*** Miscellany ***/ if (Luck) { -- 2.40.0