drm/linux: Add clamp_val()
[dragonfly.git] / games / hack / hack.pri.c
blob86629ed7799af2060caa4cb12063dcc390e4fc27
1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
2 /* hack.pri.c - version 1.0.3 */
3 /* $FreeBSD: src/games/hack/hack.pri.c,v 1.5 1999/11/16 10:26:37 marcel Exp $ */
4 /* $DragonFly: src/games/hack/hack.pri.c,v 1.5 2006/08/21 19:45:32 pavalos Exp $ */
6 #include "hack.h"
7 #include <curses.h>
8 xchar scrlx, scrhx, scrly, scrhy; /* corners of new area on screen */
10 extern char *CD;
12 #ifdef NEWSCR
13 static void pobj(struct obj *);
14 #endif
15 static void cornbot(int);
17 void
18 swallowed(void)
20 char ulook[] = { "|@|" };
22 ulook[1] = u.usym;
24 cls();
25 curs(u.ux - 1, u.uy + 1);
26 fputs("/-\\", stdout);
27 curx = u.ux + 2;
28 curs(u.ux - 1, u.uy + 2);
29 fputs(ulook, stdout);
30 curx = u.ux + 2;
31 curs(u.ux - 1, u.uy + 3);
32 fputs("\\-/", stdout);
33 curx = u.ux + 2;
34 u.udispl = 1;
35 u.udisx = u.ux;
36 u.udisy = u.uy;
39 /* VARARGS1 */
40 boolean panicking;
42 void
43 panic(const char *str, ...)
45 va_list ap;
47 if (panicking++) /* avoid loops - this should never happen*/
48 exit(1);
49 home();
50 puts(" Suddenly, the dungeon collapses.");
51 fputs(" ERROR: ", stdout);
52 va_start(ap, str);
53 vprintf(str, ap);
54 va_end(ap);
55 #ifdef DEBUG
56 #ifdef UNIX
57 if (!fork())
58 abort(); /* generate core dump */
59 #endif /* UNIX */
60 #endif /* DEBUG */
61 more(); /* contains a fflush() */
62 done("panicked");
65 void
66 atl(int x, int y, char ch)
68 struct rm *crm = &levl[x][y];
70 if (x < 0 || x > COLNO - 1 || y < 0 || y > ROWNO - 1) {
71 impossible("atl(%d,%d,%c)", x, y, ch);
72 return;
74 if (crm->seen && crm->scrsym == ch)
75 return;
76 crm->scrsym = ch;
77 crm->new = 1;
78 on_scr(x, y);
81 void
82 on_scr(int x, int y)
84 if (x < scrlx)
85 scrlx = x;
86 if (x > scrhx)
87 scrhx = x;
88 if (y < scrly)
89 scrly = y;
90 if (y > scrhy)
91 scrhy = y;
94 /* call: (x,y) - display
95 * (-1,0) - close (leave last symbol)
96 * (-1,-1)- close (undo last symbol)
97 * (-1,let)-open: initialize symbol
98 * (-2,let)-change let
101 void
102 tmp_at(schar x, schar y)
104 static schar prevx, prevy;
105 static char let;
107 if ((int)x == -2) { /* change let call */
108 let = y;
109 return;
111 if ((int)x == -1 && (int)y >= 0) { /* open or close call */
112 let = y;
113 prevx = -1;
114 return;
116 if (prevx >= 0 && cansee(prevx, prevy)) {
117 delay_output(50);
118 prl(prevx, prevy); /* in case there was a monster */
119 at(prevx, prevy, levl[prevx][prevy].scrsym);
121 if (x >= 0) { /* normal call */
122 if (cansee(x, y))
123 at(x, y, let);
124 prevx = x;
125 prevy = y;
126 } else { /* close call */
127 let = 0;
128 prevx = -1;
132 /* like the previous, but the symbols are first erased on completion */
133 void
134 Tmp_at(schar x, schar y)
136 static char let;
137 static xchar cnt;
138 static coord tc[COLNO]; /* but watch reflecting beams! */
139 int xx, yy;
141 if ((int)x == -1) {
142 if (y > 0) { /* open call */
143 let = y;
144 cnt = 0;
145 return;
147 /* close call (do not distinguish y==0 and y==-1) */
148 while (cnt--) {
149 xx = tc[cnt].x;
150 yy = tc[cnt].y;
151 prl(xx, yy);
152 at(xx, yy, levl[xx][yy].scrsym);
154 cnt = let = 0; /* superfluous */
155 return;
157 if ((int)x == -2) { /* change let call */
158 let = y;
159 return;
161 /* normal call */
162 if (cansee(x, y)) {
163 if (cnt)
164 delay_output(50);
165 at(x, y, let);
166 tc[cnt].x = x;
167 tc[cnt].y = y;
168 if (++cnt >= COLNO)
169 panic("Tmp_at overflow?");
170 levl[x][y].new = 0; /* prevent pline-nscr erasing --- */
174 void
175 setclipped(void)
177 error("Hack needs a screen of size at least %d by %d.\n",
178 ROWNO + 2, COLNO);
181 void
182 at(xchar x, xchar y, char ch)
184 #ifndef lint
185 /* if xchar is unsigned, lint will complain about if (x < 0) */
186 if (x < 0 || x > COLNO - 1 || y < 0 || y > ROWNO - 1) {
187 impossible("At gets 0%o at %d %d.", ch, x, y);
188 return;
190 #endif /* lint */
191 if (!ch) {
192 impossible("At gets null at %d %d.", x, y);
193 return;
195 y += 2;
196 curs(x, y);
197 putchar(ch);
198 curx++;
201 void
202 prme(void)
204 if (!Invisible)
205 at(u.ux, u.uy, u.usym);
209 doredraw(void)
211 docrt();
212 return (0);
215 void
216 docrt(void)
218 int x, y;
219 struct rm *room;
220 struct monst *mtmp;
222 if (u.uswallow) {
223 swallowed();
224 return;
226 cls();
228 /* Some ridiculous code to get display of @ and monsters (almost) right */
229 if (!Invisible) {
230 levl[(u.udisx = u.ux)][(u.udisy = u.uy)].scrsym = u.usym;
231 levl[u.udisx][u.udisy].seen = 1;
232 u.udispl = 1;
233 } else
234 u.udispl = 0;
236 seemons(); /* reset old positions */
237 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
238 mtmp->mdispl = 0;
239 seemons(); /* force new positions to be shown */
240 /* This nonsense should disappear soon --------------------------------- */
242 for (y = 0; y < ROWNO; y++)
243 for (x = 0; x < COLNO; x++)
244 if ((room = &levl[x][y])->new) {
245 room->new = 0;
246 at(x, y, room->scrsym);
247 } else if (room->seen)
248 at(x, y, room->scrsym);
249 scrlx = COLNO;
250 scrly = ROWNO;
251 scrhx = scrhy = 0;
252 flags.botlx = 1;
253 bot();
256 void
257 docorner(int xmin, int ymax)
259 int x, y;
260 struct rm *room;
261 struct monst *mtmp;
263 if (u.uswallow) { /* Can be done more efficiently */
264 swallowed();
265 return;
267 seemons(); /* reset old positions */
268 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
269 if (mtmp->mx >= xmin && mtmp->my < ymax)
270 mtmp->mdispl = 0;
271 seemons(); /* force new positions to be shown */
273 for (y = 0; y < ymax; y++) {
274 if (y > ROWNO && CD)
275 break;
276 curs(xmin, y + 2);
277 cl_end();
278 if (y < ROWNO) {
279 for (x = xmin; x < COLNO; x++) {
280 if ((room = &levl[x][y])->new) {
281 room->new = 0;
282 at(x, y, room->scrsym);
283 } else if (room->seen)
284 at(x, y, room->scrsym);
288 if (ymax > ROWNO) {
289 cornbot(xmin - 1);
290 if (ymax > ROWNO + 1 && CD) {
291 curs(1, ROWNO + 3);
292 cl_eos();
297 void
298 curs_on_u(void)
300 curs(u.ux, u.uy + 2);
303 void
304 pru(void)
306 if (u.udispl && (Invisible || u.udisx != u.ux || u.udisy != u.uy))
307 if (!vism_at(u.udisx, u.udisy))
308 newsym(u.udisx, u.udisy);
309 if (Invisible) {
310 u.udispl = 0;
311 prl(u.ux, u.uy);
312 } else if (!u.udispl || u.udisx != u.ux || u.udisy != u.uy) {
313 atl(u.ux, u.uy, u.usym);
314 u.udispl = 1;
315 u.udisx = u.ux;
316 u.udisy = u.uy;
318 levl[u.ux][u.uy].seen = 1;
321 #ifndef NOWORM
322 extern struct wseg *m_atseg;
323 #endif /* NOWORM */
325 /* print a position that is visible for @ */
326 void
327 prl(int x, int y)
329 struct rm *room;
330 struct monst *mtmp;
331 struct obj *otmp;
333 if (x == u.ux && y == u.uy && (!Invisible)) {
334 pru();
335 return;
337 if (!isok(x, y))
338 return;
339 room = &levl[x][y];
340 if ((!room->typ) ||
341 (IS_ROCK(room->typ) && levl[u.ux][u.uy].typ == CORR))
342 return;
343 if ((mtmp = m_at(x, y)) && !mtmp->mhide &&
344 (!mtmp->minvis || See_invisible)) {
345 #ifndef NOWORM
346 if (m_atseg)
347 pwseg(m_atseg);
348 else
349 #endif /* NOWORM */
350 pmon(mtmp);
351 } else if ((otmp = o_at(x, y)) && room->typ != POOL)
352 atl(x, y, otmp->olet);
353 else if (mtmp && (!mtmp->minvis || See_invisible)) {
354 /* must be a hiding monster, but not hiding right now */
355 /* assume for the moment that long worms do not hide */
356 pmon(mtmp);
357 } else if (g_at(x, y) && room->typ != POOL)
358 atl(x, y, '$');
359 else if (!room->seen || room->scrsym == ' ') {
360 room->new = room->seen = 1;
361 newsym(x, y);
362 on_scr(x, y);
364 room->seen = 1;
367 char
368 news0(xchar x, xchar y)
370 struct obj *otmp;
371 struct trap *ttmp;
372 struct rm *room;
373 char tmp;
375 room = &levl[x][y];
376 if (!room->seen)
377 tmp = ' ';
378 else if (room->typ == POOL)
379 tmp = POOL_SYM;
380 else if (!Blind && (otmp = o_at(x, y)))
381 tmp = otmp->olet;
382 else if (!Blind && g_at(x, y))
383 tmp = '$';
384 else if (x == xupstair && y == yupstair)
385 tmp = '<';
386 else if (x == xdnstair && y == ydnstair)
387 tmp = '>';
388 else if ((ttmp = t_at(x, y)) && ttmp->tseen)
389 tmp = '^';
390 else
391 switch (room->typ) {
392 case SCORR:
393 case SDOOR:
394 tmp = room->scrsym; /* %% wrong after killing mimic ! */
395 break;
396 case HWALL:
397 tmp = '-';
398 break;
399 case VWALL:
400 tmp = '|';
401 break;
402 case LDOOR:
403 case DOOR:
404 tmp = '+';
405 break;
406 case CORR:
407 tmp = CORR_SYM;
408 break;
409 case ROOM:
410 if (room->lit || cansee(x, y) || Blind)
411 tmp = '.';
412 else
413 tmp = ' ';
414 break;
415 default:
416 tmp = ERRCHAR;
418 return (tmp);
421 void
422 newsym(int x, int y)
424 atl(x, y, news0(x, y));
427 /* used with wand of digging (or pick-axe): fill scrsym and force display */
428 /* also when a POOL evaporates */
429 void
430 mnewsym(int x, int y)
432 struct rm *room;
433 char newscrsym;
435 if (!vism_at(x, y)) {
436 room = &levl[x][y];
437 newscrsym = news0(x, y);
438 if (room->scrsym != newscrsym) {
439 room->scrsym = newscrsym;
440 room->seen = 0;
445 void
446 nosee(int x, int y)
448 struct rm *room;
450 if (!isok(x, y))
451 return;
452 room = &levl[x][y];
453 if (room->scrsym == '.' && !room->lit && !Blind) {
454 room->scrsym = ' ';
455 room->new = 1;
456 on_scr(x, y);
460 #ifndef QUEST
461 void
462 prl1(int x, int y)
464 if (u.dx) {
465 if (u.dy) {
466 prl(x - (2 * u.dx), y);
467 prl(x - u.dx, y);
468 prl(x, y);
469 prl(x, y - u.dy);
470 prl(x, y - (2 * u.dy));
471 } else {
472 prl(x, y - 1);
473 prl(x, y);
474 prl(x, y + 1);
476 } else {
477 prl(x - 1, y);
478 prl(x, y);
479 prl(x + 1, y);
483 void
484 nose1(int x, int y)
486 if (u.dx) {
487 if (u.dy) {
488 nosee(x, u.uy);
489 nosee(x, u.uy - u.dy);
490 nosee(x, y);
491 nosee(u.ux - u.dx, y);
492 nosee(u.ux, y);
493 } else {
494 nosee(x, y - 1);
495 nosee(x, y);
496 nosee(x, y + 1);
498 } else {
499 nosee(x - 1, y);
500 nosee(x, y);
501 nosee(x + 1, y);
504 #endif /* QUEST */
506 bool
507 vism_at(int x, int y)
509 struct monst *mtmp;
511 return ((x == u.ux && y == u.uy && !Invisible)
512 ? 1 :
513 (mtmp = m_at(x, y))
514 ? ((Blind && Telepat) || canseemon(mtmp)) :
518 #ifdef NEWSCR
519 static void
520 pobj(struct obj *obj)
522 int show = (!obj->oinvis || See_invisible) &&
523 cansee(obj->ox, obj->oy);
525 if (obj->odispl) {
526 if (obj->odx != obj->ox || obj->ody != obj->oy || !show)
527 if (!vism_at(obj->odx, obj->ody)) {
528 newsym(obj->odx, obj->ody);
529 obj->odispl = 0;
532 if (show && !vism_at(obj->ox, obj->oy)) {
533 atl(obj->ox, obj->oy, obj->olet);
534 obj->odispl = 1;
535 obj->odx = obj->ox;
536 obj->ody = obj->oy;
539 #endif /* NEWSCR */
541 void
542 unpobj(struct obj *obj)
544 if (!vism_at(obj->ox, obj->oy))
545 newsym(obj->ox, obj->oy);
548 void
549 seeobjs(void)
551 struct obj *obj, *obj2;
553 for (obj = fobj; obj; obj = obj2) {
554 obj2 = obj->nobj;
555 if (obj->olet == FOOD_SYM && obj->otyp >= CORPSE
556 && obj->age + 250 < moves)
557 delobj(obj);
559 for (obj = invent; obj; obj = obj2) {
560 obj2 = obj->nobj;
561 if (obj->olet == FOOD_SYM && obj->otyp >= CORPSE
562 && obj->age + 250 < moves)
563 useup(obj);
567 void
568 seemons(void)
570 struct monst *mtmp;
572 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
573 if (mtmp->data->mlet == ';')
574 mtmp->minvis = (u.ustuck != mtmp &&
575 levl[mtmp->mx][mtmp->my].typ == POOL);
576 pmon(mtmp);
577 #ifndef NOWORM
578 if (mtmp->wormno)
579 wormsee(mtmp->wormno);
580 #endif /* NOWORM */
584 void
585 pmon(struct monst *mon)
587 int show = (Blind && Telepat) || canseemon(mon);
589 if (mon->mdispl) {
590 if (mon->mdx != mon->mx || mon->mdy != mon->my || !show)
591 unpmon(mon);
593 if (show && !mon->mdispl) {
594 atl(mon->mx, mon->my,
595 (!mon->mappearance
596 || u.uprops[PROP(RIN_PROTECTION_FROM_SHAPE_CHANGERS)].p_flgs
597 ) ? mon->data->mlet : mon->mappearance);
598 mon->mdispl = 1;
599 mon->mdx = mon->mx;
600 mon->mdy = mon->my;
604 void
605 unpmon(struct monst *mon)
607 if (mon->mdispl) {
608 newsym(mon->mdx, mon->mdy);
609 mon->mdispl = 0;
613 void
614 nscr(void)
616 int x, y;
617 struct rm *room;
619 if (u.uswallow || u.ux == FAR || flags.nscrinh)
620 return;
621 pru();
622 for (y = scrly; y <= scrhy; y++)
623 for (x = scrlx; x <= scrhx; x++)
624 if ((room = &levl[x][y])->new) {
625 room->new = 0;
626 at(x, y, room->scrsym);
628 scrhx = scrhy = 0;
629 scrlx = COLNO;
630 scrly = ROWNO;
633 /* 100 suffices for bot(); no relation with COLNO */
634 char oldbot[100], newbot[100];
636 static void
637 cornbot(int lth)
639 if (lth < (int)sizeof(oldbot)) {
640 oldbot[lth] = 0;
641 flags.botl = 1;
645 void
646 bot(void)
648 char *ob = oldbot, *nb = newbot;
649 int i;
651 if (flags.botlx)
652 *ob = 0;
653 flags.botl = flags.botlx = 0;
654 #ifdef GOLD_ON_BOTL
655 sprintf(newbot,
656 "Level %-2d Gold %-5lu Hp %3d(%d) Ac %-2d Str ",
657 dlevel, u.ugold, u.uhp, u.uhpmax, u.uac);
658 #else
659 sprintf(newbot,
660 "Level %-2d Hp %3d(%d) Ac %-2d Str ",
661 dlevel, u.uhp, u.uhpmax, u.uac);
662 #endif /* GOLD_ON_BOTL */
663 if (u.ustr > 18) {
664 if (u.ustr > 117)
665 strcat(newbot, "18/**");
666 else
667 sprintf(eos(newbot), "18/%02d", u.ustr - 18);
668 } else
669 sprintf(eos(newbot), "%-2d ", u.ustr);
670 #ifdef EXP_ON_BOTL
671 sprintf(eos(newbot), " Exp %2d/%-5lu ", u.ulevel, u.uexp);
672 #else
673 sprintf(eos(newbot), " Exp %2u ", u.ulevel);
674 #endif /* EXP_ON_BOTL */
675 strcat(newbot, hu_stat[u.uhs]);
676 if (flags.time)
677 sprintf(eos(newbot), " %ld", moves);
678 if (strlen(newbot) >= COLNO) {
679 char *bp0, *bp1;
680 bp0 = bp1 = newbot;
681 do {
682 if (*bp0 != ' ' || bp0[1] != ' ' || bp0[2] != ' ')
683 *bp1++ = *bp0;
684 } while (*bp0++);
686 for (i = 1; i < COLNO; i++) {
687 if (*ob != *nb) {
688 curs(i, ROWNO + 2);
689 putchar(*nb ? *nb : ' ');
690 curx++;
692 if (*ob)
693 ob++;
694 if (*nb)
695 nb++;
697 strcpy(oldbot, newbot);
700 #ifdef WAN_PROBING
701 void
702 mstatusline(struct monst *mtmp)
704 pline("Status of %s: ", monnam(mtmp));
705 pline("Level %-2d Gold %-5lu Hp %3d(%d) Ac %-2d Dam %d",
706 mtmp->data->mlevel, mtmp->mgold, mtmp->mhp, mtmp->mhpmax,
707 mtmp->data->ac, (mtmp->data->damn + 1) * (mtmp->data->damd + 1));
709 #endif /* WAN_PROBING */
711 void
712 cls(void)
714 if (flags.toplin == 1)
715 more();
716 flags.toplin = 0;
718 clear_screen();
720 flags.botlx = 1;