Last updated
May 25, 2025
Rolling Dice in PowerShell
If you’re a lover of tabletop role-playing games and like PowerShell, rolling virtual dice with PowerShell can be a fun exercise in scripting. Today, we’re dissecting my Invoke-DiceRoll
function—a simple way to generate random dice rolls using PowerShell. Let’s have a look!
Desired Output
Before getting too far into the script, I thought about what I wanted the output to look like. It’s best practice to return only one item, but I want to show the die type and roll result for each one; it might also be nice to show which unit of the dice was rolled if more than one of the same die type was rolled. Because of this, a PSCustomObject
seemed to be a decent choice, with each die rolled being a child object.
1
2
3
4
5
6
7
| # Create the object to be output
$rollResults = [System.Collections.Generic.List[PSObject]]::new()
#...
# Actually outputting the object
Write-Output $rollResults
|
Parameters
We want to be able to roll different quantities and types of polyhedral dice, so we’ll accept an integer for each of the most common dice types (d34, d6, d8, d10, d12, and of course, d20):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| param(
[Parameter(ParameterSetName = 'Default')]
[int]$D4 = 0,
[Parameter(ParameterSetName = 'Default')]
[int]$D6 = 0,
[Parameter(ParameterSetName = 'Default')]
[int]$D8 = 0,
[Parameter(ParameterSetName = 'Default')]
[int]$D10 = 0,
[Parameter(ParameterSetName = 'Default')]
[int]$D12 = 0,
[Parameter(ParameterSetName = 'Default')]
[int]$D20 = 0
)
|
And we’ll use a hashtable to map the type of die to the parameter so we can output the die type in the output later.
1
2
3
4
5
6
7
8
| [hashtable]$diceTypes = @{
d4 = $D4
d6 = $D6
d8 = $D8
d10 = $D10
d12 = $D12
d20 = $D20
}
|
Now we just need to roll the dice and add the results to $rollResults
!
Get-Random and Outputting Results
As we may want to roll multiple dice, we’ll use a foreach
loop. Inside the loop, we’ll evaluate what types and quantities are being rolled, then use the Get-Random
cmdlet to “roll” the dice. The -Minimum
parameter will be 1
, as it is impossible to roll a 0
on any of our dice, and the -Maximum
will be the number of sides on the die, plus 1
.
1
2
3
4
5
6
7
8
9
10
11
12
| foreach ($dice in $diceTypes.Keys) {
[int]$count = $diceTypes[$dice]
[int]$sides = $dice.Substring(1)
for ($i = 1; $i -le $count; $i++) {
[int]$roll = Get-Random -Minimum 1 -Maximum ($sides + 1)
$rollResults.Add([PSCustomObject]@{
Die = $dice
Unit = $i
RollValue = $roll
})
}
}
|
With all of the above, we have a complete function as shown below:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
| function Invoke-DiceRoll {
param(
[Parameter(ParameterSetName = 'Default')]
[int]$D4 = 0,
[Parameter(ParameterSetName = 'Default')]
[int]$D6 = 0,
[Parameter(ParameterSetName = 'Default')]
[int]$D8 = 0,
[Parameter(ParameterSetName = 'Default')]
[int]$D10 = 0,
[Parameter(ParameterSetName = 'Default')]
[int]$D12 = 0,
[Parameter(ParameterSetName = 'Default')]
[int]$D20 = 0
)
[hashtable]$diceTypes = @{
d4 = $D4
d6 = $D6
d8 = $D8
d10 = $D10
d12 = $D12
d20 = $D20
}
$rollResults = [System.Collections.Generic.List[psobject]]::new()
foreach ($dice in $diceTypes.Keys) {
[int]$count = $diceTypes[$dice]
[int]$sides = $dice.Substring(1)
for ($i = 1; $i -le $count; $i++) {
[int]$roll = Get-Random -Minimum 1 -Maximum ($sides + 1)
$rollResults.Add(
[PSCustomObject]@{
Die = $dice
Unit = $i
RollValue = $roll
}
)
}
}
Write-Output $rollResults
}
|
And we can roll dice like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
| # dot source the function, then run the function
. /path/to/Invoke-DiceRoll.ps1
Invoke-DiceRoll -D6 2 -D20 1
# Or, simply call the function script itself
& /path/to/Invoke-DiceRoll.ps1 -D6 2 -D20 1
# Sample output:
# Die Unit RollValue
# --- ---- ---------
# d20 1 11
# d6 1 5
# d6 2 2
|
Checking Our Work and Wrapping Up
Now that the function is–well–functional…let’s check out work. Running the function does not appear to produce any errors, but how well is the randomness working?
I ran the following to see how balanced the dice were, testing using 10,000 d4 dice (which only took 321ms, by the way):
1
2
3
4
5
6
7
8
9
10
11
12
| Invoke-DiceRoll -d4 10000 |
Group-Object RollValue |
Sort-Object Name -Descending |
Select-Object Name, Count
# Output
# Name Count
# ---- -----
# 4 2409
# 3 2531
# 2 2561
# 1 2499
|
Note that the 4 sides of the d4 die have roughly equivalent times rolled over 10,000 iterations, representing pretty fair dice. The spread gets even tighter over 100,000 rolls (which takes around 3.5s):
1
2
3
4
5
6
7
8
9
10
11
12
| Invoke-DiceRoll -d4 100000 |
Group-Object RollValue |
Sort-Object Name -Descending |
Select-Object Name, Count
# Output
# Name Count
# ---- -----
# 4 24984
# 3 24932
# 2 24965
# 1 25119
|
The full function file is available in a
GitHub gist.
So there we go! A simple function in PowerShell to “roll” polyhedral dice. Now at your next Dungeons and Dragons session you can be extra nerdy and whip out your preferred terminal on your laptop if you’ve forgotten your dice. If you do, feel free to share a screenshot or picture of your usage by tagging me in a post on
BlueSky (@griff.systems) or
LinkedIn (@griffeth-barker)!