Page 1 of 2

Hit a snag: "max recourse limit reached"

Posted: Fri Apr 29, 2016 3:12 pm
by wolph42
While working on the random dungeon generator I had to make use of a recursive function, which to my surprise rendered the above error. Is this a java limitation or a maptool limitation, and if the latter, can it be circumvented (if its the former actually the same question...

additional note: when that happens, I need to restart mt as everything I do from then on gives the same error!

Re: Hit a snag: "max recourse limit reached"

Posted: Fri Apr 29, 2016 4:29 pm
by aliasmask
max "recourse"? I do know that there is a limit to recursive calls to avoid infinite loops. I'm not sure if I tested this before, but it may be 1000 iterations like with other loops or a depth limit (limit in the number of open callbacks). I do believe it is handled by java.

Re: Hit a snag: "max recourse limit reached"

Posted: Fri Apr 29, 2016 7:39 pm
by Jagged
Yes,this is a Maptool limitation and nothing new. So I would expect you to experience the same result from the previous build.

It probably is something we should consider removing or increasing.

Re: Hit a snag: "max recourse limit reached"

Posted: Sat Apr 30, 2016 4:58 am
by wolph42
Forgot to tell you that this was in 1.91, but as with the max loop limit, not something I expected to have changed in 1.4
I would be in favor to increase the loop limit to 10000, I don't know what the recursive limit is

Re: Hit a snag: "max recourse limit reached"

Posted: Sat Apr 30, 2016 8:15 am
by Full Bleed
Jagged wrote:Yes,this is a Maptool limitation and nothing new. So I would expect you to experience the same result from the previous build.

It probably is something we should consider removing or increasing.
With regard to the loops... Wondering if this should be a setting somewhere with the default being 1-2K. That would probably suit the majority of users.

I worry about opening things up to 10K and people getting themselves caught in loops and thinking that MT is being unresponsive. And I suspect that once the increase was made to 10K it would only be a matter of time before someone wished they had 20k. ;)

Re: Hit a snag: "max recourse limit reached"

Posted: Sat Apr 30, 2016 8:45 am
by wolph42
Actually Ive already build a function that allows me 1,000,000 loops, so far I've never gone over 10,000. So no if you up the limit to 10k it will not be a matter of time for more.

That said, I wouldn't mind a setting however I already see the mess this would end in as I make something for eg 5k loops and every user has set it to default of 1k. That and the error in the chat will not show that error so no one knows why it does not work.

The only way to omit this is a function that sets max loops, but then it starts to become silly and redundant

Re: Hit a snag: "max recourse limit reached"

Posted: Sat Apr 30, 2016 11:37 am
by Full Bleed
wolph42 wrote:So no if you up the limit to 10k it will not be a matter of time for more.
That's a pretty bold statement (to assume that since you've never wanted more than 10k that no one else could come up with a reason for more)! Reminds me of statements people make about how much memory, storage space, or resolution they'd ever need (i.e. they're never right... in 5-10 years "too much" has a sneaky way of becoming "not enough").
That said, I wouldn't mind a setting however I already see the mess this would end in as I make something for eg 5k loops and every user has set it to default of 1k. That and the error in the chat will not show that error so no one knows why it does not work.
I would assume that it would have to be a campaign setting to assure consistency.

Re: Hit a snag: "max recourse limit reached"

Posted: Sat Apr 30, 2016 2:27 pm
by aliasmask
Campaign setting or java switch would be nice. There are a couple of times where dealing with the 1000 limit has been a pain. Mostly when dealing with parsing of data and creating databases.

Re: Hit a snag: "max recourse limit reached"

Posted: Sat Apr 30, 2016 4:41 pm
by JamzTheMan
How about the dialog approach? I'm sure the setting was to either prevent memory over usage or infinite loop times.

Maybe turn the limit off and instead "watch" the macros and pop up a dialog after x seconds, "This macro has been running excessively long, do you wish to kill it?" and if you say no, restart the timer.

If you run out of memory, well, you already will get a OOM error. Computers are way faster with more memory than they were when MT was first written, making up for some of the shortcomings the script engine has. If someone has 16gb ram and 8 or more cores, i say let em abuse em lol

Re: Hit a snag: "max recourse limit reached"

Posted: Sat Apr 30, 2016 5:22 pm
by wolph42
I like the idea of campaign settings, although this would not work with drop ins like the BoT. I certainly don't like the timer as I have many routines that can run for minutes, such a thing would require the user to keep an eye on the monitor.

Perhaps set the default to 10k and have the option to change the max loop limit.

If it's a changeable setting I'm most in favor to have it as a function that sets it for the campaign and when changed it forces a popup on the user screen explaining why is required and what the repercussions are. This thus also requires another function checkLoopLimit () so you can use an if() to prevent the pop up every time.

So
1. Change default to 10k
2. setLoopLimit (number, whyString): changes it for campaign. Shows repercussions text always.
3. checkLoopLimit () checks it for campaign.

Re: Hit a snag: "max recourse limit reached"

Posted: Sun May 01, 2016 1:06 am
by Craig
I have created the following changes that will go into the next build.

