Creating a dice game in Python (part 1)

Introduction

In this series of posts we will look at how to code a simple dice game in Python, starting with the initial concept, all the way through to the coding and adding extension features.


The game that we will develop is a simple two dice game called Sevens out. The game rules from lovetoknow.com are as follows:

Game rules

  1. The players decide upon a winning score, this could be 500 or 1,000.
  2. Each player, in turn, throws the dice.
  3. Each player rolls and continues to roll the dice until they throw a 7.
  4. They score the sum of all the numbers thrown before the 7.
  5. Players announce their tally after each throw and once they have thrown a 7, their score is noted on the score sheet.
  6. Doubles score double the value. For example, if a player who throws two 4s making eight, their score is 16.
  7. The player reaches the pre-arranged total first is the winner.

Iteration 1

Rather than attempting to develop the entire game in one pass, we will develop the game in multiple stages using an iterative development approach.
For the first iteration we will get one round of dice rolling completed for a single player.

Before writing any code we will develop a high-level design using pseudocode. This allows us to consider the key logical parts of the algorithmic solution without having to get bogged downed in the finer details of exactly how to code this in Python.

The pseudocode for our proposed first iteration is shown below. The most important part of the pseudocode is that it conveys the intended logic of the problem we are solving. For example the third and fourth lines of pseudocode indicates that a random number between 1 and 6 needs to be generated. How this is done does not matter at this stage – indeed the solution is dependent on the coding language being used, whereas pseudocode should be coding language independent.


set score to 0
loop
   set roll1 to random number between 1 and 6
   set roll2 to random number between 1 and 6
   set total to roll1 + roll2
   if total = 7
   then
      exit the loop
   else
      set score to score + total
   end if
end loop
output score

The resulting code in Python is almost a line for line translation of the pseudocode. One noteworthy change is the addition of a Boolean-valued variable, valid, which is used to indicate whether all rolls to date are valid (do not add up to 7). The while loop will continue whilst this variable is true. When a total of 7 is rolled the value of the variable becomes false. The use of this loop termination variable is highlighted in the code below. The relationship between the remainder of the code and the pseudocode should hopefully be evident.

import random

valid = True
score = 0

while valid:
    roll1 = random.randint(1, 6)
    roll2 = random.randint(1, 6)
    total = roll1 + roll2
    if total == 7:
        valid = False
    else:
        score = score + total

print("Score is", score)

The screenshot below shows the code running in the Pycharm IDE. The code runs until a total of 7 is rolled and then prints the resulting score.

Developing a text-based adventure game (Part 2)

Adding and linking multiple locations

In the first part of the text-based adventure game development tutorial we described how print, input and conditional statements can be used to implement an interactive encounter. We also noted that although nested conditional statements could be used to link multiple encounters, this approach will quickly lead to the development of spaghetti code.

In this tutorial we investigate a solution to developing linked encounters using functions and loops.

Game synopsis

We begin by providing a brief synopsis for our proposed game.

The player quests to retrieve the magical sippy cup, which is believed to grant eternal life whoever has it in their possession. However the sippy cup has been stolen, and
it is the responsibility of our brave adventurer to rescue it. The game consists of three location.

  • Location 1 contains a locked chest. The chest cannot be opened without the key which is not in this location.
  • Location 2 contains a magical sword hidden on a ledge at the top of a steep cliff face.
  • Location 3 contains an evil Ogre who happens to have the key to the chest in his possession. The Ogre can only be slain if the player has found the magical sword.

Game layout

Having come up with an overall synopsis for the game, the next step is to consider the game layout and how the locations connect to each other. This can be done with pencil and paper, or a simple digital tool such as OneNote or Paint.

In the layout design shown below there are three locations in addition to a start and finish location. Directed arcs show the possible transitions between locations; for example the start location links to location 1 and location 2.

The diagram shows the layout for a simple non-linear text based adventure game. The nodes of the diagram represent the game locations, while the edges represent connections between these locations.

Initial layout for a simple non-linear text based adventure game

Location details

Having designed the layout of the adventure, we next need to define the narrative for each location. This should include the contextual information as well as the options available to the player. For example, the narrative for the start location would be as follows.

