ID:1232608
 
Keywords: bad, loc, proc, spawn
(See the best response by Stephen001.)
Code:
proc
topGenerator()
var/turf/Dirt/origin = new(locate(100,100,1))
for(var/iy=3; iy; iy--)
spawn(-1) Generation(origin)
var/Odir=pick(NORTH,SOUTH,WEST,EAST)
for(var/i=(15+rand(-10,10)); i; i--)
origin = get_step(origin,Odir)

Generation(var/turf/origin)


Problem description:
Every now and again, perhaps 30% of the time I run topGenerator(), it comes up with an error message or two.

runtime error: bad loc
proc name: Generation (/proc/Generation)
source file: generator.dm,26
usr: Guest-3154373468 (/mob)
src: null
call stack:
Generation(Sand (121,100,1) (/turf/Sand))
topGenerator()
topGenerator()
Guest-3154373468 (/client): NewGame()
Guest-3154373468 (/client): NewGame()
runtime error: bad loc
proc name: Generation (/proc/Generation)
source file: generator.dm,26
usr: Guest-3154373468 (/mob)
src: null
call stack:
Generation(Dirt (121,76,1) (/turf/Dirt))
topGenerator()
topGenerator()
Guest-3154373468 (/client): NewGame()
Guest-3154373468 (/client): NewGame()


Now I'm pretty sure this is due to multiple 'entities' of Generation trying to access the same location.

Line 26 is:
                var/turf/Dirt/temp = new(location)

and occurs within Generation().

The reasoning for the spawn(-1) is due to the Help Guide saying "If delay is negative, the spawned code is executed before continuing in the main code." though it doesn't seem to help a lot. That said, it is not the cause of the errors as it was only added as a countermeasure to them occurring beforehand.
Can you show us the contents of Generation()? Specifically, where the location variable is defined/assigned.
Can you post how exactly you get the location variable that you used in line 26?

EDIT: Yeah, what he said. ^
In BYOND, your code is run in one thread of execution. As such, you cannot ever get two procedures accessing the same variable or making co-modification of some data. So you can rule out two executions of generation accessing the same thing at the same time.

The issue will be more to do with whatever Generation() is doing, and the kind of data it is receiving. As SSX notes, we could do with seeing what Generation() does.
Of course,

    Generation(var/turf/origin)
var/dirt = 450+rand(-50,50)
var/numOfDice=4
var/sidesOnDice=19
var/subtractor = sidesOnDice*numOfDice/2

while(dirt) //Place 'dirt' number of dirt tiles. Make them grass if the dirt tile exists there already.
var/turf/location = locate(origin.x+roll(numOfDice,sidesOnDice)-subtractor,origin.y+roll(numOfDice,sidesOnDice)-subtractor,1)
if(istype(location,/turf/Grass))
dirt--
continue
if(istype(location,/turf/Dirt))
new /turf/Grass/ (location)
else
var/turf/Dirt/temp = new(location)
dirt--


Although I must confess I have hidden a few select lines than I don't want released to the masses. I'm 99.9% certain they don't affect the erroneous lines, but just keep that in mind. I know you're all trying to help and as such I should do my utmost to facilitate that (and I really appreciate it), but with that said there are a lot of other newbies scanning these forums for "neat codes" to copy and paste.

The rest of the proc all happens after and outside of that while() loop.
Stephen001 wrote:
Which line would be line 26?

Line 26 is:
                var/turf/Dirt/temp = new(location)

and occurs within Generation().


Have you tried some general debugging techniques?
In that else statement, simply world << location?

Best response
I suppose it would be possible that your roll()s have pushed the x or y value in locate() past the edge of the map, thus giving you a null value? Placing a turf on a null location would certainly be something I consider a "bad loc".
Might need to call min(world.maxx, roll()) instead of just roll().
I had thought that, and I will try it when I am next back at my machine, but my reasons for not doing this yet is that the world is 150x150 and the co-ords given in the error message are always within that.
In the error message? In the stack trace?
That's the turf passed to Generation() as the origin argument, not the location.
In response to Super Saiyan X
Super Saiyan X wrote:
In the error message? In the stack trace?
That's the turf passed to Generation() as the origin argument, not the location.

You are indeed right, I had forgotten that "origin" moved after each Generation(). I've now added min() and run it 10 times and the error hasn't reoccurred, so that must have been the issue. Curious though that I've never noticed the island reaching the edges of the map before though...
Just a random thought. You have this:
var/dirt = 450 + rand(-50,50)


Is there any particular reason you don't do this?
var/dirt = rand(400,500)
Obviously my way is a bajillion times better...

Just kidding. Originally it was just 450 but at a later date I increased the randomness of the entire generator... and I was a little lazy :P Thank you for pointing it out though Albro1 ^_^