/*There is no easy way to explain everything in this module. You're going to have to look through it for yourself and figure it out. If you're writing your first game then this probably isn't something you should use unless you're willing to spend a lot of time debugging, and I mean a lot. This code defines several new classes of objects, things can be hard, earth, wood, fragile, liquid, liquid container, or firestarters. This gives useful responses for just about anything in an average IF game. I eventually plan to move liquids and liquid containers to their own, more comprehensive module that will include mixing, measuring, and powders. Keep in mind that you can't just include this code in your game and go around defining things as hard or earth or whatever. Different types have different requirements. For instance if you define something as wood you also have to define broken and burned properties so it knows what sort of item to replace the wood with when it is destroyed. There is also a property called specialbreak that will allow you to override breaking for certain items if they have to have special puzzle-related responses. Like I said before, this code is not simple. You have to look over all of it and understand it before you use it or your game will be horribly broken. It is a very useful piece of code though and much of The Erudition Chamber was based on this module. In fact if you need examples of how to use this then I recommend looking through The Erudition Chamber's source since this module was written specifically for that game. Code written by Daniel Freas I can be reached at erthwin@cox.net */ //PARSE WITH NORMAL TADS OPERATORS #pragma C- modify breakVerb verb = 'break' 'ruin' 'destroy' 'chop' sdesc = "break" doAction = 'Break' ioAction(withPrep) = 'BreakWith' ; modify attackVerb verb = 'attack' 'kill' 'hit' sdesc = "attack" doAction = 'Attack' prepDefault = withPrep ioAction(withPrep) = 'AttackWith' ; burnVerb: deepverb verb = 'burn' 'light' sdesc = "burn" doAction = 'Burn' ioAction(withPrep) = 'BurnWith' ; Pourverb: deepverb sdesc = "pour" verb = 'pour' doAction = 'Pour' ioAction(onPrep) = 'PourOn' ; Emptyverb: deepverb sdesc = "empty" verb = 'empty' doAction = 'Empty' ; Fillverb: deepverb sdesc = "fill" verb = 'fill' doAction = 'Fill' ioAction(withPrep) = 'FillWith' ; modify class item verDoLift( actor ) = self.verDoTake( actor ) doLift( actor ) = self.doTake( actor ) ; modify class thing type = nil verDoTalkTo( actor ) = {} doTalkTo( actor ) = { "\^<> doesn’t seem interested.\n"; } verDoOil(actor) = { "You cannot oil <>"; } verDoLift( actor ) = { "You cannot lift <>"; } verDoBreak(actor) = {} doBreak(actor) = { askio(withPrep); } verDoAttack(actor) = {} doAttack(actor) = { askio(withPrep); } verIoBreakWith(actor) = {} ioBreakWith(actor, dobj) = { "\^<> cannot be used to break anything.\n"; } verDoAttackWith(actor, iobj) = {} verDoBreakWith(actor, iobj) = {} verDoBurn(actor) = { if ( self.type = nil ) "\^<> cannot be burned.\n"; } doBurn(actor) = { self.tmpList := actor.contents + actor.location.contents; self.tmpObj := car( tmpList ); self.tmpFObj := nil; while ( tmpObj <> nil ) { if ( tmpObj.isfire ) tmpFObj := tmpObj; tmpList := cdr( tmpList ); tmpObj := car( tmpList ); } if ( tmpFObj <> nil ) { "(With <>)\n"; if ( not actor.isCarrying( tmpFObj ) ) { "(First taking <>)\n"; tmpFObj.doTake( actor ); } tmpFObj.ioBurnWith(actor, self); } else askio(withPrep); } verIoBurnWith(actor) = { "\^<> cannot be used to burn things.\n"; } verDoBurnWith(actor, iobj) = {} verDoTake( actor ) = { if ( self.ishot ) "\^<> is too hot to touch right now, you\'ll have to wait for it to cool down.\n"; } verDoTouch( actor ) = { if ( self.ishot ) "\^<> is too hot to touch right now, you\'ll have to wait for it to cool down.\n"; } doTouch( actor ) = { "You feel nothing notable.\n"; } verIoPourOn( actor ) = {} ioPourOn( actor, dobj ) = { if( isclass( dobj, liquidcont ) ) //IF DOBJ IS CONTAINER ASSUME PLAYER MEANS CONTENTS OF CONTAINER dobj := car( dobj.contents ); "You pour <> out and watch as it "; if( !isclass(self, wood) and !isclass(self, earth) )//EARTH AND WOOD ABSORB LIQUID "runs across the surface of <> and pours out onto the ground."; else "slowly soaks into <>, disappearing in moments."; if( dobj.isdynamic ) //DELETE DYNAMIC OBJECTS delete dobj; else dobj.moveInto( nil ); //STATIC OBJECTS ARE MOVED INTO NIL } scriptNum = 0 script = { self.scriptNum++; switch( self.scriptNum ) { case 1: break; case 2: break; case 3: { self.ishot := nil; unnotify (self, &script); self.scriptNum := 0; } } } ; class firestarter: thing isfire = true verIoBurnWith(actor) = {} ioBurnWith(actor, dobj) = { if ( self.isfire ) { if ( actor.isCarrying( dobj ) ) "It would likely be less painful if you avoided burning things while you were carrying them.\n"; else if ( dobj.type = fragile ) { "The heat from <> causes <> to blacken and crack but it does not burn.\n"; dobj.burned.moveInto( dobj.location ); dobj.moveInto( nil ); } else if ( dobj.type = hard ) { "\^<> causes <> to heat up but it refuses to burn.\n"; dobj.ishot := true; notify (dobj, &script, 0); } else if ( dobj.type = wood ) { "The fire from <> quickly catches and <> "; if ( dobj.contents ) { self.tmpList := dobj.contents; self.passList := []; self.tmpObj := car( tmpList ); while ( tmpObj <> nil ) { outhide( true ); self.ioBurnWith( actor, tmpObj ); outhide( nil ); if ( tmpObj.location <> nil ) { tmpObj.moveInto( dobj.location ); self.passList := self.passList + tmpObj; } else tmpObj.burned.moveInto( dobj.location ); tmpList := cdr( tmpList ); self.tmpObj := car( tmpList ); } } "goes up in flames. Within moments it has burnt down to nothing and the flame subsides.\n"; if ( length( self.passList ) <> 0 ) "\^<> <> survived the flames.\n"; dobj.burned.moveInto( dobj.location ); dobj.moveInto( nil ); } else if ( dobj.type = earth ) { "You attempt to burn <> with <> but it refuses to catch.\n"; } else { "\^<> cannot be burned.\n"; } } else { "\^<> can no longer be used to burn things.\n"; } } ; class fragile: thing type = fragile doTouch( actor ) = { "\^<> feels rather fragile.\n"; } verDoBreak(actor) = {} doBreak(actor) = { "You throw <> against the ground, shattering it into hundreds of tiny pieces.\n"; self.broken.moveInto( self.location ); if ( self.contents <> nil ) { self.tmpList := self.contents; self.tmpObj := car( tmpList ); while ( tmpObj <> nil ) { tmpObj.moveInto( self.location ); tmpList := cdr( tmpList ); self.tmpObj := car( tmpList ); } } self.moveInto( nil ); } verIoAttackWith(actor) = {self.verIoBreakWith(actor);} verIoBreakWith(actor) = { if ( not actor.isCarrying( self ) ) "You aren't carrying <>\n"; } ioAttackWith(actor, dobj) = {self.ioBreakWith(actor, dobj);} ioBreakWith(actor, dobj) = { if ( dobj.type = fragile ) { "As you smash <> and <> together both shatter into hundreds of tiny pieces.\n"; self.broken.moveInto( self.location ); if ( self.contents <> nil ) { self.tmpList := self.contents; self.tmpObj := car( tmpList ); while ( tmpObj <> nil ) { tmpObj.moveInto( self.location ); tmpList := cdr( tmpList ); self.tmpObj := car( tmpList ); } } dobj.broken.moveInto( dobj.location ); if ( dobj.contents <> nil ) { self.tmpList := dobj.contents; self.tmpObj := car( tmpList ); while ( tmpObj <> nil ) { tmpObj.moveInto( dobj.location ); tmpList := cdr( tmpList ); tmpObj := car( tmpList ); } } self.moveInto( nil ); dobj.moveInto( nil ); } if ( dobj.type = hard or dobj.type = wood or dobj.type = earth ) { "The sudden force causes <> to shatter into hundreds of tiny pieces.\n"; self.broken.moveInto( self.location ); if ( self.contents <> nil ) { self.tmpList := self.contents; self.tmpObj := car( tmpList ); while ( tmpObj <> nil ) { tmpObj.moveInto( self.location ); tmpList := cdr( tmpList ); tmpObj := car( tmpList ); } } self.moveInto( nil ); } if ( dobj.type = liquid ) { "\^<> is a liquid. It is a generally accepted fact that liquids cannot be broken.\n"; } if ( dobj.type = nil ) { "\^<> cannot be broken.\n"; } } ; class liquidcont: container verIoPutIn( actor ) = {} ioPutIn( actor, dobj ) = { if ( not actor.isCarrying( self ) ) //IMPLICIT TAKE FOR FILL COMMAND { "(First taking <>)\n"; self.doTake( actor ); } if ( !isclass(dobj, liquid) ) "\^<> is only suitable for holding liquids. "; else if ( itemcnt(self.contents) != 0 ) "\^<> already contains <>. "; else pass ioPutIn; } verDoFillWith( actor, iobj ) = {} verDoFill(actor) = {} doFill(actor) = { askio(withPrep); } holds = { if ( itemcnt(self.contents) != 0 ) "It currently contains <>. "; else "It is currently empty. "; } verDoEmpty( actor ) = { if( itemcnt(self.contents) = 0 ) "\^<> is already empty.\n"; } doEmpty( actor ) = { tmpObj := car( self.contents ); tmpObj.doDrop( actor ); } verDoPour( actor ) = { if( itemcnt(self.contents) = 0 ) "\^<> is already empty.\n"; } doPour( actor ) = ( self.doEmpty( actor ) ) verDoPourOn( actor, iobj ) = { if( itemcnt(self.contents) = 0 ) "\^<> is already empty.\n"; } ; class liquid: thing type = liquid verIoBreakWith(actor) = { if ( not actor.isCarrying( self ) ) "You aren't carrying <>. "; } ioBreakWith(actor, dobj) = { "\^<> is a liquid. Liquids are notoriously ineffective when used to break things. "; } doTouch( actor ) = { "\^<> feels like any other liquid might. "; } verDoTake( actor ) = { if ( Me.isCarrying( self ) ) "You already have <>. "; } doTake( actor ) = { if ( isclass(self.location, liquidcont) ) //IS IT IN A CONTAINER? { "You take <> of <>. "; //TAKE THE CONTAINER OF LIQUID self.location.moveInto(actor); } else "You’ll have to put <> in something. "; //NEEDS A CONTAINER FIRST } doPutOn(actor, io) = { io.ioPourOn(actor, self); } verDoPour( actor ) = {} doPour( actor ) = ( self.doDrop( actor ) ) verDoPourOn( actor, iobj ) = {} doPourOn(actor, io) = { io.ioPourOn(actor, self); } verDoPutOn( actor, iobj ) = {} verIoFillWith( actor ) = {} ioFillWith( actor, dobj ) = { dobj.ioPutIn( actor, self ); //FILL WITH IS JUST PUT IN WITH THE NOUNS REVERSED } verDoDrop( actor ) = { if ( not Me.isCarrying( self ) ) "You\'re not carrying <>.\n"; } doDrop( actor ) = { "You pour <> out onto the ground.\n"; if( self.isdynamic ) delete self; //DELETE DYNAMIC OBJECTS else self.moveInto( nil ); //STATIC OBJECTS JUST GET MOVED INTO NIL } ; class hard: thing type = hard doTouch( actor ) = { "You feel nothing notable. \^<> is solid.\n"; } verIoAttackWith(actor) = {self.verIoBreakWith(actor);} verIoBreakWith(actor) = { if ( not actor.isCarrying( self ) ) "You aren't carrying <>\n"; } ioAttackWith(actor, dobj) = {self.ioBreakWith(actor, dobj);} ioBreakWith(actor, dobj) = { if( dobj.specialbreak = true ) //ALLOW OVERRIDE OF BREAK FOR SPECIFIC ITEMS dobj.broke( self ); else { if ( dobj.type = fragile or dobj.type = wood ) { "You swing <> violently and smash <> to bits.\n"; dobj.broken.moveInto( dobj.location ); if ( dobj.contents <> nil ) { self.tmpList := dobj.contents; self.tmpObj := car( tmpList ); while ( tmpObj <> nil ) { tmpObj.moveInto( dobj.location ); tmpList := cdr( tmpList ); tmpObj := car( tmpList ); } } dobj.moveInto( nil ); } if ( dobj.type = hard ) { if ( dobj.hashardshocked ) { "It hurt like all heck the first time you tried that, what makes you think things will go better if you try again?\n"; } else { "The force of the blow sends a violent shockwave up <> causing your hands to go numb with pain and thoroughly convincing you that you do not want to try that again.\n"; dobj.hashardshocked := true; } } if ( dobj.type = earth ) { "There is a hollow thud as <> hits <> but nothing obvious happens.\n"; } if ( dobj.type = liquid ) { "\^<> is a liquid. It is a generally accepted fact that liquids cannot be broken.\n"; } if ( dobj.type = nil ) { "\^<> cannot be broken.\n"; } } } ; class wood: thing type = wood doTouch( actor ) = { "You can feel the grains in the wood of <>.\n"; } verIoAttackWith(actor) = {self.verIoBreakWith(actor);} verIoBreakWith(actor) = { if ( not actor.isCarrying( self ) ) "You aren't carrying <>\n"; } ioAttackWith(actor, dobj) = {self.ioBreakWith(actor, dobj);} ioBreakWith(actor, dobj) = { if ( dobj.type = fragile ) { "You swing <> violently and smash <> to bits.\n"; dobj.broken.moveInto( dobj.location ); if ( dobj.contents <> nil ) { self.tmpList := dobj.contents; self.tmpObj := car( tmpList ); while ( tmpObj <> nil ) { tmpObj.moveInto( dobj.location ); tmpList := cdr( tmpList ); tmpObj := car( tmpList ); } } dobj.moveInto( nil ); } if ( dobj.type = wood or dobj.type = hard ) { if ( dobj.haswoodshocked ) { "It hurt like all heck the first time you tried that, what makes you think things will go better if you try again?\n"; } else { "The force of the blow sends a violent shockwave up <> causing your hands to go numb with pain and thoroughly convincing you that you do not want to try that again.\n"; dobj.haswoodshocked := true; } } if ( dobj.type = earth ) { "There is a hollow thud as <> hits <> but nothing obvious happens.\n"; } if ( dobj.type = liquid ) { "\^<> is a liquid. It is a generally accepted fact that liquids cannot be broken.\n"; } if ( dobj.type = nil ) { "\^<> cannot be broken.\n"; } } ; class earth: thing type = earth verIoAttackWith(actor) = {self.verIoBreakWith(actor);} verIoBreakWith(actor) = { if ( not actor.isCarrying( self ) ) "You aren't carrying <>\n"; } ioAttackWith(actor, dobj) = {self.ioBreakWith(actor, dobj);} ioBreakWith(actor, dobj) = { if ( dobj.type = fragile ) { "You swing <> violently and smash <> to bits.\n"; dobj.broken.moveInto( dobj.location ); if ( dobj.contents <> nil ) { self.tmpList := dobj.contents; self.tmpObj := car( tmpList ); while ( tmpObj <> nil ) { tmpObj.moveInto( dobj.location ); tmpList := cdr( tmpList ); tmpObj := car( tmpList ); } } dobj.moveInto( nil ); } if ( dobj.type = wood or dobj.type = hard or dobj.type = earth ) { "There is a hollow thud as <> hits <> but nothing obvious happens.\n"; } if ( dobj.type = liquid ) { "\^<> is a liquid. It is a generally accepted fact that liquids cannot be broken.\n"; } if ( dobj.type = nil ) { "\^<> cannot be broken.\n"; } } ; //