/* Automated quest code originall written by Vassago (Who i'm giving
credit to despite the fact he gives no credit to the people who's code he
copies (aka the rom consortium).  
Revamped by Kharas (mud@fading.tcimet.net) */
/* This code is great. However, since there is one "stock"object
 * for all quest recovery objects, it reads that vnum's short 
 *description when it comes to item quests. It does restring the 
 * item correctly, and drops it into the world. but the original 
 * code drops it ANYWHERE even if the room is not accessible. 
 * In my MUD, I made an object called "aquest item"(I changed all
 * quest references to aquest). When you type quest info, you see:
 * "You are on a quest to find the fabled quest item!"
 * Plus, there was no way to tell if a mob in the room was actually
 * your target or not.
 * Yeah... Not cool. I noticed the item bugs when creating a prompt
 * variable for questing. I've included the prompt variables below.
 * If you don't need or want them, simply don't use them. I've made
 * the fixes compatible with the previous quest3.txt to make it work.
 * Therefore, this code makes it so inaccessible mobs and rooms
 * are not used. Changes are noted by a "+" sign at the beginning of the line.
 * DON'T FORGET TO REMOVE THE PLUS SIGNS BEFORE COMPILING!!! Hope this
 * helps, as it greatly helped my quest system.
 * --Koqlb, of Subversive Visions. http://subversive.themudhost.net
 */
/**************** BEGIN PROMPT STUFF (Optional)************************/
/* First, in comm.c, look for "Bust a prompt".
Then do a search for "case 'O'
If you don't have the case 'O' then add it below the "break;"
of the last case variable you have. If you already have the
case '<letter>' then pick one that you haven't used. 
Add the code with plus signs:*/
            case 'z':
                if (IS_IMMORTAL (ch) && ch->in_room != NULL)
                    sprintf (buf2, "%-20s", ch->in_room->area->name);
                else
                    sprintf (buf2, " ");
                i = buf2;
                break;
            case '%':
                sprintf (buf2, "%%");
                i = buf2;
                break;
            case 'o':
                sprintf (buf2, "%s", olc_ed_name (ch));
                i = buf2;
                break;
            case 'O':
                sprintf (buf2, "%s", olc_ed_vnum (ch));
                i = buf2;
                break;
+	/* Current Questpoints */
+	    case 'q':
+		sprintf(buf2, "%-6d", ch->pcdata->quest_curr);
+		i = buf2;
+		break;
+	/* Show Quest Mob or Quest Object -Koqlb */
+	   case 'I':
+               questinfo = get_mob_index(ch->pcdata->questmob);
+		if (ch->pcdata->questmob > 0)
+	      {
+		sprintf(buf2, "%s", questinfo->short_descr);
+	      }
+	     else if (ch->pcdata->questobj > 0)
+             {
+		sprintf(buf2, "%s", ch->pcdata->questshort);
+	     }
+		else
+		{
+		sprintf(buf2, "None");
+		}
+		i = buf2;
+		break;
+	/* Time left for current quest */
+	   case 'T':
+		if (ch->pcdata->countdown > 0)
+               {
+		sprintf(buf2, "%-2d{cm{x", ch->pcdata->countdown);
+               }
+		else
+		{
+		sprintf(buf2, "N/A ");
+		}
+		i = buf2;
+		break;

/************* That's it. Done with prompt variables **************/

/* In merc.h you need to add the following to pc_data:*/
    sh_int         quest_curr; /*Current QPoints */
    int            quest_accum;/* Total QPoints */
    CHAR_DATA *    questgiver; /* Questing */
    int            questpoints;/* Reward */
    int            nextquest;/* Time til next quest */
    int            countdown;/* Time for current quest*/
    int            questobj;/* Quest Object */
    int            questmob;/* Quest Mob */
+    char *	   questshort; /* Short Desc of restrung quest obj */
/* NOTE: Questshort doesn't actually SAVE with the character since
 * temporary thing. Once the quest is over, questshort is null. -Koqlb
 */
/*Also in merc.h search for "NOUNCURSE" and the code with plus signs*/
#define ITEM_NOUNCURSE     (Z)
#define ITEM_QUESTITEM     (aa) /*Quest Item for flag */

