How to use commands again without copy and pasting them? - python

I don't really know how to explain this exactly.. But I'm making a text adventure for learning the basics. Now I want to make a gold and money system, I am using def... things for different levels and such. but in every prompt I have to put in if the user types gold, or inv it shows the inventory and then go back to the def where it was.. which I find irritating to do every time. And I forget it too at some periods. I want to do it as default in the prompt.
I have a def prompt(): that is this easy code:
def prompt():
x = input('Type a command: ')
return x
and if I put it there it just ends the code. I have to do this in every prompt:
def AlleenThuis():
command = prompt()
if command == '1':
print()
elif command == '2':
print()
elif command == '3':
print()
elif command == '4':
print()
elif command == 'geld': #Actions start here
print('\n\tYou have ' + str(gold) + ' euro. RICH BOY BRO!.\n')
print()
return AlleenThuis()
elif command == 'inv':
if not inv:
print("\n\tYou don't have any items..\n")
return AlleenThuis()
else: #The else has to stay in this place because it's part of the 'if not inv:' guys.
print('\n\t' + str(inv) + '\n')
return AlleenThuis()
#Actions end here
So if there's any way to just implement it so that I don't have to put it in again every time that would be awesome!
Thanks.
EDIT: It looks like you guys aren't understanding what I'm saying, so I have 2 images.
So..
http://i.imgur.com/GLArsyu.png (I can't post pictures yet =[ )
As you can see in this picture, I have included gold and inv.
But in http://i.imgur.com/V3ZhJ36.png I have also done that, so I have coded that in the code again, that is what I Don't want!
I just want to have that in the code 1 time, and let the gold and inventory show all the time when the player enters the commands for them!

On a more fundamental level, the object-oriented paradigm elegantly solves the problem of repetitive code like this:
global gold = 0
def cave():
print "You are in a cave."
print "You have %i gold." % gold
direction = input()
if direction = 'N':
stream()
elif direction == 'S':
house()
elif direction == 'W':
mountain()
elif direction == 'directions':
print "You can go North, West, or South."
else:
print "You cannot go there."
def stream():
print "A small stream flows out of the building and down a gully."
print "You have %i gold." % gold
direction = input()
if direction == 'N':
tree()
elif direction == 'S':
cave()
elif direction == 'directions':
print "You can go North or South."
else:
print "You cannot go there."
def main():
cave()
by turning it into something like this:
class Location:
map = { 'cave': {
'description': 'You are in a cave.',
'directions': { 'N': 'stream', 'S': 'house', 'W': 'mountain' } },
'stream': {
'description':
'A small stream flows out the building and down a gully.',
'directions': { 'N': 'tree', 'S': 'cave' } } #...
}
def __init__ (self):
self.location = 'cave'
def enter (self, direction):
self.location = self.map[self.location]["directions"][direction]
print self.map[self.location]["description"]
def directions(self):
return self.map[self.location]["directions"].keys()
def readable(self, dirs):
readable = { 'S': 'South', 'N': 'North', 'W': 'West', 'E': 'East' }
return [readable[d] for d in dirs]
class Inventory:
def __init__ (self):
self.inventory = { 'gold': 0 }
def query (self):
print "You have %i gold." % self.inventory['gold']
def main:
loc = Location()
inv = Inventory()
while True:
directions = loc.directions()
action = raw_input()
if action in directions:
loc.enter(action)
inv.query()
elif action == 'directions':
where = loc.readable(directions)
print "You can go " + ", ".join(where[:-1])\
+ ", or " + where[-1]
else:
print "You cannot go there."
You will notice that the more modular code is also easier to extend. For example, the inventory can now hold more things than gold, and it's easy to add new commands to query for weapons, potions, etc. Furthermore, it somewhat separates the code from the data, making it less cumbersome and error-prone to add new locations and actions.
Next up, define class Object with subclasses for animate objects, objects you can pick up, immobile objects, etc; and populate the locations with instances of these. Different subclasses can have different interactions defined, and inherit from more basic superclasses which implement fundamentals like take, drop, kill, etc.
What to map into objects is a broad topic, but a few simple guidelines would be to isolate and encapsulate unrelated code into their own classes, and make them as decoupled as possible (code implementing "location" should not need to know pretty much anything about code in "inventory", and vice versa).

