BASH Dice Game

Jarret B

Well-Known Member
Staff member
Joined
May 22, 2017
Messages
348
Reaction score
387
Credits
12,246
Previously, I did an article on a BASH card game called Go Fish. In this article, I will make a Yahtzee style game in BASH. The completed game is downloadable from below.

Let's go over some of the basic concepts for the base of the game.

Basic Concepts

I have split the score card into two sections. In the original game, there is an upper and lower section. I split these into the left and right side so they would fit on the screen easier. To handle the screen better, I use the command 'tput' to manipulate where we place things on the screen.

The command 'tput clear' will clear the screen. When using 'tput cup <row> <column>' you can move the cursor to a specific spot and then 'echo' some information at that exact spot. I print out the scorecard on the screen and include the score or a letter for the specific score line. You can see this in Figure 1.

Figure 01.JPG

FIGURE 1

For example, to place a score at 'Ones', you would select 'A' or 'a' at the prompt. It automatically makes any entry uppercase. Use 'R' to roll the dice not selected to keep. Press 'x' to quit the game. As you place a score on the scorecard, the grand total is updated.

Once you choose a slot for a score, the letter will disappear and show the proper score for that slot. Once the slot has a score and not a letter, then you cannot choose the letter from valid entries for the prompt. If you choose 'M' for 'Chance', then 'M' is no longer a valid choice. Initially, the string of valid choices is in a variable called 'instr' and looks like 'instr="ABCDEFGHIJKLM12345XR"'. As we select letters for the scorecard, we remove them from the list. The list is auto generated in the function 'makeinstr'. Here, all characters remaining on the board, 'A-M', the function adds to the list. At the end of the function, '12345XR'. These characters are always valid and usable by the player.

The numbers 1-5 are used to specify to keep or re-roll a specific die. Press a number once and it moves the die to the Keep column. Press the same number again and it moves to the Roll column. Use 'R' to roll the dice in the 'Roll' column.

On the third roll, the script creates the 'instr' list again, but now it removes the '12345R' from the choices. The player cannot roll or move the dice from the Keep column since it is the last roll. The function is called 'makelastinstr'.

During the input option for selecting a single character, there is a variable named 'rollnow' that is set to false ('0'). When the user presses the 'R' key to 'Roll' the dice, the 'rollnow' variable is set to true ('1').

If the user selects a score slot, then the variable 'breakoutnow' is set to a value of '1' and the number of rolls ('rollcount') is set to 4. Once this is set, the loop for the 3 rolls is left. The loop is entered 13 times, since there are 13 slots on the scorecard to choose.

When the user fills all 13 slots, the script displays the final score of the player in a Zenity message box.

Arrays

There are a few arrays used in the script.

The 'card[]' array stores the 13 slots on the scorecard, which are originally set to letters.

There are also six array elements called 'die[]'. The script initializes the 'die' as:

die[1]="⚀"
die[2]="⚁"
die[3]="⚂"
die[4]="⚃"
die[5]="⚄"
die[6]="⚅"


These are a graphical representation of the individual die. We generate them using UTF-8 symbols. We make them, in Linux, using CTRL+SHIFT+U to generate a 'u' on the screen. Then type in the UTF-8 code and press Enter. The characters should change into the character of the specific die. The codes are as follows:

- 2680
- 2681
- 2682
- 2683
- 2684
- 2685

The 'roll' array stores the value of the die, 1 to 6, for the specific die, 1 to 5.

The 'reroll' array holds the value of '0' or '1' to determine if the die is to keep or roll.

These are the arrays used in the script for the game.

Functions

There are quite a few functions in the script, but let's look at a few that are important.

function screensize {
col=tput cols
row=tput lines
if [[ col -lt "100" ]]
then
col=100
fi
if [[ row -lt "25" ]]
then
row=25
fi
printf '\e[8;'${row}';'${col}'t'
}


The function called 'screensize' is used to make the terminal a minimum size to be adequate to view the score card and dice.

The first two commands will get the current number of columns and rows for the current terminal window.

If the current window is less than 100 columns wide, then the minimum is set to 100. If the terminal is over 100, then it is fine to keep as is.

We checked the number of rows for a value of 25. If it is 25 or more, then we keep the higher number. Otherwise, the number of rows is set to 25.

