Neale Pickett
·
2011-10-13
signal.c
1/*
2 * Functions to implement the various sticks one might find
3 * while wandering around the dungeon.
4 *
5 * @(#)signal.c 4.39 (Berkeley) 02/05/99
6 */
7
8#include <curses.h>
9#include <ctype.h>
10#include "netprot.h"
11
12/*
13 * fix_stick:
14 * Set up a new stick
15 */
16void
17fix_stick(THING *cur)
18{
19 if (strcmp(Ws_type[cur->o_which], "staff") == 0)
20 cur->o_damage = "2x3";
21 else
22 cur->o_damage = "1x1";
23 cur->o_hurldmg = "1x1";
24
25 switch (cur->o_which)
26 {
27 when WS_LIGHT:
28 cur->o_charges = rnd(10) + 10;
29 otherwise:
30 cur->o_charges = rnd(5) + 3;
31 }
32}
33
34/*
35 * do_zap:
36 * Perform a zap with a wand
37 */
38void
39do_zap(void)
40{
41 THING *obj, *tp;
42 int y, x;
43 char *name;
44 char monster, oldch;
45 int rm;
46 char omonst;
47 static THING bolt;
48
49 if ((obj = get_item("zap with", STICK)) == NULL)
50 return;
51 if (obj->o_type != STICK)
52 {
53 After = FALSE;
54 msg("you can't zap with that!");
55 return;
56 }
57 if (obj->o_charges == 0)
58 {
59 msg("nothing happens");
60 return;
61 }
62 switch (obj->o_which)
63 {
64 when WS_LIGHT:
65 /*
66 * Reddy Kilowat wand. Light up the room
67 */
68 Ws_info[WS_LIGHT].oi_know = TRUE;
69 if (Proom->r_flags & ISGONE)
70 msg("the corridor glows and then fades");
71 else
72 {
73 Proom->r_flags &= ~ISDARK;
74 /*
75 * Light the room and put the player back up
76 */
77 enter_room(&Hero);
78 addmsg("the room is lit");
79 if (!Terse)
80 addmsg(" by a shimmering %s light", pick_color("blue"));
81 endmsg();
82 }
83 when WS_DRAIN:
84 /*
85 * Take away 1/2 of hero's hit points, then take it away
86 * evenly from the monsters in the room (or next to hero
87 * if he is in a passage)
88 */
89 if (Pstats.s_hpt < 2)
90 {
91 msg("you are too weak to use it");
92 return;
93 }
94 else
95 drain();
96 when WS_INVIS:
97 case WS_POLYMORPH:
98 case WS_TELAWAY:
99 case WS_TELTO:
100 case WS_CANCEL:
101 y = Hero.y;
102 x = Hero.x;
103 while (step_ok(winat(y, x)))
104 {
105 y += Delta.y;
106 x += Delta.x;
107 }
108 if ((tp = moat(y, x)) != NULL)
109 {
110 omonst = monster = tp->t_type;
111 if (monster == 'F')
112 Player.t_flags &= ~ISHELD;
113 switch (obj->o_which) {
114 case WS_INVIS:
115 tp->t_flags |= ISINVIS;
116 if (cansee(y, x))
117 mvaddch(y, x, tp->t_oldch);
118 break;
119 case WS_POLYMORPH:
120 {
121 THING *pp;
122
123 pp = tp->t_pack;
124 detach(Mlist, tp);
125 if (see_monst(tp))
126 mvaddch(y, x, chat(y, x));
127 oldch = tp->t_oldch;
128 Delta.y = y;
129 Delta.x = x;
130 new_monster(tp, monster = rnd(26) + 'A', &Delta);
131 if (see_monst(tp))
132 mvaddch(y, x, monster);
133 tp->t_oldch = oldch;
134 tp->t_pack = pp;
135 Ws_info[WS_POLYMORPH].oi_know |= see_monst(tp);
136 break;
137 }
138 case WS_CANCEL:
139 tp->t_flags |= ISCANC;
140 tp->t_flags &= ~(ISINVIS|CANHUH);
141 tp->t_disguise = tp->t_type;
142 if (see_monst(tp))
143 mvaddch(y, x, tp->t_disguise);
144 break;
145 case WS_TELAWAY:
146 case WS_TELTO:
147 {
148 coord new_pos;
149
150 if (obj->o_which == WS_TELAWAY)
151 {
152 do
153 {
154 find_floor(NULL, &new_pos, FALSE, TRUE);
155 } while (ce(new_pos, Hero));
156 }
157 else
158 {
159 new_pos.y = Hero.y + Delta.y;
160 new_pos.x = Hero.x + Delta.x;
161 }
162 tp->t_dest = &Hero;
163 tp->t_flags |= ISRUN;
164 relocate(tp, &new_pos);
165 }
166 }
167 }
168 when WS_MISSILE:
169 Ws_info[WS_MISSILE].oi_know = TRUE;
170 bolt.o_type = '*';
171 bolt.o_hurldmg = "1x4";
172 bolt.o_hplus = 100;
173 bolt.o_dplus = 1;
174 bolt.o_flags = ISMISL;
175 if (Cur_weapon != NULL)
176 bolt.o_launch = Cur_weapon->o_which;
177 do_motion(&bolt, Delta.y, Delta.x);
178 if ((tp = moat(bolt.o_pos.y, bolt.o_pos.x)) != NULL
179 && !save_throw(VS_MAGIC, tp))
180 hit_monster(unc(bolt.o_pos), &bolt);
181 else if (Terse)
182 msg("missle vanishes");
183 else
184 msg("the missle vanishes with a puff of smoke");
185 when WS_HASTE_M:
186 case WS_SLOW_M:
187 y = Hero.y;
188 x = Hero.x;
189 while (step_ok(winat(y, x)))
190 {
191 y += Delta.y;
192 x += Delta.x;
193 }
194 if ((tp = moat(y, x)) != NULL)
195 {
196 if (obj->o_which == WS_HASTE_M)
197 {
198 if (on(*tp, ISSLOW))
199 tp->t_flags &= ~ISSLOW;
200 else
201 tp->t_flags |= ISHASTE;
202 }
203 else
204 {
205 if (on(*tp, ISHASTE))
206 tp->t_flags &= ~ISHASTE;
207 else
208 tp->t_flags |= ISSLOW;
209 tp->t_turn = TRUE;
210 }
211 Delta.y = y;
212 Delta.x = x;
213 runto(&Delta);
214 }
215 when WS_ELECT:
216 case WS_FIRE:
217 case WS_COLD:
218 if (obj->o_which == WS_ELECT)
219 name = "bolt";
220 else if (obj->o_which == WS_FIRE)
221 name = "flame";
222 else
223 name = "ice";
224 fire_bolt(&Hero, &Delta, name);
225 Ws_info[obj->o_which].oi_know = TRUE;
226 when WS_NOP:
227 break;
228#ifdef MASTER
229 otherwise:
230 msg("what a bizarre schtick!");
231#endif
232 }
233 obj->o_charges--;
234}
235
236/*
237 * drain:
238 * Do drain hit points from player shtick
239 */
240void
241drain(void)
242{
243 THING *mp;
244 struct room *corp;
245 THING **dp;
246 int cnt;
247 bool inpass;
248 static THING *drainee[40];
249
250 /*
251 * First cnt how many things we need to spread the hit points among
252 */
253 cnt = 0;
254 if (chat(Hero.y, Hero.x) == DOOR)
255 corp = &Passages[flat(Hero.y, Hero.x) & F_PNUM];
256 else
257 corp = NULL;
258 inpass = (Proom->r_flags & ISGONE);
259 dp = drainee;
260 for (mp = Mlist; mp != NULL; mp = next(mp))
261 if (mp->t_room == Proom || mp->t_room == corp ||
262 (inpass && chat(mp->t_pos.y, mp->t_pos.x) == DOOR &&
263 &Passages[flat(mp->t_pos.y, mp->t_pos.x) & F_PNUM] == Proom))
264 *dp++ = mp;
265 if ((cnt = dp - drainee) == 0)
266 {
267 msg("you have a tingling feeling");
268 return;
269 }
270 *dp = NULL;
271 Pstats.s_hpt /= 2;
272 cnt = Pstats.s_hpt / cnt;
273 /*
274 * Now zot all of the monsters
275 */
276 for (dp = drainee; *dp; dp++)
277 {
278 mp = *dp;
279 if ((mp->t_stats.s_hpt -= cnt) <= 0)
280 killed(mp, see_monst(mp));
281 else
282 runto(&mp->t_pos);
283 }
284}
285
286/*
287 * fire_bolt:
288 * Fire a bolt in a given direction from a specific starting place
289 */
290void
291fire_bolt(coord *start, coord *dir, char *name)
292{
293 coord *c1, *c2;
294 THING *tp;
295 char dirch, ch;
296 bool hit_hero, used, changed;
297 static coord pos;
298 static coord spotpos[BOLT_LENGTH];
299 THING bolt;
300
301 bolt.o_type = WEAPON;
302 bolt.o_which = FLAME;
303 bolt.o_hurldmg = "6x6";
304 bolt.o_hplus = 100;
305 bolt.o_dplus = 0;
306 Weap_info[FLAME].oi_name = name;
307 switch (dir->y + dir->x)
308 {
309 when 0: dirch = '/';
310 when 1: case -1: dirch = (dir->y == 0 ? '-' : '|');
311 when 2: case -2: dirch = '\\';
312 }
313 pos = *start;
314 hit_hero = (start != &Hero);
315 used = FALSE;
316 changed = FALSE;
317 for (c1 = spotpos; c1 < &spotpos[BOLT_LENGTH] && !used; c1++)
318 {
319 pos.y += dir->y;
320 pos.x += dir->x;
321 *c1 = pos;
322 ch = winat(pos.y, pos.x);
323 switch (ch)
324 {
325 case DOOR:
326 /*
327 * this code is necessary if the hero is on a door
328 * and he fires at the wall the door is in, it would
329 * otherwise loop infinitely
330 */
331 if (ce(Hero, pos))
332 goto def;
333 /* FALLTHROUGH */
334 case '|':
335 case '-':
336 case ' ':
337 if (!changed)
338 hit_hero = !hit_hero;
339 changed = FALSE;
340 dir->y = -dir->y;
341 dir->x = -dir->x;
342 c1--;
343 msg("the %s bounces", name);
344 break;
345 default:
346def:
347 if (!hit_hero && (tp = moat(pos.y, pos.x)) != NULL)
348 {
349 hit_hero = TRUE;
350 changed = !changed;
351 tp->t_oldch = chat(pos.y, pos.x);
352 if (!save_throw(VS_MAGIC, tp))
353 {
354 bolt.o_pos = pos;
355 used = TRUE;
356 if (tp->t_type == 'D' && strcmp(name, "flame") == 0)
357 {
358 addmsg("the flame bounces");
359 if (!Terse)
360 addmsg(" off the dragon");
361 endmsg();
362 }
363 else
364 hit_monster(unc(pos), &bolt);
365 }
366 else if (ch != 'M' || tp->t_disguise == 'M')
367 {
368 if (start == &Hero)
369 runto(&pos);
370 if (Terse)
371 msg("%s misses", name);
372 else
373 msg("the %s whizzes past %s", name, set_mname(tp));
374 }
375 }
376 else if (hit_hero && ce(pos, Hero))
377 {
378 hit_hero = FALSE;
379 changed = !changed;
380 if (!save(VS_MAGIC))
381 {
382 if ((Pstats.s_hpt -= roll(6, 6)) <= 0)
383 if (start == &Hero)
384 death('b');
385 else
386 death(moat(start->y, start->x)->t_type);
387 used = TRUE;
388 if (Terse)
389 msg("the %s hits", name);
390 else
391 msg("you are hit by the %s", name);
392 }
393 else
394 msg("the %s whizzes by you", name);
395 }
396 mvaddch(pos.y, pos.x, dirch);
397 refresh();
398 }
399 }
400 for (c2 = spotpos; c2 < c1; c2++)
401 mvaddch(c2->y, c2->x, chat(c2->y, c2->x));
402}
403
404/*
405 * charge_str:
406 * Return an appropriate string for a wand charge
407 */
408char *
409charge_str(THING *obj)
410{
411 static char buf[20];
412
413 if (!(obj->o_flags & ISKNOW))
414 buf[0] = '\0';
415 else if (Terse)
416 sprintf(buf, " [%d]", obj->o_charges);
417 else
418 sprintf(buf, " [%d charges]", obj->o_charges);
419 return buf;
420}