pdirt/data/
pdirt/data/HELP/
pdirt/data/HELP/0/
pdirt/data/HELP/F/
pdirt/data/HELP/G/
pdirt/data/HELP/H/
pdirt/data/HELP/J/
pdirt/data/HELP/K/
pdirt/data/HELP/O/
pdirt/data/HELP/Q/
pdirt/data/HELP/R/
pdirt/data/HELP/U/
pdirt/data/HELP/V/
pdirt/data/HELP/Y/
pdirt/data/HELP/Z/
pdirt/data/MESSAGES/
pdirt/data/POWERINFO/
pdirt/data/WIZ_ZONES/
pdirt/drv/
pdirt/drv/bin/
pdirt/drv/compiler/converter/
pdirt/drv/compiler/libs/
pdirt/drv/compiler/scripts/
pdirt/drv/include/AberChat/
pdirt/drv/include/InterMud/
pdirt/drv/include/machine/
pdirt/drv/src/InterMud/
pdirt/drv/src/Players/
pdirt/drv/utils/UAFPort/
pdirt/drv/utils/dnsresolv/
pdirt/drv/utils/gdbm/
/***************************************************************************
 ** Project    : pDirt (Aber IV MUD daemon)
 ** Module     : quest.c
 ** Author     : Various
 ** Date       : 7 April 1996
 ** Description: Some quest related stuff
 ***************************************************************************/
#define QUEST_C

/***************************************************************************
 ** IMPORT
 ***************************************************************************/ 
#include "kernel.h"
#include "sendsys.h"                        /* Message send functions */
#include "questnames.h"                     /* String format of the quests */
#include "questpoints.h"
#include "quests.h"                         /* The quest defines */
#include "quest.h"                          /* Prototypes of the functions */
#include "parse.h"                          /* brkword() etc */
#include "bprintf.h"                        /* Standard print functions */
#include "flags.h"                          /* Flag maninpulation */
#include "uaf.h"                            /* User file manipulation */
#include "log.h"                            /* Syslog functions */
#include "mobile.h"
#include "zones.h"
#include "wizlist.h"

/****************************************************************************
 ** PROTOTYPES
 ****************************************************************************/
void set_quest(int qnum, int plx);          /* Set the quest on player    */
A_COMMAND(questcom);                        /* Show quest stat for player */
A_COMMAND(qdonecom);                        /* Show quests done this reset*/

extern const int zonetab[];

int get_quest_of_zone(int zone)
{  int i;

   if (zone == -1)
      return -1;

   for (i = 0; zonetab[i] != -1; i+=2)
   {   if (zonetab[i] == zone)
         return zonetab[i+1];
   }
   return -1;
}

int get_zone_by_quest(int q)
{  int i=0;
   
   while (zonetab[i+1] != q && zonetab[i] != -1)
     i+=2;

   return zonetab[i];
}

int count_players_in_zone(int zone)
{   int start,end, ct=0, i =0;

    if (get_zone_locs(zone,&start,&end)< 0)
       return 0;
    else
    {   for (i=0;i < max_players; i++)
        {   if (is_in_game(i) && ploc(i) <= start && ploc(i) > end)
               ct++;
        }
    }
    return ct;
}

char * queststat(int q)
{   int zone = get_zone_by_quest(q);

    if (questsdone[q])
        return "&+wDone&*";
    else if (count_players_in_zone(zone) > 0)
        return "&+wProg&*";
    else
        return "&+wFree&*";
}

int qp_for_level(int lvl)
{   int i;

    for (i=0; QP_Per_level[i] != -1; i += 2)
    {   if (QP_Per_level[i] == lvl)
           return QP_Per_level[i+1];
    }
    return 0;
}

/*************************************************************************** 
 ** Sets the questflag, updates questsdone and sends messages to the player,
 ** and wizards.
 ***************************************************************************/
void set_quest(int qnum, int plx)
{   
    /** Do a check to see if the player already did this quest. If so, we
     ** change the message a little
     **/
    if (questsdone[qnum])
       return;

    if (!qtstflg(plx,qnum))
    {  
       qsetflg(plx,qnum);           /* Set the flag of this quest */
       send_msg(DEST_ALL,MODE_QUIET|MODE_BRACKET,LVL_APPREN,LVL_MAX,plx,NOBODY,
                "%s has solved the %s Quest",pname(plx),Quests[qnum]);
       sendf(plx,"&+wCongratulations, You just finished the %s Quest&*\n",Quests[qnum]);
       addqpoints(plx,qnum); 
    } 
    else
    {  
       send_msg(DEST_ALL,MODE_QUIET|MODE_BRACKET,LVL_APPREN,LVL_MAX,plx,NOBODY,
                "%s has solved the %s Quest (again)",pname(plx),
                Quests[qnum]);
       sendf(plx,"&+wCongratulations, You just finished the %s Quest, again&*\n",Quests[qnum]);
    }
    questsdone[qnum] = True;
    saveme();
}

