Mercurial > hg > early-roguelike
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 } | |