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