home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Games / larn12s.arc / LARN.ARC / MAIN.C < prev    next >
C/C++ Source or Header  |  1987-10-28  |  30KB  |  1,123 lines

  1. /*    main.c        */
  2. #include "header.h"
  3. #ifdef UNIX
  4. # include <pwd.h>
  5. #endif
  6. #ifdef GEMDOS
  7. long    _stksize = 65536;
  8. #endif
  9. static char copyright[]="\nLarn is copyrighted 1986 by Noah Morgan.\n";
  10. int srcount=0;    /* line counter for showstr()    */
  11. int dropflag=0; /* if 1 then don't lookforobject() next round */
  12. int rmst=80;    /*    random monster creation counter        */
  13. int userid;        /* the players login user id number */
  14. char nowelcome=0,nomove=0; /* if (nomove) then don't count next iteration as a move */
  15. static char viewflag=0;
  16.     /*    if viewflag then we have done a 99 stay here and don't showcell in the main loop */
  17. char restorflag=0;    /* 1 means restore has been done    */
  18.  
  19. # ifndef UNIX
  20.  
  21. static char cmdhelp[] = "\
  22. Cmd line format: larn [-slicnh] [-o<optsfile>] [-##] [++]\n\
  23.   -s   show the scoreboard\n\
  24.   -l   show the logfile (wizard id only)\n\
  25.   -i   show scoreboard with inventories of dead characters\n\
  26.   -c   create new scoreboard (wizard id only)\n\
  27.   -n   suppress welcome message on starting game\n\
  28.   -##  specify level of difficulty (example: -5)\n\
  29.   -h   print this help text\n\
  30.   ++   restore game from checkpoint file\n\
  31.   -o<optsfile>   specify larnopts filename to be used instead of \"larn.opt\"\n\
  32. ";
  33.  
  34. # else
  35.  
  36. static char cmdhelp[] = "\
  37. Cmd line format: larn [-slicnh] [-o<optsfile>] [-##] [++]\n\
  38.   -s   show the scoreboard\n\
  39.   -l   show the logfile (wizard id only)\n\
  40.   -i   show scoreboard with inventories of dead characters\n\
  41.   -c   create new scoreboard (wizard id only)\n\
  42.   -n   suppress welcome message on starting game\n\
  43.   -##  specify level of difficulty (example: -5)\n\
  44.   -h   print this help text\n\
  45.   ++   restore game from checkpoint file\n\
  46.   -o<optsfile>   specify .larnopts filename to be used instead of \"~/.larnopts\"\n\
  47. ";
  48.  
  49. # endif
  50.  
  51. # ifdef DGK
  52. int    save_mode = 0;        /* 1 if doing a save game */
  53. jmp_buf    save_jbuf;        /* To recover from disk full errors */
  54. # endif
  55.  
  56. #ifdef VT100
  57. static char *termtypes[] = { "vt100", "vt101", "vt102", "vt103", "vt125",
  58.     "vt131", "vt140", "vt180", "vt220", "vt240", "vt241", "vt320", "vt340",
  59.     "vt341"  };
  60. #endif
  61. /*
  62.     ************
  63.     MAIN PROGRAM
  64.     ************
  65.  */
  66. main(argc,argv)
  67.     int argc;
  68.     char **argv;
  69.     {
  70.     register int i;
  71. #ifdef VT100
  72.     register int j;
  73.     char *ttype;
  74. #endif
  75.     int hard = -1;
  76.     char *ptr=0;
  77. #ifdef UNIX
  78.     struct passwd *pwe,*getpwuid();
  79. #endif
  80.  
  81. /*
  82.  *    first task is to identify the player
  83.  */
  84. #ifndef VT100
  85.     init_term();    /* setup the terminal (find out what type) for termcap */
  86. #endif
  87. #ifndef UNIX
  88.     ptr = "PLAYER";
  89. #else
  90.     if (((ptr = getlogin()) == 0) || (*ptr==0))    /* try to get login name */
  91.       if (pwe=getpwuid(getuid())) /* can we get it from /etc/passwd? */
  92.         ptr = pwe->pw_name;
  93.       else
  94.       if ((ptr = getenv("USER")) == 0)
  95.         if ((ptr = getenv("LOGNAME")) == 0)
  96.           {
  97.           noone: write(2, "Can't find your logname.  Who Are You?\n",39);
  98.                   exit();
  99.           }
  100.     if (ptr==0) goto noone;
  101.     if (strlen(ptr)==0) goto noone;
  102. #endif
  103. /*
  104.  *    second task is to prepare the pathnames the player will need
  105.  */
  106.     strcpy(loginname,ptr); /* save loginname of the user for logging purposes */
  107.     strcpy(logname,ptr);    /* this will be overwritten with the players name */
  108.  
  109. /* Set up the input and output buffers.
  110.  */
  111.     lpbuf    = malloc((5* BUFBIG)>>2);    /* output buffer */
  112.     inbuffer = malloc((5*MAXIBUF)>>2);    /* output buffer */
  113.     if ((lpbuf==0) || (inbuffer==0)) died(-285); /* malloc() failure */
  114.  
  115. # ifdef DGK
  116.     /* LARNHOME now comes from the options file, so it must be read in
  117.      * before constructing the other file names.  Unfortunately we have
  118.      * to look for the -o option now.
  119.      */
  120.     strcpy(optsfile, LARNOPTS);
  121.     for (i = 1; i < argc; i++)
  122.         if (strncmp(argv[i], "-o", 2) == 0) {
  123.             argv[i][0] = 0;            /* remove this argv */
  124.             if (argv[i][2] != '\0')
  125.                 strncpy(optsfile, &argv[i][2], PATHLEN);
  126.             else {
  127.                 strncpy(optsfile, argv[i + 1], PATHLEN);
  128.                 argv[i + 1][0] = 0;    /* and this argv */
  129.             }
  130.             optsfile[PATHLEN - 1] = 0;
  131.             break;
  132.         }
  133.     readopts();
  134.     append_slash(larndir);
  135.  
  136.     /* Savefile and swapfile can be given explicitly as options
  137.      */
  138.     if (!savefilename[0]) {
  139.         strcpy(savefilename, larndir);
  140.         strcat(savefilename, SAVEFILE);
  141.     }
  142.     if (!swapfile[0]) {
  143.         strcpy(swapfile, larndir);
  144.         strcat(swapfile, SWAPFILE);
  145.     }
  146.     strcpy(scorefile, larndir);
  147.     strcpy(logfile, larndir);
  148.     strcpy(helpfile, larndir);
  149.     strcpy(larnlevels, larndir);
  150.     strcpy(fortfile, larndir);
  151.     strcpy(playerids, larndir);
  152.     strcpy(ckpfile, larndir);
  153.  
  154. # else /* DGK */
  155.  
  156.     if ((ptr = getenv("HOME")) == 0) ptr = ".";
  157. #ifdef SAVEINHOME
  158.     /* save file name in home directory */
  159.     sprintf(savefilename, "%s/%s",ptr, SAVEFILE);
  160. #else
  161.     strcat(savefilename,logname);    /* prepare savefile name */
  162.     strcat(savefilename,".sav");    /* prepare savefile name */
  163. #endif
  164.     sprintf(optsfile, "%s/%s",ptr, LARNOPTS);    /* the options filename */
  165.  
  166. # endif /* DGK */
  167.  
  168.     strcat(scorefile, SCORENAME);    /* the larn scoreboard filename */
  169.     strcat(logfile, LOGFNAME);        /* larn activity logging filename */
  170.     strcat(helpfile, HELPNAME);        /* the larn on-line help file */
  171.     strcat(larnlevels, LEVELSNAME);    /* the pre-made cave level data file */
  172.     strcat(fortfile, FORTSNAME);    /* the fortune data file name */
  173.     strcat(playerids, PLAYERIDS);    /* the playerid data file name */
  174.     strcat(ckpfile, CKPFILE);
  175.  
  176. # ifdef TIMECHECK
  177.     strcat(holifile, HOLIFILE);        /* the holiday data file name */
  178. # endif
  179.  
  180. #ifdef VT100
  181. /*
  182.  *    check terminal type to avoid users who have not vt100 type terminals
  183.  */
  184.     ttype = getenv("TERM");
  185.     for (j=1, i=0; i<sizeof(termtypes)/sizeof(char *); i++)
  186.         if (strcmp(ttype,termtypes[i]) == 0) { j=0;  break; }
  187.     if (j)
  188.         {
  189.         lprcat("Sorry, Larn needs a VT100 family terminal for all it's features.\n"); lflush();
  190.         exit();
  191.         }
  192. #endif
  193.  
  194. /*
  195.  *    now make scoreboard if it is not there (don't clear) 
  196.  */
  197.     if (access(scorefile,0) == -1) /* not there */
  198.         makeboard();
  199.  
  200. /*
  201.  *    now process the command line arguments 
  202.  */
  203.     for (i=1; i<argc; i++)
  204.         {
  205.         if (argv[i][0] == '-')
  206.           switch(argv[i][1])
  207.             {
  208.             case 's': showscores();  exit();  /* show scoreboard   */
  209.  
  210.             case 'l': /* show log file     */
  211.                         diedlog();        exit();
  212.  
  213.             case 'i': showallscores();  exit();  /* show all scoreboard */
  214.  
  215.             case 'c':          /* anyone with password can create scoreboard */
  216.                       lprcat("Preparing to initialize the scoreboard.\n");
  217.                       if (getpassword() != 0)  /*make new scoreboard*/
  218.                             {
  219.                             makeboard(); lprc('\n'); showscores();
  220.                             }
  221.                       exit();
  222.  
  223.             case 'n':    /* no welcome msg    */ nowelcome=1; argv[i][0]=0; break;
  224.  
  225.             case '0': case '1': case '2': case '3': case '4': case '5':
  226.             case '6': case '7': case '8': case '9':    /* for hardness */
  227.                 hard = atoi(&argv[i][1]);
  228.                 break;
  229.  
  230.             case 'h':    /* print out command line arguments */
  231.                 printf("%s",cmdhelp);  exit();
  232.  
  233.             case 'o':    /* specify a .larnopts filename */
  234.                         strncpy(optsfile,argv[i]+2,127);  break;
  235.             default:    printf("Unknown option <%s>\n",argv[i]);  exit();
  236.             };
  237.  
  238.         if (strcmp(argv[i], "++") == 0)
  239.             restorflag = 1;
  240.     }
  241.  
  242. # ifndef DGK
  243.     readopts();        /* read the options file if there is one */
  244. # endif
  245.  
  246. #ifdef TIMECHECK
  247. /*
  248.  *    this section of code checks to see if larn is allowed during working hours
  249.  */
  250.     if (dayplay==0)    /* check for not-during-daytime-hours */
  251.       if (playable())
  252.         {
  253.         write(2,"Sorry, Larn can not be played during working hours.\n",52);
  254.         exit();
  255.         }
  256. #endif TIMECHECK
  257.  
  258. #ifdef UIDSCORE
  259.     userid = geteuid();    /* obtain the user's effective id number */
  260. #else UIDSCORE
  261.     userid = getplid(logname);    /* obtain the players id number */
  262. #endif UIDSCORE
  263.     if (userid < 0) { write(2,"Can't obtain playerid\n",22); exit(); }
  264.  
  265. #ifdef HIDEBYLINK
  266. /*
  267.  *    this section of code causes the program to look like something else to ps
  268.  */
  269.     if (strcmp(psname,argv[0])) /* if a different process name only */
  270.         {
  271.         if ((i=access(psname,1)) < 0)
  272.             {        /* link not there */
  273.             if (link(argv[0],psname)>=0)
  274.                 {
  275.                 argv[0] = psname;   execv(psname,argv);
  276.                 }
  277.             }
  278.         else 
  279.             unlink(psname);
  280.         }
  281.  
  282.     for (i=1; i<argc; i++)
  283.         {
  284.         szero(argv[i]);    /* zero the argument to avoid ps snooping */
  285.         }
  286. #endif HIDEBYLINK
  287.  
  288. /*
  289.  *    He really wants to play, so malloc the memory for the dungeon.
  290.  */
  291. # ifndef UNIX
  292.     allocate_memory();
  293. # else
  294.     cell = (struct cel *)malloc(sizeof(struct cel)*(MAXLEVEL+MAXVLEVEL)*MAXX*MAXY);
  295.     if (cell == 0) died(-285);    /* malloc failure */
  296. # endif
  297.     lcreat((char*)0);    newgame();        /*    set the initial clock  */
  298.  
  299.     if (restorflag == 1) {            /* restore checkpoint file */
  300.         clear();
  301.         hitflag = 1;
  302.         restoregame(ckpfile);
  303.     } else if (access(savefilename,0)==0)    /* restore game if need to */
  304.         {
  305.         clear();    restorflag = 1;
  306.         hitflag=1;    restoregame(savefilename);  /* restore last game    */
  307.         }
  308.     sigsetup();        /* trap all needed signals    */
  309.     setupvt100();    /*    setup the terminal special mode                */
  310.     sethard(hard);    /* set up the desired difficulty                */
  311.     if (c[HP]==0)    /* create new game */
  312.         {
  313.         makeplayer();    /*    make the character that will play            */
  314.         newcavelevel(0);/*    make the dungeon                             */
  315.         predostuff = 1;    /* tell signals that we are in the welcome screen */
  316.         if (nowelcome==0) welcome();     /* welcome the player to the game */
  317. # ifdef DGK
  318.         /* Display their mail if they've just won the previous game
  319.          */
  320.         checkmail();
  321. # endif
  322.         }
  323.     lprc(T_INIT);    /* Reinit the screen because of welcome and check mail
  324.              * having embedded escape sequences.*/
  325.     drawscreen();    /*    show the initial dungeon                    */
  326.     predostuff = 2;    /* tell the trap functions that they must do a showplayer()
  327.                 from here on */
  328. #ifdef UNIX
  329.     nice(1);    /* games should be run niced */
  330. #endif
  331.     yrepcount = hit2flag = 0;
  332.     while (1)
  333.         {
  334.         if (dropflag==0) lookforobject(); /* see if there is an object here    */
  335.             else dropflag=0; /* don't show it just dropped an item */
  336.         if (hitflag==0) { if (c[HASTEMONST]) movemonst(); movemonst(); }    /*    move the monsters        */
  337.         if (viewflag==0) showcell(playerx,playery); else viewflag=0;    /*    show stuff around player    */
  338.         if (hit3flag) flushall();
  339.         hitflag=hit3flag=0;    nomove=1;
  340.         bot_linex();    /* update bottom line */
  341.         while (nomove)
  342.             {
  343.             if (hit3flag) flushall();
  344.             nomove=0; parse();
  345.             }    /*    get commands and make moves    */
  346.         regen();            /*    regenerate hp and spells            */
  347.         if (c[TIMESTOP]==0)
  348.             if (--rmst <= 0)
  349.                 { rmst = 120-(level<<2); fillmonst(makemonst(level)); }
  350.         }
  351.     }
  352.  
  353. /*
  354.     showstr()
  355.  
  356.     show character's inventory
  357.  */
  358. showstr()
  359.     {
  360.     register int i,number;
  361.     for (number=3, i=0; i<26; i++)
  362.         if (iven[i]) number++;    /* count items in inventory */
  363.     t_setup(number);    qshowstr();      t_endup(number);
  364.     }
  365.  
  366. qshowstr()
  367.     {
  368.     register int i,j,k,sigsav;
  369.     srcount=0;  sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
  370.     if (c[GOLD]) { lprintf(".)   %d gold pieces",(long)c[GOLD]); srcount++; }
  371.     for (k=25; k>=0; k--)    /* bug fix - dgk */
  372. /*    for (k=26; k>=0; k--)             */
  373.       if (iven[k])
  374.         {  for (i=22; i<84; i++)
  375.              for (j=0; j<=k; j++)  if (i==iven[j])  show3(j); k=0; }
  376.  
  377.     lprintf("\nElapsed time is %d.  You have %d mobuls left",(long)((gtime+99)/100+1),(long)((TIMELIMIT-gtime)/100));
  378.     more();        nosignal=sigsav;
  379.     }
  380.  
  381. /*
  382.  *    subroutine to clear screen depending on # lines to display
  383.  */
  384. t_setup(count)
  385.     register int count;
  386.     {
  387.     if (count<20)  /* how do we clear the screen? */
  388.         {
  389.         cl_up(79,count);  cursor(1,1);
  390.         }
  391.     else
  392.         {
  393.         resetscroll(); clear();
  394.         }
  395.     }
  396.  
  397. /*
  398.  *    subroutine to restore normal display screen depending on t_setup()
  399.  */
  400. t_endup(count)
  401.     register int count;
  402.     {
  403.     if (count<18)  /* how did we clear the screen? */
  404.         draws(0,MAXX,0,(count>MAXY) ? MAXY : count);
  405.     else
  406.         {
  407.         drawscreen(); setscroll();
  408.         }
  409.     }
  410.  
  411. /*
  412.     function to show the things player is wearing only
  413.  */
  414. showwear()
  415.     {
  416.     register int i,j,sigsav,count;
  417.     sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
  418.     srcount=0;
  419.  
  420.      for (count=2,j=0; j<=26; j++)     /* count number of items we will display */
  421.        if (i=iven[j])
  422.         switch(i)
  423.             {
  424.             case OLEATHER:    case OPLATE:    case OCHAIN:
  425.             case ORING:        case OSTUDLEATHER:    case OSPLINT:
  426.             case OPLATEARMOR:    case OSSPLATE:    case OSHIELD:
  427.             count++;
  428.             };
  429.  
  430.     t_setup(count);
  431.  
  432.     for (i=22; i<84; i++)
  433.          for (j=0; j<=26; j++)
  434.            if (i==iven[j])
  435.             switch(i)
  436.                 {
  437.                 case OLEATHER:    case OPLATE:    case OCHAIN:
  438.                 case ORING:        case OSTUDLEATHER:    case OSPLINT:
  439.                 case OPLATEARMOR:    case OSSPLATE:    case OSHIELD:
  440.                 show3(j);
  441.                 };
  442.     more();        nosignal=sigsav;    t_endup(count);
  443.     }
  444.  
  445. /*
  446.     function to show the things player can wield only 
  447.  */
  448. showwield()
  449.     {
  450.     register int i,j,sigsav,count;
  451.     sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
  452.     srcount=0;
  453.  
  454.      for (count=2,j=0; j<=26; j++)    /* count how many items */
  455.        if (i=iven[j])
  456.         switch(i)
  457.             {
  458.             case ODIAMOND:  case ORUBY:  case OEMERALD:  case OSAPPHIRE:
  459.             case OBOOK:     case OCHEST:  case OLARNEYE: case ONOTHEFT:
  460.             case OSPIRITSCARAB:  case OCUBEofUNDEAD:
  461.             case OPOTION:   case OSCROLL:  break;
  462.             default:  count++;
  463.             };
  464.  
  465.     t_setup(count);
  466.  
  467.     for (i=22; i<84; i++)
  468.          for (j=0; j<=26; j++)
  469.            if (i==iven[j])
  470.             switch(i)
  471.                 {
  472.                 case ODIAMOND:  case ORUBY:  case OEMERALD:  case OSAPPHIRE:
  473.                 case OBOOK:     case OCHEST:  case OLARNEYE: case ONOTHEFT:
  474.                 case OSPIRITSCARAB:  case OCUBEofUNDEAD:
  475.                 case OPOTION:   case OSCROLL:  break;
  476.                 default:  show3(j);
  477.                 };
  478.     more();        nosignal=sigsav;    t_endup(count);
  479.     }
  480.  
  481. /*
  482.  *    function to show the things player can read only
  483.  */
  484. showread()
  485.     {
  486.     register int i,j,sigsav,count;
  487.     sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
  488.     srcount=0;
  489.  
  490.     for (count=2,j=0; j<=26; j++)
  491.         switch(iven[j])
  492.             {
  493.             case OBOOK:    case OSCROLL:    count++;
  494.             };
  495.     t_setup(count);
  496.  
  497.     for (i=22; i<84; i++)
  498.          for (j=0; j<=26; j++)
  499.            if (i==iven[j])
  500.             switch(i)
  501.                 {
  502.                 case OBOOK:    case OSCROLL:    show3(j);
  503.                 };
  504.     more();        nosignal=sigsav;    t_endup(count);
  505.     }
  506.  
  507. /*
  508.  *    function to show the things player can eat only
  509.  */
  510. showeat()
  511.     {
  512.     register int i,j,sigsav,count;
  513.     sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
  514.     srcount=0;
  515.  
  516.     for (count=2,j=0; j<=26; j++)
  517.         switch(iven[j])
  518.             {
  519.             case OCOOKIE:    count++;
  520.             };
  521.     t_setup(count);
  522.  
  523.     for (i=22; i<84; i++)
  524.          for (j=0; j<=26; j++)
  525.            if (i==iven[j])
  526.             switch(i)
  527.                 {
  528.                 case OCOOKIE:    show3(j);
  529.                 };
  530.     more();        nosignal=sigsav;    t_endup(count);
  531.     }
  532.  
  533. /*
  534.     function to show the things player can quaff only
  535.  */
  536. showquaff()
  537.     {
  538.     register int i,j,sigsav,count;
  539.     sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
  540.     srcount=0;
  541.  
  542.     for (count=2,j=0; j<=26; j++)
  543.         switch(iven[j])
  544.             {
  545.             case OPOTION:    count++;
  546.             };
  547.     t_setup(count);
  548.  
  549.     for (i=22; i<84; i++)
  550.          for (j=0; j<=26; j++)
  551.            if (i==iven[j])
  552.             switch(i)
  553.                 {
  554.                 case OPOTION:    show3(j);
  555.                 };
  556.     more();        nosignal=sigsav;        t_endup(count);
  557.     }
  558.  
  559. show1(idx,str2)
  560.     register int idx;
  561.     register char *str2[];
  562.     {
  563.         lprc('\n');
  564.         cltoeoln();
  565.     if (str2==0)
  566.         lprintf("%c)   %s",idx+'a',objectname[iven[idx]]);
  567.     else if (*str2[ivenarg[idx]]==0)
  568.         lprintf("%c)   %s",idx+'a',objectname[iven[idx]]);
  569.     else
  570.         lprintf("%c)   %s of%s",idx+'a',objectname[iven[idx]],str2[ivenarg[idx]]);
  571.     }
  572.  
  573. show3(index)
  574.     register int index;
  575.     {
  576.     switch(iven[index]) 
  577.         {
  578.         case OPOTION:    show1(index,potionname);  break;
  579.         case OSCROLL:    show1(index,scrollname);  break;
  580.  
  581.         case OLARNEYE:        case OBOOK:            case OSPIRITSCARAB:
  582.         case ODIAMOND:        case ORUBY:            case OCUBEofUNDEAD:
  583.         case OEMERALD:        case OCHEST:        case OCOOKIE:
  584.         case OSAPPHIRE:        case ONOTHEFT:        show1(index,(char **)0);  break;
  585.  
  586.         default:
  587.         lprc('\n');
  588.         cltoeoln();
  589.         lprintf("%c)   %s",index+'a',objectname[iven[index]]);
  590.         if (ivenarg[index]>0)
  591.             lprintf(" + %d",(long)ivenarg[index]);
  592.         else if (ivenarg[index]<0)
  593.             lprintf(" %d",(long)ivenarg[index]);
  594.         break;
  595.         }
  596.     if (c[WIELD]==index) lprcat(" (weapon in hand)");
  597.     if ((c[WEAR]==index) || (c[SHIELD]==index))  lprcat(" (being worn)");
  598.     if (++srcount>=22) { srcount=0; more(); clear(); }
  599.     }
  600.  
  601. /*
  602.     subroutine to randomly create monsters if needed
  603.  */
  604. randmonst()
  605.     {
  606.     if (c[TIMESTOP]) return;    /*    don't make monsters if time is stopped    */
  607.     if (--rmst <= 0)
  608.         {
  609.         rmst = 120 - (level<<2);  fillmonst(makemonst(level));
  610.         }
  611.     }
  612.  
  613.  
  614. /*
  615.     parse()
  616.  
  617.     get and execute a command
  618.  */
  619. parse()
  620.     {
  621.     register int i,j,k,flag;
  622.  
  623.     while    (1)
  624.         {
  625.         k = yylex();
  626.         switch(k)    /*    get the token from the input and switch on it    */
  627.             {
  628.             case 'h':    moveplayer(4);    return;        /*    west        */
  629.             case 'H':    run(4);            return;        /*    west        */
  630.             case 'l':    moveplayer(2);    return;        /*    east        */
  631.             case 'L':    run(2);            return;        /*    east        */
  632.             case 'j':    moveplayer(1);    return;        /*    south        */
  633.             case 'J':    run(1);            return;        /*    south        */
  634.             case 'k':    moveplayer(3);    return;        /*    north        */
  635.             case 'K':    run(3);            return;        /*    north        */
  636.             case 'u':    moveplayer(5);    return;        /*    northeast    */
  637.             case 'U':    run(5);            return;        /*    northeast    */
  638.             case 'y':    moveplayer(6);  return;        /*    northwest    */
  639.             case 'Y':    run(6);            return;        /*    northwest    */
  640.             case 'n':    moveplayer(7);    return;        /*    southeast    */
  641.             case 'N':    run(7);            return;        /*    southeast    */
  642.             case 'b':    moveplayer(8);    return;        /*    southwest    */
  643.             case 'B':    run(8);            return;        /*    southwest    */
  644.  
  645.             case '.':    if (yrepcount) viewflag=1; return;        /*    stay here        */
  646.  
  647.             case 'w':    yrepcount=0;    wield();    return;        /*    wield a weapon */
  648.  
  649.             case 'W':    yrepcount=0;    wear();        return;    /*    wear armor    */
  650.  
  651.             case 'r':    yrepcount=0;
  652.                         if (c[BLINDCOUNT]) { cursors(); lprcat("\nYou can't read anything when you're blind!"); } else
  653.                         if (c[TIMESTOP]==0) readscr(); return;        /*    to read a scroll    */
  654.  
  655.             case 'q':    yrepcount=0;    if (c[TIMESTOP]==0) quaff();    return;    /*    quaff a potion        */
  656.  
  657.             case 'd':    yrepcount=0;    if (c[TIMESTOP]==0) dropobj(); return;    /*    to drop an object    */
  658.  
  659.             case 'c':    yrepcount=0;    cast();        return;        /*    cast a spell    */
  660.  
  661.             case 'i':    yrepcount=0;    nomove=1;  showstr();    return;        /*    status        */
  662.  
  663.             case 'e':    yrepcount=0;
  664.                         if (c[TIMESTOP]==0) eatcookie(); return;    /*    to eat a fortune cookie */
  665.  
  666.             case 'D':    yrepcount=0;    seemagic(0);    nomove=1; return;    /*    list spells and scrolls */
  667.  
  668.             case '?':    yrepcount=0;    help(); nomove=1; return;    /*    give the help screen*/
  669.  
  670. # ifdef DGK
  671.             case 'S':
  672.                 /* Set up error recovery
  673.                  */
  674.                 if (setjmp(save_jbuf) != 0) {
  675.  
  676.                     /* can't use lwclose!
  677.                      */
  678.                     if (lfd > 2)
  679.                         close(lfd);
  680.                     lcreat(NULL);
  681.                     setscroll();
  682.                     cursors();
  683.                     lprcat("\nSave failed !\n");
  684. #ifdef ENOSPC
  685.                     if (errno == ENOSPC)
  686.                         lprcat("Disk is full !\n");
  687. #endif
  688.                     beep();
  689.                     (void) unlink(savefilename);
  690.                     save_mode = 0;
  691.                     yrepcount = 0;
  692.                     nomove = 1;
  693.                     break;
  694.                 }
  695.  
  696.                 /* And do the save.
  697.                  */
  698.                 cursors();
  699.                 lprintf("\nSaving to `%s' . . . ", savefilename);
  700.                 lflush();
  701.                 save_mode = 1;
  702.                 savegame(savefilename);
  703.                 clear();
  704.                 lflush();
  705.                 wizard=1;
  706.                 died(-257);    /* doesn't return */
  707.                 break;
  708. # else
  709.             case 'S':    clear();  lprcat("Saving . . ."); lflush();  
  710.                         savegame(savefilename); wizard=1; died(-257);    /*    save the game - doesn't return    */
  711. # endif
  712.  
  713.             case 'Z':    yrepcount=0;    if (c[LEVEL]>9) { oteleport(1); return; }
  714.                         cursors(); lprcat("\nAs yet, you don't have enough experience to use teleportation");
  715.                         return;    /*    teleport yourself    */
  716.  
  717.             case '^':    /* identify traps */  flag=yrepcount=0;  cursors();
  718.                         lprc('\n');  for (j=playery-1; j<playery+2; j++)
  719.                             {
  720.                             if (j < 0) j=0;        if (j >= MAXY) break;
  721.                             for (i=playerx-1; i<playerx+2; i++)
  722.                                 {
  723.                                 if (i < 0) i=0;    if (i >= MAXX) break;
  724.                                 switch(item[i][j])
  725.                                     {
  726.                                     case OTRAPDOOR:        case ODARTRAP:
  727.                                     case OTRAPARROW:    case OTELEPORTER:
  728.                                         lprcat("\nIts "); lprcat(objectname[item[i][j]]);  flag++;
  729.                                     };
  730.                                 }
  731.                             }
  732.                         if (flag==0) lprcat("\nNo traps are visible");
  733.                         return;
  734.  
  735. #if WIZID
  736.             case '_':    /*    this is the fudge player password for wizard mode*/
  737.                         yrepcount=0;    cursors(); nomove=1;
  738. # ifdef UNIX
  739.                         if (userid!=wisid)
  740.                             {
  741.                             lprcat("Sorry, you are not empowered to be a wizard.\n");
  742.                             scbr(); /* system("stty -echo cbreak"); */
  743.                             lflush();  return;
  744.                             }
  745. # endif
  746.                         if (getpassword()==0)
  747.                             {
  748.                             scbr(); /* system("stty -echo cbreak"); */ return;
  749.                             }
  750.                         wizard=1;  scbr(); /* system("stty -echo cbreak"); */
  751.                         for (i=0; i<6; i++)  c[i]=70;  iven[0]=iven[1]=0;
  752.                         take(OPROTRING,50);   take(OLANCE,25);  c[WIELD]=1;
  753.                         c[LANCEDEATH]=1;   c[WEAR] = c[SHIELD] = -1;
  754.                         raiseexperience(6000000L);  c[AWARENESS] += 25000;
  755.                         {
  756.                         register int i,j;
  757.                         for (i=0; i<MAXY; i++)
  758. # ifdef DGK
  759.                             for (j=0; j<MAXX; j++)  know[j][i]=KNOWALL;
  760. # else
  761.                             for (j=0; j<MAXX; j++)  know[j][i]=1;
  762. # endif
  763.                         for (i=0; i<SPNUM; i++)    spelknow[i]=1;
  764.                         for (i=0; i<MAXSCROLL; i++)  scrollname[i][0]=' ';
  765.                         for (i=0; i<MAXPOTION; i++)  potionname[i][0]=' ';
  766.                         }
  767.                         for (i=0; i<MAXSCROLL; i++)
  768.                           if (strlen(scrollname[i])>2) /* no null items */
  769.                             { item[i][0]=OSCROLL; iarg[i][0]=i; }
  770.                         for (i=MAXX-1; i>MAXX-1-MAXPOTION; i--)
  771.                           if (strlen(potionname[i-MAXX+MAXPOTION])>2) /* no null items */
  772.                             { item[i][0]=OPOTION; iarg[i][0]=i-MAXX+MAXPOTION; }
  773.                         for (i=1; i<MAXY; i++)
  774.                             { item[0][i]=i; iarg[0][i]=0; }
  775.                         for (i=MAXY; i<MAXY+MAXX; i++)
  776.                             { item[i-MAXY][MAXY-1]=i; iarg[i-MAXY][MAXY-1]=0; }
  777.                         for (i=MAXX+MAXY; i<MAXX+MAXY+MAXY; i++)
  778.                             { item[MAXX-1][i-MAXX-MAXY]=i; iarg[MAXX-1][i-MAXX-MAXY]=0; }
  779.                         c[GOLD]+=250000L;    drawscreen();    return;
  780. #endif
  781.  
  782.             case 'T':    yrepcount=0;    cursors();  if (c[SHIELD] != -1) { c[SHIELD] = -1; lprcat("\nYour shield is off"); bottomline(); } else
  783.                                         if (c[WEAR] != -1) { c[WEAR] = -1; lprcat("\nYour armor is off"); bottomline(); }
  784.                         else lprcat("\nYou aren't wearing anything");
  785.                         return;
  786.  
  787.             case 'g':    cursors();
  788.                         lprintf("\nThe stuff you are carrying presently weighs %d pounds",(long)packweight());
  789.             case ' ':    yrepcount=0;    nomove=1;  return;
  790.  
  791.             case 'v':    yrepcount=0;    cursors();
  792.                         lprintf("\nCaverns of Larn, Version %d.%d, Diff=%d",(long)VERSION,(long)SUBVERSION,(long)c[HARDGAME]);
  793.                         if (wizard) lprcat(" Wizard"); nomove=1;
  794.                         if (cheat) lprcat(" Cheater");
  795.                         lprcat(copyright);
  796.                         return;
  797. # ifdef DGK
  798.             case 'V':
  799.                 yrepcount = 0;
  800.                 nomove = 1;
  801.                 cursors();
  802. #ifdef MSDOS
  803.                 lprcat("\nMSDOS version 12b by Don Kneller, Berkeley CA.\n");
  804. #endif
  805. #ifdef GEMDOS
  806.                 lprcat("\nATARI ST version 12 by Howard Chu, Ann Arbor MI.\n");
  807. #endif
  808.                 return;
  809.             case 'D'-64:
  810.                 yrepcount = 0;
  811.                 nomove = 1;
  812.                 levelinfo();
  813.                 return;
  814. # endif
  815.  
  816.             case 'Q':    yrepcount=0;    quit(); nomove=1;    return;    /*    quit        */
  817.  
  818.             case 'L'-64:  yrepcount=0;    drawscreen();  nomove=1; return;    /*    look        */
  819.  
  820. #if WIZID
  821. #ifdef EXTRA
  822.             case 'A':    yrepcount=0;    nomove=1; if (wizard) { diag(); return; }  /*    create diagnostic file */
  823.                         return;
  824. #endif
  825. #endif
  826.             case 'P':    cursors(); 
  827.                         if (outstanding_taxes>0)
  828.                             lprintf("\nYou presently owe %d gp in taxes.",(long)outstanding_taxes);
  829.                         else
  830.                             lprcat("\nYou do not owe any taxes.");
  831.                         return;
  832.             };
  833.         }
  834.     }
  835.  
  836. parse2()
  837.     {
  838.     if (c[HASTEMONST]) movemonst(); movemonst(); /*    move the monsters        */
  839.     randmonst();    regen();
  840.     }
  841.  
  842. run(dir)
  843.     int dir;
  844.     {
  845.     register int i;
  846.     i=1; while (i)
  847.         {
  848.         i=moveplayer(dir);
  849.         if (i>0) {  if (c[HASTEMONST]) movemonst();  movemonst(); randmonst(); regen(); }
  850.         if (hitflag) i=0;
  851.         if (i!=0)  showcell(playerx,playery);
  852.         }
  853.     }
  854.  
  855. /*
  856.     function to wield a weapon
  857.  */
  858. wield()    
  859.     {
  860.     register int i;
  861.     while (1)
  862.         {
  863.         if ((i = whatitem("wield"))=='\33')  return;
  864.         if (i != '.')
  865.             {
  866.             if (i=='*') showwield();
  867.             else  if (iven[i-'a']==0) { ydhi(i); return; }
  868.             else if (iven[i-'a']==OPOTION) { ycwi(i); return; }
  869.             else if (iven[i-'a']==OSCROLL) { ycwi(i); return; }
  870.             else  if ((c[SHIELD]!= -1) && (iven[i-'a']==O2SWORD)) { lprcat("\nBut one arm is busy with your shield!"); return; }
  871.             else  { c[WIELD]=i-'a'; if (iven[i-'a'] == OLANCE) c[LANCEDEATH]=1; else c[LANCEDEATH]=0;  bottomline(); return; }
  872.             }
  873.         }
  874.     }
  875.  
  876. /*
  877.     common routine to say you don't have an item
  878.  */
  879. ydhi(x)
  880.     int x;
  881.     { cursors();  lprintf("\nYou don't have item %c!",x); }
  882. ycwi(x)
  883.     int x;
  884.     { cursors();  lprintf("\nYou can't wield item %c!",x); }
  885.  
  886. /*
  887.     function to wear armor
  888.  */
  889. wear()
  890.     {
  891.     register int i;
  892.     while (1)
  893.         {
  894.         if ((i = whatitem("wear"))=='\33')  return;
  895.         if (i != '.')
  896.             {
  897.             if (i=='*') showwear(); else
  898.             switch(iven[i-'a'])
  899.                 {
  900.                 case 0:  ydhi(i); return;
  901.                 case OLEATHER:  case OCHAIN:  case OPLATE:    case OSTUDLEATHER:
  902.                 case ORING:        case OSPLINT:    case OPLATEARMOR:    case OSSPLATE:
  903.                         if (c[WEAR] != -1) { lprcat("\nYou're already wearing some armor"); return; }
  904.                             c[WEAR]=i-'a';  bottomline(); return;
  905.                 case OSHIELD:    if (c[SHIELD] != -1) { lprcat("\nYou are already wearing a shield"); return; }
  906.                                 if (iven[c[WIELD]]==O2SWORD) { lprcat("\nYour hands are busy with the two handed sword!"); return; }
  907.                                 c[SHIELD] = i-'a';  bottomline(); return;
  908.                 default:    lprcat("\nYou can't wear that!");
  909.                 };
  910.             }
  911.         }
  912.     }
  913.  
  914. /*
  915.     function to drop an object
  916.  */
  917. dropobj()
  918.     {
  919.     register int i;
  920.     register char *p;
  921.     long amt;
  922.     p = &item[playerx][playery];
  923.     while (1)
  924.         {
  925.         if ((i = whatitem("drop"))=='\33')  return;
  926.         if (i=='*') showstr(); else 
  927.             {
  928.             if (i=='.')    /* drop some gold */
  929.                 {
  930.                 if (*p) { lprcat("\nThere's something here already!"); return; }
  931.                 lprcat("\n\n");
  932.                 cl_dn(1,23);
  933.                 lprcat("How much gold do you drop? ");
  934.                 if ((amt=readnum((long)c[GOLD])) == 0) return;
  935.                 if (amt>c[GOLD])
  936.                     { lprcat("\nYou don't have that much!"); return; }
  937.                 if (amt<=32767)
  938.                     { *p=OGOLDPILE; i=amt; }
  939.                 else if (amt<=327670L)
  940.                     { *p=ODGOLD; i=amt/10; amt = 10L*i; }
  941.                 else if (amt<=3276700L)
  942.                     { *p=OMAXGOLD; i=amt/100; amt = 100L*i; }
  943.                 else if (amt<=32767000L)
  944.                     { *p=OKGOLD; i=amt/1000; amt = 1000L*i; }
  945.                 else
  946.                     { *p=OKGOLD; i=32767; amt = 32767000L; }
  947.                 c[GOLD] -= amt; 
  948.                 lprintf("\nYou drop %d gold pieces",(long)amt);
  949.                 iarg[playerx][playery]=i; bottomgold();
  950.                 know[playerx][playery]=0; dropflag=1;  return;
  951.                 }
  952.             drop_object(i-'a');
  953.             return;
  954.             }
  955.         }
  956.     }
  957.  
  958. /*
  959.  *    readscr()        Subroutine to read a scroll one is carrying
  960.  */
  961. readscr()
  962.     {
  963.     register int i;
  964.     while (1)
  965.         {
  966.         if ((i = whatitem("read"))=='\33')  return;
  967.         if (i != '.')
  968.             {
  969.             if (i=='*') showread(); else
  970.                 {
  971.                 if (iven[i-'a']==OSCROLL) { read_scroll(ivenarg[i-'a']); iven[i-'a']=0; return; }
  972.                 if (iven[i-'a']==OBOOK)   { readbook(ivenarg[i-'a']);  iven[i-'a']=0; return; }
  973.                 if (iven[i-'a']==0) { ydhi(i); return; }
  974.                 lprcat("\nThere's nothing on it to read");  return;
  975.                 }
  976.             }
  977.         }
  978.     }
  979.  
  980. /*
  981.  *    subroutine to eat a cookie one is carrying
  982.  */
  983. eatcookie()
  984. {
  985. register int i;
  986. char *p;
  987. while (1)
  988.     {
  989.     if ((i = whatitem("eat"))=='\33')  return;
  990.     if (i != '.')
  991.         if (i=='*') showeat(); else
  992.             {
  993.             if (iven[i-'a']==OCOOKIE)
  994.                 {
  995.                 lprcat("\nThe cookie was delicious.");
  996.                 iven[i-'a']=0;
  997.                 if (!c[BLINDCOUNT])
  998.                     {
  999. # ifdef MSDOS
  1000.                     outfortune();
  1001. # else
  1002.                     if (p=fortune(fortfile))
  1003.                         {
  1004.                         lprcat("  Inside you find a scrap of paper that says:\n");
  1005.                         lprcat(p);
  1006.                         }
  1007. # endif
  1008.                     }
  1009.                 return;
  1010.                 }
  1011.             if (iven[i-'a']==0) { ydhi(i); return; }
  1012.             lprcat("\nYou can't eat that!");  return;
  1013.             }
  1014.     }
  1015. }
  1016.  
  1017. /*
  1018.  *    subroutine to quaff a potion one is carrying
  1019.  */
  1020. quaff()
  1021.     {
  1022.     register int i;
  1023.     while (1)
  1024.         {
  1025.         if ((i = whatitem("quaff"))=='\33')  return;
  1026.         if (i != '.')
  1027.             {
  1028.             if (i=='*') showquaff(); else
  1029.                 {
  1030.                 if (iven[i-'a']==OPOTION) { quaffpotion(ivenarg[i-'a']); iven[i-'a']=0; return; }
  1031.                 if (iven[i-'a']==0) { ydhi(i); return; }
  1032.                 lprcat("\nYou wouldn't want to quaff that, would you? ");  return;
  1033.                 }
  1034.             }
  1035.         }
  1036.     }
  1037.  
  1038. /*
  1039.     function to ask what player wants to do
  1040.  */
  1041. whatitem(str)
  1042.     char *str;
  1043.     {
  1044.     int i;
  1045.     cursors();  lprintf("\nWhat do you want to %s [* for all] ? ",str);
  1046.     i=0; while (i>'z' || (i<'a' && i!='*' && i!='\33' && i!='.')) i=getchar();
  1047.     if (i=='\33')  lprcat(" aborted");
  1048.     return(i);
  1049.     }
  1050.  
  1051. /*
  1052.     subroutine to get a number from the player
  1053.     and allow * to mean return amt, else return the number entered
  1054.  */
  1055. unsigned long readnum(mx)
  1056.     long mx;
  1057.     {
  1058.     register int i;
  1059.     register unsigned long amt=0;
  1060.     sncbr();
  1061.     if ((i=getchar()) == '*')  amt = mx;   /* allow him to say * for all gold */
  1062.     else
  1063.         while (i != '\n')
  1064.             {
  1065.             if (i=='\033') { scbr(); lprcat(" aborted"); return(0); }
  1066.             if ((i <= '9') && (i >= '0') && amt<(unsigned long) mx)
  1067.                 amt = amt*10+i-'0';
  1068.             i = getchar();
  1069.             }
  1070.     scbr();  return(amt < (unsigned long) mx ? amt : (unsigned long) mx);
  1071.     }
  1072.  
  1073. #ifdef HIDEBYLINK
  1074. /*
  1075.  *    routine to zero every byte in a string
  1076.  */
  1077. szero(str)
  1078.     register char *str;
  1079.     {
  1080.     while (*str)
  1081.         *str++ = 0;
  1082.     }
  1083. #endif HIDEBYLINK
  1084.  
  1085. #ifdef TIMECHECK
  1086. /*
  1087.  *    routine to check the time of day and return 1 if its during work hours
  1088.  *    checks the file ".holidays" for forms like "mmm dd comment..."
  1089.  */
  1090. int playable()
  1091.     {
  1092.     long g_time,time();
  1093.     int hour,day,year;
  1094.     char *date,*month,*p;
  1095.  
  1096.     time(&g_time);    /* get the time and date */
  1097.     date = ctime(&g_time); /* format: Fri Jul  4 00:27:56 EDT 1986 */
  1098.     year = atoi(date+20);
  1099.     hour = (date[11]-'0')*10 + date[12]-'0';
  1100.     day  = (date[8]!=' ') ? ((date[8]-'0')*10 + date[9]-'0') : (date[9]-'0');
  1101.     month = date+4;  date[7]=0;    /* point to and NULL terminate month */
  1102.  
  1103.     if (((hour>=8 && hour<17)) /* 8AM - 5PM */
  1104.         && strncmp("Sat",date,3)!=0     /* not a Saturday */
  1105.         && strncmp("Sun",date,3)!=0)    /* not a Sunday */
  1106.             {
  1107.         /* now check for a .holidays datafile */
  1108.             lflush();
  1109.             if (lopen(holifile) >= 0)
  1110.                 for ( ; ; )
  1111.                     {
  1112.                     if ((p=lgetw())==0) break;
  1113.                     if (strlen(p)<6) continue;
  1114.                     if ((strncmp(p,month,3)==0) && (day==atoi(p+4)) && (year==atoi(p+7)))
  1115.                         return(0); /* a holiday */
  1116.                     }
  1117.             lrclose();  lcreat((char*)0);
  1118.             return(1);
  1119.             }
  1120.     return(0);
  1121.     }
  1122. #endif TIMECHECK
  1123.