Elevator simulation

From Rosetta Code
Elevator simulation is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
Task


To see how it works watch the next video
Evelator Game in Ring - video
Necessary image files - download
Please if you can attach a video file how your sample works.

Phix

Library: Phix/online

You can run this online here.

--
-- demo\rosetta\ElevatorSimulation.exw
-- ===================================
--
-- Even dumber than a real lift - clicking 16161616 ties it up for ages...
--
with javascript_semantics
include pGUI.e
Ihandle dlg, canvas, timer
cdCanvas cdcanvas

constant title = "Elevator Simulation",
         CD_DARKER_GREY = #383838,      -- (darker than CD_DARK_GREY)
         CD_LIGHTER_ORANGE = #FFA500,   -- (lighter than CD_ORANGE)
         CD_PALE_BLUE = #98C5DA,        -- (lighter than CD_LIGHT_BLUE)
         CD_MEDIUM_BLUE = #759EB4,      -- (darker than CD_LIGHT_BLUE)
         panels = {{195,30,45,12},      -- indicator
                   {380,150,50,90},     -- up/down
                   {380,465,100,210},   -- main 
                   {625,330,75,25},     -- restart
                   {625,530,75,25}},    -- exit
         buttons = {{380,110,"^"},
                    {380,190,"v"},
                    {335,305,"5"},{420,305,"6"},
                    {335,385,"3"},{420,385,"4"},
                    {335,465,"1"},{420,465,"2"},
                    {380,540,"GF"},
                    {380,630,">|<"}}

integer cur_floor,  -- 0..6
        wait_sign   -- "", -1 if none
bool door_open

sequence actions = {}   -- (see timer_cb)

procedure new_game()
    cur_floor = rand(7)-1
    wait_sign = rand(7)-1
    door_open = rand(2)==1
end procedure

