diff rogue5/weapons.c @ 33:f502bf60e6e4

Import Rogue 5.4 from the Roguelike Restoration Project (r1490)
author elwin
date Mon, 24 May 2010 20:10:59 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue5/weapons.c	Mon May 24 20:10:59 2010 +0000
@@ -0,0 +1,286 @@
+/*
+ * Functions for dealing with problems brought about by weapons
+ *
+ * @(#)weapons.c	4.34 (Berkeley) 02/05/99
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980-1983, 1985, 1999 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 <string.h>
+#include <ctype.h>
+#include "rogue.h"
+
+#define NO_WEAPON -1
+
+static const struct init_weaps {
+    char *iw_dam;	/* Damage when wielded */
+    char *iw_hrl;	/* Damage when thrown */
+    int iw_launch;	/* Launching weapon */
+    int iw_flags;	/* Miscellaneous flags */
+} init_dam[MAXWEAPONS] = {
+    { "2x4",	"1x3",	NO_WEAPON,	0,		},	/* Mace */
+    { "3x4",	"1x2",	NO_WEAPON,	0,		},	/* Long sword */
+    { "1x1",	"1x1",	NO_WEAPON,	0,		},	/* Bow */
+    { "1x1",	"2x3",	BOW,		ISMANY|ISMISL,	},	/* Arrow */
+    { "1x6",	"1x4",	NO_WEAPON,	ISMISL|ISMISL,	},	/* Dagger */
+    { "4x4",	"1x2",	NO_WEAPON,	0,		},	/* 2h sword */
+    { "1x1",	"1x3",	NO_WEAPON,	ISMANY|ISMISL,	},	/* Dart */
+    { "1x2",	"2x4",	NO_WEAPON,	ISMANY|ISMISL,	},	/* Shuriken */
+    { "2x3",	"1x6",	NO_WEAPON,	ISMISL,		},	/* Spear */
+};
+
+/*
+ * missile:
+ *	Fire a missile in a given direction
+ */
+
+void
+missile(int ydelta, int xdelta)
+{
+    THING *obj;
+
+    /*
+     * Get which thing we are hurling
+     */
+    if ((obj = get_item("throw", WEAPON)) == NULL)
+	return;
+    if (!dropcheck(obj) || is_current(obj))
+	return;
+    obj = leave_pack(obj, TRUE, FALSE);
+    do_motion(obj, ydelta, xdelta);
+    /*
+     * AHA! Here it has hit something.  If it is a wall or a door,
+     * or if it misses (combat) the monster, put it on the floor
+     */
+    if (moat(obj->o_pos.y, obj->o_pos.x) == NULL ||
+	!hit_monster(unc(obj->o_pos), obj))
+	    fall(obj, TRUE);
+}
+
+/*
+ * do_motion:
+ *	Do the actual motion on the screen done by an object traveling
+ *	across the room
+ */
+
+void
+do_motion(THING *obj, int ydelta, int xdelta)
+{
+    int ch;
+
+    /*
+     * Come fly with us ...
+     */
+    obj->o_pos = hero;
+    for (;;)
+    {
+	/*
+	 * Erase the old one
+	 */
+	if (!ce(obj->o_pos, hero) && cansee(unc(obj->o_pos)) && !terse)
+	{
+	    ch = chat(obj->o_pos.y, obj->o_pos.x);
+	    if (ch == FLOOR && !show_floor())
+		ch = ' ';
+	    mvaddch(obj->o_pos.y, obj->o_pos.x, ch);
+	}
+	/*
+	 * Get the new position
+	 */
+	obj->o_pos.y += ydelta;
+	obj->o_pos.x += xdelta;
+	if (step_ok(ch = winat(obj->o_pos.y, obj->o_pos.x)) && ch != DOOR)
+	{
+	    /*
+	     * It hasn't hit anything yet, so display it
+	     * If it alright.
+	     */
+	    if (cansee(unc(obj->o_pos)) && !terse)
+	    {
+		mvaddch(obj->o_pos.y, obj->o_pos.x, obj->o_type);
+		refresh();
+	    }
+	    continue;
+	}
+	break;
+    }
+}
+
+/*
+ * fall:
+ *	Drop an item someplace around here.
+ */
+
+void
+fall(THING *obj, int pr)
+{
+    PLACE *pp;
+    coord fpos;
+
+    if (fallpos(&obj->o_pos, &fpos))
+    {
+	pp = INDEX(fpos.y, fpos.x);
+	pp->p_ch = obj->o_type;
+	obj->o_pos = fpos;
+	if (cansee(fpos.y, fpos.x))
+	{
+	    if (pp->p_monst != NULL)
+		pp->p_monst->t_oldch = obj->o_type;
+	    else
+		mvaddch(fpos.y, fpos.x, obj->o_type);
+	}
+	attach(lvl_obj, obj);
+	return;
+    }
+    if (pr)
+    {
+	if (has_hit)
+	{
+	    endmsg();
+	    has_hit = FALSE;
+	}
+	msg("the %s vanishes as it hits the ground",
+	    weap_info[obj->o_which].oi_name);
+    }
+    discard(obj);
+}
+
+/*
+ * init_weapon:
+ *	Set up the initial goodies for a weapon
+ */
+
+void
+init_weapon(THING *weap, int which)
+{
+    const struct init_weaps *iwp;
+
+    weap->o_type = WEAPON;
+    weap->o_which = which;
+    iwp = &init_dam[which];
+    strncpy(weap->o_damage, iwp->iw_dam, sizeof(weap->o_damage));
+    strncpy(weap->o_hurldmg,iwp->iw_hrl, sizeof(weap->o_hurldmg));
+    weap->o_launch = iwp->iw_launch;
+    weap->o_flags = iwp->iw_flags;
+    weap->o_hplus = 0;
+    weap->o_dplus = 0;
+    if (which == DAGGER)
+    {
+	weap->o_count = rnd(4) + 2;
+	weap->o_group = group++;
+    }
+    else if (weap->o_flags & ISMANY)
+    {
+	weap->o_count = rnd(8) + 8;
+	weap->o_group = group++;
+    }
+    else
+    {
+	weap->o_count = 1;
+	weap->o_group = 0;
+    }
+}
+
+/*
+ * hit_monster:
+ *	Does the missile hit the monster?
+ */
+int
+hit_monster(int y, int x, const THING *obj)
+{
+    coord mp;
+
+    mp.y = y;
+    mp.x = x;
+    return fight(&mp, obj, TRUE);
+}
+
+/*
+ * num:
+ *	Figure out the plus number for armor/weapons
+ */
+const char *
+num(int n1, int n2, int type)
+{
+    static char numbuf[10];
+
+    sprintf(numbuf, n1 < 0 ? "%d" : "+%d", n1);
+    if (type == WEAPON)
+	sprintf(&numbuf[strlen(numbuf)], n2 < 0 ? ",%d" : ",+%d", n2);
+    return numbuf;
+}
+
+/*
+ * wield:
+ *	Pull out a certain weapon
+ */
+
+void
+wield(void)
+{
+    THING *obj, *oweapon;
+    char *sp;
+
+    oweapon = cur_weapon;
+    if (!dropcheck(cur_weapon))
+    {
+	cur_weapon = oweapon;
+	return;
+    }
+    cur_weapon = oweapon;
+    if ((obj = get_item("wield", WEAPON)) == NULL)
+    {
+bad:
+	after = FALSE;
+	return;
+    }
+
+    if (obj->o_type == ARMOR)
+    {
+	msg("you can't wield armor");
+	goto bad;
+    }
+    if (is_current(obj))
+        goto bad;
+
+    sp = inv_name(obj, TRUE);
+    cur_weapon = obj;
+    if (!terse)
+	addmsg("you are now ");
+    msg("wielding %s (%c)", sp, obj->o_packch);
+}
+
+/*
+ * fallpos:
+ *	Pick a random position around the give (y, x) coordinates
+ */
+int
+fallpos(const coord *pos, coord *newpos)
+{
+    int y, x, cnt, ch;
+
+    cnt = 0;
+    for (y = pos->y - 1; y <= pos->y + 1; y++)
+	for (x = pos->x - 1; x <= pos->x + 1; x++)
+	{
+	    /*
+	     * check to make certain the spot is empty, if it is,
+	     * put the object there, set it in the level list
+	     * and re-draw the room if he can see it
+	     */
+	    if (y == hero.y && x == hero.x)
+		continue;
+	    if (((ch = chat(y, x)) == FLOOR || ch == PASSAGE)
+					&& rnd(++cnt) == 0)
+	    {
+		newpos->y = y;
+		newpos->x = x;
+	    }
+	}
+    return (cnt != 0);
+}