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