The first text adventure games were extremely terse, compressed affairs. Players encountered the messages “You can’t go that way” and “You can’t see any such thing” a whole lot — and nobody minded.
Players today have much higher expectations. If, in writing a description of an outdoor location, you mention the distant hills and the flowering shrubs, players will expect to be able to examine them. When the shrubs are mentioned as present in the location but the response to ‘x shrubs’ is “You can’t see any such thing,” the realism of the game takes a nosedive.
I’ve now reached the point in the development of my next game where I’m going through several dozen locations and carefully adding such scenery items to each location. Scenery itself isn’t too difficult; the TADS 3 development system, which I’m using, defines a Decoration class, which serves admirably. But Decoration objects won’t always do the job. In one outdoor location there’s a prominent boulder. The boulder serves no real purpose, but that particular setting seemed to me to need a picturesque boulder. The player is bound to try ‘look behind boulder’, because hiding things behind large objects is a standard technique in interactive fiction. There’s nothing behind the boulder in this case, but nonetheless, I have to implement the command.
And what if the player tries ‘sit on boulder’ or ‘stand on boulder’? Those are reasonable commands. They don’t advance the story in the least, but if you want a realistic boulder, you really ought to handle those commands. Once I’ve done that, I have to invoke several TADS library methods so that the player can’t pick up objects that are on the ground while situated on the boulder.
I took a break from adding scenery to consider the pesky business of how large various portable objects are. TADS has a good system for preventing the player from putting large objects in small containers … but TADS doesn’t natively know that a bowling ball is large and a thimble is small. In order to get the system to work, you have to define the bowlingBall object with a bulk property of, say, 50, and the thimble container with a bulkCapacity of, say, 5. Once you’ve done that, TADS will handle the details and print out an error message if the player tries ‘put bowling ball in thimble’. But you have to add a suitable bulk property to every movable object in the game, and a suitable bulkCapacity to every container.
This whole process is about as much fun as doing the dishes. But if you want to build a model world that players can believe in, you have to do it.
I’ve barely started on the conversations. The game I’m working on has four or five major characters, plus a few others that you’ll run into along the way. The player is bound to want to chat with all of them about various topics that crop up during the story. The default message “Joe does not respond”, which would have worked fine 25 years ago, just won’t cut it today. Conversations, even when they don’t advance the story, help build realism by giving the player the impression that the characters are real people. They’re also incredibly useful for filling in story background.
TADS provides some slick tools for writing flexible conversations — but if your game has half a dozen characters and forty or fifty possible topics of conversation, as mine does, a lot of work will be needed. Plus, as the story unfolds, the characters’ responses to conversational gambits (such as ‘ask joe about beatrice’) may need to change drastically. Again, TADS provides great tools with which to do this, but the number of possible conversations starts to grow exponentially, so the writing process is not going to be polished off in a few hours.
Not only do you have to write all this stuff (“write” meaning both write the text the player will read and write the code that will cause the text to appear at the proper moment), you have to test it. If you forget to put a single plus sign ahead of a single conversation topic object, a dozen different conversations can become unavailable to the player.
Another example: Tonight I implemented a path between two outdoor locations. The TADS PathPassage class is ideal for this. But when I ran a test script to check whether an entirely different bit of business was working properly, I discovered that an important dramatic scene wasn’t working anymore. In this scene, the player character is supposed to lead another character along a particular route. The other character will protest if the player tries to deviate from the route. (TADS uses the GuidedTourState class for this.) But the route to be traversed now included a PathPassage, which meant that the other character was now refusing to let the player lead the way.
This was an easy bug to fix, fortunately. But I have a lot of sympathy for aspiring authors who feel TADS is just too darn complicated. It is complicated. It’s complicated because it lets you do so much. This is the third or fourth game I’ve written using TADS, depending on how you count. (“Mrs. Pepper’s Nasty Secret” was a collaboration, so it only counts for 1/2.) I hope eventually to become a power user!