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