Python, How to add more choices in an if statement - python

I have a python program with an if statement. I want to add more choices to the if statement, how do I do it?
def start():
print ("A Wise man once said ...")
o1 = input("\n" +
"[L]ook to the poverty of Africa ... [T]HIS HAS YET TO BE WRITTEN")
if o1 == "L" or "l" or "Africa" or "1":
print ("\n" + "You decide only a radical solution is viable...")
else:
print ("THIS IS NOT WRITTEN YET")
def menu ():
print ("Menu\n")
print ("(1)Start")
print ("(2)Exit\n\n")
choice = (input('>>'))
if choice=="1":
start()
if choice=="2":
quit()
menu()
I am trying to make this option next:
o2 = input (
"\n" + "[D]ecide to take advantage ..., or T[H]IS HAS YET TO BE WRITTEN?"*)
How should I go about adding more options and choices so that I end up with a story?

There are a couple of good ways to do this, but I would make a class (lets call it "option_node") that uses dictionaries. The class would hold the text of the prompt, then a dictionary that mapped the text options to other option_nodes or a special option node that ends the dialog.
class option_node:
def __init__(self, prompt):
self.prompt = prompt
self.options = {}
def add_option(self, option_text, next_node):
self.options[option_text] = next_node
def print_prompt(self):
print(prompt)
def select_input(self):
for each in self.options:
print(each)
while(True)
user_input = input(">>")
if self.options.get(in):
return self.options.get(in)
def main():
nodes = []
nodes.append(option_node("Welcome"))
nodes.append(option_node("Stay Awhile"))
nodes.append(option_node("That's fine, I don't like you much either"))
nodes[0].add_option("Hello friend", nodes[1])
nodes[0].add_option("Hello enemy", nodes[2])
nodes[1].options = None
nodes[2].options = None
current_node = nodes[0]
while current_node.options is not None:
current_node.print_prompt()
current_node = current_node.select_input()
Hope this helps. I can elaborate more if you'd like

Add a new condition using elif (else if):
if ...
elif o1 == "D" or o1 == "H":
# your code here
else ...
By the way, you have a syntax error in your conditional statement. Correct it to this:
if o1 == "L" or o1 == "l" or o1 == "Africa" or o1 == "1":
If it makes it easier, look at it this way:
if (o1 == "L") or (o1 == "l") or (o1 == "Africa") or (o1 == "1"):
You should think about the order of operations in your statements. or has higher precedence than ==; additionally, the meaning of "L" or "l" is not what you think it is.
>>> if "L" or "l":
... print("foo")
...
foo
Curious, no? Try some of this stuff out for yourself at the interpreter.

Related

How do I save my place in a text adventure (a function) to a file?

I'm starting a rudimentary text adventure game. I got a prototype working, but because each choice is a function, I can't figure out how to safely save my place in a file.
I considered saving the function's name to a file, but I can't think of a good way to get the function from its name as a str after reading the file. eval on an arbitrary str is notoriously unsafe. I considered a dict mapping every function to its name as a str, but it seems that as more choices pile up, this dict is gonna bloat my script.
def choice1():
while True:
text = input("A or B?: ")
if text == "A":
return False, choice2
elif text == "B":
saygameover()
return True, None
elif askedforsave(text):
return True, choice1
else:
saytryagain()
def choice2():
while True:
text = input("C or D?: ")
if text == "C":
print("you win!")
return True, None
elif text == "D":
saygameover()
return True, None
elif askedforsave(text):
return True, choice2
else:
saytryagain()
def askedforsave(text):
if text == "save":
return True
else:
return False
def saytryagain():
print("try again...")
def saygameover():
print("game over.")
def play(choice = choice1):
done = False
while not done:
done, choice = choice()
if choice != None:
save(choice)
def save(choice):
pass
def load(file):
pass
return choice
This is what I got so far. isidentifier is probably unnecessary when I'm already checking for a name in globals() but it's a good trick for making sure you're working with a valid Python name instead of an expression.
import types
def load(string):
# if string is valid Python name
if (string.isidentifier() and
# if string in this global scope's symbol table
string in (thisglobal := globals()) and
# if object is a non-builtin function
isinstance(something := thisglobal[string], types.FunctionType)):
return something
else:
return nogame
def nogame():
return True, None

