emud/area_current/
emud/area_current/castle/
emud/area_current/newareas/
emud/area_current/nwcentral/
emud/area_current/scontinent/
emud/clans/
emud/player/
emud/player/d/e/bak/
emud/player/e/m/
emud/player/e/m/bak/
/***************************************************************************
 * Emud  2.2 by Igor van den Hoven, Michiel Lange, and Martin Bethlehem.   *
 *                                                                         *
 * MrMud 1.4 by David Bills and Dug Michael.                               *
 *                                                                         *
 * Merc  2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael      *
 * Chastain, Michael Quan, and Mitchell Tse.                               *
 *                                                                         *
 * Original Diku Mud copyright (C) 1990 1991 by Sebastian Hammer,          *
 * Michael Seifert, Hans Henrik St{rfeld, Tom Madsen, and Katje Nyboe.     *
 ***************************************************************************/

#include "emud.h"

/*
	Local functions.
*/

int	hit_gain			args ((CHAR_DATA * ch));
int	mana_gain			args ((CHAR_DATA * ch));
int	move_gain			args ((CHAR_DATA * ch));
void	mobile_update		args ((void));
void	shop_update		args ((void));
void	weather_update		args ((void));
void time_update		args ((void));
void	char_update		args ((void));
void	obj_update		args ((void));
void	aggr_update		args ((void));
void	bounty_update		args ((void));
void	auto_area_save		args ((void));
void auto_char_save		args ((void));
void mob_program_update	args ((void));
void obj_program_update	args ((void));
void purger_update		args ((void));

/*
	Advancement stuff.
*/

void advance_level (CHAR_DATA * ch, bool fSave)
{
	int add_hp;
	int add_mana;
	int add_move;
	int add_prac;

	push_call("advance_level(%p,%p)",ch,fSave);

	add_hp = con_app[get_curr_con (ch)].hitp +
		number_range ( class_table[ch->class].hp_min,
		class_table[ch->class].hp_max) +
	race_table[ch->race].hp_mod;

	add_mana = int_app[get_curr_int (ch)].manap +
		number_range ( class_table[ch->class].mana_min,
		class_table[ch->class].mana_max) +
		race_table[ch->race].mana_mod;

	add_move = number_range(get_curr_dex(ch)/3, 10+get_curr_dex(ch)/3) +
		race_table[ch->race].move_mod;

	add_prac = wis_app[get_curr_wis (ch)].practice;

	add_hp   = UMAX (1, add_hp);
	add_mana = UMAX (1, add_mana);
	add_move = UMAX (3, add_move);

	add_hp   += ch->pcdata->reincarnation * 8;
	add_mana += ch->pcdata->reincarnation * 6;
	add_move += ch->pcdata->reincarnation * 5;
	add_prac += ch->pcdata->reincarnation * 3;

	/* Knight stuff get double   - Chaos     9/14/95 */

	if (ch->level > 90 && ch->level < 96)
	{
		add_hp   *= 2;
		add_mana *= 2;
		add_move *= 2;
		add_prac *= 2;
	}

	/* Followers get extra juice !! - Martin 22/7/98 */

	if (ch->pcdata->god != GOD_NEUTRAL)
	{
		ch_printf(ch, "%s\n\r", god_table[ch->pcdata->god].level_msg);

		add_hp   += god_table[ch->pcdata->god].bonus_hp;
		add_mana += god_table[ch->pcdata->god].bonus_mana;
		add_move += god_table[ch->pcdata->god].bonus_move;
	}

	ch->pcdata->actual_max_hit  += add_hp;
	ch->pcdata->actual_max_mana += add_mana;
	ch->pcdata->actual_max_move += add_move;
	ch->max_hit += add_hp;
	ch->max_mana += add_mana;
	ch->max_move += add_move;
	ch->pcdata->practice += add_prac;

	if (fSave)
	{
		sub_player (ch);
		add_player (ch);
		save_char_obj (ch, NORMAL_SAVE);
		save_char_obj (ch, BACKUP_SAVE);
	}

	ch_printf(ch, "Your gain is: %d/%d hp, %d/%d m, %d/%d mv %d/%d prac.\n\r",
		add_hp, ch->max_hit,
		add_mana, ch->max_mana,
		add_move, ch->max_move,
		add_prac, ch->pcdata->practice );

	vt100prompt(ch);

	pop_call();
	return;
}


void gain_exp (CHAR_DATA * ch, int gain)
{
	push_call("gain_exp(%p,%p)",ch,gain);

	if (IS_NPC (ch) || ch->level >= LEVEL_HERO - 1 || ch->in_room->area->low_r_vnum == ROOM_VNUM_ARENA)
	{
		pop_call();
		return;
	}

	ch->pcdata->exp = UMAX(0, ch->pcdata->exp + gain);

	if (ch->pcdata->exp >= exp_level(ch->class, ch->level))
	{
		send_to_char ("You raise a level!!  ", ch);
		ch->pcdata->exp = exp_level(ch->class, ch->level) + 1;
		ch->level += 1;
		if (ch->level % 3 == 0) /*add a language every 3 levels  Chaos 4/27/99*/
		{
			add_language(ch);
		}
		ch->pcdata->mclass[ch->class] += 1;
		advance_level (ch, TRUE);
	}
	pop_call();
	return;
}

/*
	Regeneration stuff.
*/

int hit_gain (CHAR_DATA * ch)
{
	int gain;

	push_call("hit_gain(%p)",ch);

	if (IS_NPC (ch))
	{
		gain = ch->level * 4 / 3;
	}
	else
	{
		gain = get_curr_con(ch) * 2;

		switch (ch->position)
		{
			case POS_SLEEPING:
				gain += gain;
				break;
			case POS_RESTING:
				gain += gain / 2;
				break;
			case POS_SITTING:
				gain += gain / 3;
				break;
		}

		if (ch->pcdata->condition[COND_FULL] == 0)
		{
			gain /= 2;
		}

		if (ch->pcdata->condition[COND_THIRST] == 0)
		{
			gain /= 2;
		}
	}

	if (ch->furniture && ch->furniture->item_type == ITEM_FURNITURE)
	{
		gain = gain * ch->furniture->value[3] / 100;
	}

	if (IS_AFFECTED(ch, AFF2_BERSERK))
	{
		gain *= 2;
	}

	if (IS_AFFECTED(ch, AFF_POISON))
	{
		gain /= 4;
	}

	if (IS_AFFECTED(ch, AFF2_TORRID_BALM))
	{
		gain /= 4;
	}

	if (in_camp(ch))
	{
		gain *= 2;
	}

	if (!IS_NPC(ch) && rspec_req(ch, RSPEC_FASTHEAL))
	{
		gain = 3 * gain / 2;
	}

	if (IS_AFFECTED(ch, AFF2_ENHANCED_HEAL))
	{
		if (!IS_NPC(ch) && rspec_req(ch,RSPEC_FASTHEAL))
		{
			send_to_char ("You heal faster.\n\r", ch);
		}
		else
		{
			send_to_char ("You heal easier.\n\r", ch);
		}
		gain = 3 * gain / 2;
	}

	pop_call();
	return UMIN(gain, ch->max_hit - ch->hit);
}


int mana_gain (CHAR_DATA * ch)
{
	int gain;

	push_call("mana_gain(%p)",ch);

	if (IS_NPC (ch))
	{
		gain = ch->level * 2;
	}
	else
	{
		gain = get_curr_wis(ch) * 3;

		switch (ch->position)
		{
			case POS_SLEEPING:
				gain += gain;
				break;
			case POS_RESTING:
				gain += gain / 2;
				break;
			case POS_SITTING:
				gain += gain / 3;
				break;
		}

		if (ch->pcdata->condition[COND_FULL] == 0)
		{
			gain /= 2;
		}

		if (ch->pcdata->condition[COND_THIRST] == 0)
		{
			gain /= 2;
		}
	}

	if (ch->furniture && ch->furniture->item_type == ITEM_FURNITURE)
	{
		gain = gain * ch->furniture->value[3] / 100;
	}

	if (IS_AFFECTED (ch, AFF2_BERSERK))
	{
		gain /= 4;
	}

	if (IS_AFFECTED (ch, AFF_POISON))
	{
		gain /= 4;
	}

	if (IS_AFFECTED (ch, AFF2_QUICKEN))
	{
		gain /= 2;
	}

	if (in_camp (ch))
	{
		gain *= 2;
	}

	if (!IS_NPC(ch) && rspec_req(ch, RSPEC_FASTREVIVE))
	{
		gain = 3 * gain / 2;
	}

	if (!IS_NPC(ch) && learned(ch, gsn_warmth))
	{
		gain += gain * multi_skill_level(ch, gsn_warmth) / 100;
	}

	if (IS_AFFECTED (ch, AFF2_ENHANCED_REVIVE))
	{
		if (!IS_NPC(ch) && learned(ch, gsn_warmth))
		{
			send_to_char("You feel warmth spreading through your body.\n\r", ch);
			check_improve(ch, gsn_warmth);
		}
		else if (!IS_NPC(ch) && rspec_req(ch, RSPEC_FASTREVIVE))
		{
			send_to_char ("You revive quicker.\n\r", ch);
		}
		else
		{
			send_to_char ("You revive easier.\n\r", ch);
		}
		gain = 3 * gain / 2;
	}
	pop_call();
	return UMIN (gain, ch->max_mana - ch->mana);
}

