xref: /dragonfly/games/larn/main.c (revision e9d1c8d1)
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