ID:1843756
 
Code:
proc/r_time(usrip,oppip)

set background = 1

RTIME += "[usrip] - [oppip]"

var/timer = 18000

while("[usrip] - [oppip]" in RTIME)

timer--

if(!timer||timer<0)
RTIME -= "[usrip] - [oppip]"
sleep(1)
return


Problem description:

This is a code im using to prevent players from feeding wins to other players for a ranking system. When they start a match it runs this. Adds both of their IP's to a list. Keeps them on the list until the timer is done. And then removes them. While they're on this list they cant have a ranked match against each other.

Sleep runs in 10ths of a second as far as I'm aware... so a timer of 18000 here should run for 30 minutes right? It seems to be running for approximately 12 minutes though.

Am I overlooking something here?
I've used timers before with no issues like this but this is the longest one I've used I think.

My fps is currently set for 14. That hasn't changed in a long time.
Actually wow, now that I actually go back and look at it. It seems like even my mute command wasn't actually following the correct timer. I'm going to have to readjust the timers.

So what's the relationship between FPS and how quick the sleep proc lasts?

sleep(1) actually lasts how long? since the help files indicate it lasts for 1/10th of a second.
Well going by the reference, Sleep(value) sleeps by a time period of value/10 seconds like you said, so the issue shouldn't be that.

Maybe it's to do with nesting a sleep within a while, perhaps that's messing things up? i haven't given it much thought though.
Eitherway what i'd suggest, is to just change how you're doing this, and instead have the players removed from the RTIME variable once world.time was >= match start time + 30 minutes(timer value). Think that is probably the nicer way.
Just to add also perhaps your
set background = 1
plays a part, i'm not sure how exactly it all factors in, but going off this from the help description

"To avoid lag from procedures that hog the CPU for too long, you can turn on background processing. This will cause it to periodically sleep for long enough to allow other events to be processed. "

This is possibly messing up the intended behaviour of the proc. I have a guess as to how it might maybe affect this, but i'm not sure at all so i'm not going to make assumptions on this one. Try removing the line and see how it goes from there.
Im actually a new coder. I took over a game from someone else so I'm still learning everything. It does seem to be the while loop that's causing it. I've neatened up this code a bit.

proc/r_time(usrip,oppip)

RTIME += "[usrip] - [oppip]"
sleep(18000)
RTIME -= "[usrip] - [oppip]"
return

seems to work better.
Turboskill pretty much hit the nail on the head I think. Setting background doesn't do what you think it does. There was also a lot that didn't need to be there, it was a really round-about way of doing it but we're all new at some point.

What you were actually looking for was spawn(), not set background.

proc/r_time(usrip,oppip)

// Branch off, run what's spawned simultaniously
spawn()

RTIME += "[usrip] - [oppip]"

// Wait 30 minutes
var/timer = 18000
while(timer > 0)

sleep(1)
timer--

RTIME -= "[usrip] - [oppip]"


If you wanted to be a really good programmer you could write a helper method so you don't have to keep writing timing processes all the time.

proc/r_time(usrip,oppip)

// Branch off, run what's spawned simultaniously
spawn()

RTIME += "[usrip] - [oppip]"
wait(18000)
RTIME -= "[usrip] - [oppip]"

proc/wait(MILLISECONDS)

var/timer = MILLISECONDS
while(timer > 0)

sleep(1)
timer--


I hope that helps. I compiled it but didn't run it. I'm 99% sure that should work fine.
In response to IceFire2050
IceFire2050 wrote:
Im actually a new coder. I took over a game from someone else so I'm still learning everything. It does seem to be the while loop that's causing it. I've neatened up this code a bit.

Haha yes, that's the most efficient arrangement but you'll still want to spawn that I'm pretty sure. Also return isn't needed. It automatically returns when it reaches the end of the method.

proc/r_time(usrip,oppip)

RTIME += "[usrip] - [oppip]"
spawn(18000)
RTIME -= "[usrip] - [oppip]"


I dont really understand what the difference between sleep and spawn would be here.

From what I can see...

sleep waits the set amount of time before proceeding through the code.

spawn waits the set amount of time before executing the nested statement.

Is there an actual difference here aside from having to use indentation on one?
In response to IceFire2050
The difference is that the procedure you called r_time from will continue. Using sleep the procedure you called r_time from can't continue until r_time has finished sleeping.
Ah, I see. I hadn't noticed that since calling this is the last step in the proc that calls it.
Ah right
Just a quick question. Why not do something like this?

mob/verb/Timer(secs as num)
var/now = world.timeofday
secs = secs * 10
while(now < secs)
sleep(10)
continue


And if you wanted the time, you could divide the difference between now and secs by 10. This isn't tested. Just a theory to make things a bit less dependent on how a loop will work. Whether or not a loop iterates in time doesn't matter. Because your endgoal is predetermined and TIME itself becomes your loop control variable.

If you want to get the time outside of the verb, simply make the secs variable outside of it and do what I said to get the difference. Also, store the start time, now, outside of the verb too.
In response to Xirre
With world.timeofday you have to plan for wrapping. Even if the code was correct, you'd still need to account for the fact that at some point, world.timeofday-start would be negative--it's entirely possible to have a loop run forever if you don't account for that.
In response to Lummox JR
I think what I did in my "Which loop is efficient" post was I added to the world.timeofday.

----

http://www.byond.com/forum/?post=1769348#comment13730260

So just set secs to world.timeofday and add (input value * 10) to secs. When world.timeofday equals secs, then the time has passed. To get the remaining time, just get the difference and divide by ten. To compensate for negatives, get the absolute value of them I guess?
In response to Xirre
Xirre wrote:
So just set secs to world.timeofday and add (input value * 10) to secs. When world.timeofday equals secs, then the time has passed. To get the remaining time, just get the difference and divide by ten. To compensate for negatives, get the absolute value of them I guess?

Absolute value would be incorrect; you would need to add one day's worth of time to a negative value.

You can't do an equality check, because if for any reason execution skips past the time you want, you're doomed to wait one more day. This is similar to why you can't start at 1, subtract 0.1 in a loop, and wait for it to equal zero--rounding errors can screw you over.

To do this correctly, at each check you should subtract the start time from world.timeofday. If the result is negative, add 864000 (one day, in standard ticks). Then compare that to the duration; you're finished if the difference is equal to or greater than the duration.