! Through the Looking-Glass ! An Inform tutorial by Gareth Rees ! All rights given away ! Version 3 Switches v5; Constant DEBUG; Constant Story "THROUGH THE LOOKING GLASS"; Constant Headline "^An Interactive Tutorial^by Gareth Rees^"; Include "parser"; Include "verblib"; Include "grammar"; [ Initialise; location = Drawing_Room; StartDaemon(white_kitten); StartDaemon(black_kitten); print "^^^^^It's a cold winter day outside, but in the \ looking-glass house it's summer. All you need to do is \ pretend there's a way of getting through into it \ somehow...^^"; ]; [ UntangleSub; "What curious ideas you have!"; ]; [ ReflectSub; if (second ~= mirror) "What a strange idea!"; if (noun == hearth or mirror || (player notin mantelpiece && player notin armchair)) "You can't see that in the looking-glass."; print "The looking-glass "; if (noun == player) print "Alice"; else PrintShortName(noun); if (player in mantelpiece) " looks very misty and blurred."; print " looks just like the real "; if (noun == player) print "Alice"; else PrintShortName(noun); " only all reversed, left for right."; ]; Extend "look" * "at" noun "in" noun -> Reflect; Extend "examine" * noun "in" noun -> Reflect; Verb "roll" "untangle" "wind" * noun -> Untangle * "up" noun -> Untangle * noun "up" -> Untangle; Object Drawing_Room "Drawing room" has light with name "snow", description "The gentle sound of snow against the window pane \ suggests that it's cold outside, and you're glad to be \ here in the warmth. The drawing-room is reflected in the \ large looking-glass on the wall above the mantelpiece, \ and a very comfortable room it is too, with a warm \ hearth, a soft rug and an arm-chair that you can curl up \ and sleep in.", before [; if (player in mantelpiece && (action == ##Exit || (action == ##Go && noun == d_obj or out_obj))) "That's not the way to get down from a mantelpiece!"; if (player in mantelpiece && action ~= ##Examine or ##Enter or ##Go && action ~= ##ThrownAt or ##ThrowAt or ##Reflect) if ((noun > 0 && noun notin mantelpiece && noun ~= mantelpiece or mirror && noun notin player) || (second > 0 && second notin mantelpiece && second ~= mantelpiece or mirror && second notin player)) "Not from up here you can't!"; ]; Object red_queen "red queen" has female with name "red" "queen", describe [; if (white_kitten.state == 1 || black_kitten.state == 1) rtrue; ], description "She's a fierce little chess piece.", after [; Take: if (white_kitten.state == 1) white_kitten.state = 3; if (black_kitten.state == 1) black_kitten.state = 3; PutOn,Transfer,Insert: if (second == chess_board) "Alone on the chess board, the red queen is monarch of \ all she surveys."; ]; Object chess_board "chess board" Drawing_Room has supporter with name "chess" "board" "checker" "chequer" "chessboard", initial "An abandoned chess board lies on the floor.", description "It's left here from the game you were playing \ just now, but the pieces are all missing - the kittens \ will insist on playing with them."; Object hearth "hearth" Drawing_Room has scenery with name "hearth" "fire" "place" "fireplace"; Object rug "rug" Drawing_Room has concealed static supporter enterable ! general if you've found the red queen under it with name "hearthrug" "hearth-rug" "rug" "indian" "arabian" "beautiful" "soft", description "It's a beautiful rug, made in some far off \ country, perhaps India or Araby, wherever those might \ be.", before [; Take: "The rug is much too large and heavy for you to carry."; Push,Pull: "But a hearth-rug is meant to be next to the \ hearth!"; LookUnder: if (player in mantelpiece || player in armchair) "You're unable to reach the rug from here."; if (player in self) "You try to lift up a corner of the rug, but fail. After \ a while, you realise that this is because you are \ standing on it. How curious the world is!"; if (self hasnt general) { give self general; move red_queen to player; "You lift up a corner of the rug and, peering \ underneath, discover the red queen from the chess \ set."; } ]; Object armchair "arm-chair" Drawing_Room has static concealed supporter enterable ! general if its by the mantelpiece with name "arm" "chair" "armchair" "arm-chair", description [; print "It's a huge arm-chair, the perfect place for a kitten \ or a little girl to curl up in and doze. It has been \ pushed over to the "; if (self has general) "fireplace."; "window."; ], before [ i; Push,Pull: if (player notin Drawing_Room) print_ret "You'll have to get off ", (the) parent(player), " first."; if (white_kitten in player || black_kitten in player) "Not with a kitten in your arms!"; if (white_kitten.state == 3) i = white_kitten; else if (black_kitten.state == 3) i = black_kitten; if (i ~= 0) print_ret "You are about to start moving the chair when you \ notice that ", (the) i, " is right in the way. It's a \ good thing you spotted it, or you would have squashed \ flat the poor little thing."; if (self has general) { give self ~general; "You push the arm-chair away from the hearth."; } give self general; "You push the arm-chair over to the hearth."; Climb,Enter: move player to armchair; "You jump into the warm and comfortable arm-chair."; ]; Object mantelpiece "mantelpiece" Drawing_Room has concealed supporter enterable with name "mantel" "mantelpiece", description "It's higher off the ground than your head, but \ it looks wide enough and sturdy enough to support you.", before [; Enter,Climb: if (player notin armchair) "The mantelpiece is much too high to climb up onto."; if (armchair hasnt general) "You can't reach the mantelpiece from here."; if (children(player) > 0) "Your hands are too full."; move player to mantelpiece; "You scramble up onto the mantelpiece."; PutOn,LetGo: if (player notin self && (player notin armchair || armchair hasnt general)) "The mantelpiece is so high that you can't reach."; ]; Object mirror "looking-glass" Drawing_Room has static concealed with name "mirror" "looking" "glass" "looking-glass", description [; if (player in mantelpiece) "Strangely, the glass is beginning to melt away, \ just like a bright silvery mist."; if (player in armchair) "In the looking-glass you can see the drawing-room of \ the looking-glass house. What you can see is very \ much the same as this drawing-room, only all \ reversed, left for right. But you are sure that out \ of the corners of the glass, where you can't see, the \ looking-glass world is quite different from yours."; "In the looking-glass you can see the ceiling of the \ drawing-room of the looking-glass house. It looks much \ the same as the ceiling of your drawing-room."; ], before [; if (action ~= ##Examine or ##ThrownAt or ##Reflect && player notin mantelpiece) "You can't reach the looking-glass from where you're \ standing."; Touch,Pull,Push: "Your hand goes right through the silvery mist!"; ThrownAt: "You don't want seven years' bad luck, do you?"; Enter: ! Really, move Alice to the looking-glass house. deadflag = 2; "Your hand goes right through the silvery mist, and in \ another moment the rest of you follows, and you are \ through the glass..."; ]; Object worsted "ball of worsted" Drawing_Room ! general if its in a tangle with name "ball" "of" "worsted" "fine" "blue" "wool", describe [; if (white_kitten.state ~= 2 && black_kitten.state ~= 2) "^A discarded ball of worsted lies on the floor here."; rtrue; ], description [; if (self has general) "It's in a terrible tangle. All that time you spent \ rolling it up, and now look at it!"; "It's a ball of fine blue wool, all rolled up in preparation \ for some embroidery."; ], before [; Untangle: give self ~general; "You're as quick as can be at rolling up balls of wool, \ though you say so yourself! Soon it's neat and tidy again."; ], after [; Take: if (white_kitten.state == 2) white_kitten.state = 3; if (black_kitten.state == 2) black_kitten.state = 3; ]; Object chess_pieces "chess pieces" Drawing_Room has scenery with parse_name [ w colour n; w = NextWord(); if (w == 'white' or 'red') { n ++; colour = w; w = NextWord(); } if (w == 'pawn' or 'rook' or 'castle' || w == 'knight' or 'horse' or 'bishop' || w == 'king' || (w == 'queen' && (colour == 'white' || rug hasnt general))) return n + 1; return 0; ], before [; "Alas, that chess piece seems to be missing. Those \ naughty kittens!"; ]; Object window "window" Drawing_Room has scenery with name "window" "pane", description "Outside the window it's snowing gently, and you're \ glad to be in here in the warmth.", before [; Open: "You wouldn't want to catch a chill, would you? Better \ leave the window shut."; Search: <>; ]; Property other_kitten; Property state; ! 1=red queen, 2=ball of wool, 3=arm-chair, 0=held Class Kitten_Class has animate ! general if it's been described this turn with parse_name [ w ok n; do { ok = 0; w = NextWord(); if (w == 'kittens' or 'cats') { ok = 1; n++; parser_action=##PluralFound; } if (w == 'kitten' or 'kitty' or 'cat' || w == ((self.&name)-->0)) { ok = 1; n++; } } until (ok == 0); return n; ], state 3, describe [ i; switch (self.state) { 1: print_ret "^A ", (name) self, " is playing with the red \ queen."; 2: print_ret "^A ", (name) self, " is playing with a ball of \ worsted."; 3: if (self has general) rtrue; if ((self.other_kitten).state == 3) { i = self.other_kitten; give i general; "^Two kittens, one white and one black, are playing \ together by the arm-chair."; } print_ret "^A ", (name) self, " is playing by the \ arm-chair."; default: rtrue; } ], description [; print_ret "What a beautiful kitten ", (the) self, " is. Why, \ it's quite definitely your favourite of the pair, and \ much prettier than that naughty ", (name) self.other_kitten, "."; ], life [; Ask,Answer,Order: print_ret (The) self, " twitches its whiskers and looks at \ you with such a clever expression that you are certain it \ understands every word you are saying."; Kiss: print_ret "You give ", (the) self, " a little kiss on its \ nose, and it looks sweetly and demurely at you."; Attack: "You would never do such a beastly thing to such \ a defenceless little animal!"; Show: print_ret (The) self, " bats a paw at ", (the) noun, "."; Give,ThrowAt: if (noun ~= red_queen or worsted) { if (action == ##ThrowAt) { move noun to Drawing_Room; print "You toss ", (the) noun, " onto the floor, but ", (the) self; } else print (The) self, print_ret " just examines ", (the) noun, " with a \ quizzical expression."; } print "You toss ", (the) noun, " onto the floor and ", (the) self; if (self in player) print " squirms out of your grasp and"; move noun to Drawing_Room; move self to Drawing_Room; print " scampers after it"; if (noun == worsted) { give worsted general; self.state = 2; print ", quickly turning the neat ball into a tangle"; } else self.state = 1; "."; ], before [; Take: if (self.other_kitten in player) "You can't hold two kittens at once!"; self.state = 0; move self to player; print_ret "You pick up ", (the) self, ". What a beautiful \ creature it is!"; ], after [; Drop: self.state = 3; move self to Drawing_Room; print_ret (The) self, " squirms out of your arms and scampers \ away."; Transfer,PutOn,Insert: self.state = 3; print (The) self, " jumps off ", (the) parent(self); move self to Drawing_Room; ", landing lightly on the floor before scampering away."; ], daemon [ i; give self ~general; self.number = 1 - self.number; if (self.number == 1 || random(3) == 2) rtrue; new_line; print (The) self; switch (self.state) { 0: switch(random(5)) { 1: " mews plaintively."; 2: " purrs quietly to itself."; 3: " purrs contentedly to itself."; 4: " rubs its ears against you."; 5: move self to Drawing_Room; self.state = 3; " squirms out of your arms and scampers away."; } 1: switch (random(5)) { 1: " bats at the red queen with its paw."; 2: " stops playing and sits up, pretending to be \ innocent of any kittenish tendancies."; 3: " knocks the red queen across the floor and chases \ after it."; 4: " stops to wash itself."; 5: " bites the red queen and shakes it to make sure that \ it's dead."; } 2: give worsted general; switch (random(5)) { 1: " bats at the ball of worsted with its paw."; 2: " pushes the ball of worsted across the floor and \ chases after it."; 3: " leaps onto the ball of worsted and grapples bravely \ with it."; 4: " jumps into the ball of worsted and gets tangled up \ in a mess of threads."; 5: " stops playing and scratches its ears."; } 3: if ((self.other_kitten).state == 3 && random(2) == 1) { i = random(5); switch (i) { 1: print " chases after "; 2: print " jumps on top of "; 3: print " washes "; 4: print " scampers around the arm-chair and "; 5: print " bats at "; } print (the) self.other_kitten; switch (i) { 1,3: "."; 2: " and they roll around on the floor."; 4: " chases after it."; 5: " with its paw."; } } switch (random(5)) { 1: " scampers after a speck of dust."; 2: " rolls around on the floor."; 3: " sits up and washes its tail."; 4: " scratches its head on the arm-chair."; 5: " chases its tail."; } } ]; Object white_kitten "white kitten" Drawing_Room class Kitten_Class with name "white", number 0, other_kitten black_kitten; Object black_kitten "black kitten" Drawing_Room class Kitten_Class with name "black", number 1, other_kitten white_kitten; End;