--- /dev/null
+!% +code_path=../../Games/devours
+!% $MAX_STATIC_DATA=150000
+
+
+!============================================================================
+
+! This program was written by Toby Ord (half sick of shadows) and has been
+! released into the public domain, so you are legally free to be distribute
+! and modify it as you see fit. So long as you do so in good faith and with good
+! taste (or sufficient taste) then you have my blessing.
+!
+! Oh, and apologies for the messy code! It was my first program in Inform.
+
+Constant Story "All Things Devours";
+
+Constant Headline
+ "^Written for IFComp 2004 by half sick of shadows.^
+ This is the post-competition release.^
+ It is in the public domain and may thus be freely copied or modified.^
+ First-time players should type 'about'.^";
+
+
+Release 3; ! post-competition release, (plus 1 bugfix)
+
+Replace DrawStatusLine;
+Replace ScoreSub;
+
+
+!============================================================================
+! Constants and Globals
+!
+
+Constant DEATH_MENTION_UNDO;
+
+! EARLIEST_TIME is a time before which no action can happen
+! (can't time travel to before this time)
+! start_time is when the player arrives.
+! From ten seconds earlier,
+! the player is outside (and can interfere with escape attempts at this time)
+! <<< thus the EARLIEST_TIME must be at least ten seconds before start_time >>>
+! FINAL_TIME is when the security team arrive and any attempt to stay beyond this
+! will get you caught.
+
+! the time units are 5 second blocks
+
+Global my_time; ! used instead of the_time to allow sub-minute turns
+
+! the timeline has the player in a non-specified 'limbo' from EARLIEST_TIME to
+
+Constant EARLIEST_TIME = ((4 * 60) + 13) * 12 + 11;
+Constant FINAL_TIME = ((4 * 60) + 23) * 12 + 0;
+
+Global start_time = ((4 * 60) + 17) * 12 + 0;
+Global early_guard_time = EARLIEST_TIME; ! but this changes in the challenge mode
+
+Constant CHALLENGE_EARLY_GUARD_TIME = ((4 * 60) + 15) * 12 + 11;
+
+
+! the times of the two military experiments, if allowed to happen
+
+Constant EXPERIMENT1_TIME = (( 9 * 60) + 27) * 12 + 3;
+Constant EXPERIMENT2_TIME = ((11 * 60) + 33) * 12 + 9;
+
+Constant GAME_LENGTH = FINAL_TIME - EARLIEST_TIME;
+
+Constant LATER_ = -1; ! A constant to represent a later time
+
+Constant DEFAULT_SIREN_TIMEOUT = 16; ! the time before the guard arrives
+Constant CHALLENGE_SIREN_TIMEOUT = 11; ! 1:20 vs. 0:55
+
+Constant TIME_BEFORE_DRAGGED_OFF = 4; ! the time between arrest and removal
+
+Constant MAX_TIME_TRAVELS = 2;
+
+! ***************** Important ********************
+! This MUST be set to be equal to 2 to the power of MAX_TIME_TRAVELS
+
+Constant MAX_ITEM_COPIES = 4;
+
+! Constants for death states
+
+Constant ACCELERATED_ = 4; ! brought about the premature destruction of Boston
+Constant USELESS_ = 5; ! achieved nothing of consequence
+Constant DELAYED_ = 6; ! delayed the destruction by blowing up prototype
+Constant SAVED_DEAD_ = 7; ! saved the city but died
+Constant SAVED_CAUGHT_ = 8; ! saved the city but caught
+Constant SAVED_FREE_ = 9; ! saved the city and free
+Constant SAVED_FREE_CHALLENGE_ = 10; ! saved the city and free and completed the challenge
+! Constants for object states
+
+Constant NA_ = -2;
+Constant UNKNOWN_ = -1;
+Constant LOCKED_ = 0;
+Constant CLOSED_ = 1;
+Constant OPEN_ = 2;
+
+! Potentially dangerous actions:
+
+Constant NONE_ = 0;
+Constant LOCK_ = 1;
+!Constant OPEN_ = 2; Not needed since defined above
+Constant UNLOCK_ = 3;
+Constant X_CCTV_ = 4;
+Constant X_UPSTAIRS_CORRIDOR_ = 5;
+Constant X_UPSTAIRS_LANDING_ = 6;
+Constant X_GROUND_CORRIDOR_ = 7;
+Constant X_FOYER_ = 8;
+Constant X_BASEMENT_CORRIDOR_ = 9;
+Constant X_BASEMENT_LANDING_ = 10;
+Constant X_BALCONY_ = 11;
+Constant TAKE_FLASHLIGHT_ = 12;
+Constant BLOW_BASEMENT_LIGHT_ = 13;
+Constant SING_ = 14; ! these are not dangerous in the same way
+Constant SHOUT_ = 15; ! but need to be caught and replayed
+
+Global time_travelled;
+Global last_travel_time;
+
+Global d_paradox;
+Global d_caught;
+Global d_detained;
+Global d_escaped;
+Global d_exploded;
+Global d_killed_by_bomb;
+Global d_injured_by_bomb;
+Global d_fs_hears_bomb;
+Global d_fs_killed_by_bomb;
+Global d_destroyed_notes;
+Global d_destroyed_prototype;
+
+ !! The moveable items (which can be taken back in time):
+
+Array bomb --> MAX_ITEM_COPIES;
+Array id_card --> MAX_ITEM_COPIES;
+Array equipment_key --> MAX_ITEM_COPIES;
+Array deutsch_key --> MAX_ITEM_COPIES;
+Array flashlight --> MAX_ITEM_COPIES;
+Array battery --> MAX_ITEM_COPIES;
+Array cable --> MAX_ITEM_COPIES;
+Array crowbar --> MAX_ITEM_COPIES;
+Array notes --> MAX_ITEM_COPIES;
+
+Array former_self --> MAX_TIME_TRAVELS;
+
+
+ !! The locations of various things at various times
+ !! These contain an immense amount of info:
+ !! Location of each copy of that item at each time for each run through
+ !! Amongst other things, this allows one to recreate the world at a given time
+
+Array player_loc --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
+
+Array bomb_loc --> (GAME_LENGTH + 1) *
+ (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1);
+Array id_card_loc --> (GAME_LENGTH + 1) *
+ (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1);
+Array equipment_key_loc --> (GAME_LENGTH + 1) *
+ (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1);
+Array deutsch_key_loc --> (GAME_LENGTH + 1) *
+ (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1);
+Array flashlight_loc --> (GAME_LENGTH + 1) *
+ (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1);
+Array battery_loc --> (GAME_LENGTH + 1) *
+ (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1);
+Array cable_loc --> (GAME_LENGTH + 1) *
+ (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1);
+Array crowbar_loc --> (GAME_LENGTH + 1) *
+ (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1);
+Array notes_loc --> (GAME_LENGTH + 1) *
+ (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1);
+
+ !! The states of various things at various times
+
+Global prototype_fixed_time = UNKNOWN_;
+Global siren_start_time = UNKNOWN_;
+
+Array flashlight_state --> (GAME_LENGTH + 1) *
+ (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1);
+Array bomb_setting --> (GAME_LENGTH + 1) *
+ (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1);
+
+!! activity_target is used to distinguish which door was (dangerously) locked/unlocked/opened
+
+Array dangerous_activity --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
+Array activity_target --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
+
+Array siren_state --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
+Array panel_setting --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
+Array ground_equipment_light --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
+Array basement_equipment_light --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
+
+Array main_doors_state --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
+Array basement_door_state --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
+Array ground_door_state --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
+Array upstairs_door_state --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
+Array balcony_door_state --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
+Array conference_window_state --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
+Array deutsch_door_state --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
+Array basement_equipment_door_state --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
+Array ground_equipment_door_state --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
+
+Array main_doors_smashed --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
+Array basement_door_smashed --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
+Array ground_door_smashed --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
+Array upstairs_door_smashed --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
+Array balcony_door_smashed --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1);
+
+
+Global poem_interleaving = false;
+Global initialising = true;
+Global first_turn = true;
+Global challenge = false;
+Global siren_timeout = DEFAULT_SIREN_TIMEOUT;
+Global instant_action_this_turn = false;
+Global warned_of_jump = false;
+Global id_card_used = false;
+Global have_looked_at_bench = false;
+Global prototype_seen = false;
+
+!============================================================================
+
+
+
+Include "Parser";
+
+Object LibraryMessages
+with before [;
+ Jump:
+ if (real_location == balcony) {
+ Jumped();
+ return true;
+ }
+ "You jump on the spot, fruitlessly.";
+ Listen:
+ if ((siren_start_time ~= UNKNOWN_) && (siren_start_time < my_time))
+ return true;
+ else if (Get2D(dangerous_activity, time_travelled-1, my_time-EARLIEST_TIME) == SHOUT_)
+ return true;
+ else if (Get2D(dangerous_activity, time_travelled-1, my_time-EARLIEST_TIME) == SING_)
+ return true;
+ else
+ "You can hear nothing but a soft electric hum.";
+ Burn:
+ "You have no source of flame.";
+ Sing:
+ "You sing out a few clear notes.";
+ Miscellany:
+ if (lm_n == 44)
+ "It is not clear what you are trying to refer to with 'all'.";
+];
+
+Include "VerbLib";
+
+
+!============================================================================
+
+
+! Object classes
+
+Class Room
+ with before [t;
+ Inv, Look:
+ if (initialising) {
+ initialising = false;
+ return false;
+ }
+ instant_action_this_turn = true;
+ return false;
+ Sing:
+ for (t=0 : t<time_travelled : t++) {
+ if ((former_self-->t notin limbo) &&
+ ((siren_start_time == UNKNOWN_) || (siren_start_time > my_time))) {
+
+ print "You sing out a few clear notes.^";
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print (Nearby) 0, "your former self hears the muffled sounds of your
+ singing.^^Something of an anticlimactic way to kill
+ so many millions of people...^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ return true;
+ }
+ }
+ Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,SING_);
+ return false;
+ ],
+ each_turn [t i;
+ first_turn = false;
+ if (instant_action_this_turn) {
+ instant_action_this_turn = false;
+ return true;
+ }
+ MoveFloatingObjects();
+ my_time++;
+ if (time_travelled > 0) {
+ for(i=0 : i < Exp(2,time_travelled-1) : i++) {
+ MoveObject(bomb, bomb_loc, i);
+ MoveObject(id_card, id_card_loc, i);
+ MoveObject(equipment_key, equipment_key_loc, i);
+ MoveObject(deutsch_key, deutsch_key_loc, i);
+ MoveObject(flashlight, flashlight_loc, i);
+ MoveObject(battery, battery_loc, i);
+ MoveObject(cable, cable_loc, i);
+ MoveObject(crowbar, crowbar_loc, i);
+ MoveObject(notes, notes_loc, i);
+ }
+
+ if (my_time == prototype_fixed_time)
+ prototype.fixed = true;
+
+ MaybeSetBombs();
+ MaybeSetFlashlights();
+ MaybeSetPanel(panel_setting);
+ MaybeSetBasementLight(basement_equipment_light);
+ MaybeSetGroundLight(ground_equipment_light);
+ MaybeSetAutomaticDoor(main_doors, main_doors_state);
+ MaybeSetAutomaticDoor(basement_door, basement_door_state);
+ MaybeSetAutomaticDoor(ground_door, ground_door_state);
+ MaybeSetAutomaticDoor(upstairs_door, upstairs_door_state);
+
+ MaybeBreakDoor(main_doors, main_doors_smashed);
+ MaybeBreakDoor(basement_door, basement_door_smashed);
+ MaybeBreakDoor(ground_door, ground_door_smashed);
+ MaybeBreakDoor(upstairs_door, upstairs_door_smashed);
+ MaybeBreakDoor(balcony_door, balcony_door_smashed);
+
+ MaybeSing();
+ MaybeShout();
+
+!-- from here down paradox may occur and we need to be able to stop if one occurs if (~~d_paradox)...
+
+ for(t=0 : t < time_travelled : t++)
+ MoveFormerSelf(t);
+
+ MaybeSetManualDoor(balcony_door, balcony_door_state);
+ MaybeSetManualDoor(conference_window, conference_window_state);
+ MaybeSetManualDoor(deutsch_door, deutsch_door_state);
+ MaybeSetManualDoor(basement_equipment_door, basement_equipment_door_state);
+ MaybeSetManualDoor(ground_equipment_door, ground_equipment_door_state);
+
+ }
+
+ MaybeCloseAutomaticDoor(main_doors);
+ MaybeCloseAutomaticDoor(basement_door);
+ MaybeCloseAutomaticDoor(ground_door);
+ MaybeCloseAutomaticDoor(upstairs_door);
+
+ ObserveLocations();
+ ObserveBombs();
+ ObserveFlashlights();
+ ObserveSiren();
+ ObservePanel();
+ ObserveBasementLight(basement_equipment_light);
+ ObserveGroundLight(ground_equipment_light);
+ ObserveAutomaticDoor(main_doors, main_doors_state);
+ ObserveAutomaticDoor(basement_door, basement_door_state);
+ ObserveAutomaticDoor(ground_door, ground_door_state);
+ ObserveAutomaticDoor(upstairs_door, upstairs_door_state);
+ ObserveManualDoor(balcony_door, balcony_door_state);
+ ObserveManualDoor(conference_window, conference_window_state);
+ ObserveManualDoor(deutsch_door, deutsch_door_state);
+ ObserveManualDoor(basement_equipment_door, basement_equipment_door_state);
+ ObserveManualDoor(ground_equipment_door, ground_equipment_door_state);
+
+ ObserveBrokenDoor(main_doors, main_doors_smashed);
+ ObserveBrokenDoor(basement_door, basement_door_smashed);
+ ObserveBrokenDoor(ground_door, ground_door_smashed);
+ ObserveBrokenDoor(upstairs_door, upstairs_door_smashed);
+ ObserveBrokenDoor(balcony_door, balcony_door_smashed);
+
+ CheckPassiveParadox();
+ CheckActiveParadox();
+
+ if (~~(Stopped())) {
+ if (siren_start_time ~= UNKNOWN_) {
+ if (my_time - siren_start_time == 1)
+ print "^A piercing siren rings out.^";
+ if (my_time - siren_start_time > 1) {
+ if (my_time - siren_start_time <= siren_timeout)
+ print "^The siren wails.^";
+ else
+ CaughtInside();
+ }
+ }
+ if ((my_time > FINAL_TIME) && (~~Stopped()))
+ CaughtInside();
+ }
+
+ if (main_doors.just_closed) main_doors.closing_message();
+ if (basement_door.just_closed) basement_door.closing_message();
+ if (ground_door.just_closed) ground_door.closing_message();
+ if (upstairs_door.just_closed) upstairs_door.closing_message();
+
+ MaybeExplodeBombs();
+
+ ],
+
+ has light;
+
+Class Sight
+ with before [;
+ Examine: return false;
+ Listen: return false;
+ default:
+ print_ret "You cannot do that from here.";
+ ],
+ has scenery concealed static;
+
+Class PluralSight
+ with before [;
+ Examine: return false;
+ default:
+ print_ret "You cannot do that to all of ", (the) self, " at once.";
+ ],
+ has scenery concealed static;
+
+Class Prop
+ with before [;
+ Examine: return false;
+ default:
+ print_ret "You don't need to worry about ", (the) self, ".";
+ ],
+ has scenery concealed static;
+
+
+Class Furniture
+ with before [;
+ Take,Pull,Push,PushDir:
+ print_ret (The) self, " is too heavy for that.";
+ ],
+ has static supporter;
+
+
+Class AutomaticDoor
+ with before [;
+ Take,Pull,Push,PushDir:
+ print_ret (The) self, " is locked in place.";
+ Lock:
+ Close:
+ "Like most automatic doors, this one closes of its own accord.";
+ Attack:
+ if (AmHolding(crowbar)) {
+ print "You swing the crowbar firmly into the door. It shudders,
+ a star of cracks reaching out from the point of impact,
+ but the glass stays in place.^";
+ self.smashed = true;
+ StartSiren();
+ return true;
+ }
+ else
+ "You don't have anything heavy enough to smash the door with.";
+ Search:
+ <<Examine self>>;
+ ],
+ just_closed false,
+ smashed false,
+ to_close_at UNKNOWN_,
+ open_self [t;
+ if (self hasnt open) {
+ give self open ~locked;
+ if (self in LocationOf(player))
+ print "The door slides open with a soft rattle.^";
+ }
+ self.to_close_at = t;
+ ],
+ close_self [;
+ give self ~open locked;
+ self.to_close_at = UNKNOWN_;
+ self.just_closed = true;
+ ],
+ closing_message [;
+ if ((~~Stopped()) && (self in LocationOf(player)))
+ "The automatic door softly slides closed.";
+ ],
+ has static door openable locked;
+
+Class ManualDoor
+ with name 'door' 'to' 'the',
+ before [;
+ Take,PushDir:
+ print_ret (The) self, " is locked in place.";
+ Attack:
+ if (AmHolding(crowbar)) {
+ print "You swing the crowbar firmly into the door,
+ but it barely leaves a mark.^";
+ return true;
+ }
+ else
+ "You don't have anything heavy enough to break the door with.";
+ ],
+ react_before [;
+ Go: if (noun.door_dir() == self.door_dir())
+ return self.open_by_myself();
+ if (noun.door_dir() == out_to) !! XX hack, going 'out' always uses door in this game
+ return self.open_by_myself();
+ Enter:
+ if (noun == self) return self.open_by_myself();
+ ],
+ open_by_myself [ ks;
+ if (self has open)
+ rfalse;
+ print "(first opening ", (the) self, ")^";
+ ks = keep_silent;
+ keep_silent = true;
+ <Open self>;
+ keep_silent = ks;
+ if (self hasnt open)
+ rtrue;
+ else {
+ IncTime();
+ if (Stopped()) return true;
+ }
+ ],
+ has static door openable lockable;
+
+
+[LockUnlockParadox;
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print "On the other side of the door, your former self hears you turn the
+ key in the lock.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+];
+
+[OpenParadox;
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print "On the other side, your former self sees the door open in front
+ of her.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+];
+
+[CloseParadox;
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print "On the other side, your former self sees the door close in front
+ of her.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+];
+
+[OpenManualDoor door ks;
+ if (door has locked) {
+ if (door.with_key_type == nothing
+ || ~~AmHolding(door.with_key_type))
+ "Try as you might, none of your keys will unlock the door.";
+ print "(first unlocking ", (the) door, ")^";
+ ks = keep_silent;
+ keep_silent = true;
+ <Unlock door (GetHeld(door.with_key_type))>;
+ keep_silent = ks;
+ if (door has locked)
+ return true;
+ else {
+ IncTime();
+ if (Stopped()) return true;
+ }
+ }
+ Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,OPEN_);
+ Put2D(activity_target,time_travelled,my_time-EARLIEST_TIME,door);
+ return false;
+];
+
+[UnlockManualDoor door key;
+ Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,UNLOCK_);
+ Put2D(activity_target,time_travelled,my_time-EARLIEST_TIME,door);
+ if (door has locked) {
+ if ( IsOfType(key,door.with_key_type) ) {
+ give door ~locked;
+ if (~~keep_silent)
+ print (The) key, " turns smoothly in the lock.^";
+ return true;
+ }
+ else
+ "It does not fit in the lock.";
+ }
+ return false;
+];
+
+[LockManualDoor door key ks;
+ if (door has open) {
+ print "(first closing ", (the) door, ")^";
+ ks = keep_silent;
+ keep_silent = true;
+ <Close door>;
+ keep_silent = ks;
+ if (door has open)
+ rtrue;
+ IncTime();
+ if (Stopped()) return true;
+ }
+ Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,LOCK_);
+ Put2D(activity_target,time_travelled,my_time-EARLIEST_TIME,door);
+ if (door hasnt locked) {
+ if ( IsOfType(key,door.with_key_type) ) {
+ give door locked;
+ if (~~keep_silent)
+ print (The) key, " turns smoothly in the lock.^";
+ return true;
+ }
+ else
+ "It does not fit in the lock.";
+ }
+ return false;
+];
+
+
+Class FakeDoor
+ with name 'door' 'to' 'the',
+ before [;
+ Take,PushDir:
+ print_ret (The) self, " is locked in place.";
+ Unlock:
+ if (IsOfType(second,crowbar))
+ <<Attack self>>;
+ Attack:
+ if (AmHolding(crowbar)) {
+ print "You swing the crowbar firmly into the door,
+ but it barely leaves a mark.^";
+ return true;
+ }
+ else
+ "You don't have anything heavy enough to break the door with.";
+ Enter:
+ "The door is locked.";
+ ],
+ door_to nothing,
+ door_dir nothing,
+ with_key_type nothing,
+ has static door openable lockable locked;
+
+
+!============================================================================
+
+! the moveable objects (defined as classes)
+! with trailing _ to avoid ambiguity with individual item names
+
+
+Class Bomb_(MAX_ITEM_COPIES)
+ with short_name "timed explosive device",
+ plural "timed explosive devices",
+ description [t i;
+ print "A length of steel pipe filled with powder and fused with a digital timer.
+ Not your most elegant piece of work, but it will
+ hopefully do the job.^";
+ t = (self.time_value - my_time) * 5 + self.left_over_seconds;
+ if (self.time_value == NA_)
+ print "^You have not yet set the timer.^";
+ else {
+ if (t == -4)
+ print "^On the timer's small LED screen, the number 0
+ blinks out at you.^";
+ else {
+ print "^On the timer's small LED screen, the numbers ";
+ for (i = t+4 : (i>t) && (i>0) : i--)
+ print i, ", ";
+ if (t < 0)
+ print 0;
+ else
+ print t;
+ print "... blink out at you insistently, illuminating
+ the room with faint blue-green flashes.^";
+ }
+ }
+ ],
+ name 'time' 'timed' 'explosive' 'device' 'bomb' 'timebomb' 'C4'
+ 'timer' 'digital' 'pipe'
+ 'devices//p' 'bombs//p' 'timebombs//p' 'timers//p',
+ time_value NA_,
+ left_over_seconds 0,
+ before [;
+ Set:
+ print "To set the explosive device,
+ you need to specify a number of seconds,
+ for example, with 'set timer to 30'.^";
+ return true;
+ SetTo:
+ if (self.time_value ~= NA_) {
+ print "(first resetting the timer)^";
+ self.time_value = NA_;
+ }
+ if (second > 0 && second <= 100) {
+ self.time_value = my_time + (second/5);
+ self.left_over_seconds = second%5;
+ print "Time until detonation: ", (self.time_value - my_time) * 5
+ + self.left_over_seconds;
+ print " seconds.^";
+ if (parent(self) == player)
+ print "(you probably don't want to be carrying the device
+ when that occurs...)^";
+ }
+ else {
+ print "Your timer only accepts between 1 and
+ 100 seconds.^";
+ }
+ return true;
+ Reset:
+ if (self.time_value ~= NA_) {
+ self.time_value = NA_;
+ "You reset the timer.";
+ }
+ else
+ "The timer is not currently set.";
+ ],
+ has ;
+
+Class IDCard_(MAX_ITEM_COPIES)
+ with short_name "ID card",
+ plural "ID cards",
+ description "Natalie Williams.^
+ Deutsch Lab.^
+ Doctoral Student, MIT^
+ ^
+ On the right is a familiar photo of you, back when you
+ wore your hair long.
+ A black magnetic stripe runs the width of the reverse.",
+ name 'id' 'card' 'cards',
+ before[; Insert:
+ if (second == id_slot){
+ if (second in foyer or upstairs_landing) {
+ "The slot emits a small beep and your card is rejected.";
+ }
+ if (second in basement_landing) {
+ if (~~id_card_used) {
+ print "You swipe your card through the slot, and hold your breath.^";
+ basement_door.open_self(my_time+1);
+ print "Perfect. Just as you'd hoped.
+ The bastards hadn't even thought to disable your card.^";
+ id_card_used = true;
+ }
+ else
+ basement_door.open_self(my_time+1);
+ return true;
+ }
+ }
+ if (second == ground_door or upstairs_door
+ && player in foyer or upstairs_landing) {
+ "The slot emits a small beep and your card is rejected.";
+ }
+ if ((second == basement_door) && (player in basement_landing)) {
+ basement_door.open_self(my_time+1);
+ return true;
+ }
+ ],
+ has ;
+
+Class Crowbar_(MAX_ITEM_COPIES)
+ with short_name "crowbar",
+ plural "crowbars",
+ name 'crow' 'bar' 'crowbar' 'black' 'crowbars//p' 'bars//p',
+ description "A curved black crowbar.",
+ has;
+
+Class Flashlight_(MAX_ITEM_COPIES)
+ with short_name "flashlight",
+ plural "flashlights",
+ name 'flashlight' 'torch' 'flashlights//p' 'torches//p'
+ 'flash' 'metallic' 'blue' 'metallic-blue',
+ description "A small metallic-blue flashlight.",
+ capacity 2,
+ before [;
+ SwitchOn:
+ if (self has on)
+ "That's already on.";
+ if (BatteriesContained(self) == 2) {
+ give self on;
+ if (real_location == basement_equipment ||
+ (real_location == ground_equipment && ground_equipment.lit == false)) {
+ <Look>;
+ instant_action_this_turn = false;
+ return true;
+ }
+ else
+ "A thin beam of icy light shines forth.";
+ }
+ if (BatteriesContained(self) == 1) {
+ "The switch clicks, but no light is forthcoming.
+ It looks as if you will need two batteries.";
+ }
+ if (BatteriesContained(self) == 0) {
+ "The switch clicks, but no light is forthcoming.
+ Not surprising considering flashlights usually need batteries.";
+ }
+ SwitchOff:
+ if (player in basement_equipment)
+ MoveMoveableChildren(basement_equipment,basement_equipment_gloom);
+ else if ((player in ground_equipment) && (ground_light_switch hasnt on))
+ MoveMoveableChildren(ground_equipment,ground_equipment_gloom);
+ Receive:
+ if (~~IsOfType(noun,battery))
+ print_ret (The) noun, " won't fit in the flashlight.";
+ Take:
+ Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,TAKE_FLASHLIGHT_);
+ return false;
+ ],
+ after [;
+ LetGo:
+ if (self has on) {
+ print "As you remove the battery, the light fails.^";
+ give self ~on;
+ if (player in basement_equipment)
+ MoveMoveableChildren(basement_equipment,basement_equipment_gloom);
+ else if ((player in ground_equipment) && (ground_light_switch hasnt on))
+ MoveMoveableChildren(ground_equipment,ground_equipment_gloom);
+ return false;
+ }
+ ],
+ has container open switchable;
+
+Class Battery_(MAX_ITEM_COPIES)
+ with short_name "battery",
+ plural "batteries",
+ name 'battery' 'batteries//p' 'AA',
+ description "An AA sized battery.",
+ before [;
+ Remove:
+ <<Take noun>>;
+ ],
+ has;
+
+Class Cable_(MAX_ITEM_COPIES)
+ with short_name "length of ribbon cable",
+ plural "lengths of ribbon cable",
+ name 'cable' 'wire' 'cables//p' 'wires//p' 'ribbon' 'length' 'lengths//p' 'of',
+ description "A 10cm length of ribbon cable. It will do nicely.",
+ before[;
+ Tie:
+ if (second == control_panel or prototype)
+ <<Tie prototype>>;
+ if (second == nothing)
+ if (real_location == deutsch_lab or prototype_interior)
+ <<Tie prototype>>;
+ else
+ "There is nothing here that you could attach the cable to.";
+ else
+ "You cannot attach the cable to that.";
+ ],
+ has;
+
+Class Notes_(MAX_ITEM_COPIES)
+ with short_name "collection of notes",
+ plural "collections of notes",
+ name 'collection' 'notes' 'collections//p',
+ description "Your research notes. The hundred or so pages here comprise
+ everything you have written so far. It would not be easy for
+ someone else to turn the scribbles herein into another working
+ prototype, but it may just be possible.",
+ before[;
+ Eat:
+ "You look determinedly at the thick bundle of papers, but there is no
+ way that you could eat more than a couple of pages. You had better think
+ of something a little more sensible.";
+ Attack, Cut:
+ "There are about a hundred pages and there is no way that you could tear them
+ up in time.";
+ ],
+ has;
+
+Class EquipmentKey_(MAX_ITEM_COPIES)
+ with short_name "worn brass key",
+ plural "worn brass keys",
+ name 'key' 'equipment' 'brass' 'worn' 'keys//p',
+ description "A well worn brass key. It opens the various
+ equipment rooms in the complex.",
+ has;
+
+Class DeutschKey_(MAX_ITEM_COPIES)
+ with short_name "bright steel key",
+ plural "bright steel keys",
+ name 'key' 'deutsch' 'steel' 'bright' 'keys//p',
+ description "A bright steel key. It unlocks the door to the Deutsch lab, downstairs.",
+ has;
+
+Class FormerSelf_(MAX_ITEM_COPIES)
+ with short_name "your former self",
+ plural "your former selves",
+ name 'self' 'former' 'past' 'selves//p',
+ description "She looks strangely familiar.",
+ has animate proper container concealed;
+
+
+!===============================================================================
+! The one-of-a-kind moveable objects
+
+Object myselfobj "(self object)"
+ with
+ short_name "yourself",
+ description "Dark hair frames a warm face. Despite the anxiety written now in your
+ tense brow, the confidence of youth and vibrancy of intellect are clear.
+ There is a depth in your clear green eyes.",
+ capacity 100,
+ number 0,
+ orders 0,
+ weakness 0,
+ has concealed animate proper transparent;
+
+
+Object skeleton_key "skeleton key (fake item to neaten code)"
+ with
+ name 'key' 'skeleton',
+ description "A skeleton key. And I thought they were make-believe!",
+ has;
+
+
+!===============================================================================
+! The rooms
+
+!-----------------------------------------------
+! Generic props and sights:
+
+Prop walls "walls"
+ with name 'wall' 'walls',
+ found_in [;
+ if (location ~= prototype_interior)
+ return true;
+ else
+ return false;
+ ],
+ has ;
+
+Prop floor "floor"
+ with name 'floor' 'ground' 'carpet',
+ description "The floor is covered by a thin carpet in a dark but warm gray.",
+ found_in [;
+ if ((location ~= balcony) && (location ~= prototype_interior))
+ return true;
+ else
+ return false;
+ ],
+ has ;
+
+Prop ceiling "ceiling"
+ with name 'ceiling',
+ found_in [;
+ if (location ~= prototype_interior)
+ return true;
+ else
+ return false;
+ ],
+ has ;
+
+Sight darkness "darkness"
+ with name 'darkness' 'dark' 'gloom',
+ description "You cannot see what lies in the darkness.",
+ before [;
+ Examine:
+ Listen:
+ return false;
+ default:
+ "It is not clear what you mean.";
+ ],
+ found_in [;
+ return true;
+ ],
+ has ;
+
+Sight shadows "shadows"
+ with name 'shadows' 'shadow' 'corners' 'cobwebs',
+ description "Shadows fill the corners of the rooms like old cobwebs.",
+ before [;
+ Examine:
+ Listen:
+ return false;
+ default:
+ "It is not clear what you mean.";
+ ],
+ found_in [;
+ return true;
+ ],
+ has ;
+
+Sight complex "complex"
+ with name 'complex' 'building' 'surface' 'surfaces' 'texture' 'textures',
+ description "The building has modern but ultimately shallow feel.
+ There is a preoccupation with surfaces and textures.
+ Almost everything is coloured with dark, yet somewhat warm, shades of gray,
+ darkened further by the midnight gloom.",
+ before [;
+ Examine:
+ Listen:
+ return false;
+ default:
+ "It is not clear what you mean.";
+ ],
+ found_in [;
+ return true;
+ ],
+ has ;
+
+Prop lights "lights"
+ with name 'lights' 'light' 'fluorescent',
+ description "Most of the overhead lights are currently off, leaving the complex in dim half-light.",
+ before [;
+ SwitchOn:
+ "Switching on the overhead lights would alert security to your presence, and besides, you
+ can see clearly enough in the gloom.";
+ ],
+ found_in [;
+ if ((location ~= balcony) && (location ~= prototype_interior) &&
+ (location ~= basement_equipment) && (location ~= ground_equipment))
+ return true;
+ else
+ return false;
+ ],
+ has ;
+
+Prop stairs "stairs"
+ with name 'stairs' 'staircase',
+ before [;
+ Climb:
+ if (self in foyer or basement_landing)
+ <<Go u_obj>>;
+ if (self in upstairs_landing)
+ "You are already at the top of the stairs.";
+ ],
+ found_in basement_landing foyer upstairs_landing,
+ has ;
+
+!-----------------------------------------------
+! Item-related props and sights:
+
+Prop beam "flashlight beam"
+ with name 'beam' 'blue-white' 'blue' 'white',
+ description "A thin icy beam that cuts through the darkness.",
+ found_in [;
+ if (Flashlit())
+ return true;
+ else
+ return false;
+ ],
+ has ;
+
+Prop photo "photograph"
+ with name 'photo' 'photograph' 'long' 'hair',
+ description "You look young, bright and proud of
+ your new position at the lab.",
+ found_in [;
+ if (AmHolding(id_card) || IsIn(id_card,real_location))
+ return true;
+ else
+ return false;
+ ],
+ has ;
+
+Prop stripe "magnetic stripe"
+ with name 'stripe' 'magnetic' 'reverse' 'back',
+ description "It is the type of magnetic stripe found on the back of a regular credit card,
+ but is used to open the automatic doors in the building.",
+ found_in [;
+ if (AmHolding(id_card) || IsIn(id_card,real_location))
+ return true;
+ else
+ return false;
+ ],
+ has ;
+
+!-----------------------------------------------
+
+Room foyer "Foyer"
+ with name 'foyer',
+ description
+ "A darkened foyer, presided over by a security desk near the north wall.
+ Floating above it in the capacious darkness is
+ a small landing. A set of stairs both rises up to meet it
+ and stretches downwards into the dark.",
+ u_to upstairs_landing,
+ d_to basement_landing,
+ n_to ground_door,
+ s_to main_doors,
+ cant_go "The only exits are the automatic doors to the north and south,
+ and the staircases up and down.",
+ lower_name "the foyer",
+ has ;
+
+Furniture security_desk "security desk" foyer
+ with description "A large black desk equipped with four CCTV screens showing
+ live feeds from around the complex. ",
+ before [;
+ Examine:
+ print "A large black desk equipped with four CCTV screens showing
+ live feeds from around the complex. ";
+ cctv_screens.display();
+ print "There are also four buttons, labeled 'basement',
+ 'first', 'second' and 'alarm'.^";
+ return true;
+ ],
+ name 'desk' 'security' 'black' 'table',
+ has scenery;
+
+Object cctv_screens "CCTV images" foyer
+ with description [;
+ print "These screens flash images from the corridors and grounds
+ of the complex. ";
+ self.display();
+ print "^";
+ ],
+ name 'images' 'CCTV' 'screen' 'screens' 'feed' 'feeds' 'image',
+ display [;
+ Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_CCTV_);
+
+ if ((my_time == start_time - 1) || (my_time == start_time - 2))
+ print "On one of the screens you see your former self approaching the
+ complex. ";
+ if (IsIn(former_self,ground_corridor))
+ print "On one of the screens you see your former self in the first
+ floor corridor. ";
+ if (IsIn(former_self,upstairs_corridor))
+ print "On one of the screens you see your former self in the second
+ floor corridor. ";
+ if (IsIn(former_self,basement_corridor))
+ print "On one of the screens you see your former self in the basement
+ corridor. ";
+ ],
+ has scenery concealed;
+
+
+Object alarm_button "alarm button" foyer
+ with description "A discrete black button carefully labeled 'alarm'.",
+ name 'alarm' '^alarm^' 'button' 'black' 'labeled' 'marked',
+ before [;
+ Push:
+ StartSiren();
+ return true;
+ Receive:
+ "The button is set into a vertical surface, making it impossible
+ to place objects on top of it.";
+ ],
+ has scenery concealed;
+
+Object first_button "'first' button" foyer
+ with description "A small black button carefully labeled 'first'.",
+ name 'first' '^first^' 'floor' 'button' 'black' 'labeled' 'marked',
+ before [; Push:
+ ground_door.open_self(my_time+1);
+ ground_door.known_exterior_opening = true;
+ return true;
+ Receive:
+ "The button is set into a vertical surface, making it impossible
+ to place objects on top of it.";
+ ],
+ has scenery concealed;
+
+Object basement_button "'basement' button" foyer
+ with description "A small black button carefully labeled 'basement'.",
+ name 'basement' '^basement^' 'floor' 'button' 'black' 'labeled' 'marked',
+ before [; Push:
+ basement_door.open_self(my_time+1);
+ "Nothing obvious happens.";
+ Receive:
+ "The button is set into a vertical surface, making it impossible
+ to place objects on top of it.";
+ ],
+ has scenery concealed;
+
+Object second_button "'second' button" foyer
+ with description "A small black button carefully labeled 'second'.",
+ name 'second' '^second^' 'floor' 'button' 'black' 'labeled' 'marked',
+ before [; Push:
+ upstairs_door.open_self(my_time+1);
+ "Nothing obvious happens.";
+ Receive:
+ "The button is set into a vertical surface, making it impossible
+ to place objects on top of it.";
+ ],
+ has scenery concealed;
+
+Sight upstairs_landing_from_foyer "upstairs landing" foyer
+ with description "The landing above is lost in shadow.",
+ name 'upstairs' 'landing',
+ has ;
+
+Sight outside_from_foyer "outside" foyer
+ with description "The grounds are empty and still on this frosty night.",
+ name 'grounds' 'outside' 'night',
+ has ;
+
+Sight ground_corridor_from_foyer "corridor" foyer
+ with description [;<<Examine ground_door>>;],
+ name 'corridor',
+ has ;
+
+!-----------------------------------------------
+
+Room basement_landing "Basement Landing"
+ with name 'landing',
+ description
+ "A cramped space at the bottom of the stairs.
+ A corridor can be seen to the north through the automatic door,
+ and the stairs lead back up to the foyer.",
+ u_to foyer,
+ n_to basement_door,
+ cant_go "The only exits are north and up.",
+ lower_name "the basement landing",
+ has ;
+
+Sight foyer_from_basement_landing "foyer" basement_landing
+ with description "You cannot see the foyer properly from here.",
+ name 'foyer' 'upstairs',
+ has ;
+
+!-----------------------------------------------
+
+Room upstairs_landing "Upstairs Landing"
+ with name 'landing',
+ description
+ "A small landing, hanging in the still darkness above the foyer.",
+ d_to foyer,
+ n_to upstairs_door,
+ cant_go "The only exits are north and down.",
+ lower_name "the upstairs landing",
+ has ;
+
+Sight foyer_from_upstairs_landing "Foyer" upstairs_landing
+ with description [;
+ Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_FOYER_);
+ if (IsIn(former_self,foyer)) {
+ "From the shadowy landing, you can just make out your former
+ self alone in the foyer.";
+ }
+ else
+ "From the shadowy landing, you can see much of the empty
+ foyer stretching out below you.";
+ ],
+ name 'foyer',
+ has ;
+
+!-----------------------------------------------
+
+Room ground_corridor "First Floor Corridor"
+ with name 'first' 'floor' 'ground' 'corridor',
+ description [;
+ print "A long north-south corridor, much the same as
+ those on the other floors. ";
+ print "Three gray doors line the eastern wall. The first two have small
+ glass windows, peering into darkened laboratories. The third ";
+ if (ground_equipment_door has open)
+ print "is open onto an equipment room.^";
+ else
+ print "is plain and leads to a small equipment room. All three are closed.^";
+ ],
+ s_to ground_door,
+ se_to saunders_door,
+ e_to pooley_door,
+ ne_to ground_equipment_door,
+ cant_go "The only exits are the three doors lining
+ the corridor (south-east, east and north-east) and the automatic door
+ back to the foyer (south).",
+ lower_name "the first floor corridor",
+ has ;
+
+FakeDoor saunders_door "door to the Saunders Lab" ground_corridor
+ with name 'door' 'grey' 'gray' 'saunders' 'first' 'lab' 'se' 'south-east',
+ description "A gray door with a small glass window,
+ looking into a darkened lab.
+ A small plaque reads: 'Saunders Lab'.",
+ has locked scenery;
+
+FakeDoor pooley_door "door to the Pooley Lab" ground_corridor
+ with name 'door' 'grey' 'gray' 'pooley' 'second' 'lab' 'e\\' 'east',
+ description "A gray door with a small glass window,
+ looking into a darkened lab.
+ A small plaque reads: 'Pooley Lab'.",
+ has locked scenery;
+
+Prop door_window "small glass window"
+ with name 'small' 'glass' 'window' 'windows',
+ description "You can't see anything of interest through the glass.",
+ before [;
+ Take,PushDir:
+ print_ret (The) self, " is fixed in the door.";
+ Unlock:
+ if (IsOfType(second,crowbar))
+ <<Attack self>>;
+ else
+ "The embedded window does not open.";
+ Open:
+ "The embedded window does not open.";
+ Attack:
+ if (AmHolding(crowbar)) {
+ print "You swing the crowbar firmly into the small window,
+ but it barely leaves a mark.^";
+ return true;
+ }
+ else
+ "You don't have anything heavy enough to break the window with.";
+ Search:
+ <<Examine self>>;
+ ],
+ found_in ground_corridor basement_corridor,
+ has scenery concealed lockable;
+
+PluralSight doors_in_ground_corridor "doors" ground_corridor
+ with name 'doors',
+ description [;
+ print "There are three doors on the eastern wall of the corridor,
+ the first two (to the south-east and east) lead to the Saunders
+ and Pooley labs. The third (to the north-east) ";
+ if (ground_equipment_door has open)
+ print "is open and ";
+ print "leads to a small equipment room. To the south, the plate glass
+ automatic door to the foyer ";
+ if (ground_door has open)
+ print "lies open.^";
+ else
+ print "stands closed.^";
+ ],
+ has pluralname;
+
+!-----------------------------------------------
+
+Room basement_corridor "Basement Corridor"
+ with name 'basement' 'corridor',
+ description [;
+ print "A long north-south corridor, much the same as
+ those on the other floors. ";
+ print "Three gray doors line the eastern wall. The first two have small
+ glass windows, peering into darkened laboratories. The third ";
+ if (basement_equipment_door has open)
+ print "is open onto an equipment room.^^";
+ else
+ print "is plain and leads to a small equipment room. All three are closed.^^";
+ if (deutsch_door has open)
+ print "At the north end is an
+ open door leading to the Deutsch lab.^";
+ else
+ print "At the north end a fourth door leads to
+ the Deutsch lab.^";
+ ],
+ s_to basement_door,
+ se_to bostrom_door,
+ e_to wallace_door,
+ ne_to basement_equipment_door,
+ n_to deutsch_door,
+ cant_go "The only exits are to the Deutsch lab (north) the three doors lining
+ the corridor (south-east, east and north-east) and the automatic door
+ back to the landing (south).",
+ lower_name "the basement corridor",
+ has ;
+
+FakeDoor bostrom_door "door to the Bostrom Lab" basement_corridor
+ with name 'door' 'grey' 'gray' 'bostrom' 'first' 'lab' 'se' 'south-east',
+ description "A gray door with a small glass window,
+ looking into a darkened lab.
+ A small plaque reads: 'Bostrom Lab'.",
+ has locked scenery;
+
+FakeDoor wallace_door "door to the Wallace Lab" basement_corridor
+ with name 'door' 'grey' 'gray' 'wallace' 'second' 'lab' 'e\\' 'east',
+ description "A gray door with a small glass window,
+ looking into a darkened lab.
+ A small plaque reads: 'Wallace Lab'.",
+ has locked scenery;
+
+PluralSight doors_in_basement_corridor "doors" basement_corridor
+ with name 'doors',
+ description [;
+ print "There are three doors on the eastern wall of the corridor,
+ the first two (to the south-east and east) lead to the Bostrom
+ and Wallace labs. The third (to the north-east) ";
+ if (basement_equipment_door has open)
+ print "is open and ";
+ print "leads to a small equipment room. At the north end is the ";
+ if (deutsch_door has open)
+ print "open ";
+ print "door to the Deutsch lab. ";
+ print "To the south, the plate glass automatic door to the landing ";
+ if (basement_door has open)
+ print "lies open.^";
+ else
+ print "stands closed.^";
+ ],
+ has pluralname;
+
+!-----------------------------------------------
+
+Room upstairs_corridor "Second Floor Corridor"
+ with description
+ "A long north-south corridor, much the same as
+ those on the other floors. Three plain gray doors line the eastern wall.",
+ n_to balcony_door,
+ ne_to conference_door,
+ e_to butterfield_door,
+ se_to brown_door,
+ s_to upstairs_door,
+ cant_go "The only exits are to the balcony (north) the three doors lining
+ the corridor (south-east, east and north-east) and the automatic door
+ back to the landing (south).",
+ lower_name "the second floor corridor",
+ has ;
+
+FakeDoor brown_door "door to Dr Brown's office" upstairs_corridor
+ with name 'door' 'grey' 'gray' 'brown' 'office' 'brown^s' 'Dr' 'first' 'se' 'south-east',
+ description "A simple gray door.
+ A small plaque reads: 'Dr Brown'.",
+ has locked scenery;
+
+FakeDoor butterfield_door "door to Professor Butterfield's office" upstairs_corridor
+ with name 'door' 'office' 'grey' 'gray' 'butterfield' 'butterfield^s' 'Prof' 'second'
+ 'e\\' 'east',
+ description "A simple gray door.
+ A small plaque reads: 'Prof Butterfield'.",
+ has locked scenery;
+
+FakeDoor conference_door "door to the conference room" upstairs_corridor
+ with name 'door' 'grey' 'gray' 'conference' 'third' 'ne' 'north-east',
+ description "A plain gray door.
+ A small plaque reads: 'Conference Room'.",
+ found_in upstairs_corridor conference_room,
+ has locked scenery;
+
+PluralSight doors_in_upstairs_corridor "doors" upstairs_corridor
+ with name 'doors',
+ description [;
+ print "There are three doors on the eastern wall of the corridor,
+ the first two (to the south-east and east) lead to Dr Brown
+ and Professor Butterfield's offices. The third (to the north-east)
+ leads to the conference room. At the north end is the ";
+ if (balcony_door has open)
+ print "open ";
+ print "glass door to the balcony. ";
+ print "To the south, the plate glass automatic door to the landing ";
+ if (upstairs_door has open)
+ print "lies open.^";
+ else
+ print "stands closed.^";
+ ],
+ has pluralname;
+
+!-----------------------------------------------
+
+Room deutsch_lab "The Deutsch Laboratory"
+ with name 'lab' 'deutsch' 'laboratory',
+ description [;
+ if (self hasnt visited) {
+ print "The lab is order and chaos. By the dim blue-green light of a few swirling
+ screen savers, you can see the cluttered benches of your colleagues, frozen in the
+ mess of academic creativity. Frozen exactly as they were when badges were flashed,
+ when we looked on in disbelief as they took control of the lab. Yours however, is clean.
+ The books and papers are in neat stacks. They have been working here.^
+ ^
+ Nearby, against the north wall is the prototype, a six foot cylinder of brushed steel cladding.
+ The door has been taken off and is nowhere to be seen. They have been working on it too.
+ You wince at the sight.^";
+
+ if (deutsch_door has open)
+ print "^To the south, the door to the lab lies open.^";
+ else
+ print "^To the south, the door to the lab stands closed.^";
+
+ return true;
+ }
+ print "The lab is order and chaos. By the dim blue-green light of a few swirling
+ screen savers, you can see the cluttered benches of your colleagues, frozen in the
+ mess of academic creativity. Yours however, is clean.
+ The books and papers are in neat stacks. They have been working here.^
+ ^
+ Nearby, against the north wall is the prototype, a six foot cylinder of brushed steel cladding.
+ They have been working on it too.
+ The door has been taken off and is nowhere to be seen.^";
+
+ if (deutsch_door has open)
+ "^To the south, the door to the lab lies open.";
+ else
+ "^To the south, the door to the lab stands closed.";
+ ],
+ out_to deutsch_door,
+ s_to deutsch_door,
+ in_to prototype_interior,
+ cant_go "The only exits are to the south and in to the prototype.",
+ lower_name "the Deutsch laboratory",
+ has proper;
+
+
+Object prototype "prototype"
+ with description [;
+ if (~~prototype_seen) {
+ prototype_seen = true;
+ print "You had built the prototype to get a strong negative result,
+ to show that the standard model of Quantum Mechanics
+ led to demonstrably false claims involving reverse causation. You were mistaken.
+ One by one, your experiments showed your preliminary calculations to have been correct.
+ When the military removed you from your project, only one aspect
+ remained untested -- an aspect
+ you had been loath to test before you could predict the results -- inconsistent observation.^
+ ^
+ What would happen if anomalies were observed by those in the original
+ time-line? Your prior experiments had heavily shielded the prototype from outside interaction
+ to avoid the very possibility. And as the calculations came out time and again,
+ that is the only reason you are alive today.
+ When an observer in the original time-line has an anomalous observation, the wave
+ function of the temporally relocated object collapses and the relocation retrospectively fails,
+ preserving chronological consistency. There is just one side effect:
+ total transformation of the object's mass into a burst of photons -- pure energy.^
+ ^
+ You tried to tell them over and again. They assumed you were merely jealous of the takeover.
+ Now, the night before their scheduled 'first main experiment', you have come to
+ put an end to it all. To destroy your prototype and avoid tomorrow's nightmare.^
+ ^
+ The prototype itself is a six foot tall, four foot wide cylinder, clad with
+ brushed steel. The frame and door were fitted with quantum shielding
+ to prevent decoherence of the wave function, but now the door has been
+ removed and any use of the machine is potentially disastrous.^";
+ }
+ else
+ print "The prototype is a six foot tall, four foot wide cylinder clad with
+ brushed steel. The frame and door were fitted with quantum shielding
+ to prevent decoherence of the wave function, but now the door has been
+ removed and any use of the machine is potentially disastrous.^";
+ if (~~(self.fixed))
+ "^On close inspection, it appears that an attempt is in progress
+ to move the control panel so that it can be operated from the inside.
+ As it is, the prototype is currently not functioning, but you think
+ you could probably complete the modification within a minute or two.";
+ return true;
+ ],
+ name 'prototype' 'time' 'machine' 'six' 'foot' 'cylinder',
+ fixed,
+ before [t;
+ Set:
+ if (self.fixed) {
+ if (self in deutsch_lab)
+ "The prototype has been modified so that the only way to operate it is
+ to enter it and use the internal control panel.";
+ if (self in prototype_interior)
+ <<Set control_panel>>;
+ }
+ else
+ "You will need to complete the partial modifications to use the prototype.";
+ SetTo:
+ if (self.fixed) {
+ if (self in deutsch_lab)
+ "The prototype has been modified so that the only way to operate it is
+ to enter it and use the internal control panel.";
+ if (self in prototype_interior)
+ <<SetTo control_panel second>>;
+ }
+ else
+ "You will need to complete the partial modifications to use the prototype.";
+ SwitchOn:
+ if (self.fixed) {
+ if (self in deutsch_lab)
+ "The prototype has been modified so that the only way to operate it is
+ to enter it and use the internal control panel.";
+ if (self in prototype_interior) {
+ print "(pressing the silver button)^";
+ <<Push silver_button>>;
+ }
+ }
+ else
+ "You will need to complete the partial modifications to use the prototype.";
+ Enter:
+ <<Go in_obj>>;
+ Exit:
+ if (real_location == prototype_interior)
+ <<Go out_obj>>;
+ Tie:
+ if (~~d_paradox) {
+ if (second == nothing) {
+ if (self.fixed)
+ "It is already fixed.";
+ if (AmHolding(cable)) {
+ if (self in deutsch_lab) {
+ print "(first entering the prototype)^";
+ <Go in_obj>;
+ IncTime();
+ if (Stopped()) return true;
+ print "^";
+ }
+ move GetHeld(cable) to limbo;
+ print "You begin work completing the modifications...^";
+ for (t=0 : t<10 : t++) {
+ IncTime();
+ if (Stopped()) return true;
+ }
+ self.fixed = true;
+ prototype_fixed_time = my_time;
+ print "After a minute or so, you are done.^";
+ return true;
+ }
+ else
+ "After a few moments, you realise that completing the modification
+ will require a ribbon cable to connect the components. You know the
+ type of cable well, but don't have any in the lab right now.
+ Still, the equipment room in the corridor should have one.";
+ }
+ }
+ Attack:
+ "It won't be enough to smash the prototype by hand as there are too many
+ circuits buried away inside that would not be harmed.
+ Besides, that is why you brought the bomb.";
+ Search:
+ if (self in deutsch_lab) {
+ print "(first entering the prototype)^";
+ <<Go in_obj>>;
+ }
+ else
+ <<Look>>;
+ ],
+ react_before[;
+ Insert:
+ if (~~(self.fixed))
+ if (IsOfType(noun,cable))
+ if ((second == self) || (second == control_panel))
+ <<Tie prototype>>;
+ if (second == self) {
+ if (noun == self)
+ "It wont fit. Obviously. What were you thinking? It is a prototype
+ chrono-transference device, not some kind of TARDIS.";
+ if (self in deutsch_lab) {
+ move noun to prototype_interior;
+ print "You reach in and place ", (the) noun, " inside the prototype.^";
+ return true;
+ }
+ else
+ <<Drop noun>>;
+ }
+ ],
+ found_in deutsch_lab prototype_interior,
+ has scenery concealed;
+
+Furniture bench "your bench" deutsch_lab
+ with description "Your bench has clearly been used recently, and not by you.",
+ before [;
+ Examine:
+ print "Your bench has clearly been used recently, and not by you.
+ Your books and papers are neatly piled to one side, leaving
+ the largest expanse of bare desk you have ever seen here.^";
+ if (~~have_looked_at_bench) {
+ have_looked_at_bench = true;
+ "^You suddenly notice that your research notes are not here.
+ You were sure they would be -- and would thus be destroyed in the blast.
+ This is bad. Very bad.";
+ }
+ return true;
+ Search:
+ <<Examine self>>;
+ ],
+ name 'bench' 'your' 'benches' 'table' 'desk',
+ has scenery proper;
+
+Prop books "text books" deutsch_lab
+ with description "A few texts on Quantum Mechanics and String Theory
+ that have served you very well.",
+ name 'books' 'book' 'texts',
+ has;
+
+Prop papers "papers" deutsch_lab
+ with description [;
+ print "A collection of photocopied journal papers that you had been reading
+ a few weeks ago.^";
+ if (~~have_looked_at_bench) {
+ have_looked_at_bench = true;
+ "^You suddenly notice that your research notes are not here.
+ You were sure they would be -- and would thus be destroyed in the blast.
+ This is bad. Very bad.";
+ }
+ return true;
+ ],
+ name 'papers' 'photocopies' 'stack' 'stacks',
+ has;
+
+Prop screen_savers "screen savers" deutsch_lab
+ with description "Abstract, organic shapes leave glowing phosphor trails as they swirl around
+ and through themselves.",
+ name 'screen' 'screens' 'saver' 'savers' 'computer' 'computers' 'light' 'violet' 'green' 'blue'
+ 'blue-green' 'swirling',
+ has;
+
+Prop cladding "cladding" deutsch_lab
+ with name 'cladding' 'steel' 'brushed' 'frame' 'hatch',
+ has;
+
+Prop mess "mess" deutsch_lab
+ with description "The usual academic mess -- open books, coffee stained mugs, sprawling papers
+ -- frozen in time.",
+ name 'mess' 'chaos',
+ has;
+
+Sight control_panel_from_lab "control panel" deutsch_lab
+ with description "You cannot see the control panel clearly from here, and would need to enter the prototype.",
+ name 'control' 'panel',
+ before [;
+ Push:
+ <<Tie prototype>>;
+ Examine:
+ "You cannot see the control panel clearly from here, and would need to enter the prototype.";
+ default:
+ "You would have to enter the prototype to do that.";
+ ],
+ has;
+
+!-----------------------------------------------
+
+Room prototype_interior "Inside the prototype"
+ with description [;
+ if (prototype.fixed) {
+ print "The interior of the prototype is cramped and dark.
+ On the wall you see the control panel with a small LED timer
+ set to ", control_panel.time_value, " seconds, and a silver button.
+ Through the open hatch you can see some of the Deutsch lab.^";
+ }
+ else
+ "The interior of the prototype is cramped and dark.
+ On the wall you can see the half-installed control panel.
+ Through the open hatch you can see some of the Deutsch lab.";
+ ],
+ name 'prototype' 'time' 'machine' 'interior',
+ out_to deutsch_lab,
+ lower_name "the prototype",
+ cant_go "The only exit is out to the Deutsch lab.",
+ has proper;
+
+Object control_panel "control panel" prototype_interior
+ with name 'control' 'panel' 'led' 'timer' 'time' 'screen',
+ description [;
+ print "A brushed steel control panel with a blue LED timer, set to ",
+ control_panel.time_value, " seconds, and a shiny silver button.^";
+ ],
+ time_value,
+ before [;
+ Push:
+ <<Tie prototype>>;
+ Set:
+ if (prototype.fixed)
+ "To set the control panel,
+ you need to specify a number of seconds,
+ for example, with 'set panel to 75'.";
+ else
+ "You won't be able to set the control panel
+ until you complete the modifications.";
+ SetTo:
+ if (prototype.fixed) {
+ if (second > 0 && second <= 500) {
+ self.time_value = second;
+ "You quickly type the number in to the control panel.";
+ }
+ else {
+ "The prototype's control panel only accepts
+ between 1 and 500 seconds.";
+ }
+ }
+ else
+ "You won't be able to set the control panel
+ until you complete the modifications.";
+ SwitchOn:
+ if (self.fixed) {
+ print "(pressing the silver button)^";
+ <<Push silver_button>>;
+ }
+ else
+ "You will need to complete the partial modifications to use the prototype.";
+ ],
+ has scenery concealed;
+
+Object silver_button "silver button" prototype_interior
+ with name 'button' 'silver' 'silvered',
+ description "A silvered button.",
+ before [old_value t;
+ Push:
+ if (prototype.fixed) {
+ if (control_panel.time_value == 0)
+ "The control panel emits a small beep and the number '0'
+ flashes out at you. Perhaps you should set it first.";
+ else if (time_travelled < MAX_TIME_TRAVELS) {
+ old_value = control_panel.time_value;
+ TravelThroughTime(control_panel.time_value);
+ if (deadflag)
+ return true;
+ for (t=0 : t < time_travelled : t++)
+ if ((Get2D(player_loc,t,my_time-EARLIEST_TIME) == deutsch_lab) ||
+ (Get2D(player_loc,t,my_time-EARLIEST_TIME) == prototype_interior))
+ "You hold your breath and activate the prototype.";
+ ! this is needed to avoid silly message below, then death
+ if ((old_value % 5) ~= 0)
+ "You pause for a moment after pressing the button,
+ carefully resynchronizing yourself with the
+ five second turn increments.";
+ else
+ "You hold your breath and activate the prototype.";
+ }
+ else
+ "Nothing happens.";
+ }
+ else
+ "The button won't work
+ until you complete the modifications.";
+ Receive:
+ "The button is set into a vertical surface, making it impossible
+ to place objects on top of it.";
+ ],
+ has scenery concealed;
+
+Sight deutsch_lab_from_prototype "Deutsch lab" prototype_interior
+ with description "You can't make out much of interest from here, just a few benches
+ under the shifting blue-violet-green light.",
+ name 'deutsch' 'lab' 'hatch' 'bench' 'benches',
+ has;
+
+Prop surface "inside surface" prototype_interior
+ with name 'walls' 'interior' 'surface' 'ceiling' 'floor' 'ground',
+ description "The interior of the prototype is clad
+ in smooth brushed steel.",
+ has ;
+!-----------------------------------------------
+
+Room basement_equipment "Basement Equipment Room"
+ with name 'equipment' 'room',
+ description [;
+ if (FlashLit()) {
+ MoveMoveableChildren(basement_equipment_gloom,self);
+ print "By the thin blue-white beam of your flashlight, you
+ see the crowded shelves of the equipment room.^";
+ if (basement_equipment_door has open)
+ print "^To the west, the door to the corridor lies open.^";
+ else
+ print "^To the west, the door to the corridor stands closed.^";
+ }
+ else {
+ MoveMoveableChildren(self,basement_equipment_gloom);
+ if (basement_equipment_door has open)
+ print "It is almost completely dark. Some faint light spills
+ in from the west through the open door, allowing you to just
+ discern the outlines of a series of shelves. By the door is
+ a light switch.^";
+ else
+ print "You are in complete darkness.^";
+ }
+ ],
+ out_to basement_equipment_door,
+ w_to basement_equipment_door,
+ sw_to [;<<Go w_obj>>;],
+ cant_go "The only exit is westwards, back to the corridor.",
+ lit false,
+ has_been_lit false,
+ lower_name "the basement equipment room",
+ has ;
+
+! A behind-the-scenes 'room' to store the items that should be hidden while the
+! basement equipment room is in darkness
+
+Room basement_equipment_gloom "Dark Basement Equipment Room"
+ with name 'equipment' 'room' 'dark',
+ lower_name "the dark basement equipment room",
+ has ;
+
+Object basement_light_switch "light switch" basement_equipment
+ with name 'switch' 'light' 'lights',
+ before [;
+ Push:
+ <<SwitchOn basement_light_switch>>;
+ SwitchOn:
+ if (~~self.blown) {
+ Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,BLOW_BASEMENT_LIGHT_);
+ self.blown = true;
+ if (FlashLit())
+ "The fluorescent lights flicker hopefully, strobing rapidly across the
+ scattered equipment. Then darkness. You blink away the after-images
+ and are left with only the faint torchlight.";
+ else
+ "The fluorescent lights flicker hopefully, strobing rapidly across the
+ scattered equipment. Then darkness. Nothing but a few fleeting
+ after-images of the cluttered room.";
+ }
+ else
+ "Click. Nothing happens.";
+ ],
+ react_before [;
+ Go:
+ MoveMoveableChildren(basement_equipment,basement_equipment_gloom);
+ ],
+ react_after [;
+ Drop:
+ if (~~(FlashLit())) {
+ move noun to basement_equipment_gloom;
+ }
+ Go:
+ if (basement_equipment.lit || FlashLit()) {
+ MoveMoveableChildren(basement_equipment_gloom,basement_equipment);
+ }
+ ],
+ blown false,
+ has static scenery concealed switchable;
+
+!-----------------------------------------------
+
+Room ground_equipment "First Floor Equipment Room"
+ with name 'equipment' 'room',
+ description [;
+ if (self.lit) {
+ MoveMoveableChildren(ground_equipment_gloom,self);
+ print "By the flickering fluorescent lights, you
+ see the crowded shelves of the equipment room.^";
+ if (ground_equipment_door has open)
+ print "^To the west, the door to the corridor lies open.^";
+ else
+ print "^To the west, the door to the corridor stands closed.^";
+ }
+ else {
+ if (FlashLit()) {
+ MoveMoveableChildren(ground_equipment_gloom,self);
+ print "By the thin blue-white beam of your flashlight, you
+ see the crowded shelves of the equipment room.^";
+ if (ground_equipment_door has open)
+ print "^To the west, the door to the corridor lies open.^";
+ else
+ print "^To the west, the door to the corridor stands closed.^";
+ }
+ else {
+ MoveMoveableChildren(self,ground_equipment_gloom);
+ if (ground_equipment_door has open)
+ print "It is almost completely dark. Some faint light spills
+ in from the west through the open door, allowing you to just
+ discern the outlines of a series of shelves. By the door is
+ a light switch.^";
+ else
+ print "You are in complete darkness.^";
+ }
+ }
+ ],
+ out_to ground_equipment_door,
+ w_to ground_equipment_door,
+ sw_to [;<<Go w_obj>>;],
+ cant_go "The only exit is westwards, back to the corridor.",
+ lit false,
+ has_been_lit false,
+ lower_name "the first floor equipment room",
+ has ;
+
+Room ground_equipment_gloom "Dark First Floor Equipment Room"
+ with name 'equipment' 'room' 'dark',
+ lower_name "the dark first floor equipment room",
+ has ;
+
+Object ground_light_switch "light switch" ground_equipment
+ with name 'switch' 'light' 'lights',
+ before [;
+ Push:
+ if (~~ground_equipment.lit) {
+ <<SwitchOn ground_light_switch>>;
+ }
+ else {
+ <<SwitchOff ground_light_switch>>;
+ }
+ SwitchOn:
+ if (~~ground_equipment.lit) {
+ ground_equipment.lit = true;
+ give self on;
+ print "The lights come on after a brief flicker.^";
+ <Look>;
+ instant_action_this_turn = false;
+ return true;
+ }
+ SwitchOff:
+ if (ground_equipment.lit) {
+ ground_equipment.lit = false;
+ give self ~on;
+ if (FlashLit())
+ "The lights flicker briefly, then go out,
+ leaving you in the faint torchlight.";
+ else {
+ MoveMoveableChildren(ground_equipment,ground_equipment_gloom);
+ "The lights flicker briefly, then go out,
+ leaving you in the darkness.";
+ }
+ }
+ ],
+ react_before [;
+ Go:
+ if (~~(ground_equipment.lit))
+ MoveMoveableChildren(ground_equipment,ground_equipment_gloom);
+ ],
+ react_after [;
+ Drop:
+ if (~~(ground_equipment.lit || FlashLit())) {
+ move noun to ground_equipment_gloom;
+ }
+ Go:
+ if ((ground_equipment.lit) || FlashLit()) {
+ MoveMoveableChildren(ground_equipment_gloom,ground_equipment);
+ }
+ ],
+ has static scenery concealed switchable;
+
+Prop shelves "shelves"
+ with name 'shelf' 'shelves' 'equipment' 'series' 'outlines' 'outline' 'clutter' 'cluttered',
+ description [;
+ if (((parent(self)).lit) || (Flashlit()))
+ "The shelves are filled with assorted lab equipment, but nothing of use
+ to you now.";
+ else
+ "You cannot make out any of the objects on the dark shelves.";
+ ],
+ found_in ground_equipment basement_equipment,
+ has ;
+
+Prop fluoro_light "fluorescent lights"
+ with name 'fluoro' 'fluorescent' 'flicker' 'flickering' 'tube',
+ description [;
+ if ((parent(self)).lit)
+ "The fluorescent tubes flicker brightly.";
+ else
+ "You can just make out a dark fluorescent tube in the ceiling above.";
+ ],
+ found_in ground_equipment basement_equipment,
+ has ;
+
+!-----------------------------------------------
+
+Room balcony "Balcony"
+ with name 'balcony',
+ description
+ "A wide balcony, looking out over the sleeping city. Below you, a lawn slopes gently away
+ into the gloom, a few silhouetted trees marking the edge of the modest grounds. Above, the
+ clear sky is a deep black, dusted with glinting stars.",
+ d_to [;Jumped(); return true;],
+ n_to [;Jumped(); return true;],
+ s_to balcony_door,
+ se_to conference_window,
+ in_to conference_window,
+ cant_go [;
+ if (conference_window has open)
+ "The only exits are the door back to the corridor (to the south)
+ and the window into the conference room (to the south-east).";
+ else
+ "The only exit is the door back to the corridor (to the south).";
+ ],
+ lower_name "the balcony",
+ has ;
+
+Prop balcony_floor "floor" balcony
+ with name 'floor' 'ground' 'tiles',
+ description "The floor is covered in white tiles.",
+ has ;
+
+Prop railing "railing" balcony
+ with name 'rail' 'railing' 'hand' 'handrail',
+ has ;
+
+Sight trees "trees" balcony
+ with name 'tree' 'trees' 'silhouette' 'silhouettes' 'cypress' 'cypresses' 'conifer' 'conifers',
+ description "The trees are some kind of tall conifer, cypress perhaps. You have fond
+ memories of dozing under them one afternoon last summer.",
+ has ;
+
+Sight grounds "grounds" balcony
+ with name 'lawn' 'slope' 'slopes' 'grounds' 'grass' 'gloom',
+ description "The grounds are little more than a well-kept lawn and a few tall trees, but
+ every night the security guard has to give them a brief inspection.",
+ has ;
+
+Sight guard "guard" balcony
+ with name 'guard' 'security' 'guards',
+ description "There is no sign of the security guard.",
+ has ;
+
+Sight stars "stars"
+ with name 'stars' 'star' 'black' 'dust' 'constellations',
+ description "The stars are a beautiful spray of glinting jewels in the blackness above.",
+ found_in balcony conference_room,
+ has ;
+
+Sight night "night"
+ with name 'night' 'starry',
+ description "Outside, it is one of the finest fall nights you can recall.",
+ found_in balcony conference_room,
+ has ;
+
+Sight city "city"
+ with name 'city' 'boston' 'town' 'light' 'rooftops' 'roofs' 'skyscrapers' 'buildings' 'building',
+ description "Before you, lie the rooftops and skyscrapers of your home town. Here and there
+ a small yellow light glows, but for now Boston sleeps.",
+ found_in balcony conference_room,
+ has ;
+
+
+!-----------------------------------------------
+
+Room conference_room "Conference Room"
+ with name 'conference',
+ description "A rather slick but soulless affair. A large table of dark polished wood
+ takes pride of place and is surrounded by a half-dozen chairs.",
+ n_to conference_window,
+ nw_to conference_window,
+ out_to conference_window,
+ w_to conference_door,
+ cant_go "The only exits are the door to the west and the window to the north.",
+ lower_name "the conference room",
+ has ;
+
+Sight conference_room_sight "room" conference_room
+ with name 'room' 'conference',
+ description "A rather slick but soulless affair.",
+ before [;
+ Exit:
+ <<Go n_obj>>;
+ ],
+ has ;
+
+Furniture conference_table "conference table" conference_room
+ with description "A large round table of dark polished wood.",
+ name 'table' 'round' 'large' 'polished' 'dark' 'wood',
+ has scenery;
+
+Furniture chair "chair" conference_room
+ with description "Each chair is of a rather elegant, modern design
+ in the same dark wood as the table.",
+ name 'chair' 'chairs' 'seat' 'seats',
+ has scenery concealed;
+
+!-----------------------------------------------
+
+Room outside "Outside"
+ with description "Outside the lab, the street is quiet.",
+ n_to main_doors,
+ lower_name "the night",
+ has ;
+
+!-----------------------------------------------
+
+Room limbo "Night"
+ with description "The waiting place for unrealised items.",
+ lower_name "the night",
+ has ;
+
+
+!------------------------------------------------------------------------
+!
+! Door stuff
+!
+
+AutomaticDoor main_doors "main doors" foyer
+ with description [;
+ if (self has open)
+ print "Through the open doors, you can see the quiet grounds.
+ On the right hand side is a green button.^";
+ else
+ print "A pair of ";
+ if (self.smashed) print "cracked ";
+ print "plate glass sliding doors,
+ through which you can see the quiet grounds.
+ On the right hand side is a green button.^";
+ ],
+ when_closed "To the south is a set of automatic doors leading
+ out into the inky night.",
+ when_open "To the south is an open set of automatic doors leading
+ out into the inky night.",
+ name 'doors' 'main' 'south' 'plate' 'glass' 'sliding' 'set' 'auto',
+ door_to [;Escaped(); return true;],
+ door_dir s_to,
+ open_self [t;
+ if (self hasnt open) {
+ give self open ~locked;
+ if (self in LocationOf(player))
+ print "The main doors open onto the night.^";
+ }
+ self.to_close_at = t;
+ if ((player in foyer) && (my_time < start_time-1) && (my_time >= start_time-3)) {
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print "Outside, your former self darts quickly towards the main doors.
+ When she sees them open, she breaks her stride
+ and lets out a shocked gasp.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+ ],
+ closing_message [;
+ if ((~~Stopped()) && (self in LocationOf(player)))
+ "The main doors softly slide closed.";
+ ],
+ before [;
+ Open:
+ print "(pressing the green exit button)^";
+ <<Push exit_button>>;
+ Unlock:
+ if (IsOfType(second,crowbar))
+ <<Attack self>>;
+ else
+ "You cannot open the door with that.";
+ Enter:
+ if (self hasnt open) {
+ print "(first pressing the green exit button)^";
+ <Push exit_button>;
+ IncTime();
+ if (Stopped()) return true;
+ <<Go s_obj>>;
+ }
+ ],
+ react_before [; Go:
+ if (noun == s_to && self hasnt open)
+ <<Enter self>>;
+ ],
+ has pluralname;
+
+
+AutomaticDoor ground_door "automatic door"
+ with description [;
+ if (self in foyer) {
+ Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_GROUND_CORRIDOR_);
+ print "A ";
+ if (self.smashed) print "cracked ";
+ print "plate glass sliding door,
+ through which you can see a dim corridor. ";
+ if (IsIn(former_self,ground_corridor))
+ print "In the shadows stands your past self. ";
+ print "On the right hand side is a slot for an ID card.^";
+ }
+ if (self in ground_corridor) {
+ Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_FOYER_);
+ print "A ";
+ if (self.smashed) print "cracked ";
+ print "plate glass sliding door,
+ through which you can see the darkened foyer. ";
+ if (IsIn(former_self,foyer))
+ print "In the shadows stands your past self. ";
+ print "On the right hand side is a green button.^";
+ }
+ ],
+ when_closed [;
+ if (self in foyer)
+ "In the north wall is a closed
+ automatic door.";
+ if (self in ground_corridor)
+ "To the south is a closed automatic door, leading back
+ to the foyer.";
+
+ ],
+ when_open [;
+ if (self in foyer)
+ "In the north wall is an open
+ automatic door.";
+ if (self in ground_corridor)
+ "To the south is an open automatic door, leading back
+ to the foyer.";
+
+ ],
+ name 'north' 'door' 'automatic' 'auto' 'plate' 'glass' 'sliding',
+ door_to [;
+ if (self in foyer)
+ return ground_corridor;
+ if (self in ground_corridor)
+ return foyer;
+
+ ],
+ door_dir [;
+ if (self in foyer)
+ return n_to;
+ if (self in ground_corridor)
+ return s_to;
+
+ ],
+ before [;
+ Unlock:
+ if (IsOfType(second,crowbar))
+ <<Attack self>>;
+ else if (IsOfType(second,id_card) && (self in foyer))
+ <<Insert second id_slot>>;
+ else
+ "You cannot open the door with that.";
+ Open:
+ if (self in foyer)
+ if (self.known_exterior_opening == 0)
+ "There is no obvious way to get
+ the automatic door to open.";
+ else {
+ print "You press the button marked 'first'.^";
+ <<Push first_button>>;
+ }
+ if (self in ground_corridor) {
+ print "(pressing the green exit button)^";
+ <<Push exit_button>>;
+ }
+ Enter:
+ if (self in ground_corridor && self hasnt open) {
+ print "(first pressing the green exit button)^";
+ <Push exit_button>;
+ IncTime();
+ if (Stopped()) return true;
+ <<Go s_obj>>;
+ }
+ if (self in foyer && self hasnt open) {
+ if (self.known_exterior_opening == true) {
+ print "(first pressing the button marked 'first')^";
+ <Push first_button>;
+ IncTime();
+ if (Stopped()) return true;
+ <<Go n_obj>>;
+ }
+ else {
+ "There is no obvious way to get
+ the automatic door to open.";
+ }
+ }
+ ],
+ react_before [; Go:
+ if (noun == n_to && self in foyer && self hasnt open)
+ <<Enter self>>;
+ if (noun == s_to && self in ground_corridor && self hasnt open)
+ <<Enter self>>;
+ ],
+ known_exterior_opening,
+ found_in foyer ground_corridor,
+ has ;
+
+
+AutomaticDoor basement_door "automatic door"
+ with description [;
+ if (self in basement_landing) {
+ Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_BASEMENT_CORRIDOR_);
+ print "A ";
+ if (self.smashed) print "cracked ";
+ print "plate glass sliding door,
+ through which you can see a dim corridor. ";
+ if (IsIn(former_self,basement_corridor))
+ print "In the shadows stands your past self. ";
+ print "On the right hand side is a slot for an ID card.^";
+ }
+ if (self in basement_corridor) {
+ Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_BASEMENT_LANDING_);
+ print "A ";
+ if (self.smashed) print "cracked ";
+ print "plate glass sliding door,
+ through which you can see the small basement landing. ";
+ if (IsIn(former_self,basement_landing))
+ print "In the shadows stands your past self. ";
+ print "On the right hand side is a green button.^";
+ }
+ ],
+ name 'door' 'automatic' 'auto' 'plate' 'glass' 'sliding',
+ when_closed [;
+ if (self in basement_landing)
+ "To the north is a closed automatic door.";
+ if (self in basement_corridor)
+ "To the south is a closed automatic door, leading back
+ to the landing.";
+
+ ],
+ when_open [;
+ if (self in basement_landing)
+ "To the north is an open automatic door.";
+ if (self in basement_corridor)
+ "To the south is an open automatic door, leading back
+ to the landing.";
+
+ ],
+ door_to [;
+ if (self in basement_landing)
+ return basement_corridor;
+ if (self in basement_corridor)
+ return basement_landing;
+
+ ],
+ door_dir [;
+ if (self in basement_landing)
+ return n_to;
+ if (self in basement_corridor)
+ return s_to;
+
+ ],
+ before [;
+ Unlock:
+ if (IsOfType(second,crowbar))
+ <<Attack self>>;
+ else if (IsOfType(second,id_card) && (self in basement_landing))
+ <<Insert second id_slot>>;
+ else
+ "You cannot open the door with that.";
+ Open:
+ if (self in basement_landing) {
+ if ( AmHolding(id_card) ) {
+ print "(inserting your ID card)^";
+ <<Insert (GetHeld(id_card)) id_slot>>;
+ }
+ else
+ "You would need you ID card to do that.";
+ }
+ if (self in basement_corridor) {
+ print "(pressing the green exit button)^";
+ <<Push exit_button>>;
+ }
+ Enter:
+ if (self in basement_corridor && self hasnt open) {
+ print "(first pressing the green exit button)^";
+ <Push exit_button>;
+ IncTime();
+ if (Stopped()) return true;
+ <<Go s_obj>>;
+ }
+ if (self in basement_landing && self hasnt open) {
+ if ( AmHolding(id_card) ) {
+ print "(first inserting your ID card)^";
+ <Insert (GetHeld(id_card)) id_slot>;
+ IncTime();
+ if (Stopped()) return true;
+ <<Go n_obj>>;
+ }
+ else
+ "You would need you ID card to do that.";
+ }
+ ],
+ react_before [; Go:
+ if (noun == n_to && self in basement_landing && self hasnt open)
+ <<Enter self>>;
+ if (noun == s_to && self in basement_corridor && self hasnt open)
+ <<Enter self>>;
+ ],
+ known_exterior_opening,
+ found_in basement_landing basement_corridor,
+ has ;
+
+
+AutomaticDoor upstairs_door "automatic door"
+ with description [;
+ if (self in upstairs_landing) {
+ Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_UPSTAIRS_CORRIDOR_);
+ print "A ";
+ if (self.smashed) print "cracked ";
+ print "plate glass sliding door,
+ through which you can see a dim corridor. ";
+ if (IsIn(former_self,upstairs_corridor))
+ print "In the shadows stands your past self. ";
+ print "On the right hand side is a slot for an ID card.^";
+ }
+ if (self in upstairs_corridor) {
+ Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_UPSTAIRS_LANDING_);
+ print "A ";
+ if (self.smashed) print "cracked ";
+ print "plate glass sliding door,
+ through which you can see the upper part of the darkened foyer. ";
+ if (IsIn(former_self,upstairs_landing))
+ print "In the shadows of the landing stands your past self. ";
+ print "On the right hand side is a green button.^";
+ }
+ ],
+ name 'door' 'automatic' 'auto' 'plate' 'glass' 'sliding',
+ when_closed [;
+ if (self in upstairs_landing)
+ "On the north wall lies a closed automatic door.";
+ if (self in upstairs_corridor)
+ "To the south is a closed automatic door, leading back
+ to the landing.";
+ ],
+ when_open [;
+ if (self in upstairs_landing)
+ "On the north wall lies an open automatic door.";
+ if (self in upstairs_corridor)
+ "To the south is an open automatic door, leading back
+ to the landing.";
+ ],
+ door_to [;
+ if (self in upstairs_landing)
+ return upstairs_corridor;
+ if (self in upstairs_corridor)
+ return upstairs_landing;
+ ],
+ door_dir [;
+ if (self in upstairs_landing)
+ return n_to;
+ if (self in upstairs_corridor)
+ return s_to;
+ ],
+ before [;
+ Unlock:
+ if (IsOfType(second,crowbar))
+ <<Attack self>>;
+ else if (IsOfType(second,id_card) && (self in upstairs_landing))
+ <<Insert second id_slot>>;
+ else
+ "You cannot open the door with that.";
+ Open:
+ if (self in upstairs_landing)
+ if (AmHolding(id_card)) {
+ print "(inserting your ID card)^";
+ <<Insert (GetHeld(id_card)) id_slot>>;
+ }
+ if (self in upstairs_corridor) {
+ print "(pressing the green exit button)^";
+ <<Push exit_button>>;
+ }
+ Enter:
+ if (self in upstairs_corridor && self hasnt open) {
+ print "(first pressing the green exit button)^";
+ <Push exit_button>;
+ if (self has open) {
+ IncTime();
+ if (Stopped()) return true;
+ <<Go s_obj>>;
+ }
+ return true;
+ }
+ if (self in upstairs_landing && self hasnt open) {
+ "There is no obvious way to get the automatic door to open.";
+ }
+ ],
+ react_before [; Go:
+ if (noun == s_to && self in upstairs_corridor && self hasnt open)
+ <<Enter self>>;
+ ],
+ found_in upstairs_landing upstairs_corridor,
+ has ;
+
+Object exit_button "green exit button"
+ with description "A green button beside the door.",
+ name 'green' 'button',
+ before [; Push:
+ if (self in ground_corridor) {
+ ground_door.open_self(my_time+1);
+ }
+ if (self in upstairs_corridor) {
+ if (challenge)
+ "Nothing happens -- the button must be broken.";
+ else
+ upstairs_door.open_self(my_time+1);
+ }
+ if (self in basement_corridor) {
+ basement_door.open_self(my_time+1);
+ }
+ if (self in foyer) {
+ main_doors.open_self(my_time+1);
+ }
+ return true;
+ Receive:
+ "The button is set into a vertical surface, making it impossible
+ to place objects on top of it.";
+ ],
+ found_in ground_corridor upstairs_corridor basement_corridor foyer,
+ has scenery concealed;
+
+Object id_slot "ID card slot"
+ with description "A narrow slot to the right of the door.
+ The doors are coded so that only those with legitimate
+ business can use their card to gain entrance.",
+
+ name 'slot',
+ found_in foyer upstairs_landing basement_landing,
+ has scenery concealed;
+
+
+ManualDoor ground_equipment_door "door to the equipment room"
+ with name 'door' 'equipment' 'room' 'grey' 'gray' 'third' 'plain' 'ne' 'north-east',
+ description
+ "A simple gray door.",
+ door_to [;
+ if (self in ground_corridor)
+ return ground_equipment;
+ if (self in ground_equipment)
+ return ground_corridor;
+ ],
+ door_dir [;
+ if (self in ground_corridor)
+ return ne_to;
+ if (self in ground_equipment)
+ return w_to;
+ ],
+ before [;
+ Close:
+ if (((self in ground_equipment) && IsIn(former_self,ground_corridor)) ||
+ ((self in ground_corridor) && IsIn(former_self,ground_equipment)) ) {
+ CloseParadox();
+ return true;
+ }
+ Open:
+ if (((self in ground_equipment) && IsIn(former_self,ground_corridor)) ||
+ ((self in ground_corridor) && IsIn(former_self,ground_equipment)) ) {
+ OpenParadox();
+ return true;
+ }
+ else
+ return (OpenManualDoor(self,second));
+ Unlock:
+ if (IsOfType(second,crowbar))
+ <<Attack self>>;
+ if (((self in ground_equipment) && IsIn(former_self,ground_corridor)) ||
+ ((self in ground_corridor) && IsIn(former_self,ground_equipment)) ) {
+ LockUnlockParadox();
+ return true;
+ }
+ else
+ return (UnlockManualDoor(self,second));
+ Lock:
+ if (((self in ground_equipment) && IsIn(former_self,ground_corridor)) ||
+ ((self in ground_corridor) && IsIn(former_self,ground_equipment)) ) {
+ LockUnlockParadox();
+ return true;
+ }
+ else
+ return (LockManualDoor(self,second));
+ ],
+ with_key_type equipment_key,
+ found_in ground_corridor ground_equipment,
+ has locked scenery;
+
+ManualDoor basement_equipment_door "door to the equipment room"
+ with name 'door' 'equipment' 'room' 'grey' 'gray' 'third' 'plain' 'ne' 'north-east',
+ description
+ "A simple gray door.",
+ door_to [;
+ if (self in basement_corridor)
+ return basement_equipment;
+ if (self in basement_equipment)
+ return basement_corridor;
+
+ ],
+ door_dir [;
+ if (self in basement_corridor)
+ return ne_to;
+ if (self in basement_equipment)
+ return w_to;
+ ],
+ before [;
+ Close:
+ if (((self in basement_equipment) && IsIn(former_self,basement_corridor)) ||
+ ((self in basement_corridor) && IsIn(former_self,basement_equipment)) ) {
+ CloseParadox();
+ return true;
+ }
+ Open:
+ if (((self in basement_equipment) && IsIn(former_self,basement_corridor)) ||
+ ((self in basement_corridor) && IsIn(former_self,basement_equipment)) ) {
+ OpenParadox();
+ return true;
+ }
+ else
+ return (OpenManualDoor(self,second));
+ Unlock:
+ if (IsOfType(second,crowbar))
+ <<Attack self>>;
+ if (((self in basement_equipment) && IsIn(former_self,basement_corridor)) ||
+ ((self in basement_corridor) && IsIn(former_self,basement_equipment)) ) {
+ LockUnlockParadox();
+ return true;
+ }
+ else
+ return (UnlockManualDoor(self,second));
+ Lock:
+ if (((self in basement_equipment) && IsIn(former_self,basement_corridor)) ||
+ ((self in basement_corridor) && IsIn(former_self,basement_equipment)) ) {
+ LockUnlockParadox();
+ return true;
+ }
+ else
+ return (LockManualDoor(self,second));
+ ],
+ with_key_type equipment_key,
+ found_in basement_corridor basement_equipment,
+ has locked scenery;
+
+ManualDoor deutsch_door "door to the Deutsch lab"
+ with name 'door' 'deutsch' 'lab' 'fourth' 'north' 'n\\',
+ description [;
+ if (self in basement_corridor)
+ "A gray door with a small glass window,
+ looking into the darkened lab.";
+ if (self in deutsch_lab)
+ "A gray door with a small glass window,
+ looking into the darkened corridor.";
+ ],
+ door_to [;
+ if (self in basement_corridor)
+ return deutsch_lab;
+ if (self in deutsch_lab)
+ return basement_corridor;
+ ],
+ door_dir [;
+ if (self in basement_corridor)
+ return n_to;
+ if (self in deutsch_lab)
+ return s_to;
+ ],
+ before [;
+ Close:
+ if (((self in deutsch_lab) && IsIn(former_self,basement_corridor)) ||
+ ((self in basement_corridor) && IsIn(former_self,deutsch_lab)) ) {
+ CloseParadox();
+ return true;
+ }
+ Open:
+ if (((self in deutsch_lab) && IsIn(former_self,basement_corridor)) ||
+ ((self in basement_corridor) && IsIn(former_self,deutsch_lab)) ) {
+ OpenParadox();
+ return true;
+ }
+ else
+ return (OpenManualDoor(self,second));
+ Unlock:
+ if (IsOfType(second,crowbar))
+ <<Attack self>>;
+ if (((self in deutsch_lab) && IsIn(former_self,basement_corridor)) ||
+ ((self in basement_corridor) && IsIn(former_self,deutsch_lab)) ) {
+ LockUnlockParadox();
+ return true;
+ }
+ else
+ return (UnlockManualDoor(self,second));
+ Lock:
+ if (((self in deutsch_lab) && IsIn(former_self,basement_corridor)) ||
+ ((self in basement_corridor) && IsIn(former_self,deutsch_lab)) ) {
+ LockUnlockParadox();
+ return true;
+ }
+ else
+ return (LockManualDoor(self,second));
+ ],
+ with_key_type deutsch_key,
+ found_in basement_corridor deutsch_lab,
+ has locked scenery;
+
+ManualDoor balcony_door "balcony door"
+ with name 'door' 'balcony' 'n\\' 'north' 'glass',
+ description [;
+ if (self in upstairs_corridor) {
+ Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_BALCONY_);
+ print "A ";
+ if (self.smashed) print "cracked ";
+ print "glass door looking out onto the balcony. ";
+ if (IsIn(former_self,balcony))
+ print "In the shadows you can see your past self.^";
+ else
+ print "^";
+ }
+ if (self in balcony) {
+ Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_UPSTAIRS_CORRIDOR_);
+ print "A ";
+ if (self.smashed) print "cracked ";
+ print "glass door looking into the upstairs corridor. ";
+ if (IsIn(former_self,upstairs_corridor))
+ print "In the shadows you can see your past self.^";
+ else
+ print "^";
+ }
+ ],
+ when_closed [;
+ if (self in balcony)
+ "To the south, the door to the upstairs corridor stands closed.";
+ else
+ "At the north end of the corridor is a closed glass door leading out
+ to the balcony.";
+ ],
+ when_open [;
+ if (self in balcony)
+ "To the south, the door to the upstairs corridor lies open.";
+ else
+ "At the north end of the corridor is an open glass door leading out
+ to the balcony.";
+ ],
+ door_to [;
+ if (self in upstairs_corridor)
+ return balcony;
+ if (self in balcony)
+ return upstairs_corridor;
+
+ ],
+ door_dir [;
+ if (self in upstairs_corridor)
+ return n_to;
+ if (self in balcony)
+ return s_to;
+ ],
+ before [;
+ Close:
+ if (((self in balcony) && IsIn(former_self,upstairs_corridor)) ||
+ ((self in upstairs_corridor) && IsIn(former_self,balcony)) ) {
+ CloseParadox();
+ return true;
+ }
+ Open:
+ if (((self in balcony) && IsIn(former_self,upstairs_corridor)) ||
+ ((self in upstairs_corridor) && IsIn(former_self,balcony)) ) {
+ OpenParadox();
+ return true;
+ }
+ else
+ return (OpenManualDoor(self,second));
+ Unlock:
+ if (IsOfType(second,crowbar))
+ <<Attack self>>;
+ if (((self in balcony) && IsIn(former_self,upstairs_corridor)) ||
+ ((self in upstairs_corridor) && IsIn(former_self,balcony)) ) {
+ LockUnlockParadox();
+ return true;
+ }
+ else
+ return (UnlockManualDoor(self,second));
+ Lock:
+ if (((self in balcony) && IsIn(former_self,upstairs_corridor)) ||
+ ((self in upstairs_corridor) && IsIn(former_self,balcony)) ) {
+ LockUnlockParadox();
+ return true;
+ }
+ else
+ return (LockManualDoor(self,second));
+ Attack:
+ if (AmHolding(crowbar)) {
+ print "You swing the crowbar firmly into the door. It shudders,
+ cracks reaching out from the point of impact, but the glass
+ stays in place.^";
+ self.smashed = true;
+ StartSiren();
+ return true;
+ }
+ else
+ "You don't have anything heavy enough to smash the door with.";
+ Search:
+ <<Examine self>>;
+ ],
+ smashed false,
+ with_key_type nothing,
+ found_in upstairs_corridor balcony,
+ has ;
+
+Object conference_window "window into the conference room"
+ with name 'window' 'glass' 'tinted' 'remains' 'shards',
+ description [;
+ if (self in balcony) {
+ if (self has open)
+ "The remains of a plate glass window that has been smashed in with
+ something heavy. Large shards of glass still protrude from the edges,
+ framing the murky interior of the conference room.";
+ else if (FlashLit())
+ "My God! It's full of stars.";
+ else
+ "A plate glass window looking into the murky interior of an conference room.";
+ }
+ if (self in conference_room) {
+ Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_BALCONY_);
+ if (self has open)
+ print "The remains of a plate glass window that has been smashed in with
+ something heavy. Large shards of glass still protrude from the edges,
+ framing the starry night beyond. ";
+ else
+ "A plate glass window looking out into the starry night. ";
+ if (IsIn(former_self,balcony))
+ print "Against the stars, you can just make out the silhouette of your
+ past self.^";
+ else
+ print "^";
+ }
+ ],
+ when_closed [;
+ if (self in balcony)
+ "To the south-east is a large, tinted glass window.";
+ if (self in conference_room)
+ "To the north is a large plate glass window, amazingly intact.";
+
+ ],
+ when_open [;
+ if (self in balcony)
+ "To the south-east, lie the shattered remains of a window, opening into
+ a murky conference room.";
+
+ if (self in conference_room)
+ "To the north, lie the shattered remains of a window, open to
+ the starry night.";
+ ],
+ door_to [;
+ if (self in balcony)
+ return conference_room;
+ if (self in conference_room)
+ return balcony;
+
+ ],
+ door_dir [;
+ if (self in balcony)
+ return se_to;
+ if (self in conference_room)
+ return n_to;
+
+ ],
+ before [;
+ Open:
+ if (second == nothing)
+ "The window appears to be locked from the inside.";
+ Unlock:
+ if (IsOfType(second, crowbar))
+ <<Attack self>>;
+ else if (second ~= nothing)
+ "You cannot get the window open with that.";
+ else
+ "You cannot find the lock.";
+ Attack:
+ if (AmHolding(crowbar)) {
+ if (self has open)
+ "The window is already thoroughly broken.";
+ give self open;
+ print "You swing the crowbar firmly into the window and it shatters with
+ a loud crash.^";
+ StartSiren();
+ return true;
+ }
+ else
+ "You don't have anything heavy enough to smash the window with.";
+ Search:
+ <<Examine self>>;
+ ],
+ with_key_type nothing,
+ found_in balcony conference_room,
+ has static locked door lockable;
+
+
+
+!============================================================================
+!
+! Functions:
+!
+
+!----------------------------------------------------
+!
+! Entry point functions:
+
+
+! Puts the time in HH:MM:SS format on the status line
+
+[ DrawStatusLine width pos;
+
+ ! @split_window 0;
+ ! return;
+
+ @split_window 1;
+ @set_window 1;
+ @set_cursor 1 1;
+ style reverse;
+ width = 0->33;
+ pos = width-20;
+ spaces (width);
+
+ @set_cursor 1 2;
+ PrintShortName(location);
+
+ @set_cursor 1 pos;
+ print (PrintTime) my_time;
+
+ @set_cursor 1 1;
+ style roman;
+ @set_window 0;
+];
+
+[ ScoreSub;
+ if (deadflag == 0)
+ "There is no score in this game.";
+];
+
+[ ChooseObjects obj code;
+ if (code < 2) {
+ if (obj has scenery)
+ return 2; ! exclude scenery from 'get all' commands
+ if (action_to_be == ##Take && obj has static)
+ return 2; ! exclude scenery from 'get all' commands
+ rfalse;
+ }
+ if (action_to_be == ##Insert && obj in player) ! prefer to insert into held objects
+ return 3; ! particularly important with all
+ ! these duplicates...
+ if (action_to_be == ##Close && (obj has openable) && (obj has open))
+ return 3;
+ if (action_to_be == ##Open && (obj has openable) && (obj hasnt open))
+ return 3;
+ if (action_to_be == ##Lock && (obj has lockable) && (obj hasnt locked))
+ return 3;
+ if (action_to_be == ##Unlock && (obj has lockable) && (obj has locked))
+ return 3;
+ if (action_to_be == ##LockSimple && (obj has lockable) && (obj hasnt locked))
+ return 3;
+ if (action_to_be == ##UnlockSimple && (obj has lockable) && (obj has locked))
+ return 3;
+ if (action_to_be == ##Take && obj has static) ! prefer to get non-statics
+ return 1;
+ if (obj hasnt scenery) ! prefer non-scenery in general
+ return 2;
+ return 1;
+];
+
+[ Initialise i;
+
+ lookmode = 2; ! 'verbose'
+
+ my_time = start_time;
+
+ location = foyer;
+
+ player = myselfobj;
+
+ for (i=0 : i < MAX_ITEM_COPIES : i++) {
+ bomb-->i = Bomb_.create();
+ id_card-->i = IDCard_.create();
+ equipment_key-->i = EquipmentKey_.create();
+ deutsch_key-->i = DeutschKey_.create();
+ flashlight-->i = Flashlight_.create();
+ battery-->i = Battery_.create();
+ cable-->i = Cable_.create();
+ crowbar-->i = Crowbar_.create();
+ notes-->i = Notes_.create();
+ }
+
+ move bomb-->0 to player;
+ move id_card-->0 to player;
+ move deutsch_key-->0 to player;
+ move equipment_key-->0 to deutsch_lab;
+ move flashlight-->0 to deutsch_lab;
+ move battery-->0 to ground_equipment_gloom;
+ move cable-->0 to ground_equipment_gloom;
+ move crowbar-->0 to basement_equipment_gloom;
+ move notes-->0 to conference_table;
+
+ for (i=1 : i < MAX_ITEM_COPIES : i++) {
+ move bomb-->i to limbo;
+ move id_card-->i to limbo;
+ move equipment_key-->i to limbo;
+ move deutsch_key-->i to limbo;
+ move flashlight-->i to limbo;
+ move battery-->i to limbo;
+ move cable-->i to limbo;
+ move crowbar-->i to limbo;
+ move notes-->i to limbo;
+ }
+
+ for (i=0 : i < MAX_TIME_TRAVELS : i++) {
+ former_self-->i = FormerSelf_.create();
+ move former_self-->i to limbo;
+ }
+
+ InitHistory();
+
+ "^
+ ^
+ You're in.^
+ ^
+ The plan now is simple: go to your lab, plant the bomb, and run.
+ The prototype will be destroyed. The military will have no way to
+ continue the experiment. No-one will die.^
+ ^
+ The guard is out securing the grounds. The building is empty. You have six minutes.^
+ ^
+ ";
+
+];
+
+!----------------------------------------------------
+!
+! Major tasks:
+
+
+!! Initialises the first self's history for all items
+!! First wipe's the history clean with all locations as 'limbo'
+!! Next updates pre-start_time histories of all items and the player
+!! Then updates the states with the proper pasts and UNKNOWN futures
+
+[InitHistory t i s;
+ for (t = EARLIEST_TIME : t <= FINAL_TIME : t++) {
+ for (i=0 : i < MAX_ITEM_COPIES : i++) {
+ Put3D(bomb_loc, 0, (t - EARLIEST_TIME),
+ i, limbo );
+ Put3D(id_card_loc, 0, (t - EARLIEST_TIME),
+ i, limbo );
+ Put3D(equipment_key_loc, 0, (t - EARLIEST_TIME),
+ i, limbo );
+ Put3D(deutsch_key_loc, 0, (t - EARLIEST_TIME),
+ i, limbo );
+ Put3D(flashlight_loc, 0, (t - EARLIEST_TIME),
+ i, limbo );
+ Put3D(battery_loc, 0, (t - EARLIEST_TIME),
+ i, limbo );
+ Put3D(cable_loc, 0, (t - EARLIEST_TIME),
+ i, limbo );
+ Put3D(crowbar_loc, 0, (t - EARLIEST_TIME),
+ i, limbo );
+ Put3D(notes_loc, 0, (t - EARLIEST_TIME),
+ i, limbo );
+
+ Put3D(flashlight_state, 0, (t - EARLIEST_TIME),
+ i, UNKNOWN_ );
+ Put3D(bomb_setting, 0, (t - EARLIEST_TIME),
+ i, UNKNOWN_ );
+ }
+ }
+
+ for (t = EARLIEST_TIME : t <= start_time : t++) {
+ Put3D(bomb_loc, 0, (t - EARLIEST_TIME),
+ 0, parent(bomb-->0) );
+ Put3D(id_card_loc, 0, (t - EARLIEST_TIME),
+ 0, parent(id_card-->0) );
+ Put3D(equipment_key_loc, 0, (t - EARLIEST_TIME),
+ 0, parent(equipment_key-->0) );
+ Put3D(deutsch_key_loc, 0, (t - EARLIEST_TIME),
+ 0, parent(deutsch_key-->0) );
+ Put3D(flashlight_loc, 0, (t - EARLIEST_TIME),
+ 0, parent(flashlight-->0) );
+ Put3D(battery_loc, 0, (t - EARLIEST_TIME),
+ 0, parent(battery-->0) );
+ Put3D(cable_loc, 0, (t - EARLIEST_TIME),
+ 0, parent(cable-->0) );
+ Put3D(crowbar_loc, 0, (t - EARLIEST_TIME),
+ 0, parent(crowbar-->0) );
+ Put3D(notes_loc, 0, (t - EARLIEST_TIME),
+ 0, parent(notes-->0) );
+ }
+ for (t = EARLIEST_TIME : t < start_time : t++) {
+ Put2D(player_loc, 0, (t - EARLIEST_TIME), limbo);
+ }
+ Put2D(player_loc, 0, start_time - EARLIEST_TIME, foyer);
+
+ for (t = EARLIEST_TIME : t <= start_time : t++) {
+ for (s=0 : s < MAX_TIME_TRAVELS : s++) {
+ Put2D(dangerous_activity, s, (t - EARLIEST_TIME), NONE_);
+ Put2D(activity_target, s, (t - EARLIEST_TIME), nothing);
+ Put2D(siren_state, s, (t - EARLIEST_TIME), false);
+ Put2D(panel_setting, s, (t - EARLIEST_TIME), 0);
+ Put2D(basement_equipment_light, s, (t - EARLIEST_TIME), false);
+ Put2D(ground_equipment_light, s, (t - EARLIEST_TIME), false);
+ Put2D(main_doors_state, s, (t - EARLIEST_TIME), LOCKED_);
+ Put2D(basement_door_state, s, (t - EARLIEST_TIME), LOCKED_);
+ Put2D(ground_door_state, s, (t - EARLIEST_TIME), LOCKED_);
+ Put2D(upstairs_door_state, s, (t - EARLIEST_TIME), LOCKED_);
+ Put2D(balcony_door_state, s, (t - EARLIEST_TIME), CLOSED_);
+ Put2D(conference_window_state, s, (t - EARLIEST_TIME), LOCKED_);
+ Put2D(deutsch_door_state, s, (t - EARLIEST_TIME), LOCKED_);
+ Put2D(basement_equipment_door_state, s, (t - EARLIEST_TIME), LOCKED_);
+ Put2D(ground_equipment_door_state, s, (t - EARLIEST_TIME), LOCKED_);
+
+ Put2D(main_doors_smashed, s, (t - EARLIEST_TIME), false);
+ Put2D(basement_door_smashed, s, (t - EARLIEST_TIME), false);
+ Put2D(ground_door_smashed, s, (t - EARLIEST_TIME), false);
+ Put2D(upstairs_door_smashed, s, (t - EARLIEST_TIME), false);
+ Put2D(balcony_door_smashed, s, (t - EARLIEST_TIME), false);
+
+ for (i=0 : i < MAX_ITEM_COPIES : i++) {
+ Put3D(flashlight_state, 0, (t - EARLIEST_TIME),
+ i, false );
+ Put3D(bomb_setting, 0, (t - EARLIEST_TIME),
+ i, NA_ );
+ }
+ }
+ }
+
+ for (t = start_time+1 : t <= FINAL_TIME : t++) {
+ for (s=0 : s < MAX_TIME_TRAVELS : s++) {
+ Put2D(dangerous_activity, s, (t - EARLIEST_TIME), NONE_);
+ Put2D(activity_target, s, (t - EARLIEST_TIME), nothing);
+ Put2D(siren_state, s, (t - EARLIEST_TIME), UNKNOWN_);
+ Put2D(panel_setting, s, (t - EARLIEST_TIME), UNKNOWN_);
+ Put2D(basement_equipment_light, s, (t - EARLIEST_TIME), UNKNOWN_);
+ Put2D(ground_equipment_light, s, (t - EARLIEST_TIME), UNKNOWN_);
+ Put2D(main_doors_state, s, (t - EARLIEST_TIME), UNKNOWN_);
+ Put2D(basement_door_state, s, (t - EARLIEST_TIME), UNKNOWN_);
+ Put2D(ground_door_state, s, (t - EARLIEST_TIME), UNKNOWN_);
+ Put2D(upstairs_door_state, s, (t - EARLIEST_TIME), UNKNOWN_);
+ Put2D(balcony_door_state, s, (t - EARLIEST_TIME), UNKNOWN_);
+ Put2D(conference_window_state, s, (t - EARLIEST_TIME), UNKNOWN_);
+ Put2D(deutsch_door_state, s, (t - EARLIEST_TIME), UNKNOWN_);
+ Put2D(basement_equipment_door_state, s, (t - EARLIEST_TIME), UNKNOWN_);
+ Put2D(ground_equipment_door_state, s, (t - EARLIEST_TIME), UNKNOWN_);
+
+ Put2D(main_doors_smashed, s, (t - EARLIEST_TIME), UNKNOWN_);
+ Put2D(basement_door_smashed, s, (t - EARLIEST_TIME), UNKNOWN_);
+ Put2D(ground_door_smashed, s, (t - EARLIEST_TIME), UNKNOWN_);
+ Put2D(upstairs_door_smashed, s, (t - EARLIEST_TIME), UNKNOWN_);
+ Put2D(balcony_door_smashed, s, (t - EARLIEST_TIME), UNKNOWN_);
+ }
+ }
+
+];
+
+!! Update the time, remove the old objects that don't travel,
+!! create new objects, move them to the appropriate places
+
+[TravelThroughTime time_amount t s i j;
+
+ last_travel_time = my_time;
+
+ time_amount = time_amount / 5; ! round down to nearest five seconds
+ if (time_amount == 0)
+ time_amount = 1;
+
+ my_time = my_time - time_amount;
+
+ if (my_time < early_guard_time) {
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print (Nearby) 0, "the guard gives the inside corridors a last look before
+ heading out. A small sound from the Deutsch lab. He turns.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ return true;
+ }
+
+ !! replace those items the player brought with them
+
+ FixBombSettings(time_amount);
+ FixFlashlightStates();
+
+ for (j=0 : j < Exp(2,time_travelled) : j++) {
+ ReplaceTravellingItem(bomb, j);
+ ReplaceTravellingItem(id_card, j);
+ ReplaceTravellingItem(equipment_key, j);
+ ReplaceTravellingItem(deutsch_key, j);
+ ReplaceTravellingItem(flashlight, j);
+
+ ReplaceTravellingItem(cable, j);
+ ReplaceTravellingItem(crowbar, j);
+ ReplaceTravellingItem(notes, j);
+
+ !! tricky battery issues, since they can be in flashlights
+ !! if other items could be in containers this would hurt here too
+
+ if (PlayerHas(battery-->j)) {
+ if (battery-->j in player)
+ move battery-->(j+Exp(2,time_travelled)) to player;
+ else {
+ for (i=0 : i < Exp(2,time_travelled) : i++)
+ if (battery-->j in (flashlight-->i))
+ move (battery-->(j+Exp(2,time_travelled))) to (flashlight-->(i+Exp(2,time_travelled)));
+ }
+ }
+ else if (LocationOf(battery-->j) == prototype_interior) {
+ if (battery-->j in prototype_interior)
+ move battery-->(j+Exp(2,time_travelled)) to prototype_interior;
+ else
+ for (i=0 : i < Exp(2,time_travelled) : i++)
+ if (battery-->j in flashlight-->i)
+ move battery-->(j+Exp(2,time_travelled)) to
+ flashlight-->(i+Exp(2,time_travelled));
+ }
+
+ }
+
+
+ !! move all the old items and selves into limbo
+
+ for (t=0 : t < Exp(2,time_travelled) : t++) {
+ move bomb-->t to limbo;
+ move id_card-->t to limbo;
+ move equipment_key-->t to limbo;
+ move deutsch_key-->t to limbo;
+ move flashlight-->t to limbo;
+ move battery-->t to limbo;
+ move cable-->t to limbo;
+ move crowbar-->t to limbo;
+ move notes-->t to limbo;
+ }
+
+ for (t=0 : t < time_travelled : t++)
+ move former_self-->t to limbo;
+
+
+ !! fix up history of immediate past self so 'player' becomes appropriate former self
+
+ for (s = EARLIEST_TIME : s <= FINAL_TIME : s++) {
+ for (t=0 : t < Exp(2,time_travelled) : t++) {
+ if (Get3D(bomb_loc, time_travelled, (s - EARLIEST_TIME), t) == player)
+ Put3D(bomb_loc, time_travelled, (s - EARLIEST_TIME), t,
+ former_self-->time_travelled);
+ if (Get3D(id_card_loc, time_travelled, (s - EARLIEST_TIME), t) == player)
+ Put3D(id_card_loc, time_travelled, (s - EARLIEST_TIME), t,
+ former_self-->time_travelled);
+ if (Get3D(equipment_key_loc, time_travelled, (s - EARLIEST_TIME), t) == player)
+ Put3D(equipment_key_loc, time_travelled, (s - EARLIEST_TIME), t,
+ former_self-->time_travelled);
+ if (Get3D(deutsch_key_loc, time_travelled, (s - EARLIEST_TIME), t) == player)
+ Put3D(deutsch_key_loc, time_travelled, (s - EARLIEST_TIME), t,
+ former_self-->time_travelled);
+ if (Get3D(flashlight_loc, time_travelled, (s - EARLIEST_TIME), t) == player)
+ Put3D(flashlight_loc, time_travelled, (s - EARLIEST_TIME), t,
+ former_self-->time_travelled);
+ if (Get3D(battery_loc, time_travelled, (s - EARLIEST_TIME), t) == player)
+ Put3D(battery_loc, time_travelled, (s - EARLIEST_TIME), t,
+ former_self-->time_travelled);
+ if (Get3D(cable_loc, time_travelled, (s - EARLIEST_TIME), t) == player)
+ Put3D(cable_loc, time_travelled, (s - EARLIEST_TIME), t,
+ former_self-->time_travelled);
+ if (Get3D(crowbar_loc, time_travelled, (s - EARLIEST_TIME), t) == player)
+ Put3D(crowbar_loc, time_travelled, (s - EARLIEST_TIME), t,
+ former_self-->time_travelled);
+ if (Get3D(notes_loc, time_travelled, (s - EARLIEST_TIME), t) == player)
+ Put3D(notes_loc, time_travelled, (s - EARLIEST_TIME), t,
+ former_self-->time_travelled);
+ }
+ }
+
+ !! recreate the world as it was for most recent former self
+ !! (ie move a lot of old items and selves back to the world)
+ !! (fix states of doors and machine)
+
+ for (i=0 : i < Exp(2,time_travelled) : i++) {
+ move bomb-->i to Get3D(bomb_loc,time_travelled,my_time-EARLIEST_TIME,i);
+ move id_card-->i to Get3D(id_card_loc,time_travelled,my_time-EARLIEST_TIME,i);
+ move equipment_key-->i to Get3D(equipment_key_loc,time_travelled,my_time-EARLIEST_TIME,i);
+ move deutsch_key-->i to Get3D(deutsch_key_loc,time_travelled,my_time-EARLIEST_TIME,i);
+ move flashlight-->i to Get3D(flashlight_loc,time_travelled,my_time-EARLIEST_TIME,i);
+ move battery-->i to Get3D(battery_loc,time_travelled,my_time-EARLIEST_TIME,i);
+ move cable-->i to Get3D(cable_loc,time_travelled,my_time-EARLIEST_TIME,i);
+ move crowbar-->i to Get3D(crowbar_loc,time_travelled,my_time-EARLIEST_TIME,i);
+ move notes-->i to Get3D(notes_loc,time_travelled,my_time-EARLIEST_TIME,i);
+ }
+ for (t=0 : t <= time_travelled : t++) {
+ if (Get2D(player_loc,t,my_time-EARLIEST_TIME) == nothing)
+ move former_self-->t to limbo;
+ else
+ move former_self-->t to Get2D(player_loc,t,my_time-EARLIEST_TIME);
+ }
+
+ if (my_time < prototype_fixed_time)
+ prototype.fixed = false;
+
+ SetBombs();
+ SetFlashlights();
+ SetPanel(panel_setting);
+ SetBasementLight(basement_equipment_light);
+ SetGroundLight(ground_equipment_light);
+ SetAutomaticDoor(main_doors, main_doors_state);
+ SetAutomaticDoor(basement_door, basement_door_state);
+ SetAutomaticDoor(ground_door, ground_door_state);
+ SetAutomaticDoor(upstairs_door, upstairs_door_state);
+ SetManualDoor(balcony_door, balcony_door_state);
+ SetManualDoor(conference_window, conference_window_state);
+ SetManualDoor(deutsch_door, deutsch_door_state);
+ SetManualDoor(basement_equipment_door, basement_equipment_door_state);
+ SetManualDoor(ground_equipment_door, ground_equipment_door_state);
+
+ SetBrokenDoor(main_doors, main_doors_smashed);
+ SetBrokenDoor(basement_door, basement_door_smashed);
+ SetBrokenDoor(ground_door, ground_door_smashed);
+ SetBrokenDoor(upstairs_door, upstairs_door_smashed);
+ SetBrokenDoor(balcony_door, balcony_door_smashed);
+
+ !! initialise the history for the new self from the most recent self
+
+ for (t = EARLIEST_TIME : t <= FINAL_TIME : t++) {
+ for (i=0 : i < MAX_ITEM_COPIES : i++) {
+ Put3D(bomb_loc, time_travelled+1, (t - EARLIEST_TIME), i,
+ Get3D(bomb_loc, time_travelled, (t - EARLIEST_TIME), i));
+ Put3D(id_card_loc, time_travelled+1, (t - EARLIEST_TIME), i,
+ Get3D(id_card_loc, time_travelled, (t - EARLIEST_TIME), i));
+ Put3D(equipment_key_loc, time_travelled+1, (t - EARLIEST_TIME), i,
+ Get3D(equipment_key_loc, time_travelled, (t - EARLIEST_TIME), i));
+ Put3D(deutsch_key_loc, time_travelled+1, (t - EARLIEST_TIME), i,
+ Get3D(deutsch_key_loc, time_travelled, (t - EARLIEST_TIME), i));
+ Put3D(flashlight_loc, time_travelled+1, (t - EARLIEST_TIME), i,
+ Get3D(flashlight_loc, time_travelled, (t - EARLIEST_TIME), i));
+ Put3D(battery_loc, time_travelled+1, (t - EARLIEST_TIME), i,
+ Get3D(battery_loc, time_travelled, (t - EARLIEST_TIME), i));
+ Put3D(cable_loc, time_travelled+1, (t - EARLIEST_TIME), i,
+ Get3D(cable_loc, time_travelled, (t - EARLIEST_TIME), i));
+ Put3D(crowbar_loc, time_travelled+1, (t - EARLIEST_TIME), i,
+ Get3D(crowbar_loc, time_travelled, (t - EARLIEST_TIME), i));
+ Put3D(notes_loc, time_travelled+1, (t - EARLIEST_TIME), i,
+ Get3D(notes_loc, time_travelled, (t - EARLIEST_TIME), i));
+
+ Put3D(bomb_setting, time_travelled+1, (t - EARLIEST_TIME), i,
+ Get3D(bomb_setting, time_travelled, (t - EARLIEST_TIME), i));
+ Put3D(flashlight_state, time_travelled+1, (t - EARLIEST_TIME), i,
+ Get3D(flashlight_state, time_travelled, (t - EARLIEST_TIME), i));
+ }
+ Put2D(dangerous_activity, time_travelled+1, (t - EARLIEST_TIME),
+ Get2D(dangerous_activity, time_travelled, (t - EARLIEST_TIME)));
+ Put2D(activity_target, time_travelled+1, (t - EARLIEST_TIME),
+ Get2D(activity_target, time_travelled, (t - EARLIEST_TIME)));
+ Put2D(siren_state, time_travelled+1, (t - EARLIEST_TIME),
+ Get2D(siren_state, time_travelled, (t - EARLIEST_TIME)));
+ Put2D(panel_setting, time_travelled+1, (t - EARLIEST_TIME),
+ Get2D(panel_setting, time_travelled, (t - EARLIEST_TIME)));
+ Put2D(basement_equipment_light, time_travelled+1, (t - EARLIEST_TIME),
+ Get2D(basement_equipment_light, time_travelled, (t - EARLIEST_TIME)));
+ Put2D(ground_equipment_light, time_travelled+1, (t - EARLIEST_TIME),
+ Get2D(ground_equipment_light, time_travelled, (t - EARLIEST_TIME)));
+ Put2D(main_doors_state, time_travelled+1, (t - EARLIEST_TIME),
+ Get2D(main_doors_state, time_travelled, (t - EARLIEST_TIME)));
+ Put2D(basement_door_state, time_travelled+1, (t - EARLIEST_TIME),
+ Get2D(basement_door_state, time_travelled, (t - EARLIEST_TIME)));
+ Put2D(ground_door_state, time_travelled+1, (t - EARLIEST_TIME),
+ Get2D(ground_door_state, time_travelled, (t - EARLIEST_TIME)));
+ Put2D(upstairs_door_state, time_travelled+1, (t - EARLIEST_TIME),
+ Get2D(upstairs_door_state, time_travelled, (t - EARLIEST_TIME)));
+ Put2D(balcony_door_state, time_travelled+1, (t - EARLIEST_TIME),
+ Get2D(balcony_door_state, time_travelled, (t - EARLIEST_TIME)));
+ Put2D(conference_window_state, time_travelled+1, (t - EARLIEST_TIME),
+ Get2D(conference_window_state, time_travelled, (t - EARLIEST_TIME)));
+ Put2D(deutsch_door_state, time_travelled+1, (t - EARLIEST_TIME),
+ Get2D(deutsch_door_state, time_travelled, (t - EARLIEST_TIME)));
+ Put2D(basement_equipment_door_state, time_travelled+1, (t - EARLIEST_TIME),
+ Get2D(basement_equipment_door_state, time_travelled, (t - EARLIEST_TIME)));
+ Put2D(ground_equipment_door_state, time_travelled+1, (t - EARLIEST_TIME),
+ Get2D(ground_equipment_door_state, time_travelled, (t - EARLIEST_TIME)));
+
+ Put2D(main_doors_smashed, time_travelled+1, (t - EARLIEST_TIME),
+ Get2D(main_doors_smashed, time_travelled, (t - EARLIEST_TIME)));
+ Put2D(basement_door_smashed, time_travelled+1, (t - EARLIEST_TIME),
+ Get2D(basement_door_smashed, time_travelled, (t - EARLIEST_TIME)));
+ Put2D(ground_door_smashed, time_travelled+1, (t - EARLIEST_TIME),
+ Get2D(ground_door_smashed, time_travelled, (t - EARLIEST_TIME)));
+ Put2D(upstairs_door_smashed, time_travelled+1, (t - EARLIEST_TIME),
+ Get2D(upstairs_door_smashed, time_travelled, (t - EARLIEST_TIME)));
+ Put2D(balcony_door_smashed, time_travelled+1, (t - EARLIEST_TIME),
+ Get2D(balcony_door_smashed, time_travelled, (t - EARLIEST_TIME)));
+ }
+
+ time_travelled++;
+
+ return true;
+];
+
+[ReplaceTravellingItem thing_type i;
+ if (PlayerHas(thing_type-->i))
+ move thing_type-->(i+Exp(2,time_travelled)) to player;
+ else if (LocationOf(thing_type-->i) == prototype_interior)
+ move thing_type-->(i+Exp(2,time_travelled)) to prototype_interior;
+];
+
+
+[FixBombSettings time_amount i;
+ for (i=0 : i < Exp(2,time_travelled) : i++) {
+ if (PlayerHas(bomb-->i) || (LocationOf(bomb-->i) == prototype_interior))
+ if ((bomb-->i).time_value ~= NA_)
+ (bomb-->(i+Exp(2,time_travelled))).time_value
+ = (bomb-->i).time_value - time_amount;
+ (bomb-->i).time_value = NA_;
+ }
+];
+
+[FixFlashlightStates i;
+ for (i=0 : i < Exp(2,time_travelled) : i++) {
+ if (PlayerHas(flashlight-->i) || (LocationOf(flashlight-->i) == prototype_interior)) {
+ if (flashlight-->i has on)
+ give flashlight-->(i+Exp(2,time_travelled)) on;
+ else
+ give flashlight-->(i+Exp(2,time_travelled)) ~on;
+ }
+ give flashlight-->i ~on;
+ }
+];
+
+
+!----------------------------------------------------
+!
+! Little utility functions:
+
+
+[IsOfType thing thing_type i;
+ for (i=0 : i < MAX_ITEM_COPIES : i++)
+ if (thing_type-->i == thing)
+ return true;
+ return false;
+];
+
+[AmHolding thing_type i;
+ for (i=0 : i < MAX_ITEM_COPIES : i++)
+ if (thing_type-->i ~= nothing && thing_type-->i in player)
+ return true;
+ return false;
+];
+
+[GetHeld thing_type i;
+ for (i=0 : i < MAX_ITEM_COPIES : i++)
+ if (thing_type-->i ~= nothing && thing_type-->i in player)
+ return thing_type-->i;
+ return false;
+];
+
+[IsIn thing_type loc i;
+ for (i=0 : i < MAX_ITEM_COPIES : i++)
+ if (thing_type-->i ~= nothing && thing_type-->i in loc)
+ return true;
+ return false;
+];
+
+[GetFrom thing_type loc i;
+ for (i=0 : i < MAX_ITEM_COPIES : i++)
+ if (thing_type-->i ~= nothing && thing_type-->i in loc)
+ return thing_type-->i;
+ return false;
+];
+
+![Present thing_type t;
+! for (t=0 : t < MAX_ITEM_COPIES : t++)
+! if (thing_type-->t ~= nothing && thing_type-->t in real_location)
+! return true;
+! return false;
+!];
+
+![GetPresent thing_type t;
+! for (t=0 : t < MAX_ITEM_COPIES : t++)
+! if (thing_type-->t ~= nothing && thing_type-->t in real_location)
+! return thing_type-->t;
+! return false;
+!];
+
+[BatteriesContained thing batteries i;
+ batteries = 0;
+ for (i=0 : i < MAX_ITEM_COPIES : i++)
+ if (battery-->i ~= nothing && battery-->i in thing)
+ batteries++;
+ return batteries;
+];
+
+[StartSiren;
+ if (siren_start_time == UNKNOWN_ || siren_start_time > my_time)
+ siren_start_time = my_time;
+];
+
+[MoveMoveableChildren old_loc new_loc x y;
+ while (child(old_loc)) {
+ x = nothing;
+ y = child(old_loc);
+ if ((y hasnt static) && (y ~= player)) {
+ x = y;
+ }
+ while (sibling(y)) {
+ y = sibling(y);
+ if ((y hasnt static) && (y ~= player)) {
+ x = y;
+ }
+ }
+ if (x ~= nothing) {
+ move x to new_loc;
+ }
+ else
+ break;
+ }
+];
+
+[ LocationOf x;
+ if (parent(x) == 0)
+ return x;
+ else
+ return LocationOf(parent(x));
+];
+
+[ PlayerHas x;
+ if (parent(x) == 0)
+ return false;
+ if (parent(x) == player)
+ return true;
+ return PlayerHas(parent(x));
+];
+
+[ Flashlit i;
+ for (i=0 : i < MAX_ITEM_COPIES : i++) {
+ if (flashlight-->i ~= nothing && (flashlight-->i in player or real_location)
+ && flashlight-->i has on)
+ return true;
+ }
+ return false;
+];
+
+[PrintTime t;
+ if (t == NA_)
+ return true;
+
+ print (t/720), ":", ((t/12)%60)/10, (t/12)%10, ":", ((t%12)/2);
+ if ((t%2) == 0)
+ print "0";
+ else
+ print "5";
+
+ if (t/(720*12) == 0)
+ print " am";
+ else
+ print " pm";
+];
+
+[PrintShortTime t;
+ print (t/720), ":", ((t/12)%60)/10, (t/12)%10;
+
+ if (t/(720*12) == 0)
+ print " am";
+ else
+ print " pm";
+];
+
+[IncTime;
+ InformLibrary.end_turn_sequence();
+];
+
+!! x == run_through, y == time_index
+
+[Put2D array x y thing;
+ array-->((x * (GAME_LENGTH+1)) + y) = thing;
+];
+
+!! x == run_through, y == time_index
+
+[Get2D array x y;
+ return array-->((x * (GAME_LENGTH+1)) + y);
+];
+
+!! x == run_through, y == time_index, z == thing_number
+
+[Put3D array x y z thing;
+ array-->( (z*(MAX_TIME_TRAVELS+1) + x)*(GAME_LENGTH+1) + y ) = thing;
+];
+
+!! x == run_through, y == time_index, z == thing_number
+
+[Get3D array x y z;
+ return array-->( (z*(MAX_TIME_TRAVELS+1) + x)*(GAME_LENGTH+1) + y );
+];
+
+[Exp b e i result;
+ result = 1;
+ for (i=0 : i<e : i++)
+ result = result * b;
+ return result;
+];
+
+!----------------------------------------------------
+!
+! 'Observe' functions: (these make note of current state of things)
+
+
+[ObserveBombs i;
+ for (i=0 : i < MAX_ITEM_COPIES : i++) {
+ Put3D(bomb_setting, time_travelled, (my_time - EARLIEST_TIME), i, (bomb-->i).time_value);
+ }
+];
+
+[ObserveFlashlights i;
+ for (i=0 : i < MAX_ITEM_COPIES : i++) {
+ Put3D(flashlight_state, time_travelled, (my_time - EARLIEST_TIME), i, flashlight-->i has on);
+ }
+];
+
+[ObserveSiren siren_on;
+ siren_on = (siren_start_time ~= UNKNOWN_) && (siren_start_time < my_time);
+ Put2D(siren_state, time_travelled, my_time - EARLIEST_TIME, siren_on);
+];
+
+[ObservePanel;
+ Put2D(panel_setting, time_travelled, my_time - EARLIEST_TIME, control_panel.time_value);
+];
+
+[ObserveGroundLight light_array;
+ Put2D(light_array, time_travelled, my_time - EARLIEST_TIME, ground_equipment.lit);
+];
+
+[ObserveBasementLight light_array;
+ Put2D(light_array, time_travelled, my_time - EARLIEST_TIME, basement_light_switch.blown);
+];
+
+[ObserveBrokenDoor door door_smashed;
+ Put2D(door_smashed, time_travelled, my_time - EARLIEST_TIME, door.smashed);
+];
+
+[ObserveManualDoor door door_state door_status;
+ if (door has locked)
+ door_status = LOCKED_;
+ else {
+ if (door has open)
+ door_status = OPEN_;
+ else
+ door_status = CLOSED_;
+ }
+ Put2D(door_state, time_travelled, my_time - EARLIEST_TIME, door_status);
+];
+
+[ObserveAutomaticDoor door door_state door_status;
+ if (door has locked)
+ door_status = 0;
+ else
+ door_status = door.to_close_at;
+ Put2D(door_state, time_travelled, my_time - EARLIEST_TIME, door_status);
+];
+
+[ObserveLocations i;
+ Put2D(player_loc, time_travelled, (my_time - EARLIEST_TIME), parent(player));
+ for (i=0 : i < MAX_ITEM_COPIES : i++) {
+ Put3D(bomb_loc, time_travelled, (my_time - EARLIEST_TIME),
+ i, parent(bomb-->i) );
+ Put3D(id_card_loc, time_travelled, (my_time - EARLIEST_TIME),
+ i, parent(id_card-->i) );
+ Put3D(equipment_key_loc, time_travelled, (my_time - EARLIEST_TIME),
+ i, parent(equipment_key-->i) );
+ Put3D(deutsch_key_loc, time_travelled, (my_time - EARLIEST_TIME),
+ i, parent(deutsch_key-->i) );
+ Put3D(flashlight_loc, time_travelled, (my_time - EARLIEST_TIME),
+ i, parent(flashlight-->i) );
+ Put3D(battery_loc, time_travelled, (my_time - EARLIEST_TIME),
+ i, parent(battery-->i) );
+ Put3D(cable_loc, time_travelled, (my_time - EARLIEST_TIME),
+ i, parent(cable-->i) );
+ Put3D(crowbar_loc, time_travelled, (my_time - EARLIEST_TIME),
+ i, parent(crowbar-->i) );
+ Put3D(notes_loc, time_travelled, (my_time - EARLIEST_TIME),
+ i, parent(notes-->i) );
+ }
+];
+
+!----------------------------------------------------
+!
+! 'Set' functions: (these take care of certain former actions every turn)
+
+
+[SetBombs setting_now i;
+ for (i=0 : i < Exp(2,time_travelled) : i++) {
+ setting_now = Get3D(bomb_setting,time_travelled,my_time-EARLIEST_TIME,i);
+ (bomb-->i).time_value = setting_now;
+ }
+];
+
+[SetFlashlights setting_now i;
+ for (i=0 : i < Exp(2,time_travelled) : i++) {
+ setting_now = Get3D(flashlight_state,time_travelled,my_time-EARLIEST_TIME,i);
+ if (setting_now == true)
+ give flashlight-->i on;
+ else
+ give flashlight-->i ~on;
+ }
+];
+
+[SetPanel setting_array setting_now;
+ setting_now = Get2D(setting_array, time_travelled, my_time - EARLIEST_TIME);
+ control_panel.time_value = setting_now;
+];
+
+[SetBasementLight setting_array setting_now;
+ setting_now = Get2D(setting_array, time_travelled, my_time - EARLIEST_TIME);
+ basement_light_switch.blown = setting_now;
+];
+
+[SetGroundLight setting_array setting_now;
+ setting_now = Get2D(setting_array, time_travelled, my_time - EARLIEST_TIME);
+ ground_equipment.lit = setting_now;
+ if (setting_now)
+ give ground_light_switch on;
+ else
+ give ground_light_switch ~on;
+];
+
+[SetManualDoor door door_state door_status;
+ door_status = Get2D(door_state, time_travelled, my_time - EARLIEST_TIME);
+ if (door_status == LOCKED_) {
+ give door ~open;
+ give door locked;
+ }
+ if (door_status == CLOSED_) {
+ give door ~open;
+ give door ~locked;
+ }
+ if (door_status == OPEN_) {
+ give door open;
+ give door ~locked;
+ }
+ if (door_status == UNKNOWN_) {
+ print "Error: unknown door status needing to be set for some reason.";
+ }
+];
+
+[SetAutomaticDoor door door_state door_status;
+ door_status = Get2D(door_state, time_travelled, my_time - EARLIEST_TIME);
+ if (door_status == UNKNOWN_) {
+ give door ~open locked;
+ }
+ if (door_status > 0) {
+ give door open ~locked;
+ door.to_close_at = door_status;
+ }
+];
+
+[SetBrokenDoor door door_smashed door_status;
+ door_status = Get2D(door_smashed, time_travelled, my_time - EARLIEST_TIME);
+ if (door_status == UNKNOWN_) {
+ door.smashed = false;
+ }
+ if (door_status == true) {
+ door.smashed = true;
+ }
+ if (door_status == false) {
+ door.smashed = false;
+ }
+];
+
+[MoveFormerSelf run_through loc_next;
+ loc_next = Get2D(player_loc, run_through, my_time - EARLIEST_TIME);
+
+ if (~~d_paradox) {
+ if (d_destroyed_prototype && ((former_self-->run_through) in limbo) &&
+ (loc_next == prototype_interior)) {
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print (PrintTime) (my_time), "^^";
+ print "Back in the Deutsch lab, the debris from the prototype
+ lies smoldering on the floor and no past self appears.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+ else if (d_destroyed_prototype && (my_time == start_time)) {
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print (PrintTime) (my_time), "^^";
+ print "Elsewhere, your past self enters the foyer and smells the
+ bitter smoke from a recent explosion.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+ else {
+ if (loc_next == nothing)
+ move former_self-->run_through to limbo;
+ else
+ move former_self-->run_through to loc_next;
+ }
+
+! if ((~~d_paradox) && (~~d_escaped) && (~~d_caught))
+! print "<<< former self (", run_through, ") is in: ", (name) loc_next, " >>>^";
+ }
+];
+
+!! Moves an object around according to the actions of former selves
+!! Uses the item histories to work out when an item was moved, but since
+!! that copy of the item may have been swapped for another (which is fine)
+!! we must get the first available copy in the right location to be safe.
+!! Also, we don't want to remove all normal objects when someone time-travels
+!! so, since this only happens when the player is not present and no other moving
+!! happens when the player is not present, we can get around it by only moving
+!! objects when a former self is present in the same location.
+
+[MoveObject thing_type thing_loc i loc_now loc_next;
+ loc_now = Get3D(thing_loc,time_travelled-1,my_time-EARLIEST_TIME-1,i);
+ loc_next = Get3D(thing_loc,time_travelled-1,my_time-EARLIEST_TIME,i);
+ if (loc_now ~= loc_next) {
+ if (IsIn(thing_type, loc_now)) {
+ if (IsIn(former_self,LocationOf(GetFrom(thing_type, loc_now)))) {
+! print "<<< Moving ", (name) thing_type-->i, " (", i, ") in ", (name) loc_now,
+! " to ", (name) loc_next, " >>>^";
+ move GetFrom(thing_type, loc_now) to loc_next;
+ }
+ else {
+ !! handle the odd case of object left in prototype when button pressed
+ if (LocationOf(GetFrom(thing_type, loc_now)) == prototype_interior) {
+! print "<<< Moving ", (name) thing_type-->i, " (", i, ") in ", (name) loc_now,
+! " to ", (name) loc_next, " >>>^";
+ move GetFrom(thing_type, loc_now) to loc_next;
+ }
+ else if ((loc_now == basement_equipment_gloom) || (loc_now == ground_equipment_gloom)) {
+! print "<<< Moving ", (name) thing_type-->i, " (", i, ") in ", (name) loc_now,
+! " to ", (name) loc_next, " >>>^";
+ move GetFrom(thing_type, loc_now) to loc_next;
+ }
+! else {
+! print "<<< Ignoring ", (name) thing_type-->0, " in ", (name) loc_now,
+! " (wanted to move it to ", (name) loc_next, ") >>>^";
+! }
+ }
+ }
+! else
+! print "<<< Missing ", (name) thing_type-->0, " in ", (name) loc_now,
+! " (wanted to move it to ", (name) loc_next, ") >>>^";
+ }
+];
+
+!----------------------------------------------------
+!
+! 'Maybe' functions: (these take care of former actions)
+
+
+[MaybeExplodeBombs i;
+ for (i=0 : i < MAX_ITEM_COPIES : i++)
+ if (bomb-->i ~= nothing) {
+ if (LocationOf(bomb-->i) ~= limbo) {
+ if (((bomb-->i).time_value == my_time - 1) &&
+ ((bomb-->i).left_over_seconds == 0))
+ ExplodeBomb(i);
+ else if (((bomb-->i).time_value == my_time - 2) &&
+ ((bomb-->i).left_over_seconds ~=0))
+ ExplodeBomb(i);
+ }
+ }
+];
+
+[MaybeSing;
+ if (Get2D(dangerous_activity, time_travelled-1, my_time-EARLIEST_TIME-1) == SING_)
+ if (player notin limbo)
+ "You hear muffled singing from somewhere in the building.";
+];
+
+[MaybeShout;
+ if (Get2D(dangerous_activity, time_travelled-1, my_time-EARLIEST_TIME-1) == SHOUT_)
+ if (player notin limbo)
+ "You hear muffled shouting from somewhere in the building.";
+];
+
+!!! a little tricky to ensure that when two bombs are in same room that the one set
+!!! has the same original setting as it should (ie is indistinguishable from former one)
+
+[MaybeSetBombs setting_now setting_next loc_now b i j;
+ for (i=0 : i < Exp(2,time_travelled-1) : i++) {
+ setting_now = Get3D(bomb_setting,time_travelled-1,my_time-EARLIEST_TIME-1,i);
+ setting_next = Get3D(bomb_setting,time_travelled-1,my_time-EARLIEST_TIME,i);
+ loc_now = Get3D(bomb_loc,time_travelled-1,my_time-EARLIEST_TIME-1,i);
+ if (setting_now ~= setting_next) {
+ if (IsIn(bomb, loc_now)) {
+ if (IsIn(former_self,LocationOf(GetFrom(bomb, loc_now)))) {
+ for (j=0 : j < MAX_ITEM_COPIES : j++)
+ if ((bomb-->j ~= nothing) && (bomb-->j in loc_now))
+ if ((bomb-->j).time_value == setting_now)
+ b = bomb-->j;
+! print "<<< setting bomb (via maybeset) >>>^";
+ if (b ~= nothing)
+ b.time_value = setting_next;
+! else
+! print "<<<Missing bomb of former time setting.>>>^";
+ }
+ }
+! else
+! print "<<<Missing ", (name) bomb-->0, " in ", (name) loc_now,
+! " (wanted to set it to ", setting_next, ")>>>^";
+ }
+ }
+];
+
+!!! a little tricky to ensure that when two flashlights are in same room that the one set
+!!! has the same original setting as it should (ie is indistinguishable from former one)
+
+[MaybeSetFlashlights setting_now setting_next loc_now f i j;
+ for (i=0 : i < Exp(2,time_travelled-1) : i++) {
+ setting_now = Get3D(flashlight_state,time_travelled-1,my_time-EARLIEST_TIME-1,i);
+ setting_next = Get3D(flashlight_state,time_travelled-1,my_time-EARLIEST_TIME,i);
+ loc_now = Get3D(flashlight_loc,time_travelled-1,my_time-EARLIEST_TIME-1,i);
+ if (setting_now ~= setting_next) {
+ if (IsIn(flashlight, loc_now)) {
+ if (IsIn(former_self,LocationOf(GetFrom(flashlight, loc_now)))) {
+ for (j=0 : j < MAX_ITEM_COPIES : j++)
+ if ((flashlight-->j ~= nothing) && (flashlight-->j in loc_now))
+ if ((flashlight-->j has on) == setting_now)
+ f = flashlight-->j;
+! print "<<< setting flashlight (via maybeset) >>>^";
+ if (f ~= nothing) {
+ if (setting_next == true)
+ give f on;
+ else
+ give f ~on;
+ }
+! else
+! print "<<<Missing flashlight of former time setting.>>>^";
+ }
+ }
+! else
+! print "<<<Missing ", (name) flashlight-->0, " in ", (name) loc_now,
+! " (wanted to set it to ", setting_next, ")>>>^";
+ }
+ }
+];
+
+[MaybeSetPanel setting_array setting_now setting_next;
+ setting_now = Get2D(setting_array, time_travelled - 1, my_time - EARLIEST_TIME - 1);
+ setting_next = Get2D(setting_array, time_travelled - 1, my_time - EARLIEST_TIME);
+ if (setting_next ~= UNKNOWN_ && setting_next ~= setting_now) {
+ control_panel.time_value = setting_next;
+ }
+];
+
+[MaybeSetBasementLight setting_array setting_now setting_next;
+ setting_now = Get2D(setting_array, time_travelled - 1, my_time - EARLIEST_TIME - 1);
+ setting_next = Get2D(setting_array, time_travelled - 1, my_time - EARLIEST_TIME);
+ if (setting_next ~= UNKNOWN_ && setting_next ~= setting_now) {
+ basement_light_switch.blown = setting_next;
+ }
+];
+
+[MaybeSetGroundLight setting_array setting_now setting_next;
+ setting_now = Get2D(setting_array, time_travelled - 1, my_time - EARLIEST_TIME - 1);
+ setting_next = Get2D(setting_array, time_travelled - 1, my_time - EARLIEST_TIME);
+ if (setting_next ~= UNKNOWN_ && setting_next ~= setting_now) {
+ ground_equipment.lit = setting_next;
+ if (setting_next)
+ give ground_light_switch on;
+ else
+ give ground_light_switch ~on;
+ }
+];
+
+[MaybeCloseAutomaticDoor door;
+ if (door.just_closed)
+ door.just_closed = false;
+ if (~~deadflag)
+ if (door.to_close_at == my_time - 1)
+ door.close_self();
+];
+
+!! Opens/closes/locks/unlocks doors for the past self and catches paradoxes that could not
+!! be seen, but where the locked/unlocked state of the door differs and interferes with the action.
+!! Also works when the former self unlocks an unlocked door or locks
+!! a locked door, but this door had the converse state and the key actually turns.
+
+[MaybeSetManualDoor door door_state past_door_status_now past_door_status_next
+ present_door_status_now the_action t;
+
+ for (t=0 : t<time_travelled : t++) {
+
+ past_door_status_now = Get2D(door_state, t, my_time - EARLIEST_TIME - 1);
+ past_door_status_next = Get2D(door_state, t, my_time - EARLIEST_TIME);
+
+ present_door_status_now = Get2D(door_state, time_travelled, my_time - EARLIEST_TIME - 1);
+
+ the_action = Get2D(dangerous_activity, t, my_time - EARLIEST_TIME - 1);
+
+!-- if there was a locking/unlocking, check for paradox:
+ if (Get2D(activity_target, t, my_time - EARLIEST_TIME - 1) == door) {
+ if (the_action == UNLOCK_) {
+ if ((present_door_status_now == CLOSED_) && (past_door_status_now == LOCKED_)) {
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print (Nearby) 0, "your past self attempts to unlock ", (the) door,
+ " but finds it already unlocked.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+ else if ((present_door_status_now == LOCKED_) && (past_door_status_now == CLOSED_)) {
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print (Nearby) 0, "your past self foolishly attempts to unlock ", (the) door,
+ " and succeeds where you had originally found it already unlocked.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+ }
+ if (the_action == LOCK_) {
+ if ((present_door_status_now == CLOSED_) && (past_door_status_now == LOCKED_)) {
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print (Nearby) 0, "your past self foolishly attempts to lock ", (the) door,
+ " and succeeds where you had originally found it already locked.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+ if ((present_door_status_now == LOCKED_) && (past_door_status_now == CLOSED_)) {
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print (Nearby) 0, "your past self attempts to lock ", (the) door,
+ " but finds it already locked.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+ }
+ if (the_action == OPEN_) {
+ if ((present_door_status_now == CLOSED_) && (past_door_status_now == LOCKED_)) {
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print (Nearby) 0, "your past self foolishly attempts to open ", (the) door,
+ " and succeeds where you had originally found it locked.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+ if ((present_door_status_now == LOCKED_) && (past_door_status_now == CLOSED_)) {
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print (Nearby) 0, "your past self attempts to open ", (the) door,
+ " but finds it locked.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+ }
+ }
+
+!-- if there should be a state change, do it:
+ if (~~d_paradox) {
+ if ((past_door_status_now ~= past_door_status_next) && (past_door_status_next ~= UNKNOWN_)) {
+ if (past_door_status_now == present_door_status_now) {
+ if (past_door_status_next == LOCKED_) {
+ give door ~open;
+ give door locked;
+ if (door in real_location)
+ print "You hear someone locking the ", (name) door, ".^";
+ }
+ if (past_door_status_next == CLOSED_) {
+ give door ~open;
+ give door ~locked;
+ if (door in real_location && past_door_status_now == LOCKED_)
+ print "You hear someone unlocking the ", (name) door, ".^";
+ if (door in real_location && past_door_status_now == OPEN_)
+ print "Someone closes ", (name) door, ".^";
+ }
+ if (past_door_status_next == OPEN_) {
+ give door open;
+ give door ~locked;
+ if (door in real_location)
+ print "Someone opens the ", (name) door, ".^";
+ }
+ }
+ }
+ }
+
+ }
+];
+
+[MaybeSetAutomaticDoor door door_state door_status_now door_status_next;
+ door_status_now = Get2D(door_state, time_travelled - 1, my_time - EARLIEST_TIME - 1);
+ door_status_next = Get2D(door_state, time_travelled - 1, my_time - EARLIEST_TIME);
+ if (door_status_next == my_time) {
+ door.open_self(my_time);
+ }
+ if ((door == main_doors) && (my_time == start_time - 1)) {
+ door.open_self(my_time);
+ }
+];
+
+[MaybeBreakDoor door door_smashed door_smashed_next;
+ door_smashed_next = Get2D(door_smashed, time_travelled - 1, my_time - EARLIEST_TIME);
+ if (door_smashed_next && (~~door.smashed)) {
+ door.smashed = true;
+ }
+];
+
+!----------------------------------------------------
+!
+! 'Check' functions: (these check for paradoxes, both active and passive)
+
+
+[CheckActiveParadox t action_de_jour trouble i j k flash_i_batteries flash_j_loc flash_j_batteries
+ past_count present_count too_heavy;
+ action_de_jour = Get2D(dangerous_activity, t, my_time-EARLIEST_TIME-1);
+ trouble = false;
+
+ for (t=0 : t < time_travelled : t++) {
+ if (~~d_paradox) {
+ switch (action_de_jour) {
+ X_CCTV_:
+ if (player in upstairs_corridor or ground_corridor or basement_corridor)
+ trouble = true;
+ X_UPSTAIRS_CORRIDOR_:
+ if (player in upstairs_corridor)
+ trouble = true;
+ X_UPSTAIRS_LANDING_:
+ if (player in upstairs_landing)
+ trouble = true;
+ X_GROUND_CORRIDOR_:
+ if (player in ground_corridor)
+ trouble = true;
+ X_FOYER_:
+ if (player in foyer)
+ trouble = true;
+ X_BASEMENT_CORRIDOR_:
+ if (player in basement_corridor)
+ trouble = true;
+ X_BASEMENT_LANDING_:
+ if (player in basement_landing)
+ trouble = true;
+ X_BALCONY_:
+ if (player in balcony)
+ trouble = true;
+ TAKE_FLASHLIGHT_:
+ for (i=0 : i<MAX_ITEM_COPIES : i++) {
+ if ((flashlight-->i) in (former_self-->t)) {
+ flash_i_batteries = BatteriesContained(flashlight-->i);
+ past_count = 0;
+ present_count = 0;
+ for (j=0 : j < MAX_ITEM_COPIES : j++)
+ if ((flashlight-->j) in (former_self-->t))
+ if (BatteriesContained(flashlight-->j) == flash_i_batteries)
+ present_count++;
+ for (j=0 : j < MAX_ITEM_COPIES : j++) {
+ flash_j_loc = Get3D(flashlight_loc,t,my_time-EARLIEST_TIME,j);
+ flash_j_batteries = 0;
+ for (k=0 : k<MAX_ITEM_COPIES : k++) {
+ if (Get3D(battery_loc,t,my_time-EARLIEST_TIME,k) == (flashlight-->j))
+ flash_j_batteries++;
+ }
+ if (flash_j_loc == former_self-->t)
+ if (flash_j_batteries == flash_i_batteries)
+ past_count++;
+ }
+ if (present_count ~= past_count) {
+ too_heavy = (past_count < present_count);
+ trouble = true;
+ }
+ }
+ }
+ BLOW_BASEMENT_LIGHT_:
+ if (Get2D(basement_equipment_light, time_travelled, my_time-EARLIEST_TIME-1) == true)
+ trouble = true;
+ }
+ if (trouble) {
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ switch (action_de_jour) {
+ X_CCTV_:
+ print "In the foyer, your past self glances at a CCTV screen and sees you in the
+ shadowed corridor.^";
+ X_UPSTAIRS_CORRIDOR_:
+ if (former_self-->t in balcony)
+ print "From the chilly balcony, your former self looks through the glass door
+ and sees you in the shadowed corridor.^";
+ else
+ print "From the upstairs landing, your former self looks through the glass
+ and sees you in the shadowed corridor.^";
+ X_UPSTAIRS_LANDING_:
+ print "From the second floor corridor, your former self looks through the glass door
+ and sees you in the shadowy landing.^";
+ X_GROUND_CORRIDOR_:
+ print "From within the foyer, your former self looks through
+ the glass door and sees you in the shadowed corridor.^";
+ X_FOYER_:
+ if (former_self-->t in upstairs_landing)
+ print "From the landing above, your former self looks down
+ and sees you.^";
+ else
+ print "From the first floor corridor, your former self looks through
+ the glass door and sees you.^";
+ X_BASEMENT_CORRIDOR_:
+ print "From the basement landing, your former self looks through the glass door
+ and sees you in the shadowed corridor.^";
+ X_BASEMENT_LANDING_:
+ print "From the basement corridor, your former self looks through the glass door
+ and sees you in the shadowy landing.^";
+ X_BALCONY_:
+ if (former_self-->t in upstairs_corridor)
+ print "From the second floor corridor, your former self looks through the glass door
+ and sees you on the chilly balcony.^";
+ else
+ print "From within the darkened conference room, your former self looks out
+ and sees you on the chilly balcony.^";
+ TAKE_FLASHLIGHT_:
+ if (too_heavy)
+ print (Nearby) 0, "your past self picks up a flashlight, but finds it
+ strangely heavy.^";
+ else
+ print (Nearby) 0, "your past self picks up a flashlight, but finds it
+ strangely light.^";
+ BLOW_BASEMENT_LIGHT_:
+ print "In the basement equipment room, your past self switches on the light
+ but there is no flicker, for it has already blown.^";
+ }
+ if ((action_de_jour >= X_CCTV_) && (action_de_jour <= X_BALCONY_))
+ print "^This is one of the all time most embarrassing ways
+ to destroy the city of Boston.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+ }
+ }
+];
+
+
+[CheckPassiveParadox t;
+ for (t=0 : t < time_travelled : t++)
+ if (LocationOf(former_self-->t) ~= limbo) {
+ CheckPlayerInRoom(t);
+ CheckStateOfSiren(t);
+
+ CheckStateOfDoors(t);
+
+ CheckStateOfGroundLight(t);
+
+ CheckQuantityInRoom(bomb,bomb_loc,t);
+ CheckQuantityInRoom(id_card,id_card_loc,t);
+ CheckQuantityInRoom(equipment_key,equipment_key_loc,t);
+ CheckQuantityInRoom(deutsch_key,deutsch_key_loc,t);
+ CheckQuantityInRoom(flashlight,flashlight_loc,t);
+ CheckQuantityInRoom(battery,battery_loc,t);
+ CheckQuantityInRoom(cable,cable_loc,t);
+ CheckQuantityInRoom(crowbar,crowbar_loc,t);
+ CheckQuantityInRoom(notes,notes_loc,t);
+
+ CheckStateOfFlashlights(t);
+
+ if (former_self-->t in foyer)
+ CheckObjectsOnDesk(security_desk,t);
+ if (former_self-->t in conference_room) {
+ CheckObjectsOnDesk(conference_table,t);
+ CheckObjectsOnDesk(chair,t);
+ }
+ if (former_self-->t in deutsch_lab)
+ CheckObjectsOnDesk(bench,t);
+ if (former_self-->t in prototype_interior)
+ CheckTimeOnPanel(t);
+
+ CheckTimesOnBombs(t);
+ }
+];
+
+[CheckStateOfDoors t fs_loc;
+ fs_loc = LocationOf(former_self-->t);
+
+ switch (fs_loc) {
+ foyer:
+ CheckStateOfDoor(main_doors, main_doors_state, t, fs_loc);
+ CheckStateOfDoor(ground_door, ground_door_state, t, fs_loc);
+ CheckBrokenDoor(main_doors, main_doors_smashed, t, fs_loc);
+ CheckBrokenDoor(ground_door, ground_door_smashed, t, fs_loc);
+ ground_corridor:
+ CheckStateOfDoor(ground_door, ground_door_state, t, fs_loc);
+ CheckBrokenDoor(ground_door, ground_door_smashed, t, fs_loc);
+ CheckStateOfDoor(ground_equipment_door, ground_equipment_door_state, t, fs_loc);
+ ground_equipment:
+ CheckStateOfDoor(ground_equipment_door, ground_equipment_door_state, t, fs_loc);
+ basement_landing:
+ CheckStateOfDoor(basement_door, basement_door_state, t, fs_loc);
+ CheckBrokenDoor(basement_door, basement_door_smashed, t, fs_loc);
+ basement_corridor:
+ CheckStateOfDoor(basement_door, basement_door_state, t, fs_loc);
+ CheckBrokenDoor(basement_door, basement_door_smashed, t, fs_loc);
+ CheckStateOfDoor(basement_equipment_door, basement_equipment_door_state, t, fs_loc);
+ CheckStateOfDoor(deutsch_door, deutsch_door_state, t, fs_loc);
+ deutsch_lab:
+ CheckStateOfDoor(deutsch_door, deutsch_door_state, t, fs_loc);
+ prototype_interior:
+ CheckStateOfDoor(deutsch_door, deutsch_door_state, t, fs_loc);
+ upstairs_landing:
+ CheckStateOfDoor(upstairs_door, upstairs_door_state, t, fs_loc);
+ CheckBrokenDoor(upstairs_door, upstairs_door_smashed, t, fs_loc);
+ upstairs_corridor:
+ CheckStateOfDoor(upstairs_door, upstairs_door_state, t, fs_loc);
+ CheckStateOfDoor(balcony_door, balcony_door_state, t, fs_loc);
+ CheckBrokenDoor(upstairs_door, upstairs_door_smashed, t, fs_loc);
+ CheckBrokenDoor(balcony_door, balcony_door_smashed, t, fs_loc);
+ balcony:
+ CheckStateOfDoor(balcony_door, balcony_door_state, t, fs_loc);
+ CheckBrokenDoor(balcony_door, balcony_door_smashed, t, fs_loc);
+ CheckStateOfDoor(conference_window, conference_window_state, t, fs_loc);
+ conference_room:
+ CheckStateOfDoor(conference_window, conference_window_state, t, fs_loc);
+ default:
+ return false;
+ }
+];
+
+! this is a tiny bit of a hack, using the fact that OPEN_ is higher than CLOSED_, LOCKED_.
+! and the fact that automatic doors which are open have values higher than OPEN_.
+
+[CheckStateOfDoor door door_state t fs_loc past_door_state fs_loc_last_turn;
+ past_door_state = Get2D(door_state,t,my_time-EARLIEST_TIME);
+ fs_loc_last_turn = Get2D(player_loc,t,my_time-EARLIEST_TIME-1);
+
+ if (~~d_paradox) {
+ if ((past_door_state >= OPEN_) && (door hasnt open)) {
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print (Nearby) 0, "your former self enters ", (TheLower) fs_loc,
+ " and sees ", (the) door, " pulled closed.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+ else if ((past_door_state < OPEN_) && (door has open)) {
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ if (door ~= conference_window) {
+ if (fs_loc_last_turn ~= fs_loc)
+ print (Nearby) 0, "your former self enters ", (TheLower) fs_loc,
+ " and sees ", (the) door, " standing open.^";
+ else
+ print (Nearby) 0, "your former self standing in ", (TheLower) fs_loc,
+ " sees ", (the) door, " open.^";
+ }
+ else
+ print (Nearby) 0, "your former self enters ", (TheLower) fs_loc,
+ " and sees the shattered conference room window.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+ }
+];
+
+
+[CheckBrokenDoor door door_smashed t fs_loc past_door_smashed_now past_door_smashed_next;
+ past_door_smashed_now = Get2D(door_smashed,t,my_time-EARLIEST_TIME-1);
+ past_door_smashed_next = Get2D(door_smashed,t,my_time-EARLIEST_TIME);
+ if (~~d_paradox) {
+ if ((~~past_door_smashed_next) && door.smashed) {
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ if (past_door_smashed_now)
+ print "In ", (TheLower) fs_loc, ", your former self sees the web of cracks in ",
+ (the) door, ".^";
+ else
+ print "In ", (TheLower) fs_loc, ", your former self hears the crack of your
+ crowbar smashing into ",
+ (the) door, ".^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+ }
+
+];
+
+[CheckTimesOnBombs t i j bomb_i_time bomb_j_time bomb_j_loc
+ past_count present_count fs_loc;
+
+ fs_loc = LocationOf(former_self-->t);
+
+ if (~~d_paradox) {
+ for (i=0 : i < MAX_ITEM_COPIES : i++) {
+ if (LocationOf(bomb-->i) == fs_loc) {
+ bomb_i_time = (bomb-->i).time_value;
+ past_count = 0;
+ present_count = 0;
+ for (j=0 : j < MAX_ITEM_COPIES : j++)
+ if (LocationOf(bomb-->j) == fs_loc)
+ if ((bomb-->j).time_value == bomb_i_time)
+ present_count++;
+ for (j=0 : j < MAX_ITEM_COPIES : j++) {
+ bomb_j_loc = Get3D(bomb_loc,t,my_time-EARLIEST_TIME,j);
+ bomb_j_time = Get3D(bomb_setting,t,my_time-EARLIEST_TIME,j);
+ if (((bomb_j_loc == fs_loc) || (parent(bomb_j_loc) == fs_loc)))
+ if (bomb_j_time == bomb_i_time)
+ past_count++;
+ }
+ if (past_count ~= present_count) {
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print (Nearby) 0, "your former self enters ", (TheLower) fs_loc,
+ " and sees a different value flashing on the explosive device's
+ timer.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+ }
+ }
+ }
+
+];
+
+[CheckStateOfFlashlights t i present_flashlights_on past_flashlights_on
+ fs_loc flash_loc flash_state;
+ fs_loc = LocationOf(former_self-->t);
+ if (~~d_paradox) {
+ for (i=0 : i < MAX_ITEM_COPIES : i++) {
+ flash_loc = Get3D(flashlight_loc,t,my_time-EARLIEST_TIME,i);
+ flash_state = Get3D(flashlight_state,t,my_time-EARLIEST_TIME,i);
+ if (flash_state && ((flash_loc == fs_loc) || (parent(flash_loc) == fs_loc)))
+ past_flashlights_on++;
+ if ((flashlight-->i has on) && (LocationOf(flashlight-->i) == fs_loc))
+ present_flashlights_on++;
+ }
+ if (past_flashlights_on ~= present_flashlights_on) {
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ if (past_flashlights_on < present_flashlights_on)
+ print (Nearby) 0, "your former self enters ", (TheLower) fs_loc,
+ " and sees a thin white beam of light shining where once
+ was darkness.^";
+ else
+ print (Nearby) 0, "your former self enters ", (TheLower) fs_loc,
+ " and sees only darkness where once a thin white beam of light
+ was shining.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+ }
+];
+
+! only need to check if in corridor with open door as this will catch all cases
+
+[CheckStateOfGroundLight t past_ground_light_state;
+ past_ground_light_state = Get2D(ground_equipment_light,t,my_time-EARLIEST_TIME);
+
+ if (~~d_paradox)
+ if ((ground_light_switch has on) ~= past_ground_light_state) {
+ if ((former_self-->t in ground_corridor) && (ground_equipment_door has open)) {
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ if (ground_light_switch has on) {
+ if (Get2D(ground_equipment_door_state,t,my_time-EARLIEST_TIME-1)==OPEN_)
+ print (Nearby) 0, "your former self enters the first floor corridor
+ and sees a pool of light spilling from the equipment room.^";
+ else
+ print (Nearby) 0, "your former self opens the door to the first floor
+ equipment room and bright fluorescent light
+ spills over her.^";
+ }
+ else {
+ if (Get2D(ground_equipment_door_state,t,my_time-EARLIEST_TIME-1)==OPEN_)
+ print (Nearby) 0, "your former self enters the first floor corridor
+ but does not see a pool of light spilling from the
+ equipment room.^";
+ else
+ print (Nearby) 0, "your former self opens the door to the first floor
+ equipment room but no bright fluorescent light
+ spills over her.^";
+ }
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+ }
+];
+
+[CheckStateOfSiren t past_state siren_on;
+ past_state = Get2D(siren_state,t,my_time-EARLIEST_TIME);
+ siren_on = (siren_start_time ~= UNKNOWN_) && (siren_start_time < my_time);
+
+ if (~~d_paradox)
+ if (past_state ~= siren_on) {
+ if (my_time - siren_start_time == 1)
+ print "^A piercing siren rings out.^";
+ if (my_time - siren_start_time > 1)
+ print "^The siren wails.^";
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print (Nearby) 0, "your former self cringes from the sound of the siren.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+];
+
+
+!! Only checks the bare contents of the room, not the containers, states etc.
+
+[CheckQuantityInRoom thing_type thing_loc t i present_count past_count;
+ present_count = 0;
+ past_count = 0;
+
+ if (~~d_paradox) {
+ for (i=0 : i < Exp(2,t+1) : i++) {
+ if (parent(thing_type-->i) == LocationOf(former_self-->t))
+ present_count++;
+ if (Get3D(thing_loc,t,my_time-EARLIEST_TIME,i) == LocationOf(former_self-->t))
+ past_count++;
+ }
+ if (past_count ~= present_count) {
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print "Entering ", (TheLower) LocationOf(former_self-->t),
+ " your past self looks quickly about. ";
+ if (past_count > present_count)
+ print "Unlike the last time, her gaze passes straight over the place
+ where ", (the) thing_type-->0,
+ " had lain.^";
+ else
+ print "As her glance falls upon ", (the) thing_type-->0,
+ " a moment of worry passes over her features.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+ }
+];
+
+[CheckPlayerInRoom t player_loc_now player_loc_next fs_loc_now fs_loc_next;
+
+ player_loc_now = Get2D(player_loc,time_travelled,my_time-EARLIEST_TIME-1);
+ player_loc_next = Get2D(player_loc,time_travelled,my_time-EARLIEST_TIME);
+ fs_loc_now = Get2D(player_loc,t,my_time-EARLIEST_TIME-1);
+ fs_loc_next = Get2D(player_loc,t,my_time-EARLIEST_TIME);
+
+ if ((player_loc_next == fs_loc_next)) {
+ if (player_loc_now == nothing) {
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print "Someone appears beside you in the cramped chamber.
+ Soft hair and anxious eyes. It is you.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+ else if (player_loc_now ~= player_loc_next) { !! if the player had moved...
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print "As you enter ", (TheLower) player_loc_next,
+ " you see your former self standing before you.
+ Hearing your soft footfall, she turns. Horror fills her eyes.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+ else if (fs_loc_now ~= fs_loc_next) { !! if the former self had moved...
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print "You turn at the sound of footsteps. It is you.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+ else
+ print "Error, former self saw player but neither had moved.^";
+ }
+ else if ((player_loc_next == fs_loc_now) && (player_loc_now == fs_loc_next)) {
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print "As you enter ", (TheLower) player_loc_next,
+ ", your eyes catch upon a figure coming towards you.
+ She pauses, fear all about her.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+ else if ((player_loc_next == deutsch_lab) && (fs_loc_next == prototype_interior)) {
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print "Hunched inside the prototype, your former self sees you through the open
+ hatch.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+ else if ((player_loc_next == prototype_interior) && (fs_loc_next == deutsch_lab)) {
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print "As your past self looks around, her eyes catch on
+ something inside the prototype.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+
+];
+
+[CheckObjectsOnDesk desk t;
+ CheckObjectOnDesk(desk, t, bomb, bomb_loc);
+ CheckObjectOnDesk(desk, t, id_card, id_card_loc);
+ CheckObjectOnDesk(desk, t, equipment_key, equipment_key_loc);
+ CheckObjectOnDesk(desk, t, deutsch_key, deutsch_key_loc);
+ CheckObjectOnDesk(desk, t, flashlight, flashlight_loc);
+ CheckObjectOnDesk(desk, t, battery, battery_loc);
+ CheckObjectOnDesk(desk, t, cable, cable_loc);
+ CheckObjectOnDesk(desk, t, crowbar, crowbar_loc);
+ CheckObjectOnDesk(desk, t, notes, notes_loc);
+];
+
+[CheckObjectOnDesk desk t thing_type thing_loc present_count past_count i;
+ if (~~d_paradox) {
+ for (i=0 : i < Exp(2,t+1) : i++) {
+ if (thing_type-->i in desk)
+ present_count++;
+ if (Get3D(thing_loc,t,my_time-EARLIEST_TIME,i) == desk)
+ past_count++;
+ }
+ if (past_count ~= present_count) {
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print "Entering ", (TheLower) LocationOf(former_self-->t),
+ " your past self looks quickly about. ";
+ if (past_count > present_count)
+ print "Unlike the last time, her gaze passes straight over the place
+ on ", (the) desk, " where ", (the) thing_type-->0,
+ " had lain.^";
+ else
+ print "As her glance falls upon ", (the) thing_type-->0,
+ " a moment of worry passes over her features.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+ }
+];
+
+[CheckTimeOnPanel t old_setting;
+ old_setting = Get2D(panel_setting, t, my_time-EARLIEST_TIME);
+ if (~~d_paradox)
+ if (control_panel.time_value ~= old_setting) {
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print "Entering the prototype, your past self glances at the control panel,
+ seeing ", control_panel.time_value, " instead of ", old_setting, ".^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+];
+
+
+!----------------------------------------------------
+!
+! Endgame functions:
+
+
+[CaughtInside t;
+ d_caught = true;
+
+!-- Initial method of being caught:
+
+ if (my_time > FINAL_TIME)
+ print "^A quick noise from behind, then a strong grip on your wrist.
+ The guard is back -- time has slipped away from you.^";
+ else if ((siren_start_time ~= UNKNOWN_) && (my_time - siren_start_time > siren_timeout))
+ print "^As the siren shrieks out around you, you catch a glimpse of movement.
+ A sudden jolt, then you are wrestled to the ground. Security has arrived.^";
+ else
+ print "Error: unknown reason for being caught^";
+
+!-- Allow a small amount of time for bomb to explode before player dragged off...
+
+ for (t=0 : (t<TIME_BEFORE_DRAGGED_OFF) && (my_time<FINAL_TIME) && (~~d_exploded) : t++) {
+ IncTime(); ! as it happens, this can lead to bomb-explosion, but not paradox
+ }
+
+ if (~~d_exploded) ! make sure player is dragged off
+ DragPlayerOff();
+];
+
+[Jumped;
+ if (~~warned_of_jump) {
+ print "It is a large drop and you are not at all sure that you could make it
+ without serious injury.^";
+ warned_of_jump = true;
+ return true;
+ }
+
+ d_caught = true;
+
+!-- Initial method of being caught:
+
+ print "You hit the ground hard and collapse. Your right ankle sears with pain.
+ Before you can stand, you see the security guard running swiftly towards you.^";
+
+ DragPlayerOff();
+];
+
+
+[DragPlayerOff t;
+
+ print "^Deaf to your protests, the guard ";
+ if (AmHolding(bomb) && ((GetHeld(bomb)).time_value ~= NA_))
+ print "disarms your bomb, ";
+ print "handcuffs you and forces you
+ into a dark sedan. You speed through the chill Boston night, head held in your hands,
+ almost oblivious to the blur of the suburbs rushing past.^";
+
+ d_detained = true;
+ move player to limbo;
+
+!-- Allow some more time for bomb to explode
+!-- and for paradoxes to occur
+
+ for (t=0 : (my_time<FINAL_TIME) && (~~d_exploded) && (~~d_paradox) : t++) {
+ IncTime();
+ }
+
+ MaybeExplodeBombAfterwards();
+
+ deadflag = 3;
+
+!-- Consequences of being caught:
+
+ if (~~d_paradox) {
+ print "^Half an hour later, the car pulls up outside a non-descript building and you
+ are dragged inside";
+ if (AmHolding(notes))
+ print ", the notes are taken from you and you are ";
+ else
+ print " then ";
+ print "thrown into a small cell to await questioning.^";
+
+ if (d_exploded) {
+ if (d_destroyed_prototype && d_destroyed_notes) {
+ print "^The months that follow are a nightmare. Solitary confinement, sleepless nights,
+ merciless interrogations. Eventually, you are taken before a civilian court and
+ tried for treason. A drawn-out trial, a guilty verdict, prison. Ambitions falter and
+ then fade. Still, as the months and then years pass, they do not bring the disaster
+ you had so feared and you cling, anxiously, longingly, to the dream that it was you who brought
+ this about, that your sacrifice was not in vain.^";
+ my_time = NA_;
+ DrawStatusLine();
+ deadflag = SAVED_CAUGHT_;
+ }
+! else if (d_destroyed_prototype && AmHolding(notes)) {
+! }
+ else if (d_destroyed_prototype) {
+ print "^The days that follow are a nightmare. Solitary confinement, sleepless nights,
+ merciless interrogations. All that keeps you going is the small hope that your actions
+ were not in vain.^";
+ Seperator();
+ print "With your research notes at hand, the military scientists painstakingly rebuild the
+ prototype and prepare it for testing.^";
+ }
+! else if (d_destroyed_notes) {
+! print " ";
+! }
+! else if (AmHolding(notes)) {
+! print " ";
+! }
+! else {
+! print " ";
+! }
+ }
+! else if (AmHolding(bomb) && AmHolding(notes)) {
+! print " ";
+! }
+! else if (AmHolding(bomb)) {
+! print " ";
+! }
+! else if (AmHolding(notes)) {
+! print " ";
+! }
+! else {
+! print " ";
+! }
+
+ if ((~~d_destroyed_prototype) || (~~d_destroyed_notes))
+ MilitaryTest();
+ }
+];
+
+[InBlastRadius thing bomb;
+ if (LocationOf(thing) == LocationOf(bomb))
+ return true;
+ if ((LocationOf(bomb) == deutsch_lab) && (LocationOf(thing) == prototype_interior))
+ return true;
+ if ((LocationOf(bomb) == prototype_interior) && (LocationOf(thing) == deutsch_lab))
+ return true;
+ return false;
+];
+
+[MaybeExplodeBombAfterwards i j;
+ if (~~d_exploded)
+ for (i=0 : i<MAX_ITEM_COPIES : i++)
+ if (((bomb-->i).time_value >= FINAL_TIME) && ~~(bomb-->i in player)) {
+ d_exploded = true;
+ if (LocationOf(bomb-->i) == deutsch_lab or prototype_interior)
+ d_destroyed_prototype = true;
+ for (j=0 : j < MAX_ITEM_COPIES : j++)
+ if (InBlastRadius(notes-->j,bomb-->i))
+ d_destroyed_notes = true;
+ }
+];
+
+[ExplodeBomb i j t;
+
+ if (d_exploded)
+ return true;
+
+ d_exploded = true;
+
+!-- what exploded?
+
+ if ((~~(d_escaped || d_detained)) && InBlastRadius(player,bomb-->i) )
+ d_killed_by_bomb = true;
+ if (~~(d_escaped || d_detained))
+ d_injured_by_bomb = true;
+ if (LocationOf(bomb-->i) == deutsch_lab or prototype_interior)
+ d_destroyed_prototype = true;
+ for (j=0 : j < MAX_ITEM_COPIES : j++)
+ if (InBlastRadius(notes-->j,bomb-->i))
+ d_destroyed_notes = true;
+ for (t=0 : t < time_travelled : t++)
+ if (InBlastRadius(former_self-->t, bomb-->i)) {
+ d_fs_killed_by_bomb = true;
+ d_paradox = true;
+ }
+ for (t=0 : t < time_travelled : t++)
+ if ((LocationOf(former_self-->t) ~= limbo)) {
+ d_fs_hears_bomb = true;
+ d_paradox = true;
+ }
+
+!-- Consequences of explosion
+
+ if (d_killed_by_bomb == true) {
+ print "^The bomb detonates. A wall of force rips through the room with savage
+ power, killing you immediately.^";
+ if (~~d_fs_hears_bomb) {
+ for (t=0 : (my_time<FINAL_TIME) && (~~d_paradox) : t++) {
+ IncTime();
+ }
+ deadflag = 3;
+ if ((~~d_paradox) && d_destroyed_prototype && d_destroyed_notes) {
+ my_time = NA_;
+ DrawStatusLine();
+ deadflag = SAVED_DEAD_;
+ }
+ else
+ MilitaryTest();
+ }
+ }
+ else if (d_injured_by_bomb) {
+ print "^The bomb detonates. You are knocked to the floor by the force of the
+ explosion and your ears ring. ";
+ if (~~d_fs_hears_bomb) {
+ print "Stunned, you lie prone on the floor as
+ the siren wails and the reek of smoke stings your nostrils.^^
+ Before you recover your senses, security is upon you.^";
+ DragPlayerOff();
+ }
+ else
+ print "^";
+ }
+
+ if (d_fs_killed_by_bomb) {
+ Seperator();
+ if (d_detained || d_escaped)
+ print "Across town, the bomb detonates.
+ The explosion tears into your former self and she falls lifeless to
+ the ground.^";
+ else
+ print (Nearby) 0, "the explosion tears into your former self and she falls lifeless to
+ the ground.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+ else if (d_fs_hears_bomb) {
+ Seperator();
+ if (d_detained || d_escaped)
+ print "Across town, the bomb detonates.
+ Your former self is brought to her knees by the sudden blast,
+ the horror of understanding written in her eyes.^";
+ else
+ print (Nearby) 0, "your former self is brought to her knees by the sudden blast,
+ the horror of understanding written in her eyes.^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ }
+
+
+];
+
+[Escaped t;
+ d_escaped = true;
+
+ move player to outside;
+
+!-- result of escaping:
+
+ print "^";
+
+ if (my_time >= FINAL_TIME - 3) {
+ print "The night beckons you from the open doors, but as you rush
+ forwards to meet it your hopes fail you -- security has arrived.^";
+ d_caught = true;
+ DragPlayerOff();
+ }
+ else if ((siren_start_time ~= UNKNOWN_) && (my_time - siren_start_time > siren_timeout - 2)) {
+ print "The night beckons you from the open doors, but as you rush
+ forwards to meet it your hopes fail you. With the siren shrieking out around you,
+ security has arrived.^";
+ d_caught = true;
+ DragPlayerOff();
+ }
+
+!-- Deal with the true escapes:
+
+ else {
+ move player to limbo;
+
+ print "You slip out into the night, darting quickly through the Cambridge
+ shadows until you reach the quiet corner where you left your car.
+ Exhausted, you gently start the cold motor and roll off towards the
+ interstate.^";
+
+!-- Step through the rest of the time to check for paradox and/or explosion
+
+ for (t=0 : (my_time<FINAL_TIME) && (~~d_paradox) : t++) {
+ IncTime();
+ }
+
+ MaybeExplodeBombAfterwards();
+
+ deadflag = 3;
+
+!-- Final wrap-up:
+
+ if (~~d_paradox) {
+ if (d_exploded) {
+ if (d_destroyed_prototype && d_destroyed_notes) {
+ print "^Days, months, years run by.
+ You find a new name, a new life.
+ Fresh challenges are gladly met and life proceeds with full force in its
+ new and welcome direction.
+ Only now and then do you stop on a chill starry night and
+ wonder whether you were right, what really would have happened.^";
+ my_time = NA_;
+ DrawStatusLine();
+ deadflag = SAVED_FREE_;
+ }
+ else if (d_destroyed_prototype && AmHolding(notes) && challenge) {
+ print "^Days, months, years run by.
+ You find a new name, a new life.
+ You travel abroad.
+ Eventually, you look again at your time-stained research notes
+ and think of the possibilities.^^
+ The inconsistencies are the key; the freed energy.
+ Maybe now, without the shadow of military interests, you could
+ make something of this.^";
+ my_time = NA_;
+ DrawStatusLine();
+ deadflag = SAVED_FREE_CHALLENGE_;
+ }
+ else if (d_destroyed_prototype && AmHolding(notes)) {
+ print "^Days, months, years run by.
+ You find a new name, a new life.
+ Fresh challenges are gladly met and life proceeds with full force in its
+ new and welcome direction.
+ Only now and then do you stop on a chill starry night and
+ wonder whether you were right, what really would have happened.^";
+ my_time = NA_;
+ DrawStatusLine();
+ deadflag = SAVED_FREE_;
+ }
+ else if (d_destroyed_prototype) {
+ print "^Days run by. You find a new name, begin a new life.
+ You hope, pray, that all you have done will stop them, that the
+ catastrophe will not come.^";
+ Seperator();
+ print "With your research notes at hand, the military scientists painstakingly rebuild the
+ prototype and prepare it for testing.^";
+ deadflag = DELAYED_;
+ }
+! else if (d_destroyed_notes) {
+! print "^Escape: ~d-prototype + d-notes.^";
+! }
+! else if (AmHolding(notes)) {
+! print "^Escape: useless explosion + holding notes.^";
+! }
+ else {
+ print "^Morning finds you in a truck-stop cafe, near Woodstock, NY. You sit there,
+ anxiously watching the morning news as you sip your bitter coffee.^";
+ }
+ }
+! else if (AmHolding(bomb) && AmHolding(notes)) {
+! print "^Escape: holding bomb + notes.^";
+! }
+! else if (AmHolding(bomb)) {
+! print "^Escape: holding bomb.^";
+! }
+! else if (AmHolding(notes)) {
+! print "^Escape: holding notes.^";
+! }
+ else {
+ print "^Morning finds you in a truck-stop cafe, near Woodstock, NY. You sit there,
+ anxiously watching the morning news as you sip your bitter coffee.^";
+ }
+
+ if (~~(d_destroyed_prototype && (d_destroyed_notes || AmHolding(notes)))) {
+ MilitaryTest();
+ }
+ }
+ }
+];
+
+! tests whether something has happened to stop the player continuing their actions
+
+[Stopped;
+ if (d_paradox || d_caught || d_exploded || d_escaped)
+ return true;
+ else
+ return false;
+];
+
+[Seperator;
+ print "^*******^^";
+];
+
+[MilitaryTest;
+ Devours(LATER_);
+];
+
+[Devours given_time explosion_time;
+
+ Seperator();
+ if (given_time == LATER_) {
+ if (d_destroyed_prototype) {
+ print "Monday 1st November 2004^^";
+ explosion_time = EXPERIMENT2_TIME;
+ deadflag = DELAYED_;
+ }
+ else {
+ print "Wednesday 13th October 2004^^";
+ explosion_time = EXPERIMENT1_TIME;
+ deadflag = USELESS_;
+ }
+ }
+ else {
+ print "Tuesday 12th October 2004^^";
+ deadflag = ACCELERATED_;
+ explosion_time = last_travel_time;
+ }
+
+ !my_time = explosion_time; ! these lines would update the status line time
+ !DrawStatusLine();
+
+ if (poem_interleaving) {
+ print "At precisely ", (PrintShortTime) explosion_time, " this morning ";
+
+ PoemStyleOn();
+ print "This thing all things devours: ";
+ PoemStyleOff();
+
+ print "a catastrophe of unprecedented scale occurred. ";
+
+ PoemStyleOn();
+ print "birds, beasts, trees, flowers; ";
+ PoemStyleOff();
+
+ print "An immense explosion -- that could only have been atomic in nature -- ";
+
+ PoemStyleOn();
+ print "gnaws iron, bites steel; ";
+ PoemStyleOff();
+
+ print "tore through the city and suburbs of Boston MA, destroying all in its path. ";
+
+ PoemStyleOn();
+ print "grinds hard stones to meal; ";
+ PoemStyleOff();
+
+ print "Casualties will number in the millions and martial law has been declared. ";
+
+ PoemStyleOn();
+ print "slays king, ruins town; ";
+ PoemStyleOff();
+
+ print "The military is mobilizing for war with the as yet unknown enemy. ";
+
+ PoemStyleOn();
+ print "and beats high mountain down. ";
+ PoemStyleOff();
+
+ print "^";
+ }
+ else {
+ print "At precisely ", (PrintShortTime) explosion_time, " this morning
+ a catastrophe of unprecedented scale occurred.
+ An immense explosion -- that could only have been atomic in nature --
+ tore through the city and suburbs of Boston MA, destroying all in its path.
+ Casualties are expected to number in the millions. The President has declared
+ a state of emergency across the nation and
+ the military is mobilizing for a possible war with the as yet unknown enemy.^^";
+ PoemStyleOn();
+ print "This thing all things devours:^";
+ print "birds, beasts, trees, flowers;^";
+ print "gnaws iron, bites steel;^";
+ print "grinds hard stones to meal;^";
+ print "slays king, ruins town;^";
+ print "and beats high mountain down.^";
+ PoemStyleOff();
+ }
+
+];
+
+[PoemStyleOn;
+ style bold;
+];
+
+[PoemStyleOff;
+ style roman;
+];
+
+[ DeathMessage;
+ switch (deadflag) {
+ ACCELERATED_: print "You have failed";
+ USELESS_: print "You have failed";
+ DELAYED_: print "You have failed";
+ SAVED_DEAD_: print "Success, but at such a cost";
+ SAVED_CAUGHT_: print "Success, but at such a cost";
+ SAVED_FREE_: print "Success. Final, lasting success.";
+ SAVED_FREE_CHALLENGE_: print "Success and, perhaps, a new hope.";
+ }
+];
+
+[Nearby;
+ if (~~(player in limbo))
+ print "Nearby, ";
+ else
+ print "Back at the lab, ";
+];
+
+[TheLower room;
+ print (string) room.lower_name;
+];
+
+
+
+!============================================================================
+
+! Include "../Contrib/Scenic";
+
+
+!============================================================================
+
+! Standard and extended grammar
+
+
+
+Include "Grammar";
+
+
+!----------------------------------------------------------------------------
+
+[ AboutSub;
+ instant_action_this_turn = true;
+ print "^All Things Devours is a short piece of interactive fiction, leaning strongly
+ towards the text-adventure end of the spectrum. It explores an all-too-familiar
+ science fiction paradigm in what I hope is a rather refreshing and satisfying manner.
+ However, due to the intrinsic nature of its subject matter, it is more cruel
+ than one might hope for a modern piece of interactive fiction. In particular,
+ any move you make may put things into an unwinnable state. You are therefore encouraged
+ to save frequently, and also to realise that you will probably have to start over several times
+ to find the most satisfactory ending.^^
+ Hints, reviews and more can be found at http://devours.amirrorclear.net^";
+];
+
+Verb 'about'
+ * 'game' -> About
+ * 'devours' -> About
+ * 'all' 'things' 'devours' -> About
+ * -> About;
+
+[ WalkthroughSub;
+ instant_action_this_turn = true;
+ print_ret "Hints and a walkthrough are located at http://devours.amirrorclear.net^
+ You might also want to try the 'about' command.^^
+ If you are unfamiliar with text adventures, then you may want to
+ learn the basics first at an introductory website such as
+ http://brasslantern.org/beginners/"; ];
+
+Verb 'walkthrough' 'walkthru' 'hint' 'hints' 'help'
+ * -> Walkthrough;
+
+[ CreditsSub;
+ instant_action_this_turn = true;
+ print_ret "Written by half sick of shadows for IFComp 2004.^
+ Beta tested by Stephen Bond.^
+ Special thanks go to those who submitted detailed bug reports and suggestions
+ during the competition, notably: Peter Eckersley, Oliver Nash,
+ Hugo Thorvaldsen and Evin Robertson.^
+ ^
+ No rights are reserved by the author:
+ this work is in the public domain and may be freely copied and modified.";
+];
+
+Verb 'credits'
+ * -> Credits;
+
+[ InterleavingOnSub;
+ instant_action_this_turn = true;
+ poem_interleaving = true;
+ "The ending will now be in the original, interleaved, style.";
+];
+
+[ InterleavingOffSub;
+ instant_action_this_turn = true;
+ poem_interleaving = false;
+ "The ending will now be in the standard style.";
+];
+
+Verb 'interleaving'
+ * 'on' -> InterleavingOn
+ * 'off' -> InterleavingOff;
+
+[ ResetSub; print_ret "It is not clear what you are trying to do."; ];
+
+Verb 'reset' 'stop' 'halt' 'defuse'
+ * noun -> Reset;
+
+Verb 'swipe'
+ * noun 'in' noun -> Insert
+ * noun 'through' noun -> Insert;
+
+[ CompleteModificationsSub;
+ if ((real_location == deutsch_lab) || (real_location == prototype_interior))
+ <<Tie prototype>>;
+ else
+ "You would need to be near the prototype to do that.";
+];
+
+Verb 'complete' 'finish'
+ * 'modifications' -> CompleteModifications
+ * 'work' -> CompleteModifications
+ * 'changes' -> CompleteModifications
+ * 'alteration' -> CompleteModifications;
+
+[ ModifySub;
+ if ((noun == prototype) || (noun == control_panel) || (noun == nothing)) {
+ if ((real_location == deutsch_lab) || (real_location == prototype_interior))
+ <<Tie prototype>>;
+ else
+ "You would need to be near the prototype to do that.";
+ }
+ "It is not clear what you are trying to do.";
+];
+
+Verb 'modify' 'change' 'alter'
+ * -> Modify
+ * noun -> Modify;
+
+[ SwitchSub;
+ if (noun has on)
+ <<SwitchOff noun>>;
+ else
+ <<SwitchOn noun>>;
+];
+
+Verb 'flick' 'flip'
+ * noun -> Switch;
+
+Extend 'switch' first
+ * noun -> Switch;
+
+[ SwingAtSub; if (second == nothing)
+ print_ret "You swing ", (the) noun, " through the air, harmlessly.";
+ else if (IsOfType(noun, crowbar))
+ <<Attack second>>;
+ else if ((second == conference_window) || (second ofclass AutomaticDoor)) {
+ print_ret (The) noun, " bounces harmlessly off the ",
+ (the) second, ".";
+ }
+ else
+ <<Attack noun>>;
+];
+
+Extend 'swing' first
+ * held -> SwingAt
+ * held 'at' noun -> SwingAt
+ * held 'into' noun -> SwingAt
+ * held 'through' noun -> SwingAt;
+
+
+[ AttackWithSub; if (IsOfType(second, crowbar))
+ <<Attack noun>>;
+ else if ((noun == conference_window) || (noun ofclass AutomaticDoor)) {
+ if (second == nothing)
+ print_ret "You are not strong enough to break ",
+ (the) noun, " by yourself.";
+ else
+ print_ret (The) second, " is not heavy enough to break ",
+ (the) noun, ".";
+ }
+ else
+ <<Attack noun>>;
+];
+
+Extend 'attack'
+ * noun 'with' 'fist' -> AttackWith
+ * noun 'with' 'foot' -> AttackWith
+ * noun 'with' 'hand' -> AttackWith
+ * noun 'with' held -> AttackWith;
+
+[ JumpDownSub; if (real_location == balcony)
+ Jumped();
+ else if ((real_location == upstairs_landing) || (real_location == foyer)) {
+ print "You hit the ground hard. Maybe you should have used the stairs.^";
+ <<Go d_obj>>;
+ }
+ else
+ "There is nothing to jump down to.";
+];
+
+Extend 'jump' first
+ * 'down' -> JumpDown;
+
+[ ClimbDownSub; if (real_location == balcony)
+ Jumped();
+ else if ((real_location == upstairs_landing) || (real_location == foyer))
+ <<Go d_obj>>;
+ else
+ "There is nothing to climb down to.";
+];
+
+Extend 'climb' first
+ * 'down' -> ClimbDown;
+
+[ LockSimpleSub k;
+if (noun has lockable) {
+ if (noun.with_key_type == nothing)
+ "You do not have the key.";
+ k = GetHeld(noun.with_key_type);
+ if (k == nothing)
+ "You do not have the key.";
+ <<Lock noun k>>;
+ }
+ else
+ "That doesn't seem to be something you can lock.";
+
+];
+
+Extend 'lock' first
+ * noun -> LockSimple;
+
+
+[ UnlockSimpleSub k;
+if (noun has lockable) {
+ if (noun.with_key_type == nothing)
+ "You do not have the key.";
+ k = GetHeld(noun.with_key_type);
+ if (k == nothing)
+ "You do not have the key.";
+ <<Unlock noun k>>;
+ }
+ else
+ "That doesn't seem to be something you can unlock.";
+
+];
+
+Extend 'unlock' first
+ * noun -> UnlockSimple;
+
+[ UseSub;
+ "You will have to be more specific about your action.";
+];
+
+Verb 'use'
+ * -> Use
+ * noun -> Use;
+
+[ PlantSub p;
+ p = parent(noun);
+ <Drop noun>;
+ if (parent(noun) ~= p)
+ if (noun ofclass Bomb_)
+ if (noun.time_value == NA_)
+ "(you may also want to set the timer)";
+];
+
+[ PlantInSub p;
+ p = parent(noun);
+ <Insert noun second>;
+ if (parent(noun) ~= p)
+ if (noun ofclass Bomb_)
+ if (noun.time_value == NA_)
+ "(you may also want to set the timer)";
+];
+
+[ PlantOnSub p;
+ p = parent(noun);
+ <PutOn noun second>;
+ if (parent(noun) ~= p)
+ if (noun ofclass Bomb_)
+ if (noun.time_value == NA_)
+ "(you may also want to set the timer)";
+];
+
+Verb 'plant'
+ * noun -> Plant
+ * noun 'in' noun -> PlantIn
+ * noun 'on' noun -> PlantOn;
+
+Extend 'look'
+ * noun -> Examine;
+
+[ WaitSecondsSub t;
+ if (noun == 0) {
+ instant_action_this_turn = true;
+ "That didn't take long.";
+ }
+ if (noun < 0) {
+ instant_action_this_turn = true;
+ "If you could do that, you wouldn't have built the prototype.";
+ }
+ print "Time passes.^";
+ if (noun%5 ~= 0) {
+ if (noun/5 > 0)
+ IncTime();
+ }
+ for (t=1 : t<noun/5 : t++)
+ IncTime();
+ if (~~deadflag)
+ if (noun%5 ~= 0)
+ print "Indeed you pause for slightly longer than you had planned,
+ carefully resynchronizing yourself with the
+ five second turn increments.^";
+];
+
+[ WaitTurnsSub t;
+ if (noun == 0) {
+ instant_action_this_turn = true;
+ "That didn't take long.";
+ }
+ print "Time passes.^";
+ if (noun < 0) {
+ instant_action_this_turn = true;
+ "If you could do that, you wouldn't have built the prototype.";
+ }
+ for (t=1 : t<noun : t++)
+ IncTime();
+];
+
+[ WaitUntilSub time_in_turns t;
+ time_in_turns = noun / 5 - my_time;
+ if (time_in_turns > FINAL_TIME - my_time)
+ time_in_turns = FINAL_TIME - my_time + 2;
+
+ if (time_in_turns == 0 && (noun%5 ==0)) {
+ instant_action_this_turn = true;
+ "That didn't take long.";
+ }
+ if (time_in_turns < 0) {
+ instant_action_this_turn = true;
+ "If you could do that, you wouldn't have built the prototype.";
+ }
+ print "Time passes.^";
+ if (noun%5 ~= 0) {
+ if (time_in_turns > 0)
+ IncTime();
+ }
+ for (t=1 : t<time_in_turns : t++)
+ IncTime();
+
+ if (~~deadflag)
+ if (noun%5 ~= 0)
+ print "Indeed you pause for slightly longer than you had planned,
+ carefully resynchronizing yourself with the
+ five second turn increments.^";
+];
+
+[ HoursMinsSecsWordToTime hour minute second word;
+ if (hour >= 24) return -1;
+ if (minute >= 60) return -1;
+ if (second >= 60) return -1;
+ if (hour > 4) return 18000; ! this is to avoid integer overflow
+ if (word == 'pm')
+ return 18000;
+
+ return (hour*60 + minute) * 60 + second;
+];
+
+! based on the code from the DM4.
+! looks for a time in the format 2:39 or 4:17:18
+
+[ TimeOfDay first_word second_word at length colons illegal_char digits hr mn se i;
+ first_word = NextWordStopped();
+ if (first_word == -1)
+ return GPR_FAIL;
+ at = WordAddress(wn-1);
+ length = WordLength(wn-1);
+ for (i=0: i<length: i++) {
+ switch (at->i) {
+ ':': if (colons == 0 && digits>0 && i<length-1) {
+ colons = 1;
+ digits = 0;
+ }
+ else if (colons == 1 && digits==2 && i<length-1) {
+ colons = 2;
+ digits = 0;
+ }
+ else
+ illegal_char = true;
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ digits = digits+1;
+ if (digits > 2)
+ illegal_char = true;
+ default: illegal_char = true;
+ }
+ }
+ if (length < 3 || length > 8 || illegal_char || colons == 0)
+ return GPR_FAIL;
+ for (i=0: at->i~=':': i++, hr=hr*10)
+ hr = hr + at->i - '0';
+ hr = hr/10;
+ mn = ((at->(i+1) - '0') * 10) + at->(i+2) - '0';
+ if (colons == 2) {
+ i = i+3;
+ se = ((at->(i+1) - '0') * 10) + at->(i+2) - '0';
+ }
+ second_word = NextWordStopped();
+ parsed_number = HoursMinsSecsWordToTime(hr, mn, se, second_word);
+ if (parsed_number == -1) return GPR_FAIL; if (second_word ~= 'pm' or 'am') wn--;
+ return GPR_NUMBER;
+];
+
+Extend 'wait'
+ * number -> WaitSeconds
+ * number 'seconds' -> WaitSeconds
+ * number 'second' -> WaitSeconds
+ * number 'turns' -> WaitTurns
+ * number 'turn' -> WaitTurns
+ * 'until' TimeOfDay -> WaitUntil;
+
+
+[ ShoutSub t;
+ print "You shout loudly.^";
+ for (t=0 : t<time_travelled : t++) {
+ if ((former_self-->t notin limbo) &&
+ ((siren_start_time == UNKNOWN_) || (siren_start_time > my_time))) {
+
+ d_paradox = true;
+ deadflag = 3;
+ Seperator();
+ print (Nearby) 0, "your former self hears the muffled sounds of your
+ shouting.^^Something of an anticlimactic way to kill
+ so many millions of people...^";
+ print "^Time unravels...^";
+ Devours(my_time);
+ return true;
+ }
+ }
+ Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,SHOUT_);
+ MaybeSing();
+ return true;
+];
+
+Extend only 'shout' replace
+ * -> Shout
+ * topic -> Shout;
+
+Verb 'yell'
+ * -> Shout
+ * topic -> Shout;
+
+Verb 'tear'
+ * noun -> Attack
+ * 'up' noun -> Attack;
+
+Extend 'remove' first ! so that 'remove battery' works
+ * multiinside -> Remove;
+
+[ HoldDownWithSub;
+ if (noun == alarm_button || noun == basement_button || noun == first_button ||
+ noun == second_button || noun == silver_button || noun == exit_button ) {
+ "The button is set into a vertical surface,
+ making it impossible to hold it down with another object.";
+ }
+ else
+ "It is not clear what that is supposed to accomplish.";
+];
+
+Extend 'hold' first ! so that 'remove battery' works
+ * 'down' noun -> Push
+ * 'down' noun 'with' noun -> HoldDownWith
+ * 'down' noun 'using' noun -> HoldDownWith;
+
+[ ChallengeSub;
+ instant_action_this_turn = true;
+ if (challenge)
+ "The challenge has already been initiated.";
+ if (first_turn) {
+ challenge = true;
+ siren_timeout = CHALLENGE_SIREN_TIMEOUT;
+ early_guard_time = CHALLENGE_EARLY_GUARD_TIME;
+ "The game is now in its most challenging form.
+ Three key elements have been changed to make success considerably
+ more difficult. This challenge is not
+ required for a successful completion of the game. It is just here
+ for those who, upon finishing, wish there was a little bit more.^
+ ^
+ If you do want to take up the challenge, then remember to initiate this
+ mode each time you begin play.";
+ }
+ else
+ "The challenge can only be initiated in the first turn.";
+];
+
+[ EndChallengeSub;
+ instant_action_this_turn = true;
+ challenge = false;
+ siren_timeout = DEFAULT_SIREN_TIMEOUT;
+ early_guard_time = EARLIEST_TIME;
+ "The game is now at its standard difficulty.";
+];
+
+Verb 'challenge'
+ * -> Challenge
+ * 'on' -> Challenge
+ * 'mode' 'on' -> Challenge
+ * 'off' -> EndChallenge
+ * 'mode' 'off' -> EndChallenge;
+
+Verb 'start' 'begin' 'initiate'
+ * 'challenge' -> Challenge
+ * 'challenge' 'mode' -> Challenge;
+
+Verb 'end'
+ * 'challenge' -> EndChallenge
+ * 'challenge' 'mode' -> EndChallenge;
+
+!============================================================================
+