OMG! Not ANOTHER stupid IF system!

What was I thinking? I mean, if there’s on thing the world does not need it’s yet another IF authoring language. Yet still I’m working on one. Why?

  1. Because it’s fun. (And that should be justification enough.)
  2. Because of the special challenges of my chosen platform.

I’m writing an IF system that runs on a web server so that the games can be played in any browser. The special challenges have to do with how a php server script works.

You type your command: “put the marble in the wooden box” and hit enter. Unlike a program running on your own computer, there is no interpreter waiting patiently for you to hit enter. Instead, the web server gets your request in the form of a URL and some posted data, maybe something like: somephoneyurl.com/thisgame.php&cmd=put%20the%20marble%20in%20the%20wooden%20box

At that point, the game is not running. Nothing that you’ve done before is saved anywhere on the web server. The game has to be loaded from scratch and your current game state set up. Then your command line is parsed and interpreted; the script does something like change the location of the marble to be in the blue box; builds a new html page showing what it just did; sends that html page back to your browser; and then the script goes away. It stops executing. It’s dumped out of the server box. It’s gone.

Later, (an hour later, or maybe two days later), you type in “go north” and hit enter. The whole process gets repeated. The whole game engine has to be loaded; the whole state of the game re-established, etc. etc. You get the new room description and the server script is dumped out again. Meanwhile the server is busy with other clients on other browsers who are ordering widgets from their favorite widget vender.

But how does it know the state of the world each time it gets summoned? Especially since there’s no reason why 15 different people can’t be playing their own copy of the same game on the same server. Probably from a cookie the script sends to your browser. That way you never have to save or load a game. Turn off your system. Take a vacation to Germany. Come back two months later and turn on your system. Click the bookmark to your game URL and you find yourself exactly where you left off last time you were playing the game. You’re in the same room, with the same inventory, and the same score and same tasks already marked as accomplished. And you still only have two moves left to decide which wire to clip before the bomb goes off.

I took a look at the source code for several good sized games, including some of my own old TADS source files and figured that the average state of the game, including locations of all moveable objects, states of all binary flags (door is open/closed; room has (or has not) been found;) and numeric values (scores, damage counts, fuse and timer countdown values) and found that the complete state description of the average game can be packed into less than 100 bytes. That 100 byte cookie is enough to save/load the game and put you right back where you left off. Even if a really complex game takes twice that much, that’s not bad.

(There could also be provision for a MySQL database to hold player’s game states, but that would require each player have a unique ID which would require registering on the site just like registering on this forum to reserve your ID and protect it with your own password.)

Because of that way of doing things, the organization of the engine needs to be very different for the sake of efficiency. For example, each room of the adventure is probably in a separate file, so when you say “Put the marble in the wooden box” the engine doesn’t load the whole game. In fact, it might only load the object files for the marble and the wooden box, and not even load a room file at all.

Your player character would suspended in the void of empty space, putting a marble into a wooden box. But that doesn’t matter, because to accomplish that one task the engine doesn’t need to know anything about the room, and it doesn’t have to say anything about the room in its reply to you. All it really needs to do is verify that putting the marble in the box is a permissible action, and then update a few bits in your cookie and send it back to you to reflect that the marble has a new parent object.

Another example, with the player command: “Go north”. There’s no need to load up the room data for the room you’re in. Just load up the doors data for that room. Maybe a hundred bytes is all. Check the north door in that file, and if movement is not possible, report back that fact and, as usual, just stop executing. But if movement is possible, load up the room description for the destination room so the engine can describe the new room. Then as usual, stop executing and wait for the new input.

There are loads of other considerations and problems to work out. I’ve got a long list. And I’ve got some preliminary php scripts that sort of work, but it’s likely to be a long project. But it’s been fun so far.

One issue I’m wrestling with right now is whether to create a new game file format from scratch or to try to get the engine to run existing games in some existing format like Z-machine. The obvious problem is that Z-machine code is not organized for piecemeal loading as required by the hypothetical php engine I’m designing. But maybe Z-machine code could be “compiled” into segmented files…? Well, that’s just dreaming. For now I’m using XML files, similar in basic concept to Quest files, but organized differently for piecemeal loading and execution.

Any thoughts and suggestions, or even scathing criticism, would be more than welcome.

–gary

While a few very simple stories might be able to squash the state into a 4KB cookie, I really doubt whether substantial stories will be able to. If that is a limit hard limit then you won’t be able to get authors on board (and I think you’ll have a hard job as it is, there are already so many authoring systems.)

Now as to your goals, running IF on a server, even in PHP, isn’t actually very unusual. Almost every major IF system now comes with some sort of web support, some client based and some server based. And a decade ago PHPZork was running in PHP :slight_smile:!

