ackfuss-4.4.0/board/
ackfuss-4.4.0/help/e/
ackfuss-4.4.0/help/f/
ackfuss-4.4.0/help/h/
ackfuss-4.4.0/help/l/
ackfuss-4.4.0/help/n/
ackfuss-4.4.0/help/q/
ackfuss-4.4.0/help/s/
ackfuss-4.4.0/help/u/
ackfuss-4.4.0/help/v/
ackfuss-4.4.0/help/y/
ackfuss-4.4.0/help/z/
ackfuss-4.4.0/player/c/
/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  Ack 2.2 improvements copyright (C) 1994 by Stephen Dooley              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *       _/          _/_/_/     _/    _/     _/    ACK! MUD is modified    *
 *      _/_/        _/          _/  _/       _/    Merc2.0/2.1/2.2 code    *
 *     _/  _/      _/           _/_/         _/    (c)Stephen Zepp 1998    *
 *    _/_/_/_/      _/          _/  _/             Version #: 4.3          *
 *   _/      _/      _/_/_/     _/    _/     _/                            *
 *                                                                         *
 *                        http://ackmud.nuc.net/                           *
 *                        zenithar@ackmud.nuc.net                          *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/
/***************************************************************************
 * _/_/_/_/  _/    _/  _/_/_/_/ _/_/_/_/ AckFUSS is modified ACK!MUD 4.3.1 *
 * _/        _/    _/  _/       _/       copyright Matt Goff (Kline) 2008  *
 * _/_/      _/    _/  _/_/_/_/ _/_/_/_/                                   *
 * _/        _/    _/        _/       _/ Support for this code is provided *
 * _/        _/_/_/_/  _/_/_/_/ _/_/_/_/ at www.ackmud.net -- check it out!*
 ***************************************************************************/

/* Mob/player hunting.. */
/* Copied this from one of my old MUDs..  Much cleaner than the sillymud
   hunt routines  -- Alty */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "globals.h"

#ifndef DEC_ACT_COMM_H
#include "h/act_comm.h"
#endif

#ifndef DEC_ACT_MOVE_H
#include "h/act_move.h"
#endif

#ifndef DEC_ACT_WIZ_H
#include "h/act_wiz.h"
#endif

#ifndef DEC_COMM_H
#include "h/comm.h"
#endif

#ifndef DEC_DB_H
#include "h/db.h"
#endif

#ifndef DEC_FIGHT_H
#include "h/fight.h"
#endif

#ifndef DEC_HANDLER_H
#include "h/handler.h"
#endif

#ifndef DEC_SSM_H
#include "h/ssm.h"
#endif
 
H_QUEUE *h_head = NULL;
H_QUEUE *h_tail = NULL;

#ifdef DEBUG_HUNT_CODE
static FILE *h_fp;
#endif

void h_dequeue( void )
{
H_QUEUE *hunt;
 
if( !( hunt = h_head ) )
return;
h_head = hunt->next;
if( h_tail == hunt )
h_tail = NULL;
hunt->room->room_flags.reset(RFLAG_HUNT_MARK);
#ifdef DEBUG_HUNT_CODE
fprintf( h_fp, "Dequeue: %5d\n", hunt->room->vnum );
fflush( h_fp );
#endif
dispose( hunt, sizeof( *hunt ) );
return;
}
 
void h_clear( void )
{
#ifdef DEBUG_HUNT_CODE
fprintf( h_fp, "h_clear\n" );
fflush( h_fp );
#endif
while( h_head != NULL )
h_dequeue( );
#ifdef DEBUG_HUNT_CODE
fprintf( h_fp, "Cleared\n" );
fflush( h_fp );
#endif
}

void h_enqueue( ROOM_INDEX_DATA * room, short dir )
{
   H_QUEUE *hunt;

   hunt = (H_QUEUE *)getmem( sizeof( *hunt ) );
   hunt->next = NULL;
   hunt->room = room;
   hunt->dir = dir;
   room->room_flags.set(RFLAG_HUNT_MARK);
   if( !h_head )
    h_head = hunt;
   else
    h_tail->next = hunt;
   h_tail = hunt;
#ifdef DEBUG_HUNT_CODE
   fprintf( h_fp, "Enqueue: %5d - %s\n", room->vnum, room->room_flags.test(RFLAG_HUNT_MARK) ? "set" : "unset" );
   fflush( h_fp );
#endif
   return;
}

