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