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