The Pianosa Reference Version 1.0 (c) 1999-2000 John McCall (TenthStone) tenthstone@hotmail.com Warning: this is a reference, not a primer. Any attempt to learn Pianosa should be accompanied by a copy of the library and any Pianosa source code that happens to exist. Any attempt to learn TADS directly with Pianosa is unadvisable at this time. Introduction I suppose anyone reading this paragraph is wondering why I wrote an alternate library for TADS. Well, here goes an attempt to explain. My problem with adv.t is that too often I find myself fighting against the library, trying to get some basic effect but lacking any good tools to that end. I don't mind hacking a library -- my work in progress has required me to modify Pianosa a good bit, and the more generally useful of those modifications, like doorwayframe, I've permanently placed in the library. But my old adv.t sources were riddled with hacks and out-and-out replacements -- and that's where I draw the line, when it's no longer worthwhile to keep patching the old system. My problem with WorldClass is that I can't figure out how to extend it. The library tends to work via long, complicated procedures without any escape hatches; the fact that it works on a higher level than adv.t serves only to make the inevitable adjustments that much more difficult to handle -- see, for example, the monstrosity that is listcontentsX. I haven't looked very hard at Kevin Forchione's Alt library yet, although that's something I've been meaning to do. (Pianosa predated the unification of Alt by a few months; since then, I've had three major IF projects (Pianosa, Finch (a library for TADS3), and my work-in-progress (WIP)), so my IF programming time has been mostly devoted to those). Why should someone convert to Pianosa? They shouldn't. Unless their work is still far from complete (programming-wise, not writing-wise), or unless they're absolutely frustrated in their current library, it's not really worth the effort to actually convert a work in progress. Why should someone use Pianosa? Because it's a hacker's library. Because I've painstakingly opened as many processes as I could think of to easy adjustment. Because it is my hope that that person never need to wage war against the library again. Because it's a powerful library, with a large number of features and options that can fiddle down to the smallest technicality. Because it's a simple library, with very few direct requirements if one's willing to accept the defaults. Because moving from one extreme towards the other has been made as painless as I think it can be without sacrificing some of the power underneath. Because it's an intelligent library, with a large amount of code devoted to avoiding unnecessary duplication, while preserving the capability of fine dinstinctions. Because it's a creative library, engineered to make it as easy as possible to write the damn game and stop fiddling with the controls already. Because it's here. Because it's good. Because it's time. Past, present, future. What will come of Pianosa in the age of TADS 3? That's a good question, and the answer depends largely upon whether TADS 3 becomes widely accepted in the IF community. I'm not going to stop supporting it regardless, but if TADS 3 catches on I doubt many will spend much time on an alternative library for an outmoded old system. That's all I've got to say about that. -- TenthStone Pittsburgh 8-28-2000 Table of Contents Searching this document for the text in the first column should browse instantly to that section of the reference. Chapter 1 Quick Start 1.0. The very quick start 1.1. The quick start Chapter 2 TADS Programming (not found) Chapter 3 The Pianosa Classes 3.1.0. thing 3.1.1. room 3.1.2. container, cover, mask, surface 3.1.2.3.0. movableActor 3.1.3. other gameworld classes 3.1.3.12. Verb 3.2. Pianosa defined objects 3.3. Inheritance hierarchy Chapter 4 The Pianosa Functions 4.1. Pianosa defined functions 4.2. General functions 4.3. External functions Chapter 5 The Pianosa Procedures (not found) Chapter 6 Supplemental Files 6.1. ts_codes.t 6.2. ts_funcs.t 6.3. ts_grid.t 6.4. ts_menu.t 6.5. ts_sense.t 6.6. ts_std.t Chapter 1 Quick Start 1.0. The very quick start I'm going to assume you know how to compile a file, so open ts_basic.t and compile it. It should work -- that's all it takes. And that's the very quick start. Note that our pathetically bare game is already close to 100KB even when compiled without debugging symbols. We'd better add something to it to make it worthwhile, since all we've got in the world is a default description which doesn't even make sense. I'll take you through a quick sample game, but understand this: the majority of adv.t-designed code will still work in Pianosa, and most of what doesn't work will work with a quick name-change. adv.t method is very sound there, and I've taken care not to disturb it. Where Pianosa has a marked difference, and where changing libraries will be hardest, is advanced code, where you're not merely defining something but where you're trying to achieve something. That's not the sort of problem I can guide you through in this kind of reference. You should first look at the appropriate class's entry here; if the information you need isn't there, check its superclass(es); if you still need help, please feel free to contact me at tenthstone@hotmail.com or better yet, on the newsgroup rec.arts.int-fiction (remember to put [TADS][Pianosa] in the subject line). I'm always open to suggestions, and I always give credit when I remember to. Anyway, on to the sample game. 1.1. The quick start Let's look at what we've got in here already. #including ts_std.t gives us Pianosa and the standard definitions package. version holds information about the game; commence() prints startup messages; startroom is the room we're in. First, let's annoy all the auteurs and pick our title before we write our game. How about, "The House of Locked Doors". It's nicely mysterious, yet kitschy enough to qualify for a programming reference. Besides, I've changed it anyway; it used to be "The Hidden Button." Looking up the version object in this reference (try searching for "version:"), we find that version.sdesc holds the name of the work. Filling in a little, we have version: object sdesc = "Is Road Like Wish So Empty?" bdesc = "<< sdesc >>, unrelease 1 (5 September, 2000)" ldesc = "<< sdesc >> \nAn interactive English in Three and Twenty Easy Steps for native Ashwen speakers, copyright (c) A.D. 2000. \n<< versionVerb.ldesc >>" ; Now we need a commence() function. Searching here for it gives us one reference: it's called by init(). In fact, commence() is responsible for all the introductory text printed by the game except for the initial room description (and if you're using random numbers, you might want to throw in a randomize() call as well). commence: function { "\H+\b \bOh by the village winds, there he goes again. Rising over the walls of the night's camp is another of his damned green bubbles. Some little girl from the nearby town -- Brinson-on-Gere, is it? -- comes out to look after the flocks, and Faraj the Great has to show off his little magic tricks. \bAh, but as long as it amuses the children, you ought not to complain. There's precious little to cheer one in an age like this. You smile softly to yourself, lean on your sword, and dream of your own family, safe far from these troubled borderlands. \bWipe that insipid grin off your face, Brac. That sharp crack could only be Mirane's voice, and you open your eyes. There she is again, the newest member of your party, only an hour after she left to check on the road ahead. \bYou look in Mirane's eyes and see no anxiety; the road, then, must be clear. But why has she returned so quickly? Her smile is a trace more smug than usual; perhaps she's found something interesting. You search for a subtle way to coax the information out while still allowing her her moment in the sun -- and then you've got it, you know exactly what to say, you open your mouth, and you say, \bIs road like wish so empty? \b \b \b<< version.ldesc >> \b \b \b"; } Now on to the third required entry, startroom. In fact, the code requiring startroom is in std.t, so if we were working directly with Pianosa, we wouldn't need startroom at all. But that's all irrelevent. Technically speaking, we could use .roomdesc and .statusdesc instead of .ldesc and .sdesc, respectively; however, I've gotten into the habit of using the adv.t conventions, and I only use the Pianosa equivalents when there's a need to differentiate between the two, as in when the room object is a physical world object (e.g. a vehicle). startroom: room sdesc = " BOOKMARK: The example game here is not complete ; Chapter 3 The Pianosa Classes The core of any TADS library is its classes. I could go on and explain why, but there's really no point so I won't, subject to later revisions of this paragraph. In Pianosa, there are five core classes, representing the five core groups of gameworld ideas. A thing is a basic inanimate object. A container class object is to meant to hold other objects. A character can perform actions. A room is meant to hold characters. Actions define the player's interface with the gameworld. This categorisation will never be mentioned again. There will be no test. Partially because of this idea of core classes, but mostly because it makes organisation simpler, the library is not ordered purely by inheritance and alphabetisation. There are three general sets -- thing-derived, container-class-derived, and other-base-classes. 3.1. Class reference. 3.1.0. thing class thing: object thing is the central class to the adv.t archiecture, from which Pianosa derives. Every phsyical object in the gameworld inherits from thing. It is therefore somewhat appropriate that most of our time will be spent with thing. Other classes which may inherit much, if not all, of their behavior from thing have properties more specific to themselves described in their entries. There is probably no reason to inherit directly from thing in actual game code, although there's certainly no reason not to. Movable objects which can be picked up and carried with the player should be defined as item; other objects are as like to be fixedthing or a more specific class. Attributes .adesc Displays the name of self preceded by the indefinite article. Defined. .adjective Vocabulary attribute; should be an unbracketed list of single quoted strings. .bdesc Displays a brief description of objects listed seperately (see .describealone). Defined, but better redefined. .behind Defines the location of self. Only one of the following properties is applicable at any one time; priority is in the following order: .in, .on, .under, .behind, etc. Should point to a valid container class object. These properties are not updated after preinitialization. .bulk Defines the bulk (size) of an object. Container-class objects can set maximum bulks which they can carry. .cdesc Displays a cursory description of an object when it is picked up (via a "take" or "put in/on/etc." command). Returns true to abort the pick-up. .circularmessage( object ) Displays a message forbidding a circular object scenario (where A is in B which is in A, or even more complex); called on the object being moved. .dart Displays the correct definite article. Defined by .isproper. .describealone Defines whether self should be listed alone instead of in a standard inventory. If so, .bdesc is called after the standard inventory is concluded. .Dropped( actor ) Displays a message saying that self has been successfully dropped by actor. .followlist List of all objects which should be sent a follow message when this object moves by .moveInto. .grammarperson Determines which grammatical "person" this object should be conjugated by; used in association with .isplural. Defined as THIRD_PERSON; other options are FIRST_PERSON, SECOND_PERSON. .iart Displays the correct indefinite article. Defined by .isproper and .isThem. .idesc Displays the name of self as for an inventory listing, with .specialdesc appended. Defined. .in See .behind. .isdesc Displays self's .sdesc followed by a conjugated form of to be. Defined. .isfixed Flag determining whether self is fixed or not. If it is, .putInto checks with .Fail before continuing. .isfollowable Flag determining whether self can be followed or not; referenced only by the doFollow routine itself, and not by the actual following routines. .isher Flag allowing this object to be referred to as "her". .ishidden Flag for an object which should not be listed until it is taken by an actor. .ishim Flag allowing this object to be referred to as "him". .ispasttense Flag marking whether verbs conjugated with self as subject should be placed in the past tense or not. Defined as parserGetMe().ispasttense. .isplural Flag marking whether verbs conjugated with self as subject should be placed in one of the plural forms. .isproper Flag marking whether self's .sdesc is a proper noun. .istaken Flag marking whether self has been taken by the player as of yet. Objects getting their .istaken attribute set true also have the .FirstTake message called. .isthem Flag allowing this object to be referred to as "them". Defined as self.isplural. .ldesc Displays a long description of the object, as displayed when examined. Defined, but better redefined. .locdesc Displays a description of self's location. Defined as self.locate.posdesc( self.position ). .Movearound Displays a message stating what happens when the object is moved (e.g. north). An error message, not a handling method. .multisdesc Displays the name of self as it should appear before the colon when multiple objects are referenced in one command. Defined as .sdesc. Once a parser mainstay, now only used as referenced by .prefixdesc. Example: >Take all. red hat: Taken. blue scarf: Taken. .noun Vocabulary attribute; should be an unbracketed list of single quoted strings. .objcount Defines the number of objects referenced by self. Roughly defined such that if .isThem is true, .objcount is more than one. Otherwise, one. Such is sufficient. .on See .behind. .plural Vocabulary attribute; should be an unbracketed list of single quoted strings. .plural allows groups of objects to be referred to at once; it should consist of plural nouns which can then be used in this fashion. .pluraldesc Displays a plural form of .sdesc by appending .pluralizer. Defined. .pluralidesc Displays a plural form of .idesc. Defined. .pluralizer Displays what to add to self's .sdesc to make it plural. Defined as "s" when self isn't already plural. .predthedesc Displays a short description of self, considering that it is a predicate object in some sentence. Defined as .thedesc. .prefixdesc Displays a short description of self before executing it in a multiple-object command. Defaults to .sdesc. .Put( actor, position, object ) Displays a message stating that the object has been successfully put in a position around object; called by the doPutX routines. .readdesc Displays what can be seen when self is read (although verDoRead must be cleared) .sdesc Displays a short description of the object, i.e. a noun phrase without article. .specialdesc Displays additional information on self to be included in a standard inventory. Defined for clothing and lamps. .subjthedesc Displays a short description of self, considering that it is the subject of some sentence (should be lowercase). Defined as .thedesc. .Taken( actor ) Displays a message stating that the object has been succesfully taken by actor. .thatdesc Displays a reference to self as an indefinite pronoun (`that'/'those' ). Defined. .thedesc Displays the name of self preceded by the definite article. Defined. .thrudesc Displays what can seen when self is looked through. .uberlocate List determining the location of self, in the form [ position object ]. .under See .behind. .isdesc Displays self's .sdesc followed by a conjugated form of to be, but in the past tense. Defined. .weight Defines the weight of an object. Container-class objects can set maximum weights which they can carry. Methods .addadjective( word ) Adds a word (or list of words) to self's set of adjectives. Words should be single quoted strings. .addnoun( word ) Adds a word (or list of words) to self's set of nouns. Words should be single quoted strings. .addplural( word ) Adds a word (or list of words) to self's set of plurals. Words should be single quoted strings. .cantreach( actor ) Displays a message stating that while self is visible, it is not reachable. .checkdrop Checks with the object to see if anything special should be done before the object is moved. For instance, clothing should be taken off. It is usually called by direct-object movement routines such as .doPutIn and .doDrop, but it is not called by .putInto. .clearloc Resets .uberlocate to [ nil nil ]. .deladjective( word ) Removes a word (or list of words) from self's set of adjectives. Words should be single quoted strings. .delnoun( word ) Removes a word (or list of words) from self's set of nouns. Words should be single quoted strings. .delplural( word ) Removes a word (or list of words) from self's set of plurals. Words should be single quoted strings. .distinguish( object ) Returns whether self can be distinguished from object. Called by contListing(), which considers two items indistinguishable only if .isequivalent is true on both and both .distinguish routines return nil. By default, calls isIndistinguishable(). .Fail Checks whether a fixed object (.isfixed = true) can be moved; if it cannot, should display a message and return true. .Follow( object, destination, position ) Displays statement that self is following object into a certain position around destination. .hasclass( class ) Determines whether self has a certain class or not. I never can remember whether it's isclass( object, class ) (it is) or the other way around. .isaddressable( actor ) Determines whether self is addressable by actor. Defaults to .isVisible. .isheldbyactor Determines whether self is being ultimately held by an actor or not. .isin( object {, position} ) Determines whether self is located, but not necessarily visible, around an object. If a position is given, either self or some ultimate container of self must be held in that position around object. Compare .isvisiblyin. .islisted Determines whether self should be listed in the standard inventory or not. .isreachable( actor ) Determines whether self is reachable by actor. .isvisible( vantage ) Determines whether self is visible from vantage. .isvisiblyin( object {, position} ) Determines whether self is visible around an object. If a position is given, either self or some ultimate container of self must be held in that position around object. Compare .isin. .Leaving( actor ) Message sent to self when actor leaves a room. Returns true to be removed from .leavelist. .locate Determines the location of self. .locatetree Determines the location tree of self, in form [ self, self.position, self.locate, self.locate.position, self.locate.locate, ... ]. Recursive. .Move( target ) Message sent to self by .putInto to verify movement to target. Returns true to abort movement. .position Determines the position of self relative to .locate. .sameloc( object ) Determines whether self is in the same location and position as object. .Say( actor ) Displays how actor would refer to self. .totalweight Determines the total weight of this object and all of its contents. .totalbulk Determines the total bulk of this object and all of its contents. .ultimatelocate Determines the ultimate (typically, ultimate visible) location of self. .verifyremove( actor ) Verification routine which calls .verGrab all the way up the contents tree until it reaches either the actor or nil. Called by direct-object movement verification routines. Actions .dropFrom( object {, position {, jostle}} ) Drops self from a certain object and position (default = In) according to .dropping. .follow( object, desitination {, position} ) Causes self to follow object into a position (default = In) around destination if possible. .forceInto( object {, position } ) Moves self into a certain position (default = In) around object (or nil) by calling .forceRelease on self's location (if exists) and .forceAccept on the target (if exists). .hearNoise( type ) Responds to a sound of a certain type. .jostle( jostle ) Jostles this object and everything in it. By default, runs through the contents calling the same level of jostle. .listen( sound, specificity ) Responds to a speech-sound of a certain type, either directed at self or not. .mixWith( list ) Mixes self with every object in the list. Should return true if it moves any of the objects. .moveInto( object {, position} ) Moves self into a certain position (default = In) around object (or nil), first notifying containers via .Grab messages and followers via .follow messages and then calling .forceInto. .putInto( target {, position {, jostle }} ) Moves self into a certain position (default = In) around object, verifying the movement with self (see .routePutInto) and the target (see .routebehind), checking for weight and bulk overload, and then one last time checking with the source (see .Drop), self (see .Move), jostling effects (see .jostle), and the target (see .Take) before calling .moveInto. Returns true upon a routing halt or completion; returns nil for failure. .routePutInto( target, position, jostle ) Routes wheres self, being put into a certain position around target, should really go. If it should abort the movement, this should return true. .sayTo( actor, sound, specificity ) Responds to a speech-sound of a certain type, either directed at self or not, usually by calling .listen. .speak( sound ) Displays a message on how self would cause sound to be emitted. Returns true to abort. - thing subclasses 3.1.0.0. dialthing class dialthing: thing dialthings are gameworld objects which happen to have dials upon them which can be set anywhere from .minsetting to .maxsetting, or to strings corresponding to labels upon the dial. Unlike most other subclasses, dialthing supplies its own .ldesc supplying information on the dial's settings. Attributes .maxsetting Number of the maximum setting on the dial. .minsetting Number of the minimum setting on the dial. .setting Number of the current setting on the dial. .settings List of valid labels on the dial. .settingsvalues List of valid settings on the dial corresponding to entries in .settings. .settingsonly Flag determining whether numbers can be used for the dial (nil). Defaults to nil. Methods .validsetting( number_or_string ) Determines whether the given setting is valid on the dial. 3.1.0.1. fixedthing class fixedthing: thing fixedthings are gameworld objects which happen to be fixed (perhaps temporarily) within a location. The default behaviour has .isfixed set true and .Fail set to return true -- aborting any attempt at movement. fixedthings are typically important enough to warrant their own descriptions, so .describealone is set to true. If tied to a room, they would also usually be described in the room's description -- so .ishidden is set true as well to suppress the individual description. -- fixedthing subclasses 3.1.0.1.0. buttonthing class buttonthing: fixedthing buttonthings are fixed gameworld objects which may be pushed. By default, pushing the button toggles .isactive on and off. Attributes .isactive Flag determining whether self is on or off. Defaults to nil (off). .routebutton Object to modify the .isactive properties for. Defaults to nil, meaning self. Actions .turnOn Sets .isactive true and displays a message. .turnOff Sets .isactive nil and displays a message. 3.1.0.1.1. decoration class decoration: fixedthing decorations are fixed gameworld objects which may be examined and nothing else. To add another possible action, adding the appropriate verification routine to the object definition will let it pass through -- but really, adding other actions is not advisable as seasoned IF players have grown accustomed to not being able to do anything at all to a decorative object. While decorations should be added for every object listed in or implied by the room description, it is often a nice touch to define such objects as real gameworld objects that may be fairly interacted with. Any object of any importance at all should definitely not be declared a decoration. You've been warned. Attribute .Error Message to the effect that this object is not important. 3.1.0.1.2. distantthing class distantthing: fixedthing distantthings are gameworld objects that are not really present in this room, but instead are simply visible from here. Any attempt at interaction with the object fails. Attribute .Error Message to the effect that self is too far away to be dealt with like that. 3.1.0.2. foodthing class foodthing: thing foodthings are gameworld objects which happen to be edible. Attributes .Eat Displays message upon consumption. Returning true aborts the action. .foodvalue Number specifying how many extra turns the player can last on the basis of self. .meal Number specifying how many meals can be made of self. 3.1.0.3. item class item: thing items are normal gameworld objects which can be moved around at ease. There is no special code within the class definition; in fact, there is no code whatsoever. item is a marker class. -- item subclasses 3.1.0.3.0. clothingitem class clothingitem: item clothingitems are normal gameworld objects which can be worn by an actor. The act of wearing is summed up like this: self is held by the wearer and .isworn is true. Attribute .isworn Flag determining whether the object is being worn or not. Defaults nil. Actions .remove Removes self by setting .isworn nil. .wear Wears self by setting .isworn true. 3.1.0.3.1. keyitem class keyitem: item keyitems are gameworld objects which can be carried around and used to unlock things. What they can unlock is not up to the key: it's up to the door, or the chest, or whatever. keyitem is an enabler class, simply defining the verb actions and leaving all the work to the door. 3.1.0.4. lightsource class lightsource: thing lightsources are gameworld objects which can supply light to a darkened room. The class supplies code in the .doTurnon routine for turning on the lights, but that is all. Attributes .isactive Flag determining whether the light is on or not. .islamp Flag determining whether the object is a lamp. All objects with this attribute set true at preinit() are assembled into global.lampList. .islit Alias to .isactive. 3.1.0.5. liquid class liquid: thing liquids are gameworld objects which are liquid in nature. They can be poured onto random objects, mixed with other liquids, and spilled if the player isn't careful. They can (as defined in Pianosa) be put only in liquidcontainers. For all these reasons, liquids can be a pain to put in IF. Ofttimes, liquid objects can simply be instances of a type of liquid. This type is defined in an object called the liquidclass which contains rules about how the liquid functions; for single instances, this object should probably just be the object itself. Attributes .isliquid Flag declaring for all the world to know that this is, indeed, a liquid. .liquidtype Determines the liquidclass for self. Actions .mixWith( list ) Mixes self with every object on the list. Reduces each object to its liquidclass, if applicable, and calls .mix on the liquidclass. Returns true if the contents are altered. .mix( instance, reactant_liquidclass, reactant ) Mixes self with a reactant. Should return true if contents are altered. .spill( jostlelevel ) Causes self to spill out of its container and by default disappear. 3.1.0.6. readable class readable: thing readables are gameworld objects which happen to be readable. All this class does is overwrite thing's verDoRead definition. The text can be put in .readdesc. 3.1.0.7. switchablething class switchablething: thing switchablethings are gameworld objects which happen to be turnable on and off. They can also be switched (toggled). They can be turned on in the dark as long as the .verDarkSwitch property does not display a message. Attributes .isactive Flag determining whether self is switched on or off. .routeswitch Defines whether self should be switched (returns nil), or whether another object should be (returns that object). Methods .verDarkSwitch( actor ) Verification routine called when the actor's location is dark (.islit = nil). Actions .turnOff Sets .isactive nil and displays a message. .turnOn Sets .isactive true and displays a message. 3.1.1. room class room: thing A room is an object meant to contain actors such as the player character. Rooms set the maxweight and maxbulk properties nil for In and On. The In position describes a state of floating above the floor; the On position describes a state of lying on the floor. Direction properties are also tied to the room; they are defined by the .dirTravel attribute of the Direction objects. Unlike in Adv.t, these are meant to be straight objects and not contain code. Any code related with traveling in a certain direction is in the Go direction property (.dirGoDirProp on the Direction), which is called with one argument, the actor doing the traveling. Although Pianosa does not define any Directions, ts_std.t includes the standard twelve (compass rose, up/down, enter/exit). The nomenclature used by that file, although not binding, follows the form of &north and &goNorth. Attributes .ambientlist String/string list of ambient sound resource names. .bgambientlist String/string list of background ambient sound resource names. .darkdesc Displays an error message saying that it's too dark to do that. .darkroomdesc Displays the long description of the room in the dark. .darkstatusdesc Displays the short description of the room in the dark. .doesecho Flag determining whether .echonoise is called in this room instead of .hearnoise. Defaults to nil. .Exitless Displays a message stating that there is no exit in the intended direction. .exitlist Property list of the standard exits. .flooradesc Displays the short description of the floor, preceded by the indefinite article. .floorldesc Displays the long description of the floor. .floorsdesc Displays the short description of the floor. .floorthedesc Displays the short description of the floor, preceded by the definite article. .genadesc Displays a short epithet for the room, preceded by the indefinite article. .gensdesc Displays a short epithet for the room, such as "area" or "room". .genthedesc Displays a short epithet for the room, preceded by the definite article. .hasambient Flag determining whether self has ambient sounds or not. .hasbgambient Flag determining whether self has background ambient sounds or not. .hasfloor Flag determining whether self has a floor or not. .hasmusic Flag determining whether self has background music or not. .incontdesc( c ) See container classes. .isinside Flag determining whether self is inside or outside. .isroom Flag specifying that yes, this is a room. .isseen Flag determining whether self has been entered by the player character or not. .issleepable( actor, position ) Flag determining whether actor may comfortably sleep here; if not, displays a message. .killoldambient Flag determining whether ambient sounds currently queued should be removed upon entrance into self. Defaults to true. .killoldbgambient Flag determining whether background ambient sounds currently queued should be removed upon entrance into self. Defaults to nil. .killoldmusic Flag determining whether background music currently queued should be removed upon entrance into self. Defaults to nil. .leavelist List of objects to be given a .leaving message when an actor leaves self. .lightson Flag determining whether the room's lighting is on or not. Defaults true. .musiclist String/string list of background music resource names. .notfollowroom Flag determining whether followers shouldn't follow their targets into self. .incontdesc( c ) See container classes. .reachable List of objects which are specifically reachable from self. .repeatambient Number of times ambient sounds should repeat or true for continual repeat. .repeatbgambient Number of times background ambient sounds should repeat or true for continual repeat. .repeatmusic Number of times background music should repeat or true for continual repeat. .roomdesc Displays the long description of the room. Defaults to .ldesc. .roomdescafter Displays whatever after the .roomdesc and .bdescs, but before the inventories. Defaults to "\n\t". .scoredesc Displays the score description (on the right in the default status line) in HTML mode. .sequenceambient String value for "sequence" attribute in ambient sound definition. Can be `random', `cycle', or `replace'. Defaults to `random'. .sequencebgambient See .sequenceAmbient. .sequencemusic See .sequenceAmbient. .sitloc Object to be sat in if the command is just "sit"; defaults to nil (meaning the floor). .statusdesc Displays the short status-line description of the room. Default to .sdesc. .statusLine Displays the status-line text or, in HTML mode, configures the status-line banner. .tagdesc The status-line text; defaults to .statusdesc or .darkstatusdesc apropos. .Wait( actor ) Displays a message when the player types "wait". Methods .actorlist( actor ) Finds all actors within the room, the given actor excluded, verifies them via .inEveryone, and returns them in a list. .addleavelist( object ) Adds the given object to .leavelist. .cantexit Displays a message stating that movement is impossible, either because it is blocked in the specified direction (.Exitless) or because it is too dark (stumble()). .cantreachfrom( actor, object ) Displays a message stating that an object cannot be reached from self by actor. Called by .cantreach. .Enter Displays a message associated with entering self. .enterRoom( actor, verbosity ) Does tasks associated with actor's entering self. verbosity equaling nil means that passive messages (like describing the room) should be suppressed. If actor is the player character, calls .Enter, .initSound, .lookAround (if verbosity is true), and .firstseen (if .isseen is nil). .firstseen Displays a message associated with entering self for the first time. .initAmbient Initiates ambient sounds for self. See .hasAmbient, .ambientList, .repeatAmbient, .seqenceAmbient, and .killOldAmbient. .initBGAmbient Initiates background ambient sounds for self. See .hasBGAmbient, .bgambientList, .repeatBGAmbient, .seqenceBGAmbient, and .killOldBGAmbient. .initMusic Initiates background music for self. See .hasMusic, .musicList, .repeatMusic, .seqenceMusic, and .killOldMusic. .initSound Initiates all sound for self by calling .initMusic, .initBGAmbient, and .initAmbient. Called from .enterRoom. .islit Determines whether the room is lit or not. Checks .lightson, and if that fails then checks every object in global.lampList to see if it's on and visible from self, and if that fails checks for a parent room and sees whether that room's lights are on. .leaveRoom( actor, verbosity ) Notification to room that an actor is leaving. Sends .Leaving messages to all objects in .leavelist. verbosity equaling nil usually means that this is a nested room to parent room movement. .lookAround( verbosity ) Displays a description of the room according to the given verbosity. By default, displays the tagline and then calls .nrmLookAround or .darkroomdesc as appropriate. .notifyPreactors( actor, verbobject, directobject_object, prepositionobject, indirectobject_object) Sends .preactorAction messages to all objects of class Preactor visible within self. Called by .roomAction. .notifyReactors( actor, verbobject, directobject_object, prepositionobject, indirectobject_object) Sends .reactorAction messages to all objects of class Reactor visible within self. Called by reactorDaemon. .nrmLookAround( verbosity ) Describes self with a given verbosity. By default nil verbosity means to display only a standard inventory of self's contents and true verbosity means to display the long description (.roomdesc), list the .describealone objects, and then display the standard inventory. .orderPreactorList( list ) Allows modification and ordering of the list of Preactors for .notifyPreactors .orderReactorList( list ) Allows modification and ordering of the list of Reactors for .notifyReactors. .roomAction( actor, verbobject, directobject_object, prepositionobject, indirectobject_object) Action routine for the actor's location. .roomCheck( verbobject ) Determines whether verbobject is a valid verb within self; called by the parser. Should display a message if returning nil. Actions .darkTravel( actor, dir ) Handles movement in a darkened room. By default, replicates the .travel experience except that it requires that the destination be lit. .echoNoise( type ) Causes a noise of a certain type to be echoed within self. The default procedure is to call .hearnoise in self and then call .hearnoise in all adjoining rooms (with no option for echo) and any existant parent room. .hearNoise( type ) Causes a noise of a certain type to be heard by all objects of class hearer within self; .hearnoise is called on all of said objects. .jump( actor ) Causes actor to jump within self. The default version displays a "witty" response and jostles the actor's contents. .makeNoise( type ) Causes a noise of a certain type to be made within self. The default procedure is to call .hearnoise in self, call .echonoise in an adjoining room if said room has .doesecho set true (otherwise, call .hearnoise), and then call .makenoise in any existing parent room. .sitDown( actor ) Causes actor to sit down within self. The default version checks for a .sitloc on self and if none is found calls .Sitdown on actor. .standUp( actor ) Causes actor to stand up within self. The default version calls .Standup on actor. .travel( actor, direction_property ) Causes actor to attempt travel in the given direction. Calls .darkTravel if the room is not lit, verifies the movement via the .go property (see .goDown), checks to see that direction leads somewhere (if not, calls .cantexit), and then calls .travelTo on actor if all checks out. -- room subclasses 3.1.1.0. nestedroom class nestedroom: room nestedrooms are rooms designed to be within other rooms; however, the code their definition adds is mostly veneer. .lookAround messages are passed to parent locations and .statusdesc is set to show that this room is really just a location within a location. Followers, for the most part, should not follow their quarries into these locations (.isfollowroom is nil); articles dropped here should really fall into other places (.isdroploc is nil). Attributes .statusPrep Displays the preposition to be used in the status line: "Cellar, in the comfy chair". .outOfPrep Displays the preposition to be used when leaving: "You get out of the car.". --- nestedroom subclasses 3.1.1.0.0. bednested class bednested: fixedthing, nestedroom, surface bednesteds are gameworld objects which can either be sat upon or lied down upon. Objects put into the chair are instead put onto the chair. The definition changes .standup to move the standing actor into the parent room. Attributes .autoExit Flag determining whether self should be automatically left when the sitting actor attempts to leave the parent room. Defaults to nil. Methods .removePrepPosture( posture ) Displays the preposition for removing oneself from the bed when one is in a given posture. 3.1.1.0.1. chairnested class chairnested: fixedthing, nestedroom, surface chairnesteds are gameworld objects meant to be sat in like a chair. They are identical to bednesteds except that they do not allow actors to lie upon them, their exit prepositions are slightly different, and .autoExit has a different default. chairnesteds have the infrastructure to be lied upon, so if a sofa or futon is desired, simply copying bednested code into the object's definition should be enough. Attributes .autoExit Flag determining whether self should be automatically left when the sitting actor attempts to leave the parent room. Defaults to true. Methods .removePrepPosture( posture ) Displays the preposition for removing oneself from the chair when one is in a given posture. (the roomfloor object is found here in the Pianosa library file) 3.1.1.0.2. vehicle class vehicle: nestedroom vehicles are gameworld objects which are meant to convey actors from one place to another. They can either be "open" or "closed"; if closed (.isopen is nil), they are (or should be) in their own little world, with the whole of the outside inaccessible. Some vehicles can also be taken; this case is provided for within the definition. Furthermore, many actions are forbidden to be done to the vehicle while inside it; because this is done with .dobjGen and .iobjGen, it is possible to allow further actions (than examine, put in/on, and leave) by making sure that the proper verification routine is defined specifically within the object's code. Atributes .Error Displays a message that the action is not possible from within the vehicle. .isvehicle Flag specifying that yes indeed, this is a vehicle. .reachable List of objects accessible from within vehicle. If adding anything to this, make sure the list 1) includes self and 2) takes into account openness, if that feature is being used. 3.1.2. container, cover, mask, surface class container: thing class cover: thing class mask: thing class surface: thing A container is an object meant to contain other objects within it. A cover is an object meant to contain other objects beneath it. A mask is an object meant to contain other objects behind it. A surface is an object meant to contain other objects on top of it. These are the four default position-holders in Pianosa. Properties dealing with the duties of having contents will be dealt with here, including the contents-listing methods. There are four companion classes: qcontainer, qcover, qmask, and qsurface. These classes simply set their respective .isq attributes true. Attributes .behindcont List of all objects held directly behind self. Set up automatically. .behindcontdesc( c ) Displays an introductory message for an inventory listing; if this returns true a form of "to be" will be conjugated (according to the number of objects to be listed) directly after the message. c is the number of objects (invCount) in the list. .behindcontreachable Flag determining whether objects held behind self are generally accessible. Defaults to .behindcontvisible. .behindcontvisible Flag determining whether objects held behind self are generally visible. Defaults to true. .behinddesc Displays a description of what's behind self. Defaults to nothing. .emptybehind Displays a message stating that there is nothing (visible) behind self. .emptyin See .emptybehind. .emptyon See .emptybehind. .emptyunder See .emptybehind. .excessbulk( object, position ) Displays a message stating that object will not fit in position because it is too large. .excessweight( object, position ) Displays a message stating that object will not fit in position because it is too heavy. .incont See .behindcont. .incontdesc( c ) See .behindcontdesc. .incontreachable See .behindcontreachable. Also, defined to check .isopen. .incontvisible See .behindcontvisible. Also, defined to check .isopen and .istransparent. .indesc See .behinddesc. .iscontainer Flag specifying that yes, good sir, this is a container. .iscover Flag specifying that indeed, this is a most verifiable cover. .isdroploc Flag determining whether dropping an object here should cause it to stay here or fall further. Default true for rooms, nil for everything else. .ismask Flag specifying that in fact, this is a certified mask. .isqcontainer Flag determining whether a container will list its contents in room listings and inventories. Default nil. .isqcover See .isqcontainer. .isqmask See .isqcontainer. .isqsurface See .isqcontainer. .issurface Flag specifying that this is truly a surface to have things laid upon. .istransparent Flag determining whether, when closed, the contents of self can be seen anyway. .listcontoninspect Flag determining whether .listallcontents will be called when an object is looked at. Default is true. .maxbulkbehind Bulk limit for the Behind position. Set nil for no limit. Default is 10. .maxbulkin See .maxbulkbehind. .maxbulkon See .maxbulkbehind. .maxbulkunder See .maxbulkbehind. .maxweightbehind Weight limit for the Behind position. Set nil for no limit. Default is 10. .maxweightin See .maxweightbehind. .maxweighton See .maxweightbehind. .maxweightunder See .maxweightbehind. .oncont See .behindcont. .oncontdesc( c ) See .behindcontdesc. .oncontreachable See .behindcontreachable. .oncontvisible See .behindcontvisible. .ondesc See .behinddesc. .outOfPrep Displays the preposition for actors getting off of/out of a nestedroom like a chair or a bed. Compare .removePrep. .posdesc( position ) Displays how to refer to an object being held in a certain position relative to self. Example: desk.posdesc( Under ) displays "under the desk" .posPrep( position ) Displays the preposition to describe being in a certain position relative to self. Example: desk.posPrep( Under ) displays "under" .removePrep( position ) Displays the preposition to describe being taken out from a certain position relative to self. Example: desk.removeProp( Under ) displays "out from under" .statusPrep Displays the preposition for actors within a nestedroom like a chair or a bed. Compare .posPrep. .undercont See .behindcont. .undercontdesc( c ) See .behindcontdesc. .undercontreachable See .behindcontreachable. .undercontvisible See .behindcontvisible. .underdesc See .behinddesc. Methods .bulkbehind Determines the total extra bulk added by objects within the Behind position. Defaults to returning 0 regardless, because most containers are fixed. .bulkin Determines the total extra bulk added by objects within the In position. If self has .isflexiblecontainer set true, it actually sums this up; otherwise, it simply returns 0. .bulkon See .bulkbehind. .bulkunder See .bulkbehind. .contents An alias to .allcont. .Drop( object, target ) Message sent to self by .putInto to verify letting go of object being moved to target. Returns true to abort movement. .dropall( {position, {, dontDropWornObjects {, jostle }}} ) Causes all objects in a position (default In) to be dropped from self (excepting objects with .isworn set true unless the first argument is nil) according to .dropFrom. .dropping( object, position ) Returns a list in the format [ object position ] specifying where an object, dropping from a certain position around self, should fall. By default, if .isdroploc is set nil then .dropping is called on self's location with the position On. .endPutInto( object, position ) Notification by .putInto that object has been successfully put into position around self. By default, calls .mixCont. .gaca( class {, property {, value {, argument }}} ) Gets all contents of a certain class in any position around self. Loops through the positions calling the appropriate gac-class property on self. If property exists, that property must equal value (default = true) on an object for it to be included in the list; if argument exists, it will be passed to the property. .gacb( class {, property {, value {, argument }}} ) Gets all contents of a certain class behind self. Calls .gacva on every object behind self and adds those objects as well. For the last three parameters, see .gaca. .gaci( class {, property {, value {, argument }}} ) See .gacb. .gaco( class {, property {, value {, argument }}} ) See .gacb. .gacu( class {, property {, value {, argument }}} ) See .gacb. .gacva( class {, property {, value {, argument }}} ) Gets all contents of a certain class in any visible position around self. See .gaca. .Grab( object, position ) Notification by .moveInto that object is being removed from a certain position around self (or from an object in a certain position around self); if this returns non-nil the movement is canceled. .listallalonecontents( {depth} ) Lists all describe-alone contents in all non-quiet, visible positions around self at a certain inventory depth (default = 1). Calls aloneContListing , which calls .bdesc. .listallcontcontents( {depth, {verbosity_type }} ) Lists all non-quiet, visible contents positions of objects held in non-quiet, visible positions around self at a certain inventory depth (default = 2) and with a certain verbosity type. Calls innerContListing, which in turn calls .listallcontents on the contents items. .listallcontents( {depth, {verbosity_type}} ) Lists all non-quiet, visible contents positions on self at a certain inventory depth (default = 1) and with a certain verbosity type. Calls the specific contents-listing properties (see .listbehindcont) and then .listallcontcontents. .listbehindcont( depth, verbosity_type ) See .listXcont. .listincont( depth, verbosity_type ) See .listXcont. .listoncont( depth, verbosity_type ) See .listXcont. .listundercont( depth, verbosity_type ) See .listXcont. .listXcont( position, depth, verbosity_type ) Lists objects in a certain position relative to self, provided that the objects there are visible (see .behindcontvisible). Passing true as depth forces a wide-inventory display; otherwise, depth just specifies indentation. Displays the appropriate introduction message (see .behindcontdesc) if there are to-be-listed contents or the verbosity type is 0, then calls contListing. .reachList( actor ) Determines the list of all objects reachable by actor around self. .routebehind( object, jostle ) Routes where a certain object, being put behind self, should go. To abort the movement, this should return nil. .routein( object, jostle ) See .routebehind. .routeon( object, jostle ) See .routebehind. .routeunder( object, jostle ) See .routebehind. .speakList( actor ) Determines the list of all objects speakable to by actor around self. Defaults to .visList. .Take( object, position ) Message sent to self by .putInto to verify accepting object being moved to a position around self. Returns true to abort movement. .verGrab( object, position ) Verification routine checking whether object can be removed from a certain position around self (or from an object in a certain position around self). Shows displeasure by diplaying a message, should not otherwise. .visList( actor ) Determines the list of all objects visible by actor from self. .weightbehind Determines the total extra weight added by objects within the Behind position. Defaults to 0. .weightin Determines the total extra weight added by objects within the In position. .weighton See .weightin. .weightunder See .weightbehind. Actions .forceAccept( object {, position } ) Causes object to be moved into a certain position (default = In) relative to self. By default, does this by setting the appropriate location property on object to self and adding object to the appropriate contents list on self. .forceRelease( object ) Causes object to be removed from around self. By default, does this by removing object from the appropriate contents list of self and then clearing all location properties of object (by calling .clearloc). .mixCont( position ) Causes contents in a certain position to be suddenly mixed. Loops through the contents list, calling .mixwith on each object with every other object in the loop. -- container class subclasses 3.1.2.0. coverer class coverer: qcover coverers are covers which do not have a real-world Under position counterpart per se, but instead are capable of hiding things underneath them until they are moved. The class defines a special .Move, so any other code there should include or pass to the library code. It also defines .verDoMove and .doMove routines which enable that command to cause covered items to be revealed. 3.1.2.1. liquidcontainer class liquidcontainer: qcontainer liquidcontainers are containers designed to hold liquids. They can either service only liquids (.liquidsonly set true) or function as general containers. Whether they are qcontainers or not depends upon whether they hold liquids or not, because they alter .specialdesc to include what they contain if it's a liquid. This class overrides .Take. Attributes .liquidsonly Flag determining whether other objects can be placed in self beside liquids. .oneliquidonly Flag determining whether more than one liquid may be placed in self at a time. .spillsafe Determines what jostle level must be exceeded to cause liquids inside to spill; true if self is completely spillsafe. Methods .holdsliquid Determines whether self holds a liquid or not. .liquiddesc Describes the liquid within self. 3.1.2.2. openable class openable: container openables are containers which can be opened (if .isopenable is true) and shut (if .iscloseable is true) at will. If transparent (.istransparent is true), their contents can be seen from without. Attributes .Close( actor ) Displays a message upon closing self. .iscloseable Flag determining whether self is closeable or not. Defaults true. .isopen Flag determining whether self is currently open or not. Defaults true. .isopenable Flag determining whether self is openable or not. Defaults true. .istransparent Flag determining whether self is transparent or not. Defaults nil. .Open( actor ) Displays a message upon opening self. Actions .close( actor ) Closes self. .open( actor ) Opens self. --- openable subclass 3.1.2.2.0. lockable class lockable: openable, Lockcode lockables are openables which can be locked and unlocked as well (if .islockable and .isunlockable are set true). Most of their functional code is in the Lockcode class. Attributes .autoUnlock Flag determining whether attemping to open self should automatically unlock self if possible. .Close( actor ) Displays a message upon closing self. .iscloseable Flag determining whether self is closeable or not. Defaults true. .islockable Flag determining whether self is lockable or not. Defaults nil. .isopen Flag determining whether self is currently open or not. Defaults true. .isopenable Flag determining whether self is openable or not. Defaults true. .istransparent Flag determining whether self is transparent or not. Defaults nil. .isunlockable Flag determining whether self is unlockable or not. Defaults true. .Lock( actor, key ) Displays a message upon locking self. .mykey Object or object list of valid keys for self. nil means no key is necessary. .mykeyKnown Flag determining whether a correct key for self is known to the player. .Open( actor ) Displays a message upon opening self. .Unlock( actor, key ) Displays a message upon unlocking self. Methods .keyHeldBy( object ) Checks whether a defaultable key is being held by object. .keyIsValid( object ) Checks whether object is a valid key for self. Actions .close( actor ) Closes self. .lock( actor, key ) Locks self. .open( actor ) Opens self. .unlock( actor, key ) Unlocks self. 3.1.2.3. qcontainer, qcover, qmask, qsurface class qcontainer: container class qcover: cover class qmask: mask class qsurface: surface These four classes are enabler classes, merely setting their respective q-properties true. --- qcontainer subclass 3.1.2.3.0. movableActor class movableActor: qcontainer movableActors are NPCs which can be picked up and taken with the player. All characters in the game inherit from movableActor. Attributes .actorname The name of the actor. Referenced by sdesc. .bdesc Message briefly describing self to everything else in the room. .disavow Message saying that self knows nothing about what was asked of self. .Hungerwarning Message notifying self that if self doesn't eat almost immediately, self is going to die. .Hungerwatch Message notifying self that if self doesn't eat "soon", self is going to die. .hasfollower Flag determining whether self can be followed. .hashunger Flag determining whether self must eat to survive. .hassleep Flag determining whether self must occaisionally sleep. .hungerTime Number determining how long self can live without dying. .hungryTime Number determining how long self has gone without eating. .inEveryone Flag determining whether self is included in Everyone. Defaults true. .iPos Determines the inventory position for self. .isactor Flag specifying the fact that self is an actor, and thus can be given commands. .isasleep Flag determining whether self is asleep or not. .possessive Displays the possessive, e.g. "your" or "'s". .posture Determines the current posture of self (Stand, Sit, or Lie). .preferredActor Flag specifying that not only is self an actor, but is a preferred actor. .primaryIPos Displays the primay inventory position, i.e. that which taken objects are sent to. .sayArriving Message displaying that self is entering the room that parserGetMe() is in. .sayLeaving Message displaying that self is leaving the room that parserGetMe() is in. .sleepTime Number determining how long self can go without passing out and sleeping. .sleepDuration Number determining for how long self will sleep. .Sleepwarning Displays a message that if self doesn't get to sleep almost immediately, self is going to pass out on the floor. .Sleepwatch Message displaying that if self doesn't sleep relatively soon, self is going to pass out on the floor. .sleepyTime Number determining how long self has gone without sleeping. Methods .askobject( object ) Asks self about a specific object (called before .askword). Should return true if a response is forthcoming. .allheld List of all objects held by self. .askword( word, wordlist ) Asks self about a specific word in a list. Should return true if an answer is displayed. .followedFrom( room ) Causes self's follower, if it exists, to move into the room just vacated by self. .Hungry( time_left ) Message sent to self every turn with the argument (.hungerTime - .hungryTime), i.e. the time left until self should die of starvation. Any actual consequences of not eating are left up to this method. .inventory( {inventory_depth {, verbosity_type}} ) Displays a full inventory for self at a given inventory depth and verbosity type. .isCarrying( object/list ) Determines whether self is visibly carrying an object or any one of a set of objects. .isCarryingAll( object/list ) Determines whether self is visibly carrying a certain object or every object in a list. .isHolding( object ) Determines whether self is holding an object -- i.e. the object's location is exactly self, not some other object that self is holding. .Sleepy( time_left ) Message sent to self every turn with the argument (.sleepTime - .sleepyTime), or the time left until self should die of starvation. Any actual consequences of not eating are left up to this method. .travelTo( destination {, position {, verbosity}} ) Causes self to travel to a certain position (default = On) in destination. If destination is an obstacle, instead travels to room.destination. Calls .leaveRoom on the old location (if it exists), calls .sayLeaving on self if self is in sight of but is not parserGetMe(), moves self into destination, calls .enterRoom on destination, and calls .sayArriving (again, if visible to parserGetMe()). Finally calls .followedFrom on self if destination isn't .notfollowroom. Actions .Awaken Causes self to awaken. Sets .isasleep to nil and displays a message. .hungerdeath Self dies! from hunger. Calls .perish. .perish Calls die() if is parserGetMe(), otherwise fades away like a Jedi master (.forceInto( nil )). .sleep Causes self to fall asleep. If self is parserGetMe(), this just displays a cute message and wakes up again (calls .Awaken). Otherwise, sets .isasleep true and sets .Awaken as a notifier until .sleepDuration passes. .sleepeasy Causes self to fall asleep comfortably. Calls .sleep. .sleephard Causes self to fall asleep uncomfortably. Calls .sleep. .Sitdown Causes self to sit down by setting posture to Sit and displaying an approriate message. .Speak( sound ) Displays a message on how self would cause sound to be emitted. Calls .Say on the sound. Returns true to abort. .Standup Causes self to stand up by setting posture to Stand and displaying an appropriate message. ---- movableActor subclasses 3.1.2.3.0.0. NPC class NPC: fixedthing, movableActor NPCs are actors which cannot be picked up. ----- NPC subclasses 3.1.2.3.0.0.0. Actor class Actor: NPC An Actor is a male actor. 3.1.2.3.0.0.1. Actors class Actors: NPC Actors are groups of actors, not necessarily all male. 3.1.2.3.0.0.2. Actress class Actress: NPC An Actress is a female actor. 3.1.2.3.0.0.3. basicMe class basicMe: NPC basicMe is the basic class for player characters; however, the definition also easily allows for switching out of one character into another. Attribute .actorname The name of the actor. Referenced by sdesc when self is not the PC. .actorperson The grammatical person of the actor, used for conjugation; can be FIRST_PERSON, SECOND_PERSON, or THIRD_PERSON, and with .isplural any of the 5 English persons can be used. Referenced by grammarperson when self is the PC. .grammarperson See thing.grammarperson. Redefined as a method. When self is not the PC, returns THIRD_PERSON; otherwise, returns .actorperson. .ispasttense Flag determining whether verbs using this object as subject should be conjugated in the present or the past tense. thing.ispasttense by default returns parserGetMe().ispasttense. Method .becomeMe Turns self into the active player character by removing the special words `me' and `myself' from the old PC object's noun list, adding them to self's vocabulary list, and calling parserSetMe(). (the Everyone object is found here in the Pianosa library file) 3.1.2.3.0.0.4. Follower class Follower: NPC A Follower is a library-handled logical character which follows one room behind its actor so that the player can type "follow her" and she will be followed. It is possible to declare an object of this class in the gamefile if desired, although the .remove method should be overwritten. Attribute .myactor Determines the actor that self is following. Action .remove Removes self from the game. By default, deletes it, because Followers are typically dynamic objects. -- container subclasses continued 3.1.2.4. transparentcontainer class transparentcontainer: container transparentcontainers are containers which can be seen through (if .istransparent is true). This is an enabler class, simply setting the attribute true. 3.1.3. Other gameworld classes 3.1.3.0. concept class concept: object concepts are logical objects which can be asked about but which do not necessarily correspond to an object present in the gameworld. The class is an enabler class with simple verb routines. 3.1.3.1. Direction class Direction: object Direction is a programmatical structure allowing movement directions to be defined easily without the need for editing Pianosa. Unlike Positions, there are no Directions defined within Pianosa, although one is required (see 3.3. External Objects). The standard twelve included in ts_std.t are listed under room. Further unlike Positions, the Direction access functions (travelProp() and sayDirection()) are not indexed by number but rather by the .dirTravel property value. Attributes .dirGoDirProp Property pointer for the verification travel property. .dirNames List of single-quoted names for this direction, including abbreviations. .dirTravel Property pointer for the general travel property. 3.1.3.2. floatingobject class floatingobject: object floatingobjects are objects which are not tied to one location in the gameworld. Because defining .locate (and .position) as methods works in only one direction -- up the object tree -- and the valid-object routines work in the opposite direction, floatingobject is provided as a way to bring these objects into consideration as objects of actions (since .validDo moves up the object tree, they stand the same chance as any other object). floatingobject is a marker class, all objects of which class are assembled into global.floatingList in preinit(). 3.1.3.3. hearer class hearer: object hearers are gameworld objects which receive .hearnoise messages. hearer is a marker class. 3.1.3.4. Lockcode class Lockcode: object Lockcode is a programmatical convenience which brings the repetitive and complex key-lock system into one class used by doorway and lockable and available for use by others. The attributes of Lockcode are discussed in the doorway and lockable classes. Lockcode provides mechanisms for opening, closing, locking, and unlocking objects, with or without a key. 3.1.3.5. multiobject class multiobject: object multiobject is a programmatical device for easily creating multiple instances of an object in multiple locations through the use of dynamic objects. The .ismultiobject flag is important, unlike in other classes; since multiobjects almost invariably create objects of their own class, it is important that these new objects not be included in the initMultiobject() loop; therefore, only multiobjects with this flag set true will have .create called on them. Attributes .ismultiobject Flag stating with all strength of purpose that this is, indeed, a multiobject (and thus .create will be called on this object). .locatelist List of locations, each optionally followed by a position (default = In), in which the multiobject should go. .multiobjectlist List of dynamic objects, one for every object in .locatelist. Method .create Spawns the multiobjects from .locatelist. Called by initMultiobject(). 3.1.3.5.0. multilocatefixed class multilocatefixed: fixedthing, multiobject A multilocatefixed is the best way to implement a large number of unchanging, identical objects in multiple locations. Essentially, the object places itself in the contents lists of multiple locations. Attribute .locatelist List of locations in format [ location1 {position1} ... ]. The default position is In. Example: [ cabinet sink dormitory bunkbed On ] places the object inside the cabinet, the sink, and the dormitory, and on the surface of the bunk bed. 3.1.3.6. notified class notified: object A notified object receives notification at the end of each turn. This is a marker class by class-loop. Method .notification Called by notifiedDaemon every turn. 3.1.3.7. obstacle class obstacle: object obstacles are programmatical conveniences which allow exits to be reliant upon, for example, whether or not a door is open as to whether or not the player may pass. obstacle is a marker class which sets the .isobstacle attribute. Attribute .isobstacle Flag define an obstacle self is. Method .destination( actor ) Determines whether or not actor may pass. Returns the destination object or nil. - notified subclasses 5.1.3.7.0. doorway class doorway: fixedthing, obstacle, Lockcode doorways are gameworld objects which may be open and shut, locked and unlocked as the player desires. They are also obstacles, so whether they are open or not can decide whether the player can move through an exit or not. By default, doorways also pass .hearnoise messages on to their destinations. Attributes .autoOpen Flag determining whether self will be automatically opened when an actor attempts to pass through it shut. Defaults to true. .autoUnlock Flag determining whether self will be automatically unlocked when an actor attempts to open it when locked. .Close( actor ) Displays a message upon closing self. .doordest Object for what lies on the other side of the door. .doordir Property pointer for which direction should be traveled in when self is entered. .iscloseable Flag determining whether self can be closed or not. Defaults to true. .isdoorway Flag postulating that self's existence may, indeed, be determined to be that of a doorway. .islockable Flag determining whether self can be locked or not. Defaults to nil. .islocked Flag determining whether self is locked or unlocked. Defaults to nil. .isopen Flag determining whether self is open or shut. Defaults to true. .isopenable Flag determining whether self can be opened or not. Defaults to true. .isunlockable Flag determining whether self can be unlocked or not. Defaults to true. .Lock( actor, key ) Displays a message upon locking self. .mykey List of valid keys for self. .mykeyKnown Flag determining whether a valid key for self is known or not. .Open( actor ) Displays a message upon opening self. .otherside Object for the other side of this door (the side facing .doordest), which can thus be kept in harmony with this side. .Unlock( actor, key ) Displays a message upon unlocking self. Methods .destination( actor ) Determines whether actor may pass through self; if so, returns .doordest. .keyHeldBy( object ) Determines whether a valid key for self is known and is held by object. .keyIsValid( object ) Determines whether a given object is valid as a key for self. Actions .close( actor ) Closes self. .lock( actor, key ) Locks self. .open( actor ) Opens self. .unlock( actor, key ) Unlocks self. -- doorway subclass 3.1.3.7.0.0. matchdoorway class matchdoorway: doorway, multiobject matchdoorways are doorways which are automatically generated by the library. The class defines its own .create, so the only reason it inherits from multiobject is to hook initMultiobject(). .locatelist is also in a wildly different format. locatelist = [ source1 destination1_1 {destination1_2 ... } is_bidirectional { source2 destination2_1 {destination2_2 ... } is_bidirectional ... } ] A door is created at the direction properties (see room.exitList) on source1 which equal destination1_1 (or destination1_2, etc.). If is_bidirectional is true, then the same process is repeated for the destination rooms, this time looking for the source room. All source/destination/is_bidirectional sets are independent. Attributes .locatelist List from which the doorways are generated. See class description. Methods .create Spawns the matchdoorways from .locatelist. Called by initMultiobject(). .getdoor( source {, destination } ) Returns the door object of class self leading from source (to destination, if given). If some number other than one such door is found, returns nil. .initdoor( source, destination ) Initiates self, a door leading from source to destination. .setupdoor( source, destination, is_bidirectional ) Creates an instance of the matchdoorway, sets .doordest, places it, calls .initdoor, changes any direction properties on source which lead to destination so that they pass through the instance, adds vocabulary to the instance, and sets .doordir. If is_bidirectional, spawns another door, sets .otherside on each, and repeats the process. --- matchdoorway subclass 3.1.3.7.0.0.0. doorwayframe class doorwayframe: matchdoorway, openable doorwayframes are doorways with built-in frames which accept objects. Like any matchdoorway, doorwayframes can be placed in multiple locations, but beware -- in the current implementation, the frame will be shared between all of the doorways. 3.1.3.8. Position class Position: object Position is a programmatical structure allowing relative positions to be defined as painlessly as it can get. Four Positions are defined within Pianosa. On and In are used specifically by the movableActor and room classes, while Under and Behind are simply fully declared. The Position objects are set by preinitAdaptables(), which goes through every object of class Position and adds it to global.positionList in order of .position attribute. In the case of duplicated .position values, one of the positions will not be included. Attributes .position Number of position's order in line. .bulkProp Property for the amount of additional bulk of contents in self. .contProp Property for the contents-list of self. .contdescProp Property for the inventory listing introduction of self. .descProp Property for the position description of self. .emptyProp Property for the empty message for self. .gacProp Property pointer for the "contents held of class" method for self. .listcontProp Property for the contents-listing method for self. .locProp Property for the object location attribute for self. .maxbulkProp Property for the maximum bulk allowed in self. .maxweightProp Property for the maximum weight allowed in self. .outofPrepobject Preposition object/object list for removing objects from self. .posPrepobject Preposition object/object list for removing objects from self. .qProp Property for the quiet-container attribute for self. .reachProp Property for the contents-reachable attribute for self. .removePrep Double-quoted string for the preposition for removing objects from self. .routeProp Property for routing objects being placed into this position. .showactiveposition Double-quoted string for the preposition for putting objects into self. .showposition Double-quoted string for the preposition for objects being held in self. .visProp Property for the contents-visible attribute for self. .weightProp Property for the amount of additional weight of contents in self. Method .initposition Called by preinitAdaptables, adds .posPrepobject and .outofPrepobjects values to takeVerb.pospreplist, which that verbs uses internally. (the In object is found here in the Pianosa library file) (the On object is found here in the Pianosa library file) (the Under object is found here in the Pianosa library file) (the Behind object is found here in the Pianosa library file) 3.1.3.9. Preactor class Preactor: object Preactors are game objects which, when visible to the actor, are notified of an actor's intended actions before he/she completes them. The notification is performed by .roomAction, which calls .notifyPreactors on the room, which in turn calls .preactorAction on all Preactors in visible scope. Preactor is a marker class. Method .preactorAction( actor, verb, direct_object, preposition, indirect_object ) Notifies self that actor is performing a certain action. Can exit or abort the command if so desired. 3.1.3.10. Prep class Prep: object Preps are programmatical conveniences which define preposition grammar. Preps are used to differentiate between prepositions for the purposes of verb .ioActions. Two-word verbs must also have the second word defined somewhere as a preposition. (the Prep objects are found here in the Pianosa library file) 3.1.3.11. Reactor class Reactor: object Reactors are game objects which, when visible to the actor, are notified of an actor's intended actions after he/she has completed them. The notification is performed by reactorDaemon, which calls .notifyReactors on the room, which in turn calls .reactorAction on all Reactors in visible scope. Reactor is a marker class. Method .reactorAction( actor, verb, direct_object, preposition, indirect_object ) Notifies self that actor has performed a certain action. 3.1.3.12. Verb class Verb: object Verbs are logical constructs detailing how actions are to be carried out. The special Pianosa attributes deal mainly with general object selection; other verb properties can be found in a general TADS reference. Attributes .doIsSeen( preposition ) Determines whether the direct object for an action on self should be visible. .doIsSpokenTo( preposition ) Determines whether the direct object for an action on self should be speakable to. .doIsTouched( preposition ) Determines whether the direct object for an actionon self should be touchable. .ioIsSeen( preposition ) Determines whether the indirect object for an action on self should be visible. .ioIsSpokenTo( preposition ) Determines whether the indirect object for an action on self should be speakable to. .ioIsTouched( preposition ) Determines whether the indirect object for an action on self should be touchable. - Verb subclasses 3.1.3.12.0. darkVerb class darkVerb: Verb darkVerbs are Verbs which are at least potentially valid in the dark. Attribute .isDarkVerb Flag definitively declaring that self is a darkVerb (and thus passes .roomCheck). Method .validInDark( actor, direct_object, preposition, indirect_object ) Determines whether a certain command is valid in the dark; called by .roomAction. Does not need to display a message. Defaults to .isDarkVerb, which defaults to true. -- darkVerb subclasses 3.1.3.12.0.0. sysVerb class sysVerb: darkVerb sysVerbs are system-oriented actions which have nothing to do with gameplay and everything to do with performing interface tasks such as saving and quitting. Attributes .Help Message displaying the help text for self. All sysVerbs are listed. .isSysVerb Flag defining the absolute truth of self's identity as a sysVerb. .ldesc (some) Message displaying important text or prompt. .value Position in which the sysVerb will be listed by help. Higher signifies later. By convention, all debug verbs are value 0. The library already orders its collection alphabetically, so it simply assigns values of (5 * (order)), thus leaving plenty of space for additional sysVerbs. Multiple values at a certain index are okay. Method .verbtask( actor ) Performs the verb's action. 3.1.3.12.0.1. TravelVerb class travelVerb: darkVerb, Direction travelVerbs are player-movement actions which can occur in the dark. There are no travelVerbs defined in Pianosa, but the twelve standard directions can be found in ts_std.t. Attributes .isTravelVerb Flag ajudging the probability of self's being a travelVerb. .verbdir Property-pointer for the direction of movement for this verb as passed to .travel. 3.1.3.13. versionInfo class versionInfo: object versionInfos are programmatical conveniences which contain information about library versions, including helper libraries. Attributes .bdesc Brief description of the library and its version. 3.2. Pianosa defined objects 3.2.0. articles articles: object articles defines the articles allowed in the game. There are three: 'a', 'and', and 'the'. 3.2.1. In, On, Under, Behind In: Position On: Position Under: Position Behind: Position These four objects define the standard four positions for the Pianosa libraries. In and On are required. 3.2.2. numObj numObj: object numObj is a TADS-required programmatical convenience which allows plain numbers to be used as objects in commands. The number is assigned to the .value property upon command entry. 3.2.3. Pianosa Pianosa: versionInfo Pianosa contains version information about the Pianosa libraries. No auxiliary Pianosa file defines such version information. 3.2.4. strObj strObj: object strObj is a TADS-required programmatical convenience which allows plain text to be used as an object in a command. The text is assigned to the .value property upon command entry. 3.3. External Classes and Objects There are several objects and classes not included in the Pianosa libraries which are required for usage. 3.3.0. required directions At least one Direction should be defined, .dirTravel equaling &out. This is used for departing from chairnesteds and bednesteds. Its presence is not verified, and is not technically required, but the chairnested and bednested code reference it. 3.3.1. global global: object global is the official options and defaults object for Pianosa. An attributes list, for now, can be found in ts_std.t. 3.2.2. menus All menus are classes, referenced by a call to writeMenu with one argument, the menu class name. See the section on ts_menu.t (6.1) for more information. These menus, with sub-menus where applicable, are included in ts_std.t. 3.2.2.0. optionsMenu class optionsMenu: Menu Entered via the "options" verb. 3.2.2.1. quitMenu class quitMenu: Menu Entered via the "quit" verb. 3.2.2.2. restartMenu class restartMenu: Menu Entered via the "restart" verb. 3.2.3. version version: object version is the official information object for the work; despite its name, it is not a versionInfo object. Attributes .sdesc The title of the work, underlined or quoted or whatever. .bdesc A brief description of the work. Used not by Pianosa, but by ts_std.t. .ldesc The about text of the work. 3.3. Inheritance hierarchy Objects are listed in parentheses; only non-instance objects are listed. Core classes are listed in bold. For those classes with multiple inheritance, multiple listings are made with cross-referencing; asterisks signify that the class's definition can be found by the marked superclass's definition, rather than the current category. (Pianosa) object thing container openable doorwayframe (also *matchdoorway) lockable (also Lockcode) qcontainer liquidcontainer movableActor NPC Actor Actors Actress basicMe (Everyone) Follower transparentcontainer cover qcover coverer dialthing fixedthing bednested (also *nestedroom, surface) buttonthing chairnested (also *nestedroom, surface) decoration distantthing doorway (also Lockcode, *obstacle) matchdoorway (also multiobject) doorwayframe (also openable) multilocatefixed (also *multiobject) foodthing item clothingitem keyitem lightsource liquid mask qmask readable room nestedroom bednested (also fixedthing, surface) (roomfloor) (also floatingobject) chairnested (also surface) vehicle surface bednested (also fixedthing, *nestedroom) chairnested (also fixedthing, *nestedroom) qsurface switchablething (articles) concept Direction travelVerb (also *darkVerb) floatingobject (Everyone) (also *NPC) (roomfloor) (also *bednested) hearer Lockcode doorway (also fixedthing, *obstacle) matchdoorway (also multiobject) lockable (also *openable) multiobject multilocatefixed (also fixedthing) matchdoorway (also *doorway) doorwayframe (also openable) notified (numObj) obstacle doorway (also fixedthing, Lockcode) matchdoorway (also multiobject) doorwayframe (also openable) Position (Behind) (In) (On) (Under) Preactor Prep Reactor (strObj) versionInfo (Pianosa) (found in front of library) Verb darkVerb sysVerb travelVerb (also Direction) Chapter 4 The Pianosa Functions The role of functions in an object-oriented system is frequently questioned. The response is that there are some tasks of universal importance which are best left in universal domain. If there is a possibility that an argument object might want to modify the procedure, then it belongs in a method. Yet again, however, if the code is repetitive it may be best left in a function but only accessed through methods. Such is the debate over functions. Although many functions are defined within Pianosa, some are left to the writer to develop -- or at least to a standard interface file such as ts_std.t. Others have been exported to the (automatically included) support file ts_funcs.t; these are, however, classified in the included set. 4.1. Pianosa Defined Functions addScore( amt ) Increments the score by amt (possibly negative). Calls global.Score. aloneContListing( object {, position {, inventory_depth }} ) Lists the describe-alone contents of object in a certain position (default = In). Returns the total number of spaces listed (see invSpaces). By default, ignores inventory_depth. checkReach( location, actor, verb, object ) Verification routine which calls object.cantReach if object cannot be reached by actor. conj( verb_string {, {tense,} rule_object} ) conj( verb_string {, tense} ) Returns a single-quoted string conjugating verb_string according to the rules set by rule_object (defaults to the current actor). Optionally, the tense can be set one tense back from the norm by setting tense to PAST_TENSE. See the library for more information. Uses the functions getPastParticiple() and getPastTense(). contListing( object {, position {, inventory_depth {, empty_verbosity }}} ) Lists the contents in position (default = In) around object at a certain inventory depth (default = 1) and verbosity. Each content is listed with .idesc (or .pluralidesc if multiple). If the inventory is empty, then either "nothing" will be displayed (e_v = 0), nothing will be displayed (e_v = nil), or the emptyposition property will be called (e_v = true). currentActor() Returns the current actor. currentDobj() Returns the direct object of the current command. currentIobj() Returns the indirect object of the current command. currentPrep() Returns the indirect-object preposition of the current command. currentVerb() Returns the verb of the current command. daemonDaemon( parm ) Daemon organizing the other daemons. Don't use setdaemon and remdaemon; instead, use setDaemon and remDaemon, which interface with this daemon. The daemon list is kept in global.daemonlist. getPastParticiple( verb_string ) Returns the past participle of the given verb. getPastTense( verb_string ) Returns the past tense of the given verb (does not work for 'be'). hungerDaemon( parm ) Actor hunger, not set in Pianosa. initLibrary() Initiates library routines by setting daemons and calling initMultiobject(). initMultiobject() Initiates multiobjects. innerContListing( object {, position {, inventory_depth {, verbosity}}} ) Lists the visible contents of objects held in positions around object. See contListing(). invCount( list ) Retrieves the gameworld number of to-be-listed objects in a list. Three quarters, a dime, and a pair of geese make six objects. invSpaces( list ) Retrieves the number of slots for to-be-listed objects in a list. Three quarters, a dime, and a pair of geese make three slots. isIndistinguishable( object_1, object_2 ) Determines whether the two objects are indistinguishable. A general routine called by .distinguish. nextTurn( parm ) Handles the passage of time, set in initLibrary(). notifiedDaemon( parm ) Notifies all objects of class notified by calling object.notification. parseErrorParam( error_number, default_message, ... ) Returns an error message; see standard TADS documentation. Pianosa defines this function, but calls modifyParseError with the same configuration as that received. preinit() Initiates at compile time object.uberlocate, global.floatingList, global.lampList; calls preinitAdaptables() first. preinitAdaptables() Initiates at compile time both Positions and Directions. reactorDaemon( parm ) Handles Reactors, set in initLibrary(). remDaemon( pointer, parameter {, object } {, clear_all_instances } ) Removes a daemon from global.daemonlist. pointer can be either a function or a method; if a method, object must be included. clear_all_instances will remove all instances of that function- parameter pair; otherwise, only one will go. sayDirection( direction_property ) Returns a list of direction words for the given direction. setDaemon( pointer, parameter {, object } {, place } ) Places the daemon in global.daemonlist with the given parameter at the given place (by default, just past the middle of the list). Can be either a function or a method pointer. showScore( points, turns ) Updates the score readout in non-HTML interpretations. sleepDaemon( parm ) Actor sleep, not set in Pianosa. sumBulk( list ) Sums the .totalbulk properties of all objects in list. sumWeight( list ) Sums the .totalweight properties of all objects in list. travelProp( direction_property ) Returns the ".go" property for the given direction. 4.2. General Functions These functions are found in ts_funcs.t execute( actor, verb {, direct_object {, preposition, indirect_object {, time_passes }}} ) Executes a command with execCommand, also allowing the current command to finish with grace. If time passes, runs daemons and fuses. gac( class {, property {, value {, argument }}} ) Gets all objects of a certain class in the entire gameworld. If property exists, checks it on the object to see if it matches with value (default = true) before including the object; if argument exists, supplies it to the property. gacal( class, list {, property {, value {, argument}}} ) Gets all objects of a certain class in a list, including visible contents of the objects. gacil( class, list {, property {, value {, argument}}} ) Gets all objects of a certain class in a list. getIndexList( list, value ) Returns a list of all indeces in the list with the given value, or returns nil for none such. getOutput( function_pointer ) Returns the outcapture() for a function. getOutput( object, property_pointer ) Returns the outcapture() for a method. imperative( a, b ) IMP operation. Returns nil only if a is true and b is nil. inputLine() Retrieves a line of input, setting the input font. listListing( list ) Lists the contents of a list, using .thedesc. listWithout( list, index ) Removes a given index from a list. pac() Prompt for a keypress, then clear the screen. _rand( number ) Adjusted random-number algorithm. redirect( actor, verb {, direct_object {, preposition, indirect_object}} ) Executes a command with execCommand, aborting the current command. resource( resource_string {, options_string } ) Attempts to display the given resource; if cannot, returns true. options_string is passed directly into the HTML code. sayDate( date_string ) Displays the date from the string, which has the format "Mth dd yyyy", in the format "Month d, yyyy". This former format is that used by __DATE__. sayNumber( number ) Displays the number (-100 <= number <= 100) in words; outside of this spectrum, just displays the number. sayValue( value ) Displays the given value, like so: Double: "(double-quoted string)" Function: "(function pointer)" List: "[" value1 value2 "]" Nil: "nil" Number: value Object: "(object: " value.sdesc ")" Property: "(property pointer)" Single: "'" value "'" True: "true" setHer( object ) Sets the "her" pronoun to object. setHim( object ) Sets the "him" pronoun to object. setThem( object|list ) Sets the "them" pronoun to an object or a list. sublist( list, start {, end} ) Returns part of a list. tabs( number {, string } ) Displays number instances of string (default = "\t"). 4.3. External Functions All functions here are supplied by ts_std.t. conclude() Ends the work. die() Kills off the player character. init() Initiates when the work is loaded. initRestart( parameter ) Initiates when the work is restarted. modifyParseError( error_number, default_message, ... ) Allows modifications to parserErrorParam without having to overwrite what's in Pianosa. Returning a list causes parserErrorParam to return the first content of that list. ts_std.t defines this emptily, ready to be replaced. pardon() Message called by the parser when the player types a blank line. rank() Function displaying a complete rank report. specialPreinit() Special compile-time initiation routines go here. stumble() Message called by .cantexit when travel occurs in the dark. terminate() Message called by ts_std.t's conclude() when quitting. Chapter 6 Supplemental Files There are six supplemental files: ts_codes.t, ts_funcs.t, ts_menu.t, ts_sense.t, ts_std.t, and ts_grid.t. The first two are included within Pianosa and provide core functionality. ts_std.t includes Pianosa and ts_menu.t, and provides standard functionality. ts_grid.t is an optional file which implements a randomly generated three-dimensional dynamically-constructed grid. ts_sense.t is a sense-passing library extension. 6.1. ts_codes.t These are the precompiler codes as defined by Michael J. Roberts in adv.t. The file is up to date with adv.t v2.5.1. This file may be harmlessly included in any programming endeavor without risk of code bloat, as it defines nothing which will be retained in a non-debugging version of the gamefile. 6.2. ts_funcs.t These functions are of general programming use, and so are drawn into their own file; those functions left in Pianosa are related directly to IF programming. For descriptions of the functions, see 4.2. 6.3. ts_grid.t There's a loophole in Pianosa. The .travel() routine allows direction properties to return a list of two elements: the first element must be an object, on which the .create routine will be called with three arguments: the second element, the source object, and the direction. Example: GreatHall: room east = [ MirrorHall 5 ] ; Going east will result in the call MirrorHall.create( 5, GreatHall, &east ) ts_grid.t brings in a simple application of this, dynamically generated pathways, which it accomplishes through the dynamicgrid object and the grid class. class dynamicgridclass: room Attributes .xposProp Property pointer which will contain the location information for the x coordinate. .yposProp Property pointer which will contain the location information for the y coordinate. .zposProp Property pointer which will contain the location information for the z coordinate. Methods .approve( x, y, z, source_object, direction_pointer ) Determines whether or not a room at coordinates (x,y,z), being reached from source_object via the given direction, is valid. .create( x, y, z, source_object, direction_pointer ) Creates an object for the room at (x,y,z) and calls .initiate upon it. .dynamicLinkTo( target_object, direction_pointer, deltax, deltay, deltaz, gridclass ) Links self to target_object and returns true if the action should be reciprocated (all linking is done beginning at the new object; back-links are only done when .dynamicLinkTo returns true) .dynamicLookup( x, y, z ) Returns the object for the room at (x,y,z) or nil if none exists or has been created yet. .initiate Initiates the dynamic object. .translateProp( deltax, deltay, deltaz ) Returns the property corresponding to the given changes in x, y, and z, or nil if none exists. Setup for the standard directions; x is west- east, y is south-north, and z is altitude. .xconvert( direction_pointer ) Converts the given property into its corresponding change in x. .yconvert( direction_pointer ) Converts the given property into its corresponding change in y. .zconvert( direction_pointer ) Converts the given property into its corresponding change in z. Only .approve, .initiate, and the three location properties are necessary in a class definition. To use a grid system, define an object of the grid class, give it location attributes, and assign one or more direction properties the value: [ dynamicgrid {grid class name} ] An excellent example of grids in action is the gridskeleton.t file. 6.4. ts_menu.t The following is excerpted and modified from a letter to Chad Schultz, to whom I owe a debt of gratitude -- you see, he forced me to write this. >And how do I use ts_menu.t? It's a supplemental library which establishes object-oriented menus. You don't have to do anything; it's automatically included [by ts_std.t]. Now, if you mean "How do I use it to write menus?", that's a harder question. The first thing you need is a menu class. A complete definition: class askMenu: menuclass menuCaseSensitive = nil // default menuTitle = "Ask about what?" // displayed above the menu menuKeyed = nil // keypress (true) or line input menuPrompt = ">" // displayed below the menu, where the // player types input orderMenu( lst, lvl, parm ) = { local i, newlist := [], len := length( lst ); for (i := 1; i <= len; ++i) if (lst[i].isKnownAbout) newlist += lst[i]; return newlist; } // order/modify the menu, where lst is a list of every object of this menu // class and lvl is how deep this menu is embedded. Should return a list of // objects, which do not necessarily have to be of the menu class. ; You then define menu items by declaring them as being of the menu class. Menu items can be gameworld objects. Momma: Actress, askMenu isKnownAbout = true noun = 'momma' 'mother' 'mom' 'mommy' 'mommie' 'ma' on = mommabed posture = Lie menuDesc = "Momma" // a description of the menu item menuKeys = [ 'momma' ] // a list of all inputs which should // be taken to mean this object menuAction( cls, lvl, dobj ) = { self.ioAskAbout( Me, dobj ); return true; } ; In order to display a menu, call writeMenu( menuclass ). writeMenu takes two optional arguments: the first being the depth (i.e. is this menu being displayed within another menu or not) and the second being parm, a completely unrestricted parameter which is passed to .menuAction, .orderMenu, .dispMenu, and .dispMenuItem. writeMenu() gets all the menu class objects with a specialized gac() that verifies that .disallowMenu( parm ) is nil for each object. It then passes the whole thing through .orderMenu and calls .dispMenu. From this point on, handling is divided as to whether the menu has .menuKeyed or not. .menuKeyed = true. writeMenu() compiles a list of all the valid keys for this object (in debug mode, there's a special key '$' which aborts the menu and returns true), prints .menuPrompt and then retrieves valid input. It finds the first object in the list with a .menuKeys entry matching the input and calls .menuAction on that object. .menuKeyed = nil. writeMenu() prints .menuPrompt, gets input and (in debug mode) tests to see if it's the special escape sequence '$'. Otherwise, it cycles through the menu items and calls .checkKey on each, making a list of those returning true. If only one returns true, .menuAction is called on it; if none return true but one returns 1, .menuAction is called on that; otherwise, it repeats this process. On menu items: .checkKey( key, class, level, parameter ) By default, just checks to see if the key is in self's .menuKeys list. True for absolutely approved, 1 for conditionally approved. .dispMenuItem( class, level, index, parm ) By default, goes to the next line, tabs once, and calls .menuDesc. .menuAction( class, level, parm ) Can do anything it wants. It should return one of three things, though: true to tell writeMenu to abort the entire menu system a number to move up a certain number of menus (1 goes back one menu) nil to just return to the same menu from which it was called By default, if self.menuList <> [], then it cycles to the next value (the current is stored in self.value) in .menuList and returns nil. On class: .menuClear If true, the screen is cleared by the default .dispMenu. .menuPrompt Defaults to ">". .dispMenu( level, parm, list ) Prints .menuTitle and then cycles through list, calling .dispMenuItem on each object. .orderMenu( list, depth, parm ) By default, does special behavior. If the depth is only, it only adds menuQuit (a simple "abort menu" item); if the depth is more than 1, it adds menuBack ("go to previous menu") too. 6.5. ts_sense.t ts_sense.t is a sense-passing system which is not integrated in the rest of Pianosa for performance concerns. It's all fairly simple: each sense is given its own sensory object -- although only three `senses' are defined in ts_sense.t -- and the whole thing revolves around one method, .cansense. class Sense: object Attributes .blocksenseProp Property for the specific sense-blocking method for this sense. .issensibleProp Property for the method determining whether an object is sensible. .positionProp Property for the "contents sensible" property on a Position object (or nil). .quicksensibleProp Property for a list of objects automatically sensible to the player. modify thing Attributes .audiblelist List of objects automatically audible to the player. .reachable List of objects automatically reachable by the player. .visiblelist List of objects automatically visible to the player. Methods .blockhearing( from_object, to_object, stepcount ) See .blocksense. The default version of .blockhearing defaults to .blockvision. .blockreach( from_object, to_object, stepcount ) See .blocksense. .blocksense( sense, from_object, to_object, stepcount ) Determines whether a sense can pass from from_object to to_object at a certain number of steps. Calls the appropriate sense-blocking method, e.g. .blockreach. .blockvision( from_object, to_object, stepcount ) See .blocksense. .cansense( sense, object {, stepcount } ) Determines whether self can sense object using sense at a given number of steps away from each other (default is 1). stepcount is not taken into account by .cansense, but is instead passed on to individual .blocksense routines which can then do as they will. .cansense will be discussed in a moment. .isreachable( obj ) Re-routed through .cansense. .isvisible( obj ) Re-routed through .cansense. .locatetree( object ) Returns a location-list from self up to object. If the pipe is in the bowl is on the table is on the floor in the car in the driveway, then pipe.locatetree( carfloor ) returns: [ pipe In bowl On table On carfloor ] If the argument is not in the full location-list, the full location list will be returned. The .cansense mechanism takes the following steps: 1. If object is inside and sensible to any object in self's quicksensible list, self can sense object. 2. The relationship between the two objects must be determined. a. If self is inside object, .cansense is simply called up the location list. b. If object is inside self, .cansense is not-so-simply called down the location list. c. If self and object have a common parent (determined using location lists), .blocksense is checked on the intersection, and then .cansense is called up to that parent and then down to object. The three senses provided for in ts_sense.t are Vision, Reach, and Hearing. 6.6. ts_std.t The standard definitions file. Included are such diverse elements as: 6.6.0. Functions addfootnote( message ) Adds a footnote with a given message. Footnotes are accessible via the footnote verb. conclude() Ends the game; calls terminate() and quit(). die( { message } ) Displays a message (default = `You have died.') and calls endMenu. init() Begins the game; sets Me as the player object, calls initCommon(), commence(), and then parserGetMe().startAt(). initCommon() Calls initLibrary(), sets hunger and sleep daemons, and sets up the title and about box. initRestart() Begins the game after a restart. Calls initCommon() and sets global.restarting true. pardon() Called by the parser when a blank line is typed. rank() Gives the score readout. stumble() Called by Pianosa when traveling in the dark. terminate() Prints a message when quitting; called by conclude(). 6.6.1. global global is the options object in Pianosa. There is an enormous amount of information stored on this single object. Behold. Attributes .directionlist List of all the direction objects in the game. .exitlist List of all proerty pointers of possible exits from a room. .floatinglist List of floating objects. .footnotelist List of footnote texts. .hungerTime Number determining default time between necessary meals. .hungryTime Number determining default time elapsed since the last meal for all actors. .initRestartParam Parameter passed to initRestart. .inventall Flag determining whether inventories should be given in tall or wide forms. .jostleJump Amount of default jostle passed to objects when a player jumps up and down. .jostlePutInto Amount of default jostle passed to objects by putInto. .jostleThrow Amount of default jostle passed to thrown objects. .lamplist List of all lamp objects in the game. .maxScore Number determining the maximum score. .minScore Number determining the minimum score. .Misunderstand A message stating that whatever was done is not understood. .positionlist List of all position objects in the game. .restarting Flag determining whether the game has been restarted this session. .score Number determining the current score. .sleepTime Number determining default time between necessary naps. .sleepyTime Number determining default time elapsed since the last nap for all actors. .sleepDuration Number determining how long an NPC sleeps for. .thisturn Number determining which turn this is right now. .verbose Flag determining whether the game is in verbose or terse mode (ts_std.t: true). .verboseLook Flag determining whether switching to verbose mode should automatically look around (ts_std.t: nil). .verboseScore Flag determining whether the player should be notified of score changes (ts_std.t: true). Methods .hasHTML Determines whether the game is in HTML mode or not. .hasAmbient Determines whether the game has ambient noises turned on or not. .hasBGAmbient Determines whether the game has background ambient noises turned on or not. .hasMusic Determines whether the game has music turned on or not. 6.6.2. directions ts_std.t defines the twelve standard directions: north, south, east, west, northeast, southeast, northwest, southwest, in, out, up, and down. 6.6.3. menus ts_std.t includes four sets of menus: endMenu Called after death/conclusion. optionsMenu Called after an options command. quitMenu Called after a quit command. restartMenu Called after a restart command. optionsMenu, in turn, defines two submenus: soundMenu and displayMenu. 6.6.4. miscellaneous Me: basicMe, notified startAt = (self.travelTo( startroom ));