new AI: ai_composite
This commit is contained in:
parent
cdfcaf800a
commit
59f781e290
38 changed files with 2655 additions and 129 deletions
|
@ -1,6 +1,7 @@
|
|||
Version 1.7.0+svn:
|
||||
* AI:
|
||||
* Reworked AI code to allow easier creation of AI components.
|
||||
* New AI: Composite AI
|
||||
* Campaigns
|
||||
* Delfador's Memoirs: new portrait for Lionel.
|
||||
* Graphics
|
||||
|
|
22
data/ai/dev/testing_ai_default.cfg
Normal file
22
data/ai/dev/testing_ai_default.cfg
Normal file
|
@ -0,0 +1,22 @@
|
|||
#textdomain wesnoth
|
||||
ai_algorithm=composite_ai
|
||||
[ai]
|
||||
ai_identifier=testing_ai_default
|
||||
[stage]
|
||||
engine=cpp
|
||||
name=testing_ai_default::candidate_action_evaluation_loop
|
||||
[candidate_action]
|
||||
engine=cpp
|
||||
name=testing_ai_default::goto_phase
|
||||
[/candidate_action]
|
||||
[candidate_action]
|
||||
engine=cpp
|
||||
name=testing_ai_default::recruitment_phase
|
||||
[/candidate_action]
|
||||
[/stage]
|
||||
[stage]
|
||||
engine=cpp
|
||||
name=testing_ai_default::fallback
|
||||
fallback=default
|
||||
[/stage]
|
||||
[/ai]
|
|
@ -2737,10 +2737,66 @@
|
|||
RelativePath="..\..\src\ai\game_info.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\registry.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\testing.cpp"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="composite"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\composite\ai.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\composite\contexts.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\composite\engine.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\composite\engine_default.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\composite\rca.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\composite\stage.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="default"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\default\contexts.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="testing"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\testing\ca.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\testing\stage_rca.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\testing\stage_fallback.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
|
@ -3576,10 +3632,66 @@
|
|||
RelativePath="..\..\src\ai\game_info.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\registry.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\testing.hpp"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="composite"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\composite\ai.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\composite\contexts.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\composite\engine.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\composite\engine_default.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\composite\rca.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\composite\stage.hpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="default"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\default\contexts.hpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="testing"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\testing\ca.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\testing\stage_rca.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\testing\stage_fallback.hpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
|
|
|
@ -226,10 +226,21 @@ SET(wesnoth-main_SRC
|
|||
ai/ai_manager.cpp
|
||||
ai/ai_move.cpp
|
||||
ai/ai_village.cpp
|
||||
ai/composite/ai.cpp
|
||||
ai/composite/contexts.cpp
|
||||
ai/composite/engine.cpp
|
||||
ai/composite/engine_default.cpp
|
||||
ai/composite/rca.cpp
|
||||
ai/composite/stage.cpp
|
||||
ai/contexts.cpp
|
||||
ai/default/contexts.cpp
|
||||
ai/formula_ai.cpp
|
||||
ai/formula_candidates.cpp
|
||||
ai/game_info.cpp
|
||||
ai/registry.cpp
|
||||
ai/testing/ca.cpp
|
||||
ai/testing/stage_rca.cpp
|
||||
ai/testing/stage_fallback.cpp
|
||||
ai/testing.cpp
|
||||
animated_game.cpp
|
||||
attack_prediction.cpp
|
||||
|
|
|
@ -51,10 +51,21 @@ wesnoth_source = \
|
|||
ai/ai_manager.cpp \
|
||||
ai/ai_move.cpp \
|
||||
ai/ai_village.cpp \
|
||||
ai/composite/ai.cpp \
|
||||
ai/composite/context.cpp \
|
||||
ai/composite/engine.cpp \
|
||||
ai/composite/engine_default.cpp \
|
||||
ai/composite/rca.cpp \
|
||||
ai/composite/stage.cpp \
|
||||
ai/contexts.cpp \
|
||||
ai/default/contexts.cpp \
|
||||
ai/formula_ai.cpp \
|
||||
ai/formula_candidates.cpp \
|
||||
ai/game_info.cpp \
|
||||
ai/registry.cpp \
|
||||
ai/testing/ca.cpp \
|
||||
ai/testing/stage_rca.cpp \
|
||||
ai/testing/stage_fallback.cpp \
|
||||
ai/testing.cpp \
|
||||
animated_game.cpp \
|
||||
attack_prediction.cpp \
|
||||
|
|
|
@ -156,10 +156,21 @@ wesnoth_sources = Split("""
|
|||
ai/ai_manager.cpp
|
||||
ai/ai_move.cpp
|
||||
ai/ai_village.cpp
|
||||
ai/composite/ai.cpp
|
||||
ai/composite/contexts.cpp
|
||||
ai/composite/engine.cpp
|
||||
ai/composite/engine_default.cpp
|
||||
ai/composite/rca.cpp
|
||||
ai/composite/stage.cpp
|
||||
ai/contexts.cpp
|
||||
ai/default/contexts.cpp
|
||||
ai/formula_ai.cpp
|
||||
ai/formula_candidates.cpp
|
||||
ai/game_info.cpp
|
||||
ai/registry.cpp
|
||||
ai/testing/ca.cpp
|
||||
ai/testing/stage_rca.cpp
|
||||
ai/testing/stage_fallback.cpp
|
||||
ai/testing.cpp
|
||||
animated_game.cpp
|
||||
attack_prediction.cpp
|
||||
|
|
4
src/ai/SConstruct
Normal file
4
src/ai/SConstruct
Normal file
|
@ -0,0 +1,4 @@
|
|||
import sys
|
||||
from subprocess import call
|
||||
print "scons --directory=../.. " + " ".join(sys.argv[1:])
|
||||
Exit(call(Split("scons --directory=../..") + sys.argv[1:]))
|
|
@ -36,7 +36,6 @@
|
|||
|
||||
#include <fstream>
|
||||
|
||||
|
||||
static lg::log_domain log_ai("ai/general");
|
||||
#define DBG_AI LOG_STREAM(debug, log_ai)
|
||||
#define LOG_AI LOG_STREAM(info, log_ai)
|
||||
|
@ -46,8 +45,9 @@ static lg::log_domain log_ai("ai/general");
|
|||
typedef util::array<map_location,6> adjacent_tiles_array;
|
||||
|
||||
|
||||
idle_ai::idle_ai(ai::readwrite_context &context) : ai::side_context_proxy(context), ai::readonly_context_proxy(context), ai::readwrite_context_proxy(context), recursion_counter_(context.get_recursion_count())
|
||||
idle_ai::idle_ai(ai::readwrite_context &context) : recursion_counter_(context.get_recursion_count())
|
||||
{
|
||||
init_readwrite_context_proxy(context);
|
||||
}
|
||||
|
||||
std::string idle_ai::describe_self()
|
||||
|
@ -76,7 +76,9 @@ void idle_ai::play_turn()
|
|||
class sample_ai : public ai::readwrite_context_proxy, public ai_interface {
|
||||
public:
|
||||
sample_ai(ai::readwrite_context &context)
|
||||
: ai::side_context_proxy(context), ai::readonly_context_proxy(context), ai::readwrite_context_proxy(context), recursion_counter_(context.get_recursion_count()) {}
|
||||
: recursion_counter_(context.get_recursion_count()) {
|
||||
init_readwrite_context_proxy(context);
|
||||
}
|
||||
|
||||
virtual void play_turn() {
|
||||
game_events::fire("ai turn");
|
||||
|
@ -217,20 +219,17 @@ private:
|
|||
ai::recursion_counter recursion_counter_;
|
||||
};
|
||||
|
||||
ai_default::ai_default(ai::readwrite_context &context) :
|
||||
ai::side_context_proxy(context),
|
||||
ai::readonly_context_proxy(context),
|
||||
ai::readwrite_context_proxy(context),
|
||||
ai_default::ai_default(ai::default_ai_context &context) :
|
||||
game_logic::formula_callable(),
|
||||
recursion_counter_(context.get_recursion_count()),
|
||||
defensive_position_cache_(),
|
||||
threats_found_(false),
|
||||
attacks_(),
|
||||
disp_(get_info().disp),
|
||||
map_(get_info().map),
|
||||
units_(get_info().units),
|
||||
teams_(get_info().teams),
|
||||
state_(get_info().state),
|
||||
disp_(context.get_info().disp),
|
||||
map_(context.get_info().map),
|
||||
units_(context.get_info().units),
|
||||
teams_(context.get_info().teams),
|
||||
state_(context.get_info().state),
|
||||
consider_combat_(true),
|
||||
additional_targets_(),
|
||||
unit_movement_scores_(),
|
||||
|
@ -241,9 +240,10 @@ ai_default::ai_default(ai::readwrite_context &context) :
|
|||
unit_stats_cache_(),
|
||||
attack_depth_(0),
|
||||
recruiting_preferred_(0),
|
||||
formula_ai_(NULL)
|
||||
formula_ai_()
|
||||
{
|
||||
add_ref();
|
||||
init_default_ai_context_proxy(context);
|
||||
}
|
||||
|
||||
ai_default::~ai_default(){
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "../actions.hpp"
|
||||
#include "ai_interface.hpp"
|
||||
#include "contexts.hpp"
|
||||
#include "default/contexts.hpp"
|
||||
#include "../formula_callable.hpp"
|
||||
|
||||
class formula_ai;
|
||||
|
@ -38,12 +39,12 @@ private:
|
|||
ai::recursion_counter recursion_counter_;
|
||||
};
|
||||
|
||||
class ai_default : public virtual ai::readwrite_context_proxy, public ai_interface, public game_logic::formula_callable {
|
||||
class ai_default : public virtual ai::default_ai_context_proxy, public ai_interface, public game_logic::formula_callable {
|
||||
public:
|
||||
typedef ai::move_map move_map;
|
||||
typedef map_location location;//will get rid of this later
|
||||
|
||||
ai_default(ai::readwrite_context &context);
|
||||
ai_default(ai::default_ai_context &context);
|
||||
virtual ~ai_default();
|
||||
|
||||
virtual void play_turn();
|
||||
|
|
|
@ -23,23 +23,29 @@
|
|||
#include "ai_interface.hpp"
|
||||
#include "contexts.hpp"
|
||||
|
||||
class ai2 : public ai::readwrite_context_proxy, public ai_interface {
|
||||
namespace ai {
|
||||
|
||||
class ai2 : public readwrite_context_proxy, public ai_interface {
|
||||
public:
|
||||
ai2(ai::readwrite_context &context)
|
||||
: ai::side_context_proxy(context), ai::readonly_context_proxy(context), ai::readwrite_context_proxy(context),recursion_counter_(context.get_recursion_count())
|
||||
{}
|
||||
ai2(readwrite_context &context)
|
||||
: recursion_counter_(context.get_recursion_count())
|
||||
{
|
||||
init_readwrite_context_proxy(context);
|
||||
}
|
||||
virtual ~ai2() {}
|
||||
virtual void play_turn() {}
|
||||
virtual void switch_side(ai::side_number side){
|
||||
virtual void switch_side(side_number side){
|
||||
set_side(side);
|
||||
}
|
||||
int get_recursion_count() const{
|
||||
return recursion_counter_.get_count();
|
||||
}
|
||||
private:
|
||||
ai::recursion_counter recursion_counter_;
|
||||
recursion_counter recursion_counter_;
|
||||
|
||||
};
|
||||
|
||||
} //of namespace ai
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -102,7 +102,10 @@ namespace dfool {
|
|||
class dfool_ai : public ai::readwrite_context_proxy, public ai_interface {
|
||||
public:
|
||||
dfool_ai(ai::readwrite_context &context)
|
||||
: ai::side_context_proxy(context), ai::readonly_context_proxy(context), ai::readwrite_context_proxy(context), recursion_counter_(context.get_recursion_count()), unit_memory_(current_team().ai_memory()){}
|
||||
: recursion_counter_(context.get_recursion_count()), unit_memory_(current_team().ai_memory())
|
||||
{
|
||||
init_readwrite_context_proxy(context);
|
||||
}
|
||||
void play_turn();
|
||||
virtual std::string describe_self();
|
||||
virtual int get_recursion_count() const{
|
||||
|
|
|
@ -23,7 +23,9 @@
|
|||
#include "ai_manager.hpp"
|
||||
#include "ai_dfool.hpp"
|
||||
#include "contexts.hpp"
|
||||
#include "composite/ai.hpp"
|
||||
#include "formula_ai.hpp"
|
||||
#include "registry.hpp"
|
||||
#include "../game_events.hpp"
|
||||
#include "../game_preferences.hpp"
|
||||
#include "../log.hpp"
|
||||
|
@ -35,6 +37,9 @@
|
|||
#include <stack>
|
||||
#include <vector>
|
||||
|
||||
using namespace ai;
|
||||
|
||||
const std::string ai_manager::AI_TYPE_COMPOSITE_AI = "composite_ai";
|
||||
const std::string ai_manager::AI_TYPE_SAMPLE_AI = "sample_ai";
|
||||
const std::string ai_manager::AI_TYPE_IDLE_AI = "idle_ai";
|
||||
const std::string ai_manager::AI_TYPE_FORMULA_AI = "formula_ai";
|
||||
|
@ -49,7 +54,7 @@ static lg::log_domain log_ai_manager("ai/manager");
|
|||
#define ERR_AI_MANAGER LOG_STREAM(err, log_ai_manager)
|
||||
|
||||
ai_holder::ai_holder( int side, const std::string& ai_algorithm_type )
|
||||
: ai_(NULL), side_context_(NULL), readonly_context_(NULL), readwrite_context_(NULL), ai_algorithm_type_(ai_algorithm_type), ai_effective_parameters_(), ai_global_parameters_(), ai_memory_(), ai_parameters_(), side_(side)
|
||||
: ai_(NULL), side_context_(NULL), readonly_context_(NULL), readwrite_context_(NULL), default_ai_context_(NULL), ai_algorithm_type_(ai_algorithm_type), ai_effective_parameters_(), ai_global_parameters_(), ai_memory_(), ai_parameters_(), side_(side)
|
||||
{
|
||||
DBG_AI_MANAGER << describe_ai() << "Preparing new AI holder" << std::endl;
|
||||
}
|
||||
|
@ -59,15 +64,18 @@ void ai_holder::init( int side )
|
|||
{
|
||||
LOG_AI_MANAGER << describe_ai() << "Preparing to create new managed master AI" << std::endl;
|
||||
if (side_context_ == NULL) {
|
||||
side_context_ = new ai::side_context_impl(side);
|
||||
side_context_ = new side_context_impl(side);
|
||||
} else {
|
||||
side_context_->set_side(side);
|
||||
}
|
||||
if (readonly_context_ == NULL){
|
||||
readonly_context_ = new ai::readonly_context_impl(*side_context_);
|
||||
readonly_context_ = new readonly_context_impl(*side_context_);
|
||||
}
|
||||
if (readwrite_context_ == NULL){
|
||||
readwrite_context_ = new ai::readwrite_context_impl(*readonly_context_);
|
||||
readwrite_context_ = new readwrite_context_impl(*readonly_context_);
|
||||
}
|
||||
if (default_ai_context_ == NULL){
|
||||
default_ai_context_ = new default_ai_context_impl(*readwrite_context_);
|
||||
}
|
||||
this->ai_ = create_ai(side);
|
||||
if (this->ai_ == NULL) {
|
||||
|
@ -83,6 +91,7 @@ ai_holder::~ai_holder()
|
|||
LOG_AI_MANAGER << describe_ai() << "Managed AI will be deleted" << std::endl;
|
||||
}
|
||||
delete this->ai_;
|
||||
delete this->default_ai_context_;
|
||||
delete this->readwrite_context_;
|
||||
delete this->readonly_context_;
|
||||
delete this->side_context_;
|
||||
|
@ -196,9 +205,9 @@ bool ai_holder::is_mandate_ok()
|
|||
ai_interface* ai_holder::create_ai( int side )
|
||||
{
|
||||
assert (side > 0);
|
||||
assert (readwrite_context_!=NULL);
|
||||
assert (default_ai_context_!=NULL);
|
||||
//@note: ai_params, contexts, and ai_algorithm_type are supposed to be set before calling init( );
|
||||
return ai_manager::create_transient_ai(ai_algorithm_type_,readwrite_context_);
|
||||
return ai_manager::create_transient_ai(ai_algorithm_type_,default_ai_context_);
|
||||
|
||||
}
|
||||
|
||||
|
@ -281,6 +290,7 @@ void ai_manager::set_ai_info(const ai_game_info& i)
|
|||
clear_ai_info();
|
||||
}
|
||||
ai_info_ = new ai_game_info(i);
|
||||
ai_registry::init();
|
||||
}
|
||||
|
||||
|
||||
|
@ -539,9 +549,9 @@ bool ai_manager::add_ai_for_side( int side, const std::string& ai_algorithm_type
|
|||
}
|
||||
|
||||
|
||||
ai_interface* ai_manager::create_transient_ai( const std::string &ai_algorithm_type, ai::readwrite_context *rw_context )
|
||||
ai_interface* ai_manager::create_transient_ai( const std::string &ai_algorithm_type, default_ai_context *ai_context )
|
||||
{
|
||||
assert(rw_context!=NULL);
|
||||
assert(ai_context!=NULL);
|
||||
//@todo 1.7 modify this code to use a 'factory lookup' pattern -
|
||||
//a singleton which holds a map<string,ai_factory_ptr> of all functors which can create AIs.
|
||||
//this will allow individual AI implementations to 'register' themselves.
|
||||
|
@ -551,7 +561,7 @@ ai_interface* ai_manager::create_transient_ai( const std::string &ai_algorithm_t
|
|||
//: To add an AI of your own, put
|
||||
// if(ai_algorithm_type == "my_ai") {
|
||||
// LOG_AI_MANAGER << "Creating new AI of type [" << "my_ai" << "]"<< std::endl;
|
||||
// ai_interface *a = new my_ai(*rw_context);
|
||||
// ai_interface *a = new my_ai(*ai_context);
|
||||
// a->on_create();
|
||||
// return a;
|
||||
// }
|
||||
|
@ -559,45 +569,54 @@ ai_interface* ai_manager::create_transient_ai( const std::string &ai_algorithm_t
|
|||
|
||||
//if(ai_algorithm_type == ai_manager::AI_TYPE_SAMPLE_AI) {
|
||||
// LOG_AI_MANAGER << "Creating new AI of type [" << ai_manager::AI_TYPE_IDLE_AI << "]"<< std::endl;
|
||||
// ai_interface *a = new sample_ai(*rw_context);
|
||||
// ai_interface *a = new sample_ai(*ai_context);
|
||||
// a->on_create();
|
||||
// return a;
|
||||
//}
|
||||
|
||||
if(ai_algorithm_type == ai_manager::AI_TYPE_IDLE_AI) {
|
||||
LOG_AI_MANAGER << "Creating new AI of type [" << ai_manager::AI_TYPE_IDLE_AI << "]"<< std::endl;
|
||||
ai_interface *a = new idle_ai(*rw_context);
|
||||
ai_interface *a = new idle_ai(*ai_context);
|
||||
a->on_create();
|
||||
return a;
|
||||
}
|
||||
|
||||
if(ai_algorithm_type == ai_manager::AI_TYPE_FORMULA_AI) {
|
||||
LOG_AI_MANAGER << "Creating new AI of type [" << ai_manager::AI_TYPE_FORMULA_AI << "]"<< std::endl;
|
||||
ai_interface *a = new formula_ai(*rw_context);
|
||||
ai_interface *a = new formula_ai(*ai_context);
|
||||
a->on_create();
|
||||
return a;
|
||||
}
|
||||
|
||||
if(ai_algorithm_type == ai_manager::AI_TYPE_DFOOL_AI) {
|
||||
LOG_AI_MANAGER << "Creating new AI of type [" << ai_manager::AI_TYPE_DFOOL_AI << "]"<< std::endl;
|
||||
ai_interface *a = new dfool::dfool_ai(*rw_context);
|
||||
ai_interface *a = new dfool::dfool_ai(*ai_context);
|
||||
a->on_create();
|
||||
return a;
|
||||
}
|
||||
|
||||
if(ai_algorithm_type == ai_manager::AI_TYPE_AI2) {
|
||||
LOG_AI_MANAGER << "Creating new AI of type [" << ai_manager::AI_TYPE_AI2 << "]"<< std::endl;
|
||||
ai_interface *a = new ai2(*rw_context);
|
||||
ai_interface *a = new ai2(*ai_context);
|
||||
a->on_create();
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
if(ai_algorithm_type == ai_manager::AI_TYPE_COMPOSITE_AI) {
|
||||
LOG_AI_MANAGER << "Creating new AI of type [" << ai_manager::AI_TYPE_COMPOSITE_AI << "]"<< std::endl;
|
||||
ai_interface *a = new composite_ai::ai_composite(*ai_context);
|
||||
a->on_create();
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
if (!ai_algorithm_type.empty() && ai_algorithm_type != ai_manager::AI_TYPE_DEFAULT) {
|
||||
ERR_AI_MANAGER << "AI not found: [" << ai_algorithm_type << "]. Using default instead.\n";
|
||||
}
|
||||
|
||||
LOG_AI_MANAGER << "Creating new AI of type [" << ai_manager::AI_TYPE_DEFAULT << "]"<< std::endl;
|
||||
ai_interface *a = new ai_default(*rw_context);
|
||||
ai_interface *a = new ai_default(*ai_context);
|
||||
a->on_create();
|
||||
return a;
|
||||
}
|
||||
|
|
|
@ -25,8 +25,9 @@
|
|||
|
||||
#include "../global.hpp"
|
||||
#include "contexts.hpp"
|
||||
|
||||
#include "game_info.hpp"
|
||||
#include "default/contexts.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
|
@ -78,6 +79,7 @@ private:
|
|||
ai::side_context *side_context_;
|
||||
ai::readonly_context *readonly_context_;
|
||||
ai::readwrite_context *readwrite_context_;
|
||||
ai::default_ai_context *default_ai_context_;
|
||||
std::string ai_algorithm_type_;
|
||||
config ai_effective_parameters_;
|
||||
config ai_global_parameters_;
|
||||
|
@ -130,6 +132,7 @@ public:
|
|||
static const int AI_TEAM_FALLBACK_AI = -1;
|
||||
|
||||
|
||||
static const std::string AI_TYPE_COMPOSITE_AI;
|
||||
static const std::string AI_TYPE_SAMPLE_AI;
|
||||
static const std::string AI_TYPE_IDLE_AI;
|
||||
static const std::string AI_TYPE_FORMULA_AI;
|
||||
|
@ -269,7 +272,7 @@ public:
|
|||
* @param context context in which this ai is created
|
||||
* @return the reference to the created AI
|
||||
*/
|
||||
static ai_interface* create_transient_ai( const std::string& ai_algorithm_type, ai::readwrite_context *rw_context);
|
||||
static ai_interface* create_transient_ai( const std::string& ai_algorithm_type, ai::default_ai_context *ai_context);
|
||||
|
||||
|
||||
/**
|
||||
|
|
127
src/ai/composite/ai.cpp
Normal file
127
src/ai/composite/ai.cpp
Normal file
|
@ -0,0 +1,127 @@
|
|||
/* $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 with turn sequence which is a vector of stages
|
||||
* @file ai/composite/ai.cpp
|
||||
*/
|
||||
|
||||
#include "ai.hpp"
|
||||
#include "stage.hpp"
|
||||
#include "../ai_manager.hpp"
|
||||
#include "../../foreach.hpp"
|
||||
#include "../../log.hpp"
|
||||
|
||||
namespace ai {
|
||||
|
||||
namespace composite_ai {
|
||||
|
||||
static lg::log_domain log_ai_composite("ai/composite");
|
||||
#define DBG_AI_COMPOSITE LOG_STREAM(debug, log_ai_composite)
|
||||
#define LOG_AI_COMPOSITE LOG_STREAM(info, log_ai_composite)
|
||||
#define ERR_AI_COMPOSITE LOG_STREAM(err, log_ai_composite)
|
||||
|
||||
// =======================================================================
|
||||
// COMPOSITE AI
|
||||
// =======================================================================
|
||||
std::string ai_composite::describe_self(){
|
||||
return "[composite_ai]";
|
||||
}
|
||||
|
||||
ai_composite::ai_composite( default_ai_context &context)
|
||||
: recursion_counter_(context.get_recursion_count())
|
||||
{
|
||||
init_default_ai_context_proxy(context);
|
||||
}
|
||||
|
||||
void ai_composite::on_create()
|
||||
{
|
||||
const config& ai_global_parameters = ai_manager::get_active_ai_global_parameters_for_side(get_side());
|
||||
LOG_AI_COMPOSITE << "side "<< get_side() << " : "<<" created AI with ai_identifier=["<<
|
||||
ai_global_parameters["ai_identifier"]<<"]"<<std::endl;
|
||||
|
||||
//init the composite ai engines
|
||||
foreach(const config &cfg_element, ai_global_parameters.child_range("engine")){
|
||||
engine::parse_engine_from_config(*this,cfg_element,std::back_inserter(engines_));
|
||||
}
|
||||
|
||||
// init the composite ai stages
|
||||
foreach(const config &cfg_element, ai_global_parameters.child_range("stage")){
|
||||
engine::parse_stage_from_config(*this,cfg_element,std::back_inserter(stages_));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ai_composite::~ai_composite()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ai_composite::play_turn(){
|
||||
foreach(stage_ptr &s, stages_){
|
||||
s->play_stage();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
engine_ptr ai_composite::get_engine(const config& cfg)
|
||||
{
|
||||
const std::string& engine_name = cfg["engine"];
|
||||
std::vector<engine_ptr>::iterator en = engines_.begin();
|
||||
while (en!=engines_.end() && ((*en)->get_name()!=engine_name)) {
|
||||
en++;
|
||||
}
|
||||
|
||||
if (en != engines_.end()){
|
||||
return *en;
|
||||
}
|
||||
|
||||
engine_factory::factory_map::iterator eng = engine_factory::get_list().find(engine_name);
|
||||
if (eng == engine_factory::get_list().end()){
|
||||
ERR_AI_COMPOSITE << "side "<<get_side()<<" : UNABLE TO FIND engine["<<
|
||||
engine_name <<"]" << std::endl;
|
||||
DBG_AI_COMPOSITE << "config snippet contains: " << std::endl << cfg << std::endl;
|
||||
return engine_ptr();
|
||||
}
|
||||
|
||||
engine_ptr new_engine = eng->second->get_new_instance(*this,engine_name);
|
||||
if (!new_engine) {
|
||||
ERR_AI_COMPOSITE << "side "<<get_side()<<" : UNABLE TO CREATE engine["<<
|
||||
engine_name <<"] " << std::endl;
|
||||
DBG_AI_COMPOSITE << "config snippet contains: " << std::endl << cfg << std::endl;
|
||||
return engine_ptr();
|
||||
}
|
||||
engines_.push_back(new_engine);
|
||||
return engines_.back();
|
||||
}
|
||||
|
||||
int ai_composite::get_recursion_count() const
|
||||
{
|
||||
return recursion_counter_.get_count();
|
||||
}
|
||||
|
||||
void ai_composite::switch_side(side_number side)
|
||||
{
|
||||
set_side(side);
|
||||
}
|
||||
|
||||
composite_ai_context& ai_composite::get_composite_ai_context()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
} //end of namespace composite_ai
|
||||
|
||||
} //end of namespace ai
|
106
src/ai/composite/ai.hpp
Normal file
106
src/ai/composite/ai.hpp
Normal file
|
@ -0,0 +1,106 @@
|
|||
/* $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/ai.hpp
|
||||
* Composite AI with turn sequence which is a vector of stages
|
||||
*/
|
||||
|
||||
#ifndef AI_COMPOSITE_AI_HPP_INCLUDED
|
||||
#define AI_COMPOSITE_AI_HPP_INCLUDED
|
||||
|
||||
#include "../../global.hpp"
|
||||
|
||||
#include "contexts.hpp"
|
||||
#include "engine.hpp"
|
||||
#include "stage.hpp"
|
||||
#include "../contexts.hpp"
|
||||
#include "../default/contexts.hpp"
|
||||
#include "../ai_interface.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
//============================================================================
|
||||
namespace ai {
|
||||
|
||||
namespace composite_ai {
|
||||
|
||||
class ai_composite : public composite_ai_context, public virtual default_ai_context_proxy, public ai_interface {
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ai_composite( default_ai_context &context );
|
||||
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ai_composite();
|
||||
|
||||
|
||||
/**
|
||||
* Play the turn
|
||||
*/
|
||||
void play_turn();
|
||||
|
||||
|
||||
/**
|
||||
* get engine by cfg, creating it if it is not created yet but known
|
||||
*/
|
||||
virtual engine_ptr get_engine(const config& cfg);
|
||||
|
||||
|
||||
std::string describe_self();
|
||||
|
||||
|
||||
int get_recursion_count() const;
|
||||
|
||||
|
||||
void switch_side(side_number side);
|
||||
|
||||
|
||||
void on_create();
|
||||
|
||||
/**
|
||||
* unwrap
|
||||
*/
|
||||
virtual composite_ai_context& get_composite_ai_context();
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Stages of the composite AI
|
||||
*/
|
||||
std::vector< stage_ptr > stages_;
|
||||
|
||||
/**
|
||||
* Engines of the composite AI
|
||||
*/
|
||||
std::vector< engine_ptr > engines_;
|
||||
|
||||
|
||||
/**
|
||||
* Recursion counter
|
||||
*/
|
||||
recursion_counter recursion_counter_;
|
||||
};
|
||||
|
||||
} //end of namespace composite_ai
|
||||
|
||||
} //end of namespace ai
|
||||
|
||||
#endif
|
72
src/ai/composite/contexts.cpp
Normal file
72
src/ai/composite/contexts.cpp
Normal file
|
@ -0,0 +1,72 @@
|
|||
/* $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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Helper functions for the object which operates in the context of AI for specific side
|
||||
* This is part of AI interface
|
||||
* @file ai/composite/contexts.cpp
|
||||
*/
|
||||
|
||||
#include "contexts.hpp"
|
||||
|
||||
// =======================================================================
|
||||
namespace ai {
|
||||
|
||||
namespace composite_ai {
|
||||
|
||||
|
||||
composite_ai_context::composite_ai_context()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
composite_ai_context::~composite_ai_context()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
composite_ai_context_proxy::composite_ai_context_proxy()
|
||||
: target_()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
composite_ai_context_proxy::~composite_ai_context_proxy()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
rca_context::rca_context()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
rca_context::~rca_context()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
rca_context_proxy::rca_context_proxy()
|
||||
: target_()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
rca_context_proxy::~rca_context_proxy()
|
||||
{
|
||||
}
|
||||
|
||||
} //end of namespace composite_ai
|
||||
|
||||
} //end of namespace ai
|
185
src/ai/composite/contexts.hpp
Normal file
185
src/ai/composite/contexts.hpp
Normal file
|
@ -0,0 +1,185 @@
|
|||
/* $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/contexts.hpp
|
||||
* Composite AI contexts
|
||||
*/
|
||||
|
||||
#ifndef AI_COMPOSITE_CONTEXTS_HPP_INCLUDED
|
||||
#define AI_COMPOSITE_CONTEXTS_HPP_INCLUDED
|
||||
|
||||
#include "../../global.hpp"
|
||||
|
||||
#include "../contexts.hpp"
|
||||
#include "../default/contexts.hpp"
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <vector>
|
||||
|
||||
//============================================================================
|
||||
namespace ai {
|
||||
|
||||
namespace composite_ai {
|
||||
|
||||
class engine;
|
||||
|
||||
class stage;
|
||||
|
||||
class composite_ai_context;
|
||||
|
||||
typedef boost::shared_ptr< engine > engine_ptr;
|
||||
|
||||
typedef boost::shared_ptr< stage > stage_ptr;
|
||||
|
||||
class composite_ai_context : public virtual default_ai_context{
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
composite_ai_context();
|
||||
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~composite_ai_context();
|
||||
|
||||
|
||||
/**
|
||||
* Unwrap
|
||||
*/
|
||||
virtual composite_ai_context& get_composite_ai_context() = 0;
|
||||
|
||||
|
||||
/**
|
||||
* get engine by cfg, creating it if it is not created yet but known
|
||||
*/
|
||||
virtual engine_ptr get_engine(const config& cfg) = 0;
|
||||
};
|
||||
|
||||
|
||||
class rca_context;
|
||||
class rca_context : public virtual composite_ai_context {
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
rca_context();
|
||||
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~rca_context();
|
||||
|
||||
|
||||
/**
|
||||
* Unwrap
|
||||
*/
|
||||
virtual rca_context& get_rca_context() = 0;
|
||||
};
|
||||
|
||||
|
||||
class candidate_action_context;
|
||||
class candidate_action_context : public virtual rca_context {
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
candidate_action_context() {}
|
||||
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~candidate_action_context() {}
|
||||
|
||||
|
||||
/**
|
||||
* Unwrap
|
||||
*/
|
||||
virtual candidate_action_context& get_candidate_action_context() = 0;
|
||||
};
|
||||
|
||||
// proxies
|
||||
class composite_ai_context_proxy : public virtual composite_ai_context, public virtual default_ai_context_proxy {
|
||||
public:
|
||||
composite_ai_context_proxy();
|
||||
|
||||
|
||||
void init_composite_ai_context_proxy(composite_ai_context &target)
|
||||
{
|
||||
init_default_ai_context_proxy(target);
|
||||
target_ = ⌖
|
||||
}
|
||||
|
||||
|
||||
virtual ~composite_ai_context_proxy();
|
||||
|
||||
|
||||
composite_ai_context& get_composite_ai_context()
|
||||
{
|
||||
return target_->get_composite_ai_context();
|
||||
}
|
||||
|
||||
|
||||
engine_ptr get_engine(const config& cfg)
|
||||
{
|
||||
return target_->get_engine(cfg);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
composite_ai_context *target_;
|
||||
};
|
||||
|
||||
|
||||
class rca_context_proxy : public virtual rca_context, public virtual composite_ai_context_proxy {
|
||||
public:
|
||||
rca_context_proxy();
|
||||
|
||||
|
||||
virtual ~rca_context_proxy();
|
||||
|
||||
|
||||
void init_rca_context_proxy(rca_context &target)
|
||||
{
|
||||
init_composite_ai_context_proxy(target);
|
||||
target_ = ⌖
|
||||
}
|
||||
|
||||
|
||||
rca_context& get_rca_context()
|
||||
{
|
||||
return target_->get_rca_context();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
rca_context *target_;
|
||||
};
|
||||
|
||||
|
||||
} //end of namespace composite_ai
|
||||
|
||||
} //end of namespace ai
|
||||
|
||||
#endif
|
90
src/ai/composite/engine.cpp
Normal file
90
src/ai/composite/engine.cpp
Normal file
|
@ -0,0 +1,90 @@
|
|||
/* $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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* AI Support engine - creating specific ai components from config
|
||||
* @file ai/composite/engine.cpp
|
||||
*/
|
||||
|
||||
#include "ai.hpp"
|
||||
#include "engine.hpp"
|
||||
#include "../../foreach.hpp"
|
||||
#include "../../log.hpp"
|
||||
|
||||
namespace ai {
|
||||
|
||||
namespace composite_ai {
|
||||
|
||||
static lg::log_domain log_ai_composite_engine("ai/composite/engine");
|
||||
#define DBG_AI_COMPOSITE_ENGINE LOG_STREAM(debug, log_ai_composite_engine)
|
||||
#define LOG_AI_COMPOSITE_ENGINE LOG_STREAM(info, log_ai_composite_engine)
|
||||
#define ERR_AI_COMPOSITE_ENGINE LOG_STREAM(err, log_ai_composite_engine)
|
||||
|
||||
engine::engine( composite_ai_context &context, const config &cfg )
|
||||
: ai_(context)
|
||||
{
|
||||
LOG_AI_COMPOSITE_ENGINE << "side "<< ai_.get_side() << " : "<<" created engine with name=["<<cfg["name"]<<"]"<<std::endl;
|
||||
}
|
||||
|
||||
engine::~engine()
|
||||
{
|
||||
}
|
||||
|
||||
void engine::parse_candidate_action_from_config( rca_context& context, const config &cfg, std::back_insert_iterator<std::vector< candidate_action_ptr > > b )
|
||||
{
|
||||
engine_ptr eng = context.get_engine(cfg);
|
||||
if (eng){
|
||||
//do not override that method in subclasses which cannot create candidate actions
|
||||
eng->do_parse_candidate_action_from_config(context,cfg, b);
|
||||
}
|
||||
}
|
||||
|
||||
void engine::parse_engine_from_config( composite_ai_context &context, const config &cfg, std::back_insert_iterator<std::vector< engine_ptr > > b )
|
||||
{
|
||||
engine_ptr eng = context.get_engine(cfg);
|
||||
if (eng){
|
||||
//do not override that method in subclasses which cannot create engines
|
||||
eng->do_parse_engine_from_config(cfg, b);
|
||||
}
|
||||
}
|
||||
|
||||
void engine::parse_stage_from_config( composite_ai_context &context, const config &cfg, std::back_insert_iterator<std::vector< stage_ptr > > b )
|
||||
{
|
||||
engine_ptr eng = context.get_engine(cfg);
|
||||
if (eng){
|
||||
//do not override that method in subclasses which cannot create stages
|
||||
eng->do_parse_stage_from_config(cfg, b);
|
||||
}
|
||||
}
|
||||
|
||||
void engine::do_parse_candidate_action_from_config( rca_context &/*context*/, const config &/*cfg*/, std::back_insert_iterator<std::vector< candidate_action_ptr > > /*b*/ ){
|
||||
|
||||
}
|
||||
|
||||
void engine::do_parse_engine_from_config( const config &/*cfg*/, std::back_insert_iterator<std::vector< engine_ptr > > /*b*/ ){
|
||||
|
||||
}
|
||||
|
||||
void engine::do_parse_stage_from_config( const config &/*cfg*/, std::back_insert_iterator<std::vector< stage_ptr > > /*b*/ )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string engine::get_name(){
|
||||
return "null";
|
||||
}
|
||||
|
||||
} //end of namespace composite_ai
|
||||
|
||||
} //end of namespace ai
|
123
src/ai/composite/engine.hpp
Normal file
123
src/ai/composite/engine.hpp
Normal file
|
@ -0,0 +1,123 @@
|
|||
/* $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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* AI Support engine - creating specific ai components from config
|
||||
* @file ai/composite/engine.hpp
|
||||
*/
|
||||
|
||||
#ifndef AI_COMPOSITE_ENGINE_HPP_INCLUDED
|
||||
#define AI_COMPOSITE_ENGINE_HPP_INCLUDED
|
||||
|
||||
#include "../../global.hpp"
|
||||
|
||||
#include "contexts.hpp"
|
||||
#include "rca.hpp"
|
||||
#include "stage.hpp"
|
||||
#include "../../config.hpp"
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
//============================================================================
|
||||
|
||||
namespace ai {
|
||||
|
||||
namespace composite_ai {
|
||||
|
||||
class ai_composite;
|
||||
|
||||
|
||||
class engine {
|
||||
public:
|
||||
engine( composite_ai_context &context, const config &cfg );
|
||||
|
||||
virtual ~engine();
|
||||
|
||||
static void parse_candidate_action_from_config( rca_context &context, const config &cfg, std::back_insert_iterator<std::vector< candidate_action_ptr > > b );
|
||||
|
||||
static void parse_engine_from_config( composite_ai_context &context, const config &cfg, std::back_insert_iterator<std::vector< engine_ptr > > b );
|
||||
|
||||
static void parse_stage_from_config( composite_ai_context &context, const config &cfg, std::back_insert_iterator<std::vector< stage_ptr > > b );
|
||||
|
||||
//do not override that method in subclasses which cannot create candidate_actions
|
||||
virtual void do_parse_candidate_action_from_config( rca_context &context, const config &cfg, std::back_insert_iterator<std::vector< candidate_action_ptr > > b );
|
||||
|
||||
//do not override that method in subclasses which cannot create engines
|
||||
virtual void do_parse_engine_from_config( const config &cfg, std::back_insert_iterator<std::vector< engine_ptr > > b );
|
||||
|
||||
//do not override that method in subclasses which cannot create stages
|
||||
virtual void do_parse_stage_from_config( const config &cfg, std::back_insert_iterator<std::vector< stage_ptr > > b );
|
||||
|
||||
|
||||
virtual std::string get_name();
|
||||
|
||||
|
||||
protected:
|
||||
composite_ai_context &ai_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class engine_factory;
|
||||
|
||||
class engine_factory{
|
||||
public:
|
||||
typedef boost::shared_ptr< engine_factory > factory_ptr;
|
||||
typedef std::map<std::string, factory_ptr> factory_map;
|
||||
typedef std::pair<const std::string, factory_ptr> factory_map_pair;
|
||||
|
||||
static factory_map& get_list() {
|
||||
static factory_map *engine_factories;
|
||||
if (engine_factories==NULL) {
|
||||
engine_factories = new factory_map;
|
||||
}
|
||||
return *engine_factories;
|
||||
}
|
||||
|
||||
virtual engine_ptr get_new_instance( composite_ai_context &ai, const config &cfg ) = 0;
|
||||
virtual engine_ptr get_new_instance( composite_ai_context &ai, const std::string& name ) = 0;
|
||||
|
||||
engine_factory( const std::string &name )
|
||||
{
|
||||
factory_ptr ptr_to_this(this);
|
||||
get_list().insert(make_pair(name,ptr_to_this));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class ENGINE>
|
||||
class register_engine_factory : public engine_factory {
|
||||
public:
|
||||
register_engine_factory( const std::string &name )
|
||||
: engine_factory( name )
|
||||
{
|
||||
}
|
||||
|
||||
virtual engine_ptr get_new_instance( composite_ai_context &ai, const config &cfg ){
|
||||
return engine_ptr(new ENGINE(ai,cfg));
|
||||
}
|
||||
|
||||
virtual engine_ptr get_new_instance( composite_ai_context &ai, const std::string& name ){
|
||||
config cfg;
|
||||
cfg["name"] = name;
|
||||
return engine_ptr(new ENGINE(ai,cfg));
|
||||
}
|
||||
};
|
||||
|
||||
} //end of namespace composite_ai
|
||||
|
||||
} //end of namespace ai
|
||||
|
||||
#endif
|
87
src/ai/composite/engine_default.cpp
Normal file
87
src/ai/composite/engine_default.cpp
Normal file
|
@ -0,0 +1,87 @@
|
|||
/* $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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* CPP AI Support engine - creating specific ai components from config
|
||||
* @file ai/composite/engine_default.cpp
|
||||
*/
|
||||
|
||||
#include "ai.hpp"
|
||||
#include "engine_default.hpp"
|
||||
#include "rca.hpp"
|
||||
#include "../../foreach.hpp"
|
||||
#include "../../log.hpp"
|
||||
|
||||
namespace ai {
|
||||
|
||||
namespace composite_ai {
|
||||
|
||||
static lg::log_domain log_ai_composite_engine_cpp("ai/composite/engine/cpp");
|
||||
#define DBG_AI_COMPOSITE_ENGINE_CPP LOG_STREAM(debug, log_ai_composite_engine_cpp)
|
||||
#define LOG_AI_COMPOSITE_ENGINE_CPP LOG_STREAM(info, log_ai_composite_engine_cpp)
|
||||
#define ERR_AI_COMPOSITE_ENGINE_CPP LOG_STREAM(err, log_ai_composite_engine_cpp)
|
||||
|
||||
engine_cpp::engine_cpp( composite_ai_context &context, const config &cfg )
|
||||
: engine(context,cfg)
|
||||
{
|
||||
}
|
||||
|
||||
engine_cpp::~engine_cpp()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void engine_cpp::do_parse_candidate_action_from_config( rca_context &context, const config &cfg, std::back_insert_iterator<std::vector< candidate_action_ptr > > b ){
|
||||
candidate_action_factory::factory_map::iterator f = candidate_action_factory::get_list().find(cfg["name"]);
|
||||
if (f == candidate_action_factory::get_list().end()){
|
||||
ERR_AI_COMPOSITE_ENGINE_CPP << "side "<<ai_.get_side()<< " : UNKNOWN candidate_action["<<cfg["name"]<<"]"<< std::endl;
|
||||
DBG_AI_COMPOSITE_ENGINE_CPP << "config snippet contains: " << std::endl << cfg << std::endl;
|
||||
return;
|
||||
}
|
||||
candidate_action_ptr new_candidate_action = f->second->get_new_instance(context,cfg);
|
||||
if (!new_candidate_action) {
|
||||
ERR_AI_COMPOSITE_ENGINE_CPP << "side "<<ai_.get_side()<< " : UNABLE TO CREATE candidate_action["<<cfg["name"]<<"]"<< std::endl;
|
||||
DBG_AI_COMPOSITE_ENGINE_CPP << "config snippet contains: " << std::endl << cfg << std::endl;
|
||||
return;
|
||||
}
|
||||
*b = new_candidate_action;
|
||||
|
||||
}
|
||||
|
||||
void engine_cpp::do_parse_stage_from_config( const config &cfg, std::back_insert_iterator<std::vector< stage_ptr > > b )
|
||||
{
|
||||
stage_factory::factory_map::iterator f = stage_factory::get_list().find(cfg["name"]);
|
||||
if (f == stage_factory::get_list().end()){
|
||||
ERR_AI_COMPOSITE_ENGINE_CPP << "side "<<ai_.get_side()<< " : UNKNOWN stage["<<cfg["name"]<<"]"<< std::endl;
|
||||
DBG_AI_COMPOSITE_ENGINE_CPP << "config snippet contains: " << std::endl << cfg << std::endl;
|
||||
return;
|
||||
}
|
||||
stage_ptr new_stage = f->second->get_new_instance(ai_,cfg);
|
||||
if (!new_stage) {
|
||||
ERR_AI_COMPOSITE_ENGINE_CPP << "side "<<ai_.get_side()<< " : UNABLE TO CREATE stage["<<cfg["name"]<<"]"<< std::endl;
|
||||
DBG_AI_COMPOSITE_ENGINE_CPP << "config snippet contains: " << std::endl << cfg << std::endl;
|
||||
return;
|
||||
}
|
||||
*b = new_stage;
|
||||
}
|
||||
|
||||
|
||||
std::string engine_cpp::get_name()
|
||||
{
|
||||
return "cpp";
|
||||
}
|
||||
|
||||
} //end of namespace composite_ai
|
||||
|
||||
} //end of namespace ai
|
52
src/ai/composite/engine_default.hpp
Normal file
52
src/ai/composite/engine_default.hpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
/* $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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* CPP AI Support engine - creating specific ai components from config
|
||||
* @file ai/composite/engine_default.hpp
|
||||
*/
|
||||
|
||||
#ifndef AI_COMPOSITE_ENGINE_DEFAULT_HPP_INCLUDED
|
||||
#define AI_COMPOSITE_ENGINE_DEFAULT_HPP_INCLUDED
|
||||
|
||||
#include "../../global.hpp"
|
||||
|
||||
#include "engine.hpp"
|
||||
#include "../contexts.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
//============================================================================
|
||||
namespace ai {
|
||||
|
||||
namespace composite_ai {
|
||||
|
||||
class engine_cpp : public engine {
|
||||
public:
|
||||
engine_cpp( composite_ai_context &context, const config &cfg );
|
||||
|
||||
virtual ~engine_cpp();
|
||||
|
||||
virtual void do_parse_candidate_action_from_config( rca_context &context, const config &cfg, std::back_insert_iterator<std::vector< candidate_action_ptr > > b );
|
||||
|
||||
virtual void do_parse_stage_from_config( const config &cfg, std::back_insert_iterator<std::vector< stage_ptr > > b );
|
||||
|
||||
|
||||
virtual std::string get_name();
|
||||
};
|
||||
|
||||
} //end of namespace composite_ai
|
||||
|
||||
} //end of namespace ai
|
||||
|
||||
#endif
|
138
src/ai/composite/rca.cpp
Normal file
138
src/ai/composite/rca.cpp
Normal file
|
@ -0,0 +1,138 @@
|
|||
/* $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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Candidate actions framework
|
||||
* @file ai/composite/rca.cpp
|
||||
*/
|
||||
|
||||
#include "ai.hpp"
|
||||
#include "engine.hpp"
|
||||
#include "rca.hpp"
|
||||
#include "../../foreach.hpp"
|
||||
#include "../../log.hpp"
|
||||
|
||||
namespace ai {
|
||||
|
||||
namespace composite_ai {
|
||||
|
||||
static lg::log_domain log_ai_composite_rca("ai/composite/rca");
|
||||
#define DBG_AI_COMPOSITE_RCA LOG_STREAM(debug, log_ai_composite_rca)
|
||||
#define LOG_AI_COMPOSITE_RCA LOG_STREAM(info, log_ai_composite_rca)
|
||||
#define ERR_AI_COMPOSITE_RCA LOG_STREAM(err, log_ai_composite_rca)
|
||||
|
||||
|
||||
candidate_action::candidate_action(rca_context &context, const std::string &name, const std::string &type)
|
||||
: recursion_counter_(context.get_recursion_count()), enabled_(true), score_(BAD_SCORE),name_(name),type_(type)
|
||||
{
|
||||
init_rca_context_proxy(context);
|
||||
//LOG_AI_COMPOSITE_RCA << "side "<< get_side() << " : "<<" created "<<*this<<std::endl;
|
||||
}
|
||||
|
||||
candidate_action::~candidate_action()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool candidate_action::is_enabled() const
|
||||
{
|
||||
return enabled_;
|
||||
}
|
||||
|
||||
|
||||
void candidate_action::enable()
|
||||
{
|
||||
enabled_ = true;
|
||||
}
|
||||
|
||||
int candidate_action::get_recursion_count() const
|
||||
{
|
||||
return recursion_counter_.get_count();
|
||||
}
|
||||
|
||||
void candidate_action::disable()
|
||||
{
|
||||
enabled_ = false;
|
||||
}
|
||||
|
||||
|
||||
double candidate_action::get_score() const
|
||||
{
|
||||
return score_;
|
||||
}
|
||||
|
||||
|
||||
const std::string& candidate_action::get_name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
|
||||
const std::string& candidate_action::get_type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
candidate_action_evaluation_exception::candidate_action_evaluation_exception(const std::string &message)
|
||||
: message_(message)
|
||||
{
|
||||
}
|
||||
|
||||
candidate_action_execution_exception::candidate_action_execution_exception(const std::string &message)
|
||||
: message_(message)
|
||||
{
|
||||
}
|
||||
|
||||
candidate_action_evaluation_exception::~candidate_action_evaluation_exception()
|
||||
{
|
||||
}
|
||||
|
||||
candidate_action_execution_exception::~candidate_action_execution_exception()
|
||||
{
|
||||
}
|
||||
|
||||
const std::string& candidate_action_evaluation_exception::get_message() const
|
||||
{
|
||||
return message_;
|
||||
}
|
||||
|
||||
const std::string& candidate_action_execution_exception::get_message() const
|
||||
{
|
||||
return message_;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
} //end of namespace composite_ai
|
||||
|
||||
} // of namespace ai
|
||||
|
||||
|
||||
std::ostream &operator<<(std::ostream &s, ai::composite_ai::candidate_action_evaluation_exception const &caee) {
|
||||
s << "candidate action evaluation exception :"<< caee.get_message();
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
std::ostream &operator<<(std::ostream &s, ai::composite_ai::candidate_action_execution_exception const &caee) {
|
||||
s << "candidate action execution exception :"<< caee.get_message();
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
std::ostream &operator<<(std::ostream &s, ai::composite_ai::candidate_action const &ca) {
|
||||
s << "candidate action with name ["<< ca.get_name() <<"]";
|
||||
return s;
|
||||
}
|
||||
|
193
src/ai/composite/rca.hpp
Normal file
193
src/ai/composite/rca.hpp
Normal file
|
@ -0,0 +1,193 @@
|
|||
/* $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/rca.hpp
|
||||
* candidate action framework
|
||||
*/
|
||||
|
||||
#ifndef AI_COMPOSITE_RCA_HPP_INCLUDED
|
||||
#define AI_COMPOSITE_RCA_HPP_INCLUDED
|
||||
|
||||
#include "../../global.hpp"
|
||||
|
||||
#include "../../config.hpp"
|
||||
|
||||
#include "contexts.hpp"
|
||||
#include "../contexts.hpp"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
//============================================================================
|
||||
namespace ai {
|
||||
|
||||
namespace composite_ai {
|
||||
|
||||
class candidate_action : public virtual rca_context_proxy {
|
||||
public:
|
||||
//this is a score guaranteed to be <=0, thus candidate action with this score will not be selected for execution
|
||||
static const double BAD_SCORE = 0;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param ai context of the candidate action
|
||||
* @param name name of the action (for debug purposes)
|
||||
* @param type type of the action (for debug purposes)
|
||||
*/
|
||||
candidate_action( rca_context &context, const std::string &name, const std::string &type );
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~candidate_action();
|
||||
|
||||
|
||||
/**
|
||||
* Evaluate the candidate action, resetting the internal state of the action
|
||||
* @return the score
|
||||
* @retval >0 if the action is good
|
||||
* @retval <0 if the action is not good
|
||||
*/
|
||||
virtual double evaluate() = 0;
|
||||
|
||||
/**
|
||||
* Execute the candidate action
|
||||
*/
|
||||
virtual bool execute() = 0;
|
||||
|
||||
/**
|
||||
* Is this candidate action enabled ?
|
||||
*/
|
||||
bool is_enabled() const;
|
||||
|
||||
/**
|
||||
* Disable the candidate action
|
||||
*/
|
||||
void enable();
|
||||
|
||||
/**
|
||||
* Enable the candidate action
|
||||
*/
|
||||
void disable();
|
||||
|
||||
/**
|
||||
* Get the last score of the candidate action without re-evaluation
|
||||
*/
|
||||
double get_score() const;
|
||||
|
||||
/**
|
||||
* Get the name of the candidate action (useful for debug purposes)
|
||||
*/
|
||||
const std::string& get_name() const;
|
||||
|
||||
/**
|
||||
* Get the type of the candidate action (useful for debug purposes)
|
||||
*/
|
||||
const std::string& get_type() const;
|
||||
|
||||
int get_recursion_count() const;
|
||||
private:
|
||||
|
||||
recursion_counter recursion_counter_;
|
||||
|
||||
bool enabled_;
|
||||
|
||||
double score_;
|
||||
|
||||
std::string name_;
|
||||
|
||||
std::string type_;
|
||||
|
||||
};
|
||||
|
||||
class candidate_action_evaluation_exception{
|
||||
public:
|
||||
candidate_action_evaluation_exception(const std::string& message);
|
||||
|
||||
~candidate_action_evaluation_exception();
|
||||
|
||||
// get the message associated with this exception
|
||||
const std::string& get_message() const;
|
||||
private:
|
||||
std::string message_;
|
||||
};
|
||||
|
||||
|
||||
class candidate_action_execution_exception{
|
||||
public:
|
||||
candidate_action_execution_exception(const std::string& message);
|
||||
|
||||
~candidate_action_execution_exception();
|
||||
|
||||
// get the message associated with this exception
|
||||
const std::string& get_message() const;
|
||||
private:
|
||||
std::string message_;
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<candidate_action> candidate_action_ptr;
|
||||
|
||||
class candidate_action_factory;
|
||||
|
||||
class candidate_action_factory{
|
||||
public:
|
||||
typedef boost::shared_ptr< candidate_action_factory > factory_ptr;
|
||||
typedef std::map<std::string, factory_ptr> factory_map;
|
||||
typedef std::pair<const std::string, factory_ptr> factory_map_pair;
|
||||
|
||||
static factory_map& get_list() {
|
||||
static factory_map *candidate_action_factories;
|
||||
if (candidate_action_factories==NULL) {
|
||||
candidate_action_factories = new factory_map;
|
||||
}
|
||||
return *candidate_action_factories;
|
||||
}
|
||||
|
||||
virtual candidate_action_ptr get_new_instance( rca_context &context, const config &cfg ) = 0;
|
||||
|
||||
candidate_action_factory( const std::string &name )
|
||||
{
|
||||
factory_ptr ptr_to_this(this);
|
||||
get_list().insert(make_pair(name,ptr_to_this));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class CANDIDATE_ACTION>
|
||||
class register_candidate_action_factory : public candidate_action_factory {
|
||||
public:
|
||||
register_candidate_action_factory( const std::string &name )
|
||||
: candidate_action_factory( name )
|
||||
{
|
||||
}
|
||||
|
||||
virtual candidate_action_ptr get_new_instance( rca_context &ai, const config &cfg ){
|
||||
return candidate_action_ptr(new CANDIDATE_ACTION(ai,cfg));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//============================================================================
|
||||
} //end of namespace composite_ai
|
||||
|
||||
} //end of namespace ai
|
||||
|
||||
std::ostream &operator<<(std::ostream &s, ai::composite_ai::candidate_action const &ca);
|
||||
|
||||
std::ostream &operator<<(std::ostream &s, ai::composite_ai::candidate_action_evaluation_exception const &caee);
|
||||
|
||||
std::ostream &operator<<(std::ostream &s, ai::composite_ai::candidate_action_execution_exception const &caee);
|
||||
|
||||
#endif
|
86
src/ai/composite/stage.cpp
Normal file
86
src/ai/composite/stage.cpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
/* $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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Stage of a composite AI
|
||||
* @file ai/composite/stage.cpp
|
||||
*/
|
||||
|
||||
#include "ai.hpp"
|
||||
#include "stage.hpp"
|
||||
#include "../contexts.hpp"
|
||||
#include "../../foreach.hpp"
|
||||
#include "../../log.hpp"
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace ai {
|
||||
|
||||
namespace composite_ai {
|
||||
|
||||
static lg::log_domain log_ai_composite_stage("ai/composite/stage");
|
||||
#define DBG_AI_COMPOSITE_STAGE LOG_STREAM(debug, log_ai_composite_stage)
|
||||
#define LOG_AI_COMPOSITE_STAGE LOG_STREAM(info, log_ai_composite_stage)
|
||||
#define ERR_AI_COMPOSITE_STAGE LOG_STREAM(err, log_ai_composite_stage)
|
||||
|
||||
// =======================================================================
|
||||
// COMPOSITE AI STAGE
|
||||
// =======================================================================
|
||||
|
||||
stage::stage( composite_ai_context &context, const config &cfg )
|
||||
: recursion_counter_(context.get_recursion_count()), cfg_(cfg)
|
||||
{
|
||||
init_composite_ai_context_proxy(context);
|
||||
}
|
||||
|
||||
void stage::on_create()
|
||||
{
|
||||
LOG_AI_COMPOSITE_STAGE << "side "<< get_side() << " : "<<" created stage with name=["<<cfg_["name"]<<"]"<<std::endl;
|
||||
}
|
||||
|
||||
stage::~stage()
|
||||
{
|
||||
}
|
||||
|
||||
void stage::play_stage()
|
||||
{
|
||||
do_play_stage();
|
||||
}
|
||||
|
||||
int stage::get_recursion_count() const
|
||||
{
|
||||
return recursion_counter_.get_count();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// COMPOSITE AI IDLE STAGE
|
||||
// =======================================================================
|
||||
|
||||
|
||||
idle_stage::idle_stage( composite_ai_context &context, const config &cfg )
|
||||
: stage(context,cfg)
|
||||
{
|
||||
}
|
||||
|
||||
idle_stage::~idle_stage()
|
||||
{
|
||||
}
|
||||
|
||||
void idle_stage::do_play_stage(){
|
||||
LOG_AI_COMPOSITE_STAGE << "Turn " << get_info().state.turn() << ": playing idle stage for side: "<< get_side() << std::endl;
|
||||
}
|
||||
|
||||
} //end of namespace composite_ai
|
||||
|
||||
} //end of namespace ai
|
137
src/ai/composite/stage.hpp
Normal file
137
src/ai/composite/stage.hpp
Normal file
|
@ -0,0 +1,137 @@
|
|||
/* $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/stage.hpp
|
||||
* Composite AI stages
|
||||
*/
|
||||
|
||||
#ifndef AI_COMPOSITE_STAGE_HPP_INCLUDED
|
||||
#define AI_COMPOSITE_STAGE_HPP_INCLUDED
|
||||
|
||||
#include "../../global.hpp"
|
||||
|
||||
#include "contexts.hpp"
|
||||
#include "../contexts.hpp"
|
||||
#include "../../config.hpp"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace ai {
|
||||
|
||||
namespace composite_ai {
|
||||
|
||||
class ai_composite;
|
||||
|
||||
class stage : public virtual composite_ai_context_proxy {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
stage( composite_ai_context &context, const config &cfg );
|
||||
|
||||
/**
|
||||
* Initialization
|
||||
*/
|
||||
virtual void on_create();
|
||||
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~stage();
|
||||
|
||||
/**
|
||||
* Play the turn - strategy
|
||||
*/
|
||||
void play_stage();
|
||||
|
||||
|
||||
/**
|
||||
* get the value of the recursion counter
|
||||
*/
|
||||
int get_recursion_count() const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Play the turn - implementation
|
||||
*/
|
||||
virtual void do_play_stage() = 0;
|
||||
|
||||
recursion_counter recursion_counter_;
|
||||
|
||||
const config &cfg_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class idle_stage : public stage {
|
||||
|
||||
idle_stage( composite_ai_context &context, const config &cfg );
|
||||
|
||||
~idle_stage();
|
||||
|
||||
virtual void do_play_stage();
|
||||
};
|
||||
|
||||
|
||||
class stage_factory;
|
||||
|
||||
class stage_factory{
|
||||
public:
|
||||
typedef boost::shared_ptr< stage_factory > factory_ptr;
|
||||
typedef std::map<std::string, factory_ptr> factory_map;
|
||||
typedef std::pair<const std::string, factory_ptr> factory_map_pair;
|
||||
|
||||
static factory_map& get_list() {
|
||||
static factory_map *stage_factories;
|
||||
if (stage_factories==NULL) {
|
||||
stage_factories = new factory_map;
|
||||
}
|
||||
return *stage_factories;
|
||||
}
|
||||
|
||||
virtual stage_ptr get_new_instance( composite_ai_context &context, const config &cfg ) = 0;
|
||||
|
||||
stage_factory( const std::string &name )
|
||||
{
|
||||
factory_ptr ptr_to_this(this);
|
||||
get_list().insert(make_pair(name,ptr_to_this));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class STAGE>
|
||||
class register_stage_factory : public stage_factory {
|
||||
public:
|
||||
register_stage_factory( const std::string &name )
|
||||
: stage_factory( name )
|
||||
{
|
||||
}
|
||||
|
||||
virtual stage_ptr get_new_instance( composite_ai_context &context, const config &cfg ){
|
||||
stage_ptr a(new STAGE(context,cfg));
|
||||
a->on_create();
|
||||
return a;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} //end of namespace composite_ai
|
||||
|
||||
} //end of namespace ai
|
||||
|
||||
#endif
|
|
@ -31,11 +31,6 @@ class gamemap;
|
|||
#include "../pathfind.hpp"
|
||||
#include "../playturn.hpp"
|
||||
|
||||
class ai_attack_result;
|
||||
class ai_move_result;
|
||||
class ai_recruit_result;
|
||||
class ai_stopunit_result;
|
||||
|
||||
namespace ai {
|
||||
|
||||
// recursion counter
|
||||
|
@ -49,12 +44,30 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
int get_count() const{
|
||||
|
||||
/**
|
||||
* Get the current value of the recursion counter
|
||||
*/
|
||||
int get_count() const
|
||||
{
|
||||
return counter_;
|
||||
}
|
||||
|
||||
static const int MAX_COUNTER_VALUE = 100;//max recursion depth
|
||||
|
||||
//max recursion depth
|
||||
static const int MAX_COUNTER_VALUE = 100;
|
||||
|
||||
|
||||
/**
|
||||
* Check if more recursion is allowed
|
||||
*/
|
||||
bool is_ok() const
|
||||
{
|
||||
return counter_ < MAX_COUNTER_VALUE;
|
||||
}
|
||||
private:
|
||||
|
||||
// recursion counter value
|
||||
int counter_;
|
||||
};
|
||||
|
||||
|
@ -64,13 +77,42 @@ class side_context;
|
|||
|
||||
class side_context{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Get the side number
|
||||
*/
|
||||
virtual side_number get_side() const = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Set the side number
|
||||
*/
|
||||
virtual void set_side(side_number side) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* empty destructor
|
||||
*/
|
||||
virtual ~side_context(){}
|
||||
|
||||
|
||||
/**
|
||||
* empty constructor
|
||||
*/
|
||||
side_context() {}
|
||||
|
||||
|
||||
/**
|
||||
* unwrap
|
||||
*/
|
||||
virtual side_context& get_side_context() = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of the recursion counter
|
||||
*/
|
||||
virtual int get_recursion_count() const = 0;
|
||||
|
||||
};
|
||||
|
||||
class readonly_context;
|
||||
|
@ -121,180 +163,253 @@ public:
|
|||
virtual ai_game_info& get_info_w() = 0;
|
||||
};
|
||||
|
||||
class ai_default_context;
|
||||
class ai_default_context : public virtual readwrite_context {
|
||||
public:
|
||||
ai_default_context(){}
|
||||
virtual ~ai_default_context(){}
|
||||
virtual ai_default_context& get_ai_default_context() = 0;
|
||||
};
|
||||
|
||||
|
||||
//proxies
|
||||
|
||||
class side_context_proxy : public virtual side_context {
|
||||
public:
|
||||
side_context_proxy(side_context& target)
|
||||
:target_(target.get_side_context())
|
||||
side_context_proxy()
|
||||
: target_(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~side_context_proxy(){}
|
||||
|
||||
|
||||
void init_side_context_proxy(side_context &target)
|
||||
{
|
||||
target_= &target.get_side_context();
|
||||
}
|
||||
|
||||
virtual side_number get_side() const
|
||||
{
|
||||
return target_.get_side();
|
||||
return target_->get_side();
|
||||
}
|
||||
|
||||
virtual void set_side(side_number side)
|
||||
{
|
||||
return target_.set_side(side);
|
||||
return target_->set_side(side);
|
||||
}
|
||||
|
||||
virtual side_context& get_side_context()
|
||||
{
|
||||
return target_.get_side_context();
|
||||
return target_->get_side_context();
|
||||
}
|
||||
|
||||
virtual int get_recursion_count(){
|
||||
return target_.get_recursion_count();
|
||||
return target_->get_recursion_count();
|
||||
}
|
||||
|
||||
private:
|
||||
side_context& target_;
|
||||
side_context *target_;
|
||||
};
|
||||
|
||||
|
||||
class readonly_context_proxy : public virtual readonly_context, public virtual side_context_proxy {
|
||||
public:
|
||||
readonly_context_proxy(readonly_context &target)
|
||||
: side_context_proxy(target.get_side_context()), target_(target.get_readonly_context())
|
||||
readonly_context_proxy()
|
||||
: target_(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~readonly_context_proxy() {}
|
||||
|
||||
void init_readonly_context_proxy(readonly_context &target)
|
||||
{
|
||||
init_side_context_proxy(target);
|
||||
target_ = &target.get_readonly_context();
|
||||
}
|
||||
|
||||
virtual readonly_context& get_readonly_context()
|
||||
{
|
||||
return target_.get_readonly_context();
|
||||
return target_->get_readonly_context();
|
||||
}
|
||||
|
||||
virtual const team& current_team() const{
|
||||
return target_.current_team();
|
||||
virtual const team& current_team() const
|
||||
{
|
||||
return target_->current_team();
|
||||
}
|
||||
|
||||
virtual void diagnostic(const std::string& msg){
|
||||
target_.diagnostic(msg);
|
||||
virtual void diagnostic(const std::string& msg)
|
||||
{
|
||||
target_->diagnostic(msg);
|
||||
}
|
||||
|
||||
virtual void log_message(const std::string& msg){
|
||||
target_.log_message(msg);
|
||||
virtual void log_message(const std::string& msg)
|
||||
{
|
||||
target_->log_message(msg);
|
||||
}
|
||||
|
||||
virtual ai_attack_result_ptr check_attack_action(const map_location &attacker_loc, const map_location &defender_loc, int attacker_weapon) {
|
||||
return target_.check_attack_action(attacker_loc, defender_loc, attacker_weapon);
|
||||
virtual ai_attack_result_ptr check_attack_action(const map_location &attacker_loc, const map_location &defender_loc, int attacker_weapon)
|
||||
{
|
||||
return target_->check_attack_action(attacker_loc, defender_loc, attacker_weapon);
|
||||
}
|
||||
|
||||
virtual ai_move_result_ptr check_move_action(const map_location &from, const map_location &to, bool remove_movement=true){
|
||||
return target_.check_move_action(from, to, remove_movement);
|
||||
virtual ai_move_result_ptr check_move_action(const map_location &from, const map_location &to, bool remove_movement=true)
|
||||
{
|
||||
return target_->check_move_action(from, to, remove_movement);
|
||||
}
|
||||
|
||||
virtual ai_recruit_result_ptr check_recruit_action(const std::string &unit_name, const map_location &where = map_location::null_location){
|
||||
return target_.check_recruit_action(unit_name, where);
|
||||
virtual ai_recruit_result_ptr check_recruit_action(const std::string &unit_name, const map_location &where = map_location::null_location)
|
||||
{
|
||||
return target_->check_recruit_action(unit_name, where);
|
||||
}
|
||||
|
||||
virtual ai_stopunit_result_ptr check_stopunit_action(const map_location &unit_location, bool remove_movement = true, bool remove_attacks = false){
|
||||
return target_.check_stopunit_action(unit_location, remove_movement, remove_attacks);
|
||||
virtual ai_stopunit_result_ptr check_stopunit_action(const map_location &unit_location, bool remove_movement = true, bool remove_attacks = false)
|
||||
{
|
||||
return target_->check_stopunit_action(unit_location, remove_movement, remove_attacks);
|
||||
}
|
||||
|
||||
virtual void calculate_possible_moves(std::map<map_location,paths>& possible_moves,
|
||||
move_map& srcdst, move_map& dstsrc, bool enemy,
|
||||
bool assume_full_movement=false,
|
||||
const std::set<map_location>* remove_destinations=NULL) const{
|
||||
target_.calculate_possible_moves(possible_moves, srcdst, dstsrc, enemy, assume_full_movement, remove_destinations);
|
||||
const std::set<map_location>* remove_destinations=NULL) const
|
||||
{
|
||||
target_->calculate_possible_moves(possible_moves, srcdst, dstsrc, enemy, assume_full_movement, remove_destinations);
|
||||
}
|
||||
|
||||
virtual void calculate_moves(const unit_map& units,
|
||||
std::map<map_location,paths>& possible_moves, move_map& srcdst,
|
||||
move_map& dstsrc, bool enemy, bool assume_full_movement=false,
|
||||
const std::set<map_location>* remove_destinations=NULL,
|
||||
bool see_all=false) const{
|
||||
target_.calculate_moves(units, possible_moves, srcdst, dstsrc, enemy, assume_full_movement, remove_destinations, see_all);
|
||||
bool see_all=false) const
|
||||
{
|
||||
target_->calculate_moves(units, possible_moves, srcdst, dstsrc, enemy, assume_full_movement, remove_destinations, see_all);
|
||||
}
|
||||
|
||||
const virtual ai_game_info& get_info() const{
|
||||
return target_.get_info();
|
||||
const virtual ai_game_info& get_info() const
|
||||
{
|
||||
return target_->get_info();
|
||||
}
|
||||
|
||||
virtual void raise_user_interact() const{
|
||||
target_.raise_user_interact();
|
||||
virtual void raise_user_interact() const
|
||||
{
|
||||
target_->raise_user_interact();
|
||||
}
|
||||
|
||||
virtual int get_recursion_count(){
|
||||
return target_.get_recursion_count();
|
||||
virtual int get_recursion_count() const
|
||||
{
|
||||
return target_->get_recursion_count();
|
||||
}
|
||||
|
||||
private:
|
||||
readonly_context& target_;
|
||||
readonly_context *target_;
|
||||
};
|
||||
|
||||
|
||||
class readwrite_context_proxy : public virtual readwrite_context, public virtual readonly_context_proxy {
|
||||
public:
|
||||
readwrite_context_proxy(readwrite_context &target)
|
||||
: side_context_proxy(target.get_side_context()), readonly_context_proxy(target.get_readonly_context()),target_(target.get_readwrite_context())
|
||||
readwrite_context_proxy()
|
||||
: target_(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void init_readwrite_context_proxy(readwrite_context &target)
|
||||
{
|
||||
init_readonly_context_proxy(target);
|
||||
target_ = &target.get_readwrite_context();
|
||||
}
|
||||
|
||||
|
||||
virtual readwrite_context& get_readwrite_context()
|
||||
{
|
||||
return target_.get_readwrite_context();
|
||||
return target_->get_readwrite_context();
|
||||
}
|
||||
virtual ai_attack_result_ptr execute_attack_action(const map_location& attacker_loc, const map_location& defender_loc, int attacker_weapon){
|
||||
return target_.execute_attack_action(attacker_loc,defender_loc,attacker_weapon);
|
||||
|
||||
|
||||
virtual ai_attack_result_ptr execute_attack_action(const map_location& attacker_loc, const map_location& defender_loc, int attacker_weapon)
|
||||
{
|
||||
return target_->execute_attack_action(attacker_loc,defender_loc,attacker_weapon);
|
||||
}
|
||||
|
||||
|
||||
virtual ai_move_result_ptr execute_move_action(const map_location& from, const map_location& to, bool remove_movement=true)
|
||||
{
|
||||
return target_.execute_move_action(from, to, remove_movement);
|
||||
}
|
||||
virtual ai_recruit_result_ptr execute_recruit_action(const std::string& unit_name, const map_location &where = map_location::null_location){
|
||||
return target_.execute_recruit_action(unit_name,where);
|
||||
}
|
||||
virtual ai_stopunit_result_ptr execute_stopunit_action(const map_location& unit_location, bool remove_movement = true, bool remove_attacks = false){
|
||||
return target_.execute_stopunit_action(unit_location,remove_movement,remove_attacks);
|
||||
return target_->execute_move_action(from, to, remove_movement);
|
||||
}
|
||||
|
||||
virtual team& current_team_w(){
|
||||
return target_.current_team_w();
|
||||
|
||||
virtual ai_recruit_result_ptr execute_recruit_action(const std::string& unit_name, const map_location &where = map_location::null_location)
|
||||
{
|
||||
return target_->execute_recruit_action(unit_name,where);
|
||||
}
|
||||
|
||||
virtual void attack_enemy(const map_location u, const map_location target, int att_weapon, int def_weapon){
|
||||
target_.attack_enemy(u, target, att_weapon, def_weapon);
|
||||
|
||||
virtual ai_stopunit_result_ptr execute_stopunit_action(const map_location& unit_location, bool remove_movement = true, bool remove_attacks = false)
|
||||
{
|
||||
return target_->execute_stopunit_action(unit_location,remove_movement,remove_attacks);
|
||||
}
|
||||
|
||||
virtual map_location move_unit(map_location from, map_location to, std::map<map_location,paths>& possible_moves){
|
||||
return target_.move_unit(from, to, possible_moves);
|
||||
|
||||
virtual team& current_team_w()
|
||||
{
|
||||
return target_->current_team_w();
|
||||
}
|
||||
|
||||
virtual map_location move_unit_partial(map_location from, map_location to, std::map<map_location,paths>& possible_moves){
|
||||
return target_.move_unit_partial(from, to, possible_moves);
|
||||
|
||||
virtual void attack_enemy(const map_location u, const map_location target, int att_weapon, int def_weapon)
|
||||
{
|
||||
target_->attack_enemy(u, target, att_weapon, def_weapon);
|
||||
}
|
||||
|
||||
virtual bool recruit(const std::string& unit_name, map_location loc=map_location()){
|
||||
return target_.recruit(unit_name, loc);
|
||||
}
|
||||
virtual void raise_unit_recruited() const{
|
||||
target_.raise_unit_recruited();
|
||||
|
||||
virtual map_location move_unit(map_location from, map_location to, std::map<map_location,paths>& possible_moves)
|
||||
{
|
||||
return target_->move_unit(from, to, possible_moves);
|
||||
}
|
||||
|
||||
virtual void raise_unit_moved() const{
|
||||
target_.raise_unit_moved();
|
||||
|
||||
virtual map_location move_unit_partial(map_location from, map_location to, std::map<map_location,paths>& possible_moves)
|
||||
{
|
||||
return target_->move_unit_partial(from, to, possible_moves);
|
||||
}
|
||||
|
||||
virtual void raise_enemy_attacked() const{
|
||||
target_.raise_enemy_attacked();
|
||||
}
|
||||
virtual ai_game_info& get_info_w() {
|
||||
return target_.get_info_w();
|
||||
|
||||
virtual bool recruit(const std::string& unit_name, map_location loc=map_location())
|
||||
{
|
||||
return target_->recruit(unit_name, loc);
|
||||
}
|
||||
|
||||
virtual int get_recursion_count(){
|
||||
return target_.get_recursion_count();
|
||||
|
||||
virtual void raise_unit_recruited() const
|
||||
{
|
||||
target_->raise_unit_recruited();
|
||||
}
|
||||
|
||||
|
||||
virtual void raise_unit_moved() const
|
||||
{
|
||||
target_->raise_unit_moved();
|
||||
}
|
||||
|
||||
|
||||
virtual void raise_enemy_attacked() const
|
||||
{
|
||||
target_->raise_enemy_attacked();
|
||||
}
|
||||
|
||||
|
||||
virtual ai_game_info& get_info_w()
|
||||
{
|
||||
return target_->get_info_w();
|
||||
}
|
||||
|
||||
|
||||
virtual int get_recursion_count()
|
||||
{
|
||||
return target_->get_recursion_count();
|
||||
}
|
||||
private:
|
||||
readwrite_context& target_;
|
||||
readwrite_context *target_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -336,30 +451,41 @@ private:
|
|||
//@todo: public game_logic::formula_callable
|
||||
class readonly_context_impl : public virtual side_context_proxy, public readonly_context {
|
||||
public:
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
* Constructor
|
||||
*/
|
||||
readonly_context_impl( side_context &context )
|
||||
: side_context_proxy(context), recursion_counter_(context.get_recursion_count())
|
||||
readonly_context_impl(side_context &context)
|
||||
: recursion_counter_(context.get_recursion_count())
|
||||
{
|
||||
//add_ref(); //this class shouldn't be reference counted.
|
||||
init_side_context_proxy(context);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~readonly_context_impl() {}
|
||||
|
||||
|
||||
/**
|
||||
* Unwrap - this class is not a proxy, so return *this
|
||||
:w
|
||||
*/
|
||||
virtual readonly_context& get_readonly_context()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/** Return a reference to the 'team' object for the AI. */
|
||||
const team& current_team() const { return get_info().teams[get_side()-1]; }
|
||||
|
||||
|
||||
/** Show a diagnostic message on the screen. */
|
||||
void diagnostic(const std::string& msg);
|
||||
|
||||
|
||||
/** Display a debug message as a chat message. */
|
||||
void log_message(const std::string& msg);
|
||||
|
||||
|
@ -473,7 +599,7 @@ private:
|
|||
|
||||
};
|
||||
|
||||
class readwrite_context_impl : public virtual side_context_proxy, public virtual readonly_context_proxy, public readwrite_context {
|
||||
class readwrite_context_impl : public virtual readonly_context_proxy, public readwrite_context {
|
||||
public:
|
||||
/**
|
||||
* Unwrap - this class is not a proxy, so return *this
|
||||
|
@ -539,6 +665,7 @@ public:
|
|||
/** Return a reference to the 'team' object for the AI. */
|
||||
virtual team& current_team_w() { return get_info_w().teams[get_side()-1]; }
|
||||
|
||||
|
||||
/**
|
||||
* This function should be called to attack an enemy.
|
||||
*
|
||||
|
@ -555,6 +682,7 @@ public:
|
|||
*/
|
||||
virtual void attack_enemy(const map_location u, const map_location target, int att_weapon, int def_weapon);
|
||||
|
||||
|
||||
/**
|
||||
* This function should be called to move a unit.
|
||||
*
|
||||
|
@ -592,13 +720,17 @@ public:
|
|||
void raise_unit_moved() const;
|
||||
void raise_enemy_attacked() const;
|
||||
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
* Constructor.
|
||||
*/
|
||||
readwrite_context_impl(readonly_context &context)
|
||||
: side_context_proxy(context), readonly_context_proxy(context), recursion_counter_(context.get_recursion_count())
|
||||
: recursion_counter_(context.get_recursion_count())
|
||||
{
|
||||
init_readonly_context_proxy(context);
|
||||
}
|
||||
|
||||
|
||||
virtual ~readwrite_context_impl() {}
|
||||
|
||||
/**
|
||||
|
@ -607,6 +739,7 @@ public:
|
|||
*/
|
||||
virtual ai_game_info& get_info_w();
|
||||
|
||||
|
||||
virtual int get_recursion_count() const;
|
||||
|
||||
private:
|
||||
|
|
56
src/ai/default/contexts.cpp
Normal file
56
src/ai/default/contexts.cpp
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* $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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Helper functions for the object which operates in the context of AI for specific side
|
||||
* This is part of AI interface
|
||||
* @file ai/default/contexts.cpp
|
||||
*/
|
||||
|
||||
#include "contexts.hpp"
|
||||
|
||||
// =======================================================================
|
||||
namespace ai {
|
||||
|
||||
|
||||
default_ai_context::default_ai_context()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
default_ai_context::~default_ai_context()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
default_ai_context_proxy::~default_ai_context_proxy()
|
||||
{
|
||||
}
|
||||
|
||||
void default_ai_context_proxy::init_default_ai_context_proxy(default_ai_context &target)
|
||||
{
|
||||
init_readwrite_context_proxy(target);
|
||||
target_= &target.get_default_ai_context();
|
||||
}
|
||||
|
||||
default_ai_context& default_ai_context_impl::get_default_ai_context(){
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
default_ai_context_impl::~default_ai_context_impl()
|
||||
{
|
||||
}
|
||||
|
||||
} //of namespace ai
|
98
src/ai/default/contexts.hpp
Normal file
98
src/ai/default/contexts.hpp
Normal file
|
@ -0,0 +1,98 @@
|
|||
/* $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/default/contexts.hpp
|
||||
* Default AI contexts
|
||||
*/
|
||||
|
||||
#ifndef AI_DEFAULT_CONTEXTS_HPP_INCLUDED
|
||||
#define AI_DEFAULT_CONTEXTS_HPP_INCLUDED
|
||||
|
||||
#include "../../global.hpp"
|
||||
|
||||
#include "../contexts.hpp"
|
||||
#include <vector>
|
||||
|
||||
//============================================================================
|
||||
namespace ai {
|
||||
|
||||
|
||||
class default_ai_context;
|
||||
class default_ai_context : public virtual readwrite_context{
|
||||
public:
|
||||
|
||||
default_ai_context();
|
||||
|
||||
virtual ~default_ai_context();
|
||||
|
||||
|
||||
virtual default_ai_context& get_default_ai_context() = 0;
|
||||
};
|
||||
|
||||
|
||||
// proxies
|
||||
class default_ai_context_proxy : public virtual default_ai_context, public virtual readwrite_context_proxy {
|
||||
public:
|
||||
|
||||
|
||||
default_ai_context_proxy()
|
||||
: target_(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void init_default_ai_context_proxy(default_ai_context &target);
|
||||
|
||||
|
||||
virtual ~default_ai_context_proxy();
|
||||
|
||||
|
||||
virtual default_ai_context& get_default_ai_context()
|
||||
{
|
||||
return target_->get_default_ai_context();
|
||||
}
|
||||
|
||||
private:
|
||||
default_ai_context *target_;
|
||||
};
|
||||
|
||||
class default_ai_context_impl : public virtual readwrite_context_proxy, public default_ai_context {
|
||||
public:
|
||||
|
||||
|
||||
default_ai_context_impl(readwrite_context &context)
|
||||
: recursion_counter_(context.get_recursion_count())
|
||||
{
|
||||
init_readwrite_context_proxy(context);
|
||||
}
|
||||
|
||||
|
||||
virtual ~default_ai_context_impl();
|
||||
|
||||
|
||||
virtual default_ai_context& get_default_ai_context();
|
||||
|
||||
int get_recursion_count() const
|
||||
{
|
||||
return recursion_counter_.get_count();
|
||||
}
|
||||
|
||||
private:
|
||||
recursion_counter recursion_counter_;
|
||||
};
|
||||
|
||||
} //end of namespace ai
|
||||
|
||||
#endif
|
|
@ -1600,10 +1600,7 @@ expression_ptr ai_function_symbol_table::create_function(const std::string &fn,
|
|||
|
||||
}
|
||||
|
||||
formula_ai::formula_ai(ai::readwrite_context &context) :
|
||||
side_context_proxy(context),
|
||||
readonly_context_proxy(context),
|
||||
readwrite_context_proxy(context),
|
||||
formula_ai::formula_ai(ai::default_ai_context &context) :
|
||||
ai_default(context),
|
||||
recursion_counter_(context.get_recursion_count()),
|
||||
recruit_formula_(),
|
||||
|
|
|
@ -63,9 +63,9 @@ private:
|
|||
|
||||
}
|
||||
|
||||
class formula_ai : public ai_default, public virtual ai::readwrite_context_proxy {
|
||||
class formula_ai : public ai_default {
|
||||
public:
|
||||
explicit formula_ai(ai::readwrite_context &context);
|
||||
explicit formula_ai(ai::default_ai_context &context);
|
||||
virtual ~formula_ai() {};
|
||||
virtual void play_turn();
|
||||
virtual void new_turn();
|
||||
|
|
76
src/ai/registry.cpp
Normal file
76
src/ai/registry.cpp
Normal file
|
@ -0,0 +1,76 @@
|
|||
/* $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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* All known AI parts. Workaround to a linker feature of not includning all symbols from files, and including only actually referenced stuff. this is not good for 'static registry' pattern. (other workarounds such as --whole-archive for ld are possible, but require messing with all buildsystems)
|
||||
* @file ai/registry.cpp
|
||||
*/
|
||||
|
||||
#include "ai.hpp"
|
||||
#include "ai2.hpp"
|
||||
#include "ai_dfool.hpp"
|
||||
#include "composite/ai.hpp"
|
||||
#include "composite/engine_default.hpp"
|
||||
#include "formula_ai.hpp"
|
||||
#include "registry.hpp"
|
||||
#include "testing/ca.hpp"
|
||||
#include "testing/stage_rca.hpp"
|
||||
#include "testing/stage_fallback.hpp"
|
||||
|
||||
// =======================================================================
|
||||
// AIs
|
||||
// =======================================================================
|
||||
/*
|
||||
static ai_factory<ai> ai_factory("");
|
||||
static ai_factory<ai> default_ai_ai_factory("default_ai");
|
||||
static ai_factory<ai2> ai2_ai_factory("ai2");
|
||||
static ai_factory<dfool_ai> dfool_ai_ai_factory("dfool_ai");
|
||||
static ai_factory<formula_ai> formula_ai_ai_factory("formula_ai");
|
||||
static ai_factory<composite_ai> composite_ai_ai_factory("composite_ai");
|
||||
*/
|
||||
|
||||
// =======================================================================
|
||||
// Engines
|
||||
// =======================================================================
|
||||
|
||||
static ai::composite_ai::register_engine_factory<ai::composite_ai::engine_cpp>
|
||||
composite_ai_factory("cpp");
|
||||
|
||||
// =======================================================================
|
||||
// Stages
|
||||
// =======================================================================
|
||||
static ai::composite_ai::register_stage_factory<testing_ai_default::candidate_action_evaluation_loop>
|
||||
candidate_action_evaluation_loop_factory("testing_ai_default::candidate_action_evaluation_loop");
|
||||
|
||||
static ai::composite_ai::register_stage_factory<testing_ai_default::fallback_to_other_ai>
|
||||
fallback_to_other_ai_factory("testing_ai_default::fallback");
|
||||
|
||||
// =======================================================================
|
||||
// Candidate actions
|
||||
// =======================================================================
|
||||
|
||||
static ai::composite_ai::register_candidate_action_factory<testing_ai_default::goto_phase>
|
||||
goto_phase_factory("testing_ai_default::goto_phase");
|
||||
|
||||
static ai::composite_ai::register_candidate_action_factory<testing_ai_default::recruitment_phase>
|
||||
recruitment_phase_factory("testing_ai_default::recruitment_phase");
|
||||
|
||||
|
||||
void ai_registry::init()
|
||||
{
|
||||
}
|
||||
|
||||
ai_registry::ai_registry()
|
||||
{
|
||||
}
|
33
src/ai/registry.hpp
Normal file
33
src/ai/registry.hpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
/* $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/registry.hpp
|
||||
* All known AI parts
|
||||
*/
|
||||
|
||||
#ifndef AI_REGISTRY_HPP_INCLUDED
|
||||
#define AI_REGISTRY_HPP_INCLUDED
|
||||
|
||||
#include "../global.hpp"
|
||||
|
||||
|
||||
class ai_registry{
|
||||
public:
|
||||
static void init();
|
||||
private:
|
||||
ai_registry();
|
||||
};
|
||||
|
||||
#endif
|
77
src/ai/testing/ca.cpp
Normal file
77
src/ai/testing/ca.cpp
Normal file
|
@ -0,0 +1,77 @@
|
|||
/* $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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Default AI (Testing)
|
||||
* @file ai/testing/ca.cpp
|
||||
*/
|
||||
#include "../../global.hpp"
|
||||
|
||||
#include "ca.hpp"
|
||||
#include "../composite/engine.hpp"
|
||||
#include "../composite/rca.hpp"
|
||||
#include "../../log.hpp"
|
||||
|
||||
static lg::log_domain log_ai_testing_ai_default("ai/testing/ai_default");
|
||||
#define DBG_AI_TESTING_AI_DEFAULT LOG_STREAM(debug, log_ai_testing_ai_default)
|
||||
#define LOG_AI_TESTING_AI_DEFAULT LOG_STREAM(info, log_ai_testing_ai_default)
|
||||
#define ERR_AI_TESTING_AI_DEFAULT LOG_STREAM(err, log_ai_testing_ai_default)
|
||||
|
||||
|
||||
namespace testing_ai_default {
|
||||
|
||||
goto_phase::goto_phase( ai::composite_ai::rca_context &context, const config &cfg )
|
||||
: candidate_action(context,"testing_ai_default::goto_phase",cfg["type"])
|
||||
{
|
||||
}
|
||||
|
||||
goto_phase::~goto_phase()
|
||||
{
|
||||
}
|
||||
|
||||
double goto_phase::evaluate()
|
||||
{
|
||||
ERR_AI_TESTING_AI_DEFAULT << get_name() << ": evaluate - not yet implemented" << std::endl;
|
||||
return BAD_SCORE;
|
||||
}
|
||||
|
||||
bool goto_phase::execute()
|
||||
{
|
||||
ERR_AI_TESTING_AI_DEFAULT << get_name() << ": execute - not yet implemented" << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
recruitment_phase::recruitment_phase( ai::composite_ai::rca_context &context, const config &cfg )
|
||||
: candidate_action(context,"testing_ai_default::recruitment_phase",cfg["type"])
|
||||
{
|
||||
}
|
||||
|
||||
recruitment_phase::~recruitment_phase()
|
||||
{
|
||||
}
|
||||
|
||||
double recruitment_phase::evaluate()
|
||||
{
|
||||
ERR_AI_TESTING_AI_DEFAULT << get_name() << ": evaluate - not yet implemented!" << std::endl;
|
||||
return BAD_SCORE;
|
||||
}
|
||||
|
||||
bool recruitment_phase::execute()
|
||||
{
|
||||
ERR_AI_TESTING_AI_DEFAULT << get_name() << ": execute - not yet implemented!" << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
172
src/ai/testing/ca.hpp
Normal file
172
src/ai/testing/ca.hpp
Normal file
|
@ -0,0 +1,172 @@
|
|||
/* $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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Default AI (Testing)
|
||||
* @file ai/testing/ca.hpp
|
||||
*/
|
||||
|
||||
#ifndef AI_TESTING_CA_HPP_INCLUDED
|
||||
#define AI_TESTING_CA_HPP_INCLUDED
|
||||
|
||||
#include "../../global.hpp"
|
||||
|
||||
#include "../composite/rca.hpp"
|
||||
#include "../composite/engine_default.hpp"
|
||||
|
||||
namespace testing_ai_default {
|
||||
|
||||
//============================================================================
|
||||
|
||||
class goto_phase : public ai::composite_ai::candidate_action {
|
||||
public:
|
||||
|
||||
goto_phase( ai::composite_ai::rca_context &context, const config &cfg );
|
||||
|
||||
virtual ~goto_phase();
|
||||
|
||||
virtual double evaluate();
|
||||
|
||||
virtual bool execute();
|
||||
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
class recruitment_phase : public ai::composite_ai::candidate_action {
|
||||
public:
|
||||
|
||||
recruitment_phase( ai::composite_ai::rca_context &context, const config &cfg );
|
||||
|
||||
virtual ~recruitment_phase();
|
||||
|
||||
virtual double evaluate();
|
||||
|
||||
virtual bool execute();
|
||||
|
||||
};
|
||||
/*
|
||||
//============================================================================
|
||||
|
||||
class combat_phase : public ai_candidate_action {
|
||||
public:
|
||||
|
||||
combat_phase( ai_readonly_context& ai, const std::string& name, const std::string& type );
|
||||
|
||||
virtual ~combat_phase();
|
||||
|
||||
virtual double evaluate();
|
||||
|
||||
virtual bool execute(ai_readwrite_context& context);
|
||||
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
class move_leader_to_goals_phase : public ai_candidate_action {
|
||||
public:
|
||||
|
||||
move_leader_to_goals_phase( ai_readonly_context& ai, const std::string& name, const std::string& type );
|
||||
|
||||
virtual ~move_leader_to_goals_phase();
|
||||
|
||||
virtual double evaluate();
|
||||
|
||||
virtual bool execute(ai_readwrite_context& ai);
|
||||
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
class get_villages_phase : public ai_candidate_action {
|
||||
public:
|
||||
|
||||
get_villages_phase( ai_readonly_context& ai, const std::string& name, const std::string& type );
|
||||
|
||||
virtual ~get_villages_phase();
|
||||
|
||||
virtual double evaluate();
|
||||
|
||||
virtual bool execute(ai_readwrite_context& ai);
|
||||
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
class get_healing_phase : public ai_candidate_action {
|
||||
public:
|
||||
|
||||
get_healing_phase( ai_readonly_context& ai, const std::string& name, const std::string& type );
|
||||
|
||||
virtual ~get_healing_phase();
|
||||
|
||||
virtual double evaluate();
|
||||
|
||||
virtual bool execute(ai_readwrite_context& ai);
|
||||
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
class retreat_phase : public ai_candidate_action {
|
||||
public:
|
||||
|
||||
retreat_phase( ai_readonly_context& ai, const std::string& name, const std::string& type );
|
||||
|
||||
virtual ~retreat_phase();
|
||||
|
||||
virtual double evaluate();
|
||||
|
||||
virtual bool execute(ai_readwrite_context& ai);
|
||||
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
class move_and_targeting_phase : public ai_candidate_action {
|
||||
public:
|
||||
|
||||
move_and_targeting_phase( ai_readonly_context& ai, const std::string& name, const std::string& type );
|
||||
|
||||
virtual ~move_and_targeting_phase();
|
||||
|
||||
virtual double evaluate();
|
||||
|
||||
virtual bool execute(ai_readwrite_context& ai);
|
||||
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
class leader_control_phase : public ai_candidate_action {
|
||||
public:
|
||||
|
||||
leader_control_phase( ai_readonly_context& ai, const std::string& name, const std::string& type );
|
||||
|
||||
virtual ~leader_control_phase();
|
||||
|
||||
virtual double evaluate();
|
||||
|
||||
virtual bool execute(ai_readwrite_context& ai);
|
||||
|
||||
};
|
||||
|
||||
|
||||
//============================================================================
|
||||
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
#endif
|
61
src/ai/testing/stage_fallback.cpp
Normal file
61
src/ai/testing/stage_fallback.cpp
Normal file
|
@ -0,0 +1,61 @@
|
|||
/* $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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Stage: fallback to other AI
|
||||
* @file ai/testing/rca_default.cpp
|
||||
*/
|
||||
|
||||
#include "stage_fallback.hpp"
|
||||
|
||||
#include "../ai_manager.hpp"
|
||||
#include "../composite/ai.hpp"
|
||||
#include "../../foreach.hpp"
|
||||
#include "../../log.hpp"
|
||||
|
||||
namespace testing_ai_default {
|
||||
|
||||
static lg::log_domain log_ai_testing_stage_fallback("ai/testing/stage_fallback");
|
||||
#define DBG_AI_TESTING_STAGE_FALLBACK LOG_STREAM(debug, log_ai_testing_stage_fallback)
|
||||
#define LOG_AI_TESTING_STAGE_FALLBACK LOG_STREAM(info, log_ai_testing_stage_fallback)
|
||||
#define ERR_AI_TESTING_STAGE_FALLBACK LOG_STREAM(err, log_ai_testing_stage_fallback)
|
||||
|
||||
fallback_to_other_ai::fallback_to_other_ai( ai::composite_ai::composite_ai_context &context, const config &cfg )
|
||||
: stage(context,cfg), cfg_(cfg), fallback_ai_(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
void fallback_to_other_ai::on_create()
|
||||
{
|
||||
fallback_ai_ = ai_manager::create_transient_ai(cfg_["fallback"], this);
|
||||
}
|
||||
|
||||
void fallback_to_other_ai::do_play_stage()
|
||||
{
|
||||
if (fallback_ai_) {
|
||||
LOG_AI_TESTING_STAGE_FALLBACK << "side "<<get_side()<<" : falling back to "<<fallback_ai_->describe_self()<<std::endl;
|
||||
fallback_ai_->play_turn();
|
||||
} else {
|
||||
ERR_AI_TESTING_STAGE_FALLBACK << "side "<<get_side()<<" : UNABLE TO FALLBACK, fallback ai is NULL"<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
fallback_to_other_ai::~fallback_to_other_ai()
|
||||
{
|
||||
if (fallback_ai_!=NULL){
|
||||
delete fallback_ai_;
|
||||
}
|
||||
}
|
||||
|
||||
} // of namespace testing_ai_default
|
51
src/ai/testing/stage_fallback.hpp
Normal file
51
src/ai/testing/stage_fallback.hpp
Normal file
|
@ -0,0 +1,51 @@
|
|||
/* $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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Stage: fallback to other AI
|
||||
* @file ai/testing/stage_fallback.hpp
|
||||
*/
|
||||
|
||||
#ifndef AI_TESTING_STAGE_FALLBACK_HPP_INCLUDED
|
||||
#define AI_TESTING_STAGE_FALLBACK_HPP_INCLUDED
|
||||
|
||||
#include "../../global.hpp"
|
||||
|
||||
#include "../composite/stage.hpp"
|
||||
#include "../ai_interface.hpp"
|
||||
#include "../../config.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace testing_ai_default {
|
||||
|
||||
class fallback_to_other_ai: public ai::composite_ai::stage {
|
||||
public:
|
||||
fallback_to_other_ai( ai::composite_ai::composite_ai_context &context, const config &cfg );
|
||||
|
||||
~fallback_to_other_ai();
|
||||
|
||||
void do_play_stage();
|
||||
|
||||
void on_create();
|
||||
|
||||
private:
|
||||
const config &cfg_;
|
||||
ai_interface *fallback_ai_;
|
||||
};
|
||||
|
||||
|
||||
} // of namespace testing_ai_default
|
||||
|
||||
#endif
|
116
src/ai/testing/stage_rca.cpp
Normal file
116
src/ai/testing/stage_rca.cpp
Normal file
|
@ -0,0 +1,116 @@
|
|||
/* $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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Candidate actions evaluator
|
||||
* @file ai/testing/stage_rca.cpp
|
||||
*/
|
||||
|
||||
#include "stage_rca.hpp"
|
||||
|
||||
#include "../composite/ai.hpp"
|
||||
#include "../../foreach.hpp"
|
||||
#include "../../log.hpp"
|
||||
|
||||
namespace testing_ai_default {
|
||||
|
||||
static lg::log_domain log_ai_testing_rca_default("ai/testing/rca_default");
|
||||
#define DBG_AI_TESTING_RCA_DEFAULT LOG_STREAM(debug, log_ai_testing_rca_default)
|
||||
#define LOG_AI_TESTING_RCA_DEFAULT LOG_STREAM(info, log_ai_testing_rca_default)
|
||||
#define ERR_AI_TESTING_RCA_DEFAULT LOG_STREAM(err, log_ai_testing_rca_default)
|
||||
|
||||
candidate_action_evaluation_loop::candidate_action_evaluation_loop( ai::composite_ai::composite_ai_context &context, const config &cfg)
|
||||
: stage(context,cfg),cfg_(cfg)
|
||||
{
|
||||
}
|
||||
|
||||
void candidate_action_evaluation_loop::on_create()
|
||||
{
|
||||
//init the candidate actions
|
||||
foreach(const config &cfg_element, cfg_.child_range("candidate_action")){
|
||||
ai::composite_ai::engine::parse_candidate_action_from_config(*this,cfg_element,back_inserter(candidate_actions_));
|
||||
}
|
||||
}
|
||||
|
||||
void candidate_action_evaluation_loop::do_play_stage()
|
||||
{
|
||||
LOG_AI_TESTING_RCA_DEFAULT << "Starting candidate action evaluation loop for side "<< get_side() << std::endl;
|
||||
const static double STOP_VALUE = 0;
|
||||
|
||||
foreach(ai::composite_ai::candidate_action_ptr ca, candidate_actions_){
|
||||
ca->enable();
|
||||
}
|
||||
|
||||
bool executed = false;
|
||||
do {
|
||||
executed = false;
|
||||
double best_score = ai::composite_ai::candidate_action::BAD_SCORE;
|
||||
ai::composite_ai::candidate_action_ptr best_ptr;
|
||||
|
||||
//Evaluation
|
||||
foreach(ai::composite_ai::candidate_action_ptr ca_ptr, candidate_actions_){
|
||||
if (!ca_ptr->is_enabled()){
|
||||
continue;
|
||||
}
|
||||
|
||||
double score = STOP_VALUE;
|
||||
try {
|
||||
DBG_AI_TESTING_RCA_DEFAULT << "Evaluating candidate action: "<< *ca_ptr << std::endl;
|
||||
score = ca_ptr->evaluate();
|
||||
DBG_AI_TESTING_RCA_DEFAULT << "Evaluated candidate action to score "<< score << " : " << *ca_ptr << std::endl;
|
||||
} catch (ai::composite_ai::candidate_action_evaluation_exception &caee) {
|
||||
ERR_AI_TESTING_RCA_DEFAULT << "Candidate action evaluation threw an exception: " << caee << std::endl;
|
||||
ca_ptr->disable();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (score>best_score) {
|
||||
best_score = score;
|
||||
best_ptr = ca_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
//Execution
|
||||
if (best_score>ai::composite_ai::candidate_action::BAD_SCORE) {
|
||||
try {
|
||||
DBG_AI_TESTING_RCA_DEFAULT << "Best candidate action: "<< *best_ptr << std::endl;
|
||||
executed = best_ptr->execute();
|
||||
} catch (ai::composite_ai::candidate_action_execution_exception &caee) {
|
||||
ERR_AI_TESTING_RCA_DEFAULT << "Candidate action execution threw an exception: " << caee << std::endl;
|
||||
executed = false;
|
||||
}
|
||||
if (!executed) {
|
||||
//this means that this CA has lied to us in evaluate()
|
||||
//we punish it by disabling it
|
||||
best_ptr->disable();
|
||||
//since we don't re-enable at this play_stage, if we disable this CA, other may get the change to go.
|
||||
executed = true;
|
||||
}
|
||||
} else {
|
||||
LOG_AI_TESTING_RCA_DEFAULT << "Ending candidate action evaluation loop due to best score "<< best_score<<"<="<< ai::composite_ai::candidate_action::BAD_SCORE<<std::endl;
|
||||
}
|
||||
} while (executed);
|
||||
LOG_AI_TESTING_RCA_DEFAULT << "Ended candidate action evaluation loop for side "<< get_side() << std::endl;
|
||||
}
|
||||
|
||||
ai::composite_ai::rca_context& candidate_action_evaluation_loop::get_rca_context()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
candidate_action_evaluation_loop::~candidate_action_evaluation_loop()
|
||||
{
|
||||
}
|
||||
|
||||
} // of namespace testing_ai_default
|
56
src/ai/testing/stage_rca.hpp
Normal file
56
src/ai/testing/stage_rca.hpp
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* $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/testing/stage_rca.hpp
|
||||
* candidate action evaluator
|
||||
*/
|
||||
|
||||
#ifndef AI_TESTING_STAGE_RCA_HPP_INCLUDED
|
||||
#define AI_TESTING_STAGE_RCA_HPP_INCLUDED
|
||||
|
||||
#include "../../global.hpp"
|
||||
|
||||
#include "../composite/contexts.hpp"
|
||||
#include "../composite/rca.hpp"
|
||||
#include "../composite/stage.hpp"
|
||||
#include "../../config.hpp"
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace testing_ai_default {
|
||||
|
||||
class candidate_action_evaluation_loop: public virtual ai::composite_ai::stage, public virtual ai::composite_ai::rca_context {
|
||||
public:
|
||||
candidate_action_evaluation_loop( ai::composite_ai::composite_ai_context &context, const config &cfg );
|
||||
|
||||
~candidate_action_evaluation_loop();
|
||||
|
||||
void do_play_stage();
|
||||
|
||||
void on_create();
|
||||
|
||||
ai::composite_ai::rca_context& get_rca_context();
|
||||
|
||||
private:
|
||||
std::vector<ai::composite_ai::candidate_action_ptr> candidate_actions_;
|
||||
|
||||
const config &cfg_;
|
||||
};
|
||||
|
||||
|
||||
} // of namespace testing_ai_default
|
||||
|
||||
#endif
|
Loading…
Add table
Reference in a new issue