bool h_is_valid_exit( ROOM_INDEX_DATA * room, short dir, int h_flags )
{
   EXIT_DATA *exit = room->exit[dir];

   if( !exit )
      return FALSE;
   if( !exit->to_room )
      return FALSE;
#ifdef DEBUG_HUNT_CODE
   fprintf( h_fp, "IsValid: %5d - %s\n", exit->to_room->vnum,
            ( exit->to_room->room_flags.test(RFLAG_HUNT_MARK) ? "set" : "unset" ) );
   fflush( h_fp );
#endif
   if( exit->to_room->room_flags.test(RFLAG_HUNT_MARK) )
      return FALSE;
   if( !IS_SET( h_flags, HUNT_WORLD ) && room->area != exit->to_room->area )
      return FALSE;
   if( exit->exit_info.test(EX_CLOSED) )
   {
      if( !IS_SET( h_flags, HUNT_OPENDOOR ) )
         return FALSE;
      if( exit->exit_info.test(EX_LOCKED) )
      {
         if( !IS_SET( h_flags, HUNT_UNLOCKDOOR | HUNT_PICKDOOR ) )
            return FALSE;
         if( !IS_SET( h_flags, HUNT_UNLOCKDOOR ) && exit->exit_info.test(EX_PICKPROOF) )
            return FALSE;
      }
   }
   return TRUE;
}

void h_enqueue_room( ROOM_INDEX_DATA * room, short dir, int h_flags )
{
   short edir;

#ifdef DEBUG_HUNT_CODE
   fprintf( h_fp, "h_enqueue_room\n" );
   fflush( h_fp );
#endif
   for( edir = 0; edir < MAX_DIR; edir++ )
      if( h_is_valid_exit( room, edir, h_flags ) )
         h_enqueue( room->exit[edir]->to_room, ( dir == -1 ? edir : dir ) );
   return;
}

short h_find_dir( ROOM_INDEX_DATA * room, ROOM_INDEX_DATA * target, int h_flags )
{
   H_QUEUE *hunt;

   if( room == target )
      return -1;
#ifdef DEBUG_HUNT_CODE
   if( !h_fp )
      h_fp = file_open( "hunt.out", "w" );
   fprintf( h_fp, "h_find_dir\n" );
   fflush( h_fp );
#endif
   room->room_flags.set(RFLAG_HUNT_MARK);
   h_enqueue_room( room, -1, h_flags );
   for( hunt = h_head; hunt; hunt = hunt->next )
   {
      if( hunt->room == target )
      {
         short dir = hunt->dir;

#ifdef DEBUG_HUNT_CODE
         fprintf( h_fp, "Found dir %d\n", dir );
         fflush( h_fp );
#endif
         h_clear();
         room->room_flags.reset(RFLAG_HUNT_MARK);
         return dir;
      }
      h_enqueue_room( hunt->room, hunt->dir, h_flags );
   }
#ifdef DEBUG_HUNT_CODE
   fprintf( h_fp, "Invalid dir\n" );
   fflush( h_fp );
#endif
   h_clear();
   room->room_flags.reset(RFLAG_HUNT_MARK);
   return -1;
}

bool set_hunt( CHAR_DATA * ch, CHAR_DATA * fch, CHAR_DATA * vch, OBJ_DATA * vobj, int set_flags, int rem_flags )
{
   int nflags;
   ROOM_INDEX_DATA *troom;
   char buf[MAX_STRING_LENGTH];

   troom = ( vch ? vch->in_room : vobj ? vobj->in_room : NULL );
   nflags = ( ( ch ? ch->hunt_flags : 0 ) | set_flags ) & ~rem_flags;
   if( !ch || !troom || h_find_dir( ch->in_room, troom, nflags ) < 0 )
      return FALSE;
   ch->hunting = vch;
   ch->hunt_obj = vobj;
   ch->hunt_for = fch;
   if( IS_NPC( ch ) )
      ch->hunt_home = ( ch->hunt_home ? ch->hunt_home : ch->in_room );
   else
      ch->hunt_home = NULL;
   if( ch->searching )
   {
      free_string( ch->searching );
      ch->searching = NULL;
   }
   ch->hunt_flags = nflags;
   snprintf( buf, MSL, "%s has started hunting (%s) %s",
            NAME( ch ),
            ( vch ? IS_NPC( vch ) ? "mobile" : "player" : "object" ), ( vch ? NAME( vch ) : vobj->short_descr ) );
   if( fch )
      snprintf( buf + strlen( buf ), (2 * MIL), " for %s", NAME( fch ) );
   monitor_chan( buf, MONITOR_HUNTING );
   return TRUE;
}

