Python = repeat every second - python

So I am creating just a basic game, where you purchase ballons and every balloon you buy raises the amount of money you have get per second. But I cant seem to work out how to add the money on every second, considering I already have a While loop and you can't have another one
This is my code
###Game###
import time
money=1
money_ps=0
score=0
while True:
time.sleep(1)
money=money+money_ps
while score==0:
inp=input().lower()
if inp=="buy" or inp=="purchase":
print("What would you like to buy")
print("•Red Balloon (£1)")
print("•Blue Balloon (£100)")
print("•Yellow Balloon (£10000)")
print("•Green Balloon (£1000000)")
print("•Pink Balloon (£100000000)")
inp=input().lower()
if inp=="red balloon":
if money >= 1:
money_ps=money_ps+0.1
money=money-1
print("You successfully bought a Red Balloon")
else:
print("You are unable to afford this")
elif inp=="blue balloon":
if money >= 100:
money_ps=money_ps+1
money=money-1
print("You successfully bought a Blue Balloon")
else:
print("You are unable to afford this")
elif inp=="bank":
print("You have £",money)
Any help is greatly appreciated

Your problem is that your main loop is blocking on those input calls. Fortunately, this is really just a special case of the fundamental problem behind GUI applications, 3D games, and network servers, so the solutions are pretty well known. Unfortunately, the solutions can be a bit complicated, or at least require a lot of learning.
One solution is asynchronous I/O. If you read from a non-blocking file (input just reads from sys.stdin, which acts like a file, even though it isn't on disk), you can use a loop from selectors, or something higher-level like asyncio, to wait, with a timeout, until it's ready, instead of waiting forever. Or you can go below the level of stdin and loop over waiting (with a timeout) for events from the console or the OS and then put those events together into input. Or you can use a higher-level library like curses to do that for you.
The other solution requires less rethinking of your code: Let your main thread spend all its time running a loop around input, and use a background thread that runs a different loop, one which updates your money and then sleeps for a second.
See the threading docs for details and some examples, but you're probably going to want to work through a more thorough tutorial. Anyway, here's the changes you need to make the money loop run in a thread:
money = 1
money_ps = 0
money_lock = threading.Lock()
def money_loop():
global money
global money_ps
global money_lock
while True:
time.sleep(1)
with money_lock:
money=money+money_ps
money_thread = threading.Thread(target=money_loop, args=())
money_thread.start()
Now, we also have to make sure to use the same Lock whenever we want to access money or money_ps in the main thread:
if inp=="red balloon":
with money_lock:
if money >= 1:
money_ps=money_ps+0.1
money=money-1
print("You successfully bought a Red Balloon")
else:
print("You are unable to afford this")
And that's it; now it will work.
Except for one problem: you need a way to tell the background thread to stop when it's time to quit. If your whole program is just going to quit at the same time, then there's a quick and dirty solution to this: using a daemon thread:
money_thread = threading.Thread(target=money_loop, args=(), daemon=True)
Daemon threads get hard-killed as soon as the main thread exits. If your background threads are, say, rewriting files, this can be dangerous, because you can end up with corrupted files only half-way written. But here, all your background thread does is sleep and modify some variables used by the main thread, which doesn't care about them anymore at quitting time, so it's safe.

There are multiple approaches to writing event loops in games. Threading and asyncio are some of the more advanced approaches you may want to consider.
But the simplest approach is to put all the updates inside your while loop. Import time, and add an if statement inside the main loop that checks if at least one second has passed since the last update. If it has, update your state variable.
Game engines will often have a task loop inside the main loop that has a list of any entity that needs to change over time. It then calls an update() method on each entity. Then each entity will check the clock and decide how much to change based on the current time.
while True:
for entity in entities:
entity.update()
But, your input calls will block the main loop from running. Consider using tkinter for input instead, since this won't block.

The other answers have done a good job of introducing you to multithreading and event loops, which will be the right answer if you need to report changes to the user while waiting for input. But in your case, since you're not reporting new money as it is added, you could just wait until you get input, then update the money status. That is, you can update the money status from your main input loop, like this:
import time
money = 1
money_ps = 0
score = 0
last_update_time = int(time.time())
def update_money():
global money, last_update_time
new_time = int(time.time())
money = money + (new_time - last_update_time)
last_update_time = new_time
while score==0:
inp=input().lower()
update_money()
if inp=="buy" or inp=="purchase":
print("What would you like to buy")
print("•Red Balloon (£1)")
print("•Blue Balloon (£100)")
print("•Yellow Balloon (£10000)")
print("•Green Balloon (£1000000)")
print("•Pink Balloon (£100000000)")
inp=input().lower()
update_money()
if inp=="red balloon":
if money >= 1:
money_ps=money_ps+0.1
money=money-1
print("You successfully bought a Red Balloon")
else:
print("You are unable to afford this")
elif inp=="blue balloon":
if money >= 100:
money_ps = money_ps+1
money = money - 1
print("You successfully bought a Blue Balloon")
else:
print("You are unable to afford this")
elif inp=="bank":
print("You have £", money)

Related

How to add random action to Python?

I've been coding an adventure game in Python myself and through YouTube and stuff I found online, but I want to add a part where You gotta get on this boat but a ticket costs $10 (Which you have an option to get earlier).
But say you didn't get the 10 earlier, you have another option to run past the guy who's asking you to pay for it (Which I guess you Could also do even if you have the 10 and just save money). But if you have $10, you just go through, and if you don't, you just restart and it runs sys.exit()
As of writing, the code looks like this:
print("A man offers you a trip to the eastern side of the village via boat")
print(
"as a bridge has not been constructed yet, but it will cost $10, do you give him it ($10 Required) or try run past him(Free)")
check_inv = input()
if "$10" not in inv:
print("He caught you making a run for it! restart game")
sys.exit()
else:
print("Let's see if you have enough...")
print(inv)
print("You have enough and cross the river")
removeFrominventory("$10")
I know how to write a random number generator as it was another beginner project I was advised to work on, but I want to to be that if you type 'Run' you will have a 50/50 chance to be able to outrun him.
Assuming you want it to be like the RNG in pokemon or want to create a coin flip event, you could either create a list of list = [0,1] and use random.choice(list) or you could use randrange() to get a number b/w 0 and 100. Let's say the chances to outrun are x%. If the value obtained from randrange is less than x, you outrun else you don't. You can create a function like:
def RNG(probability):
Generate Random num b/w 0 and 100
if num<probability:
return True
else:
return False
I would prefer the RNG function. Though it is time and memory consuming, it can be reused in the code again and again.

why is there def enter(self): function in all the classes of ex43.py of LPTHW that's never called anywhere in the whole project?

i am on exercise 43 from Learn Python The Hard Way by Zed Shaw. There are so many things i don't get but they are here or there been asked in different forums. what i didn't get here is in the following code excerpts:
class Scene(object):
def enter(self):
print("This scene is not yet configured.")
print("Subclass it and implement and enter().")
exit(1)
this enter(self) has been defined in almost all the classes of the project. but i don't see it being called anywhere. what's its purpose?
class LaserWeaponArmory(Scene):
def enter(self):
print(dedent("""
You do a dive roll into the Weapon Armory, crouch and scan
the room for more Gothons that might be hiding. It's dead
quiet, too quiet. You stand up and run to the far side of
the room and find the neutron bomb in its container.
There's a keypad lock on the box and you need the code to
get the bomb out. If you get the cod e wrong 10 times then
the lock closes forever and you can't get the bomb. The
code is 3 digits.
"""))
code = f"{randint(1,9)}{randint(1, 9)}{randint(1, 9)}"
guess = input("[keypad]> ")
guesses = 0
while guess != code and guesses < 10:
print("BUZZZZZED!")
guesses += 1
guess = input("[keypad]> ")
if guess == code:
print(dedent("""
The container clicks open and the seal breaks, letting
gas out. You grab the neutron bomb and run as fast as
you can to the bridge where you must place it in the
right spot.
#########
"""))
return 'the_bridge'
else:
print(dedent("""
The lock buzzes one last time and then you hear a
sickening melting sound as the mechanism is fused
together. You decide to sit there, and finally the
Gothons blow up the ship from their ship and you die.
"""))
return 'death'
i found similar things called context manager: enter, though i still dont understant what that mean as i am just a beginner.
please explain each of them, if different, differently.
thank you

How would I sent user to new "block" instead of continue same path?

response = ""
while response not in directions_window:
print("While crouched below the window you begin weighing you options")
print("You decide your only options are to listen in, knock on window, or wait")
response = input("Which are you doing?\nlisten/knock/wait")
if response == "listen":
print("You raise your head slightly to hear better\n")
print("You can ony make out a few words before the figure inside sees you\n")
print("Latin words can be heard screaming as it charges towards the window\n")
print("You try to run away, but slip and fall on your stomach.\n")
print("The figure catches up to you only to knock you unconsious.\n")
print("You wake up with scratches and marks around your wrist\n")
print("Taking in your surroundings, you notice you're at the entrance to the forest.\n")
print("You cut your losses, and leave the forest. Forever wondering who, or what, that was.\n")
quit()
I'm in the process of making a text-based adventure game. I want to send the user to a new "part" of the game if this option is selected instead of quit(). How would I skip to a new block? Also, I know I can write it without print every line, but I wrote this over time as ideas came to me. Will fix later
What you might be looking for is to use functions to branch your adventure's "path" into different "sections" which each direct the user to a different area (and can even loop the user back to an area they were before if desired), like this:
def adventure_listen():
print("you picked listen")
# ... more text
response = input("Which do you pick?\nA/B")
if response == "A":
do_something()
elif response == "B":
do_something_else()
def adventure_knock():
# code similar to above
def adventure_wait():
# code similar to above
print("message1")
response = input("Which are you doing?\nlisten/knock/wait")
if response == "listen":
adventure_listen()
elif response == "knock":
adventure_knock()
elif response == "wait":
adventure_wait()
"Jumping blocks" as you call it, is something that is used in assembler code. In high level languages (such as python), flow control structures are used (if else, for loops, while, etc).
For your specific case, if you decide to use flow control structures, and your story is long you will sooner than later get lost in your own code. Functions, as proposed by Cristopher Rybicki, would be a better way to go. For this you should either (a) first know your story in advance and/or (b) find a common structure or pattern in your story that allows you to "open" and "close" chapters.
(a) because it will help you structure better your code
(b) because if you cannot draw at first your story it will help you keep a structure and follow some patterns.
Execution of code is sequential, so you (cannot) should not "jump" from one function to another avoiding (or hoping to) the code after some "branch" line not to execute.
The more advanced approach (and the one I would recommend), is to go with classes and learn your way through inheritance. So your program could have Actions, Moves or whatever you choose it to have. Because you might now want to adventure_knock, and later it might be adventure_throw_the_door_down. They both (i) come from another step in the story, (ii) will have a feedback given to the user, and (iii) will have to go back to a point in the story.
in your main execution you can have a loop that initiates your stories, chapters?, and so on.
a pseudocode example would be:
Action:
abstract function start_action:
...
abstract function end_action:
...
abstract function give_feedback:
...
function ask_for_input:
input('What are you waiting for?')
Knock extends Action:
function start_action:
#specific implementation of knock...
...

How to add a delay or wait to a print() . (python)

I am currently working on a text-based game and I would like to add a delay in the appearance of a text. The text where I want the delay is the third descendant of an if-else command.
I've tried time.sleep() function but that doesn't seem to work.
if path.lower().strip() == "yes":
print("Then let your journey begin")
else:
print("\nWell,")
print("You don't have much of a choice do you.")
# the text I need to delay ^^^
So what I'm hoping to do is add a few seconds of delay to the entrance of the commented text.
import time
# ...
if path.lower().strip() == "yes":
print("Then let your journey begin")
else:
print("\nWell,")
time.sleep(3) # parameter used here is in seconds
print("You don't have much of a choice do you.")
# the text I need to delay ^^^
time.sleep(secs)
secs - The number of seconds the Python program should pause execution. This argument should be either an int or a float.
Suspend execution of the calling thread for the given number of seconds. The argument may be a floating point number to indicate a more precise sleep time. The actual suspension time may be less than that requested because any caught signal will terminate the sleep() following execution of that signal’s catching routine. Also, the suspension time may be longer than requested by an arbitrary amount because of the scheduling of other activity in the system.
Changed in version 3.5: The function now sleeps at least secs even if the sleep is interrupted by a signal, except if the signal handler raises an exception (see PEP 475 for the rationale).

How to have input while a while loop ( or similar) is executed

I do believe that thread may accomplish this, although I am not sure. Most of the threads out there that address this problem doesn't address it to match my problem. I have created a simple mud-like fighting system that executes when you 'fight' an NPC. I have the code that runs under a while loop that checks health between you and NPC and if one of you dies then the loop ends.
However
During the loop I want to have it where a user can type in commands, instead of being stuck watching a looping code block without you being able to do anything. From what I have read online it looks like thread module may be of some help to me? Also if anyone has PyGame experience, maybe looking into that would be a solution? Please let me know what you think.
Below is a very simple example of what I am trying to accomplish.
import time
fighting = True
while fighting:
# do the magic here
time.sleep(4) # to give it a nice even pace between loop intervals
Although at any time i want to be able do input a command like a skill or spell.
Any ideas or suggestions?
You can separate your human interface and fight game into separate threads. The fight game uses a queue for input, which uses a timeout to continue. Here is a very simple queue structure that should minimally do what you want.
import time
import threading
import Queue
def fighter(input_queue):
while True:
start = time.time()
# do stuff
wait = time.time() - start()
if wait <= 0.0:
wait = 0
try:
msg = input_queue.get(wait, wait)
if msg == 'done':
return
# do something else with message
except Queue.Empty:
pass
def main():
input_queue = Queue.Queue()
fight_thread = threading.Thread(target=fighter, args=(input_queue,))
fight_thread.start()
while True:
msg = raw_input('hello ') # py 2.x
input_queue.put(msg)
if msg == 'done':
break
fight_thread.join()
If you only want this to work on Windows, and you want to keep your simple event loop:
fighting = True
inputbuf = ''
while fighting:
# do the magic here
while msvcrt.khbit():
newkey = msvcrt.getwche()
inputbuf += newkey
if newkey == '\r':
process_command(inputbuf)
inputbuf = ''
time.sleep(4) # to give it a nice even pace between loop intervals
On the other hand, if you want to use a background thread, it would be a lot simpler:
def background():
for line in sys.stdin:
process_command(line)
bt = threading.Thread(target=background)
bt.start
fighting = True
while fighting:
# do the magic here
time.sleep(4) # to give it a nice even pace between loop intervals
This works cross-platform, and it gives normal line-buffered input (including full readline support), which people will probably like.
However, I'm assuming you want that process_command to share information with the # do the magic here code, and possibly even to set fighting = False. If you do that without any thread synchronization, it will no longer work cross-platform. (It may work on both Windows CPython and Unix CPython, but will probably not work on IronPython or Jython—or, worse, it will work most of the time but randomly fail just often enough that you have to fix it but not often enough that you can debug it…)
What you may be looking for is a non-blocking raw_input implementation. This would allow the loop to keep going while allowing the user a possibility at entering commands.
There is an example of an implementation of this here and here. Maybe you can adapt one of them to suit your purpose.
Edit:
Or, if you're working on Windows...

Categories