Increased max recursion depth by 50% (to 150).
Increased max loop iterations to 10,000
Added the following macro functions to query/set parser properties.
  • getMaxRecusionDepth()
  • getRecursionDepth()
  • getMaxLoopIterations()
  • setMaxRecusionDepth(<value>)
  • setMaxLoopIterations(<value>)
  • getMacroContext() -- Returns information about the source, name, index of the button of the macro being executed as a JSON object.
Some notes/things to keep in mind.
  • The recursion depth of the parser is not quite straight forward, there are actually two different recursion depths that track two different types of recursive call, you can have up to 150 of each, the getRecursionDepth() will return the greater of the two levels.
  • Small increases in max recursion depth can cause stack problems (that is why I didn't increase it more than 50).
  • If you change the Max Loop Iterations or the Max Recursion Depth it only lasts until you restart MapTool, its not saved to the campaign or MapTool settings.
  • You can not use either of the set functions to set the levels below the default values (because allowing you to do so could really screw things up if you have a bug and set it very low). You can use this fact to reset to default values with setMaxRecursionDepth(0), setMaxLoopIterations(0).

Re: Hit a snag: "max recourse limit reached"

Posted: Sun May 01, 2016 5:12 am
by Jagged
Wow Craig. You had one hell of a productive day :mrgreen:

Great job.

Re: Hit a snag: "max recourse limit reached"

Posted: Sun May 01, 2016 5:38 am
by wolph42
Craig wrote:I have created the following changes that will go into the next build.

Increased max recursion depth by 50% (to 150).
Increased max loop iterations to 10,000
Added the following macro functions to query/set parser properties.
  • getMaxRecusionDepth()
  • getRecursionDepth()
  • getMaxLoopIterations()
  • setMaxRecusionDepth(<value>)
  • setMaxLoopIterations(<value>)
  • getMacroContext() -- Returns information about the source, name, index of the button of the macro being executed as a JSON object.
Some notes/things to keep in mind.
  • The recursion depth of the parser is not quite straight forward, there are actually two different recursion depths that track two different types of recursive call, you can have up to 150 of each, the getRecursionDepth() will return the greater of the two levels.
  • Small increases in max recursion depth can cause stack problems (that is why I didn't increase it more than 50).
  • If you change the Max Loop Iterations or the Max Recursion Depth it only lasts until you restart MapTool, its not saved to the campaign or MapTool settings.
  • You can not use either of the set functions to set the levels below the default values (because allowing you to do so could really screw things up if you have a bug and set it very low). You can use this fact to reset to default values with setMaxRecursionDepth(0), setMaxLoopIterations(0).
Well that's one way of short cutting the discussion :).

Mucho thanks for the swift action. Also good to know that the recursion limit was set to 100, that explains a lot.

Re: Hit a snag: "max recourse limit reached"

Posted: Sun May 01, 2016 5:45 am
by aliasmask
Recursion is typically used to traverse a tree-like structure where 100 is plenty. The one method where I think 100 could be too little is something like searching a maze where the path has more than 100 squares or points to check along a path. Wolph42, how were you using your recursion?

Re: Hit a snag: "max recourse limit reached"

Posted: Sun May 01, 2016 6:15 am
by wolph42
aliasmask wrote:Recursion is typically used to traverse a tree-like structure where 100 is plenty. The one method where I think 100 could be too little is something like searching a maze where the path has more than 100 squares or points to check along a path. Wolph42, how were you using your recursion?
"*are* using".

random dungeon generator. I've already have a field with randomly generated room in it. now im trying to create paths between the rooms. Starting in one room and going in a random direction (recursively) until another room is found. Repeat for all rooms. I've thought of at least 5 other methods, but this is the one I would like to get working first.

as for how...
-pick a random point in first room.
-choose a random direction: N/E/S/W.
-Create an array with all four directions,
while empty corridor OR !all 4 direction checked
-pick the direction randomly chosen (get that coord)
- check coord is 'ok' (that is: no edge of dungeon)
- recursive function: corridor = nextCoord(coord, other stuff)
end while

<!-- start recursive function: nextCoord() -->
- add coord to 'corridor array'
- low random chance that direction changes
- create array of 3 adjacent coords
- pick coord of cell in the current direction
- check if is 'ok'. If not return empty corridor ; if it is corridor = nextCoord(coord)
- return corridor

its a bit more complex e.g. not 1 but 2 steps at the time to limit the required recursions. if a corridor fails, fall back to the point where the direction changed, pick the next direction and try again from that point onward until all 3 directions have been tried.

currently debugging. so far I've either hit bugs OR recursive limit.
Recursive loops give me head-aches...

if all fails:

Other ideas:
- not doing it recursively but using a forward 'defer' loop, remembering the 'direction change nodes' on which you can fall back and try again from there on. That however is WAY trickier, but theoretically should give infinite amount of trial on error
- plot a straight corridor from S to N and simply plot corridors from that one to the room in a straight line (not pretty but effective)
- pick two rooms, pick two coords from those room and simply plot the shortest path between those two (potentially going around other rooms or not)