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