hack.potion.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. /* $NetBSD: hack.potion.c,v 1.6 2003/04/02 18:36:39 jsm Exp $ */
  2. /*
  3. * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
  4. * Amsterdam
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are
  9. * met:
  10. *
  11. * - Redistributions of source code must retain the above copyright notice,
  12. * this list of conditions and the following disclaimer.
  13. *
  14. * - Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. *
  18. * - Neither the name of the Stichting Centrum voor Wiskunde en
  19. * Informatica, nor the names of its contributors may be used to endorse or
  20. * promote products derived from this software without specific prior
  21. * written permission.
  22. *
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  24. * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  25. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  26. * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
  27. * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  28. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  29. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  30. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  31. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  32. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  33. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  34. */
  35. /*
  36. * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
  37. * All rights reserved.
  38. *
  39. * Redistribution and use in source and binary forms, with or without
  40. * modification, are permitted provided that the following conditions
  41. * are met:
  42. * 1. Redistributions of source code must retain the above copyright
  43. * notice, this list of conditions and the following disclaimer.
  44. * 2. Redistributions in binary form must reproduce the above copyright
  45. * notice, this list of conditions and the following disclaimer in the
  46. * documentation and/or other materials provided with the distribution.
  47. * 3. The name of the author may not be used to endorse or promote products
  48. * derived from this software without specific prior written permission.
  49. *
  50. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
  51. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  52. * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  53. * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  54. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  55. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  56. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  57. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  58. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  59. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  60. */
  61. #include <sys/cdefs.h>
  62. #ifndef lint
  63. __RCSID("$NetBSD: hack.potion.c,v 1.6 2003/04/02 18:36:39 jsm Exp $");
  64. #endif /* not lint */
  65. #include "hack.h"
  66. #include "extern.h"
  67. int
  68. dodrink()
  69. {
  70. struct obj *otmp, *objs;
  71. struct monst *mtmp;
  72. int unkn = 0, nothing = 0;
  73. otmp = getobj("!", "drink");
  74. if (!otmp)
  75. return (0);
  76. if (!strcmp(objects[otmp->otyp].oc_descr, "smoky") && !rn2(13)) {
  77. ghost_from_bottle();
  78. goto use_it;
  79. }
  80. switch (otmp->otyp) {
  81. case POT_RESTORE_STRENGTH:
  82. unkn++;
  83. pline("Wow! This makes you feel great!");
  84. if (u.ustr < u.ustrmax) {
  85. u.ustr = u.ustrmax;
  86. flags.botl = 1;
  87. }
  88. break;
  89. case POT_BOOZE:
  90. unkn++;
  91. pline("Ooph! This tastes like liquid fire!");
  92. Confusion += d(3, 8);
  93. /* the whiskey makes us feel better */
  94. if (u.uhp < u.uhpmax)
  95. losehp(-1, "bottle of whiskey");
  96. if (!rn2(4)) {
  97. pline("You pass out.");
  98. multi = -rnd(15);
  99. nomovemsg = "You awake with a headache.";
  100. }
  101. break;
  102. case POT_INVISIBILITY:
  103. if (Invis || See_invisible)
  104. nothing++;
  105. else {
  106. if (!Blind)
  107. pline("Gee! All of a sudden, you can't see yourself.");
  108. else
  109. pline("You feel rather airy."), unkn++;
  110. newsym(u.ux, u.uy);
  111. }
  112. Invis += rn1(15, 31);
  113. break;
  114. case POT_FRUIT_JUICE:
  115. pline("This tastes like fruit juice.");
  116. lesshungry(20);
  117. break;
  118. case POT_HEALING:
  119. pline("You begin to feel better.");
  120. flags.botl = 1;
  121. u.uhp += rnd(10);
  122. if (u.uhp > u.uhpmax)
  123. u.uhp = ++u.uhpmax;
  124. if (Blind)
  125. Blind = 1; /* see on next move */
  126. if (Sick)
  127. Sick = 0;
  128. break;
  129. case POT_PARALYSIS:
  130. if (Levitation)
  131. pline("You are motionlessly suspended.");
  132. else
  133. pline("Your feet are frozen to the floor!");
  134. nomul(-(rn1(10, 25)));
  135. break;
  136. case POT_MONSTER_DETECTION:
  137. if (!fmon) {
  138. strange_feeling(otmp, "You feel threatened.");
  139. return (1);
  140. } else {
  141. cls();
  142. for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  143. if (mtmp->mx > 0)
  144. at(mtmp->mx, mtmp->my, mtmp->data->mlet);
  145. prme();
  146. pline("You sense the presence of monsters.");
  147. more();
  148. docrt();
  149. }
  150. break;
  151. case POT_OBJECT_DETECTION:
  152. if (!fobj) {
  153. strange_feeling(otmp, "You feel a pull downward.");
  154. return (1);
  155. } else {
  156. for (objs = fobj; objs; objs = objs->nobj)
  157. if (objs->ox != u.ux || objs->oy != u.uy)
  158. goto outobjmap;
  159. pline("You sense the presence of objects close nearby.");
  160. break;
  161. outobjmap:
  162. cls();
  163. for (objs = fobj; objs; objs = objs->nobj)
  164. at(objs->ox, objs->oy, objs->olet);
  165. prme();
  166. pline("You sense the presence of objects.");
  167. more();
  168. docrt();
  169. }
  170. break;
  171. case POT_SICKNESS:
  172. pline("Yech! This stuff tastes like poison.");
  173. if (Poison_resistance)
  174. pline("(But in fact it was biologically contaminated orange juice.)");
  175. losestr(rn1(4, 3));
  176. losehp(rnd(10), "contaminated potion");
  177. break;
  178. case POT_CONFUSION:
  179. if (!Confusion)
  180. pline("Huh, What? Where am I?");
  181. else
  182. nothing++;
  183. Confusion += rn1(7, 16);
  184. break;
  185. case POT_GAIN_STRENGTH:
  186. pline("Wow do you feel strong!");
  187. if (u.ustr >= 118)
  188. break; /* > 118 is impossible */
  189. if (u.ustr > 17)
  190. u.ustr += rnd(118 - u.ustr);
  191. else
  192. u.ustr++;
  193. if (u.ustr > u.ustrmax)
  194. u.ustrmax = u.ustr;
  195. flags.botl = 1;
  196. break;
  197. case POT_SPEED:
  198. if (Wounded_legs) {
  199. heal_legs();
  200. unkn++;
  201. break;
  202. }
  203. if (!(Fast & ~INTRINSIC))
  204. pline("You are suddenly moving much faster.");
  205. else
  206. pline("Your legs get new energy."), unkn++;
  207. Fast += rn1(10, 100);
  208. break;
  209. case POT_BLINDNESS:
  210. if (!Blind)
  211. pline("A cloud of darkness falls upon you.");
  212. else
  213. nothing++;
  214. Blind += rn1(100, 250);
  215. seeoff(0);
  216. break;
  217. case POT_GAIN_LEVEL:
  218. pluslvl();
  219. break;
  220. case POT_EXTRA_HEALING:
  221. pline("You feel much better.");
  222. flags.botl = 1;
  223. u.uhp += d(2, 20) + 1;
  224. if (u.uhp > u.uhpmax)
  225. u.uhp = (u.uhpmax += 2);
  226. if (Blind)
  227. Blind = 1;
  228. if (Sick)
  229. Sick = 0;
  230. break;
  231. case POT_LEVITATION:
  232. if (!Levitation)
  233. float_up();
  234. else
  235. nothing++;
  236. Levitation += rnd(100);
  237. u.uprops[PROP(RIN_LEVITATION)].p_tofn = float_down;
  238. break;
  239. default:
  240. impossible("What a funny potion! (%u)", otmp->otyp);
  241. return (0);
  242. }
  243. if (nothing) {
  244. unkn++;
  245. pline("You have a peculiar feeling for a moment, then it passes.");
  246. }
  247. if (otmp->dknown && !objects[otmp->otyp].oc_name_known) {
  248. if (!unkn) {
  249. objects[otmp->otyp].oc_name_known = 1;
  250. more_experienced(0, 10);
  251. } else if (!objects[otmp->otyp].oc_uname)
  252. docall(otmp);
  253. }
  254. use_it:
  255. useup(otmp);
  256. return (1);
  257. }
  258. void
  259. pluslvl()
  260. {
  261. int num;
  262. pline("You feel more experienced.");
  263. num = rnd(10);
  264. u.uhpmax += num;
  265. u.uhp += num;
  266. if (u.ulevel < 14) {
  267. u.uexp = newuexp() + 1;
  268. pline("Welcome to experience level %u.", ++u.ulevel);
  269. }
  270. flags.botl = 1;
  271. }
  272. void
  273. strange_feeling(obj, txt)
  274. struct obj *obj;
  275. const char *txt;
  276. {
  277. if (flags.beginner)
  278. pline("You have a strange feeling for a moment, then it passes.");
  279. else
  280. pline(txt);
  281. if (!objects[obj->otyp].oc_name_known && !objects[obj->otyp].oc_uname)
  282. docall(obj);
  283. useup(obj);
  284. }
  285. const char *const bottlenames[] = {
  286. "bottle", "phial", "flagon", "carafe", "flask", "jar", "vial"
  287. };
  288. void
  289. potionhit(mon, obj)
  290. struct monst *mon;
  291. struct obj *obj;
  292. {
  293. const char *botlnam = bottlenames[rn2(SIZE(bottlenames))];
  294. boolean uclose, isyou = (mon == &youmonst);
  295. if (isyou) {
  296. uclose = TRUE;
  297. pline("The %s crashes on your head and breaks into shivers.",
  298. botlnam);
  299. losehp(rnd(2), "thrown potion");
  300. } else {
  301. uclose = (dist(mon->mx, mon->my) < 3);
  302. /* perhaps 'E' and 'a' have no head? */
  303. pline("The %s crashes on %s's head and breaks into shivers.",
  304. botlnam, monnam(mon));
  305. if (rn2(5) && mon->mhp > 1)
  306. mon->mhp--;
  307. }
  308. pline("The %s evaporates.", xname(obj));
  309. if (!isyou && !rn2(3))
  310. switch (obj->otyp) {
  311. case POT_RESTORE_STRENGTH:
  312. case POT_GAIN_STRENGTH:
  313. case POT_HEALING:
  314. case POT_EXTRA_HEALING:
  315. if (mon->mhp < mon->mhpmax) {
  316. mon->mhp = mon->mhpmax;
  317. pline("%s looks sound and hale again!", Monnam(mon));
  318. }
  319. break;
  320. case POT_SICKNESS:
  321. if (mon->mhpmax > 3)
  322. mon->mhpmax /= 2;
  323. if (mon->mhp > 2)
  324. mon->mhp /= 2;
  325. break;
  326. case POT_CONFUSION:
  327. case POT_BOOZE:
  328. mon->mconf = 1;
  329. break;
  330. case POT_INVISIBILITY:
  331. unpmon(mon);
  332. mon->minvis = 1;
  333. pmon(mon);
  334. break;
  335. case POT_PARALYSIS:
  336. mon->mfroz = 1;
  337. break;
  338. case POT_SPEED:
  339. mon->mspeed = MFAST;
  340. break;
  341. case POT_BLINDNESS:
  342. mon->mblinded |= 64 + rn2(64);
  343. break;
  344. /*
  345. * case POT_GAIN_LEVEL: case POT_LEVITATION: case
  346. * POT_FRUIT_JUICE: case POT_MONSTER_DETECTION: case
  347. * POT_OBJECT_DETECTION: break;
  348. */
  349. }
  350. if (uclose && rn2(5))
  351. potionbreathe(obj);
  352. obfree(obj, Null(obj));
  353. }
  354. void
  355. potionbreathe(obj)
  356. struct obj *obj;
  357. {
  358. switch (obj->otyp) {
  359. case POT_RESTORE_STRENGTH:
  360. case POT_GAIN_STRENGTH:
  361. if (u.ustr < u.ustrmax)
  362. u.ustr++, flags.botl = 1;
  363. break;
  364. case POT_HEALING:
  365. case POT_EXTRA_HEALING:
  366. if (u.uhp < u.uhpmax)
  367. u.uhp++, flags.botl = 1;
  368. break;
  369. case POT_SICKNESS:
  370. if (u.uhp <= 5)
  371. u.uhp = 1;
  372. else
  373. u.uhp -= 5;
  374. flags.botl = 1;
  375. break;
  376. case POT_CONFUSION:
  377. case POT_BOOZE:
  378. if (!Confusion)
  379. pline("You feel somewhat dizzy.");
  380. Confusion += rnd(5);
  381. break;
  382. case POT_INVISIBILITY:
  383. pline("For an instant you couldn't see your right hand.");
  384. break;
  385. case POT_PARALYSIS:
  386. pline("Something seems to be holding you.");
  387. nomul(-rnd(5));
  388. break;
  389. case POT_SPEED:
  390. Fast += rnd(5);
  391. pline("Your knees seem more flexible now.");
  392. break;
  393. case POT_BLINDNESS:
  394. if (!Blind)
  395. pline("It suddenly gets dark.");
  396. Blind += rnd(5);
  397. seeoff(0);
  398. break;
  399. /*
  400. * case POT_GAIN_LEVEL: case POT_LEVITATION: case
  401. * POT_FRUIT_JUICE: case POT_MONSTER_DETECTION: case
  402. * POT_OBJECT_DETECTION: break;
  403. */
  404. }
  405. /* note: no obfree() */
  406. }
  407. /*
  408. * -- rudimentary -- to do this correctly requires much more work
  409. * -- all sharp weapons get one or more qualities derived from the potions
  410. * -- texts on scrolls may be (partially) wiped out; do they become blank?
  411. * -- or does their effect change, like under Confusion?
  412. * -- all objects may be made invisible by POT_INVISIBILITY
  413. * -- If the flask is small, can one dip a large object? Does it magically
  414. * -- become a jug? Etc.
  415. */
  416. int
  417. dodip()
  418. {
  419. struct obj *potion, *obj;
  420. if (!(obj = getobj("#", "dip")))
  421. return (0);
  422. if (!(potion = getobj("!", "dip into")))
  423. return (0);
  424. pline("Interesting...");
  425. if (obj->otyp == ARROW || obj->otyp == DART ||
  426. obj->otyp == CROSSBOW_BOLT) {
  427. if (potion->otyp == POT_SICKNESS) {
  428. useup(potion);
  429. if (obj->spe < 7)
  430. obj->spe++; /* %% */
  431. }
  432. }
  433. return (1);
  434. }
  435. void
  436. ghost_from_bottle()
  437. {
  438. struct monst *mtmp;
  439. if (!(mtmp = makemon(PM_GHOST, u.ux, u.uy))) {
  440. pline("This bottle turns out to be empty.");
  441. return;
  442. }
  443. mnexto(mtmp);
  444. pline("As you open the bottle, an enormous ghost emerges!");
  445. pline("You are frightened to death, and unable to move.");
  446. nomul(-3);
  447. }