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