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