Your code for this has some serious structural problems. If I understand correctly, you're trying to accept repeated commands and execute some code to make them function the way you intend.
The problem is that your function to run the game is recursive, so every time you execute a command other than 1, 2, 3, or 4, you're calling your function again without returning from the first one. Eventually, if you enter enough commands, you'll get an error saying that you're recursing too deeply and the game will error out.
What you want is something more like this:
def prompt():
x = input('Type a command: ')
return x
def ProcessAction(command):
if command == '1':
print()
elif command == '2':
print()
elif command == '3':
print()
elif command == '4':
print()
elif command == 'geld': #Actions start here
print('\n\tYou have ' + str(gold) + ' euro. RICH BOY BRO!.\n')
print()
elif command == 'inv':
if not inv:
print("\n\tYou don't have any items..\n")
else:
print('\n\t' + str(inv) + '\n')
#Actions end here
curr_command = None
while curr_command not in ("1", "2", "3", "4"):
curr_command = prompt()
ProcessAction(curr_command)
What this will do is keep asking for new commands and processing them until one of the commands that exits the game is entered.
Edit: From your comment below, it sounds like you're trying to figure out how to display gold and inventory every time a command is entered without requiring a special command to do it. If this is what you're after, you can add print statements to the while loop above to ensure that it's printed before every prompt. In that case, the while loop might look like:
while curr_command not in ("1", "2", "3", "4"):
print('\n\tYou have ' + str(gold) + ' euro. RICH BOY BRO!.\n')
if not inv:
print("\n\tYou don't have any items..\n")
else:
print('\n\t' + str(inv) + '\n')
curr_command = prompt()
ProcessAction(curr_command)
Hope that gets closer to what you're after.
Edit 2: Ok, after reading the full code for your game, I think you might want to consider reorganizing the entire thing. Think about what you want the game to be: the player enters a series of commands and each command does two things, it changes the game's state and it prints out a response based on both the current state and the new state.
So, you should think about processing your commands with a loop like I described. Then, fold all those different functions into ONE ProcessAction(command) function that figures out from the game's state (which you store in variables) what to print out and how to change the state.
If it's a game where you're going room to room, for example, you might keep a global variable room that defines where you are. Your ProcessAction function then follows logic that says "If I'm in room A and the character types this thing then print out B and change room to C, and sets gold to 0."
To make this work well, you'll have to step back and think about the overall "story" of your game, how to store the state in various variables, and how to make your ONE ProcessAction function handle all the possible states and commands that can be issued.
Doing this puts you on the path of developing what's called a "state machine," where you have a simple, general function that looks at a data structure (probably some nested dicts) that you fill up with what each command does when your game is in each state and where to go next, as well as what to print out.
This Wikipedia article describes the concept of a state machine. How you implement it in Python is up to you. I can tell you that if you're careful you should be able to do this without repeating any code. http://en.wikipedia.org/wiki/State_machine
Another edit: Answering a question you placed in the comments below, if you think you have to print out, for example, the value of a player's gold in multiple places, you can do something like this:
def print_gold(gold_value):
print('\n\tYou have ' + str(gold_value) + ' euro. RICH BOY BRO!.\n')
print()
then use print_gold(gold) in place of those print statements whenever you need to do that. However, I think you may want to take a step back and think about rewriting the whole thing with some of the thoughts I've offered before you tackle that problem.

