예제 #1
0
파일: obj-pile.c 프로젝트: fizzix/angband
/**
 * Remove object 'obj' from pile 'pile'.
 */
void pile_excise(struct object **pile, struct object *obj)
{
	struct object *prev = obj->prev;
	struct object *next = obj->next;

	assert(pile_contains(*pile, obj));
	pile_check_integrity("excise [pre]", *pile, obj);

	/* Special case: unlink top object */
	if (*pile == obj) {
		assert(prev == NULL);	/* Invariant - if it's the top of the pile */

		*pile = next;
	} else {
		assert(obj->prev != NULL);	/* Should definitely have a previous one set */

		/* Otherwise unlink from the previous */
		prev->next = next;
		obj->prev = NULL;
	}

	/* And then unlink from the next */
	if (next) {
		next->prev = prev;
		obj->next = NULL;
	}

	pile_check_integrity("excise [post]", *pile, NULL);
}
예제 #2
0
파일: obj-pile.c 프로젝트: awalding/angband
/**
 * Check that both the object lists are consistent and relate to locations of
 * objects correctly
 */
void object_lists_check_integrity(void)
{
	int i;
	assert(cave->obj_max == cave_k->obj_max);
	for (i = 0; i < cave->obj_max; i++) {
		struct object *obj = cave->objects[i];
		struct object *known_obj = cave_k->objects[i];
		if (obj) {
			assert(obj->oidx == i);
			if (obj->iy && obj->ix)
				assert(pile_contains(cave->squares[obj->iy][obj->ix].obj, obj));
		}
		if (known_obj) {
			assert (obj);
			assert(known_obj == obj->known);
			if (known_obj->iy && known_obj->ix)
				assert (pile_contains(cave_k->squares[known_obj->iy][known_obj->ix].obj, known_obj));
			assert (known_obj->oidx == i);
		}
	}
}
예제 #3
0
파일: cave.c 프로젝트: datatypevoid/angband
/**
 * Check that a pair of object lists are consistent and relate to locations of
 * objects correctly
 */
void object_lists_check_integrity(struct chunk *c, struct chunk *c_k)
{
	int i;
	assert(c->obj_max == c_k->obj_max);
	for (i = 0; i < c->obj_max; i++) {
		struct object *obj = c->objects[i];
		struct object *known_obj = c_k->objects[i];
		if (obj) {
			assert(obj->oidx == i);
			if (obj->iy && obj->ix)
				assert(pile_contains(c->squares[obj->iy][obj->ix].obj, obj));
		}
		if (known_obj) {
			assert (obj);
			if (player->upkeep->playing) {
				assert(known_obj == obj->known);
			}
			if (known_obj->iy && known_obj->ix)
				assert (pile_contains(c_k->squares[known_obj->iy][known_obj->ix].obj, known_obj));
			assert (known_obj->oidx == i);
		}
	}
}
예제 #4
0
/**
 * Drop (some of) a non-cursed inventory/equipment item "near" the current
 * location
 *
 * There are two cases here - a single object or entire stack is being dropped,
 * or part of a stack is being split off and dropped
 */
void inven_drop(struct object *obj, int amt)
{
	int py = player->py;
	int px = player->px;
	struct object *dropped;

	char o_name[80];
	char label;

	/* Error check */
	if (amt <= 0)
		return;

	/* Check it is still held, in case there were two drop commands queued
	 * for this item.  This is in theory not ideal, but in practice should
	 * be safe. */
	if (!pile_contains(player->gear, obj))
		return;

	/* Get where the object is now */
	label = gear_to_label(obj);

	/* Not too many */
	if (amt > obj->number) amt = obj->number;

	/* Take off equipment */
	if (object_is_equipped(player->body, obj))
		inven_takeoff(obj);

	/* Get the object */
	dropped = gear_object_for_use(obj, amt, TRUE);

	/* Describe the dropped object */
	object_desc(o_name, sizeof(o_name), dropped, ODESC_PREFIX | ODESC_FULL);

	/* Message */
	msg("You drop %s (%c).", o_name, label);

	/* Drop it near the player */
	drop_near(cave, dropped, 0, py, px, FALSE);

	event_signal(EVENT_INVENTORY);
	event_signal(EVENT_EQUIPMENT);
}
예제 #5
0
파일: obj-gear.c 프로젝트: tingley/angband
/**
 * Drop (some of) a non-cursed inventory/equipment item "near" the current
 * location
 *
 * There are two cases here - a single object or entire stack is being dropped,
 * or part of a stack is being split off and dropped
 */
