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