/*In act_info.c look for void show_char_to_char_0.
Add the code with plus signs:*/
    buf[0] ='\0';

+ /* Show Quest Mob targets in the room -Koqlb*/
+ if (IS_NPC(victim) &&ch->pcdata->questmob > 0 
+    && victim->pIndexData->vnum == ch->pcdata->questmob)
+        strcat( buf, "{g[{GTARGET{g]{x ");

/*---- Then, search for format_obj_to_char -------*/
Find ITEM_HUM, then add the code with plus signs below the code:
    if (IS_OBJ_STAT (obj, ITEM_HUM))
        strcat (buf, "(Humming) ");
    if (IS_OBJ_STAT (obj, ITEM_QUESTITEM))
	strcat (buf, "(AQST)");
=============================================Left off here===========================
In the player flags add:
#define PLR_QUESTING (??) /* Use a free BIT*/



/*Add a new spec_fun in special.c:*/
At the top add: DECLARE_SPEC_FUN(       spec_questmaster                );

In: const   struct  spec_type    spec_table[] =
Add:    {   "spec_questmaster",             spec_questmaster        },

Add the following anywhere in special.c:
bool spec_questmaster( CHAR_DATA *ch )
{
    return TRUE;
}
In fight.c, in the function group_gain, after all the stuff about
getting zapped by equipment, add the following:
   if (!IS_NPC(gch) && IS_SET(gch->act,PLR_QUESTING )
        && IS_NPC(victim))
        {
            if (gch->pcdata->questmob == victim->pIndexData->vnum)
            {
               send_to_char("You have almost completed your quest!\n\r",gch);
        send_to_char(
        "Return to the questmaster before your time runs of time.\n\r",gch);
                ch->pcdata->questmob = -1;
            }
        }
....
In save.c you need add the following in fwrite_char:
    fprintf( fp, "Quest_Curr    %d\n",   ch->pcdata->quest_curr  );
    fprintf( fp, "Quest_Accum  %d\n",   ch->pcdata->quest_accum );
    if (ch->pcdata->nextquest != 0)
        fprintf( fp, "QuestNext   %d\n",  ch->pcdata->nextquest   );
    else if (ch->pcdata->countdown != 0)
        fprintf( fp, "QuestNext   %d\n",  10              );
in fread_char, under case 'Q': you need to add:
     KEY( "Quest_Curr",   ch->pcdata->quest_curr, fread_number( fp ) );
     KEY( "Quest_Accum",  ch->pcdata->quest_accum, fread_number( fp ) );
     KEY( "QuestNext",   ch->pcdata->nextquest,    fread_number( fp ));
You will also need to add quest_update(); in update.c right before/after
area_update();.

This was originally modified for my smaug mud, but I think i've changed
everything so it will work with rom.  Go ahead and write me if ya have
problems (mud@fading.tcimet.net)
/*++++++++++++++++ END INSTALLATION PREP +++++++++++++*/

/* Begin the quest.c file */

#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include "mud.h"

struct reward_type 
{
  char *name;
  char *keyword;
  int cost;
  bool object;
  int value;
  void *      where;
};

/* Descriptions of quest items go here:
Format is: "keywords", "Short description", "Long description" */
const struct quest_desc_type quest_desc[] =
{
{"quest sceptre", 	"The Sceptre of Courage is lying here, waiting to be returned to its owner."
"the Sceptre of Courage", },

{"quest crown", 	"the Crown of Wisdom", 
"The Crown of Wisdom is lying here, waiting to be returned to its owner."},

{"quest gauntlet", 	"the Gauntlets of Strength", 
"The Gauntlets of Strength are lying here, waiting to be returned to its owner."},

{NULL, NULL, NULL}
};

/* Local functions */
void generate_quest	args(( CHAR_DATA *ch, CHAR_DATA *questman ));
void quest_update	args(( void ));
bool quest_level_diff   args(( int clevel, int mlevel));

