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