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