ID:138856
 
Code:
[Code...]

turf
icon = 'Sectors.dmi';
var/contains[0]
New()
..()
contains["1"] = list()
contains["2"] = list()

[Code...]

[Code...]

Entered(obj/units/A, atom/B)
if(!istype(A, /obj/units))return 1
contains["[A.color]"] += A//***************LINE: 119***************/
world<<"Debug: [contains[1]], [contains[2]], [A.color]"
if(A.prev_loc)
var/turf/t = A.prev_loc
var/list/L = t.contains["[A.color]"]
if(L == null)
var/turf/r = locate(x, y, z)
for(var/c in colors_in_use)r.contains[c] = list()
for(var/obj/units/o in r)
world<<"Debug: [r.contains[1]], [r.contains[2]], [o.color]"
r.contains["[o.color]"] += o//***************LINE: 129***************/
//world<<"NULL!"
return 1
L -= A//***************LINE: 132***************/
t.contains["[A.color]"] = L
//else world<<"ADGGAD"
A.prev_loc = src
..()


ideally turf/Entered() would look like this:
    Entered(obj/units/A, atom/B)
if(!istype(A, /obj/units))return 1
contains["[A.color]"] += A
A.prev_loc.contains["[A.color]"] -= A
A.prev_loc = src


Problem description:

This code works most of the time but every now and again it gets an error that makes the list think it's an obj/unit1 obj.
It happens in a few places. I've tried everything I can think of to fix it. I even remake the lists just above line 129.


Here are the errors:

runtime error: type mismatch: the unit1 (/obj/units/unit1) += the unit1 (/obj/units/unit1)
proc name: Entered (/turf/Entered)
source file: Sectors.dm,119
usr: 0
src: the turf (6,7,1) (/turf)
call stack:
the turf (6,7,1) (/turf): Entered(the unit1 (/obj/units/unit1), the turf (7,7,1) (/turf))
gameTimer()
: New()
runtime error: type mismatch: the unit1 (/obj/units/unit1) -= the unit1 (/obj/units/unit1)
proc name: Entered (/turf/Entered)
source file: Sectors.dm,132
usr: 0
src: the turf (6,9,1) (/turf)
call stack:
the turf (6,9,1) (/turf): Entered(the unit1 (/obj/units/unit1), the turf (6,8,1) (/turf))
gameTimer()
: New()
runtime error: type mismatch: the unit1 (/obj/units/unit1) += the unit1 (/obj/units/unit1)
proc name: Entered (/turf/Entered)
source file: Sectors.dm,129
usr: 0
src: the turf (6,7,1) (/turf)
call stack:
the turf (6,7,1) (/turf): Entered(the unit1 (/obj/units/unit1), the turf (7,7,1) (/turf))
gameTimer()
: New()

Here is some code that is called when I create a new units using turf.MouseDown():
                [Code...]
if(rand(1, 2) == 1)
o.icon_state = "Unit1"
o.color = 1
else
o.color = 2
o.icon_state = "Unit2"
o.loc = locate(x, y, z)
o.prev_loc = src
o.destination = null
o.step_x = rand(10, 54)
o.step_y = rand(10, 54)
usr.units += o
var/turf/t = locate(x, y, z)
t.contains["[o.color]"] += o


When I remove lines 264 through 286 from GameTimer I don't get any of those errors. I need those lines for units to be able to combat each other. I don't see how those lines are messing things up.

Here is GameTimer, it is called once when the games starts:

proc/gameTimer()
set background = 1
//var/count = 0
while(1)
//count++
for(var/obj/units/o in active_units)
//if(count % 10 == 0)o.direction = pick(NORTH, EAST, SOUTH, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST)
if(o.destination)
if(o.loc == o.destination)
var/list/dirs = list()
if(o.step_y > 32)
if(o.step_x > 10)dirs += SOUTHWEST
if(o.step_x < 54)dirs += SOUTHEAST
if(o.step_x > 10 && o.step_x < 54)dirs += SOUTH
if(o.step_y < 32)
if(o.step_x > 10)dirs += NORTHWEST
if(o.step_x < 54)dirs += NORTHEAST
if(o.step_x > 10 && o.step_x < 54)dirs += NORTH
if(o.step_x > 32)
if(o.step_y > 10 && o.step_y < 54)dirs += WEST
if(o.step_x < 32)
if(o.step_y > 10 && o.step_y < 54)dirs += EAST
if(dirs.len > 0)
o.direction = pick(dirs)
o.destination = null
else step_towards(o, o.destination, rand(o.spd - 1, o.spd + 1))
else
step(o, o.direction, o.spd)
var/move_on = FALSE
for(var/c in colors_in_use)if("[o.color]" != c)//***************Line: 264******************/
if(move_on)break
for(var/obj/units/A in o.prev_loc.contains["[c]"])if(o.color > 0 && A.color > 0 && o.color != A.color)
o.hp -= A.atk
A.hp -= o.atk
if(A.hp <= 0)
A.prev_loc.contains["[A.color]"] -= A
A.color = 0
A.icon_state = ""
if(A.owner)
A.owner.units -= A
A.owner = null
inactive_units += A
active_units -= A
if(o.hp <= 0)
o.prev_loc.contains["[o.color]"] -= o
o.icon_state = ""
o.color = 0
if(o.owner)
o.owner.units -= o
o.owner = null
inactive_units += o
active_units -= o
move_on = TRUE
break//***************Line: 289******************/
sleep(5)
Zaltron wrote:
Code:
> [Code...]
>
> turf
> icon = 'Sectors.dmi';
> var/contains[0]
> New()
> ..()
> contains["1"] = list()
> contains["2"] = list()
>
> [Code...]
>
> [Code...]
>
> Entered(obj/units/A, atom/B)
> if(!istype(A, /obj/units))return 1
> contains["[A.color]"] += A//***************LINE: 119***************/
> world<<"Debug: [contains[1]], [contains[2]], [A.color]"
> if(A.prev_loc)
> var/turf/t = A.prev_loc
> var/list/L = t.contains["[A.color]"]
> if(L == null)
> var/turf/r = locate(x, y, z)
> for(var/c in colors_in_use)r.contains[c] = list()
> for(var/obj/units/o in r)
> world<<"Debug: [r.contains[1]], [r.contains[2]], [o.color]"
> r.contains["[o.color]"] += o//***************LINE: 129***************/
> //world<<"NULL!"
> return 1
> L -= A//***************LINE: 132***************/
> t.contains["[A.color]"] = L
> //else world<<"ADGGAD"
> A.prev_loc = src
> ..()
>


