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