Jump to content

Elevator simulation

From Rosetta Code
Revision as of 21:36, 10 November 2024 by Jjuanhdez (talk | contribs) (Added FreeBASIC)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
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
Elevator Simulation in Ring - video
Necessary image files - download
Please if you can attach a video file how your sample works.

FreeBASIC

#include "fbgfx.bi"

' Constants
Const WINDOW_WIDTH = 800
Const WINDOW_HEIGHT = 700
Const CD_DARKER_GREY = &h383838
Const CD_LIGHTER_ORANGE = &hFFA500
Const CD_PALE_BLUE = &h98C5DA
Const CD_MEDIUM_BLUE = &h759EB4

Type Button
    x As Integer
    y As Integer
    text As String
    
    Declare Constructor ()
    Declare Constructor (x As Integer, y As Integer, txt As String)
End Type

Constructor Button()
    x = 0
    y = 0
    text = ""
End Constructor

Constructor Button(x As Integer, y As Integer, txt As String)
    This.x = x
    This.y = y
    This.text = txt
End Constructor

Type Panel
    x As Integer
    y As Integer
    ancho As Integer
    alto As Integer
    
    Declare Constructor ()
    Declare Constructor (x As Integer, y As Integer, w As Integer, h As Integer)
End Type

Constructor Panel()
    x = 0
    y = 0
    ancho = 0
    alto = 0
End Constructor

Constructor Panel(x As Integer, y As Integer, w As Integer, h As Integer)
    This.x = x
    This.y = y
    This.ancho = w
    This.alto = h
End Constructor

' Variables
Dim Shared As Integer curFloor, waitSign, actionCount
Dim Shared As Boolean doorOpen
Dim Shared As String actions(100)

' Initialize panels
Dim Shared panels(4) As Panel
panels(0) = Panel(195, 30, 45, 12)    ' indicator
panels(1) = Panel(380, 150, 50, 90)   ' up/down
panels(2) = Panel(380, 465, 100, 210) ' main
panels(3) = Panel(625, 330, 75, 25)   ' restart
panels(4) = Panel(625, 530, 75, 25)   ' exit

' Initialize buttons
Dim Shared buttons(9) As Button
buttons(0) = Button(380, 110, "^")
buttons(1) = Button(380, 190, "v")
buttons(2) = Button(335, 305, "5")
buttons(3) = Button(420, 305, "6")
buttons(4) = Button(335, 385, "3")
buttons(5) = Button(420, 385, "4")
buttons(6) = Button(335, 465, "1")
buttons(7) = Button(420, 465, "2")
buttons(8) = Button(380, 540, "GF")
buttons(9) = Button(380, 630, "><")

Sub NewGame()
    curFloor = Int(Rnd * 7)
    waitSign = Int(Rnd * 7)
    doorOpen = (Int(Rnd * 2) = 1)
    actionCount = 0
End Sub

