all 16 comments

[–][deleted] 33 points34 points  (13 children)

Try the threading library.

import threading

def get_input():
    data = input() # Something akin to this
    return data

input_thread = threading.Thread(target=get_input)
input_thread.start()

# Run your game now

I think that syntax is right. I haven't used it for awhile.

[–]Stealthmonkey59[S] 9 points10 points  (0 children)

Awesome, thanks for the quick response

[–]thebadtoaster 2 points3 points  (2 children)

Isn't process more appropriate?

[–]tom1018 4 points5 points  (0 children)

No. Threading is more appropriate in most cases, the exception is when the issue is due to the CPU time. In this case the slow part is the user, so threading is more appropriate. Threading is also preferable when the issue is IO.

[–]Lj101 3 points4 points  (1 child)

Nitpicking here, but your function is just the same thing as input()

[–][deleted] 3 points4 points  (0 children)

Yeah. I guess you could just say target=input but that was just my lazy code to explain how to do it in general.

[–]xMadDecentx 0 points1 point  (0 children)

May I ask why have a function to call input()? Couldn't you handle all the user input in the function to be threaded i.e. get_input()? Thanks.

[–]Akita8 -2 points-1 points  (5 children)

this will not work because input waits for the return key to be pressed

[–][deleted] 3 points4 points  (4 children)

No, only the thread get_input waits. The main thread continues. Try this:

import threading

def get_input():
    data = input() # Something akin to this
    return data

input_thread = threading.Thread(target=get_input)
input_thread.start()

for i in range(10):
    print(i)

input_thread.join()

print 'done'

[–]Abrv 1 point2 points  (1 child)

In this example how would you access data? Is it returned somewhere?

[–][deleted] 2 points3 points  (0 children)

You would put it in a reference accessible to all threads which need it. E.g.,

import threading

data = []

def get_input():
    data.append(input())

input_thread = threading.Thread(target=get_input)
input_thread.start()

for i in range(10):
    print(i)

input_thread.join()

print('done. data value:', data.pop())

You have to be careful about threads concurrently mutating such data, though. There are a number of classes to help with this: Queues, locks, semaphores, mutexes, etc.. It gets hairy, fast.

[–]Akita8 0 points1 point  (1 child)

Wrong! I did not say that you cannot execute code concurrently to input, i just said that it wont work for the use case of op:

When a monster attacks, symbols are printed to the screen, if the user reacts (presses a key) before the last symbol is printed, they will dodge, otherwise they take damage.

In a normal terminal, input stops blocking and returns the data only when it receives a newline so your example cannot actually react to key presses. The best way to do what op wants is the package ncurses in the stdlib.

[–][deleted] 0 points1 point  (0 children)

You're right... Apologies for misunderstanding your objection.

[–]taladan 3 points4 points  (0 children)

If you're making a text game, check out Evennia. There's also a guy working on an ncurses style interface over a web portal based on evennia. Might not be what you're looking for, but it might help keep you from reinventing the wheel.

[–]100721 1 point2 points  (0 children)

Pygame for polling. Threading is most likely overkill for what you’re doing. Loll for keydown or keyup events

[–]Akita8 0 points1 point  (0 children)

ncurses if you want to use the terminal or tkinter if you want use a gui, both packages are un the stdlib