RemGlk: remote-procedure-call implementation of the Glk IF API

RemGlk version 0.2.1
Designed by Andrew Plotkin (erkyrath@eblong.com)
Glk home page)

This documentation is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License.


What is RemGlk?

RemGlk is a C library which implements the Glk API. You can compile a Glk application and link it with this library.

RemGlk does not provide a user interface. Instead, it wraps up the application's output as a JSON data structure and sends it to stdout. It then waits for input to arrive from stdin; the input data must also be encoded as JSON.

RemGlk is therefore like CheapGlk, in that it works entirely through input and output streams, and can easily be attached to a bot or web service. However, unlike CheapGlk, RemGlk supports multiple Glk windows and most Glk I/O features. Whatever it's attached to just has to decode the structured output and display it appropriately.

RemGlk was designed to complement the GlkOte Javascript library. GlkOte more or less implements the other half of the job: it accepts game output (as Javascript objects), displays it, and then returns the player's commands in the same format. It should be possible to connect an IF interpreter, RemGlk, and GlkOte to build a complete IF web service.

Warning: this has not yet been tested in any way. This is an alpha release of RemGlk, and nothing is guaranteed.

While this is labelled "release 0.2", I may be fixing bugs and adding features iteratively in the near future. Or not. You are best advised to follow my GitHub repository for updates.

Using RemGlk

Starting up

Once you have compiled your application, run it as usual. For glulxe, this probably looks like:

glulxe Advent.ulx

If you do this, you will see nothing at first. The application is waiting for an initial input which describes the display and font sizes. Try typing this, exactly:

{ "type": "init", "gen": 0, "metrics": { "width":80, "height":24 } }

This tells RemGlk that it has an 80x24 "screen" to work with. The default "font size" is 1, so this gives the effect of an 80x24 terminal window.

If you instead entered:

{ "type": "init", "gen": 0, "metrics": { "width":400, "height":600,
  "charwidth":12, "charheight":14 } }

...you would get a layout for a 400x600 pixel window, assuming a 14-point font with 12-pixel-wide characters.

(The font size is only critical for grid (status) windows. You can approximate the measurements for buffer (story) windows; these typically have proportional fonts and perhaps various font sizes as well.)

The metrics object also allows you to specify margins and border spacing, which improve the layout behavior. See below for details.

Alternatively, you can specify basic layout information on the command line. If you type:

glulxe -fm -width 80 -height 50 Advent.ulx

...then the application will not wait for an init event. (And you should not enter one.) Instead, the game will start immediately (with an 80x50 "terminal window"), and send its first screenful of output.

The first screen of output

For Adventure, the initial output looks something like:
{"type":"update", "gen":1,
 "windows":[
 { "id":25, "type":"grid", "rock":202,
   "gridwidth":80, "gridheight":1,
   "left":0, "top":0, "width":80, "height":1 },
 { "id":22, "type":"buffer", "rock":201,
   "left":0, "top":1, "width":80, "height":49 } ],
 "content":[
 {"id":25, "lines": [
  { "line":0, "content":[{ "style":"normal", "text":" At End Of Road
     Score: 36    Moves: 1      "}]}
 ] },
 {"id":22, "clear":true, "text": [
  {"append":true},
  {}, {}, {}, {}, {},
  {"content":[{ "style":"normal", "text":"Welcome to Adventure!"}]},
  {},
  {"content":[{ "style":"header", "text":"ADVENTURE"}]},
  {"content":[{ "style":"normal", "text":"The Interactive Original"}]},
  {"content":[{ "style":"normal", "text":"By Will Crowther (1973)
     and Don Woods (1977)"}]},
  {"content":[{ "style":"normal", "text":"Reconstructed in three steps by:"}]},
  {"content":[{ "style":"normal", "text":"Donald Ekman, David M. Baggett (1993)
     and Graham Nelson (1994)"}]},
  {"content":[{ "style":"normal", "text":"[In memoriam Stephen Bishop
     (1820?-1857): GN]"}]},
  {"content":[{ "style":"normal", "text":"Release 5 / Serial number
     961209 / Inform v6.21(G0.33) Library 6/10 "}]},
  {},
  {"content":[{ "style":"subheader", "text":"At End Of Road"}]},
  {"content":[{ "style":"normal", "text":"You are standing at the end of
     a road before a small brick building. Around you is a forest. A small
     stream flows out of the building and down a gully."}]},
  {},
  {"content":[{ "style":"normal", "text":">"}]}
 ] } ],
 "input":[
 {"id":22, "gen":1, "type":"line", "maxlen":256 }
 ]}

This is just to give you a feel for what's going on. Roughly, this says:

(The window ID numbers will vary from run to run, by the way. Window rock numbers are consistent for a given game, but may vary from game to game.)

The first input

A human types "go east" into some user interface, which then passes the following input to RemGlk:

{ "type":"line", "gen":1, "window":22, "value":"go east"}

The library accepts this, mulls it, and generates a new output update. So it goes.

The Data Format

I have not written out this documentation in detail yet. Please refer to the GlkOte documentation. Input what GlkOte outputs, and vice versa.

Prior to version 0.2.1, this library used contents and inputs as the names of the top-level data fields, rather than the correct content and input. The prior version also omitted the xpos and ypos fields for grid window input.

A note on JSON: this is a strict (in both senses) subset of Javascript's data literal format. The biggest differences are: you always use double quotes, never single quotes; strings are always quoted, but numbers never are; an object (dictionary) always has quotes around its keys.

All input and output is UTF-8.


Last updated January 27, 2014.

Glk home page