Sunday 8 May 2022

Levels Distribution

Simulating, but simulating what?

I’ve mentioned before that D&D has a problem in deciding what it is simulating, but that happens at the table too. Many DMs have a simulationist streak but it is sometimes hard to decide whether we’re simulating some sort of extrapolated reality based on the world as experienced personally by the PCs, or something more literary.

One topic where this plays out is in the realm of classed NPCs. When making broad-brush strokes about a campaign, for example, the numbers of high-level NPCs in the countries around the starting location, it’s handy to have a quick way of generating those numbers. But what method to use?

Basic Assumptions: Demographics

Two basic assumptions carry through both methods: firstly that classed characters are 1% of the human population. Secondly, that the age demographics are something like the Coale-Demeny West table at level 4. This basically means that half the population is old enough to have or have started training in a class, and that 60 is a reasonable expectation for characters.

A. Simulating PCs

One approach I have used is a complete simulation based on entrance requirements for the classes, age demographics, and an assumed rate of experience point accumulation.

Without going into too much detail, what you find with this approach is that there are relatively few 1st level characters, especially thieves, because it takes so little experience to pass through the low levels, resulting in a sort of bulge at mid-levels. Exactly where depends on how much xp per month you figure in, how many active months in a year you assume etc.

For fighters this gives an output something like this for 1000 fighters:

Level #Fighters
1 33
2 42
3 59
4 107
5 205
6 209
7 273
8 70
9 2

The shape of the bulge varies depending on how exactly you see the rate of xp gain working over time, but you get the idea. Mid- to high-levels dominate over the lower levels.

B. Simulating Fiction & The Implied Reality

The above doesn’t fit most people’s expectations of the world which are taken from fiction and/or the Monster Manual’s listings for “Men”. The implied world is one where low-level characters are outnumbered by 0-level normal people, and low level characters greatly outnumber name-level characters.

As a simple example, an encounter with 200 bandits will consist of 200 0-level bandits, 6 second-level fighters, 10 third-level fighters, 7 fourth-level fighters, 5 fifth-level fighters, 4 sixth-level fighters, one seventh-level fighter, and a tenth-level fighter. The MM seldom places first-level characters, although Berserkers do have them at a ratio of 1:10 compared to 0-level types.

Another area where the game departs from the “simulated PCs” method is in the incidence of the individual classes. Rather than depending on the odds of qualifying for each class, and some factor for how desirable the classes are, we can just use the numbers from DMG p35 (which assumes that the distribution of prospective henchmen in a town or city is the same as the general distribution of classes everywhere).

For the purposes of quickly determining what’s happening in a specific country, or in a town, we quickly boil the assumptions down to this:

Class Divisor
Cleric 1200
Druid 6000
Fighter 561
Paladin 4545
Ranger 4545
Magic-user 1200
Illusionist 6000
Thief 1600
Assassin 8000
Monk 200000

So, a location with a population of 300,000 will have on average 535 fighters, 2 monks (I’m rounding up at .5), and 38 assassins (300000 divided by 561, 200000, and 8000 respectively). Here’s the full table:

Class Divisor #
Cleric 1200 250
Druid 6000 50
Fighter 561 535
Paladin 4545 66
Ranger 4545 66
Magic-user 1200 250
Illusionist 6000 50
Thief 1600 188
Assassin 8000 38
Monk 200000 2

But what levels are these guys?

Last week's post was really just a bit of Javascript which tries to generate higher levels based on how hard they are to reach as an absolute number.

What the method boils down to is that the ratio of 1st level clerics to 2nd level clerics is the ratio 1500:3000 (the maximum number of xp in first and second level), so basically 2:1. This is a fairly complicated calculation so I’ve done tables up to high levels below.

Aside: An obvious alternative is to take the ratio of the mid-points of the various levels rather than the maximum values. This leads to a normal ratio of 1:3 at lower levels, and since this is compounded the numbers appearing of even 4th level and upward are insignificant. So, if this method gives too many mid-level characters, you could try adjusting that.