My earlier answer is long and addresses a number of problems in the OP's code, but he's asking about one specific thing, so I thought I'd separate out that answer here.
If you have some code you'd like to repeat multiple times, you might be tempted to copy and paste it around in your code In your case, that would be something like:
print('\n\tYou have ' + str(gold) + ' euro. RICH BOY BRO!.\n')
print()
Wrapping that in a function will allow you to execute that same code anytime you need to do that thing, without copying and pasting. You're already defining functions, so you seem to have the concept down, but this wrapped in a function might look like:
def print_gold(gold_value):
print('\n\tYou have ' + str(gold_value) + ' euro. RICH BOY BRO!.\n')
print()
With this function defined, anytime you place print_gold(gold) in your code, it'll pass the value of gold into that function as the variable gold_value and print it out as you've specified.
So, if for some reason you had code that looked like this:
print('\n\tYou have ' + str(gold) + ' euro. RICH BOY BRO!.\n')
print()
print('\n\tYou have ' + str(gold) + ' euro. RICH BOY BRO!.\n')
print()
print('\n\tYou have ' + str(gold) + ' euro. RICH BOY BRO!.\n')
print()
you could turn this into:
def print_gold(gold_value):
print('\n\tYou have ' + str(gold_value) + ' euro. RICH BOY BRO!.\n')
print()
... somewhere else in your code ...
print_gold(gold)
print_gold(gold)
print_gold(gold)
Those three lines are function calls, which tell Python to execute the function you've defined with def.

I am assuming you are currently pasting something into this prompt everytime you want to run your Python program, and your question is about how to avoid that:
The answer to this problem is generally to save your program's code in a whatever.py file and run that file... either by doubleclick or through the terminal. The exact instructions depend on your operating system etc.

If I understood correctly the latest edit to your question, then you might want something like:
def get_gold_or_inv(command):
if command == 'geld': #Actions start here
print('\n\tYou have ' + str(gold) + ' euro. RICH BOY BRO!.\n')
print()
elif command == 'inv':
if not inv:
print("\n\tYou don't have any items..\n")
else:
print('\n\t' + str(inv) + '\n')
while True:
command = prompt()
if command == '1':
print()
elif command == '2':
print()
elif command == '3':
print()
elif command == '4':
print()
get_gold_or_inv(command)

Are you trying to say that you want this to run in an infinite loop until quit?
You can do that either by encapsulating the entire function block with a while True: or just by calling AlleenThuis() after the ifs and elifs. I took the liberty to rewrite your implementation using the first option below.
def AlleenThuis():
while True:
command = prompt()
if command == '1':
print()
elif command == '2':
print()
elif command == '3':
print()
elif command == '4':
print()
elif command == 'geld': #Actions start here
print('\n\tYou have ' + str(gold) + ' euro. RICH BOY BRO!.\n')
print()
elif command == 'inv':
if not inv:
print("\n\tYou don't have any items..\n")
else:
print('\n\t' + str(inv) + '\n')
else:
print("Invalid command")
Hope I didn't misunderstand you.
EDIT:
def action(cmd):
if cmd == 'geld':
print('\n\tYou have ' + str(gold) + ' euro. RICH BOY BRO!.\n')
print()
elif cmd == 'inv':
if not inv:
print("\n\tYou don't have any items..\n")
else:
print('\n\t' + str(inv) + '\n')
else:
# If the command was not found
return False
# If the command was found and the else statement was not run.
return True
Then just run this at the start of every scenario if action(command): return ScenarioName().
Hope that helps!

Related

Why does it give me IndexError: list index out of range for this piece of code? I double-checked

