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