Home | History | Annotate | Line # | Download | only in larn
display.c revision 1.7
      1 /*	$NetBSD: display.c,v 1.7 2008/01/28 05:38:53 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.7 2008/01/28 05:38:53 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, const 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), "%3ld");
     96 	if (c[SPELLMAX] > 99)
     97 		botsub(makecode(SPELLMAX, 12, 18), "%3ld)");
     98 	else
     99 		botsub(makecode(SPELLMAX, 12, 18), "%2ld) ");
    100 	botsub(makecode(HP, 5, 19), "%3ld");
    101 	botsub(makecode(HPMAX, 9, 19), "%3ld");
    102 	botsub(makecode(AC, 21, 18), "%-3ld");
    103 	botsub(makecode(WCLASS, 30, 18), "%-3ld");
    104 	botsub(makecode(EXPERIENCE, 49, 18), "%-9ld");
    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), "%3ld");
    111 	else
    112 		botsub(makecode(LEVEL, 40, 18), " %-2ld");
    113 	c[TMP] = c[STRENGTH] + c[STREXTRA];
    114 	botsub(makecode(TMP, 18, 19), "%-2ld");
    115 	botsub(makecode(INTELLIGENCE, 25, 19), "%-2ld");
    116 	botsub(makecode(WISDOM, 32, 19), "%-2ld");
    117 	botsub(makecode(CONSTITUTION, 39, 19), "%-2ld");
    118 	botsub(makecode(DEXTERITY, 46, 19), "%-2ld");
    119 	botsub(makecode(CHARISMA, 53, 19), "%-2ld");
    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), "%-6ld");
    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), "%-6ld");
    143 	/* botsub(GOLD,"%-6ld",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), "%3ld");
    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), "%2ld");
    167 }
    168 
    169 /*
    170 	common subroutine for a more economical bottomline()
    171  */
    172 static struct bot_side_def {
    173 	int             typ;
    174 	const 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(int idx, const char *str)
    221 {
    222 	int    x, y;
    223 	y = idx & 0xff;
    224 	x = (idx >> 8) & 0xff;
    225 	idx >>= 16;
    226 	if (c[idx] != cbak[idx]) {
    227 		cbak[idx] = c[idx];
    228 		cursor(x, y);
    229 		lprintf(str, (long) c[idx]);
    230 	}
    231 }
    232 
    233 /*
    234  *	subroutine to draw only a section of the screen
    235  *	only the top section of the screen is updated.
    236  *	If entire lines are being drawn, then they will be cleared first.
    237  */
    238 /* for limited screen drawing */
    239 int             d_xmin = 0, d_xmax = MAXX, d_ymin = 0, d_ymax = MAXY;
    240 
    241 void
    242 draws(xmin, xmax, ymin, ymax)
    243 	int             xmin, xmax, ymin, ymax;
    244 {
    245 	int    i, idx;
    246 	if (xmin == 0 && xmax == MAXX) {	/* clear section of screen as
    247 						 * needed */
    248 		if (ymin == 0)
    249 			cl_up(79, ymax);
    250 		else
    251 			for (i = ymin; i < ymin; i++)
    252 				cl_line(1, i + 1);
    253 		xmin = -1;
    254 	}
    255 	d_xmin = xmin;
    256 	d_xmax = xmax;
    257 	d_ymin = ymin;
    258 	d_ymax = ymax;		/* for limited screen drawing */
    259 	drawscreen();
    260 	if (xmin <= 0 && xmax == MAXX) {	/* draw stuff on right side
    261 						 * of screen as needed */
    262 		for (i = ymin; i < ymax; i++) {
    263 			idx = bot_data[i].typ;
    264 			if (c[idx]) {
    265 				cursor(70, i + 1);
    266 				lprcat(bot_data[i].string);
    267 			}
    268 			cbak[idx] = c[idx];
    269 		}
    270 	}
    271 }
    272 
    273 /*
    274 	drawscreen()
    275 
    276 	subroutine to redraw the whole screen as the player knows it
    277  */
    278 u_char            screen[MAXX][MAXY], d_flag;	/* template for the screen */
    279 void
    280 drawscreen()
    281 {
    282 	int    i, j, kk;
    283 	int             lastx, lasty;	/* variables used to optimize the
    284 					 * object printing */
    285 	if (d_xmin == 0 && d_xmax == MAXX && d_ymin == 0 && d_ymax == MAXY) {
    286 		d_flag = 1;
    287 		clear();	/* clear the screen */
    288 	} else {
    289 		d_flag = 0;
    290 		cursor(1, 1);
    291 	}
    292 	if (d_xmin < 0)
    293 		d_xmin = 0;	/* d_xmin=-1 means display all without
    294 				 * bottomline */
    295 
    296 	for (i = d_ymin; i < d_ymax; i++)
    297 		for (j = d_xmin; j < d_xmax; j++)
    298 			if (know[j][i] == 0)
    299 				screen[j][i] = ' ';
    300 			else if ((kk = mitem[j][i]) != 0)
    301 				screen[j][i] = monstnamelist[kk];
    302 			else if ((kk = item[j][i]) == OWALL)
    303 				screen[j][i] = '#';
    304 			else
    305 				screen[j][i] = ' ';
    306 
    307 	for (i = d_ymin; i < d_ymax; i++) {
    308 		j = d_xmin;
    309 		while ((screen[j][i] == ' ') && (j < d_xmax))
    310 			j++;
    311 		/* was m=0 */
    312 		if (j >= d_xmax)
    313 			m = d_xmin;	/* don't search backwards if blank
    314 					 * line */
    315 		else {		/* search backwards for end of line */
    316 			m = d_xmax - 1;
    317 			while ((screen[m][i] == ' ') && (m > d_xmin))
    318 				--m;
    319 			if (j <= m)
    320 				cursor(j + 1, i + 1);
    321 			else
    322 				continue;
    323 		}
    324 		while (j <= m) {
    325 			if (j <= m - 3) {
    326 				for (kk = j; kk <= j + 3; kk++)
    327 					if (screen[kk][i] != ' ')
    328 						kk = 1000;
    329 				if (kk < 1000) {
    330 					while (screen[j][i] == ' ' && j <= m)
    331 						j++;
    332 					cursor(j + 1, i + 1);
    333 				}
    334 			}
    335 			lprc(screen[j++][i]);
    336 		}
    337 	}
    338 	setbold();		/* print out only bold objects now */
    339 
    340 	for (lastx = lasty = 127, i = d_ymin; i < d_ymax; i++)
    341 		for (j = d_xmin; j < d_xmax; j++) {
    342 			if ((kk = item[j][i]) != 0)
    343 				if (kk != OWALL)
    344 					if ((know[j][i]) && (mitem[j][i] == 0))
    345 						if (objnamelist[kk] != ' ') {
    346 							if (lasty != i + 1 || lastx != j)
    347 								cursor(lastx = j + 1, lasty = i + 1);
    348 							else
    349 								lastx++;
    350 							lprc(objnamelist[kk]);
    351 						}
    352 		}
    353 
    354 	resetbold();
    355 	if (d_flag) {
    356 		always = 1;
    357 		botside();
    358 		always = 1;
    359 		bot_linex();
    360 	}
    361 	oldx = 99;
    362 	d_xmin = 0, d_xmax = MAXX, d_ymin = 0, d_ymax = MAXY;	/* for limited screen
    363 								 * drawing */
    364 }
    365 
    366 
    367 /*
    368 	showcell(x,y)
    369 
    370 	subroutine to display a cell location on the screen
    371  */
    372 void
    373 showcell(x, y)
    374 	int             x, y;
    375 {
    376 	int    i, j, kk, mm;
    377 	if (c[BLINDCOUNT])
    378 		return;		/* see nothing if blind		 */
    379 	if (c[AWARENESS]) {
    380 		minx = x - 3;
    381 		maxx = x + 3;
    382 		miny = y - 3;
    383 		maxy = y + 3;
    384 	} else {
    385 		minx = x - 1;
    386 		maxx = x + 1;
    387 		miny = y - 1;
    388 		maxy = y + 1;
    389 	}
    390 
    391 	if (minx < 0)
    392 		minx = 0;
    393 	if (maxx > MAXX - 1)
    394 		maxx = MAXX - 1;
    395 	if (miny < 0)
    396 		miny = 0;
    397 	if (maxy > MAXY - 1)
    398 		maxy = MAXY - 1;
    399 
    400 	for (j = miny; j <= maxy; j++)
    401 		for (mm = minx; mm <= maxx; mm++)
    402 			if (know[mm][j] == 0) {
    403 				cursor(mm + 1, j + 1);
    404 				x = maxx;
    405 				while (know[x][j])
    406 					--x;
    407 				for (i = mm; i <= x; i++) {
    408 					if ((kk = mitem[i][j]) != 0)
    409 						lprc(monstnamelist[kk]);
    410 					else
    411 						switch (kk = item[i][j]) {
    412 						case OWALL:
    413 						case 0:
    414 						case OIVTELETRAP:
    415 						case OTRAPARROWIV:
    416 						case OIVDARTRAP:
    417 						case OIVTRAPDOOR:
    418 							lprc(objnamelist[kk]);
    419 							break;
    420 
    421 						default:
    422 							setbold();
    423 							lprc(objnamelist[kk]);
    424 							resetbold();
    425 						};
    426 					know[i][j] = 1;
    427 				}
    428 				mm = maxx;
    429 			}
    430 }
    431 
    432 /*
    433 	this routine shows only the spot that is given it.  the spaces around
    434 	these coordinated are not shown
    435 	used in godirect() in monster.c for missile weapons display
    436  */
    437 void
    438 show1cell(x, y)
    439 	int             x, y;
    440 {
    441 	if (c[BLINDCOUNT])
    442 		return;		/* see nothing if blind		 */
    443 	cursor(x + 1, y + 1);
    444 	if ((k = mitem[x][y]) != 0)
    445 		lprc(monstnamelist[k]);
    446 	else
    447 		switch (k = item[x][y]) {
    448 		case OWALL:
    449 		case 0:
    450 		case OIVTELETRAP:
    451 		case OTRAPARROWIV:
    452 		case OIVDARTRAP:
    453 		case OIVTRAPDOOR:
    454 			lprc(objnamelist[k]);
    455 			break;
    456 
    457 		default:
    458 			setbold();
    459 			lprc(objnamelist[k]);
    460 			resetbold();
    461 		};
    462 	know[x][y] |= 1;	/* we end up knowing about it */
    463 }
    464 
    465 /*
    466 	showplayer()
    467 
    468 	subroutine to show where the player is on the screen
    469 	cursor values start from 1 up
    470  */
    471 void
    472 showplayer()
    473 {
    474 	cursor(playerx + 1, playery + 1);
    475 	oldx = playerx;
    476 	oldy = playery;
    477 }
    478 
    479 /*
    480 	moveplayer(dir)
    481 
    482 	subroutine to move the player from one room to another
    483 	returns 0 if can't move in that direction or hit a monster or on an object
    484 	else returns 1
    485 	nomove is set to 1 to stop the next move (inadvertent monsters hitting
    486 	players when walking into walls) if player walks off screen or into wall
    487  */
    488 short           diroffx[] = {0, 0, 1, 0, -1, 1, -1, 1, -1};
    489 short           diroffy[] = {0, 1, 0, -1, 0, -1, -1, 1, 1};
    490 int
    491 moveplayer(dir)
    492 	int             dir;	/* from = present room #  direction =
    493 				 * [1-north] [2-east] [3-south] [4-west]
    494 				 * [5-northeast] [6-northwest] [7-southeast]
    495 				 * [8-southwest] if direction=0, don't
    496 				 * move--just show where he is */
    497 {
    498 	int    kk, mm, i, j;
    499 	if (c[CONFUSE])
    500 		if (c[LEVEL] < rnd(30))
    501 			dir = rund(9);	/* if confused any dir */
    502 	kk = playerx + diroffx[dir];
    503 	mm = playery + diroffy[dir];
    504 	if (kk < 0 || kk >= MAXX || mm < 0 || mm >= MAXY) {
    505 		nomove = 1;
    506 		return (yrepcount = 0);
    507 	}
    508 	i = item[kk][mm];
    509 	j = mitem[kk][mm];
    510 	if (i == OWALL && c[WTW] == 0) {
    511 		nomove = 1;
    512 		return (yrepcount = 0);
    513 	}			/* hit a wall	 */
    514 	if (kk == 33 && mm == MAXY - 1 && level == 1) {
    515 		newcavelevel(0);
    516 		for (kk = 0; kk < MAXX; kk++)
    517 			for (mm = 0; mm < MAXY; mm++)
    518 				if (item[kk][mm] == OENTRANCE) {
    519 					playerx = kk;
    520 					playery = mm;
    521 					positionplayer();
    522 					drawscreen();
    523 					return (0);
    524 				}
    525 	}
    526 	if (j > 0) {
    527 		hitmonster(kk, mm);
    528 		return (yrepcount = 0);
    529 	}			/* hit a monster */
    530 	lastpx = playerx;
    531 	lastpy = playery;
    532 	playerx = kk;
    533 	playery = mm;
    534 	if (i && i != OTRAPARROWIV && i != OIVTELETRAP && i != OIVDARTRAP && i != OIVTRAPDOOR)
    535 		return (yrepcount = 0);
    536 	else
    537 		return (1);
    538 }
    539 
    540 
    541 /*
    542  *	function to show what magic items have been discovered thus far
    543  *	enter with -1 for just spells, anything else will give scrolls & potions
    544  */
    545 static int      lincount, count;
    546 void
    547 seemagic(arg)
    548 	int             arg;
    549 {
    550 	int    i, number = 0;
    551 	count = lincount = 0;
    552 	nosignal = 1;
    553 
    554 	if (arg == -1) {	/* if display spells while casting one */
    555 		for (number = i = 0; i < SPNUM; i++)
    556 			if (spelknow[i])
    557 				number++;
    558 		number = (number + 2) / 3 + 4;	/* # lines needed to display */
    559 		cl_up(79, number);
    560 		cursor(1, 1);
    561 	} else {
    562 		resetscroll();
    563 		clear();
    564 	}
    565 
    566 	lprcat("The magic spells you have discovered thus far:\n\n");
    567 	for (i = 0; i < SPNUM; i++)
    568 		if (spelknow[i]) {
    569 			lprintf("%s %-20s ", spelcode[i], spelname[i]);
    570 			seepage();
    571 		}
    572 	if (arg == -1) {
    573 		seepage();
    574 		more();
    575 		nosignal = 0;
    576 		draws(0, MAXX, 0, number);
    577 		return;
    578 	}
    579 	lincount += 3;
    580 	if (count != 0) {
    581 		count = 2;
    582 		seepage();
    583 	}
    584 	lprcat("\nThe magic scrolls you have found to date are:\n\n");
    585 	count = 0;
    586 	for (i = 0; i < MAXSCROLL; i++)
    587 		if (scrollname[i][0])
    588 			if (scrollname[i][1] != ' ') {
    589 				lprintf("%-26s", &scrollname[i][1]);
    590 				seepage();
    591 			}
    592 	lincount += 3;
    593 	if (count != 0) {
    594 		count = 2;
    595 		seepage();
    596 	}
    597 	lprcat("\nThe magic potions you have found to date are:\n\n");
    598 	count = 0;
    599 	for (i = 0; i < MAXPOTION; i++)
    600 		if (potionname[i][0])
    601 			if (potionname[i][1] != ' ') {
    602 				lprintf("%-26s", &potionname[i][1]);
    603 				seepage();
    604 			}
    605 	if (lincount != 0)
    606 		more();
    607 	nosignal = 0;
    608 	setscroll();
    609 	drawscreen();
    610 }
    611 
    612 /*
    613  *	subroutine to paginate the seemagic function
    614  */
    615 void
    616 seepage()
    617 {
    618 	if (++count == 3) {
    619 		lincount++;
    620 		count = 0;
    621 		lprc('\n');
    622 		if (lincount > 17) {
    623 			lincount = 0;
    624 			more();
    625 			clear();
    626 		}
    627 	}
    628 }
    629