void end_hunt( CHAR_DATA * ch )
{
   ch->hunting = NULL;
   ch->hunt_obj = NULL;
   ch->hunt_for = NULL;
   if( !IS_NPC( ch ) )
   {
      ch->hunt_home = NULL;
      ch->hunt_flags = 0;
   }
   else
      ch->hunt_flags = ch->npcdata->pIndexData->hunt_flags;
   if( ch->searching )
   {
      free_string( ch->searching );
      ch->searching = NULL;
   }
}

bool has_key args( ( CHAR_DATA * ch, int key ) );
void hunt_move( CHAR_DATA * mob, short dir )
{
   EXIT_DATA *exit = mob->in_room->exit[dir];

   if( exit->exit_info.test(EX_CLOSED) )
   {
      if( exit->exit_info.test(EX_LOCKED) )
      {
         if( IS_SET( mob->hunt_flags, HUNT_UNLOCKDOOR ) && has_key( mob, exit->key ) )
            do_unlock( mob, dir_name[dir] );
         else if( IS_SET( mob->hunt_flags, HUNT_PICKDOOR ) && !exit->exit_info.test(EX_PICKPROOF) )
            do_pick( mob, dir_name[dir] );
      }
      else if( IS_SET( mob->hunt_flags, HUNT_OPENDOOR ) )
         do_open( mob, dir_name[dir] );
   }
   else
      move_char( mob, dir, FALSE );
   return;
}

