ID:138409
 
Okay I seem to have quite unintentionally pushed some Dantom buttons about Move(), so here are some details about how I'm using it and why, and we can see what makes sense and what doesn't.

At first, as Dan would expect, I was a good little object boy and only used Move(), having a deep aversion to touching instance variables directly (they have germs you know). Don't get me started on what it does to my brain to use F.cd as a function, or not be able to intercept calls to mob.name...

To reiterate what started me down the path to the Dark Procedural Side:

Probably I'm biased in this direction because of some bad early experiences, where I'd move a player onto the map, the Move() would fail, and they would get bounced into limbo. Then I'd end up writing a bunch of code to check if the Move() succeeded, find a random spot nearby, see if they could Move() there, etc. Sometimes this meant they showed up on the other side of a wall they weren't supposed to be able to cross or something... Finally I just got tired of it and decided that when adding a mob to a known spot on the map, I'd just stick them there and avoid the hassle.

This is a pretty intractable problem. When a mob is entering a map, other mobs may be standing in the normal entry place. If you cycle through the turfs looking for the first empty one, you might end up placing the mob in an undesirable place. If you try to put systems in place to indicate which spots are okay to land on, you increase your implementation hassle considerably. And, in the end, there may not be an acceptable open spot (say you enter the map in a hallway and there are 6 people standing on all 6 acceptable spots).

So, like EverQuest, I give up and have everyone enter in the same spot, even if that means they land on top of each other. This is the cleanest approach and saves loads of implementation hassle. And requires using loc instead of Move().

Doing a search through my code, here are the other places where I'm using loc instead of Move(), and why:

------------

Checking for anything interesting to pick up on the mob's current turf:

for (current in my_loc.contents)
if (current.isHoldable)
current.loc = src


I don't use Move() here because Move() has a possibility of failure and I want to guarantee that this move occurs. If I end up limiting the number of items a mob can carry I might use Move() here to get the Enter() check, but in that case I'm actually more likely to just see if the mob has any open slots before I enter into this loop, so I don't waste time in it if there are no open slots anyway.

--------------

Sending things to null. Again, I don't want any chance of failure, so I use loc instead of Move().

--------------

Dropping stuff when a mob dies. I have some extra conditions, so I use my own code for this instead of the default behavior:

for (current in contents)
if (current.isDisposable)
del(current)
else
current.loc = src.loc


Again this is done to guarantee success of the movement.

-------------

There are more examples, but I think what it boils down to is:

If I want to ensure a movement is successful in special game circumstances, I use loc. Frequently this has to do with creation/initial placement of an object, or with object destruction.

Or to put it another way:

I default to loc unless I know I want the extra behavior of Move(), because I can't be sure of the outcome of Move().


It's possible I do this too much because I had several very bad debugging hours early on where my mob would get lost in null because the initial Move() to the map failed.

And that's the whole story.