Once we have determined the minimum number of rows and columns, we change the size of the terminal window with the command 'printf '\e[8;'${row}';'${col}'t''. The screen should be adequate for what we need. You can make the terminal window a small size and then start the script to see that the window changes to be bigger. If you have the window larger than needed, it should not change size.

Another important function is the 'scorecard' function. Once a user chooses a slot to place a score, we need to show the updated score card. This function redraws the score card.

function showcard {
place1=1
place2=7
tput clear
echo -e "Ones \t ${card[$place1]} \t\t 3 of a kind \t\t ${card[$place2]}"
((place1+=1))
((place2+=1))
echo -e "Twos \t ${card[$place1]} \t\t 4 of a kind \t\t ${card[$place2]}"
((place1+=1))
((place2+=1))
echo -e "Threes \t ${card[$place1]} \t\t Full House \t\t ${card[$place2]}"
((place1+=1))
((place2+=1))
echo -e "Fours \t ${card[$place1]} \t\t Small Straight \t ${card[$place2]}"
((place1+=1))
((place2+=1))
echo -e "Fives \t ${card[$place1]} \t\t Large Straight \t ${card[$place2]}"
((place1+=1))
((place2+=1))
echo -e "Sixes \t ${card[$place1]} \t\t Yahtzee \t\t ${card[$place2]}"
((place2+=1))
echo -e "\t\t\t Chance \t\t ${card[$place2]}"
echo -e "Sub-Total: \t $total "
echo -e "Bonus: \t\t $bonus "
echo -e "Left Total: \t $ltotal "
echo " "
echo " "
echo -e "Game Total: \t $gtotal"
}


NOTE: The 'showcard' function does not redraw the die in the Roll or Keep columns.

This function has two variables we used to specify the two columns of data. The first column shows the 'card' array for element 1-6, so 'place1' starts at '1'. The right column shows the slots 7-13. At the end of the card is the 'Sub-Total', 'Bonus', 'Left Total' and 'Grand Total'.

Another good function to cover is the function to show the dice on the screen:

function showdice {
tput cup 0 70
echo "Roll Keep "
for count in {1..5}
do
tput cup $count 70
if [[ ${reroll[$count]} -eq "1" ]]
then
echo " ${die[${roll[$count]}]} $count "
else
echo " $count ${die[${roll[$count]}]}"
fi
done
}


We start by printing the column header for the 'Roll' and 'Keep' columns. The script then enters into a loop for a count from 1 to 5. We move the cursor to the specific line 'tput cup $count 70'. We check if the 'reroll' value for the die is set to Roll or Keep and print the line accordingly.

Scoring

The left side of the scorecard is easy to tally. When the user makes a selection (A-F), the script examines the dice values. If the value of the die is what we are looking for, we add it to the tally. Once done, we place the tally value in the slot.

If the user chooses the right side of the scorecard, we first sort the dice in numeric order. For three and four of a kind, we just check if the specified amount of dice match. For three of a kind, we check die 1, 2, 3 and 2, 3, 4 and 3, 4, 5. If any of of the three dice are in any set match, then there is a three of a kind. The same goes for four of a kind. We just check die 1, 2, 3, 4 and 2, 3, 4, 5.

For full house, we check that dice 1 and 2 match and then 3, 4 and 5 match. We also check that dice 1, 2 and 3 match as well as 4 and 5. If either of these is true, then there is a full house.

Yahtzee is just a matter of seeing if all five dice are the same.

Chance is just adding up the total of all five dice.

Large straight is simple, after we sort the die, we just check that the dice are '12345' or '23456'.

Small straight is the most difficult. After sorting the dice, any duplicates need removed. After it removes the duplicates, we just need to see if the remaining dice are equal to '1234', '2345', or '3456'. If we left in a duplicate, such as the dice, are '12334', it will match none of the strings we are looking for. After removing the duplicate, we get the string of '1234', which matches one of our strings.

These are the main areas of logic that need a little explaining. The rest should be straightforward, I hope.

The code is attached below. Just rename the file to 'jyaht.sh' and make it executable. You should then be able to play the game.

Conclusion

Writing code in any programming or scripting language can be helpful to make some tasks on a computer easier to manage. Learning the language can be a little difficult, but if you find a program to write that makes you want to write it, then it helps.

Writing games, even simple ones, can help learn a language and logic methods. Coding can sometimes be difficult to accomplish certain tasks, but working through it and finding a good way to make it work can help you. It sharpens your coding skills and makes you think about a problem and find a solution. There may even be times you come back to a program and improve the coding because you think of a better solution.
 

Attachments

  • jyaht.txt
    8.1 KB · Views: 260
Last edited:

Members online


Top