Sub DrawElevator()
    Dim As Integer i, x, y
    
    Screenlock
    Cls
    
    ' Draw panels
    For i = 0 To 4
        Line (panels(i).x - panels(i).ancho, panels(i).y - panels(i).alto)- _
        (panels(i).x + panels(i).ancho, panels(i).y + panels(i).alto), _
        CD_LIGHTER_ORANGE, BF
    Next i
    
    ' Draw floor indicator
    Draw String (180, 20), Iif(curFloor = 0, "GF", Str(curFloor)), &hFFFFFF
    
    ' Draw elevator shaft
    Dim As Integer floorY = 50
    For i = 6 To 0 Step -1
        ' Draw floor background
        Line (155, floorY)-(235, floorY + 80), &hFFFFFF, BF
        Line (155, floorY)-(235, floorY + 80), &h808080, B
        
        ' Draw floor number with better positioning
        Draw String (130, floorY + 35), Iif(i = 0, "GF", Str(i)), &hFFFFFF
        
        If i = curFloor Then
            ' Draw elevator car with better visibility
            Line (160, floorY + 5)-(230, floorY + 75), CD_MEDIUM_BLUE, BF
            
            If doorOpen Then
                ' Draw open doors
                Line (165, floorY + 5)-(185, floorY + 75), CD_PALE_BLUE, BF
                Line (205, floorY + 5)-(225, floorY + 75), CD_PALE_BLUE, BF
            Else
                ' Draw closed doors
                Line (160, floorY + 5)-(230, floorY + 75), CD_MEDIUM_BLUE, BF
            End If
        End If
        
        ' The WAIT sign indicates a floor where the elevator needs to stop
        If i = waitSign Then
            Circle (195, floorY + 40), 25, &hFFFF00,, , , F
            Draw String (185, floorY + 35), "WAIT", &h000000
        End If
        
        floorY += 90
    Next i
    
    ' Draw buttons
    For i = 0 To 9
        Circle (buttons(i).x, buttons(i).y), 30, &hC0C0C0,, , , F
        Circle (buttons(i).x, buttons(i).y), 30, &h000000
        Draw String (buttons(i).x - 5, buttons(i).y - 5), buttons(i).text, &h000000
    Next i
    
    ' Draw panel labels
    Draw String (panels(3).x - 20, panels(3).y - 5), "Restart", &hFFFFFF
    Draw String (panels(4).x - 15, panels(4).y - 5), "Exit", &hFFFFFF
    
    Screenunlock
End Sub

Sub ProcessActions()
    If actionCount > 0 Then
        Dim action As String = actions(0)
        
        ' Shift array left
        For i As Integer = 0 To actionCount - 2
            actions(i) = actions(i + 1)
        Next i
        actionCount -= 1
        
        ' Regular floor movement processing
        Select Case action
        Case "GF"
            If curFloor > 0 Then
                curFloor -= 1
                doorOpen = False
            Else
                doorOpen = True
            End If
        Case "1" To "6"
            Dim As Integer targetFloor = Valint(action)
            ' Add multiple movements until target floor is reached
            While curFloor <> targetFloor
                If curFloor < targetFloor Then
                    curFloor += 1
                Else
                    curFloor -= 1
                End If
                DrawElevator()
                Sleep 500
            Wend
            doorOpen = True
        Case "^"
            If curFloor < 6 Then 
                curFloor += 1
                doorOpen = False
            End If
        Case "v"
            If curFloor > 0 Then 
                curFloor -= 1
                doorOpen = False
            End If
        Case "><"
            doorOpen = Not doorOpen
        End Select
        
        ' Check for WAIT sign
        If curFloor = waitSign Then
            waitSign = -1
            doorOpen = True
            actions(actionCount) = "><"
            actionCount += 1
        End If
        
        DrawElevator()
    End If
End Sub

Sub main()
    Screenres WINDOW_WIDTH, WINDOW_HEIGHT, 32
    Windowtitle "Elevator Simulation"
    
    Randomize Timer
    NewGame()
    
    Dim As Integer mx, my, mb, i
    Do
        DrawElevator()
        
        Getmouse mx, my, , mb
        If mb And 1 Then
            ' Check button clicks
            For i = 0 To 9
                If (mx - buttons(i).x) ^ 2 + (my - buttons(i).y) ^ 2 <= 900 Then
                    actions(actionCount) = buttons(i).text
                    actionCount += 1
                    Sleep 100
                    Exit For
                End If
            Next i
            
            ' Check panel clicks
            If mx >= panels(3).x - panels(3).ancho And mx <= panels(3).x + panels(3).ancho Then
                If my >= panels(3).y - panels(3).alto And my <= panels(3).y + panels(3).alto Then
                    NewGame()
                Elseif my >= panels(4).y - panels(4).alto And my <= panels(4).y + panels(4).alto Then
                    Exit Do
                End If
            End If
        End If
        
        ProcessActions()
        Sleep 100
        
    Loop Until Multikey(FB.SC_ESCAPE)
End Sub

main()

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


Elevator Simulation in Ring - video

# Project : Elevator Game
# Date    : 21/08/2021-02:26:57
# Author  : Gal Zsolt (~ CalmoSoft ~)
# 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()

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.

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()
Cookies help us deliver our services. By using our services, you agree to our use of cookies.