Console/Terminal interactive chosen menu with keyboard arrow - python

main.py:
import keyboard
import ui
import os
os.system("cls")
ui.play[ui.counter] = "> " + ui.play[ui.counter] + " <"
ui.navmenuprint(ui.play)
while True:
while ui.state == "play":
keypressed = keyboard.read_key()
while keyboard.is_pressed("down"): pass
while keyboard.is_pressed("up"): pass
while keyboard.is_pressed("enter"): pass
if keypressed == "up":
os.system("cls")
ui.navup(ui.play, ui.play2)
ui.navmenuprint(ui.play)
if keypressed == "down":
os.system("cls")
ui.navdown(ui.play, ui.play2)
ui.navmenuprint(ui.play)
if keypressed == "enter":
if ui.counter == 0:
ui.switchstate("shop")
if ui.counter == 1:
ui.switchstate("shop")
if ui.counter == 2:
ui.switchstate("shop")
if ui.counter == 3:
ui.switchstate("shop")
while ui.state == "shop":
keypressed = keyboard.read_key()
while keyboard.is_pressed("down"): pass
while keyboard.is_pressed("up"): pass
while keyboard.is_pressed("enter"): pass
if keypressed == "up":
os.system("cls")
ui.navup(ui.shop, ui.shop2)
ui.navmenuprint(ui.shop)
if keypressed == "down":
os.system("cls")
ui.navdown(ui.shop, ui.shop2)
ui.navmenuprint(ui.shop)
if keypressed == "enter":
if ui.counter == 0:
ui.switchstate("play")
if ui.counter == 1:
ui.switchstate("play")
if ui.counter == 2:
ui.switchstate("play")
if ui.counter == 3:
ui.switchstate("play")
if ui.counter == 4:
ui.switchstate("play")
ui.py:
import os
from termcolor import cprint
state = "play"
counter = 0
play = ["TOSHOP", "TOSHOP", "TOSHOP","TOSHOP"]
play2 = ["TOSHOP", "TOSHOP", "TOSHOP","TOSHOP"]
shop = ["TOPLAY", "TOPLAY","TOPLAY","TOPLAY","TOPLAY"]
shop2 = ["TOPLAY", "TOPLAY","TOPLAY","TOPLAY","TOPLAY"]
def switchstate(fromwhere):
global state, counter
if fromwhere == "play":
counter = 0
state = fromwhere
play = play2.copy()
os.system("cls")
play[counter] = "> " + play[counter] + " <"
navmenuprint(play)
if fromwhere == "shop":
counter = 0
state = fromwhere
shop = shop2.copy()
os.system("cls")
shop[counter] = "> " + shop[counter] + " <"
navmenuprint(shop)
def navup(list1, list2):
global counter
if counter != 0:
list1[counter] = list2[counter]
counter -= 1
list1[counter] = "> " + list1[counter] + " <"
else:
list1[counter] = list2[counter]
counter -= 1
list1[counter] = "> " + list1[counter] + " <"
counter = len(list1) - 1
print (counter)
def navdown(list1,list2):
global counter
if counter != len(list1) - 1:
list1[counter] = list2[counter]
counter += 1
list1[counter] = "> " + list1[counter] + " <"
else:
list1[counter] = list2[counter]
counter = 0
list1[counter] = "> " + list1[counter] + " <"
print (counter)
def navmenuprint(list):
global counter
for i in list:
print(i)
This code is an extract from my little homemade console game project, I tried to delete all unnecessary code, I successfully made a working interactive menu which means I want to achieve navigation with up and down arrow in menu and currently selected item show as > item <, handle error if list out of index, state handling (for switching screens).
Unfortunately I had to make a few ugly workaround to make this happen or I just too beginner to figure it out.
Python 3.11, I don't want to use additional modules.
The problem:
Go down to 4th item (counter variable value will be 3)
Press Enter
Go down to 5th item (counter variable value will be 4)
Press Enter
Press down
Actual:
TOSHOP
> TOSHOP <
TOSHOP
> TOSHOP <
Expected:
TOSHOP
> TOSHOP <
TOSHOP
TOSHOP
I understand my code and spent many hours to solve this issue but I have no idea why it's faulty.
I think counter variable value is good everywhere.
I make sure to reset "play" and "shop" list to original form and counter variable to 0.

I had to expand global variables with lists inside switchstate function:
def switchstate(fromwhere):
global state, counter, play, play2, shop, shop2

Related

Why am I not breaking out of a try loop with a break statement?

