Beispiel #1
0
battle_context::battle_context(const unit_map& units,
		const map_location& attacker_loc, const map_location& defender_loc,
		int attacker_weapon, int defender_weapon, double aggression,
		const combatant *prev_def, const unit* attacker_ptr) :
	attacker_stats_(nullptr), defender_stats_(nullptr), attacker_combatant_(nullptr),
	defender_combatant_(nullptr)
{
	const unit &attacker = attacker_ptr ? *attacker_ptr : *units.find(attacker_loc);
	const unit &defender = *units.find(defender_loc);
	const double harm_weight = 1.0 - aggression;

	if (attacker_weapon == -1 && attacker.attacks().size() == 1 && attacker.attacks()[0].attack_weight() > 0 )
		attacker_weapon = 0;

	if (attacker_weapon == -1) {
		attacker_weapon = choose_attacker_weapon(attacker, defender, units,
			attacker_loc, defender_loc,
				harm_weight, &defender_weapon, prev_def);
	} else if (defender_weapon == -1) {
		defender_weapon = choose_defender_weapon(attacker, defender, attacker_weapon,
			units, attacker_loc, defender_loc, prev_def);
	}

	// If those didn't have to generate statistics, do so now.
	if (!attacker_stats_) {
		const attack_type *adef = nullptr;
		const attack_type *ddef = nullptr;
		if (attacker_weapon >= 0) {
			VALIDATE(attacker_weapon < static_cast<int>(attacker.attacks().size()),
					_("An invalid attacker weapon got selected."));
			adef = &attacker.attacks()[attacker_weapon];
		}
		if (defender_weapon >= 0) {
			VALIDATE(defender_weapon < static_cast<int>(defender.attacks().size()),
					_("An invalid defender weapon got selected."));
			ddef = &defender.attacks()[defender_weapon];
		}
		assert(!defender_stats_ && !attacker_combatant_ && !defender_combatant_);
		attacker_stats_ = new battle_context_unit_stats(attacker, attacker_loc, attacker_weapon,
				true, defender, defender_loc, ddef, units);
		defender_stats_ = new battle_context_unit_stats(defender, defender_loc, defender_weapon, false,
				attacker, attacker_loc, adef, units);
	}

	// There have been various bugs where only one of these was set
	assert(attacker_stats_);
	assert(defender_stats_);
}
Beispiel #2
0
int battle_context::choose_attacker_weapon(const unit &attacker,
		const unit &defender, const unit_map& units,
		const map_location& attacker_loc, const map_location& defender_loc,
		double harm_weight, int *defender_weapon, const combatant *prev_def)
{
	std::vector<unsigned int> choices;

	// What options does attacker have?
	unsigned int i;
	for (i = 0; i < attacker.attacks().size(); ++i) {
		const attack_type &att = attacker.attacks()[i];
		if (att.attack_weight() > 0) {
			choices.push_back(i);
		}
	}
	if (choices.empty())
		return -1;
	if (choices.size() == 1) {
		*defender_weapon = choose_defender_weapon(attacker, defender, choices[0], units,
			attacker_loc, defender_loc, prev_def);
		return choices[0];
	}

	// Multiple options: simulate them, save best.
	battle_context_unit_stats *best_att_stats = NULL, *best_def_stats = NULL;
	combatant *best_att_comb = NULL, *best_def_comb = NULL;

	for (i = 0; i < choices.size(); ++i) {
		const attack_type &att = attacker.attacks()[choices[i]];
		int def_weapon = choose_defender_weapon(attacker, defender, choices[i], units,
			attacker_loc, defender_loc, prev_def);
		// If that didn't simulate, do so now.
		if (!attacker_combatant_) {
			const attack_type *def = NULL;
			if (def_weapon >= 0) {
				def = &defender.attacks()[def_weapon];
			}
			attacker_stats_ = new battle_context_unit_stats(attacker, attacker_loc, choices[i],
				true, defender, defender_loc, def, units);
			defender_stats_ = new battle_context_unit_stats(defender, defender_loc, def_weapon, false,
				attacker, attacker_loc, &att, units);
			attacker_combatant_ = new combatant(*attacker_stats_);
			defender_combatant_ = new combatant(*defender_stats_, prev_def);
			attacker_combatant_->fight(*defender_combatant_);
		}
		if (!best_att_comb || better_combat(*attacker_combatant_, *defender_combatant_,
					*best_att_comb, *best_def_comb, harm_weight)) {
			delete best_att_comb;
			delete best_def_comb;
			delete best_att_stats;
			delete best_def_stats;
			best_att_comb = attacker_combatant_;
			best_def_comb = defender_combatant_;
			best_att_stats = attacker_stats_;
			best_def_stats = defender_stats_;
		} else {
			delete attacker_combatant_;
			delete defender_combatant_;
			delete attacker_stats_;
			delete defender_stats_;
		}
		attacker_combatant_ = NULL;
		defender_combatant_ = NULL;
		attacker_stats_ = NULL;
		defender_stats_ = NULL;
	}

	attacker_combatant_ = best_att_comb;
	defender_combatant_ = best_def_comb;
	attacker_stats_ = best_att_stats;
	defender_stats_ = best_def_stats;

	*defender_weapon = defender_stats_->attack_num;
	return attacker_stats_->attack_num;
}
Beispiel #3
0
int battle_context::choose_attacker_weapon(const unit& attacker,
		const unit& defender,
		const unit_map& units,
		const map_location& attacker_loc,
		const map_location& defender_loc,
		double harm_weight,
		int* defender_weapon,
		const combatant* prev_def)
{
	std::vector<unsigned int> choices;

	// What options does attacker have?
	unsigned int i;

	for(i = 0; i < attacker.attacks().size(); ++i) {
		const attack_type& att = attacker.attacks()[i];

		if(att.attack_weight() > 0) {
			choices.push_back(i);
		}
	}

	if(choices.empty()) {
		return -1;
	}

	if(choices.size() == 1) {
		*defender_weapon
				= choose_defender_weapon(attacker, defender, choices[0], units, attacker_loc, defender_loc, prev_def);
		const_attack_ptr def_weapon
				= *defender_weapon >= 0 ? defender.attacks()[*defender_weapon].shared_from_this() : nullptr;
		attacker_stats_.reset(new battle_context_unit_stats(
				attacker, attacker_loc, choices[0], true, defender, defender_loc, def_weapon, units));

		if(attacker_stats_->disable) {
			return -1;
		}

		const attack_type& att = attacker.attacks()[choices[0]];
		defender_stats_.reset(new battle_context_unit_stats(
				defender, defender_loc, *defender_weapon, false, attacker, attacker_loc, att.shared_from_this(), units));

		return choices[0];
	}

	// Multiple options: simulate them, save best.
	std::unique_ptr<battle_context_unit_stats> best_att_stats(nullptr);
	std::unique_ptr<battle_context_unit_stats> best_def_stats(nullptr);

	std::unique_ptr<combatant> best_att_comb(nullptr);
	std::unique_ptr<combatant> best_def_comb(nullptr);

	for(i = 0; i < choices.size(); ++i) {
		const attack_type& att = attacker.attacks()[choices[i]];

		int def_weapon =
			choose_defender_weapon(attacker, defender, choices[i], units, attacker_loc, defender_loc, prev_def);

		// If that didn't simulate, do so now.
		if(!attacker_combatant_) {
			const_attack_ptr def = nullptr;

			if(def_weapon >= 0) {
				def = defender.attacks()[def_weapon].shared_from_this();
			}

			attacker_stats_.reset(new battle_context_unit_stats(
					attacker, attacker_loc, choices[i], true, defender, defender_loc, def, units));

			if(attacker_stats_->disable) {
				continue;
			}

			defender_stats_.reset(new battle_context_unit_stats(
					defender, defender_loc, def_weapon, false, attacker, attacker_loc, att.shared_from_this(), units));

			attacker_combatant_.reset(new combatant(*attacker_stats_));
			defender_combatant_.reset(new combatant(*defender_stats_, prev_def));

			attacker_combatant_->fight(*defender_combatant_);
		} else {
			if(attacker_stats_ != nullptr && attacker_stats_->disable) {
				continue;
			}
		}

		if(!best_att_comb ||
			better_combat(*attacker_combatant_, *defender_combatant_, *best_att_comb, *best_def_comb, harm_weight)
		) {
			best_att_comb = std::move(attacker_combatant_);
			best_def_comb = std::move(defender_combatant_);
			best_att_stats = std::move(attacker_stats_);
			best_def_stats = std::move(defender_stats_);
		}

		attacker_combatant_.reset();
		defender_combatant_.reset();
		attacker_stats_.reset();
		defender_stats_.reset();
	}

	attacker_combatant_ = std::move(best_att_comb);
	defender_combatant_ = std::move(best_def_comb);
	attacker_stats_ = std::move(best_att_stats);
	defender_stats_ = std::move(best_def_stats);

	// These currently mean the same thing, but assumptions like that have been broken before
	if(!defender_stats_ || !attacker_stats_) {
		return -1;
	}

	*defender_weapon = defender_stats_->attack_num;
	return attacker_stats_->attack_num;
}