Title: Unraveling the DnD Dice Duel Riddle with Monte Carlo Simulation in R

R
Fun
Author

Giorgio Luciano and ChatGPT

Published

January 14, 2024

Unraveling the DnD Dice Duel Riddle with Monte Carlo Simulation in R

Introduction

Embark on a journey into the realm of Dungeons & Dragons as we unravel a captivating fiddle riddle involving a dice duel. Using the power of the R programming language and the Monte Carlo simulation method, we’ll simulate the outcomes of duels between two players, each armed with a bag containing six distinct DnD dice. Prepare to explore the fascinating world of probability and randomness! See the riddle posted here by Fiddler on the Proof

At a table sit two individuals, each equipped with a bag housing six DnD dice: a d4, a d6, a d8, a d10, a d12, and a d20. The challenge is to randomly select one die from each bag and roll them simultaneously. For example, if a d4 and a d12 are chosen, both players roll their respective dice, hoping for fortuitous results. Monte Carlo Simulation in R:

To confront this enigma, we turn to the Monte Carlo method. The following R code snippet initiates a simulation of multiple dice duels, offering a glimpse into the complexities of DnD dice outcomes.

we can break down the analysis into different cases:

  1. Case 1: Both players take the same type of dice.

  2. Case 2: Both players take different types of dice (without repetition of the same combination).

We’ll generate plots for each case and then provide a summary of the results. Here’s the code:

library(ggplot2)
# Function to simulate a single dice duel with both players taking the same type of dice
simulate_same_dice_duel <- function() {
  dice_type <- sample(c(4, 6, 8, 10, 12,20,40,64,80,120,128), 1)
  roll_player1 <- sample(1:dice_type, 1)
  roll_player2 <- sample(1:dice_type, 1)
  return(c(dice_type, roll_player1, dice_type, roll_player2))
}

# Function to simulate a single dice duel with both players taking different types of dice
simulate_different_dice_duel <- function() {
  dice_types <- sample(c(4, 6, 8, 10, 12,20,40,64,80,120,128), 2, replace = FALSE)
  roll_player1 <- sample(1:dice_types[1], 1)
  roll_player2 <- sample(1:dice_types[2], 1)
  return(c(dice_types[1], roll_player1, dice_types[2], roll_player2))
}

# Monte Carlo simulation for both cases
num_trials <- 10000

# Case 1: Both players take the same type of dice
same_dice_simulation_results <- replicate(num_trials, simulate_same_dice_duel())
same_dice_data <- data.frame(Player = rep(c("Player 1", "Player 2"), each = ncol(same_dice_simulation_results)),
                             Dice_Type = rep(same_dice_simulation_results[1, ], 2),
                             Roll_Value = as.integer(c(same_dice_simulation_results[2, ], same_dice_simulation_results[4, ])))

# Visualize the results for Case 1 using ggplot2
ggplot(same_dice_data, aes(x = factor(Dice_Type), y = Roll_Value, fill = Player)) +
  geom_boxplot() +
  labs(title = paste("Case 1: Both Players Take the Same Dice (", num_trials, "trials)"),
       x = "Dice Type",
       y = "Roll Value",
       fill = "Player") +
  theme_minimal()

# Case 2: Both players take different types of dice
different_dice_simulation_results <- replicate(num_trials, simulate_different_dice_duel())
different_dice_data <- data.frame(Player = rep(c("Player 1", "Player 2"), each = ncol(different_dice_simulation_results)),
                                  Dice_Type_Player1 = rep(different_dice_simulation_results[1, ], 2),
                                  Roll_Value_Player1 = as.integer(c(different_dice_simulation_results[2, ])),
                                  Dice_Type_Player2 = rep(different_dice_simulation_results[3, ], 2),
                                  Roll_Value_Player2 = as.integer(c(different_dice_simulation_results[4, ])))

# Visualize the results for Case 2 - Player 1 (Dice 4 vs. Dice 20)
ggplot(subset(different_dice_data, Dice_Type_Player1 %in% c(4, 20)), aes(x = factor(Dice_Type_Player2), y = Roll_Value_Player1)) +
  geom_boxplot() +
  labs(title = paste("Case 2 - Player 1: Dice 4 vs. Dice 20 (", num_trials, "trials)"),
       x = "Dice Type Player 2",
       y = "Roll Value Player 1") +
  theme_minimal()

