/*
  SillyMUD Distribution V1.1b             (c) 1993 SillyMUD Developement
 
  See license.doc for distribution terms.   SillyMUD is based on DIKUMUD

  With an attempt by Rip to convert to merc 2.1
*/

#include <stdio.h>

#include "merc.h"
#include "hash.h"

struct hunting_data {
  char	*name;
  struct char_data **victim;
};

struct room_q
{
  int	room_nr;
  struct room_q	*next_q;
};

struct nodes
{
  int	visited;
  int	ancestor;
};

int exit_ok( EXIT_DATA *pexit )
{
	ROOM_INDEX_DATA *to_room;

	if ( ( pexit == NULL )
	||   ( to_room = pexit->to_room ) == NULL )
		return (0);

	return (1);
}

void donothing()
{
	return;
}

#define IS_DIR	(get_room_index(q_head->room_nr)->exit[i])

#define GO_OK (!IS_SET( IS_DIR->exit_info, EX_CLOSED ) \
		|| IS_AFFECTED( ch, AFF_PASS_DOOR ) )

/*
#define GO_OK_SMARTER ( !IS_SET( IS_DIR->exit_info, EX_LOCKED ) \
			|| IS_AFFECTED( ch, AFF_PASS_DOOR ) )
*/
#define GO_OK_SMARTER 1

int find_path(int in_room_vnum, int out_room_vnum, CHAR_DATA *ch, 
	      int depth, int in_zone)
{
   struct room_q *tmp_q, *q_head, *q_tail;
#if 1
  struct hash_header	x_room;
/*  static struct hash_header	x_room; */
#else
  struct nodes x_room[MAX_ROOMS];
#endif
   int i, tmp_room, count=0, thru_doors;
  ROOM_INDEX_DATA	*herep, *therep;
  ROOM_INDEX_DATA	*startp;
  EXIT_DATA		*exitp;

#if 0
   if (top_of_world > MAX_ROOMS) {
     log("TRACK Is disabled, too many rooms.\n\rContact Loki soon.\n\r");
    return -1;
   }
#endif

   if (depth<0) {
     thru_doors = TRUE;
     depth = - depth;
   } else {
     thru_doors = FALSE;
   }

  startp = get_room_index(in_room_vnum);

  init_hash_table(&x_room, sizeof(int), 2048);
  hash_enter(&x_room, in_room_vnum, (void*)-1);

	   /* initialize queue */
   q_head = (struct room_q *) malloc(sizeof(struct room_q));
   q_tail = q_head;
   q_tail->room_nr = in_room_vnum;
   q_tail->next_q = 0;

  while(q_head)
  {
    herep = get_room_index(q_head->room_nr);
		/* for each room test all directions */
    if (herep->area == startp->area || !in_zone)
    {
                                           /* only look in this zone.. 
					      saves cpu time.  makes world
					      safer for players
					      */
      for(i = 0; i <= 5; i++)
      {
        exitp = herep->exit[i];
        if (exit_ok(exitp) && (thru_doors ? GO_OK_SMARTER : GO_OK))
	{
	  /* next room */
	  tmp_room = herep->exit[i]->to_room->vnum;
          if (tmp_room != out_room_vnum)
	  {
	    /* shall we add room to queue ? */
	    /* count determines total breadth and depth */
	    if(!hash_find(&x_room,tmp_room) && (count < depth) )
/*
	       && !IS_SET(RM_FLAGS(tmp_room),DEATH))
*/
	    {
	      count++;
	      /* mark room as visted and put on queue */
	      
	      tmp_q = (struct room_q *) malloc(sizeof(struct room_q));
	      tmp_q->room_nr = tmp_room;
	      tmp_q->next_q = 0;
	      q_tail->next_q = tmp_q;
	      q_tail = tmp_q;
	      
	      /* ancestor for first layer is the direction */
	      hash_enter(&x_room, tmp_room,
			 ((int)hash_find(&x_room,q_head->room_nr) == -1) ?
			 (void*)(i+1) : hash_find(&x_room,q_head->room_nr));
	    }
	  }
	  else
	  {
	    /* have reached our goal so free queue */
	    tmp_room = q_head->room_nr;
	    for(;q_head;q_head = tmp_q)
	    {
	      tmp_q = q_head->next_q;
	      free(q_head);
	    }
	    /* return direction if first layer */
	    if ((int)hash_find(&x_room,tmp_room)==-1)
	    {
              if (x_room.buckets) { /* junk left over from a previous track */
		destroy_hash_table(&x_room, donothing);
            }
	    return(i);
	   }
	   else
	   {  /* else return the ancestor */
	      int i;
	      
              i = (int)hash_find(&x_room,tmp_room);
              if (x_room.buckets) { /* junk left over from a previous track */
		destroy_hash_table(&x_room, donothing);
           }
	      return( -1+i);
	}
      }
    }
  }
}
  
      /* free queue head and point to next entry */
      tmp_q = q_head->next_q;
      free(q_head);
      q_head = tmp_q;
   }
   /* couldn't find path */
   if (x_room.buckets) { /* junk left over from a previous track */
      destroy_hash_table(&x_room, donothing);
   } 
   return(-1);

}



void do_whichway( CHAR_DATA *ch, char *argument )
{
	char buf[MAX_STRING_LENGTH];
	char arg[MAX_STRING_LENGTH];
	CHAR_DATA *victim;
	int direction;

	one_argument( argument, arg );

	if (arg[0] == '\0')
	{
		send_to_char("Which way to WHAT?\n\r", ch );
		return;
	}

	if ( (victim = get_char_world( ch, arg ) ) == NULL )
	{
		send_to_char("No such victim!\n\r", ch );
		return;
	}

	direction = find_path( ch->in_room->vnum, victim->in_room->vnum,
			ch, -40000, FALSE );

	switch (direction)
	{
		case DIR_NORTH:
			send_to_char("Your quarry is to the north.\n\r", ch );
			break;
		case DIR_SOUTH:
			send_to_char("Your quarry is to the south.\n\r", ch );
			break;
		case DIR_EAST:
			send_to_char("Your quarry is to the east.\n\r", ch );
			break;
		case DIR_WEST:
			send_to_char("Your quarry is to the west.\n\r", ch );
			break;
		case DIR_UP:
			send_to_char("Your quarry is up.\n\r", ch );
			break;
		case DIR_DOWN:
			send_to_char("Your quarry is down.\n\r", ch );
			break;
	}

	return;
}


void do_sic_mob( CHAR_DATA *ch, char *argument )
{
	CHAR_DATA *victim;
	CHAR_DATA *mob;
	OBJ_DATA *obj;
	char arg[MAX_STRING_LENGTH];

	one_argument( argument, arg );

	if (arg[0] == '\0')
	{
		send_to_char("Sic em on who?\n\r", ch );
		return;
	}

	if ( ( victim = get_char_world( ch, arg ) ) == NULL )
	{
		send_to_char("They aren't here.\n\r", ch );
		return;
	}

	if ( victim->desc == NULL)
	{
		send_to_char("Not a player.\n\r", ch );
		return;
	}

	mob = create_mobile( get_mob_index( 10 ) );

	mob->hunting = victim;

	obj = create_object( get_obj_index(50), 0 );
	obj_to_char( obj, mob );
	equip_char( mob, obj, WEAR_WIELD );

	obj = create_object( get_obj_index(3620), 0 );
	obj_to_char( obj, mob );
	equip_char( mob, obj, WEAR_SHIELD );

	char_to_room( mob, get_room_index(ROOM_VNUM_TEMPLE) );

	return;
}