/*
 *      ADVDBG.C - Collosal Cave Adventure debugging routines
 *      (C) 1986 Ravi Bhavnani
 *      All rights reserved
 */

#include "adv.h"


dbg (rtn_name)
char	*rtn_name;
/*
 *	DISPLAYS ROUTINE TRACE IN DEBUG MODE.
 */
{
int	derf;

	if (!debug)
	   return;

	margin += TRACE_MARGIN;
	for (derf=0; (derf<margin); derf++)
	    printf (" ");
	printf ("(%d)%s", margin, rtn_name);
}


advdbg()
/*
 *      ENABLES INTERACTIVE DEBUGGING.
 */
{
	/* ONLY WIZARDS CAN DO THIS... */

        if (strcmp(getenv("USER"),"BHAVNANI") && strcmp(getenv("USER"),"CHARDON"))
           {
             printf ("Sorry, only wizards are allowed to do that.\n");
             return;
           }

        display_main_menu();
        do
        {
          printf ("\nAMS> ");
          gets (str);
          str[1] = '\0';
          switch (str[0])
          {
            case '1': toggle_dbg(); break;
            case '2': check_place(); break;
            case '3': check_obj(); break;
            case '4': check_msg(); break;
            case '5': check_vocab(); break;
            case '6': travel_to_loc(); break;
            case '7': get_obj(); break;
            case '8': move_obj(); break;
            case '9': display_vars(); break;
/*	    case 'e':					*/
/*	    case 'E': toggle_extended_mode(); break;	*/
	    case 't':
	    case 'T': transport_treasures(); break;
            case '?': display_main_menu(); break;
            case 'X':
            case 'x': printf ("\n");
                      return;
            default:  printf ("\007");
                      break;
          }
        }
        forever;
}


display_main_menu()
{
        printf ("\n"); cls();

        printf ("Adventure Maintenance System / %ld bytes RAM used\n\n", memused);
        printf ("  1 - debug off/on\n");
        printf ("  2 - place checker\n");
        printf ("  3 - object checker\n");
        printf ("  4 - message checker\n");
        printf ("  5 - vocabulary checker\n");
        printf ("  6 - travel to a location\n");
        printf ("  7 - get an object\n");
        printf ("  8 - move an object\n");
        printf ("  9 - display variables\n");
/*	printf ("  E - enable/disable extended mode\n");	*/
	printf ("  T - transport all treasures to building\n");
        printf ("  ? - display this menu\n");
        printf ("  x - exit\n");
}


transport_treasures()
{
int	derf,
	movedp;

	do
	{
	  printf ("Are you sure (Y/N)? ");
	  gets (str);
	  str[1] = '\0';
	  if (!strlen(str) || str[0]=='n' || str[0]=='N')
	     {
	       printf ("Treasures not transported\n");
	       return;
	     }
	  else
	     if (str[0]=='y' || str[0]=='Y')
	        {
	          for (movedp=0,derf=MINTREASURES; (derf <= MAXTREASURES); derf++)
	              if (where_is[derf] != building)
	                 {
	                   apport (derf, building);
                           printf ("(%s moved)\n", obj[derf].invdesc);
	                   movedp++;
	                 }
	          if (movedp)
	             printf ("%d treasure(s) moved\n", movedp);
	          else
	             printf ("No treasures moved\n");
	          return;
	        }
	     else
	        printf ("\007");
	}
	while (1);
}


toggle_extended_mode()
{
	extended = (extended ? 0 : 1);
	printf ("Extended mode is now %sabled.\n", extended ? "en" : "dis");
}


toggle_dbg()
{
        debug = (debug ? 0 : 1);
	if (!debug)
	   margin = 0;
        printf ("Debug is now %s.\n", debug ? "ON" : "OFF");
}


