Posts Tagged ‘channel io’

As mentioned in a previous post, I’ve been working on a unit testing program and in that process decided to tackle the coupling issues in the FyreVM engine. There were two, the channel order and layout as well as the output filtering (turning text into markup for HTML or XAML).

Both of these things are now removed from the open source version of FyreVM. The latest extension for FyreVM for Inform 7 6F95 is checked into the sourceforge.net site as well as FyreVMOS itself.

The channel layout is now dynamic. If you add a channel in your code, FyreVM will automatically allocate space for its output and return it to your calling program. In .NET this comes through as a Dictionary<channel, data> where channel is a 4 byte mnemonic and data is the text for that channel.

The extension contains the current definitions (in Inform 6 syntax):


! **** Channel IO Layout ****
!
! Each channel constant is a 4 byte integer packed with 4 upper case letters.
!
! Required Channels for FY_CHANNEL.
!
Constant FYC_MAIN = ('M' * $1000000) + ('A' * $10000) + ('I' * $100) + 'N';   ! MAIN
Constant FYC_PROMPT = ('P' * $1000000) + ('R' * $10000) + ('P' * $100) + 'T';   ! PRPT
Constant FYC_LOCATION = ('L' * $1000000) + ('O' * $10000) + ('C' * $100) + 'N';  ! LOCN
Constant FYC_SCORE = ('S' * $1000000) + ('C' * $10000) + ('O' * $100) + 'R';   ! SCOR
Constant FYC_TIME = ('T' * $1000000) + ('I' * $10000) + ('M' * $100) + 'E';    ! TIME
Constant FYC_DEATH = ('D' * $1000000) + ('E' * $10000) + ('A' * $100) + 'D';   ! DEAD

! Game specific channels for FY_CHANNEL
Constant FYC_TITLE = ('T' * $1000000) + ('I' * $10000) + ('T' * $100) + 'L';    ! TITL
Constant FYC_CREDITS = ('C' * $1000000) + ('R' * $10000) + ('E' * $100) + 'D';   ! CRED
Constant FYC_PROLOGUE = ('P' * $1000000) + ('L' * $10000) + ('O' * $100) + 'G';  ! PLOG
Constant FYC_TURN = ('T' * $1000000) + ('U' * $10000) + ('R' * $100) + 'N';   ! TURN
Constant FYC_HINT = ('H' * $1000000) + ('I' * $10000) + ('N' * $100) + 'T';    ! HINT
Constant FYC_HELP = ('H' * $1000000) + ('E' * $10000) + ('L' * $100) + 'P';    ! HELP
Constant FYC_MAP = ('M' * $1000000) + ('A' * $10000) + ('P' * $100) + ' ';    ! MAP
Constant FYC_SOUND = ('S' * $1000000) + ('O' * $10000) + ('N' * $100) + 'D';   ! SOND
Constant FYC_CHAPTER = ('C' * $1000000) + ('H' * $10000) + ('A' * $100) + 'P';  ! CHAP
Constant FYC_ACHIEVEMENT = ('A' * $1000000) + ('C' * $10000) + ('H' * $100) + 'V'; ! ACHV
Constant FYC_TIPS = ('T' * $1000000) + ('I' * $10000) + ('P' * $100) + 'S';    ! TIPS
Constant FYC_VERSION = ('V' * $1000000) + ('R' * $10000) + ('S' * $100) + 'N';   ! VRSN

I’m aware that the required math in each constant definition may seem a little daunting to non-programmers, but if you follow the pattern, you should be able to easily add your own channel definitions.

The Inform 7 code to direct output to a channel is defined as such:

To Select the Main Channel:
        (- if (is_fyrevm) FyreCall(FY_CHANNEL, FYC_MAIN); -).

Note the constant FYC_MAIN is used here to select the main channel. All of the channels above are defined and some have additional code for easy channel access, like the chapter channel’s phrase:

To Set the Chapter to (T - text):
        Select the Chapter Channel;
        say T;
        Select the Main Channel.

Which allows you to: set the chapter to “Chapter 1 – The Trap”.

Next post will be about regression testing.

One of the aspects of FyreVM that always frustrated me was the hard-coded nature of the channel layout. The engine, up until now, had a hard-coded enumeration of named channels. There wasn’t really any reason for this, other than it makes consuming FyreVM easier to understand. This was a feature that was nice to have, but now that I’m working on three different sets of source, it’s becoming a royal pain. I also have a better understanding of ways in which FyreVM will be used and ported and removing the tightly-coupled nature of the channel layout from the engine seems like a natural course to pursue.

