PHP CLI - enter the user when doing something in the background

I am working on a game written in PHP and working in the console. Remember the old MUD and other text games, even some ASCII art!

Anyway, what I'm trying to do is what happens and also accepts user input.

For example, let's say that this is a dual-player game, and player 1 waits for Player 2 to make a move. This is easy to do just by listening to the message.

But what if player 1 wants to change some parameters? What if they want to see details about aspects of the game’s state? How about a game assignment? There are many things a player may want to do while waiting for their opponent to make a move.

Unfortunately, the best I have right now is the fact that Ctrl + C completely kills the program. Then the other player remains hanging until the connection is reset. Oh, and the game is completely lost.

I get user input with fgets(STDIN) . But this blocks execution until an input is received (which is usually good).

Is it possible that such a console program can handle both input and output? Or should I just look at another interface?

0
source share
3 answers

Sorry, Matthew, I have to refuse to accept your answer because I found it myself:

Use the following code to get user input while doing something else:

 while(/* some condition that the code running is waiting on */) { // perform one step or iteration of that code exec("choice /N /C ___ /D _ /T _",$out,$ret); // /C is a list of letters that do something // /D is the default action that will be used as a no-op // /T is the amount of time to wait, probably best set to one second switch($ret) { // handle cases - the "default" case should be "continue 2" } } 

This can then be used to interrupt the cycle and enter the options menu, or to trigger some other event, or even to use the command when used correctly.

0
source

In short, PHP was not created for this, but you can get some help from one of these extensions . I'm not sure how thorough they are, but you probably want to use a text library user interface. (And really, you probably don't want to use PHP for this.)

All that being said, you need to get non-blocking input from the STDIN character by character. Unfortunately, most terminals are buffered from a PHP perspective, so you won't get anything until a key is pressed.

If you run stty -icanon (or the equivalent of your OS) on your terminal to disable buffering, then basically the following short program works:

 <?php stream_set_blocking(STDIN, false); $line = ''; $time = microtime(true); $prompt = '> '; echo $prompt; while (true) { if (microtime(true) - $time > 5) { echo "\nTick...\n$prompt$line"; $time = microtime(true); } $c = fgetc(STDIN); if ($c !== false) { if ($c != "\n") $line .= $c; else { if ($line == 'exit' || $line == 'quit') break; else if ($line == 'help') echo "Type exit\n"; else echo "Unrecognized command.\n"; echo $prompt; $line = ''; } } } 

(It uses a local echo, which allows you to print characters as you type them).

As you can see, we just go in cycles forever. If the character exists, add it to $line . If you press enter, execute $line . Meanwhile, we mark every five seconds to show that we can do something else while we wait for input. (This will consume the maximum processor, you will have to release sleep() to get around this.)

This does not mean that this is a practical example in itself, but perhaps you will think in the right direction.

+2
source

You can create a game as you describe using ncurses (non-blocking mode) and libevent. This way, you are not getting close to CPU consumption. Processing individual keys is sometimes inconvenient (implementing Backspace yourself, this is not at all interesting), and did you know that different OSs send different key codes to Backspace?), And it becomes very difficult if you want to correctly support UTF-8. However, fully viable.

In particular, it is useful to make extensive use of libevent when reading both the network and keyboard input (stdin) with it. This function allows you to listen to individual keys: http://www.php.net/manual/en/function.ncurses-cbreak.php which can later be read using the libevent API. The key to keep in mind is that you will sometimes read more than one key at a time, and need to be processed (so go through everything you read). Otherwise, the user will be annoyed to see that not all keystrokes "reach" the application, and some are lost.

0
source

Source: https://habr.com/ru/post/1479951/


All Articles