From: PatR Date: Fri, 30 Jun 2017 00:54:01 +0000 (-0700) Subject: robustness of #timeout and #wizintrinsic X-Git-Tag: NetHack-3.6.1_RC01~462 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ff6139c6c55b579788a2596f2f109613dabb6c46;p=nethack robustness of #timeout and #wizintrinsic Remove the assumption of property index values from the list of property names. Move the properties that can't have timed values in normal play to after those which can. (Mainly only matters for the #wizintrinsic command.) Bug fix: #wizintrinsic variable 'any' wasn't initialized properly if 'a_int' is smaller than a long or a pointer. The separator line I've added was ending up as a menu choice. --- diff --git a/include/prop.h b/include/prop.h index cb4cd3fde..3bbc7182f 100644 --- a/include/prop.h +++ b/include/prop.h @@ -7,7 +7,7 @@ /*** What the properties are *** * - * note: propertynames[] array in timeout.c must be kept in synch with these. + * note: propertynames[] array in timeout.c has string values for these. * Property #0 is not used. */ /* Resistances to troubles */ diff --git a/src/cmd.c b/src/cmd.c index 2ec304a8a..ade3352cd 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -135,6 +135,7 @@ STATIC_PTR int NDECL(wiz_level_change); STATIC_PTR int NDECL(wiz_show_seenv); STATIC_PTR int NDECL(wiz_show_vision); STATIC_PTR int NDECL(wiz_smell); +STATIC_PTR int NDECL(wiz_intrinsic); STATIC_PTR int NDECL(wiz_mon_polycontrol); STATIC_PTR int NDECL(wiz_show_wmodes); STATIC_DCL void NDECL(wiz_map_levltyp); @@ -1157,29 +1158,37 @@ STATIC_PTR int wiz_intrinsic(VOID_ARGS) { if (wizard) { - extern const char *const propertynames[]; /* timeout.c */ + extern const struct propname { + int prop_num; + const char *prop_name; + } propertynames[]; /* timeout.c */ static const char wizintrinsic[] = "#wizintrinsic"; static const char fmt[] = "You are%s %s."; winid win; anything any; char buf[BUFSZ]; - int i, n, p, amt, typ; + int i, j, n, p, amt, typ; long oldtimeout, newtimeout; const char *propname; menu_item *pick_list = (menu_item *) 0; + any = zeroany; win = create_nhwindow(NHW_MENU); start_menu(win); - - for (i = 1; (propname = propertynames[i]) != 0; ++i) { - if (i == HALLUC_RES) { + for (i = 0; (propname = propertynames[i].prop_name) != 0; ++i) { + p = propertynames[i].prop_num; + if (p == HALLUC_RES) { /* Grayswandir vs hallucination; ought to be redone to use u.uprops[HALLUC].blocked instead of being treated as a separate property; letting in be manually toggled even only in wizard mode would be asking for trouble... */ continue; } - any.a_int = i; + if (p == FIRE_RES) { + any.a_int = 0; + add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "--", FALSE); + } + any.a_int = i + 1; /* +1: avoid 0 */ add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, propname, FALSE); } end_menu(win, "Which intrinsics?"); @@ -1187,8 +1196,9 @@ wiz_intrinsic(VOID_ARGS) destroy_nhwindow(win); amt = 30; /* TODO: prompt for duration */ - for (i = 0; i < n; ++i) { - p = pick_list[i].item.a_int; + for (j = 0; j < n; ++j) { + i = pick_list[j].item.a_int - 1; /* -1: reverse +1 above */ + p = propertynames[i].prop_num; oldtimeout = u.uprops[p].intrinsic & TIMEOUT; newtimeout = oldtimeout + (long) amt; switch (p) { @@ -1204,9 +1214,12 @@ wiz_intrinsic(VOID_ARGS) case BLINDED: make_blinded(newtimeout, TRUE); break; +#if 0 /* make_confused() only gives feedback when confusion is + * ending so use the 'default' case for it instead */ case CONFUSION: make_confused(newtimeout, TRUE); break; +#endif /*0*/ case DEAF: make_deaf(newtimeout, TRUE); break; @@ -1236,7 +1249,7 @@ wiz_intrinsic(VOID_ARGS) pline1(buf); break; default: - pline("Timeout for %s %s %d.", propertynames[p], + pline("Timeout for %s %s %d.", propertynames[i].prop_name, oldtimeout ? "increased by" : "set to", amt); incr_itimeout(&u.uprops[p].intrinsic, amt); break; diff --git a/src/timeout.c b/src/timeout.c index 66add4ec8..81285fc37 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -15,43 +15,83 @@ STATIC_DCL void FDECL(see_lamp_flicker, (struct obj *, const char *)); STATIC_DCL void FDECL(lantern_message, (struct obj *)); STATIC_DCL void FDECL(cleanup_burn, (ANY_P *, long)); -/* the order of these must match their numerical sequence in prop.h - because the property number is inferred from the array index; - used by wizard mode #timeout and #wizintrinsic */ -const char *const propertynames[] = { - "0: not used", -/* Resistances */ - /* 1..2 */ "fire resistance", "cold resistance", - /* 3..4 */ "sleep resistance", "disintegration resistance", - /* 5..6 */ "shock resistance", "poison resistance", - /* 7..8 */ "acid resistance", "stoning resistance", - /* 9..10 */ "drain resistance", "sickness resistance", - /* 11..12 */ "invulnerable", "magic resistance", -/* Troubles */ - /* 13..16 */ "stunned", "confused", "blinded", "deafness", - /* 17..20 */ "fatally sick", "petrifying", "strangling", "vomiting", - /* 21..22 */ "slippery fingers", "becoming slime", - /* 23..24 */ "hallucinating", "halluicination resistance", - /* 25..28 */ "fumbling", "wounded legs", "sleepy", "voracious hunger", -/* Vision and senses */ - /* 29..30 */ "see invisible", "telepathic", - /* 31..33 */ "warning", "warn:monster", "warn:undead", - /* 34..37 */ "searching", "clairvoyant", "infravision", "monster detection", -/* Appearance and behavior */ - /* 38..41 */ "adorned (+/-Cha)", "invisible", "displaced", "stealthy", - /* 42..43 */ "monster aggrevation", "conflict", -/* Transportation */ - /* 44..46 */ "jumping", "teleporting", "teleport control", - /* 47..49 */ "levitating", "flying", "water walking", - /* 50..52 */ "swimming", "magical breathing", "pass thru walls", -/* Physical attributes */ - /* 53..55 */ "slow digestion", "half spell damage", "half physical damage", - /* 56..58 */ "HP regeneration", "energy regeneration", "extra protection", - /* 59 */ "protection from shape changers", - /* 60..62 */ "polymorphing", "polymorph control", "unchanging", - /* 63..66 */ "fast", "reflecting", "free action", "fixed abilites", - /* 67 */ "life will be saved", - 0 /* sentinel */ +/* used by wizard mode #timeout and #wizintrinsic; order by 'interest' + for timeout countdown, where most won't occur in normal play */ +const struct propname { + int prop_num; + const char *prop_name; +} propertynames[] = { + { INVULNERABLE, "invulnerable" }, + { STONED, "petrifying" }, + { SLIMED, "becoming slime" }, + { STRANGLED, "strangling" }, + { SICK, "fatally sick" }, + { STUNNED, "stunned" }, + { CONFUSION, "confused" }, + { HALLUC, "hallucinating" }, + { BLINDED, "blinded" }, + { DEAF, "deafness" }, + { VOMITING, "vomiting" }, + { GLIB, "slippery fingers" }, + { WOUNDED_LEGS, "wounded legs" }, + { SLEEPY, "sleepy" }, + { TELEPORT, "teleporting" }, + { POLYMORPH, "polymorphing" }, + { LEVITATION, "levitating" }, + { FAST, "very fast" }, /* timed 'FAST' is very fast */ + { CLAIRVOYANT, "clairvoyant" }, + { DETECT_MONSTERS, "monster detection" }, + { SEE_INVIS, "see invisible" }, + { INVIS, "invisible" }, + /* properties beyond here don't have timed values during normal play, + so there's no much point in trying to order them sensibly; + they're either on or off based on equipment, role, actions, &c */ + { FIRE_RES, "fire resistance" }, + { COLD_RES, "cold resistance" }, + { SLEEP_RES, "sleep resistance" }, + { DISINT_RES, "disintegration resistance" }, + { SHOCK_RES, "shock resistance" }, + { POISON_RES, "poison resistance" }, + { ACID_RES, "acid resistance" }, + { STONE_RES, "stoning resistance" }, + { DRAIN_RES, "drain resistance" }, + { SICK_RES, "sickness resistance" }, + { ANTIMAGIC, "magic resistance" }, + { HALLUC_RES, "hallucination resistance" }, + { FUMBLING, "fumbling" }, + { HUNGER, "voracious hunger" }, + { TELEPAT, "telepathic" }, + { WARNING, "warning" }, + { WARN_OF_MON, "warn: monster type or class" }, + { WARN_UNDEAD, "warn: undead" }, + { SEARCHING, "searching" }, + { INFRAVISION, "infravision" }, + { ADORNED, "adorned (+/- Cha)" }, + { DISPLACED, "displaced" }, + { STEALTH, "stealthy" }, + { AGGRAVATE_MONSTER, "monster aggravation" }, + { CONFLICT, "conflict" }, + { JUMPING, "jumping" }, + { TELEPORT_CONTROL, "teleport control" }, + { FLYING, "flying" }, + { WWALKING, "water walking" }, + { SWIMMING, "swimming" }, + { MAGICAL_BREATHING, "magical breathing" }, + { PASSES_WALLS, "pass thru walls" }, + { SLOW_DIGESTION, "slow digestion" }, + { HALF_SPDAM, "half spell damage" }, + { HALF_PHDAM, "half physical damage" }, + { REGENERATION, "HP regeneration" }, + { ENERGY_REGENERATION, "energy regeneration" }, + { PROTECTION, "extra protection" }, + { PROT_FROM_SHAPE_CHANGERS, "protection from shape changers" }, + { POLYMORPH_CONTROL, "polymorph control" }, + { UNCHANGING, "unchanging" }, + { REFLECTING, "reflecting" }, + { FREE_ACTION, "free action" }, + { FIXED_ABIL, "fixed abilites" }, + { LIFESAVED, "life will be saved" }, + { 0, 0 }, }; /* He is being petrified - dialogue by inmet!tower */ @@ -1544,7 +1584,7 @@ wiz_timeout_queue() char buf[BUFSZ]; const char *propname; long intrinsic; - int i, count, longestlen, ln; + int i, p, count, longestlen, ln, specindx = 0; win = create_nhwindow(NHW_MENU); /* corner text window */ if (win == WIN_ERR) @@ -1562,13 +1602,16 @@ wiz_timeout_queue() * normal play but those can be forced via the #wizintrinsic command. */ count = longestlen = 0; - for (i = 1; (propname = propertynames[i]) != 0; ++i) { /* [0] not used */ - intrinsic = u.uprops[i].intrinsic; + for (i = 0; (propname = propertynames[i].prop_name) != 0; ++i) { + p = propertynames[i].prop_num; + intrinsic = u.uprops[p].intrinsic; if (intrinsic & TIMEOUT) { ++count; if ((ln = (int) strlen(propname)) > longestlen) longestlen = ln; } + if (specindx == 0 && p == FIRE_RES) + specindx = i; } putstr(win, 0, ""); if (!count) { @@ -1576,9 +1619,14 @@ wiz_timeout_queue() } else { putstr(win, 0, "Timed properties:"); putstr(win, 0, ""); - for (i = 1; (propname = propertynames[i]) != 0; ++i) { - intrinsic = u.uprops[i].intrinsic; + for (i = 0; (propname = propertynames[i].prop_name) != 0; ++i) { + p = propertynames[i].prop_num; + intrinsic = u.uprops[p].intrinsic; if (intrinsic & TIMEOUT) { + if (specindx > 0 && i >= specindx) { + putstr(win, 0, " -- settable via #wizinstrinc only --"); + specindx = 0; + } /* timeout value can be up to 16777215 (0x00ffffff) but width of 4 digits should result in values lining up almost all the time (if/when they don't, it won't