check_place()
{
int     derf, bar, foobar;

        derf = 0;
        do
        {
          printf ("\nCheck place (0..%d, -1 quits): ", nlongs);
          gets (str);
          if ((sscanf (str, "%d", &derf) != 1) || (derf < 0 || derf > nlongs))
             {
               printf ("\n");
               continue;
             }

          printf ("VISITED %d time(s)\n", visited[derf]);
          printf ("SHORT DESCRIPTION\n");
          ssay (derf);
          printf ("LONG DESCRIPTION\n");
          lsay (derf);
          printf ("OBJECTS HERE (VALUE)\n");
          bar = 0;
          for (foobar=MINOBJECTS; (foobar <= MAXOBJECTS); foobar++)
              if (where_is [foobar] == derf)
                 {
                   bar++;
                   printf ("%d: %s (%d)\n", foobar, obj[foobar].invdesc, val[foobar]);
                 }
           if (bar)
              printf ("%d objects found\n", bar);
           else
              printf ("None\n");
        }
        while (derf!=-1);
}


check_obj()
{
int     derf, foobar, indx;

        derf = 0;
        do
        {
          printf ("\nCheck object (1..%d, or name <RETURN> quits): ", nobj);
          gets (str);
	  if (!strlen(str))
	     {
	       printf ("\n");
	       return;
	     }

          if (sscanf (str, "%d", &derf) == 1)
	     if (derf < 1 || derf > nobj)
                {
	          printf ("\007");
	          continue;
	        }
	     else
	        ;
	  else
	     {
	       derf = errword;
	       strlwr (str);
	       for (indx=0; (indx <= nvocab); indx++)
	           if (!strcmp (str, vocab[indx].word))
	              {
                        derf = vocab[indx].meaning;
	                break;
	              }
	       if (derf == errword || !isobj(derf))
                  {
	            printf ("\007");
	            continue;
	          }
	      }

          printf ("INVENTORY DESCRIPTION\n");
          printf ("%d: %s\n", derf, obj[derf].invdesc);
          printf ("VALUE  LOCATION\n");
          printf ("%4d%8d\n", val[derf], where_is[derf]);
          printf ("OBJECT DESCRIPTIONS\n");
          for (foobar=0; (foobar < MAXVALS); foobar++)
              {
                printf ("%d\n", foobar);
                osay (derf, foobar);
              }
          printf ("\n");
        }
        while (1);
}


check_vocab()
{
int     derf;

        do
        {
          printf ("Vocab entry (0-%d, -1 quits)? ", nvocab);
          gets (str);
          if ((sscanf (str, "%d", &derf) != 1) || (derf < 0 || derf > nvocab))
             {
               printf ("\n");
               continue;
             }
          printf ("%d: %s\n\n", vocab[derf].meaning, vocab[derf].word);
        }
        while (derf != -1);
}


check_msg()
{
int     derf;

        derf = 0;
        do
        {
          printf ("Message (0..%d, -1 quits): ", nmsgs);
          gets (str);
          if ((sscanf (str, "%d", &derf) != 1) || (derf < 0 || derf > nmsgs))
             {
               printf ("\n");
               continue;
             }

          msay (derf);
          printf ("\n");
        }
        while (derf!=-1);
}


travel_to_loc()
{
int     derf, oldloc, foobar;

        oldloc = here;
        derf = 0;
        do
        {
          printf ("\nCurrently at %d, visited %d time(s):\n", oldloc, visited[oldloc]);
          ssay (oldloc);

          for (foobar=MINOBJECTS; (foobar <= MAXOBJECTS); foobar++)
              if (where_is [foobar] == oldloc)
                 printf ("      [%s] (%d)\n", obj[foobar].invdesc, val[foobar]);

          printf ("New location (0..%d, -1 quits): ", nlongs);
          gets (str);
          if ((sscanf (str, "%d", &derf) != 1) || (derf < 0 || derf > nlongs))
             {
               printf ("\n");
               continue;
             }
          oldloc = derf;
          printf ("\n");
        }
        while (derf != -1);

        if (oldloc != here)
           {
             here = oldloc;
             moved = 1;
           }
}


