"Sorry guys, I missed the rolls. Let me log in again."
In 2009, myself and a group of friends were playing a Dark Heresy tabletop roleplaying game over the Internet. We used TeamSpeak for voice communication and a bot implemented over IRC for simulating die rolls.
One of our players had a problem, however. If a connection from his computer was inactive for five minutes, this resulted in him being disconnected. This usually meant he had to log in to IRC for each die roll, and he would frequently miss other people's rolls, and thus much of the excitement during these sections of the game. This was extremely frustrating for both him and us.
Once upon a time, I was a coder for a MUD. Since then, I have begun development for a couple of experimental codebase frameworks that were, unfortunately, never in a complete enough state to see the light of day. Nevertheless, I decided I had the knowledge, and I had the technology (since our gaming group maintains a colocated box upon which the TeamSpeak server and other goodies are installed). Why should I not use my old MUD knowledge to put together something everyone can use for rolling dice?
And so I did. A few lunchtimes later, most of which was spent looking for a decent enough pun, the Paradice project was born.
The first iteration of Paradice was what could be considered a simple one-room talker. It was, like most MUDs, Telnet-based and fundamentally line-mode, although it made use of the "scrolling region" (DECSTBM) feature of the VT100 protocol. This allowed for two regions on the screen, one containing the names of all the players currently online, and the other containing the more normal interactive area of dice rolls, whispers, chats, and so on.
The disconnection issue was also solved by using a feature that I never thought would be useful: every thirty seconds or so, the server sends out a two-byte packet that represents a Telnet NOP (No Operation instruction). On all good terminal software, including PuTTY (which I had recommended to our group), this has no visible effect, and is thus a non-intrusive solution to the problem.
At this point, Paradice was everything that it needed to be, but not what I wanted it to be. There were two major complaints with the program. First, due to the scrolling regions feature I was using, there was no scrollback available in the client. This could be solved by removing the feature that used the scrolling regions and reverting to the classic scrolling text look-and-feel that MUDs have. However, it would also mean that the player list was no longer visible all the time.
The other complaint was the same complaint I had about MUDs in the late ‘90s: if you were typing a command in, and some other action occurred in-game, then it would interrupt your typing. These days, this problem is mostly solved by using a MUD client. But the vast majority of clients do not support scrolling regions, so the solution became not only to get my gaming group to download yet another piece of software, but also to re-implement a feature to make it less useful.
I found this to be unacceptable, especially since I already knew that this was solvable using the technology that was in front of me.
By using the Telnet options of WILL ECHO and WILL SUPPRESS_GO_AHEAD, terminals change from line mode to the so-called "character-at-a-time" mode, or character mode. At this point, the terminal becomes an 80 x 24 character-by-character window rather than an 80 x ∞ line-by-line window. Add your VT100 protocol onto this and you control the display in its entirety, including all text on the screen and the cursor position.
Taking my inspiration from Java, I created a library called Munin that implements a component-based user interface where positioning and sizing of components is controlled by a series of layout objects. For example, a container component that is managed by a grid layout will arrange its components in a fixed number of rows and columns. A compass layout will arrange its components by squeezing them to the north, east, south or west sides and giving the remaining space to a centre component.
Each element of a component is then an attributed character that contains information about the underlying character it represents. This includes graphical attributes, such as foreground colour and background colour, lesser-known attributes such as polarity and underlining, and its character set and locale attributes, which are useful for accessing alternative character sets for graphical drawing characters.
Actually drawing to the display is one of the more interesting parts of the process, of which the essence is an attempt to update changes to the screen in the most efficient way possible. For example, if a text box's border has changed colour, then only the characters for the border need to change; the text inside does not need to be rewritten. This involves maintaining a copy of the client's screen on the server and some careful detection of the parts of the screen that are changed. Then, the client's cursor is manipulated to produce the shortest sequence of characters that can be sent to the client to complete the update.
Paradice also implements an event framework that recognises VT100 command codes and forwards them through the user interface. For example, hitting the up arrow on the terminal sends the CUP sequence, ESC [ H. This can filter through the top-level window component, down through the containers to, for example, the command prompt component. This component then looks at the command history and fills its text area with the previous command. Handling these command codes can result in a much more intuitive interface than just handling textual commands alone.
Later on in the development of Paradice, I implemented some button-like components. However, to "click" these buttons, you had to tab to them and hit either space or enter. When one of our gaming group asked me why clicking on them wasn't working, my initial response was that it couldn't work that way. After research, I stumbled upon another protocol layer that proved me wrong.
PuTTY also implements many of the XTerm control sequences. These overlap somewhat with the VT100 control sequences, but with the addition of some very interesting extensions — for example, being able to control the text in the title bar of the client window and to detect mouse button presses. Since this discovery, the capabilities of the user interface have grown greatly, to the point where one of the most recent features is almost entirely point-and-click based, although it can still be controlled via the keyboard.
Development of Paradice is still ongoing, but the conclusion of this tale is that the features of the basic textual interface that MUDs have been provided with since the 1990s are woefully underused. Some of the protocols that exist in certain clients need never have existed at all, their functionality already being replicable using existing features. Worse yet, while clients have gone forward to produce some astounding pieces of work — KaVir's work on customising MUSHClient is truly inspirational in this respect — the clients have also gone backwards in not supporting character mode, and by having input fields separate from the output display. The only client I know of not to have gone backwards this way is TinTin++.
Truly, the MUD codebase of tomorrow would be better served by a client with character mode, fully server-controllable displays and the scripting and customisability of modern clients. With client development having once more come to the foreground over the past few months and the launch of new clients such as The MUD Portal, I hope that developers of these clients will consider this article carefully.