Chapter 6 - Expanding the Horizons
Doors and Windows
If you've managed to follow this Guide so far, you should have grasped most of the basics of programming in TADS 3. In the present chapter we'll look at more features of the library, but we'll move on a bit more briskly, on the assumption that much of the code should start to be self-explanatory.
In order to make Heidi's life more difficult, we'll make it harder for her to get hold of the chair she needs to climb the tree. To do that, we simply need to supply the cottage with a locked front door and hide the key in some out-of-the-way place.
The first thing to realize is that doors in TADS 3 are normally two-sided. That is, they are generally represented not by one object, but by two, the two objects being the two sides of the door. At first sight this may seem something of an unnecessary complication, and it does require a little more work, but not as much more work as you might think. Provided the two sides of the door are properly set up, the library will take care of keeping them in sync (i.e. ensuring that one side is open or closed or locked or unlocked when the other is). It will also take care of making travel through one side of the door result in the traveler arriving in the location of the other side. One reason for doing it this way (i.e. with each side of the door represented by a separate object) is that it allows more flexibility; the two sides of a door often aren't identical: they may, for example, be painted different colours, or they may use different locking mechanisms, say with one side requiring a key and the other using a paddle.
We'll start by adding the outside of the front door (which should be contained in outsideCottage):
|
"It's a neat little door, painted green to match the window frame. "
keyList = [cottageKey]
;
|
|
This needs to be located in insideCottage, and we need to change the out property of insideCottage to cottageDoorInside. The ->cottageDoor is a template shortcut for assigning cottageDoor to the masterObject property, which (a) keeps both sides of the door in sync (both open/closed and locked/unlocked) together, and (b) tells each door what its other side is (through code executed in the preinitialization routine, which we don't need to worry about).
Note that we have defined the outside of the door as a LockableWithKey and the inside as simply Lockable; this reflects the way many house doors in fact behave (we don't need a key to lock or unlock the front door from the inside). Note also that the order of the classes here is important: Lockable, LockableWithKey or IndirectLockable must come before Door in this kind of declaration, or else the lock won't work. The short explanation for this is that Lockable, LockableWithKey and IndirectLockable are examples of mix-in classes (not derived from Thing) which must come before the any Thing-derived class with which they are combined.
Before this door will work, we have to define the key object. As a temporary measure (we'll move it elsewhere later), we'll do this with simply:
|
|
The question is, how should this be implemented? We could just write a LookThrough routine that displayed a pre-programmed message, but that's less than ideal, since the contents of the cottage could change as the player moves objects around. Writing a LookThrough routine that does the job properly is quite tricky, so for now we'll attempt something a little less ambitious: a window through which whatever is on the other side is visible. We'll return to a more sophisticated LookThrough later.
To create a window through which the contents of another location are visible, we need to use a SenseConnector, and locate it in the two rooms joined by the window:
|
"The cottage window has a freshly painted green frame.
The glass has been freshly cleaned. "
connectorMaterial = glass
locationList = [outsideCottage, insideCottage]
;
|
If you compile and test the game now, you'll find that this works, but that objects visible through the window are listed in a less than ideal fashion. There are several steps we can take to improve that. You'll recall that we defined an initSpecialDesc on the chair. The first problem is that we'll now see that initSpecialDesc when Heidi is standing just outside the cottage:
|
You stand just outside a cottage; the forest stretches east. A short path leads round the cottage to the northwest.
|
|
|
see a plain wooden chair sitting in the corner of the front room. "; }
|
If you test the game now, you'll find the window works okay with the chair, but is not so good with portable objects. For example, if you drop the key outside the cottage and then go inside, you'll see the key listed as:
|
|
|
In the inside cottage, you see a small brass key.
|
|
|
"The front parlour of the little cottage looks impeccably neat.
The door out is to the east. "
out = cottageDoorInside
east asExit(out)
inRoomName(pov) { return 'inside the cottage'; }
remoteRoomContentsLister(other)
{
return new CustomRoomLister('Through the window, {you/he} see{s}',
' lying on the ground.');
}
;
|
|
Through the window, you see a small brass key lying on the ground.
|
Similarly, if the key is left inside the cottage, then from the outside you'd see:
|
Inside the cottage, you see a small brass key.
|
|
Getting Started in TADS 3
[Main]
[Previous] [Next]