03 Aug, 2010, KaVir wrote in the 81st comment:
Votes: 0
Rarva.Riendf said:
The 'flag' for mobs already exist it is the 'valid' boolean

No, I mean don't create a "corpse object" at all. Just leave the mob there, and flag it as dead. It'll require a few changes elsewhere, but I find it a nicer solution overall.

You could do the same for players as well. Let them lie there as a corpse for a little while, then move them to recall (or whereever).
03 Aug, 2010, Oliver wrote in the 82nd comment:
Votes: 0
Rarva.Riendf said:
2-their position do not stay POS_DEAD very long, position is not something you can use for that.


But. They only need to be POS_DEAD until the end of the pulse, right? If the issue is with the integrity of linked lists failing when a character is unduly extracted before the iteration is complete, then POS_DEAD would work just fine. The chain lightning (or earthquake, etc. etc.) function would be completely resolved by the time that the pulse finishes.

Also, I didn't necessarily mean "characters" as in "player-characters." I moreso meant in the sense of a character object, which mobs also are.
03 Aug, 2010, Rarva.Riendf wrote in the 83rd comment:
Votes: 0
David Haley said:
I thought I said earlier that delayed extraction was a fairly common solution to this, but it looks like I never said explicitly that SMAUG uses it, sorry. :wink:

Yep but delayed extraction made only sense to me for mobs, as ROM have this problem.
I never thought this delayed extraction was meaning 'flag a char dead' (for me extracting is really freeing the memory at one point.)


David Haley said:
I don't know if I'd say it works perfectly because SMAUG has a number of bugs of its own, but it does basically solve this problem.


Will look at how it is handled then, may help me avoid some pitfall I do not think about yet.
Someone should make a sticky note with all the potential bug you can fall in with basic ROM due to these loops over char_list.
And how the only solution to fix it is:
Delayed extraction for mobs, flag players and mobs dead till end of round.
Test for this after every call to a method that could end up killing a char.
03 Aug, 2010, quixadhal wrote in the 84th comment:
Votes: 0
The question is, why do you ever actually NEED to move a character (NPC or Player) from their current location until the current combat round is resolved?

The issues described above all result from characters moving. It doesn't matter how they move… extracted, teleported away, whatever. The idea is that they change lists, so if you're using a pointer, you end up traversing the wrong list. So, don't do that any more.

