!% -~S !% $OMIT_UNUSED_ROUTINES=1 !% $MAX_STATIC_DATA=60000 !% $MAX_LABELS=5000 !% $MAX_ZCODE_SIZE=50000 Switches e; ! Testbench - a platform for trying things out in PunyInform ! compile as z8 to use Inform stdlib instead of puny (for debugging) #Iftrue (#version_number == 8); Constant USEINFORM; #Endif; ! Uncomment ONE of the two following lines, to show either time or score/turns ! Leaving both commented out makes the library bigger. Statusline time; !Constant STATUSLINE_SCORE; Statusline score; Constant RUNTIME_ERRORS = 2; ! 0 = Minimal error checking, 1 = Numeric error codes, 2: Error messages #IfnDef USEINFORM; ! Uncomment to add optional features to PunyInform !Constant OPTIONAL_NO_DARKNESS; Constant STATUSLINE_TIME; Constant OPTIONAL_ALLOW_WRITTEN_NUMBERS; Constant OPTIONAL_EXTENDED_METAVERBS; Constant OPTIONAL_EXTENDED_VERBSET; Constant OPTIONAL_PRINT_SCENERY_CONTENTS; Constant OPTIONAL_SCORED; Constant OPTIONAL_FULL_SCORE; Constant OPTIONAL_GUESS_MISSING_NOUN; Constant OPTIONAL_FULL_DIRECTIONS; Constant OPTIONAL_SIMPLE_DOORS; Constant OPTIONAL_SHIP_DIRECTIONS; Constant OPTIONAL_MANUAL_SCOPE; Constant OPTIONAL_MANUAL_REACTIVE; Constant OPTIONAL_REACTIVE_PARSE_NAME; Constant OPTIONAL_ORDERED_TIMERS; Constant MAX_SCOPE = 50; #Iftrue (#version_number == 5); Constant OPTIONAL_PROVIDE_UNDO; #Endif; Constant INITIAL_LOCATION_VALUE = Library; !Constant DEBUG; ! Provides debug verbs for both Inform and PunyInform !Constant DEBUG_PARSEANDPERFORM; !Constant DEBUG_PARSEPATTERN; !Constant DEBUG_PARSETOKEN; !Constant DEBUG_CHECKNOUN; !Constant DEBUG_GETNEXTNOUN; !Constant DEBUG_SCOPE; !Constant DEBUG_TIMER; ! requires special Ozmoo #EndIf; !Constant TEST_BEFOREAFTER; Constant Story "Testbench"; Constant Headline "^A sandbox for PunyInform development^"; #IfDef DEBUG_TIMER; Serial "999999"; ! Serial "999999" enables timing in Ozmoo, meaning that the RTC (jiffies since start) can be read from $1c-->0 #EndIf; Constant MAX_CARRIED 3; Constant SACK_OBJECT infiniteBag; Constant AMUSING_PROVIDED; #IfDef OPTIONAL_FULL_SCORE; Constant MAX_SCORE = 7; Constant OBJECT_SCORE = 1; Array task_scores -> 3 0; ! inform doens't like array of length 1 Constant TASKS_PROVIDED; Constant NUMBER_TASKS = 1; #IfNot; Constant MAX_SCORE = 3; #EndIf; [ Amusing; "^Did you try?^^1. Pushing John many times.^2. Going outside and looking at the sun"; ]; ! Setup cheap scenery [SceneryReply w1 w2; Push: if(w1=='bird' && w2=='birds') "The birds fly away as you try."; "Now how would you do that?"; default: rfalse; ]; ! Setup flags Constant FLAG_COUNT 8; !Constant F_SQUIRREL_ESCAPED 0; !Constant F_PARROT_FED 1; !Constant F_BOUGHT_TICKETS 2; #IfDef TEST_BEFOREAFTER; [LookRoutine; "***** LookRoutine, yay!"; ]; #EndIf; #Ifdef USEINFORM; Include "Parser"; Attribute reactive; Include "VerbLib"; Include "ext_cheap_scenery.h"; Include "ext_flags.h"; [OnOff obj; ! TODO: is there something like this in I6? change name if needed if(obj has on) print "on"; else print "off"; return; ]; #IfNot; Include "globals.h"; #EndIf; [InScope p_actor; if(p_actor == player && location == thedark && John in real_location) PlaceInScope(John); rfalse; ]; [ParseNoun obj w; if(obj == LargeBox) { w = NextWord(); if(w == 'crate') { wn = wn + 7; return 1; } ! Change wn just to check that nothing breaks if(w == 'huge') return -1; wn--; } if(obj == PinkBook) { w = NextWord(); if(w == 'tiny') return -1; wn--; } return -1; ]; [ DarkToDark; deadflag = 1; "You are eaten by a grue."; ]; [ PrintRank; print ", earning you the rank of "; if (score >= 3) "Treasure hunter."; if (score >= 2) "Explorer."; "Tourist."; ]; [ PrintTaskName task_number; switch (task_number) { 0: "opening the box"; } ]; #Ifndef USEINFORM; Include "ext_cheap_scenery.h"; Include "ext_flags.h"; Include "ext_menu.h"; ! Setup custom library messages Constant MSG_OPEN_YOU_CANT 1000; Constant MSG_AREYOUSUREQUIT 1001; Constant MSG_DISROBE_NOT_WEARING 1002; Constant MSG_LOOK_BEFORE_ROOMNAME 1003; [LibraryMessages p_msg p_arg_1 p_arg_2; switch(p_msg) { MSG_OPEN_YOU_CANT: "How would you go about opening ", (a) noun, "?"; MSG_AREYOUSUREQUIT: print "You ain't no quitter eh? "; rtrue; MSG_DISROBE_NOT_WEARING: "Not worn!"; MSG_LOOK_BEFORE_ROOMNAME: if(turns >= 0) new_line; } p_arg_1 = 0; p_arg_2 = 0; ! To avoid warnings ]; [DisallowTakeAnimate; if(noun == Lizard) rfalse; ]; Include "puny.h"; Include "ext_waittime.h"; #Endif; [ HelpItems; print "There is information provided on the following:^^"; print " Instructions^"; print " About this game^"; print " Game credits^"; ]; [ HelpMenu; switch(menu_item) { 0: item_width=20; item_name="Help and Information"; return 3; 1: item_width=12; item_name="Instructions"; 2: item_width=15; item_name="About this game"; 3: item_width=12; item_name="Game credits"; } ]; [ HelpInfo; switch(menu_item) { 1: "You play this game like any old Infocom game.^^Common commands lnclude examine, open, close, save, restore and quit."; 2: "This is a test game"; 3: "This was was created by us"; } ]; [ HelpSub; DoMenu(HelpItems, HelpMenu, HelpInfo); ]; Verb 'help' * -> Help; Verb 'talk' * 'to'/'with' creature -> Talk; [TalkSub; if (noun == player) "The conversation is hardly inspiring."; if (RunLife(noun,##Talk) ~= false) return; "You have nothing to say."; ]; [ScanScope; switch(scope_stage) { 1: rfalse; 2: ScopeWithin(RiverBank); rtrue; 3: "You're crazy!"; } ]; [BangParse; #Ifdef USEINFORM; return ParseToken(ELEMENTARY_TT, NUMBER_TOKEN); #Ifnot; return ParseToken(TT_OBJECT, NUMBER_OBJECT); #Endif; ]; Verb 'bang' * BangParse -> Bang; [BangSub; "Noun is ", parsed_number, "."; ]; [WowScope; switch(scope_stage) { 1: rfalse; 2: ScopeWithin(CarPark); rtrue; 3: "You can't wow that, you crazy person!"; } ]; [WowParse x; #Ifdef USEINFORM; x = ParseToken(SCOPE_TT, WowScope); #Ifnot; x = ParseToken(TT_SCOPE, WowScope); #Endif; print "ParseToken returned ", x, "^"; return x; ]; Verb 'wow' * WowParse -> Wow; [WowSub; print (The) noun, " is in scope!^"; ! LoopOverScope(WowLoop); ]; Verb 'scan' * scope=ScanScope -> Scan * 'local' noun -> Scan; [ScanSub; if(AfterRoutines()) rtrue; print "Scanning ", (the) noun, "... Clear!^"; ]; Constant SCN_WATER = "The water is so beautiful this time of year, all clear and glittering."; [SCN_SUN; deadflag = 1; "As you stare right into the sun, you feel a burning sensation in your eyes. After a while, all goes black. With no eyesight, you have little hope of completing your investigations."; ]; Class Book with name 'books//p', description [; print "Self is ", self, "^"; if(self provides hello) { print (The) self, " has a Hello value of ", self.hello, ". ^"; } rfalse; ], hello 0, party [a; print "Self is ", self, "^"; print "a is ", a, "^"; ! print "b is ", b, "^"; ! print "c is ", c, "^"; ], before [; Open: "You've never been much of a reader."; ], has openable; Object CarPark "Car Park" with !short_name [; print "In front of the library!"; rtrue; ], initial "Wow, this is a huge car park!", description [; "You are in a car park in front of the library. You can enter to the north. There is a river off to the east.";], n_to Library, sw_to [; "There's an angry dragon blocking the path!"; ], e_to RiverBank, each_turn [; print (string) random( "^An owl is howling nearby.", "^A terrible scream is heard from the library.", "^The sound of many birds comes from the east."); ""; ], #IfDef TEST_BEFOREAFTER; after [; print "*** CarPark.after^"; ], before [; print "*** CarPark.before^"; ], #EndIf; cant_go "Without a car the only viable exit is to the north.", #IfDef OPTIONAL_FULL_SCORE; has scored light reactive; #IfNot; has light reactive; #EndIf; Object -> Key "key" with description "It's a metal key, with a keyring attached to it.", name 'key' 'metal', #IfDef TEST_BEFOREAFTER; after [; print "*** Key.after^"; ], before [; print "*** Key.before^"; ], #EndIf; has transparent #IfDef OPTIONAL_FULL_SCORE; scored #EndIf; ; Object -> -> Keyring "keyring" with name 'keyring', description "It's just a plain metal ring really."; Object -> LeadWeight "lead weight" with name 'weight' 'lead', before [; Drop: remove self; move pencil to parent(player); PronounNotice(pencil); #IfDef OPTIONAL_MANUAL_SCOPE; scope_modified = true; #EndIf; "When the lead weight hits the ground it sounds different."; ] ; Object Pencil "pencil" with name 'pencil'; Object car "little red car" CarPark with name 'little' 'red' 'car', description "Large enough to sit inside. Among the controls is a prominent on/off switch. The numberplate is KAR 1.", describe [; @new_line; if(self has on) { "The red car sits here, its engine still running."; } else { "A little red car is parked here."; } ], !when_on "The red car sits here, its engine still running.", !when_off "A little red car is parked here.", before [; Go: if (car has on) "Brmm! Brmm!"; print "(The ignition is off at the moment.)^"; ], has switchable enterable static container open; Object RiverBank "River Bank" with description "The river is quite wide here. The sun reflects in the blue water, the birds are flying high up above.", d_to SecretHatch, w_to CarPark, nw_to Library, cheap_scenery 'blue' 'water' SCN_WATER 'bird' 'birds' "They seem so carefree." 1 'sun' SCN_SUN, has light; Object -> Microphone "microphone" with name 'microphone', orders [; "~Don't you boss me around!~ says the microphone."; ], before [; Ask: print "Before: Microphone - Ask^"; AskFor: print "Before: Microphone - AskFor^"; Answer: print "Before: Microphone - Answer^"; Tell: print "Before: Microphone - Tell^"; ], life [; Ask: "Life: Microphone - Ask"; AskFor: "Life: Microphone - AskFor"; Answer: "Life: Microphone - Answer"; Tell: "Life: Microphone - Tell"; ], has talkable; Object -> SecretHatch "secret hatch" with name 'secret' 'hatch', description "It's very secret.", after [; give self ~concealed; ], door_to Library, door_dir (d_to), has static concealed door openable; Object -> Lizard "cute little lizard" with name 'cute' 'little' 'lizard', description "It looks at you with big eyes.", after [; Take: "It dives into your breast pocket, spins around and peaks out, ready for adventure!"; Drop: print "He jumps up and bites your hand. You die."; @quit; ], has animate neuter; Object -> paper "paper" with name 'paper', describe "^There is a paper here."; Object -> paperclip "paperclip" with name 'paperclip' 'clip', describe "^There is a paperclip here."; Object Toilet "The toilet" with short_name [; print "A toilet"; rtrue; ], description[; print "This toilet is in dire need of cleaning. The toilet door leads west back into the library, and there's a dark doorway to the east. "; if(Faucet has on) { "Water is streaming from the faucet into the sink. "; } ""; ], #IfDef USEINFORM; w_to Library, #IfNot; w_to ToiletDoor, #EndIf; e_to DarkChamber, has ~light; Object -> ToiletDoor "toilet door" with name 'toilet' 'door', describe [; rtrue; ], ! parse_name [ _w; ! _w = NextWord(); ! if(_w == 'toilet') { ! _w = NextWord(); ! if(_w == 'door') ! return 2; ! return 0; ! } ! if(_w == 'door') ! return 1; ! ], description "Surprisingly clean.", when_open "The toilet door stands slightly ajar.", when_closed "The toilet door is closed.", #IfDef USEINFORM; door_to [; if(self in Toilet) return Library; return Toilet; ], door_dir [; if(self in Toilet) return w_to; return e_to; ], #IfNot; door_dir (w_to) (e_to), #EndIf; found_in Toilet Library, with_key [; if(second == Key or Sweater) return second;], #IfDef TEST_BEFOREAFTER; after [; print "*** ToiletDoor.after^"; ], before [; print "*** ToiletDoor.before^"; ], #EndIf; has door openable static lockable; Object -> Goblin "Goblin" with short_name "Goblin", description "He is a mean looking creature, not to be messed around with. ", name 'goblin' 'creature', before[; Attack: print "But he has a grim looking scimitar, and you are defenceless. Are you sure that's a good idea? "; if(YesOrNo()) { deadflag = 1; "You'd never believe that so much blood could be contained within this body. "; } else { "Wise call."; } rtrue; ], has animate; Object -> Sink "Sink" with short_name "sink", name 'sink' 'water', description[; print "It's a regular white sink with a faucet for turning water on or off."; if(Faucet has on) " There's water running into the sink from the faucet."; ""; ], has container static scenery; Object -> Faucet "faucet" with short_name "faucet", name 'faucet', description[; print "It's a faucet, possible to switch on/off. "; "It's currently ", (OnOff) self, "."; ], has switchable static scenery; Object DarkChamber "Dark Chamber" with description "It's almost entirely dark.", w_to Toilet; Object Library "The Library" with name 'library', ! should create "you don't need to refer to ..." short_name [; print "Huge library"; rtrue; ], description "You are in an old and deserted library. There is an exit leading south and a toilet to the east.", s_to CarPark, se_to RiverBank, #IfDef USEINFORM; e_to Toilet, #IfNot; e_to ToiletDoor, #EndIf; #IfDef TEST_BEFOREAFTER; after [; print "*** Library.after^"; ], before [; print "*** Library.before^"; ], #IfNot; before [; Look: if(self hasnt general) { give self general; !QuoteBox(quote_1); } ], #EndIf; has light; Object -> LightSwitch "LightSwitch" with short_name "light switch", description "It's a switch located near the toilet. ", name 'light' 'switch', before [; Push: if(self has on) <>; else <>; ], after[; SwitchOn: give toilet light; #IfnDef USEINFORM; ship_directions_enabled = true; "You flip the light switch next to the toilet upwards. You get a weird feeling that ship directions now work. "; #Endif; SwitchOff: give toilet ~light; #IfnDef USEINFORM; ship_directions_enabled = false; "You flip the light switch next to the toilet downwards. You get a weird feeling that ship directions no longer work."; #Endif; ], has switchable static; Object -> Sweater "sweater" with name 'sweater' 'red', with before [; Wear: if(PinkBook in player) "You don't put things on while holding the pink book. It might bring bad luck."; if(self has worn) rfalse; give self worn; "You put it on. The fit is perfect!"; ], has clothing; Object -> Aquarium "aquarium" with name 'aquarium', article "an", description "A big glass aquarium with a lid.", has container open openable transparent static enterable; Object -> LargeBox "The box" ! Set the object name to the name we want on the z3 status line when we're in the box. short_name will be used for all other cases. with short_name "box", name 'large' 'box', inside_description "The box looked pretty big from the outside, but you feel really confined in here.", description "It's a large box. You could probably fit several people in there.", time_out [; print "^The box goes BOOM.^"; ], before [; ! LetGo: ! "No can do!"; ], after [; LetGo: --score; "Yay, got rid of ", (the) noun, "!"; Open: #IfDef OPTIONAL_FULL_SCORE; Achieved(0); ! opening the box is an achievement #EndIf; Receive: ++score; ! win if you put two things in the box if(score >= MAX_SCORE) deadflag = 2; ], time_left 0, timer_order 50, has container openable enterable static; Book -> -> RedBook "red book" with name 'red' 'book', initial "On the bottom of the box, there is a red book.", description "The book is old and worn.", before [; Transfer: "NO WAY!"; Take, Remove: if(player in LargeBox) { "It's too hard to pick it up while inside the box."; } if(BlueBook in player) { print "The blue book does not want to be near the red book and jumps out of your grasp and lands on the floor.^^"; move BlueBook to location; } ]; Book -> -> BrownBook "brown book" with name 'brown' 'book', description "The book is beautiful.."; Object -> -> Gun "gun" with name 'gun', before [; Examine: rfalse; ! default: "It's very dangerous, better just leave it alone!"; ], has transparent; Object -> -> -> Trigger "trigger" with name 'trigger'; Object -> Shelf "shelf" with name 'shelf', capacity 1, has supporter enterable; Object -> -> Boots "boots" with name 'pair' 'of' 'boots', article "a pair of", has supporter enterable pluralname; Object -> Ladder "ladder" with name 'ladder', description [; print "It's very sturdy. "; ; ! if(_PrintContents(" (which contains ", p_obj)) print ")"; ], after [; Receive: "Wow, you put ",(a) noun," on ", (the) self, "..."; ], inside_description "It's a really good ladder for standing on.", has supporter enterable; Object -> -> Sticker "sticker" with name 'sticker', each_turn [; #IfnDef USEINFORM; ! if(location ~= thedark) "The sticker looks oh so sticky."; #Endif; ], add_to_scope Key, has reactive; Object -> BlueBook "blue book" class Book with name 'book' 'blue', time_left 0, initial [; !print "Self is ", self, ". "; !if(BlueBook provides hello && BlueBook.hello > 10) { ! print "BlueBook.Hello is ", BlueBook.hello, ". "; !} print "A "; PrintShortName(self); " is standing on a shelf. Looking at ", (the) self, " makes you dizzy."; ], before [; Turn: "You turn the book around and around. It is endlessly fun. "; ], after [; ! Drop: ! StopDaemon(Self); Take: if(RedBook in player) { print "The red book does not want to be near the blue book and jumps out of your grasp and lands on the floor.^^"; move RedBook to location; } ! StartDaemon(LargeBox); StartDaemon(self); self.time_left = turns; ! Remember which turn we started StartTimer(LargeBox, 3); print "The blue book starts ticking...^"; rtrue; ! stop normal printouts ], ! description "The book looks new and shiny.", daemon [; if(self.time_left < turns - 1) { if(TestScope(self)) print "^The blue book ticks loudly.^"; else print "^You hear a faint ticking in the distance.^"; } ], bobby 7, hello 13, timer_order 190, pants (-1000) (-1001) (-1002) (-1003) (-1004) (-1005) (-1006) (-1007) (-1008) (-1009) (-1010) (-1011) (-1012) (-1013) (-1014) (-1015) (-1016) (-1017) (-1018) (-1019) (-1020) (-1021) (-1022) (-1023) (-1024) (-1025) (-1026) (-1027) (-1028) (-1029) (-1030) (-1031), has light; ! well, it is glowing Object -> -> BlueBookTitle "title" with name 'title', description "The title of the blue book is ~War and peace~"; #Ifdef DEBUG; [ DebugLife rule; ! same output as the table in ! http://www.inform-fiction.org/manual/html/s18.html print "Rule ", (string) rule, ", action ", (DebugAction) action, ", noun "; if (noun == 0) print "0"; else if(noun <= top_object) print (the) noun; else print "'",(address) noun,"'"; print ", second "; if (second == 0) print "0"; else if(second > 0 && second <= top_object) print (the) second; else print "'",(address) second,"'"; if(consult_from > 0) print ", consult ", consult_from, " ", consult_words; print ", special_number ", special_number, "^"; ]; #Endif; Object -> John "John" with name 'john' 'johan', description "John is the meanest gangster around. Don't mess with him.", messed_with 0, ! add_to_scope Hair Beard, add_to_scope [; PlaceInScope(Hair); PlaceInScope(Beard); ], react_before [; Take: if(noun == GreenBook && IndirectlyContains(parent(John), GreenBook) ) { print_ret (The) John, " says, ~Oh no! That's mine!~"; } ], react_after [; Scan: if(noun == Paper) "John scoffs at your feeble attempt to scan the paper."; ], before[; Pull, Push: switch(++self.messed_with) { 1: "~I'm gonna make you regret that!~, John mutters. "; 2: "~This is your final warning!~, John says. "; 3: deadflag=1; "Oh dear, who would have guessed John was carrying a double barrelled gun with him to the library. "; } ], orders [; Go: "~I must not leave this room.~"; NotUnderstood: #IfDef DEBUG; DebugLife("trying john.orders.NotUnderstood"); #EndIf; rfalse; !print special_number, " ", special_word, " ", 'pink', " ", consult_from; !if(special_word == 0) "~You speak in riddles.~"; ], life [c w1 w2; ! Attack Kiss WakeOther ThrowAt Give Show Ask Tell Answer Order Order: #IfDef DEBUG; DebugLife("order"); #EndIf; if(action==##Take && noun==LargeBox) "~", (The) noun, " is too big.~"; if(action==##Take) "~I don't need more possessions.~"; if(action==##NotUnderstood) "~I don't understand what you say.~"; "John ignores your comment."; Show, Give: #IfDef DEBUG; DebugLife("life"); #EndIf; if(noun==PinkBook) <>; "John doesn't appear to be interested."; Ask, Tell, Answer: #IfDef DEBUG; DebugLife("life"); #EndIf; w1=0; w2=0; wn=consult_from; c=consult_words; if(c>0) w1=NextWord(); if(w1=='the') { c=c-1; if(c>0) w1=NextWord(); } if(c>1) w2=NextWord(); if(c>2) "What you cannot say in few words, probably isn't worth saying."; if(w1=='help') "'I will help you, if you tell me how.'"; if(second == 'pink') "~That is a nice pink book.~"; "John ignores your question."; ], has proper animate transparent reactive; Object -> -> JohnsBall "pink ball" with name 'pink' 'ball', has concealed; Object -> infiniteBag "infinite bag" with invent 0, name 'infinite' 'bag', article "an", has container open openable; Book -> GreenBook "green book" with ! name 'book' 'green', parse_name [ first_word; first_word = NextWord(); if(first_word == 'green') { if(NextWord() == 'book') return 2; return 1; } else if (first_word == 'pinkish') { parser_action = ##PluralFound; if(NextWord() == 'green') { if(NextWord() == 'book') return 3; return 2; } return 1; } else if (first_word == 'book' or 'books') { return 1; } return 0; ], describe [; "^An old and torn green book is here."; ], description "The green book is nice and tidy.", has reactive; Book -> PinkBook "pink book" with invent "that stupid old pink book", parse_name [ first_word; first_word = NextWord(); if(first_word == 'pink') { if(NextWord() == 'book') return 2; return 1; } else if (first_word == 'pinkish') { parser_action = ##PluralFound; if(NextWord() == 'book') return 2; return 1; } else if (first_word == 'book' or 'books') { return 1; } return 0; ], after [; Take: "You dared taking the pink book. Bravo!"; ], description "The pink book is nice and tidy.", has clothing reactive; Object -> Torch "electric torch" with name 'torch' 'electric' 'flashlight', article "an", invent [; if(inventory_stage == 2) { print " (Ugly as sin)"; rfalse; } ], ! description "A simple battery powered electric torch.", before [; Push: if(self has on) <>; else <>; ], after[; SwitchOn: give self light; #IfDef OPTIONAL_MANUAL_SCOPE; scope_modified = true; #EndIf; "The torch is now providing light."; SwitchOff: give self ~light; #IfDef OPTIONAL_MANUAL_SCOPE; scope_modified = true; #EndIf; "The torch is dark again."; ], has switchable; ! -- testing scope grammar token ! See: https://www.inform-fiction.org/manual/html/s32.html [ QueryTopic; switch (scope_stage) { 1: rfalse; 2: ScopeWithin(questions); rtrue; 3: "At the moment, even the simplest questions confuse you."; } ]; [ QuerySub; noun.description();]; Verb 'what' * 'is'/'was' scope=QueryTopic -> Query; Class MultiTopic with number 0, parse_name [ _w1 _w2 _i _sw1 _sw2 _len; _w1 = NextWordStopped(); _w2 = NextWordStopped(); _i = 0; _len = self.#topics / 2; #IfTrue RUNTIME_ERRORS > RTE_MINIMUM; #IfTrue RUNTIME_ERRORS == RTE_VERBOSE; if(_len % 3 > 0) "ERROR: multi_topic topics property of ", (the) self," has incorrect # of values!^"; #IfNot; if(_len % 3 > 0) "ERROR: multi_topic #1!^"; #EndIf; while(_i < _len) { _sw1 = self.&topics-->(_i+2); #IfTrue RUNTIME_ERRORS == RTE_VERBOSE; if(~~(_sw1 ofclass String or Routine)) "ERROR: Element ", _i+2, " in multi_topic topics property of ", (the) self," is not a string or routine!^", "Element: ", (name) _sw1, "^"; #IfNot; if(~~(_sw1 ofclass String or Routine)) "ERROR: multi_topic #2!^"; #EndIf; _i = _i + 3; } _i = 0; #endif; while(_i < _len) { _sw1 = self.&topics-->_i; _sw2 = self.&topics-->(_i+1); if(_w1 == _sw1 && _w2 == _sw2) { self.number = _i; return 2; } if(_w1 == _sw1 or _sw2) { self.number = _i; return 1; } _i = _i + 3; } ! It would make sense to return 0 here, but property ! routines return 0 by default anyway. ], description [ _k; _k = self.&topics-->(self.number + 2); if(_k ofclass Routine) { _k(); rtrue; } print_ret (string) _k; ], has reactive; Object questions "questions"; MultiTopic -> MultiQuestion_1 "MultiQuestion_1" with topics 'long' 'count' "The Long Count is the Great Mayan cycle of time, which began in 3114 BC and will finish with the world's end in 2012 AD." 1 'samarkand' "Samarkand is a nice city in south-eastern Uzbekistan."; ! Object -> "long count" ! with name 'long' 'count', ! description "The Long Count is the great Mayan cycle of ! time, which began in 3114 BC and will finish with ! the world's end in 2012 AD."; ! Object -> "samarkand" ! with name 'samarkand', ! description "Samarkand is a city in south-eastern Uzbekistan."; Object Hair "John's hair" with name 'hair' 'head', before [; Examine,Pull,Search: "John doesn't want to you to mess up his hair."; default: "Huh?"; ], has proper concealed; Object Beard "John's beard" with name 'beard', before [; Examine,Pull,Search: "You wouldn't dare to touch his beard."; default: "Huh?"; ], has proper concealed; !Array quote_1 --> 5 35 !"When I die, I want to go peacefully" !"in my sleep like my grandfather." !"Not screaming in terror, like the" !"passengers in his car." !" -- Jack Handey"; [Initialise; #IfnDef USEINFORM; ship_directions_enabled = false; #Endif; give player reactive; thedark.short_name = "Yucky darkness"; thedark.initial = "Oh, so scary."; thedark.description = "Now you are really scared."; SetTime(9*60+30, 5); ! 9:30 am, each turn 5 minutes #Ifdef USEINFORM; location = Library; #Endif; ! PlayerTo(LargeBox); ! print "Parrot fed = ", FlagIsSet(F_PARROT_FED),"^"; ! SetFlag(F_PARROT_FED); ! print "Have set. Parrot fed = ", FlagIsSet(F_PARROT_FED),"^"; ! ClearFlag(F_PARROT_FED); ! print "Have cleared. Parrot fed = ", FlagIsSet(F_PARROT_FED),"^"; ! print "Parrot fed != ", FlagIsClear(F_PARROT_FED),"^"; ! b = BlueBook.&pants; ! for(i=0 : ii, "^"; ! BlueBook.description(); ! print "BlueBook.party is ", BlueBook.party, "^"; ! BlueBook.party(5); move Gun to John; print "^^Welcome to the Testbench... This is where all sorts of PunyInform features are tried out. Don't expect much of a game here. Currently, you can win by putting stuff in the box, or lose by checking out the sun by the river or by pushing John around.^"; ]; #Ifdef USEINFORM; Include "Grammar"; #Endif; [NotHeld; if(noun in player) rfalse; ]; Extend 'remove' first * noun=NotHeld -> Take;