int move_gain (CHAR_DATA * ch)
{
	int gain;

	push_call("move_gain(%p)",ch);

	if (IS_NPC (ch))
	{
		gain = ch->level;
	}
	else
	{
		gain = get_curr_dex(ch) * 4;

		switch (ch->position)
		{
			case POS_SLEEPING:
				gain += gain;
				break;
			case POS_RESTING:
				gain += gain / 2;
				break;
			case POS_SITTING:
				gain += gain / 3;
				break;
		}

		if (ch->pcdata->condition[COND_FULL] == 0)
		{
			gain /= 2;
		}
		if (ch->pcdata->condition[COND_THIRST] == 0)
		{
			gain /= 2;
		}
	}

	if (ch->furniture && ch->furniture->item_type == ITEM_FURNITURE)
	{
		gain = gain * ch->furniture->value[3] / 100;
	}

	if (IS_AFFECTED (ch, AFF2_BERSERK))
	{
		gain *= 2;
	}

	if (IS_AFFECTED (ch, AFF_POISON))
	{
		gain /= 4;
	}

	if (in_camp (ch))
	{
		gain *= 2;
	}

	if (IS_AFFECTED (ch, AFF2_ENHANCED_REST))
	{
		send_to_char ("You rest easier.\n\r", ch);
		gain = 3 * gain / 2;
	}

	pop_call();
	return UMIN (gain, ch->max_move - ch->move);
}

void gain_condition (CHAR_DATA * ch, int iCond, int value)
{
	int condition;

	push_call("gain_condition(%p,%p,%p)",ch,iCond,value);

	if ( value == 0 || IS_NPC (ch))
	{
		pop_call();
		return;
	}
	condition	= ch->pcdata->condition[iCond];
	ch->pcdata->condition[iCond]	= URANGE( 0, condition + value, 48 );

	if (rspec_req(ch,RSPEC_VAMPIRIC))
	{
		if (iCond == COND_THIRST && ch->pcdata->condition[COND_THIRST] <= 3)
		{
			send_to_char("Your body is craving for blood.\n\r", ch);
			act("$n looks pale and weak.", ch, NULL, NULL, TO_ROOM);

			damage(ch, ch, 1+ch->level/7, TYPE_NOFIGHT);
		}

		pop_call();
		return;
	}

	if ( ch->pcdata->condition[iCond] == 0 )
	{
		switch ( iCond )
		{
			case COND_FULL:
				if (ch->level > 1)
				{
					send_to_char( "You are STARVING!\n\r",  ch );
					act( "$n is starved half to death!", ch, NULL, NULL, TO_ROOM);
					damage(ch, ch, 1+ch->level/7, TYPE_NOFIGHT);
				}
				else
				{
					send_to_char( "You are really hungry.\n\r",  ch );
				}
				pop_call();
				return;
				break;

			case COND_THIRST:
				if( ch->level > 1 )
				{
					send_to_char( "You are DYING of THIRST!\n\r", ch );
					act( "$n is dying of thirst!", ch, NULL, NULL, TO_ROOM);
					damage(ch, ch, 1+ch->level/5, TYPE_NOFIGHT);
				}
				else
				{
					send_to_char( "You are really thirsty.\n\r", ch );
				}
				pop_call();
				return;
				break;

			case COND_DRUNK:
				if ( condition != 0 )
				{
					send_to_char( "You are sober.\n\r", ch );
					pop_call();
					return;

				}
				break;

			default:
				bug( "Gain_condition: invalid condition type %d", iCond );
				break;
		}
	}

	if ( ch->pcdata->condition[iCond] == 1 )
	{
		switch ( iCond )
		{
			case COND_FULL:
				send_to_char( "You are really hungry.\n\r",  ch );
				act( "You can hear $n's stomach growling.", ch, NULL, NULL, TO_ROOM);
				break;

			case COND_THIRST:
				send_to_char( "You are really thirsty.\n\r", ch );
				act( "$n looks a little parched.", ch, NULL, NULL, TO_ROOM);
				break;

			case COND_DRUNK:
				if ( condition != 0 )
				{
					send_to_char( "You are feeling a little less light headed.\n\r", ch );
				}
				break;
		}
	}

	if ( ch->pcdata->condition[iCond] == 2 )
	{
		switch ( iCond )
		{
			case COND_FULL:
				send_to_char( "You are hungry.\n\r",  ch );
				break;

			case COND_THIRST:
				send_to_char( "You are thirsty.\n\r", ch );
				break;
		}
	}

	if ( ch->pcdata->condition[iCond] == 3 )
	{
		switch ( iCond )
		{
			case COND_FULL:
				send_to_char( "You are a mite peckish.\n\r",  ch );
				break;

			case COND_THIRST:
				send_to_char( "You could use a sip of something refreshing.\n\r", ch );
				break;
		}
	}
	pop_call();
	return;
}

void obj_program_update (void)
{
	PLAYER_GAME *pch, *pch_next;
	OBJ_DATA *obj, *obj_next;
	OBJ_PROG *prg;

	push_call("obj_program_update()");

	for (pch = mud->f_player ; pch ; pch = pch_next)
	{
		pch_next = pch->next;

		if (pch->ch->desc)
		{
			for (obj = pch->ch->first_carrying ; obj ; obj = obj_next)
			{
				obj_next = obj->next_content;

				if (obj->carried_by && IS_SET(obj->pIndexData->progtypes, TRIG_TICK))
				{
					for (prg = obj->pIndexData->first_prog ; prg ; prg = prg->next)
					{
						if (prg->trigger == TRIG_TICK)
						{
							if (number_range(1, 200) <= prg->percentage)
							{
								start_object_program( pch->ch, obj, prg, "");
							}
						}
					}
				}
			}
		}
	}
	pop_call();
	return;
}

void mob_program_update (void)
{
	CHAR_DATA *ich;
	AREA_DATA *area;

	int vnum;

	push_call("mob_program_update()");

	for (area = mud->f_area ; area ; area = area->next)
	{
		for (vnum = area->low_m_vnum ; vnum <= area->hi_m_vnum ; vnum++)
		{
			if (mob_index[vnum] == NULL || mob_index[vnum]->first_instance == NULL)
			{
				continue;
			}

			if (IS_SET(mob_index[vnum]->progtypes, RAND_PROG))
			{
				for (ich = mob_index[vnum]->first_instance ; ich ; ich = mud->update_ich)
				{
					mud->update_ich = ich->next_instance;

					if (!MP_VALID_MOB(ich))
					{
						continue;
					}

					if (ich->position <= POS_SLEEPING || ich->position == POS_FIGHTING)
					{
						continue;
					}
					mprog_percent_check(ich, NULL, NULL, NULL, RAND_PROG);
				}
				continue;
			}

			if (mob_index[vnum]->spec_fun && area->nplayer)
			{
				for (ich = mob_index[vnum]->first_instance ; ich ; ich = mud->update_ich)
				{
					mud->update_ich = ich->next_instance;

					if (!MP_VALID_MOB(ich))
					{
						continue;
					}

					(*ich->pIndexData->spec_fun) (ich);
				}
			}
		}
	}
	/*
		Let's see if some trivia can be played - Scandum 01-11-2002
	*/

	if (mud->f_trivia)
	{
		update_trivia();
	}
	pop_call();
	return;
}

void auto_char_save (void)
{
	PLAYER_GAME *npl;
	CHAR_DATA *oldest;
	CLAN_DATA *oldest_clan, *clan;
	int oldest_time, oldest_clan_time, total_clans;
	static int save_delay;
	static int clan_delay;

	push_call("auto_char_save()");

	if (save_delay >= 0)
	{
		save_delay--;
	}
	else
	{
		save_delay	= 600 / PULSE_CHARSAVE / UMAX(1, mud->total_plr);
		oldest		= NULL;
		oldest_time	= mud->current_time;

		for (npl = mud->f_player ; npl ; npl = npl->next)
		{
			if (npl->ch->pcdata->last_saved < oldest_time)
			{
				oldest_time	= npl->ch->pcdata->last_saved;
				oldest		= npl->ch;
			}
		}

		if (oldest)
		{
			save_char_obj(oldest, NORMAL_SAVE);

			check_most(oldest);
		}

		for (npl = mud->f_player ; npl ; npl = npl->next)
		{
			if (npl->ch->timer > 30 && (!npl->ch->pcdata->switched || npl->ch->timer > 60) && (!IS_IMMORTAL(npl->ch) || !is_desc_valid(npl->ch)))
			{
				char_from_room(npl->ch);
				char_to_room(npl->ch, npl->ch->pcdata->was_in_room);

				do_quit(npl->ch, NULL);
				break;
			}
		}
	}

	if (clan_delay >= 0)
	{
		clan_delay--;
	}
	else
	{
		for (total_clans = 0, clan = mud->f_clan ; clan ; clan = clan->next)
		{
			total_clans++;
		}

		clan_delay		= 3600 / PULSE_CHARSAVE / UMAX(1, total_clans);
		oldest_clan_time	= mud->current_time;
		oldest_clan		= NULL;

		for (clan = mud->f_clan ; clan ; clan = clan->next)
		{
			if (clan->last_saved < oldest_clan_time)
			{
				oldest_clan_time	= clan->last_saved;
				oldest_clan		= clan;
			}
		}

		if (oldest_clan)
		{
			save_clan(oldest_clan);
			oldest_clan->last_saved = mud->current_time;
		}
	}
	pop_call();
	return;
}

void auto_area_save (void)
{
	push_call("auto_area_save(void)");

	do_savearea(NULL, "forreal");

	pop_call();
	return;
}


void shop_update (void)
{
	OBJ_DATA *obj;
	CHAR_DATA *ich;
	AREA_DATA *area;

	int vnum;

	push_call("shop_update()");

	for (area = mud->f_area ; area ; area = area->next)
	{
		for (vnum = area->low_m_vnum ; vnum <= area->hi_m_vnum ; vnum++)
		{
			if (mob_index[vnum] == NULL || mob_index[vnum]->pShop == NULL)
			{
				continue;
			}

			for (ich = mob_index[vnum]->first_instance ; ich ; ich = ich->next_instance)
			{
				for (obj = ich->last_carrying ; obj ; obj = obj->prev_content)
				{
					if (obj->reset == NULL)
					{
						if (number_bits(3) == 0)
						{
							act ("$n discards $p.", ich, obj, NULL, TO_ROOM);
							junk_obj(obj);
						}
					}
					else
					{
						break;
					}
				}
			}
		}
	}
	pop_call();
	return;
}


