view srogue/pack.c @ 239:837044d2c362

Merge the GCC5 and build fix branches. This fixes all warnings produced by GCC 5, except the ones related to system functions. Those could be fixed by including the proper headers, but it would be better to replace the system-dependent code with functions from mdport.c.
author John "Elwin" Edwards
date Fri, 11 Mar 2016 19:47:52 -0500
parents 94a0d9dd5ce1
children
line wrap: on
line source

/*
 * Routines to deal with the pack
 *
 * @(#)pack.c	9.0	(rdk)	 7/17/84
 *
 * Super-Rogue
 * Copyright (C) 1984 Robert D. Kindelberger
 * All rights reserved.
 *
 * Based on "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 <ctype.h>
#include "rogue.h"
#include "rogue.ext"

/*
 * 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
 * getting it off the ground.
 */
bool
add_pack(struct linked_list *item, bool silent)
{
	reg struct linked_list *ip, *lp;
	reg struct object *obj, *op = NULL;
	bool from_floor;
	char delchar;

	if (player.t_room == NULL)
		delchar = PASSAGE;
	else
		delchar = FLOOR;
	if (item == NULL) {
		from_floor = TRUE;
		if ((item = find_obj(hero.y, hero.x)) == NULL) {
			mpos = 0;
			msg("That object must have been an illusion.");
			mvaddch(hero.y, hero.x, delchar);
			return FALSE;
		}
		/*
		 * Check for scare monster scrolls
		 */
		obj = OBJPTR(item);
		if (obj->o_type == SCROLL && obj->o_which == S_SCARE) {
			if (o_on(obj,ISFOUND)) {
				msg("The scroll turns to dust as you pick it up.");
				detach(lvl_obj, item);
				discard(item);
				mvaddch(hero.y, hero.x, delchar);	
				return FALSE;
			}
		}
	}
	else
		from_floor = FALSE;
	obj = OBJPTR(item);
	/*
	 * See if this guy can carry any more weight
	 */
	if (itemweight(obj) + him->s_pack > him->s_carry) {
		msg("You can't carry that %s.", obj->o_typname);
		return FALSE;
	}
	/*
	 * Check if there is room
	 */
	if (packvol + obj->o_vol > V_PACK) {
		msg("That %s won't fit in your pack.", obj->o_typname);
		return FALSE;
	}
	if (from_floor) {
		detach(lvl_obj, item);
		mvaddch(hero.y, hero.x, delchar);
	}
	item->l_prev = NULL;
	item->l_next = NULL;
	setoflg(obj, ISFOUND);
	/*
	 * start looking thru pack to find the start of items
	 * with the same type.
	 */
	lp = pack;
	for (ip = pack; ip != NULL; ip = next(ip)) {
		op = OBJPTR(ip);
		/*
		 * If we find a matching type then quit.
		 */
		if (op->o_type == obj->o_type)
			break;
		if (next(ip) != NULL)
			lp = next(lp);		/* update "previous" entry */
	}
	/*
	 * If the pack was empty, just stick the item in it.
	 */
	if (pack == NULL) {
		pack = item;
		item->l_prev = NULL;
	}
	/*
	 * If we looked thru the pack, but could not find an
	 * item of the same type, then stick it at the end,
	 * unless it was food, then put it in front.
	 */
	else if (ip == NULL) {
		if (obj->o_type == FOOD) {	/* insert food at front */
			item->l_next = pack;
			pack->l_prev = item;
			pack = item;
			item->l_prev = NULL;
		}
		else {						/* insert other stuff at back */
			lp->l_next = item;
			item->l_prev = lp;
		}
	}
	/*
	 * Here, we found at least one item of the same type.
	 * Look thru these items to see if there is one of the
	 * same group. If so, increment the count and throw the
	 * new item away. If not, stick it at the end of the
	 * items with the same type. Also keep all similar
	 * objects near each other, like all identify scrolls, etc.
	 */
	else {
		struct linked_list **save;

		while (ip != NULL && op->o_type == obj->o_type) {
			if (op->o_group == obj->o_group) {
				if (op->o_flags == obj->o_flags) {
					op->o_count++;
					discard(item);
					item = ip;
					goto picked_up;
				}
				else {
					goto around;
				}
			}
			if (op->o_which == obj->o_which) {
				if (obj->o_type == FOOD)
					ip = next(ip);
				break;
			}
around:
			ip = next(ip);
			if (ip != NULL) {
				op = OBJPTR(ip);
				lp = next(lp);
			}
		}
		/*
		 * If inserting into last of group at end of pack,
		 * just tack on the end.
		 */
		if (ip == NULL) {
			lp->l_next = item;
			item->l_prev = lp;
		}
		/*
		 * Insert into the last of a group of objects
		 * not at the end of the pack.
		 */
		else {
			save = &((ip->l_prev)->l_next);
			item->l_next = ip;
			item->l_prev = ip->l_prev;
			ip->l_prev = item;
			*save = item;
		}
	}
picked_up:
	obj = OBJPTR(item);
	if (!silent)
		msg("%s (%c)",inv_name(obj,FALSE),pack_char(obj));
	if (obj->o_type == AMULET)
		amulet = TRUE;
	updpack();				/* new pack weight & volume */
	return TRUE;
}

