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