Inspired by Prakbot, an XMPP bridge to the Hitchhiker’s Guide to the Galaxy text adventure, allowing anyone to play the text-based game via Jabber or GoogleTalk, I decided it might be fun to write a similar XMPP bot using Ruby’s XMPP4R. In addition to figuring out how to make an XMPP bridge to a z-machine I also wanted to bridge to other text-based game systems, like a MUSH/MUD or a Trivia game.
What I ended up with was a Jabber/XMPP bot, “XMPP Bridge”, which acts as a sort of “chat lobby” for any subscribed users and from which users can launch other text-based games. So far I have implemented the z-machine bridge, a MUSH bridge, and a simple Trivia game module.
To try it out, just add bridge@xmpplink.com to your contact list. It is currently set to auto-authorize any subscription requests received. Once the XMPP Bridge has accepted your subscription request, just initiate a chat with it and send the !help command to receive a list of valid commands:

Connecting to the Z-Machine:

To connect to the z-machine and run a z-game, use the !frotz command. For instance, !frotz zork1 will connect you to the Zork I game:

The z-machine implementation supports Save and Restore. Save files are automatically saved based on the player’s Jabber ID (JID). The advantage to this system is that a player’s Save files are guaranteed to be inaccessible to other players, but the disadvantage is that each player only gets one Save file per z-game. So think before typing “save”, as your last game save will be overwritten.
The !frotz command also supports a screen-width parameter (e.g., !frotz zork1 35) to make it easier for playing and viewing the output on mobile devices.
To get a listing of the available z-games, use the !frotzlist command:

Connecting to the MUSH:
To connect to the MUSH, use the !mush command.

Using a separate thread and a network socket to connect to the MUSH, input and output is bridged between the player’s Jabber client and the MUSH.
Connected to the MUSH:

Simple Trivia Module using an SQLite database for questions:

A trivia game can be started using either the !new command or the !join command, The trivia module supports up to five players per game. Several games can run concurrently and players can join or leave running games or start a completely new game. This module still needs some tweaks (e.g., accepting an answer of “20″ as well as “twenty”). Another issue is the fact that there is no real guarantee that messages sent by the bridge to players will arrive in the same order they were sent.


#1 by Ryan Parish on 2009/02/02 - 22:33
A couple of things to look at for google talk compatibility.
1. message replies are sent back to the bare JID rather than the JID + resource, you need to reply to the full JID per http://tools.ietf.org/html/rfc3921#section-11. Since google talk ignores resource priority all replies sent from the bot get received by all logged in resources.
2. Perhaps you should buffer the responses from the z-machine and then send a single message stanza when the z-machine is done sending data, rather than one message per line (I imagine your doing some kind of readline deal). With clients like google talk for blackberry and PSI the users nick or jid is displayed with each message like this…
[22:49:29] ———- XMPP Bridge commands ———–
[22:49:29] !about : About the Gamebridge.
[22:49:29] !enter : Enter the chat lobby.
[22:49:29] !exit : Exit the chat lobby.
[22:49:29] !frotz : Connect to a z-game. (e.g., !frotz zork1 [scrn_width] )
On a blackberry that’s half the screen real estate used up per line.
Keep up the good work!
#2 by Steve Gibson on 2009/02/02 - 22:35
You’re right about it needing to send to the
JID/resource. I’m not sure how I overlooked that, but I’ll definitely
see about fixing it.
The z-machine bridge buffering may be a bit more tricky (for me) to
figure out. I think the problem will be knowing when the process is
done sending data. Currently I’m using popen3() and a select() call
to grab the data from STDOUT and STDERR as the frotz process spits it
out. Dunno if you are a programmer, but here is what I’m doing:
I can probably play around with this a bit, maybe use a timeout or
something… but I definitely understand the issue with limited screen
real estate on a Blackberry. I personally use a Blackberry Curve and
the BeeJive IM client. What I do, though, is create a very short
nickname in my roster for the bot (like “xb”) and don’t use timestamps
on each message. The BeeJive IM client even goes one better and
doesn’t prepend the sender’s nickname for consecutive messages. In
addition to the point you raise, the current method has another
problem where occasionally lines in a paragraph will arrive in the
opposite order they were sent. Doing as you suggest and sending the
response from the frotz process as a single message will solve that
problem as well.
Thanks again for the feedback! I’ll take a look at these issues
tomorrow and will likely have an update running very soonish.
#3 by Steve Gibson on 2009/02/02 - 22:37
Actually, after looking into it a bit further, it looks like that RFC is directed at server implementations. Since the bot is a client, it is only required to send to the base JID. The server is supposed to determine how to route the message.
Still looking at buffering to frotz output…
#4 by Sven N. on 2009/05/12 - 07:03
I noticed the out-of-order messages are still there.
I think you should just add a short timeout (like 300msec) to the select() call and send all data collected in that time period as one message.
In pseudo code:
a. select() on stdout+stderr with a 300ms timeout.
b1. if you read something, append the bytes read to a buffer
b2. else: (you didn’t read anything i.e. the timeout kicked in), send the buffer data via xmpp and empty the buffer
c. goto a.
#5 by Steve Gibson on 2009/05/12 - 09:16
Sven,
Thanks. I’ll give it a go and see if that corrects the problem.
#6 by Zac on 2009/06/16 - 10:43
How long does the bridge normally take to accept an invitation? I’m eager to try this out.
#7 by Steve Gibson on 2009/06/17 - 09:18
@Zac
Zac, generally it occurs within a few seconds. Contact me via email or xmpp if you’re still having a problem.