diff rogue4/sticks.c @ 12:9535a08ddc39

Import Rogue 5.2 from the Roguelike Restoration Project (r1490)
author edwarj4
date Sat, 24 Oct 2009 16:52:52 +0000
parents
children 1b73a8641b37
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/sticks.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,461 @@
+/*
+ * Functions to implement the various sticks one might find
+ * while wandering around the dungeon.
+ *
+ * @(#)sticks.c	4.22 (Berkeley) 5/19/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <curses.h>
+#include <ctype.h>
+#include <string.h>
+#include "rogue.h"
+
+/*
+ * fix_stick:
+ *	Set up a new stick
+ */
+fix_stick(cur)
+register THING *cur;
+{
+    if (strcmp(ws_type[cur->o_which], "staff") == 0)
+	strcpy(cur->o_damage,"2d3");
+    else
+	strcpy(cur->o_damage,"1d1");
+    strcpy(cur->o_hurldmg,"1d1");
+
+    cur->o_charges = 3 + rnd(5);
+    switch (cur->o_which)
+    {
+	case WS_HIT:
+	    cur->o_hplus = 100;
+	    cur->o_dplus = 3;
+	    strcpy(cur->o_damage,"1d8");
+	when WS_LIGHT:
+	    cur->o_charges = 10 + rnd(10);
+    }
+}
+
+/*
+ * do_zap:
+ *	Perform a zap with a wand
+ */
+do_zap()
+{
+    register THING *obj, *tp;
+    register int y, x;
+    register char *name;
+
+    if ((obj = get_item("zap with", STICK)) == NULL)
+	return;
+    if (obj->o_type != STICK)
+    {
+	after = FALSE;
+	msg("you can't zap with that!");
+	return;
+    }
+    if (obj->o_charges == 0)
+    {
+	msg("nothing happens");
+	return;
+    }
+    switch (obj->o_which)
+    {
+	case WS_LIGHT:
+	    /*
+	     * Reddy Kilowat wand.  Light up the room
+	     */
+	    ws_know[WS_LIGHT] = TRUE;
+	    if (proom->r_flags & ISGONE)
+		msg("the corridor glows and then fades");
+	    else
+	    {
+		proom->r_flags &= ~ISDARK;
+		/*
+		 * Light the room and put the player back up
+		 */
+		enter_room(&hero);
+		addmsg("the room is lit");
+		if (!terse)
+		    addmsg(" by a shimmering blue light");
+		endmsg();
+	    }
+	when WS_DRAIN:
+	    /*
+	     * Take away 1/2 of hero's hit points, then take it away
+	     * evenly from the monsters in the room (or next to hero
+	     * if he is in a passage)
+	     */
+	    if (pstats.s_hpt < 2)
+	    {
+		msg("you are too weak to use it");
+		return;
+	    }
+	    else
+		drain();
+	when WS_POLYMORPH:
+	case WS_TELAWAY:
+	case WS_TELTO:
+	case WS_CANCEL:
+	{
+	    register char monster, oldch;
+	    register int rm;
+
+	    y = hero.y;
+	    x = hero.x;
+	    while (step_ok(winat(y, x)))
+	    {
+		y += delta.y;
+		x += delta.x;
+	    }
+	    if ((tp = moat(y, x)) != NULL)
+	    {
+		register char omonst;
+
+		omonst = monster = tp->t_type;
+		if (monster == 'F')
+		    player.t_flags &= ~ISHELD;
+		if (obj->o_which == WS_POLYMORPH)
+		{
+		    register THING *pp;
+
+		    pp = tp->t_pack;
+		    detach(mlist, tp);
+		    if (see_monst(tp))
+			mvaddch(y, x, chat(y, x));
+		    oldch = tp->t_oldch;
+		    delta.y = y;
+		    delta.x = x;
+		    new_monster(tp, monster = rnd(26) + 'A', &delta);
+		    if (see_monst(tp))
+			mvaddch(y, x, monster);
+		    tp->t_oldch = oldch;
+		    tp->t_pack = pp;
+		    ws_know[WS_POLYMORPH] |= (monster != omonst);
+		}
+		else if (obj->o_which == WS_CANCEL)
+		{
+		    tp->t_flags |= ISCANC;
+		    tp->t_flags &= ~(ISINVIS|CANHUH);
+		    tp->t_disguise = tp->t_type;
+		}
+		else
+		{
+		    if (isupper(toascii(mvinch(y,x))))
+			mvaddch(y, x, tp->t_oldch);
+		    if (obj->o_which == WS_TELAWAY)
+		    {
+			do
+			{
+			    rm = rnd_room();
+			    rnd_pos(&rooms[rm], &tp->t_pos);
+			} until (winat(tp->t_pos.y, tp->t_pos.x) == FLOOR);
+			tp->t_room = roomin(&tp->t_pos);
+			tp->t_oldch = mvinch(tp->t_pos.y, tp->t_pos.x);
+			if (see_monst(tp))
+			    mvaddch(tp->t_pos.y, tp->t_pos.x, tp->t_disguise);
+			else if (on(player, SEEMONST))
+			{
+			    standout();
+			    mvaddch(tp->t_pos.y, tp->t_pos.x, tp->t_disguise);
+			    standend();
+			}
+		    }
+		    else
+		    {
+			tp->t_pos.y = hero.y + delta.y;
+			tp->t_pos.x = hero.x + delta.x;
+		    
+		        if (tp->t_pos.y != y || tp->t_pos.x != x)
+			    tp->t_oldch = mvinch(tp->t_pos.y, tp->t_pos.x);
+		    }
+		    moat(y, x) = NULL;
+		    moat(tp->t_pos.y, tp->t_pos.x) = tp;
+		    if (tp->t_type == 'F')
+			player.t_flags &= ~ISHELD;
+		}
+		tp->t_dest = &hero;
+		tp->t_flags |= ISRUN;
+	    }
+	}
+	when WS_MISSILE:
+	{
+	    THING bolt;
+
+	    ws_know[WS_MISSILE] = TRUE;
+	    bolt.o_type = '*';
+	    strcpy(bolt.o_hurldmg,"1d4");
+	    bolt.o_hplus = 100;
+	    bolt.o_dplus = 1;
+	    bolt.o_flags = ISMISL;
+	    if (cur_weapon != NULL)
+		bolt.o_launch = cur_weapon->o_which;
+	    do_motion(&bolt, delta.y, delta.x);
+	    if ((tp = moat(bolt.o_pos.y, bolt.o_pos.x)) != NULL && !save_throw(VS_MAGIC, tp))
+		    hit_monster(unc(bolt.o_pos), &bolt);
+	    else if (terse)
+		msg("missle vanishes");
+	    else
+		msg("the missle vanishes with a puff of smoke");
+	}
+	when WS_HIT:
+	    delta.y += hero.y;
+	    delta.x += hero.x;
+	    if ((tp = moat(delta.y, delta.x)) != NULL)
+	    {
+		if (rnd(20) == 0)
+		{
+		    strcpy(obj->o_damage,"3d8");
+		    obj->o_dplus = 9;
+		}
+		else
+		{
+		    strcpy(obj->o_damage,"1d8");
+		    obj->o_dplus = 3;
+		}
+		fight(&delta, tp->t_type, obj, FALSE);
+	    }
+	when WS_HASTE_M:
+	case WS_SLOW_M:
+	    y = hero.y;
+	    x = hero.x;
+	    while (step_ok(winat(y, x)))
+	    {
+		y += delta.y;
+		x += delta.x;
+	    }
+	    if ((tp = moat(y, x)) != NULL)
+	    {
+		if (obj->o_which == WS_HASTE_M)
+		{
+		    if (on(*tp, ISSLOW))
+			tp->t_flags &= ~ISSLOW;
+		    else
+			tp->t_flags |= ISHASTE;
+		}
+		else
+		{
+		    if (on(*tp, ISHASTE))
+			tp->t_flags &= ~ISHASTE;
+		    else
+			tp->t_flags |= ISSLOW;
+		    tp->t_turn = TRUE;
+		}
+		delta.y = y;
+		delta.x = x;
+		runto(&delta, &hero);
+	    }
+	when WS_ELECT:
+	case WS_FIRE:
+	case WS_COLD:
+	    if (obj->o_which == WS_ELECT)
+		name = "bolt";
+	    else if (obj->o_which == WS_FIRE)
+		name = "flame";
+	    else
+		name = "ice";
+	    fire_bolt(&hero, &delta, name);
+	    ws_know[obj->o_which] = TRUE;
+	when WS_NOP:
+	otherwise:
+	    msg("what a bizarre schtick!");
+    }
+    obj->o_charges--;
+}
+
+/*
+ * drain:
+ *	Do drain hit points from player shtick
+ */
+drain()
+{
+    register THING *mp;
+    register int cnt;
+    register struct room *corp;
+    register THING **dp;
+    register bool inpass;
+    static THING *drainee[40];
+
+    /*
+     * First cnt how many things we need to spread the hit points among
+     */
+    cnt = 0;
+    if (chat(hero.y, hero.x) == DOOR)
+	corp = &passages[flat(hero.y, hero.x) & F_PNUM];
+    else
+	corp = NULL;
+    inpass = (proom->r_flags & ISGONE);
+    dp = drainee;
+    for (mp = mlist; mp != NULL; mp = next(mp))
+	if (mp->t_room == proom || mp->t_room == corp ||
+	    (inpass && chat(mp->t_pos.y, mp->t_pos.x) == DOOR &&
+	    &passages[flat(mp->t_pos.y, mp->t_pos.x) & F_PNUM] == proom))
+		*dp++ = mp;
+    if ((cnt = dp - drainee) == 0)
+    {
+	msg("you have a tingling feeling");
+	return;
+    }
+    *dp = NULL;
+    pstats.s_hpt /= 2;
+    cnt = pstats.s_hpt / cnt;
+    /*
+     * Now zot all of the monsters
+     */
+    for (dp = drainee; *dp; dp++)
+    {
+	mp = *dp;
+	if ((mp->t_stats.s_hpt -= cnt) <= 0)
+	    killed(mp, see_monst(mp));
+	else
+	    runto(&mp->t_pos, &hero);
+    }
+}
+
+/*
+ * fire_bolt:
+ *	Fire a bolt in a given direction from a specific starting place
+ */
+fire_bolt(start, dir, name)
+coord *start, *dir;
+char *name;
+{
+    register char dirch, ch;
+    register THING *tp;
+    register bool hit_hero, used, changed;
+    register int i, j;
+    coord pos;
+    coord spotpos[BOLT_LENGTH];
+    THING bolt;
+
+    bolt.o_type = WEAPON;
+    bolt.o_which = FLAME;
+    strcpy(bolt.o_hurldmg,"6d6");
+    bolt.o_hplus = 100;
+    bolt.o_dplus = 0;
+    bolt.o_flags = 0;
+    w_names[FLAME] = name;
+    switch (dir->y + dir->x)
+    {
+	case 0: dirch = '/';
+	when 1: case -1: dirch = (dir->y == 0 ? '-' : '|');
+	when 2: case -2: dirch = '\\';
+    }
+    pos = *start;
+    hit_hero = (start != &hero);
+    used = FALSE;
+    changed = FALSE;
+    for (i = 0; i < BOLT_LENGTH && !used; i++)
+    {
+	pos.y += dir->y;
+	pos.x += dir->x;
+	ch = winat(pos.y, pos.x);
+	spotpos[i] = pos;
+	switch (ch)
+	{
+	    case DOOR:
+		/*
+ 		 * this code is necessary if the hero is on a door
+ 		 * and he fires at the wall the door is in, it would
+ 		 * otherwise loop infinitely
+ 		 * It is also needed if a dragon flames at the hero.
+ 		 * If the hero is at a door, the dragon flame would bounce
+ 		 * and could kill other monsters inadvertly.
+ 		 */
+ 		if (ce(hero, pos))
+ 		    goto def;
+ 		/* FALLTHROUGH */
+
+	    case '|':
+	    case '-':
+	    case ' ':
+		if (!changed)
+		    hit_hero = !hit_hero;
+		changed = FALSE;
+		dir->y = -dir->y;
+		dir->x = -dir->x;
+		i--;
+		msg("the %s bounces", name);
+		break;
+	    default:
+def:
+		if (!hit_hero && (tp = moat(pos.y, pos.x)) != NULL)
+		{
+		    hit_hero = TRUE;
+		    changed = !changed;
+		    tp->t_oldch = chat(pos.y, pos.x);
+		    if (!save_throw(VS_MAGIC, tp))
+		    {
+			bolt.o_pos = pos;
+			used = TRUE;
+			if (tp->t_type == 'D' && strcmp(name, "flame") == 0)
+			{
+			    addmsg("the flame bounces");
+			    if (!terse)
+				msg("off the dragon");
+			    endmsg();
+			}
+			else
+			    hit_monster(unc(pos), &bolt);
+		    }
+		    else if (ch != 'M' || tp->t_disguise == 'M')
+		    {
+			if (start == &hero)
+			    runto(&pos, &hero);
+			if (terse)
+			    msg("%s misses", name);
+			else
+			    msg("the %s whizzes past the %s", name, monsters[ch-'A'].m_name);
+		    }
+		}
+		else if (hit_hero && ce(pos, hero))
+		{
+		    hit_hero = FALSE;
+		    changed = !changed;
+		    if (!save(VS_MAGIC))
+		    {
+			if ((pstats.s_hpt -= roll(6, 6)) <= 0)
+			    if (start == &hero)
+				death('b');
+			    else
+				death(moat(start->y, start->x)->t_type);
+			used = TRUE;
+			if (terse)
+			    msg("the %s hits", name);
+			else
+			    msg("you are hit by the %s", name);
+		    }
+		    else
+			msg("the %s whizzes by you", name);
+		}
+		mvaddch(pos.y, pos.x, dirch);
+		refresh();
+	}
+    }
+    for (j = 0; j < i; j++)
+	mvaddch(spotpos[j].y, spotpos[j].x, chat(spotpos[j].y, spotpos[j].x));
+}
+
+/*
+ * charge_str:
+ *	Return an appropriate string for a wand charge
+ */
+char *
+charge_str(obj)
+register THING *obj;
+{
+    static char buf[20];
+
+    if (!(obj->o_flags & ISKNOW))
+	buf[0] = '\0';
+    else if (terse)
+	sprintf(buf, " [%d]", obj->o_charges);
+    else
+	sprintf(buf, " [%d charges]", obj->o_charges);
+    return buf;
+}