The current engine also had an output filtering system for the different types of clients we were developing. I removed this from the engine as well. A separate project will be created to offer basic output filtering mechanisms for Silverlight, WinForms (RichTextEdit controls), and HTML. This is a simple layer that takes the contents of each specified channel and replaces standardized markup or characters with the specified output. For instance, if you were doing HTML, you’d replace double carriage returns with a wrapping <p> tag for paragraph. A single carriage return would get a </br> tag. Character styling, including bold, italics, underline, double-strike, subscript, superscript, and fonts, if supported by your output system, can also be implemented through the filtering layer. If a particular game had a very specialized output, the layout engine may be built into a special client that understands the layout markup. So if the game marked up all nouns, the client may know what to do with these words outside of just marking them up. It’s possible they’re links to other data or links to commands to be returned to the game engine. Maybe the UI shows a tooltip for such marked up nouns. This would be considered a non-standard layout engine.

There are a set of channels required for every game and they include Main, Prompt, Location, Score, Time, and Death. Main has to be the first channel.

The engine will now automatically allocate buckets for channel data. Since it uses a hashtable and text named channels, this leaves room for any number of channels a person might want. It also removes any need for ordering the channels. — updated 2:24pm

I plan to have a standard set of channels for public consumption, but the expectation is that the author or publisher can modify the channel list for their own purposes. My assumption going forward is that each game will have its own list of channels. The standard is really just a jumping off point.

The output filtering will also require a set of standard extensions, which will be titled something like FyreVM for HTML or FyreVM for Silverlight or FyreVM for WinForms RichText. This will offer the author easy ways to markup their output so that the client can filter it appropriately.

The client will require a second class library that takes the channel layout and the filtering rules and returns the channel data in the expected form.

The channel layout and filtering rules will probably be XML as the default standard, but I may decide plain text is easier to read and edit.

The output filtering requires character by character reading/writing because of begin and end tags in many cases.

I know this is meaningless to nearly everyone, but eventually the benefits will become obvious.

So I had set aside a lot of IF work in the past month for work and health reasons. I found myself with a very bad case of whiplash after several wild rollercoaster rides at Six Flags which uncovered high blood pressure, which led to me to get a stress test, a physical, and to see a foot doctor. The neck pain and dizziness are gone, the new orthopedic shoe inserts are wonderful, and the blood work all came back normal. I feel better. Relieved.

I had left Zifmia in a nearly working state, outside of details like security and the client aspects. The server was very close to being completed. So I’ve spent the last three days working through the issues and it’s now running perfectly. Here’s what I did.

I’ve developed FyreVM in a new WCF web service. For newcomers, WCF is a framework from Microsoft that allows you to easily build web services. The service has a single interface, GetResponse:

    [ServiceContract(Name="ZifmiaService",Namespace="FyreVM")]
    public interface IZifmia
    {
        [OperationContract]
        [WebGet(ResponseFormat=WebMessageFormat.Json)]
        ZifmiaResponse GetResponse(ZifmiaCommand zCommand);
    }

The ZifmiaCommand is parameter class:

    [DataContract]
    public class ZifmiaCommand
    {
        [DataMember]
        public string SiteKey { get; set; }
        [DataMember]
        public string GameKey { get; set; }
        [DataMember]
        public string UserKey { get; set; }
        [DataMember]
        public string Command { get; set; }
    }

The main parts we’re interested in today are GameKey, UserKey, and Command. The GameKey is a reference to a server-side game file. The UserKey is a user’s identity. The Command is whatever the user has typed into the game window.

WCF has a built in test client that helps us test:

In the first frame, we’ve opened up our test client. We click on the GetResponse interface, which displays our available zCommand interface. Then we add in our start up arguments and invoke. You can see the results in the third image. Each channel has a value or is blank. Then we add a command and invoke a second time. This shows the channels again with different data. In the final image there is a couple of files that represent the state of the game. The main file is the save data and the numbered XML files are the channel data saved for each turn. We can re-use this data to display previous turns in the browser (or any application that consumes the Zifmia service).

It all works and is very fast.

Next up, the client with fancy jQuery controls to display our channel data.

