Dragon Realm
Displaying the Game Results
Back to the game's source code:
20. print('You approach the cave...') 21. time.sleep(2)
We display some text to the player, and then call the time.sleep() function. Remember how in our call to randint(), the function randint() is inside the random module? In the Dragon Realm game, we also imported the time module. The time module has a function called sleep() that will pause the program for a few seconds. We pass the integer value 2 as an argument to the time.sleep() function to tell it to pause for exactly 2 seconds.
22 . print('It is dark and spooky...') 23. time.sleep(2)
Here we print some more text and wait again for another 2 seconds. These short pauses add suspense to the game, instead of displaying all the text all at once. In our jokes program, we called the input() function to wait until the player pressed the Enter key. Here, the player doesn't have to do anything at all except wait.
24. print('A large dragon jumps out in front of you! He opens his jaws and...') 25 . print() 26. time.sleep(2)
What happens next? And how does the program decide what happens?
Deciding Which Cave has the Friendly Dragon
28. friendlyCave = random.randint(1, 2)
Now we are going to have the program randomly chose which cave had the friendly dragon in it. Our call to the random.randint() function will return either the integer 1 or the integer 2, and store this value in a variable called friendlyCave.
30. if chosenCave == str(friendlyCave): 31. print('Gives you his treasure!')
Here we check if the integer of the cave we chose ('1' or '2') is equal to the cave randomly selected to have the friendly dragon. But wait, the value in chosenCave was a string (because input() returns strings) and the value in friendlyCave is an integer (because random.randint() returns integers). We can't compare strings and integers with the == sign, because they will always be different ('1' does not equal 1).
Comparing values of different data types with the == operator will always evaluate to False.
So we are passing friendlyCave to the str() function, which returns the string value of friendlyCave.
What the condition in this if statement is really comparing is the string in chosenCave and the string returned by the str() function. We could have also had this line instead:
if int(chosenCave) == friendlyCave:
Then the if statement's condition would compare the integer value returned by the int () function to the integer value in friendlyCave. The return value of the int() function is the integer form of the string stored in chosenCave.
If the if statement's condition evaluates to True, we tell the player they have won the treasure.
32. else: 33. print('Gobbles you down in one bite!')
Line 32 has a new keyword. The else keyword always comes after the if-block. The else-block that follows the else keyword executes if the condition in the if statement was False. Think of it as the program's way of saying, "If this condition is true then execute the if-block or else execute the else-block."
Remember to put the colon (the : sign) after the else keyword.
The Colon :
You may have noticed that we always place a colon at the end of if, else, while, and def statements. The colon marks the end of the statement, and tells us that the next line should be the beginning of a new block.
Where the Program Really Begins
35. playAgain = 'yes'
This is the first line that is not a def statement or inside a def-block. This line is where our program really begins. The previous def statements merely defined the functions, it did not run the code inside of the functions. Programs must always define functions before the function can be called. This is exactly like how variables must be defined with an assignment statement before the variable can be used in the program.
36. while playAgain == 'yes' or playAgain == 'y':
Here is the beginning of a while loop. We enter the loop if playAgain is equal to either 'yes' or 'y'. The first time we come to this while statement, we have just assigned the string value 'yes' to the playAgain variable. That means this condition will be True.
Calling the Functions in Our Program
38. displayIntro()
Here we call the displayIntro() function. This isn't a Python function, it is our function that we defined earlier in our program. When this function is called, the program execution jumps to the first line in the displayIntro() function on line 5. When all the lines in the function are done, the execution jumps back down to the line after this one.
40. caveNumber = chooseCave()
This line also calls a function that we created. Remember that the chooseCave() function lets the player type in the cave they choose to go into. When the return cave line in this function executes, the program execution jumps back down here, and the local variable cave's value is the return value of this function. The return value is stored in a new variable named caveNumber. Then the execution moves to the next line.
42. checkCave(caveNumber)
This line calls our checkCave() function with the argument of caveNumber's value. Not only does execution jump to line 20, but the value stored in caveNumber is copied to the parameter chosenCave inside the checkCave() function. This is the function that will display either 'Gives you his treasure!' or 'Gobbles you down in one bite!', depending on the cave the player chose to go in.
Asking the Player to Play Again
44. print('Do you want to play again? (yes or no)') 45. playAgain = input()
After the game has been played, the player is asked if they would like to play again. The variable playAgain stores the string that the user typed in. Then we reach the end of the while-block, so the program rechecks the while statement's condition: while playAgain == 'yes' or playAgain == 'y'
The difference is, now the value of playAgain is equal to whatever string the player typed in. If the player typed in the string 'yes' or 'y', then we would enter the loop again at line 38.
If the player typed in 'no' or 'n' or something silly like 'Abraham Lincoln', then the while statement's condition would be False, and we would go to the next line after the while-block. But since there are no more lines after the while-block, the program terminates.
But remember, the string 'YES' is different from the string 'yes'. If the player typed in the string 'YES', then the while statement's condition would evaluate to False and the program would still terminate.
We've just completed our second game! In our Dragon Realm game, we used a lot of what we learned in the "Guess the Number" game and picked up a few new tricks as well. If you didn't understand some of the concepts in this program, then read the summary at the end of this chapter, or go over each line of the source code again, or try changing the source code and see how the program changes. In the next chapter we won't create a game, but a computer program that will create secret codes out of ordinary messages and also decode the secret code back to the original message.
We went through the source code from top to bottom. If you would like to go through the source code in the order that the execution flows, then check out the online tracing web site for this program at the URL http://inventwithpython.com/traces/dragon.html.
Designing the Program
Dragon Realm was a pretty simple game. The other games in this book will be a bit more complicated. It sometimes helps to write down everything you want your game or program to do before you start writing code. This is called "designing the program."
For example, it may help to draw a flow chart. A flow chart is a picture that shows every possible action that can happen in our game, and in what order. Normally we would create a flow chart before writing our program, so that we remember to write code for each thing that happens in the game. Figure 6.2 is a flow chart for Dragon Realm.
To see what happens in the game, put your finger on the "Start" box and follow one arrow from the box to another box. Your finger is kind of like the program execution. Your finger will trace out a path from box to box, until finally your finger lands on the "End" box. As you can see, when you get to the "Check for friendly or hungry dragon" box, the program could either go to the "Player wins" box or the "Player loses" box. Either way, both paths will end up at the "Ask to play again" box, and from there the program will either end or show the introduction to the player again.
Summary
In the "Dragon Realm" game, we created our own functions that the main section of the program called. You can think of functions as mini-programs within our program. The code inside the function is run when our program calls that function. By breaking up our code into functions, we can organize our code into smaller and easier to understand sections. We can also run the same code by placing it inside of a function, instead of typing it out each time we want to run that code.
The inputs for functions are the arguments we pass when we make a function call. The function call itself evaluates to a value called the return value. The return value is the output of the function.
We also learned about variable scopes. Variables that are created inside of a function exist in the local scope, and variables created outside of all functions exist in the global scope. Code in the global scope can not make use of local variables. If a local variable has the same name as a variable in the global scope, Python considers it to be a separate variable and assigning new values to the local variable will not change the value in the global variable.
Variable scopes might seem complicated, but they are very useful for organizing functions as pieces of code that are separate from the rest of the function. Because each function has it's own local scope, we can be sure that the code in one function will not cause bugs in other functions.
All nontrivial programs use functions because they are so useful, including the rest of the games in this book. By understanding how functions work, we can save ourselves a lot of typing and make our programs easier to read later on.