comparison urogue/sticks.c @ 256:c495a4f288c6

Import UltraRogue from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Tue, 31 Jan 2017 19:56:04 -0500
parents
children e52a8a7ad4c5
comparison
equal deleted inserted replaced
253:d9badb9c0179 256:c495a4f288c6
1 /*
2 sticks.c - Functions to implement the various sticks one might find
3
4 UltraRogue: The Ultimate Adventure in the Dungeons of Doom
5 Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
6 All rights reserved.
7
8 Based on "Advanced Rogue"
9 Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
10 All rights reserved.
11
12 Based on "Rogue: Exploring the Dungeons of Doom"
13 Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
14 All rights reserved.
15
16 See the file LICENSE.TXT for full copyright and licensing information.
17 */
18
19 #include <limits.h>
20 #include <string.h>
21 #include <ctype.h>
22 #include "rogue.h"
23
24 /* for WS_HIT, WS_WEB, etc */
25
26 static struct object null_stick =
27 {
28 {0,0},NULL,NULL,"",0,"0d0",0,0,'X',0,0,0,0,0,0,0,0,0,{0}
29 };
30
31 /*
32 * Mask for cancelling special abilities The flags listed here will be the
33 * ones left on after the cancellation takes place
34 */
35
36 #define CANC0MASK ( ISBLIND | ISINWALL | ISRUN | \
37 ISFLEE | ISMEAN | ISGREED | \
38 CANSHOOT | ISHELD | ISHUH | \
39 ISSLOW | ISHASTE | ISCLEAR | \
40 ISUNIQUE)
41
42 #define CANC1MASK ( HASDISEASE | DIDSUFFOCATE | CARRYGOLD | \
43 HASITCH | CANSELL | CANBBURN | \
44 CANSPEAK | CANFLY | ISFRIENDLY)
45
46 #define CANC2MASK ( HASINFEST | NOMOVE | ISSCAVENGE | \
47 DOROT | HASSTINK | DIDHOLD)
48
49 #define CANC3MASK ( ISUNDEAD | CANBREATHE | CANCAST | \
50 HASOXYGEN)
51
52 #define CANC4MASK ( CANTRAMPLE | CANSWIM | CANWIELD | \
53 ISFAST | CANBARGAIN | CANSPORE | \
54 ISLARGE | ISSMALL | ISFLOCK | \
55 ISSWARM | CANSTICK | CANTANGLE | \
56 SHOOTNEEDLE | CANZAP | HASARMOR | \
57 CANTELEPORT | ISBERSERK | ISFAMILIAR | \
58 HASFAMILIAR | SUMMONING)
59
60 #define CANC5MASK ( CANREFLECT | MAGICATTRACT | HASSHIELD | HASMSHIELD)
61
62 #define CANC6MASK ( 0 )
63 #define CANC7MASK ( 0 )
64 #define CANC8MASK ( 0 )
65 #define CANC9MASK ( 0 )
66 #define CANCAMASK ( 0 )
67 #define CANCBMASK ( 0 )
68 #define CANCCMASK ( 0 )
69 #define CANCDMASK ( 0 )
70 #define CANCEMASK ( 0 )
71 #define CANCFMASK ( 0 )
72
73 void
74 fix_stick(struct object *cur)
75 {
76 if (strcmp(ws_type[cur->o_which], "staff") == 0)
77 {
78 cur->o_weight = 100;
79 cur->o_charges = 5 + rnd(10);
80 cur->o_damage = "2d3";
81
82 switch (cur->o_which)
83 {
84 case WS_HIT:
85 cur->o_hplus = 3;
86 cur->o_dplus = 3;
87 cur->o_damage = "2d8";
88 break;
89
90 case WS_LIGHT:
91 cur->o_charges = 20 + rnd(10);
92 break;
93 }
94 }
95 else /* A wand */
96 {
97 cur->o_damage = "1d3";
98 cur->o_weight = 60;
99 cur->o_charges = 3 + rnd(5);
100
101 switch (cur->o_which)
102 {
103 case WS_HIT:
104 cur->o_hplus = 3;
105 cur->o_dplus = 3;
106 cur->o_damage = "1d8";
107 break;
108
109 case WS_LIGHT:
110 cur->o_charges = 10 + rnd(10);
111 break;
112 }
113 }
114
115 cur->o_hurldmg = "1d1";
116 }
117
118 /*
119 do_zap()
120 zap a stick (or effect a stick-like spell)
121 zapper: who does it
122 got_dir: need to ask for direction?
123 which: which WS_STICK (-1 means ask from pack)
124 flags: ISBLESSED, ISCURSED
125 */
126
127 void
128 do_zap(struct thing *zapper, int which, unsigned long flags)
129 {
130 struct linked_list *item = NULL, *nitem;
131 struct object *obj, *nobj;
132 struct room *rp;
133 struct thing *tp = NULL;
134 char *mname = NULL;
135 int y, x;
136 int blessed = flags & ISBLESSED;
137 int cursed = flags & ISCURSED;
138 int is_stick = (which < 0 ? TRUE : FALSE);
139 int got_one = TRUE;
140
141 if (zapper != &player)
142 {
143 monster_do_zap(zapper, which, flags);
144 return;
145 }
146
147 if (is_stick)
148 {
149 if ((obj = get_object(pack, "zap with", 0, bff_zappable)) == NULL)
150 return;
151
152 if (obj->o_type != STICK && !(obj->o_flags & ISZAPPED))
153 {
154 msg("You can't zap with that!");
155 return;
156 }
157
158 if (obj->o_type != STICK) /* an electrified weapon */
159 which = WS_ELECT;
160 else
161 which = obj->o_which;
162
163 if (obj->o_charges < 1)
164 {
165 nothing_message(flags);
166 return;
167 }
168
169 obj->o_charges--;
170
171 if (delta.y == 0 && delta.x == 0)
172 do
173 {
174 delta.y = rnd(3) - 1;
175 delta.x = rnd(3) - 1;
176 }
177 while (delta.y == 0 && delta.x == 0);
178
179 flags = obj->o_flags;
180 cursed = obj->o_flags & ISCURSED;
181 blessed = obj->o_flags & ISBLESSED;
182 }
183 else
184 obj = &null_stick;
185
186 /* Find out who the target is */
187
188 y = hero.y;
189 x = hero.x;
190
191 while(shoot_ok(CCHAR(winat(y, x))))
192 {
193 y += delta.y;
194 x += delta.x;
195 }
196
197 if (x >= 0 && x < COLS && y >= 1 && y < LINES - 2 &&
198 isalpha(mvwinch(mw, y, x)))
199 {
200 item = find_mons(y, x);
201 tp = THINGPTR(item);
202 mname = on(player, ISBLIND) ? "monster" :
203 monsters[tp->t_index].m_name;
204
205 if (on(*tp, CANSELL))
206 {
207 luck++;
208 aggravate();
209 }
210 }
211 else
212 got_one = FALSE;
213
214 debug("Zapping with %d", which);
215
216 switch(which)
217 {
218 case WS_LIGHT:
219 /* Reddy Kilowat wand. Light up the room */
220 if (blue_light(flags) && is_stick)
221 if (is_stick)
222 know_items[TYP_STICK][WS_LIGHT] = TRUE;
223 break;
224
225 case WS_DRAIN:
226
227 /*
228 * Take away 1/2 of hero's hit points, then take it away
229 * evenly from the monsters in the room or next to hero if he
230 * is in a passage. Leave the monsters alone if the stick is
231 * cursed. Drain 1/3rd of hero's hit points if blessed.
232 */
233
234 if (pstats.s_hpt < 2)
235 {
236 death(D_DRAINLIFE);
237 return;
238 }
239
240 if (cursed)
241 pstats.s_hpt /= 2;
242 else if ((rp = roomin(hero)) == NULL)
243 drain(hero.y - 1, hero.y + 1, hero.x - 1, hero.x + 1);
244 else
245 drain(rp->r_pos.y, rp->r_pos.y + rp->r_max.y,
246 rp->r_pos.x, rp->r_pos.x + rp->r_max.x);
247
248 if (blessed)
249 pstats.s_hpt = (int) (pstats.s_hpt * 2.0 / 3.0);
250
251 break;
252
253 case WS_POLYMORPH:
254 case WS_MONSTELEP:
255 case WS_CANCEL:
256 {
257 char oldch;
258 int rm;
259 int save_adj = 0;
260
261 if (got_one)
262 {
263 /* if the monster gets the saving throw, leave the case */
264
265 if (blessed)
266 save_adj = -5;
267
268 if (cursed)
269 if (which == WS_POLYMORPH)
270 save_adj = -5; /* not save vs becoming tougher */
271 else
272 save_adj = 5;
273
274 if (save_throw(VS_MAGIC - save_adj, tp))
275 {
276 nothing_message(flags);
277 break;
278 }
279 else if (is_stick)
280 know_items[TYP_STICK][which] = TRUE;
281
282 /* Unhold player */
283
284 if (on(*tp, DIDHOLD))
285 {
286 turn_off(*tp, DIDHOLD);
287
288 if (--hold_count == 0)
289 turn_off(player, ISHELD);
290 }
291
292 /* unsuffocate player */
293
294 if (on(*tp, DIDSUFFOCATE))
295 {
296 turn_off(*tp, DIDSUFFOCATE);
297 extinguish_fuse(FUSE_SUFFOCATE);
298 }
299
300 if (which == WS_POLYMORPH)
301 {
302 int which_new;
303 int charmed;
304
305 detach(mlist, item);
306 charmed = on(*tp, ISCHARMED);
307 oldch = tp->t_oldch;
308 delta.y = y;
309 delta.x = x;
310
311 if (!blessed && !cursed)
312 which_new = randmonster(WANDER, GRAB);
313 else
314 {
315 /* duplicate randmonster() for now */
316 /* Eventually fix to take level */
317
318 int cur_level = 0, range, i;
319
320 if (blessed)
321 cur_level = level / 2;
322
323 if (cursed)
324 cur_level = level * 2;
325
326 range = 4 * NLEVMONS;
327 i = 0;
328
329 do
330 {
331 if (i++ > range * 10) /* just in case all have */
332 { /* been genocided */
333 i = 0;
334
335 if (--cur_level <= 0)
336 fatal("Rogue could not find a monster to make");
337 }
338
339 which_new = NLEVMONS * (cur_level - 1) + (rnd(range) - (range - 1 - NLEVMONS));
340
341 if (which_new < 1)
342 which_new = rnd(NLEVMONS) + 1;
343
344 if (which_new > nummonst - NUMSUMMON - 1)
345 {
346 if (blessed)
347 which_new = rnd(range) + (nummonst - NUMSUMMON - 1) - (range - 1);
348 else if (which_new > nummonst - 1)
349 which_new = rnd(range + NUMSUMMON) + (nummonst - 1) - (range + NUMSUMMON - 1);
350 }
351 }
352 while (!monsters[which_new].m_normal);
353 }
354
355 new_monster(item, which_new, &delta, NOMAXSTATS);
356 mname = on(player, ISBLIND) ? "monster" : monsters[tp->t_index].m_name;
357
358 if (!cursed && charmed)
359 turn_on(*tp, ISCHARMED);
360
361 if (off(*tp, ISRUN))
362 chase_it(&delta, &player);
363
364 if (isalpha(mvwinch(cw, y, x)))
365 mvwaddch(cw, y, x, tp->t_type);
366
367 tp->t_oldch = oldch;