Help I tried running this piece of code yet it keeps saying list index out of range. Whenever I go to the last list item it just gives that error. Everything else works fine. What am I doing wrong and how do I fix it?
'
conversations = ['favouriteFood', 'anyPets', 'idealGift', 'favouriteShow']
def conversationStarter():
if conversations[1] == 'favouriteFood':
conversations.remove('favouriteFood')
answer1 = input('What is your favourite food? My favourite food is codewords.')
answer2 = input('Wow! I love eating ' + answer1.lower() + ' too! What is your second favourite?')
print('Really? I never really learnt to like ' + answer2.lower() + ', but I will have a go!')
conversationStarter()
elif conversations[1] == 'anyPets':
conversations.remove('anyPets')
answer = input('Hey hey hey! Do you have any pets? I do, of course, a pet python! Do you have any pets?')
if answer == 'yes':
answer = input('Really! What kind of pet do you own?')
print('Wow! I would love to have a ' + answer.lower() + ' someday!')
conversationStarter()
if answer == 'no':
print('Oh. OK! However, I highly recommend a pet, they make you happier!')
conversationStarter()
elif conversations[1] == 'idealGift':
conversations.remove('idealGift')
answer = input('What is your most ideal gift for the New Year?')
print('WHAT? You think of a ' + answer.lower() + ' as an ideal gift? I would rather like a Python code.')
conversationStarter()
elif conversations[1] == 'favouriteShow':
conversations.remove('favouriteShow')
answer = input('What is your favourite movie or TV film?')
print('Wait what? I never heard of ' + answer + '. I should watch it! I love watching Python tutorials though.')
conversationStarter()
def greetingMenu():
print('Welcome to the NewYearPyChat.home file. Do you want a conversation?')
answer = input("Please answer 'yes' or 'no'.")
if answer == 'yes':
print('Amazing! Let us start chatting then!')
conversationStarter()
elif answer == 'no':
print('Oh. Try again next time.')
greetingMenu()
else:
print('What are you saying?')
greetingMenu()
greetingMenu()
print('And by the way, my name is PyChat if you have not guessed already.')
I tried looking at the piece of code and fixing bits and deleting nearly all of it but it still doesn't work.
You are referencing the second element of the array in each of your if-elif checks. Change each instance of conversations[1] to conversations[0] and you should see the results you're looking for.

Python fill-in-the-blanks code

