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 }