I have some ideas for an IF game that can’t be completely implemented inside of standard IF engines. Imagine, for instance, that a core part of the game requires the player to actually sit down and play poker with NPCs, and that I have code that implements a poker AI. I can imagine several ways that this could be done, and I’ve listed them in order of desirability for me. What game engines would support each of these approaches? Are there other ways that I’m not thinking of?
Game engine has an FFI that allows us to make a call into a poker.dll. Presumably, it has a command in the scripting language to initiate these calls.
Game engine is open source and written in a language I know and can extend directly, or in a language with an FFI.
Game engine allows calling external HTTP APIs. (This is the least desirable option, as I’d like to distribute the resultant game.)
You could write a poker AI inside of TADS 3, no problem. No need for the fancy extensibility.
Most IF games come in fairly innocuous forms: HTML with JavaScript (Twine etc), or specialised mini VMs for IF (Inform or TADS 3). They are quite capable, but aren’t the full shebang of raw code with FFI. This is a positive - you can share the games without as high a risk for viruses, machine incompatibilities etc
First things first—are you looking for a primarily parser-based system, or a primarily choice-based system? Many systems can do both, nowadays, but they’re still focused on one or the other: it’s a lot easier to write a parser game in Inform and a choice game in Twine than vice versa (though not impossible).
Making calls into a DLL: most systems actually don’t do that, because cross-platform support is highly valued. Off the top of my head, I can’t think of any. IF also usually isn’t distributed as platform executables, which helps security-wise.
FFI: Inform and Ink both support this. Dialog and ChoiceScript don’t, by design (to maximize portability). TADS doesn’t (to my knowledge?), but is such a fully-featured language that you can generally implement anything you want within TADS.
Engine is open-source: Basically every IF tool is, now. Inform was the big exception, but it open-sourced a while ago. Note that TADS does not allow derivative works, and ChoiceScript allows derivative works but doesn’t allow them to be used for any commercial purpose. Twine deserves special mention for being basically a macro language whose output runs in a web browser, so most Twine coding is literally JavaScript—adding new features to it isn’t considered “modifying” Twine so much as just using it as intended!
External APIs: Very few do this. The ones that do are generally the ones whose output runs in a web browser and let you call arbitrary JavaScript so you can use AJAX or what-have-you.
If you’re interested in choice-based IF then the correct answer here is probably Ink. Unlike many of the other IF tools, it’s explicitly intended for use as middleware in a larger game, with (open source) extensions available for all the major game engines (Unity, Unreal, Godot), plus a JS port so you can embed it into any arbitrary web app of your choice, plus ports to various other languages as well.
A core belief I have in designing Sharpee is that having an IF platform built on a common language like C# and platform like .NET Core will enable a lot of programming solutions no one would try on an IF-specific VM based platform.
There really is no technical need for a VM anymore. Sharpee will be able to run as WebAssembly in the browser.
I’m not the first person to believe this. People have used all sorts of languages in the past. But C# is now very modern and cross platform with generics and Linq which elevates it well beyond anything in the IF world.
I suppose an embeddable IF “library” is one option I didn’t think of, and it sounds like Ink is kind of like that.
I took a brief look at the Inform build system. Is it as complex as it seems? Are there any examples available of building in and calling external code?
I’m just using a poker AI as an stand in for “something very complex that is really best implemented in a tier 1 language, and that may even involve using libraries that are beyond my ability to implement from scratch.” Let’s take it for grated that such problems exist for the purposes of this conversation.
I’m looking for methods to extend the state of the art of IF game features without directly changing game engines or writing my own.
Yeah, pretty much. Compiling Inform to C is still a proof-of-concept technology. I don’t think anybody’s seriously rolled it into a live project.
One option for Inform is the Vorple extension. This basically means compiling an Inform game using the normal Inform tools. Then you run the game in a browser-based interpreter (on a web page) which has a channel to pass information to the browser’s Javascript environment. Then you can include any kind of JS library you want and make calls to it.
Personally, I would love to have a suite of C++ libraries to do all the parser IF stuff while being able to code up stuff that doesn’t fit that paradigm… being able to compile C++ to glulxe or another IF virtual machine would be great too, especially since I have no clue how to compile for platforms other than the one I’m on and while I’d probably opensource any IF games I released, I wouldn’t want to make compiling from source the only way for people not running x86-64 Linux to play my game.
Not a fan of the trend of making everything a web app.
TADS 3 has “intrinsic functions”, which are native code functions in the interpreter that are exposed to the game code. It’s not strictly speaking an FFI, by itself, because it doesn’t allow loading arbitrary platform libraries by name, but it is an extensibility interface that could be used to create bindings either to libffi or directly to whatever library you need. (That means distributing a customized interpreter, of course.)
I wrote a (non-IF) game using WebAssembly a couple of years ago, put it up online and largely left it alone. It’s broken twice since then as a result of dependencies changing. I’m not saying that those sort of issues are insurmountable with careful design, but for a community that values its back catalogue as much as this one, the current major platforms set a high bar in terms of long-term durability.
For “keeping the back catalogue working” the salient difference between something like C# and traditional IF-specific VMs is that the latter (by default) have a modest, fixed scope without an open-ended set of dependencies that need to be preserved and kept working separately.
Taking the Z-machine spec, or the Glulx + Glk specs, and implementing that from scratch for a new platform is not exactly easy but can be pulled off by a single programmer in a realistic time horizon. And that would be enough for running a large fraction of Z-machine/Glulx games from the IF archive. Vorple-based games are an exception for obvious reasons.
An arbitrary program written in C# or JS or […] has no upper limit on how much effort may be required to keep it working indefinitely and in many different environments. Especially if they transitively depend on a million lines of code in the form of libraries (which is tempting once you have the option!). Writing code is easy, deploying applications is hard.
To my knowledge, the interpreter sources are now dual-licensed under the original source-available license and the GPLv2. QTads and Gargoyle both use the latter. (IIRC Thaumistry used a modified interpreter to facilitate a dynamic map.)
Shell scripts are a time honored way of mashing incompatible elements together. I’m not an expert on parser interpreters but I’m sure there’s one that operates in the shell. So output some kind of token in the parser, pass the output through a shell script which replaces the token with output from the poker program.