diff rogue4/pack.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/pack.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,421 @@
+/*
+ * Routines to deal with the pack
+ *
+ * @(#)pack.c	4.15 (Berkeley) 4/6/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 "rogue.h"
+
+/*
+ * update_mdest:
+ *	Called after picking up an object, before discarding it.
+ *	If this was the object of something's desire, that monster will
+ *	get mad and run at the hero
+ */
+update_mdest(obj)
+register THING *obj;
+{
+    register THING *mp;
+
+    for (mp = mlist; mp != NULL; mp = next(mp))
+	if (mp->t_dest == &obj->o_pos)
+     mp->t_dest = &hero;
+}
+
+/*
+ * add_pack:
+ *	Pick up an object and add it to the pack.  If the argument is
+ *	non-null use it as the linked_list pointer instead of gettting
+ *	it off the ground.
+ */
+add_pack(obj, silent)
+register THING *obj;
+bool silent;
+{
+    register THING *op, *lp = NULL;
+    register bool exact, from_floor;
+    register char floor;
+    int discarded = 0;
+
+    if (obj == NULL)
+    {
+	from_floor = TRUE;
+	if ((obj = find_obj(hero.y, hero.x)) == NULL)
+	    return;
+    }
+    else
+	from_floor = FALSE;
+    /*
+     * Link it into the pack.  Search the pack for a object of similar type
+     * if there isn't one, stuff it at the beginning, if there is, look for one
+     * that is exactly the same and just increment the count if there is.
+     * it  that.  Food is always put at the beginning for ease of access, but
+     * is not ordered so that you can't tell good food from bad.  First check
+     * to see if there is something in thr same group and if there is then
+     * increment the count.
+     */
+/*    floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR; */
+    if (proom) floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
+    else floor = FLOOR;
+    if (obj->o_group)
+    {
+	for (op = pack; op != NULL; op = next(op))
+	{
+	    if (op->o_group == obj->o_group)
+	    {
+		/*
+		 * Put it in the pack and notify the user
+		 */
+		op->o_count++;
+		if (from_floor)
+		{
+		    detach(lvl_obj, obj);
+		    mvaddch(hero.y, hero.x, floor);
+		    chat(hero.y, hero.x) = floor;
+		}
+		update_mdest(obj);
+		discard(obj);
+		obj = op;
+		discarded = 1;
+		goto picked_up;
+	    }
+	}
+    }
+    /*
+     * Check if there is room
+     */
+    if (inpack == MAXPACK-1)
+    {
+	msg("you can't carry anything else");
+	return;
+    }
+    /*
+     * Check for and deal with scare monster scrolls
+     */
+    if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
+	if (obj->o_flags & ISFOUND)
+	{
+	    detach(lvl_obj, obj);
+	    mvaddch(hero.y, hero.x, floor);
+	    chat(hero.y, hero.x) = floor;
+	    msg("the scroll turns to dust as you pick it up");
+	    return;
+	}
+	else
+	    obj->o_flags |= ISFOUND;
+
+    inpack++;
+    if (from_floor)
+    {
+	detach(lvl_obj, obj);
+	mvaddch(hero.y, hero.x, floor);
+	chat(hero.y, hero.x) = floor;
+    }
+    /*
+     * Search for an object of the same type
+     */
+    exact = FALSE;
+    for (op = pack; op != NULL; op = next(op))
+	if (obj->o_type == op->o_type)
+	    break;
+    if (op == NULL)
+    {
+	/*
+	 * Put it at the end of the pack since it is a new type
+	 */
+	for (op = pack; op != NULL; op = next(op))
+	{
+	    if (op->o_type != FOOD)
+		break;
+	    lp = op;
+	}
+    }
+    else
+    {
+	/*
+	 * Search for an object which is exactly the same
+	 */
+	while (op->o_type == obj->o_type)
+	{
+	    if (op->o_which == obj->o_which)
+	    {
+		exact = TRUE;
+		break;
+	    }
+	    lp = op;
+	    if ((op = next(op)) == NULL)
+		break;
+	}
+    }
+    if (op == NULL)
+    {
+	/*
+	 * Didn't find an exact match, just stick it here
+	 */
+	if (pack == NULL)
+	    pack = obj;
+	else
+	{
+	    lp->l_next = obj;
+	    obj->l_prev = lp;
+	    obj->l_next = NULL;
+	}
+    }
+    else
+    {
+	/*
+	 * If we found an exact match.  If it is a potion, food, or a 
+	 * scroll, increase the count, otherwise put it with its clones.
+	 */
+	if (exact && ISMULT(obj->o_type))
+	{
+	    op->o_count++;
+	    update_mdest(obj);
+	    discard(obj);
+	    obj = op;
+	    discarded = 1;
+	    goto picked_up;
+	}
+	if ((obj->l_prev = prev(op)) != NULL)
+	    obj->l_prev->l_next = obj;
+	else
+	    pack = obj;
+	obj->l_next = op;
+	op->l_prev = obj;
+    }
+picked_up:
+    /*
+     * If this was the object of something's desire, that monster will
+     * get mad and run at the hero
+     */
+    if (!discarded)
+        update_mdest(obj);
+
+    if (obj->o_type == AMULET)
+	amulet = TRUE;
+    /*
+     * Notify the user
+     */
+    if (!silent)
+    {
+	if (!terse)
+	    addmsg("you now have ");
+	msg("%s (%c)", inv_name(obj, !terse), pack_char(obj));
+    }
+}
+
+/*
+ * inventory:
+ *	List what is in the pack
+ */
+inventory(list, type)
+THING *list;
+int type;
+{
+    register char ch;
+    register int n_objs;
+    char inv_temp[MAXSTR];
+
+    n_objs = 0;
+    for (ch = 'a'; list != NULL; ch++, list = next(list))
+    {
+	if (type && type != list->o_type && !(type == CALLABLE &&
+	    (list->o_type == SCROLL || list->o_type == POTION ||
+	     list->o_type == RING || list->o_type == STICK)))
+		continue;
+	n_objs++;
+	sprintf(inv_temp, "%c) %%s", ch);
+	add_line(inv_temp, inv_name(list, FALSE));
+    }
+    if (n_objs == 0)
+    {
+	if (terse)
+	    msg(type == 0 ? "empty handed" :
+			    "nothing appropriate");
+	else
+	    msg(type == 0 ? "you are empty handed" :
+			    "you don't have anything appropriate");
+	return FALSE;
+    }
+    end_line();
+    return TRUE;
+}
+
+/*
+ * pick_up:
+ *	Add something to characters pack.
+ */
+pick_up(ch)
+char ch;
+{
+    register THING *obj, *mp;
+
+    switch (ch)
+    {
+	case GOLD:
+	    if ((obj = find_obj(hero.y, hero.x)) == NULL)
+		return;
+	    money(obj->o_goldval);
+	    detach(lvl_obj, obj);
+	    update_mdest(obj);
+	    discard(obj);
+	    proom->r_goldval = 0;
+	    break;
+	default:
+#ifdef WIZARD
+	    debug("Where did you pick a '%s' up???", unctrol(ch));
+#endif
+	case ARMOR:
+	case POTION:
+	case FOOD:
+	case WEAPON:
+	case SCROLL:	
+	case AMULET:
+	case RING:
+	case STICK:
+	    add_pack(NULL, FALSE);
+	    break;
+    }
+}
+
+/*
+ * picky_inven:
+ *	Allow player to inventory a single item
+ */
+picky_inven()
+{
+    register THING *obj;
+    register char ch, mch;
+
+    if (pack == NULL)
+	msg("you aren't carrying anything");
+    else if (next(pack) == NULL)
+	msg("a) %s", inv_name(pack, FALSE));
+    else
+    {
+	msg(terse ? "item: " : "which item do you wish to inventory: ");
+	mpos = 0;
+	if ((mch = readchar()) == ESCAPE)
+	{
+	    msg("");
+	    return;
+	}
+	for (ch = 'a', obj = pack; obj != NULL; obj = next(obj), ch++)
+	    if (ch == mch)
+	    {
+		msg("%c) %s",ch,inv_name(obj, FALSE));
+		return;
+	    }
+	if (!terse)
+	    msg("'%s' not in pack", unctrol(mch));
+	msg("range is 'a' to '%c'", --ch);
+    }
+}
+
+/*
+ * get_item:
+ *	Pick something out of a pack for a purpose
+ */
+THING *
+get_item(purpose, type)
+char *purpose;
+int type;
+{
+    register THING *obj;
+    register char ch, och;
+
+    if (pack == NULL)
+	msg("you aren't carrying anything");
+    else
+    {
+	for (;;)
+	{
+	    if (!terse)
+		addmsg("which object do you want to ");
+	    addmsg(purpose);
+	    if (terse)
+		addmsg(" what");
+	    msg("? (* for list): ");
+	    ch = readchar();
+	    mpos = 0;
+	    /*
+	     * Give the poor player a chance to abort the command
+	     */
+	    if (ch == ESCAPE || ch == CTRL('G'))
+	    {
+		after = FALSE;
+		msg("");
+		return NULL;
+	    }
+	    if (ch == '*')
+	    {
+		mpos = 0;
+		if (inventory(pack, type) == 0)
+		{
+		    after = FALSE;
+		    return NULL;
+		}
+		continue;
+	    }
+	    for (obj = pack, och = 'a'; obj != NULL; obj = next(obj), och++)
+		if (ch == och)
+		    break;
+	    if (obj == NULL)
+	    {
+		msg("please specify a letter between 'a' and '%c'", och-1);
+		continue;
+	    }
+	    else 
+		return obj;
+	}
+    }
+    return NULL;
+}
+
+/*
+ * pack_char:
+ *	Return which character would address a pack object
+ */
+pack_char(obj)
+register THING *obj;
+{
+    register THING *item;
+    register char c;
+
+    c = 'a';
+    for (item = pack; item != NULL; item = next(item))
+	if (item == obj)
+	    return c;
+	else
+	    c++;
+    return '?';
+}
+
+/*
+ * money:
+ *	Add or subtract gold from the pack
+ */
+money(value)
+register int value;
+{
+    register char floor;
+
+    floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
+    purse += value;
+    mvaddch(hero.y, hero.x, floor);
+    chat(hero.y, hero.x) = floor;
+    if (value > 0)
+    {
+	if (!terse)
+	    addmsg("you found ");
+	msg("%d gold pieces", value);
+    }
+}