I am a programming beginner and I am trying to build a fill-in-the-blank quiz. I am almost finished but I am stuck on 2 problems I am not able to solve, whatever I do. I would really appreciate your help with this. Thank you for helping me with this!
If you try to run the code and play the game:
1) It prints the quiz according to the difficulty(easy-insane) and quiz you want to play(apple, bond and programming quiz) which is great but afterwards it prompts you to choose difficulty again (the player_level() function keeps going even though the player/user has already chosen the difficulty level. I don't really understand why it does it? The player_level() procedure seems perfectly okay and logical to me.
2) The errors:
a) local variable blanks_index referenced before assignment
b) global name list_of_answers is not defined.
I know that it is related to the initialize_game() function but I don't know how to change the code so it refers all the variables (blanks_index, answers_index, player_lives) correctly.
It could be solved by creating global variables(I guess) but that is not a good practice so I am trying to avoid it. Formerly, the whole function initialise_game() and play_game() were one function, but as there are over 25 lines of code in one function, it is not a good practice as it is long and messy and I know that I can separate it but I don't know how.
Here is the code:
"""3 diffferent quizzes : Apple quiz, James Bond quiz, Programming quiz"""
"""Quiz and answers about Apple"""
Apple_quiz = ("The most valuable company in terms of market cap in 2016 is, ___1___."
"It was founded in ___2___. Its flagship product is called ___3___."
"___1___ has many competitors, the biggest rival is ___4___,founded by"
" nobody but the richest man on the planet,___5___ ___6___.")
list_of_answers_Apple = ["Apple", "1976", "Iphone", "Microsoft", "Bill", "Gates"]
"""Quiz and answers about Bond"""
Bond_quiz = ("James Bond is agent ___1___. He serves his country,___2___ ___3___"
" against its enemies. His car of choice is usually ___4___ ___5___."
" His favorite drink is ___6___.")
list_of_answers_Bond = ["007", "United", "Kingdom", "Aston", "Martin", "Martini"]
"""Quiz and answers about programming basics"""
Programming_quiz = ("___1___ are created with the def keyword. ___1___ are also called ___2___"
" You specify the inputs a ___1___ take by adding ___3___ separated by commas"
" between the parentheses. ___3___ can be standard data types such as string, number"
" ,dictionary, tuple, and ___4___ or can be more complicated such as ___5___"
" and ___6___ functions.")
list_of_answers_Programming = ["Functions", "procedures", "arguments", "lists", "objects", "lambda"]
blank_space = ["___1___", "___2___", "___3___", "___4___", "___5___", "___6___]"]
#List of levels with corresponding lives/guesses that player can have
quiz_list = ["Apple", "Bond", "Programming"]
level_list = ["easy", "medium", "hard", "superhard", "insane"]
lives_easy = 5
lives_medium = 4
lives_hard = 3
lives_superhard = 2
lives_insane = 1
def choose_quiz():
""" Prompts player to pick a type of quiz and loads the quiz """
#Input = player_quiz (raw input from player)
#Output = loaded quiz, player chose
while True:
player_quiz = raw_input("Please, select a quiz you want to play: "
"(Apple, Bond or Programming): ")
if player_quiz == "Apple":
return Apple_quiz
elif player_quiz == "Bond":
return Bond_quiz
elif player_quiz == "Programming":
return Programming_quiz
else:
print "We don't have such quiz, pick again!"
def answers_for_quiz():
""" Loads appropiate answers to the quiz that player has chosen"""
#Input = player quiz (raw input from player)
#Output = loaded quiz answers from the quiz player chose
player_quiz_pick = choose_quiz()
if player_quiz_pick == Apple_quiz:
return list_of_answers_Apple
elif player_quiz_pick == Bond_quiz:
return list_of_answers_Bond
elif player_quiz_pick == Programming_quiz:
return list_of_answers_Programming
def player_level():
""" Loads a difficulty that player chooses """
#Input = player_level_input (raw input of player choosing a difficulty)
#Output = corresponding number of lives:
#Easy = 5 lives, Medium = 4 lives
#Hard = 3 lives, Superhard = 2 lives
#Insane = 1 life
while True:
player_level_input = raw_input("Please type in a difficulty level: "
"(easy, medium, hard, superhard, insane): ")
if player_level_input == "easy":
return lives_easy #Easy = 5 lives
elif player_level_input == "medium":
return lives_medium #Medium = 4 lives
elif player_level_input == "hard":
return lives_hard #Hard = 3 lives
elif player_level_input == "superhard":
return lives_superhard #Superhard = 2 lives
elif player_level_input == "insane":
return lives_insane #Insane = 1 life
else:
print "We do not have such difficulty! Pick again!"
def correct_answer(player_answer, list_of_answers, answers_index):
""" Checks, whether the the answer from player matches with the answer list. """
#Input: player_answer (raw input that player enters in order to fill in the blank)
#Output: "Right answer!" or "Wrong! Try again!" this output will be later used in the game
if player_answer == list_of_answers[answers_index]:
return "Right answer!"
return "Wrong! Try again!"
def initialize_game():
"""Functions that sets up a game so we can play it """
player_quiz_pick, player_level_pick, list_of_answers = choose_quiz(), player_level(), answers_for_quiz()
print player_quiz_pick
print "\nYou will get maximum " + str(player_level_pick) + " guesses for this game. Good luck.\n"
blanks_index, answers_index, player_lives = 0, 0, 0
#for elements in blank_space:
while blanks_index < len(blank_space):
player_answer = raw_input("Please type in your answer for " + blank_space[blanks_index] + ": ")
if correct_answer(player_answer,list_of_answers,answers_index) == "Right answer!":
print "Correct answer! Keep going!\n"
player_quiz_pick = player_quiz_pick.replace(blank_space[blanks_index],player_answer)
answers_index += 1
blanks_index += 1
print player_quiz_pick
if blanks_index == len(blank_space):
print "Congratulations! You nailed it! You are the winner!"
else:
player_level_pick -= 1
if player_level_pick == 0:
print "Game over! Maybe next time!"
break
else:
print "One life less, that sucks! Have another shot!"
print "You have " + str(player_level_pick) + " guesses left."
initialize_game()
Your main problem is that you keep calling the same functions over and over again and do not save the input into variables. Here are some tips about your code and questions:
You are not doing anything with your player_level() method call, so the player doesn't actually chooses a level in a way that affects the game. You should change the function call, so the returned value will be stored.
//the call to the method:
player_level_pick = player_level()
Afterwards, you keep calling the player_level() method, and not using the actual answer that the user supplied. Change all player_level() appearences to player_level_pick - the variable you use to save the answer (as I showed above). Same goes to all other unneeded function calls such as choose_level().
You should initialize number_of_guesses, player_lives, list_of_answers, and other vars to a matching value to player_level_pick as well, so it will hold the right value according to the level. Likewise, you should change this line:
# the line that checks if game is over
# change from:
if number_of_guesses == player_lives:
# to :
if number_of_guesses == 0:
In order to return multiple values, you have to use tuples. Using multiple return statements one after the other does not work anywhere.
so, instead of:
return list_of_answers
return number_of_guesses
return blanks_index
return answers_index
return player_lives
you should use tuples, and unpack them properly:
# the return statement:
return (list_of_answers, number_of_guesses, blanks_index, answers_index, player_lives)
# and the unpacking in the calling function:
list_of_answers, number_of_guesses, blanks_index, answers_index, player_lives = initialize_game()
this way, all of the returned values go into the wanted variables in the calling function. this way, you need to call the initialize_game() from play_game(). it will be the efficient way for you.
Just saying it again, as I said in the end of (4) - you should unit initialize_game() and play_game() into a single function (because a lot of data is the same needed data), or just call initialize_game() from play_game().
Better practice then using this recursivly: return choose_level(), you should use a while True: loop, and just brake when you get a proper answer.

