Found: Qt Glk / RemGlk app

#1

I have found this code form David Fletcher:
bubblycloud.com/qglk/

A port of the Glk library to Qt, even a bit old, the build should work.
I couldn’t compile it on Ubuntu and it might be helpful an upgrade to QtQuick.

Edit: to make clear this is not my code.

#2

It would be nice to see these modernized, along with Glk for SDL called NanoGlk that is out there too… it needs updating from SDL 1.2 to SDL 2.0.

#3

:slight_smile: so many interesting projects

#4

I tried it, there was a binary for i686 Linux and it worked.
However, after Gargoyle’s smooth fonts I couldn’t stand how it displays the text.
QTads seems to look better in comparison.

#5

Thanks for the note. I have to make a list of projects :slight_smile:

#6

I’ve started to prototype a QT 5.9 Glk app built on top of RemGlk JSON instead of the lower level direct Glk like David Fletcher’s effort. The primary advantage I see with levering RemGlk as a middle layer is that it presents Interactive Fiction turns as frames of changes (RemGlk generations) instead of having to wrangle a bunch of string streams on a character-by-character level.

(Andrew Plotkin) #7

I’ve found that you always want a middle layer that collects generations of changes. (iOSGlk is built this way.) Just a question of what language you write it in.

(jkj yuio) #8

I already started a remglk back-end for brahman (qtquick 5.9 codebase). I agree the Json interface is a better plan than going direct.

The problem was how to step up the rich integration over just text. For example, access to the world model. can remglk, or an adaptation thereof, return a list of items carried for example. How would the front end go about querying the known map is another problem.

I don’t have answers to these for glk, so i stopped.

#9

Anything to share?

I don’t think any Glk does what you are seeking. Glk, as far as I have experienced it, does these things: character output to the player, input of the next command (“go north”), mouse clicks, hyperlink callbacks, sound start/stop, a single timer (tied to the input, a kind of auto-input time event), and graphics assets references based on an index, saving and reading data files, filename dialog triggering, window open/close/size/position (for graphics or character output).

There is no concept of “intelligence of IF related to the story” in Glk - it doesn’t know the name of the player, no idea of the story author’s name or copyright, it doesn’t know the room the player is in, it doesn’t know the inventory, it doesn’t know the map, it doesn’t know the score of the game, it doesn’t know when a user enters or exits a room, it doesn’t know if an item is picked up or dropped, it has no idea of what commands are valid to input in a room (input hinting). All that is outside of the “low-level” scope of what the Glk API defines and I would say at a more “intelligent” or “smart” level of IF awareness of “objects” and “story events”.

That’s been my experience at least.

(jkj yuio) #10

The plan is to open source our codebase. Right now, there’s not a lot in the way of documentation. I’d also like to work on a more stable front-back interface before publishing it, which brings me to the second issue; interfacing to backends like remglk.

You are right that there is no glk way to get to this “inside information” (as far as i know).

Is it possible to make an I6 extension that provides calls that can be made to determine these things. I am presuming that almost every game uses the standard library together with some extensions. To that extent, there is a defacto “standard” world model.

For example, all games use the same way of “knowing” what the player is carrying. This data could be exported with a custom extension. could it?

Now, whether that goes through GLK or around it is another question. For one thing, i like the idea of using a JSON interface, so if it could be passed through remglk, that could work.

So, in general, the problem is to;

design and define a standard JSON information interface schema.

To cover what i have so far, I’m currently using JSON interfaces (with WIP schema) for;

  • the sidebar (inventory, things worn, carried in hand, icons, colors, people met, things known etc.)
  • the map (known locations on a grid, box size, color, text in box, exits).
  • options in (means to pass generic information, eg game difficulty)
  • options out (game controlled color theme, story meta data, cover page content, credits etc.)
  • choice box (choices, greyed-out choices, presentation style etc).

These are by no means final nor complete. I would welcome the idea of exploring the possibilities here.

#11

Vorple is an example of an Inform set of extensions that go “out of band” of Glk by writing Glk files to disk that are then processed by a secondary user interface system.

