Python 3 adventure game in modules I have been learning Python 3 for about a year now. I have been looking for a project to do instead of just going through tutorials and completing some Code Wars challenges. One website suggested that a text game would be something good to work on. So, I tried to come up with a story line and did a basic map design. But, as soon as I started coding I realized that I had better just try something simple first to learn how to break things up so the game could be manageable as it got bigger. 

The three small files listed below are what I have so far. You should be able to just copy and paste the code, and then run it. (To run through all the possibilities/options you want to try "N", "S", "E", "e" and then "W".)

I quickly found that using modules is essential. For this simple project I am using a separate file for storage of health and wealth. 

I have tried to use descriptive names for variables and functions. I think the "page_01.py" should have a more descriptive name. But, this first little project is basically an experiment for learning. I would also use comments for a bigger game. For now, I think the variable names and function names will allow you to easily figure out what is going on in the code listed below.

Here is main.py

import page_01
import storage

page_01.instructions()
print("You have " + str(storage.health) + " health points and " + str(storage.wealth) + " coins.")

action = input("What do you want to do now?")
page_01.player_move(action) 


Here is page_01.py

import storage

def instructions():
  print("You can move N, S, E or W.")

def ask_player_for_move():
  react = input("\nWhat is your next move?")
  player_move(react)

def player_update():
  print("\nYour health is now: " + str(storage.health))
  print("You now have " + str(storage.wealth) + " coins.\n")

def player_move(action):
  if action == "N":
    print("You stepped on a bear trap.")
    storage.health -= 10
    player_update()    
    ask_player_for_move()
  elif action == "S":
    print("You tripped over a pengiun!")
    print("But, you found a small bag of 15 coins.")
    storage.health -= 3
    storage.wealth += 15
    player_update()
    ask_player_for_move()
  elif action == "E":
    print("Err...I wouldn't go that way if I were you!")
    ask_player_for_move()
  elif action == "W":
    print("You ride off into the sunset")
    player_update()
  else:
    print("That is not a valid entry.")
    ask_player_for_move()


Here is storage.py

health = 100

wealth = 10
Style

There is an official standard Python style guide called PEP 8. This is highly recommended reading. It gives guidelines to help writing code that is both readable and consistent. The Python community tries to follow these guidelines, more or less strictly (a key aspect of PEP 8 is that it provides guidelines and not strict rules to follow blindly).

It deals with various aspects of the code style: naming conventions, indentation convention, etc.

You'll find various tools to try to check whether your code is PEP 8 compliant and if is it not, to try and fix this:


pycodestyle package (formerly known as pep8) to check you code
pep8online to check your code with an online tool
autopep8 package to fix your code automatically
Also, this is also checked by various linters: pylint, pyflakes, flake8, etc.


In your case, the major point is that indentation should be 4 space. Also, you should not have trailing whitespaces.

Modules

Splitting the code into small modules can be a good idea. However, I find page_01 to be a pretty weird name. Also, the way the code is splitted in different modules does not seem to be perfect to me. The way you use storage suggests that is should probably be a data structure (a class?).

For the time being, let's move everything back to a single file:

health = 100
wealth = 10


def instructions():
    print("You can move N, S, E or W.")


def ask_player_for_move():
    react = input("\nWhat is your next move?")
    player_move(react)


def player_update():
    print("\nYour health is now: " + str(health))
    print("You now have " + str(wealth) + " coins.\n")


def player_move(action):
    if action == "N":
        print("You stepped on a bear trap.")
        health -= 10
        player_update()
        ask_player_for_move()
    elif action == "S":
        print("You tripped over a pengiun!")
        print("But, you found a small bag of 15 coins.")
        health -= 3
        wealth += 15
        player_update()
        ask_player_for_move()
    elif action == "E":
        print("Err...I wouldn't go that way if I were you!")
        ask_player_for_move()
    elif action == "W":
        print("You ride off into the sunset")
        player_update()
    else:
        print("That is not a valid entry.")
        ask_player_for_move()


