2 min read

Riddler 2020-05-15

Two things are guaranteed to grab my attention in a Riddler Column - Dungeons and Dragons (DnD) and probability spaces small enough to enumerate all combinations.

The default position is roll 1 20-sided die (d20), and the other scenarios involve 4 d20 rolls, with a probability space of 20^4= 160,000. More than I’m willing to do by hand, but R laughs at how easy this is.


die <- 1:20
all_combinations <- list(die_1 = die,die_2=die,die_3=die,die_4=die) %>% 
  cross_df()
result_table <- all_combinations %>% 
  mutate(advantage_1 = pmax(die_1,die_2), advantage_2 = pmax(die_3,die_4),
         dis_1 = pmin(die_1,die_2), dis_2=pmin(die_3,die_4)) %>% 
  mutate(dis_of_advantage = pmin(advantage_1, advantage_2),
         advantage_of_dis = pmax(dis_1,dis_2)) 

Then the average for each is:

result_table %>% 
  summarise(default = mean(die_1),
            dis_of_advantage = mean(dis_of_advantage),
            advantage_of_dis = mean(advantage_of_dis)) %>% 
  knitr::kable()
default dis_of_advantage advantage_of_dis
10.5 11.16666 9.833338

So disadvantage of advantage is better than default, which is better than advantage of disadvantage. On average.

The probability of getting exactly each roll is:

result_table %>% 
  select(die_1, dis_of_advantage, advantage_of_dis) %>% 
  pivot_longer(1:3) %>% 
  count(name,value) %>% 
  group_by(name) %>% 
  mutate(p=n/sum(n)) %>% 
  ungroup() %>% 
  ggplot(aes(x=value,y=p,colour=name)) + geom_line() +
  scale_y_continuous(labels=scales::percent) +
  expand_limits(y=0) +
  theme_minimal()

Or the probability of getting at least N on the roll is:

result_table %>% 
  select(die_1, dis_of_advantage, advantage_of_dis) %>% 
  pivot_longer(1:3) %>% 
  count(name,value) %>% 
  group_by(name) %>% 
  mutate(p=n/sum(n)) %>% 
  arrange(-value) %>% 
  mutate(p=cumsum(p)) %>% 
  ungroup() %>% 
  plot_ly(x=~value,y=~p,split=~name) %>% 
  add_lines() %>% 
          layout(yaxis = list(tickformat = "%"))