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