home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / src / lock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  20.2 KB  |  836 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)lock.c    3.1    93/06/12    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6.  
  7. #define CONTAINER_BITS 0    /* box options not [yet?] implemented */
  8.  
  9. STATIC_PTR int NDECL(picklock);
  10. STATIC_PTR int NDECL(forcelock);
  11.  
  12. STATIC_VAR NEARDATA struct xlock_s {
  13.     int    door_or_box, picktyp;
  14.     struct rm  *door;
  15.     struct obj *box;
  16.     int chance, usedtime;
  17. } xlock;
  18.  
  19. #ifdef OVLB
  20.  
  21. static const char *NDECL(lock_action);
  22. static boolean FDECL(obstructed,(int,int));
  23. static void FDECL(chest_shatter_msg, (struct obj *));
  24.  
  25. boolean
  26. picking_lock(x, y)
  27.     int *x, *y;
  28. {
  29.     if(occupation != picklock) return 0;
  30.     else {
  31.         *x = u.ux + u.dx;
  32.         *y = u.uy + u.dy;
  33.         return 1;
  34.     }
  35. }
  36.  
  37. boolean
  38. picking_at(x, y)
  39. int x, y;
  40. {
  41.     return((boolean)((occupation == picklock) && 
  42.            xlock.door_or_box && (xlock.door == &levl[x][y]))); 
  43. }
  44.  
  45. /* produce an occupation string appropriate for the current activity */
  46. static const char *
  47. lock_action()
  48. {
  49.     /* "unlocking"+2 == "locking" */
  50.     static const char *actions[] = {
  51.         /* [0] */    "unlocking the door",
  52.         /* [1] */    "unlocking the chest",
  53.         /* [2] */    "unlocking the box",
  54.         /* [3] */    "picking the lock"
  55.     };
  56.  
  57.     /* if the target is currently unlocked, we're trying to lock it now */
  58.     if (xlock.door_or_box && !(xlock.door->doormask & D_LOCKED))
  59.         return actions[0]+2;    /* "locking the door" */
  60.     else if (!xlock.door_or_box && !xlock.box->olocked)
  61.         return xlock.box->otyp == CHEST ? actions[1]+2 : actions[2]+2;
  62.     /* otherwise we're trying to unlock it */
  63.     else if (xlock.picktyp == LOCK_PICK)
  64.         return actions[3];    /* "picking the lock" */
  65. #ifdef TOURIST
  66.     else if (xlock.picktyp == CREDIT_CARD)
  67.         return actions[3];    /* same as lock_pick */
  68. #endif
  69.     else if (xlock.door_or_box)
  70.         return actions[0];    /* "unlocking the door" */
  71.     else
  72.         return xlock.box->otyp == CHEST ? actions[1] : actions[2];
  73. }
  74.  
  75. STATIC_PTR
  76. int
  77. picklock()    /* try to open/close a lock */
  78. {
  79.  
  80.     if(!xlock.door_or_box) {    /* box */
  81.  
  82.         if((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy)) {
  83.         return((xlock.usedtime = 0));        /* you or it moved */
  84.         }
  85.     } else {        /* door */
  86.         if(xlock.door != &(levl[u.ux+u.dx][u.uy+u.dy])) {
  87.         return((xlock.usedtime = 0));        /* you moved */
  88.         }
  89.         switch (xlock.door->doormask) {
  90.         case D_NODOOR:
  91.             pline("This doorway has no door.");
  92.             return((xlock.usedtime = 0));
  93.         case D_ISOPEN:
  94.             pline("Picking the lock of an open door is pointless.");
  95.             return((xlock.usedtime = 0));
  96.         case D_BROKEN:
  97.             pline("This door is broken.");
  98.             return((xlock.usedtime = 0));
  99.         }
  100.     }
  101.  
  102.     if(xlock.usedtime++ >= 50
  103. #ifdef POLYSELF
  104.        || nohands(uasmon)
  105. #endif
  106.        ) {
  107.         You("give up your attempt at %s.", lock_action());
  108.         exercise(A_DEX, TRUE);    /* even if you don't succeed */
  109.         return((xlock.usedtime = 0));
  110.     }
  111.  
  112.     if(rn2(100) > xlock.chance) return(1);        /* still busy */
  113.  
  114.     You("succeed in %s.", lock_action());
  115.     if(xlock.door_or_box) {
  116.         if(xlock.door->doormask & D_TRAPPED) {
  117.             b_trapped("door", FINGER);
  118.             xlock.door->doormask = D_NODOOR;
  119.             unblock_point(u.ux+u.dx, u.uy+u.dy);
  120.             newsym(u.ux+u.dx, u.uy+u.dy);
  121.         } else if(xlock.door->doormask == D_LOCKED)
  122.         xlock.door->doormask = D_CLOSED;
  123.         else xlock.door->doormask = D_LOCKED;
  124.     } else {
  125.         xlock.box->olocked = !xlock.box->olocked;
  126.         if(xlock.box->otrapped)    
  127.         (void) chest_trap(xlock.box, FINGER, FALSE);
  128.     }
  129.     exercise(A_DEX, TRUE);
  130.     return((xlock.usedtime = 0));
  131. }
  132.  
  133. STATIC_PTR
  134. int
  135. forcelock()    /* try to force a locked chest */
  136. {
  137.  
  138.     register struct obj *otmp, *otmp2;
  139.  
  140.     if((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy))
  141.         return((xlock.usedtime = 0));        /* you or it moved */
  142.  
  143.     if(xlock.usedtime++ >= 50 || !uwep
  144. #ifdef POLYSELF
  145.        || nohands(uasmon)
  146. #endif
  147.        ) {
  148.         You("give up your attempt to force the lock.");
  149.         if(xlock.usedtime >= 50)        /* you made the effort */
  150.           exercise((xlock.picktyp) ? A_DEX : A_STR, TRUE);
  151.         return((xlock.usedtime = 0));
  152.     }
  153.  
  154.     if(xlock.picktyp) {    /* blade */
  155.  
  156.         if(rn2(1000-(int)uwep->spe) > (992-(int)uwep->oeroded*10) && 
  157.            !uwep->cursed && !obj_resists(uwep, 0, 99)) {
  158.         /* for a +0 weapon, probability that it survives an unsuccessful
  159.          * attempt to force the lock is (.992)^50 = .67
  160.          */
  161.         pline("%sour %s broke!",
  162.               (uwep->quan > 1L) ? "One of y" : "Y", xname(uwep));
  163.         useup(uwep);
  164.         You("give up your attempt to force the lock.");
  165.         exercise(A_DEX, TRUE);
  166.         return((xlock.usedtime = 0));
  167.         }
  168.     } else            /* blunt */
  169.         wake_nearby();    /* due to hammering on the container */
  170.  
  171.     if(rn2(100) > xlock.chance) return(1);        /* still busy */
  172.  
  173.     You("succeed in forcing the lock.");
  174.     xlock.box->olocked = 0;
  175.     xlock.box->obroken = 1;
  176.     if(!xlock.picktyp && !rn2(3)) {
  177.         struct monst *shkp;
  178.         boolean costly;
  179.         long loss = 0L;
  180.  
  181.         costly = (*u.ushops && costly_spot(u.ux, u.uy));
  182.         shkp = costly ? shop_keeper(*u.ushops) : 0;
  183.  
  184.         pline("In fact, you've totally destroyed %s.",
  185.           the(xname(xlock.box)));
  186.  
  187.         /* Put the contents on ground at the hero's feet. */
  188.         for (otmp = xlock.box->cobj; otmp; otmp = otmp2) {
  189.         otmp2 = otmp->nobj;
  190.         if(!rn2(3) || otmp->oclass == POTION_CLASS) {
  191.             chest_shatter_msg(otmp);
  192.             if (costly)
  193.                 loss += stolen_value(otmp, u.ux, u.uy,
  194.                          (boolean)shkp->mpeaceful, TRUE);
  195.             if (otmp->quan == 1L) {
  196.             obfree(otmp, (struct obj *) 0);
  197.             continue;
  198.             }
  199.             useup(otmp);
  200.         }
  201.         place_object(otmp,u.ux,u.uy);
  202.         otmp->nobj = fobj;
  203.         fobj = otmp;
  204.         stackobj(otmp);
  205.         }
  206.         xlock.box->cobj = (struct obj *) 0;    /* no contents */
  207.         if (costly)
  208.         loss += stolen_value(xlock.box, u.ux, u.uy,
  209.                          (boolean)shkp->mpeaceful, TRUE);
  210.         if(loss) You("owe %ld zorkmids for objects destroyed.", loss);
  211.         delobj(xlock.box);
  212.     }
  213.     exercise((xlock.picktyp) ? A_DEX : A_STR, TRUE);
  214.     return((xlock.usedtime = 0));
  215. }
  216.  
  217. #endif /* OVLB */
  218. #ifdef OVL0
  219.  
  220. void
  221. reset_pick() { xlock.usedtime = 0; }
  222.  
  223. #endif /* OVL0 */
  224. #ifdef OVLB
  225.  
  226. int
  227. pick_lock(pick) /* pick a lock with a given object */
  228.     register struct    obj    *pick;
  229. {
  230.     register int x, y, picktyp, c, ch;
  231.     register struct rm    *door;
  232.     register struct obj    *otmp;
  233.     char qbuf[QBUFSZ];
  234.  
  235. #ifdef GCC_WARN
  236.     ch = 0;        /* GCC myopia */
  237. #endif
  238.     picktyp = pick->otyp;
  239.     if (xlock.usedtime && picktyp == xlock.picktyp) {
  240.         const char *action = lock_action();
  241.  
  242.         You("resume your attempt at %s.", action);
  243.         set_occupation(picklock, action, 0);
  244.         return(1);
  245.     }
  246.  
  247. #ifdef POLYSELF
  248.     if(nohands(uasmon)) {
  249.         You("can't hold a %s - you have no hands!", xname(pick));
  250.         return(0);
  251.     }
  252. #endif
  253.     if((picktyp != LOCK_PICK &&
  254. #ifdef TOURIST
  255.         picktyp != CREDIT_CARD &&
  256. #endif
  257.         picktyp != SKELETON_KEY)) {
  258.         impossible("picking lock with object %d?", picktyp);
  259.         return(0);
  260.     }
  261.     if(!getdir(NULL)) return(0);
  262.  
  263.     x = u.ux + u.dx;
  264.     y = u.uy + u.dy;
  265.     if((x == u.ux) && (y == u.uy)) { /* pick the lock on a container */
  266.         c = 'n';            /* in case there are no boxes here */
  267.         for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
  268.         if (Is_box(otmp)) {
  269.             const char *verb;
  270.             boolean it = 0;
  271. #if CONTAINER_BITS
  272.             if (!otmp->oclosed) {    /* it's open */
  273.             pline("There is %s here.", doname(otmp));
  274.             continue;
  275.             }
  276.             if (!otmp->lknown) verb = "work";
  277.             else
  278. #endif
  279.              if (otmp->obroken) verb = "fix";
  280.             else if (!otmp->olocked) verb = "lock", it = 1;
  281.             else if (picktyp != LOCK_PICK) verb = "unlock", it = 1;
  282.             else verb = "pick";
  283.             Sprintf(qbuf, "There is %s here, %s %s?",
  284.                 doname(otmp), verb, it ? "it" : "its lock");
  285.  
  286.             c = ynq(qbuf);
  287.             if(c == 'q') return(0);
  288.             if(c == 'n') continue;
  289.  
  290. #if CONTAINER_BITS
  291.             otmp->lknown = 1;
  292. #endif
  293.             if (otmp->obroken) {
  294.             You("can't fix its broken lock with %s.", doname(pick));
  295.             return 0;
  296.             }
  297. #ifdef TOURIST
  298.             else if (picktyp == CREDIT_CARD && !otmp->olocked) {
  299.             /* credit cards are only good for unlocking */
  300.             You("can't do that with %s.", doname(pick));
  301.             return 0;
  302.             }
  303. #endif
  304.             switch(picktyp) {
  305. #ifdef TOURIST
  306.             case CREDIT_CARD:
  307.                 ch = ACURR(A_DEX)+(20*(pl_character[0] == 'R'));
  308.                 break;
  309. #endif
  310.             case LOCK_PICK:
  311.                 ch = 4*ACURR(A_DEX)+(25*(pl_character[0] == 'R'));
  312.                 break;
  313.             case SKELETON_KEY:
  314.                 ch = 75 + ACURR(A_DEX);
  315.                 break;
  316.             default:    ch = 0;
  317.             }
  318.             if(otmp->cursed) ch /= 2;
  319.  
  320.             xlock.door_or_box = 0;
  321.             xlock.picktyp = picktyp;
  322.             xlock.box = otmp;
  323.             break;
  324.         }
  325.         if(c != 'y')
  326.         return(0);        /* decided against all boxes */
  327.     } else {            /* pick the lock in a door */
  328.         struct monst *mtmp;
  329.  
  330.         door = &levl[x][y];
  331.         if ((mtmp = m_at(x, y)) && canseemon(mtmp)
  332.             && mtmp->m_ap_type != M_AP_FURNITURE
  333.             && mtmp->m_ap_type != M_AP_OBJECT) {
  334. #ifdef TOURIST
  335.         if (picktyp == CREDIT_CARD &&
  336.             (mtmp->isshk || mtmp->data == &mons[PM_ORACLE]))
  337.             verbalize("No checks, no credit, no problem.");
  338.         else
  339. #endif
  340.             pline("I don't think %s would appreciate that.", mon_nam(mtmp));
  341.         return(0);
  342.         }
  343.         if(!IS_DOOR(door->typ)) {
  344.         if (is_drawbridge_wall(x,y) >= 0)
  345.             You("%s no lock on the drawbridge.",
  346.                 Blind ? "feel" : "see");
  347.         else
  348.             You("%s no door there.",
  349.                 Blind ? "feel" : "see");
  350.         return(0);
  351.         }
  352.         switch (door->doormask) {
  353.         case D_NODOOR:
  354.             pline("This doorway has no door.");
  355.             return(0);
  356.         case D_ISOPEN:
  357.             pline("Picking the lock of an open door is pointless.");
  358.             return(0);
  359.         case D_BROKEN:
  360.             pline("This door is broken.");
  361.             return(0);
  362.         default:
  363. #ifdef TOURIST
  364.             /* credit cards are only good for unlocking */
  365.             if(picktyp == CREDIT_CARD && !(door->doormask & D_LOCKED)) {
  366.             You("can't lock a door with a credit card.");
  367.             return(0);
  368.             }
  369. #endif
  370.  
  371.             Sprintf(qbuf,"%sock it?",
  372.             (door->doormask & D_LOCKED) ? "Unl" : "L" );
  373.  
  374.             c = yn(qbuf);
  375.             if(c == 'n') return(0);
  376.  
  377.             switch(picktyp) {
  378. #ifdef TOURIST
  379.             case CREDIT_CARD:
  380.                 ch = 2*ACURR(A_DEX)+(20*(pl_character[0] == 'R'));
  381.                 break;
  382. #endif
  383.             case LOCK_PICK:
  384.                 ch = 3*ACURR(A_DEX)+(30*(pl_character[0] == 'R'));
  385.                 break;
  386.             case SKELETON_KEY:
  387.                 ch = 70 + ACURR(A_DEX);
  388.                 break;
  389.             default:    ch = 0;
  390.             }
  391.             xlock.door_or_box = 1;
  392.             xlock.door = door;
  393.         }
  394.     }
  395.     flags.move = 0;
  396.     xlock.chance = ch;
  397.     xlock.picktyp = picktyp;
  398.     xlock.usedtime = 0;
  399.     set_occupation(picklock, lock_action(), 0);
  400.     return(1);
  401. }
  402.  
  403. int
  404. doforce()        /* try to force a chest with your weapon */
  405. {
  406.     register struct obj *otmp;
  407.     register int c, picktyp;
  408.     char qbuf[QBUFSZ];
  409.  
  410.     if(!uwep ||    /* proper type test */
  411.        (uwep->oclass != WEAPON_CLASS && uwep->oclass != ROCK_CLASS &&
  412.                         uwep->otyp != PICK_AXE) ||
  413.        (uwep->otyp < BOOMERANG) ||
  414.        (uwep->otyp > AKLYS && uwep->oclass != ROCK_CLASS &&
  415.                         uwep->otyp != PICK_AXE)
  416. #ifdef KOPS
  417.        || uwep->otyp == RUBBER_HOSE
  418. #endif
  419.       ) {
  420.         You("can't force anything without a %sweapon.",
  421.           (uwep) ? "proper " : "");
  422.         return(0);
  423.     }
  424.  
  425.     picktyp = is_blade(uwep);
  426.     if(xlock.usedtime && xlock.box && picktyp == xlock.picktyp) {
  427.         You("resume your attempt to force the lock.");
  428.         set_occupation(forcelock, "forcing the lock", 0);
  429.         return(1);
  430.     }
  431.  
  432.     /* A lock is made only for the honest man, the thief will break it. */
  433.     xlock.box = (struct obj *)0;
  434.     for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere)
  435.         if(Is_box(otmp)) {
  436. #if CONTAINER_BITS
  437.         if (!otmp->oclosed) {    /* it's open */
  438.             pline("There is %s here.", doname(otmp));
  439.             continue;
  440.         }
  441.         if (otmp->obroken || (otmp->lknown && !otmp->olocked)) {
  442. #else
  443.         if (otmp->obroken || !otmp->olocked) {
  444. #endif
  445.             pline("There is %s here, but its lock is already %s.",
  446.               doname(otmp), otmp->obroken ? "broken" : "unlocked");
  447.             continue;
  448.         }
  449.         Sprintf(qbuf,"There is %s here, force its lock?", doname(otmp));
  450.  
  451.         c = ynq(qbuf);
  452.         if(c == 'q') return(0);
  453.         if(c == 'n') continue;
  454.  
  455. #if CONTAINER_BITS
  456.         if (!otmp->olocked) {    /* lock-status wasn't known */
  457.             pline("Well what'd'ya know?  It's already unlocked.");
  458.             otmp->lknown = 1;
  459.             return 0;
  460.         }
  461. #endif
  462.         if(picktyp)
  463.             You("force your %s into a crack and pry.", xname(uwep));
  464.         else
  465.             You("start bashing it with your %s.", xname(uwep));
  466.         xlock.box = otmp;
  467.         xlock.chance = objects[otmp->otyp].oc_wldam * 2;
  468.         xlock.picktyp = picktyp;
  469.         xlock.usedtime = 0;
  470.         break;
  471.         }
  472.  
  473.     if(xlock.box)    set_occupation(forcelock, "forcing the lock", 0);
  474.     else        You("decide not to force the issue.");
  475.     return(1);
  476. }
  477.  
  478. int
  479. doopen()        /* try to open a door */
  480. {
  481.     register int x, y;
  482.     register struct rm *door;
  483.     struct monst *mtmp;
  484.  
  485.     if (u.utrap && u.utraptype == TT_PIT) {
  486.         You("can't reach over the edge of the pit.");
  487.         return 0;
  488.     }
  489.  
  490.     if(!getdir(NULL)) return(0);
  491.  
  492.     x = u.ux + u.dx;
  493.     y = u.uy + u.dy;
  494.     if((x == u.ux) && (y == u.uy)) return(0);
  495.  
  496.     if ((mtmp = m_at(x,y))                &&
  497.         mtmp->m_ap_type == M_AP_FURNITURE    &&
  498.         (mtmp->mappearance == S_hcdoor ||
  499.             mtmp->mappearance == S_vcdoor)    &&
  500.         !Protection_from_shape_changers)     {
  501.  
  502.         stumble_onto_mimic(mtmp);
  503.         return(1);
  504.     }
  505.  
  506.     door = &levl[x][y];
  507.  
  508.     if(!IS_DOOR(door->typ)) {
  509.         if (is_db_wall(x,y)) {
  510.             pline("There is no obvious way to open the drawbridge.");
  511.             return(0);
  512.         }
  513.         You("%s no door there.",
  514.                 Blind ? "feel" : "see");
  515.         return(0);
  516.     }
  517.  
  518.     if(!(door->doormask & D_CLOSED)) {
  519.       switch(door->doormask) {
  520.          case D_BROKEN: pline("This door is broken."); break;
  521.          case D_NODOOR: pline("This doorway has no door."); break;
  522.          case D_ISOPEN: pline("This door is already open."); break;
  523.          default:        pline("This door is locked."); break;
  524.       }
  525.       return(0);
  526.     }
  527.  
  528. #ifdef POLYSELF
  529.     if(verysmall(uasmon)) {
  530.         pline("You're too small to pull the door open.");
  531.         return(0);
  532.     }
  533. #endif
  534.     /* door is known to be CLOSED */
  535.     if (rnl(20) < (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3) {
  536.         pline("The door opens.");
  537.         if(door->doormask & D_TRAPPED) {
  538.         b_trapped("door", FINGER);
  539.         door->doormask = D_NODOOR;
  540.         } else
  541.         door->doormask = D_ISOPEN;
  542.         if (Blind)
  543.         feel_location(x,y);    /* the hero knows she opened it  */
  544.         else
  545.         newsym(x,y);
  546.         unblock_point(x,y);        /* vision: new see through there */
  547.     } else {
  548.         exercise(A_STR, TRUE);
  549.         pline("The door resists!");
  550.     }
  551.  
  552.     return(1);
  553. }
  554.  
  555. static
  556. boolean
  557. obstructed(x,y)
  558. register int x, y;
  559. {
  560.     register struct monst *mtmp = m_at(x, y);
  561.  
  562.     if(mtmp && mtmp->m_ap_type != M_AP_FURNITURE) {
  563.         if (mtmp->m_ap_type == M_AP_OBJECT) goto objhere;
  564.         pline("%s stands in the way!", Blind ?
  565.             "Some creature" : Monnam(mtmp));
  566.         return(TRUE);
  567.     }
  568.     if (OBJ_AT(x, y)) {
  569. objhere:    pline("Something's in the way.");
  570.         return(TRUE);
  571.     }
  572.     return(FALSE);
  573. }
  574.  
  575. int
  576. doclose()        /* try to close a door */
  577. {
  578.     register int x, y;
  579.     register struct rm *door;
  580.     struct monst *mtmp;
  581.  
  582.     if (u.utrap && u.utraptype == TT_PIT) {
  583.         You("can't reach over the edge of the pit.");
  584.         return 0;
  585.     }
  586.  
  587.     if(!getdir(NULL)) return(0);
  588.  
  589.     x = u.ux + u.dx;
  590.     y = u.uy + u.dy;
  591.     if((x == u.ux) && (y == u.uy)) {
  592.         You("are in the way!");
  593.         return(1);
  594.     }
  595.  
  596.     if ((mtmp = m_at(x,y))                &&
  597.         mtmp->m_ap_type == M_AP_FURNITURE    && 
  598.         (mtmp->mappearance == S_hcdoor ||
  599.             mtmp->mappearance == S_vcdoor)    &&
  600.         !Protection_from_shape_changers)     {
  601.  
  602.         stumble_onto_mimic(mtmp);
  603.         return(1);
  604.     }
  605.  
  606.     door = &levl[x][y];
  607.  
  608.     if(!IS_DOOR(door->typ)) {
  609.         if (door->typ == DRAWBRIDGE_DOWN)
  610.             pline("There is no obvious way to close the drawbridge.");
  611.         else
  612.             You("%s no door there.",
  613.                 Blind ? "feel" : "see");
  614.         return(0);
  615.     }
  616.  
  617.     if(door->doormask == D_NODOOR) {
  618.         pline("This doorway has no door.");
  619.         return(0);
  620.     }
  621.  
  622.     if(obstructed(x, y)) return(0);
  623.  
  624.     if(door->doormask == D_BROKEN) {
  625.         pline("This door is broken.");
  626.         return(0);
  627.     }
  628.  
  629.     if(door->doormask & (D_CLOSED | D_LOCKED)) {
  630.         pline("This door is already closed.");
  631.         return(0);
  632.     }
  633.  
  634.     if(door->doormask == D_ISOPEN) {
  635. #ifdef POLYSELF
  636.         if(verysmall(uasmon)) {
  637.          pline("You're too small to push the door closed.");
  638.          return(0);
  639.          }
  640. #endif
  641.         if (rn2(25) < (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3) {
  642.         pline("The door closes.");
  643.         door->doormask = D_CLOSED;
  644.         if (Blind)
  645.             feel_location(x,y);    /* the hero knows she closed it */
  646.         else
  647.             newsym(x,y);
  648.         block_point(x,y);    /* vision:  no longer see there */
  649.         }
  650.         else {
  651.             exercise(A_STR, TRUE);
  652.             pline("The door resists!");
  653.         }
  654.     }
  655.  
  656.     return(1);
  657. }
  658.  
  659. boolean            /* box obj was hit with spell effect otmp */
  660. boxlock(obj, otmp)    /* returns true if something happened */
  661. register struct obj *obj, *otmp;    /* obj *is* a box */
  662. {
  663.     register boolean res = 0;
  664.  
  665.     switch(otmp->otyp) {
  666.     case WAN_LOCKING:
  667.     case SPE_WIZARD_LOCK:
  668.         if (!obj->olocked) {    /* lock it; fix if broken */
  669.         pline("Klunk!");
  670. #if CONTAINER_BITS
  671.         obj->lknown = 0;
  672.         obj->oclosed = 1;
  673. #endif
  674.         obj->olocked = 1;
  675.         obj->obroken = 0;
  676.         res = 1;
  677.         } /* else already closed and locked */
  678.         break;
  679.     case WAN_OPENING:
  680.     case SPE_KNOCK:
  681.         if (obj->olocked) {        /* unlock; couldn't be broken */
  682.         pline("Klick!");
  683. #if CONTAINER_BITS
  684.         obj->lknown = 0;
  685. #endif
  686.         obj->olocked = 0;
  687.         res = 1;
  688.         } else            /* silently fix if broken */
  689.         obj->obroken = 0;
  690. #if CONTAINER_BITS
  691.         obj->oclosed = 0;        /* now open, unconditionally */
  692. #endif
  693.         break;
  694.     }
  695.     return res;
  696. }
  697.  
  698. boolean            /* Door/secret door was hit with spell effect otmp */
  699. doorlock(otmp,x,y)    /* returns true if something happened */
  700. register struct obj *otmp;
  701. int x, y;
  702. {
  703.     register struct rm *door = &levl[x][y];
  704.     boolean res = 1;
  705.     const char *msg = NULL;
  706.  
  707.     if (door->typ == SDOOR) {
  708.         if (otmp->otyp == WAN_OPENING || otmp->otyp == SPE_KNOCK) {
  709.         door->typ = DOOR;
  710.         door->doormask = D_CLOSED | (door->doormask & D_TRAPPED);
  711.         if (cansee(x,y)) pline("A section of the wall opens up!");
  712.         newsym(x,y);
  713.         return(1);
  714.         } else
  715.         return(0);
  716.     }
  717.  
  718.     switch(otmp->otyp) {
  719.     case WAN_LOCKING:
  720.     case SPE_WIZARD_LOCK:
  721.         if (obstructed(x,y)) return 0;
  722.         /* Don't allow doors to close over traps.  This is for pits */
  723.         /* & trap doors, but is it ever OK for anything else? */
  724.         if (t_at(x,y)) {
  725.         /* maketrap() clears doormask, so it should be NODOOR */
  726.         pline(
  727.     "A cloud of dust springs up in the doorway, but quickly dissipates.");
  728.         return 0;
  729.         }
  730.  
  731.         switch (door->doormask & ~D_TRAPPED) {
  732.         case D_CLOSED:
  733.         msg = "The door locks!";
  734.         break;
  735.         case D_ISOPEN:
  736.         msg = "The door swings shut, and locks!";
  737.         break;
  738.         case D_BROKEN:
  739.         msg = "The broken door reassembles and locks!";
  740.         break;
  741.         case D_NODOOR:
  742.         msg =
  743.         "A cloud of dust springs up and assembles itself into a door!";
  744.         break;
  745.         default:
  746.         res = 0;
  747.         break;
  748.         }
  749.         block_point(x, y);
  750.         door->doormask = D_LOCKED | (door->doormask & D_TRAPPED);
  751.         newsym(x,y);
  752.         break;
  753.     case WAN_OPENING:
  754.     case SPE_KNOCK:
  755.         if (door->doormask & D_LOCKED) {
  756.         msg = "The door unlocks!";
  757.         door->doormask = D_CLOSED | (door->doormask & D_TRAPPED);
  758.         } else res = 0;
  759.         break;
  760.     case WAN_STRIKING:
  761.     case SPE_FORCE_BOLT:
  762.         if (door->doormask & (D_LOCKED | D_CLOSED)) {
  763.         if (door->doormask & D_TRAPPED) {
  764.             if (MON_AT(x, y))
  765.             (void) mb_trapped(m_at(x,y));
  766.             else if (flags.verbose) {
  767.             if (cansee(x,y))
  768.                 pline("KABOOM!!  You see a door explode.");
  769.             else if (flags.soundok)
  770.                 You("hear a distant explosion.");
  771.             }
  772.             door->doormask = D_NODOOR;
  773.             unblock_point(x,y);
  774.             newsym(x,y);
  775.             break;
  776.         }
  777.         door->doormask = D_BROKEN;
  778.         if (flags.verbose) {
  779.             if (cansee(x,y))
  780.             pline("The door crashes open!");
  781.             else if (flags.soundok)
  782.             You("hear a crashing sound.");
  783.         }
  784.         unblock_point(x,y);
  785.         newsym(x,y);
  786.         } else res = 0;
  787.         break;
  788.     default: impossible("magic (%d) attempted on door.", otmp->otyp);
  789.         break;
  790.     }
  791.     if (msg && cansee(x,y)) pline(msg);
  792.     return res;
  793. }
  794.  
  795. static void
  796. chest_shatter_msg(otmp)
  797. struct obj *otmp;
  798. {
  799.     const char *disposition, *article = (otmp->quan > 1L) ? "A" : "The";
  800.     char *thing;
  801.     long save_Blinded;
  802.  
  803.     if (otmp->oclass == POTION_CLASS) {
  804.         You("%s a flask shatter!", Blind ? "hear" : "see");
  805.         potionbreathe(otmp);
  806.         return;
  807.     }
  808.     /* We have functions for distant and singular names, but not one */
  809.     /* which does _both_... */
  810.     save_Blinded = Blinded;
  811.     Blinded = 1;
  812.     thing = singular(otmp, xname);
  813.     Blinded = save_Blinded;
  814.     switch (objects[otmp->otyp].oc_material) {
  815.     case PAPER:    disposition = "is torn to shreds";
  816.         break;
  817.     case WAX:    disposition = "is crushed";
  818.         break;
  819.     case VEGGY:    disposition = "is pulped";
  820.         break;
  821.     case FLESH:    disposition = "is mashed";
  822.         break;
  823.     case GLASS:    disposition = "shatters";
  824.         break;
  825.     case WOOD:    disposition = "splinters to fragments";
  826.         break;
  827.     default:    disposition = "is destroyed";
  828.         break;
  829.     }
  830.     pline("%s %s %s!", article, thing, disposition);
  831. }
  832.  
  833. #endif /* OVLB */
  834.  
  835. /*lock.c*/
  836.