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