You are on a quest to retrieve the find the lost sippy cup. The sippy cup is a priceless treasure that grants the user eternal life. You come to a junction. You can either go west or east.

Linking locations

The final step before we can begin code is to define the links between the different locations. We need to provide details of the actions or events that need to occur to move from one location to another.

Shows how locations can be linked with events.

Game layout with linking events

Initial coding step

To code the flowchart shown earlier we firstly add a variable to represent the location that the player is currently in. Line 1 of the code listing below
initialises the location variable to the start location. Lines 20-24 contain a while loop which is run repeatedly until the condition is true.
In this case, the code inside the while loop is repeated until the player is in the finish location. The != operator checks that the first argument is not equal to the second argument. A conditional statement is used to check the current location and call a function corresponding to the location the player is currently in. The else branch at the end uses a break statement to exit the loop. This is used to ensure that the game does not get stuck in an infinite loop.

location="start"

def playStart():
    print("You are on a quest to find the lost sippy cup.")
    print("The sippy cup is a priceless treasure that grants\nthe user eternal life")
    print("You come to a junction. You can either go (w)est or (e)ast.")
    print("What do you select?")
    response=input("> ")
    if (response=="w"):
        location="location1"
        print("You travel along the path to the west...")
    elif (response=="e"):
        location="location2"
        print("You travel along the path to the east.")
        print("The path leads gradually upwards until you finally reach a ledge.")
    else:
        location="start"
    return location

while (location!="finish"):
    if (location=="start"):
        location=playStart()
    else:
        break

Download source code [Stage 1 code]

Defining functions

To avoid monolithic code and to aid with the understandability of the code we employ functions to break up the code. In lines 3-18 a function that handles the starting location is defined. Line 3 of the function declares the name of the function, in this case playStart, together with any inputs that are passed to the function. The first line of a function definition must begin with the def keyword and end with a colon. Input arguments are specified inside of brackets – note that if the function does not have any inputs then an empty of brackets are used. Lines 4-18 contain the body of the function – this is the code that runs when the function is called. Lines 4-7 output the narrative text using print statements. Line 8 prompts the user for their action and assigns the value to the response variable. If the player enters ‘w’, then “location1” is assigned to a local variable used to store the location. Otherwise, if the player enters ‘e’, then “location2” is stored in the local variable. In all other cases the local variable is assigned the “start” location. On line 18 the value stored in the local variable is returned as the result of the function.

Looking at line 22 of the code again, on this line the playStart function is called. Since this function has no inputs we do not pass any values, however we still need to include the empty pair of brackets. The result returned by the function is assigned to the location variable, which will in turn be used in the next iteration of the loop to determine the next function to call.

Coding the other locations

Once we have got the first location coded we follow a similar process to add the additional locations. A function needs to be defined for each of the additional locations and extra cases need to be added in the while loop.

location="start"

def playStart():
    print("You are on a quest to find the lost sippy cup.")
    print("The sippy cup is a priceless treasure that grants\nthe user eternal life")
    print("You come to a junction. You can either go (w)est or (e)ast.")
    print("What do you select?")
    response=input("> ")
    if (response=="w"):
        location="location1"
        print("You travel along the path to the west...")
    elif (response=="e"):
        location="location2"
        print("You travel along the path to the east.")
        print("The path leads gradually upwards until you finally reach a ledge.")
    else:
        location="start"
    return location


def playLocation1():
    print("You are in a large clearing.")
    print("In the centre of the clearing is a chest.")
    print("There is a path leading north.")
    print("To the south you can see a cliff face with a rope ladder leading to a ledge.")
    print("You can go (n)orth, (c)limb the ladder or attempt to (o)pen the chest.")
    print("Enter your selection.")
    response=input("> ")
    if (response=="o"):
        print("You are unable to open the chest.")
        print("It has a large padlock which cannot be broken.")
        location="location1"
    elif (response=="n"):
        print("You travel for several hours along a winding path.")
        location="location3"
    elif (response=="c"):
        print("You climb the rope ladder which sways dangerously as you make your way up.")
        print("At the top of a ladder you climb up to a ledge.")
        location="location2"
    else:
        location="location1"
    return location

