Added component class interface, which is needed to support [modify_ai]

This commit is contained in:
Iurii Chernyi 2009-08-23 19:30:38 +00:00
parent 2eebb9c0d7
commit d2ef421454
15 changed files with 324 additions and 28 deletions

View file

@ -53,6 +53,8 @@
<Unit filename="..\..\src\ai\composite\ai.hpp" />
<Unit filename="..\..\src\ai\composite\aspect.cpp" />
<Unit filename="..\..\src\ai\composite\aspect.hpp" />
<Unit filename="..\..\src\ai\composite\component.cpp" />
<Unit filename="..\..\src\ai\composite\component.hpp" />
<Unit filename="..\..\src\ai\composite\contexts.cpp" />
<Unit filename="..\..\src\ai\composite\contexts.hpp" />
<Unit filename="..\..\src\ai\composite\engine.cpp" />

View file

@ -82,6 +82,8 @@
<Unit filename="..\..\src\ai\composite\ai.hpp" />
<Unit filename="..\..\src\ai\composite\aspect.cpp" />
<Unit filename="..\..\src\ai\composite\aspect.hpp" />
<Unit filename="..\..\src\ai\composite\component.cpp" />
<Unit filename="..\..\src\ai\composite\component.hpp" />
<Unit filename="..\..\src\ai\composite\contexts.cpp" />
<Unit filename="..\..\src\ai\composite\contexts.hpp" />
<Unit filename="..\..\src\ai\composite\engine.cpp" />

View file

@ -4059,6 +4059,34 @@
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\ai\composite\component.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)\ai\composite\"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)\ai\composite\"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug (fast)|Win32"
>
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)\ai\composite\"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\ai\composite\contexts.cpp"
>
@ -5870,6 +5898,10 @@
RelativePath="..\..\src\ai\composite\aspect.hpp"
>
</File>
<File
RelativePath="..\..\src\ai\composite\component.hpp"
>
</File>
<File
RelativePath="..\..\src\ai\composite\contexts.hpp"
>

View file

