comparison rogue4/sticks.c @ 12:9535a08ddc39

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