f3fe1c61ef17a1f297205a8237bf2723d082a847
[devours.git] / devours.inf
1 !% $MAX_STATIC_DATA=150000
2
3
4 !============================================================================
5
6 ! This program was written by Toby Ord (half sick of shadows) and has been
7 ! released into the public domain, so you are legally free to be distribute 
8 ! and modify it as you see fit. So long as you do so in good faith and with good
9 ! taste (or sufficient taste) then you have my blessing.
10 !
11 ! Oh, and apologies for the messy code! It was my first program in Inform.
12
13 Constant Story "All Things Devours";
14
15 Constant Headline
16    "^Written for IFComp 2004 by half sick of shadows.^
17      This is the post-competition release.^
18      It is in the public domain and may thus be freely copied or modified.^
19      First-time players should type 'about'.^";
20
21
22 Release 3;    ! post-competition release, (plus 1 bugfix)
23 Serial "190818";
24
25 Replace DrawStatusLine;
26 Replace ScoreSub;
27
28
29 !============================================================================
30 ! Constants and Globals
31 !
32
33 Constant DEATH_MENTION_UNDO;
34
35 ! EARLIEST_TIME is a time before which no action can happen 
36 ! (can't time travel to before this time)
37 ! start_time is when the player arrives.
38 ! From ten seconds earlier,
39 ! the player is outside (and can interfere with escape attempts at this time)
40 ! <<< thus the EARLIEST_TIME must be at least ten seconds before start_time >>>
41 ! FINAL_TIME is when the security team arrive and any attempt to stay beyond this
42 ! will get you caught.
43
44 ! the time units are 5 second blocks
45
46 Global my_time;        ! used instead of the_time to allow sub-minute turns
47
48 ! the timeline has the player in a non-specified 'limbo' from EARLIEST_TIME to
49
50 Constant EARLIEST_TIME = ((4 * 60) + 13) * 12 + 11;
51 Constant FINAL_TIME =    ((4 * 60) + 23) * 12 + 0;
52
53 Global start_time =      ((4 * 60) + 17) * 12 + 0;
54 Global early_guard_time = EARLIEST_TIME;            ! but this changes in the challenge mode
55
56 Constant CHALLENGE_EARLY_GUARD_TIME = ((4 * 60) + 15) * 12 + 11;
57
58
59 ! the times of the two military experiments, if allowed to happen
60
61 Constant EXPERIMENT1_TIME = (( 9 * 60) + 27) * 12 + 3;
62 Constant EXPERIMENT2_TIME = ((11 * 60) + 33) * 12 + 9;
63
64 Constant GAME_LENGTH = FINAL_TIME - EARLIEST_TIME;
65
66 Constant LATER_ = -1;  ! A constant to represent a later time
67
68 Constant DEFAULT_SIREN_TIMEOUT   = 16;      ! the time before the guard arrives 
69 Constant CHALLENGE_SIREN_TIMEOUT = 11;      ! 1:20 vs. 0:55
70
71 Constant TIME_BEFORE_DRAGGED_OFF = 4;   ! the time between arrest and removal
72
73 Constant MAX_TIME_TRAVELS = 2;
74
75 ! ***************** Important ********************
76 ! This MUST be set to be equal to 2 to the power of MAX_TIME_TRAVELS
77
78 Constant MAX_ITEM_COPIES = 4;
79
80 ! Constants for death states
81
82 Constant ACCELERATED_          =  4;   ! brought about the premature destruction of Boston
83 Constant USELESS_              =  5;   ! achieved nothing of consequence
84 Constant DELAYED_              =  6;   ! delayed the destruction by blowing up prototype
85 Constant SAVED_DEAD_           =  7;   ! saved the city but died
86 Constant SAVED_CAUGHT_         =  8;   ! saved the city but caught
87 Constant SAVED_FREE_           =  9;   ! saved the city and free
88 Constant SAVED_FREE_CHALLENGE_ = 10;   ! saved the city and free and completed the challenge
89 ! Constants for object states
90
91 Constant NA_      = -2;
92 Constant UNKNOWN_ = -1;
93 Constant LOCKED_  =  0;
94 Constant CLOSED_  =  1;
95 Constant OPEN_    =  2;
96
97 ! Potentially dangerous actions:
98
99 Constant NONE_                      =  0;
100 Constant LOCK_                      =  1;
101 !Constant OPEN_                     =  2;    Not needed since defined above
102 Constant UNLOCK_                    =  3;
103 Constant X_CCTV_                    =  4;
104 Constant X_UPSTAIRS_CORRIDOR_       =  5;
105 Constant X_UPSTAIRS_LANDING_        =  6;
106 Constant X_GROUND_CORRIDOR_         =  7;
107 Constant X_FOYER_                   =  8;
108 Constant X_BASEMENT_CORRIDOR_       =  9;
109 Constant X_BASEMENT_LANDING_        = 10;
110 Constant X_BALCONY_                 = 11;
111 Constant TAKE_FLASHLIGHT_           = 12;
112 Constant BLOW_BASEMENT_LIGHT_       = 13;
113 Constant SING_                      = 14;     ! these are not dangerous in the same way
114 Constant SHOUT_                     = 15;     ! but need to be caught and replayed
115
116 Global time_travelled;
117 Global last_travel_time;
118
119 Global d_paradox;
120 Global d_caught;
121 Global d_detained;
122 Global d_escaped;
123 Global d_exploded;
124 Global d_killed_by_bomb;
125 Global d_injured_by_bomb;
126 Global d_fs_hears_bomb;
127 Global d_fs_killed_by_bomb;
128 Global d_destroyed_notes;
129 Global d_destroyed_prototype;
130
131       !! The moveable items (which can be taken back in time):
132
133 Array bomb          --> MAX_ITEM_COPIES;
134 Array id_card       --> MAX_ITEM_COPIES;
135 Array equipment_key --> MAX_ITEM_COPIES;
136 Array deutsch_key   --> MAX_ITEM_COPIES;
137 Array flashlight    --> MAX_ITEM_COPIES;
138 Array battery       --> MAX_ITEM_COPIES;
139 Array cable         --> MAX_ITEM_COPIES;
140 Array crowbar       --> MAX_ITEM_COPIES;
141 Array notes         --> MAX_ITEM_COPIES;
142
143 Array former_self   --> MAX_TIME_TRAVELS;
144
145
146        !! The locations of various things at various times
147        !! These contain an immense amount of info:
148        !!     Location of each copy of that item at each time for each run through
149        !! Amongst other things, this allows one to recreate the world at a given time
150
151 Array player_loc        --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
152
153 Array bomb_loc          --> (GAME_LENGTH + 1) *
154                             (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1);
155 Array id_card_loc       --> (GAME_LENGTH + 1) *
156                             (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1);
157 Array equipment_key_loc --> (GAME_LENGTH + 1) *
158                             (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1);
159 Array deutsch_key_loc   --> (GAME_LENGTH + 1) *
160                             (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1);
161 Array flashlight_loc    --> (GAME_LENGTH + 1) *
162                             (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1);
163 Array battery_loc       --> (GAME_LENGTH + 1) *
164                             (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1);
165 Array cable_loc         --> (GAME_LENGTH + 1) *
166                             (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1);
167 Array crowbar_loc       --> (GAME_LENGTH + 1) *
168                             (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1);
169 Array notes_loc         --> (GAME_LENGTH + 1) *
170                             (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1);
171
172        !! The states of various things at various times
173
174 Global prototype_fixed_time = UNKNOWN_;
175 Global siren_start_time     = UNKNOWN_;
176
177 Array flashlight_state  --> (GAME_LENGTH + 1) *
178                             (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1);
179 Array bomb_setting      --> (GAME_LENGTH + 1) *
180                             (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1);
181
182 !! activity_target is used to distinguish which door was (dangerously) locked/unlocked/opened
183
184 Array dangerous_activity            --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
185 Array activity_target               --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
186
187 Array siren_state                   --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
188 Array panel_setting                 --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
189 Array ground_equipment_light        --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
190 Array basement_equipment_light      --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
191
192 Array main_doors_state              --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
193 Array basement_door_state           --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
194 Array ground_door_state             --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
195 Array upstairs_door_state           --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
196 Array balcony_door_state            --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
197 Array conference_window_state       --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
198 Array deutsch_door_state            --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
199 Array basement_equipment_door_state --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
200 Array ground_equipment_door_state   --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
201
202 Array main_doors_smashed            --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
203 Array basement_door_smashed         --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
204 Array ground_door_smashed           --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
205 Array upstairs_door_smashed         --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
206 Array balcony_door_smashed          --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
207
208
209 Global poem_interleaving        = false;
210 Global initialising             = true;
211 Global first_turn               = true;
212 Global challenge                = false;
213 Global siren_timeout            = DEFAULT_SIREN_TIMEOUT;
214 Global instant_action_this_turn = false;
215 Global warned_of_jump           = false;
216 Global id_card_used             = false;
217 Global have_looked_at_bench     = false;
218 Global prototype_seen           = false;
219
220 !============================================================================
221
222
223
224 Include "parser";
225
226 Object LibraryMessages
227 with before [;
228     Jump:
229         if (real_location == balcony) {
230             Jumped();
231             return true;
232         }
233         "You jump on the spot, fruitlessly.";
234     Listen:
235         if ((siren_start_time ~= UNKNOWN_) && (siren_start_time < my_time))
236             return true;
237         else if (Get2D(dangerous_activity, time_travelled-1, my_time-EARLIEST_TIME) == SHOUT_)
238            return true;
239         else if (Get2D(dangerous_activity, time_travelled-1, my_time-EARLIEST_TIME) == SING_)
240            return true;
241         else
242            "You can hear nothing but a soft electric hum.";
243     Burn:
244         "You have no source of flame.";
245     Sing:
246         "You sing out a few clear notes.";
247     Miscellany:
248         if (lm_n == 44)
249             "It is not clear what you are trying to refer to with 'all'.";
250 ]; 
251
252 Include "verblib";
253
254
255 !============================================================================
256
257
258 ! Object classes
259
260 Class   Room
261   with  before [t;
262           Inv, Look:
263             if (initialising) {
264                 initialising = false;
265                 return false;
266             }
267             instant_action_this_turn = true;
268             return false;
269           Sing:
270             for (t=0 : t<time_travelled : t++) {
271                 if ((former_self-->t notin limbo) && 
272                     ((siren_start_time == UNKNOWN_) || (siren_start_time > my_time))) {
273                     
274                     print "You sing out a few clear notes.^";
275                     d_paradox = true;
276                     deadflag = 3;
277                     Seperator();
278                     print (Nearby) 0, "your former self hears the muffled sounds of your
279                            singing.^^Something of an anticlimactic way to kill 
280                            so many millions of people...^"; 
281                     print "^Time unravels...^";
282                     Devours(my_time);                            
283                     return true;
284                 }
285             }
286             Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,SING_);
287             return false;
288         ],
289         each_turn [t i;  
290             first_turn = false;
291             if (instant_action_this_turn) {
292                 instant_action_this_turn = false;
293                 return true;
294             }
295             MoveFloatingObjects();
296             my_time++;
297             if (time_travelled > 0) {
298                 for(i=0 : i < Exp(2,time_travelled-1) : i++) {
299                     MoveObject(bomb, bomb_loc, i);
300                     MoveObject(id_card, id_card_loc, i);
301                     MoveObject(equipment_key, equipment_key_loc, i);
302                     MoveObject(deutsch_key, deutsch_key_loc, i);
303                     MoveObject(flashlight, flashlight_loc, i);
304                     MoveObject(battery, battery_loc, i);
305                     MoveObject(cable, cable_loc, i);
306                     MoveObject(crowbar, crowbar_loc, i);
307                     MoveObject(notes, notes_loc, i);
308                 }
309                 
310                 if (my_time == prototype_fixed_time)
311                     prototype.fixed = true;
312                                       
313                 MaybeSetBombs();
314                 MaybeSetFlashlights();
315                 MaybeSetPanel(panel_setting);
316                 MaybeSetBasementLight(basement_equipment_light);
317                 MaybeSetGroundLight(ground_equipment_light);
318                 MaybeSetAutomaticDoor(main_doors, main_doors_state);
319                 MaybeSetAutomaticDoor(basement_door, basement_door_state);
320                 MaybeSetAutomaticDoor(ground_door, ground_door_state);
321                 MaybeSetAutomaticDoor(upstairs_door, upstairs_door_state);
322
323                 MaybeBreakDoor(main_doors, main_doors_smashed);
324                 MaybeBreakDoor(basement_door, basement_door_smashed);
325                 MaybeBreakDoor(ground_door, ground_door_smashed);
326                 MaybeBreakDoor(upstairs_door, upstairs_door_smashed);
327                 MaybeBreakDoor(balcony_door, balcony_door_smashed);
328                 
329                 MaybeSing();
330                 MaybeShout();
331
332 !-- from here down paradox may occur and we need to be able to stop if one occurs  if (~~d_paradox)...
333                 
334                 for(t=0 : t < time_travelled : t++)
335                     MoveFormerSelf(t);
336
337                 MaybeSetManualDoor(balcony_door, balcony_door_state);
338                 MaybeSetManualDoor(conference_window, conference_window_state);
339                 MaybeSetManualDoor(deutsch_door, deutsch_door_state);
340                 MaybeSetManualDoor(basement_equipment_door, basement_equipment_door_state);
341                 MaybeSetManualDoor(ground_equipment_door, ground_equipment_door_state);
342                                 
343             }
344
345             MaybeCloseAutomaticDoor(main_doors);
346             MaybeCloseAutomaticDoor(basement_door);
347             MaybeCloseAutomaticDoor(ground_door);
348             MaybeCloseAutomaticDoor(upstairs_door);
349                             
350             ObserveLocations();
351             ObserveBombs();
352             ObserveFlashlights();
353             ObserveSiren();
354             ObservePanel();
355             ObserveBasementLight(basement_equipment_light);
356             ObserveGroundLight(ground_equipment_light);
357             ObserveAutomaticDoor(main_doors, main_doors_state);
358             ObserveAutomaticDoor(basement_door, basement_door_state);
359             ObserveAutomaticDoor(ground_door, ground_door_state);
360             ObserveAutomaticDoor(upstairs_door, upstairs_door_state);
361             ObserveManualDoor(balcony_door, balcony_door_state);
362             ObserveManualDoor(conference_window, conference_window_state);
363             ObserveManualDoor(deutsch_door, deutsch_door_state);
364             ObserveManualDoor(basement_equipment_door, basement_equipment_door_state);
365             ObserveManualDoor(ground_equipment_door, ground_equipment_door_state);
366
367             ObserveBrokenDoor(main_doors, main_doors_smashed);
368             ObserveBrokenDoor(basement_door, basement_door_smashed);
369             ObserveBrokenDoor(ground_door, ground_door_smashed);
370             ObserveBrokenDoor(upstairs_door, upstairs_door_smashed);
371             ObserveBrokenDoor(balcony_door, balcony_door_smashed);
372    
373             CheckPassiveParadox();
374             CheckActiveParadox();
375        
376             if (~~(Stopped())) {
377                 if (siren_start_time ~= UNKNOWN_) {
378                     if (my_time - siren_start_time == 1)
379                             print "^A piercing siren rings out.^";
380                     if (my_time - siren_start_time > 1) {
381                         if (my_time - siren_start_time <= siren_timeout)
382                             print "^The siren wails.^";
383                         else
384                             CaughtInside();
385                     }
386                 }
387                 if ((my_time > FINAL_TIME) && (~~Stopped()))
388                     CaughtInside();
389             }
390     
391             if (main_doors.just_closed) main_doors.closing_message();
392             if (basement_door.just_closed) basement_door.closing_message();
393             if (ground_door.just_closed) ground_door.closing_message();
394             if (upstairs_door.just_closed) upstairs_door.closing_message();
395
396             MaybeExplodeBombs();
397             
398         ],
399         
400   has   light;
401
402 Class   Sight
403   with  before [;
404             Examine: return false;
405             Listen: return false;
406             default:
407                 print_ret "You cannot do that from here.";
408         ],
409   has   scenery concealed static;
410  
411 Class   PluralSight
412   with  before [;
413             Examine: return false;
414             default:
415                 print_ret "You cannot do that to all of ", (the) self, " at once.";
416         ],
417   has   scenery concealed static;
418       
419 Class   Prop
420   with  before [;
421             Examine: return false;
422             default:
423                 print_ret "You don't need to worry about ", (the) self, ".";
424         ],
425   has   scenery concealed static;
426
427
428 Class   Furniture
429   with  before [;
430             Take,Pull,Push,PushDir:
431                 print_ret (The) self, " is too heavy for that.";
432         ],
433   has   static supporter;
434
435
436 Class   AutomaticDoor
437   with  before [;
438             Take,Pull,Push,PushDir:
439                 print_ret (The) self, " is locked in place.";
440             Lock:
441             Close:
442               "Like most automatic doors, this one closes of its own accord.";
443             Attack:
444               if (AmHolding(crowbar)) {
445                   print "You swing the crowbar firmly into the door. It shudders,
446                          a star of cracks reaching out from the point of impact,
447                          but the glass stays in place.^";
448                   self.smashed = true;
449                   StartSiren();
450                   return true;
451               }
452               else
453                 "You don't have anything heavy enough to smash the door with.";              
454             Search:
455               <<Examine self>>;             
456         ],
457         just_closed false,
458         smashed false,
459         to_close_at UNKNOWN_,
460         open_self [t;
461             if (self hasnt open) {
462                 give self open ~locked;
463                 if (self in LocationOf(player))
464                     print "The door slides open with a soft rattle.^";
465             }
466             self.to_close_at = t;
467         ],
468         close_self [;
469             give self ~open locked;
470             self.to_close_at = UNKNOWN_;
471             self.just_closed = true;
472         ],
473         closing_message [;
474             if ((~~Stopped()) && (self in LocationOf(player)))
475                 "The automatic door softly slides closed.";
476         ],
477   has   static door openable locked;
478
479 Class   ManualDoor
480   with  name 'door' 'to' 'the',
481         before [;
482           Take,PushDir:
483                 print_ret (The) self, " is locked in place.";
484           Attack:
485               if (AmHolding(crowbar)) {
486                   print "You swing the crowbar firmly into the door, 
487                          but it barely leaves a mark.^";
488                   return true;
489               }
490               else
491                 "You don't have anything heavy enough to break the door with.";              
492           ],  
493         react_before [;
494           Go: if (noun.door_dir() == self.door_dir())
495                   return self.open_by_myself();
496               if (noun.door_dir() == out_to)      !! XX hack, going 'out' always uses door in this game
497                   return self.open_by_myself();
498           Enter: 
499                if (noun == self) return self.open_by_myself(); 
500         ], 
501         open_by_myself [ ks;
502             if (self has open)
503                 rfalse;
504             print "(first opening ", (the) self, ")^";
505             ks = keep_silent;
506             keep_silent = true;
507             <Open self>;
508             keep_silent = ks;
509             if (self hasnt open)
510                 rtrue;
511             else {
512                 IncTime();
513                 if (Stopped()) return true;
514             }
515         ], 
516   has   static door openable lockable;
517
518
519 [LockUnlockParadox;
520     d_paradox = true;
521     deadflag = 3;
522     Seperator();
523     print "On the other side of the door, your former self hears you turn the
524            key in the lock.^"; 
525     print "^Time unravels...^";
526     Devours(my_time);                            
527 ];
528
529 [OpenParadox;
530     d_paradox = true;
531     deadflag = 3;
532     Seperator();
533     print "On the other side, your former self sees the door open in front
534            of her.^"; 
535     print "^Time unravels...^";
536     Devours(my_time);                            
537 ];
538
539 [CloseParadox;
540     d_paradox = true;
541     deadflag = 3;
542     Seperator();
543     print "On the other side, your former self sees the door close in front
544            of her.^"; 
545     print "^Time unravels...^";
546     Devours(my_time);                            
547 ];
548
549 [OpenManualDoor door ks;
550     if (door has locked) {
551         if (door.with_key_type == nothing
552           || ~~AmHolding(door.with_key_type)) 
553               "Try as you might, none of your keys will unlock the door."; 
554         print "(first unlocking ", (the) door, ")^"; 
555         ks = keep_silent; 
556         keep_silent = true; 
557         <Unlock door (GetHeld(door.with_key_type))>; 
558         keep_silent = ks; 
559         if (door has locked) 
560             return true;
561         else {
562             IncTime();
563             if (Stopped()) return true;
564         }
565     }
566     Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,OPEN_);
567     Put2D(activity_target,time_travelled,my_time-EARLIEST_TIME,door);
568     return false;
569 ];
570
571 [UnlockManualDoor door key;
572     Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,UNLOCK_);
573     Put2D(activity_target,time_travelled,my_time-EARLIEST_TIME,door);
574     if (door has locked) {
575       if ( IsOfType(key,door.with_key_type) ) {
576           give door ~locked;
577           if (~~keep_silent)
578               print (The) key, " turns smoothly in the lock.^";
579           return true;
580       }
581       else
582           "It does not fit in the lock.";
583     }
584     return false;
585 ];
586
587 [LockManualDoor door key ks;
588     if (door has open) {
589         print "(first closing ", (the) door, ")^"; 
590         ks = keep_silent;
591         keep_silent = true;
592         <Close door>;
593         keep_silent = ks; 
594         if (door has open) 
595             rtrue; 
596         IncTime();
597         if (Stopped()) return true;
598     }
599     Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,LOCK_);
600     Put2D(activity_target,time_travelled,my_time-EARLIEST_TIME,door);
601     if (door hasnt locked) {
602         if ( IsOfType(key,door.with_key_type) ) {
603             give door locked;
604           if (~~keep_silent)
605               print (The) key, " turns smoothly in the lock.^";
606           return true;
607         }
608         else
609             "It does not fit in the lock.";
610     }
611     return false;
612 ];
613
614
615 Class   FakeDoor
616   with  name 'door' 'to' 'the',
617         before [;
618           Take,PushDir:
619                 print_ret (The) self, " is locked in place.";
620           Unlock:
621               if (IsOfType(second,crowbar))
622                   <<Attack self>>;
623           Attack:
624             if (AmHolding(crowbar)) {
625                 print "You swing the crowbar firmly into the door, 
626                        but it barely leaves a mark.^";
627                 return true;
628             }
629             else
630               "You don't have anything heavy enough to break the door with.";              
631           Enter:
632             "The door is locked.";
633         ],
634         door_to nothing,
635         door_dir nothing,
636         with_key_type nothing,
637   has   static door openable lockable locked;
638
639
640 !============================================================================
641
642 ! the moveable objects (defined as classes)
643 ! with trailing _ to avoid ambiguity with individual item names
644
645
646 Class   Bomb_(MAX_ITEM_COPIES) 
647   with  short_name "timed explosive device",
648         plural "timed explosive devices",
649         description [t i;
650             print "A length of steel pipe filled with powder and fused with a digital timer.
651                    Not your most elegant piece of work, but it will
652                    hopefully do the job.^";
653             t = (self.time_value - my_time) * 5 + self.left_over_seconds;
654             if (self.time_value == NA_) 
655                 print "^You have not yet set the timer.^";
656             else {
657                 if (t == -4)
658                     print "^On the timer's small LED screen, the number 0 
659                            blinks out at you.^";
660                 else {
661                     print "^On the timer's small LED screen, the numbers ";
662                     for (i = t+4 : (i>t) && (i>0) : i--)
663                         print i, ", ";
664                     if (t < 0)
665                         print 0;
666                     else
667                         print t;
668                     print "... blink out at you insistently, illuminating
669                            the room with faint blue-green flashes.^";
670                 }
671             }
672             ],
673         name 'time' 'timed' 'explosive' 'device' 'bomb' 'timebomb' 'C4'
674              'timer' 'digital' 'pipe'
675              'devices//p' 'bombs//p' 'timebombs//p' 'timers//p',
676         time_value NA_,
677         left_over_seconds 0,
678         before [;
679           Set:
680             print "To set the explosive device,
681                        you need to specify a number of seconds,
682                        for example, with 'set timer to 30'.^";
683             return true;
684           SetTo:
685             if (self.time_value ~= NA_) {
686                 print "(first resetting the timer)^";
687                 self.time_value = NA_;
688             }
689             if (second > 0 && second <= 100) {
690                 self.time_value = my_time + (second/5);
691                 self.left_over_seconds = second%5;
692                 print "Time until detonation: ", (self.time_value - my_time) * 5
693                                                                  + self.left_over_seconds;
694                 print " seconds.^";
695                 if (parent(self) == player)
696                     print "(you probably don't want to be carrying the device
697                             when that occurs...)^";
698             }
699             else {
700                 print "Your timer only accepts between 1 and
701                        100 seconds.^";
702             }
703             return true;
704           Reset:
705              if (self.time_value ~= NA_) {
706                  self.time_value = NA_;
707                  "You reset the timer.";
708              }
709              else
710                 "The timer is not currently set.";
711           ],
712   has  ;
713
714 Class   IDCard_(MAX_ITEM_COPIES) 
715   with  short_name "ID card",
716         plural "ID cards",
717         description "Natalie Williams.^
718                      Deutsch Lab.^
719                      Doctoral Student, MIT^
720                      ^
721                      On the right is a familiar photo of you, back when you
722                      wore your hair long. 
723                      A black magnetic stripe runs the width of the reverse.",
724         name 'id' 'card' 'cards',
725         before[; Insert:
726             if (second == id_slot){
727                     if (second in foyer or upstairs_landing) {
728                         "The slot emits a small beep and your card is rejected.";
729                     }
730                     if (second in basement_landing) {
731                         if (~~id_card_used) {
732                             print "You swipe your card through the slot, and hold your breath.^";
733                             basement_door.open_self(my_time+1);
734                             print "Perfect. Just as you'd hoped.
735                                    The bastards hadn't even thought to disable your card.^";
736                             id_card_used = true;
737                         }
738                         else
739                             basement_door.open_self(my_time+1);
740                         return true;
741                     }
742             }
743             if (second == ground_door or upstairs_door 
744                 && player in foyer or upstairs_landing) {
745                     "The slot emits a small beep and your card is rejected.";
746             }
747             if ((second == basement_door) && (player in basement_landing)) {
748                 basement_door.open_self(my_time+1);
749                 return true;
750             }
751        ],
752   has  ;
753
754 Class   Crowbar_(MAX_ITEM_COPIES) 
755   with  short_name "crowbar",
756         plural "crowbars",
757         name 'crow' 'bar' 'crowbar' 'black' 'crowbars//p' 'bars//p',
758         description "A curved black crowbar.",
759   has;
760
761 Class   Flashlight_(MAX_ITEM_COPIES) 
762   with  short_name "flashlight",
763         plural "flashlights",
764         name 'flashlight' 'torch' 'flashlights//p' 'torches//p'
765              'flash' 'metallic' 'blue' 'metallic-blue',
766         description "A small metallic-blue flashlight.",
767         capacity 2,
768         before [;
769           SwitchOn:
770             if (self has on)
771                 "That's already on.";
772             if (BatteriesContained(self) == 2) {
773                 give self on;
774                 if (real_location == basement_equipment ||
775                     (real_location == ground_equipment && ground_equipment.lit == false)) {
776                     <Look>;
777                     instant_action_this_turn = false;
778                     return true;
779                 }
780                 else
781                   "A thin beam of icy light shines forth.";
782             }
783             if (BatteriesContained(self) == 1) {
784                 "The switch clicks, but no light is forthcoming.
785                  It looks as if you will need two batteries.";
786             }
787             if (BatteriesContained(self) == 0) {
788                 "The switch clicks, but no light is forthcoming.
789                  Not surprising considering flashlights usually need batteries.";
790             }
791           SwitchOff:
792             if (player in basement_equipment)
793                 MoveMoveableChildren(basement_equipment,basement_equipment_gloom);
794             else if ((player in ground_equipment) && (ground_light_switch hasnt on))
795                 MoveMoveableChildren(ground_equipment,ground_equipment_gloom);
796           Receive:
797             if (~~IsOfType(noun,battery))
798                 print_ret (The) noun, " won't fit in the flashlight.";
799           Take:
800             Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,TAKE_FLASHLIGHT_);
801             return false;
802         ],
803         after [;
804           LetGo:
805             if (self has on) {
806                 print "As you remove the battery, the light fails.^";
807                 give self ~on;
808                 if (player in basement_equipment)
809                     MoveMoveableChildren(basement_equipment,basement_equipment_gloom);
810                 else if ((player in ground_equipment) && (ground_light_switch hasnt on))
811                     MoveMoveableChildren(ground_equipment,ground_equipment_gloom);
812                 return false;
813             }
814         ],
815   has container open switchable;
816
817 Class   Battery_(MAX_ITEM_COPIES) 
818   with  short_name "battery",
819         plural "batteries",
820         name 'battery' 'batteries//p' 'AA',
821         description "An AA sized battery.",
822         before [;
823           Remove:
824             <<Take noun>>;
825         ],
826   has;
827
828 Class   Cable_(MAX_ITEM_COPIES) 
829   with  short_name "length of ribbon cable",
830         plural "lengths of ribbon cable",
831         name 'cable' 'wire' 'cables//p' 'wires//p' 'ribbon' 'length' 'lengths//p' 'of',
832         description "A 10cm length of ribbon cable. It will do nicely.",
833         before[;
834           Tie:
835             if (second == control_panel or prototype)
836                 <<Tie prototype>>;
837             if (second == nothing)
838                 if (real_location == deutsch_lab or prototype_interior)
839                     <<Tie prototype>>;
840                 else
841                     "There is nothing here that you could attach the cable to.";
842             else
843                 "You cannot attach the cable to that.";
844         ],
845   has;
846
847 Class   Notes_(MAX_ITEM_COPIES) 
848   with  short_name "collection of notes",
849         plural "collections of notes",
850         name 'collection' 'notes' 'collections//p',
851         description "Your research notes. The hundred or so pages here comprise
852                      everything you have written so far. It would not be easy for
853                      someone else to turn the scribbles herein into another working
854                      prototype, but it may just be possible.",
855         before[;
856           Eat:
857             "You look determinedly at the thick bundle of papers, but there is no
858              way that you could eat more than a couple of pages. You had better think
859              of something a little more sensible.";
860           Attack, Cut:
861             "There are about a hundred pages and there is no way that you could tear them
862              up in time.";
863         ],
864   has;
865
866 Class   EquipmentKey_(MAX_ITEM_COPIES) 
867   with  short_name "worn brass key",
868         plural "worn brass keys",
869         name 'key' 'equipment' 'brass' 'worn' 'keys//p',
870         description "A well worn brass key. It opens the various
871                  equipment rooms in the complex.",
872   has;
873
874 Class   DeutschKey_(MAX_ITEM_COPIES) 
875   with  short_name "bright steel key",
876         plural "bright steel keys",
877         name 'key' 'deutsch' 'steel' 'bright' 'keys//p',
878         description "A bright steel key. It unlocks the door to the Deutsch lab, downstairs.",
879   has;
880
881 Class   FormerSelf_(MAX_ITEM_COPIES)
882   with  short_name "your former self",
883         plural "your former selves",
884         name 'self' 'former' 'past' 'selves//p',
885         description "She looks strangely familiar.",
886   has animate proper container concealed;
887
888
889 !===============================================================================
890 ! The one-of-a-kind moveable objects
891
892 Object myselfobj "(self object)"
893   with 
894     short_name "yourself",
895     description "Dark hair frames a warm face. Despite the anxiety written now in your
896                  tense brow, the confidence of youth and vibrancy of intellect are clear.
897                  There is a depth in your clear green eyes.",
898     capacity 100,
899     number 0,
900     orders 0,
901     weakness 0,
902   has concealed animate proper transparent;
903
904
905 Object skeleton_key "skeleton key (fake item to neaten code)"
906   with
907     name 'key' 'skeleton',
908     description "A skeleton key. And I thought they were make-believe!",
909   has;
910
911
912 !===============================================================================
913 ! The rooms
914
915 !-----------------------------------------------
916 ! Generic props and sights:
917
918 Prop   walls "walls"
919   with name 'wall' 'walls',
920        found_in [;
921            if (location ~= prototype_interior)
922                return true;
923            else
924                return false;
925        ],
926   has  ;
927
928 Prop   floor "floor"
929   with name 'floor' 'ground' 'carpet',
930        description "The floor is covered by a thin carpet in a dark but warm gray.",
931        found_in [;
932            if ((location ~= balcony) && (location ~= prototype_interior))
933                return true;
934            else
935                return false;
936        ],
937   has  ;
938
939 Prop   ceiling "ceiling"
940   with name 'ceiling',
941        found_in [;
942            if (location ~= prototype_interior)
943                return true;
944            else
945                return false;
946        ],
947   has  ;
948
949 Sight   darkness "darkness"
950   with name 'darkness' 'dark' 'gloom',
951        description "You cannot see what lies in the darkness.",
952        before [;
953           Examine:
954           Listen:
955               return false;
956           default:
957               "It is not clear what you mean.";
958        ],
959        found_in [;
960            return true;
961        ],
962   has  ;
963
964 Sight   shadows "shadows"
965   with name 'shadows' 'shadow' 'corners' 'cobwebs',
966        description "Shadows fill the corners of the rooms like old cobwebs.",
967        before [;
968           Examine:
969           Listen:
970               return false;
971           default:
972               "It is not clear what you mean.";
973        ],
974        found_in [;
975            return true;
976        ],
977   has  ;
978
979 Sight   complex "complex"
980   with name 'complex' 'building' 'surface' 'surfaces' 'texture' 'textures',
981        description "The building has modern but ultimately shallow feel.
982                     There is a preoccupation with surfaces and textures.
983                     Almost everything is coloured with dark, yet somewhat warm, shades of gray,
984                     darkened further by the midnight gloom.",
985        before [;
986           Examine:
987           Listen:
988               return false;
989           default:
990               "It is not clear what you mean.";
991        ],
992        found_in [;
993            return true;
994        ],
995   has  ;
996
997 Prop   lights "lights"
998   with name 'lights' 'light' 'fluorescent',
999        description "Most of the overhead lights are currently off, leaving the complex in dim half-light.",
1000        before [;
1001            SwitchOn:
1002              "Switching on the overhead lights would alert security to your presence, and besides, you
1003               can see clearly enough in the gloom.";
1004        ],
1005        found_in [;
1006            if ((location ~= balcony) && (location ~= prototype_interior) && 
1007                (location ~= basement_equipment) && (location ~= ground_equipment))
1008                return true;
1009            else
1010                return false;
1011        ],
1012   has  ;
1013
1014 Prop   stairs "stairs"
1015   with name 'stairs' 'staircase',
1016        before [;
1017          Climb:
1018              if (self in foyer or basement_landing)
1019                  <<Go u_obj>>;
1020              if (self in upstairs_landing)
1021                  "You are already at the top of the stairs.";
1022        ],
1023        found_in basement_landing foyer upstairs_landing,
1024   has  ;
1025   
1026 !-----------------------------------------------
1027 ! Item-related props and sights:
1028
1029 Prop   beam "flashlight beam"
1030   with name 'beam' 'blue-white' 'blue' 'white',
1031        description "A thin icy beam that cuts through the darkness.",
1032        found_in [;
1033            if (Flashlit())
1034                return true;
1035            else
1036                return false;
1037        ],
1038   has  ;
1039
1040 Prop   photo "photograph"
1041   with name 'photo' 'photograph' 'long' 'hair',
1042        description "You look young, bright and proud of
1043                     your new position at the lab.",
1044        found_in [;
1045            if (AmHolding(id_card) || IsIn(id_card,real_location))
1046                return true;
1047            else
1048                return false;
1049        ],
1050   has  ;
1051
1052 Prop   stripe "magnetic stripe"
1053   with name 'stripe' 'magnetic' 'reverse' 'back',
1054        description "It is the type of magnetic stripe found on the back of a regular credit card,
1055                     but is used to open the automatic doors in the building.",
1056        found_in [;
1057            if (AmHolding(id_card) || IsIn(id_card,real_location))
1058                return true;
1059            else
1060                return false;
1061        ],
1062   has  ;
1063
1064 !-----------------------------------------------
1065
1066 Room  foyer "Foyer"
1067   with  name 'foyer',
1068         description
1069             "A darkened foyer, presided over by a security desk near the north wall.
1070              Floating above it in the capacious darkness is
1071              a small landing. A set of stairs both rises up to meet it 
1072              and stretches downwards into the dark.",
1073         u_to upstairs_landing,
1074         d_to basement_landing,
1075         n_to ground_door,
1076         s_to main_doors,
1077         cant_go "The only exits are the automatic doors to the north and south,
1078                  and the staircases up and down.",
1079         lower_name "the foyer",
1080   has   ;
1081
1082 Furniture  security_desk "security desk" foyer
1083   with  description "A large black desk equipped with four CCTV screens showing
1084                      live feeds from around the complex. ",
1085         before [;
1086           Examine:
1087             print "A large black desk equipped with four CCTV screens showing
1088                    live feeds from around the complex. ";
1089             cctv_screens.display();
1090             print "There are also four buttons, labeled 'basement',
1091                    'first', 'second' and 'alarm'.^";
1092             return true;
1093         ],
1094         name 'desk' 'security' 'black' 'table',
1095   has   scenery;
1096
1097 Object cctv_screens "CCTV images" foyer
1098   with description [;
1099            print "These screens flash images from the corridors and grounds
1100                   of the complex. ";
1101            self.display();
1102            print "^";
1103        ],
1104        name 'images' 'CCTV' 'screen' 'screens' 'feed' 'feeds' 'image',
1105        display [;
1106             Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_CCTV_);
1107         
1108             if ((my_time == start_time - 1) || (my_time == start_time - 2))
1109                 print "On one of the screens you see your former self approaching the
1110                        complex. ";
1111             if (IsIn(former_self,ground_corridor))
1112                 print "On one of the screens you see your former self in the first
1113                        floor corridor. ";
1114             if (IsIn(former_self,upstairs_corridor))
1115                 print "On one of the screens you see your former self in the second
1116                        floor corridor. ";
1117             if (IsIn(former_self,basement_corridor))
1118                 print "On one of the screens you see your former self in the basement
1119                         corridor. ";
1120        ],
1121   has  scenery concealed;
1122
1123
1124 Object  alarm_button "alarm button" foyer
1125   with  description "A discrete black button carefully labeled 'alarm'.",
1126         name 'alarm' '^alarm^' 'button' 'black' 'labeled' 'marked',
1127         before [; 
1128           Push:
1129             StartSiren();
1130             return true;
1131           Receive:
1132             "The button is set into a vertical surface, making it impossible
1133              to place objects on top of it.";
1134         ],
1135   has   scenery concealed;
1136
1137 Object  first_button "'first' button" foyer
1138   with  description "A small black button carefully labeled 'first'.",
1139         name 'first' '^first^' 'floor' 'button' 'black' 'labeled' 'marked',
1140         before [; Push:
1141             ground_door.open_self(my_time+1);
1142             ground_door.known_exterior_opening = true;
1143             return true;
1144           Receive:
1145             "The button is set into a vertical surface, making it impossible
1146              to place objects on top of it.";
1147         ],
1148   has   scenery concealed;
1149
1150 Object  basement_button "'basement' button" foyer
1151   with  description "A small black button carefully labeled 'basement'.",
1152         name 'basement' '^basement^' 'floor' 'button' 'black' 'labeled' 'marked',
1153         before [; Push:
1154             basement_door.open_self(my_time+1);
1155             "Nothing obvious happens.";
1156           Receive:
1157             "The button is set into a vertical surface, making it impossible
1158              to place objects on top of it.";
1159         ],
1160   has   scenery concealed;
1161
1162 Object  second_button "'second' button" foyer
1163   with  description "A small black button carefully labeled 'second'.",
1164         name 'second' '^second^' 'floor' 'button' 'black' 'labeled' 'marked',
1165         before [; Push:
1166             upstairs_door.open_self(my_time+1);
1167             "Nothing obvious happens.";
1168           Receive:
1169             "The button is set into a vertical surface, making it impossible
1170              to place objects on top of it.";
1171         ],
1172   has   scenery concealed;
1173   
1174 Sight  upstairs_landing_from_foyer "upstairs landing" foyer
1175   with description "The landing above is lost in shadow.",
1176        name 'upstairs' 'landing',
1177   has  ;
1178
1179 Sight  outside_from_foyer "outside" foyer
1180   with description "The grounds are empty and still on this frosty night.",
1181        name 'grounds' 'outside' 'night',
1182   has  ;
1183   
1184 Sight  ground_corridor_from_foyer "corridor" foyer
1185   with description [;<<Examine ground_door>>;],
1186        name 'corridor',
1187   has  ;
1188   
1189 !-----------------------------------------------
1190
1191 Room  basement_landing "Basement Landing"
1192   with  name 'landing',
1193         description
1194             "A cramped space at the bottom of the stairs.
1195              A corridor can be seen to the north through the automatic door,
1196              and the stairs lead back up to the foyer.",
1197         u_to foyer,
1198         n_to basement_door,
1199         cant_go "The only exits are north and up.",
1200         lower_name "the basement landing",
1201   has  ;
1202
1203 Sight  foyer_from_basement_landing "foyer" basement_landing
1204   with description "You cannot see the foyer properly from here.",
1205        name 'foyer' 'upstairs',
1206   has  ;
1207
1208 !-----------------------------------------------
1209
1210 Room  upstairs_landing "Upstairs Landing"
1211   with  name 'landing',
1212         description
1213             "A small landing, hanging in the still darkness above the foyer.",
1214         d_to foyer,
1215         n_to upstairs_door,
1216         cant_go "The only exits are north and down.",
1217         lower_name "the upstairs landing",
1218   has   ;
1219
1220 Sight  foyer_from_upstairs_landing "Foyer" upstairs_landing
1221   with description [;
1222        Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_FOYER_);
1223            if (IsIn(former_self,foyer)) {
1224                "From the shadowy landing, you can just make out your former
1225                 self alone in the foyer.";
1226            }
1227            else
1228                "From the shadowy landing, you can see much of the empty
1229                 foyer stretching out below you.";
1230        ],
1231        name 'foyer',
1232   has  ;
1233
1234 !-----------------------------------------------
1235
1236 Room  ground_corridor "First Floor Corridor"
1237   with  name 'first' 'floor' 'ground' 'corridor',
1238         description [;
1239             print "A long north-south corridor, much the same as
1240                    those on the other floors. ";
1241             print "Three gray doors line the eastern wall. The first two have small
1242                    glass windows, peering into darkened laboratories. The third ";
1243             if (ground_equipment_door has open)
1244                 print "is open onto an equipment room.^";
1245             else 
1246                 print "is plain and leads to a small equipment room. All three are closed.^";
1247         ],
1248         s_to ground_door,
1249         se_to saunders_door,
1250         e_to pooley_door,
1251         ne_to ground_equipment_door,
1252         cant_go "The only exits are the three doors lining
1253                  the corridor (south-east, east and north-east) and the automatic door
1254                  back to the foyer (south).",
1255         lower_name "the first floor corridor",
1256   has   ;
1257
1258 FakeDoor  saunders_door "door to the Saunders Lab" ground_corridor
1259   with  name 'door' 'grey' 'gray' 'saunders' 'first' 'lab' 'se' 'south-east',
1260         description "A gray door with a small glass window,
1261                      looking into a darkened lab.
1262                      A small plaque reads: 'Saunders Lab'.",
1263   has   locked scenery;
1264
1265 FakeDoor  pooley_door "door to the Pooley Lab" ground_corridor
1266   with  name 'door' 'grey' 'gray' 'pooley' 'second' 'lab' 'e\\' 'east',
1267         description "A gray door with a small glass window,
1268                      looking into a darkened lab.
1269                      A small plaque reads: 'Pooley Lab'.",
1270   has   locked scenery;
1271   
1272 Prop   door_window "small glass window"
1273   with  name 'small' 'glass' 'window' 'windows',
1274         description "You can't see anything of interest through the glass.",
1275         before [;
1276             Take,PushDir:
1277                 print_ret (The) self, " is fixed in the door.";
1278             Unlock:
1279                 if (IsOfType(second,crowbar))
1280                     <<Attack self>>;
1281                 else
1282                     "The embedded window does not open.";
1283             Open:
1284                 "The embedded window does not open.";            
1285             Attack:
1286               if (AmHolding(crowbar)) {
1287                   print "You swing the crowbar firmly into the small window, 
1288                          but it barely leaves a mark.^";
1289                   return true;
1290               }
1291               else
1292                 "You don't have anything heavy enough to break the window with.";
1293             Search:
1294               <<Examine self>>;             
1295         ],  
1296         found_in ground_corridor basement_corridor,
1297   has   scenery concealed lockable;
1298   
1299 PluralSight doors_in_ground_corridor "doors" ground_corridor
1300   with  name 'doors',
1301         description [;
1302               print "There are three doors on the eastern wall of the corridor, 
1303                      the first two (to the south-east and east) lead to the Saunders
1304                      and Pooley labs. The third (to the north-east) ";
1305               if (ground_equipment_door has open)
1306                   print "is open and ";
1307               print "leads to a small equipment room. To the south, the plate glass
1308                      automatic door to the foyer ";
1309               if (ground_door has open)
1310                   print "lies open.^";
1311               else
1312                   print "stands closed.^";
1313         ],
1314   has   pluralname;
1315
1316 !-----------------------------------------------
1317
1318 Room  basement_corridor "Basement Corridor"
1319   with  name 'basement' 'corridor',
1320         description [;
1321             print "A long north-south corridor, much the same as
1322                    those on the other floors. ";
1323             print "Three gray doors line the eastern wall. The first two have small
1324                    glass windows, peering into darkened laboratories. The third ";
1325             if (basement_equipment_door has open)
1326                 print "is open onto an equipment room.^^";
1327             else 
1328                 print "is plain and leads to a small equipment room. All three are closed.^^";
1329             if (deutsch_door has open)
1330                 print "At the north end is an
1331                        open door leading to the Deutsch lab.^";
1332             else
1333                 print "At the north end a fourth door leads to
1334                        the Deutsch lab.^";
1335         ],
1336         s_to basement_door,
1337         se_to bostrom_door,
1338         e_to wallace_door,
1339         ne_to basement_equipment_door,
1340         n_to deutsch_door,
1341         cant_go "The only exits are to the Deutsch lab (north) the three doors lining
1342                  the corridor (south-east, east and north-east) and the automatic door
1343                  back to the landing (south).",
1344         lower_name "the basement corridor",
1345   has   ;
1346
1347 FakeDoor  bostrom_door "door to the Bostrom Lab" basement_corridor
1348   with  name 'door' 'grey' 'gray' 'bostrom' 'first' 'lab' 'se' 'south-east',
1349         description "A gray door with a small glass window,
1350                      looking into a darkened lab.
1351                      A small plaque reads: 'Bostrom Lab'.",
1352   has   locked scenery;
1353
1354 FakeDoor  wallace_door "door to the Wallace Lab" basement_corridor
1355   with  name 'door' 'grey' 'gray' 'wallace' 'second' 'lab' 'e\\' 'east',
1356         description "A gray door with a small glass window,
1357                      looking into a darkened lab.
1358                      A small plaque reads: 'Wallace Lab'.",
1359   has   locked scenery;
1360
1361 PluralSight doors_in_basement_corridor "doors" basement_corridor
1362   with  name 'doors',
1363         description [;
1364               print "There are three doors on the eastern wall of the corridor, 
1365                      the first two (to the south-east and east) lead to the Bostrom
1366                      and Wallace labs. The third (to the north-east) ";
1367               if (basement_equipment_door has open)
1368                   print "is open and ";
1369               print "leads to a small equipment room. At the north end is the ";
1370               if (deutsch_door has open)
1371                   print "open ";
1372               print "door to the Deutsch lab. ";
1373               print "To the south, the plate glass automatic door to the landing ";
1374               if (basement_door has open)
1375                   print "lies open.^";
1376               else
1377                   print "stands closed.^";
1378         ],
1379   has   pluralname;
1380
1381 !-----------------------------------------------
1382
1383 Room  upstairs_corridor "Second Floor Corridor"
1384   with  description
1385             "A long north-south corridor, much the same as
1386              those on the other floors. Three plain gray doors line the eastern wall.",
1387         n_to balcony_door,
1388         ne_to conference_door,
1389         e_to butterfield_door,
1390         se_to brown_door,
1391         s_to upstairs_door,
1392         cant_go "The only exits are to the balcony (north) the three doors lining
1393                  the corridor (south-east, east and north-east) and the automatic door
1394                  back to the landing (south).",
1395         lower_name "the second floor corridor",
1396   has   ;
1397
1398 FakeDoor  brown_door "door to Dr Brown's office" upstairs_corridor
1399   with  name 'door' 'grey' 'gray' 'brown' 'office' 'brown^s' 'Dr' 'first' 'se' 'south-east',
1400         description "A simple gray door.
1401                      A small plaque reads: 'Dr Brown'.",
1402   has   locked scenery;
1403
1404 FakeDoor  butterfield_door "door to Professor Butterfield's office" upstairs_corridor
1405   with  name 'door' 'office' 'grey' 'gray' 'butterfield' 'butterfield^s' 'Prof' 'second'
1406              'e\\' 'east',
1407         description "A simple gray door.
1408                      A small plaque reads: 'Prof Butterfield'.",
1409   has   locked scenery;
1410
1411 FakeDoor  conference_door "door to the conference room" upstairs_corridor
1412   with  name 'door' 'grey' 'gray' 'conference' 'third' 'ne' 'north-east',
1413         description "A plain gray door.
1414                      A small plaque reads: 'Conference Room'.",
1415         found_in upstairs_corridor conference_room,
1416   has   locked scenery;
1417
1418 PluralSight doors_in_upstairs_corridor "doors" upstairs_corridor
1419   with  name 'doors',
1420         description [;
1421               print "There are three doors on the eastern wall of the corridor, 
1422                      the first two (to the south-east and east) lead to Dr Brown
1423                      and Professor Butterfield's offices. The third (to the north-east) 
1424                      leads to the conference room. At the north end is the ";
1425               if (balcony_door has open)
1426                   print "open ";
1427               print "glass door to the balcony. ";
1428               print "To the south, the plate glass automatic door to the landing ";
1429               if (upstairs_door has open)
1430                   print "lies open.^";
1431               else
1432                   print "stands closed.^";
1433         ],
1434   has   pluralname;
1435
1436 !-----------------------------------------------
1437
1438 Room  deutsch_lab "The Deutsch Laboratory"
1439   with  name 'lab' 'deutsch' 'laboratory',
1440         description [;
1441             if (self hasnt visited) {
1442                 print "The lab is order and chaos. By the dim blue-green light of a few swirling
1443                 screen savers, you can see the cluttered benches of your colleagues, frozen in the
1444                 mess of academic creativity. Frozen exactly as they were when badges were flashed,
1445                 when we looked on in disbelief as they took control of the lab. Yours however, is clean.
1446                 The books and papers are in neat stacks. They have been working here.^
1447                 ^
1448                 Nearby, against the north wall is the prototype, a six foot cylinder of brushed steel cladding.
1449                 The door has been taken off and is nowhere to be seen. They have been working on it too.
1450                 You wince at the sight.^";
1451
1452                 if (deutsch_door has open)
1453                     print "^To the south, the door to the lab lies open.^";
1454                 else
1455                     print "^To the south, the door to the lab stands closed.^";     
1456                 
1457                 return true;
1458             }
1459             print "The lab is order and chaos. By the dim blue-green light of a few swirling
1460                 screen savers, you can see the cluttered benches of your colleagues, frozen in the
1461                 mess of academic creativity. Yours however, is clean.
1462                 The books and papers are in neat stacks. They have been working here.^
1463                 ^
1464                 Nearby, against the north wall is the prototype, a six foot cylinder of brushed steel cladding.
1465                 They have been working on it too.
1466                 The door has been taken off and is nowhere to be seen.^";
1467                 
1468             if (deutsch_door has open)
1469                 "^To the south, the door to the lab lies open.";
1470             else
1471                 "^To the south, the door to the lab stands closed.";
1472         ],
1473         out_to deutsch_door,
1474         s_to deutsch_door,
1475         in_to prototype_interior,
1476         cant_go "The only exits are to the south and in to the prototype.",
1477         lower_name "the Deutsch laboratory",
1478   has   proper;
1479
1480   
1481 Object  prototype "prototype"
1482   with  description [;
1483             if (~~prototype_seen) {
1484                 prototype_seen = true;
1485                 print "You had built the prototype to get a strong negative result,
1486                     to show that the standard model of Quantum Mechanics
1487                     led to demonstrably false claims involving reverse causation. You were mistaken.
1488                     One by one, your experiments showed your preliminary calculations to have been correct.
1489                     When the military removed you from your project, only one aspect
1490                     remained untested  -- an aspect
1491                     you had been loath to test before you could predict the results -- inconsistent observation.^
1492                     ^
1493                     What would happen if anomalies were observed by those in the original
1494                     time-line? Your prior experiments had heavily shielded the prototype from outside interaction
1495                     to avoid the very possibility. And as the calculations came out time and again,
1496                     that is the only reason you are alive today.
1497                     When an observer in the original time-line has an anomalous observation, the wave
1498                     function of the temporally relocated object collapses and the relocation retrospectively fails,
1499                     preserving chronological consistency. There is just one side effect:
1500                     total transformation of the object's mass into a burst of photons -- pure energy.^
1501                     ^
1502                     You tried to tell them over and again. They assumed you were merely jealous of the takeover.
1503                     Now, the night before their scheduled 'first main experiment', you have come to 
1504                     put an end to it all. To destroy your prototype and avoid tomorrow's nightmare.^
1505                     ^
1506                     The prototype itself is a six foot tall, four foot wide cylinder, clad with
1507                     brushed steel. The frame and door were fitted with quantum shielding
1508                     to prevent decoherence of the wave function, but now the door has been
1509                     removed and any use of the machine is potentially disastrous.^";
1510             }
1511             else 
1512                 print "The prototype is a six foot tall, four foot wide cylinder clad with
1513                        brushed steel. The frame and door were fitted with quantum shielding
1514                        to prevent decoherence of the wave function, but now the door has been
1515                        removed and any use of the machine is potentially disastrous.^";
1516             if (~~(self.fixed))
1517                 "^On close inspection, it appears that an attempt is in progress
1518                  to move the control panel so that it can be operated from the inside.
1519                  As it is, the prototype is currently not functioning, but you think
1520                  you could probably complete the modification within a minute or two.";
1521             return true;
1522         ],
1523         name 'prototype' 'time' 'machine' 'six' 'foot' 'cylinder',
1524         fixed,
1525         before [t;
1526           Set:
1527             if (self.fixed) {
1528                 if (self in deutsch_lab)
1529                     "The prototype has been modified so that the only way to operate it is
1530                      to enter it and use the internal control panel.";
1531                 if (self in prototype_interior)
1532                     <<Set control_panel>>;
1533             }
1534             else
1535                 "You will need to complete the partial modifications to use the prototype.";
1536           SetTo:
1537             if (self.fixed) {
1538                 if (self in deutsch_lab)
1539                     "The prototype has been modified so that the only way to operate it is
1540                      to enter it and use the internal control panel.";
1541                 if (self in prototype_interior)
1542                     <<SetTo control_panel second>>;
1543             }
1544             else
1545                 "You will need to complete the partial modifications to use the prototype.";
1546           SwitchOn:
1547             if (self.fixed) {
1548                 if (self in deutsch_lab)
1549                     "The prototype has been modified so that the only way to operate it is
1550                      to enter it and use the internal control panel.";
1551                 if (self in prototype_interior) {
1552                     print "(pressing the silver button)^";
1553                     <<Push silver_button>>;
1554                 }
1555             }
1556             else
1557                 "You will need to complete the partial modifications to use the prototype.";
1558           Enter:
1559             <<Go in_obj>>;
1560           Exit:
1561             if (real_location == prototype_interior)
1562                    <<Go out_obj>>;
1563           Tie:
1564             if (~~d_paradox) {
1565                 if (second == nothing) {
1566                     if (self.fixed)
1567                         "It is already fixed.";
1568                     if (AmHolding(cable)) {
1569                         if (self in deutsch_lab) {
1570                             print "(first entering the prototype)^";
1571                             <Go in_obj>;
1572                             IncTime();
1573                             if (Stopped()) return true;
1574                             print "^";
1575                         }
1576                         move GetHeld(cable) to limbo;
1577                         print "You begin work completing the modifications...^";
1578                         for (t=0 : t<10 : t++) {
1579                             IncTime();
1580                             if (Stopped()) return true;
1581                         }
1582                         self.fixed = true;
1583                         prototype_fixed_time = my_time;
1584                         print "After a minute or so, you are done.^";
1585                         return true;
1586                     }
1587                     else
1588                         "After a few moments, you realise that completing the modification
1589                          will require a ribbon cable to connect the components. You know the
1590                          type of cable well, but don't have any in the lab right now.
1591                          Still, the equipment room in the corridor should have one.";          
1592                 }
1593             }
1594           Attack:
1595             "It won't be enough to smash the prototype by hand as there are too many
1596              circuits buried away inside that would not be harmed.
1597              Besides, that is why you brought the bomb.";
1598           Search:
1599             if (self in deutsch_lab) {
1600                 print "(first entering the prototype)^";
1601                 <<Go in_obj>>;
1602             }
1603             else
1604                 <<Look>>;
1605         ],
1606         react_before[;
1607           Insert:
1608             if (~~(self.fixed))
1609                 if (IsOfType(noun,cable))
1610                     if ((second == self) || (second == control_panel))
1611                         <<Tie prototype>>;
1612             if (second == self) {
1613                 if (noun == self)
1614                     "It wont fit. Obviously. What were you thinking? It is a prototype
1615                      chrono-transference device, not some kind of TARDIS.";
1616                 if (self in deutsch_lab) {
1617                     move noun to prototype_interior;
1618                     print "You reach in and place ", (the) noun, " inside the prototype.^";
1619                     return true;
1620                 }
1621                 else
1622                     <<Drop noun>>;
1623             }
1624         ],
1625         found_in deutsch_lab prototype_interior,
1626   has   scenery concealed;
1627
1628 Furniture  bench "your bench" deutsch_lab
1629   with  description "Your bench has clearly been used recently, and not by you.",
1630         before [;
1631           Examine:
1632             print "Your bench has clearly been used recently, and not by you.
1633                    Your books and papers are neatly piled to one side, leaving
1634                    the largest expanse of bare desk you have ever seen here.^";
1635             if (~~have_looked_at_bench) {
1636                 have_looked_at_bench = true;
1637                 "^You suddenly notice that your research notes are not here.
1638                  You were sure they would be -- and would thus be destroyed in the blast.
1639                  This is bad. Very bad.";
1640             }
1641             return true;
1642           Search:
1643             <<Examine self>>;
1644         ],
1645         name 'bench' 'your' 'benches' 'table' 'desk',
1646   has   scenery proper;
1647
1648 Prop books "text books" deutsch_lab
1649   with  description "A few texts on Quantum Mechanics and String Theory
1650                      that have served you very well.",
1651         name 'books' 'book' 'texts',
1652   has;
1653
1654 Prop papers "papers" deutsch_lab
1655   with  description [;
1656             print "A collection of photocopied journal papers that you had been reading
1657                    a few weeks ago.^";
1658             if (~~have_looked_at_bench) {
1659                 have_looked_at_bench = true;
1660                 "^You suddenly notice that your research notes are not here.
1661                  You were sure they would be -- and would thus be destroyed in the blast.
1662                  This is bad. Very bad.";
1663             }
1664             return true;
1665         ],
1666         name 'papers' 'photocopies' 'stack' 'stacks',
1667   has;
1668
1669 Prop screen_savers "screen savers" deutsch_lab
1670   with  description "Abstract, organic shapes leave glowing phosphor trails as they swirl around
1671                      and through themselves.",
1672         name 'screen' 'screens' 'saver' 'savers' 'computer' 'computers' 'light' 'violet' 'green' 'blue'
1673              'blue-green' 'swirling',
1674   has;
1675
1676 Prop cladding "cladding" deutsch_lab
1677   with  name 'cladding' 'steel' 'brushed' 'frame' 'hatch',
1678   has;
1679
1680 Prop mess "mess" deutsch_lab
1681   with  description "The usual academic mess -- open books, coffee stained mugs, sprawling papers
1682                      -- frozen in time.",
1683         name 'mess' 'chaos',
1684   has;
1685
1686 Sight control_panel_from_lab "control panel" deutsch_lab
1687   with  description "You cannot see the control panel clearly from here, and would need to enter the prototype.",
1688         name 'control' 'panel',
1689         before [;
1690             Push:
1691                 <<Tie prototype>>;
1692             Examine:
1693                 "You cannot see the control panel clearly from here, and would need to enter the prototype.";
1694             default:
1695                 "You would have to enter the prototype to do that.";
1696         ],
1697   has;
1698
1699 !-----------------------------------------------
1700
1701 Room  prototype_interior "Inside the prototype"
1702   with  description [;
1703             if (prototype.fixed) {
1704                 print "The interior of the prototype is cramped and dark.
1705                        On the wall you see the control panel with a small LED timer
1706                        set to ", control_panel.time_value, " seconds, and a silver button.
1707                        Through the open hatch you can see some of the Deutsch lab.^";
1708             }
1709             else
1710                 "The interior of the prototype is cramped and dark. 
1711                  On the wall you can see the half-installed control panel.
1712                  Through the open hatch you can see some of the Deutsch lab.";
1713          ],
1714         name 'prototype' 'time' 'machine' 'interior',
1715         out_to deutsch_lab,
1716         lower_name "the prototype",
1717         cant_go "The only exit is out to the Deutsch lab.",
1718   has proper;
1719
1720 Object control_panel "control panel" prototype_interior
1721   with  name 'control' 'panel' 'led' 'timer' 'time' 'screen', 
1722         description [;
1723             print "A brushed steel control panel with a blue LED timer, set to ", 
1724                    control_panel.time_value, " seconds, and a shiny silver button.^";
1725             ],
1726         time_value,
1727         before [;
1728           Push:
1729             <<Tie prototype>>;
1730           Set:
1731             if (prototype.fixed)
1732                 "To set the control panel,
1733                  you need to specify a number of seconds,
1734                  for example, with 'set panel to 75'.";
1735             else
1736                 "You won't be able to set the control panel
1737                  until you complete the modifications.";
1738           SetTo:
1739             if (prototype.fixed) {
1740                 if (second > 0 && second <= 500) {
1741                     self.time_value = second;
1742                     "You quickly type the number in to the control panel.";
1743                 }
1744                 else {
1745                     "The prototype's control panel only accepts
1746                      between 1 and 500 seconds.";
1747                 }
1748             }
1749             else
1750                 "You won't be able to set the control panel
1751                  until you complete the modifications.";
1752           SwitchOn:
1753             if (self.fixed) {
1754                 print "(pressing the silver button)^";
1755                 <<Push silver_button>>;
1756             }
1757             else
1758                 "You will need to complete the partial modifications to use the prototype.";
1759         ],
1760   has scenery concealed;
1761
1762 Object silver_button "silver button" prototype_interior
1763   with  name 'button' 'silver' 'silvered',
1764         description "A silvered button.",
1765         before [old_value t;
1766           Push:
1767             if (prototype.fixed) {
1768                 if (control_panel.time_value == 0)
1769                     "The control panel emits a small beep and the number '0'
1770                      flashes out at you. Perhaps you should set it first.";
1771                 else if (time_travelled < MAX_TIME_TRAVELS) {
1772                     old_value = control_panel.time_value;
1773                     TravelThroughTime(control_panel.time_value);
1774                     if (deadflag)
1775                         return true;
1776                     for (t=0 : t < time_travelled : t++)
1777                         if ((Get2D(player_loc,t,my_time-EARLIEST_TIME) == deutsch_lab) ||
1778                             (Get2D(player_loc,t,my_time-EARLIEST_TIME) == prototype_interior))
1779                                 "You hold your breath and activate the prototype.";
1780                                 ! this is needed to avoid silly message below, then death
1781                     if ((old_value % 5) ~= 0)
1782                         "You pause for a moment after pressing the button,
1783                          carefully resynchronizing yourself with the 
1784                          five second turn increments.";
1785                     else 
1786                         "You hold your breath and activate the prototype.";
1787                 }
1788                 else
1789                     "Nothing happens.";
1790             }
1791             else
1792                 "The button won't work
1793                  until you complete the modifications.";
1794           Receive:
1795             "The button is set into a vertical surface, making it impossible
1796              to place objects on top of it.";
1797         ],
1798   has scenery concealed;
1799
1800 Sight deutsch_lab_from_prototype "Deutsch lab" prototype_interior
1801   with  description "You can't make out much of interest from here, just a few benches
1802                      under the shifting blue-violet-green light.",
1803         name 'deutsch' 'lab' 'hatch' 'bench' 'benches',
1804   has;
1805
1806 Prop surface "inside surface" prototype_interior
1807   with name 'walls' 'interior' 'surface' 'ceiling' 'floor' 'ground',
1808        description "The interior of the prototype is clad
1809                     in smooth brushed steel.",
1810   has  ;
1811 !-----------------------------------------------
1812
1813 Room  basement_equipment "Basement Equipment Room"
1814   with  name 'equipment' 'room',
1815         description [;
1816             if (FlashLit()) {
1817                 MoveMoveableChildren(basement_equipment_gloom,self);
1818                 print "By the thin blue-white beam of your flashlight, you
1819                        see the crowded shelves of the equipment room.^";
1820                 if (basement_equipment_door has open)
1821                     print "^To the west, the door to the corridor lies open.^";
1822                 else
1823                     print "^To the west, the door to the corridor stands closed.^";
1824             }
1825             else {
1826                 MoveMoveableChildren(self,basement_equipment_gloom);
1827                 if (basement_equipment_door has open)
1828                     print "It is almost completely dark. Some faint light spills
1829                            in from the west through the open door, allowing you to just
1830                            discern the outlines of a series of shelves. By the door is
1831                            a light switch.^";
1832                 else
1833                     print "You are in complete darkness.^";
1834             }
1835         ],
1836         out_to basement_equipment_door,
1837         w_to basement_equipment_door,
1838         sw_to [;<<Go w_obj>>;],
1839         cant_go "The only exit is westwards, back to the corridor.",
1840         lit false,
1841         has_been_lit false,
1842         lower_name "the basement equipment room",
1843   has   ;
1844
1845 ! A behind-the-scenes 'room' to store the items that should be hidden while the
1846 ! basement equipment room is in darkness
1847
1848 Room  basement_equipment_gloom "Dark Basement Equipment Room"
1849   with  name 'equipment' 'room' 'dark',
1850         lower_name "the dark basement equipment room",
1851   has   ;
1852   
1853 Object basement_light_switch "light switch" basement_equipment
1854   with  name 'switch' 'light' 'lights',
1855         before [;
1856           Push:
1857             <<SwitchOn basement_light_switch>>;
1858           SwitchOn:
1859             if (~~self.blown) {
1860                 Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,BLOW_BASEMENT_LIGHT_);
1861                 self.blown = true;
1862                 if (FlashLit())
1863                     "The fluorescent lights flicker hopefully, strobing rapidly across the
1864                      scattered equipment. Then darkness. You blink away the after-images
1865                      and are left with only the faint torchlight.";
1866                 else
1867                     "The fluorescent lights flicker hopefully, strobing rapidly across the
1868                      scattered equipment. Then darkness. Nothing but a few fleeting
1869                      after-images of the cluttered room.";                
1870             }
1871             else
1872                 "Click. Nothing happens.";
1873         ],
1874         react_before [;
1875           Go:
1876             MoveMoveableChildren(basement_equipment,basement_equipment_gloom);
1877         ],
1878         react_after [;
1879           Drop:
1880             if (~~(FlashLit())) {
1881                 move noun to basement_equipment_gloom;
1882             }
1883           Go:
1884             if (basement_equipment.lit || FlashLit()) {
1885                 MoveMoveableChildren(basement_equipment_gloom,basement_equipment);
1886             }
1887         ],
1888         blown false,
1889   has static scenery concealed switchable;
1890   
1891 !-----------------------------------------------
1892
1893 Room  ground_equipment "First Floor Equipment Room"
1894   with  name 'equipment' 'room',
1895         description [;
1896             if (self.lit) {
1897                 MoveMoveableChildren(ground_equipment_gloom,self);
1898                 print "By the flickering fluorescent lights, you
1899                        see the crowded shelves of the equipment room.^";
1900                 if (ground_equipment_door has open)
1901                     print "^To the west, the door to the corridor lies open.^";
1902                 else
1903                     print "^To the west, the door to the corridor stands closed.^";
1904             }
1905             else {
1906                 if (FlashLit()) {
1907                     MoveMoveableChildren(ground_equipment_gloom,self);
1908                     print "By the thin blue-white beam of your flashlight, you
1909                            see the crowded shelves of the equipment room.^";
1910                     if (ground_equipment_door has open)
1911                         print "^To the west, the door to the corridor lies open.^";
1912                     else
1913                         print "^To the west, the door to the corridor stands closed.^";
1914                 }
1915                 else {
1916                     MoveMoveableChildren(self,ground_equipment_gloom);
1917                     if (ground_equipment_door has open)
1918                         print "It is almost completely dark. Some faint light spills
1919                                in from the west through the open door, allowing you to just
1920                                discern the outlines of a series of shelves. By the door is
1921                                a light switch.^";
1922                     else
1923                         print "You are in complete darkness.^";
1924                 }
1925             }
1926         ],
1927         out_to ground_equipment_door,
1928         w_to ground_equipment_door,
1929         sw_to [;<<Go w_obj>>;],
1930         cant_go "The only exit is westwards, back to the corridor.",
1931         lit false,
1932         has_been_lit false,
1933         lower_name "the first floor equipment room",
1934   has   ;
1935
1936 Room  ground_equipment_gloom "Dark First Floor Equipment Room"
1937   with  name 'equipment' 'room' 'dark',
1938         lower_name "the dark first floor equipment room",
1939   has   ;
1940
1941 Object ground_light_switch "light switch" ground_equipment
1942   with  name 'switch' 'light' 'lights',
1943         before [;
1944           Push:
1945             if (~~ground_equipment.lit) {
1946                 <<SwitchOn ground_light_switch>>;
1947             }
1948             else {
1949                 <<SwitchOff ground_light_switch>>;
1950             }
1951           SwitchOn:
1952             if (~~ground_equipment.lit) {
1953                 ground_equipment.lit = true;
1954                 give self on;
1955                 print "The lights come on after a brief flicker.^";
1956                 <Look>;
1957                 instant_action_this_turn = false;
1958                 return true;
1959             }
1960           SwitchOff:
1961             if (ground_equipment.lit) {
1962                 ground_equipment.lit = false;
1963                 give self ~on;
1964                 if (FlashLit())
1965                     "The lights flicker briefly, then go out,
1966                      leaving you in the faint torchlight.";                  
1967                 else {
1968                     MoveMoveableChildren(ground_equipment,ground_equipment_gloom);
1969                     "The lights flicker briefly, then go out,
1970                      leaving you in the darkness.";
1971                 }
1972             }
1973         ],
1974         react_before [;
1975           Go:
1976             if (~~(ground_equipment.lit))
1977                 MoveMoveableChildren(ground_equipment,ground_equipment_gloom);
1978         ],
1979         react_after [;
1980           Drop:
1981             if (~~(ground_equipment.lit || FlashLit())) {
1982                 move noun to ground_equipment_gloom;
1983             }
1984           Go:
1985             if ((ground_equipment.lit) || FlashLit()) {
1986                 MoveMoveableChildren(ground_equipment_gloom,ground_equipment);
1987             }
1988         ],
1989   has static scenery concealed switchable;
1990
1991 Prop  shelves "shelves"
1992   with  name 'shelf' 'shelves' 'equipment' 'series' 'outlines' 'outline' 'clutter' 'cluttered',
1993         description [;
1994             if (((parent(self)).lit) || (Flashlit()))
1995                 "The shelves are filled with assorted lab equipment, but nothing of use
1996                  to you now.";
1997             else
1998                 "You cannot make out any of the objects on the dark shelves.";
1999         ],
2000         found_in ground_equipment basement_equipment,
2001   has   ;
2002
2003 Prop  fluoro_light "fluorescent lights"
2004   with  name 'fluoro' 'fluorescent' 'flicker' 'flickering' 'tube',
2005         description [;
2006             if ((parent(self)).lit) 
2007                 "The fluorescent tubes flicker brightly.";
2008             else
2009                 "You can just make out a dark fluorescent tube in the ceiling above.";
2010         ],
2011         found_in ground_equipment basement_equipment,
2012   has   ;
2013
2014 !-----------------------------------------------
2015
2016 Room  balcony "Balcony"
2017   with  name 'balcony',
2018         description
2019             "A wide balcony, looking out over the sleeping city. Below you, a lawn slopes gently away
2020              into the gloom, a few silhouetted trees marking the edge of the modest grounds. Above, the
2021              clear sky is a deep black, dusted with glinting stars.",
2022         d_to [;Jumped(); return true;],
2023         n_to [;Jumped(); return true;],
2024         s_to balcony_door,
2025         se_to conference_window,
2026         in_to conference_window,
2027         cant_go [;
2028             if (conference_window has open)
2029                 "The only exits are the door back to the corridor (to the south)
2030                  and the window into the conference room (to the south-east).";
2031             else
2032                 "The only exit is the door back to the corridor (to the south).";
2033         ],
2034         lower_name "the balcony",
2035   has   ;
2036
2037 Prop   balcony_floor "floor" balcony
2038   with name 'floor' 'ground' 'tiles',
2039        description "The floor is covered in white tiles.",
2040   has  ;
2041
2042 Prop   railing "railing" balcony
2043   with name 'rail' 'railing' 'hand' 'handrail',
2044   has  ;
2045
2046 Sight  trees "trees" balcony
2047   with name 'tree' 'trees' 'silhouette' 'silhouettes' 'cypress' 'cypresses' 'conifer' 'conifers',
2048        description "The trees are some kind of tall conifer, cypress perhaps. You have fond
2049                     memories of dozing under them one afternoon last summer.",
2050   has  ;
2051
2052 Sight  grounds "grounds" balcony
2053   with name 'lawn' 'slope' 'slopes' 'grounds' 'grass' 'gloom',
2054        description "The grounds are little more than a well-kept lawn and a few tall trees, but
2055                     every night the security guard has to give them a brief inspection.",
2056   has  ;
2057
2058 Sight  guard "guard" balcony
2059   with name 'guard' 'security' 'guards',
2060        description "There is no sign of the security guard.",
2061   has  ;
2062
2063 Sight  stars "stars"
2064   with name 'stars' 'star' 'black' 'dust' 'constellations',
2065        description "The stars are a beautiful spray of glinting jewels in the blackness above.",
2066        found_in balcony conference_room,
2067   has  ;
2068
2069 Sight  night "night"
2070   with name 'night' 'starry',
2071        description "Outside, it is one of the finest fall nights you can recall.",
2072        found_in balcony conference_room,
2073   has  ;
2074
2075 Sight  city "city"
2076   with name 'city' 'boston' 'town' 'light' 'rooftops' 'roofs' 'skyscrapers' 'buildings' 'building',
2077        description "Before you, lie the rooftops and skyscrapers of your home town. Here and there
2078                     a small yellow light glows, but for now Boston sleeps.",
2079        found_in balcony conference_room,
2080   has  ;
2081
2082
2083 !-----------------------------------------------
2084
2085 Room  conference_room "Conference Room"
2086   with  name 'conference',
2087         description "A rather slick but soulless affair. A large table of dark polished wood
2088                      takes pride of place and is surrounded by a half-dozen chairs.",
2089         n_to conference_window,
2090         nw_to conference_window,
2091         out_to conference_window,
2092         w_to conference_door,
2093         cant_go "The only exits are the door to the west and the window to the north.",
2094         lower_name "the conference room",
2095   has   ;
2096   
2097 Sight  conference_room_sight "room" conference_room
2098   with name 'room' 'conference',
2099        description "A rather slick but soulless affair.",
2100        before [;
2101          Exit:
2102              <<Go n_obj>>;
2103        ],
2104   has  ;
2105
2106 Furniture  conference_table "conference table" conference_room
2107   with  description "A large round table of dark polished wood.",
2108         name 'table' 'round' 'large' 'polished' 'dark' 'wood',
2109   has   scenery;
2110
2111 Furniture  chair "chair" conference_room
2112   with  description "Each chair is of a rather elegant, modern design
2113                      in the same dark wood as the table.",
2114         name 'chair' 'chairs' 'seat' 'seats',
2115   has   scenery concealed;
2116
2117 !-----------------------------------------------
2118
2119 Room  outside "Outside"
2120   with  description "Outside the lab, the street is quiet.",
2121         n_to main_doors,
2122         lower_name "the night",
2123   has   ;
2124
2125 !-----------------------------------------------
2126
2127 Room  limbo "Night"
2128   with  description "The waiting place for unrealised items.",
2129         lower_name "the night",
2130   has   ;
2131
2132
2133 !------------------------------------------------------------------------
2134 !
2135 !  Door stuff
2136 !
2137
2138 AutomaticDoor  main_doors "main doors" foyer
2139   with  description [;
2140            if (self has open)
2141                print "Through the open doors, you can see the quiet grounds.
2142                       On the right hand side is a green button.^";
2143            else
2144                print "A pair of ";
2145                if (self.smashed) print "cracked ";
2146                print "plate glass sliding doors, 
2147                       through which you can see the quiet grounds.
2148                       On the right hand side is a green button.^";
2149         ],
2150         when_closed "To the south is a set of automatic doors leading
2151                     out into the inky night.",
2152         when_open "To the south is an open set of automatic doors leading
2153                     out into the inky night.",
2154         name 'doors' 'main' 'south' 'plate' 'glass' 'sliding' 'set' 'auto',
2155         door_to [;Escaped(); return true;],
2156         door_dir s_to,
2157         open_self [t;
2158             if (self hasnt open) {
2159                 give self open ~locked;
2160                 if (self in LocationOf(player))
2161                     print "The main doors open onto the night.^";
2162             }
2163             self.to_close_at = t;
2164             if ((player in foyer) && (my_time < start_time-1) && (my_time >= start_time-3)) {
2165                 d_paradox = true;
2166                 deadflag = 3;
2167                 Seperator();
2168                 print "Outside, your former self darts quickly towards the main doors.
2169                        When she sees them open, she breaks her stride
2170                        and lets out a shocked gasp.^";
2171                 print "^Time unravels...^";
2172                 Devours(my_time);   
2173             }
2174         ],
2175         closing_message [;
2176             if ((~~Stopped()) && (self in LocationOf(player)))
2177                 "The main doors softly slide closed.";
2178         ],
2179         before [; 
2180         Open:
2181             print "(pressing the green exit button)^";
2182             <<Push exit_button>>;
2183         Unlock:
2184            if (IsOfType(second,crowbar))
2185                <<Attack self>>;
2186            else
2187                "You cannot open the door with that.";
2188         Enter:
2189           if (self hasnt open) {
2190               print "(first pressing the green exit button)^";
2191               <Push exit_button>;
2192               IncTime();
2193               if (Stopped()) return true;
2194               <<Go s_obj>>;
2195           }
2196         ],
2197         react_before [; Go:
2198             if (noun == s_to && self hasnt open)
2199                 <<Enter self>>;
2200         ],
2201   has   pluralname;
2202
2203
2204 AutomaticDoor  ground_door "automatic door"
2205   with  description [;
2206           if (self in foyer) {
2207               Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_GROUND_CORRIDOR_);
2208               print "A ";
2209               if (self.smashed) print "cracked ";
2210               print "plate glass sliding door, 
2211                      through which you can see a dim corridor. ";
2212               if (IsIn(former_self,ground_corridor))
2213                   print "In the shadows stands your past self. ";
2214               print "On the right hand side is a slot for an ID card.^";
2215           }
2216           if (self in ground_corridor) {
2217               Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_FOYER_);
2218               print "A ";
2219               if (self.smashed) print "cracked ";
2220               print "plate glass sliding door, 
2221                      through which you can see the darkened foyer. ";
2222               if (IsIn(former_self,foyer))
2223                   print "In the shadows stands your past self. ";
2224               print "On the right hand side is a green button.^";
2225           }
2226         ],
2227         when_closed [;
2228           if (self in foyer)
2229                     "In the north wall is a closed
2230                      automatic door.";
2231           if (self in ground_corridor)
2232                     "To the south is a closed automatic door, leading back
2233                      to the foyer.";
2234
2235         ],
2236         when_open [;
2237           if (self in foyer)
2238                     "In the north wall is an open
2239                      automatic door.";
2240           if (self in ground_corridor)
2241                     "To the south is an open automatic door, leading back
2242                      to the foyer.";
2243
2244         ],
2245         name 'north' 'door' 'automatic' 'auto' 'plate' 'glass' 'sliding',
2246         door_to [;
2247           if (self in foyer)
2248               return ground_corridor;
2249           if (self in ground_corridor)
2250               return foyer;
2251
2252         ],
2253         door_dir [;
2254           if (self in foyer)
2255               return n_to;
2256           if (self in ground_corridor)
2257               return s_to;
2258
2259         ],
2260         before [; 
2261         Unlock:
2262            if (IsOfType(second,crowbar))
2263                <<Attack self>>;
2264            else if (IsOfType(second,id_card) && (self in foyer))
2265                <<Insert second id_slot>>;
2266            else
2267                "You cannot open the door with that.";
2268         Open:
2269           if (self in foyer)
2270               if (self.known_exterior_opening == 0)
2271                   "There is no obvious way to get 
2272                    the automatic door to open.";
2273               else {
2274                   print "You press the button marked 'first'.^";
2275                   <<Push first_button>>;
2276               }
2277           if (self in ground_corridor) {
2278               print "(pressing the green exit button)^";
2279               <<Push exit_button>>;
2280           }
2281         Enter:
2282           if (self in ground_corridor && self hasnt open) {
2283               print "(first pressing the green exit button)^";
2284               <Push exit_button>;
2285               IncTime();
2286               if (Stopped()) return true;
2287               <<Go s_obj>>;
2288           }
2289           if (self in foyer && self hasnt open) {
2290               if (self.known_exterior_opening == true)  {
2291                   print "(first pressing the button marked 'first')^";
2292                   <Push first_button>;
2293                   IncTime();
2294                   if (Stopped()) return true;
2295                   <<Go n_obj>>;
2296               }
2297               else {
2298                   "There is no obvious way to get 
2299                    the automatic door to open.";
2300               }
2301           }
2302         ],
2303         react_before [; Go:
2304             if (noun == n_to && self in foyer && self hasnt open)
2305                 <<Enter self>>;
2306             if (noun == s_to && self in ground_corridor && self hasnt open)
2307                 <<Enter self>>;
2308         ],
2309         known_exterior_opening,
2310         found_in foyer ground_corridor,
2311   has  ;
2312
2313
2314 AutomaticDoor  basement_door "automatic door"
2315   with  description [;
2316           if (self in basement_landing) {
2317               Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_BASEMENT_CORRIDOR_);
2318               print "A ";
2319               if (self.smashed) print "cracked ";
2320               print "plate glass sliding door, 
2321                      through which you can see a dim corridor. ";
2322               if (IsIn(former_self,basement_corridor))
2323                   print "In the shadows stands your past self. ";
2324               print "On the right hand side is a slot for an ID card.^";
2325           }
2326           if (self in basement_corridor) {
2327               Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_BASEMENT_LANDING_);
2328               print "A ";
2329               if (self.smashed) print "cracked ";
2330               print "plate glass sliding door, 
2331                      through which you can see the small basement landing. ";
2332               if (IsIn(former_self,basement_landing))
2333                   print "In the shadows stands your past self. ";
2334               print "On the right hand side is a green button.^";
2335           }
2336         ],
2337         name 'door' 'automatic' 'auto' 'plate' 'glass' 'sliding',
2338         when_closed [;
2339           if (self in basement_landing)
2340                     "To the north is a closed automatic door.";
2341           if (self in basement_corridor)
2342                     "To the south is a closed automatic door, leading back
2343                      to the landing.";
2344
2345         ],
2346         when_open [;
2347           if (self in basement_landing)
2348                     "To the north is an open automatic door.";
2349           if (self in basement_corridor)
2350                     "To the south is an open automatic door, leading back
2351                      to the landing.";
2352
2353         ],
2354         door_to [;
2355           if (self in basement_landing)
2356               return basement_corridor;
2357           if (self in basement_corridor)
2358               return basement_landing;
2359
2360         ],
2361         door_dir [;
2362           if (self in basement_landing)
2363               return n_to;
2364           if (self in basement_corridor)
2365               return s_to;
2366
2367         ],
2368         before [; 
2369         Unlock:
2370            if (IsOfType(second,crowbar))
2371                <<Attack self>>;
2372            else if (IsOfType(second,id_card) && (self in basement_landing))
2373                <<Insert second id_slot>>;
2374            else
2375                "You cannot open the door with that.";
2376         Open:
2377           if (self in basement_landing) {
2378               if ( AmHolding(id_card) ) {
2379                   print "(inserting your ID card)^";
2380                   <<Insert (GetHeld(id_card)) id_slot>>;
2381               }
2382               else
2383                   "You would need you ID card to do that.";
2384           }
2385           if (self in basement_corridor) {
2386               print "(pressing the green exit button)^";
2387               <<Push exit_button>>;
2388           }
2389         Enter:
2390           if (self in basement_corridor && self hasnt open) {
2391               print "(first pressing the green exit button)^";
2392               <Push exit_button>;
2393               IncTime();
2394               if (Stopped()) return true;
2395               <<Go s_obj>>;
2396           }
2397           if (self in basement_landing && self hasnt open) {
2398               if ( AmHolding(id_card) ) {
2399                   print "(first inserting your ID card)^";
2400                   <Insert (GetHeld(id_card)) id_slot>;
2401                   IncTime();
2402                   if (Stopped()) return true;
2403                   <<Go n_obj>>;
2404               }
2405               else
2406                   "You would need you ID card to do that.";
2407           }
2408         ],
2409         react_before [; Go:
2410             if (noun == n_to && self in basement_landing && self hasnt open)
2411                 <<Enter self>>;
2412             if (noun == s_to && self in basement_corridor && self hasnt open)
2413                 <<Enter self>>;
2414         ],
2415         known_exterior_opening,
2416         found_in basement_landing basement_corridor,
2417   has   ;
2418
2419
2420 AutomaticDoor  upstairs_door "automatic door"
2421   with  description [;
2422           if (self in upstairs_landing) {
2423               Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_UPSTAIRS_CORRIDOR_);
2424               print "A ";
2425               if (self.smashed) print "cracked ";
2426               print "plate glass sliding door, 
2427                      through which you can see a dim corridor. ";
2428               if (IsIn(former_self,upstairs_corridor))
2429                   print "In the shadows stands your past self. ";
2430               print "On the right hand side is a slot for an ID card.^";
2431           }
2432           if (self in upstairs_corridor) {
2433               Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_UPSTAIRS_LANDING_);
2434               print "A ";
2435               if (self.smashed) print "cracked ";
2436               print "plate glass sliding door, 
2437                      through which you can see the upper part of the darkened foyer. ";
2438               if (IsIn(former_self,upstairs_landing))
2439                   print "In the shadows of the landing stands your past self. ";
2440               print "On the right hand side is a green button.^";
2441           }
2442         ],
2443         name 'door' 'automatic' 'auto' 'plate' 'glass' 'sliding',
2444         when_closed [;
2445           if (self in upstairs_landing)
2446                     "On the north wall lies a closed automatic door.";
2447           if (self in upstairs_corridor)
2448                     "To the south is a closed automatic door, leading back
2449                      to the landing.";
2450         ],
2451         when_open [;
2452           if (self in upstairs_landing)
2453                     "On the north wall lies an open automatic door.";
2454           if (self in upstairs_corridor)
2455                     "To the south is an open automatic door, leading back
2456                      to the landing.";
2457         ],
2458         door_to [;
2459           if (self in upstairs_landing)
2460               return upstairs_corridor;
2461           if (self in upstairs_corridor)
2462               return upstairs_landing;
2463         ],
2464         door_dir [;
2465           if (self in upstairs_landing)
2466               return n_to;
2467           if (self in upstairs_corridor)
2468               return s_to;
2469         ],
2470         before [; 
2471         Unlock:
2472            if (IsOfType(second,crowbar))
2473                <<Attack self>>;
2474            else if (IsOfType(second,id_card) && (self in upstairs_landing))
2475                <<Insert second id_slot>>;
2476            else
2477                "You cannot open the door with that.";
2478         Open:
2479           if (self in upstairs_landing)
2480               if (AmHolding(id_card)) {
2481                   print "(inserting your ID card)^";
2482                   <<Insert (GetHeld(id_card)) id_slot>>;
2483               }
2484           if (self in upstairs_corridor) {
2485               print "(pressing the green exit button)^";
2486               <<Push exit_button>>;
2487           }
2488         Enter:
2489           if (self in upstairs_corridor && self hasnt open) {
2490               print "(first pressing the green exit button)^";
2491               <Push exit_button>;
2492               if (self has open) {
2493                   IncTime();
2494                   if (Stopped()) return true;
2495                   <<Go s_obj>>;
2496               }
2497               return true;
2498           }
2499           if (self in upstairs_landing && self hasnt open) {
2500               "There is no obvious way to get the automatic door to open.";
2501           }
2502         ],
2503         react_before [; Go:
2504             if (noun == s_to && self in upstairs_corridor && self hasnt open)
2505                 <<Enter self>>;
2506         ],
2507         found_in upstairs_landing upstairs_corridor,
2508   has   ;
2509
2510 Object  exit_button "green exit button"
2511   with  description "A green button beside the door.",
2512         name 'green' 'button',
2513         before [; Push:
2514             if (self in ground_corridor) {
2515                 ground_door.open_self(my_time+1);
2516             }
2517             if (self in upstairs_corridor) {
2518                 if (challenge)
2519                     "Nothing happens -- the button must be broken.";
2520                 else
2521                     upstairs_door.open_self(my_time+1);
2522             }
2523             if (self in basement_corridor) {
2524                 basement_door.open_self(my_time+1);
2525             }
2526             if (self in foyer) {
2527                 main_doors.open_self(my_time+1);
2528             }
2529             return true;
2530           Receive:
2531             "The button is set into a vertical surface, making it impossible
2532              to place objects on top of it.";
2533         ],
2534        found_in ground_corridor upstairs_corridor basement_corridor foyer,
2535   has  scenery concealed;
2536
2537 Object  id_slot "ID card slot"
2538   with  description "A narrow slot to the right of the door.
2539                      The doors are coded so that only those with legitimate
2540                      business can use their card to gain entrance.",
2541
2542         name 'slot',
2543         found_in foyer upstairs_landing basement_landing,
2544   has   scenery concealed;
2545
2546
2547 ManualDoor  ground_equipment_door "door to the equipment room"
2548   with  name 'door' 'equipment' 'room' 'grey' 'gray' 'third' 'plain' 'ne' 'north-east',
2549         description
2550             "A simple gray door.",
2551         door_to [;
2552           if (self in ground_corridor)
2553               return ground_equipment;
2554           if (self in ground_equipment)
2555               return ground_corridor;
2556         ],
2557         door_dir [;
2558           if (self in ground_corridor)
2559               return ne_to;
2560           if (self in ground_equipment)
2561               return w_to;
2562         ],
2563         before [;
2564           Close:
2565               if (((self in ground_equipment) && IsIn(former_self,ground_corridor)) ||
2566                   ((self in ground_corridor) && IsIn(former_self,ground_equipment)) )  {
2567                       CloseParadox();
2568                       return true;
2569               }
2570           Open:
2571               if (((self in ground_equipment) && IsIn(former_self,ground_corridor)) ||
2572                   ((self in ground_corridor) && IsIn(former_self,ground_equipment)) )  {
2573                       OpenParadox();
2574                       return true;
2575               }
2576               else
2577                   return (OpenManualDoor(self,second));
2578           Unlock:
2579               if (IsOfType(second,crowbar))
2580                   <<Attack self>>;
2581               if (((self in ground_equipment) && IsIn(former_self,ground_corridor)) ||
2582                   ((self in ground_corridor) && IsIn(former_self,ground_equipment)) )  {
2583                       LockUnlockParadox();
2584                       return true;
2585               }
2586               else
2587                   return (UnlockManualDoor(self,second));
2588           Lock:
2589               if (((self in ground_equipment) && IsIn(former_self,ground_corridor)) ||
2590                   ((self in ground_corridor) && IsIn(former_self,ground_equipment)) )  {
2591                       LockUnlockParadox();
2592                       return true;
2593               }
2594               else
2595                   return (LockManualDoor(self,second));
2596         ],
2597         with_key_type equipment_key,
2598         found_in ground_corridor ground_equipment,
2599   has   locked scenery;
2600
2601 ManualDoor  basement_equipment_door "door to the equipment room"
2602   with  name 'door' 'equipment' 'room' 'grey' 'gray' 'third' 'plain' 'ne' 'north-east',
2603         description
2604             "A simple gray door.",
2605         door_to [;
2606           if (self in basement_corridor)
2607               return basement_equipment;
2608           if (self in basement_equipment)
2609               return basement_corridor;
2610
2611         ],
2612         door_dir [;
2613           if (self in basement_corridor)
2614               return ne_to;
2615           if (self in basement_equipment)
2616               return w_to;
2617         ],
2618         before [;
2619           Close:
2620               if (((self in basement_equipment) && IsIn(former_self,basement_corridor)) ||
2621                   ((self in basement_corridor) && IsIn(former_self,basement_equipment)) )  {
2622                       CloseParadox();
2623                       return true;
2624               }
2625           Open:
2626               if (((self in basement_equipment) && IsIn(former_self,basement_corridor)) ||
2627                   ((self in basement_corridor) && IsIn(former_self,basement_equipment)) )  {
2628                       OpenParadox();
2629                       return true;
2630               }
2631               else
2632                   return (OpenManualDoor(self,second));
2633           Unlock:
2634               if (IsOfType(second,crowbar))
2635                   <<Attack self>>;
2636               if (((self in basement_equipment) && IsIn(former_self,basement_corridor)) ||
2637                   ((self in basement_corridor) && IsIn(former_self,basement_equipment)) )  {
2638                       LockUnlockParadox();
2639                       return true;
2640               }
2641               else
2642                   return (UnlockManualDoor(self,second));
2643           Lock:
2644               if (((self in basement_equipment) && IsIn(former_self,basement_corridor)) ||
2645                   ((self in basement_corridor) && IsIn(former_self,basement_equipment)) )  {
2646                       LockUnlockParadox();
2647                       return true;
2648               }
2649               else
2650                   return (LockManualDoor(self,second));
2651         ],
2652         with_key_type equipment_key,
2653         found_in basement_corridor basement_equipment,
2654   has   locked scenery;
2655
2656 ManualDoor  deutsch_door "door to the Deutsch lab"
2657   with  name 'door' 'deutsch' 'lab' 'fourth' 'north' 'n\\',
2658         description [;
2659           if (self in basement_corridor)
2660               "A gray door with a small glass window,
2661                looking into the darkened lab.";
2662           if (self in deutsch_lab)
2663               "A gray door with a small glass window,
2664                looking into the darkened corridor.";
2665         ],
2666         door_to [;
2667           if (self in basement_corridor)
2668               return deutsch_lab;
2669           if (self in deutsch_lab)
2670               return basement_corridor;
2671         ],
2672         door_dir [;
2673           if (self in basement_corridor)
2674               return n_to;
2675           if (self in deutsch_lab)
2676               return s_to;
2677         ],
2678         before [;
2679           Close:
2680               if (((self in deutsch_lab) && IsIn(former_self,basement_corridor)) ||
2681                   ((self in basement_corridor) && IsIn(former_self,deutsch_lab)) )  {
2682                       CloseParadox();
2683                       return true;
2684               }
2685           Open:
2686               if (((self in deutsch_lab) && IsIn(former_self,basement_corridor)) ||
2687                   ((self in basement_corridor) && IsIn(former_self,deutsch_lab)) )  {
2688                       OpenParadox();
2689                       return true;
2690               }
2691               else
2692                   return (OpenManualDoor(self,second));
2693           Unlock:
2694               if (IsOfType(second,crowbar))
2695                   <<Attack self>>;
2696               if (((self in deutsch_lab) && IsIn(former_self,basement_corridor)) ||
2697                   ((self in basement_corridor) && IsIn(former_self,deutsch_lab)) )  {
2698                       LockUnlockParadox();
2699                       return true;
2700               }
2701               else
2702                   return (UnlockManualDoor(self,second));
2703           Lock:
2704               if (((self in deutsch_lab) && IsIn(former_self,basement_corridor)) ||
2705                   ((self in basement_corridor) && IsIn(former_self,deutsch_lab)) )  {
2706                       LockUnlockParadox();
2707                       return true;
2708               }
2709               else
2710                   return (LockManualDoor(self,second));
2711         ],
2712         with_key_type deutsch_key,
2713         found_in basement_corridor deutsch_lab,
2714   has   locked scenery;
2715
2716 ManualDoor  balcony_door "balcony door"
2717   with  name 'door' 'balcony' 'n\\' 'north' 'glass',
2718         description [;
2719           if (self in upstairs_corridor) {
2720               Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_BALCONY_);
2721               print "A ";
2722               if (self.smashed) print "cracked ";
2723               print "glass door looking out onto the balcony. ";
2724               if (IsIn(former_self,balcony))
2725                   print "In the shadows you can see your past self.^";
2726               else
2727                   print "^";
2728           }
2729           if (self in balcony) {
2730               Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_UPSTAIRS_CORRIDOR_);
2731               print "A ";
2732               if (self.smashed) print "cracked ";
2733               print "glass door looking into the upstairs corridor. ";
2734               if (IsIn(former_self,upstairs_corridor))
2735                   print "In the shadows you can see your past self.^";
2736               else
2737                   print "^";
2738           }
2739         ],
2740         when_closed [;
2741           if (self in balcony)
2742               "To the south, the door to the upstairs corridor stands closed.";
2743           else
2744              "At the north end of the corridor is a closed glass door leading out
2745                to the balcony.";
2746         ],
2747         when_open [;
2748           if (self in balcony)
2749               "To the south, the door to the upstairs corridor lies open.";
2750           else
2751              "At the north end of the corridor is an open glass door leading out
2752                to the balcony.";
2753         ],
2754         door_to [;
2755           if (self in upstairs_corridor)
2756               return balcony;
2757           if (self in balcony)
2758               return upstairs_corridor;
2759
2760         ],
2761         door_dir [;
2762           if (self in upstairs_corridor)
2763               return n_to;
2764           if (self in balcony)
2765               return s_to;
2766         ],
2767         before [;
2768           Close:
2769               if (((self in balcony) && IsIn(former_self,upstairs_corridor)) ||
2770                   ((self in upstairs_corridor) && IsIn(former_self,balcony)) )  {
2771                       CloseParadox();
2772                       return true;
2773               }
2774           Open:
2775               if (((self in balcony) && IsIn(former_self,upstairs_corridor)) ||
2776                   ((self in upstairs_corridor) && IsIn(former_self,balcony)) )  {
2777                       OpenParadox();
2778                       return true;
2779               }
2780               else
2781                   return (OpenManualDoor(self,second));
2782           Unlock:
2783               if (IsOfType(second,crowbar))
2784                   <<Attack self>>;
2785               if (((self in balcony) && IsIn(former_self,upstairs_corridor)) ||
2786                   ((self in upstairs_corridor) && IsIn(former_self,balcony)) )  {
2787                       LockUnlockParadox();
2788                       return true;
2789               }
2790               else
2791                   return (UnlockManualDoor(self,second));
2792           Lock:
2793               if (((self in balcony) && IsIn(former_self,upstairs_corridor)) ||
2794                   ((self in upstairs_corridor) && IsIn(former_self,balcony)) )  {
2795                       LockUnlockParadox();
2796                       return true;
2797               }
2798               else
2799                   return (LockManualDoor(self,second));
2800           Attack:
2801               if (AmHolding(crowbar)) {
2802                   print "You swing the crowbar firmly into the door. It shudders,
2803                          cracks reaching out from the point of impact, but the glass
2804                          stays in place.^";
2805                   self.smashed = true;
2806                   StartSiren();
2807                   return true;
2808               }
2809               else
2810                 "You don't have anything heavy enough to smash the door with.";              
2811           Search:
2812               <<Examine self>>;             
2813         ],
2814         smashed false,
2815         with_key_type nothing,
2816         found_in upstairs_corridor balcony,
2817   has   ;
2818
2819 Object  conference_window "window into the conference room"
2820   with  name 'window' 'glass' 'tinted' 'remains' 'shards',
2821         description [;
2822           if (self in balcony) {
2823               if (self has open)
2824                   "The remains of a plate glass window that has been smashed in with
2825                    something heavy. Large shards of glass still protrude from the edges,
2826                    framing the murky interior of the conference room.";
2827               else if (FlashLit())
2828                   "My God! It's full of stars.";
2829               else
2830                   "A plate glass window looking into the murky interior of an conference room.";
2831           }
2832           if (self in conference_room) {
2833               Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_BALCONY_);
2834               if (self has open)
2835                   print "The remains of a plate glass window that has been smashed in with
2836                    something heavy. Large shards of glass still protrude from the edges,
2837                    framing the starry night beyond. ";
2838               else
2839                   "A plate glass window looking out into the starry night. ";
2840               if (IsIn(former_self,balcony))
2841                   print "Against the stars, you can just make out the silhouette of your
2842                          past self.^";
2843               else
2844                   print "^";
2845           }
2846         ],
2847         when_closed [;
2848           if (self in balcony)
2849                     "To the south-east is a large, tinted glass window.";
2850           if (self in conference_room)
2851                     "To the north is a large plate glass window, amazingly intact.";
2852
2853         ],
2854         when_open [;
2855           if (self in balcony)
2856                     "To the south-east, lie the shattered remains of a window, opening into
2857                      a murky conference room.";
2858
2859           if (self in conference_room)
2860                     "To the north, lie the shattered remains of a window, open to
2861                      the starry night.";
2862         ],
2863         door_to [;
2864           if (self in balcony)
2865               return conference_room;
2866           if (self in conference_room)
2867               return balcony;
2868
2869         ],
2870         door_dir [;
2871           if (self in balcony)
2872               return se_to;
2873           if (self in conference_room)
2874               return n_to;
2875
2876         ],
2877         before [;
2878           Open:
2879               if (second == nothing)
2880                   "The window appears to be locked from the inside.";
2881           Unlock:
2882               if (IsOfType(second, crowbar))
2883                   <<Attack self>>;
2884               else if (second ~= nothing)
2885                   "You cannot get the window open with that.";
2886               else
2887                   "You cannot find the lock.";               
2888           Attack:
2889               if (AmHolding(crowbar)) {
2890                   if (self has open)
2891                       "The window is already thoroughly broken.";
2892                   give self open;
2893                   print "You swing the crowbar firmly into the window and it shatters with
2894                    a loud crash.^";
2895                   StartSiren();
2896                   return true;
2897               }
2898               else
2899                 "You don't have anything heavy enough to smash the window with.";
2900            Search:
2901               <<Examine self>>;            
2902         ],
2903         with_key_type nothing,
2904         found_in balcony conference_room,
2905   has   static locked door lockable;
2906
2907
2908
2909 !============================================================================
2910 !
2911 ! Functions:
2912 !
2913
2914 !----------------------------------------------------
2915 !
2916 ! Entry point functions:
2917
2918
2919 ! Puts the time in HH:MM:SS format on the status line
2920
2921 [ DrawStatusLine width pos;
2922
2923  ! @split_window 0; 
2924  ! return; 
2925   
2926   @split_window 1;
2927   @set_window 1; 
2928   @set_cursor 1 1; 
2929   style reverse; 
2930   width = 0->33; 
2931   pos = width-20; 
2932   spaces (width); 
2933
2934   @set_cursor 1 2; 
2935   PrintShortName(location);
2936    
2937   @set_cursor 1 pos; 
2938   print (PrintTime) my_time; 
2939
2940   @set_cursor 1 1; 
2941   style roman; 
2942   @set_window 0; 
2943 ]; 
2944
2945 [ ScoreSub;
2946   if (deadflag == 0)
2947     "There is no score in this game.";
2948 ];
2949
2950 [ ChooseObjects obj code;
2951   if (code < 2) {
2952       if (obj has scenery)
2953           return 2;            ! exclude scenery from 'get all' commands
2954       if (action_to_be == ##Take && obj has static)
2955           return 2;            ! exclude scenery from 'get all' commands
2956       rfalse;
2957   }
2958   if (action_to_be == ##Insert && obj in player)   ! prefer to insert into held objects
2959       return 3;                                    ! particularly important with all
2960                                                    ! these duplicates...
2961   if (action_to_be == ##Close && (obj has openable) && (obj has open))
2962       return 3;        
2963   if (action_to_be == ##Open && (obj has openable) && (obj hasnt open))
2964       return 3;        
2965   if (action_to_be == ##Lock && (obj has lockable) && (obj hasnt locked))
2966       return 3;        
2967   if (action_to_be == ##Unlock && (obj has lockable) && (obj has locked))
2968       return 3;        
2969   if (action_to_be == ##LockSimple && (obj has lockable) && (obj hasnt locked))
2970       return 3;        
2971   if (action_to_be == ##UnlockSimple && (obj has lockable) && (obj has locked))
2972       return 3;        
2973   if (action_to_be == ##Take && obj has static)    ! prefer to get non-statics
2974       return 1;
2975   if (obj hasnt scenery)                           ! prefer non-scenery in general
2976       return 2;
2977   return 1; 
2978 ]; 
2979
2980 [ Initialise i;
2981
2982     lookmode = 2;            ! 'verbose'
2983
2984     my_time = start_time;
2985        
2986     location = foyer;
2987
2988     player = myselfobj;
2989     
2990     for (i=0 : i < MAX_ITEM_COPIES : i++) {
2991                 bomb-->i          = Bomb_.create();
2992                 id_card-->i       = IDCard_.create();
2993                 equipment_key-->i = EquipmentKey_.create();
2994                 deutsch_key-->i   = DeutschKey_.create();
2995                 flashlight-->i    = Flashlight_.create();
2996                 battery-->i       = Battery_.create();
2997                 cable-->i         = Cable_.create();
2998                 crowbar-->i       = Crowbar_.create();
2999                 notes-->i         = Notes_.create();
3000     }
3001
3002     move bomb-->0          to player;
3003     move id_card-->0       to player;
3004     move deutsch_key-->0   to player;
3005     move equipment_key-->0 to deutsch_lab;
3006     move flashlight-->0    to deutsch_lab;
3007     move battery-->0       to ground_equipment_gloom;
3008     move cable-->0         to ground_equipment_gloom;
3009     move crowbar-->0       to basement_equipment_gloom;
3010     move notes-->0         to conference_table;
3011
3012     for (i=1 : i < MAX_ITEM_COPIES : i++) {
3013                 move bomb-->i          to limbo;
3014                 move id_card-->i       to limbo;
3015                 move equipment_key-->i to limbo;
3016                 move deutsch_key-->i   to limbo;
3017                 move flashlight-->i    to limbo;
3018                 move battery-->i       to limbo;
3019                 move cable-->i         to limbo;
3020                 move crowbar-->i       to limbo;
3021                 move notes-->i         to limbo;
3022     }
3023
3024     for (i=0 : i < MAX_TIME_TRAVELS : i++) {
3025                 former_self-->i = FormerSelf_.create();
3026                 move former_self-->i to limbo;
3027     }
3028
3029     InitHistory();
3030
3031     "^
3032      ^
3033      You're in.^
3034      ^
3035      The plan now is simple: go to your lab, plant the bomb, and run.
3036      The prototype will be destroyed. The military will have no way to
3037      continue the experiment. No-one will die.^
3038      ^
3039      The guard is out securing the grounds. The building is empty. You have six minutes.^
3040      ^
3041      ";
3042
3043 ];
3044
3045 !----------------------------------------------------
3046 !
3047 ! Major tasks:
3048
3049
3050 !! Initialises the first self's history for all items
3051 !!    First wipe's the history clean with all locations as 'limbo'
3052 !!    Next updates pre-start_time histories of all items and the player
3053 !!    Then updates the states with the proper pasts and UNKNOWN futures
3054
3055 [InitHistory t i s;
3056     for (t = EARLIEST_TIME : t <= FINAL_TIME : t++) {
3057                 for (i=0 : i < MAX_ITEM_COPIES : i++) {
3058                         Put3D(bomb_loc, 0, (t - EARLIEST_TIME),
3059                                   i, limbo ); 
3060                         Put3D(id_card_loc, 0, (t - EARLIEST_TIME),
3061                                   i, limbo ); 
3062                         Put3D(equipment_key_loc, 0, (t - EARLIEST_TIME),
3063                                   i, limbo ); 
3064                         Put3D(deutsch_key_loc, 0, (t - EARLIEST_TIME),
3065                                   i, limbo ); 
3066                         Put3D(flashlight_loc, 0, (t - EARLIEST_TIME),
3067                                   i, limbo ); 
3068                         Put3D(battery_loc, 0, (t - EARLIEST_TIME),
3069                                   i, limbo ); 
3070                         Put3D(cable_loc, 0, (t - EARLIEST_TIME),
3071                                   i, limbo ); 
3072                         Put3D(crowbar_loc, 0, (t - EARLIEST_TIME),
3073                                   i, limbo ); 
3074                         Put3D(notes_loc, 0, (t - EARLIEST_TIME),
3075                                   i, limbo ); 
3076
3077             Put3D(flashlight_state, 0, (t - EARLIEST_TIME),
3078                   i, UNKNOWN_ ); 
3079             Put3D(bomb_setting, 0, (t - EARLIEST_TIME),
3080                   i, UNKNOWN_ ); 
3081                 }
3082     }
3083
3084     for (t = EARLIEST_TIME : t <= start_time : t++) {
3085                 Put3D(bomb_loc, 0, (t - EARLIEST_TIME),
3086                           0, parent(bomb-->0) ); 
3087                 Put3D(id_card_loc, 0, (t - EARLIEST_TIME),
3088                           0, parent(id_card-->0) ); 
3089                 Put3D(equipment_key_loc, 0, (t - EARLIEST_TIME),
3090                           0, parent(equipment_key-->0) ); 
3091             Put3D(deutsch_key_loc, 0, (t - EARLIEST_TIME),
3092                           0, parent(deutsch_key-->0) ); 
3093                 Put3D(flashlight_loc, 0, (t - EARLIEST_TIME),
3094                           0, parent(flashlight-->0) ); 
3095                 Put3D(battery_loc, 0, (t - EARLIEST_TIME),
3096                           0, parent(battery-->0) ); 
3097                 Put3D(cable_loc, 0, (t - EARLIEST_TIME),
3098                           0, parent(cable-->0) ); 
3099                 Put3D(crowbar_loc, 0, (t - EARLIEST_TIME),
3100                           0, parent(crowbar-->0) ); 
3101                 Put3D(notes_loc, 0, (t - EARLIEST_TIME),
3102                           0, parent(notes-->0) ); 
3103         }
3104     for (t = EARLIEST_TIME : t < start_time : t++) {    
3105         Put2D(player_loc, 0, (t - EARLIEST_TIME), limbo); 
3106     }
3107         Put2D(player_loc, 0, start_time - EARLIEST_TIME, foyer); 
3108
3109     for (t = EARLIEST_TIME : t <= start_time : t++) {
3110                 for (s=0 : s < MAX_TIME_TRAVELS : s++) {
3111                         Put2D(dangerous_activity, s, (t - EARLIEST_TIME),            NONE_);
3112                         Put2D(activity_target, s, (t - EARLIEST_TIME),               nothing);
3113                         Put2D(siren_state, s, (t - EARLIEST_TIME),                   false);
3114                         Put2D(panel_setting, s, (t - EARLIEST_TIME),                 0);
3115                         Put2D(basement_equipment_light, s, (t - EARLIEST_TIME),      false);
3116                         Put2D(ground_equipment_light, s, (t - EARLIEST_TIME),        false);
3117                         Put2D(main_doors_state, s, (t - EARLIEST_TIME),              LOCKED_);
3118                         Put2D(basement_door_state, s, (t - EARLIEST_TIME),           LOCKED_);
3119                         Put2D(ground_door_state, s, (t - EARLIEST_TIME),             LOCKED_);
3120                         Put2D(upstairs_door_state, s, (t - EARLIEST_TIME),           LOCKED_);
3121                         Put2D(balcony_door_state, s, (t - EARLIEST_TIME),            CLOSED_);
3122                         Put2D(conference_window_state, s, (t - EARLIEST_TIME),       LOCKED_);
3123                         Put2D(deutsch_door_state, s, (t - EARLIEST_TIME),            LOCKED_);
3124                         Put2D(basement_equipment_door_state, s, (t - EARLIEST_TIME), LOCKED_);
3125                         Put2D(ground_equipment_door_state, s, (t - EARLIEST_TIME),   LOCKED_);
3126                         
3127                         Put2D(main_doors_smashed, s, (t - EARLIEST_TIME),            false);
3128                         Put2D(basement_door_smashed, s, (t - EARLIEST_TIME),         false);
3129                         Put2D(ground_door_smashed, s, (t - EARLIEST_TIME),           false);
3130                         Put2D(upstairs_door_smashed, s, (t - EARLIEST_TIME),         false);
3131                         Put2D(balcony_door_smashed, s, (t - EARLIEST_TIME),          false);
3132                         
3133                         for (i=0 : i < MAX_ITEM_COPIES : i++) {    
3134                 Put3D(flashlight_state, 0, (t - EARLIEST_TIME),
3135                       i, false ); 
3136                 Put3D(bomb_setting, 0, (t - EARLIEST_TIME),
3137                       i, NA_ );
3138                         }
3139                 }
3140     }
3141     
3142     for (t = start_time+1 : t <= FINAL_TIME : t++) {
3143                 for (s=0 : s < MAX_TIME_TRAVELS : s++) {
3144                         Put2D(dangerous_activity, s, (t - EARLIEST_TIME),            NONE_);
3145                         Put2D(activity_target, s, (t - EARLIEST_TIME),               nothing);
3146                         Put2D(siren_state, s, (t - EARLIEST_TIME),                   UNKNOWN_);
3147                         Put2D(panel_setting, s, (t - EARLIEST_TIME),                 UNKNOWN_);
3148                         Put2D(basement_equipment_light, s, (t - EARLIEST_TIME),      UNKNOWN_);
3149                         Put2D(ground_equipment_light, s, (t - EARLIEST_TIME),        UNKNOWN_);
3150                         Put2D(main_doors_state, s, (t - EARLIEST_TIME),              UNKNOWN_);
3151                         Put2D(basement_door_state, s, (t - EARLIEST_TIME),           UNKNOWN_);
3152                         Put2D(ground_door_state, s, (t - EARLIEST_TIME),             UNKNOWN_);
3153                         Put2D(upstairs_door_state, s, (t - EARLIEST_TIME),           UNKNOWN_);
3154                         Put2D(balcony_door_state, s, (t - EARLIEST_TIME),            UNKNOWN_);
3155                         Put2D(conference_window_state, s, (t - EARLIEST_TIME),       UNKNOWN_);
3156                         Put2D(deutsch_door_state, s, (t - EARLIEST_TIME),            UNKNOWN_);
3157                         Put2D(basement_equipment_door_state, s, (t - EARLIEST_TIME), UNKNOWN_);
3158                         Put2D(ground_equipment_door_state, s, (t - EARLIEST_TIME),   UNKNOWN_);
3159
3160                         Put2D(main_doors_smashed, s, (t - EARLIEST_TIME),            UNKNOWN_);
3161                         Put2D(basement_door_smashed, s, (t - EARLIEST_TIME),         UNKNOWN_);
3162                         Put2D(ground_door_smashed, s, (t - EARLIEST_TIME),           UNKNOWN_);
3163                         Put2D(upstairs_door_smashed, s, (t - EARLIEST_TIME),         UNKNOWN_);
3164                         Put2D(balcony_door_smashed, s, (t - EARLIEST_TIME),          UNKNOWN_);
3165                 }
3166     }
3167                           
3168 ];
3169
3170 !! Update the time, remove the old objects that don't travel,
3171 !! create new objects, move them to the appropriate places
3172
3173 [TravelThroughTime time_amount t s i j;
3174
3175     last_travel_time = my_time;
3176     
3177     time_amount = time_amount / 5;   ! round down to nearest five seconds
3178     if (time_amount == 0)
3179         time_amount = 1;
3180         
3181     my_time = my_time - time_amount;
3182
3183     if (my_time < early_guard_time) {
3184         d_paradox = true;
3185         deadflag = 3;
3186         Seperator();
3187         print (Nearby) 0, "the guard gives the inside corridors a last look before
3188                            heading out. A small sound from the Deutsch lab. He turns.^"; 
3189         print "^Time unravels...^";
3190         Devours(my_time); 
3191         return true;                           
3192     }
3193           
3194     !! replace those items the player brought with them
3195     
3196     FixBombSettings(time_amount);
3197     FixFlashlightStates();
3198         
3199     for (j=0 : j < Exp(2,time_travelled) : j++) {
3200         ReplaceTravellingItem(bomb, j);
3201         ReplaceTravellingItem(id_card, j);
3202         ReplaceTravellingItem(equipment_key, j);
3203         ReplaceTravellingItem(deutsch_key, j);
3204         ReplaceTravellingItem(flashlight, j);
3205
3206         ReplaceTravellingItem(cable, j);
3207         ReplaceTravellingItem(crowbar, j);
3208         ReplaceTravellingItem(notes, j);
3209         
3210         !! tricky battery issues, since they can be in flashlights
3211         !! if other items could be in containers this would hurt here too
3212         
3213         if (PlayerHas(battery-->j)) {
3214             if (battery-->j in player)
3215                 move battery-->(j+Exp(2,time_travelled)) to player;
3216             else {
3217                 for (i=0 : i < Exp(2,time_travelled) : i++)
3218                     if (battery-->j in (flashlight-->i))
3219                         move (battery-->(j+Exp(2,time_travelled))) to (flashlight-->(i+Exp(2,time_travelled)));
3220             }
3221         }
3222         else if (LocationOf(battery-->j) == prototype_interior) {
3223             if (battery-->j in prototype_interior)
3224                 move battery-->(j+Exp(2,time_travelled)) to prototype_interior;
3225             else
3226                 for (i=0 : i < Exp(2,time_travelled) : i++)
3227                     if (battery-->j in flashlight-->i)
3228                         move battery-->(j+Exp(2,time_travelled)) to
3229                              flashlight-->(i+Exp(2,time_travelled));
3230         }
3231
3232     }
3233
3234     
3235     !! move all the old items and selves into limbo
3236     
3237     for (t=0 : t < Exp(2,time_travelled) : t++) {
3238                 move bomb-->t          to limbo;
3239                 move id_card-->t       to limbo;
3240                 move equipment_key-->t to limbo;
3241                 move deutsch_key-->t   to limbo;
3242                 move flashlight-->t    to limbo;
3243                 move battery-->t       to limbo;
3244                 move cable-->t         to limbo;
3245                 move crowbar-->t       to limbo;
3246                 move notes-->t         to limbo;
3247     }
3248      
3249     for (t=0 : t < time_travelled : t++)
3250         move former_self-->t   to limbo;
3251     
3252
3253     !! fix up history of immediate past self so 'player' becomes appropriate former self
3254     
3255     for (s = EARLIEST_TIME : s <= FINAL_TIME : s++) {
3256         for (t=0 : t < Exp(2,time_travelled) : t++) {
3257             if (Get3D(bomb_loc, time_travelled, (s - EARLIEST_TIME), t) == player)
3258                 Put3D(bomb_loc, time_travelled, (s - EARLIEST_TIME), t,
3259                       former_self-->time_travelled);
3260             if (Get3D(id_card_loc, time_travelled, (s - EARLIEST_TIME), t) == player)
3261                 Put3D(id_card_loc, time_travelled, (s - EARLIEST_TIME), t,
3262                       former_self-->time_travelled);
3263             if (Get3D(equipment_key_loc, time_travelled, (s - EARLIEST_TIME), t) == player)
3264                 Put3D(equipment_key_loc, time_travelled, (s - EARLIEST_TIME), t,
3265                       former_self-->time_travelled);
3266             if (Get3D(deutsch_key_loc, time_travelled, (s - EARLIEST_TIME), t) == player)
3267                 Put3D(deutsch_key_loc, time_travelled, (s - EARLIEST_TIME), t,
3268                       former_self-->time_travelled);
3269             if (Get3D(flashlight_loc, time_travelled, (s - EARLIEST_TIME), t) == player)
3270                 Put3D(flashlight_loc, time_travelled, (s - EARLIEST_TIME), t,
3271                       former_self-->time_travelled);
3272             if (Get3D(battery_loc, time_travelled, (s - EARLIEST_TIME), t) == player)
3273                 Put3D(battery_loc, time_travelled, (s - EARLIEST_TIME), t,
3274                       former_self-->time_travelled);
3275             if (Get3D(cable_loc, time_travelled, (s - EARLIEST_TIME), t) == player)
3276                 Put3D(cable_loc, time_travelled, (s - EARLIEST_TIME), t,
3277                       former_self-->time_travelled);
3278             if (Get3D(crowbar_loc, time_travelled, (s - EARLIEST_TIME), t) == player)
3279                 Put3D(crowbar_loc, time_travelled, (s - EARLIEST_TIME), t,
3280                       former_self-->time_travelled);
3281             if (Get3D(notes_loc, time_travelled, (s - EARLIEST_TIME), t) == player)
3282                 Put3D(notes_loc, time_travelled, (s - EARLIEST_TIME), t,
3283                       former_self-->time_travelled);
3284         }
3285     }
3286
3287     !! recreate the world as it was for most recent former self
3288     !! (ie move a lot of old items and selves back to the world)
3289     !! (fix states of doors and machine)
3290     
3291     for (i=0 : i < Exp(2,time_travelled) : i++) {
3292                 move bomb-->i          to Get3D(bomb_loc,time_travelled,my_time-EARLIEST_TIME,i);
3293                 move id_card-->i       to Get3D(id_card_loc,time_travelled,my_time-EARLIEST_TIME,i);
3294                 move equipment_key-->i to Get3D(equipment_key_loc,time_travelled,my_time-EARLIEST_TIME,i);
3295                 move deutsch_key-->i   to Get3D(deutsch_key_loc,time_travelled,my_time-EARLIEST_TIME,i);
3296                 move flashlight-->i    to Get3D(flashlight_loc,time_travelled,my_time-EARLIEST_TIME,i);
3297                 move battery-->i       to Get3D(battery_loc,time_travelled,my_time-EARLIEST_TIME,i);
3298                 move cable-->i         to Get3D(cable_loc,time_travelled,my_time-EARLIEST_TIME,i);
3299                 move crowbar-->i       to Get3D(crowbar_loc,time_travelled,my_time-EARLIEST_TIME,i);
3300                 move notes-->i         to Get3D(notes_loc,time_travelled,my_time-EARLIEST_TIME,i);
3301     }
3302     for (t=0 : t <= time_travelled : t++) {
3303         if (Get2D(player_loc,t,my_time-EARLIEST_TIME) == nothing)
3304             move former_self-->t to limbo;
3305         else
3306             move former_self-->t to Get2D(player_loc,t,my_time-EARLIEST_TIME);
3307     }
3308     
3309     if (my_time < prototype_fixed_time)
3310         prototype.fixed = false;
3311     
3312     SetBombs();
3313     SetFlashlights();
3314     SetPanel(panel_setting);
3315     SetBasementLight(basement_equipment_light);
3316     SetGroundLight(ground_equipment_light);
3317     SetAutomaticDoor(main_doors, main_doors_state);
3318     SetAutomaticDoor(basement_door, basement_door_state);
3319     SetAutomaticDoor(ground_door, ground_door_state);
3320     SetAutomaticDoor(upstairs_door, upstairs_door_state);
3321     SetManualDoor(balcony_door, balcony_door_state); 
3322     SetManualDoor(conference_window, conference_window_state); 
3323     SetManualDoor(deutsch_door, deutsch_door_state); 
3324     SetManualDoor(basement_equipment_door, basement_equipment_door_state); 
3325     SetManualDoor(ground_equipment_door, ground_equipment_door_state); 
3326
3327     SetBrokenDoor(main_doors, main_doors_smashed);
3328     SetBrokenDoor(basement_door, basement_door_smashed);
3329     SetBrokenDoor(ground_door, ground_door_smashed);
3330     SetBrokenDoor(upstairs_door, upstairs_door_smashed);
3331     SetBrokenDoor(balcony_door, balcony_door_smashed); 
3332                         
3333     !! initialise the history for the new self from the most recent self
3334                 
3335     for (t = EARLIEST_TIME : t <= FINAL_TIME : t++) {
3336                 for (i=0 : i < MAX_ITEM_COPIES : i++) {
3337                         Put3D(bomb_loc, time_travelled+1, (t - EARLIEST_TIME), i,
3338                               Get3D(bomb_loc, time_travelled, (t - EARLIEST_TIME), i));
3339                         Put3D(id_card_loc, time_travelled+1, (t - EARLIEST_TIME), i,
3340                               Get3D(id_card_loc, time_travelled, (t - EARLIEST_TIME), i));
3341                         Put3D(equipment_key_loc, time_travelled+1, (t - EARLIEST_TIME), i,
3342                               Get3D(equipment_key_loc, time_travelled, (t - EARLIEST_TIME), i));
3343                         Put3D(deutsch_key_loc, time_travelled+1, (t - EARLIEST_TIME), i,
3344                               Get3D(deutsch_key_loc, time_travelled, (t - EARLIEST_TIME), i));
3345                         Put3D(flashlight_loc, time_travelled+1, (t - EARLIEST_TIME), i,
3346                               Get3D(flashlight_loc, time_travelled, (t - EARLIEST_TIME), i));
3347                         Put3D(battery_loc, time_travelled+1, (t - EARLIEST_TIME), i,
3348                               Get3D(battery_loc, time_travelled, (t - EARLIEST_TIME), i));
3349                         Put3D(cable_loc, time_travelled+1, (t - EARLIEST_TIME), i,
3350                               Get3D(cable_loc, time_travelled, (t - EARLIEST_TIME), i));
3351                         Put3D(crowbar_loc, time_travelled+1, (t - EARLIEST_TIME), i,
3352                               Get3D(crowbar_loc, time_travelled, (t - EARLIEST_TIME), i));
3353                         Put3D(notes_loc, time_travelled+1, (t - EARLIEST_TIME), i,
3354                               Get3D(notes_loc, time_travelled, (t - EARLIEST_TIME), i));
3355
3356                         Put3D(bomb_setting, time_travelled+1, (t - EARLIEST_TIME), i,
3357                               Get3D(bomb_setting, time_travelled, (t - EARLIEST_TIME), i));
3358                         Put3D(flashlight_state, time_travelled+1, (t - EARLIEST_TIME), i,
3359                               Get3D(flashlight_state, time_travelled, (t - EARLIEST_TIME), i));
3360                 }
3361                 Put2D(dangerous_activity, time_travelled+1, (t - EARLIEST_TIME),
3362                     Get2D(dangerous_activity, time_travelled, (t - EARLIEST_TIME)));            
3363                 Put2D(activity_target, time_travelled+1, (t - EARLIEST_TIME),
3364                     Get2D(activity_target, time_travelled, (t - EARLIEST_TIME)));               
3365                 Put2D(siren_state, time_travelled+1, (t - EARLIEST_TIME),
3366                     Get2D(siren_state, time_travelled, (t - EARLIEST_TIME)));           
3367                 Put2D(panel_setting, time_travelled+1, (t - EARLIEST_TIME),
3368                     Get2D(panel_setting, time_travelled, (t - EARLIEST_TIME)));         
3369                 Put2D(basement_equipment_light, time_travelled+1, (t - EARLIEST_TIME),
3370                     Get2D(basement_equipment_light, time_travelled, (t - EARLIEST_TIME)));              
3371                 Put2D(ground_equipment_light, time_travelled+1, (t - EARLIEST_TIME),
3372                     Get2D(ground_equipment_light, time_travelled, (t - EARLIEST_TIME)));                
3373                 Put2D(main_doors_state, time_travelled+1, (t - EARLIEST_TIME),
3374                     Get2D(main_doors_state, time_travelled, (t - EARLIEST_TIME)));
3375                 Put2D(basement_door_state, time_travelled+1, (t - EARLIEST_TIME),
3376                     Get2D(basement_door_state, time_travelled, (t - EARLIEST_TIME)));           
3377                 Put2D(ground_door_state, time_travelled+1, (t - EARLIEST_TIME),
3378                     Get2D(ground_door_state, time_travelled, (t - EARLIEST_TIME)));             
3379                 Put2D(upstairs_door_state, time_travelled+1, (t - EARLIEST_TIME),
3380                     Get2D(upstairs_door_state, time_travelled, (t - EARLIEST_TIME)));           
3381                 Put2D(balcony_door_state, time_travelled+1, (t - EARLIEST_TIME),
3382                     Get2D(balcony_door_state, time_travelled, (t - EARLIEST_TIME)));            
3383                 Put2D(conference_window_state, time_travelled+1, (t - EARLIEST_TIME),
3384                     Get2D(conference_window_state, time_travelled, (t - EARLIEST_TIME)));               
3385                 Put2D(deutsch_door_state, time_travelled+1, (t - EARLIEST_TIME),
3386                     Get2D(deutsch_door_state, time_travelled, (t - EARLIEST_TIME)));            
3387                 Put2D(basement_equipment_door_state, time_travelled+1, (t - EARLIEST_TIME),
3388                     Get2D(basement_equipment_door_state, time_travelled, (t - EARLIEST_TIME)));         
3389                 Put2D(ground_equipment_door_state, time_travelled+1, (t - EARLIEST_TIME),
3390                     Get2D(ground_equipment_door_state, time_travelled, (t - EARLIEST_TIME)));           
3391
3392                 Put2D(main_doors_smashed, time_travelled+1, (t - EARLIEST_TIME),
3393                     Get2D(main_doors_smashed, time_travelled, (t - EARLIEST_TIME)));
3394                 Put2D(basement_door_smashed, time_travelled+1, (t - EARLIEST_TIME),
3395                     Get2D(basement_door_smashed, time_travelled, (t - EARLIEST_TIME)));         
3396                 Put2D(ground_door_smashed, time_travelled+1, (t - EARLIEST_TIME),
3397                     Get2D(ground_door_smashed, time_travelled, (t - EARLIEST_TIME)));           
3398                 Put2D(upstairs_door_smashed, time_travelled+1, (t - EARLIEST_TIME),
3399                     Get2D(upstairs_door_smashed, time_travelled, (t - EARLIEST_TIME)));         
3400                 Put2D(balcony_door_smashed, time_travelled+1, (t - EARLIEST_TIME),
3401                     Get2D(balcony_door_smashed, time_travelled, (t - EARLIEST_TIME)));          
3402         }
3403
3404     time_travelled++;
3405     
3406     return true;
3407 ];
3408
3409 [ReplaceTravellingItem thing_type i;
3410    if (PlayerHas(thing_type-->i))
3411        move thing_type-->(i+Exp(2,time_travelled)) to player;
3412    else if (LocationOf(thing_type-->i) == prototype_interior)
3413        move thing_type-->(i+Exp(2,time_travelled)) to prototype_interior;
3414 ];
3415
3416
3417 [FixBombSettings time_amount i;
3418     for (i=0 : i < Exp(2,time_travelled) : i++) {
3419        if (PlayerHas(bomb-->i) || (LocationOf(bomb-->i) == prototype_interior))
3420            if ((bomb-->i).time_value ~= NA_)
3421                (bomb-->(i+Exp(2,time_travelled))).time_value 
3422                                  = (bomb-->i).time_value - time_amount;
3423        (bomb-->i).time_value = NA_;
3424     }
3425 ];
3426
3427 [FixFlashlightStates i;
3428     for (i=0 : i < Exp(2,time_travelled) : i++) {
3429        if (PlayerHas(flashlight-->i) || (LocationOf(flashlight-->i) == prototype_interior)) {
3430            if (flashlight-->i has on)
3431                give flashlight-->(i+Exp(2,time_travelled)) on;
3432            else
3433                give flashlight-->(i+Exp(2,time_travelled)) ~on;       
3434        }
3435        give flashlight-->i ~on;
3436     }
3437 ];
3438
3439
3440 !----------------------------------------------------
3441 !
3442 ! Little utility functions:
3443
3444
3445 [IsOfType thing thing_type i;
3446     for (i=0 : i < MAX_ITEM_COPIES : i++)
3447         if (thing_type-->i == thing)
3448             return true;
3449     return false;
3450 ]; 
3451
3452 [AmHolding thing_type i;
3453     for (i=0 : i < MAX_ITEM_COPIES : i++)
3454         if (thing_type-->i ~= nothing && thing_type-->i in player)
3455             return true;
3456     return false;
3457 ]; 
3458
3459 [GetHeld thing_type i;
3460     for (i=0 : i < MAX_ITEM_COPIES : i++)
3461         if (thing_type-->i ~= nothing && thing_type-->i in player)
3462             return thing_type-->i;
3463     return false;
3464 ]; 
3465
3466 [IsIn thing_type loc i;
3467     for (i=0 : i < MAX_ITEM_COPIES : i++)
3468         if (thing_type-->i ~= nothing && thing_type-->i in loc)
3469             return true;
3470     return false;
3471 ]; 
3472
3473 [GetFrom thing_type loc i;
3474     for (i=0 : i < MAX_ITEM_COPIES : i++)
3475         if (thing_type-->i ~= nothing && thing_type-->i in loc)
3476             return thing_type-->i;
3477     return false;
3478 ]; 
3479
3480 ![Present thing_type t;
3481 !    for (t=0 : t < MAX_ITEM_COPIES : t++)
3482 !        if (thing_type-->t ~= nothing && thing_type-->t in real_location)
3483 !            return true;
3484 !    return false;
3485 !]; 
3486
3487 ![GetPresent thing_type t;
3488 !    for (t=0 : t < MAX_ITEM_COPIES : t++)
3489 !        if (thing_type-->t ~= nothing && thing_type-->t in real_location)
3490 !            return thing_type-->t;
3491 !    return false;
3492 !]; 
3493
3494 [BatteriesContained thing batteries i;
3495     batteries = 0;
3496     for (i=0 : i < MAX_ITEM_COPIES : i++)
3497         if (battery-->i ~= nothing && battery-->i in thing)
3498             batteries++;
3499     return batteries;
3500 ]; 
3501
3502 [StartSiren;
3503     if (siren_start_time == UNKNOWN_ || siren_start_time > my_time)
3504       siren_start_time = my_time;
3505 ];
3506
3507 [MoveMoveableChildren old_loc new_loc x y;
3508     while (child(old_loc)) {
3509         x = nothing;
3510         y = child(old_loc);
3511         if ((y hasnt static) && (y ~= player)) {
3512             x = y;
3513         }
3514         while (sibling(y)) {
3515             y = sibling(y);
3516             if ((y hasnt static) && (y ~= player)) {
3517                 x = y;
3518             }
3519         }
3520         if (x ~= nothing) {
3521             move x to new_loc;
3522         }
3523         else
3524             break;
3525     }
3526 ];
3527
3528 [ LocationOf x;
3529     if (parent(x) == 0)
3530         return x;
3531     else
3532         return LocationOf(parent(x));
3533 ];
3534
3535 [ PlayerHas x;
3536     if (parent(x) == 0)
3537         return false;
3538     if (parent(x) == player)
3539         return true;
3540     return PlayerHas(parent(x));
3541 ];
3542
3543 [ Flashlit i;
3544     for (i=0 : i < MAX_ITEM_COPIES : i++) {
3545         if (flashlight-->i ~= nothing && (flashlight-->i in player or real_location)
3546             && flashlight-->i has on)
3547             return true;
3548      }
3549      return false;
3550 ];
3551
3552 [PrintTime t;
3553     if (t == NA_)
3554         return true;
3555
3556     print (t/720), ":", ((t/12)%60)/10, (t/12)%10, ":", ((t%12)/2);
3557     if ((t%2) == 0)
3558        print "0";
3559     else
3560        print "5"; 
3561
3562     if (t/(720*12) == 0)
3563         print " am";
3564     else
3565         print " pm";
3566 ];
3567
3568 [PrintShortTime t;
3569     print (t/720), ":", ((t/12)%60)/10, (t/12)%10;
3570
3571     if (t/(720*12) == 0)
3572         print " am";
3573     else
3574         print " pm";
3575 ];
3576
3577 [IncTime;
3578     InformLibrary.end_turn_sequence();
3579 ];
3580
3581 !! x == run_through, y == time_index
3582
3583 [Put2D array x y thing;
3584     array-->((x * (GAME_LENGTH+1)) + y) = thing;
3585 ];
3586
3587 !! x == run_through, y == time_index
3588
3589 [Get2D array x y;
3590     return array-->((x * (GAME_LENGTH+1)) + y);
3591 ];
3592
3593 !! x == run_through, y == time_index, z == thing_number
3594
3595 [Put3D array x y z thing;
3596     array-->( (z*(MAX_TIME_TRAVELS+1) + x)*(GAME_LENGTH+1) + y ) = thing;
3597 ];
3598
3599 !! x == run_through, y == time_index, z == thing_number
3600
3601 [Get3D array x y z;
3602     return array-->( (z*(MAX_TIME_TRAVELS+1) + x)*(GAME_LENGTH+1) + y );
3603 ];
3604
3605 [Exp b e i result;
3606     result = 1;
3607     for (i=0 : i<e : i++)
3608         result = result * b;
3609     return result;
3610 ];
3611
3612 !----------------------------------------------------
3613 !
3614 ! 'Observe' functions:    (these make note of current state of things)
3615
3616
3617 [ObserveBombs i;
3618     for (i=0 : i < MAX_ITEM_COPIES : i++) {
3619         Put3D(bomb_setting, time_travelled, (my_time - EARLIEST_TIME), i, (bomb-->i).time_value); 
3620     }
3621 ];
3622
3623 [ObserveFlashlights i;
3624     for (i=0 : i < MAX_ITEM_COPIES : i++) {
3625         Put3D(flashlight_state, time_travelled, (my_time - EARLIEST_TIME), i, flashlight-->i has on); 
3626     }
3627 ];
3628
3629 [ObserveSiren siren_on;
3630     siren_on = (siren_start_time ~= UNKNOWN_) && (siren_start_time < my_time);
3631     Put2D(siren_state, time_travelled, my_time - EARLIEST_TIME, siren_on);
3632 ];
3633
3634 [ObservePanel;
3635     Put2D(panel_setting, time_travelled, my_time - EARLIEST_TIME, control_panel.time_value);
3636 ];
3637
3638 [ObserveGroundLight light_array;
3639     Put2D(light_array, time_travelled, my_time - EARLIEST_TIME, ground_equipment.lit);
3640 ];
3641
3642 [ObserveBasementLight light_array;
3643     Put2D(light_array, time_travelled, my_time - EARLIEST_TIME, basement_light_switch.blown);
3644 ];
3645
3646 [ObserveBrokenDoor door door_smashed;
3647     Put2D(door_smashed, time_travelled, my_time - EARLIEST_TIME, door.smashed);
3648 ];
3649
3650 [ObserveManualDoor door door_state door_status;
3651     if (door has locked)
3652         door_status = LOCKED_;
3653     else {
3654         if (door has open)
3655             door_status = OPEN_;
3656         else
3657             door_status = CLOSED_;
3658     }
3659     Put2D(door_state, time_travelled, my_time - EARLIEST_TIME, door_status);
3660 ];
3661
3662 [ObserveAutomaticDoor door door_state door_status;
3663     if (door has locked)
3664         door_status = 0;
3665     else
3666         door_status = door.to_close_at;
3667     Put2D(door_state, time_travelled, my_time - EARLIEST_TIME, door_status);
3668 ];
3669
3670 [ObserveLocations i;
3671     Put2D(player_loc, time_travelled, (my_time - EARLIEST_TIME), parent(player)); 
3672     for (i=0 : i < MAX_ITEM_COPIES : i++) {
3673         Put3D(bomb_loc, time_travelled, (my_time - EARLIEST_TIME),
3674               i, parent(bomb-->i) ); 
3675         Put3D(id_card_loc, time_travelled, (my_time - EARLIEST_TIME),
3676               i, parent(id_card-->i) ); 
3677         Put3D(equipment_key_loc, time_travelled, (my_time - EARLIEST_TIME),
3678               i, parent(equipment_key-->i) ); 
3679         Put3D(deutsch_key_loc, time_travelled, (my_time - EARLIEST_TIME),
3680               i, parent(deutsch_key-->i) ); 
3681         Put3D(flashlight_loc, time_travelled, (my_time - EARLIEST_TIME),
3682               i, parent(flashlight-->i) ); 
3683         Put3D(battery_loc, time_travelled, (my_time - EARLIEST_TIME),
3684               i, parent(battery-->i) ); 
3685         Put3D(cable_loc, time_travelled, (my_time - EARLIEST_TIME),
3686               i, parent(cable-->i) ); 
3687         Put3D(crowbar_loc, time_travelled, (my_time - EARLIEST_TIME),
3688               i, parent(crowbar-->i) ); 
3689         Put3D(notes_loc, time_travelled, (my_time - EARLIEST_TIME),
3690               i, parent(notes-->i) ); 
3691     }
3692 ];
3693
3694 !----------------------------------------------------
3695 !
3696 ! 'Set' functions:    (these take care of certain former actions every turn)
3697
3698
3699 [SetBombs setting_now i;
3700     for (i=0 : i < Exp(2,time_travelled) : i++) {
3701         setting_now  = Get3D(bomb_setting,time_travelled,my_time-EARLIEST_TIME,i);
3702         (bomb-->i).time_value = setting_now;
3703     }
3704 ];
3705
3706 [SetFlashlights setting_now i;
3707     for (i=0 : i < Exp(2,time_travelled) : i++) {
3708         setting_now  = Get3D(flashlight_state,time_travelled,my_time-EARLIEST_TIME,i);
3709         if (setting_now == true)
3710             give flashlight-->i on;
3711         else
3712             give flashlight-->i ~on;
3713     }
3714 ];
3715
3716 [SetPanel setting_array setting_now;
3717     setting_now = Get2D(setting_array, time_travelled, my_time - EARLIEST_TIME);    
3718     control_panel.time_value = setting_now;
3719 ];
3720
3721 [SetBasementLight setting_array setting_now;
3722     setting_now = Get2D(setting_array, time_travelled, my_time - EARLIEST_TIME);    
3723     basement_light_switch.blown = setting_now;
3724 ];
3725
3726 [SetGroundLight setting_array setting_now;
3727     setting_now = Get2D(setting_array, time_travelled, my_time - EARLIEST_TIME);    
3728     ground_equipment.lit = setting_now;
3729     if (setting_now)
3730         give ground_light_switch on;
3731     else
3732         give ground_light_switch ~on;
3733 ];
3734
3735 [SetManualDoor door door_state door_status;
3736     door_status = Get2D(door_state, time_travelled, my_time - EARLIEST_TIME);    
3737     if (door_status == LOCKED_) {
3738         give door ~open;
3739         give door locked;
3740     }
3741     if (door_status == CLOSED_) {
3742         give door ~open;
3743         give door ~locked;
3744     }
3745     if (door_status == OPEN_) {
3746         give door open;
3747         give door ~locked;
3748     }
3749     if (door_status == UNKNOWN_) {
3750         print "Error: unknown door status needing to be set for some reason.";
3751     }
3752 ];
3753
3754 [SetAutomaticDoor door door_state door_status;
3755     door_status = Get2D(door_state, time_travelled, my_time - EARLIEST_TIME);
3756     if (door_status == UNKNOWN_) {
3757         give door ~open locked;
3758     }
3759     if (door_status > 0) {
3760         give door open ~locked;
3761         door.to_close_at = door_status;
3762     }
3763 ];
3764
3765 [SetBrokenDoor door door_smashed door_status;
3766     door_status = Get2D(door_smashed, time_travelled, my_time - EARLIEST_TIME);
3767     if (door_status == UNKNOWN_) {
3768         door.smashed = false;
3769     }
3770     if (door_status == true) {
3771         door.smashed = true;
3772     }
3773     if (door_status == false) {
3774         door.smashed = false;
3775     }
3776 ];
3777
3778 [MoveFormerSelf run_through loc_next;
3779     loc_next = Get2D(player_loc, run_through, my_time - EARLIEST_TIME);
3780
3781     if (~~d_paradox) {
3782         if (d_destroyed_prototype && ((former_self-->run_through) in limbo) &&
3783             (loc_next == prototype_interior))    {
3784                         d_paradox = true;
3785                         deadflag = 3;
3786                         Seperator();
3787                         print (PrintTime) (my_time), "^^";
3788                         print "Back in the Deutsch lab, the debris from the prototype
3789                                lies smoldering on the floor and no past self appears.^"; 
3790                         print "^Time unravels...^";
3791                         Devours(my_time);                            
3792         }   
3793         else if (d_destroyed_prototype && (my_time == start_time))    {
3794                         d_paradox = true;
3795                         deadflag = 3;
3796                         Seperator();
3797                         print (PrintTime) (my_time), "^^";
3798                         print "Elsewhere, your past self enters the foyer and smells the
3799                                bitter smoke from a recent explosion.^"; 
3800                         print "^Time unravels...^";
3801                         Devours(my_time);                            
3802         }   
3803         else {
3804             if (loc_next == nothing)
3805                 move former_self-->run_through to limbo;
3806             else
3807                 move former_self-->run_through to loc_next;    
3808         }
3809         
3810 !        if ((~~d_paradox) && (~~d_escaped) && (~~d_caught))
3811 !            print "<<< former self (", run_through, ") is in: ", (name) loc_next, " >>>^";
3812     }
3813 ];
3814
3815 !! Moves an object around according to the actions of former selves
3816 !! Uses the item histories to work out when an item was moved, but since
3817 !! that copy of the item may have been swapped for another (which is fine)
3818 !! we must get the first available copy in the right location to be safe.
3819 !! Also, we don't want to remove all normal objects when someone time-travels
3820 !! so, since this only happens when the player is not present and no other moving
3821 !! happens when the player is not present, we can get around it by only moving
3822 !! objects when a former self is present in the same location.
3823
3824 [MoveObject thing_type thing_loc i loc_now loc_next;
3825     loc_now  = Get3D(thing_loc,time_travelled-1,my_time-EARLIEST_TIME-1,i);
3826     loc_next = Get3D(thing_loc,time_travelled-1,my_time-EARLIEST_TIME,i);
3827     if (loc_now ~= loc_next) {
3828         if (IsIn(thing_type, loc_now)) {
3829             if (IsIn(former_self,LocationOf(GetFrom(thing_type, loc_now)))) {
3830 !                print "<<< Moving ", (name) thing_type-->i, " (", i, ") in ", (name) loc_now, 
3831 !                      " to ", (name) loc_next, " >>>^";
3832                 move GetFrom(thing_type, loc_now) to loc_next;
3833              }
3834              else {
3835                 !! handle the odd case of object left in prototype when button pressed
3836                 if (LocationOf(GetFrom(thing_type, loc_now)) == prototype_interior) {
3837 !                    print "<<< Moving ", (name) thing_type-->i, " (", i, ") in ", (name) loc_now, 
3838 !                          " to ", (name) loc_next, " >>>^";
3839                     move GetFrom(thing_type, loc_now) to loc_next;                    
3840                 }
3841                 else if ((loc_now == basement_equipment_gloom) || (loc_now == ground_equipment_gloom)) {
3842 !                    print "<<< Moving ", (name) thing_type-->i, " (", i, ") in ", (name) loc_now, 
3843 !                          " to ", (name) loc_next, " >>>^";
3844                     move GetFrom(thing_type, loc_now) to loc_next;                                    
3845                 }
3846 !                else {
3847 !                    print "<<< Ignoring ", (name) thing_type-->0, " in ", (name) loc_now, 
3848 !                          " (wanted to move it to ", (name) loc_next, ") >>>^";             
3849 !                }
3850              }
3851         }
3852 !        else
3853 !            print "<<< Missing ", (name) thing_type-->0, " in ", (name) loc_now, 
3854 !                  " (wanted to move it to ", (name) loc_next, ") >>>^";
3855     }
3856 ];
3857
3858 !----------------------------------------------------
3859 !
3860 ! 'Maybe' functions:   (these take care of former actions)
3861
3862
3863 [MaybeExplodeBombs i;
3864     for (i=0 : i < MAX_ITEM_COPIES : i++)
3865         if (bomb-->i ~= nothing) {
3866             if (LocationOf(bomb-->i) ~= limbo) {
3867                 if (((bomb-->i).time_value == my_time - 1) &&
3868                     ((bomb-->i).left_over_seconds == 0))
3869                         ExplodeBomb(i);
3870                 else if (((bomb-->i).time_value == my_time - 2) &&
3871                          ((bomb-->i).left_over_seconds ~=0))
3872                     ExplodeBomb(i);
3873             }
3874         }
3875 ];
3876   
3877 [MaybeSing;
3878        if (Get2D(dangerous_activity, time_travelled-1, my_time-EARLIEST_TIME-1) == SING_)
3879            if (player notin limbo)
3880                "You hear muffled singing from somewhere in the building.";
3881 ];
3882
3883 [MaybeShout;
3884        if (Get2D(dangerous_activity, time_travelled-1, my_time-EARLIEST_TIME-1) == SHOUT_)
3885            if (player notin limbo)
3886                "You hear muffled shouting from somewhere in the building.";
3887 ];
3888               
3889 !!! a little tricky to ensure that when two bombs are in same room that the one set
3890 !!! has the same original setting as it should (ie is indistinguishable from former one)
3891
3892 [MaybeSetBombs setting_now setting_next loc_now b i j;
3893     for (i=0 : i < Exp(2,time_travelled-1) : i++) {
3894         setting_now  = Get3D(bomb_setting,time_travelled-1,my_time-EARLIEST_TIME-1,i);
3895         setting_next = Get3D(bomb_setting,time_travelled-1,my_time-EARLIEST_TIME,i);
3896         loc_now  = Get3D(bomb_loc,time_travelled-1,my_time-EARLIEST_TIME-1,i);
3897         if (setting_now ~= setting_next) {
3898             if (IsIn(bomb, loc_now)) {
3899                 if (IsIn(former_self,LocationOf(GetFrom(bomb, loc_now)))) {
3900                     for (j=0 : j < MAX_ITEM_COPIES : j++)
3901                         if ((bomb-->j ~= nothing) && (bomb-->j in loc_now))
3902                             if ((bomb-->j).time_value == setting_now)
3903                                 b = bomb-->j;
3904 !                    print "<<< setting bomb (via maybeset) >>>^";
3905                     if (b ~= nothing)
3906                         b.time_value = setting_next;
3907 !                    else
3908 !                       print "<<<Missing bomb of former time setting.>>>^";
3909                 }
3910             }
3911 !            else
3912 !                print "<<<Missing ", (name) bomb-->0, " in ", (name) loc_now, 
3913 !                      " (wanted to set it to ", setting_next, ")>>>^";
3914         }
3915     }
3916 ];
3917
3918 !!! a little tricky to ensure that when two flashlights are in same room that the one set
3919 !!! has the same original setting as it should (ie is indistinguishable from former one)
3920
3921 [MaybeSetFlashlights setting_now setting_next loc_now f i j;
3922     for (i=0 : i < Exp(2,time_travelled-1) : i++) {
3923         setting_now  = Get3D(flashlight_state,time_travelled-1,my_time-EARLIEST_TIME-1,i);
3924         setting_next = Get3D(flashlight_state,time_travelled-1,my_time-EARLIEST_TIME,i);
3925         loc_now  = Get3D(flashlight_loc,time_travelled-1,my_time-EARLIEST_TIME-1,i);
3926         if (setting_now ~= setting_next) {
3927             if (IsIn(flashlight, loc_now)) {
3928                 if (IsIn(former_self,LocationOf(GetFrom(flashlight, loc_now)))) {
3929                     for (j=0 : j < MAX_ITEM_COPIES : j++)
3930                         if ((flashlight-->j ~= nothing) && (flashlight-->j in loc_now))
3931                             if ((flashlight-->j has on) == setting_now)
3932                                 f = flashlight-->j;
3933 !                    print "<<< setting flashlight (via maybeset) >>>^";
3934                     if (f ~= nothing) {
3935                         if (setting_next == true)
3936                             give f on;
3937                         else
3938                             give f ~on;
3939                     }
3940 !                    else
3941 !                       print "<<<Missing flashlight of former time setting.>>>^";
3942                 }
3943             }
3944 !            else
3945 !                print "<<<Missing ", (name) flashlight-->0, " in ", (name) loc_now, 
3946 !                      " (wanted to set it to ", setting_next, ")>>>^";
3947         }
3948     }
3949 ];
3950
3951 [MaybeSetPanel setting_array setting_now setting_next;
3952     setting_now = Get2D(setting_array, time_travelled - 1, my_time - EARLIEST_TIME - 1);
3953     setting_next = Get2D(setting_array, time_travelled - 1, my_time - EARLIEST_TIME);
3954     if (setting_next ~= UNKNOWN_ && setting_next ~= setting_now) { 
3955         control_panel.time_value = setting_next;
3956     }
3957 ];
3958
3959 [MaybeSetBasementLight setting_array setting_now setting_next;
3960     setting_now = Get2D(setting_array, time_travelled - 1, my_time - EARLIEST_TIME - 1);
3961     setting_next = Get2D(setting_array, time_travelled - 1, my_time - EARLIEST_TIME);
3962     if (setting_next ~= UNKNOWN_ && setting_next ~= setting_now) { 
3963         basement_light_switch.blown = setting_next;
3964     }
3965 ];
3966
3967 [MaybeSetGroundLight setting_array setting_now setting_next;
3968     setting_now = Get2D(setting_array, time_travelled - 1, my_time - EARLIEST_TIME - 1);
3969     setting_next = Get2D(setting_array, time_travelled - 1, my_time - EARLIEST_TIME);
3970     if (setting_next ~= UNKNOWN_ && setting_next ~= setting_now) { 
3971         ground_equipment.lit = setting_next;
3972         if (setting_next)
3973             give ground_light_switch on;
3974         else
3975             give ground_light_switch ~on;
3976     }
3977 ];
3978
3979 [MaybeCloseAutomaticDoor door;
3980     if (door.just_closed)
3981         door.just_closed = false;
3982     if (~~deadflag)
3983         if (door.to_close_at == my_time - 1)
3984             door.close_self();
3985 ];
3986
3987 !! Opens/closes/locks/unlocks doors for the past self and catches paradoxes that could not
3988 !! be seen, but where the locked/unlocked state of the door differs and interferes with the action.
3989 !! Also works when the former self unlocks an unlocked door or locks
3990 !! a locked door, but this door had the converse state and the key actually turns.
3991
3992 [MaybeSetManualDoor door door_state past_door_status_now past_door_status_next
3993                     present_door_status_now the_action t;
3994     
3995     for (t=0 : t<time_travelled : t++) {
3996
3997         past_door_status_now = Get2D(door_state, t, my_time - EARLIEST_TIME - 1);
3998         past_door_status_next = Get2D(door_state, t, my_time - EARLIEST_TIME);
3999
4000         present_door_status_now = Get2D(door_state, time_travelled, my_time - EARLIEST_TIME - 1);
4001         
4002         the_action = Get2D(dangerous_activity, t, my_time - EARLIEST_TIME - 1);
4003
4004 !-- if there was a locking/unlocking, check for paradox:
4005         if (Get2D(activity_target, t, my_time - EARLIEST_TIME - 1) == door) {
4006             if (the_action == UNLOCK_) {
4007                 if ((present_door_status_now == CLOSED_) && (past_door_status_now == LOCKED_)) {
4008                     d_paradox = true;
4009                     deadflag = 3;
4010                     Seperator();
4011                                 print (Nearby) 0, "your past self attempts to unlock ", (the) door,
4012                                       " but finds it already unlocked.^"; 
4013                     print "^Time unravels...^";
4014                     Devours(my_time);                            
4015                 }
4016                 else if ((present_door_status_now == LOCKED_) && (past_door_status_now == CLOSED_)) {
4017                     d_paradox = true;
4018                     deadflag = 3;
4019                     Seperator();
4020                                 print (Nearby) 0, "your past self foolishly attempts to unlock ", (the) door,
4021                                       " and succeeds where you had originally found it already unlocked.^"; 
4022                     print "^Time unravels...^";
4023                     Devours(my_time);                            
4024                 }
4025             }
4026             if (the_action == LOCK_) {
4027                 if ((present_door_status_now == CLOSED_) && (past_door_status_now == LOCKED_)) {
4028                     d_paradox = true;
4029                     deadflag = 3;
4030                     Seperator();
4031                                 print (Nearby) 0, "your past self foolishly attempts to lock ", (the) door,
4032                                       " and succeeds where you had originally found it already locked.^"; 
4033                     print "^Time unravels...^";
4034                     Devours(my_time);                            
4035                 }
4036                 if ((present_door_status_now == LOCKED_) && (past_door_status_now == CLOSED_)) {
4037                     d_paradox = true;
4038                     deadflag = 3;
4039                     Seperator();
4040                                 print (Nearby) 0, "your past self attempts to lock ", (the) door,
4041                                       " but finds it already locked.^"; 
4042                     print "^Time unravels...^";
4043                     Devours(my_time);                            
4044                 }
4045             }
4046             if (the_action == OPEN_) {
4047                 if ((present_door_status_now == CLOSED_) && (past_door_status_now == LOCKED_)) {
4048                     d_paradox = true;
4049                     deadflag = 3;
4050                     Seperator();
4051                                 print (Nearby) 0, "your past self foolishly attempts to open ", (the) door,
4052                                       " and succeeds where you had originally found it locked.^"; 
4053                     print "^Time unravels...^";
4054                     Devours(my_time);                            
4055                 }
4056                 if ((present_door_status_now == LOCKED_) && (past_door_status_now == CLOSED_)) {
4057                     d_paradox = true;
4058                     deadflag = 3;
4059                     Seperator();
4060                                 print (Nearby) 0, "your past self attempts to open ", (the) door,
4061                                       " but finds it locked.^"; 
4062                     print "^Time unravels...^";
4063                     Devours(my_time);                            
4064                 }
4065             }
4066         }
4067         
4068 !-- if there should be a state change, do it:
4069         if (~~d_paradox) {
4070             if ((past_door_status_now ~= past_door_status_next) && (past_door_status_next ~= UNKNOWN_)) {             
4071                 if (past_door_status_now == present_door_status_now) {
4072                     if (past_door_status_next == LOCKED_) {
4073                         give door ~open;
4074                         give door locked;
4075                         if (door in real_location)
4076                             print "You hear someone locking the ", (name) door, ".^";
4077                     }
4078                     if (past_door_status_next == CLOSED_) {
4079                         give door ~open;
4080                         give door ~locked;
4081                         if (door in real_location && past_door_status_now == LOCKED_)
4082                             print "You hear someone unlocking the ", (name) door, ".^";
4083                         if (door in real_location && past_door_status_now == OPEN_)
4084                             print "Someone closes ", (name) door, ".^";
4085                     }
4086                     if (past_door_status_next == OPEN_) {
4087                         give door open;
4088                         give door ~locked;
4089                         if (door in real_location)
4090                             print "Someone opens the ", (name) door, ".^";
4091                     }
4092                 }
4093             }
4094         }
4095         
4096     }
4097 ];
4098
4099 [MaybeSetAutomaticDoor door door_state door_status_now door_status_next;
4100     door_status_now = Get2D(door_state, time_travelled - 1, my_time - EARLIEST_TIME - 1);
4101     door_status_next = Get2D(door_state, time_travelled - 1, my_time - EARLIEST_TIME);
4102     if (door_status_next == my_time) {
4103         door.open_self(my_time);
4104     }
4105     if ((door == main_doors) && (my_time == start_time - 1)) {
4106         door.open_self(my_time);
4107     }
4108 ];
4109
4110 [MaybeBreakDoor door door_smashed door_smashed_next;
4111     door_smashed_next = Get2D(door_smashed, time_travelled - 1, my_time - EARLIEST_TIME);
4112     if (door_smashed_next && (~~door.smashed)) {
4113         door.smashed = true;
4114     }
4115 ];
4116
4117 !----------------------------------------------------
4118 !
4119 ! 'Check' functions:   (these check for paradoxes, both active and passive)
4120
4121
4122 [CheckActiveParadox t action_de_jour trouble i j k flash_i_batteries flash_j_loc flash_j_batteries
4123                     past_count present_count too_heavy;
4124     action_de_jour = Get2D(dangerous_activity, t, my_time-EARLIEST_TIME-1);
4125     trouble = false;
4126
4127     for (t=0 : t < time_travelled : t++) {
4128         if (~~d_paradox) {
4129             switch (action_de_jour) {
4130                 X_CCTV_:
4131                     if (player in upstairs_corridor or ground_corridor or basement_corridor)
4132                         trouble = true;
4133                 X_UPSTAIRS_CORRIDOR_:
4134                     if (player in upstairs_corridor)
4135                         trouble = true;
4136                 X_UPSTAIRS_LANDING_:
4137                     if (player in upstairs_landing)
4138                         trouble = true;
4139                 X_GROUND_CORRIDOR_:
4140                     if (player in ground_corridor)
4141                         trouble = true;
4142                 X_FOYER_:
4143                     if (player in foyer)
4144                         trouble = true;
4145                 X_BASEMENT_CORRIDOR_:
4146                     if (player in basement_corridor)
4147                         trouble = true;
4148                 X_BASEMENT_LANDING_:
4149                     if (player in basement_landing)
4150                         trouble = true;
4151                 X_BALCONY_:
4152                     if (player in balcony)
4153                         trouble = true;
4154                 TAKE_FLASHLIGHT_:
4155                     for (i=0 : i<MAX_ITEM_COPIES : i++) {
4156                         if ((flashlight-->i) in (former_self-->t)) {
4157                             flash_i_batteries = BatteriesContained(flashlight-->i);
4158                             past_count = 0;
4159                             present_count = 0;
4160                             for (j=0 : j < MAX_ITEM_COPIES : j++)
4161                                 if ((flashlight-->j) in (former_self-->t))
4162                                     if (BatteriesContained(flashlight-->j) == flash_i_batteries)
4163                                         present_count++;
4164                             for (j=0 : j < MAX_ITEM_COPIES : j++) {
4165                                 flash_j_loc = Get3D(flashlight_loc,t,my_time-EARLIEST_TIME,j);
4166                                 flash_j_batteries = 0;
4167                                 for (k=0 : k<MAX_ITEM_COPIES : k++) {
4168                                     if (Get3D(battery_loc,t,my_time-EARLIEST_TIME,k) == (flashlight-->j))
4169                                         flash_j_batteries++;
4170                                 }
4171                                 if (flash_j_loc == former_self-->t)
4172                                     if (flash_j_batteries == flash_i_batteries)
4173                                         past_count++;
4174                             }               
4175                             if (present_count ~= past_count) {
4176                                 too_heavy = (past_count < present_count);
4177                                 trouble = true;
4178                             }
4179                         }
4180                     }
4181                 BLOW_BASEMENT_LIGHT_:
4182                     if (Get2D(basement_equipment_light, time_travelled, my_time-EARLIEST_TIME-1) == true)
4183                         trouble = true;
4184             }
4185             if (trouble) {
4186                 d_paradox = true;
4187                 deadflag = 3;
4188                 Seperator();
4189                 switch (action_de_jour) {
4190                     X_CCTV_:
4191                         print "In the foyer, your past self glances at a CCTV screen and sees you in the 
4192                                shadowed corridor.^";
4193                     X_UPSTAIRS_CORRIDOR_:
4194                         if (former_self-->t in balcony)
4195                             print "From the chilly balcony, your former self looks through the glass door
4196                                    and sees you in the shadowed corridor.^";
4197                         else
4198                             print "From the upstairs landing, your former self looks through the glass
4199                                    and sees you in the shadowed corridor.^";
4200                     X_UPSTAIRS_LANDING_:
4201                         print "From the second floor corridor, your former self looks through the glass door
4202                                and sees you in the shadowy landing.^";
4203                     X_GROUND_CORRIDOR_:
4204                         print "From within the foyer, your former self looks through
4205                                the glass door and sees you in the shadowed corridor.^";
4206                     X_FOYER_:
4207                         if (former_self-->t in upstairs_landing)
4208                             print "From the landing above, your former self looks down
4209                                    and sees you.^";
4210                         else
4211                             print "From the first floor corridor, your former self looks through
4212                                    the glass door and sees you.^";
4213                     X_BASEMENT_CORRIDOR_:
4214                         print "From the basement landing, your former self looks through the glass door
4215                                and sees you in the shadowed corridor.^";
4216                     X_BASEMENT_LANDING_:
4217                         print "From the basement corridor, your former self looks through the glass door
4218                                and sees you in the shadowy landing.^";
4219                     X_BALCONY_:
4220                         if (former_self-->t in upstairs_corridor)
4221                             print "From the second floor corridor, your former self looks through the glass door
4222                                    and sees you on the chilly balcony.^";
4223                         else
4224                             print "From within the darkened conference room, your former self looks out
4225                                    and sees you on the chilly balcony.^";
4226                     TAKE_FLASHLIGHT_:
4227                         if (too_heavy)
4228                             print (Nearby) 0, "your past self picks up a flashlight, but finds it
4229                                    strangely heavy.^";
4230                         else
4231                             print (Nearby) 0, "your past self picks up a flashlight, but finds it
4232                                    strangely light.^";
4233                     BLOW_BASEMENT_LIGHT_:
4234                         print "In the basement equipment room, your past self switches on the light
4235                                but there is no flicker, for it has already blown.^";
4236                 }
4237                 if ((action_de_jour >= X_CCTV_) && (action_de_jour <= X_BALCONY_))
4238                     print "^This is one of the all time most embarrassing ways
4239                             to destroy the city of Boston.^";
4240                 print "^Time unravels...^";
4241                 Devours(my_time); 
4242             }
4243         }
4244     }
4245 ];
4246
4247
4248 [CheckPassiveParadox t;
4249     for (t=0 : t < time_travelled : t++)
4250         if (LocationOf(former_self-->t) ~= limbo) {
4251             CheckPlayerInRoom(t);
4252             CheckStateOfSiren(t);
4253             
4254             CheckStateOfDoors(t);
4255
4256             CheckStateOfGroundLight(t);
4257     
4258             CheckQuantityInRoom(bomb,bomb_loc,t);
4259             CheckQuantityInRoom(id_card,id_card_loc,t);
4260             CheckQuantityInRoom(equipment_key,equipment_key_loc,t);
4261             CheckQuantityInRoom(deutsch_key,deutsch_key_loc,t);
4262             CheckQuantityInRoom(flashlight,flashlight_loc,t);
4263             CheckQuantityInRoom(battery,battery_loc,t);
4264             CheckQuantityInRoom(cable,cable_loc,t);
4265             CheckQuantityInRoom(crowbar,crowbar_loc,t);
4266             CheckQuantityInRoom(notes,notes_loc,t);
4267             
4268             CheckStateOfFlashlights(t);
4269     
4270             if (former_self-->t in foyer)
4271                 CheckObjectsOnDesk(security_desk,t);
4272             if (former_self-->t in conference_room) {
4273                 CheckObjectsOnDesk(conference_table,t);
4274                 CheckObjectsOnDesk(chair,t);
4275             }
4276             if (former_self-->t in deutsch_lab)
4277                 CheckObjectsOnDesk(bench,t);
4278             if (former_self-->t in prototype_interior)
4279                 CheckTimeOnPanel(t);
4280                 
4281             CheckTimesOnBombs(t);       
4282         }
4283 ];
4284
4285 [CheckStateOfDoors t fs_loc;
4286     fs_loc = LocationOf(former_self-->t);
4287     
4288     switch (fs_loc) {
4289         foyer:
4290             CheckStateOfDoor(main_doors, main_doors_state, t, fs_loc);
4291             CheckStateOfDoor(ground_door, ground_door_state, t, fs_loc);
4292             CheckBrokenDoor(main_doors, main_doors_smashed, t, fs_loc);
4293             CheckBrokenDoor(ground_door, ground_door_smashed, t, fs_loc);
4294         ground_corridor:
4295             CheckStateOfDoor(ground_door, ground_door_state, t, fs_loc);
4296             CheckBrokenDoor(ground_door, ground_door_smashed, t, fs_loc);
4297             CheckStateOfDoor(ground_equipment_door, ground_equipment_door_state, t, fs_loc);
4298         ground_equipment:
4299             CheckStateOfDoor(ground_equipment_door, ground_equipment_door_state, t, fs_loc);
4300         basement_landing:
4301             CheckStateOfDoor(basement_door, basement_door_state, t, fs_loc);
4302             CheckBrokenDoor(basement_door, basement_door_smashed, t, fs_loc);
4303         basement_corridor:
4304             CheckStateOfDoor(basement_door, basement_door_state, t, fs_loc);
4305             CheckBrokenDoor(basement_door, basement_door_smashed, t, fs_loc);
4306             CheckStateOfDoor(basement_equipment_door, basement_equipment_door_state, t, fs_loc);
4307             CheckStateOfDoor(deutsch_door, deutsch_door_state, t, fs_loc);
4308         deutsch_lab:
4309             CheckStateOfDoor(deutsch_door, deutsch_door_state, t, fs_loc);
4310         prototype_interior:
4311             CheckStateOfDoor(deutsch_door, deutsch_door_state, t, fs_loc);
4312         upstairs_landing:
4313             CheckStateOfDoor(upstairs_door, upstairs_door_state, t, fs_loc);
4314             CheckBrokenDoor(upstairs_door, upstairs_door_smashed, t, fs_loc);
4315         upstairs_corridor:
4316             CheckStateOfDoor(upstairs_door, upstairs_door_state, t, fs_loc);
4317             CheckStateOfDoor(balcony_door, balcony_door_state, t, fs_loc);
4318             CheckBrokenDoor(upstairs_door, upstairs_door_smashed, t, fs_loc);
4319             CheckBrokenDoor(balcony_door, balcony_door_smashed, t, fs_loc);
4320         balcony:
4321             CheckStateOfDoor(balcony_door, balcony_door_state, t, fs_loc);
4322             CheckBrokenDoor(balcony_door, balcony_door_smashed, t, fs_loc);
4323             CheckStateOfDoor(conference_window, conference_window_state, t, fs_loc);
4324         conference_room:
4325             CheckStateOfDoor(conference_window, conference_window_state, t, fs_loc);
4326         default:
4327             return false;
4328     }
4329 ];
4330
4331 ! this is a tiny bit of a hack, using the fact that OPEN_ is higher than CLOSED_, LOCKED_.
4332 ! and the fact that automatic doors which are open have values higher than OPEN_.
4333
4334 [CheckStateOfDoor door door_state t fs_loc past_door_state fs_loc_last_turn;
4335     past_door_state = Get2D(door_state,t,my_time-EARLIEST_TIME);
4336     fs_loc_last_turn = Get2D(player_loc,t,my_time-EARLIEST_TIME-1);
4337
4338     if (~~d_paradox) {
4339         if ((past_door_state >= OPEN_) && (door hasnt open)) {
4340             d_paradox = true;
4341             deadflag = 3;
4342             Seperator();
4343             print (Nearby) 0, "your former self enters ", (TheLower) fs_loc,
4344                   " and sees ", (the) door, " pulled closed.^"; 
4345             print "^Time unravels...^";
4346             Devours(my_time);                            
4347         }
4348         else if ((past_door_state < OPEN_) && (door has open)) {
4349             d_paradox = true;
4350             deadflag = 3;
4351             Seperator();
4352             if (door ~= conference_window) {
4353                 if (fs_loc_last_turn ~= fs_loc)
4354                     print (Nearby) 0, "your former self enters ", (TheLower) fs_loc,
4355                           " and sees ", (the) door, " standing open.^";      
4356                 else
4357                     print (Nearby) 0, "your former self standing in ", (TheLower) fs_loc,
4358                           " sees ", (the) door, " open.^";   
4359             }   
4360             else
4361                 print (Nearby) 0, "your former self enters ", (TheLower) fs_loc,
4362                       " and sees the shattered conference room window.^";                         
4363             print "^Time unravels...^";
4364             Devours(my_time); 
4365         }
4366     }
4367 ];
4368
4369
4370 [CheckBrokenDoor door door_smashed t fs_loc past_door_smashed_now past_door_smashed_next;
4371     past_door_smashed_now  = Get2D(door_smashed,t,my_time-EARLIEST_TIME-1);
4372     past_door_smashed_next = Get2D(door_smashed,t,my_time-EARLIEST_TIME);
4373     if (~~d_paradox) {
4374         if ((~~past_door_smashed_next) && door.smashed) {
4375             d_paradox = true;
4376             deadflag = 3;
4377             Seperator();
4378             if (past_door_smashed_now)
4379                 print "In ", (TheLower) fs_loc, ", your former self sees the web of cracks in ",
4380                       (the) door, ".^"; 
4381             else
4382                 print "In ", (TheLower) fs_loc, ", your former self hears the crack of your
4383                        crowbar smashing into ",
4384                       (the) door, ".^"; 
4385             print "^Time unravels...^";
4386             Devours(my_time);
4387         }
4388     }
4389
4390 ];
4391
4392 [CheckTimesOnBombs t i j bomb_i_time bomb_j_time bomb_j_loc 
4393                    past_count present_count fs_loc;
4394                    
4395     fs_loc = LocationOf(former_self-->t);
4396     
4397     if (~~d_paradox) {
4398         for (i=0 : i < MAX_ITEM_COPIES : i++) {
4399             if (LocationOf(bomb-->i) == fs_loc) {
4400                 bomb_i_time = (bomb-->i).time_value;
4401                 past_count = 0;
4402                 present_count = 0;
4403                 for (j=0 : j < MAX_ITEM_COPIES : j++)
4404                     if (LocationOf(bomb-->j) == fs_loc)
4405                         if ((bomb-->j).time_value == bomb_i_time)
4406                             present_count++;
4407                 for (j=0 : j < MAX_ITEM_COPIES : j++) {
4408                     bomb_j_loc = Get3D(bomb_loc,t,my_time-EARLIEST_TIME,j);
4409                     bomb_j_time = Get3D(bomb_setting,t,my_time-EARLIEST_TIME,j);
4410                     if (((bomb_j_loc == fs_loc) || (parent(bomb_j_loc) == fs_loc)))
4411                         if (bomb_j_time == bomb_i_time)
4412                             past_count++;
4413                 }               
4414                 if (past_count ~= present_count) {
4415                     d_paradox = true;
4416                     deadflag = 3;
4417                     Seperator();
4418                     print (Nearby) 0, "your former self enters ", (TheLower) fs_loc,
4419                           " and sees a different value flashing on the explosive device's
4420                            timer.^"; 
4421                     print "^Time unravels...^";
4422                     Devours(my_time);                            
4423                 }
4424             }
4425         }
4426     }
4427
4428 ];
4429
4430 [CheckStateOfFlashlights t i present_flashlights_on past_flashlights_on
4431                          fs_loc flash_loc flash_state;
4432     fs_loc = LocationOf(former_self-->t);
4433     if (~~d_paradox) {
4434         for (i=0 : i < MAX_ITEM_COPIES : i++) {
4435             flash_loc = Get3D(flashlight_loc,t,my_time-EARLIEST_TIME,i);
4436             flash_state = Get3D(flashlight_state,t,my_time-EARLIEST_TIME,i);
4437             if (flash_state && ((flash_loc == fs_loc) || (parent(flash_loc) == fs_loc)))
4438                 past_flashlights_on++;
4439             if ((flashlight-->i has on) && (LocationOf(flashlight-->i) == fs_loc))
4440                 present_flashlights_on++;
4441         }
4442         if (past_flashlights_on ~= present_flashlights_on) {
4443                 d_paradox = true;
4444                 deadflag = 3;
4445                 Seperator();
4446                 if (past_flashlights_on < present_flashlights_on)
4447                     print (Nearby) 0, "your former self enters ", (TheLower) fs_loc,
4448                           " and sees a thin white beam of light shining where once
4449                            was darkness.^"; 
4450                 else
4451                     print (Nearby) 0, "your former self enters ", (TheLower) fs_loc,
4452                           " and sees only darkness where once a thin white beam of light
4453                             was shining.^";
4454                 print "^Time unravels...^";
4455                 Devours(my_time);        
4456         }
4457     }
4458 ];
4459
4460 ! only need to check if in corridor with open door as this will catch all cases
4461
4462 [CheckStateOfGroundLight t past_ground_light_state;
4463     past_ground_light_state = Get2D(ground_equipment_light,t,my_time-EARLIEST_TIME);
4464
4465     if (~~d_paradox)
4466         if ((ground_light_switch has on) ~= past_ground_light_state) {
4467             if ((former_self-->t in ground_corridor) && (ground_equipment_door has open)) {
4468                 d_paradox = true;
4469                 deadflag = 3;
4470                 Seperator();
4471                 if (ground_light_switch has on) {
4472                     if (Get2D(ground_equipment_door_state,t,my_time-EARLIEST_TIME-1)==OPEN_)
4473                         print (Nearby) 0, "your former self enters the first floor corridor
4474                                and sees a pool of light spilling from the equipment room.^"; 
4475                     else
4476                         print (Nearby) 0, "your former self opens the door to the first floor
4477                                equipment room and bright fluorescent light
4478                                spills over her.^";
4479                 }
4480                 else {
4481                     if (Get2D(ground_equipment_door_state,t,my_time-EARLIEST_TIME-1)==OPEN_)
4482                         print (Nearby) 0, "your former self enters the first floor corridor
4483                                but does not see a pool of light spilling from the
4484                                equipment room.^"; 
4485                     else
4486                         print (Nearby) 0, "your former self opens the door to the first floor
4487                                equipment room but no bright fluorescent light
4488                                spills over her.^";
4489                 }
4490                 print "^Time unravels...^";
4491                 Devours(my_time);
4492             }
4493         }
4494 ];
4495
4496 [CheckStateOfSiren t past_state siren_on;
4497     past_state = Get2D(siren_state,t,my_time-EARLIEST_TIME);
4498     siren_on = (siren_start_time ~= UNKNOWN_) && (siren_start_time < my_time);
4499
4500     if (~~d_paradox)
4501         if (past_state ~= siren_on) {
4502                 if (my_time - siren_start_time == 1)
4503                     print "^A piercing siren rings out.^";
4504                 if (my_time - siren_start_time > 1)
4505                     print "^The siren wails.^";
4506                 d_paradox = true;
4507                 deadflag = 3;
4508                 Seperator();
4509                 print (Nearby) 0, "your former self cringes from the sound of the siren.^"; 
4510                 print "^Time unravels...^";
4511                 Devours(my_time);
4512             }
4513 ];
4514
4515
4516 !! Only checks the bare contents of the room, not the containers, states etc.
4517
4518 [CheckQuantityInRoom thing_type thing_loc t i present_count past_count;
4519     present_count = 0;
4520     past_count = 0;
4521     
4522     if (~~d_paradox) {
4523         for (i=0 : i < Exp(2,t+1) : i++) {
4524             if (parent(thing_type-->i) == LocationOf(former_self-->t))
4525                 present_count++;  
4526             if (Get3D(thing_loc,t,my_time-EARLIEST_TIME,i) == LocationOf(former_self-->t))
4527                 past_count++;
4528         }
4529         if (past_count ~= present_count) {
4530             d_paradox = true;
4531             deadflag = 3;
4532             Seperator();
4533             print "Entering ", (TheLower) LocationOf(former_self-->t),
4534                   " your past self looks quickly about. ";
4535             if (past_count > present_count)
4536                 print "Unlike the last time, her gaze passes straight over the place
4537                        where ", (the) thing_type-->0,
4538                       " had lain.^"; 
4539             else
4540                 print "As her glance falls upon ", (the) thing_type-->0,
4541                       " a moment of worry passes over her features.^"; 
4542             print "^Time unravels...^";
4543             Devours(my_time);
4544         }
4545     }
4546 ];
4547
4548 [CheckPlayerInRoom t player_loc_now player_loc_next fs_loc_now fs_loc_next;
4549
4550     player_loc_now  = Get2D(player_loc,time_travelled,my_time-EARLIEST_TIME-1);
4551     player_loc_next = Get2D(player_loc,time_travelled,my_time-EARLIEST_TIME);
4552     fs_loc_now      = Get2D(player_loc,t,my_time-EARLIEST_TIME-1);
4553     fs_loc_next     = Get2D(player_loc,t,my_time-EARLIEST_TIME);
4554
4555     if ((player_loc_next == fs_loc_next)) {
4556         if (player_loc_now == nothing) {
4557             d_paradox = true;
4558             deadflag = 3;
4559             Seperator();
4560             print "Someone appears beside you in the cramped chamber.
4561                    Soft hair and anxious eyes. It is you.^";
4562             print "^Time unravels...^";
4563             Devours(my_time);
4564         }
4565         else if (player_loc_now ~= player_loc_next) {    !! if the player had moved...
4566             d_paradox = true;
4567             deadflag = 3;
4568             Seperator();
4569             print "As you enter ", (TheLower) player_loc_next,
4570                   " you see your former self standing before you.
4571                    Hearing your soft footfall, she turns. Horror fills her eyes.^";
4572             print "^Time unravels...^";
4573             Devours(my_time);
4574         }
4575         else if (fs_loc_now ~= fs_loc_next) {       !! if the former self had moved...
4576             d_paradox = true;
4577             deadflag = 3;
4578             Seperator();
4579             print "You turn at the sound of footsteps. It is you.^";
4580             print "^Time unravels...^";
4581             Devours(my_time);
4582         }
4583         else
4584             print "Error, former self saw player but neither had moved.^";
4585     }
4586     else if ((player_loc_next == fs_loc_now) && (player_loc_now == fs_loc_next)) {
4587             d_paradox = true;
4588             deadflag = 3;
4589             Seperator();
4590             print "As you enter ", (TheLower) player_loc_next,
4591                   ", your eyes catch upon a figure coming towards you.
4592                    She pauses, fear all about her.^";
4593             print "^Time unravels...^";
4594             Devours(my_time);
4595     }
4596     else if ((player_loc_next == deutsch_lab) && (fs_loc_next == prototype_interior)) {
4597             d_paradox = true;
4598             deadflag = 3;
4599             Seperator();
4600             print "Hunched inside the prototype, your former self sees you through the open
4601                    hatch.^";
4602             print "^Time unravels...^";
4603             Devours(my_time);
4604     }
4605     else if ((player_loc_next == prototype_interior) && (fs_loc_next == deutsch_lab)) {
4606             d_paradox = true;
4607             deadflag = 3;
4608             Seperator();
4609             print "As your past self looks around, her eyes catch on
4610                    something inside the prototype.^";
4611             print "^Time unravels...^";
4612             Devours(my_time);
4613     }
4614     
4615 ];
4616
4617 [CheckObjectsOnDesk desk t;
4618     CheckObjectOnDesk(desk, t, bomb, bomb_loc);
4619     CheckObjectOnDesk(desk, t, id_card, id_card_loc);
4620     CheckObjectOnDesk(desk, t, equipment_key, equipment_key_loc);
4621     CheckObjectOnDesk(desk, t, deutsch_key, deutsch_key_loc);
4622     CheckObjectOnDesk(desk, t, flashlight, flashlight_loc);
4623     CheckObjectOnDesk(desk, t, battery, battery_loc);
4624     CheckObjectOnDesk(desk, t, cable, cable_loc);
4625     CheckObjectOnDesk(desk, t, crowbar, crowbar_loc);
4626     CheckObjectOnDesk(desk, t, notes, notes_loc);            
4627 ];
4628
4629 [CheckObjectOnDesk desk t thing_type thing_loc present_count past_count i;
4630     if (~~d_paradox) {
4631         for (i=0 : i < Exp(2,t+1) : i++) {
4632             if (thing_type-->i in desk)
4633                 present_count++;
4634             if (Get3D(thing_loc,t,my_time-EARLIEST_TIME,i) == desk)
4635                 past_count++;
4636         }
4637         if (past_count ~= present_count) {
4638             d_paradox = true;
4639             deadflag = 3;
4640             Seperator();
4641             print "Entering ", (TheLower) LocationOf(former_self-->t),
4642                   " your past self looks quickly about. ";
4643             if (past_count > present_count)
4644                 print "Unlike the last time, her gaze passes straight over the place
4645                        on ", (the) desk, " where ", (the) thing_type-->0,
4646                       " had lain.^"; 
4647             else
4648                 print "As her glance falls upon ", (the) thing_type-->0,
4649                       " a moment of worry passes over her features.^"; 
4650             print "^Time unravels...^";
4651             Devours(my_time);
4652         }
4653     }
4654 ];
4655
4656 [CheckTimeOnPanel t old_setting;
4657     old_setting = Get2D(panel_setting, t, my_time-EARLIEST_TIME);
4658     if (~~d_paradox)
4659         if (control_panel.time_value ~= old_setting) {
4660             d_paradox = true;
4661             deadflag = 3;
4662             Seperator();
4663             print "Entering the prototype, your past self glances at the control panel,
4664                    seeing ", control_panel.time_value, " instead of ", old_setting, ".^"; 
4665             print "^Time unravels...^";
4666             Devours(my_time);        
4667         }
4668 ];
4669
4670
4671 !----------------------------------------------------
4672 !
4673 ! Endgame functions:
4674
4675
4676 [CaughtInside t;
4677     d_caught = true;
4678
4679 !-- Initial method of being caught:
4680         
4681     if (my_time > FINAL_TIME)
4682         print "^A quick noise from behind, then a strong grip on your wrist.
4683                The guard is back -- time has slipped away from you.^";
4684     else if ((siren_start_time ~= UNKNOWN_) && (my_time - siren_start_time > siren_timeout))
4685         print "^As the siren shrieks out around you, you catch a glimpse of movement.
4686                A sudden jolt, then you are wrestled to the ground. Security has arrived.^";
4687     else
4688         print "Error: unknown reason for being caught^";
4689     
4690 !-- Allow a small amount of time for bomb to explode before player dragged off...
4691     
4692     for (t=0 : (t<TIME_BEFORE_DRAGGED_OFF) && (my_time<FINAL_TIME) && (~~d_exploded) : t++) {
4693         IncTime();    ! as it happens, this can lead to bomb-explosion, but not paradox
4694     }
4695     
4696     if (~~d_exploded)     ! make sure player is dragged off
4697         DragPlayerOff();
4698 ];
4699
4700 [Jumped;
4701     if (~~warned_of_jump) {
4702         print "It is a large drop and you are not at all sure that you could make it
4703                without serious injury.^";
4704         warned_of_jump = true;
4705         return true;
4706     }
4707     
4708     d_caught = true;
4709
4710 !-- Initial method of being caught:
4711         
4712     print "You hit the ground hard and collapse. Your right ankle sears with pain.
4713            Before you can stand, you see the security guard running swiftly towards you.^";
4714     
4715     DragPlayerOff();
4716 ];
4717
4718
4719 [DragPlayerOff t;
4720
4721     print "^Deaf to your protests, the guard ";
4722     if (AmHolding(bomb) && ((GetHeld(bomb)).time_value ~= NA_))
4723         print "disarms your bomb, ";
4724     print "handcuffs you and forces you
4725            into a dark sedan. You speed through the chill Boston night, head held in your hands,
4726            almost oblivious to the blur of the suburbs rushing past.^";
4727
4728     d_detained = true;
4729     move player to limbo;
4730     
4731 !-- Allow some more time for bomb to explode
4732 !-- and for paradoxes to occur
4733
4734     for (t=0 : (my_time<FINAL_TIME) && (~~d_exploded) && (~~d_paradox) : t++) {
4735         IncTime();
4736     }
4737     
4738     MaybeExplodeBombAfterwards();
4739         
4740     deadflag = 3;
4741         
4742 !-- Consequences of being caught:
4743
4744     if (~~d_paradox) {
4745         print "^Half an hour later, the car pulls up outside a non-descript building and you
4746                 are dragged inside";
4747         if (AmHolding(notes))
4748             print ", the notes are taken from you and you are ";
4749         else
4750             print " then ";
4751         print "thrown into a small cell to await questioning.^";
4752                 
4753         if (d_exploded) {
4754             if (d_destroyed_prototype && d_destroyed_notes) {
4755                 print "^The months that follow are a nightmare. Solitary confinement, sleepless nights,
4756                         merciless interrogations. Eventually, you are taken before a civilian court and
4757                         tried for treason. A drawn-out trial, a guilty verdict, prison. Ambitions falter and
4758                         then fade. Still, as the months and then years pass, they do not bring the disaster
4759                         you had so feared and you cling, anxiously, longingly, to the dream that it was you who brought
4760                         this about, that your sacrifice was not in vain.^";
4761                 my_time = NA_;
4762                 DrawStatusLine();
4763                 deadflag = SAVED_CAUGHT_;
4764            }
4765 !            else if (d_destroyed_prototype && AmHolding(notes)) {
4766 !            }
4767             else if (d_destroyed_prototype) {
4768                 print "^The days that follow are a nightmare. Solitary confinement, sleepless nights,
4769                         merciless interrogations. All that keeps you going is the small hope that your actions
4770                         were not in vain.^";
4771                 Seperator();
4772                 print "With your research notes at hand, the military scientists painstakingly rebuild the
4773                        prototype and prepare it for testing.^";
4774             }
4775 !            else if (d_destroyed_notes) {
4776 !                print " ";
4777 !            }            
4778 !            else if (AmHolding(notes)) {
4779 !                print " ";
4780 !            }        
4781 !            else {
4782 !                print " ";
4783 !            }
4784         }          
4785 !        else if (AmHolding(bomb) && AmHolding(notes)) {
4786 !            print " ";
4787 !        }
4788 !        else if (AmHolding(bomb)) {
4789 !            print " ";
4790 !        }
4791 !        else if (AmHolding(notes)) {
4792 !            print " ";
4793 !        }
4794 !        else {
4795 !            print " ";
4796 !        }
4797
4798         if ((~~d_destroyed_prototype) || (~~d_destroyed_notes))         
4799            MilitaryTest(); 
4800     }
4801 ];
4802
4803 [InBlastRadius thing bomb;
4804     if (LocationOf(thing) == LocationOf(bomb))
4805         return true;
4806     if ((LocationOf(bomb) == deutsch_lab) && (LocationOf(thing) == prototype_interior))
4807         return true;
4808     if ((LocationOf(bomb) == prototype_interior) && (LocationOf(thing) == deutsch_lab))
4809         return true;
4810     return false;
4811 ];
4812
4813 [MaybeExplodeBombAfterwards i j;
4814     if (~~d_exploded)
4815         for (i=0 : i<MAX_ITEM_COPIES : i++)
4816             if (((bomb-->i).time_value >= FINAL_TIME) && ~~(bomb-->i in player)) {
4817                 d_exploded = true;
4818                 if (LocationOf(bomb-->i) == deutsch_lab or prototype_interior)
4819                     d_destroyed_prototype = true;
4820                 for (j=0 : j < MAX_ITEM_COPIES : j++)
4821                     if (InBlastRadius(notes-->j,bomb-->i))
4822                         d_destroyed_notes = true;
4823             }
4824 ];
4825
4826 [ExplodeBomb i j t;
4827
4828     if (d_exploded)
4829         return true;
4830         
4831     d_exploded = true;
4832
4833 !-- what exploded?
4834           
4835     if ((~~(d_escaped || d_detained)) && InBlastRadius(player,bomb-->i) )
4836         d_killed_by_bomb = true;
4837     if (~~(d_escaped || d_detained))
4838         d_injured_by_bomb = true;
4839     if (LocationOf(bomb-->i) == deutsch_lab or prototype_interior)
4840         d_destroyed_prototype = true;
4841     for (j=0 : j < MAX_ITEM_COPIES : j++)
4842         if (InBlastRadius(notes-->j,bomb-->i))
4843             d_destroyed_notes = true;
4844     for (t=0 : t < time_travelled : t++)
4845         if (InBlastRadius(former_self-->t, bomb-->i)) {
4846             d_fs_killed_by_bomb = true;
4847             d_paradox = true;
4848         }
4849     for (t=0 : t < time_travelled : t++)
4850         if ((LocationOf(former_self-->t) ~= limbo)) {
4851             d_fs_hears_bomb = true;
4852             d_paradox = true;
4853         }
4854     
4855 !-- Consequences of explosion
4856
4857     if (d_killed_by_bomb == true) {
4858         print "^The bomb detonates. A wall of force rips through the room with savage
4859                power, killing you immediately.^";
4860         if (~~d_fs_hears_bomb) {
4861             for (t=0 : (my_time<FINAL_TIME) && (~~d_paradox) : t++) {
4862                 IncTime();
4863             }
4864             deadflag = 3;
4865             if ((~~d_paradox) && d_destroyed_prototype && d_destroyed_notes) {
4866                 my_time = NA_;
4867                 DrawStatusLine();
4868                 deadflag = SAVED_DEAD_;
4869             }
4870             else 
4871                 MilitaryTest();
4872         }
4873     }
4874     else if (d_injured_by_bomb) {
4875         print "^The bomb detonates. You are knocked to the floor by the force of the
4876                explosion and your ears ring. ";
4877         if (~~d_fs_hears_bomb) {
4878             print "Stunned, you lie prone on the floor as
4879                    the siren wails and the reek of smoke stings your nostrils.^^
4880                    Before you recover your senses, security is upon you.^";
4881             DragPlayerOff(); 
4882         }
4883         else
4884             print "^";
4885     }
4886        
4887     if (d_fs_killed_by_bomb) {
4888         Seperator();
4889         if (d_detained || d_escaped)
4890             print "Across town, the bomb detonates.
4891                    The explosion tears into your former self and she falls lifeless to
4892                    the ground.^";
4893         else     
4894             print (Nearby) 0, "the explosion tears into your former self and she falls lifeless to
4895                    the ground.^";
4896         print "^Time unravels...^";
4897         Devours(my_time);
4898     }
4899     else if (d_fs_hears_bomb) {
4900         Seperator();
4901         if (d_detained || d_escaped)
4902             print "Across town, the bomb detonates.
4903                    Your former self is brought to her knees by the sudden blast,
4904                    the horror of understanding written in her eyes.^";
4905         else
4906             print (Nearby) 0, "your former self is brought to her knees by the sudden blast,
4907                    the horror of understanding written in her eyes.^";
4908         print "^Time unravels...^";
4909         Devours(my_time);
4910     }
4911
4912     
4913 ];
4914
4915 [Escaped t;
4916     d_escaped = true;
4917
4918     move player to outside;
4919
4920 !-- result of escaping:
4921   
4922     print "^";
4923         
4924     if (my_time >= FINAL_TIME - 3) {
4925         print "The night beckons you from the open doors, but as you rush
4926                forwards to meet it your hopes fail you -- security has arrived.^";
4927         d_caught = true;
4928         DragPlayerOff();  
4929     }
4930     else if ((siren_start_time ~= UNKNOWN_) && (my_time - siren_start_time > siren_timeout - 2)) {
4931         print "The night beckons you from the open doors, but as you rush
4932                forwards to meet it your hopes fail you. With the siren shrieking out around you, 
4933                security has arrived.^";
4934         d_caught = true;
4935         DragPlayerOff();   
4936     }
4937           
4938 !-- Deal with the true escapes:
4939     
4940     else {
4941         move player to limbo;
4942         
4943         print "You slip out into the night, darting quickly through the Cambridge
4944                shadows until you reach the quiet corner where you left your car.
4945                Exhausted, you gently start the cold motor and roll off towards the
4946                interstate.^";
4947                 
4948 !-- Step through the rest of the time to check for paradox and/or explosion
4949         
4950         for (t=0 : (my_time<FINAL_TIME) && (~~d_paradox) : t++) {
4951             IncTime();
4952         }
4953
4954         MaybeExplodeBombAfterwards();
4955      
4956         deadflag = 3;
4957             
4958 !-- Final wrap-up:
4959
4960         if (~~d_paradox) {
4961             if (d_exploded) {
4962                 if (d_destroyed_prototype && d_destroyed_notes) {
4963                     print "^Days, months, years run by. 
4964                             You find a new name, a new life. 
4965                             Fresh challenges are gladly met and life proceeds with full force in its
4966                             new and welcome direction. 
4967                             Only now and then do you stop on a chill starry night and
4968                             wonder whether you were right, what really would have happened.^";
4969                     my_time = NA_;
4970                     DrawStatusLine();
4971                     deadflag = SAVED_FREE_;
4972                }
4973                 else if (d_destroyed_prototype && AmHolding(notes) && challenge) {
4974                     print "^Days, months, years run by. 
4975                             You find a new name, a new life. 
4976                             You travel abroad.
4977                             Eventually, you look again at your time-stained research notes
4978                             and think of the possibilities.^^
4979                             The inconsistencies are the key; the freed energy.
4980                             Maybe now, without the shadow of military interests, you could
4981                             make something of this.^";
4982                     my_time = NA_;
4983                     DrawStatusLine();
4984                     deadflag = SAVED_FREE_CHALLENGE_;
4985                 }
4986                 else if (d_destroyed_prototype && AmHolding(notes)) {
4987                     print "^Days, months, years run by. 
4988                             You find a new name, a new life. 
4989                             Fresh challenges are gladly met and life proceeds with full force in its
4990                             new and welcome direction. 
4991                             Only now and then do you stop on a chill starry night and
4992                             wonder whether you were right, what really would have happened.^";
4993                     my_time = NA_;
4994                     DrawStatusLine();
4995                     deadflag = SAVED_FREE_;
4996                 }
4997                 else if (d_destroyed_prototype) {
4998                     print "^Days run by. You find a new name, begin a new life.
4999                             You hope, pray, that all you have done will stop them, that the
5000                             catastrophe will not come.^";
5001                     Seperator();
5002                     print "With your research notes at hand, the military scientists painstakingly rebuild the
5003                            prototype and prepare it for testing.^";
5004                     deadflag = DELAYED_;
5005                 }
5006 !                else if (d_destroyed_notes) {
5007 !                    print "^Escape: ~d-prototype + d-notes.^";
5008 !                }    
5009 !                else if (AmHolding(notes)) {
5010 !                    print "^Escape: useless explosion + holding notes.^";
5011 !                }        
5012                 else {
5013                     print "^Morning finds you in a truck-stop cafe, near Woodstock, NY. You sit there,
5014                             anxiously watching the morning news as you sip your bitter coffee.^";
5015                 }
5016             }          
5017 !            else if (AmHolding(bomb) && AmHolding(notes)) {
5018 !                print "^Escape: holding bomb + notes.^";
5019 !            }
5020 !            else if (AmHolding(bomb)) {
5021 !                print "^Escape: holding bomb.^";
5022 !            }
5023 !            else if (AmHolding(notes)) {
5024 !                print "^Escape: holding notes.^";
5025 !            }
5026             else {
5027                     print "^Morning finds you in a truck-stop cafe, near Woodstock, NY. You sit there,
5028                             anxiously watching the morning news as you sip your bitter coffee.^";
5029             }
5030     
5031             if (~~(d_destroyed_prototype && (d_destroyed_notes || AmHolding(notes)))) {
5032                MilitaryTest(); 
5033             }
5034         }
5035     }
5036 ];
5037
5038 ! tests whether something has happened to stop the player continuing their actions
5039
5040 [Stopped;
5041     if (d_paradox || d_caught || d_exploded || d_escaped)
5042         return true;
5043     else
5044         return false;
5045 ];
5046
5047 [Seperator;
5048     print "^*******^^";
5049 ];
5050
5051 [MilitaryTest;
5052     Devours(LATER_);
5053 ];
5054
5055 [Devours given_time explosion_time;
5056     
5057     Seperator();
5058     if (given_time == LATER_) {
5059         if (d_destroyed_prototype) {
5060             print "Monday 1st November 2004^^";
5061             explosion_time = EXPERIMENT2_TIME;
5062             deadflag = DELAYED_;
5063         }
5064         else {
5065             print "Wednesday 13th October 2004^^";
5066             explosion_time = EXPERIMENT1_TIME;
5067             deadflag = USELESS_;
5068         }
5069     }
5070     else {
5071         print "Tuesday 12th October 2004^^";
5072         deadflag = ACCELERATED_;
5073         explosion_time = last_travel_time; 
5074     }
5075     
5076     !my_time = explosion_time;   ! these lines would update the status line time
5077     !DrawStatusLine();
5078
5079     if (poem_interleaving) {
5080         print "At precisely ", (PrintShortTime) explosion_time, " this morning ";
5081         
5082         PoemStyleOn();
5083         print "This thing all things devours: ";
5084         PoemStyleOff();
5085     
5086         print "a catastrophe of unprecedented scale occurred. ";
5087             
5088         PoemStyleOn();
5089         print "birds, beasts, trees, flowers; ";
5090         PoemStyleOff();
5091         
5092         print "An immense explosion -- that could only have been atomic in nature -- ";
5093         
5094         PoemStyleOn();
5095         print "gnaws iron, bites steel; ";
5096         PoemStyleOff();   
5097         
5098         print "tore through the city and suburbs of Boston MA, destroying all in its path. ";
5099         
5100         PoemStyleOn();
5101         print "grinds hard stones to meal; ";
5102         PoemStyleOff();   
5103     
5104         print "Casualties will number in the millions and martial law has been declared. ";
5105     
5106         PoemStyleOn();
5107         print "slays king, ruins town; ";
5108         PoemStyleOff();   
5109         
5110         print "The military is mobilizing for war with the as yet unknown enemy. ";
5111         
5112         PoemStyleOn();
5113         print "and beats high mountain down. ";
5114         PoemStyleOff();   
5115         
5116         print "^";
5117     }
5118     else {
5119         print "At precisely ", (PrintShortTime) explosion_time, " this morning 
5120                a catastrophe of unprecedented scale occurred. 
5121                An immense explosion -- that could only have been atomic in nature --
5122                tore through the city and suburbs of Boston MA, destroying all in its path.
5123                Casualties are expected to number in the millions. The President has declared
5124                a state of emergency across the nation and
5125                the military is mobilizing for a possible war with the as yet unknown enemy.^^";
5126         PoemStyleOn();
5127         print "This thing all things devours:^";
5128         print "birds, beasts, trees, flowers;^";
5129         print "gnaws iron, bites steel;^";
5130         print "grinds hard stones to meal;^";
5131         print "slays king, ruins town;^";
5132         print "and beats high mountain down.^";
5133         PoemStyleOff();   
5134     }
5135
5136 ];
5137
5138 [PoemStyleOn;
5139     style bold;
5140 ];
5141
5142 [PoemStyleOff;
5143     style roman;
5144 ];
5145
5146 [ DeathMessage; 
5147     switch (deadflag) {
5148         ACCELERATED_:            print "You have failed";
5149         USELESS_:                print "You have failed";
5150         DELAYED_:                print "You have failed";
5151         SAVED_DEAD_:             print "Success, but at such a cost";
5152         SAVED_CAUGHT_:           print "Success, but at such a cost";
5153         SAVED_FREE_:             print "Success. Final, lasting success."; 
5154         SAVED_FREE_CHALLENGE_:   print "Success and, perhaps, a new hope."; 
5155     }
5156 ];
5157
5158 [Nearby;
5159     if (~~(player in limbo))
5160         print "Nearby, ";
5161     else
5162         print "Back at the lab, ";
5163 ];
5164
5165 [TheLower room;
5166     print (string) room.lower_name;
5167 ];
5168
5169
5170
5171 !============================================================================
5172
5173 ! Include "../Contrib/Scenic";
5174
5175
5176 !============================================================================
5177
5178 ! Standard and extended grammar
5179
5180
5181
5182 Include "grammar";
5183
5184
5185 !----------------------------------------------------------------------------
5186
5187 [ AboutSub;
5188   instant_action_this_turn = true;
5189   print "^All Things Devours is a short piece of interactive fiction, leaning strongly
5190           towards the text-adventure end of the spectrum. It explores an all-too-familiar
5191           science fiction paradigm in what I hope is a rather refreshing and satisfying manner.
5192           However, due to the intrinsic nature of its subject matter, it is more cruel
5193           than one might hope for a modern piece of interactive fiction. In particular,
5194           any move you make may put things into an unwinnable state. You are therefore encouraged
5195           to save frequently, and also to realise that you will probably have to start over several times
5196           to find the most satisfactory ending.^^
5197           Hints, reviews and more can be found at http://devours.amirrorclear.net^";
5198 ];
5199
5200 Verb 'about'
5201     * 'game'                        -> About
5202     * 'devours'                     -> About
5203     * 'all' 'things' 'devours'      -> About
5204     *                               -> About;
5205
5206 [ WalkthroughSub;
5207   instant_action_this_turn = true;
5208   print_ret "Hints and a walkthrough are located at http://devours.amirrorclear.net^
5209              You might also want to try the 'about' command.^^
5210              If you are unfamiliar with text adventures, then you may want to
5211              learn the basics first at an introductory website such as
5212              http://brasslantern.org/beginners/"; ];
5213
5214 Verb 'walkthrough' 'walkthru' 'hint' 'hints' 'help'
5215     *                               -> Walkthrough;
5216
5217 [ CreditsSub;
5218   instant_action_this_turn = true;
5219   print_ret "Written by half sick of shadows for IFComp 2004.^
5220              Beta tested by Stephen Bond.^
5221              Special thanks go to those who submitted detailed bug reports and suggestions
5222              during the competition, notably: Peter Eckersley, Oliver Nash,
5223              Hugo Thorvaldsen and Evin Robertson.^
5224              ^
5225              No rights are reserved by the author:
5226              this work is in the public domain and may be freely copied and modified.";
5227 ];
5228
5229 Verb 'credits'
5230     *                               -> Credits;
5231
5232 [ InterleavingOnSub;
5233   instant_action_this_turn = true;
5234   poem_interleaving = true;
5235   "The ending will now be in the original, interleaved, style.";
5236 ];
5237
5238 [ InterleavingOffSub;
5239   instant_action_this_turn = true;
5240   poem_interleaving = false;
5241   "The ending will now be in the standard style.";
5242 ];
5243
5244 Verb 'interleaving'
5245     * 'on'                              -> InterleavingOn
5246     * 'off'                             -> InterleavingOff;
5247
5248 [ ResetSub; print_ret "It is not clear what you are trying to do."; ];
5249
5250 Verb 'reset' 'stop' 'halt' 'defuse'
5251     * noun                          -> Reset;
5252
5253 Verb 'swipe'
5254     * noun 'in' noun                -> Insert
5255     * noun 'through' noun           -> Insert;
5256
5257 [ CompleteModificationsSub; 
5258     if ((real_location == deutsch_lab) || (real_location == prototype_interior))
5259         <<Tie prototype>>;
5260     else
5261         "You would need to be near the prototype to do that.";
5262 ];
5263
5264 Verb 'complete' 'finish'
5265     * 'modifications'                     -> CompleteModifications
5266     * 'work'                              -> CompleteModifications
5267     * 'changes'                           -> CompleteModifications
5268     * 'alteration'                        -> CompleteModifications;
5269
5270 [ ModifySub; 
5271     if ((noun == prototype) || (noun == control_panel) || (noun == nothing)) {
5272         if ((real_location == deutsch_lab) || (real_location == prototype_interior)) 
5273             <<Tie prototype>>;
5274         else
5275             "You would need to be near the prototype to do that.";
5276     }
5277     "It is not clear what you are trying to do.";
5278 ];
5279
5280 Verb 'modify' 'change' 'alter'
5281     *                          -> Modify
5282     * noun                     -> Modify;
5283
5284 [ SwitchSub; 
5285     if (noun has on)
5286         <<SwitchOff noun>>;
5287     else
5288         <<SwitchOn noun>>;
5289 ];
5290
5291 Verb 'flick' 'flip'
5292     * noun                     -> Switch;
5293     
5294 Extend 'switch' first
5295     * noun                     -> Switch;
5296
5297 [ SwingAtSub; if (second == nothing)
5298                   print_ret "You swing ", (the) noun, " through the air, harmlessly.";
5299               else if (IsOfType(noun, crowbar))
5300                   <<Attack second>>;
5301               else if ((second == conference_window) || (second ofclass AutomaticDoor)) {
5302                   print_ret (The) noun, " bounces harmlessly off the ",
5303                             (the) second, ".";
5304               }
5305               else
5306                   <<Attack noun>>;
5307 ];
5308
5309 Extend 'swing' first
5310     * held                          -> SwingAt
5311     * held 'at' noun                -> SwingAt
5312     * held 'into' noun              -> SwingAt
5313     * held 'through' noun           -> SwingAt;
5314     
5315
5316 [ AttackWithSub; if (IsOfType(second, crowbar))
5317                      <<Attack noun>>;
5318                  else if ((noun == conference_window) || (noun ofclass AutomaticDoor)) {
5319                      if (second == nothing)
5320                          print_ret "You are not strong enough to break ",
5321                                    (the) noun, " by yourself.";
5322                      else
5323                          print_ret (The) second, " is not heavy enough to break ",
5324                                    (the) noun, ".";
5325                  }
5326                  else
5327                      <<Attack noun>>;
5328 ];
5329
5330 Extend 'attack'
5331     * noun 'with' 'fist'            -> AttackWith
5332     * noun 'with' 'foot'            -> AttackWith
5333     * noun 'with' 'hand'            -> AttackWith
5334     * noun 'with' held              -> AttackWith;
5335
5336 [ JumpDownSub; if (real_location == balcony)
5337                    Jumped();
5338                else if ((real_location == upstairs_landing) || (real_location == foyer)) {
5339                    print "You hit the ground hard. Maybe you should have used the stairs.^";
5340                    <<Go d_obj>>;
5341                }
5342                else
5343                    "There is nothing to jump down to.";
5344 ];
5345
5346 Extend 'jump' first
5347     * 'down'                        -> JumpDown;
5348
5349 [ ClimbDownSub; if (real_location == balcony)
5350                    Jumped();
5351                else if ((real_location == upstairs_landing) || (real_location == foyer))
5352                    <<Go d_obj>>;
5353                else
5354                    "There is nothing to climb down to.";
5355 ];
5356
5357 Extend 'climb' first
5358     * 'down'                        -> ClimbDown;
5359
5360 [ LockSimpleSub k;
5361 if (noun has lockable) {
5362      if (noun.with_key_type == nothing)
5363          "You do not have the key.";         
5364      k = GetHeld(noun.with_key_type);
5365      if (k == nothing)
5366          "You do not have the key.";
5367      <<Lock noun k>>;
5368  }
5369  else 
5370      "That doesn't seem to be something you can lock.";
5371
5372 ];
5373
5374 Extend 'lock' first
5375     * noun                        -> LockSimple;
5376
5377
5378 [ UnlockSimpleSub k;
5379 if (noun has lockable) {
5380      if (noun.with_key_type == nothing)
5381          "You do not have the key.";         
5382      k = GetHeld(noun.with_key_type);
5383      if (k == nothing)
5384          "You do not have the key.";
5385      <<Unlock noun k>>;
5386  }
5387  else 
5388      "That doesn't seem to be something you can unlock.";
5389
5390 ];
5391
5392 Extend 'unlock' first
5393     * noun                        -> UnlockSimple;
5394
5395 [ UseSub;
5396   "You will have to be more specific about your action.";
5397 ];
5398
5399 Verb 'use' 
5400     *                             -> Use
5401     * noun                        -> Use;
5402
5403 [ PlantSub p;
5404   p = parent(noun);
5405   <Drop noun>;
5406   if (parent(noun) ~= p)
5407       if (noun ofclass Bomb_)
5408           if (noun.time_value == NA_)
5409               "(you may also want to set the timer)";
5410 ];
5411
5412 [ PlantInSub p;
5413   p = parent(noun);
5414   <Insert noun second>;
5415   if (parent(noun) ~= p)
5416       if (noun ofclass Bomb_)
5417           if (noun.time_value == NA_)
5418               "(you may also want to set the timer)";
5419 ];
5420
5421 [ PlantOnSub p;
5422   p = parent(noun);
5423   <PutOn noun second>;
5424   if (parent(noun) ~= p)
5425       if (noun ofclass Bomb_)
5426           if (noun.time_value == NA_)
5427               "(you may also want to set the timer)";
5428 ];
5429
5430 Verb 'plant' 
5431     * noun                        -> Plant
5432     * noun 'in' noun              -> PlantIn
5433     * noun 'on' noun              -> PlantOn;
5434
5435 Extend 'look'
5436     * noun                        -> Examine;
5437
5438 [ WaitSecondsSub t;
5439   if (noun == 0) {
5440       instant_action_this_turn = true;
5441       "That didn't take long.";  
5442   }
5443   if (noun < 0) {
5444       instant_action_this_turn = true;
5445       "If you could do that, you wouldn't have built the prototype.";
5446   }
5447   print "Time passes.^";
5448   if (noun%5 ~= 0) {
5449       if (noun/5 > 0)
5450           IncTime();
5451   }
5452   for (t=1 : t<noun/5 : t++)
5453       IncTime();
5454   if (~~deadflag)
5455       if (noun%5 ~= 0)
5456             print "Indeed you pause for slightly longer than you had planned,
5457                  carefully resynchronizing yourself with the 
5458                  five second turn increments.^";
5459 ];
5460
5461 [ WaitTurnsSub t;
5462   if (noun == 0) {
5463       instant_action_this_turn = true;
5464       "That didn't take long.";  
5465   }
5466   print "Time passes.^";
5467   if (noun < 0) {
5468       instant_action_this_turn = true;
5469       "If you could do that, you wouldn't have built the prototype.";
5470   }
5471   for (t=1 : t<noun : t++)
5472       IncTime();
5473 ];
5474
5475 [ WaitUntilSub time_in_turns t;
5476    time_in_turns = noun / 5 - my_time;
5477    if (time_in_turns > FINAL_TIME - my_time)
5478        time_in_turns = FINAL_TIME - my_time + 2;
5479  
5480   if (time_in_turns == 0 && (noun%5 ==0)) {
5481       instant_action_this_turn = true;
5482       "That didn't take long.";   
5483   }
5484   if (time_in_turns < 0) {
5485       instant_action_this_turn = true;
5486       "If you could do that, you wouldn't have built the prototype.";
5487   }
5488   print "Time passes.^";
5489   if (noun%5 ~= 0) {
5490       if (time_in_turns > 0)
5491           IncTime();
5492   }
5493   for (t=1 : t<time_in_turns : t++)
5494       IncTime();
5495
5496   if (~~deadflag)
5497       if (noun%5 ~= 0)
5498             print "Indeed you pause for slightly longer than you had planned,
5499                  carefully resynchronizing yourself with the 
5500                  five second turn increments.^";
5501 ];
5502
5503 [ HoursMinsSecsWordToTime hour minute second word;
5504   if (hour >= 24) return -1;
5505   if (minute >= 60) return -1;
5506   if (second >= 60) return -1;
5507   if (hour > 4) return 18000;      ! this is to avoid integer overflow
5508   if (word == 'pm') 
5509       return 18000;
5510
5511   return (hour*60 + minute) * 60 + second;
5512 ]; 
5513     
5514 ! based on the code from the DM4.
5515 ! looks for a time in the format 2:39 or 4:17:18
5516     
5517 [ TimeOfDay first_word second_word at length colons illegal_char digits hr mn se i;
5518    first_word = NextWordStopped();
5519    if (first_word == -1) 
5520        return GPR_FAIL;
5521    at = WordAddress(wn-1);
5522    length = WordLength(wn-1);
5523    for (i=0: i<length: i++) {
5524        switch (at->i) {
5525            ':': if (colons == 0 && digits>0 && i<length-1) {
5526                     colons = 1;
5527                     digits = 0;
5528                 }
5529                 else if (colons == 1 && digits==2 && i<length-1) {
5530                     colons = 2;
5531                     digits = 0;
5532                 }
5533                 else
5534                     illegal_char = true;
5535            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': 
5536                 digits = digits+1;
5537                 if (digits > 2)
5538                     illegal_char = true;
5539            default: illegal_char = true;
5540        } 
5541    }
5542    if (length < 3 || length > 8 || illegal_char || colons == 0)
5543         return GPR_FAIL;
5544    for (i=0: at->i~=':': i++, hr=hr*10)
5545        hr = hr + at->i - '0';
5546    hr = hr/10;
5547    mn = ((at->(i+1) - '0') * 10) + at->(i+2) - '0';
5548    if (colons == 2) {
5549        i = i+3;
5550        se = ((at->(i+1) - '0') * 10) + at->(i+2) - '0';
5551    }
5552    second_word = NextWordStopped();
5553    parsed_number = HoursMinsSecsWordToTime(hr, mn, se, second_word);
5554    if (parsed_number == -1) return GPR_FAIL; if (second_word ~= 'pm' or 'am') wn--;
5555    return GPR_NUMBER;
5556 ];
5557  
5558 Extend 'wait'
5559     * number                      -> WaitSeconds
5560     * number 'seconds'            -> WaitSeconds
5561     * number 'second'             -> WaitSeconds
5562     * number 'turns'              -> WaitTurns
5563     * number 'turn'               -> WaitTurns
5564     * 'until' TimeOfDay           -> WaitUntil;
5565     
5566     
5567 [ ShoutSub t;
5568     print "You shout loudly.^";
5569     for (t=0 : t<time_travelled : t++) {
5570         if ((former_self-->t notin limbo) && 
5571             ((siren_start_time == UNKNOWN_) || (siren_start_time > my_time))) {
5572             
5573             d_paradox = true;
5574             deadflag = 3;
5575             Seperator();
5576             print (Nearby) 0, "your former self hears the muffled sounds of your
5577                    shouting.^^Something of an anticlimactic way to kill 
5578                    so many millions of people...^"; 
5579             print "^Time unravels...^";
5580             Devours(my_time);                            
5581             return true;
5582         }
5583     }
5584     Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,SHOUT_);
5585                 MaybeSing();
5586     return true;
5587 ];
5588
5589 Extend only 'shout' replace
5590     *                             -> Shout
5591     * topic                       -> Shout;
5592     
5593 Verb 'yell'
5594     *                             -> Shout
5595     * topic                       -> Shout;
5596
5597 Verb 'tear'
5598     * noun                        -> Attack
5599     * 'up' noun                   -> Attack;
5600
5601 Extend 'remove' first                                   ! so that 'remove battery' works
5602     * multiinside                 -> Remove;
5603
5604 [ HoldDownWithSub;
5605     if (noun == alarm_button || noun == basement_button || noun == first_button ||
5606         noun == second_button || noun == silver_button || noun == exit_button ) {
5607         "The button is set into a vertical surface, 
5608          making it impossible to hold it down with another object.";
5609     }        
5610     else
5611         "It is not clear what that is supposed to accomplish.";
5612 ];
5613
5614 Extend 'hold' first                                   ! so that 'remove battery' works
5615     * 'down' noun                 -> Push
5616     * 'down' noun 'with' noun     -> HoldDownWith
5617     * 'down' noun 'using' noun    -> HoldDownWith;
5618   
5619 [ ChallengeSub;
5620     instant_action_this_turn = true;
5621     if (challenge)
5622         "The challenge has already been initiated.";
5623     if (first_turn) {
5624         challenge = true;
5625         siren_timeout = CHALLENGE_SIREN_TIMEOUT;
5626         early_guard_time = CHALLENGE_EARLY_GUARD_TIME;
5627         "The game is now in its most challenging form.
5628          Three key elements have been changed to make success considerably
5629          more difficult. This challenge is not
5630          required for a successful completion of the game. It is just here
5631          for those who, upon finishing, wish there was a little bit more.^
5632          ^
5633          If you do want to take up the challenge, then remember to initiate this
5634          mode each time you begin play.";
5635     }
5636     else
5637         "The challenge can only be initiated in the first turn.";
5638 ];
5639
5640 [ EndChallengeSub;
5641     instant_action_this_turn = true;
5642     challenge = false;
5643     siren_timeout = DEFAULT_SIREN_TIMEOUT;
5644     early_guard_time = EARLIEST_TIME;
5645     "The game is now at its standard difficulty.";
5646 ];
5647
5648 Verb 'challenge'
5649     *                             -> Challenge
5650     * 'on'                        -> Challenge
5651     * 'mode' 'on'                 -> Challenge
5652     * 'off'                       -> EndChallenge
5653     * 'mode' 'off'                -> EndChallenge;
5654
5655 Verb 'start' 'begin' 'initiate'
5656     * 'challenge'                 -> Challenge
5657     * 'challenge' 'mode'          -> Challenge;
5658
5659 Verb 'end'
5660     * 'challenge'                 -> EndChallenge
5661     * 'challenge' 'mode'          -> EndChallenge;
5662     
5663 !============================================================================
5664