If you’re after fun, you should consider whether you might enjoy working on another existing interpreter, I’m sure that all interpreters would appreciate the help. I certainly would! And some interpreters are pretty high tech too - my ZVM for example has a just-in-time compiler (it’s essentially an Inform decompiler) and uses abstract syntax trees to allow us to manipulate the source code however we like. In the future I’ll be adding support for Typed Arrays and Web Workers. My goal is to eventually get it to the stage where it’s the faster interpreter there is, including the regular desktop terps!

I think Zifmia already works like that. Though it’s hard to find any info on that project. It seems the authors chose to keep it incognito or something. IIRC, it shuts down the interpreter between commands and restores state whenever the PHP script receives new player commands.

The state “cookie” is probably best kept on the server though. It’s totally pointless to send it to the client. The only time where the client needs it is when entering SAVE. Otherwise you’re slowing things down and generate traffic for no reason whatsoever.

Of course I’ll make the “state cookie” as big as it needs to be, even if it has to go into a MySQL database filed by the user’s login name. One way or another, though, the complete state needs to be saved every move. In a database that might actually only mean changing a few entries in the “state cookie” after each move.

I do wonder about your 4KB figure. Where did that come from? The game sources I looked at were around the 80 to 120 rooms in size with 50 to 75 stationary objects, and around 30 to 50 moveable objects. Counting all the state variables that had to be written to save the game state. and writing 8 boolean variables per byte, and using 32 bit integers, and 16 bit object id numbers I had a hard time using up more than a couple hundred bytes or so. If we assume the very worst and say every room has 16 boolean flags and some integer value, that’s 120 rooms * 6 bytes = 720 bytes. Give every stationary object 16 boolean flags at 2 bytes each for 75 * 2 = 150 bytes, and give every moveable object a location (2 bytes) an integer value (4 bytes) and 16 flags (2 bytes) and that’s 50 objects * 8 bytes = 400 bytes for a grand total of 1270 bytes for an exaggerated worst-case.

Obviously I’m overlooking something. I just don’t know what.

That’s certainly something to keep in mind. But now that I’m retired, after 45 years of programming other people’s code, I want to write my own code. :wink:

I’m sure you’re right. Especially for more complex games that require larger “state cookies”. The state could even be divided among several tables in a database, so that if the players move was “Put the red marble in the wooden box” only a very small portion of the “state cookie” would have to be changed in the DB. It would only require rewriting the table that held the marble’s parent object id.

On the other hand, right click one of those smilie images :laughing: in this forum and read the image info. Those smilies run 620 to 750 bytes, depending on whether they are animated or not. My worst case state cookie mentioned above (1270 bytes) is as much internet traffic as two smilies! :astonished: :unamused: In reality, does the presence of an extra two smilies worth of traffic really matter to the response speed? :question:

I’m playing around with a different way of organizing my data files right now. Maybe in a day or two I’ll have my toy implementation of “Hunt the Wumpus” running so I can try out my new file system.

–gary

The short answer: by the time you’ve built a fully-usable IF system, you’ve moved several layers of code past the sort of byte-obsessive focus that perfectly optimizes state size.

It’s perfectly reasonable to start at the beginning, though.

Hey Gary,

Your basic idea is fairly sound and yes, building a new IF platform is fun. I have some VB.NET code laying around where the only requirement is to have fun trying to create a viable platform in VB.NET. Maybe someday I’ll get back to it…

For Textfyre, I have a Glulx engine with a different IO layer and the whole thing is called FyreVM. This was created by vaporware in about 80 hours, which I still find astonishing. Since then I have managed to wrap the engine with a simple state manager and run it on a web server and I called this Zifmia. Then I moved to implementing something useful with this technology.

At first I had the idea of calling “save” after every turn and storing the save files on disk or in a database. But after playing around, I realized it was no more expensive to simply store a binary serialized version of the engine, in a database. As it happens, I’m using Eloquera, a free object database.

So the logic is:

  1. user starts game
  2. if user has running session, load it and present most recent turn data
  3. if user is starting a new session, create the session and present the first turn data
    NOTE: A session is the data structure for all of the play of a particular game. I plan to allow one session per game per user when the system is released publicly.
  4. user enters a command into the browser
  5. ajax call is made to server, sending session identifier and command
  6. server loads session, deserializes engine, executes command, saves session, returns turn-data back to browser
  7. browser places turn-data in appropriate CSS DIV tags
    NOTE: the response turn-data in FyreVM/Zifmia comes in name/value pairs, so the room name is in the LOCN value and MAIN contains the main text response. Other keys include SCOR, TURN, TIME, HINT, HELP, TITL, CHAP, etc.

