I’ve put together a working demo of real-time parsing of input for Inform 7, which gives the player feedback on how the game will understand what they type as they type it, including spell-correction via suggestions.
Some brief looking into this over lunch makes me think,yeah, character input is the way to go, so that when the player presses the space key I can use that input directly without having to start and stop the line-input every few milliseconds to see if anything’s happened.
That said, what I was doing was just using VM_KeyDelay() and I can probably smooth the whole thing out a bit by writing my own version which doesn’t turn off the character input event when it goes off to do some parsing.
The problem with using character input is that you’ll be emulating what interpreters do naturally, and you’ll never be able to emulate it perfectly. There’ll be some situation when it doesn’t work as people expect, maybe you won’t be able to select text, or move the cursor or copy a command. Using the Glk 0.7.1 features lets you use real line input while also intercepting it.
Line input has a couple of big wins - I like that the player could be continuing to type while in the background I’m doing some processing on what the last glimpse of the input line was. That feels smoother.
But I’m not sure how to best handle big changes between the old input line and the new, after a new “snapshot” is taken - particularly in handling the space-bar-to-accept-suggestions. What if they’ve deleted several characters and then pressed space? If I have to rerun the parser over the new input data it’ll be harder to optimise so probably slower; it might lead to the game making invisible suggestions because they’re only computed, and then written in, after the player has pressed the space key.
At the moment, I’m looking at using character input, and allowing command processing to be interrupted by the user pressing an additional key. Looking at it this way, it’s a real shame that glk_select_poll can’t recognise character input, as that would let me say “The user’s pressed something, get on with handling that” but without having the pause the gameflow to do that. (I can do something similar using a 1 millisecond timer and a normal glk_select call, but I can’t help feeling that introducing a deliberate delay is a weird way to speed things up.)
I’ll probably get the current version stabilised and out there, and then look at a line input rewrite and see how it goes. If checking for changes in the input line is really fast, then potentially I could use it as a glorified character input anyway…
I get a multisecond delay and spinning beachball after pressing return when running this second version in Firefox 3.6 (I’ve tried it on two Macs, one running 10.5.8, the other 10.6). I don’t see that issue in Chrome on either machine.
This post discusses ways to ascertain whether you are disambiguating or answering a yes/no question from within VM_ReadKeyboard():
An aside: You’ve already got pretty much got this completed, but if you were just starting, you might have founf the Glulx Input Loops extension useful (it lets you change the behavior of VM_ReadKeyboard pretty easily using I7 code).
Gargoyle maps the scroll wheel to keycode_PageUp / keycode_PageDown during character input. The function keys produce similar anomalies.
Also, unsurprisingly, Delete gets remapped to keycode_Delete, which then works like Backspace.
I’ve never understood why Glk fails to distinguish the two. Maybe I’m showing my age, but I haven’t used a computer where both were available and they didn’t work as expected. Of course, the Mac keyboard calls backspace ‘Delete’, which muddies the waters a bit, but the underlying functionality is the same: there’s a key that erases input to the left of the cursor, and possibly a key that erases input to the right of the cursor. It seems like we could add a keycode_DeleteRight without causing too much trouble.
With commands addressed to others (like “Anthuk, up”), the first word (the name of the person you address, e.g. “Anthuk”), is mapped to a verb (“attack” in the case of Anthuk). Adding a comma and a blank space will replace the comma with that verb (so "Anthuk, " results in "Anthukattack ").
“Anthuk,up” (without the blank) works as expected, though.