! 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.";
];
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: <<Examine self>>;
];
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;