About: Source:SLASH'EM 0.0.7E7F2/potion.c   Sponge Permalink

An Entity of Type : owl:Thing, within Data Space : 134.155.108.49:8890 associated with source dataset(s)

Below is the full text to potion.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/potion.c#line123]], for example. The latest source code for vanilla NetHack is at Source code.

AttributesValues
rdfs:label
  • Source:SLASH'EM 0.0.7E7F2/potion.c
rdfs:comment
  • Below is the full text to potion.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/potion.c#line123]], for example. The latest source code for vanilla NetHack is at Source code.
dcterms:subject
dbkwik:nethack/pro...iPageUsesTemplate
abstract
  • Below is the full text to potion.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/potion.c#line123]], for example. The latest source code for vanilla NetHack is at Source code. 1. /* SCCS Id: @(#)potion.c 3.4 2002/10/02 */ 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. 8. /* KMH, intrinsics patch 9. * There are many changes here to support >32-bit properties. 10. * Also, blessed potions are once again permitted to convey 11. * permanent intrinsics. 12. */ 13. 14. 15. #ifdef OVLB 16. boolean notonhead = FALSE; 17. 18. static NEARDATA int nothing, unkn; 19. static NEARDATA const char beverages[] = { POTION_CLASS, 0 }; 20. 21. STATIC_DCL long FDECL(itimeout, (long)); 22. STATIC_DCL long FDECL(itimeout_incr, (long,int)); 23. STATIC_DCL void NDECL(ghost_from_bottle); 24. STATIC_DCL short FDECL(mixtype, (struct obj *,struct obj *)); 25. 26. STATIC_DCL void FDECL(healup_mon, (struct monst *, int,int,BOOLEAN_P,BOOLEAN_P)); 27. /* For healing monsters - analogous to healup for players */ 28. 29. 30. /* force `val' to be within valid range for intrinsic timeout value */ 31. STATIC_OVL long 32. itimeout(val) 33. long val; 34. { 35. if (val >= TIMEOUT) val = TIMEOUT; 36. else if (val < 1) val = 0; 37. 38. return val; 39. } 40. 41. /* increment `old' by `incr' and force result to be valid intrinsic timeout */ 42. STATIC_OVL long 43. itimeout_incr(old, incr) 44. long old; 45. int incr; 46. { 47. return itimeout((old & TIMEOUT) + (long)incr); 48. } 49. 50. /* set the timeout field of intrinsic `which' */ 51. void 52. set_itimeout(which, val) 53. long *which, val; 54. { 55. *which &= ~TIMEOUT; 56. *which |= itimeout(val); 57. } 58. 59. /* increment the timeout field of intrinsic `which' */ 60. void 61. incr_itimeout(which, incr) 62. long *which; 63. int incr; 64. { 65. set_itimeout(which, itimeout_incr(*which, incr)); 66. } 67. 68. void 69. make_confused(xtime,talk) 70. long xtime; 71. boolean talk; 72. { 73. long old = HConfusion; 74. 75. if (!xtime && old) { 76. if (talk) 77. You_feel("less %s now.", 78. Hallucination ? "trippy" : "confused"); 79. } 80. if ((xtime && !old) || (!xtime && old)) flags.botl = TRUE; 81. 82. set_itimeout(&HConfusion, xtime); 83. } 84. 85. void 86. make_stunned(xtime,talk) 87. long xtime; 88. boolean talk; 89. { 90. long old = HStun; 91. 92. if (!xtime && old) { 93. if (talk) 94. You_feel("%s now.", 95. Hallucination ? "less wobbly" : "a bit steadier"); 96. } 97. if (xtime && !old) { 98. if (talk) { 99. #ifdef STEED 100. if (u.usteed) 101. You("wobble in the saddle."); 102. else 103. #endif 104. You("%s...", stagger(youmonst.data, "stagger")); 105. } 106. } 107. if ((!xtime && old) || (xtime && !old)) flags.botl = TRUE; 108. 109. set_itimeout(&HStun, xtime); 110. } 111. 112. void 113. make_sick(xtime, cause, talk, type) 114. long xtime; 115. const char *cause; /* sickness cause */ 116. boolean talk; 117. int type; 118. { 119. long old = Sick; 120. 121. if (xtime > 0L) { 122. if (Sick_resistance) return; 123. if (!old) { 124. /* newly sick */ 125. You_feel("deathly sick."); 126. } else { 127. /* already sick */ 128. if (talk) You_feel("%s worse.", 129. xtime <= Sick/2L ? "much" : "even"); 130. } 131. set_itimeout(&Sick, xtime); 132. u.usick_type |= type; 133. flags.botl = TRUE; 134. } else if (old && (type & u.usick_type)) { 135. /* was sick, now not */ 136. u.usick_type &= ~type; 137. if (u.usick_type) { /* only partly cured */ 138. if (talk) You_feel("somewhat better."); 139. set_itimeout(&Sick, Sick * 2); /* approximation */ 140. } else { 141. if (talk) pline("What a relief!"); 142. Sick = 0L; /* set_itimeout(&Sick, 0L) */ 143. } 144. flags.botl = TRUE; 145. } 146. 147. if (Sick) { 148. exercise(A_CON, FALSE); 149. if (cause) { 150. (void) strncpy(u.usick_cause, cause, sizeof(u.usick_cause)); 151. u.usick_cause[sizeof(u.usick_cause)-1] = 0; 152. } 153. else 154. u.usick_cause[0] = 0; 155. } else 156. u.usick_cause[0] = 0; 157. } 158. 159. void 160. make_vomiting(xtime, talk) 161. long xtime; 162. boolean talk; 163. { 164. long old = Vomiting; 165. 166. if(!xtime && old) 167. if(talk) You_feel("much less nauseated now."); 168. 169. set_itimeout(&Vomiting, xtime); 170. } 171. 172. static const char vismsg[] = "vision seems to %s for a moment but is %s now."; 173. static const char eyemsg[] = "%s momentarily %s."; 174. 175. void 176. make_blinded(xtime, talk) 177. long xtime; 178. boolean talk; 179. { 180. long old = Blinded; 181. boolean u_could_see, can_see_now; 182. int eyecnt; 183. char buf[BUFSZ]; 184. 185. /* we need to probe ahead in case the Eyes of the Overworld 186. are or will be overriding blindness */ 187. u_could_see = !Blind; 188. Blinded = xtime ? 1L : 0L; 189. can_see_now = !Blind; 190. Blinded = old; /* restore */ 191. 192. if (u.usleep) talk = FALSE; 193. 194. if (can_see_now && !u_could_see) { /* regaining sight */ 195. if (talk) { 196. if (Hallucination) 197. pline("Far out! Everything is all cosmic again!"); 198. else 199. You("can see again."); 200. } 201. } else if (old && !xtime) { 202. /* clearing temporary blindness without toggling blindness */ 203. if (talk) { 204. if (!haseyes(youmonst.data)) { 205. strange_feeling((struct obj *)0, (char *)0); 206. } else if (Blindfolded) { 207. Strcpy(buf, body_part(EYE)); 208. eyecnt = eyecount(youmonst.data); 209. Your(eyemsg, (eyecnt == 1) ? buf : makeplural(buf), 210. (eyecnt == 1) ? "itches" : "itch"); 211. } else { /* Eyes of the Overworld */ 212. Your(vismsg, "brighten", 213. Hallucination ? "sadder" : "normal"); 214. } 215. } 216. } 217. 218. if (u_could_see && !can_see_now) { /* losing sight */ 219. if (talk) { 220. if (Hallucination) 221. pline("Oh, bummer! Everything is dark! Help!"); 222. else 223. pline("A cloud of darkness falls upon you."); 224. } 225. /* Before the hero goes blind, set the ball&chain variables. */ 226. if (Punished) set_bc(0); 227. } else if (!old && xtime) { 228. /* setting temporary blindness without toggling blindness */ 229. if (talk) { 230. if (!haseyes(youmonst.data)) { 231. strange_feeling((struct obj *)0, (char *)0); 232. } else if (Blindfolded) { 233. Strcpy(buf, body_part(EYE)); 234. eyecnt = eyecount(youmonst.data); 235. Your(eyemsg, (eyecnt == 1) ? buf : makeplural(buf), 236. (eyecnt == 1) ? "twitches" : "twitch"); 237. } else { /* Eyes of the Overworld */ 238. Your(vismsg, "dim", 239. Hallucination ? "happier" : "normal"); 240. } 241. } 242. } 243. 244. set_itimeout(&Blinded, xtime); 245. 246. if (u_could_see ^ can_see_now) { /* one or the other but not both */ 247. flags.botl = 1; 248. vision_full_recalc = 1; /* blindness just got toggled */ 249. if (Blind_telepat || Infravision) see_monsters(); 250. } 251. } 252. 253. boolean 254. make_hallucinated(xtime, talk, mask) 255. long xtime; /* nonzero if this is an attempt to turn on hallucination */ 256. boolean talk; 257. long mask; /* nonzero if resistance status should change by mask */ 258. { 259. long old = HHallucination; 260. boolean changed = 0; 261. const char *message, *verb; 262. 263. message = (!xtime) ? "Everything %s SO boring now." : 264. "Oh wow! Everything %s so cosmic!"; 265. verb = (!Blind) ? "looks" : "feels"; 266. 267. if (mask) { 268. if (HHallucination) changed = TRUE; 269. 270. if (!xtime) EHalluc_resistance |= mask; 271. else EHalluc_resistance &= ~mask; 272. } else { 273. if (!EHalluc_resistance && (!!HHallucination != !!xtime)) 274. changed = TRUE; 275. set_itimeout(&HHallucination, xtime); 276. 277. /* clearing temporary hallucination without toggling vision */ 278. if (!changed && !HHallucination && old && talk) { 279. if (!haseyes(youmonst.data)) { 280. strange_feeling((struct obj *)0, (char *)0); 281. } else if (Blind) { 282. char buf[BUFSZ]; 283. int eyecnt = eyecount(youmonst.data); 284. 285. Strcpy(buf, body_part(EYE)); 286. Your(eyemsg, (eyecnt == 1) ? buf : makeplural(buf), 287. (eyecnt == 1) ? "itches" : "itch"); 288. } else { /* Grayswandir */ 289. Your(vismsg, "flatten", "normal"); 290. } 291. } 292. } 293. 294. if (changed) { 295. if (u.uswallow) { 296. swallowed(0); /* redraw swallow display */ 297. } else { 298. /* The see_* routines should be called *before* the pline. */ 299. see_monsters(); 300. see_objects(); 301. see_traps(); 302. } 303. 304. /* for perm_inv and anything similar 305. (eg. Qt windowport's equipped items display) */ 306. update_inventory(); 307. 308. flags.botl = 1; 309. if (talk) pline(message, verb); 310. } 311. return changed; 312. } 313. 314. STATIC_OVL void 315. ghost_from_bottle() 316. { 317. struct monst *mtmp = makemon(&mons[PM_GHOST], u.ux, u.uy, NO_MM_FLAGS); 318. 319. if (!mtmp) { 320. pline("This bottle turns out to be empty."); 321. return; 322. } 323. if (Blind) { 324. pline("As you open the bottle, %s emerges.", something); 325. return; 326. } 327. pline("As you open the bottle, an enormous %s emerges!", 328. Hallucination ? rndmonnam() : (const char *)"ghost"); 329. if(flags.verbose) 330. You("are frightened to death, and unable to move."); 331. nomul(-3); 332. nomovemsg = "You regain your composure."; 333. } 334. 335. /* "Quaffing is like drinking, except you spill more." -- Terry Pratchett 336. */ 337. int 338. dodrink() 339. { 340. register struct obj *otmp; 341. const char *potion_descr; 342. char quaffables[SIZE(beverages) + 2]; 343. char *qp = quaffables; 344. 345. if (Strangled) { 346. pline("If you can't breathe air, how can you drink liquid?"); 347. return 0; 348. } 349. 350. *qp++ = ALLOW_FLOOROBJ; 351. if (!u.uswallow && (IS_FOUNTAIN(levl[u.ux][u.uy].typ) || 352. #ifdef SINKS 353. IS_SINK(levl[u.ux][u.uy].typ) || 354. IS_TOILET(levl[u.ux][u.uy].typ) || 355. #endif 356. Underwater || IS_POOL(levl[u.ux][u.uy].typ))) 357. *qp++ = ALLOW_THISPLACE; 358. Strcpy(qp, beverages); 359. 360. otmp = getobj(quaffables, "drink"); 361. if (otmp == &thisplace) { 362. if (IS_FOUNTAIN(levl[u.ux][u.uy].typ)) { 363. drinkfountain(); 364. return 1; 365. } 366. #ifdef SINKS 367. else if (IS_SINK(levl[u.ux][u.uy].typ)) { 368. drinksink(); 369. return 1; 370. } 371. else if (IS_TOILET(levl[u.ux][u.uy].typ)) { 372. drinktoilet(); 373. return 1; 374. } 375. #endif 376. pline("Do you know what lives in this water!"); 377. return 1; 378. } 379. if(!otmp) return(0); 380. otmp->in_use = TRUE; /* you've opened the stopper */ 381. 382. #define POTION_OCCUPANT_CHANCE(n) (13 + 2*(n)) /* also in muse.c */ 383. 384. potion_descr = OBJ_DESCR(objects[otmp->otyp]); 385. if (potion_descr) { 386. if (!strcmp(potion_descr, "milky") && 387. flags.ghost_count < MAXMONNO && 388. !rn2(POTION_OCCUPANT_CHANCE(flags.ghost_count))) { 389. ghost_from_bottle(); 390. if (carried(otmp)) useup(otmp); 391. else useupf(otmp, 1L); 392. return(1); 393. } else if (!strcmp(potion_descr, "smoky") && 394. (flags.djinni_count < MAXMONNO) && 395. !rn2(POTION_OCCUPANT_CHANCE(flags.djinni_count))) { 396. djinni_from_bottle(otmp); 397. if (carried(otmp)) useup(otmp); 398. else useupf(otmp, 1L); 399. return(1); 400. } 401. } 402. return dopotion(otmp); 403. } 404. 405. int 406. dopotion(otmp) 407. register struct obj *otmp; 408. { 409. int retval; 410. 411. otmp->in_use = TRUE; 412. nothing = unkn = 0; 413. 414. 415. if((retval = peffects(otmp)) >= 0) return(retval); 416. 417. if(nothing) { 418. unkn++; 419. You("have a %s feeling for a moment, then it passes.", 420. Hallucination ? "normal" : "peculiar"); 421. } 422. if(otmp->dknown && !objects[otmp->otyp].oc_name_known) { 423. if(!unkn) { 424. makeknown(otmp->otyp); 425. more_experienced(0,10); 426. } else if(!objects[otmp->otyp].oc_uname) 427. docall(otmp); 428. } 429. if (carried(otmp)) useup(otmp); 430. else if (mcarried(otmp)) m_useup(otmp->ocarry, otmp); 431. else if (otmp->where == OBJ_FLOOR) useupf(otmp, 1L); 432. else dealloc_obj(otmp); /* Dummy potion */ 433. return(1); 434. } 435. 436. /* return -1 if potion is used up, 0 if error, 1 not used */ 437. int 438. peffects(otmp) 439. register struct obj *otmp; 440. { 441. register int i, ii, lim; 442. 443. 444. /* KMH, balance patch -- this is too cruel for novices */ 445. #if 0 446. /* sometimes your constitution can be a little _too_ high! */ 447. if ((Role_if(PM_BARBARIAN) || ACURR(A_CON) > 15) && !rn2(5)) { 448. pline("Strange ..."); 449. nothing++; 450. return(-1); 451. } 452. #endif 453. 454. switch(otmp->otyp){ 455. case POT_RESTORE_ABILITY: 456. case SPE_RESTORE_ABILITY: 457. unkn++; 458. if(otmp->cursed) { 459. pline("Ulch! This makes you feel mediocre!"); 460. break; 461. } else { 462. pline("Wow! This makes you feel %s!", 463. (otmp->blessed) ? 464. (unfixable_trouble_count(FALSE) ? "better" : "great") 465. : "good"); 466. i = rn2(A_MAX); /* start at a random point */ 467. for (ii = 0; ii < A_MAX; ii++) { 468. lim = AMAX(i); 469. if (i == A_STR && u.uhs >= 3) --lim; /* WEAK */ 470. if (ABASE(i) < lim) { 471. ABASE(i) = lim; 472. flags.botl = 1; 473. /* only first found if not blessed */ 474. if (!otmp->blessed) break; 475. } 476. if(++i >= A_MAX) i = 0; 477. } 478. } 479. break; 480. case POT_HALLUCINATION: 481. if (Hallucination || Halluc_resistance) nothing++; 482. (void) make_hallucinated(itimeout_incr(HHallucination, 483. rn1(200, 600 - 300 * bcsign(otmp))), 484. TRUE, 0L); 485. break; 486. case POT_AMNESIA: 487. pline(Hallucination? "This tastes like champagne!" : 488. "This liquid bubbles and fizzes as you drink it."); 489. forget((!otmp->blessed? ALL_SPELLS : 0) | ALL_MAP); 490. if (Hallucination) 491. pline("Hakuna matata!"); 492. else 493. You_feel("your memories dissolve."); 494. 495. /* Blessed amnesia makes you forget lycanthropy, sickness */ 496. if (otmp->blessed) { 497. if (u.ulycn >= LOW_PM && !Race_if(PM_HUMAN_WEREWOLF)) { 498. You("forget your affinity to %s!", 499. makeplural(mons[u.ulycn].mname)); 500. if (youmonst.data == &mons[u.ulycn]) 501. you_unwere(FALSE); 502. u.ulycn = NON_PM; /* cure lycanthropy */ 503. } 504. make_sick(0L, (char *) 0, TRUE, SICK_ALL); 505. 506. /* You feel refreshed */ 507. u.uhunger += 50 + rnd(50); 508. newuhs(FALSE); 509. } else 510. exercise(A_WIS, FALSE); 511. break; 512. case POT_WATER: 513. if(!otmp->blessed && !otmp->cursed) { 514. pline("This tastes like water."); 515. u.uhunger += rnd(10); 516. newuhs(FALSE); 517. break; 518. } 519. unkn++; 520. if(is_undead(youmonst.data) || is_demon(youmonst.data) || 521. u.ualign.type == A_CHAOTIC) { 522. if(otmp->blessed) { 523. pline("This burns like acid!"); 524. exercise(A_CON, FALSE); 525. if (u.ulycn >= LOW_PM && !Race_if(PM_HUMAN_WEREWOLF)) { 526. Your("affinity to %s disappears!", 527. makeplural(mons[u.ulycn].mname)); 528. if (youmonst.data == &mons[u.ulycn]) 529. you_unwere(FALSE); 530. u.ulycn = NON_PM; /* cure lycanthropy */ 531. } 532. losehp(d(6,6), "potion of holy water", KILLED_BY_AN); 533. } else if(otmp->cursed) { 534. You_feel("quite proud of yourself."); 535. healup(d(6,6),0,0,0); 536. if (u.ulycn >= LOW_PM && !Upolyd) you_were(); 537. exercise(A_CON, TRUE); 538. } 539. } else { 540. if(otmp->blessed) { 541. You_feel("full of awe."); 542. if(u.ualign.type == A_LAWFUL) healup(d(6,6),0,0,0); 543. make_sick(0L, (char *) 0, TRUE, SICK_ALL); 544. exercise(A_WIS, TRUE); 545. exercise(A_CON, TRUE); 546. if (u.ulycn >= LOW_PM && !Race_if(PM_HUMAN_WEREWOLF)) { 547. you_unwere(TRUE); /* "Purified" */ 548. } 549. /* make_confused(0L,TRUE); */ 550. } else { 551. if(u.ualign.type == A_LAWFUL) { 552. pline("This burns like acid!"); 553. losehp(d(6,6), "potion of unholy water", 554. KILLED_BY_AN); 555. } else 556. You_feel("full of dread."); 557. if (u.ulycn >= LOW_PM && !Upolyd) you_were(); 558. exercise(A_CON, FALSE); 559. } 560. } 561. break; 562. case POT_BOOZE: 563. unkn++; 564. pline("Ooph! This tastes like %s%s!", 565. otmp->odiluted ? "watered down " : "", 566. Hallucination ? "dandelion wine" : "liquid fire"); 567. if (!otmp->blessed) 568. make_confused(itimeout_incr(HConfusion, d(3,8)), FALSE); 569. /* the whiskey makes us feel better */ 570. if (!otmp->odiluted) healup(1, 0, FALSE, FALSE); 571. u.uhunger += 10 * (2 + bcsign(otmp)); 572. newuhs(FALSE); 573. exercise(A_WIS, FALSE); 574. if(otmp->cursed) { 575. You("pass out."); 576. multi = -rnd(15); 577. nomovemsg = "You awake with a headache."; 578. } 579. break; 580. case POT_ENLIGHTENMENT: 581. if(otmp->cursed) { 582. unkn++; 583. You("have an uneasy feeling..."); 584. exercise(A_WIS, FALSE); 585. } else { 586. if (otmp->blessed) { 587. (void) adjattrib(A_INT, 1, FALSE); 588. (void) adjattrib(A_WIS, 1, FALSE); 589. } 590. You_feel("self-knowledgeable..."); 591. display_nhwindow(WIN_MESSAGE, FALSE); 592. enlightenment(0); 593. pline_The("feeling subsides."); 594. exercise(A_WIS, TRUE); 595. } 596. break; 597. case SPE_INVISIBILITY: 598. /* spell cannot penetrate mummy wrapping */ 599. if (BInvis && uarmc->otyp == MUMMY_WRAPPING) { 600. You_feel("rather itchy under your %s.", xname(uarmc)); 601. break; 602. } 603. /* FALLTHRU */ 604. case POT_INVISIBILITY: 605. if (Invis || Blind || BInvis) { 606. nothing++; 607. } else { 608. self_invis_message(); 609. } 610. if (otmp->blessed) HInvis |= FROMOUTSIDE; 611. else incr_itimeout(&HInvis, rn1(15,31)); 612. newsym(u.ux,u.uy); /* update position */ 613. if(otmp->cursed) { 614. pline("For some reason, you feel your presence is known."); 615. aggravate(); 616. } 617. break; 618. case POT_SEE_INVISIBLE: 619. /* tastes like fruit juice in Rogue */ 620. case POT_FRUIT_JUICE: 621. { 622. int msg = Invisible && !Blind; 623. 624. unkn++; 625. if (otmp->cursed) 626. pline("Yecch! This tastes %s.", 627. Hallucination ? "overripe" : "rotten"); 628. else 629. pline(Hallucination ? 630. "This tastes like 10%% real %s%s all-natural beverage." : 631. "This tastes like %s%s.", 632. otmp->odiluted ? "reconstituted " : "", 633. fruitname(TRUE)); 634. if (otmp->otyp == POT_FRUIT_JUICE) { 635. u.uhunger += (otmp->odiluted ? 5 : 10) * (2 + bcsign(otmp)); 636. newuhs(FALSE); 637. break; 638. } 639. if (!otmp->cursed) { 640. /* Tell them they can see again immediately, which 641. * will help them identify the potion... 642. */ 643. make_blinded(0L,TRUE); 644. } 645. if (otmp->blessed) 646. HSee_invisible |= FROMOUTSIDE; 647. else 648. incr_itimeout(&HSee_invisible, rn1(100,750)); 649. set_mimic_blocking(); /* do special mimic handling */ 650. see_monsters(); /* see invisible monsters */ 651. newsym(u.ux,u.uy); /* see yourself! */ 652. if (msg && !Blind) { /* Blind possible if polymorphed */ 653. You("can see through yourself, but you are visible!"); 654. unkn--; 655. } 656. break; 657. } 658. case POT_PARALYSIS: 659. if (Free_action) 660. You("stiffen momentarily."); 661. else { 662. if (Levitation || Is_airlevel(&u.uz)||Is_waterlevel(&u.uz)) 663. You("are motionlessly suspended."); 664. #ifdef STEED 665. else if (u.usteed) 666. You("are frozen in place!"); 667. #endif 668. else 669. Your("%s are frozen to the %s!", 670. makeplural(body_part(FOOT)), surface(u.ux, u.uy)); 671. nomul(-(rn1(10, 25 - 12*bcsign(otmp)))); 672. nomovemsg = You_can_move_again; 673. exercise(A_DEX, FALSE); 674. } 675. break; 676. case POT_SLEEPING: 677. if(Sleep_resistance || Free_action) 678. You("yawn."); 679. else { 680. You("suddenly fall asleep!"); 681. fall_asleep(-rn1(10, 25 - 12*bcsign(otmp)), TRUE); 682. } 683. break; 684. case POT_MONSTER_DETECTION: 685. case SPE_DETECT_MONSTERS: 686. if (otmp->blessed) { 687. int x, y; 688. 689. if (Detect_monsters) nothing++; 690. unkn++; 691. /* after a while, repeated uses become less effective */ 692. if (HDetect_monsters >= 300L) 693. i = 1; 694. else 695. i = rn1(40,21); 696. incr_itimeout(&HDetect_monsters, i); 697. for (x = 1; x < COLNO; x++) { 698. for (y = 0; y < ROWNO; y++) { 699. if (memory_is_invisible(x, y)) { 700. unmap_object(x, y); 701. newsym(x,y); 702. } 703. if (MON_AT(x,y)) unkn = 0; 704. } 705. } 706. see_monsters(); 707. if (unkn) You_feel("lonely."); 708. break; 709. } 710. if (monster_detect(otmp, 0)) 711. return(1); /* nothing detected */ 712. exercise(A_WIS, TRUE); 713. break; 714. case POT_OBJECT_DETECTION: 715. case SPE_DETECT_TREASURE: 716. if (object_detect(otmp, 0)) 717. return(1); /* nothing detected */ 718. exercise(A_WIS, TRUE); 719. break; 720. case POT_SICKNESS: 721. pline("Yecch! This stuff tastes like poison."); 722. if (otmp->blessed) { 723. pline("(But in fact it was mildly stale %s.)", 724. fruitname(TRUE)); 725. if (!Role_if(PM_HEALER)) { 726. /* NB: blessed otmp->fromsink is not possible */ 727. losehp(1, "mildly contaminated potion", KILLED_BY_AN); 728. } 729. } else { 730. if(Poison_resistance) 731. pline( 732. "(But in fact it was biologically contaminated %s.)", 733. fruitname(TRUE)); 734. if (Role_if(PM_HEALER)) 735. pline("Fortunately, you have been immunized."); 736. else { 737. int typ = rn2(A_MAX); 738. 739. if (!Fixed_abil) { 740. poisontell(typ); 741. (void) adjattrib(typ, 742. Poison_resistance ? -1 : -rn1(4,3), 743. TRUE); 744. } 745. if(!Poison_resistance) { 746. if (otmp->fromsink) 747. losehp(rnd(10)+5*!!(otmp->cursed), 748. "contaminated tap water", KILLED_BY); 749. else 750. losehp(rnd(10)+5*!!(otmp->cursed), 751. "contaminated potion", KILLED_BY_AN); 752. } 753. exercise(A_CON, FALSE); 754. } 755. } 756. if(Hallucination) { 757. You("are shocked back to your senses!"); 758. (void) make_hallucinated(0L,FALSE,0L); 759. } 760. break; 761. case POT_CONFUSION: 762. if(!Confusion) { 763. if (Hallucination) { 764. pline("What a trippy feeling!"); 765. unkn++; 766. } else 767. pline("Huh, What? Where am I?"); 768. } else nothing++; 769. make_confused(itimeout_incr(HConfusion, 770. rn1(7, 16 - 8 * bcsign(otmp))), 771. FALSE); 772. break; 773. case POT_CLAIRVOYANCE: 774. /* KMH -- handle cursed, blessed, blocked */ 775. if (otmp->cursed) 776. nothing++; 777. else if (!BClairvoyant) { 778. if (Hallucination) pline("Dude! See-through walls!"); 779. do_vicinity_map(); 780. } 781. if (otmp->blessed) 782. incr_itimeout(&HClairvoyant, rn1(50, 100)); 783. break; 784. case POT_ESP: 785. { 786. const char *mod; 787. 788. /* KMH -- handle cursed, blessed */ 789. if (otmp->cursed) { 790. if (HTelepat) mod = "less "; 791. else { 792. unkn++; 793. mod = NULL; 794. } 795. HTelepat = 0; 796. } else if (otmp->blessed) { 797. mod = "fully "; 798. incr_itimeout(&HTelepat, rn1(100, 200)); 799. HTelepat |= FROMOUTSIDE; 800. } else { 801. mod = "more "; 802. incr_itimeout(&HTelepat, rn1(50, 100)); 803. } 804. if (mod) 805. You_feel(Hallucination ? 806. "%sin touch with the cosmos." : 807. "%smentally acute.", mod); 808. see_monsters(); 809. break; 810. } 811. /* KMH, balance patch -- removed 812. case POT_FIRE_RESISTANCE: 813. if(!(HFire_resistance & FROMOUTSIDE)) { 814. if (Hallucination) 815. pline("You feel, like, totally cool!"); 816. else You("feel cooler."); 817. HFire_resistance += rn1(100,50); 818. unkn++; 819. HFire_resistance |= FROMOUTSIDE; 820. } 821. break;*/ 822. case POT_INVULNERABILITY: 823. incr_itimeout(&Invulnerable, rn1(4, 8 + 4 * bcsign(otmp))); 824. You_feel(Hallucination ? 825. "like a super-duper hero!" : "invulnerable!"); 826. break; 827. case POT_GAIN_ABILITY: 828. if(otmp->cursed) { 829. pline("Ulch! That potion tasted foul!"); 830. unkn++; 831. } else if (Fixed_abil) { 832. nothing++; 833. } else { /* If blessed, increase all; if not, try up to */ 834. int itmp; /* 6 times to find one which can be increased. */ 835. i = -1; /* increment to 0 */ 836. for (ii = A_MAX; ii > 0; ii--) { 837. i = (otmp->blessed ? i + 1 : rn2(A_MAX)); 838. /* only give "your X is already as high as it can get" 839. message on last attempt (except blessed potions) */ 840. itmp = (otmp->blessed || ii == 1) ? 0 : -1; 841. if (adjattrib(i, 1, itmp) && !otmp->blessed) 842. break; 843. } 844. } 845. break; 846. case POT_SPEED: 847. if(Wounded_legs && !otmp->cursed 848. #ifdef STEED 849. && !u.usteed /* heal_legs() would heal steeds legs */ 850. #endif 851. ) { 852. heal_legs(); 853. unkn++; 854. break; 855. } /* and fall through */ 856. case SPE_HASTE_SELF: 857. if (!Very_fast) 858. You("are suddenly moving %sfaster.", 859. Fast ? "" : "much "); 860. else { 861. Your("%s get new energy.", 862. makeplural(body_part(LEG))); 863. unkn++; 864. } 865. exercise(A_DEX, TRUE); 866. incr_itimeout(&HFast, rn1(10, 100 + 60 * bcsign(otmp))); 867. break; 868. case POT_BLINDNESS: 869. if(Blind) nothing++; 870. make_blinded(itimeout_incr(Blinded, 871. rn1(200, 250 - 125 * bcsign(otmp))), 872. (boolean)!Blind); 873. break; 874. 875. case POT_GAIN_LEVEL: 876. if (otmp->cursed) { 877. unkn++; 878. /* they went up a level */ 879. if((ledger_no(&u.uz) == 1 && u.uhave.amulet) || 880. Can_rise_up(u.ux, u.uy, &u.uz)) { 881. const char *riseup ="rise up, through the %s!"; 882. /* [ALI] Special handling for quaffing potions 883. * off the floor (otmp won't be valid after 884. * we change levels otherwise). 885. */ 886. if (otmp->where == OBJ_FLOOR) { 887. if (otmp->quan > 1) 888. (void) splitobj(otmp, 1); 889. /* Make sure you're charged if in shop */ 890. otmp->quan++; 891. useupf(otmp, 1); 892. obj_extract_self(otmp); 893. } 894. if(ledger_no(&u.uz) == 1) { 895. You(riseup, ceiling(u.ux,u.uy)); 896. goto_level(&earth_level, FALSE, FALSE, FALSE); 897. } else { 898. register int newlev = depth(&u.uz)-1; 899. d_level newlevel; 900. 901. get_level(&newlevel, newlev); 902. if(on_level(&newlevel, &u.uz)) { 903. pline("It tasted bad."); 904. break; 905. } else You(riseup, ceiling(u.ux,u.uy)); 906. goto_level(&newlevel, FALSE, FALSE, FALSE); 907. } 908. } 909. else You("have an uneasy feeling."); 910. break; 911. } 912. pluslvl(FALSE); 913. if (otmp->blessed) 914. /* blessed potions place you at a random spot in the 915. * middle of the new level instead of the low point 916. */ 917. u.uexp = rndexp(TRUE); 918. break; 919. case POT_HEALING: 920. You_feel("better."); 921. healup(d(5,6) + 5 * bcsign(otmp), 922. !otmp->cursed ? 1 : 0, 1+1*!!otmp->blessed, !otmp->cursed); 923. exercise(A_CON, TRUE); 924. break; 925. case POT_EXTRA_HEALING: 926. You_feel("much better."); 927. healup(d(6,8) + 5 * bcsign(otmp), 928. otmp->blessed ? 5 : !otmp->cursed ? 2 : 0, 929. !otmp->cursed, TRUE); 930. (void) make_hallucinated(0L,TRUE,0L); 931. exercise(A_CON, TRUE); 932. exercise(A_STR, TRUE); 933. break; 934. case POT_FULL_HEALING: 935. You_feel("completely healed."); 936. healup(400, 4+4*bcsign(otmp), !otmp->cursed, TRUE); 937. /* Restore one lost level if blessed */ 938. if (otmp->blessed && u.ulevel < u.ulevelmax) { 939. /* when multiple levels have been lost, drinking 940. multiple potions will only get half of them back */ 941. u.ulevelmax -= 1; 942. pluslvl(FALSE); 943. } 944. (void) make_hallucinated(0L,TRUE,0L); 945. exercise(A_STR, TRUE); 946. exercise(A_CON, TRUE); 947. break; 948. case POT_LEVITATION: 949. case SPE_LEVITATION: 950. if (otmp->cursed) HLevitation &= ~I_SPECIAL; 951. if(!Levitation) { 952. /* kludge to ensure proper operation of float_up() */ 953. HLevitation = 1; 954. float_up(); 955. /* reverse kludge */ 956. HLevitation = 0; 957. if (otmp->cursed && !Is_waterlevel(&u.uz)) { 958. if((u.ux != xupstair || u.uy != yupstair) 959. && (u.ux != sstairs.sx || u.uy != sstairs.sy || !sstairs.up) 960. && (!xupladder || u.ux != xupladder || u.uy != yupladder) 961. ) { 962. You("hit your %s on the %s.", 963. body_part(HEAD), 964. ceiling(u.ux,u.uy)); 965. losehp(uarmh ? 1 : rnd(10), 966. "colliding with the ceiling", 967. KILLED_BY); 968. } else (void) doup(); 969. } 970. } else 971. nothing++; 972. if (otmp->blessed) { 973. incr_itimeout(&HLevitation, rn1(50,250)); 974. HLevitation |= I_SPECIAL; 975. } else incr_itimeout(&HLevitation, rn1(140,10)); 976. spoteffects(FALSE); /* for sinks */ 977. break; 978. case POT_GAIN_ENERGY: /* M. Stephenson */ 979. { register int num , num2; 980. if(otmp->cursed) 981. You_feel("lackluster."); 982. else 983. pline("Magical energies course through your body."); 984. num = rnd(25) + 5 * otmp->blessed + 10; 985. num2 = rnd(2) + 2 * otmp->blessed + 1; 986. u.uenmax += (otmp->cursed) ? -num2 : num2; 987. u.uen += (otmp->cursed) ? -num : num; 988. if(u.uenmax <= 0) u.uenmax = 0; 989. if(u.uen <= 0) u.uen = 0; 990. if(u.uen > u.uenmax) { 991. u.uenmax += ((u.uen - u.uenmax) / 2); 992. u.uen = u.uenmax; 993. } 994. flags.botl = 1; 995. exercise(A_WIS, TRUE); 996. } 997. break; 998. case POT_OIL: /* P. Winner */ 999. { 1000. boolean good_for_you = FALSE; 1001. 1002. if (otmp->lamplit) { 1003. if (likes_fire(youmonst.data)) { 1004. pline("Ahh, a refreshing drink."); 1005. good_for_you = TRUE; 1006. } else { 1007. You("burn your %s.", body_part(FACE)); 1008. losehp(d(Fire_resistance ? 1 : 3, 4), 1009. "burning potion of oil", KILLED_BY_AN); 1010. } 1011. } else if(otmp->cursed) 1012. pline("This tastes like castor oil."); 1013. else 1014. pline("That was smooth!"); 1015. exercise(A_WIS, good_for_you); 1016. } 1017. break; 1018. case POT_ACID: 1019. if (Acid_resistance) 1020. /* Not necessarily a creature who _likes_ acid */ 1021. pline("This tastes %s.", Hallucination ? "tangy" : "sour"); 1022. else { 1023. pline("This burns%s!", otmp->blessed ? " a little" : 1024. otmp->cursed ? " a lot" : " like acid"); 1025. losehp(d(otmp->cursed ? 2 : 1, otmp->blessed ? 4 : 8), 1026. "potion of acid", KILLED_BY_AN); 1027. exercise(A_CON, FALSE); 1028. } 1029. if (Stoned) fix_petrification(); 1030. unkn++; /* holy/unholy water can burn like acid too */ 1031. break; 1032. case POT_POLYMORPH: 1033. You_feel("a little %s.", Hallucination ? "normal" : "strange"); 1034. if (!Unchanging) polyself(FALSE); 1035. break; 1036. case POT_BLOOD: 1037. case POT_VAMPIRE_BLOOD: 1038. unkn++; 1039. u.uconduct.unvegan++; 1040. if (maybe_polyd(is_vampire(youmonst.data), Race_if(PM_VAMPIRE))) { 1041. violated_vegetarian(); 1042. if (otmp->cursed) 1043. pline("Yecch! This %s.", Hallucination ? 1044. "liquid could do with a good stir" : "blood has congealed"); 1045. else pline(Hallucination ? 1046. "The %s liquid stirs memories of home." : 1047. "The %s blood tastes delicious.", 1048. otmp->odiluted ? "watery" : "thick"); 1049. if (!otmp->cursed) 1050. lesshungry((otmp->odiluted ? 1 : 2) * 1051. (otmp->otyp == POT_VAMPIRE_BLOOD ? 400 : 1052. otmp->blessed ? 15 : 10)); 1053. if (otmp->otyp == POT_VAMPIRE_BLOOD && otmp->blessed) { 1054. int num = newhp(); 1055. if (Upolyd) { 1056. u.mhmax += num; 1057. u.mh += num; 1058. } else { 1059. u.uhpmax += num; 1060. u.uhp += num; 1061. } 1062. } 1063. } else if (otmp->otyp == POT_VAMPIRE_BLOOD) { 1064. /* [CWC] fix conducts for potions of (vampire) blood - 1065. doesn't use violated_vegetarian() to prevent 1066. duplicated "you feel guilty" messages */ 1067. u.uconduct.unvegetarian++; 1068. if (u.ualign.type == A_LAWFUL || Role_if(PM_MONK)) { 1069. You_feel("%sguilty about drinking such a vile liquid.", 1070. Role_if(PM_MONK) ? "especially " : ""); 1071. u.ugangr++; 1072. adjalign(-15); 1073. } else if (u.ualign.type == A_NEUTRAL) 1074. adjalign(-3); 1075. exercise(A_CON, FALSE); 1076. if (!Unchanging && polymon(PM_VAMPIRE)) 1077. u.mtimedone = 0; /* "Permament" change */ 1078. } else { 1079. violated_vegetarian(); 1080. pline("Ugh. That was vile."); 1081. make_vomiting(Vomiting+d(10,8), TRUE); 1082. } 1083. break; 1084. default: 1085. impossible("What a funny potion! (%u)", otmp->otyp); 1086. return(0); 1087. } 1088. return(-1); 1089. } 1090. 1091. void 1092. healup(nhp, nxtra, curesick, cureblind) 1093. int nhp, nxtra; 1094. register boolean curesick, cureblind; 1095. { 1096. if (nhp) { 1097. if (Upolyd) { 1098. u.mh += nhp; 1099. if(u.mh > u.mhmax) u.mh = (u.mhmax += nxtra); 1100. } else { 1101. u.uhp += nhp; 1102. if(u.uhp > u.uhpmax) u.uhp = (u.uhpmax += nxtra); 1103. } 1104. } 1105. if(cureblind) make_blinded(0L,TRUE); 1106. if(curesick) make_sick(0L, (char *) 0, TRUE, SICK_ALL); 1107. flags.botl = 1; 1108. return; 1109. } 1110. 1111. void 1112. healup_mon(mtmp, nhp, nxtra, curesick, cureblind) 1113. struct monst *mtmp; 1114. int nhp, nxtra; 1115. register boolean curesick, cureblind; 1116. { 1117. if (nhp) { 1118. mtmp->mhp += nhp; 1119. if (mtmp->mhp > mtmp->mhpmax) mtmp->mhp = (mtmp->mhpmax += nxtra); 1120. } 1121. #if 0 1122. if(cureblind) ; /* NOT DONE YET */ 1123. if(curesick) ; /* NOT DONE YET */ 1124. #endif 1125. return; 1126. } 1127. 1128. void 1129. strange_feeling(obj,txt) 1130. register struct obj *obj; 1131. register const char *txt; 1132. { 1133. if (flags.beginner || !txt) 1134. You("have a %s feeling for a moment, then it passes.", 1135. Hallucination ? "normal" : "strange"); 1136. else 1137. pline(txt); 1138. 1139. if(!obj) /* e.g., crystal ball finds no traps */ 1140. return; 1141. 1142. if(obj->dknown && !objects[obj->otyp].oc_name_known && 1143. !objects[obj->otyp].oc_uname) 1144. docall(obj); 1145. if (carried(obj)) useup(obj); 1146. else useupf(obj, 1L); 1147. } 1148. 1149. const char *bottlenames[] = { 1150. "bottle", "phial", "flagon", "carafe", "flask", "jar", "vial" 1151. }; 1152. 1153. const char * 1154. bottlename() 1155. { 1156. return bottlenames[rn2(SIZE(bottlenames))]; 1157. } 1158. 1159. /* WAC -- monsters can throw potions around too! */ 1160. void 1161. potionhit(mon, obj, your_fault) 1162. register struct monst *mon; /* Monster that got hit */ 1163. register struct obj *obj; 1164. boolean your_fault; 1165. { 1166. register const char *botlnam = bottlename(); 1167. boolean isyou = (mon == &youmonst); 1168. int distance; 1169. 1170. if(isyou) { 1171. distance = 0; 1172. pline_The("%s crashes on your %s and breaks into shards.", 1173. botlnam, body_part(HEAD)); 1174. losehp(rnd(2), "thrown potion", KILLED_BY_AN); 1175. } else { 1176. distance = distu(mon->mx,mon->my); 1177. if (!cansee(mon->mx,mon->my)) pline("Crash!"); 1178. else { 1179. char *mnam = mon_nam(mon); 1180. char buf[BUFSZ]; 1181. 1182. if(has_head(mon->data)) { 1183. Sprintf(buf, "%s %s", 1184. s_suffix(mnam), 1185. (notonhead ? "body" : "head")); 1186. } else { 1187. Strcpy(buf, mnam); 1188. } 1189. pline_The("%s crashes on %s and breaks into shards.", 1190. botlnam, buf); 1191. } 1192. if(rn2(5) && mon->mhp > 1) 1193. mon->mhp--; 1194. } 1195. 1196. /* oil doesn't instantly evaporate */ 1197. if (obj->otyp != POT_OIL && cansee(mon->mx,mon->my)) 1198. pline("%s.", Tobjnam(obj, "evaporate")); 1199. 1200. if (isyou) { 1201. switch (obj->otyp) { 1202. case POT_OIL: 1203. if (obj->lamplit) 1204. splatter_burning_oil(u.ux, u.uy); 1205. break; 1206. case POT_POLYMORPH: 1207. You_feel("a little %s.", Hallucination ? "normal" : "strange"); 1208. if (!Unchanging && !Antimagic) polyself(FALSE); 1209. break; 1210. case POT_ACID: 1211. if (!Acid_resistance) { 1212. pline("This burns%s!", obj->blessed ? " a little" : 1213. obj->cursed ? " a lot" : ""); 1214. losehp(d(obj->cursed ? 2 : 1, obj->blessed ? 4 : 8), 1215. "potion of acid", KILLED_BY_AN); 1216. } 1217. break; 1218. case POT_AMNESIA: 1219. /* Uh-oh! */ 1220. if (uarmh && is_helmet(uarmh) && 1221. rn2(10 - (uarmh->cursed? 8 : 0))) 1222. get_wet(uarmh, TRUE); 1223. break; 1224. } 1225. } else { 1226. boolean angermon = TRUE; 1227. 1228. if (!your_fault) angermon = FALSE; 1229. switch (obj->otyp) { 1230. case POT_HEALING: 1231. do_healing: 1232. if (mon->data == &mons[PM_PESTILENCE]) goto do_illness; 1233. angermon = FALSE; 1234. if (canseemon(mon)) 1235. pline("%s looks better.", Monnam(mon)); 1236. healup_mon(mon, d(5,6) + 5 * bcsign(obj), 1237. !obj->cursed ? 1 : 0, 1+1*!!obj->blessed, !obj->cursed); 1238. break; 1239. case POT_EXTRA_HEALING: 1240. if (mon->data == &mons[PM_PESTILENCE]) goto do_illness; 1241. angermon = FALSE; 1242. if (canseemon(mon)) 1243. pline("%s looks much better.", Monnam(mon)); 1244. healup_mon(mon, d(6,8) + 5 * bcsign(obj), 1245. obj->blessed ? 5 : !obj->cursed ? 2 : 0, 1246. !obj->cursed, TRUE); 1247. break; 1248. case POT_FULL_HEALING: 1249. if (mon->data == &mons[PM_PESTILENCE]) goto do_illness; 1250. /*FALLTHRU*/ 1251. case POT_RESTORE_ABILITY: 1252. case POT_GAIN_ABILITY: 1253. angermon = FALSE; 1254. if (canseemon(mon)) 1255. pline("%s looks sound and hale again.", Monnam(mon)); 1256. healup_mon(mon, 400, 5+5*!!(obj->blessed), !(obj->cursed), 1); 1257. break; 1258. case POT_SICKNESS: 1259. if (mon->data == &mons[PM_PESTILENCE]) goto do_healing; 1260. if (dmgtype(mon->data, AD_DISE) || 1261. dmgtype(mon->data, AD_PEST) || /* won't happen, see prior goto */ 1262. resists_poison(mon)) { 1263. if (canseemon(mon)) 1264. pline("%s looks unharmed.", Monnam(mon)); 1265. break; 1266. } 1267. do_illness: 1268. if((mon->mhpmax > 3) && !resist(mon, POTION_CLASS, 0, NOTELL)) 1269. mon->mhpmax /= 2; 1270. if((mon->mhp > 2) && !resist(mon, POTION_CLASS, 0, NOTELL)) 1271. mon->mhp /= 2; 1272. if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax; 1273. if (canseemon(mon)) 1274. pline("%s looks rather ill.", Monnam(mon)); 1275. break; 1276. case POT_CONFUSION: 1277. case POT_BOOZE: 1278. if(!resist(mon, POTION_CLASS, 0, NOTELL)) mon->mconf = TRUE; 1279. break; 1280. #if 0 /* NH 3.3.0 version */ 1281. case POT_POLYMORPH: 1282. (void) bhitm(mon, obj); 1283. break; 1284. #endif 1285. case POT_POLYMORPH: 1286. /* [Tom] polymorph potion thrown 1287. * [max] added poor victim a chance to resist 1288. * magic resistance protects from polymorph traps, so make 1289. * it guard against involuntary polymorph attacks too... 1290. */ 1291. if (resists_magm(mon)) { 1292. shieldeff(mon->mx, mon->my); 1293. } else if (!resist (mon, POTION_CLASS, 0, NOTELL)) { 1294. mon_poly(mon, your_fault, "%s changes!"); 1295. if (!Hallucination && canspotmon (mon)) 1296. makeknown (POT_POLYMORPH); 1297. } 1298. break; 1299. case POT_INVISIBILITY: 1300. angermon = FALSE; 1301. mon_set_minvis(mon); 1302. break; 1303. case POT_SLEEPING: 1304. /* wakeup() doesn't rouse victims of temporary sleep */ 1305. if (sleep_monst(mon, rnd(12), POTION_CLASS)) { 1306. pline("%s falls asleep.", Monnam(mon)); 1307. slept_monst(mon); 1308. } 1309. break; 1310. case POT_PARALYSIS: 1311. if (mon->mcanmove) { 1312. mon->mcanmove = 0; 1313. /* really should be rnd(5) for consistency with players 1314. * breathing potions, but... 1315. */ 1316. mon->mfrozen = rnd(25); 1317. } 1318. break; 1319. case POT_SPEED: 1320. angermon = FALSE; 1321. mon_adjust_speed(mon, 1, obj); 1322. break; 1323. case POT_BLINDNESS: 1324. if(haseyes(mon->data)) { 1325. register int btmp = 64 + rn2(32) + 1326. rn2(32) * !resist(mon, POTION_CLASS, 0, NOTELL); 1327. btmp += mon->mblinded; 1328. mon->mblinded = min(btmp,127); 1329. mon->mcansee = 0; 1330. } 1331. break; 1332. case POT_WATER: 1333. if (is_undead(mon->data) || is_demon(mon->data) || 1334. is_were(mon->data)) { 1335. if (obj->blessed) { 1336. pline("%s %s in pain!", Monnam(mon), 1337. is_silent(mon->data) ? "writhes" : "shrieks"); 1338. mon->mhp -= d(2,6); 1339. if (mon->mhp < 1) { 1340. if (your_fault) 1341. killed(mon); 1342. else 1343. monkilled(mon, "", AD_ACID); 1344. } 1345. else if (is_were(mon->data) && !is_human(mon->data)) 1346. new_were(mon); /* revert to human */ 1347. } else if (obj->cursed) { 1348. angermon = FALSE; 1349. if (canseemon(mon)) 1350. pline("%s looks healthier.", Monnam(mon)); 1351. mon->mhp += d(2,6); 1352. if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax; 1353. if (is_were(mon->data) && is_human(mon->data) && 1354. !Protection_from_shape_changers) 1355. new_were(mon); /* transform into beast */ 1356. } 1357. } else if(mon->data == &mons[PM_GREMLIN]) { 1358. angermon = FALSE; 1359. (void)split_mon(mon, (struct monst *)0); 1360. } else if(mon->data == &mons[PM_FLAMING_SPHERE] || 1361. mon->data == &mons[PM_IRON_GOLEM]) { 1362. if (canseemon(mon)) 1363. pline("%s %s.", Monnam(mon), 1364. mon->data == &mons[PM_IRON_GOLEM] ? 1365. "rusts" : "flickers"); 1366. mon->mhp -= d(1,6); 1367. if (mon->mhp < 1) { 1368. if (your_fault) 1369. killed(mon); 1370. else 1371. monkilled(mon, "", AD_ACID); 1372. } 1373. } 1374. break; 1375. case POT_AMNESIA: 1376. switch (monsndx(mon->data)) { 1377. case PM_GREMLIN: 1378. /* Gremlins multiply... */ 1379. mon->mtame = FALSE; 1380. (void)split_mon(mon, (struct monst *)0); 1381. break; 1382. case PM_FLAMING_SPHERE: 1383. case PM_IRON_GOLEM: 1384. if (canseemon(mon)) pline("%s %s.", Monnam(mon), 1385. monsndx(mon->data) == PM_IRON_GOLEM ? 1386. "rusts" : "flickers"); 1387. mon->mhp -= d(1,6); 1388. if (mon->mhp < 1) 1389. if (your_fault) 1390. killed(mon); 1391. else 1392. monkilled(mon, "", AD_ACID); 1393. else 1394. mon->mtame = FALSE; 1395. break; 1396. case PM_WIZARD_OF_YENDOR: 1397. if (your_fault) { 1398. if (canseemon(mon)) 1399. pline("%s laughs at you!", Monnam(mon)); 1400. forget(1); 1401. } 1402. break; 1403. case PM_MEDUSA: 1404. if (canseemon(mon)) 1405. pline("%s looks like %s's having a bad hair day!", 1406. Monnam(mon), mhe(mon)); 1407. break; 1408. case PM_CROESUS: 1409. if (canseemon(mon)) 1410. pline("%s says: 'My gold! I must count my gold!'", 1411. Monnam(mon)); 1412. break; 1413. case PM_DEATH: 1414. if (canseemon(mon)) 1415. pline("%s pauses, then looks at you thoughtfully!", 1416. Monnam(mon)); 1417. break; 1418. case PM_FAMINE: 1419. if (canseemon(mon)) 1420. pline("%s looks unusually hungry!", Monnam(mon)); 1421. break; 1422. case PM_PESTILENCE: 1423. if (canseemon(mon)) 1424. pline("%s looks unusually well!", Monnam(mon)); 1425. break; 1426. default: 1427. if (mon->data->msound == MS_NEMESIS && canseemon(mon) 1428. && your_fault) 1429. pline("%s curses your ancestors!", Monnam(mon)); 1430. else if (mon->isshk) { 1431. angermon = FALSE; 1432. if (canseemon(mon)) 1433. pline("%s looks at you curiously!", 1434. Monnam(mon)); 1435. make_happy_shk(mon, FALSE); 1436. } else if (!is_covetous(mon->data) && !rn2(4) && 1437. !resist(mon, POTION_CLASS, 0, 0)) { 1438. angermon = FALSE; 1439. if (canseemon(mon)) { 1440. if (mon->msleeping) { 1441. wakeup(mon); 1442. pline("%s wakes up looking bewildered!", 1443. Monnam(mon)); 1444. } else 1445. pline("%s looks bewildered!", Monnam(mon)); 1446. mon->mpeaceful = TRUE; 1447. mon->mtame = FALSE; 1448. } 1449. } 1450. break; 1451. } 1452. break; 1453. case POT_OIL: 1454. if (obj->lamplit) 1455. splatter_burning_oil(mon->mx, mon->my); 1456. break; 1457. /* 1458. case POT_GAIN_LEVEL: 1459. case POT_LEVITATION: 1460. case POT_FRUIT_JUICE: 1461. case POT_MONSTER_DETECTION: 1462. case POT_OBJECT_DETECTION: 1463. break; 1464. */ 1465. /* KMH, balance patch -- added */ 1466. case POT_ACID: 1467. if (!resists_acid(mon) && !resist(mon, POTION_CLASS, 0, NOTELL)) { 1468. pline("%s %s in pain!", Monnam(mon), 1469. is_silent(mon->data) ? "writhes" : "shrieks"); 1470. mon->mhp -= d(obj->cursed ? 2 : 1, obj->blessed ? 4 : 8); 1471. if (mon->mhp < 1) { 1472. if (your_fault) 1473. killed(mon); 1474. else 1475. monkilled(mon, "", AD_ACID); 1476. } 1477. } 1478. break; 1479. } 1480. if (angermon) 1481. wakeup(mon); 1482. else 1483. mon->msleeping = 0; 1484. } 1485. 1486. /* Note: potionbreathe() does its own docall() */ 1487. if ((distance==0 || ((distance < 3) && rn2(5))) && 1488. (!breathless(youmonst.data) || haseyes(youmonst.data))) 1489. potionbreathe(obj); 1490. else if (obj->dknown && !objects[obj->otyp].oc_name_known && 1491. !objects[obj->otyp].oc_uname && cansee(mon->mx,mon->my)) 1492. docall(obj); 1493. if(*u.ushops && obj->unpaid) { 1494. register struct monst *shkp = 1495. shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE)); 1496. 1497. if(!shkp) 1498. obj->unpaid = 0; 1499. else { 1500. (void)stolen_value(obj, u.ux, u.uy, 1501. (boolean)shkp->mpeaceful, FALSE, TRUE); 1502. subfrombill(obj, shkp); 1503. } 1504. } 1505. obfree(obj, (struct obj *)0); 1506. } 1507. 1508. /* vapors are inhaled or get in your eyes */ 1509. void 1510. potionbreathe(obj) 1511. register struct obj *obj; 1512. { 1513. register int i, ii, isdone, kn = 0; 1514. 1515. switch(obj->otyp) { 1516. case POT_RESTORE_ABILITY: 1517. case POT_GAIN_ABILITY: 1518. if(obj->cursed) { 1519. if (!breathless(youmonst.data)) 1520. pline("Ulch! That potion smells terrible!"); 1521. else if (haseyes(youmonst.data)) { 1522. int numeyes = eyecount(youmonst.data); 1523. Your("%s sting%s!", 1524. (numeyes == 1) ? body_part(EYE) : makeplural(body_part(EYE)), 1525. (numeyes == 1) ? "s" : ""); 1526. } 1527. break; 1528. } else { 1529. i = rn2(A_MAX); /* start at a random point */ 1530. for(isdone = ii = 0; !isdone && ii < A_MAX; ii++) { 1531. if(ABASE(i) < AMAX(i)) { 1532. ABASE(i)++; 1533. /* only first found if not blessed */ 1534. isdone = !(obj->blessed); 1535. flags.botl = 1; 1536. } 1537. if(++i >= A_MAX) i = 0; 1538. } 1539. } 1540. break; 1541. case POT_FULL_HEALING: 1542. if (Upolyd && u.mh < u.mhmax) u.mh++, flags.botl = 1; 1543. if (u.uhp < u.uhpmax) u.uhp++, flags.botl = 1; 1544. /*FALL THROUGH*/ 1545. case POT_EXTRA_HEALING: 1546. if (Upolyd && u.mh < u.mhmax) u.mh++, flags.botl = 1; 1547. if (u.uhp < u.uhpmax) u.uhp++, flags.botl = 1; 1548. /*FALL THROUGH*/ 1549. case POT_HEALING: 1550. if (Upolyd && u.mh < u.mhmax) u.mh++, flags.botl = 1; 1551. if (u.uhp < u.uhpmax) u.uhp++, flags.botl = 1; 1552. exercise(A_CON, TRUE); 1553. break; 1554. case POT_SICKNESS: 1555. if (!Role_if(PM_HEALER)) { 1556. if (Upolyd) { 1557. if (u.mh <= 5) u.mh = 1; else u.mh -= 5; 1558. } else { 1559. if (u.uhp <= 5) u.uhp = 1; else u.uhp -= 5; 1560. } 1561. flags.botl = 1; 1562. exercise(A_CON, FALSE); 1563. } 1564. break; 1565. case POT_HALLUCINATION: 1566. You("have a momentary vision."); 1567. break; 1568. case POT_CONFUSION: 1569. case POT_BOOZE: 1570. if(!Confusion) 1571. You_feel("somewhat dizzy."); 1572. make_confused(itimeout_incr(HConfusion, rnd(5)), FALSE); 1573. break; 1574. case POT_INVISIBILITY: 1575. if (!Blind && !Invis) { 1576. kn++; 1577. pline("For an instant you %s!", 1578. See_invisible ? "could see right through yourself" 1579. : "couldn't see yourself"); 1580. } 1581. break; 1582. case POT_PARALYSIS: 1583. kn++; 1584. if (!Free_action) { 1585. pline("%s seems to be holding you.", Something); 1586. nomul(-rnd(5)); 1587. nomovemsg = You_can_move_again; 1588. exercise(A_DEX, FALSE); 1589. } else You("stiffen momentarily."); 1590. break; 1591. case POT_SLEEPING: 1592. kn++; 1593. if (!Free_action && !Sleep_resistance) { 1594. You_feel("rather tired."); 1595. nomul(-rnd(5)); 1596. nomovemsg = You_can_move_again; 1597. exercise(A_DEX, FALSE); 1598. } else You("yawn."); 1599. break; 1600. case POT_SPEED: 1601. if (!Fast) Your("knees seem more flexible now."); 1602. incr_itimeout(&HFast, rnd(5)); 1603. exercise(A_DEX, TRUE); 1604. break; 1605. case POT_BLINDNESS: 1606. if (!Blind && !u.usleep) { 1607. kn++; 1608. pline("It suddenly gets dark."); 1609. } 1610. make_blinded(itimeout_incr(Blinded, rnd(5)), FALSE); 1611. if (!Blind && !u.usleep) Your(vision_clears); 1612. break; 1613. case POT_WATER: 1614. if(u.umonnum == PM_GREMLIN) { 1615. (void)split_mon(&youmonst, (struct monst *)0); 1616. } else if (u.ulycn >= LOW_PM) { 1617. /* vapor from [un]holy water will trigger 1618. transformation but won't cure lycanthropy */ 1619. if (obj->blessed && youmonst.data == &mons[u.ulycn]) 1620. you_unwere(FALSE); 1621. else if (obj->cursed && !Upolyd) 1622. you_were(); 1623. } 1624. break; 1625. case POT_AMNESIA: 1626. if(u.umonnum == PM_GREMLIN) 1627. (void)split_mon(&youmonst, (struct monst *)0); 1628. else if(u.umonnum == PM_FLAMING_SPHERE) { 1629. You("flicker!"); 1630. losehp(d(1,6),"potion of amnesia", KILLED_BY_AN); 1631. } else if(u.umonnum == PM_IRON_GOLEM) { 1632. You("rust!"); 1633. losehp(d(1,6),"potion of amnesia", KILLED_BY_AN); 1634. } 1635. You_feel("dizzy!"); 1636. forget(1 + rn2(5)); 1637. break; 1638. case POT_ACID: 1639. case POT_POLYMORPH: 1640. exercise(A_CON, FALSE); 1641. break; 1642. case POT_BLOOD: 1643. case POT_VAMPIRE_BLOOD: 1644. if (maybe_polyd(is_vampire(youmonst.data), Race_if(PM_VAMPIRE))) { 1645. exercise(A_WIS, FALSE); 1646. You_feel("a %ssense of loss.", 1647. obj->otyp == POT_VAMPIRE_BLOOD ? "terrible " : ""); 1648. } else 1649. exercise(A_CON, FALSE); 1650. break; 1651. /* 1652. case POT_GAIN_LEVEL: 1653. case POT_LEVITATION: 1654. case POT_FRUIT_JUICE: 1655. case POT_MONSTER_DETECTION: 1656. case POT_OBJECT_DETECTION: 1657. case POT_OIL: 1658. break; 1659. */ 1660. } 1661. /* note: no obfree() */ 1662. if (obj->dknown) { 1663. if (kn) 1664. makeknown(obj->otyp); 1665. else if (!objects[obj->otyp].oc_name_known && 1666. !objects[obj->otyp].oc_uname) 1667. docall(obj); 1668. } 1669. } 1670. 1671. STATIC_OVL short 1672. mixtype(o1, o2) 1673. register struct obj *o1, *o2; 1674. /* returns the potion type when o1 is dipped in o2 */ 1675. { 1676. /* cut down on the number of cases below */ 1677. if (o1->oclass == POTION_CLASS && 1678. (o2->otyp == POT_GAIN_LEVEL || 1679. o2->otyp == POT_GAIN_ENERGY || 1680. o2->otyp == POT_HEALING || 1681. o2->otyp == POT_EXTRA_HEALING || 1682. o2->otyp == POT_FULL_HEALING || 1683. o2->otyp == POT_ENLIGHTENMENT || 1684. o2->otyp == POT_FRUIT_JUICE)) { 1685. struct obj *swp; 1686. 1687. swp = o1; o1 = o2; o2 = swp; 1688. } 1689. 1690. switch (o1->otyp) { 1691. case POT_HEALING: 1692. switch (o2->otyp) { 1693. case POT_SPEED: 1694. case POT_GAIN_LEVEL: 1695. case POT_GAIN_ENERGY: 1696. return POT_EXTRA_HEALING; 1697. } 1698. break; 1699. case POT_EXTRA_HEALING: 1700. switch (o2->otyp) { 1701. case POT_GAIN_LEVEL: 1702. case POT_GAIN_ENERGY: 1703. return POT_FULL_HEALING; 1704. } 1705. break; 1706. case POT_FULL_HEALING: 1707. switch (o2->otyp) { 1708. case POT_GAIN_LEVEL: 1709. case POT_GAIN_ENERGY: 1710. return POT_GAIN_ABILITY; 1711. } 1712. break; 1713. case UNICORN_HORN: 1714. switch (o2->otyp) { 1715. case POT_SICKNESS: 1716. return POT_FRUIT_JUICE; 1717. case POT_HALLUCINATION: 1718. case POT_BLINDNESS: 1719. case POT_CONFUSION: 1720. case POT_BLOOD: 1721. case POT_VAMPIRE_BLOOD: 1722. return POT_WATER; 1723. } 1724. break; 1725. case AMETHYST: /* "a-methyst" == "not intoxicated" */ 1726. if (o2->otyp == POT_BOOZE) 1727. return POT_FRUIT_JUICE; 1728. break; 1729. case POT_GAIN_LEVEL: 1730. case POT_GAIN_ENERGY: 1731. switch (o2->otyp) { 1732. case POT_CONFUSION: 1733. return (rn2(3) ? POT_BOOZE : POT_ENLIGHTENMENT); 1734. case POT_HEALING: 1735. return POT_EXTRA_HEALING; 1736. case POT_EXTRA_HEALING: 1737. return POT_FULL_HEALING; 1738. case POT_FULL_HEALING: 1739. return POT_GAIN_ABILITY; 1740. case POT_FRUIT_JUICE: 1741. return POT_SEE_INVISIBLE; 1742. case POT_BOOZE: 1743. return POT_HALLUCINATION; 1744. } 1745. break; 1746. case POT_FRUIT_JUICE: 1747. switch (o2->otyp) { 1748. case POT_SICKNESS: 1749. return POT_SICKNESS; 1750. case POT_BLOOD: 1751. return POT_BLOOD; 1752. case POT_VAMPIRE_BLOOD: 1753. return POT_VAMPIRE_BLOOD; 1754. case POT_SPEED: 1755. return POT_BOOZE; 1756. case POT_GAIN_LEVEL: 1757. case POT_GAIN_ENERGY: 1758. return POT_SEE_INVISIBLE; 1759. } 1760. break; 1761. case POT_ENLIGHTENMENT: 1762. switch (o2->otyp) { 1763. case POT_LEVITATION: 1764. if (rn2(3)) return POT_GAIN_LEVEL; 1765. break; 1766. case POT_FRUIT_JUICE: 1767. return POT_BOOZE; 1768. case POT_BOOZE: 1769. return POT_CONFUSION; 1770. } 1771. break; 1772. } 1773. /* MRKR: Extra alchemical effects. */ 1774. 1775. if (o2->otyp == POT_ACID && o1->oclass == GEM_CLASS) { 1776. const char *potion_descr; 1777. 1778. /* Note: you can't create smoky, milky or clear potions */ 1779. 1780. switch (o1->otyp) { 1781. 1782. /* white */ 1783. 1784. case DILITHIUM_CRYSTAL: 1785. /* explodes - special treatment in dodip */ 1786. /* here we just want to return something non-zero */ 1787. return POT_WATER; 1788. break; 1789. case DIAMOND: 1790. /* won't dissolve */ 1791. potion_descr = NULL; 1792. break; 1793. case OPAL: 1794. potion_descr = "cloudy"; 1795. break; 1796. 1797. /* red */ 1798. 1799. case RUBY: 1800. potion_descr = "ruby"; 1801. break; 1802. case GARNET: 1803. potion_descr = "pink"; 1804. break; 1805. case JASPER: 1806. potion_descr = "purple-red"; 1807. break; 1808. 1809. /* orange */ 1810. 1811. case JACINTH: 1812. potion_descr = "orange"; 1813. break; 1814. case AGATE: 1815. potion_descr = "swirly"; 1816. break; 1817. 1818. /* yellow */ 1819. 1820. case CITRINE: 1821. potion_descr = "yellow"; 1822. break; 1823. case CHRYSOBERYL: 1824. potion_descr = "golden"; 1825. break; 1826. 1827. /* yellowish brown */ 1828. 1829. case AMBER: 1830. potion_descr = "brown"; 1831. break; 1832. case TOPAZ: 1833. potion_descr = "murky"; 1834. break; 1835. 1836. /* green */ 1837. 1838. case EMERALD: 1839. potion_descr = "emerald"; 1840. break; 1841. case TURQUOISE: 1842. potion_descr = "sky blue"; 1843. break; 1844. case AQUAMARINE: 1845. potion_descr = "cyan"; 1846. break; 1847. case JADE: 1848. potion_descr = "dark green"; 1849. break; 1850. 1851. /* blue */ 1852. 1853. case SAPPHIRE: 1854. potion_descr = "brilliant blue"; 1855. break; 1856. 1857. /* violet */ 1858. 1859. case AMETHYST: 1860. potion_descr = "magenta"; 1861. break; 1862. case FLUORITE: 1863. potion_descr = "white"; 1864. break; 1865. 1866. /* black */ 1867. 1868. case BLACK_OPAL: 1869. potion_descr = "black"; 1870. break; 1871. case JET: 1872. potion_descr = "dark"; 1873. break; 1874. case OBSIDIAN: 1875. potion_descr = "effervescent"; 1876. break; 1877. default: potion_descr = NULL; 1878. } 1879. 1880. if (potion_descr) { 1881. int typ; 1882. 1883. /* find a potion that matches the description */ 1884. 1885. for (typ = bases[POTION_CLASS]; 1886. objects[typ].oc_class == POTION_CLASS; 1887. typ++) { 1888. 1889. if (strcmp(potion_descr, OBJ_DESCR(objects[typ])) == 0) { 1890. return typ; 1891. } 1892. } 1893. } 1894. } 1895. 1896. return 0; 1897. } 1898. 1899. /* Bills an object that's about to be downgraded, assuming that's not already 1900. * been done */ 1901. STATIC_OVL 1902. void 1903. pre_downgrade_obj(obj, used) 1904. register struct obj *obj; 1905. boolean *used; 1906. { 1907. boolean dummy = FALSE; 1908. 1909. if (!used) used = &dummy; 1910. if (!*used) Your("%s for a moment.", aobjnam(obj, "sparkle")); 1911. if(obj->unpaid && costly_spot(u.ux, u.uy) && !*used) { 1912. You("damage it, you pay for it."); 1913. bill_dummy_object(obj); 1914. } 1915. *used = TRUE; 1916. } 1917. 1918. /* Implements the downgrading effect of potions of amnesia and Lethe water */ 1919. STATIC_OVL 1920. void 1921. downgrade_obj(obj, nomagic, used) 1922. register struct obj *obj; 1923. int nomagic; /* The non-magical object to downgrade to */ 1924. boolean *used; 1925. { 1926. pre_downgrade_obj(obj, used); 1927. obj->otyp = nomagic; 1928. obj->spe = 0; 1929. obj->owt = weight(obj); 1930. flags.botl = TRUE; 1931. } 1932. 1933. boolean 1934. get_wet(obj, amnesia) 1935. register struct obj *obj; 1936. boolean amnesia; 1937. /* returns TRUE if something happened (potion should be used up) */ 1938. { 1939. char Your_buf[BUFSZ]; 1940. boolean used = FALSE; 1941. 1942. if (snuff_lit(obj)) return(TRUE); 1943. 1944. if (obj->greased) { 1945. grease_protect(obj,(char *)0,&youmonst); 1946. return(FALSE); 1947. } 1948. (void) Shk_Your(Your_buf, obj); 1949. /* (Rusting shop goods ought to be charged for.) */ 1950. switch (obj->oclass) { 1951. case POTION_CLASS: 1952. if (obj->otyp == POT_WATER) { 1953. if (amnesia) { 1954. Your("%s to sparkle.", aobjnam(obj,"start")); 1955. obj->odiluted = 0; 1956. obj->otyp = POT_AMNESIA; 1957. used = TRUE; 1958. break; 1959. } 1960. return FALSE; 1961. } 1962. 1963. /* Diluting a !ofAmnesia just gives water... */ 1964. if (obj->otyp == POT_AMNESIA) { 1965. Your("%s flat.", aobjnam(obj, "become")); 1966. obj->odiluted = 0; 1967. obj->otyp = POT_WATER; 1968. used = TRUE; 1969. break; 1970. } 1971. 1972. /* KMH -- Water into acid causes an explosion */ 1973. if (obj->otyp == POT_ACID) { 1974. pline("It boils vigorously!"); 1975. You("are caught in the explosion!"); 1976. losehp(Acid_resistance ? rnd(5) : rnd(10), 1977. "elementary chemistry", KILLED_BY); 1978. if (amnesia) { 1979. You_feel("a momentary lapse of reason!"); 1980. forget(2 + rn2(3)); 1981. } 1982. makeknown(obj->otyp); 1983. used = TRUE; 1984. break; 1985. } 1986. if (amnesia) 1987. pline("%s %s completely.", Your_buf, aobjnam(obj,"dilute")); 1988. else 1989. pline("%s %s%s.", Your_buf, aobjnam(obj,"dilute"), 1990. obj->odiluted ? " further" : ""); 1991. if(obj->unpaid && costly_spot(u.ux, u.uy)) { 1992. You("dilute it, you pay for it."); 1993. bill_dummy_object(obj); 1994. } 1995. if (obj->odiluted || amnesia) { 1996. obj->odiluted = 0; 1997. #ifdef UNIXPC 1998. obj->blessed = FALSE; 1999. obj->cursed = FALSE; 2000. #else 2001. obj->blessed = obj->cursed = FALSE; 2002. #endif 2003. obj->otyp = POT_WATER; 2004. } else obj->odiluted++; 2005. used = TRUE; 2006. break; 2007. case SCROLL_CLASS: 2008. if (obj->otyp != SCR_BLANK_PAPER 2009. #ifdef MAIL 2010. && obj->otyp != SCR_MAIL 2011. #endif 2012. ) { 2013. if (!Blind) { 2014. boolean oq1 = obj->quan == 1L; 2015. pline_The("scroll%s %s.", 2016. oq1 ? "" : "s", otense(obj, "fade")); 2017. } 2018. if(obj->unpaid && costly_spot(u.ux, u.uy)) { 2019. You("erase it, you pay for it."); 2020. bill_dummy_object(obj); 2021. } 2022. obj->otyp = SCR_BLANK_PAPER; 2023. obj->spe = 0; 2024. used = TRUE; 2025. } 2026. break; 2027. case SPBOOK_CLASS: 2028. if (obj->otyp != SPE_BLANK_PAPER) { 2029. if (obj->otyp == SPE_BOOK_OF_THE_DEAD) { 2030. pline("%s suddenly heats up; steam rises and it remains dry.", 2031. The(xname(obj))); 2032. } else { 2033. if (!Blind) { 2034. boolean oq1 = obj->quan == 1L; 2035. pline_The("spellbook%s %s.", 2036. oq1 ? "" : "s", otense(obj, "fade")); 2037. } 2038. if(obj->unpaid) { 2039. subfrombill(obj, shop_keeper(*u.ushops)); 2040. You("erase it, you pay for it."); 2041. bill_dummy_object(obj); 2042. } 2043. obj->otyp = SPE_BLANK_PAPER; 2044. } 2045. used = TRUE; 2046. } 2047. break; 2048. case GEM_CLASS: 2049. if (amnesia && (obj->otyp == LUCKSTONE || 2050. obj->otyp == LOADSTONE || obj->otyp == HEALTHSTONE || 2051. obj->otyp == TOUCHSTONE)) 2052. downgrade_obj(obj, FLINT, &used); 2053. break; 2054. case TOOL_CLASS: 2055. /* Artifacts aren't downgraded by amnesia */ 2056. if (amnesia && !obj->oartifact) { 2057. switch (obj->otyp) { 2058. case MAGIC_LAMP: 2059. /* Magic lamps forget their djinn... */ 2060. downgrade_obj(obj, OIL_LAMP, &used); 2061. break; 2062. case MAGIC_CANDLE: 2063. downgrade_obj(obj, 2064. rn2(2)? WAX_CANDLE : TALLOW_CANDLE, 2065. &used); 2066. break; 2067. case DRUM_OF_EARTHQUAKE: 2068. downgrade_obj(obj, LEATHER_DRUM, &used); 2069. break; 2070. case MAGIC_WHISTLE: 2071. /* Magic whistles lose their powers... */ 2072. downgrade_obj(obj, TIN_WHISTLE, &used); 2073. break; 2074. case MAGIC_FLUTE: 2075. /* Magic flutes sound normal again... */ 2076. downgrade_obj(obj, WOODEN_FLUTE, &used); 2077. break; 2078. case MAGIC_HARP: 2079. /* Magic harps sound normal again... */ 2080. downgrade_obj(obj, WOODEN_HARP, &used); 2081. break; 2082. case FIRE_HORN: 2083. case FROST_HORN: 2084. case HORN_OF_PLENTY: 2085. downgrade_obj(obj, TOOLED_HORN, &used); 2086. break; 2087. case MAGIC_MARKER: 2088. /* Magic markers run... */ 2089. if (obj->spe > 0) { 2090. pre_downgrade_obj(obj, &used); 2091. if ((obj->spe -= (3 + rn2(10))) < 0) 2092. obj->spe = 0; 2093. } 2094. break; 2095. } 2096. } 2097. 2098. /* The only other tools that can be affected are pick axes and 2099. * unicorn horns... */ 2100. if (!is_weptool(obj)) break; 2101. /* Drop through for disenchantment and rusting... */ 2102. /* fall through */ 2103. case ARMOR_CLASS: 2104. case WEAPON_CLASS: 2105. case WAND_CLASS: 2106. case RING_CLASS: 2107. /* Just "fall through" to generic rustprone check for now. */ 2108. /* fall through */ 2109. default: 2110. switch(artifact_wet(obj, FALSE)) { 2111. case -1: break; 2112. default: 2113. return TRUE; 2114. } 2115. /* !ofAmnesia acts as a disenchanter... */ 2116. if (amnesia && obj->spe > 0) { 2117. pre_downgrade_obj(obj, &used); 2118. drain_item(obj); 2119. } 2120. if (!obj->oerodeproof && is_rustprone(obj) && 2121. (obj->oeroded < MAX_ERODE) && !rn2(2)) { 2122. pline("%s %s some%s.", 2123. Your_buf, aobjnam(obj, "rust"), 2124. obj->oeroded ? " more" : "what"); 2125. obj->oeroded++; 2126. if(obj->unpaid && costly_spot(u.ux, u.uy) && !used) { 2127. You("damage it, you pay for it."); 2128. bill_dummy_object(obj); 2129. } 2130. used = TRUE; 2131. } 2132. break; 2133. } 2134. /* !ofAmnesia might strip away fooproofing... */ 2135. if (amnesia && obj->oerodeproof && !rn2(13)) { 2136. pre_downgrade_obj(obj, &used); 2137. obj->oerodeproof = FALSE; 2138. } 2139. 2140. /* !ofAmnesia also strips blessed/cursed status... */ 2141. 2142. if (amnesia && (obj->cursed || obj->blessed)) { 2143. /* Blessed objects are valuable, cursed objects aren't, unless 2144. * they're water. 2145. */ 2146. if (obj->blessed || obj->otyp == POT_WATER) 2147. pre_downgrade_obj(obj, &used); 2148. else if (!used) { 2149. Your("%s for a moment.", aobjnam(obj, "sparkle")); 2150. used = TRUE; 2151. } 2152. uncurse(obj); 2153. unbless(obj); 2154. } 2155. 2156. if (used) 2157. update_inventory(); 2158. else 2159. pline("%s %s wet.", Your_buf, aobjnam(obj,"get")); 2160. 2161. return used; 2162. } 2163. 2164. 2165. /* KMH, balance patch -- idea by Dylan O'Donnell 2166. * The poor hacker's polypile. This includes weapons, armor, and tools. 2167. * To maintain balance, magical categories (amulets, scrolls, spellbooks, 2168. * potions, rings, and wands) should NOT be supported. 2169. * Polearms are not currently implemented. 2170. */ 2171. int 2172. upgrade_obj(obj) 2173. register struct obj *obj; 2174. /* returns 1 if something happened (potion should be used up) 2175. * returns 0 if nothing happened 2176. * returns -1 if object exploded (potion should be used up) 2177. */ 2178. { 2179. int chg, otyp = obj->otyp, otyp2; 2180. xchar ox, oy; 2181. long owornmask; 2182. struct obj *otmp; 2183. boolean explodes; 2184. 2185. /* Check to see if object is valid */ 2186. if (!obj) 2187. return 0; 2188. (void)snuff_lit(obj); 2189. if (obj->oartifact) 2190. /* WAC -- Could have some funky fx */ 2191. return 0; 2192. 2193. switch (obj->otyp) 2194. { 2195. /* weapons */ 2196. case ORCISH_DAGGER: 2197. obj->otyp = DAGGER; 2198. break; 2199. case GREAT_DAGGER: 2200. case DAGGER: 2201. if (!rn2(2)) obj->otyp = ELVEN_DAGGER; 2202. else obj->otyp = DARK_ELVEN_DAGGER; 2203. break; 2204. case ELVEN_DAGGER: 2205. case DARK_ELVEN_DAGGER: 2206. obj->otyp = GREAT_DAGGER; 2207. break; 2208. case KNIFE: 2209. obj->otyp = STILETTO; 2210. break; 2211. case STILETTO: 2212. obj->otyp = KNIFE; 2213. break; 2214. case AXE: 2215. obj->otyp = BATTLE_AXE; 2216. break; 2217. case BATTLE_AXE: 2218. obj->otyp = AXE; 2219. break; 2220. case PICK_AXE: 2221. obj->otyp = DWARVISH_MATTOCK; 2222. break; 2223. case DWARVISH_MATTOCK: 2224. obj->otyp = PICK_AXE; 2225. break; 2226. case ORCISH_SHORT_SWORD: 2227. obj->otyp = SHORT_SWORD; 2228. break; 2229. case ELVEN_SHORT_SWORD: 2230. case DARK_ELVEN_SHORT_SWORD: 2231. case SHORT_SWORD: 2232. obj->otyp = DWARVISH_SHORT_SWORD; 2233. break; 2234. case DWARVISH_SHORT_SWORD: 2235. if (!rn2(2)) obj->otyp = ELVEN_SHORT_SWORD; 2236. else obj->otyp = DARK_ELVEN_SHORT_SWORD; 2237. break; 2238. case BROADSWORD: 2239. obj->otyp = ELVEN_BROADSWORD; 2240. break; 2241. case ELVEN_BROADSWORD: 2242. obj->otyp = BROADSWORD; 2243. break; 2244. case CLUB: 2245. obj->otyp = AKLYS; 2246. break; 2247. case AKLYS: 2248. obj->otyp = CLUB; 2249. break; 2250. case WAR_HAMMER: 2251. obj->otyp = HEAVY_HAMMER; 2252. break; 2253. case HEAVY_HAMMER: 2254. obj->otyp = WAR_HAMMER; 2255. break; 2256. case ELVEN_BOW: 2257. case DARK_ELVEN_BOW: 2258. case YUMI: 2259. case ORCISH_BOW: 2260. obj->otyp = BOW; 2261. break; 2262. case BOW: 2263. switch (rn2(3)) { 2264. case 0: obj->otyp = ELVEN_BOW; break; 2265. case 1: obj->otyp = DARK_ELVEN_BOW; break; 2266. case 2: obj->otyp = YUMI; break; 2267. } 2268. break; 2269. case ELVEN_ARROW: 2270. case DARK_ELVEN_ARROW: 2271. case YA: 2272. case ORCISH_ARROW: 2273. obj->otyp = ARROW; 2274. break; 2275. case ARROW: 2276. switch (rn2(3)) { 2277. case 0: obj->otyp = ELVEN_ARROW; break; 2278. case 1: obj->otyp = DARK_ELVEN_ARROW; break; 2279. case 2: obj->otyp = YA; break; 2280. } 2281. break; 2282. /* armour */ 2283. case ELVEN_MITHRIL_COAT: 2284. obj->otyp = DARK_ELVEN_MITHRIL_COAT; 2285. break; 2286. case DARK_ELVEN_MITHRIL_COAT: 2287. obj->otyp = ELVEN_MITHRIL_COAT; 2288. break; 2289. case ORCISH_CHAIN_MAIL: 2290. obj->otyp = CHAIN_MAIL; 2291. break; 2292. case CHAIN_MAIL: 2293. obj->otyp = ORCISH_CHAIN_MAIL; 2294. break; 2295. case STUDDED_LEATHER_ARMOR: 2296. case LEATHER_JACKET: 2297. obj->otyp = LEATHER_ARMOR; 2298. break; 2299. case LEATHER_ARMOR: 2300. obj->otyp = STUDDED_LEATHER_ARMOR; 2301. break; 2302. /* robes */ 2303. case ROBE: 2304. if (!rn2(2)) obj->otyp = ROBE_OF_PROTECTION; 2305. else obj->otyp = ROBE_OF_POWER; 2306. break; 2307. case ROBE_OF_PROTECTION: 2308. case ROBE_OF_POWER: 2309. obj->otyp = ROBE; 2310. break; 2311. /* cloaks */ 2312. case CLOAK_OF_PROTECTION: 2313. case CLOAK_OF_INVISIBILITY: 2314. case CLOAK_OF_MAGIC_RESISTANCE: 2315. case CLOAK_OF_DISPLACEMENT: 2316. case DWARVISH_CLOAK: 2317. case ORCISH_CLOAK: 2318. if (!rn2(2)) obj->otyp = OILSKIN_CLOAK; 2319. else obj->otyp = ELVEN_CLOAK; 2320. break; 2321. case OILSKIN_CLOAK: 2322. case ELVEN_CLOAK: 2323. switch (rn2(4)) { 2324. case 0: obj->otyp = CLOAK_OF_PROTECTION; break; 2325. case 1: obj->otyp = CLOAK_OF_INVISIBILITY; break; 2326. case 2: obj->otyp = CLOAK_OF_MAGIC_RESISTANCE; break; 2327. case 3: obj->otyp = CLOAK_OF_DISPLACEMENT; break; 2328. } 2329. break; 2330. /* helms */ 2331. case FEDORA: 2332. obj->otyp = ELVEN_LEATHER_HELM; 2333. break; 2334. case ELVEN_LEATHER_HELM: 2335. obj->otyp = FEDORA; 2336. break; 2337. case DENTED_POT: 2338. obj->otyp = ORCISH_HELM; 2339. break; 2340. case ORCISH_HELM: 2341. case HELM_OF_BRILLIANCE: 2342. case HELM_OF_TELEPATHY: 2343. obj->otyp = DWARVISH_IRON_HELM; 2344. break; 2345. case DWARVISH_IRON_HELM: 2346. if (!rn2(2)) obj->otyp = HELM_OF_BRILLIANCE; 2347. else obj->otyp = HELM_OF_TELEPATHY; 2348. break; 2349. case CORNUTHAUM: 2350. obj->otyp = DUNCE_CAP; 2351. break; 2352. case DUNCE_CAP: 2353. obj->otyp = CORNUTHAUM; 2354. break; 2355. /* gloves */ 2356. case LEATHER_GLOVES: 2357. if (!rn2(2)) obj->otyp = GAUNTLETS_OF_SWIMMING; 2358. else obj->otyp = GAUNTLETS_OF_DEXTERITY; 2359. break; 2360. case GAUNTLETS_OF_SWIMMING: 2361. case GAUNTLETS_OF_DEXTERITY: 2362. obj->otyp = LEATHER_GLOVES; 2363. break; 2364. /* shields */ 2365. case ELVEN_SHIELD: 2366. if (!rn2(2)) obj->otyp = URUK_HAI_SHIELD; 2367. else obj->otyp = ORCISH_SHIELD; 2368. break; 2369. case URUK_HAI_SHIELD: 2370. case ORCISH_SHIELD: 2371. obj->otyp = ELVEN_SHIELD; 2372. break; 2373. case DWARVISH_ROUNDSHIELD: 2374. obj->otyp = LARGE_SHIELD; 2375. break; 2376. case LARGE_SHIELD: 2377. obj->otyp = DWARVISH_ROUNDSHIELD; 2378. break; 2379. /* boots */ 2380. case LOW_BOOTS: 2381. obj->otyp = HIGH_BOOTS; 2382. break; 2383. case HIGH_BOOTS: 2384. obj->otyp = LOW_BOOTS; 2385. break; 2386. /* NOTE: Supposedly, HIGH_BOOTS should upgrade to any of the 2387. other magic leather boots (except for fumble). IRON_SHOES 2388. should upgrade to the iron magic boots, unless 2389. the iron magic boots are fumble */ 2390. /* rings, amulets */ 2391. case LARGE_BOX: 2392. case ICE_BOX: 2393. obj->otyp = CHEST; 2394. break; 2395. case CHEST: 2396. obj->otyp = ICE_BOX; 2397. break; 2398. case SACK: 2399. obj->otyp = rn2(5) ? OILSKIN_SACK : BAG_OF_HOLDING; 2400. break; 2401. case OILSKIN_SACK: 2402. obj->otyp = BAG_OF_HOLDING; 2403. break; 2404. case BAG_OF_HOLDING: 2405. obj->otyp = OILSKIN_SACK; 2406. break; 2407. #ifdef TOURIST 2408. case TOWEL: 2409. obj->otyp = BLINDFOLD; 2410. break; 2411. case BLINDFOLD: 2412. obj->otyp = TOWEL; 2413. break; 2414. case CREDIT_CARD: 2415. #endif 2416. case LOCK_PICK: 2417. obj->otyp = SKELETON_KEY; 2418. break; 2419. case SKELETON_KEY: 2420. obj->otyp = LOCK_PICK; 2421. break; 2422. case TALLOW_CANDLE: 2423. obj->otyp = WAX_CANDLE; 2424. break; 2425. case WAX_CANDLE: 2426. obj->otyp = TALLOW_CANDLE; 2427. break; 2428. case OIL_LAMP: 2429. obj->otyp = BRASS_LANTERN; 2430. break; 2431. case BRASS_LANTERN: 2432. obj->otyp = OIL_LAMP; 2433. break; 2434. case TIN_WHISTLE: 2435. obj->otyp = MAGIC_WHISTLE; 2436. break; 2437. case MAGIC_WHISTLE: 2438. obj->otyp = TIN_WHISTLE; 2439. break; 2440. case WOODEN_FLUTE: 2441. obj->otyp = MAGIC_FLUTE; 2442. obj->spe = rn1(5,10); 2443. break; 2444. case MAGIC_FLUTE: 2445. obj->otyp = WOODEN_FLUTE; 2446. break; 2447. case TOOLED_HORN: 2448. obj->otyp = rn1(HORN_OF_PLENTY - TOOLED_HORN, FROST_HORN); 2449. obj->spe = rn1(5,10); 2450. obj->known = 0; 2451. break; 2452. case HORN_OF_PLENTY: 2453. case FIRE_HORN: 2454. case FROST_HORN: 2455. obj->otyp = TOOLED_HORN; 2456. break; 2457. case WOODEN_HARP: 2458. obj->otyp = MAGIC_HARP; 2459. obj->spe = rn1(5,10); 2460. obj->known = 0; 2461. break; 2462. case MAGIC_HARP: 2463. obj->otyp = WOODEN_HARP; 2464. break; 2465. #ifdef STEED 2466. case LEASH: 2467. obj->otyp = SADDLE; 2468. break; 2469. case SADDLE: 2470. obj->otyp = LEASH; 2471. break; 2472. #endif 2473. case TIN_OPENER: 2474. obj->otyp = TINNING_KIT; 2475. obj->spe = rn1(30,70); 2476. obj->known = 0; 2477. break; 2478. case TINNING_KIT: 2479. obj->otyp = TIN_OPENER; 2480. break; 2481. case CRYSTAL_BALL: 2482. /* "ball-point pen" */ 2483. obj->otyp = MAGIC_MARKER; 2484. /* Keep the charges (crystal ball usually less than marker) */ 2485. break; 2486. case MAGIC_MARKER: 2487. obj->otyp = CRYSTAL_BALL; 2488. chg = rn1(10,3); 2489. if (obj->spe > chg) 2490. obj->spe = chg; 2491. obj->known = 0; 2492. break; 2493. case K_RATION: 2494. case C_RATION: 2495. case LEMBAS_WAFER: 2496. if (!rn2(2)) obj->otyp = CRAM_RATION; 2497. else obj->otyp = FOOD_RATION; 2498. break; 2499. case FOOD_RATION: 2500. case CRAM_RATION: 2501. obj->otyp = LEMBAS_WAFER; 2502. break; 2503. case LOADSTONE: 2504. obj->otyp = FLINT; 2505. break; 2506. case FLINT: 2507. if (!rn2(2)) obj->otyp = LUCKSTONE; 2508. else obj->otyp = HEALTHSTONE; 2509. break; 2510. default: 2511. /* This object is not upgradable */ 2512. return 0; 2513. } 2514. 2515. if ((!carried(obj) || obj->unpaid) && 2516. #ifdef UNPOLYPILE 2517. !is_hazy(obj) && 2518. #endif 2519. get_obj_location(obj, &ox, &oy, BURIED_TOO|CONTAINED_TOO) && 2520. costly_spot(ox, oy)) { 2521. char objroom = *in_rooms(ox, oy, SHOPBASE); 2522. register struct monst *shkp = shop_keeper(objroom); 2523. 2524. if ((!obj->no_charge || 2525. (Has_contents(obj) && 2526. (contained_cost(obj, shkp, 0L, FALSE, FALSE) != 0L))) 2527. && inhishop(shkp)) { 2528. if(shkp->mpeaceful) { 2529. if(*u.ushops && *in_rooms(u.ux, u.uy, 0) == 2530. *in_rooms(shkp->mx, shkp->my, 0) && 2531. !costly_spot(u.ux, u.uy)) 2532. make_angry_shk(shkp, ox, oy); 2533. else { 2534. pline("%s gets angry!", Monnam(shkp)); 2535. hot_pursuit(shkp); 2536. } 2537. } else Norep("%s is furious!", Monnam(shkp)); 2538. otyp2 = obj->otyp; 2539. obj->otyp = otyp; 2540. /* 2541. * [ALI] When unpaid containers are upgraded, the 2542. * old container is billed as a dummy object, but 2543. * it's contents are unaffected and will remain 2544. * either unpaid or not as appropriate. 2545. */ 2546. otmp = obj->cobj; 2547. obj->cobj = NULL; 2548. if (costly_spot(u.ux, u.uy) && objroom == *u.ushops) 2549. bill_dummy_object(obj); 2550. else 2551. (void) stolen_value(obj, ox, oy, FALSE, FALSE, FALSE); 2552. obj->otyp = otyp2; 2553. obj->cobj = otmp; 2554. } 2555. } 2556. 2557. /* The object was transformed */ 2558. obj->owt = weight(obj); 2559. obj->oclass = objects[obj->otyp].oc_class; 2560. if (!objects[obj->otyp].oc_uses_known) 2561. obj->known = 1; 2562. 2563. if (carried(obj)) { 2564. if (obj == uskin) rehumanize(); 2565. /* Quietly remove worn item if no longer compatible --ALI */ 2566. owornmask = obj->owornmask; 2567. if (owornmask & W_ARM && !is_suit(obj)) 2568. owornmask &= ~W_ARM; 2569. if (owornmask & W_ARMC && !is_cloak(obj)) 2570. owornmask &= ~W_ARMC; 2571. if (owornmask & W_ARMH && !is_helmet(obj)) 2572. owornmask &= ~W_ARMH; 2573. if (owornmask & W_ARMS && !is_shield(obj)) 2574. owornmask &= ~W_ARMS; 2575. if (owornmask & W_ARMG && !is_gloves(obj)) 2576. owornmask &= ~W_ARMG; 2577. if (owornmask & W_ARMF && !is_boots(obj)) 2578. owornmask &= ~W_ARMF; 2579. #ifdef TOURIST 2580. if (owornmask & W_ARMU && !is_shirt(obj)) 2581. owornmask &= ~W_ARMU; 2582. #endif 2583. if (owornmask & W_TOOL && obj->otyp != BLINDFOLD && 2584. obj->otyp != TOWEL && obj->otyp != LENSES) 2585. owornmask &= ~W_TOOL; 2586. otyp2 = obj->otyp; 2587. obj->otyp = otyp; 2588. if (obj->otyp == LEASH && obj->leashmon) o_unleash(obj); 2589. remove_worn_item(obj, TRUE); 2590. obj->otyp = otyp2; 2591. obj->owornmask = owornmask; 2592. setworn(obj, obj->owornmask); 2593. puton_worn_item(obj); 2594. } 2595. 2596. if (obj->otyp == BAG_OF_HOLDING && Has_contents(obj)) { 2597. explodes = FALSE; 2598. 2599. for (otmp = obj->cobj; otmp; otmp = otmp->nobj) 2600. if (mbag_explodes(otmp, 0)) { 2601. explodes = TRUE; 2602. break; 2603. } 2604. 2605. if (explodes) { 2606. pline("As you upgrade your bag, you are blasted by a magical explosion!"); 2607. delete_contents(obj); 2608. if (carried(obj)) 2609. useup(obj); 2610. else 2611. useupf(obj, obj->quan); 2612. losehp(d(6,6), "magical explosion", KILLED_BY_AN); 2613. return -1; 2614. } 2615. } 2616. return 1; 2617. } 2618. 2619. int 2620. dodip() 2621. { 2622. struct obj *potion, *obj, *singlepotion; 2623. const char *tmp; 2624. uchar here; 2625. char allowall[2], qbuf[QBUFSZ], Your_buf[BUFSZ]; 2626. short mixture; 2627. int res; 2628. 2629. allowall[0] = ALL_CLASSES; allowall[1] = '\0'; 2630. if(!(obj = getobj(allowall, "dip"))) 2631. return(0); 2632. 2633. here = levl[u.ux][u.uy].typ; 2634. /* Is there a fountain to dip into here? */ 2635. if (IS_FOUNTAIN(here)) { 2636. if(yn("Dip it into the fountain?") == 'y') { 2637. dipfountain(obj); 2638. return(1); 2639. } 2640. } else if (IS_TOILET(here)) { 2641. if(yn("Dip it into the toilet?") == 'y') { 2642. diptoilet(obj); 2643. return(1); 2644. } 2645. } else if (is_pool(u.ux,u.uy)) { 2646. tmp = waterbody_name(u.ux,u.uy); 2647. Sprintf(qbuf, "Dip it into the %s?", tmp); 2648. if (yn(qbuf) == 'y') { 2649. if (Levitation) { 2650. floating_above(tmp); 2651. #ifdef STEED 2652. } else if (u.usteed && !is_swimmer(u.usteed->data) && 2653. P_SKILL(P_RIDING) < P_BASIC) { 2654. rider_cant_reach(); /* not skilled enough to reach */ 2655. #endif 2656. } else { 2657. (void) get_wet(obj, level.flags.lethe); 2658. if (obj->otyp == POT_ACID) useup(obj); 2659. } 2660. return 1; 2661. } 2662. } 2663. 2664. if(!(potion = getobj(beverages, "dip into"))) 2665. return(0); 2666. if (potion == obj && potion->quan == 1L) { 2667. pline("That is a potion bottle, not a Klein bottle!"); 2668. return 0; 2669. } 2670. 2671. if(potion->otyp != POT_WATER && obj->otyp == POT_WATER) { 2672. /* swap roles, to ensure symmetry */ 2673. struct obj *otmp = potion; 2674. potion = obj; 2675. obj = otmp; 2676. } 2677. potion->in_use = TRUE; /* assume it will be used up */ 2678. if(potion->otyp == POT_WATER) { 2679. boolean useeit = !Blind; 2680. if (useeit) (void) Shk_Your(Your_buf, obj); 2681. if (potion->blessed) { 2682. if (obj->cursed) { 2683. if (useeit) 2684. pline("%s %s %s.", 2685. Your_buf, 2686. aobjnam(obj, "softly glow"), 2687. hcolor(NH_AMBER)); 2688. uncurse(obj); 2689. obj->bknown=1; 2690. poof: 2691. if(!(objects[potion->otyp].oc_name_known) && 2692. !(objects[potion->otyp].oc_uname)) 2693. docall(potion); 2694. useup(potion); 2695. return(1); 2696. } else if(!obj->blessed) { 2697. if (useeit) { 2698. tmp = hcolor(NH_LIGHT_BLUE); 2699. pline("%s %s with a%s %s aura.", 2700. Your_buf, 2701. aobjnam(obj, "softly glow"), 2702. index(vowels, *tmp) ? "n" : "", tmp); 2703. } 2704. bless(obj); 2705. obj->bknown=1; 2706. goto poof; 2707. } 2708. } else if (potion->cursed) { 2709. if (obj->blessed) { 2710. if (useeit) 2711. pline("%s %s %s.", 2712. Your_buf, 2713. aobjnam(obj, "glow"), 2714. hcolor((const char *)"brown")); 2715. unbless(obj); 2716. obj->bknown=1; 2717. goto poof; 2718. } else if(!obj->cursed) { 2719. if (useeit) { 2720. tmp = hcolor(NH_BLACK); 2721. pline("%s %s with a%s %s aura.", 2722. Your_buf, 2723. aobjnam(obj, "glow"), 2724. index(vowels, *tmp) ? "n" : "", tmp); 2725. } 2726. curse(obj); 2727. obj->bknown=1; 2728. goto poof; 2729. } 2730. } else { 2731. switch(artifact_wet(obj,TRUE)) { 2732. /* Assume ZT_xxx is AD_xxx-1 */ 2733. case -1: break; 2734. default: 2735. zap_over_floor(u.ux, u.uy, 2736. (artifact_wet(obj,TRUE)-1), NULL); 2737. break; 2738. } 2739. if (get_wet(obj, FALSE)) 2740. goto poof; 2741. } 2742. } else if (potion->otyp == POT_AMNESIA) { 2743. if (potion == obj) { 2744. obj->in_use = FALSE; 2745. potion = splitobj(obj, 1L); 2746. potion->in_use = TRUE; 2747. } 2748. if (get_wet(obj, TRUE)) goto poof; 2749. } 2750. /* WAC - Finn Theoderson - make polymorph and gain level msgs similar 2751. * Give out name of new object and allow user to name the potion 2752. */ 2753. /* KMH, balance patch -- idea by Dylan O'Donnell */ 2754. else if (potion->otyp == POT_GAIN_LEVEL) { 2755. res = upgrade_obj(obj); 2756. 2757. if (res != 0) { 2758. 2759. if (res == 1) { 2760. /* The object was upgraded */ 2761. pline("Hmm! You don't recall dipping that into the potion."); 2762. prinv((char *)0, obj, 0L); 2763. } /* else potion exploded */ 2764. if (!objects[potion->otyp].oc_name_known && 2765. !objects[potion->otyp].oc_uname) 2766. docall(potion); 2767. useup(potion); 2768. update_inventory(); 2769. exercise(A_WIS, TRUE); 2770. return(1); 2771. } 2772. /* no return here, go for Interesting... message */ 2773. } else if (obj->otyp == POT_POLYMORPH || 2774. potion->otyp == POT_POLYMORPH) { 2775. /* some objects can't be polymorphed */ 2776. if (obj->otyp == potion->otyp || /* both POT_POLY */ 2777. obj->otyp == WAN_POLYMORPH || 2778. obj->otyp == SPE_POLYMORPH || 2779. obj == uball || obj == uskin || 2780. obj_resists(obj->otyp == POT_POLYMORPH ? 2781. potion : obj, 5, 95)) { 2782. pline(nothing_happens); 2783. } else { 2784. boolean was_wep = FALSE, was_swapwep = FALSE, was_quiver = FALSE; 2785. short save_otyp = obj->otyp; 2786. /* KMH, conduct */ 2787. u.uconduct.polypiles++; 2788. 2789. if (obj == uwep) was_wep = TRUE; 2790. else if (obj == uswapwep) was_swapwep = TRUE; 2791. else if (obj == uquiver) was_quiver = TRUE; 2792. 2793. obj = poly_obj(obj, STRANGE_OBJECT); 2794. 2795. if (was_wep) setuwep(obj, TRUE); 2796. else if (was_swapwep) setuswapwep(obj, TRUE); 2797. else if (was_quiver) setuqwep(obj); 2798. 2799. if (obj->otyp != save_otyp) { 2800. makeknown(POT_POLYMORPH); 2801. useup(potion); 2802. prinv((char *)0, obj, 0L); 2803. return 1; 2804. } else { 2805. pline("Nothing seems to happen."); 2806. goto poof; 2807. } 2808. } 2809. potion->in_use = FALSE; /* didn't go poof */ 2810. return(1); 2811. #ifdef UNPOLYPILE 2812. } else if (potion->otyp == POT_RESTORE_ABILITY && is_hazy(obj)) { 2813. /* KMH -- Restore ability will stop unpolymorphing */ 2814. stop_timer(UNPOLY_OBJ, (genericptr_t) obj); 2815. obj->oldtyp = STRANGE_OBJECT; 2816. if (!Blind) 2817. pline("%s seems less hazy.", Yname2(obj)); 2818. useup(potion); 2819. return (1); 2820. #endif 2821. } else if(obj->oclass == POTION_CLASS && obj->otyp != potion->otyp) { 2822. /* Mixing potions is dangerous... */ 2823. pline_The("potions mix..."); 2824. /* KMH, balance patch -- acid is particularly unstable */ 2825. if (obj->cursed || obj->otyp == POT_ACID || 2826. potion->cursed || potion->otyp == POT_ACID || !rn2(10)) { 2827. pline("BOOM! They explode!"); 2828. exercise(A_STR, FALSE); 2829. if (!breathless(youmonst.data) || haseyes(youmonst.data)) 2830. potionbreathe(obj); 2831. useup(obj); 2832. useup(potion); 2833. /* MRKR: an alchemy smock ought to be */ 2834. /* some protection against this: */ 2835. losehp(Acid_resistance ? rnd(5) : rnd(10), 2836. "alchemic blast", KILLED_BY_AN); 2837. return(1); 2838. } 2839. 2840. obj->blessed = obj->cursed = obj->bknown = 0; 2841. if (Blind || Hallucination) obj->dknown = 0; 2842. 2843. if ((mixture = mixtype(obj, potion)) != 0) { 2844. obj->otyp = mixture; 2845. } else { 2846. switch (obj->odiluted ? 1 : rnd(8)) { 2847. case 1: 2848. obj->otyp = POT_WATER; 2849. break; 2850. case 2: 2851. case 3: 2852. obj->otyp = POT_SICKNESS; 2853. break; 2854. case 4: 2855. { 2856. struct obj *otmp; 2857. otmp = mkobj(POTION_CLASS,FALSE); 2858. obj->otyp = otmp->otyp; 2859. obfree(otmp, (struct obj *)0); 2860. } 2861. break; 2862. default: 2863. if (!Blind) 2864. pline_The("mixture glows brightly and evaporates."); 2865. useup(obj); 2866. useup(potion); 2867. return(1); 2868. } 2869. } 2870. 2871. obj->odiluted = (obj->otyp != POT_WATER); 2872. 2873. if (obj->otyp == POT_WATER && !Hallucination) { 2874. pline_The("mixture bubbles%s.", 2875. Blind ? "" : ", then clears"); 2876. } else if (!Blind) { 2877. pline_The("mixture looks %s.", 2878. hcolor(OBJ_DESCR(objects[obj->otyp]))); 2879. } 2880. 2881. useup(potion); 2882. return(1); 2883. } 2884. #ifdef INVISIBLE_OBJECTS 2885. if (!always_visible(obj)) { 2886. if (potion->otyp == POT_INVISIBILITY && !obj->oinvis) { 2887. obj->oinvis = TRUE; 2888. if (!Blind) 2889. pline(!See_invisible ? "Where did %s go?" : 2890. "Gee! All of a sudden you can see right through %s.", 2891. the(xname(obj))); 2892. goto poof; 2893. } else if (potion->otyp == POT_SEE_INVISIBLE && obj->oinvis) { 2894. obj->oinvis = FALSE; 2895. if (!Blind) { 2896. if (!See_invisible) 2897. pline("So that's where %s went!", the(xname(obj))); 2898. else 2899. You("can no longer see through %s.", 2900. the(xname(obj))); 2901. } 2902. goto poof; 2903. } 2904. } 2905. #endif 2906. 2907. if(is_poisonable(obj)) { 2908. if(potion->otyp == POT_SICKNESS && !obj->opoisoned) { 2909. char buf[BUFSZ]; 2910. if (potion->quan > 1L) 2911. Sprintf(buf, "One of %s", the(xname(potion))); 2912. else 2913. Strcpy(buf, The(xname(potion))); 2914. pline("%s forms a coating on %s.", 2915. buf, the(xname(obj))); 2916. obj->opoisoned = TRUE; 2917. goto poof; 2918. } else if(obj->opoisoned && 2919. (potion->otyp == POT_HEALING || 2920. potion->otyp == POT_EXTRA_HEALING || 2921. potion->otyp == POT_FULL_HEALING)) { 2922. pline("A coating wears off %s.", the(xname(obj))); 2923. obj->opoisoned = 0; 2924. goto poof; 2925. } 2926. } 2927. 2928. if (potion->otyp == POT_OIL) { 2929. boolean wisx = FALSE; 2930. if (potion->lamplit) { /* burning */ 2931. int omat = objects[obj->otyp].oc_material; 2932. /* the code here should be merged with fire_damage */ 2933. if (catch_lit(obj)) { 2934. /* catch_lit does all the work if true */ 2935. } else if (obj->oerodeproof || obj_resists(obj, 5, 95) || 2936. !is_flammable(obj) || obj->oclass == FOOD_CLASS) { 2937. pline("%s %s to burn for a moment.", 2938. Yname2(obj), otense(obj, "seem")); 2939. } else { 2940. if ((omat == PLASTIC || omat == PAPER) && !obj->oartifact) 2941. obj->oeroded = MAX_ERODE; 2942. pline_The("burning oil %s %s.", 2943. obj->oeroded == MAX_ERODE ? "destroys" : "damages", 2944. yname(obj)); 2945. if (obj->oeroded == MAX_ERODE) { 2946. obj_extract_self(obj); 2947. obfree(obj, (struct obj *)0); 2948. obj = (struct obj *) 0; 2949. } else { 2950. /* we know it's carried */ 2951. if (obj->unpaid) { 2952. /* create a dummy duplicate to put on bill */ 2953. verbalize("You burnt it, you bought it!"); 2954. bill_dummy_object(obj); 2955. } 2956. obj->oeroded++; 2957. } 2958. } 2959. } else if (potion->cursed) { 2960. pline_The("potion spills and covers your %s with oil.", 2961. makeplural(body_part(FINGER))); 2962. incr_itimeout(&Glib, d(2,10)); 2963. } else if (obj->oclass != WEAPON_CLASS && !is_weptool(obj)) { 2964. /* the following cases apply only to weapons */ 2965. goto more_dips; 2966. /* Oil removes rust and corrosion, but doesn't unburn. 2967. * Arrows, etc are classed as metallic due to arrowhead 2968. * material, but dipping in oil shouldn't repair them. 2969. */ 2970. } else if ((!is_rustprone(obj) && !is_corrodeable(obj)) || 2971. is_ammo(obj) || (!obj->oeroded && !obj->oeroded2)) { 2972. /* uses up potion, doesn't set obj->greased */ 2973. pline("%s %s with an oily sheen.", 2974. Yname2(obj), otense(obj, "gleam")); 2975. } else { 2976. pline("%s %s less %s.", 2977. Yname2(obj), otense(obj, "are"), 2978. (obj->oeroded && obj->oeroded2) ? "corroded and rusty" : 2979. obj->oeroded ? "rusty" : "corroded"); 2980. if (obj->oeroded > 0) obj->oeroded--; 2981. if (obj->oeroded2 > 0) obj->oeroded2--; 2982. wisx = TRUE; 2983. } 2984. exercise(A_WIS, wisx); 2985. makeknown(potion->otyp); 2986. useup(potion); 2987. return 1; 2988. } 2989. 2990. /* KMH, balance patch -- acid affects damage(proofing) */ 2991. if (potion->otyp == POT_ACID && (obj->oclass == ARMOR_CLASS || 2992. obj->oclass == WEAPON_CLASS || is_weptool(obj))) { 2993. if (!potion->blessed && obj->oerodeproof) { 2994. pline("%s %s golden shield.", Yname2(obj), 2995. (obj->quan > 1L) ? "lose their" : "loses its"); 2996. obj->oerodeproof = 0; 2997. makeknown(potion->otyp); 2998. } else { 2999. pline("%s looks a little dull.", Yname2(obj)); 3000. if (!objects[potion->otyp].oc_name_known && 3001. !objects[potion->otyp].oc_uname) 3002. docall(potion); 3003. } 3004. exercise(A_WIS, FALSE); 3005. useup(potion); 3006. return 1; 3007. } 3008. more_dips: 3009. 3010. /* Allow filling of MAGIC_LAMPs to prevent identification by player */ 3011. if ((obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP) && 3012. (potion->otyp == POT_OIL)) { 3013. 3014. /* Turn off engine before fueling, turn off fuel too :-) */ 3015. if (obj->lamplit || potion->lamplit) { 3016. useup(potion); 3017. explode(u.ux, u.uy, ZT_SPELL(ZT_FIRE), d(6,6), 0, EXPL_FIERY); 3018. exercise(A_WIS, FALSE); 3019. return 1; 3020. } 3021. /* Adding oil to an empty magic lamp renders it into an oil lamp */ 3022. if ((obj->otyp == MAGIC_LAMP) && obj->spe == 0) { 3023. obj->otyp = OIL_LAMP; 3024. obj->age = 0; 3025. } 3026. if (obj->age > 1000L) { 3027. pline("%s %s full.", Yname2(obj), otense(obj, "are")); 3028. potion->in_use = FALSE; /* didn't go poof */ 3029. } else { 3030. You("fill your %s with oil.", yname(obj)); 3031. check_unpaid(potion); /* Yendorian Fuel Tax */ 3032. obj->age += 2*potion->age; /* burns more efficiently */ 3033. if (obj->age > 1500L) obj->age = 1500L; 3034. useup(potion); 3035. exercise(A_WIS, TRUE); 3036. } 3037. makeknown(POT_OIL); 3038. obj->spe = 1; 3039. update_inventory(); 3040. return 1; 3041. } 3042. 3043. potion->in_use = FALSE; /* didn't go poof */ 3044. if ((obj->otyp == UNICORN_HORN || obj->oclass == GEM_CLASS) && 3045. (mixture = mixtype(obj, potion)) != 0) { 3046. char oldbuf[BUFSZ], newbuf[BUFSZ]; 3047. short old_otyp = potion->otyp; 3048. boolean old_dknown = FALSE; 3049. boolean more_than_one = potion->quan > 1; 3050. 3051. oldbuf[0] = '\0'; 3052. if (potion->dknown) { 3053. old_dknown = TRUE; 3054. Sprintf(oldbuf, "%s ", 3055. hcolor(OBJ_DESCR(objects[potion->otyp]))); 3056. } 3057. /* with multiple merged potions, split off one and 3058. just clear it */ 3059. if (potion->quan > 1L) { 3060. singlepotion = splitobj(potion, 1L); 3061. } else singlepotion = potion; 3062. 3063. /* MRKR: Gems dissolve in acid to produce new potions */ 3064. 3065. if (obj->oclass == GEM_CLASS && potion->otyp == POT_ACID) { 3066. struct obj *singlegem = (obj->quan > 1L ? 3067. splitobj(obj, 1L) : obj); 3068. 3069. singlegem->in_use = TRUE; 3070. if (potion->otyp == POT_ACID && 3071. (obj->otyp == DILITHIUM_CRYSTAL || 3072. potion->cursed || !rn2(10))) { 3073. /* Just to keep them on their toes */ 3074. 3075. singlepotion->in_use = TRUE; 3076. if (Hallucination && obj->otyp == DILITHIUM_CRYSTAL) { 3077. /* Thanks to Robin Johnson */ 3078. pline("Warning, Captain! The warp core has been breached!"); 3079. } 3080. pline("BOOM! %s explodes!", The(xname(singlegem))); 3081. exercise(A_STR, FALSE); 3082. if (!breathless(youmonst.data) || haseyes(youmonst.data)) 3083. potionbreathe(singlepotion); 3084. useup(singlegem); 3085. useup(singlepotion); 3086. /* MRKR: an alchemy smock ought to be */ 3087. /* some protection against this: */ 3088. losehp(Acid_resistance ? rnd(5) : rnd(10), 3089. "alchemic blast", KILLED_BY_AN); 3090. return(1); 3091. } 3092. 3093. pline("%s dissolves in %s.", The(xname(singlegem)), 3094. the(xname(singlepotion))); 3095. makeknown(POT_ACID); 3096. useup(singlegem); 3097. } 3098. 3099. if(singlepotion->unpaid && costly_spot(u.ux, u.uy)) { 3100. You("use it, you pay for it."); 3101. bill_dummy_object(singlepotion); 3102. } 3103. 3104. if (singlepotion->otyp == mixture) { 3105. /* no change - merge it back in */ 3106. if (more_than_one && !merged(&potion, &singlepotion)) { 3107. /* should never happen */ 3108. impossible("singlepotion won't merge with parent potion."); 3109. } 3110. } else { 3111. singlepotion->otyp = mixture; 3112. singlepotion->blessed = 0; 3113. if (mixture == POT_WATER) 3114. singlepotion->cursed = singlepotion->odiluted = 0; 3115. else 3116. singlepotion->cursed = obj->cursed; /* odiluted left as-is */ 3117. singlepotion->bknown = FALSE; 3118. if (Blind) { 3119. singlepotion->dknown = FALSE; 3120. } else { 3121. singlepotion->dknown = !Hallucination; 3122. if (mixture == POT_WATER && singlepotion->dknown) 3123. Sprintf(newbuf, "clears"); 3124. else 3125. Sprintf(newbuf, "turns %s", 3126. hcolor(OBJ_DESCR(objects[mixture]))); 3127. pline_The("%spotion%s %s.", oldbuf, 3128. more_than_one ? " that you dipped into" : "", 3129. newbuf); 3130. if(!objects[old_otyp].oc_uname && 3131. !objects[old_otyp].oc_name_known && old_dknown) { 3132. struct obj fakeobj; 3133. fakeobj = zeroobj; 3134. fakeobj.dknown = 1; 3135. fakeobj.otyp = old_otyp; 3136. fakeobj.oclass = POTION_CLASS; 3137. docall(&fakeobj); 3138. } 3139. } 3140. obj_extract_self(singlepotion); 3141. singlepotion = hold_another_object(singlepotion, 3142. "You juggle and drop %s!", 3143. doname(singlepotion), (const char *)0); 3144. update_inventory(); 3145. } 3146. 3147. return(1); 3148. } 3149. 3150. pline("Interesting..."); 3151. return(1); 3152. } 3153. 3154. 3155. void 3156. djinni_from_bottle(obj) 3157. register struct obj *obj; 3158. { 3159. struct monst *mtmp; 3160. int genie_type; 3161. int chance; 3162. 3163. #if 0 3164. /* KMH -- See comments in monst.c */ 3165. switch (rn2(4)) { 3166. default: 3167. case 0: genie_type = PM_DJINNI; break; 3168. case 1: genie_type = PM_EFREETI; break; 3169. case 2: genie_type = PM_MARID; break; 3170. case 3: genie_type = PM_DAO; break; 3171. } 3172. #else 3173. genie_type = PM_DJINNI; 3174. #endif 3175. if(!(mtmp = makemon(&mons[genie_type], u.ux, u.uy, NO_MM_FLAGS))){ 3176. pline("It turns out to be empty."); 3177. return; 3178. } 3179. 3180. if (!Blind) { 3181. pline("In a cloud of smoke, %s emerges!", a_monnam(mtmp)); 3182. pline("%s speaks.", Monnam(mtmp)); 3183. } else { 3184. You("smell acrid fumes."); 3185. pline("%s speaks.", Something); 3186. } 3187. 3188. chance = rn2(5); 3189. if (obj->blessed) chance = (chance == 4) ? rnd(4) : 0; 3190. else if (obj->cursed) chance = (chance == 0) ? rn2(4) : 4; 3191. /* 0,1,2,3,4: b=80%,5,5,5,5; nc=20%,20,20,20,20; c=5%,5,5,5,80 */ 3192. 3193. switch (chance) { 3194. case 0 : verbalize("I am in your debt. I will grant one wish!"); 3195. makewish(); 3196. mongone(mtmp); 3197. break; 3198. case 1 : verbalize("Thank you for freeing me!"); 3199. (void) tamedog(mtmp, (struct obj *)0); 3200. break; 3201. case 2 : verbalize("You freed me!"); 3202. mtmp->mpeaceful = TRUE; 3203. set_malign(mtmp); 3204. break; 3205. case 3 : verbalize("It is about time!"); 3206. pline("%s vanishes.", Monnam(mtmp)); 3207. mongone(mtmp); 3208. break; 3209. default: verbalize("You disturbed me, fool!"); 3210. break; 3211. } 3212. } 3213. 3214. /* clone a gremlin or mold (2nd arg non-null implies heat as the trigger); 3215. hit points are cut in half (odd HP stays with original) */ 3216. struct monst * 3217. split_mon(mon, mtmp) 3218. struct monst *mon, /* monster being split */ 3219. *mtmp; /* optional attacker whose heat triggered it */ 3220. { 3221. struct monst *mtmp2; 3222. char reason[BUFSZ]; 3223. 3224. reason[0] = '\0'; 3225. if (mtmp) Sprintf(reason, " from %s heat", 3226. (mtmp == &youmonst) ? (const char *)"your" : 3227. (const char *)s_suffix(mon_nam(mtmp))); 3228. 3229. if (mon == &youmonst) { 3230. mtmp2 = cloneu(); 3231. if (mtmp2) { 3232. mtmp2->mhpmax = u.mhmax / 2; 3233. u.mhmax -= mtmp2->mhpmax; 3234. flags.botl = 1; 3235. You("multiply%s!", reason); 3236. } 3237. } else { 3238. mtmp2 = clone_mon(mon, 0, 0); 3239. if (mtmp2) { 3240. mtmp2->mhpmax = mon->mhpmax / 2; 3241. mon->mhpmax -= mtmp2->mhpmax; 3242. if (canspotmon(mon)) 3243. pline("%s multiplies%s!", Monnam(mon), reason); 3244. } 3245. } 3246. return mtmp2; 3247. } 3248. 3249. #endif /* OVLB */ 3250. 3251. /*potion.c*/
Alternative Linked Data Views: ODE     Raw Data in: CXML | CSV | RDF ( N-Triples N3/Turtle JSON XML ) | OData ( Atom JSON ) | Microdata ( JSON HTML) | JSON-LD    About   
This material is Open Knowledge   W3C Semantic Web Technology [RDF Data] Valid XHTML + RDFa
OpenLink Virtuoso version 07.20.3217, on Linux (x86_64-pc-linux-gnu), Standard Edition
Data on this page belongs to its respective rights holders.
Virtuoso Faceted Browser Copyright © 2009-2012 OpenLink Software