]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - larn/display.c
Fix coredump on start.
[bsdgames-darwin.git] / larn / display.c
1 /* $NetBSD: display.c,v 1.4 1997/10/18 20:03:15 christos 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.4 1997/10/18 20:03:15 christos Exp $");
7 #endif /* not lint */
8
9 #include "header.h"
10 #include "extern.h"
11 #define makecode(_a,_b,_c) (((_a)<<16) + ((_b)<<8) + (_c))
12
13 static void botsub __P((int, char *));
14
15 static int minx, maxx, miny, maxy, k, m;
16 static char bot1f = 0, bot2f = 0, bot3f = 0;
17 char always = 0;
18 /*
19 bottomline()
20
21 now for the bottom line of the display
22 */
23 void
24 bottomline()
25 {
26 recalc();
27 bot1f = 1;
28 }
29
30 void
31 bottomhp()
32 {
33 bot2f = 1;
34 }
35
36 void
37 bottomspell()
38 {
39 bot3f = 1;
40 }
41
42 void
43 bottomdo()
44 {
45 if (bot1f) {
46 bot3f = bot1f = bot2f = 0;
47 bot_linex();
48 return;
49 }
50 if (bot2f) {
51 bot2f = 0;
52 bot_hpx();
53 }
54 if (bot3f) {
55 bot3f = 0;
56 bot_spellx();
57 }
58 }
59
60 void
61 bot_linex()
62 {
63 int i;
64 if (cbak[SPELLS] <= -50 || (always)) {
65 cursor(1, 18);
66 if (c[SPELLMAX] > 99)
67 lprintf("Spells:%3d(%3d)", (long) c[SPELLS], (long) c[SPELLMAX]);
68 else
69 lprintf("Spells:%3d(%2d) ", (long) c[SPELLS], (long) c[SPELLMAX]);
70 lprintf(" AC: %-3d WC: %-3d Level", (long) c[AC], (long) c[WCLASS]);
71 if (c[LEVEL] > 99)
72 lprintf("%3d", (long) c[LEVEL]);
73 else
74 lprintf(" %-2d", (long) c[LEVEL]);
75 lprintf(" Exp: %-9d %s\n", (long) c[EXPERIENCE], class[c[LEVEL] - 1]);
76 lprintf("HP: %3d(%3d) STR=%-2d INT=%-2d ",
77 (long) c[HP], (long) c[HPMAX], (long) (c[STRENGTH] + c[STREXTRA]), (long) c[INTELLIGENCE]);
78 lprintf("WIS=%-2d CON=%-2d DEX=%-2d CHA=%-2d LV:",
79 (long) c[WISDOM], (long) c[CONSTITUTION], (long) c[DEXTERITY], (long) c[CHARISMA]);
80
81 if ((level == 0) || (wizard))
82 c[TELEFLAG] = 0;
83 if (c[TELEFLAG])
84 lprcat(" ?");
85 else
86 lprcat(levelname[level]);
87 lprintf(" Gold: %-6d", (long) c[GOLD]);
88 always = 1;
89 botside();
90 c[TMP] = c[STRENGTH] + c[STREXTRA];
91 for (i = 0; i < 100; i++)
92 cbak[i] = c[i];
93 return;
94 }
95 botsub(makecode(SPELLS, 8, 18), "%3d");
96 if (c[SPELLMAX] > 99)
97 botsub(makecode(SPELLMAX, 12, 18), "%3d)");
98 else
99 botsub(makecode(SPELLMAX, 12, 18), "%2d) ");
100 botsub(makecode(HP, 5, 19), "%3d");
101 botsub(makecode(HPMAX, 9, 19), "%3d");
102 botsub(makecode(AC, 21, 18), "%-3d");
103 botsub(makecode(WCLASS, 30, 18), "%-3d");
104 botsub(makecode(EXPERIENCE, 49, 18), "%-9d");
105 if (c[LEVEL] != cbak[LEVEL]) {
106 cursor(59, 18);
107 lprcat(class[c[LEVEL] - 1]);
108 }
109 if (c[LEVEL] > 99)
110 botsub(makecode(LEVEL, 40, 18), "%3d");
111 else
112 botsub(makecode(LEVEL, 40, 18), " %-2d");
113 c[TMP] = c[STRENGTH] + c[STREXTRA];
114 botsub(makecode(TMP, 18, 19), "%-2d");
115 botsub(makecode(INTELLIGENCE, 25, 19), "%-2d");
116 botsub(makecode(WISDOM, 32, 19), "%-2d");
117 botsub(makecode(CONSTITUTION, 39, 19), "%-2d");
118 botsub(makecode(DEXTERITY, 46, 19), "%-2d");
119 botsub(makecode(CHARISMA, 53, 19), "%-2d");
120 if ((level != cbak[CAVELEVEL]) || (c[TELEFLAG] != cbak[TELEFLAG])) {
121 if ((level == 0) || (wizard))
122 c[TELEFLAG] = 0;
123 cbak[TELEFLAG] = c[TELEFLAG];
124 cbak[CAVELEVEL] = level;
125 cursor(59, 19);
126 if (c[TELEFLAG])
127 lprcat(" ?");
128 else
129 lprcat(levelname[level]);
130 }
131 botsub(makecode(GOLD, 69, 19), "%-6d");
132 botside();
133 }
134
135 /*
136 special subroutine to update only the gold number on the bottomlines
137 called from ogold()
138 */
139 void
140 bottomgold()
141 {
142 botsub(makecode(GOLD, 69, 19), "%-6d");
143 /* botsub(GOLD,"%-6d",69,19); */
144 }
145
146 /*
147 special routine to update hp and level fields on bottom lines
148 called in monster.c hitplayer() and spattack()
149 */
150 void
151 bot_hpx()
152 {
153 if (c[EXPERIENCE] != cbak[EXPERIENCE]) {
154 recalc();
155 bot_linex();
156 } else
157 botsub(makecode(HP, 5, 19), "%3d");
158 }
159
160 /*
161 special routine to update number of spells called from regen()
162 */
163 void
164 bot_spellx()
165 {
166 botsub(makecode(SPELLS, 9, 18), "%2d");
167 }
168
169 /*
170 common subroutine for a more economical bottomline()
171 */
172 static struct bot_side_def {
173 int typ;
174 char *string;
175 }
176 bot_data[] =
177 {
178 { STEALTH, "stealth"},
179 { UNDEADPRO, "undead pro" },
180 { SPIRITPRO, "spirit pro" },
181 { CHARMCOUNT, "Charm"},
182 { TIMESTOP, "Time Stop" },
183 { HOLDMONST, "Hold Monst" },
184 { GIANTSTR, "Giant Str"},
185 { FIRERESISTANCE, "Fire Resit" },
186 { DEXCOUNT, "Dexterity" },
187 { STRCOUNT, "Strength"},
188 { SCAREMONST, "Scare" },
189 { HASTESELF, "Haste Self" },
190 { CANCELLATION, "Cancel"},
191 { INVISIBILITY, "Invisible" },
192 { ALTPRO, "Protect 3" },
193 { PROTECTIONTIME, "Protect 2"},
194 { WTW, "Wall-Walk" }
195 };
196
197 void
198 botside()
199 {
200 int i, idx;
201 for (i = 0; i < 17; i++) {
202 idx = bot_data[i].typ;
203 if ((always) || (c[idx] != cbak[idx])) {
204 if ((always) || (cbak[idx] == 0)) {
205 if (c[idx]) {
206 cursor(70, i + 1);
207 lprcat(bot_data[i].string);
208 }
209 } else if (c[idx] == 0) {
210 cursor(70, i + 1);
211 lprcat(" ");
212 }
213 cbak[idx] = c[idx];
214 }
215 }
216 always = 0;
217 }
218
219 static void
220 botsub(idx, str)
221 int idx;
222 char *str;
223 {
224 int x, y;
225 y = idx & 0xff;
226 x = (idx >> 8) & 0xff;
227 idx >>= 16;
228 if (c[idx] != cbak[idx]) {
229 cbak[idx] = c[idx];
230 cursor(x, y);
231 lprintf(str, (long) c[idx]);
232 }
233 }
234
235 /*
236 * subroutine to draw only a section of the screen
237 * only the top section of the screen is updated.
238 * If entire lines are being drawn, then they will be cleared first.
239 */
240 /* for limited screen drawing */
241 int d_xmin = 0, d_xmax = MAXX, d_ymin = 0, d_ymax = MAXY;
242
243 void
244 draws(xmin, xmax, ymin, ymax)
245 int xmin, xmax, ymin, ymax;
246 {
247 int i, idx;
248 if (xmin == 0 && xmax == MAXX) { /* clear section of screen as
249 * needed */
250 if (ymin == 0)
251 cl_up(79, ymax);
252 else
253 for (i = ymin; i < ymin; i++)
254 cl_line(1, i + 1);
255 xmin = -1;
256 }
257 d_xmin = xmin;
258 d_xmax = xmax;
259 d_ymin = ymin;
260 d_ymax = ymax; /* for limited screen drawing */
261 drawscreen();
262 if (xmin <= 0 && xmax == MAXX) { /* draw stuff on right side
263 * of screen as needed */
264 for (i = ymin; i < ymax; i++) {
265 idx = bot_data[i].typ;
266 if (c[idx]) {
267 cursor(70, i + 1);
268 lprcat(bot_data[i].string);
269 }
270 cbak[idx] = c[idx];
271 }
272 }
273 }
274
275 /*
276 drawscreen()
277
278 subroutine to redraw the whole screen as the player knows it
279 */
280 u_char screen[MAXX][MAXY], d_flag; /* template for the screen */
281 void
282 drawscreen()
283 {
284 int i, j, k;
285 int lastx, lasty; /* variables used to optimize the
286 * object printing */
287 if (d_xmin == 0 && d_xmax == MAXX && d_ymin == 0 && d_ymax == MAXY) {
288 d_flag = 1;
289 clear(); /* clear the screen */
290 } else {
291 d_flag = 0;
292 cursor(1, 1);
293 }
294 if (d_xmin < 0)
295 d_xmin = 0; /* d_xmin=-1 means display all without
296 * bottomline */
297
298 for (i = d_ymin; i < d_ymax; i++)
299 for (j = d_xmin; j < d_xmax; j++)
300 if (know[j][i] == 0)
301 screen[j][i] = ' ';
302 else if ((k = mitem[j][i]) != 0)
303 screen[j][i] = monstnamelist[k];
304 else if ((k = item[j][i]) == OWALL)
305 screen[j][i] = '#';
306 else
307 screen[j][i] = ' ';
308
309 for (i = d_ymin; i < d_ymax; i++) {
310 j = d_xmin;
311 while ((screen[j][i] == ' ') && (j < d_xmax))
312 j++;
313 /* was m=0 */
314 if (j >= d_xmax)
315 m = d_xmin; /* don't search backwards if blank
316 * line */
317 else { /* search backwards for end of line */
318 m = d_xmax - 1;
319 while ((screen[m][i] == ' ') && (m > d_xmin))
320 --m;
321 if (j <= m)
322 cursor(j + 1, i + 1);
323 else
324 continue;
325 }
326 while (j <= m) {
327 if (j <= m - 3) {
328 for (k = j; k <= j + 3; k++)
329 if (screen[k][i] != ' ')
330 k = 1000;
331 if (k < 1000) {
332 while (screen[j][i] == ' ' && j <= m)
333 j++;
334 cursor(j + 1, i + 1);
335 }
336 }
337 lprc(screen[j++][i]);
338 }
339 }
340 setbold(); /* print out only bold objects now */
341
342 for (lastx = lasty = 127, i = d_ymin; i < d_ymax; i++)
343 for (j = d_xmin; j < d_xmax; j++) {
344 if ((k = item[j][i]) != 0)
345 if (k != OWALL)
346 if ((know[j][i]) && (mitem[j][i] == 0))
347 if (objnamelist[k] != ' ') {
348 if (lasty != i + 1 || lastx != j)
349 cursor(lastx = j + 1, lasty = i + 1);
350 else
351 lastx++;
352 lprc(objnamelist[k]);
353 }
354 }
355
356 resetbold();
357 if (d_flag) {
358 always = 1;
359 botside();
360 always = 1;
361 bot_linex();
362 }
363 oldx = 99;
364 d_xmin = 0, d_xmax = MAXX, d_ymin = 0, d_ymax = MAXY; /* for limited screen
365 * drawing */
366 }
367
368
369 /*
370 showcell(x,y)
371
372 subroutine to display a cell location on the screen
373 */
374 void
375 showcell(x, y)
376 int x, y;
377 {
378 int i, j, k, m;
379 if (c[BLINDCOUNT])
380 return; /* see nothing if blind */
381 if (c[AWARENESS]) {
382 minx = x - 3;
383 maxx = x + 3;
384 miny = y - 3;
385 maxy = y + 3;
386 } else {
387 minx = x - 1;
388 maxx = x + 1;
389 miny = y - 1;
390 maxy = y + 1;
391 }
392
393 if (minx < 0)
394 minx = 0;
395 if (maxx > MAXX - 1)
396 maxx = MAXX - 1;
397 if (miny < 0)
398 miny = 0;
399 if (maxy > MAXY - 1)
400 maxy = MAXY - 1;
401
402 for (j = miny; j <= maxy; j++)
403 for (m = minx; m <= maxx; m++)
404 if (know[m][j] == 0) {
405 cursor(m + 1, j + 1);
406 x = maxx;
407 while (know[x][j])
408 --x;
409 for (i = m; i <= x; i++) {
410 if ((k = mitem[i][j]) != 0)
411 lprc(monstnamelist[k]);
412 else
413 switch (k = item[i][j]) {
414 case OWALL:
415 case 0:
416 case OIVTELETRAP:
417 case OTRAPARROWIV:
418 case OIVDARTRAP:
419 case OIVTRAPDOOR:
420 lprc(objnamelist[k]);
421 break;
422
423 default:
424 setbold();
425 lprc(objnamelist[k]);
426 resetbold();
427 };
428 know[i][j] = 1;
429 }
430 m = maxx;
431 }
432 }
433
434 /*
435 this routine shows only the spot that is given it. the spaces around
436 these coordinated are not shown
437 used in godirect() in monster.c for missile weapons display
438 */
439 void
440 show1cell(x, y)
441 int x, y;
442 {
443 if (c[BLINDCOUNT])
444 return; /* see nothing if blind */
445 cursor(x + 1, y + 1);
446 if ((k = mitem[x][y]) != 0)
447 lprc(monstnamelist[k]);
448 else
449 switch (k = item[x][y]) {
450 case OWALL:
451 case 0:
452 case OIVTELETRAP:
453 case OTRAPARROWIV:
454 case OIVDARTRAP:
455 case OIVTRAPDOOR:
456 lprc(objnamelist[k]);
457 break;
458
459 default:
460 setbold();
461 lprc(objnamelist[k]);
462 resetbold();
463 };
464 know[x][y] |= 1; /* we end up knowing about it */
465 }
466
467 /*
468 showplayer()
469
470 subroutine to show where the player is on the screen
471 cursor values start from 1 up
472 */
473 void
474 showplayer()
475 {
476 cursor(playerx + 1, playery + 1);
477 oldx = playerx;
478 oldy = playery;
479 }
480
481 /*
482 moveplayer(dir)
483
484 subroutine to move the player from one room to another
485 returns 0 if can't move in that direction or hit a monster or on an object
486 else returns 1
487 nomove is set to 1 to stop the next move (inadvertent monsters hitting
488 players when walking into walls) if player walks off screen or into wall
489 */
490 short diroffx[] = {0, 0, 1, 0, -1, 1, -1, 1, -1};
491 short diroffy[] = {0, 1, 0, -1, 0, -1, -1, 1, 1};
492 int
493 moveplayer(dir)
494 int dir; /* from = present room # direction =
495 * [1-north] [2-east] [3-south] [4-west]
496 * [5-northeast] [6-northwest] [7-southeast]
497 * [8-southwest] if direction=0, don't
498 * move--just show where he is */
499 {
500 int k, m, i, j;
501 if (c[CONFUSE])
502 if (c[LEVEL] < rnd(30))
503 dir = rund(9); /* if confused any dir */
504 k = playerx + diroffx[dir];
505 m = playery + diroffy[dir];
506 if (k < 0 || k >= MAXX || m < 0 || m >= MAXY) {
507 nomove = 1;
508 return (yrepcount = 0);
509 }
510 i = item[k][m];
511 j = mitem[k][m];
512 if (i == OWALL && c[WTW] == 0) {
513 nomove = 1;
514 return (yrepcount = 0);
515 } /* hit a wall */
516 if (k == 33 && m == MAXY - 1 && level == 1) {
517 newcavelevel(0);
518 for (k = 0; k < MAXX; k++)
519 for (m = 0; m < MAXY; m++)
520 if (item[k][m] == OENTRANCE) {
521 playerx = k;
522 playery = m;
523 positionplayer();
524 drawscreen();
525 return (0);
526 }
527 }
528 if (j > 0) {
529 hitmonster(k, m);
530 return (yrepcount = 0);
531 } /* hit a monster */
532 lastpx = playerx;
533 lastpy = playery;
534 playerx = k;
535 playery = m;
536 if (i && i != OTRAPARROWIV && i != OIVTELETRAP && i != OIVDARTRAP && i != OIVTRAPDOOR)
537 return (yrepcount = 0);
538 else
539 return (1);
540 }
541
542
543 /*
544 * function to show what magic items have been discovered thus far
545 * enter with -1 for just spells, anything else will give scrolls & potions
546 */
547 static int lincount, count;
548 void
549 seemagic(arg)
550 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 void
618 seepage()
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 }