Mercurial > hg > early-roguelike
comparison rogue5/potions.c @ 33:f502bf60e6e4
Import Rogue 5.4 from the Roguelike Restoration Project (r1490)
| author | elwin |
|---|---|
| date | Mon, 24 May 2010 20:10:59 +0000 |
| parents | |
| children | 696277507a2e |
comparison
equal
deleted
inserted
replaced
| 32:2dcd75e6a736 | 33:f502bf60e6e4 |
|---|---|
| 1 /* | |
| 2 * Function(s) for dealing with potions | |
| 3 * | |
| 4 * @(#)potions.c 4.46 (Berkeley) 06/07/83 | |
| 5 * | |
| 6 * Rogue: Exploring the Dungeons of Doom | |
| 7 * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman | |
| 8 * All rights reserved. | |
| 9 * | |
| 10 * See the file LICENSE.TXT for full copyright and licensing information. | |
| 11 */ | |
| 12 | |
| 13 #include <curses.h> | |
| 14 #include <ctype.h> | |
| 15 #include "rogue.h" | |
| 16 | |
| 17 typedef struct PACT | |
| 18 { | |
| 19 const int pa_flags; | |
| 20 void (*pa_daemon)(); | |
| 21 const int pa_time; | |
| 22 const char *pa_high, *pa_straight; | |
| 23 } PACT; | |
| 24 | |
| 25 static const PACT p_actions[] = | |
| 26 { | |
| 27 { ISHUH, unconfuse, HUHDURATION, /* P_CONFUSE */ | |
| 28 "what a tripy feeling!", | |
| 29 "wait, what's going on here. Huh? What? Who?" }, | |
| 30 { ISHALU, come_down, SEEDURATION, /* P_LSD */ | |
| 31 "Oh, wow! Everything seems so cosmic!", | |
| 32 "Oh, wow! Everything seems so cosmic!" }, | |
| 33 { 0, NULL, 0 }, /* P_POISON */ | |
| 34 { 0, NULL, 0 }, /* P_STRENGTH */ | |
| 35 { CANSEE, unsee, SEEDURATION, /* P_SEEINVIS */ | |
| 36 prbuf, | |
| 37 prbuf }, | |
| 38 { 0, NULL, 0 }, /* P_HEALING */ | |
| 39 { 0, NULL, 0 }, /* P_MFIND */ | |
| 40 { 0, NULL, 0 }, /* P_TFIND */ | |
| 41 { 0, NULL, 0 }, /* P_RAISE */ | |
| 42 { 0, NULL, 0 }, /* P_XHEAL */ | |
| 43 { 0, NULL, 0 }, /* P_HASTE */ | |
| 44 { 0, NULL, 0 }, /* P_RESTORE */ | |
| 45 { ISBLIND, sight, SEEDURATION, /* P_BLIND */ | |
| 46 "oh, bummer! Everything is dark! Help!", | |
| 47 "a cloak of darkness falls around you" }, | |
| 48 { ISLEVIT, land, HEALTIME, /* P_LEVIT */ | |
| 49 "oh, wow! You're floating in the air!", | |
| 50 "you start to float in the air" } | |
| 51 }; | |
| 52 | |
| 53 /* | |
| 54 * quaff: | |
| 55 * Quaff a potion from the pack | |
| 56 */ | |
| 57 | |
| 58 void | |
| 59 quaff(void) | |
| 60 { | |
| 61 THING *obj, *tp, *mp; | |
| 62 int discardit = FALSE; | |
| 63 int show, trip; | |
| 64 | |
| 65 obj = get_item("quaff", POTION); | |
| 66 /* | |
| 67 * Make certain that it is somethings that we want to drink | |
| 68 */ | |
| 69 if (obj == NULL) | |
| 70 return; | |
| 71 if (obj->o_type != POTION) | |
| 72 { | |
| 73 if (!terse) | |
| 74 msg("yuk! Why would you want to drink that?"); | |
| 75 else | |
| 76 msg("that's undrinkable"); | |
| 77 return; | |
| 78 } | |
| 79 if (obj == cur_weapon) | |
| 80 cur_weapon = NULL; | |
| 81 | |
| 82 /* | |
| 83 * Calculate the effect it has on the poor guy. | |
| 84 */ | |
| 85 trip = on(player, ISHALU); | |
| 86 discardit = (obj->o_count == 1); | |
| 87 leave_pack(obj, FALSE, FALSE); | |
| 88 switch (obj->o_which) | |
| 89 { | |
| 90 case P_CONFUSE: | |
| 91 do_pot(P_CONFUSE, !trip); | |
| 92 when P_POISON: | |
| 93 pot_info[P_POISON].oi_know = TRUE; | |
| 94 if (ISWEARING(R_SUSTSTR)) | |
| 95 msg("you feel momentarily sick"); | |
| 96 else | |
| 97 { | |
| 98 chg_str(-(rnd(3) + 1)); | |
| 99 msg("you feel very sick now"); | |
| 100 come_down(); | |
| 101 } | |
| 102 when P_HEALING: | |
| 103 pot_info[P_HEALING].oi_know = TRUE; | |
| 104 if ((pstats.s_hpt += roll(pstats.s_lvl, 4)) > max_hp) | |
| 105 pstats.s_hpt = ++max_hp; | |
| 106 sight(); | |
| 107 msg("you begin to feel better"); | |
| 108 when P_STRENGTH: | |
| 109 pot_info[P_STRENGTH].oi_know = TRUE; | |
| 110 chg_str(1); | |
| 111 msg("you feel stronger, now. What bulging muscles!"); | |
| 112 when P_MFIND: | |
| 113 player.t_flags |= SEEMONST; | |
| 114 fuse((void(*)())turn_see, TRUE, HUHDURATION, AFTER); | |
| 115 if (!turn_see(FALSE)) | |
| 116 msg("you have a %s feeling for a moment, then it passes", | |
| 117 choose_str("normal", "strange")); | |
| 118 when P_TFIND: | |
| 119 /* | |
| 120 * Potion of magic detection. Show the potions and scrolls | |
| 121 */ | |
| 122 show = FALSE; | |
| 123 if (lvl_obj != NULL) | |
| 124 { | |
| 125 wclear(hw); | |
| 126 for (tp = lvl_obj; tp != NULL; tp = next(tp)) | |
| 127 { | |
| 128 if (is_magic(tp)) | |
| 129 { | |
| 130 show = TRUE; | |
| 131 wmove(hw, tp->o_pos.y, tp->o_pos.x); | |
| 132 waddch(hw, MAGIC); | |
| 133 pot_info[P_TFIND].oi_know = TRUE; | |
| 134 } | |
| 135 } | |
| 136 for (mp = mlist; mp != NULL; mp = next(mp)) | |
| 137 { | |
| 138 for (tp = mp->t_pack; tp != NULL; tp = next(tp)) | |
| 139 { | |
| 140 if (is_magic(tp)) | |
| 141 { | |
| 142 show = TRUE; | |
| 143 wmove(hw, mp->t_pos.y, mp->t_pos.x); | |
| 144 waddch(hw, MAGIC); | |
| 145 } | |
| 146 } | |
| 147 } | |
| 148 } | |
| 149 if (show) | |
| 150 { | |
| 151 pot_info[P_TFIND].oi_know = TRUE; | |
| 152 show_win("You sense the presence of magic on this level.--More--"); | |
| 153 } | |
| 154 else | |
| 155 msg("you have a %s feeling for a moment, then it passes", | |
| 156 choose_str("normal", "strange")); | |
| 157 when P_LSD: | |
| 158 if (!trip) | |
| 159 { | |
| 160 if (on(player, SEEMONST)) | |
| 161 turn_see(FALSE); | |
| 162 start_daemon(visuals, 0, BEFORE); | |
| 163 seenstairs = seen_stairs(); | |
| 164 } | |
| 165 do_pot(P_LSD, TRUE); | |
| 166 when P_SEEINVIS: | |
| 167 sprintf(prbuf, "this potion tastes like %s juice", fruit); | |
| 168 show = on(player, CANSEE); | |
| 169 do_pot(P_SEEINVIS, FALSE); | |
| 170 if (!show) | |
| 171 invis_on(); | |
| 172 sight(); | |
| 173 when P_RAISE: | |
| 174 pot_info[P_RAISE].oi_know = TRUE; | |
| 175 msg("you suddenly feel much more skillful"); | |
| 176 raise_level(); | |
| 177 when P_XHEAL: | |
| 178 pot_info[P_XHEAL].oi_know = TRUE; | |
| 179 if ((pstats.s_hpt += roll(pstats.s_lvl, 8)) > max_hp) | |
| 180 { | |
| 181 if (pstats.s_hpt > max_hp + pstats.s_lvl + 1) | |
| 182 ++max_hp; | |
| 183 pstats.s_hpt = ++max_hp; | |
| 184 } | |
| 185 sight(); | |
| 186 come_down(); | |
| 187 msg("you begin to feel much better"); | |
| 188 when P_HASTE: | |
| 189 pot_info[P_HASTE].oi_know = TRUE; | |
| 190 after = FALSE; | |
| 191 if (add_haste(TRUE)) | |
| 192 msg("you feel yourself moving much faster"); | |
| 193 when P_RESTORE: | |
| 194 if (ISRING(LEFT, R_ADDSTR)) | |
| 195 add_str(&pstats.s_str, -cur_ring[LEFT]->o_arm); | |
| 196 if (ISRING(RIGHT, R_ADDSTR)) | |
| 197 add_str(&pstats.s_str, -cur_ring[RIGHT]->o_arm); | |
| 198 if (pstats.s_str < max_stats.s_str) | |
| 199 pstats.s_str = max_stats.s_str; | |
| 200 if (ISRING(LEFT, R_ADDSTR)) | |
| 201 add_str(&pstats.s_str, cur_ring[LEFT]->o_arm); | |
| 202 if (ISRING(RIGHT, R_ADDSTR)) | |
| 203 add_str(&pstats.s_str, cur_ring[RIGHT]->o_arm); | |
| 204 msg("hey, this tastes great. It make you feel warm all over"); | |
| 205 when P_BLIND: | |
| 206 do_pot(P_BLIND, TRUE); | |
| 207 when P_LEVIT: | |
| 208 do_pot(P_LEVIT, TRUE); | |
| 209 #ifdef MASTER | |
| 210 otherwise: | |
| 211 msg("what an odd tasting potion!"); | |
| 212 return; | |
| 213 #endif | |
| 214 } | |
| 215 status(); | |
| 216 /* | |
| 217 * Throw the item away | |
| 218 */ | |
| 219 | |
| 220 call_it(&pot_info[obj->o_which]); | |
| 221 | |
| 222 if (discardit) | |
| 223 discard(obj); | |
| 224 return; | |
| 225 } | |
| 226 | |
| 227 /* | |
| 228 * is_magic: | |
| 229 * Returns true if an object radiates magic | |
| 230 */ | |
| 231 int | |
| 232 is_magic(const THING *obj) | |
| 233 { | |
| 234 switch (obj->o_type) | |
| 235 { | |
| 236 case ARMOR: | |
| 237 return ((obj->o_flags&ISPROT) || obj->o_arm != a_class[obj->o_which]); | |
| 238 case WEAPON: | |
| 239 return (obj->o_hplus != 0 || obj->o_dplus != 0); | |
| 240 case POTION: | |
| 241 case SCROLL: | |
| 242 case STICK: | |
| 243 case RING: | |
| 244 case AMULET: | |
| 245 return TRUE; | |
| 246 } | |
| 247 return FALSE; | |
| 248 } | |
| 249 | |
| 250 /* | |
| 251 * invis_on: | |
| 252 * Turn on the ability to see invisible | |
| 253 */ | |
| 254 | |
| 255 void | |
| 256 invis_on(void) | |
| 257 { | |
| 258 THING *mp; | |
| 259 | |
| 260 player.t_flags |= CANSEE; | |
| 261 for (mp = mlist; mp != NULL; mp = next(mp)) | |
| 262 if (on(*mp, ISINVIS) && see_monst(mp) && !on(player, ISHALU)) | |
| 263 mvaddch(mp->t_pos.y, mp->t_pos.x, mp->t_disguise); | |
| 264 } | |
| 265 | |
| 266 /* | |
| 267 * turn_see: | |
| 268 * Put on or off seeing monsters on this level | |
| 269 */ | |
| 270 int | |
| 271 turn_see(int turn_off) | |
| 272 { | |
| 273 THING *mp; | |
| 274 int can_see, add_new; | |
| 275 | |
| 276 add_new = FALSE; | |
| 277 for (mp = mlist; mp != NULL; mp = next(mp)) | |
| 278 { | |
| 279 move(mp->t_pos.y, mp->t_pos.x); | |
| 280 can_see = see_monst(mp); | |
| 281 if (turn_off) | |
| 282 { | |
| 283 if (!can_see) | |
| 284 addch(mp->t_oldch); | |
| 285 } | |
| 286 else | |
| 287 { | |
| 288 if (!can_see) | |
| 289 standout(); | |
| 290 if (!on(player, ISHALU)) | |
| 291 addch(mp->t_type); | |
| 292 else | |
| 293 addch(rnd(26) + 'A'); | |
| 294 if (!can_see) | |
| 295 { | |
| 296 standend(); | |
| 297 add_new++; | |
| 298 } | |
| 299 } | |
| 300 } | |
| 301 if (turn_off) | |
| 302 player.t_flags &= ~SEEMONST; | |
| 303 else | |
| 304 player.t_flags |= SEEMONST; | |
| 305 return add_new; | |
| 306 } | |
| 307 | |
| 308 /* | |
| 309 * seen_stairs: | |
| 310 * Return TRUE if the player has seen the stairs | |
| 311 */ | |
| 312 int | |
| 313 seen_stairs(void) | |
| 314 { | |
| 315 THING *tp; | |
| 316 | |
| 317 move(stairs.y, stairs.x); | |
| 318 if (CCHAR( inch() ) == STAIRS) /* it's on the map */ | |
| 319 return TRUE; | |
| 320 if (ce(hero, stairs)) /* It's under him */ | |
| 321 return TRUE; | |
| 322 | |
| 323 /* | |
| 324 * if a monster is on the stairs, this gets hairy | |
| 325 */ | |
| 326 if ((tp = moat(stairs.y, stairs.x)) != NULL) | |
| 327 { | |
| 328 if (see_monst(tp) && on(*tp, ISRUN)) /* if it's visible and awake */ | |
| 329 return TRUE; /* it must have moved there */ | |
| 330 | |
| 331 if (on(player, SEEMONST) /* if she can detect monster */ | |
| 332 && tp->t_oldch == STAIRS) /* and there once were stairs */ | |
| 333 return TRUE; /* it must have moved there */ | |
| 334 } | |
| 335 return FALSE; | |
| 336 } | |
| 337 | |
| 338 /* | |
| 339 * raise_level: | |
| 340 * The guy just magically went up a level. | |
| 341 */ | |
| 342 | |
| 343 void | |
| 344 raise_level(void) | |
| 345 { | |
| 346 pstats.s_exp = e_levels[pstats.s_lvl-1] + 1L; | |
| 347 check_level(); | |
| 348 } | |
| 349 | |
| 350 /* | |
| 351 * do_pot: | |
| 352 * Do a potion with standard setup. This means it uses a fuse and | |
| 353 * turns on a flag | |
| 354 */ | |
| 355 | |
| 356 void | |
| 357 do_pot(int type, int knowit) | |
| 358 { | |
| 359 const PACT *pp; | |
| 360 int t; | |
| 361 | |
| 362 pp = &p_actions[type]; | |
| 363 if (!pot_info[type].oi_know) | |
| 364 pot_info[type].oi_know = knowit; | |
| 365 t = spread(pp->pa_time); | |
| 366 if (!on(player, pp->pa_flags)) | |
| 367 { | |
| 368 player.t_flags |= pp->pa_flags; | |
| 369 fuse(pp->pa_daemon, 0, t, AFTER); | |
| 370 look(FALSE); | |
| 371 } | |
| 372 else | |
| 373 lengthen(pp->pa_daemon, t); | |
| 374 msg(choose_str(pp->pa_high, pp->pa_straight)); | |
| 375 } |