void inven_drop(struct object *obj, int amt)
{
	int py = player->py;
	int px = player->px;
	struct object *dropped;

	char o_name[80];

	/* Error check */
	if (amt <= 0)
		return;

	/* This should not happen - ask for report */
	if (!pile_contains(player->gear, obj)) {
		/* Describe the dropped object */
		object_desc(o_name, sizeof(o_name), obj, ODESC_PREFIX | ODESC_FULL);

		msg("Bug - attempt to drop %s when not held!", o_name);
		return;
	}

	/* Not too many */
	if (amt > obj->number) amt = obj->number;

	/* Take off equipment */
	if (object_is_equipped(player->body, obj))
		inven_takeoff(obj);

	/* Get the object */
	dropped = gear_object_for_use(obj, amt, TRUE);

	/* Describe the dropped object */
	object_desc(o_name, sizeof(o_name), dropped, ODESC_PREFIX | ODESC_FULL);

	/* Message */
	msg("You drop %s (%c).", o_name, gear_to_label(obj));

	/* Drop it near the player */
	drop_near(cave, dropped, 0, py, px, FALSE);

	event_signal(EVENT_INVENTORY);
}
예제 #6
0
/**
 * Return TRUE if the given object is on the floor at this grid
 */
bool square_holds_object(struct chunk *c, int y, int x, struct object *obj) {
	return pile_contains(square_object(c, y, x), obj);
}
예제 #7
0
파일: obj-gear.c 프로젝트: fe051/angband
bool object_is_carried(struct player *p, const struct object *obj)
{
	return pile_contains(p->gear, obj);
}
예제 #8
0
/**
 * Drop (some of) a non-cursed inventory/equipment item "near" the current
 * location
 *
 * There are two cases here - a single object or entire stack is being dropped,
 * or part of a stack is being split off and dropped
 */
void inven_drop(struct object *obj, int amt)
{
	int py = player->py;
	int px = player->px;
	struct object *dropped;
	bool none_left = FALSE;
	bool quiver = FALSE;

	char name[80];
	char label;

	/* Error check */
	if (amt <= 0)
		return;

	/* Check it is still held, in case there were two drop commands queued
	 * for this item.  This is in theory not ideal, but in practice should
	 * be safe. */
	if (!pile_contains(player->gear, obj))
		return;

	/* Get where the object is now */
	label = gear_to_label(obj);

	/* Is it in the quiver? */
	if (object_is_in_quiver(player, obj))
		quiver = TRUE;

	/* Not too many */
	if (amt > obj->number) amt = obj->number;

	/* Take off equipment, don't combine */
	if (object_is_equipped(player->body, obj))
		inven_takeoff(obj);

	/* Get the object */
	dropped = gear_object_for_use(obj, amt, FALSE, &none_left);

	/* Describe the dropped object */
	object_desc(name, sizeof(name), dropped, ODESC_PREFIX | ODESC_FULL);

	/* Message */
	msg("You drop %s (%c).", name, label);

	/* Describe what's left */
	if (dropped->artifact) {
		object_desc(name, sizeof(name), dropped,
					ODESC_FULL | ODESC_SINGULAR);
		msg("You no longer have the %s (%c).", name, label);
	} else if (none_left) {
		/* Play silly games to get the right description */
		int number = dropped->number;
		dropped->number = 0;
		object_desc(name, sizeof(name), dropped, ODESC_PREFIX | ODESC_FULL);
		msg("You have %s (%c).", name, label);
		dropped->number = number;
	} else {
		object_desc(name, sizeof(name), obj, ODESC_PREFIX | ODESC_FULL);
		msg("You have %s (%c).", name, label);
	}

	/* Drop it near the player */
	drop_near(cave, dropped, 0, py, px, FALSE);

	/* Sound for quiver objects */
	if (quiver)
		sound(MSG_QUIVER);

	event_signal(EVENT_INVENTORY);
	event_signal(EVENT_EQUIPMENT);
}
예제 #9
0
/**
 * Wield or wear a single item from the pack or floor
 */
