Home | History | Annotate | Line # | Download | only in larn
main.c revision 1.2
      1 /*	main.c		*/
      2 #include <sys/types.h>
      3 #include "header.h"
      4 #include <pwd.h>
      5 static char copyright[]="\nLarn is copyrighted 1986 by Noah Morgan.\n";
      6 int srcount=0;	/* line counter for showstr()	*/
      7 int dropflag=0; /* if 1 then don't lookforobject() next round */
      8 int rmst=80;	/*	random monster creation counter		*/
      9 int userid;		/* the players login user id number */
     10 char nowelcome=0,nomove=0; /* if (nomove) then don't count next iteration as a move */
     11 static char viewflag=0;
     12 	/*	if viewflag then we have done a 99 stay here and don't showcell in the main loop */
     13 char restorflag=0;	/* 1 means restore has been done	*/
     14 static char cmdhelp[] = "\
     15 Cmd 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
     27 static 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  */
     36 main(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 /*
    230 	showstr()
    231 
    232 	show character's inventory
    233  */
    234 showstr()
    235 	{
    236 	register int i,number;
    237 	for (number=3, i=0; i<26; i++)
    238 		if (iven[i]) number++;	/* count items in inventory */
    239 	t_setup(number);	qshowstr();	  t_endup(number);
    240 	}
    241 
    242 qshowstr()
    243 	{
    244 	register int i,j,k,sigsav;
    245 	srcount=0;  sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
    246 	if (c[GOLD]) { lprintf(".)   %d gold pieces",(long)c[GOLD]); srcount++; }
    247 	for (k=26; k>=0; k--)
    248 	  if (iven[k])
    249 		{  for (i=22; i<84; i++)
    250 			 for (j=0; j<=k; j++)  if (i==iven[j])  show3(j); k=0; }
    251 
    252 	lprintf("\nElapsed time is %d.  You have %d mobuls left",(long)((gtime+99)/100+1),(long)((TIMELIMIT-gtime)/100));
    253 	more();		nosignal=sigsav;
    254 	}
    255 
    256 /*
    257  *	subroutine to clear screen depending on # lines to display
    258  */
    259 t_setup(count)
    260 	register int count;
    261 	{
    262 	if (count<20)  /* how do we clear the screen? */
    263 		{
    264 		cl_up(79,count);  cursor(1,1);
    265 		}
    266 	else
    267 		{
    268 		resetscroll(); clear();
    269 		}
    270 	}
    271 
    272 /*
    273  *	subroutine to restore normal display screen depending on t_setup()
    274  */
    275 t_endup(count)
    276 	register int count;
    277 	{
    278 	if (count<18)  /* how did we clear the screen? */
    279 		draws(0,MAXX,0,(count>MAXY) ? MAXY : count);
    280 	else
    281 		{
    282 		drawscreen(); setscroll();
    283 		}
    284 	}
    285 
    286 /*
    287 	function to show the things player is wearing only
    288  */
    289 showwear()
    290 	{
    291 	register int i,j,sigsav,count;
    292 	sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
    293 	srcount=0;
    294 
    295 	 for (count=2,j=0; j<=26; j++)	 /* count number of items we will display */
    296 	   if (i=iven[j])
    297 		switch(i)
    298 			{
    299 			case OLEATHER:	case OPLATE:	case OCHAIN:
    300 			case ORING:		case OSTUDLEATHER:	case OSPLINT:
    301 			case OPLATEARMOR:	case OSSPLATE:	case OSHIELD:
    302 			count++;
    303 			};
    304 
    305 	t_setup(count);
    306 
    307 	for (i=22; i<84; i++)
    308 		 for (j=0; j<=26; j++)
    309 		   if (i==iven[j])
    310 			switch(i)
    311 				{
    312 				case OLEATHER:	case OPLATE:	case OCHAIN:
    313 				case ORING:		case OSTUDLEATHER:	case OSPLINT:
    314 				case OPLATEARMOR:	case OSSPLATE:	case OSHIELD:
    315 				show3(j);
    316 				};
    317 	more();		nosignal=sigsav;	t_endup(count);
    318 	}
    319 
    320 /*
    321 	function to show the things player can wield only
    322  */
    323 showwield()
    324 	{
    325 	register int i,j,sigsav,count;
    326 	sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
    327 	srcount=0;
    328 
    329 	 for (count=2,j=0; j<=26; j++)	/* count how many items */
    330 	   if (i=iven[j])
    331 		switch(i)
    332 			{
    333 			case ODIAMOND:  case ORUBY:  case OEMERALD:  case OSAPPHIRE:
    334 			case OBOOK:     case OCHEST:  case OLARNEYE: case ONOTHEFT:
    335 			case OSPIRITSCARAB:  case OCUBEofUNDEAD:
    336 			case OPOTION:   case OSCROLL:  break;
    337 			default:  count++;
    338 			};
    339 
    340 	t_setup(count);
    341 
    342 	for (i=22; i<84; i++)
    343 		 for (j=0; j<=26; j++)
    344 		   if (i==iven[j])
    345 			switch(i)
    346 				{
    347 				case ODIAMOND:  case ORUBY:  case OEMERALD:  case OSAPPHIRE:
    348 				case OBOOK:     case OCHEST:  case OLARNEYE: case ONOTHEFT:
    349 				case OSPIRITSCARAB:  case OCUBEofUNDEAD:
    350 				case OPOTION:   case OSCROLL:  break;
    351 				default:  show3(j);
    352 				};
    353 	more();		nosignal=sigsav;	t_endup(count);
    354 	}
    355 
    356 /*
    357  *	function to show the things player can read only
    358  */
    359 showread()
    360 	{
    361 	register int i,j,sigsav,count;
    362 	sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
    363 	srcount=0;
    364 
    365 	for (count=2,j=0; j<=26; j++)
    366 		switch(iven[j])
    367 			{
    368 			case OBOOK:	case OSCROLL:	count++;
    369 			};
    370 	t_setup(count);
    371 
    372 	for (i=22; i<84; i++)
    373 		 for (j=0; j<=26; j++)
    374 		   if (i==iven[j])
    375 			switch(i)
    376 				{
    377 				case OBOOK:	case OSCROLL:	show3(j);
    378 				};
    379 	more();		nosignal=sigsav;	t_endup(count);
    380 	}
    381 
    382 /*
    383  *	function to show the things player can eat only
    384  */
    385 showeat()
    386 	{
    387 	register int i,j,sigsav,count;
    388 	sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
    389 	srcount=0;
    390 
    391 	for (count=2,j=0; j<=26; j++)
    392 		switch(iven[j])
    393 			{
    394 			case OCOOKIE:	count++;
    395 			};
    396 	t_setup(count);
    397 
    398 	for (i=22; i<84; i++)
    399 		 for (j=0; j<=26; j++)
    400 		   if (i==iven[j])
    401 			switch(i)
    402 				{
    403 				case OCOOKIE:	show3(j);
    404 				};
    405 	more();		nosignal=sigsav;	t_endup(count);
    406 	}
    407 
    408 /*
    409 	function to show the things player can quaff only
    410  */
    411 showquaff()
    412 	{
    413 	register int i,j,sigsav,count;
    414 	sigsav=nosignal;  nosignal=1; /* don't allow ^c etc */
    415 	srcount=0;
    416 
    417 	for (count=2,j=0; j<=26; j++)
    418 		switch(iven[j])
    419 			{
    420 			case OPOTION:	count++;
    421 			};
    422 	t_setup(count);
    423 
    424 	for (i=22; i<84; i++)
    425 		 for (j=0; j<=26; j++)
    426 		   if (i==iven[j])
    427 			switch(i)
    428 				{
    429 				case OPOTION:	show3(j);
    430 				};
    431 	more();		nosignal=sigsav;		t_endup(count);
    432 	}
    433 
    434 show1(idx,str2)
    435 	register int idx;
    436 	register char *str2[];
    437 	{
    438 	if (str2==0)  lprintf("\n%c)   %s",idx+'a',objectname[iven[idx]]);
    439 	else if (*str2[ivenarg[idx]]==0)  lprintf("\n%c)   %s",idx+'a',objectname[iven[idx]]);
    440 	else lprintf("\n%c)   %s of%s",idx+'a',objectname[iven[idx]],str2[ivenarg[idx]]);
    441 	}
    442 
    443 show3(index)
    444 	register int index;
    445 	{
    446 	switch(iven[index])
    447 		{
    448 		case OPOTION:	show1(index,potionname);  break;
    449 		case OSCROLL:	show1(index,scrollname);  break;
    450 
    451 		case OLARNEYE:		case OBOOK:			case OSPIRITSCARAB:
    452 		case ODIAMOND:		case ORUBY:			case OCUBEofUNDEAD:
    453 		case OEMERALD:		case OCHEST:		case OCOOKIE:
    454 		case OSAPPHIRE:		case ONOTHEFT:		show1(index,(char **)0);  break;
    455 
    456 		default:		lprintf("\n%c)   %s",index+'a',objectname[iven[index]]);
    457 						if (ivenarg[index]>0) lprintf(" + %d",(long)ivenarg[index]);
    458 						else if (ivenarg[index]<0) lprintf(" %d",(long)ivenarg[index]);
    459 						break;
    460 		}
    461 	if (c[WIELD]==index) lprcat(" (weapon in hand)");
    462 	if ((c[WEAR]==index) || (c[SHIELD]==index))  lprcat(" (being worn)");
    463 	if (++srcount>=22) { srcount=0; more(); clear(); }
    464 	}
    465 
    466 /*
    467 	subroutine to randomly create monsters if needed
    468  */
    469 randmonst()
    470 	{
    471 	if (c[TIMESTOP]) return;	/*	don't make monsters if time is stopped	*/
    472 	if (--rmst <= 0)
    473 		{
    474 		rmst = 120 - (level<<2);  fillmonst(makemonst(level));
    475 		}
    476 	}
    477 
    478 
    479 /*
    481 	parse()
    482 
    483 	get and execute a command
    484  */
    485 parse()
    486 	{
    487 	register int i,j,k,flag;
    488 	while	(1)
    489 		{
    490 		k = yylex();
    491 		switch(k)	/*	get the token from the input and switch on it	*/
    492 			{
    493 			case 'h':	moveplayer(4);	return;		/*	west		*/
    494 			case 'H':	run(4);			return;		/*	west		*/
    495 			case 'l':	moveplayer(2);	return;		/*	east		*/
    496 			case 'L':	run(2);			return;		/*	east		*/
    497 			case 'j':	moveplayer(1);	return;		/*	south		*/
    498 			case 'J':	run(1);			return;		/*	south		*/
    499 			case 'k':	moveplayer(3);	return;		/*	north		*/
    500 			case 'K':	run(3);			return;		/*	north		*/
    501 			case 'u':	moveplayer(5);	return;		/*	northeast	*/
    502 			case 'U':	run(5);			return;		/*	northeast	*/
    503 			case 'y':	moveplayer(6);  return;		/*	northwest	*/
    504 			case 'Y':	run(6);			return;		/*	northwest	*/
    505 			case 'n':	moveplayer(7);	return;		/*	southeast	*/
    506 			case 'N':	run(7);			return;		/*	southeast	*/
    507 			case 'b':	moveplayer(8);	return;		/*	southwest	*/
    508 			case 'B':	run(8);			return;		/*	southwest	*/
    509 
    510 			case '.':	if (yrepcount) viewflag=1; return;		/*	stay here		*/
    511 
    512 			case 'w':	yrepcount=0;	wield();	return;		/*	wield a weapon */
    513 
    514 			case 'W':	yrepcount=0;	wear();		return;	/*	wear armor	*/
    515 
    516 			case 'r':	yrepcount=0;
    517 						if (c[BLINDCOUNT]) { cursors(); lprcat("\nYou can't read anything when you're blind!"); } else
    518 						if (c[TIMESTOP]==0) readscr(); return;		/*	to read a scroll	*/
    519 
    520 			case 'q':	yrepcount=0;	if (c[TIMESTOP]==0) quaff();	return;	/*	quaff a potion		*/
    521 
    522 			case 'd':	yrepcount=0;	if (c[TIMESTOP]==0) dropobj(); return;	/*	to drop an object	*/
    523 
    524 			case 'c':	yrepcount=0;	cast();		return;		/*	cast a spell	*/
    525 
    526 			case 'i':	yrepcount=0;	nomove=1;  showstr();	return;		/*	status		*/
    527 
    528 			case 'e':	yrepcount=0;
    529 						if (c[TIMESTOP]==0) eatcookie(); return;	/*	to eat a fortune cookie */
    530 
    531 			case 'D':	yrepcount=0;	seemagic(0);	nomove=1; return;	/*	list spells and scrolls */
    532 
    533 			case '?':	yrepcount=0;	help(); nomove=1; return;	/*	give the help screen*/
    534 
    535 			case 'S':	clear();  lprcat("Saving . . ."); lflush();
    536 						savegame(savefilename); wizard=1; died(-257);	/*	save the game - doesn't return	*/
    537 
    538 			case 'Z':	yrepcount=0;	if (c[LEVEL]>9) { oteleport(1); return; }
    539 						cursors(); lprcat("\nAs yet, you don't have enough experience to use teleportation");
    540 						return;	/*	teleport yourself	*/
    541 
    542 			case '^':	/* identify traps */  flag=yrepcount=0;  cursors();
    543 						lprc('\n');  for (j=playery-1; j<playery+2; j++)
    544 							{
    545 							if (j < 0) j=0;		if (j >= MAXY) break;
    546 							for (i=playerx-1; i<playerx+2; i++)
    547 								{
    548 								if (i < 0) i=0;	if (i >= MAXX) break;
    549 								switch(item[i][j])
    550 									{
    551 									case OTRAPDOOR:		case ODARTRAP:
    552 									case OTRAPARROW:	case OTELEPORTER:
    553 										lprcat("\nIts "); lprcat(objectname[item[i][j]]);  flag++;
    554 									};
    555 								}
    556 							}
    557 						if (flag==0) lprcat("\nNo traps are visible");
    558 						return;
    559 
    560 #if WIZID
    561 			case '_':	/*	this is the fudge player password for wizard mode*/
    562 						yrepcount=0;	cursors(); nomove=1;
    563 						if (userid!=wisid)
    564 							{
    565 							lprcat("Sorry, you are not empowered to be a wizard.\n");
    566 							scbr(); /* system("stty -echo cbreak"); */
    567 							lflush();  return;
    568 							}
    569 						if (getpassword()==0)
    570 							{
    571 							scbr(); /* system("stty -echo cbreak"); */ return;
    572 							}
    573 						wizard=1;  scbr(); /* system("stty -echo cbreak"); */
    574 						for (i=0; i<6; i++)  c[i]=70;  iven[0]=iven[1]=0;
    575 						take(OPROTRING,50);   take(OLANCE,25);  c[WIELD]=1;
    576 						c[LANCEDEATH]=1;   c[WEAR] = c[SHIELD] = -1;
    577 						raiseexperience(6000000L);  c[AWARENESS] += 25000;
    578 						{
    579 						register int i,j;
    580 						for (i=0; i<MAXY; i++)
    581 							for (j=0; j<MAXX; j++)  know[j][i]=1;
    582 						for (i=0; i<SPNUM; i++)	spelknow[i]=1;
    583 						for (i=0; i<MAXSCROLL; i++)  scrollname[i]=scrollhide[i];
    584 						for (i=0; i<MAXPOTION; i++)  potionname[i]=potionhide[i];
    585 						}
    586 						for (i=0; i<MAXSCROLL; i++)
    587 						  if (strlen(scrollname[i])>2) /* no null items */
    588 							{ item[i][0]=OSCROLL; iarg[i][0]=i; }
    589 						for (i=MAXX-1; i>MAXX-1-MAXPOTION; i--)
    590 						  if (strlen(potionname[i-MAXX+MAXPOTION])>2) /* no null items */
    591 							{ item[i][0]=OPOTION; iarg[i][0]=i-MAXX+MAXPOTION; }
    592 						for (i=1; i<MAXY; i++)
    593 							{ item[0][i]=i; iarg[0][i]=0; }
    594 						for (i=MAXY; i<MAXY+MAXX; i++)
    595 							{ item[i-MAXY][MAXY-1]=i; iarg[i-MAXY][MAXY-1]=0; }
    596 						for (i=MAXX+MAXY; i<MAXX+MAXY+MAXY; i++)
    597 							{ item[MAXX-1][i-MAXX-MAXY]=i; iarg[MAXX-1][i-MAXX-MAXY]=0; }
    598 						c[GOLD]+=25000;	drawscreen();	return;
    599 #endif
    600 
    601 			case 'T':	yrepcount=0;	cursors();  if (c[SHIELD] != -1) { c[SHIELD] = -1; lprcat("\nYour shield is off"); bottomline(); } else
    602 										if (c[WEAR] != -1) { c[WEAR] = -1; lprcat("\nYour armor is off"); bottomline(); }
    603 						else lprcat("\nYou aren't wearing anything");
    604 						return;
    605 
    606 			case 'g':	cursors();
    607 						lprintf("\nThe stuff you are carrying presently weighs %d pounds",(long)packweight());
    608 			case ' ':	yrepcount=0;	nomove=1;  return;
    609 
    610 			case 'v':	yrepcount=0;	cursors();
    611 						lprintf("\nCaverns of Larn, Version %d.%d, Diff=%d",(long)VERSION,(long)SUBVERSION,(long)c[HARDGAME]);
    612 						if (wizard) lprcat(" Wizard"); nomove=1;
    613 						if (cheat) lprcat(" Cheater");
    614 						lprcat(copyright);
    615 						return;
    616 
    617 			case 'Q':	yrepcount=0;	quit(); nomove=1;	return;	/*	quit		*/
    618 
    619 			case 'L'-64:  yrepcount=0;	drawscreen();  nomove=1; return;	/*	look		*/
    620 
    621 #if WIZID
    622 #ifdef EXTRA
    623 			case 'A':	yrepcount=0;	nomove=1; if (wizard) { diag(); return; }  /*	create diagnostic file */
    624 						return;
    625 #endif
    626 #endif
    627 			case 'P':	cursors();
    628 						if (outstanding_taxes>0)
    629 							lprintf("\nYou presently owe %d gp in taxes.",(long)outstanding_taxes);
    630 						else
    631 							lprcat("\nYou do not owe any taxes.");
    632 						return;
    633 			};
    634 		}
    635 	}
    636 
    637 parse2()
    638 	{
    639 	if (c[HASTEMONST]) movemonst(); movemonst(); /*	move the monsters		*/
    640 	randmonst();	regen();
    641 	}
    642 
    643 run(dir)
    644 	int dir;
    645 	{
    646 	register int i;
    647 	i=1; while (i)
    648 		{
    649 		i=moveplayer(dir);
    650 		if (i>0) {  if (c[HASTEMONST]) movemonst();  movemonst(); randmonst(); regen(); }
    651 		if (hitflag) i=0;
    652 		if (i!=0)  showcell(playerx,playery);
    653 		}
    654 	}
    655 
    656 /*
    657 	function to wield a weapon
    658  */
    659 wield()
    660 	{
    661 	register int i;
    662 	while (1)
    663 		{
    664 		if ((i = whatitem("wield"))=='\33')  return;
    665 		if (i != '.')
    666 			{
    667 			if (i=='*') showwield();
    668 			else  if (iven[i-'a']==0) { ydhi(i); return; }
    669 			else if (iven[i-'a']==OPOTION) { ycwi(i); return; }
    670 			else if (iven[i-'a']==OSCROLL) { ycwi(i); return; }
    671 			else  if ((c[SHIELD]!= -1) && (iven[i-'a']==O2SWORD)) { lprcat("\nBut one arm is busy with your shield!"); return; }
    672 			else  { c[WIELD]=i-'a'; if (iven[i-'a'] == OLANCE) c[LANCEDEATH]=1; else c[LANCEDEATH]=0;  bottomline(); return; }
    673 			}
    674 		}
    675 	}
    676 
    677 /*
    678 	common routine to say you don't have an item
    679  */
    680 ydhi(x)
    681 	int x;
    682 	{ cursors();  lprintf("\nYou don't have item %c!",x); }
    683 ycwi(x)
    684 	int x;
    685 	{ cursors();  lprintf("\nYou can't wield item %c!",x); }
    686 
    687 /*
    688 	function to wear armor
    689  */
    690 wear()
    691 	{
    692 	register int i;
    693 	while (1)
    694 		{
    695 		if ((i = whatitem("wear"))=='\33')  return;
    696 		if (i != '.')
    697 			{
    698 			if (i=='*') showwear(); else
    699 			switch(iven[i-'a'])
    700 				{
    701 				case 0:  ydhi(i); return;
    702 				case OLEATHER:  case OCHAIN:  case OPLATE:	case OSTUDLEATHER:
    703 				case ORING:		case OSPLINT:	case OPLATEARMOR:	case OSSPLATE:
    704 						if (c[WEAR] != -1) { lprcat("\nYou're already wearing some armor"); return; }
    705 							c[WEAR]=i-'a';  bottomline(); return;
    706 				case OSHIELD:	if (c[SHIELD] != -1) { lprcat("\nYou are already wearing a shield"); return; }
    707 								if (iven[c[WIELD]]==O2SWORD) { lprcat("\nYour hands are busy with the two handed sword!"); return; }
    708 								c[SHIELD] = i-'a';  bottomline(); return;
    709 				default:	lprcat("\nYou can't wear that!");
    710 				};
    711 			}
    712 		}
    713 	}
    714 
    715 /*
    716 	function to drop an object
    717  */
    718 dropobj()
    719 	{
    720 	register int i;
    721 	register char *p;
    722 	long amt;
    723 	p = &item[playerx][playery];
    724 	while (1)
    725 		{
    726 		if ((i = whatitem("drop"))=='\33')  return;
    727 		if (i=='*') showstr(); else
    728 			{
    729 			if (i=='.')	/* drop some gold */
    730 				{
    731 				if (*p) { lprcat("\nThere's something here already!"); return; }
    732 				lprcat("\n\n");
    733 				cl_dn(1,23);
    734 				lprcat("How much gold do you drop? ");
    735 				if ((amt=readnum((long)c[GOLD])) == 0) return;
    736 				if (amt>c[GOLD])
    737 					{ lprcat("\nYou don't have that much!"); return; }
    738 				if (amt<=32767)
    739 					{ *p=OGOLDPILE; i=amt; }
    740 				else if (amt<=327670L)
    741 					{ *p=ODGOLD; i=amt/10; amt = 10*i; }
    742 				else if (amt<=3276700L)
    743 					{ *p=OMAXGOLD; i=amt/100; amt = 100*i; }
    744 				else if (amt<=32767000L)
    745 					{ *p=OKGOLD; i=amt/1000; amt = 1000*i; }
    746 				else
    747 					{ *p=OKGOLD; i=32767; amt = 32767000L; }
    748 				c[GOLD] -= amt;
    749 				lprintf("You drop %d gold pieces",(long)amt);
    750 				iarg[playerx][playery]=i; bottomgold();
    751 				know[playerx][playery]=0; dropflag=1;  return;
    752 				}
    753 			drop_object(i-'a');
    754 			return;
    755 			}
    756 		}
    757 	}
    758 
    759 /*
    760  *	readscr()		Subroutine to read a scroll one is carrying
    761  */
    762 readscr()
    763 	{
    764 	register int i;
    765 	while (1)
    766 		{
    767 		if ((i = whatitem("read"))=='\33')  return;
    768 		if (i != '.')
    769 			{
    770 			if (i=='*') showread(); else
    771 				{
    772 				if (iven[i-'a']==OSCROLL) { read_scroll(ivenarg[i-'a']); iven[i-'a']=0; return; }
    773 				if (iven[i-'a']==OBOOK)   { readbook(ivenarg[i-'a']);  iven[i-'a']=0; return; }
    774 				if (iven[i-'a']==0) { ydhi(i); return; }
    775 				lprcat("\nThere's nothing on it to read");  return;
    776 				}
    777 			}
    778 		}
    779 	}
    780 
    781 /*
    782  *	subroutine to eat a cookie one is carrying
    783  */
    784 eatcookie()
    785 {
    786 register int i;
    787 char *p;
    788 while (1)
    789 	{
    790 	if ((i = whatitem("eat"))=='\33')  return;
    791 	if (i != '.')
    792 		if (i=='*') showeat(); else
    793 			{
    794 			if (iven[i-'a']==OCOOKIE)
    795 				{
    796 				lprcat("\nThe cookie was delicious.");
    797 				iven[i-'a']=0;
    798 				if (!c[BLINDCOUNT])
    799 					{
    800 					if (p=fortune(fortfile))
    801 						{
    802 						lprcat("  Inside you find a scrap of paper that says:\n");
    803 						lprcat(p);
    804 						}
    805 					}
    806 				return;
    807 				}
    808 			if (iven[i-'a']==0) { ydhi(i); return; }
    809 			lprcat("\nYou can't eat that!");  return;
    810 			}
    811 	}
    812 }
    813 
    814 /*
    815  *	subroutine to quaff a potion one is carrying
    816  */
    817 quaff()
    818 	{
    819 	register int i;
    820 	while (1)
    821 		{
    822 		if ((i = whatitem("quaff"))=='\33')  return;
    823 		if (i != '.')
    824 			{
    825 			if (i=='*') showquaff(); else
    826 				{
    827 				if (iven[i-'a']==OPOTION) { quaffpotion(ivenarg[i-'a']); iven[i-'a']=0; return; }
    828 				if (iven[i-'a']==0) { ydhi(i); return; }
    829 				lprcat("\nYou wouldn't want to quaff that, would you? ");  return;
    830 				}
    831 			}
    832 		}
    833 	}
    834 
    835 /*
    836 	function to ask what player wants to do
    837  */
    838 whatitem(str)
    839 	char *str;
    840 	{
    841 	int i;
    842 	cursors();  lprintf("\nWhat do you want to %s [* for all] ? ",str);
    843 	i=0; while (i>'z' || (i<'a' && i!='*' && i!='\33' && i!='.')) i=getchar();
    844 	if (i=='\33')  lprcat(" aborted");
    845 	return(i);
    846 	}
    847 
    848 /*
    849 	subroutine to get a number from the player
    850 	and allow * to mean return amt, else return the number entered
    851  */
    852 unsigned long readnum(mx)
    853 	long mx;
    854 	{
    855 	register int i;
    856 	register unsigned long amt=0;
    857 	sncbr();
    858 	if ((i=getchar()) == '*')  amt = mx;   /* allow him to say * for all gold */
    859 	else
    860 		while (i != '\n')
    861 			{
    862 			if (i=='\033') { scbr(); lprcat(" aborted"); return(0); }
    863 			if ((i <= '9') && (i >= '0') && (amt<99999999))
    864 				amt = amt*10+i-'0';
    865 			i = getchar();
    866 			}
    867 	scbr();  return(amt);
    868 	}
    869 
    870 #ifdef HIDEBYLINK
    871 /*
    872  *	routine to zero every byte in a string
    873  */
    874 szero(str)
    875 	register char *str;
    876 	{
    877 	while (*str)
    878 		*str++ = 0;
    879 	}
    880 #endif HIDEBYLINK
    881