Author: dhains
Date: Wed Jul 30 09:10:29 2008
New Revision: 28263
URL: http://svn.gna.org/viewcvs/wesnoth?rev=28263&view=rev
Log:
Formula AI can now make moves based on eval/move list.
Changes to class formula_ai:
*Added build_move_list function to formula_ai to create eval/move list with
eval scores.
*Added make_candidate_move function to take best move found.
Various changes made to the candidate_move class to allow this functionality.
Modified:
trunk/data/scenario-formula.cfg
trunk/src/formula_ai.cpp
trunk/src/formula_ai.hpp
Modified: trunk/data/scenario-formula.cfg
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/data/scenario-formula.cfg?rev=28263&r1=28262&r2=28263&view=diff
==============================================================================
--- trunk/data/scenario-formula.cfg (original)
+++ trunk/data/scenario-formula.cfg Wed Jul 30 09:10:29 2008
@@ -80,29 +80,39 @@
x,y=6,20
type="Ghost"
generate_description=yes
-
formula="if(size(filter(unit_moves(me.loc),units_can_reach(enemy_moves, self)))
!= 0, fallback('default'), if(size(villages) != 0, move(me.loc,
nearest_loc(nearest_loc(me.loc,villages),unit_moves(me.loc))), if(size(shroud)
= 0, fallback('default'), move(me.loc,
nearest_loc(nearest_loc(me.loc,shroud),unit_moves(me.loc))))))
- where villages =
filter(unit_moves(me.loc),is_unowned_village(map,x,y)),
- shroud = find_shroud()"
+ #
formula="if(size(filter(unit_moves(me.loc),units_can_reach(enemy_moves, self)))
!= 0, fallback('default'), if(size(villages) != 0, move(me.loc,
nearest_loc(nearest_loc(me.loc,villages),unit_moves(me.loc))), if(size(shroud)
= 0, fallback('default'), move(me.loc,
nearest_loc(nearest_loc(me.loc,shroud),unit_moves(me.loc))))))
+ # where villages =
filter(unit_moves(me.loc),is_unowned_village(map,x,y)),
+ # shroud = find_shroud()"
[/unit]
[unit]
x,y=15,22
type="Ghost"
generate_description=yes
-
formula="if(size(filter(unit_moves(me.loc),units_can_reach(enemy_moves, self)))
!= 0, fallback('default'), if(size(villages) != 0, move(me.loc,
nearest_loc(nearest_loc(me.loc,villages),unit_moves(me.loc))), if(size(shroud)
= 0, fallback('default'), move(me.loc,
nearest_loc(nearest_loc(me.loc,shroud),unit_moves(me.loc))))))
- where villages =
filter(unit_moves(me.loc),is_unowned_village(map,x,y)),
- shroud = find_shroud()"
+ #
formula="if(size(filter(unit_moves(me.loc),units_can_reach(enemy_moves, self)))
!= 0, fallback('default'), if(size(villages) != 0, move(me.loc,
nearest_loc(nearest_loc(me.loc,villages),unit_moves(me.loc))), if(size(shroud)
= 0, fallback('default'), move(me.loc,
nearest_loc(nearest_loc(me.loc,shroud),unit_moves(me.loc))))))
+ # where villages =
filter(unit_moves(me.loc),is_unowned_village(map,x,y)),
+ # shroud = find_shroud()"
[/unit]
[unit]
x,y=12,19
type="Ghost"
generate_description=yes
-
formula="if(size(filter(unit_moves(me.loc),units_can_reach(enemy_moves, self)))
!= 0, fallback('default'), if(size(villages) != 0, move(me.loc,
nearest_loc(nearest_loc(me.loc,villages),unit_moves(me.loc))), if(size(shroud)
= 0, fallback('default'), move(me.loc,
nearest_loc(nearest_loc(me.loc,shroud),unit_moves(me.loc))))))
- where villages =
filter(unit_moves(me.loc),is_unowned_village(map,x,y)),
- shroud = find_shroud()"
+ #
formula="if(size(filter(unit_moves(me.loc),units_can_reach(enemy_moves, self)))
!= 0, fallback('default'), if(size(villages) != 0, move(me.loc,
nearest_loc(nearest_loc(me.loc,villages),unit_moves(me.loc))), if(size(shroud)
= 0, fallback('default'), move(me.loc,
nearest_loc(nearest_loc(me.loc,shroud),unit_moves(me.loc))))))
+ # where villages =
filter(unit_moves(me.loc),is_unowned_village(map,x,y)),
+ # shroud = find_shroud()"
[/unit]
ai_algorithm=formula_ai
[ai]
+ eval_list=yes
+ [register_candidate_move]
+ name=test
+ type=test
+
action="if(size(filter(unit_moves(me.loc),units_can_reach(enemy_moves, self)))
!= 0, fallback('default'), if(size(villages) != 0, move(me.loc,
nearest_loc(nearest_loc(me.loc,villages),unit_moves(me.loc))), if(size(shroud)
= 0, fallback('default'), move(me.loc,
nearest_loc(nearest_loc(me.loc,shroud),unit_moves(me.loc))))))
+ where villages =
filter(unit_moves(me.loc),is_unowned_village(map,x,y)),
+ shroud = find_shroud()"
+ evaluation="if(me.id='Ghost', 100, -5)"
+ [/register_candidate_move]
+
[team_formula]
rulebase="{opening.fai}"
[/team_formula]
Modified: trunk/src/formula_ai.cpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/formula_ai.cpp?rev=28263&r1=28262&r2=28263&view=diff
==============================================================================
--- trunk/src/formula_ai.cpp (original)
+++ trunk/src/formula_ai.cpp Wed Jul 30 09:10:29 2008
@@ -1121,7 +1121,7 @@
const_formula_ptr formula, const_formula_ptr eval,
const_formula_ptr precondition, const std::vector<std::string>&
args)
{
- candidate_move_ptr new_move(new candidate_move(name,eval));
+ candidate_move_ptr new_move(new candidate_move(name,eval,formula));
candidate_moves.push_back(new_move);
function_symbol_table::add_formula_function(name, formula,
precondition, args);
@@ -1145,11 +1145,18 @@
attacks_cache_(),
keeps_cache_(),
vars_(),
- function_table(*this)
+ function_table(*this),
+ candidate_moves_(),
+ use_eval_lists_(false)
{
//make sure we don't run out of refcount
vars_.add_ref();
const config& ai_param = current_team().ai_parameters();
+
+ // Check to see if we want to use eval_lists
+ if(ai_param.get_attribute("eval_list") == "yes") {
+ use_eval_lists_ = true;
+ }
// Register candidate moves in function symbol table
config::const_child_itors rc_moves =
@@ -1214,9 +1221,57 @@
}
}
- game_logic::map_formula_callable callable(this);
- callable.add_ref();
- while(make_move(move_formula_,callable)) {
+ if(use_eval_lists_) {
+ make_candidate_moves();
+ } else {
+ game_logic::map_formula_callable callable(this);
+ callable.add_ref();
+ while(make_move(move_formula_,callable)) {
+ }
+ }
+}
+
+void formula_ai::make_candidate_moves() {
+
+ build_move_list();
+ candidate_move_set::iterator best_move = candidate_moves_.begin();
+
+ while( best_move != candidate_moves_.end() ) {
+ int best_score = (*best_move)->get_score();
+ std::cout << "size of set is " << candidate_moves_.size() <<
std::endl;
+ std::cout << "best score is " << best_score << std::endl;
+ // If no evals > 0, fallback
+ if(best_score < 0) {
+ ai_interface* fallback = create_ai("", get_info());
+ fallback->play_turn();
+ return;
+ }
+ // Otherwise, make the best scoring move
+ game_logic::map_formula_callable callable(this);
+ callable.add_ref();
+ variant action_unit_callable(new
unit_callable(*(*best_move)->get_action_unit()));
+ callable.add("me", action_unit_callable);
+ const_formula_ptr move_formula((*best_move)->get_move());
+ make_move(move_formula, callable);
+ // And re-evaluate candidate moves
+ build_move_list();
+ best_move = candidate_moves_.begin();
+ }
+
+ // After all candidate moves have been exhausted, fallback
+ ai_interface* fallback = create_ai("", get_info());
+ fallback->play_turn();
+
+}
+
+
+void formula_ai::build_move_list() {
+ std::cout << "BUILDING MOVE LIST" << std::endl;
+ candidate_moves_.clear();
+ std::vector<candidate_move_ptr>::iterator itor =
function_table.candidate_move_begin();
+ for( ; itor != function_table.candidate_move_end(); ++itor) {
+ (*itor)->evaluate_move(this, units_, get_info().team_num);
+ candidate_moves_.insert(*itor);
}
}
@@ -1277,6 +1332,7 @@
bool formula_ai::make_move(game_logic::const_formula_ptr formula_, const
game_logic::formula_callable& variables)
{
+ std::cout << "Makin move yo" << std::endl;
if(!formula_) {
ai_interface* fallback = create_ai("", get_info());
fallback->play_turn();
Modified: trunk/src/formula_ai.hpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/formula_ai.hpp?rev=28263&r1=28262&r2=28263&view=diff
==============================================================================
--- trunk/src/formula_ai.hpp (original)
+++ trunk/src/formula_ai.hpp Wed Jul 30 09:10:29 2008
@@ -30,50 +30,56 @@
class candidate_move {
public:
- candidate_move(std::string name, const_formula_ptr eval) :
+ candidate_move(std::string name, const_formula_ptr eval,
const_formula_ptr move) :
name_(name),
eval_(eval),
+ move_(move),
score_(-1),
action_unit_()
{};
void evaluate_move(const formula_callable* ai, unit_map& units, int
team_num) {
-
+ score_ = -1000;
for(unit_map::unit_iterator i = units.begin() ; i !=
units.end() ; ++i)
{
- if(i->second.side() == team_num) {
+ if( (i->second.side() == team_num) &&
+ (i->second.has_moved() == false) ) {
game_logic::map_formula_callable callable(ai);
callable.add_ref();
callable.add("me", variant(new
unit_callable(*i)));
int res = (formula::evaluate(eval_,
callable)).as_int();
if(res > score_) {
score_ = res;
- action_unit_.reset(&i->second);
+ action_unit_ = i;
}
}
}
-
}
int get_score() const {return score_;}
+ unit_map::unit_iterator get_action_unit() {return action_unit_;}
+ const_formula_ptr get_move() {return move_;}
struct move_compare {
- bool operator() (const candidate_move& lmove,
- const candidate_move& rmove) const
+ bool operator() (const boost::shared_ptr<candidate_move> lmove,
+ const boost::shared_ptr<candidate_move> rmove)
const
{
- return lmove.get_score() < rmove.get_score();
+ return lmove->get_score() < rmove->get_score();
}
};
private:
+
std::string name_;
const_formula_ptr eval_;
+ const_formula_ptr move_;
int score_;
- boost::shared_ptr<unit> action_unit_;
+ unit_map::unit_iterator action_unit_;
};
typedef boost::shared_ptr<candidate_move> candidate_move_ptr;
+typedef std::set<game_logic::candidate_move_ptr,
game_logic::candidate_move::move_compare> candidate_move_set;
class ai_function_symbol_table : public function_symbol_table {
@@ -88,8 +94,12 @@
const_formula_ptr formula, const_formula_ptr eval,
const_formula_ptr precondition, const
std::vector<std::string>& args);
- std::vector<candidate_move_ptr>::iterator get_candidate_move_itor() {
+ std::vector<candidate_move_ptr>::iterator candidate_move_begin() {
return candidate_moves.begin();
+ }
+
+ std::vector<candidate_move_ptr>::iterator candidate_move_end() {
+ return candidate_moves.end();
}
private:
@@ -156,6 +166,8 @@
mutable std::map<location,paths> possible_moves_;
void prepare_move() const;
+ void build_move_list();
+ void make_candidate_moves();
mutable bool move_maps_valid_;
mutable move_map srcdst_, dstsrc_, full_srcdst_, full_dstsrc_,
enemy_srcdst_, enemy_dstsrc_;
mutable variant attacks_cache_;
@@ -164,7 +176,8 @@
game_logic::map_formula_callable vars_;
game_logic::ai_function_symbol_table function_table;
- std::set<game_logic::candidate_move,
game_logic::candidate_move::move_compare> candidate_moves;
+ game_logic::candidate_move_set candidate_moves_;
+ bool use_eval_lists_;
};
#endif
_______________________________________________
Wesnoth-commits mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-commits