How can I concatenate 2 variables, to call another variable of that combination?

I have a defined function that includes a counter to know how many times it has been used, and asks for a user input of either L, R or F.
I want it to then check the input and add it to the counter and call the function of that name.
eg:
user choose L
count is at 3
call function L3
here is what I have so far, but I get an error:
def getUserDirection():
getUserDirection.counter = 0
getUserDirection.counter += 1
direction = str(input("Which direction do you wish to go? (L/F/R) "))
direction = direction.upper()
if direction not in ("L", "F", "R"):
print("whats does {} mean? You were meant to type 'L', 'F' or 'R'! Try again..".format(direction))
direction = getUserDirection()
elif direction == "L":
print(direction()+counter())
elif direction == "F":
print(direction()+counter())
elif direction == "R":
print(direction()+counter())
return getUserDirection()
The other functions I want it to call are:
def L1():
print("you go left and see...")
def F1():
print("You continue forward and see...")
def R1():
print("You go right and see...")
The idea is to loop through getUserDirection() and call a different function with each pass. There will be plenty of functions as it progresses eg L1, L2, L3... each having a different story and new choice of direction to make.
What am I doing wrong?
FULL CODE
#PLAYER DETAILS
first_name = input("What is your first name? ")
last_name = input("What is your last name? ")
while True:
middle = input("Do you have a middle name? (y/n) ")
if middle.upper() not in ("Y", "N"):
print("whats does {} mean? You were meant to type 'y' or 'n'! Try again.." .format(middle))
elif middle.upper() == "Y":
middle_name = input("What is it? ")
break
elif middle.upper() == "N":
middle_name = None
break
# is_middle_empty = bool(middle_name)
# print(is_middle_empty)
print("So your full name is {} {} {}? ".format(first_name, '' if middle_name is None else middle_name, last_name))
import time
time.sleep(1)
print("Hmmm..")
time.sleep(1)
just_first = str(input("Should I just call you {}? (y/n) ".format(first_name)))
if just_first.upper() == "Y":
player = first_name
print("Great, nice to meet you", player)
elif just_first.upper() != "Y":
name = first_name, "" if middle_name is None else middle_name, last_name
player = " ".join(name)
print("Sorry about that, let's stick to {} then." .format(player))
print()
#DIRECTION FUNCTION
def getUserDirection():
getUserDirection.counter = 0
getUserDirection.counter += 1
direction = str(input("Which direction do you wish to go? (L/F/R) "))
direction = direction.upper()
if direction not in ("L", "F", "R"):
print("whats does {} mean? You were meant to type 'L', 'F' or 'R'! Try again..".format(direction))
direction = getUserDirection()
elif direction == "L":
print(direction()+counter())
elif direction == "F":
print(direction()+counter())
elif direction == "R":
print(direction()+counter())
return getUserDirection()
#STORY LINES
def start():
print("You have arrived at ... To your left (L) is ..., ahead (F) is ... To your right (R) is ...")
def L1():
print("you go left")
def F1():
print("You continue forward")
def R1():
print("You turn right")
#ADVENTURE-1
adventure = input("So do you fancy a quick adventure? (y/n) ")
if adventure.upper() == "Y":
print("Great then lets set off...")
elif adventure.upper() == "N":
print("Ah well, I guess we can't all be ubercool adventurers like me, fairwell {}, I hope we meet again some day." .format(player))
#ADVENTURE-2
time.sleep(1)
print(start())
print(getUserDirection())
ERROR TRACEBACK
Traceback (most recent call last):
File "C:\Users\admin\PycharmProjects\pythonProject1\main.py", line 70, in <module>
print(getUserDirection())
File "C:\Users\admin\PycharmProjects\pythonProject1\main.py", line 43, in getUserDirection
print(direction()+counter())
TypeError: 'str' object is not callable
The cleanest way is to store your functions in a dict-
def L1():
print("you go left and see...")
def F1():
print("You continue forward and see...")
def R1():
print("You go right and see...")
# define more functions....
inp_to_func = {
'L1': L1,
'F1': F1,
'R1': R1
# define more key-value pairs....
}
Which you can then use like-
func = inp_to_func.get(f'{direction}{counter()}')
if not func:
# no function found for input
# do error handling here
pass
else:
func()
This assumes direction is a string and counter() returns a number - and combining them in the shown order forms the key in the dictionary.
Edit: If you have a counter variable instead, and not a function - you'd have to do f'{direction}{counter}' of course. It just seemed from your code that counter is a function you have defined that returns a number.
Suppose direction is a string variable with the value of 'L', and counter is an int variable with the value of 1.
f'{direction}{counter}' gives you 'L1'
If L1 is a key in the inp_to_func dictionary and its value is a function object, inp_to_func.get('L1') will return said function object.
The function object can now be treated like any other function, that is - it can be called using parens - ().
So, going line by line-
func = inp_to_func.get(f'{direction}{counter}')
# ^ Gets the function object corresponding to the input, or `None`
if not func:
# ^ func was `None` (as in, no key was found)
# no function found for input
# do error handling here
pass
else:
func()
# ^ calls the function
You can do this by accessing the globals or by using eval.
direction, counter = "L", 1
globals()[f"{direction}{counter}"]() # globals return a dictionary, where you can access the variable through this dictionary.
eval(f"{direction}{counter}()") # eval evaluates python expression, in this case, the function call
This is what you're looking for based on your question, although if I would do this... I would probably create a single function then pass the direction and counter arguments to it.
def fun(direction, counter):
if direction == "L":
if counter == 1:
# do something...
elif direction == "R":
# do something...
direction, counter = "L", 1
# then you'll call it like...
fun(direction, counter)