bool mob_hunt( CHAR_DATA * mob )
{
   short dir;
   char buf[128];

   if( !mob || !IS_NPC( mob ) )
      return FALSE;
   if( !mob->hunting )
   {
      if( mob->hunt_obj != NULL )
      {
         if( mob->hunt_obj->in_room == NULL )
         {
            if( IS_SET( mob->hunt_flags, HUNT_CR ) && mob->hunt_for && mob->hunt_obj->item_type == ITEM_CORPSE_PC )
               act( "$N tells you 'Someone else seems to have gotten to your "
                    "corpse before me.'", mob->hunt_for, NULL, mob, TO_CHAR );
            end_hunt( mob );
            return TRUE;
         }
         if( can_see_obj( mob, mob->hunt_obj ) && mob->in_room == mob->hunt_obj->in_room )
         {
            if( IS_SET( mob->hunt_flags, HUNT_CR ) && mob->hunt_for && mob->hunt_obj->item_type == ITEM_CORPSE_PC )
               act( "$N tell you 'I have found your corpse.  I shall return it "
                    "to you now.", mob->hunt_for, NULL, mob, TO_CHAR );
            obj_from_room( mob->hunt_obj );
            obj_to_char( mob->hunt_obj, mob );
            act( "$n gets $o.", mob, mob->hunt_obj, NULL, TO_ROOM );
            set_hunt( mob, NULL, mob->hunt_for, mob->hunt_obj, 0, 0 );
            return TRUE;
         }
         if( !can_see_obj( mob, mob->hunt_obj ) ||
             ( dir = h_find_dir( mob->in_room, mob->hunt_obj->in_room, mob->hunt_flags ) ) < 0 )
         {
            if( IS_SET( mob->hunt_flags, HUNT_CR ) && mob->hunt_for && mob->hunt_obj->item_type == ITEM_CORPSE_PC )
               act( "$N tells you 'I seem to have lost the way to your corpse.'", mob->hunt_for, NULL, mob, TO_CHAR );
            end_hunt( mob );
            return TRUE;
         }
         hunt_move( mob, dir );
         if( mob->in_room == mob->hunt_obj->in_room )
            mob_hunt( mob );
      }
      /*
       * deleted because the hunt is started in mobile_update
       * else if ( mob->searching &&
       * (mob->hunting = get_char_world(mob, mob->searching)) != NULL )
       * {
       * free_string(mob->searching);
       * mob->searching = NULL;
       * }
       * --Aeria 
       */
      else if( mob->hunt_home )
      {
         dir = -1;
         if( mob->in_room == mob->hunt_home || ( dir = h_find_dir( mob->in_room, mob->hunt_home, mob->hunt_flags ) ) < 0 )
         {
            mob->hunt_home = NULL;
            mob->hunt_flags = mob->npcdata->pIndexData->hunt_flags;
         }
         else if( dir >= 0 )
            hunt_move( mob, dir );
      }
      else
      {
         return FALSE;
      }
      return TRUE;
   }
   if( !can_see( mob, mob->hunting ) )
   {
      if( IS_SET( mob->hunt_flags, HUNT_MERC ) && mob->hunt_for )
      {
         /*
          * 6.25% chance of giving up, 18.75% chance of telling employer. 
          */
         switch ( number_bits( 4 ) )
         {
            case 0:
               snprintf( buf, MSL, "$N tells you '%s seems to have disappeared!'", NAME( mob->hunting ) );
               act( buf, mob->hunt_for, NULL, mob, TO_CHAR );
               end_hunt( mob );
               return TRUE;
            case 1:
            case 2:
            case 3:
               snprintf( buf, MSL, "$N tells you '%s seems to have disappeared!  I shall "
                        "find %s though!'", NAME( mob->hunting ),
                        ( mob->hunting->sex == SEX_MALE ? "him" : mob->hunting->sex == SEX_FEMALE ? "her" : "it" ) );
               act( buf, mob->hunt_for, NULL, mob, TO_CHAR );
               return TRUE;
         }
      }
      if( IS_SET( mob->hunt_flags, HUNT_INFORM ) )
      {
         switch ( number_bits( 5 ) )
         {
            case 0:
               snprintf( buf, MSL, "Where are you, %s?", NAME( mob->hunting ) );
               break;
            case 1:
               snprintf( buf, MSL, "Why can't I find you, %s?", NAME( mob->hunting ) );
               break;
            case 2:
               snprintf( buf, MSL, "I know you're out there, %s!", NAME( mob->hunting ) );
               break;
            case 3:
               snprintf( buf, MSL, "I'll find you, %s, just wait!", NAME( mob->hunting ) );
               break;
            default:
               return FALSE;
         }
         do_yell( mob, buf );
         return TRUE;
      }
      return FALSE;
   }
   if( mob->in_room == mob->hunting->in_room )
   {
      if( IS_SET( mob->hunt_flags, HUNT_CR ) && mob->hunt_obj && mob->hunt_obj->item_type == ITEM_CORPSE_PC )
      {
         act( "$N tells you 'I have returned with your corpse!'", mob->hunting, NULL, mob, TO_CHAR );
         /*
          * Ok maybe im a little paranoid here.. :).. -- Alty 
          */
         if( mob->hunt_obj->carried_by == mob )
         {
            if( mob->hunt_obj->wear_loc != WEAR_NONE )
               unequip_char( mob, mob->hunt_obj );
            act( "$n drops $o.", mob, mob->hunt_obj, NULL, TO_ROOM );
            obj_from_char( mob->hunt_obj );
            obj_to_room( mob->hunt_obj, mob->in_room );
         }
         end_hunt( mob );
         return TRUE;
      }
      if( IS_SET( mob->hunt_flags, HUNT_MERC ) && mob->hunt_for )
      {
         snprintf( buf, MSL, "$N tells you 'I have found %s!  Now %s shall die!'",
                  NAME( mob->hunting ),
                  ( mob->hunting->sex == SEX_FEMALE ? "she" : mob->hunting->sex == SEX_MALE ? "he" : "it" ) );
         act( buf, mob->hunt_for, NULL, mob, TO_CHAR );
      }
      switch ( number_bits( 2 ) )
      {
         case 0:
            snprintf( buf, MSL, "Now I have you, %s!", NAME( mob->hunting ) );
            break;
         case 1:
            snprintf( buf, MSL, "I knew you'd be here, %s!", NAME( mob->hunting ) );
            break;
         case 2:
            snprintf( buf, MSL, "Did you really think you were safe, %s?", NAME( mob->hunting ) );
            break;
         case 3:
            snprintf( buf, MSL, "So here you are, %s!", NAME( mob->hunting ) );
            break;
      }
      if( IS_SET( mob->hunt_flags, HUNT_INFORM ) )
         do_yell( mob, buf );
      else
         do_say( mob, buf );
      one_hit( mob, mob->hunting, TYPE_UNDEFINED );
      end_hunt( mob );
      return TRUE;
   }

   if( ( dir = h_find_dir( mob->in_room, mob->hunting->in_room, mob->hunt_flags ) ) == -1 )
   {
      if( IS_SET( mob->hunt_flags, HUNT_MERC ) && mob->hunt_for )
      {
         /*
          * 6.25% chance of giving up, 18.75% chance of informing employer 
          */
         switch ( number_bits( 4 ) )
         {
            case 0:
               snprintf( buf, MSL, "$N tells you 'I seem to have lost %s's trail.'", NAME( mob->hunting ) );
               act( buf, mob->hunt_for, NULL, mob, TO_CHAR );
               end_hunt( mob );
               return TRUE;
            case 1:
            case 2:
            case 3:
               snprintf( buf, MSL, "$N tells you 'I seem to have lost %s's trail.  I shall "
                        "find it again, though!'", NAME( mob->hunting ) );
               act( buf, mob->hunt_for, NULL, mob, TO_CHAR );
               return TRUE;
         }
      }
      if( IS_SET( mob->hunt_flags, HUNT_INFORM ) )
      {
         switch ( number_bits( 6 ) )
         {
            case 0:
               snprintf( buf, MSL, "Where are you hiding, %s?", NAME( mob->hunting ) );
               break;
            case 1:
               snprintf( buf, MSL, "You can't run forever, %s!", NAME( mob->hunting ) );
               break;
            case 2:
               snprintf( buf, MSL, "Come out, come out, wherever you are, %s!", NAME( mob->hunting ) );
               break;
            case 3:
               snprintf( buf, MSL, "I promise I won't hurt you, %s.", NAME( mob->hunting ) );
               break;
            default:
               return FALSE;
         }
         do_yell( mob, buf );
         return TRUE;
      }
      return FALSE;
   }
   hunt_move( mob, dir );
   if( mob->in_room == mob->hunting->in_room )
      mob_hunt( mob );
   return TRUE;
}