function redraw_cb(Ihandle /*ih*/, integer /*posx*/, /*posy*/)
    integer {width, height} = IupGetIntInt(canvas, "DRAWSIZE")
    cdCanvasActivate(cdcanvas)
    cdCanvasSetBackground(cdcanvas, CD_DARKER_GREY)
    cdCanvasClear(cdcanvas)
    cdCanvasSetForeground(cdcanvas, CD_LIGHTER_ORANGE)
    cdCanvasSetInteriorStyle(cdcanvas, CD_SOLID)
    for i=1 to length(panels) do
        integer {cx,cy,hw,hh} = panels[i]
        cdCanvasRoundedBox(cdcanvas,cx-hw,cx+hw,height-(cy+hh),height-(cy-hh),5,4)
        // (a filled box has no antialiasing, so overwrite with an outline box too:)
        cdCanvasRoundedRect(cdcanvas,cx-hw,cx+hw,height-(cy+hh),height-(cy-hh),5,4)
    end for
    cdCanvasSetForeground(cdcanvas, CD_BLACK)
    cdCanvasFont(cdcanvas, "Helvetica", CD_PLAIN, 16)
    {} = cdCanvasTextAlignment(cdcanvas,CD_CENTER)
    integer {cx,cy} = panels[1]
    string floor_text = iff(cur_floor=0?"GF":sprintf("%d",cur_floor))
    cdCanvasText(cdcanvas,cx,height-cy,floor_text)
    cy += 75
    for i=6 to 0 by -1 do
        integer minx = cx-40,
                maxx = cx+40,
                miny = height-(cy+45),
                maxy = height-(cy-40)
        cdCanvasSetForeground(cdcanvas, CD_PARCHMENT)
        cdCanvasBox(cdcanvas,minx,maxx,miny,maxy)
        if i=cur_floor then
            if i=wait_sign then wait_sign = -1 end if
            cdCanvasSetForeground(cdcanvas, CD_MEDIUM_BLUE)
            cdCanvasBox(cdcanvas,minx,maxx,miny,maxy)
            cdCanvasSetForeground(cdcanvas, CD_PALE_BLUE)
            cdCanvasBox(cdcanvas,minx+5,maxx-5,miny,maxy)
            if door_open then
                cdCanvasSetForeground(cdcanvas, CD_CYAN)
                cdCanvasBox(cdcanvas,minx+8,maxx-8,miny,maxy)
            else
                cdCanvasSetForeground(cdcanvas, CD_MEDIUM_BLUE)
                cdCanvasLine(cdcanvas,cx,miny,cx,maxy)
            end if
        elsif i=wait_sign then
            integer y3 = height-cy-3
            for j=1 to 2 do
                cdCanvasSetForeground(cdcanvas, {CD_YELLOW,CD_BLACK}[j])
                cdCanvasBegin(cdcanvas,{CD_FILL,CD_CLOSED_LINES}[j])
                cdCanvasVertex(cdcanvas, cx, miny+3)
                cdCanvasVertex(cdcanvas, maxx-2, y3)
                cdCanvasVertex(cdcanvas, cx, maxy-4)
                cdCanvasVertex(cdcanvas, minx+1, y3)
                cdCanvasEnd(cdcanvas)
            end for
            cdCanvasText(cdcanvas,cx,y3,"WAIT")
        end if
        cy += 90
    end for
    cdCanvasFont(cdcanvas, "Helvetica", CD_PLAIN, 20)
    for i=1 to length(buttons) do
        {cx,cy,floor_text} = buttons[i]
        cy = height-cy
        cdCanvasSetForeground(cdcanvas, CD_SILVER)
        cdCanvasSector(cdcanvas, cx, cy, 60, 60, 0, 360) 
        cdCanvasSetForeground(cdcanvas, CD_BLACK)
        cdCanvasArc(cdcanvas, cx, cy, 50, 50, 0, 360) 
        cdCanvasArc(cdcanvas, cx, cy, 60, 60, 0, 360) 
        {} = cdCanvasTextOrientation(cdcanvas, iff(i=1?180:0)) 
        cdCanvasText(cdcanvas,cx,cy,iff(i=1?"v":floor_text))
    end for
    cdCanvasFont(cdcanvas, "Helvetica", CD_PLAIN, 16)
    cdCanvasSetForeground(cdcanvas, CD_BLACK)
    {cx,cy} = panels[4]
    cdCanvasText(cdcanvas,cx,height-cy,"Restart")
    {cx,cy} = panels[5]
    cdCanvasText(cdcanvas,cx,height-cy,"Exit")
    cdCanvasFlush(cdcanvas)
    return IUP_DEFAULT
end function

function map_cb(Ihandle ih)
    atom res = IupGetDouble(NULL, "SCREENDPI")/25.4
    IupGLMakeCurrent(canvas)
    if platform()=JS then
        cdcanvas = cdCreateCanvas(CD_IUP, canvas)
    else
        cdcanvas = cdCreateCanvas(CD_GL, "798x698 %g", {res})
    end if
    cdCanvasSetBackground(cdcanvas, CD_PARCHMENT)
    return IUP_DEFAULT
end function

function button_cb(Ihandle canvas, integer button, pressed, x, y, atom /*pStatus*/)
    if button=IUP_BUTTON1 and pressed then
        integer cx,cy,hw,hh
        string floor_text
        for i=1 to length(buttons) do
            {cx,cy,floor_text} = buttons[i]
            {cx,cy} = {cx-x,cy-y}
            if cx*cx+cy*cy<=3600 then -- (the button radius is 60)
                actions &= floor_text[1] -- (let timer_cb sort it out)
                IupSetInt(timer,"RUN",true)
                exit
            end if
        end for
        for i=4 to 5 do
            {cx,cy,hw,hh} = panels[i]
            if x>=cx-hw and x<=cx+hw
            and y>=cy-hh and y<=cy+hh then  
                if i=5 then return IUP_CLOSE end if
                new_game()
                IupRedraw(dlg)
                exit    
            end if
        end for
    end if
    return IUP_CONTINUE
end function

