/* $OpenBSD: hack.pri.c,v 1.9 2003/05/19 09:00:54 pjanzen Exp $ */ /* * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica, * Amsterdam * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of the Stichting Centrum voor Wiskunde en * Informatica, nor the names of its contributors may be used to endorse or * promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1982 Jay Fenlason * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef lint static const char rcsid[] = "$OpenBSD: hack.pri.c,v 1.9 2003/05/19 09:00:54 pjanzen Exp $"; #endif /* not lint */ #include #include #include #include #include "hack.h" xchar scrlx, scrhx, scrly, scrhy; /* corners of new area on screen */ extern char *hu_stat[]; /* in eat.c */ extern char *CD; static void cornbot(int); void swallowed() { char ulook[] = "|@|"; ulook[1] = u.usym; cls(); curs(u.ux-1, u.uy+1); fputs("/-\\", stdout); curx = u.ux+2; curs(u.ux-1, u.uy+2); fputs(ulook, stdout); curx = u.ux+2; curs(u.ux-1, u.uy+3); fputs("\\-/", stdout); curx = u.ux+2; u.udispl = 1; u.udisx = u.ux; u.udisy = u.uy; } /*VARARGS1*/ boolean panicking; void panic(char *str, ...) { va_list ap; if(panicking++) exit(1); /* avoid loops - this should never happen*/ home(); puts(" Suddenly, the dungeon collapses."); fputs(" ERROR: ", stdout); va_start(ap, str); vprintf(str, ap); va_end(ap); #ifdef DEBUG #ifdef UNIX if(!fork()) abort(); /* generate core dump */ #endif /* UNIX */ #endif /* DEBUG */ more(); /* contains a fflush() */ done("panicked"); } void atl(int x, int y, int ch) { struct rm *crm = &levl[x][y]; if(x<0 || x>COLNO-1 || y<0 || y>ROWNO-1){ impossible("atl(%d,%d,%c)",x,y,ch); return; } if(crm->seen && crm->scrsym == ch) return; crm->scrsym = ch; crm->new = 1; on_scr(x,y); } void on_scr(int x, int y) { if(x < scrlx) scrlx = x; if(x > scrhx) scrhx = x; if(y < scrly) scrly = y; if(y > scrhy) scrhy = y; } /* call: (x,y) - display * (-1,0) - close (leave last symbol) * (-1,-1)- close (undo last symbol) * (-1,let)-open: initialize symbol * (-2,let)-change let */ void tmp_at(schar x, schar y) { static schar prevx, prevy; static char let; if((int)x == -2){ /* change let call */ let = y; return; } if((int)x == -1 && (int)y >= 0){ /* open or close call */ let = y; prevx = -1; return; } if(prevx >= 0 && cansee(prevx,prevy)) { delay_output(50); prl(prevx, prevy); /* in case there was a monster */ at(prevx, prevy, levl[(int)prevx][(int)prevy].scrsym); } if(x >= 0){ /* normal call */ if(cansee(x,y)) at(x,y,let); prevx = x; prevy = y; } else { /* close call */ let = 0; prevx = -1; } } /* like the previous, but the symbols are first erased on completion */ void Tmp_at(schar x, schar y) { static char let; static xchar cnt; static coord tc[COLNO]; /* but watch reflecting beams! */ int xx,yy; if((int)x == -1) { if(y > 0) { /* open call */ let = y; cnt = 0; return; } /* close call (do not distinguish y==0 and y==-1) */ while(cnt--) { xx = tc[(int)cnt].x; yy = tc[(int)cnt].y; prl(xx, yy); at(xx, yy, levl[xx][yy].scrsym); } cnt = let = 0; /* superfluous */ return; } if((int)x == -2) { /* change let call */ let = y; return; } /* normal call */ if(cansee(x,y)) { if(cnt) delay_output(50); at(x,y,let); tc[(int)cnt].x = x; tc[(int)cnt].y = y; if(++cnt >= COLNO) panic("Tmp_at overflow?"); levl[(int)x][(int)y].new = 0; /* prevent pline-nscr erasing --- */ } } void setclipped() { error("Hack needs a screen of size at least %d by %d.\n", ROWNO+2, COLNO); } void at(xchar x, xchar y, char ch) { #ifndef lint /* if xchar is unsigned, lint will complain about if(x < 0) */ if(x < 0 || x > COLNO-1 || y < 0 || y > ROWNO-1) { impossible("At gets 0%o at %d %d.", ch, x, y); return; } #endif /* lint */ if(!ch) { impossible("At gets null at %d %d.", x, y); return; } y += 2; curs(x,y); (void) putchar(ch); curx++; } void prme() { if(!Invisible) at(u.ux,u.uy,u.usym); } int doredraw() { docrt(); return(0); } void docrt() { int x,y; struct rm *room; struct monst *mtmp; if(u.uswallow) { swallowed(); return; } cls(); /* Some ridiculous code to get display of @ and monsters (almost) right */ if(!Invisible) { levl[(int)(u.udisx = u.ux)][(int)(u.udisy = u.uy)].scrsym = u.usym; levl[(int)u.udisx][(int)u.udisy].seen = 1; u.udispl = 1; } else u.udispl = 0; seemons(); /* reset old positions */ for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) mtmp->mdispl = 0; seemons(); /* force new positions to be shown */ /* This nonsense should disappear soon --------------------------------- */ for(y = 0; y < ROWNO; y++) for(x = 0; x < COLNO; x++) if((room = &levl[x][y])->new) { room->new = 0; at(x,y,room->scrsym); } else if(room->seen) at(x,y,room->scrsym); scrlx = COLNO; scrly = ROWNO; scrhx = scrhy = 0; flags.botlx = 1; bot(); } void docorner(int xmin, int ymax) { int x,y; struct rm *room; struct monst *mtmp; if(u.uswallow) { /* Can be done more efficiently */ swallowed(); return; } seemons(); /* reset old positions */ for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) if(mtmp->mx >= xmin && mtmp->my < ymax) mtmp->mdispl = 0; seemons(); /* force new positions to be shown */ for(y = 0; y < ymax; y++) { if(y > ROWNO && CD) break; curs(xmin,y+2); cl_end(); if(y < ROWNO) { for(x = xmin; x < COLNO; x++) { if((room = &levl[x][y])->new) { room->new = 0; at(x,y,room->scrsym); } else if(room->seen) at(x,y,room->scrsym); } } } if(ymax > ROWNO) { cornbot(xmin-1); if(ymax > ROWNO+1 && CD) { curs(1,ROWNO+3); cl_eos(); } } } void curs_on_u() { curs(u.ux, u.uy+2); } void pru() { if(u.udispl && (Invisible || u.udisx != u.ux || u.udisy != u.uy)) /* if(! levl[u.udisx][u.udisy].new) */ if(!vism_at(u.udisx, u.udisy)) newsym(u.udisx, u.udisy); if(Invisible) { u.udispl = 0; prl(u.ux,u.uy); } else if(!u.udispl || u.udisx != u.ux || u.udisy != u.uy) { atl(u.ux, u.uy, u.usym); u.udispl = 1; u.udisx = u.ux; u.udisy = u.uy; } levl[(int)u.ux][(int)u.uy].seen = 1; } #ifndef NOWORM extern struct wseg *m_atseg; #endif /* NOWORM */ /* print a position that is visible for @ */ void prl(int x, int y) { struct rm *room; struct monst *mtmp; struct obj *otmp; if(x == u.ux && y == u.uy && (!Invisible)) { pru(); return; } if(!isok(x,y)) return; room = &levl[x][y]; if((!room->typ) || (IS_ROCK(room->typ) && levl[(int)u.ux][(int)u.uy].typ == CORR)) return; if((mtmp = m_at(x,y)) && !mtmp->mhide && (!mtmp->minvis || See_invisible)) { #ifndef NOWORM if(m_atseg) pwseg(m_atseg); else #endif /* NOWORM */ pmon(mtmp); } else if((otmp = o_at(x,y)) && room->typ != POOL) atl(x,y,otmp->olet); else if(mtmp && (!mtmp->minvis || See_invisible)) { /* must be a hiding monster, but not hiding right now */ /* assume for the moment that long worms do not hide */ pmon(mtmp); } else if(g_at(x,y) && room->typ != POOL) atl(x,y,'$'); else if(!room->seen || room->scrsym == ' ') { room->new = room->seen = 1; newsym(x,y); on_scr(x,y); } room->seen = 1; } char news0(xchar x, xchar y) { struct obj *otmp; struct trap *ttmp; struct rm *room; char tmp; room = &levl[(int)x][(int)y]; if(!room->seen) tmp = ' '; else if(room->typ == POOL) tmp = POOL_SYM; else if(!Blind && (otmp = o_at(x,y))) tmp = otmp->olet; else if(!Blind && g_at(x,y)) tmp = '$'; else if(x == xupstair && y == yupstair) tmp = '<'; else if(x == xdnstair && y == ydnstair) tmp = '>'; else if((ttmp = t_at(x,y)) && ttmp->tseen) tmp = '^'; else switch(room->typ) { case SCORR: case SDOOR: tmp = room->scrsym; /* %% wrong after killing mimic ! */ break; case HWALL: tmp = '-'; break; case VWALL: tmp = '|'; break; case LDOOR: case DOOR: tmp = '+'; break; case CORR: tmp = CORR_SYM; break; case ROOM: if(room->lit || cansee(x,y) || Blind) tmp = '.'; else tmp = ' '; break; /* case POOL: tmp = POOL_SYM; break; */ default: tmp = ERRCHAR; } return(tmp); } void newsym(int x, int y) { atl(x,y,news0(x,y)); } /* used with wand of digging (or pick-axe): fill scrsym and force display */ /* also when a POOL evaporates */ void mnewsym(int x, int y) { struct rm *room; char newscrsym; if(!vism_at(x,y)) { room = &levl[x][y]; newscrsym = news0(x,y); if(room->scrsym != newscrsym) { room->scrsym = newscrsym; room->seen = 0; } } } void nosee(int x, int y) { struct rm *room; if(!isok(x,y)) return; room = &levl[x][y]; if(room->scrsym == '.' && !room->lit && !Blind) { room->scrsym = ' '; room->new = 1; on_scr(x,y); } } #ifndef QUEST void prl1(int x, int y) { if(u.dx) { if(u.dy) { prl(x-(2*u.dx),y); prl(x-u.dx,y); prl(x,y); prl(x,y-u.dy); prl(x,y-(2*u.dy)); } else { prl(x,y-1); prl(x,y); prl(x,y+1); } } else { prl(x-1,y); prl(x,y); prl(x+1,y); } } void nose1(int x, int y) { if(u.dx) { if(u.dy) { nosee(x,u.uy); nosee(x,u.uy-u.dy); nosee(x,y); nosee(u.ux-u.dx,y); nosee(u.ux,y); } else { nosee(x,y-1); nosee(x,y); nosee(x,y+1); } } else { nosee(x-1,y); nosee(x,y); nosee(x+1,y); } } #endif /* QUEST */ int vism_at(int x, int y) { struct monst *mtmp; return((x == u.ux && y == u.uy && !Invisible) ? 1 : (mtmp = m_at(x,y)) ? ((Blind && Telepat) || canseemon(mtmp)) : 0); } void unpobj(struct obj *obj) { /* if(obj->odispl){ if(!vism_at(obj->odx, obj->ody)) newsym(obj->odx, obj->ody); obj->odispl = 0; } */ if(!vism_at(obj->ox,obj->oy)) newsym(obj->ox,obj->oy); } void seeobjs() { struct obj *obj, *obj2; for(obj = fobj; obj; obj = obj2) { obj2 = obj->nobj; if(obj->olet == FOOD_SYM && obj->otyp >= CORPSE && obj->age + 250 < moves) delobj(obj); } for(obj = invent; obj; obj = obj2) { obj2 = obj->nobj; if(obj->olet == FOOD_SYM && obj->otyp >= CORPSE && obj->age + 250 < moves) useup(obj); } } void seemons() { struct monst *mtmp; for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){ if(mtmp->data->mlet == ';') mtmp->minvis = (u.ustuck != mtmp && levl[(int)mtmp->mx][(int)mtmp->my].typ == POOL); pmon(mtmp); #ifndef NOWORM if(mtmp->wormno) wormsee(mtmp->wormno); #endif /* NOWORM */ } } void pmon(struct monst *mon) { int show = (Blind && Telepat) || canseemon(mon); if(mon->mdispl){ if(mon->mdx != mon->mx || mon->mdy != mon->my || !show) unpmon(mon); } if(show && !mon->mdispl){ atl(mon->mx,mon->my, (!mon->mappearance || u.uprops[PROP(RIN_PROTECTION_FROM_SHAPE_CHANGERS)].p_flgs ) ? mon->data->mlet : mon->mappearance); mon->mdispl = 1; mon->mdx = mon->mx; mon->mdy = mon->my; } } void unpmon(struct monst *mon) { if(mon->mdispl){ newsym(mon->mdx, mon->mdy); mon->mdispl = 0; } } void nscr() { int x,y; struct rm *room; if(u.uswallow || u.ux == FAR || flags.nscrinh) return; pru(); for(y = scrly; y <= scrhy; y++) for(x = scrlx; x <= scrhx; x++) if((room = &levl[x][y])->new) { room->new = 0; at(x,y,room->scrsym); } scrhx = scrhy = 0; scrlx = COLNO; scrly = ROWNO; } /* 100 suffices for bot(); no relation with COLNO */ char oldbot[100], newbot[100]; static void cornbot(int lth) { if(lth < sizeof(oldbot)) { oldbot[lth] = 0; flags.botl = 1; } } void bot() { char *ob = oldbot, *nb = newbot, *bp; int i; if(flags.botlx) *ob = 0; flags.botl = flags.botlx = 0; #ifdef GOLD_ON_BOTL (void) snprintf(newbot, sizeof newbot, "Level %-2d Gold %-5lu Hp %3d(%d) Ac %-2d Str ", dlevel, u.ugold, u.uhp, u.uhpmax, u.uac); #else (void) snprintf(newbot, sizeof newbot, "Level %-2d Hp %3d(%d) Ac %-2d Str ", dlevel, u.uhp, u.uhpmax, u.uac); #endif /* GOLD_ON_BOTL */ if(u.ustr>18) { if(u.ustr>117) (void) strlcat(newbot,"18/**",sizeof newbot); else { bp = eos(newbot); (void) snprintf(bp, newbot + sizeof newbot - bp, "18/%02d",u.ustr-18); } } else { bp = eos(newbot); (void) snprintf(bp, newbot + sizeof newbot - bp, "%-2d ",u.ustr); } bp = eos(newbot); #ifdef EXP_ON_BOTL (void) snprintf(bp, newbot + sizeof newbot - bp, " Exp %2d/%-5lu ", u.ulevel,u.uexp); #else (void) snprintf(bp, newbot + sizeof newbot - bp, " Exp %2u ", u.ulevel); #endif /* EXP_ON_BOTL */ (void) strlcat(newbot, hu_stat[u.uhs], sizeof newbot); if(flags.time) { bp = eos(newbot); (void) snprintf(bp, newbot + sizeof newbot - bp, " %ld", moves); } if(strlen(newbot) >= COLNO) { char *bp0, *bp1; bp0 = bp1 = newbot; do { if(*bp0 != ' ' || bp0[1] != ' ' || bp0[2] != ' ') *bp1++ = *bp0; } while(*bp0++); } for(i = 1; idata->mlevel, mtmp->mgold, mtmp->mhp, mtmp->mhpmax, mtmp->data->ac, (mtmp->data->damn + 1) * (mtmp->data->damd + 1)); } #endif /* WAN_PROBING */ void cls() { if(flags.toplin == 1) more(); flags.toplin = 0; clr_screen(); flags.botlx = 1; }