]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - larn/display.c
don't use char values for functions that can return -1; chars are not always
[bsdgames-darwin.git] / larn / display.c
1 /* $NetBSD: display.c,v 1.8 2008/02/03 19:20:41 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.8 2008/02/03 19:20:41 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 char always = 0;
23 /*
24 bottomline()
25
26 now for the bottom line of the display
27 */
28 void
29 bottomline()
30 {
31 recalc();
32 bot1f = 1;
33 }
34
35 void
36 bottomhp()
37 {
38 bot2f = 1;
39 }
40
41 void
42 bottomspell()
43 {
44 bot3f = 1;
45 }
46
47 void
48 bottomdo()
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()
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()
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 int d_xmin = 0, d_xmax = MAXX, d_ymin = 0, d_ymax = MAXY;
245
246 void
247 draws(xmin, xmax, ymin, ymax)
248 int xmin, xmax, ymin, ymax;
249 {
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;
259 }
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);
272 }
273 cbak[idx] = c[idx];
274 }
275 }
276 }
277
278 /*
279 drawscreen()
280
281 subroutine to redraw the whole screen as the player knows it
282 */
283 u_char screen[MAXX][MAXY], d_flag; /* template for the screen */
284 void
285 drawscreen()
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(x, y)
379 int x, y;
380 {
381 int i, j, kk, mm;
382 if (c[BLINDCOUNT])
383 return; /* see nothing if blind */
384 if (c[AWARENESS]) {
385 minx = x - 3;
386 maxx = x + 3;
387 miny = y - 3;
388 maxy = y + 3;
389 } else {
390 minx = x - 1;
391 maxx = x + 1;
392 miny = y - 1;
393 maxy = y + 1;
394 }
395
396 if (minx < 0)
397 minx = 0;
398 if (maxx > MAXX - 1)
399 maxx = MAXX - 1;
400 if (miny < 0)
401 miny = 0;
402 if (maxy > MAXY - 1)
403 maxy = MAXY - 1;
404
405 for (j = miny; j <= maxy; j++)
406 for (mm = minx; mm <= maxx; mm++)
407 if (know[mm][j] == 0) {
408 cursor(mm + 1, j + 1);
409 x = maxx;
410 while (know[x][j])
411 --x;
412 for (i = mm; i <= x; i++) {
413 if ((kk = mitem[i][j]) != 0)
414 lprc(monstnamelist[kk]);
415 else
416 switch (kk = item[i][j]) {
417 case OWALL:
418 case 0:
419 case OIVTELETRAP:
420 case OTRAPARROWIV:
421 case OIVDARTRAP:
422 case OIVTRAPDOOR:
423 lprc(objnamelist[kk]);
424 break;
425
426 default:
427 setbold();
428 lprc(objnamelist[kk]);
429 resetbold();
430 };
431 know[i][j] = 1;
432 }
433 mm = maxx;
434 }
435 }
436
437 /*
438 this routine shows only the spot that is given it. the spaces around
439 these coordinated are not shown
440 used in godirect() in monster.c for missile weapons display
441 */
442 void
443 show1cell(x, y)
444 int x, y;
445 {
446 if (c[BLINDCOUNT])
447 return; /* see nothing if blind */
448 cursor(x + 1, y + 1);
449 if ((k = mitem[x][y]) != 0)
450 lprc(monstnamelist[k]);
451 else
452 switch (k = item[x][y]) {
453 case OWALL:
454 case 0:
455 case OIVTELETRAP:
456 case OTRAPARROWIV:
457 case OIVDARTRAP:
458 case OIVTRAPDOOR:
459 lprc(objnamelist[k]);
460 break;
461
462 default:
463 setbold();
464 lprc(objnamelist[k]);
465 resetbold();
466 };
467 know[x][y] |= 1; /* we end up knowing about it */
468 }
469
470 /*
471 showplayer()
472
473 subroutine to show where the player is on the screen
474 cursor values start from 1 up
475 */
476 void
477 showplayer()
478 {
479 cursor(playerx + 1, playery + 1);
480 oldx = playerx;
481 oldy = playery;
482 }
483
484 /*
485 moveplayer(dir)
486
487 subroutine to move the player from one room to another
488 returns 0 if can't move in that direction or hit a monster or on an object
489 else returns 1
490 nomove is set to 1 to stop the next move (inadvertent monsters hitting
491 players when walking into walls) if player walks off screen or into wall
492 */
493 short diroffx[] = {0, 0, 1, 0, -1, 1, -1, 1, -1};
494 short diroffy[] = {0, 1, 0, -1, 0, -1, -1, 1, 1};
495 int
496 moveplayer(dir)
497 int dir; /* from = present room # direction =
498 * [1-north] [2-east] [3-south] [4-west]
499 * [5-northeast] [6-northwest] [7-southeast]
500 * [8-southwest] if direction=0, don't
501 * move--just show where he is */
502 {
503 int kk, mm, i, j;
504 if (c[CONFUSE])
505 if (c[LEVEL] < rnd(30))
506 dir = rund(9); /* if confused any dir */
507 kk = playerx + diroffx[dir];
508 mm = playery + diroffy[dir];
509 if (kk < 0 || kk >= MAXX || mm < 0 || mm >= MAXY) {
510 nomove = 1;
511 return (yrepcount = 0);
512 }
513 i = item[kk][mm];
514 j = mitem[kk][mm];
515 if (i == OWALL && c[WTW] == 0) {
516 nomove = 1;
517 return (yrepcount = 0);
518 } /* hit a wall */
519 if (kk == 33 && mm == MAXY - 1 && level == 1) {
520 newcavelevel(0);
521 for (kk = 0; kk < MAXX; kk++)
522 for (mm = 0; mm < MAXY; mm++)
523 if (item[kk][mm] == OENTRANCE) {
524 playerx = kk;
525 playery = mm;
526 positionplayer();
527 drawscreen();
528 return (0);
529 }
530 }
531 if (j > 0) {
532 hitmonster(kk, mm);
533 return (yrepcount = 0);
534 } /* hit a monster */
535 lastpx = playerx;
536 lastpy = playery;
537 playerx = kk;
538 playery = mm;
539 if (i && i != OTRAPARROWIV && i != OIVTELETRAP && i != OIVDARTRAP && i != OIVTRAPDOOR)
540 return (yrepcount = 0);
541 else
542 return (1);
543 }
544
545
546 /*
547 * function to show what magic items have been discovered thus far
548 * enter with -1 for just spells, anything else will give scrolls & potions
549 */
550 static int lincount, count;
551 void
552 seemagic(arg)
553 int arg;
554 {
555 int i, number = 0;
556 count = lincount = 0;
557 nosignal = 1;
558
559 if (arg == -1) { /* if display spells while casting one */
560 for (number = i = 0; i < SPNUM; i++)
561 if (spelknow[i])
562 number++;
563 number = (number + 2) / 3 + 4; /* # lines needed to display */
564 cl_up(79, number);
565 cursor(1, 1);
566 } else {
567 resetscroll();
568 clear();
569 }
570
571 lprcat("The magic spells you have discovered thus far:\n\n");
572 for (i = 0; i < SPNUM; i++)
573 if (spelknow[i]) {
574 lprintf("%s %-20s ", spelcode[i], spelname[i]);
575 seepage();
576 }
577 if (arg == -1) {
578 seepage();
579 more();
580 nosignal = 0;
581 draws(0, MAXX, 0, number);
582 return;
583 }
584 lincount += 3;
585 if (count != 0) {
586 count = 2;
587 seepage();
588 }
589 lprcat("\nThe magic scrolls you have found to date are:\n\n");
590 count = 0;
591 for (i = 0; i < MAXSCROLL; i++)
592 if (scrollname[i][0])
593 if (scrollname[i][1] != ' ') {
594 lprintf("%-26s", &scrollname[i][1]);
595 seepage();
596 }
597 lincount += 3;
598 if (count != 0) {
599 count = 2;
600 seepage();
601 }
602 lprcat("\nThe magic potions you have found to date are:\n\n");
603 count = 0;
604 for (i = 0; i < MAXPOTION; i++)
605 if (potionname[i][0])
606 if (potionname[i][1] != ' ') {
607 lprintf("%-26s", &potionname[i][1]);
608 seepage();
609 }
610 if (lincount != 0)
611 more();
612 nosignal = 0;
613 setscroll();
614 drawscreen();
615 }
616
617 /*
618 * subroutine to paginate the seemagic function
619 */
620 static void
621 seepage(void)
622 {
623 if (++count == 3) {
624 lincount++;
625 count = 0;
626 lprc('\n');
627 if (lincount > 17) {
628 lincount = 0;
629 more();
630 clear();
631 }
632 }
633 }