I wish Vorple would create empty Glk windows and stream to them instead of the file to disk approach. Streaming to a Glk window (rock) is the approach that FyreVM extensions take. Writing to a window already works well with RemGlk data stream to JSON. Vorple has proven trouble for me as RemGlk doesn’t expose when a file is closed and so far it seems to me that’s a critical event to know - as the secondary user interface system (Smart IF interface above Glk) needs to know that Vorple just created one of it’s data-sharing files.

(jkj yuio) #12

I agree, it should not write to files.

Is it possible to “call into” something within the engine. Does anyone do this? One way to (sort of) do this would be to have “secret” commands that are sent to the parser.

At first, i thought this would be a neat approach (ie commands), but i ran into problems. Pretty soon you need to send in somewhat esoteric information, and then if you’re using JSON out, you may as well use JSON in.

The other issue is which things are synchronous and which are not;

For example, i found i could host choice systems synchronously, but parser systems often need to be in their own thread. So calling in has a sync problem. In some cases you call in, and later the engine emits an answer via a JSON channel (I used channels instead of windows, but it’s similar).

But for some, you want to return the result synchronously.

(Andrew Plotkin) #13

I agree that this is what you want to do. The important point is that this is an interface between the game code and your customized interpreter. You can either bypass Glk (as Vorple does) or create a very simple Glk extension call which passes the information up and down.

(To be fair, a “very simple Glk extension call” can be somewhat complicated to implement, especially if you want to build a new stream type. There’s a fair amount of boilerplate in GlkOte/RemGlk/etc around stream handling.) (But once it exists, calling it from I6 is very easy.)

You can send custom Glk events. These are handled by the game like any other input events (keystrokes, hyperlink clicks, etc).

Don’t rely on synchronous communication. Always assume that you’re firing events in and stuff will come out “later”. In normal operation that will be fast enough, and if it fails, it’s a symptom of something worse going wrong.

(Andrew Plotkin) #14

The other way to do this is to inspect VM memory directly while the game is waiting for input. This is how I did the dynamic map in the Hadean Lands apps. It’s a giant pain in the ass to set up; the advantage is that it requires no game code at all.

#15

Made some progress. I have very stable Qt input/output of the JSON exchange via RemGlk on Linux desktop app (Ubuntu 17.04). Started to format the text styles Glk requires. Here is a screen shot of Emily Short’s Bronze story opening:

#16

Request for help: It would be great if someone could create a GitHub project to build all of the Gargoyle interpreters as independent binaries linked with RemGlk instead of GarGlk. Probably ideal to output all of the various terp binaries to a single folder so it can be listed (ls) for available engines. Example output binaries: binTerps/Git_remglk binTerps/Glulx_remglk binTerps/ScottAdams_remglk etc.

#17

Yes! I managed to get cross-compile RemGlk+Glulxe interpreter for Android and to be able to get Qt Creator to automatically put this binary into the Android APK - and figured out the magic path for Qt to launch the console executable for the stdin/stdout interchange. It isn’t pretty, but here is a screen shot of a 5" Android phone running Bronze:

The Qt controls don’t look good on Android, the QComboBox are truncated in height, the scroll bar of the window is a massive thick thing on the right side. However, this problem exists on standard Qt 5.9 Example apps - so hopefully there is information out there to improve the appearance. Right now this is entirely identical code for desktop and Android except for a couple path references. That was my main motivation - to have a code base that was nearly identical for desktop and mobile.

(jkj yuio) #18

I had to make all my controls in QML, so that they could be the same and work for mobile.

In particular it was very important to ensure that everything scales to DPI. In other words, all my UI controls must support arbitrary scaling.

With QML in the picture, your architecture breaks down into 3 main parts:

  • the QML front end
  • the game engine back-end
  • the middle bit.

The “middle bit” i call the “API” which is the glue between the QML and the engine. You have a trade-off with functionality; you can either write logic in javascript and put with the QML, or you can write in C++ and put it in “the middle”.

I prefer the keep the QML + JS thin, but i know a lot of people like JS, so it’s a matter of preference.

#19

That’s really cool. Any code you could/want to share?

#20

To me the easiest is designing all I can as svg.