void inven_wield(struct object *obj, int slot)
{
	struct object *wielded, *old = player->body.slots[slot].obj;

	const char *fmt;
	char o_name[80];

	/* Increase equipment counter if empty slot */
	if (old == NULL)
		player->upkeep->equip_cnt++;

	/* Take a turn */
	player->upkeep->energy_use = z_info->move_energy;

	/* Split off a new object if necessary */
	if (obj->number > 1) {
		/* Split off a new single object */
		wielded = object_split(obj, 1);

		/* If it's a gear object, give the split item a list entry */
		if (pile_contains(player->gear, obj)) {
			wielded->next = obj->next;
			obj->next = wielded;
			wielded->prev = obj;
			if (wielded->next)
				(wielded->next)->prev = wielded;
		}
	} else
		wielded = obj;

	/* Carry floor items, don't allow combining */
	if (square_holds_object(cave, player->py, player->px, wielded)) {
		square_excise_object(cave, player->py, player->px, wielded);
		inven_carry(player, wielded, FALSE, FALSE);
	}

	/* Wear the new stuff */
	player->body.slots[slot].obj = wielded;

	/* Do any ID-on-wield */
	object_notice_on_wield(wielded);

	/* Where is the item now */
	if (tval_is_melee_weapon(wielded))
		fmt = "You are wielding %s (%c).";
	else if (wielded->tval == TV_BOW)
		fmt = "You are shooting with %s (%c).";
	else if (tval_is_light(wielded))
		fmt = "Your light source is %s (%c).";
	else
		fmt = "You are wearing %s (%c).";

	/* Describe the result */
	object_desc(o_name, sizeof(o_name), wielded, ODESC_PREFIX | ODESC_FULL);

	/* Message */
	msgt(MSG_WIELD, fmt, o_name, I2A(slot));

	/* Cursed! */
	if (cursed_p(wielded->flags)) {
		/* Warn the player */
		msgt(MSG_CURSED, "Oops! It feels deathly cold!");

		/* Sense the object */
		object_notice_curses(wielded);
	}

	/* See if we have to overflow the pack */
	combine_pack();
	pack_overflow(old);

	/* Recalculate bonuses, torch, mana, gear */
	player->upkeep->notice |= (PN_IGNORE);
	player->upkeep->update |= (PU_BONUS | PU_INVEN);
	player->upkeep->redraw |= (PR_INVEN | PR_EQUIP | PR_ARMOR);
	player->upkeep->redraw |= (PR_STATS | PR_HP | PR_MANA | PR_SPEED);

	/* Disable repeats */
	cmd_disable_repeat();
}
예제 #10
0
/**
 * Return true if the given object is on the floor at this grid
 */
bool square_holds_object(struct chunk *c, int y, int x, struct object *obj) {
	assert(square_in_bounds(c, y, x));
	return pile_contains(square_object(c, y, x), obj);
}
예제 #11
0
파일: pile.c 프로젝트: myshkin/angband
NOTEARDOWN

/* Testing the linked list functions in obj-pile.c */
int test_obj_piles(void *state) {
	struct object *pile = NULL;

	struct object *o1 = object_new();
	struct object *o2 = object_new();
	struct object *o3 = object_new();
	struct object *o4 = object_new();

	pile_insert(&pile, o1);
	eq(pile_contains(pile, o1), TRUE);
	eq(pile_contains(pile, o2), FALSE);
	ptreq(pile, o1);
	ptreq(pile_last_item(pile), o1);

	pile_insert_end(&pile, o2);
	eq(pile_contains(pile, o1), TRUE);
	eq(pile_contains(pile, o2), TRUE);
	eq(pile_contains(pile, o3), FALSE);
	ptreq(pile, o1);
	ptreq(pile_last_item(pile), o2);

	pile_insert_end(&pile, o3);
	eq(pile_contains(pile, o1), TRUE);
	eq(pile_contains(pile, o2), TRUE);
	eq(pile_contains(pile, o3), TRUE);
	ptreq(pile, o1);
	ptreq(pile_last_item(pile)->prev, o2);
	ptreq(pile_last_item(pile), o3);

	/* Now let's try excision */

	/* From the top */
	pile_excise(&pile, o1);
	ptreq(pile, o2);
	eq(pile_contains(pile, o1), FALSE);

	/* Now put it back */
	pile_insert(&pile, o1);

	/* From the end */
	pile_excise(&pile, o3);
	ptreq(pile, o1);
	eq(pile_contains(pile, o3), FALSE);
	ptreq(pile_last_item(pile), o2);
	ptreq(pile_last_item(pile)->prev, o1);
	object_delete(o3);

	/* Now put it back, and add another */
	o3 = object_new();
	pile_insert_end(&pile, o3);
	pile_insert_end(&pile, o4);

	/* Try removing from the middle */
	pile_excise(&pile, o3);
	ptreq(pile, o1);

	/* Now the list should look like o1 <-> o2 <-> o4, so check that */
	ptreq(o1->prev, NULL);
	ptreq(o1->next, o2);

	ptreq(o2->prev, o1);
	ptreq(o2->next, o4);

	ptreq(o3->prev, NULL);
	ptreq(o3->next, NULL);

	ptreq(o4->prev, o2);
	ptreq(o4->next, NULL);

	/* Free up */
	object_pile_free(pile);

	ok;
}