Home | History | Annotate | Line # | Download | only in hack
      1 /*	$NetBSD: hack.pri.c,v 1.13 2010/02/03 15:34:38 roy 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 (at) 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 <sys/cdefs.h>
     65 #ifndef lint
     66 __RCSID("$NetBSD: hack.pri.c,v 1.13 2010/02/03 15:34:38 roy Exp $");
     67 #endif				/* not lint */
     68 
     69 #include "hack.h"
     70 #include "extern.h"
     71 
     72 static xchar scrlx, scrhx, scrly, scrhy;	/* corners of new area on
     73 						 * screen */
     74 
     75 static void cornbot(int);
     76 
     77 void
     78 swallowed(void)
     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 static boolean panicking;
    101 
    102 void
    103 panic(const char *fmt, ...)
    104 {
    105 	va_list ap;
    106 
    107 	va_start(ap, fmt);
    108 	if (panicking++)
    109 		exit(1);	/* avoid loops - this should never happen */
    110 	home();
    111 	puts(" Suddenly, the dungeon collapses.");
    112 	fputs(" ERROR:  ", stdout);
    113 	vprintf(fmt, ap);
    114 	va_end(ap);
    115 #ifdef DEBUG
    116 #ifdef UNIX
    117 	if (!fork())
    118 		abort();	/* generate core dump */
    119 #endif	/* UNIX */
    120 #endif	/* DEBUG */
    121 	more();			/* contains a fflush() */
    122 	done("panicked");
    123 }
    124 
    125 void
    126 atl(int x, int y, int ch)
    127 {
    128 	struct rm      *crm = &levl[x][y];
    129 
    130 	if (x < 0 || x > COLNO - 1 || y < 0 || y > ROWNO - 1) {
    131 		impossible("atl(%d,%d,%c)", x, y, ch);
    132 		return;
    133 	}
    134 	if (crm->seen && crm->scrsym == ch)
    135 		return;
    136 	crm->scrsym = ch;
    137 	crm->new = 1;
    138 	on_scr(x, y);
    139 }
    140 
    141 void
    142 on_scr(int x, int y)
    143 {
    144 	if (x < scrlx)
    145 		scrlx = x;
    146 	if (x > scrhx)
    147 		scrhx = x;
    148 	if (y < scrly)
    149 		scrly = y;
    150 	if (y > scrhy)
    151 		scrhy = y;
    152 }
    153 
    154 /*
    155  * call: (x,y) - display (-1,0) - close (leave last symbol) (-1,-1)- close
    156  * (undo last symbol) (-1,let)-open: initialize symbol (-2,let)-change let
    157  */
    158 
    159 void
    160 tmp_at(schar x, schar y)
    161 {
    162 	static schar    prevx, prevy;
    163 	static char     let;
    164 	if ((int) x == -2) {	/* change let call */
    165 		let = y;
    166 		return;
    167 	}
    168 	if ((int) x == -1 && (int) y >= 0) {	/* open or close call */
    169 		let = y;
    170 		prevx = -1;
    171 		return;
    172 	}
    173 	if (prevx >= 0 && cansee(prevx, prevy)) {
    174 		delay_output();
    175 		prl(prevx, prevy);	/* in case there was a monster */
    176 		at(prevx, prevy, levl[prevx][prevy].scrsym);
    177 	}
    178 	if (x >= 0) {		/* normal call */
    179 		if (cansee(x, y))
    180 			at(x, y, let);
    181 		prevx = x;
    182 		prevy = y;
    183 	} else {		/* close call */
    184 		let = 0;
    185 		prevx = -1;
    186 	}
    187 }
    188 
    189 /* like the previous, but the symbols are first erased on completion */
    190 void
    191 Tmp_at(schar x, schar y)
    192 {
    193 	static char     let;
    194 	static xchar    cnt;
    195 	static coord    tc[COLNO];	/* but watch reflecting beams! */
    196 	int xx, yy;
    197 	if ((int) x == -1) {
    198 		if (y > 0) {	/* open call */
    199 			let = y;
    200 			cnt = 0;
    201 			return;
    202 		}
    203 		/* close call (do not distinguish y==0 and y==-1) */
    204 		while (cnt--) {
    205 			xx = tc[cnt].x;
    206 			yy = tc[cnt].y;
    207 			prl(xx, yy);
    208 			at(xx, yy, levl[xx][yy].scrsym);
    209 		}
    210 		cnt = let = 0;	/* superfluous */
    211 		return;
    212 	}
    213 	if ((int) x == -2) {	/* change let call */
    214 		let = y;
    215 		return;
    216 	}
    217 	/* normal call */
    218 	if (cansee(x, y)) {
    219 		if (cnt)
    220 			delay_output();
    221 		at(x, y, let);
    222 		tc[cnt].x = x;
    223 		tc[cnt].y = y;
    224 		if (++cnt >= COLNO)
    225 			panic("Tmp_at overflow?");
    226 		levl[x][y].new = 0;	/* prevent pline-nscr erasing --- */
    227 	}
    228 }
    229 
    230 void
    231 setclipped(void)
    232 {
    233 	error("Hack needs a screen of size at least %d by %d.\n",
    234 	      ROWNO + 2, COLNO);
    235 }
    236 
    237 void
    238 at(xchar x, xchar y, int ch)
    239 {
    240 #ifndef lint
    241 	/* if xchar is unsigned, lint will complain about  if(x < 0)  */
    242 	if (x < 0 || x > COLNO - 1 || y < 0 || y > ROWNO - 1) {
    243 		impossible("At gets 0%o at %d %d.", ch, x, y);
    244 		return;
    245 	}
    246 #endif	/* lint */
    247 	if (!ch) {
    248 		impossible("At gets null at %d %d.", x, y);
    249 		return;
    250 	}
    251 	y += 2;
    252 	curs(x, y);
    253 	(void) putchar(ch);
    254 	curx++;
    255 }
    256 
    257 void
    258 prme(void)
    259 {
    260 	if (!Invisible)
    261 		at(u.ux, u.uy, u.usym);
    262 }
    263 
    264 int
    265 doredraw(void)
    266 {
    267 	docrt();
    268 	return (0);
    269 }
    270 
    271 void
    272 docrt(void)
    273 {
    274 	int x, y;
    275 	struct rm      *room;
    276 	struct monst   *mtmp;
    277 
    278 	if (u.uswallow) {
    279 		swallowed();
    280 		return;
    281 	}
    282 	cls();
    283 
    284 	/*
    285 	 * Some ridiculous code to get display of @ and monsters (almost)
    286 	 * right
    287 	 */
    288 	if (!Invisible) {
    289 		levl[(u.udisx = u.ux)][(u.udisy = u.uy)].scrsym = u.usym;
    290 		levl[u.udisx][u.udisy].seen = 1;
    291 		u.udispl = 1;
    292 	} else
    293 		u.udispl = 0;
    294 
    295 	seemons();		/* reset old positions */
    296 	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
    297 		mtmp->mdispl = 0;
    298 	seemons();		/* force new positions to be shown */
    299 	/*
    300 	 * This nonsense should disappear soon
    301 	 * ---------------------------------
    302 	 */
    303 
    304 	for (y = 0; y < ROWNO; y++)
    305 		for (x = 0; x < COLNO; x++)
    306 			if ((room = &levl[x][y])->new) {
    307 				room->new = 0;
    308 				at(x, y, room->scrsym);
    309 			} else if (room->seen)
    310 				at(x, y, room->scrsym);
    311 	scrlx = COLNO;
    312 	scrly = ROWNO;
    313 	scrhx = scrhy = 0;
    314 	flags.botlx = 1;
    315 	bot();
    316 }
    317 
    318 void
    319 docorner(int xmin, int ymax)
    320 {
    321 	int x, y;
    322 	struct rm      *room;
    323 	struct monst   *mtmp;
    324 
    325 	if (u.uswallow) {	/* Can be done more efficiently */
    326 		swallowed();
    327 		return;
    328 	}
    329 	seemons();		/* reset old positions */
    330 	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
    331 		if (mtmp->mx >= xmin && mtmp->my < ymax)
    332 			mtmp->mdispl = 0;
    333 	seemons();		/* force new positions to be shown */
    334 
    335 	for (y = 0; y < ymax; y++) {
    336 		if (y > ROWNO && CD)
    337 			break;
    338 		curs(xmin, y + 2);
    339 		cl_end();
    340 		if (y < ROWNO) {
    341 			for (x = xmin; x < COLNO; x++) {
    342 				if ((room = &levl[x][y])->new) {
    343 					room->new = 0;
    344 					at(x, y, room->scrsym);
    345 				} else if (room->seen)
    346 					at(x, y, room->scrsym);
    347 			}
    348 		}
    349 	}
    350 	if (ymax > ROWNO) {
    351 		cornbot(xmin - 1);
    352 		if (ymax > ROWNO + 1 && CD) {
    353 			curs(1, ROWNO + 3);
    354 			cl_eos();
    355 		}
    356 	}
    357 }
    358 
    359 void
    360 curs_on_u(void)
    361 {
    362 	curs(u.ux, u.uy + 2);
    363 }
    364 
    365 void
    366 pru(void)
    367 {
    368 	if (u.udispl && (Invisible || u.udisx != u.ux || u.udisy != u.uy))
    369 		/* if(! levl[u.udisx][u.udisy].new) */
    370 		if (!vism_at(u.udisx, u.udisy))
    371 			newsym(u.udisx, u.udisy);
    372 	if (Invisible) {
    373 		u.udispl = 0;
    374 		prl(u.ux, u.uy);
    375 	} else if (!u.udispl || u.udisx != u.ux || u.udisy != u.uy) {
    376 		atl(u.ux, u.uy, u.usym);
    377 		u.udispl = 1;
    378 		u.udisx = u.ux;
    379 		u.udisy = u.uy;
    380 	}
    381 	levl[u.ux][u.uy].seen = 1;
    382 }
    383 
    384 #ifndef NOWORM
    385 #include	"def.wseg.h"
    386 #endif	/* NOWORM */
    387 
    388 /* print a position that is visible for @ */
    389 void
    390 prl(int x, int y)
    391 {
    392 	struct rm      *room;
    393 	struct monst   *mtmp;
    394 	struct obj     *otmp;
    395 
    396 	if (x == u.ux && y == u.uy && (!Invisible)) {
    397 		pru();
    398 		return;
    399 	}
    400 	if (!isok(x, y))
    401 		return;
    402 	room = &levl[x][y];
    403 	if ((!room->typ) ||
    404 	    (IS_ROCK(room->typ) && levl[u.ux][u.uy].typ == CORR))
    405 		return;
    406 	if ((mtmp = m_at(x, y)) && !mtmp->mhide &&
    407 	    (!mtmp->minvis || See_invisible)) {
    408 #ifndef NOWORM
    409 		if (m_atseg)
    410 			pwseg(m_atseg);
    411 		else
    412 #endif	/* NOWORM */
    413 			pmon(mtmp);
    414 	} else if ((otmp = o_at(x, y)) && room->typ != POOL)
    415 		atl(x, y, otmp->olet);
    416 	else if (mtmp && (!mtmp->minvis || See_invisible)) {
    417 		/* must be a hiding monster, but not hiding right now */
    418 		/* assume for the moment that long worms do not hide */
    419 		pmon(mtmp);
    420 	} else if (g_at(x, y) && room->typ != POOL)
    421 		atl(x, y, '$');
    422 	else if (!room->seen || room->scrsym == ' ') {
    423 		room->new = room->seen = 1;
    424 		newsym(x, y);
    425 		on_scr(x, y);
    426 	}
    427 	room->seen = 1;
    428 }
    429 
    430 char
    431 news0(xchar x, xchar y)
    432 {
    433 	struct obj     *otmp;
    434 	struct trap    *ttmp;
    435 	struct rm      *room;
    436 	char            tmp;
    437 
    438 	room = &levl[x][y];
    439 	if (!room->seen)
    440 		tmp = ' ';
    441 	else if (room->typ == POOL)
    442 		tmp = POOL_SYM;
    443 	else if (!Blind && (otmp = o_at(x, y)))
    444 		tmp = otmp->olet;
    445 	else if (!Blind && g_at(x, y))
    446 		tmp = '$';
    447 	else if (x == xupstair && y == yupstair)
    448 		tmp = '<';
    449 	else if (x == xdnstair && y == ydnstair)
    450 		tmp = '>';
    451 	else if ((ttmp = t_at(x, y)) && ttmp->tseen)
    452 		tmp = '^';
    453 	else
    454 		switch (room->typ) {
    455 		case SCORR:
    456 		case SDOOR:
    457 			tmp = room->scrsym;	/* %% wrong after killing
    458 						 * mimic ! */
    459 			break;
    460 		case HWALL:
    461 			tmp = '-';
    462 			break;
    463 		case VWALL:
    464 			tmp = '|';
    465 			break;
    466 		case LDOOR:
    467 		case DOOR:
    468 			tmp = '+';
    469 			break;
    470 		case CORR:
    471 			tmp = CORR_SYM;
    472 			break;
    473 		case ROOM:
    474 			if (room->lit || cansee(x, y) || Blind)
    475 				tmp = '.';
    476 			else
    477 				tmp = ' ';
    478 			break;
    479 			/*
    480 				case POOL:
    481 					tmp = POOL_SYM;
    482 					break;
    483 			*/
    484 		default:
    485 			tmp = ERRCHAR;
    486 		}
    487 	return (tmp);
    488 }
    489 
    490 void
    491 newsym(int x, int y)
    492 {
    493 	atl(x, y, news0(x, y));
    494 }
    495 
    496 /* used with wand of digging (or pick-axe): fill scrsym and force display */
    497 /* also when a POOL evaporates */
    498 void
    499 mnewsym(int x, int y)
    500 {
    501 	struct rm      *room;
    502 	char            newscrsym;
    503 
    504 	if (!vism_at(x, y)) {
    505 		room = &levl[x][y];
    506 		newscrsym = news0(x, y);
    507 		if (room->scrsym != newscrsym) {
    508 			room->scrsym = newscrsym;
    509 			room->seen = 0;
    510 		}
    511 	}
    512 }
    513 
    514 void
    515 nosee(int x, int y)
    516 {
    517 	struct rm      *room;
    518 
    519 	if (!isok(x, y))
    520 		return;
    521 	room = &levl[x][y];
    522 	if (room->scrsym == '.' && !room->lit && !Blind) {
    523 		room->scrsym = ' ';
    524 		room->new = 1;
    525 		on_scr(x, y);
    526 	}
    527 }
    528 
    529 #ifndef QUEST
    530 void
    531 prl1(int x, int y)
    532 {
    533 	if (u.dx) {
    534 		if (u.dy) {
    535 			prl(x - (2 * u.dx), y);
    536 			prl(x - u.dx, y);
    537 			prl(x, y);
    538 			prl(x, y - u.dy);
    539 			prl(x, y - (2 * u.dy));
    540 		} else {
    541 			prl(x, y - 1);
    542 			prl(x, y);
    543 			prl(x, y + 1);
    544 		}
    545 	} else {
    546 		prl(x - 1, y);
    547 		prl(x, y);
    548 		prl(x + 1, y);
    549 	}
    550 }
    551 
    552 void
    553 nose1(int x, int y)
    554 {
    555 	if (u.dx) {
    556 		if (u.dy) {
    557 			nosee(x, u.uy);
    558 			nosee(x, u.uy - u.dy);
    559 			nosee(x, y);
    560 			nosee(u.ux - u.dx, y);
    561 			nosee(u.ux, y);
    562 		} else {
    563 			nosee(x, y - 1);
    564 			nosee(x, y);
    565 			nosee(x, y + 1);
    566 		}
    567 	} else {
    568 		nosee(x - 1, y);
    569 		nosee(x, y);
    570 		nosee(x + 1, y);
    571 	}
    572 }
    573 #endif	/* QUEST */
    574 
    575 int
    576 vism_at(int x, int y)
    577 {
    578 	struct monst   *mtmp;
    579 
    580 	return ((x == u.ux && y == u.uy && !Invisible)
    581 		? 1 :
    582 		(mtmp = m_at(x, y))
    583 		? ((Blind && Telepat) || canseemon(mtmp)) :
    584 		0);
    585 }
    586 
    587 #ifdef NEWSCR
    588 void
    589 pobj(struct obj *obj)
    590 {
    591 	int             show = (!obj->oinvis || See_invisible) &&
    592 	cansee(obj->ox, obj->oy);
    593 	if (obj->odispl) {
    594 		if (obj->odx != obj->ox || obj->ody != obj->oy || !show)
    595 			if (!vism_at(obj->odx, obj->ody)) {
    596 				newsym(obj->odx, obj->ody);
    597 				obj->odispl = 0;
    598 			}
    599 	}
    600 	if (show && !vism_at(obj->ox, obj->oy)) {
    601 		atl(obj->ox, obj->oy, obj->olet);
    602 		obj->odispl = 1;
    603 		obj->odx = obj->ox;
    604 		obj->ody = obj->oy;
    605 	}
    606 }
    607 #endif	/* NEWSCR */
    608 
    609 void
    610 unpobj(struct obj *obj)
    611 {
    612 	/*
    613 	 * if(obj->odispl){ if(!vism_at(obj->odx, obj->ody)) newsym(obj->odx,
    614 	 * obj->ody); obj->odispl = 0; }
    615 	 */
    616 	if (!vism_at(obj->ox, obj->oy))
    617 		newsym(obj->ox, obj->oy);
    618 }
    619 
    620 void
    621 seeobjs(void)
    622 {
    623 	struct obj     *obj, *obj2;
    624 	for (obj = fobj; obj; obj = obj2) {
    625 		obj2 = obj->nobj;
    626 		if (obj->olet == FOOD_SYM && obj->otyp >= CORPSE
    627 		    && obj->age + 250 < moves)
    628 			delobj(obj);
    629 	}
    630 	for (obj = invent; obj; obj = obj2) {
    631 		obj2 = obj->nobj;
    632 		if (obj->olet == FOOD_SYM && obj->otyp >= CORPSE
    633 		    && obj->age + 250 < moves)
    634 			useup(obj);
    635 	}
    636 }
    637 
    638 void
    639 seemons(void)
    640 {
    641 	struct monst   *mtmp;
    642 	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
    643 		if (mtmp->data->mlet == ';')
    644 			mtmp->minvis = (u.ustuck != mtmp &&
    645 				      levl[mtmp->mx][mtmp->my].typ == POOL);
    646 		pmon(mtmp);
    647 #ifndef NOWORM
    648 		if (mtmp->wormno)
    649 			wormsee(mtmp->wormno);
    650 #endif	/* NOWORM */
    651 	}
    652 }
    653 
    654 void
    655 pmon(struct monst *mon)
    656 {
    657 	int             show = (Blind && Telepat) || canseemon(mon);
    658 	if (mon->mdispl) {
    659 		if (mon->mdx != mon->mx || mon->mdy != mon->my || !show)
    660 			unpmon(mon);
    661 	}
    662 	if (show && !mon->mdispl) {
    663 		atl(mon->mx, mon->my,
    664 		    (!mon->mappearance
    665 		|| u.uprops[PROP(RIN_PROTECTION_FROM_SHAPE_CHANGERS)].p_flgs
    666 		     ) ? mon->data->mlet : mon->mappearance);
    667 		mon->mdispl = 1;
    668 		mon->mdx = mon->mx;
    669 		mon->mdy = mon->my;
    670 	}
    671 }
    672 
    673 void
    674 unpmon(struct monst *mon)
    675 {
    676 	if (mon->mdispl) {
    677 		newsym(mon->mdx, mon->mdy);
    678 		mon->mdispl = 0;
    679 	}
    680 }
    681 
    682 void
    683 nscr(void)
    684 {
    685 	int x, y;
    686 	struct rm      *room;
    687 
    688 	if (u.uswallow || u.ux == FAR || flags.nscrinh)
    689 		return;
    690 	pru();
    691 	for (y = scrly; y <= scrhy; y++)
    692 		for (x = scrlx; x <= scrhx; x++)
    693 			if ((room = &levl[x][y])->new) {
    694 				room->new = 0;
    695 				at(x, y, room->scrsym);
    696 			}
    697 	scrhx = scrhy = 0;
    698 	scrlx = COLNO;
    699 	scrly = ROWNO;
    700 }
    701 
    702 /* 100 suffices for bot(); no relation with COLNO */
    703 static char oldbot[100], newbot[100];
    704 void
    705 cornbot(int lth)
    706 {
    707 	if ((unsigned)lth < sizeof(oldbot)) {
    708 		oldbot[lth] = 0;
    709 		flags.botl = 1;
    710 	}
    711 }
    712 
    713 void
    714 bot(void)
    715 {
    716 	char           *ob = oldbot, *nb = newbot;
    717 	int             i;
    718 	size_t pos;
    719 
    720 	if (flags.botlx)
    721 		*ob = 0;
    722 	flags.botl = flags.botlx = 0;
    723 #ifdef GOLD_ON_BOTL
    724 	(void) snprintf(newbot, sizeof(newbot),
    725 		       "Level %-2d  Gold %-5lu  Hp %3d(%d)  Ac %-2d  Str ",
    726 		       dlevel, u.ugold, u.uhp, u.uhpmax, u.uac);
    727 #else
    728 	(void) snprintf(newbot, sizeof(newbot),
    729 		       "Level %-2d   Hp %3d(%d)   Ac %-2d   Str ",
    730 		       dlevel, u.uhp, u.uhpmax, u.uac);
    731 #endif	/* GOLD_ON_BOTL */
    732 	if (u.ustr > 18) {
    733 		if (u.ustr > 117)
    734 			(void) strlcat(newbot, "18/**", sizeof(newbot));
    735 		else {
    736 			pos = strlen(newbot);
    737 			(void) snprintf(newbot+pos, sizeof(newbot)-pos,
    738 					"18/%02d", u.ustr - 18);
    739 		}
    740 	} else {
    741 		pos = strlen(newbot);
    742 		(void) snprintf(newbot+pos, sizeof(newbot)-pos,
    743 				"%-2d   ", u.ustr);
    744 	}
    745 	pos = strlen(newbot);
    746 #ifdef EXP_ON_BOTL
    747 	(void) snprintf(newbot+pos, sizeof(newbot)-pos,
    748 			"  Exp %2d/%-5lu ", u.ulevel, u.uexp);
    749 #else
    750 	(void) snprintf(newbot+pos, sizeof(newbot)-pos,
    751 			"   Exp %2u  ", u.ulevel);
    752 #endif	/* EXP_ON_BOTL */
    753 	(void) strlcat(newbot, hu_stat[u.uhs], sizeof(newbot));
    754 	if (flags.time) {
    755 		pos = strlen(newbot);
    756 		(void) snprintf(newbot+pos, sizeof(newbot)-pos,
    757 				"  %ld", moves);
    758 	}
    759 	if (strlen(newbot) >= COLNO) {
    760 		char           *bp0, *bp1;
    761 		bp0 = bp1 = newbot;
    762 		do {
    763 			if (*bp0 != ' ' || bp0[1] != ' ' || bp0[2] != ' ')
    764 				*bp1++ = *bp0;
    765 		} while (*bp0++);
    766 	}
    767 	for (i = 1; i < COLNO; i++) {
    768 		if (*ob != *nb) {
    769 			curs(i, ROWNO + 2);
    770 			(void) putchar(*nb ? *nb : ' ');
    771 			curx++;
    772 		}
    773 		if (*ob)
    774 			ob++;
    775 		if (*nb)
    776 			nb++;
    777 	}
    778 	(void) strcpy(oldbot, newbot);
    779 }
    780 
    781 #ifdef WAN_PROBING
    782 void
    783 mstatusline(struct monst *mtmp)
    784 {
    785 	pline("Status of %s: ", monnam(mtmp));
    786 	pline("Level %-2d  Gold %-5lu  Hp %3d(%d)  Ac %-2d  Dam %d",
    787 	      mtmp->data->mlevel, mtmp->mgold, mtmp->mhp, mtmp->mhpmax,
    788 	   mtmp->data->ac, (mtmp->data->damn + 1) * (mtmp->data->damd + 1));
    789 }
    790 #endif	/* WAN_PROBING */
    791 
    792 void
    793 cls(void)
    794 {
    795 	if (flags.toplin == 1)
    796 		more();
    797 	flags.toplin = 0;
    798 
    799 	clearscreen();
    800 
    801 	flags.botlx = 1;
    802 }
    803