My code for now works as desired where the user can input a level 1-3 depending on how hard they would like it to be (1-3 being the amount of digits the numbers will have in the math equation), and then must solve math equations. Those math equations will output EEE if the answer is incorrect and everything works as planned if you correctly answer the question as it exits the function and adds one total_correct_answers variable at the bottom, then will prompt you with another equation. However, if you input an incorrect answer and then a correct answer, you will just be prompted with the same question over and over again without the try loop being truly broken out of and total_correct_answers not being incremented positively by 1. The incrementation block of code is at lines 61-65, and the equation code is lines 30-49.
import random
def main():
ten_questions()
def get_level():
while True:
try:
level_input = int(input("Level: "))
if level_input in [1,2,3]:
return level_input
except:
pass
def integer_generator(level):
if level == 1:
x = random.randint(0,9)
y = random.randint(0,9)
elif level == 2:
x = random.randint(10, 99)
y = random.randint(10, 99)
else:
x = random.randint(100, 999)
y = random.randint(100, 999)
return x, y
def question_generator(x, y):
real_answer = x + y
wrong_counter = 0
while True:
try:
answer_given = input(str(x) + " + " + str(y) + " = ")
if int(answer_given) == real_answer:
if wrong_counter == 0:
return True
elif int(answer_given) == real_answer and wrong_counter != 0:
break
else:
while wrong_counter < 2:
print("EEE")
wrong_counter +=1
break
else:
print(str(x) + " + " + str(y) + " = " + str(real_answer))
print("False, that was last attempt")
break
except:
print("EEE")
pass
def ten_questions():
num_of_questions = 0
total_correct_answers = 1
my_level = get_level()
correct_answers = question_generator(*integer_generator(my_level))
while num_of_questions <= 8:
question_generator(*integer_generator(my_level))
num_of_questions +=1
if correct_answers == True:
total_correct_answers +=1
print("Score: " + str(total_correct_answers))
if __name__ == "__main__":
main()
Because of your line 36:
if int(answer_given) == real_answer: happens when someone answers correctly, wether they are right or wrong. So it enters the if, and then faces if wrong_counter == 0: which discards wrong answers. So just replace those two lines with if int(answer_given) == real_answer and wrong_counter == 0: and you are good to go.

TypeErr: Object "int" is not callable

I tried to make a "typing game" and at first, it worked out pretty nice. But when I translated my code to English (variable names, class names, function names etc.) it gave me the warning "Object int is not callable". How can I solve this?
Here's my code:
import time
import random
import sys
class Player():
def __init__(self, name, health = 5, energy = 10):
self.name = name
self.health = health
self.energy = energy
self.hit = 0
def inf(self):
print("Health: ", self.health, "\nEnergy: ", self.energy, "\nName: ", self.name)
def attack(self, opponent):
print("Attacking")
time.sleep(.300)
for i in range(3):
print(".", end=" ", flush=True)
x = self.randomAttack()
if x == 0:
print("Nobody attacks.")
elif x == 1:
print("{} hits {} !".format(name, opponentName))
self.hit(opponent)
opponent.health -= 1
elif x == 2:
print("{} hits {}!".format(opponentName, name))
opponent.hit(self)
self.health -= 1
def randomAttack(self):
return random.randint(0, 2)
def hit(self, hit):
hit.hitVariable += 1
hit.energy -= 1
if (hit.hitVariable % 5) == 0:
hit.health -= 1
if hit.health < 1:
hit.energy = 0
print('{} won the game!'.format(self.name))
self.exit()
#classmethod
def exit(cls):
sys.exit()
def run(self):
print("Running...")
time.sleep(.300)
print("Opponent catch you!")
#######################################################
print("Welcome!\n----------")
name = input("What's your name?\n>>>")
opponentName = input("What's your opponent's name?\n>>>")
you = Player(name)
opponent = Player(opponentName)
print("Commands: \nAttack: a\nRun: r\nInformation: i\nExit: e")
while True:
x = input(">>>")
if x == "a":
you.attack(opponent)
elif x == "r":
you.run()
elif x == "i":
you.inf()
elif x == "e":
Player.exit()
break
else:
print("Command not found!")
continue
It gives me the error at line 24 (self.hit(opponent)).
Your hit function is the problem. You have member and a function with the same name. Change one of them.
Also rename the hit argument of the hit(). You call it via self.hit(opponent) so I would rename it to def hit(self, opponent):.
def __init__(self, name, health = 5, energy = 10):
self.hit = 0
def hit(self, hit):
hit.hitVariable += 1
hit.energy -= 1
if (hit.hitVariable % 5) == 0:
hit.health -= 1
if hit.health < 1:
hit.energy = 0
print('{} won the game!'.format(self.name))
self.exit()