You can play around with alpha code at beta.textfyre.com, running the demo of Cloak of Darkness. I still have some design tasks to complete, mostly around how to handle displaying and accessing historical turns as well as displaying branches, since the user can “go back” and enter an alternate command at any past “turn”. Branching is managed within a session.

NOTE: I do use an MD5 hash routine to prevent storing engines that are identical more than once…thanks to Zarf for that idea…

Anyway…this may give you something to think about as you work on your system…

David C.

That’s an interesting approach, and one I hadn’t thought of. I’m experimenting with a new approach I dreamed up last night that I think is very promising. I’m chronicling my experiments and musings here: fiziwig.com/intfic/design.html

I like the idea of using AJAX. It had crossed my mind, but I haven’t really given any thought as to how I might use it yet. I’m still too early in the experimentation phase.

Very slick! I really like the look of your interface. The icons for map, hints, and history are a nice touch. My own experiments haven’t gone much beyond basic HTML so far. I’m still kind of stuck in the “Commodore 64 look and feel” mode until I get further along on the functionality.

For what it’s worth, I have my skeleton Hunt the Wumpus game running with 25 rooms, and about 100 lines of php code. No Wumpus, bats, bottomless pits, or arrows yet, but you can explore the whole map with simple move commands: fiziwig.com/intfic/wumpus/

Each room is in a separate file of around 10 to 12 lines of mixed php/html.
Everyone is welcome to give it a try, even though so far it’s just a dungeon hike to see the sights. I tried to make each room interesting. See if you can guess the theme of the map.

Still plugging along on this PHPIF project.

My current step is that I’m starting to work out the details of the script internal bytecode, and just how the game files will be structured.

I have a sample two-room game outlined in pseudo code, and a simulated transcript of each step in the process of playing the game showing how the control flow gets passed back and forth between interpreter code and game-specific code.

The whole process works very differently than it would for IF on a local machine, but the outline I have so far looks very promising. I might even have some bytecode running in the interpreter in a few more days.

Latest stuff: fiziwig.com/intfic/design2.html
Parser description: fiziwig.com/intfic/design.html
Working parser to play with: fiziwig.com/intfic/parser.php

–gary

You might want to switch to a normal user interface for this rather than having a separate input field. Like this:

>look
You see nothing.

>

This will make it easier for people to try it out and test it. :slight_smile:

The focus right now is on functionality. Once I get everything actually working the format is just window dressing that can be changed easily. After all, it’s all HTML. That’s means images, sound effects, wild fonts, crazy formatting, that’s all gravy that I get for free because I’m using the player’s browser as the game interface.

For now I want to keep the code as simple as earthly possible so I can concentrate on the internal nuts and bolts. Later there will be time to make it pretty.

Right now, to support that kind of interface would require Javascript and AJAX which introduces a whole extra layer of complexity that would make the job of getting it all working that much more difficult.

Eventually it will be prettied up. But not yet. :wink:

First, I’d like to congratulate a fellow re-inventor of the wheel!

And second, a few hints and tips from my own web-building and programming experience.
My website has user log-ins and cookies; you could probably make user log-in as simple as their email address. The way I keep track of users is by storing a unique ID in a cookie, and reading that value out of the cookie to get whatever data they need. In your case, that would be the list of items, etc., stored in a SQL table somewhere. As easy as it would be to store all that information in a cookie, there is always the chance that someone will clear their cookies (and thus their game)… better to tie it back to a login, and keep it safe on the server. Plus, that allows people to log in from wherever they want; a new login creates a new UID, as does logging out, so it’s never out of sync.

Next - for AJAX (and all your dynamic content needs), I would suggest using jQuery (or another library like that). It makes all the “pretty” so much easier, including AJAX. If nothing else, the commands a lot simpler, and a lot better documented, than the equivalent javascript. Believe me, I know…

And finally - re-inventing the wheel is fun and all, but some things just scream for special features. One such special feature is adding a little more interactivity to interactive fiction. Right now, the one thing almost every IF parser has in common is… they’re just parsers. They take commands, and return text (or pictures, or sounds, or even videos), but in the end, when you’re done playing, you’re done. With the full power of a webserver, you could add all sorts of interesting tidbits to games - for instance, you talk to someone about keycodes in the game, and soon after you get an email from that person in “real life” - you got their email on sign-up, right? Or with a bit more work - someone is really getting into the spooky part of the story, and suddenly… their phone rings. And no one is on the line. All things you can do with a system like that, and not really all that hard to do, either. Once everything else is working, of course :slight_smile: