Example #1
0
/**
 * Find a grid near the given one for an object to fall on
 *
 * We check several locations to see if we can find a location at which
 * the object can combine, stack, or be placed.  Artifacts will try very
 * hard to be placed, including "teleporting" to a useful grid if needed.
 *
 * If no appropriate grid is found, the given grid is unchanged
 */
static void drop_find_grid(struct object *drop, int *y, int *x)
{
	int best_score = -1;
	int best_y = *y;
	int best_x = *x;
	int i, dy, dx;
	struct object *obj;

	/* Scan local grids */
	for (dy = -3; dy <= 3; dy++) {
		for (dx = -3; dx <= 3; dx++) {
			bool combine = false;
			int dist = (dy * dy) + (dx * dx);
			int ty = *y + dy;
			int tx = *x + dx;
			int num_shown = 0;
			int num_ignored = 0;
			int score;

			/* Lots of reasons to say no */
			if ((dist > 10) ||
				!square_in_bounds_fully(cave, ty, tx) ||
				!los(cave, *y, *x, ty, tx) ||
				!square_isfloor(cave, ty, tx) ||
				square_isplayertrap(cave, ty, tx) ||
				square_iswarded(cave, ty, tx))
				continue;

			/* Analyse the grid for carrying the new object */
			for (obj = square_object(cave, ty, tx); obj; obj = obj->next) {
				/* Check for possible combination */
				if (object_similar(obj, drop, OSTACK_FLOOR))
					combine = true;

				/* Count objects */
				if (!ignore_item_ok(obj))
					num_shown++;
				else
					num_ignored++;
			}
			if (!combine)
				num_shown++;

			/* Disallow if the stack size is too big */
			if ((OPT(player, birth_stacking) && (num_shown > 1)) ||
				((num_shown + num_ignored) > z_info->floor_size &&
				 !floor_get_oldest_ignored(ty, tx)))
				continue;

			/* Score the location based on how close and how full the grid is */
			score = 1000 - (dist + num_shown * 5);

			if ((score < best_score) || ((score == best_score) && one_in_(2)))
				continue;

			best_score = score;
			best_y = ty;
			best_x = tx;
		}
	}

	/* Return if we have a score, otherwise fail or try harder for artifacts */
	if (best_score >= 0) {
		*y = best_y;
		*x = best_x;
		return;
	} else if (!drop->artifact) {
		return;
	}
	for (i = 0; i < 2000; i++) {
		/* Start bouncing from grid to grid, stopping if we find an empty one */
		if (i < 1000) {
			best_y = rand_spread(best_y, 1);
			best_x = rand_spread(best_x, 1);
		} else {
			/* Now go to purely random locations */
			best_y = randint0(cave->height);
			best_x = randint0(cave->width);
		}
		if (square_canputitem(cave, best_y, best_x)) {
			*y = best_y;
			*x = best_x;
			return;
		}
	}
}
Example #2
0
/**
 * Place random stairs at (x, y).
 * \param c current chunk
 * \param y co-ordinates
 * \param x co-ordinates
 */
void place_random_stairs(struct chunk *c, int y, int x)
{
    int feat = randint0(100) < 50 ? FEAT_LESS : FEAT_MORE;
    if (square_canputitem(c, y, x))
		place_stairs(c, y, x, feat);
}
Example #3
0
/**
 * Let an object fall to the ground at or near a location.
 *
 * The initial location is assumed to be "square_in_bounds_fully(cave, )".
 *
 * This function takes a parameter "chance".  This is the percentage
 * chance that the item will "disappear" instead of drop.  If the object
 * has been thrown, then this is the chance of disappearance on contact.
 *
 * This function will produce a description of a drop event under the player
 * when "verbose" is true.
 *
 * We check several locations to see if we can find a location at which
 * the object can combine, stack, or be placed.  Artifacts will try very
 * hard to be placed, including "teleporting" to a useful grid if needed.
 *
 * Objects which fail to be carried by the floor are deleted.  This function
 * attempts to add successfully dropped objects to, and to remove failures
 * from, the object list (as dropped items may or may not be already listed).
 */
void drop_near(struct chunk *c, struct object *dropped, int chance, int y,
			   int x, bool verbose)
{
	int i, k, n, d, s;

	int bs, bn;
	int by, bx;
	int dy, dx;
	int ty, tx;

	struct object *obj;

	char o_name[80];

	bool flag = false;

	/* Only called in the current level */
	assert(c == cave);

	/* Describe object */
	object_desc(o_name, sizeof(o_name), dropped, ODESC_BASE);

	/* Handle normal "breakage" */
	if (!dropped->artifact && (randint0(100) < chance)) {
		/* Message */
		msg("The %s %s.", o_name,
			VERB_AGREEMENT(dropped->number, "breaks", "break"));

		/* Failure */
		if (dropped->known) {
			delist_object(cave_k, dropped->known);
			object_delete(&dropped->known);
		}
		delist_object(c, dropped);
		object_delete(&dropped);
		return;
	}

	/* Score */
	bs = -1;

	/* Picker */
	bn = 0;

	/* Default */
	by = y;
	bx = x;

	/* Scan local grids */
	for (dy = -3; dy <= 3; dy++) {
		for (dx = -3; dx <= 3; dx++) {
			bool comb = false;

			/* Calculate actual distance */
			d = (dy * dy) + (dx * dx);

			/* Ignore distant grids */
			if (d > 10) continue;

			/* Location */
			ty = y + dy;
			tx = x + dx;

			/* Skip illegal grids */
			if (!square_in_bounds_fully(c, ty, tx)) continue;

			/* Require line of sight */
			if (!los(c, y, x, ty, tx)) continue;

			/* Require floor space */
			if (!square_isfloor(c, ty, tx)) continue;

			/* Require no trap or rune */
			if (square_isplayertrap(c, ty, tx) ||
				square_iswarded(c, ty, tx))
				continue;

			/* No objects */
			k = 0;
			n = 0;

			/* Scan objects in that grid */
			for (obj = square_object(c, ty, tx); obj; obj = obj->next) {
				/* Check for possible combination */
				if (object_similar(obj, dropped, OSTACK_FLOOR))
					comb = true;

				/* Count objects */
				if (!ignore_item_ok(obj))
					k++;
				else
					n++;
			}

			/* Add new object */
			if (!comb) k++;

			/* Option -- disallow stacking */
			if (OPT(birth_no_stacking) && (k > 1)) continue;

			/* Paranoia? */
			if ((k + n) > z_info->floor_size &&
				!floor_get_oldest_ignored(ty, tx)) continue;

			/* Calculate score */
			s = 1000 - (d + k * 5);

			/* Skip bad values */
			if (s < bs) continue;

			/* New best value */
			if (s > bs) bn = 0;

			/* Apply the randomizer to equivalent values */
			if ((++bn >= 2) && (randint0(bn) != 0)) continue;

			/* Keep score */
			bs = s;

			/* Track it */
			by = ty;
			bx = tx;

			/* Okay */
			flag = true;
		}
	}

	/* Handle lack of space */
	if (!flag && !dropped->artifact) {
		/* Message */
		msg("The %s %s.", o_name,
			VERB_AGREEMENT(dropped->number, "disappears", "disappear"));

		/* Debug */
		if (player->wizard) msg("Breakage (no floor space).");

		/* Failure */
		if (dropped->known) {
			delist_object(cave_k, dropped->known);
			object_delete(&dropped->known);
		}
		delist_object(c, dropped);
		object_delete(&dropped);
		return;
	}

	/* Find a grid */
	for (i = 0; !flag; i++) {
		/* Bounce around */
		if (i < 1000) {
			ty = rand_spread(by, 1);
			tx = rand_spread(bx, 1);
		} else {
			/* Random locations */
			ty = randint0(c->height);
			tx = randint0(c->width);
		}

		/* Require floor space */
		if (!square_canputitem(c, ty, tx)) continue;

		/* Bounce to that location */
		by = ty;
		bx = tx;

		/* Okay */
		flag = true;
	}

	/* Give it to the floor */
	if (!floor_carry(c, by, bx, dropped, false)) {
		/* Message */
		msg("The %s %s.", o_name,
			VERB_AGREEMENT(dropped->number, "disappears", "disappear"));

		/* Debug */
		if (player->wizard) msg("Breakage (too many objects).");

		if (dropped->artifact) dropped->artifact->created = false;

		/* Failure */
		if (dropped->known) {
			delist_object(cave_k, dropped->known);
			object_delete(&dropped->known);
		}
		delist_object(c, dropped);
		object_delete(&dropped);
		return;
	}

	/* Sound */
	sound(MSG_DROP);

	/* Message when an object falls under the player */
	if (verbose && (c->squares[by][bx].mon < 0))
		/* Check the item still exists and isn't ignored */
		if (c->objects[dropped->oidx] && !ignore_item_ok(dropped))
			msg("You feel something roll beneath your feet.");
}