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