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