Python: Mad Libs

Hi I have this project of Mad libs but I don´t know how to make a function that ask the user what level of difficulty between easy, medium or hard they want, and depending on their answer redirect them to the desired level of mad libs. This is what I have so far. Thanks.
parts_of_speech_words = ["VERB","PLACE","ADJECTIVE","NOUN","PLURALNOUN","ADVERB"]
level_easy = """I __VERB__ to go to the __PLACE__
but I don't go in the __ADJECTIVE__
I am __ADJECTIVE__ of the __NOUN__
and getting __VERB__ by a __NOUN__."""
level_medium = """Begging to hear __NOUN__
My ears remain __ADJECTIVE__
__NOUN__ for signs
my __NOUN__ remain __VERB__
Yet __NOUN__still VERB."""
level_hard = """I __VERB__ you without __NOUN__
how, or when, or from where,
I love you __ADVERB__,
without __PLURALNOUN__ or pride;
So I love you because I know
no other way that this:
Where I does not VERB, nor you,
so close that your NOUN
on my chest is my hand,
so close that your NOUN close
as I fall ADJECTIVE."""
greeting = raw_input ("Welcome to mad libs, What's your name? ")
prompt = raw_input ("Select your level: easy, medium or hard: ")
def entry_level_prompt (variable_level):
easy = level_easy
medium = level_medium
hard = level_hard
for e in variable_level:
if prompt == easy:
return level_easy
print level_easy
if prompt == medium:
return level_medium
print level_medium
if prompt == hard:
return level_hard
print lever_hard
print "Ok %s you chose the %s level" % (greeting , prompt)
print entry_level_prompt (variable_level)
def parts_of_speech (words_string, list_of_part_of_speech):
for pos in list_of_part_of_speech:
if pos in words_string:
return pos
return None
def play_mad_libs (split_string, list_of_part_of_speech):
replaced = []
split_string = split_string.split ()
for words_string in split_string:
replacement = parts_of_speech (words_string, list_of_part_of_speech)
if replacement != None:
user_input = raw_input ("Type in a: " + replacement + " ")
words_string = words_string.replace (replacement, user_input)
replaced.append(words_string)
else:
replaced.append(words_string)
replaced = " ".join(replaced)
return replaced
print play_mad_libs (entry_level_prompt, parts_of_speech_words)
You have a bug in your code. You are calling entry_level_prompt(variable_level) but variable_level does not exist outside of the method scope.
To control the difficulty, you can create a method called get_difficulty()
def get_difficulty():
choice = ""
while choice not in ('easy', 'medium', 'hard'):
choice = raw_input("choose your difficulty: ")
if choice == "easy":
return level_easy
elif choice == "medium":
return level_medium
elif choice == "hard":
return level_hard
else:
print("Invalid choice...")
You've confused the selector -- "easy", "medium", or "hard" -- with the variable you want to return -- level_easy, level_medium, or level_hard. You cannot use the variable prompt for both purposes at the same time.
I recommend that you keep variable prompt as you started: it holds the user input. Then, simply test it and return the needed script:
if prompt == "easy":
return level_easy
elif prompt == "medium"
return level_medium
elif prompt == "hard"
return level_hard
else:
"Please enter easy, medium, or hard for the level."