move_obj()
{
int     derf, foobar, indx, bar;

        derf = 0;
        do
        {
          printf ("\nMove object (1..%d, or name <RETURN> quits): ", nobj);
          gets (str);
	  if (!strlen(str))
	     {
	       printf ("\n");
	       return;
	     }

          if (sscanf (str, "%d", &derf) == 1)
	     if (derf < 1 || derf > nobj)
                {
	          printf ("\007");
	          continue;
	        }
	     else
	        ;
	  else
	     {
	       derf = errword;
	       strlwr (str);
	       for (indx=0; (indx <= nvocab); indx++)
	           if (!strcmp (str, vocab[indx].word))
	              {
                        derf = vocab[indx].meaning;
	                break;
	              }
	       if (derf == errword || !isobj(derf))
                  {
	            printf ("\007");
	            continue;
	          }
	      }

          printf ("OBJECT %d\n", derf);
          printf ("%s\n", obj[derf].invdesc);
          printf ("NOW AT %d\n", where_is[derf]);
	  if (derf == inhand)
	     printf ("In hand.\n");
	  else
             ssay (where_is[derf]);

          printf ("New location (0..%d, <RETURN> quits): ", nlongs);
          gets (str);
	  if (!strlen(str))
	     {
	       printf ("(Object not moved)\n");
	       continue;
	     }

          if (sscanf(str,"%d",&bar)!=1 || bar<0 || bar>nlongs)
             {
               bar = 1;        /* loop back to object */
               printf ("\007Invalid location\n");
               continue;
             }
          where_is[derf] = bar;
          printf ("MOVED TO\n");
	  if (derf == inhand)
	     printf ("In hand.\n");
	  else
             ssay (where_is[derf]);
        }
        while (1);
}


get_obj()
{
int     derf, indx;

        do
        {
          printf ("\nGet object (1..%d, or name <RETURN> quits): ", nobj);
          gets (str);
	  if (!strlen(str))
	     {
	       printf ("\n");
	       return;
	     }

          if (sscanf (str, "%d", &derf) == 1)
	     if (derf < 1 || derf > nobj)
                {
	          printf ("\007");
	          continue;
	        }
	     else
	        ;
	  else
	     {
	       derf = errword;
	       strlwr (str);
	       for (indx=0; (indx <= nvocab); indx++)
	           if (!strcmp (str, vocab[indx].word))
	              {
                        derf = vocab[indx].meaning;
	                break;
	              }
	       if (derf == errword || !isobj(derf))
                  {
	            printf ("\007");
	            continue;
	          }
	      }

          printf ("\"%s\" now at location %d\n", obj[derf].invdesc, where_is[derf]);
          printf ("Get object (Y/N)? ");
          gets (str);
          if (strlen(str) && (!strcmp(str,"Y") || !strcmp(str,"y")))
	    {
               printf ("Taken");
               seen [derf]++;
               where_is[derf] = inhand;
             }
          printf ("\n");
        }
        while (derf != -1);
}


display_vars()
/*
 *      DISPLAY KEY VARIABLES.
 */
{
        printf ("\n");
        printf ("cameotime   = %d\n", cameotime);
        printf ("clock       = %d\n", clock);
        printf ("closure     = %d\n", closure);
        printf ("deaths      = %d\n", deaths);
        printf ("dragtime    = %d\n", dragtime);
        printf ("dwarfcount  = %d\n", dwarfcount);
        printf ("dwarrows    = %d\n", dwarrows);
        printf ("foobar      = %d\n", foobar);
        printf ("hintime     = %d\n", hintime);
        printf ("invct       = %d\n", invct);
        printf ("knives      = %d\n", knives);
        printf ("lamplife    = %d\n", lamplife);
        printf ("lastclock   = %d\n", lastclock);
        printf ("maxscore    = %d\n", maxscore);
        printf ("mushtime    = %d\n", mushtime);
        printf ("nmoves      = %d\n", nmoves);
        printf ("nturns      = %d\n", nturns);
        printf ("penalties   = %d\n", penalties);
        printf ("scorex      = %d\n", scorex);
        printf ("strength    = %d\n", strength);
        printf ("ticker      = %d\n", ticker);
}


