mirror of
https://github.com/wesnoth/wesnoth
synced 2025-05-02 15:58:10 +00:00

This constitutes drop-in replacements for: * boost::shared_ptr * boost::scoped_ptr * boost::weak_ptr * boost::enable_shared_from_this * boost::static_pointer_cast * boost::dynamic_pointer_cast This excludes boost::intrusive_ptr, except for stray includes. Refactoring that is more complicated.
544 lines
16 KiB
C++
544 lines
16 KiB
C++
/*
|
|
Copyright (C) 2009 - 2016 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
|
|
* Managing the AIs lifecycle - headers
|
|
* @todo 1.9 Refactor history handling and internal commands.
|
|
* @todo 1.9 AI Interface command to clear the history.
|
|
*/
|
|
|
|
#ifndef AI_MANAGER_HPP_INCLUDED
|
|
#define AI_MANAGER_HPP_INCLUDED
|
|
|
|
#include "config.hpp" // for config, etc
|
|
#include "global.hpp"
|
|
#include "ai/game_info.hpp" // for side_number, ai_ptr
|
|
|
|
#include <deque> // for deque
|
|
#include <map> // for map, map<>::value_compare
|
|
#include <stack> // for stack
|
|
#include <string> // for string
|
|
|
|
namespace ai { class ai_composite; } // lines 45-45
|
|
namespace ai { class ai_context; } // lines 42-42
|
|
namespace ai { class component; } // lines 43-43
|
|
namespace ai { class default_ai_context; } // lines 41-41
|
|
namespace ai { class readonly_context; } // lines 39-39
|
|
namespace ai { class readwrite_context; } // lines 40-40
|
|
namespace ai { class side_context; } // lines 38-38
|
|
namespace events { class generic_event; }
|
|
namespace events { class observer; }
|
|
|
|
|
|
namespace ai {
|
|
|
|
typedef std::shared_ptr<ai_composite> composite_ai_ptr;
|
|
|
|
/**
|
|
* Base class that holds the AI and current AI parameters.
|
|
* It is an implementation detail.
|
|
* @todo 1.9 move it out of public view
|
|
*/
|
|
class holder{
|
|
public:
|
|
holder(side_number side, const config &cfg);
|
|
|
|
virtual ~holder();
|
|
|
|
ai_composite& get_ai_ref();
|
|
|
|
const std::string describe_ai();
|
|
|
|
config to_config() const;
|
|
|
|
void modify_ai(const config& cfg);
|
|
void modify_side_ai_config(config cfg);
|
|
|
|
|
|
const std::string get_ai_overview();
|
|
|
|
|
|
const std::string get_ai_structure();
|
|
|
|
|
|
const std::string get_ai_identifier() const;
|
|
|
|
component* get_component(component *root, const std::string &path); // Ai debug method
|
|
|
|
private:
|
|
void init( side_number side );
|
|
|
|
|
|
composite_ai_ptr ai_;
|
|
side_context *side_context_;
|
|
readonly_context *readonly_context_;
|
|
readwrite_context *readwrite_context_;
|
|
default_ai_context *default_ai_context_;
|
|
side_number side_;
|
|
config cfg_;
|
|
};
|
|
|
|
/**
|
|
* AI Command History Item. It is an implementation detail
|
|
*/
|
|
class command_history_item{
|
|
public:
|
|
|
|
command_history_item(int number, const std::string &command)
|
|
: number_(number), command_(command)
|
|
{}
|
|
|
|
int get_number() const { return number_; }
|
|
|
|
const std::string& get_command() const { return command_; }
|
|
|
|
private:
|
|
int number_;
|
|
std::string command_;
|
|
|
|
};
|
|
|
|
/**
|
|
* Class that manages AIs for all sides and manages AI redeployment.
|
|
* This class is responsible for managing the AI lifecycle
|
|
* It can be accessed like this: ai::manager::foo(...);
|
|
*/
|
|
class manager
|
|
{
|
|
public:
|
|
|
|
// =======================================================================
|
|
// CONSTANTS
|
|
// =======================================================================
|
|
|
|
static const size_t MAX_HISTORY_SIZE = 200;
|
|
|
|
static const std::string AI_TYPE_COMPOSITE_AI;
|
|
static const std::string AI_TYPE_SAMPLE_AI;
|
|
static const std::string AI_TYPE_IDLE_AI;
|
|
static const std::string AI_TYPE_FORMULA_AI;
|
|
static const std::string AI_TYPE_DFOOL_AI;
|
|
static const std::string AI_TYPE_AI2;
|
|
static const std::string AI_TYPE_DEFAULT;
|
|
|
|
|
|
// =======================================================================
|
|
// LIFECYCLE
|
|
// =======================================================================
|
|
|
|
/**
|
|
* Sets AI information.
|
|
* @param info ai_information to be set.
|
|
*/
|
|
static void set_ai_info(const game_info& info);
|
|
|
|
|
|
/**
|
|
* Clears AI information.
|
|
* Should be called in playsingle_controller 's destructor.
|
|
*/
|
|
static void clear_ai_info();
|
|
|
|
|
|
/**
|
|
* Adds observer of game events.
|
|
* Should be called in playsingle_controller 's constructor.
|
|
*/
|
|
static void add_observer( events::observer* event_observer);
|
|
|
|
|
|
/**
|
|
* Removes an observer of game events.
|
|
* Should be called in playsingle_controller 's destructor.
|
|
*/
|
|
static void remove_observer( events::observer* event_observer );
|
|
|
|
|
|
/**
|
|
* Adds observer of game events except ai_user_interact event and ai_sync_network event
|
|
*/
|
|
static void add_gamestate_observer( events::observer* event_observer);
|
|
|
|
|
|
/**
|
|
* Removes an observer of game events except ai_user_interact event and ai_sync_network event
|
|
*/
|
|
static void remove_gamestate_observer( events::observer* event_observer );
|
|
|
|
|
|
/**
|
|
* Notifies all observers of 'ai_user_interact' event.
|
|
* Function which should be called frequently to allow the user to interact
|
|
* with the interface. This function will make sure that interaction
|
|
* doesn't occur too often, so there is no problem with calling it very
|
|
* regularly.
|
|
*/
|
|
static void raise_user_interact();
|
|
|
|
/**
|
|
* Notifies all observers of 'ai_sync_network' event.
|
|
* Basically a request from the AI to sync the network.
|
|
*/
|
|
static void raise_sync_network();
|
|
|
|
|
|
/**
|
|
* Notifies all observers of 'ai_gamestate_changed' event.
|
|
*/
|
|
static void raise_gamestate_changed();
|
|
|
|
|
|
/**
|
|
* Notifies all observers of 'ai_tod_changed' event.
|
|
*/
|
|
static void raise_tod_changed();
|
|
|
|
|
|
/**
|
|
* Notifies all observers of 'ai_recruit_list_changed' event.
|
|
*/
|
|
static void raise_recruit_list_changed();
|
|
|
|
|
|
/**
|
|
* Notifies all observers of 'ai_turn_started' event.
|
|
*/
|
|
static void raise_turn_started();
|
|
|
|
|
|
/**
|
|
* Notifies all observers of 'ai_map_changed' event.
|
|
*/
|
|
static void raise_map_changed();
|
|
|
|
|
|
/**
|
|
* Adds an observer of 'ai_map_changed' event.
|
|
*/
|
|
static void add_map_changed_observer( events::observer* event_observer );
|
|
|
|
|
|
/**
|
|
* Adds an observer of 'ai_recruit_list_changed' event.
|
|
*/
|
|
static void add_recruit_list_changed_observer( events::observer* event_observer );
|
|
|
|
|
|
/**
|
|
* Adds an observer of 'ai_turn_started' event.
|
|
*/
|
|
static void add_turn_started_observer( events::observer* event_observer );
|
|
|
|
|
|
/**
|
|
* Adds an observer of 'ai_tod_changed' event.
|
|
*/
|
|
static void add_tod_changed_observer( events::observer* event_observer );
|
|
|
|
|
|
/**
|
|
* Deletes an observer of 'ai_map_changed' event.
|
|
*/
|
|
static void remove_map_changed_observer( events::observer* event_observer );
|
|
|
|
|
|
|
|
/**
|
|
* Deletes an observer of 'ai_recruit_list_changed' event.
|
|
*/
|
|
static void remove_recruit_list_changed_observer( events::observer* event_observer );
|
|
|
|
|
|
/**
|
|
* Deletes an observer of 'ai_turn_started' event.
|
|
*/
|
|
static void remove_turn_started_observer( events::observer* event_observer );
|
|
|
|
|
|
/**
|
|
* Deletes an observer of 'ai_tod_changed' event.
|
|
*/
|
|
static void remove_tod_changed_observer( events::observer* event_observer );
|
|
|
|
|
|
private:
|
|
|
|
manager();
|
|
|
|
|
|
public:
|
|
|
|
// =======================================================================
|
|
// EVALUATION
|
|
// =======================================================================
|
|
|
|
/**
|
|
* Evaluates a string command using command AI.
|
|
* @note Running this command may invalidate references previously returned
|
|
* by manager. Will intercept those commands which start with '!'
|
|
* and '?', and will try to evaluate them as internal commands.
|
|
* @param side side number (1-based).
|
|
* @param str string to evaluate.
|
|
* @return string result of evaluation.
|
|
*/
|
|
static const std::string evaluate_command( side_number side, const std::string& str );
|
|
|
|
|
|
// =======================================================================
|
|
// ADD, CREATE AIs, OR LIST AI TYPES
|
|
// =======================================================================
|
|
|
|
/**
|
|
* Adds active AI for specified @a side from @a file.
|
|
* @note Running this command may invalidate references previously returned
|
|
* by manager. AI is not initialized at this point.
|
|
* @param side side number (1-based, as in game_info).
|
|
* @param file file name, follows the usual WML convention.
|
|
* @param replace should new ai replace the current ai or 'be placed on top of it'.
|
|
* @return true if successful.
|
|
*/
|
|
static bool add_ai_for_side_from_file( side_number side, const std::string& file, bool replace = true );
|
|
|
|
|
|
/**
|
|
* Adds active AI for specified @a side from @a cfg.
|
|
* @note Running this command may invalidate references previously returned
|
|
* by manager. AI is not initialized at this point.
|
|
* @param side side number (1-based, as in game_info).
|
|
* @param cfg the config from which all ai parameters are to be read.
|
|
* @param replace should new ai replace the current ai or 'be placed on top of it'.
|
|
* @return true if successful.
|
|
*/
|
|
static bool add_ai_for_side_from_config(side_number side, const config &cfg, bool replace = true);
|
|
|
|
|
|
/**
|
|
* Adds active AI for specified @a side from parameters.
|
|
* @note Running this command may invalidate references previously returned
|
|
* by manager. AI is not initialized at this point.
|
|
* @param side side number (1-based, as in game_info).
|
|
* @param ai_algorithm_type type of AI algorithm to create.
|
|
* @param replace should new ai replace the current ai or 'be placed on top of it'.
|
|
* @return true if successful.
|
|
*/
|
|
static bool add_ai_for_side( side_number side, const std::string& ai_algorithm_type, bool replace = true);
|
|
|
|
|
|
// =======================================================================
|
|
// REMOVE
|
|
// =======================================================================
|
|
|
|
/**
|
|
* Removes top-level AI from @a side.
|
|
* @note Running this command may invalidate references previously returned
|
|
* by manager.
|
|
* @param side side number (1-based, as in game_info).
|
|
*/
|
|
static void remove_ai_for_side( side_number side );
|
|
|
|
|
|
/**
|
|
* Removes all AIs from @a side.
|
|
* @note Running this command may invalidate references previously returned
|
|
* by manager.
|
|
* @param side side number (1-based, as in game_info).
|
|
*/
|
|
static void remove_all_ais_for_side( side_number side );
|
|
|
|
|
|
/**
|
|
* Clears all the AIs.
|
|
* @note Running this command may invalidate references previously returned
|
|
* by manager. For example, this is called from the destructor of
|
|
* playsingle_controller. It is necessary to do this if any of the
|
|
* info structures used by the AI goes out of scope.
|
|
*/
|
|
static void clear_ais();
|
|
|
|
// =======================================================================
|
|
// GET active AI parameters
|
|
// =======================================================================
|
|
|
|
|
|
/**
|
|
* Gets AI info for active AI of the given @a side.
|
|
* @param side side number (1-based).
|
|
* @return a reference to active AI info.
|
|
*/
|
|
static game_info& get_active_ai_info_for_side( side_number side );
|
|
|
|
|
|
/**
|
|
* Gets AI Overview for active AI of the given @a side
|
|
* @param side side number (1-based)
|
|
* @return an ai overview
|
|
*/
|
|
static std::string get_active_ai_overview_for_side( side_number side);
|
|
|
|
|
|
/**
|
|
* Gets AI Structure for active AI of the given @a side
|
|
* @param side side number (1-based)
|
|
* @return an ai structure
|
|
*/
|
|
static std::string get_active_ai_structure_for_side( side_number side);
|
|
|
|
/**
|
|
* Gets AI algorithm identifier for active AI of the given @a side.
|
|
* @param side side number (1-based).
|
|
* @return ai identifier for the active AI
|
|
*/
|
|
static std::string get_active_ai_identifier_for_side( side_number side );
|
|
|
|
/**
|
|
* Gets the active AI holder for debug purposes.
|
|
* Will only work in debug mode, otherwise returns a reference to an empty holder
|
|
* @param side side number(1-based)
|
|
* @return debug ? active holder : empty holder
|
|
*/
|
|
static ai::holder& get_active_ai_holder_for_side_dbg(side_number side);
|
|
|
|
/**
|
|
* Gets AI config for active AI of the given @a side.
|
|
* @param side side number (1-based).
|
|
* @return a config object for the active AI
|
|
*/
|
|
static config to_config( side_number side );
|
|
|
|
|
|
/**
|
|
* Gets global AI-game info
|
|
* @return a reference to the AI-game info.
|
|
*/
|
|
static game_info& get_ai_info();
|
|
|
|
|
|
// =======================================================================
|
|
// SET active AI parameters
|
|
// =======================================================================
|
|
|
|
|
|
/**
|
|
* Modifies AI parameters for active AI of the given @a side.
|
|
* This function is provided for backward-compatibility with [modify_side][ai]...[/ai][/modify_side]
|
|
* It can only add new facets to aspects
|
|
* @param side side_number (1-based, as in game_info).
|
|
* @param ai_parameters AI parameters to be modified.
|
|
*/
|
|
static void modify_active_ai_config_old_for_side ( side_number side, const config::const_child_itors &ai_parameters );
|
|
|
|
|
|
|
|
/**
|
|
* Modifies AI parameters for active AI of the given @a side.
|
|
* This function is a backend for [modify_ai] tag
|
|
* @param side side_number (1-based, as in game_info).
|
|
* @param cfg - content of [modify_ai] tag
|
|
*/
|
|
|
|
static void modify_active_ai_for_side( ai::side_number side, const config &cfg );
|
|
|
|
// =======================================================================
|
|
// PROXY
|
|
// =======================================================================
|
|
|
|
/**
|
|
* Plays a turn for the specified side using its active AI.
|
|
* @param side side number (1-based, as in game_info).
|
|
*/
|
|
static void play_turn(side_number side);
|
|
|
|
|
|
private:
|
|
|
|
typedef std::map< side_number, std::stack< holder > > AI_map_of_stacks;
|
|
static AI_map_of_stacks ai_map_;
|
|
static std::deque< command_history_item > history_;
|
|
static long history_item_counter_;
|
|
static game_info *ai_info_;
|
|
|
|
static events::generic_event map_changed_;
|
|
static events::generic_event recruit_list_changed_;
|
|
static events::generic_event user_interact_;
|
|
static events::generic_event sync_network_;
|
|
static events::generic_event tod_changed_;
|
|
static events::generic_event gamestate_changed_;
|
|
static events::generic_event turn_started_;
|
|
static int last_interact_;
|
|
static int num_interact_;
|
|
|
|
|
|
|
|
// =======================================================================
|
|
// EVALUATION
|
|
// =======================================================================
|
|
|
|
/**
|
|
* Evaluates an internal manager command.
|
|
* @param side side number (1-based).
|
|
* @param str string to evaluate.
|
|
* @return string result of evaluation.
|
|
* @todo 1.9 rewrite this function to use a fai or lua parser.
|
|
*/
|
|
static const std::string internal_evaluate_command( side_number side, const std::string& str );
|
|
|
|
/**
|
|
* Determines if the command should be intercepted and evaluated as internal command.
|
|
* @param str command string to check.
|
|
* @return true if the command should be intercepted and evaluated.
|
|
*/
|
|
static bool should_intercept( const std::string& str );
|
|
|
|
// =======================================================================
|
|
// AI STACKS
|
|
// =======================================================================
|
|
|
|
|
|
/**
|
|
* Gets the AI stack for the specified side, create it if it doesn't exist.
|
|
*/
|
|
static std::stack< holder >& get_or_create_ai_stack_for_side(side_number side);
|
|
|
|
// =======================================================================
|
|
// AI HOLDERS
|
|
// =======================================================================
|
|
|
|
|
|
/**
|
|
* Gets active holder for specified @a side.
|
|
*/
|
|
static holder& get_active_ai_holder_for_side( side_number side );
|
|
|
|
// =======================================================================
|
|
// AI POINTERS
|
|
// =======================================================================
|
|
|
|
/**
|
|
* Gets active AI for specified side.
|
|
* @note Running this command may invalidate references previously returned
|
|
* by manager.
|
|
* @param side side number (1-based, as in game_info).
|
|
* @return a reference to the active AI.
|
|
* @note This reference may become invalid after specific manager operations.
|
|
*/
|
|
static ai_composite& get_active_ai_for_side( side_number side );
|
|
|
|
|
|
};
|
|
|
|
} //end of namespace ai
|
|
|
|
#endif
|