User:Tungtn/Physical damage analysis

From NetHackWiki
Jump to navigation Jump to search

There are a number of complaints that tend to pop up with respect to late game NetHack, such as:

  • Late game is too easy/dull/boring/grindy/repetitive.
    • "grind" in this sense means to do the same thing over and over whilst advancing, not in order to build up power.
  • Gehennom "is a bit of a clobber-or-cast-fest".
  • Ascension kit is too rigid/not enough equipment variety.
  • Every game post-Castle feels the same.

I wanted to look at one factor that contributes to these feelings: late game physical damage.

I have two main hypotheses that damage has unwanted impacts on how late game NetHack plays:

  1. It is possible to inflict so much damage that all monsters can be trivially dealt with by killing them, denying opportunities for alternative tactics, e.g. zapping, kiting, falling back to chokepoints, teleporting them away, teleporting yourself, exploiting monster AI, etc. This also leads to anti-climatic confrontations, e.g. killing the Wizard of Yendor or Riders in 2 or 3 hits.
  2. Certain equipment choices and tactics (e.g. #twoweapon) do so much more damage relative to their alternatives that they are almost always chosen, independent of race and role, leading to different characters making the same decisions and therefore playing very similarly.

The following notes cover NetHack, DynaHack (since I'm the DynaHack maintainer and I have a vested interest in improving it), and also a bit of UnNetHack, SporkHack and dNetHack.

Contents

Aims

NetHack has been seen for a long time as broken, imbalanced and forever unfixable. I'd like to see if that's really the case.

More specifically, here's what I'd like to come from all of this:

  • Increase reliance on moment-to-moment tactics in late game NetHack to reduce boredom.
  • Make equipment choices and tactics more role-dependent, making different roles feel less samey.
  • Make adjustments to damage that are big enough to be noticed, but don't go so far as to invalidate other mechanics.
  • Build a foundation to eventually make accuracy relevant in the late game of NetHack, like in the early and mid game.

Related factors and assumptions

These notes don't cover the concepts of to-hit or speed, so I'll touch on them here.

To-hit

To-hit is NetHack's way of simulating combat accuracy. The way it works is that a target number is added together from all factors that would affect whether or not an attempted physical attack lands, like your experience level, your skill, your luck, the weapon's to-hit bonus, the weapon's enchantment, the monster's AC and armor, and a bunch of other things. If that target number is greater than a d20 roll, you get the hit, otherwise you miss. This system has a few outcomes:

  1. If the target number is 21 or higher, you will always hit.
  2. If the target number is 1 or lower, you will always miss.
  3. Target numbers from 2 to 20 inclusive give a chance to hit from 5% to 95%, in 5% increments.

For the purpose of looking at late game damage, I'm assuming that every hit lands, which seems to be the case in most games. I suspect the biggest contributing factors to this are:

  • Experience level - +15 to hit at level 15; there's a one-to-one relationship here for all characters.
  • Luck - +13 to hit: +10 is the natural maximum luck, and +3 comes from having more not-cursed luck sources than cursed ones.
  • Weapon enchantment - +6 or +7; that is, +1 to hit for every +1 enchantment.

This sums to about +34 or +35 (before dexterity: 18 dex adds +4 to this, 25 dex adds +11). For perspective, monster AC values are pulled directly from Source:monst.c (only modified by worn armor which most monsters don't have; consult Source:worn.c#find_mac) and vary from 10 (gnomes and gnome lords) to -10 (Master Kaen). In other words, the worst target number for a hit with standard late game strategy is +24, which means that normal late game hits will never miss!

Other notable monster AC values:

  • -8 AC for the Wizard of Yendor.
  • -5 AC for the Riders (Death, Pestilence and Famine).
  • -2 to -8 AC for the demon princes:
    • -2 AC - Dispater
    • -3 AC - Geryon
    • -5 AC - Yeenoghu and Baalzebub
    • -6 AC - Orcus
    • -7 AC - Juiblex and Asmodeus
    • -8 AC - Demogorgon
  • 9 AC for lichens and other fungi (yes, sessile fungi have better AC than gnomes).
  • 10 AC for the Yendorian Army (soldiers, sergeants, lieutenants, captains) and the watch (watchmen, watch captains), but they spawn with armor randomly selected to approximate target AC values; see Source:makemon.c#m_initinv.

Interesting quote from MetaFilter about experience level in to-hit in D&D (from John Harris, writer of the now-defunct roguelike column @Play):

http://www.metafilter.com/143037/But-waityour-medallion-begins-to-glow#5751697

I had a thought a little while ago. One of the complaints, and it's one that I agree with, about the game is that, while the early game demands a variety of approached depending on role, the late game tends to be about smacking things until they die, whether you're a barbarian, archeologist, wizard, tourist or healer. I think I've figured out a major part of the reason for that. It's that, unlike D&D, all the characters advance in their to-hit rate at the same speed, which is the same as that of the classic D&D Fighter: +1 to hit per level.
If non-combat-wombats had less than a bucketfull of to-hit, it'd force them towards using alternative means of killing monsters. It'd make some classes much more difficult unless special care were taken to balance though. Maybe different to-hit tracks for melee and missile weapons, so Rangers could uniquely excel with missile weapons.

Speed

The wiki page on speed covers the nitty gritty technical details, but I'll summarize what assumptions I'm working off of.

In general, speed affects how many actions you get per turn:

  • action - a player input that leads to in-game consequences.
  • turn - a fixed unit of in-game time, the same way you might think of "seconds" or "minutes" in the real world.

There are three speed levels relevant to standard strategy: normal (100%), fast (133%) and very fast (166%). There are three sources of very fast speed: speed boots, potions of speed and the haste self spell. Out of these options, speed boots are the only permanent (read: won't run out) source of very fast speed, so naturally they form part of the standard ascension kit.

An important thing to note is that speed affects all actions equally, whether you choose to move, use an item, or most importantly attack.

From all this, it's safe to assume that players that enter Gehennom are:

  1. permanently very fast (due to speed boots), and
  2. can attack 66% more often than monsters that move at normal speed

These notes on damage DO NOT account for speed, so if you see a damage number and you're fighting a monster that is normal speed, you need to increase that damage number by 66% to get damage-per-turn, rather than damage-per-player-action.

Sources of damage

The main sources of damage are:

  • weapon base damage: one-handed weapons tend to do between d2 and d12 damage
  • weapon enchantment: directly added to damage, so e.g. a +7 weapon grants +7 bonus damage
  • artifact bonus damage: adds either fixed damage or double damage, usually applied conditionally
    • fixed damage is used if the artifact bonus damage value is non-zero (see artilist.h), ranges from +d6 (Cleaver) to +d10 (Excalibur), with +d24 from Mjollnir as an outlier
    • double damage is used if the artifact bonus damage value is zero; doubling applies to weapon base damage, enchantment and rogue backstab
  • artifact special effects: things like d8 life draining from Stormbringer, double damage vs. large from Tsurugi of Muramasa, and extra damage and effects for Magicbane (yes, this is done after artifact damage doubling, e.g. Staff of Aesculapius)
  • strength: -1 to +6 damage
  • skill damage modifier
    • -2 to +2 for most hits
    • -3 to +1 for two-weapon hits
    • +1 to +3 for bare-handed combat
    • +3 to +9 for martial arts
    • +0 to +2 for riding (stacks)

Strength

Strength Damage Notes
3-5 -1
6-15 +0 common start bonus
16-17 +1
18 +2 elf max
18/01-18/75 +3 gnome and orc max
18/76-18/90 +4
18/91-18/99 +5
18/**-25 +6 human and dwarf max

DynaHack, UnNetHack and SporkHack go further:

Strength Damage Notes
18/** +6 vampire max (DynaHack and UnNetHack only)
25 +7 DynaHack, UnNetHack and SporkHack

Skill

Damage modifiers come from one of normal weapon skills, two-weapon skill, bare-handed combat and martial arts.

On top of this, riding skill stacks its own bonus on top of one of those four skill tables.

Normal weapon skills

Weapon skill level Damage
restricted and unskilled -2
basic +0
skilled +1
expert +2

DynaHack and dNetHack go further:

Skill level Damage Notes
restricted -5 DynaHack and dNetHack only
expert +3 DynaHack and dNetHack only

Two-weapon skill

Two-weapon is handled in a peculiar way: for each hit, you take the lesser of the skill of the hitting weapon and the two-weapon skill, then use the damage table in this section instead of the weapon skill table.

Two-weapon skill level Damage
restricted and unskilled -3
basic -1
skilled +0
expert +1

DynaHack and dNetHack go further:

Two-weapon skill level Damage Notes
expert +2 DynaHack and dNetHack only

Bare-handed combat

Bare-handed skill Damage Notes
unskilled +0
basic and skilled +1
expert and master +2
grand master +3 N/A; no role can reach this

Martial arts

Martial arts is bare-handed combat special-cased to Samurai and Monks, with higher damage and perks like staggering blows.

Martial arts skill Damage Notes
unskilled +1 N/A; martial arts roles always start at basic
basic +3
skilled +4
expert +6
master +7 Samurai max
grand master +9 Monk max

Special note: If the base damage rolled for a weapon and its enchantment does 1 damage (the minimum), it won't train the skill, but more importantly it won't get bonus damage from skill either. For most skill damage tables this distinction is negligible, but martial arts is treated like a d4 weapon, meaning 1-in-4 martial arts hits don't get the skill damage bonus. I account for this difference for Monk martial arts, but I omit it elsewhere.

DynaHack and UnNetHack always grant the skill damage bonus, in contrast to NetHack.

Riding skill

Unlike the other skill damage tables, this one stacks with the others.

Riding skill Damage
unskilled and basic +0
skilled +1
expert +2

DynaHack and dNetHack go further:

Riding skill Damage Notes
skilled +2 DynaHack and dNetHack only
expert +5 DynaHack and dNetHack only

Dealing with dice

The values that I've calculated express damage from D notation (or dice notation) give three values: minimum, average (mean) and maximum, like so:

   d6 = 1 / 3.5 / 6

That is, a single 6-sided die rolls a minimum of 1, an average of 3.5 and a maximum of 6.

The way to calculate the average of dice in the form of xdy is x * (y + 1) / 2, e.g. the average of 3d5 is 3 * (5 + 1) / 2 = 9.

hmon_hitmon and valid_weapon_attack

hmon_hitmon() is the core function where damage done by the player to a monster is calculated and ultimately inflicted. It pulls together the base damage done by a weapon from dmgval() (or rolls a d4 itself for bare-handed combat or martial arts), calls artifact_hit() for bonus damage and effects for artifact weapons, then stacks on your increase damage bonus, your strength damage bonus, your skill damage bonus, poison damage or instakill, silver damage and many other potential effects on hit.

Apart from the damage itself (tmp), the valid_weapon_attack flag is the most important variable of the whole function. In short, it determines whether the skill damage bonus is applied to the final damage, as well as whether the skill relevant to the attack (if any) is trained. The way valid_weapon_attack is set and used can be seen in this cut-down reproduction of the hmon_hitmon() function:

/* Note: rnd(x) returns a number from 1 to x inclusive. */

boolean hmon_hitmon(mon, obj, thrown)
{
    int tmp;
    boolean valid_weapon_attack = FALSE;

    if (!obj) { /* attack with bare hands */
        if (/* martial arts role */) {
            tmp = rnd(4);
        } else {
            tmp = rnd(2);
        }
        valid_weapon_attack = (tmp > 1);
    } else {
        if (/* potentially a proper weapon */) {
            if (/* invalid method of attack, e.g. hitting with a bow */) {
                tmp = rnd(2);
            } else {
                /* valid method of attack with a proper weapon */
                tmp = dmgval(obj, mon); /* <-- WEAPON BASE DAMAGE ROLLED HERE */
                valid_weapon_attack = (tmp > 1);

                /* Rogue backstab and some other stuff here... */

                /* artifact_hit() does bonus damage and effects */
                if (/* obj is an artifact */ && artifact_hit(...)) {
                    if (/* monster was killed by the artifact alone */) {
                        return FALSE;
                    } else if (/* artifact was ineffective against monster */) {
                        return TRUE;
                    }
                }
            }
        } else {
            /* handle non-weapons with tons of special cases */
        }
    }

    /* Add ring/intrinsic bonus damage and (conditionally) strength bonus here... */

    if (valid_weapon_attack) {
        tmp += weapon_dam_bonus(...); /* <-- SKILL DAMAGE BONUS ADDED HERE */
        use_skill(..., 1); /* TRAIN SKILL BY +1 POINT HERE */
    }

    /* Tons of special cases here... */

    /* Inflict damage, print hit messages here... */

    return destroyed ? FALSE : TRUE;
}

Note the two places where valid_weapon_attack = (tmp > 1), i.e. valid_weapon_attack is only true if the basic damage roll does 2 or more damage. In the case of a valid weapon attack with a proper weapon, here's a cut-down summary of the dmgval() function:

int dmgval(otmp, mon)
{
    int tmp = 0;

    /* WEAPON DAMAGE ROLL */
    if (/* mon is large */) {
        if (/* otmp base weapon type has non-zero damage specified vs. large */)
            tmp = /* base weapon type damage vs. large set in objects.c */;
        /* Add rest of large damage to tmp that should be in objects.c but doesn't fit. */
    } else {
        /* Do the same thing for small as for large above, but for damage vs. small instead. */
    }

    if (/* otmp is a proper weapon */) {
        tmp += otmp->spe; /* ADD/SUBTRACT WEAPON ENCHANTMENT */
        if (tmp < 0) tmp = 0; /* prevent negative damage */
    }

    if (/* otmp is made of leather */ && /* mon is thick-skinned */) {
        tmp = 0;
    }

    if (/* mon is a shade */ && /* otmp is not made of silver */) {
        tmp = 0;
    }

    if (/* a per-monster-and-object special case may apply */) {
        int bonus = 0;

        /* add to bonus for blessed otmp vs. undead mon */
        /* add to bonus for axe otmp vs. wooden mon */
        /* add to bonus for silver otmp vs. silver-hating mon */

        if (/* damage will ultimately be doubled due to otmp doing artifact damage */) {
            bonus = (bonus + 1) / 2; /* <-- halve bonus in anticipation of damage doubling */
        }
    }

    if (tmp > 0) {
        tmp -= greatest_erosion(otmp); /* <-- deduct damage for rust/rot/corrosion/etc. */
        if (tmp < 0) tmp = 0;
    }

    return tmp;
}

The most important parts here are the weapon roll at the very top, and where enchantment is directly included in damage.

Pulling all this knowledge together reveals that a +0 weapon that rolls a 1 will not inflict bonus damage for skill, nor will it train the relevant skill. This means that low damage weapons train slower that high damage ones. Note also that a +1 weapon will always include skill bonus damage and train skill, and a negatively enchanted weapon will roll 1 much more often and therefore will makes skill bonus damage and skill training much less likely per hit.

The skill bonus damage granted by NetHack is usually around +2 even at expert skill, so valid_weapon_attack makes very little difference in many cases, but for martial arts it makes quite a bit of difference, where grand master skill grants +9 damage. Recall that the martial arts damage roll in hmon_hitmon() is a d4:

Martial arts base damage and bonus
  Unconditional bonus Bonus considering valid_weapon_attack
Damage roll (d4) Skill bonus Total (before strength) Skill bonus Total (before strength)
1 9 10 0 1
2 9 11 9 11
3 9 12 9 12
4 9 13 9 13

If valid_weapon_attack is ignored, the average damage of martial arts considering the base damage roll and skill bonus damage is (10 + 11 + 12 + 13) / 4 = 11.5. However, if valid_weapon_attack is considered, the true average damage becomes (1 + 11 + 12 + 13) / 4 = 9.25, which is nearly a 20% damage reduction from what it otherwise could be. For simplicity, most of the damage calculations done here ignore this mechanic, except for martial arts.

DynaHack and UnNetHack change the valid_weapon_attack condition from (tmp > 1) to (tmp > 0), removing these biases for when to grant skill bonus damage and train skills from +0 weapons and martial arts entirely.

Common weapon and artifact reference tables

The common tables linked below ignore skill and enchantment. The tables for long swords and Grayswandir consider enchantments and different skill levels for quick comparison to final damage figures for different roles.

Damage profiles

I had two choices in calculating physical damage: be comprehensive, or only cover common cases. Being comprehensive would have involved hundreds more calculations than only covering common cases, so common cases is what I went with for the sake of practicality.

To that end, I divide the game into three phases, and make assumptions accordingly:

  • Early game
    • start str: +0 damage
    • basic skill for starting weapons, unskilled otherwise
    • enchantments: +0, unless it's a starting weapon with a guaranteed enchantment
  • Mid game
    • 18 str: +2 damage
    • expert skill, or the role's max skill(s) for the weapon(s)
    • enchantments: +0, most players don't enchant weapons until ready to enter Gehennom
  • Late game
    • 18/** str: +6 damage
      • for simplicity, 18/** is the only strength considered
      • only reachable by humans, dwarves and gauntlets of power
      • gnomes, orcs: 18/75 max strength = +3 damage
      • elves: 18 max strength = +2 damage
    • expert skill, or the role's max skill(s) for the weapon(s)
    • enchantments: +7

Common damage values by role

Each role page consists of the damage of various physical damage options in the early, mid and late game phases, followed by specific damage breakdown for selected late game physical damage options.

The values below are the average damage inflicted by various damage options available to each role in the late game. Check the role page links for damage breakdown and damage at other phases of the game.

  • User:tungtn/Physical damage analysis/Archeologist
    • +7 Grayswandir
      • non-silver: 31
      • silver: 41.5
    • two-weapon +7 Grayswandir, +7 silver saber
      • non-silver: 48.5
      • silver: 69.5
  • User:tungtn/Physical damage analysis/Barbarian
    • +7 Cleaver
      • 25.5/27
    • two-weapon +7 Frost Brand, +7 silver saber
      • resist cold non-silver: 33/35
      • resist cold silver: 43.5/45.5
      • cold non-silver: 44.5/48.5
      • cold silver: 55/59
  • User:tungtn/Physical damage analysis/Caveman
    • +7 Sceptre of Might
      • co-aligned: 15.5/14.5
      • cross-aligned: 27/25
  • User:tungtn/Physical damage analysis/Healer
    • +7 poisoned darts
      • resist poison: 22/21
      • poison: 29/28
    • +7 Grayswandir
      • non-silver: 29
      • silver: 39.5
    • +7 Staff of Aesculapius
      • non-drain: 18.5
      • drain: 33.5
    • +2 Magicbane
      • non-stun: 13.57/13.07
      • stun: 16.48/15.98
  • User:tungtn/Physical damage analysis/Knight
    • +7 lance (riding)
      • 29.3/30.3
    • two-weapon +7 lance, +7 long sword (riding)
      • 32.9/34.7
    • two-weapon +7 Excalibur, +7 long sword
      • 40.5/44.5
    • two-weapon +7 Frost Brand, +7 long sword
      • cold resist: 35/39
      • cold: 46.5/52.5
  • User:tungtn/Physical damage analysis/Monk
    • martial arts (grand master)
      • 18/17.5
    • +7 Excalibur (lawful crowning)
      • 23/25
  • User:tungtn/Physical damage analysis/Priest
    • +7 Grayswandir
      • non-silver: 29
      • silver: 39.5
    • +7 unicorn horn
      • 20.5
  • User:tungtn/Physical damage analysis/Ranger
    • +7 poisoned silver arrows
      • resist poison non-silver: 31.25
      • resist poison silver: 57.5
      • poison non-silver: 40
      • poison silver: 66.25
    • +7 Stormbringer
      • resist drain: 18/17.5
      • drain: 24/23.5
    • +7 Grayswandir
      • non-silver: 27
      • silver: 37.5
  • User:tungtn/Physical damage analysis/Rogue
    • +7 Stormbringer
      • resist drain (XL15 backstab): 19/18.5 (27/26.5)
      • drain (XL15 backstab): 25/24.5 (33/32.5)
    • +7 Grayswandir
      • non-silver (XL15 backstab): 30 (46)
      • silver (XL15 backstab): 40.5 (56.5)
    • two-weapon +7 Stormbringer, +7 crysknife
      • resist drain: 37.5/37
      • drain: 43.5/43
    • two-weapon +7 Grayswandir, +7 crysknife
      • non-silver: 48.5
      • silver: 59
    • +7 silver daggers
      • non-silver (XL15 backstab): 28.75/27.5 (48.75/47.5)
      • silver (XL15 backstab): 55/53.75 (75/73.75)
  • User:tungtn/Physical damage analysis/Samurai
    • +7 ya (fired from a yumi)
      • 35
    • +7 Tsurugi of Muramasa
      • 28.775/31.925
    • two-weapon +7 Excalibur, +7 katana
      • 43.5/46.5
    • two-weapon +7 Grayswandir, +7 silver saber
      • non-silver: 44.5
      • silver: 65.5
  • User:tungtn/Physical damage analysis/Tourist
    • +7 unicorn horn
      • 20.5
    • +7 poisoned darts
      • resist poison: 22/21
      • poison: 29/28
    • two-weapon +7 Grayswandir, +7 silver saber
      • non-silver: 46.5
      • silver: 67.5
  • User:tungtn/Physical damage analysis/Valkyrie
    • two-weapon +7 Excalibur, +7 long sword
      • 40.5/44.5
    • two-weapon +7 Grayswandir, +7 silver saber
      • non-silver: 44.5
      • silver: 65.5
  • User:tungtn/Physical damage analysis/Wizard
    • +7 silver daggers
      • non-silver: 23/22
      • silver: 44/43
    • +2 Magicbane
      • non-stun: 10.57/10.07
      • stun: 13.48/12.98
    • +7 Staff of Aesculapius
      • resist drain: 14.5
      • drain: 29.5
    • +7 Frost Brand
      • resist cold: 13.5/15.5
      • cold: 25/29
    • +7 Grayswandir
      • non-silver: 23
      • silver: 33.5

All of these calculations were done manually, and with the sheer volume of calculations it's almost certain that small errors exist, so keep that in mind when reading the raw damage values.

Monster hit point examples

To put these damage numbers in perspective, it helps to know the maximum hit points of certain monsters. See Hit points#Monster for the exact details.

Monster hit points are generally based on a monster's level: d8 per level. A monster's level is based on its intended level listed in monst.c, which is then modified by the current difficulty level (+1 for every 5 points of difference) and hero experience level (+1 for every 4 points of difference) in adj_lev().

Knowing these rules, you can approximate likely initial hit points of monsters by predicting the level, then:

  • minimum HP = level * 1
  • average HP = level * 4.5
  • maximum HP = level * 8

For example, a level 5 soldier ant has 5 min / 22.5 avg / 40 max initial hit points.

Hit points of notable monsters, most of which have special rules for their starting hit points:

  • Riders - 10 min / 45 avg / 80 max - Riders are hard-coded to have 10d8 hit points in makemon().
  • Demon princes:
    • Juiblex - 88 exactly
      • Note that zapping a wand of digging while engulfed will reduce Juiblex to 1 hit point!
    • Yeenoghu - 100 exactly
    • Orcus - 120 exactly
    • Geryon - 132 exactly
    • Dispater - 144 exactly
    • Baalzebub - 166 exactly
    • Asmodeus - 198 exactly
    • Demogorgon - 200 exactly
  • Wizard of Yendor (killed 0 times) - 30 min / 135 avg / 240 max - 30d8 from standard hit point rules, since the Wizard starts at level 30.

Taking the initial hit points of a monster and dividing it by damage gives a rough idea of how tough a monster is in combat.

Observations

Sources of damage from player attacks can be broadly divided into flat bonuses and multipliers. The main flat bonuses are, in rough descending order of impact:

  • silver - Against a silver-hating monster, any silver object does +d20 damage from an average of +10.5 damage per hit, which is more than any artifact weapon effect. Notably, this applies to demons and thus demon princes.
  • Rogue backstab - Exact impact scales based on the Rogue's experience level, since it does +d(XL) bonus damage to fleeing monsters.
  • enchantment - e.g. a +7 weapon does +7 damage. Two-weaponing with two +7 weapons grants +14 damage before considering anything else.
  • strength - Maximum strength grants +6 damage to melee hits, but not ranged ones. Two-weaponing pushes this up to +12 damage.
  • weapon base damage - The damage in dice notation that's listed next to weapons in their wiki pages. Non-two-handed weapons have dice ranging from d2 to d12, averaging 1.5 to 6.5 damage per hit.
  • weapon skill - Almost meaningless in terms of damage, despite needing multiple tables to describe earlier. More impactful in the early game where its to-hit modifiers make a difference.

Except for silver and a handful of other tiny factors, these flat bonuses are modified by what I loosely refer to as multipliers, which amplify or diminish the flat bonuses to determine the final damage inflicted to monsters. The main multipliers are, in rough descending order of impact:

  • speed - Going from normal speed (100%) to very fast (166%) adds +66% to damage per turn on average, and going from fast (133%) to very fast (166%) adds about +25% to damage per turn on average. It is the only multiplier that applies to all flat bonuses, and it stacks with other multipliers here! All characters with speed boots effectively get this bonus permanently.
  • two-weapon - Effectively almost x2 damage for melee for the 6 out of 13 roles that have any skill in it. Late game two-weapon does 35 average damage minimum per round; the best non-two-weapon non-Grayswandir alternatives do 25 average damage maximum (Grayswandir does around 30). Much of its damage comes from allowing two enchantable weapons (+7 each for +14 total, the corollary of the Monk adage: "You can't enchant your fists") and applying strength bonus to both hits (+6 each for +12 total).
  • artifact weapon double damage - Applies to certain artifact weapons, and only to the damage done by the artifact itself, though it does stack with two-weapon if the artifact is one-handed. Most double damage artifact weapons are the Banes, notable exceptions are:
    • Grayswandir - vs. all, also does silver damage, which is not doubled
    • Frost Brand and Fire Brand - vs. non-cold and non-fire resistant respectively
    • Sceptre of Might - vs. cross-aligned (i.e. monsters whose alignment differs from yours)
    • Staff of Aesculapius - vs. non-drain resistant, also does d8 bonus draining which is not doubled
  • multishot - Applies only to ranged attacks. Expert multishot grants d3 shots and grants x2 average damage, the special role/weapon bonuses for Ranger, Rogue and Samurai push this up to d4 shots for x2.5 average damage, and race/weapon can push this up to d5 shots for x3 average damage.

The damage inflicted by characters in late-game NetHack is a combination of all of these factors.

One-weapon melee vs. Two-weapon vs. Ranged Damage

Minimum, maximum and average late game damage. Damage for each combat option has been normalized by taking the average small/large damage, then the average of all distinct damage cases.

  • One-weapon melee
    • Minimum: 11.75 for Wizard with +2 Magicbane.
      • Ignoring Magicbane, minimum is 17.75 for Monk martial arts at grand master.
      • Considering only "proper" weapons, minimum is 20.5, a tie between Caveman +7 Sceptre of Might and Priest/Tourist +7 unicorn horn.
    • Maximum: 36.25 for Archeologist +7 Grayswandir.
    • Average: 25.71, keeping in mind that some of the weaker roles had multiple options due to lack of obviously powerful options.
  • Two-weapon
    • Minimum: 33.8 for Knight two-weapon +7 lance, +7 long sword.
      • If the main hand lance knocks the monster backwards, the second hit won't land. Swapping lance and long sword hands reduces joust damage from +2d10 to +2d3.
    • Maximum: 59 for Archeologist two-weapon +7 Grayswandir, +7 silver saber.
    • Average: 47.69.
  • Ranged
    • Minimum: 25 for Healer/Tourist +7 poisoned darts.
    • Maximum: 51.25 for Rogue +7 silver daggers.
    • Average: 36.33.

Qualitative mapping of damage to Gehennom experiences

Just looking at the late game damage options and how people on IRC talk about their experiences of Gehennom and what weapons they're using, you can get a rough idea of what people consider good damage and bad damage.

The minimum damage that people are still comfortable fighting monsters in Gehennom is around 20 per hit (or 33 per turn with "Very Fast" speed), which is about the average damage done by +7 Stormbringer. Martial arts at grand master skill is considered weak, doing around 18 damage on average per hit (or 30 per turn with "Very Fast" speed).

The point where combat starts to become trivial in Gehennom is around 35 damage per hit (or 58 per turn with "Very Fast" speed), which is about the average damage done by two-weapon +7 Frost Brand, +7 long sword in the worst case of a cold-resistant monster.

Impact of skill on overall damage

Just how much do combat skills contribute to late game damage?

One-weapon combat

As a reminder, this is the bonus damage granted to attacks by skill level:

Normal weapon skills
Weapon skill level Damage
restricted and unskilled -2
basic +0
skilled +1
expert +2

This applies once for one-weapon combat for +2 damage at expert skill. Recall that one-weapon combat (with actual weapons) ranges from 20.5 minimum, 36.25 maximum and 25.71 average. Skill for one-weapon combat in this case therefore comprises 5.5-9.7%, average 7.8% of its late game damage.

Martial arts

Martial arts is a skill exclusive to monks and samurai, both of whom start with it at basic skill. Samurai can advance the skill to master, while monks can advance all the way to grand master. Martial arts for samurai is vastly inferior damage-wise to any of their other combat options, so this section will only consider monks.

Martial arts
Skill level Bonus damage
basic +3
skilled +4
expert +6
master +7
grand master +9

It's probably easier to illustrate how martial arts skill contributes to final damage by simply showing how the damage breaks down, since the valid_weapon_attack mechanic affects it. Assuming 18/** strength and grand master skill:

Martial arts damage breakdowns
Damage roll (d4) Skill damage (% of total) Strength damage Total
1 +0 (0%) +6 7
2 +9 (53%) +6 17
3 +9 (50%) +6 18
4 +9 (47%) +6 19

Two-weapon combat

The two-weapon bonus damage table is identical to one-weapon skills, but -1 at all levels.

Two-weapon skill damage
Skill level Bonus damage
unskilled -3
basic -1
skilled +0
expert +1

This applies twice, once for each weapon hit for a total of +2 damage at expert skill. Recall that two-weapon combat damage ranges from 33.8 minimum, 59 maximum and 47.69 average. Skill for two-weapon combat therefore comprises 3.3-5.9%, average 4.1% of its late game damage.

Ranged combat

Ranged combat uses the same skill-to-damage table as one-weapon combat, but also permit multishot (at least for all ranged weapons that matter): the ability to fire/throw 1-to-n projectiles in a single attack round. The maximum multishot limit is determined as follows:

  • Base multishot count from skill:
    • 1 at basic skill
    • 2 at skilled
    • 3 at expert skill
  • +1 if one of the following role bonuses apply:
    • Ranger using any ranged weapon.
    • Rogue throwing daggers of any kind.
    • Samurai firing ya from a yumi.
  • +1 if one of the following race bonuses apply:
    • Elf firing elven arrows from an elven bow.
    • Orc firing orcish arrows from an orcish bow.

In other words, expert multishot alone launches d3 projectiles for an average of 2, and stacking an extra bonus shot launches d4 projectiles for an average of 2.5. Getting to d5 projectiles for an average of 3 is only possible as an elven or orcish ranger with the right bow and arrows.

Returning to bonus damage from skill, the +2 damage applies to each projectile that hits, which is an average of 2 to 3 times, leading to +4 to +6 damage per volley. Recall the bounds of ranged damage in the late game is 25 to 51.25 damage. Skill for ranged attacks therefore comprises 11.7-16% of its late game damage.

Combat option selection

The fact that skill matters so little would imply would imply that almost all late game characters would gravitate towards the same weapons, regardless of role. If that's so, why do all of the role pages in these notes have such different combat options?

The combat options for each of the roles was mostly based on advice given in these wiki pages. There a couple of factors that explain this. The first is that players don't like to use weapons outside of their role's skill set, even going into the late game, as a habit carried from the early game where skills in fact do matter, due to their to-hit bonuses being noticeable/relevant in the early game. The other factor is availability/convenience, e.g. random sacrifice gifts, and Excalibur for lawful characters since they either start with or can get a long sword from a barrow wight and dip it into a fountain.

Also note that due the high damage done by late game characters in general, there's no compelling need to get the most damaging weapon(s)/combat options. This is a specific instance of a more general pattern in NetHack gameplay, where players fall into old habits game after game because the mechanics put no pressure to push players out of their comfort zone and into variety. This is the result of NetHack being designed more around the idea of enabling actions than restricting them, but the idea of coercing players out of habit and into variety is fertile ground for variants.

Grayswandir damage

User:tungtn/Physical damage analysis/Grayswandir damage

Breakdown of Grayswandir damage:

  • +9 avg - d8 base damage, doubled
  • +0 to +14 - +0 to +7 enchantment, doubled
  • +10.5 avg - +d20 silver damage vs. silver haters, not doubled

Fire Brand and Frost Brand are identical to Grayswandir in damage, except that their double damage can be resisted, they don't get silver damage, and they do slightly more damage against large monsters due to slightly higher damage dice that long swords get in that case. Grayswandir is arguably the strongest weapon in NetHack, but by how much?

Consider that almost all +7 weapons get +7 to damage, while +7 Grayswandir gets +14 to damage, in other words, a difference of 7 points. If we consider that its base d8 damage from being a silver saber is doubled and line it up against other artifact weapons, we can estimate that Grayswandir has a 7 point advantage over other weapons, Fire Brand, Frost Brand and The Sceptre of Might aside.

The difference in bonus damage from skill between unskilled (-2) and expert (+2) is 4 points, therefore Grayswandir is the most damaging weapon for almost all characters regardless of skill level! This fact is only cemented by the broken late game to-hit calculations and the fact that Grayswandir is unintelligent and therefore will not evade the grasp of any character. As a fun exercise, compare the damage done by Grayswandir in the linked page against many of the damage options in the individual role pages.

On top of all this, Grayswandir is so mighty that it even out-damages Demonbane when used against demons!

Grayswandir vs. Demonbane used against demons
  +0 +7
  Demonbane Grayswandir Demonbane Grayswandir
base damage (avg) 9/13 9 9/13 9
enchantment (vs. demons) +0 +0 +14 +14
silver damage (avg) n/a +10.5 n/a +10.5
total (avg) 9/13 19.5 23/27 33.5

Fire Brand vs. Frost Brand

Fire Brand and Frost Brand do damage similar to Grayswandir, as long as the target monster doesn't resist the artifact weapon's element. If the target monster does resist the element, the Brands essentially function as a long sword, which is their base item type. The following table lists examples of monsters that resist fire, resist cold or resist both:

Resists fire Resists fire and cold Resists cold
  • almost all demons
  • all demon princes (except Asmodeus)
  • Minion of Huhetotl (Arc nemesis)
  • Ixoth (Kni nemesis)
  • Nalzok (Pri nemesis)
  • Lord Surtur (Val nemesis)
  • master liches and arch-liches
  • Asmodeus
  • archons
  • all Riders
  • Chromatic Dragon (Cav nemesis)
  • aleax
  • angels
  • liches and demiliches
  • all puddings including green slimes
  • all zombies
  • ghosts and shades

Frost Brand seems more effective than Fire Brand in Gehennom due to demons resisting fire, but Fire Brand seems better on the Astral Plane with its high concentration of angels. Neither will work better than a regular long sword against archons or Asmodeus.

Combat changes made by Variants

NetHack variants have historically made changes to the basic combat system laid out by NetHack, though they often go unnoticed by players due to the high randomness present in how accuracy and damage is dealt, the subtlety of the changes themselves, and the lack of understanding of how combat in NetHack works in general.

This section lists and describes the mechanics and impact of some of the more notable but overlooked of these changes.

See also this discussion from the dNetHack developer: User talk:Tungtn/Physical damage analysis

Double damage for two-handed weapons (SporkHack, UnNetHack, DynaHack, dNetHack)

In NetHack, (almost) all melee attack damage is modified by the character's strength attribute, ranging from -1 for strength 5 and under, all the way up to +6 for 18/** strength and up.

SporkHack introduced the idea of making two-handed (or bimanual) weapons distinct, by doubling this modifier for such weapons. Therefore a character using a two-handed weapon will get a strength damage modifier of between -2 to +12, which moves two-handed weapons from doing mediocre damage in the late game to doing respectable damage. This bonus damage also partially offsets the typical downside for two-handed weapons: being cursed and causing "stuck hands" that prevents bag/container access and spell casting.

This change was later ported into UnNetHack and DynaHack, and also exists in dNetHack.

Extra damage beyond +6 for 18/** strength (SporkHack, UnNetHack, DynaHack, dNetHack)

In NetHack, the maximum damage bonus you can get from strength is +6 damage from 18/** strength; higher strength than that has no effect on damage.

SporkHack made a subtle change for 25 strength, the strength level that you get when you wear gauntlets of power, by granting a +7 damage bonus for that point. This change was later ported into UnNetHack and DynaHack. It's only a 1 point difference in most cases (2 points if considering the two-handed strength modifier mechanic).

dNethack also gives higher bonuses for higher strength scores: +6 for 19-21, +7 for 22-24, and +8 for 25.

Changes to damage from skill (dNetHack, DynaHack)

dNetHack increases the impact of very high and very low skill as follows (changes in bold):

Skill damage modifiers in NetHack vs. dNetHack
  One-weapon/ranged Two-weapon Riding
NetHack dNetHack NetHack dNetHack NetHack dNetHack
restricted -2 -5 (3 less) n/a n/a n/a n/a
unskilled -2 -2 -3 -3 +0 +0
basic +0 +0 -1 -1 +0 +0
skilled +1 +1 +0 +0 +1 +2 (1 more)
expert +2 +3 (1 more) +1 +2 (1 more) +2 +5 (3 more)

The -5 to damage for restricted one-weapon/ranged skill has a pretty big impact, considering typical weapons range from d2 to d12 damage, or 1.5 to 6.5 damage on average, so in dNetHack you usually don't want to use weapons if their skill doesn't appear in your #enhance menu.

The 1 extra damage for expert in one-weapon/ranged and two-weapon skill was included in the individual role pages, and they had almost no impact on the final damage for late game or even mid game combat options. It's not necessarily a bad change, but it'd have to have gone further to have an influence on combat option choices for players.

The damage increases for skilled and expert riding are hard to gauge the impact of. They only kick in if the player is mounted, and most players in the late game aren't mounted due to the extra fuss of getting a steed that can survive the late game, and the incredible rarity of saddles, which are required for riding.

At the time of writing, I've adopted these changes in DynaHack myself, but I'm open to going even further than what's been done here.

Reduce influence of Luck on To-Hit (SporkHack, DynaHack)

Recall earlier in the brief section on "To-Hit" that the hidden "luck" attribute is one of the biggest contributors to a character's to-hit value: +13 at its highest, compared to 18 dexterity which gives +4, or 23 dexterity which gives +9.

SporkHack reduces this by simply dividing the luck attribute by 3 for these calculations, so the it ranges from -4 to +4 instead of -13 to +13 as in NetHack.

Incidentally this also makes early Sokoban "cheating" much less reset-worthy; enough attempts to fix a botched Sokoban level can make it impossible to hit anything in early game NetHack. I'm not sure if SporkHack changed anything about the way Sokoban works to tell if this mechanic has the impact I'm stating it has here.

DynaHack independently simply removed the luck attribute from to-hit calculations altogether, though as of this writing, due to an oversight it only affects melee attacks (I will fix this when I have a chance to). DynaHack converts Sokoban cheating from a luck penalty into a conduct, a change it borrows from UnNetHack, so fixing botched Sokoban levels is far less punishing than it is in NetHack.

Player combat makes noise (SporkHack, UnNetHack, DynaHack, dNetHack)

Most NetHack players will be familiar with the random special rooms that are sometimes inserted into standard dungeon levels filled with sleeping monsters. The vast majority of the time each monster can be killed piecemeal by only attacking one of them at a time. The only other times the monsters will ever wake up is if a soldier decides to use a bugle in a barracks, and each monster on the entire level has a one-in-three chance to awaken whenever you step into a court room, swamp, morgue or zoo.

SporkHack causes player attacks on monsters to create noise, awakening nearby monsters:

  • Missing an attack is silent.
  • Thrown darts, shuriken and knives have a 2-in-3 chance to be silent.
  • Hitting with a knife and having stealth is silent.
  • Hitting without stealth, or with a non-weapon, Mjollnir or a bullwhip has a chance to awaken monsters in a 8-space radius circle around the struck monster, otherwise only those in a 3-space radius circle may be affected.
  • If you are a Rogue, 2-in-3 affected monsters will awaken, otherwise 4-in-5 will awaken.

Note that this is asymmetric: monsters hitting the player or each other will not awaken nearby monsters. This change is adopted verbatim in UnNetHack. DynaHack uses more-or-less the same process, but hitting with weapons with the special stealth property is also considered completely silent.

dNetHack recently implemented combat awakening nearby monsters, but does it very differently from SporkHack/UnNetHack/DynaHack. The most important differences are:

  1. Both player- and monster-initiated combat will awaken nearby monsters.
  2. The radius of awakened monsters is about 2 spaces regardless of conditions.
  3. Stealth, attack type and weapon type do not come into play.

Regardless of the particulars, noise awakening means that variants that implement this mechanic have good and bad ways to fight sleeping monsters in special rooms, unlike in NetHack where all the inhabitants can be slaughtered in their sleep, making these rooms much more interesting to deal with.

A side effect of this noise-combat mechanic is that you don't want to fight close to certain sleeping monsters like nymphs and nalfeshnee, since the combat will awaken them and force you to deal with them, often mid-combat.

To-Hit Cap for Low Skill Levels (SporkHack, UnNetHack, DynaHack)

Recall that whenever a character tries to attack a monster that a target number is added together from various factors such as the character's experience level, luck, weapon enchantment and the target monster's AC, which is then compared against a d20 roll to decide if the character's attack hits or misses.

In SporkHack, in the case of melee attacks at least, being at restricted or unskilled in the relevant weapon/combat skill caps the hit value at 15, effectively capping attacks of that nature at 70% accuracy (Note: SporkHack's source code says 75%, but it's slightly incorrect since the hit condition is number > rnd(20) where rnd(20) returns a number from 1 to 20 inclusive.) Non-weapon objects like cockatrice corpses count as restricted for this purpose.

Placing a cap on to-hit values that sky-rocket in the late game is one of the most direct and noticeable ways to limit them in the late game (and a 30% miss chance will indeed be noticed) while having no impact on the early game. However, it sweeps the problem of how to-hit values are calculated to be so high in the late game to begin with under the rug. The cap also "flattens" all values above 15 down to 15, eliminating many of the intricacies present in the to-hit calculations, including the fixed to-hit modifiers in the skill tables.

Brainstorm of possible improvements

The problems with NetHack's combat system are not errors in the same way that bugs in the code are errors: there is no single point of failure, which means there are no obvious fixes that could be applied on their own. NetHack's combat system is badly designed, which means that fixing it requires replacing or reworking its design into a better design. If we drill down into what a "design" is, it can be loosely described the choice of numbers and rules about how they interact such that:

  1. The set of player actions that are encouraged and discouraged by the numbers and rules are enjoyable.
  2. The set of outcomes due to the numbers and rules are enjoyable.

Recall the two hypotheses from the intro:

  1. It is possible to inflict so much damage in the late game that players don't need to use tactics, leading to dull confrontations.
  2. Certain equipment choices and tactics (e.g. #twoweapon) do so much more damage than their alternatives that they overshadow them, leading to different characters playing in similar ways.

Hypothesis 1 is a problematic outcome of the current combat system. Hypothesis 2 is a problematic set of actions of the current combat system.

The overall problems with NetHack's combat system is that:

  1. The damage being done in the late game is too high.
  2. The number of ways to do the most damage is very small.
  3. The ways to do the most damage can almost all be reached by in-game actions rather than character selection or in-game circumstances.

Therefore, an improvement to NetHack's current combat system must:

  1. Increase number of hits needed to kill enemies by top combat options.
  2. Increase the set of top combat options.
  3. Increase the influence of character selection and/or in-game circumstances on the set of top combat options relative to in-game actions.

(Aside: A word of warning to developers that intend to make design changes: players are generally very loss-averse. Players react very negatively to having powers or bonuses taken away from them, while they embrace increases to powers and bonuses that they receive, regardless of the overall design implications. First, be careful not to give too much power to players at once, since taking it back will be difficult if not impossible. Second, taking away power from players should be accompanied by adding new features or powers elsewhere, otherwise you may end up releasing a new version of your game, only to find players mutiny by playing an older version or stop playing altogether!)

The following ideas are NOT necessarily recommendations; they are only mentioned to provoke thought.

Increase number of hits needed to kill enemies by top combat options

The theory here is simple: If enemies can't be killed as quickly as they are in NetHack's current combat system, players will be required to adopt tactics more often.

There are two general approaches to increasing enemy durability: make the top combat options weaker, and make the enemies stronger.

Examples of making top combat options weaker:

  • Identify and weaken equipment used in the top combat options, e.g.:
    • Find artifacts that do the most damage and make them do less damage or apply to a narrower set of enemies.
  • Identify and amend rules that cause a lot of damage to be dealt, e.g.:
    • Change how strength/enchantment affect multiple-hit combat options such as two-weapon and multishot.
    • Two-weapon and multishot benefit a lot from enchantment, so change the effect of enchantment on damage from +x into +1dx.
  • Decrease the player's accuracy so they'll hit less often, thus causing less damage.
    • Take any of the biggest factors contributing to very high to-hit values and come up with ways to reduce them, like the 1-to-1 link between to-hit and experience level, or the Luck attribute.
    • Reduce or remove the effect of weapon enchantment on to-hit.
  • Reduce the effect of individual top combat options that stack, e.g.:
    • Change speed boots to provide only Fast speed instead of Very Fast speed, thus making Very Fast speed only available from temporary sources like Potions of Speed or the Haste Self spell.
      • Consider providing selective benefits to speed boots to not make them useless to characters that already have Fast speed, like allowing them to be #invoked to grant temporary Very Fast speed, and/or only increasing movement speed but not combat speed.
    • Add more restrictions to how artifact weapons can be used, e.g. a powerful artifact weapon may deny being used in two-weapon combat altogether, or have its bonus effects only apply 50% of the time during two-weapon combat.

Examples of making monsters stronger:

  • Improve the numbers associated with monsters, e.g.:
    • Increase their average HP and/or AC.
    • Spawn armor-capable monsters with armor more often.
  • Change the rules to make monsters more durable, e.g. negative AC on monsters reduces incoming damage like on the player.

Increase the set of top combat options

Having only a small set of top combat options causes players to end up with them game after game, which leads to boredom. Increasing the number of top combat options will allow players to aim for and end up with different combat options. There are three ways to do this:

  1. Reduce the power of or remove the top combat options, thus handing the status of top combat options to the next most powerful successors.
  2. Select existing non-top combat options and increase their power to add to the set of top combat options.
  3. Create new combat options with power comparable to the top combat options.

Examples of reducing the power of top combat options:

  • Reduce the damage done by artifacts that apply to a large percentage of enemies, e.g. Grayswandir, Excalibur, Fire/Frost Brand.
  • Narrow the range of monsters that high-damage artifacts apply against, e.g.
    • Grayswandir could be made to apply against chaotic monsters only instead of all of them.
    • Fire Brand could be made to do double damage to ice creatures, and +50% damage to non-fire resistant creatures otherwise.
  • Only apply artifact bonus damage on some hits instead of all of them, perhaps linking it to high hit rolls or to-hit values.
  • Change two-weapon to only hit with the off-hand weapon some of the time instead of every time the primary weapon connects.
  • Reduce or remove the strength damage bonus for part or all of the individual hits of two-weapon.
  • Reduce the effectiveness (AC, weight, spell-casting) of dragon scale mails.
    • Make dragon scale mail much heavier and block spell-casting like most heavy body armor suits, but allow plain dragon scales to be enchanted for less AC but permitting spell-casting.

Examples of increasing the power of existing non-top combat options:

  • Double the strength damage bonus when using a two-handed weapon.
  • Allow occasional critical hits or an extra hit for non-two-weapon melee combat based on skill level.
  • Add powers more useful powers to artifact weapons that are currently very weak, like the Banes.
  • Increase the AC/MC of and/or reduce the weight of heavier suits of body armor.
  • Identify weaker weapons and increase their damage straight up.

Examples of creating new combat options:

  • Add A LOT more artifact weapons covering a much wider range of weapon skills, like dNetHack has.
  • Add more weapons to each weapon skill family, e.g. higher damage but with to-hit penalties, like how dwarvish mattocks compare to pick-axes, there could be iron/silver chain-whips to complement bullwhips.
  • Find 'gaps' to cover unfilled niches, e.g. NetHack has no silver two-handed weapons, so perhaps add one.

Note that just providing more options does not promote more variety on its own: without some external force, players will naturally form gameplay habits which will cause them to end up with the same combat options game after game anyway.

Increase influence of character selection/circumstances and decrease influence of actions on gaining combat options

As hinted in the previous section, having a lot of combat options is an improvement, but is meaningless, since players naturally form habits about how to play the game, thus consciously asking for variety across games while subconsciously doing the same things game after game. To combat this habit-forming tendancy, the game itself must apply some pressure for players to diversify that overrides the effects of their subconcious habits.

The topic of how much control the game rules have over the outcome of play versus the actions of the player themselves is strategy headroom (http://nethack4.org/blog/strategy-headroom.html) as described by ais523, which you should read because it does a far better job of explaining the concept than I ever could. Nonetheless, the key take-away from it is the dichotomy of freedom and variety. Players who tend to develop habits will be happier with low-headroom games that force them out of their comfort zones and experience more of the game's mechanics as a result. Players who find themselves frustrated at being punished for not playing the game in exact lock-step with the developers intentions will be happier with high-headroom games that give them breathing space to discover and overcome the game on their own terms.

NetHack, on purpose or by accident, is a high headroom game, which makes it very hard to apply character-specific or circumstantial elements on the choices the players have without changing the nature of the game itself. Any changes along this line is likely to put off at least some players, which makes it tempting to simply do nothing and give some players their freedom whilst others fall victim to their habits. Whether or not this is acceptable depends on how much you agree with either of these statements:

  • I want to be able to do X every single game.
  • I want reasons to not do X every single game.

These statements at face value are contradictory: to accept one statement is to deny the other. But yet, it feels like there are a lot of players that could sympathize with both statements to some degree, so it must be possible to satisfy both of these statements at least partially.

The biggest example of partial simultaneous fulfillment of both freedom of choice and variety is, funnily enough, NetHack's current combat system. One of the biggest things I noticed over the course of studying and breaking down the damage done in NetHack's late game is that players don't need to do the most damage; they only need to do enough damage. The most damaging weapon for chaotic characters to wield is +7 Grayswandir (23 average damage to all monsters before other factors), but players regularly get away with using +7 Stormbringer (18/17.5 average damage to non-drain resistant monsters before other factors). It's easy to just write this off as evidence of NetHack being a high headroom game, but that would be stopping too soon. Just because characters that use Stormbringer don't die significantly more often than those that wish for Grayswandir doesn't mean the decision is necessarily meaningless: Grayswandir still kills foes faster than Stormbringer, which changes the way the game plays. This duality of options being meaningfully different without the game punishing players for making "wrong"/"sub-optimal" choices is our ray of hope that variety can be introduced to NetHack without dictating play-style too much.

With all that in mind, here are some ways that character selection and circumstances could be applied to add some variety across NetHack games:

  • Increase the influence of skills on damage. Skill maximums are one of the only ways that roles differ from one another. This would be the first step to differentiating all of the fighter roles like Barbarian, Knight, Samurai and Valkyrie.
    • Increase the skill damage modifiers, e.g. from -2/-2/+0/+1/+2 to -5/-2/+0/+2/+5 for Restricted/Unskilled/Basic/Skilled/Expert.
    • Increase the skill to-hit modifiers. This requires to-hit values in the late game to be brought within 20 points of monster AC, since hit rolls use a 20-sided die.
    • If introducing critical hits or extra hits in one-weapon melee combat, trigger it based on skill level.
    • Find more ways to base damage on skill level, e.g. if the off-hand weapon of two-weapon is changed to only hit sometimes, base the chance on the level of the two-weapon skill. However, be careful not to make two-weapon useless below Expert skill.
  • Make powerful artifact weapons harder to get by choice, e.g.:
    • Increase the current difficulty to gain sacrifice gifts from repeatedly sacrificing at an altar, or limit sacrifice gifts to one gift per altar.
    • Require 2 charges from a wand of wishing to grant an artifact. This would also make it impossible to wish for an artifact from sources other than a Wand of Wishing, which may not be intended.
      • Consider decoupling the chance of successfully gaining an artifact from a wish from the number of existing artifacts if going down this path, as an example of the give-and-take principle of changing existing designs whilst simultaneously squashing the odd meta-game quirk that players are often disappointed instead of pleased when they find a random artifact.
    • Returning to the idea from the previous section of adding many more artifacts, make some of them "lesser artifacts" that:
      • are less powerful that full-fledged artifacts but more useful than normal objects
      • aren't as restrictive about their use, e.g. can be used as an off-hand weapon in two-weapon combat
      • don't count against the number of existing artifacts for the purpose of artifact wishes
      • spawn often enough that players will encounter a few in almost every game
      • dNetHack does exactly this, which makes players more opportunistic. DynaHack borrows GruntHack's system of random object properties that effectively create "lesser artifacts" on a random basis, with similar results.

Closing comments

In looking at how NetHack decides how much damage the player does when attacking a creature, I've chased a mysterious rabbit down a very deep hole, and I don't feel like I've reached the end of it. However, I don't have enough time to keep chasing it, so I'm going to close this out for now in the hopes that somebody will look in-depth at what I haven't.

The first big area that I wasn't able fully look into was to-hit. Going through all of these numbers and algorithms have convinced me that the skill to-hit modifier was supposed to reign in the big damage done by things like powerful artifact weapons and two-weapon, but the fact that to-hit calculations are broken makes them completely irrelevant, and is simultaneously the reason why it matters in the early game and why it doesn't in the late game. If anybody intends to look at to-hit more closely, I have a few tips:

  • I already covered the basics in the "To-hit" section of "Related factors and assumptions" earlier in these notes.
  • The player's melee and kick accuracy goes through a function called find_roll_to_hit().
  • The player's ranged accuracy is calculated inline in the thitmonst() function.
  • Hit rolls use virtual 20-sided dice, so a search for "rnd(20)" in the source code will pick up most places where the game feels a hit/miss chance should apply, including common things like wand zaps and traps, to obscure things like a punishment ball hitting a monster in a pit because it was dragged into it when the attached chain was dragged over it.
  • Take care to look at the inequality operator when the d20 is rolled and compared to the target number; SporkHack limits the return value of find_roll_to_hit() to 15 for hits at Restricted/Unskilled, claiming that it limits accuracy to 75%, but in practice actually limits it to 70% due to the inequality operator used in the hitum() function.
  • It's possible to manually patch in the display of to-hit values using pline() in the right places, which sheds some light on the values that NetHack comes up with. I played one game like this with a two-weaponing Archeologist that had around 170% hit chance against almost everything in Gehennom with standard experience level, standard weapon enchantment and standard luck.
    • It might even be possible to log to-hit values of players versus monster AC values, as well as break-downs of contributing factors like experience level and luck. You could then put them on a graph to visualize how to-hit values stack up against monster AC. NetHack4 has interactive replays that run game code almost identically to how it was played, so with some modifications it could be used to examine the to-hit values of past games, limited to ascensions to remove early-game biases, for example.

The other big thing I didn't look too much into was speed, again from earlier in these notes. Speed is essentially an "everything" multiplier, to the point where speed boots invalidate all other boots for all characters (except for spellcasters lucky enough to have the Haste Self spell and be able to cast it reliably). One thing that stuck out to me about speed boots is that not only are they a permanent source of Very Fast speed, but out of all the ways to get Very Fast speed (boots, potion, spell), it is the only one that IS permanent. This makes it feel like the Very Fast speed of speed boots was more an accident of intrinsic/extrinsic flag book-keeping than an intended meta-game effect, and that speed boots should perhaps only grant Fast speed instead.

You may have noticed in the brainstorming section that the ideas are not particularly inspired, and a lot of them are focused on toning back on things rather than going all-out. This is partly due to my lack of creativity, but also because toning back on things is easier and therefore much more feasible to enact than introducing variety by adding tons of new things. Going all-out like this takes much more effort than adjusting what already exists, but it has the benefit that players notice new features, and they don't really notice new mechanics. Against all conventional wisdom, I've seen players ignore stability, game crashes, save file losses, server downtime, unfair deaths and temporary balance issues just to experience new things in dNetHack, for example. I don't feel that either approach is better or worse, or even that they're mutually exclusive, so dNetHack is worth looking at for an example of attacking the lack of variety in NetHack's gameplay from the other side, with some very interesting results. It's harder to do this with a variant like SLASH'EM because most of its changes were added essentially at random, in contrast to dNetHack's balance-conscious design.

I should probably note once again that nothing in the brainstorming section is really a recommendation; it's just me playing with ideas. The reason this conclusion was delayed for so long was that the problem of damage in NetHack dovetails with the problem of accuracy in NetHack: you can't fix one without fixing the other. For example, if accuracy causes players to miss a lot, then damage on hit should not be reduced much. Flip it around, with accuracy being changed very little, and damage needs to be reduced by a lot. I have concrete numbers for damage, I don't have concrete numbers for to-hit, so I can't recommend any specific numbers without punting, which was what I was trying to avoid doing in DynaHack to begin with. Unfortunately, if I want to move on with DynaHack development, it looks like I'm going to have to punt... at least my punting now will be more educated guessing instead of plain old guessing.

Thoughts? There's a talk page for all this here: User talk:tungtn/Physical damage analysis