Introducing iffinity, a new minimal IF engine with iffinite possibilities!

Hello everyone!

After getting introduced to the world of interactive fiction via my participation in the IFComp 2023, I instantly fell in love with the genre and especially with its creative aspect, both artistic and technical.

After having written my game for the competition (The Ship, which may have been a bit too ambitious, but I loved every minute of making it) in Twine/Snowman, I wanted to keep on building IF games but I felt quite limited by Twine. Don’t get me wrong, it’s a great tool, but I wanted something with more freedom, especially regarding text/code organization. I also tend to write code-heavy mini-games, so that was also a bit of a pain in Twine/Snowman.

So, I decided to write my own engine which I have been writing/designing for the past couple of months, and now…

I am extremely proud to introduce iffinity version 0.4.0 (beta) to the intfiction community!

(many MANY thanks to @HAL9000 for the awesome logos!)

iffinity is an extremely minimal, command-line engine for browser, choice/hypertext based interactive fiction. It is heavily inspired by Twine, and especially by its Snowman story format. Long story short, you write your story in HTML files (as many as you want, organized however you like) and break up your JS code in whatever way you want (inline in your prose or in (a) separate file(s)), and the iffinity compiler takes all of them and produces a single HTML file with your game.

iffinity is written in TypeScript and is distributed via npm, making its installation as straightforward as possible. I.e., type npm i -g iffinity in a terminal and you are good to go!

You can find the iffinity repo here, and here is the changelog of the latest release. The engine is fully documented in the project’s GitHub wiki. Also, there are a few examples in the repo, mainly used to test some features of the engine. I am currently working on a roguelite role-playing text adventure/mystery (maybe too ambitious once again…) which I hope will serve as the first fully-fledged use case of iffinity; if no one builds something else first, that is!

By opening this topic, I hope to gain a bit more exposure and hopefully reach out to like-minded IF creators who also feel like me regarding the needs that gave birth to iffinity. You are all kindly invited to check out the project’s README to get a better feel of what the project is all about and, if you feel that it resonates with you, feel free to play around with it and, hopefully, build something with it; don’t forget to reach out to me if you do! So, this topic is an exposure attempt, as well as an RFC (Request For Comments). Also, it goes without saying that if any thought/feedback/constructive criticism comes to mind, feel free to share it.

That is all! I hope iffinity finds creators in this awesome forum that would benefit from it and, hopefully, be a useful tool for future IF works. Cheers everyone!

20 Likes

It’s truly impressive to see the level of creativity that goes into developing new tools. As someone who is always on the lookout for new tools to streamline my work, I can definitely appreciate the effort that goes into creating something that is both useful and user-friendly. In fact, I’ve spent the last couple of days trying to slim down some of my old games and make them more efficient, so I would love to give this new tool a try and see how much I can learn.

5 Likes

That’s so great to hear! I hope you find iffinity useful and fun to play around and experiment with!

4 Likes

@MightyPigeon Congratulations on releasing the iffinity beta! I’m excited to check it out!

For those who wish to try it out with VS Code, Sotiris was kind enough to toss me a link for syntax highlighting of the EJS files used to compile iffinity projects. It made viewing the code so much better for me.

EJS language support - Visual Studio Marketplace

Can’t wait to see what people make with iffinity. :slight_smile:

3 Likes

I’ve updated my project (a very unfinished mall-themed Pokemon ripoff) to use the newest version of iffinity! Great job working on this, it’s been really useful so far. The iffinity version of my game has more progress on it than the Twine version now, and it looks like I’ll be using iffinity from now on.

:eyes:

4 Likes

Just updated the release changelog of the latest version, to note that if anyone (like @Cerfeuil) has used previous versions of iffinity, it is strongly advised to delete the output HTML of your project and recompile it from scratch after you download the latest iffinity version (there was a quite funky bug).

3 Likes

Haven’t played with it yet, but regardless of how this all plays out, your name game slaps.

5 Likes

Maybe next year we’ll have an iffinity winner in IFComp!

I’m a simple player of IF, and mostly parser within IF. I have no coding skills whatsoever. But seriously, even I can see how cool this is.

Congratulations on building a Choice-engine to your specific tastes and sharing it for others to use and explore its possibilities. I hope many people make great stories with it.

5 Likes

Looks interesting. Is there some way to run the examples from the repo?

4 Likes

Absolutely!

  1. Install iffinity on your machine (you’ll need npm for this as iffinity is distributed as an npm package). Just fire up a terminal and type npm i -g iffinity. Then run ifc -v to make sure that it was properly installed (you should get iffinity engine v0.4.0 as output).
  2. Go inside the directory (i.e. cd) of the example you want to play with and type ifc. This should output an HTML file in the same directory.
  3. Open the HTML with the browser of your choice.

Bear in mind that these examples are not that good (that’s something I should fix, as a matter of fact); and by that I mean I mainly made them to test aspects of the engine. They should, however, provide a nice feel of how the engine is designed.

Also, one of the examples (the simple one) can be produced directly by iffinity when you run ifc init to start a new project (inspired by npm init), as a template project. Just answer “yes” to the last prompt.

Hope that helps. Please feel free to either reply on this thread or PM me directly if you have any more questions/need any more clarifications. :slight_smile:

Edit: Just noticed something I had forgotten: Each example has its HTML output in the repo already, so you don’t have to compile them yourself to try them out.

4 Likes

Congrats on the new project! It’s a little weird for me to see concepts across Snowman and Extwee – I have config file support as a long-term goal! – in one project as a story compilation tool based on a specific story format. It’s, like, all my recent stuff in one place. Exciting!