Python tkinter can't use Entry.get() fucntion

So I have been working on a quizzing application for some time now (about 4 days). I managed to make all the logical part of the code (the quiz taking, the quiz question handling, score outputting, etc.) I know that this code is neither the best nor the most efficient as it can be but I'm just a beginner. Anyways, the get() function for the entry function for tkinter does not return anything. I am aware that there is a way to fix it however I'm not sure how to implement the solution with an external loop. Please help me. Here is my code:
import random
from time import sleep
import tkinter as tk
from tkinter import *
import threading
class App(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.start()
def callback(self):
self.root.quit()
def run(self):
self.root = tk.Tk()
self.root.protocol("WM_DELETE_WINDOW", self.callback)
#label = tk.Label(self.root, text="Hello World")
#label.pack()
#Button(self.root, text = "Choose", command=btnPressed).pack()
tk.Label(self.root, text="Answer: ").grid(row=0,column=0)
#answerField_get = StringVar()
answerField = tk.Entry(self.root)
answerField.grid(row=0, column=1)
#Button(self.root, text='Show').grid(row=3, column=1, sticky=tk.W, pady=4)
print(str(answerField.get()))
Button(self.root, text='Show', command = lambda arg1=answerField.get():btnPressed("<"+str(arg1)+">")).grid(row=3, column=1, sticky=tk.W, pady=4)
self.root.mainloop()
def sendTMP(self, sendStr):
btnPressed(sendStr)
SCORE_SET = []
qasTmp = {}
qas = {}
qasSequenced = {}
incorrectResponses = []
incorrectResponses_replies = []
quiztaker_name = ""
attachAnsCode = "%% Fun fact: rgb computer parts lovers are somewhat weird hehe %%********^^&&^^&&^^&&"
qasQsSequenced = False
qasQsL = 0
qasQsL_divisionFactor = 2
qasINDEX = 0
err_noCode = "<!>NO_CODE<!>"
codes_answerCorrect = "A_C"
codes_answerIncorrect = "A_I"
answerCode = err_noCode
score = 0
randQs = False
# File
# the metadata will corrupt the reading from the file, a separate file, created in the targeted system, must be used to properly read the data.
# comment out the file name that is not being used.
filename_windows = "qas-windows"
filename_rpi = "qas-rpi"
filename = filename_windows
fileformat = "txt"
file_name_format = filename + "." + fileformat
spaceIndicator = "|"
char_commentLine_qasFile = "*"
char_newline = "`"
print("Information about modes: ")
print(" *Easy: No point deductions for an incorrect response")
print(" *Hard: One point deducted for every incorrect response")
modes_err = "0"
modes_ez = "1"
modes_hard = "2"
gameOn = False
selectedMode = modes_err
askReplay = True
data_prev = []
with open("SCORES.txt", 'r') as scores_prev:
data_prev = scores_prev.readlines()
scores_prev.close()
for i in range(0, len(data_prev)):
SCORE_SET.append(data_prev[i])
def btnPressInform():
print("A button has been pressed!")
def importAndClean():
# import questions from qas-windows.txt
with open(file_name_format, 'r') as document:
for line in document:
if line.strip():
key, value = line.split(None, 1)
if key[0] != char_commentLine_qasFile: # Custom comments for the txt file
qasTmp[key] = value.split()
# Clean up dictionary input from the txt file
for i in range(0, len(qasTmp)): # FIVE FOR LOOPS!!!! (FOUR IN THIS ONE)
for ii in qasTmp:
output = ""
output_ans = ""
for iii in range(0, len(ii)):
if ii[iii] != spaceIndicator:
output += ii[iii]
else:
output += " "
for iiii in range(0, len(qasTmp[ii])):
TEMP = str(qasTmp[ii])
for iiiii in range(2, len(TEMP) - 2): # IGNORE [' and ']
# print(TEMP[iiiii])
if TEMP[iiiii] != spaceIndicator:
output_ans += TEMP[iiiii]
else:
output_ans += " "
# print(output + " : " + output_ans) #Output question: answer
qas[output] = output_ans
importAndClean()
def getL():
qasQsL = len(qas) / qasQsL_divisionFactor # only ask 1/qasQsL_divisionFactor the questions
qasQsL = int(qasQsL) # round to an integer as odd numbers will end in .5 after division
if qasQsL < 1:
qasQsL = 1 # Have atleast ONE question
return qasQsL
def debug1(keys, vals, index, i):
print(str(index) + "/" + str((len(keys) - 1)))
print(keys)
print(vals)
print()
print(keys[index] + " : " + vals[index] + "\n")
print("Sorting original index " + str(i) + " at random index " + str(index))
def debug2(keys, vals, index):
print(keys)
print(vals)
print("\n")
def debugFinal():
print("Temp (OG reading): ")
print(qasTmp)
print("\nQAS (Non-sequenced, cleaned): ")
print(qas)
print("\nQAS Sequenced (Randomly sequenced, cleaned): ")
print(qasSequenced)
def randomize(qasQsL_tmp):
qas_keys = list(qas.keys())
qas_vals = list(qas.values())
if randQs == False:
qasQsL_tmp = len(qas_keys) # all questions
print("You will be asked all " + str(qasQsL_tmp) + " questions")
else:
qasQsL_tmp = getL() # random question
print("You will be asked " + str(qasQsL_tmp) + " questions out of " + str(len(qas)) + " possible questions!")
print("\n\nRandomly sequencing questions...")
for i in range(0, qasQsL_tmp):
INDEX = random.randint(0, qasQsL_tmp - 1)
# debug1(qas_keys, qas_vals, INDEX, i)
qasSequenced[qas_keys[INDEX]] = qas_vals[INDEX]
qas_keys.pop(INDEX)
qas_vals.pop(INDEX)
qasQsL_tmp -= 1
# debug2(qas_keys, qas_vals, INDEX)
sleep(0.05)
# debugFinal()
print("Done sequencing! Starting quiz now! \n\n")
return "0"
def quizController(index):
qas_keys = list(qasSequenced.keys())
qas_vals = list(qasSequenced.values())
# print(qas_keys)
# print(qas_vals)
lines = []
lines_index = 0
tmp = ""
# Splitter
for i in range(0, len(qas_keys[index])):
if lines_index < len(qas_keys[index]) - 1:
if qas_keys[index][i] != char_newline:
tmp += qas_keys[index][i]
else:
lines.append(tmp)
tmp = ""
lines.append(tmp)
# Multiple choice
mChoiceQ = False
mChoice_startBrackets = 0
mChoice_endBrackets = 0
mChoice_options = []
mChoice_numOptions = 0
mChoice_seperatorsAt = []
for i in range(0, len(qas_keys[index])):
if qas_keys[index][i] == "[":
mChoice_startBrackets = i
mChoiceQ = True
elif qas_keys[index][i] == "]":
mChoice_endBrackets = i
elif qas_keys[index][i] == "/":
mChoice_seperatorsAt.append(i)
if mChoiceQ == True:
TEMP = ""
for i in range(mChoice_startBrackets, mChoice_endBrackets + 1):
if qas_keys[index][i] != "[":
if qas_keys[index][i] != "/" and qas_keys[index][i] != "]":
TEMP += qas_keys[index][i]
else:
mChoice_options.append(TEMP)
TEMP = ""
mChoice_numOptions = len(mChoice_seperatorsAt) + 1
# Default options (yes, no) full names
for i in range(0, len(mChoice_options)):
if mChoice_options[i].lower() == "y":
mChoice_options.append("yes")
elif mChoice_options[i].lower() == "n":
mChoice_options.append("no")
# if mChoiceQ == True:
# print("It is a multiple choice question! There are " + str(mChoice_numOptions) + " options. They are: ")
# print(mChoice_options)
print("\nQuestion " + str(index + 1) + "/" + str(qasQsL) + ":")
for i in range(0, len(lines)):
print(lines[i])
# answer = ""
answer = input(">")
# answer = input(qas_keys[index]+ ": ")
if mChoiceQ == False:
if len(answer) > 0:
if answer.lower() == str(qas_vals[index]).lower():
return codes_answerCorrect
else:
incorrectResponses.append(qas_keys[index])
incorrectResponses_replies.append(answer)
# print("DEBUG: Incorrect response! Expected '" + str(qas_vals[index]).lower() + "', received " + answer.lower())
return codes_answerIncorrect
else:
print("Please insert an answer!")
else:
allowedResponse = False
for i in range(0, len(mChoice_options)):
if answer.lower() == mChoice_options[i].lower():
allowedResponse = True
if allowedResponse == True:
ans = qas_vals[index].lower()
yn = False
ans_yesno = ""
if ans.lower() == "y" or ans.lower() == "n":
yn = True
else:
yn = False
if yn == True:
if ans == "y":
ans_yesno = "yes"
elif ans == "n":
ans_yesno = "no"
if len(answer) > 0:
if yn == True:
if answer.lower() == ans.lower() or answer.lower() == ans_yesno.lower():
return codes_answerCorrect
else:
return codes_answerIncorrect
incorrectResponses.append(qas_keys[index])
incorrectResponses_replies.append(answer)
else:
if answer.lower() == ans.lower():
return codes_answerCorrect
else:
return codes_answerIncorrect
incorrectResponses.append(qas_keys[index])
incorrectResponses_replies.append(answer)
else:
print("Please insert an answer!")
else:
print("Invalid response! You may only enter the following: " + str(mChoice_options))
def saveScore():
# Clear file!
score_file_CLEAR = open("SCORES.txt", "wt")
score_file_CLEAR.close()
# Save contents
score_file = open("SCORES.txt", "wt")
for i in range(0, len(SCORE_SET)):
score_file.write(SCORE_SET[i])
print("Done saving!")
def btnPressed(tmp):
print(tmp)
app = App()
while True:
qasQsL = len(qasSequenced)
if gameOn == True and selectedMode != modes_err:
if qasQsSequenced == True:
if qasINDEX < qasQsL:
answerCode = quizController(qasINDEX)
else:
output = randomize(qasQsL)
if output == "0":
qasQsSequenced = True
if qasINDEX < qasQsL:
if answerCode == codes_answerCorrect:
score += 1
qasINDEX += 1
# print("DEBUG: Correct! Score set to: " + str(score))
elif answerCode == codes_answerIncorrect:
if selectedMode == modes_hard:
score -= 1
qasINDEX += 1
# print("Score set to: " + str(score))
else:
print("")
if qasQsL != 0:
score_per = score / qasQsL
if score_per < 0:
score_per = 0
if score < 0:
score = 0
print("You score was lower than 0, therefore it was set to 0")
# print("Your score: " + str(score) + "/" + str(len(qasSequenced)) + " (" + str(int(score_per*100)) + "%)")
# if score != qasQsL:
# print("You responded to the following questions incorrectly:")
# print(incorrectResponses)
if score / qasQsL == 1:
SCORE_SET.append(quiztaker_name + " scored " + str(score) + " out of " + str(qasQsL) + "(" + str(
int(score / qasQsL) * 100) + "%). PART OF Qs: " + str(
int(randQs)) + " at division factor 1/" + str(qasQsL_divisionFactor) + ", MODE: " + str(
int(selectedMode)) + "\n")
if score / qasQsL != 1:
SCORE_SET.append(quiztaker_name + " scored " + str(score) + " out of " + str(qasQsL) + " (" + str(
int(score / qasQsL) * 100) + "%). PART OF Qs: " + str(
int(randQs)) + " at division factor 1/" + str(qasQsL_divisionFactor) + ", MODE: " + str(
int(selectedMode)) + " They got the following questions wrong: \n")
for i in range(0, len(incorrectResponses)):
SCORE_SET.append(" " + str(i + 1) + ") " + incorrectResponses[i] + " --RESPONSE-- " +
incorrectResponses_replies[i] + "\n")
SCORE_SET.append("\n")
saveScore()
qasQsSequenced = False
gameOn = False
print("\nGame over!")
askReplay = True
else:
continue
elif askReplay == False:
TEMP = input("What mode would you like? (E = Easy, H = Hard): ")
if len(str(TEMP)) > 0:
if str(TEMP).lower() == "e":
selectedMode = modes_ez
gameOn = True
print("Set mode to: NO POINT DEDUCTIONS")
elif str(TEMP).lower() == "h":
selectedMode = modes_hard
gameOn = True
print("Set mode to: POINT DEDUCTIONS ALLOWED")
else:
print("Error: Undefined response. Please try again!")
elif askReplay == True:
TEMP = input("Would you like to (re)do the quiz? (Y/N): ")
if len(str(TEMP)) > 0:
if str(TEMP).lower() == "y":
askReplay = False
qasQsSequenced = False
qasQsL = 0
qas.clear()
qasSequenced.clear()
qasTmp.clear()
qasINDEX = 0
incorrectResponses.clear()
answerCode = err_noCode
score = 0
selectedMode = modes_err
importAndClean()
randQs = False
USER_TEMP = input("Please enter your name >")
if len(USER_TEMP) > 0:
quiztaker_name = str(USER_TEMP)
print("Welcome " + quiztaker_name + "!")
USER_TEMP = input("Would you like all questions (a) or a part of the questions(p)? (A/P) > ")
if len(USER_TEMP) > 0:
if USER_TEMP.lower() == "a":
print("Set to all questions!")
randQs = False
elif USER_TEMP.lower() == "p":
print("Set to 1/" + str(qasQsL_divisionFactor) + " questions (pre-set variable)")
randQs = True
else:
print("Undefined response! Setting to default value (ALL)")
randQs = False
gameOn = False
askReplay = False
elif str(TEMP).lower() == "n":
selectedMode = modes_hard
gameOn = False
print("Exiting now!")
saveScore()
sleep(2)
exit(0)
else:
print("Error: Undefined response. Please try again!")
Entry() doesn't work like input(). It doesn't wait for your data but it only informs tkitner that you want to display Entry widget (and mainloop() will display it) and Python goes to next lines of code and it runs print(str(answerField.get())) before it even displays window - so you try to get from empty Entry.
You should get it in function assigned to Button which you will press after you put some text in Entry.
The same problem is with
lambda arg1=self.answerField.get():print(arg1)
it assigns to args value from Entry only once when lambda is defined at start - so it get empty string. You should use it inside function
command=lambda:print(self.answerField.get())
or create normal function and assign to button.
Minimal working code
import tkinter as tk
import threading
class App(threading.Thread):
def run(self):
self.root = tk.Tk()
#self.root.protocol("WM_DELETE_WINDOW", self.on_close)
self.answerField = tk.Entry(self.root)
self.answerField.grid(row=0, column=1)
#b = tk.Button(self.root, text='Show', command=lambda:print(self.answerField.get()))
b = tk.Button(self.root, text='Show', command=self.on_click)
b.grid(row=1, column=1)
self.root.mainloop()
def on_click(self):
print(self.answerField.get())
#def on_close(self):
# self.root.destroy()
App().start()
#App().run()

List not copying (empty) [duplicate]

This question already has answers here:
Defining lists as global variables in Python
(3 answers)
Slicing list inside a method (Python 3)
(1 answer)
Closed 5 years ago.
I have the following code:
import sys
import os.path
import ConfigParser
import copy
import time
import colorama
from colorama import init
from colorama import Fore, Back, Style
init()
#init variables
discoveredelements = []
discoveredgroups = []
combo = []
savefile = ConfigParser.ConfigParser()
os.chdir(os.getcwd())
#init other stuff
class style:
BOLD = '\033[1m'
END = '\033[0m'
def combos():
#all combos
combo.append(('Air', 'Air', 'Wind'))
combo.append(('Earth', 'Earth', 'Pressure'))
combo.append(('Fire', 'Fire', 'Explosion'))
combo.append(('Water', 'Water', 'Sea'))
combo.append(('Air', 'Earth', 'Dust'))
combo.append(('Air', 'Fire', 'Energy'))
combo.append(('Air', 'Water', 'Steam'))
combo.append(('Earth', 'Fire', 'Lava'))
combo.append(('Earth', 'Water', 'Swamp'))
combo.append(('Fire', 'Water', 'Alcohol'))
def mainmenu():
print(style.BOLD + "ALCHEMY" + style.END)
print(style.BOLD + "Load Game" + style.END)
print(style.BOLD + "New Game" + style.END)
print(style.BOLD + "Exit" + style.END)
print("Type \"load\" or \"new\" or \"exit\" ")
mainmenuinput = raw_input()
if mainmenuinput == "exit":
sys.exit()
elif mainmenuinput == "load":
if os.path.exists('save.ini'):
savefile.read('save.ini')
discoveredelements = savefile.get('Elements','discoveredelements')
print("Game Loaded")
rungame()
else:
print("Save file not found, check file directory or start a new game.")
mainmenu()
elif mainmenuinput == "new":
if os.path.exists("save.ini"):
print("Current save file will be overwritten. Proceed?")
print("Y or N")
overwriteinput = raw_input()
if overwriteinput == "Y":
newgame()
rungame()
elif overwriteinput == "N":
mainmenu()
else:
newgame()
rungame()
def newgame():
save = open('save.ini','w')
#reset data
savefile.add_section('Elements')
savefile.add_section('Groups')
savefile.set('Elements','discoveredelements',"")
savefile.set('Groups','discoveredgroups',"")
#adds the default elements
discoveredelements.append("Air")
discoveredelements.append("Earth")
discoveredelements.append("Fire")
discoveredelements.append("Water")
savefile.set('Elements','discoveredelements',discoveredelements)
discoveredgroups.append("Air")
discoveredgroups.append("Earth")
discoveredgroups.append("Fire")
discoveredgroups.append("Water")
savefile.set('Groups','discoveredgroups',discoveredgroups)
savefile.write(save)
save.close()
print("Game Loaded")
def gameloop():
#actual gameplay
print("Type two elements (seperately) or \"list\" or \"hint\" or \"save\" or \"exit\"")
gameinput = raw_input()
if gameinput == "list":
displayelements = copy.copy(discoveredelements)
print(','.join(map(str, displayelements)))
gameloop()
elif gameinput == "hint":
if (time.time() - timerstart) >= 10:
print('hint')
timerstart = time.time()
gameloop()
else:
print("Hint is still on cooldown")
gameloop()
elif gameinput == "save":
savefile.set('Elements','discoveredelements',discoveredelements)
savefile.set('Groups','discoveredgroups',discoveredgroups)
print("Game saved")
elif gameinput == "exit":
savefile.read('save.ini')
savelist = savefile.get('Elements','discoveredelements')
if len(savelist) < len(discoveredelements):
print("Game not saved! Do you wish to exit without saving?")
print("Y or N")
overwriteinput = raw_input()
if overwriteinput == "Y":
mainmenu()
else:
gameloop()
else:
elementA = gameinput
elementB = raw_input()
if (elementA in discoveredelements) and (elementB in discoveredelements):
i = 0
created = 0
while True:
if (combo[i][0] == elementA and combo[i][1] == elementB) or (combo[i][1] == elementA and combo[i][0] == elementB):
print("You created " + combo[i][2])
discoveredelements.append(combo[i][2])
created = 1
break
i += 1
if i == len(combo):
break
if created == 0:
print("No elements created")
gameloop()
else:
print("Error, using non-existent or not yet discovered elements")
gameloop()
def rungame():
#initializing game
timerstart = time.time()
displayelements = copy.copy(discoveredelements)
print(','.join(map(str, displayelements)))
gameloop()
#game starts here
print(Style.RESET_ALL)
combos()
mainmenu()
When I type "load" into the console, nothing is outputted for displayelements. So I tried to see if the list contained anything (and if the copy.copy() worked or not) by doing print(displayelements) and it printed []
Then I checked if discoveredelements contained anything and it did:
['Air', 'Earth', 'Fire', 'Water']
Why isn't the copy.copy() working?
EDIT:
I declared discoveredelements as global:
global discoveredelements
discoveredelements = []
The copying still doesn't work, displayelements is still an empty list.
To assign to a global var in function you must declare is as global:
discoveredelements = []
def func():
# a new var is created in the scope of this function
discoveredelements = [1,2,3,4]
func()
print (discoveredelements)
discoveredelements = []
def func():
# declare as global
global discoveredelements
# assign to the global var
discoveredelements = [1,2,3,4]
func()
print (discoveredelements)

error making text based game spawn monster

I am making a text based game with my friend for a programming class, we are avoiding using object oriented stuff so please avoid those suggestions. to use the program I would normally do type "help" then I can go in any direction to move like "right", "left", "down" and "up" when I try to use those commands I get an error. this happend after I added the spawnMonster command part
#Connor and Griffin's text based adventure
import os
import random
############################
####---Variable setup---####
#########ADD COMMAND VARIATION############
#########ADD ITEM LISTS#################
commands = 1 #for debuging only please
maxHealth = 100 #Default begin health
health = 100 #Current health
mana = 0 #THERES NO MAGIC
mapS = [5, 5]
objects = {}
color = "0f"
output = "" #this is where whats happening is told to you
level = 1
canMove = 1
playerSym = "P"
# for activeQuests remember that if the value is 0 its not completed and if its 1 its completed
activeQuests = {"Journey To Riverwood": 0}
# Add new quest names above^
commandList = {"help", "legend", "color", "show inv", "quests", "console", "up", "left", "right", "down", "clear", "map"}
#Default inventory
inv = {"apple(s)":2, "shortsword":1, "gold":50,"cloth shirt":1,"pair of cloth pants":1,"pair of shoes":1}
clearedSpaces = []
##### "Name":baseDMG #####
monsters = {"Goblin":1, "Troll":3, "Bear":2, "Giant Spider": 1, "Bandit":1, "Goblin Chief":3}
###########################
###########################
##### Name:lv:monsterSpawnRate #####
zones = {"Forest":[1,90]}
#######################
#---Quest Log Stuff---#
def checkQuest():
for questn in activeQuests:
print("\n------", questn, "------")
if activeQuests[questn] == 0:
print("\nNot Complete")
else:
print("\nComplete")
######Description for quests######
if questn == "Journey To Riverwood":
print("""
Welcome to Connor and Griffins excellent adventure!
try out some of the commands like; help, quests,
color, inv or show inv. now using your new found
commands move to the city of riverwood.\n\n""")
#########################
#########################
############################
###---Scenes/Functions---###
def mapSize(x, y):
global mapS
mapS = [x, y]
####Ads point to map
def addObject(name, x, y, symbol):
objects[name] = [x, y, symbol]
legend[symbol] = name
#### Clears some variables
def roomStart():
global objects
objects = {}
global legend
legend = {"░":"Unknown area"}
global roomName
roomName = "BLANK"
def newArea():
for area in zones:
global spawnChance
spawnChance = zones[area][1]
def spawnMonster():
enemy, DMG = random.choice(monsters)
return enemy
def moveToNewSpace():
rand = random.randint(1,100)
if rand <= spawnChance:
global spawnedMonster
spawnMonster()
###Move player
def changePos(name, newx, newy):
objects[name][0] += newx
objects[name][1] += newy
global clearedSpaces
clearedSpaces.append([objects[name][0],objects[name][1]])
moveToNewSpace()
###First room
def roomBegin():
roomStart()
mapSize(15,10)
global roomName
roomName = "Forest"
newArea()
addObject("Riverwood",10,5,"R")
addObject("Griffin's House",2,2,"G")
addObject("Player",2,3,playerSym) #######Remember to make a "ChangePos" command to change the pos of the player when they move#######
clearedSpaces.append([2,3])
################### MAPPING HERE ##################
def makeMap():
print("\n------"+roomName+"------")
for y in range(mapS[1]):
line = ""
numy = y+1
for x in range(mapS[0]):
numx = x + 1
for place in objects:
if objects[place][:2] == [numx, numy]:
line += objects[place][2]
break
else:
if [numx, numy] in clearedSpaces:
line += " "
else:
line += "░"
print(line)
print("\n----Legend----\n")
for thing in legend:
print(thing + " - " + legend[thing])
############################
############################
#######################
###--- MAIN LOOP ---###
roomBegin()
while 1 == 1:
makeMap()
print("\n\n" + output + "\n\n")
print("\n\nHealth is at ",health,"/",maxHealth)
command = input("Enter action: ")
if command.lower() == "quests":
os.system("cls")
checkQuest()
elif command.lower() == "legend":
os.system("cls")
print("\n----Legend----\n")
for thing in legend:
print(thing + " - " + legend[thing])
elif command.lower() == "help":
os.system("cls")
print("\n\n------HelpMenu------\n")
for comd in commandList:
print(comd)
elif command.lower() == "color":
newc = input("new color: ")
os.system("color 0" + newc)
os.system("cls")
elif command.lower() == "show inv" or command.lower() == "inv" or command.lower() == "inventory":
os.system("cls")
print("\n------Inventory------\n")
for item in inv:
print(" ", inv[item]," ", item)
elif command.lower() == "console":
if commands == 1:
consolecmd = input("Enter a command: ")
os.system(consolecmd)
else:
print("Sorry, you dont have permition to use that command.")
elif command.lower() == "up":
if canMove == 1:
os.system("cls")
changePos("Player", 0,-1)
else:
os.system("cls")
output += "\nCant move that way right now!"
elif command.lower() == "down":
if canMove == 1:
os.system("cls")
changePos("Player", 0,1)
else:
os.system("cls")
output += "\nCant move that way right now!"
elif command.lower() == "left":
if canMove == 1:
os.system("cls")
changePos("Player", -1,0)
else:
os.system("cls")
output += "\nCant move that way right now!"
elif command.lower() == "right":
if canMove == 1:
os.system("cls")
output = "There are some trees here, and a small pond"
changePos("Player", 1,0)
else:
os.system("cls")
output += "\nCant move that way right now!"
elif command.lower() == "clear":
os.system("cls")
else:
os.system("cls")
print("Previous attempt was an invalid command, try again.")
#######END MAIN#######
######################
The random.choice function requires a sequence.
In a previous version of your code (or maybe it was code from a classmate of yours just having similar but not identical problems with similar code?), you had the monsters stored in a list, like [("Goblin", 1), ("Troll", 3), …]. For that code, random.choice works, because a list is a sequence.
But now you have a dict. And a dict is not a sequence.
You can get a list of all of the keys in a dict just by writing list(d). So, you could do this:
return random.choice(list(monsters))
But you're not actually getting any benefit from monsters being a dict from what I can tell, so why not just use a list in the first place?
monsters is a dictionary. It is being passed to random.choice(), however, random.choice() accepts a sequence as its argument (from which it randomly selects one element). This will not work for a dictionary and you will see a KeyError exception if you try.
Since you just want to return an enemy from spawnMonster() you can instead use the keys of monsters which is a list:
monsters = {"Goblin":1, "Troll":3, "Bear":2, "Giant Spider": 1, "Bandit":1, "Goblin Chief":3}
def spawnMonster():
return random.choice(monsters.keys())
Update
Since you are using Python 3 you can do this instead (also works in Python 2):
def spawnMonster():
return random.choice(tuple(monsters))

Categories

Resources