Elevator and stairs (Inform 6 example)
From IFWiki
This was more complicated than I expected, but anyway...
Constant Story "Elevator and stairs example";
Constant Headline "^By David Welbourn for IFWiki^";
Release 1;
Constant MAX_SCORE = 0;
Constant DIALECT_US = 1;
Constant DEATH_MENTION_UNDO;
! This helps me figure out when to insert an extra newline before or after
! tricky paragraphs built out of the following messages:
! The X lights up. The X blinks off. The elevator door opens/closes.
Global inPara = 0;
Include "Parser";
Include "VerbLib";
!------------------CLASSES----------------------
! Use classes to reduce duplicate code and make a cleaner design.
Class Room
with each_turn [;
if (inPara == 1) { new_line; inPara = 0; }
],
has light;
Class ElevatorDoor
with name 'elevator' 'door',
description [; "The elevator door is ", (string) self.openname(),
", and there's a call button beside it."; ],
openname [; if (self has open) return "open"; else return "closed"; ],
door_dir n_to,
door_to Elevator,
before [;
Open:
if (self has open) "The elevator door is already open.";
if (parent(self) == Elevator) "Try pushing a button.";
"Try pushing the call button.";
Close:
if (self has open) "The elevator door will close automatically when it needs to.";
"The elevator door is already closed.";
],
makeClosed [;
if (self hasnt open) return; ! precaution
give self ~open;
if (location == parent(self)) {
if (inPara == 0) new_line;
inPara = 0; "The elevator door closes. ";
}
],
makeOpen [;
if (self has open) return; ! precaution
give self open;
if (location == parent(self)) {
if (inPara == 0) new_line;
inPara = 0; "The elevator door opens. ";
}
],
has door scenery;
Class TouchButton
with name 'button',
floor 1,
litname [; if (self has on) return "lit"; else return "dark"; ],
before [;
Push, Touch:
if (self has on) print_ret (The) self, " is already lit.";
if (Elevator.floor == self.floor) {
if (door_e has open) {
door_e.daemonFuse = door_e.daemonFuse + 1; "Nothing happens.";
}
door_e.openEvent(); rtrue;
}
self.makeOn();
Elevator.floortarget = self.floor;
StartDaemon(Elevator); rtrue;
],
makeOff [;
if (self hasnt on) rfalse; ! precaution
give self ~on;
if (location == parent(self)) {
if (inPara == 0) new_line;
print (The) self, " blinks off. "; inPara = 1;
}
],
makeOn [;
if (self has on) rfalse; ! precaution
! tricky ordering: We say this one goes on, then turn them all off, then turn this on.
if (location == parent(self)) { print (The) self, " lights up. "; inPara = 1; }
AllButtonsOff();
give self on;
],
has scenery;
Class CallButton class TouchButton
with name 'call' 'button',
description [; "Pushing this button summons the elevator to this floor. It's currently ",
(string) self.litname(), "."; ];
Class PanelButton class TouchButton
with description [; print_ret (The) self, " is ", (string) self.litname(), "."; ];
Class Stairs
with name 'stairs', article "a set of",
has scenery;
!--------------EXTRA FUNCTIONS---------------
[ AllButtonsOff ;
call_button_g.makeOff(); call_button_2.makeOff(); call_button_3.makeOff();
pbutton_g.makeOff(); pbutton_2.makeOff(); pbutton_3.makeOff();
];
[ LongClimbTo rm;
print "It takes longer than you'd expect to use the stairs...^";
PlayerTo(Midstairs, true); AdvanceClock(); AdvanceClock();
return rm;
];
[ AdvanceClock; ! borrowed this code from timesys.h
#ifdef InformLibrary;
InformLibrary.End_Turn_Sequence();
#ifnot;
#ifdef EndTurnSequence;
EndTurnSequence();
#ifnot;
Message fatalerror "[Can't advance the clock.]";
#endif;
#endif;
];
!-------------ROOMS AND OBJECTS----------------
Room Ground_Floor "Ground Floor"
with description [;
"You are on the ground floor. The ", (string) door_g.openname(),
" door to the elevator is north, and the stairs are up.";
],
before [;
TakeStairsUp: <<Go u_to>>;
],
n_to door_g, in_to door_g, u_to [; return LongClimbTo(Second_Floor); ];
ElevatorDoor -> door_g "elevator door";
CallButton -> call_button_g "call button";
Stairs -> stairs_g "stairs" with description "They go up.",
before [;
Take: <<Go u_obj>>;
];
Room Second_Floor "Second Floor"
with description [;
"You are on the second floor. The ", (string) door_2.openname(),
" door to the elevator is north, and stairs go both up and down from here.";
],
before [;
TakeStairsUp: <<Go u_to>>;
TakeStairsDown: <<Go d_to>>;
],
n_to door_2, in_to door_2,
u_to [; return LongClimbTo(Third_Floor); ],
d_to [; return LongClimbTo(Ground_Floor); ];
ElevatorDoor -> door_2 "elevator door";
CallButton -> call_button_2 "call button" with floor 2;
Stairs -> stairs_2 "stairs" with description "They go up and down.",
before [;
Take: "Do you want to take the stairs up, or take the stairs down?";
];
Room Third_Floor "Third Floor"
with description [;
"You are on the third floor. The ", (string) door_3.openname(),
" door to the elevator is north, or you can take the stairs down.";
],
before [;
TakeStairsDown: <<Go d_to>>;
],
n_to door_3, in_to door_3, d_to [; return LongClimbTo(Second_Floor); ];
ElevatorDoor -> door_3 "elevator door";
CallButton -> call_button_3 "call button" with floor 3;
Stairs -> stairs_3 "stairs" with description "They go down.",
before [;
Take: <<Go d_obj>>;
];
Room Elevator "Elevator"
with description [;
"You are inside the elevator. The door to the south is ", (string) door_e.openname(),
", and there's the usual panel of buttons beside it.";
],
floor 1, ! Which floor the elevator car is currently on.
floortarget 1, ! Which floor the elevator is trying to get to.
daemon [;
! Either close the doors, move the car, or open the doors.
if (door_e has open) door_e.closeEvent();
else if (self.floor < self.floortarget) {
self.floor = self.floor + 1;
if (location == Elevator) {
if (inPara == 1) { new_line; inPara = 0; }
print "^You feel the elevator go up";
if (self.floor == self.floortarget) print " and come to a stop";
print ". The LED changes to "; led.readout(); ".";
}
}
else if (self.floor > self.floortarget) {
self.floor = self.floor - 1;
if (location == Elevator) {
if (inPara == 1) { new_line; inPara = 0; }
print "^You feel the elevator go down";
if (self.floor == self.floortarget) print " and come to a stop";
print ". The LED changes to "; led.readout(); ".";
}
}
else door_e.openEvent();
],
s_to door_e, out_to door_e;
ElevatorDoor -> door_e "elevator door"
with description [; "The elevator door is ", (string) self.openname(), "."; ],
door_dir s_to,
door_to [;
switch (Elevator.floor) {
1: return Ground_Floor;
2: return Second_Floor;
3: return Third_Floor;
}
],
openEvent [;
if (self has open) return; ! A precaution against opening an open door.
switch (Elevator.floor) {
1: call_button_g.makeOff(); pbutton_g.makeOff(); door_g.makeOpen();
2: call_button_2.makeOff(); pbutton_2.makeOff(); door_2.makeOpen();
3: call_button_3.makeOff(); pbutton_3.makeOff(); door_3.makeOpen();
}
self.makeOpen();
StopDaemon(Elevator);
self.daemonFuse = 3; StartDaemon(self);
],
closeEvent [;
if (self hasnt open) return; ! A precaution against closing a closed door.
switch (Elevator.floor) {
1: door_g.makeClosed();
2: door_2.makeClosed();
3: door_3.makeClosed();
}
self.makeClosed(); self.daemonFuse = 0; StopDaemon(self);
],
daemonFuse 0, ! how long until the doors auto-close?
daemon [; !
self.daemonFuse = self.daemonFuse - 1;
if (self.daemonFuse <= 0) self.closeEvent();
];
Object -> panel "panel of buttons"
with name "panel" "of" "buttons",
description [; print "The panel has three buttons: G, 2, and 3.
There is also a LED display that reads ~"; led.readout(); "~."; ],
has scenery;
PanelButton -> pbutton_g "G button" with name 'ground' 'g//';
PanelButton -> pbutton_2 "2 button" with name '2//' 'two', floor 2;
PanelButton -> pbutton_3 "3 button" with name '3//' 'three', floor 3;
Object -> led "LED display"
with name 'led' 'display',
description [; print "The LED display is showing a large red "; self.readout(); "."; ],
readout [;
if (Elevator.floor == 1) print "G"; else print Elevator.floor;
],
has scenery;
! Midstairs is a temporary room to move the player to, so event messages
! won't reach him/her during the first two turns of the 3-turn movement.
Room midstairs "Midstairs";
[ Initialise;
location = Ground_Floor;
lookmode = 2; ! verbose mode
score = 0;
];
[ TakeStairsUpSub;
"There are no stairs going up here.";
];
[ TakeStairsDownSub;
"There are no stairs going down here.";
];
Include "Grammar";
Extend only 'take' first
* 'stairs' 'up' -> TakeStairsUp
* 'stairs' 'down' -> TakeStairsDown;