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