bug (errcode)
int     errcode;
/*
 *      PRINT ERROR MESSAGE IF DEBUG IS ENABLED.
 */
{
static char     errmsg [STRINGLEN];

        fprintf (stderr, "\nGLITCH! (%d)", errcode);

        switch (errcode)
        {
          case CANTOPENMSGFILE:
            sprintf (errmsg, "Can't open message file \"%s\"", msgfile);
            break;
          case BADMSGFILE:
            sprintf (errmsg, "Message file contains invalid entry /%s/", str);
            break;
          case TOOMANYMSGS:
            sprintf (errmsg, "Messages exceed %d entries", MAXMESSAGES);
            break;
          case NOTENUFMSGMEM:
            sprintf (errmsg, "Insufficient memory at message %d", nmsgs);
            break;
          case CANTOPENLONGFILE:
            sprintf (errmsg, "Can't open description file \"%s\"", longfile);
            break;
          case BADLONGFILE:
            sprintf (errmsg, "Long description file contains invalid entry /%s/", str);
            break;
          case TOOMANYLONGS:
            sprintf (errmsg, "Long descriptions exceed %d entries", MAXPLACES);
            break;
          case NOTENUFLONGMEM:
            sprintf (errmsg, "Insufficient memory at long description %d", nlongs);
            break;
          case CANTOPENSHORTFILE:
            sprintf (errmsg, "Can't open description file \"%s\"", shortfile);
            break;
          case BADSHORTFILE:
            sprintf (errmsg, "Short description file contains invalid entry /%s/", str);
            break;
          case TOOMANYSHORTS:
            sprintf (errmsg, "Short descriptions exceed %d entries", MAXPLACES);
            break;
          case NOTENUFSHORTMEM:
            sprintf (errmsg, "Insufficient memory at short description %d", nshorts);
            break;
          case CANTOPENVOCABFILE:
            sprintf (errmsg, "Can't open vocabulary file \"%s\"", vocabfile);
            break;
          case BADVOCABFILE:
            sprintf (errmsg, "Vocabulary file contains invalid entry /%s/", str);
            break;
          case BADVOCABWORD:
            sprintf (errmsg, "Vocabulary entry too long /%s/", str);
            break;
          case VOCAB2BIG:
            sprintf (errmsg, "Vocabulary exceeds %d entries", MAXVOCAB);
            break;
         case CANTOPENOBJFILE:
            sprintf (errmsg, "Can't open object description file \"%s\"", objfile);
            break;
          case BADOBJFILE:
            sprintf (errmsg, "Object description file contains invalid entry /%s/", str);
            break;
          case TOOMANYOBJECTS:
            sprintf (errmsg, "Object descriptions exceed %d entries", MAXOBJECTS);
            break;
          case OBJ2MANYVALS:
            sprintf (errmsg, "Object %d contains more than %d states", nobj, MAXVALS);
            break;
          case NOTENUFOBJMEM:
            sprintf (errmsg, "Insufficient memory at object %d", nobj);
            break;
          case BADQUERY:
            strcpy (errmsg, "Invalid prompt");
            break;
          default:
            sprintf (errmsg, "Unknown error code (%d)", errcode);
       }

        fprintf (stderr, ", %s", errmsg);
        if (errcode==NOTENUFMSGMEM || errcode==NOTENUFSHORTMEM ||
            errcode==NOTENUFLONGMEM || errcode==NOTENUFOBJMEM)
            fprintf (stderr, "\nDynamic memory used = %d bytes", memused);
        exit();
}