How it works is to set a maximum possible level, then assume that all the NPCs are distributed across those levels in inverse proportion to the amount of xp needed to reach each level. The tables are normalised so the values add up to one.

Here’s the tables.

Level Bard Cleric Druid Monk
1 4.706451e-01 5.045307e-01 4.587672e-01 5.254946e-01
2 2.353225e-01 2.522653e-01 2.293836e-01 2.489185e-01
3 1.176613e-01 1.261327e-01 1.223379e-01 1.182363e-01
4 5.883064e-02 5.821508e-02 7.340276e-02 5.254946e-02
5 3.765161e-02 2.751985e-02 4.587672e-02 2.489185e-02
6 2.353225e-02 1.375993e-02 2.621527e-02 1.206493e-02
7 1.568817e-02 6.879964e-03 1.529224e-02 5.911814e-03
8 1.107400e-02 3.363538e-03 1.019483e-02 3.378179e-03
9 8.557183e-03 1.681769e-03 7.340276e-03 2.364725e-03
10 6.275268e-03 1.121179e-03 4.587672e-03 1.689090e-03
11 4.706451e-03 8.408845e-04 3.058448e-03 1.244592e-03
12 2.353225e-03 6.727076e-04 1.223379e-03 9.458902e-04
13 1.568817e-03 5.605896e-04 6.116896e-04 6.756359e-04
14 1.176613e-03 4.805054e-04 2.621527e-04 5.254946e-04
15 9.412902e-04 4.204422e-04 2.293836e-04 4.299501e-04
16 7.844085e-04 3.737264e-04 2.038965e-04 3.638039e-04
17 6.723501e-04 3.363538e-04 1.835069e-04 3.152967e-04
18 5.883064e-04 3.057762e-04 1.668244e-04  
19 5.229390e-04 2.802948e-04 1.529224e-04  
20 4.706451e-04 2.587337e-04 1.411591e-04  
21 4.278592e-04 2.400907e-04 1.310764e-04  
22 3.137634e-04 2.240847e-04 1.223379e-04  
23 2.353225e-04 2.100794e-04 1.146918e-04  
Level Fighter Paladin Ranger
1 5.029507e-01 5.064549e-01 4.894399e-01
2 2.514753e-01 2.532274e-01 2.447199e-01
3 1.257377e-01 1.160626e-01 1.223600e-01
4 5.588341e-02 5.803129e-02 5.438221e-02
5 2.874004e-02 3.095002e-02 3.058999e-02
6 1.437002e-02 1.466054e-02 2.039333e-02
7 8.047211e-03 7.958577e-03 1.359555e-02
8 4.023606e-03 3.979288e-03 9.063702e-03
9 2.011803e-03 1.989644e-03 4.894399e-03
10 1.341202e-03 1.326429e-03 3.262933e-03
11 1.005901e-03 9.948221e-04 1.748000e-03
12 8.047211e-04 7.958577e-04 1.193756e-03
13 6.706009e-04 6.632147e-04 9.063702e-04
14 5.748008e-04 5.684698e-04 7.305073e-04
15 5.029507e-04 4.974110e-04 6.117999e-04
16 4.470673e-04 4.421432e-04 5.262795e-04
17 4.023606e-04 3.979288e-04 4.617357e-04
18 3.657823e-04 3.617535e-04 4.112940e-04
19 3.353005e-04 3.316074e-04 3.707878e-04
20 3.095081e-04 3.060991e-04 3.375448e-04
Level Magic-user Illusionist
1 4.897863e-01 4.883469e-01
2 2.448932e-01 2.441735e-01
3 1.224466e-01 1.220867e-01
4 5.442070e-02 6.104337e-02
5 3.061165e-02 3.139373e-02
6 2.040776e-02 1.831301e-02
7 1.360518e-02 1.156611e-02
8 9.070117e-03 7.577797e-03
9 4.897863e-03 4.994457e-03
10 3.265242e-03 2.497229e-03
11 1.632621e-03 1.664819e-03
12 1.088414e-03 1.248614e-03
13 8.163106e-04 9.988915e-04
14 6.530485e-04 8.324095e-04
15 5.442070e-04 7.134939e-04
16 4.664632e-04 6.243072e-04
17 4.081553e-04 5.549397e-04
18 3.628047e-04 4.994457e-04
19 3.265242e-04 4.540416e-04
20 2.968402e-04 4.162048e-04
Lv Thief Assassin
1 4.947792e-01 4.984702e-01
2 2.473896e-01 2.492351e-01
3 1.236948e-01 1.246175e-01
4 6.184740e-02 6.230877e-02
5 3.092370e-02 2.990821e-02
6 1.455233e-02 1.495411e-02
7 8.835343e-03 7.477053e-03
8 5.622491e-03 3.738526e-03
9 3.865463e-03 2.492351e-03
10 2.811246e-03 1.759306e-03
11 1.405623e-03 1.300357e-03
12 9.370819e-04 9.969403e-04
13 7.028114e-04 7.477053e-04
14 5.622491e-04 4.984702e-04
15 4.685409e-04 3.742724e-04
16 4.016065e-04  
17 3.514057e-04  
18 3.123606e-04  
19 2.811246e-04  
20 2.555678e-04  