How to?: If string contains uppercase ''X'' print("X spotted!")

I'm working on a school assignment and it works (so far) but I don't understand why I had to put the second if statement after else in the tester function for that if p condition (Xavier) to work.
I need someone to explain why I couldn't use the if before else in this case.
The same condition. It actually needs to test if the user input contains an uppercase X. I have searched online but just can't figure out which method to use.
def tester(p, givenstring = "Too short"):
result=len(p)
if result>=10:
print(p)
else:
print(givenstring)
if p == "Is Xavier here?": # if p == "X" doesn't work.
print("X is spotted!")
def main():
while True:
prompt=input("Write something (quit ends): ")
if prompt=="quit":
break
else:
tester(prompt)
if __name__ == "__main__":
main()
def tester(p, givenstring = "Too short"):
result=len(p)
if result>=10:
print(p)
else:
print(givenstring)
#Comments should be created using hash(#) not (//) >> //if p == "X" doesn't work.
if p == "Is Xavier here?": # this is doing an exact match of the string and not finding 'X'
print("X is spotted!")
def tester(p, givenstring = "Too short"):
result=len(p)
if result>=10:
print(p)
else:
print(givenstring)
if 'X' in p: # this will return True if 'X' is present in p
print("X is spotted!")
def main():
while True:
prompt=input("Write something (quit ends): ")
if prompt=="quit":
break
else:
tester(prompt)
main()
Write something (quit ends): This is captain x-merica
This is captain x-merica
Write something (quit ends): This is captain X-merica
This is captain X-merica
X is spotted!
Write something (quit ends): quit

Can I add two VALUES to a dictionary from user input?

