Esempio n. 1
0
/*
 * Checks for additional knowledge implied by what the player already knows.
 *
 * \param o_ptr is the object to check
 *
 * returns whether it calls object_notice_everyting
 */
bool object_check_for_ident(object_type *o_ptr)
{
	bitflag flags[OF_SIZE], known_flags[OF_SIZE];
	
	object_flags(o_ptr, flags);
	object_flags_known(o_ptr, known_flags);

	/* Some flags are irrelevant or never learned or too hard to learn */
	flags_clear(flags, OF_SIZE, OF_OBJ_ONLY_MASK, FLAG_END);
	flags_clear(known_flags, OF_SIZE, OF_OBJ_ONLY_MASK, FLAG_END);

	if (!of_is_equal(flags, known_flags)) return FALSE;

	/* If we know attack bonuses, and defence bonuses, and effect, then
	 * we effectively know everything, so mark as such */
	if ((object_attack_plusses_are_visible(o_ptr) || (object_was_sensed(o_ptr) && o_ptr->to_h == 0 && o_ptr->to_d == 0)) &&
	    (object_defence_plusses_are_visible(o_ptr) || (object_was_sensed(o_ptr) && o_ptr->to_a == 0)) &&
	    (object_effect_is_known(o_ptr) || !object_effect(o_ptr)))
	{
		object_notice_everything(o_ptr);
		return TRUE;
	}

	/* We still know all the flags, so we still know if it's an ego */
	else if (ego_item_p(o_ptr))
	{
		/* require worn status so you don't learn launcher of accuracy or gloves of slaying before wield */
		if (object_was_worn(o_ptr))
			object_notice_ego(o_ptr);
	}

	return FALSE;
}
Esempio n. 2
0
/**
 * Describe random powers on ego items
 *
 * \param tb is the description textblock we're building
 * \param ego is the ego type we're analysing
 */
static bool describe_ego(textblock *tb, const struct ego_item *ego)
{
	if (ego && ego->num_randlines) {
		int i, of_type, tot = 0;
		bitflag f[OF_SIZE];

		for (i = 0; i < ego->num_randlines; i++) {
			/* See whether we recognise the flagset for this choice */
			of_type = obj_flag_type(of_next(ego->randmask[i], FLAG_START));
			create_mask(f, FALSE, of_type, OFT_MAX);

			if (of_is_equal(f, ego->randmask[i])) {
				textblock_append(tb, "It provides %s random %s.  ",
					ego->num_randflags[i] > 1 ? "more than one" : "one",
					obj_flagtype_name(of_type));
			} else /* We don't, so count the number for later */
				tot += ego->num_randflags[i];
		}
		if (tot)
			textblock_append(tb, "It provides %s random power.  ",
				tot > 1 ? "more than one" : "one");

		return TRUE;
	}

	return FALSE;
}
Esempio n. 3
0
/**
 * Create a cache of slay combinations found on ego items, and the values of
 * these combinations. This is to speed up slay_power(), which will be called
 * many times for ego items during the game.
 *
 * \param items is the set of ego types from which we are extracting slay
 * combinations
 */
errr create_slay_cache(struct ego_item *items)
{
    int i;
    int j;
    int count = 0;
    bitflag cacheme[OF_SIZE];
    bitflag slay_mask[OF_SIZE];
    bitflag **dupcheck;
    ego_item_type *e_ptr;

    /* Build the slay mask */
	create_mask(slay_mask, FALSE, OFT_SLAY, OFT_KILL, OFT_BRAND, OFT_MAX);

    /* Calculate necessary size of slay_cache */
    dupcheck = C_ZNEW(z_info->e_max, bitflag *);

    for (i = 0; i < z_info->e_max; i++) {
        dupcheck[i] = C_ZNEW(OF_SIZE, bitflag);
        e_ptr = items + i;

        /* Find the slay flags on this ego */
        of_copy(cacheme, e_ptr->flags);
        of_inter(cacheme, slay_mask);

        /* Only consider non-empty combinations of slay flags */
        if (!of_is_empty(cacheme)) {
            /* Skip previously scanned combinations */
            for (j = 0; j < i; j++)
                if (of_is_equal(cacheme, dupcheck[j])) continue;

            /* msg("Found a new slay combo on an ego item"); */
            count++;
            of_copy(dupcheck[i], cacheme);
        }
    }

    /* Allocate slay_cache with an extra empty element for an iteration stop */
    slay_cache = C_ZNEW((count + 1), struct flag_cache);
    count = 0;

    /* Populate the slay_cache */
    for (i = 0; i < z_info->e_max; i++) {
        if (!of_is_empty(dupcheck[i])) {
            of_copy(slay_cache[count].flags, dupcheck[i]);
            slay_cache[count].value = 0;
            count++;
            /*msg("Cached a slay combination");*/
        }
    }

    for (i = 0; i < z_info->e_max; i++)
        FREE(dupcheck[i]);
    FREE(dupcheck);

    /* Success */
    return 0;
}
Esempio n. 4
0
/**
 * Check the slay cache for a combination of slays and return a slay value
 * 
 * \param index is the set of slay flags to look for
 */
s32b check_slay_cache(bitflag *index)
{
	int i;

	for (i = 0; !of_is_empty(slay_cache[i].flags); i++)
		if (of_is_equal(index, slay_cache[i].flags)) break;

	return slay_cache[i].value;
}
Esempio n. 5
0
/**
 * Fill in a value in the slay cache. Return TRUE if a change is made.
 *
 * \param index is the set of slay flags whose value we are adding
 * \param value is the value of the slay flags in index
 */
bool fill_slay_cache(bitflag *index, s32b value)
{
	int i;

	for (i = 0; !of_is_empty(slay_cache[i].flags); i++) {
		if (of_is_equal(index, slay_cache[i].flags)) {
			slay_cache[i].value = value;
			return TRUE;
		}
	}

	return FALSE;
}
Esempio n. 6
0
/**
 * Determine if an item can "absorb" a second item
 *
 * See "object_absorb()" for the actual "absorption" code.
 *
 * If permitted, we allow weapons/armor to stack, if "known".
 *
 * Missiles will combine if both stacks have the same "known" status.
 * This is done to make unidentified stacks of missiles useful.
 *
 * Food, potions, scrolls, and "easy know" items always stack.
 *
 * Chests, and activatable items, except rods, never stack (for various
 * reasons).
 */
bool object_stackable(const struct object *obj1, const struct object *obj2,
					  object_stack_t mode)
{
	int i;

	/* Equipment items don't stack */
	if (object_is_equipped(player->body, obj1))
		return false;
	if (object_is_equipped(player->body, obj2))
		return false;

	/* If either item is unknown, do not stack */
	if (mode & OSTACK_LIST && obj1->kind != obj1->known->kind) return false;
	if (mode & OSTACK_LIST && obj2->kind != obj2->known->kind) return false;

	/* Hack -- identical items cannot be stacked */
	if (obj1 == obj2) return false;

	/* Require identical object kinds */
	if (obj1->kind != obj2->kind) return false;

	/* Different flags don't stack */
	if (!of_is_equal(obj1->flags, obj2->flags)) return false;

	/* Different elements don't stack */
	for (i = 0; i < ELEM_MAX; i++) {
		if (obj1->el_info[i].res_level != obj2->el_info[i].res_level)
			return false;
		if ((obj1->el_info[i].flags & (EL_INFO_HATES | EL_INFO_IGNORE)) !=
			(obj2->el_info[i].flags & (EL_INFO_HATES | EL_INFO_IGNORE)))
			return false;
	}

	/* Artifacts never stack */
	if (obj1->artifact || obj2->artifact) return false;

	/* Analyze the items */
	if (tval_is_chest(obj1)) {
		/* Chests never stack */
		return false;
	}
	else if (tval_is_edible(obj1) || tval_is_potion(obj1) ||
		tval_is_scroll(obj1) || tval_is_rod(obj1)) {
		/* Food, potions, scrolls and rods all stack nicely,
		   since the kinds are identical, either both will be
		   aware or both will be unaware */
	} else if (tval_can_have_charges(obj1) || tval_is_money(obj1)) {
		/* Gold, staves and wands stack most of the time */
		/* Too much gold or too many charges */
		if (obj1->pval + obj2->pval > MAX_PVAL)
			return false;

		/* ... otherwise ok */
	} else if (tval_is_weapon(obj1) || tval_is_armor(obj1) ||
		tval_is_jewelry(obj1) || tval_is_light(obj1)) {
		bool obj1_is_known = object_fully_known((struct object *)obj1);
		bool obj2_is_known = object_fully_known((struct object *)obj2);

		/* Require identical values */
		if (obj1->ac != obj2->ac) return false;
		if (obj1->dd != obj2->dd) return false;
		if (obj1->ds != obj2->ds) return false;

		/* Require identical bonuses */
		if (obj1->to_h != obj2->to_h) return false;
		if (obj1->to_d != obj2->to_d) return false;
		if (obj1->to_a != obj2->to_a) return false;

		/* Require all identical modifiers */
		for (i = 0; i < OBJ_MOD_MAX; i++)
			if (obj1->modifiers[i] != obj2->modifiers[i])
				return (false);

		/* Require identical ego-item types */
		if (obj1->ego != obj2->ego) return false;

		/* Require identical curses */
		if (!curses_are_equal(obj1->curses, obj2->curses)) return false;

		/* Hack - Never stack recharging wearables ... */
		if ((obj1->timeout || obj2->timeout) &&
			!tval_is_light(obj1)) return false;

		/* ... and lights must have same amount of fuel */
		else if ((obj1->timeout != obj2->timeout) &&
				 tval_is_light(obj1)) return false;

		/* Prevent unIDd items stacking with IDd items in the object list */
		if (mode & OSTACK_LIST && (obj1_is_known != obj2_is_known))
			return false;
	} else {
		/* Anything else probably okay */
	}

	/* Require compatible inscriptions */
	if (obj1->note && obj2->note && (obj1->note != obj2->note))
		return false;

	/* They must be similar enough */
	return true;
}
Esempio n. 7
0
/*
 * Calculate the rating for a given slay combination
 */