text based game in python

heres my code
direction = 0
while direction != ("quit"):
direction = input("> ")
if direction[0:4] != "quit" and direction != "go north" and direction != "go south" and direction != "go east" and direction != "go west" and direction != "go up" and direction != "go down" and direction[0:4] != "look":
if direction[0:2] == "go" and direction[3:] == (""):
print("please tell me more")
else:
print("huh?")
elif direction[0:1] == "go" and direction != "north" and direction != "south" and direction != "east" and direction != "west" and direction != "up" and direction != "down":
print ("please tell me more")
elif direction[0:4] == "quit":
print ("OK ... but a small part of you may never leave until you have personally saved Muirfieland from the clutches of evil .. Bwahahahahahah (sinister laugh).")
elif direction[0:4] == "look":
print ("You see nothing but endless void stretching off in all directions ...")
else:
print ("You wander of in the direction of " + direction)
im trying to add this into my code
if the first word is recognised but the second is not, it will respond with :
"sorry, im afraid i cant do that"
im just having troubles getting that one bit into my code, any help will be appreciated thanks.
So quick analysis... You're making text parser which works as following:
Get first word of "command", if we don't know word user used invalid input -> inform and restart
If user used known "command", parse its arguments (like: go north, go south) and let "nested" function take care of argument
Note that "main parsing function" doesn't need to know whether arguments for go() are valid, it just delegates responsibility for validation to go().
So I think you should build code (class) like this:
class Game:
# Initialize internal variables, method automatically called on g = Game()
def __init__(self):
self._exit = False
# Array of known commands, used in run, basically maps commands
# to function and it says: if will get 'go' execute self._go
self._commands = {
'go': self._go,
'quit': self._quit
}
# Array of go sub commands, used by _go
self._commands_go = {
'north': self._go_north
# ...
}
# Mathod for parsing command, if it gets "comamnd" returns ("command",None)
# if "command arg1 arg2" returns ("command", "arg1 arg2")
#staticmethod
def parse_command(string):
string = str(string)
index = string.find(' ')
if index < 0:
return (string, None)
return (string[:index], string[index+1:])
# This is main method; the only one which should be called from outside
# It will just read data from input in never ending loop and parse commands
def run(self):
while not self._exit:
src = input('> ')
(command,args) = Game.parse_command( src)
# Do we have this command, execute it
if command in self._commands:
self._commands[command](args)
else:
print( 'I\'m sorry I don\'t known command {}, try one of these:'.format(command))
print( '\n'.join( self._commands.keys()))
#######################################################
# All game commands go here
#######################################################
def _quit(self,args):
self._exit = True
print( 'Bye bye')
# Movement handling, will get executed when user types 'go ...' nad '...' will be in arg
def _go(self,args):
# No argument
if args is None:
print( 'Go excepts one of these:', '; '.join( self._commands_go.keys()))
return False
# Split sub command anr arguments
(command,args) = Game.parse_command(args)
if command not in self._commands_go:
print( 'Go excepts one of these:', '; '.join( self._commands_go.keys()))
return False
if args is not None:
print( 'Too many arguments for go')
return False
self._commands_go[command](args)
return True
# Go north
def _go_north(self, args):
print( 'Going north')
game = Game()
game.run()
Which would allow you to:
build complex nested commands
build nice and readable commands hierarchy (inventory item 123 update use potion 345) instead of hardly readable set of complex conditions
build function aliases go north can be aliased as gn by adding 'gn': self._go_north to _commands
build reusable arguments parsing (item_id, action, args) = self._parse_item_action(args)
take advantages of object oriented programming (no global variables, everything will be class attribute, lower risk of accidental variables overwriting)
And if you need to parse goasdf as go you can just simply:
for i in self._commands:
if input.startswirh( i):
return self._commands[i](...)
print('Invalid command')
return False
Note: I haven't tested the code, it's just out of my head.
Your code looks quite confusing to me, here is just a simpler version of your code:
flag = 0
count = 0
direction = 0
while direction != ("quit"):
direction = input("> ")
count += 1
if recognised and count == 1: # word is recognised
flag = 1
print "whatever you want..."
elif (not recognised) and count == 2 and flag == 1:
flag = 0
print "sorry, im afraid i cant do that"
else:
flag = 1
print "second is recognised or whatever you want..."
In my code, I've set a flag if first guess is recognised and incremented the count also. On second guess, I'm just checking the flag and count's value.
Not very relative with your code but, When you could instead get the user input, split it so it turns into a list and compare the first word then the second so it could be something like
user = user_input("> ")
user = user.split()
if user[0] == "look"
if user[1] == "left"
do something
if user[1] == "right"
do something
else
print ("sorry, im afraid i cant do that")
Not sure if this is what your looking for though
Simply, I think you need to learn more code to make things a lot easier for yourself here, though maybe classes are a bit much, and I don't mean this in an insulting way.
As a simple start, I'd suggest using the in keyword rather than ==.
For example:
if "north" in direction:
do something
This will "do something" if the input is North, NORTH, go North, go north please and so on.
To solve your issue therefore your code could use something like this:
input = ("> ")
if "go" in input and not ("north" in input and "south" in input...):
print "That is not a direction you can go in."
And so on. The "and not (...)" section can be rewritten much neater but I wrote it as-is to show what is happening easier.
truthcase = None
directions = ["north", "south", ...]
for i in directions:
if i not in input:
continue
else:
truthcase = True
truthcase = False
if "go" in input and not truthcase:
print something
Hopefully this helps.

