1 /* 2 * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. 3 */ 4 5 #ifndef lint 6 static char rcsid[] = "$Id: hack.pri.c,v 1.3 1993/12/02 03:07:18 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