示例#1
0
AIInfo *AIScannerInfo::SelectRandomAI() const
{
	uint num_random_ais = 0;
	for (ScriptInfoList::const_iterator it = this->info_single_list.begin(); it != this->info_single_list.end(); it++) {
		AIInfo *i = static_cast<AIInfo *>((*it).second);
		if (i->UseAsRandomAI()) num_random_ais++;
	}

	if (num_random_ais == 0) {
		DEBUG(script, 0, "No suitable AI found, loading 'dummy' AI.");
		return this->info_dummy;
	}

	/* Find a random AI */
	uint pos;
	if (_networking) {
		pos = InteractiveRandomRange(num_random_ais);
	} else {
		pos = RandomRange(num_random_ais);
	}

	/* Find the Nth item from the array */
	ScriptInfoList::const_iterator it = this->info_single_list.begin();

#define GetAIInfo(it) static_cast<AIInfo *>((*it).second)
	while (!GetAIInfo(it)->UseAsRandomAI()) it++;
	for (; pos > 0; pos--) {
		it++;
		while (!GetAIInfo(it)->UseAsRandomAI()) it++;
	}
	return GetAIInfo(it);
#undef GetAIInfo
}
void ScriptConfig::AddRandomDeviation()
{
	for (ScriptConfigItemList::const_iterator it = this->GetConfigList()->begin(); it != this->GetConfigList()->end(); it++) {
		if ((*it).random_deviation != 0) {
			this->SetSetting((*it).name, InteractiveRandomRange((*it).random_deviation * 2) - (*it).random_deviation + this->GetSetting((*it).name));
		}
	}
}
void ScriptConfig::Change(const char *name, int version, bool force_exact_match, bool is_random)
{
	free(this->name);
	this->name = (name == NULL) ? NULL : strdup(name);
	this->info = (name == NULL) ? NULL : this->FindInfo(this->name, version, force_exact_match);
	this->version = (info == NULL) ? -1 : info->GetVersion();
	this->is_random = is_random;
	if (this->config_list != NULL) delete this->config_list;
	this->config_list = (info == NULL) ? NULL : new ScriptConfigItemList();
	if (this->config_list != NULL) this->PushExtraConfigList();

	this->ClearConfigList();

	if (_game_mode == GM_NORMAL && this->info != NULL) {
		/* If we're in an existing game and the Script is changed, set all settings
		 *  for the Script that have the random flag to a random value. */
		for (ScriptConfigItemList::const_iterator it = this->info->GetConfigList()->begin(); it != this->info->GetConfigList()->end(); it++) {
			if ((*it).flags & SCRIPTCONFIG_RANDOM) {
				this->SetSetting((*it).name, InteractiveRandomRange((*it).max_value - (*it).min_value) + (*it).min_value);
			}
		}
		this->AddRandomDeviation();
	}
}
void AIScanner::RegisterLibrary(AILibrary *library)
{
	char library_name[1024];
	snprintf(library_name, sizeof(library_name), "%s.%s.%d", library->GetCategory(), library->GetInstanceName(), library->GetVersion());
	strtolower(library_name);

	if (this->library_list.find(library_name) != this->library_list.end()) {
		/* This AI was already registered */
#ifdef WIN32
		/* Windows doesn't care about the case */
		if (strcasecmp(this->library_list[library_name]->GetMainScript(), library->GetMainScript()) == 0) {
#else
		if (strcmp(this->library_list[library_name]->GetMainScript(), library->GetMainScript()) == 0) {
#endif
			delete library;
			return;
		}

		DEBUG(ai, 1, "Registering two libraries with the same name and version");
		DEBUG(ai, 1, "  1: %s", this->library_list[library_name]->GetMainScript());
		DEBUG(ai, 1, "  2: %s", library->GetMainScript());
		DEBUG(ai, 1, "The first is taking precedence.");

		delete library;
		return;
	}

	this->library_list[strdup(library_name)] = library;
}

void AIScanner::RegisterAI(AIInfo *info)
{
	char ai_name[1024];
	snprintf(ai_name, sizeof(ai_name), "%s.%d", info->GetName(), info->GetVersion());
	strtolower(ai_name);

	/* Check if GetShortName follows the rules */
	if (strlen(info->GetShortName()) != 4) {
		DEBUG(ai, 0, "The AI '%s' returned a string from GetShortName() which is not four characaters. Unable to load the AI.", info->GetName());
		delete info;
		return;
	}

	if (this->info_list.find(ai_name) != this->info_list.end()) {
		/* This AI was already registered */
#ifdef WIN32
		/* Windows doesn't care about the case */
		if (strcasecmp(this->info_list[ai_name]->GetMainScript(), info->GetMainScript()) == 0) {
#else
		if (strcmp(this->info_list[ai_name]->GetMainScript(), info->GetMainScript()) == 0) {
#endif
			delete info;
			return;
		}

		DEBUG(ai, 1, "Registering two AIs with the same name and version");
		DEBUG(ai, 1, "  1: %s", this->info_list[ai_name]->GetMainScript());
		DEBUG(ai, 1, "  2: %s", info->GetMainScript());
		DEBUG(ai, 1, "The first is taking precedence.");

		delete info;
		return;
	}

	this->info_list[strdup(ai_name)] = info;

	/* Add the AI to the 'unique' AI list, where only the highest version of the
	 *  AI is registered. */
	snprintf(ai_name, sizeof(ai_name), "%s", info->GetName());
	strtolower(ai_name);
	if (this->info_single_list.find(ai_name) == this->info_single_list.end()) {
		this->info_single_list[strdup(ai_name)] = info;
	} else if (this->info_single_list[ai_name]->GetVersion() < info->GetVersion()) {
		this->info_single_list[ai_name] = info;
	}
}

AIInfo *AIScanner::SelectRandomAI() const
{
	uint num_random_ais = 0;
	for (AIInfoList::const_iterator it = this->info_single_list.begin(); it != this->info_single_list.end(); it++) {
		if (it->second->UseAsRandomAI()) num_random_ais++;
	}

	if (num_random_ais == 0) {
		DEBUG(ai, 0, "No suitable AI found, loading 'dummy' AI.");
		return this->info_dummy;
	}

	/* Find a random AI */
	uint pos;
	if (_networking) {
		pos = InteractiveRandomRange(num_random_ais);
	} else {
		pos = RandomRange(num_random_ais);
	}

	/* Find the Nth item from the array */
	AIInfoList::const_iterator it = this->info_single_list.begin();
	while (!it->second->UseAsRandomAI()) it++;
	for (; pos > 0; pos--) {
		it++;
		while (!it->second->UseAsRandomAI()) it++;
	}
	return (*it).second;
}