This is lock.c in view mode; [Download] [Up]
/* SCCS Id: @(#)lock.c 3.0 88/10/22 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ #include "hack.h" #ifndef OVERLAY static int NDECL(picklock); static int NDECL(forcelock); #else int NDECL(picklock); int NDECL(forcelock); #endif static boolean FDECL(obstructed,(int,int)); VSTATIC struct xlock_s { int door_or_box, picktyp; struct rm *door; struct obj *box; int chance, usedtime; } xlock; #ifdef OVLB #ifndef OVERLAY static #endif int picklock() { /* try to open/close a lock */ if(!xlock.door_or_box) { /* box */ if((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy)) { return((xlock.usedtime = 0)); /* you or it moved */ } } else { /* door */ if(xlock.door != &(levl[u.ux+u.dx][u.uy+u.dy])) { return((xlock.usedtime = 0)); /* you moved */ } switch (xlock.door->doormask) { case D_NODOOR: pline("This doorway has no door."); return((xlock.usedtime = 0)); case D_ISOPEN: pline("Picking the lock of an open door is pointless."); return((xlock.usedtime = 0)); case D_BROKEN: pline("This door is broken."); return((xlock.usedtime = 0)); } } if(xlock.usedtime++ >= 50 #ifdef POLYSELF || nohands(uasmon) #endif ) { You("give up your attempt to %s the lock.", (xlock.door_or_box ? !(xlock.door->doormask & D_LOCKED) : !xlock.box->olocked) ? "lock" : ((xlock.picktyp == LOCK_PICK) ? "pick" : "open" )); return((xlock.usedtime = 0)); } if(rn2(100) > xlock.chance) return(1); /* still busy */ if(xlock.door_or_box) { You("succeed in %sing the lock.", !(xlock.door->doormask & D_LOCKED) ? "lock" : ((xlock.picktyp == LOCK_PICK) ? "pick" : "open" )); if(xlock.door->doormask & D_TRAPPED) { b_trapped("door"); xlock.door->doormask = D_NODOOR; mnewsym(u.ux+u.dx, u.uy+u.dy); prl(u.ux+u.dx, u.uy+u.dy); } else if(xlock.door->doormask == D_LOCKED) xlock.door->doormask = D_CLOSED; else xlock.door->doormask = D_LOCKED; } else { You("succeed in %sing the lock.", (!xlock.box->olocked) ? "lock" : (xlock.picktyp == LOCK_PICK) ? "pick" : "open" ); xlock.box->olocked = !xlock.box->olocked; if(xlock.box->otrapped) chest_trap(xlock.box, FINGER); } return((xlock.usedtime = 0)); } #ifndef OVERLAY static #endif int forcelock() { /* try to force a locked chest */ register struct obj *otmp, *otmp2; register struct obj *probj = fcobj; /* initialize to make lint happy */ if((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy)) return((xlock.usedtime = 0)); /* you or it moved */ if(xlock.usedtime++ >= 50 || !uwep #ifdef POLYSELF || nohands(uasmon) #endif ) { You("give up your attempt to force the lock."); return((xlock.usedtime = 0)); } if(xlock.picktyp) { /* blade */ if(rn2(1000-uwep->spe) > 992 && !uwep->cursed) { /* for a +0 weapon, probability that it survives an unsuccessful * attempt to force the lock is (.992)^50 = .67 */ pline("%sour %s broke!", (uwep->quan > 1) ? "One of y" : "Y", xname(uwep)); useup(uwep); You("give up your attempt to force the lock."); return((xlock.usedtime = 0)); } } else /* blunt */ wake_nearby(); /* due to hammering on the container */ if(rn2(100) > xlock.chance) return(1); /* still busy */ You("succeed in forcing the lock."); xlock.box->olocked = !xlock.box->olocked; if(!xlock.picktyp && !rn2(3)) { pline("In fact, you've totally destroyed the %s.", xname(xlock.box)); for(otmp = fcobj; otmp; otmp = otmp2) { otmp2 = otmp->nobj; if(otmp->cobj == xlock.box) { /* unlink it from the "contained" list */ if(otmp == fcobj) fcobj = otmp2; else probj->nobj = otmp2; if(!rn2(3) || otmp->olet == POTION_SYM) free((genericptr_t) otmp); else { /* spill it onto the floor */ otmp->nobj = xlock.box->nobj; xlock.box->nobj = otmp; otmp->cobj = (struct obj *)0; place_object(otmp, u.ux, u.uy); stackobj(otmp); } } else probj = otmp; } delobj(xlock.box); } return((xlock.usedtime = 0)); } #endif /* OVLB */ #ifdef OVL0 void reset_pick() { xlock.usedtime = 0; } #endif /* OVL0 */ #ifdef OVLB int pick_lock(pick) /* pick a lock with a given object */ register struct obj *pick; { register int x, y, picktyp, c, ch; register struct rm *door; register struct obj *otmp; #ifdef __GNULINT__ ch = 0; /* GCC myopia */ #endif picktyp = pick->otyp; if(xlock.usedtime && picktyp == xlock.picktyp) { You("resume your attempt to %s the lock.", (xlock.door_or_box ? !(xlock.door->doormask & D_LOCKED) : !xlock.box->olocked) ? "lock" : ((xlock.picktyp == LOCK_PICK) ? "pick" : "open" )); set_occupation(picklock, (picktyp == LOCK_PICK) ? "picking the lock" : "opening the lock", 0); return(1); } #ifdef POLYSELF if(nohands(uasmon)) { You("can't hold a %s - you have no hands!", xname(pick)); return(0); } #endif if((picktyp != LOCK_PICK && picktyp != CREDIT_CARD && picktyp != SKELETON_KEY && picktyp != KEY)) { impossible("picking lock with object %d?", picktyp); return(0); } if(!getdir(1)) return(0); x = u.ux + u.dx; y = u.uy + u.dy; if((x == u.ux) && (y == u.uy)) { /* pick the lock on a container */ c = 'n'; /* in case there are no boxes here */ for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere) if(Is_box(otmp) && /* credit cards are only good for unlocking */ (picktyp != CREDIT_CARD || otmp->olocked)) { pline("There is %s here, %s the lock? ", doname(otmp), (!otmp->olocked) ? "close" : ((picktyp == LOCK_PICK) ? "pick" : "open" )); c = ynq(); if(c == 'q') return(0); if(c == 'n') continue; if(picktyp == KEY && otmp->spe != pick->spe) { pline("The %s won't fit the lock.",xname(pick)); return(1); } switch(picktyp) { case CREDIT_CARD: ch = ACURR(A_DEX)+(20*(pl_character[0] == 'R')); break; case LOCK_PICK: ch = 4*ACURR(A_DEX)+(25*(pl_character[0] == 'R')); break; case SKELETON_KEY: ch = 75 + ACURR(A_DEX); break; case KEY: ch = 1000; break; default: ch = 0; } if(otmp->cursed) ch /= 2; xlock.door_or_box = 0; xlock.picktyp = picktyp; xlock.box = otmp; break; } if(c != 'y') return(0); /* decided against all boxes */ } else { /* pick the lock in a door */ struct monst *mtmp; door = &levl[x][y]; if (MON_AT(x, y) && canseemon(mtmp = m_at(x,y)) && !mtmp->mimic) { if (picktyp == CREDIT_CARD && #ifdef ORACLE (mtmp->isshk || mtmp->data == &mons[PM_ORACLE])) #else mtmp->isshk) #endif verbalize("No checks, no credit, no problem."); else kludge("I don't think %s would appreciate that.", mon_nam(mtmp)); return(0); } if(!IS_DOOR(door->typ)) { #ifdef STRONGHOLD if (is_drawbridge_wall(x,y) >= 0) You("%s no lock on the drawbridge.", Blind ? "feel" : "see"); else #endif You("%s no door there.", Blind ? "feel" : "see"); return(0); } switch (door->doormask) { case D_NODOOR: pline("This doorway has no door."); return(0); case D_ISOPEN: pline("Picking the lock of an open door is pointless."); return(0); case D_BROKEN: pline("This door is broken."); return(0); default: /* credit cards are only good for unlocking */ if(picktyp == CREDIT_CARD && !(door->doormask & D_LOCKED)) { You("can't lock a door with a credit card."); return(0); } pline("%sock it? ", (door->doormask & D_LOCKED) ? "Unl" : "L" ); c = yn(); if(c == 'n') return(0); switch(picktyp) { case CREDIT_CARD: ch = 2*ACURR(A_DEX)+(20*(pl_character[0] == 'R')); break; case LOCK_PICK: ch = 3*ACURR(A_DEX)+(30*(pl_character[0] == 'R')); break; case SKELETON_KEY: ch = 70 + ACURR(A_DEX); break; case KEY: pline("The %s won't fit the door.", xname(pick)); return(1); default: ch = 0; } xlock.door_or_box = 1; xlock.door = door; } } flags.move = 0; xlock.chance = ch; xlock.picktyp = picktyp; xlock.usedtime = 0; set_occupation(picklock, (picktyp == LOCK_PICK) ? "picking the lock" : "opening the lock", 0); return(1); } int doforce() { /* try to force a chest with your weapon */ register struct obj *otmp; register int c, picktyp; if(!uwep || /* proper type test */ (uwep->olet != WEAPON_SYM && uwep->olet != ROCK_SYM && uwep->otyp != PICK_AXE) || (uwep->otyp < DAGGER) || (uwep->otyp > VOULGE && uwep->olet != ROCK_SYM && uwep->otyp != PICK_AXE) ) { You("can't force anything without a %sweapon.", (uwep) ? "proper " : ""); return(0); } picktyp = (uwep->otyp >= DAGGER && uwep->otyp <= KATANA); if(xlock.usedtime && xlock.box && picktyp == xlock.picktyp) { You("resume your attempt to force the lock."); set_occupation(forcelock, "forcing the lock", 0); return(1); } /* A lock is made only for the honest man, the thief will break it. */ xlock.box = (struct obj *)0; for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere) if(Is_box(otmp)) { if(otmp->olocked) pline("There is %s here, force the lock? ", doname(otmp)); else { pline("There is a %s here, but it's already unlocked.", xname(otmp)); continue; } c = ynq(); if(c == 'q') return(0); if(c == 'n') continue; if(picktyp) You("force your %s into a crack and pry.", xname(uwep)); else You("start bashing it with your %s.", xname(uwep)); xlock.box = otmp; xlock.chance = objects[otmp->otyp].wldam * 2; xlock.picktyp = picktyp; xlock.usedtime = 0; break; } if(xlock.box) set_occupation(forcelock, "forcing the lock", 0); else You("decide not to force the issue."); return(1); } int doopen() { /* try to open a door */ register int x, y; register struct rm *door; struct monst *mtmp; if(!getdir(1)) return(0); x = u.ux + u.dx; y = u.uy + u.dy; if((x == u.ux) && (y == u.uy)) return(0); if(MON_AT(x, y) && (mtmp = m_at(x,y))->mimic && mtmp->m_ap_type == M_AP_FURNITURE && mtmp->mappearance == S_cdoor && !Protection_from_shape_changers) { stumble_onto_mimic(mtmp); return(1); } door = &levl[x][y]; if(!IS_DOOR(door->typ)) { #ifdef STRONGHOLD if (is_db_wall(x,y)) { pline("There is no obvious way to open the drawbridge."); return(0); } #endif You("%s no door there.", Blind ? "feel" : "see"); return(0); } if(!(door->doormask & D_CLOSED)) { switch(door->doormask) { case D_BROKEN: pline("This door is broken."); break; case D_NODOOR: pline("This doorway has no door."); break; case D_ISOPEN: pline("This door is already open."); break; default: pline("This door is locked."); break; } return(0); } #ifdef POLYSELF if(verysmall(uasmon)) { pline("You're too small to pull the door open."); return(0); } #endif /* door is known to be CLOSED */ if (rnl(20) < (ACURR(A_STR)+ACURR(A_DEX)+ACURR(A_CON))/3) { pline("The door opens."); if(door->doormask & D_TRAPPED) { b_trapped("door"); door->doormask = D_NODOOR; } else door->doormask = D_ISOPEN; mnewsym(x,y); prl(x,y); } else { pline("The door resists!"); } return(1); } static boolean obstructed(x,y) register int x, y; { if(MON_AT(x, y)) { if (m_at(x,y)->mimic) goto obj; pline("%s stands in the way!", Blind ? "Some creature" : Monnam(m_at(x,y))); return(TRUE); } if (OBJ_AT(x, y) || levl[x][y].gmask) { obj: pline("Something's in the way."); return(TRUE); } return(FALSE); } int doclose() { /* try to close a door */ register int x, y; register struct rm *door; struct monst *mtmp; if(!getdir(1)) return(0); x = u.ux + u.dx; y = u.uy + u.dy; if((x == u.ux) && (y == u.uy)) { You("are in the way!"); return(1); } if(MON_AT(x, y) && (mtmp = m_at(x,y))->mimic && mtmp->m_ap_type == M_AP_FURNITURE && mtmp->mappearance == S_cdoor && !Protection_from_shape_changers) { stumble_onto_mimic(mtmp); return(1); } door = &levl[x][y]; if(!IS_DOOR(door->typ)) { #ifdef STRONGHOLD if (door->typ == DRAWBRIDGE_DOWN) pline("There is no obvious way to close the drawbridge."); else #endif You("%s no door there.", Blind ? "feel" : "see"); return(0); } if(door->doormask == D_NODOOR) { pline("This doorway has no door."); return(0); } if(obstructed(x, y)) return(0); if(door->doormask == D_BROKEN) { pline("This door is broken."); return(0); } if(door->doormask & (D_CLOSED | D_LOCKED)) { pline("This door is already closed."); return(0); } if(door->doormask == D_ISOPEN) { #ifdef POLYSELF if(verysmall(uasmon)) { pline("You're too small to push the door closed."); return(0); } #endif if (rn2(25) < (ACURR(A_STR)+ACURR(A_DEX)+ACURR(A_CON))/3) { pline("The door closes."); door->doormask = D_CLOSED; mnewsym(x,y); prl(x,y); } else pline("The door resists!"); } return(1); } int boxlock(obj, otmp) /* box obj was hit with spell effect otmp */ /* returns 1 if something happened */ register struct obj *obj, *otmp; /* obj *is* a box */ { register boolean res = 0; switch(otmp->otyp) { case WAN_LOCKING: #ifdef SPELLS case SPE_WIZARD_LOCK: #endif if(!obj->olocked) { pline("Klunk!"); obj->olocked = !(obj->olocked); res = 1; } else res = 0; break; case WAN_OPENING: #ifdef SPELLS case SPE_KNOCK: #endif if(obj->olocked) { pline("Klick!"); obj->olocked = !(obj->olocked); res = 1; } else res = 0; break; } return(res); } int doorlock(otmp,x,y) /* door was hit with spell effect otmp */ register struct obj *otmp; int x, y; { register struct rm *door = &levl[x][y]; boolean res = 1; if(door->typ == SDOOR) { if(otmp->otyp == WAN_OPENING #ifdef SPELLS || otmp->otyp == SPE_KNOCK #endif /* SPELLS /**/ ) { door->typ = DOOR; door->doormask = D_CLOSED | (door->doormask & D_TRAPPED); if(cansee(x,y)) pline("A section of the wall opens up!"); mnewsym(x,y); return(1); } else return(0); } #ifdef STRONGHOLD /* make sure it isn't an open drawbridge */ if (is_maze_lev && find_drawbridge(&x,&y)) { if(otmp->otyp == WAN_OPENING #ifdef SPELLS || otmp->otyp == SPE_KNOCK #endif /* SPELLS /**/ ) (void) open_drawbridge(x,y); else (void) close_drawbridge(x,y); return 1; } #endif switch(otmp->otyp) { case WAN_LOCKING: #ifdef SPELLS case SPE_WIZARD_LOCK: #endif if(obstructed(x,y)) return 0; if (cansee(x,y)) switch (door->doormask & ~D_TRAPPED) { case D_CLOSED: pline("The door locks!"); break; case D_ISOPEN: pline("The door swings shut, and locks!"); break; case D_BROKEN: pline("The broken door reassembles and locks!"); break; case D_NODOOR: pline("A cloud of dust springs up and assembles itself into a door!"); break; default: res = 0; } door->doormask = D_LOCKED | (door->doormask & D_TRAPPED); mnewsym(x,y); if(cansee(x,y)) prl(x,y); break; case WAN_OPENING: #ifdef SPELLS case SPE_KNOCK: #endif if(door->doormask & D_LOCKED) { door->doormask = D_CLOSED | (door->doormask & D_TRAPPED); if(cansee(x,y)) pline("The door unlocks!"); } else res = 0; break; case WAN_STRIKING: #ifdef SPELLS case SPE_FORCE_BOLT: #endif if(door->doormask & (D_LOCKED | D_CLOSED)) { if(door->doormask & D_TRAPPED) { if (MON_AT(x, y)) (void) mb_trapped(m_at(x,y)); else if (flags.verbose) if (cansee(x,y)) pline("KABOOM!! You see a door explode."); else if (flags.soundok) You("hear a distant explosion."); door->doormask = D_NODOOR; mnewsym(x,y); if (cansee(x,y)) prl(x,y); break; } door->doormask = D_BROKEN; if (flags.verbose) if (cansee(x,y)) pline("The door crashes open!"); else if (flags.soundok) You("hear a crashing sound."); mnewsym(x,y); if (cansee(x,y)) prl(x,y); } else res = 0; break; default: impossible("magic (%d) attempted on door.", otmp->otyp); } return res; } #ifdef STUPID_CPP /* otherwise these functions are macros in obj.h */ int Is_container(otmp) struct obj * otmp; { return(otmp->otyp >= ICE_BOX && otmp->otyp <= BAG_OF_TRICKS); } int Is_box(otmp) struct obj * otmp; { return(otmp->otyp == LARGE_BOX || otmp->otyp == CHEST); } int Is_mbag(otmp) struct obj * otmp; { return(otmp->otyp == BAG_OF_HOLDING || otmp->otyp == BAG_OF_TRICKS); } int is_sword(otmp) struct obj * otmp; { return(otmp->otyp >= SHORT_SWORD && otmp->otyp <= KATANA); } int bimanual(otmp) struct obj * otmp; { return(otmp->olet == WEAPON_SYM && objects[otmp->otyp].oc_bimanual); } #endif /* STUPID_CPP */ #endif /* OVLB */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.