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