instructions()
print("You have " + str(health) + " health points and " + str(wealth) + " coins.")

action = input("What do you want to do now?")
player_move(action)


Functions

player_update does not update the player, maybe print_player would be more relevant.

Similarly, I'd expect ask_player_for_move to be a function returning the move asked to the user.

In both cases, it seems like the functions could be used in the "main" part instead of duplicating the code.

health = 100
wealth = 10


def show_intructions():
    print("You can move N, S, E or W.")


def ask_player_for_move():
    react = input("\nWhat is your next move?")
    player_move(react)


def print_player():
    print("\nYour health is now: " + str(health))
    print("You now have " + str(wealth) + " coins.\n")


def player_move(action):
    global health
    global wealth
    if action == "N":
        print("You stepped on a bear trap.")
        health -= 10
        print_player()
        ask_player_for_move()
    elif action == "S":
        print("You tripped over a pengiun!")
        print("But, you found a small bag of 15 coins.")
        health -= 3
        wealth += 15
        print_player()
        ask_player_for_move()
    elif action == "E":
        print("Err...I wouldn't go that way if I were you!")
        ask_player_for_move()
    elif action == "W":
        print("You ride off into the sunset")
        print_player()
    else:
        print("That is not a valid entry.")
        ask_player_for_move()


show_intructions()
print_player()
ask_player_for_move()


Hidden recursion

Your game loop relies on a hidden recursion: player_move calls ask_player_for_move which calls player_move. This makes things heard to follow but also will add another level of function calls in the stack. This can be an issue if you need a backtrace because you'll get something like:

  File "new_main.py", line 37, in player_move
    ask_player_for_move()
  File "new_main.py", line 12, in ask_player_for_move
    player_move(react)
  File "new_main.py", line 37, in player_move
    ask_player_for_move()
  File "new_main.py", line 12, in ask_player_for_move
    player_move(react)
  File "new_main.py", line 37, in player_move
    ask_player_for_move()
  File "new_main.py", line 12, in ask_player_for_move
    player_move(react)
  File "new_main.py", line 37, in player_move
    ask_player_for_move()
  File "new_main.py", line 12, in ask_player_for_move
    player_move(react)
  File "new_main.py", line 37, in player_move
    ask_player_for_move()
  File "new_main.py", line 12, in ask_player_for_move
    player_move(react)
  File "new_main.py", line 37, in player_move
    ask_player_for_move()
  File "new_main.py", line 12, in ask_player_for_move
    player_move(react)
  File "new_main.py", line 43, in player_move
    ask_player_for_move()
  File "new_main.py", line 12, in ask_player_for_move
    player_move(react)
  File "new_main.py", line 43, in player_move
    ask_player_for_move()
  File "new_main.py", line 11, in ask_player_for_move
    react = input("\nWhat is your next move?")
KeyboardInterrupt


but the other issue is that you could end up reaching the recursion limit.

You could write something like:

health = 100
wealth = 10
finished = False

def show_intructions():
    print("You can move N, S, E or W.")


def ask_player_for_move():
    return input("\nWhat is your next move?")


def print_player():
    print("\nYour health is now: " + str(health))
    print("You now have " + str(wealth) + " coins.\n")


def player_move(action):
    global health
    global wealth
    global finished
    if action == "N":
        print("You stepped on a bear trap.")
        health -= 10
        print_player()
    elif action == "S":
        print("You tripped over a pengiun!")
        print("But, you found a small bag of 15 coins.")
        health -= 3
        wealth += 15
        print_player()
    elif action == "E":
        print("Err...I wouldn't go that way if I were you!")
    elif action == "W":
        print("You ride off into the sunset")
        print_player()
        finished = True
    else:
        print("That is not a valid entry.")

def game():
    global finished
    show_intructions()
    print_player()
    while not finished:
        action = ask_player_for_move()
        player_move(action)

game()


Then you could move the call of game() behind an if __name__ == "__main__": guard.