Home | History | Annotate | Line # | Download | only in hack
hack.pri.c revision 1.2
      1 /*
      2  * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985.
      3  */
      4 
      5 #ifndef lint
      6 static char rcsid[] = "$Id: hack.pri.c,v 1.2 1993/08/02 17:19:16 mycroft Exp $";
      7 #endif /* not lint */
      8 
      9 #include "hack.h"
     10 #include <stdio.h>
     11 xchar scrlx, scrhx, scrly, scrhy;	/* corners of new area on screen */
     12 
     13 extern char *hu_stat[];	/* in eat.c */
     14 extern char *CD;
     15 
     16 swallowed()
     17 {
     18 	char *ulook = "|@|";
     19 	ulook[1] = u.usym;
     20 
     21 	cls();
     22 	curs(u.ux-1, u.uy+1);
     23 	fputs("/-\\", stdout);
     24 	curx = u.ux+2;
     25 	curs(u.ux-1, u.uy+2);
     26 	fputs(ulook, stdout);
     27 	curx = u.ux+2;
     28 	curs(u.ux-1, u.uy+3);
     29 	fputs("\\-/", stdout);
     30 	curx = u.ux+2;
     31 	u.udispl = 1;
     32 	u.udisx = u.ux;
     33 	u.udisy = u.uy;
     34 }
     35 
     36 
     37 /*VARARGS1*/
     38 boolean panicking;
     39 
     40 panic(str,a1,a2,a3,a4,a5,a6)
     41 char *str;
     42 {
     43 	if(panicking++) exit(1);    /* avoid loops - this should never happen*/
     44 	home();
     45 	puts(" Suddenly, the dungeon collapses.");
     46 	fputs(" ERROR:  ", stdout);
     47 	printf(str,a1,a2,a3,a4,a5,a6);
     48 #ifdef DEBUG
     49 #ifdef UNIX
     50 	if(!fork())
     51 		abort();	/* generate core dump */
     52 #endif UNIX
     53 #endif DEBUG
     54 	more();			/* contains a fflush() */
     55 	done("panicked");
     56 }
     57 
     58 atl(x,y,ch)
     59 register x,y;
     60 {
     61 	register struct rm *crm = &levl[x][y];
     62 
     63 	if(x<0 || x>COLNO-1 || y<0 || y>ROWNO-1){
     64 		impossible("atl(%d,%d,%c)",x,y,ch);
     65 		return;
     66 	}
     67 	if(crm->seen && crm->scrsym == ch) return;
     68 	crm->scrsym = ch;
     69 	crm->new = 1;
     70 	on_scr(x,y);
     71 }
     72 
     73 on_scr(x,y)
     74 register x,y;
     75 {
     76 	if(x < scrlx) scrlx = x;
     77 	if(x > scrhx) scrhx = x;
     78 	if(y < scrly) scrly = y;
     79 	if(y > scrhy) scrhy = y;
     80 }
     81 
     82 /* call: (x,y) - display
     83 	(-1,0) - close (leave last symbol)
     84 	(-1,-1)- close (undo last symbol)
     85 	(-1,let)-open: initialize symbol
     86 	(-2,let)-change let
     87 */
     88 
     89 tmp_at(x,y) schar x,y; {
     90 static schar prevx, prevy;
     91 static char let;
     92 	if((int)x == -2){	/* change let call */
     93 		let = y;
     94 		return;
     95 	}
     96 	if((int)x == -1 && (int)y >= 0){	/* open or close call */
     97 		let = y;
     98 		prevx = -1;
     99 		return;
    100 	}
    101 	if(prevx >= 0 && cansee(prevx,prevy)) {
    102 		delay_output();
    103 		prl(prevx, prevy);	/* in case there was a monster */
    104 		at(prevx, prevy, levl[prevx][prevy].scrsym);
    105 	}
    106 	if(x >= 0){	/* normal call */
    107 		if(cansee(x,y)) at(x,y,let);
    108 		prevx = x;
    109 		prevy = y;
    110 	} else {	/* close call */
    111 		let = 0;
    112 		prevx = -1;
    113 	}
    114 }
    115 
    116 /* like the previous, but the symbols are first erased on completion */
    117 Tmp_at(x,y) schar x,y; {
    118 static char let;
    119 static xchar cnt;
    120 static coord tc[COLNO];		/* but watch reflecting beams! */
    121 register xx,yy;
    122 	if((int)x == -1) {
    123 		if(y > 0) {	/* open call */
    124 			let = y;
    125 			cnt = 0;
    126 			return;
    127 		}
    128 		/* close call (do not distinguish y==0 and y==-1) */
    129 		while(cnt--) {
    130 			xx = tc[cnt].x;
    131 			yy = tc[cnt].y;
    132 			prl(xx, yy);
    133 			at(xx, yy, levl[xx][yy].scrsym);
    134 		}
    135 		cnt = let = 0;	/* superfluous */
    136 		return;
    137 	}
    138 	if((int)x == -2) {	/* change let call */
    139 		let = y;
    140 		return;
    141 	}
    142 	/* normal call */
    143 	if(cansee(x,y)) {
    144 		if(cnt) delay_output();
    145 		at(x,y,let);
    146 		tc[cnt].x = x;
    147 		tc[cnt].y = y;
    148 		if(++cnt >= COLNO) panic("Tmp_at overflow?");
    149 		levl[x][y].new = 0;	/* prevent pline-nscr erasing --- */
    150 	}
    151 }
    152 
    153 setclipped(){
    154 	error("Hack needs a screen of size at least %d by %d.\n",
    155 		ROWNO+2, COLNO);
    156 }
    157 
    158 at(x,y,ch)
    159 register xchar x,y;
    160 char ch;
    161 {
    162 #ifndef lint
    163 	/* if xchar is unsigned, lint will complain about  if(x < 0)  */
    164 	if(x < 0 || x > COLNO-1 || y < 0 || y > ROWNO-1) {
    165 		impossible("At gets 0%o at %d %d.", ch, x, y);
    166 		return;
    167 	}
    168 #endif lint
    169 	if(!ch) {
    170 		impossible("At gets null at %d %d.", x, y);
    171 		return;
    172 	}
    173 	y += 2;
    174 	curs(x,y);
    175 	(void) putchar(ch);
    176 	curx++;
    177 }
    178 
    179 prme(){
    180 	if(!Invisible) at(u.ux,u.uy,u.usym);
    181 }
    182 
    183 doredraw()
    184 {
    185 	docrt();
    186 	return(0);
    187 }
    188 
    189 docrt()
    190 {
    191 	register x,y;
    192 	register struct rm *room;
    193 	register struct monst *mtmp;
    194 
    195 	if(u.uswallow) {
    196 		swallowed();
    197 		return;
    198 	}
    199 	cls();
    200 
    201 /* Some ridiculous code to get display of @ and monsters (almost) right */
    202 	if(!Invisible) {
    203 		levl[(u.udisx = u.ux)][(u.udisy = u.uy)].scrsym = u.usym;
    204 		levl[u.udisx][u.udisy].seen = 1;
    205 		u.udispl = 1;
    206 	} else	u.udispl = 0;
    207 
    208 	seemons();	/* reset old positions */
    209 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
    210 		mtmp->mdispl = 0;
    211 	seemons();	/* force new positions to be shown */
    212 /* This nonsense should disappear soon --------------------------------- */
    213 
    214 	for(y = 0; y < ROWNO; y++)
    215 		for(x = 0; x < COLNO; x++)
    216 			if((room = &levl[x][y])->new) {
    217 				room->new = 0;
    218 				at(x,y,room->scrsym);
    219 			} else if(room->seen)
    220 				at(x,y,room->scrsym);
    221 	scrlx = COLNO;
    222 	scrly = ROWNO;
    223 	scrhx = scrhy = 0;
    224 	flags.botlx = 1;
    225 	bot();
    226 }
    227 
    228 docorner(xmin,ymax) register xmin,ymax; {
    229 	register x,y;
    230 	register struct rm *room;
    231 	register struct monst *mtmp;
    232 
    233 	if(u.uswallow) {	/* Can be done more efficiently */
    234 		swallowed();
    235 		return;
    236 	}
    237 
    238 	seemons();	/* reset old positions */
    239 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
    240 	    if(mtmp->mx >= xmin && mtmp->my < ymax)
    241 		mtmp->mdispl = 0;
    242 	seemons();	/* force new positions to be shown */
    243 
    244 	for(y = 0; y < ymax; y++) {
    245 		if(y > ROWNO && CD) break;
    246 		curs(xmin,y+2);
    247 		cl_end();
    248 		if(y < ROWNO) {
    249 		    for(x = xmin; x < COLNO; x++) {
    250 			if((room = &levl[x][y])->new) {
    251 				room->new = 0;
    252 				at(x,y,room->scrsym);
    253 			} else
    254 				if(room->seen)
    255 					at(x,y,room->scrsym);
    256 		    }
    257 		}
    258 	}
    259 	if(ymax > ROWNO) {
    260 		cornbot(xmin-1);
    261 		if(ymax > ROWNO+1 && CD) {
    262 			curs(1,ROWNO+3);
    263 			cl_eos();
    264 		}
    265 	}
    266 }
    267 
    268 curs_on_u(){
    269 	curs(u.ux, u.uy+2);
    270 }
    271 
    272 pru()
    273 {
    274 	if(u.udispl && (Invisible || u.udisx != u.ux || u.udisy != u.uy))
    275 		/* if(! levl[u.udisx][u.udisy].new) */
    276 			if(!vism_at(u.udisx, u.udisy))
    277 				newsym(u.udisx, u.udisy);
    278 	if(Invisible) {
    279 		u.udispl = 0;
    280 		prl(u.ux,u.uy);
    281 	} else
    282 	if(!u.udispl || u.udisx != u.ux || u.udisy != u.uy) {
    283 		atl(u.ux, u.uy, u.usym);
    284 		u.udispl = 1;
    285 		u.udisx = u.ux;
    286 		u.udisy = u.uy;
    287 	}
    288 	levl[u.ux][u.uy].seen = 1;
    289 }
    290 
    291 #ifndef NOWORM
    292 #include	"def.wseg.h"
    293 extern struct wseg *m_atseg;
    294 #endif NOWORM
    295 
    296 /* print a position that is visible for @ */
    297 prl(x,y)
    298 {
    299 	register struct rm *room;
    300 	register struct monst *mtmp;
    301 	register struct obj *otmp;
    302 
    303 	if(x == u.ux && y == u.uy && (!Invisible)) {
    304 		pru();
    305 		return;
    306 	}
    307 	if(!isok(x,y)) return;
    308 	room = &levl[x][y];
    309 	if((!room->typ) ||
    310 	   (IS_ROCK(room->typ) && levl[u.ux][u.uy].typ == CORR))
    311 		return;
    312 	if((mtmp = m_at(x,y)) && !mtmp->mhide &&
    313 		(!mtmp->minvis || See_invisible)) {
    314 #ifndef NOWORM
    315 		if(m_atseg)
    316 			pwseg(m_atseg);
    317 		else
    318 #endif NOWORM
    319 		pmon(mtmp);
    320 	}
    321 	else if((otmp = o_at(x,y)) && room->typ != POOL)
    322 		atl(x,y,otmp->olet);
    323 	else if(mtmp && (!mtmp->minvis || See_invisible)) {
    324 		/* must be a hiding monster, but not hiding right now */
    325 		/* assume for the moment that long worms do not hide */
    326 		pmon(mtmp);
    327 	}
    328 	else if(g_at(x,y) && room->typ != POOL)
    329 		atl(x,y,'$');
    330 	else if(!room->seen || room->scrsym == ' ') {
    331 		room->new = room->seen = 1;
    332 		newsym(x,y);
    333 		on_scr(x,y);
    334 	}
    335 	room->seen = 1;
    336 }
    337 
    338 char
    339 news0(x,y)
    340 register xchar x,y;
    341 {
    342 	register struct obj *otmp;
    343 	register struct trap *ttmp;
    344 	struct rm *room;
    345 	register char tmp;
    346 
    347 	room = &levl[x][y];
    348 	if(!room->seen) tmp = ' ';
    349 	else if(room->typ == POOL) tmp = POOL_SYM;
    350 	else if(!Blind && (otmp = o_at(x,y))) tmp = otmp->olet;
    351 	else if(!Blind && g_at(x,y)) tmp = '$';
    352 	else if(x == xupstair && y == yupstair) tmp = '<';
    353 	else if(x == xdnstair && y == ydnstair) tmp = '>';
    354 	else if((ttmp = t_at(x,y)) && ttmp->tseen) tmp = '^';
    355 	else switch(room->typ) {
    356 	case SCORR:
    357 	case SDOOR:
    358 		tmp = room->scrsym;	/* %% wrong after killing mimic ! */
    359 		break;
    360 	case HWALL:
    361 		tmp = '-';
    362 		break;
    363 	case VWALL:
    364 		tmp = '|';
    365 		break;
    366 	case LDOOR:
    367 	case DOOR:
    368 		tmp = '+';
    369 		break;
    370 	case CORR:
    371 		tmp = CORR_SYM;
    372 		break;
    373 	case ROOM:
    374 		if(room->lit || cansee(x,y) || Blind) tmp = '.';
    375 		else tmp = ' ';
    376 		break;
    377 /*
    378 	case POOL:
    379 		tmp = POOL_SYM;
    380 		break;
    381 */
    382 	default:
    383 		tmp = ERRCHAR;
    384 	}
    385 	return(tmp);
    386 }
    387 
    388 newsym(x,y)
    389 register x,y;
    390 {
    391 	atl(x,y,news0(x,y));
    392 }
    393 
    394 /* used with wand of digging (or pick-axe): fill scrsym and force display */
    395 /* also when a POOL evaporates */
    396 mnewsym(x,y)
    397 register x,y;
    398 {
    399 	register struct rm *room;
    400 	char newscrsym;
    401 
    402 	if(!vism_at(x,y)) {
    403 		room = &levl[x][y];
    404 		newscrsym = news0(x,y);
    405 		if(room->scrsym != newscrsym) {
    406 			room->scrsym = newscrsym;
    407 			room->seen = 0;
    408 		}
    409 	}
    410 }
    411 
    412 nosee(x,y)
    413 register x,y;
    414 {
    415 	register struct rm *room;
    416 
    417 	if(!isok(x,y)) return;
    418 	room = &levl[x][y];
    419 	if(room->scrsym == '.' && !room->lit && !Blind) {
    420 		room->scrsym = ' ';
    421 		room->new = 1;
    422 		on_scr(x,y);
    423 	}
    424 }
    425 
    426 #ifndef QUEST
    427 prl1(x,y)
    428 register x,y;
    429 {
    430 	if(u.dx) {
    431 		if(u.dy) {
    432 			prl(x-(2*u.dx),y);
    433 			prl(x-u.dx,y);
    434 			prl(x,y);
    435 			prl(x,y-u.dy);
    436 			prl(x,y-(2*u.dy));
    437 		} else {
    438 			prl(x,y-1);
    439 			prl(x,y);
    440 			prl(x,y+1);
    441 		}
    442 	} else {
    443 		prl(x-1,y);
    444 		prl(x,y);
    445 		prl(x+1,y);
    446 	}
    447 }
    448 
    449 nose1(x,y)
    450 register x,y;
    451 {
    452 	if(u.dx) {
    453 		if(u.dy) {
    454 			nosee(x,u.uy);
    455 			nosee(x,u.uy-u.dy);
    456 			nosee(x,y);
    457 			nosee(u.ux-u.dx,y);
    458 			nosee(u.ux,y);
    459 		} else {
    460 			nosee(x,y-1);
    461 			nosee(x,y);
    462 			nosee(x,y+1);
    463 		}
    464 	} else {
    465 		nosee(x-1,y);
    466 		nosee(x,y);
    467 		nosee(x+1,y);
    468 	}
    469 }
    470 #endif QUEST
    471 
    472 vism_at(x,y)
    473 register x,y;
    474 {
    475 	register struct monst *mtmp;
    476 
    477 	return((x == u.ux && y == u.uy && !Invisible)
    478 			? 1 :
    479 	       (mtmp = m_at(x,y))
    480 			? ((Blind && Telepat) || canseemon(mtmp)) :
    481 		0);
    482 }
    483 
    484 #ifdef NEWSCR
    485 pobj(obj) register struct obj *obj; {
    486 register int show = (!obj->oinvis || See_invisible) &&
    487 		cansee(obj->ox,obj->oy);
    488 	if(obj->odispl){
    489 		if(obj->odx != obj->ox || obj->ody != obj->oy || !show)
    490 		if(!vism_at(obj->odx,obj->ody)){
    491 			newsym(obj->odx, obj->ody);
    492 			obj->odispl = 0;
    493 		}
    494 	}
    495 	if(show && !vism_at(obj->ox,obj->oy)){
    496 		atl(obj->ox,obj->oy,obj->olet);
    497 		obj->odispl = 1;
    498 		obj->odx = obj->ox;
    499 		obj->ody = obj->oy;
    500 	}
    501 }
    502 #endif NEWSCR
    503 
    504 unpobj(obj) register struct obj *obj; {
    505 /* 	if(obj->odispl){
    506 		if(!vism_at(obj->odx, obj->ody))
    507 			newsym(obj->odx, obj->ody);
    508 		obj->odispl = 0;
    509 	}
    510 */
    511 	if(!vism_at(obj->ox,obj->oy))
    512 		newsym(obj->ox,obj->oy);
    513 }
    514 
    515 seeobjs(){
    516 register struct obj *obj, *obj2;
    517 	for(obj = fobj; obj; obj = obj2) {
    518 		obj2 = obj->nobj;
    519 		if(obj->olet == FOOD_SYM && obj->otyp >= CORPSE
    520 			&& obj->age + 250 < moves)
    521 				delobj(obj);
    522 	}
    523 	for(obj = invent; obj; obj = obj2) {
    524 		obj2 = obj->nobj;
    525 		if(obj->olet == FOOD_SYM && obj->otyp >= CORPSE
    526 			&& obj->age + 250 < moves)
    527 				useup(obj);
    528 	}
    529 }
    530 
    531 seemons(){
    532 register struct monst *mtmp;
    533 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){
    534 		if(mtmp->data->mlet == ';')
    535 			mtmp->minvis = (u.ustuck != mtmp &&
    536 					levl[mtmp->mx][mtmp->my].typ == POOL);
    537 		pmon(mtmp);
    538 #ifndef NOWORM
    539 		if(mtmp->wormno) wormsee(mtmp->wormno);
    540 #endif NOWORM
    541 	}
    542 }
    543 
    544 pmon(mon) register struct monst *mon; {
    545 register int show = (Blind && Telepat) || canseemon(mon);
    546 	if(mon->mdispl){
    547 		if(mon->mdx != mon->mx || mon->mdy != mon->my || !show)
    548 			unpmon(mon);
    549 	}
    550 	if(show && !mon->mdispl){
    551 		atl(mon->mx,mon->my,
    552 		 (!mon->mappearance
    553 		  || u.uprops[PROP(RIN_PROTECTION_FROM_SHAPE_CHANGERS)].p_flgs
    554 		 ) ? mon->data->mlet : mon->mappearance);
    555 		mon->mdispl = 1;
    556 		mon->mdx = mon->mx;
    557 		mon->mdy = mon->my;
    558 	}
    559 }
    560 
    561 unpmon(mon) register struct monst *mon; {
    562 	if(mon->mdispl){
    563 		newsym(mon->mdx, mon->mdy);
    564 		mon->mdispl = 0;
    565 	}
    566 }
    567 
    568 nscr()
    569 {
    570 	register x,y;
    571 	register struct rm *room;
    572 
    573 	if(u.uswallow || u.ux == FAR || flags.nscrinh) return;
    574 	pru();
    575 	for(y = scrly; y <= scrhy; y++)
    576 		for(x = scrlx; x <= scrhx; x++)
    577 			if((room = &levl[x][y])->new) {
    578 				room->new = 0;
    579 				at(x,y,room->scrsym);
    580 			}
    581 	scrhx = scrhy = 0;
    582 	scrlx = COLNO;
    583 	scrly = ROWNO;
    584 }
    585 
    586 /* 100 suffices for bot(); no relation with COLNO */
    587 char oldbot[100], newbot[100];
    588 cornbot(lth)
    589 register int lth;
    590 {
    591 	if(lth < sizeof(oldbot)) {
    592 		oldbot[lth] = 0;
    593 		flags.botl = 1;
    594 	}
    595 }
    596 
    597 bot()
    598 {
    599 register char *ob = oldbot, *nb = newbot;
    600 register int i;
    601 extern char *eos();
    602 	if(flags.botlx) *ob = 0;
    603 	flags.botl = flags.botlx = 0;
    604 #ifdef GOLD_ON_BOTL
    605 	(void) sprintf(newbot,
    606 		"Level %-2d  Gold %-5lu  Hp %3d(%d)  Ac %-2d  Str ",
    607 		dlevel, u.ugold, u.uhp, u.uhpmax, u.uac);
    608 #else
    609 	(void) sprintf(newbot,
    610 		"Level %-2d   Hp %3d(%d)   Ac %-2d   Str ",
    611 		dlevel,  u.uhp, u.uhpmax, u.uac);
    612 #endif GOLD_ON_BOTL
    613 	if(u.ustr>18) {
    614 	    if(u.ustr>117)
    615 		(void) strcat(newbot,"18/**");
    616 	    else
    617 		(void) sprintf(eos(newbot), "18/%02d",u.ustr-18);
    618 	} else
    619 	    (void) sprintf(eos(newbot), "%-2d   ",u.ustr);
    620 #ifdef EXP_ON_BOTL
    621 	(void) sprintf(eos(newbot), "  Exp %2d/%-5lu ", u.ulevel,u.uexp);
    622 #else
    623 	(void) sprintf(eos(newbot), "   Exp %2u  ", u.ulevel);
    624 #endif EXP_ON_BOTL
    625 	(void) strcat(newbot, hu_stat[u.uhs]);
    626 	if(flags.time)
    627 	    (void) sprintf(eos(newbot), "  %ld", moves);
    628 	if(strlen(newbot) >= COLNO) {
    629 		register char *bp0, *bp1;
    630 		bp0 = bp1 = newbot;
    631 		do {
    632 			if(*bp0 != ' ' || bp0[1] != ' ' || bp0[2] != ' ')
    633 				*bp1++ = *bp0;
    634 		} while(*bp0++);
    635 	}
    636 	for(i = 1; i<COLNO; i++) {
    637 		if(*ob != *nb){
    638 			curs(i,ROWNO+2);
    639 			(void) putchar(*nb ? *nb : ' ');
    640 			curx++;
    641 		}
    642 		if(*ob) ob++;
    643 		if(*nb) nb++;
    644 	}
    645 	(void) strcpy(oldbot, newbot);
    646 }
    647 
    648 #ifdef WAN_PROBING
    649 mstatusline(mtmp) register struct monst *mtmp; {
    650 	pline("Status of %s: ", monnam(mtmp));
    651 	pline("Level %-2d  Gold %-5lu  Hp %3d(%d)  Ac %-2d  Dam %d",
    652 	    mtmp->data->mlevel, mtmp->mgold, mtmp->mhp, mtmp->mhpmax,
    653 	    mtmp->data->ac, (mtmp->data->damn + 1) * (mtmp->data->damd + 1));
    654 }
    655 #endif WAN_PROBING
    656 
    657 cls(){
    658 	if(flags.toplin == 1)
    659 		more();
    660 	flags.toplin = 0;
    661 
    662 	clear_screen();
    663 
    664 	flags.botlx = 1;
    665 }
    666