static s32b slay_power(const object_type *o_ptr, int verbose, ang_file* log_file,
	const bitflag flags[OF_SIZE])
{
	bitflag s_index[OF_SIZE];
	s32b sv = 0;
	int i;
	int mult;
	const slay_t *s_ptr;

	/* Combine the slay bytes into an index value */
	of_copy(s_index, flags);
	flags_mask(s_index, OF_SIZE, OF_ALL_SLAY_MASK, FLAG_END);

	/* Look in the cache to see if we know this one yet */
	for (i = 0; !of_is_empty(slay_cache[i].flags); i++)
	{
		if (of_is_equal(s_index, slay_cache[i].flags))
			break;
	}

	sv = slay_cache[i].value;

	/* If it's cached (or there are no slays), return the value */
	if (sv)
	{
		LOG_PRINT("Slay cache hit\n");
		return sv;
	}

	/*
	 * Otherwise we need to calculate the expected average multiplier
	 * for this combination (multiplied by the total number of
	 * monsters, which we'll divide out later).
	 */
	for (i = 0; i < z_info->r_max; i++)
	{
		monster_race *r_ptr = &r_info[i];
		mult = 1;

		/*
		 * Do the following in ascending order so that the best
		 * multiple is retained
		 */
		for (s_ptr = slay_table; s_ptr->slay_flag; s_ptr++)
		{
			if (!of_has(flags, s_ptr->slay_flag)) continue;

			if (rf_has(r_ptr->flags, s_ptr->monster_flag) ||
			    (s_ptr->resist_flag && !rf_has(r_ptr->flags,
			    s_ptr->resist_flag)))
			{
			    mult = s_ptr->mult;
			}
		}

		/* Add the multiple to sv */
		sv += mult * r_ptr->power;
	}

	/*
	 * To get the expected damage for this weapon, multiply the
	 * average damage from base dice by sv, and divide by the
	 * total number of monsters.
	 */
	if (verbose)
	{
		/* Write info about the slay combination and multiplier */
		file_putf(log_file,"Slay multiplier for:");

		if (of_has(flags, OF_SLAY_EVIL)) file_putf(log_file,"Evl ");
		if (of_has(flags, OF_KILL_DRAGON)) file_putf(log_file,"XDr ");
		if (of_has(flags, OF_KILL_DEMON)) file_putf(log_file,"XDm ");
		if (of_has(flags, OF_KILL_UNDEAD)) file_putf(log_file,"XUn ");
		if (of_has(flags, OF_SLAY_ANIMAL)) file_putf(log_file,"Ani ");
		if (of_has(flags, OF_SLAY_UNDEAD)) file_putf(log_file,"Und ");
		if (of_has(flags, OF_SLAY_DRAGON)) file_putf(log_file,"Drg ");
		if (of_has(flags, OF_SLAY_DEMON)) file_putf(log_file,"Dmn ");
		if (of_has(flags, OF_SLAY_TROLL)) file_putf(log_file,"Tro ");
		if (of_has(flags, OF_SLAY_ORC)) file_putf(log_file,"Orc ");
		if (of_has(flags, OF_SLAY_GIANT)) file_putf(log_file,"Gia ");
		if (of_has(flags, OF_BRAND_ACID)) file_putf(log_file,"Acd ");
		if (of_has(flags, OF_BRAND_ELEC)) file_putf(log_file,"Elc ");
		if (of_has(flags, OF_BRAND_FIRE)) file_putf(log_file,"Fir ");
		if (of_has(flags, OF_BRAND_COLD)) file_putf(log_file,"Cld ");
		if (of_has(flags, OF_BRAND_POIS)) file_putf(log_file,"Poi ");

		file_putf(log_file,"sv is: %d\n", sv);
		file_putf(log_file," and t_m_p is: %d \n", tot_mon_power);

		file_putf(log_file,"times 1000 is: %d\n", (1000 * sv) / tot_mon_power);
	}

	/* Add to the cache */
	for (i = 0; !of_is_empty(slay_cache[i].flags); i++)
	{
		if (of_is_equal(s_index, slay_cache[i].flags))
		{
			slay_cache[i].value = sv;
			LOG_PRINT("Added to slay cache\n");
			break;
		}
	}

	return sv;
}