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