mud++0.35/etc/
mud++0.35/etc/guilds/
mud++0.35/help/propert/
mud++0.35/mudC/
mud++0.35/player/
mud++0.35/src/interface/
mud++0.35/src/os/cygwin32/
mud++0.35/src/os/win32/
mud++0.35/src/os/win32/bcppbuilder/
mud++0.35/src/osaddon/
mud++0.35/src/util/
/*
....[@@@..[@@@..............[@.................. MUD++ is a written from
....[@..[@..[@..[@..[@..[@@@@@....[@......[@.... scratch multi-user swords and
....[@..[@..[@..[@..[@..[@..[@..[@@@@@..[@@@@@.. sorcery game written in C++.
....[@......[@..[@..[@..[@..[@....[@......[@.... This server is an ongoing
....[@......[@..[@@@@@..[@@@@@.................. development project.  All 
................................................ contributions are welcome. 
....Copyright(C).1995.Melvin.Smith.............. Enjoy. 
------------------------------------------------------------------------------
Melvin Smith (aka Fusion)         msmith@hom.net 
MUD++ development mailing list    mudpp@van.ml.org
------------------------------------------------------------------------------
pulse.cc
*/

#include "config.h"
#include "string.h"
#include "llist.h"
#include "room.h"
#include "hash.h"
#include "area.h"
#include "pc.h"
#include "npc.h"
#include "object.h"
#include "env.h"

#include "global.h"

Environment envir;

const int MAX_IDLE = 100;

const int PULSE_NPC = 8;
const int PULSE_OBJ = 8;
const int PULSE_VM = PULSE_PER_SEC;
const int PULSE_PC = 10;
const int PULSE_COMBAT = 3;
const int PULSE_UPDATE = 45;

void pulseArea();
void pulseIdle();
void pulsePC();
void pulseNPC();
void pulseObj();
void pulseCombat();
void pulseVM();
void wakeSleepingVM();

// Heartbeat of the game.
// This is what makes the MUD run.

void heartbeat()
{
	static int combat_timer = PULSE_COMBAT;	
	static int npc_timer = PULSE_NPC;
	static int obj_timer = PULSE_OBJ;
	static int vm_timer = PULSE_VM;
	static int pc_timer = PULSE_PC;
	static int update_timer = PULSE_UPDATE;

	if( ! combat_timer-- )
	{
		pulseCombat();
		combat_timer = PULSE_COMBAT;
	}

	if( ! npc_timer-- )
	{
		pulseNPC();
		npc_timer = PULSE_NPC; 
	}

	if( ! obj_timer-- )
	{
		pulseObj();
		obj_timer = PULSE_OBJ; 
	}

	if( ! pc_timer-- )
	{
		pulsePC();
		pc_timer = PULSE_PC;
	}

	if( ! vm_timer-- )
	{
		pulseVM();
		vm_timer = PULSE_VM;
	}

	if( ! update_timer-- )
	{
		wakeSleepingVM();
		envir.update();
		pulseArea();
		pulseIdle();
		update_timer = PULSE_UPDATE;	
	}
}


void action_heartbeat()
{
	Action *act;

	actions.reset();
	while ( ( act = actions.peek() ) )
	{
		actions.next();
		if ( act->getType() == 0 )
			act->update();
	}
	Cout.flush();
}


void pulseArea()
{
	Area * area;
	for_each( areas, area )
		area->tick();
}


void pulsePC()
{
	PC *pc;
	LList<PC> tlist = pcs;
	for_each( tlist, pc )
		pc->pulse();
}


void pulseIdle()
{
	PC *pc;
	LList<PC> tlist = pcs;
	for_each( tlist, pc )
	{
		pc->idle();

		// Wizzes can idle all they want.
		if( pc->authorized( WIZARD ) )
			continue;

		if( pc->getIdle() > MAX_IDLE )
			pc->setState( STATE_BOOT );
		else if( pc->getIdle() == MAX_IDLE )
			pc->out( "You have been idle. Autologout next pulse.\n\r" );
	}
}


void pulseNPC()
{
	NPC *npc;
	LList<NPC> tlist = npcs;
	for_each( tlist, npc )
	{
		if ( npc->TgUpdate() )
			continue;

		if ( npc->isBusy() )
			continue;

		if( randgen.get( 0, 4 ) )
			continue;

		npc->moveDir( randgen.get( 0, 5 ) );
	}
}


void pulseObj()
{
	Object *obj;
	objects.reset();

	while( ( obj = objects.peek() ) )
	{
		if ( obj->TgUpdate() )
		{
			objects.next();
			continue;
		}

		if( obj->getTimer() > 0 )
		{
			if( obj->tick() )
			{
				objects.next();
				continue;
			}
			
			if ( obj->TgTimerOut() )
			{
				objects.next();
				continue;
			}

			if( obj->inRoom() )
			{
				obj->inRoom()->out( obj->getShort() );
				obj->inRoom()->out( " decays into dust.\n\r" );

				if( obj->isCorpse() )
				{
					obj->setName( "pile bones" );
					obj->setShort( "a pile of old bones" );
					obj->setLong( "A pile of old bones is here." );
					objects.next();
					continue;
				}

				obj->inRoom()->rmObjInv( obj );
			}
			else if( obj->carriedBy() )
			{
				obj->carriedBy()->out( obj->getShort() );
				obj->carriedBy()->out( " crumbles in your hands.\n\r" );
				obj->carriedBy()->rmObjInv( obj );
			}
			else if( obj->inObj() )
			{
				obj->inObj()->rmObjInv( obj );
			}

			// call to remove expects obj to be current.
			// after remove current points to the next node so no ++
			objects.remove();
			obj->fordelete();
		}
		else
		{
			objects.next();
		}
	}
}


void pulseCombat()
{
	Char *ch;
	Char *vict;

	// Run through npc list first	
	// Do somethin here with isBusy()
	for_each( npcs, ch )
	{
		vict = ch->getFighting();
		if( !vict )
			continue;

		ch->attack( vict, -1 );
	}

	for_each( pcs, ch )
	{
		vict = ch->getFighting();
		if( !vict )
			continue;

		ch->attack( vict, -1 );
	}
}