main.c revision 1.21
1/*	$NetBSD: main.c,v 1.21 2008/02/03 03:45:55 dholland Exp $	*/
2
3/* main.c		 */
4#include <sys/cdefs.h>
5#ifndef lint
6__RCSID("$NetBSD: main.c,v 1.21 2008/02/03 03:45:55 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 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 */
23gid_t           gid, egid;	/* 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	i = 0;
66	egid = getegid();
67	gid = getgid();
68	setegid(gid);		/* 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 its 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 */
310void
311showstr()
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
322void
323qshowstr()
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(".)   %ld 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 %ld.  You have %ld 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 */
349void
350t_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 */
365void
366t_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 */
380void
381showwear()
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 */
429void
430showwield()
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 */
487void
488showread()
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 */
519void
520showeat()
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 */
549void
550showquaff()
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
576void
577show1(idx, str2)
578	int    idx;
579	const 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
586void
587show3(int indx)
588{
589	switch (iven[indx]) {
590	case OPOTION:
591		show1(indx, potionname);
592		break;
593	case OSCROLL:
594		show1(indx, scrollname);
595		break;
596
597	case OLARNEYE:
598	case OBOOK:
599	case OSPIRITSCARAB:
600	case ODIAMOND:
601	case ORUBY:
602	case OCUBEofUNDEAD:
603	case OEMERALD:
604	case OCHEST:
605	case OCOOKIE:
606	case OSAPPHIRE:
607	case ONOTHEFT:
608		show1(indx, NULL);
609		break;
610
611	default:
612		lprintf("\n%c)   %s", indx + 'a', objectname[iven[indx]]);
613		if (ivenarg[indx] > 0)
614			lprintf(" + %ld", (long) ivenarg[indx]);
615		else if (ivenarg[indx] < 0)
616			lprintf(" %ld", (long) ivenarg[indx]);
617		break;
618	}
619	if (c[WIELD] == indx)
620		lprcat(" (weapon in hand)");
621	if ((c[WEAR] == indx) || (c[SHIELD] == indx))
622		lprcat(" (being worn)");
623	if (++srcount >= 22) {
624		srcount = 0;
625		more();
626		clear();
627	}
628}
629
630/*
631	subroutine to randomly create monsters if needed
632 */
633void
634randmonst()
635{
636	if (c[TIMESTOP])
637		return;		/* don't make monsters if time is stopped	 */
638	if (--rmst <= 0) {
639		rmst = 120 - (level << 2);
640		fillmonst(makemonst(level));
641	}
642}
643
644
645
646/*
647	parse()
648
649	get and execute a command
650 */
651void
652parse()
653{
654	int    i, j, k, flag;
655	while (1) {
656		k = yylex();
657		switch (k) {	/* get the token from the input and switch on
658				 * it	 */
659		case 'h':
660			moveplayer(4);
661			return;	/* west		 */
662		case 'H':
663			run(4);
664			return;	/* west		 */
665		case 'l':
666			moveplayer(2);
667			return;	/* east		 */
668		case 'L':
669			run(2);
670			return;	/* east		 */
671		case 'j':
672			moveplayer(1);
673			return;	/* south		 */
674		case 'J':
675			run(1);
676			return;	/* south		 */
677		case 'k':
678			moveplayer(3);
679			return;	/* north		 */
680		case 'K':
681			run(3);
682			return;	/* north		 */
683		case 'u':
684			moveplayer(5);
685			return;	/* northeast	 */
686		case 'U':
687			run(5);
688			return;	/* northeast	 */
689		case 'y':
690			moveplayer(6);
691			return;	/* northwest	 */
692		case 'Y':
693			run(6);
694			return;	/* northwest	 */
695		case 'n':
696			moveplayer(7);
697			return;	/* southeast	 */
698		case 'N':
699			run(7);
700			return;	/* southeast	 */
701		case 'b':
702			moveplayer(8);
703			return;	/* southwest	 */
704		case 'B':
705			run(8);
706			return;	/* southwest	 */
707
708		case '.':
709			if (yrepcount)
710				viewflag = 1;
711			return;	/* stay here		 */
712
713		case 'w':
714			yrepcount = 0;
715			wield();
716			return;	/* wield a weapon */
717
718		case 'W':
719			yrepcount = 0;
720			wear();
721			return;	/* wear armor	 */
722
723		case 'r':
724			yrepcount = 0;
725			if (c[BLINDCOUNT]) {
726				cursors();
727				lprcat("\nYou can't read anything when you're blind!");
728			} else if (c[TIMESTOP] == 0)
729				readscr();
730			return;	/* to read a scroll	 */
731
732		case 'q':
733			yrepcount = 0;
734			if (c[TIMESTOP] == 0)
735				quaff();
736			return;	/* quaff a potion		 */
737
738		case 'd':
739			yrepcount = 0;
740			if (c[TIMESTOP] == 0)
741				dropobj();
742			return;	/* to drop an object	 */
743
744		case 'c':
745			yrepcount = 0;
746			cast();
747			return;	/* cast a spell	 */
748
749		case 'i':
750			yrepcount = 0;
751			nomove = 1;
752			showstr();
753			return;	/* status		 */
754
755		case 'e':
756			yrepcount = 0;
757			if (c[TIMESTOP] == 0)
758				eatcookie();
759			return;	/* to eat a fortune cookie */
760
761		case 'D':
762			yrepcount = 0;
763			seemagic(0);
764			nomove = 1;
765			return;	/* list spells and scrolls */
766
767		case '?':
768			yrepcount = 0;
769			help();
770			nomove = 1;
771			return;	/* give the help screen */
772
773		case 'S':
774			clear();
775			lprcat("Saving . . .");
776			lflush();
777			savegame(savefilename);
778			wizard = 1;
779			died(-257);	/* save the game - doesn't return	 */
780
781		case 'Z':
782			yrepcount = 0;
783			if (c[LEVEL] > 9) {
784				oteleport(1);
785				return;
786			}
787			cursors();
788			lprcat("\nAs yet, you don't have enough experience to use teleportation");
789			return;	/* teleport yourself	 */
790
791		case '^':	/* identify traps */
792			flag = yrepcount = 0;
793			cursors();
794			lprc('\n');
795			for (j = playery - 1; j < playery + 2; j++) {
796				if (j < 0)
797					j = 0;
798				if (j >= MAXY)
799					break;
800				for (i = playerx - 1; i < playerx + 2; i++) {
801					if (i < 0)
802						i = 0;
803					if (i >= MAXX)
804						break;
805					switch (item[i][j]) {
806					case OTRAPDOOR:
807					case ODARTRAP:
808					case OTRAPARROW:
809					case OTELEPORTER:
810						lprcat("\nIt's ");
811						lprcat(objectname[item[i][j]]);
812						flag++;
813					};
814				}
815			}
816			if (flag == 0)
817				lprcat("\nNo traps are visible");
818			return;
819
820#if WIZID
821		case '_':	/* this is the fudge player password for
822				 * wizard mode */
823			yrepcount = 0;
824			cursors();
825			nomove = 1;
826			if (userid != wisid) {
827				lprcat("Sorry, you are not empowered to be a wizard.\n");
828				scbr();	/* system("stty -echo cbreak"); */
829				lflush();
830				return;
831			}
832			if (getpassword() == 0) {
833				scbr();	/* system("stty -echo cbreak"); */
834				return;
835			}
836			wizard = 1;
837			scbr();	/* system("stty -echo cbreak"); */
838			for (i = 0; i < 6; i++)
839				c[i] = 70;
840			iven[0] = iven[1] = 0;
841			take(OPROTRING, 50);
842			take(OLANCE, 25);
843			c[WIELD] = 1;
844			c[LANCEDEATH] = 1;
845			c[WEAR] = c[SHIELD] = -1;
846			raiseexperience(6000000L);
847			c[AWARENESS] += 25000;
848			{
849				int    i, j;
850				for (i = 0; i < MAXY; i++)
851					for (j = 0; j < MAXX; j++)
852						know[j][i] = 1;
853				for (i = 0; i < SPNUM; i++)
854					spelknow[i] = 1;
855				for (i = 0; i < MAXSCROLL; i++)
856					scrollname[i] = scrollhide[i];
857				for (i = 0; i < MAXPOTION; i++)
858					potionname[i] = potionhide[i];
859			}
860			for (i = 0; i < MAXSCROLL; i++)
861				if (strlen(scrollname[i]) > 2) {	/* no null items */
862					item[i][0] = OSCROLL;
863					iarg[i][0] = i;
864				}
865			for (i = MAXX - 1; i > MAXX - 1 - MAXPOTION; i--)
866				if (strlen(potionname[i - MAXX + MAXPOTION]) > 2) {	/* no null items */
867					item[i][0] = OPOTION;
868					iarg[i][0] = i - MAXX + MAXPOTION;
869				}
870			for (i = 1; i < MAXY; i++) {
871				item[0][i] = i;
872				iarg[0][i] = 0;
873			}
874			for (i = MAXY; i < MAXY + MAXX; i++) {
875				item[i - MAXY][MAXY - 1] = i;
876				iarg[i - MAXY][MAXY - 1] = 0;
877			}
878			for (i = MAXX + MAXY; i < MAXX + MAXY + MAXY; i++) {
879				item[MAXX - 1][i - MAXX - MAXY] = i;
880				iarg[MAXX - 1][i - MAXX - MAXY] = 0;
881			}
882			c[GOLD] += 25000;
883			drawscreen();
884			return;
885#endif
886
887		case 'T':
888			yrepcount = 0;
889			cursors();
890			if (c[SHIELD] != -1) {
891				c[SHIELD] = -1;
892				lprcat("\nYour shield is off");
893				bottomline();
894			} else if (c[WEAR] != -1) {
895				c[WEAR] = -1;
896				lprcat("\nYour armor is off");
897				bottomline();
898			} else
899				lprcat("\nYou aren't wearing anything");
900			return;
901
902		case 'g':
903			cursors();
904			lprintf("\nThe stuff you are carrying presently weighs %ld pounds", (long) packweight());
905		case ' ':
906			yrepcount = 0;
907			nomove = 1;
908			return;
909
910		case 'v':
911			yrepcount = 0;
912			cursors();
913			lprintf("\nCaverns of Larn, Version %ld.%ld, Diff=%ld",
914				(long) VERSION, (long) SUBVERSION,
915				(long) c[HARDGAME]);
916			if (wizard)
917				lprcat(" Wizard");
918			nomove = 1;
919			if (cheat)
920				lprcat(" Cheater");
921			lprcat(copyright);
922			return;
923
924		case 'Q':
925			yrepcount = 0;
926			quit();
927			nomove = 1;
928			return;	/* quit		 */
929
930		case 'L' - 64:
931			yrepcount = 0;
932			drawscreen();
933			nomove = 1;
934			return;	/* look		 */
935
936#if WIZID
937#ifdef EXTRA
938		case 'A':
939			yrepcount = 0;
940			nomove = 1;
941			if (wizard) {
942				diag();
943				return;
944			}	/* create diagnostic file */
945			return;
946#endif
947#endif
948		case 'P':
949			cursors();
950			if (outstanding_taxes > 0)
951				lprintf("\nYou presently owe %ld gp in taxes.",
952					(long) outstanding_taxes);
953			else
954				lprcat("\nYou do not owe any taxes.");
955			return;
956		};
957	}
958}
959
960void
961parse2()
962{
963	if (c[HASTEMONST])
964		movemonst();
965	movemonst();		/* move the monsters		 */
966	randmonst();
967	regen();
968}
969
970void
971run(dir)
972	int             dir;
973{
974	int    i;
975	i = 1;
976	while (i) {
977		i = moveplayer(dir);
978		if (i > 0) {
979			if (c[HASTEMONST])
980				movemonst();
981			movemonst();
982			randmonst();
983			regen();
984		}
985		if (hitflag)
986			i = 0;
987		if (i != 0)
988			showcell(playerx, playery);
989	}
990}
991
992/*
993	function to wield a weapon
994 */
995void
996wield()
997{
998	int    i;
999	while (1) {
1000		if ((i = whatitem("wield")) == '\33')
1001			return;
1002		if (i != '.') {
1003			if (i == '*')
1004				showwield();
1005			else if (iven[i - 'a'] == 0) {
1006				ydhi(i);
1007				return;
1008			} else if (iven[i - 'a'] == OPOTION) {
1009				ycwi(i);
1010				return;
1011			} else if (iven[i - 'a'] == OSCROLL) {
1012				ycwi(i);
1013				return;
1014			} else if ((c[SHIELD] != -1) && (iven[i - 'a'] == O2SWORD)) {
1015				lprcat("\nBut one arm is busy with your shield!");
1016				return;
1017			} else {
1018				c[WIELD] = i - 'a';
1019				if (iven[i - 'a'] == OLANCE)
1020					c[LANCEDEATH] = 1;
1021				else
1022					c[LANCEDEATH] = 0;
1023				bottomline();
1024				return;
1025			}
1026		}
1027	}
1028}
1029
1030/*
1031	common routine to say you don't have an item
1032 */
1033void
1034ydhi(x)
1035	int             x;
1036{
1037	cursors();
1038	lprintf("\nYou don't have item %c!", x);
1039}
1040void
1041ycwi(x)
1042	int             x;
1043{
1044	cursors();
1045	lprintf("\nYou can't wield item %c!", x);
1046}
1047
1048/*
1049	function to wear armor
1050 */
1051void
1052wear()
1053{
1054	int    i;
1055	while (1) {
1056		if ((i = whatitem("wear")) == '\33')
1057			return;
1058		if (i != '.') {
1059			if (i == '*')
1060				showwear();
1061			else
1062				switch (iven[i - 'a']) {
1063				case 0:
1064					ydhi(i);
1065					return;
1066				case OLEATHER:
1067				case OCHAIN:
1068				case OPLATE:
1069				case OSTUDLEATHER:
1070				case ORING:
1071				case OSPLINT:
1072				case OPLATEARMOR:
1073				case OSSPLATE:
1074					if (c[WEAR] != -1) {
1075						lprcat("\nYou're already wearing some armor");
1076						return;
1077					}
1078					c[WEAR] = i - 'a';
1079					bottomline();
1080					return;
1081				case OSHIELD:
1082					if (c[SHIELD] != -1) {
1083						lprcat("\nYou are already wearing a shield");
1084						return;
1085					}
1086					if (iven[c[WIELD]] == O2SWORD) {
1087						lprcat("\nYour hands are busy with the two handed sword!");
1088						return;
1089					}
1090					c[SHIELD] = i - 'a';
1091					bottomline();
1092					return;
1093				default:
1094					lprcat("\nYou can't wear that!");
1095				};
1096		}
1097	}
1098}
1099
1100/*
1101	function to drop an object
1102 */
1103void
1104dropobj()
1105{
1106	int    i;
1107	unsigned char  *p;
1108	long            amt;
1109	p = &item[playerx][playery];
1110	while (1) {
1111		if ((i = whatitem("drop")) == '\33')
1112			return;
1113		if (i == '*')
1114			showstr();
1115		else {
1116			if (i == '.') {	/* drop some gold */
1117				if (*p) {
1118					lprcat("\nThere's something here already!");
1119					return;
1120				}
1121				lprcat("\n\n");
1122				cl_dn(1, 23);
1123				lprcat("How much gold do you drop? ");
1124				if ((amt = readnum((long) c[GOLD])) == 0)
1125					return;
1126				if (amt > c[GOLD]) {
1127					lprcat("\nYou don't have that much!");
1128					return;
1129				}
1130				if (amt <= 32767) {
1131					*p = OGOLDPILE;
1132					i = amt;
1133				} else if (amt <= 327670L) {
1134					*p = ODGOLD;
1135					i = amt / 10;
1136					amt = 10 * i;
1137				} else if (amt <= 3276700L) {
1138					*p = OMAXGOLD;
1139					i = amt / 100;
1140					amt = 100 * i;
1141				} else if (amt <= 32767000L) {
1142					*p = OKGOLD;
1143					i = amt / 1000;
1144					amt = 1000 * i;
1145				} else {
1146					*p = OKGOLD;
1147					i = 32767;
1148					amt = 32767000L;
1149				}
1150				c[GOLD] -= amt;
1151				lprintf("You drop %ld gold pieces", (long)amt);
1152				iarg[playerx][playery] = i;
1153				bottomgold();
1154				know[playerx][playery] = 0;
1155				dropflag = 1;
1156				return;
1157			}
1158			drop_object(i - 'a');
1159			return;
1160		}
1161	}
1162}
1163
1164/*
1165 *	readscr()		Subroutine to read a scroll one is carrying
1166 */
1167void
1168readscr()
1169{
1170	int    i;
1171	while (1) {
1172		if ((i = whatitem("read")) == '\33')
1173			return;
1174		if (i != '.') {
1175			if (i == '*')
1176				showread();
1177			else {
1178				if (iven[i - 'a'] == OSCROLL) {
1179					read_scroll(ivenarg[i - 'a']);
1180					iven[i - 'a'] = 0;
1181					return;
1182				}
1183				if (iven[i - 'a'] == OBOOK) {
1184					readbook(ivenarg[i - 'a']);
1185					iven[i - 'a'] = 0;
1186					return;
1187				}
1188				if (iven[i - 'a'] == 0) {
1189					ydhi(i);
1190					return;
1191				}
1192				lprcat("\nThere's nothing on it to read");
1193				return;
1194			}
1195		}
1196	}
1197}
1198
1199/*
1200 *	subroutine to eat a cookie one is carrying
1201 */
1202void
1203eatcookie(void)
1204{
1205	const char *p;
1206	int i;
1207
1208	while (1) {
1209		if ((i = whatitem("eat")) == '\33')
1210			return;
1211		if (i != '.') {
1212			if (i == '*')
1213				showeat();
1214			else {
1215				if (iven[i - 'a'] == OCOOKIE) {
1216					lprcat("\nThe cookie was delicious.");
1217					iven[i - 'a'] = 0;
1218					if (!c[BLINDCOUNT]) {
1219						if ((p = fortune()) != NULL) {
1220							lprcat("  Inside you find a scrap of paper that says:\n");
1221							lprcat(p);
1222						}
1223					}
1224					return;
1225				}
1226				if (iven[i - 'a'] == 0) {
1227					ydhi(i);
1228					return;
1229				}
1230				lprcat("\nYou can't eat that!");
1231				return;
1232			}
1233		}
1234	}
1235}
1236
1237/*
1238 *	subroutine to quaff a potion one is carrying
1239 */
1240void
1241quaff()
1242{
1243	int    i;
1244	while (1) {
1245		if ((i = whatitem("quaff")) == '\33')
1246			return;
1247		if (i != '.') {
1248			if (i == '*')
1249				showquaff();
1250			else {
1251				if (iven[i - 'a'] == OPOTION) {
1252					quaffpotion(ivenarg[i - 'a']);
1253					iven[i - 'a'] = 0;
1254					return;
1255				}
1256				if (iven[i - 'a'] == 0) {
1257					ydhi(i);
1258					return;
1259				}
1260				lprcat("\nYou wouldn't want to quaff that, would you? ");
1261				return;
1262			}
1263		}
1264	}
1265}
1266
1267/*
1268	function to ask what player wants to do
1269 */
1270int
1271whatitem(const char *str)
1272{
1273	int             i;
1274	cursors();
1275	lprintf("\nWhat do you want to %s [* for all] ? ", str);
1276	i = 0;
1277	while (i > 'z' || (i < 'a' && i != '*' && i != '\33' && i != '.'))
1278		i = lgetchar();
1279	if (i == '\33')
1280		lprcat(" aborted");
1281	return (i);
1282}
1283
1284/*
1285	subroutine to get a number from the player
1286	and allow * to mean return amt, else return the number entered
1287 */
1288unsigned long
1289readnum(mx)
1290	long            mx;
1291{
1292	int    i;
1293	unsigned long amt = 0;
1294	sncbr();
1295	if ((i = lgetchar()) == '*')
1296		amt = mx;	/* allow him to say * for all gold */
1297	else
1298		while (i != '\n') {
1299			if (i == '\033') {
1300				scbr();
1301				lprcat(" aborted");
1302				return (0);
1303			}
1304			if ((i <= '9') && (i >= '0') && (amt < 99999999))
1305				amt = amt * 10 + i - '0';
1306			i = lgetchar();
1307		}
1308	scbr();
1309	return (amt);
1310}
1311
1312#ifdef HIDEBYLINK
1313/*
1314 *	routine to zero every byte in a string
1315 */
1316void
1317szero(str)
1318	char  *str;
1319{
1320	while (*str)
1321		*str++ = 0;
1322}
1323#endif	/* HIDEBYLINK */
1324