Stop acting on things immediately and instead make any changes to their position (room, lists they're on, etc) at the END of the combat round. It's not like the player gets a chance to act again anyways, nor do they typically even see output yet (as that's all pushed into the output queue, to be flushed to them at the start of the next round).
04 Aug, 2010, David Haley wrote in the 85th comment:
Votes: 0
No, Quix, it's not that simple. An easy demonstration is player 1 killing player 3; even if player 3 is not moved away you still need a mechanism to denote that player 3 is "gone" as far as combat is concerned. Similar but more complex situations may arise when an earlier player in the list is meant to be dead and therefore no longer affect the world.
04 Aug, 2010, Runter wrote in the 86th comment:
Votes: 0
The way I would solve this is by never removing the player at all. I'd use the same data structure for a corpse as I would the living thing.

Its a difference without distinction as far as players would be concerned.


This is related to my prior comment that there is no reason you couldn't hit a corpse after they expire. You wouldn't need a lot of checks or specialized code. You'd just need to act upon the target of damage based on state.
04 Aug, 2010, ralgith wrote in the 87th comment:
Votes: 0
Actually CircleMUD's delayed extraction works fine. Since everything that can cause death comes BEFORE extraction, and players get flagged with NOTDEADYET and mobs get flagged with MOB_NOTDEADYET. This flag being set makes them be skipped for anything that would normally damage them, since they're "dead" but not a corpse, hence the "not dead YET" weirdness.
04 Aug, 2010, quixadhal wrote in the 88th comment:
Votes: 0
Exactly Runter… I never understood why Diku needed to make so many distinctions between types of things. So, the player is dead and you hit them…. do they care if their hit points go MORE negative? To put it bluntly, why *should* the game have problems with attacking dead people? Why should the player be "gone" from combat until the round is over? Being dead just means they can no longer react, not that they're somehow not there.

At this point in the game, why go to so much effort to kludge ways around a clearly broken system to keep it from crashing? Fix the root of the problem… calling damage on dead people should simply be a no-op, not a deal breaker. POS_DEAD should be honored, rather than ignored, and only used for players and NPC's that are in fact dead.
04 Aug, 2010, ATT_Turan wrote in the 89th comment:
Votes: 0
David Haley said:
ATT_Turan said:
Yes, but that would happen from nested damage calls, so the NULLification should recurse its way back up (unless you're doing counter-damage via a function other than damage which, well, you shouldn't in this case :wink: )

How do you tell apart the situations where ch died vs. when victim died? What about if both die?

victim = damage(ch, victim, …)
// ch is dead now, how do we tell?


if (ch)
04 Aug, 2010, David Haley wrote in the 90th comment:
Votes: 0
And how did ch become null if damage's return value is for victim?
04 Aug, 2010, Rarva.Riendf wrote in the 91st comment:
Votes: 0
quixadhal said:
Exactly Runter… I never understood why Diku needed to make so many distinctions between types of things. So, the player is dead and you hit them…. do they care if their hit points go MORE negative? To put it bluntly, why *should* the game have problems with attacking dead people?


Dunno for you but when I am attacking dead people I would wish to see an actual differences in the messages I get…..
When you have special attacks that do damage and other effect, those other effect not being dealt if the player is dead.
Or when killing someone launch a trigger at his death meaning he will not be in the same room not have the effect when he is now elsewhere.

For all these reason you NEED something to show you a player is dead or not.

Quote
Actually CircleMUD's delayed extraction works fine. Since everything that can cause death comes BEFORE extraction, and players get flagged with NOTDEADYET and mobs get flagged with MOB_NOTDEADYET. This flag being set makes them be skipped for anything that would normally damage them, since they're "dead" but not a corpse, hence the "not dead YET" weirdness.

I did not see any snippet showing these flag in your code, hence my interrogations. And I may not get it, but why the flag should be different for mobs and chars ?
04 Aug, 2010, Runter wrote in the 92nd comment:
Votes: 0
Quote
For all these reason you NEED something to show you a player is dead or not.


Yes. That would be what state is for in a data structure.

You're really confusing the real problem here.

As I said already the change would be seamless for a player. The real issue isn't how do you ensure you haven't extracted a player but actually how do you ensure the pointer is always valid. The answer isn't returning boolean values. You can do something sloppy predicated on testing for every edge case or you can find a more elegant solution.

You're disputing my proposition based on cosmetic reasons that don't exist in actuality.
04 Aug, 2010, KaVir wrote in the 93rd comment:
Votes: 0
Runter said:
The way I would solve this is by never removing the player at all. I'd use the same data structure for a corpse as I would the living thing.

That's what I just proposed! And yes, I find it works very well.
04 Aug, 2010, Rarva.Riendf wrote in the 94th comment:
Votes: 0
Runter said:
Quote
For all these reason you NEED something to show you a player is dead or not.


Yes. That would be what state is for in a data structure.

You're really confusing the real problem here.

state ? Not in stock rom, you have 'position', and 'valid' pointer, and that is all.
And position cannot be used because pos_dead does not even stay after the end of the damage method (look at raw_kill)

Runter said:
As I said already the change would be seamless for a player. The real issue isn't how do you ensure you haven't extracted a player but actually how do you ensure the pointer is always valid.

You are the one confusing the issue here, the problem is really not the validity of the pointer, and the problem are not the mobs either, those are dead, their valid value put to false etc…problem are the character, who can move or disapear while in the loop.
Their pointer is still valid AND the problem is ROM engine makes then no difference between a char that just died and another that just moved, while YOU want it to know.

Runter said:
The answer isn't returning boolean values. You can do something sloppy predicated on testing for every edge case or you can find a more elegant solution.

If you read me I do not propose that, I propose to add something in the char_data that can reflect the fact a player is dead, (or a mob) Something common to both that can make the code easier to read.

Runter said:
You're disputing my proposition based on cosmetic reasons that don't exist in actuality.

Not in your mud maybe but definitely in mine and many other that use area spell that are coded (like in ROM code) and not handled all the same.

And it is not cosmetic. A lot of messages should not be sent to you if you are dead.
04 Aug, 2010, David Haley wrote in the 95th comment:
Votes: 0
Quote
state ? Not in stock rom, you have 'position', and 'valid' pointer, and that is all.

He's saying that a data structure can be used to maintain state that is useful, not that there is a actual 'state' variable.

Basically Runter is saying that the entire paradigm here is broken, since it introduces needless complexity. If, for example, player character objects were not immediately "extracted" to their recall zone, there would be no worry about characters disappearing upon death.

For example, if you were to simply create a new character object for the player upon death and repoint the connection to that character, you could leave the (dead) character object where it is and treat it just like you would a mob.
04 Aug, 2010, Rarva.Riendf wrote in the 96th comment:
Votes: 0
David Haley said:
Basically Runter is saying that the entire paradigm here is broken, since it introduces needless complexity. If, for example, player character objects were not immediately "extracted" to their recall zone, there would be no worry about characters disappearing upon death.

For example, if you were to simply create a new character object for the player upon death and repoint the connection to that character, you could leave the (dead) character object where it is and treat it just like you would a mob.


Oh ok ! I better understand. Sorry but being french here, I am sometimes quite too literal.
Seems like a nice an easy to code solution.
Duplicate the char_data and put it to the start of the char_list with its descriptor (basically the player character), so he wont be iterated over again (especially since he is not in the room anymore anyway.)

Leave the original char_data in the room but in an invalid state like a mob. So the loop is not broken at all, since you have the invalid flag like a mob anyway to check if you should affect him.

And it gets extracted like a mob at the end.

Seems like the easier thing to integrate, no need for another value in char_data, and only one thing to test that should already be tested anyway, being the vlid value.

Dunno what you all think of this, but delayed extraction of mobs + creating a duplicate of a player date in case he dies seems the best solution to fix ROM since yet.
05 Aug, 2010, ATT_Turan wrote in the 97th comment:
Votes: 0
David Haley said:
And how did ch become null if damage's return value is for victim?


How did ch (the attacker) get hurt while doing damage to his target? If there was some sort of counterattack inside of the damage function, it would have been called with a
ch=damage(victim,ch,…)
which would modify the value of ch in the original function since it's all being passed by pointer. I mean, if I've made some stupid logical mistake in my thought process, that's fine, just tell me, but it seems to me to be a perfectly valid way of keeping track of these things if you absolutely want to do it by checking the validity of the pointer variable.
05 Aug, 2010, David Haley wrote in the 98th comment:
Votes: 0
I *have* been trying to tell you that this won't work. :smile:

If ch becomes null inside the damage function, like with a counterattack, then it is only null in *that* scope. In particular it is not made null in the calling scope.

- ch attacks victim
victim = damage(ch, victim, …)
–> victim counterattacks
ch = damage(victim, ch)
ch becomes null in this scope
- victim = damage(ch, victim) returns
- ch not null in this scope but ch is dead…. oops.
05 Aug, 2010, Runter wrote in the 99th comment:
Votes: 0
Just use realloc.

On a more serious note roms memory recycling system is partially intended to solve this. Memory is never freed. It is just placed in a free list for that type of object. This results in extracted pointers always remaining at least technically valid. Particularly right after extraction.

I would argue that this just masks the problem and makes it possible to have unintentional memory corruption from these would be rogue pointers.

Odds are this could only happen under certain conditions not met with stock rom. But they'd be achievable with relative ignorance to what is causing it. It could become a debugging nightmare.

Ultimately my thought on this system for rom after many years working with it is that its poorly thought out.
05 Aug, 2010, Rarva.Riendf wrote in the 100th comment:
Votes: 0
Runter said:
Just use realloc.

On a more serious note roms memory recycling system is partially intended to solve this. Memory is never freed. It is just placed in a free list for that type of object. This results in extracted pointers always remaining at least technically valid. Particularly right after extraction.

I would argue that this just masks the problem and makes it possible to have unintentional memory corruption from these would be rogue pointers.

Odds are this could only happen under certain conditions not met with stock rom. But they'd be achievable with relative ignorance to what is causing it. It could become a debugging nightmare.

Ultimately my thought on this system for rom after many years working with it is that its poorly thought out.


Yes stock ROM is poorly thought and hides every logical mistakes it has with its recycling memory, never having null pointer, but then you have strange things happening as soon as you try area spell.

That is why I am trying to find the perfect fit solution to fix ROM. I think we pretty much all agree delayed extraction for mobs works totally fine without any problems, but we also have to deal with players. Creating a duplicate of the char as a mob that will takes its place (I mean pointer value here) seems to me the best solution as stated by David Haley (and you first if I get it right). That will make the same test works for both chars and mobs (ie check ch->valid and victim->valid), and replacing the char by a mob can be easily done in some lines of code.
80.0/108