Source:NetHack 3.0.0/lock.c
Jump to navigation
Jump to search
Below is the full text to lock.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.0/lock.c#line123]], for example.
Warning! This is the source code from an old release. For the latest release, see Source code
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
1. /* SCCS Id: @(#)lock.c 3.0 88/10/22 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 struct { 8. int door_or_box, picktyp; 9. struct rm *door; 10. struct obj *box; 11. int chance, usedtime; 12. } xlock; 13. 14. static 15. int 16. picklock() { /* try to open/close a lock */ 17. 18. if(!xlock.door_or_box) { /* box */ 19. 20. if((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy)) { 21. return((xlock.usedtime = 0)); /* you or it moved */ 22. } 23. } else { /* door */ 24. if(xlock.door != &(levl[u.ux+u.dx][u.uy+u.dy])) { 25. return((xlock.usedtime = 0)); /* you moved */ 26. } 27. switch (xlock.door->doormask) { 28. case D_NODOOR: 29. pline("This doorway has no door."); 30. return((xlock.usedtime = 0)); 31. case D_ISOPEN: 32. pline("Picking the lock of an open door is pointless."); 33. return((xlock.usedtime = 0)); 34. case D_BROKEN: 35. pline("This door is broken."); 36. return((xlock.usedtime = 0)); 37. } 38. } 39. 40. if(xlock.usedtime++ >= 50 41. #ifdef POLYSELF 42. || nohands(uasmon) 43. #endif 44. ) { 45. You("give up your attempt to %s the lock.", 46. (xlock.door_or_box ? !(xlock.door->doormask & D_LOCKED) : 47. !xlock.box->olocked) ? "lock" : 48. ((xlock.picktyp == LOCK_PICK) ? "pick" : "open" )); 49. 50. return((xlock.usedtime = 0)); 51. } 52. 53. if(rn2(100) > xlock.chance) return(1); /* still busy */ 54. 55. if(xlock.door_or_box) { 56. You("succeed in %sing the lock.", 57. !(xlock.door->doormask & D_LOCKED) ? "lock" : 58. ((xlock.picktyp == LOCK_PICK) ? "pick" : "open" )); 59. if(xlock.door->doormask & D_TRAPPED) { 60. b_trapped("door"); 61. xlock.door->doormask = D_NODOOR; 62. } else if(xlock.door->doormask == D_LOCKED) 63. xlock.door->doormask = D_CLOSED; 64. else xlock.door->doormask = D_LOCKED; 65. } else { 66. You("succeed in %sing the lock.", 67. (!xlock.box->olocked) ? "lock" : 68. (xlock.picktyp == LOCK_PICK) ? "pick" : "open" ); 69. xlock.box->olocked = !xlock.box->olocked; 70. if(xlock.box->otrapped) chest_trap(xlock.box, FINGER); 71. } 72. return((xlock.usedtime = 0)); 73. } 74. 75. static 76. int 77. forcelock() { /* try to force a locked chest */ 78. 79. register struct obj *otmp, *otmp2; 80. register struct obj *probj = fcobj; /* initialize to make lint happy */ 81. 82. if((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy)) 83. return((xlock.usedtime = 0)); /* you or it moved */ 84. 85. if(xlock.usedtime++ >= 50 || !uwep 86. #ifdef POLYSELF 87. || nohands(uasmon) 88. #endif 89. ) { 90. You("give up your attempt to force the lock."); 91. 92. return((xlock.usedtime = 0)); 93. } 94. 95. if(xlock.picktyp) { /* blade */ 96. 97. if(rn2(1000-uwep->spe) > 992 && !uwep->cursed) { 98. /* for a +0 weapon, probability that it survives an unsuccessful 99. * attempt to force the lock is (.992)^50 = .67 100. */ 101. pline("%sour %s broke!", 102. (uwep->quan > 1) ? "One of y" : "Y", xname(uwep)); 103. useup(uwep); 104. You("give up your attempt to force the lock."); 105. return((xlock.usedtime = 0)); 106. } 107. } else /* blunt */ 108. wake_nearby(); /* due to hammering on the container */ 109. 110. if(rn2(100) > xlock.chance) return(1); /* still busy */ 111. 112. You("succeed in forcing the lock."); 113. xlock.box->olocked = !xlock.box->olocked; 114. if(!xlock.picktyp && !rn2(3)) { 115. 116. pline("In fact, you've totally destroyed the %s.", 117. xname(xlock.box)); 118. for(otmp = fcobj; otmp; otmp = otmp2) { 119. 120. otmp2 = otmp->nobj; 121. if(otmp->cobj == xlock.box) { 122. 123. /* unlink it from the "contained" list */ 124. if(otmp == fcobj) fcobj = otmp2; 125. else probj->nobj = otmp2; 126. 127. if(!rn2(3) || otmp->olet == POTION_SYM) 128. free((genericptr_t) otmp); 129. else { /* spill it onto the floor */ 130. otmp->nobj = xlock.box->nobj; 131. xlock.box->nobj = otmp; 132. otmp->cobj = (struct obj *)0; 133. otmp->ox = u.ux; 134. otmp->oy = u.uy; 135. levl[u.ux][u.uy].omask = 1; 136. stackobj(otmp); 137. } 138. } else probj = otmp; 139. } 140. delobj(xlock.box); 141. } 142. return((xlock.usedtime = 0)); 143. } 144. 145. int 146. pick_lock(pick) /* pick a lock with a given object */ 147. register struct obj *pick; 148. { 149. register int x, y, picktyp, c, ch; 150. register struct rm *door; 151. register struct obj *otmp; 152. 153. picktyp = pick->otyp; 154. if(xlock.usedtime && picktyp == xlock.picktyp) { 155. 156. You("resume your attempt to %s the lock.", 157. (xlock.door_or_box ? !(xlock.door->doormask & D_LOCKED) : 158. !xlock.box->olocked) ? "lock" : 159. ((xlock.picktyp == LOCK_PICK) ? "pick" : "open" )); 160. 161. set_occupation(picklock, 162. (picktyp == LOCK_PICK) ? "picking the lock" : 163. "opening the lock", 0); 164. return(1); 165. } 166. 167. #ifdef POLYSELF 168. if(nohands(uasmon)) { 169. You("can't hold a %s - you have no hands!"); 170. return(0); 171. } 172. #endif 173. if((picktyp != LOCK_PICK && picktyp != CREDIT_CARD && 174. picktyp != SKELETON_KEY && picktyp != KEY)) { 175. impossible("picking lock with object %d?", picktyp); 176. return(0); 177. } 178. if(!getdir(1)) return(0); 179. 180. x = u.ux + u.dx; 181. y = u.uy + u.dy; 182. if((x == u.ux) && (y == u.uy)) { /* pick the lock on a container */ 183. c = 'n'; /* in case there are no boxes here */ 184. if(levl[x][y].omask) 185. for(otmp = fobj; otmp; otmp = otmp->nobj) 186. if((otmp->ox == x) && (otmp->oy == y)) 187. if(Is_box(otmp)) { 188. pline("There is %s here, %s the lock? ", 189. doname(otmp), (!otmp->olocked) ? "close" : 190. ((picktyp == LOCK_PICK) ? "pick" : "open" )); 191. 192. c = ynq(); 193. if(c == 'q') return(0); 194. if(c == 'n') continue; 195. 196. if(picktyp == KEY && otmp->spe != pick->spe) { 197. pline("The %s won't fit the lock.",xname(pick)); 198. return(1); 199. } 200. switch(picktyp) { 201. case CREDIT_CARD: 202. ch = ACURR(A_DEX)+(20*(pl_character[0] == 'R')); 203. break; 204. case LOCK_PICK: 205. ch = 4*ACURR(A_DEX)+(25*(pl_character[0] == 'R')); 206. break; 207. case SKELETON_KEY: 208. ch = 75 + ACURR(A_DEX); 209. break; 210. case KEY: 211. ch = 1000; 212. break; 213. default: ch = 0; 214. } 215. if(otmp->cursed) ch /= 2; 216. 217. xlock.door_or_box = 0; 218. xlock.picktyp = picktyp; 219. xlock.box = otmp; 220. break; 221. } 222. if(c != 'y') 223. return(0); /* decided against all boxes */ 224. } else { /* pick the lock in a door */ 225. struct monst *mtmp; 226. 227. door = &levl[x][y]; 228. if (door->mmask && canseemon(mtmp = m_at(x,y)) && !mtmp->mimic) { 229. if (picktyp == CREDIT_CARD && 230. #ifdef ORACLE 231. (mtmp->isshk || mtmp->data == &mons[PM_ORACLE])) 232. #else 233. mtmp->isshk) 234. #endif 235. pline("\"No checks, no credit, no problem.\""); 236. else 237. kludge("I don't think %s would appreciate that.", mon_nam(mtmp)); 238. return(0); 239. } 240. if(!IS_DOOR(door->typ)) { 241. #ifdef STRONGHOLD 242. if (is_drawbridge_wall(x,y) >= 0) 243. You("%s no lock on the drawbridge.", 244. Blind ? "feel" : "see"); 245. else 246. #endif 247. You("%s no door there.", 248. Blind ? "feel" : "see"); 249. return(0); 250. } 251. switch (door->doormask) { 252. case D_NODOOR: 253. pline("This doorway has no door."); 254. return(0); 255. case D_ISOPEN: 256. pline("Picking the lock of an open door is pointless."); 257. return(0); 258. case D_BROKEN: 259. pline("This door is broken."); 260. return(0); 261. default: 262. pline("%sock it? ", (door->doormask & D_LOCKED) ? "Unl" : "L" ); 263. 264. c = yn(); 265. if(c == 'n') return(0); 266. 267. switch(picktyp) { 268. case CREDIT_CARD: 269. ch = 2*ACURR(A_DEX)+(20*(pl_character[0] == 'R')); 270. break; 271. case LOCK_PICK: 272. ch = 3*ACURR(A_DEX)+(30*(pl_character[0] == 'R')); 273. break; 274. case SKELETON_KEY: 275. ch = 70 + ACURR(A_DEX); 276. break; 277. case KEY: 278. pline("The %s won't fit the door.", xname(pick)); 279. return(1); 280. default: ch = 0; 281. } 282. xlock.door_or_box = 1; 283. xlock.door = door; 284. } 285. } 286. flags.move = 0; 287. xlock.chance = ch; 288. xlock.picktyp = picktyp; 289. xlock.usedtime = 0; 290. set_occupation(picklock, 291. (picktyp == LOCK_PICK) ? "picking the lock" : 292. "opening the lock", 0); 293. return(1); 294. } 295. 296. int 297. doforce() { /* try to force a chest with your weapon */ 298. 299. register struct obj *otmp; 300. register int c, picktyp; 301. 302. if(!uwep || /* proper type test */ 303. (uwep->olet != WEAPON_SYM && uwep->olet != ROCK_SYM && 304. uwep->otyp != PICK_AXE) || 305. (uwep->otyp < DAGGER) || 306. (uwep->otyp > VOULGE && uwep->olet != ROCK_SYM && 307. uwep->otyp != PICK_AXE) 308. ) { 309. You("can't force anything without a %sweapon.", 310. (uwep) ? "proper " : ""); 311. return(0); 312. } 313. 314. picktyp = (uwep->otyp >= DAGGER && uwep->otyp <= KATANA); 315. if(xlock.usedtime && xlock.box && picktyp == xlock.picktyp) { 316. You("resume your attempt to force the lock."); 317. set_occupation(forcelock, "forcing the lock", 0); 318. return(1); 319. } 320. 321. /* A lock is made only for the honest man, the thief will break it. */ 322. xlock.box = (struct obj *)0; 323. if(levl[u.ux][u.uy].omask) 324. for(otmp = fobj; otmp; otmp = otmp->nobj) 325. if((otmp->ox == u.ux) && (otmp->oy == u.uy)) 326. if(Is_box(otmp)) { 327. if(otmp->olocked) 328. pline("There is %s here, force the lock? ", doname(otmp)); 329. else { 330. pline("There is a %s here, but it's already unlocked.", 331. xname(otmp)); 332. continue; 333. } 334. 335. c = ynq(); 336. if(c == 'q') return(0); 337. if(c == 'n') continue; 338. 339. if(picktyp) 340. You("force your %s into a crack and pry.", xname(uwep)); 341. else 342. You("start bashing it with your %s.", xname(uwep)); 343. xlock.box = otmp; 344. xlock.chance = objects[otmp->otyp].wldam * 2; 345. xlock.picktyp = picktyp; 346. xlock.usedtime = 0; 347. break; 348. } 349. 350. if(xlock.box) set_occupation(forcelock, "forcing the lock", 0); 351. else You("decide not to force the issue."); 352. return(1); 353. } 354. 355. int 356. doopen() { /* try to open a door */ 357. register int x, y; 358. register struct rm *door; 359. 360. if(!getdir(1)) return(0); 361. 362. x = u.ux + u.dx; 363. y = u.uy + u.dy; 364. if((x == u.ux) && (y == u.uy)) return(0); 365. 366. door = &levl[x][y]; 367. 368. if(!IS_DOOR(door->typ)) { 369. #ifdef STRONGHOLD 370. if (is_drawbridge_wall(x,y) >= 0) { 371. pline("There is no obvious way to open the drawbridge."); 372. return(0); 373. } 374. #endif 375. You("%s no door there.", 376. Blind ? "feel" : "see"); 377. return(0); 378. } 379. 380. if(!(door->doormask & D_CLOSED)) { 381. switch(door->doormask) { 382. case D_BROKEN: pline("This door is broken."); break; 383. case D_NODOOR: pline("This doorway has no door."); break; 384. case D_ISOPEN: pline("This door is already open."); break; 385. default: pline("This door is locked."); break; 386. } 387. return(0); 388. } 389. 390. #ifdef POLYSELF 391. if(verysmall(uasmon)) { 392. pline("You're too small to pull the door open."); 393. return(0); 394. } 395. #endif 396. /* door is known to be CLOSED */ 397. if (rnl(20) < (ACURR(A_STR)+ACURR(A_DEX)+ACURR(A_CON))/3) { 398. pline("The door opens."); 399. if(door->doormask & D_TRAPPED) { 400. b_trapped("door"); 401. door->doormask = D_NODOOR; 402. } else 403. door->doormask = D_ISOPEN; 404. } else { 405. pline("The door resists!"); 406. } 407. 408. return(1); 409. } 410. 411. static 412. boolean 413. obstructed(x,y) 414. register int x, y; 415. { 416. if(levl[x][y].mmask) { 417. if (m_at(x,y)->mimic) goto obj; 418. pline("%s stands in the way!", Blind ? 419. "Some creature" : Monnam(m_at(x,y))); 420. return(TRUE); 421. } 422. if (levl[x][y].omask || levl[x][y].gmask) { 423. obj: 424. pline("Something's in the way."); 425. return(TRUE); 426. } 427. return(FALSE); 428. } 429. 430. int 431. doclose() { /* try to close a door */ 432. register int x, y; 433. register struct rm *door; 434. 435. if(!getdir(1)) return(0); 436. 437. x = u.ux + u.dx; 438. y = u.uy + u.dy; 439. if((x == u.ux) && (y == u.uy)) { 440. You("are in the way!"); 441. return(1); 442. } 443. door = &levl[x][y]; 444. 445. if(!IS_DOOR(door->typ)) { 446. #ifdef STRONGHOLD 447. if (door->typ == DRAWBRIDGE_DOWN) 448. pline("There is no obvious way to close the drawbridge."); 449. else 450. #endif 451. You("%s no door there.", 452. Blind ? "feel" : "see"); 453. return(0); 454. } 455. 456. if(door->doormask == D_NODOOR) { 457. pline("This doorway has no door."); 458. return(0); 459. } 460. 461. if(obstructed(x, y)) return(0); 462. 463. if(door->doormask == D_BROKEN) { 464. pline("This door is broken."); 465. return(0); 466. } 467. 468. if(door->doormask & (D_CLOSED | D_LOCKED)) { 469. pline("This door is already closed."); 470. return(0); 471. } 472. 473. if(door->doormask == D_ISOPEN) { 474. #ifdef POLYSELF 475. if(verysmall(uasmon)) { 476. pline("You're too small to push the door closed."); 477. return(0); 478. } 479. #endif 480. if (rn2(25) < (ACURR(A_STR)+ACURR(A_DEX)+ACURR(A_CON))/3) { 481. pline("The door closes."); 482. door->doormask = D_CLOSED; 483. } 484. else pline("The door resists!"); 485. } 486. 487. return(1); 488. } 489. 490. int 491. boxlock(obj, otmp) /* box obj was hit with spell effect otmp */ 492. /* returns 1 if something happened */ 493. register struct obj *obj, *otmp; /* obj *is* a box */ 494. { 495. register boolean res; 496. 497. switch(otmp->otyp) { 498. case WAN_LOCKING: 499. #ifdef SPELLS 500. case SPE_WIZARD_LOCK: 501. #endif 502. if(!obj->olocked) { 503. pline("Klunk!"); 504. obj->olocked = !(obj->olocked); 505. res = 1; 506. } else res = 0; 507. break; 508. case WAN_OPENING: 509. #ifdef SPELLS 510. case SPE_KNOCK: 511. #endif 512. if(obj->olocked) { 513. pline("Klick!"); 514. obj->olocked = !(obj->olocked); 515. res = 1; 516. } else res = 0; 517. break; 518. } 519. return(res); 520. } 521. 522. int 523. doorlock(otmp,x,y) /* door was hit with spell effect otmp */ 524. register struct obj *otmp; 525. int x, y; 526. { 527. register struct rm *door = &levl[x][y]; 528. boolean res = 1; 529. 530. if(obstructed(x,y)) 531. return 0; 532. 533. if(door->typ == SDOOR) { 534. if(otmp->otyp == WAN_OPENING 535. #ifdef SPELLS 536. || otmp->otyp == SPE_KNOCK 537. #endif /* SPELLS /**/ 538. ) { 539. door->typ = DOOR; 540. door->doormask = D_CLOSED | (door->doormask & D_TRAPPED); 541. if(cansee(x,y)) { 542. pline("A section of the wall opens up!"); 543. newsym(x,y); 544. } 545. return(1); 546. } else 547. return(0); 548. } 549. 550. #ifdef STRONGHOLD 551. /* make sure it isn't an open drawbridge */ 552. if (is_maze_lev && find_drawbridge(&x,&y)) { 553. if(otmp->otyp == WAN_OPENING 554. #ifdef SPELLS 555. || otmp->otyp == SPE_KNOCK 556. #endif /* SPELLS /**/ 557. ) 558. (void) open_drawbridge(x,y); 559. else 560. (void) close_drawbridge(x,y); 561. return 1; 562. } 563. #endif 564. 565. switch(otmp->otyp) { 566. case WAN_LOCKING: 567. #ifdef SPELLS 568. case SPE_WIZARD_LOCK: 569. #endif 570. if (cansee(x,y)) 571. switch (door->doormask & ~D_TRAPPED) { 572. case D_CLOSED: 573. pline("The door locks!"); 574. break; 575. case D_ISOPEN: 576. pline("The door swings shut, and locks!"); 577. break; 578. case D_BROKEN: 579. pline("The broken door reassembles and locks!"); 580. break; 581. case D_NODOOR: 582. pline("A cloud of dust springs up and assembles itself into a door!"); 583. break; 584. default: res = 0; 585. } 586. door->doormask = D_LOCKED | (door->doormask & D_TRAPPED); 587. break; 588. case WAN_OPENING: 589. #ifdef SPELLS 590. case SPE_KNOCK: 591. #endif 592. if(door->doormask & D_LOCKED) { 593. door->doormask = D_CLOSED | (door->doormask & D_TRAPPED); 594. if(cansee(x,y)) pline("The door unlocks!"); 595. } else res = 0; 596. break; 597. default: impossible("magic (%d) attempted on door.", otmp->otyp); 598. } 599. return res; 600. } 601. 602. #ifdef STUPID_CPP /* otherwise these functions are macros in obj.h */ 603. int 604. Is_container(otmp) struct obj * otmp; { 605. return(otmp->otyp >= ICE_BOX && otmp->otyp <= BAG_OF_TRICKS); 606. } 607. 608. int 609. Is_box(otmp) struct obj * otmp; { 610. return(otmp->otyp == LARGE_BOX || otmp->otyp == CHEST); 611. } 612. 613. int 614. Is_mbag(otmp) struct obj * otmp; { 615. return(otmp->otyp == BAG_OF_HOLDING || otmp->otyp == BAG_OF_TRICKS); 616. } 617. 618. int 619. is_sword(otmp) struct obj * otmp; { 620. return(otmp->otyp >= SHORT_SWORD && otmp->otyp <= KATANA); 621. } 622. 623. int 624. bimanual(otmp) struct obj * otmp; { 625. return(otmp->olet == WEAPON_SYM && objects[otmp->otyp].oc_bimanual); 626. } 627. #endif /* STUPID_CPP */