I didn't have time to read much beyond this snippet, but see if the following modification helps any. If not I'll try to analyze it more later when I actually have time:
    Entered(obj/units/A, atom/B)
if(!istype(A, /obj/units)) return 1
// Validate that contains["[A.color]"] exists and is a list:
if(!contains.Find("[A.color]") || !istype(contains["[A.color]"], /list)) contains["[A.color]"] = new/list
contains["[A.color]"] += A
if(A.prev_loc)
var/turf/t = A.prev_loc
var/list/L = t.contains["[A.color]"]
L -= A
if(L && !L.len)
L = t.contains["[A.color]"] = null
A.prev_loc = src
..()

The checks I added are indeed a lot of overhead for normal operation but if they fix it then it just shows the lists are being built or destroyed improperly somewhere.
In response to Hiead
It doesn't like to think that a list even exists.

If you're willing to examine it further I can send you the source with instructions of how to recreate the bug.

    Entered(obj/units/A, atom/B)
if(!istype(A, /obj/units)) return 1
// Validate that contains["[A.color]"] exists and is a list:
if(!contains.Find("[A.color]") || !istype(contains["[A.color]"], /list)) contains["[A.color]"] = new/list
contains["[A.color]"] += A
if(A.prev_loc)
var/turf/t = A.prev_loc
var/list/L = t.contains["[A.color]"]
L -= A//**********************Line: 126*******************/
if(L && !L.len)
L = t.contains["[A.color]"] = null
A.prev_loc = src
..()


runtime error: type mismatch: null -= the unit1 (/obj/units/unit1)
proc name: Entered (/turf/Entered)
source file: Sectors.dm,126
usr: 0
src: the turf (5,8,1) (/turf)
call stack:
the turf (5,8,1) (/turf): Entered(the unit1 (/obj/units/unit1), the turf (5,7,1) (/turf))
gameTimer()
: New()
In response to Zaltron
Have you tried something like.
var/list/loaded_list = contains["[A.color]"]
loaded_list += some_thing


Also, don't use this on anything with an overly large map, you're creating TWO lists for every turf in the game, so you'll crash things pretty quickly if you start placing a ton of turfs. As a rule it's pretty unwise to create any kind of list() under the /turf type.
In response to Nadrew
Nadrew wrote:
Have you tried something like.
> var/list/loaded_list = contains["[A.color]"]
> loaded_list += some_thing
>

Also, don't use this on anything with an overly large map, you're creating TWO lists for every turf in the game, so you'll crash things pretty quickly if you start placing a ton of turfs. As a rule it's pretty unwise to create any kind of list() under the /turf type.

Yeah, I've tried that, still can't get it to work. The map is a 10x10 grid - 4.
In response to Zaltron
Obviously moving the if(L) part of the check would fix the immediate error, but I don't understand why A.prev_loc should ever be not-null if t.contains["[A.color]"] is null---I suspect related code or potentially the typo that I spotted:
L = t.contains["[A.color]"] = null
Oops, my bad...shouldn't write in a hurry.

If you want me to take a look at it, I should probably be able to find some time tonight to do so. xhiead via gmail.
In response to Hiead
Sent, thanks for taking a look.
In response to Zaltron
After reviewing the code, I think this is the simplest fix. I've also tested it various times with the scenario you provided and have yet to make it fail:
    Entered(obj/units/A, atom/B)
if(istype(A))
contains[A.color] += A

Exited(obj/units/A, atom/B)
if(istype(A))
contains[A.color] -= A

Please let me know if that doesn't solve your problem for you.