@ -224,6 +224,7 @@ SET(wesnoth-main_SRC
ai/actions.cpp
ai/composite/ai.cpp
ai/composite/aspect.cpp
ai/composite/component.cpp
ai/composite/contexts.cpp
ai/composite/engine.cpp
ai/composite/engine_default.cpp

View file

@ -45,6 +45,7 @@ wesnoth_source = \
ai/actions.cpp \
ai/composite/ai.cpp \
ai/composite/aspect.cpp \
ai/composite/component.cpp \
ai/composite/contexts.cpp \
ai/composite/engine.cpp \
ai/composite/engine_default.cpp \

View file

@ -150,6 +150,7 @@ wesnoth_sources = Split("""
ai/actions.cpp
ai/composite/ai.cpp
ai/composite/aspect.cpp
ai/composite/component.cpp
ai/composite/contexts.cpp
ai/composite/engine.cpp
ai/composite/engine_default.cpp

View file

@ -0,0 +1,144 @@
/* $Id$ */
/*
Copyright (C) 2009 by Yurii Chernyi <terraninfo@terraninfo.net>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2
or at your option any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
/**
* Composite AI component
* @file ai/composite/component.cpp
*/
#include "component.hpp"
#include "engine.hpp"
#include "../formula/ai.hpp"
#include "../../log.hpp"
#include <boost/regex.hpp>
namespace ai {
static lg::log_domain log_ai_composite_component("ai/composite/component");
#define DBG_AI_COMPOSITE LOG_STREAM(debug, log_ai_composite_component)
#define LOG_AI_COMPOSITE LOG_STREAM(info, log_ai_composite_component)
#define ERR_AI_COMPOSITE LOG_STREAM(err, log_ai_composite_component)
/*
[modify_ai]
component = "aspect['aggression']"
property = "facet"
action= "add"
[cfg]...[/cfg]
[/modify_ai]
[modify_ai]
component = "stage['fallback']
action = "change"
[/modify_ai]
[modify_ai]
component = "aspect['avoid'].facet['zzz']"
action = "change"
[cfg]...[/cfg]
[/modify_ai]
[modify_ai]
component = "aspect['aggression']"
property = facet['zzzz']
action = "delete"
[cfg]...[/cfg]
[/modify_ai]
[modify_ai]
component = "aspect['aggression']"
action = "add"
property = "facet"
where="end"
[cfg]...[/cfg]
[/modify_ai]
*/
static component *find_component(component *root, const std::string &path, path_element &tail)
{
if (root==NULL) {
return NULL;
}
//match path elements in [modify_ai] tag
boost::regex re("([^\\.^\\[]+)(\\['([^\\]]+)'\\]|\\[(\\d*)\\]|())");
boost::sregex_token_iterator i(path.begin(), path.end(), re, 0);
boost::sregex_token_iterator j;
component *c = root;
std::vector< path_element > elements;
while(i != j)
{
path_element pe;
pe.property = *i++;
pe.id = *i++;
pe.position = *i++;
elements.push_back(pe);
}
if (elements.size()<1) {
return NULL;
}
std::vector< path_element >::iterator k_max = elements.end()-1;
for (std::vector< path_element >::iterator k = elements.begin(); k!=k_max; ++k) {
//not last
c = c->get_child(*k);
if (c==NULL) {
return NULL;
}
}
tail = *k_max;
return c;
}
bool component_manager::add_component(component *root, const std::string &path, const config &cfg)
{
path_element tail;
component *c = find_component(root,path,tail);
if (c==NULL) {
return false;
}
return c->add_child(tail, cfg);
}
bool component_manager::change_component(component *root, const std::string &path, const config &cfg)
{
path_element tail;
component *c = find_component(root,path,tail);
if (c==NULL) {
return false;
}
return c->change_child(tail,cfg);
}
bool component_manager::delete_component(component *root, const std::string &path)
{
path_element tail;
component *c = find_component(root,path,tail);
if (c==NULL) {
return false;
}
return c->delete_child(tail);
}
} //end of namespace ai

View file

@ -0,0 +1,69 @@
/* $Id$ */
/*
Copyright (C) 2009 by Yurii Chernyi <terraninfo@terraninfo.net>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2
or at your option any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
/**
* @file ai/composite/component.hpp
* A component of the AI framework
*/
#ifndef AI_COMPOSITE_COMPONENT_HPP_INCLUDED
#define AI_COMPOSITE_COMPONENT_HPP_INCLUDED
#include "../../global.hpp"
#include "../game_info.hpp"
#include <vector>
#ifdef _MSC_VER
#pragma warning(push)
//silence "inherits via dominance" warnings
#pragma warning(disable:4250)
#endif
//============================================================================
namespace ai {
struct path_element {
std::string property;
std::string id;
std::string position;
};
class component {
public:
component() {};
virtual ~component() {};
virtual component* get_child(const path_element &child) = 0;
virtual bool change_child(const path_element &child, const config &cfg) = 0;
virtual bool add_child(const path_element &child, const config &cfg) = 0;
virtual bool delete_child(const path_element &child) = 0;
};
class component_manager {
public:
static bool add_component(component *root, const std::string &path, const config &cfg);
static bool change_component(component *root, const std::string &path, const config &cfg);
static bool delete_component(component *root, const std::string &path);
};
} //end of namespace ai
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#endif

View file

@ -119,6 +119,7 @@ std::string engine::evaluate(const std::string& /*str*/)
}
std::string engine::get_name() const
{
return "null";
@ -138,4 +139,11 @@ config engine::to_config() const
return cfg;
}
component* find_component( component */*root*/, const std::string &/*path*/ )
{
LOG_AI_COMPOSITE_ENGINE << "find_component is not implemented by this engine" << std::endl;
return NULL;
}
} //end of namespace ai

View file

@ -36,6 +36,7 @@ namespace ai {
class rca_context;
class ai_context;
class component;
class engine {
public:
@ -77,7 +78,7 @@ public:
//do not override that method in subclasses which cannot create stages
virtual void do_parse_stage_from_config( ai_context &context, const config &cfg, std::back_insert_iterator<std::vector< stage_ptr > > b );
//do not override that method in subclasse which cannot evaluate formulas
//do not override that method in subclasses which cannot evaluate formulas
virtual std::string evaluate(const std::string& str);

View file

@ -26,6 +26,7 @@
#include "../serialization/parser.hpp"
#include "../serialization/preprocessor.hpp"
#include "../team.hpp"
#include <boost/lexical_cast.hpp>
#include <vector>
@ -262,13 +263,7 @@ bool configuration::parse_side_config(const config& original_cfg, config &cfg )
aspect_cfg.add_child("default",c);
}
LOG_AI_CONFIGURATION << "Finally, applying [modify_ai] tags to configuration"<< std::endl;
foreach (const config &mod_ai, parsed_cfg.child_range("modify_ai")){
//do ai config modification without redeployement
modify_ai_configuration(mod_ai,parsed_cfg);
}
DBG_AI_CONFIGURATION << "After applying [modify_ai] tags, config contains:"<< std::endl << parsed_cfg << std::endl;
DBG_AI_CONFIGURATION << "Done parsing side config, it contains:"<< std::endl << parsed_cfg << std::endl;
LOG_AI_CONFIGURATION << "Done parsing side config"<< std::endl;
cfg = parsed_cfg;
@ -323,12 +318,6 @@ bool configuration::upgrade_side_config_from_1_07_02_to_1_07_03(config &cfg)
return cfg;//in boolean context
}
bool configuration::modify_ai_configuration(const config &/*mod_ai*/, config &/*parsed_cfg*/)
{
//@todo 1.7.4 implement
return true;
}
void configuration::upgrade_aspect_configs_from_1_07_02_to_1_07_03(const config::const_child_itors &ai_parameters, config &parsed_cfg)
{

View file

@ -97,17 +97,6 @@ public:
/**
* modify a config of the ai by applying rules in [modify_ai] tag
* @param[in] mod_ai config containing the contents of the [modify_ai] tag
* @param[in][out] cfg ai configuration to modify
* @return was all ok?
* @retval true success, cfg is guaranteed to be valid
* @retval false failure
*/
static bool modify_ai_configuration(const config &mod_ai, config &cfg);
/**
* change a bunch of old aspect configs into a new-style [ai] snippet
* @param[in] ai_parameters - old [ai] snippets

View file

@ -53,6 +53,11 @@ typedef boost::shared_ptr< interface > ai_ptr;
class attack_analysis;
typedef std::vector<attack_analysis> attacks_vector;
class readonly_context;
class readwrite_context;
class default_ai_context;
class ai_context;
class aspect;
class candidate_action;
class engine;

View file

@ -32,6 +32,7 @@
#include "../replay.hpp"
#include "../serialization/string_utils.hpp"
#include "../statistics.hpp"
#include "composite/component.hpp"
#include <map>
#include <stack>
@ -79,9 +80,16 @@ void holder::init( side_number side )
}
if (!this->ai_){
ai_ = boost::shared_ptr<ai_composite>(new ai_composite(*default_ai_context_,cfg_));
ai_->on_create();
}
if (!this->ai_) {
if (this->ai_) {
ai_->on_create();
foreach (const config &mod_ai, cfg_.child_range("modify_ai")) {
modify_ai(mod_ai);
}
cfg_.clear_children("modify_ai");
} else {
ERR_AI_MANAGER << describe_ai()<<"AI lazy initialization error!" << std::endl;
}
@ -135,6 +143,31 @@ void holder::modify_ai_config_old( const config::const_child_itors &ai_parameter
}
}
void holder::modify_ai(const config &cfg)
{
if (this->readonly_context_ == NULL) {
// if not initialized, initialize now.
get_ai_ref();
}
const std::string &act = cfg["action"];
bool res = false;
if (act == "add") {
res = component_manager::add_component(NULL,cfg["path"],cfg.child("cfg"));
} else if (act == "change") {
res = component_manager::change_component(NULL,cfg["path"],cfg.child("cfg"));
} else if (act == "delete") {
res = component_manager::delete_component(NULL,cfg["path"]);
} else {
ERR_AI_MANAGER << "modify_ai tag has invalid 'action' attribute " << std::endl;
}
if (!res) {
ERR_AI_MANAGER << "[modify_ai] failed"<< std::endl;
DBG_AI_MANAGER << "[modify_ai] config is: "<< std::endl << cfg << std::endl;
}
}
config holder::to_config() const
{
if (!this->ai_) {
@ -619,6 +652,13 @@ void manager::modify_active_ai_config_old_for_side ( side_number side, const con
get_active_ai_holder_for_side(side).modify_ai_config_old(ai_parameters);
}
void manager::modify_active_ai_for_side ( side_number side, const config &cfg )
{
get_active_ai_holder_for_side(side).modify_ai(cfg);
}
std::string manager::get_active_ai_identifier_for_side( side_number side )
{
return get_active_ai_holder_for_side(side).get_ai_identifier();

View file

@ -64,6 +64,8 @@ public:
config to_config() const;
void modify_ai(const config& cfg);
const std::string get_ai_identifier() const;
private:
@ -387,11 +389,21 @@ public:
* This function is provided for backward-compatability with [modify_side][ai]...[/ai][/modify_side]
* It can only add new facets to aspects
* @param side side_number (1-based, as in game_info).
* @param ai_parameters AI paramters to be modified.
* @param ai_parameters AI parameters to be modified.
*/
static void modify_active_ai_config_old_for_side ( side_number side, const config::const_child_itors &ai_parameters );
/**
* Modifies AI parameters for active AI of the given @a side.
* This function is a backend for [modify_ai] tag
* @param side side_number (1-based, as in game_info).
* @param cfg - content of [modify_ai] tag
*/
static void modify_active_ai_for_side( ai::side_number, const config &cfg );
// =======================================================================
// PROXY
// =======================================================================