diff rogue3/pack.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 d9e44e18eeec
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/pack.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,399 @@
+/*
+ * Routines to deal with the pack
+ *
+ * @(#)pack.c	3.6 (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 "rogue.h"
+
+/*
+ * 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(struct linked_list *item, int silent)
+{
+    struct linked_list *ip, *lp;
+    struct object *obj, *op;
+    int exact, from_floor;
+
+    if (item == NULL)
+    {
+	from_floor = TRUE;
+	if ((item = find_obj(hero.y, hero.x)) == NULL)
+	    return;
+    }
+    else
+	from_floor = FALSE;
+    obj = (struct object *) ldata(item);
+    /*
+     * 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.
+     */
+    if (obj->o_group)
+    {
+	for (ip = pack; ip != NULL; ip = next(ip))
+	{
+	    op = (struct object *) ldata(ip);
+	    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, item);
+		    mvaddch(hero.y, hero.x,
+			(roomin(&hero) == NULL ? PASSAGE : FLOOR));
+		}
+		discard(item);
+		item = ip;
+		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)
+	{
+	    msg("The scroll turns to dust as you pick it up.");
+	    detach(lvl_obj, item);
+	    mvaddch(hero.y, hero.x, FLOOR);
+	    return;
+	}
+	else
+	    obj->o_flags |= ISFOUND;
+
+    inpack++;
+    if (from_floor)
+    {
+	detach(lvl_obj, item);
+	mvaddch(hero.y, hero.x, (roomin(&hero) == NULL ? PASSAGE : FLOOR));
+    }
+    /*
+     * Search for an object of the same type
+     */
+    exact = FALSE;
+    for (ip = pack; ip != NULL; ip = next(ip))
+    {
+	op = (struct object *) ldata(ip);
+	if (obj->o_type == op->o_type)
+	    break;
+    }
+    if (ip == NULL)
+    {
+	/*
+	 * Put it at the end of the pack since it is a new type
+	 */
+	for (ip = pack; ip != NULL; ip = next(ip))
+	{
+	    op = (struct object *) ldata(ip);
+	    if (op->o_type != FOOD)
+		break;
+	    lp = ip;
+	}
+    }
+    else
+    {
+	/*
+	 * Search for an object which is exactly the same
+	 */
+	while (ip != NULL && op->o_type == obj->o_type)
+	{
+	    if (op->o_which == obj->o_which)
+	    {
+		exact = TRUE;
+		break;
+	    }
+	    lp = ip;
+	    if ((ip = next(ip)) == NULL)
+		break;
+	    op = (struct object *) ldata(ip);
+	}
+    }
+    if (ip == NULL)
+    {
+	/*
+	 * Didn't find an exact match, just stick it here
+	 */
+	if (pack == NULL)
+	    pack = item;
+	else
+	{
+	    lp->l_next = item;
+	    item->l_prev = lp;
+	    item->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++;
+	    discard(item);
+	    item = ip;
+	    goto picked_up;
+	}
+	if ((item->l_prev = prev(ip)) != NULL)
+	    item->l_prev->l_next = item;
+	else
+	    pack = item;
+	item->l_next = ip;
+	ip->l_prev = item;
+    }
+picked_up:
+    /*
+     * Notify the user
+     */
+    obj = (struct object *) ldata(item);
+    if (notify && !silent)
+    {
+	if (!terse)
+	    addmsg("You now have ");
+	msg("%s (%c)", inv_name(obj, !terse), pack_char(obj));
+    }
+    if (obj->o_type == AMULET)
+	amulet = TRUE;
+}
+
+/*
+ * inventory:
+ *	list what is in the pack
+ */
+int
+inventory(struct linked_list *list, int type)
+{
+    struct object *obj;
+    int ch;
+    int n_objs;
+    char inv_temp[80];
+
+    n_objs = 0;
+    for (ch = 'a'; list != NULL; ch++, list = next(list))
+    {
+	obj = (struct object *) ldata(list);
+	if (type && type != obj->o_type && !(type == CALLABLE &&
+	    (obj->o_type == SCROLL || obj->o_type == POTION ||
+	     obj->o_type == RING || obj->o_type == STICK)))
+		continue;
+	switch (n_objs++)
+	{
+	    /*
+	     * For the first thing in the inventory, just save the string
+	     * in case there is only one.
+	     */
+	    case 0:
+		sprintf(inv_temp, "%c) %s", ch, inv_name(obj, FALSE));
+		break;
+	    /*
+	     * If there is more than one, clear the screen, print the
+	     * saved message and fall through to ...
+	     */
+	    case 1:
+		if (slow_invent)
+		    msg(inv_temp);
+		else
+		{
+		    wclear(hw);
+		    waddstr(hw, inv_temp);
+		    waddch(hw, '\n');
+		}
+	    /*
+	     * Print the line for this object
+	     */
+	    default:
+		if (slow_invent)
+		    msg("%c) %s", ch, inv_name(obj, FALSE));
+		else
+		    wprintw(hw, "%c) %s\n", ch, inv_name(obj, 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;
+    }
+    if (n_objs == 1)
+    {
+	msg(inv_temp);
+	return TRUE;
+    }
+    if (!slow_invent)
+    {
+	mvwaddstr(hw, LINES-1, 0, "--Press space to continue--");
+	draw(hw);
+	wait_for(hw,' ');
+	clearok(cw, TRUE);
+	touchwin(cw);
+    }
+    return TRUE;
+}
+
+/*
+ * pick_up:
+ *	Add something to characters pack.
+ */
+void
+pick_up(int ch)
+{
+    switch(ch)
+    {
+	case GOLD:
+	    money();
+	    break;
+	default:
+	    debug("Where did you pick that up???");
+	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
+ */
+void
+picky_inven()
+{
+    struct linked_list *item;
+    int ch, mch;
+
+    if (pack == NULL)
+	msg("You aren't carrying anything");
+    else if (next(pack) == NULL)
+	msg("a) %s", inv_name((struct object *) ldata(pack), FALSE));
+    else
+    {
+	msg(terse ? "Item: " : "Which item do you wish to inventory: ");
+	mpos = 0;
+	if ((mch = readchar(cw)) == ESCAPE)
+	{
+	    msg("");
+	    return;
+	}
+	for (ch = 'a', item = pack; item != NULL; item = next(item), ch++)
+	    if (ch == mch)
+	    {
+		msg("%c) %s",ch,inv_name((struct object *) ldata(item), FALSE));
+		return;
+	    }
+	if (!terse)
+	    msg("'%s' not in pack", unctrl(mch));
+	msg("Range is 'a' to '%c'", --ch);
+    }
+}
+
+/*
+ * get_item:
+ *	pick something out of a pack for a purpose
+ */
+struct linked_list *
+get_item(char *purpose, int type)
+{
+    struct linked_list *obj;
+    int 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(cw);
+	    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;
+}
+
+int
+pack_char(struct object *obj)
+{
+    struct linked_list *item;
+    int c;
+
+    c = 'a';
+    for (item = pack; item != NULL; item = next(item))
+	if ((struct object *) ldata(item) == obj)
+	    return c;
+	else
+	    c++;
+    return 'z';
+}