Page 1 of 1

Runaway loop error annoyance...

Posted: Sun May 08, 2011 9:42 pm
by blubswillrule
Hey guys, I've been' having this major problem with my ai for a mod of mine, and I cannot figure out what is wrong for the life of me!

The ai is basically following the AStar algorithm for pathfinding (in case anyone here knows about it)

The function looks for waypoint with a .link of "OPEN", and the lowest F value, and it looks at all the waypoints on the map.

Code: Select all

entity(entity treeb) find_open = 
{
	local entity way;
	local float fbest;
	local entity best;
	fbest = 10000;
	way = find(world,classname, "waypoint");
	self.loopcount = 0;
	while(way)
	{
                /////////////////////////////////
		if(self.loopcount > 300)
		{
			bprint("find_open-loopcount max! \n");
			self.loopcount = 0;
			return(world);
		}
			self.loopcount = self.loopcount + 1;
                /////////////////////////////////
		if(way.link == "OPEN")
		{
	        	if(way.F < fbest)
		        {	
		        	fbest = way.F;
		        	best = way;
		        }
		}
		way = find(way, classname, "waypoint");
	}
	
	return(best);
};
This code will spontaneously crash with a runaway loop error, even though I added something to counter that (limiting the loops to 300, when the quake limit is something like 10000 )

Could anybody please help?

Thanks.

Posted: Sun May 08, 2011 10:08 pm
by Spike
that code is not an infinite loop.

check where its called from, you might find the parent function is the looper, or just really expensive.

Posted: Sun May 08, 2011 10:12 pm
by frag.machine
For a start, I suggest not using an entity field as break condition for your loop. Use a local var instead.

Also, in the case of path finding, may be a good idea to adapt the code to use findradius() instead.

Posted: Mon May 09, 2011 9:39 pm
by blubswillrule
I tried using a local float, but it still gets the runaway loop error

What is realy interesting is how can it get a runaway loop error if it should only run 300 times then stop.
(it technically should only run like 60 times, that's the average amount of waypoints on a map)

Also, as for findradius...

this find_open function is for finding the path basically, so it won't exactly run from the ai's perspective...

unless you had some other form of using it in mind.

Posted: Tue May 10, 2011 12:58 am
by frag.machine
blubswillrule wrote:I tried using a local float, but it still gets the runaway loop error

What is realy interesting is how can it get a runaway loop error if it should only run 300 times then stop.
(it technically should only run like 60 times, that's the average amount of waypoints on a map)

Also, as for findradius...

this find_open function is for finding the path basically, so it won't exactly run from the ai's perspective...

unless you had some other form of using it in mind.
Its not like using find() wouldn't work, absolutely. It's just that if you're creating a function that does something like "here, take this waypoint entity and find the nearest similar one" a findradius() would chop off all too far entities, engine-side. Besides, findradius() isn't restricted to AI aspects (although finding a waypoint may be considered part of AI).

To ensure your code is actually being interrupted below 300 interactions, you may want to use this instead:

Code: Select all

(...)
loopcount = 0;
way = find(world, classname, "waypoint");
while((way) && (loopcount < 300))
{
    (...)
    loopcount = loopcount + 1;
    way = find(way, classname, "waypoint");
}
(...)

Posted: Tue May 10, 2011 3:46 am
by andrewj
blubswillrule wrote:What is realy interesting is how can it get a runaway loop error if it should only run 300 times then stop.
You misunderstand the runaway error. It is a limit on instructions and applies to all the code that gets executed once the engine starts running some QuakeC code -- not just the code in a single function.

As Spike said, it's not the find_open() code which is the problem (or main problem) but the parent function which calls it. The combination of them both will be causing the limit to be hit.

Posted: Sun May 15, 2011 1:02 am
by blubswillrule
Well guys, I've hit a brick wall with this... yet again, I now understand that I get this because of everything going on at once, and heres the details...

average number of waypoints in a map ~ 60

find_open is in another while statement.
(this while statement varies on how much it runs, the ideal testing condition would be it running once per waypoint on a map (it won't always use every waypoint)

so, theoretically, within a single frame, the while statement in find_open is being ran 3600 times, (not sure if it's enough to cause a runaway loop error on a psp)


Also, I ONLY EVER get a runaway loop error on psp, NEVER on pc (obviously due to different runaway loop # limits (darkplaces's is 10,000,000?))

Frankly, this bug is extremely annoying.

I was looking through the frikbot source, and they had an interesting comment there. (something along the lines of) "use thinks to avoid triggering the runaway loop counter"

I have tried to make my pathfinding use thinks, but have failed miserably, could anyone lend a hand please?

Posted: Sun May 15, 2011 3:38 am
by Arkage
The limits a 100000 on the psp.
If you want to bump it up its line 372 ish in pr_exec.c.

Posted: Sun May 15, 2011 4:21 am
by blubswillrule
would bumping it up cause any undesired results?

Since nothing else causes a runaway loop error, they'll stop way before going too high up the count... so the only function to go up that high would be these.

Posted: Sun May 15, 2011 6:19 am
by Spike
increasing the limit is fairly safe

removing it entirely won't break anything either, except that if a mod does go wrong the user will need to end-task, which shouldn't happen anyway. same problem as an unreasonably high limit.

the limit is already fatal, the map will be killed.

really the value should be in seconds-on-the-lowest-reasonably-specced-computer, which means the ideal limit changes over time. bumping the limit is consistant with that. even if the limit is fairly generous, its not too bad.

Posted: Mon May 16, 2011 9:40 pm
by necros
i haven't seen the frikbot code, but probably what he meant by 'use thinks' is he is deferring some of the while loop to another frame.

for example, if you use find(), you can tell it to loop only 10 times then at the end of the loop, store the last entity in a field until next frame, then, next frame, instead of starting your find() at world (the start of the list), feed in that stored entity field, and you'll basically pick up where you left off.

spreading out large loops in thinks can speed things up too, because if you have multiple loops going on that are extensive, they may not trip the runaway loop error (because they are spread out in multiple loops) but you'll be able to see a visible slow down as the engine is looping through all those instructions.

Posted: Mon May 16, 2011 10:28 pm
by blubswillrule
yeah, I couldn't get thinks to work for the life of me, haha, the hardest part was getting the ai to recognize where it left off...

but anyways, raising the runaway loop counter to 1,000,000 worked :D

thanks guys!

Posted: Tue May 17, 2011 2:45 pm
by Jukki
YEah. while making it so that there is a lagspike where used to be crash