def playLocation2():
    print("You stand atop a narrow ledge.")
    print("A rickety rope ladder dangles off the edge.")
    print("You see a pile of rubble at the far end of the ledge.")
    print("You can either (c)limb down the rope ladder or (s)earch the rubble.")
    response=input("> ")
    if (response=="c"):
        print("You carefully climb down the rope ladder.")
        location="location1"
    elif (response=="s"):
        print("You edge your way along the ledge, almost slipping a couple of times.")
        print("You search the pile of rubble, move large rocks until you discover a sword.")
        print("The sword is inscribed with runes and shimmers in the sun.")
        print("You carefully strap the sword to your back.")
        location="location2"
    else:
        location="location2"
    return location

def playLocation3():
    print("You reach what looks like a rudimentary camp site.")
    print("You notice a fire pit in the middle of the camp site.")
    print("Scattered around the fire pit are the many bones picked clean of flesh.")
    print("Ominously some of the bones look human like.")
    print("Just as you finish surveying the scene you here a roar.")
    print("Running towards you, wielding a large club is an Ogre.")
    print("You can either (f)lee to the south, (a)ttack the Ogre or try to (t)alk with the Ogre.")
    response=input("> ")
    if (response=="f"):
        print("You run away from the Ogre at full speed")
        print("The Ogre pursues for a while but eventually gives up.")
        print("You survive another day.")
        print("Once you know you are safe you continue your journey southward at a slower pace.")
        location="location1"
    elif (response=="a"):
        print("You fight valiantly with the Ogre.")
        print("You manage to inflict several telling blows against it but it fights on.")
        print("Having dodged several sweeping blows, the Ogre brings its club down upon you with a crash.")
        print("...")
        location="finish"
    elif (response=="t"):
        print("You attempt to make conversation with the Ogre but this only makes it more angry.")
        location="location3"
    else:
        location="location3"
    return location

    
while (location!="finish"):
    if (location=="start"):
        location=playStart()
    elif (location=="location1"):
        location=playLocation1()
    elif (location=="location2"):
        location=playLocation2()
    elif (location=="location3"):
        location=playLocation3()
    else:
        break

Download source code [Stage 2 code]

Limitations

If you download and run the code you may notice that collecting the sword in location 2 still does not allow you to kill the Ogre. We will address this issue in the next tutorial using a simple inventory solution.

Alice Tutorial: Indefinite Loops

The learning objectives for this tutorial are:

  • Students can design and implement programs using indefinite loops
  • Students can use the random number function in their programs
  • Students can design and use class level methods

In this activity you will design and develop a cat and mouse game. The cat chases the mouse at the same time the mouse moves in a random direction trying to evade the cat. When the cat finally catches the mouse it will enjoy a tasty meal. To assist in the development of the program we provide a number of suggested development steps.

Step 1: creating the world

Create a new world that includes a Cat object (Animals) and a Mouse object (Animals). Ensure that the mouse is initially a reasonable distance away from the cat and that it is facing away from the cat. You may wish to add some additional scenery to make the chase a little more interesting.

Cat and mouse game

Cat and mouse game

Step 2: creating Chase method

Create a new class method for the Cat class called chase. In this method the cat should turn to face the mouse, then move forward 1 metre. You may wish to add some animation to the cat’s movement, but you should do this after you have completed the other steps.

Step 3: creating run away method

Create a new class method for the Cat class called runAway. In this method the mouse should turn left or right a random amount (up to a maximum of ¼ of a revolution in either direction). You will need to use the random number function to determine the amount to turn. The mouse should then move forward 1 metre.

Step 4: Introducing a loop

In my first methodcreate a while loop. In the body of the while loop you must call the methods chase and runAway. You will need to design a test for the while loop, such that the loop continues until the cat is within a certain distance of the mouse (use an appropriate function to determine the distance between the cat and mouse).

STEP 5: catching the mouse

Create a new class method for the Cat class called eatMouse. The method should perform an appropriate action once the cat catches the mouse. Call the eatMouse method in my first method after the while loop.