I’ve been working on trying to help with the modularity issue with Twine through some more recent work on the Twine 2 JSON format (which doesn’t have support in Twine yet with compilation tool functionality coming across multiple projects), but I’m hopeful it can help with people generating many passages or saving specific selections and then combining them all together. (We might even have passage metadata support one day!)

I look forward to trying iffinity for myself soon!

4 Likes

Thanks for your detailed answer. What i was thinking of is that, isn’t there some way to have github serve HTML directly, so you can run the demos from the repo ? Perhaps someone knows how to do this.

4 Likes

What I’m aware of is GitHub pages. I’ll definately look into that, because I’m also thinking of transferring the documentation from the repo wiki to a webpage as well.

3 Likes

Yeah, IIRC you just go to Settings > GitHub Pages and enable the feature and choose a branch to be published, then any files on that branch will be served under your-name.github.io/repository-name. Super simple.

But look at the settings first because you used to be limited as to what branch names you could use with it…

You can also get fancy and use Jekyll (I think? some static site generator), but that gets more complicated fast.

4 Likes

Hi all! Just wanted to let you know that I moved iffinity’s documentation from the repo wiki to a nice site here (with GitHub Pages). I also added an “Examples” page where you can play around with the (compiled) examples directly, as per @jkj_yuio’s request. Cheers!

6 Likes

Alright, so I have another question slash feature request. Twine has this thing where if you refresh, it takes you back to the same node/passage you were on before the refresh, and I think it preserves variables, too. But with iffinity it resets back to the start again, and I think the variables get reset? (Haven’t tested that bit.) Wondering if there’s any way to mimic what Twine does, or how easy it would be to add that as a feature. If it’s not possible I might try using cookies or something, but I think it’d be more convenient if there was a built in setting for it. (Also, thank you in advance!)

3 Likes

@Cerfeuil

I think you could block accidental refreshing with something like…

$(window).bind("beforeunload", function(){
        return confirm("Are you sure you want to refresh the page and lose all progress?"); 
});

I admit, I have not tested this though, but more info on this can be found here… https://mkyong.com/jquery/how-to-stop-a-page-from-exit-or-unload-with-jquery/

I agree with you that accidentally hitting the refresh button (or F5 key) and losing all your progress would not be desirable in any situation. Good call on bringing this to people’s attention. :slight_smile:

In iffinity there is the save() and load() methods… The Author API | iffinity docs

You could call save() after each snippet is drawn; and when your game starts, you can always call load(). Again, haven’t tested this, but it might give you something to tinker with until @MightyPigeon has a chance to respond.


Edit: I should add that you must store the JSON string that is created by the save() method yourself. Local storage is the way to go.

2 Likes

Hello there! I just want to let you know that I haven’t been that active because I was on a trip and then I got really sick for almost a week (today’s the first day I start feeling like myself again). I kindly ask for a few more days and I’ll come back to your questions/suggestions ASAP. Cheers and happy (start of) holidays!

3 Likes

@MightyPigeon Hope you’re doing okay, and don’t mind the ping! Being sick around holiday season is no fun. I’ve been meaning to add that the game I entered into Shufflecomp 2023 (Messages From the Universe Graveyard) was made with iffinity. Unlike the other iffinity project I was working on, this one is actually finished. Mostly, barring the potential for later updates.

I just put the source code on Github today, so I can finally make this post now. It can serve as a larger example project if anyone’s interested, I guess. Although the code may be somewhat sketchy (but what big project doesn’t have a few spots of questionable code… right? May the coding gods forgive me for my sins).

4 Likes

@Cerfeuil and @HAL9000,

First of all, allow me to deeply apologize for my radio silence. I started my Master’s abroad recently and things have been extremely hectic, I’ve been having almost no free time for a while now… But please know that by no means I’ll let iffinity die :slight_smile: apart from me liking the project, I find it thrilling that many of you have reached out to me and expressed how much you enjoy working with it, so I’ll try my best to be more active in the forum and, if the need/will arises, in further developing iffinity.

Now, regarding @Cerfeuil 's question, let me start by saying that the whole page refresh thing is a huge pain for front-end dev in general (take a look at this StackOverflow reply for example). Also, I had no idea Twine supported that out-of-the-box - what story format are you referring to? I’d like to take a deeper look.

Having said that, I feel that dealing with such a feature is something that shouldn’t be a part of the engine, but a part of the author’s game logic. Two reasons for that (feel free to fight either/both of them):

  1. The main idea behind iffinity’s design is simplicity; providing the author with the essential tools to create a fully personalized game. By enforcing a specific way of keeping track of the state, you lose part of that freedom that iffinity advocates (an extreme example would be a game where refreshing is actually a game mechanic, with very peculiar or esoteric implications for the story :wink: )
  2. Given that refreshing is such a strange and definitely not straightforward browser event/mechanism (I’m not a front-end developer myself, actually), incorporating its handling in the engine’s core would mean that design choices would have to be made in order to accommodate for edge cases etc etc etc, leading to a more complicated codebase for something that each author may want to handle differently.

Regarding the code snippet that @HAL9000 provided, that’s indeed a good start, but have in mind that it will only prompt the user if they’ve actually interacted with the page before refreshing; the browser will simply not fire this event if not. This means that if you get to a new snippet and immediately refresh (without clicking or anything), then the event won’t be triggered. Front end is a strange world…

To sum up, I’d say start from iffinity’s save/load API and use some logic to cache the state at each snippet change (sounds like a perfect usecase for the iffinity’s global scripts mechanism) and utilize the local storage (the only real storage you have when working in a browser), like @HAL9000 suggested.

Again, nothing is written in stone; feel free to share your views and/or objections to the above reasoning. In any case, I’m looking forward to hearing your thoughts and, hopefully, I’ll be (much) more responsive from now on. Cheers (and thank you)!

4 Likes