home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / games / larn / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-28  |  23.2 KB  |  879 lines

  1. /*    main.c        */
  2. #include <sys/types.h>
  3. #include "header.h"
  4. #include <pwd.h>
  5. static char copyright[]="\nLarn is copyrighted 1986 by Noah Morgan.\n";
  6. int srcount=0;    /* line counter for showstr()    */
  7. int dropflag=0; /* if 1 then don't lookforobject() next round */
  8. int rmst=80;    /*    random monster creation counter        */
  9. int userid;        /* the players login user id number */
  10. char nowelcome=0,nomove=0; /* if (nomove) then don't count next iteration as a move */
  11. static char viewflag=0;
  12.     /*    if viewflag then we have done a 99 stay here and don't showcell in the main loop */
  13. char restorflag=0;    /* 1 means restore has been done    */
  14. static char cmdhelp[] = "\
  15. Cmd line format: larn [-slicnh] [-o<optsifle>] [-##] [++]\n\
  16.   -s   show the scoreboard\n\
  17.   -l   show the logfile (wizard id only)\n\
  18.   -i   show scoreboard with inventories of dead characters\n\
  19.   -c   create new scoreboard (wizard id only)\n\
  20.   -n   suppress welcome message on starting game\n\
  21.   -##  specify level of difficulty (example: -5)\n\
  22.   -h   print this help text\n\
  23.   ++   restore game from checkpoint file\n\
  24.   -o<optsfile>   specify .larnopts filename to be used instead of \"~/.larnopts\"\n\
  25. ";
  26. #ifdef VT100
  27. static char *termtypes[] = { "vt100", "vt101", "vt102", "vt103", "vt125",
  28.     "vt131", "vt140", "vt180", "vt220", "vt240", "vt241", "vt320", "vt340",
  29.     "vt341"  };
  30. #endif VT100
  31. /*
  32.     ************
  33.     MAIN PROGRAM
  34.     ************
  35.  */
  36. main(argc,argv)
  37.     int argc;
  38.     char **argv;
  39.     {
  40.     register int i,j;
  41.     int hard;
  42.     char *ptr=0,*ttype;
  43.     struct passwd *pwe;
  44.  
  45. /*
  46.  *    first task is to identify the player
  47.  */
  48. #ifndef VT100
  49.     init_term();    /* setup the terminal (find out what type) for termcap */
  50. #endif VT100
  51.     if (((ptr = getlogin()) == 0) || (*ptr==0))    /* try to get login name */
  52.       if (pwe=getpwuid(getuid())) /* can we get it from /etc/passwd? */
  53.         ptr = pwe->pw_name;
  54.       else
  55.       if ((ptr = getenv("USER")) == 0)
  56.         if ((ptr = getenv("LOGNAME")) == 0)
  57.           {
  58.           noone: write(2, "Can't find your logname.  Who Are You?\n",39);
  59.                   exit();
  60.           }
  61.     if (ptr==0) goto noone;
  62.     if (strlen(ptr)==0) goto noone;
  63. /*
  64.  *    second task is to prepare the pathnames the player will need
  65.  */
  66.     strcpy(loginname,ptr); /* save loginname of the user for logging purposes */
  67.     strcpy(logname,ptr);    /* this will be overwritten with the players name */
  68.     if ((ptr = getenv("HOME")) == 0) ptr = ".";
  69.     strcpy(savefilename, ptr);
  70.     strcat(savefilename, "/Larn.sav");    /* save file name in home directory */
  71.     sprintf(optsfile, "%s/.larnopts",ptr);    /* the .larnopts filename */
  72.  
  73. /*
  74.  *    now malloc the memory for the dungeon 
  75.  */
  76.     cell = (struct cel *)malloc(sizeof(struct cel)*(MAXLEVEL+MAXVLEVEL)*MAXX*MAXY);
  77.     if (cell == 0) died(-285);    /* malloc failure */
  78.     lpbuf    = malloc((5* BUFBIG)>>2);    /* output buffer */
  79.     inbuffer = malloc((5*MAXIBUF)>>2);    /* output buffer */
  80.     if ((lpbuf==0) || (inbuffer==0)) died(-285); /* malloc() failure */
  81.  
  82.     lcreat((char*)0);    newgame();        /*    set the initial clock  */ hard= -1;
  83.  
  84. #ifdef VT100
  85. /*
  86.  *    check terminal type to avoid users who have not vt100 type terminals
  87.  */
  88.     ttype = getenv("TERM");
  89.     for (j=1, i=0; i<sizeof(termtypes)/sizeof(char *); i++)
  90.         if (strcmp(ttype,termtypes[i]) == 0) { j=0;  break; }
  91.     if (j)
  92.         {
  93.         lprcat("Sorry, Larn needs a VT100 family terminal for all it's features.\n"); lflush();
  94.         exit();
  95.         }
  96. #endif VT100
  97.  
  98. /*
  99.  *    now make scoreboard if it is not there (don't clear) 
  100.  */
  101.     if (access(scorefile,0) == -1) /* not there */
  102.         makeboard();
  103.  
  104. /*
  105.  *    now process the command line arguments 
  106.  */
  107.     for (i=1; i<argc; i++)
  108.         {
  109.         if (argv[i][0] == '-')
  110.           switch(argv[i][1])
  111.             {
  112.             case 's': showscores();  exit();  /* show scoreboard   */
  113.  
  114.             case 'l': /* show log file     */
  115.                         diedlog();        exit();
  116.  
  117.             case 'i': showallscores();  exit();  /* show all scoreboard */
  118.  
  119.             case 'c':          /* anyone with password can create scoreboard */
  120.                       lprcat("Preparing to initialize the scoreboard.\n");
  121.                       if (getpassword() != 0)  /*make new scoreboard*/
  122.                             {
  123.                             makeboard(); lprc('\n'); showscores();
  124.                             }
  125.                       exit();
  126.  
  127.             case 'n':    /* no welcome msg    */ nowelcome=1; argv[i][0]=0; break;
  128.  
  129.             case '0': case '1': case '2': case '3': case '4': case '5':
  130.             case '6': case '7': case '8': case '9':    /* for hardness */
  131.                         sscanf(&argv[i][1],"%d",&hard);    
  132.                         break;
  133.  
  134.             case 'h':    /* print out command line arguments */
  135.                         write(1,cmdhelp,sizeof(cmdhelp));  exit();
  136.  
  137.             case 'o':    /* specify a .larnopts filename */
  138.                         strncpy(optsfile,argv[i]+2,127);  break;
  139.  
  140.             default:    printf("Unknown option <%s>\n",argv[i]);  exit();
  141.             };
  142.  
  143.         if (argv[i][0] == '+')
  144.             {
  145.             clear();    restorflag = 1;
  146.             if (argv[i][1] == '+')
  147.                 {
  148.                 hitflag=1; restoregame(ckpfile); /* restore checkpointed game */
  149.                 }
  150.             i = argc;
  151.             }
  152.         }
  153.  
  154.     readopts();        /* read the options file if there is one */
  155.  
  156.  
  157. #ifdef UIDSCORE
  158.     userid = geteuid();    /* obtain the user's effective id number */
  159. #else UIDSCORE
  160.     userid = getplid(logname);    /* obtain the players id number */
  161. #endif UIDSCORE
  162.     if (userid < 0) { write(2,"Can't obtain playerid\n",22); exit(); }
  163.  
  164. #ifdef HIDEBYLINK
  165. /*
  166.  *    this section of code causes the program to look like something else to ps
  167.  */
  168.     if (strcmp(psname,argv[0])) /* if a different process name only */
  169.         {
  170.         if ((i=access(psname,1)) < 0)
  171.             {        /* link not there */
  172.             if (link(argv[0],psname)>=0)
  173.                 {
  174.                 argv[0] = psname;   execv(psname,argv);
  175.                 }
  176.             }
  177.         else 
  178.             unlink(psname);
  179.         }
  180.  
  181.     for (i=1; i<argc; i++)
  182.         {
  183.         szero(argv[i]);    /* zero the argument to avoid ps snooping */
  184.         }
  185. #endif HIDEBYLINK
  186.  
  187.     if (access(savefilename,0)==0)    /* restore game if need to */
  188.         {
  189.         clear();    restorflag = 1;
  190.         hitflag=1;    restoregame(savefilename);  /* restore last game    */
  191.         }
  192.     sigsetup();        /* trap all needed signals    */
  193.     sethard(hard);    /* set up the desired difficulty                */
  194.     setupvt100();    /*    setup the terminal special mode                */
  195.     if (c[HP]==0)    /* create new game */
  196.         {
  197.         makeplayer();    /*    make the character that will play            */
  198.         newcavelevel(0);/*    make the dungeon                             */
  199.         predostuff = 1;    /* tell signals that we are in the welcome screen */
  200.         if (nowelcome==0) welcome();     /* welcome the player to the game */
  201.         }
  202.     drawscreen();    /*    show the initial dungeon                    */
  203.     predostuff = 2;    /* tell the trap functions that they must do a showplayer()
  204.                         from here on */
  205.     /* nice(1);    /* games should be run niced */
  206.     yrepcount = hit2flag = 0;
  207.     while (1)
  208.         {
  209.         if (dropflag==0) lookforobject(); /* see if there is an object here    */
  210.             else dropflag=0; /* don't show it just dropped an item */
  211.         if (hitflag==0) { if (c[HASTEMONST]) movemonst(); movemonst(); }    /*    move the monsters        */
  212.         if (viewflag==0) showcell(playerx,playery); else viewflag=0;    /*    show stuff around player    */
  213.         if (hit3flag) flushall();
  214.         hitflag=hit3flag=0;    nomove=1;
  215.         bot_linex();    /* update bottom line */
  216.         while (nomove)
  217.             {
  218.             if (hit3flag) flushall();
  219.             nomove=0; parse();
  220.             }    /*    get commands and make moves    */
  221.         regen();            /*    regenerate hp and spells            */
  222.         if (c[TIMESTOP]==0)
  223.             if (--rmst <= 0)
  224.                 { rmst = 120-(level<<2); fillmonst(makemonst(level)); }
  225.         }
  226.     }
  227.  
  228. /*
  229.     showstr()
  230.  
  231.     show character's inventory
  232.  */
  233. showstr()
  234.     {
  235.     register int i,number;
  236.     for (number=3, i=0; i<26; i++)
  237.         if (iven[i]) number++;    /* count items in inventory */
  238.     t_setup(number);    qshowstr();      t_endup(number);
  239.     }
  240.  
  241. qshowstr()
  242.     {
  243.     register int i,j,k,sigsav;
  244.     srcount=0;  sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
  245.     if (c[GOLD]) { lprintf(".)   %d gold pieces",(long)c[GOLD]); srcount++; }
  246.     for (k=26; k>=0; k--)
  247.       if (iven[k])
  248.         {  for (i=22; i<84; i++)
  249.              for (j=0; j<=k; j++)  if (i==iven[j])  show3(j); k=0; }
  250.  
  251.     lprintf("\nElapsed time is %d.  You have %d mobuls left",(long)((gtime+99)/100+1),(long)((TIMELIMIT-gtime)/100));
  252.     more();        nosignal=sigsav;
  253.     }
  254.  
  255. /*
  256.  *    subroutine to clear screen depending on # lines to display
  257.  */
  258. t_setup(count)
  259.     register int count;
  260.     {
  261.     if (count<20)  /* how do we clear the screen? */
  262.         {
  263.         cl_up(79,count);  cursor(1,1);
  264.         }
  265.     else
  266.         {
  267.         resetscroll(); clear();
  268.         }
  269.     }
  270.  
  271. /*
  272.  *    subroutine to restore normal display screen depending on t_setup()
  273.  */
  274. t_endup(count)
  275.     register int count;
  276.     {
  277.     if (count<18)  /* how did we clear the screen? */
  278.         draws(0,MAXX,0,(count>MAXY) ? MAXY : count);
  279.     else
  280.         {
  281.         drawscreen(); setscroll();
  282.         }
  283.     }
  284.  
  285. /*
  286.     function to show the things player is wearing only
  287.  */
  288. showwear()
  289.     {
  290.     register int i,j,sigsav,count;
  291.     sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
  292.     srcount=0;
  293.  
  294.      for (count=2,j=0; j<=26; j++)     /* count number of items we will display */
  295.        if (i=iven[j])
  296.         switch(i)
  297.             {
  298.             case OLEATHER:    case OPLATE:    case OCHAIN:
  299.             case ORING:        case OSTUDLEATHER:    case OSPLINT:
  300.             case OPLATEARMOR:    case OSSPLATE:    case OSHIELD:
  301.             count++;
  302.             };
  303.  
  304.     t_setup(count);
  305.  
  306.     for (i=22; i<84; i++)
  307.          for (j=0; j<=26; j++)
  308.            if (i==iven[j])
  309.             switch(i)
  310.                 {
  311.                 case OLEATHER:    case OPLATE:    case OCHAIN:
  312.                 case ORING:        case OSTUDLEATHER:    case OSPLINT:
  313.                 case OPLATEARMOR:    case OSSPLATE:    case OSHIELD:
  314.                 show3(j);
  315.                 };
  316.     more();        nosignal=sigsav;    t_endup(count);
  317.     }
  318.  
  319. /*
  320.     function to show the things player can wield only 
  321.  */
  322. showwield()
  323.     {
  324.     register int i,j,sigsav,count;
  325.     sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
  326.     srcount=0;
  327.  
  328.      for (count=2,j=0; j<=26; j++)    /* count how many items */
  329.        if (i=iven[j])
  330.         switch(i)
  331.             {
  332.             case ODIAMOND:  case ORUBY:  case OEMERALD:  case OSAPPHIRE:
  333.             case OBOOK:     case OCHEST:  case OLARNEYE: case ONOTHEFT:
  334.             case OSPIRITSCARAB:  case OCUBEofUNDEAD:
  335.             case OPOTION:   case OSCROLL:  break;
  336.             default:  count++;
  337.             };
  338.  
  339.     t_setup(count);
  340.  
  341.     for (i=22; i<84; i++)
  342.          for (j=0; j<=26; j++)
  343.            if (i==iven[j])
  344.             switch(i)
  345.                 {
  346.                 case ODIAMOND:  case ORUBY:  case OEMERALD:  case OSAPPHIRE:
  347.                 case OBOOK:     case OCHEST:  case OLARNEYE: case ONOTHEFT:
  348.                 case OSPIRITSCARAB:  case OCUBEofUNDEAD:
  349.                 case OPOTION:   case OSCROLL:  break;
  350.                 default:  show3(j);
  351.                 };
  352.     more();        nosignal=sigsav;    t_endup(count);
  353.     }
  354.  
  355. /*
  356.  *    function to show the things player can read only
  357.  */
  358. showread()
  359.     {
  360.     register int i,j,sigsav,count;
  361.     sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
  362.     srcount=0;
  363.  
  364.     for (count=2,j=0; j<=26; j++)
  365.         switch(iven[j])
  366.             {
  367.             case OBOOK:    case OSCROLL:    count++;
  368.             };
  369.     t_setup(count);
  370.  
  371.     for (i=22; i<84; i++)
  372.          for (j=0; j<=26; j++)
  373.            if (i==iven[j])
  374.             switch(i)
  375.                 {
  376.                 case OBOOK:    case OSCROLL:    show3(j);
  377.                 };
  378.     more();        nosignal=sigsav;    t_endup(count);
  379.     }
  380.  
  381. /*
  382.  *    function to show the things player can eat only
  383.  */
  384. showeat()
  385.     {
  386.     register int i,j,sigsav,count;
  387.     sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
  388.     srcount=0;
  389.  
  390.     for (count=2,j=0; j<=26; j++)
  391.         switch(iven[j])
  392.             {
  393.             case OCOOKIE:    count++;
  394.             };
  395.     t_setup(count);
  396.  
  397.     for (i=22; i<84; i++)
  398.          for (j=0; j<=26; j++)
  399.            if (i==iven[j])
  400.             switch(i)
  401.                 {
  402.                 case OCOOKIE:    show3(j);
  403.                 };
  404.     more();        nosignal=sigsav;    t_endup(count);
  405.     }
  406.  
  407. /*
  408.     function to show the things player can quaff only
  409.  */
  410. showquaff()
  411.     {
  412.     register int i,j,sigsav,count;
  413.     sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
  414.     srcount=0;
  415.  
  416.     for (count=2,j=0; j<=26; j++)
  417.         switch(iven[j])
  418.             {
  419.             case OPOTION:    count++;
  420.             };
  421.     t_setup(count);
  422.  
  423.     for (i=22; i<84; i++)
  424.          for (j=0; j<=26; j++)
  425.            if (i==iven[j])
  426.             switch(i)
  427.                 {
  428.                 case OPOTION:    show3(j);
  429.                 };
  430.     more();        nosignal=sigsav;        t_endup(count);
  431.     }
  432.  
  433. show1(idx,str2)
  434.     register int idx;
  435.     register char *str2[];
  436.     {
  437.     if (str2==0)  lprintf("\n%c)   %s",idx+'a',objectname[iven[idx]]);
  438.     else if (*str2[ivenarg[idx]]==0)  lprintf("\n%c)   %s",idx+'a',objectname[iven[idx]]);
  439.     else lprintf("\n%c)   %s of%s",idx+'a',objectname[iven[idx]],str2[ivenarg[idx]]);
  440.     }
  441.  
  442. show3(index)
  443.     register int index;
  444.     {
  445.     switch(iven[index]) 
  446.         {
  447.         case OPOTION:    show1(index,potionname);  break;
  448.         case OSCROLL:    show1(index,scrollname);  break;
  449.  
  450.         case OLARNEYE:        case OBOOK:            case OSPIRITSCARAB:
  451.         case ODIAMOND:        case ORUBY:            case OCUBEofUNDEAD:
  452.         case OEMERALD:        case OCHEST:        case OCOOKIE:
  453.         case OSAPPHIRE:        case ONOTHEFT:        show1(index,(char **)0);  break;
  454.  
  455.         default:        lprintf("\n%c)   %s",index+'a',objectname[iven[index]]);
  456.                         if (ivenarg[index]>0) lprintf(" + %d",(long)ivenarg[index]);
  457.                         else if (ivenarg[index]<0) lprintf(" %d",(long)ivenarg[index]);
  458.                         break;
  459.         }
  460.     if (c[WIELD]==index) lprcat(" (weapon in hand)");
  461.     if ((c[WEAR]==index) || (c[SHIELD]==index))  lprcat(" (being worn)");
  462.     if (++srcount>=22) { srcount=0; more(); clear(); }
  463.     }
  464.  
  465. /*
  466.     subroutine to randomly create monsters if needed
  467.  */
  468. randmonst()
  469.     {
  470.     if (c[TIMESTOP]) return;    /*    don't make monsters if time is stopped    */
  471.     if (--rmst <= 0)
  472.         {
  473.         rmst = 120 - (level<<2);  fillmonst(makemonst(level));
  474.         }
  475.     }
  476.  
  477.  
  478. /*
  479.     parse()
  480.  
  481.     get and execute a command
  482.  */
  483. parse()
  484.     {
  485.     register int i,j,k,flag;
  486.     while    (1)
  487.         {
  488.         k = yylex();
  489.         switch(k)    /*    get the token from the input and switch on it    */
  490.             {
  491.             case 'h':    moveplayer(4);    return;        /*    west        */
  492.             case 'H':    run(4);            return;        /*    west        */
  493.             case 'l':    moveplayer(2);    return;        /*    east        */
  494.             case 'L':    run(2);            return;        /*    east        */
  495.             case 'j':    moveplayer(1);    return;        /*    south        */
  496.             case 'J':    run(1);            return;        /*    south        */
  497.             case 'k':    moveplayer(3);    return;        /*    north        */
  498.             case 'K':    run(3);            return;        /*    north        */
  499.             case 'u':    moveplayer(5);    return;        /*    northeast    */
  500.             case 'U':    run(5);            return;        /*    northeast    */
  501.             case 'y':    moveplayer(6);  return;        /*    northwest    */
  502.             case 'Y':    run(6);            return;        /*    northwest    */
  503.             case 'n':    moveplayer(7);    return;        /*    southeast    */
  504.             case 'N':    run(7);            return;        /*    southeast    */
  505.             case 'b':    moveplayer(8);    return;        /*    southwest    */
  506.             case 'B':    run(8);            return;        /*    southwest    */
  507.  
  508.             case '.':    if (yrepcount) viewflag=1; return;        /*    stay here        */
  509.  
  510.             case 'w':    yrepcount=0;    wield();    return;        /*    wield a weapon */
  511.  
  512.             case 'W':    yrepcount=0;    wear();        return;    /*    wear armor    */
  513.  
  514.             case 'r':    yrepcount=0;
  515.                         if (c[BLINDCOUNT]) { cursors(); lprcat("\nYou can't read anything when you're blind!"); } else
  516.                         if (c[TIMESTOP]==0) readscr(); return;        /*    to read a scroll    */
  517.  
  518.             case 'q':    yrepcount=0;    if (c[TIMESTOP]==0) quaff();    return;    /*    quaff a potion        */
  519.  
  520.             case 'd':    yrepcount=0;    if (c[TIMESTOP]==0) dropobj(); return;    /*    to drop an object    */
  521.  
  522.             case 'c':    yrepcount=0;    cast();        return;        /*    cast a spell    */
  523.  
  524.             case 'i':    yrepcount=0;    nomove=1;  showstr();    return;        /*    status        */
  525.  
  526.             case 'e':    yrepcount=0;
  527.                         if (c[TIMESTOP]==0) eatcookie(); return;    /*    to eat a fortune cookie */
  528.  
  529.             case 'D':    yrepcount=0;    seemagic(0);    nomove=1; return;    /*    list spells and scrolls */
  530.  
  531.             case '?':    yrepcount=0;    help(); nomove=1; return;    /*    give the help screen*/
  532.  
  533.             case 'S':    clear();  lprcat("Saving . . ."); lflush();  
  534.                         savegame(savefilename); wizard=1; died(-257);    /*    save the game - doesn't return    */
  535.  
  536.             case 'Z':    yrepcount=0;    if (c[LEVEL]>9) { oteleport(1); return; }
  537.                         cursors(); lprcat("\nAs yet, you don't have enough experience to use teleportation");
  538.                         return;    /*    teleport yourself    */
  539.  
  540.             case '^':    /* identify traps */  flag=yrepcount=0;  cursors();
  541.                         lprc('\n');  for (j=playery-1; j<playery+2; j++)
  542.                             {
  543.                             if (j < 0) j=0;        if (j >= MAXY) break;
  544.                             for (i=playerx-1; i<playerx+2; i++)
  545.                                 {
  546.                                 if (i < 0) i=0;    if (i >= MAXX) break;
  547.                                 switch(item[i][j])
  548.                                     {
  549.                                     case OTRAPDOOR:        case ODARTRAP:
  550.                                     case OTRAPARROW:    case OTELEPORTER:
  551.                                         lprcat("\nIts "); lprcat(objectname[item[i][j]]);  flag++;
  552.                                     };
  553.                                 }
  554.                             }
  555.                         if (flag==0) lprcat("\nNo traps are visible");
  556.                         return;
  557.  
  558. #if WIZID
  559.             case '_':    /*    this is the fudge player password for wizard mode*/
  560.                         yrepcount=0;    cursors(); nomove=1;
  561.                         if (userid!=wisid)
  562.                             {
  563.                             lprcat("Sorry, you are not empowered to be a wizard.\n");
  564.                             scbr(); /* system("stty -echo cbreak"); */
  565.                             lflush();  return;
  566.                             }
  567.                         if (getpassword()==0)
  568.                             {
  569.                             scbr(); /* system("stty -echo cbreak"); */ return;
  570.                             }
  571.                         wizard=1;  scbr(); /* system("stty -echo cbreak"); */
  572.                         for (i=0; i<6; i++)  c[i]=70;  iven[0]=iven[1]=0;
  573.                         take(OPROTRING,50);   take(OLANCE,25);  c[WIELD]=1;
  574.                         c[LANCEDEATH]=1;   c[WEAR] = c[SHIELD] = -1;
  575.                         raiseexperience(6000000L);  c[AWARENESS] += 25000;
  576.                         {
  577.                         register int i,j;
  578.                         for (i=0; i<MAXY; i++)
  579.                             for (j=0; j<MAXX; j++)  know[j][i]=1;
  580.                         for (i=0; i<SPNUM; i++)    spelknow[i]=1;
  581.                         for (i=0; i<MAXSCROLL; i++)  scrollname[i][0]=' ';
  582.                         for (i=0; i<MAXPOTION; i++)  potionname[i][0]=' ';
  583.                         }
  584.                         for (i=0; i<MAXSCROLL; i++)
  585.                           if (strlen(scrollname[i])>2) /* no null items */
  586.                             { item[i][0]=OSCROLL; iarg[i][0]=i; }
  587.                         for (i=MAXX-1; i>MAXX-1-MAXPOTION; i--)
  588.                           if (strlen(potionname[i-MAXX+MAXPOTION])>2) /* no null items */
  589.                             { item[i][0]=OPOTION; iarg[i][0]=i-MAXX+MAXPOTION; }
  590.                         for (i=1; i<MAXY; i++)
  591.                             { item[0][i]=i; iarg[0][i]=0; }
  592.                         for (i=MAXY; i<MAXY+MAXX; i++)
  593.                             { item[i-MAXY][MAXY-1]=i; iarg[i-MAXY][MAXY-1]=0; }
  594.                         for (i=MAXX+MAXY; i<MAXX+MAXY+MAXY; i++)
  595.                             { item[MAXX-1][i-MAXX-MAXY]=i; iarg[MAXX-1][i-MAXX-MAXY]=0; }
  596.                         c[GOLD]+=25000;    drawscreen();    return;
  597. #endif
  598.  
  599.             case 'T':    yrepcount=0;    cursors();  if (c[SHIELD] != -1) { c[SHIELD] = -1; lprcat("\nYour shield is off"); bottomline(); } else
  600.                                         if (c[WEAR] != -1) { c[WEAR] = -1; lprcat("\nYour armor is off"); bottomline(); }
  601.                         else lprcat("\nYou aren't wearing anything");
  602.                         return;
  603.  
  604.             case 'g':    cursors();
  605.                         lprintf("\nThe stuff you are carrying presently weighs %d pounds",(long)packweight());
  606.             case ' ':    yrepcount=0;    nomove=1;  return;
  607.  
  608.             case 'v':    yrepcount=0;    cursors();
  609.                         lprintf("\nCaverns of Larn, Version %d.%d, Diff=%d",(long)VERSION,(long)SUBVERSION,(long)c[HARDGAME]);
  610.                         if (wizard) lprcat(" Wizard"); nomove=1;
  611.                         if (cheat) lprcat(" Cheater");
  612.                         lprcat(copyright);
  613.                         return;
  614.  
  615.             case 'Q':    yrepcount=0;    quit(); nomove=1;    return;    /*    quit        */
  616.  
  617.             case 'L'-64:  yrepcount=0;    drawscreen();  nomove=1; return;    /*    look        */
  618.  
  619. #if WIZID
  620. #ifdef EXTRA
  621.             case 'A':    yrepcount=0;    nomove=1; if (wizard) { diag(); return; }  /*    create diagnostic file */
  622.                         return;
  623. #endif
  624. #endif
  625.             case 'P':    cursors(); 
  626.                         if (outstanding_taxes>0)
  627.                             lprintf("\nYou presently owe %d gp in taxes.",(long)outstanding_taxes);
  628.                         else
  629.                             lprcat("\nYou do not owe any taxes.");
  630.                         return;
  631.             };
  632.         }
  633.     }
  634.  
  635. parse2()
  636.     {
  637.     if (c[HASTEMONST]) movemonst(); movemonst(); /*    move the monsters        */
  638.     randmonst();    regen();
  639.     }
  640.  
  641. run(dir)
  642.     int dir;
  643.     {
  644.     register int i;
  645.     i=1; while (i)
  646.         {
  647.         i=moveplayer(dir);
  648.         if (i>0) {  if (c[HASTEMONST]) movemonst();  movemonst(); randmonst(); regen(); }
  649.         if (hitflag) i=0;
  650.         if (i!=0)  showcell(playerx,playery);
  651.         }
  652.     }
  653.  
  654. /*
  655.     function to wield a weapon
  656.  */
  657. wield()    
  658.     {
  659.     register int i;
  660.     while (1)
  661.         {
  662.         if ((i = whatitem("wield"))=='\33')  return;
  663.         if (i != '.')
  664.             {
  665.             if (i=='*') showwield();
  666.             else  if (iven[i-'a']==0) { ydhi(i); return; }
  667.             else if (iven[i-'a']==OPOTION) { ycwi(i); return; }
  668.             else if (iven[i-'a']==OSCROLL) { ycwi(i); return; }
  669.             else  if ((c[SHIELD]!= -1) && (iven[i-'a']==O2SWORD)) { lprcat("\nBut one arm is busy with your shield!"); return; }
  670.             else  { c[WIELD]=i-'a'; if (iven[i-'a'] == OLANCE) c[LANCEDEATH]=1; else c[LANCEDEATH]=0;  bottomline(); return; }
  671.             }
  672.         }
  673.     }
  674.  
  675. /*
  676.     common routine to say you don't have an item
  677.  */
  678. ydhi(x)
  679.     int x;
  680.     { cursors();  lprintf("\nYou don't have item %c!",x); }
  681. ycwi(x)
  682.     int x;
  683.     { cursors();  lprintf("\nYou can't wield item %c!",x); }
  684.  
  685. /*
  686.     function to wear armor
  687.  */
  688. wear()
  689.     {
  690.     register int i;
  691.     while (1)
  692.         {
  693.         if ((i = whatitem("wear"))=='\33')  return;
  694.         if (i != '.')
  695.             {
  696.             if (i=='*') showwear(); else
  697.             switch(iven[i-'a'])
  698.                 {
  699.                 case 0:  ydhi(i); return;
  700.                 case OLEATHER:  case OCHAIN:  case OPLATE:    case OSTUDLEATHER:
  701.                 case ORING:        case OSPLINT:    case OPLATEARMOR:    case OSSPLATE:
  702.                         if (c[WEAR] != -1) { lprcat("\nYou're already wearing some armor"); return; }
  703.                             c[WEAR]=i-'a';  bottomline(); return;
  704.                 case OSHIELD:    if (c[SHIELD] != -1) { lprcat("\nYou are already wearing a shield"); return; }
  705.                                 if (iven[c[WIELD]]==O2SWORD) { lprcat("\nYour hands are busy with the two handed sword!"); return; }
  706.                                 c[SHIELD] = i-'a';  bottomline(); return;
  707.                 default:    lprcat("\nYou can't wear that!");
  708.                 };
  709.             }
  710.         }
  711.     }
  712.  
  713. /*
  714.     function to drop an object
  715.  */
  716. dropobj()
  717.     {
  718.     register int i;
  719.     register char *p;
  720.     long amt;
  721.     p = &item[playerx][playery];
  722.     while (1)
  723.         {
  724.         if ((i = whatitem("drop"))=='\33')  return;
  725.         if (i=='*') showstr(); else 
  726.             {
  727.             if (i=='.')    /* drop some gold */
  728.                 {
  729.                 if (*p) { lprcat("\nThere's something here already!"); return; }
  730.                 lprcat("\n\n");
  731.                 cl_dn(1,23);
  732.                 lprcat("How much gold do you drop? ");
  733.                 if ((amt=readnum((long)c[GOLD])) == 0) return;
  734.                 if (amt>c[GOLD])
  735.                     { lprcat("\nYou don't have that much!"); return; }
  736.                 if (amt<=32767)
  737.                     { *p=OGOLDPILE; i=amt; }
  738.                 else if (amt<=327670L)
  739.                     { *p=ODGOLD; i=amt/10; amt = 10*i; }
  740.                 else if (amt<=3276700L)
  741.                     { *p=OMAXGOLD; i=amt/100; amt = 100*i; }
  742.                 else if (amt<=32767000L)
  743.                     { *p=OKGOLD; i=amt/1000; amt = 1000*i; }
  744.                 else
  745.                     { *p=OKGOLD; i=32767; amt = 32767000L; }
  746.                 c[GOLD] -= amt; 
  747.                 lprintf("You drop %d gold pieces",(long)amt);
  748.                 iarg[playerx][playery]=i; bottomgold();
  749.                 know[playerx][playery]=0; dropflag=1;  return;
  750.                 }
  751.             drop_object(i-'a');
  752.             return;
  753.             }
  754.         }
  755.     }
  756.  
  757. /*
  758.  *    readscr()        Subroutine to read a scroll one is carrying
  759.  */
  760. readscr()
  761.     {
  762.     register int i;
  763.     while (1)
  764.         {
  765.         if ((i = whatitem("read"))=='\33')  return;
  766.         if (i != '.')
  767.             {
  768.             if (i=='*') showread(); else
  769.                 {
  770.                 if (iven[i-'a']==OSCROLL) { read_scroll(ivenarg[i-'a']); iven[i-'a']=0; return; }
  771.                 if (iven[i-'a']==OBOOK)   { readbook(ivenarg[i-'a']);  iven[i-'a']=0; return; }
  772.                 if (iven[i-'a']==0) { ydhi(i); return; }
  773.                 lprcat("\nThere's nothing on it to read");  return;
  774.                 }
  775.             }
  776.         }
  777.     }
  778.  
  779. /*
  780.  *    subroutine to eat a cookie one is carrying
  781.  */
  782. eatcookie()
  783. {
  784. register int i;
  785. char *p;
  786. while (1)
  787.     {
  788.     if ((i = whatitem("eat"))=='\33')  return;
  789.     if (i != '.')
  790.         if (i=='*') showeat(); else
  791.             {
  792.             if (iven[i-'a']==OCOOKIE)
  793.                 {
  794.                 lprcat("\nThe cookie was delicious.");
  795.                 iven[i-'a']=0;
  796.                 if (!c[BLINDCOUNT])
  797.                     {
  798.                     if (p=fortune(fortfile))
  799.                         {
  800.                         lprcat("  Inside you find a scrap of paper that says:\n");
  801.                         lprcat(p);
  802.                         }
  803.                     }
  804.                 return;
  805.                 }
  806.             if (iven[i-'a']==0) { ydhi(i); return; }
  807.             lprcat("\nYou can't eat that!");  return;
  808.             }
  809.     }
  810. }
  811.  
  812. /*
  813.  *    subroutine to quaff a potion one is carrying
  814.  */
  815. quaff()
  816.     {
  817.     register int i;
  818.     while (1)
  819.         {
  820.         if ((i = whatitem("quaff"))=='\33')  return;
  821.         if (i != '.')
  822.             {
  823.             if (i=='*') showquaff(); else
  824.                 {
  825.                 if (iven[i-'a']==OPOTION) { quaffpotion(ivenarg[i-'a']); iven[i-'a']=0; return; }
  826.                 if (iven[i-'a']==0) { ydhi(i); return; }
  827.                 lprcat("\nYou wouldn't want to quaff that, would you? ");  return;
  828.                 }
  829.             }
  830.         }
  831.     }
  832.  
  833. /*
  834.     function to ask what player wants to do
  835.  */
  836. whatitem(str)
  837.     char *str;
  838.     {
  839.     int i;
  840.     cursors();  lprintf("\nWhat do you want to %s [* for all] ? ",str);
  841.     i=0; while (i>'z' || (i<'a' && i!='*' && i!='\33' && i!='.')) i=getchar();
  842.     if (i=='\33')  lprcat(" aborted");
  843.     return(i);
  844.     }
  845.  
  846. /*
  847.     subroutine to get a number from the player
  848.     and allow * to mean return amt, else return the number entered
  849.  */
  850. unsigned long readnum(mx)
  851.     long mx;
  852.     {
  853.     register int i;
  854.     register unsigned long amt=0;
  855.     sncbr();
  856.     if ((i=getchar()) == '*')  amt = mx;   /* allow him to say * for all gold */
  857.     else
  858.         while (i != '\n')
  859.             {
  860.             if (i=='\033') { scbr(); lprcat(" aborted"); return(0); }
  861.             if ((i <= '9') && (i >= '0') && (amt<99999999))
  862.                 amt = amt*10+i-'0';
  863.             i = getchar();
  864.             }
  865.     scbr();  return(amt);
  866.     }
  867.  
  868. #ifdef HIDEBYLINK
  869. /*
  870.  *    routine to zero every byte in a string
  871.  */
  872. szero(str)
  873.     register char *str;
  874.     {
  875.     while (*str)
  876.         *str++ = 0;
  877.     }
  878. #endif HIDEBYLINK
  879.