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