optional new-style AI configs...
...and generation of AI lists in multiplayer from files
This commit is contained in:
parent
a07832cf93
commit
5652b111c0
14 changed files with 246 additions and 53 deletions
|
@ -10,6 +10,13 @@
|
|||
|
||||
{campaigns/}
|
||||
|
||||
[ais]
|
||||
{ai/ais/}
|
||||
#ifdef DEBUG_MODE
|
||||
{ai/dev/}
|
||||
#endif
|
||||
[/ais]
|
||||
|
||||
#ifdef EDITOR
|
||||
[textdomain]
|
||||
name="wesnoth-editor"
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
#textdomain wesnoth
|
||||
ai_algorithm=formula_ai
|
||||
[ai]
|
||||
ai_identifier=formula_ai_stable
|
||||
[/ai]
|
10
data/ai/dev/formula_ai.cfg
Normal file
10
data/ai/dev/formula_ai.cfg
Normal 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]
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
// =======================================================================
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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_;
|
||||
|
|
Loading…
Add table
Reference in a new issue