Source:NetHack 3.4.3/src/potion.c

From NetHackWiki
Revision as of 18:37, 12 June 2006 by Jayt (talk | contribs) (upload)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Below is the full text to src/potion.c from NetHack 3.4.3. To link to a particular line, write [[potion.c#line123]], for example.

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. #ifdef OVLB
8. boolean notonhead = FALSE;
9.
10. static NEARDATA int nothing, unkn;
11. static NEARDATA const char beverages[] = { POTION_CLASS, 0 };
12.
13. STATIC_DCL long FDECL(itimeout, (long));
14. STATIC_DCL long FDECL(itimeout_incr, (long,int));
15. STATIC_DCL void NDECL(ghost_from_bottle);
16. STATIC_DCL short FDECL(mixtype, (struct obj *,struct obj *));
17.
18. /* force `val' to be within valid range for intrinsic timeout value */
19. STATIC_OVL long
20. itimeout(val)
21. long val;
22. {
23. if (val >= TIMEOUT) val = TIMEOUT;
24. else if (val < 1) val = 0;
25.
26. return val;
27. }
28.
29. /* increment `old' by `incr' and force result to be valid intrinsic timeout */
30. STATIC_OVL long
31. itimeout_incr(old, incr)
32. long old;
33. int incr;
34. {
35. return itimeout((old & TIMEOUT) + (long)incr);
36. }
37.
38. /* set the timeout field of intrinsic `which' */
39. void
40. set_itimeout(which, val)
41. long *which, val;
42. {
43. *which &= ~TIMEOUT;
44. *which |= itimeout(val);
45. }
46.
47. /* increment the timeout field of intrinsic `which' */
48. void
49. incr_itimeout(which, incr)
50. long *which;
51. int incr;
52. {
53. set_itimeout(which, itimeout_incr(*which, incr));
54. }
55.
56. void
57. make_confused(xtime,talk)
58. long xtime;
59. boolean talk;
60. {
61. long old = HConfusion;
62.
63. if (!xtime && old) {
64. if (talk)
65. You_feel("less %s now.",
66. Hallucination ? "trippy" : "confused");
67. }
68. if ((xtime && !old) || (!xtime && old)) flags.botl = TRUE;
69.
70. set_itimeout(&HConfusion, xtime);
71. }
72.
73. void
74. make_stunned(xtime,talk)
75. long xtime;
76. boolean talk;
77. {
78. long old = HStun;
79.
80. if (!xtime && old) {
81. if (talk)
82. You_feel("%s now.",
83. Hallucination ? "less wobbly" : "a bit steadier");
84. }
85. if (xtime && !old) {
86. if (talk) {
87. #ifdef STEED
88. if (u.usteed)
89. You("wobble in the saddle.");
90. else
91. #endif
92. You("%s...", stagger(youmonst.data, "stagger"));
93. }
94. }
95. if ((!xtime && old) || (xtime && !old)) flags.botl = TRUE;
96.
97. set_itimeout(&HStun, xtime);
98. }
99.
100. void
101. make_sick(xtime, cause, talk, type)
102. long xtime;
103. const char *cause; /* sickness cause */
104. boolean talk;
105. int type;
106. {
107. long old = Sick;
108.
109. if (xtime > 0L) {
110. if (Sick_resistance) return;
111. if (!old) {
112. /* newly sick */
113. You_feel("deathly sick.");
114. } else {
115. /* already sick */
116. if (talk) You_feel("%s worse.",
117. xtime <= Sick/2L ? "much" : "even");
118. }
119. set_itimeout(&Sick, xtime);
120. u.usick_type |= type;
121. flags.botl = TRUE;
122. } else if (old && (type & u.usick_type)) {
123. /* was sick, now not */
124. u.usick_type &= ~type;
125. if (u.usick_type) { /* only partly cured */
126. if (talk) You_feel("somewhat better.");
127. set_itimeout(&Sick, Sick * 2); /* approximation */
128. } else {
129. if (talk) pline("What a relief!");
130. Sick = 0L; /* set_itimeout(&Sick, 0L) */
131. }
132. flags.botl = TRUE;
133. }
134.
135. if (Sick) {
136. exercise(A_CON, FALSE);
137. if (cause) {
138. (void) strncpy(u.usick_cause, cause, sizeof(u.usick_cause));
139. u.usick_cause[sizeof(u.usick_cause)-1] = 0;
140. }
141. else
142. u.usick_cause[0] = 0;
143. } else
144. u.usick_cause[0] = 0;
145. }
146.
147. void
148. make_vomiting(xtime, talk)
149. long xtime;
150. boolean talk;
151. {
152. long old = Vomiting;
153.
154. if(!xtime && old)
155. if(talk) You_feel("much less nauseated now.");
156.
157. set_itimeout(&Vomiting, xtime);
158. }
159.
160. static const char vismsg[] = "vision seems to %s for a moment but is %s now.";
161. static const char eyemsg[] = "%s momentarily %s.";
162.
163. void
164. make_blinded(xtime, talk)
165. long xtime;
166. boolean talk;
167. {
168. long old = Blinded;
169. boolean u_could_see, can_see_now;
170. int eyecnt;
171. char buf[BUFSZ];
172.
173. /* we need to probe ahead in case the Eyes of the Overworld
174. are or will be overriding blindness */
175. u_could_see = !Blind;
176. Blinded = xtime ? 1L : 0L;
177. can_see_now = !Blind;
178. Blinded = old; /* restore */
179.
180. if (u.usleep) talk = FALSE;
181.
182. if (can_see_now && !u_could_see) { /* regaining sight */
183. if (talk) {
184. if (Hallucination)
185. pline("Far out! Everything is all cosmic again!");
186. else
187. You("can see again.");
188. }
189. } else if (old && !xtime) {
190. /* clearing temporary blindness without toggling blindness */
191. if (talk) {
192. if (!haseyes(youmonst.data)) {
193. strange_feeling((struct obj *)0, (char *)0);
194. } else if (Blindfolded) {
195. Strcpy(buf, body_part(EYE));
196. eyecnt = eyecount(youmonst.data);
197. Your(eyemsg, (eyecnt == 1) ? buf : makeplural(buf),
198. (eyecnt == 1) ? "itches" : "itch");
199. } else { /* Eyes of the Overworld */
200. Your(vismsg, "brighten",
201. Hallucination ? "sadder" : "normal");
202. }
203. }
204. }
205.
206. if (u_could_see && !can_see_now) { /* losing sight */
207. if (talk) {
208. if (Hallucination)
209. pline("Oh, bummer! Everything is dark! Help!");
210. else
211. pline("A cloud of darkness falls upon you.");
212. }
213. /* Before the hero goes blind, set the ball&chain variables. */
214. if (Punished) set_bc(0);
215. } else if (!old && xtime) {
216. /* setting temporary blindness without toggling blindness */
217. if (talk) {
218. if (!haseyes(youmonst.data)) {
219. strange_feeling((struct obj *)0, (char *)0);
220. } else if (Blindfolded) {
221. Strcpy(buf, body_part(EYE));
222. eyecnt = eyecount(youmonst.data);
223. Your(eyemsg, (eyecnt == 1) ? buf : makeplural(buf),
224. (eyecnt == 1) ? "twitches" : "twitch");
225. } else { /* Eyes of the Overworld */
226. Your(vismsg, "dim",
227. Hallucination ? "happier" : "normal");
228. }
229. }
230. }
231.
232. set_itimeout(&Blinded, xtime);
233.
234. if (u_could_see ^ can_see_now) { /* one or the other but not both */
235. flags.botl = 1;
236. vision_full_recalc = 1; /* blindness just got toggled */
237. if (Blind_telepat || Infravision) see_monsters();
238. }
239. }
240.
241. boolean
242. make_hallucinated(xtime, talk, mask)
243. long xtime; /* nonzero if this is an attempt to turn on hallucination */
244. boolean talk;
245. long mask; /* nonzero if resistance status should change by mask */
246. {
247. long old = HHallucination;
248. boolean changed = 0;
249. const char *message, *verb;
250.
251. message = (!xtime) ? "Everything %s SO boring now." :
252. "Oh wow! Everything %s so cosmic!";
253. verb = (!Blind) ? "looks" : "feels";
254.
255. if (mask) {
256. if (HHallucination) changed = TRUE;
257.
258. if (!xtime) EHalluc_resistance |= mask;
259. else EHalluc_resistance &= ~mask;
260. } else {
261. if (!EHalluc_resistance && (!!HHallucination != !!xtime))
262. changed = TRUE;
263. set_itimeout(&HHallucination, xtime);
264.
265. /* clearing temporary hallucination without toggling vision */
266. if (!changed && !HHallucination && old && talk) {
267. if (!haseyes(youmonst.data)) {
268. strange_feeling((struct obj *)0, (char *)0);
269. } else if (Blind) {
270. char buf[BUFSZ];
271. int eyecnt = eyecount(youmonst.data);
272.
273. Strcpy(buf, body_part(EYE));
274. Your(eyemsg, (eyecnt == 1) ? buf : makeplural(buf),
275. (eyecnt == 1) ? "itches" : "itch");
276. } else { /* Grayswandir */
277. Your(vismsg, "flatten", "normal");
278. }
279. }
280. }
281.
282. if (changed) {
283. if (u.uswallow) {
284. swallowed(0); /* redraw swallow display */
285. } else {
286. /* The see_* routines should be called *before* the pline. */
287. see_monsters();
288. see_objects();
289. see_traps();
290. }
291.
292. /* for perm_inv and anything similar
293. (eg. Qt windowport's equipped items display) */
294. update_inventory();
295.
296. flags.botl = 1;
297. if (talk) pline(message, verb);
298. }
299. return changed;
300. }
301.
302. STATIC_OVL void
303. ghost_from_bottle()
304. {
305. struct monst *mtmp = makemon(&mons[PM_GHOST], u.ux, u.uy, NO_MM_FLAGS);
306.
307. if (!mtmp) {
308. pline("This bottle turns out to be empty.");
309. return;
310. }
311. if (Blind) {
312. pline("As you open the bottle, %s emerges.", something);
313. return;
314. }
315. pline("As you open the bottle, an enormous %s emerges!",
316. Hallucination ? rndmonnam() : (const char *)"ghost");
317. if(flags.verbose)
318. You("are frightened to death, and unable to move.");
319. nomul(-3);
320. nomovemsg = "You regain your composure.";
321. }
322.
323. /* "Quaffing is like drinking, except you spill more." -- Terry Pratchett
324. */
325. int
326. dodrink()
327. {
328. register struct obj *otmp;
329. const char *potion_descr;
330.
331. if (Strangled) {
332. pline("If you can't breathe air, how can you drink liquid?");
333. return 0;
334. }
335. /* Is there a fountain to drink from here? */
336. if (IS_FOUNTAIN(levl[u.ux][u.uy].typ) && !Levitation) {
337. if(yn("Drink from the fountain?") == 'y') {
338. drinkfountain();
339. return 1;
340. }
341. }
342. #ifdef SINKS
343. /* Or a kitchen sink? */
344. if (IS_SINK(levl[u.ux][u.uy].typ)) {
345. if (yn("Drink from the sink?") == 'y') {
346. drinksink();
347. return 1;
348. }
349. }
350. #endif
351.
352. /* Or are you surrounded by water? */
353. if (Underwater) {
354. if (yn("Drink the water around you?") == 'y') {
355. pline("Do you know what lives in this water!");
356. return 1;
357. }
358. }
359.
360. otmp = getobj(beverages, "drink");
361. if(!otmp) return(0);
362. otmp->in_use = TRUE; /* you've opened the stopper */
363.
364. #define POTION_OCCUPANT_CHANCE(n) (13 + 2*(n)) /* also in muse.c */
365.
366. potion_descr = OBJ_DESCR(objects[otmp->otyp]);
367. if (potion_descr) {
368. if (!strcmp(potion_descr, "milky") &&
369. flags.ghost_count < MAXMONNO &&
370. !rn2(POTION_OCCUPANT_CHANCE(flags.ghost_count))) {
371. ghost_from_bottle();
372. useup(otmp);
373. return(1);
374. } else if (!strcmp(potion_descr, "smoky") &&
375. flags.djinni_count < MAXMONNO &&
376. !rn2(POTION_OCCUPANT_CHANCE(flags.djinni_count))) {
377. djinni_from_bottle(otmp);
378. useup(otmp);
379. return(1);
380. }
381. }
382. return dopotion(otmp);
383. }
384.
385. int
386. dopotion(otmp)
387. register struct obj *otmp;
388. {
389. int retval;
390.
391. otmp->in_use = TRUE;
392. nothing = unkn = 0;
393. if((retval = peffects(otmp)) >= 0) return(retval);
394.
395. if(nothing) {
396. unkn++;
397. You("have a %s feeling for a moment, then it passes.",
398. Hallucination ? "normal" : "peculiar");
399. }
400. if(otmp->dknown && !objects[otmp->otyp].oc_name_known) {
401. if(!unkn) {
402. makeknown(otmp->otyp);
403. more_experienced(0,10);
404. } else if(!objects[otmp->otyp].oc_uname)
405. docall(otmp);
406. }
407. useup(otmp);
408. return(1);
409. }
410.
411. int
412. peffects(otmp)
413. register struct obj *otmp;
414. {
415. register int i, ii, lim;
416.
417. switch(otmp->otyp){
418. case POT_RESTORE_ABILITY:
419. case SPE_RESTORE_ABILITY:
420. unkn++;
421. if(otmp->cursed) {
422. pline("Ulch! This makes you feel mediocre!");
423. break;
424. } else {
425. pline("Wow! This makes you feel %s!",
426. (otmp->blessed) ?
427. (unfixable_trouble_count(FALSE) ? "better" : "great")
428. : "good");
429. i = rn2(A_MAX); /* start at a random point */
430. for (ii = 0; ii < A_MAX; ii++) {
431. lim = AMAX(i);
432. if (i == A_STR && u.uhs >= 3) --lim; /* WEAK */
433. if (ABASE(i) < lim) {
434. ABASE(i) = lim;
435. flags.botl = 1;
436. /* only first found if not blessed */
437. if (!otmp->blessed) break;
438. }
439. if(++i >= A_MAX) i = 0;
440. }
441. }
442. break;
443. case POT_HALLUCINATION:
444. if (Hallucination || Halluc_resistance) nothing++;
445. (void) make_hallucinated(itimeout_incr(HHallucination,
446. rn1(200, 600 - 300 * bcsign(otmp))),
447. TRUE, 0L);
448. break;
449. case POT_WATER:
450. if(!otmp->blessed && !otmp->cursed) {
451. pline("This tastes like water.");
452. u.uhunger += rnd(10);
453. newuhs(FALSE);
454. break;
455. }
456. unkn++;
457. if(is_undead(youmonst.data) || is_demon(youmonst.data) ||
458. u.ualign.type == A_CHAOTIC) {
459. if(otmp->blessed) {
460. pline("This burns like acid!");
461. exercise(A_CON, FALSE);
462. if (u.ulycn >= LOW_PM) {
463. Your("affinity to %s disappears!",
464. makeplural(mons[u.ulycn].mname));
465. if (youmonst.data == &mons[u.ulycn])
466. you_unwere(FALSE);
467. u.ulycn = NON_PM; /* cure lycanthropy */
468. }
469. losehp(d(2,6), "potion of holy water", KILLED_BY_AN);
470. } else if(otmp->cursed) {
471. You_feel("quite proud of yourself.");
472. healup(d(2,6),0,0,0);
473. if (u.ulycn >= LOW_PM && !Upolyd) you_were();
474. exercise(A_CON, TRUE);
475. }
476. } else {
477. if(otmp->blessed) {
478. You_feel("full of awe.");
479. make_sick(0L, (char *) 0, TRUE, SICK_ALL);
480. exercise(A_WIS, TRUE);
481. exercise(A_CON, TRUE);
482. if (u.ulycn >= LOW_PM)
483. you_unwere(TRUE); /* "Purified" */
484. /* make_confused(0L,TRUE); */
485. } else {
486. if(u.ualign.type == A_LAWFUL) {
487. pline("This burns like acid!");
488. losehp(d(2,6), "potion of unholy water",
489. KILLED_BY_AN);
490. } else
491. You_feel("full of dread.");
492. if (u.ulycn >= LOW_PM && !Upolyd) you_were();
493. exercise(A_CON, FALSE);
494. }
495. }
496. break;
497. case POT_BOOZE:
498. unkn++;
499. pline("Ooph! This tastes like %s%s!",
500. otmp->odiluted ? "watered down " : "",
501. Hallucination ? "dandelion wine" : "liquid fire");
502. if (!otmp->blessed)
503. make_confused(itimeout_incr(HConfusion, d(3,8)), FALSE);
504. /* the whiskey makes us feel better */
505. if (!otmp->odiluted) healup(1, 0, FALSE, FALSE);
506. u.uhunger += 10 * (2 + bcsign(otmp));
507. newuhs(FALSE);
508. exercise(A_WIS, FALSE);
509. if(otmp->cursed) {
510. You("pass out.");
511. multi = -rnd(15);
512. nomovemsg = "You awake with a headache.";
513. }
514. break;
515. case POT_ENLIGHTENMENT:
516. if(otmp->cursed) {
517. unkn++;
518. You("have an uneasy feeling...");
519. exercise(A_WIS, FALSE);
520. } else {
521. if (otmp->blessed) {
522. (void) adjattrib(A_INT, 1, FALSE);
523. (void) adjattrib(A_WIS, 1, FALSE);
524. }
525. You_feel("self-knowledgeable...");
526. display_nhwindow(WIN_MESSAGE, FALSE);
527. enlightenment(0);
528. pline_The("feeling subsides.");
529. exercise(A_WIS, TRUE);
530. }
531. break;
532. case SPE_INVISIBILITY:
533. /* spell cannot penetrate mummy wrapping */
534. if (BInvis && uarmc->otyp == MUMMY_WRAPPING) {
535. You_feel("rather itchy under your %s.", xname(uarmc));
536. break;
537. }
538. /* FALLTHRU */
539. case POT_INVISIBILITY:
540. if (Invis || Blind || BInvis) {
541. nothing++;
542. } else {
543. self_invis_message();
544. }
545. if (otmp->blessed) HInvis |= FROMOUTSIDE;
546. else incr_itimeout(&HInvis, rn1(15,31));
547. newsym(u.ux,u.uy); /* update position */
548. if(otmp->cursed) {
549. pline("For some reason, you feel your presence is known.");
550. aggravate();
551. }
552. break;
553. case POT_SEE_INVISIBLE:
554. /* tastes like fruit juice in Rogue */
555. case POT_FRUIT_JUICE:
556. {
557. int msg = Invisible && !Blind;
558.
559. unkn++;
560. if (otmp->cursed)
561. pline("Yecch! This tastes %s.",
562. Hallucination ? "overripe" : "rotten");
563. else
564. pline(Hallucination ?
565. "This tastes like 10%% real %s%s all-natural beverage." :
566. "This tastes like %s%s.",
567. otmp->odiluted ? "reconstituted " : "",
568. fruitname(TRUE));
569. if (otmp->otyp == POT_FRUIT_JUICE) {
570. u.uhunger += (otmp->odiluted ? 5 : 10) * (2 + bcsign(otmp));
571. newuhs(FALSE);
572. break;
573. }
574. if (!otmp->cursed) {
575. /* Tell them they can see again immediately, which
576. * will help them identify the potion...
577. */
578. make_blinded(0L,TRUE);
579. }
580. if (otmp->blessed)
581. HSee_invisible |= FROMOUTSIDE;
582. else
583. incr_itimeout(&HSee_invisible, rn1(100,750));
584. set_mimic_blocking(); /* do special mimic handling */
585. see_monsters(); /* see invisible monsters */
586. newsym(u.ux,u.uy); /* see yourself! */
587. if (msg && !Blind) { /* Blind possible if polymorphed */
588. You("can see through yourself, but you are visible!");
589. unkn--;
590. }
591. break;
592. }
593. case POT_PARALYSIS:
594. if (Free_action)
595. You("stiffen momentarily.");
596. else {
597. if (Levitation || Is_airlevel(&u.uz)||Is_waterlevel(&u.uz))
598. You("are motionlessly suspended.");
599. #ifdef STEED
600. else if (u.usteed)
601. You("are frozen in place!");
602. #endif
603. else
604. Your("%s are frozen to the %s!",
605. makeplural(body_part(FOOT)), surface(u.ux, u.uy));
606. nomul(-(rn1(10, 25 - 12*bcsign(otmp))));
607. nomovemsg = You_can_move_again;
608. exercise(A_DEX, FALSE);
609. }
610. break;
611. case POT_SLEEPING:
612. if(Sleep_resistance || Free_action)
613. You("yawn.");
614. else {
615. You("suddenly fall asleep!");
616. fall_asleep(-rn1(10, 25 - 12*bcsign(otmp)), TRUE);
617. }
618. break;
619. case POT_MONSTER_DETECTION:
620. case SPE_DETECT_MONSTERS:
621. if (otmp->blessed) {
622. int x, y;
623.
624. if (Detect_monsters) nothing++;
625. unkn++;
626. /* after a while, repeated uses become less effective */
627. if (HDetect_monsters >= 300L)
628. i = 1;
629. else
630. i = rn1(40,21);
631. incr_itimeout(&HDetect_monsters, i);
632. for (x = 1; x < COLNO; x++) {
633. for (y = 0; y < ROWNO; y++) {
634. if (levl[x][y].glyph == GLYPH_INVISIBLE) {
635. unmap_object(x, y);
636. newsym(x,y);
637. }
638. if (MON_AT(x,y)) unkn = 0;
639. }
640. }
641. see_monsters();
642. if (unkn) You_feel("lonely.");
643. break;
644. }
645. if (monster_detect(otmp, 0))
646. return(1); /* nothing detected */
647. exercise(A_WIS, TRUE);
648. break;
649. case POT_OBJECT_DETECTION:
650. case SPE_DETECT_TREASURE:
651. if (object_detect(otmp, 0))
652. return(1); /* nothing detected */
653. exercise(A_WIS, TRUE);
654. break;
655. case POT_SICKNESS:
656. pline("Yecch! This stuff tastes like poison.");
657. if (otmp->blessed) {
658. pline("(But in fact it was mildly stale %s.)",
659. fruitname(TRUE));
660. if (!Role_if(PM_HEALER)) {
661. /* NB: blessed otmp->fromsink is not possible */
662. losehp(1, "mildly contaminated potion", KILLED_BY_AN);
663. }
664. } else {
665. if(Poison_resistance)
666. pline(
667. "(But in fact it was biologically contaminated %s.)",
668. fruitname(TRUE));
669. if (Role_if(PM_HEALER))
670. pline("Fortunately, you have been immunized.");
671. else {
672. int typ = rn2(A_MAX);
673.
674. if (!Fixed_abil) {
675. poisontell(typ);
676. (void) adjattrib(typ,
677. Poison_resistance ? -1 : -rn1(4,3),
678. TRUE);
679. }
680. if(!Poison_resistance) {
681. if (otmp->fromsink)
682. losehp(rnd(10)+5*!!(otmp->cursed),
683. "contaminated tap water", KILLED_BY);
684. else
685. losehp(rnd(10)+5*!!(otmp->cursed),
686. "contaminated potion", KILLED_BY_AN);
687. }
688. exercise(A_CON, FALSE);
689. }
690. }
691. if(Hallucination) {
692. You("are shocked back to your senses!");
693. (void) make_hallucinated(0L,FALSE,0L);
694. }
695. break;
696. case POT_CONFUSION:
697. if(!Confusion)
698. if (Hallucination) {
699. pline("What a trippy feeling!");
700. unkn++;
701. } else
702. pline("Huh, What? Where am I?");
703. else nothing++;
704. make_confused(itimeout_incr(HConfusion,
705. rn1(7, 16 - 8 * bcsign(otmp))),
706. FALSE);
707. break;
708. case POT_GAIN_ABILITY:
709. if(otmp->cursed) {
710. pline("Ulch! That potion tasted foul!");
711. unkn++;
712. } else if (Fixed_abil) {
713. nothing++;
714. } else { /* If blessed, increase all; if not, try up to */
715. int itmp; /* 6 times to find one which can be increased. */
716. i = -1; /* increment to 0 */
717. for (ii = A_MAX; ii > 0; ii--) {
718. i = (otmp->blessed ? i + 1 : rn2(A_MAX));
719. /* only give "your X is already as high as it can get"
720. message on last attempt (except blessed potions) */
721. itmp = (otmp->blessed || ii == 1) ? 0 : -1;
722. if (adjattrib(i, 1, itmp) && !otmp->blessed)
723. break;
724. }
725. }
726. break;
727. case POT_SPEED:
728. if(Wounded_legs && !otmp->cursed
729. #ifdef STEED
730. && !u.usteed /* heal_legs() would heal steeds legs */
731. #endif
732. ) {
733. heal_legs();
734. unkn++;
735. break;
736. } /* and fall through */
737. case SPE_HASTE_SELF:
738. if(!Very_fast) /* wwf@doe.carleton.ca */
739. You("are suddenly moving %sfaster.",
740. Fast ? "" : "much ");
741. else {
742. Your("%s get new energy.",
743. makeplural(body_part(LEG)));
744. unkn++;
745. }
746. exercise(A_DEX, TRUE);
747. incr_itimeout(&HFast, rn1(10, 100 + 60 * bcsign(otmp)));
748. break;
749. case POT_BLINDNESS:
750. if(Blind) nothing++;
751. make_blinded(itimeout_incr(Blinded,
752. rn1(200, 250 - 125 * bcsign(otmp))),
753. (boolean)!Blind);
754. break;
755. case POT_GAIN_LEVEL:
756. if (otmp->cursed) {
757. unkn++;
758. /* they went up a level */
759. if((ledger_no(&u.uz) == 1 && u.uhave.amulet) ||
760. Can_rise_up(u.ux, u.uy, &u.uz)) {
761. const char *riseup ="rise up, through the %s!";
762. if(ledger_no(&u.uz) == 1) {
763. You(riseup, ceiling(u.ux,u.uy));
764. goto_level(&earth_level, FALSE, FALSE, FALSE);
765. } else {
766. register int newlev = depth(&u.uz)-1;
767. d_level newlevel;
768.
769. get_level(&newlevel, newlev);
770. if(on_level(&newlevel, &u.uz)) {
771. pline("It tasted bad.");
772. break;
773. } else You(riseup, ceiling(u.ux,u.uy));
774. goto_level(&newlevel, FALSE, FALSE, FALSE);
775. }
776. }
777. else You("have an uneasy feeling.");
778. break;
779. }
780. pluslvl(FALSE);
781. if (otmp->blessed)
782. /* blessed potions place you at a random spot in the
783. * middle of the new level instead of the low point
784. */
785. u.uexp = rndexp(TRUE);
786. break;
787. case POT_HEALING:
788. You_feel("better.");
789. healup(d(6 + 2 * bcsign(otmp), 4),
790. !otmp->cursed ? 1 : 0, !!otmp->blessed, !otmp->cursed);
791. exercise(A_CON, TRUE);
792. break;
793. case POT_EXTRA_HEALING:
794. You_feel("much better.");
795. healup(d(6 + 2 * bcsign(otmp), 8),
796. otmp->blessed ? 5 : !otmp->cursed ? 2 : 0,
797. !otmp->cursed, TRUE);
798. (void) make_hallucinated(0L,TRUE,0L);
799. exercise(A_CON, TRUE);
800. exercise(A_STR, TRUE);
801. break;
802. case POT_FULL_HEALING:
803. You_feel("completely healed.");
804. healup(400, 4+4*bcsign(otmp), !otmp->cursed, TRUE);
805. /* Restore one lost level if blessed */
806. if (otmp->blessed && u.ulevel < u.ulevelmax) {
807. /* when multiple levels have been lost, drinking
808. multiple potions will only get half of them back */
809. u.ulevelmax -= 1;
810. pluslvl(FALSE);
811. }
812. (void) make_hallucinated(0L,TRUE,0L);
813. exercise(A_STR, TRUE);
814. exercise(A_CON, TRUE);
815. break;
816. case POT_LEVITATION:
817. case SPE_LEVITATION:
818. if (otmp->cursed) HLevitation &= ~I_SPECIAL;
819. if(!Levitation) {
820. /* kludge to ensure proper operation of float_up() */
821. HLevitation = 1;
822. float_up();
823. /* reverse kludge */
824. HLevitation = 0;
825. if (otmp->cursed && !Is_waterlevel(&u.uz)) {
826. if((u.ux != xupstair || u.uy != yupstair)
827. && (u.ux != sstairs.sx || u.uy != sstairs.sy || !sstairs.up)
828. && (!xupladder || u.ux != xupladder || u.uy != yupladder)
829. ) {
830. You("hit your %s on the %s.",
831. body_part(HEAD),
832. ceiling(u.ux,u.uy));
833. losehp(uarmh ? 1 : rnd(10),
834. "colliding with the ceiling",
835. KILLED_BY);
836. } else (void) doup();
837. }
838. } else
839. nothing++;
840. if (otmp->blessed) {
841. incr_itimeout(&HLevitation, rn1(50,250));
842. HLevitation |= I_SPECIAL;
843. } else incr_itimeout(&HLevitation, rn1(140,10));
844. spoteffects(FALSE); /* for sinks */
845. break;
846. case POT_GAIN_ENERGY: /* M. Stephenson */
847. { register int num;
848. if(otmp->cursed)
849. You_feel("lackluster.");
850. else
851. pline("Magical energies course through your body.");
852. num = rnd(5) + 5 * otmp->blessed + 1;
853. u.uenmax += (otmp->cursed) ? -num : num;
854. u.uen += (otmp->cursed) ? -num : num;
855. if(u.uenmax <= 0) u.uenmax = 0;
856. if(u.uen <= 0) u.uen = 0;
857. flags.botl = 1;
858. exercise(A_WIS, TRUE);
859. }
860. break;
861. case POT_OIL: /* P. Winner */
862. {
863. boolean good_for_you = FALSE;
864.
865. if (otmp->lamplit) {
866. if (likes_fire(youmonst.data)) {
867. pline("Ahh, a refreshing drink.");
868. good_for_you = TRUE;
869. } else {
870. You("burn your %s.", body_part(FACE));
871. losehp(d(Fire_resistance ? 1 : 3, 4),
872. "burning potion of oil", KILLED_BY_AN);
873. }
874. } else if(otmp->cursed)
875. pline("This tastes like castor oil.");
876. else
877. pline("That was smooth!");
878. exercise(A_WIS, good_for_you);
879. }
880. break;
881. case POT_ACID:
882. if (Acid_resistance)
883. /* Not necessarily a creature who _likes_ acid */
884. pline("This tastes %s.", Hallucination ? "tangy" : "sour");
885. else {
886. pline("This burns%s!", otmp->blessed ? " a little" :
887. otmp->cursed ? " a lot" : " like acid");
888. losehp(d(otmp->cursed ? 2 : 1, otmp->blessed ? 4 : 8),
889. "potion of acid", KILLED_BY_AN);
890. exercise(A_CON, FALSE);
891. }
892. if (Stoned) fix_petrification();
893. unkn++; /* holy/unholy water can burn like acid too */
894. break;
895. case POT_POLYMORPH:
896. You_feel("a little %s.", Hallucination ? "normal" : "strange");
897. if (!Unchanging) polyself(FALSE);
898. break;
899. default:
900. impossible("What a funny potion! (%u)", otmp->otyp);
901. return(0);
902. }
903. return(-1);
904. }
905.
906. void
907. healup(nhp, nxtra, curesick, cureblind)
908. int nhp, nxtra;
909. register boolean curesick, cureblind;
910. {
911. if (nhp) {
912. if (Upolyd) {
913. u.mh += nhp;
914. if (u.mh > u.mhmax) u.mh = (u.mhmax += nxtra);
915. } else {
916. u.uhp += nhp;
917. if(u.uhp > u.uhpmax) u.uhp = (u.uhpmax += nxtra);
918. }
919. }
920. if(cureblind) make_blinded(0L,TRUE);
921. if(curesick) make_sick(0L, (char *) 0, TRUE, SICK_ALL);
922. flags.botl = 1;
923. return;
924. }
925.
926. void
927. strange_feeling(obj,txt)
928. register struct obj *obj;
929. register const char *txt;
930. {
931. if (flags.beginner || !txt)
932. You("have a %s feeling for a moment, then it passes.",
933. Hallucination ? "normal" : "strange");
934. else
935. pline(txt);
936.
937. if(!obj) /* e.g., crystal ball finds no traps */
938. return;
939.
940. if(obj->dknown && !objects[obj->otyp].oc_name_known &&
941. !objects[obj->otyp].oc_uname)
942. docall(obj);
943. useup(obj);
944. }
945.
946. const char *bottlenames[] = {
947. "bottle", "phial", "flagon", "carafe", "flask", "jar", "vial"
948. };
949.
950.
951. const char *
952. bottlename()
953. {
954. return bottlenames[rn2(SIZE(bottlenames))];
955. }
956.
957. void
958. potionhit(mon, obj, your_fault)
959. register struct monst *mon;
960. register struct obj *obj;
961. boolean your_fault;
962. {
963. register const char *botlnam = bottlename();
964. boolean isyou = (mon == &youmonst);
965. int distance;
966.
967. if(isyou) {
968. distance = 0;
969. pline_The("%s crashes on your %s and breaks into shards.",
970. botlnam, body_part(HEAD));
971. losehp(rnd(2), "thrown potion", KILLED_BY_AN);
972. } else {
973. distance = distu(mon->mx,mon->my);
974. if (!cansee(mon->mx,mon->my)) pline("Crash!");
975. else {
976. char *mnam = mon_nam(mon);
977. char buf[BUFSZ];
978.
979. if(has_head(mon->data)) {
980. Sprintf(buf, "%s %s",
981. s_suffix(mnam),
982. (notonhead ? "body" : "head"));
983. } else {
984. Strcpy(buf, mnam);
985. }
986. pline_The("%s crashes on %s and breaks into shards.",
987. botlnam, buf);
988. }
989. if(rn2(5) && mon->mhp > 1)
990. mon->mhp--;
991. }
992.
993. /* oil doesn't instantly evaporate */
994. if (obj->otyp != POT_OIL && cansee(mon->mx,mon->my))
995. pline("%s.", Tobjnam(obj, "evaporate"));
996.
997. if (isyou) {
998. switch (obj->otyp) {
999. case POT_OIL:
1000. if (obj->lamplit)
1001. splatter_burning_oil(u.ux, u.uy);
1002. break;
1003. case POT_POLYMORPH:
1004. You_feel("a little %s.", Hallucination ? "normal" : "strange");
1005. if (!Unchanging && !Antimagic) polyself(FALSE);
1006. break;
1007. case POT_ACID:
1008. if (!Acid_resistance) {
1009. pline("This burns%s!", obj->blessed ? " a little" :
1010. obj->cursed ? " a lot" : "");
1011. losehp(d(obj->cursed ? 2 : 1, obj->blessed ? 4 : 8),
1012. "potion of acid", KILLED_BY_AN);
1013. }
1014. break;
1015. }
1016. } else {
1017. boolean angermon = TRUE;
1018.
1019. if (!your_fault) angermon = FALSE;
1020. switch (obj->otyp) {
1021. case POT_HEALING:
1022. case POT_EXTRA_HEALING:
1023. case POT_FULL_HEALING:
1024. if (mon->data == &mons[PM_PESTILENCE]) goto do_illness;
1025. /*FALLTHRU*/
1026. case POT_RESTORE_ABILITY:
1027. case POT_GAIN_ABILITY:
1028. do_healing:
1029. angermon = FALSE;
1030. if(mon->mhp < mon->mhpmax) {
1031. mon->mhp = mon->mhpmax;
1032. if (canseemon(mon))
1033. pline("%s looks sound and hale again.", Monnam(mon));
1034. }
1035. break;
1036. case POT_SICKNESS:
1037. if (mon->data == &mons[PM_PESTILENCE]) goto do_healing;
1038. if (dmgtype(mon->data, AD_DISE) ||
1039. dmgtype(mon->data, AD_PEST) || /* won't happen, see prior goto */
1040. resists_poison(mon)) {
1041. if (canseemon(mon))
1042. pline("%s looks unharmed.", Monnam(mon));
1043. break;
1044. }
1045. do_illness:
1046. if((mon->mhpmax > 3) && !resist(mon, POTION_CLASS, 0, NOTELL))
1047. mon->mhpmax /= 2;
1048. if((mon->mhp > 2) && !resist(mon, POTION_CLASS, 0, NOTELL))
1049. mon->mhp /= 2;
1050. if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax;
1051. if (canseemon(mon))
1052. pline("%s looks rather ill.", Monnam(mon));
1053. break;
1054. case POT_CONFUSION:
1055. case POT_BOOZE:
1056. if(!resist(mon, POTION_CLASS, 0, NOTELL)) mon->mconf = TRUE;
1057. break;
1058. case POT_INVISIBILITY:
1059. angermon = FALSE;
1060. mon_set_minvis(mon);
1061. break;
1062. case POT_SLEEPING:
1063. /* wakeup() doesn't rouse victims of temporary sleep */
1064. if (sleep_monst(mon, rnd(12), POTION_CLASS)) {
1065. pline("%s falls asleep.", Monnam(mon));
1066. slept_monst(mon);
1067. }
1068. break;
1069. case POT_PARALYSIS:
1070. if (mon->mcanmove) {
1071. mon->mcanmove = 0;
1072. /* really should be rnd(5) for consistency with players
1073. * breathing potions, but...
1074. */
1075. mon->mfrozen = rnd(25);
1076. }
1077. break;
1078. case POT_SPEED:
1079. angermon = FALSE;
1080. mon_adjust_speed(mon, 1, obj);
1081. break;
1082. case POT_BLINDNESS:
1083. if(haseyes(mon->data)) {
1084. register int btmp = 64 + rn2(32) +
1085. rn2(32) * !resist(mon, POTION_CLASS, 0, NOTELL);
1086. btmp += mon->mblinded;
1087. mon->mblinded = min(btmp,127);
1088. mon->mcansee = 0;
1089. }
1090. break;
1091. case POT_WATER:
1092. if (is_undead(mon->data) || is_demon(mon->data) ||
1093. is_were(mon->data)) {
1094. if (obj->blessed) {
1095. pline("%s %s in pain!", Monnam(mon),
1096. is_silent(mon->data) ? "writhes" : "shrieks");
1097. mon->mhp -= d(2,6);
1098. /* should only be by you */
1099. if (mon->mhp < 1) killed(mon);
1100. else if (is_were(mon->data) && !is_human(mon->data))
1101. new_were(mon); /* revert to human */
1102. } else if (obj->cursed) {
1103. angermon = FALSE;
1104. if (canseemon(mon))
1105. pline("%s looks healthier.", Monnam(mon));
1106. mon->mhp += d(2,6);
1107. if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax;
1108. if (is_were(mon->data) && is_human(mon->data) &&
1109. !Protection_from_shape_changers)
1110. new_were(mon); /* transform into beast */
1111. }
1112. } else if(mon->data == &mons[PM_GREMLIN]) {
1113. angermon = FALSE;
1114. (void)split_mon(mon, (struct monst *)0);
1115. } else if(mon->data == &mons[PM_IRON_GOLEM]) {
1116. if (canseemon(mon))
1117. pline("%s rusts.", Monnam(mon));
1118. mon->mhp -= d(1,6);
1119. /* should only be by you */
1120. if (mon->mhp < 1) killed(mon);
1121. }
1122. break;
1123. case POT_OIL:
1124. if (obj->lamplit)
1125. splatter_burning_oil(mon->mx, mon->my);
1126. break;
1127. case POT_ACID:
1128. if (!resists_acid(mon) && !resist(mon, POTION_CLASS, 0, NOTELL)) {
1129. pline("%s %s in pain!", Monnam(mon),
1130. is_silent(mon->data) ? "writhes" : "shrieks");
1131. mon->mhp -= d(obj->cursed ? 2 : 1, obj->blessed ? 4 : 8);
1132. if (mon->mhp < 1) {
1133. if (your_fault)
1134. killed(mon);
1135. else
1136. monkilled(mon, "", AD_ACID);
1137. }
1138. }
1139. break;
1140. case POT_POLYMORPH:
1141. (void) bhitm(mon, obj);
1142. break;
1143. /*
1144. case POT_GAIN_LEVEL:
1145. case POT_LEVITATION:
1146. case POT_FRUIT_JUICE:
1147. case POT_MONSTER_DETECTION:
1148. case POT_OBJECT_DETECTION:
1149. break;
1150. */
1151. }
1152. if (angermon)
1153. wakeup(mon);
1154. else
1155. mon->msleeping = 0;
1156. }
1157.
1158. /* Note: potionbreathe() does its own docall() */
1159. if ((distance==0 || ((distance < 3) && rn2(5))) &&
1160. (!breathless(youmonst.data) || haseyes(youmonst.data)))
1161. potionbreathe(obj);
1162. else if (obj->dknown && !objects[obj->otyp].oc_name_known &&
1163. !objects[obj->otyp].oc_uname && cansee(mon->mx,mon->my))
1164. docall(obj);
1165. if(*u.ushops && obj->unpaid) {
1166. register struct monst *shkp =
1167. shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE));
1168.
1169. if(!shkp)
1170. obj->unpaid = 0;
1171. else {
1172. (void)stolen_value(obj, u.ux, u.uy,
1173. (boolean)shkp->mpeaceful, FALSE);
1174. subfrombill(obj, shkp);
1175. }
1176. }
1177. obfree(obj, (struct obj *)0);
1178. }
1179.
1180. /* vapors are inhaled or get in your eyes */
1181. void
1182. potionbreathe(obj)
1183. register struct obj *obj;
1184. {
1185. register int i, ii, isdone, kn = 0;
1186.
1187. switch(obj->otyp) {
1188. case POT_RESTORE_ABILITY:
1189. case POT_GAIN_ABILITY:
1190. if(obj->cursed) {
1191. if (!breathless(youmonst.data))
1192. pline("Ulch! That potion smells terrible!");
1193. else if (haseyes(youmonst.data)) {
1194. int numeyes = eyecount(youmonst.data);
1195. Your("%s sting%s!",
1196. (numeyes == 1) ? body_part(EYE) : makeplural(body_part(EYE)),
1197. (numeyes == 1) ? "s" : "");
1198. }
1199. break;
1200. } else {
1201. i = rn2(A_MAX); /* start at a random point */
1202. for(isdone = ii = 0; !isdone && ii < A_MAX; ii++) {
1203. if(ABASE(i) < AMAX(i)) {
1204. ABASE(i)++;
1205. /* only first found if not blessed */
1206. isdone = !(obj->blessed);
1207. flags.botl = 1;
1208. }
1209. if(++i >= A_MAX) i = 0;
1210. }
1211. }
1212. break;
1213. case POT_FULL_HEALING:
1214. if (Upolyd && u.mh < u.mhmax) u.mh++, flags.botl = 1;
1215. if (u.uhp < u.uhpmax) u.uhp++, flags.botl = 1;
1216. /*FALL THROUGH*/
1217. case POT_EXTRA_HEALING:
1218. if (Upolyd && u.mh < u.mhmax) u.mh++, flags.botl = 1;
1219. if (u.uhp < u.uhpmax) u.uhp++, flags.botl = 1;
1220. /*FALL THROUGH*/
1221. case POT_HEALING:
1222. if (Upolyd && u.mh < u.mhmax) u.mh++, flags.botl = 1;
1223. if (u.uhp < u.uhpmax) u.uhp++, flags.botl = 1;
1224. exercise(A_CON, TRUE);
1225. break;
1226. case POT_SICKNESS:
1227. if (!Role_if(PM_HEALER)) {
1228. if (Upolyd) {
1229. if (u.mh <= 5) u.mh = 1; else u.mh -= 5;
1230. } else {
1231. if (u.uhp <= 5) u.uhp = 1; else u.uhp -= 5;
1232. }
1233. flags.botl = 1;
1234. exercise(A_CON, FALSE);
1235. }
1236. break;
1237. case POT_HALLUCINATION:
1238. You("have a momentary vision.");
1239. break;
1240. case POT_CONFUSION:
1241. case POT_BOOZE:
1242. if(!Confusion)
1243. You_feel("somewhat dizzy.");
1244. make_confused(itimeout_incr(HConfusion, rnd(5)), FALSE);
1245. break;
1246. case POT_INVISIBILITY:
1247. if (!Blind && !Invis) {
1248. kn++;
1249. pline("For an instant you %s!",
1250. See_invisible ? "could see right through yourself"
1251. : "couldn't see yourself");
1252. }
1253. break;
1254. case POT_PARALYSIS:
1255. kn++;
1256. if (!Free_action) {
1257. pline("%s seems to be holding you.", Something);
1258. nomul(-rnd(5));
1259. nomovemsg = You_can_move_again;
1260. exercise(A_DEX, FALSE);
1261. } else You("stiffen momentarily.");
1262. break;
1263. case POT_SLEEPING:
1264. kn++;
1265. if (!Free_action && !Sleep_resistance) {
1266. You_feel("rather tired.");
1267. nomul(-rnd(5));
1268. nomovemsg = You_can_move_again;
1269. exercise(A_DEX, FALSE);
1270. } else You("yawn.");
1271. break;
1272. case POT_SPEED:
1273. if (!Fast) Your("knees seem more flexible now.");
1274. incr_itimeout(&HFast, rnd(5));
1275. exercise(A_DEX, TRUE);
1276. break;
1277. case POT_BLINDNESS:
1278. if (!Blind && !u.usleep) {
1279. kn++;
1280. pline("It suddenly gets dark.");
1281. }
1282. make_blinded(itimeout_incr(Blinded, rnd(5)), FALSE);
1283. if (!Blind && !u.usleep) Your(vision_clears);
1284. break;
1285. case POT_WATER:
1286. if(u.umonnum == PM_GREMLIN) {
1287. (void)split_mon(&youmonst, (struct monst *)0);
1288. } else if (u.ulycn >= LOW_PM) {
1289. /* vapor from [un]holy water will trigger
1290. transformation but won't cure lycanthropy */
1291. if (obj->blessed && youmonst.data == &mons[u.ulycn])
1292. you_unwere(FALSE);
1293. else if (obj->cursed && !Upolyd)
1294. you_were();
1295. }
1296. break;
1297. case POT_ACID:
1298. case POT_POLYMORPH:
1299. exercise(A_CON, FALSE);
1300. break;
1301. /*
1302. case POT_GAIN_LEVEL:
1303. case POT_LEVITATION:
1304. case POT_FRUIT_JUICE:
1305. case POT_MONSTER_DETECTION:
1306. case POT_OBJECT_DETECTION:
1307. case POT_OIL:
1308. break;
1309. */
1310. }
1311. /* note: no obfree() */
1312. if (obj->dknown) {
1313. if (kn)
1314. makeknown(obj->otyp);
1315. else if (!objects[obj->otyp].oc_name_known &&
1316. !objects[obj->otyp].oc_uname)
1317. docall(obj);
1318. }
1319. }
1320.
1321. STATIC_OVL short
1322. mixtype(o1, o2)
1323. register struct obj *o1, *o2;
1324. /* returns the potion type when o1 is dipped in o2 */
1325. {
1326. /* cut down on the number of cases below */
1327. if (o1->oclass == POTION_CLASS &&
1328. (o2->otyp == POT_GAIN_LEVEL ||
1329. o2->otyp == POT_GAIN_ENERGY ||
1330. o2->otyp == POT_HEALING ||
1331. o2->otyp == POT_EXTRA_HEALING ||
1332. o2->otyp == POT_FULL_HEALING ||
1333. o2->otyp == POT_ENLIGHTENMENT ||
1334. o2->otyp == POT_FRUIT_JUICE)) {
1335. struct obj *swp;
1336.
1337. swp = o1; o1 = o2; o2 = swp;
1338. }
1339.
1340. switch (o1->otyp) {
1341. case POT_HEALING:
1342. switch (o2->otyp) {
1343. case POT_SPEED:
1344. case POT_GAIN_LEVEL:
1345. case POT_GAIN_ENERGY:
1346. return POT_EXTRA_HEALING;
1347. }
1348. case POT_EXTRA_HEALING:
1349. switch (o2->otyp) {
1350. case POT_GAIN_LEVEL:
1351. case POT_GAIN_ENERGY:
1352. return POT_FULL_HEALING;
1353. }
1354. case POT_FULL_HEALING:
1355. switch (o2->otyp) {
1356. case POT_GAIN_LEVEL:
1357. case POT_GAIN_ENERGY:
1358. return POT_GAIN_ABILITY;
1359. }
1360. case UNICORN_HORN:
1361. switch (o2->otyp) {
1362. case POT_SICKNESS:
1363. return POT_FRUIT_JUICE;
1364. case POT_HALLUCINATION:
1365. case POT_BLINDNESS:
1366. case POT_CONFUSION:
1367. return POT_WATER;
1368. }
1369. break;
1370. case AMETHYST: /* "a-methyst" == "not intoxicated" */
1371. if (o2->otyp == POT_BOOZE)
1372. return POT_FRUIT_JUICE;
1373. break;
1374. case POT_GAIN_LEVEL:
1375. case POT_GAIN_ENERGY:
1376. switch (o2->otyp) {
1377. case POT_CONFUSION:
1378. return (rn2(3) ? POT_BOOZE : POT_ENLIGHTENMENT);
1379. case POT_HEALING:
1380. return POT_EXTRA_HEALING;
1381. case POT_EXTRA_HEALING:
1382. return POT_FULL_HEALING;
1383. case POT_FULL_HEALING:
1384. return POT_GAIN_ABILITY;
1385. case POT_FRUIT_JUICE:
1386. return POT_SEE_INVISIBLE;
1387. case POT_BOOZE:
1388. return POT_HALLUCINATION;
1389. }
1390. break;
1391. case POT_FRUIT_JUICE:
1392. switch (o2->otyp) {
1393. case POT_SICKNESS:
1394. return POT_SICKNESS;
1395. case POT_SPEED:
1396. return POT_BOOZE;
1397. case POT_GAIN_LEVEL:
1398. case POT_GAIN_ENERGY:
1399. return POT_SEE_INVISIBLE;
1400. }
1401. break;
1402. case POT_ENLIGHTENMENT:
1403. switch (o2->otyp) {
1404. case POT_LEVITATION:
1405. if (rn2(3)) return POT_GAIN_LEVEL;
1406. break;
1407. case POT_FRUIT_JUICE:
1408. return POT_BOOZE;
1409. case POT_BOOZE:
1410. return POT_CONFUSION;
1411. }
1412. break;
1413. }
1414.
1415. return 0;
1416. }
1417.
1418.
1419. boolean
1420. get_wet(obj)
1421. register struct obj *obj;
1422. /* returns TRUE if something happened (potion should be used up) */
1423. {
1424. char Your_buf[BUFSZ];
1425.
1426. if (snuff_lit(obj)) return(TRUE);
1427.
1428. if (obj->greased) {
1429. grease_protect(obj,(char *)0,&youmonst);
1430. return(FALSE);
1431. }
1432. (void) Shk_Your(Your_buf, obj);
1433. /* (Rusting shop goods ought to be charged for.) */
1434. switch (obj->oclass) {
1435. case POTION_CLASS:
1436. if (obj->otyp == POT_WATER) return FALSE;
1437. /* KMH -- Water into acid causes an explosion */
1438. if (obj->otyp == POT_ACID) {
1439. pline("It boils vigorously!");
1440. You("are caught in the explosion!");
1441. losehp(rnd(10), "elementary chemistry", KILLED_BY);
1442. makeknown(obj->otyp);
1443. update_inventory();
1444. return (TRUE);
1445. }
1446. pline("%s %s%s.", Your_buf, aobjnam(obj,"dilute"),
1447. obj->odiluted ? " further" : "");
1448. if(obj->unpaid && costly_spot(u.ux, u.uy)) {
1449. You("dilute it, you pay for it.");
1450. bill_dummy_object(obj);
1451. }
1452. if (obj->odiluted) {
1453. obj->odiluted = 0;
1454. #ifdef UNIXPC
1455. obj->blessed = FALSE;
1456. obj->cursed = FALSE;
1457. #else
1458. obj->blessed = obj->cursed = FALSE;
1459. #endif
1460. obj->otyp = POT_WATER;
1461. } else obj->odiluted++;
1462. update_inventory();
1463. return TRUE;
1464. case SCROLL_CLASS:
1465. if (obj->otyp != SCR_BLANK_PAPER
1466. #ifdef MAIL
1467. && obj->otyp != SCR_MAIL
1468. #endif
1469. ) {
1470. if (!Blind) {
1471. boolean oq1 = obj->quan == 1L;
1472. pline_The("scroll%s %s.",
1473. oq1 ? "" : "s", otense(obj, "fade"));
1474. }
1475. if(obj->unpaid && costly_spot(u.ux, u.uy)) {
1476. You("erase it, you pay for it.");
1477. bill_dummy_object(obj);
1478. }
1479. obj->otyp = SCR_BLANK_PAPER;
1480. obj->spe = 0;
1481. update_inventory();
1482. return TRUE;
1483. } else break;
1484. case SPBOOK_CLASS:
1485. if (obj->otyp != SPE_BLANK_PAPER) {
1486.
1487. if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
1488. pline("%s suddenly heats up; steam rises and it remains dry.",
1489. The(xname(obj)));
1490. } else {
1491. if (!Blind) {
1492. boolean oq1 = obj->quan == 1L;
1493. pline_The("spellbook%s %s.",
1494. oq1 ? "" : "s", otense(obj, "fade"));
1495. }
1496. if(obj->unpaid && costly_spot(u.ux, u.uy)) {
1497. You("erase it, you pay for it.");
1498. bill_dummy_object(obj);
1499. }
1500. obj->otyp = SPE_BLANK_PAPER;
1501. update_inventory();
1502. }
1503. return TRUE;
1504. }
1505. break;
1506. case WEAPON_CLASS:
1507. /* Just "fall through" to generic rustprone check for now. */
1508. /* fall through */
1509. default:
1510. if (!obj->oerodeproof && is_rustprone(obj) &&
1511. (obj->oeroded < MAX_ERODE) && !rn2(2)) {
1512. pline("%s %s some%s.",
1513. Your_buf, aobjnam(obj, "rust"),
1514. obj->oeroded ? " more" : "what");
1515. obj->oeroded++;
1516. update_inventory();
1517. return TRUE;
1518. } else break;
1519. }
1520. pline("%s %s wet.", Your_buf, aobjnam(obj,"get"));
1521. return FALSE;
1522. }
1523.
1524. int
1525. dodip()
1526. {
1527. register struct obj *potion, *obj;
1528. struct obj *singlepotion;
1529. const char *tmp;
1530. uchar here;
1531. char allowall[2];
1532. short mixture;
1533. char qbuf[QBUFSZ], Your_buf[BUFSZ];
1534.
1535. allowall[0] = ALL_CLASSES; allowall[1] = '\0';
1536. if(!(obj = getobj(allowall, "dip")))
1537. return(0);
1538.
1539. here = levl[u.ux][u.uy].typ;
1540. /* Is there a fountain to dip into here? */
1541. if (IS_FOUNTAIN(here)) {
1542. if(yn("Dip it into the fountain?") == 'y') {
1543. dipfountain(obj);
1544. return(1);
1545. }
1546. } else if (is_pool(u.ux,u.uy)) {
1547. tmp = waterbody_name(u.ux,u.uy);
1548. Sprintf(qbuf, "Dip it into the %s?", tmp);
1549. if (yn(qbuf) == 'y') {
1550. if (Levitation) {
1551. floating_above(tmp);
1552. #ifdef STEED
1553. } else if (u.usteed && !is_swimmer(u.usteed->data) &&
1554. P_SKILL(P_RIDING) < P_BASIC) {
1555. rider_cant_reach(); /* not skilled enough to reach */
1556. #endif
1557. } else {
1558. (void) get_wet(obj);
1559. if (obj->otyp == POT_ACID) useup(obj);
1560. }
1561. return 1;
1562. }
1563. }
1564.
1565. if(!(potion = getobj(beverages, "dip into")))
1566. return(0);
1567. if (potion == obj && potion->quan == 1L) {
1568. pline("That is a potion bottle, not a Klein bottle!");
1569. return 0;
1570. }
1571. potion->in_use = TRUE; /* assume it will be used up */
1572. if(potion->otyp == POT_WATER) {
1573. boolean useeit = !Blind;
1574. if (useeit) (void) Shk_Your(Your_buf, obj);
1575. if (potion->blessed) {
1576. if (obj->cursed) {
1577. if (useeit)
1578. pline("%s %s %s.",
1579. Your_buf,
1580. aobjnam(obj, "softly glow"),
1581. hcolor(NH_AMBER));
1582. uncurse(obj);
1583. obj->bknown=1;
1584. poof:
1585. if(!(objects[potion->otyp].oc_name_known) &&
1586. !(objects[potion->otyp].oc_uname))
1587. docall(potion);
1588. useup(potion);
1589. return(1);
1590. } else if(!obj->blessed) {
1591. if (useeit) {
1592. tmp = hcolor(NH_LIGHT_BLUE);
1593. pline("%s %s with a%s %s aura.",
1594. Your_buf,
1595. aobjnam(obj, "softly glow"),
1596. index(vowels, *tmp) ? "n" : "", tmp);
1597. }
1598. bless(obj);
1599. obj->bknown=1;
1600. goto poof;
1601. }
1602. } else if (potion->cursed) {
1603. if (obj->blessed) {
1604. if (useeit)
1605. pline("%s %s %s.",
1606. Your_buf,
1607. aobjnam(obj, "glow"),
1608. hcolor((const char *)"brown"));
1609. unbless(obj);
1610. obj->bknown=1;
1611. goto poof;
1612. } else if(!obj->cursed) {
1613. if (useeit) {
1614. tmp = hcolor(NH_BLACK);
1615. pline("%s %s with a%s %s aura.",
1616. Your_buf,
1617. aobjnam(obj, "glow"),
1618. index(vowels, *tmp) ? "n" : "", tmp);
1619. }
1620. curse(obj);
1621. obj->bknown=1;
1622. goto poof;
1623. }
1624. } else
1625. if (get_wet(obj))
1626. goto poof;
1627. } else if (obj->otyp == POT_POLYMORPH ||
1628. potion->otyp == POT_POLYMORPH) {
1629. /* some objects can't be polymorphed */
1630. if (obj->otyp == potion->otyp || /* both POT_POLY */
1631. obj->otyp == WAN_POLYMORPH ||
1632. obj->otyp == SPE_POLYMORPH ||
1633. obj == uball || obj == uskin ||
1634. obj_resists(obj->otyp == POT_POLYMORPH ?
1635. potion : obj, 5, 95)) {
1636. pline(nothing_happens);
1637. } else {
1638. boolean was_wep = FALSE, was_swapwep = FALSE, was_quiver = FALSE;
1639. short save_otyp = obj->otyp;
1640. /* KMH, conduct */
1641. u.uconduct.polypiles++;
1642.
1643. if (obj == uwep) was_wep = TRUE;
1644. else if (obj == uswapwep) was_swapwep = TRUE;
1645. else if (obj == uquiver) was_quiver = TRUE;
1646.
1647. obj = poly_obj(obj, STRANGE_OBJECT);
1648.
1649. if (was_wep) setuwep(obj);
1650. else if (was_swapwep) setuswapwep(obj);
1651. else if (was_quiver) setuqwep(obj);
1652.
1653. if (obj->otyp != save_otyp) {
1654. makeknown(POT_POLYMORPH);
1655. useup(potion);
1656. prinv((char *)0, obj, 0L);
1657. return 1;
1658. } else {
1659. pline("Nothing seems to happen.");
1660. goto poof;
1661. }
1662. }
1663. potion->in_use = FALSE; /* didn't go poof */
1664. return(1);
1665. } else if(obj->oclass == POTION_CLASS && obj->otyp != potion->otyp) {
1666. /* Mixing potions is dangerous... */
1667. pline_The("potions mix...");
1668. /* KMH, balance patch -- acid is particularly unstable */
1669. if (obj->cursed || obj->otyp == POT_ACID || !rn2(10)) {
1670. pline("BOOM! They explode!");
1671. exercise(A_STR, FALSE);
1672. if (!breathless(youmonst.data) || haseyes(youmonst.data))
1673. potionbreathe(obj);
1674. useup(obj);
1675. useup(potion);
1676. losehp(rnd(10), "alchemic blast", KILLED_BY_AN);
1677. return(1);
1678. }
1679.
1680. obj->blessed = obj->cursed = obj->bknown = 0;
1681. if (Blind || Hallucination) obj->dknown = 0;
1682.
1683. if ((mixture = mixtype(obj, potion)) != 0) {
1684. obj->otyp = mixture;
1685. } else {
1686. switch (obj->odiluted ? 1 : rnd(8)) {
1687. case 1:
1688. obj->otyp = POT_WATER;
1689. break;
1690. case 2:
1691. case 3:
1692. obj->otyp = POT_SICKNESS;
1693. break;
1694. case 4:
1695. {
1696. struct obj *otmp;
1697. otmp = mkobj(POTION_CLASS,FALSE);
1698. obj->otyp = otmp->otyp;
1699. obfree(otmp, (struct obj *)0);
1700. }
1701. break;
1702. default:
1703. if (!Blind)
1704. pline_The("mixture glows brightly and evaporates.");
1705. useup(obj);
1706. useup(potion);
1707. return(1);
1708. }
1709. }
1710.
1711. obj->odiluted = (obj->otyp != POT_WATER);
1712.
1713. if (obj->otyp == POT_WATER && !Hallucination) {
1714. pline_The("mixture bubbles%s.",
1715. Blind ? "" : ", then clears");
1716. } else if (!Blind) {
1717. pline_The("mixture looks %s.",
1718. hcolor(OBJ_DESCR(objects[obj->otyp])));
1719. }
1720.
1721. useup(potion);
1722. return(1);
1723. }
1724.
1725. #ifdef INVISIBLE_OBJECTS
1726. if (potion->otyp == POT_INVISIBILITY && !obj->oinvis) {
1727. obj->oinvis = TRUE;
1728. if (!Blind) {
1729. if (!See_invisible) pline("Where did %s go?",
1730. the(xname(obj)));
1731. else You("notice a little haziness around %s.",
1732. the(xname(obj)));
1733. }
1734. goto poof;
1735. } else if (potion->otyp == POT_SEE_INVISIBLE && obj->oinvis) {
1736. obj->oinvis = FALSE;
1737. if (!Blind) {
1738. if (!See_invisible) pline("So that's where %s went!",
1739. the(xname(obj)));
1740. else pline_The("haziness around %s disappears.",
1741. the(xname(obj)));
1742. }
1743. goto poof;
1744. }
1745. #endif
1746.
1747. if(is_poisonable(obj)) {
1748. if(potion->otyp == POT_SICKNESS && !obj->opoisoned) {
1749. char buf[BUFSZ];
1750. if (potion->quan > 1L)
1751. Sprintf(buf, "One of %s", the(xname(potion)));
1752. else
1753. Strcpy(buf, The(xname(potion)));
1754. pline("%s forms a coating on %s.",
1755. buf, the(xname(obj)));
1756. obj->opoisoned = TRUE;
1757. goto poof;
1758. } else if(obj->opoisoned &&
1759. (potion->otyp == POT_HEALING ||
1760. potion->otyp == POT_EXTRA_HEALING ||
1761. potion->otyp == POT_FULL_HEALING)) {
1762. pline("A coating wears off %s.", the(xname(obj)));
1763. obj->opoisoned = 0;
1764. goto poof;
1765. }
1766. }
1767.
1768. if (potion->otyp == POT_OIL) {
1769. boolean wisx = FALSE;
1770. if (potion->lamplit) { /* burning */
1771. int omat = objects[obj->otyp].oc_material;
1772. /* the code here should be merged with fire_damage */
1773. if (catch_lit(obj)) {
1774. /* catch_lit does all the work if true */
1775. } else if (obj->oerodeproof || obj_resists(obj, 5, 95) ||
1776. !is_flammable(obj) || obj->oclass == FOOD_CLASS) {
1777. pline("%s %s to burn for a moment.",
1778. Yname2(obj), otense(obj, "seem"));
1779. } else {
1780. if ((omat == PLASTIC || omat == PAPER) && !obj->oartifact)
1781. obj->oeroded = MAX_ERODE;
1782. pline_The("burning oil %s %s.",
1783. obj->oeroded == MAX_ERODE ? "destroys" : "damages",
1784. yname(obj));
1785. if (obj->oeroded == MAX_ERODE) {
1786. obj_extract_self(obj);
1787. obfree(obj, (struct obj *)0);
1788. obj = (struct obj *) 0;
1789. } else {
1790. /* we know it's carried */
1791. if (obj->unpaid) {
1792. /* create a dummy duplicate to put on bill */
1793. verbalize("You burnt it, you bought it!");
1794. bill_dummy_object(obj);
1795. }
1796. obj->oeroded++;
1797. }
1798. }
1799. } else if (potion->cursed) {
1800. pline_The("potion spills and covers your %s with oil.",
1801. makeplural(body_part(FINGER)));
1802. incr_itimeout(&Glib, d(2,10));
1803. } else if (obj->oclass != WEAPON_CLASS && !is_weptool(obj)) {
1804. /* the following cases apply only to weapons */
1805. goto more_dips;
1806. /* Oil removes rust and corrosion, but doesn't unburn.
1807. * Arrows, etc are classed as metallic due to arrowhead
1808. * material, but dipping in oil shouldn't repair them.
1809. */
1810. } else if ((!is_rustprone(obj) && !is_corrodeable(obj)) ||
1811. is_ammo(obj) || (!obj->oeroded && !obj->oeroded2)) {
1812. /* uses up potion, doesn't set obj->greased */
1813. pline("%s %s with an oily sheen.",
1814. Yname2(obj), otense(obj, "gleam"));
1815. } else {
1816. pline("%s %s less %s.",
1817. Yname2(obj), otense(obj, "are"),
1818. (obj->oeroded && obj->oeroded2) ? "corroded and rusty" :
1819. obj->oeroded ? "rusty" : "corroded");
1820. if (obj->oeroded > 0) obj->oeroded--;
1821. if (obj->oeroded2 > 0) obj->oeroded2--;
1822. wisx = TRUE;
1823. }
1824. exercise(A_WIS, wisx);
1825. makeknown(potion->otyp);
1826. useup(potion);
1827. return 1;
1828. }
1829. more_dips:
1830.
1831. /* Allow filling of MAGIC_LAMPs to prevent identification by player */
1832. if ((obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP) &&
1833. (potion->otyp == POT_OIL)) {
1834. /* Turn off engine before fueling, turn off fuel too :-) */
1835. if (obj->lamplit || potion->lamplit) {
1836. useup(potion);
1837. explode(u.ux, u.uy, 11, d(6,6), 0, EXPL_FIERY);
1838. exercise(A_WIS, FALSE);
1839. return 1;
1840. }
1841. /* Adding oil to an empty magic lamp renders it into an oil lamp */
1842. if ((obj->otyp == MAGIC_LAMP) && obj->spe == 0) {
1843. obj->otyp = OIL_LAMP;
1844. obj->age = 0;
1845. }
1846. if (obj->age > 1000L) {
1847. pline("%s %s full.", Yname2(obj), otense(obj, "are"));
1848. potion->in_use = FALSE; /* didn't go poof */
1849. } else {
1850. You("fill %s with oil.", yname(obj));
1851. check_unpaid(potion); /* Yendorian Fuel Tax */
1852. obj->age += 2*potion->age; /* burns more efficiently */
1853. if (obj->age > 1500L) obj->age = 1500L;
1854. useup(potion);
1855. exercise(A_WIS, TRUE);
1856. }
1857. makeknown(POT_OIL);
1858. obj->spe = 1;
1859. update_inventory();
1860. return 1;
1861. }
1862.
1863. potion->in_use = FALSE; /* didn't go poof */
1864. if ((obj->otyp == UNICORN_HORN || obj->otyp == AMETHYST) &&
1865. (mixture = mixtype(obj, potion)) != 0) {
1866. char oldbuf[BUFSZ], newbuf[BUFSZ];
1867. short old_otyp = potion->otyp;
1868. boolean old_dknown = FALSE;
1869. boolean more_than_one = potion->quan > 1;
1870.
1871. oldbuf[0] = '\0';
1872. if (potion->dknown) {
1873. old_dknown = TRUE;
1874. Sprintf(oldbuf, "%s ",
1875. hcolor(OBJ_DESCR(objects[potion->otyp])));
1876. }
1877. /* with multiple merged potions, split off one and
1878. just clear it */
1879. if (potion->quan > 1L) {
1880. singlepotion = splitobj(potion, 1L);
1881. } else singlepotion = potion;
1882.
1883. if(singlepotion->unpaid && costly_spot(u.ux, u.uy)) {
1884. You("use it, you pay for it.");
1885. bill_dummy_object(singlepotion);
1886. }
1887. singlepotion->otyp = mixture;
1888. singlepotion->blessed = 0;
1889. if (mixture == POT_WATER)
1890. singlepotion->cursed = singlepotion->odiluted = 0;
1891. else
1892. singlepotion->cursed = obj->cursed; /* odiluted left as-is */
1893. singlepotion->bknown = FALSE;
1894. if (Blind) {
1895. singlepotion->dknown = FALSE;
1896. } else {
1897. singlepotion->dknown = !Hallucination;
1898. if (mixture == POT_WATER && singlepotion->dknown)
1899. Sprintf(newbuf, "clears");
1900. else
1901. Sprintf(newbuf, "turns %s",
1902. hcolor(OBJ_DESCR(objects[mixture])));
1903. pline_The("%spotion%s %s.", oldbuf,
1904. more_than_one ? " that you dipped into" : "",
1905. newbuf);
1906. if(!objects[old_otyp].oc_uname &&
1907. !objects[old_otyp].oc_name_known && old_dknown) {
1908. struct obj fakeobj;
1909. fakeobj = zeroobj;
1910. fakeobj.dknown = 1;
1911. fakeobj.otyp = old_otyp;
1912. fakeobj.oclass = POTION_CLASS;
1913. docall(&fakeobj);
1914. }
1915. }
1916. obj_extract_self(singlepotion);
1917. singlepotion = hold_another_object(singlepotion,
1918. "You juggle and drop %s!",
1919. doname(singlepotion), (const char *)0);
1920. update_inventory();
1921. return(1);
1922. }
1923.
1924. pline("Interesting...");
1925. return(1);
1926. }
1927.
1928.
1929. void
1930. djinni_from_bottle(obj)
1931. register struct obj *obj;
1932. {
1933. struct monst *mtmp;
1934. int chance;
1935.
1936. if(!(mtmp = makemon(&mons[PM_DJINNI], u.ux, u.uy, NO_MM_FLAGS))){
1937. pline("It turns out to be empty.");
1938. return;
1939. }
1940.
1941. if (!Blind) {
1942. pline("In a cloud of smoke, %s emerges!", a_monnam(mtmp));
1943. pline("%s speaks.", Monnam(mtmp));
1944. } else {
1945. You("smell acrid fumes.");
1946. pline("%s speaks.", Something);
1947. }
1948.
1949. chance = rn2(5);
1950. if (obj->blessed) chance = (chance == 4) ? rnd(4) : 0;
1951. else if (obj->cursed) chance = (chance == 0) ? rn2(4) : 4;
1952. /* 0,1,2,3,4: b=80%,5,5,5,5; nc=20%,20,20,20,20; c=5%,5,5,5,80 */
1953.
1954. switch (chance) {
1955. case 0 : verbalize("I am in your debt. I will grant one wish!");
1956. makewish();
1957. mongone(mtmp);
1958. break;
1959. case 1 : verbalize("Thank you for freeing me!");
1960. (void) tamedog(mtmp, (struct obj *)0);
1961. break;
1962. case 2 : verbalize("You freed me!");
1963. mtmp->mpeaceful = TRUE;
1964. set_malign(mtmp);
1965. break;
1966. case 3 : verbalize("It is about time!");
1967. pline("%s vanishes.", Monnam(mtmp));
1968. mongone(mtmp);
1969. break;
1970. default: verbalize("You disturbed me, fool!");
1971. break;
1972. }
1973. }
1974.
1975. /* clone a gremlin or mold (2nd arg non-null implies heat as the trigger);
1976. hit points are cut in half (odd HP stays with original) */
1977. struct monst *
1978. split_mon(mon, mtmp)
1979. struct monst *mon, /* monster being split */
1980. *mtmp; /* optional attacker whose heat triggered it */
1981. {
1982. struct monst *mtmp2;
1983. char reason[BUFSZ];
1984.
1985. reason[0] = '\0';
1986. if (mtmp) Sprintf(reason, " from %s heat",
1987. (mtmp == &youmonst) ? (const char *)"your" :
1988. (const char *)s_suffix(mon_nam(mtmp)));
1989.
1990. if (mon == &youmonst) {
1991. mtmp2 = cloneu();
1992. if (mtmp2) {
1993. mtmp2->mhpmax = u.mhmax / 2;
1994. u.mhmax -= mtmp2->mhpmax;
1995. flags.botl = 1;
1996. You("multiply%s!", reason);
1997. }
1998. } else {
1999. mtmp2 = clone_mon(mon, 0, 0);
2000. if (mtmp2) {
2001. mtmp2->mhpmax = mon->mhpmax / 2;
2002. mon->mhpmax -= mtmp2->mhpmax;
2003. if (canspotmon(mon))
2004. pline("%s multiplies%s!", Monnam(mon), reason);
2005. }
2006. }
2007. return mtmp2;
2008. }
2009.
2010. #endif /* OVLB */
2011.
2012. /*potion.c*/