Home | History | Annotate | Line # | Download | only in larn
display.c revision 1.2
      1 #ifndef lint
      2 static char rcsid[] = "$Id: display.c,v 1.2 1993/08/02 17:19:59 mycroft Exp $";
      3 #endif /* not lint */
      4 
      5 /*	display.c		Larn is copyrighted 1986 by Noah Morgan. */
      6 #include "header.h"
      7 #define makecode(_a,_b,_c) (((_a)<<16) + ((_b)<<8) + (_c))
      8 
      9 static int minx,maxx,miny,maxy,k,m;
     10 static char bot1f=0,bot2f=0,bot3f=0;
     11 char always=0;
     12 /*
     13 	bottomline()
     14 
     15 	now for the bottom line of the display
     16  */
     17 bottomline()
     18 	{	recalc();	bot1f=1;	}
     19 bottomhp()
     20 	{	bot2f=1;	}
     21 bottomspell()
     22 	{	bot3f=1;	}
     23 bottomdo()
     24 	{
     25 	if (bot1f) { bot3f=bot1f=bot2f=0; bot_linex(); return; }
     26 	if (bot2f) { bot2f=0; bot_hpx(); }
     27 	if (bot3f) { bot3f=0; bot_spellx(); }
     28 	}
     29 
     30 static void botsub();
     31 
     32 bot_linex()
     33 	{
     34 	register int i;
     35 	if (cbak[SPELLS] <= -50 || (always))
     36 		{
     37 		cursor( 1,18);
     38 		if (c[SPELLMAX]>99)  lprintf("Spells:%3d(%3d)",(long)c[SPELLS],(long)c[SPELLMAX]);
     39 						else lprintf("Spells:%3d(%2d) ",(long)c[SPELLS],(long)c[SPELLMAX]);
     40 		lprintf(" AC: %-3d  WC: %-3d  Level",(long)c[AC],(long)c[WCLASS]);
     41 		if (c[LEVEL]>99) lprintf("%3d",(long)c[LEVEL]);
     42 					else lprintf(" %-2d",(long)c[LEVEL]);
     43 		lprintf(" Exp: %-9d %s\n",(long)c[EXPERIENCE],class[c[LEVEL]-1]);
     44 		lprintf("HP: %3d(%3d) STR=%-2d INT=%-2d ",
     45 			(long)c[HP],(long)c[HPMAX],(long)(c[STRENGTH]+c[STREXTRA]),(long)c[INTELLIGENCE]);
     46 		lprintf("WIS=%-2d CON=%-2d DEX=%-2d CHA=%-2d LV:",
     47 			(long)c[WISDOM],(long)c[CONSTITUTION],(long)c[DEXTERITY],(long)c[CHARISMA]);
     48 
     49 		if ((level==0) || (wizard))  c[TELEFLAG]=0;
     50 		if (c[TELEFLAG])  lprcat(" ?");  else  lprcat(levelname[level]);
     51 		lprintf("  Gold: %-6d",(long)c[GOLD]);
     52 		always=1;  botside();
     53 		c[TMP] = c[STRENGTH]+c[STREXTRA];
     54 		for (i=0; i<100; i++) cbak[i]=c[i];
     55 		return;
     56 		}
     57 
     58 	botsub(makecode(SPELLS,8,18),"%3d");
     59 	if (c[SPELLMAX]>99)  botsub(makecode(SPELLMAX,12,18),"%3d)");
     60 					else botsub(makecode(SPELLMAX,12,18),"%2d) ");
     61 	botsub(makecode(HP,5,19),"%3d");
     62 	botsub(makecode(HPMAX,9,19),"%3d");
     63 	botsub(makecode(AC,21,18),"%-3d");
     64 	botsub(makecode(WCLASS,30,18),"%-3d");
     65 	botsub(makecode(EXPERIENCE,49,18),"%-9d");
     66 	if (c[LEVEL] != cbak[LEVEL])
     67 		{ cursor(59,18);	lprcat(class[c[LEVEL]-1]);  }
     68 	if (c[LEVEL]>99) botsub(makecode(LEVEL,40,18),"%3d");
     69 				else botsub(makecode(LEVEL,40,18)," %-2d");
     70 	c[TMP] = c[STRENGTH]+c[STREXTRA];	botsub(makecode(TMP,18,19),"%-2d");
     71 	botsub(makecode(INTELLIGENCE,25,19),"%-2d");
     72 	botsub(makecode(WISDOM,32,19),"%-2d");
     73 	botsub(makecode(CONSTITUTION,39,19),"%-2d");
     74 	botsub(makecode(DEXTERITY,46,19),"%-2d");
     75 	botsub(makecode(CHARISMA,53,19),"%-2d");
     76 	if ((level != cbak[CAVELEVEL]) || (c[TELEFLAG] != cbak[TELEFLAG]))
     77 		{
     78 		if ((level==0) || (wizard))  c[TELEFLAG]=0;
     79 		cbak[TELEFLAG] = c[TELEFLAG];
     80 		cbak[CAVELEVEL] = level;	cursor(59,19);
     81 		if (c[TELEFLAG])  lprcat(" ?");  else  lprcat(levelname[level]);
     82 		}
     83 	botsub(makecode(GOLD,69,19),"%-6d");
     84 	botside();
     85 	}
     86 
     87 /*
     88 	special subroutine to update only the gold number on the bottomlines
     89 	called from ogold()
     90  */
     91 bottomgold()
     92 	{
     93 	botsub(makecode(GOLD,69,19),"%-6d");
     94 /*	botsub(GOLD,"%-6d",69,19); */
     95 	}
     96 
     97 /*
     98 	special routine to update hp and level fields on bottom lines
     99 	called in monster.c hitplayer() and spattack()
    100  */
    101 bot_hpx()
    102 	{
    103 	if (c[EXPERIENCE] != cbak[EXPERIENCE])
    104 		{
    105 		recalc();	 bot_linex();
    106 		}
    107 	else botsub(makecode(HP,5,19),"%3d");
    108 	}
    109 
    110 /*
    111 	special routine to update number of spells called from regen()
    112  */
    113 bot_spellx()
    114 	{
    115 	botsub(makecode(SPELLS,9,18),"%2d");
    116 	}
    117 
    118 /*
    119 	common subroutine for a more economical bottomline()
    120  */
    121 static struct bot_side_def
    122 	{
    123 	int typ;
    124 	char *string;
    125 	}
    126 	bot_data[] =
    127 	{
    128 	STEALTH,"stealth",		UNDEADPRO,"undead pro",		SPIRITPRO,"spirit pro",
    129 	CHARMCOUNT,"Charm",		TIMESTOP,"Time Stop",		HOLDMONST,"Hold Monst",
    130 	GIANTSTR,"Giant Str",	FIRERESISTANCE,"Fire Resit", DEXCOUNT,"Dexterity",
    131 	STRCOUNT,"Strength",	SCAREMONST,"Scare",			HASTESELF,"Haste Self",
    132 	CANCELLATION,"Cancel",	INVISIBILITY,"Invisible",	ALTPRO,"Protect 3",
    133 	PROTECTIONTIME,"Protect 2", WTW,"Wall-Walk"
    134 	};
    135 
    136 botside()
    137 	{
    138 	register int i,idx;
    139 	for (i=0; i<17; i++)
    140 		{
    141 		idx = bot_data[i].typ;
    142 		if ((always) || (c[idx] != cbak[idx]))
    143 		   {
    144 		   if ((always) || (cbak[idx] == 0))
    145 				{ if (c[idx]) { cursor(70,i+1); lprcat(bot_data[i].string); } }  else
    146 		   if (c[idx]==0)     { cursor(70,i+1); lprcat("          "); }
    147 		   cbak[idx]=c[idx];
    148 		   }
    149 		}
    150 	always=0;
    151 	}
    152 
    153 static void
    154 botsub(idx,str)
    155 	register int idx;
    156 	char *str;
    157 	{
    158 	register int x,y;
    159 	y = idx & 0xff;		x = (idx>>8) & 0xff;	  idx >>= 16;
    160 	if (c[idx] != cbak[idx])
    161 		{ cbak[idx]=c[idx];  cursor(x,y);  lprintf(str,(long)c[idx]); }
    162 	}
    163 
    164 /*
    165  *	subroutine to draw only a section of the screen
    166  *	only the top section of the screen is updated.  If entire lines are being
    167  *	drawn, then they will be cleared first.
    168  */
    169 int d_xmin=0,d_xmax=MAXX,d_ymin=0,d_ymax=MAXY;	/* for limited screen drawing */
    170 draws(xmin,xmax,ymin,ymax)
    171 	int xmin,xmax,ymin,ymax;
    172 	{
    173 	register int i,idx;
    174 	if (xmin==0 && xmax==MAXX) /* clear section of screen as needed */
    175 		{
    176 		if (ymin==0) cl_up(79,ymax);
    177 		else for (i=ymin; i<ymin; i++)  cl_line(1,i+1);
    178 		xmin = -1;
    179 		}
    180 	d_xmin=xmin;	d_xmax=xmax;	d_ymin=ymin;	d_ymax=ymax;	/* for limited screen drawing */
    181 	drawscreen();
    182 	if (xmin<=0 && xmax==MAXX) /* draw stuff on right side of screen as needed*/
    183 		{
    184 		for (i=ymin; i<ymax; i++)
    185 			{
    186 			idx = bot_data[i].typ;
    187 			if (c[idx])
    188 				{
    189 				cursor(70,i+1); lprcat(bot_data[i].string);
    190 				}
    191 			cbak[idx]=c[idx];
    192 			}
    193 		}
    194 	}
    195 
    196 /*
    197 	drawscreen()
    198 
    199 	subroutine to redraw the whole screen as the player knows it
    200  */
    201 char screen[MAXX][MAXY],d_flag;	/* template for the screen */
    202 drawscreen()
    203 	{
    204 	register int i,j,k;
    205 	int lastx,lasty;  /* variables used to optimize the object printing */
    206 	if (d_xmin==0 && d_xmax==MAXX && d_ymin==0 && d_ymax==MAXY)
    207 		{
    208 		d_flag=1;  clear(); /* clear the screen */
    209 		}
    210 	else
    211 		{
    212 		d_flag=0;  cursor(1,1);
    213 		}
    214 	if (d_xmin<0)
    215 		d_xmin=0; /* d_xmin=-1 means display all without bottomline */
    216 
    217 	for (i=d_ymin; i<d_ymax; i++)
    218 	  for (j=d_xmin; j<d_xmax; j++)
    219 		if (know[j][i]==0)  screen[j][i] = ' ';  else
    220 		if (k=mitem[j][i])  screen[j][i] = monstnamelist[k];  else
    221 		if ((k=item[j][i])==OWALL) screen[j][i] = '#';
    222 		else screen[j][i] = ' ';
    223 
    224 	for (i=d_ymin; i<d_ymax; i++)
    225 		{
    226 		j=d_xmin;  while ((screen[j][i]==' ') && (j<d_xmax)) j++;
    227 		/* was m=0 */
    228 		if (j >= d_xmax)  m=d_xmin; /* don't search backwards if blank line */
    229 		else
    230 			{	/* search backwards for end of line */
    231 			m=d_xmax-1;  while ((screen[m][i]==' ') && (m>d_xmin)) --m;
    232 			if (j<=m)  cursor(j+1,i+1);  else continue;
    233 			}
    234 		while (j <= m)
    235 			{
    236 			if (j <= m-3)
    237 				{
    238 				for (k=j; k<=j+3; k++) if (screen[k][i] != ' ') k=1000;
    239 				if (k < 1000)
    240 					{ while(screen[j][i]==' ' && j<=m) j++;  cursor(j+1,i+1); }
    241 				}
    242 			lprc(screen[j++][i]);
    243 			}
    244 		}
    245 	setbold();		/* print out only bold objects now */
    246 
    247 	for (lastx=lasty=127, i=d_ymin; i<d_ymax; i++)
    248 		for (j=d_xmin; j<d_xmax; j++)
    249 			{
    250 			if (k=item[j][i])
    251 				if (k != OWALL)
    252 					if ((know[j][i]) && (mitem[j][i]==0))
    253 						if (objnamelist[k]!=' ')
    254 							{
    255 							if (lasty!=i+1 || lastx!=j)
    256 								cursor(lastx=j+1,lasty=i+1); else lastx++;
    257 							lprc(objnamelist[k]);
    258 							}
    259 			}
    260 
    261 	resetbold();  if (d_flag)  { always=1; botside(); always=1; bot_linex(); }
    262 	oldx=99;
    263 	d_xmin = 0 , d_xmax = MAXX , d_ymin = 0 , d_ymax = MAXY; /* for limited screen drawing */
    264 	}
    265 
    266 /*
    268 	showcell(x,y)
    269 
    270 	subroutine to display a cell location on the screen
    271  */
    272 showcell(x,y)
    273 	int x,y;
    274 	{
    275 	register int i,j,k,m;
    276 	if (c[BLINDCOUNT])  return;	/* see nothing if blind		*/
    277 	if (c[AWARENESS]) { minx = x-3;	maxx = x+3;	miny = y-3;	maxy = y+3; }
    278 			else	  { minx = x-1;	maxx = x+1;	miny = y-1;	maxy = y+1; }
    279 
    280 	if (minx < 0) minx=0;		if (maxx > MAXX-1) maxx = MAXX-1;
    281 	if (miny < 0) miny=0;		if (maxy > MAXY-1) maxy = MAXY-1;
    282 
    283 	for (j=miny; j<=maxy; j++)
    284 	  for (m=minx; m<=maxx; m++)
    285 		if (know[m][j]==0)
    286 			{
    287 			cursor(m+1,j+1);
    288 			x=maxx;  while (know[x][j]) --x;
    289 			for (i=m; i<=x; i++)
    290 				{
    291 				if ((k=mitem[i][j]) != 0)  lprc(monstnamelist[k]);
    292 				else switch(k=item[i][j])
    293 					{
    294 					case OWALL:  case 0: case OIVTELETRAP:  case OTRAPARROWIV:
    295 					case OIVDARTRAP: case OIVTRAPDOOR:
    296 						lprc(objnamelist[k]);	break;
    297 
    298 					default: setbold(); lprc(objnamelist[k]); resetbold();
    299 					};
    300 				know[i][j]=1;
    301 				}
    302 			m = maxx;
    303 			}
    304 	}
    305 
    306 /*
    307 	this routine shows only the spot that is given it.  the spaces around
    308 	these coordinated are not shown
    309 	used in godirect() in monster.c for missile weapons display
    310  */
    311 show1cell(x,y)
    312 	int x,y;
    313 	{
    314 	if (c[BLINDCOUNT])  return;	/* see nothing if blind		*/
    315 	cursor(x+1,y+1);
    316 	if ((k=mitem[x][y]) != 0)  lprc(monstnamelist[k]);
    317 		else switch(k=item[x][y])
    318 			{
    319 			case OWALL:  case 0:  case OIVTELETRAP:  case OTRAPARROWIV:
    320 			case OIVDARTRAP: case OIVTRAPDOOR:
    321 				lprc(objnamelist[k]);	break;
    322 
    323 			default: setbold(); lprc(objnamelist[k]); resetbold();
    324 			};
    325 	know[x][y]|=1;	/* we end up knowing about it */
    326 	}
    327 
    328 /*
    329 	showplayer()
    330 
    331 	subroutine to show where the player is on the screen
    332 	cursor values start from 1 up
    333  */
    334 showplayer()
    335 	{
    336 	cursor(playerx+1,playery+1);
    337 	oldx=playerx;  oldy=playery;
    338 	}
    339 
    340 /*
    341 	moveplayer(dir)
    342 
    343 	subroutine to move the player from one room to another
    344 	returns 0 if can't move in that direction or hit a monster or on an object
    345 	else returns 1
    346 	nomove is set to 1 to stop the next move (inadvertent monsters hitting
    347 	players when walking into walls) if player walks off screen or into wall
    348  */
    349 short diroffx[] = { 0,  0, 1,  0, -1,  1, -1, 1, -1 };
    350 short diroffy[] = { 0,  1, 0, -1,  0, -1, -1, 1,  1 };
    351 moveplayer(dir)
    352 	int dir;			/*	from = present room #  direction = [1-north]
    353 							[2-east] [3-south] [4-west] [5-northeast]
    354 							[6-northwest] [7-southeast] [8-southwest]
    355 						if direction=0, don't move--just show where he is */
    356 	{
    357 	register int k,m,i,j;
    358 	if (c[CONFUSE]) if (c[LEVEL]<rnd(30)) dir=rund(9); /*if confused any dir*/
    359 	k = playerx + diroffx[dir];		m = playery + diroffy[dir];
    360 	if (k<0 || k>=MAXX || m<0 || m>=MAXY) { nomove=1; return(yrepcount = 0); }
    361 	i = item[k][m];			j = mitem[k][m];
    362 	if (i==OWALL && c[WTW]==0) { nomove=1;  return(yrepcount = 0); }		/*	hit a wall	*/
    363 	if (k==33 && m==MAXY-1 && level==1)
    364 		{
    365 		newcavelevel(0); for (k=0; k<MAXX; k++) for (m=0; m<MAXY; m++)
    366 		if (item[k][m]==OENTRANCE)
    367 		  { playerx=k; playery=m; positionplayer();  drawscreen(); return(0); }
    368 		}
    369 	if (j>0)     { hitmonster(k,m);	return(yrepcount = 0); } /* hit a monster*/
    370 	lastpx = playerx;			lastpy = playery;
    371 	playerx = k;		playery = m;
    372 	if (i && i!=OTRAPARROWIV && i!=OIVTELETRAP && i!=OIVDARTRAP && i!=OIVTRAPDOOR) return(yrepcount = 0);  else return(1);
    373 	}
    374 
    375 /*
    377  *	function to show what magic items have been discovered thus far
    378  *	enter with -1 for just spells, anything else will give scrolls & potions
    379  */
    380 static int lincount,count;
    381 seemagic(arg)
    382 	int arg;
    383 	{
    384 	register int i,number;
    385 	count = lincount = 0;  nosignal=1;
    386 
    387 	if (arg== -1) /* if display spells while casting one */
    388 		{
    389 		for (number=i=0; i<SPNUM; i++) if (spelknow[i]) number++;
    390 		number = (number+2)/3 + 4;	/* # lines needed to display */
    391 		cl_up(79,number);  cursor(1,1);
    392 		}
    393 	else
    394 		{
    395 		resetscroll();  clear();
    396 		}
    397 
    398 	lprcat("The magic spells you have discovered thus far:\n\n");
    399 	for (i=0; i<SPNUM; i++)
    400 		if (spelknow[i])
    401 			{ lprintf("%s %-20s ",spelcode[i],spelname[i]);  seepage(); }
    402 
    403 	if (arg== -1)
    404 		{
    405 		seepage();  more();	 nosignal=0;
    406 		draws(0,MAXX,0,number);  return;
    407 		}
    408 
    409 	lincount += 3;  if (count!=0) { count=2;  seepage(); }
    410 
    411 	lprcat("\nThe magic scrolls you have found to date are:\n\n");
    412 	count=0;
    413 	for (i=0; i<MAXSCROLL; i++)
    414 		if (scrollname[i][0])
    415 		  if (scrollname[i][1]!=' ')
    416 			{ lprintf("%-26s",&scrollname[i][1]);  seepage(); }
    417 
    418 	lincount += 3;  if (count!=0) { count=2;  seepage(); }
    419 
    420 	lprcat("\nThe magic potions you have found to date are:\n\n");
    421 	count=0;
    422 	for (i=0; i<MAXPOTION; i++)
    423 		if (potionname[i][0])
    424 		  if (potionname[i][1]!=' ')
    425 			{ lprintf("%-26s",&potionname[i][1]);  seepage(); }
    426 
    427 	if (lincount!=0) more();	nosignal=0;  setscroll();	drawscreen();
    428 	}
    429 
    430 /*
    431  *	subroutine to paginate the seemagic function
    432  */
    433 seepage()
    434 	{
    435 	if (++count==3)
    436 		{
    437 		lincount++;	count=0;	lprc('\n');
    438 		if (lincount>17) {	lincount=0;  more();  clear();	}
    439 		}
    440 	}
    441