void char_hunt( CHAR_DATA * ch )
{
   short dir;
   char buf[MAX_STRING_LENGTH];

   if( IS_NPC( ch ) )
      return;
   if( !ch->hunting )
   {
      if( ch->hunt_obj )
      {
         if( !can_see_obj( ch, ch->hunt_obj ) || !ch->hunt_obj->in_room )
         {
            snprintf( buf, MSL, "@@RYou seem to have lost the trail to %s.@@N\r\n", ch->hunt_obj->short_descr );
            send_to_char( buf, ch );
            end_hunt( ch );
         }
         else if( ch->hunt_obj->in_room == ch->in_room )
         {
            snprintf( buf, MSL, "@@RAhhh.  You have found %s!@@N\r\n", ch->hunt_obj->short_descr );
            send_to_char( buf, ch );
            end_hunt( ch );
         }
         else if( ( dir = h_find_dir( ch->in_room, ch->hunt_obj->in_room, ch->hunt_flags ) ) < 0 )
         {
            snprintf( buf, MSL, "@@RYou seem to have lost the trail to %s.@@N\r\n", ch->hunt_obj->short_descr );
            send_to_char( buf, ch );
            end_hunt( ch );
         }
         else
         {
            snprintf( buf, MSL, "@@RYou sense that %s is %s of here.@@N\r\n", ch->hunt_obj->short_descr, dir_name[dir] );
            send_to_char( buf, ch );
         }
      }
      return;
   }
   if( !can_see( ch, ch->hunting ) )
   {
      send_to_char( "@@RYou seem to have lost your prey.@@N\r\n", ch );
      end_hunt( ch );
   }
   else if( ch->in_room == ch->hunting->in_room )
   {
      send_to_char( "@@RAhhh.  You have found your prey!@@N\r\n", ch );
      end_hunt( ch );
   }
   else if( ( dir = h_find_dir( ch->in_room, ch->hunting->in_room, ch->hunt_flags ) ) < 0 )
   {
      send_to_char( "@@RYou seem to have lost your prey.@@N\r\n", ch );
      end_hunt( ch );
   }
   else
   {
      snprintf( buf, MSL, "@@RYou sense your prey is %s of here.@@N\r\n", dir_name[dir] );
      send_to_char( buf, ch );
   }
   return;
}

