Update to serial 210405
[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 Constant DEATH_MENTION_UNDO;
17 Constant Story "Snowed In";
18 Constant Headline 
19     "^A work of interactive fiction.
20     ^If you get stuck try typing HELP.
21     ^Ongoing development: https://jxself.org/git/?p=snowed-in.git
22     ^Send bugs and feedback by email to j@@64jxself.org.
23     ^IFID DE9FA2E5-4EC7-4166-9218-E56EFA1DF40F
24     ^Copyright (C) 2021 Jason Self
25     ^You can change and share this game under the terms of the GNU 
26     Affero General Public License as published by the Free Software 
27     Foundation (FSF), either version 3 of the License, or (at your 
28     option) any later version published by the FSF. See the GNU Affero 
29     General Public License for more details.^^You should have received 
30     a copy of this game's source code along with a copy of the GNU 
31     Affero General Public License so that you can know your rights. 
32     If not, contact the place you got it from.^^";
33 Include "parser";
34 Include "verblib";
35 Release 0;
36 Serial "210405";
37
38 Object  mainroom "Main Room"
39   with  description 
40             "This room is a total wreck - it looks like a major fight 
41             happened in here. There's a ripped up sofa and a broken 
42             old coffee table in the middle of the room. A flat-screen 
43             TV is mounted against the wall, with the screen dangling 
44             out. This cabin has three other rooms. There's an office 
45             area to the east, and a bedroom to the north. A 
46             kitchenette can be found to the west. There's a doorway 
47             in the south wall leading outside.",
48         n_to bedroom,
49         e_to office,
50         w_to kitchenette,
51   has   light;
52
53 Object  sofa "sofa" mainroom
54   with  name 'sofa' 'couch',
55   with  description 
56             "The sofa is in poor shape. The upholstery is ripped and 
57             there are several holes in it.",
58         before [;
59           Take, Pull, Push, PushDir, Turn:
60             print_ret (The) self, " is too heavy for that.";
61         ],
62   has   scenery supporter enterable;
63
64 Object  coffeetable "coffee table" mainroom
65   with  name 'coffee' 'table',
66   with  description 
67             "The old coffee table looks as if it's had quite a bit 
68             of use. There are burn marks covering it and the paint is 
69             worn off in most places.",
70         before [;
71           Take, Pull, Push, PushDir, Turn:
72             print_ret (The) self, " is too heavy for that.";
73         ],
74   has   scenery supporter enterable;
75
76 Object  lantern "copper lantern" coffeetable
77   with  name 'lantern' 'copper' 'lamp',
78         description 
79             "This is an exceptionally beautiful lamp. About eleven 
80             inches high, with a base of about 5 inches or so in 
81             diameter and a large, brass-closed hook at the top. The 
82             glass in the lamp has a fresnel type of design, which is 
83             used to distribute light widely.",
84         time_left,
85         time_out [;
86             if (lantern has on) {
87                 lantern_fuel_left = 0;
88                 give lantern ~on;
89                 give lantern ~light;
90                 StopDaemon(lantern);
91                 print_ret 
92                     "The lantern has run out of fuel and is now 
93                     off.";
94             }
95         ],
96         before [;
97           SwitchOn:
98             if (lantern_fuel_left > 0) {
99                 give lantern light;
100                 StartTimer(lantern, lantern_fuel_left);
101             }
102             else {
103                 print_ret 
104                     "The lantern is out of fuel and cannot be turned 
105                     on.";
106             }
107           SwitchOff:
108             StopTimer(lantern);
109             give lantern ~light;
110         ],
111         daemon [;
112             if (lantern has on)
113                 lantern_fuel_left = lantern.time_left;
114             if (lantern has on && lantern_fuel_left <= 5)
115                 print_ret "The lantern's fuel runs low.";
116         ],
117   has   switchable;
118
119 Object  television "flat-screen TV" mainroom
120   with  name 'TV' 'television' 'flat' 'screen' 'flat-screen',
121   with  description 
122             "The flat-screen TV looks fairly modern but it's 
123             been broken in a fight and the screen is dangling out.",
124         before [;
125           Take, Pull, Push, PushDir, Turn:
126             print_ret (The) self, " is firmly mounted to the wall.";
127           SwitchOn:
128             if (television hasnt visited) {
129                 print 
130                     "Despite the significant damage, the television 
131                     comes to life in one last valiant attempt to be 
132                     useful. Your favorite news program is on: U.S. 
133                     News And Grue Report. The news anchor is giving a 
134                     warning of Grue sightings in the area of the 
135                     forest before the television finally dies.^";
136                 give television visited;
137             }
138             else {
139                 print 
140                     "The flat-screen TV is broken and can't be 
141                     turned on.^";
142             }
143             return true;
144         ],
145   has   scenery switchable;
146
147 Object  lightsocket "light socket" mainroom
148   with  name 'socket' 'lightsocket',
149         before [;
150           Take, Pull, Push, PushDir, Turn:
151             print_ret 
152                 "You don't have the tools to remove a light 
153                 socket.";
154           Receive:
155             if (noun ~= lightbulb) {
156                 print "Put ";
157                 print (a) noun;
158                 print_ret 
159                     " into the light socket? Maybe you should come with a
160                     warning label because you contain more than a trace
161                     amount of nut.";
162             }
163             if (noun == lightbulb && light has on) {
164                 give mainroom light;
165                 give office light;
166                 give kitchenette light;
167                 give bedroom light;
168                 give eastofcabin light;
169             }
170         ],
171   has   scenery container transparent open;
172
173 Object  lightbulb "light bulb" lightsocket
174   with  name 'light' 'bulb' 'lightbulb',
175         before [;
176           SwitchOn:
177             if (lightbulb in lightsocket) {
178                 give mainroom light;
179                 give office light;
180                 give kitchenette light;
181                 give bedroom light;
182                 give eastofcabin light;
183             }
184             else {
185                 print_ret 
186                     "Turn on a lightbulb when it's not in the 
187                     socket? What a strange idea.";
188             }
189         ],
190         after [;
191           Take, Pull, Push, PushDir, Turn, SwitchOff:
192             give lightbulb ~on;
193             give mainroom ~light;
194             give office ~light;
195             give kitchenette ~light;
196             give bedroom ~light;
197             give eastofcabin ~light;
198         ],
199   has   switchable on;
200
201 Object  office "Office"
202   with  description 
203             "There seems to have been quite a fight in here. The room 
204             is a wreck. Holes are in the walls and the windows are 
205             broken, letting in the cold air from outside. Chunks of 
206             drywall and insulation cover the floor. The desk has a 
207             bullet hole through the middle.",
208         w_to mainroom,
209         e_to window,
210   has   light;
211
212 Object  desk "solid oak desk" office
213   with  name 'solid' 'oak' 'desk',
214   with  description 
215             "The desk is old and made of solid oak. The right side of 
216             it has been smashed and all of the drawers have been 
217             removed. A bullet hole goes straight through the middle of 
218             the desk.",
219         before [;
220           Take, Pull, Push, PushDir, Turn:
221             print_ret (The) self, " is too heavy for that.";
222         ],
223   has   scenery supporter enterable;
224
225 Object  businesscard "business card" desk
226   with  name 'business' 'card',
227   with  description 
228             "The business card is white and has blacked edges. It 
229             bears the name ~Lasting Solutions~, a local data recovery 
230             company, in bold letters on the top. The company's 
231             website URL is printed in blue at the bottom.";
232
233 Object  salesreceipt "sales receipt" desk
234   with  name 'sales' 'receipt',
235   with  description 
236             "The sales receipt is for $200, dated three years ago. 
237             It's printed on old tractor feed printer paper and bears 
238             the name ~Lasting Solutions~, a local data recovery 
239             company. A handwritten note is scrawled on the bottom: 
240             ~Start working on these hard drives soon.~";
241
242 Object  computer "computer" desk
243   with  name 'computer' 'PC',
244   with  description 
245             "It's a heavy older model that appears to have been 
246             seriously damaged in a fight. It's clearly on its last 
247             legs but is perhaps still useful.",
248         before [;
249           Take, Pull, Push, PushDir, Turn:
250             print_ret (The) self, " is too heavy for that.";
251           SwitchOn:
252             if (computer hasnt visited) {
253                 print 
254                     "The computer makes some concerning noises while 
255                     lights on the front also illuminate. The last 
256                     file is quickly displayed. ~If anyone else reads 
257                     this, you're in serious danger. I've been fighting 
258                     a ferocious grue for the last three days. I'm 
259                     almost out of supplies and can't last much 
260                     longer. I'm going to take the last of the supplies 
261                     and escape through the office window in a 
262                     last-ditch effort to get away and get back into 
263                     town. I hope I can make it.~ The computer then 
264                     makes a sickly sound and finally dies as some 
265                     smoke comes out of it.^";
266                 give computer visited;
267             }
268             else {
269                 print 
270                     "The display briefly flickers but nothing 
271                     else happens.^";
272             }
273             return true;
274         ],
275   has   switchable;
276
277 Object  drywall "drywall" office
278   with  name 'drywall' 'dry' 'wall',
279         before [;
280           Take, Pull, Push, PushDir, Turn:
281             print_ret "Taking that would achieve little.";
282         ],
283   has   scenery;
284
285 Object  insulation "insulation" office
286   with  name 'insulation',
287         before [;
288           Take, Pull, Push, PushDir, Turn:
289             print_ret "Taking that would achieve little.";
290         ],
291   has   scenery;
292
293 Object  bullethole "bullet hole" desk
294   with  name 'bullet' 'hole' 'holes',
295   with  description 
296             "Looks to have come from something that's capable of 
297             doing a lot of damage.",
298         found_in desk bedroom,
299   has   scenery;
300
301 Object  window "window" office
302   with  name 'window' 'windows',
303         description 
304             "The window faces the east side of the cabin. It's broken, 
305             letting in the cold air from outside.",
306         short_name [;
307             if (location == office)
308                 print "window";
309             else
310                 print "window into the cabin";
311             return true;
312         ],
313         found_in office eastofcabin,
314         door_dir [;
315             if (location == office)
316                 return e_to;
317             else
318                 return w_to;
319         ],
320         door_to [;
321             if (location == office)
322                 return eastofcabin;
323             else
324                 return office;
325         ],
326         before [;
327           Search:
328             print_ret "The window faces the east side of the cabin.";
329           Open, Close:
330             print_ret 
331                 "The window's broken so it's not clear how 
332                 you'd do that.";
333         ],
334   has   scenery door openable open;
335
336 Object  kitchenette "Kitchenette"
337   with  description 
338             "The kitchenette is empty. A sink, you think, though it's 
339             hard to tell what's a pipe and what's a faucet. A 
340             refrigerator, standing open and empty. The door has been 
341             ripped off. There's no indication as to where it 
342             went. There's no food anywhere in here.",
343         e_to mainroom,
344   has   light;
345
346 Object  refrigerator "refrigerator" kitchenette
347   with  name 'fridge' 'refrigerator',
348   with  description 
349             "An old rusty refrigerator, standing open and empty. The 
350             door has been ripped off. There's no indication as to 
351             where it went.",
352         before [;
353           Take, Pull, Push, PushDir, Turn:
354             print_ret (The) self, " is too heavy for that.";
355           Open, Close:
356             print_ret (The) self, " door is missing.";
357         ],
358   has   scenery enterable container openable open;
359
360 Object  sink "sink" kitchenette
361   with  name 'sink' 'pipe' 'faucet',
362   with  description 
363             "A sink, you think, though it's hard to tell what's a 
364             pipe and what's a faucet.",
365         after [;
366           SwitchOn:
367             print_ret 
368                 "Pipes from in the walls make a groaning sound, 
369                 almost like pain and despair. No water comes out.";
370         ],
371   has   scenery container switchable;
372
373 Object  bedroom "Bedroom"
374   with  description 
375             "This bedroom is small and cramped, and looks like a 
376             major fight happened as the exterior wall has bullet 
377             holes. The bed is lying on the floor, torn to shreds. It 
378             has no sheets, just a bare mattress.",
379         s_to mainroom,
380   has   light;
381
382 Object  bed "bed" bedroom
383   with  name 'bed' 'mattress',
384   with  description "The mattress is bare and empty.",
385         before [;
386           Take, Pull, Push, PushDir, Turn:
387             print_ret (The) self, " is too heavy for that.";
388         ],
389   has   scenery supporter;
390
391 Object  suitcase "suitcase" bedroom
392   with  name 'suitcase',
393   with  description 
394             "The suitcase is made of a light metallic material that 
395             you can't quite make out. The color of it is somewhere 
396             between silver and grey.",
397   has   container open openable;
398
399 Object  snowsuit "snowsuit" suitcase
400   with  name 'snowsuit' 'snow' 'suit',
401   with  description 
402             "The snowsuit is blue, decorated with white and purple 
403             designs. On the chest is a large emblem with the letters 
404             ~CE~ in purple.",
405         before [;
406           Wear:
407             if (snowshoes in player && snowshoes has worn) {
408                 print_ret "The snowsuit can't fit over the snowshoes.";
409             }
410           Remove:
411             if (snowshoes in player && snowshoes has worn) {
412                 print_ret "The snowsuit can't be taken off over the snowshoes.";
413             }
414         ],
415   has   clothing;
416
417 Object  snowshoes "snowshoes" bedroom
418   with  name 'snowshoe' 'snowshoes' 'snow' 'boot' 'boots' 'shoe' 'shoes' 'metal' 'frame',
419   with  description 
420             "They're light blue in color and have a thick, hard 
421             rubber bottom that's attached to a metal frame that keeps 
422             you from sinking into the snow. They look to be warm and 
423             comfortable.",
424         after [;
425           Wear:
426             print_ret (The) self, 
427                 " fit perfectly and go up to your 
428                 knees.";
429         ],
430         daemon [;
431             if (location ~= mainroom && location ~= office && location ~= kitchenette
432             && location ~= bedroom && snowshoes hasnt worn) {
433                 deadflag = 3;
434             }
435         ],
436   has   pluralname clothing;
437
438 Object  eastofcabin "East Of Cabin"
439   with  description [;
440             print "It's dark outside. ";
441             if (lightbulb has on) {
442                 print 
443                     "The light from inside the cabin only penetrates 
444                     a few feet from the building. ";
445             }
446             else
447                 if (lantern in player && lantern has on) {
448                     print 
449                         "The lantern provides the only source of 
450                         light. ";
451                 }
452             if (snowshoes in player && snowshoes has worn) {
453                 print 
454                     "The snowshoes are doing their job by making sure 
455                     you don't sink into the snow.";
456             }
457         ],
458         w_to window,
459   has   light;
460
461 [ Initialise;
462     Location = mainroom;
463     thedark.description = 
464         "It is pitch black. You are likely to be eaten 
465         by a grue.";
466     print 
467         "You're trapped in a snowstorm while visiting the forest 
468         during your vacation to a small rural town. This is the worst 
469         snowstorm in more than 40 years. If only you has listened to 
470         the news. Well, it's too late for that. The snow has been 
471         falling for the past seven hours and shows no signs of 
472         stopping anytime soon. You need to get back to your hotel in 
473         the town. You finally manage to find an old cabin in the 
474         woods and get inside but have no idea where you are. You're 
475         not dressed for this weather.^";
476     StartDaemon(lantern);
477     StartDaemon(snowshoes);
478 ];
479
480 [ DeathMessage;
481     if (deadflag == 3)
482         print 
483             "You sink into the deep snow and are unable to move. 
484             It's only a matter of time until your light source dies and the grue 
485             comes. Or until you freeze to death. Or both. I wonder if the grue 
486             likes a popsicle.";
487 ];
488
489 [ InScope;
490     if (location == thedark && real_location == mainroom) {
491         PlaceInScope(lightsocket);
492         PlaceInScope(lightbulb);
493     }
494     return false;
495 ];
496
497 Object  grue "grue" thedark
498   with  article "the",
499         name 'grue' 'monster',
500         each_turn [;
501             StartDaemon(self);
502         ],
503         turns_active,
504         daemon [;
505             if (location ~= thedark) {
506                 self.turns_active = 0;
507                 StopDaemon(self);
508                 return true;
509             }
510             switch (++(self.turns_active)) {
511               1:
512                 "^You hear horrible gurgling sounds in the dark.";
513               2:
514                 "^You hear the clink of razor-sharp claws nearby.";
515               3:
516                 deadflag = 1;
517                 "^Your last memory is of the slavering fangs of the 
518                 horrible Grue as it claims you for a meal.";
519             }
520         ],
521   has   scenery;
522
523 [ DarkToDark;
524     deadflag = 1;
525     "Oh, no! You have walked into the slavering fangs of a lurking 
526     grue!";
527 ];
528
529 [ URL;
530     print 
531         "^If you need help try some of the commands from: 
532         ^http://pr-if.org/doc/play-if-card/^";
533 ];
534
535 [ XyzzySub;
536     print "Nothing obvious happens.^";
537     return true;
538 ];
539
540 [ HelpSub;
541     URL();
542     return true;
543 ];
544
545 Include "grammar";
546
547 Verb 'About'
548     * -> Version;
549
550 Verb 'Info'
551     * -> Version;
552
553 Verb 'Help'
554     * -> Help;
555
556 Verb 'Clue'
557     * -> Help;
558
559 Verb 'Hint'
560     * -> Help;
561
562 Verb 'xyzzy'
563     * -> Xyzzy;
564
565 Verb 'crawl'
566     * 'through' / 'out' / 'via' noun -> Go;
567
568 Verb 'escape'
569     * 'through' / 'out' / 'via' noun -> Go;
570
571 Extend 'jump'
572     * 'through' / 'out' / 'via' noun -> Go;
573
574 Extend 'climb'
575     * 'through' / 'out' / 'via' noun -> Go;
576
577 Extend 'go'
578     * 'through' / 'out' / 'via' noun -> Go;