Work the Shell - <emphasis>Yahtzee</emphasis> as a Shell Script? When Will It End?

We seem to spend a lot of time talking about games and how to program them
as shell scripts, don't we? From Blackjack to
Baccarat, we're in danger of
having to rename this column “game programming in the
shell”. But, that'd
be crazy; who in the heck would write multiple games as shell scripts?

So, this month, I thought it would be fun to look at a dice game and
see how the basic set of playing card functions we've written previously
compare to the necessary functions to play a dice game.

Yahtzee was first introduced by Hasbro in 1956 as
Yacht (having been
invented by a wealthy couple on their fancy boat) and has been one of
its best-selling titles since, spawning many variants,
including hand-held electronic games and more. At its heart though,
it's basically five-card draw poker played with dice. The wrinkle is that
there are a set number of possible hands you can roll, and you attempt
to achieve them all to maximize your score.

For example, roll a 3 4 4 4 5, and you might well pick up the 3 and the 5,
hoping for either “your fours” (which you can get only once and want to
choose when you have the maximum number of fours showing), or if you get
five of a kind, a “Yahtzee”, which is a big-points bonus but obviously
difficult to achieve.

Like five-card draw, you can pick up zero to five dice and reroll
them, but unlike five-card draw, you can do this twice on your turn,
not once. So, perhaps the 3 4 4 4 5 rerolls as a 1 4 4 4 4. The second
roll would then be to reroll the one and hope for another four. Either way,
it's a good roll (unless you've already marked your fours).

Modeling It All

Dice are quite easy to create in a script—so easy it reveals how
straightforward a script like liar's dice would be to write:

function rollDie()
{
dieroll=$(( ( $RANDOM % 6 ) + 1 ))
}

If it's this easy to roll a die, though (dice, by the way, is plural of
die), it'd be darn easy to write a quick Dungeons and
Dragons dice
roller too, as shown:

All you need to do is call rollDie with the number of sides you want on
the dice it needs to roll. Using a 20-sided die? Try rollDie
20 to see
what rolls.

This also can quickly and easily be converted into a command-line
function, so you could be a real D&D nerd by having a laptop adjacent and
typing in roll 20 every time you're actually supposed to roll the die.

But back to Yahtzee, yes? The easy part of modeling the game is the dice
rolls. We need to have five dice, and that easily can be done with an array:

Note carefully where I do and don't need to use the curly braces to get
the array to work properly in the shell. Try this to see how it differs:

echo "You rolled " $dice[0] $dice[1]

Quite different results, as you can see. (And, as usual with shell
programming, there's no useful warnings or error messages to clue you in
to what might be wrong.)

Rerolling Specific Dice

Rolling the dice to get an initial hand is pretty straightforward,
so let's take the next step and write the code to let you reroll
any or all of the five dice twice to get your final hand.

There are a number of ways to ask for this sort of input, but to make it
a bit chatty, let's simply present each die in ordinal value and let the
player enter the appropriate number to indicate that it should be rerolled.
Um, let me show you what I mean:

Now, of course, it's time for some actual logic here, not merely a
rudimentary test. I've simplified things just a wee bit by using array
indices 1–5 rather than 0–4, sacrificing the slot of entry 0 so that
it's easier to work with the values. This means if you ask to reroll
die 4, for example, it's just a reassignment of dice[4].

Yes, I snuck in the notation of having the dice values shown within
square brackets just for visual appearance. It makes the echo statements
a bit more confusing, as you can see just a bit earlier, but the output
is more attractive.

Dave Taylor has been hacking shell scripts for over thirty years. Really.
He's the author of the popular "Wicked Cool Shell Scripts" and
can be found on Twitter as @DaveTaylor and more generally at
www.DaveTaylorOnline.com.

Trending Topics

Upcoming Webinar

Getting Started with DevOps - Including New Data on IT Performance from Puppet Labs 2015 State of DevOps Report

August 27, 2015
12:00 PM CDT

DevOps represents a profound change from the way most IT departments have traditionally worked: from siloed teams and high-anxiety releases to everyone collaborating on uneventful and more frequent releases of higher-quality code. It doesn't matter how large or small an organization is, or even whether it's historically slow moving or risk averse — there are ways to adopt DevOps sanely, and get measurable results in just weeks.