1 /*
2    Copyright (C) 2009 - 2018 by Yurii Chernyi <terraninfo@terraninfo.net>
3    Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY.
11 
12    See the COPYING file for more details.
13 */
14 
15 /**
16  * @file
17  * candidate action framework
18  */
19 
20 #pragma once
21 
22 #include "ai/composite/component.hpp"
23 #include "ai/composite/contexts.hpp"
24 
25 //============================================================================
26 namespace ai {
27 
28 class candidate_action : public virtual rca_context_proxy, public component {
29 public:
30 	//this is a score guaranteed to be <=0, thus candidate action with this score will not be selected for execution
31 	static const double BAD_SCORE;
32 
33 	//this is a score guaranteed to be very high, higher than any 'normal' candidate action score
34 	static const double HIGH_SCORE;
35 
36 	candidate_action( rca_context &context, const config &cfg );
37 
38 	/**
39 	 * Destructor
40 	 */
41 	virtual ~candidate_action();
42 
43 
44 	/**
45 	 * Evaluate the candidate action, resetting the internal state of the action
46 	 * @return the score
47 	 * @retval >0 if the action is good
48 	 * @retval <=0 if the action is not good
49 	 */
50 	virtual double evaluate() = 0;
51 
52 	/**
53 	 * Execute the candidate action
54 	 */
55 	virtual void execute() = 0;
56 
57 	/**
58 	 * Is this candidate action enabled ?
59 	 */
60 	bool is_enabled() const;
61 
62 	/**
63 	 * Enable the candidate action
64 	 */
65 	void enable();
66 
67 	/**
68 	 * Disable the candidate action
69 	 */
70 	void disable();
71 
72 	/**
73 	 * Get the usual score of the candidate action without re-evaluation
74 	 */
75 	double get_score() const;
76 
77 
78 	/**
79 	 * Get the upper bound of the score of the candidate action without re-evaluation
80 	 */
81 	double get_max_score() const;
82 
83 	/**
84 	 * Get the name of the candidate action (useful for debug purposes)
85 	 */
get_name() const86 	virtual std::string get_name() const
87 	{ return name_; }
88 
89 	/**
90 	 * Get the type of the candidate action (useful for debug purposes)
91 	 */
92 	const std::string& get_type() const;
93 
get_id() const94 	virtual std::string get_id() const
95 	{ return id_; }
96 
get_engine() const97 	virtual std::string get_engine() const
98 	{ return engine_; }
99 
100 	int get_recursion_count() const;
101 
102 
103 	/**
104 	 * serialize
105 	 */
106 	virtual config to_config() const;
107 
108 	virtual void set_to_be_removed();
109 
110 	virtual bool to_be_removed();
111 
112 private:
113 
114 	recursion_counter recursion_counter_;
115 
116 	bool enabled_;
117 
118 
119 	std::string engine_;
120 
121 
122 	double score_;
123 
124 
125 	double max_score_;
126 
127 
128 	std::string id_;
129 
130 
131 	std::string name_;
132 
133 
134 	std::string type_;
135 
136 
137 	bool to_be_removed_;
138 
139 };
140 
141 typedef std::shared_ptr<candidate_action> candidate_action_ptr;
142 
143 class candidate_action_factory;
144 
145 class candidate_action_factory{
146 	bool is_duplicate(const std::string &name);
147 public:
148 	typedef std::shared_ptr< candidate_action_factory > factory_ptr;
149 	typedef std::map<std::string, factory_ptr> factory_map;
150 	typedef std::pair<const std::string, factory_ptr> factory_map_pair;
151 
get_list()152 	static factory_map& get_list() {
153 		static factory_map *candidate_action_factories;
154 		if (candidate_action_factories==nullptr) {
155 			candidate_action_factories = new factory_map;
156 		}
157 		return *candidate_action_factories;
158 	}
159 
160 	virtual candidate_action_ptr get_new_instance( rca_context &context, const config &cfg ) = 0;
161 
candidate_action_factory(const std::string & name)162 	candidate_action_factory( const std::string &name )
163 	{
164 		if (is_duplicate(name)) {
165 			return;
166 		}
167 		factory_ptr ptr_to_this(this);
168 		get_list().emplace(name,ptr_to_this);
169 	}
170 
~candidate_action_factory()171 	virtual ~candidate_action_factory() {}
172 };
173 
174 
175 template<class CANDIDATE_ACTION>
176 class register_candidate_action_factory : public candidate_action_factory {
177 public:
register_candidate_action_factory(const std::string & name)178 	register_candidate_action_factory( const std::string &name )
179 		: candidate_action_factory( name )
180 	{
181 	}
182 
get_new_instance(rca_context & ai,const config & cfg)183 	virtual candidate_action_ptr get_new_instance( rca_context &ai, const config &cfg ){
184 		return std::make_shared<CANDIDATE_ACTION>(ai, cfg);
185 	}
186 };
187 
188 //============================================================================
189 
190 std::ostream &operator<<(std::ostream &s, const ai::candidate_action& ca);
191 
192 } //end of namespace ai
193