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