main.c revision 1.7
1#ifndef lint
2static char rcsid[] = "$NetBSD: main.c,v 1.7 1995/04/24 12:24:01 cgd Exp $";
3#endif /* not lint */
4
5/*	main.c		*/
6#include <sys/types.h>
7#include "header.h"
8#include <pwd.h>
9#include <string.h>
10
11static char copyright[]="\nLarn is copyrighted 1986 by Noah Morgan.\n";
12int srcount=0;	/* line counter for showstr()	*/
13int dropflag=0; /* if 1 then don't lookforobject() next round */
14int rmst=80;	/*	random monster creation counter		*/
15int userid;		/* the players login user id number */
16char nowelcome=0,nomove=0; /* if (nomove) then don't count next iteration as a move */
17static char viewflag=0;
18	/*	if viewflag then we have done a 99 stay here and don't showcell in the main loop */
19char restorflag=0;	/* 1 means restore has been done	*/
20static char cmdhelp[] = "\
21Cmd line format: larn [-slicnh] [-o<optsifle>] [-##] [++]\n\
22  -s   show the scoreboard\n\
23  -l   show the logfile (wizard id only)\n\
24  -i   show scoreboard with inventories of dead characters\n\
25  -c   create new scoreboard (wizard id only)\n\
26  -n   suppress welcome message on starting game\n\
27  -##  specify level of difficulty (example: -5)\n\
28  -h   print this help text\n\
29  ++   restore game from checkpoint file\n\
30  -o<optsfile>   specify .larnopts filename to be used instead of \"~/.larnopts\"\n\
31";
32#ifdef VT100
33static char *termtypes[] = { "vt100", "vt101", "vt102", "vt103", "vt125",
34	"vt131", "vt140", "vt180", "vt220", "vt240", "vt241", "vt320", "vt340",
35	"vt341"  };
36#endif VT100
37/*
38	************
39	MAIN PROGRAM
40	************
41 */
42main(argc,argv)
43	int argc;
44	char **argv;
45	{
46	register int i,j;
47	int hard;
48	char *ptr=0,*ttype;
49	struct passwd *pwe;
50
51/*
52 *	first task is to identify the player
53 */
54#ifndef VT100
55	init_term();	/* setup the terminal (find out what type) for termcap */
56#endif VT100
57	if (((ptr = getlogin()) == 0) || (*ptr==0))	/* try to get login name */
58	  if (pwe=getpwuid(getuid())) /* can we get it from /etc/passwd? */
59		ptr = pwe->pw_name;
60	  else
61	  if ((ptr = getenv("USER")) == 0)
62		if ((ptr = getenv("LOGNAME")) == 0)
63		  {
64		  noone: write(2, "Can't find your logname.  Who Are You?\n",39);
65		 		 exit();
66		  }
67	if (ptr==0) goto noone;
68	if (strlen(ptr)==0) goto noone;
69/*
70 *	second task is to prepare the pathnames the player will need
71 */
72	strcpy(loginname,ptr); /* save loginname of the user for logging purposes */
73	strcpy(logname,ptr);	/* this will be overwritten with the players name */
74	if ((ptr = getenv("HOME")) == 0) ptr = ".";
75	strcpy(savefilename, ptr);
76	strcat(savefilename, "/Larn.sav");	/* save file name in home directory */
77	sprintf(optsfile, "%s/.larnopts",ptr);	/* the .larnopts filename */
78
79/*
80 *	now malloc the memory for the dungeon
81 */
82	cell = (struct cel *)malloc(sizeof(struct cel)*(MAXLEVEL+MAXVLEVEL)*MAXX*MAXY);
83	if (cell == 0) died(-285);	/* malloc failure */
84	lpbuf    = malloc((5* BUFBIG)>>2);	/* output buffer */
85	inbuffer = malloc((5*MAXIBUF)>>2);	/* output buffer */
86	if ((lpbuf==0) || (inbuffer==0)) died(-285); /* malloc() failure */
87
88	lcreat((char*)0);	newgame();		/*	set the initial clock  */ hard= -1;
89
90#ifdef VT100
91/*
92 *	check terminal type to avoid users who have not vt100 type terminals
93 */
94	ttype = getenv("TERM");
95	for (j=1, i=0; i<sizeof(termtypes)/sizeof(char *); i++)
96		if (strcmp(ttype,termtypes[i]) == 0) { j=0;  break; }
97	if (j)
98		{
99		lprcat("Sorry, Larn needs a VT100 family terminal for all it's features.\n"); lflush();
100		exit();
101		}
102#endif VT100
103
104/*
105 *	now make scoreboard if it is not there (don't clear)
106 */
107	if (access(scorefile,0) == -1) /* not there */
108		makeboard();
109
110/*
111 *	now process the command line arguments
112 */
113	for (i=1; i<argc; i++)
114		{
115		if (argv[i][0] == '-')
116		  switch(argv[i][1])
117			{
118			case 's': showscores();  exit();  /* show scoreboard   */
119
120			case 'l': /* show log file     */
121						diedlog();		exit();
122
123			case 'i': showallscores();  exit();  /* show all scoreboard */
124
125			case 'c': 		 /* anyone with password can create scoreboard */
126					  lprcat("Preparing to initialize the scoreboard.\n");
127					  if (getpassword() != 0)  /*make new scoreboard*/
128							{
129							makeboard(); lprc('\n'); showscores();
130							}
131					  exit();
132
133			case 'n':	/* no welcome msg	*/ nowelcome=1; argv[i][0]=0; break;
134
135			case '0': case '1': case '2': case '3': case '4': case '5':
136			case '6': case '7': case '8': case '9':	/* for hardness */
137						sscanf(&argv[i][1],"%d",&hard);
138						break;
139
140			case 'h':	/* print out command line arguments */
141						write(1,cmdhelp,sizeof(cmdhelp));  exit();
142
143			case 'o':	/* specify a .larnopts filename */
144						strncpy(optsfile,argv[i]+2,127);  break;
145
146			default:	printf("Unknown option <%s>\n",argv[i]);  exit();
147			};
148
149		if (argv[i][0] == '+')
150			{
151			clear();	restorflag = 1;
152			if (argv[i][1] == '+')
153				{
154				hitflag=1; restoregame(ckpfile); /* restore checkpointed game */
155				}
156			i = argc;
157			}
158		}
159
160	readopts();		/* read the options file if there is one */
161
162
163#ifdef UIDSCORE
164	userid = geteuid();	/* obtain the user's effective id number */
165#else UIDSCORE
166	userid = getplid(logname);	/* obtain the players id number */
167#endif UIDSCORE
168	if (userid < 0) { write(2,"Can't obtain playerid\n",22); exit(); }
169
170#ifdef HIDEBYLINK
171/*
172 *	this section of code causes the program to look like something else to ps
173 */
174	if (strcmp(psname,argv[0])) /* if a different process name only */
175		{
176		if ((i=access(psname,1)) < 0)
177			{		/* link not there */
178			if (link(argv[0],psname)>=0)
179				{
180				argv[0] = psname;   execv(psname,argv);
181				}
182			}
183		else
184			unlink(psname);
185		}
186
187	for (i=1; i<argc; i++)
188		{
189		szero(argv[i]);	/* zero the argument to avoid ps snooping */
190		}
191#endif HIDEBYLINK
192
193	if (access(savefilename,0)==0)	/* restore game if need to */
194		{
195		clear();	restorflag = 1;
196		hitflag=1;	restoregame(savefilename);  /* restore last game	*/
197		}
198	sigsetup();		/* trap all needed signals	*/
199	sethard(hard);	/* set up the desired difficulty				*/
200	setupvt100();	/*	setup the terminal special mode				*/
201	if (c[HP]==0)	/* create new game */
202		{
203		makeplayer();	/*	make the character that will play			*/
204		newcavelevel(0);/*	make the dungeon						 	*/
205		predostuff = 1;	/* tell signals that we are in the welcome screen */
206		if (nowelcome==0) welcome();	 /* welcome the player to the game */
207		}
208	drawscreen();	/*	show the initial dungeon					*/
209	predostuff = 2;	/* tell the trap functions that they must do a showplayer()
210						from here on */
211	/* nice(1);	/* games should be run niced */
212	yrepcount = hit2flag = 0;
213	while (1)
214		{
215		if (dropflag==0) lookforobject(); /* see if there is an object here	*/
216			else dropflag=0; /* don't show it just dropped an item */
217		if (hitflag==0) { if (c[HASTEMONST]) movemonst(); movemonst(); }	/*	move the monsters		*/
218		if (viewflag==0) showcell(playerx,playery); else viewflag=0;	/*	show stuff around player	*/
219		if (hit3flag) flushall();
220		hitflag=hit3flag=0;	nomove=1;
221		bot_linex();	/* update bottom line */
222		while (nomove)
223			{
224			if (hit3flag) flushall();
225			nomove=0; parse();
226			}	/*	get commands and make moves	*/
227		regen();			/*	regenerate hp and spells			*/
228		if (c[TIMESTOP]==0)
229			if (--rmst <= 0)
230				{ rmst = 120-(level<<2); fillmonst(makemonst(level)); }
231		}
232	}
233
234/*
235	showstr()
236
237	show character's inventory
238 */
239showstr()
240	{
241	register int i,number;
242	for (number=3, i=0; i<26; i++)
243		if (iven[i]) number++;	/* count items in inventory */
244	t_setup(number);	qshowstr();	  t_endup(number);
245	}
246
247qshowstr()
248	{
249	register int i,j,k,sigsav;
250	srcount=0;  sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
251	if (c[GOLD]) { lprintf(".)   %d gold pieces",(long)c[GOLD]); srcount++; }
252	for (k=26; k>=0; k--)
253	  if (iven[k])
254		{  for (i=22; i<84; i++)
255			 for (j=0; j<=k; j++)  if (i==iven[j])  show3(j); k=0; }
256
257	lprintf("\nElapsed time is %d.  You have %d mobuls left",(long)((gtime+99)/100+1),(long)((TIMELIMIT-gtime)/100));
258	more();		nosignal=sigsav;
259	}
260
261/*
262 *	subroutine to clear screen depending on # lines to display
263 */
264t_setup(count)
265	register int count;
266	{
267	if (count<20)  /* how do we clear the screen? */
268		{
269		cl_up(79,count);  cursor(1,1);
270		}
271	else
272		{
273		resetscroll(); clear();
274		}
275	}
276
277/*
278 *	subroutine to restore normal display screen depending on t_setup()
279 */
280t_endup(count)
281	register int count;
282	{
283	if (count<18)  /* how did we clear the screen? */
284		draws(0,MAXX,0,(count>MAXY) ? MAXY : count);
285	else
286		{
287		drawscreen(); setscroll();
288		}
289	}
290
291/*
292	function to show the things player is wearing only
293 */
294showwear()
295	{
296	register int i,j,sigsav,count;
297	sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
298	srcount=0;
299
300	 for (count=2,j=0; j<=26; j++)	 /* count number of items we will display */
301	   if (i=iven[j])
302		switch(i)
303			{
304			case OLEATHER:	case OPLATE:	case OCHAIN:
305			case ORING:		case OSTUDLEATHER:	case OSPLINT:
306			case OPLATEARMOR:	case OSSPLATE:	case OSHIELD:
307			count++;
308			};
309
310	t_setup(count);
311
312	for (i=22; i<84; i++)
313		 for (j=0; j<=26; j++)
314		   if (i==iven[j])
315			switch(i)
316				{
317				case OLEATHER:	case OPLATE:	case OCHAIN:
318				case ORING:		case OSTUDLEATHER:	case OSPLINT:
319				case OPLATEARMOR:	case OSSPLATE:	case OSHIELD:
320				show3(j);
321				};
322	more();		nosignal=sigsav;	t_endup(count);
323	}
324
325/*
326	function to show the things player can wield only
327 */
328showwield()
329	{
330	register int i,j,sigsav,count;
331	sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
332	srcount=0;
333
334	 for (count=2,j=0; j<=26; j++)	/* count how many items */
335	   if (i=iven[j])
336		switch(i)
337			{
338			case ODIAMOND:  case ORUBY:  case OEMERALD:  case OSAPPHIRE:
339			case OBOOK:     case OCHEST:  case OLARNEYE: case ONOTHEFT:
340			case OSPIRITSCARAB:  case OCUBEofUNDEAD:
341			case OPOTION:   case OSCROLL:  break;
342			default:  count++;
343			};
344
345	t_setup(count);
346
347	for (i=22; i<84; i++)
348		 for (j=0; j<=26; j++)
349		   if (i==iven[j])
350			switch(i)
351				{
352				case ODIAMOND:  case ORUBY:  case OEMERALD:  case OSAPPHIRE:
353				case OBOOK:     case OCHEST:  case OLARNEYE: case ONOTHEFT:
354				case OSPIRITSCARAB:  case OCUBEofUNDEAD:
355				case OPOTION:   case OSCROLL:  break;
356				default:  show3(j);
357				};
358	more();		nosignal=sigsav;	t_endup(count);
359	}
360
361/*
362 *	function to show the things player can read only
363 */
364showread()
365	{
366	register int i,j,sigsav,count;
367	sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
368	srcount=0;
369
370	for (count=2,j=0; j<=26; j++)
371		switch(iven[j])
372			{
373			case OBOOK:	case OSCROLL:	count++;
374			};
375	t_setup(count);
376
377	for (i=22; i<84; i++)
378		 for (j=0; j<=26; j++)
379		   if (i==iven[j])
380			switch(i)
381				{
382				case OBOOK:	case OSCROLL:	show3(j);
383				};
384	more();		nosignal=sigsav;	t_endup(count);
385	}
386
387/*
388 *	function to show the things player can eat only
389 */
390showeat()
391	{
392	register int i,j,sigsav,count;
393	sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
394	srcount=0;
395
396	for (count=2,j=0; j<=26; j++)
397		switch(iven[j])
398			{
399			case OCOOKIE:	count++;
400			};
401	t_setup(count);
402
403	for (i=22; i<84; i++)
404		 for (j=0; j<=26; j++)
405		   if (i==iven[j])
406			switch(i)
407				{
408				case OCOOKIE:	show3(j);
409				};
410	more();		nosignal=sigsav;	t_endup(count);
411	}
412
413/*
414	function to show the things player can quaff only
415 */
416showquaff()
417	{
418	register int i,j,sigsav,count;
419	sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
420	srcount=0;
421
422	for (count=2,j=0; j<=26; j++)
423		switch(iven[j])
424			{
425			case OPOTION:	count++;
426			};
427	t_setup(count);
428
429	for (i=22; i<84; i++)
430		 for (j=0; j<=26; j++)
431		   if (i==iven[j])
432			switch(i)
433				{
434				case OPOTION:	show3(j);
435				};
436	more();		nosignal=sigsav;		t_endup(count);
437	}
438
439show1(idx,str2)
440	register int idx;
441	register char *str2[];
442	{
443	lprintf("\n%c)   %s",idx+'a',objectname[iven[idx]]);
444	if (str2!=0 && str2[ivenarg[idx]][0]!=0)  lprintf(" of%s",str2[ivenarg[idx]]);
445	}
446
447show3(index)
448	register 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 */
473randmonst()
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 */
488parse()
489	{
490	register 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						register 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]=scrollhide[i];
587						for (i=0; i<MAXPOTION; i++)  potionname[i]=potionhide[i];
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
640parse2()
641	{
642	if (c[HASTEMONST]) movemonst(); movemonst(); /*	move the monsters		*/
643	randmonst();	regen();
644	}
645
646run(dir)
647	int dir;
648	{
649	register 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 */
662wield()
663	{
664	register 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 */
683ydhi(x)
684	int x;
685	{ cursors();  lprintf("\nYou don't have item %c!",x); }
686ycwi(x)
687	int x;
688	{ cursors();  lprintf("\nYou can't wield item %c!",x); }
689
690/*
691	function to wear armor
692 */
693wear()
694	{
695	register 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 */
721dropobj()
722	{
723	register int i;
724	register 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 */
765readscr()
766	{
767	register 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 */
787eatcookie()
788{
789register int i;
790char *p;
791while (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())
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 *	subroutine to quaff a potion one is carrying
819 */
820quaff()
821	{
822	register int i;
823	while (1)
824		{
825		if ((i = whatitem("quaff"))=='\33')  return;
826		if (i != '.')
827			{
828			if (i=='*') showquaff(); else
829				{
830				if (iven[i-'a']==OPOTION) { quaffpotion(ivenarg[i-'a']); iven[i-'a']=0; return; }
831				if (iven[i-'a']==0) { ydhi(i); return; }
832				lprcat("\nYou wouldn't want to quaff that, would you? ");  return;
833				}
834			}
835		}
836	}
837
838/*
839	function to ask what player wants to do
840 */
841whatitem(str)
842	char *str;
843	{
844	int i;
845	cursors();  lprintf("\nWhat do you want to %s [* for all] ? ",str);
846	i=0; while (i>'z' || (i<'a' && i!='*' && i!='\33' && i!='.')) i=getchar();
847	if (i=='\33')  lprcat(" aborted");
848	return(i);
849	}
850
851/*
852	subroutine to get a number from the player
853	and allow * to mean return amt, else return the number entered
854 */
855unsigned long readnum(mx)
856	long mx;
857	{
858	register int i;
859	register unsigned long amt=0;
860	sncbr();
861	if ((i=getchar()) == '*')  amt = mx;   /* allow him to say * for all gold */
862	else
863		while (i != '\n')
864			{
865			if (i=='\033') { scbr(); lprcat(" aborted"); return(0); }
866			if ((i <= '9') && (i >= '0') && (amt<99999999))
867				amt = amt*10+i-'0';
868			i = getchar();
869			}
870	scbr();  return(amt);
871	}
872
873#ifdef HIDEBYLINK
874/*
875 *	routine to zero every byte in a string
876 */
877szero(str)
878	register char *str;
879	{
880	while (*str)
881		*str++ = 0;
882	}
883#endif HIDEBYLINK
884