/****************************************************************************
 ** The QUESTS-Command. Mortals may find out which quests they have
 ** comleted and which are left. Arch-Wizards may in addition set or
 ** clear quests for a mortal, Wizards only for themselves.
 ** Usage: QUESTS <player> <questname> <true/false>
 ****************************************************************************/
A_COMMAND(questcom)
{ int a, b, c, l;
  char *n;
  Boolean f, all;
  QFLAGS q, *p;
  PERSONA d;
  int *qp;

  f = False;
  
  if (brkword () == -1)           
  {  a = mynum;                    /* Index to Players[] */
     p = &(qflags (a));            /* Pointer to quests bitmap */
     n = pname (a);                /* Pointer to name of player */
     l = plev (a);                 /* Level of the player */
     qp = &qpoints(a);
  }
  else if ((a = fpbn (wordbuf)) != -1)
  {  
     if (a != mynum && plev (mynum) < LVL_APPREN) /* Level check */
     {  bprintf ("You can only check your own Quest-stats.\n");
        return;
     }
     else if (a >= max_players)
     {  bprintf("Mobiles don't do quests.\n");
        return;
     }
     p = &(qflags (a));
     n = pname (a);
     l = plev (a);
     qp = &qpoints(a);
  }
  else if (!getuaf (wordbuf, &d))      /* Data retrieval for offline players */
  {  bprintf ("No such persona in system.\n");
     return;
  }
  else if (plev (mynum) < LVL_APPREN)
  {  bprintf ("You can only check your own Quest-stats.\n");
     return;
  }
  else
  {  f = True;
     p = &(d.p_quests);
     n = d.p_name;
     l = d.p_level;
     qp = &d.p_questpoints;
  }
  
  if (brkword () == -1)
  {  bprintf ("\nPlayer: %s\n\n", n);
      
     all = False;
     bprintf ("&+wCompleted Quests:&*\n");
     if (q_all(p))
     {  bprintf("All!\n");
        all = True;
     }
     else if (p->h != 0 || p->l != 0)
        show_bits((int *)p, sizeof(QFLAGS)/sizeof(int), ReqQuests);
     else 
        bprintf("None!\n");

     if (!all)
     { 
        bprintf ("\n&+wStill to do:&*\n");
        invert_all(&q,p);
        show_bits ((int *) &q, sizeof (QFLAGS) / sizeof (int), ReqQuests);
     }
     return;
  }
  else if ((b = tlookup (wordbuf, Quests)) == -1)
  {  bprintf ("%s: No such Quest.\n", wordbuf);
     return;
  }
  else if (brkword () == -1 || plev (mynum) < LVL_ARCHWIZARD)
  {  c = tst_bit(p,b) ? 1 : 0;
     bprintf ("Value of %s is %s, and it is worth %d questpoints.\n", Quests[b], TF[c],QuestPoints[b]);
     return;
  }
  else if (plev (mynum) < LVL_ARCHWIZARD && !EQ (n, pname (mynum)))
  {  bprintf ("You can't change other players Quest-stats.\n");
     return;
  }
  else if ((c = tlookup (wordbuf, TF)) == -1)
  {  bprintf ("Value must be True or False.\n");
     return;
  }

#ifdef LOG_SET  
  mudlog ("QUEST: %s by %s, %s := %s", n, pname (mynum), Quests[b], TF[c]);
#endif
  
  if (c == 0)
  {   if (tst_bit(p,b)) 
          (*qp) -= QuestPoints[b];
      clr_bit(p,b);
  }
  else
  {   if (!tst_bit(p,b))
         (*qp) += QuestPoints[b];
      set_bit(p,b);
  }
  if (f)
     putuaf (&d);
}


/*****************************************************************************
 ** Show which quests have been completed this reset.
 ** Adjusted the code to show the quests in 2 columns instead of one - Marty
 ***************************************************************************/
