Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
-1

What kind of loop should i use?

Asked by
nich17 95
9 years ago

i am currently scripting an elevator and i have reached a problem where when a button is clicked and the elevator is in use the button will not work because i have a variable active set to true when the elevator is in use so i would like to know what loop would be useful to use so that when a button is clicked and the elevator is active it will still eventually proceed to run its function after the button is pushed?

some pseudo code of what im dealing with here looks like this

1 button is pushed 2 if active = false continue 3 active = true 4 elevator moves to designated floor 5 active = false 6 else nothing happens 7 end

but if another button is pushed while it is active u will see that it will just not work so how could i possibly troubleshoot this issue that has come up?

0
I haven't the faintest idea what you're problem is... Perci1 4988 — 9y
0
i want to know how to make a loop that will wait until the elevator is idle to run nich17 95 — 9y

1 answer

Log in to vote
0
Answered by
BlueTaslem 18071 Moderation Voter Administrator Community Moderator Super Administrator
9 years ago

This is a really poorly done question on your part -- You haven't described what you're doing or exactly what you have in mind.


I'm going to assume you have an elevator, and either an "up", "down", and "stop" button, and a "call to this floor" button (maybe a few of these).

That means the elevator has a few states: moving up, moving down, or stopped.

Based on the last button that was pressed, it has a particular state (or we could get more complicated).


At this point, there are two approaches. Since the important state changes are when you press buttons, it might actually be best to not have some constant loop and just do work when the buttons are pressed. This gets a little complicated, but I'll outline it first, because it sometimes looks nice.

The other option is for something to constantly be looking at the elevator's state and make sure it is appropriate based on the last button pressed. I'll do this second.

Events

I'm going to use a "hypothetical" elevator where the only thing I do is set a variable velocity -- 1 for up, -1 for down, 0 for stopped.

function stopButton()
    velocity = 0
end

function upButton()
    velocity = 1
end

function downButton()
    velocity = -1
end

This is remarkably simple -- no loops required.

Now, let's consider a "call" button. For this, we need to know where the elevator is. We'll use y to mean the elevator's position (but we won't set y, only read from it). I'll use ty as the "target y" (the y of the given floor) in this event:

function callTo(ty)
    if ty == y then
        -- You would actually want a small
        -- tolerance, since it probably won't ever be exact
        velocity = 0
    elseif ty < y then
        velocity = -1
    else
        velocity = 1
    end
end

This will make the elevator go towards the floor, but it won't stop when it gets there.

An idiomatic way would be to use a while loop (though a repeat until would be equivalent)

function callTo(ty)
    while ty ~= y do
        -- again, a tolerance would be better
        if ty < y then
            velocity = -1
        else
            velocity = 1
        end
        wait() -- Some pause, to not freeze
    end
    velocity = 0
end

This will work -- but it will only work with 1 call at a time.

One simple solution is the debounce pattern - we essentially "disable" calling as long as it is still going to its floor:

canCall = true

function callTo(ty)
    if not canCall then
        return
    end
    canCall = false -- No one *else* can call
    while ty ~= y do
        --.....
    end
    velocity  = 0
    canCall = true -- Now someone else can call
end

This may be what we want, but it may not. We may want to interrupt the current action whenever we press a button (this would be more sensical to most users, though probably isn't what a real elevator would do)

To do that, we will keep track of something like a reverse debounce, where any other call will inform all previous ones to stop operating.

controller = nil -- which call is controlling the elevator?

function callTo(ty)
    local myControl = math.random()
    -- Or, equivalently, = {}, which I like for succinctness
    controller = myControl
    while controller == myControl and ty ~= y do
        -- .... (same body)
    end
    velocity = 0
end

Now, whenever callTo gets called, it changes controller, but it doesn't change myControl -- so controller == myControl becomes false and the old call stops working.

Single, Constant Loop

The final design that we have is essentially just one loop -- it just gets traded off between different calls to the function with a different ty variable.

With that in mind, we can make a much simpler system:

target = 0 -- ground floor?

function callTo(ty)
    target = ty -- Store most recent call to target
end

while true do
    wait()
    if y == target then
        velocity = 0
    elseif y < target then
        velocity = -1
    else
        velocity = 1
    end
end

This is all we need. If we wanted to put some sort of "debounce", we could do that, too:

target = 0

function callTo(ty)
    target = ty
end

local realTarget = 0
while true do
    wait()
    if y == realTarget then
        velocity = 0
    elseif y < realTarget then
        velocity - 1
    else
        velocity = 1
    end
    if velocity == 0 then
        -- I'm at my floor, so now I can go to the next one
        -- (Maybe also a `wait(1)` in here to stay at the
        -- floor for a least a moment?)
        realTarget = target
        -- Accept the most recent button press.
    end
end

One interesting difference between this and the debounce above is that this will still hear when you press. It just waits until it's done, and then does it. (You could, with the above system, do this by instead repeat wait() until canCall, but this would be a problem if multiple buttons were pressed in that time -- since they might all start more or less at the same time but don't check the debounce -- or, worse, make a big stack of different locations to track to -- so the elevator would be "frozen" in an odd path for however many times people pressed buttons)


Real-er elevator?

I would like to think that real elevators aren't so dumb. I will write more about this shortly.

Here is what I would suggest a real elevator does:

Keeps a list of all floors that need to be visited. A floor needs to be visited because either it was called to that floor, or because that floor was indicated while inside the elevator. I am not going to make any distinction about priority between the two types of calls, though you could if you wanted to.

Whenever a floor that needs to be visited is passed, stop and open the doors -- then continue on.

Here is what it might look like:

-- finds `val` in table `tab`, returning position found
-- warning: false is a valid key.
-- Returns `nil` when not found.
function find(tab, val)
    for i,v in pairs(tab) do
        if v == val then
            return i
        end
    end
end

local visits = {} -- Floors to visit
-- Guaranteed to not contain repeats of any value

function callTo(ty)
    if not find(visits, ty) then
        -- If the list doesn't already contain this target,
        -- then add it.
        table.insert(visits, ty)
    end
end


local target = y -- Ground floor?

while true do
    wait()
    if find(visits, y) then
        -- I'm on a floor that's wanted!
        -- (Thus the elevator will stop on its way rather than
        -- go all the way up then back down to floors in
        -- the middle)

        open = true -- Open doors
        wait(1)
        open = false -- Close doors

        table.remove(visits, find(visits, y))
        -- remove this floor from the list to visit
    end
    if y == target then
        if #visits > 0 then
            target = table.remove(1) -- Attend to oldest first.
        else
            -- No floors to visit. Stop and wait
            velocity = 0
        end
    end
end
0
My elevator is extremely realistic if u want to see then here is a link to my place http://www.roblox.com/Building-place?id=205928773 nich17 95 — 9y
0
this is still alittle confusing on what this script does because I need to know how to combine it with my existing script nich17 95 — 9y
0
This is sort of "pseudocode" -- it doesn't do anything on its own (I just set `velocity`, `open`; read `y`, etc which would probably *actually* be modifying properties of objects or calling functions). It's well explained and fairly simple so you should be able to implement it (or derivations of it) if you know any Lua. Given that you gave *no* details of what you were working with... If you have BlueTaslem 18071 — 9y
0
ok thank you i thought this was like more actual code than pseudo code and the only confusing part is the first 2 functions at the beginning i haven't really gone into that part of lua yet being a fairly new scripter nich17 95 — 9y
Ad

Answer this question