void mobile_update (void)
{
	CHAR_DATA *ich;
	CHAR_DATA *rch;
	AREA_DATA *area;
	PLAYER_GAME *gch;
	EXIT_DATA *pexit;
	OBJ_DATA *obj, *obj_best;
	int vnum, door, max;

	push_call("mobile_update()");

	for (area = mud->f_area ; area ; area = area->next)
	{
		for (vnum = area->low_m_vnum ; vnum <= area->hi_m_vnum ; vnum++)
		{
			if (mob_index[vnum] == NULL || mob_index[vnum]->first_instance == NULL)
			{
				continue;
			}

			if (mob_index[vnum]->area->nplayer == 0 && number_bits(6))
			{
				continue;
			}

			if (!IS_SET(mob_index[vnum]->act, ACT_SENTINEL))
			{
				for (ich = mob_index[vnum]->first_instance ; ich ; ich = mud->update_ich)
				{
					mud->update_ich = ich->next_instance;

					if (!MP_VALID_MOB(ich))
					{
						continue;
					}

					if (ich->position != POS_STANDING)
					{
						continue;
					}

					if (*ich->npcdata->hate_fear == '\0' && number_bits(4) != 0)
					{
						continue;
					}

					door = number_door();

					if ((pexit = ich->in_room->exit[door]) == NULL)
					{
						continue;
					}
					if (room_index[pexit->to_room] == NULL)
					{
						continue;
					}
					if (IS_SET(room_index[pexit->to_room]->room_flags, ROOM_NO_MOB))
					{
						continue;
					}
					if (IS_SET(ich->act, ACT_STAY_SECTOR) && ich->reset && room_index[pexit->to_room]->sector_type != room_index[ich->reset->arg3]->sector_type)
					{
						continue;
					}
					if (room_index[pexit->to_room]->area == ich->in_room->area)
					{
						move_char(ich, door, TRUE);
					}
				}
			}

			if (IS_SET(mob_index[vnum]->act, ACT_SCAVENGER))
			{
				for (ich = mob_index[vnum]->first_instance ; ich ; ich = mud->update_ich)
				{
					mud->update_ich = ich->next_instance;

					if (!MP_VALID_MOB(ich))
					{
						continue;
					}

					if (ich->position != POS_STANDING)
					{
						continue;
					}

					if (ich->in_room->first_content == NULL)
					{
						continue;
					}

					if (ich->carry_number >= 10)
					{
						continue;
					}

					if (number_bits(4))
					{
						continue;
					}

					max = 1;
					obj_best = NULL;

					for (obj = ich->in_room->first_content ; obj ; obj = obj->next_content)
					{
						if (IS_SET(obj->wear_flags, ITEM_TAKE) && obj->cost > max)
						{
							obj_best = obj;
							max = obj->cost;
						}
					}
					if (obj_best)
					{
						char objName[MAX_INPUT_LENGTH];
						sprintf (objName, "i%u", obj_best->pIndexData->vnum);
						do_get (ich, objName);
						do_wear(ich, objName);
					}
				}
			}

			if (mob_index[vnum]->area->nplayer == 0)
			{
				continue;
			}

			for (ich = mob_index[vnum]->first_instance ; ich ; ich = mud->update_ich)
			{
				mud->update_ich = ich->next_instance;

				if (*ich->npcdata->hate_fear == '\0')
				{
					continue;
				}

				if (!MP_VALID_MOB(ich))
				{
					continue;
				}

				if (ich->position < POS_STANDING)
				{
					continue;
				}

				if (!IS_SET(ich->act, ACT_WIMPY))
				{
					if (ich->fighting == NULL)
					{
						for (rch = ich->in_room->first_person ; rch ; rch = rch->next_in_room)
						{
							if (ich->npcdata->hate_fear == rch->name)
							{
								found_hating(ich, rch);
								break;
							}
						}
					}
					continue;
				}
				else
				{
					if (ich->hit > ich->max_hit / 2)
					{
						continue;
					}
					if (ich->fighting)
					{
						do_flee(ich, "");
						continue;
					}
					door = number_door();

					if ((pexit = get_exit(ich->in_room->vnum, door)) == NULL)
					{
						continue;
					}

					if (IS_SET(pexit->exit_info, EX_CLOSED))
					{
						continue;
					}

					if (IS_SET(room_index[pexit->to_room]->room_flags, ROOM_NO_MOB))
					{
						continue;
					}

					if (IS_SET(ich->act, ACT_STAY_SECTOR) && ich->reset && room_index[pexit->to_room]->sector_type != room_index[ich->reset->arg3]->sector_type)
					{
						continue;
					}
					for (rch = ich->in_room->first_person ; rch ; rch = rch->next_in_room)
					{
						if (ich->npcdata->hate_fear == rch->name && IS_SET(ich->act, ACT_SMART))
						{
							char buf[MAX_INPUT_LENGTH];

							if (IS_SET(ich->act, ACT_SMART))
							{
								switch (number_bits (2))
								{
									case 0:
										sprintf (buf, "Argh! %s is trying to kill me!", capitalize(get_name(rch)));
										break;
									case 1:
										sprintf (buf, "Help! I'm being attacked by %s!", get_name(rch));
										break;
									case 2:
										sprintf (buf, "Stay away from me %s! Help!", short_to_name(get_name(rch), 1));
										break;
									case 3:
										sprintf (buf, "Someone help me! %s is attacking me!", get_name(rch));
										break;
								}
								do_shout (ich, buf);
							}
							else
							{
								switch (number_bits(2))
								{
									case 0:
										act("$n looks around frantically as it searches for an escape!", ich, NULL, NULL, TO_ROOM);
										break;
									case 1:
										act("$n darts around mindlessly in an attempt to get away!", ich, NULL, NULL, TO_ROOM);
										break;
									case 2:
										act("$n lets out a whimper and tries to flee!", ich, NULL, NULL, TO_ROOM);
										break;
									case 3:
										act("$n howls in fear as it attempts to flee!", ich, NULL, NULL, TO_ROOM);
										break;
								}
							}
							break;
						}
					}
					if (rch)
					{
						move_char(ich, door, TRUE);
					}
				}
			}
		}
	}

	for (gch = mud->f_player ; gch ; gch = gch->next)
	{
		switch (gch->ch->in_room->sector_type)
		{
			case SECT_ASTRAL:
				if (!CAN_ASTRAL_WALK(gch->ch))
				{
					if (gch->ch->position == POS_FIGHTING)
					{
						stop_fighting (gch->ch, FALSE);
					}
					char_from_room (gch->ch);
					if (room_index[gch->ch->pcdata->last_real_room]->sector_type == SECT_ASTRAL)
					{
						char_to_room (gch->ch, ROOM_VNUM_TEMPLE);
					}
					else
					{
						char_to_room (gch->ch, gch->ch->pcdata->last_real_room);
					}
				}
				break;

			case SECT_UNDER_WATER:
				if (!CAN_BREATH_WATER(gch->ch))
				{
					if (!vnum_in_group (gch->ch, MOB_VNUM_WATER_ELEMENTAL))
					{
						if (gch->ch->pcdata->condition[COND_AIR] <= 0)
						{
							send_to_char ("You cannot breath!\n\r", gch->ch);
							damage (gch->ch, gch->ch, 50, TYPE_NOFIGHT);
						}
						else
						{
							gch->ch->pcdata->condition[COND_AIR]--;
							if (gch->ch->pcdata->condition[COND_AIR] == 5)
							{
								send_to_char("You cannot hold in your breath much longer.\n\r", gch->ch);
							}
						}
					}
				}
				break;

			case SECT_LAVA:
				if (!CAN_FIREWALK(gch->ch))
				{
					if (!vnum_in_group (gch->ch, MOB_VNUM_FIRE_ELEMENTAL))
					{
						send_to_char ("That lava is REALLY hot!\n\r", gch->ch);

						if (CAN_FLY(gch->ch))
						{
							damage(gch->ch, gch->ch, 15, TYPE_NOFIGHT);
						}
						else
						{
							damage(gch->ch, gch->ch, 20, TYPE_NOFIGHT);
						}
					}
				}
				break;

			case SECT_OCEAN:
				if (!CAN_FLY(gch->ch))
				{
					if (!CAN_BREATH_WATER(gch->ch))
					{
						if (!CAN_SWIM(gch->ch))
						{
							OBJ_DATA *obj;
							for (obj = gch->ch->first_carrying ; obj ; obj = obj->next_content)
							{
								if (obj->item_type == ITEM_BOAT)
								{
									break;
								}
							}
							if (obj == NULL)
							{
								send_to_char ("You are sinking FAST!\n\r", gch->ch);
								damage (gch->ch, gch->ch, 10, TYPE_NOFIGHT);
								continue;
							}
						}
					}
				}
				break;

			default:
				if (gch->ch->pcdata->condition[COND_AIR] < 10)
				{
					send_to_char("You take a deep breath of fresh air.\n\r", gch->ch);
					gch->ch->pcdata->condition[COND_AIR] = 10;
				}
				break;
		}
	}
	pop_call();
	return;
}


/*
	Update the weather - Scandum 22-06-2003
*/

