]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - larn/main.c
Heads up on Bell patents
[bsdgames-darwin.git] / larn / main.c
1 /* $NetBSD: main.c,v 1.26 2019/02/03 03:19:25 mrg Exp $ */
2
3 /* main.c */
4 #include <sys/cdefs.h>
5 #ifndef lint
6 __RCSID("$NetBSD: main.c,v 1.26 2019/02/03 03:19:25 mrg 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
979 parse2(void)
980 {
981 if (c[HASTEMONST])
982 movemonst();
983 movemonst(); /* move the monsters */
984 randmonst();
985 regen();
986 }
987
988 static void
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
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
1051 ydhi(int x)
1052 {
1053 cursors();
1054 lprintf("\nYou don't have item %c!", x);
1055 }
1056 static void
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
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
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
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
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
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
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
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
1331 szero(str)
1332 char *str;
1333 {
1334 while (*str)
1335 *str++ = 0;
1336 }
1337 #endif /* HIDEBYLINK */