/* $NetBSD: display.c,v 1.10 2012/06/19 05:30:43 dholland Exp $ */ /* display.c Larn is copyrighted 1986 by Noah Morgan. */ #include #ifndef lint __RCSID("$NetBSD: display.c,v 1.10 2012/06/19 05:30:43 dholland Exp $"); #endif /* not lint */ #include "header.h" #include "extern.h" #define makecode(_a,_b,_c) (((_a)<<16) + ((_b)<<8) + (_c)) static void bot_hpx(void); static void bot_spellx(void); static void botside(void); static void botsub(int, const char *); static void seepage(void); static int minx, maxx, miny, maxy, k, m; static char bot1f = 0, bot2f = 0, bot3f = 0; static char always = 0; /* bottomline() now for the bottom line of the display */ void bottomline(void) { recalc(); bot1f = 1; } void bottomhp(void) { bot2f = 1; } void bottomspell(void) { bot3f = 1; } void bottomdo(void) { if (bot1f) { bot3f = bot1f = bot2f = 0; bot_linex(); return; } if (bot2f) { bot2f = 0; bot_hpx(); } if (bot3f) { bot3f = 0; bot_spellx(); } } void bot_linex(void) { int i; if (cbak[SPELLS] <= -50 || (always)) { cursor(1, 18); if (c[SPELLMAX] > 99) lprintf("Spells:%3ld(%3ld)", (long) c[SPELLS], (long) c[SPELLMAX]); else lprintf("Spells:%3ld(%2ld) ", (long) c[SPELLS], (long) c[SPELLMAX]); lprintf(" AC: %-3ld WC: %-3ld Level", (long) c[AC], (long) c[WCLASS]); if (c[LEVEL] > 99) lprintf("%3ld", (long) c[LEVEL]); else lprintf(" %-2ld", (long) c[LEVEL]); lprintf(" Exp: %-9ld %s\n", (long) c[EXPERIENCE], class[c[LEVEL] - 1]); lprintf("HP: %3ld(%3ld) STR=%-2ld INT=%-2ld ", (long) c[HP], (long) c[HPMAX], (long) (c[STRENGTH] + c[STREXTRA]), (long) c[INTELLIGENCE]); lprintf("WIS=%-2ld CON=%-2ld DEX=%-2ld CHA=%-2ld LV:", (long) c[WISDOM], (long) c[CONSTITUTION], (long) c[DEXTERITY], (long) c[CHARISMA]); if ((level == 0) || (wizard)) c[TELEFLAG] = 0; if (c[TELEFLAG]) lprcat(" ?"); else lprcat(levelname[level]); lprintf(" Gold: %-6ld", (long) c[GOLD]); always = 1; botside(); c[TMP] = c[STRENGTH] + c[STREXTRA]; for (i = 0; i < 100; i++) cbak[i] = c[i]; return; } botsub(makecode(SPELLS, 8, 18), "%3ld"); if (c[SPELLMAX] > 99) botsub(makecode(SPELLMAX, 12, 18), "%3ld)"); else botsub(makecode(SPELLMAX, 12, 18), "%2ld) "); botsub(makecode(HP, 5, 19), "%3ld"); botsub(makecode(HPMAX, 9, 19), "%3ld"); botsub(makecode(AC, 21, 18), "%-3ld"); botsub(makecode(WCLASS, 30, 18), "%-3ld"); botsub(makecode(EXPERIENCE, 49, 18), "%-9ld"); if (c[LEVEL] != cbak[LEVEL]) { cursor(59, 18); lprcat(class[c[LEVEL] - 1]); } if (c[LEVEL] > 99) botsub(makecode(LEVEL, 40, 18), "%3ld"); else botsub(makecode(LEVEL, 40, 18), " %-2ld"); c[TMP] = c[STRENGTH] + c[STREXTRA]; botsub(makecode(TMP, 18, 19), "%-2ld"); botsub(makecode(INTELLIGENCE, 25, 19), "%-2ld"); botsub(makecode(WISDOM, 32, 19), "%-2ld"); botsub(makecode(CONSTITUTION, 39, 19), "%-2ld"); botsub(makecode(DEXTERITY, 46, 19), "%-2ld"); botsub(makecode(CHARISMA, 53, 19), "%-2ld"); if ((level != cbak[CAVELEVEL]) || (c[TELEFLAG] != cbak[TELEFLAG])) { if ((level == 0) || (wizard)) c[TELEFLAG] = 0; cbak[TELEFLAG] = c[TELEFLAG]; cbak[CAVELEVEL] = level; cursor(59, 19); if (c[TELEFLAG]) lprcat(" ?"); else lprcat(levelname[level]); } botsub(makecode(GOLD, 69, 19), "%-6ld"); botside(); } /* special subroutine to update only the gold number on the bottomlines called from ogold() */ void bottomgold(void) { botsub(makecode(GOLD, 69, 19), "%-6ld"); /* botsub(GOLD,"%-6ld",69,19); */ } /* special routine to update hp and level fields on bottom lines called in monster.c hitplayer() and spattack() */ static void bot_hpx(void) { if (c[EXPERIENCE] != cbak[EXPERIENCE]) { recalc(); bot_linex(); } else botsub(makecode(HP, 5, 19), "%3ld"); } /* special routine to update number of spells called from regen() */ static void bot_spellx(void) { botsub(makecode(SPELLS, 9, 18), "%2ld"); } /* common subroutine for a more economical bottomline() */ static struct bot_side_def { int typ; const char *string; } bot_data[] = { { STEALTH, "stealth"}, { UNDEADPRO, "undead pro" }, { SPIRITPRO, "spirit pro" }, { CHARMCOUNT, "Charm"}, { TIMESTOP, "Time Stop" }, { HOLDMONST, "Hold Monst" }, { GIANTSTR, "Giant Str"}, { FIRERESISTANCE, "Fire Resit" }, { DEXCOUNT, "Dexterity" }, { STRCOUNT, "Strength"}, { SCAREMONST, "Scare" }, { HASTESELF, "Haste Self" }, { CANCELLATION, "Cancel"}, { INVISIBILITY, "Invisible" }, { ALTPRO, "Protect 3" }, { PROTECTIONTIME, "Protect 2"}, { WTW, "Wall-Walk" } }; static void botside(void) { int i, idx; for (i = 0; i < 17; i++) { idx = bot_data[i].typ; if ((always) || (c[idx] != cbak[idx])) { if ((always) || (cbak[idx] == 0)) { if (c[idx]) { cursor(70, i + 1); lprcat(bot_data[i].string); } } else if (c[idx] == 0) { cursor(70, i + 1); lprcat(" "); } cbak[idx] = c[idx]; } } always = 0; } static void botsub(int idx, const char *str) { int x, y; y = idx & 0xff; x = (idx >> 8) & 0xff; idx >>= 16; if (c[idx] != cbak[idx]) { cbak[idx] = c[idx]; cursor(x, y); lprintf(str, (long) c[idx]); } } /* * subroutine to draw only a section of the screen * only the top section of the screen is updated. * If entire lines are being drawn, then they will be cleared first. */ /* for limited screen drawing */ static int d_xmin = 0, d_xmax = MAXX, d_ymin = 0, d_ymax = MAXY; void draws(int xmin, int xmax, int ymin, int ymax) { int i, idx; if (xmin == 0 && xmax == MAXX) { /* clear section of screen as * needed */ if (ymin == 0) cl_up(79, ymax); else for (i = ymin; i < ymin; i++) cl_line(1, i + 1); xmin = -1; } d_xmin = xmin; d_xmax = xmax; d_ymin = ymin; d_ymax = ymax; /* for limited screen drawing */ drawscreen(); if (xmin <= 0 && xmax == MAXX) { /* draw stuff on right side * of screen as needed */ for (i = ymin; i < ymax; i++) { idx = bot_data[i].typ; if (c[idx]) { cursor(70, i + 1); lprcat(bot_data[i].string); } cbak[idx] = c[idx]; } } } /* drawscreen() subroutine to redraw the whole screen as the player knows it */ u_char screen[MAXX][MAXY]; /* template for the screen */ static u_char d_flag; void drawscreen(void) { int i, j, kk; int lastx, lasty; /* variables used to optimize the * object printing */ if (d_xmin == 0 && d_xmax == MAXX && d_ymin == 0 && d_ymax == MAXY) { d_flag = 1; clear(); /* clear the screen */ } else { d_flag = 0; cursor(1, 1); } if (d_xmin < 0) d_xmin = 0; /* d_xmin=-1 means display all without * bottomline */ for (i = d_ymin; i < d_ymax; i++) for (j = d_xmin; j < d_xmax; j++) if (know[j][i] == 0) screen[j][i] = ' '; else if ((kk = mitem[j][i]) != 0) screen[j][i] = monstnamelist[kk]; else if ((kk = item[j][i]) == OWALL) screen[j][i] = '#'; else screen[j][i] = ' '; for (i = d_ymin; i < d_ymax; i++) { j = d_xmin; while ((screen[j][i] == ' ') && (j < d_xmax)) j++; /* was m=0 */ if (j >= d_xmax) m = d_xmin; /* don't search backwards if blank * line */ else { /* search backwards for end of line */ m = d_xmax - 1; while ((screen[m][i] == ' ') && (m > d_xmin)) --m; if (j <= m) cursor(j + 1, i + 1); else continue; } while (j <= m) { if (j <= m - 3) { for (kk = j; kk <= j + 3; kk++) if (screen[kk][i] != ' ') kk = 1000; if (kk < 1000) { while (screen[j][i] == ' ' && j <= m) j++; cursor(j + 1, i + 1); } } lprc(screen[j++][i]); } } setbold(); /* print out only bold objects now */ for (lastx = lasty = 127, i = d_ymin; i < d_ymax; i++) for (j = d_xmin; j < d_xmax; j++) { if ((kk = item[j][i]) != 0) if (kk != OWALL) if ((know[j][i]) && (mitem[j][i] == 0)) if (objnamelist[kk] != ' ') { if (lasty != i + 1 || lastx != j) cursor(lastx = j + 1, lasty = i + 1); else lastx++; lprc(objnamelist[kk]); } } resetbold(); if (d_flag) { always = 1; botside(); always = 1; bot_linex(); } oldx = 99; d_xmin = 0, d_xmax = MAXX, d_ymin = 0, d_ymax = MAXY; /* for limited screen * drawing */ } /* showcell(x,y) subroutine to display a cell location on the screen */ void showcell(int x, int y) { int i, j, kk, mm; if (c[BLINDCOUNT]) return; /* see nothing if blind */ if (c[AWARENESS]) { minx = x - 3; maxx = x + 3; miny = y - 3; maxy = y + 3; } else { minx = x - 1; maxx = x + 1; miny = y - 1; maxy = y + 1; } if (minx < 0) minx = 0; if (maxx > MAXX - 1) maxx = MAXX - 1; if (miny < 0) miny = 0; if (maxy > MAXY - 1) maxy = MAXY - 1; for (j = miny; j <= maxy; j++) for (mm = minx; mm <= maxx; mm++) if (know[mm][j] == 0) { cursor(mm + 1, j + 1); x = maxx; while (know[x][j]) --x; for (i = mm; i <= x; i++) { if ((kk = mitem[i][j]) != 0) lprc(monstnamelist[kk]); else switch (kk = item[i][j]) { case OWALL: case 0: case OIVTELETRAP: case OTRAPARROWIV: case OIVDARTRAP: case OIVTRAPDOOR: lprc(objnamelist[kk]); break; default: setbold(); lprc(objnamelist[kk]); resetbold(); }; know[i][j] = 1; } mm = maxx; } } /* this routine shows only the spot that is given it. the spaces around these coordinated are not shown used in godirect() in monster.c for missile weapons display */ void show1cell(int x, int y) { if (c[BLINDCOUNT]) return; /* see nothing if blind */ cursor(x + 1, y + 1); if ((k = mitem[x][y]) != 0) lprc(monstnamelist[k]); else switch (k = item[x][y]) { case OWALL: case 0: case OIVTELETRAP: case OTRAPARROWIV: case OIVDARTRAP: case OIVTRAPDOOR: lprc(objnamelist[k]); break; default: setbold(); lprc(objnamelist[k]); resetbold(); }; know[x][y] |= 1; /* we end up knowing about it */ } /* showplayer() subroutine to show where the player is on the screen cursor values start from 1 up */ void showplayer(void) { cursor(playerx + 1, playery + 1); oldx = playerx; oldy = playery; } /* moveplayer(dir) subroutine to move the player from one room to another returns 0 if can't move in that direction or hit a monster or on an object else returns 1 nomove is set to 1 to stop the next move (inadvertent monsters hitting players when walking into walls) if player walks off screen or into wall */ short diroffx[] = {0, 0, 1, 0, -1, 1, -1, 1, -1}; short diroffy[] = {0, 1, 0, -1, 0, -1, -1, 1, 1}; int moveplayer(int dir) /* from = present room # direction = * [1-north] [2-east] [3-south] [4-west] * [5-northeast] [6-northwest] [7-southeast] * [8-southwest] if direction=0, don't * move--just show where he is */ { int kk, mm, i, j; if (c[CONFUSE]) if (c[LEVEL] < rnd(30)) dir = rund(9); /* if confused any dir */ kk = playerx + diroffx[dir]; mm = playery + diroffy[dir]; if (kk < 0 || kk >= MAXX || mm < 0 || mm >= MAXY) { nomove = 1; return (yrepcount = 0); } i = item[kk][mm]; j = mitem[kk][mm]; if (i == OWALL && c[WTW] == 0) { nomove = 1; return (yrepcount = 0); } /* hit a wall */ if (kk == 33 && mm == MAXY - 1 && level == 1) { newcavelevel(0); for (kk = 0; kk < MAXX; kk++) for (mm = 0; mm < MAXY; mm++) if (item[kk][mm] == OENTRANCE) { playerx = kk; playery = mm; positionplayer(); drawscreen(); return (0); } } if (j > 0) { hitmonster(kk, mm); return (yrepcount = 0); } /* hit a monster */ lastpx = playerx; lastpy = playery; playerx = kk; playery = mm; if (i && i != OTRAPARROWIV && i != OIVTELETRAP && i != OIVDARTRAP && i != OIVTRAPDOOR) return (yrepcount = 0); else return (1); } /* * function to show what magic items have been discovered thus far * enter with -1 for just spells, anything else will give scrolls & potions */ static int lincount, count; void seemagic(int arg) { int i, number = 0; count = lincount = 0; nosignal = 1; if (arg == -1) { /* if display spells while casting one */ for (number = i = 0; i < SPNUM; i++) if (spelknow[i]) number++; number = (number + 2) / 3 + 4; /* # lines needed to display */ cl_up(79, number); cursor(1, 1); } else { resetscroll(); clear(); } lprcat("The magic spells you have discovered thus far:\n\n"); for (i = 0; i < SPNUM; i++) if (spelknow[i]) { lprintf("%s %-20s ", spelcode[i], spelname[i]); seepage(); } if (arg == -1) { seepage(); more(); nosignal = 0; draws(0, MAXX, 0, number); return; } lincount += 3; if (count != 0) { count = 2; seepage(); } lprcat("\nThe magic scrolls you have found to date are:\n\n"); count = 0; for (i = 0; i < MAXSCROLL; i++) if (scrollname[i][0]) if (scrollname[i][1] != ' ') { lprintf("%-26s", &scrollname[i][1]); seepage(); } lincount += 3; if (count != 0) { count = 2; seepage(); } lprcat("\nThe magic potions you have found to date are:\n\n"); count = 0; for (i = 0; i < MAXPOTION; i++) if (potionname[i][0]) if (potionname[i][1] != ' ') { lprintf("%-26s", &potionname[i][1]); seepage(); } if (lincount != 0) more(); nosignal = 0; setscroll(); drawscreen(); } /* * subroutine to paginate the seemagic function */ static void seepage(void) { if (++count == 3) { lincount++; count = 0; lprc('\n'); if (lincount > 17) { lincount = 0; more(); clear(); } } }