A_COMMAND(qdonecom)
{ int q,i=0;        /* Q = Questcounter, i = indentation counter */
  int free=0;

#ifdef TWOCOLUMNS  
  bprintf("&+wQuest information for this reset&*\n");
  bprintf("&+w--------------------------------   --------------------------------&*\n");
  for (q = 0; q <= LAST_QUEST; q++)
  { 
    bprintf("%-15s       %-15s   ", Quests[q],
            (questsdone[q] == True ? "&+wcompleted&*" : "&+wyet to do!&*"));

    if (!i)                      /* IF only one column was printed */
        i++;                     /* increase indentation counter */
    else                         /* ELSE we have printed two columns */
    {  bprintf("\n");            /* And we reset the stuff */
       i=0;
    }
  }
  bprintf("%s&+w--------------------------------   --------------------------------&*\n",i ? "\n" : "");
#else   
  bprintf("&+wQuest Information for this reset.\n");
  bprintf("&+w---------------------    ---------------------    ---------------------\n");
  for (q=0; q <= LAST_QUEST; q++)
  {  
     /*bprintf("%-15s  %s    ", Quests[q], (questsdone[q] == True) ? "&+wDone&*" : "&+wFree&*");*/
     bprintf("%-15s  %s    ",Quests[q],queststat(q));
     if (questsdone[q] != True)
        free++;

     if (i != 2)
        i++;
     else
     {  bprintf("\n");
        i=0;
     }
  }
  bprintf("%s&+w---------------------    ---------------------    ---------------------\n", (i != 0) ? "\n" : "");
  bprintf("&+wOf a total of &+w%d&+w quests, &+w%d&+w are still available for players.\n",LAST_QUEST+1,free);
#endif 
}

void qinfo_list(void)
{   int i,indent = 0;
    int req=0;

    bprintf("&+w=============================&+w[Quest Index]&+w===================================\n"
            "This mud has a wide variaty of quests available for you to solve. Here is a\n"
            "list of all quests available on this MUD:\n\n",DOUBLELINE);

    for (i=0; i <= LAST_QUEST; i++)
    {   req = isrequired(i);
        bprintf("%s &+w%-15s&*   &+w%1d&*    ", req != 0 ? "&+w*&*" : "&+w-&*",
		Quests[i], QuestPoints[i]);
        indent++;
        if (indent == 3)
        {   bprintf("\n");
            indent = 0;
        }
    }
    bprintf("%s\nUse &+wQINFO <questname>&* to get a short description of the quest.\n&+w%s\n",indent != 0 ? "\n" : "",DOUBLELINE);
}

void calib_questpoints(int plr)
{   int qp = 0,i;

    for (i = 0; i <= LAST_QUEST; i++)
    {   if (qtstflg(plr,i))
           qp += QuestPoints[i];
    }

    if (qpoints(plr) != qp)
    {   bprintf("Calibrating Questpoints...\n");
        mudlog("QUEST: Calibrated questpoints for %s from %d to %d\n",pname(plr),qpoints(plr),qp);
        qpoints(plr) = qp;
    }

    if (!q_all(&qflags(plr)) && wlevel(plev(plr)) == LEV_SENIOR)
    {   QFLAGS q, *pq = &(qflags(plr));

        invert_all(&q,pq);
        bprintf("You do not qualify for the senior wizard status anymore you do not have\n"
                "all the quests anymore. You need the following quest(s) to become senior\n"
                "again:\n\n");
        show_bits((int *)&q,sizeof(QFLAGS)/sizeof(int),ReqQuests);
        bprintf("\n");
        mudlog("GAME: %s doesnt qualify for senior wizard anymore.",pname(plr));
        setplev(plr,LVL_WIZARD);
        set_xpflags(plev(plr),&pflags(plr),&pmask(plr));
        update_wizlist(pname(plr),wlevel(plev(plr)));
    }
}

Boolean q_required(LongInt *f)
{   int i;

    for (i = 0; quest_list[i] != (-1); i += 2)
    {   if (quest_list[i+1] && !tst_bit(f,quest_list[i]))
           return False;
    }
    return True;
}

Boolean q_all(LongInt *f)
{   int i;

    for (i = 0; i <= LAST_QUEST; i++)
    {   if (!tst_bit(f,i))
           return False;
    }
    return False;
}

void invert_all(LongInt *inverted, LongInt *orig)
{   int i;

    inverted->h = inverted->l = 0;

    for (i = 0; i <= LAST_QUEST; i++)
    {   if (tst_bit(orig,i))
           clr_bit(inverted,i);
        else
           set_bit(inverted,i);
    }
}

void invert_req(LongInt *inverted, LongInt *org)
{   int i;

    inverted->h = inverted->l = 0;
   
    for (i = 0; quest_list[i] != -1 ; i += 2)
    {   if (quest_list[i+1])
        {  if (tst_bit(org,quest_list[i]))
              clr_bit(inverted,quest_list[i]);
           else
              set_bit(inverted,quest_list[i]);
        }
        else
           clr_bit(org,quest_list[i]);
    }
}

Boolean isrequired(int bit)
{   int i;

    for (i = 0; quest_list[i] != -1; i += 2)
    {   if (quest_list[i] == bit)
           return quest_list[i+1];

    }
    /* Assume any entry not in the quest_list isnt required */
    return False;
}