Search

Shell Scripting: Dungeons, Dragons and Dice

Dungeons, Dragons and Dice—a script that lets you roll those 3d6 and 2d20
that a surprising number of games require.

In my last
article, I talked about a really simple shell script for a game called Bunco,
which is a dice game played in rounds where you roll three dice and compare your
values to the round number. Match all three and match the round number,
and you just got a bunco for 25 points. Otherwise, any die that match
the round are worth one point each. It's simple—a game designed for people
who are getting tipsy at the local pub, and it also is easy to program.

The core function in the Bunco program was one that produced
a random number between 1–6 to simulate rolling a six-sided die. It looked
like this:

To test it, let's just write a tiny wrapper that simply asks for a
20-sided die (d20) result:

rolldie die 20
echo resultant roll is $die

Easy enough. To make it a bit more useful, let's allow users to specify
a sequence of dice rolls, using the standard D&D notation of
nDm—that
is, nm-sided dice. Bunco would have been done with 3d6,
for example (three six-sided die). Got it?

Since you might well have starting flags too, let's build that into
the parsing loop using the ever handy getopt:

Ah, the last one points out a mistake in the script. If there's no
number of dice specified, the default should be 1. You theoretically
could default to a six-sided die too, but that's not anywhere near so safe
an assumption.

With that, you're close to a functional program because all you need is a
loop to process more than one die in a request. It's easily done with a while
loop, but let's add some additional smarts to the script:

Did you catch that I fixed the case when $dice has no value? It's
tucked into the reference in the while statement. Instead of referring
to it as $dice, I'm using the notation
${dice:=1}, which uses the value
specified unless it's null or no value, in which case the value 1 is
assigned and used. It's a handy and a perfect fix in this case.

In a game, you generally don't care much about individual die values;
you just want to sum everything up and see what the total value
is. So
if you're rolling 4d20, for example, it's just a single value you
calculate and share with the game master or dungeon master.

Let's run it a second time just to ensure you're getting different
values too:

3d6 = 11
1d20 = 10
2d100 = 162
4d3 = 6
d5 = 3

There are definitely different values, and it's a pretty useful script, all in all.

You could create a number of variations with this as a basis,
including what some gamers enjoy called "exploding
dice". The
idea is
simple: if you roll the best possible value, you get to roll again and
add the second value too. Roll a d20 and get a 20? You can roll again,
and your result is then 20 + whatever the second value is. Where this
gets crazy is that you can do this for multiple cycles, so a d20 could
become 30, 40 or even 50.

And, that's it for this article. There isn't much else you can do with dice at this
point. In my next article, I'll look at...well, you'll have to wait and see! Don't
forget, if there's a topic you'd like me to tackle, please send me
a note!

Dave Taylor has been hacking shell scripts on UNIX and Linux systems for a
really long time. He's the author of Learning Unix for Mac OS
X and Wicked Cool Shell Scripts. You can find him on Twitter
as @DaveTaylor, and you can reach him through his tech Q&A site: Ask Dave Taylor.