What you need is a main game loop:
while game.is_running:
command = get_user_input()
user_do(command)
update_world()
This will repeat the three lines of code inside the while
loop for as long as game.is_running
is True
. First, you get the user input. Next, you act on it. Finally, you perform any other updates your game needs, like moving or spawning monsters. At this point, it loops back and asks the user for another command.
Update: here is a working example:
# In commands.py:
def bag():
print 'bag'
def other():
print 'other'
def unrecognized():
print 'unknown command'
# In main.py:
import commands
def user_input():
print 'a question'
return raw_input('>')
def user_do(command):
# get the matching command out of commands, or pass back
# the unrecognized function if it's not found
action = getattr(commands, command, commands.unrecognized)
action()
is_running = True
while is_running:
command = user_input()
if command == 'quit':
is_running = False
else:
user_do(command)
In this example, I've cheated and am relying on the user input commands being identical to the name of the functions to be called. In user_do
, the getattr
call compares the string the user has input with the contents of the command
module, returning the function of the same name if one exists, or the fallback function unrecognized
if it doesn't. action
will now either hold the command function or unrecognized
.
If you don't want to have your user commands so tightly bound to the actual functions themselves, you can use a dict
as a branching construct (or dispatch) instead of having a lot of if / elif / else
statements:
# Modified main.py
import commands
COMMAND_DISPATCH = {
'bag': commands.bag,
'sack': commands.bag,
'other': commands.other,
# ...
}
# ...
def user_do(command):
action = COMMAND_DISPATCH.get(command, commands.unrecognized)
action()
In this example, rather than look up the functions in the commands
module, we look them up in COMMAND_DISPATCH
instead.
One more bit of advice: pretty soon you'll want to look at parsing the user input into more than just a single command. For this example, let's assume you want to be able to accept input of the form "command ... ". You can extend the user_input
function to take care of this:
def user_input():
print 'a question'
user_input = raw_input('>').split(' ')
command = user_input[0]
arguments = user_input[1:]
return command, arguments
So if you enter 'foo bar baz', this would return the tuple ('foo', ['bar', 'baz'])
. Next we update the main loop to deal with the arguments.
while is_running:
# use tuple unpacking to split into command, argument pairs
command, arguments = user_input()
if command == 'quit':
is_running = False
else:
user_do(command, arguments)
Then make sure we pass them to the command:
def user_do(command, arguments):
action = COMMAND_DISPATCH.get(command, commands.unrecognized)
action(arguments)
And finally, we modify the commands to accept and handle the arguments:
def bag(arguments):
for argument in arguments:
print 'bagged ', argument
For a text adventure, you'll want a more substantial parser, something that deals with command object
, command object preposition subject
, and possibly even command adjective object ...
.