xref: /dragonfly/games/larn/main.c (revision 2038fb68)
1 /*	main.c		*/
2 /* $FreeBSD: src/games/larn/main.c,v 1.9 1999/11/30 03:48:59 billf Exp $ */
3 /* $DragonFly: src/games/larn/main.c,v 1.5 2008/06/05 18:06:30 swildner Exp $ */
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include "header.h"
7 #include <pwd.h>
8 static const char copyright[]="\nLarn is copyrighted 1986 by Noah Morgan.\n";
9 int srcount=0;	/* line counter for showstr()	*/
10 int dropflag=0; /* if 1 then don't lookforobject() next round */
11 int rmst=80;	/*	random monster creation counter		*/
12 int userid;		/* the players login user id number */
13 char nowelcome=0,nomove=0; /* if (nomove) then don't count next iteration as a move */
14 static char viewflag=0;
15 	/*	if viewflag then we have done a 99 stay here and don't showcell in the main loop */
16 char restorflag=0;	/* 1 means restore has been done	*/
17 static char cmdhelp[] = "\
18 Cmd line format: larn [-slicnh] [-o<optsifle>] [-##] [++]\n\
19   -s   show the scoreboard\n\
20   -l   show the logfile (wizard id only)\n\
21   -i   show scoreboard with inventories of dead characters\n\
22   -c   create new scoreboard (wizard id only)\n\
23   -n   suppress welcome message on starting game\n\
24   -##  specify level of difficulty (example: -5)\n\
25   -h   print this help text\n\
26   ++   restore game from checkpoint file\n\
27   -o<optsfile>   specify .larnopts filename to be used instead of \"~/.larnopts\"\n\
28 ";
29 #ifdef VT100
30 static const char *termtypes[] = { "vt100", "vt101", "vt102", "vt103", "vt125",
31 	"vt131", "vt140", "vt180", "vt220", "vt240", "vt241", "vt320", "vt340",
32 	"vt341"  };
33 #endif /* VT100 */
34 
35 static void	showstr(void);
36 static void	t_setup(int);
37 static void	t_endup(int);
38 static void	showwear(void);
39 static void	showwield(void);
40 static void	showread(void);
41 static void	showeat(void);
42 static void	showquaff(void);
43 static void	show1(int, const char **);
44 static void	randmonst(void);
45 static void	parse(void);
46 static void	run(int);
47 static void	wield(void);
48 static void	ydhi(int);
49 static void	ycwi(int);
50 static void	wear(void);
51 static void	dropobj(void);
52 static void	readscr(void);
53 static void	eatcookie(void);
54 static void	quaff(void);
55 static int	whatitem(const char *);
56 #ifdef HIDEBYLINK
57 static void	szero(char *);
58 #endif
59 
60 /*
61 	************
62 	MAIN PROGRAM
63 	************
64  */
65 int
66 main(int argc, char **argv)
67 	{
68 	int i;
69 	int hard;
70 	const char *ptr;
71 #ifdef VT100
72 	char *ttype;
73 	int j;
74 #endif
75 	struct passwd *pwe;
76 	struct stat sb;
77 
78 /*
79  *	first task is to identify the player
80  */
81 #ifndef VT100
82 	init_term();	/* setup the terminal (find out what type) for termcap */
83 #endif /* VT100 */
84 	if (((ptr = getlogin()) == 0) || (*ptr==0)) {	/* try to get login name */
85 	  if ((pwe=getpwuid(getuid()))) /* can we get it from /etc/passwd? */
86 		ptr = pwe->pw_name;
87 	  else
88 	  if ((ptr = getenv("USER")) == 0)
89 		if ((ptr = getenv("LOGNAME")) == 0)
90 		  {
91 		  noone: write(2, "Can't find your logname.  Who Are You?\n",39);
92 				 exit(1);
93 		  }
94 	}
95 	if (ptr==0) goto noone;
96 	if (strlen(ptr)==0) goto noone;
97 /*
98  *	second task is to prepare the pathnames the player will need
99  */
100 	strcpy(loginname,ptr); /* save loginname of the user for logging purposes */
101 	strcpy(logname,ptr);	/* this will be overwritten with the players name */
102 	if ((ptr = getenv("HOME")) == 0) ptr = ".";
103 	strcpy(savefilename, ptr);
104 	strcat(savefilename, "/Larn.sav");	/* save file name in home directory */
105 	sprintf(optsfile, "%s/.larnopts",ptr);	/* the .larnopts filename */
106 
107 /*
108  *	now malloc the memory for the dungeon
109  */
110 	cell = (struct cel *)malloc(sizeof(struct cel)*(MAXLEVEL+MAXVLEVEL)*MAXX*MAXY);
111 	if (cell == 0) 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)) died(-285); /* malloc() failure */
115 
116 	lcreat(NULL);	newgame();		/*	set the initial clock  */ hard= -1;
117 
118 #ifdef VT100
119 /*
120  *	check terminal type to avoid users who have not vt100 type terminals
121  */
122 	ttype = getenv("TERM");
123 	for (j=1, i=0; i<sizeof(termtypes)/sizeof(char *); i++)
124 		if (strcmp(ttype,termtypes[i]) == 0) { j=0;  break; }
125 	if (j)
126 		{
127 		lprcat("Sorry, Larn needs a VT100 family terminal for all it's features.\n"); lflush();
128 		exit(1);
129 		}
130 #endif /* VT100 */
131 
132 /*
133  *	now make scoreboard if it is not there (don't clear)
134  */
135 	if (stat(scorefile,&sb) < 0 || sb.st_size == 0) /* not there */
136 		makeboard();
137 
138 /*
139  *	now process the command line arguments
140  */
141 	for (i=1; i<argc; i++)
142 		{
143 		if (argv[i][0] == '-')
144 		  switch(argv[i][1])
145 			{
146 			case 's': showscores();  exit(0);  /* show scoreboard   */
147 
148 			case 'l': /* show log file     */
149 						diedlog();              exit(0);
150 
151 			case 'i': showallscores();  exit(0);  /* show all scoreboard */
152 
153 			case 'c': 		 /* anyone with password can create scoreboard */
154 					  lprcat("Preparing to initialize the scoreboard.\n");
155 					  if (getpassword() != 0)  /*make new scoreboard*/
156 							{
157 							makeboard(); lprc('\n'); showscores();
158 							}
159 					  exit(0);
160 
161 			case 'n':	/* no welcome msg	*/ nowelcome=1; argv[i][0]=0; break;
162 
163 			case '0': case '1': case '2': case '3': case '4': case '5':
164 			case '6': case '7': case '8': case '9':	/* for hardness */
165 						sscanf(&argv[i][1],"%d",&hard);
166 						break;
167 
168 			case 'h':	/* print out command line arguments */
169 						write(1,cmdhelp,sizeof(cmdhelp));  exit(0);
170 
171 			case 'o':	/* specify a .larnopts filename */
172 						strncpy(optsfile,argv[i]+2,127);  break;
173 
174 			default:        printf("Unknown option <%s>\n",argv[i]);  exit(1);
175 			};
176 
177 		if (argv[i][0] == '+')
178 			{
179 			clear();	restorflag = 1;
180 			if (argv[i][1] == '+')
181 				{
182 				hitflag=1; restoregame(ckpfile); /* restore checkpointed game */
183 				}
184 			i = argc;
185 			}
186 		}
187 
188 	readopts();		/* read the options file if there is one */
189 
190 
191 #ifdef UIDSCORE
192 	userid = geteuid();	/* obtain the user's effective id number */
193 #else /* UIDSCORE */
194 	userid = getplid(logname);	/* obtain the players id number */
195 #endif /* UIDSCORE */
196 	if (userid < 0) { write(2,"Can't obtain playerid\n",22); exit(1); }
197 
198 #ifdef HIDEBYLINK
199 /*
200  *	this section of code causes the program to look like something else to ps
201  */
202 	if (strcmp(psname,argv[0])) /* if a different process name only */
203 		{
204 		if ((i=access(psname,1)) < 0)
205 			{		/* link not there */
206 			if (link(argv[0],psname)>=0)
207 				{
208 				argv[0] = psname;   execv(psname,argv);
209 				}
210 			}
211 		else
212 			unlink(psname);
213 		}
214 
215 	for (i=1; i<argc; i++)
216 		{
217 		szero(argv[i]);	/* zero the argument to avoid ps snooping */
218 		}
219 #endif /* HIDEBYLINK */
220 
221 	if (access(savefilename,0)==0)	/* restore game if need to */
222 		{
223 		clear();	restorflag = 1;
224 		hitflag=1;	restoregame(savefilename);  /* restore last game	*/
225 		}
226 	sigsetup();		/* trap all needed signals	*/
227 	sethard(hard);	/* set up the desired difficulty				*/
228 	setupvt100();	/*	setup the terminal special mode				*/
229 	if (c[HP]==0)	/* create new game */
230 		{
231 		makeplayer();	/*	make the character that will play			*/
232 		newcavelevel(0);/*	make the dungeon						 	*/
233 		predostuff = 1;	/* tell signals that we are in the welcome screen */
234 		if (nowelcome==0) welcome();	 /* welcome the player to the game */
235 		}
236 	drawscreen();	/*	show the initial dungeon					*/
237 	predostuff = 2;	/* tell the trap functions that they must do a showplayer()
238 						from here on */
239 	/* nice(1); */	/* games should be run niced */
240 	yrepcount = hit2flag = 0;
241 	while (1)
242 		{
243 		if (dropflag==0) lookforobject(); /* see if there is an object here	*/
244 			else dropflag=0; /* don't show it just dropped an item */
245 		if (hitflag==0) { if (c[HASTEMONST]) movemonst(); movemonst(); }	/*	move the monsters		*/
246 		if (viewflag==0) showcell(playerx,playery); else viewflag=0;	/*	show stuff around player	*/
247 		if (hit3flag) flushall();
248 		hitflag=hit3flag=0;	nomove=1;
249 		bot_linex();	/* update bottom line */
250 		while (nomove)
251 			{
252 			if (hit3flag) flushall();
253 			nomove=0; parse();
254 			}	/*	get commands and make moves	*/
255 		regen();			/*	regenerate hp and spells			*/
256 		if (c[TIMESTOP]==0)
257 			if (--rmst <= 0)
258 				{ rmst = 120-(level<<2); fillmonst(makemonst(level)); }
259 		}
260 	}
261 
262 /*
263 	showstr()
264 
265 	show character's inventory
266  */
267 static void
268 showstr(void)
269 	{
270 	int i,number;
271 	for (number=3, i=0; i<26; i++)
272 		if (iven[i]) number++;	/* count items in inventory */
273 	t_setup(number);	qshowstr();	  t_endup(number);
274 	}
275 
276 void
277 qshowstr(void)
278 	{
279 	int i,j,k,sigsav;
280 	srcount=0;  sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
281 	if (c[GOLD]) { lprintf(".)   %d gold pieces",(long)c[GOLD]); srcount++; }
282 	for (k=26; k>=0; k--)
283 	  if (iven[k])
284 		{  for (i=22; i<84; i++)
285 			 for (j=0; j<=k; j++)  if (i==iven[j])  show3(j); k=0; }
286 
287 	lprintf("\nElapsed time is %d.  You have %d mobuls left",(long)((gtime+99)/100+1),(long)((TIMELIMIT-gtime)/100));
288 	more();		nosignal=sigsav;
289 	}
290 
291 /*
292  *	subroutine to clear screen depending on # lines to display
293  */
294 static void
295 t_setup(int count)
296 	{
297 	if (count<20)  /* how do we clear the screen? */
298 		{
299 		cl_up(79,count);  cursor(1,1);
300 		}
301 	else
302 		{
303 		resetscroll(); clear();
304 		}
305 	}
306 
307 /*
308  *	subroutine to restore normal display screen depending on t_setup()
309  */
310 static void
311 t_endup(int count)
312 	{
313 	if (count<18)  /* how did we clear the screen? */
314 		draws(0,MAXX,0,(count>MAXY) ? MAXY : count);
315 	else
316 		{
317 		drawscreen(); setscroll();
318 		}
319 	}
320 
321 /*
322 	function to show the things player is wearing only
323  */
324 static void
325 showwear(void)
326 	{
327 	int i,j,sigsav,count;
328 	sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
329 	srcount=0;
330 
331 	 for (count=2,j=0; j<=26; j++)	 /* count number of items we will display */
332 	   if ((i=iven[j]))
333 		switch(i)
334 			{
335 			case OLEATHER:	case OPLATE:	case OCHAIN:
336 			case ORING:		case OSTUDLEATHER:	case OSPLINT:
337 			case OPLATEARMOR:	case OSSPLATE:	case OSHIELD:
338 			count++;
339 			};
340 
341 	t_setup(count);
342 
343 	for (i=22; i<84; i++)
344 		 for (j=0; j<=26; j++)
345 		   if (i==iven[j])
346 			switch(i)
347 				{
348 				case OLEATHER:	case OPLATE:	case OCHAIN:
349 				case ORING:		case OSTUDLEATHER:	case OSPLINT:
350 				case OPLATEARMOR:	case OSSPLATE:	case OSHIELD:
351 				show3(j);
352 				};
353 	more();		nosignal=sigsav;	t_endup(count);
354 	}
355 
356 /*
357 	function to show the things player can wield only
358  */
359 static void
360 showwield(void)
361 	{
362 	int i,j,sigsav,count;
363 	sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
364 	srcount=0;
365 
366 	 for (count=2,j=0; j<=26; j++)	/* count how many items */
367 	   if ((i=iven[j]))
368 		switch(i)
369 			{
370 			case ODIAMOND:  case ORUBY:  case OEMERALD:  case OSAPPHIRE:
371 			case OBOOK:     case OCHEST:  case OLARNEYE: case ONOTHEFT:
372 			case OSPIRITSCARAB:  case OCUBEofUNDEAD:
373 			case OPOTION:   case OSCROLL:  break;
374 			default:  count++;
375 			};
376 
377 	t_setup(count);
378 
379 	for (i=22; i<84; i++)
380 		 for (j=0; j<=26; j++)
381 		   if (i==iven[j])
382 			switch(i)
383 				{
384 				case ODIAMOND:  case ORUBY:  case OEMERALD:  case OSAPPHIRE:
385 				case OBOOK:     case OCHEST:  case OLARNEYE: case ONOTHEFT:
386 				case OSPIRITSCARAB:  case OCUBEofUNDEAD:
387 				case OPOTION:   case OSCROLL:  break;
388 				default:  show3(j);
389 				};
390 	more();		nosignal=sigsav;	t_endup(count);
391 	}
392 
393 /*
394  *	function to show the things player can read only
395  */
396 static void
397 showread(void)
398 	{
399 	int i,j,sigsav,count;
400 	sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
401 	srcount=0;
402 
403 	for (count=2,j=0; j<=26; j++)
404 		switch(iven[j])
405 			{
406 			case OBOOK:	case OSCROLL:	count++;
407 			};
408 	t_setup(count);
409 
410 	for (i=22; i<84; i++)
411 		 for (j=0; j<=26; j++)
412 		   if (i==iven[j])
413 			switch(i)
414 				{
415 				case OBOOK:	case OSCROLL:	show3(j);
416 				};
417 	more();		nosignal=sigsav;	t_endup(count);
418 	}
419 
420 /*
421  *	function to show the things player can eat only
422  */
423 static void
424 showeat(void)
425 	{
426 	int i,j,sigsav,count;
427 	sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
428 	srcount=0;
429 
430 	for (count=2,j=0; j<=26; j++)
431 		switch(iven[j])
432 			{
433 			case OCOOKIE:	count++;
434 			};
435 	t_setup(count);
436 
437 	for (i=22; i<84; i++)
438 		 for (j=0; j<=26; j++)
439 		   if (i==iven[j])
440 			switch(i)
441 				{
442 				case OCOOKIE:	show3(j);
443 				};
444 	more();		nosignal=sigsav;	t_endup(count);
445 	}
446 
447 /*
448 	function to show the things player can quaff only
449  */
450 static void
451 showquaff(void)
452 	{
453 	int i,j,sigsav,count;
454 	sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
455 	srcount=0;
456 
457 	for (count=2,j=0; j<=26; j++)
458 		switch(iven[j])
459 			{
460 			case OPOTION:	count++;
461 			};
462 	t_setup(count);
463 
464 	for (i=22; i<84; i++)
465 		 for (j=0; j<=26; j++)
466 		   if (i==iven[j])
467 			switch(i)
468 				{
469 				case OPOTION:	show3(j);
470 				};
471 	more();		nosignal=sigsav;		t_endup(count);
472 	}
473 
474 static void
475 show1(int idx, const char *str2[])
476 	{
477 	lprintf("\n%c)   %s",idx+'a',objectname[(int)iven[idx]]);
478 	if(str2 != NULL && str2[ivenarg[idx]][0] != 0)
479 		lprintf(" of%s", str2[ivenarg[idx]]);
480 	}
481 
482 void
483 show3(int idx)
484 	{
485 	switch(iven[idx])
486 		{
487 		case OPOTION:	show1(idx,potionname);  break;
488 		case OSCROLL:	show1(idx,scrollname);  break;
489 
490 		case OLARNEYE:		case OBOOK:			case OSPIRITSCARAB:
491 		case ODIAMOND:		case ORUBY:			case OCUBEofUNDEAD:
492 		case OEMERALD:		case OCHEST:		case OCOOKIE:
493 		case OSAPPHIRE:		case ONOTHEFT:		show1(idx,NULL);  break;
494 
495 		default:		lprintf("\n%c)   %s",idx+'a',objectname[(int)iven[idx]]);
496 						if (ivenarg[idx]>0) lprintf(" + %d",(long)ivenarg[idx]);
497 						else if (ivenarg[idx]<0) lprintf(" %d",(long)ivenarg[idx]);
498 						break;
499 		}
500 	if (c[WIELD]==idx) lprcat(" (weapon in hand)");
501 	if ((c[WEAR]==idx) || (c[SHIELD]==idx))  lprcat(" (being worn)");
502 	if (++srcount>=22) { srcount=0; more(); clear(); }
503 	}
504 
505 /*
506 	subroutine to randomly create monsters if needed
507  */
508 static void
509 randmonst(void)
510 	{
511 	if (c[TIMESTOP]) return;	/*	don't make monsters if time is stopped	*/
512 	if (--rmst <= 0)
513 		{
514 		rmst = 120 - (level<<2);  fillmonst(makemonst(level));
515 		}
516 	}
517 
518 
519 /*
520 	parse()
521 
522 	get and execute a command
523  */
524 static void
525 parse(void)
526 	{
527 	int i,j,k,flag;
528 	while	(1)
529 		{
530 		k = yylex();
531 		switch(k)	/*	get the token from the input and switch on it	*/
532 			{
533 			case 'h':	moveplayer(4);	return;		/*	west		*/
534 			case 'H':	run(4);			return;		/*	west		*/
535 			case 'l':	moveplayer(2);	return;		/*	east		*/
536 			case 'L':	run(2);			return;		/*	east		*/
537 			case 'j':	moveplayer(1);	return;		/*	south		*/
538 			case 'J':	run(1);			return;		/*	south		*/
539 			case 'k':	moveplayer(3);	return;		/*	north		*/
540 			case 'K':	run(3);			return;		/*	north		*/
541 			case 'u':	moveplayer(5);	return;		/*	northeast	*/
542 			case 'U':	run(5);			return;		/*	northeast	*/
543 			case 'y':	moveplayer(6);  return;		/*	northwest	*/
544 			case 'Y':	run(6);			return;		/*	northwest	*/
545 			case 'n':	moveplayer(7);	return;		/*	southeast	*/
546 			case 'N':	run(7);			return;		/*	southeast	*/
547 			case 'b':	moveplayer(8);	return;		/*	southwest	*/
548 			case 'B':	run(8);			return;		/*	southwest	*/
549 
550 			case '.':	if (yrepcount) viewflag=1; return;		/*	stay here		*/
551 
552 			case 'w':	yrepcount=0;	wield();	return;		/*	wield a weapon */
553 
554 			case 'W':	yrepcount=0;	wear();		return;	/*	wear armor	*/
555 
556 			case 'r':	yrepcount=0;
557 						if (c[BLINDCOUNT]) { cursors(); lprcat("\nYou can't read anything when you're blind!"); } else
558 						if (c[TIMESTOP]==0) readscr(); return;		/*	to read a scroll	*/
559 
560 			case 'q':	yrepcount=0;	if (c[TIMESTOP]==0) quaff();	return;	/*	quaff a potion		*/
561 
562 			case 'd':	yrepcount=0;	if (c[TIMESTOP]==0) dropobj(); return;	/*	to drop an object	*/
563 
564 			case 'c':	yrepcount=0;	cast();		return;		/*	cast a spell	*/
565 
566 			case 'i':	yrepcount=0;	nomove=1;  showstr();	return;		/*	status		*/
567 
568 			case 'e':	yrepcount=0;
569 						if (c[TIMESTOP]==0) eatcookie(); return;	/*	to eat a fortune cookie */
570 
571 			case 'D':	yrepcount=0;	seemagic(0);	nomove=1; return;	/*	list spells and scrolls */
572 
573 			case '?':	yrepcount=0;	help(); nomove=1; return;	/*	give the help screen*/
574 
575 			case 'S':	clear();  lprcat("Saving . . ."); lflush();
576 						savegame(savefilename); wizard=1; died(-257);	/*	save the game - doesn't return	*/
577 
578 			case 'Z':	yrepcount=0;	if (c[LEVEL]>9) { oteleport(1); return; }
579 						cursors(); lprcat("\nAs yet, you don't have enough experience to use teleportation");
580 						return;	/*	teleport yourself	*/
581 
582 			case '^':	/* identify traps */  flag=yrepcount=0;  cursors();
583 						lprc('\n');  for (j=playery-1; j<playery+2; j++)
584 							{
585 							if (j < 0) j=0;		if (j >= MAXY) break;
586 							for (i=playerx-1; i<playerx+2; i++)
587 								{
588 								if (i < 0) i=0;	if (i >= MAXX) break;
589 								switch(item[i][j])
590 									{
591 									case OTRAPDOOR:		case ODARTRAP:
592 									case OTRAPARROW:	case OTELEPORTER:
593 										lprcat("\nIts "); lprcat(objectname[(int)item[i][j]]);  flag++;
594 									};
595 								}
596 							}
597 						if (flag==0) lprcat("\nNo traps are visible");
598 						return;
599 
600 #if WIZID
601 			case '_':	/*	this is the fudge player password for wizard mode*/
602 						yrepcount=0;	cursors(); nomove=1;
603 						if (userid!=wisid)
604 							{
605 							lprcat("Sorry, you are not empowered to be a wizard.\n");
606 							scbr(); /* system("stty -echo cbreak"); */
607 							lflush();  return;
608 							}
609 						if (getpassword()==0)
610 							{
611 							scbr(); /* system("stty -echo cbreak"); */ return;
612 							}
613 						wizard=1;  scbr(); /* system("stty -echo cbreak"); */
614 						for (i=0; i<6; i++)  c[i]=70;  iven[0]=iven[1]=0;
615 						take(OPROTRING,50);   take(OLANCE,25);  c[WIELD]=1;
616 						c[LANCEDEATH]=1;   c[WEAR] = c[SHIELD] = -1;
617 						raiseexperience(6000000L);  c[AWARENESS] += 25000;
618 						{
619 						int i,j;
620 						for (i=0; i<MAXY; i++)
621 							for (j=0; j<MAXX; j++)  know[j][i]=1;
622 						for (i=0; i<SPNUM; i++)	spelknow[i]=1;
623 						for (i=0; i<MAXSCROLL; i++)  scrollname[i] = scrollhide[i];
624 						for (i=0; i<MAXPOTION; i++)  potionname[i] = potionhide[i];
625 						}
626 						for (i=0; i<MAXSCROLL; i++)
627 						  if (strlen(scrollname[i])>2) /* no null items */
628 							{ item[i][0]=OSCROLL; iarg[i][0]=i; }
629 						for (i=MAXX-1; i>MAXX-1-MAXPOTION; i--)
630 						  if (strlen(potionname[i-MAXX+MAXPOTION])>2) /* no null items */
631 							{ item[i][0]=OPOTION; iarg[i][0]=i-MAXX+MAXPOTION; }
632 						for (i=1; i<MAXY; i++)
633 							{ item[0][i]=i; iarg[0][i]=0; }
634 						for (i=MAXY; i<MAXY+MAXX; i++)
635 							{ item[i-MAXY][MAXY-1]=i; iarg[i-MAXY][MAXY-1]=0; }
636 						for (i=MAXX+MAXY; i<MAXX+MAXY+MAXY; i++)
637 							{ item[MAXX-1][i-MAXX-MAXY]=i; iarg[MAXX-1][i-MAXX-MAXY]=0; }
638 						c[GOLD]+=25000;	drawscreen();	return;
639 #endif
640 
641 			case 'T':	yrepcount=0;	cursors();  if (c[SHIELD] != -1) { c[SHIELD] = -1; lprcat("\nYour shield is off"); bottomline(); } else
642 										if (c[WEAR] != -1) { c[WEAR] = -1; lprcat("\nYour armor is off"); bottomline(); }
643 						else lprcat("\nYou aren't wearing anything");
644 						return;
645 
646 			case 'g':	cursors();
647 						lprintf("\nThe stuff you are carrying presently weighs %d pounds",(long)packweight());
648 			case ' ':	yrepcount=0;	nomove=1;  return;
649 
650 			case 'v':	yrepcount=0;	cursors();
651 						lprintf("\nCaverns of Larn, Version %d.%d, Diff=%d",(long)VERSION,(long)SUBVERSION,(long)c[HARDGAME]);
652 						if (wizard) lprcat(" Wizard"); nomove=1;
653 						if (cheat) lprcat(" Cheater");
654 						lprcat(copyright);
655 						return;
656 
657 			case 'Q':	yrepcount=0;	quit(); nomove=1;	return;	/*	quit		*/
658 
659 			case 'L'-64:  yrepcount=0;	drawscreen();  nomove=1; return;	/*	look		*/
660 
661 #if WIZID
662 #ifdef EXTRA
663 			case 'A':	yrepcount=0;	nomove=1; if (wizard) { diag(); return; }  /*	create diagnostic file */
664 						return;
665 #endif
666 #endif
667 			case 'P':	cursors();
668 						if (outstanding_taxes>0)
669 							lprintf("\nYou presently owe %d gp in taxes.",(long)outstanding_taxes);
670 						else
671 							lprcat("\nYou do not owe any taxes.");
672 						return;
673 			};
674 		}
675 	}
676 
677 void
678 parse2(void)
679 	{
680 	if (c[HASTEMONST]) movemonst(); movemonst(); /*	move the monsters		*/
681 	randmonst();	regen();
682 	}
683 
684 static void
685 run(int dir)
686 	{
687 	int i;
688 	i=1; while (i)
689 		{
690 		i=moveplayer(dir);
691 		if (i>0) {  if (c[HASTEMONST]) movemonst();  movemonst(); randmonst(); regen(); }
692 		if (hitflag) i=0;
693 		if (i!=0)  showcell(playerx,playery);
694 		}
695 	}
696 
697 /*
698 	function to wield a weapon
699  */
700 static void
701 wield(void)
702 	{
703 	int i;
704 	while (1)
705 		{
706 		if ((i = whatitem("wield"))=='\33')  return;
707 		if (i != '.')
708 			{
709 			if (i=='*') showwield();
710 			else  if (iven[i-'a']==0) { ydhi(i); return; }
711 			else if (iven[i-'a']==OPOTION) { ycwi(i); return; }
712 			else if (iven[i-'a']==OSCROLL) { ycwi(i); return; }
713 			else  if ((c[SHIELD]!= -1) && (iven[i-'a']==O2SWORD)) { lprcat("\nBut one arm is busy with your shield!"); return; }
714 			else  { c[WIELD]=i-'a'; if (iven[i-'a'] == OLANCE) c[LANCEDEATH]=1; else c[LANCEDEATH]=0;  bottomline(); return; }
715 			}
716 		}
717 	}
718 
719 /*
720 	common routine to say you don't have an item
721  */
722 static void
723 ydhi(int x)
724 	{ cursors();  lprintf("\nYou don't have item %c!",x); }
725 
726 static void
727 ycwi(int x)
728 	{ cursors();  lprintf("\nYou can't wield item %c!",x); }
729 
730 /*
731 	function to wear armor
732  */
733 static void
734 wear(void)
735 	{
736 	int i;
737 	while (1)
738 		{
739 		if ((i = whatitem("wear"))=='\33')  return;
740 		if (i != '.')
741 			{
742 			if (i=='*') showwear(); else
743 			switch(iven[i-'a'])
744 				{
745 				case 0:  ydhi(i); return;
746 				case OLEATHER:  case OCHAIN:  case OPLATE:	case OSTUDLEATHER:
747 				case ORING:		case OSPLINT:	case OPLATEARMOR:	case OSSPLATE:
748 						if (c[WEAR] != -1) { lprcat("\nYou're already wearing some armor"); return; }
749 							c[WEAR]=i-'a';  bottomline(); return;
750 				case OSHIELD:	if (c[SHIELD] != -1) { lprcat("\nYou are already wearing a shield"); return; }
751 								if (iven[c[WIELD]]==O2SWORD) { lprcat("\nYour hands are busy with the two handed sword!"); return; }
752 								c[SHIELD] = i-'a';  bottomline(); return;
753 				default:	lprcat("\nYou can't wear that!");
754 				};
755 			}
756 		}
757 	}
758 
759 /*
760 	function to drop an object
761  */
762 static void
763 dropobj(void)
764 	{
765 	int i;
766 	char *p;
767 	long amt;
768 	p = &item[playerx][playery];
769 	while (1)
770 		{
771 		if ((i = whatitem("drop"))=='\33')  return;
772 		if (i=='*') showstr(); else
773 			{
774 			if (i=='.')	/* drop some gold */
775 				{
776 				if (*p) { lprcat("\nThere's something here already!"); return; }
777 				lprcat("\n\n");
778 				cl_dn(1,23);
779 				lprcat("How much gold do you drop? ");
780 				if ((amt=readnum((long)c[GOLD])) == 0) return;
781 				if (amt>c[GOLD])
782 					{ lprcat("\nYou don't have that much!"); return; }
783 				if (amt<=32767)
784 					{ *p=OGOLDPILE; i=amt; }
785 				else if (amt<=327670L)
786 					{ *p=ODGOLD; i=amt/10; amt = 10*i; }
787 				else if (amt<=3276700L)
788 					{ *p=OMAXGOLD; i=amt/100; amt = 100*i; }
789 				else if (amt<=32767000L)
790 					{ *p=OKGOLD; i=amt/1000; amt = 1000*i; }
791 				else
792 					{ *p=OKGOLD; i=32767; amt = 32767000L; }
793 				c[GOLD] -= amt;
794 				lprintf("You drop %d gold pieces",(long)amt);
795 				iarg[playerx][playery]=i; bottomgold();
796 				know[playerx][playery]=0; dropflag=1;  return;
797 				}
798 			drop_object(i-'a');
799 			return;
800 			}
801 		}
802 	}
803 
804 /*
805  *	readscr()		Subroutine to read a scroll one is carrying
806  */
807 static void
808 readscr(void)
809 	{
810 	int i;
811 	while (1)
812 		{
813 		if ((i = whatitem("read"))=='\33')  return;
814 		if (i != '.')
815 			{
816 			if (i=='*') showread(); else
817 				{
818 				if (iven[i-'a']==OSCROLL) { read_scroll(ivenarg[i-'a']); iven[i-'a']=0; return; }
819 				if (iven[i-'a']==OBOOK)   { readbook(ivenarg[i-'a']);  iven[i-'a']=0; return; }
820 				if (iven[i-'a']==0) { ydhi(i); return; }
821 				lprcat("\nThere's nothing on it to read");  return;
822 				}
823 			}
824 		}
825 	}
826 
827 /*
828  *	subroutine to eat a cookie one is carrying
829  */
830 static void
831 eatcookie(void)
832 {
833 int i;
834 const char *p;
835 while (1)
836 	{
837 	if ((i = whatitem("eat"))=='\33')  return;
838 	if (i != '.') {
839 		if (i=='*') showeat(); else
840 			{
841 			if (iven[i-'a']==OCOOKIE)
842 				{
843 				lprcat("\nThe cookie was delicious.");
844 				iven[i-'a']=0;
845 				if (!c[BLINDCOUNT])
846 					{
847 					if ((p=fortune()))
848 						{
849 						lprcat("  Inside you find a scrap of paper that says:\n");
850 						lprcat(p);
851 						}
852 					}
853 				return;
854 				}
855 			if (iven[i-'a']==0) { ydhi(i); return; }
856 			lprcat("\nYou can't eat that!");  return;
857 			}
858 		 }
859 	}
860 }
861 
862 /*
863  *	subroutine to quaff a potion one is carrying
864  */
865 static void
866 quaff(void)
867 	{
868 	int i;
869 	while (1)
870 		{
871 		if ((i = whatitem("quaff"))=='\33')  return;
872 		if (i != '.')
873 			{
874 			if (i=='*') showquaff(); else
875 				{
876 				if (iven[i-'a']==OPOTION) { quaffpotion(ivenarg[i-'a']); iven[i-'a']=0; return; }
877 				if (iven[i-'a']==0) { ydhi(i); return; }
878 				lprcat("\nYou wouldn't want to quaff that, would you? ");  return;
879 				}
880 			}
881 		}
882 	}
883 
884 /*
885 	function to ask what player wants to do
886  */
887 static int
888 whatitem(const char *str)
889 	{
890 	int i;
891 	cursors();  lprintf("\nWhat do you want to %s [* for all] ? ",str);
892 	i=0; while (i>'z' || (i<'a' && i!='*' && i!='\33' && i!='.')) i=getchr();
893 	if (i=='\33')  lprcat(" aborted");
894 	return(i);
895 	}
896 
897 /*
898 	subroutine to get a number from the player
899 	and allow * to mean return amt, else return the number entered
900  */
901 unsigned long
902 readnum(long mx)
903 	{
904 	int i;
905 	unsigned long amt=0;
906 	sncbr();
907 	if ((i=getchr()) == '*')  amt = mx;   /* allow him to say * for all gold */
908 	else
909 		while (i != '\n')
910 			{
911 			if (i=='\033') { scbr(); lprcat(" aborted"); return(0); }
912 			if ((i <= '9') && (i >= '0') && (amt<99999999))
913 				amt = amt*10+i-'0';
914 			i = getchr();
915 			}
916 	scbr();  return(amt);
917 	}
918 
919 #ifdef HIDEBYLINK
920 /*
921  *	routine to zero every byte in a string
922  */
923 static void
924 szero(char *str)
925 	{
926 	while (*str)
927 		*str++ = 0;
928 	}
929 #endif /* HIDEBYLINK */
930