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