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