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