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