Annotation of early-roguelike/rogue5/sticks.c, Revision 1.1.1.1
1.1 rubenllo 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: strncpy(bolt.o_damage,"0x0",sizeof(bolt.o_damage));
314: bolt.o_launch = -1;
315: bolt.o_hplus = 100;
316: bolt.o_dplus = 0;
317: weap_info[FLAME].oi_name = name;
318: switch (dir->y + dir->x)
319: {
320: case 0: dirch = '/';
321: when 1: case -1: dirch = (dir->y == 0 ? '-' : '|');
322: when 2: case -2: dirch = '\\';
323: }
324: pos = *start;
325: hit_hero = (start != &hero);
326: used = FALSE;
327: changed = FALSE;
328: for (c1 = spotpos; c1 <= &spotpos[BOLT_LENGTH-1] && !used; c1++)
329: {
330: pos.y += dir->y;
331: pos.x += dir->x;
332: *c1 = pos;
333: ch = winat(pos.y, pos.x);
334: switch (ch)
335: {
336: case DOOR:
337: /*
338: * this code is necessary if the hero is on a door
339: * and he fires at the wall the door is in, it would
340: * otherwise loop infinitely
341: */
342: if (ce(hero, pos))
343: goto def;
344: /* FALLTHROUGH */
345: case '|':
346: case '-':
347: case ' ':
348: if (!changed)
349: hit_hero = !hit_hero;
350: changed = FALSE;
351: dir->y = -dir->y;
352: dir->x = -dir->x;
353: c1--;
354: msg("the %s bounces", name);
355: break;
356: default:
357: def:
358: if (!hit_hero && (tp = moat(pos.y, pos.x)) != NULL)
359: {
360: hit_hero = TRUE;
361: changed = !changed;
362: tp->t_oldch = chat(pos.y, pos.x);
363: if (!save_throw(VS_MAGIC, tp))
364: {
365: bolt.o_pos = pos;
366: used = TRUE;
367: if (tp->t_type == 'D' && strcmp(name, "flame") == 0)
368: {
369: addmsg("the flame bounces");
370: if (!terse)
371: addmsg(" off the dragon");
372: endmsg();
373: }
374: else
375: hit_monster(unc(pos), &bolt);
376: }
377: else if (ch != 'M' || tp->t_disguise == 'M')
378: {
379: if (start == &hero)
380: runto(&pos);
381: if (terse)
382: msg("%s misses", name);
383: else
384: msg("the %s whizzes past %s", name, set_mname(tp));
385: }
386: }
387: else if (hit_hero && ce(pos, hero))
388: {
389: hit_hero = FALSE;
390: changed = !changed;
391: if (!save(VS_MAGIC))
392: {
393: if ((pstats.s_hpt -= roll(6, 6)) <= 0)
394: {
395: if (start == &hero)
396: death('b');
397: else
398: death(moat(start->y, start->x)->t_type);
399: }
400: used = TRUE;
401: if (terse)
402: msg("the %s hits", name);
403: else
404: msg("you are hit by the %s", name);
405: }
406: else
407: msg("the %s whizzes by you", name);
408: }
409: mvaddch(pos.y, pos.x, dirch);
410: refresh();
411: }
412: }
413: for (c2 = spotpos; c2 < c1; c2++)
414: mvaddch(c2->y, c2->x, chat(c2->y, c2->x));
415: }
416:
417: /*
418: * charge_str:
419: * Return an appropriate string for a wand charge
420: */
421: const char *
422: charge_str(const THING *obj)
423: {
424: static char buf[20];
425:
426: if (!(obj->o_flags & ISKNOW))
427: buf[0] = '\0';
428: else if (terse)
429: sprintf(buf, " [%d]", obj->o_charges);
430: else
431: sprintf(buf, " [%d charges]", obj->o_charges);
432: return buf;
433: }
CVSweb