Recently I have finished working on v1.0 of my interactive fiction engine, called Discoteque. There's a demo available online, so you can check out a sample story to see how it works. The main point of this engine is that it tries to replicate a lightweight version of Disco Elysium's design approach: A text-based adventure game where you earn XP by talking to people and unlock skills to use in dialogue to open up special options. The engine is dead simple: Using react + Redux for store & presentation, it allows writer to compose interactive fiction by chaining Nodes together - each node contains lines which are presented to the reader. After all lines end, a node can lead to another node, or it can end abruptly. A line can also contain various options, which can be subject to a skill check (which player posses) or could be free to pick, which can also lead to a different node. Each line can also read from and write to the game's state, thus line can be treated as a single iteration over the engine's "Main loop". This allows to create fast, robust and engaging interactive stories, driven by chance and player choice with minimal effort on the writers part.
While not being at the stage where one can freely download it as a library from npm, it is at the stage right now where one can clone the main repository with the engine and edit the default demo to achieve their desired story. Developing with Discoteque is easy! src/game/index.ts exports an EngineConfig - a configuration object from which we build our game! It contains a few parameters, such as list of skills available in the game, how much points should be available to spend when creating a new game, a list of Nodes that this game will have and a node that starts the game.
INode object contains following self-explanatory properties: id, image, lines and next. id Represents a string ID that is used to reference this node by others (such as in actorId or next field). image is a property containing link to the image that represents a node (most commonly used to represent speaker's picture). next is an ID of a node that should be switched to when all lines in current one are depleted. lines is a special property containing a list of lines. They can be either ILine Object, or a function which returns ILine object. ILine contains following properties: actorId, which is a string ID pointing to a node that represents current speaker. text is an actual, spoken line that gets recorded. If no actorId is present, then line is presented as is, if it is present, then line is decorated with speaker's name. options is a special array that contains list of ILineOption, which represent various responses player can pick and where they lead. ILineOption is an object which contains: text, which is a text of this particular choice as visible to the player. value, which is an ID of a node that picking this answer will lead to and skill, which is an object containing name, name of the skill, and difficulty, which is difficulty number against which the skillcheck will be rolled. If no skill is provided, then the option is always a success and no check is performed.
lines member on INode could also be a function, which accepts (engine: Engine, gameState: IGameState, dispatch: Dispatch). It can be used to perform various operations on a state (but be mindful of operations order and continuity!) and must return either null or ILine object. Essentially this function acts as a programmatic getter for the next line. IActor and ILocation are sub-classes of the INode, which both contain extra property name, which represents name for location \ speaker.
(engine: Engine, gameState: IGameState, dispatch: Dispatch)
These simple elements, chained together constitute a complete Discoteque adventure. By manipulating the game's state, as well as advancing lines and switching nodes, we can create simple, yet effective branching interactive novellas that are bound only by your prowess as an author and imagination!
Demo is available at deiru.moeCode is available at GenSoc Code