Skip to content

Instantly share code, notes, and snippets.

@horstjens
Last active Jun 20, 2022
Embed
What would you like to do?
doors_chest1
"""minigames for temple of doors:
opening a chest, guessing a number with hint system
using PySimpleGUI as GUI
"""
import PySimpleGUI as sg
import random
# graph window
WIDTH = 600
HEIGHT = 50
class Riddle:
storage = {}
number = 1
def __init__(self, solution_list, hint_list, full_bonus=60, bounty=100):
self.number = Riddle.number
Riddle.storage[self.number] = self
Riddle.number += 1
self.solutions = solution_list
self.solved = False
self.hints = hint_list # ( [[func_string, description_text, price in gold ],])
self.full_bonus = full_bonus # max. time in seconds to solve this riddle, bonus gold is the remaining time left
self.bonus = full_bonus # current time left
self.bounty = bounty # how much gold you get for solving this riddle, independent of time spent
#self.visible_hints = [True if price == 0 else False for (func, text, price) in self.hints] # how many hints are already visible
self.wrong_answers = set()
self.wrong_answers.add("--type your guess here--")
# ----------- self-test ----------
results = []
# check all hints for all provided solutions
for solution in self.solutions:
results = self.test(solution)
if not all(results): # all: only True's in the iterable
print(f"self-test: riddle {self.number}: found error for solution {solution}!", results)
def history(self):
"""get big text of wrong answers"""
wrongs = list(self.wrong_answers)
wrongs.sort()
return "\n".join(wrongs)
def test(self, solution):
"""check if all hints are True for one provided solutions
returns a list of boolean values"""
all_results = []
for (func_string, func_txt, price) in self.hints:
try:
result = eval(func_string)(str(solution))
except:
result = False
all_results.append(result)
return all_results
def calculate_hint_list(self, solution):
results = self.test(solution)
t = []
for i, (func_string, func_txt, price) in enumerate(self.hints):
if price == 0:
t.append([price, func_txt, results[i]])
else:
t.append([price, "--you can buy this hint--", results[i]])
return t
def get_riddle(riddle_number):
riddle = Riddle.storage[riddle_number]
window2["bonus"].update(f"{riddle.bonus:.1f}")
window2["riddle_number"].update(f"Bounty for riddle #{riddle_number}:")
window2["bounty"].update(f"{riddle.bounty}")
# TODO: actual bonus, hints etc.
if riddle_number > 1:
window2["previous riddle"].update(disabled=False)
if riddle_number < len(Riddle.storage):
window2["next riddle"].update(disabled=False)
return riddle
# ------------------ riddles ----------------
# --------- create riddle number 1 ----------
# hints: function-string, description, price in gold
# price of 0 means this hint is instantly visible
hints = [["""lambda x: len(x) == 3""", "the code has 3 chars", 0],
["""lambda x: x.isnumeric()""", "the code has only (decimalsystem) digits", 0],
["""lambda x: "4" in x""" , "there is at least one '4' in the code", 10],
["""lambda x: x[0]=='7'""", "the first char is x, where 5x -14 = 3x", 20],
["""lambda x: int(x[0])+int(x[1])+int(x[2])==16""", "the sum of all digits in the code is 16", 40],
]
solutions = [745,754]
Riddle(solution_list=solutions, hint_list = hints )
# --------- create riddle number 2 ----------
hints = [["""lambda x: len(x)>0""" , "it sails on the sea", 0],
["""lambda x: x.isalpha()""", "the code has only letters", 0],
["""lambda x: len(x) == 4""", "the code has 4 chars", 5],
["""lambda x: 'i' in x""", "the code conains an 'i'", 20],
]
solutions = ["ship"]
Riddle(solution_list=solutions, hint_list = hints )
# -------- first gui: theme cooser --------------------------
sg.theme(random.choice(sg.theme_list()))
# ---------------------- theme selector layout -------------
layout1 = [
[
sg.Text("Select theme:"),
sg.Combo(
values=sg.theme_list(),
default_value=sg.theme(),
enable_events=True,
key="selector",
),
],
[sg.Button("play the game")],
]
window1 = sg.Window("theme selector", layout1)
# ---------------- main loop for first layout ---------------
while True:
event1, values1 = window1.read()
if event1 == "play the game" or event1 == sg.WIN_CLOSED:
# sg.theme("DarkBlue3")
break
if event1 == "selector":
old = sg.theme()
sg.theme(values1["selector"])
if sg.PopupYesNo("do you like this Theme?") == "Yes":
break
else:
sg.theme(old)
window1.close()
# sg.PopupOK("and now to the main program...")
# 745
layout2 = [
[sg.Text("Bonus:"),sg.Text("10", key="bonus", font=("Arial", 20, "bold")),
sg.Graph((WIDTH,HEIGHT), graph_bottom_left=(0,HEIGHT), graph_top_right=(WIDTH,0),
key="g", background_color=sg.theme_background_color())],
[sg.Text("Your gold:"), sg.Text(100,key="gold"),
sg.Text("Bounty for riddle #1:", key="riddle_number"),
sg.Text("100", key="bounty"),
sg.Text("riddles solved:"),sg.Text(f"0/{len(Riddle.storage)}", key="solved") ],
[ sg.Column([
[sg.Text("Enter Code:")],
[sg.Input(default_text="???", key="code", enable_events=True,
font=("Courier New",20), size=(20,1))],
[sg.Text("wrong codes:")],
[sg.Multiline("???\n", disabled=True, size=(40,5), key="history", autoscroll=True )],
]),
sg.Column([
[sg.Image(filename="chest.png", key="img")],
]),
],
[ sg.Text(f"hints: 2 / 4", key="hints"),
sg.Button(f"buy this hint for 10 gold", key="buy_hint")],
[ sg.Table([[]],
alternating_row_color=sg.theme_input_background_color(), # "light grey",
headings=["price","condition","status"],
font=("System", 12),
auto_size_columns=False,
justification="left",
num_rows = 10,
col_widths = [10,40,10],
enable_events = True,
select_mode = sg.TABLE_SELECT_MODE_BROWSE,
key="table"),],
[sg.Button("previous riddle", disabled=True), sg.Button("next riddle", disabled=True), sg.Button("Exit")],
]
window2 = sg.Window("code guesser game", layout2)
window2.Finalize()
g = window2["g"]
fig1 = g.draw_rectangle(top_left=(0,0), bottom_right=(150,20),
line_color=sg.theme_input_text_color(),
fill_color=sg.theme_text_color(),
line_width=3)
riddle = Riddle.storage[1]
#print(riddle.solutions)
window2["table"].update(riddle.calculate_hint_list("???"))
window2["table"].update(select_rows=[0])
# left align for first column in table, see pysimplegui issue #
window2["table"].Widget.column('#1', anchor='e') # east for right
# TODO: replace with the brand_new cols_justification , as soon as all my students have upgraded to newest pysimplegui
gold = 100
anim = False
while True:
event2, values2 = window2.read(timeout=10)
#print(event2, values2)
if event2 in ("Exit", sg.WIN_CLOSED):
break
elif event2 == sg.TIMEOUT_EVENT:
if anim:
window2["img"].update_animation("chest_animation.gif", time_between_frames = 200)
else:
if riddle.bonus > 0:
riddle.bonus -= 0.01 # 10 ms
#window2["bonus"].update(f"{bonus:.2f}")
g.delete_figure(fig1)
w = (WIDTH / riddle.full_bonus) * riddle.bonus
fig1 = g.draw_rectangle(top_left=(0,0), bottom_right=(w,HEIGHT),
line_color=sg.theme_input_text_color(),
fill_color=sg.theme_text_color(),
line_width=3)
else:
riddle.bonus = 0
g.delete_figure(fig1)
window2["bonus"].update(f"{riddle.bonus:.1f}")
elif event2 == "table":
# a hint line was clicked
# or code was changed and for unknow reason this triggered the table event...
try:
line_number = values2["table"][0]
except IndexError:
continue
# using named tuples would be fine, but I need named list (??) because the price will be changed after buying a hint
price = riddle.hints[line_number][2]
if price == 0:
window2["buy_hint"].update(disabled=True)
window2["buy_hint"].update(text="This hint is already bought")
else:
window2["buy_hint"].update(text=f"Buy this hint for {price} gold")
window2["buy_hint"].update(disabled=False)
elif event2 == "buy_hint":
line_number = values2["table"][0]
price = riddle.hints[line_number][2] # TODO: use named tuples
if gold < price:
sg.PopupOK("You have not enough gold")
continue
gold -= price
window2["gold"].update(f"{gold}")
window2["buy_hint"].update(disabled=True)
window2["buy_hint"].update(text="This hint is already bought")
riddle.hints[line_number][2] = 0 # set price to 0
window2["hints"].update(f"hints: {[price for (f,d,price) in riddle.hints].count(0)} / {len(riddle.hints)}")
window2["table"].update(riddle.calculate_hint_list(values2["code"]))
window2["table"].update(select_rows=[line_number])
elif event2 == "next riddle":
i = riddle.number + 1
if i <= len(Riddle.storage):
riddle = get_riddle(i)
elif event2 == "code":
#print("something happened in code")
guess = values2["code"]
# ----- check how many hints are true -------
window2["table"].update(riddle.calculate_hint_list(guess))
#print("guess/solution", guess, solutions)
# ------ check if guess is one of the correct answers ---
if guess.lower() in [str(x).lower() for x in riddle.solutions]:
window2["img"].update(filename="chest_animation.gif")
window2["img"].update_animation_no_buffering("chest_animation.gif", time_between_frames = 200)
anim =True
riddle.solved = True
window2["solved"].update(f"{len([r for r in Riddle.storage.values() if r.solved])}/{len(Riddle.storage)}")
wintext = "Your guess is correct!\n"
wintext += "You win gold:\n"
wintext += f"bounty: {riddle.bounty:8.2f}\n"
wintext += f"+bonus: {riddle.bonus:8.2f}\n"
wintext += "======================\n"
wintext += f"=total: {riddle.bounty+riddle.bonus:8.2f}"
sg.PopupOK(wintext, title="You win!", font=("Courier New",12))
gold += (riddle.bounty + riddle.bonus)
window2["gold"].update(str(round(gold,2)))
window2["code"].update(disabled=True)
window2["buy_hint"].update(disabled=True)
# next / prev riddle?
if riddle.number < len(Riddle.storage):
window2["next riddle"].update(disabled=False)
else:
# wrong answer
if anim:
window2["img"].update(filename="chest.png")
anim = False
if len(guess) > 0:
# adding to a set will never create duplicate values
riddle.wrong_answers.add(guess)
window2["history"].update(riddle.history())
window2.close()
print("bye")
"""minigames for temple of doors:
opening a chest, guessing a number with hint system
using PySimpleGUI as GUI
"""
import PySimpleGUI as sg
import random
# graph window
WIDTH = 800
HEIGHT = 500
# -------- first gui: theme cooser --------------------------
sg.theme(random.choice(sg.theme_list()))
# ---------------------- theme selector layout -------------
layout1 = [
[
sg.Text("Select theme:"),
sg.Combo(
values=sg.theme_list(),
default_value=sg.theme(),
enable_events=True,
key="selector",
),
],
[sg.Button("play the game")],
]
window1 = sg.Window("theme selector", layout1)
# ---------------- main loop for first layout ---------------
while True:
event1, values1 = window1.read()
if event1 == "play the game" or event1 == sg.WIN_CLOSED:
# sg.theme("DarkBlue3")
break
if event1 == "selector":
old = sg.theme()
sg.theme(values1["selector"])
if sg.PopupYesNo("do you like this Theme?") == "Yes":
break
else:
sg.theme(old)
window1.close()
# sg.PopupOK("and now to the main program...")
layout2 = [
[sg.Text("Enter the Code:"),
sg.Input(default_text="???", key="code", enable_events=True)],
[sg.Text("hints:"),],
[sg.Table([["condition1:","fullfilled"],
["condition2:","not fullfilled"],
],alternating_row_color="grey",
headings=["condition","status"],
key="table")],
[sg.Button("Exit")],
]
window2 = sg.Window("code guesser game", layout2)
while True:
event2, values2 = window2.read(timeout=10)
if event2 in ("Exit", sg.WIN_CLOSED):
break
elif event2 == "code":
print("something happened in code")
window2.close()
print("bye")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment