diff rogue5/pack.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 e5a15b09ce1d
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue5/pack.c	Mon May 24 20:10:59 2010 +0000
@@ -0,0 +1,526 @@
+/*
+ * Routines to deal with the pack
+ *
+ * @(#)pack.c	4.40 (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 <string.h>
+#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.
+ */
+
+void
+add_pack(THING *obj, int silent)
+{
+    THING *op, *lp;
+    int from_floor;
+    int discarded = 0;
+
+    from_floor = FALSE;
+    if (obj == NULL)
+    {
+	if ((obj = find_obj(hero.y, hero.x)) == NULL)
+	    return;
+	from_floor = TRUE;
+    }
+
+    /*
+     * 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_ch());
+	    chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
+            update_mdest(obj);
+            discarded = 1;
+	    discard(obj);
+	    msg("the scroll turns to dust as you pick it up");
+	    return;
+	}
+
+    if (pack == NULL)
+    {
+	pack = obj;
+	obj->o_packch = pack_char();
+	inpack++;
+    }
+    else
+    {
+	lp = NULL;
+	for (op = pack; op != NULL; op = next(op))
+	{
+	    if (op->o_type != obj->o_type)
+		lp = op;
+	    else
+	    {
+		while (op->o_type == obj->o_type && op->o_which != obj->o_which)
+		{
+		    lp = op;
+		    if (next(op) == NULL)
+			break;
+		    else
+			op = next(op);
+		}
+		if (op->o_type == obj->o_type && op->o_which == obj->o_which)
+		{
+		    if (ISMULT(op->o_type))
+		    {
+			if (!pack_room(from_floor, obj))
+			    return;
+			op->o_count++;
+dump_it:
+			update_mdest(obj);
+			discard(obj);
+			obj = op;
+                        discarded = 1;
+			lp = NULL;
+			goto out;
+		    }
+		    else if (obj->o_group)
+		    {
+			lp = op;
+			while (op->o_type == obj->o_type
+			    && op->o_which == obj->o_which
+			    && op->o_group != obj->o_group)
+			{
+			    lp = op;
+			    if (next(op) == NULL)
+				break;
+			    else
+				op = next(op);
+			}
+			if (op->o_type == obj->o_type
+			    && op->o_which == obj->o_which
+			    && op->o_group == obj->o_group)
+			{
+				op->o_count += obj->o_count;
+				inpack--;
+				if (!pack_room(from_floor, obj))
+				    return;
+				goto dump_it;
+			}
+		    }
+		    else
+			lp = op;
+		}
+out:
+		break;
+	    }
+	}
+
+	if (lp != NULL)
+	{
+	    if (!pack_room(from_floor, obj))
+		return;
+	    else
+	    {
+		obj->o_packch = pack_char();
+		next(obj) = next(lp);
+		prev(obj) = lp;
+		if (next(lp) != NULL)
+		    prev(next(lp)) = obj;
+		next(lp) = obj;
+	    }
+	}
+    }
+
+    obj->o_flags |= ISFOUND;
+
+    /*
+     * 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), obj->o_packch);
+    }
+}
+
+/*
+ * pack_room:
+ *	See if there's room in the pack.  If not, print out an
+ *	appropriate message
+ */
+int
+pack_room(int from_floor, THING *obj)
+{
+    if (++inpack > MAXPACK)
+    {
+	if (!terse)
+	    addmsg("there's ");
+	addmsg("no room");
+	if (!terse)
+	    addmsg(" in your pack");
+	endmsg();
+	if (from_floor)
+	    move_msg(obj);
+	inpack = MAXPACK;
+	return FALSE;
+    }
+
+    if (from_floor)
+    {
+	detach(lvl_obj, obj);
+	mvaddch(hero.y, hero.x, floor_ch());
+	chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
+    }
+
+    return TRUE;
+}
+
+/*
+ * leave_pack:
+ *	take an item out of the pack
+ */
+THING *
+leave_pack(THING *obj, int newobj, int all)
+{
+    THING *nobj;
+
+    inpack--;
+    nobj = obj;
+    if (obj->o_count > 1 && !all)
+    {
+	last_pick = obj;
+	obj->o_count--;
+	if (obj->o_group)
+	    inpack++;
+	if (newobj)
+	{
+	    nobj = new_item();
+	    *nobj = *obj;
+	    next(nobj) = NULL;
+	    prev(nobj) = NULL;
+	    nobj->o_count = 1;
+	}
+    }
+    else
+    {
+	last_pick = NULL;
+	pack_used[obj->o_packch - 'a'] = FALSE;
+	detach(pack, obj);
+    }
+    return nobj;
+}
+
+/*
+ * pack_char:
+ *	Return the next unused pack character.
+ */
+int
+pack_char(void)
+{
+    int *bp;
+
+    for (bp = pack_used; *bp; bp++)
+	continue;
+    *bp = TRUE;
+    return ((int)(bp - pack_used) + 'a');
+}
+
+/*
+ * inventory:
+ *	List what is in the pack.  Return TRUE if there is something of
+ *	the given type.
+ */
+int
+inventory(const THING *list, int type)
+{
+    static char inv_temp[MAXSTR];
+
+    n_objs = 0;
+    for (; list != NULL; list = next(list))
+    {
+	if (type && type != list->o_type && !(type == CALLABLE &&
+	    list->o_type != FOOD && list->o_type != AMULET) &&
+	    !(type == R_OR_S && (list->o_type == RING || list->o_type == STICK)))
+		continue;
+	n_objs++;
+#ifdef MASTER
+	if (!list->o_packch)
+	    strcpy(inv_temp, "%s");
+	else
+#endif
+	    sprintf(inv_temp, "%c) %%s", list->o_packch);
+	msg_esc = TRUE;
+	if (add_line(inv_temp, inv_name(list, FALSE)) == ESCAPE)
+	{
+	    msg_esc = FALSE;
+	    msg("");
+	    return TRUE;
+	}
+	msg_esc = 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.
+ */
+
+void
+pick_up(int ch)
+{
+    THING *obj;
+
+    if (on(player, ISLEVIT))
+	return;
+
+    obj = find_obj(hero.y, hero.x);
+    if (move_on)
+	move_msg(obj);
+    else
+	switch (ch)
+	{
+	    case GOLD:
+		if (obj == NULL)
+		    return;
+		money(obj->o_goldval);
+		detach(lvl_obj, obj);
+		update_mdest(obj);
+		discard(obj);
+		proom->r_goldval = 0;
+		break;
+	    default:
+#ifdef MASTER
+		debug("Where did you pick a '%s' up???", unctrl(ch));
+#endif
+	    case ARMOR:
+	    case POTION:
+	    case FOOD:
+	    case WEAPON:
+	    case SCROLL:	
+	    case AMULET:
+	    case RING:
+	    case STICK:
+		add_pack(NULL, FALSE);
+		break;
+	}
+}
+
+/*
+ * move_msg:
+ *	Print out the message if you are just moving onto an object
+ */
+
+void
+move_msg(const THING *obj)
+{
+    if (!terse)
+	addmsg("you ");
+    msg("moved onto %s", inv_name(obj, TRUE));
+}
+
+/*
+ * picky_inven:
+ *	Allow player to inventory a single item
+ */
+
+void
+picky_inven(void)
+{
+    THING *obj;
+    int 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 (obj = pack; obj != NULL; obj = next(obj))
+	    if (mch == obj->o_packch)
+	    {
+		msg("%c) %s", mch, inv_name(obj, FALSE));
+		return;
+	    }
+	msg("'%s' not in pack", unctrl(mch));
+    }
+}
+
+/*
+ * get_item:
+ *	Pick something out of a pack for a purpose
+ */
+THING *
+get_item(const char *purpose, int type)
+{
+    THING *obj;
+    int ch;
+
+    if (pack == NULL)
+	msg("you aren't carrying anything");
+    else if (again)
+	if (last_pick)
+	    return last_pick;
+	else
+	    msg("you ran out");
+    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)
+	    {
+		reset_last();
+		after = FALSE;
+		msg("");
+		return NULL;
+	    }
+	    n_objs = 1;		/* normal case: person types one char */
+	    if (ch == '*')
+	    {
+		mpos = 0;
+		if (inventory(pack, type) == 0)
+		{
+		    after = FALSE;
+		    return NULL;
+		}
+		continue;
+	    }
+	    for (obj = pack; obj != NULL; obj = next(obj))
+		if (obj->o_packch == ch)
+		    break;
+	    if (obj == NULL)
+	    {
+		msg("'%s' is not a valid item",unctrl(ch));
+		continue;
+	    }
+	    else {
+		msg("");
+		return obj;
+	    }
+	}
+    }
+    return NULL;
+}
+
+/*
+ * money:
+ *	Add or subtract gold from the pack
+ */
+
+void
+money(int value)
+{
+    purse += value;
+    mvaddch(hero.y, hero.x, floor_ch());
+    chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
+    if (value > 0)
+    {
+	if (!terse)
+	    addmsg("you found ");
+	msg("%d gold pieces", value);
+    }
+}
+
+/*
+ * floor_ch:
+ *	Return the appropriate floor character for her room
+ */
+int
+floor_ch(void)
+{
+    if (proom->r_flags & ISGONE)
+	return PASSAGE;
+    return (show_floor() ? FLOOR : ' ');
+}
+
+/*
+ * floor_at:
+ *	Return the character at hero's position, taking see_floor
+ *	into account
+ */
+int
+floor_at(void)
+{
+    int ch;
+
+    ch = chat(hero.y, hero.x);
+    if (ch == FLOOR)
+	ch = floor_ch();
+    return ch;
+}
+
+/*
+ * reset_last:
+ *	Reset the last command when the current one is aborted
+ */
+
+void
+reset_last(void)
+{
+    last_comm = l_last_comm;
+    last_dir = l_last_dir;
+    last_pick = l_last_pick;
+}