Blindfold removal fix
[slashemextended.git] / src / lock.c
blob86239eab8078a3f426232ee337f9fc4516c07333
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. */
5 #include "hack.h"
7 STATIC_PTR int picklock(void);
8 STATIC_PTR int forcelock(void);
9 STATIC_PTR int forcedoor(void);
11 /* at most one of `door' and `box' should be non-null at any given time */
12 STATIC_VAR NEARDATA struct xlock_s {
13 struct rm *door;
14 struct obj *box;
15 int picktyp, chance, usedtime;
16 /* ALI - Artifact doors */
17 int key; /* Key being used (doors only) */
18 } xlock;
20 #ifdef OVLB
22 STATIC_DCL const char *lock_action(void);
23 STATIC_DCL boolean obstructed(int,int);
24 STATIC_DCL void chest_shatter_msg(struct obj *);
26 boolean
27 picking_lock(x, y)
28 int *x, *y;
30 if (occupation == picklock || occupation == forcedoor) {
31 *x = u.ux + u.dx;
32 *y = u.uy + u.dy;
33 return TRUE;
34 } else {
35 *x = *y = 0;
36 return FALSE;
40 boolean
41 picking_at(x, y)
42 int x, y;
44 return (boolean)(occupation == picklock && xlock.door == &levl[x][y]);
47 /* produce an occupation string appropriate for the current activity */
48 STATIC_OVL const char *
49 lock_action()
51 /* "unlocking"+2 == "locking" */
52 static const char *actions[] = {
53 /* [0] */ "unlocking the door",
54 /* [1] */ "unlocking the chest",
55 /* [2] */ "unlocking the box",
56 /* [3] */ "picking the lock"
59 /* if the target is currently unlocked, we're trying to lock it now */
60 if (xlock.door && !(xlock.door->doormask & D_LOCKED))
61 return actions[0]+2; /* "locking the door" */
62 else if (xlock.box && !xlock.box->olocked)
63 return (xlock.box->otyp == CHEST || xlock.box->otyp == NANO_CHEST || xlock.box->otyp == CHEST_OF_HOLDING) ? actions[1]+2 : actions[2]+2;
64 /* otherwise we're trying to unlock it */
65 else if (xlock.picktyp == LOCK_PICK)
66 return actions[3]; /* "picking the lock" */
67 else if (xlock.picktyp == HAIRCLIP)
68 return actions[3]; /* "picking the lock" */
69 else if (xlock.picktyp == CREDIT_CARD)
70 return actions[3]; /* same as lock_pick */
71 else if (xlock.picktyp == DATA_CHIP)
72 return actions[3]; /* same as lock_pick */
73 else if (xlock.door)
74 return actions[0]; /* "unlocking the door" */
75 else
76 return (xlock.box->otyp == CHEST || xlock.box->otyp == NANO_CHEST || xlock.box->otyp == CHEST_OF_HOLDING) ? actions[1] : actions[2];
79 STATIC_PTR
80 int
81 picklock() /* try to open/close a lock */
83 register struct obj *trophy;
85 if (xlock.box) {
86 if((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy)) {
87 return((xlock.usedtime = 0)); /* you or it moved */
89 } else { /* door */
90 if(xlock.door != &(levl[u.ux+u.dx][u.uy+u.dy])) {
91 return((xlock.usedtime = 0)); /* you moved */
93 switch (xlock.door->doormask) {
94 case D_NODOOR:
95 pline("This doorway has no door.");
96 return((xlock.usedtime = 0));
97 case D_ISOPEN:
98 You("cannot lock an open door.");
99 return((xlock.usedtime = 0));
100 case D_BROKEN:
101 pline("This door is broken.");
102 return((xlock.usedtime = 0));
106 if (xlock.usedtime++ >= 50 ) {
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));
112 if(rn2(100) >= xlock.chance) return(1); /* still busy */
113 if(isfriday && (rn2(100) >= xlock.chance)) return(1); /* still busy */
115 You("succeed in %s.", lock_action());
116 if (xlock.door) {
117 if(xlock.door->doormask & D_TRAPPED) {
118 b_trapped("door", FINGER);
119 xlock.door->doormask = D_NODOOR;
120 unblock_point(u.ux+u.dx, u.uy+u.dy);
121 if (*in_rooms(u.ux+u.dx, u.uy+u.dy, SHOPBASE))
122 add_damage(u.ux+u.dx, u.uy+u.dy, 0L);
123 newsym(u.ux+u.dx, u.uy+u.dy);
124 } else if(xlock.door->doormask == D_LOCKED) {
125 xlock.door->doormask = D_CLOSED;
126 u.cnd_unlockamount++;
127 } else xlock.door->doormask = D_LOCKED;
129 /* better handling for special doors in Vlad's: only give the rewards if you actually unlock them --Amy */
130 if (artifact_door(u.ux+u.dx, u.uy+u.dy) && !strcmp(dungeons[u.uz.dnum].dname, "Vlad's Tower")) {
132 switch (artifact_door(u.ux+u.dx, u.uy+u.dy)) {
134 case ART_MASTER_KEY_OF_THIEVERY:
135 if (!u.keythief) {
136 u.keythief = TRUE;
137 pline("Congratulations, a reward for picking this lock was dropped at your %s!", makeplural(body_part(FOOT)));
138 trophy = mksobj(STONE_OF_MAGIC_RESISTANCE, TRUE, FALSE, FALSE);
139 if (trophy) {
140 dropy(trophy);
143 break;
144 case ART_NOCTURNAL_KEY:
145 if (!u.keynocturn) {
146 u.keynocturn = TRUE;
147 pline("Congratulations, a reward for picking this lock was dropped at your %s!", makeplural(body_part(FOOT)));
148 trophy = mksobj(SPE_PASSWALL, TRUE, FALSE, FALSE);
149 if (trophy) {
150 dropy(trophy);
153 break;
154 case ART_KEY_OF_ACCESS:
155 if (!u.keyaccess) {
156 u.keyaccess = TRUE;
157 pline("Congratulations, a reward for picking this lock was dropped at your %s!", makeplural(body_part(FOOT)));
158 trophy = mksobj(SPE_GODMODE, TRUE, FALSE, FALSE);
159 if (trophy) {
160 dropy(trophy);
163 break;
164 case ART_GAUNTLET_KEY:
165 if (!u.keygauntlet) {
166 u.keygauntlet = TRUE;
167 pline("Congratulations, a reward for picking this lock was dropped at your %s!", makeplural(body_part(FOOT)));
168 trophy = mksobj(SCR_WISHING, TRUE, FALSE, FALSE);
169 if (trophy) {
170 dropy(trophy);
173 break;
174 default:
175 break;
181 } else {
182 xlock.box->olocked = !xlock.box->olocked;
183 if (!xlock.box->olocked) u.cnd_unlockamount++;
184 if(xlock.box->otrapped) {
185 if (Role_if(PM_CYBERNINJA) && rn2(5)) You("also disarm the trap you found on it.");
186 else (void) chest_trap(xlock.box, FINGER, FALSE);
189 exercise(A_DEX, TRUE);
190 return((xlock.usedtime = 0));
193 STATIC_PTR
195 forcelock() /* try to force a locked chest */
198 register struct obj *otmp;
200 if((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy))
201 return((xlock.usedtime = 0)); /* you or it moved */
203 if (xlock.usedtime++ >= 50 || !uwep ) {
204 You("give up your attempt to force the lock.");
205 if(xlock.usedtime >= 50) /* you made the effort */
206 exercise((xlock.picktyp) ? A_DEX : A_STR, TRUE);
207 return((xlock.usedtime = 0));
210 if(xlock.picktyp == 1) { /* blade */
212 if(rn2(1000 - (int)uwep->spe) > ((isfriday ? 980 : 992) - (greatest_erosionX(uwep) * 10)) &&
213 !uwep->cursed && !obj_resists(uwep, 0, 99)) {
214 /* for a +0 weapon, probability that it survives an unsuccessful
215 * attempt to force the lock is (.992)^50 = .67 or on a friday the 13th (.980)^50 = .36
217 pline("%sour %s broke!",
218 (uwep->quan > 1L) ? "One of y" : "Y", xname(uwep));
219 useup(uwep);
220 You("give up your attempt to force the lock.");
221 exercise(A_DEX, TRUE);
222 return((xlock.usedtime = 0));
224 } else if(xlock.picktyp == 0) /* blunt */
225 wake_nearby(); /* due to hammering on the container */
227 if(rn2(100) >= xlock.chance) return(1); /* still busy */
228 if(isfriday && (rn2(100) >= xlock.chance)) return(1); /* still busy */
230 You("succeed in forcing the lock.");
232 if (uwep && is_lightsaber(uwep) && (uwep->lamplit || Role_if(PM_SHADOW_JEDI))) {
233 use_skill(P_WEDI, 1);
235 if (uwep && uwep->oartifact == ART_DIGSRU) {
236 use_skill(P_WEDI, 1);
239 xlock.box->olocked = 0;
240 xlock.box->obroken = 1;
241 if((xlock.picktyp == 0 && !rn2(isfriday ? 2 : 3)) || (xlock.picktyp == 2 && !rn2(isfriday ? 3 : 5))) {
242 struct monst *shkp;
243 boolean costly;
244 long loss = 0L;
246 costly = (*u.ushops && costly_spot(u.ux, u.uy));
247 shkp = costly ? shop_keeper(*u.ushops) : 0;
249 pline("In fact, you've totally destroyed %s.",
250 the(xname(xlock.box)));
252 /* Put the contents on ground at the hero's feet. */
253 while ((otmp = xlock.box->cobj) != 0) {
254 obj_extract_self(otmp);
255 /* [ALI] Allowing containers to be destroyed is complicated
256 * (because they might contain indestructible objects).
257 * Since this is very unlikely to occur in practice simply
258 * avoid the possibility.
260 if (!evades_destruction(otmp) && !Has_contents(otmp) &&
261 (!rn2(isfriday ? 2 : 3) || otmp->oclass == POTION_CLASS)) {
262 chest_shatter_msg(otmp);
263 if (costly)
264 loss += stolen_value(otmp, u.ux, u.uy,
265 (boolean)shkp->mpeaceful, TRUE,
266 TRUE);
267 if (otmp->quan == 1L) {
268 obfree(otmp, (struct obj *) 0);
269 continue;
271 useup(otmp);
273 if ( (xlock.box->otyp == ICE_BOX || xlock.box->otyp == DISPERSION_BOX || xlock.box->otyp == ICE_BOX_OF_HOLDING || xlock.box->otyp == ICE_BOX_OF_WATERPROOFING || xlock.box->otyp == ICE_BOX_OF_DIGESTION) && otmp->otyp == CORPSE) {
274 otmp->age = monstermoves - otmp->age; /* actual age */
275 otmp->icedobject = TRUE;
276 start_corpse_timeout(otmp);
278 place_object(otmp, u.ux, u.uy);
279 stackobj(otmp);
282 if (costly)
283 loss += stolen_value(xlock.box, u.ux, u.uy,
284 (boolean)shkp->mpeaceful, TRUE, TRUE);
285 if(loss) You("owe %ld %s for objects destroyed.", loss, currency(loss));
286 delobj(xlock.box);
288 exercise((xlock.picktyp) ? A_DEX : A_STR, TRUE);
289 return((xlock.usedtime = 0));
292 STATIC_PTR
294 forcedoor() /* try to break/pry open a door */
297 if(xlock.door != &(levl[u.ux+u.dx][u.uy+u.dy])) {
298 return((xlock.usedtime = 0)); /* you moved */
300 switch (xlock.door->doormask) {
301 case D_NODOOR:
302 pline("This doorway has no door.");
303 return((xlock.usedtime = 0));
304 case D_ISOPEN:
305 You("cannot lock an open door.");
306 return((xlock.usedtime = 0));
307 case D_BROKEN:
308 pline("This door is broken.");
309 return((xlock.usedtime = 0));
312 if (xlock.usedtime++ >= 50 ) {
313 You("give up your attempt at %s the door.",
314 (xlock.picktyp == 2 ? "melting" : xlock.picktyp == 1 ?
315 "prying open" : "breaking down"));
316 exercise(A_STR, TRUE); /* even if you don't succeed */
317 return((xlock.usedtime = 0));
320 if(rn2(100) > xlock.chance) return(1); /* still busy */
321 if(isfriday && (rn2(100) > xlock.chance)) return(1); /* still busy */
323 You("succeed in %s the door.",
324 (xlock.picktyp == 2 ? "melting" : xlock.picktyp == 1 ?
325 "prying open" : "breaking down"));
327 if(xlock.door->doormask & D_TRAPPED) {
328 b_trapped("door", 0);
329 xlock.door->doormask = D_NODOOR;
330 } else if (xlock.picktyp == 1)
331 xlock.door->doormask = D_BROKEN;
332 else xlock.door->doormask = D_NODOOR;
333 unblock_point(u.ux+u.dx, u.uy+u.dy);
334 if (*in_rooms(u.ux+u.dx, u.uy+u.dy, SHOPBASE)) {
335 add_damage(u.ux+u.dx, u.uy+u.dy, 400L);
336 pay_for_damage("break", FALSE);
338 if (in_town(u.ux+u.dx, u.uy+u.dy)) {
339 struct monst *mtmp;
340 for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
341 if (DEADMONSTER(mtmp)) continue;
342 if((mtmp->data == &mons[PM_WATCHMAN] ||
343 mtmp->data == &mons[PM_WATCH_CAPTAIN]) &&
344 couldsee(mtmp->mx, mtmp->my) &&
345 mtmp->mpeaceful) {
346 if (canspotmon(mtmp))
347 pline("%s yells:", Amonnam(mtmp));
348 else
349 You_hear("someone yell:");
350 verbalize("Halt, thief! You're under arrest!");
351 (void) angry_guards(FALSE);
352 break;
357 if (Blind)
358 feel_location(u.ux+u.dx, u.uy+u.dy); /* we know we broke it */
359 else
360 newsym(u.ux+u.dx, u.uy+u.dy);
362 exercise(A_STR, TRUE);
363 return((xlock.usedtime = 0));
366 #endif /* OVLB */
367 #ifdef OVL0
369 void
370 reset_pick()
372 xlock.usedtime = xlock.chance = xlock.picktyp = 0;
373 xlock.door = 0;
374 xlock.box = 0;
377 #endif /* OVL0 */
378 #ifdef OVLB
381 pick_lock(pickp) /* pick a lock with a given object */
382 struct obj **pickp;
384 int picktyp, c, ch;
385 coord cc;
386 int key;
387 struct rm *door;
388 struct obj *otmp;
389 struct obj *pick = *pickp;
390 char qbuf[QBUFSZ];
391 boolean bypassartilock = FALSE;
393 picktyp = pick->otyp;
395 /* check whether we're resuming an interrupted previous attempt */
396 if (xlock.usedtime && picktyp == xlock.picktyp) {
397 static char no_longer[] = "Unfortunately, you can no longer %s %s.";
399 if (nohands(youmonst.data) && !Race_if(PM_TRANSFORMER)) {
400 const char *what = (picktyp == LOCK_PICK) ? "pick" : (picktyp == HAIRCLIP) ? "hairclip" : "key";
401 if (picktyp == CREDIT_CARD) what = "card";
402 if (picktyp == DATA_CHIP) what = "chip";
403 pline(no_longer, "hold the", what);
404 reset_pick();
405 return 0;
406 } else if (xlock.box && !can_reach_floor()) {
407 pline(no_longer, "reach the", "lock");
408 reset_pick();
409 return 0;
410 } else if (!xlock.door || xlock.key == pick->oartifact) {
411 const char *action = lock_action();
412 You("resume your attempt at %s.", action);
413 set_occupation(picklock, action, 0);
414 if (AutoDestruct || u.uprops[AUTO_DESTRUCT].extrinsic || (uarmf && uarmf->oartifact == ART_KHOR_S_REQUIRED_IDEA) || have_autodestructstone() || (uchain && uchain->oartifact == ART_SIYID) ) picklock();
415 return(1);
419 if(nohands(youmonst.data) && !Race_if(PM_TRANSFORMER)) {
420 You_cant("hold %s -- you have no hands!", doname(pick));
421 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
422 if (yn("Attempt it anyway?") == 'y') {
423 if (rn2(3) && !polyskillchance()) {
424 playerbleed(rnd(2 + (level_difficulty() * 10)));
425 pline("Great. Now your %s is squirting everywhere.", body_part(BLOOD));
426 if (!rn2(20)) badeffect();
427 return 1;
431 else return(0);
434 if((picktyp != LOCK_PICK &&
435 picktyp != HAIRCLIP &&
436 picktyp != CREDIT_CARD &&
437 picktyp != DATA_CHIP &&
438 picktyp != SECRET_KEY &&
439 picktyp != CONTROVERSY_CODE &&
440 picktyp != SKELETON_KEY)) {
441 impossible("picking lock with object %d?", picktyp);
442 return(0);
444 ch = 0; /* lint suppression */
446 if(!get_adjacent_loc((char *)0, "Invalid location!", u.ux, u.uy, &cc)) return 0;
447 if (cc.x == u.ux && cc.y == u.uy) { /* pick lock on a container */
448 const char *verb;
449 boolean it;
450 int count;
452 if (u.dz < 0) {
453 There("isn't any sort of lock up %s.",
454 Levitation ? "here" : "there");
455 return 0;
456 } else if (is_lava(u.ux, u.uy)) {
457 pline("Doing that would probably melt your %s.",
458 xname(pick));
459 return 0;
460 } else if (is_waterypool(u.ux, u.uy) && !is_crystalwater(u.ux, u.uy) && !Underwater) {
461 pline_The("water has no lock.");
462 return 0;
465 count = 0;
466 c = 'n'; /* in case there are no boxes here */
467 for(otmp = level.objects[cc.x][cc.y]; otmp; otmp = otmp->nexthere)
468 if (Is_box(otmp)) {
469 ++count;
470 if (!can_reach_floor()) {
471 You_cant("reach %s from up here.", the(xname(otmp)));
472 return 0;
474 it = 0;
475 if (otmp->obroken) verb = "fix";
476 else if (!otmp->olocked) verb = "lock", it = 1;
477 else if (picktyp != LOCK_PICK && picktyp != HAIRCLIP) verb = "unlock", it = 1;
478 else verb = "pick";
479 sprintf(qbuf, "There is %s here, %s %s?",
480 safe_qbuf("", sizeof("There is here, unlock its lock?"),
481 doname(otmp), an(simple_typename(otmp->otyp)), "a box"),
482 verb, it ? "it" : "its lock");
484 c = ynq(qbuf);
485 if(c == 'q') return(0);
486 if(c == 'n') continue;
488 if (pick->oartifact && !(pick->oartifact == ART_UNBRIT_SOV) && (pick->obrittle || pick->obrittle2) ) {
489 Your("key doesn't seem to fit.");
490 return 0;
493 if (otmp->obroken) {
494 You_cant("fix its broken lock with %s.", doname(pick));
495 return 0;
497 else if (picktyp == CREDIT_CARD && !otmp->olocked) {
498 /* credit cards are only good for unlocking */
499 You_cant("do that with %s.", doname(pick));
500 return 0;
502 else if (picktyp == DATA_CHIP && !otmp->olocked) {
503 You_cant("do that with %s.", doname(pick));
504 return 0;
506 switch(picktyp) {
507 case CREDIT_CARD:
508 if(!rn2(isfriday ? 10 : 20) && (!pick->blessed || !rn2(3)) && !pick->oartifact) {
509 Your("credit card breaks in half!");
510 useup(pick);
511 *pickp = (struct obj *)0;
512 return(1);
514 if(!rn2(isfriday ? 10 : 20) && (!pick->blessed || !rn2(3)) && pick->oartifact) {
515 Your("credit card becomes dull and is no longer capable of picking locks!");
516 pick->obrittle = pick->obrittle2 = 3;
517 return(1);
519 ch = ACURR(A_DEX) + 20*Role_if(PM_ROGUE) + 40*Role_if(PM_LOCKSMITH) + 20*Role_if(PM_CYBERNINJA);
520 break;
521 case DATA_CHIP:
522 if(!rn2(isfriday ? 10 : 20) && (!pick->blessed || !rn2(3)) && !pick->oartifact) {
523 Your("data chip breaks in half!");
524 useup(pick);
525 *pickp = (struct obj *)0;
526 return(1);
528 if(!rn2(isfriday ? 10 : 20) && (!pick->blessed || !rn2(3)) && pick->oartifact) {
529 Your("data chip becomes dull and is no longer capable of picking locks!");
530 pick->obrittle = pick->obrittle2 = 3;
531 return(1);
533 ch = ACURR(A_DEX) + 20*Role_if(PM_ROGUE) + 40*Role_if(PM_LOCKSMITH) + 20*Role_if(PM_CYBERNINJA);
534 break;
535 case LOCK_PICK:
536 case HAIRCLIP:
537 if(!rn2(isfriday ? 20 : Role_if(PM_LOCKSMITH) ? 60: (Role_if(PM_ROGUE) || Role_if(PM_CYBERNINJA)) ? 40 : 30) &&
538 (!pick->blessed || !rn2(3)) && !pick->oartifact) {
539 You("break your pick!");
540 useup(pick);
541 *pickp = (struct obj *)0;
542 return(1);
544 if(!rn2(isfriday ? 20 : Role_if(PM_LOCKSMITH) ? 60: (Role_if(PM_ROGUE) || Role_if(PM_CYBERNINJA)) ? 40 : 30) &&
545 (!pick->blessed || !rn2(3)) && pick->oartifact) {
546 if (pick->oartifact == ART_DITHERS_WUMA) {
547 FemaleTrapJette += 50000;
548 pline_The("power of feminism compels you.");
549 } else {
550 Your("pick becomes brittle and is no longer capable of picking locks!");
551 pick->obrittle = pick->obrittle2 = 3;
553 return(1);
555 ch = 4*ACURR(A_DEX) + 25*Role_if(PM_ROGUE) + 50*Role_if(PM_LOCKSMITH) + 30*Role_if(PM_CYBERNINJA);
556 break;
557 case SKELETON_KEY:
558 case CONTROVERSY_CODE:
559 case SECRET_KEY:
560 if(!rn2(isfriday ? 7 : 15) && !(pick->oartifact == ART_VANULLA_SCORE) && (!pick->blessed || !rn2(3)) && !pick->oartifact) {
561 Your("key didn't quite fit the lock and snapped!");
562 useup(pick);
563 *pickp = (struct obj *)0;
564 return(1);
566 if(!rn2(isfriday ? 7 : 15) && !(pick->oartifact == ART_VANULLA_SCORE) && (!pick->blessed || !rn2(3)) && pick->oartifact) {
567 Your("key becomes brittle and is no longer capable of picking locks!");
568 if (pick->oartifact == ART_UNBRIT_SOV) {
569 u.badfcursed += 10000;
570 if (pick->obrittle || pick->obrittle2) u.badfdoomed += 10000;
572 pick->obrittle = pick->obrittle2 = 3;
573 return(1);
575 ch = 75 + ACURR(A_DEX);
576 break;
577 default: ch = 0;
579 if(otmp->cursed) ch /= 2;
581 xlock.picktyp = picktyp;
582 xlock.box = otmp;
583 xlock.door = 0;
584 break;
586 if (c != 'y') {
587 if (!count)
588 There("doesn't seem to be any sort of lock here.");
589 return(0); /* decided against all boxes */
591 } else { /* pick the lock in a door */
592 struct monst *mtmp;
594 if (u.utrap && u.utraptype == TT_PIT) {
595 You_cant("reach over the edge of the pit.");
596 return(0);
599 door = &levl[cc.x][cc.y];
600 if ((mtmp = m_at(cc.x, cc.y)) && canseemon(mtmp)
601 && mtmp->m_ap_type != M_AP_FURNITURE
602 && mtmp->m_ap_type != M_AP_OBJECT) {
603 if (picktyp == CREDIT_CARD &&
604 (mtmp->isshk || mtmp->data == &mons[PM_ORACLE]))
605 verbalize("No checks, no credit, no problem.");
606 else
607 pline("I don't think %s would appreciate that.", mon_nam(mtmp));
608 return(0);
610 if(!IS_DOOR(door->typ)) {
611 if (is_drawbridge_wall(cc.x,cc.y) >= 0)
612 You("%s no lock on the drawbridge.",
613 Blind ? "feel" : "see");
614 else
615 You("%s no door there.",
616 Blind ? "feel" : "see");
617 return(0);
619 switch (door->doormask) {
620 case D_NODOOR:
621 pline("This doorway has no door.");
622 return(0);
623 case D_ISOPEN:
624 You("cannot lock an open door.");
625 return(0);
626 case D_BROKEN:
627 pline("This door is broken.");
628 return(0);
629 default:
630 /* credit cards are only good for unlocking */
631 if(picktyp == CREDIT_CARD && !(door->doormask & D_LOCKED)) {
632 You_cant("lock a door with a credit card.");
633 return(0);
635 if(picktyp == DATA_CHIP && !(door->doormask & D_LOCKED)) {
636 You_cant("lock a door with a data chip.");
637 return(0);
639 /* ALI - Artifact doors */
640 key = artifact_door(cc.x, cc.y);
642 sprintf(qbuf,"%sock it?",
643 (door->doormask & D_LOCKED) ? "Unl" : "L" );
645 c = yn(qbuf);
646 if(c == 'n') return(0);
648 switch(picktyp) {
649 case CREDIT_CARD:
650 if(!rn2(isfriday ? 10 : Role_if(PM_LOCKSMITH) ? 40 : (Role_if(PM_TOURIST) || Role_if(PM_CYBERNINJA)) ? 30 : 20) &&
651 (!pick->blessed || !rn2(3)) && !pick->oartifact) {
652 You("break your card off in the door!");
653 useup(pick);
654 *pickp = (struct obj *)0;
655 return(0);
657 if(!rn2(isfriday ? 10 : Role_if(PM_LOCKSMITH) ? 40 : (Role_if(PM_TOURIST) || Role_if(PM_CYBERNINJA)) ? 30 : 20) &&
658 (!pick->blessed || !rn2(3)) && pick->oartifact) {
659 Your("credit card becomes dull and is no longer capable of picking locks!");
660 pick->obrittle = pick->obrittle2 = 3;
661 return(0);
663 ch = 2*ACURR(A_DEX) + 20*Role_if(PM_ROGUE) + 40*Role_if(PM_LOCKSMITH) + 20*Role_if(PM_CYBERNINJA);
664 break;
665 case DATA_CHIP:
666 if(!rn2(isfriday ? 10 : Role_if(PM_LOCKSMITH) ? 40 : (Role_if(PM_TOURIST) || Role_if(PM_CYBERNINJA)) ? 30 : 20) &&
667 (!pick->blessed || !rn2(3)) && !pick->oartifact) {
668 You("break your chip off in the door!");
669 useup(pick);
670 *pickp = (struct obj *)0;
671 return(0);
673 if(!rn2(isfriday ? 10 : Role_if(PM_LOCKSMITH) ? 40 : (Role_if(PM_TOURIST) || Role_if(PM_CYBERNINJA)) ? 30 : 20) &&
674 (!pick->blessed || !rn2(3)) && pick->oartifact) {
675 Your("data chip becomes dull and is no longer capable of picking locks!");
676 pick->obrittle = pick->obrittle2 = 3;
677 return(0);
679 ch = 2*ACURR(A_DEX) + 20*Role_if(PM_ROGUE) + 40*Role_if(PM_LOCKSMITH) + 20*Role_if(PM_CYBERNINJA);
680 break;
681 case LOCK_PICK:
682 case HAIRCLIP:
683 if(!rn2(isfriday ? 20 : Role_if(PM_LOCKSMITH) ? 60 : (Role_if(PM_ROGUE) || Role_if(PM_CYBERNINJA)) ? 40 : 30) &&
684 (!pick->blessed || !rn2(3)) && !pick->oartifact) {
685 You("break your pick!");
686 useup(pick);
687 *pickp = (struct obj *)0;
688 return(0);
690 if(!rn2(isfriday ? 20 : Role_if(PM_LOCKSMITH) ? 60 : (Role_if(PM_ROGUE) || Role_if(PM_CYBERNINJA)) ? 40 : 30) &&
691 (!pick->blessed || !rn2(3)) && pick->oartifact) {
692 if (pick->oartifact == ART_DITHERS_WUMA) {
693 FemaleTrapJette += 50000;
694 pline_The("power of feminism compels you.");
695 } else {
696 Your("pick becomes brittle and is no longer capable of picking locks!");
697 pick->obrittle = pick->obrittle2 = 3;
699 return(0);
701 ch = 3*ACURR(A_DEX) + 30*Role_if(PM_ROGUE) + 60*Role_if(PM_LOCKSMITH) + 30*Role_if(PM_CYBERNINJA);
702 break;
703 case SKELETON_KEY:
704 case CONTROVERSY_CODE:
705 case SECRET_KEY:
706 if(!rn2(isfriday ? 7 : Role_if(PM_LOCKSMITH) ? 40 : Role_if(PM_CYBERNINJA) ? 30 : 15) && !(pick->oartifact == ART_VANULLA_SCORE) && (!pick->blessed || !rn2(3)) && !pick->oartifact) {
707 Your("key wasn't designed for this door and broke!");
708 useup(pick);
709 *pickp = (struct obj *)0;
710 return(0);
712 if(!rn2(isfriday ? 7 : Role_if(PM_LOCKSMITH) ? 40 : Role_if(PM_CYBERNINJA) ? 30 : 15) && !(pick->oartifact == ART_VANULLA_SCORE) && (!pick->blessed || !rn2(3)) && pick->oartifact) {
713 Your("key becomes brittle and is no longer capable of picking locks!");
714 if (pick->oartifact == ART_UNBRIT_SOV) {
715 u.badfcursed += 10000;
716 if (pick->obrittle || pick->obrittle2) u.badfdoomed += 10000;
718 pick->obrittle = pick->obrittle2 = 3;
719 return(0);
721 ch = 70 + ACURR(A_DEX) + 10*Role_if(PM_LOCKSMITH) + 5*Role_if(PM_CYBERNINJA);
722 break;
723 default: ch = 0;
725 xlock.door = door;
726 xlock.box = 0;
728 /* ALI - Artifact doors */
729 xlock.key = pick->oartifact;
731 /* these variable names... who the hell would expect "key" to be the one that's required and "xlock.key"
732 * to somehow be set to "pick->oartifact", i.e. be the same that you're trying to use??? --Amy */
733 bypassartilock = FALSE;
734 if (key && key == ART_GAUNTLET_KEY && pick->oartifact == ART_GAUNTLET_ABBREVIATION && !In_V_tower(&u.uz)) {
735 bypassartilock = TRUE;
737 if (key && key == ART_KEY_OF_LAW && pick->oartifact == ART_GETIN_ON_VLADS) bypassartilock = TRUE;
738 if (key && key == ART_KEY_OF_NEUTRALITY && pick->oartifact == ART_GETIN_ON_VLADS) bypassartilock = TRUE;
739 if (key && key == ART_KEY_OF_CHAOS && pick->oartifact == ART_GETIN_ON_VLADS) bypassartilock = TRUE;
741 if (key && (xlock.key != key) && !bypassartilock) {
742 if (picktyp == SKELETON_KEY || picktyp == CONTROVERSY_CODE || picktyp == SECRET_KEY) {
743 Your("key doesn't seem to fit.");
744 return(0);
746 else ch = -1; /* -1 == 0% chance */
749 /* artifact keys shouldn't be overpowered --Amy */
751 if (!key && pick->oartifact && !(pick->oartifact == ART_UNBRIT_SOV) && (pick->obrittle || pick->obrittle2) && !issoviet) {
752 Your("key doesn't seem to fit.");
753 return(0);
756 /* "Artifact key/locking tools work properly again. There is next to no reason for this, especially considering keys/lock picks/etc can break in this game." In Soviet Russia, people will tell you that there's no reason for something, and then proceed to tell you the EXACT reason for the same thing but pretend that it's the reason why the "something" shouldn't be! Can you believe that? To clarify: keys being able to break is the exact reason why I'm not allowing artifact keys to unlock everything, cause otherwise that would render the point of breakable keys completely moot. Once you got your artifact key, it just doesn't matter anymore since you're not going to use normal keys. And what *I* want is that it freaking *MATTERS* if you get lucky finding enough keys. The threat of running out should be present for the entire game, not just until you beat the way-too-easy neutral quest! */
760 flags.move = 0;
761 xlock.chance = ch;
762 xlock.picktyp = picktyp;
763 xlock.usedtime = 0;
764 set_occupation(picklock, lock_action(), 0);
765 if (AutoDestruct || u.uprops[AUTO_DESTRUCT].extrinsic || (uarmf && uarmf->oartifact == ART_KHOR_S_REQUIRED_IDEA) || have_autodestructstone() || (uchain && uchain->oartifact == ART_SIYID) ) picklock();
766 return(1);
770 doforce() /* try to force a chest with your weapon */
773 if (MenuIsBugged) {
774 pline("The force command is currently unavailable!");
775 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
776 return 0;
779 register struct obj *otmp;
780 register int x, y, c, picktyp;
781 struct rm *door;
782 char qbuf[QBUFSZ];
784 if (!uwep) { /* Might want to make this so you use your shoulder */
785 You_cant("force anything without a weapon.");
786 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
787 return(0);
790 if (u.utrap && u.utraptype == TT_WEB) {
791 You("are entangled in a web!");
792 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
793 return(0);
794 } else if (uwep && is_lightsaber(uwep)) {
795 if (!uwep->lamplit && !Role_if(PM_SHADOW_JEDI)) {
796 Your("lightsaber is deactivated!");
797 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
798 return(0);
800 } else if(uwep->otyp == LOCK_PICK ||
801 uwep->otyp == HAIRCLIP ||
802 uwep->otyp == CREDIT_CARD ||
803 uwep->otyp == DATA_CHIP ||
804 uwep->otyp == SECRET_KEY ||
805 uwep->otyp == CONTROVERSY_CODE ||
806 uwep->otyp == SKELETON_KEY) {
807 return pick_lock(&uwep);
808 /* not a lightsaber or lockpicking device*/
809 } else if(!uwep || /* proper type test */
810 (uwep->oclass != WEAPON_CLASS && !is_weptool(uwep) &&
811 uwep->oclass != ROCK_CLASS && uwep->oclass != BALL_CLASS && uwep->oclass != CHAIN_CLASS && uwep->oclass != VENOM_CLASS) ||
812 (objects[uwep->otyp].oc_skill < P_DAGGER) ||
813 (objects[uwep->otyp].oc_skill > P_LANCE && uwep->otyp != STEEL_WHIP) ||
814 uwep->otyp == FLAIL || uwep->otyp == AKLYS
815 || uwep->otyp == RUBBER_HOSE
817 You_cant("force anything without a %sweapon.",
818 (uwep) ? "proper " : "");
819 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
820 return(0);
823 /* so we're trying to force something now, which means you touch your weapon; artifact can blast now --Amy */
824 if (!touch_artifact(uwep, &youmonst)) return 0;
826 if (is_lightsaber(uwep))
827 picktyp = 2;
828 else
829 picktyp = is_blade(uwep) ? 1 : 0;
830 if(xlock.usedtime && picktyp == xlock.picktyp) {
831 if (xlock.box) {
832 if (!can_reach_floor()) {
833 pline("Unfortunately, you can no longer reach the lock.");
834 return 0;
836 You("resume your attempt to force the lock.");
837 set_occupation(forcelock, "forcing the lock", 0);
838 if (AutoDestruct || u.uprops[AUTO_DESTRUCT].extrinsic || (uarmf && uarmf->oartifact == ART_KHOR_S_REQUIRED_IDEA) || have_autodestructstone() || (uchain && uchain->oartifact == ART_SIYID) ) forcelock();
839 return(1);
840 } else if (xlock.door) {
841 You("resume your attempt to force the door.");
842 set_occupation(forcedoor, "forcing the door", 0);
843 if (AutoDestruct || u.uprops[AUTO_DESTRUCT].extrinsic || (uarmf && uarmf->oartifact == ART_KHOR_S_REQUIRED_IDEA) || have_autodestructstone() || (uchain && uchain->oartifact == ART_SIYID) ) forcedoor();
844 return(1);
848 /* A lock is made only for the honest man, the thief will break it. */
849 xlock.box = (struct obj *)0;
851 if(!getdir((char *)0)) return(0);
853 x = u.ux + u.dx;
854 y = u.uy + u.dy;
855 if (x == u.ux && y == u.uy) {
856 if (u.dz < 0) {
857 There("isn't any sort of lock up %s.",
858 Levitation ? "here" : "there");
859 return 0;
860 } else if (is_lava(u.ux, u.uy)) {
861 pline("Doing that would probably melt your %s.",
862 xname(uwep));
863 return 0;
864 } else if (is_waterypool(u.ux, u.uy) && !is_crystalwater(u.ux, u.uy) && !Underwater) {
865 pline_The("water has no lock.");
866 return 0;
869 for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere)
870 if(Is_box(otmp)) {
871 if (!can_reach_floor()) {
872 You_cant("reach %s from up here.", the(xname(otmp)));
873 return 0;
876 if (otmp->obroken || !otmp->olocked) {
877 There("is %s here, but its lock is already %s.",
878 doname(otmp), otmp->obroken ? "broken" : "unlocked");
879 continue;
881 sprintf(qbuf,"There is %s here, force its lock?",
882 safe_qbuf("", sizeof("There is here, force its lock?"),
883 doname(otmp), an(simple_typename(otmp->otyp)),
884 "a box"));
886 c = ynq(qbuf);
887 if(c == 'q') return(0);
888 if(c == 'n') continue;
890 if(picktyp == 2)
891 You("begin melting it with your %s.", xname(uwep));
892 else
893 if(picktyp)
894 You("force your %s into a crack and pry.", xname(uwep));
895 else
896 You("start bashing it with your %s.", xname(uwep));
897 xlock.box = otmp;
898 if (is_lightsaber(uwep))
899 xlock.chance = uwep->spe * 2 + 75;
900 else
901 xlock.chance = (uwep->spe + objects[uwep->otyp].oc_wldam) * 2;
902 xlock.picktyp = picktyp;
903 xlock.usedtime = 0;
904 break;
906 if(xlock.box) {
907 xlock.door = 0;
908 set_occupation(forcelock, "forcing the lock", 0);
909 if (AutoDestruct || u.uprops[AUTO_DESTRUCT].extrinsic || (uarmf && uarmf->oartifact == ART_KHOR_S_REQUIRED_IDEA) || have_autodestructstone() || (uchain && uchain->oartifact == ART_SIYID) ) forcelock();
910 return(1);
912 if (u.dz > 0) {
913 if (picktyp != 2) You("cannot find any sort of lock down there.");
914 else {
915 return use_pick_axe2(uwep);
919 } else { /* break down/open door */
920 struct monst *mtmp;
922 door = &levl[x][y];
923 if ((mtmp = m_at(x, y)) && canseemon(mtmp)
924 && mtmp->m_ap_type != M_AP_FURNITURE
925 && mtmp->m_ap_type != M_AP_OBJECT) {
927 if (mtmp->isshk || mtmp->data == &mons[PM_ORACLE])
928 if (Role_if(PM_JEDI) || Role_if(PM_SHADOW_JEDI) || Role_if(PM_HEDDERJEDI))
929 verbalize("Your puny Jedi tricks won't work on me!"); /* Return of the Jedi */
930 else
932 verbalize("What do you think you are, a Jedi?"); /* Phantom Menace */
933 else {
934 if (Role_if(PM_JEDI) ? (u.uen < 5) : Role_if(PM_SHADOW_JEDI) ? (u.uen < 5) : Role_if(PM_HEDDERJEDI) ? (u.uen < 5) : Race_if(PM_BORG) ? (u.uen < 7) : (u.uen < 10) ) pline("I don't think %s would appreciate that. Besides, you need %d mana in order to use the force.", mon_nam(mtmp), Role_if(PM_JEDI) ? 5 : Role_if(PM_SHADOW_JEDI) ? 5 : Role_if(PM_HEDDERJEDI) ? 5 : Race_if(PM_BORG) ? 7 : 10);
935 else {
937 if (!UseTheForce || rn2(StrongUseTheForce ? 3 : 10)) u.uen -= (Role_if(PM_JEDI) ? 5 : Role_if(PM_SHADOW_JEDI) ? 5 : Role_if(PM_HEDDERJEDI) ? 5 : Race_if(PM_BORG) ? 7 : 10);
939 int dmg;
940 int mdx, mdy;
941 dmg = rnd(2) + dbon() + uwep->spe;
943 /* having both blades on boosts the damage --Amy */
944 if (uwep->lamplit && uwep->altmode) dmg += rnd(3);
946 if (UseTheForce) dmg += 5;
947 if (StrongUseTheForce) dmg += 5;
948 if (tech_inuse(T_USE_THE_FORCE_LUKE)) dmg += techlevX(get_tech_no(T_USE_THE_FORCE_LUKE));
949 if (uarmg && uarmg->oartifact == ART_USE_THE_FORCE_LUKE) dmg += 10;
950 if (uwep && uwep->oartifact == ART_DE_SID && uwep->lamplit) dmg += 5;
951 if (uwep && uwep->oartifact == ART_DE_SID && uwep->lamplit && uwep->altmode) dmg += 5;
953 if (Role_if(PM_JEDI) && UseTheForce) dmg += u.ulevel;
954 else if (Role_if(PM_HEDDERJEDI) && UseTheForce) dmg += u.ulevel;
955 else if (Role_if(PM_SHADOW_JEDI) && UseTheForce) dmg += u.ulevel;
956 else if (Race_if(PM_BORG) && UseTheForce) dmg += rnd(u.ulevel);
957 if (Role_if(PM_JEDI) && StrongUseTheForce) dmg += u.ulevel;
958 else if (Role_if(PM_HEDDERJEDI) && StrongUseTheForce) dmg += u.ulevel;
959 else if (Role_if(PM_SHADOW_JEDI) && StrongUseTheForce) dmg += u.ulevel;
960 else if (Race_if(PM_BORG) && StrongUseTheForce) dmg += rnd(u.ulevel);
962 if (Role_if(PM_EMERA) && (mtmp->data->msound == MS_SHOE || mtmp->data->msound == MS_PANTS || mtmp->data->msound == MS_SOCKS)) {
963 dmg += rnd(2 * u.ulevel);
966 if (u.ulevel >= 30) dmg += rnd(4);
967 else if (u.ulevel >= 24) dmg += rnd(3);
968 else if (u.ulevel >= 16) dmg += rnd(2);
969 else if (u.ulevel >= 8) dmg += 1;
971 if (!PlayerCannotUseSkills) {
972 switch (P_SKILL(P_WEDI)) { /* again, bigger boosts if you use both blades --Amy */
974 case P_BASIC:
975 dmg += (uwep && is_lightsaber(uwep) && uwep->lamplit) ? rnd(2) : 1;
976 if (uwep && uwep->oartifact == ART_CHRISMISS) dmg += rn2(2);
977 if (uwep && is_lightsaber(uwep) && uwep->lamplit && uwep->altmode) dmg += rnd(2);
978 break;
979 case P_SKILLED:
980 dmg += (uwep && is_lightsaber(uwep) && uwep->lamplit) ? rnd(4) : rnd(2); if (uwep && uwep->oartifact == ART_CHRISMISS) dmg += rnd(2);
981 if (uwep && is_lightsaber(uwep) && uwep->lamplit && uwep->altmode) dmg += rnd(4);
982 break;
983 case P_EXPERT:
984 dmg += (uwep && is_lightsaber(uwep) && uwep->lamplit) ? rnd(6) : rnd(3); if (uwep && uwep->oartifact == ART_CHRISMISS) dmg += rnd(3);
985 if (uwep && is_lightsaber(uwep) && uwep->lamplit && uwep->altmode) dmg += rnd(6);
986 break;
987 case P_MASTER:
988 dmg += (uwep && is_lightsaber(uwep) && uwep->lamplit) ? rnd(8) : rnd(4);
989 if (uwep && uwep->oartifact == ART_CHRISMISS) dmg += rnd(4);
990 if (uwep && is_lightsaber(uwep) && uwep->lamplit && uwep->altmode) dmg += rnd(8);
991 break;
992 case P_GRAND_MASTER:
993 dmg += (uwep && is_lightsaber(uwep) && uwep->lamplit) ? rnd(10) : rnd(5);
994 if (uwep && uwep->oartifact == ART_CHRISMISS) dmg += rnd(5);
995 if (uwep && is_lightsaber(uwep) && uwep->lamplit && uwep->altmode) dmg += rnd(10);
996 break;
997 case P_SUPREME_MASTER:
998 dmg += (uwep && is_lightsaber(uwep) && uwep->lamplit) ? rnd(12) : rnd(6);
999 if (uwep && uwep->oartifact == ART_CHRISMISS) dmg += rnd(6);
1000 if (uwep && is_lightsaber(uwep) && uwep->lamplit && uwep->altmode) dmg += rnd(12);
1001 break;
1002 default: break;
1006 boolean trapkilled = FALSE;
1008 pline("You use the force on %s.", mon_nam(mtmp));
1009 u.cnd_forcecount++;
1011 if (Role_if(PM_EMERA) && (mtmp->data->msound == MS_SHOE || mtmp->data->msound == MS_PANTS || mtmp->data->msound == MS_SOCKS)) pline("Your %s furiously rip into %s. You evil bastard.", makeplural(body_part(HAND)), mon_nam(mtmp));
1013 setmangry(mtmp);
1014 wakeup(mtmp);
1016 if (uwep && is_lightsaber(uwep) && (uwep->lamplit || Role_if(PM_SHADOW_JEDI)) ) {
1017 u.uwediturns++;
1018 mightbooststat(rn2(2) ? A_STR : A_CON);
1019 if (u.uwediturns >= 2) {
1020 u.uwediturns = 0;
1021 use_skill(P_WEDI, 1);
1024 if (uwep && uwep->oartifact == ART_DIGSRU) {
1025 u.uwediturns++;
1026 mightbooststat(rn2(2) ? A_STR : A_CON);
1027 if (u.uwediturns >= 2) {
1028 u.uwediturns = 0;
1029 use_skill(P_WEDI, 1);
1033 if(mtmp->mtame) {
1034 abuse_dog(mtmp);
1037 if (mtmp->meating) {
1038 pline("Startled, %s spits out the food it was eating!", mon_nam(mtmp));
1039 mtmp->meating = 0;
1041 if (mtmp->mfrozen) {
1042 pline("Being hit by your force, %s is jolted back to its senses.", mon_nam(mtmp));
1043 mtmp->mfrozen = 0;
1045 if (mtmp->msleeping) {
1046 pline("Being hit by your force, %s suddenly wakes up!", mon_nam(mtmp));
1047 mtmp->msleeping = 0;
1049 mtmp->mcanmove = 1;
1050 mtmp->masleep = 0;
1051 if (mtmp->mtame)
1052 monflee(mtmp, (dmg ? rnd(dmg) : 1), FALSE, FALSE);
1053 else
1054 mtmp->mflee = 0;
1056 if (dmg > 0) {
1057 mtmp->mhp -= dmg;
1058 #ifdef SHOW_DMG
1059 showdmg(dmg);
1060 #endif
1063 if (mtmp->mhp > 0 && ( (UseTheForce && uwep && is_lightsaber(uwep) && uwep->lamplit && rn2(2) ) || (StrongUseTheForce && uwep && is_lightsaber(uwep) && uwep->lamplit && rn2(2) ) || ( (Role_if(PM_JEDI) || Role_if(PM_SHADOW_JEDI) || Role_if(PM_HEDDERJEDI)) ? (rnd(100) < (u.ulevel * 2) ) : (rnd(100) < u.ulevel) ) ) &&
1064 mtmp->mcanmove && mtmp != u.ustuck && !mtmp->mtrapped) {
1065 /* see if the monster has a place to move into */
1066 mdx = mtmp->mx + u.dx;
1067 mdy = mtmp->my + u.dy;
1068 if(goodpos(mdx, mdy, mtmp, 0)) {
1069 pline("%s is pushed back!", Monnam(mtmp));
1070 if (m_in_out_region(mtmp, mdx, mdy)) {
1071 remove_monster(mtmp->mx, mtmp->my);
1072 newsym(mtmp->mx, mtmp->my);
1073 place_monster(mtmp, mdx, mdy);
1074 newsym(mtmp->mx, mtmp->my);
1075 set_apparxy(mtmp);
1076 if (mintrap(mtmp) == 2) trapkilled = TRUE;
1081 (void) passive(mtmp, TRUE, mtmp->mhp > 0, AT_TUCH, FALSE);
1082 if (mtmp->mhp <= 0 && !trapkilled) killed(mtmp);
1084 if (mtmp->mhp > 0 && (mtmp->data->msound == MS_FART_QUIET || (!rn2(5) && mtmp->egotype_farter) ) ) {
1085 pline("You bash %s's %s butt using %s %s.", mon_nam(mtmp), mtmp->female ? "sexy" : "ugly", !rn2(3) ? "both your left and right" : rn2(2) ? "your left" : "your right", body_part(HAND) );
1086 if (practicantterror) {
1087 pline("%s thunders: 'Bashing other people's butts is not permitted! 100 zorkmids!'", noroelaname());
1088 fineforpracticant(100, 0, 0);
1091 if (Role_if(PM_BUTT_LOVER)) {
1092 You_feel("bad for hurting one of your beloved butts!");
1093 adjalign(-5);
1094 if (u.negativeprotection > 0 && !rn2(5)) u.negativeprotection--;
1096 u.cnd_forcebuttcount++;
1097 if (mtmp->butthurt < 25 && (!rn2(3) || Role_if(PM_EMERA)) ) {
1098 int butthurting = 5;
1099 if (!PlayerCannotUseSkills) {
1100 switch (P_SKILL(P_WEDI)) {
1101 case P_BASIC: butthurting++; break;
1102 case P_SKILLED: butthurting += 2; break;
1103 case P_EXPERT: butthurting += 3; break;
1104 case P_MASTER: butthurting += 4; break;
1105 case P_GRAND_MASTER: butthurting += 5; break;
1106 case P_SUPREME_MASTER: butthurting += 6; break;
1107 default: break;
1110 if (uwep && uwep->spe > 0) butthurting += rn2(uwep->spe + 1);
1111 if (UseTheForce) butthurting += 3;
1112 if (StrongUseTheForce) butthurting += 3;
1114 mtmp->butthurt += rnd(butthurting);
1115 if (mtmp->butthurt < 5) pline("%s's %s butt is getting %s red bruises.", Monnam(mtmp), mtmp->female ? "sexy" : "ugly", mtmp->female ? "beautiful" : "intense");
1116 else if (mtmp->butthurt < 9) pline("%s's %s butt is getting sore from your beating.", Monnam(mtmp), mtmp->female ? "sexy" : "ugly");
1117 else if (mtmp->butthurt < 13) pline("%s's %s butt is hurt badly, and blood is slowly dripping out...", Monnam(mtmp), mtmp->female ? "sexy" : "ugly");
1118 else if (mtmp->butthurt < 17) pline("%s's %s butt is heavily injured and severely bleeding!", Monnam(mtmp), mtmp->female ? "sexy" : "ugly");
1119 else {
1120 pline("You hurt %s so badly that %s ended up crying, and is begging you to spare %s...", mon_nam(mtmp), mhe(mtmp), mhim(mtmp) );
1121 if (!mtmp->mfrenzied) mtmp->mpeaceful = 1;
1122 mtmp->butthurt = 0;
1126 if (mtmp->mhp > 0 && (mtmp->data->msound == MS_FART_NORMAL || (!rn2(5) && mtmp->egotype_farter) ) ) {
1127 pline("You bash %s's %s butt using %s %s.", mon_nam(mtmp), mtmp->female ? "sexy" : "ugly", !rn2(3) ? "both your left and right" : rn2(2) ? "your left" : "your right", body_part(HAND) );
1128 if (practicantterror) {
1129 pline("%s thunders: 'Bashing other people's butts is not permitted! 100 zorkmids!'", noroelaname());
1130 fineforpracticant(100, 0, 0);
1134 if (FemtrapActiveSueLyn && mtmp->female && !mtmp->mfrenzied) {
1135 pline("Now %s is really angry, and %s will hurt you badly with %s %snails.", mon_nam(mtmp), mhe(mtmp), mhis(mtmp), mbodypart(mtmp, FINGER));
1136 mtmp->mtame = FALSE;
1137 mtmp->mpeaceful = FALSE;
1138 mtmp->mfrenzied = TRUE;
1141 if (Role_if(PM_BUTT_LOVER)) {
1142 You_feel("bad for hurting one of your beloved butts!");
1143 adjalign(-5);
1144 if (u.negativeprotection > 0 && !rn2(5)) u.negativeprotection--;
1146 u.cnd_forcebuttcount++;
1147 if (mtmp->butthurt < 25 && (!rn2(3) || Role_if(PM_EMERA)) ) {
1148 int butthurting = 3;
1149 if (!PlayerCannotUseSkills) {
1150 switch (P_SKILL(P_WEDI)) {
1151 case P_BASIC: butthurting++; break;
1152 case P_SKILLED: butthurting += rnd(2); break;
1153 case P_EXPERT: butthurting += rnd(3); break;
1154 case P_MASTER: butthurting += rnd(4); break;
1155 case P_GRAND_MASTER: butthurting += rnd(5); break;
1156 case P_SUPREME_MASTER: butthurting += rnd(6); break;
1157 default: break;
1160 if (uwep && rn2(2) && uwep->spe > 0) butthurting += rn2(uwep->spe + 1);
1161 if (UseTheForce) butthurting += 2;
1162 if (StrongUseTheForce) butthurting += 2;
1164 mtmp->butthurt += rnd(butthurting);
1165 if (mtmp->butthurt < 5) pline("%s's %s butt is getting %s red bruises.", Monnam(mtmp), mtmp->female ? "sexy" : "ugly", mtmp->female ? "beautiful" : "intense");
1166 else if (mtmp->butthurt < 9) pline("%s's %s butt is getting sore from your beating.", Monnam(mtmp), mtmp->female ? "sexy" : "ugly");
1167 else if (mtmp->butthurt < 13) pline("%s's %s butt is hurt badly, and blood is slowly dripping out...", Monnam(mtmp), mtmp->female ? "sexy" : "ugly");
1168 else if (mtmp->butthurt < 17) pline("%s's %s butt is heavily injured and severely bleeding!", Monnam(mtmp), mtmp->female ? "sexy" : "ugly");
1169 else {
1170 pline("You hurt %s so badly that %s gets unconscious from the pain.", mon_nam(mtmp), mhe(mtmp));
1171 mtmp->mcanmove = 0;
1172 mtmp->mfrozen = 5 + rnd(15);
1173 mtmp->mstrategy &= ~STRAT_WAITFORU;
1174 mtmp->butthurt = 0;
1178 if (mtmp->mhp > 0 && (mtmp->data->msound == MS_FART_LOUD || (!rn2(5) && mtmp->egotype_farter) ) ) {
1179 pline("You bash %s's %s butt using %s %s.", mon_nam(mtmp), mtmp->female ? "sexy" : "ugly", !rn2(3) ? "both your left and right" : rn2(2) ? "your left" : "your right", body_part(HAND) );
1180 if (practicantterror) {
1181 pline("%s thunders: 'Bashing other people's butts is not permitted! 100 zorkmids!'", noroelaname());
1182 fineforpracticant(100, 0, 0);
1185 if (Role_if(PM_BUTT_LOVER)) {
1186 You_feel("bad for hurting one of your beloved butts!");
1187 adjalign(-5);
1188 if (u.negativeprotection > 0 && !rn2(5)) u.negativeprotection--;
1190 u.cnd_forcebuttcount++;
1191 if (mtmp->butthurt < 25 && (!rn2(3) || Role_if(PM_EMERA)) ) {
1192 int butthurting = 1;
1193 if (!PlayerCannotUseSkills && !rn2(2)) {
1194 switch (P_SKILL(P_WEDI)) {
1195 case P_BASIC: butthurting++; break;
1196 case P_SKILLED: butthurting += rnd(2); break;
1197 case P_EXPERT: butthurting += rnd(3); break;
1198 case P_MASTER: butthurting += rnd(4); break;
1199 case P_GRAND_MASTER: butthurting += rnd(5); break;
1200 case P_SUPREME_MASTER: butthurting += rnd(6); break;
1201 default: break;
1204 if (uwep && !rn2(4) && uwep->spe > 0) butthurting += rn2(uwep->spe + 1);
1205 if (UseTheForce) butthurting += 1;
1206 if (StrongUseTheForce) butthurting += 1;
1208 mtmp->butthurt += rnd(butthurting);
1209 if (mtmp->butthurt < 5) pline("%s's %s butt is getting %s red bruises.", Monnam(mtmp), mtmp->female ? "sexy" : "ugly", mtmp->female ? "beautiful" : "intense");
1210 else if (mtmp->butthurt < 9) pline("%s's %s butt is getting sore from your beating.", Monnam(mtmp), mtmp->female ? "sexy" : "ugly");
1211 else if (mtmp->butthurt < 13) pline("%s's %s butt is hurt badly, and blood is slowly dripping out...", Monnam(mtmp), mtmp->female ? "sexy" : "ugly");
1212 else if (mtmp->butthurt < 17) pline("%s's %s butt is heavily injured and severely bleeding!", Monnam(mtmp), mtmp->female ? "sexy" : "ugly");
1213 else {
1214 pline("You hurt %s so badly that %s is furious, and realize that you're going to learn a lesson in pain!", mon_nam(mtmp), mhe(mtmp));
1215 mtmp->mpeaceful = mtmp->mtame = 0;
1216 mon_adjust_speed(mtmp, 2, (struct obj *)0);
1217 mtmp->butthurt = 0;
1218 if (!grow_up(mtmp,(struct monst *)0)) return 1;
1219 if (!grow_up(mtmp,(struct monst *)0)) return 1;
1220 if (!grow_up(mtmp,(struct monst *)0)) return 1;
1225 return(1);
1227 } /* monster forced by player */
1230 return(0);
1233 if (is_farmland(x,y)) {
1234 if (u.uen < 5) {
1235 pline("You have too little energy to force the farmland!");
1236 return(0);
1237 } else {
1238 u.uen -= 5;
1239 pline("You fire an ammo at the farmland.");
1240 if (rn2(20)) pline("It doesn't seem to have any effect.");
1241 else {
1242 pline("The farmland disappears.");
1243 u.cnd_farmlandremoved++;
1244 levl[x][y].typ = CORR;
1245 newsym(x,y);
1246 blockorunblock_point(x,y);
1247 more_experienced(25 * (deepest_lev_reached(FALSE) + 1), 0);
1248 newexplevel();
1250 return(1);
1254 /* Lightsabers dig through doors and walls via dig.c */
1255 if (is_pick(uwep) || is_antibar(uwep) ||
1256 is_lightsaber(uwep) ||
1257 is_axe(uwep))
1258 return use_pick_axe2(uwep);
1260 if(!IS_DOOR(door->typ)) {
1261 if (is_drawbridge_wall(x,y) >= 0)
1262 pline("The drawbridge is too solid to force open.");
1263 else
1264 You("%s no door there.",
1265 Blind ? "feel" : "see");
1266 return(0);
1268 /* ALI - artifact doors */
1269 if (artifact_door(x, y)) {
1270 pline("This door is too solid to force open.");
1271 return 0;
1273 switch (door->doormask) {
1274 case D_NODOOR:
1275 pline("This doorway has no door.");
1276 return(0);
1277 case D_ISOPEN:
1278 You("cannot force an open door.");
1279 return(0);
1280 case D_BROKEN:
1281 pline("This door is broken.");
1282 return(0);
1283 default:
1284 c = yn("Break down the door?");
1285 if(c == 'n') return(0);
1287 if(picktyp == 1)
1288 You("force your %s into a crack and pry.", xname(uwep));
1289 else
1290 You("start bashing it with your %s.", xname(uwep));
1291 if (is_lightsaber(uwep))
1292 xlock.chance = uwep->spe + 38;
1293 else
1294 xlock.chance = uwep->spe + objects[uwep->otyp].oc_wldam;
1295 xlock.picktyp = picktyp;
1296 xlock.usedtime = 0;
1297 xlock.door = door;
1298 xlock.box = 0;
1299 set_occupation(forcedoor, "forcing the door", 0);
1300 if (AutoDestruct || u.uprops[AUTO_DESTRUCT].extrinsic || (uarmf && uarmf->oartifact == ART_KHOR_S_REQUIRED_IDEA) || have_autodestructstone() || (uchain && uchain->oartifact == ART_SIYID) ) forcedoor();
1301 return(1);
1304 You("decide not to force the issue.");
1305 return(0);
1309 doopen() /* try to open a door */
1311 return doopen_indir(0, 0);
1315 doopen_indir(x, y) /* try to open a door in direction u.dx/u.dy */
1316 int x, y; /* if true, prompt for direction */
1318 coord cc;
1319 register struct rm *door;
1320 struct monst *mtmp;
1322 if (nohands(youmonst.data) && !Race_if(PM_TRANSFORMER)) {
1323 You_cant("open anything -- you have no hands!");
1324 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
1326 if (yn("Try to open it with another part of your body instead?") == 'y') {
1327 if (rn2(3) && !polyskillchance()) {
1328 make_blinded(Blinded + rnd(50),TRUE);
1329 pline("Off - you just blinded yourself!");
1330 if (!rn2(20)) badeffect();
1331 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
1332 return 1;
1335 else {return(0);}
1338 if (u.utrap && u.utraptype == TT_PIT) {
1339 You_cant("reach over the edge of the pit.");
1340 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
1341 return 0;
1344 if (x > 0 && y > 0) {
1345 cc.x = x;
1346 cc.y = y;
1348 else if(!get_adjacent_loc((char *)0, (char *)0, u.ux, u.uy, &cc)) return(0);
1350 if((cc.x == u.ux) && (cc.y == u.uy)) return(0);
1352 if ((mtmp = m_at(cc.x,cc.y)) &&
1353 mtmp->m_ap_type == M_AP_FURNITURE &&
1354 (mtmp->mappearance == S_hcdoor ||
1355 mtmp->mappearance == S_vcdoor) &&
1356 !Protection_from_shape_changers) {
1358 stumble_onto_mimic(mtmp);
1359 return(1);
1362 door = &levl[cc.x][cc.y];
1364 if(!IS_DOOR(door->typ)) {
1365 if (is_db_wall(cc.x,cc.y)) {
1366 There("is no obvious way to open the drawbridge.");
1367 return(0);
1369 You("%s no door there.",
1370 Blind ? "feel" : "see");
1371 return(0);
1374 dooragain:
1375 if (!(door->doormask & D_CLOSED)) {
1376 const char *mesg;
1378 if (uwep && uwep->oartifact == ART_FINAL_DOOR_SOLUTION && !artifact_door(cc.x, cc.y) && (door->doormask & D_LOCKED)) {
1379 door->doormask &= ~D_LOCKED;
1380 door->doormask |= D_CLOSED;
1381 pline("kloeck!");
1382 goto dooragain;
1385 switch (door->doormask) {
1386 case D_BROKEN: mesg = " is broken"; break;
1387 case D_NODOOR: mesg = "way has no door"; break;
1388 case D_ISOPEN: mesg = " is already open"; break;
1389 default: mesg = " is locked"; break;
1391 pline("This door%s.", mesg);
1392 if (Blind) feel_location(cc.x,cc.y);
1393 return(0);
1396 if(verysmall(youmonst.data) && !Race_if(PM_TRANSFORMER) ) {
1397 pline("You're too small to pull the door open.");
1398 return(0);
1401 if (uwep && uwep->oartifact == ART_DUURVOID && (door->doormask & D_TRAPPED) && !rn2(5)) {
1402 pline("There seems to be a trap on this door!");
1403 if (yn("Stop handling the door?") == 'y') {
1404 return(0);
1408 /* door is known to be CLOSED */
1409 if ((rnl(20) < (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3) || (uwep && uwep->oartifact == ART_DOORBANE) ) {
1410 pline_The("door opens.");
1411 if(door->doormask & D_TRAPPED) {
1412 b_trapped("door", FINGER);
1413 door->doormask = D_NODOOR;
1414 if (*in_rooms(cc.x, cc.y, SHOPBASE)) add_damage(cc.x, cc.y, 0L);
1415 } else
1416 door->doormask = D_ISOPEN;
1417 if (Blind)
1418 feel_location(cc.x,cc.y); /* the hero knows she opened it */
1419 else
1420 newsym(cc.x,cc.y);
1421 unblock_point(cc.x,cc.y); /* vision: new see through there */
1422 } else {
1423 exercise(A_STR, TRUE);
1424 pline_The("door resists!");
1427 return(1);
1430 STATIC_OVL
1431 boolean
1432 obstructed(x,y)
1433 register int x, y;
1435 register struct monst *mtmp = m_at(x, y);
1437 if(mtmp && mtmp->m_ap_type != M_AP_FURNITURE) {
1438 if (mtmp->m_ap_type == M_AP_OBJECT) goto objhere;
1439 pline("%s stands in the way!", !canspotmon(mtmp) ?
1440 "Some creature" : Monnam(mtmp));
1441 if (!canspotmon(mtmp) && !(mtmp->data->msound == MS_DEEPSTATE) && !(mtmp->egotype_deepstatemember))
1442 map_invisible(mtmp->mx, mtmp->my);
1443 return(TRUE);
1445 if (OBJ_AT(x, y)) {
1446 objhere: pline("%s's in the way.", Something);
1447 return(TRUE);
1449 return(FALSE);
1452 STATIC_OVL
1453 boolean
1454 obstructedX(x,y)
1455 register int x, y;
1457 register struct monst *mtmp = m_at(x, y);
1459 if(mtmp && mtmp->m_ap_type != M_AP_FURNITURE) {
1460 if (mtmp->m_ap_type == M_AP_OBJECT) goto objhere;
1461 if (!canspotmon(mtmp) && !(mtmp->data->msound == MS_DEEPSTATE) && !(mtmp->egotype_deepstatemember))
1462 map_invisible(mtmp->mx, mtmp->my);
1463 return(TRUE);
1465 if (OBJ_AT(x, y)) {
1466 objhere: return(TRUE);
1468 return(FALSE);
1472 doclose() /* try to close a door */
1474 register int x, y;
1475 register struct rm *door;
1476 struct monst *mtmp;
1478 if (nohands(youmonst.data) && !Race_if(PM_TRANSFORMER)) {
1479 You_cant("close anything -- you have no hands!");
1480 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
1482 if (yn("Try to close it with another part of your body instead?") == 'y') {
1483 if (rn2(3) && !polyskillchance()) {
1484 make_blinded(Blinded + rnd(50),TRUE);
1485 pline("Something got in your face! You can't see!");
1486 if (!rn2(20)) badeffect();
1487 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
1488 return 1;
1491 else {return(0);}
1494 if (u.utrap && u.utraptype == TT_PIT) {
1495 You_cant("reach over the edge of the pit.");
1496 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
1497 return 0;
1500 if(!getdir((char *)0)) return(0);
1502 x = u.ux + u.dx;
1503 y = u.uy + u.dy;
1504 if((x == u.ux) && (y == u.uy)) {
1505 You("are in the way!");
1506 return(1);
1509 if ((mtmp = m_at(x,y)) &&
1510 mtmp->m_ap_type == M_AP_FURNITURE &&
1511 (mtmp->mappearance == S_hcdoor ||
1512 mtmp->mappearance == S_vcdoor) &&
1513 !Protection_from_shape_changers) {
1515 stumble_onto_mimic(mtmp);
1516 return(1);
1519 door = &levl[x][y];
1521 if(!IS_DOOR(door->typ)) {
1522 if (door->typ == DRAWBRIDGE_DOWN)
1523 There("is no obvious way to close the drawbridge.");
1524 else
1525 You("%s no door there.",
1526 Blind ? "feel" : "see");
1527 return(0);
1530 if(door->doormask == D_NODOOR) {
1531 pline("This doorway has no door.");
1532 return(0);
1535 if(obstructed(x, y)) return(0);
1537 if(door->doormask == D_BROKEN) {
1538 pline("This door is broken.");
1539 return(0);
1542 if(door->doormask & (D_CLOSED | D_LOCKED)) {
1543 pline("This door is already closed.");
1544 return(0);
1547 if(door->doormask == D_ISOPEN) {
1548 if(verysmall(youmonst.data) && !Race_if(PM_TRANSFORMER)
1549 && !u.usteed ) {
1550 pline("You're too small to push the door closed.");
1551 return(0);
1553 if (u.usteed || (rn2(25) < (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3) || (uwep && uwep->oartifact == ART_DOORBANE)) {
1554 pline_The("door closes.");
1555 door->doormask = D_CLOSED;
1556 if (Blind)
1557 feel_location(x,y); /* the hero knows she closed it */
1558 else
1559 newsym(x,y);
1560 block_point(x,y); /* vision: no longer see there */
1562 else {
1563 exercise(A_STR, TRUE);
1564 pline_The("door resists!");
1568 return(1);
1571 boolean /* box obj was hit with spell effect otmp */
1572 boxlock(obj, otmp) /* returns true if something happened */
1573 register struct obj *obj, *otmp; /* obj *is* a box */
1575 register boolean res = 0;
1577 switch(otmp->otyp) {
1578 case WAN_LOCKING:
1579 if (!obj->olocked) { /* lock it; fix if broken */
1580 pline("Klunk!");
1581 obj->olocked = 1;
1582 obj->obroken = 0;
1583 res = 1;
1584 } /* else already closed and locked */
1585 break;
1586 case SPE_WIZARD_LOCK:
1587 if (Role_if(PM_LOCKSMITH) ? !rn2(100) : rn2(2)) {
1588 if (!rn2(10)) containerkaboom();
1589 break;
1591 if (!obj->olocked) { /* lock it; fix if broken */
1592 pline("Klunk!");
1593 obj->olocked = 1;
1594 obj->obroken = 0;
1595 res = 1;
1596 } /* else already closed and locked */
1597 break;
1598 case WAN_OPENING:
1599 if (obj->olocked) { /* unlock; couldn't be broken */
1600 pline("Klick!");
1601 obj->olocked = 0;
1602 res = 1;
1603 } else /* silently fix if broken */
1604 obj->obroken = 0;
1605 break;
1606 case SPE_KNOCK:
1607 if (Role_if(PM_LOCKSMITH) ? !rn2(50) : rn2(3)) {
1608 if (!rn2(10)) containerkaboom();
1609 break;
1611 if (obj->olocked) { /* unlock; couldn't be broken */
1612 pline("Klick!");
1613 obj->olocked = 0;
1614 res = 1;
1615 } else /* silently fix if broken */
1616 obj->obroken = 0;
1617 break;
1618 case SPE_LOCK_MANIPULATION:
1620 if (Role_if(PM_LOCKSMITH) ? !rn2(50) : rn2(3)) {
1621 if (!rn2(10)) containerkaboom();
1622 break;
1625 if (!rn2(2)) {
1626 if (!obj->olocked) { /* lock it; fix if broken */
1627 pline("Klunk!");
1628 obj->olocked = 1;
1629 obj->obroken = 0;
1630 res = 1;
1631 } /* else already closed and locked */
1633 } else {
1635 if (obj->olocked) { /* unlock; couldn't be broken */
1636 pline("Klick!");
1637 obj->olocked = 0;
1638 res = 1;
1639 } else /* silently fix if broken */
1640 obj->obroken = 0;
1644 break;
1645 case WAN_POLYMORPH:
1646 case WAN_MUTATION:
1647 case SPE_POLYMORPH:
1648 case SPE_MUTATION:
1649 /* maybe start unlocking chest, get interrupted, then zap it;
1650 we must avoid any attempt to resume unlocking it */
1651 if (xlock.box == obj)
1652 reset_pick();
1653 break;
1655 return res;
1658 boolean
1659 doorlockX(x,y,update)
1660 int x, y;
1661 boolean update;
1664 register struct rm *door = &levl[x][y];
1665 boolean res = TRUE;
1666 int key = artifact_door(x, y); /* ALI - Artifact doors */
1668 if (levl[x][y].typ != SDOOR && levl[x][y].typ != DOOR) return FALSE;
1670 /* Amy edit: sigh. The obstructed check was *also* causing savegame errors. Anyway, there's no real reason
1671 * for doors to not close over monsters or objects, so we'll simply allow that to happen. */
1673 /*if (obstructedX(x,y)) return FALSE;*/
1674 /* Don't allow doors to close over traps. This is for pits */
1675 /* & trap doors, but is it ever OK for anything else? */
1676 /*if (t_at(x,y)) {*/
1677 /* maketrap() clears doormask, so it should be NODOOR */
1678 /*return FALSE;
1681 block_point(x, y);
1682 if (key)
1683 door->doormask = D_CLOSED | (door->doormask & D_TRAPPED);
1684 else
1685 door->doormask = D_LOCKED | (door->doormask & D_TRAPPED);
1686 if (update) newsym(x,y);
1688 if (update && res && picking_at(x, y)) {
1689 /* maybe unseen monster zaps door you're unlocking */
1690 stop_occupation();
1691 reset_pick();
1693 return res;
1696 boolean /* Door/secret door was hit with spell effect otmp */
1697 doorlock(otmp,x,y) /* returns true if something happened */
1698 struct obj *otmp;
1699 int x, y;
1701 register struct rm *door = &levl[x][y];
1702 boolean res = TRUE;
1703 int loudness = 0;
1704 const char *msg = (const char *)0;
1705 const char *dustcloud = "A cloud of dust";
1706 const char *quickly_dissipates = "quickly dissipates";
1707 int key = artifact_door(x, y); /* ALI - Artifact doors */
1709 if (door->typ == SDOOR) {
1710 switch (otmp->otyp) {
1712 case WAN_OPENING:
1713 case WAN_STRIKING:
1714 case WAN_GRAVITY_BEAM:
1715 case SPE_GRAVITY_BEAM:
1716 case WAN_DISINTEGRATION:
1717 case SPE_FORCE_BOLT:
1718 if (key) /* Artifact doors are revealed only */
1719 cvt_sdoor_to_door(door);
1720 else {
1721 door->typ = DOOR;
1722 door->doormask = D_CLOSED | (door->doormask & D_TRAPPED);
1724 newsym(x,y);
1725 if (cansee(x,y)) pline("A door appears in the wall!");
1726 if (otmp->otyp == WAN_OPENING || otmp->otyp == SPE_LOCK_MANIPULATION)
1727 return TRUE;
1728 break; /* striking: continue door handling below */
1730 case SPE_LOCK_MANIPULATION:
1731 if (rn2(2)) return FALSE;
1732 if (Role_if(PM_LOCKSMITH) ? !rn2(50) : rn2(3)) {
1733 if (!rn2(10)) containerkaboom();
1734 return TRUE;
1737 if (key) /* Artifact doors are revealed only */
1738 cvt_sdoor_to_door(door);
1739 else {
1740 door->typ = DOOR;
1741 door->doormask = D_CLOSED | (door->doormask & D_TRAPPED);
1743 newsym(x,y);
1744 if (cansee(x,y)) pline("A door appears in the wall!");
1745 return TRUE;
1747 case SPE_KNOCK:
1748 if (Role_if(PM_LOCKSMITH) ? !rn2(50) : rn2(3)) {
1749 if (!rn2(10)) containerkaboom();
1750 return TRUE;
1753 if (key) /* Artifact doors are revealed only */
1754 cvt_sdoor_to_door(door);
1755 else {
1756 door->typ = DOOR;
1757 door->doormask = D_CLOSED | (door->doormask & D_TRAPPED);
1759 newsym(x,y);
1760 if (cansee(x,y)) pline("A door appears in the wall!");
1761 return TRUE;
1762 case WAN_LOCKING:
1763 case SPE_WIZARD_LOCK:
1764 default:
1765 return FALSE;
1769 switch(otmp->otyp) {
1771 case SPE_LOCK_MANIPULATION:
1773 if (!rn2(2)) {
1774 if (!key && door->doormask & D_LOCKED) {
1775 msg = "The door unlocks!";
1776 door->doormask = D_CLOSED | (door->doormask & D_TRAPPED);
1777 } else res = FALSE;
1778 break;
1779 } /* else fall through */
1780 case WAN_LOCKING:
1781 case SPE_WIZARD_LOCK:
1783 if (otmp->otyp == SPE_WIZARD_LOCK && (Role_if(PM_LOCKSMITH) ? !rn2(150) : !rn2(3))) {
1784 if (!rn2(10)) containerkaboom();
1785 return FALSE;
1787 if (otmp->otyp == SPE_LOCK_MANIPULATION && (Role_if(PM_LOCKSMITH) ? !rn2(50) : rn2(3))) {
1788 if (!rn2(10)) containerkaboom();
1789 return FALSE;
1792 if (door->doormask == D_BROKEN && otmp->otyp == SPE_WIZARD_LOCK && (Role_if(PM_LOCKSMITH) ? !rn2(50) : rn2(3))) {
1793 if (!rn2(10)) containerkaboom();
1794 return FALSE;
1796 if (door->doormask == D_NODOOR && otmp->otyp == SPE_WIZARD_LOCK && (Role_if(PM_LOCKSMITH) ? !rn2(100) : rn2(2))) {
1797 if (!rn2(10)) containerkaboom();
1798 return FALSE;
1802 #ifdef REINCARNATION
1803 if (Is_rogue_level(&u.uz)) {
1804 boolean vis = cansee(x,y);
1805 /* Can't have real locking in Rogue, so just hide doorway */
1806 if (vis) pline("%s springs up in the older, more primitive doorway.",
1807 dustcloud);
1808 else
1809 You_hear("a swoosh.");
1810 if (obstructed(x,y)) {
1811 if (vis) pline_The("cloud %s.",quickly_dissipates);
1812 return FALSE;
1814 block_point(x, y);
1815 door->typ = SDOOR;
1816 if (vis) pline_The("doorway vanishes!");
1817 newsym(x,y);
1818 return TRUE;
1820 #endif
1821 if (obstructed(x,y)) return FALSE;
1822 /* Don't allow doors to close over traps. This is for pits */
1823 /* & trap doors, but is it ever OK for anything else? */
1824 if (t_at(x,y)) {
1825 /* maketrap() clears doormask, so it should be NODOOR */
1826 pline(
1827 "%s springs up in the doorway, but %s.",
1828 dustcloud, quickly_dissipates);
1829 return FALSE;
1832 switch (door->doormask & ~D_TRAPPED) {
1833 case D_CLOSED:
1834 if (key)
1835 msg = "The door closes!";
1836 else
1837 msg = "The door locks!";
1838 break;
1839 case D_ISOPEN:
1840 if (key)
1841 msg = "The door swings shut!";
1842 else
1843 msg = "The door swings shut, and locks!";
1844 break;
1845 case D_BROKEN:
1846 if (key)
1847 msg = "The broken door reassembles!";
1848 else
1849 msg = "The broken door reassembles and locks!";
1850 break;
1851 case D_NODOOR:
1852 msg =
1853 "A cloud of dust springs up and assembles itself into a door!";
1854 break;
1855 default:
1856 res = FALSE;
1857 break;
1859 block_point(x, y);
1860 if (key)
1861 door->doormask = D_CLOSED | (door->doormask & D_TRAPPED);
1862 else
1863 door->doormask = D_LOCKED | (door->doormask & D_TRAPPED);
1864 newsym(x,y);
1865 break;
1866 case WAN_OPENING:
1867 if (!key && door->doormask & D_LOCKED) {
1868 msg = "The door unlocks!";
1869 door->doormask = D_CLOSED | (door->doormask & D_TRAPPED);
1870 } else res = FALSE;
1871 break;
1872 case SPE_KNOCK:
1873 if (Role_if(PM_LOCKSMITH) ? !rn2(50) : rn2(3)) {
1874 if (!rn2(10)) containerkaboom();
1875 break;
1877 if (!key && door->doormask & D_LOCKED) {
1878 msg = "The door unlocks!";
1879 door->doormask = D_CLOSED | (door->doormask & D_TRAPPED);
1880 } else res = FALSE;
1881 break;
1882 case WAN_STRIKING:
1883 case WAN_GRAVITY_BEAM:
1884 case WAN_DISINTEGRATION:
1885 case SPE_FORCE_BOLT:
1886 case SPE_GRAVITY_BEAM:
1887 case WAN_WIND:
1888 case SPE_WIND:
1889 if (!key && door->doormask & (D_LOCKED | D_CLOSED)) {
1890 if (door->doormask & D_TRAPPED) {
1891 if (MON_AT(x, y))
1892 (void) mb_trapped(m_at(x,y));
1893 else if (flags.verbose) {
1894 if (cansee(x,y))
1895 pline("KABOOM!! You see a door explode.");
1896 else if (flags.soundok)
1897 You_hear("a distant explosion.");
1899 door->doormask = D_NODOOR;
1900 unblock_point(x,y);
1901 newsym(x,y);
1902 loudness = 40;
1903 break;
1905 door->doormask = D_BROKEN;
1906 if (flags.verbose) {
1907 if (cansee(x,y))
1908 pline_The("door crashes open!");
1909 else if (flags.soundok)
1910 You_hear("a crashing sound.");
1912 unblock_point(x,y);
1913 newsym(x,y);
1914 /* force vision recalc before printing more messages */
1915 if (vision_full_recalc) vision_recalc(0);
1916 loudness = 20;
1917 } else res = FALSE;
1918 break;
1919 default: impossible("magic (%ld) attempted on door.", otmp->otyp);
1920 break;
1922 if (msg && cansee(x,y)) pline("%s", msg);
1923 if (loudness > 0) {
1924 /* door was destroyed */
1925 wake_nearto(x, y, loudness);
1926 if (*in_rooms(x, y, SHOPBASE)) add_damage(x, y, 0L);
1929 if (res && picking_at(x, y)) {
1930 /* maybe unseen monster zaps door you're unlocking */
1931 stop_occupation();
1932 reset_pick();
1934 return res;
1937 STATIC_OVL void
1938 chest_shatter_msg(otmp)
1939 struct obj *otmp;
1941 const char *disposition;
1942 const char *thing;
1943 long save_Blinded;
1945 if (otmp->oclass == POTION_CLASS) {
1946 You("%s %s shatter!", Blind ? "hear" : "see", an(bottlename()));
1947 if (!breathless(youmonst.data) || haseyes(youmonst.data))
1948 potionbreathe(otmp);
1949 return;
1951 /* We have functions for distant and singular names, but not one */
1952 /* which does _both_... */
1953 save_Blinded = Blinded;
1954 Blinded = 1;
1955 thing = singular(otmp, xname);
1956 Blinded = save_Blinded;
1957 /* Amy grepping target: "materialeffect" */
1958 switch (objects[otmp->otyp].oc_material) {
1959 case MT_PAPER: disposition = "is torn to shreds";
1960 break;
1961 case MT_WAX: disposition = "is crushed";
1962 break;
1963 case MT_VEGGY: disposition = "is pulped";
1964 break;
1965 case MT_FLESH: disposition = "is mashed";
1966 break;
1967 case MT_FILM: disposition = "evaporates";
1968 break;
1969 case MT_FOAM: disposition = "is mashed";
1970 break;
1971 case MT_TAR: disposition = "breaks apart";
1972 break;
1973 case MT_GLASS: disposition = "shatters";
1974 break;
1975 case MT_VIVA: disposition = "disintegrates";
1976 break;
1977 case MT_SECREE: disposition = "decomposes";
1978 break;
1979 case MT_ALKALINE: disposition = "decomposes";
1980 break;
1981 case MT_WOOD: disposition = "splinters to fragments";
1982 break;
1983 case MT_SHADOWSTUFF: disposition = "is swallowed";
1984 break;
1985 default: disposition = "is destroyed";
1986 break;
1988 pline("%s %s!", An(thing), disposition);
1991 /* ALI - Kevin Hugo's artifact doors.
1992 * Return the artifact which unlocks the door at (x, y), or
1993 * zero if it is an ordinary door.
1994 * Note: Not all doors are listed in the doors array (eg., doors
1995 * dynamically converted from secret doors). Since only trapped
1996 * and artifact doors are needed this isn't a problem. If we ever
1997 * implement trapped secret doors we will have to extend this.
2001 artifact_door(x, y)
2002 int x, y;
2004 int i;
2006 for(i = 0; i < doorindex; i++) {
2007 if (x == doors[i].x && y == doors[i].y)
2008 return doors[i].arti_key;
2010 return 0;
2013 #endif /* OVLB */
2015 /*lock.c*/