I keep getting an error when I run this functions. Everything goes through and then it shows this error. I have tried adding .items() to the end when I print the dictionary and still throws this error.
CLARIFICATION just realized. Not getting any type errors or anything. It prints fine but when doesn't add the second variable to the dictionary. Instead it prints this..
{'Frappe': ('small', function type_of_milk at 0x000002BE2BCD2F78>)}
def order():
ready_to_order = True
while ready_to_order != False:
ordering_q = input(
"""Do you know what you would like to order or do you need to see the menu?
[M]enu or [R]eady to order or [Q]uit: """)
if ordering_q.upper() == "Q":
sys.exit()
elif ordering_q.upper() == "M":
print(Menu())
elif ordering_q.upper() == "R":
ready_to_order = False
else:
print("Please enter valid letters only, try again.")
print(" ")
print(" ")
add_cart = True
while add_cart != False:
order1 = input("What would you like to order?")
if order1.upper() == "Done":
add_cart = False
elif order1 == 'a1':
print("Frappe added to cart")
global total_order
total_order += 3
drink_size()
type_of_milk()
order_dict['Frappe'] = (drink_sizes, type_of_milk)
add_cart = False
print(order_dict)
This line:
order_dict['Frappe'] = (drink_sizes, type_of_milk)
is adding the function type_of_milk to your dict, which is why you see function type_of_milk at 0x000002BE2BCD2F78> when you print the dict out. Maybe you meant to say type_of_milk()?

"list index out of range" exception (Python3)

I keep getting a list index out of range exception when I check the length of the list a. The error pops up for either the if or elif part of the second if statement, depending on what the user inputs. I know that when the user input is split the list is created correctly because I print it out... So I'm a little lost about why I'm getting that error.
if __name__ == '__main__':
for line in sys.stdin:
s = line.strip()
if not s: break
if (str(s) is "quit") == True: quit()
elif (str(s) is "quit") == False:
a = s.split()
print(a)
if (len(a) == 2) == True: first(a)
elif (len(a) == 3) == True: first(a)
else: print("Invalid Input. Please Re-enter.")
The first method is: (The methods it calls in the if statement just print things out at the moment)
def first(self, a = list()):
word = a[0]
if word is ls:
ls(a[1])
elif word is format:
form(a[1]) # EDIT: was format
elif word is reconnect:
reconnect(a[1])
elif word is mkfile:
mkfile(a[1])
elif word is mkdir:
mkdir(a[1])
elif word is append:
append(a[1], a[2])
elif word is delfile:
delfile(a[1])
elif word is deldir:
deldir(a[1])
else:
print("Invalid Prompt. Please Re-enter.")
Other methods:
def reconnect(one = ""):
print("Reconnect")
def ls(one = ""):
print("list")
def mkfile(one = ""):
print("make file")
def mkdir(one = ""):
print("make drive")
def append(one = "", two = ""):
print("append")
def form(one = ""):
print("format")
def delfile(one = ""):
print("delete file")
def deldir(one = ""):
print("delete directory")
def quit():
print("quit")
sys.exit(0)
The problem seems to be the definition of first(). You invoke it as a function:
if (len(a) == 2) == True: first(a)
elif (len(a) == 3) == True: first(a)
But you define it as a method:
def first(self, a = list()):
The array of command and argument gets put into self and a is always an empty list which you attempt to index and fail. Also, you shouldn't use a mutable type like list() as a default value unless you're certain what you are doing. I suggest simply:
def first(a):
As far as your __main__ code goes, simplify:
if __name__ == '__main__':
for line in sys.stdin:
string = line.strip()
if not string:
break
if string == "quit":
quit()
tokens = string.split()
length = len(tokens)
if 2 <= length <= 3:
first(tokens)
else:
print("Invalid Input. Please Re-enter.")
Real issue:
To solve your error you have to remove the self parameter of the first function
def first(a=list())
Basically the self is only used for object orientation creating methods.
Function like yours can't use self otherwise you will passing the first parameter to self not to a which you want to.
My second issue I can point out is that, You are trying to compare using is between a string and a function.
def first(a = list()):
word = a[0]
if word is "ls":
ls(a[1])
elif word is "format":
format(a[1])
elif word is "reconnect":
reconnect(a[1])
elif word is "mkfile":
mkfile(a[1])
elif word is "mkdir":
mkdir(a[1])
elif word is "append":
append(a[1], a[2])
elif word is "delfile":
delfile(a[1])
elif word is "deldir":
deldir(a[1])
else:
print("Invalid Prompt. Please Re-enter.")
Extra
The is function on built in operations in Python. is compare the equity of the objects.
But this expression:
if (str(s) is "quit") == True:
Can be simpler like:
if str(s) == "quit":
Or:
if str(s) is "quit":
The == True is meaningless either == False you can use not more pythonicly.

Categories