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