xref: /csrg-svn/games/larn/main.c (revision 46749)
132222Sbostic /*	main.c		*/
236976Sbostic #include <sys/types.h>
332222Sbostic #include "header.h"
432222Sbostic #include <pwd.h>
532222Sbostic static char copyright[]="\nLarn is copyrighted 1986 by Noah Morgan.\n";
632222Sbostic int srcount=0;	/* line counter for showstr()	*/
732222Sbostic int dropflag=0; /* if 1 then don't lookforobject() next round */
832222Sbostic int rmst=80;	/*	random monster creation counter		*/
932222Sbostic int userid;		/* the players login user id number */
1032222Sbostic char nowelcome=0,nomove=0; /* if (nomove) then don't count next iteration as a move */
1132222Sbostic static char viewflag=0;
1232222Sbostic 	/*	if viewflag then we have done a 99 stay here and don't showcell in the main loop */
1332222Sbostic char restorflag=0;	/* 1 means restore has been done	*/
1432222Sbostic static char cmdhelp[] = "\
1532222Sbostic Cmd line format: larn [-slicnh] [-o<optsifle>] [-##] [++]\n\
1632222Sbostic   -s   show the scoreboard\n\
1732222Sbostic   -l   show the logfile (wizard id only)\n\
1832222Sbostic   -i   show scoreboard with inventories of dead characters\n\
1932222Sbostic   -c   create new scoreboard (wizard id only)\n\
2032222Sbostic   -n   suppress welcome message on starting game\n\
2132222Sbostic   -##  specify level of difficulty (example: -5)\n\
2232222Sbostic   -h   print this help text\n\
2332222Sbostic   ++   restore game from checkpoint file\n\
2432222Sbostic   -o<optsfile>   specify .larnopts filename to be used instead of \"~/.larnopts\"\n\
2532222Sbostic ";
2632222Sbostic #ifdef VT100
2732222Sbostic static char *termtypes[] = { "vt100", "vt101", "vt102", "vt103", "vt125",
2832222Sbostic 	"vt131", "vt140", "vt180", "vt220", "vt240", "vt241", "vt320", "vt340",
2932222Sbostic 	"vt341"  };
3032222Sbostic #endif VT100
3132222Sbostic /*
3232222Sbostic 	************
3332222Sbostic 	MAIN PROGRAM
3432222Sbostic 	************
3532222Sbostic  */
main(argc,argv)3632222Sbostic main(argc,argv)
3732222Sbostic 	int argc;
3832222Sbostic 	char **argv;
3932222Sbostic 	{
4032222Sbostic 	register int i,j;
4132222Sbostic 	int hard;
4232222Sbostic 	char *ptr=0,*ttype;
43*46749Sbostic 	struct passwd *pwe;
4432222Sbostic 
4532222Sbostic /*
4632222Sbostic  *	first task is to identify the player
4732222Sbostic  */
4832222Sbostic #ifndef VT100
4932222Sbostic 	init_term();	/* setup the terminal (find out what type) for termcap */
5032222Sbostic #endif VT100
5132222Sbostic 	if (((ptr = getlogin()) == 0) || (*ptr==0))	/* try to get login name */
5232222Sbostic 	  if (pwe=getpwuid(getuid())) /* can we get it from /etc/passwd? */
5332222Sbostic 		ptr = pwe->pw_name;
5432222Sbostic 	  else
5532222Sbostic 	  if ((ptr = getenv("USER")) == 0)
5632222Sbostic 		if ((ptr = getenv("LOGNAME")) == 0)
5732222Sbostic 		  {
5832222Sbostic 		  noone: write(2, "Can't find your logname.  Who Are You?\n",39);
5932222Sbostic 		 		 exit();
6032222Sbostic 		  }
6132222Sbostic 	if (ptr==0) goto noone;
6232222Sbostic 	if (strlen(ptr)==0) goto noone;
6332222Sbostic /*
6432222Sbostic  *	second task is to prepare the pathnames the player will need
6532222Sbostic  */
6632222Sbostic 	strcpy(loginname,ptr); /* save loginname of the user for logging purposes */
6732222Sbostic 	strcpy(logname,ptr);	/* this will be overwritten with the players name */
6832222Sbostic 	if ((ptr = getenv("HOME")) == 0) ptr = ".";
6932222Sbostic 	strcpy(savefilename, ptr);
7032222Sbostic 	strcat(savefilename, "/Larn.sav");	/* save file name in home directory */
7132222Sbostic 	sprintf(optsfile, "%s/.larnopts",ptr);	/* the .larnopts filename */
7232222Sbostic 
7332222Sbostic /*
7432222Sbostic  *	now malloc the memory for the dungeon
7532222Sbostic  */
7632222Sbostic 	cell = (struct cel *)malloc(sizeof(struct cel)*(MAXLEVEL+MAXVLEVEL)*MAXX*MAXY);
7732222Sbostic 	if (cell == 0) died(-285);	/* malloc failure */
7832222Sbostic 	lpbuf    = malloc((5* BUFBIG)>>2);	/* output buffer */
7932222Sbostic 	inbuffer = malloc((5*MAXIBUF)>>2);	/* output buffer */
8032222Sbostic 	if ((lpbuf==0) || (inbuffer==0)) died(-285); /* malloc() failure */
8132222Sbostic 
8232222Sbostic 	lcreat((char*)0);	newgame();		/*	set the initial clock  */ hard= -1;
8332222Sbostic 
8432222Sbostic #ifdef VT100
8532222Sbostic /*
8632222Sbostic  *	check terminal type to avoid users who have not vt100 type terminals
8732222Sbostic  */
8832222Sbostic 	ttype = getenv("TERM");
8932222Sbostic 	for (j=1, i=0; i<sizeof(termtypes)/sizeof(char *); i++)
9032222Sbostic 		if (strcmp(ttype,termtypes[i]) == 0) { j=0;  break; }
9132222Sbostic 	if (j)
9232222Sbostic 		{
9332222Sbostic 		lprcat("Sorry, Larn needs a VT100 family terminal for all it's features.\n"); lflush();
9432222Sbostic 		exit();
9532222Sbostic 		}
9632222Sbostic #endif VT100
9732222Sbostic 
9832222Sbostic /*
9932222Sbostic  *	now make scoreboard if it is not there (don't clear)
10032222Sbostic  */
10132223Sbostic 	if (access(scorefile,0) == -1) /* not there */
10232223Sbostic 		makeboard();
10332222Sbostic 
10432222Sbostic /*
10532222Sbostic  *	now process the command line arguments
10632222Sbostic  */
10732222Sbostic 	for (i=1; i<argc; i++)
10832222Sbostic 		{
10932222Sbostic 		if (argv[i][0] == '-')
11032222Sbostic 		  switch(argv[i][1])
11132222Sbostic 			{
11232222Sbostic 			case 's': showscores();  exit();  /* show scoreboard   */
11332222Sbostic 
11432222Sbostic 			case 'l': /* show log file     */
11532222Sbostic 						diedlog();		exit();
11632222Sbostic 
11732222Sbostic 			case 'i': showallscores();  exit();  /* show all scoreboard */
11832222Sbostic 
11932222Sbostic 			case 'c': 		 /* anyone with password can create scoreboard */
12032222Sbostic 					  lprcat("Preparing to initialize the scoreboard.\n");
12132222Sbostic 					  if (getpassword() != 0)  /*make new scoreboard*/
12232222Sbostic 							{
12332222Sbostic 							makeboard(); lprc('\n'); showscores();
12432222Sbostic 							}
12532222Sbostic 					  exit();
12632222Sbostic 
12732222Sbostic 			case 'n':	/* no welcome msg	*/ nowelcome=1; argv[i][0]=0; break;
12832222Sbostic 
12932222Sbostic 			case '0': case '1': case '2': case '3': case '4': case '5':
13032222Sbostic 			case '6': case '7': case '8': case '9':	/* for hardness */
13132222Sbostic 						sscanf(&argv[i][1],"%d",&hard);
13232222Sbostic 						break;
13332222Sbostic 
13432222Sbostic 			case 'h':	/* print out command line arguments */
13532222Sbostic 						write(1,cmdhelp,sizeof(cmdhelp));  exit();
13632222Sbostic 
13732222Sbostic 			case 'o':	/* specify a .larnopts filename */
13832222Sbostic 						strncpy(optsfile,argv[i]+2,127);  break;
13932222Sbostic 
14032222Sbostic 			default:	printf("Unknown option <%s>\n",argv[i]);  exit();
14132222Sbostic 			};
14232222Sbostic 
14332222Sbostic 		if (argv[i][0] == '+')
14432222Sbostic 			{
14532222Sbostic 			clear();	restorflag = 1;
14632222Sbostic 			if (argv[i][1] == '+')
14732222Sbostic 				{
14832222Sbostic 				hitflag=1; restoregame(ckpfile); /* restore checkpointed game */
14932222Sbostic 				}
15032222Sbostic 			i = argc;
15132222Sbostic 			}
15232222Sbostic 		}
15332222Sbostic 
15432222Sbostic 	readopts();		/* read the options file if there is one */
15532222Sbostic 
15632222Sbostic 
15732222Sbostic #ifdef UIDSCORE
15832222Sbostic 	userid = geteuid();	/* obtain the user's effective id number */
15932222Sbostic #else UIDSCORE
16032222Sbostic 	userid = getplid(logname);	/* obtain the players id number */
16132222Sbostic #endif UIDSCORE
16232222Sbostic 	if (userid < 0) { write(2,"Can't obtain playerid\n",22); exit(); }
16332222Sbostic 
16432222Sbostic #ifdef HIDEBYLINK
16532222Sbostic /*
16632222Sbostic  *	this section of code causes the program to look like something else to ps
16732222Sbostic  */
16832222Sbostic 	if (strcmp(psname,argv[0])) /* if a different process name only */
16932222Sbostic 		{
17032222Sbostic 		if ((i=access(psname,1)) < 0)
17132222Sbostic 			{		/* link not there */
17232222Sbostic 			if (link(argv[0],psname)>=0)
17332222Sbostic 				{
17432222Sbostic 				argv[0] = psname;   execv(psname,argv);
17532222Sbostic 				}
17632222Sbostic 			}
17732222Sbostic 		else
17832222Sbostic 			unlink(psname);
17932222Sbostic 		}
18032222Sbostic 
18132222Sbostic 	for (i=1; i<argc; i++)
18232222Sbostic 		{
18332222Sbostic 		szero(argv[i]);	/* zero the argument to avoid ps snooping */
18432222Sbostic 		}
18532222Sbostic #endif HIDEBYLINK
18632222Sbostic 
18732222Sbostic 	if (access(savefilename,0)==0)	/* restore game if need to */
18832222Sbostic 		{
18932222Sbostic 		clear();	restorflag = 1;
19032222Sbostic 		hitflag=1;	restoregame(savefilename);  /* restore last game	*/
19132222Sbostic 		}
19232222Sbostic 	sigsetup();		/* trap all needed signals	*/
19332222Sbostic 	sethard(hard);	/* set up the desired difficulty				*/
19432222Sbostic 	setupvt100();	/*	setup the terminal special mode				*/
19532222Sbostic 	if (c[HP]==0)	/* create new game */
19632222Sbostic 		{
19732222Sbostic 		makeplayer();	/*	make the character that will play			*/
19832222Sbostic 		newcavelevel(0);/*	make the dungeon						 	*/
19932222Sbostic 		predostuff = 1;	/* tell signals that we are in the welcome screen */
20032222Sbostic 		if (nowelcome==0) welcome();	 /* welcome the player to the game */
20132222Sbostic 		}
20232222Sbostic 	drawscreen();	/*	show the initial dungeon					*/
20332222Sbostic 	predostuff = 2;	/* tell the trap functions that they must do a showplayer()
20432222Sbostic 						from here on */
20532222Sbostic 	/* nice(1);	/* games should be run niced */
20632222Sbostic 	yrepcount = hit2flag = 0;
20732222Sbostic 	while (1)
20832222Sbostic 		{
20932222Sbostic 		if (dropflag==0) lookforobject(); /* see if there is an object here	*/
21032222Sbostic 			else dropflag=0; /* don't show it just dropped an item */
21132222Sbostic 		if (hitflag==0) { if (c[HASTEMONST]) movemonst(); movemonst(); }	/*	move the monsters		*/
21232222Sbostic 		if (viewflag==0) showcell(playerx,playery); else viewflag=0;	/*	show stuff around player	*/
21332222Sbostic 		if (hit3flag) flushall();
21432222Sbostic 		hitflag=hit3flag=0;	nomove=1;
21532222Sbostic 		bot_linex();	/* update bottom line */
21632222Sbostic 		while (nomove)
21732222Sbostic 			{
21832222Sbostic 			if (hit3flag) flushall();
21932222Sbostic 			nomove=0; parse();
22032222Sbostic 			}	/*	get commands and make moves	*/
22132222Sbostic 		regen();			/*	regenerate hp and spells			*/
22232222Sbostic 		if (c[TIMESTOP]==0)
22332222Sbostic 			if (--rmst <= 0)
22432222Sbostic 				{ rmst = 120-(level<<2); fillmonst(makemonst(level)); }
22532222Sbostic 		}
22632222Sbostic 	}
22732222Sbostic 
22832222Sbostic /*
22932222Sbostic 	showstr()
23032222Sbostic 
23132222Sbostic 	show character's inventory
23232222Sbostic  */
showstr()23332222Sbostic showstr()
23432222Sbostic 	{
23532222Sbostic 	register int i,number;
23632222Sbostic 	for (number=3, i=0; i<26; i++)
23732222Sbostic 		if (iven[i]) number++;	/* count items in inventory */
23832222Sbostic 	t_setup(number);	qshowstr();	  t_endup(number);
23932222Sbostic 	}
24032222Sbostic 
qshowstr()24132222Sbostic qshowstr()
24232222Sbostic 	{
24332222Sbostic 	register int i,j,k,sigsav;
24432222Sbostic 	srcount=0;  sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
24532222Sbostic 	if (c[GOLD]) { lprintf(".)   %d gold pieces",(long)c[GOLD]); srcount++; }
24632222Sbostic 	for (k=26; k>=0; k--)
24732222Sbostic 	  if (iven[k])
24832222Sbostic 		{  for (i=22; i<84; i++)
24932222Sbostic 			 for (j=0; j<=k; j++)  if (i==iven[j])  show3(j); k=0; }
25032222Sbostic 
25132222Sbostic 	lprintf("\nElapsed time is %d.  You have %d mobuls left",(long)((gtime+99)/100+1),(long)((TIMELIMIT-gtime)/100));
25232222Sbostic 	more();		nosignal=sigsav;
25332222Sbostic 	}
25432222Sbostic 
25532222Sbostic /*
25632222Sbostic  *	subroutine to clear screen depending on # lines to display
25732222Sbostic  */
t_setup(count)25832222Sbostic t_setup(count)
25932222Sbostic 	register int count;
26032222Sbostic 	{
26132222Sbostic 	if (count<20)  /* how do we clear the screen? */
26232222Sbostic 		{
26332222Sbostic 		cl_up(79,count);  cursor(1,1);
26432222Sbostic 		}
26532222Sbostic 	else
26632222Sbostic 		{
26732222Sbostic 		resetscroll(); clear();
26832222Sbostic 		}
26932222Sbostic 	}
27032222Sbostic 
27132222Sbostic /*
27232222Sbostic  *	subroutine to restore normal display screen depending on t_setup()
27332222Sbostic  */
t_endup(count)27432222Sbostic t_endup(count)
27532222Sbostic 	register int count;
27632222Sbostic 	{
27732222Sbostic 	if (count<18)  /* how did we clear the screen? */
27832222Sbostic 		draws(0,MAXX,0,(count>MAXY) ? MAXY : count);
27932222Sbostic 	else
28032222Sbostic 		{
28132222Sbostic 		drawscreen(); setscroll();
28232222Sbostic 		}
28332222Sbostic 	}
28432222Sbostic 
28532222Sbostic /*
28632222Sbostic 	function to show the things player is wearing only
28732222Sbostic  */
showwear()28832222Sbostic showwear()
28932222Sbostic 	{
29032222Sbostic 	register int i,j,sigsav,count;
29132222Sbostic 	sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
29232222Sbostic 	srcount=0;
29332222Sbostic 
29432222Sbostic 	 for (count=2,j=0; j<=26; j++)	 /* count number of items we will display */
29532222Sbostic 	   if (i=iven[j])
29632222Sbostic 		switch(i)
29732222Sbostic 			{
29832222Sbostic 			case OLEATHER:	case OPLATE:	case OCHAIN:
29932222Sbostic 			case ORING:		case OSTUDLEATHER:	case OSPLINT:
30032222Sbostic 			case OPLATEARMOR:	case OSSPLATE:	case OSHIELD:
30132222Sbostic 			count++;
30232222Sbostic 			};
30332222Sbostic 
30432222Sbostic 	t_setup(count);
30532222Sbostic 
30632222Sbostic 	for (i=22; i<84; i++)
30732222Sbostic 		 for (j=0; j<=26; j++)
30832222Sbostic 		   if (i==iven[j])
30932222Sbostic 			switch(i)
31032222Sbostic 				{
31132222Sbostic 				case OLEATHER:	case OPLATE:	case OCHAIN:
31232222Sbostic 				case ORING:		case OSTUDLEATHER:	case OSPLINT:
31332222Sbostic 				case OPLATEARMOR:	case OSSPLATE:	case OSHIELD:
31432222Sbostic 				show3(j);
31532222Sbostic 				};
31632222Sbostic 	more();		nosignal=sigsav;	t_endup(count);
31732222Sbostic 	}
31832222Sbostic 
31932222Sbostic /*
32032222Sbostic 	function to show the things player can wield only
32132222Sbostic  */
showwield()32232222Sbostic showwield()
32332222Sbostic 	{
32432222Sbostic 	register int i,j,sigsav,count;
32532222Sbostic 	sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
32632222Sbostic 	srcount=0;
32732222Sbostic 
32832222Sbostic 	 for (count=2,j=0; j<=26; j++)	/* count how many items */
32932222Sbostic 	   if (i=iven[j])
33032222Sbostic 		switch(i)
33132222Sbostic 			{
33232222Sbostic 			case ODIAMOND:  case ORUBY:  case OEMERALD:  case OSAPPHIRE:
33332222Sbostic 			case OBOOK:     case OCHEST:  case OLARNEYE: case ONOTHEFT:
33432222Sbostic 			case OSPIRITSCARAB:  case OCUBEofUNDEAD:
33532222Sbostic 			case OPOTION:   case OSCROLL:  break;
33632222Sbostic 			default:  count++;
33732222Sbostic 			};
33832222Sbostic 
33932222Sbostic 	t_setup(count);
34032222Sbostic 
34132222Sbostic 	for (i=22; i<84; i++)
34232222Sbostic 		 for (j=0; j<=26; j++)
34332222Sbostic 		   if (i==iven[j])
34432222Sbostic 			switch(i)
34532222Sbostic 				{
34632222Sbostic 				case ODIAMOND:  case ORUBY:  case OEMERALD:  case OSAPPHIRE:
34732222Sbostic 				case OBOOK:     case OCHEST:  case OLARNEYE: case ONOTHEFT:
34832222Sbostic 				case OSPIRITSCARAB:  case OCUBEofUNDEAD:
34932222Sbostic 				case OPOTION:   case OSCROLL:  break;
35032222Sbostic 				default:  show3(j);
35132222Sbostic 				};
35232222Sbostic 	more();		nosignal=sigsav;	t_endup(count);
35332222Sbostic 	}
35432222Sbostic 
35532222Sbostic /*
35632222Sbostic  *	function to show the things player can read only
35732222Sbostic  */
showread()35832222Sbostic showread()
35932222Sbostic 	{
36032222Sbostic 	register int i,j,sigsav,count;
36132222Sbostic 	sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
36232222Sbostic 	srcount=0;
36332222Sbostic 
36432222Sbostic 	for (count=2,j=0; j<=26; j++)
36532222Sbostic 		switch(iven[j])
36632222Sbostic 			{
36732222Sbostic 			case OBOOK:	case OSCROLL:	count++;
36832222Sbostic 			};
36932222Sbostic 	t_setup(count);
37032222Sbostic 
37132222Sbostic 	for (i=22; i<84; i++)
37232222Sbostic 		 for (j=0; j<=26; j++)
37332222Sbostic 		   if (i==iven[j])
37432222Sbostic 			switch(i)
37532222Sbostic 				{
37632222Sbostic 				case OBOOK:	case OSCROLL:	show3(j);
37732222Sbostic 				};
37832222Sbostic 	more();		nosignal=sigsav;	t_endup(count);
37932222Sbostic 	}
38032222Sbostic 
38132222Sbostic /*
38232222Sbostic  *	function to show the things player can eat only
38332222Sbostic  */
showeat()38432222Sbostic showeat()
38532222Sbostic 	{
38632222Sbostic 	register int i,j,sigsav,count;
38732222Sbostic 	sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
38832222Sbostic 	srcount=0;
38932222Sbostic 
39032222Sbostic 	for (count=2,j=0; j<=26; j++)
39132222Sbostic 		switch(iven[j])
39232222Sbostic 			{
39332222Sbostic 			case OCOOKIE:	count++;
39432222Sbostic 			};
39532222Sbostic 	t_setup(count);
39632222Sbostic 
39732222Sbostic 	for (i=22; i<84; i++)
39832222Sbostic 		 for (j=0; j<=26; j++)
39932222Sbostic 		   if (i==iven[j])
40032222Sbostic 			switch(i)
40132222Sbostic 				{
40232222Sbostic 				case OCOOKIE:	show3(j);
40332222Sbostic 				};
40432222Sbostic 	more();		nosignal=sigsav;	t_endup(count);
40532222Sbostic 	}
40632222Sbostic 
40732222Sbostic /*
40832222Sbostic 	function to show the things player can quaff only
40932222Sbostic  */
showquaff()41032222Sbostic showquaff()
41132222Sbostic 	{
41232222Sbostic 	register int i,j,sigsav,count;
41332222Sbostic 	sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
41432222Sbostic 	srcount=0;
41532222Sbostic 
41632222Sbostic 	for (count=2,j=0; j<=26; j++)
41732222Sbostic 		switch(iven[j])
41832222Sbostic 			{
41932222Sbostic 			case OPOTION:	count++;
42032222Sbostic 			};
42132222Sbostic 	t_setup(count);
42232222Sbostic 
42332222Sbostic 	for (i=22; i<84; i++)
42432222Sbostic 		 for (j=0; j<=26; j++)
42532222Sbostic 		   if (i==iven[j])
42632222Sbostic 			switch(i)
42732222Sbostic 				{
42832222Sbostic 				case OPOTION:	show3(j);
42932222Sbostic 				};
43032222Sbostic 	more();		nosignal=sigsav;		t_endup(count);
43132222Sbostic 	}
43232222Sbostic 
show1(idx,str2)43332222Sbostic show1(idx,str2)
43432222Sbostic 	register int idx;
43532222Sbostic 	register char *str2[];
43632222Sbostic 	{
43732222Sbostic 	if (str2==0)  lprintf("\n%c)   %s",idx+'a',objectname[iven[idx]]);
43832222Sbostic 	else if (*str2[ivenarg[idx]]==0)  lprintf("\n%c)   %s",idx+'a',objectname[iven[idx]]);
43932222Sbostic 	else lprintf("\n%c)   %s of%s",idx+'a',objectname[iven[idx]],str2[ivenarg[idx]]);
44032222Sbostic 	}
44132222Sbostic 
show3(index)44232222Sbostic show3(index)
44332222Sbostic 	register int index;
44432222Sbostic 	{
44532222Sbostic 	switch(iven[index])
44632222Sbostic 		{
44732222Sbostic 		case OPOTION:	show1(index,potionname);  break;
44832222Sbostic 		case OSCROLL:	show1(index,scrollname);  break;
44932222Sbostic 
45032222Sbostic 		case OLARNEYE:		case OBOOK:			case OSPIRITSCARAB:
45132222Sbostic 		case ODIAMOND:		case ORUBY:			case OCUBEofUNDEAD:
45232222Sbostic 		case OEMERALD:		case OCHEST:		case OCOOKIE:
45332222Sbostic 		case OSAPPHIRE:		case ONOTHEFT:		show1(index,(char **)0);  break;
45432222Sbostic 
45532222Sbostic 		default:		lprintf("\n%c)   %s",index+'a',objectname[iven[index]]);
45632222Sbostic 						if (ivenarg[index]>0) lprintf(" + %d",(long)ivenarg[index]);
45732222Sbostic 						else if (ivenarg[index]<0) lprintf(" %d",(long)ivenarg[index]);
45832222Sbostic 						break;
45932222Sbostic 		}
46032222Sbostic 	if (c[WIELD]==index) lprcat(" (weapon in hand)");
46132222Sbostic 	if ((c[WEAR]==index) || (c[SHIELD]==index))  lprcat(" (being worn)");
46232222Sbostic 	if (++srcount>=22) { srcount=0; more(); clear(); }
46332222Sbostic 	}
46432222Sbostic 
46532222Sbostic /*
46632222Sbostic 	subroutine to randomly create monsters if needed
46732222Sbostic  */
randmonst()46832222Sbostic randmonst()
46932222Sbostic 	{
47032222Sbostic 	if (c[TIMESTOP]) return;	/*	don't make monsters if time is stopped	*/
47132222Sbostic 	if (--rmst <= 0)
47232222Sbostic 		{
47332222Sbostic 		rmst = 120 - (level<<2);  fillmonst(makemonst(level));
47432222Sbostic 		}
47532222Sbostic 	}
47632222Sbostic 
47732222Sbostic 
47832222Sbostic /*
47932222Sbostic 	parse()
48032222Sbostic 
48132222Sbostic 	get and execute a command
48232222Sbostic  */
parse()48332222Sbostic parse()
48432222Sbostic 	{
48532222Sbostic 	register int i,j,k,flag;
48632222Sbostic 	while	(1)
48732222Sbostic 		{
48832222Sbostic 		k = yylex();
48932222Sbostic 		switch(k)	/*	get the token from the input and switch on it	*/
49032222Sbostic 			{
49132222Sbostic 			case 'h':	moveplayer(4);	return;		/*	west		*/
49232222Sbostic 			case 'H':	run(4);			return;		/*	west		*/
49332222Sbostic 			case 'l':	moveplayer(2);	return;		/*	east		*/
49432222Sbostic 			case 'L':	run(2);			return;		/*	east		*/
49532222Sbostic 			case 'j':	moveplayer(1);	return;		/*	south		*/
49632222Sbostic 			case 'J':	run(1);			return;		/*	south		*/
49732222Sbostic 			case 'k':	moveplayer(3);	return;		/*	north		*/
49832222Sbostic 			case 'K':	run(3);			return;		/*	north		*/
49932222Sbostic 			case 'u':	moveplayer(5);	return;		/*	northeast	*/
50032222Sbostic 			case 'U':	run(5);			return;		/*	northeast	*/
50132222Sbostic 			case 'y':	moveplayer(6);  return;		/*	northwest	*/
50232222Sbostic 			case 'Y':	run(6);			return;		/*	northwest	*/
50332222Sbostic 			case 'n':	moveplayer(7);	return;		/*	southeast	*/
50432222Sbostic 			case 'N':	run(7);			return;		/*	southeast	*/
50532222Sbostic 			case 'b':	moveplayer(8);	return;		/*	southwest	*/
50632222Sbostic 			case 'B':	run(8);			return;		/*	southwest	*/
50732222Sbostic 
50832222Sbostic 			case '.':	if (yrepcount) viewflag=1; return;		/*	stay here		*/
50932222Sbostic 
51032222Sbostic 			case 'w':	yrepcount=0;	wield();	return;		/*	wield a weapon */
51132222Sbostic 
51232222Sbostic 			case 'W':	yrepcount=0;	wear();		return;	/*	wear armor	*/
51332222Sbostic 
51432222Sbostic 			case 'r':	yrepcount=0;
51532222Sbostic 						if (c[BLINDCOUNT]) { cursors(); lprcat("\nYou can't read anything when you're blind!"); } else
51632222Sbostic 						if (c[TIMESTOP]==0) readscr(); return;		/*	to read a scroll	*/
51732222Sbostic 
51832222Sbostic 			case 'q':	yrepcount=0;	if (c[TIMESTOP]==0) quaff();	return;	/*	quaff a potion		*/
51932222Sbostic 
52032222Sbostic 			case 'd':	yrepcount=0;	if (c[TIMESTOP]==0) dropobj(); return;	/*	to drop an object	*/
52132222Sbostic 
52232222Sbostic 			case 'c':	yrepcount=0;	cast();		return;		/*	cast a spell	*/
52332222Sbostic 
52432222Sbostic 			case 'i':	yrepcount=0;	nomove=1;  showstr();	return;		/*	status		*/
52532222Sbostic 
52632222Sbostic 			case 'e':	yrepcount=0;
52732222Sbostic 						if (c[TIMESTOP]==0) eatcookie(); return;	/*	to eat a fortune cookie */
52832222Sbostic 
52932222Sbostic 			case 'D':	yrepcount=0;	seemagic(0);	nomove=1; return;	/*	list spells and scrolls */
53032222Sbostic 
53132222Sbostic 			case '?':	yrepcount=0;	help(); nomove=1; return;	/*	give the help screen*/
53232222Sbostic 
53332222Sbostic 			case 'S':	clear();  lprcat("Saving . . ."); lflush();
53432222Sbostic 						savegame(savefilename); wizard=1; died(-257);	/*	save the game - doesn't return	*/
53532222Sbostic 
53632222Sbostic 			case 'Z':	yrepcount=0;	if (c[LEVEL]>9) { oteleport(1); return; }
53732222Sbostic 						cursors(); lprcat("\nAs yet, you don't have enough experience to use teleportation");
53832222Sbostic 						return;	/*	teleport yourself	*/
53932222Sbostic 
54032222Sbostic 			case '^':	/* identify traps */  flag=yrepcount=0;  cursors();
54132222Sbostic 						lprc('\n');  for (j=playery-1; j<playery+2; j++)
54232222Sbostic 							{
54332222Sbostic 							if (j < 0) j=0;		if (j >= MAXY) break;
54432222Sbostic 							for (i=playerx-1; i<playerx+2; i++)
54532222Sbostic 								{
54632222Sbostic 								if (i < 0) i=0;	if (i >= MAXX) break;
54732222Sbostic 								switch(item[i][j])
54832222Sbostic 									{
54932222Sbostic 									case OTRAPDOOR:		case ODARTRAP:
55032222Sbostic 									case OTRAPARROW:	case OTELEPORTER:
55132222Sbostic 										lprcat("\nIts "); lprcat(objectname[item[i][j]]);  flag++;
55232222Sbostic 									};
55332222Sbostic 								}
55432222Sbostic 							}
55532222Sbostic 						if (flag==0) lprcat("\nNo traps are visible");
55632222Sbostic 						return;
55732222Sbostic 
55832222Sbostic #if WIZID
55932222Sbostic 			case '_':	/*	this is the fudge player password for wizard mode*/
56032222Sbostic 						yrepcount=0;	cursors(); nomove=1;
56132222Sbostic 						if (userid!=wisid)
56232222Sbostic 							{
56332222Sbostic 							lprcat("Sorry, you are not empowered to be a wizard.\n");
56432222Sbostic 							scbr(); /* system("stty -echo cbreak"); */
56532222Sbostic 							lflush();  return;
56632222Sbostic 							}
56732222Sbostic 						if (getpassword()==0)
56832222Sbostic 							{
56932222Sbostic 							scbr(); /* system("stty -echo cbreak"); */ return;
57032222Sbostic 							}
57132222Sbostic 						wizard=1;  scbr(); /* system("stty -echo cbreak"); */
57232222Sbostic 						for (i=0; i<6; i++)  c[i]=70;  iven[0]=iven[1]=0;
57332222Sbostic 						take(OPROTRING,50);   take(OLANCE,25);  c[WIELD]=1;
57432222Sbostic 						c[LANCEDEATH]=1;   c[WEAR] = c[SHIELD] = -1;
57532222Sbostic 						raiseexperience(6000000L);  c[AWARENESS] += 25000;
57632222Sbostic 						{
57732222Sbostic 						register int i,j;
57832222Sbostic 						for (i=0; i<MAXY; i++)
57932222Sbostic 							for (j=0; j<MAXX; j++)  know[j][i]=1;
58032222Sbostic 						for (i=0; i<SPNUM; i++)	spelknow[i]=1;
58132222Sbostic 						for (i=0; i<MAXSCROLL; i++)  scrollname[i][0]=' ';
58232222Sbostic 						for (i=0; i<MAXPOTION; i++)  potionname[i][0]=' ';
58332222Sbostic 						}
58432222Sbostic 						for (i=0; i<MAXSCROLL; i++)
58532222Sbostic 						  if (strlen(scrollname[i])>2) /* no null items */
58632222Sbostic 							{ item[i][0]=OSCROLL; iarg[i][0]=i; }
58732222Sbostic 						for (i=MAXX-1; i>MAXX-1-MAXPOTION; i--)
58832222Sbostic 						  if (strlen(potionname[i-MAXX+MAXPOTION])>2) /* no null items */
58932222Sbostic 							{ item[i][0]=OPOTION; iarg[i][0]=i-MAXX+MAXPOTION; }
59032222Sbostic 						for (i=1; i<MAXY; i++)
59132222Sbostic 							{ item[0][i]=i; iarg[0][i]=0; }
59232222Sbostic 						for (i=MAXY; i<MAXY+MAXX; i++)
59332222Sbostic 							{ item[i-MAXY][MAXY-1]=i; iarg[i-MAXY][MAXY-1]=0; }
59432222Sbostic 						for (i=MAXX+MAXY; i<MAXX+MAXY+MAXY; i++)
59532222Sbostic 							{ item[MAXX-1][i-MAXX-MAXY]=i; iarg[MAXX-1][i-MAXX-MAXY]=0; }
59632222Sbostic 						c[GOLD]+=25000;	drawscreen();	return;
59732222Sbostic #endif
59832222Sbostic 
59932222Sbostic 			case 'T':	yrepcount=0;	cursors();  if (c[SHIELD] != -1) { c[SHIELD] = -1; lprcat("\nYour shield is off"); bottomline(); } else
60032222Sbostic 										if (c[WEAR] != -1) { c[WEAR] = -1; lprcat("\nYour armor is off"); bottomline(); }
60132222Sbostic 						else lprcat("\nYou aren't wearing anything");
60232222Sbostic 						return;
60332222Sbostic 
60432222Sbostic 			case 'g':	cursors();
60532222Sbostic 						lprintf("\nThe stuff you are carrying presently weighs %d pounds",(long)packweight());
60632222Sbostic 			case ' ':	yrepcount=0;	nomove=1;  return;
60732222Sbostic 
60832222Sbostic 			case 'v':	yrepcount=0;	cursors();
60932222Sbostic 						lprintf("\nCaverns of Larn, Version %d.%d, Diff=%d",(long)VERSION,(long)SUBVERSION,(long)c[HARDGAME]);
61032222Sbostic 						if (wizard) lprcat(" Wizard"); nomove=1;
61132222Sbostic 						if (cheat) lprcat(" Cheater");
61232222Sbostic 						lprcat(copyright);
61332222Sbostic 						return;
61432222Sbostic 
61532222Sbostic 			case 'Q':	yrepcount=0;	quit(); nomove=1;	return;	/*	quit		*/
61632222Sbostic 
61732222Sbostic 			case 'L'-64:  yrepcount=0;	drawscreen();  nomove=1; return;	/*	look		*/
61832222Sbostic 
61932222Sbostic #if WIZID
62032222Sbostic #ifdef EXTRA
62132222Sbostic 			case 'A':	yrepcount=0;	nomove=1; if (wizard) { diag(); return; }  /*	create diagnostic file */
62232222Sbostic 						return;
62332222Sbostic #endif
62432222Sbostic #endif
62532222Sbostic 			case 'P':	cursors();
62632222Sbostic 						if (outstanding_taxes>0)
62732222Sbostic 							lprintf("\nYou presently owe %d gp in taxes.",(long)outstanding_taxes);
62832222Sbostic 						else
62932222Sbostic 							lprcat("\nYou do not owe any taxes.");
63032222Sbostic 						return;
63132222Sbostic 			};
63232222Sbostic 		}
63332222Sbostic 	}
63432222Sbostic 
parse2()63532222Sbostic parse2()
63632222Sbostic 	{
63732222Sbostic 	if (c[HASTEMONST]) movemonst(); movemonst(); /*	move the monsters		*/
63832222Sbostic 	randmonst();	regen();
63932222Sbostic 	}
64032222Sbostic 
run(dir)64132222Sbostic run(dir)
64232222Sbostic 	int dir;
64332222Sbostic 	{
64432222Sbostic 	register int i;
64532222Sbostic 	i=1; while (i)
64632222Sbostic 		{
64732222Sbostic 		i=moveplayer(dir);
64832222Sbostic 		if (i>0) {  if (c[HASTEMONST]) movemonst();  movemonst(); randmonst(); regen(); }
64932222Sbostic 		if (hitflag) i=0;
65032222Sbostic 		if (i!=0)  showcell(playerx,playery);
65132222Sbostic 		}
65232222Sbostic 	}
65332222Sbostic 
65432222Sbostic /*
65532222Sbostic 	function to wield a weapon
65632222Sbostic  */
wield()65732222Sbostic wield()
65832222Sbostic 	{
65932222Sbostic 	register int i;
66032222Sbostic 	while (1)
66132222Sbostic 		{
66232222Sbostic 		if ((i = whatitem("wield"))=='\33')  return;
66332222Sbostic 		if (i != '.')
66432222Sbostic 			{
66532222Sbostic 			if (i=='*') showwield();
66632222Sbostic 			else  if (iven[i-'a']==0) { ydhi(i); return; }
66732222Sbostic 			else if (iven[i-'a']==OPOTION) { ycwi(i); return; }
66832222Sbostic 			else if (iven[i-'a']==OSCROLL) { ycwi(i); return; }
66932222Sbostic 			else  if ((c[SHIELD]!= -1) && (iven[i-'a']==O2SWORD)) { lprcat("\nBut one arm is busy with your shield!"); return; }
67032222Sbostic 			else  { c[WIELD]=i-'a'; if (iven[i-'a'] == OLANCE) c[LANCEDEATH]=1; else c[LANCEDEATH]=0;  bottomline(); return; }
67132222Sbostic 			}
67232222Sbostic 		}
67332222Sbostic 	}
67432222Sbostic 
67532222Sbostic /*
67632222Sbostic 	common routine to say you don't have an item
67732222Sbostic  */
ydhi(x)67832222Sbostic ydhi(x)
67932222Sbostic 	int x;
68032222Sbostic 	{ cursors();  lprintf("\nYou don't have item %c!",x); }
ycwi(x)68132222Sbostic ycwi(x)
68232222Sbostic 	int x;
68332222Sbostic 	{ cursors();  lprintf("\nYou can't wield item %c!",x); }
68432222Sbostic 
68532222Sbostic /*
68632222Sbostic 	function to wear armor
68732222Sbostic  */
wear()68832222Sbostic wear()
68932222Sbostic 	{
69032222Sbostic 	register int i;
69132222Sbostic 	while (1)
69232222Sbostic 		{
69332222Sbostic 		if ((i = whatitem("wear"))=='\33')  return;
69432222Sbostic 		if (i != '.')
69532222Sbostic 			{
69632222Sbostic 			if (i=='*') showwear(); else
69732222Sbostic 			switch(iven[i-'a'])
69832222Sbostic 				{
69932222Sbostic 				case 0:  ydhi(i); return;
70032222Sbostic 				case OLEATHER:  case OCHAIN:  case OPLATE:	case OSTUDLEATHER:
70132222Sbostic 				case ORING:		case OSPLINT:	case OPLATEARMOR:	case OSSPLATE:
70232222Sbostic 						if (c[WEAR] != -1) { lprcat("\nYou're already wearing some armor"); return; }
70332222Sbostic 							c[WEAR]=i-'a';  bottomline(); return;
70432222Sbostic 				case OSHIELD:	if (c[SHIELD] != -1) { lprcat("\nYou are already wearing a shield"); return; }
70532222Sbostic 								if (iven[c[WIELD]]==O2SWORD) { lprcat("\nYour hands are busy with the two handed sword!"); return; }
70632222Sbostic 								c[SHIELD] = i-'a';  bottomline(); return;
70732222Sbostic 				default:	lprcat("\nYou can't wear that!");
70832222Sbostic 				};
70932222Sbostic 			}
71032222Sbostic 		}
71132222Sbostic 	}
71232222Sbostic 
71332222Sbostic /*
71432222Sbostic 	function to drop an object
71532222Sbostic  */
dropobj()71632222Sbostic dropobj()
71732222Sbostic 	{
71832222Sbostic 	register int i;
71932222Sbostic 	register char *p;
72032222Sbostic 	long amt;
72132222Sbostic 	p = &item[playerx][playery];
72232222Sbostic 	while (1)
72332222Sbostic 		{
72432222Sbostic 		if ((i = whatitem("drop"))=='\33')  return;
72532222Sbostic 		if (i=='*') showstr(); else
72632222Sbostic 			{
72732222Sbostic 			if (i=='.')	/* drop some gold */
72832222Sbostic 				{
72932222Sbostic 				if (*p) { lprcat("\nThere's something here already!"); return; }
73032222Sbostic 				lprcat("\n\n");
73132222Sbostic 				cl_dn(1,23);
73232222Sbostic 				lprcat("How much gold do you drop? ");
73332222Sbostic 				if ((amt=readnum((long)c[GOLD])) == 0) return;
73432222Sbostic 				if (amt>c[GOLD])
73532222Sbostic 					{ lprcat("\nYou don't have that much!"); return; }
73632222Sbostic 				if (amt<=32767)
73732222Sbostic 					{ *p=OGOLDPILE; i=amt; }
73832222Sbostic 				else if (amt<=327670L)
73932222Sbostic 					{ *p=ODGOLD; i=amt/10; amt = 10*i; }
74032222Sbostic 				else if (amt<=3276700L)
74132222Sbostic 					{ *p=OMAXGOLD; i=amt/100; amt = 100*i; }
74232222Sbostic 				else if (amt<=32767000L)
74332222Sbostic 					{ *p=OKGOLD; i=amt/1000; amt = 1000*i; }
74432222Sbostic 				else
74532222Sbostic 					{ *p=OKGOLD; i=32767; amt = 32767000L; }
74632222Sbostic 				c[GOLD] -= amt;
74732222Sbostic 				lprintf("You drop %d gold pieces",(long)amt);
74832222Sbostic 				iarg[playerx][playery]=i; bottomgold();
74932222Sbostic 				know[playerx][playery]=0; dropflag=1;  return;
75032222Sbostic 				}
75132222Sbostic 			drop_object(i-'a');
75232222Sbostic 			return;
75332222Sbostic 			}
75432222Sbostic 		}
75532222Sbostic 	}
75632222Sbostic 
75732222Sbostic /*
75832222Sbostic  *	readscr()		Subroutine to read a scroll one is carrying
75932222Sbostic  */
readscr()76032222Sbostic readscr()
76132222Sbostic 	{
76232222Sbostic 	register int i;
76332222Sbostic 	while (1)
76432222Sbostic 		{
76532222Sbostic 		if ((i = whatitem("read"))=='\33')  return;
76632222Sbostic 		if (i != '.')
76732222Sbostic 			{
76832222Sbostic 			if (i=='*') showread(); else
76932222Sbostic 				{
77032222Sbostic 				if (iven[i-'a']==OSCROLL) { read_scroll(ivenarg[i-'a']); iven[i-'a']=0; return; }
77132222Sbostic 				if (iven[i-'a']==OBOOK)   { readbook(ivenarg[i-'a']);  iven[i-'a']=0; return; }
77232222Sbostic 				if (iven[i-'a']==0) { ydhi(i); return; }
77332222Sbostic 				lprcat("\nThere's nothing on it to read");  return;
77432222Sbostic 				}
77532222Sbostic 			}
77632222Sbostic 		}
77732222Sbostic 	}
77832222Sbostic 
77932222Sbostic /*
78032222Sbostic  *	subroutine to eat a cookie one is carrying
78132222Sbostic  */
eatcookie()78232222Sbostic eatcookie()
78332222Sbostic {
78432222Sbostic register int i;
78532222Sbostic char *p;
78632222Sbostic while (1)
78732222Sbostic 	{
78832222Sbostic 	if ((i = whatitem("eat"))=='\33')  return;
78932222Sbostic 	if (i != '.')
79032222Sbostic 		if (i=='*') showeat(); else
79132222Sbostic 			{
79232222Sbostic 			if (iven[i-'a']==OCOOKIE)
79332222Sbostic 				{
79432222Sbostic 				lprcat("\nThe cookie was delicious.");
79532222Sbostic 				iven[i-'a']=0;
79632222Sbostic 				if (!c[BLINDCOUNT])
79732222Sbostic 					{
79832222Sbostic 					if (p=fortune(fortfile))
79932222Sbostic 						{
80032222Sbostic 						lprcat("  Inside you find a scrap of paper that says:\n");
80132222Sbostic 						lprcat(p);
80232222Sbostic 						}
80332222Sbostic 					}
80432222Sbostic 				return;
80532222Sbostic 				}
80632222Sbostic 			if (iven[i-'a']==0) { ydhi(i); return; }
80732222Sbostic 			lprcat("\nYou can't eat that!");  return;
80832222Sbostic 			}
80932222Sbostic 	}
81032222Sbostic }
81132222Sbostic 
81232222Sbostic /*
81332222Sbostic  *	subroutine to quaff a potion one is carrying
81432222Sbostic  */
quaff()81532222Sbostic quaff()
81632222Sbostic 	{
81732222Sbostic 	register int i;
81832222Sbostic 	while (1)
81932222Sbostic 		{
82032222Sbostic 		if ((i = whatitem("quaff"))=='\33')  return;
82132222Sbostic 		if (i != '.')
82232222Sbostic 			{
82332222Sbostic 			if (i=='*') showquaff(); else
82432222Sbostic 				{
82532222Sbostic 				if (iven[i-'a']==OPOTION) { quaffpotion(ivenarg[i-'a']); iven[i-'a']=0; return; }
82632222Sbostic 				if (iven[i-'a']==0) { ydhi(i); return; }
82732222Sbostic 				lprcat("\nYou wouldn't want to quaff that, would you? ");  return;
82832222Sbostic 				}
82932222Sbostic 			}
83032222Sbostic 		}
83132222Sbostic 	}
83232222Sbostic 
83332222Sbostic /*
83432222Sbostic 	function to ask what player wants to do
83532222Sbostic  */
whatitem(str)83632222Sbostic whatitem(str)
83732222Sbostic 	char *str;
83832222Sbostic 	{
83932222Sbostic 	int i;
84032222Sbostic 	cursors();  lprintf("\nWhat do you want to %s [* for all] ? ",str);
84132222Sbostic 	i=0; while (i>'z' || (i<'a' && i!='*' && i!='\33' && i!='.')) i=getchar();
84232222Sbostic 	if (i=='\33')  lprcat(" aborted");
84332222Sbostic 	return(i);
84432222Sbostic 	}
84532222Sbostic 
84632222Sbostic /*
84732222Sbostic 	subroutine to get a number from the player
84832222Sbostic 	and allow * to mean return amt, else return the number entered
84932222Sbostic  */
readnum(mx)85032222Sbostic unsigned long readnum(mx)
85132222Sbostic 	long mx;
85232222Sbostic 	{
85332222Sbostic 	register int i;
85432222Sbostic 	register unsigned long amt=0;
85532222Sbostic 	sncbr();
85632222Sbostic 	if ((i=getchar()) == '*')  amt = mx;   /* allow him to say * for all gold */
85732222Sbostic 	else
85832222Sbostic 		while (i != '\n')
85932222Sbostic 			{
86032222Sbostic 			if (i=='\033') { scbr(); lprcat(" aborted"); return(0); }
86132222Sbostic 			if ((i <= '9') && (i >= '0') && (amt<99999999))
86232222Sbostic 				amt = amt*10+i-'0';
86332222Sbostic 			i = getchar();
86432222Sbostic 			}
86532222Sbostic 	scbr();  return(amt);
86632222Sbostic 	}
86732222Sbostic 
86832222Sbostic #ifdef HIDEBYLINK
86932222Sbostic /*
87032222Sbostic  *	routine to zero every byte in a string
87132222Sbostic  */
szero(str)87232222Sbostic szero(str)
87332222Sbostic 	register char *str;
87432222Sbostic 	{
87532222Sbostic 	while (*str)
87632222Sbostic 		*str++ = 0;
87732222Sbostic 	}
87832222Sbostic #endif HIDEBYLINK
879