void violence_update (void)
{
CHAR_DATA *ch;
CHAR_DATA *ch_next;
CHAR_DATA *victim;
for (ch = char_list; ch != NULL; ch = ch_next)
{
ch_next = ch->next;
if ((victim = ch->fighting) == NULL || ch->in_room == NULL)
continue;
if (IS_AWAKE (ch) && ch->in_room == victim->in_room)
{
multi_hit (ch, victim, TYPE_UNDEFINED);
/*
* Swords will very rarely get in an extra round.
*/
if (get_weapon_sn (ch) == gsn_sword
&& ch->wait <= 0)
{
int chance;
CHAR_DATA * was_fighting;
CHAR_DATA * vch;
chance = get_skill (ch, gsn_sword) / 15;
/*
* Penalty if the opponent can see.
*/
if (can_see (victim, ch))
chance = chance * 3 / 5;
for (vch = ch->in_room->people; vch != NULL;
vch = vch->next_in_room)
{
if (vch->fighting == ch
|| is_same_group (vch->fighting, ch))
{
if (number_percent () < chance)
{
was_fighting = ch->fighting;
ch->fighting = vch;
multi_hit (ch, vch, TYPE_UNDEFINED);
check_improve (ch, gsn_sword, TRUE, 2);
ch->fighting = was_fighting;
WAIT_STATE (ch, PULSE_VIOLENCE);
break;
}
}
}
}
}
else
stop_fighting (ch, FALSE);
if ((victim = ch->fighting) == NULL)
continue;
/*
* Fun for the whole family!
*/
check_assist (ch, victim);
if (IS_NPC (ch))
{
if (HAS_TRIGGER (ch, TRIG_FIGHT))
mp_percent_trigger (ch, victim, NULL, NULL, TRIG_FIGHT);
if (HAS_TRIGGER (ch, TRIG_HPCNT))
mp_hprct_trigger (ch, victim);
}
}
return;
}
ie.
if (victim->in_room == NULL || ch->in_room == NULL)
return FALSE;
Actually, I was just thinking about this, this morning. Years ago, I would have agreed with you, and in fact my old MUD has lots of extra sanity checks that try to return "the right answer" when something isn't there, thus avoiding a crash. In those days, I shared the mindset that a crash is something to be avoided at all costs.
Now, I'm far more inclined to only put such checks into things where they get used in a wide variety of circumstances. Unless you're running a mission critical system (one where lives, or decades of work, are at stake), I prefer having the game crash when the impossible happens. Read that again. :)
The DikuMUD system was designed to always have characters (player or NPC) be contained in a room. That's why rooms like "The Void" exist, because if you can't figure out where to put someone, you have to put them somewhere. Given that design, it's not appropriate to check if ch->in_room is NULL, because it should never happen. You should extract a character and immediately put them into some other room. If you do anything else in that undefined state, you should either do all the checking yourself, or rethink if you really need to do it there, OR do all the work of redesigning the system.
Having said all that, I'm of the opinion that extract_char() is being called too early, and that whatever other processing is happening should happen before that call, or should be delayed until they're restored to whatever destination that game's death system sends them to.
can_see() sounds like too much of a utility function, and I don't think *IT* should be the thing that checks for a valid room, since it shouldn't be called on dead people. Either you can_see() a living pc/npc, or you can_see() a corpse object… not a dead person. :)