void weather_area_update( AREA_DATA *area )
{
	char buf[MAX_STRING_LENGTH];

	PLAYER_GAME *gch;

	int temp, season, daily;

	buf[0] = '\0';

	/*
		Calculate temperature in degrees Celcius
	*/

	season = area->weather_info->temp_summer - area->weather_info->temp_winter;
	daily  = area->weather_info->temp_daily;

	temp   = area->weather_info->temp_winter;

	temp  += season * ( 8 - abs(mud->time_info->month -  8)) /  8;
	temp  += daily  * (12 - abs(mud->time_info->hour  - 12)) / 12;

	/*
		Calculate the wind speed based on current wind speed 0 - 10
	*/

	if (area->weather_info->wind_speed > area->weather_info->wind_scale + 1)
	{
		area->weather_info->wind_speed += number_range(0, 3) - 2;
	}
	else if (area->weather_info->wind_speed < area->weather_info->wind_scale - 1)
	{
		area->weather_info->wind_speed += number_range(0, 3) - 1;
	}
	else
	{
		area->weather_info->wind_speed += number_range(0, 2) - 1;
	}

	area->weather_info->wind_speed = URANGE(-10, area->weather_info->wind_speed, 20);

	/*
		Calculate the wind direction, based on current wind direction
	*/

	area->weather_info->wind_dir   = abs(area->weather_info->wind_dir + number_range(0, 2) - 1) % 8;

	/*
		Calculate the weather, based on current weather
	*/

	if (area->weather_info->change < area->weather_info->wet_scale - 1)
	{
		area->weather_info->change += number_range(0, 3) - 1;
	}
	else if (area->weather_info->change > area->weather_info->wet_scale + 1)
	{
		area->weather_info->change += number_range(0, 3) - 2;
	}
	else
	{
		area->weather_info->change += number_range(0, 4) - 2;
	}

	area->weather_info->change = URANGE(-100, area->weather_info->change, 110);

	/*
		Modify temperature based on weather
	*/

	temp += 5 - URANGE(0, area->weather_info->change, 10);

	area->weather_info->temperature = temp;

	switch (area->weather_info->sky)
	{
		default:
			bug ("Weather_update: bad sky %d.", area->weather_info->sky);
			area->weather_info->sky = SKY_CLOUDLESS;
			break;

		case SKY_CLOUDLESS:
			if (area->weather_info->change > 3)
			{
				switch (number_bits(2))
				{
					case 0:
						cat_sprintf(buf, "Threatening clouds gather on the %s horizon, blocking the sky from view.\n\r", wind_dir_name[area->weather_info->wind_dir]);
						break;
					case 1:
						cat_sprintf(buf, "Low clouds form on the %s horizon and slowly drift towards you.\n\r", wind_dir_name[area->weather_info->wind_dir]);
						break;
					case 2:
						cat_sprintf(buf, "Clouds sweep quickly across the %s horizon, darkening the skies above.\n\r", wind_dir_name[area->weather_info->wind_dir]);
						break;
					case 3:
						cat_sprintf(buf, "Bright white clouds drift lazily towards you from the %s horizon.\n\r", wind_dir_name[area->weather_info->wind_dir]);
						break;
				}
				area->weather_info->sky = SKY_CLOUDY;
			}
			break;

		case SKY_CLOUDY:
			if (area->weather_info->change > 6)
			{
				if (area->weather_info->temperature < 0)
				{
					switch (number_bits(2))
					{
						case 0:
							strcat(buf, "Snowflakes flutter down from the leaden skies above.\n\r");
							break;
						case 1:
							strcat(buf, "Lacy flakes of snow silently fall to the ground from the clouds above.\n\r");
							break;
						case 2:
							strcat(buf, "The clouds above give way to softly falling snow.\n\r");
							break;
						case 3:
							strcat(buf, "Snowflakes whisper down from the skies in a soft white dance.\n\r");
							break;
					}
				}
				else if (area->weather_info->temperature < 4)
				{
					switch (number_bits(2))
					{
						case 0:
							strcat(buf, "Snow begins to meld with icy rain as sleet falls to the ground.\n\r");
							break;
						case 1:
							strcat(buf, "Sharp sleet stings as it falls from the clouds above.\n\r");
							break;
						case 2:
							strcat(buf, "Icy sleet rains down from the heavens.\n\r");
							break;
						case 3:
							strcat(buf, "Sheets of stinging sleet fall from the dark clouds.\n\r");
							break;
					}
				}
				else
				{
					switch (number_bits(2))
					{
						case 0:
							strcat(buf, "Dark clouds break open, pouring rain down upon the lands.\n\r");
							break;
						case 1:
							strcat(buf, "Silvery drops of rain fall from angry looking clouds above.\n\r");
							break;
						case 2:
							strcat(buf, "Soft ribbons of rain slip unheeded from the dark skies overhead.\n\r");
							break;
						case 3:
							strcat(buf, "Fat raindrops merrily pepper the lands from the clouds looming above.\n\r");
							break;
					}
				}
				area->weather_info->change += 2;
				area->weather_info->sky     = SKY_RAINING;
			}
			else if (area->weather_info->change < 4)
			{
				switch (number_bits(2))
				{
					case 0:
						strcat(buf, "The clouds recede, revealing a crystal clear sky.\n\r");
						break;
					case 1:
						strcat(buf, "Dark clouds dip below the horizon as the skies clear.\n\r");
						break;
					case 2:
						strcat(buf, "The clouds swiftly move across the skies as it grows clear.\n\r");
						break;
					case 3:
						strcat(buf, "Clouds sigh softly as they disperse, leaving the skies clear.\n\r");
						break;
				}
				area->weather_info->change -= 2;
				area->weather_info->sky     = SKY_CLOUDLESS;
			}
			break;

		case SKY_RAINING:
			if (area->weather_info->change < 7)
			{
				if (area->weather_info->temperature < 0)
				{
					switch (number_bits(2))
					{
						case 0:
							strcat(buf, "A few last snowflakes swirl over the ground as the snow stops.\n\r");
							break;
						case 1:
							strcat(buf, "The world is left in silence as the snows stop falling.\n\r");
							break;
						case 2:
							strcat(buf, "The lands are blanketed in white as the last snowflakes fall.\n\r");
							break;
						case 3:
							strcat(buf, "With a final whisper, the snow stops falling.\n\r");
							break;
					}
				}
				else if (area->weather_info->temperature < 4)
				{
					switch (number_bits(2))
					{
						case 0:
							strcat(buf, "The final slivers of sleet fall from the dark clouds as it stops.\n\r");
							break;
						case 1:
							strcat(buf, "The miserable sleet falling from the clouds above stops.\n\r");
							break;
						case 2:
							strcat(buf, "The slippery razor-sharp sleet ends its assault on the lands.\n\r");
							break;
						case 3:
							strcat(buf, "The stinging sleet suddenly ceases as quickly as it began.\n\r");
							break;
					}
				}
				else
				{
					switch (number_bits(2))
					{
						case 0:
							strcat(buf, "The air smells fresh as the rain stops falling.\n\r");
							break;
						case 1:
							strcat(buf, "The clouds above dry their tears as the rain ceases.\n\r");
							break;
						case 2:
							strcat(buf, "The greyness above seems to ease as the rains halt.\n\r");
							break;
						case 3:
							strcat(buf, "A sweet scent fills the air as the rain suddenly stops.\n\r");
							break;
					}
				}
				area->weather_info->change -= 1;
				area->weather_info->sky     = SKY_CLOUDY;
			}
			else if (area->weather_info->wind_speed > 6)
			{
				if (area->weather_info->temperature < 0)
				{
					switch (number_bits(2))
					{
						case 0:
							strcat(buf, "A ferocious blizzard sweeps through the lands, burying them in white.\n\r");
							break;
						case 1:
							strcat(buf, "Heavy snows swirl in the air as the blizzard rages.\n\r");
							break;
						case 2:
							strcat(buf, "The snows fall heavily upon the ground as a blizzard takes hold.\n\r");
							break;
						case 3:
							strcat(buf, "Snowdrifts form quickly as the blizzard increases its fierceness.\n\r");
							break;
					}
				}
				else if (area->weather_info->temperature < 4)
				{
					switch (number_bits(2))
					{
						case 0:
							strcat(buf, "The clouds darken and thicken as they fill with hail.\n\r");
							break;
						case 1:
							strcat(buf, "Huge chunks of hail fall to the grounds with a sizzle.\n\r");
							break;
						case 2:
							strcat(buf, "Hail bombards the ground as creatures run for cover.\n\r");
							break;
						case 3:
							strcat(buf, "A shower of hail falls from the sky to pelts the lands below.\n\r");
							break;
					}
				}
				else
				{
					switch (number_bits(2))
					{
						case 0:
							strcat(buf, "The lands glow blue-white as lightning cracks across the sky.\n\r");
							break;
						case 1:
							strcat(buf, "Electricity fills the air as forks of lightning dance over the sky.\n\r");
							break;
						case 2:
							strcat(buf, "The horizon shines brightly as sheet lightning flashes in a quick stutter.\n\r");
							break;
						case 3:
							strcat(buf, "The winds gather speed as lightning paints the skies with broad strokes.\n\r");
							break;
					}
				}
				area->weather_info->wind_speed += 2;
				area->weather_info->sky         = SKY_LIGHTNING;
			}
			break;

		case SKY_LIGHTNING:
			if (area->weather_info->change < 7 || area->weather_info->wind_speed < 7)
			{
				if (area->weather_info->temperature < 0)
				{
					switch (number_bits(2))
					{
						case 0:
							strcat(buf, "The thick, swirling snow peters out as the blizzard ends.\n\r");
							break;
						case 1:
							strcat(buf, "The ferocity of the blizzard gives way as the snows diminish.\n\r");
							break;
						case 2:
							strcat(buf, "With a last gasp, the blizzard dwindles away to nothing.\n\r");
							break;
						case 3:
							strcat(buf, "With a final stroke of white, the blizzard dies out.\n\r");
							break;
					}
				}
				else if (area->weather_info->temperature < 4)
				{
					switch (number_bits(2))
					{
						case 0:
							strcat(buf, "The cannonade of hail comes to a sudden halt.\n\r");
							break;
						case 1:
							strcat(buf, "The burning hail ends its furious salvo of the lands.\n\r");
							break;
						case 2:
							strcat(buf, "The icy hot hail diminishes, retreating to the clouds above.\n\r");
							break;
						case 3:
							strcat(buf, "As swiftly as it started, the hailstorm recedes.\n\r");
							break;
					}
				}
				else
				{
					switch (number_bits(2))
					{
						case 0:
							strcat(buf, "With a few last flashes, the lightning moves down the horizon.\n\r");
							break;
						case 1:
							strcat(buf, "The skies turn ice blue and brilliant white with a final flash of lightning.\n\r");
							break;
						case 2:
							strcat(buf, "The heavens calm as the lightning storm ends.\n\r");
							break;
						case 3:
							strcat(buf, "The air is alive with electricity as the last fork of lightning appears.\n\r");
							break;
					}
				}
				area->weather_info->wind_speed -= 2;
				area->weather_info->sky         = SKY_RAINING;
			}
			break;
	}

	if (area->nplayer <= 0 || buf[0] == '\0')
	{
		return;
	}

	for (gch = mud->f_player ; gch ; gch = gch->next)
	{
		if (gch->ch->in_room->area != area)
		{
			continue;
		}
		if (!IS_OUTSIDE(gch->ch) || NO_WEATHER_SECT(gch->ch->in_room->sector_type))
		{
			continue;
		}
		if (!IS_AWAKE(gch->ch))
		{
			continue;
		}
		send_to_char(justify(buf, get_page_width(gch->ch)), gch->ch);
	}
}

void weather_update (void)
{
	AREA_DATA *area;

	push_call("weather_update()");

	for (area = mud->f_area ; area ; area = area->next)
	{
		weather_area_update(area);
	}

	pop_call();
	return;
}

void strip_greater (char *str)
{
	char *pt;

	push_call("strip_greater(%p)",str);

	for (pt = str; *pt != '\0'; pt++)
	{
		if (*pt == '<')
		{
			*pt = '(';
		}
		else if (*pt == '>')
		{
			*pt = ')';
		}
	}
	pop_call();
	return;
}


/* Make a html web page - Chaos  3/28/96 */

void save_html_who (void)
{
	FILE *fp;
	char buf[MAX_STRING_LENGTH], buf_race[20];
	char buf2[MAX_STRING_LENGTH];
	int leng;
	CHAR_DATA *fch;
	DESCRIPTOR_DATA *d;
	int nMatch;
	int nTotal;
	CHAR_DATA *wch;
	char const *class;
	char god;
	char killer_thief;
	PLAYER_GAME *fpl;
	char *pt;

	push_call("save_html_who()");

	/*
		Disabled since we're not using this atm - Scandum
	*/

	pop_call();
	return;

	close_reserve();

	fp = my_fopen ("../public_html/who.html", "w",TRUE);

	if (fp == NULL)
	{
		open_reserve();
		pop_call();
		return;
	}

	fprintf (fp, "<!DOCTYPE html PUBLIC \"-//IETF//DTD// HTML 2.0//EN\">\n");
	fprintf (fp, "<BODY BACKGROUND=\"bumps1.jpg\" text=#ffff30 alink=#80FF30 vlink=#90FF30 link=#FFFF30 >\n");

	fprintf (fp, "<HTML><HEAD><TITLE>E-Mud Who List</TITLE></HEAD>\n");
	fprintf (fp, "<BODY><FONT SIZE=+2><CENTER>\n");
	fprintf (fp, "E-Mud WHO Page<p>\n");

	/* Set default arguments. */

	fch = NULL;

	/* Now show matching chars. */

	nMatch = 0;
	nTotal = 0;
	buf[0] = '\0';
	leng = 0;
	for (fpl = mud->f_player ; fpl ; fpl = fpl->next)
	{
		wch = fpl->ch;
		d = NULL;
		if (is_desc_valid (wch))
			d = wch->desc;
		/* Check for match against restrictions.
		 * Don't use trust as that exposes trusted mortals.
		 * Chaos set to see all chars, invis or not.
		 */

		if (IS_SET (wch->act, PLR_WIZINVIS)|| IS_SET(wch->act,PLR_WIZCLOAK))
		{
			continue;
		}
		nTotal++;
		nMatch++;

	      /*
     	  * Figure out what to print for class.
	       */

		class = class_table[wch->class].who_name;
		switch (wch->level)
		{
			default:
				break;
			case MAX_LEVEL - 0:
				class = "GOD";
				break;
			case MAX_LEVEL - 1:
				class = "ARC";
				break;
			case MAX_LEVEL - 2:
				class = "ANG"; break;
				break;
		}

		strcpy (buf_race, race_table[wch->race].race_name);
		buf_race[3] = '\0';


		if (wch->level > MAX_LEVEL - 4)
			strcpy (buf_race, "---");

		god = god_table[wch->pcdata->god].who_letter[0];

		if (IS_SET (wch->act, PLR_KILLER))
		{
			killer_thief = 'K';
		}
		else if (IS_SET (wch->act, PLR_THIEF))
		{
			killer_thief = 'T';
		}
		else
		{
			killer_thief = ' ';
		}
		/*
		* Format it up.
		*/

		sprintf (buf2, "[%2d %s %s]%c%c%s%s",
			wch->level, class, buf_race, god, killer_thief, wch->name,
			IS_NPC (wch) ? "the monster" : wch->pcdata->title);
		buf2[71] = '\0';
		strip_greater (buf2);
		while (strlen (buf2) < 71)
		{
			str_cat_max (buf2, " ", MAX_STRING_LENGTH);\
		}
		leng = str_apd_max (buf, buf2, leng, MAX_STRING_LENGTH);

		if ((wch->pcdata->switched || wch->desc != NULL)
		&&  !IS_AFFECTED (wch, AFF_STEALTH))
		{
			strcpy (buf2, wch->in_room->area->name);
			buf2[8] = '\0';
			while (strlen (buf2) < 8)
			{
				str_cat_max (buf2, " ", MAX_STRING_LENGTH);
			}
		}
		else if (wch->desc == NULL)
		{
			strcpy (buf2, "LinkLost");
		}
		else
		{
			strcpy (buf2, "Unknown ");	/* Stealth Mode */
		}

		leng = str_apd_max (buf, " {", leng, MAX_STRING_LENGTH);
		leng = str_apd_max (buf, buf2, leng, MAX_STRING_LENGTH);
		leng = str_apd_max (buf, "} ", leng, MAX_STRING_LENGTH);

		/*  They don't need to see this either -  Chaos  4/30/99

		if (wch->desc != NULL && wch->desc->host != NULL)
		{
			leng = str_apd_max (buf, " (", leng, MAX_STRING_LENGTH);
			leng = str_apd_max (buf, wch->desc->host, leng, MAX_STRING_LENGTH);
			leng = str_apd_max (buf, ")", leng, MAX_STRING_LENGTH);
		}  */

		/*  Let's be a bit discreet here.   -  Chaos   4/25/99
		if (wch->pcdata->mail_address != NULL &&
			*wch->pcdata->mail_address != '\0')
		{
			leng = str_apd_max (buf, " Email: <a href=\"mailto:", leng, MAX_STRING_LENGTH);
			leng = str_apd_max (buf, wch->pcdata->mail_address, leng, MAX_STRING_LENGTH);
			leng = str_apd_max (buf, "\">", leng, MAX_STRING_LENGTH);
			leng = str_apd_max (buf, wch->pcdata->mail_address, leng, MAX_STRING_LENGTH);
			leng = str_apd_max (buf, "</a>", leng, MAX_STRING_LENGTH);
		}   */

		if (wch->pcdata->html_address != NULL && *wch->pcdata->html_address != '\0')
		{
			strcpy (buf2, wch->pcdata->html_address);
			for (pt = buf2; *pt != '\0'; pt++)
			{
				if (*pt == '*')
				{
					*pt = '~';
				}
			}
			leng = str_apd_max (buf, " Home Page: <a href=\"http://", leng, MAX_STRING_LENGTH);
			leng = str_apd_max (buf, buf2, leng, MAX_STRING_LENGTH);
			leng = str_apd_max (buf, "\">", leng, MAX_STRING_LENGTH);
			leng = str_apd_max (buf, buf2, leng, MAX_STRING_LENGTH);
			leng = str_apd_max (buf, "</a>", leng, MAX_STRING_LENGTH);
		}

		leng = str_apd_max (buf, "<p>\n", leng, MAX_STRING_LENGTH);
	}

	sprintf (buf2, "Players: %d</CENTER></font><p><font size=-1>\n", nTotal);


	fprintf (fp, "%s", buf2);
	fprintf (fp, "%s", buf);

	fprintf (fp, "</font></BODY></HTML>\n");

	if(fp) /* this prevents the possibility to my_fclose(NULL) - Manwe, 15-10-2000 */
	{
		my_fclose (fp);
	}

	open_reserve();

	pop_call();
	return;
}


void time_update (void)
{
	char buf[MAX_INPUT_LENGTH];
	AREA_DATA 		*area;
	PLAYER_GAME		*gpl;

	push_call("time_update()");

	mud->time_info->hour++;

	if (mud->time_info->hour >= 24)
	{
		mud->time_info->hour = 0;
		mud->time_info->day++;
	}

	if (mud->time_info->day >= 35)
	{
		mud->time_info->day = 0;
		mud->time_info->month++;
	}

	if (mud->time_info->month >= 16)
	{
		mud->time_info->month = 0;
		mud->time_info->year++;
	}

	switch (mud->time_info->hour)
	{
		case 5:
			mud->sunlight = SUN_RISE;
			break;
		case 6:
			mud->sunlight = SUN_LIGHT;
			break;

		case 19:
			mud->sunlight = SUN_SET;
			break;

		case 20:
			mud->sunlight = SUN_DARK;
			break;
	}

	for (area = mud->f_area ; area ; area = area->next)
	{


		if (area->nplayer == 0)
		{
			continue;
		}

		buf[0] = '\0';

		switch (mud->time_info->hour)
		{
			case 5:
				sprintf(buf, "The day has begun.\n\r");
				break;

			case 6:
				sprintf(buf, "The sun rises in the east.\n\r");
				break;

			case 19:
				sprintf(buf, "The sun slowly disappears in the west.\n\r");
				break;

			case 20:
				sprintf(buf, "The night has begun.\n\r");
				break;
		}

		if (buf[0] == '\0')
		{
			continue;
		}

		for (gpl = mud->f_player ; gpl ; gpl = gpl->next)
		{
			if (gpl->ch->in_room->area == area
			&&  IS_OUTSIDE(gpl->ch)
			&& !NO_WEATHER_SECT(gpl->ch->in_room->sector_type)
			&& IS_AWAKE(gpl->ch))
			{
				send_to_char(buf, gpl->ch);
			}
		}
	}
	pop_call();
	return;
}


void char_update (void)
{
	CHAR_DATA *ch;
	ROOM_TIMER_DATA *rtd, *rtd_next;
	AFFECT_DATA *paf, *paf_next;

	push_call("char_update()");

	for (rtd = mud->f_room_timer ; rtd ; rtd = rtd_next)
	{
		rtd_next = rtd->next;

		if (--rtd->timer <= 0)
		{
			switch (rtd->type)
			{
				case ROOM_TIMER_SANCTIFY:
					REMOVE_BIT(room_index[rtd->vnum]->room_flags, ROOM_SAFE);
					room_index[rtd->vnum]->sanctify_char = NULL;
					send_to_room("The area does not look safe now..\n\r", room_index[rtd->vnum]);
					break;

				case ROOM_TIMER_SMOKE:
					REMOVE_BIT(room_index[rtd->vnum]->room_flags, ROOM_SMOKE);
					send_to_room("The smoke dissipates.\n\r", room_index[rtd->vnum]);
					break;

				case ROOM_TIMER_GLOBE:
					REMOVE_BIT(room_index[rtd->vnum]->room_flags, ROOM_GLOBE);
					send_to_room("The shroud of darkness dissipates.\n\r", room_index[rtd->vnum]);
					break;

				case ROOM_TIMER_BLOCK:
					REMOVE_BIT(room_index[rtd->vnum]->room_flags, ROOM_BLOCK);
					send_to_room("The magical plant life withers and dies.\n\r", room_index[rtd->vnum]);
					break;

				case ROOM_TIMER_ICE:
					REMOVE_BIT(room_index[rtd->vnum]->room_flags, ROOM_ICE);
					send_to_room("The air becomes warmer as the ice sheets melt away.\n\r", room_index[rtd->vnum]);
					break;

				case ROOM_TIMER_UNBLOCK:
					SET_BIT(room_index[rtd->vnum]->room_flags, ROOM_BLOCK);
					send_to_room("All sorts of plant growth sprout up everywhere!\n\r", room_index[rtd->vnum]);
					break;
			}
			del_room_timer(rtd->vnum, rtd->type);
		}
	}

	for (ch = mud->f_char ; ch ; ch = mud->update_wch)
	{
		mud->update_wch = ch->next;

		if (!IS_NPC(ch))
		{
			if (ch->gold > 1000000 * ch->level)
			{
				ch->gold = 1000000 * ch->level;
			}

			if (ch->gold < 0)
			{
				ch->gold = 0;
			}

			if (ch->level < LEVEL_IMMORTAL)
			{
				if (ch->level < ch->in_room->area->low_hard_range || ch->level > ch->in_room->area->hi_hard_range)
				{
					char_to_room(ch, ROOM_VNUM_TEMPLE);
					ch->pcdata->death_room = ch->pcdata->recall = ROOM_VNUM_TEMPLE;
				}
			}

			if (IS_SET(ch->act, PLR_KILLER) && (ch->pcdata->played - ch->pcdata->killer_played) > 60 * 60 * 24)
			{
				REMOVE_BIT (ch->act, PLR_KILLER);
			}

			if (IS_SET(ch->act, PLR_OUTCAST) && (ch->pcdata->played - ch->pcdata->outcast_played) > 60 * 60 * 24)
			{
				REMOVE_BIT (ch->act, PLR_OUTCAST);
			}

			if (ch->pcdata->just_died_ctr > 0)
			{
				if (--ch->pcdata->just_died_ctr == 0)
				{
					send_to_char ("The Gods are no longer protecting you.\n\r", ch); break;
				}
			}

			if (++ch->timer > 20)
			{
				if (ch->in_room && ch->in_room->vnum != ROOM_VNUM_LIMBO)
				{
					if (!ch->pcdata->switched && !IS_IMMORTAL(ch))
					{
						ch->pcdata->was_in_room = ch->in_room->vnum;
						if (ch->fighting)
						{
							stop_fighting(ch, FALSE);
						}
						act("$n disappears into the void.", ch, NULL, NULL, TO_ROOM);
						act("You disappear into the void.", ch, NULL, NULL, TO_CHAR);
						save_char_obj(ch, NORMAL_SAVE);
						char_from_room(ch);
						char_to_room(ch, ROOM_VNUM_LIMBO);
					}
				}
			}

			ch->pcdata->idle++;

			gain_condition (ch, COND_DRUNK, -1);

			if (ch->level > 5 && ch->level < 95 && (!IS_UNDEAD(ch) || rspec_req(ch, RSPEC_VAMPIRIC)))
			{
				gain_condition (ch, COND_FULL,   -1);
				gain_condition (ch, COND_THIRST, -1);
			}
		}

		if (ch->position >= POS_STUNNED)
		{
			if (ch->hit < ch->max_hit)
			{
				ch->hit += hit_gain(ch);
			}

			if (ch->mana < ch->max_mana)
			{
				ch->mana += mana_gain(ch);
			}

			if (ch->move < ch->max_move)
			{
				ch->move += move_gain(ch);
			}
		}

		if (IS_NPC(ch))
		{
			if (ch->npcdata->pvnum_last_hit != 0)
			{
				if (ch->hit == ch->max_hit)
				{
					ch->npcdata->pvnum_last_hit = 0;

					RESTRING(ch->npcdata->hate_fear, "");
				}
			}

			if (ch->fighting == NULL && ch->position != POS_FIGHTING)
			{
				if (IS_SET(ch->pIndexData->affected_by, AFF_INVISIBLE) && !IS_SET(ch->affected_by, AFF_INVISIBLE))
				{
					SET_BIT(ch->affected_by, AFF_INVISIBLE );
				}
				if (IS_SET(ch->pIndexData->affected_by, AFF_HIDE) && !IS_SET(ch->affected_by, AFF_HIDE))
				{
					SET_BIT(ch->affected_by, AFF_HIDE);
				}
				if (IS_SET(ch->pIndexData->affected_by,  AFF_STEALTH) && !IS_SET(ch->affected_by, AFF_STEALTH))
				{
					SET_BIT(ch->affected_by, AFF_STEALTH);
				}
			}
		}

		update_pos(ch);

		if (ch->position == POS_DEAD)
		{
			raw_kill(ch);
			continue;
		}

		for (paf = ch->first_affect ; paf ; paf = paf_next)
		{
			paf_next = paf->next;

			if (paf->duration >= 0 && --paf->duration <= 0)
			{
				if (paf->type > 0 && skill_table[paf->type].msg_off)
				{
					if (paf->next == NULL || paf->type != paf->next->type)
					{
						ch_printf(ch, "%s\n\r", skill_table[paf->type].msg_off);
					}
				}

				switch (paf->bitvector)
				{
					case AFF_CHARM:
						raw_kill(ch);
						continue;

					case AFF2_POSSESS:
						raw_kill(ch);
						continue;

					case AFF_SLEEP:
						if (IS_NPC(ch))
						{
							ch->position = ch->pIndexData->position;
						}
						break;
				}

				if (paf->type == gsn_polymorph)
				{
					do_polymorph(ch, NULL);
					continue;
				}

				affect_from_char(ch, paf);
			}
		}

		if (IS_AFFECTED(ch, AFF_POISON))
		{
			act ("$n shivers and suffers.", ch, NULL, NULL, TO_ROOM);
			send_to_char ("You shiver and suffer.\n\r", ch);
			damage (ch, ch, 2 + ch->level / 3, TYPE_NOFIGHT);
		}
		if (ch->position < POS_STUNNED)
		{
			damage(ch, ch, ch->position, TYPE_UNDEFINED);
		}

		if (!MP_VALID_MOB(ch))
		{
			if (ch->desc && CH(ch->desc)->pcdata->vt100 == 1)
			{
				vt100prompt (ch);
			}
			continue;
		}

		if (ch->timer > 0)
		{
			ch->timer--;
			if (ch->timer == 0)
			{
				mprog_delay_trigger(ch, ch->npcdata->delay_index);
			}
		}

		if (IS_SET(ch->pIndexData->progtypes, TIME_PROG))
		{
			if (!MP_VALID_MOB(ch) || ch->position < POS_RESTING || ch->position == POS_FIGHTING)
			{
				continue;
			}
			mprog_time_check(ch, NULL, NULL, NULL, TIME_PROG);
		}
	}

	{
		static int lastHour;

		mud->usage->players[mud->time.tm_hour][mud->time.tm_wday] = mud->total_plr;

		if (lastHour != mud->time.tm_hour)
		{
			save_usage();
			save_hiscores();
			bounty_update();
			save_timeinfo();

			/*
				Check for Clan Rent, Purger, Backup - Scandum 03-09-2002
			*/

			if (mud->time.tm_hour == 0)
			{
				log_printf("Backing up player files.");

				system("cd ..;./backup&");
			}

			if (mud->time.tm_wday == 0 && mud->time.tm_hour == 0)
			{
				if (IS_SET(mud->flags, MUD_CLANRENT))
				{
					if (mud->f_clan == NULL)
					{
						log_printf("There are no clans.");
					}
					else
					{
						do_forcerent(NULL, NULL);
					}
					REMOVE_BIT(mud->flags, MUD_CLANRENT);

					start_purger();
				}
			}
			else if (mud->time.tm_hour != 0)
			{
				SET_BIT(mud->flags, MUD_CLANRENT);
			}
		}
		lastHour = mud->time.tm_hour;
	}

	/*
		Minutely update on the WHO HTML Page    -   Chaos 3/26/96
		We're not using this atm - Scandum
		if (IS_SET(mud->flags, MUD_EMUD_REALGAME))
		{
			save_html_who();
		}
	*/

	pop_call();
	return;
}

/*
	Update all objs.
*/

void obj_update (void)
{
	OBJ_DATA *obj;
	CHAR_DATA *owner;
	AFFECT_DATA *paf, *paf_next;
	char *message;

	push_call("obj_update()");

	for (obj = mud->f_obj ; obj ; obj = mud->update_obj)
	{
		mud->update_obj = obj->next;

		/*
			Look for enhanced objects
		*/

		if (obj->item_type != obj->pIndexData->item_type)
		{
			obj->item_type = obj->pIndexData->item_type;

			obj->value[0] = obj->pIndexData->value[0];
			obj->value[1] = obj->pIndexData->value[1];
			obj->value[2] = obj->pIndexData->value[2];
			obj->value[3] = obj->pIndexData->value[3];

			log_printf("obj_update: bad item type: %d", obj->pIndexData->vnum);
		}

		switch (obj->item_type)
		{
			case ITEM_ARMOR:
			case ITEM_WEAPON:
				if (IS_SET(obj->extra_flags, ITEM_MODIFIED))
				{
					if (obj->value[0] != obj->pIndexData->value[0]
					||  obj->value[1] != obj->pIndexData->value[1]
					||  obj->value[2] != obj->pIndexData->value[2]
					||  obj->value[3] != obj->pIndexData->value[3])
					{
						obj->value[0] = obj->pIndexData->value[0];
						obj->value[1] = obj->pIndexData->value[1];
						obj->value[2] = obj->pIndexData->value[2];
						obj->value[3] = obj->pIndexData->value[3];
					}
				}
				break;

			case ITEM_CONTAINER:
				if (obj->carried_by == NULL && IS_SET(obj->value[1], CONT_CLOSEABLE) && !IS_SET(obj->value[1], CONT_CLOSED))
				{
					SET_BIT(obj->value[1], CONT_CLOSED);

					if (obj->value[2] > 0)
					{
						SET_BIT(obj->value[1], CONT_LOCKED);
					}
				}
				break;

			case ITEM_LIGHT:
				if (obj->value[0] != obj->pIndexData->value[0])
				{
					obj->value[0] = obj->pIndexData->value[0];
				}
				if (obj->wear_loc == WEAR_LIGHT && obj->carried_by && obj->carried_by->desc && obj->carried_by->desc->connected >= CON_PLAYING)
				{
					if (obj->value[2] > 1 && obj->value[2] < 5)
					{
						act ("$p flickers.", obj->carried_by, obj, NULL, TO_CHAR);
					}
					if (obj->value[2] > 0)
					{
						SET_BIT(obj->extra_flags, ITEM_MODIFIED);

						if (--obj->value[2] == 0)
						{
							act ("$p goes out.", obj->carried_by, obj, NULL, TO_ROOM);
							act ("$p goes out.", obj->carried_by, obj, NULL, TO_CHAR);
							junk_obj(obj);
							continue;
						}
					}
				}
				break;

			case ITEM_ARTIFACT:
				if (obj->value[0] && obj->value[0] < mud->current_time)
				{
					if (obj->carried_by)
					{
						act("$p has started to decay.", obj->carried_by, obj, NULL, TO_CHAR);
					}
					obj->value[0]	= 0;
					obj->timer	= OBJ_SAC_TIME;
				}
				break;
			case ITEM_TOTEM:
				totem_cast_spell(obj);
				break;
		}

		for (paf = obj->first_affect ; paf ; paf = paf_next)
		{
			paf_next = paf->next;

			if (paf->duration >= 0 && --paf->duration <= 0)
			{
				if (obj->carried_by)
				{
					act(skill_table[paf->type].msg_obj_off, obj->carried_by, obj, NULL, TO_CHAR);
				}
				if (obj->in_room && obj->in_room->first_person)
				{
					act(skill_table[paf->type].msg_obj_off, obj->in_room->first_person, obj, NULL, TO_CHAR);
					act(skill_table[paf->type].msg_obj_off, obj->in_room->first_person, obj, NULL, TO_ROOM);
				}
				affect_from_obj(obj, paf);
			}
		}

		if (!IS_SET(obj->extra_flags, ITEM_NOT_VALID)
		&&  !IS_SET(obj->pIndexData->extra_flags, ITEM_NOT_VALID))
		{
			if (obj->timer == 0 && obj->sac_timer == 0)
			{
				continue;
			}

			if (obj->in_room == NULL)
			{
				if (obj->timer == 0 || (obj->timer > 0 && --obj->timer > 0))
				{
					continue;
				}
			}
			if (obj->in_room != NULL)
			{
				if (IS_SET(obj->in_room->room_flags, ROOM_CLAN_DONATION))
				{
					if (obj->timer == 0 || (obj->timer > 0 && --obj->timer > 0))
					{
						continue;
					}
				}
				else
				{
					if ((obj->timer == 0     || (obj->timer > 0     && --obj->timer     > 0))
					&&  (obj->sac_timer == 0 || (obj->sac_timer > 0 && --obj->sac_timer > 0)))
					{
						continue;
					}
				}
			}
		}

		switch (obj->item_type)
		{
			default:
				message = "$p vanishes.";
				break;
			case ITEM_FOUNTAIN:
				message = "$p dries up.";
				break;
			case ITEM_CORPSE_NPC:
			case ITEM_CORPSE_PC:
				message = "$p decays into dust.";
				break;
			case ITEM_FOOD:
				message = "$p decomposes.";
				break;
			case ITEM_ARTIFACT:
				message = "$p cackles in delight as the last vestiges of its power dies away.";
				break;
		}

		if (obj->carried_by != NULL)
		{
			act (message, obj->carried_by, obj, NULL, TO_CHAR);
		}
		else if (obj->in_room != NULL && obj->in_room->first_person != NULL)
		{
			act (message, obj->in_room->first_person, obj, NULL, TO_ROOM);
			act (message, obj->in_room->first_person, obj, NULL, TO_CHAR);
		}

		while (obj->first_content)
		{
			if (obj->carried_by)
			{
				obj_to_char(obj->first_content, obj->carried_by);
			}
			else if (obj->in_room)
			{
				obj->first_content->sac_timer = OBJ_SAC_TIME;
				obj_to_room(obj->first_content, obj->in_room->vnum);
			}
			else
			{
				junk_obj(obj->first_content);
			}
		}

		if (obj->owned_by
		&& (owner = get_char_pvnum(obj->owned_by)) != NULL
		&&  owner->pcdata->corpse == obj)
		{
			send_to_char("Your corpse decays.\n\r", owner);
			owner->pcdata->corpse = find_char_corpse (owner, TRUE);
			save_char_obj(owner, NORMAL_SAVE);
		}
		junk_obj(obj);
	}
	pop_call();
	return;
}

void aggr_update (void)
{
	CHAR_DATA *ich;
	CHAR_DATA *ch;
	AREA_DATA *area;
	PLAYER_GAME *npl, *next_npl;
	int vnum;

	push_call("aggr_update()");

	for (area = mud->f_area ; area ; area = area->next)
	{
		for (vnum = area->low_m_vnum ; vnum <= area->hi_m_vnum ; vnum++)
		{
			if (mob_index[vnum] == NULL)
			{
				continue;
			}

			if (!IS_SET(mob_index[vnum]->progtypes, DELAY_PROG))
			{
				continue;
			}

			for (ich = mob_index[vnum]->first_instance ; ich ; ich = mud->update_ich)
			{
				mud->update_ich = ich->next_instance;
	
				if (ich->wait > 0 && !ich->desc)
				{
					ich->wait--;

					if (ich->wait == 0 && MP_VALID_MOB(ich))
					{
						mprog_delay_trigger(ich, ich->npcdata->delay_index);
					}
				}
			}
		}
	}

	for (npl = mud->f_player ; npl ; npl = next_npl)
	{
		next_npl = npl->next;

		if (npl->ch->level >= LEVEL_IMMORTAL)
		{
			continue;
		}

		if (npl->ch->desc == NULL && npl->ch->wait > 0)
		{
			npl->ch->wait = UMAX(0, npl->ch->wait - PULSE_AGGRESSIVE);
		}

		for (ch = npl->ch->in_room->first_person ; ch ; ch = mud->update_rch)
		{
			mud->update_rch = ch->next_in_room;

			if (!IS_NPC(ch) || !IS_SET(ch->act, ACT_AGGRESSIVE))
			{
				continue;
			}

			if (!MP_VALID_MOB(ch))
			{
				continue;
			}

			if (!IS_AWAKE(ch) || ch->fighting || ch->hit < ch->max_hit/2)
			{
				continue;
			}

			if (IS_SET(ch->act, ACT_WIMPY) && IS_AWAKE(npl->ch))
			{
				continue;
			}

			if (!can_see(ch, npl->ch) || number_bits(1) == 0)
			{
				continue;
			}

			if (abs(npl->ch->alignment - ch->alignment) <= 500)
			{
				if (npl->ch->class == CLASS_SHAMAN || number_bits(1) == 0)
				{
					continue;
				}
			}
			multi_hit(ch, npl->ch, TYPE_UNDEFINED);
		}
	}
	pop_call();
	return;
}


