AI Refactoring: new stub AI actions code.
This commit is contained in:
parent
3014f70d47
commit
cef695a685
8 changed files with 519 additions and 7 deletions
|
@ -290,6 +290,10 @@
|
|||
RelativePath="..\..\src\ai_dfool.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai_interface.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai_manager.cpp"
|
||||
>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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
65
src/ai_interface.cpp
Normal 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);
|
||||
}
|
|
@ -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.
|
||||
*/
|
||||
|
|
Loading…
Add table
Reference in a new issue