1 
2 /*
3    Copyright (C) 2009 - 2018 by Yurii Chernyi <terraninfo@terraninfo.net>
4    Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY.
12 
13    See the COPYING file for more details.
14 */
15 
16 /**
17  * AI Support engine - creating specific ai components from config
18  * @file
19  */
20 
21 #pragma once
22 
23 #include "ai/composite/component.hpp"
24 #include "ai/contexts.hpp"
25 
26 #include <algorithm>
27 #include <iterator>
28 
29 //============================================================================
30 
31 namespace ai {
32 
33 class rca_context;
34 class ai_context;
35 class component;
36 
37 class engine : public component {
38 public:
39 	engine( readonly_context &context, const config &cfg );
40 
41 
42 	virtual ~engine();
43 
44 	virtual bool is_ok() const;
45 
46 	static void parse_aspect_from_config( readonly_context &context, const config &cfg, const std::string &id, std::back_insert_iterator<std::vector< aspect_ptr >> b );
47 
48 
49 	static void parse_goal_from_config( readonly_context &context, const config &cfg, std::back_insert_iterator<std::vector< goal_ptr >> b );
50 
51 
52 	static void parse_candidate_action_from_config( rca_context &context, const config &cfg, std::back_insert_iterator<std::vector< candidate_action_ptr >> b );
53 
54 
55 	static void parse_engine_from_config( readonly_context &context, const config &cfg, std::back_insert_iterator<std::vector< engine_ptr >> b );
56 
57 
58 	static void parse_stage_from_config( ai_context &context, const config &cfg, std::back_insert_iterator<std::vector< stage_ptr >> b );
59 
60 
61 	//do not override that method in subclasses which cannot create aspects
62 	virtual void do_parse_aspect_from_config( const config &cfg, const std::string &id, std::back_insert_iterator< std::vector< aspect_ptr>> b );
63 
64 
65 	//do not override that method in subclasses which cannot create candidate_actions
66 	virtual void do_parse_candidate_action_from_config( rca_context &context, const config &cfg, std::back_insert_iterator<std::vector< candidate_action_ptr >> b );
67 
68 	//do not override that method in subclasses which cannot create goals
69 	virtual void do_parse_goal_from_config( const config &cfg, std::back_insert_iterator<std::vector< goal_ptr >> b );
70 
71 	//do not override that method in subclasses which cannot create engines
72 	virtual void do_parse_engine_from_config( const config &cfg, std::back_insert_iterator<std::vector< engine_ptr >> b );
73 
74 
75 	//do not override that method in subclasses which cannot create stages
76 	virtual void do_parse_stage_from_config( ai_context &context, const config &cfg, std::back_insert_iterator<std::vector< stage_ptr >> b );
77 
78 	//do not override that method in subclasses which cannot evaluate formulas
79 	virtual std::string evaluate(const std::string& str);
80 
81 	readonly_context& get_readonly_context();
82 
83 	/**
84 	 * set ai context (which is not available during early initialization)
85 	 */
86 	virtual void set_ai_context(ai_context_ptr context);
87 
88 	virtual ai_context_ptr get_ai_context();
89 	/**
90 	 * serialize
91 	 */
92 	virtual config to_config() const;
93 
94 
get_id() const95 	virtual std::string get_id() const
96 	{ return id_; }
97 
get_engine() const98 	virtual std::string get_engine() const
99 	{ return engine_; }
100 
get_name() const101 	virtual std::string get_name() const
102 	{ return name_; }
103 
104 protected:
105 	readonly_context &ai_;
106 	ai_context_ptr ai_context_;
107 
108 	/** name of the engine which has created this engine*/
109 	std::string engine_;
110 	std::string id_;
111 	std::string name_;
112 };
113 
114 
115 class engine_factory;
116 
117 class engine_factory{
118 	bool is_duplicate(const std::string &name);
119 public:
120 	typedef std::shared_ptr< engine_factory > factory_ptr;
121 	typedef std::map<std::string, factory_ptr> factory_map;
122 	typedef std::pair<const std::string, factory_ptr> factory_map_pair;
123 
get_list()124 	static factory_map& get_list() {
125 		static factory_map *engine_factories;
126 		if (engine_factories==nullptr) {
127 			engine_factories = new factory_map;
128 		}
129 		return *engine_factories;
130 	}
131 
132 	virtual engine_ptr get_new_instance( readonly_context &ai, const config &cfg ) = 0;
133 	virtual engine_ptr get_new_instance( readonly_context &ai, const std::string& name ) = 0;
134 
engine_factory(const std::string & name)135 	engine_factory( const std::string &name )
136 	{
137 		if (is_duplicate(name)) {
138 			return;
139 		}
140 		factory_ptr ptr_to_this(this);
141 		get_list().emplace(name,ptr_to_this);
142 	}
143 
~engine_factory()144 	virtual ~engine_factory() {}
145 };
146 
147 
148 template<class ENGINE>
149 class register_engine_factory : public engine_factory {
150 public:
register_engine_factory(const std::string & name)151 	register_engine_factory( const std::string &name )
152 		: engine_factory( name )
153 	{
154 	}
155 
get_new_instance(readonly_context & ai,const config & cfg)156 	virtual engine_ptr get_new_instance( readonly_context &ai, const config &cfg ){
157 		engine_ptr e = std::make_shared<ENGINE>(ai, cfg);
158 		if (!e->is_ok()) {
159 			return engine_ptr();
160 		}
161 		return e;
162 	}
163 
get_new_instance(readonly_context & ai,const std::string & name)164 	virtual engine_ptr get_new_instance( readonly_context &ai, const std::string& name ){
165 		config cfg;
166 		cfg["name"] = name;
167 		cfg["engine"] = "cpp"; // @Crab: what is the purpose of this line(neph)
168 		return std::make_shared<ENGINE>(ai, cfg);
169 	}
170 };
171 
172 } //end of namespace ai
173