// // += 3: A Logical Adventure // // Concept by Carl de Marcken and Dave Baggett. // Coding by Dave Baggett. // // Created 15-Nov-94. // Made easier 19-Nov-94 (v1.1) // Fixed bug (things given to troll don't disappear) (v1.2) // // This source requires WorldClass, a free TADS class library available // from ftp.gmd.de: if-archive/programming/tads/worldclass/ // #include modify global playtesting = nil turns = 1587 score = 99 ; modify putVerb doDefault(actor, prep, io) = { return dropVerb.doDefault(actor, prep, io); } ; modify dropVerb doDefault(actor, prep, io) = { local l, r, i; l := actor.itemcontents(actor, nil); r := []; for (i := 1; i <= length(l); i++) if (not l[i].isworn) r += l[i]; return r; } ; replace intro: function { I(); "Wow! This sure has been one tough game so far. But you're almost there -- 99 points out of 100 and what looks to be a run-of-the-mill troll on the bridge puzzle. Should be trivial for an adventure game god like you. And besides, any puzzle with a logical solution can't be *too* hard to solve. It's about time you got busy and finished the last puzzle and wrote up a walkthrough for..."; "\b"; version.sdesc; "\b"; } replace version: object name = { "\(+=\ 3: A Controversial but Nevertheless Logical Adventure\)\n Version 1.2"; } sdesc = { self.name; "\n"; "Copyright (C) 1994 David M.\ Baggett\n All rights reserved.\n Developed with TADS, the Text Adventure Development System.\n"; classlibrary.info; "\n"; "Difficulty Rating: Probably Requires Random Search (10 out of 10)\b"; "***"; P(); I(); "For instructions, type \"instructions\"."; P(); I(); "Read footnotes "; note(self); " with the note command; e.g., type \"note 1.\""; P(); I(); "Type \"credits\" for more information about the game."; P(); "***"; P(); } footnote = { "Footnote markers are numbers enclosed in square brackets."; } ; replace userpreinit: function { local v; for (v := firstobj(Verb); v <> nil; v := nextobj(v, Verb)) v.allok := nil; } replace userinit: function { if (global.restarting = nil) { "\b\b\b\b\b\b\b\b"; intro(); } global.lastactor := Me; Me.location.enter(Me); score_statusline(); } creditsVerb: Soloverb verb = 'credits' 'acknowledgements' sdesc = "list credits for" soloaction(actor) = { I(); "Carl de Marcken and Dave Baggett designed this game. Dave Baggett coded."; P(); I(); "Russ Bryan asked for it."; P(); I(); "\"You know, it looks to me like the real message of the game is that common-sense puzzles are a bad idea.\""; P(); "\t\t\t -- Felix Lee\n"; } ; instructVerb: Soloverb verb = 'instructions' 'help' 'hint' sdesc = "HELP!" soloaction(help) = { I(); "This game is not impossible, but it is very difficult. In fact, the authors suspect that few (if any) will be able to solve it the direct way; i.e., by using the clues in the game and common sense to figure out how to solve the puzzles."; P(); } ; Me: Player location = bridge noun = 'me' 'self' 'myself' ldesc = { "You're the adventurer in \(Zork\) who was too polite to open someone else's mailbox."; } isnoticeable(actor) = { return nil; } smelldesc = "You smell inextinguishable." listendesc = "You sound like a colorless green idea." starvationcheck = nil dehydrationcheck = nil sleepcheck = nil ; bridge: Room tdesc = "On the Three Troll Bridge" ldesc = { I(); "You are standing on a rickety wooden bridge. "; if (troll.givencount < 3) { "A burly Three Troll blocks your passage north, across the bridge."; } } sdesc = "<>" verGoSouth(actor) = { "Sorry, you've already explored that area and gotten all the points."; } verGoNorth(actor) = { if (troll.givencount < 3) "The troll won't let you pass."; } goNorth(actor) = { "You stride confidently past the troll and onto a glorious but drafty victory."; incscore(1); end(); } verGoDown(actor) = { "There's no way to get down there short of jumping, which seems like a bad idea indeed."; } verJump(actor) = { return self.verGoDown(actor); } ; bridgedecoration: Qover location = bridge noun = 'bridge' adjective = 'troll' 'three' 'rickety' 'wooden' sdesc = "rickety wooden bridge" ldesc = "It's just a typical rickety adventure game bridge." acceptsput(actor, loctype) = { "You can't reach."; } ; water: Qcontainer sdesc = "the water" isdetermined = true ldesc = "There's nothing special about the water." location = bridgedecoration locationtype = 'under' noun = 'water' verIoPutin(actor) = {} ioPutin(actor, dobj) = { local r; "Splash. "; r := rand(4); if (r = 1) "The fish jumps."; else if (r = 2) "The fish jumps high in the air, executes a flawless double twist, and then splashes back into the water."; else if (r = 3) "The fish jumps high in the air -- almost as high as the bridge."; else if (r = 4) "The fish jumps over the bridge and back into the water, startling the troll!"; dobj.movein(nil); } passgen(actor, obj, loctype, passmethod) = { // If not "in" containment or nil, call our parent's method. if (loctype <> nil and loctype <> 'in') return inherited.(passmethod)(actor, obj, loctype); "You can't reach the water from here."; return nil; } passcantouchin(actor, obj, loctype) = { return self.passgen(actor, obj, loctype, &passcantouch); } passcantakein(actor, obj, loctype) = { return self.passgen(actor, obj, loctype, &passcantake); } passcansmellin(actor, obj, loctype) = { return self.passgen(actor, obj, loctype, &passcansmell); } ; redthing: Decoration location = water locationtype = 'in' sdesc = "red thing" ldesc = "It seems to be swimming around." noun = 'thing' 'fish' 'herring' adjective = 'red' verDoTake(actor) = { "There is no \(obvious\) way to get at it."; } ; troll: Male, Actor, Listablesound givencount = 0 sdesc = "burly Three Troll" ldesc = { if (self.givencount < 3) "He holds his hand out expectantly."; else "He seems to be ignoring you."; } noun = 'troll' adjective = 'burly' location = bridge actordesc = {} islistable(actor) = { return nil; } verIoGiveto(actor) = {} ioGiveto(actor, dobj) = { if (self.givencount = 3) { "The troll ignores you."; } else { dobj.movein(nil); self.givencount++; "\^\"<>!\" he grunts."; if (self.givencount = 3) " The troll now seems less overbearing."; } } listlistendesc = "is ticking." listendesc = "The troll, oddly enough, seems to be ticking." smelldesc = "The troll smells lemony fresh." ; trollhand: Part partof = troll sdesc = "troll's hand" ldesc = { if (troll.givencount < 3) "It's being held out by its owner, the troll, expectantly."; else "It looks like an ordinary troll hand."; } noun = 'hand' adjective = 'troll\'s' 'troll' acceptsput(actor, loctype) = { return loctype = 'in' ? true : nil; } verIoPutin(actor) = { troll.verIoPutin(actor); } ioPutin(actor, dobj) = { troll.ioPutin(actor, dobj); } ; class myclothes: Clothing ldesc = "There's nothing special about <>." isdetermined = true adjective = 'my' location = Me isnoticeable(actor) = { if (self.isin(Me) and self.isworn) return nil; else return true; } isworn = true ; shirt: myclothes sdesc = "your shirt" noun = 'shirt' ; pants: myclothes isplural = true sdesc = "your pants" noun = 'pants' ; shoes: myclothes isplural = true sdesc = "your shoes" noun = 'shoes' ; socks: myclothes isplural = true sdesc = "your socks" noun = 'socks' ; glasses: myclothes isplural = true sdesc = "your glasses" noun = 'glasses' 'spectacles' 'specs' ; underwear: myclothes sdesc = "your underwear (yuck)" noun = 'underwear' ; clothes: Decoration noun = 'clothes' 'clothing' adjective = 'my' location = bridge sdesc = "your clothes" isplural = true isdetermined = true ldesc = { if (troll.givencount = 0) "There's nothing unusual about your clothes."; else "There's nothing unusual about the clothing that you still have."; } verDoTake(actor) = { "You'll need to be more specific."; } ; qual_calculator: Item sdesc = "qualitative calculator" ldesc = { I(); "Your parents gave you this for your birthday last year. It's just the sort of thing they'd be absolutely wrong about thinking you'd need. And indeed, you've found no use for it to date. <>"; P(); I(); "It has has 9 buttons: ZERO, POSITIVE, NEGATIVE, ADD, SUBTRACT, MULTIPLY, DIVIDE, Clear and deClear. The readout currently shows <>."; } noun = 'calculator' 'calc' adjective = 'qualitative' location = Me footnote = { "Respects to Walter Hamscher and Carl de Marcken."; } stack = [] secondstack = [] saynewreadout = { "\nThe readout now shows <>.\n"; } sayreadout = { local v; if (length(stack) < 1) v := 0; else v := stack[1]; if (v = -1) "[[\ -\ ]]"; else if (v = 0) "[[\ 0\ ]]"; else if (v = 1) "[[\ +\ ]]"; else "[[\ ?\ ]]"; } pop = { local v; if (length(stack) < 1) v := 0; else { v := car(stack); stack := cdr(stack); } return v; } ; readout: Part sdesc = "readout" ldesc = { qual_calculator.saynewreadout; } partof = qual_calculator noun = 'readout' adjective = 'calculator' ; qualbutton: Part, Button ldesc = "There is nothing special about <>." partof = qual_calculator ; clear: qualbutton sdesc = "Clear button" noun = 'button' adjective = 'clear' 'kleer' doPush(actor) = { qual_calculator.secondstack := qual_calculator.stack; qual_calculator.stack := []; qual_calculator.saynewreadout; } ; declear: qualbutton sdesc = "deClear button" noun = 'button' adjective = 'declear' 'dekleer' doPush(actor) = { local tmp; tmp := qual_calculator.stack; qual_calculator.stack := qual_calculator.secondstack; qual_calculator.secondstack := tmp; qual_calculator.saynewreadout; } ; zerobutton: qualbutton sdesc = "ZERO button" noun = 'button' adjective = 'zero' doPush(actor) = { qual_calculator.stack := [ 0 ] + qual_calculator.stack; qual_calculator.saynewreadout; } ; positivebutton: qualbutton sdesc = "POSITIVE button" noun = 'button' adjective = 'positive' doPush(actor) = { qual_calculator.stack := [ 1 ] + qual_calculator.stack; qual_calculator.saynewreadout; } ; negativebutton: qualbutton sdesc = "NEGATIVE button" noun = 'button' adjective = 'negative' doPush(actor) = { qual_calculator.stack := [ -1 ] + qual_calculator.stack; qual_calculator.saynewreadout; } ; addbutton: qualbutton sdesc = "ADD button" noun = 'button' adjective = 'add' doPush(actor) = { local v, v1, v2; v1 := qual_calculator.pop; v2 := qual_calculator.pop; if (v1=2 or v2=2) v := 2; else if ((v1=1 and v2=-1) or (v1=-1 and v2=1)) v := 2; else if (v1=1 or v2=1) v := 1; else if (v1=-1 or v2=-1) v := -1; else v := 0; qual_calculator.stack := [ v ] + qual_calculator.stack; qual_calculator.saynewreadout; } ; subtractbutton: qualbutton sdesc = "SUBTRACT button" noun = 'button' adjective = 'subtract' doPush(actor) = { local v, v1, v2; v1 := qual_calculator.pop; v2 := qual_calculator.pop; if (v1=2 or v2=2) v := 2; else if ((v1=1 and v2=1) or (v1=-1 and v2=-1)) v := 2; else if (v2<>0) v := v2; else v := -v1; qual_calculator.stack := [ v ] + qual_calculator.stack; qual_calculator.saynewreadout; } ; multiplybutton: qualbutton sdesc = "MULTIPLY button" noun = 'button' adjective = 'multiply' doPush(actor) = { local v, v1, v2; v1 := qual_calculator.pop; v2 := qual_calculator.pop; if (v1=2 or v2=2) v := 2; else if (v1=0 or v2=0) v:= 0; else if (v1=v2) v := 1; else v := -1; qual_calculator.stack := [ v ] + qual_calculator.stack; qual_calculator.saynewreadout; } ; dividebutton: qualbutton sdesc = "DIVIDE button" noun = 'button' adjective = 'divide' doPush(actor) = { local v, v1, v2; v1 := qual_calculator.pop; v2 := qual_calculator.pop; if (v1=2 or v2=2 or v1=0) v := 2; else if (v2=0) v := 0; else if (v1=v2) v := 1; else v := -1; qual_calculator.stack := [ v ] + qual_calculator.stack; qual_calculator.saynewreadout; } ;