*** CSC: Complex Sense Connector *** TADS 3/Adv 3 Library Extension Version 1.2 Created by M.D. Dollahite and Steve Breslin Requires Library Version 3.0.8 or better. Version 3.0.9 or better preferred. +------------------------------------------+ Table of Contents 1. Introduction 2. Changes 3. Installation 4. Using Complex Sense Connectors 5. More Examples 6. Known Issues 7. Translating 8. License +------------------------------------------+ ****************************************************************************** * Introduction The TADS 3 default library, Adv 3, contains an exciting new system for improving the realism of simulated environments: the sense connector. Sense Connectors allow a character standing in one room to perceive objects located in another, dismantling the old notion that rooms are separate self-contained cells and allowing rooms to come together into a larger worldspace. The sense connectors included in Adv 3 have a problem, however. They are implemented as simple multiple-location objects that allow sense data to pass between all of their locations omnidirectionally. Besides having no directionality, the multi-loc implementation also means that these sense connectors can appear as tangible objects only in the most trivial cases, where the same object should appear in all connected rooms. If an asymmetric connection is desired, the classes provided by the library are unsuitable. The Complex Sense Connector (CSC) extension steps in to fill this gap. It allows sense connections to be built from systems of one-way connectors that exist only in one location, but provide visibility into another. This opens up a whole range of new possibilities for the use of sense connections, including robust doors and windows, closed-circuit cameras, walkie-talkies, and so on. ****************************************************************************** * Changes 1.2 Corrected a bug in which an opaque window would display it's lookThroughDesc as if it were transparent if another sense connector joined the same locations. Also added the "shineThru" flag for OneWaySenseConnectors, which controls whether light is transmitted through them. It is appropriate for light to shine through windows, but inappropriate for it to shine through video monitors; this new flag lets you control this behaviour. Modified the sample game to demonstrate this. 1.1 Moved some code from Window and BasicWindow to the new OpenableWindow class, which simplifies setting up windows that the player can open. Fixed bug where LOOKing THROUGH a closed window showed the lookThroughDesc twice. Fixed up the sample game to work a little better. ****************************************************************************** * Installation 1. Place the contents of the CSC package in your library folder 2. Add csc.tl in your TADS 3 project file, after Adv 3 but before your game files. 3. If you want to use the provided templates, #include csc.h right after adv3.h and your language-specific header file. 4. If using library version 3.0.8, add the file 308mods.t to your project right after Adv 3 and before csc.tl. This file is not necessary for library versions later than 3.0.8. ****************************************************************************** * Using Complex Sense Connectors The CSC extension is made up of four source files. "csc" merely contains the module ID, please always include this file in your projects. "owsc" defines the OneWaySenseConnector class upon which the rest of the extension is built. "obstructor" is optional, it provides a more intuitive method for making sense connectors point-of-view-aware than the library's Occluder class. "window" gets you started with one of the most common customizations of the OneWaySenseConnector, windows; it is also optional. The additional file, "308mods", contains a patch for library version 3.0.8, and is not needed if you're using a later version of the library. -------------------------------------------- OneWaySenseConnector (owsc.t) OneWaySenseConnector is a mix-in class that can be combined with a Thing subclass to create a one-way sense link. Actors in the same room as the OWSC will be able to sense objects in the other locations referenced by the OWSC, but Actors in those locations will not be able to see through to the OWSC's location. The "connectionList" property determines what can be sensed through the connector; the normal Thing "location" property determines where they can be sensed from. The "connectorMaterial" property and "transSensingThru" method control how transparent the connector is. Here's an example: OneWaySenseConnector, Intangible location = fromRoom connectionList = [otherRoom1, otherRoom2] connectorMaterial = glass ; An actor in the room "fromRoom" will be able to see into otherRoom1 and otherRoom2, but actors in either of the other rooms will not be able to see into fromRoom, at least not through this connector. The "connectionList" property must be a list, but does not need to be rooms. For example, you can join two OWSCs together for two-way sense transmission: conn1: OneWaySenseConnector, Intangible location = room1 connectionList = [conn2] connectorMaterial = glass ; conn2: OneWaySenseConnector, Intangible location = room2 connectionList = [conn1] connectorMaterial = glass ; This is how the Window class discussed below works. OneWaySenseConnector has one other property that can be set. The "shineThru" property controls whether light travels through the sense connection or not. It is true be default, which is appropriate for windows and the like, but it can be set to nil for things like video monitors, which do not illuminate the location they display. Note that even when this is true, the usual rules regarding sense transparency apply (see the adjustBrightness() function in the library, in "sense.t"). -------------------------------------------- OneWayDistanceConnector (owsc.t) OneWayDistanceConnector makes the same customization to OneWaySenseConnector that the library DistanceConnector makes to SenseConnector. Set the "location" and "connectionList" properties as usual, but no connectorMaterial is needed because transSensingThru is already overridden to make a DistanceConnector. -------------------------------------------- Obstructor (obstructor.t) In real life, what you can see through a window is determined by the size and location of the window relative to the objects on the other side of it. For example, if a bookcase is pushed against the wall beside the window, you probably can't see it looking through the window from the other side. The shape of the window and the direction you're facing restrict your field of vision. To simulate this kind of occlusion, Adv 3 provides the Occluder class. However, Occluder has proven unintuitive due to its disregard for the containment hierarchy. Obstructor is a similar mix-in class that does the same thing, but does it by pruning entire branches off the sense path as it is built, instead of making an extra pass to remove arbitrary objects afterwards. Obstructor can be mixed-in with any SenseConnector or OneWaySenseConnector to provide obstruction capabilities. Simply override the "obstructObj" method to return true for any objects you want removed from view. For example: Obstructor, OneWaySenseConnector, Intangible obstructObj(obj, sense) { if(sense == sight && obj == bookcase) return true; else return nil; } ; Unlike Occluder, Obstructor can only be mixed with sense connectors, and is only useful for window-style occlusion. Occluder has some other uses that Obstructor isn't capable of. If you don't need this feature, don't include the module in your build, as it causes a slight drop in performance on slower computers if the feature is not used. If the feature is used, however, it provides better performance than doing the same thing with Occluder. -------------------------------------------- BasicWindow (window.t) BasicWindow is derived from OneWaySenseConnector, with extra features for implementing windows and other such two-way sense connections. BasicWindow also inherits from BasicOpenable and Thing. BasicWindows are used in linked pairs, much like Doors, and set their "connectionList" property automatically to their counterpart in the linked pair. To allow for opening and closing the window, BasicWindow also uses the "material" property in it's default transSensingThru method. "connectorMaterial" controls transparency when the window is open; the transparency of a closed window is given by the compounding of both materials. Thus, you may think of "connectorMaterial" as the transparency of the air on that line of vision, and "material" as the transparency of the pane or shutters. BasicWindow provides a property named "lookThroughDesc", which can be used to describe what is seen through the window. The default implementation uses lookAroundWithin to produce a normal description of the room on the other side of the window. You can use "roomRemoteDesc" and the other various "remote" description features to customize this, or you can override lookThroughDesc to provide a simple static description (though the latter somewhat defeats the purpose of the BasicWindow class.) If you want to display a look through response programmatically, call the window's "lookThrough" method with the actor doing the looking as the only argument. This method is called automatically when the object is Examined, after the regular long description. -------------------------------------------- Window (window.t) As implied by the name, BasicWindow does not handle any Actions. Window adds handling for LookThrough, and can be combined with Openable to handle Open and Close. Openable should be placed to the right of Window in the superclass list to make sure inheritance works out right. Here's an example, using the templates defined in "csc.h": southWindowSide: Window, OneWayDistanceConnector, Fixture 'window' 'window' @southRoom "It's a plain white-trimmed window in the north wall. " ; northWindowSide: Window, OneWayDistanceConnector, Fixture ->southWindowSide 'window' 'window' @northRoom "It's a plain white-trimmed window in the south wall. " ; The -> part of the template sets the "masterObject" property, just as it does with most other classes derived from Linkable. -------------------------------------------- OpenableWindow (window.t) OpenableWindow mixes Window and Openable together for you, and also adds handling to automatically LOOK THROUGH a window when opening it (just as Container automatically LOOKs IN when opened). This class also includes a "remote open" notifier like in Door, which announces when the window is opened from the other side. ****************************************************************************** * More Examples -------------------------------------------- A webcam: webcam: Thing 'webcam/cam' 'webcam' "It's a battery-powered wireless webcam. " ; pda: OneWaySenseConnector, Thing 'pda' 'PDA' "It displays the feed from the webcam. " connectionList = [webcam] connectorMaterial = glass shineThru = nil examineStatus() { inherited; webcam.lookAround(gActor, LookRoomDesc|LookListSpecials|LookListPortables); } ; NOTE: Some odd things may happen if the PDA is seen from a distance or in other special situations, so additional considerations may be needed on the PDA object to make everything work right in such cases. Since the solution to these problems is usually case-specific, they are left as an excercize for the reader. One method of solving them is demonstrated in the sample game. -------------------------------------------- A look-out tower: OneWayDistanceConnector, Distant 'forest' 'forest' @lookOutTower "You can look out over the entire forest from here. " sightSize = large connectionList = [forest1, forest2, forest3, forest4] examineStatus() { fromPOV(gActor, &lookAroundWithin, gActor, gActor, LookListSpecials|LookListPortables); } ; This will respond to an EXAMINE FOREST command with the connector's description following by a listing of the contents of the four forest rooms. With the right inRoomName overrides, this will make the entire forest appear more or less as a single object from the tower, but as separate rooms from within the forest itself. ****************************************************************************** * Known Issues * Although a pair of BasicWindow objects are mostly made to act as two sides of a single physical object, they do not share their "material" or "connectorMaterial" properties. Although this may sometimes be counter to expectations, it is considered a feature, not a bug, because it allows for such things as one-way mirrors. * When two sense connectors (either CSC or library) connect the same two locations and are both opaque to touch, attempting to reach an object in the other location will choose one of the two connectors arbitrarily as the obstructing object. With intangible library connectors this isn't really a problem, but with tangible CSC connectors this sometimes results in illogical actions; for example, the included sample game will often try to reach objects through the PDA instead of the window. There does not appear to be any way to solve this problem short of completely rewriting the library's sense path algorythm. Since that is unlikely to happen, the best solution is probably to replace the appropriate library messages with alternatives that don't mention which object is causing the obstruction. * It has been suggested that descriptions of object should be prefixed with a mention of the sense connector they are seen through. Unfortunately the current design of the library's sense path algorythm does not provide objects with any information on the path used to reach them, so this is not possible unless that limitation is removed. * Theoretically, it should be possible to combine a Door with a Window or OpenableWindow to make a door you can look through, but this is currently untested. ****************************************************************************** * Translating This extension is mostly internal logic and contains very few strings. Currently, only the "window" modules contains strings (aside from the module ID, which even the Adv3 library does not seem to consider a language-specific component). As there are only a four of them, I did not deem it necessary to create a separate language module; just use a modify statement in your project to replace them. ****************************************************************************** * License TADS 3 Complex Sense Connector Extension Copyright 2004 M.D. Dollahite and Steve Breslin. All Rights Reserved. This extension may be freely distributed as long as all files remain intact and unaltered. It may be used in any TADS 3 game without restrictions. If used in a game, we'd appreciate a mention in the credits, but it is not required. If you wish to create a port or other derivative work, contact the authors for permission. At time of writing, their email addresses are: M.D. Dollahite: ryukage@aol.com Steve Breslin: versim@hotmail.com If contact cannot be established by email, try the internet newsgroup . This software is provided "as is" without warranty of any kind, express or implied, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose or a warranty of non-infringement.