optional new-style AI configs...

...and generation of AI lists in multiplayer from files
This commit is contained in:
Iurii Chernyi 2009-06-28 13:01:41 +00:00
parent a07832cf93
commit 5652b111c0
14 changed files with 246 additions and 53 deletions

View file

@ -10,6 +10,13 @@
{campaigns/}
[ais]
{ai/ais/}
#ifdef DEBUG_MODE
{ai/dev/}
#endif
[/ais]
#ifdef EDITOR
[textdomain]
name="wesnoth-editor"

View file

@ -1,5 +1,6 @@
#textdomain wesnoth
ai_algorithm=default
ai_algorithm=default_ai
[ai]
ai_identifier=default_ai_stable
id=default
description=Default AI
[/ai]

View file

@ -1,5 +0,0 @@
#textdomain wesnoth
ai_algorithm=formula_ai
[ai]
ai_identifier=formula_ai_stable
[/ai]

View file

@ -0,0 +1,10 @@
#textdomain wesnoth
[ai]
id=formula_ai_stable
description=Formula AI
[stage]
engine=cpp
name=testing_ai_default::fallback
fallback=formula_ai
[/stage]
[/ai]

View file

@ -1,8 +1,14 @@
#textdomain wesnoth
ai_algorithm =formula_ai
[ai]
ai_algorithm =formula_ai
id=formula_ai_poisoning
description=Formula AI with poisoning formula
[stage]
engine=cpp
name=testing_ai_default::fallback
fallback=formula_ai
[/stage]
eval_list=yes
[register_candidate_action]
name=poisoner
type=attack

View file

@ -1,2 +1,10 @@
#textdomain wesnoth
ai_algorithm=idle_ai
[ai]
id=ai_idle
description=Idle AI
[stage]
engine=cpp
name=testing_ai_default::fallback
fallback=idle_ai
[/stage]
[/ai]

View file

@ -1,7 +1,7 @@
#textdomain wesnoth
ai_algorithm=composite_ai
[ai]
ai_identifier=testing_ai_default
id=testing_ai_default
description=RCA AI
[stage]
engine=cpp
name=testing_ai_default::candidate_action_evaluation_loop

View file

