Python Multithreading to allow user to exit at anytime - python

I'm writing a text based RPG, and I am using Python 3.3.4. It will be played through the Python command line, with no graphics. I'm wanting to make it so that no matter what options the user is presented with, they have the capability of typing "exit" or "help" and exiting (or getting help information) respectively at any time during the game. So if they're in the middle of fighting some monster and the only options presented to them directly would be to attack, defend, or flee, they're still able to exit or get help. Same for once they leave that function and they're just moving around the map, or talking to NPCs. From what I've found, starting a thread that waits for "exit" to be entered is the best way to do that. If I'm wrong, please let me know! If not, please explain (or show me a guide) how I'm supposed to go about this because none of my ideas have worked.
I've attempted using the threading module, and _thread. I may not have implemented them correctly, and I have no code to show for my attempts as I just trashed it when it didn't work.
Thank you in advance.

Your game doesn't have to do any work in the background, so you do not need to spawn any additional threads. The main loop of your program will listen for user input, perform the action, and then prompt the user for their next action. It should look something like this:
while True:
input = get_user_input()
if input == 'exit':
break
next_actions = modify_game_state(input)
print "You can now do: %s" % next_actions
Edit: You should not have more than one thread accept user input. It's possible for one of the threads to gobble information that was intended for the other, so no matter what solution you decide on, don't add a thread that just checks if the user input was "exit", unless it reads all of the user input.

Looking back at this, I feel like an absolute idiot.
The proper way to handle this would be calling a function that accepts input and checks it against different expected strings or numerical values.
I just thought I'd answer this in a little more clear way than Stu did.

Related

Can I put input in Mindstorms 51515 while programming in python?

When I was programming in Mindstorms Robot Inventor, and decided to put an input in my code, I bumped into this NameErrorThis is the Error
Is it Even possible to put an input in Mindstorms??
The Python available isn’t the complete Python standard library. The terminal view in the code editor doesn’t provide for a way to put in input either, so unfortunately no.
What you can do instead is use the buttons on the hub as a type of input. This wouldn’t be free-form text, but if you’re using input() as a user-controlled wait before progressing, you can do that.
_ = hub.right_button.was_pressed() # clear out any button press
while not hub.right_button.was_pressed():
# do something
# do something after the button was pressed
You can string multiple of the above in a row if you want to do multiple actions separated by waiting for you to let it continue, or even take different actions based on which button was pressed.
Finally, you could do a very slow text input using the buttons and the display screen to scroll through the alphabet, confirm the letter, and finish the input.

Difference between pynput key clicks and physical key clicks on the keyboard?

I've recently realized that Python's pynput module's key click doesn't get registered in certain software. However, physical key clicks work perfectly fine. This raises the question of how are the two different methods been recognized. I thought this would've been an answered question from a long time ago but I can't seem to find any post about this.
Let's take a random game such as Genshin for example. The "w" key on the keyboard would result in the character in the game moving forward. However, a program such as the following that "holds" down the "w" key doesn't get registered by the game.
from pynput.keyboard import Key, Controller
keyboard = Controller()
while True:
keyboard.press("w")
keyboard.release("w")
The two big questions that I have are:
What is the difference between physical key clicks and the program generate key clicks that allowed these softwares to distinguish which method is used?
Based on the answer to the first question, is there a way to bypass such a difference without tempering with the software's code (aka disguise program generated key clicks as physical key clicks)?
Thanks in advance!
Edit: If anyone has any idea on how this works, please let me know. Any help would be much appreciated!
I also encountered this problem when I was trying to write a small program to help myself in Genshin. After an excruciating search, I found these two questions: question1, question2
I'm not very sure how it exactly works, so I can only give you my conclusion: When we run Genshin, we give it admin rights. Programs without admin rights sort of can't interact with it.
To solve this problem, you can merge this into your code:
import ctypes, sys
def is_admin():
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
if is_admin():
# Code of your program here
else:
# Re-run the program with admin rights
ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join(sys.argv), None, 1)
Then you need to make the code an executable with pyinstaller module. When you execute it, it will re-run and ask you for admin rights, then it can do its job on Genshin or other program.
There are certainly games that intentionally try to prevent the kind of cheating you're trying to do. How they do so depends on the operating system.
pynput on Windows, for example, uses the send_input API to inject keystrokes into the input system, but a sufficiently motivated application could be reading at a lower level, by using a keyboard filter driver to pull keystrokes before they get into the input system.
With such a design, there's nothing you can do in user mode to cheat the keys. You would need your own kernel driver, and even then it's not trivial to guarantee the order that the filters load.

