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