mirror of
https://github.com/wesnoth/wesnoth
synced 2025-05-18 11:23:27 +00:00
273 lines
8.5 KiB
C++
273 lines
8.5 KiB
C++
/* $Id$ */
|
|
/*
|
|
Copyright (C) 2003 - 2009 by David White <dave@whitevine.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.
|
|
*/
|
|
|
|
/** @file ai/default/ai.hpp */
|
|
|
|
#ifndef AI_DEFAULT_AI_HPP_INCLUDED
|
|
#define AI_DEFAULT_AI_HPP_INCLUDED
|
|
|
|
#include "../../global.hpp"
|
|
|
|
#include "contexts.hpp"
|
|
|
|
#include "../actions.hpp"
|
|
#include "../interface.hpp"
|
|
#include "../contexts.hpp"
|
|
#include "../composite/stage.hpp"
|
|
#include "../../formula_callable.hpp"
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning(push)
|
|
//silence "inherits via dominance" warnings
|
|
#pragma warning(disable:4250)
|
|
#endif
|
|
|
|
namespace ai {
|
|
|
|
class formula_ai;
|
|
|
|
/** A trivial ai that sits around doing absolutely nothing. */
|
|
class idle_ai : public readwrite_context_proxy, public interface {
|
|
public:
|
|
idle_ai(readwrite_context &context, const config &cfg);
|
|
void play_turn();
|
|
void new_turn();
|
|
virtual std::string describe_self();
|
|
void switch_side(side_number side);
|
|
int get_recursion_count() const;
|
|
virtual config to_config() const;
|
|
private:
|
|
const config &cfg_;
|
|
recursion_counter recursion_counter_;
|
|
};
|
|
|
|
class ai_default_recruitment_stage : public stage {
|
|
public:
|
|
ai_default_recruitment_stage(ai_context &context, const config &cfg);
|
|
virtual ~ai_default_recruitment_stage();
|
|
void on_create();
|
|
bool do_play_stage();
|
|
config to_config() const;
|
|
private:
|
|
config cfg_;
|
|
|
|
virtual bool recruit_usage(const std::string& usage);
|
|
|
|
/**
|
|
* Analyze all the units that this side can recruit
|
|
* and rate their movement types.
|
|
* Ratings will be placed in 'unit_movement_scores_',
|
|
* with lower scores being better,
|
|
* and the lowest possible rating being '10'.
|
|
*/
|
|
virtual void analyze_potential_recruit_movements();
|
|
|
|
std::map<std::string,int> unit_movement_scores_;
|
|
std::set<std::string> not_recommended_units_;
|
|
|
|
/**
|
|
* Analyze all the units that this side can recruit
|
|
* and rate their fighting suitability against enemy units.
|
|
* Ratings will be placed in 'unit_combat_scores_',
|
|
* with a '0' rating indicating that the unit is 'average' against enemy units,
|
|
* negative ratings meaning they are poorly suited,
|
|
* and positive ratings meaning they are well suited.
|
|
*/
|
|
virtual void analyze_potential_recruit_combat();
|
|
|
|
std::map<std::string,int> unit_combat_scores_;
|
|
|
|
/**
|
|
* Rates two unit types for their suitability against each other.
|
|
* Returns 0 if the units are equally matched,
|
|
* a positive number if a is suited against b,
|
|
* and a negative number if b is suited against a.
|
|
*/
|
|
virtual int compare_unit_types(const unit_type& a, const unit_type& b) const;
|
|
|
|
/**
|
|
* calculates the average resistance unit type a has against the attacks of
|
|
* unit type b.
|
|
*/
|
|
virtual int average_resistance_against(const unit_type& a, const unit_type& b) const;
|
|
|
|
|
|
};
|
|
|
|
class ai_default : public virtual ai_context_proxy, public interface, public game_logic::formula_callable {
|
|
public:
|
|
typedef map_location location;//will get rid of this later
|
|
|
|
ai_default(ai_context &context, const config &cfg);
|
|
virtual ~ai_default();
|
|
|
|
virtual void play_turn();
|
|
virtual void new_turn();
|
|
virtual std::string describe_self();
|
|
virtual config to_config() const;
|
|
void switch_side(side_number side);
|
|
|
|
|
|
virtual variant get_value(const std::string& key) const;
|
|
virtual void get_inputs(std::vector<game_logic::formula_input>* inputs) const;
|
|
|
|
/** get the recursion counter */
|
|
int get_recursion_count() const;
|
|
private:
|
|
const config cfg_;
|
|
recursion_counter recursion_counter_;
|
|
|
|
protected:
|
|
|
|
virtual void do_move();
|
|
|
|
virtual bool do_combat(std::map<map_location,paths>& possible_moves,
|
|
const move_map& srcdst, const move_map& dstsrc,
|
|
const move_map& enemy_srcdst, const move_map& enemy_dstsrc);
|
|
virtual bool get_villages(std::map<map_location,paths>& possible_moves,
|
|
const move_map& dstsrc, const move_map& enemy_dstsrc,
|
|
unit_map::iterator &leader);
|
|
virtual bool get_healing(std::map<map_location,paths>& possible_moves,
|
|
const move_map& srcdst, const move_map& enemy_dstsrc);
|
|
virtual bool retreat_units(std::map<map_location,paths>& possible_moves,
|
|
const move_map& srcdst, const move_map& dstsrc,
|
|
const move_map& enemy_dstsrc, unit_map::const_iterator leader);
|
|
virtual bool move_to_targets(std::map<map_location,paths>& possible_moves,
|
|
move_map& srcdst, move_map& dstsrc, const move_map& enemy_dstsrc,
|
|
unit_map::const_iterator leader);
|
|
|
|
virtual bool should_retreat(const map_location& loc,
|
|
const unit_map::const_iterator un, const move_map& srcdst,
|
|
const move_map& dstsrc, const move_map& enemy_dstsrc, double caution);
|
|
|
|
virtual bool do_recruitment();
|
|
|
|
virtual void move_leader_to_keep(const move_map& enemy_dstsrc);
|
|
virtual void move_leader_after_recruit(const move_map& srcdst,
|
|
const move_map& dstsrc, const move_map& enemy_dstsrc);
|
|
|
|
virtual void move_leader_to_goals(const move_map& enemy_dstsrc);
|
|
|
|
|
|
virtual bool desperate_attack(const map_location &loc);
|
|
|
|
void remove_unit_from_moves(const map_location& u, move_map& srcdst, move_map& dstsrc);
|
|
|
|
/** Find enemy units that threaten our valuable assets. */
|
|
void find_threats();
|
|
|
|
bool threats_found_;
|
|
|
|
/**
|
|
* Our own version of 'move_unit'. It is like the version in readwrite_context
|
|
* however if it is the leader moving, it will first attempt recruitment.
|
|
*/
|
|
location move_unit(location from, location to, std::map<location,paths>& possible_moves);
|
|
|
|
/**
|
|
* Our own version of 'attack_enemy'. We record all attacks to support
|
|
* group attacking.
|
|
*/
|
|
bool attack_enemy(const location& attacking_unit, const location& target,
|
|
int att_weapon, int def_weapon);
|
|
|
|
|
|
/**
|
|
* Sees if it's possible for a unit to move 'from' -> 'via' -> 'to' all in
|
|
* one turn.
|
|
*/
|
|
bool multistep_move_possible(const location& from,
|
|
const location& to, const location& via,
|
|
const std::map<location,paths>& possible_moves) const;
|
|
|
|
public:
|
|
|
|
protected:
|
|
|
|
bool is_accessible(const location& loc, const move_map& dstsrc) const;
|
|
|
|
|
|
/**
|
|
* Function to form a group of units suitable for moving along the route, 'route'.
|
|
*
|
|
* @Returns The location which the group may reach this
|
|
* turn. Stores the locations of the units in
|
|
* the group in 'units'.
|
|
*/
|
|
virtual location form_group(const std::vector<location>& route,
|
|
const move_map& dstsrc, std::set<location>& units);
|
|
|
|
/** Return the group of enemies that threaten a certain path. */
|
|
virtual void enemies_along_path(const std::vector<location>& route,
|
|
const move_map& dstsrc, std::set<location>& units);
|
|
|
|
virtual bool move_group(const location& dst, const std::vector<location>& route,
|
|
const std::set<location>& units);
|
|
|
|
virtual double rate_group(const std::set<location>& group,
|
|
const std::vector<location>& battlefield) const;
|
|
|
|
virtual double compare_groups(const std::set<location>& our_group,
|
|
const std::set<location>& enemy_groups,
|
|
const std::vector<location>& battlefield) const;
|
|
|
|
virtual std::pair<location,location> choose_move(std::vector<target>& targets,
|
|
const move_map& srcdst, const move_map& dstsrc, const move_map& enemy_dstsrc);
|
|
|
|
game_display& disp_;
|
|
gamemap& map_;
|
|
unit_map& units_;
|
|
std::vector<team>& teams_;
|
|
tod_manager& tod_manager_;
|
|
bool consider_combat_;
|
|
|
|
/** Functions to deal with keeps. */
|
|
void evaluate_recruiting_value(const map_location &leader_loc);
|
|
|
|
/**
|
|
* Function which, given a unit position, and a position the unit wants to
|
|
* get to in two turns, will return all possible positions the unit can
|
|
* move to, that will make the destination position accessible next turn.
|
|
*/
|
|
void access_points(const move_map& srcdst, const location& u,
|
|
const location& dst, std::vector<location>& out);
|
|
|
|
|
|
friend class attack_analysis;
|
|
|
|
private:
|
|
void find_villages(/*std::vector<unit_map::const_iterator>& our_units,
|
|
std::vector<std::vector<map_location> >& reachable_villages, */
|
|
std::map<map_location /*unit location*/, std::vector<map_location /* villages we can reach*/> >& reachmap,
|
|
std::vector<std::pair<map_location,map_location> >& moves,
|
|
const std::multimap<map_location,map_location>& dstsrc,
|
|
const std::map<map_location,paths>& possible_moves,
|
|
const std::multimap<map_location,map_location>& enemy_dstsrc) const;
|
|
|
|
int recruiting_preferred_;
|
|
static const int min_recruiting_value_to_force_recruit = 28;
|
|
protected:
|
|
formula_ai *formula_ai_;
|
|
ai_ptr formula_ai_ptr_;
|
|
};
|
|
|
|
} //end of namespace ai
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning(pop)
|
|
#endif
|
|
|
|
|
|
#endif
|