One way to use these tables is just to find the number of clerics, say, in a town using table 1, then you can multiply that number by the value given for 1st level clerics on the table below to find how many Acolytes there are; then multiply the total number of clerics again by the value given for second level clerics to find the number of Adepts, and so on.

For example, Say you have a large town with 12,000 inhabitants. Table 1 tells you that there will be 12,000 divided by 1200 = 10 clerics in the town. Multiplying by 10 all the way down the cleric table gives this:

Level # Clerics
1 5.041905
2 2.520952
3 1.260476
4 0.581758
5 0.275013
6 0.137506
7 0.068753
8 0.033613
9 0.016806
10 0.011204
11 0.008403
12 0.006723
13 0.005602
14 0.004802
15 0.004202
16 0.003735
17 0.003361
18 0.003056
19 0.002801
20 0.002586
21 0.002401
22 0.002241
23 0.002101

What I normally do is actually feed the values into a poisson-distribution random number generator so that I get a spread of values who’s mean is the number given, which is what last week's program does (I've added the source code at the end here).

This final result is much more like a literary setting where the central characters (the PCs) are much less likely to encounter high level NPCs than low level ones. However, there is an issue with high levels.

Once the xp totals reach name level (for most classes) the amount of xp needed increases at a constant rate. This means that the ratio from, say, 12th level to 13th level, to 14th is gradually falling rather than increasing. The practical result is that the representation of very high level characters in the population reaches a plateau and 22nd level clerics are not really any rarer than 21st level ones, as you can see in the above table.

You might want to tinker with this for your campaign.

I've stuck the code up onto GitHub but I would warn you that I'm not a Javascript programmer and this is the first real program I've written in the language so the code is not great (I've done lots of glue-code in it of course, AJAX and stuff, but that's mostly calling other programs and just updating displays rather than being a complete application). The program was originally in Perl but I wanted to post it on the blog so I converted it. Consequently, the JS is currently the more up-to-date version but if I make further change it's more likely to be to the Perl version since that version's output is suitable for reading into Emacs' org-mode where I can further format and manipulate it.

Anyway, with the code on your local machine you can fiddle with assumptions such as half the population being too young to be classed, or perhaps add features such as generating ages for the npcs. Or whatever!


  1. This comment has been removed by the author.

  2. Have you considered what the implied mortality rate of an adventurer is in approach B if approach A is accurate assuming a 100% survival rate?