So somewhere way back a couple of years ago, Jesse McGrew helped build FyreVM with a new IO layer we called Channel IO. This has turned out to be extremely useful, especially when building different kinds of user interfaces.

Recently at work I’ve been tasked with designing and building a customer service chat system. The best way to do this is using AJAX Long Polling and the best way to do that is to use a Comet library based on the Bayeux Specification. All of this is some older networking patterns being reworked into existing and future HTML specifications and the underlying pattern is a publication subscription model.

All of my research on Comet got me thinking about Channel IO and that got me thinking about Zifmia and how best to serve many users a particular IF game or to even allow them to play the same game at the same time. It also got me thinking about how we implement output in Interactive Fiction.

Leaving the Zifmia impact for another post, I want to focus on IF output and this has been something I’ve been thinking about for awhile, even outside of the Comet stuff.

In an IF game we have different targeted locations of output. Channel IO handles this great. We can direct text to a main channel, a location channel, a score channel and in the UI place these pieces of text where we want them. Now I’m wondering if we can’t dig deeper into the IF engine and provide a completely different output paradigm. I believe Emily and a few others have actually done things like this in their code, but I think the pattern should be extended as a standard layer.

The idea is to output textual parts given some meta data. Let’s focus on what we consider main output. anything that shows up in the main window. However, we want this process to work for any channel.

The different kinds of parts include sentences and items with descriptions. The meta data might include things like “sentence beginning”, “sentence end”, sentence middle”, “can be preceded”, “can be followed”, “must be listed separately”, and “must be output with a pattern” (and the pattern is somehow included in the meta data).

From here we allow the author to identify pieces of output beyond using just a “say” or “print” command. Possibly:

say “From the crib you hear a wimpering toddler” as sentence-beginning, can-be-preceded.

The result is likely to be some type of markup that has to be processed within the VM.

The idea is that within the IF game, the author is less concerned about format and more concerned about content. The question is, can a post-output processor be smart enough to string everything together properly? Does this break down the talent of an author or does it enable them to do interesting things?

The reason I bring all of this up is that I continue to think of alternate user experiences, server based IF, as well as mobile device output.

The idea is obviously not well-formed, but bothered me enough that I needed to blog about it.

One of the reasons I started Textfyre was that I had and have a firm belief that paid programming was a considerable missing component of the development and improvement of Interactive Fiction as an artform and medium. The “IF community”, depending on your definition of such a thing, generally focuses on the academic and hobbyist participatory aspects of the medium. We’ve had a few people sell games within the community and they’ve shared some of their processes and thoughts, but no one has recycled any profits into the community at large.

Although I don’t have any profits (let’s not talk about the increasing debt I’ve incurred) to speak of, I do have a sincere interest in sharing the fruits of our internal workings as much as possible without crossing swords with my attorney.

So with that in mind, we’ve put together a “shared source” version of our Glulx VM implementation named FyreVM which can be reviewed and downloaded from the FyreVM website. By shared source we mean that there is a non-commercial aspect to the source code and we also want to restrict branched versions of the VM itself. Any code you write that uses the FyreVM is of course all yours. We’re going to put up samples and those will all be public domain. We will entertain friendly requests for a limited (individual) royalty-free commercial license.

FyreVM is the culmination of a lot of thought on my part and a frustrated review of the Glk specification. I’m not saying Glk is bad or wrong. I just think its limited in its usability by the average developer. There has been a sizable effort by several people to make Glulx and Glk as friendly as possible and yet we still aren’t seeing any increase in games developed with higher quality user interfaces.

So I’m sharing FyreVM because of how we implemented I/O, which is differently from how Glk implements I/O. FyreVM uses channels to convey all information between the virtual machine (game engine) and the user interface. We’ve completely abstracted away any detailed knowledge of pointers and memory and low level programming hacks to access the I/O interface. The developer has to simply retrieve the text that comes out of each channel on each “turn” in a game and do with it as they may.

To aid in this process, we’ve also created a very friendly set of Inform 7 extensions to give developers the tools they need to create channel based games.

Of course we’re still working on sample games to show off the potential of FyreVM and Channel I/O and we will report updates on the website. We invite anyone and everyone to help create samples for the website.

Textfyre is dedicated to being involved in the interactive fiction community and will continue to share our tools and processes as time, money, and lawyers permit.