main.c revision 1.4
1#ifndef lint
2static 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>
9static char copyright[]="\nLarn is copyrighted 1986 by Noah Morgan.\n";
10int srcount=0;	/* line counter for showstr()	*/
11int dropflag=0; /* if 1 then don't lookforobject() next round */
12int rmst=80;	/*	random monster creation counter		*/
13int userid;		/* the players login user id number */
14char nowelcome=0,nomove=0; /* if (nomove) then don't count next iteration as a move */
15static char viewflag=0;
16	/*	if viewflag then we have done a 99 stay here and don't showcell in the main loop */
17char restorflag=0;	/* 1 means restore has been done	*/
18static char cmdhelp[] = "\
19Cmd 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
31static 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 */
40main(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 */
237showstr()
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
245qshowstr()
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 */
262t_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 */
278t_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 */
292showwear()
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 */
326showwield()
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 */
362showread()
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 */
388showeat()
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 */
414showquaff()
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
437show1(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
445show3(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 */
471randmonst()
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 */
486parse()
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
638parse2()
639	{
640	if (c[HASTEMONST]) movemonst(); movemonst(); /*	move the monsters		*/
641	randmonst();	regen();
642	}
643
644run(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 */
660wield()
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 */
681ydhi(x)
682	int x;
683	{ cursors();  lprintf("\nYou don't have item %c!",x); }
684ycwi(x)
685	int x;
686	{ cursors();  lprintf("\nYou can't wield item %c!",x); }
687
688/*
689	function to wear armor
690 */
691wear()
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 */
719dropobj()
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 */
763readscr()
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 */
785eatcookie()
786{
787register int i;
788char *p;
789while (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 */
818quaff()
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 */
839whatitem(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 */
853unsigned 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 */
875szero(str)
876	register char *str;
877	{
878	while (*str)
879		*str++ = 0;
880	}
881#endif HIDEBYLINK
882