From: nhmall Date: Fri, 7 Oct 2022 14:26:40 +0000 (-0400) Subject: during devel make it easy to review mon difficulty X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b0029472debe2a15dd535c9b320d3d482d9006ef;p=nethack during devel make it easy to review mon difficulty --- diff --git a/include/extern.h b/include/extern.h index 9f6a426c6..51f13b319 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1604,6 +1604,9 @@ extern void pacify_guards(void); extern void decide_to_shapeshift(struct monst *, int); extern boolean vamp_stone(struct monst *); extern void check_gear_next_turn(struct monst *); +#if (NH_DEVEL_STATUS != NH_STATUS_RELEASED) || defined(DEBUG) +extern int mstrength(struct permonst *ptr); +#endif /* ### mondata.c ### */ diff --git a/src/cmd.c b/src/cmd.c index 804c0f017..beb6011bc 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -17,6 +17,7 @@ #endif #if (NH_DEVEL_STATUS != NH_STATUS_RELEASED) || defined(DEBUG) static int wiz_display_macros(void); +static int wiz_check_mdifficulty(void); #endif #ifdef DUMB /* stuff commented out in extern.h, but needed here */ @@ -2756,6 +2757,8 @@ struct ext_func_tab extcmdlist[] = { { C('e'), "wizdetect", "reveal hidden things within a small radius", wiz_detect, IFBURIED | WIZMODECMD, NULL }, #if (NH_DEVEL_STATUS != NH_STATUS_RELEASED) || defined(DEBUG) + { '\0', "wizcheckmdifficulty", "validate the difficulty levels of monsters", + wiz_check_mdifficulty, IFBURIED | AUTOCOMPLETE | WIZMODECMD, NULL }, { '\0', "wizdispmacros", "validate the display macro ranges", wiz_display_macros, IFBURIED | AUTOCOMPLETE | WIZMODECMD, NULL }, #endif @@ -4088,6 +4091,39 @@ wiz_display_macros(void) } #endif /* (NH_DEVEL_STATUS != NH_STATUS_RELEASED) || defined(DEBUG) */ +#if (NH_DEVEL_STATUS != NH_STATUS_RELEASED) || defined(DEBUG) +/* the #wizcheckmdifficulty command */ +static int +wiz_check_mdifficulty(void) +{ + char buf[BUFSZ]; + winid win; + int mhardcoded = 0, mcalculated = 0, trouble = 0, cnt = 0, mdiff = 0; + struct permonst *ptr; + static const char *const display_issues = "Review of monster difficulties:"; + + win = create_nhwindow(NHW_TEXT); + for (ptr = &mons[0]; ptr->mlet; ptr++, cnt++) { + mcalculated = mstrength(ptr); + mhardcoded = (int) ptr->difficulty; + mdiff = mhardcoded - mcalculated; + if (mdiff) { + trouble++; + Snprintf(buf, sizeof buf, + "%-18s [%4d]: calculated: %2d, hardcoded: %2d (%+d)", + ptr->pmnames[NEUTRAL], cnt, mcalculated, mhardcoded, + mdiff); + putstr(win, 0, buf); + } + } + if (!trouble) + putstr(win, 0, "No monster difficulty discrepencies were detected"); + display_nhwindow(win, FALSE); + destroy_nhwindow(win); + return ECMD_OK; +} +#endif /* (NH_DEVEL_STATUS != NH_STATUS_RELEASED) || defined(DEBUG) */ + RESTORE_WARNING_FORMAT_NONLITERAL static void diff --git a/src/mon.c b/src/mon.c index cc18b0c46..6e5f359e6 100644 --- a/src/mon.c +++ b/src/mon.c @@ -30,6 +30,10 @@ static struct permonst *accept_newcham_form(struct monst *, int); static void kill_eggs(struct obj *); static void pacify_guard(struct monst *); +#ifdef DEBUG +int mstrength(struct permonst *ptr); +#endif + #define LEVEL_SPECIFIC_NOCORPSE(mdat) \ (Is_rogue_level(&u.uz) \ || (g.level.flags.graveyard && is_undead(mdat) && rn2(3))) @@ -5177,4 +5181,63 @@ check_gear_next_turn(struct monst *mon) mon->misc_worn_check |= I_SPECIAL; } +#if (NH_DEVEL_STATUS != NH_STATUS_RELEASED) || defined(DEBUG) +/* This routine is designed to return an integer value which represents + * an approximation of monster strength. It uses a similar method of + * determination as "experience()" to arrive at the strength. + */ +int +mstrength(struct permonst *ptr) +{ + int i, tmp2, n, tmp = ptr->mlevel; + + if(tmp > 49) /* special fixed hp monster */ + tmp = 2*(tmp - 6) / 4; + +/* For creation in groups */ + n = (!!(ptr->geno & G_SGROUP)); + n += (!!(ptr->geno & G_LGROUP)) << 1; + +/* For ranged attacks */ + if (ranged_attk(ptr)) n++; + +/* For higher ac values */ + n += (ptr->ac < 4); + n += (ptr->ac < 0); + +/* For very fast monsters */ + n += (ptr->mmove >= 18); + +/* For each attack and "special" attack */ + for(i = 0; i < NATTK; i++) { + + tmp2 = ptr->mattk[i].aatyp; + n += (tmp2 > 0); + n += (tmp2 == AT_MAGC); + n += (tmp2 == AT_WEAP && (ptr->mflags2 & M2_STRONG)); + } + +/* For each "special" damage type */ + for(i = 0; i < NATTK; i++) { + + tmp2 = ptr->mattk[i].adtyp; + if ((tmp2 == AD_DRLI) || (tmp2 == AD_STON) || (tmp2 == AD_DRST) + || (tmp2 == AD_DRDX) || (tmp2 == AD_DRCO) || (tmp2 == AD_WERE)) + n += 2; + else if (strcmp(ptr->pmnames[NEUTRAL], "grid bug")) n += (tmp2 != AD_PHYS); + n += ((int) (ptr->mattk[i].damd * ptr->mattk[i].damn) > 23); + } + +/* Leprechauns are special cases. They have many hit dice so they + can hit and are hard to kill, but they don't really do much damage. */ + if (!strcmp(ptr->pmnames[NEUTRAL], "leprechaun")) n -= 2; + +/* Finally, adjust the monster level 0 <= n <= 24 (approx.) */ + if(n == 0) tmp--; + else if(n >= 6) tmp += ( n / 2 ); + else tmp += ( n / 3 + 1); + + return((tmp >= 0) ? tmp : 0); +} +#endif /* (NH_DEVEL_STATUS != NH_STATUS_RELEASED) || DEBUG */ /*mon.c*/