Skip to contents

Creating balanced combat encounters can be surprisingly difficult, especially for newer Dungeon/Game Masters (DMs / GMs). If you want to use the Dungeon Master’s Guide (DMG) you need to consult several interrelated tables for each encounter. To help other newbies–like myself!–dndR includes a handful of functions aimed at simplifying the encounter balancing process.

Encounter Creation

If you’d rather avoid consulting the DMG at all, the encounter_creator function may be a valuable tool for you to consider. This function requires the average level of all player characters in the party, the number of players in the party, and how difficult you’d like to make the encounter (allowable answers are ‘easy’, ‘medium’, ‘hard’, and ‘deadly’). Once you’ve provided this information, it will automatically select one tougher creature and as many other creatures as possible without making the encounter more difficult than you specified.

The function returns a dataframe with one row for each unique experience point (XP) value of the selected creatures. A separate column indicates the number of creatures worth that amount of XP that should be selected in the encounter. The function also returns the “pool” of XP available for the encounter and the realized XP “cost” of the chosen creatures. More detail is provided on this later in this vignette but for now keep in mind that there is an optimization step being done under the hood so this function will not always return identical results. I suggest running the function more than once until you are satisfied with the results!

# Pick a hard set of creatures for a four-person party of 3rd level characters
dndR::encounter_creator(party_level = 3, party_size = 4, difficulty = "hard")
#> # A tibble: 4 × 4
#>   creature_xp creature_count encounter_xp_pool encounter_xp_cost
#>         <dbl>          <int>             <dbl>             <dbl>
#> 1         200              1              1112              1100
#> 2          50              3              1112              1100
#> 3          25              2              1112              1100
#> 4          10              4              1112              1100

After this function has identified the number and XP value of the creatures in this encounter, you may consider using other dndR functions to identify specific creatures (e.g., creature_list, etc.) or use your favorite source book / homebrew to decide on particular creatures.

XP Balancing

This may be more detail than you require but a small description of how experience points are used to balance encounters (in and outside of this R package) will be useful context for some of the other encounter balancing tools described below. In essence, the difficulty of a combat encounter in Dungeons and Dragons is affected by four things:

  1. Level of characters
  2. Number of characters in the party
  3. How difficult the GM wants to make the encounter
  4. How many enemy creatures are included

The first three go into the “pool” of available experience points to spend on a given encounter. However, the number of creatures can dramatically influence how difficult an encounter is even if their total XP value is the same (e.g., a fight against one 1000 XP creature versus against four 250 XP creatures). This realized XP “cost” is calculated by applying a multiplier to the total rules-as-written XP value of all monsters in the encounter. This multiplier is affected by the number of enemy creatures as well as the number of player characters.

The DMG handles the total XP pool and the XP cost in two separate tables. In order to balance an encounter you need to carefully consult both of them. Often this involves iterative testing of which number and combination of creatures is below the available pool after applying the relevant multiplier. dndR provides two functions to handle this instead: xp_pool and xp_cost.

xp_pool returns the amount of XP the GM can ‘spend’ on monsters in a given encounter to ensure the difficulty is as desired based on the three factors identified above. You may note that it has identical arguments to encounter_creator–this is because that function relies on both of these functions ‘under the hood.’

# How much XP is available for a hard encounter for the four-person, 3rd level party?
dndR::xp_pool(party_level = 3, party_size = 4, difficulty = "hard")
#> [1] 1112

Once you have that in mind, you can make a note of that number and then use xp_cost repeatedly until you find the highest realized XP cost that will still fall beneath that threshold.

# Identify 'realized' XP of two monsters worth a total of 1,000 XP versus our party
dndR::xp_cost(monster_xp = 1000, monster_count = 2, party_size = 4)
#> [1] 1500

Even though the total XP value of the creatures is beneath the threshold identified by xp_pool it is dramatically higher after the appropriate multipliers are applied. Using xp_pool alone would risk creating a much harder encounter than you intended. In fact, in this case, that realized XP value is actually appropriate for a “deadly” encounter!

While encounter_creator is meant to avoid needing to use these helper functions, you can of course use these if you’d rather take a middle path between relying entirely on this package versus relying entirely on the DMG.