Update to serial 210501
[snowed-in.git] / src / snowed-in.inf
1 ! Copyright (C) 2021 Jason Self <j@jxself.org>
2 !
3 ! This file is free software: you may copy, redistribute and/or
4 ! modify it under the terms of the GNU Affero General Public License
5 ! as published by the Free Software Foundation, either version 3 of
6 ! the License, or (at your option) any later version.
7 !
8 ! This file is distributed in the hope that it will be useful, but
9 ! WITHOUT ANY WARRANTY; without even the implied warranty of
10 ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 ! Affero General Public License for more details.
12 !
13 ! You should have received a copy of the GNU Affero General Public
14 ! License along with this file. If not, see https://gnu.org/licenses/
15 Global lantern_fuel_left = 20;
16 Global body_temperature = 20;
17 Global cabin_has_electricity = 1;
18 Constant DEATH_MENTION_UNDO;
19 Constant Story "Snowed In";
20 Constant Headline 
21     "^A work of interactive fiction.
22     ^If you get stuck try typing HELP.
23     ^Ongoing development: https://jxself.org/git/?p=snowed-in.git
24     ^Send bugs and feedback by email to j@@64jxself.org.
25     ^IFID DE9FA2E5-4EC7-4166-9218-E56EFA1DF40F
26     ^Copyright (C) 2021 Jason Self
27     ^You can change and share this game under the terms of the GNU 
28     Affero General Public License as published by the Free Software 
29     Foundation (FSF), either version 3 of the License, or (at your 
30     option) any later version published by the FSF. See the GNU Affero 
31     General Public License for more details.^^You should have received 
32     a copy of this game's source code along with a copy of the GNU 
33     Affero General Public License so that you can know your rights. 
34     If not, contact the place you got it from.^^";
35 Include "parser";
36 Include "verblib";
37 Release 0;
38 Serial "210501";
39
40 Object  mainroom "Main Room"
41   with  description 
42             "This room is a total wreck - it looks like a major fight 
43             happened in here. There's a ripped up sofa and a broken 
44             old coffee table in the middle of the room. A flat-screen 
45             TV is mounted against the wall, with the screen dangling 
46             out. This cabin has three other rooms. There's an office 
47             area to the east, and a bedroom to the north. A 
48             kitchenette can be found to the west. There's a doorway 
49             in the south wall leading outside.",
50         n_to bedroom,
51         s_to frontdoor,
52         e_to office,
53         w_to kitchenette,
54   has   light;
55
56 Object  frontdoor "front door" mainroom
57   with  name 'door' 'front',
58         description 
59             "The wooden door is made of thick oak wood with the shape 
60             of a bear claw engraved in it.",
61         short_name [;
62             if (location == mainroom)
63                 print "door to the outside";
64             else
65                 print "door to the cabin";
66             return true;
67         ],
68         found_in mainroom southofcabin,
69         door_dir [;
70             if (location == mainroom)
71                 return s_to;
72             else
73                 return n_to;
74         ],
75         door_to [;
76             if (location == mainroom)
77                 return southofcabin;
78             else
79                 return mainroom;
80         ],
81   has   scenery door openable;
82
83 Object  bearclaw "bear claw" mainroom
84   with  name 'bear' 'claw',
85   with  description 
86             "It's in the shape of a thin, sharp claw with three jagged 
87             points at the top of it.",
88   has   scenery;
89
90 Object  sofa "sofa" mainroom
91   with  name 'sofa' 'couch',
92   with  description 
93             "The sofa is in poor shape. The upholstery is ripped and 
94             there are several holes in it.",
95         before [;
96           Take, Pull, Push, PushDir, Turn:
97             print_ret (The) self, " is too heavy for that.";
98         ],
99   has   scenery supporter enterable;
100
101 Object  coffeetable "coffee table" mainroom
102   with  name 'coffee' 'table',
103   with  description 
104             "The old coffee table looks as if it's had quite a bit of 
105             use. There are burn marks covering it and the paint is 
106             worn off in most places.",
107         before [;
108           Take, Pull, Push, PushDir, Turn:
109             print_ret (The) self, " is too heavy for that.";
110         ],
111   has   scenery supporter enterable;
112
113 Object  lantern "copper lantern" coffeetable
114   with  name 'lantern' 'copper' 'lamp',
115         description 
116             "This is an exceptionally beautiful lantern. About eleven 
117             inches high, with a base of about 5 inches or so in 
118             diameter and a large, brass-closed hook at the top. A 
119             rainbow of unique colors run through the copper. The 
120             glass in the lamp has a fresnel type of design, which is 
121             used to distribute light widely.",
122         time_left,
123         time_out [;
124             if (lantern has on) {
125                 lantern_fuel_left = 0;
126                 give lantern ~on;
127                 give lantern ~light;
128                 StopDaemon(lantern);
129                 print_ret 
130                     "Suddenly, the lantern's flame begins to flicker 
131                     violently within its glass prison and then 
132                     extinguishes itself.";
133             }
134         ],
135         before [;
136           SwitchOn:
137             if (lantern_fuel_left > 0) {
138                 give lantern light;
139                 StartTimer(lantern, lantern_fuel_left);
140             }
141             else {
142                 print_ret 
143                     "You snap the switch a few times, but nothing 
144                     happens.";
145             }
146           SwitchOff:
147             StopTimer(lantern);
148             give lantern ~light;
149         ],
150         daemon [;
151             if (lantern has on)
152                 lantern_fuel_left = lantern.time_left;
153             if (lantern has on && lantern_fuel_left <= 5)
154                 print_ret "The lantern's fuel runs low.";
155         ],
156   has   switchable;
157
158 Object  television "flat-screen TV" mainroom
159   with  name 'TV' 'television' 'flat' 'screen' 'flat-screen',
160   with  description 
161              "The flat-screen TV looks fairly modern but it's been 
162              broken in a fight and the screen is dangling out.",
163         before [;
164           Take, Pull, Push, PushDir, Turn:
165             print_ret (The) self, " is firmly mounted to the wall.";
166           SwitchOn:
167             if (television hasnt visited) {
168                 print 
169                     "Despite the significant damage, the television 
170                     comes to life in one last valiant attempt to be 
171                     useful. Your favorite news program is on: U.S. 
172                     News And Grue Report. The news anchor is giving a 
173                     warning of Grue sightings in the area of the 
174                     forest before the television finally dies.^";
175                 give television visited;
176             }
177             else {
178                 print 
179                     "The flat-screen TV is broken and can't be 
180                     turned on.^";
181             }
182             return true;
183         ],
184   has   scenery switchable;
185
186 Object  lightsocket "light socket" mainroom
187   with  name 'socket' 'lightsocket',
188         before [;
189           Take, Pull, Push, PushDir, Turn:
190             print_ret 
191                 "You don't have the tools to remove a light 
192                 socket.";
193           Receive:
194             if (noun ~= lightbulb) {
195                 print "Put ";
196                 print (a) noun;
197                 print_ret 
198                     " into the light socket? Maybe you should come 
199                     with a warning label because you contain more than 
200                     a trace amount of nut.";
201             }
202             if (noun == lightbulb && light has on) {
203                 give mainroom light;
204                 give office light;
205                 give kitchenette light;
206                 give bedroom light;
207                 give eastofcabin light;
208             }
209         ],
210   has   scenery container transparent open;
211
212 Object  lightbulb "light bulb" lightsocket
213   with  name 'light' 'bulb' 'lightbulb',
214         before [;
215           SwitchOn:
216             if (lightbulb in lightsocket) {
217                 if (cabin_has_electricity == 1) {
218                     give mainroom light;
219                     give office light;
220                     give kitchenette light;
221                     give bedroom light;
222                     give eastofcabin light;
223                 }
224                 else {
225                     print_ret 
226                         "You flip the switch a few times, but nothing 
227                         happens.";
228                 }
229             }
230             else {
231                 print_ret 
232                     "Turn on a lightbulb when it's not in the 
233                     socket? What a strange idea.";
234             }
235         ],
236         after [;
237           Take, Pull, Push, PushDir, Turn, SwitchOff:
238             give lightbulb ~on;
239             give mainroom ~light;
240             give office ~light;
241             give kitchenette ~light;
242             give bedroom ~light;
243             give eastofcabin ~light;
244         ],
245   has   switchable on;
246
247 Object  office "Office"
248   with  description 
249             "There seems to have been quite a fight in here. The room 
250             is a wreck. Holes are in the walls and the windows are 
251             broken, letting in the cold air from outside. Chunks of 
252             drywall and insulation cover the floor. The desk has a 
253             bullet hole through the middle.",
254         w_to mainroom,
255         e_to window,
256   has   light;
257
258 Object  desk "solid oak desk" office
259   with  name 'solid' 'oak' 'desk',
260   with  description 
261             "The desk is old and made of solid oak. The right side of 
262             it has been smashed and all of the drawers have been 
263             removed. A bullet hole goes straight through the middle of 
264             the desk.",
265         before [;
266           Take, Pull, Push, PushDir, Turn:
267             print_ret (The) self, " is too heavy for that.";
268         ],
269   has   scenery supporter enterable;
270
271 Object  businesscard "business card" desk
272   with  name 'business' 'card',
273   with  description 
274             "The business card is white and has blacked edges. It 
275             bears the name ~Lasting Solutions~, a local data recovery 
276             company, in bold letters on the top. The company's 
277             website URL is printed in blue at the bottom.";
278
279 Object  salesreceipt "sales receipt" desk
280   with  name 'sales' 'receipt',
281   with  description 
282             "The sales receipt is for $200, dated three years ago. 
283             It's printed on old tractor feed printer paper and bears 
284             the name ~Lasting Solutions~, a local data recovery 
285             company. A handwritten note is scrawled on the bottom: 
286             ~Start working on these hard drives soon.~";
287
288 Object  computer "computer" desk
289   with  name 'computer' 'PC',
290   with  description 
291             "It's a heavy older model that appears to have been 
292             seriously damaged in a fight. It's clearly on its last 
293             legs but is perhaps still useful.",
294         before [;
295           Take, Pull, Push, PushDir, Turn:
296             print_ret (The) self, " is too heavy for that.";
297           SwitchOn:
298             if (computer hasnt visited) {
299                 print 
300                     "The computer makes some concerning noises while 
301                     lights on the front also illuminate. The last 
302                     file is quickly displayed. ~If anyone else reads 
303                     this, you're in serious danger. I've been fighting 
304                     a ferocious grue for the last three days. I'm 
305                     almost out of supplies and can't last much 
306                     longer. I'm going to take the last of the supplies 
307                     and escape through the office window in a 
308                     last-ditch effort to get away and get back into 
309                     town. I hope I can make it.~ The computer then 
310                     makes a sickly sound and finally dies as some 
311                     smoke comes out of it.^";
312                 give computer visited;
313             }
314             else {
315                 print 
316                     "The display briefly flickers but nothing 
317                     else happens.^";
318             }
319             return true;
320         ],
321   has   switchable;
322
323 Object  drywall "drywall" office
324   with  name 'drywall' 'dry' 'wall',
325         before [;
326           Take, Pull, Push, PushDir, Turn:
327             print_ret "Taking that would achieve little.";
328         ],
329   has   scenery;
330
331 Object  insulation "insulation" office
332   with  name 'insulation',
333         before [;
334           Take, Pull, Push, PushDir, Turn:
335             print_ret "Taking that would achieve little.";
336         ],
337   has   scenery;
338
339 Object  bullethole "bullet hole" desk
340   with  name 'bullet' 'hole' 'holes',
341   with  description 
342             "Looks to have come from something that's capable of 
343             doing a lot of damage.",
344         found_in desk bedroom,
345   has   scenery;
346
347 Object  window "window" office
348   with  name 'window' 'windows',
349         description 
350             "The window faces the east side of the cabin. It's broken, 
351             letting in the cold air from outside.",
352         short_name [;
353             if (location == office)
354                 print "window";
355             else
356                 print "window into the cabin";
357             return true;
358         ],
359         found_in office eastofcabin,
360         door_dir [;
361             if (location == office)
362                 return e_to;
363             else
364                 return w_to;
365         ],
366         door_to [;
367             if (location == office)
368                 return eastofcabin;
369             else
370                 return office;
371         ],
372         before [;
373           Search:
374             print_ret "The window faces the east side of the cabin.";
375           Open, Close:
376             print_ret 
377                 "The window's broken so it's not clear how 
378                 you'd do that.";
379         ],
380   has   scenery door openable open;
381
382 Object  kitchenette "Kitchenette"
383   with  description 
384             "The kitchenette is empty. A sink, you think, though it's 
385             hard to tell what's a pipe and what's a faucet. A 
386             refrigerator, standing open and empty. The door has been 
387             ripped off. There's no indication as to where it 
388             went. There's no food anywhere in here.",
389         e_to mainroom,
390   has   light;
391
392 Object  refrigerator "refrigerator" kitchenette
393   with  name 'fridge' 'refrigerator',
394   with  description 
395             "An old rusty refrigerator, standing open and empty. The 
396             door has been ripped off. There's no indication as to 
397             where it went.",
398         before [;
399           Take, Pull, Push, PushDir, Turn:
400             print_ret (The) self, " is too heavy for that.";
401           Open, Close:
402             print_ret (The) self, " door is missing.";
403         ],
404   has   scenery enterable container openable open;
405
406 Object  sink "sink" kitchenette
407   with  name 'sink' 'pipe' 'faucet',
408   with  description 
409             "A sink, you think, though it's hard to tell what's a 
410             pipe and what's a faucet.",
411         after [;
412           SwitchOn:
413             print_ret 
414                 "Pipes from in the walls make a groaning sound, 
415                 almost like pain and despair. No water comes out.";
416         ],
417   has   scenery container switchable;
418
419 Object  bedroom "Bedroom"
420   with  description 
421             "This bedroom is small and cramped, and looks like a 
422             major fight happened as the exterior wall has bullet 
423             holes. The bed is lying on the floor, torn to shreds. It 
424             has no sheets, just a bare mattress.",
425         s_to mainroom,
426   has   light;
427
428 Object  bed "bed" bedroom
429   with  name 'bed' 'mattress',
430   with  description "The mattress is bare and empty.",
431         before [;
432           Take, Pull, Push, PushDir, Turn:
433             print_ret (The) self, " is too heavy for that.";
434         ],
435   has   scenery supporter;
436
437 Object  suitcase "suitcase" bedroom
438   with  name 'suitcase',
439   with  description 
440             "The suitcase is made of a light metallic material that 
441             you can't quite make out. The color of it is somewhere 
442             between silver and grey.",
443   has   container open openable;
444
445 Object  snowsuit "snowsuit" suitcase
446   with  name 'snowsuit' 'snow' 'suit',
447   with  description 
448             "The snowsuit is blue, decorated with white and purple 
449             designs. On the chest is a large emblem with the letters 
450             ~CE~ in purple.",
451         before [;
452           Wear:
453             if (snowshoes in player && snowshoes has worn) {
454                 print_ret "The snowsuit can't fit over the snowshoes.";
455             }
456           Disrobe, Remove:
457             if (snowshoes in player && snowshoes has worn) {
458                 print_ret "The snowsuit can't be taken off over the snowshoes.";
459             }
460         ],
461         daemon [;
462             if (location ~= mainroom && location ~= office && location ~=
463             kitchenette && location ~= bedroom && location ~= thedark &&
464             snowsuit hasnt worn) {
465                 body_temperature = --body_temperature;
466                 print body_temperature;
467             }
468             if (location == mainroom || location == office || location ==
469             kitchenette || location == bedroom || location ~= thedark ||
470             snowsuit has worn && body_temperature < 20) {
471                 body_temperature = ++body_temperature;
472             }
473             if (body_temperature == 0) {
474                 deadflag = 4;
475             }
476             if (body_temperature <= 5)
477                 print_ret 
478                     "You're shivering uncontrollably, and it's hard 
479                     to move. You feel very exhausted and drowsy. It's 
480                     all you can do to keep from falling over.";
481             if (body_temperature > 5 && location ~= mainroom && location
482             ~= office && location ~= kitchenette && location ~= bedroom
483             && location ~= thedark && snowsuit hasnt worn) {
484                 switch (body_temperature) {
485                   19:
486                     "The feeling of cold overwhelms you. Surely the cold will get to 
487                     you before anything else does. Right?";
488                   18:
489                     "You can feel yourself getting colder and colder.";
490                   17:
491                     "You can see your own breath freezing in the air, forming little 
492                     clouds.";
493                   16:
494                     "You shiver in the cold.";
495                   15:
496                     "You continue to shiver in the cold.";
497                   14:
498                     "Your hands grow numb from the cold.";
499                   13:
500                     "You continue shivering in order to keep warm.";
501                   12:
502                     "Your shivering grows worse as your body becomes colder by the
503                     minute.";
504                   11:
505                     "Your teeth begin to chatter as you desperately try to warm 
506                     yourself up.";
507                   10:
508                     "Your shivering intensifies as your body begins to freeze over 
509                     from the cold.";
510                   9:
511                     "Your fingers become stiff and you feel sharp pains all over your
512                     body.";
513                   8:
514                     "The cold has gotten to a point where it is too much for you. You 
515                     begin to shiver uncontrollably.";
516                   7:
517                     "Your eyesight begins to fade and you can't even feel yourself 
518                     shivering anymore.";
519                   6:
520                     "You can feel your body shutting down from the cold as you slowly 
521                     begin to lose consciousness.";
522                 }
523             }
524         ],
525   has   clothing;
526
527 Object  snowshoes "snowshoes" bedroom
528   with  name 'snowshoe' 'snowshoes' 'snow' 'boot' 'boots' 'shoe' 'shoes'
529         'metal' 'frame',
530   with  description 
531             "They're light blue in color and have a thick, hard 
532             rubber bottom that's attached to a metal frame that keeps 
533             you from sinking into the snow. They look to be warm and 
534             comfortable.",
535         after [;
536           Wear:
537             print_ret (The) self, 
538                 " fit perfectly and go up to your 
539                 knees.";
540         ],
541         daemon [;
542             if (location ~= mainroom && location ~= office && location ~=
543             kitchenette && location ~= bedroom && location ~= thedark &&
544             snowshoes hasnt worn) {
545                 deadflag = 3;
546             }
547         ],
548   has   pluralname clothing;
549
550 Object  southofcabin "South Of Cabin"
551   with  description [;
552             print "The wind is howling, and there's snow flying everywhere.";
553             if (snowsuit hasnt worn)
554                 print 
555                     " It's really cold and 
556                     you're not dressed for this weather.";
557             print 
558                 " The snow stings your face and you 
559                 can barely see three feet in front of you.^";
560         ],
561         n_to frontdoor,
562         e_to eastofcabin,
563   has   light;
564
565 Object  eastofcabin "East Of Cabin"
566   with  description [;
567             print "It's dark outside. ";
568             if (lightbulb has on) {
569                 print 
570                     "The light from inside the cabin only penetrates 
571                     a few feet from the building. ";
572             }
573             else
574                 if (lantern in player && lantern has on) {
575                     print 
576                         "The lantern provides the only source of 
577                         light. ";
578                 }
579             if (snowshoes in player && snowshoes has worn) {
580                 print 
581                     "The snowshoes are doing their job by making sure 
582                     you don't sink into the snow.^";
583             }
584         ],
585         w_to window,
586         s_to southofcabin,
587   has   light;
588
589 [ Initialise;
590     Location = mainroom;
591     thedark.description = 
592         "It is pitch black. You are likely to be eaten 
593         by a grue.";
594     print 
595         "You're trapped in a snowstorm while visiting the forest 
596         during your vacation to a small rural town. This is the worst 
597         snowstorm in more than 40 years. If only you has listened to 
598         the news. Well, it's too late for that. The snow has been 
599         falling for the past seven hours and shows no signs of 
600         stopping anytime soon. You need to get back to your hotel in 
601         the town. You finally manage to find an old cabin in the 
602         woods and get inside but have no idea where you are. You're 
603         not dressed for this weather.^";
604     StartDaemon(lantern);
605     StartDaemon(snowshoes);
606     StartDaemon(snowsuit);
607     StartDaemon(grue);
608 ];
609
610 [ DeathMessage;
611     if (deadflag == 3)
612         print "You sink into the deep snow and are unable to move.";
613     if (deadflag == 4)
614         print 
615             "Finally, you succumb to the cold. Your mind goes blank as 
616             you slip away into the endless darkness and the deep sleep 
617             of death.";
618 ];
619
620 ! Don't have 'take all' take the lightbulb in the mainroom of the 
621 ! cabin
622
623 [ ChooseObjects obj code;
624     if (code < 2) {
625         if (obj has scenery)
626             return 2;
627         rfalse;
628     }
629     if (obj == lightbulb)
630         return 0;
631 ];
632
633 [ InScope;
634     if (location == thedark && real_location == mainroom) {
635         PlaceInScope(lightsocket);
636         PlaceInScope(lightbulb);
637     }
638     return false;
639 ];
640
641 Object  grue "grue" thedark
642   with  article "the",
643         name 'grue' 'monster',
644         grue_active_around_cabin,
645         grue_active_in_the_dark,
646         daemon [;
647             if (location == thedark) {
648                 switch (++(self.grue_active_in_the_dark)) {
649                   1:
650                     "^You hear horrible gurgling sounds in the dark.";
651                   2:
652                     "^You hear the clink of razor-sharp claws nearby.";
653                   3:
654                     deadflag = 1;
655                     "^Your last memory is of the slavering fangs of the 
656                     horrible Grue as it claims you for a meal.";
657                 }
658             }
659             if (location == mainroom || location == office || location ==
660             kitchenette || location == bedroom) {
661                 switch (++(self.grue_active_around_cabin)) {
662                   1:
663                     "^You hear the wind howling outside, if it is the wind.";
664                   2:
665                     "^You hear horrible gurgling sounds outside.";
666                   3:
667                     "^The noise outside gets louder.";
668                   4:
669                     "^You hear the sound of shuffling feet outside.";
670                   5:
671                     "^You hear a deep guttural sound from outside that sends a chill down your spine.";
672                   6:
673                     "^You hear something sniffing around the cabin.";
674                   7:
675                     "^You hear something scratching on the cabin walls from outside.";
676                   8:
677                     "^You hear something howl outside. It's a chilling, mournful wail that sends a chill down your spine.";
678                   9:
679                     "^A thunderous CRACK can be heard coming from outside.";
680                   10:
681                     "^There's a sudden crashing sound as something is thrown against the cabin walls.";
682                   11:
683                     "^Something begins to beat against the walls of the cabin, as if trying to to break in. It makes a loud, thunderous noise.";
684                   12:
685                     "^The wind is howling and the walls are being beaten so hard it feels like the cabin is shaking.";
686                   13:
687                     "^Suddenly, there's ominous silence from outside the cabin.";
688                 }
689             }
690             if (location == mainroom || location == office || location ==
691             kitchenette || location == bedroom && self.grue_active_around_cabin
692             == 15) {
693                 print "^The lights flicker and suddenly go out.";
694                 cabin_has_electricity = 0;
695                 give lightbulb ~on;
696                 give mainroom ~light;
697                 give office ~light;
698                 give kitchenette ~light;
699                 give bedroom ~light;
700                 give eastofcabin ~light;
701             }
702             return true;
703         ],
704   has   scenery;
705
706 [ DarkToDark;
707     deadflag = 1;
708     "Oh, no! You have walked into the slavering fangs of a lurking 
709     grue!";
710 ];
711
712 [ URL;
713     print 
714         "^If you need help try some of the commands from: 
715         ^http://pr-if.org/doc/play-if-card/^";
716 ];
717
718 [ XyzzySub;
719     print "Nothing obvious happens.^";
720     return true;
721 ];
722
723 [ HelpSub;
724     URL();
725     return true;
726 ];
727
728 Include "grammar";
729
730 Verb 'About'
731     * -> Version;
732
733 Verb 'Info'
734     * -> Version;
735
736 Verb 'Help'
737     * -> Help;
738
739 Verb 'Clue'
740     * -> Help;
741
742 Verb 'Hint'
743     * -> Help;
744
745 Verb 'xyzzy'
746     * -> Xyzzy;
747
748 Verb 'crawl'
749     * 'through' / 'out' / 'via' noun -> Go;
750
751 Verb 'escape'
752     * 'through' / 'out' / 'via' noun -> Go;
753
754 Extend 'jump'
755     * 'through' / 'out' / 'via' noun -> Go;
756
757 Extend 'climb'
758     * 'through' / 'out' / 'via' noun -> Go;
759
760 Extend 'go'
761     * 'through' / 'out' / 'via' noun -> Go;