#FLOO

# model.floo: Model program for Floo, using Glk.
# Designed by Andrew Plotkin <[email protected]>
# http://www.eblong.com/zarf/glk/floo/index.html
# This program is in the public domain.

# This is an even simpler model of a text adventure which uses the Glk API.
# It is written in Floo. If you don't know anything about Floo, start with
# the fact that it's all reverse polish.

# Define an input buffer.
/inbuffer 80 string def

# Define a procedure to draw the status line.
/draw_status_line {
   # Only proceed if there *is* a status line.
   statuswin 0 ne {
       # Set and clear the window
       statuswin glk_set_window
       statuswin glk_window_clear
       # Define a string to put in the window
       /statusstring "Welcome to Floo" def
       # Compute the width of the window...
       statuswin true false glk_window_get_size
       # ...and then compute (win-strlen) / 2.
       statusstring strlen
       sub 2 idiv
       # Move the cursor and print.
       statuswin exch 0 glk_window_move_cursor
       statusstring glk_put_string
       # Reset the window.
       mainwin glk_set_window
   } if
} def

# Now the actual program begins.

# Open the main window.
0 0 0 wintype_TextBuffer 1 glk_window_open
/mainwin exch def

# If we couldn't do that, forget it.
mainwin 0 eq {
   glk_exit
} if

# Open the status window.
mainwin
winmethod_Above winmethod_Fixed or
1 wintype_TextGrid 2 glk_window_open
/statuswin exch def

# Set the current stream to the main window stream.
mainwin glk_set_window

"Welcome to a simple sample parser in Floo.\n"
glk_put_string
"Type \"help\" for the short list of commands.\n"
glk_put_string

# Begin the program loop.
{
   # Draw the status line, and then print the prompt.
   draw_status_line
   "\n>" glk_put_string
   # Request a line of input.
   mainwin inbuffer 0 glk_request_line_event

   # Here's the event loop.
   {
       glk_select /ev exch def
       # ev is now a four-element event array: [type window val1 val2]
       # Define evtype to the first element (type)
       ev 0 get
           /evtype exch def
       # If it was a line input event, exit the event loop.
       evtype evtype_LineInput eq { exit } if
       # If it was a window-arrangement event, redraw the status line.
       evtype evtype_Arrange eq { draw_status_line } if
   } loop

   # Trim the buffer down to the returned length.
   inbuffer  ev 2 get  0 put

   # Parse the buffer, very simply and stupidly.

   inbuffer "quit" eq {
       "Thanks for playing.\n" glk_put_string
       glk_exit
   } if

   inbuffer "jump" eq {
       "You jump.\n" glk_put_string
       continue
   } if

   inbuffer "help" eq {
       "This is an even simpler model program.\n\
HELP: Display this list\n\
JUMP: Jump.\n\
QUIT: Quit.\n" glk_put_string
       continue
   } if

   inbuffer "" eq {
       continue
   } if

   "I don't know the command \"" glk_put_string
   inbuffer glk_put_string
   "\".\n" glk_put_string
} loop