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: }