rogue

Ken Arnold's Rogue
git clone https://git.woozle.org/neale/rogue.git

Neale Pickett  ·  2011-10-13

signal.c

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