Introducing the Å-machine

The Å-machine is a virtual machine for delivering interactive stories. It is designed for stories implemented in the Dialog programming language.

As the name suggests, the Å-machine is inspired by the Z-machine. The letter Å (pronounced [ɔː], like the English word “awe”) follows Z in the Swedish alphabet. In international contexts, å can be transcribed into aa, as in “The Aa-machine”.

The Dialog compiler can produce Å-machine story files starting with version 0g/01. The filename ending is .aastory. Support for the widely used and historically important Z-machine remains, and will not go away. But stories compiled for the Å-machine look better on the web, and are smaller and potentially faster on vintage hardware (the latter claim is unsubstantiated at the moment, but it has been an important design principle).

In a sense, the Å-machine is to Dialog what Glulx is to Inform 7. It eliminates the tight restrictions on story size, and extends the basic functionality with a carefully balanced set of new features. But the Å-machine is designed to run the same stories on everything from 8-bit systems to modern web browsers. Data structures and encodings are economical, and the overall word size has not increased. Large stories are supported, but small stories still have a very compact binary representation.

Compared to the Z-machine and Glulx, the Å-machine operates at a higher level of abstraction. This improves performance on vintage hardware, both by making story files smaller, which improves loading times, and by allowing larger chunks of computation to be implemented as native machine code. The downside is that the virtual machine is more tightly coupled to the idiosyncracies of a particular high-level language, in this case Dialog.

Currently, only a single Å-machine interpreter exists. It is implemented in pure javascript, and must be combined with a frontend that handles all input and output. Two frontends are provided: A web frontend based on jquery, for publishing stories online, and a Node.js frontend for running automated tests. A tool, aambundle, can convert an .aastory file into a web-friendly directory structure, including story and interpreter, ready for deployment on a server.

Release 3 of Tethered runs on the Å-machine.

This Cloak of Darkness implementation illustrates how to enhance touchscreen play with clickable links.

Browser compatibility is hard, and this first release already comes with a couple of known problems. Safari on iOS doesn’t adjust the window size when the on-screen keyboard appears, so for now only half the screen real estate gets used. Internet Explorer cannot save the game state or a transcript. Chromium on mobile devices somehow picks a slightly different font size for the paragraph that contains the input field. And I haven’t been able to get any screen readers to work.

I hope to address all of these issues eventually. Suggestions are welcome!

8 Likes

You’re free to take your own approach of course, but I wonder just how much would need to be added to Glk to implement your Å-machine features in GlkOte. Being able to leverage existing frameworks would help with compatibility, while extending Glk would let other authoring systems use the new features.

One thought for performance: no idea how big a change this would be, but if the opcodes which wait for interactivity (input, save/restore) could set a callback register and then stop processing rather than waiting, then that could allow for a lot of improvements. It’s not a pattern that Inform or Z-code/Glulx really support well, but maybe it could be with Dialog’s predicate design. Or it could be just as messy as with Inform. :slight_smile:

2 Likes

Hi Linus,

You’re efforts are nothing short of marvelous. You’ve written the foundation for an extensive IF language employing sensible design decisions.

You now go on to write a VM that sheds legacy limitations having an eye toward modern standards at the presentation level. Full CSS support? “Uh, yeah, nice.” It’s not a stretch, I believe that you’re a better software architect and developer than the vast majority even on your bad days.

I played ‘Tethered’ on the Å-machine through your Javascript interpreter. The ‘basic’ presentation looked inviting and unassuming; the introductory scenes pulled me in. I finished your game in roughly three hours. The game’s length is perfect, a kind of quality “beer and pretzels” experience as they say in American English parlance.

By the way, here’s what I liked most (no spoilers):

  • In two points in the game I knew I had to perform fairly complicated tasks. “Oh, boy,” I thought, “here we go” but it wasn’t like that. By the first action I took you automatically completed the task for me without giving away the challenge

  • Your clever use of foreshadowing

  • Multiple ways to figure out just what the heck is going on

Also, I find myself amused thinking I found a bug in your game–I didn’t. :slight_smile:

I suppose the following may be interpreted as feature requests but I know you’re busy (see "good design decisions above) so I suppose I’m simply asking for your thoughts:

  1. The concept of travel connectors in Dialog.

Travel connectors are neat as they provide the author all kinds of hooks for conditioned narratives at each point of travel including, " describeDeparture, describeArrival, TravelMessage, etc. I kind of think of travel connectors as ways to author the “sticks” between locations found on most IF maps.

  1. XHTML links/Javascript Hooks

Dialog, in my opinion, would be greatly served by an ability to call Javascript routines from directly within the Dialog code and receive objects back from said routines. This may range from a simple button to a MongoDB query to current GPS coordinates

  1. Ability to split project into multiple makefiles, i.e. one file per room

I commend you on your efforts (and so nice, too!). What are your thoughts?

4 Likes

I don’t think Dialog has any precise equivalent to describeDeparture and describeArrival, but that is partly because it doesn’t yet have a very sophisticated set of predicates dealing with NPCs (which I think they are mostly for). It does however have a pretty straightforward equivalent to TravelMessage: (narrate leaving $ $). So, suppose you had a room (#room) with a description like this:

You are in a clearing at the bottom of a cliff. Steep steps lead north up the cliff. A broad path, almost obscured by leaves, goes west.

You could then have “travel messages” like this:

(narrate leaving #room #north)
     With great effort your pick your way up the steep track.

(narrate leaving #room #west)
      The leaves rustle under your feet as you walk along the path.

The other concept in Dialog’s standard library which resembles TADS’ travel connector is (door $). Doors work not just for typical open-or-close-doors, but for any sort of “connection” which can block access.

3 Likes

This is a nice suggestion. The javascript engine has an i/o interface, and it could indeed be possible to implement a GlkOte frontend. I’ve been meaning to write an interpreter in C, once the Å-machine specification feels stable enough, and for that I would definitely use Glk. I’ll look into GlkOte as a potential long-term option. Still, right now I think it’s probably less trouble to fix the outstanding issues with the current javascript frontend than to make a new one.

The short answer is that it would probably be equally messy. I’m not sure how it would improve performance. I know parchment does just-in-time transpilation; is that what you had in mind? I don’t think that technique would have a comparable impact on Dialog code, since there isn’t a one-to-one correspondence between predicate queries and function calls.

Thank you very much for the praise! It makes me warm and happy inside.

Thanks also for the nice feedback on Tethered!

I’ll note, for the record, that “full CSS support” may be a bit of an overstatement. All CSS properties are indeed forwarded to the web browser, but only if the player decides to use a javascript interpreter. The Å-machine will eventually run on 8-bit hardware, presumably without much CSS support at all, which is why the Dialog manual specifies that all style tags are hints, and can be ignored by interpreters.

I concur with @PaulS that (narrate leaving $ $) provides some of the functionality. There’s also (narrate failing to leave $ $). I also concur that more thorough NPC handling would have to be in place before travel connectors could be supported to a wider extent.

But I fully agree that the liminal spaces between rooms are an important part of parser game geography, and deserve attention both at the story and library level.

I am wary of this. All web-related functionality (currently CSS and hyperlinks) is optional for interpreters, and the manual makes a point of telling the author not to rely on it. This is to ensure that Dialog games will remain playable for a long time, as Inform stories have been (and still are). Platforms and features come and go. Javascript changes all the time, and browser compatibility is frankly a mess. Hence the need for a simple, consistent, well-specified interface to carry the actual story, with an optional layer of bells and whistles and graphical presentation on top. As soon as there is a way for the actual game logic to escape into the presentation layer, then forwards and backwards compatibility is compromised. Would you trust a Vorple game to be playable in ten years? Twenty? What about a plain Z-machine game? And if story code has direct access to network communication, that opens the door for online-only games, and those are even more ephemeral.

This would have to be balanced against the need for a strict ordering of rule definitions. There is currently no limit on the number of source code files in a project, but it is critically important to always provide their filenames in the same order on the commandline. The rule definitions in earlier files supersede those in later files. Therefore, in my opinion, it seems sensible for authors to restrict themselves to one file of story code, one file of library code, and possibly one or two small configuration files that go at the very top, controlling global options (e.g. is this a debug build, or a pre-release for testers) that the story code can react to. But there is no technical limitation.

If you are thinking of incremental builds, I’m afraid performance would suffer too much. The full source code is required in order to determine which predicates are dynamic, which can be invoked using multi-queries, which are known to fail or succeed, what words might refer to which objects, and so on, and all of this information is crucial for generating sufficiently fast and compact Z-code (or Å-code for that matter).

All in all, your suggestions have been food for thought. I have attempted to clarify the reasoning behind some of my design choices. But Dialog is still in beta, and a lot could happen before it stabilizes. That evolution will certainly be influenced by thoughtful comments such as yours.

2 Likes

Yeah I was thinking in terms of a JITting interpreter. But also from my experience with Emscripten - which is less necessary seeing as you’ve already provided a JS terp. So it probably won’t actually be an issue.

Å-machine release 0.2 contains the following changes:

Javascript engine

  • Bugfix: Runtime error handler can now use undo.

Web frontend

  • Improved screen reader support.
  • Now possible to save gamestate and transcript in Internet Explorer.
  • Text selection now works, for copy-paste.
  • Support for logging to a remote server.
  • Progress bars are displayed correctly.
  • Simplified the HTML wrapper by moving most of the initial document structure to javascript.

The specification is still at version 0.1.

2 Likes

Will A-machine support html type hyperlinks to external resources? (now or in future releases)

For example a link to a photograph or additional optional narrative?

Thank you,
Jeff

Yes, I have some plans for this. But it needs to be designed carefully, to blend in well with the rest of the language, and to encourage (as far as possible) self-contained games that can be archived.

1 Like

Very good news. My use for limited external links involving photographs and possibly audio as a post lesson clarification in an educational based project.

Thank you,
v/r
Jeff

The Å-machine toolkit version 0.2.1 has been released. This includes version 0.2 of the specification, and updated versions of the Å-machine toolchain and official Javascript interpreter.

From now on, the version number has three parts. The first two are equal to the specification version, and the third gets incremented when the tools are improved without changing the specification.

Changes introduced in version 0.2 of the specification:

  • Support for external resources (e.g. embedded graphics and external link targets).

  • Ability to check at runtime whether the interpreter supports quitting.

Changes introduced in version 0.2.1 of the web interpreter:

  • Support for embedded images, downloadable feelies, and external links.

  • Added “restart” and “save story file” menu items.

  • Don’t move focus to the input element if the last command was clicked. Only do it if the last command was typed.

Changes introduced in version 0.2.1 of the Node.js interpreter:

  • Slight modification to the word-wrapping code, to ensure compatibility with dgdebug and dumbfrotz.
4 Likes

The Dialog system is amazing. Its features keep moving toward things that will find most useful. In this case, the availability of external links will be most useful in education applications that I have in mind for special needs students.

Thank you,
v/r
Jeff

If there is a Jesus, he must be Linus.