Why doesn't my list change?

I've been hacking away on a little game, just for fun, and I've run into a problem. I'll post the code and try my best to explain:
def parseCmd(string):
cmd = string.split(' ')
if cmd[0] == 'help':
showHelp()
elif cmd[0] == 'add':
addServer()
elif cmd[0] == 'bag':
viewInventory(inventory)
elif len(cmd) == 1 and cmd[0] == 'look':
describeRoom()
elif len(cmd) == 1 and cmd[0] == 'take':
print 'What do you want me to take?'
elif cmd[0] == 'take':
pickUp(cmd[1], items)
elif cmd[0] == 'exit':
sys.exit(0)
else:
print 'I don\'t know how to ' + cmd[0]
def describeRoom():
print locations[player_location]
def pickUp(item, item_list):
if item in item_list[player_location]:
item_list[player_location].remove(item)
inventory.append(item)
print 'You took the ' + item
else:
print 'I can\'t find any ' + item
inventory = ['id card', 'money', 'keys']
player_location = 'cookieroom'
items = {'cookieroom': ['crowbar', 'hammer']}
locations = {'cookieroom': 'The cookieroom, where all the hard work gets done. \n\nNORTH: LFA - ITEMS: %s' % items[player_location],
'LFA': 'The infamous LFA, where dreams of office supplies become reality. there is a big guy sleeping in his chair next to a fire extinguisher.\n\nSOUTH: Cookieroom, WEST: WC'}
if __name__ == "__main__":
while 1:
t = raw_input('-> ')
parseCmd(t)
So, as you can see I want the list of items in the items dictionary to change when you pick up an item available in that specific room. I can pick up the item and it gets added to my inventory but if I issue the command 'look' it shows the list of items in it's original state.
I've been googling and stackoverflowing for 1½ day now and I can't find anything that seems to solve this problem.
If something is unclear, just ask me and I'll try to answer.
The locations dictionary, which is from where the describeRoom function picks up its room description, is initialised once when the program starts. At that time, the location of the player is the cookieroom and the objects there are the crowbar and the hammer. So, a string is created like so
'The cookieroom, where all the hard work gets done. \n\nNORTH: LFA - ITEMS: ["crowbar", "hammer"]'
This string never changes even if you later alter the contents of the items dictionary.
Your locations dictionary should only contain the non changing part of the room description. The changing part (e.g. the list of items in the room etc.) should be recomputed everytime the users requests the description of the room.

Categories

Resources