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