Adding new files concerning new AI...

...(ai/akihara/recruitment.?pp) and new scenario for the ai_arena_small.
This commit is contained in:
Riss Aline 2012-07-13 08:38:01 +00:00
parent b40dc28d59
commit 104a28654d
10 changed files with 385 additions and 1 deletions

View file

@ -18,6 +18,8 @@ Version 1.11.0-svn:
markup character (any of *, `, ~, {, ^, }, |, @, #, <, &)
* AI:
* AI now properly considers the expected damage from poison when attacking using poisoners.
* Adding a new scenario for the ai-arena-small in order to test the new AI.
* Adding new files for the new AI (ai/akihara/recruitment.?pp)
* Campaigns:
* Added a note to all final scenarios, stating which one is the last scenario
* Dead Water:

View file

@ -0,0 +1,27 @@
#textdomain wesnoth
{core/macros}
[ai]
id=ai_akihara
description="Experimental Recruitment AI"
version=10800
[stage]
id=main_loop
name=testing_ai_default::candidate_action_evaluation_loop
{AI_CA_GOTO}
[candidate_action]
id=alternate_recruitment
engine=cpp
name=akihara_recruitment::recruitment
max_score={AI_CA_RECRUITMENT_SCORE}
score={AI_CA_RECRUITMENT_SCORE}
[/candidate_action]
{AI_CA_MOVE_LEADER_TO_GOALS}
{AI_CA_MOVE_LEADER_TO_KEEP}
{AI_CA_COMBAT}
{AI_CA_HEALING}
{AI_CA_VILLAGES}
{AI_CA_RETREAT}
{AI_CA_MOVE_TO_TARGETS}
[/stage]
[/ai]

View file

@ -0,0 +1,31 @@
#textdomain wesnoth
[event]
name=preload
first_time_only=no
[lua]
code = << register_test('0005-recruitment_test','Recruitment test'); >>
[/lua]
[/event]
[event]
name=0005-recruitment_test
first_time_only=no
[message]
speaker=narrator
image=wesnoth-icon.png
message= "This situation should test the recruitment phase"
[/message]
[move_unit]
name="Challenger AI"
to_x,to_y=15,2
[/move_unit]
[move_unit]
name="Champion AI"
to_x,to_y=15,24
[/move_unit]
[modify_side]
side=2
switch_ai=$test_path_to_akihara_recruitment
[/modify_side]
[/event]

View file

@ -51,9 +51,13 @@
name=test_path_to_testing_ai_default
value=ai/dev/testing_ai_default.cfg
[/set_variable]
[set_variable]
name=test_path_to_akihara_recruitment
value=ai/dev/akihara_recruitment.cfg
[/set_variable]
[set_variable]
name=test_id
value=0002-poisoning
value=0005-recruitment_test
[/set_variable]
[set_menu_item]
@ -119,6 +123,7 @@
team_name=north
user_team_name= "North"
fog=yes
recruit="Dwarvish Guardsman,Dwarvish Fighter,Dwarvish Thunderer,Thief,Poacher,Footpad"
[/side]
[side]
side=3
@ -129,6 +134,7 @@
team_name=south
user_team_name= "South"
fog=yes
recruit="Dwarvish Guardsman,Dwarvish Fighter,Dwarvish Thunderer,Thief,Poacher,Footpad"
[/side]
[event]
@ -169,6 +175,15 @@
[option]
message="I am happy with the current AI of team 2, [$test_path_to_ai]"
[/option]
[option]
message="Akihara's ai will be awesome, won't it?"
[command]
[set_variable]
name=test_path_to_ai
value=$test_path_to_akihara_recruitment
[/set_variable]
[/command]
[/option]
[option]
message="My AI is TESTING AI DEFAULT, implemented as ai_composite."
[command]

View file

@ -3,6 +3,7 @@ src/actions.cpp
src/addon/manager.cpp
src/addon/validation.cpp
src/ai/actions.cpp
src/ai/akihara/recruitment.cpp
src/ai/composite/ai.cpp
src/ai/composite/aspect.cpp
src/ai/composite/component.cpp

View file

@ -590,6 +590,7 @@ set(wesnoth-main_SRC
addon/state.cpp
addon/validation.cpp
ai/actions.cpp
ai/akihara/recruitment.cpp
ai/composite/ai.cpp
ai/composite/aspect.cpp
ai/composite/component.cpp

View file

@ -170,6 +170,7 @@ wesnoth_sources = Split("""
addon/state.cpp
addon/validation.cpp
ai/actions.cpp
ai/akihara/recruitment.cpp
ai/composite/ai.cpp
ai/composite/aspect.cpp
ai/composite/component.cpp

View file

@ -0,0 +1,203 @@
/*
Copyright (C) 2009 - 2012 by Aline Riss <aline.riss@gmail.com>
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 as published by
the Free Software Foundation; either version 2 of the License, 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
* Experimental recruitment phase
*/
#include "recruitment.hpp"
#include <boost/foreach.hpp>
#include "../composite/rca.hpp"
#include "../../resources.hpp"
#include "../../unit_map.hpp"
#include "../../map.hpp"
#include "../../team.hpp"
#include "../../unit_display.hpp"
#include "../../unit_types.hpp"
#include "../../log.hpp"
static lg::log_domain log_ai_aki("ai/aki");
#define DBG_AI_AKI LOG_STREAM(debug, log_ai_aki)
#define LOG_AI_AKI LOG_STREAM(info, log_ai_aki)
#define WRN_AI_AKI LOG_STREAM(warn, log_ai_aki)
#define ERR_AI_AKI LOG_STREAM(err, log_ai_aki)
#include <map>
#ifdef _MSC_VER
#pragma warning(push)
//silence "inherits via dominance" warnings
#pragma warning(disable:4250)
#endif
namespace ai {
namespace akihara_recruitment {
recruitment::recruitment(rca_context &context, const config &cfg)
: candidate_action(context,cfg),
depth_(2)
{
BOOST_FOREACH( team &t, *resources::teams) {
if (current_team().is_enemy(t.side()))
enemy_.push_back(t);
else if (!current_team().is_enemy(t.side()))
ally_.push_back(t);
}
}
recruitment::~recruitment()
{
}
double recruitment::evaluate()
{
std::vector<unit_map::unit_iterator> leaders = resources::units->find_leaders(get_side());
BOOST_FOREACH(unit_map::unit_iterator &leader, leaders){
if (leader == resources::units->end()) {
return BAD_SCORE;
}
std::set<map_location> checked_hexes;
const map_location &keep = leader->get_location();
checked_hexes.insert(keep);
if (resources::game_map->is_keep(leader->get_location()) && count_free_hexes_in_castle(leader->get_location(), checked_hexes) != 0) {
return get_score();
}
}
return BAD_SCORE;
}
struct situation recruitment::get_next_stage(std::string unit, situation current) {
situation new_situation;
new_situation.ally_new_unit = current.ally_new_unit;
new_situation.enemy_new_unit = current.enemy_new_unit;
if (current.current_team_side == current_team().side()) {
new_situation.new_unit = unit;
} else {
new_situation.new_unit = current.new_unit;
new_situation.enemy_new_unit.insert(unit);
}
new_situation.current_team_side = get_next_team(current.current_team_side);
if (new_situation.current_team_side == -1) {
LOG_AI_AKI << "Error: get_mext_team";
exit(0);
}
if (current_team().is_enemy(new_situation.current_team_side) && new_situation.current_team_side != enemy_[0].side())
new_situation.depth = current.depth;
else
new_situation.depth = current.depth - 1;
return new_situation;
}
int recruitment::get_next_team(int current_side) {
if (current_team().side() == current_side)
return enemy_[0].side();
unsigned i;
for(i = 0; i < enemy_.size()-1; i++) {
if (enemy_[i].side() == current_side)
return enemy_[i+1].side();
}
if (enemy_[enemy_.size()-1].side() == current_side)
return current_team().side();
return -1;
}
struct situation recruitment::do_min_max(situation current) {
LOG_AI_AKI << "\nDepth : " << current.depth << "; Side : " << current.current_team_side << "\n";
if (current.depth == 0) {
LOG_AI_AKI << "On evalue " << current.new_unit << "\n";
current.score = evaluate_unit(current);
return current;
}
situation best_situation;
best_situation = do_min_max(get_next_stage("", current));
std::set<std::string> list = get_current_team_recruit(current.current_team_side).recruits();
BOOST_FOREACH(std::string unit, list) {
situation new_situation;
new_situation = do_min_max(get_next_stage(unit, current));
if (new_situation.score > best_situation.score)
best_situation = new_situation;
}
return best_situation;
}
team recruitment::get_current_team_recruit(int side) {
BOOST_FOREACH( team &t, *resources::teams) {
if (t.side() == side)
return t;
}
return current_team();
}
double recruitment::evaluate_unit(situation current) {
LOG_AI_AKI << "EVALUATION! unit: " << current.new_unit << "; enemies : \n";
BOOST_FOREACH(std::string s, current.enemy_new_unit) {
LOG_AI_AKI << s << "\n";
}
double score = 0;
LOG_AI_AKI << "score = " << score << "\n";
return score;
}
void recruitment::execute()
{
LOG_AI_AKI << "Akihara's recruitment begin! \n";
LOG_AI_AKI << "Init: Depth : " << depth_ << "; Side : " << current_team().side() << "\n";
struct situation current_situation;
current_situation.current_team_side = current_team().side();
current_situation.depth = depth_;
situation best_situation = do_min_max(current_situation);
LOG_AI_AKI << "Unit to recruit is.... " << best_situation.new_unit << "\n";
}
} //end of akihara_recruitment
} // end of namespace ai

View file

@ -0,0 +1,99 @@
/* $Id: ca_testing_recruitment.hpp 52533 2012-01-07 02:35:17 +0000 (Sat, 07 Jan 2012) shadowmaster $ */
/*
Copyright (C) 2009 - 2012 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 as published by
the Free Software Foundation; either version 2 of the License, 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
* Strategic recruitment routine, for experimentation
*/
#ifndef AKIHARA_AI_HPP_INCLUDED
#define AKIHARA_AI_HPP_INCLUDED
#include "../composite/rca.hpp"
#include "../../team.hpp"
#ifdef _MSC_VER
#pragma warning(push)
//silence "inherits via dominance" warnings
#pragma warning(disable:4250)
#endif
namespace ai {
namespace akihara_recruitment {
struct situation {
int depth;
//Score of the current situation;
double score;
//Current team to analyze
int current_team_side;
//New unit of AI
std::string new_unit;
//New unit of allies
std::set<std::string> ally_new_unit;
//New unit of enemies
std::set<std::string> enemy_new_unit;
};
class recruitment : public candidate_action {
public:
recruitment( rca_context &context , const config &cfg );
virtual ~recruitment();
virtual double evaluate();
virtual void execute();
void do_describe(struct situation);
private:
int depth_;
std::vector<team> ally_;
std::vector<team> enemy_;
void do_recruit(int max_units_to_recruit, double quality_factor);
struct situation get_next_stage(std::string unit, situation current);
double analyze_situation();
double evaluate_unit(situation current);
situation do_min_max(situation current);
int get_next_team(int current_side);
team get_current_team_recruit(int side);
};
} // of namespace testing_ai_default
} // of namespace ai
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#endif

View file

@ -34,6 +34,7 @@
#include "testing/ca_global_fallback.hpp"
#include "testing/stage_rca.hpp"
#include "testing/stage_fallback.hpp"
#include "akihara/recruitment.hpp"
namespace ai {
// =======================================================================
@ -127,6 +128,9 @@ static register_candidate_action_factory<testing_ai_default::passive_leader_shar
static register_candidate_action_factory<testing_ai_default::global_fallback_phase>
global_fallback_phase_factory("testing_ai_default::global_fallback_phase");
static register_candidate_action_factory<akihara_recruitment::recruitment>
recruitment_factory("akihara_recruitment::recruitment");
// =======================================================================
// Goals
// =======================================================================