diff rogue3/sticks.c @ 0:527e2150eaf0

Import Rogue 3.6 from the Roguelike Restoration Project (r1490)
author edwarj4
date Tue, 13 Oct 2009 13:33:34 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/sticks.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,401 @@
+/*
+ * Functions to implement the various sticks one might find
+ * while wandering around the dungeon.
+ *
+ * @(#)sticks.c	3.14 (Berkeley) 6/15/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 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"
+
+void
+fix_stick(struct object *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 = 3;
+	    cur->o_dplus = 3;
+	    strcpy(cur->o_damage,"1d8");
+	when WS_LIGHT:
+	    cur->o_charges = 10 + rnd(10);
+    }
+}
+
+void
+do_zap(int gotdir)
+{
+    struct linked_list *item;
+    struct object *obj;
+    struct room *rp;
+    struct thing *tp;
+    int y, x;
+
+    if ((item = get_item("zap with", STICK)) == NULL)
+	return;
+    obj = (struct object *) ldata(item);
+    if (obj->o_type != STICK)
+    {
+	msg("You can't zap with that!");
+	after = FALSE;
+	return;
+    }
+    if (obj->o_charges == 0)
+    {
+	msg("Nothing happens.");
+	return;
+    }
+    if (!gotdir)
+	do {
+	    delta.y = rnd(3) - 1;
+	    delta.x = rnd(3) - 1;
+	} while (delta.y == 0 && delta.x == 0);
+    switch (obj->o_which)
+    {
+	case WS_LIGHT:
+	    /*
+	     * Reddy Kilowat wand.  Light up the room
+	     */
+	    ws_know[WS_LIGHT] = TRUE;
+	    if ((rp = roomin(&hero)) == NULL)
+		msg("The corridor glows and then fades");
+	    else
+	    {
+		addmsg("The room is lit");
+		if (!terse)
+		    addmsg(" by a shimmering blue light.");
+		endmsg();
+		rp->r_flags &= ~ISDARK;
+		/*
+		 * Light the room and put the player back up
+		 */
+		light(&hero);
+		mvwaddch(cw, hero.y, hero.x, PLAYER);
+	    }
+	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 if ((rp = roomin(&hero)) == NULL)
+		drain(hero.y-1, hero.y+1, hero.x-1, hero.x+1);
+	    else
+		drain(rp->r_pos.y, rp->r_pos.y+rp->r_max.y,
+		    rp->r_pos.x, rp->r_pos.x+rp->r_max.x);
+	when WS_POLYMORPH:
+	case WS_TELAWAY:
+	case WS_TELTO:
+	case WS_CANCEL:
+	{
+	    int monster;
+	    int oldch;
+	    int rm;
+
+	    y = hero.y;
+	    x = hero.x;
+	    while (step_ok(winat(y, x)))
+	    {
+		y += delta.y;
+		x += delta.x;
+	    }
+	    if (isupper(monster = mvwinch(mw, y, x)))
+	    {
+		int omonst = monster;
+
+		if (monster == 'F')
+		    player.t_flags &= ~ISHELD;
+		item = find_mons(y, x);
+		tp = (struct thing *) ldata(item);
+		if (obj->o_which == WS_POLYMORPH)
+		{
+		    detach(mlist, item);
+		    oldch = tp->t_oldch;
+		    delta.y = y;
+		    delta.x = x;
+		    new_monster(item, monster = rnd(26) + 'A', &delta);
+		    if (!(tp->t_flags & ISRUN))
+			runto(&delta, &hero);
+		    if (isupper(mvwinch(cw, y, x)))
+			mvwaddch(cw, y, x, monster);
+		    tp->t_oldch = oldch;
+		    ws_know[WS_POLYMORPH] |= (monster != omonst);
+		}
+		else if (obj->o_which == WS_CANCEL)
+		{
+		    tp->t_flags |= ISCANC;
+		    tp->t_flags &= ~ISINVIS;
+		}
+		else
+		{
+		    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);
+		    }
+		    else
+		    {
+			tp->t_pos.y = hero.y + delta.y;
+			tp->t_pos.x = hero.x + delta.x;
+		    }
+		    if (isupper(mvwinch(cw, y, x)))
+			mvwaddch(cw, y, x, tp->t_oldch);
+		    tp->t_dest = &hero;
+		    tp->t_flags |= ISRUN;
+		    mvwaddch(mw, y, x, ' ');
+		    mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, monster);
+		    if (tp->t_pos.y != y || tp->t_pos.x != x)
+			tp->t_oldch = mvwinch(cw, tp->t_pos.y, tp->t_pos.x);
+		}
+	    }
+	}
+	when WS_MISSILE:
+	{
+	    static struct object bolt =
+	    {
+		'*' , {0, 0}, 0, "", "1d4" , 0, 0, 100, 1, 0, 0, 0
+	    };
+
+	    do_motion(&bolt, delta.y, delta.x);
+	    if (isupper(mvwinch(mw, bolt.o_pos.y, bolt.o_pos.x))
+		&& !save_throw(VS_MAGIC, THINGPTR(find_mons(unc(bolt.o_pos)))))
+		    hit_monster(unc(bolt.o_pos), &bolt);
+	    else if (terse)
+		msg("Missile vanishes");
+	    else
+		msg("The missile vanishes with a puff of smoke");
+	    ws_know[WS_MISSILE] = TRUE;
+	}
+	when WS_HIT:
+	{
+	    int ch;
+
+	    delta.y += hero.y;
+	    delta.x += hero.x;
+	    ch = winat(delta.y, delta.x);
+	    if (isupper(ch))
+	    {
+		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, ch, 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 (isupper(mvwinch(mw, y, x)))
+	    {
+		item = find_mons(y, x);
+		tp = (struct thing *) ldata(item);
+		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:
+	{
+	    int dirch;
+	    char *name;
+	    int ch;
+	    int bounced, used;
+	    coord pos;
+	    coord spotpos[BOLT_LENGTH];
+	    static struct object bolt =
+	    {
+		'*' , {0, 0}, 0, "", "6d6" , 0, 0, 100, 0, 0, 0 ,0
+	    };
+
+
+	    switch (delta.y + delta.x)
+	    {
+		case 0: dirch = '/';
+		when 1: case -1: dirch = (delta.y == 0 ? '-' : '|');
+		when 2: case -2: dirch = '\\';
+	    }
+	    pos = hero;
+	    bounced = FALSE;
+	    used = FALSE;
+	    if (obj->o_which == WS_ELECT)
+		name = "bolt";
+	    else if (obj->o_which == WS_FIRE)
+		name = "flame";
+	    else
+		name = "ice";
+	    for (y = 0; y < BOLT_LENGTH && !used; y++)
+	    {
+		ch = winat(pos.y, pos.x);
+		spotpos[y] = pos;
+		switch (ch)
+		{
+		    case DOOR:
+		    case SECRETDOOR:
+		    case '|':
+		    case '-':
+		    case ' ':
+			bounced = TRUE;
+			delta.y = -delta.y;
+			delta.x = -delta.x;
+			y--;
+			msg("The bolt bounces");
+			break;
+		    default:
+			if (!bounced && isupper(ch))
+			{
+			    if (!save_throw(VS_MAGIC, THINGPTR(find_mons(unc(pos)))))
+			    {
+				bolt.o_pos = pos;
+				hit_monster(unc(pos), &bolt);
+				used = TRUE;
+			    }
+			    else if (ch != 'M' || show(pos.y, pos.x) == 'M')
+			    {
+				if (terse)
+				    msg("%s misses", name);
+				else
+				    msg("The %s whizzes past the %s", name, monsters[ch-'A'].m_name);
+				runto(&pos, &hero);
+			    }
+			}
+			else if (bounced && pos.y == hero.y && pos.x == hero.x)
+			{
+			    bounced = FALSE;
+			    if (!save(VS_MAGIC))
+			    {
+				if (terse)
+				    msg("The %s hits", name);
+				else
+				    msg("You are hit by the %s", name);
+				if ((pstats.s_hpt -= roll(6, 6)) <= 0)
+				    death('b');
+				used = TRUE;
+			    }
+			    else
+				msg("The %s whizzes by you", name);
+			}
+			mvwaddch(cw, pos.y, pos.x, dirch);
+			draw(cw);
+		}
+		pos.y += delta.y;
+		pos.x += delta.x;
+	    }
+	    for (x = 0; x < y; x++)
+		mvwaddch(cw, spotpos[x].y, spotpos[x].x, show(spotpos[x].y, spotpos[x].x));
+	    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
+ */
+
+void
+drain(int ymin, int ymax, int xmin, int xmax)
+{
+    int i, j, cnt;
+    struct thing *ick;
+    struct linked_list *item;
+
+    /*
+     * First count how many things we need to spread the hit points among
+     */
+    cnt = 0;
+    for (i = ymin; i <= ymax; i++)
+	for (j = xmin; j <= xmax; j++)
+	    if (isupper(mvwinch(mw, i, j)))
+		cnt++;
+    if (cnt == 0)
+    {
+	msg("You have a tingling feeling");
+	return;
+    }
+    cnt = pstats.s_hpt / cnt;
+    pstats.s_hpt /= 2;
+    /*
+     * Now zot all of the monsters
+     */
+    for (i = ymin; i <= ymax; i++)
+	for (j = xmin; j <= xmax; j++)
+	    if (isupper(mvwinch(mw, i, j)) &&
+	        ((item = find_mons(i, j)) != NULL))
+	    {
+		ick = (struct thing *) ldata(item);
+		if ((ick->t_stats.s_hpt -= cnt) < 1)
+		    killed(item, cansee(i, j) && !on(*ick, ISINVIS));
+	    }
+}
+
+/*
+ * charge a wand for wizards.
+ */
+char *
+charge_str(struct object *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;
+}