Newsgroups: rec.arts.int-fiction
Path: nntp.gmd.de!news.ruhr-uni-bochum.de!news.rwth-aachen.de!uni-paderborn.de!fu-berlin.de!news.belwue.de!swidir.switch.ch!in2p3.fr!univ-lyon1.fr!howland.erols.net!newsfeed.internetmci.com!in1.uu.net!netnews.worldnet.att.net!cbgw2.lucent.com!nntphub.cb.lucent.com!alice!allegra!ulysses!netnews
From: eostrom@research.att.com (Erik Ostrom)
Subject: non-blocking keyboard input (was Re: Why you must use Prolog)
Sender: netnews@ulysses.homer.att.com (Siva P Misra)
Message-ID: <DzuK99.9zu@ulysses.homer.att.com>
Date: Fri, 25 Oct 1996 19:46:03 GMT
References: <54g91v$j2q@prometheus.acsu.buffalo.edu> <baf.845936561@max.tiac.net> <erkyrathDznnEK.D1L@netcom.com> <DzoCLq.8A@ladle.demon.co.uk> <54j5l8$c1@prometheus.acsu.buffalo.edu>
Organization: AT&T Bell Laboratories, Murray Hill, NJ 07974
X-Newsreader: Forte Free Agent 1.0.82
Lines: 90

goetz@cs.buffalo.edu (Phil Goetz) wrote:

>John Hartnup  <slim@ladle.demon.co.uk> wrote:
>>Another thing to bear in mind: when would NPCs be allowed to "think",
>>"plan" etc... do these goal-analysis computations occur in normal
>>game computation time (i.e. between when you press "enter" and when
>>the game's response appears), or should they occur in the background,
>>calculating while the prompt is waiting for input?

>This is an excellent idea.  It would be impossible to implement without
>using operating-system-specific calls, I think.  Prolog doesn't have
>(at least not that I've seen) any way to check the keyboard for input,
>and then return if nothing has been typed.  Once you ask to read
>the keyboard, you have to wait until someone types something.
>How does Inform handle this?  It must, because I saw Tetris in Inform.
>Does it use machine-specific opsys calls?

I'm no Inform expert, but after a little digging in some manuals and
the Freefall source code, here's my educated guess:

  * Inform doesn't provide any particular support for this, aside from
    access to the Z-machine opcodes.

  * Z-machine assembly language includes an opcode "@read_char",
    which waits for a character to arrive, and reads it.  Every so
    often (as specified by a timeout parameter, in tenths of a
    second), it calls a specified function if no input has yet
    arrived.  If this function returns true, @read_char exits without
    having read a character.  So you can implement roughly what you
    want by writing a timeout function that sets a global variable and
    then returns true.  (The global variable is to indicate to the
    rest of the program that no character was read.)

  * Z-code interpreters implement this opcode in whatever way
    their designers felt would be best.  If they're using a language
    that provides support for this sort of thing, they may use the
    language facility.  Otherwise, yeah, here's where the OS-specific
    calls probably creep in.

I believe that if you write in Inform/Z-code, you _can't_ call any
OS-specific routines directly, even if you want to.  Credit where it's
due:  The mechanism described for doing this with the Z-machine
is lifted directly from Andrew Plotkin's _Freefall_, modulo
transmission errors on my part.

>RANT ON
>This really annoys me -- I have never seen a programming language that
>had a primitive for checking for keyboard input but not waiting for it.
>This is an important operation, but language designers never put it in,
>so it makes all realtime code un-portable because it has to use OS calls
>to read the keyboard.  X-Windows can do it, and I think curses (the C
>library, not the game) can, but they don't count.
>RANT OFF

Offhand, I've got a few answers to this one:

  * The Scheme standard includes a "non-essential" procedure,
    "char-ready?", which indicates whether or not a character is ready
    on a given input port.  (The keyboard would be an obvious input
    port for a Scheme implementation to provide.)  Once your program
    knows there's a character ready, it can call "read-char" to get a
    character of input without blocking.

  * In a language that provides threads, there's another solution:
    Launch a separate thread whose only job is to read the keyboard
    and store input in some buffer that the rest of the program can
    get at.  If your keyboard-reading thread blocks, it's no big
    deal--it hasn't got anything _else_ to be doing.  If another
    thread wants to see if there's any input available, it just (with
    some appropriate synchronization) checks the buffer and takes
    a character if available.  Modula 3 and Python are two of many
    examples.

  * Tcl allows you to specify a function to call whenever input is
    available on a given I/O stream.  With that, you can use the
    same buffer strategy that you would use with the more general
    mechanism of threads.

  * Finally, I'm not sure why libraries don't count (it's so hard to
    draw a line between language and library), but both Tk and
    Java's AWT provide facilities similar to the Tcl model, but
    for input events (keyboard and other) rather than I/O streams.

Of these, Scheme probably comes closest to what you asked for.
Threading might be better for the NPC computation problem, though.

--Erik
  (not that you asked for this much detail)


