]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - larn/main.c
Larn now builds with WARNS=4.
[bsdgames-darwin.git] / larn / main.c
1 /* $NetBSD: main.c,v 1.20 2008/01/28 05:38:54 dholland Exp $ */
2
3 /* main.c */
4 #include <sys/cdefs.h>
5 #ifndef lint
6 __RCSID("$NetBSD: main.c,v 1.20 2008/01/28 05:38:54 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 const 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(int indx)
588 {
589 switch (iven[indx]) {
590 case OPOTION:
591 show1(indx, potionname);
592 break;
593 case OSCROLL:
594 show1(indx, 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(indx, NULL);
609 break;
610
611 default:
612 lprintf("\n%c) %s", indx + 'a', objectname[iven[indx]]);
613 if (ivenarg[indx] > 0)
614 lprintf(" + %ld", (long) ivenarg[indx]);
615 else if (ivenarg[indx] < 0)
616 lprintf(" %ld", (long) ivenarg[indx]);
617 break;
618 }
619 if (c[WIELD] == indx)
620 lprcat(" (weapon in hand)");
621 if ((c[WEAR] == indx) || (c[SHIELD] == indx))
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("\nIt's ");
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 %ld 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 %ld.%ld, Diff=%ld",
914 (long) VERSION, (long) SUBVERSION,
915 (long) c[HARDGAME]);
916 if (wizard)
917 lprcat(" Wizard");
918 nomove = 1;
919 if (cheat)
920 lprcat(" Cheater");
921 lprcat(copyright);
922 return;
923
924 case 'Q':
925 yrepcount = 0;
926 quit();
927 nomove = 1;
928 return; /* quit */
929
930 case 'L' - 64:
931 yrepcount = 0;
932 drawscreen();
933 nomove = 1;
934 return; /* look */
935
936 #if WIZID
937 #ifdef EXTRA
938 case 'A':
939 yrepcount = 0;
940 nomove = 1;
941 if (wizard) {
942 diag();
943 return;
944 } /* create diagnostic file */
945 return;
946 #endif
947 #endif
948 case 'P':
949 cursors();
950 if (outstanding_taxes > 0)
951 lprintf("\nYou presently owe %ld gp in taxes.",
952 (long) outstanding_taxes);
953 else
954 lprcat("\nYou do not owe any taxes.");
955 return;
956 };
957 }
958 }
959
960 void
961 parse2()
962 {
963 if (c[HASTEMONST])
964 movemonst();
965 movemonst(); /* move the monsters */
966 randmonst();
967 regen();
968 }
969
970 void
971 run(dir)
972 int dir;
973 {
974 int i;
975 i = 1;
976 while (i) {
977 i = moveplayer(dir);
978 if (i > 0) {
979 if (c[HASTEMONST])
980 movemonst();
981 movemonst();
982 randmonst();
983 regen();
984 }
985 if (hitflag)
986 i = 0;
987 if (i != 0)
988 showcell(playerx, playery);
989 }
990 }
991
992 /*
993 function to wield a weapon
994 */
995 void
996 wield()
997 {
998 int i;
999 while (1) {
1000 if ((i = whatitem("wield")) == '\33')
1001 return;
1002 if (i != '.') {
1003 if (i == '*')
1004 showwield();
1005 else if (iven[i - 'a'] == 0) {
1006 ydhi(i);
1007 return;
1008 } else if (iven[i - 'a'] == OPOTION) {
1009 ycwi(i);
1010 return;
1011 } else if (iven[i - 'a'] == OSCROLL) {
1012 ycwi(i);
1013 return;
1014 } else if ((c[SHIELD] != -1) && (iven[i - 'a'] == O2SWORD)) {
1015 lprcat("\nBut one arm is busy with your shield!");
1016 return;
1017 } else {
1018 c[WIELD] = i - 'a';
1019 if (iven[i - 'a'] == OLANCE)
1020 c[LANCEDEATH] = 1;
1021 else
1022 c[LANCEDEATH] = 0;
1023 bottomline();
1024 return;
1025 }
1026 }
1027 }
1028 }
1029
1030 /*
1031 common routine to say you don't have an item
1032 */
1033 void
1034 ydhi(x)
1035 int x;
1036 {
1037 cursors();
1038 lprintf("\nYou don't have item %c!", x);
1039 }
1040 void
1041 ycwi(x)
1042 int x;
1043 {
1044 cursors();
1045 lprintf("\nYou can't wield item %c!", x);
1046 }
1047
1048 /*
1049 function to wear armor
1050 */
1051 void
1052 wear()
1053 {
1054 int i;
1055 while (1) {
1056 if ((i = whatitem("wear")) == '\33')
1057 return;
1058 if (i != '.') {
1059 if (i == '*')
1060 showwear();
1061 else
1062 switch (iven[i - 'a']) {
1063 case 0:
1064 ydhi(i);
1065 return;
1066 case OLEATHER:
1067 case OCHAIN:
1068 case OPLATE:
1069 case OSTUDLEATHER:
1070 case ORING:
1071 case OSPLINT:
1072 case OPLATEARMOR:
1073 case OSSPLATE:
1074 if (c[WEAR] != -1) {
1075 lprcat("\nYou're already wearing some armor");
1076 return;
1077 }
1078 c[WEAR] = i - 'a';
1079 bottomline();
1080 return;
1081 case OSHIELD:
1082 if (c[SHIELD] != -1) {
1083 lprcat("\nYou are already wearing a shield");
1084 return;
1085 }
1086 if (iven[c[WIELD]] == O2SWORD) {
1087 lprcat("\nYour hands are busy with the two handed sword!");
1088 return;
1089 }
1090 c[SHIELD] = i - 'a';
1091 bottomline();
1092 return;
1093 default:
1094 lprcat("\nYou can't wear that!");
1095 };
1096 }
1097 }
1098 }
1099
1100 /*
1101 function to drop an object
1102 */
1103 void
1104 dropobj()
1105 {
1106 int i;
1107 unsigned char *p;
1108 long amt;
1109 p = &item[playerx][playery];
1110 while (1) {
1111 if ((i = whatitem("drop")) == '\33')
1112 return;
1113 if (i == '*')
1114 showstr();
1115 else {
1116 if (i == '.') { /* drop some gold */
1117 if (*p) {
1118 lprcat("\nThere's something here already!");
1119 return;
1120 }
1121 lprcat("\n\n");
1122 cl_dn(1, 23);
1123 lprcat("How much gold do you drop? ");
1124 if ((amt = readnum((long) c[GOLD])) == 0)
1125 return;
1126 if (amt > c[GOLD]) {
1127 lprcat("\nYou don't have that much!");
1128 return;
1129 }
1130 if (amt <= 32767) {
1131 *p = OGOLDPILE;
1132 i = amt;
1133 } else if (amt <= 327670L) {
1134 *p = ODGOLD;
1135 i = amt / 10;
1136 amt = 10 * i;
1137 } else if (amt <= 3276700L) {
1138 *p = OMAXGOLD;
1139 i = amt / 100;
1140 amt = 100 * i;
1141 } else if (amt <= 32767000L) {
1142 *p = OKGOLD;
1143 i = amt / 1000;
1144 amt = 1000 * i;
1145 } else {
1146 *p = OKGOLD;
1147 i = 32767;
1148 amt = 32767000L;
1149 }
1150 c[GOLD] -= amt;
1151 lprintf("You drop %ld gold pieces", (long)amt);
1152 iarg[playerx][playery] = i;
1153 bottomgold();
1154 know[playerx][playery] = 0;
1155 dropflag = 1;
1156 return;
1157 }
1158 drop_object(i - 'a');
1159 return;
1160 }
1161 }
1162 }
1163
1164 /*
1165 * readscr() Subroutine to read a scroll one is carrying
1166 */
1167 void
1168 readscr()
1169 {
1170 int i;
1171 while (1) {
1172 if ((i = whatitem("read")) == '\33')
1173 return;
1174 if (i != '.') {
1175 if (i == '*')
1176 showread();
1177 else {
1178 if (iven[i - 'a'] == OSCROLL) {
1179 read_scroll(ivenarg[i - 'a']);
1180 iven[i - 'a'] = 0;
1181 return;
1182 }
1183 if (iven[i - 'a'] == OBOOK) {
1184 readbook(ivenarg[i - 'a']);
1185 iven[i - 'a'] = 0;
1186 return;
1187 }
1188 if (iven[i - 'a'] == 0) {
1189 ydhi(i);
1190 return;
1191 }
1192 lprcat("\nThere's nothing on it to read");
1193 return;
1194 }
1195 }
1196 }
1197 }
1198
1199 /*
1200 * subroutine to eat a cookie one is carrying
1201 */
1202 void
1203 eatcookie(void)
1204 {
1205 const char *p;
1206 int i;
1207
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(const char *str)
1272 {
1273 int i;
1274 cursors();
1275 lprintf("\nWhat do you want to %s [* for all] ? ", str);
1276 i = 0;
1277 while (i > 'z' || (i < 'a' && i != '*' && i != '\33' && i != '.'))
1278 i = lgetchar();
1279 if (i == '\33')
1280 lprcat(" aborted");
1281 return (i);
1282 }
1283
1284 /*
1285 subroutine to get a number from the player
1286 and allow * to mean return amt, else return the number entered
1287 */
1288 unsigned long
1289 readnum(mx)
1290 long mx;
1291 {
1292 int i;
1293 unsigned long amt = 0;
1294 sncbr();
1295 if ((i = lgetchar()) == '*')
1296 amt = mx; /* allow him to say * for all gold */
1297 else
1298 while (i != '\n') {
1299 if (i == '\033') {
1300 scbr();
1301 lprcat(" aborted");
1302 return (0);
1303 }
1304 if ((i <= '9') && (i >= '0') && (amt < 99999999))
1305 amt = amt * 10 + i - '0';
1306 i = lgetchar();
1307 }
1308 scbr();
1309 return (amt);
1310 }
1311
1312 #ifdef HIDEBYLINK
1313 /*
1314 * routine to zero every byte in a string
1315 */
1316 void
1317 szero(str)
1318 char *str;
1319 {
1320 while (*str)
1321 *str++ = 0;
1322 }
1323 #endif /* HIDEBYLINK */