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