main.c revision 1.19
1/*	$NetBSD: main.c,v 1.19 2008/01/28 03:39:31 dholland Exp $	*/
2
3/* main.c		 */
4#include <sys/cdefs.h>
5#ifndef lint
6__RCSID("$NetBSD: main.c,v 1.19 2008/01/28 03:39:31 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 */
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	i = 0;
66	euid = geteuid();
67	uid = getuid();
68	seteuid(uid);		/* give up "games" if we have it */
69	/*
70	 *	first task is to identify the player
71	 */
72#ifndef VT100
73	init_term();		/* setup the terminal (find out what type)
74				 * for termcap */
75#endif	/* VT100 */
76	/* try to get login name */
77	if (((ptr = getlogin()) == 0) || (*ptr == 0)) {
78		/* can we get it from /etc/passwd? */
79		if ((pwe = getpwuid(getuid())) != NULL)
80			ptr = pwe->pw_name;
81		else if ((ptr = getenv("USER")) == 0)
82			if ((ptr = getenv("LOGNAME")) == 0) {
83		noone:		write(2, "Can't find your logname.  Who Are You?\n", 39);
84				exit(1);
85			}
86	}
87	if (ptr == 0)
88		goto noone;
89	if (strlen(ptr) == 0)
90		goto noone;
91	/*
92	 *	second task is to prepare the pathnames the player will need
93	 */
94	strcpy(loginname, ptr);	/* save loginname of the user for logging
95				 * purposes */
96	strcpy(logname, ptr);	/* this will be overwritten with the players
97				 * name */
98	if ((ptr = getenv("HOME")) == NULL)
99		ptr = ".";
100	strcpy(savefilename, ptr);
101	strcat(savefilename, "/Larn.sav");	/* save file name in home
102						 * directory */
103	snprintf(optsfile, sizeof(optsfile), "%s/.larnopts", ptr);
104	/* the .larnopts filename */
105
106	/*
107	 *	now malloc the memory for the dungeon
108	 */
109	cell = (struct cel *) malloc(sizeof(struct cel) * (MAXLEVEL + MAXVLEVEL) * MAXX * MAXY);
110	if (cell == 0)
111		died(-285);	/* malloc failure */
112	lpbuf = malloc((5 * BUFBIG) >> 2);	/* output buffer */
113	inbuffer = malloc((5 * MAXIBUF) >> 2);	/* output buffer */
114	if ((lpbuf == 0) || (inbuffer == 0))
115		died(-285);	/* malloc() failure */
116
117	lcreat((char *) 0);
118	newgame();		/* set the initial clock  */
119	hard = -1;
120
121#ifdef VT100
122	/*
123	 *	check terminal type to avoid users who have not vt100 type terminals
124	 */
125	ttype = getenv("TERM");
126	for (j = 1, i = 0; i < sizeof(termtypes) / sizeof(char *); i++)
127		if (strcmp(ttype, termtypes[i]) == 0) {
128			j = 0;
129			break;
130		}
131	if (j) {
132		lprcat("Sorry, Larn needs a VT100 family terminal for all 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	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(index)
588	int    index;
589{
590	switch (iven[index]) {
591	case OPOTION:
592		show1(index, potionname);
593		break;
594	case OSCROLL:
595		show1(index, scrollname);
596		break;
597
598	case OLARNEYE:
599	case OBOOK:
600	case OSPIRITSCARAB:
601	case ODIAMOND:
602	case ORUBY:
603	case OCUBEofUNDEAD:
604	case OEMERALD:
605	case OCHEST:
606	case OCOOKIE:
607	case OSAPPHIRE:
608	case ONOTHEFT:
609		show1(index, (char **) 0);
610		break;
611
612	default:
613		lprintf("\n%c)   %s", index + 'a', objectname[iven[index]]);
614		if (ivenarg[index] > 0)
615			lprintf(" + %ld", (long) ivenarg[index]);
616		else if (ivenarg[index] < 0)
617			lprintf(" %ld", (long) ivenarg[index]);
618		break;
619	}
620	if (c[WIELD] == index)
621		lprcat(" (weapon in hand)");
622	if ((c[WEAR] == index) || (c[SHIELD] == index))
623		lprcat(" (being worn)");
624	if (++srcount >= 22) {
625		srcount = 0;
626		more();
627		clear();
628	}
629}
630
631/*
632	subroutine to randomly create monsters if needed
633 */
634void
635randmonst()
636{
637	if (c[TIMESTOP])
638		return;		/* don't make monsters if time is stopped	 */
639	if (--rmst <= 0) {
640		rmst = 120 - (level << 2);
641		fillmonst(makemonst(level));
642	}
643}
644
645
646
647/*
648	parse()
649
650	get and execute a command
651 */
652void
653parse()
654{
655	int    i, j, k, flag;
656	while (1) {
657		k = yylex();
658		switch (k) {	/* get the token from the input and switch on
659				 * it	 */
660		case 'h':
661			moveplayer(4);
662			return;	/* west		 */
663		case 'H':
664			run(4);
665			return;	/* west		 */
666		case 'l':
667			moveplayer(2);
668			return;	/* east		 */
669		case 'L':
670			run(2);
671			return;	/* east		 */
672		case 'j':
673			moveplayer(1);
674			return;	/* south		 */
675		case 'J':
676			run(1);
677			return;	/* south		 */
678		case 'k':
679			moveplayer(3);
680			return;	/* north		 */
681		case 'K':
682			run(3);
683			return;	/* north		 */
684		case 'u':
685			moveplayer(5);
686			return;	/* northeast	 */
687		case 'U':
688			run(5);
689			return;	/* northeast	 */
690		case 'y':
691			moveplayer(6);
692			return;	/* northwest	 */
693		case 'Y':
694			run(6);
695			return;	/* northwest	 */
696		case 'n':
697			moveplayer(7);
698			return;	/* southeast	 */
699		case 'N':
700			run(7);
701			return;	/* southeast	 */
702		case 'b':
703			moveplayer(8);
704			return;	/* southwest	 */
705		case 'B':
706			run(8);
707			return;	/* southwest	 */
708
709		case '.':
710			if (yrepcount)
711				viewflag = 1;
712			return;	/* stay here		 */
713
714		case 'w':
715			yrepcount = 0;
716			wield();
717			return;	/* wield a weapon */
718
719		case 'W':
720			yrepcount = 0;
721			wear();
722			return;	/* wear armor	 */
723
724		case 'r':
725			yrepcount = 0;
726			if (c[BLINDCOUNT]) {
727				cursors();
728				lprcat("\nYou can't read anything when you're blind!");
729			} else if (c[TIMESTOP] == 0)
730				readscr();
731			return;	/* to read a scroll	 */
732
733		case 'q':
734			yrepcount = 0;
735			if (c[TIMESTOP] == 0)
736				quaff();
737			return;	/* quaff a potion		 */
738
739		case 'd':
740			yrepcount = 0;
741			if (c[TIMESTOP] == 0)
742				dropobj();
743			return;	/* to drop an object	 */
744
745		case 'c':
746			yrepcount = 0;
747			cast();
748			return;	/* cast a spell	 */
749
750		case 'i':
751			yrepcount = 0;
752			nomove = 1;
753			showstr();
754			return;	/* status		 */
755
756		case 'e':
757			yrepcount = 0;
758			if (c[TIMESTOP] == 0)
759				eatcookie();
760			return;	/* to eat a fortune cookie */
761
762		case 'D':
763			yrepcount = 0;
764			seemagic(0);
765			nomove = 1;
766			return;	/* list spells and scrolls */
767
768		case '?':
769			yrepcount = 0;
770			help();
771			nomove = 1;
772			return;	/* give the help screen */
773
774		case 'S':
775			clear();
776			lprcat("Saving . . .");
777			lflush();
778			savegame(savefilename);
779			wizard = 1;
780			died(-257);	/* save the game - doesn't return	 */
781
782		case 'Z':
783			yrepcount = 0;
784			if (c[LEVEL] > 9) {
785				oteleport(1);
786				return;
787			}
788			cursors();
789			lprcat("\nAs yet, you don't have enough experience to use teleportation");
790			return;	/* teleport yourself	 */
791
792		case '^':	/* identify traps */
793			flag = yrepcount = 0;
794			cursors();
795			lprc('\n');
796			for (j = playery - 1; j < playery + 2; j++) {
797				if (j < 0)
798					j = 0;
799				if (j >= MAXY)
800					break;
801				for (i = playerx - 1; i < playerx + 2; i++) {
802					if (i < 0)
803						i = 0;
804					if (i >= MAXX)
805						break;
806					switch (item[i][j]) {
807					case OTRAPDOOR:
808					case ODARTRAP:
809					case OTRAPARROW:
810					case OTELEPORTER:
811						lprcat("\nIt's ");
812						lprcat(objectname[item[i][j]]);
813						flag++;
814					};
815				}
816			}
817			if (flag == 0)
818				lprcat("\nNo traps are visible");
819			return;
820
821#if WIZID
822		case '_':	/* this is the fudge player password for
823				 * wizard mode */
824			yrepcount = 0;
825			cursors();
826			nomove = 1;
827			if (userid != wisid) {
828				lprcat("Sorry, you are not empowered to be a wizard.\n");
829				scbr();	/* system("stty -echo cbreak"); */
830				lflush();
831				return;
832			}
833			if (getpassword() == 0) {
834				scbr();	/* system("stty -echo cbreak"); */
835				return;
836			}
837			wizard = 1;
838			scbr();	/* system("stty -echo cbreak"); */
839			for (i = 0; i < 6; i++)
840				c[i] = 70;
841			iven[0] = iven[1] = 0;
842			take(OPROTRING, 50);
843			take(OLANCE, 25);
844			c[WIELD] = 1;
845			c[LANCEDEATH] = 1;
846			c[WEAR] = c[SHIELD] = -1;
847			raiseexperience(6000000L);
848			c[AWARENESS] += 25000;
849			{
850				int    i, j;
851				for (i = 0; i < MAXY; i++)
852					for (j = 0; j < MAXX; j++)
853						know[j][i] = 1;
854				for (i = 0; i < SPNUM; i++)
855					spelknow[i] = 1;
856				for (i = 0; i < MAXSCROLL; i++)
857					scrollname[i] = scrollhide[i];
858				for (i = 0; i < MAXPOTION; i++)
859					potionname[i] = potionhide[i];
860			}
861			for (i = 0; i < MAXSCROLL; i++)
862				if (strlen(scrollname[i]) > 2) {	/* no null items */
863					item[i][0] = OSCROLL;
864					iarg[i][0] = i;
865				}
866			for (i = MAXX - 1; i > MAXX - 1 - MAXPOTION; i--)
867				if (strlen(potionname[i - MAXX + MAXPOTION]) > 2) {	/* no null items */
868					item[i][0] = OPOTION;
869					iarg[i][0] = i - MAXX + MAXPOTION;
870				}
871			for (i = 1; i < MAXY; i++) {
872				item[0][i] = i;
873				iarg[0][i] = 0;
874			}
875			for (i = MAXY; i < MAXY + MAXX; i++) {
876				item[i - MAXY][MAXY - 1] = i;
877				iarg[i - MAXY][MAXY - 1] = 0;
878			}
879			for (i = MAXX + MAXY; i < MAXX + MAXY + MAXY; i++) {
880				item[MAXX - 1][i - MAXX - MAXY] = i;
881				iarg[MAXX - 1][i - MAXX - MAXY] = 0;
882			}
883			c[GOLD] += 25000;
884			drawscreen();
885			return;
886#endif
887
888		case 'T':
889			yrepcount = 0;
890			cursors();
891			if (c[SHIELD] != -1) {
892				c[SHIELD] = -1;
893				lprcat("\nYour shield is off");
894				bottomline();
895			} else if (c[WEAR] != -1) {
896				c[WEAR] = -1;
897				lprcat("\nYour armor is off");
898				bottomline();
899			} else
900				lprcat("\nYou aren't wearing anything");
901			return;
902
903		case 'g':
904			cursors();
905			lprintf("\nThe stuff you are carrying presently weighs %ld pounds", (long) packweight());
906		case ' ':
907			yrepcount = 0;
908			nomove = 1;
909			return;
910
911		case 'v':
912			yrepcount = 0;
913			cursors();
914			lprintf("\nCaverns of Larn, Version %ld.%ld, Diff=%ld",
915				(long) VERSION, (long) SUBVERSION,
916				(long) c[HARDGAME]);
917			if (wizard)
918				lprcat(" Wizard");
919			nomove = 1;
920			if (cheat)
921				lprcat(" Cheater");
922			lprcat(copyright);
923			return;
924
925		case 'Q':
926			yrepcount = 0;
927			quit();
928			nomove = 1;
929			return;	/* quit		 */
930
931		case 'L' - 64:
932			yrepcount = 0;
933			drawscreen();
934			nomove = 1;
935			return;	/* look		 */
936
937#if WIZID
938#ifdef EXTRA
939		case 'A':
940			yrepcount = 0;
941			nomove = 1;
942			if (wizard) {
943				diag();
944				return;
945			}	/* create diagnostic file */
946			return;
947#endif
948#endif
949		case 'P':
950			cursors();
951			if (outstanding_taxes > 0)
952				lprintf("\nYou presently owe %ld gp in taxes.",
953					(long) outstanding_taxes);
954			else
955				lprcat("\nYou do not owe any taxes.");
956			return;
957		};
958	}
959}
960
961void
962parse2()
963{
964	if (c[HASTEMONST])
965		movemonst();
966	movemonst();		/* move the monsters		 */
967	randmonst();
968	regen();
969}
970
971void
972run(dir)
973	int             dir;
974{
975	int    i;
976	i = 1;
977	while (i) {
978		i = moveplayer(dir);
979		if (i > 0) {
980			if (c[HASTEMONST])
981				movemonst();
982			movemonst();
983			randmonst();
984			regen();
985		}
986		if (hitflag)
987			i = 0;
988		if (i != 0)
989			showcell(playerx, playery);
990	}
991}
992
993/*
994	function to wield a weapon
995 */
996void
997wield()
998{
999	int    i;
1000	while (1) {
1001		if ((i = whatitem("wield")) == '\33')
1002			return;
1003		if (i != '.') {
1004			if (i == '*')
1005				showwield();
1006			else if (iven[i - 'a'] == 0) {
1007				ydhi(i);
1008				return;
1009			} else if (iven[i - 'a'] == OPOTION) {
1010				ycwi(i);
1011				return;
1012			} else if (iven[i - 'a'] == OSCROLL) {
1013				ycwi(i);
1014				return;
1015			} else if ((c[SHIELD] != -1) && (iven[i - 'a'] == O2SWORD)) {
1016				lprcat("\nBut one arm is busy with your shield!");
1017				return;
1018			} else {
1019				c[WIELD] = i - 'a';
1020				if (iven[i - 'a'] == OLANCE)
1021					c[LANCEDEATH] = 1;
1022				else
1023					c[LANCEDEATH] = 0;
1024				bottomline();
1025				return;
1026			}
1027		}
1028	}
1029}
1030
1031/*
1032	common routine to say you don't have an item
1033 */
1034void
1035ydhi(x)
1036	int             x;
1037{
1038	cursors();
1039	lprintf("\nYou don't have item %c!", x);
1040}
1041void
1042ycwi(x)
1043	int             x;
1044{
1045	cursors();
1046	lprintf("\nYou can't wield item %c!", x);
1047}
1048
1049/*
1050	function to wear armor
1051 */
1052void
1053wear()
1054{
1055	int    i;
1056	while (1) {
1057		if ((i = whatitem("wear")) == '\33')
1058			return;
1059		if (i != '.') {
1060			if (i == '*')
1061				showwear();
1062			else
1063				switch (iven[i - 'a']) {
1064				case 0:
1065					ydhi(i);
1066					return;
1067				case OLEATHER:
1068				case OCHAIN:
1069				case OPLATE:
1070				case OSTUDLEATHER:
1071				case ORING:
1072				case OSPLINT:
1073				case OPLATEARMOR:
1074				case OSSPLATE:
1075					if (c[WEAR] != -1) {
1076						lprcat("\nYou're already wearing some armor");
1077						return;
1078					}
1079					c[WEAR] = i - 'a';
1080					bottomline();
1081					return;
1082				case OSHIELD:
1083					if (c[SHIELD] != -1) {
1084						lprcat("\nYou are already wearing a shield");
1085						return;
1086					}
1087					if (iven[c[WIELD]] == O2SWORD) {
1088						lprcat("\nYour hands are busy with the two handed sword!");
1089						return;
1090					}
1091					c[SHIELD] = i - 'a';
1092					bottomline();
1093					return;
1094				default:
1095					lprcat("\nYou can't wear that!");
1096				};
1097		}
1098	}
1099}
1100
1101/*
1102	function to drop an object
1103 */
1104void
1105dropobj()
1106{
1107	int    i;
1108	char  *p;
1109	long            amt;
1110	p = &item[playerx][playery];
1111	while (1) {
1112		if ((i = whatitem("drop")) == '\33')
1113			return;
1114		if (i == '*')
1115			showstr();
1116		else {
1117			if (i == '.') {	/* drop some gold */
1118				if (*p) {
1119					lprcat("\nThere's something here already!");
1120					return;
1121				}
1122				lprcat("\n\n");
1123				cl_dn(1, 23);
1124				lprcat("How much gold do you drop? ");
1125				if ((amt = readnum((long) c[GOLD])) == 0)
1126					return;
1127				if (amt > c[GOLD]) {
1128					lprcat("\nYou don't have that much!");
1129					return;
1130				}
1131				if (amt <= 32767) {
1132					*p = OGOLDPILE;
1133					i = amt;
1134				} else if (amt <= 327670L) {
1135					*p = ODGOLD;
1136					i = amt / 10;
1137					amt = 10 * i;
1138				} else if (amt <= 3276700L) {
1139					*p = OMAXGOLD;
1140					i = amt / 100;
1141					amt = 100 * i;
1142				} else if (amt <= 32767000L) {
1143					*p = OKGOLD;
1144					i = amt / 1000;
1145					amt = 1000 * i;
1146				} else {
1147					*p = OKGOLD;
1148					i = 32767;
1149					amt = 32767000L;
1150				}
1151				c[GOLD] -= amt;
1152				lprintf("You drop %ld gold pieces", (long)amt);
1153				iarg[playerx][playery] = i;
1154				bottomgold();
1155				know[playerx][playery] = 0;
1156				dropflag = 1;
1157				return;
1158			}
1159			drop_object(i - 'a');
1160			return;
1161		}
1162	}
1163}
1164
1165/*
1166 *	readscr()		Subroutine to read a scroll one is carrying
1167 */
1168void
1169readscr()
1170{
1171	int    i;
1172	while (1) {
1173		if ((i = whatitem("read")) == '\33')
1174			return;
1175		if (i != '.') {
1176			if (i == '*')
1177				showread();
1178			else {
1179				if (iven[i - 'a'] == OSCROLL) {
1180					read_scroll(ivenarg[i - 'a']);
1181					iven[i - 'a'] = 0;
1182					return;
1183				}
1184				if (iven[i - 'a'] == OBOOK) {
1185					readbook(ivenarg[i - 'a']);
1186					iven[i - 'a'] = 0;
1187					return;
1188				}
1189				if (iven[i - 'a'] == 0) {
1190					ydhi(i);
1191					return;
1192				}
1193				lprcat("\nThere's nothing on it to read");
1194				return;
1195			}
1196		}
1197	}
1198}
1199
1200/*
1201 *	subroutine to eat a cookie one is carrying
1202 */
1203void
1204eatcookie()
1205{
1206	int    i;
1207	char           *p;
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(str)
1272	char           *str;
1273{
1274	int             i;
1275	cursors();
1276	lprintf("\nWhat do you want to %s [* for all] ? ", str);
1277	i = 0;
1278	while (i > 'z' || (i < 'a' && i != '*' && i != '\33' && i != '.'))
1279		i = lgetchar();
1280	if (i == '\33')
1281		lprcat(" aborted");
1282	return (i);
1283}
1284
1285/*
1286	subroutine to get a number from the player
1287	and allow * to mean return amt, else return the number entered
1288 */
1289unsigned long
1290readnum(mx)
1291	long            mx;
1292{
1293	int    i;
1294	unsigned long amt = 0;
1295	sncbr();
1296	if ((i = lgetchar()) == '*')
1297		amt = mx;	/* allow him to say * for all gold */
1298	else
1299		while (i != '\n') {
1300			if (i == '\033') {
1301				scbr();
1302				lprcat(" aborted");
1303				return (0);
1304			}
1305			if ((i <= '9') && (i >= '0') && (amt < 99999999))
1306				amt = amt * 10 + i - '0';
1307			i = lgetchar();
1308		}
1309	scbr();
1310	return (amt);
1311}
1312
1313#ifdef HIDEBYLINK
1314/*
1315 *	routine to zero every byte in a string
1316 */
1317void
1318szero(str)
1319	char  *str;
1320{
1321	while (*str)
1322		*str++ = 0;
1323}
1324#endif	/* HIDEBYLINK */
1325