Capabilities testing

Imagine you have a game set in an Old West town, and when the protagonist enters the town he passes a sign saying "Dead Dog, Kansas, Population 213" in faded paint on weathered, shot-up wood. The player doesn't know that's what it says until she types "LOOK AT SIGN", however -- the description of the room just has the line "You see a sign here" or some such to indicate it's there. And let's say you also have a great picture of a weathered sign that's had a couple run-ins with a shotgun. Ideally, you'd like to display the picture if the player's interpreter can handle graphics, or print a paragraph describing the sign if not. This is what glk_gestalt() is for.

There are over a dozen things you can test for. In this case, the constant to use would be gestalt_Graphics, and the sign object might look like this:

   Object sign "weathered sign"
      with name 'weathered' 'sign',
         description [;
            if (glk_gestalt(gestalt_Graphics, 0)) {
               ! insert code to display the picture of the sign here
            else "The sign says ~DEAD DOG, KANSAS, POP. 213.~ Or maybe
               that's supposed to be 2130, or 21,300 -- someone's blown
               off the corner of the sign with a shotgun.";
      has static;

(Note the 0 in the glk_gestalt call -- it's mandatory. glk_gestalt takes two arguments, even in cases where the second one doesn't do anything.)

Here are the various constants you can use with glk_gestalt:

Constant 2nd arg What it returns
gestalt_Version 0 A 32-bit number with the Glk version number encoded in it (first sixteen bits = major version number, next eight = minor number, last eight = sub-minor number, so 0.6.1 would be hex 00000601.)
gestalt_CharOutput the character code to test (footnote) This is for checking whether a particular character (like an "n" with a tilda over it) can be printed on the player's platform. It'll return one of three constants: gestalt_CharOutput_ExactPrint if it can, gestalt_CharOutput_CannotPrint if it can't, or gestalt_CharOutput_ApproxPrint if it'll swap in something else (like regular "n" for n-with-tilda, or "ae" for ae-with-ligature.)
gestalt_LineInput the character code to test As above, but for whether a character can be accepted during line input (ie, input that is processed after Enter is pressed.)
gestalt_CharInput the character code to test As above, but for whether a character can be accepted during character input (ie, input that is processed one keystroke at a time.)
gestalt_MouseInput the type of window to test 1 if mouse input is supported, 0 if not.
gestalt_Timer 0 1 if real timekeeping is supported, 0 if not.
gestalt_Graphics 0 1 if graphics are supported, 0 if not.
gestalt_DrawImage the type of window to test This is to test specifically if images can be placed in a particular sort of window (wintype_TextBuffer or wintype_Graphics). 1 if they can, 0 if not.
gestalt_GraphicsTransparency 0 This tests whether PNG images with transparent areas will actually appear with the transparency gimmick working like it's supposed to. 1 if so, 0 if not.
gestalt_Sound 0 1 if sound is available, 0 if not.
gestalt_SoundMusic 0 1 if MOD sounds can be played, 0 if not. (This may be 0 even if glk_gestalt(gestalt_Sound, 0); returns 1 -- in that case, only AIFF sounds are supported.)
gestalt_SoundVolume 0 1 if glk_schannel_set_volume() is supported, 0 if not.
gestalt_SoundNotify 0 1 if the HandleGlkEvent() can run customized code the moment a sound finishes playing, 0 if not.
gestalt_Hyperlinks 0 1 if hyperlinks are supported, 0 if not.
gestalt_HyperlinkInput the type of window to test 1 if hyperlinks are supported within a particular type of window, 0 if not.

The sections that follow will explain how to take advantage of these capabilities -- but as you read these sections, remember that before you can display graphics, or play music, or declare a hyperlink, or what have you, you should first use glk_gestalt() to check if the player's interpreter can do those things. If not, you need to make alternative arrangements -- text descriptions of images, that sort of thing -- or at least display a message telling the player what capabilities her interpreter needs to have before she can use it to play your game. Ideally, you want to do a gestalt check every time you use one of Glk's optional capabilities -- if you just run the check in Initialise(), you're setting yourself up for problems if, say, the player starts a game on her ritzy desktop machine, then saves the game and loads it up on her Palm device to play on a plane later. (This doesn't necessarily mean typing a lot of glk_gestalt() calls yourself -- you might, for instance, create a MyGlkImageDraw() routine that performs the relevant gestalt checks and then draws the image the way you want.)

Next section: Glk windows
Subsection: (footnote on character codes)
Or return to the table of contents