new formula_ai-related stages
This commit is contained in:
parent
5e0e72324e
commit
2ce5d43784
21 changed files with 805 additions and 365 deletions
|
@ -40,38 +40,38 @@ Gs^Fp , Gs^Fp , Wwf , Wwf , Mm , Rd
|
|||
{DEFAULT_SCHEDULE}
|
||||
|
||||
[label]
|
||||
x,y=16,5
|
||||
text="Patrol waypoint 1"
|
||||
x,y=16,5
|
||||
text="Patrol waypoint 1"
|
||||
[/label]
|
||||
|
||||
[label]
|
||||
x,y=16,15
|
||||
text="Patrol waypoint 2"
|
||||
x,y=16,15
|
||||
text="Patrol waypoint 2"
|
||||
[/label]
|
||||
|
||||
[label]
|
||||
x,y=3,14
|
||||
text="Formula priorities test"
|
||||
x,y=3,14
|
||||
text="Formula priorities test"
|
||||
[/label]
|
||||
|
||||
[label]
|
||||
x,y=2,12
|
||||
text="first"
|
||||
x,y=2,12
|
||||
text="first"
|
||||
[/label]
|
||||
|
||||
[label]
|
||||
x,y=3,11
|
||||
text="second"
|
||||
x,y=3,11
|
||||
text="second"
|
||||
[/label]
|
||||
|
||||
[label]
|
||||
x,y=3,13
|
||||
text="third"
|
||||
x,y=3,13
|
||||
text="third"
|
||||
[/label]
|
||||
|
||||
[label]
|
||||
x,y=8,5
|
||||
text="Location guarded (range = 3)"
|
||||
x,y=8,5
|
||||
text="Location guarded (range = 3)"
|
||||
[/label]
|
||||
|
||||
[side]
|
||||
|
@ -92,26 +92,25 @@ Gs^Fp , Gs^Fp , Wwf , Wwf , Mm , Rd
|
|||
[unit]
|
||||
x,y=3,12
|
||||
type="Elvish Fighter"
|
||||
random_traits=no
|
||||
random_traits=no
|
||||
generate_name=yes
|
||||
[modifications]
|
||||
[trait]
|
||||
id=move
|
||||
[effect]
|
||||
apply_to=movement
|
||||
set=0
|
||||
[/effect]
|
||||
[/trait]
|
||||
[trait]
|
||||
id=hp
|
||||
[effect]
|
||||
apply_to=hitpoints
|
||||
increase_total=120
|
||||
[/effect]
|
||||
[/trait]
|
||||
[/modifications]
|
||||
[modifications]
|
||||
[trait]
|
||||
id=move
|
||||
[effect]
|
||||
apply_to=movement
|
||||
set=0
|
||||
[/effect]
|
||||
[/trait]
|
||||
[trait]
|
||||
id=hp
|
||||
[effect]
|
||||
apply_to=hitpoints
|
||||
increase_total=120
|
||||
[/effect]
|
||||
[/trait]
|
||||
[/modifications]
|
||||
[/unit]
|
||||
|
||||
[/side]
|
||||
|
||||
[side]
|
||||
|
@ -128,69 +127,68 @@ Gs^Fp , Gs^Fp , Wwf , Wwf , Mm , Rd
|
|||
x,y=8,5
|
||||
type="Orcish Archer"
|
||||
generate_name=yes
|
||||
[ai]
|
||||
formula="if(attack, attack, move(me.loc, me.vars.guard_loc))
|
||||
[ai]
|
||||
formula="if(attack, attack, move(me.loc, me.vars.guard_loc))
|
||||
where attack = choose(filter(attacks, units = [me.loc] and distance_between(me.vars.guard_loc, target) <= me.vars.guard_radius), avg_damage_inflicted)"
|
||||
[vars]
|
||||
guard_radius=3
|
||||
guard_loc="loc(8,5)"
|
||||
[/vars]
|
||||
[/ai]
|
||||
[vars]
|
||||
guard_radius=3
|
||||
guard_loc="loc(8,5)"
|
||||
[/vars]
|
||||
[/ai]
|
||||
[/unit]
|
||||
[unit]
|
||||
x,y=3,8
|
||||
type="Walking Corpse"
|
||||
generate_name=yes
|
||||
[ai]
|
||||
formula="move(me.loc, nearest_loc(nearest_loc(me.loc,map(filter(map.terrain,id='castle'),loc)),unit_moves(me.loc)))"
|
||||
[/ai]
|
||||
[ai]
|
||||
formula="move(me.loc, nearest_loc(nearest_loc(me.loc,map(filter(map.terrain,id='castle'),loc)),unit_moves(me.loc)))"
|
||||
[/ai]
|
||||
[/unit]
|
||||
|
||||
[unit]
|
||||
x,y=16,5
|
||||
type="Wolf Rider"
|
||||
generate_name=yes
|
||||
[ai]
|
||||
loop_formula="{ai/formula/patrol.fai}"
|
||||
[vars]
|
||||
guard_radius=3
|
||||
waypoints=[ loc(16,5) -> loc(16,15), loc(16,15) -> loc(16,5) ]
|
||||
next_step="loc(16,5)"
|
||||
[/vars]
|
||||
[/ai]
|
||||
[ai]
|
||||
loop_formula="{ai/formula/patrol.fai}"
|
||||
[vars]
|
||||
guard_radius=3
|
||||
waypoints=[ loc(16,5) -> loc(16,15), loc(16,15) -> loc(16,5) ]
|
||||
next_step="loc(16,5)"
|
||||
[/vars]
|
||||
[/ai]
|
||||
[/unit]
|
||||
|
||||
[unit]
|
||||
x,y=3,11
|
||||
type="Goblin Spearman"
|
||||
generate_name=yes
|
||||
[ai]
|
||||
formula="attack(me.loc, me.loc, loc(3,12))"
|
||||
priority=10
|
||||
[/ai]
|
||||
[ai]
|
||||
formula="attack(me.loc, me.loc, loc(3,12))"
|
||||
priority=10
|
||||
[/ai]
|
||||
[/unit]
|
||||
|
||||
[unit]
|
||||
x,y=3,13
|
||||
type="Goblin Spearman"
|
||||
generate_name=yes
|
||||
[ai]
|
||||
priority=9
|
||||
formula="attack(me.loc, me.loc, loc(3,12))"
|
||||
[/ai]
|
||||
[ai]
|
||||
priority=9
|
||||
formula="attack(me.loc, me.loc, loc(3,12))"
|
||||
[/ai]
|
||||
[/unit]
|
||||
|
||||
[unit]
|
||||
x,y=2,12
|
||||
type="Goblin Spearman"
|
||||
generate_name=yes
|
||||
[ai]
|
||||
priority=11
|
||||
formula="attack(me.loc, me.loc, loc(3,12))"
|
||||
[/ai]
|
||||
[ai]
|
||||
priority=11
|
||||
formula="attack(me.loc, me.loc, loc(3,12))"
|
||||
[/ai]
|
||||
[/unit]
|
||||
|
||||
|
||||
[unit]
|
||||
x,y=7,20
|
||||
type="Silver Mage"
|
||||
|
@ -219,26 +217,36 @@ Gs^Fp , Gs^Fp , Wwf , Wwf , Mm , Rd
|
|||
generate_name=yes
|
||||
[/unit]
|
||||
|
||||
ai_algorithm=formula_ai
|
||||
[ai]
|
||||
version=10703
|
||||
[stage]
|
||||
engine=fai
|
||||
name=unit_formulas
|
||||
[/stage]
|
||||
|
||||
eval_list=yes
|
||||
[register_candidate_move]
|
||||
name=scouting
|
||||
type=movement
|
||||
action="{ai/formula/scouting_move.fai}"
|
||||
evaluation="{ai/formula/scouting_eval.fai}"
|
||||
[/register_candidate_move]
|
||||
[stage]
|
||||
engine=fai
|
||||
name=move
|
||||
move="{ai/formula/opening.fai}"
|
||||
[/stage]
|
||||
|
||||
[register_candidate_move]
|
||||
name=level_up_attack
|
||||
type=attack
|
||||
action="{ai/formula/level_up_attack_move.fai}"
|
||||
evaluation="{ai/formula/level_up_attack_eval.fai}"
|
||||
[/register_candidate_move]
|
||||
[stage]
|
||||
engine=fai
|
||||
name=rca
|
||||
[register_candidate_move]
|
||||
name=scouting
|
||||
type=movement
|
||||
action="{ai/formula/scouting_move.fai}"
|
||||
evaluation="{ai/formula/scouting_eval.fai}"
|
||||
[/register_candidate_move]
|
||||
|
||||
|
||||
move="{ai/formula/opening.fai}"
|
||||
[register_candidate_move]
|
||||
name=level_up_attack
|
||||
type=attack
|
||||
action="{ai/formula/level_up_attack_move.fai}"
|
||||
evaluation="{ai/formula/level_up_attack_eval.fai}"
|
||||
[/register_candidate_move]
|
||||
[/stage]
|
||||
[/ai]
|
||||
[/side]
|
||||
[/test]
|
||||
|
|
|
@ -88,6 +88,12 @@
|
|||
<Unit filename="..\..\src\ai\formula\candidates.hpp" />
|
||||
<Unit filename="..\..\src\ai\formula\function_table.cpp" />
|
||||
<Unit filename="..\..\src\ai\formula\function_table.hpp" />
|
||||
<Unit filename="..\..\src\ai\formula\stage_rca_formulas.cpp" />
|
||||
<Unit filename="..\..\src\ai\formula\stage_rca_formulas.hpp" />
|
||||
<Unit filename="..\..\src\ai\formula\stage_side_formulas.cpp" />
|
||||
<Unit filename="..\..\src\ai\formula\stage_side_formulas.hpp" />
|
||||
<Unit filename="..\..\src\ai\formula\stage_unit_formulas.cpp" />
|
||||
<Unit filename="..\..\src\ai\formula\stage_unit_formulas.hpp" />
|
||||
<Unit filename="..\..\src\ai\game_info.cpp" />
|
||||
<Unit filename="..\..\src\ai\game_info.hpp" />
|
||||
<Unit filename="..\..\src\ai\interface.cpp" />
|
||||
|
|
|
@ -117,6 +117,12 @@
|
|||
<Unit filename="..\..\src\ai\formula\candidates.hpp" />
|
||||
<Unit filename="..\..\src\ai\formula\function_table.cpp" />
|
||||
<Unit filename="..\..\src\ai\formula\function_table.hpp" />
|
||||
<Unit filename="..\..\src\ai\formula\stage_rca_formulas.cpp" />
|
||||
<Unit filename="..\..\src\ai\formula\stage_rca_formulas.hpp" />
|
||||
<Unit filename="..\..\src\ai\formula\stage_side_formulas.cpp" />
|
||||
<Unit filename="..\..\src\ai\formula\stage_side_formulas.hpp" />
|
||||
<Unit filename="..\..\src\ai\formula\stage_unit_formulas.cpp" />
|
||||
<Unit filename="..\..\src\ai\formula\stage_unit_formulas.hpp" />
|
||||
<Unit filename="..\..\src\ai\game_info.cpp" />
|
||||
<Unit filename="..\..\src\ai\game_info.hpp" />
|
||||
<Unit filename="..\..\src\ai\interface.cpp" />
|
||||
|
|
|
@ -4391,6 +4391,90 @@
|
|||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\formula\stage_rca_formulas.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\ai\formula\"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\ai\formula\"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug (fast)|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\ai\formula\"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\formula\stage_side_formulas.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\ai\formula\"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\ai\formula\"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug (fast)|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\ai\formula\"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\formula\stage_unit_formulas.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\ai\formula\"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\ai\formula\"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug (fast)|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\ai\formula\"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="testing"
|
||||
|
@ -5682,6 +5766,18 @@
|
|||
RelativePath="..\..\src\ai\formula\function_table.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\formula\stage_rca_formulas.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\formula\stage_side_formulas.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\formula\stage_unit_formulas.hpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="testing"
|
||||
|
|
|
@ -241,6 +241,9 @@ SET(wesnoth-main_SRC
|
|||
ai/formula/callable_objects.cpp
|
||||
ai/formula/candidates.cpp
|
||||
ai/formula/function_table.cpp
|
||||
ai/formula/stage_rca_formulas.cpp
|
||||
ai/formula/stage_side_formulas.cpp
|
||||
ai/formula/stage_unit_formulas.cpp
|
||||
ai/game_info.cpp
|
||||
ai/interface.cpp
|
||||
ai/manager.cpp
|
||||
|
|
|
@ -64,6 +64,9 @@ wesnoth_source = \
|
|||
ai/formula/callable_objects.cpp \
|
||||
ai/formula/candidates.cpp \
|
||||
ai/formula/function_table.cpp \
|
||||
ai/formula/stage_rca_formulas.cpp \
|
||||
ai/formula/stage_side_formulas.cpp \
|
||||
ai/formula/stage_unit_formulas.cpp \
|
||||
ai/game_info.cpp \
|
||||
ai/interface.cpp \
|
||||
ai/manager.cpp \
|
||||
|
@ -227,7 +230,7 @@ wesnoth_source = \
|
|||
widgets/combo_drag.cpp \
|
||||
widgets/drop_target.cpp \
|
||||
widgets/scrollpane.cpp
|
||||
|
||||
|
||||
# used with editor option in the wesnoth target
|
||||
wesnoth_editor_SOURCES = \
|
||||
gui/dialogs/editor_generate_map.cpp \
|
||||
|
|
|
@ -169,6 +169,9 @@ wesnoth_sources = Split("""
|
|||
ai/formula/callable_objects.cpp
|
||||
ai/formula/candidates.cpp
|
||||
ai/formula/function_table.cpp
|
||||
ai/formula/stage_rca_formulas.cpp
|
||||
ai/formula/stage_side_formulas.cpp
|
||||
ai/formula/stage_unit_formulas.cpp
|
||||
ai/game_info.cpp
|
||||
ai/interface.cpp
|
||||
ai/manager.cpp
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
|
||||
#include "ai.hpp"
|
||||
#include "engine_fai.hpp"
|
||||
#include "../formula/stage_rca_formulas.hpp"
|
||||
#include "../formula/stage_side_formulas.hpp"
|
||||
#include "../formula/stage_unit_formulas.hpp"
|
||||
#include "rca.hpp"
|
||||
#include "../../foreach.hpp"
|
||||
#include "../../log.hpp"
|
||||
|
@ -70,9 +73,9 @@ private:
|
|||
};
|
||||
|
||||
engine_fai::engine_fai( readonly_context &context, const config &cfg )
|
||||
: engine(context,cfg), formula_ai_(context,cfg.child("formula_ai"))
|
||||
: engine(context,cfg), formula_ai_(context,cfg.child_or_empty("formula_ai"))
|
||||
{
|
||||
|
||||
formula_ai_.on_create();
|
||||
}
|
||||
|
||||
|
||||
|
@ -93,6 +96,20 @@ void engine_fai::do_parse_candidate_action_from_config( rca_context &context, co
|
|||
|
||||
}
|
||||
|
||||
void engine_fai::do_parse_stage_from_config( ai_context &context, const config &cfg, std::back_insert_iterator<std::vector< stage_ptr > > b )
|
||||
{
|
||||
if (!cfg) {
|
||||
return;
|
||||
}
|
||||
const std::string &name = cfg["name"];
|
||||
if (name=="rca_formulas") {
|
||||
*b = stage_ptr(new stage_rca_formulas(context,cfg,formula_ai_));
|
||||
} else if (name=="side_formulas") {
|
||||
*b = stage_ptr(new stage_side_formulas(context,cfg,formula_ai_));
|
||||
} else if (name=="unit_formulas") {
|
||||
*b = stage_ptr(new stage_unit_formulas(context,cfg,formula_ai_));
|
||||
}
|
||||
}
|
||||
|
||||
std::string engine_fai::evaluate(const std::string &str)
|
||||
{
|
||||
|
|
|
@ -38,6 +38,8 @@ public:
|
|||
|
||||
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( ai_context &context, const config &cfg, std::back_insert_iterator<std::vector< stage_ptr > > b );
|
||||
|
||||
virtual std::string evaluate(const std::string &str);
|
||||
|
||||
virtual std::string get_name() const;
|
||||
|
|
|
@ -293,9 +293,6 @@ void ai_default::new_turn()
|
|||
unit_combat_scores_.clear();
|
||||
invalidate_keeps_cache();
|
||||
unit_stats_cache().clear();
|
||||
if (formula_ai_ != NULL){
|
||||
formula_ai_->new_turn();
|
||||
}
|
||||
}
|
||||
|
||||
std::string ai_default::describe_self(){
|
||||
|
@ -1774,18 +1771,13 @@ bool ai_default::is_accessible(const location& loc, const move_map& dstsrc) cons
|
|||
}
|
||||
|
||||
|
||||
variant ai_default::get_value(const std::string& key) const
|
||||
variant ai_default::get_value(const std::string &/*key*/) const
|
||||
{
|
||||
if(key == "map") {
|
||||
return variant(new gamemap_callable(get_info().map));
|
||||
}
|
||||
return variant();
|
||||
}
|
||||
|
||||
void ai_default::get_inputs(std::vector<game_logic::formula_input>* inputs) const
|
||||
void ai_default::get_inputs(std::vector<game_logic::formula_input> */*inputs*/) const
|
||||
{
|
||||
using game_logic::FORMULA_READ_ONLY;
|
||||
inputs->push_back(game_logic::formula_input("map", FORMULA_READ_ONLY));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "../../menu_events.hpp"
|
||||
|
||||
static lg::log_domain log_formula_ai("ai/formula_ai");
|
||||
#define DBG_AI LOG_STREAM(debug, log_formula_ai)
|
||||
#define LOG_AI LOG_STREAM(info, log_formula_ai)
|
||||
#define WRN_AI LOG_STREAM(warn, log_formula_ai)
|
||||
#define ERR_AI LOG_STREAM(err, log_formula_ai)
|
||||
|
@ -45,11 +46,7 @@ namespace ai {
|
|||
|
||||
game_logic::candidate_action_ptr formula_ai::load_candidate_action_from_config(const config& cfg)
|
||||
{
|
||||
return candidate_action_manager_.load_candidate_action_from_config(cfg,this,&function_table);
|
||||
}
|
||||
|
||||
std::string formula_ai::describe_self(){
|
||||
return "[formula_ai]";
|
||||
return candidate_action_manager_.load_candidate_action_from_config(cfg,this,&function_table_);
|
||||
}
|
||||
|
||||
int formula_ai::get_recursion_count() const{
|
||||
|
@ -57,20 +54,18 @@ int formula_ai::get_recursion_count() const{
|
|||
}
|
||||
|
||||
|
||||
formula_ai::formula_ai(readonly_context &context, const config &cfg) :
|
||||
formula_ai::formula_ai(readonly_context &context, const config &cfg)
|
||||
:
|
||||
readonly_context_proxy(),
|
||||
cfg_(cfg),
|
||||
recursion_counter_(context.get_recursion_count()),
|
||||
recruit_formula_(),
|
||||
move_formula_(),
|
||||
outcome_positions_(),
|
||||
possible_moves_(),
|
||||
move_maps_valid_(false),
|
||||
attacks_cache_(),
|
||||
keeps_cache_(),
|
||||
infinite_loop_guardian_(),
|
||||
vars_(),
|
||||
function_table(*this),
|
||||
function_table_(*this),
|
||||
candidate_action_manager_()
|
||||
{
|
||||
add_ref();
|
||||
|
@ -105,7 +100,7 @@ void formula_ai::display_message(const std::string& msg) const
|
|||
|
||||
formula_ptr formula_ai::create_optional_formula(const std::string& formula_string){
|
||||
try{
|
||||
return game_logic::formula::create_optional_formula(formula_string, &function_table);
|
||||
return game_logic::formula::create_optional_formula(formula_string, &function_table_);
|
||||
}
|
||||
catch(formula_error& e) {
|
||||
handle_exception(e);
|
||||
|
@ -113,127 +108,6 @@ formula_ptr formula_ai::create_optional_formula(const std::string& formula_strin
|
|||
}
|
||||
}
|
||||
|
||||
void formula_ai::new_turn()
|
||||
{
|
||||
move_maps_valid_ = false;
|
||||
//ai_default::new_turn();
|
||||
}
|
||||
|
||||
void formula_ai::play_turn()
|
||||
{
|
||||
/*
|
||||
//execute units formulas first
|
||||
|
||||
unit_formula_set units_with_formulas;
|
||||
|
||||
for(unit_map::unit_iterator i = units_.begin() ; i != units_.end() ; ++i)
|
||||
{
|
||||
if ( (i->second.side() == get_side()) )
|
||||
{
|
||||
if ( i->second.has_formula() || i->second.has_loop_formula()) {
|
||||
int priority = 0;
|
||||
if( i->second.has_priority_formula() ) {
|
||||
try {
|
||||
game_logic::const_formula_ptr priority_formula(new game_logic::formula(i->second.get_priority_formula(), &function_table));
|
||||
game_logic::map_formula_callable callable(this);
|
||||
callable.add_ref();
|
||||
callable.add("me", variant(new unit_callable(*i)));
|
||||
priority = (formula::evaluate(priority_formula, callable)).as_int();
|
||||
} catch(formula_error& e) {
|
||||
if(e.filename == "formula")
|
||||
e.line = 0;
|
||||
handle_exception( e, "Unit priority formula error for unit: '" + i->second.type_id() + "' standing at (" + boost::lexical_cast<std::string>(i->first.x+1) + "," + boost::lexical_cast<std::string>(i->first.y+1) + ")");
|
||||
|
||||
priority = 0;
|
||||
} catch(type_error& e) {
|
||||
priority = 0;
|
||||
ERR_AI << "formula type error while evaluating unit priority formula " << e.message << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
units_with_formulas.insert( unit_formula_pair( i, priority ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(unit_formula_set::iterator pair_it = units_with_formulas.begin() ; pair_it != units_with_formulas.end() ; ++pair_it)
|
||||
{
|
||||
unit_map::iterator i = pair_it->first;
|
||||
|
||||
if( i.valid() ) {
|
||||
|
||||
if ( i->second.has_formula() ) {
|
||||
try {
|
||||
game_logic::const_formula_ptr formula(new game_logic::formula(i->second.get_formula(), &function_table));
|
||||
game_logic::map_formula_callable callable(this);
|
||||
callable.add_ref();
|
||||
callable.add("me", variant(new unit_callable(*i)));
|
||||
make_action(formula, callable);
|
||||
}
|
||||
catch(formula_error& e) {
|
||||
if(e.filename == "formula")
|
||||
e.line = 0;
|
||||
handle_exception( e, "Unit formula error for unit: '" + i->second.type_id() + "' standing at (" + boost::lexical_cast<std::string>(i->first.x+1) + "," + boost::lexical_cast<std::string>(i->first.y+1) + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( i.valid() ) {
|
||||
if( i->second.has_loop_formula() )
|
||||
{
|
||||
try {
|
||||
game_logic::const_formula_ptr loop_formula(new game_logic::formula(i->second.get_loop_formula(), &function_table));
|
||||
game_logic::map_formula_callable callable(this);
|
||||
callable.add_ref();
|
||||
callable.add("me", variant(new unit_callable(*i)));
|
||||
while ( !make_action(loop_formula, callable).is_empty() && i.valid() ) {}
|
||||
}
|
||||
catch(formula_error& e) {
|
||||
if(e.filename == "formula")
|
||||
e.line = 0;
|
||||
handle_exception( e, "Unit loop formula error for unit: '" + i->second.type_id() + "' standing at (" + boost::lexical_cast<std::string>(i->first.x+1) + "," + boost::lexical_cast<std::string>(i->first.y+1) + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if( candidate_action_manager_.has_candidate_actions() ) {
|
||||
move_maps_valid_ = false;
|
||||
while( candidate_action_manager_.evaluate_candidate_actions(this, units_) )
|
||||
{
|
||||
game_logic::map_formula_callable callable(this);
|
||||
callable.add_ref();
|
||||
|
||||
candidate_action_manager_.update_callable_map( callable );
|
||||
|
||||
const_formula_ptr move_formula(candidate_action_manager_.get_best_action_formula());
|
||||
|
||||
make_action(move_formula, callable);
|
||||
|
||||
move_maps_valid_ = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(formula_error& e) {
|
||||
if(e.filename == "formula")
|
||||
e.line = 0;
|
||||
handle_exception( e, "Formula error in RCA loop");
|
||||
}
|
||||
|
||||
game_logic::map_formula_callable callable(this);
|
||||
callable.add_ref();
|
||||
try {
|
||||
while( !make_action(move_formula_,callable).is_empty() ) { }
|
||||
}
|
||||
catch(formula_error& e) {
|
||||
if(e.filename == "formula")
|
||||
e.line = 0;
|
||||
handle_exception( e, "Formula error");
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void formula_ai::set_ai_context(ai_context *context)
|
||||
{
|
||||
|
@ -246,7 +120,7 @@ std::string formula_ai::evaluate(const std::string& formula_str)
|
|||
try{
|
||||
move_maps_valid_ = false;
|
||||
|
||||
game_logic::formula f(formula_str, &function_table);
|
||||
game_logic::formula f(formula_str, &function_table_);
|
||||
|
||||
game_logic::map_formula_callable callable(this);
|
||||
callable.add_ref();
|
||||
|
@ -289,17 +163,6 @@ void formula_ai::prepare_move() const
|
|||
|
||||
variant formula_ai::make_action(game_logic::const_formula_ptr formula_, const game_logic::formula_callable& variables)
|
||||
{
|
||||
// if(!formula_) {
|
||||
// if(get_recursion_count()<recursion_counter::MAX_COUNTER_VALUE) {
|
||||
// LOG_AI << "Falling back to default AI.\n";
|
||||
// ai_ptr fallback( manager::create_transient_ai(manager::AI_TYPE_DEFAULT, config(), this));
|
||||
// if (fallback){
|
||||
// fallback->play_turn();
|
||||
// }
|
||||
// }
|
||||
// return variant();
|
||||
// }
|
||||
|
||||
move_maps_valid_ = false;
|
||||
|
||||
LOG_AI << "do move...\n";
|
||||
|
@ -392,51 +255,43 @@ std::set<map_location> formula_ai::get_allowed_teleports(unit_map::iterator& uni
|
|||
}
|
||||
|
||||
map_location formula_ai::path_calculator(const map_location& src, const map_location& dst, unit_map::iterator& unit_it) const{
|
||||
std::map<map_location,paths>::iterator path = possible_moves_.find(src);
|
||||
std::map<map_location,paths>::const_iterator path = get_possible_moves().find(src);
|
||||
|
||||
map_location destination = dst;
|
||||
map_location destination = dst;
|
||||
|
||||
//check if destination is within unit's reach, if not, calculate where to move
|
||||
//check if destination is within unit's reach, if not, calculate where to move
|
||||
if (!path->second.destinations.contains(dst))
|
||||
{
|
||||
std::set<map_location> allowed_teleports = get_allowed_teleports(unit_it);
|
||||
//destination is too far, check where unit can go
|
||||
|
||||
std::set<map_location> allowed_teleports = get_allowed_teleports(unit_it);
|
||||
//destination is too far, check where unit can go
|
||||
plain_route route = shortest_path_calculator( src, dst, unit_it, allowed_teleports );
|
||||
|
||||
if( route.steps.size() == 0 ) {
|
||||
emergency_path_calculator em_calc(unit_it->second, get_info().map);
|
||||
|
||||
route = a_star_search(src, dst, 1000.0, &em_calc, get_info().map.w(), get_info().map.h(), &allowed_teleports);
|
||||
|
||||
if( route.steps.size() < 2 ) {
|
||||
return map_location();
|
||||
}
|
||||
}
|
||||
|
||||
destination = map_location();
|
||||
|
||||
for (std::vector<map_location>::const_iterator loc_iter = route.steps.begin() + 1 ; loc_iter !=route.steps.end(); ++loc_iter) {
|
||||
typedef move_map::const_iterator Itor;
|
||||
std::pair<Itor,Itor> range = get_srcdst().equal_range(src);
|
||||
|
||||
bool found = false;
|
||||
for(Itor i = range.first; i != range.second; ++i) {
|
||||
if (i->second == *loc_iter ) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if( route.steps.size() == 0 ) {
|
||||
emergency_path_calculator em_calc(unit_it->second, get_info().map);
|
||||
route = a_star_search(src, dst, 1000.0, &em_calc, get_info().map.w(), get_info().map.h(), &allowed_teleports);
|
||||
if( route.steps.size() < 2 ) {
|
||||
return map_location();
|
||||
}
|
||||
}
|
||||
if ( !found ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
destination = *loc_iter;
|
||||
}
|
||||
return destination;
|
||||
}
|
||||
|
||||
return destination;
|
||||
destination = map_location();
|
||||
for (std::vector<map_location>::const_iterator loc_iter = route.steps.begin() + 1 ; loc_iter !=route.steps.end(); ++loc_iter) {
|
||||
typedef move_map::const_iterator Itor;
|
||||
std::pair<Itor,Itor> range = get_srcdst().equal_range(src);
|
||||
bool found = false;
|
||||
for(Itor i = range.first; i != range.second; ++i) {
|
||||
if (i->second == *loc_iter ) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !found ) {
|
||||
continue;
|
||||
}
|
||||
destination = *loc_iter;
|
||||
}
|
||||
return destination;
|
||||
}
|
||||
return destination;
|
||||
}
|
||||
|
||||
//commandline=true when we evaluate formula from commandline, false otherwise (default)
|
||||
|
@ -592,7 +447,7 @@ variant formula_ai::execute_variant(const variant& var, ai_context &ai_, bool co
|
|||
//is_ok() must be checked or the code will complain :)
|
||||
if (!recruit_result->is_ok()) {
|
||||
//get_status() can be used to fetch the error code
|
||||
LOG_AI << "ERROR #" <<recruit_result->get_status() << " while executing 'recruit' formula function\n"<<std::endl;
|
||||
ERR_AI << "ERROR #" <<recruit_result->get_status() << " while executing 'recruit' formula function\n"<<std::endl;
|
||||
|
||||
if(safe_call) {
|
||||
//safe call was called, prepare error information
|
||||
|
@ -612,7 +467,7 @@ variant formula_ai::execute_variant(const variant& var, ai_context &ai_, bool co
|
|||
made_moves.push_back(action);
|
||||
} else {
|
||||
//too many calls in a row - possible infinite loop
|
||||
LOG_AI << "ERROR #" << 5001 << " while executing 'set_var' formula function\n";
|
||||
ERR_AI << "ERROR #" << 5001 << " while executing 'set_var' formula function\n";
|
||||
|
||||
if( safe_call )
|
||||
error = variant(new safe_call_result(set_var_command, 5001));
|
||||
|
@ -621,7 +476,7 @@ variant formula_ai::execute_variant(const variant& var, ai_context &ai_, bool co
|
|||
int status = 0;
|
||||
unit_map::iterator unit;
|
||||
|
||||
if( infinite_loop_guardian_.set_unit_var_check() ) {
|
||||
if( !infinite_loop_guardian_.set_unit_var_check() ) {
|
||||
status = 5001; //exceeded nmber of calls in a row - possible infinite loop
|
||||
} else if( (unit = get_info().units.find(set_unit_var_command->loc())) == get_info().units.end() ) {
|
||||
status = 5002; //unit not found
|
||||
|
@ -634,21 +489,23 @@ variant formula_ai::execute_variant(const variant& var, ai_context &ai_, bool co
|
|||
unit->second.add_formula_var(set_unit_var_command->key(), set_unit_var_command->value());
|
||||
made_moves.push_back(action);
|
||||
} else {
|
||||
LOG_AI << "ERROR #" << status << " while executing 'set_unit_var' formula function\n";
|
||||
ERR_AI << "ERROR #" << status << " while executing 'set_unit_var' formula function\n";
|
||||
if(safe_call)
|
||||
error = variant(new safe_call_result(set_unit_var_command,
|
||||
status));
|
||||
}
|
||||
|
||||
} else if( action.is_string() && action.as_string() == "recruit") {
|
||||
if( do_recruitment() )
|
||||
made_moves.push_back(action);
|
||||
//:} else if( action.is_string() && action.as_string() == "recruit") {
|
||||
// recruitment temporary disabled
|
||||
// @todo 1.7.3 rework recruitment as aspect
|
||||
//if( do_recruitment() )
|
||||
// made_moves.push_back(action);
|
||||
} else if( action.is_string() && action.as_string() == "continue") {
|
||||
if( infinite_loop_guardian_.continue_check() ) {
|
||||
made_moves.push_back(action);
|
||||
} else {
|
||||
//too many calls in a row - possible infinite loop
|
||||
LOG_AI << "ERROR #" << 5001 << " while executing 'continue' formula keyword\n";
|
||||
ERR_AI << "ERROR #" << 5001 << " while executing 'continue' formula keyword\n";
|
||||
|
||||
if( safe_call )
|
||||
error = variant(new safe_call_result(NULL, 5001));
|
||||
|
@ -713,30 +570,9 @@ variant formula_ai::execute_variant(const variant& var, ai_context &ai_, bool co
|
|||
return variant(&made_moves);
|
||||
}
|
||||
|
||||
|
||||
bool formula_ai::do_recruitment()
|
||||
void formula_ai::add_formula_function(const std::string& name, const_formula_ptr formula, const_formula_ptr precondition, const std::vector<std::string>& args)
|
||||
{
|
||||
if(!recruit_formula_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
|
||||
game_logic::map_formula_callable callable(this);
|
||||
callable.add_ref();
|
||||
try {
|
||||
while( !make_action(recruit_formula_,callable).is_empty() )
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
catch(formula_error& e) {
|
||||
if(e.filename == "recruit formula")
|
||||
e.line = 0;
|
||||
handle_exception( e, "Formula error");
|
||||
}
|
||||
|
||||
return ret;
|
||||
function_table_.add_formula_function(name,formula,precondition,args);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -937,11 +773,12 @@ variant formula_ai::get_value(const std::string& key) const
|
|||
} else if(key == "keeps")
|
||||
{
|
||||
return get_keeps();
|
||||
|
||||
} else if(key == "map")
|
||||
{
|
||||
return variant(new gamemap_callable(get_info().map));
|
||||
} else if(key == "villages")
|
||||
{
|
||||
return villages_from_set(get_info().map.villages());
|
||||
|
||||
} else if(key == "villages_of_side")
|
||||
{
|
||||
std::vector<variant> vars;
|
||||
|
@ -964,7 +801,6 @@ variant formula_ai::get_value(const std::string& key) const
|
|||
return villages_from_set(get_info().map.villages(), ¤t_team().villages());
|
||||
}
|
||||
|
||||
//return ai_default::get_value(key);
|
||||
return variant();
|
||||
}
|
||||
|
||||
|
@ -980,7 +816,7 @@ void formula_ai::get_inputs(std::vector<formula_input>* inputs) const
|
|||
inputs->push_back(game_logic::formula_input("vars", FORMULA_READ_ONLY));
|
||||
inputs->push_back(game_logic::formula_input("allies", FORMULA_READ_ONLY));
|
||||
inputs->push_back(game_logic::formula_input("enemies", FORMULA_READ_ONLY));
|
||||
inputs->push_back(game_logic::formula_input("my_moves", FORMULA_READ_ONLY));
|
||||
inputs->push_back(game_logic::formula_input("map", FORMULA_READ_ONLY));
|
||||
inputs->push_back(game_logic::formula_input("my_attacks", FORMULA_READ_ONLY));
|
||||
inputs->push_back(game_logic::formula_input("enemy_moves", FORMULA_READ_ONLY));
|
||||
inputs->push_back(game_logic::formula_input("my_leader", FORMULA_READ_ONLY));
|
||||
|
@ -994,8 +830,6 @@ void formula_ai::get_inputs(std::vector<formula_input>* inputs) const
|
|||
inputs->push_back(game_logic::formula_input("my_villages", FORMULA_READ_ONLY));
|
||||
inputs->push_back(game_logic::formula_input("villages_of_side", FORMULA_READ_ONLY));
|
||||
inputs->push_back(game_logic::formula_input("enemy_and_unowned_villages", FORMULA_READ_ONLY));
|
||||
|
||||
//ai_default::get_inputs(inputs);
|
||||
}
|
||||
|
||||
variant formula_ai::get_keeps() const
|
||||
|
@ -1046,49 +880,28 @@ 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 = cfg_;
|
||||
|
||||
// load candidate actions from config
|
||||
candidate_action_manager_.load_config(ai_param, this, &function_table);
|
||||
|
||||
foreach (const config &func, ai_param.child_range("function"))
|
||||
foreach (const config &func, cfg_.child_range("function"))
|
||||
{
|
||||
const t_string &name = func["name"];
|
||||
const t_string &inputs = func["inputs"];
|
||||
const t_string &formula_str = func["formula"];
|
||||
|
||||
std::vector<std::string> args = utils::split(inputs);
|
||||
|
||||
try {
|
||||
function_table.add_formula_function(name,
|
||||
game_logic::const_formula_ptr(new game_logic::formula(formula_str, &function_table)),
|
||||
game_logic::formula::create_optional_formula(func["precondition"], &function_table),
|
||||
args);
|
||||
}
|
||||
catch(formula_error& e) {
|
||||
handle_exception(e, "Error while registering function '" + name + "'");
|
||||
}
|
||||
add_formula_function(name,
|
||||
create_optional_formula(formula_str),
|
||||
create_optional_formula(func["precondition"]),
|
||||
args);
|
||||
}
|
||||
|
||||
|
||||
try{
|
||||
recruit_formula_ = game_logic::formula::create_optional_formula(cfg_["recruitment"], &function_table);
|
||||
}
|
||||
catch(formula_error& e) {
|
||||
handle_exception(e);
|
||||
recruit_formula_ = game_logic::formula_ptr();
|
||||
}
|
||||
|
||||
try{
|
||||
move_formula_ = game_logic::formula::create_optional_formula(cfg_["move"], &function_table);
|
||||
}
|
||||
catch(formula_error& e) {
|
||||
handle_exception(e);
|
||||
move_formula_ = game_logic::formula_ptr();
|
||||
}
|
||||
catch(game_logic::formula_error& e) {
|
||||
handle_exception(e, "Error while registering function '" + name + "'");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void formula_ai::evaluate_candidate_action(game_logic::candidate_action_ptr fai_ca)
|
||||
{
|
||||
fai_ca->evaluate(this,get_info().units);
|
||||
|
@ -1152,6 +965,7 @@ config formula_ai::to_config() const
|
|||
{
|
||||
return config();
|
||||
}
|
||||
DBG_AI << "formula_ai::to_config(): "<< cfg_<<std::endl;
|
||||
return cfg_;//@todo 1.7 add a proper serialization
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
#include "../composite/contexts.hpp"
|
||||
#include "../default/ai.hpp"
|
||||
#include "../../formula.hpp"
|
||||
#include "../../formula_fwd.hpp"
|
||||
#include "../../formula_callable.hpp"
|
||||
|
||||
|
||||
|
@ -60,15 +60,12 @@ class formula_ai : public readonly_context_proxy, public game_logic::formula_cal
|
|||
public:
|
||||
explicit formula_ai(readonly_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;
|
||||
|
||||
const move_map& srcdst() const { if(!move_maps_valid_) { prepare_move(); } return srcdst_; }
|
||||
|
||||
std::string evaluate(const std::string& formula_str);
|
||||
|
||||
virtual void add_formula_function(const std::string& name, game_logic::const_formula_ptr formula, game_logic::const_formula_ptr precondition, const std::vector<std::string>& args);
|
||||
|
||||
//class responsible for looking for possible infinite loops when calling set_var or set_unit_var
|
||||
class gamestate_change_observer : public events::observer
|
||||
{
|
||||
|
@ -104,8 +101,6 @@ public:
|
|||
// Check if given unit can reach another unit
|
||||
bool can_reach_unit(map_location unit_A, map_location unit_B) const;
|
||||
|
||||
const std::map<map_location,paths>& get_possible_moves() const { prepare_move(); return possible_moves_; }
|
||||
|
||||
void handle_exception(game_logic::formula_error& e) const;
|
||||
void handle_exception(game_logic::formula_error& e, const std::string& failed_operation) const;
|
||||
|
||||
|
@ -137,34 +132,29 @@ public:
|
|||
bool execute_candidate_action(game_logic::candidate_action_ptr fai_ca);
|
||||
|
||||
void set_ai_context(ai_context *context);
|
||||
|
||||
variant make_action(game_logic::const_formula_ptr formula_, const game_logic::formula_callable& variables);
|
||||
|
||||
private:
|
||||
ai_context *ai_ptr_;
|
||||
const config &cfg_;
|
||||
const config cfg_;
|
||||
recursion_counter recursion_counter_;
|
||||
void display_message(const std::string& msg) const;
|
||||
bool do_recruitment();
|
||||
variant make_action(game_logic::const_formula_ptr formula_, const game_logic::formula_callable& variables);
|
||||
variant execute_variant(const variant& var, ai_context &ai_, bool commandline=false);
|
||||
virtual variant get_value(const std::string& key) const;
|
||||
virtual void get_inputs(std::vector<game_logic::formula_input>* inputs) const;
|
||||
game_logic::const_formula_ptr recruit_formula_;
|
||||
game_logic::const_formula_ptr move_formula_;
|
||||
|
||||
std::vector<variant> outcome_positions_;
|
||||
|
||||
mutable std::map<map_location,paths> possible_moves_;
|
||||
|
||||
void prepare_move() const;
|
||||
|
||||
map_location path_calculator(const map_location& src, const map_location& dst, unit_map::iterator& unit_it) const;
|
||||
mutable bool move_maps_valid_;
|
||||
mutable move_map srcdst_, dstsrc_, full_srcdst_, full_dstsrc_, enemy_srcdst_, enemy_dstsrc_;
|
||||
mutable variant attacks_cache_;
|
||||
mutable variant keeps_cache_;
|
||||
|
||||
gamestate_change_observer infinite_loop_guardian_;
|
||||
game_logic::map_formula_callable vars_;
|
||||
game_logic::ai_function_symbol_table function_table;
|
||||
game_logic::ai_function_symbol_table function_table_;
|
||||
game_logic::candidate_action_manager candidate_action_manager_;
|
||||
|
||||
friend class ai_default;
|
||||
|
|
|
@ -24,6 +24,12 @@
|
|||
#include "../../formula_fwd.hpp"
|
||||
#include "../../formula_function.hpp"
|
||||
|
||||
namespace ai {
|
||||
|
||||
class formula_ai;
|
||||
|
||||
}
|
||||
|
||||
namespace game_logic {
|
||||
|
||||
class base_candidate_action;
|
||||
|
|
|
@ -947,7 +947,7 @@ private:
|
|||
}
|
||||
|
||||
const map_location& loc = convert_variant<location_callable>(res)->loc();
|
||||
const ai::move_map& srcdst = ai_.srcdst();
|
||||
const ai::move_map& srcdst = ai_.get_srcdst();
|
||||
typedef ai::move_map::const_iterator Itor;
|
||||
std::pair<Itor,Itor> range = srcdst.equal_range(loc);
|
||||
|
||||
|
|
90
src/ai/formula/stage_rca_formulas.cpp
Normal file
90
src/ai/formula/stage_rca_formulas.cpp
Normal file
|
@ -0,0 +1,90 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2009 by Yurii Chernyi <terraninfo@terraninfo.net>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
or at your option any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ai/formula/stage_rca_formulas.cpp
|
||||
* Defines formula ai rca formulas stage
|
||||
* */
|
||||
|
||||
|
||||
#include "stage_rca_formulas.hpp"
|
||||
#include "ai.hpp"
|
||||
|
||||
#include "../../formula.hpp"
|
||||
#include "../../formula_function.hpp"
|
||||
#include "../../log.hpp"
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
static lg::log_domain log_ai("ai/stage/rca_formulas");
|
||||
#define LOG_AI LOG_STREAM(info, log_ai)
|
||||
#define WRN_AI LOG_STREAM(warn, log_ai)
|
||||
#define ERR_AI LOG_STREAM(err, log_ai)
|
||||
|
||||
namespace ai {
|
||||
|
||||
stage_rca_formulas::stage_rca_formulas(ai_context &context, const config &cfg, formula_ai &fai)
|
||||
: stage(context,cfg), cfg_(cfg), fai_(fai)
|
||||
{
|
||||
/* try {
|
||||
if( candidate_action_manager_.has_candidate_actions() ) {
|
||||
|
||||
while( candidate_action_manager_.evaluate_candidate_actions(&fai_, get_info().units) )
|
||||
{
|
||||
game_logic::map_formula_callable callable(&fai_);
|
||||
callable.add_ref();
|
||||
|
||||
candidate_action_manager_.update_callable_map( callable );
|
||||
|
||||
game_logic::const_formula_ptr move_formula(candidate_action_manager_.get_best_action_formula());
|
||||
|
||||
fai_.make_action(move_formula, callable);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(game_logic::formula_error& e) {
|
||||
if(e.filename == "formula") {
|
||||
e.line = 0;
|
||||
}
|
||||
fai_.handle_exception( e, "Formula error in RCA loop");
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
stage_rca_formulas::~stage_rca_formulas()
|
||||
{
|
||||
}
|
||||
|
||||
void stage_rca_formulas::do_play_stage()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void stage_rca_formulas::on_create()
|
||||
{
|
||||
//@todo parse the formulas
|
||||
//candidate_action_manager_.load_config(ai_param, this, &function_table);
|
||||
}
|
||||
|
||||
|
||||
config stage_rca_formulas::to_config() const
|
||||
{
|
||||
config cfg = stage::to_config();
|
||||
//@todo: serialize to config
|
||||
cfg.append(cfg_);
|
||||
return cfg;
|
||||
}
|
||||
|
||||
} // end of namespace ai
|
63
src/ai/formula/stage_rca_formulas.hpp
Normal file
63
src/ai/formula/stage_rca_formulas.hpp
Normal file
|
@ -0,0 +1,63 @@
|
|||
/* $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/formula/stage_rca_formulas.hpp
|
||||
* Stage which executes rca formulas
|
||||
* */
|
||||
|
||||
|
||||
#ifndef AI_FORMULA_STAGE_RCA_FORMULAS_HPP_INCLUDED
|
||||
#define AI_FORMULA_STAGE_RCA_FORMULAS_HPP_INCLUDED
|
||||
|
||||
#include "../composite/stage.hpp"
|
||||
#include "candidates.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
//silence "inherits via dominance" warnings
|
||||
#pragma warning(disable:4250)
|
||||
#endif
|
||||
|
||||
|
||||
namespace ai {
|
||||
|
||||
class formula_ai;
|
||||
|
||||
class stage_rca_formulas: public stage {
|
||||
public:
|
||||
stage_rca_formulas( ai_context &context, const config &cfg, formula_ai &fai );
|
||||
|
||||
virtual ~stage_rca_formulas();
|
||||
|
||||
void do_play_stage();
|
||||
|
||||
void on_create();
|
||||
|
||||
config to_config() const;
|
||||
|
||||
private:
|
||||
const config &cfg_;
|
||||
formula_ai &fai_;
|
||||
game_logic::candidate_action_manager candidate_action_manager_;
|
||||
|
||||
};
|
||||
|
||||
} //end of namespace ai
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
78
src/ai/formula/stage_side_formulas.cpp
Normal file
78
src/ai/formula/stage_side_formulas.cpp
Normal file
|
@ -0,0 +1,78 @@
|
|||
/* $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/formula/stage_stage_formulas.cpp
|
||||
* Defines formula ai side formulas stage
|
||||
* */
|
||||
|
||||
|
||||
#include "stage_side_formulas.hpp"
|
||||
#include "ai.hpp"
|
||||
|
||||
#include "../../foreach.hpp"
|
||||
#include "../../formula.hpp"
|
||||
#include "../../formula_function.hpp"
|
||||
#include "../../log.hpp"
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
static lg::log_domain log_ai("ai/stage/side_formulas");
|
||||
#define LOG_AI LOG_STREAM(info, log_ai)
|
||||
#define WRN_AI LOG_STREAM(warn, log_ai)
|
||||
#define ERR_AI LOG_STREAM(err, log_ai)
|
||||
|
||||
namespace ai {
|
||||
|
||||
stage_side_formulas::stage_side_formulas(ai_context &context, const config &cfg, formula_ai &fai)
|
||||
: stage(context,cfg), cfg_(cfg), fai_(fai), move_formula_()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
stage_side_formulas::~stage_side_formulas()
|
||||
{
|
||||
}
|
||||
|
||||
void stage_side_formulas::do_play_stage()
|
||||
{
|
||||
game_logic::map_formula_callable callable(&fai_);
|
||||
callable.add_ref();
|
||||
try {
|
||||
while( !fai_.make_action(move_formula_,callable).is_empty() ) { }
|
||||
}
|
||||
catch(game_logic::formula_error& e) {
|
||||
if(e.filename == "formula") {
|
||||
e.line = 0;
|
||||
}
|
||||
fai_.handle_exception( e, "Formula error");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void stage_side_formulas::on_create()
|
||||
{
|
||||
move_formula_ = fai_.create_optional_formula(cfg_["move"]);
|
||||
}
|
||||
|
||||
|
||||
config stage_side_formulas::to_config() const
|
||||
{
|
||||
config cfg = stage::to_config();
|
||||
//@todo: serialize to config
|
||||
cfg.append(cfg_);
|
||||
return cfg;
|
||||
}
|
||||
|
||||
} // end of namespace ai
|
62
src/ai/formula/stage_side_formulas.hpp
Normal file
62
src/ai/formula/stage_side_formulas.hpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
/* $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/formula/stage_side_formulas.hpp
|
||||
* Stage which executes side formulas
|
||||
* */
|
||||
|
||||
|
||||
#ifndef AI_FORMULA_STAGE_SIDE_FORMULAS_HPP_INCLUDED
|
||||
#define AI_FORMULA_STAGE_SIDE_FORMULAS_HPP_INCLUDED
|
||||
|
||||
#include "../composite/stage.hpp"
|
||||
#include "../../formula_fwd.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
//silence "inherits via dominance" warnings
|
||||
#pragma warning(disable:4250)
|
||||
#endif
|
||||
|
||||
namespace ai {
|
||||
|
||||
class formula_ai;
|
||||
|
||||
class stage_side_formulas: public stage {
|
||||
public:
|
||||
stage_side_formulas( ai_context &context, const config &cfg, formula_ai &fai );
|
||||
|
||||
virtual ~stage_side_formulas();
|
||||
|
||||
void do_play_stage();
|
||||
|
||||
void on_create();
|
||||
|
||||
config to_config() const;
|
||||
|
||||
private:
|
||||
const config &cfg_;
|
||||
formula_ai &fai_;
|
||||
game_logic::const_formula_ptr move_formula_;
|
||||
|
||||
};
|
||||
|
||||
} //end of namespace ai
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
142
src/ai/formula/stage_unit_formulas.cpp
Normal file
142
src/ai/formula/stage_unit_formulas.cpp
Normal file
|
@ -0,0 +1,142 @@
|
|||
/* $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/formula/stage_unit_formulas.cpp
|
||||
* Defines formula ai unit formulas stage
|
||||
* */
|
||||
|
||||
|
||||
#include "stage_unit_formulas.hpp"
|
||||
#include "ai.hpp"
|
||||
|
||||
#include "../../formula.hpp"
|
||||
#include "../../formula_function.hpp"
|
||||
#include "../../log.hpp"
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
static lg::log_domain log_formula_ai("ai/stage/unit_formulas");
|
||||
#define LOG_AI LOG_STREAM(info, log_formula_ai)
|
||||
#define WRN_AI LOG_STREAM(warn, log_formula_ai)
|
||||
#define ERR_AI LOG_STREAM(err, log_formula_ai)
|
||||
|
||||
namespace ai {
|
||||
|
||||
stage_unit_formulas::stage_unit_formulas(ai_context &context, const config &cfg, formula_ai &fai)
|
||||
: stage(context,cfg), cfg_(cfg), fai_(fai)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
stage_unit_formulas::~stage_unit_formulas()
|
||||
{
|
||||
}
|
||||
|
||||
void stage_unit_formulas::do_play_stage()
|
||||
{
|
||||
//execute units formulas first
|
||||
game_logic::unit_formula_set units_with_formulas;
|
||||
|
||||
unit_map &units_ = get_info().units;
|
||||
|
||||
for(unit_map::unit_iterator i = units_.begin() ; i != units_.end() ; ++i)
|
||||
{
|
||||
if ( (i->second.side() == get_side()) ) {
|
||||
if ( i->second.has_formula() || i->second.has_loop_formula()) {
|
||||
int priority = 0;
|
||||
if( i->second.has_priority_formula() ) {
|
||||
try {
|
||||
game_logic::const_formula_ptr priority_formula(fai_.create_optional_formula(i->second.get_priority_formula()));
|
||||
game_logic::map_formula_callable callable(&fai_);
|
||||
callable.add_ref();
|
||||
callable.add("me", variant(new unit_callable(*i)));
|
||||
priority = (game_logic::formula::evaluate(priority_formula, callable)).as_int();
|
||||
} catch(game_logic::formula_error& e) {
|
||||
if(e.filename == "formula")
|
||||
e.line = 0;
|
||||
fai_.handle_exception( e, "Unit priority formula error for unit: '" + i->second.type_id() + "' standing at (" + boost::lexical_cast<std::string>(i->first.x+1) + "," + boost::lexical_cast<std::string>(i->first.y+1) + ")");
|
||||
|
||||
priority = 0;
|
||||
} catch(type_error& e) {
|
||||
priority = 0;
|
||||
ERR_AI << "formula type error while evaluating unit priority formula " << e.message << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
units_with_formulas.insert( game_logic::unit_formula_pair( i, priority ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(game_logic::unit_formula_set::iterator pair_it = units_with_formulas.begin() ; pair_it != units_with_formulas.end() ; ++pair_it)
|
||||
{
|
||||
unit_map::iterator i = pair_it->first;
|
||||
|
||||
if( i.valid() ) {
|
||||
|
||||
if ( i->second.has_formula() ) {
|
||||
try {
|
||||
game_logic::const_formula_ptr formula(fai_.create_optional_formula(i->second.get_formula()));
|
||||
game_logic::map_formula_callable callable(&fai_);
|
||||
callable.add_ref();
|
||||
callable.add("me", variant(new unit_callable(*i)));
|
||||
fai_.make_action(formula, callable);
|
||||
}
|
||||
catch(game_logic::formula_error& e) {
|
||||
if(e.filename == "formula") {
|
||||
e.line = 0;
|
||||
}
|
||||
fai_.handle_exception( e, "Unit formula error for unit: '" + i->second.type_id() + "' standing at (" + boost::lexical_cast<std::string>(i->first.x+1) + "," + boost::lexical_cast<std::string>(i->first.y+1) + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( i.valid() ) {
|
||||
if( i->second.has_loop_formula() )
|
||||
{
|
||||
try {
|
||||
game_logic::const_formula_ptr loop_formula(fai_.create_optional_formula(i->second.get_loop_formula()));
|
||||
game_logic::map_formula_callable callable(&fai_);
|
||||
callable.add_ref();
|
||||
callable.add("me", variant(new unit_callable(*i)));
|
||||
while ( !fai_.make_action(loop_formula, callable).is_empty() && i.valid() )
|
||||
{
|
||||
}
|
||||
} catch(game_logic::formula_error& e) {
|
||||
if (e.filename == "formula") {
|
||||
e.line = 0;
|
||||
}
|
||||
fai_.handle_exception( e, "Unit loop formula error for unit: '" + i->second.type_id() + "' standing at (" + boost::lexical_cast<std::string>(i->first.x+1) + "," + boost::lexical_cast<std::string>(i->first.y+1) + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void stage_unit_formulas::on_create()
|
||||
{
|
||||
//@todo parse the formulas
|
||||
}
|
||||
|
||||
|
||||
config stage_unit_formulas::to_config() const
|
||||
{
|
||||
config cfg = stage::to_config();
|
||||
//@todo: serialize to config
|
||||
return cfg;
|
||||
}
|
||||
|
||||
} // end of namespace ai
|
61
src/ai/formula/stage_unit_formulas.hpp
Normal file
61
src/ai/formula/stage_unit_formulas.hpp
Normal file
|
@ -0,0 +1,61 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2009 by Yurii Chernyi <terraninfo@terraninfo.net>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
or at your option any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ai/formula/stage_unit_formulas.hpp
|
||||
* Stage which executes unit formulas
|
||||
* */
|
||||
|
||||
|
||||
#ifndef AI_FORMULA_STAGE_UNIT_FORMULAS_HPP_INCLUDED
|
||||
#define AI_FORMULA_STAGE_UNIT_FORMULAS_HPP_INCLUDED
|
||||
|
||||
#include "../composite/stage.hpp"
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
//silence "inherits via dominance" warnings
|
||||
#pragma warning(disable:4250)
|
||||
#endif
|
||||
|
||||
namespace ai {
|
||||
|
||||
class formula_ai;
|
||||
|
||||
class stage_unit_formulas: public stage {
|
||||
public:
|
||||
stage_unit_formulas( ai_context &context, const config &cfg, formula_ai &fai );
|
||||
|
||||
virtual ~stage_unit_formulas();
|
||||
|
||||
void do_play_stage();
|
||||
|
||||
void on_create();
|
||||
|
||||
config to_config() const;
|
||||
|
||||
private:
|
||||
const config &cfg_;
|
||||
formula_ai &fai_;
|
||||
|
||||
};
|
||||
|
||||
} //end of namespace ai
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -40,10 +40,8 @@ fallback_to_other_ai::fallback_to_other_ai( ai_context &context, const config &c
|
|||
|
||||
void fallback_to_other_ai::on_create()
|
||||
{
|
||||
const config &ai_cfg = cfg_.child("ai");
|
||||
if (ai_cfg) {
|
||||
fallback_ai_ = manager::create_transient_ai(ai_cfg["ai_algorithm"], ai_cfg, this);
|
||||
}
|
||||
const config &ai_cfg = cfg_.child_or_empty("ai");
|
||||
fallback_ai_ = manager::create_transient_ai(ai_cfg["ai_algorithm"], ai_cfg, this);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue