/***************************************************************************
 *  file: mob_act.c , Mobile action module.                Part of DIKUMUD *
 *  Usage: Procedures generating 'intelligent' behavior in the mobiles.    *
 *  Copyright (C) 1990, 1991 - see 'license.doc' for complete information. *
 *                                                                         *
 *  Copyright (C) 1992, 1993 Michael Chastain, Michael Quan, Mitchell Tse  *
 *  Performance optimization and bug fixes by MERC Industries.             *
 *  You can use our stuff in any way you like whatsoever so long as this   *
 *  copyright notice remains intact.  If you like it please drop a line    *
 *  to mec@garnet.berkeley.edu.                                            *
 *                                                                         *
 *  This is free software and you are benefitting.  We hope that you       *
 *  share your changes too.  What goes around, comes around.               *
 ***************************************************************************/

#include <stdio.h>

#include "structs.h"
#include "mob.h"
#include "obj.h"
#include "utils.h"
#include "db.h"

extern struct char_data *character_list;
extern struct index_data *mob_index;
extern struct room_data *world;
extern struct str_app_type str_app[];

void mobile_activity(void)
{
    register struct char_data *ch;
    struct char_data *tmp_ch;
    struct obj_data *obj, *best_obj;
    int door, max;

    void do_move(struct char_data *ch, char *argument, int cmd);
    void do_get(struct char_data *ch, char *argument, int cmd);

    /* Examine all mobs. */
    for ( ch = character_list; ch; ch = ch->next )
    {
	if ( !IS_MOB(ch) )
	    continue;

	/* Examine call for special procedure */
	if ( IS_SET(ch->specials.act, ACT_SPEC) )
	{
	    if (!mob_index[ch->nr].func)
	    {
		sprintf( log_buf, "Mobile_activity: MOB %d no func",
			mob_index[ch->nr].virtual );
		log( log_buf );
		REMOVE_BIT( ch->specials.act, ACT_SPEC );
	    }
	    else
	    {
		if ( (*mob_index[ch->nr].func) (ch, 0, "") )
		    continue;
	    }
	}

	/* That's all for busy monster */
	if ( !AWAKE(ch) || ch->specials.fighting )
	    continue;

	/* Scavenge */
	if ( IS_SET(ch->specials.act, ACT_SCAVENGER)
	&& world[ch->in_room].contents && number(0,10) == 0 )
	{
	    max         = 1;
	    best_obj    = 0;
	    for ( obj = world[ch->in_room].contents; obj;
		obj = obj->next_content )
	    {
		if ( CAN_GET_OBJ(ch, obj) && obj->obj_flags.cost > max )
		{
		    best_obj    = obj;
		    max         = obj->obj_flags.cost;
		}
	    }

	    if ( best_obj )
	    {
		obj_from_room( best_obj );
		obj_to_char( best_obj, ch );
		act( "$n gets $p.", FALSE, ch, best_obj, 0, TO_ROOM );
	    }
	}

	/* Wander */
	if ( !IS_SET(ch->specials.act, ACT_SENTINEL)
	&& GET_POS(ch) == POSITION_STANDING
	&& (door = number(0,45)) <= 5
	&& CAN_GO(ch, door)
	&& !IS_SET(world[EXIT(ch,door)->to_room].room_flags, NO_MOB|DEATH) )
	{
	    if (ch->specials.last_direction == door)
	    {
		ch->specials.last_direction = -1;
	    }
	    else if ( !IS_SET(ch->specials.act, ACT_STAY_ZONE)
	    || world[EXIT(ch, door)->to_room].zone == world[ch->in_room].zone )
	    {
		ch->specials.last_direction = door;
		do_move( ch, "", ++door );
	    }
	}

	/* Aggress */
	if ( IS_SET(ch->specials.act, ACT_AGGRESSIVE) )
	{
	    for ( tmp_ch = world[ch->in_room].people; tmp_ch;
	    tmp_ch = tmp_ch->next_in_room )
	    {
		if ( IS_NPC(tmp_ch) || !CAN_SEE(ch, tmp_ch) )
		    continue;
		if ( IS_SET(ch->specials.act, ACT_WIMPY) && AWAKE(tmp_ch) )
		    continue;

		if ( ( IS_SET(ch->specials.act, ACT_AGGR_EVIL)
		    && IS_EVIL(tmp_ch) ) 
		||   ( IS_SET(ch->specials.act, ACT_AGGR_NEUT)
		    && IS_NEUTRAL(tmp_ch) ) 
		||   ( IS_SET(ch->specials.act, ACT_AGGR_GOOD)
		    && IS_GOOD(tmp_ch) )
		||   ( ch->specials.act & ACT_AGGR_ALL ) == 0 )
		{
		  hit(ch, tmp_ch, 0);
		  break;
		}
	    }
	}

    }
}