intfiction.org

The Interactive Fiction Community Forum
It is currently Thu Jun 20, 2013 7:36 am

All times are UTC - 6 hours [ DST ]




Post new topic Reply to topic  [ 12 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Tue Jan 17, 2012 7:04 pm 
Offline

Joined: Sun Jan 15, 2012 8:04 pm
Posts: 13
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


Top
 Profile Send private message  
 
PostPosted: Tue Jan 17, 2012 7:29 pm 
Offline
User avatar

Joined: Wed Oct 14, 2009 4:02 am
Posts: 981
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 :)!

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!


Top
 Profile Send private message  
 
PostPosted: Tue Jan 17, 2012 8:13 pm 
Offline
User avatar

Joined: Tue Apr 20, 2010 2:48 pm
Posts: 696
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.


Top
 Profile Send private message  
 
PostPosted: Wed Jan 18, 2012 1:01 am 
Offline

Joined: Sun Jan 15, 2012 8:04 pm
Posts: 13
Dannii wrote:
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.)


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.

Dannii wrote:
---
If you're after fun, you should consider whether you might enjoy working on another existing interpreter, ---


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. ;)

RealNC wrote:
---
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.


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 :lol: 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! :o :roll: In reality, does the presence of an extra two smilies worth of traffic really matter to the response speed? :?:

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


Top
 Profile Send private message  
 
PostPosted: Wed Jan 18, 2012 1:23 am 
Offline

Joined: Sat Jan 23, 2010 4:56 pm
Posts: 2130
Quote:
Obviously I'm overlooking something. I just don't know what.


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.


Top
 Profile Send private message  
 
PostPosted: Wed Jan 18, 2012 12:18 pm 
Offline
User avatar

Joined: Thu Feb 11, 2010 1:51 pm
Posts: 217
Location: Chicago, Illinois, USA
fiziwig wrote:
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.


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.


Top
 Profile Send private message  
 
PostPosted: Wed Jan 18, 2012 1:50 pm 
Offline

Joined: Sun Jan 15, 2012 8:04 pm
Posts: 13
DavidC wrote:
fiziwig wrote:
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.

Hey Gary,
Your basic idea is fairly sound and yes, building a new IF platform is fun.
--<snipage>--
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.

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: http://fiziwig.com/intfic/design.html

DavidC wrote:

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.

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.

DavidC wrote:
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.


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.


Top
 Profile Send private message  
 
PostPosted: Thu Jan 19, 2012 1:05 am 
Offline

Joined: Sun Jan 15, 2012 8:04 pm
Posts: 13
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: http://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.


Top
 Profile Send private message  
 
PostPosted: Tue Jan 24, 2012 5:58 pm 
Offline

Joined: Sun Jan 15, 2012 8:04 pm
Posts: 13
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: http://fiziwig.com/intfic/design2.html
Parser description: http://fiziwig.com/intfic/design.html
Working parser to play with: http://fiziwig.com/intfic/parser.php

--gary


Top
 Profile Send private message  
 
PostPosted: Tue Jan 24, 2012 6:29 pm 
Offline
User avatar

Joined: Tue Apr 20, 2010 2:48 pm
Posts: 696
You might want to switch to a normal user interface for this rather than having a separate input field. Like this:

Code:
>look
You see nothing.

>


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


Top
 Profile Send private message  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 12 posts ]  Go to page 1, 2  Next

All times are UTC - 6 hours [ DST ]


Who is online

Users browsing this forum: No registered users and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group