AI Refactoring: new stub AI actions code.

This commit is contained in:
Iurii Chernyi 2009-04-13 01:28:30 +00:00
parent 3014f70d47
commit cef695a685
8 changed files with 519 additions and 7 deletions

View file

@ -290,6 +290,10 @@
RelativePath="..\..\src\ai_dfool.cpp"
>
</File>
<File
RelativePath="..\..\src\ai_interface.cpp"
>
</File>
<File
RelativePath="..\..\src\ai_manager.cpp"
>

View file

@ -207,9 +207,10 @@ SET(wesnoth-main_SRC
addon_management.cpp
ai.cpp
ai_actions.cpp
ai_dfool.cpp
ai_attack.cpp
ai_configuration.cpp
ai_interface.cpp
ai_dfool.cpp
ai_manager.cpp
ai_move.cpp
ai_village.cpp

View file

@ -47,6 +47,7 @@ wesnoth_source = \
ai_attack.cpp \
ai_configuration.cpp \
ai_dfool.cpp \
ai_interface.cpp \
ai_manager.cpp \
ai_move.cpp \
ai_village.cpp \

View file

@ -148,10 +148,11 @@ wesnoth_sources = Split("""
actions.cpp
addon_checks.cpp
addon_management.cpp
ai_dfool.cpp
ai_attack.cpp
ai_actions.cpp
ai_configuration.cpp
ai_dfool.cpp
ai_interface.cpp
ai_manager.cpp
ai_move.cpp
ai_village.cpp

View file

@ -18,6 +18,7 @@
*/
#include "ai_actions.hpp"
#include "log.hpp"
#define DBG_AI_ACTIONS LOG_STREAM(debug, ai_actions)
#define LOG_AI_ACTIONS LOG_STREAM(info, ai_actions)
@ -25,6 +26,231 @@
#define ERR_AI_ACTIONS LOG_STREAM(err, ai_actions)
// =======================================================================
//
// AI ACTIONS
// =======================================================================
ai_action_result::ai_action_result()
{
}
ai_action_result::~ai_action_result()
{
if (tried_ && !return_value_checked_) {
ERR_AI_ACTIONS << "Return value of AI ACTION was not checked. This may cause bugs!" << std::endl;
}
}
void ai_action_result::check_after()
{
do_check_after();
}
void ai_action_result::check_before()
{
init_for_check_before();
do_check_before();
}
void ai_action_result::execute()
{
check_before();
if (is_success()){
init_for_execution();
do_execute();
}
if (is_success()){
check_after();
}
}
void ai_action_result::init_for_check_before()
{
do_init_for_check_before();
}
void ai_action_result::init_for_execution()
{
tried_ = true;
return_value_checked_ = false;
status_ = ai_action_result::AI_ACTION_STARTED;
do_init_for_execution();
}
bool ai_action_result::is_ok()
{
return_value_checked_ = true;
return is_success();
}
bool ai_action_result::is_success()
{
return (status_ == ai_action_result::AI_ACTION_SUCCESS);
}
// ai_attack_result
void ai_attack_result::do_check_before()
{
}
void ai_attack_result::do_check_after()
{
}
void ai_attack_result::do_execute()
{
}
void ai_attack_result::do_init_for_check_before()
{
}
void ai_attack_result::do_init_for_execution()
{
}
// ai_move_result
void ai_move_result::do_check_before()
{
}
void ai_move_result::do_check_after()
{
}
void ai_move_result::do_execute()
{
}
void ai_move_result::do_init_for_check_before()
{
}
void ai_move_result::do_init_for_execution()
{
}
// ai_recruit_result
void ai_recruit_result::do_check_before()
{
}
void ai_recruit_result::do_check_after()
{
}
void ai_recruit_result::do_execute()
{
}
void ai_recruit_result::do_init_for_check_before()
{
}
void ai_recruit_result::do_init_for_execution()
{
}
// ai_stopunit_result
void ai_stopunit_result::do_check_before()
{
}
void ai_stopunit_result::do_check_after()
{
}
void ai_stopunit_result::do_execute()
{
}
void ai_stopunit_result::do_init_for_check_before()
{
}
void ai_stopunit_result::do_init_for_execution()
{
}
// =======================================================================
// STATELESS INTERFACE TO AI ACTIONS
// =======================================================================
std::auto_ptr< ai_attack_result > ai_actions::execute_attack_action( int side,
bool execute,
const map_location& attacker_loc,
const map_location& defender_loc,
int attacks )
{
std::auto_ptr< ai_attack_result > ai_action(new ai_attack_result());
execute ? ai_action->execute() : ai_action->check_before();
return ai_action;
}
std::auto_ptr< ai_move_result > ai_actions::execute_move_action( int side,
bool execute,
const map_location& from,
const map_location& to,
bool remove_movement )
{
std::auto_ptr< ai_move_result > ai_action(new ai_move_result());
execute ? ai_action->execute() : ai_action->check_before();
return ai_action;
}
std::auto_ptr< ai_recruit_result > ai_actions::execute_recruit_action( int side,
bool execute,
const std::string& unit_name,
const map_location& where )
{
std::auto_ptr< ai_recruit_result > ai_action(new ai_recruit_result());
execute ? ai_action->execute() : ai_action->check_before();
return ai_action;
}
std::auto_ptr< ai_stopunit_result > ai_actions::execute_stopunit_action( int side,
bool execute,
const map_location& unit_location,
bool remove_movement,
bool remove_attacks )
{
std::auto_ptr< ai_stopunit_result > ai_action(new ai_stopunit_result());
execute ? ai_action->execute() : ai_action->check_before();
return ai_action;
}

View file

@ -22,8 +22,153 @@
#include "global.hpp"
// =======================================================================
//
// =======================================================================
#include "map_location.hpp"
#include <memory>
class ai_action_result {
public:
static const int AI_ACTION_SUCCESS = 0;
static const int AI_ACTION_STARTED = 1;
ai_action_result();
virtual ~ai_action_result();
void check_before();
void execute();
bool is_ok();
protected:
virtual void do_check_before() = 0;
virtual void do_check_after() = 0;
virtual void do_execute() = 0;
virtual void do_init_for_check_before() = 0;
virtual void do_init_for_execution() = 0;
private:
void check_after();
void init_for_check_before();
void init_for_execution();
void set_ok_checked();
bool init_for_execution_and_check();
int status_;
bool is_success();
bool return_value_checked_;
bool tried_;
};
class ai_attack_result : public ai_action_result {
virtual void do_check_before();
virtual void do_check_after();
virtual void do_execute();
virtual void do_init_for_check_before();
virtual void do_init_for_execution();
};
class ai_move_result : public ai_action_result {
virtual void do_check_before();
virtual void do_check_after();
virtual void do_execute();
virtual void do_init_for_check_before();
virtual void do_init_for_execution();
};
class ai_recruit_result : public ai_action_result {
virtual void do_check_before();
virtual void do_check_after();
virtual void do_execute();
virtual void do_init_for_check_before();
virtual void do_init_for_execution();
};
class ai_stopunit_result : public ai_action_result {
virtual void do_check_before();
virtual void do_check_after();
virtual void do_execute();
virtual void do_init_for_check_before();
virtual void do_init_for_execution();
};
class ai_actions {
public:
// =======================================================================
// Stateless interface to actions
// =======================================================================
/**
* Ask the game to attack an enemy defender using our unit attacker from attackers current location,
* @param side the side which tries to execute the move
* @param execute should move be actually executed or not
* @param attacker_loc location of attacker
* @param defender_loc location of defender
* @param attacker_weapon weapon of attacker
* @retval possible result: ok
* @retval possible result: something wrong
* @retval possible result: attacker and/or defender are invalid
* @retval possible result: attacker doesn't have the specified weapon
*/
static std::auto_ptr<ai_attack_result> execute_attack_action( int side,
bool execute,
const map_location& attacker_loc,
const map_location& defender_loc,
int attacks );
/**
* Ask the game to move our unit from location 'from' to location 'to', optionally - doing a partial move
* @param side the side which tries to execute the move
* @param execute should move be actually executed or not
* @param from location of our unit
* @param to where to move
* @param remove_movement set unit movement to 0 in case of successful move
* @retval possible result: ok
* @retval possible result: something wrong
* @retval possible result: move is interrupted
* @retval possible result: move is impossible
*/
static std::auto_ptr<ai_move_result > execute_move_action( int side,
bool execute,
const map_location& from,
const map_location& to,
bool remove_movement );
/**
* Ask the game to recruit a unit for us on specified location
* @param side the side which tries to execute the move
* @param execute should move be actually executed or not
* @param unit_name the name of the unit to be recruited.
* @param where location where the unit is to be recruited.
* @retval possible result: ok
* @retval possible_result: something wrong
* @retval possible_result: leader not on keep
* @retval possible_result: no free space on keep
* @retval possible_result: not enough gold
*/
static std::auto_ptr<ai_recruit_result> execute_recruit_action( int side,
bool execute,
const std::string& unit_name,
const map_location& where );
/**
* Ask the game to remove unit movements and/or attack
* @param side the side which tries to execute the move
* @param execute should move be actually executed or not
* @param unit_location the location of our unit
* @param remove_movement set remaining movements to 0
* @param remove_attacks set remaining attacks to 0
* @retval possible result: ok
* @retval possible_result: something wrong
* @retval possible_result: nothing to do
*/
static std::auto_ptr<ai_stopunit_result> execute_stopunit_action( int side,
bool execute,
const map_location& unit_location,
bool remove_movement,
bool remove_attacks );
};
#endif

65
src/ai_interface.cpp Normal file
View file

@ -0,0 +1,65 @@
/* $Id: ai_interface.cpp $ */
/*
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.
*/
/**
* Base class for the AI and AI-ai_manager contract.
* @file ai_interface.cpp
*/
#include "ai_actions.hpp"
#include "ai_interface.hpp"
#define DBG_AI LOG_STREAM(debug, ai)
#define LOG_AI LOG_STREAM(info, ai)
#define WRN_AI LOG_STREAM(warn, ai)
#define ERR_AI LOG_STREAM(err, ai)
// =======================================================================
//
// =======================================================================
std::auto_ptr<ai_attack_result> ai_interface::execute_attack_action(const map_location& attacker_loc, const map_location& defender_loc, int attacker_weapon){
return ai_actions::execute_attack_action(get_side(),true,attacker_loc,defender_loc,attacker_weapon);
}
std::auto_ptr<ai_attack_result> ai_interface::check_attack_action(const map_location& attacker_loc, const map_location& defender_loc, int attacker_weapon){
return ai_actions::execute_attack_action(get_side(),false,attacker_loc,defender_loc,attacker_weapon);
}
std::auto_ptr<ai_move_result> ai_interface::execute_move_action(const map_location& from, const location& to, bool remove_movement){
return ai_actions::execute_move_action(get_side(),true,from,to,remove_movement);
}
std::auto_ptr<ai_move_result> ai_interface::check_move_action(const map_location& from, const location& to, bool remove_movement){
return ai_actions::execute_move_action(get_side(),false,from,to,remove_movement);
}
std::auto_ptr<ai_recruit_result> ai_interface::execute_recruit_action(const std::string& unit_name, const location &where){
return ai_actions::execute_recruit_action(get_side(),true,unit_name,where);
}
std::auto_ptr<ai_recruit_result> ai_interface::check_recruit_action(const std::string& unit_name, const location &where){
return ai_actions::execute_recruit_action(get_side(),false,unit_name,where);
}
std::auto_ptr<ai_stopunit_result> ai_interface::execute_stopunit_action(const map_location& unit_location, bool remove_movement, bool remove_attacks){
return ai_actions::execute_stopunit_action(get_side(),true,unit_location,remove_movement,remove_attacks);
}
std::auto_ptr<ai_stopunit_result> ai_interface::check_stopunit_action(const map_location& unit_location, bool remove_movement, bool remove_attacks){
return ai_actions::execute_stopunit_action(get_side(),false,unit_location,remove_movement,remove_attacks);
}

View file

@ -29,6 +29,11 @@ class gamemap;
#include "gamestatus.hpp"
#include "playturn.hpp"
class ai_attack_result;
class ai_move_result;
class ai_recruit_result;
class ai_stopunit_result;
class ai_interface : public game_logic::formula_callable {
public:
/** get the 1-based side number which is controlled by this AI */
@ -37,11 +42,15 @@ public:
/** get the 'master' flag of the AI. 'master' AI is the top-level-AI. */
bool get_master() const { return master_;}
/** A convenient typedef for the often used 'location' object. */
typedef map_location location;
/** The standard way in which a map of possible moves is recorded. */
typedef std::multimap<location,location> move_map;
/** The standard way in which a map of possible movement routes to location is recorded*/
typedef std::map<location,paths> moves_map;
/**
* info is structure which holds references to all the important objects
@ -127,9 +136,67 @@ public:
/** Return a message with information about the ai. Useful for making debugging ai-independent. */
virtual std::string describe_self() { return "? ai"; }
protected:
/**
* Ask the game to attack an enemy defender using our unit attacker from attackers current location,
* @param attacker_loc location of attacker
* @param defender_loc location of defender
* @param attacker_weapon weapon of attacker
* @retval possible result: ok
* @retval possible result: something wrong
* @retval possible result: attacker and/or defender are invalid
* @retval possible result: attacker and/or defender are invalid
* @retval possible result: attacker doesn't have the specified weapon
*/
std::auto_ptr<ai_attack_result> execute_attack_action(const location& attacker_loc, const location& defender_loc, int attacker_weapon);
std::auto_ptr<ai_attack_result> check_attack_action(const location& attacker_loc, const location& defender_loc, int attacker_weapon);
/**
* Ask the game to move our unit from location 'from' to location 'to', optionally - doing a partial move
* @param from location of our unit
* @param to where to move
* @param remove_movement set unit movement to 0 in case of successful move
* @retval possible result: ok
* @retval possible result: something wrong
* @retval possible result: move is interrupted
* @retval possible result: move is impossible
*/
std::auto_ptr<ai_move_result> execute_move_action(const location& from, const location& to, bool remove_movement=true);
std::auto_ptr<ai_move_result> check_move_action(const location& from, const location& to, bool remove_movement=true);
/**
* Ask the game to recruit a unit for us on specified location
* @param unit_name the name of the unit to be recruited.
* @param where location where the unit is to be recruited.
* @retval possible result: ok
* @retval possible_result: something wrong
* @retval possible_result: leader not on keep
* @retval possible_result: no free space on keep
* @retval possible_result: not enough gold
*/
std::auto_ptr<ai_recruit_result> execute_recruit_action(const std::string& unit_name, const location &where);
std::auto_ptr<ai_recruit_result> check_recruit_action(const std::string& unit_name, const location &where);
/**
* Ask the game to remove unit movements and/or attack
* @param unit_location the location of our unit
* @param remove_movement set remaining movements to 0
* @param remove_attacks set remaining attacks to 0
* @retval possible result: ok
* @retval possible_result: something wrong
* @retval possible_result: nothing to do
*/
std::auto_ptr<ai_stopunit_result> execute_stopunit_action(const location& unit_location, bool remove_movement = true, bool remove_attacks = false);
std::auto_ptr<ai_stopunit_result> check_stopunit_action(const location& unit_location, bool remove_movement = true, bool remove_attacks = false);
/**
* This function should be called to attack an enemy.
*
*
* @deprecated
* @param u The location of the attacking unit. (Note this shouldn't
* be a reference since attack::attack() can invalidate the
* unit_map and references to the map are also invalid then.)
@ -145,6 +212,7 @@ protected:
/**
* This function should be called to move a unit.
*
* @deprecated
* Once the unit has been moved, its movement allowance is set to 0.
* @param from The location of the unit being moved.
* @param to The location to be moved to. This must be a
@ -155,6 +223,7 @@ protected:
location move_unit(location from, location to, std::map<location,paths>& possible_moves);
/**
* @deprecated
* Identical to 'move_unit', except that the unit's movement
* isn't set to 0 after the move is complete.
*/