@ -35,6 +35,55 @@ static lg::log_domain log_ai_configuration("ai/config");
#define WRN_AI_CONFIGURATION LOG_STREAM(warn, log_ai_configuration)
#define ERR_AI_CONFIGURATION LOG_STREAM(err, log_ai_configuration)
void configuration::init(const config &game_config)
{
ai_configurations_.clear();
const config &ais = game_config.child("ais");
foreach (const config &ai_configuration, ais.child_range("ai")) {
const std::string &id = ai_configuration["id"];
if (id.empty()){
ERR_AI_CONFIGURATION << "skipped AI config due to missing id" << ". Config contains:"<< std::endl << ai_configuration << std::endl;
continue;
}
if (ai_configurations_.count(id)>0){
ERR_AI_CONFIGURATION << "skipped AI config due to duplicate id [" << id << "]. Config contains:"<< std::endl << ai_configuration << std::endl;
continue;
}
description desc;
desc.id=id;
desc.description=ai_configuration["description"];
desc.cfg=ai_configuration;
ai_configurations_.insert(std::make_pair(id,desc));
LOG_AI_CONFIGURATION << "loaded AI config: " << ai_configuration["description"] << std::endl;
}
}
std::vector<description*> configuration::get_available_ais(){
std::vector<description*> ais_list;
for(description_map::iterator desc = ai_configurations_.begin(); desc!=ai_configurations_.end(); ++desc) {
ais_list.push_back(&desc->second);
DBG_AI_CONFIGURATION << "has ai with config: "<< std::endl << desc->second.cfg<< std::endl;
}
return ais_list;
}
const config& configuration::get_ai_config_for(const std::string &id)
{
description_map::iterator cfg_it = ai_configurations_.find(id);
if (cfg_it==ai_configurations_.end()){
return default_config_;
}
return cfg_it->second.cfg;
}
configuration::description_map configuration::ai_configurations_ = configuration::description_map();
config configuration::default_config_ = config();
static std::string bind_config_parameter( const std::string& value_from_config,
const std::string& value_from_global_config,
@ -49,16 +98,16 @@ static std::string bind_config_parameter( const std::string& value_from_config,
}
bool configuration::get_side_config_from_file(const std::string& file, config& cfg ){
try {
scoped_istream stream = preprocess_file(get_wml_location(file));
read(cfg, *stream);
LOG_AI_CONFIGURATION << "Reading AI configuration from file '" << file << "'" << std::endl;
} catch(config::error &) {
ERR_AI_CONFIGURATION << "Error while reading AI configuration from file '" << file << "'" << std::endl;
return false;
}
LOG_AI_CONFIGURATION << "Successfully read AI configuration from file '" << file << "'" << std::endl;
return true;
try {
scoped_istream stream = preprocess_file(get_wml_location(file));
read(cfg, *stream);
LOG_AI_CONFIGURATION << "Reading AI configuration from file '" << file << "'" << std::endl;
} catch(config::error &) {
ERR_AI_CONFIGURATION << "Error while reading AI configuration from file '" << file << "'" << std::endl;
return false;
}
LOG_AI_CONFIGURATION << "Successfully read AI configuration from file '" << file << "'" << std::endl;
return true;
}
@ -73,6 +122,71 @@ bool configuration::parse_side_config(const config& cfg,
LOG_AI_CONFIGURATION << "Parsing [side] configuration from config" << std::endl;
DBG_AI_CONFIGURATION << "Config contains:"<< std::endl << cfg << std::endl;
bool new_syntax=false;//@todo 1.8 remove old way when necessary
foreach (const config &aiparam, cfg.child_range("ai")) {
if (aiparam.child("stage")){
new_syntax=true;
break;
}
}
if (new_syntax) {
DBG_AI_CONFIGURATION << "new syntax parsing rules"<< std::endl;
return parse_side_config_new(cfg,ai_algorithm_type,global_ai_parameters,ai_parameters,default_ai_parameters,ai_memory,effective_ai_parameters);
} else {
DBG_AI_CONFIGURATION << "old syntax parsing rules"<< std::endl;
return parse_side_config_old(cfg,ai_algorithm_type,global_ai_parameters,ai_parameters,default_ai_parameters,ai_memory,effective_ai_parameters);
}
}
bool configuration::parse_side_config_new(const config &cfg,
std::string &ai_algorithm_type,
config &global_ai_parameters,
std::vector<config> &ai_parameters,
const config &default_ai_parameters,
config &ai_memory,
config &effective_ai_parameters )
{
//construct new-style integrated config
ai_parameters.push_back(default_ai_parameters);
global_ai_parameters.append(default_ai_parameters);
global_ai_parameters["ai_algorithm"] = "composite_ai";
DBG_AI_CONFIGURATION << "after taking default values into account, new-style config contains:"<< std::endl << global_ai_parameters << std::endl;
foreach (const config &aiparam, cfg.child_range("ai"))
{
ai_parameters.push_back(aiparam);
global_ai_parameters.append(aiparam);
}
DBG_AI_CONFIGURATION << "finally, new-style config contains:"<< std::endl << global_ai_parameters << std::endl;
ai_algorithm_type = global_ai_parameters["ai_algorithm"];
//AI memory
foreach (const config &aimem, global_ai_parameters.child_range("ai_memory")) {
ai_memory.append(aimem);
}
effective_ai_parameters["number_of_possible_recruits_to_force_recruit"]= global_ai_parameters["number_of_possible_recruits_to_force_recruit"];
effective_ai_parameters["villages_per_scout"] = global_ai_parameters["villages_per_scout"];
effective_ai_parameters["leader_value"] = global_ai_parameters["leader_value"];
effective_ai_parameters["village_value"] = global_ai_parameters["village_value"];
effective_ai_parameters["aggression"] = global_ai_parameters["aggression"];
effective_ai_parameters["caution"] = global_ai_parameters["caution"];
return true;
}
bool configuration::parse_side_config_old(const config& cfg,
std::string& ai_algorithm_type,
config& global_ai_parameters,
std::vector<config>& ai_parameters,
const config& default_ai_parameters,
config& ai_memory,
config& effective_ai_parameters )
{
foreach (const config &aiparam, cfg.child_range("ai"))
{
ai_parameters.push_back(aiparam);
@ -139,7 +253,7 @@ const config& configuration::get_default_ai_parameters(){
default_cfg["init"] = "true";
default_cfg["al_algorithm"] = "default";
default_cfg["ai_algorithm"] = "default_ai";
//A number 0 or higher which determines how many scouts the AI recruits. If 0,
//the AI doesn't recruit scouts to capture villages.

View file

@ -25,6 +25,7 @@
#include "../config.hpp"
#include <map>
#include <vector>
namespace ai {
@ -46,9 +47,37 @@ namespace ai {
* then, if (3) is equal:
* use any and loudly complain.
*/
struct description {
public:
std::string description;
std::string id;
config cfg;
};
class configuration {
public:
/**
* Init the parameters of ai configuration parser
* @param game_config_ game config
*/
static void init(const config &game_config);
/**
* Return the config for a specified ai
*/
static const config& get_ai_config_for(const std::string &id);
/**
* Returns a list of available AIs.
* @return the list of available AIs.
*/
static std::vector<description*> get_available_ais();
/**
* get side config from file
* @param file the file name to open. follows usual WML convention.
@ -81,12 +110,41 @@ public:
config& ai_memory,
config& effective_ai_parameters );
/**
* Same as parse_side_config, new syntax
*/
static bool parse_side_config_new(const config& cfg,
std::string& ai_algorithm_type,
config& global_ai_parameters,
std::vector<config>& ai_parameters,
const config& default_ai_parameters,
config& ai_memory,
config& effective_ai_parameters );
/**
* Same as parse_side_config, old syntax
*/
static bool parse_side_config_old(const config& cfg,
std::string& ai_algorithm_type,
config& global_ai_parameters,
std::vector<config>& ai_parameters,
const config& default_ai_parameters,
config& ai_memory,
config& effective_ai_parameters );
/**
* get default AI parameters
* @return default AI parameters
*/
static const config& get_default_ai_parameters();
private:
typedef std::map<std::string, description> description_map;
static std::map<std::string, description> ai_configurations_;
static config default_config_;
};
} //end of namespace ai

View file

@ -565,15 +565,6 @@ ai_ptr manager::create_transient_ai( const std::string &ai_algorithm_type, defau
return new_ai;
}
std::vector<std::string> manager::get_available_ais()
{
std::vector<std::string> ais;
ais.push_back("default");
return ais;
}
// =======================================================================
// REMOVE

View file

@ -279,14 +279,6 @@ public:
static ai_ptr create_transient_ai( const std::string& ai_algorithm_type, default_ai_context *ai_context);
/**
* Returns a list of available AIs.
* @return the list of available AIs.
* @todo 1.7 get this list from a list of files in specified directory
*/
static std::vector<std::string> get_available_ais();
// =======================================================================
// REMOVE
// =======================================================================

View file

@ -18,6 +18,7 @@
#include "SDL_mixer.h"
#include "about.hpp"
#include "ai/configuration.hpp"
#include "config.hpp"
#include "config_cache.hpp"
#include "construct_dialog.hpp"
@ -604,6 +605,12 @@ bool game_controller::init_config(const bool force)
// make sure that multiplayer mode is set if command line parameter is selected
if (multiplayer_mode_)
cache_.add_define("MULTIPLAYER");
// make sure that 'debug mode' symbol is set if command line parameter is selected
if (game_config::debug) {
cache_.add_define("DEBUG_MODE");
}
load_game_cfg(force);
const config &cfg = game_config_.child("game_config");
@ -616,6 +623,7 @@ bool game_controller::init_config(const bool force)
paths_manager_.set_paths(game_config_);
::init_textdomains(game_config_);
about::set_about(game_config_);
ai::configuration::init(game_config_);
return true;
}

View file

@ -20,7 +20,7 @@
#include "global.hpp"
#include "ai/manager.hpp"
#include "ai/configuration.hpp"
#include "dialogs.hpp"
#include "foreach.hpp"
#include "gettext.hpp"
@ -459,7 +459,7 @@ void connect::side::process_event()
changed_ = true;
}
if (combo_ai_algorithm_.changed() && combo_ai_algorithm_.selected() >= 0) {
ai_algorithm_ = parent_->ai_algorithms_[combo_ai_algorithm_.selected()];
ai_algorithm_ = parent_->ai_algorithms_[combo_ai_algorithm_.selected()]->id;
changed_ = true;
}
if (combo_leader_.changed() && combo_leader_.selected() >= 0) {
@ -563,14 +563,15 @@ void connect::side::init_ai_algorithm_combo()
assert(parent_->ai_algorithms_.empty() == false);
int sel = 0;
std::vector<std::string> ais = parent_->ai_algorithms_;
for (unsigned int i = 0; i < ais.size(); i++) {
if (ais[i] == ai_algorithm_) {
std::vector<ai::description*> &ais_list = parent_->ai_algorithms_;
std::vector<std::string> ais;
int i = 0;
foreach (const ai::description *desc, ais_list){
ais.push_back(desc->description);
if (desc->id==ai_algorithm_){
sel = i;
}
if (ais[i] == "default") {
ais[i] = _("Default AI");
}
i++;
}
combo_ai_algorithm_.set_items(ais);
combo_ai_algorithm_.set_selected(sel);
@ -661,9 +662,7 @@ config connect::side::get_config() const
}
{
res["id"] = res["save_id"];
config &ai = res.child_or_add("ai");
if (ai_algorithm_ != "default")
ai["ai_algorithm"] = ai_algorithm_;
res.add_child("ai",ai::configuration::get_ai_config_for(ai_algorithm_));
}
description = N_("Computer player");
break;
@ -1437,7 +1436,7 @@ void connect::lists_init()
}
// AI algorithms
ai_algorithms_ = ai::manager::get_available_ais();
ai_algorithms_ = ai::configuration::get_available_ais();
// Factions
config::child_itors sides = current_config()->child_range("side");

View file

@ -28,6 +28,10 @@
#include <string>
namespace ai {
class description;
}
namespace mp {
class connect : public mp::ui
@ -263,7 +267,7 @@ private:
std::vector<std::string> player_factions_;
std::vector<std::string> player_teams_;
std::vector<std::string> player_colours_;
std::vector<std::string> ai_algorithms_;
std::vector<ai::description*> ai_algorithms_;
// team_name list and "Team" prefix
std::vector<std::string> team_names_;