xref: /openbsd/games/hack/hack.pri.c (revision 91f110e0)
1 /*	$OpenBSD: hack.pri.c,v 1.11 2014/03/11 07:41:10 guenther 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 	if(x < 0 || x > COLNO-1 || y < 0 || y > ROWNO-1) {
235 		impossible("At gets 0%o at %d %d.", ch, x, y);
236 		return;
237 	}
238 	if(!ch) {
239 		impossible("At gets null at %d %d.", x, y);
240 		return;
241 	}
242 	y += 2;
243 	curs(x,y);
244 	(void) putchar(ch);
245 	curx++;
246 }
247 
248 void
249 prme()
250 {
251 	if(!Invisible) at(u.ux,u.uy,u.usym);
252 }
253 
254 int
255 doredraw()
256 {
257 	docrt();
258 	return(0);
259 }
260 
261 void
262 docrt()
263 {
264 	int x,y;
265 	struct rm *room;
266 	struct monst *mtmp;
267 
268 	if(u.uswallow) {
269 		swallowed();
270 		return;
271 	}
272 	cls();
273 
274 /* Some ridiculous code to get display of @ and monsters (almost) right */
275 	if(!Invisible) {
276 		levl[(int)(u.udisx = u.ux)][(int)(u.udisy = u.uy)].scrsym = u.usym;
277 		levl[(int)u.udisx][(int)u.udisy].seen = 1;
278 		u.udispl = 1;
279 	} else	u.udispl = 0;
280 
281 	seemons();	/* reset old positions */
282 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
283 		mtmp->mdispl = 0;
284 	seemons();	/* force new positions to be shown */
285 /* This nonsense should disappear soon --------------------------------- */
286 
287 	for(y = 0; y < ROWNO; y++)
288 		for(x = 0; x < COLNO; x++)
289 			if((room = &levl[x][y])->new) {
290 				room->new = 0;
291 				at(x,y,room->scrsym);
292 			} else if(room->seen)
293 				at(x,y,room->scrsym);
294 	scrlx = COLNO;
295 	scrly = ROWNO;
296 	scrhx = scrhy = 0;
297 	flags.botlx = 1;
298 	bot();
299 }
300 
301 void
302 docorner(int xmin, int ymax)
303 {
304 	int x,y;
305 	struct rm *room;
306 	struct monst *mtmp;
307 
308 	if(u.uswallow) {	/* Can be done more efficiently */
309 		swallowed();
310 		return;
311 	}
312 
313 	seemons();	/* reset old positions */
314 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
315 	    if(mtmp->mx >= xmin && mtmp->my < ymax)
316 		mtmp->mdispl = 0;
317 	seemons();	/* force new positions to be shown */
318 
319 	for(y = 0; y < ymax; y++) {
320 		if(y > ROWNO && CD) break;
321 		curs(xmin,y+2);
322 		cl_end();
323 		if(y < ROWNO) {
324 		    for(x = xmin; x < COLNO; x++) {
325 			if((room = &levl[x][y])->new) {
326 				room->new = 0;
327 				at(x,y,room->scrsym);
328 			} else
329 				if(room->seen)
330 					at(x,y,room->scrsym);
331 		    }
332 		}
333 	}
334 	if(ymax > ROWNO) {
335 		cornbot(xmin-1);
336 		if(ymax > ROWNO+1 && CD) {
337 			curs(1,ROWNO+3);
338 			cl_eos();
339 		}
340 	}
341 }
342 
343 void
344 curs_on_u()
345 {
346 	curs(u.ux, u.uy+2);
347 }
348 
349 void
350 pru()
351 {
352 	if(u.udispl && (Invisible || u.udisx != u.ux || u.udisy != u.uy))
353 		/* if(! levl[u.udisx][u.udisy].new) */
354 			if(!vism_at(u.udisx, u.udisy))
355 				newsym(u.udisx, u.udisy);
356 	if(Invisible) {
357 		u.udispl = 0;
358 		prl(u.ux,u.uy);
359 	} else
360 	if(!u.udispl || u.udisx != u.ux || u.udisy != u.uy) {
361 		atl(u.ux, u.uy, u.usym);
362 		u.udispl = 1;
363 		u.udisx = u.ux;
364 		u.udisy = u.uy;
365 	}
366 	levl[(int)u.ux][(int)u.uy].seen = 1;
367 }
368 
369 #ifndef NOWORM
370 extern struct wseg *m_atseg;
371 #endif /* NOWORM */
372 
373 /* print a position that is visible for @ */
374 void
375 prl(int x, int y)
376 {
377 	struct rm *room;
378 	struct monst *mtmp;
379 	struct obj *otmp;
380 
381 	if(x == u.ux && y == u.uy && (!Invisible)) {
382 		pru();
383 		return;
384 	}
385 	if(!isok(x,y)) return;
386 	room = &levl[x][y];
387 	if((!room->typ) ||
388 	   (IS_ROCK(room->typ) && levl[(int)u.ux][(int)u.uy].typ == CORR))
389 		return;
390 	if((mtmp = m_at(x,y)) && !mtmp->mhide &&
391 		(!mtmp->minvis || See_invisible)) {
392 #ifndef NOWORM
393 		if(m_atseg)
394 			pwseg(m_atseg);
395 		else
396 #endif /* NOWORM */
397 		pmon(mtmp);
398 	}
399 	else if((otmp = o_at(x,y)) && room->typ != POOL)
400 		atl(x,y,otmp->olet);
401 	else if(mtmp && (!mtmp->minvis || See_invisible)) {
402 		/* must be a hiding monster, but not hiding right now */
403 		/* assume for the moment that long worms do not hide */
404 		pmon(mtmp);
405 	}
406 	else if(g_at(x,y) && room->typ != POOL)
407 		atl(x,y,'$');
408 	else if(!room->seen || room->scrsym == ' ') {
409 		room->new = room->seen = 1;
410 		newsym(x,y);
411 		on_scr(x,y);
412 	}
413 	room->seen = 1;
414 }
415 
416 char
417 news0(xchar x, xchar y)
418 {
419 	struct obj *otmp;
420 	struct trap *ttmp;
421 	struct rm *room;
422 	char tmp;
423 
424 	room = &levl[(int)x][(int)y];
425 	if(!room->seen) tmp = ' ';
426 	else if(room->typ == POOL) tmp = POOL_SYM;
427 	else if(!Blind && (otmp = o_at(x,y))) tmp = otmp->olet;
428 	else if(!Blind && g_at(x,y)) tmp = '$';
429 	else if(x == xupstair && y == yupstair) tmp = '<';
430 	else if(x == xdnstair && y == ydnstair) tmp = '>';
431 	else if((ttmp = t_at(x,y)) && ttmp->tseen) tmp = '^';
432 	else switch(room->typ) {
433 	case SCORR:
434 	case SDOOR:
435 		tmp = room->scrsym;	/* %% wrong after killing mimic ! */
436 		break;
437 	case HWALL:
438 		tmp = '-';
439 		break;
440 	case VWALL:
441 		tmp = '|';
442 		break;
443 	case LDOOR:
444 	case DOOR:
445 		tmp = '+';
446 		break;
447 	case CORR:
448 		tmp = CORR_SYM;
449 		break;
450 	case ROOM:
451 		if(room->lit || cansee(x,y) || Blind) tmp = '.';
452 		else tmp = ' ';
453 		break;
454 /*
455 	case POOL:
456 		tmp = POOL_SYM;
457 		break;
458 */
459 	default:
460 		tmp = ERRCHAR;
461 	}
462 	return(tmp);
463 }
464 
465 void
466 newsym(int x, int y)
467 {
468 	atl(x,y,news0(x,y));
469 }
470 
471 /* used with wand of digging (or pick-axe): fill scrsym and force display */
472 /* also when a POOL evaporates */
473 void
474 mnewsym(int x, int y)
475 {
476 	struct rm *room;
477 	char newscrsym;
478 
479 	if(!vism_at(x,y)) {
480 		room = &levl[x][y];
481 		newscrsym = news0(x,y);
482 		if(room->scrsym != newscrsym) {
483 			room->scrsym = newscrsym;
484 			room->seen = 0;
485 		}
486 	}
487 }
488 
489 void
490 nosee(int x, int y)
491 {
492 	struct rm *room;
493 
494 	if(!isok(x,y)) return;
495 	room = &levl[x][y];
496 	if(room->scrsym == '.' && !room->lit && !Blind) {
497 		room->scrsym = ' ';
498 		room->new = 1;
499 		on_scr(x,y);
500 	}
501 }
502 
503 #ifndef QUEST
504 void
505 prl1(int x, int y)
506 {
507 	if(u.dx) {
508 		if(u.dy) {
509 			prl(x-(2*u.dx),y);
510 			prl(x-u.dx,y);
511 			prl(x,y);
512 			prl(x,y-u.dy);
513 			prl(x,y-(2*u.dy));
514 		} else {
515 			prl(x,y-1);
516 			prl(x,y);
517 			prl(x,y+1);
518 		}
519 	} else {
520 		prl(x-1,y);
521 		prl(x,y);
522 		prl(x+1,y);
523 	}
524 }
525 
526 void
527 nose1(int x, int y)
528 {
529 	if(u.dx) {
530 		if(u.dy) {
531 			nosee(x,u.uy);
532 			nosee(x,u.uy-u.dy);
533 			nosee(x,y);
534 			nosee(u.ux-u.dx,y);
535 			nosee(u.ux,y);
536 		} else {
537 			nosee(x,y-1);
538 			nosee(x,y);
539 			nosee(x,y+1);
540 		}
541 	} else {
542 		nosee(x-1,y);
543 		nosee(x,y);
544 		nosee(x+1,y);
545 	}
546 }
547 #endif /* QUEST */
548 
549 int
550 vism_at(int x, int y)
551 {
552 	struct monst *mtmp;
553 
554 	return((x == u.ux && y == u.uy && !Invisible)
555 			? 1 :
556 	       (mtmp = m_at(x,y))
557 			? ((Blind && Telepat) || canseemon(mtmp)) :
558 		0);
559 }
560 
561 void
562 unpobj(struct obj *obj)
563 {
564 /* 	if(obj->odispl){
565 		if(!vism_at(obj->odx, obj->ody))
566 			newsym(obj->odx, obj->ody);
567 		obj->odispl = 0;
568 	}
569 */
570 	if(!vism_at(obj->ox,obj->oy))
571 		newsym(obj->ox,obj->oy);
572 }
573 
574 void
575 seeobjs()
576 {
577 	struct obj *obj, *obj2;
578 
579 	for(obj = fobj; obj; obj = obj2) {
580 		obj2 = obj->nobj;
581 		if(obj->olet == FOOD_SYM && obj->otyp >= CORPSE
582 			&& obj->age + 250 < moves)
583 				delobj(obj);
584 	}
585 	for(obj = invent; obj; obj = obj2) {
586 		obj2 = obj->nobj;
587 		if(obj->olet == FOOD_SYM && obj->otyp >= CORPSE
588 			&& obj->age + 250 < moves)
589 				useup(obj);
590 	}
591 }
592 
593 void
594 seemons()
595 {
596 	struct monst *mtmp;
597 
598 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){
599 		if(mtmp->data->mlet == ';')
600 			mtmp->minvis = (u.ustuck != mtmp &&
601 					levl[(int)mtmp->mx][(int)mtmp->my].typ == POOL);
602 		pmon(mtmp);
603 #ifndef NOWORM
604 		if(mtmp->wormno) wormsee(mtmp->wormno);
605 #endif /* NOWORM */
606 	}
607 }
608 
609 void
610 pmon(struct monst *mon)
611 {
612 	int show = (Blind && Telepat) || canseemon(mon);
613 
614 	if(mon->mdispl){
615 		if(mon->mdx != mon->mx || mon->mdy != mon->my || !show)
616 			unpmon(mon);
617 	}
618 	if(show && !mon->mdispl){
619 		atl(mon->mx,mon->my,
620 		 (!mon->mappearance
621 		  || u.uprops[PROP(RIN_PROTECTION_FROM_SHAPE_CHANGERS)].p_flgs
622 		 ) ? mon->data->mlet : mon->mappearance);
623 		mon->mdispl = 1;
624 		mon->mdx = mon->mx;
625 		mon->mdy = mon->my;
626 	}
627 }
628 
629 void
630 unpmon(struct monst *mon)
631 {
632 	if(mon->mdispl){
633 		newsym(mon->mdx, mon->mdy);
634 		mon->mdispl = 0;
635 	}
636 }
637 
638 void
639 nscr()
640 {
641 	int x,y;
642 	struct rm *room;
643 
644 	if(u.uswallow || u.ux == FAR || flags.nscrinh) return;
645 	pru();
646 	for(y = scrly; y <= scrhy; y++)
647 		for(x = scrlx; x <= scrhx; x++)
648 			if((room = &levl[x][y])->new) {
649 				room->new = 0;
650 				at(x,y,room->scrsym);
651 			}
652 	scrhx = scrhy = 0;
653 	scrlx = COLNO;
654 	scrly = ROWNO;
655 }
656 
657 /* 100 suffices for bot(); no relation with COLNO */
658 char oldbot[100], newbot[100];
659 
660 static void
661 cornbot(int lth)
662 {
663 	if(lth < sizeof(oldbot)) {
664 		oldbot[lth] = 0;
665 		flags.botl = 1;
666 	}
667 }
668 
669 void
670 bot()
671 {
672 	char *ob = oldbot, *nb = newbot, *bp;
673 	int i;
674 
675 	if(flags.botlx) *ob = 0;
676 	flags.botl = flags.botlx = 0;
677 #ifdef GOLD_ON_BOTL
678 	(void) snprintf(newbot, sizeof newbot,
679 		"Level %-2d  Gold %-5lu  Hp %3d(%d)  Ac %-2d  Str ",
680 		dlevel, u.ugold, u.uhp, u.uhpmax, u.uac);
681 #else
682 	(void) snprintf(newbot, sizeof newbot,
683 		"Level %-2d   Hp %3d(%d)   Ac %-2d   Str ",
684 		dlevel,  u.uhp, u.uhpmax, u.uac);
685 #endif /* GOLD_ON_BOTL */
686 	if(u.ustr>18) {
687 	    if(u.ustr>117)
688 		(void) strlcat(newbot,"18/**",sizeof newbot);
689 	    else {
690 		bp = eos(newbot);
691 		(void) snprintf(bp, newbot + sizeof newbot - bp,
692 		  "18/%02d",u.ustr-18);
693 	    }
694 	} else {
695 	    bp = eos(newbot);
696 	    (void) snprintf(bp, newbot + sizeof newbot - bp, "%-2d   ",u.ustr);
697 	}
698 	bp = eos(newbot);
699 #ifdef EXP_ON_BOTL
700 	(void) snprintf(bp, newbot + sizeof newbot - bp,
701 	  "  Exp %2d/%-5lu ", u.ulevel,u.uexp);
702 #else
703 	(void) snprintf(bp, newbot + sizeof newbot - bp,
704 	  "   Exp %2u  ", u.ulevel);
705 #endif /* EXP_ON_BOTL */
706 	(void) strlcat(newbot, hu_stat[u.uhs], sizeof newbot);
707 	if(flags.time) {
708 	    bp = eos(newbot);
709 	    (void) snprintf(bp, newbot + sizeof newbot - bp, "  %ld", moves);
710 	}
711 	if(strlen(newbot) >= COLNO) {
712 		char *bp0, *bp1;
713 		bp0 = bp1 = newbot;
714 		do {
715 			if(*bp0 != ' ' || bp0[1] != ' ' || bp0[2] != ' ')
716 				*bp1++ = *bp0;
717 		} while(*bp0++);
718 	}
719 	for(i = 1; i<COLNO; i++) {
720 		if(*ob != *nb){
721 			curs(i,ROWNO+2);
722 			(void) putchar(*nb ? *nb : ' ');
723 			curx++;
724 		}
725 		if(*ob) ob++;
726 		if(*nb) nb++;
727 	}
728 	(void) strlcpy(oldbot, newbot, sizeof oldbot);
729 }
730 
731 #ifdef WAN_PROBING
732 mstatusline(mtmp) struct monst *mtmp; {
733 	pline("Status of %s: ", monnam(mtmp));
734 	pline("Level %-2d  Gold %-5lu  Hp %3d(%d)  Ac %-2d  Dam %d",
735 	    mtmp->data->mlevel, mtmp->mgold, mtmp->mhp, mtmp->mhpmax,
736 	    mtmp->data->ac, (mtmp->data->damn + 1) * (mtmp->data->damd + 1));
737 }
738 #endif /* WAN_PROBING */
739 
740 void
741 cls()
742 {
743 	if(flags.toplin == 1)
744 		more();
745 	flags.toplin = 0;
746 
747 	clr_screen();
748 
749 	flags.botlx = 1;
750 }
751