function timer_cb(Ihandle /*ih*/)
    if length(actions)=0 then
        IupSetInt(timer,"RUN",false)
    else
        integer action -- 'G'==='0', '<' is open, '>' is close.
        {action,actions} = {actions[1],actions[2..$]}
        switch action do
            case 'G': action = '0'; fallthrough
            case '0','1','2','3','4','5','6':
                integer d = action-'0'-cur_floor
                if d!=0 then
                    actions = repeat(sign(d),abs(d)) & '<' & actions
                    if door_open then actions = prepend(actions,'>') end if
                elsif not door_open then
                    actions = prepend(actions,'<')
                end if
            case -1,+1:
                cur_floor += action
            case '>','<':
                door_open = action=='<'
            case '^','v':
                if wait_sign!=-1 
                and compare(cur_floor,wait_sign)==compare(action,'_') then
                    -- (hint: in ascii, '^' < '_' whereas 'v' > '_' ...
                    ---       plus action ain't ever gonna be '_' here.)
                    actions = prepend(actions,wait_sign+'0')
                end if
            default: ?9/0 -- unknown action?
        end switch
        IupRedraw(dlg)
    end if
    return IUP_IGNORE
end function

procedure main()
    IupOpen()
    canvas = IupGLCanvas("RASTERSIZE=800x700")
    sequence cb = {"MAP_CB", Icallback("map_cb"),
                   "ACTION", Icallback("redraw_cb"),
                   "BUTTON_CB", Icallback("button_cb")}
    IupSetCallbacks(canvas, cb)
    dlg = IupDialog(canvas,`TITLE="%s", RESIZE=NO`,{title})
    new_game()
    IupShow(dlg)
    timer = IupTimer(Icallback("timer_cb"),500,false)
    if platform()!=JS then
        IupMainLoop()
        IupClose()
    end if
end procedure
main()

Ring


Evelator Game in Ring - video

<lang ring>

  1. Project : Elevator Game
  2. Date  : 21/08/2021-02:26:57
  3. Author  : Gal Zsolt (~ CalmoSoft ~)
  4. Email  : calmosoft@gmail.com

load "stdlib.ring" load "guilib.ring"

floorCount = 7 randEvelator = 1 randWait = 1 randOld = 0 nFloor = 0 count = 0 flag = 0 targetFloor = 0 floor = list(floorCount) floorbtn = list(floorCount) floorCall = list(floorCount) C_UP = "images/up.jpg" C_DOWN = "images/down.jpg" C_WAIT = "images/wait.jpg" C_EMPTY = "images/empty.jpg" C_OPEN = "images/elevatoropen.jpg" C_CLOSE = "images/elevatorclose.jpg" C_CLOSEELEVATOR = "images/closeevelator.jpg" C_RECTANGLE = "images/rectangle.jpg" floorbtn[1] = "images/floor0.jpg" floorbtn[2] = "images/floor1.jpg" floorbtn[3] = "images/floor2.jpg" floorbtn[4] = "images/floor3.jpg" floorbtn[5] = "images/floor4.jpg" floorbtn[6] = "images/floor5.jpg" floorbtn[7] = "images/floor6.jpg"

oFont = new qfont("Verdana",16,0,0) C_ButtonOrangeStyle = 'border-radius:6px;color:black; background-color: orange'

app = new qApp {

     stylefusionblack()
     processevents()
     win = new qWidget() {

setWindowTitle('Elevator Game')

           setWindowIcon(new qIcon(new qPixmap(C_OPEN)))

move(550,140) reSize(800,700)

           app.processEvents()
           for n = 1 to floorCount

floor[n] = new QPushButton(win) { setgeometry(150,510-(n-2)*90,85,85) }

           next
           showFloor = new QPushButton(win)	

{ setgeometry(150,15,90,25) setstylesheet(C_ButtonOrangestyle)

                         setfont(oFont)
                       }

rectangle = new QPushButton(win) { setgeometry(330,55,100,180) setstylesheet(C_ButtonOrangestyle)

                         setIconSize(new qSize(66,66))
                       }

down = new QPushButton(win) { setgeometry(350,150,66,66)

                    setfont(oFont)

seticon(new qicon(new qpixmap(C_DOWN)))

                    setIconSize(new qSize(66,66))
                    setclickevent("pMoveDown()")
                  }

up = new QPushButton(win) { setgeometry(350,70,66,66)

                  setfont(oFont)

seticon(new qicon(new qpixmap(C_UP)))

                  setIconSize(new qSize(66,66))
                  setclickevent("pMoveUp()")
                }

newGame = new QPushButton(win) { setgeometry(550,300,150,50) setstylesheet(C_ButtonOrangestyle)

                       setfont(oFont)
                       settext("New Game")
                       setclickevent("pNewGame()")
                     }

exitButton = new QPushButton(win) { setgeometry(550,500,150,50) setstylesheet(C_ButtonOrangestyle)

                          setfont(oFont)
                          setClickEvent("pExit()")

settext("Exit") }

rectangleFloor = new QPushButton(win) { setgeometry(280,260,190,420) setstylesheet(C_ButtonOrangestyle)

                              setIconSize(new qSize(66,66))
                            }

floorCall[1] = new QPushButton(win) { setgeometry(343,506,66,66) seticon(new qicon(new qpixmap(floorbtn[1])))

                            setIconSize(new qSize(100,100))
                            settext("GF")
                            setclickevent("pMove(" + "1" + ")")
                          }

floorCall[2] = new QPushButton(win) { setgeometry(300,420,66,66) seticon(new qicon(new qpixmap(floorbtn[2])))

                            setIconSize(new qSize(100,100))
                            setclickevent("pMove(" + "2" + ")")
                          }

floorCall[3] = new QPushButton(win) { setgeometry(386,420,66,66) seticon(new qicon(new qpixmap(floorbtn[3])))

                            setIconSize(new qSize(100,100))
                            setclickevent("pMove(" + "3" + ")")
                          }

floorCall[4] = new QPushButton(win) { setgeometry(300,344,66,66) seticon(new qicon(new qpixmap(floorbtn[4])))

                            setIconSize(new qSize(100,100))
                            setclickevent("pMove(" + "4" + ")")
                            show()	
                          }

floorCall[5] = new QPushButton(win) { setgeometry(386,344,66,66) seticon(new qicon(new qpixmap(floorbtn[5])))

                            setIconSize(new qSize(100,100))
                            setclickevent("pMove(" + "5" + ")")
                            show()	
                          }

floorCall[6] = new QPushButton(win) { setgeometry(300,268,66,66) seticon(new qicon(new qpixmap(floorbtn[6])))

                            setIconSize(new qSize(100,100))
                            setclickevent("pMove(" + "6" + ")")
                          }

floorCall[7] = new QPushButton(win) { setgeometry(386,268,66,66) seticon(new qicon(new qpixmap(floorbtn[7])))

                            setIconSize(new qSize(100,100))
                            setclickevent("pMove(" + "7" + ")")
                          }

close = new QPushButton(win) { setgeometry(340,592,66,66) seticon(new qicon(new qpixmap(C_CLOSEELEVATOR)))

                     setIconSize(new qSize(66,66))
                     setclickevent("pClose()")
                   }        
           show()
     }
     pBegin()
     exec()   

}

func pNewGame()

    pBegin()
    pWait()

func pBegin()

    flag = 0
    count = 0
    for n = 1 to floorCount

floor[n] { seticon(new qicon(new qpixmap(C_EMPTY)))

                   setIconSize(new qSize(100,100)) }	
    next
    randEvelator = random(floorCount-1) + 1
    for n = 1 to floorCount

floorCall[n] { setenabled(False) }

    next
    up { setenabled(True) }
    down { setenabled(True) }
    pWait()

func pWait()

    floor[randWait] { seticon(new qicon(new qpixmap(C_EMPTY)))
                      setIconSize(new qSize(100,100)) }
    randWait = random(floorCount-1) + 1
    while true 
          if randWait != randEvelator
             nFloor = randEvelator
             floor[randWait] { seticon(new qicon(new qpixmap(C_WAIT)))
                               setIconSize(new qSize(100,100)) }
             floor[randEvelator] { seticon(new qicon(new qpixmap(C_CLOSE)))
                                   setIconSize(new qSize(100,100)) }
             showFloor.settext(string(randEvelator-1))
             for n = 1 to floorCount
                 floorCall[n] { setenabled(False) }
             next
             exit
          else
             randEvelator = random(floorCount-1) + 1
          ok
    end
    return

func pMove(sourceFloor)

    if flag = 1
    n = 0
    pClose()
    app.processEvents()
    sleep(0.5)
    up { setenabled(false) }
    down { setenabled(false) }
    count = count + 1
    if count = 1
       targetFloor = randWait
    else
       targetFloor = randOld
    ok
    n = 0
    if sourceFloor > targetFloor
       for n = targetFloor to sourceFloor - 1
           app.processEvents()
           sleep(0.5)
           floor[n] { seticon(new qicon(new qpixmap(C_EMPTY)))
                      setIconSize(new qSize(100,100)) }
           floor[n+1] { seticon(new qicon(new qpixmap(C_CLOSE)))
                      setIconSize(new qSize(100,100)) }
           if n = 0
              showFloor.settext("GF")
           else
              showFloor.settext(string(n))
           ok
           if n = sourceFloor - 1
              nFloor = n + 1
              floor[n+1] { seticon(new qicon(new qpixmap(C_OPEN)))
                           setIconSize(new qSize(100,100)) }
           ok
       next
       see nl
    ok
    n = 0
    if sourceFloor < targetFloor 
       for n = targetFloor to sourceFloor + 1 step -1
           app.processEvents()
           sleep(0.5)
           floor[n] { seticon(new qicon(new qpixmap(C_EMPTY)))
                      setIconSize(new qSize(100,100)) }
           floor[n-1] { seticon(new qicon(new qpixmap(C_CLOSE)))
                        setIconSize(new qSize(100,100)) }
           if n = 2
              showFloor.settext("GF")
           else
              showFloor.settext(string(n-2))
           ok
           if n = sourceFloor + 1
              nFloor = n - 1
              floor[n-1] { seticon(new qicon(new qpixmap(C_OPEN)))
                           setIconSize(new qSize(100,100)) }
           ok
       next
       see nl
    ok
    randOld = sourceFloor
    ok

func pMoveDown

    if randWait > randEvelator
       return
    ok
    for n = 1 to floorCount

floorCall[n] { setenabled(True) }

    next
    if randWait < randEvelator
       for n = randEvelator to randWait + 1 step -1
           app.processEvents()
           sleep(0.5)
           floor[n] { seticon(new qicon(new qpixmap(C_EMPTY)))
                      setIconSize(new qSize(100,100)) }
           floor[n-1] { seticon(new qicon(new qpixmap(C_CLOSE)))
                        setIconSize(new qSize(100,100)) }
           if n = 0
              showFloor.settext("GF")
           else
              showFloor.settext(string(n-2))
           ok
           if n = randWait + 1
                  nFloor = n - 1
                  floor[n-1] { seticon(new qicon(new qpixmap(C_OPEN)))
                               setIconSize(new qSize(100,100)) }
           ok
       next
    ok 
    app.processEvents()
    sleep(1)
    flag++       

func pMoveUp()

    if randWait < randEvelator
       return
    ok    
    for n = 1 to floorCount

floorCall[n] { setenabled(True) }

    next
    if randWait > randEvelator
       for n = randEvelator to randWait - 1
           app.processEvents()
           sleep(0.5)
           floor[n] { seticon(new qicon(new qpixmap(C_EMPTY)))
                      setIconSize(new qSize(100,100)) }
           floor[n+1] { seticon(new qicon(new qpixmap(C_CLOSE)))
                        setIconSize(new qSize(100,100)) }
           if n = 1
              showFloor.settext("GF")
           else
              showFloor.settext(string(n))
           ok
           if n = randWait - 1
                  nFloor = n + 1
                  floor[n+1] { seticon(new qicon(new qpixmap(C_OPEN)))
                               setIconSize(new qSize(100,100)) }
           ok
        next
    ok   
    app.processEvents()
    sleep(1)
    flag++

func pClose()

    floor[nFloor] { seticon(new qicon(new qpixmap(C_CLOSE)))
                    setIconSize(new qSize(100,100)) } 

func pExit()

    win.close()
    app.quit()

</lang>

Wren

Library: DOME
Library: Wren-dynamic
Library: Wren-ellipse
Library: Go-fonts

It's not currently possible to run a DOME application online in a browser but the following is designed to look and work more or less like the Ring entry. However, the user interface is not as fancy as I don't have ready made images of elevators etc. available. <lang ecmascript>import "dome" for Window, Platform, Process import "graphics" for Canvas, Color, Font import "audio" for AudioEngine import "input" for Mouse import "random" for Random import "./dynamic" for Enum import "./ellipse" for Circle, Polygon, Rectangle, Square

var Direction = Enum.create("Direction", ["halted", "up", "down"])

var Rand = Random.new()

class Elevator {

   construct new() {
       Window.resize(820, 820)
       Canvas.resize(820, 820)
       Window.title = "Elevator game"
       // see Go-fonts page
       Font.load("Go-Regular20", "Go-Regular.ttf", 20)
       Canvas.font = "Go-Regular20"
       Font.load("Go-Regular25", "Go-Regular.ttf", 25)
       // download from https://soundbible.com/509-Mouse-Double-Click.html
       AudioEngine.load("click", "mouse_click.wav")        
   }
   init() {
       newGame()
   }
   newGame() {
       _buttons = []
       // floors
       for (i in 1..7) {
           Canvas.rectfill(120, 100*i + 5, 90, 90, Color.white)
       }
       // floor up/down buttons
       Canvas.rectfill(300, 30, 100, 200, Color.orange)
       var up = Square.new(315, 45, 70, "up")
       up.drawfill(Color.lightgray)
       _buttons.add(up)
       Canvas.print("\u25b2", 345, 70, Color.black)
       var down = Square.new(315, 145, 70, "down")
       down.drawfill(Color.lightgray)
       _buttons.add(down)
       Canvas.print("\u25bc", 345, 170, Color.black)
       // floor number buttons
       Canvas.rectfill(250, 305, 200, 490, Color.orange)
       var f25 = "Go-Regular25"
       var floor5 = Circle.new(300, 350, 40, 5)
       floor5.drawfill(Color.lightgray)
       Canvas.print("5", 295, 340, Color.black, f25) 
       var floor6 = Circle.new(400, 350, 40, 6)
       floor6.drawfill(Color.lightgray)
       Canvas.print("6", 395, 340, Color.black, f25)
       var floor3 = Circle.new(300, 450, 40, 3)
       floor3.drawfill(Color.lightgray)
       Canvas.print("3", 295, 440, Color.black, f25) 
       var floor4 = Circle.new(400, 450, 40, 4)
       floor4.drawfill(Color.lightgray)
       Canvas.print("4", 395, 440, Color.black, f25) 
       var floor1 = Circle.new(300, 550, 40, 1)
       floor1.drawfill(Color.lightgray)
       Canvas.print("1", 295, 540, Color.black, f25)
       var floor2 = Circle.new(400, 550, 40, 2)
       floor2.drawfill(Color.lightgray)
       Canvas.print("2", 395, 540, Color.black, f25)
       var ground = Square.fromCenter(350, 650, 80, "ground")
       ground.drawfill(Color.white)
       Canvas.print("GF", 335, 640, Color.black, f25)
       var close = Square.fromCenter(350, 750, 80, "close")
       close.drawfill(Color.white, Color.black, 2)
       Canvas.print("\u25ba\u25c4", 330, 740, Color.black)
       _buttons.addAll([floor1, floor2, floor3, floor4, floor5, floor6, ground, close])
       // new game button
       var newGame = Rectangle.new(525, 355, 150, 50, "new")
       newGame.drawfill(Color.orange)
       Canvas.print("New Game", 545, 365, Color.black)
       _buttons.add(newGame)
       // exit button
       var exit = Rectangle.new(525, 595, 150, 50, "exit")
       exit.drawfill(Color.orange)
       Canvas.print("Exit", 575, 605, Color.black)
       _buttons.add(exit)
   
       _floor = Rand.int(0, 7) // start by placing lift on a random floor
       drawLift()
       openDoors()
       changeFloorNumber()
       _dir = Direction.halted
       _floorDest = _floor
       _start = 0
       _wait = Rand.int(0, 7)  // start with a random wait point, different to where lift is
       if (_wait == _floor) {
           _wait = _floor - 1
           if (_wait < 0) _wait = 2
       }
       var wait = Polygon.regular(4, 165, 750 - _wait*100, 45, 0)
       wait.drawfill(Color.yellow, Color.black)
       Canvas.print("WAIT", 140, 740 - _wait*100, Color.black)
   }
   update() {
       if (Mouse["left"].justPressed) {
           var x = Mouse.x
           var y = Mouse.y
           for (btn in _buttons) {
               if (btn.contains(x, y)) {
                   var t = btn.tag
                   if (t == "up") {
                       if (_floor < 6) {
                           _dir = Direction.up
                           _floorDest = 6
                       }
                   } else if (t == "down") {
                       if (_floor > 0) {
                           _dir = Direction.down
                           _floorDest = 0
                       }
                   } else if (t is Num) {
                        if (t < _floor) {
                           _dir = Direction.down
                        } else if (t > _floor) {
                           _dir = Direction.up
                        } else {
                           _dir = Direction.halted
                           openDoors()
                        }
                        _floorDest = t
                   } else if (t == "ground") {
                        if (_floor > 0) {
                           _dir = Direction.down
                        } else {
                           _dir = Direction.halted
                           openDoors()
                        }
                        _floorDest = 0
                   } else if (t == "close") {
                        if (_dir == Direction.halted) {
                           closeDoors()
                        }
                   } else if (t == "new") {
                       Canvas.cls("black")
                       newGame()
                   } else if (t == "exit") {
                       Process.exit()
                   }
                   if (_dir != Direction.halted) {
                       closeDoors()
                       _start = Platform.time
                   } else {
                       _start = 0
                   }
               }
           }
       }
   }
   drawLift() {
       Canvas.rectfill(120, 100*(7 - _floor) + 5, 90, 90, Color.blue)
   }
   undrawLift() {
       Canvas.rectfill(120, 100*(7 - _floor) + 5, 90, 90, Color.white)
   }
   changeFloorNumber() {
       Canvas.rectfill(120, 30, 90, 40, Color.orange)
       Canvas.print(_floor.toString, 160, 40, Color.black)
   }
   openDoors() {
       Canvas.rectfill(135, 100*(7 - _floor) + 30, 60, 60, Color.white)
   }
   closeDoors() {
       Canvas.rectfill(120, 100*(7 - _floor) + 5, 90, 90, Color.blue)
   }
       
   draw(alpha) {
       if (_start > 0) {
           var delta = Platform.time - _start
           if (delta >= 1) {
               undrawLift()
               _floor = (_dir == Direction.up) ? _floor + 1 : _floor - 1
               drawLift()
               changeFloorNumber()
               if (_floor == _wait) {
                   _dir = Direction.halted
                   _start = 0
                   _wait = -1
                   openDoors()
               } else if (_floor == _floorDest) {
                   _dir = Direction.halted
                   _start = 0
                   openDoors()        
               } else {
                   _start = _start + delta
               }
           }
       }
   }

}

var Game = Elevator.new()</lang>