To make such a game I would recommend using a (decision) state-machine. If the game is in a certain state, the player is asked the corresponding question and depending on the answer the game is moved to an other state. Each state should be implemented independently from the others, i.e. avoid deeply nested if/else constructs, this avoids errors and helps you to stay on top of things. You can also visualize/draw the game decision plan as a graph, where each node represents a state (or decision to be made) and each decision connects the node to an other state.
For your concrete example, you also need to keep track of what the player has collected so far, which is essentially an other state-system.
To implement such a state-based-game you can (ab-)use the python concept of generators. A generator is basically an object that returns 'items' with yield
when queried with next()
. A generator can provide a finite or an infinite amount of 'items', it can also return 'items' from an other generator with yield from
.
Here an example implementation of your game:
Be aware that this code works only with python3! It should be possible to translate it into python2 (perhaps even automatically), but I feel no strong urge to do so ATM ;)
import random
import collections
def main(backpack):
print("You need to build a fire. the recipe is 5 stick and 3 coal.")
print("You have the following items in your backpack:")
for k,v in backpack.items():
print(' % 3d %s' % (v,k))
#TODO: add check if we have collected enough here
yield from choice1(backpack)
# tree or stone
def choice1(backpack):
answer = input("There are trees to your left and rocks to your right. Which way will you go?")
if answer.lower() in ('l', 'left'):
yield from choice2a(backpack)
elif answer.lower() in ('r', 'right'):
yield from choice2b(backpack)
else:
print('I could not understand you. Answer with either "left" or "right".')
yield from choice1(backpack)
# punch or not
def choice2a(backpack):
answer = input("You go to the tree. Would you like to punch it?")
if answer.lower() in ('y', "yes"):
R = random.randint(1,11)
print( "You punched the tree " + str(R) + " times.")
if R <= 5:
print("It did not fall down")
else:
R2 = random.randint(0, 5)
print("It fell down. It dropped " + str(R2) + " sticks.")
backpack['stick'] += R2
yield from choice2a(backpack)
elif answer.lower() in ('n', "no"):
yield from main(backpack)
else:
print('I could not understand you. Answer with either "yes" or "no".')
yield from choice2a(backpack)
# pick up or not
def choice2b(backpack):
answer = input("You go to the rocks. Would you like to pick up the coal in them?")
# TODO: implement this
yield main(backpack)
if __name__ == '__main__':
backpack=collections.defaultdict(int)
while True:
next(main(backpack))
Each of the functions is a generator-function, i.e. a function that returns a generator. Each of them represents a game-state that requires a decision. The player-state (i.e. what the player has collected so far) is passed along as backpack
which is a dictionary that contains the amount per item.
(yield from xyz()
could be interpreted as a kind of goto
command.)