How to not immediately refresh after user input curses

I am writing a DoodleJump game for the terminal in Python with curses. I use getch() to get the user input to know in which direction the character should move. When I get the user input my environment gets updated simultaneously but I want that it just keeps on moving and not update when I get the user input.
Does anybody know how I can achieve this? I tried using nodelay() but that still doesn't cut it. Thanks in advance
please try with:
time.sleep(seconds)
This will wait the seconds you want before continue.
Sources:
https://www.pythoncentral.io/pythons-time-sleep-pause-wait-sleep-stop-your-code/
Hope it help, have a nice day,
David.
curses refreshes the window associated with getch. You could prevent refreshes (or hide them) by turning off echo, and using a window that won't have changes made to it (even one that you create just for that purpose).

Different coloured print strings in python - IDLE

I'm using IDLE to just create a short, basic text adventure game. the methods I try work in other editors such as Repl.it or canopy, but I prefer the use of IDLE as I just like the simplicity of it, and that it doesn't require an Internet connection to access.
I won't mention the methods I tried, as I may have just been approaching them in the entirely wrong way, or maybe IDLE just simply doesn't have the functionality of other editors, but I just want to make the text in the game clearer to distinguish. For example, below is a short segment:
import time
print ("Welcome Traveller!")
time.sleep(1)
def name_identify():
print ()
name_input = input ("What is your name? ").lower()
name_input = name_input.title()
time.sleep(0.75)
def name_confirm():
print ()
print ("So %s is your name then?" % name_input)
Where the questions such as
name_input = input ("What is your name? ").lower()
appear in a different colour, or bold/italic even. As things similar to
print ("\x1B[3mHello World\x1B[23m")
and
print ("\033[1;31m""Hello world")
don't work, I assume this function is not naturally supported, so I ask, if it is possible to either A, make it supported, so this method, or similar work, or B, another option which does make changes at least similar to what I seek?
It would be very helpful if anyone could provide me with a way to do this, or at the very least an editor which is close in simplicity (design wise) to IDLE and does support the functions I seek. The version of python I am currently using is 3.6.1.
Thanks in advance, and I apologise if my wording confuses you, just ask about what confused you and I will attempt to clarify. Using Windows with the Idle Shell.
Due to the limitations of some python environments, I just used Tkinter to create an interactive procedurally generated script which you can scroll along as if it were the shell, with the added bonus of adding pictures for more depth.
I know what you are going through right now, but there is no benefit to make text colored or bold in python without GUI. If somehow you manage to do it it will turn back to normal text when you make the file to exe format. I have wasted a week on this.
It only makes sense when you are reach GUI programming. Tkinter would be a good place to start.
Its does not matter on the IDE but on the compiler.
In tkinter its a matter of seconds
lab_practice = label(text = "practice",fg = "red#the foreground color",bg = "yellow",font = ("Arial",40))

Pygame Write to other terminal?

I was wondering if it is possible to write the pygame code to a separate terminal so that you can still do things like print to the terminal. When pygame's display becomes initialized it seems to be impossible to put any input into the terminal. Any way to get around this?
I also want to know that if this is possible can one the other terminal edit the one running pygame to change certain things?
Github
Ok, once you initialize pygame and start your pygame loop in startDisplay() in Commands.py, you are essentially leaving your main() loop in game.py. So your repeated request for input won't happen again. If you want to call for input during the loop in startDisplay() you'll need to do it expressly there. As I stated above, this will pause your game until you enter a command, which obviously isn't very good. You could build a little logic around it and only request input during a break in the action or implement a Pause event (using a key event) which would subsequently call the prompt for a command.

Categories

Resources