/* The main quest function */
void do_qwest(CHAR_DATA *ch, char *argument)
{
    CHAR_DATA *questman;
    OBJ_DATA *obj=NULL, *obj_next;
    OBJ_INDEX_DATA *questinfoobj;
    MOB_INDEX_DATA *questinfo;
    char buf [MAX_STRING_LENGTH];
    char arg1 [MAX_INPUT_LENGTH];
    char arg2 [MAX_INPUT_LENGTH];
    int i;

/* Add your rewards here.  Works as follows:
"Obj name shown when qwest list is typed", "keywords for buying",
"Amount of quest points",  Does it load an object?,  IF it loads an
object, then the vnum, otherwise a value to set in the next thing,  This
is last field is a part of the char_data to be modified */ 

const struct reward_type reward_table[]= 
{
/*
  { "A Flask of Endless Water","flask water",   500, TRUE,  46,    0},
  { "Jug O' Moonshine",        "jug moonshine", 300, TRUE,  47,    0},
  { "Potion of Extra Healing", "extra healing", 300, TRUE,  4639,  0},
  { "Potion of Sanctuary",     "sanctuary",     150, TRUE,  3081,  0},
*/
  { "350,000 Gold Pieces",     "350000 gold",	500, FALSE, 350000,&ch->gold},
  { "4 Practices",    	       "practices", 	500, FALSE, 4,     &ch->practice},
  { NULL, NULL, 0, FALSE, 0, 0  } /* Never remove this!!! */
};


    argument = one_argument(argument, arg1);
    argument = one_argument(argument, arg2);

    if(IS_NPC(ch))
	{ send_to_char("NPC's can't quest.\n\r",ch); return; }

    if (arg1[0] == '\0')
    {
        send_to_char("Qwest commands: Info, Time, Request, Complete, Quit, List, and Buy.\n\r",ch);
        send_to_char("For more information, type 'Help Qwest'.\n\r",ch);
	return;
    }

    if (!strcmp(arg1, "info"))
    {
	if (IS_SET(ch->act,PLR_QUESTING))
	{
	    if (ch->pcdata->questmob == -1 && ch->pcdata->questgiver->short_descr != NULL)
		{	        
sprintf(buf,"Your quest is ALMOST complete!\n\rGet back to %s before your"
	   "time runs out!\n\r",ch->pcdata->questgiver->short_descr);
		send_to_char(buf,ch);
		}
	    else if (ch->pcdata->questobj > 0)
	    {
                questinfoobj = get_obj_index(ch->pcdata->questobj);
		if (questinfoobj != NULL)
		{
		    sprintf(buf,"You are on a quest to recover the"
				"fabled %s!\n\r",questinfoobj->name);		
		   send_to_char(buf,ch);
		}
		else send_to_char("You aren't currently on a quest.\n\r",ch);
		return;
	    }
	    else if (ch->pcdata->questmob > 0)
	    {
                questinfo = get_mob_index(ch->pcdata->questmob);
		if (questinfo != NULL)
		{
		    sprintf(buf,"You are on a quest to slay the dreaded"
			       "%s!\n\r",questinfo->short_descr);
		    send_to_char(buf,ch);
		}
		else send_to_char("You aren't currently on a quest.\n\r",ch);
		return;
	    }
	}
	else
	    send_to_char("You aren't currently on a quest.\n\r",ch);
	return;
    }
    else if (!strcmp(arg1, "time"))
    {
	if (!IS_SET(ch->act,PLR_QUESTING))
	{
	    send_to_char("You aren't currently on a quest.\n\r",ch);
	    if (ch->pcdata->nextquest > 1)
		{
	        sprintf(buf,"There are %d minutes remaining until you can"
			"go on another quest.\n\r",ch->pcdata->nextquest);
	        send_to_char(buf,ch);
		}
	    else if (ch->pcdata->nextquest == 1)
		{
		sprintf(buf, "There is less than a minute remaining until"
			"you can go on another quest.\n\r");
		send_to_char(ch,buf);
		}
	}
        else if (ch->pcdata->countdown > 0)
        {
	    sprintf(buf, "Time left for current quest: %d\n\r",ch->pcdata->countdown);
	    send_to_char(buf, ch);
	}
	return;
    }

    for ( questman = ch->in_room->first_person; questman != NULL; questman = questman->next_in_room )
    {
	if (!IS_NPC(questman)) continue;
        if (questman->spec_fun == spec_lookup( "spec_quest_master" )) break;
    }

    if (questman == NULL || questman->spec_fun != spec_lookup("spec_quest_master" ))
    {
        send_to_char("You can't do that here.\n\r",ch);
        return;
    }

    if ( who_fighting(questman) != NULL)
    {
	send_to_char("Wait until the fighting stops.\n\r",ch);
        return;
    }

    ch->pcdata->questgiver = questman;

    if (!strcmp(arg1, "list"))
    {
        act(AT_GREY, "$n asks $N for a list of quest items.", ch, NULL, questman, TO_ROOM); 
	act (AT_GREY,"You ask $N for a list of quest items.",ch, NULL, questman, TO_CHAR);
	send_to_char("Current Quest Items available for Purchase:\n\r", ch);
	if(reward_table[0].name == NULL)
	  send_to_char("  Nothing.\n\r",ch);
	else {
	send_to_char("  [#WCost#w]     [#BName#w]\n\r",ch);
	for(i=0;reward_table[i].name != NULL;i++)
	  {	  
	 sprintf(buf,"   #W%-4d#w       #b%s#w\n\r"
			,reward_table[i].cost,reward_table[i].name);
 	send_to_char(buf,ch);
 	     }
	send_to_char("\n\rTo buy an item, type 'Qwest buy <item>'.\n\r",ch);
	return;
    }

    else if (!strcmp(arg1, "buy"))
    {
	bool found=FALSE;
	if (arg2[0] == '\0')
	{
	    send_to_char("To buy an item, type 'Qwest buy <item>'.\n\r",ch);
	    return;
	}
	/* Use keywords rather than the name listed in qwest list */
	/* Do this to avoid problems with something like 'qwest buy the' */
	/* And people getting things they don't want... */
      for(i=0;reward_table[i].name != NULL;i++)
	if (is_name(arg2, reward_table[i].keyword))
	{ found = TRUE;
	    if (ch->pcdata->quest_curr >= reward_table[i].cost)
	    {
		ch->pcdata->quest_curr -= reward_table[i].cost;
		if(reward_table[i].object)
	            obj = create_object(get_obj_index(reward_table[i].value),ch->level);
		else
		   {
		   sprintf(buf,"In exchange for %d glory, %s gives you %s.\n\r",
			reward_table[i].cost, questman->short_descr, reward_table[i].name );
		   send_to_char(buf,ch);
		   *(int *)reward_table[i].where += reward_table[i].value;
		   }
		break;
	    }
	    else
	    {
		sprintf(buf, "Sorry, %s, but you don't have enough glory for that.",ch->name);
		do_say(questman,buf);
		return;
	    }
	}
	if(!found)
	{
	    sprintf(buf, "I don't have that item, %s.",ch->name);
	    do_say(questman, buf);
	}
	if (obj != NULL)
	{
	    sprintf(buf,"In exchange for %d glory, %s gives you %s.\n\r",
		    reward_table[i].cost, questman->short_descr, obj->short_descr);
	    send_to_char(buf,ch);
	    obj_to_char(obj, ch);
	}
	return;
    }
    else if (!strcmp(arg1, "request"))
    {
        act( AT_GREY,"$n asks $N for a quest.", ch, NULL, questman, TO_ROOM); 
	act (AT_GREY,"You ask $N for a quest.",ch, NULL, questman, TO_CHAR);
	if (IS_SET(ch->act,PLR_QUESTING))
	{
	    sprintf(buf, "But you're already on a quest!");
	    do_say(questman, buf);
	    return;
	}
	if (ch->pcdata->nextquest > 0)
	{
	    sprintf(buf, "You're very brave, %s, but let someone else have a chance.",ch->name);
	    do_say(questman, buf);
	    sprintf(buf, "Come back later.");
	    do_say(questman, buf);
	    return;
	}

	sprintf(buf, "Thank you, brave %s!",ch->name);
	if (!IS_SET(ch->act,PLR_QUESTING))
	do_say(questman, buf);
        ch->pcdata->questmob = 0;
	ch->pcdata->questobj = 0;
	generate_quest(ch, questman);

        if (ch->pcdata->questmob > 0 || ch->pcdata->questobj > 0)
	{
            ch->pcdata->countdown = number_range(10,30);
	    SET_BIT(ch->act,PLR_QUESTING);
	    sprintf(buf, "You have %d minutes to complete this quest.",ch->pcdata->countdown);
	    do_say(questman, buf);
	    sprintf(buf, "May the gods go with you!");
	    do_say(questman, buf);
	}
	return;
    }

    else if (!strcmp(arg1, "complete"))
    {
        act(AT_GREY, "$n informs $N $e has completed $s quest.", ch, NULL, questman, TO_ROOM); 
	act(AT_GREY,"You inform $N you have completed $s quest.",ch, NULL, questman, TO_CHAR);
	if (ch->pcdata->questgiver != questman)
	{
	    sprintf(buf, "I never sent you on a quest! Perhaps you're thinking of someone else.");
	    do_say(questman,buf);
	    return;
	}

	if (IS_SET(ch->act,PLR_QUESTING))
	{
	bool obj_found = FALSE;
	    if (ch->pcdata->questobj > 0 && ch->pcdata->countdown > 0)
	    {
    		for (obj = ch->first_carrying; obj != NULL; obj= obj_next)
    		{
        	    obj_next = obj->next_content;
        
		    if (obj != NULL && obj->pIndexData->vnum == ch->pcdata->questobj)
		    {
			obj_found = TRUE;
            	        break;
		    }
        	}
	    }

     if ((ch->pcdata->questmob == -1 || (ch->pcdata->questobj && obj_found)) 
	&& ch->pcdata->countdown > 0)
	{
	int reward, pointreward;
	    	reward = number_range(2500,25000);
	    	pointreward = number_range(20,50);

		sprintf(buf, "Congratulations on completing your quest!");
		do_say(questman,buf);
		sprintf(buf,"As a reward, I am giving you %d glory points, and %d gold.",pointreward,reward);
		do_say(questman,buf);

	        REMOVE_BIT(ch->act,PLR_QUESTING);
	        ch->pcdata->questgiver = NULL;
	        ch->pcdata->countdown = 0;
	        ch->pcdata->questmob = 0;
		ch->pcdata->questobj = 0;
	        ch->pcdata->nextquest = 10;
		ch->gold += reward;
		ch->pcdata->quest_curr += pointreward;
		ch->pcdata->quest_accum += pointreward;
		if(obj_found) extract_obj(obj);
		check_top10(ch);
	 return;
	}
     else if((ch->pcdata->questmob > 0 || ch->pcdata->questobj > 0)
          && ch->pcdata->countdown > 0)
	    {
		sprintf(buf, "You haven't completed the quest yet, but there is still time!");
		do_say(questman, buf);
		return;
	    }
     }
	if (ch->pcdata->nextquest > 0)
          sprintf(buf,"But you didn't complete your quest in time!");
	else 
          sprintf(buf, "You have to request a quest first, %s.",ch->name);
	do_say(questman, buf);
	return;
    }

    else if (!strcmp(arg1, "quit"))
    {
        act(AT_GREY, "$n informs $N $e wishes to quit $s quest.", ch, NULL,questman, TO_ROOM); 
	act (AT_GREY,"You inform $N you wish to quit $s quest.",ch, NULL, questman, TO_CHAR);
	if (ch->pcdata->questgiver != questman)
	{
	    sprintf(buf, "I never sent you on a quest! Perhaps you're thinking of someone else.");
	    do_say(questman,buf);
	    return;
	}

	if (IS_SET(ch->act,PLR_QUESTING))
	{
            REMOVE_BIT(ch->act,PLR_QUESTING);
            ch->pcdata->questgiver = NULL;
            ch->pcdata->countdown = 0;
            ch->pcdata->questmob = 0;
	    ch->pcdata->questobj = 0;
            ch->pcdata->nextquest = 30;
	    sprintf(buf, "Your quest is over, but for your cowardly behavior, you may not quest again for 30 minutes.");
	    do_say(questman,buf);
		    return;
        }
	else
	{
	send_to_char("You aren't on a quest!",ch);
	return;
	} 
    }


    send_to_char("Qwest commands: Info, Time, Request, Complete, Quit, List, and Buy.\n\r",ch);
    send_to_char("For more information, type 'Help Qwest'.\n\r",ch);
    return;
}

void generate_quest(CHAR_DATA *ch, CHAR_DATA *questman)
{
    CHAR_DATA *victim;
    MOB_INDEX_DATA *vsearch;
    ROOM_INDEX_DATA *room;
    OBJ_DATA *questitem;
    char buf [MAX_STRING_LENGTH];
    long mcounter;
    int mob_vnum;

    for (mcounter = 0; mcounter < 99999; mcounter ++)
    {
	mob_vnum = number_range(50, 32600);

	if ( (vsearch = get_mob_index(mob_vnum) ) != NULL )
	{
            if (aquest_level_diff(ch->level, vsearch->level) == TRUE
                && vsearch->pShop == NULL
    		&& !IS_SET(vsearch->act, ACT_TRAIN)
    		&& !IS_SET(vsearch->act, ACT_PRACTICE)
    		&& !IS_SET(vsearch->act, ACT_GAIN)
    		&& !IS_SET(vsearch->act, ACT_IS_HEALER)
    		&& !IS_SET(vsearch->act, ACT_IS_CHANGER)
		&& !IS_SET(vsearch->act, ACT_PET)
		&& !IS_AFFECTED(vsearch, AFF_CHARM)
		&& !IS_AFFECTED(vsearch, AFF_INVISIBLE)
		&& !IS_AFFECTED(vsearch, AFF_HIDE)
		&& !IS_AFFECTED(vsearch, AFF_SNEAK)
                && !IS_SET(vsearch->imm_flags, IMM_WEAPON | IMM_MAGIC)
		&& number_percent() < 40) break;
		else vsearch = NULL;
	}
    }

    if ( vsearch == NULL || ( victim = get_char_world( ch, vsearch->player_name ) ) == NULL )
    {
	sprintf(buf, "I'm sorry, but I don't have any quests for you at this time.");
	do_say(questman, buf);
	sprintf(buf, "Try again later.");
	do_say(questman, buf);
	ch->pcdata->nextquest = 2;
        return;
    }

    if ( ( room = find_location( ch, victim->name ) ) == NULL )
    {
	sprintf(buf, "I'm sorry, but I don't have any quests for you at this time.");
	do_say(questman, buf);
	sprintf(buf, "Try again later.");
	do_say(questman, buf);
	ch->pcdata->nextquest = 2;
        return;
    }

    /*  40% chance it will send the player on a 'recover item' quest. */

    if (number_percent() < 40) 
    {
	int numobjs=0;
	int descnum = 0;

	for(numobjs=0;quest_desc[numobjs].name != NULL;numobjs++)
	    ;
	numobjs--;
	descnum = number_range(0,numobjs);
        questitem = create_object( get_obj_index(QUEST_OBJ), ch->level );
if(descnum > -1)
{
	if(questitem->short_descr)
	   free_string(questitem->short_descr);
	if(questitem->description)
	   free_string(questitem->description);
	if(questitem->name)
	   free_string(questitem->name);

	questitem->name        = str_dup(quest_desc[descnum].name);
	questitem->description = str_dup(quest_desc[descnum].long_descr);
	questitem->short_descr = str_dup(quest_desc[descnum].short_descr);
}
	/* not to inaccessible rooms */
       if ( 
           !IS_SET(room->room_flags, ROOM_GODS_ONLY)
	   || !IS_SET(room->room_flags, ROOM_IMP_ONLY)
	   || !IS_SET(room->room_flags, ROOM_NEWBIES_ONLY)
	   || !IS_SET(room->room_flags, ROOM_SOLITARY)
	   || !IS_SET(room->room_flags, ROOM_PRIVATE))
	obj_to_room(questitem, room);
	ch->pcdata->questobj = questitem->pIndexData->vnum;

	sprintf(buf, "Vile pilferers have stolen %s from the royal treasury!",questitem->short_descr);
	do_say(questman, buf);
	do_say(questman, "My court wizardess, with her magic mirror, has pinpointed its location.");

	sprintf(buf, "Look in the general area of %s for %s!",room->area->name, room->name);
	do_say(questman, buf);
	return;
    }

    /* Quest to kill a mob */

    else 
    {
    switch(number_range(0,1))
    {
	case 0:
        sprintf(buf, "An enemy of mine, %s, is making vile threats against the crown.",victim->short_descr);
        do_say(questman, buf);
        sprintf(buf, "This threat must be eliminated!");
        do_say(questman, buf);
	break;

	case 1:
	sprintf(buf, "Rune's most heinous criminal, %s, has escaped from the dungeon!",victim->short_descr);
	do_say(questman, buf);
	sprintf(buf, "Since the escape, %s has murdered %d civillians!",victim->short_descr, number_range(2,20));
	do_say(questman, buf);
	do_say(questman,"The penalty for this crime is death, and you are to deliver the sentence!");
	break;
    }

    if (room->name != NULL)
    {
        sprintf(buf, "Seek %s out somewhere in the vicinity of %s!",victim->short_descr,room->name);
        do_say(questman, buf);

	sprintf(buf, "That location is in the general area of %s.",room->area->name);
	do_say(questman, buf);
    }
    ch->pcdata->questmob = victim->pIndexData->vnum;
    }

    return;
}

bool quest_level_diff(int clevel, int mlevel)
{
    if (clevel < 9 && mlevel < clevel + 2) return TRUE;
    else if (clevel <= 9 && mlevel < clevel + 3 
	  && mlevel > clevel - 5) return TRUE;
    else if (clevel <= 14 && mlevel < clevel + 4 
	  && mlevel > clevel - 5) return TRUE;
    else if (clevel <= 21 && mlevel < clevel + 5 
	  && mlevel > clevel - 4) return TRUE;
    else if (clevel <= 29 && mlevel < clevel + 6 
	  && mlevel > clevel - 3) return TRUE;
    else if (clevel <= 37 && mlevel < clevel + 7 
	  && mlevel > clevel - 2) return TRUE;
    else if (clevel <= 55 && mlevel < clevel + 8 
	  && mlevel > clevel - 1) return TRUE;
    else if(clevel > 55) return TRUE; /* Imms can get anything :) */
    else return FALSE;
}
		
/* Called from update_handler() by pulse_area */

void quest_update(void)
{
    DESCRIPTOR_DATA *d;
    CHAR_DATA *ch;
 
    for ( d = first_descriptor; d != NULL; d = d->next )
    {
        if (d->character != NULL && d->connected == CON_PLAYING)
        {
        ch = d->character;
	if(IS_NPC(ch))
	continue; 
        if (ch->pcdata->nextquest > 0)
        {
            ch->pcdata->nextquest--;
            if (ch->pcdata->nextquest == 0)
            {
                send_to_char("You may now quest again.\n\r",ch);
                return;
            }
        }
        else if (IS_SET(ch->act,PLR_QUESTING))
        {
            if (--ch->pcdata->countdown <= 0)
            {
                ch->pcdata->nextquest = 10;
                sprintf(buf,"You have run out of time for your"
"quest!\n\rYou may quest again in %d minutes.\n\r",ch->pcdata->nextquest);
		send_to_char(buf,ch);
                REMOVE_BIT(ch->act,PLR_QUESTING);
                ch->pcdata->questgiver = NULL;
                ch->pcdata->countdown = 0;
                ch->pcdata->questmob = 0;
                ch->pcdata->questobj = 0;
            }
            if (ch->pcdata->countdown > 0 && ch->pcdata->countdown < 6)
            {
                send_to_char("Better hurry, you're almost out of time for your quest!\n\r",ch);
                return;
            }
        }
        }
    }
    return;
}