Elevator and stairs (Dialog example)
From IFWiki
(current player #player) (#player is #in #ground) (story author) IF Community %% Creating the right predicates makes for simple, elegant code. (level #ground 1) (level #external-button-ground 1) (level #internal-button-g 1) (level #ground-door 1) (level #second 2) (level #external-button-second 2) (level #second-door 2) (level #internal-button-2 2) (level #third 3) (level #external-button-third 3) (level #third-door 3) (level #internal-button-3 3) ($Button is button of $Room) *(button $Button) *(room $Room) (level $Room $N) (level $Button $N) ($Door is door of $Room) *(door $Door) *(room $Room) (level $Door $N) (level $Room $N) %% Floors #ground (room *) (name *) ground floor (singleton *) (ordinal *) ground %% Instead of creating three separate stairs objects, we will create one and %% specify that each of the three floors attracts it. (* attracts #stairs) (look *) (look at *) and the stairs are up. (from * go #north through #ground-door to #elevator) (#elevator is on *) (from * go #up to #second) #second (room *) (name *) second floor (singleton *) (ordinal *) second (* attracts #stairs) (look *) (look at *) and stairs go both up and down from here. (from * go #north through #second-door to #elevator) (#elevator is on *) (from * go #up to #third) (from * go #down to #ground) #third (room *) (name *) third floor (singleton *) (ordinal *) (* attracts #stairs) (look *) (look at *) or you can take the stairs down. (from * go #north through #third-door to #elevator) (#elevator is on *) (from * go #down to #second) (look at $Room) ($Door is door of $Room) You are on the (ordinal $Room) floor. The (if)($Door is open)(then) open (else) closed (endif) door to the elevator is north, %% Call Buttons #external-button-ground (external button *) (* is #in #ground) #external-button-second (external button *) (* is #in #second) #external-button-third (external button *) (* is #in #third) (name (external button $Button)) (external button $Button) call button (descr (external button $Button)) (current room $Room) ($Button is button of $Room) Pushing this button summons the elevator to this floor. It's currently (if)($Button is lit)(then) lit (else) dark (endif) . (perform [push (button $Button)]) (push $Button) %% When the elevator is already on the floor and the door is closed (push $Button) (#elevator is on $Origin) ($Button is button of $Dest) ($Origin = $Dest) ($Door is door of $Origin) ($Door is closed) (now)($Door is open) (now)($Door closes in 2) (The $Door) opens. %% When the elevator is already on the floor and the door is already open (push $Button) (#elevator is on $Origin) ($Button is button of $Dest) ($Origin = $Dest) ($Door is door of $Origin) ($Door is open) Nothing happens. ($Door closes in $Old) ($Old plus 1 into $New) (now)($Door closes in $New) %% When the elevator is on a different floor and all the doors are closed (push $Button) *(external button $External) ($Button is button of $Room) ($External is button of $Room) (#ground-door is closed) (#second-door is closed) (#third-door is closed) (now)(#elevator has destination $Room) (now)~(#external-button-ground is lit) (now)~(#external-button-second is lit) (now)~(#external-button-third is lit) (now)($External is lit) (if)(current room $Room)(or)(current room #elevator)(then) The call button lights up. (endif) (move elevator) %% When the elevator is on a different floor and at least one door is open (push $Button) *(external button $External) ($Button is button of $Dest) ($External is button of $Dest) (now)(#elevator has destination $Dest) (now)~(#external-button-ground is lit) (now)~(#external-button-second is lit) (now)~(#external-button-third is lit) (now)($External is lit) (if)(current room $Dest)(or)(current room #elevator)(then) The call button lights up.(par) (endif) (#elevator is on $Room) ($Door is door of $Room) (if)($Door is open)(then) (if)(current room $Room)(or)(current room #elevator)(then) (The $Door) closes. (endif) (endif) (now)(#ground-door is closed) (now)(#second-door is closed) (now)(#third-door is closed) (now)~(#ground-door closes in $) (now)~(#second-door closes in $) (now)~(#third-door closes in $) (stop) %% Elevator Doors #ground-door (door *) (openable *) (* is closed) (* is #in #ground) #second-door (door *) (openable *) (* is closed) (* is #in #second) #third-door (door *) (openable *) (* is closed) (* is #in #third) (name (door $Door)) elevator door (descr (door $Door)) (current room $Room) ($Door is door of $Room) The elevator door is (if)($Door is open)(then) open, (else) closed, (endif) and there's a call button beside it. (prevent [open (door $Door)]) ($Door is open) (The $Door) is already open. (prevent [open (door $Door)]) Try pushing the call button. (prevent [close (door $Door)]) ($Door is closed) (The $Door) is already closed. (prevent [close (door $Door)]) (The $Door) will close automatically when it needs to. %% Elevator #elevator (name *) elevator (room *) (singleton *) (* is on #ground) (look *) You are inside the elevator. The door to the south is (#elevator is on $Room) ($Door is door of $Room) (if)($Door is open)(then) open (else) closed (endif) , and there's the usual panel of buttons beside it. (from * go #south through #ground-door to #ground) (* is on #ground) (from * go #south through #second-door to #second) (* is on #second) (from * go #south through #third-door to #third) (* is on #third) %% As a kindness to the player we remap OUT to SOUTH. (from * go #out to #south) (on every tick) ($Door closes in $Old) ($Door is door of $Room) (if)($Old = 0)(then) (now)~($Door closes in $) (now)($Door is closed) (if)(current room $Room)(or)(current room #elevator)(then) (par)The door closes. (endif) (else) ($Old minus 1 into $New) (now)($Door closes in $New) (endif) %% If the elevator is already on the right floor (on every tick) (#elevator is on $Current) (#elevator has destination $Dest) ($Current = $Dest) ($Door is door of $Current) (now)($Door is open) (now)~(#elevator has destination $) (now)($Door closes in 2) ($Button is button of $Current) (now)~($Button is lit) (current room $Room) (if)($Room = $Current)(or)($Room = #elevator)(then) (par)(The $Door) opens. The call button blinks off. (endif) (on every tick) (move elevator) %% If the elevator is below the destination (move elevator) (#elevator is on $Current) (#elevator has destination $Dest) (level $Current $CurrentLevel) (level $Dest $DestLevel) ($CurrentLevel < $DestLevel) ($CurrentLevel plus 1 into $NextLevel) (level $Room $NextLevel) (now)(#elevator is on $Room) (if)(current room #elevator)(then) (par)You feel the elevator going up (if)($Dest = $Room)(then) , and then it comes to a stop (endif) . (endif) (stop) %% If the elevator is above the destination (move elevator) (#elevator is on $Current) (#elevator has destination $Dest) (level $Current $CurrentLevel) (level $Dest $DestLevel) ($CurrentLevel > $DestLevel) ($CurrentLevel minus 1 into $NextLevel) (level $Room $NextLevel) (now)(#elevator is on $Room) (if)(current room #elevator)(then) (par)You feel the elevator going down (if)($Dest = $Room)(then) , and then it comes to a stop (endif) . (endif) (stop) %% Panel #panel (name *) panel (* is #in #elevator) (descr *) The panel has three buttons: G, 2, and 3. There is also a LED display that reads (display floor). #internal-button-g (name *) g button (dict *) (plural dict *) buttons (internal button *) (* is #partof #panel) #internal-button-2 (name *) 2 button (dict *) two (plural dict *) buttons (internal button *) (* is #partof #panel) #internal-button-3 (name *) 3 button (dict *) three (internal button *) (plural dict *) buttons (* is #partof #panel) %% We make external buttons and internal buttons members of the same %% class. This allows us to make our code more concise elsewhere. (button $Obj) *(external button $Obj) (button $Obj) *(internal button $Obj) %% Instead of creating a distinct "buttons" object, we create a means to refer %% to multiple already existing objects. (action [examine $] may group (internal button $) with (internal button $)) (group-perform [examine $List]) *(internal button $Obj) ($Obj is one of $List) (try [examine #panel]) (instead of [examine (internal button $)]) (try [examine #panel]) %% Display #display (name *) LED display (singleton *) (descr *) The LED display is showing a large red (display floor).(par) (* is #in #elevator) (display floor) (#elevator is on #ground) G (display floor) (#elevator is on #second) 2 (display floor) 3 %% Stairs #stairs (name *) stairs (plural *) (singleton *) (descr *) (current room $Room) (if)($Room = #ground)(then) They go up.(par) (elseif)($Room = #second)(then) They go up and down.(par) (else) They go down.(par) (endif) (instead of [take/climb #stairs]) (current room $Room) ($Room is one of [#ground #second #third]) (if)($Room = #ground)(then) (try [go #up]) (elseif)($Room = #third)(then) (try [go #down]) (else) Which way do you want to go?(par) 1. Up.(line) 2. Down.(par) (get key $Key) (handle keypress $Key) (endif) (handle keypress $Key) ($Key is one of [1 @\u]) (try [go #up]) (handle keypress $Key) ($Key is one of [2 @\d]) (current room $Room) (try [leave $Room #down]) (perform [take #stairs]) There are no stairs here.(par) %% As per our instructions, we make going up or down stairs take three ticks. (after [go $Dir]) ($Dir is one of [#up #down]) (tick)(tick) %% TAKE <obj> <dir> (grammar [take [object] [direction]] for [take $ $]) (instead of [take $Obj $Dir]) ($Obj = #stairs) ($Dir is one of [#up #down]) (try [go $Dir])