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