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