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