void do_hunt( CHAR_DATA * ch, char *argument )
{
   CHAR_DATA *victim;
   char arg[MAX_INPUT_LENGTH];
   short chance;

   if( IS_NPC( ch ) && ( ch->hunting || ch->hunt_obj ) )
      return;
   argument = one_argument( argument, arg );
   if( !*arg )
   {
      send_to_char( "Hunt for whom?\r\n", ch );
      return;
   }
   if( !IS_NPC( ch ) && IS_WOLF( ch ) && ( IS_SHIFTED( ch ) || IS_RAGED( ch ) ) )
      victim = get_char_world( ch, arg );
   else
      victim = ( get_trust( ch ) >= MAX_LEVEL ? get_char_world( ch, arg ) : get_char_area( ch, arg ) );
   if( victim == ch )
   {
      if( ch->hunting )
      {
         snprintf( arg, MIL, "You stop hunting %s.\r\n", NAME( ch->hunting ) );
         send_to_char( arg, ch );
      }
      else if( ch->hunt_obj )
      {
         snprintf( arg, MIL, "You stop looking for %s.\r\n", ch->hunt_obj->short_descr );
         send_to_char( arg, ch );
      }
      else
      {
         send_to_char( "You find yourself right where you're standing!\r\n", ch );
      }
      end_hunt( ch );
      return;
   }
   else if( !IS_IMMORTAL( ch ) && ( victim != NULL ) && !IS_NPC( victim ) && IS_IMMORTAL( victim ) )
   {
      snprintf( arg, MIL, "You can't hunt Immortal %s!\r\n", NAME( victim ) );
      send_to_char( arg, ch );
      return;
   }

   /*
    * 100% chance of finding them if you're looking right at them.. :) 
    */
   if( victim != NULL && victim->in_room == ch->in_room )
   {
      send_to_char( "You're already there!\r\n", ch );
      return;
   }
   /*
    * Chance of picking up wrong trail.. (25% for NPC, PC @ normal) 
    */
   chance = ( IS_NPC( ch ) ? 75 : ch->pcdata->learned[gsn_hunt] );
   if( !IS_NPC( ch ) && IS_WOLF( ch ) && ( IS_SHIFTED( ch ) || IS_RAGED( ch ) ) )
      chance = ( ( MAX_WOLF_LEVEL - ch->pcdata->super->generation ) * 4 ) + ch->pcdata->super->level;

   if( chance < number_percent(  ) )
   {
      CHAR_DATA *vch;
      std::list<CHAR_DATA *>::iterator li;
      short vcnt = 0;

      victim = NULL;
      for( li = char_list.begin(); li != char_list.end(); li++ )
      {
         vch = *li;
         if( IS_NPC( vch ) && vch->in_room &&
             vch->in_room->area == ch->in_room->area && vch->in_room != ch->in_room && number_range( 0, vcnt ) == 0 )
            victim = vch;
         vcnt++;
      }
   }
   /*
    * Max_level people can hunt through the world, and anyone who has
    * practiced over 70% can hunt through doors.. -- Alty 
    */
   if( !IS_NPC( ch ) && IS_WOLF( ch ) && ( IS_SHIFTED( ch ) || IS_RAGED( ch ) ) )
      ch->hunt_flags = HUNT_WORLD | HUNT_OPENDOOR | HUNT_UNLOCKDOOR | HUNT_PICKDOOR;
   else if( !IS_NPC( ch ) )
      ch->hunt_flags = ( get_trust( ch ) >= MAX_LEVEL ? HUNT_WORLD : 0 )
         | ( ch->pcdata->learned[gsn_hunt] >= 70 ? HUNT_OPENDOOR | HUNT_UNLOCKDOOR | HUNT_PICKDOOR : 0 );
   if( !victim || !set_hunt( ch, NULL, victim, NULL, 0, HUNT_CR | HUNT_MERC ) )
   {
      send_to_char( "You couldn't find a trail.\r\n", ch );
      return;
   }
   return;
}