JSZM (JavaScript Z-Machine) (v2.0.3)

While ZORKMID will remain as my main Z-machine implementation (with debugging features), JSZM is a new one for uses when JavaScript is wanted; it is made at the request of someone else. It is in the public domain.

The back-end is written as a library which is pure JavaScript (ES6) and does not use DOM. You can then write front-ends for it using HTML, XUL, Node.js, Synchronet, or whatever you want to do.

Here is the complete code: http://zzo38computer.org/jszm/jszm.js

This program should work in any JavaScript implementations based on recent versions of Mozilla or V8 JavaScript engines (for example, Firefox, XULrunner, Node.js). Some implementations might not be completely compatible; if the implementation you use is not compatible, you should notify them to add ES6 compatibility to their implementation. (Synchronet currently uses an old Mozilla JavaScript engine; it should be usable if it is updated to use the newest Mozilla JavaScript engine, and a method is added to the File API to support loading/saving with ES6 ArrayBuffer.)

[size=85](I also intend to later work further on Famizork, which is the Z-machine implementation for Famicom.)[/size]

Does it work on older browsers if you run it through the Babel transpiler?

I don’t know; I have not even heard of such thing (I also don’t know if it will allow it to work with Synchronet and/or Windows Script Host). However, it might be slow and waste memory if compiled into a code which doesn’t use ArrayBuffer or stuff like it. But once the full codes are released, you are welcome to try it and report your results.

Note that the piece of the code shown above also shows some of the JavaScript features that it requires (including some new syntax features), so that may give you a part of the information you require. (It also uses strict mode, not shown above.)

(I am using Firefox to test it, although I also expect it to work with version 5 and newer of Node.js too (older versions of Node.js are probably not compatible). Other ES6-compliant JavaScript implementations should also be compatible.)

I am also writing a very simple HTML front-end, mainly for testing it; this front-end does not support split-screen, transcripts, or save games; JSZM does itself support these features though, and you may implement your own front-end which does, or modify the existing one.

Why are you only using one character long variable names?? There’s no reason at all not to use descriptive names.

As DataViews are now supported everywhere typed arrays are, you might as well use them, they will make it much easier for memory reads and writes.

Well, it is just how I program; I tend to use short names for local variables (although the variables in the “run” method do have longer names). I can add comments in case it is unclear (but it seems clear enough to me), although sometimes I also reuse local variables for multiple purposes (parseVocab uses “n” for two different purposes).

I am actually using DataViews; “this.view” is a DataView (and “this.mem” is a Uint8Array that views the same ArrayBuffer; both initialized in the “run” method). Note that there is a lot of code not shown in this small excerpt. (Also, “this.memInit” is not the same as “this.mem”; this is why the DataView methods are not used in the constructor function.) (The “get”, “getu”, “put”, and “putu” methods then wrap the DataView methods.)

If you have any further questions, comments, complaints, or whatever, then please mention them here.

I, too, occasionally use one-character variable names, especially on one-line callbacks. But I also never write code where a function-level variable is declared more than five lines above where it gets used, and I think the entire codebase for Improv has like two let statements in it and all the rest is const, so I feel like in my case it’s a justified Haskellism rather than obscurantist…

Well if you want anyone else to use the code then you should make it as straight forward as possible. And I’m not saying that short names must never be used (I’m sure we’ve all used i for a loop index), but it’s not others friendly when 90% of the variables are one character long.

And just make sure you’re not reusing variables with different types, as that makes it very inefficient.

The new version of does now have comments in getText explaining what each local variable means, and I think I am not reusing variables with different types, as far as I can tell. However, changes can be made later if needed. Also, the file does include documentation at the top about how to use it. I expect to post full codes soon (maybe in one or two days), and then further complaints can be made more precisely and I can know which to fix.

It seems to mostly work now, but there are still some problems. I am using ZORKMID (my interpreter in C) to help with debugging; I am finding it to be very useful for this purpose. (It was actually intended for debugging story files, although I am finding it much more useful for debugging interpreters. Why?)

Version 1.0.0 is now completed. http://zzo38computer.org/jszm/jszm.js

Nice project! I think I’ll have a whirl with working with it in node.js. Thank you. :slight_smile:

I think now that I have badly design the API.

Currently it works like this: The “run” method is a generator function that yields stuff directly, while functions defined by front-end are not generator functions.

Possibly the better way would be: The “run” method is a generator function that does not yield anything directly, but instead calls the front-end functions by “yield*” and then the front-end functions may yield stuff.

I think the more sensical ways to do this are not to use generators at all, but instead:

  1. The API takes a callback; whenever a step in the interpreting is completed, that callback is called with text to print and expected to return user input;

  2. The interpreter runs on a separate thread and talks to the front-end by IPC.

  3. is vastly preferable to all other options, but the ways you do multithreading on the browser as opposed to Electron as opposed to Node are not necessarily reconcilable, unfortunately.

I suppose it is another way, although I believe generators are easier to work with. (If the front-end wishes to implement split-screen, font changing (fix pitch and variable pitch), and/or transcripting, then this also becomes more difficult. There is also save/restore prompts.)

I did write a (not yet published) Node.js package which includes functions for dealing with curried-callbacks functions, including to convert the built-in Node.js stuff into curried-callbacks format, to convert promises into curried-callbacks format (and also the other way around), and to run a generator that yields functions that take a callback as their only argument. (This last way makes it possible to still use callbacks.)

That’s one reason why I won’t do it. (Furthermore, those aren’t the only JavaScript environments, and some might not even support multithreading.)

I expect I will keep version 1 as is (although perhaps fix bugs in version 1.0.1 or whatever, if any), but will make version 2 in the new way I suggested. I could even add convenience function to do it in the ways you have suggested too, if you would suggest how to deal with the problems I have listed.

(Also, eventually I will write XJSZM, which is ZIP/EZIP/XZIP/YZIP and therefore has a more sophisticated API, but is still with generators.)

If you have any other comments and/or complaints, then please write those on here too.

Version 2 is now released: jszm.js

Example of a simple front-end with Node.js: example.js

It now is using all generators, there are also a few bug fixed too. In addition, if “module.exports” exists it will export it so that it can be used with Node.js. If you have other suggestions for convenience functions and whatever else, then you could do so.

Sounds very interesting but I’m not been able to make this one work. I have tried with Firefox ~45 to 50, Chromium and Chrome on Ubuntu 16.04, using several .z5, with no luck.
Mmm… is it me?

It won’t work with any .z5 try with a .z3. Later I can make XJSZM which will support other Z-machine version too. Also, the API has changed since display.html was made (which didn’t work anyways), so try using the example front-end for Node.js which works better. You can also try to write your own HTML-based front-end; hopefully you know how to do it better than I do (I couldn’t get scrolling to work properly).

Version 2.0.2 of JSZM is now released, which fixes a minor bug with PRINTC and which now has documentation. (When XJSZM is released, it will be announced possibly on a different thread.)

Aaaaah. Yep! working with.z3. Looks promising.
I can’t see any problems with scrolling for now :slight_smile: I want to try on mobile…

Good work

A bug found by Daniel Lehenbauer (having to do with the REMOVE instruction) has now been fixed.

D. Lehenbauer has also made a version with several more enhancements at: https://github.com/DLehenbauer/jszm/tree/dev