/*
 * inventory:
 *	Show what items are in a specific list
 */
bool
inventory(struct linked_list *list, int type)
{
	reg struct linked_list *pc;
	reg struct object *obj;
	reg char ch;
	reg int cnt;

	if (list == NULL) {			/* empty list */
		msg(type == 0 ? "Empty handed." : "Nothing appropriate.");
		return FALSE;
	}
	else if (next(list) == NULL) {	/* only 1 item in list */
		obj = OBJPTR(list);
		msg("a) %s", inv_name(obj, FALSE));
		return TRUE;
	}
	cnt = 0;
	wclear(hw);
	for (ch = 'a', pc = list; pc != NULL; pc = next(pc), ch = npch(ch)) {
		obj = OBJPTR(pc);
		wprintw(hw,"%c) %s\n\r",ch,inv_name(obj, FALSE));
		if (++cnt > LINES - 2 && next(pc) != NULL) {
			dbotline(hw, morestr);
			cnt = 0;
			wclear(hw);
		} 
	}
	dbotline(hw,spacemsg);
	restscr(cw);
	return TRUE;
}

/*
 * pick_up:
 *	Add something to characters pack.
 */
void
pick_up(char ch)
{
	nochange = FALSE;
	switch(ch) {
		case GOLD:
			money();
		when ARMOR:
		case POTION:
		case FOOD:
		case WEAPON:
		case SCROLL:	
		case AMULET:
		case RING:
		case STICK:
			add_pack(NULL, FALSE);
		otherwise:
			msg("That item is ethereal !!!");
	}
}

/*
 * picky_inven:
 *	Allow player to inventory a single item
 */
void
picky_inven(void)
{
	reg struct linked_list *item;
	reg char ch, mch;

	if (pack == NULL)
		msg("You aren't carrying anything.");
	else if (next(pack) == NULL)
		msg("a) %s", inv_name(OBJPTR(pack), FALSE));
	else {
		msg("Item: ");
		mpos = 0;
		if ((mch = readchar()) == ESCAPE) {
			msg("");
			return;
		}
		for (ch='a',item=pack; item != NULL; item=next(item),ch=npch(ch))
			if (ch == mch) {
				msg("%c) %s",ch,inv_name(OBJPTR(item), FALSE));
				return;
			}
		if (ch == 'A')
			ch = 'z';
		else
			ch -= 1;
		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)
{
	reg struct linked_list *obj, *pit, *savepit = NULL;
	struct object *pob;
	int ch, och, anr, cnt;

	if (pack == NULL) {
		msg("You aren't carrying anything.");
		return NULL;
	}
	if (type != WEAPON && (type != 0 || next(pack) == NULL)) {
		/*
		 * see if we have any of the type requested
		 */
		pit = pack;
		anr = 0;
		for (ch = 'a'; pit != NULL; pit = next(pit), ch = npch(ch)) {
			pob = OBJPTR(pit);
			if (type == pob->o_type || type == 0) {
				++anr;
				savepit = pit;	/* save in case of only 1 */
			}
		}
		if (anr == 0) {
			msg("Nothing to %s",purpose);
			after = FALSE;
			return NULL;
		}
		else if (anr == 1) {	/* only found one of 'em */
			do {
				struct object *opb;

				opb = OBJPTR(savepit);
				msg("%s what (* for the item)?",purpose);
				och = readchar();
				if (och == '*') {
					mpos = 0;
					msg("%c) %s",pack_char(opb),inv_name(opb,FALSE));
					continue;
				}
				if (och == ESCAPE) {
					msg("");
					after = FALSE;
					return NULL;
				}
				if (isalpha(och) && och != pack_char(opb)) {
					mpos = 0;
					msg("You can't %s that !!", purpose);
					after = FALSE;
					return NULL;
				}
			} while(!isalpha(och));
			mpos = 0;
			return savepit;		/* return this item */
		}
	}
	for (;;) {
		msg("%s what? (* for list): ",purpose);
		ch = readchar();
		mpos = 0;
		if (ch == ESCAPE) {		/* abort if escape hit */
			after = FALSE;
			msg("");			/* clear display */
			return NULL;
		}
		if (ch == '*') {
			wclear(hw);
			pit = pack;		/* point to pack */
			cnt = 0;
			for (ch='a'; pit != NULL; pit=next(pit), ch=npch(ch)) {
				pob = OBJPTR(pit);
				if (type == 0 || type == pob->o_type) {
					wprintw(hw,"%c) %s\n\r",ch,inv_name(pob,FALSE));
					if (++cnt > LINES - 2 && next(pit) != NULL) {
						cnt = 0;
						dbotline(hw, morestr);
						wclear(hw);
					}
				}
			}
			wmove(hw, LINES - 1,0);
			wprintw(hw,"%s what? ",purpose);
			draw(hw);		/* write screen */
			anr = FALSE;
			do {
				ch = readchar();
				if (isalpha(ch) || ch == ESCAPE)
					anr = TRUE; 
			} while(!anr);		/* do till we got it right */
			restscr(cw);		/* redraw orig screen */
			if (ch == ESCAPE) {
				after = FALSE;
				msg("");		/* clear top line */
				return NULL;	/* all done if abort */
			}
			/* ch has item to get from pack */
		}
		for (obj=pack,och='a';obj!=NULL;obj=next(obj),och=npch(och))
			if (ch == och)
				break;
		if (obj == NULL) {
			if (och == 'A')
				och = 'z';
			else
				och -= 1;
			msg("Please specify a letter between 'a' and '%c'",och);
			continue;
		}
		else 
			return obj;
	}
}

/*
 * pack_char:
 *	Get the character of a particular item in the pack
 */
char
pack_char(struct object *obj)
{
	reg struct linked_list *item;
	reg char c;

	c = 'a';
	for (item = pack; item != NULL; item = next(item))
		if (OBJPTR(item) == obj)
			return c;
		else
			c = npch(c);
	return '%';
}

/*
 * idenpack:
 *	Identify all the items in the pack
 */
void
idenpack(void)
{
	reg struct linked_list *pc;

	for (pc = pack ; pc != NULL ; pc = next(pc))
		whatis(pc);
}


/* 
 * del_pack:
 *	Take something out of the hero's pack
 */
void
del_pack(struct linked_list *what)
{
	reg struct object *op;

	op = OBJPTR(what);
	cur_null(op);		/* check for current stuff */
	if (op->o_count > 1) {
		op->o_count--;
	}
	else {
		detach(pack,what);
		discard(what);
	}
	updpack();
}

/*
 * cur_null:
 *	This updates cur_weapon etc for dropping things
 */
void
cur_null(struct object *op)
{
	if (op == cur_weapon)
		cur_weapon = NULL;
	else if (op == cur_armor)
		cur_armor = NULL;
	else if (op == cur_ring[LEFT])
		cur_ring[LEFT] = NULL;
	else if (op == cur_ring[RIGHT])
		cur_ring[RIGHT] = NULL;
}