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;