]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - larn/display.c
WARNS=5
[bsdgames-darwin.git] / larn / display.c
1 /* $NetBSD: display.c,v 1.10 2012/06/19 05:30:43 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.10 2012/06/19 05:30:43 dholland Exp $");
7 #endif /* not lint */
8
9 #include "header.h"
10 #include "extern.h"
11
12 #define makecode(_a,_b,_c) (((_a)<<16) + ((_b)<<8) + (_c))
13
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);
19
20 static int minx, maxx, miny, maxy, k, m;
21 static char bot1f = 0, bot2f = 0, bot3f = 0;
22 static char always = 0;
23 /*
24 bottomline()
25
26 now for the bottom line of the display
27 */
28 void
29 bottomline(void)
30 {
31 recalc();
32 bot1f = 1;
33 }
34
35 void
36 bottomhp(void)
37 {
38 bot2f = 1;
39 }
40
41 void
42 bottomspell(void)
43 {
44 bot3f = 1;
45 }
46
47 void
48 bottomdo(void)
49 {
50 if (bot1f) {
51 bot3f = bot1f = bot2f = 0;
52 bot_linex();
53 return;
54 }
55 if (bot2f) {
56 bot2f = 0;
57 bot_hpx();
58 }
59 if (bot3f) {
60 bot3f = 0;
61 bot_spellx();
62 }
63 }
64
65 void
66 bot_linex(void)
67 {
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]);
85
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;
99 }
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]);
113 }
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]);
135 }
136 botsub(makecode(GOLD, 69, 19), "%-6ld");
137 botside();
138 }
139
140 /*
141 special subroutine to update only the gold number on the bottomlines
142 called from ogold()
143 */
144 void
145 bottomgold(void)
146 {
147 botsub(makecode(GOLD, 69, 19), "%-6ld");
148 /* botsub(GOLD,"%-6ld",69,19); */
149 }
150
151 /*
152 special routine to update hp and level fields on bottom lines
153 called in monster.c hitplayer() and spattack()
154 */
155 static void
156 bot_hpx(void)
157 {
158 if (c[EXPERIENCE] != cbak[EXPERIENCE]) {
159 recalc();
160 bot_linex();
161 } else
162 botsub(makecode(HP, 5, 19), "%3ld");
163 }
164
165 /*
166 special routine to update number of spells called from regen()
167 */
168 static void
169 bot_spellx(void)
170 {
171 botsub(makecode(SPELLS, 9, 18), "%2ld");
172 }
173
174 /*
175 common subroutine for a more economical bottomline()
176 */
177 static struct bot_side_def {
178 int typ;
179 const char *string;
180 }
181 bot_data[] =
182 {
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" }
200 };
201
202 static void
203 botside(void)
204 {
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);
213 }
214 } else if (c[idx] == 0) {
215 cursor(70, i + 1);
216 lprcat(" ");
217 }
218 cbak[idx] = c[idx];
219 }
220 }
221 always = 0;
222 }
223
224 static void
225 botsub(int idx, const char *str)
226 {
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]);
235 }
236 }
237
238 /*
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.
242 */
243 /* for limited screen drawing */
244 static int d_xmin = 0, d_xmax = MAXX, d_ymin = 0, d_ymax = MAXY;
245
246 void
247 draws(int xmin, int xmax, int ymin, int ymax)
248 {
249 int i, idx;
250 if (xmin == 0 && xmax == MAXX) { /* clear section of screen as
251 * needed */
252 if (ymin == 0)
253 cl_up(79, ymax);
254 else
255 for (i = ymin; i < ymin; i++)
256 cl_line(1, i + 1);
257 xmin = -1;
258 }
259 d_xmin = xmin;
260 d_xmax = xmax;
261 d_ymin = ymin;
262 d_ymax = ymax; /* for limited screen drawing */
263 drawscreen();
264 if (xmin <= 0 && xmax == MAXX) { /* draw stuff on right side
265 * of screen as needed */
266 for (i = ymin; i < ymax; i++) {
267 idx = bot_data[i].typ;
268 if (c[idx]) {
269 cursor(70, i + 1);
270 lprcat(bot_data[i].string);
271 }
272 cbak[idx] = c[idx];
273 }
274 }
275 }
276
277 /*
278 drawscreen()
279
280 subroutine to redraw the whole screen as the player knows it
281 */
282 u_char screen[MAXX][MAXY]; /* template for the screen */
283 static u_char d_flag;
284 void
285 drawscreen(void)
286 {
287 int i, j, kk;
288 int lastx, lasty; /* variables used to optimize the
289 * object printing */
290 if (d_xmin == 0 && d_xmax == MAXX && d_ymin == 0 && d_ymax == MAXY) {
291 d_flag = 1;
292 clear(); /* clear the screen */
293 } else {
294 d_flag = 0;
295 cursor(1, 1);
296 }
297 if (d_xmin < 0)
298 d_xmin = 0; /* d_xmin=-1 means display all without
299 * bottomline */
300
301 for (i = d_ymin; i < d_ymax; i++)
302 for (j = d_xmin; j < d_xmax; j++)
303 if (know[j][i] == 0)
304 screen[j][i] = ' ';
305 else if ((kk = mitem[j][i]) != 0)
306 screen[j][i] = monstnamelist[kk];
307 else if ((kk = item[j][i]) == OWALL)
308 screen[j][i] = '#';
309 else
310 screen[j][i] = ' ';
311
312 for (i = d_ymin; i < d_ymax; i++) {
313 j = d_xmin;
314 while ((screen[j][i] == ' ') && (j < d_xmax))
315 j++;
316 /* was m=0 */
317 if (j >= d_xmax)
318 m = d_xmin; /* don't search backwards if blank
319 * line */
320 else { /* search backwards for end of line */
321 m = d_xmax - 1;
322 while ((screen[m][i] == ' ') && (m > d_xmin))
323 --m;
324 if (j <= m)
325 cursor(j + 1, i + 1);
326 else
327 continue;
328 }
329 while (j <= m) {
330 if (j <= m - 3) {
331 for (kk = j; kk <= j + 3; kk++)
332 if (screen[kk][i] != ' ')
333 kk = 1000;
334 if (kk < 1000) {
335 while (screen[j][i] == ' ' && j <= m)
336 j++;
337 cursor(j + 1, i + 1);
338 }
339 }
340 lprc(screen[j++][i]);
341 }
342 }
343 setbold(); /* print out only bold objects now */
344
345 for (lastx = lasty = 127, i = d_ymin; i < d_ymax; i++)
346 for (j = d_xmin; j < d_xmax; j++) {
347 if ((kk = item[j][i]) != 0)
348 if (kk != OWALL)
349 if ((know[j][i]) && (mitem[j][i] == 0))
350 if (objnamelist[kk] != ' ') {
351 if (lasty != i + 1 || lastx != j)
352 cursor(lastx = j + 1, lasty = i + 1);
353 else
354 lastx++;
355 lprc(objnamelist[kk]);
356 }
357 }
358
359 resetbold();
360 if (d_flag) {
361 always = 1;
362 botside();
363 always = 1;
364 bot_linex();
365 }
366 oldx = 99;
367 d_xmin = 0, d_xmax = MAXX, d_ymin = 0, d_ymax = MAXY; /* for limited screen
368 * drawing */
369 }
370
371
372 /*
373 showcell(x,y)
374
375 subroutine to display a cell location on the screen
376 */
377 void
378 showcell(int x, int y)
379 {
380 int i, j, kk, mm;
381 if (c[BLINDCOUNT])
382 return; /* see nothing if blind */
383 if (c[AWARENESS]) {
384 minx = x - 3;
385 maxx = x + 3;
386 miny = y - 3;
387 maxy = y + 3;
388 } else {
389 minx = x - 1;
390 maxx = x + 1;
391 miny = y - 1;
392 maxy = y + 1;
393 }
394
395 if (minx < 0)
396 minx = 0;
397 if (maxx > MAXX - 1)
398 maxx = MAXX - 1;
399 if (miny < 0)
400 miny = 0;
401 if (maxy > MAXY - 1)
402 maxy = MAXY - 1;
403
404 for (j = miny; j <= maxy; j++)
405 for (mm = minx; mm <= maxx; mm++)
406 if (know[mm][j] == 0) {
407 cursor(mm + 1, j + 1);
408 x = maxx;
409 while (know[x][j])
410 --x;
411 for (i = mm; i <= x; i++) {
412 if ((kk = mitem[i][j]) != 0)
413 lprc(monstnamelist[kk]);
414 else
415 switch (kk = item[i][j]) {
416 case OWALL:
417 case 0:
418 case OIVTELETRAP:
419 case OTRAPARROWIV:
420 case OIVDARTRAP:
421 case OIVTRAPDOOR:
422 lprc(objnamelist[kk]);
423 break;
424
425 default:
426 setbold();
427 lprc(objnamelist[kk]);
428 resetbold();
429 };
430 know[i][j] = 1;
431 }
432 mm = maxx;
433 }
434 }
435
436 /*
437 this routine shows only the spot that is given it. the spaces around
438 these coordinated are not shown
439 used in godirect() in monster.c for missile weapons display
440 */
441 void
442 show1cell(int x, int y)
443 {
444 if (c[BLINDCOUNT])
445 return; /* see nothing if blind */
446 cursor(x + 1, y + 1);
447 if ((k = mitem[x][y]) != 0)
448 lprc(monstnamelist[k]);
449 else
450 switch (k = item[x][y]) {
451 case OWALL:
452 case 0:
453 case OIVTELETRAP:
454 case OTRAPARROWIV:
455 case OIVDARTRAP:
456 case OIVTRAPDOOR:
457 lprc(objnamelist[k]);
458 break;
459
460 default:
461 setbold();
462 lprc(objnamelist[k]);
463 resetbold();
464 };
465 know[x][y] |= 1; /* we end up knowing about it */
466 }
467
468 /*
469 showplayer()
470
471 subroutine to show where the player is on the screen
472 cursor values start from 1 up
473 */
474 void
475 showplayer(void)
476 {
477 cursor(playerx + 1, playery + 1);
478 oldx = playerx;
479 oldy = playery;
480 }
481
482 /*
483 moveplayer(dir)
484
485 subroutine to move the player from one room to another
486 returns 0 if can't move in that direction or hit a monster or on an object
487 else returns 1
488 nomove is set to 1 to stop the next move (inadvertent monsters hitting
489 players when walking into walls) if player walks off screen or into wall
490 */
491 short diroffx[] = {0, 0, 1, 0, -1, 1, -1, 1, -1};
492 short diroffy[] = {0, 1, 0, -1, 0, -1, -1, 1, 1};
493 int
494 moveplayer(int dir)
495 /* from = present room # direction =
496 * [1-north] [2-east] [3-south] [4-west]
497 * [5-northeast] [6-northwest] [7-southeast]
498 * [8-southwest] if direction=0, don't
499 * move--just show where he is */
500 {
501 int kk, mm, i, j;
502 if (c[CONFUSE])
503 if (c[LEVEL] < rnd(30))
504 dir = rund(9); /* if confused any dir */
505 kk = playerx + diroffx[dir];
506 mm = playery + diroffy[dir];
507 if (kk < 0 || kk >= MAXX || mm < 0 || mm >= MAXY) {
508 nomove = 1;
509 return (yrepcount = 0);
510 }
511 i = item[kk][mm];
512 j = mitem[kk][mm];
513 if (i == OWALL && c[WTW] == 0) {
514 nomove = 1;
515 return (yrepcount = 0);
516 } /* hit a wall */
517 if (kk == 33 && mm == MAXY - 1 && level == 1) {
518 newcavelevel(0);
519 for (kk = 0; kk < MAXX; kk++)
520 for (mm = 0; mm < MAXY; mm++)
521 if (item[kk][mm] == OENTRANCE) {
522 playerx = kk;
523 playery = mm;
524 positionplayer();
525 drawscreen();
526 return (0);
527 }
528 }
529 if (j > 0) {
530 hitmonster(kk, mm);
531 return (yrepcount = 0);
532 } /* hit a monster */
533 lastpx = playerx;
534 lastpy = playery;
535 playerx = kk;
536 playery = mm;
537 if (i && i != OTRAPARROWIV && i != OIVTELETRAP && i != OIVDARTRAP && i != OIVTRAPDOOR)
538 return (yrepcount = 0);
539 else
540 return (1);
541 }
542
543
544 /*
545 * function to show what magic items have been discovered thus far
546 * enter with -1 for just spells, anything else will give scrolls & potions
547 */
548 static int lincount, count;
549 void
550 seemagic(int arg)
551 {
552 int i, number = 0;
553 count = lincount = 0;
554 nosignal = 1;
555
556 if (arg == -1) { /* if display spells while casting one */
557 for (number = i = 0; i < SPNUM; i++)
558 if (spelknow[i])
559 number++;
560 number = (number + 2) / 3 + 4; /* # lines needed to display */
561 cl_up(79, number);
562 cursor(1, 1);
563 } else {
564 resetscroll();
565 clear();
566 }
567
568 lprcat("The magic spells you have discovered thus far:\n\n");
569 for (i = 0; i < SPNUM; i++)
570 if (spelknow[i]) {
571 lprintf("%s %-20s ", spelcode[i], spelname[i]);
572 seepage();
573 }
574 if (arg == -1) {
575 seepage();
576 more();
577 nosignal = 0;
578 draws(0, MAXX, 0, number);
579 return;
580 }
581 lincount += 3;
582 if (count != 0) {
583 count = 2;
584 seepage();
585 }
586 lprcat("\nThe magic scrolls you have found to date are:\n\n");
587 count = 0;
588 for (i = 0; i < MAXSCROLL; i++)
589 if (scrollname[i][0])
590 if (scrollname[i][1] != ' ') {
591 lprintf("%-26s", &scrollname[i][1]);
592 seepage();
593 }
594 lincount += 3;
595 if (count != 0) {
596 count = 2;
597 seepage();
598 }
599 lprcat("\nThe magic potions you have found to date are:\n\n");
600 count = 0;
601 for (i = 0; i < MAXPOTION; i++)
602 if (potionname[i][0])
603 if (potionname[i][1] != ' ') {
604 lprintf("%-26s", &potionname[i][1]);
605 seepage();
606 }
607 if (lincount != 0)
608 more();
609 nosignal = 0;
610 setscroll();
611 drawscreen();
612 }
613
614 /*
615 * subroutine to paginate the seemagic function
616 */
617 static void
618 seepage(void)
619 {
620 if (++count == 3) {
621 lincount++;
622 count = 0;
623 lprc('\n');
624 if (lincount > 17) {
625 lincount = 0;
626 more();
627 clear();
628 }
629 }
630 }