void purger_update (void)
{
	JUNK_DATA *junk;

	push_call("purger_update(void)");

	while (mud->f_junk)
	{
		junk = mud->f_junk;

		if (junk->mob)
		{
			extract_char(junk->mob);
		}
		else
		{
			extract_obj(junk->obj);
		}
		UNLINK(junk, mud->f_junk, mud->l_junk, next, prev);
		FREEMEM(junk);
	}
	pop_call();
	return;
}

/*
	Called once per pulse from game loop.
	Random times to defeat tick-timing clients and players.
	Update routines spread out over 10 pulses
	Scandum - 14-05-2003
*/

void update_handler (void)
{
	static sh_int pulse_areasave		= 9 + PULSE_AREASAVE;
	static sh_int pulse_shops		= 9 + PULSE_SHOPS;
	static sh_int pulse_area			= 9 + PULSE_TICK;
	static sh_int pulse_weather		= 9 + PULSE_TICK;
	static sh_int pulse_obj			= 8 + PULSE_TICK;
	static sh_int pulse_tick			= 7 + PULSE_TICK;
	static sh_int pulse_charsave		= 6 + PULSE_CHARSAVE;
	static sh_int pulse_mobprog		= 4 + PULSE_PROGRAM;
	static sh_int pulse_objprog		= 3 + PULSE_PROGRAM;
	static sh_int pulse_violence		= 2 + PULSE_VIOLENCE;
	static sh_int pulse_mobile		= 1 + PULSE_MOBILE;
	static sh_int pulse_aggressive	= 0 + PULSE_AGGRESSIVE;

	push_call("update_handler()");

	if (--pulse_areasave <= 0)
	{
		pulse_areasave = PULSE_AREASAVE;
		start_timer(TIMER_AREA_SAVE);
		auto_area_save();
		close_timer(TIMER_AREA_SAVE);
	}

	if (--pulse_shops <= 0)
	{
		pulse_shops = PULSE_SHOPS;
		start_timer (TIMER_SHOP_UPD);
		shop_update ();
		close_timer (TIMER_SHOP_UPD);
	}

	if (--pulse_tick <= 0)
	{
		pulse_tick = PULSE_TICK / 2 + 10 * number_range(0, PULSE_TICK / 10);
		start_timer (TIMER_CHAR_UPD);
		time_update();
		char_update();
		close_timer(TIMER_CHAR_UPD);
	}

	if (--pulse_area <= 0)
	{
		pulse_area = PULSE_AREA / 2 + 10 * number_range(0, PULSE_AREA / 10);
		start_timer (TIMER_AREA_UPD);
		area_update ();
		close_timer (TIMER_AREA_UPD);
	}

	if (--pulse_weather <= 0)
	{
		pulse_weather = PULSE_TICK / 2 + 10 * number_range(0, PULSE_TICK / 10);
		start_timer (TIMER_WEATHER_UPD);
		weather_update ();
		close_timer (TIMER_WEATHER_UPD);
	}

	if (--pulse_obj <= 0)
	{
		pulse_obj = PULSE_TICK / 2 + 10 * number_range(0, PULSE_TICK / 10);
		start_timer (TIMER_OBJ_UPD);
		obj_update ();
		close_timer (TIMER_OBJ_UPD);
	}

	if (--pulse_charsave <= 0)
	{
		pulse_charsave = PULSE_CHARSAVE;
		start_timer( TIMER_CHAR_SAVE );
		auto_char_save();
		close_timer( TIMER_CHAR_SAVE );
	}

	if (--pulse_violence <= 0)
	{
		pulse_violence = PULSE_VIOLENCE;
		start_timer (TIMER_VIOL_UPD);
		violence_update ();
		close_timer (TIMER_VIOL_UPD);
	}

	if (--pulse_mobprog <= 0)
	{
		pulse_mobprog = PULSE_PROGRAM;
		start_timer(TIMER_MOB_PROG);
		mob_program_update();
		close_timer(TIMER_MOB_PROG);
	}

	if (--pulse_objprog <= 0)
	{
		pulse_objprog = PULSE_PROGRAM;
		start_timer(TIMER_OBJ_PROG);
		obj_program_update();
		close_timer(TIMER_OBJ_PROG);
	}

	if (--pulse_mobile <= 0)
	{
		pulse_mobile = PULSE_MOBILE;
		start_timer (TIMER_MOB_UPD);
		mobile_update();
		close_timer (TIMER_MOB_UPD);
	}

	if (--pulse_aggressive <= 0)
	{
		pulse_aggressive = PULSE_AGGRESSIVE;
		start_timer (TIMER_AGGR_UPD);
		aggr_update();
		close_timer (TIMER_AGGR_UPD);
	}

	{
		start_timer (TIMER_PURGE);
		purger_update();
		if (IS_SET(mud->flags, MUD_PURGER))
		{
			update_purger();
		}
		close_timer (TIMER_PURGE);
	}

	pop_call();
	return;
}


int exp_level (int class, int level)
{
	float a, b, c, d, num, cap, inc, onum;
	int cnt, lv;

	push_call("exp_level(%p,%p)",class,level);

	if (level == 0)
	{
		pop_call();
		return (0);
	}

	switch (class)
	{
		case CLASS_WARRIOR:
			a = 1600.0;
			b = 1.56;
			c = 1666.0;
			d = 0 - 250.0;
			cap = 4000000;
			inc = 1650000;
			break;

		case CLASS_GLADIATOR:
			a = 1600.0;
			b = 1.58;
			c = 1500.0;
			d = 0 - 250.0;
			cap = 4500000;
			inc = 1800000;
			break;

		case CLASS_MARAUDER:
			a = 1500.0;
			b = 1.50;
			c = 1500.0;
			d = 0 - 300;
			cap = 3000000;
			inc = 1500000;
			break;

		case CLASS_NINJA:
			a = 1550.0;
			b = 1.54;
			c = 1500.0;
			d = 0 - 300.0;
			cap = 4000000;
			inc = 1600000;
			break;


		case CLASS_DRUID:
			a = 1525.0;
			b = 1.51;
			c = 1500.0;
			d = 0 - 300.0;
			cap = 4000000;
			inc = 1550000;
			break;

		case CLASS_SORCERER:
			a = 1550.0;
			b = 1.55;
			c = 1500.0;
			d = 0 - 300.0;
			cap = 4000000;
			inc = 1700000;
			break;

		case CLASS_SHAMAN:
			a = 1525.0;
			b = 1.53;
			c = 1500.0;
			d = 0 - 300.0;
			cap = 3500000;
			inc = 1550000;
			break;

		case CLASS_WARLOCK:
			a = 1575.0;
			b = 1.57;
			c = 1500.0;
			d = 0 - 250.0;
			cap = 4500000;
			inc = 1750000;
			break;

		case CLASS_MONSTER:
			a = 45.0;
			b = 1.35;
			c = 120.0;
			d = 0;
			cap = 50000;
			inc = 7000;
			break;

		default:
			pop_call();
			return (0);
	}

	num = b;

	for (cnt = 1 ; cnt < level ; cnt++)
	{
		num *= b;
	}

	num = a * num + c * (level - 1) + d;

	if (num < cap)
	{
		pop_call();
		return ((int) num);
	}
	lv = 12;
	num = 0;
	while (num < cap)
	{
		onum = b;
		for (cnt = 1 ; cnt < lv ; cnt++)
		{
			onum *= b;
		}
		onum = a * onum + c * (lv - 1) + d;
		if (num < cap)
		{
			num = onum;
			lv++;
		}
	}
	for (; lv <= level; lv++)
	{
		num += inc;
		if (class != CLASS_MONSTER)
		{
			inc = (int) ((float) inc * 1.03);
		}
		else
		{
			inc = (int) ((float) inc * 1.01);
		}
	}
	pop_call();
	return ((int) num);
}


void bounty_update( void )
{
	BOUNTY_DATA *bounty, *bounty_next;

	push_call("bounty_update()");

	for (bounty = mud->f_bounty ; bounty ; bounty = bounty_next)
	{
		bounty_next = bounty->next;

		if (bounty->expires < mud->current_time)
		{
			remove_bounty( bounty );
			save_bounties();
		}
	}
	pop_call();
	return;
}


void set_room_timer(int vnum, int type, int timer)
{
	ROOM_TIMER_DATA *rtd;

	push_call("set_room_timer(%d,%d,%d)",vnum,type,timer);

	ALLOCMEM(rtd, ROOM_TIMER_DATA, 1);

	rtd->vnum		= vnum;
	rtd->type		= type;
	rtd->timer	= timer;

	LINK(rtd, mud->f_room_timer, mud->l_room_timer, next, prev);

	pop_call();
	return;
}


bool del_room_timer(int vnum, int type)
{
	ROOM_TIMER_DATA *rtd;

	push_call("del_room_timer(%d,%d)",vnum,type);

	for (rtd = mud->f_room_timer ; rtd ; rtd = rtd->next)
	{
		if (rtd->vnum == vnum && type == -1)
		{
			rtd->vnum = ROOM_VNUM_JUNK;
			continue;
		}

		if (rtd->vnum == vnum && rtd->type == type)
		{
			break;
		}
	}

	if (rtd)
	{
		UNLINK(rtd, mud->f_room_timer, mud->l_room_timer, next, prev);

		FREEMEM(rtd);

		pop_call();
		return TRUE;
	}

	pop_call();
	return FALSE;
}