# Visualize the results for Case 2 - Player 2 (Dice 4 vs. Dice 20)
ggplot(subset(different_dice_data, Dice_Type_Player2 %in% c(4, 20)), aes(x = factor(Dice_Type_Player1), y = Roll_Value_Player2)) +
  geom_boxplot() +
  labs(title = paste("Case 2 - Player 2: Dice 4 vs. Dice 20 (", num_trials, "trials)"),
       x = "Dice Type Player 1",
       y = "Roll Value Player 2") +
  theme_minimal()

# Visualize the results for Case 2 - Player 1 (Dice 4 vs. Dice 12)
ggplot(subset(different_dice_data, Dice_Type_Player1 %in% c(4, 12)), aes(x = factor(Dice_Type_Player2), y = Roll_Value_Player1)) +
  geom_boxplot() +
  labs(title = paste("Case 2 - Player 1: Dice 4 vs. Dice 12 (", num_trials, "trials)"),
       x = "Dice Type Player 2",
       y = "Roll Value Player 1") +
  theme_minimal()

# Visualize the results for Case 2 - Player 2 (Dice 4 vs. Dice 12)
ggplot(subset(different_dice_data, Dice_Type_Player2 %in% c(4, 12)), aes(x = factor(Dice_Type_Player1), y = Roll_Value_Player2)) +
  geom_boxplot() +
  labs(title = paste("Case 2 - Player 2: Dice 4 vs. Dice 12 (", num_trials, "trials)"),
       x = "Dice Type Player 1",
       y = "Roll Value Player 2") +
  theme_minimal()

# Visualize the results for Case 2 - Player 2 (Dice 4 vs. Dice 128)
ggplot(subset(different_dice_data, Dice_Type_Player2 %in% c(4, 128)), aes(x = factor(Dice_Type_Player1), y = Roll_Value_Player2)) +
  geom_boxplot() +
  labs(title = paste("Case 2 - Player 2: Dice 4 vs. Dice 128 (", num_trials, "trials)"),
       x = "Dice Type Player 1",
       y = "Roll Value Player 2") +
  theme_minimal()

# Summarize the results for Case 1 (Same Dice)
summary_case1 <- table(same_dice_data$Roll_Value)

# Summarize the results for Case 2 (Different Dice)
summary_case2 <- table(different_dice_data$Roll_Value_Player1 == different_dice_data$Roll_Value_Player2)

# Display summaries
cat("\nSummary of Case 1 - Same Dice:\n")

Summary of Case 1 - Same Dice:
print(summary_case1)

   1    2    3    4    5    6    7    8    9   10   11   12   13   14   15   16 
1540 1463 1570 1552 1112 1088  774  827  564  562  389  369  244  214  223  212 
  17   18   19   20   21   22   23   24   25   26   27   28   29   30   31   32 
 198  204  206  208  128  141  109  118  111  132  110  123  139  114  140  129 
  33   34   35   36   37   38   39   40   41   42   43   44   45   46   47   48 
 138  116  118  108  129  100  135  113   66   78   65   85   86   93   74   84 
  49   50   51   52   53   54   55   56   57   58   59   60   61   62   63   64 
  69   83   66  100   91   73   89   67   75   77   89   90  100   91   79   86 
  65   66   67   68   69   70   71   72   73   74   75   76   77   78   79   80 
  62   60   45   53   43   52   61   50   55   52   45   40   46   46   54   44 
  81   82   83   84   85   86   87   88   89   90   91   92   93   94   95   96 
  32   25   26   24   28   36   24   26   33   27   37   39   29   23   26   36 
  97   98   99  100  101  102  103  104  105  106  107  108  109  110  111  112 
  20   28   21   45   23   42   21   32   27   34   21   21   40   29   20   38 
 113  114  115  116  117  118  119  120  121  122  123  124  125  126  127  128 
  27   26   29   32   35   24   23   25   13   12   14    9   19   11   14   20 
cat("\nSummary of Case 2 - Different Dice:\n")

Summary of Case 2 - Different Dice:
print(summary_case2)

FALSE  TRUE 
19330   670 

Analyzing the Duel Results

Through the marriage of R programming and Monte Carlo simulation, we’ve successfully deciphered the intricacies of the DnD dice duel riddle. Whether you’re a seasoned tabletop gamer or a data science enthusiast, this approach serves as a versatile tool for exploring and comprehending complex scenarios governed by chance. As you embark on your own coding adventures, may the rolls be ever in your favor! Happy coding!