xref: /openbsd-src/games/hack/hack.pri.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*	$OpenBSD: hack.pri.c,v 1.10 2009/10/27 23:59:25 deraadt Exp $	*/
2 
3 /*
4  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
5  * Amsterdam
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are
10  * met:
11  *
12  * - Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * - Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  *
19  * - Neither the name of the Stichting Centrum voor Wiskunde en
20  * Informatica, nor the names of its contributors may be used to endorse or
21  * promote products derived from this software without specific prior
22  * written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 /*
38  * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39  * All rights reserved.
40  *
41  * Redistribution and use in source and binary forms, with or without
42  * modification, are permitted provided that the following conditions
43  * are met:
44  * 1. Redistributions of source code must retain the above copyright
45  *    notice, this list of conditions and the following disclaimer.
46  * 2. Redistributions in binary form must reproduce the above copyright
47  *    notice, this list of conditions and the following disclaimer in the
48  *    documentation and/or other materials provided with the distribution.
49  * 3. The name of the author may not be used to endorse or promote products
50  *    derived from this software without specific prior written permission.
51  *
52  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
55  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62  */
63 
64 #include <curses.h>
65 #include <stdio.h>
66 #include <stdlib.h>
67 #include <stdarg.h>
68 #include "hack.h"
69 
70 xchar scrlx, scrhx, scrly, scrhy;	/* corners of new area on screen */
71 
72 extern char *hu_stat[];	/* in eat.c */
73 extern char *CD;
74 
75 static void cornbot(int);
76 
77 void
78 swallowed()
79 {
80 	char ulook[] = "|@|";
81 	ulook[1] = u.usym;
82 
83 	cls();
84 	curs(u.ux-1, u.uy+1);
85 	fputs("/-\\", stdout);
86 	curx = u.ux+2;
87 	curs(u.ux-1, u.uy+2);
88 	fputs(ulook, stdout);
89 	curx = u.ux+2;
90 	curs(u.ux-1, u.uy+3);
91 	fputs("\\-/", stdout);
92 	curx = u.ux+2;
93 	u.udispl = 1;
94 	u.udisx = u.ux;
95 	u.udisy = u.uy;
96 }
97 
98 
99 /*VARARGS1*/
100 boolean panicking;
101 
102 void
103 panic(char *str, ...)
104 {
105 	va_list ap;
106 
107 	if(panicking++) exit(1);    /* avoid loops - this should never happen*/
108 	home();
109 	puts(" Suddenly, the dungeon collapses.");
110 	fputs(" ERROR:  ", stdout);
111 	va_start(ap, str);
112 	vprintf(str, ap);
113 	va_end(ap);
114 #ifdef DEBUG
115 #ifdef UNIX
116 	if(!fork())
117 		abort();	/* generate core dump */
118 #endif /* UNIX */
119 #endif /* DEBUG */
120 	more();			/* contains a fflush() */
121 	done("panicked");
122 }
123 
124 void
125 atl(int x, int y, int ch)
126 {
127 	struct rm *crm = &levl[x][y];
128 
129 	if(x<0 || x>COLNO-1 || y<0 || y>ROWNO-1){
130 		impossible("atl(%d,%d,%c)",x,y,ch);
131 		return;
132 	}
133 	if(crm->seen && crm->scrsym == ch) return;
134 	crm->scrsym = ch;
135 	crm->new = 1;
136 	on_scr(x,y);
137 }
138 
139 void
140 on_scr(int x, int y)
141 {
142 	if(x < scrlx) scrlx = x;
143 	if(x > scrhx) scrhx = x;
144 	if(y < scrly) scrly = y;
145 	if(y > scrhy) scrhy = y;
146 }
147 
148 /* call: (x,y) - display
149  *	(-1,0) - close (leave last symbol)
150  *	(-1,-1)- close (undo last symbol)
151  *	(-1,let)-open: initialize symbol
152  *	(-2,let)-change let
153  */
154 void
155 tmp_at(schar x, schar y)
156 {
157 	static schar prevx, prevy;
158 	static char let;
159 
160 	if((int)x == -2){	/* change let call */
161 		let = y;
162 		return;
163 	}
164 	if((int)x == -1 && (int)y >= 0){	/* open or close call */
165 		let = y;
166 		prevx = -1;
167 		return;
168 	}
169 	if(prevx >= 0 && cansee(prevx,prevy)) {
170 		delay_output(50);
171 		prl(prevx, prevy);	/* in case there was a monster */
172 		at(prevx, prevy, levl[(int)prevx][(int)prevy].scrsym);
173 	}
174 	if(x >= 0){	/* normal call */
175 		if(cansee(x,y)) at(x,y,let);
176 		prevx = x;
177 		prevy = y;
178 	} else {	/* close call */
179 		let = 0;
180 		prevx = -1;
181 	}
182 }
183 
184 /* like the previous, but the symbols are first erased on completion */
185 void
186 Tmp_at(schar x, schar y)
187 {
188 	static char let;
189 	static xchar cnt;
190 	static coord tc[COLNO];		/* but watch reflecting beams! */
191 	int xx,yy;
192 
193 	if((int)x == -1) {
194 		if(y > 0) {	/* open call */
195 			let = y;
196 			cnt = 0;
197 			return;
198 		}
199 		/* close call (do not distinguish y==0 and y==-1) */
200 		while(cnt--) {
201 			xx = tc[(int)cnt].x;
202 			yy = tc[(int)cnt].y;
203 			prl(xx, yy);
204 			at(xx, yy, levl[xx][yy].scrsym);
205 		}
206 		cnt = let = 0;	/* superfluous */
207 		return;
208 	}
209 	if((int)x == -2) {	/* change let call */
210 		let = y;
211 		return;
212 	}
213 	/* normal call */
214 	if(cansee(x,y)) {
215 		if(cnt) delay_output(50);
216 		at(x,y,let);
217 		tc[(int)cnt].x = x;
218 		tc[(int)cnt].y = y;
219 		if(++cnt >= COLNO) panic("Tmp_at overflow?");
220 		levl[(int)x][(int)y].new = 0;	/* prevent pline-nscr erasing --- */
221 	}
222 }
223 
224 void
225 setclipped()
226 {
227 	error("Hack needs a screen of size at least %d by %d.\n",
228 		ROWNO+2, COLNO);
229 }
230 
231 void
232 at(xchar x, xchar y, char ch)
233 {
234 #ifndef lint
235 	/* if xchar is unsigned, lint will complain about  if(x < 0)  */
236 	if(x < 0 || x > COLNO-1 || y < 0 || y > ROWNO-1) {
237 		impossible("At gets 0%o at %d %d.", ch, x, y);
238 		return;
239 	}
240 #endif /* lint */
241 	if(!ch) {
242 		impossible("At gets null at %d %d.", x, y);
243 		return;
244 	}
245 	y += 2;
246 	curs(x,y);
247 	(void) putchar(ch);
248 	curx++;
249 }
250 
251 void
252 prme()
253 {
254 	if(!Invisible) at(u.ux,u.uy,u.usym);
255 }
256 
257 int
258 doredraw()
259 {
260 	docrt();
261 	return(0);
262 }
263 
264 void
265 docrt()
266 {
267 	int x,y;
268 	struct rm *room;
269 	struct monst *mtmp;
270 
271 	if(u.uswallow) {
272 		swallowed();
273 		return;
274 	}
275 	cls();
276 
277 /* Some ridiculous code to get display of @ and monsters (almost) right */
278 	if(!Invisible) {
279 		levl[(int)(u.udisx = u.ux)][(int)(u.udisy = u.uy)].scrsym = u.usym;
280 		levl[(int)u.udisx][(int)u.udisy].seen = 1;
281 		u.udispl = 1;
282 	} else	u.udispl = 0;
283 
284 	seemons();	/* reset old positions */
285 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
286 		mtmp->mdispl = 0;
287 	seemons();	/* force new positions to be shown */
288 /* This nonsense should disappear soon --------------------------------- */
289 
290 	for(y = 0; y < ROWNO; y++)
291 		for(x = 0; x < COLNO; x++)
292 			if((room = &levl[x][y])->new) {
293 				room->new = 0;
294 				at(x,y,room->scrsym);
295 			} else if(room->seen)
296 				at(x,y,room->scrsym);
297 	scrlx = COLNO;
298 	scrly = ROWNO;
299 	scrhx = scrhy = 0;
300 	flags.botlx = 1;
301 	bot();
302 }
303 
304 void
305 docorner(int xmin, int ymax)
306 {
307 	int x,y;
308 	struct rm *room;
309 	struct monst *mtmp;
310 
311 	if(u.uswallow) {	/* Can be done more efficiently */
312 		swallowed();
313 		return;
314 	}
315 
316 	seemons();	/* reset old positions */
317 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
318 	    if(mtmp->mx >= xmin && mtmp->my < ymax)
319 		mtmp->mdispl = 0;
320 	seemons();	/* force new positions to be shown */
321 
322 	for(y = 0; y < ymax; y++) {
323 		if(y > ROWNO && CD) break;
324 		curs(xmin,y+2);
325 		cl_end();
326 		if(y < ROWNO) {
327 		    for(x = xmin; x < COLNO; x++) {
328 			if((room = &levl[x][y])->new) {
329 				room->new = 0;
330 				at(x,y,room->scrsym);
331 			} else
332 				if(room->seen)
333 					at(x,y,room->scrsym);
334 		    }
335 		}
336 	}
337 	if(ymax > ROWNO) {
338 		cornbot(xmin-1);
339 		if(ymax > ROWNO+1 && CD) {
340 			curs(1,ROWNO+3);
341 			cl_eos();
342 		}
343 	}
344 }
345 
346 void
347 curs_on_u()
348 {
349 	curs(u.ux, u.uy+2);
350 }
351 
352 void
353 pru()
354 {
355 	if(u.udispl && (Invisible || u.udisx != u.ux || u.udisy != u.uy))
356 		/* if(! levl[u.udisx][u.udisy].new) */
357 			if(!vism_at(u.udisx, u.udisy))
358 				newsym(u.udisx, u.udisy);
359 	if(Invisible) {
360 		u.udispl = 0;
361 		prl(u.ux,u.uy);
362 	} else
363 	if(!u.udispl || u.udisx != u.ux || u.udisy != u.uy) {
364 		atl(u.ux, u.uy, u.usym);
365 		u.udispl = 1;
366 		u.udisx = u.ux;
367 		u.udisy = u.uy;
368 	}
369 	levl[(int)u.ux][(int)u.uy].seen = 1;
370 }
371 
372 #ifndef NOWORM
373 extern struct wseg *m_atseg;
374 #endif /* NOWORM */
375 
376 /* print a position that is visible for @ */
377 void
378 prl(int x, int y)
379 {
380 	struct rm *room;
381 	struct monst *mtmp;
382 	struct obj *otmp;
383 
384 	if(x == u.ux && y == u.uy && (!Invisible)) {
385 		pru();
386 		return;
387 	}
388 	if(!isok(x,y)) return;
389 	room = &levl[x][y];
390 	if((!room->typ) ||
391 	   (IS_ROCK(room->typ) && levl[(int)u.ux][(int)u.uy].typ == CORR))
392 		return;
393 	if((mtmp = m_at(x,y)) && !mtmp->mhide &&
394 		(!mtmp->minvis || See_invisible)) {
395 #ifndef NOWORM
396 		if(m_atseg)
397 			pwseg(m_atseg);
398 		else
399 #endif /* NOWORM */
400 		pmon(mtmp);
401 	}
402 	else if((otmp = o_at(x,y)) && room->typ != POOL)
403 		atl(x,y,otmp->olet);
404 	else if(mtmp && (!mtmp->minvis || See_invisible)) {
405 		/* must be a hiding monster, but not hiding right now */
406 		/* assume for the moment that long worms do not hide */
407 		pmon(mtmp);
408 	}
409 	else if(g_at(x,y) && room->typ != POOL)
410 		atl(x,y,'$');
411 	else if(!room->seen || room->scrsym == ' ') {
412 		room->new = room->seen = 1;
413 		newsym(x,y);
414 		on_scr(x,y);
415 	}
416 	room->seen = 1;
417 }
418 
419 char
420 news0(xchar x, xchar y)
421 {
422 	struct obj *otmp;
423 	struct trap *ttmp;
424 	struct rm *room;
425 	char tmp;
426 
427 	room = &levl[(int)x][(int)y];
428 	if(!room->seen) tmp = ' ';
429 	else if(room->typ == POOL) tmp = POOL_SYM;
430 	else if(!Blind && (otmp = o_at(x,y))) tmp = otmp->olet;
431 	else if(!Blind && g_at(x,y)) tmp = '$';
432 	else if(x == xupstair && y == yupstair) tmp = '<';
433 	else if(x == xdnstair && y == ydnstair) tmp = '>';
434 	else if((ttmp = t_at(x,y)) && ttmp->tseen) tmp = '^';
435 	else switch(room->typ) {
436 	case SCORR:
437 	case SDOOR:
438 		tmp = room->scrsym;	/* %% wrong after killing mimic ! */
439 		break;
440 	case HWALL:
441 		tmp = '-';
442 		break;
443 	case VWALL:
444 		tmp = '|';
445 		break;
446 	case LDOOR:
447 	case DOOR:
448 		tmp = '+';
449 		break;
450 	case CORR:
451 		tmp = CORR_SYM;
452 		break;
453 	case ROOM:
454 		if(room->lit || cansee(x,y) || Blind) tmp = '.';
455 		else tmp = ' ';
456 		break;
457 /*
458 	case POOL:
459 		tmp = POOL_SYM;
460 		break;
461 */
462 	default:
463 		tmp = ERRCHAR;
464 	}
465 	return(tmp);
466 }
467 
468 void
469 newsym(int x, int y)
470 {
471 	atl(x,y,news0(x,y));
472 }
473 
474 /* used with wand of digging (or pick-axe): fill scrsym and force display */
475 /* also when a POOL evaporates */
476 void
477 mnewsym(int x, int y)
478 {
479 	struct rm *room;
480 	char newscrsym;
481 
482 	if(!vism_at(x,y)) {
483 		room = &levl[x][y];
484 		newscrsym = news0(x,y);
485 		if(room->scrsym != newscrsym) {
486 			room->scrsym = newscrsym;
487 			room->seen = 0;
488 		}
489 	}
490 }
491 
492 void
493 nosee(int x, int y)
494 {
495 	struct rm *room;
496 
497 	if(!isok(x,y)) return;
498 	room = &levl[x][y];
499 	if(room->scrsym == '.' && !room->lit && !Blind) {
500 		room->scrsym = ' ';
501 		room->new = 1;
502 		on_scr(x,y);
503 	}
504 }
505 
506 #ifndef QUEST
507 void
508 prl1(int x, int y)
509 {
510 	if(u.dx) {
511 		if(u.dy) {
512 			prl(x-(2*u.dx),y);
513 			prl(x-u.dx,y);
514 			prl(x,y);
515 			prl(x,y-u.dy);
516 			prl(x,y-(2*u.dy));
517 		} else {
518 			prl(x,y-1);
519 			prl(x,y);
520 			prl(x,y+1);
521 		}
522 	} else {
523 		prl(x-1,y);
524 		prl(x,y);
525 		prl(x+1,y);
526 	}
527 }
528 
529 void
530 nose1(int x, int y)
531 {
532 	if(u.dx) {
533 		if(u.dy) {
534 			nosee(x,u.uy);
535 			nosee(x,u.uy-u.dy);
536 			nosee(x,y);
537 			nosee(u.ux-u.dx,y);
538 			nosee(u.ux,y);
539 		} else {
540 			nosee(x,y-1);
541 			nosee(x,y);
542 			nosee(x,y+1);
543 		}
544 	} else {
545 		nosee(x-1,y);
546 		nosee(x,y);
547 		nosee(x+1,y);
548 	}
549 }
550 #endif /* QUEST */
551 
552 int
553 vism_at(int x, int y)
554 {
555 	struct monst *mtmp;
556 
557 	return((x == u.ux && y == u.uy && !Invisible)
558 			? 1 :
559 	       (mtmp = m_at(x,y))
560 			? ((Blind && Telepat) || canseemon(mtmp)) :
561 		0);
562 }
563 
564 void
565 unpobj(struct obj *obj)
566 {
567 /* 	if(obj->odispl){
568 		if(!vism_at(obj->odx, obj->ody))
569 			newsym(obj->odx, obj->ody);
570 		obj->odispl = 0;
571 	}
572 */
573 	if(!vism_at(obj->ox,obj->oy))
574 		newsym(obj->ox,obj->oy);
575 }
576 
577 void
578 seeobjs()
579 {
580 	struct obj *obj, *obj2;
581 
582 	for(obj = fobj; obj; obj = obj2) {
583 		obj2 = obj->nobj;
584 		if(obj->olet == FOOD_SYM && obj->otyp >= CORPSE
585 			&& obj->age + 250 < moves)
586 				delobj(obj);
587 	}
588 	for(obj = invent; obj; obj = obj2) {
589 		obj2 = obj->nobj;
590 		if(obj->olet == FOOD_SYM && obj->otyp >= CORPSE
591 			&& obj->age + 250 < moves)
592 				useup(obj);
593 	}
594 }
595 
596 void
597 seemons()
598 {
599 	struct monst *mtmp;
600 
601 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){
602 		if(mtmp->data->mlet == ';')
603 			mtmp->minvis = (u.ustuck != mtmp &&
604 					levl[(int)mtmp->mx][(int)mtmp->my].typ == POOL);
605 		pmon(mtmp);
606 #ifndef NOWORM
607 		if(mtmp->wormno) wormsee(mtmp->wormno);
608 #endif /* NOWORM */
609 	}
610 }
611 
612 void
613 pmon(struct monst *mon)
614 {
615 	int show = (Blind && Telepat) || canseemon(mon);
616 
617 	if(mon->mdispl){
618 		if(mon->mdx != mon->mx || mon->mdy != mon->my || !show)
619 			unpmon(mon);
620 	}
621 	if(show && !mon->mdispl){
622 		atl(mon->mx,mon->my,
623 		 (!mon->mappearance
624 		  || u.uprops[PROP(RIN_PROTECTION_FROM_SHAPE_CHANGERS)].p_flgs
625 		 ) ? mon->data->mlet : mon->mappearance);
626 		mon->mdispl = 1;
627 		mon->mdx = mon->mx;
628 		mon->mdy = mon->my;
629 	}
630 }
631 
632 void
633 unpmon(struct monst *mon)
634 {
635 	if(mon->mdispl){
636 		newsym(mon->mdx, mon->mdy);
637 		mon->mdispl = 0;
638 	}
639 }
640 
641 void
642 nscr()
643 {
644 	int x,y;
645 	struct rm *room;
646 
647 	if(u.uswallow || u.ux == FAR || flags.nscrinh) return;
648 	pru();
649 	for(y = scrly; y <= scrhy; y++)
650 		for(x = scrlx; x <= scrhx; x++)
651 			if((room = &levl[x][y])->new) {
652 				room->new = 0;
653 				at(x,y,room->scrsym);
654 			}
655 	scrhx = scrhy = 0;
656 	scrlx = COLNO;
657 	scrly = ROWNO;
658 }
659 
660 /* 100 suffices for bot(); no relation with COLNO */
661 char oldbot[100], newbot[100];
662 
663 static void
664 cornbot(int lth)
665 {
666 	if(lth < sizeof(oldbot)) {
667 		oldbot[lth] = 0;
668 		flags.botl = 1;
669 	}
670 }
671 
672 void
673 bot()
674 {
675 	char *ob = oldbot, *nb = newbot, *bp;
676 	int i;
677 
678 	if(flags.botlx) *ob = 0;
679 	flags.botl = flags.botlx = 0;
680 #ifdef GOLD_ON_BOTL
681 	(void) snprintf(newbot, sizeof newbot,
682 		"Level %-2d  Gold %-5lu  Hp %3d(%d)  Ac %-2d  Str ",
683 		dlevel, u.ugold, u.uhp, u.uhpmax, u.uac);
684 #else
685 	(void) snprintf(newbot, sizeof newbot,
686 		"Level %-2d   Hp %3d(%d)   Ac %-2d   Str ",
687 		dlevel,  u.uhp, u.uhpmax, u.uac);
688 #endif /* GOLD_ON_BOTL */
689 	if(u.ustr>18) {
690 	    if(u.ustr>117)
691 		(void) strlcat(newbot,"18/**",sizeof newbot);
692 	    else {
693 		bp = eos(newbot);
694 		(void) snprintf(bp, newbot + sizeof newbot - bp,
695 		  "18/%02d",u.ustr-18);
696 	    }
697 	} else {
698 	    bp = eos(newbot);
699 	    (void) snprintf(bp, newbot + sizeof newbot - bp, "%-2d   ",u.ustr);
700 	}
701 	bp = eos(newbot);
702 #ifdef EXP_ON_BOTL
703 	(void) snprintf(bp, newbot + sizeof newbot - bp,
704 	  "  Exp %2d/%-5lu ", u.ulevel,u.uexp);
705 #else
706 	(void) snprintf(bp, newbot + sizeof newbot - bp,
707 	  "   Exp %2u  ", u.ulevel);
708 #endif /* EXP_ON_BOTL */
709 	(void) strlcat(newbot, hu_stat[u.uhs], sizeof newbot);
710 	if(flags.time) {
711 	    bp = eos(newbot);
712 	    (void) snprintf(bp, newbot + sizeof newbot - bp, "  %ld", moves);
713 	}
714 	if(strlen(newbot) >= COLNO) {
715 		char *bp0, *bp1;
716 		bp0 = bp1 = newbot;
717 		do {
718 			if(*bp0 != ' ' || bp0[1] != ' ' || bp0[2] != ' ')
719 				*bp1++ = *bp0;
720 		} while(*bp0++);
721 	}
722 	for(i = 1; i<COLNO; i++) {
723 		if(*ob != *nb){
724 			curs(i,ROWNO+2);
725 			(void) putchar(*nb ? *nb : ' ');
726 			curx++;
727 		}
728 		if(*ob) ob++;
729 		if(*nb) nb++;
730 	}
731 	(void) strlcpy(oldbot, newbot, sizeof oldbot);
732 }
733 
734 #ifdef WAN_PROBING
735 mstatusline(mtmp) struct monst *mtmp; {
736 	pline("Status of %s: ", monnam(mtmp));
737 	pline("Level %-2d  Gold %-5lu  Hp %3d(%d)  Ac %-2d  Dam %d",
738 	    mtmp->data->mlevel, mtmp->mgold, mtmp->mhp, mtmp->mhpmax,
739 	    mtmp->data->ac, (mtmp->data->damn + 1) * (mtmp->data->damd + 1));
740 }
741 #endif /* WAN_PROBING */
742 
743 void
744 cls()
745 {
746 	if(flags.toplin == 1)
747 		more();
748 	flags.toplin = 0;
749 
750 	clr_screen();
751 
752 	flags.botlx = 1;
753 }
754