new AI configuration syntax. Note: boost 1.35 required for compilation
This commit is contained in:
parent
ec6b1657b0
commit
09223f03cc
68 changed files with 2775 additions and 1125 deletions
|
@ -1,4 +1,6 @@
|
|||
Version 1.7.2+svn:
|
||||
* AI:
|
||||
* New AI configuration syntax
|
||||
* Campaigns:
|
||||
* Two Brothers
|
||||
* Replaced campaign specific portraits with mainline portraits
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
{campaigns/}
|
||||
|
||||
[ais]
|
||||
[default_config]
|
||||
{ai/utils/default_config.cfg}
|
||||
[/default_config]
|
||||
{ai/ais/}
|
||||
#ifdef DEBUG_MODE
|
||||
{ai/dev/}
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
[stage]
|
||||
engine=cpp
|
||||
name=testing_ai_default::fallback
|
||||
fallback=formula_ai
|
||||
[ai]
|
||||
algorithm_type=formula_ai
|
||||
[/ai]
|
||||
[/stage]
|
||||
[/ai]
|
||||
|
|
|
@ -2,6 +2,14 @@
|
|||
[ai]
|
||||
id=testing_ai_default
|
||||
description=RCA AI
|
||||
[aspect]
|
||||
id=aggression
|
||||
[facet]
|
||||
engine=cpp
|
||||
name=standard_aspect
|
||||
value=1
|
||||
[/facet]
|
||||
[/aspect]
|
||||
[stage]
|
||||
engine=cpp
|
||||
name=testing_ai_default::candidate_action_evaluation_loop
|
||||
|
|
67
data/ai/utils/default_config.cfg
Normal file
67
data/ai/utils/default_config.cfg
Normal file
|
@ -0,0 +1,67 @@
|
|||
#define DEFAULT_ASPECT_VALUE ID VALUE
|
||||
[aspect]
|
||||
id={ID}
|
||||
engine=cpp
|
||||
name=composite_aspect
|
||||
[default]
|
||||
engine=cpp
|
||||
name=standard_aspect
|
||||
value={VALUE}
|
||||
[/default]
|
||||
[/aspect]
|
||||
#enddef
|
||||
|
||||
#define DEFAULT_ASPECT_EMPTY ID
|
||||
[aspect]
|
||||
id={ID}
|
||||
engine=cpp
|
||||
name=composite_aspect
|
||||
[default]
|
||||
engine=cpp
|
||||
name=standard_aspect
|
||||
[/default]
|
||||
[/aspect]
|
||||
#enddef
|
||||
|
||||
#define DEFAULT_ASPECT_EMPTY_SLF ID
|
||||
[aspect]
|
||||
id={ID}
|
||||
engine=cpp
|
||||
name=composite_aspect
|
||||
[default]
|
||||
engine=cpp
|
||||
name=standard_aspect
|
||||
[value]
|
||||
[not]
|
||||
[/not]
|
||||
[/value]
|
||||
[/default]
|
||||
[/aspect]
|
||||
#enddef
|
||||
|
||||
{DEFAULT_ASPECT_VALUE aggression 0.5}
|
||||
{DEFAULT_ASPECT_VALUE attack_depth 5}
|
||||
{DEFAULT_ASPECT_EMPTY_SLF avoid}
|
||||
{DEFAULT_ASPECT_VALUE caution 0.25}
|
||||
{DEFAULT_ASPECT_VALUE grouping offensive}
|
||||
{DEFAULT_ASPECT_EMPTY leader_goal}
|
||||
{DEFAULT_ASPECT_VALUE leader_value 3.0}
|
||||
{DEFAULT_ASPECT_VALUE number_of_possible_recruits_to_force_recruit 3.1}
|
||||
{DEFAULT_ASPECT_VALUE passive_leader no}
|
||||
{DEFAULT_ASPECT_VALUE passive_leader_shares_keep no}
|
||||
{DEFAULT_ASPECT_VALUE protect_leader 2.0}
|
||||
{DEFAULT_ASPECT_VALUE protect_leader_radius 10}
|
||||
{DEFAULT_ASPECT_EMPTY protect_location}
|
||||
{DEFAULT_ASPECT_EMPTY protect_unit}
|
||||
{DEFAULT_ASPECT_VALUE recruitment_ignore_bad_combat no}
|
||||
{DEFAULT_ASPECT_VALUE recruitment_ignore_bad_movement no}
|
||||
{DEFAULT_ASPECT_EMPTY recruitment_pattern}
|
||||
{DEFAULT_ASPECT_VALUE scout_village_targeting 3}
|
||||
{DEFAULT_ASPECT_VALUE simple_targeting no}
|
||||
{DEFAULT_ASPECT_VALUE support_villages no}
|
||||
{DEFAULT_ASPECT_EMPTY target}
|
||||
{DEFAULT_ASPECT_VALUE village_value 1.0}
|
||||
{DEFAULT_ASPECT_VALUE villages_per_scout 4}
|
||||
|
||||
ai_algorithm = "default_ai"
|
||||
default_config_applied="yes"
|
|
@ -51,6 +51,8 @@
|
|||
<Unit filename="..\..\src\ai\ai2\ai.hpp" />
|
||||
<Unit filename="..\..\src\ai\composite\ai.cpp" />
|
||||
<Unit filename="..\..\src\ai\composite\ai.hpp" />
|
||||
<Unit filename="..\..\src\ai\composite\aspect.cpp" />
|
||||
<Unit filename="..\..\src\ai\composite\aspect.hpp" />
|
||||
<Unit filename="..\..\src\ai\composite\contexts.cpp" />
|
||||
<Unit filename="..\..\src\ai\composite\contexts.hpp" />
|
||||
<Unit filename="..\..\src\ai\composite\engine.cpp" />
|
||||
|
@ -59,6 +61,8 @@
|
|||
<Unit filename="..\..\src\ai\composite\engine_default.hpp" />
|
||||
<Unit filename="..\..\src\ai\composite\engine_fai.cpp" />
|
||||
<Unit filename="..\..\src\ai\composite\engine_fai.hpp" />
|
||||
<Unit filename="..\..\src\ai\composite\goal.cpp" />
|
||||
<Unit filename="..\..\src\ai\composite\goal.hpp" />
|
||||
<Unit filename="..\..\src\ai\composite\rca.cpp" />
|
||||
<Unit filename="..\..\src\ai\composite\rca.hpp" />
|
||||
<Unit filename="..\..\src\ai\composite\stage.cpp" />
|
||||
|
|
|
@ -80,6 +80,8 @@
|
|||
<Unit filename="..\..\src\ai\ai2\ai.hpp" />
|
||||
<Unit filename="..\..\src\ai\composite\ai.cpp" />
|
||||
<Unit filename="..\..\src\ai\composite\ai.hpp" />
|
||||
<Unit filename="..\..\src\ai\composite\aspect.cpp" />
|
||||
<Unit filename="..\..\src\ai\composite\aspect.hpp" />
|
||||
<Unit filename="..\..\src\ai\composite\contexts.cpp" />
|
||||
<Unit filename="..\..\src\ai\composite\contexts.hpp" />
|
||||
<Unit filename="..\..\src\ai\composite\engine.cpp" />
|
||||
|
@ -88,6 +90,8 @@
|
|||
<Unit filename="..\..\src\ai\composite\engine_default.hpp" />
|
||||
<Unit filename="..\..\src\ai\composite\engine_fai.cpp" />
|
||||
<Unit filename="..\..\src\ai\composite\engine_fai.hpp" />
|
||||
<Unit filename="..\..\src\ai\composite\goal.cpp" />
|
||||
<Unit filename="..\..\src\ai\composite\goal.hpp" />
|
||||
<Unit filename="..\..\src\ai\composite\rca.cpp" />
|
||||
<Unit filename="..\..\src\ai\composite\rca.hpp" />
|
||||
<Unit filename="..\..\src\ai\composite\stage.cpp" />
|
||||
|
|
|
@ -3871,6 +3871,34 @@
|
|||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\composite\aspect.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\ai\composite\"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\ai\composite\"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug (fast)|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\ai\composite\"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\composite\contexts.cpp"
|
||||
>
|
||||
|
@ -3983,6 +4011,34 @@
|
|||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\composite\goal.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\ai\composite\"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\ai\composite\"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug (fast)|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\ai\composite\"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\composite\rca.cpp"
|
||||
>
|
||||
|
@ -5518,6 +5574,10 @@
|
|||
RelativePath="..\..\src\ai\composite\ai.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\composite\aspect.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\composite\contexts.hpp"
|
||||
>
|
||||
|
@ -5534,6 +5594,10 @@
|
|||
RelativePath="..\..\src\ai\composite\engine_fai.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\composite\goal.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\composite\rca.hpp"
|
||||
>
|
||||
|
|
|
@ -220,10 +220,12 @@ SET(wesnoth-main_SRC
|
|||
addon_management.cpp
|
||||
ai/actions.cpp
|
||||
ai/composite/ai.cpp
|
||||
ai/composite/aspect.cpp
|
||||
ai/composite/contexts.cpp
|
||||
ai/composite/engine.cpp
|
||||
ai/composite/engine_default.cpp
|
||||
ai/composite/engine_fai.cpp
|
||||
ai/composite/goal.cpp
|
||||
ai/composite/rca.cpp
|
||||
ai/composite/stage.cpp
|
||||
ai/configuration.cpp
|
||||
|
|
|
@ -44,10 +44,12 @@ wesnoth_source = \
|
|||
addon_management.cpp \
|
||||
ai/actions.cpp \
|
||||
ai/composite/ai.cpp \
|
||||
ai/composite/aspect.cpp \
|
||||
ai/composite/contexts.cpp \
|
||||
ai/composite/engine.cpp \
|
||||
ai/composite/engine_default.cpp \
|
||||
ai/composite/engine_fai.cpp \
|
||||
ai/composite/goal.cpp \
|
||||
ai/composite/rca.cpp \
|
||||
ai/composite/stage.cpp \
|
||||
ai/configuration.cpp \
|
||||
|
|
|
@ -149,10 +149,12 @@ wesnoth_sources = Split("""
|
|||
addon_management.cpp
|
||||
ai/actions.cpp
|
||||
ai/composite/ai.cpp
|
||||
ai/composite/aspect.cpp
|
||||
ai/composite/contexts.cpp
|
||||
ai/composite/engine.cpp
|
||||
ai/composite/engine_default.cpp
|
||||
ai/composite/engine_fai.cpp
|
||||
ai/composite/goal.cpp
|
||||
ai/composite/rca.cpp
|
||||
ai/composite/stage.cpp
|
||||
ai/configuration.cpp
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
* Recruiting, Fighting.
|
||||
*/
|
||||
|
||||
#include "ai/manager.hpp"
|
||||
#include "ai/testing.hpp"
|
||||
#include "attack_prediction.hpp"
|
||||
#include "foreach.hpp"
|
||||
|
@ -2013,7 +2014,7 @@ void check_victory()
|
|||
if(non_interactive()) {
|
||||
std::cout << "winner: ";
|
||||
for(std::vector<unsigned int>::const_iterator i = seen_leaders.begin(); i != seen_leaders.end(); ++i) {
|
||||
std::string ai = (*resources::teams)[*i - 1].ai_algorithm();
|
||||
std::string ai = ai::manager::get_active_ai_identifier_for_side(*i);
|
||||
if (ai == "") ai = "default ai";
|
||||
std::cout << *i << " (using " << ai << ") ";
|
||||
}
|
||||
|
|
|
@ -177,8 +177,8 @@ const team& action_result::get_my_team(const game_info& info) const
|
|||
}
|
||||
|
||||
// attack_result
|
||||
attack_result::attack_result( side_number side, const map_location& attacker_loc, const map_location& defender_loc, int attacker_weapon)
|
||||
: action_result(side), attacker_loc_(attacker_loc), defender_loc_(defender_loc), attacker_weapon_(attacker_weapon){
|
||||
attack_result::attack_result( side_number side, const map_location& attacker_loc, const map_location& defender_loc, int attacker_weapon, double aggression)
|
||||
: action_result(side), attacker_loc_(attacker_loc), defender_loc_(defender_loc), attacker_weapon_(attacker_weapon), aggression_(aggression){
|
||||
}
|
||||
|
||||
void attack_result::do_check_before()
|
||||
|
@ -200,6 +200,7 @@ std::string attack_result::do_describe() const
|
|||
s << " from location "<<attacker_loc_;
|
||||
s << " to location "<<defender_loc_;
|
||||
s << " using weapon "<< attacker_weapon_;
|
||||
s << " with aggression "<< aggression_;
|
||||
s <<std::endl;
|
||||
return s.str();
|
||||
}
|
||||
|
@ -247,8 +248,9 @@ void attack_result::do_execute()
|
|||
//CHECK ENEMY(DEFENDER)
|
||||
//CHECK ATTACKER WEAPON
|
||||
|
||||
//@note: yes, this is a decision done here. It's that way because we want to allow a simpler attack 'with whatever weapon is considered best', and because we want to allow the defender to pick it's weapon. That's why aggression is needed. a cleaner solution is needed.
|
||||
battle_context bc(get_info().units, attacker_loc_,
|
||||
defender_loc_, attacker_weapon_, -1, get_my_team(get_info()).aggression());
|
||||
defender_loc_, attacker_weapon_, -1, aggression_);
|
||||
|
||||
int attacker_weapon = bc.get_attacker_stats().attack_num;
|
||||
int defender_weapon = bc.get_defender_stats().attack_num;
|
||||
|
@ -818,9 +820,10 @@ attack_result_ptr actions::execute_attack_action( side_number side,
|
|||
bool execute,
|
||||
const map_location& attacker_loc,
|
||||
const map_location& defender_loc,
|
||||
int attacker_weapon)
|
||||
int attacker_weapon,
|
||||
double aggression)
|
||||
{
|
||||
attack_result_ptr action(new attack_result(side,attacker_loc,defender_loc,attacker_weapon));
|
||||
attack_result_ptr action(new attack_result(side,attacker_loc,defender_loc,attacker_weapon,aggression));
|
||||
execute ? action->execute() : action->check_before();
|
||||
return action;
|
||||
}
|
||||
|
|
|
@ -135,7 +135,8 @@ public:
|
|||
attack_result( side_number side,
|
||||
const map_location& attacker_loc,
|
||||
const map_location& defender_loc,
|
||||
int attacker_weapon );
|
||||
int attacker_weapon,
|
||||
double aggression );
|
||||
static const int E_EMPTY_ATTACKER = 1001;
|
||||
static const int E_EMPTY_DEFENDER = 1002;
|
||||
static const int E_INCAPACITATED_ATTACKER = 1003;
|
||||
|
@ -154,6 +155,7 @@ private:
|
|||
const map_location& attacker_loc_;
|
||||
const map_location& defender_loc_;
|
||||
int attacker_weapon_;
|
||||
double aggression_;
|
||||
};
|
||||
|
||||
class move_result : public action_result {
|
||||
|
@ -277,6 +279,7 @@ public:
|
|||
* @param attacker_loc location of attacker
|
||||
* @param defender_loc location of defender
|
||||
* @param attacker_weapon weapon of attacker
|
||||
* @param aggression aggression of attacker, is used to determine attacker's weapon if it is not specified
|
||||
* @retval possible result: ok
|
||||
* @retval possible result: something wrong
|
||||
* @retval possible result: attacker and/or defender are invalid
|
||||
|
@ -286,7 +289,8 @@ static attack_result_ptr execute_attack_action( side_number side,
|
|||
bool execute,
|
||||
const map_location& attacker_loc,
|
||||
const map_location& defender_loc,
|
||||
int attacker_weapon );
|
||||
int attacker_weapon,
|
||||
double aggression );
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -33,8 +33,8 @@ namespace ai {
|
|||
|
||||
class ai2 : public readwrite_context_proxy, public interface {
|
||||
public:
|
||||
ai2(readwrite_context &context)
|
||||
: recursion_counter_(context.get_recursion_count())
|
||||
ai2(readwrite_context &context, const config &cfg)
|
||||
: cfg_(cfg),recursion_counter_(context.get_recursion_count())
|
||||
{
|
||||
init_readwrite_context_proxy(context);
|
||||
}
|
||||
|
@ -43,14 +43,24 @@ public:
|
|||
virtual void switch_side(side_number side){
|
||||
set_side(side);
|
||||
}
|
||||
|
||||
|
||||
int get_recursion_count() const{
|
||||
return recursion_counter_.get_count();
|
||||
}
|
||||
|
||||
|
||||
virtual void new_turn()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual config to_config() const{
|
||||
return config();
|
||||
}
|
||||
|
||||
private:
|
||||
const config &cfg_;
|
||||
recursion_counter recursion_counter_;
|
||||
|
||||
};
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
|
||||
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)
|
||||
|
@ -39,25 +37,19 @@ std::string ai_composite::describe_self(){
|
|||
return "[composite_ai]";
|
||||
}
|
||||
|
||||
ai_composite::ai_composite( default_ai_context &context)
|
||||
: recursion_counter_(context.get_recursion_count())
|
||||
ai_composite::ai_composite( default_ai_context &context, const config &cfg)
|
||||
: cfg_(cfg),stages_(),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 id=["<<
|
||||
ai_global_parameters["id"]<<"]"<<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_));
|
||||
}
|
||||
cfg_["id"]<<"]"<<std::endl;
|
||||
|
||||
// init the composite ai stages
|
||||
foreach(const config &cfg_element, ai_global_parameters.child_range("stage")){
|
||||
foreach(const config &cfg_element, cfg_.child_range("stage")){
|
||||
engine::parse_stage_from_config(*this,cfg_element,std::back_inserter(stages_));
|
||||
}
|
||||
|
||||
|
@ -77,10 +69,8 @@ void ai_composite::play_turn(){
|
|||
|
||||
void ai_composite::new_turn()
|
||||
{
|
||||
//todo 1.7 replace with event system
|
||||
//@todo 1.7 replace with event system
|
||||
recalculate_move_maps();
|
||||
invalidate_attack_depth_cache();
|
||||
invalidate_avoided_locations_cache();
|
||||
invalidate_defensive_position_cache();
|
||||
invalidate_recent_attacks_list();
|
||||
invalidate_keeps_cache();
|
||||
|
@ -88,37 +78,6 @@ void ai_composite::new_turn()
|
|||
}
|
||||
|
||||
|
||||
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();
|
||||
|
@ -129,12 +88,23 @@ void ai_composite::switch_side(side_number side)
|
|||
set_side(side);
|
||||
}
|
||||
|
||||
composite_ai_context& ai_composite::get_composite_ai_context()
|
||||
ai_context& ai_composite::get_ai_context()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
} //end of namespace composite_ai
|
||||
config ai_composite::to_config() const
|
||||
{
|
||||
config cfg;
|
||||
|
||||
//serialize the composite ai stages
|
||||
foreach(const stage_ptr &s, stages_){
|
||||
cfg.add_child("stage",s->to_config());
|
||||
}
|
||||
|
||||
return cfg;
|
||||
}
|
||||
|
||||
|
||||
} //end of namespace ai
|
||||
|
|
|
@ -22,8 +22,10 @@
|
|||
|
||||
#include "../../global.hpp"
|
||||
|
||||
#include "aspect.hpp"
|
||||
#include "contexts.hpp"
|
||||
#include "engine.hpp"
|
||||
#include "goal.hpp"
|
||||
#include "stage.hpp"
|
||||
#include "../contexts.hpp"
|
||||
#include "../default/contexts.hpp"
|
||||
|
@ -40,16 +42,14 @@
|
|||
//============================================================================
|
||||
namespace ai {
|
||||
|
||||
namespace composite_ai {
|
||||
|
||||
class ai_composite : public composite_ai_context, public virtual default_ai_context_proxy, public interface {
|
||||
class ai_composite : public ai_context, public virtual default_ai_context_proxy, public interface {
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ai_composite( default_ai_context &context );
|
||||
ai_composite( default_ai_context &context, const config &cfg );
|
||||
|
||||
|
||||
/**
|
||||
|
@ -69,14 +69,14 @@ public:
|
|||
*/
|
||||
virtual void new_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();
|
||||
|
||||
/**
|
||||
* serialize
|
||||
*/
|
||||
virtual config to_config() const;
|
||||
|
||||
|
||||
int get_recursion_count() const;
|
||||
|
||||
|
@ -89,20 +89,21 @@ public:
|
|||
/**
|
||||
* unwrap
|
||||
*/
|
||||
virtual composite_ai_context& get_composite_ai_context();
|
||||
virtual ai_context& get_ai_context();
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Config of the AI
|
||||
*/
|
||||
const config &cfg_;
|
||||
|
||||
|
||||
/**
|
||||
* Stages of the composite AI
|
||||
*/
|
||||
std::vector< stage_ptr > stages_;
|
||||
|
||||
/**
|
||||
* Engines of the composite AI
|
||||
*/
|
||||
std::vector< engine_ptr > engines_;
|
||||
|
||||
|
||||
/**
|
||||
* Recursion counter
|
||||
|
@ -110,8 +111,6 @@ protected:
|
|||
recursion_counter recursion_counter_;
|
||||
};
|
||||
|
||||
} //end of namespace composite_ai
|
||||
|
||||
} //end of namespace ai
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
|
123
src/ai/composite/aspect.cpp
Normal file
123
src/ai/composite/aspect.cpp
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ai/composite/aspect.cpp
|
||||
*/
|
||||
|
||||
#include "aspect.hpp"
|
||||
#include "../manager.hpp"
|
||||
#include "../../log.hpp"
|
||||
|
||||
namespace ai {
|
||||
|
||||
static lg::log_domain log_ai_composite_aspect("ai/composite/aspect");
|
||||
#define DBG_AI_COMPOSITE_ASPECT LOG_STREAM(debug, log_ai_composite_aspect)
|
||||
#define LOG_AI_COMPOSITE_ASPECT LOG_STREAM(info, log_ai_composite_aspect)
|
||||
#define WRN_AI_COMPOSITE_ASPECT LOG_STREAM(warn, log_ai_composite_aspect)
|
||||
#define ERR_AI_COMPOSITE_ASPECT LOG_STREAM(err, log_ai_composite_aspect)
|
||||
|
||||
aspect::aspect(readonly_context &context, const config &cfg, const std::string &id)
|
||||
: valid_(false), cfg_(cfg), invalidate_on_turn_start_(utils::string_bool(cfg["invalidate_on_turn_start"],true)), invalidate_on_tod_change_(utils::string_bool(cfg["invalidate_on_tod_change"],true)), invalidate_on_gamestate_change_(utils::string_bool(cfg["invalidate_on_gamestate_change"])), invalidate_on_minor_gamestate_change_(utils::string_bool(cfg["invalidate_on_minor_gamestate_change"])),engine_(cfg["engine"]),name_(cfg["name"]),id_(id)
|
||||
{
|
||||
DBG_AI_COMPOSITE_ASPECT << "creating new aspect: engine=["<<engine_<<"], name=["<<name_<<"], id=["<<id_<<"]"<< std::endl;
|
||||
init_readonly_context_proxy(context);
|
||||
|
||||
if (invalidate_on_turn_start_) {
|
||||
manager::add_turn_started_observer(this);
|
||||
}
|
||||
if (invalidate_on_tod_change_) {
|
||||
//@todo 1.7 add tod_changed_observer
|
||||
//manager::add_tod_changed_observer(this);
|
||||
}
|
||||
if (invalidate_on_gamestate_change_) {
|
||||
manager::add_gamestate_observer(this);
|
||||
}
|
||||
if (invalidate_on_minor_gamestate_change_) {
|
||||
//@todo 1.7 add minor_gamestate_change_observer
|
||||
//manager::add_minor_gamestate_observer(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
aspect::~aspect()
|
||||
{
|
||||
if (invalidate_on_turn_start_) {
|
||||
manager::remove_turn_started_observer(this);
|
||||
}
|
||||
if (invalidate_on_tod_change_) {
|
||||
//@todo 1.7 add tod_changed_observer
|
||||
//manager::remove_tod_changed_observer(this);
|
||||
}
|
||||
if (invalidate_on_gamestate_change_) {
|
||||
manager::remove_gamestate_observer(this);
|
||||
}
|
||||
if (invalidate_on_minor_gamestate_change_) {
|
||||
//@todo 1.7 add minor_gamestate_change_observer
|
||||
//manager::remove_minor_gamestate_observer(this);
|
||||
}
|
||||
}
|
||||
|
||||
lg::log_domain& aspect::log()
|
||||
{
|
||||
return log_ai_composite_aspect;
|
||||
}
|
||||
|
||||
void aspect::on_create()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
const std::string& aspect::get_id() const
|
||||
{
|
||||
return id_;
|
||||
}
|
||||
|
||||
|
||||
const std::string& aspect::get_name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
|
||||
config aspect::to_config() const
|
||||
{
|
||||
config cfg;
|
||||
cfg["invalidate_on_turn_start"] = invalidate_on_turn_start_ ? "yes" : "no";
|
||||
cfg["invalidate_on_tod_change"] = invalidate_on_tod_change_ ? "yes" : "no";
|
||||
cfg["invalidate_on_gamestate_change"] = invalidate_on_gamestate_change_ ? "yes" : "no";
|
||||
cfg["invalidate_on_minor_gamestate_change"] = invalidate_on_minor_gamestate_change_ ? "yes" : "no";
|
||||
cfg["engine"] = engine_;
|
||||
cfg["name"] = name_;
|
||||
cfg["id"] = id_;
|
||||
return cfg;
|
||||
}
|
||||
|
||||
|
||||
known_aspect::known_aspect(const std::string &name)
|
||||
: name_(name)
|
||||
{
|
||||
}
|
||||
|
||||
const std::string& known_aspect::get_name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
known_aspect::~known_aspect()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
} //end of namespace ai
|
505
src/ai/composite/aspect.hpp
Normal file
505
src/ai/composite/aspect.hpp
Normal file
|
@ -0,0 +1,505 @@
|
|||
/* $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/aspect.hpp
|
||||
*/
|
||||
|
||||
#ifndef AI_COMPOSITE_ASPECT_HPP_INCLUDED
|
||||
#define AI_COMPOSITE_ASPECT_HPP_INCLUDED
|
||||
|
||||
#include "../../global.hpp"
|
||||
|
||||
#include "engine.hpp"
|
||||
|
||||
#include "../contexts.hpp"
|
||||
#include "../game_info.hpp"
|
||||
#include "../manager.hpp"
|
||||
#include "../../foreach.hpp"
|
||||
#include "../../log.hpp"
|
||||
#include "../../terrain_filter.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/pointer_cast.hpp>
|
||||
|
||||
namespace ai {
|
||||
|
||||
//----
|
||||
// @todo: move to some other place
|
||||
template<typename T>
|
||||
class config_value_translator {
|
||||
public:
|
||||
|
||||
static void cfg_to_value(const config &cfg, T &value)
|
||||
{
|
||||
value = boost::lexical_cast<T>(cfg["value"]);
|
||||
}
|
||||
|
||||
static void value_to_cfg(const T &value, config &cfg)
|
||||
{
|
||||
cfg["value"] = boost::lexical_cast<std::string>(value);
|
||||
}
|
||||
|
||||
static config value_to_cfg(const T &value)
|
||||
{
|
||||
config cfg;
|
||||
value_to_cfg(value,cfg);
|
||||
return cfg;
|
||||
}
|
||||
|
||||
static T cfg_to_value(const config &cfg)
|
||||
{
|
||||
T value;
|
||||
cfg_to_value(cfg,value);
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<>
|
||||
class config_value_translator<bool> {
|
||||
public:
|
||||
|
||||
static void cfg_to_value(const config &cfg, bool &value)
|
||||
{
|
||||
value = utils::string_bool(cfg["value"]);
|
||||
}
|
||||
|
||||
static void value_to_cfg(const bool &value, config &cfg)
|
||||
{
|
||||
cfg["value"] = value ? "yes" : "no";
|
||||
}
|
||||
|
||||
static config value_to_cfg(const bool &value)
|
||||
{
|
||||
config cfg;
|
||||
value_to_cfg(value,cfg);
|
||||
return cfg;
|
||||
}
|
||||
|
||||
static bool cfg_to_value(const config &cfg)
|
||||
{
|
||||
bool value;
|
||||
cfg_to_value(cfg,value);
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<>
|
||||
class config_value_translator< std::vector<std::string> > {
|
||||
public:
|
||||
|
||||
static void cfg_to_value(const config &cfg, std::vector<std::string> &value)
|
||||
{
|
||||
value = utils::split(cfg["value"]);
|
||||
}
|
||||
|
||||
static void value_to_cfg(const std::vector<std::string> &value, config &cfg)
|
||||
{
|
||||
std::stringstream buf;
|
||||
for(std::vector<std::string>::const_iterator p = value.begin(); p != value.end(); ++p) {
|
||||
if (p != value.begin()) {
|
||||
buf << ",";
|
||||
}
|
||||
buf << *p;
|
||||
}
|
||||
cfg["value"] = buf.str();
|
||||
}
|
||||
|
||||
static config value_to_cfg(const std::vector<std::string> &value)
|
||||
{
|
||||
config cfg;
|
||||
value_to_cfg(value,cfg);
|
||||
return cfg;
|
||||
}
|
||||
|
||||
static std::vector<std::string> cfg_to_value(const config &cfg)
|
||||
{
|
||||
std::vector<std::string> value;
|
||||
cfg_to_value(cfg,value);
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class config_value_translator<config> {
|
||||
public:
|
||||
|
||||
static void cfg_to_value(const config &cfg, config &value)
|
||||
{
|
||||
if (cfg.child("value")) {
|
||||
value = cfg.child("value");
|
||||
} else {
|
||||
value = config();
|
||||
}
|
||||
}
|
||||
|
||||
static void value_to_cfg(const config &value, config &cfg)
|
||||
{
|
||||
cfg.add_child("value",value);
|
||||
}
|
||||
|
||||
static config value_to_cfg(const config &value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
static config cfg_to_value(const config &cfg)
|
||||
{
|
||||
return cfg;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class config_value_translator<terrain_filter> {
|
||||
public:
|
||||
|
||||
static void cfg_to_value(const config &cfg, terrain_filter &value)
|
||||
{
|
||||
if (cfg.child("value")) {
|
||||
value = terrain_filter(vconfig(cfg.child("value")),manager::get_ai_info().units);
|
||||
} else {
|
||||
static config c;
|
||||
if (!c.child("not")) {
|
||||
c.add_child("not");
|
||||
}
|
||||
value = terrain_filter(vconfig(c),manager::get_ai_info().units);
|
||||
}
|
||||
}
|
||||
|
||||
static void value_to_cfg(const terrain_filter &value, config &cfg)
|
||||
{
|
||||
cfg.add_child("value",value.to_config());
|
||||
}
|
||||
|
||||
static config value_to_cfg(const terrain_filter &value)
|
||||
{
|
||||
config cfg;
|
||||
value_to_cfg(value,cfg);
|
||||
return cfg;
|
||||
}
|
||||
|
||||
static terrain_filter cfg_to_value(const config &cfg)
|
||||
{
|
||||
if (cfg.child("value")) {
|
||||
return terrain_filter(vconfig(cfg.child("value")),manager::get_ai_info().units);
|
||||
}
|
||||
static config c;
|
||||
if (!c.child("not")) {
|
||||
c.add_child("not");
|
||||
}
|
||||
return terrain_filter(vconfig(c),manager::get_ai_info().units);
|
||||
}
|
||||
};
|
||||
//----
|
||||
|
||||
|
||||
class aspect : public readonly_context_proxy, public events::observer {
|
||||
public:
|
||||
aspect(readonly_context &context, const config &cfg, const std::string &id);
|
||||
|
||||
virtual ~aspect();
|
||||
|
||||
void invalidate() const
|
||||
{
|
||||
valid_ = false;
|
||||
}
|
||||
|
||||
|
||||
virtual void recalculate() const = 0;
|
||||
|
||||
|
||||
virtual void on_create();
|
||||
|
||||
|
||||
virtual config to_config() const;
|
||||
|
||||
|
||||
void handle_generic_event(const std::string &/*event_name*/)
|
||||
{
|
||||
invalidate();
|
||||
}
|
||||
|
||||
|
||||
virtual bool active() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const std::string& get_name() const;
|
||||
|
||||
|
||||
const std::string& get_id() const;
|
||||
|
||||
static lg::log_domain& log();
|
||||
protected:
|
||||
mutable bool valid_;
|
||||
config cfg_;
|
||||
bool invalidate_on_turn_start_;
|
||||
bool invalidate_on_tod_change_;
|
||||
bool invalidate_on_gamestate_change_;
|
||||
bool invalidate_on_minor_gamestate_change_;
|
||||
std::string engine_;
|
||||
std::string name_;
|
||||
std::string id_;
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class typesafe_aspect : public aspect {
|
||||
public:
|
||||
typesafe_aspect(readonly_context &context, const config &cfg, const std::string &id)
|
||||
: aspect(context,cfg,id)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~typesafe_aspect()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual const T& get() const
|
||||
{
|
||||
if (!valid_) {
|
||||
recalculate();
|
||||
}
|
||||
return *value_;
|
||||
}
|
||||
|
||||
|
||||
virtual void recalculate() const = 0;
|
||||
|
||||
virtual boost::shared_ptr<T> get_ptr() const
|
||||
{
|
||||
if (!valid_) {
|
||||
recalculate();
|
||||
}
|
||||
return value_;
|
||||
}
|
||||
protected:
|
||||
|
||||
mutable boost::shared_ptr<T> value_;
|
||||
};
|
||||
|
||||
|
||||
class known_aspect {
|
||||
public:
|
||||
known_aspect(const std::string &name);
|
||||
|
||||
virtual ~known_aspect();
|
||||
|
||||
virtual void set(aspect_ptr a) = 0;
|
||||
|
||||
const std::string& get_name() const;
|
||||
|
||||
protected:
|
||||
const std::string name_;
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
class typesafe_known_aspect : public known_aspect {
|
||||
public:
|
||||
typesafe_known_aspect(const std::string &name, boost::shared_ptr< typesafe_aspect<T> > &where, aspect_map &aspects)
|
||||
: known_aspect(name), where_(where), aspects_(aspects)
|
||||
{
|
||||
}
|
||||
|
||||
void set(aspect_ptr a)
|
||||
{
|
||||
boost::shared_ptr< typesafe_aspect <T> > c = boost::dynamic_pointer_cast< typesafe_aspect<T> >(a);
|
||||
if (c) {
|
||||
assert (c->get_id()== this->get_name());
|
||||
where_ = c;
|
||||
aspects_.insert(make_pair(this->get_name(),c));
|
||||
} else {
|
||||
LOG_STREAM(debug, aspect::log()) << "typesafe_known_aspect [" << this->get_name() << "] : while setting aspect, got null. this might be caused by invalid [aspect] WML" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
boost::shared_ptr<typesafe_aspect <T> > &where_;
|
||||
aspect_map &aspects_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
class composite_aspect : public typesafe_aspect<T> {
|
||||
public:
|
||||
|
||||
composite_aspect(readonly_context &context, const config &cfg, const std::string &id)
|
||||
: typesafe_aspect<T>(context, cfg, id)
|
||||
{
|
||||
foreach (const config &cfg_element, this->cfg_.child_range("facet") ){
|
||||
std::vector< aspect_ptr > facets;
|
||||
engine::parse_aspect_from_config(*this,cfg_element,this->get_id(),std::back_inserter(facets));
|
||||
foreach (aspect_ptr a, facets ){
|
||||
boost::shared_ptr< typesafe_aspect<T> > b = boost::dynamic_pointer_cast< typesafe_aspect<T> > (a);
|
||||
facets_.push_back(b);
|
||||
}
|
||||
}
|
||||
|
||||
const config &_default = this->cfg_.child("default");
|
||||
if (_default) {
|
||||
std::vector< aspect_ptr > default_aspects;
|
||||
engine::parse_aspect_from_config(*this,_default,this->get_id(),std::back_inserter(default_aspects));
|
||||
if (!default_aspects.empty()) {
|
||||
boost::shared_ptr< typesafe_aspect<T> > b = boost::dynamic_pointer_cast< typesafe_aspect<T> >(default_aspects.front());
|
||||
default_ = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void recalculate() const
|
||||
{
|
||||
foreach (const boost::shared_ptr< typesafe_aspect<T> > f, facets_) {
|
||||
if (f->active()) {
|
||||
this->value_ = boost::shared_ptr<T>(f->get_ptr());
|
||||
return;
|
||||
}
|
||||
}
|
||||
this->value_ = boost::shared_ptr<T>(default_->get_ptr());
|
||||
|
||||
}
|
||||
|
||||
|
||||
virtual config to_config() const
|
||||
{
|
||||
config cfg = aspect::to_config();
|
||||
foreach (const boost::shared_ptr< typesafe_aspect<T> > f, facets_) {
|
||||
cfg.add_child("facet",f->to_config());
|
||||
}
|
||||
if (default_) {
|
||||
cfg.add_child("default",default_->to_config());
|
||||
}
|
||||
return cfg;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::vector< boost::shared_ptr< typesafe_aspect<T> > > facets_;
|
||||
boost::shared_ptr< typesafe_aspect<T> > default_;
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class standard_aspect : public typesafe_aspect<T> {
|
||||
public:
|
||||
standard_aspect(readonly_context &context, const config &cfg, const std::string &id)
|
||||
: typesafe_aspect<T>(context, cfg, id), time_of_day_(cfg["time_of_day"]),turns_(cfg["turns"])
|
||||
{
|
||||
boost::shared_ptr<T> value(new T(config_value_translator<T>::cfg_to_value(this->cfg_)));
|
||||
this->value_= value;
|
||||
LOG_STREAM(debug, aspect::log()) << "standard aspect has time_of_day=["<<time_of_day_<<"], turns=["<<turns_<<"], and value: "<< std::endl << config_value_translator<T>::value_to_cfg(this->get()) << std::endl;
|
||||
}
|
||||
|
||||
|
||||
virtual bool active() const
|
||||
{
|
||||
if(time_of_day_.empty() == false) {
|
||||
const std::vector<std::string>& times = utils::split(time_of_day_);
|
||||
if(std::count(times.begin(),times.end(),this->get_info().tod_manager_.get_time_of_day().name) == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(turns_.empty() == false) {
|
||||
int turn = this->get_info().tod_manager_.turn();
|
||||
const std::vector<std::string>& turns_list = utils::split(turns_);
|
||||
for(std::vector<std::string>::const_iterator j = turns_list.begin(); j != turns_list.end() ; j++ ) {
|
||||
const std::pair<int,int> range = utils::parse_range(*j);
|
||||
if(turn >= range.first && turn <= range.second) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void recalculate() const
|
||||
{
|
||||
//nothing to recalculate
|
||||
}
|
||||
|
||||
|
||||
config to_config() const
|
||||
{
|
||||
config cfg = aspect::to_config();
|
||||
config_value_translator<T>::value_to_cfg(this->get(),cfg);
|
||||
cfg["time_of_day"] = time_of_day_;
|
||||
cfg["turns"] = turns_;
|
||||
return cfg;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string time_of_day_;
|
||||
std::string turns_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class aspect_factory{
|
||||
public:
|
||||
typedef boost::shared_ptr< aspect_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 *aspect_factories;
|
||||
if (aspect_factories==NULL) {
|
||||
aspect_factories = new factory_map;
|
||||
}
|
||||
return *aspect_factories;
|
||||
}
|
||||
|
||||
virtual aspect_ptr get_new_instance( readonly_context &context, const config &cfg, const std::string &id) = 0;
|
||||
|
||||
aspect_factory( const std::string &name )
|
||||
{
|
||||
factory_ptr ptr_to_this(this);
|
||||
get_list().insert(make_pair(name,ptr_to_this));
|
||||
}
|
||||
|
||||
virtual ~aspect_factory() {}
|
||||
};
|
||||
|
||||
|
||||
template<class ASPECT>
|
||||
class register_aspect_factory : public aspect_factory {
|
||||
public:
|
||||
register_aspect_factory( const std::string &name )
|
||||
: aspect_factory( name )
|
||||
{
|
||||
}
|
||||
|
||||
virtual aspect_ptr get_new_instance( readonly_context &context, const config &cfg, const std::string &id){
|
||||
boost::shared_ptr<ASPECT> _a(new ASPECT(context,cfg,id));
|
||||
aspect_ptr a = _a;
|
||||
a->on_create();
|
||||
return a;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} //end of namespace ai
|
||||
|
||||
#endif
|
|
@ -23,26 +23,23 @@
|
|||
// =======================================================================
|
||||
namespace ai {
|
||||
|
||||
namespace composite_ai {
|
||||
|
||||
|
||||
composite_ai_context::composite_ai_context()
|
||||
ai_context::ai_context()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
composite_ai_context::~composite_ai_context()
|
||||
ai_context::~ai_context()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
composite_ai_context_proxy::composite_ai_context_proxy()
|
||||
ai_context_proxy::ai_context_proxy()
|
||||
: target_()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
composite_ai_context_proxy::~composite_ai_context_proxy()
|
||||
ai_context_proxy::~ai_context_proxy()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -67,6 +64,4 @@ rca_context_proxy::~rca_context_proxy()
|
|||
{
|
||||
}
|
||||
|
||||
} //end of namespace composite_ai
|
||||
|
||||
} //end of namespace ai
|
||||
|
|
|
@ -38,49 +38,33 @@
|
|||
//============================================================================
|
||||
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{
|
||||
class ai_context : public virtual default_ai_context{
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
composite_ai_context();
|
||||
ai_context();
|
||||
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~composite_ai_context();
|
||||
virtual ~ai_context();
|
||||
|
||||
|
||||
/**
|
||||
* Unwrap
|
||||
*/
|
||||
virtual composite_ai_context& get_composite_ai_context() = 0;
|
||||
virtual ai_context& get_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 {
|
||||
class rca_context : public virtual ai_context {
|
||||
public:
|
||||
|
||||
|
||||
|
@ -127,39 +111,33 @@ public:
|
|||
};
|
||||
|
||||
// proxies
|
||||
class composite_ai_context_proxy : public virtual composite_ai_context, public virtual default_ai_context_proxy {
|
||||
class ai_context_proxy : public virtual ai_context, public virtual default_ai_context_proxy {
|
||||
public:
|
||||
composite_ai_context_proxy();
|
||||
ai_context_proxy();
|
||||
|
||||
|
||||
void init_composite_ai_context_proxy(composite_ai_context &target)
|
||||
void init_ai_context_proxy(ai_context &target)
|
||||
{
|
||||
init_default_ai_context_proxy(target);
|
||||
target_ = ⌖
|
||||
}
|
||||
|
||||
|
||||
virtual ~composite_ai_context_proxy();
|
||||
virtual ~ai_context_proxy();
|
||||
|
||||
|
||||
composite_ai_context& get_composite_ai_context()
|
||||
ai_context& get_ai_context()
|
||||
{
|
||||
return target_->get_composite_ai_context();
|
||||
}
|
||||
|
||||
|
||||
engine_ptr get_engine(const config& cfg)
|
||||
{
|
||||
return target_->get_engine(cfg);
|
||||
return target_->get_ai_context();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
composite_ai_context *target_;
|
||||
ai_context *target_;
|
||||
};
|
||||
|
||||
|
||||
class rca_context_proxy : public virtual rca_context, public virtual composite_ai_context_proxy {
|
||||
class rca_context_proxy : public virtual rca_context, public virtual ai_context_proxy {
|
||||
public:
|
||||
rca_context_proxy();
|
||||
|
||||
|
@ -169,7 +147,7 @@ public:
|
|||
|
||||
void init_rca_context_proxy(rca_context &target)
|
||||
{
|
||||
init_composite_ai_context_proxy(target);
|
||||
init_ai_context_proxy(target);
|
||||
target_ = ⌖
|
||||
}
|
||||
|
||||
|
@ -185,8 +163,6 @@ private:
|
|||
};
|
||||
|
||||
|
||||
} //end of namespace composite_ai
|
||||
|
||||
} //end of namespace ai
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
|
|
@ -17,22 +17,21 @@
|
|||
* @file ai/composite/engine.cpp
|
||||
*/
|
||||
|
||||
#include "ai.hpp"
|
||||
#include "engine.hpp"
|
||||
#include "contexts.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)
|
||||
engine::engine( readonly_context &context, const config &cfg )
|
||||
: ai_(context), engine_(cfg["engine"])
|
||||
{
|
||||
LOG_AI_COMPOSITE_ENGINE << "side "<< ai_.get_side() << " : "<<" created engine with name=["<<cfg["name"]<<"]"<<std::endl;
|
||||
}
|
||||
|
@ -41,16 +40,26 @@ 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 )
|
||||
|
||||
void engine::parse_aspect_from_config( readonly_context &context, const config &cfg, const std::string &id, std::back_insert_iterator< std::vector< aspect_ptr > > b )
|
||||
{
|
||||
engine_ptr eng = context.get_engine(cfg);
|
||||
if (eng){
|
||||
//do not override that method in subclasses which cannot create aspects
|
||||
eng->do_parse_aspect_from_config(cfg, id, b);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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 )
|
||||
void engine::parse_engine_from_config( readonly_context &context, const config &cfg, std::back_insert_iterator<std::vector< engine_ptr > > b )
|
||||
{
|
||||
engine_ptr eng = context.get_engine(cfg);
|
||||
if (eng){
|
||||
|
@ -59,15 +68,32 @@ void engine::parse_engine_from_config( composite_ai_context &context, const conf
|
|||
}
|
||||
}
|
||||
|
||||
void engine::parse_stage_from_config( composite_ai_context &context, const config &cfg, std::back_insert_iterator<std::vector< stage_ptr > > b )
|
||||
|
||||
void engine::parse_goal_from_config( readonly_context &context, const config &cfg, std::back_insert_iterator<std::vector< goal_ptr > > b )
|
||||
{
|
||||
engine_ptr eng = context.get_engine(cfg);
|
||||
if (eng){
|
||||
//do not override that method in subclasses which cannot create goals
|
||||
eng->do_parse_goal_from_config(cfg, b);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void engine::parse_stage_from_config( 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);
|
||||
eng->do_parse_stage_from_config(context, cfg, b);
|
||||
}
|
||||
}
|
||||
|
||||
void engine::do_parse_aspect_from_config( const config &/*cfg*/, const std::string &/*id*/, std::back_insert_iterator< std::vector<aspect_ptr> > /*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*/ ){
|
||||
|
||||
}
|
||||
|
@ -76,15 +102,30 @@ void engine::do_parse_engine_from_config( const config &/*cfg*/, std::back_inser
|
|||
|
||||
}
|
||||
|
||||
void engine::do_parse_stage_from_config( const config &/*cfg*/, std::back_insert_iterator<std::vector< stage_ptr > > /*b*/ )
|
||||
|
||||
void engine::do_parse_goal_from_config( const config &/*cfg*/, std::back_insert_iterator<std::vector< goal_ptr > > /*b*/ ){
|
||||
|
||||
}
|
||||
|
||||
|
||||
void engine::do_parse_stage_from_config( ai_context &/*context*/, const config &/*cfg*/, std::back_insert_iterator<std::vector< stage_ptr > > /*b*/ )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string engine::get_name(){
|
||||
|
||||
std::string engine::get_name() const
|
||||
{
|
||||
return "null";
|
||||
}
|
||||
|
||||
} //end of namespace composite_ai
|
||||
|
||||
config engine::to_config() const
|
||||
{
|
||||
config cfg;
|
||||
cfg["engine"] = engine_;
|
||||
cfg["name"] = get_name();
|
||||
return cfg;
|
||||
}
|
||||
|
||||
} //end of namespace ai
|
||||
|
|
|
@ -22,9 +22,8 @@
|
|||
|
||||
#include "../../global.hpp"
|
||||
|
||||
#include "contexts.hpp"
|
||||
#include "rca.hpp"
|
||||
#include "stage.hpp"
|
||||
#include "../contexts.hpp"
|
||||
#include "../game_info.hpp"
|
||||
#include "../../config.hpp"
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
@ -34,38 +33,64 @@
|
|||
|
||||
namespace ai {
|
||||
|
||||
namespace composite_ai {
|
||||
|
||||
class ai_composite;
|
||||
|
||||
class rca_context;
|
||||
class ai_context;
|
||||
|
||||
class engine {
|
||||
public:
|
||||
engine( composite_ai_context &context, const config &cfg );
|
||||
engine( readonly_context &context, const config &cfg );
|
||||
|
||||
|
||||
virtual ~engine();
|
||||
|
||||
|
||||
static void parse_aspect_from_config( readonly_context &context, const config &cfg, const std::string &id, std::back_insert_iterator<std::vector< aspect_ptr > > b );
|
||||
|
||||
|
||||
static void parse_goal_from_config( readonly_context &context, const config &cfg, std::back_insert_iterator<std::vector< goal_ptr > > b );
|
||||
|
||||
|
||||
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 );
|
||||
static void parse_engine_from_config( readonly_context &context, const config &cfg, std::back_insert_iterator<std::vector< engine_ptr > > b );
|
||||
|
||||
|
||||
static void parse_stage_from_config( ai_context &context, const config &cfg, std::back_insert_iterator<std::vector< stage_ptr > > b );
|
||||
|
||||
|
||||
//do not override that method in subclasses which cannot create aspects
|
||||
virtual void do_parse_aspect_from_config( const config &cfg, const std::string &id, std::back_insert_iterator< std::vector< aspect_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 goals
|
||||
virtual void do_parse_goal_from_config( const config &cfg, std::back_insert_iterator<std::vector< goal_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 void do_parse_stage_from_config( ai_context &context, const config &cfg, std::back_insert_iterator<std::vector< stage_ptr > > b );
|
||||
|
||||
|
||||
virtual std::string get_name();
|
||||
virtual std::string get_name() const;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* serialize
|
||||
*/
|
||||
virtual config to_config() const;
|
||||
|
||||
protected:
|
||||
composite_ai_context &ai_;
|
||||
readonly_context &ai_;
|
||||
|
||||
/** name of the engine which has created this engine*/
|
||||
std::string engine_;
|
||||
|
||||
};
|
||||
|
||||
|
@ -86,8 +111,8 @@ public:
|
|||
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;
|
||||
virtual engine_ptr get_new_instance( readonly_context &ai, const config &cfg ) = 0;
|
||||
virtual engine_ptr get_new_instance( readonly_context &ai, const std::string& name ) = 0;
|
||||
|
||||
engine_factory( const std::string &name )
|
||||
{
|
||||
|
@ -107,19 +132,18 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual engine_ptr get_new_instance( composite_ai_context &ai, const config &cfg ){
|
||||
virtual engine_ptr get_new_instance( readonly_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 ){
|
||||
virtual engine_ptr get_new_instance( readonly_context &ai, const std::string& name ){
|
||||
config cfg;
|
||||
cfg["name"] = name;
|
||||
cfg["engine"] = "cpp";
|
||||
return engine_ptr(new ENGINE(ai,cfg));
|
||||
}
|
||||
};
|
||||
|
||||
} //end of namespace composite_ai
|
||||
|
||||
} //end of namespace ai
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,14 +25,12 @@
|
|||
|
||||
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_cpp::engine_cpp( readonly_context &context, const config &cfg )
|
||||
: engine(context,cfg)
|
||||
{
|
||||
}
|
||||
|
@ -42,6 +40,25 @@ engine_cpp::~engine_cpp()
|
|||
}
|
||||
|
||||
|
||||
void engine_cpp::do_parse_aspect_from_config( const config &cfg, const std::string &id, std::back_insert_iterator<std::vector< aspect_ptr > > b )
|
||||
{
|
||||
const std::string aspect_factory_key = id+"*"+cfg["name"];//@note: hack which combines aspect id and name to get the std::string key of the aspect factory
|
||||
aspect_factory::factory_map::iterator f = aspect_factory::get_list().find(aspect_factory_key);
|
||||
if (f == aspect_factory::get_list().end()){
|
||||
ERR_AI_COMPOSITE_ENGINE_CPP << "side "<<ai_.get_side()<< " : UNKNOWN aspect["<<aspect_factory_key<<"]" << std::endl;
|
||||
DBG_AI_COMPOSITE_ENGINE_CPP << "config snippet contains: " << std::endl << cfg << std::endl;
|
||||
return;
|
||||
}
|
||||
aspect_ptr new_aspect = f->second->get_new_instance(ai_,cfg,id);
|
||||
if (!new_aspect) {
|
||||
ERR_AI_COMPOSITE_ENGINE_CPP << "side "<<ai_.get_side()<< " : UNABLE TO CREATE aspect, key=["<<aspect_factory_key<<"]"<< std::endl;
|
||||
DBG_AI_COMPOSITE_ENGINE_CPP << "config snippet contains: " << std::endl << cfg << std::endl;
|
||||
return;
|
||||
}
|
||||
*b = new_aspect;
|
||||
}
|
||||
|
||||
|
||||
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()){
|
||||
|
@ -59,7 +76,7 @@ void engine_cpp::do_parse_candidate_action_from_config( rca_context &context, co
|
|||
|
||||
}
|
||||
|
||||
void engine_cpp::do_parse_stage_from_config( const config &cfg, std::back_insert_iterator<std::vector< stage_ptr > > b )
|
||||
void engine_cpp::do_parse_stage_from_config( ai_context &context, 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()){
|
||||
|
@ -67,7 +84,7 @@ void engine_cpp::do_parse_stage_from_config( const config &cfg, std::back_insert
|
|||
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);
|
||||
stage_ptr new_stage = f->second->get_new_instance(context,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;
|
||||
|
@ -77,11 +94,9 @@ void engine_cpp::do_parse_stage_from_config( const config &cfg, std::back_insert
|
|||
}
|
||||
|
||||
|
||||
std::string engine_cpp::get_name()
|
||||
std::string engine_cpp::get_name() const
|
||||
{
|
||||
return "cpp";
|
||||
}
|
||||
|
||||
} //end of namespace composite_ai
|
||||
|
||||
} //end of namespace ai
|
||||
|
|
|
@ -29,24 +29,27 @@
|
|||
//============================================================================
|
||||
namespace ai {
|
||||
|
||||
namespace composite_ai {
|
||||
|
||||
class engine_cpp : public engine {
|
||||
public:
|
||||
engine_cpp( composite_ai_context &context, const config &cfg );
|
||||
engine_cpp( readonly_context &context, const config &cfg );
|
||||
|
||||
|
||||
virtual ~engine_cpp();
|
||||
|
||||
|
||||
void do_parse_aspect_from_config( const config &cfg, const std::string &id, std::back_insert_iterator<std::vector< aspect_ptr > > b );
|
||||
|
||||
|
||||
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 void do_parse_stage_from_config( ai_context &context, const config &cfg, std::back_insert_iterator<std::vector< stage_ptr > > b );
|
||||
|
||||
|
||||
virtual std::string get_name();
|
||||
virtual std::string get_name() const;
|
||||
|
||||
};
|
||||
|
||||
} //end of namespace composite_ai
|
||||
|
||||
} //end of namespace ai
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
|
||||
namespace ai {
|
||||
|
||||
namespace composite_ai {
|
||||
|
||||
static lg::log_domain log_ai_composite_engine_fai("ai/composite/engine/fai");
|
||||
#define DBG_AI_COMPOSITE_ENGINE_FAI LOG_STREAM(debug, log_ai_composite_engine_fai)
|
||||
#define LOG_AI_COMPOSITE_ENGINE_FAI LOG_STREAM(info, log_ai_composite_engine_fai)
|
||||
|
@ -40,8 +38,8 @@ static lg::log_domain log_ai_composite_engine_fai("ai/composite/engine/fai");
|
|||
|
||||
class fai_candidate_action_wrapper : public candidate_action {
|
||||
public:
|
||||
fai_candidate_action_wrapper( rca_context &context, const config &/*cfg*/, game_logic::candidate_action_ptr fai_ca, formula_ai &_formula_ai )
|
||||
: candidate_action(context,fai_ca->get_name(),fai_ca->get_type()),fai_ca_(fai_ca),formula_ai_(_formula_ai)
|
||||
fai_candidate_action_wrapper( rca_context &context, const config &cfg, game_logic::candidate_action_ptr fai_ca, formula_ai &_formula_ai )
|
||||
: candidate_action(context,cfg),fai_ca_(fai_ca),formula_ai_(_formula_ai),cfg_(cfg)//@todo 1.7: implement fai_ca->to_config()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -60,17 +58,23 @@ public:
|
|||
{
|
||||
return formula_ai_.execute_candidate_action(fai_ca_);
|
||||
}
|
||||
|
||||
virtual config to_config() const
|
||||
{
|
||||
return cfg_;
|
||||
}
|
||||
private:
|
||||
game_logic::candidate_action_ptr fai_ca_;
|
||||
formula_ai &formula_ai_;
|
||||
const config &cfg_;
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
engine_fai::engine_fai( composite_ai_context &context, const config &cfg )
|
||||
: engine(context,cfg), formula_ai_(context)
|
||||
engine_fai::engine_fai( readonly_context &context, const config &cfg )
|
||||
: engine(context,cfg)/*, formula_ai_(context,cfg.child("formula_ai"))*///@fixme
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -81,24 +85,30 @@ engine_fai::~engine_fai()
|
|||
}
|
||||
|
||||
|
||||
void engine_fai::do_parse_candidate_action_from_config( rca_context &context, const config &cfg, std::back_insert_iterator<std::vector< candidate_action_ptr > > b ){
|
||||
game_logic::candidate_action_ptr fai_ca = formula_ai_.load_candidate_action_from_config(cfg);
|
||||
void engine_fai::do_parse_candidate_action_from_config( rca_context &/*context*/, const config &/*cfg*/, std::back_insert_iterator<std::vector< candidate_action_ptr > > /*b*/ ){
|
||||
/*game_logic::candidate_action_ptr fai_ca = formula_ai_.load_candidate_action_from_config(cfg);
|
||||
if (!fai_ca) {
|
||||
ERR_AI_COMPOSITE_ENGINE_FAI << "side "<<ai_.get_side()<< " : ERROR creating candidate_action["<<cfg["name"]<<"]"<< std::endl;
|
||||
DBG_AI_COMPOSITE_ENGINE_FAI << "config snippet contains: " << std::endl << cfg << std::endl;
|
||||
return;
|
||||
}
|
||||
candidate_action_ptr ca = candidate_action_ptr(new fai_candidate_action_wrapper(context,cfg,fai_ca,formula_ai_));
|
||||
*b = ca;
|
||||
*b = ca; */
|
||||
|
||||
}
|
||||
|
||||
|
||||
std::string engine_fai::get_name()
|
||||
std::string engine_fai::get_name() const
|
||||
{
|
||||
return "fai";
|
||||
}
|
||||
|
||||
} //end of namespace composite_ai
|
||||
|
||||
config engine_fai::to_config() const
|
||||
{
|
||||
config cfg = engine::to_config();
|
||||
/*cfg.add_child("formula_ai",formula_ai_.to_config());*/
|
||||
return cfg;
|
||||
}
|
||||
|
||||
} //end of namespace ai
|
||||
|
|
|
@ -30,22 +30,20 @@
|
|||
//============================================================================
|
||||
namespace ai {
|
||||
|
||||
namespace composite_ai {
|
||||
|
||||
class engine_fai : public engine {
|
||||
public:
|
||||
engine_fai( composite_ai_context &context, const config &cfg );
|
||||
engine_fai( readonly_context &context, const config &cfg );
|
||||
|
||||
virtual ~engine_fai();
|
||||
|
||||
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 std::string get_name();
|
||||
private:
|
||||
formula_ai formula_ai_;
|
||||
};
|
||||
virtual std::string get_name() const;
|
||||
|
||||
} //end of namespace composite_ai
|
||||
virtual config to_config() const;
|
||||
private:
|
||||
//formula_ai formula_ai_;//@fixme
|
||||
};
|
||||
|
||||
} //end of namespace ai
|
||||
|
||||
|
|
69
src/ai/composite/goal.cpp
Normal file
69
src/ai/composite/goal.cpp
Normal file
|
@ -0,0 +1,69 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2009 by Yurii Chernyi <terraninfo@terraninfo.net>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
or at your option any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ai/composite/goal.cpp
|
||||
*/
|
||||
|
||||
#include "goal.hpp"
|
||||
#include "../manager.hpp"
|
||||
#include "../../log.hpp"
|
||||
#include "../../gamestatus.hpp"
|
||||
#include "../../variable.hpp"
|
||||
|
||||
namespace ai {
|
||||
|
||||
static lg::log_domain log_ai_composite_aspect("ai/composite/goal");
|
||||
#define DBG_AI_COMPOSITE_GOAL LOG_STREAM(debug, log_ai_composite_goal)
|
||||
#define LOG_AI_COMPOSITE_GOAL LOG_STREAM(info, log_ai_composite_goal)
|
||||
#define ERR_AI_COMPOSITE_GOAL LOG_STREAM(err, log_ai_composite_goal)
|
||||
|
||||
goal::goal(const config &cfg)
|
||||
: cfg_(cfg),loc_(),value_(),type_()
|
||||
{
|
||||
//@todo 1.7: parse config of goal
|
||||
}
|
||||
|
||||
|
||||
goal::goal(const map_location &loc, double value, TYPE type)
|
||||
: cfg_(),loc_(loc), value_(value), type_(type)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
goal::~goal()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//@todo: push to subclass
|
||||
bool goal::matches_unit(unit_map::const_iterator u)
|
||||
{
|
||||
if (!u.valid()) {
|
||||
return false;
|
||||
}
|
||||
config &criteria = cfg_.child("criteria");
|
||||
return u->second.matches_filter(vconfig(criteria),u->first);
|
||||
}
|
||||
|
||||
|
||||
config goal::to_config() const
|
||||
{
|
||||
config cfg;
|
||||
//@todo 1.7 recreate config
|
||||
return cfg;
|
||||
}
|
||||
|
||||
|
||||
} //end of namespace ai
|
68
src/ai/composite/goal.hpp
Normal file
68
src/ai/composite/goal.hpp
Normal file
|
@ -0,0 +1,68 @@
|
|||
/* $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/goal.hpp
|
||||
*/
|
||||
|
||||
#ifndef AI_COMPOSITE_GOAL_HPP_INCLUDED
|
||||
#define AI_COMPOSITE_GOAL_HPP_INCLUDED
|
||||
|
||||
#include "../../global.hpp"
|
||||
|
||||
#include "../game_info.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
|
||||
|
||||
namespace ai {
|
||||
|
||||
class goal {
|
||||
public:
|
||||
enum TYPE { VILLAGE, LEADER, EXPLICIT, THREAT, BATTLE_AID, MASS, SUPPORT };
|
||||
|
||||
|
||||
goal(const config &cfg);
|
||||
|
||||
|
||||
goal(const map_location &loc, double value, TYPE type=VILLAGE);
|
||||
|
||||
|
||||
virtual ~goal();
|
||||
|
||||
|
||||
bool matches_unit(unit_map::const_iterator u);
|
||||
|
||||
|
||||
config to_config() const;
|
||||
|
||||
|
||||
double value()
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
private:
|
||||
config cfg_;
|
||||
map_location loc_;
|
||||
double value_;
|
||||
TYPE type_;
|
||||
};
|
||||
|
||||
} //end of namespace ai
|
||||
|
||||
#endif
|
|
@ -25,8 +25,6 @@
|
|||
|
||||
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)
|
||||
|
@ -34,11 +32,10 @@ static lg::log_domain log_ai_composite_rca("ai/composite/rca");
|
|||
|
||||
const double candidate_action::BAD_SCORE = 0;
|
||||
|
||||
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)
|
||||
candidate_action::candidate_action(rca_context &context, const config &cfg)
|
||||
: recursion_counter_(context.get_recursion_count()), enabled_(utils::string_bool(cfg["enabled"],true)), engine_(cfg["engine"]), score_(lexical_cast_default<double>(cfg["score"],BAD_SCORE)),name_(cfg["name"]),type_(cfg["type"])
|
||||
{
|
||||
init_rca_context_proxy(context);
|
||||
//LOG_AI_COMPOSITE_RCA << "side "<< get_side() << " : "<<" created "<<*this<<std::endl;
|
||||
}
|
||||
|
||||
candidate_action::~candidate_action()
|
||||
|
@ -85,6 +82,18 @@ const std::string& candidate_action::get_type() const
|
|||
return type_;
|
||||
}
|
||||
|
||||
|
||||
config candidate_action::to_config() const
|
||||
{
|
||||
config cfg;
|
||||
cfg["enabled"] = lexical_cast<std::string>(enabled_);
|
||||
cfg["engine"] = engine_;
|
||||
cfg["name"] = name_;
|
||||
cfg["score"] = lexical_cast<std::string>(score_);
|
||||
cfg["type"] = type_;
|
||||
return cfg;
|
||||
}
|
||||
|
||||
candidate_action_evaluation_exception::candidate_action_evaluation_exception(const std::string &message)
|
||||
: message_(message)
|
||||
{
|
||||
|
@ -115,24 +124,23 @@ const std::string& candidate_action_execution_exception::get_message() const
|
|||
|
||||
|
||||
//============================================================================
|
||||
} //end of namespace composite_ai
|
||||
|
||||
} // of namespace ai
|
||||
|
||||
|
||||
std::ostream &operator<<(std::ostream &s, ai::composite_ai::candidate_action_evaluation_exception const &caee) {
|
||||
std::ostream &operator<<(std::ostream &s, 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) {
|
||||
std::ostream &operator<<(std::ostream &s, 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) {
|
||||
std::ostream &operator<<(std::ostream &s, ai::candidate_action const &ca) {
|
||||
s << "candidate action with name ["<< ca.get_name() <<"]";
|
||||
return s;
|
||||
}
|
||||
|
|
|
@ -39,8 +39,6 @@
|
|||
//============================================================================
|
||||
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
|
||||
|
@ -52,7 +50,7 @@ public:
|
|||
* @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 );
|
||||
candidate_action( rca_context &context, const config &cfg );
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
|
@ -103,13 +101,23 @@ public:
|
|||
*/
|
||||
const std::string& get_type() const;
|
||||
|
||||
|
||||
int get_recursion_count() const;
|
||||
|
||||
|
||||
/**
|
||||
* serialize
|
||||
*/
|
||||
virtual config to_config() const;
|
||||
|
||||
private:
|
||||
|
||||
recursion_counter recursion_counter_;
|
||||
|
||||
bool enabled_;
|
||||
|
||||
std::string engine_;
|
||||
|
||||
double score_;
|
||||
|
||||
std::string name_;
|
||||
|
@ -188,15 +196,14 @@ public:
|
|||
|
||||
|
||||
//============================================================================
|
||||
} //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::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::candidate_action_evaluation_exception const &caee);
|
||||
|
||||
std::ostream &operator<<(std::ostream &s, ai::composite_ai::candidate_action_execution_exception const &caee);
|
||||
std::ostream &operator<<(std::ostream &s, ai::candidate_action_execution_exception const &caee);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
|
||||
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)
|
||||
|
@ -38,10 +36,10 @@ static lg::log_domain log_ai_composite_stage("ai/composite/stage");
|
|||
// COMPOSITE AI STAGE
|
||||
// =======================================================================
|
||||
|
||||
stage::stage( composite_ai_context &context, const config &cfg )
|
||||
stage::stage( ai_context &context, const config &cfg )
|
||||
: recursion_counter_(context.get_recursion_count()), cfg_(cfg)
|
||||
{
|
||||
init_composite_ai_context_proxy(context);
|
||||
init_ai_context_proxy(context);
|
||||
}
|
||||
|
||||
void stage::on_create()
|
||||
|
@ -63,12 +61,20 @@ int stage::get_recursion_count() const
|
|||
return recursion_counter_.get_count();
|
||||
}
|
||||
|
||||
config stage::to_config() const
|
||||
{
|
||||
config cfg;
|
||||
cfg["engine"] = cfg_["engine"];
|
||||
cfg["name"] = cfg_["name"];
|
||||
return cfg;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// COMPOSITE AI IDLE STAGE
|
||||
// =======================================================================
|
||||
|
||||
|
||||
idle_stage::idle_stage( composite_ai_context &context, const config &cfg )
|
||||
idle_stage::idle_stage( ai_context &context, const config &cfg )
|
||||
: stage(context,cfg)
|
||||
{
|
||||
}
|
||||
|
@ -81,6 +87,5 @@ void idle_stage::do_play_stage(){
|
|||
LOG_AI_COMPOSITE_STAGE << "Turn " << get_info().tod_manager_.turn() << ": playing idle stage for side: "<< get_side() << std::endl;
|
||||
}
|
||||
|
||||
} //end of namespace composite_ai
|
||||
|
||||
} //end of namespace ai
|
||||
|
|
|
@ -37,17 +37,15 @@
|
|||
|
||||
namespace ai {
|
||||
|
||||
namespace composite_ai {
|
||||
|
||||
class ai_composite;
|
||||
|
||||
class stage : public virtual composite_ai_context_proxy {
|
||||
class stage : public virtual ai_context_proxy {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
stage( composite_ai_context &context, const config &cfg );
|
||||
stage( ai_context &context, const config &cfg );
|
||||
|
||||
/**
|
||||
* Initialization
|
||||
|
@ -71,6 +69,13 @@ public:
|
|||
*/
|
||||
int get_recursion_count() const;
|
||||
|
||||
|
||||
/**
|
||||
* serialize
|
||||
*/
|
||||
virtual config to_config() const;
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Play the turn - implementation
|
||||
|
@ -86,7 +91,7 @@ protected:
|
|||
|
||||
class idle_stage : public stage {
|
||||
public:
|
||||
idle_stage( composite_ai_context &context, const config &cfg );
|
||||
idle_stage( ai_context &context, const config &cfg );
|
||||
|
||||
~idle_stage();
|
||||
|
||||
|
@ -108,7 +113,7 @@ public:
|
|||
return *stage_factories;
|
||||
}
|
||||
|
||||
virtual stage_ptr get_new_instance( composite_ai_context &context, const config &cfg ) = 0;
|
||||
virtual stage_ptr get_new_instance( ai_context &context, const config &cfg ) = 0;
|
||||
|
||||
stage_factory( const std::string &name )
|
||||
{
|
||||
|
@ -128,7 +133,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual stage_ptr get_new_instance( composite_ai_context &context, const config &cfg ){
|
||||
virtual stage_ptr get_new_instance( ai_context &context, const config &cfg ){
|
||||
stage_ptr a(new STAGE(context,cfg));
|
||||
a->on_create();
|
||||
return a;
|
||||
|
@ -136,8 +141,6 @@ public:
|
|||
};
|
||||
|
||||
|
||||
} //end of namespace composite_ai
|
||||
|
||||
} //end of namespace ai
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include "../serialization/parser.hpp"
|
||||
#include "../serialization/preprocessor.hpp"
|
||||
#include "../team.hpp"
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace ai {
|
||||
|
||||
|
@ -35,11 +37,57 @@ static lg::log_domain log_ai_configuration("ai/config");
|
|||
#define WRN_AI_CONFIGURATION LOG_STREAM(warn, log_ai_configuration)
|
||||
#define ERR_AI_CONFIGURATION LOG_STREAM(err, log_ai_configuration)
|
||||
|
||||
|
||||
class well_known_aspect {
|
||||
public:
|
||||
well_known_aspect(const std::string &name, bool attr = true)
|
||||
: name_(name),was_an_attribute_(attr)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~well_known_aspect() {};
|
||||
|
||||
std::string name_;
|
||||
bool was_an_attribute_;
|
||||
};
|
||||
|
||||
std::vector<well_known_aspect> well_known_aspects;
|
||||
|
||||
void configuration::init(const config &game_config)
|
||||
{
|
||||
ai_configurations_.clear();
|
||||
well_known_aspects.clear();
|
||||
well_known_aspects.push_back(well_known_aspect("aggression"));
|
||||
well_known_aspects.push_back(well_known_aspect("attack_depth"));
|
||||
well_known_aspects.push_back(well_known_aspect("avoid",false));
|
||||
well_known_aspects.push_back(well_known_aspect("caution"));
|
||||
well_known_aspects.push_back(well_known_aspect("grouping"));
|
||||
well_known_aspects.push_back(well_known_aspect("leader_goal",false));
|
||||
well_known_aspects.push_back(well_known_aspect("leader_value"));
|
||||
well_known_aspects.push_back(well_known_aspect("number_of_possible_recruits_to_force_recruit"));
|
||||
well_known_aspects.push_back(well_known_aspect("passive_leader"));
|
||||
well_known_aspects.push_back(well_known_aspect("passive_leader_shares_keep"));
|
||||
//well_known_aspects.push_back(well_known_aspect("protect_leader"));
|
||||
//well_known_aspects.push_back(well_known_aspect("protect_leader_radius"));
|
||||
//well_known_aspects.push_back(well_known_aspect("protect_location",false));
|
||||
//well_known_aspects.push_back(well_known_aspect("protect_unit",false));
|
||||
well_known_aspects.push_back(well_known_aspect("recruitment_ignore_bad_combat"));
|
||||
well_known_aspects.push_back(well_known_aspect("recruitment_ignore_bad_movement"));
|
||||
well_known_aspects.push_back(well_known_aspect("recruitment_pattern"));
|
||||
well_known_aspects.push_back(well_known_aspect("scout_village_targeting"));
|
||||
well_known_aspects.push_back(well_known_aspect("simple_targeting"));
|
||||
well_known_aspects.push_back(well_known_aspect("support_villages"));
|
||||
well_known_aspects.push_back(well_known_aspect("village_value"));
|
||||
well_known_aspects.push_back(well_known_aspect("villages_per_scout"));
|
||||
|
||||
const config &ais = game_config.child("ais");
|
||||
default_config_ = ais.child("default_config");
|
||||
if (!default_config_) {
|
||||
ERR_AI_CONFIGURATION << "Missing AI [default_config]. Therefore, default_config_ set to empty." << std::endl;
|
||||
default_config_ = config();
|
||||
}
|
||||
|
||||
|
||||
foreach (const config &ai_configuration, ais.child_range("ai")) {
|
||||
const std::string &id = ai_configuration["id"];
|
||||
if (id.empty()){
|
||||
|
@ -84,19 +132,6 @@ const config& configuration::get_ai_config_for(const std::string &id)
|
|||
configuration::description_map configuration::ai_configurations_ = configuration::description_map();
|
||||
config configuration::default_config_ = config();
|
||||
|
||||
|
||||
static std::string bind_config_parameter( const std::string& value_from_config,
|
||||
const std::string& value_from_global_config,
|
||||
const std::string& default_value )
|
||||
{
|
||||
if (value_from_config!=""){
|
||||
return value_from_config;
|
||||
} else if (value_from_global_config!=""){
|
||||
return value_from_global_config;
|
||||
}
|
||||
return default_value;
|
||||
}
|
||||
|
||||
bool configuration::get_side_config_from_file(const std::string& file, config& cfg ){
|
||||
try {
|
||||
scoped_istream stream = preprocess_file(get_wml_location(file));
|
||||
|
@ -107,178 +142,204 @@ bool configuration::get_side_config_from_file(const std::string& file, config& c
|
|||
return false;
|
||||
}
|
||||
LOG_AI_CONFIGURATION << "Successfully read AI configuration from file '" << file << "'" << std::endl;
|
||||
return true;
|
||||
return cfg;//in boolean context
|
||||
}
|
||||
|
||||
const config& configuration::get_default_ai_parameters()
|
||||
{
|
||||
return default_config_;
|
||||
}
|
||||
|
||||
|
||||
bool configuration::parse_side_config(const config& cfg,
|
||||
std::string& ai_algorithm_type,
|
||||
config& global_ai_parameters,
|
||||
std::vector<config>& ai_parameters,
|
||||
const config& default_ai_parameters,
|
||||
config& ai_memory,
|
||||
config& effective_ai_parameters )
|
||||
bool configuration::upgrade_aspect_config_from_1_07_02_to_1_07_03(const config& cfg, config& parsed_cfg, const std::string &id, bool aspect_was_attribute)
|
||||
{
|
||||
config aspect_config;
|
||||
aspect_config["id"] = id;
|
||||
|
||||
foreach (const config &aiparam, cfg.child_range("ai")) {
|
||||
const config &_aspect = aiparam.find_child("aspect","id",id);
|
||||
if (_aspect) {
|
||||
aspect_config.append(_aspect);
|
||||
}
|
||||
|
||||
if (aspect_was_attribute && !aiparam.has_attribute(id)) {
|
||||
continue;//we are looking for an attribute but it isn't present
|
||||
}
|
||||
|
||||
if (!aspect_was_attribute && !aiparam.child(id)) {
|
||||
continue;//we are looking for a child but it isn't present
|
||||
}
|
||||
|
||||
config facet_config;
|
||||
facet_config["engine"] = "cpp";
|
||||
facet_config["name"] = "standard_aspect";
|
||||
if (aspect_was_attribute) {
|
||||
facet_config["value"] = aiparam[id];
|
||||
} else {
|
||||
foreach (const config &value, cfg.child_range(id)) {
|
||||
facet_config.add_child("value",value);
|
||||
}
|
||||
}
|
||||
|
||||
if (aiparam.has_attribute("turns")) {
|
||||
facet_config["turns"] = aiparam["turns"];
|
||||
}
|
||||
if (aiparam.has_attribute("time_of_day")) {
|
||||
facet_config["time_of_day"] = aiparam["time_of_day"];
|
||||
}
|
||||
|
||||
aspect_config.add_child("facet",facet_config);
|
||||
}
|
||||
|
||||
parsed_cfg.add_child("aspect",aspect_config);
|
||||
return parsed_cfg;//in boolean context
|
||||
}
|
||||
|
||||
|
||||
bool configuration::parse_side_config(const config& original_cfg, config &cfg )
|
||||
{
|
||||
LOG_AI_CONFIGURATION << "Parsing [side] configuration from config" << std::endl;
|
||||
|
||||
//leave only the [ai] children
|
||||
cfg = config();
|
||||
foreach (const config &aiparam, original_cfg.child_range("ai")) {
|
||||
cfg.add_child("ai",aiparam);
|
||||
}
|
||||
DBG_AI_CONFIGURATION << "Config contains:"<< std::endl << cfg << std::endl;
|
||||
|
||||
bool new_syntax=false;//@todo 1.8 remove old way when necessary
|
||||
bool default_config_applied = false;
|
||||
//check for default config
|
||||
foreach (const config &aiparam, cfg.child_range("ai")) {
|
||||
if (aiparam.child("stage")){
|
||||
new_syntax=true;
|
||||
if (aiparam.has_attribute("default_config_applied")) {
|
||||
default_config_applied = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_syntax) {
|
||||
DBG_AI_CONFIGURATION << "new syntax parsing rules"<< std::endl;
|
||||
return parse_side_config_new(cfg,ai_algorithm_type,global_ai_parameters,ai_parameters,default_ai_parameters,ai_memory,effective_ai_parameters);
|
||||
if (!default_config_applied) {
|
||||
//insert default config at the beginning
|
||||
if (default_config_) {
|
||||
LOG_AI_CONFIGURATION << "Applying default configuration" << std::endl;
|
||||
cfg.add_child_at("ai",default_config_,0);
|
||||
} else {
|
||||
WRN_AI_CONFIGURATION << "Default configuration is not available, do not applying it" << std::endl;
|
||||
}
|
||||
} else {
|
||||
DBG_AI_CONFIGURATION << "old syntax parsing rules"<< std::endl;
|
||||
return parse_side_config_old(cfg,ai_algorithm_type,global_ai_parameters,ai_parameters,default_ai_parameters,ai_memory,effective_ai_parameters);
|
||||
}
|
||||
}
|
||||
|
||||
bool configuration::parse_side_config_new(const config &cfg,
|
||||
std::string &ai_algorithm_type,
|
||||
config &global_ai_parameters,
|
||||
std::vector<config> &ai_parameters,
|
||||
const config &default_ai_parameters,
|
||||
config &ai_memory,
|
||||
config &effective_ai_parameters )
|
||||
{
|
||||
//construct new-style integrated config
|
||||
ai_parameters.push_back(default_ai_parameters);
|
||||
global_ai_parameters.append(default_ai_parameters);
|
||||
global_ai_parameters["ai_algorithm"] = "composite_ai";
|
||||
DBG_AI_CONFIGURATION << "after taking default values into account, new-style config contains:"<< std::endl << global_ai_parameters << std::endl;
|
||||
|
||||
foreach (const config &aiparam, cfg.child_range("ai"))
|
||||
{
|
||||
ai_parameters.push_back(aiparam);
|
||||
global_ai_parameters.append(aiparam);
|
||||
DBG_AI_CONFIGURATION << "Default configuration already applied" << std::endl;
|
||||
}
|
||||
|
||||
DBG_AI_CONFIGURATION << "finally, new-style config contains:"<< std::endl << global_ai_parameters << std::endl;
|
||||
|
||||
ai_algorithm_type = global_ai_parameters["ai_algorithm"];
|
||||
|
||||
//AI memory
|
||||
foreach (const config &aimem, global_ai_parameters.child_range("ai_memory")) {
|
||||
ai_memory.append(aimem);
|
||||
}
|
||||
|
||||
effective_ai_parameters["number_of_possible_recruits_to_force_recruit"]= global_ai_parameters["number_of_possible_recruits_to_force_recruit"];
|
||||
effective_ai_parameters["villages_per_scout"] = global_ai_parameters["villages_per_scout"];
|
||||
effective_ai_parameters["leader_value"] = global_ai_parameters["leader_value"];
|
||||
effective_ai_parameters["village_value"] = global_ai_parameters["village_value"];
|
||||
effective_ai_parameters["aggression"] = global_ai_parameters["aggression"];
|
||||
effective_ai_parameters["caution"] = global_ai_parameters["caution"];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool configuration::parse_side_config_old(const config& cfg,
|
||||
std::string& ai_algorithm_type,
|
||||
config& global_ai_parameters,
|
||||
std::vector<config>& ai_parameters,
|
||||
const config& default_ai_parameters,
|
||||
config& ai_memory,
|
||||
config& effective_ai_parameters )
|
||||
{
|
||||
|
||||
foreach (const config &aiparam, cfg.child_range("ai"))
|
||||
{
|
||||
ai_parameters.push_back(aiparam);
|
||||
//those AI parameters, which are always active, are also added to global ai parameters
|
||||
if (aiparam["turns"].empty() && aiparam["time_of_day"].empty()) {
|
||||
global_ai_parameters.append(aiparam);
|
||||
//find version
|
||||
int version = 10600;
|
||||
foreach (const config &aiparam, cfg.child_range("ai")) {
|
||||
if (aiparam.has_attribute("version")){
|
||||
int v = boost::lexical_cast<int>(aiparam["version"]);//@todo 1.7 parse version from more readable form, such as "1.7.3"
|
||||
if (version<v) {
|
||||
version = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
int original_version = version;
|
||||
|
||||
//AI memory
|
||||
foreach (const config &aimem, cfg.child_range("ai_memory")) {
|
||||
ai_memory.append(aimem);
|
||||
if (version<10703) {
|
||||
if (!upgrade_side_config_from_1_07_02_to_1_07_03(cfg)) {
|
||||
return false;
|
||||
}
|
||||
version = 10703;
|
||||
}
|
||||
|
||||
//set some default config values.
|
||||
//@todo 1.7 later, the entire 'ai parameter/ai memory/ai effective parameter' system should be refactored.
|
||||
//@todo 1.7 the following can also be rewritten to use a loop and a better version of bind_config_parameter [for each in default parameters T do bind_config_parameter(T,cfg,global_ai_params,defaults) ]
|
||||
ai_algorithm_type = bind_config_parameter(
|
||||
cfg["ai_algorithm"],
|
||||
global_ai_parameters["ai_algorithm"],
|
||||
default_ai_parameters["ai_algorithm"]);
|
||||
//construct new-style integrated config
|
||||
LOG_AI_CONFIGURATION << "Doing final operations on AI config"<< std::endl;
|
||||
config parsed_cfg = config();
|
||||
|
||||
effective_ai_parameters["number_of_possible_recruits_to_force_recruit"] = bind_config_parameter(
|
||||
cfg["number_of_possible_recruits_to_force_recruit"],
|
||||
global_ai_parameters["number_of_possible_recruits_to_force_recruit"],
|
||||
default_ai_parameters["number_of_possible_recruits_to_force_recruit"]);
|
||||
LOG_AI_CONFIGURATION << "Merging AI configurations"<< std::endl;
|
||||
foreach (const config &aiparam, cfg.child_range("ai")) {
|
||||
parsed_cfg.append(aiparam);
|
||||
}
|
||||
|
||||
effective_ai_parameters["villages_per_scout"] = bind_config_parameter(
|
||||
cfg["villages_per_scout"],
|
||||
global_ai_parameters["villages_per_scout"],
|
||||
default_ai_parameters["villages_per_scout"]);
|
||||
LOG_AI_CONFIGURATION << "Setting config version to "<< version << std::endl;
|
||||
parsed_cfg["version"] = boost::lexical_cast<std::string>( version );
|
||||
|
||||
effective_ai_parameters["leader_value"] = bind_config_parameter(
|
||||
cfg["leader_value"],
|
||||
global_ai_parameters["leader_value"],
|
||||
default_ai_parameters["leader_value"]);
|
||||
|
||||
effective_ai_parameters["village_value"] = bind_config_parameter(
|
||||
cfg["village_value"],
|
||||
global_ai_parameters["village_value"],
|
||||
default_ai_parameters["village_value"]);
|
||||
LOG_AI_CONFIGURATION << "Merging AI aspect with the same id"<< std::endl;
|
||||
parsed_cfg.merge_children_by_attribute("aspect","id");
|
||||
|
||||
effective_ai_parameters["aggression"] = bind_config_parameter(
|
||||
cfg["aggression"],
|
||||
global_ai_parameters["aggression"],
|
||||
default_ai_parameters["aggression"]);
|
||||
LOG_AI_CONFIGURATION << "Finally, applying [modify_ai] tags to configuration"<< std::endl;
|
||||
foreach (const config &mod_ai, cfg.child_range("modify_ai")){
|
||||
//do ai config modification without redeployement
|
||||
modify_ai_configuration(mod_ai,parsed_cfg);
|
||||
}
|
||||
|
||||
effective_ai_parameters["caution"] = bind_config_parameter(
|
||||
cfg["caution"],
|
||||
global_ai_parameters["caution"],
|
||||
default_ai_parameters["caution"]);
|
||||
DBG_AI_CONFIGURATION << "After applying [modify_ai] tags, config contains:"<< std::endl << parsed_cfg << std::endl;
|
||||
LOG_AI_CONFIGURATION << "Done parsing side config"<< std::endl;
|
||||
|
||||
cfg = parsed_cfg;
|
||||
return cfg;//in boolean context
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool configuration::upgrade_side_config_from_1_07_02_to_1_07_03(config &cfg)
|
||||
{
|
||||
LOG_AI_CONFIGURATION << "Upgrading ai config version from version 1.7.2 to 1.7.3"<< std::endl;
|
||||
config parsed_cfg = config();
|
||||
|
||||
//get values of all aspects
|
||||
foreach (const well_known_aspect &wka, well_known_aspects) {
|
||||
upgrade_aspect_config_from_1_07_02_to_1_07_03(cfg,parsed_cfg,wka.name_,wka.was_an_attribute_);
|
||||
}
|
||||
|
||||
|
||||
//dump the rest of the config into fallback stage
|
||||
|
||||
config fallback_stage_cfg;
|
||||
fallback_stage_cfg["engine"] = "cpp";
|
||||
fallback_stage_cfg["name"] = "testing_ai_default::fallback";
|
||||
fallback_stage_cfg["id"] = "fallback";
|
||||
config fallback_stage_cfg_ai;
|
||||
|
||||
bool default_config_applied = false;
|
||||
foreach (config &aiparam, cfg.child_range("ai")) {
|
||||
if (aiparam.has_attribute("default_config_applied")) {
|
||||
default_config_applied = true;
|
||||
}
|
||||
if (!aiparam.has_attribute("turns") && !aiparam.has_attribute("time_of_day")) {
|
||||
foreach (const well_known_aspect &wka, well_known_aspects) {
|
||||
if (wka.was_an_attribute_) {
|
||||
aiparam.remove_attribute(wka.name_);
|
||||
} else {
|
||||
aiparam.clear_children(wka.name_);
|
||||
}
|
||||
}
|
||||
fallback_stage_cfg_ai.append(aiparam);
|
||||
}
|
||||
}
|
||||
fallback_stage_cfg_ai.clear_children("aspect");//@todo 1.7: cleanup only configs of well-known ai aspects
|
||||
|
||||
//move stages to root of the config
|
||||
foreach (const config &aistage, fallback_stage_cfg_ai.child_range("stage")) {
|
||||
parsed_cfg.add_child("stage",aistage);
|
||||
}
|
||||
fallback_stage_cfg_ai.clear_children("stage");
|
||||
|
||||
fallback_stage_cfg.add_child("ai",fallback_stage_cfg_ai);
|
||||
|
||||
parsed_cfg.add_child("stage",fallback_stage_cfg);
|
||||
if (default_config_applied) {
|
||||
parsed_cfg["default_config_applied"] = "yes";
|
||||
parsed_cfg.remove_attribute("default_config_applied");
|
||||
}
|
||||
|
||||
cfg = config();
|
||||
cfg.add_child("ai",parsed_cfg);
|
||||
DBG_AI_CONFIGURATION << "After upgrade to 1.7.3 syntax, config contains:"<< std::endl << cfg << std::endl;
|
||||
return cfg;//in boolean context
|
||||
}
|
||||
|
||||
bool configuration::modify_ai_configuration(const config &/*mod_ai*/, config &/*parsed_cfg*/)
|
||||
{
|
||||
//@todo 1.7.3 implement
|
||||
return true;
|
||||
}
|
||||
|
||||
//some default values for the AI parameters following the default values listed
|
||||
//in the wiki at http://www.wesnoth.org/wiki/AiWML
|
||||
//@todo 1.7 think about reading this from config
|
||||
const config& configuration::get_default_ai_parameters(){
|
||||
static config default_cfg;
|
||||
if (!default_cfg["init"].empty()) {
|
||||
return default_cfg;
|
||||
}
|
||||
|
||||
default_cfg["init"] = "true";
|
||||
|
||||
default_cfg["ai_algorithm"] = "default_ai";
|
||||
|
||||
//A number 0 or higher which determines how many scouts the AI recruits. If 0,
|
||||
//the AI doesn't recruit scouts to capture villages.
|
||||
default_cfg["villages_per_scout"] = "4";
|
||||
|
||||
//A number 0 or higher which determines how much the AI targets enemy leaders.
|
||||
default_cfg["leader_value"] = "3.0";
|
||||
|
||||
//A number 0 or higher which determines how much the AI tries to capture villages.
|
||||
default_cfg["village_value"] = "1.0";
|
||||
|
||||
//details see in the [AI] tag explaination in the wiki:
|
||||
//http://www.wesnoth.org/wiki/AiWML#the_.5Bai.5D_tag
|
||||
default_cfg["aggression"] = "0.5";
|
||||
|
||||
//details see in the [AI] tag explaination in the wiki:
|
||||
//http://www.wesnoth.org/wiki/AiWML#the_.5Bai.5D_tag
|
||||
default_cfg["caution"] = "0.25";
|
||||
|
||||
//number_of_possible_recruits_to_force_recruit: a number higher than 0.0.
|
||||
//Tells AI to force the leader to move to a keep if it has enough gold to
|
||||
//recruit the given number of units. If set to 0.0, moving to recruit is disabled.
|
||||
default_cfg["number_of_possible_recruits_to_force_recruit"] = "3.1";
|
||||
LOG_AI_CONFIGURATION << "AI default configuration is created" << std::endl;
|
||||
return default_cfg;
|
||||
}
|
||||
|
||||
} //end of namespace ai
|
||||
|
|
|
@ -81,7 +81,7 @@ public:
|
|||
/**
|
||||
* get side config from file
|
||||
* @param file the file name to open. follows usual WML convention.
|
||||
* @param cfg[out] the config to be written from file.
|
||||
* @param[out] cfg the config to be written from file.
|
||||
* @return was all ok?
|
||||
* @retval true success
|
||||
* @retval false failure
|
||||
|
@ -89,60 +89,61 @@ public:
|
|||
static bool get_side_config_from_file( const std::string& file, config& cfg );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* modify a config of the ai by applying rules in [modify_ai] tag
|
||||
* @param[in] mod_ai config containing the contents of the [modify_ai] tag
|
||||
* @param[in][out] cfg ai configuration to modify
|
||||
* @return was all ok?
|
||||
* @retval true success, cfg is guaranteed to be valid
|
||||
* @retval false failure
|
||||
*/
|
||||
static bool modify_ai_configuration(const config &mod_ai, config &cfg);
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated bug-for-bug compatibility with current parameter handling
|
||||
* @param[in] cfg the config to be read
|
||||
* @param[out] ai_algorithm_type al algorithm type to be written
|
||||
* @param[out] global_ai_parameters global AI parameters to be written
|
||||
* @param[out] ai_parameters vector of [ai] section parameters.
|
||||
* @param[in] default_ai_parameters default ai parameters to use
|
||||
* @param[out] ai_memory ai memory to be written
|
||||
* @param[out] effective_ai_parameters effective ai parameters to be written
|
||||
* @param[out] parsed_cfg parsed config
|
||||
* @return was all ok?
|
||||
* @retval true success
|
||||
* @retval false failure
|
||||
*/
|
||||
static bool parse_side_config(const config& cfg,
|
||||
std::string& ai_algorithm_type,
|
||||
config& global_ai_parameters,
|
||||
std::vector<config>& ai_parameters,
|
||||
const config& default_ai_parameters,
|
||||
config& ai_memory,
|
||||
config& effective_ai_parameters );
|
||||
static bool parse_side_config(const config& cfg, config &parsed_cfg);
|
||||
|
||||
|
||||
private:
|
||||
/**
|
||||
* Upgrade aspect config from version 1.7.2 to version 1.7.3
|
||||
* @param[in] cfg the config to be read
|
||||
* @param[out] parsed_cfg parsed config
|
||||
* @param[in] id id of the aspect to work on
|
||||
* @param aspect_was_attribute aspect was an attribute, not a [child]
|
||||
* @return was all ok?
|
||||
* @retval true success
|
||||
* @retval false failure
|
||||
*/
|
||||
static bool upgrade_aspect_config_from_1_07_02_to_1_07_03(const config& cfg, config& parsed_cfg, const std::string &id, bool aspect_was_attribute = true);
|
||||
|
||||
|
||||
/**
|
||||
* Same as parse_side_config, new syntax
|
||||
* Upgrade side config from version 1.7.2 to version 1.7.3
|
||||
* @param[in] cfg the config to be read
|
||||
* @param[out] parsed_cfg parsed config
|
||||
* @return was all ok?
|
||||
* @retval true success, cfg is guaranteed to be valid
|
||||
* @retval false failure
|
||||
*/
|
||||
static bool parse_side_config_new(const config& cfg,
|
||||
std::string& ai_algorithm_type,
|
||||
config& global_ai_parameters,
|
||||
std::vector<config>& ai_parameters,
|
||||
const config& default_ai_parameters,
|
||||
config& ai_memory,
|
||||
config& effective_ai_parameters );
|
||||
static bool upgrade_side_config_from_1_07_02_to_1_07_03(config &cfg);
|
||||
|
||||
|
||||
/**
|
||||
* Same as parse_side_config, old syntax
|
||||
*/
|
||||
static bool parse_side_config_old(const config& cfg,
|
||||
std::string& ai_algorithm_type,
|
||||
config& global_ai_parameters,
|
||||
std::vector<config>& ai_parameters,
|
||||
const config& default_ai_parameters,
|
||||
config& ai_memory,
|
||||
config& effective_ai_parameters );
|
||||
|
||||
/**
|
||||
* get default AI parameters
|
||||
* @return default AI parameters
|
||||
*/
|
||||
static const config& get_default_ai_parameters();
|
||||
|
||||
private:
|
||||
typedef std::map<std::string, description> description_map;
|
||||
static std::map<std::string, description> ai_configurations_;
|
||||
static description_map ai_configurations_;
|
||||
static config default_config_;
|
||||
|
||||
};
|
||||
|
|
|
@ -20,6 +20,11 @@
|
|||
|
||||
#include "contexts.hpp"
|
||||
#include "manager.hpp"
|
||||
|
||||
#include "composite/aspect.hpp"
|
||||
#include "composite/engine.hpp"
|
||||
#include "composite/goal.hpp"
|
||||
|
||||
#include "../callable_objects.hpp"
|
||||
#include "../dialogs.hpp"
|
||||
#include "../formula.hpp"
|
||||
|
@ -89,12 +94,12 @@ void readwrite_context_impl::raise_enemy_attacked() const
|
|||
|
||||
|
||||
attack_result_ptr readwrite_context_impl::execute_attack_action(const map_location& attacker_loc, const map_location& defender_loc, int attacker_weapon){
|
||||
return actions::execute_attack_action(get_side(),true,attacker_loc,defender_loc,attacker_weapon);
|
||||
return actions::execute_attack_action(get_side(),true,attacker_loc,defender_loc,attacker_weapon, get_aggression());
|
||||
}
|
||||
|
||||
|
||||
attack_result_ptr readonly_context_impl::check_attack_action(const map_location& attacker_loc, const map_location& defender_loc, int attacker_weapon){
|
||||
return actions::execute_attack_action(get_side(),false,attacker_loc,defender_loc,attacker_weapon);
|
||||
return actions::execute_attack_action(get_side(),false,attacker_loc,defender_loc,attacker_weapon, get_aggression());
|
||||
}
|
||||
|
||||
|
||||
|
@ -127,23 +132,116 @@ stopunit_result_ptr readonly_context_impl::check_stopunit_action(const map_locat
|
|||
return actions::execute_stopunit_action(get_side(),false,unit_location,remove_movement,remove_attacks);
|
||||
}
|
||||
|
||||
readonly_context_impl::readonly_context_impl(side_context &context)
|
||||
: recursion_counter_(context.get_recursion_count()),dstsrc_(),enemy_dstsrc_(),enemy_possible_moves_(),enemy_srcdst_(),possible_moves_(),srcdst_(),avoided_locations_(),move_maps_enemy_valid_(false),move_maps_valid_(false)
|
||||
|
||||
template<typename T>
|
||||
void readonly_context_impl::add_known_aspect(const std::string &name, boost::shared_ptr< typesafe_aspect <T> > &where)
|
||||
{
|
||||
boost::shared_ptr< typesafe_known_aspect <T> > ka_ptr(new typesafe_known_aspect<T>(name,where,aspects_));
|
||||
known_aspects_.insert(make_pair(name,ka_ptr));
|
||||
}
|
||||
|
||||
readonly_context_impl::readonly_context_impl(side_context &context, const config &cfg)
|
||||
: cfg_(cfg),
|
||||
engines_(),
|
||||
known_aspects_(),
|
||||
aggression_(),
|
||||
attack_depth_(),
|
||||
aspects_(),
|
||||
avoid_(),
|
||||
caution_(),
|
||||
dstsrc_(),enemy_dstsrc_(),
|
||||
enemy_possible_moves_(),
|
||||
enemy_srcdst_(),
|
||||
grouping_(),
|
||||
goals_(),
|
||||
leader_goal_(),
|
||||
leader_value_(),
|
||||
move_maps_enemy_valid_(false),
|
||||
move_maps_valid_(false),
|
||||
number_of_possible_recruits_to_force_recruit_(),
|
||||
passive_leader_(),
|
||||
passive_leader_shares_keep_(),
|
||||
possible_moves_(),
|
||||
recruitment_ignore_bad_combat_(),
|
||||
recruitment_ignore_bad_movement_(),
|
||||
recruitment_pattern_(),
|
||||
recursion_counter_(context.get_recursion_count()),
|
||||
scout_village_targeting_(),
|
||||
simple_targeting_(),
|
||||
srcdst_(),
|
||||
support_villages_(),
|
||||
village_value_(),
|
||||
villages_per_scout_()
|
||||
{
|
||||
init_side_context_proxy(context);
|
||||
manager::add_gamestate_observer(this);
|
||||
|
||||
add_known_aspect("aggression",aggression_);
|
||||
add_known_aspect("attack_depth",attack_depth_);
|
||||
add_known_aspect("avoid",avoid_);
|
||||
add_known_aspect("caution",caution_);
|
||||
add_known_aspect("grouping",grouping_);
|
||||
add_known_aspect("leader_goal",leader_goal_);
|
||||
add_known_aspect("leader_value",leader_value_);
|
||||
add_known_aspect("number_of_possible_recruits_to_force_recruit",number_of_possible_recruits_to_force_recruit_);
|
||||
add_known_aspect("passive_leader",passive_leader_);
|
||||
add_known_aspect("passive_leader_shares_keep",passive_leader_shares_keep_);
|
||||
add_known_aspect("recruitment_ignore_bad_combat",recruitment_ignore_bad_combat_);
|
||||
add_known_aspect("recruitment_ignore_bad_movement",recruitment_ignore_bad_movement_);
|
||||
add_known_aspect("recruitment_pattern",recruitment_pattern_);
|
||||
add_known_aspect("scout_village_targeting",scout_village_targeting_);
|
||||
add_known_aspect("simple_targeting",simple_targeting_);
|
||||
add_known_aspect("support_villages",support_villages_);
|
||||
add_known_aspect("village_value",village_value_);
|
||||
add_known_aspect("villages_per_scout",villages_per_scout_);
|
||||
|
||||
}
|
||||
|
||||
void readonly_context_impl::on_readonly_context_create() {
|
||||
//init the composite ai engines
|
||||
foreach(const config &cfg_element, cfg_.child_range("engine")){
|
||||
engine::parse_engine_from_config(*this,cfg_element,std::back_inserter(engines_));
|
||||
}
|
||||
|
||||
// init the composite ai aspects
|
||||
foreach(const config &cfg_element, cfg_.child_range("aspect")){
|
||||
std::vector<aspect_ptr> aspects;
|
||||
engine::parse_aspect_from_config(*this,cfg_element,cfg_element["id"],std::back_inserter(aspects));
|
||||
add_aspects(aspects);
|
||||
}
|
||||
|
||||
// init the composite ai goals
|
||||
foreach(const config &cfg_element, cfg_.child_range("goal")){
|
||||
engine::parse_goal_from_config(*this,cfg_element,std::back_inserter(get_goals()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
config readonly_context_impl::to_readonly_context_config() const
|
||||
{
|
||||
config cfg;
|
||||
foreach(const engine_ptr e, engines_) {
|
||||
cfg.add_child("engine",e->to_config());
|
||||
}
|
||||
foreach(const aspect_map::value_type a, aspects_) {
|
||||
cfg.add_child("aspect",a.second->to_config());
|
||||
}
|
||||
foreach(const goal_ptr g, goals_) {
|
||||
cfg.add_child("goal",g->to_config());
|
||||
}
|
||||
cfg["default_config_applied"] = "yes";
|
||||
return cfg;
|
||||
}
|
||||
|
||||
readonly_context_impl::~readonly_context_impl()
|
||||
{
|
||||
manager::remove_gamestate_observer(this);
|
||||
}
|
||||
{
|
||||
manager::remove_gamestate_observer(this);
|
||||
}
|
||||
|
||||
void readonly_context_impl::handle_generic_event(const std::string& /*event_name*/)
|
||||
{
|
||||
invalidate_move_maps();
|
||||
}
|
||||
{
|
||||
invalidate_move_maps();
|
||||
}
|
||||
|
||||
|
||||
bool readwrite_context_impl::recruit(const std::string& unit_name, map_location loc)
|
||||
|
@ -431,14 +529,14 @@ map_location readwrite_context_impl::move_unit_partial(map_location from, map_lo
|
|||
|
||||
void readonly_context_impl::calculate_possible_moves(std::map<map_location,paths>& res, move_map& srcdst,
|
||||
move_map& dstsrc, bool enemy, bool assume_full_movement,
|
||||
const std::set<map_location>* remove_destinations) const
|
||||
const terrain_filter* remove_destinations) const
|
||||
{
|
||||
calculate_moves(get_info().units,res,srcdst,dstsrc,enemy,assume_full_movement,remove_destinations);
|
||||
}
|
||||
|
||||
void readonly_context_impl::calculate_moves(const unit_map& units, std::map<map_location,paths>& res, move_map& srcdst,
|
||||
move_map& dstsrc, bool enemy, bool assume_full_movement,
|
||||
const std::set<map_location>* remove_destinations,
|
||||
const terrain_filter* remove_destinations,
|
||||
bool see_all
|
||||
) const
|
||||
{
|
||||
|
@ -485,7 +583,7 @@ void readonly_context_impl::calculate_moves(const unit_map& units, std::map<map_
|
|||
const map_location& src = m->first;
|
||||
const map_location& dst = dest.curr;
|
||||
|
||||
if(remove_destinations != NULL && remove_destinations->count(dst) != 0) {
|
||||
if(remove_destinations != NULL && remove_destinations->match(dst)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -587,22 +685,63 @@ void readwrite_context_impl::attack_enemy(const map_location u,
|
|||
|
||||
}
|
||||
|
||||
const std::set<map_location>& readonly_context_impl::avoided_locations() const
|
||||
{
|
||||
if(avoided_locations_.empty()) {
|
||||
foreach (const config &av, current_team().ai_parameters().child_range("avoid"))
|
||||
{
|
||||
foreach (const map_location &loc, parse_location_range(av["x"], av["y"])) {
|
||||
avoided_locations_.insert(loc);
|
||||
}
|
||||
}
|
||||
|
||||
if(avoided_locations_.empty()) {
|
||||
avoided_locations_.insert(map_location());
|
||||
void readonly_context_impl::add_aspects(std::vector< aspect_ptr > &aspects )
|
||||
{
|
||||
foreach (aspect_ptr a, aspects) {
|
||||
const std::string name = a->get_id();
|
||||
known_aspect_map::iterator i = known_aspects_.find(name);
|
||||
if (i != known_aspects_.end()) {
|
||||
i->second->set(a);
|
||||
} else {
|
||||
ERR_AI << "when adding aspects, unknown aspect id["<<name<<"]"<<std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return avoided_locations_;
|
||||
|
||||
const terrain_filter& readonly_context_impl::get_avoid() const
|
||||
{
|
||||
if (avoid_) {
|
||||
return avoid_->get();
|
||||
}
|
||||
config cfg;
|
||||
cfg.add_child("not");
|
||||
static terrain_filter tf(vconfig(cfg),get_info().units);
|
||||
return tf;
|
||||
}
|
||||
|
||||
|
||||
double readonly_context_impl::get_aggression() const
|
||||
{
|
||||
if (aggression_) {
|
||||
return aggression_->get();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int readonly_context_impl::get_attack_depth() const
|
||||
{
|
||||
if (attack_depth_) {
|
||||
return std::max<int>(1,attack_depth_->get()); //@todo 1.7: add minmax filter to attack_depth aspect
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
const aspect_map& readonly_context_impl::get_aspects() const
|
||||
{
|
||||
return aspects_;
|
||||
}
|
||||
|
||||
|
||||
double readonly_context_impl::get_caution() const
|
||||
{
|
||||
if (caution_) {
|
||||
return caution_->get();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const move_map& readonly_context_impl::get_dstsrc() const
|
||||
|
@ -641,6 +780,105 @@ const move_map& readonly_context_impl::get_enemy_srcdst() const
|
|||
}
|
||||
|
||||
|
||||
engine_ptr readonly_context_impl::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 << "side "<<get_side()<<" : UNABLE TO FIND engine["<<
|
||||
engine_name <<"]" << std::endl;
|
||||
DBG_AI << "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 << "side "<<get_side()<<" : UNABLE TO CREATE engine["<<
|
||||
engine_name <<"] " << std::endl;
|
||||
DBG_AI << "config snippet contains: " << std::endl << cfg << std::endl;
|
||||
return engine_ptr();
|
||||
}
|
||||
engines_.push_back(new_engine);
|
||||
return engines_.back();
|
||||
}
|
||||
|
||||
std::string readonly_context_impl::get_grouping() const
|
||||
{
|
||||
if (grouping_) {
|
||||
return grouping_->get();
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
|
||||
const std::vector<goal_ptr>& readonly_context_impl::get_goals() const
|
||||
{
|
||||
return goals_;
|
||||
}
|
||||
|
||||
|
||||
std::vector<goal_ptr>& readonly_context_impl::get_goals()
|
||||
{
|
||||
return goals_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
config readonly_context_impl::get_leader_goal() const
|
||||
{
|
||||
if (leader_goal_) {
|
||||
return leader_goal_->get();
|
||||
}
|
||||
return config();
|
||||
}
|
||||
|
||||
|
||||
double readonly_context_impl::get_leader_value() const
|
||||
{
|
||||
if (leader_value_) {
|
||||
return leader_value_->get();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
double readonly_context_impl::get_number_of_possible_recruits_to_force_recruit() const
|
||||
{
|
||||
if (number_of_possible_recruits_to_force_recruit_) {
|
||||
return number_of_possible_recruits_to_force_recruit_->get();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool readonly_context_impl::get_passive_leader() const
|
||||
{
|
||||
if (passive_leader_) {
|
||||
return passive_leader_->get();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool readonly_context_impl::get_passive_leader_shares_keep() const
|
||||
{
|
||||
if (passive_leader_shares_keep_) {
|
||||
return passive_leader_shares_keep_->get();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const moves_map& readonly_context_impl::get_possible_moves() const
|
||||
{
|
||||
if (!move_maps_valid_) {
|
||||
|
@ -650,6 +888,51 @@ const moves_map& readonly_context_impl::get_possible_moves() const
|
|||
}
|
||||
|
||||
|
||||
bool readonly_context_impl::get_recruitment_ignore_bad_combat() const
|
||||
{
|
||||
if (recruitment_ignore_bad_combat_) {
|
||||
return recruitment_ignore_bad_combat_->get();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool readonly_context_impl::get_recruitment_ignore_bad_movement() const
|
||||
{
|
||||
if (recruitment_ignore_bad_movement_) {
|
||||
return recruitment_ignore_bad_movement_->get();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const std::vector<std::string> readonly_context_impl::get_recruitment_pattern() const
|
||||
{
|
||||
if (recruitment_pattern_) {
|
||||
return recruitment_pattern_->get();
|
||||
}
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
|
||||
|
||||
double readonly_context_impl::get_scout_village_targeting() const
|
||||
{
|
||||
if (scout_village_targeting_) {
|
||||
return scout_village_targeting_->get();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
bool readonly_context_impl::get_simple_targeting() const
|
||||
{
|
||||
if (simple_targeting_) {
|
||||
return simple_targeting_->get();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const move_map& readonly_context_impl::get_srcdst() const
|
||||
{
|
||||
if (!move_maps_valid_) {
|
||||
|
@ -659,9 +942,30 @@ const move_map& readonly_context_impl::get_srcdst() const
|
|||
}
|
||||
|
||||
|
||||
void readonly_context_impl::invalidate_avoided_locations_cache() const
|
||||
bool readonly_context_impl::get_support_villages() const
|
||||
{
|
||||
avoided_locations_.clear();
|
||||
if (support_villages_) {
|
||||
return support_villages_->get();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
double readonly_context_impl::get_village_value() const
|
||||
{
|
||||
if (village_value_) {
|
||||
return village_value_->get();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int readonly_context_impl::get_villages_per_scout() const
|
||||
{
|
||||
if (villages_per_scout_) {
|
||||
return villages_per_scout_->get();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -677,7 +981,7 @@ void readonly_context_impl::recalculate_move_maps() const
|
|||
dstsrc_ = move_map();
|
||||
possible_moves_ = moves_map();
|
||||
srcdst_ = move_map();
|
||||
calculate_possible_moves(possible_moves_,srcdst_,dstsrc_,false,false,&avoided_locations());
|
||||
calculate_possible_moves(possible_moves_,srcdst_,dstsrc_,false,false,&get_avoid());
|
||||
move_maps_valid_ = true;
|
||||
}
|
||||
|
||||
|
@ -691,5 +995,4 @@ void readonly_context_impl::recalculate_move_maps_enemy() const
|
|||
move_maps_enemy_valid_ = true;
|
||||
}
|
||||
|
||||
|
||||
} //of namespace ai
|
||||
|
|
|
@ -38,11 +38,12 @@ class gamemap;
|
|||
#pragma warning(disable:4250)
|
||||
#endif
|
||||
|
||||
class terrain_filter;
|
||||
|
||||
namespace ai {
|
||||
|
||||
class interface;
|
||||
|
||||
|
||||
// recursion counter
|
||||
class recursion_counter {
|
||||
public:
|
||||
|
@ -123,6 +124,7 @@ public:
|
|||
*/
|
||||
virtual int get_recursion_count() const = 0;
|
||||
|
||||
|
||||
};
|
||||
|
||||
class readonly_context;
|
||||
|
@ -131,6 +133,7 @@ public:
|
|||
readonly_context(){}
|
||||
virtual ~readonly_context(){}
|
||||
virtual readonly_context& get_readonly_context() = 0;
|
||||
virtual void on_readonly_context_create() = 0;
|
||||
virtual const team& current_team() const = 0;
|
||||
virtual void diagnostic(const std::string& msg) = 0;
|
||||
virtual void log_message(const std::string& msg) = 0;
|
||||
|
@ -141,11 +144,11 @@ public:
|
|||
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 = 0;
|
||||
const terrain_filter* remove_destinations=NULL) const = 0;
|
||||
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,
|
||||
const terrain_filter* remove_destinations=NULL,
|
||||
bool see_all=false) const = 0;
|
||||
|
||||
const virtual game_info& get_info() const = 0;
|
||||
|
@ -154,7 +157,24 @@ public:
|
|||
virtual void raise_user_interact() const = 0;
|
||||
|
||||
|
||||
virtual const std::set<map_location>& avoided_locations() const = 0;
|
||||
//@note: following part is in alphabetic order
|
||||
|
||||
virtual double get_aggression() const = 0;
|
||||
|
||||
|
||||
virtual int get_attack_depth() const = 0;
|
||||
|
||||
|
||||
virtual const aspect_map& get_aspects() const = 0;
|
||||
|
||||
|
||||
virtual void add_aspects(std::vector< aspect_ptr > &aspects ) = 0;
|
||||
|
||||
|
||||
virtual const terrain_filter& get_avoid() const = 0;
|
||||
|
||||
|
||||
virtual double get_caution() const = 0;
|
||||
|
||||
|
||||
virtual const move_map& get_dstsrc() const = 0;
|
||||
|
@ -168,14 +188,64 @@ public:
|
|||
|
||||
virtual const move_map& get_enemy_srcdst() const = 0;
|
||||
|
||||
/**
|
||||
* get engine by cfg, creating it if it is not created yet but known
|
||||
*/
|
||||
virtual engine_ptr get_engine(const config& cfg) = 0;
|
||||
|
||||
|
||||
virtual std::string get_grouping() const = 0;
|
||||
|
||||
|
||||
virtual const std::vector<goal_ptr>& get_goals() const = 0;
|
||||
|
||||
|
||||
virtual std::vector<goal_ptr>& get_goals() = 0;
|
||||
|
||||
|
||||
virtual config get_leader_goal() const = 0;
|
||||
|
||||
|
||||
virtual double get_leader_value() const = 0;
|
||||
|
||||
|
||||
virtual double get_number_of_possible_recruits_to_force_recruit() const = 0;
|
||||
|
||||
|
||||
virtual bool get_passive_leader() const = 0;
|
||||
|
||||
|
||||
virtual bool get_passive_leader_shares_keep() const = 0;
|
||||
|
||||
|
||||
virtual const moves_map& get_possible_moves() const = 0;
|
||||
|
||||
|
||||
virtual bool get_recruitment_ignore_bad_combat() const = 0;
|
||||
|
||||
|
||||
virtual bool get_recruitment_ignore_bad_movement() const = 0;
|
||||
|
||||
|
||||
virtual const std::vector<std::string> get_recruitment_pattern() const = 0;
|
||||
|
||||
|
||||
virtual double get_scout_village_targeting() const = 0;
|
||||
|
||||
|
||||
virtual bool get_simple_targeting() const = 0;
|
||||
|
||||
|
||||
virtual const move_map& get_srcdst() const = 0;
|
||||
|
||||
|
||||
virtual void invalidate_avoided_locations_cache() const = 0;
|
||||
virtual bool get_support_villages() const = 0;
|
||||
|
||||
|
||||
virtual double get_village_value() const = 0;
|
||||
|
||||
|
||||
virtual int get_villages_per_scout() const = 0;
|
||||
|
||||
|
||||
virtual void invalidate_move_maps() const = 0;
|
||||
|
@ -186,27 +256,63 @@ public:
|
|||
|
||||
virtual void recalculate_move_maps_enemy() const = 0;
|
||||
|
||||
|
||||
/**
|
||||
* serialize to config
|
||||
*/
|
||||
virtual config to_readonly_context_config() const = 0;
|
||||
};
|
||||
|
||||
class readwrite_context;
|
||||
class readwrite_context : public virtual readonly_context {
|
||||
public:
|
||||
readwrite_context(){}
|
||||
|
||||
|
||||
virtual ~readwrite_context(){}
|
||||
|
||||
|
||||
virtual readwrite_context& get_readwrite_context() = 0;
|
||||
|
||||
|
||||
virtual attack_result_ptr execute_attack_action(const map_location& attacker_loc, const map_location& defender_loc, int attacker_weapon) = 0;
|
||||
|
||||
|
||||
virtual move_result_ptr execute_move_action(const map_location& from, const map_location& to, bool remove_movement=true) = 0;
|
||||
|
||||
|
||||
virtual recruit_result_ptr execute_recruit_action(const std::string& unit_name, const map_location &where = map_location::null_location) = 0;
|
||||
|
||||
|
||||
virtual stopunit_result_ptr execute_stopunit_action(const map_location& unit_location, bool remove_movement = true, bool remove_attacks = false) = 0;
|
||||
|
||||
|
||||
virtual team& current_team_w() = 0;
|
||||
|
||||
|
||||
virtual void attack_enemy(const map_location u, const map_location target, int att_weapon, int def_weapon) = 0;
|
||||
|
||||
|
||||
virtual map_location move_unit(map_location from, map_location to, const moves_map &possible_moves) = 0;
|
||||
|
||||
|
||||
virtual map_location move_unit_partial(map_location from, map_location to, const moves_map &possible_moves) = 0;
|
||||
|
||||
|
||||
virtual bool recruit(const std::string& unit_name, map_location loc=map_location()) = 0;
|
||||
|
||||
|
||||
virtual void raise_unit_recruited() const = 0;
|
||||
|
||||
|
||||
virtual void raise_unit_moved() const = 0;
|
||||
|
||||
|
||||
virtual void raise_enemy_attacked() const = 0;
|
||||
|
||||
|
||||
virtual game_info& get_info_w() = 0;
|
||||
|
||||
};
|
||||
|
||||
//proxies
|
||||
|
@ -241,7 +347,8 @@ public:
|
|||
return target_->get_side_context();
|
||||
}
|
||||
|
||||
virtual int get_recursion_count(){
|
||||
virtual int get_recursion_count()
|
||||
{
|
||||
return target_->get_recursion_count();
|
||||
}
|
||||
|
||||
|
@ -270,6 +377,13 @@ public:
|
|||
return target_->get_readonly_context();
|
||||
}
|
||||
|
||||
|
||||
virtual void on_readonly_context_create()
|
||||
{
|
||||
return target_->on_readonly_context_create();
|
||||
}
|
||||
|
||||
|
||||
virtual const team& current_team() const
|
||||
{
|
||||
return target_->current_team();
|
||||
|
@ -308,7 +422,7 @@ public:
|
|||
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
|
||||
const terrain_filter* remove_destinations=NULL) const
|
||||
{
|
||||
target_->calculate_possible_moves(possible_moves, srcdst, dstsrc, enemy, assume_full_movement, remove_destinations);
|
||||
}
|
||||
|
@ -316,7 +430,7 @@ public:
|
|||
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,
|
||||
const terrain_filter* remove_destinations=NULL,
|
||||
bool see_all=false) const
|
||||
{
|
||||
target_->calculate_moves(units, possible_moves, srcdst, dstsrc, enemy, assume_full_movement, remove_destinations, see_all);
|
||||
|
@ -333,17 +447,49 @@ public:
|
|||
}
|
||||
|
||||
|
||||
virtual const std::set<map_location>& avoided_locations() const
|
||||
{
|
||||
return target_->avoided_locations();
|
||||
}
|
||||
|
||||
|
||||
virtual int get_recursion_count() const
|
||||
{
|
||||
return target_->get_recursion_count();
|
||||
}
|
||||
|
||||
//@note: following part is in alphabetic order
|
||||
|
||||
|
||||
virtual double get_aggression() const
|
||||
{
|
||||
return target_->get_aggression();
|
||||
}
|
||||
|
||||
|
||||
virtual int get_attack_depth() const
|
||||
{
|
||||
return target_->get_attack_depth();
|
||||
}
|
||||
|
||||
|
||||
virtual const aspect_map& get_aspects() const
|
||||
{
|
||||
return target_->get_aspects();
|
||||
}
|
||||
|
||||
|
||||
virtual void add_aspects(std::vector< aspect_ptr > &aspects )
|
||||
{
|
||||
return target_->add_aspects(aspects);
|
||||
}
|
||||
|
||||
|
||||
virtual const terrain_filter& get_avoid() const
|
||||
{
|
||||
return target_->get_avoid();
|
||||
}
|
||||
|
||||
|
||||
virtual double get_caution() const
|
||||
{
|
||||
return target_->get_caution();
|
||||
}
|
||||
|
||||
|
||||
virtual const move_map& get_dstsrc() const
|
||||
{
|
||||
|
@ -369,21 +515,117 @@ public:
|
|||
}
|
||||
|
||||
|
||||
virtual engine_ptr get_engine(const config &cfg)
|
||||
{
|
||||
return target_->get_engine(cfg);
|
||||
}
|
||||
|
||||
|
||||
virtual std::string get_grouping() const
|
||||
{
|
||||
return target_->get_grouping();
|
||||
}
|
||||
|
||||
|
||||
virtual const std::vector<goal_ptr>& get_goals() const
|
||||
{
|
||||
return target_->get_goals();
|
||||
}
|
||||
|
||||
|
||||
virtual std::vector<goal_ptr>& get_goals()
|
||||
{
|
||||
return target_->get_goals();
|
||||
}
|
||||
|
||||
|
||||
virtual config get_leader_goal() const
|
||||
{
|
||||
return target_->get_leader_goal();
|
||||
}
|
||||
|
||||
|
||||
virtual double get_leader_value() const
|
||||
{
|
||||
return target_->get_leader_value();
|
||||
}
|
||||
|
||||
|
||||
virtual double get_number_of_possible_recruits_to_force_recruit() const
|
||||
{
|
||||
return target_->get_number_of_possible_recruits_to_force_recruit();
|
||||
}
|
||||
|
||||
|
||||
virtual bool get_passive_leader() const
|
||||
{
|
||||
return target_->get_passive_leader();
|
||||
}
|
||||
|
||||
|
||||
virtual bool get_passive_leader_shares_keep() const
|
||||
{
|
||||
return target_->get_passive_leader_shares_keep();
|
||||
}
|
||||
|
||||
|
||||
virtual const moves_map& get_possible_moves() const
|
||||
{
|
||||
return target_->get_possible_moves();
|
||||
}
|
||||
|
||||
|
||||
virtual bool get_recruitment_ignore_bad_combat() const
|
||||
{
|
||||
return target_->get_recruitment_ignore_bad_combat();
|
||||
}
|
||||
|
||||
|
||||
virtual bool get_recruitment_ignore_bad_movement() const
|
||||
{
|
||||
return target_->get_recruitment_ignore_bad_movement();
|
||||
}
|
||||
|
||||
|
||||
virtual const std::vector<std::string> get_recruitment_pattern() const
|
||||
{
|
||||
return target_->get_recruitment_pattern();
|
||||
}
|
||||
|
||||
|
||||
virtual const move_map& get_srcdst() const
|
||||
{
|
||||
return target_->get_srcdst();
|
||||
}
|
||||
|
||||
|
||||
virtual void invalidate_avoided_locations_cache() const
|
||||
virtual double get_scout_village_targeting() const
|
||||
{
|
||||
target_->invalidate_avoided_locations_cache();
|
||||
return target_->get_scout_village_targeting();
|
||||
}
|
||||
|
||||
|
||||
virtual bool get_simple_targeting() const
|
||||
{
|
||||
return target_->get_simple_targeting();
|
||||
}
|
||||
|
||||
|
||||
virtual bool get_support_villages() const
|
||||
{
|
||||
return target_->get_support_villages();
|
||||
}
|
||||
|
||||
|
||||
virtual double get_village_value() const
|
||||
{
|
||||
return target_->get_village_value();
|
||||
}
|
||||
|
||||
|
||||
virtual int get_villages_per_scout() const
|
||||
{
|
||||
return target_->get_villages_per_scout();
|
||||
}
|
||||
|
||||
|
||||
|
@ -404,6 +646,12 @@ public:
|
|||
target_->recalculate_move_maps_enemy();
|
||||
}
|
||||
|
||||
|
||||
virtual config to_readonly_context_config() const
|
||||
{
|
||||
return target_->to_readonly_context_config();
|
||||
}
|
||||
|
||||
private:
|
||||
readonly_context *target_;
|
||||
};
|
||||
|
@ -559,7 +807,7 @@ public:
|
|||
/**
|
||||
* Constructor
|
||||
*/
|
||||
readonly_context_impl(side_context &context);
|
||||
readonly_context_impl(side_context &context, const config &cfg);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -578,6 +826,9 @@ public:
|
|||
}
|
||||
|
||||
|
||||
virtual void on_readonly_context_create();
|
||||
|
||||
|
||||
/** Handle generic event */
|
||||
virtual void handle_generic_event(const std::string& event_name);
|
||||
|
||||
|
@ -667,13 +918,13 @@ public:
|
|||
* If true, the function will operate on the
|
||||
* assumption that all units can move their full
|
||||
* movement allotment.
|
||||
* @param remove_destinations a pointer to a set of possible destinations
|
||||
* @param remove_destinations a pointer to a terrain filter for possible destinations
|
||||
* to omit.
|
||||
*/
|
||||
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;
|
||||
const terrain_filter* remove_destinations=NULL) const;
|
||||
|
||||
/**
|
||||
* A more fundamental version of calculate_possible_moves which allows the
|
||||
|
@ -682,7 +933,7 @@ public:
|
|||
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,
|
||||
const terrain_filter* remove_destinations=NULL,
|
||||
bool see_all=false) const;
|
||||
|
||||
|
||||
|
@ -697,12 +948,27 @@ public:
|
|||
void raise_user_interact() const;
|
||||
|
||||
|
||||
virtual const std::set<map_location>& avoided_locations() const;
|
||||
|
||||
|
||||
virtual int get_recursion_count() const;
|
||||
|
||||
|
||||
//@note: following functions are in alphabetic order
|
||||
|
||||
|
||||
virtual double get_aggression() const;
|
||||
|
||||
|
||||
virtual int get_attack_depth() const;
|
||||
|
||||
|
||||
virtual const aspect_map& get_aspects() const;
|
||||
|
||||
|
||||
virtual const terrain_filter& get_avoid() const;
|
||||
|
||||
|
||||
virtual double get_caution() const;
|
||||
|
||||
|
||||
virtual const move_map& get_dstsrc() const;
|
||||
|
||||
|
||||
|
@ -715,13 +981,61 @@ public:
|
|||
virtual const move_map& get_enemy_srcdst() const;
|
||||
|
||||
|
||||
virtual engine_ptr get_engine(const config& cfg);
|
||||
|
||||
|
||||
virtual std::string get_grouping() const;
|
||||
|
||||
|
||||
virtual const std::vector<goal_ptr>& get_goals() const;
|
||||
|
||||
|
||||
virtual std::vector<goal_ptr>& get_goals();
|
||||
|
||||
|
||||
virtual double get_number_of_possible_recruits_to_force_recruit() const;
|
||||
|
||||
|
||||
virtual config get_leader_goal() const;
|
||||
|
||||
|
||||
virtual double get_leader_value() const;
|
||||
|
||||
|
||||
virtual bool get_passive_leader() const;
|
||||
|
||||
|
||||
virtual bool get_passive_leader_shares_keep() const;
|
||||
|
||||
|
||||
virtual const moves_map& get_possible_moves() const;
|
||||
|
||||
|
||||
virtual bool get_recruitment_ignore_bad_combat() const;
|
||||
|
||||
|
||||
virtual bool get_recruitment_ignore_bad_movement() const;
|
||||
|
||||
|
||||
virtual const std::vector<std::string> get_recruitment_pattern() const;
|
||||
|
||||
|
||||
virtual double get_scout_village_targeting() const;
|
||||
|
||||
|
||||
virtual bool get_simple_targeting() const;
|
||||
|
||||
|
||||
virtual const move_map& get_srcdst() const;
|
||||
|
||||
|
||||
virtual void invalidate_avoided_locations_cache() const;
|
||||
virtual bool get_support_villages() const;
|
||||
|
||||
|
||||
virtual double get_village_value() const;
|
||||
|
||||
|
||||
virtual int get_villages_per_scout() const;
|
||||
|
||||
|
||||
virtual void invalidate_move_maps() const;
|
||||
|
@ -732,17 +1046,57 @@ public:
|
|||
|
||||
virtual void recalculate_move_maps_enemy() const;
|
||||
|
||||
|
||||
virtual void add_aspects(std::vector< aspect_ptr > &aspects);
|
||||
|
||||
|
||||
void on_create();
|
||||
|
||||
|
||||
virtual config to_readonly_context_config() const;
|
||||
|
||||
private:
|
||||
recursion_counter recursion_counter_;
|
||||
template<typename T>
|
||||
void add_known_aspect(const std::string &name, boost::shared_ptr< typesafe_aspect <T> >& where);
|
||||
|
||||
const config cfg_;
|
||||
|
||||
/**
|
||||
* AI Support Engines
|
||||
*/
|
||||
std::vector< engine_ptr > engines_;
|
||||
|
||||
known_aspect_map known_aspects_;
|
||||
|
||||
aspect_type<double>::typesafe_ptr aggression_;
|
||||
aspect_type<int>::typesafe_ptr attack_depth_;
|
||||
aspect_map aspects_;
|
||||
mutable aspect_type<terrain_filter>::typesafe_ptr avoid_;
|
||||
aspect_type<double>::typesafe_ptr caution_;
|
||||
mutable move_map dstsrc_;
|
||||
mutable move_map enemy_dstsrc_;
|
||||
mutable moves_map enemy_possible_moves_;
|
||||
mutable move_map enemy_srcdst_;
|
||||
mutable moves_map possible_moves_;
|
||||
mutable move_map srcdst_;
|
||||
mutable std::set<map_location> avoided_locations_;
|
||||
aspect_type< std::string >::typesafe_ptr grouping_;
|
||||
std::vector< goal_ptr > goals_;
|
||||
aspect_type< config >::typesafe_ptr leader_goal_;
|
||||
aspect_type< double >::typesafe_ptr leader_value_;
|
||||
mutable bool move_maps_enemy_valid_;
|
||||
mutable bool move_maps_valid_;
|
||||
aspect_type<double>::typesafe_ptr number_of_possible_recruits_to_force_recruit_;
|
||||
aspect_type<bool>::typesafe_ptr passive_leader_;
|
||||
aspect_type<bool>::typesafe_ptr passive_leader_shares_keep_;
|
||||
mutable moves_map possible_moves_;
|
||||
aspect_type< bool >::typesafe_ptr recruitment_ignore_bad_combat_;
|
||||
aspect_type< bool >::typesafe_ptr recruitment_ignore_bad_movement_;
|
||||
aspect_type< std::vector<std::string> >::typesafe_ptr recruitment_pattern_;
|
||||
recursion_counter recursion_counter_;
|
||||
aspect_type< double >::typesafe_ptr scout_village_targeting_;
|
||||
aspect_type< bool >::typesafe_ptr simple_targeting_;
|
||||
mutable move_map srcdst_;
|
||||
aspect_type< bool >::typesafe_ptr support_villages_;
|
||||
aspect_type< double >::typesafe_ptr village_value_;
|
||||
aspect_type< int >::typesafe_ptr villages_per_scout_;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -54,7 +54,8 @@ namespace ai {
|
|||
|
||||
typedef util::array<map_location,6> adjacent_tiles_array;
|
||||
|
||||
idle_ai::idle_ai(readwrite_context &context) : recursion_counter_(context.get_recursion_count())
|
||||
idle_ai::idle_ai(readwrite_context &context, const config &cfg)
|
||||
: cfg_(cfg), recursion_counter_(context.get_recursion_count())
|
||||
{
|
||||
init_readwrite_context_proxy(context);
|
||||
}
|
||||
|
@ -75,6 +76,13 @@ void idle_ai::switch_side(side_number side)
|
|||
set_side(side);
|
||||
}
|
||||
|
||||
|
||||
config idle_ai::to_config() const
|
||||
{
|
||||
return config();
|
||||
}
|
||||
|
||||
|
||||
int idle_ai::get_recursion_count() const
|
||||
{
|
||||
return recursion_counter_.get_count();
|
||||
|
@ -91,8 +99,8 @@ void idle_ai::play_turn()
|
|||
/** Sample ai, with simple strategy. */
|
||||
class sample_ai : public readwrite_context_proxy, public interface {
|
||||
public:
|
||||
sample_ai(readwrite_context &context)
|
||||
: recursion_counter_(context.get_recursion_count()) {
|
||||
sample_ai(readwrite_context &context, const config &cfg)
|
||||
: cfg_(cfg), recursion_counter_(context.get_recursion_count()) {
|
||||
init_readwrite_context_proxy(context);
|
||||
}
|
||||
|
||||
|
@ -151,7 +159,7 @@ protected:
|
|||
|
||||
if(best_defense != -1) {
|
||||
move_unit(best_movement.second,best_movement.first,possible_moves);
|
||||
battle_context bc(get_info().units, best_movement.first, i->first, -1, -1, current_team().aggression());
|
||||
battle_context bc(get_info().units, best_movement.first, i->first, -1, -1, get_aggression());
|
||||
attack_enemy(best_movement.first,i->first,
|
||||
bc.get_attacker_stats().attack_num,
|
||||
bc.get_defender_stats().attack_num);
|
||||
|
@ -213,6 +221,12 @@ protected:
|
|||
}
|
||||
|
||||
|
||||
config to_config() const
|
||||
{
|
||||
return config();
|
||||
}
|
||||
|
||||
|
||||
bool do_recruitment() {
|
||||
const std::set<std::string>& options = current_team().recruits();
|
||||
if (!options.empty()) {
|
||||
|
@ -229,6 +243,7 @@ protected:
|
|||
return false;
|
||||
}
|
||||
private:
|
||||
const config &cfg_;
|
||||
recursion_counter recursion_counter_;
|
||||
};
|
||||
|
||||
|
@ -237,8 +252,9 @@ private:
|
|||
#endif
|
||||
|
||||
|
||||
ai_default::ai_default(default_ai_context &context) :
|
||||
ai_default::ai_default(default_ai_context &context, const config &cfg) :
|
||||
game_logic::formula_callable(),
|
||||
cfg_(cfg),
|
||||
recursion_counter_(context.get_recursion_count()),
|
||||
threats_found_(false),
|
||||
disp_(context.get_info().disp),
|
||||
|
@ -268,8 +284,6 @@ void ai_default::switch_side(side_number side){
|
|||
|
||||
void ai_default::new_turn()
|
||||
{
|
||||
invalidate_attack_depth_cache();
|
||||
invalidate_avoided_locations_cache();
|
||||
invalidate_defensive_position_cache();
|
||||
invalidate_recent_attacks_list();
|
||||
threats_found_ = false;
|
||||
|
@ -294,6 +308,13 @@ int ai_default::get_recursion_count() const
|
|||
return recursion_counter_.get_count();
|
||||
}
|
||||
|
||||
config ai_default::to_config() const
|
||||
{
|
||||
return config();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ai_default::recruit_usage(const std::string& usage)
|
||||
{
|
||||
raise_user_interact();
|
||||
|
@ -364,7 +385,9 @@ bool ai_default::recruit_usage(const std::string& usage)
|
|||
WRN_AI << warning;
|
||||
// Uncommented until the recruitment limiting macro can be fixed to not trigger this warning.
|
||||
//lg::wml_error << warning;
|
||||
return current_team_w().remove_recruitment_pattern_entry(usage);
|
||||
//@fixme
|
||||
//return current_team_w().remove_recruitment_pattern_entry(usage);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -456,7 +479,7 @@ map_location ai_default::move_unit(map_location from, map_location to, moves_map
|
|||
const unit_map::const_iterator itor = units_.find(*adj_i);
|
||||
if(itor != units_.end() && current_team().is_enemy(itor->second.side()) &&
|
||||
!itor->second.incapacitated()) {
|
||||
battle_context bc(units_, res, *adj_i, -1, -1, current_team().aggression());
|
||||
battle_context bc(units_, res, *adj_i, -1, -1, get_aggression());
|
||||
attack_enemy(res,itor->first,bc.get_attacker_stats().attack_num,bc.get_defender_stats().attack_num);
|
||||
break;
|
||||
}
|
||||
|
@ -512,7 +535,7 @@ void ai_default::find_threats()
|
|||
|
||||
threats_found_ = true;
|
||||
|
||||
const config& parms = current_team().ai_parameters();
|
||||
const config& parms = cfg_;
|
||||
|
||||
std::vector<protected_item> items;
|
||||
|
||||
|
@ -589,14 +612,14 @@ void ai_default::evaluate_recruiting_value(const map_location &leader_loc)
|
|||
recruiting_preferred_ = 0;
|
||||
return;
|
||||
}
|
||||
if (current_team().num_pos_recruits_to_force()< 0.01f)
|
||||
if (get_number_of_possible_recruits_to_force_recruit()< 0.01f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float free_slots = 0.0f;
|
||||
const float gold = static_cast<float>(current_team().gold());
|
||||
const float unit_price = static_cast<float>(current_team_w().average_recruit_price());
|
||||
const float unit_price = static_cast<float>(current_team().average_recruit_price());
|
||||
if (map_.is_keep(leader_loc))
|
||||
{
|
||||
std::set<map_location> checked_hexes;
|
||||
|
@ -606,15 +629,15 @@ void ai_default::evaluate_recruiting_value(const map_location &leader_loc)
|
|||
map_location loc = nearest_keep(leader_loc);
|
||||
if (units_.find(loc) == units_.end() && gold/unit_price > 1.0f)
|
||||
{
|
||||
free_slots -= current_team().num_pos_recruits_to_force();
|
||||
free_slots -= get_number_of_possible_recruits_to_force_recruit();
|
||||
}
|
||||
}
|
||||
recruiting_preferred_ = (gold/unit_price) - free_slots > current_team().num_pos_recruits_to_force();
|
||||
recruiting_preferred_ = (gold/unit_price) - free_slots > get_number_of_possible_recruits_to_force_recruit();
|
||||
DBG_AI << "recruiting preferred: " << (recruiting_preferred_?"yes":"no") <<
|
||||
" units to recruit: " << (gold/unit_price) <<
|
||||
" unit_price: " << unit_price <<
|
||||
" free slots: " << free_slots <<
|
||||
" limit: " << current_team().num_pos_recruits_to_force() << "\n";
|
||||
" limit: " << get_number_of_possible_recruits_to_force_recruit() << "\n";
|
||||
}
|
||||
|
||||
void ai_default::do_move()
|
||||
|
@ -630,11 +653,11 @@ void ai_default::do_move()
|
|||
|
||||
move_map srcdst, dstsrc, enemy_srcdst, enemy_dstsrc;
|
||||
|
||||
calculate_possible_moves(possible_moves,srcdst,dstsrc,false,false,&avoided_locations());
|
||||
calculate_possible_moves(possible_moves,srcdst,dstsrc,false,false,&get_avoid());
|
||||
calculate_possible_moves(enemy_possible_moves,enemy_srcdst,enemy_dstsrc,true);
|
||||
|
||||
const bool passive_leader_shares_keep = utils::string_bool(current_team().ai_parameters()["passive_leader_shares_keep"],false);
|
||||
const bool passive_leader = utils::string_bool(current_team().ai_parameters()["passive_leader"])||passive_leader_shares_keep;
|
||||
const bool passive_leader_shares_keep = get_passive_leader_shares_keep();
|
||||
const bool passive_leader = get_passive_leader()||passive_leader_shares_keep;
|
||||
|
||||
|
||||
unit_map::iterator leader = units_.find_leader(get_side());
|
||||
|
@ -815,9 +838,9 @@ bool ai_default::do_combat(std::map<map_location,paths>& possible_moves, const m
|
|||
if(skip_num > 0 && ((it - analysis.begin())%skip_num) && it->movements.size() > 1)
|
||||
continue;
|
||||
|
||||
const double rating = it->rating(current_team().aggression(),*this);
|
||||
const double rating = it->rating(get_aggression(),*this);
|
||||
LOG_AI << "attack option rated at " << rating << " ("
|
||||
<< current_team().aggression() << ")\n";
|
||||
<< get_aggression() << ")\n";
|
||||
|
||||
if (recruiting_preferred_)
|
||||
{
|
||||
|
@ -857,7 +880,7 @@ bool ai_default::do_combat(std::map<map_location,paths>& possible_moves, const m
|
|||
}
|
||||
|
||||
// Recalc appropriate weapons here: AI uses approximations.
|
||||
battle_context bc(units_, to, target_loc, -1, -1, current_team().aggression());
|
||||
battle_context bc(units_, to, target_loc, -1, -1, get_aggression());
|
||||
attack_enemy(to, target_loc, bc.get_attacker_stats().attack_num,
|
||||
bc.get_defender_stats().attack_num);
|
||||
|
||||
|
@ -965,7 +988,7 @@ bool ai_default::retreat_units(std::map<map_location,paths>& possible_moves,
|
|||
move_map fullmove_srcdst;
|
||||
move_map fullmove_dstsrc;
|
||||
calculate_possible_moves(dummy_possible_moves, fullmove_srcdst, fullmove_dstsrc,
|
||||
false, true, &avoided_locations());
|
||||
false, true, &get_avoid());
|
||||
|
||||
map_location leader_adj[6];
|
||||
if(leader != units_.end()) {
|
||||
|
@ -982,7 +1005,7 @@ bool ai_default::retreat_units(std::map<map_location,paths>& possible_moves,
|
|||
// We see the amount of power of each side on the situation,
|
||||
// and decide whether it should retreat.
|
||||
if(should_retreat(i->first, i, fullmove_srcdst, fullmove_dstsrc,
|
||||
enemy_dstsrc, current_team().caution())) {
|
||||
enemy_dstsrc, get_caution())) {
|
||||
|
||||
bool can_reach_leader = false;
|
||||
|
||||
|
@ -1276,7 +1299,7 @@ int ai_default::compare_unit_types(const unit_type& a, const unit_type& b) const
|
|||
void ai_default::analyze_potential_recruit_combat()
|
||||
{
|
||||
if(unit_combat_scores_.empty() == false ||
|
||||
utils::string_bool(current_team().ai_parameters()["recruitment_ignore_bad_combat"])) {
|
||||
get_recruitment_ignore_bad_combat()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1357,7 +1380,7 @@ private:
|
|||
void ai_default::analyze_potential_recruit_movements()
|
||||
{
|
||||
if(unit_movement_scores_.empty() == false ||
|
||||
utils::string_bool(current_team().ai_parameters()["recruitment_ignore_bad_movement"])) {
|
||||
get_recruitment_ignore_bad_movement()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1474,9 +1497,9 @@ bool ai_default::do_recruitment()
|
|||
// Let formula ai to do recruiting first
|
||||
if (get_recursion_count()<recursion_counter::MAX_COUNTER_VALUE)
|
||||
{
|
||||
if (!current_team().ai_parameters()["recruitment"].empty()){
|
||||
if (!cfg_["recruitment"].empty()){
|
||||
if (!formula_ai_){
|
||||
formula_ai_ptr_ = (manager::create_transient_ai(manager::AI_TYPE_FORMULA_AI, this));
|
||||
formula_ai_ptr_ = manager::create_transient_ai(manager::AI_TYPE_FORMULA_AI, cfg_,this);
|
||||
formula_ai_ = static_cast<formula_ai*> (formula_ai_ptr_.get());
|
||||
}
|
||||
|
||||
|
@ -1494,7 +1517,7 @@ bool ai_default::do_recruitment()
|
|||
analyze_potential_recruit_movements();
|
||||
analyze_potential_recruit_combat();
|
||||
|
||||
std::vector<std::string> options = current_team().recruitment_pattern();
|
||||
std::vector<std::string> options = get_recruitment_pattern();
|
||||
if (std::count(options.begin(), options.end(), "scout") > 0) {
|
||||
size_t neutral_villages = 0;
|
||||
|
||||
|
@ -1527,7 +1550,7 @@ bool ai_default::do_recruitment()
|
|||
// accounting for all neutral villages on the map.
|
||||
// We only look at villages closer to us, so we halve it,
|
||||
// making us get twice as many scouts.
|
||||
const int villages_per_scout = current_team().villages_per_scout()/2;
|
||||
const int villages_per_scout = get_villages_per_scout()/2;
|
||||
|
||||
// Get scouts depending on how many neutral villages there are.
|
||||
int scouts_wanted = villages_per_scout > 0 ? neutral_villages/villages_per_scout : 0;
|
||||
|
@ -1563,7 +1586,7 @@ bool ai_default::do_recruitment()
|
|||
bool ret = false;
|
||||
while (recruit_usage(options[rand()%options.size()])) {
|
||||
ret = true;
|
||||
options = current_team().recruitment_pattern();
|
||||
options = get_recruitment_pattern();
|
||||
if (options.empty()) {
|
||||
options.push_back("");
|
||||
}
|
||||
|
@ -1574,7 +1597,7 @@ bool ai_default::do_recruitment()
|
|||
|
||||
void ai_default::move_leader_to_goals( const move_map& enemy_dstsrc)
|
||||
{
|
||||
const config &goal = current_team().ai_parameters().child("leader_goal");
|
||||
const config &goal = get_leader_goal();
|
||||
|
||||
if (!goal) {
|
||||
LOG_AI << "No goal found\n";
|
||||
|
@ -1636,8 +1659,8 @@ void ai_default::move_leader_after_recruit(const move_map& /*srcdst*/,
|
|||
return;
|
||||
}
|
||||
|
||||
const bool passive_leader_shares_keep = utils::string_bool(current_team().ai_parameters()["passive_leader_shares_keep"],false);
|
||||
const bool passive_leader = utils::string_bool(current_team().ai_parameters()["passive_leader"])||passive_leader_shares_keep;
|
||||
const bool passive_leader_shares_keep = get_passive_leader_shares_keep();
|
||||
const bool passive_leader = get_passive_leader()||passive_leader_shares_keep;
|
||||
|
||||
const paths leader_paths(map_, units_, leader->first,
|
||||
teams_, false, false, current_team());
|
||||
|
@ -1740,7 +1763,7 @@ void ai_default::move_leader_after_recruit(const move_map& /*srcdst*/,
|
|||
std::map<map_location,paths> dummy_possible_moves;
|
||||
move_map fullmove_srcdst;
|
||||
move_map fullmove_dstsrc;
|
||||
calculate_possible_moves(dummy_possible_moves,fullmove_srcdst,fullmove_dstsrc,false,true,&avoided_locations());
|
||||
calculate_possible_moves(dummy_possible_moves,fullmove_srcdst,fullmove_dstsrc,false,true,&get_avoid());
|
||||
|
||||
if (should_retreat(leader->first, leader, fullmove_srcdst, fullmove_dstsrc, enemy_dstsrc, 0.5)) {
|
||||
desperate_attack(leader->first);
|
||||
|
|
|
@ -40,13 +40,15 @@ namespace ai {
|
|||
/** A trivial ai that sits around doing absolutely nothing. */
|
||||
class idle_ai : public readwrite_context_proxy, public interface {
|
||||
public:
|
||||
idle_ai(readwrite_context &context);
|
||||
idle_ai(readwrite_context &context, const config &cfg);
|
||||
void play_turn();
|
||||
void new_turn();
|
||||
virtual std::string describe_self();
|
||||
void switch_side(side_number side);
|
||||
int get_recursion_count() const;
|
||||
virtual config to_config() const;
|
||||
private:
|
||||
const config &cfg_;
|
||||
recursion_counter recursion_counter_;
|
||||
};
|
||||
|
||||
|
@ -54,12 +56,13 @@ class ai_default : public virtual default_ai_context_proxy, public interface, pu
|
|||
public:
|
||||
typedef map_location location;//will get rid of this later
|
||||
|
||||
ai_default(default_ai_context &context);
|
||||
ai_default(default_ai_context &context, const config &cfg);
|
||||
virtual ~ai_default();
|
||||
|
||||
virtual void play_turn();
|
||||
virtual void new_turn();
|
||||
virtual std::string describe_self();
|
||||
virtual config to_config() const;
|
||||
void switch_side(side_number side);
|
||||
|
||||
struct target {
|
||||
|
@ -79,6 +82,7 @@ public:
|
|||
/** get the recursion counter */
|
||||
int get_recursion_count() const;
|
||||
private:
|
||||
const config &cfg_;
|
||||
recursion_counter recursion_counter_;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -273,7 +273,7 @@ double attack_analysis::rating(double aggression, default_ai_context& ai_obj) co
|
|||
const double exposure_mod = uses_leader ? ai_obj.current_team().caution()* 8.0 : ai_obj.current_team().caution() * 4.0;
|
||||
const double exposure = exposure_mod*resources_used*((terrain_quality - alternative_terrain_quality)/10)*vulnerability/std::max<double>(0.01,support);
|
||||
#else
|
||||
const double exposure_mod = uses_leader ? 2.0 : ai_obj.current_team().caution();
|
||||
const double exposure_mod = uses_leader ? 2.0 : ai_obj.get_caution();
|
||||
const double exposure = exposure_mod*resources_used*(terrain_quality - alternative_terrain_quality)*vulnerability/std::max<double>(0.01,support);
|
||||
#endif
|
||||
LOG_AI << "attack option has base value " << value << " with exposure " << exposure << ": "
|
||||
|
|
|
@ -131,18 +131,6 @@ bool default_ai_context_impl::attack_close(const map_location& loc) const
|
|||
}
|
||||
|
||||
|
||||
int default_ai_context_impl::attack_depth()
|
||||
{
|
||||
if(attack_depth_ > 0) {
|
||||
return attack_depth_;
|
||||
}
|
||||
|
||||
const config& parms = current_team().ai_parameters();
|
||||
attack_depth_ = std::max<int>(1,lexical_cast_default<int>(parms["attack_depth"],5));
|
||||
return attack_depth_;
|
||||
}
|
||||
|
||||
|
||||
default_ai_context_impl::~default_ai_context_impl()
|
||||
{
|
||||
}
|
||||
|
@ -246,8 +234,8 @@ void default_ai_context_impl::do_attack_analysis(
|
|||
// This function is called fairly frequently, so interact with the user here.
|
||||
raise_user_interact();
|
||||
|
||||
if(cur_analysis.movements.size() >= size_t(attack_depth())) {
|
||||
//std::cerr << "ANALYSIS " << cur_analysis.movements.size() << " >= " << attack_depth() << "\n";
|
||||
if(cur_analysis.movements.size() >= size_t(get_attack_depth())) {
|
||||
//std::cerr << "ANALYSIS " << cur_analysis.movements.size() << " >= " << get_attack_depth() << "\n";
|
||||
return;
|
||||
}
|
||||
gamemap &map_ = get_info().map;
|
||||
|
@ -268,7 +256,7 @@ void default_ai_context_impl::do_attack_analysis(
|
|||
}
|
||||
|
||||
const double cur_rating = cur_analysis.movements.empty() ? -1.0 :
|
||||
cur_analysis.rating(current_team().aggression(),*this);
|
||||
cur_analysis.rating(get_aggression(),*this);
|
||||
|
||||
double rating_to_beat = cur_rating;
|
||||
|
||||
|
@ -469,13 +457,13 @@ void default_ai_context_impl::do_attack_analysis(
|
|||
|
||||
cur_analysis.is_surrounded = is_surrounded;
|
||||
|
||||
cur_analysis.analyze(map_, units_, *this, dstsrc, srcdst, enemy_dstsrc, current_team().aggression());
|
||||
cur_analysis.analyze(map_, units_, *this, dstsrc, srcdst, enemy_dstsrc, get_aggression());
|
||||
|
||||
//This logic to sometimes not add the attack because it doesn't
|
||||
//rate high enough seems to remove attacks from consideration
|
||||
//that should not be removed, so it has been removed.
|
||||
// -- David.
|
||||
// if(cur_analysis.rating(current_team().aggression(),*this) > rating_to_beat) {
|
||||
// if(cur_analysis.rating(get_aggression(),*this) > rating_to_beat) {
|
||||
|
||||
result.push_back(cur_analysis);
|
||||
used_locations[cur_position] = true;
|
||||
|
@ -501,11 +489,6 @@ default_ai_context& default_ai_context_impl::get_default_ai_context(){
|
|||
}
|
||||
|
||||
|
||||
void default_ai_context_impl::invalidate_attack_depth_cache(){
|
||||
attack_depth_ = 0;
|
||||
}
|
||||
|
||||
|
||||
void default_ai_context_impl::invalidate_defensive_position_cache()
|
||||
{
|
||||
defensive_position_cache_.clear();
|
||||
|
|
|
@ -176,9 +176,6 @@ public:
|
|||
virtual default_ai_context& get_default_ai_context() = 0;
|
||||
|
||||
|
||||
virtual void invalidate_attack_depth_cache() = 0;
|
||||
|
||||
|
||||
virtual void invalidate_defensive_position_cache() = 0;
|
||||
|
||||
|
||||
|
@ -302,12 +299,6 @@ public:
|
|||
void init_default_ai_context_proxy(default_ai_context &target);
|
||||
|
||||
|
||||
virtual void invalidate_attack_depth_cache()
|
||||
{
|
||||
target_->invalidate_attack_depth_cache();
|
||||
}
|
||||
|
||||
|
||||
void invalidate_defensive_position_cache()
|
||||
{
|
||||
return target_->invalidate_defensive_position_cache();
|
||||
|
@ -396,9 +387,6 @@ public:
|
|||
bool attack_close(const map_location& loc) const;
|
||||
|
||||
|
||||
int attack_depth();
|
||||
|
||||
|
||||
int count_free_hexes_in_castle(const map_location& loc, std::set<map_location> &checked_hexes);
|
||||
|
||||
|
||||
|
@ -408,7 +396,7 @@ public:
|
|||
|
||||
default_ai_context_impl(readwrite_context &context)
|
||||
: recursion_counter_(context.get_recursion_count()),unit_stats_cache_(),
|
||||
defensive_position_cache_(),attacks_(),keeps_(),attack_depth_()
|
||||
defensive_position_cache_(),attacks_(),keeps_()
|
||||
{
|
||||
init_readwrite_context_proxy(context);
|
||||
}
|
||||
|
@ -438,9 +426,6 @@ public:
|
|||
}
|
||||
|
||||
|
||||
virtual void invalidate_attack_depth_cache();
|
||||
|
||||
|
||||
virtual void invalidate_defensive_position_cache();
|
||||
|
||||
|
||||
|
@ -488,8 +473,6 @@ private:
|
|||
|
||||
std::set<map_location> keeps_;
|
||||
|
||||
int attack_depth_;
|
||||
|
||||
};
|
||||
|
||||
} //end of namespace ai
|
||||
|
|
|
@ -21,11 +21,13 @@
|
|||
#include "../../global.hpp"
|
||||
|
||||
#include "ai.hpp"
|
||||
#include "../composite/goal.hpp"
|
||||
|
||||
#include "../../foreach.hpp"
|
||||
#include "../../gettext.hpp"
|
||||
#include "../../log.hpp"
|
||||
#include "../../map.hpp"
|
||||
#include "../../terrain_filter.hpp"
|
||||
#include "../../wml_exception.hpp"
|
||||
|
||||
|
||||
|
@ -100,7 +102,7 @@ std::vector<ai_default::target> ai_default::find_targets(unit_map::const_iterato
|
|||
|
||||
const bool has_leader = leader != units_.end();
|
||||
|
||||
std::vector<target> targets;
|
||||
std::vector<ai_default::target> targets;
|
||||
|
||||
std::map<location,paths> friends_possible_moves;
|
||||
move_map friends_srcdst, friends_dstsrc;
|
||||
|
@ -129,8 +131,8 @@ std::vector<ai_default::target> ai_default::find_targets(unit_map::const_iterato
|
|||
assert(threats.empty() == false);
|
||||
|
||||
#ifdef SUOKKO
|
||||
//FIXME: sukko's veraion 29531 included this change. Correct?
|
||||
const double value = threat*lexical_cast_default<double>(current_team().ai_parameters()["protect_leader"], 3.0)/leader->second.hitpoints();
|
||||
//FIXME: suokko's revision 29531 included this change. Correct?
|
||||
const double value = threat*get_protect_leader()/leader->second.hitpoints();
|
||||
#else
|
||||
const double value = threat/double(threats.size());
|
||||
#endif
|
||||
|
@ -142,8 +144,8 @@ std::vector<ai_default::target> ai_default::find_targets(unit_map::const_iterato
|
|||
}
|
||||
|
||||
double corner_distance = distance_between(map_location(0,0), map_location(map_.w(),map_.h()));
|
||||
double village_value = current_team().village_value();
|
||||
if(has_leader && current_team().village_value() > 0.0) {
|
||||
double village_value = get_village_value();
|
||||
if(has_leader && get_village_value() > 0.0) {
|
||||
const std::vector<location>& villages = map_.villages();
|
||||
for(std::vector<location>::const_iterator t =
|
||||
villages.begin(); t != villages.end(); ++t) {
|
||||
|
@ -162,7 +164,7 @@ std::vector<ai_default::target> ai_default::find_targets(unit_map::const_iterato
|
|||
{
|
||||
//Support seems to cause the AI to just 'sit around' a lot, so
|
||||
//only turn it on if it's explicitly enabled.
|
||||
if(utils::string_bool(current_team().ai_parameters()["support_villages"])) {
|
||||
if(get_support_villages()) {
|
||||
double enemy = power_projection(*t, enemy_dstsrc);
|
||||
if (enemy > 0)
|
||||
{
|
||||
|
@ -185,7 +187,7 @@ std::vector<ai_default::target> ai_default::find_targets(unit_map::const_iterato
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<team::target>& team_targets = current_team_w().targets();
|
||||
std::vector<goal_ptr>& goals = get_goals();
|
||||
|
||||
//find the enemy leaders and explicit targets
|
||||
unit_map::const_iterator u;
|
||||
|
@ -195,18 +197,20 @@ std::vector<ai_default::target> ai_default::find_targets(unit_map::const_iterato
|
|||
if (u->second.can_recruit() && current_team().is_enemy(u->second.side())
|
||||
&& !u->second.invisible(u->first, units_, teams_)) {
|
||||
assert(map_.on_board(u->first));
|
||||
LOG_AI << "found enemy leader (side: " << u->second.side() << ") target... " << u->first << " with value: " << current_team().leader_value() << "\n";
|
||||
targets.push_back(target(u->first,current_team().leader_value(),target::LEADER));
|
||||
LOG_AI << "found enemy leader (side: " << u->second.side() << ") target... " << u->first << " with value: " << get_leader_value() << "\n";
|
||||
targets.push_back(target(u->first,get_leader_value(),target::LEADER));
|
||||
}
|
||||
|
||||
//explicit targets for this team
|
||||
for(std::vector<team::target>::iterator j = team_targets.begin();
|
||||
j != team_targets.end(); ++j) {
|
||||
if (u->second.matches_filter(vconfig(j->criteria), u->first)) {
|
||||
LOG_AI << "found explicit target... " << u->first << " with value: " << j->value << "\n";
|
||||
targets.push_back(target(u->first,j->value,target::EXPLICIT));
|
||||
|
||||
for(std::vector<goal_ptr>::iterator j = goals.begin();
|
||||
j != goals.end(); ++j) {
|
||||
if ((*j)->matches_unit(u)) {
|
||||
LOG_AI << "found explicit target... " << u->first << " with value: " << (*j)->value() << "\n";
|
||||
targets.push_back(target(u->first,(*j)->value(),target::EXPLICIT));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::vector<double> new_values;
|
||||
|
@ -471,7 +475,7 @@ std::pair<map_location,map_location> ai_default::choose_move(std::vector<target>
|
|||
|
||||
//choose the best target for that unit
|
||||
for(std::vector<target>::iterator tg = targets.begin(); tg != targets.end(); ++tg) {
|
||||
if(avoided_locations().count(tg->loc) > 0) {
|
||||
if(get_avoid().match(tg->loc)) {
|
||||
continue;
|
||||
}
|
||||
LOG_AI << "Considering target at: " << tg->loc <<"\n";
|
||||
|
@ -532,13 +536,7 @@ std::pair<map_location,map_location> ai_default::choose_move(std::vector<target>
|
|||
|
||||
//scouts also get a bonus for going after villages
|
||||
if(tg->type == target::VILLAGE) {
|
||||
if(current_team().ai_parameters().has_attribute("scout_village_targetting")) {
|
||||
rating *= lexical_cast_default<int>(current_team().ai_parameters()["scout_village_targetting"],3);
|
||||
lg::wml_error << "[ai_default] the 'scout_village_targetting' attribute is deprecated, support will be removed in version 1.7.0; use 'scout_village_targeting' instead\n";
|
||||
}
|
||||
else {
|
||||
rating *= lexical_cast_default<int>(current_team().ai_parameters()["scout_village_targeting"],3);
|
||||
}
|
||||
rating *= get_scout_village_targeting();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -555,7 +553,7 @@ std::pair<map_location,map_location> ai_default::choose_move(std::vector<target>
|
|||
}
|
||||
}
|
||||
|
||||
LOG_AI << "chose target...\n";
|
||||
LOG_AI << "choose target...\n";
|
||||
|
||||
|
||||
if(best_target == targets.end()) {
|
||||
|
@ -566,17 +564,9 @@ std::pair<map_location,map_location> ai_default::choose_move(std::vector<target>
|
|||
//if we have the 'simple_targeting' flag set, then we don't
|
||||
//see if any other units can put a better bid forward for this
|
||||
//target
|
||||
bool simple_targeting = false;
|
||||
if(current_team().ai_parameters().has_attribute("simple_targetting")) {
|
||||
simple_targeting = utils::string_bool(current_team().ai_parameters()["simple_targetting"]);
|
||||
lg::wml_error << "[ai_default] the 'simple_targetting' attribute is deprecated, support will be removed in version 1.7.0; use 'simple_targeting' instead\n";
|
||||
}
|
||||
else {
|
||||
simple_targeting = utils::string_bool(current_team().ai_parameters()["simple_targeting"]);
|
||||
}
|
||||
const bool& dumb_ai = simple_targeting;
|
||||
bool simple_targeting = get_simple_targeting();
|
||||
|
||||
if(dumb_ai == false) {
|
||||
if(simple_targeting == false) {
|
||||
LOG_AI << "complex targeting...\n";
|
||||
//now see if any other unit can put a better bid forward
|
||||
for(++u; u != units_.end(); ++u) {
|
||||
|
@ -666,7 +656,7 @@ std::pair<map_location,map_location> ai_default::choose_move(std::vector<target>
|
|||
for(std::vector<location>::const_iterator i = locs.begin(); i != locs.end(); ++i) {
|
||||
const int distance = distance_between(*i,best_target->loc);
|
||||
const int defense = best->second.defense_modifier(map_.get_terrain(*i));
|
||||
//FIXME: suokko multiplied by 10 * current_team().caution(). ?
|
||||
//FIXME: suokko multiplied by 10 * get_caution(). ?
|
||||
const double vulnerability = power_projection(*i,enemy_dstsrc);
|
||||
|
||||
if(best_loc.valid() == false || defense < best_defense || (defense == best_defense && vulnerability < best_vulnerability)) {
|
||||
|
@ -689,19 +679,19 @@ std::pair<map_location,map_location> ai_default::choose_move(std::vector<target>
|
|||
|
||||
bool dangerous = false;
|
||||
|
||||
if(current_team().ai_parameters()["grouping"] != "no") {
|
||||
if(get_grouping() != "no") {
|
||||
LOG_AI << "grouping...\n";
|
||||
const unit_map::const_iterator unit_at_target = units_.find(best_target->loc);
|
||||
int movement = best->second.movement_left();
|
||||
|
||||
const bool defensive_grouping = current_team().ai_parameters()["grouping"] == "defensive";
|
||||
const bool defensive_grouping = get_grouping() == "defensive";
|
||||
|
||||
//we stop and consider whether the route to this
|
||||
//target is dangerous, and whether we need to group some units to move in unison toward the target
|
||||
//if any point along the path is too dangerous for our single unit, then we hold back
|
||||
for(std::vector<location>::const_iterator i = best_route.steps.begin(); i != best_route.steps.end() && movement > 0; ++i) {
|
||||
|
||||
//FIXME: suokko multiplied by 10 * current_team().caution(). ?
|
||||
//FIXME: suokko multiplied by 10 * get_caution(). ?
|
||||
const double threat = power_projection(*i,enemy_dstsrc);
|
||||
//FIXME: sukko doubled the power-projection them in the second test. ?
|
||||
if((threat >= double(best->second.hitpoints()) && threat > power_projection(*i,fullmove_dstsrc)) ||
|
||||
|
@ -726,7 +716,7 @@ std::pair<map_location,map_location> ai_default::choose_move(std::vector<target>
|
|||
|
||||
const double our_strength = compare_groups(group,enemies,best_route.steps);
|
||||
|
||||
if(our_strength > 0.5 + current_team().caution()) {
|
||||
if(our_strength > 0.5 + get_caution()) {
|
||||
LOG_AI << "moving group\n";
|
||||
const bool res = move_group(dst,best_route.steps,group);
|
||||
if(res) {
|
||||
|
@ -762,7 +752,7 @@ std::pair<map_location,map_location> ai_default::choose_move(std::vector<target>
|
|||
for(move_map::const_iterator i = itors.first; i != itors.second; ++i) {
|
||||
const int distance = distance_between(target_loc,i->second);
|
||||
const int defense = un.defense_modifier(map_.get_terrain(i->second));
|
||||
//FIXME: suokko multiplied by 10 * current_team().caution(). ?
|
||||
//FIXME: suokko multiplied by 10 * get_caution(). ?
|
||||
const double threat = (power_projection(i->second,enemy_dstsrc)*defense)/100;
|
||||
|
||||
if(best_loc.valid() == false || (threat < std::max<double>(best_threat,max_acceptable_threat) && distance < best_distance)) {
|
||||
|
@ -804,7 +794,7 @@ std::pair<map_location,map_location> ai_default::choose_move(std::vector<target>
|
|||
while(its.first != its.second) {
|
||||
if(its.first->second == best->first) {
|
||||
if(!should_retreat(its.first->first,best,fullmove_srcdst,fullmove_dstsrc,enemy_dstsrc,
|
||||
current_team().caution())) {
|
||||
get_caution())) {
|
||||
const double value = best_target->value - best->second.cost()/20.0;
|
||||
|
||||
if(value > 0.0 && best_target->type != target::MASS) {
|
||||
|
|
|
@ -267,8 +267,7 @@ void ai_default::find_villages(
|
|||
{
|
||||
std::map<location, double> vulnerability;
|
||||
|
||||
const bool passive_leader = recruiting_preferred_ ||
|
||||
utils::string_bool(current_team().ai_parameters()["passive_leader"]);
|
||||
const bool passive_leader = recruiting_preferred_ || get_passive_leader();
|
||||
|
||||
size_t min_distance = 100000;
|
||||
|
||||
|
|
|
@ -31,8 +31,7 @@ static lg::log_domain log_ai("ai/dfool");
|
|||
|
||||
void dfool_ai::play_turn(){
|
||||
int team_num = get_side();
|
||||
const config& parms = current_team().ai_parameters();
|
||||
config ai_mem = current_team().ai_memory();
|
||||
const config& parms = cfg_;
|
||||
|
||||
LOG_AI << "dfool side:" << team_num << " of " << current_team().nteams() << '\n';
|
||||
|
||||
|
@ -182,8 +181,7 @@ static lg::log_domain log_ai("ai/dfool");
|
|||
}
|
||||
}
|
||||
|
||||
unit_memory_.write(ai_mem);
|
||||
current_team_w().set_ai_memory(ai_mem);
|
||||
//unit_memory_.write(ai_mem);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -112,8 +112,8 @@ namespace dfool {
|
|||
*/
|
||||
class dfool_ai : public default_ai_context_proxy, public interface {
|
||||
public:
|
||||
dfool_ai(default_ai_context &context)
|
||||
: recursion_counter_(context.get_recursion_count()), unit_memory_(context.current_team().ai_memory())
|
||||
dfool_ai(default_ai_context &context, const config &cfg)
|
||||
: cfg_(cfg), recursion_counter_(context.get_recursion_count()), unit_memory_(config())
|
||||
{
|
||||
init_default_ai_context_proxy(context);
|
||||
}
|
||||
|
@ -125,7 +125,14 @@ namespace dfool {
|
|||
virtual void new_turn()
|
||||
{
|
||||
}
|
||||
private:
|
||||
|
||||
|
||||
virtual config to_config() const{
|
||||
return config();
|
||||
}
|
||||
|
||||
private:
|
||||
const config &cfg_;
|
||||
recursion_counter recursion_counter_;
|
||||
// std::map<std::string,target> target_map_;
|
||||
unit_list all_units();
|
||||
|
|
|
@ -55,8 +55,9 @@ int formula_ai::get_recursion_count() const{
|
|||
}
|
||||
|
||||
|
||||
formula_ai::formula_ai(ai::default_ai_context &context) :
|
||||
ai_default(context),
|
||||
formula_ai::formula_ai(ai::default_ai_context &context, const config &cfg) :
|
||||
ai_default(context,cfg),
|
||||
cfg_(cfg),
|
||||
recursion_counter_(context.get_recursion_count()),
|
||||
recruit_formula_(),
|
||||
move_formula_(),
|
||||
|
@ -313,7 +314,7 @@ variant formula_ai::make_action(game_logic::const_formula_ptr formula_, const ga
|
|||
if(!formula_) {
|
||||
if(get_recursion_count()<ai::recursion_counter::MAX_COUNTER_VALUE) {
|
||||
LOG_AI << "Falling back to default AI.\n";
|
||||
ai::ai_ptr fallback( ai::manager::create_transient_ai(ai::manager::AI_TYPE_DEFAULT, this));
|
||||
ai::ai_ptr fallback( ai::manager::create_transient_ai(ai::manager::AI_TYPE_DEFAULT, config(), this));
|
||||
if (fallback){
|
||||
fallback->play_turn();
|
||||
}
|
||||
|
@ -686,7 +687,7 @@ variant formula_ai::execute_variant(const variant& var, bool commandline)
|
|||
} else
|
||||
{
|
||||
LOG_AI << "Explicit fallback to: " << fallback_command->key() << std::endl;
|
||||
ai::ai_ptr fallback( ai::manager::create_transient_ai(fallback_command->key(), this));
|
||||
ai::ai_ptr fallback( ai::manager::create_transient_ai(fallback_command->key(), config(), this));
|
||||
if(fallback) {
|
||||
fallback->play_turn();
|
||||
}
|
||||
|
@ -1065,7 +1066,7 @@ bool formula_ai::can_reach_unit(map_location unit_A, map_location unit_B) const
|
|||
void formula_ai::on_create(){
|
||||
//make sure we don't run out of refcount
|
||||
vars_.add_ref();
|
||||
const config& ai_param = current_team().ai_parameters();
|
||||
const config& ai_param = cfg_;
|
||||
|
||||
// load candidate actions from config
|
||||
candidate_action_manager_.load_config(ai_param, this, &function_table);
|
||||
|
@ -1091,7 +1092,7 @@ void formula_ai::on_create(){
|
|||
|
||||
|
||||
try{
|
||||
recruit_formula_ = game_logic::formula::create_optional_formula(current_team().ai_parameters()["recruitment"], &function_table);
|
||||
recruit_formula_ = game_logic::formula::create_optional_formula(cfg_["recruitment"], &function_table);
|
||||
}
|
||||
catch(formula_error& e) {
|
||||
handle_exception(e);
|
||||
|
@ -1099,7 +1100,7 @@ void formula_ai::on_create(){
|
|||
}
|
||||
|
||||
try{
|
||||
move_formula_ = game_logic::formula::create_optional_formula(current_team().ai_parameters()["move"], &function_table);
|
||||
move_formula_ = game_logic::formula::create_optional_formula(cfg_["move"], &function_table);
|
||||
}
|
||||
catch(formula_error& e) {
|
||||
handle_exception(e);
|
||||
|
@ -1164,3 +1165,8 @@ bool formula_ai::gamestate_change_observer::continue_check() {
|
|||
continue_counter_++;
|
||||
return true;
|
||||
}
|
||||
|
||||
config formula_ai::to_config() const
|
||||
{
|
||||
return cfg_;//@todo 1.7 add a proper serialization
|
||||
}
|
||||
|
|
|
@ -54,11 +54,12 @@ typedef std::multiset< unit_formula_pair, game_logic::unit_formula_compare > uni
|
|||
|
||||
class formula_ai : public ai::ai_default {
|
||||
public:
|
||||
explicit formula_ai(ai::default_ai_context &context);
|
||||
explicit formula_ai(ai::default_ai_context &context, const config &cfg);
|
||||
virtual ~formula_ai() {};
|
||||
virtual void play_turn();
|
||||
virtual void new_turn();
|
||||
virtual std::string describe_self();
|
||||
virtual config to_config() const;
|
||||
|
||||
typedef ai::move_map move_map;
|
||||
|
||||
|
@ -134,6 +135,7 @@ public:
|
|||
bool execute_candidate_action(game_logic::candidate_action_ptr fai_ca);
|
||||
|
||||
private:
|
||||
const config &cfg_;
|
||||
ai::recursion_counter recursion_counter_;
|
||||
void display_message(const std::string& msg) const;
|
||||
bool do_recruitment();
|
||||
|
|
|
@ -72,7 +72,7 @@ bool candidate_action_manager::evaluate_candidate_actions(formula_ai* ai, unit_m
|
|||
}
|
||||
|
||||
if( evaluated_candidate_actions_.empty() ||
|
||||
(*evaluated_candidate_actions_.begin())->get_score() <= 0 ) //@note ai::composite_ai::candidate_action::BAD_SCORE )
|
||||
(*evaluated_candidate_actions_.begin())->get_score() <= 0 ) //@note ai::candidate_action::BAD_SCORE )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
|
|
@ -48,6 +48,39 @@ class interface;
|
|||
|
||||
typedef boost::shared_ptr< interface > ai_ptr;
|
||||
|
||||
class aspect;
|
||||
class candidate_action;
|
||||
class engine;
|
||||
class goal;
|
||||
class known_aspect;
|
||||
class stage;
|
||||
|
||||
template<typename T>
|
||||
class typesafe_aspect;
|
||||
|
||||
template<typename T>
|
||||
struct aspect_type {
|
||||
typedef boost::shared_ptr< typesafe_aspect<T> > typesafe_ptr;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class typesafe_known_aspect;
|
||||
|
||||
template<typename T>
|
||||
struct known_aspect_type {
|
||||
typedef boost::shared_ptr< typesafe_known_aspect<T> > typesafe_ptr;
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr< aspect > aspect_ptr;
|
||||
typedef boost::shared_ptr< candidate_action > candidate_action_ptr;
|
||||
typedef boost::shared_ptr< engine > engine_ptr;
|
||||
typedef boost::shared_ptr< goal > goal_ptr;
|
||||
typedef boost::shared_ptr< known_aspect > known_aspect_ptr;
|
||||
typedef boost::shared_ptr< stage > stage_ptr;
|
||||
|
||||
typedef std::map<std::string, aspect_ptr > aspect_map;
|
||||
typedef std::map<std::string, known_aspect_ptr > known_aspect_map;
|
||||
|
||||
class game_info {
|
||||
public:
|
||||
|
||||
|
|
|
@ -30,15 +30,20 @@
|
|||
|
||||
namespace ai {
|
||||
|
||||
class interface {
|
||||
class interface : savegame_config {
|
||||
public:
|
||||
/**
|
||||
* The constructor.
|
||||
*/
|
||||
interface() {
|
||||
interface()
|
||||
: savegame_config()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual ~interface() {}
|
||||
|
||||
|
||||
/**
|
||||
* Function that is called when the AI must play its turn.
|
||||
* Derived classes should implement their AI algorithm in this function.
|
||||
|
@ -66,6 +71,9 @@ public:
|
|||
/** Describe self*/
|
||||
virtual std::string describe_self() const;
|
||||
|
||||
|
||||
/** serialize to config **/
|
||||
virtual config to_config() const = 0;
|
||||
};
|
||||
|
||||
class ai_factory;
|
||||
|
@ -85,7 +93,7 @@ public:
|
|||
}
|
||||
|
||||
/* cfg is commented out so far, because ai parameter handling is a mess atm */
|
||||
virtual ai_ptr get_new_instance( default_ai_context &context/*, const config &cfg*/) = 0;
|
||||
virtual ai_ptr get_new_instance( default_ai_context &context, const config &cfg) = 0;
|
||||
|
||||
ai_factory( const std::string &name )
|
||||
{
|
||||
|
@ -105,8 +113,8 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual ai_ptr get_new_instance( default_ai_context &context/*, const config &cfg*/){
|
||||
ai_ptr a(new AI(context));
|
||||
virtual ai_ptr get_new_instance( default_ai_context &context, const config &cfg){
|
||||
ai_ptr a(new AI(context,cfg));
|
||||
a->on_create();
|
||||
return a;
|
||||
}
|
||||
|
|
|
@ -53,8 +53,8 @@ static lg::log_domain log_ai_manager("ai/manager");
|
|||
#define LOG_AI_MANAGER LOG_STREAM(info, log_ai_manager)
|
||||
#define ERR_AI_MANAGER LOG_STREAM(err, log_ai_manager)
|
||||
|
||||
holder::holder( side_number side, const std::string& ai_algorithm_type )
|
||||
: ai_(), 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)
|
||||
holder::holder( side_number side, const config &cfg )
|
||||
: ai_(), side_context_(NULL), readonly_context_(NULL), readwrite_context_(NULL), default_ai_context_(NULL), side_(side), cfg_(cfg)
|
||||
{
|
||||
DBG_AI_MANAGER << describe_ai() << "Preparing new AI holder" << std::endl;
|
||||
}
|
||||
|
@ -62,29 +62,31 @@ holder::holder( side_number side, const std::string& ai_algorithm_type )
|
|||
|
||||
void holder::init( side_number side )
|
||||
{
|
||||
LOG_AI_MANAGER << describe_ai() << "Preparing to create new managed master AI" << std::endl;
|
||||
if (side_context_ == NULL) {
|
||||
side_context_ = new side_context_impl(side);
|
||||
side_context_ = new side_context_impl(side);//@todo 1.7.3 add config
|
||||
} else {
|
||||
side_context_->set_side(side);
|
||||
}
|
||||
if (readonly_context_ == NULL){
|
||||
readonly_context_ = new readonly_context_impl(*side_context_);
|
||||
readonly_context_ = new readonly_context_impl(*side_context_,cfg_);
|
||||
readonly_context_->on_readonly_context_create();
|
||||
}
|
||||
if (readwrite_context_ == NULL){
|
||||
readwrite_context_ = new readwrite_context_impl(*readonly_context_);
|
||||
readwrite_context_ = new readwrite_context_impl(*readonly_context_);//@todo 1.7.3 add config
|
||||
}
|
||||
if (default_ai_context_ == NULL){
|
||||
default_ai_context_ = new default_ai_context_impl(*readwrite_context_);
|
||||
default_ai_context_ = new default_ai_context_impl(*readwrite_context_);//@todo 1.7.3 add config
|
||||
}
|
||||
if (!this->ai_){
|
||||
ai_ = boost::shared_ptr<ai_composite>(new ai_composite(*default_ai_context_,cfg_));
|
||||
ai_->on_create();
|
||||
}
|
||||
this->ai_ = create_ai(side);
|
||||
if (!this->ai_) {
|
||||
ERR_AI_MANAGER << describe_ai()<<"AI lazy initialization error!" << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
holder::~holder()
|
||||
{
|
||||
if (this->ai_) {
|
||||
|
@ -113,74 +115,26 @@ interface& holder::get_ai_ref()
|
|||
}
|
||||
|
||||
|
||||
const std::string& holder::get_ai_algorithm_type() const
|
||||
config holder::to_config() const
|
||||
{
|
||||
return this->ai_algorithm_type_;
|
||||
if (!this->ai_) {
|
||||
return cfg_;
|
||||
} else {
|
||||
config cfg = ai_->to_config();
|
||||
if (this->readonly_context_) {
|
||||
cfg.merge_with(this->readonly_context_->to_readonly_context_config());
|
||||
}
|
||||
return cfg;//@todo 1.7.3: include all other upper contexts
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
config& holder::get_ai_memory()
|
||||
{
|
||||
return this->ai_memory_;
|
||||
}
|
||||
|
||||
|
||||
std::vector<config>& holder::get_ai_parameters()
|
||||
{
|
||||
return this->ai_parameters_;
|
||||
}
|
||||
|
||||
|
||||
void holder::set_ai_parameters( const std::vector<config>& ai_parameters )
|
||||
{
|
||||
this->ai_parameters_ = ai_parameters;
|
||||
DBG_AI_MANAGER << describe_ai() << "AI parameters are set." << std::endl;
|
||||
}
|
||||
|
||||
|
||||
config& holder::get_ai_effective_parameters()
|
||||
{
|
||||
return this->ai_effective_parameters_;
|
||||
}
|
||||
|
||||
|
||||
void holder::set_ai_effective_parameters( const config& ai_effective_parameters )
|
||||
{
|
||||
this->ai_effective_parameters_ = ai_effective_parameters;
|
||||
DBG_AI_MANAGER << describe_ai() << "AI effective parameters are set." << std::endl;
|
||||
}
|
||||
|
||||
|
||||
config& holder::get_ai_global_parameters()
|
||||
{
|
||||
return this->ai_global_parameters_;
|
||||
}
|
||||
|
||||
|
||||
void holder::set_ai_global_parameters( const config& ai_global_parameters )
|
||||
{
|
||||
this->ai_global_parameters_ = ai_global_parameters;
|
||||
DBG_AI_MANAGER << describe_ai() << "AI global parameters are set." << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void holder::set_ai_memory( const config& ai_memory )
|
||||
{
|
||||
this->ai_memory_ = ai_memory;
|
||||
DBG_AI_MANAGER << describe_ai() << "AI memory is set." << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void holder::set_ai_algorithm_type( const std::string& ai_algorithm_type ){
|
||||
this->ai_algorithm_type_ = ai_algorithm_type;
|
||||
DBG_AI_MANAGER << describe_ai() << "AI algorithm type is set to '"<< ai_algorithm_type_<< "'" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
const std::string holder::describe_ai()
|
||||
{
|
||||
std::string sidestr;
|
||||
//@todo 1.7 extract side naming to separate static function
|
||||
//@todo 1.7.3 refactor the command ai role
|
||||
if (this->side_ == manager::AI_TEAM_FALLBACK_AI){
|
||||
sidestr = "'fallback_side'";
|
||||
} else if (this->side_ == manager::AI_TEAM_COMMAND_AI){
|
||||
|
@ -191,23 +145,14 @@ const std::string holder::describe_ai()
|
|||
if (this->ai_!=NULL) {
|
||||
return this->ai_->describe_self()+std::string(" for side ")+sidestr+std::string(" : ");
|
||||
} else {
|
||||
return std::string("[")+this->ai_algorithm_type_+std::string("] (not initialized) for side ")+sidestr+std::string(" : ");
|
||||
return std::string("[")+cfg_["ai_algorithm"]+std::string("] (not initialized) for side ")+sidestr+std::string(" : ");
|
||||
}
|
||||
}
|
||||
|
||||
bool holder::is_mandate_ok()
|
||||
{
|
||||
DBG_AI_MANAGER << describe_ai() << "AI mandate is ok" << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
ai_ptr holder::create_ai( side_number side )
|
||||
const std::string holder::get_ai_identifier() const
|
||||
{
|
||||
assert (side > 0);
|
||||
assert (default_ai_context_!=NULL);
|
||||
//@note: ai_params, contexts, and ai_algorithm_type are supposed to be set before calling init( );
|
||||
return manager::create_transient_ai(ai_algorithm_type_,default_ai_context_);
|
||||
|
||||
return cfg_["id"];
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
|
@ -375,7 +320,7 @@ void manager::add_turn_started_observer( events::observer* event_observer )
|
|||
}
|
||||
|
||||
|
||||
void manager::delete_user_interact_observer( events::observer* event_observer )
|
||||
void manager::remove_user_interact_observer( events::observer* event_observer )
|
||||
{
|
||||
user_interact_.detach_handler(event_observer);
|
||||
}
|
||||
|
@ -387,25 +332,25 @@ void manager::delete_sync_network_observer( events::observer* event_observer )
|
|||
}
|
||||
|
||||
|
||||
void manager::delete_unit_recruited_observer( events::observer* event_observer )
|
||||
void manager::remove_unit_recruited_observer( events::observer* event_observer )
|
||||
{
|
||||
unit_recruited_.detach_handler(event_observer);
|
||||
}
|
||||
|
||||
|
||||
void manager::delete_unit_moved_observer( events::observer* event_observer )
|
||||
void manager::remove_unit_moved_observer( events::observer* event_observer )
|
||||
{
|
||||
unit_moved_.detach_handler(event_observer);
|
||||
}
|
||||
|
||||
|
||||
void manager::delete_enemy_attacked_observer( events::observer* event_observer )
|
||||
void manager::remove_enemy_attacked_observer( events::observer* event_observer )
|
||||
{
|
||||
enemy_attacked_.detach_handler(event_observer);
|
||||
}
|
||||
|
||||
|
||||
void manager::delete_turn_started_observer( events::observer* event_observer )
|
||||
void manager::remove_turn_started_observer( events::observer* event_observer )
|
||||
{
|
||||
turn_started_.detach_handler(event_observer);
|
||||
}
|
||||
|
@ -542,7 +487,7 @@ const std::string manager::internal_evaluate_command( side_number side, const st
|
|||
side_number side = lexical_cast<side_number>(cmd.at(1));
|
||||
std::string file = cmd.at(2);
|
||||
if (add_ai_for_side_from_file(side,file,false)){
|
||||
return std::string("AI MANAGER: added [")+manager::get_active_ai_algorithm_type_for_side(side)+std::string("] AI for side ")+lexical_cast<std::string>(side)+std::string(" from file ")+file;
|
||||
return std::string("AI MANAGER: added [")+manager::get_active_ai_identifier_for_side(side)+std::string("] AI for side ")+lexical_cast<std::string>(side)+std::string(" from file ")+file;
|
||||
} else {
|
||||
return std::string("AI MANAGER: failed attempt to add AI for side ")+lexical_cast<std::string>(side)+std::string(" from file ")+file;
|
||||
}
|
||||
|
@ -552,7 +497,7 @@ const std::string manager::internal_evaluate_command( side_number side, const st
|
|||
side_number side = lexical_cast<side_number>(cmd.at(1));
|
||||
std::string file = cmd.at(2);
|
||||
if (add_ai_for_side_from_file(side,file,true)){
|
||||
return std::string("AI MANAGER: added [")+manager::get_active_ai_algorithm_type_for_side(side)+std::string("] AI for side ")+lexical_cast<std::string>(side)+std::string(" from file ")+file;
|
||||
return std::string("AI MANAGER: added [")+manager::get_active_ai_identifier_for_side(side)+std::string("] AI for side ")+lexical_cast<std::string>(side)+std::string(" from file ")+file;
|
||||
} else {
|
||||
return std::string("AI MANAGER: failed attempt to add AI for side ")+lexical_cast<std::string>(side)+std::string(" from file ")+file;
|
||||
}
|
||||
|
@ -618,22 +563,14 @@ bool manager::add_ai_for_side_from_file( side_number side, const std::string& fi
|
|||
|
||||
|
||||
bool manager::add_ai_for_side_from_config( side_number side, const config& cfg, bool replace ){
|
||||
config ai_memory;//AI memory
|
||||
std::vector<config> ai_parameters;//AI parameters inside [ai] tags. May contain filters
|
||||
config global_ai_parameters ;//AI parameters which do not have a filter applied
|
||||
const config& default_ai_parameters = configuration::get_default_ai_parameters();//default AI parameters
|
||||
std::string ai_algorithm_type;//AI algorithm type
|
||||
config effective_ai_parameters;//legacy effective ai parameters
|
||||
config parsed_cfg;
|
||||
configuration::parse_side_config(cfg, parsed_cfg);
|
||||
|
||||
configuration::parse_side_config(cfg, ai_algorithm_type, global_ai_parameters, ai_parameters, default_ai_parameters, ai_memory, effective_ai_parameters);
|
||||
if (replace) {
|
||||
remove_ai_for_side (side);
|
||||
remove_ai_for_side(side);
|
||||
}
|
||||
holder new_holder(side,ai_algorithm_type);
|
||||
new_holder.set_ai_effective_parameters(effective_ai_parameters);
|
||||
new_holder.set_ai_global_parameters(global_ai_parameters);
|
||||
new_holder.set_ai_memory(ai_memory);
|
||||
new_holder.set_ai_parameters(ai_parameters);
|
||||
|
||||
holder new_holder(side,parsed_cfg);
|
||||
std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
|
||||
ai_stack_for_specific_side.push(new_holder);
|
||||
return true;
|
||||
|
@ -646,15 +583,16 @@ bool manager::add_ai_for_side( side_number side, const std::string& ai_algorithm
|
|||
if (replace) {
|
||||
remove_ai_for_side (side);
|
||||
}
|
||||
holder new_holder(side,ai_algorithm_type);
|
||||
config cfg;
|
||||
cfg["ai_algorithm"] = ai_algorithm_type;
|
||||
holder new_holder(side,cfg);
|
||||
std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
|
||||
ai_stack_for_specific_side.push(new_holder);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//@todo 1.7 refactor away from ai::manager
|
||||
ai_ptr manager::create_transient_ai( const std::string &ai_algorithm_type, default_ai_context *ai_context )
|
||||
ai_ptr manager::create_transient_ai(const std::string &ai_algorithm_type, const config &cfg, default_ai_context *ai_context )
|
||||
{
|
||||
assert(ai_context!=NULL);
|
||||
|
||||
|
@ -667,7 +605,7 @@ ai_ptr manager::create_transient_ai( const std::string &ai_algorithm_type, defau
|
|||
}
|
||||
}
|
||||
LOG_AI_MANAGER << "Creating new AI of type [" << ai_algorithm_type << "]"<< std::endl;
|
||||
ai_ptr new_ai = aii->second->get_new_instance(*ai_context);
|
||||
ai_ptr new_ai = aii->second->get_new_instance(*ai_context,cfg);
|
||||
return new_ai;
|
||||
}
|
||||
|
||||
|
@ -702,36 +640,17 @@ void manager::clear_ais()
|
|||
}
|
||||
|
||||
// =======================================================================
|
||||
// GET active AI parameters
|
||||
// Work with active AI parameters
|
||||
// =======================================================================
|
||||
|
||||
const std::vector<config>& manager::get_active_ai_parameters_for_side( side_number side )
|
||||
std::string manager::get_active_ai_identifier_for_side( side_number side )
|
||||
{
|
||||
return get_active_ai_holder_for_side(side).get_ai_parameters();
|
||||
return get_active_ai_holder_for_side(side).get_ai_identifier();
|
||||
}
|
||||
|
||||
|
||||
const config& manager::get_active_ai_effective_parameters_for_side( side_number side )
|
||||
config manager::to_config( side_number side )
|
||||
{
|
||||
return get_active_ai_holder_for_side(side).get_ai_effective_parameters();
|
||||
}
|
||||
|
||||
|
||||
const config& manager::get_active_ai_global_parameters_for_side( side_number side )
|
||||
{
|
||||
return get_active_ai_holder_for_side(side).get_ai_global_parameters();
|
||||
}
|
||||
|
||||
|
||||
const config& manager::get_active_ai_memory_for_side( side_number side )
|
||||
{
|
||||
return get_active_ai_holder_for_side(side).get_ai_memory();
|
||||
}
|
||||
|
||||
|
||||
const std::string& manager::get_active_ai_algorithm_type_for_side( side_number side )
|
||||
{
|
||||
return get_active_ai_holder_for_side(side).get_ai_algorithm_type();
|
||||
return get_active_ai_holder_for_side(side).to_config();
|
||||
}
|
||||
|
||||
|
||||
|
@ -746,39 +665,6 @@ game_info& manager::get_ai_info()
|
|||
return *ai_info_;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// SET active AI parameters
|
||||
// =======================================================================
|
||||
|
||||
void manager::set_active_ai_parameters_for_side( side_number side, const std::vector<config>& ai_parameters )
|
||||
{
|
||||
get_active_ai_holder_for_side(side).set_ai_parameters(ai_parameters);
|
||||
}
|
||||
|
||||
|
||||
void manager::set_active_ai_effective_parameters_for_side( side_number side, const config& ai_parameters )
|
||||
{
|
||||
get_active_ai_holder_for_side(side).set_ai_effective_parameters(ai_parameters);
|
||||
}
|
||||
|
||||
|
||||
void manager::set_active_ai_global_parameters_for_side( side_number side, const config& ai_global_parameters )
|
||||
{
|
||||
get_active_ai_holder_for_side(side).set_ai_global_parameters(ai_global_parameters);
|
||||
}
|
||||
|
||||
|
||||
void manager::set_active_ai_memory_for_side( side_number side, const config& ai_memory )
|
||||
{
|
||||
get_active_ai_holder_for_side(side).set_ai_memory(ai_memory);
|
||||
}
|
||||
|
||||
|
||||
void manager::set_active_ai_algorithm_type_for_side( side_number side, const std::string& ai_algorithm_type )
|
||||
{
|
||||
get_active_ai_holder_for_side(side).set_ai_algorithm_type(ai_algorithm_type);
|
||||
}
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// PROXY
|
||||
|
@ -849,7 +735,9 @@ holder& manager::get_or_create_active_ai_holder_for_side_without_fallback(side_n
|
|||
if (!ai_stack_for_specific_side.empty()){
|
||||
return ai_stack_for_specific_side.top();
|
||||
} else {
|
||||
holder new_holder(side, ai_algorithm_type);
|
||||
config cfg;
|
||||
cfg["ai_algorithm"] = ai_algorithm_type;
|
||||
holder new_holder(side, cfg);
|
||||
ai_stack_for_specific_side.push(new_holder);
|
||||
return ai_stack_for_specific_side.top();
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
* @file ai/ai_manager.hpp
|
||||
* Managing the AIs lifecycle - headers
|
||||
* @todo 1.7 Refactor history handling and internal commands.
|
||||
* @todo 1.7 Refactor all the mess with those AI parameters.
|
||||
* @todo 1.7 AI Interface command to clear the history.
|
||||
*/
|
||||
|
||||
|
@ -42,60 +41,41 @@ class readonly_context;
|
|||
class readwrite_context;
|
||||
class default_ai_context;
|
||||
|
||||
class ai_composite;
|
||||
typedef boost::shared_ptr<ai_composite> composite_ai_ptr;
|
||||
|
||||
/**
|
||||
* Base class that holds the AI and current AI parameters.
|
||||
* It is an implementation detail.
|
||||
* @todo 1.7.2 move it out of public view
|
||||
* @todo 1.7.3 move it out of public view
|
||||
*/
|
||||
class holder{
|
||||
public:
|
||||
holder(int side, const std::string& ai_algorithm_type);
|
||||
|
||||
void init( int side );
|
||||
holder(side_number side, const config &cfg);
|
||||
|
||||
virtual ~holder();
|
||||
|
||||
interface& get_ai_ref();
|
||||
interface& get_ai_ref( int side );
|
||||
|
||||
const std::string& get_ai_algorithm_type() const;
|
||||
void set_ai_algorithm_type(const std::string& ai_algorithm_type);
|
||||
|
||||
const config& get_ai_memory() const;
|
||||
config& get_ai_memory();
|
||||
void set_ai_memory(const config& ai_memory);
|
||||
|
||||
const std::vector<config>& get_ai_parameters() const;
|
||||
std::vector<config>& get_ai_parameters();
|
||||
void set_ai_parameters(const std::vector<config>& ai_parameters);
|
||||
|
||||
const config& get_ai_effective_parameters() const;
|
||||
config& get_ai_effective_parameters();
|
||||
void set_ai_effective_parameters(const config& ai_effective_parameters);
|
||||
|
||||
const config& get_ai_global_parameters() const;
|
||||
config& get_ai_global_parameters();
|
||||
void set_ai_global_parameters(const config& ai_global_parameters);
|
||||
interface& get_ai_ref( side_number side );//@todo 1.7.3 remove this
|
||||
|
||||
const std::string describe_ai();
|
||||
|
||||
//not used in the moment
|
||||
bool is_mandate_ok();
|
||||
config to_config() const;
|
||||
|
||||
const std::string get_ai_identifier() const;
|
||||
|
||||
private:
|
||||
ai_ptr ai_;
|
||||
void init( side_number side );
|
||||
|
||||
|
||||
composite_ai_ptr ai_;
|
||||
side_context *side_context_;
|
||||
readonly_context *readonly_context_;
|
||||
readwrite_context *readwrite_context_;
|
||||
default_ai_context *default_ai_context_;
|
||||
std::string ai_algorithm_type_;
|
||||
config ai_effective_parameters_;
|
||||
config ai_global_parameters_;
|
||||
config ai_memory_;
|
||||
std::vector<config> ai_parameters_;
|
||||
side_number side_;
|
||||
|
||||
ai_ptr create_ai( side_number side );
|
||||
config cfg_;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -270,9 +250,9 @@ public:
|
|||
|
||||
|
||||
/**
|
||||
* Deletes an observer of 'user interact' event.
|
||||
* Removes an observer of 'user interact' event.
|
||||
*/
|
||||
static void delete_user_interact_observer( events::observer* event_observer );
|
||||
static void remove_user_interact_observer( events::observer* event_observer );
|
||||
|
||||
|
||||
/**
|
||||
|
@ -284,25 +264,25 @@ public:
|
|||
/**
|
||||
* Deletes an observer of 'unit recruited' event.
|
||||
*/
|
||||
static void delete_unit_recruited_observer( events::observer* event_observer );
|
||||
static void remove_unit_recruited_observer( events::observer* event_observer );
|
||||
|
||||
|
||||
/**
|
||||
* Deletes an observer of 'unit moved' event.
|
||||
*/
|
||||
static void delete_unit_moved_observer( events::observer* event_observer );
|
||||
static void remove_unit_moved_observer( events::observer* event_observer );
|
||||
|
||||
|
||||
/**
|
||||
* Deletes an observer of 'enemy attacked' event.
|
||||
*/
|
||||
static void delete_enemy_attacked_observer( events::observer* event_observer );
|
||||
static void remove_enemy_attacked_observer( events::observer* event_observer );
|
||||
|
||||
|
||||
/**
|
||||
* Deletes an observer of 'turn started' event.
|
||||
*/
|
||||
static void delete_turn_started_observer( events::observer* event_observer );
|
||||
static void remove_turn_started_observer( events::observer* event_observer );
|
||||
|
||||
|
||||
protected:
|
||||
|
@ -373,10 +353,11 @@ public:
|
|||
/**
|
||||
* Returns a smart pointer to a new AI.
|
||||
* @param ai_algorithm_type type of AI algorithm to create
|
||||
* @param cfg a config of the ai
|
||||
* @param context context in which this ai is created
|
||||
* @return the reference to the created AI
|
||||
*/
|
||||
static ai_ptr create_transient_ai( const std::string& ai_algorithm_type, default_ai_context *ai_context);
|
||||
static ai_ptr create_transient_ai( const std::string &ai_algorithm_type, const config &cfg, default_ai_context *ai_context);
|
||||
|
||||
|
||||
// =======================================================================
|
||||
|
@ -456,6 +437,22 @@ public:
|
|||
static game_info& get_active_ai_info_for_side( side_number side );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets AI algorithm identifier for active AI of the given @a side.
|
||||
* @param side side number (1-based).
|
||||
* @return ai identifier for the active AI
|
||||
*/
|
||||
static std::string get_active_ai_identifier_for_side( side_number side );
|
||||
|
||||
/**
|
||||
* Gets AI config for active AI of the given @a side.
|
||||
* @param side side number (1-based).
|
||||
* @return a config object for the active AI
|
||||
*/
|
||||
static config to_config( side_number side );
|
||||
|
||||
|
||||
/**
|
||||
* Gets global AI-game info
|
||||
* @return a reference to the AI-game info.
|
||||
|
|
|
@ -13,12 +13,13 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* 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)
|
||||
* All known AI parts. Workaround to a linker feature of not including 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 "ai2/ai.hpp"
|
||||
#include "composite/ai.hpp"
|
||||
#include "composite/aspect.hpp"
|
||||
#include "composite/engine_default.hpp"
|
||||
#include "composite/engine_fai.hpp"
|
||||
#include "default/ai.hpp"
|
||||
|
@ -40,62 +41,233 @@ static register_ai_factory<ai2> ai2_ai_factory("ai2");
|
|||
static register_ai_factory<idle_ai> ai_idle_ai_factory("idle_ai");
|
||||
static register_ai_factory<dfool::dfool_ai> ai_dfool_ai_factory("dfool_ai");
|
||||
static register_ai_factory<formula_ai> ai_formula_ai_factory("formula_ai");
|
||||
static register_ai_factory<composite_ai::ai_composite> ai_composite_ai_factory("composite_ai");
|
||||
static register_ai_factory<ai_composite> ai_composite_ai_factory("composite_ai");
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// Engines
|
||||
// =======================================================================
|
||||
|
||||
static composite_ai::register_engine_factory<composite_ai::engine_cpp>
|
||||
static register_engine_factory<engine_cpp>
|
||||
composite_ai_factory_cpp("cpp");
|
||||
|
||||
static composite_ai::register_engine_factory<composite_ai::engine_fai>
|
||||
static register_engine_factory<engine_fai>
|
||||
composite_ai_factory_fai("fai");
|
||||
|
||||
// =======================================================================
|
||||
// Stages
|
||||
// =======================================================================
|
||||
static composite_ai::register_stage_factory<testing_ai_default::candidate_action_evaluation_loop>
|
||||
static register_stage_factory<testing_ai_default::candidate_action_evaluation_loop>
|
||||
candidate_action_evaluation_loop_factory("testing_ai_default::candidate_action_evaluation_loop");
|
||||
|
||||
static composite_ai::register_stage_factory<testing_ai_default::fallback_to_other_ai>
|
||||
static register_stage_factory<testing_ai_default::fallback_to_other_ai>
|
||||
fallback_to_other_ai_factory("testing_ai_default::fallback");
|
||||
|
||||
// =======================================================================
|
||||
// Candidate actions
|
||||
// =======================================================================
|
||||
|
||||
static composite_ai::register_candidate_action_factory<testing_ai_default::goto_phase>
|
||||
static register_candidate_action_factory<testing_ai_default::goto_phase>
|
||||
goto_phase_factory("testing_ai_default::goto_phase");
|
||||
|
||||
static composite_ai::register_candidate_action_factory<testing_ai_default::recruitment_phase>
|
||||
static register_candidate_action_factory<testing_ai_default::recruitment_phase>
|
||||
recruitment_phase_factory("testing_ai_default::recruitment_phase");
|
||||
|
||||
static composite_ai::register_candidate_action_factory<testing_ai_default::combat_phase>
|
||||
static register_candidate_action_factory<testing_ai_default::combat_phase>
|
||||
combat_phase_factory("testing_ai_default::combat_phase");
|
||||
|
||||
static composite_ai::register_candidate_action_factory<testing_ai_default::move_leader_to_goals_phase>
|
||||
static register_candidate_action_factory<testing_ai_default::move_leader_to_goals_phase>
|
||||
move_leader_to_goals_phase_factory("testing_ai_default::move_leader_to_goals_phase");
|
||||
|
||||
static composite_ai::register_candidate_action_factory<testing_ai_default::move_leader_to_keep_phase>
|
||||
static register_candidate_action_factory<testing_ai_default::move_leader_to_keep_phase>
|
||||
move_leader_to_keep_phase_factory("testing_ai_default::move_leader_to_keep_phase");
|
||||
|
||||
static composite_ai::register_candidate_action_factory<testing_ai_default::get_villages_phase>
|
||||
static register_candidate_action_factory<testing_ai_default::get_villages_phase>
|
||||
get_villages_phase_factory("testing_ai_default::get_villages_phase");
|
||||
|
||||
static composite_ai::register_candidate_action_factory<testing_ai_default::get_healing_phase>
|
||||
static register_candidate_action_factory<testing_ai_default::get_healing_phase>
|
||||
get_healing_phase_factory("testing_ai_default::get_healing_phase");
|
||||
|
||||
static composite_ai::register_candidate_action_factory<testing_ai_default::retreat_phase>
|
||||
static register_candidate_action_factory<testing_ai_default::retreat_phase>
|
||||
retreat_phase_factory("testing_ai_default::retreat_phase");
|
||||
|
||||
static composite_ai::register_candidate_action_factory<testing_ai_default::simple_move_and_targeting_phase>
|
||||
static register_candidate_action_factory<testing_ai_default::simple_move_and_targeting_phase>
|
||||
simple_move_and_targeting_phase_factory("testing_ai_default::simple_move_and_targeting_phase");
|
||||
|
||||
static composite_ai::register_candidate_action_factory<testing_ai_default::leader_control_phase>
|
||||
static register_candidate_action_factory<testing_ai_default::leader_control_phase>
|
||||
leader_control_phase_factory("testing_ai_default::leader_control_phase");
|
||||
|
||||
// =======================================================================
|
||||
// Aspects
|
||||
// =======================================================================
|
||||
|
||||
//name=composite_aspect
|
||||
static register_aspect_factory< composite_aspect<double> >
|
||||
aggression__composite_aspect_factory("aggression*composite_aspect");
|
||||
|
||||
static register_aspect_factory< composite_aspect<int> >
|
||||
attack_depth__composite_aspect_factory("attack_depth*composite_aspect");
|
||||
|
||||
static register_aspect_factory< composite_aspect< terrain_filter > >
|
||||
avoid__composite_aspect_factory("avoid*composite_aspect");
|
||||
|
||||
static register_aspect_factory< composite_aspect<double> >
|
||||
caution__composite_aspect_factory("caution*composite_aspect");
|
||||
|
||||
static register_aspect_factory< composite_aspect<std::string> >
|
||||
grouping__composite_aspect_factory("grouping*composite_aspect");
|
||||
|
||||
static register_aspect_factory< composite_aspect<config> >
|
||||
leader_goal__composite_aspect_factory("leader_goal*composite_aspect");
|
||||
|
||||
static register_aspect_factory< composite_aspect<double> >
|
||||
leader_value__composite_aspect_factory("leader_value*composite_aspect");
|
||||
|
||||
static register_aspect_factory< composite_aspect<double> >
|
||||
number_of_possible_recruits_to_force_recruit__composite_aspect_factory("number_of_possible_recruits_to_force_recruit*composite_aspect");
|
||||
|
||||
static register_aspect_factory< composite_aspect<bool> >
|
||||
passive_leader__composite_aspect_factory("passive_leader*composite_aspect");
|
||||
|
||||
static register_aspect_factory< composite_aspect<bool> >
|
||||
passive_leader_shares_keep__composite_aspect_factory("passive_leader_shares_keep*composite_aspect");
|
||||
|
||||
static register_aspect_factory< composite_aspect<bool> >
|
||||
recruitment_ignore_bad_combat__composite_aspect_factory("recruitment_ignore_bad_combat*composite_aspect");
|
||||
|
||||
static register_aspect_factory< composite_aspect<bool> >
|
||||
recruitment_ignore_bad_movement__composite_aspect_factory("recruitment_ignore_bad_movement*composite_aspect");
|
||||
|
||||
static register_aspect_factory< composite_aspect< std::vector<std::string> > >
|
||||
recruitment_pattern__composite_aspect_factory("recruitment_pattern*composite_aspect");
|
||||
|
||||
static register_aspect_factory< composite_aspect<double> >
|
||||
scout_village_targeting__composite_aspect_factory("scout_village_targeting*composite_aspect");
|
||||
|
||||
static register_aspect_factory< composite_aspect<bool> >
|
||||
simple_targeting__composite_aspect_factory("simple_targeting*composite_aspect");
|
||||
|
||||
static register_aspect_factory< composite_aspect<bool> >
|
||||
support_villages__composite_aspect_factory("support_villages*composite_aspect");
|
||||
|
||||
static register_aspect_factory< composite_aspect<double> >
|
||||
village_value__composite_aspect_factory("village_value*composite_aspect");
|
||||
|
||||
static register_aspect_factory< composite_aspect<int> >
|
||||
villages_per_scout__composite_aspect_factory("villages_per_scout*composite_aspect");
|
||||
|
||||
|
||||
//name=standard_aspect
|
||||
static register_aspect_factory< standard_aspect<double> >
|
||||
aggression__standard_aspect_factory("aggression*standard_aspect");
|
||||
|
||||
static register_aspect_factory< standard_aspect<int> >
|
||||
attack_depth__standard_aspect_factory("attack_depth*standard_aspect");
|
||||
|
||||
static register_aspect_factory< standard_aspect< terrain_filter > >
|
||||
avoid__standard_aspect_factory("avoid*standard_aspect");
|
||||
|
||||
static register_aspect_factory< standard_aspect<double> >
|
||||
caution__standard_aspect_factory("caution*standard_aspect");
|
||||
|
||||
static register_aspect_factory< standard_aspect<std::string> >
|
||||
grouping__standard_aspect_factory("grouping*standard_aspect");
|
||||
|
||||
static register_aspect_factory< standard_aspect<config> >
|
||||
leader_goal__standard_aspect_factory("leader_goal*standard_aspect");
|
||||
|
||||
static register_aspect_factory< standard_aspect<double> >
|
||||
leader_value__standard_aspect_factory("leader_value*standard_aspect");
|
||||
|
||||
static register_aspect_factory< standard_aspect<double> >
|
||||
number_of_possible_recruits_to_force_recruit__standard_aspect_factory("number_of_possible_recruits_to_force_recruit*standard_aspect");
|
||||
|
||||
static register_aspect_factory< standard_aspect<bool> >
|
||||
passive_leader__standard_aspect_factory("passive_leader*standard_aspect");
|
||||
|
||||
static register_aspect_factory< standard_aspect<bool> >
|
||||
passive_leader_shares_keep__standard_aspect_factory("passive_leader_shares_keep*standard_aspect");
|
||||
|
||||
static register_aspect_factory< standard_aspect<bool> >
|
||||
recruitment_ignore_bad_combat__standard_aspect_factory("recruitment_ignore_bad_combat*standard_aspect");
|
||||
|
||||
static register_aspect_factory< standard_aspect<bool> >
|
||||
recruitment_ignore_bad_movement__standard_aspect_factory("recruitment_ignore_bad_movement*standard_aspect");
|
||||
|
||||
static register_aspect_factory< standard_aspect< std::vector<std::string> > >
|
||||
recruitment_pattern__standard_aspect_factory("recruitment_pattern*standard_aspect");
|
||||
|
||||
static register_aspect_factory< standard_aspect<double> >
|
||||
scout_village_targeting__standard_aspect_factory("scout_village_targeting*standard_aspect");
|
||||
|
||||
static register_aspect_factory< standard_aspect<bool> >
|
||||
simple_targeting__standard_aspect_factory("simple_targeting*standard_aspect");
|
||||
|
||||
static register_aspect_factory< standard_aspect<bool> >
|
||||
support_villages__standard_aspect_factory("support_villages*standard_aspect");
|
||||
|
||||
static register_aspect_factory< standard_aspect<double> >
|
||||
village_value__standard_aspect_factory("village_value*standard_aspect");
|
||||
|
||||
static register_aspect_factory< standard_aspect<int> >
|
||||
villages_per_scout__standard_aspect_factory("villages_per_scout*standard_aspect");
|
||||
|
||||
|
||||
//name = default
|
||||
static register_aspect_factory< standard_aspect<double> >
|
||||
aggression__standard_aspect_factory2("aggression*");
|
||||
|
||||
static register_aspect_factory< standard_aspect<int> >
|
||||
attack_depth__standard_aspect_factory2("attack_depth*");
|
||||
|
||||
static register_aspect_factory< standard_aspect< terrain_filter > >
|
||||
avoid__standard_aspect_factory2("avoid*");
|
||||
|
||||
static register_aspect_factory< standard_aspect<double> >
|
||||
caution__standard_aspect_factory2("caution*");
|
||||
|
||||
static register_aspect_factory< standard_aspect<std::string> >
|
||||
grouping__standard_aspect_factory2("grouping*");
|
||||
|
||||
static register_aspect_factory< standard_aspect<config> >
|
||||
leader_goal__standard_aspect_factory2("leader_goal*");
|
||||
|
||||
static register_aspect_factory< standard_aspect<double> >
|
||||
leader_value__standard_aspect_factory2("leader_value*");
|
||||
|
||||
static register_aspect_factory< standard_aspect<double> >
|
||||
number_of_possible_recruits_to_force_recruit__standard_aspect_factory2("number_of_possible_recruits_to_force_recruit*");
|
||||
|
||||
static register_aspect_factory< standard_aspect<bool> >
|
||||
passive_leader__standard_aspect_factory2("passive_leader*");
|
||||
|
||||
static register_aspect_factory< standard_aspect<bool> >
|
||||
passive_leader_shares_keep__standard_aspect_factory2("passive_leader_shares_keep*");
|
||||
|
||||
static register_aspect_factory< standard_aspect<bool> >
|
||||
recruitment_ignore_bad_combat__standard_aspect_factory2("recruitment_ignore_bad_combat*");
|
||||
|
||||
static register_aspect_factory< standard_aspect<bool> >
|
||||
recruitment_ignore_bad_movement__standard_aspect_factory2("recruitment_ignore_bad_movement*");
|
||||
|
||||
static register_aspect_factory< standard_aspect< std::vector<std::string> > >
|
||||
recruitment_pattern__standard_aspect_factory2("recruitment_pattern*");
|
||||
|
||||
static register_aspect_factory< standard_aspect<double> >
|
||||
scout_village_targeting__standard_aspect_factory2("scout_village_targeting*");
|
||||
|
||||
static register_aspect_factory< standard_aspect<bool> >
|
||||
simple_targeting__standard_aspect_factory2("simple_targeting*");
|
||||
|
||||
static register_aspect_factory< standard_aspect<bool> >
|
||||
support_villages__standard_aspect_factory2("support_villages*");
|
||||
|
||||
static register_aspect_factory< standard_aspect<double> >
|
||||
village_value__standard_aspect_factory2("village_value*");
|
||||
|
||||
static register_aspect_factory< standard_aspect<int> >
|
||||
villages_per_scout__standard_aspect_factory2("villages_per_scout*");
|
||||
|
||||
void registry::init()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ void ai_testing::log_game_start()
|
|||
ai::game_info& i = ai::manager::get_ai_info();
|
||||
for (std::vector<team>::const_iterator tm = i.teams.begin(); tm != i.teams.end(); ++tm) {
|
||||
int side = tm-i.teams.begin()+1;
|
||||
LOG_AI_TESTING << "AI_IDENTIFIER"<<side<<": " << tm->ai_algorithm_identifier() <<std::endl;
|
||||
LOG_AI_TESTING << "AI_IDENTIFIER"<<side<<": " << ai::manager::get_active_ai_identifier_for_side(side) <<std::endl;
|
||||
LOG_AI_TESTING << "FACTION"<<side<<": " << tm->name() << std::endl;
|
||||
}
|
||||
LOG_AI_TESTING << "VERSION: " << game_config::revision << std::endl;
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace testing_ai_default {
|
|||
//==============================================================
|
||||
|
||||
goto_phase::goto_phase( rca_context &context, const config &cfg )
|
||||
: candidate_action(context,"testing_ai_default::goto_phase",cfg["type"])
|
||||
: candidate_action(context,cfg)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ bool goto_phase::execute()
|
|||
//==============================================================
|
||||
|
||||
recruitment_phase::recruitment_phase( rca_context &context, const config &cfg )
|
||||
: candidate_action(context,"testing_ai_default::recruitment_phase",cfg["type"])
|
||||
: candidate_action(context,cfg)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -112,7 +112,7 @@ bool recruitment_phase::execute()
|
|||
//analyze_potential_recruit_movements();
|
||||
analyze_potential_recruit_combat();
|
||||
|
||||
std::vector<std::string> options = current_team().recruitment_pattern();
|
||||
std::vector<std::string> options = get_recruitment_pattern();
|
||||
if (std::count(options.begin(), options.end(), "scout") > 0) {
|
||||
size_t neutral_villages = 0;
|
||||
|
||||
|
@ -145,7 +145,7 @@ bool recruitment_phase::execute()
|
|||
// accounting for all neutral villages on the map.
|
||||
// We only look at villages closer to us, so we halve it,
|
||||
// making us get twice as many scouts.
|
||||
const int villages_per_scout = current_team().villages_per_scout()/2;
|
||||
const int villages_per_scout = get_villages_per_scout()/2;
|
||||
|
||||
// Get scouts depending on how many neutral villages there are.
|
||||
int scouts_wanted = villages_per_scout > 0 ? neutral_villages/villages_per_scout : 0;
|
||||
|
@ -180,7 +180,7 @@ bool recruitment_phase::execute()
|
|||
// Buy units as long as we have room and can afford it.
|
||||
while (recruit_usage(options[rand()%options.size()],gamestate_changed)) {
|
||||
//refresh the recruitment pattern - it can be changed by recruit_usage
|
||||
options = current_team().recruitment_pattern();
|
||||
options = get_recruitment_pattern();
|
||||
if (options.empty()) {
|
||||
options.push_back("");
|
||||
}
|
||||
|
@ -261,7 +261,9 @@ bool recruitment_phase::recruit_usage(const std::string& usage, bool &gamestate_
|
|||
WRN_AI_TESTING_AI_DEFAULT << warning;
|
||||
// Uncommented until the recruitment limiting macro can be fixed to not trigger this warning.
|
||||
//lg::wml_error << warning;
|
||||
return current_team_w().remove_recruitment_pattern_entry(usage);
|
||||
//@fixme
|
||||
//return current_team_w().remove_recruitment_pattern_entry(usage);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -477,8 +479,7 @@ int recruitment_phase::compare_unit_types(const unit_type& a, const unit_type& b
|
|||
void recruitment_phase::analyze_potential_recruit_combat()
|
||||
{
|
||||
unit_map &units_ = get_info().units;
|
||||
if(unit_combat_scores_.empty() == false ||
|
||||
utils::string_bool(current_team().ai_parameters()["recruitment_ignore_bad_combat"])) {
|
||||
if(unit_combat_scores_.empty() == false || get_recruitment_ignore_bad_combat()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -545,7 +546,7 @@ void recruitment_phase::analyze_potential_recruit_combat()
|
|||
//==============================================================
|
||||
|
||||
combat_phase::combat_phase( rca_context &context, const config &cfg )
|
||||
: candidate_action(context,"testing_ai_default::combat_phase",cfg["type"]),best_analysis_(),choice_rating_(-1000.0)
|
||||
: candidate_action(context,cfg),best_analysis_(),choice_rating_(-1000.0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -585,9 +586,9 @@ double combat_phase::evaluate()
|
|||
if(skip_num > 0 && ((it - analysis.begin())%skip_num) && it->movements.size() > 1)
|
||||
continue;
|
||||
|
||||
const double rating = it->rating(current_team().aggression(),*this);
|
||||
const double rating = it->rating(get_aggression(),*this);
|
||||
LOG_AI_TESTING_AI_DEFAULT << "attack option rated at " << rating << " ("
|
||||
<< current_team().aggression() << ")\n";
|
||||
<< get_aggression() << ")\n";
|
||||
|
||||
if(rating > choice_rating_) {
|
||||
choice_it = it;
|
||||
|
@ -638,7 +639,7 @@ bool combat_phase::execute()
|
|||
//==============================================================
|
||||
|
||||
move_leader_to_goals_phase::move_leader_to_goals_phase( rca_context &context, const config &cfg )
|
||||
: candidate_action(context,"testing_ai_default::move_leader_to_goals_phase",cfg["type"])
|
||||
: candidate_action(context,cfg)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -661,7 +662,7 @@ bool move_leader_to_goals_phase::execute()
|
|||
//==============================================================
|
||||
|
||||
move_leader_to_keep_phase::move_leader_to_keep_phase( rca_context &context, const config &cfg )
|
||||
: candidate_action(context,"testing_ai_default::move_leader_to_keep_phase",cfg["type"]),move_()
|
||||
: candidate_action(context,cfg),move_()
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -742,7 +743,7 @@ bool move_leader_to_keep_phase::execute()
|
|||
//==============================================================
|
||||
|
||||
get_villages_phase::get_villages_phase( rca_context &context, const config &cfg )
|
||||
: candidate_action(context,"testing_ai_default::get_villages_phase",cfg["type"]), keep_loc_(),
|
||||
: candidate_action(context,cfg), keep_loc_(),
|
||||
leader_loc_(),best_leader_loc_(),debug_(false)
|
||||
{
|
||||
}
|
||||
|
@ -757,7 +758,7 @@ double get_villages_phase::evaluate()
|
|||
unit_map::const_iterator leader = get_info().units.find_leader(get_side());
|
||||
get_villages(get_possible_moves(),get_dstsrc(),get_enemy_dstsrc(),leader);
|
||||
if (moves_.size()>0) {
|
||||
return 25;
|
||||
return 25;//@todo 1.7 externalize
|
||||
}
|
||||
return BAD_SCORE;
|
||||
}
|
||||
|
@ -883,7 +884,7 @@ void get_villages_phase::find_villages(
|
|||
{
|
||||
std::map<map_location, double> vulnerability;
|
||||
|
||||
const bool passive_leader = utils::string_bool(current_team().ai_parameters()["passive_leader"]);//@todo: make an aspect
|
||||
const bool passive_leader = get_passive_leader();
|
||||
|
||||
size_t min_distance = 100000;
|
||||
gamemap &map_ = get_info().map;
|
||||
|
@ -1555,7 +1556,7 @@ void get_villages_phase::dump_reachmap(treachmap& reachmap)
|
|||
//==============================================================
|
||||
|
||||
get_healing_phase::get_healing_phase( rca_context &context, const config &cfg )
|
||||
: candidate_action(context,"testing_ai_default::get_healing_phase",cfg["type"]),from_(),to_()
|
||||
: candidate_action(context,cfg),from_(),to_()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1642,7 +1643,7 @@ bool get_healing_phase::execute()
|
|||
//==============================================================
|
||||
|
||||
retreat_phase::retreat_phase( rca_context &context, const config &cfg )
|
||||
: candidate_action(context,"testing_ai_default::retreat_phase",cfg["type"])
|
||||
: candidate_action(context,cfg)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1665,7 +1666,7 @@ bool retreat_phase::execute()
|
|||
//==============================================================
|
||||
|
||||
simple_move_and_targeting_phase::simple_move_and_targeting_phase( rca_context &context, const config &cfg )
|
||||
: candidate_action(context,"testing_ai_default::simple_move_and_targeting_phase",cfg["type"])
|
||||
: candidate_action(context,cfg)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1728,7 +1729,7 @@ bool simple_move_and_targeting_phase::execute()
|
|||
//==============================================================
|
||||
|
||||
leader_control_phase::leader_control_phase( rca_context &context, const config &cfg )
|
||||
: candidate_action(context,"testing_ai_default::leader_control_phase",cfg["type"])
|
||||
: candidate_action(context,cfg)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -36,9 +36,6 @@ namespace ai {
|
|||
|
||||
namespace testing_ai_default {
|
||||
|
||||
using composite_ai::rca_context;
|
||||
using composite_ai::candidate_action;
|
||||
|
||||
//============================================================================
|
||||
|
||||
class goto_phase : public candidate_action {
|
||||
|
|
|
@ -33,14 +33,27 @@ static lg::log_domain log_ai_testing_stage_fallback("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( composite_ai::composite_ai_context &context, const config &cfg )
|
||||
fallback_to_other_ai::fallback_to_other_ai( ai_context &context, const config &cfg )
|
||||
: stage(context,cfg), cfg_(cfg), fallback_ai_()
|
||||
{
|
||||
}
|
||||
|
||||
void fallback_to_other_ai::on_create()
|
||||
{
|
||||
fallback_ai_ = manager::create_transient_ai(cfg_["fallback"], this);
|
||||
const config &ai_cfg = cfg_.child("ai");
|
||||
if (ai_cfg) {
|
||||
fallback_ai_ = manager::create_transient_ai(ai_cfg["ai_algorithm"], ai_cfg, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
config fallback_to_other_ai::to_config() const
|
||||
{
|
||||
config cfg = stage::to_config();
|
||||
if (fallback_ai_) {
|
||||
cfg.add_child("ai",fallback_ai_->to_config());
|
||||
}
|
||||
return cfg;
|
||||
}
|
||||
|
||||
void fallback_to_other_ai::do_play_stage()
|
||||
|
|
|
@ -38,9 +38,9 @@ namespace ai {
|
|||
|
||||
namespace testing_ai_default {
|
||||
|
||||
class fallback_to_other_ai: public composite_ai::stage {
|
||||
class fallback_to_other_ai: public stage {
|
||||
public:
|
||||
fallback_to_other_ai( composite_ai::composite_ai_context &context, const config &cfg );
|
||||
fallback_to_other_ai( ai_context &context, const config &cfg );
|
||||
|
||||
~fallback_to_other_ai();
|
||||
|
||||
|
@ -48,6 +48,8 @@ public:
|
|||
|
||||
void on_create();
|
||||
|
||||
config to_config() const;
|
||||
|
||||
private:
|
||||
const config &cfg_;
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ static lg::log_domain log_ai_testing_rca_default("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( composite_ai::composite_ai_context &context, const config &cfg)
|
||||
candidate_action_evaluation_loop::candidate_action_evaluation_loop( ai_context &context, const config &cfg)
|
||||
: stage(context,cfg),cfg_(cfg)
|
||||
{
|
||||
}
|
||||
|
@ -41,27 +41,36 @@ void candidate_action_evaluation_loop::on_create()
|
|||
{
|
||||
//init the candidate actions
|
||||
foreach(const config &cfg_element, cfg_.child_range("candidate_action")){
|
||||
composite_ai::engine::parse_candidate_action_from_config(*this,cfg_element,back_inserter(candidate_actions_));
|
||||
engine::parse_candidate_action_from_config(*this,cfg_element,back_inserter(candidate_actions_));
|
||||
}
|
||||
}
|
||||
|
||||
config candidate_action_evaluation_loop::to_config() const
|
||||
{
|
||||
config cfg = stage::to_config();
|
||||
foreach(candidate_action_ptr ca, candidate_actions_){
|
||||
cfg.add_child("candidate_action",ca->to_config());
|
||||
}
|
||||
return cfg;
|
||||
}
|
||||
|
||||
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(composite_ai::candidate_action_ptr ca, candidate_actions_){
|
||||
foreach(candidate_action_ptr ca, candidate_actions_){
|
||||
ca->enable();
|
||||
}
|
||||
|
||||
bool executed = false;
|
||||
do {
|
||||
executed = false;
|
||||
double best_score = composite_ai::candidate_action::BAD_SCORE;
|
||||
composite_ai::candidate_action_ptr best_ptr;
|
||||
double best_score = candidate_action::BAD_SCORE;
|
||||
candidate_action_ptr best_ptr;
|
||||
|
||||
//Evaluation
|
||||
foreach(composite_ai::candidate_action_ptr ca_ptr, candidate_actions_){
|
||||
foreach(candidate_action_ptr ca_ptr, candidate_actions_){
|
||||
if (!ca_ptr->is_enabled()){
|
||||
DBG_AI_TESTING_RCA_DEFAULT << "Skipping disabled candidate action: "<< *ca_ptr << std::endl;
|
||||
continue;
|
||||
|
@ -72,7 +81,7 @@ void candidate_action_evaluation_loop::do_play_stage()
|
|||
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 (composite_ai::candidate_action_evaluation_exception &caee) {
|
||||
} catch (candidate_action_evaluation_exception &caee) {
|
||||
ERR_AI_TESTING_RCA_DEFAULT << "Candidate action evaluation threw an exception: " << caee << std::endl;
|
||||
ca_ptr->disable();
|
||||
continue;
|
||||
|
@ -85,11 +94,11 @@ void candidate_action_evaluation_loop::do_play_stage()
|
|||
}
|
||||
|
||||
//Execution
|
||||
if (best_score>composite_ai::candidate_action::BAD_SCORE) {
|
||||
if (best_score>candidate_action::BAD_SCORE) {
|
||||
try {
|
||||
DBG_AI_TESTING_RCA_DEFAULT << "Best candidate action: "<< *best_ptr << std::endl;
|
||||
executed = best_ptr->execute();
|
||||
} catch (composite_ai::candidate_action_execution_exception &caee) {
|
||||
} catch (candidate_action_execution_exception &caee) {
|
||||
ERR_AI_TESTING_RCA_DEFAULT << "Candidate action execution threw an exception: " << caee << std::endl;
|
||||
executed = false;
|
||||
}
|
||||
|
@ -101,13 +110,13 @@ void candidate_action_evaluation_loop::do_play_stage()
|
|||
executed = true;
|
||||
}
|
||||
} else {
|
||||
LOG_AI_TESTING_RCA_DEFAULT << "Ending candidate action evaluation loop due to best score "<< best_score<<"<="<< composite_ai::candidate_action::BAD_SCORE<<std::endl;
|
||||
LOG_AI_TESTING_RCA_DEFAULT << "Ending candidate action evaluation loop due to best score "<< best_score<<"<="<< candidate_action::BAD_SCORE<<std::endl;
|
||||
}
|
||||
} while (executed);
|
||||
LOG_AI_TESTING_RCA_DEFAULT << "Ended candidate action evaluation loop for side "<< get_side() << std::endl;
|
||||
}
|
||||
|
||||
composite_ai::rca_context& candidate_action_evaluation_loop::get_rca_context()
|
||||
rca_context& candidate_action_evaluation_loop::get_rca_context()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
|
|
@ -40,9 +40,9 @@ namespace ai {
|
|||
|
||||
namespace testing_ai_default {
|
||||
|
||||
class candidate_action_evaluation_loop: public virtual composite_ai::stage, public virtual composite_ai::rca_context {
|
||||
class candidate_action_evaluation_loop: public virtual stage, public virtual rca_context {
|
||||
public:
|
||||
candidate_action_evaluation_loop( composite_ai::composite_ai_context &context, const config &cfg );
|
||||
candidate_action_evaluation_loop( ai_context &context, const config &cfg );
|
||||
|
||||
~candidate_action_evaluation_loop();
|
||||
|
||||
|
@ -50,10 +50,12 @@ public:
|
|||
|
||||
void on_create();
|
||||
|
||||
composite_ai::rca_context& get_rca_context();
|
||||
config to_config() const;
|
||||
|
||||
rca_context& get_rca_context();
|
||||
|
||||
private:
|
||||
std::vector<composite_ai::candidate_action_ptr> candidate_actions_;
|
||||
std::vector<candidate_action_ptr> candidate_actions_;
|
||||
|
||||
const config &cfg_;
|
||||
};
|
||||
|
|
|
@ -120,6 +120,33 @@ void config::merge_children(const std::string& key)
|
|||
add_child(key,merged_children);
|
||||
}
|
||||
|
||||
void config::merge_children_by_attribute(const std::string& key, const std::string& attribute)
|
||||
{
|
||||
check_valid();
|
||||
|
||||
std::map<std::string,config> merged_children_map;
|
||||
const child_list& children = get_children(key);
|
||||
if(children.size() < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(child_list::const_iterator i = children.begin(); i != children.end(); ++i) {
|
||||
const std::string& value = (**i)[attribute];
|
||||
std::map<std::string,config>::iterator m = merged_children_map.find(value);
|
||||
if ( m!=merged_children_map.end() ) {
|
||||
m->second.append(**i);
|
||||
} else {
|
||||
merged_children_map.insert(make_pair(value,**i));
|
||||
}
|
||||
}
|
||||
|
||||
clear_children(key);
|
||||
typedef std::map<std::string,config> config_map;
|
||||
foreach (const config_map::value_type &i, merged_children_map) {
|
||||
add_child(key,i.second);
|
||||
}
|
||||
}
|
||||
|
||||
config::child_itors_bak config::child_range_bak(const std::string& key)
|
||||
{
|
||||
check_valid();
|
||||
|
|
|
@ -341,6 +341,13 @@ public:
|
|||
*/
|
||||
void merge_children(const std::string& key);
|
||||
|
||||
/**
|
||||
* All children with the given key and with equal values
|
||||
* of the specified attribute will be merged into the
|
||||
* element with that key and that value of the attribute
|
||||
*/
|
||||
void merge_children_by_attribute(const std::string& key, const std::string& attribute);
|
||||
|
||||
//this is a cheap O(1) operation
|
||||
void swap(config& cfg);
|
||||
|
||||
|
|
|
@ -522,7 +522,6 @@ void play_controller::do_init_side(const unsigned int team_index){
|
|||
}
|
||||
|
||||
const time_of_day &tod = tod_manager_.get_time_of_day();
|
||||
current_team.set_time_of_day(int(turn()), tod);
|
||||
|
||||
if (int(team_index) + 1 == first_player_)
|
||||
sound::play_sound(tod.sounds, sound::SOUND_SOURCES);
|
||||
|
|
201
src/team.cpp
201
src/team.cpp
|
@ -68,16 +68,6 @@ int teams_manager::get_first_human_team(const config::child_list::const_iterator
|
|||
return result;
|
||||
}
|
||||
|
||||
team::target::target(const config& cfg)
|
||||
: criteria(cfg), value(atof(cfg["value"].c_str()))
|
||||
{
|
||||
}
|
||||
|
||||
void team::target::write(config& cfg) const
|
||||
{
|
||||
cfg = criteria;
|
||||
}
|
||||
|
||||
team::team_info::team_info(const config& cfg) :
|
||||
name(cfg["name"]),
|
||||
gold(lexical_cast_default<int>(cfg["gold"])),
|
||||
|
@ -86,10 +76,7 @@ team::team_info::team_info(const config& cfg) :
|
|||
income(lexical_cast_default<int>(cfg["income"])),
|
||||
income_per_village(0),
|
||||
average_price(0),
|
||||
number_of_possible_recruits_to_force_recruit(),
|
||||
can_recruit(),
|
||||
global_recruitment_pattern(),
|
||||
recruitment_pattern(),
|
||||
enemies(),
|
||||
team_name(cfg["team_name"]),
|
||||
user_team_name(cfg["user_team_name"]),
|
||||
|
@ -103,12 +90,6 @@ team::team_info::team_info(const config& cfg) :
|
|||
objectives(cfg["objectives"]),
|
||||
objectives_changed(utils::string_bool(cfg["objectives_changed"])),
|
||||
controller(),
|
||||
villages_per_scout(),
|
||||
leader_value(),
|
||||
village_value(),
|
||||
aggression_(),
|
||||
caution_(),
|
||||
targets(),
|
||||
share_maps(false),
|
||||
share_view(false),
|
||||
disallow_observers(utils::string_bool(cfg["disallow_observers"])),
|
||||
|
@ -120,7 +101,7 @@ team::team_info::team_info(const config& cfg) :
|
|||
side(lexical_cast_default<int>(cfg["side"], 1)),
|
||||
persistent(false)
|
||||
{
|
||||
// If are starting new scenario overide settings from [ai] tags
|
||||
// If arel starting new scenario overide settings from [ai] tags
|
||||
if (!user_team_name.translatable())
|
||||
user_team_name = user_team_name.from_serialized(user_team_name);
|
||||
|
||||
|
@ -130,50 +111,10 @@ team::team_info::team_info(const config& cfg) :
|
|||
ai::manager::add_ai_for_side_from_config(side, cfg, true);
|
||||
}
|
||||
|
||||
//legacy parameters
|
||||
const config& global_ai_parameters = ai::manager::get_active_ai_global_parameters_for_side(side);
|
||||
const config& effective_ai_params = ai::manager::get_active_ai_effective_parameters_for_side(side);
|
||||
|
||||
number_of_possible_recruits_to_force_recruit = lexical_cast<float>(effective_ai_params["number_of_possible_recruits_to_force_recruit"]);
|
||||
villages_per_scout = lexical_cast<int>(effective_ai_params["villages_per_scout"]);
|
||||
leader_value = lexical_cast<double>(effective_ai_params["leader_value"]);
|
||||
village_value = lexical_cast<double>(effective_ai_params["village_value"]);
|
||||
aggression_ = lexical_cast<double>(effective_ai_params["aggression"]);
|
||||
caution_ = lexical_cast<double>(effective_ai_params["caution"]);
|
||||
|
||||
//START OF MESSY CODE
|
||||
//========================================================================
|
||||
//this part will be cleaned later
|
||||
|
||||
std::vector<std::string> recruits = utils::split(cfg["recruit"]);
|
||||
for(std::vector<std::string>::const_iterator i = recruits.begin(); i != recruits.end(); ++i) {
|
||||
can_recruit.insert(*i);
|
||||
}
|
||||
|
||||
recruitment_pattern = utils::split(cfg["recruitment_pattern"]);
|
||||
|
||||
if(recruitment_pattern.empty())
|
||||
{
|
||||
recruitment_pattern =
|
||||
utils::split(global_ai_parameters["recruitment_pattern"]);
|
||||
}
|
||||
// Keep a copy of the initial recruitment_pattern,
|
||||
// since it can be changed on a per-time-of-day
|
||||
// or per-turn basis inside [ai] sections.
|
||||
global_recruitment_pattern = recruitment_pattern;
|
||||
|
||||
|
||||
// Additional targets
|
||||
foreach (const config &tgt, cfg.child_range("target")) {
|
||||
targets.push_back(target(tgt));
|
||||
}
|
||||
|
||||
foreach (const config &tgt, global_ai_parameters.child_range("target")) {
|
||||
targets.push_back(target(tgt));
|
||||
}
|
||||
|
||||
//all past this point should be non-ai code
|
||||
//========================================================
|
||||
std::vector<std::string> recruits = utils::split(cfg["recruit"]);
|
||||
for(std::vector<std::string>::const_iterator i = recruits.begin(); i != recruits.end(); ++i) {
|
||||
can_recruit.insert(*i);
|
||||
}
|
||||
|
||||
// at the start of a scenario "start_gold" is not set, we need to take the
|
||||
// value from the gold setting (or fall back to the gold default)
|
||||
|
@ -259,14 +200,6 @@ team::team_info::team_info(const config& cfg) :
|
|||
|
||||
void team::team_info::write(config& cfg) const
|
||||
{
|
||||
const std::vector<config> &ai_params = ai::manager::get_active_ai_parameters_for_side(side);;
|
||||
for(std::vector<config>::const_iterator ai = ai_params.begin(); ai != ai_params.end(); ++ai) {
|
||||
cfg.add_child("ai",*ai);
|
||||
}
|
||||
const config &ai_memory_ = ai::manager::get_active_ai_memory_for_side(side);
|
||||
if(!ai_memory_.empty()) cfg.add_child("ai_memory", ai_memory_ );
|
||||
cfg["ai_algorithm"] = ai::manager::get_active_ai_algorithm_type_for_side(side);
|
||||
|
||||
cfg["gold"] = str_cast(gold);
|
||||
cfg["start_gold"] = str_cast(start_gold);
|
||||
cfg["gold_add"] = gold_add ? "yes" : "no";
|
||||
|
@ -288,7 +221,6 @@ void team::team_info::write(config& cfg) const
|
|||
cfg["allow_player"] = allow_player ? "yes" : "no";
|
||||
cfg["no_leader"] = no_leader ? "yes" : "no";
|
||||
cfg["hidden"] = hidden ? "yes" : "no";
|
||||
cfg["number_of_possible_recruits_to_force_recruit"] = lexical_cast<std::string>(number_of_possible_recruits_to_force_recruit);
|
||||
|
||||
std::stringstream enemies_str;
|
||||
for(std::vector<int>::const_iterator en = enemies.begin(); en != enemies.end(); ++en) {
|
||||
|
@ -309,16 +241,6 @@ void team::team_info::write(config& cfg) const
|
|||
default: assert(false); return;
|
||||
}
|
||||
|
||||
cfg["villages_per_scout"] = str_cast(villages_per_scout);
|
||||
cfg["leader_value"] = str_cast(leader_value);
|
||||
cfg["village_value"] = str_cast(village_value);
|
||||
cfg["aggression"] = str_cast(aggression_);
|
||||
cfg["caution"] = str_cast(caution_);
|
||||
|
||||
for(std::vector<target>::const_iterator tg = targets.begin(); tg != targets.end(); ++tg) {
|
||||
tg->write(cfg.add_child("target"));
|
||||
}
|
||||
|
||||
std::stringstream can_recruit_str;
|
||||
for(std::set<std::string>::const_iterator cr = can_recruit.begin(); cr != can_recruit.end(); ++cr) {
|
||||
if(cr != can_recruit.begin())
|
||||
|
@ -329,28 +251,6 @@ void team::team_info::write(config& cfg) const
|
|||
|
||||
cfg["recruit"] = can_recruit_str.str();
|
||||
|
||||
std::stringstream global_recruit_pattern_str;
|
||||
for(std::vector<std::string>::const_iterator p = global_recruitment_pattern.begin();
|
||||
p != global_recruitment_pattern.end(); ++p) {
|
||||
if(p != global_recruitment_pattern.begin())
|
||||
global_recruit_pattern_str << ",";
|
||||
|
||||
global_recruit_pattern_str << *p;
|
||||
}
|
||||
|
||||
cfg["global_recruitment_pattern"] = global_recruit_pattern_str.str();
|
||||
|
||||
std::stringstream recruit_pattern_str;
|
||||
for(std::vector<std::string>::const_iterator p = recruitment_pattern.begin();
|
||||
p != recruitment_pattern.end(); ++p) {
|
||||
if(p != recruitment_pattern.begin())
|
||||
recruit_pattern_str << ",";
|
||||
|
||||
recruit_pattern_str << *p;
|
||||
}
|
||||
|
||||
cfg["recruitment_pattern"] = recruit_pattern_str.str();
|
||||
|
||||
cfg["share_maps"] = share_maps ? "yes" : "no";
|
||||
cfg["share_view"] = share_view ? "yes" : "no";
|
||||
|
||||
|
@ -360,6 +260,8 @@ void team::team_info::write(config& cfg) const
|
|||
cfg["colour"] = lexical_cast_default<std::string>(colour);
|
||||
|
||||
cfg["persistent"] = persistent ? "yes" : "no";
|
||||
|
||||
cfg.add_child("ai",ai::manager::to_config(side));
|
||||
}
|
||||
|
||||
void team::merge_shroud_map_data(const std::string& shroud_data)
|
||||
|
@ -490,7 +392,7 @@ void team::add_recruits(const std::set<std::string>& recruits)
|
|||
|
||||
namespace {
|
||||
struct count_average {
|
||||
count_average(size_t& a) : a_(a), sum_(0), count_(0)
|
||||
count_average(int a) : a_(a), sum_(0), count_(0)
|
||||
{}
|
||||
~count_average() {
|
||||
// If no recruits disable leader from moving to keep
|
||||
|
@ -508,13 +410,13 @@ namespace {
|
|||
sum_ += i->second.cost();
|
||||
}
|
||||
private:
|
||||
size_t& a_;
|
||||
size_t sum_;
|
||||
size_t count_;
|
||||
int a_;
|
||||
int sum_;
|
||||
int count_;
|
||||
};
|
||||
}
|
||||
|
||||
size_t team::average_recruit_price()
|
||||
int team::average_recruit_price() const
|
||||
{
|
||||
if (info_.average_price)
|
||||
return info_.average_price;
|
||||
|
@ -528,52 +430,6 @@ size_t team::average_recruit_price()
|
|||
return info_.average_price;
|
||||
}
|
||||
|
||||
void team::set_time_of_day(int turn, const time_of_day& tod)
|
||||
{
|
||||
config aiparams_effective;//current effective_parameters_for_team are to be cleared
|
||||
const std::vector<config>& ai_params = ai::manager::get_active_ai_parameters_for_side(info_.side);
|
||||
|
||||
for(std::vector<config>::const_iterator i = ai_params.begin(); i != ai_params.end(); ++i) {
|
||||
const std::string& time_of_day = (*i)["time_of_day"];
|
||||
if(time_of_day.empty() == false) {
|
||||
const std::vector<std::string>& times = utils::split(time_of_day);
|
||||
if(std::count(times.begin(),times.end(),tod.id) == 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& turns = (*i)["turns"];
|
||||
if(turns.empty() == false) {
|
||||
bool matched = false;
|
||||
|
||||
const std::vector<std::string>& turns_list = utils::split(turns);
|
||||
for(std::vector<std::string>::const_iterator j = turns_list.begin(); j != turns_list.end(); ++j) {
|
||||
const std::pair<int,int> range = utils::parse_range(*j);
|
||||
if(turn >= range.first && turn <= range.second) {
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!matched) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
aiparams_effective.append(*i);
|
||||
}
|
||||
|
||||
// Get the recruitment pattern from the matching [ai] section,
|
||||
// and fall back to the global recruitment pattern otherwise.
|
||||
info_.recruitment_pattern = utils::split(aiparams_effective["recruitment_pattern"]);
|
||||
if (info_.recruitment_pattern.empty())
|
||||
info_.recruitment_pattern = info_.global_recruitment_pattern;
|
||||
info_.aggression_ = lexical_cast_default<double>(aiparams_effective["aggression"],info_.aggression_);
|
||||
info_.caution_ = lexical_cast_default<double>(aiparams_effective["caution"],info_.caution_);
|
||||
info_.number_of_possible_recruits_to_force_recruit = lexical_cast_default<float>(aiparams_effective["number_of_possible_recruits_to_force_recruit"],info_.number_of_possible_recruits_to_force_recruit);
|
||||
ai::manager::set_active_ai_effective_parameters_for_side(info_.side,aiparams_effective);
|
||||
}
|
||||
|
||||
bool team::calculate_enemies(size_t index) const
|
||||
{
|
||||
if(teams == NULL || index >= teams->size()) {
|
||||
|
@ -663,39 +519,6 @@ void team::set_objectives(const t_string& new_objectives, bool silently)
|
|||
info_.objectives_changed = true;
|
||||
}
|
||||
|
||||
const std::string& team::ai_algorithm() const
|
||||
{
|
||||
return ai::manager::get_active_ai_algorithm_type_for_side(info_.side);
|
||||
}
|
||||
|
||||
const std::string& team::ai_algorithm_identifier() const
|
||||
{
|
||||
return ai::manager::get_active_ai_global_parameters_for_side(info_.side)["id"];
|
||||
}
|
||||
|
||||
const config& team::ai_parameters() const
|
||||
{
|
||||
return ai::manager::get_active_ai_effective_parameters_for_side(info_.side);
|
||||
}
|
||||
|
||||
const config& team::ai_memory() const
|
||||
{
|
||||
return ai::manager::get_active_ai_memory_for_side(info_.side);
|
||||
}
|
||||
|
||||
void team::set_ai_memory(const config& ai_mem){
|
||||
ai::manager::set_active_ai_memory_for_side(info_.side,ai_mem);
|
||||
}
|
||||
|
||||
void team::set_ai_parameters(const config::const_child_itors &ai_parameters)
|
||||
{
|
||||
std::vector<config> ai_params;
|
||||
foreach (const config &p, ai_parameters) {
|
||||
ai_params.push_back(p);
|
||||
}
|
||||
ai::manager::set_active_ai_parameters_for_side(info_.side,ai_params);
|
||||
}
|
||||
|
||||
bool team::shrouded(const map_location& loc) const
|
||||
{
|
||||
if(!teams)
|
||||
|
|
56
src/team.hpp
56
src/team.hpp
|
@ -62,13 +62,6 @@ class team : public viewpoint, public savegame_config
|
|||
};
|
||||
public:
|
||||
|
||||
struct target {
|
||||
explicit target(const config& cfg);
|
||||
void write(config& cfg) const;
|
||||
config criteria;
|
||||
double value;
|
||||
};
|
||||
|
||||
struct team_info
|
||||
{
|
||||
team_info(const config& cfg);
|
||||
|
@ -79,11 +72,8 @@ public:
|
|||
bool gold_add;
|
||||
int income;
|
||||
int income_per_village;
|
||||
size_t average_price;
|
||||
float number_of_possible_recruits_to_force_recruit;
|
||||
mutable int average_price;
|
||||
std::set<std::string> can_recruit;
|
||||
std::vector<std::string> global_recruitment_pattern;
|
||||
std::vector<std::string> recruitment_pattern;
|
||||
std::vector<int> enemies;
|
||||
std::string team_name;
|
||||
t_string user_team_name;
|
||||
|
@ -108,13 +98,6 @@ public:
|
|||
enum CONTROLLER { HUMAN, HUMAN_AI, AI, NETWORK, NETWORK_AI, EMPTY };
|
||||
CONTROLLER controller;
|
||||
|
||||
int villages_per_scout;
|
||||
double leader_value, village_value;
|
||||
//cached values for ai parameters
|
||||
double aggression_, caution_;
|
||||
|
||||
std::vector<target> targets;
|
||||
|
||||
bool share_maps, share_view;
|
||||
bool disallow_observers;
|
||||
bool allow_player;
|
||||
|
@ -153,7 +136,6 @@ public:
|
|||
void set_village_gold(int income) { info_.income_per_village = income; }
|
||||
int total_income() const { return base_income() + villages_.size() * info_.income_per_village; }
|
||||
void new_turn() { gold_ += total_income(); }
|
||||
void set_time_of_day(int turn, const time_of_day &tod);
|
||||
void get_shared_maps();
|
||||
void set_gold(int amount) { gold_ = amount; }
|
||||
void spend_gold(const int amount) { gold_ -= amount; }
|
||||
|
@ -169,27 +151,14 @@ public:
|
|||
void set_current_player(const std::string player)
|
||||
{ info_.current_player = player; }
|
||||
|
||||
size_t average_recruit_price();
|
||||
float num_pos_recruits_to_force() const
|
||||
{ return info_.number_of_possible_recruits_to_force_recruit; }
|
||||
int average_recruit_price() const;
|
||||
|
||||
const std::set<std::string>& recruits() const
|
||||
{ return info_.can_recruit; }
|
||||
void add_recruits(const std::set<std::string>& recruits);
|
||||
void add_recruit(const std::string& s) { info_.can_recruit.insert(s); }
|
||||
void remove_recruit(const std::string& recruits);
|
||||
void set_recruits(const std::set<std::string>& recruits);
|
||||
const std::vector<std::string>& recruitment_pattern() const
|
||||
{ return info_.recruitment_pattern; }
|
||||
bool remove_recruitment_pattern_entry(const std::string& key)
|
||||
{
|
||||
std::vector<std::string>::iterator itor = std::find(info_.recruitment_pattern.begin(),
|
||||
info_.recruitment_pattern.end(),
|
||||
key);
|
||||
if (itor == info_.recruitment_pattern.end())
|
||||
return false;
|
||||
info_.recruitment_pattern.erase(itor);
|
||||
return true;
|
||||
}
|
||||
const std::string& name() const
|
||||
{ return info_.name; }
|
||||
const std::string& save_id() const { return info_.save_id; }
|
||||
|
@ -226,9 +195,6 @@ public:
|
|||
seen_[index] = true;
|
||||
}
|
||||
|
||||
double aggression() const { return info_.aggression_; }
|
||||
double caution() const { return info_.caution_; }
|
||||
|
||||
team_info::CONTROLLER controller() const { return info_.controller; }
|
||||
bool is_human() const { return info_.controller == team_info::HUMAN; }
|
||||
bool is_human_ai() const { return info_.controller == team_info::HUMAN_AI; }
|
||||
|
@ -257,22 +223,6 @@ public:
|
|||
const std::string& flag() const { return info_.flag; }
|
||||
const std::string& flag_icon() const { return info_.flag_icon; }
|
||||
|
||||
const std::string& ai_algorithm() const;
|
||||
const std::string& ai_algorithm_identifier() const;
|
||||
const config& ai_parameters() const;
|
||||
const config& ai_memory() const;
|
||||
void set_ai_memory(const config& ai_mem);
|
||||
void set_ai_parameters(const config::const_child_itors &ai_parameters);
|
||||
|
||||
double leader_value() const { return info_.leader_value; }
|
||||
void set_leader_value(double value) { info_.leader_value = value; }
|
||||
double village_value() const { return info_.village_value; }
|
||||
void set_village_value(double value) { info_.village_value = value; }
|
||||
|
||||
int villages_per_scout() const { return info_.villages_per_scout; }
|
||||
|
||||
std::vector<target>& targets() { return info_.targets; }
|
||||
|
||||
//Returns true if the hex is shrouded/fogged for this side, or
|
||||
//any other ally with shared vision.
|
||||
bool shrouded(const map_location& loc) const;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "global.hpp"
|
||||
|
||||
#include "actions.hpp"
|
||||
#include "config.hpp"
|
||||
#include "tod_manager.hpp"
|
||||
#include "log.hpp"
|
||||
#include "map.hpp"
|
||||
|
@ -35,6 +36,8 @@ static lg::log_domain log_engine("engine");
|
|||
terrain_filter::terrain_filter():
|
||||
cfg_(vconfig()),
|
||||
units_(unit_map()),
|
||||
cfg_(vconfig(empty_config)),
|
||||
units_(*resources::units),
|
||||
max_loop_(),
|
||||
flat_()
|
||||
{
|
||||
|
@ -43,6 +46,7 @@ terrain_filter::terrain_filter():
|
|||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
terrain_filter::terrain_filter(const vconfig& cfg, const unit_map& units,
|
||||
const bool flat_tod, const size_t max_loop) :
|
||||
cfg_(cfg),
|
||||
|
@ -91,7 +95,7 @@ namespace {
|
|||
};
|
||||
} //end anonymous namespace
|
||||
|
||||
bool terrain_filter::match_internal(const map_location& loc, const bool ignore_xy)
|
||||
bool terrain_filter::match_internal(const map_location& loc, const bool ignore_xy) const
|
||||
{
|
||||
if(cfg_.has_attribute("terrain")) {
|
||||
if(cache_.parsed_terrain == NULL) {
|
||||
|
@ -255,7 +259,7 @@ bool terrain_filter::match_internal(const map_location& loc, const bool ignore_x
|
|||
return true;
|
||||
}
|
||||
|
||||
bool terrain_filter::match(const map_location& loc)
|
||||
bool terrain_filter::match(const map_location& loc) const
|
||||
{
|
||||
if(cfg_["x"] == "recall" && cfg_["y"] == "recall") {
|
||||
return !resources::game_map->on_board(loc);
|
||||
|
@ -322,7 +326,7 @@ bool terrain_filter::match(const map_location& loc)
|
|||
return false;
|
||||
}
|
||||
|
||||
void terrain_filter::get_locations(std::set<map_location>& locs)
|
||||
void terrain_filter::get_locations(std::set<map_location>& locs) const
|
||||
{
|
||||
std::vector<map_location> xy_vector = parse_location_range(cfg_["x"],cfg_["y"], resources::game_map);
|
||||
std::set<map_location> xy_set(xy_vector.begin(), xy_vector.end());
|
||||
|
@ -461,4 +465,8 @@ void terrain_filter::get_locations(std::set<map_location>& locs)
|
|||
}
|
||||
}
|
||||
|
||||
config terrain_filter::to_config() const
|
||||
{
|
||||
return cfg_.get_config();
|
||||
}
|
||||
|
||||
|
|
|
@ -17,23 +17,25 @@
|
|||
|
||||
#include "map_location.hpp"
|
||||
#include "pathfind.hpp"
|
||||
#include "variable.hpp"
|
||||
|
||||
class config;
|
||||
class unit;
|
||||
class vconfig;
|
||||
class unit_map;
|
||||
class team;
|
||||
|
||||
//terrain_filter: a class that implements the Standard Location Filter
|
||||
class terrain_filter : public xy_pred {
|
||||
public:
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// This constructor is required for MSVC 9 SP1 due to a bug there
|
||||
// see http://social.msdn.microsoft.com/forums/en-US/vcgeneral/thread/34473b8c-0184-4750-a290-08558e4eda4e
|
||||
// other compilers don't need it.
|
||||
terrain_filter();
|
||||
terrain_filter();
|
||||
#endif
|
||||
terrain_filter(const vconfig &cfg,
|
||||
|
||||
terrain_filter(const vconfig& cfg,
|
||||
const unit_map& units, const bool flat_tod=false, const size_t max_loop=MAX_MAP_AREA);
|
||||
terrain_filter(const vconfig& cfg, const terrain_filter& original);
|
||||
~terrain_filter() {};
|
||||
|
@ -42,12 +44,12 @@ public:
|
|||
terrain_filter& operator=(const terrain_filter &other);
|
||||
|
||||
//match: returns true if and only if the given location matches this filter
|
||||
bool match(const map_location& loc);
|
||||
bool match(const map_location& loc) const;
|
||||
virtual bool operator()(const map_location& loc) { return this->match(loc); }
|
||||
|
||||
//get_locations: gets all locations on the map that match this filter
|
||||
// @param locs - out parameter containing the results
|
||||
void get_locations(std::set<map_location>& locs);
|
||||
void get_locations(std::set<map_location>& locs) const;
|
||||
|
||||
//restrict: limits the allowed radius size and also limits nesting
|
||||
// The purpose to limit the time spent for WML handling
|
||||
|
@ -57,10 +59,11 @@ public:
|
|||
//flatten: use base time of day -- ignore illumination ability
|
||||
void flatten(const bool flat_tod=true) { flat_ = flat_tod; }
|
||||
|
||||
config to_config() const;
|
||||
private:
|
||||
bool match_internal(const map_location& loc, const bool ignore_xy);
|
||||
bool match_internal(const map_location& loc, const bool ignore_xy) const;
|
||||
|
||||
const vconfig& cfg_; //config contains WML for a Standard Location Filter
|
||||
const vconfig cfg_; //config contains WML for a Standard Location Filter
|
||||
const unit_map& units_;
|
||||
|
||||
struct terrain_filter_cache {
|
||||
|
@ -86,7 +89,7 @@ private:
|
|||
std::vector< std::pair<terrain_filter, std::map<map_location,bool> > > adjacent_match_cache;
|
||||
};
|
||||
|
||||
terrain_filter_cache cache_;
|
||||
mutable terrain_filter_cache cache_;
|
||||
size_t max_loop_;
|
||||
bool flat_;
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue