00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "ai.hpp"
00022 #include "engine_lua.hpp"
00023 #include "goal.hpp"
00024 #include "rca.hpp"
00025 #include "stage.hpp"
00026 #include "aspect.hpp"
00027
00028 #include "../gamestate_observer.hpp"
00029
00030 #include "../../log.hpp"
00031 #include "../../resources.hpp"
00032 #include "../lua/core.hpp"
00033 #include "../lua/lua_object.hpp"
00034 #include "../../scripting/lua.hpp"
00035 #include "../../util.hpp"
00036 #include "../../unit.hpp"
00037 #include "../../unit_map.hpp"
00038
00039
00040 namespace ai {
00041
00042 static lg::log_domain log_ai_engine_lua("ai/engine/lua");
00043 #define DBG_AI_LUA LOG_STREAM(debug, log_ai_engine_lua)
00044 #define LOG_AI_LUA LOG_STREAM(info, log_ai_engine_lua)
00045 #define WRN_AI_LUA LOG_STREAM(warn, log_ai_engine_lua)
00046 #define ERR_AI_LUA LOG_STREAM(err, log_ai_engine_lua)
00047
00048 #ifdef _MSC_VER
00049 #pragma warning(push)
00050
00051 #pragma warning(disable:4250)
00052 #endif
00053
00054 typedef boost::shared_ptr< lua_object<int> > lua_int_obj;
00055
00056 class lua_candidate_action_wrapper : public candidate_action {
00057 public:
00058 lua_candidate_action_wrapper( rca_context &context, const config &cfg, lua_ai_context &lua_ai_ctx)
00059 : candidate_action(context,cfg),evaluation_(cfg["evaluation"]),evaluation_action_handler_(),
00060 execution_(cfg["execution"]),execution_action_handler_(),serialized_evaluation_state_()
00061 {
00062 evaluation_action_handler_ = boost::shared_ptr<lua_ai_action_handler>(resources::lua_kernel->create_lua_ai_action_handler(evaluation_.c_str(),lua_ai_ctx));
00063 execution_action_handler_ = boost::shared_ptr<lua_ai_action_handler>(resources::lua_kernel->create_lua_ai_action_handler(execution_.c_str(),lua_ai_ctx));
00064 }
00065
00066 virtual ~lua_candidate_action_wrapper() {}
00067
00068
00069 virtual double evaluate()
00070 {
00071 serialized_evaluation_state_ = config();
00072
00073 lua_int_obj l_obj = lua_int_obj(new lua_object<int>());
00074
00075 if (evaluation_action_handler_) {
00076 evaluation_action_handler_->handle(serialized_evaluation_state_, true, l_obj);
00077 } else {
00078 return BAD_SCORE;
00079 }
00080
00081 return *(l_obj->get());
00082 }
00083
00084
00085 virtual void execute() {
00086 lua_int_obj l_obj = lua_int_obj(new lua_object<int>());
00087 if (execution_action_handler_) {
00088 execution_action_handler_->handle(serialized_evaluation_state_, false, l_obj);
00089 }
00090 }
00091
00092 virtual config to_config() const
00093 {
00094 config cfg = candidate_action::to_config();
00095 cfg["evaluation"] = evaluation_;
00096 cfg["execution"] = execution_;
00097 cfg.add_child("state",serialized_evaluation_state_);
00098 return cfg;
00099 }
00100
00101 private:
00102 std::string evaluation_;
00103 boost::shared_ptr<lua_ai_action_handler> evaluation_action_handler_;
00104 std::string execution_;
00105 boost::shared_ptr<lua_ai_action_handler> execution_action_handler_;
00106 config serialized_evaluation_state_;
00107 };
00108
00109 class lua_sticky_candidate_action_wrapper : public lua_candidate_action_wrapper {
00110 public:
00111 lua_sticky_candidate_action_wrapper( rca_context &context, const config &cfg, lua_ai_context &lua_ai_ctx)
00112 : lua_candidate_action_wrapper(context, cfg, lua_ai_ctx)
00113 , bound_unit_()
00114 {
00115 map_location loc(cfg["unit_x"] - 1, cfg["unit_y"] - 1);
00116 bound_unit_ = boost::shared_ptr<unit>(new unit(*resources::units->find(loc)));
00117 }
00118
00119 virtual double evaluate()
00120 {
00121 if (resources::units->find(bound_unit_->underlying_id()).valid())
00122 {
00123 return lua_candidate_action_wrapper::evaluate();
00124 }
00125 else
00126 {
00127 this->set_to_be_removed();
00128 return 0;
00129 }
00130 }
00131
00132 virtual void execute()
00133 {
00134 lua_candidate_action_wrapper::execute();
00135 this->disable();
00136 }
00137 private:
00138 boost::shared_ptr<unit> bound_unit_;
00139
00140 };
00141
00142 class lua_stage_wrapper : public stage {
00143 public:
00144 lua_stage_wrapper( ai_context &context, const config &cfg, lua_ai_context &lua_ai_ctx )
00145 : stage(context,cfg),action_handler_(),code_(cfg["code"]),serialized_evaluation_state_(cfg.child_or_empty("state"))
00146 {
00147 action_handler_ = boost::shared_ptr<lua_ai_action_handler>(resources::lua_kernel->create_lua_ai_action_handler(code_.c_str(),lua_ai_ctx));
00148 }
00149
00150 virtual ~lua_stage_wrapper()
00151 {
00152 }
00153
00154 virtual bool do_play_stage()
00155 {
00156 gamestate_observer gs_o;
00157 lua_int_obj l_obj = lua_int_obj(new lua_object<int>());
00158
00159 if (action_handler_) {
00160 action_handler_->handle(serialized_evaluation_state_, false, l_obj);
00161 }
00162
00163 return gs_o.is_gamestate_changed();
00164 }
00165
00166 virtual config to_config() const
00167 {
00168 config cfg = stage::to_config();
00169 cfg["code"] = code_;
00170 cfg.add_child("state",serialized_evaluation_state_);
00171 return cfg;
00172 }
00173 private:
00174 boost::shared_ptr<lua_ai_action_handler> action_handler_;
00175 std::string code_;
00176 config serialized_evaluation_state_;
00177 };
00178
00179
00180
00181
00182
00183
00184 engine_lua::engine_lua( readonly_context &context, const config &cfg )
00185 : engine(context,cfg)
00186 , code_(cfg["code"])
00187 , lua_ai_context_(resources::lua_kernel->create_lua_ai_context(
00188 cfg["code"].str().c_str(), this))
00189 {
00190 name_ = "lua";
00191
00192 config data(cfg.child_or_empty("data"));
00193 lua_ai_context_->set_persistent_data(data);
00194 }
00195
00196
00197 engine_lua::~engine_lua()
00198 {
00199 }
00200
00201
00202 void engine_lua::do_parse_candidate_action_from_config( rca_context &context, const config &cfg, std::back_insert_iterator<std::vector< candidate_action_ptr > > b ){
00203 if (!cfg) {
00204 return;
00205 }
00206
00207 if (!lua_ai_context_) {
00208 return;
00209 }
00210
00211 candidate_action_ptr ca_ptr;
00212 if (!cfg["sticky"].to_bool())
00213 {
00214 ca_ptr = candidate_action_ptr(new lua_candidate_action_wrapper(context,cfg,*lua_ai_context_));
00215 }
00216 else
00217 {
00218 ca_ptr = candidate_action_ptr(new lua_sticky_candidate_action_wrapper(context,cfg,*lua_ai_context_));
00219 }
00220
00221 if (ca_ptr) {
00222 *b = ca_ptr;
00223 }
00224 }
00225
00226 void engine_lua::do_parse_stage_from_config( ai_context &context, const config &cfg, std::back_insert_iterator<std::vector< stage_ptr > > b )
00227 {
00228 if (!cfg) {
00229 return;
00230 }
00231
00232 if (!lua_ai_context_) {
00233 return;
00234 }
00235
00236 stage_ptr st_ptr = stage_ptr(new lua_stage_wrapper(context,cfg,*lua_ai_context_));
00237 if (st_ptr) {
00238 st_ptr->on_create();
00239 *b = st_ptr;
00240 }
00241 }
00242
00243 void engine_lua::do_parse_aspect_from_config( const config &cfg, const std::string &id, std::back_insert_iterator<std::vector< aspect_ptr > > b )
00244 {
00245 const std::string aspect_factory_key = id+"*lua_aspect";
00246 lua_aspect_factory::factory_map::iterator f = lua_aspect_factory::get_list().find(aspect_factory_key);
00247
00248 if (f == lua_aspect_factory::get_list().end()){
00249 ERR_AI_LUA << "side "<<ai_.get_side()<< " : UNKNOWN aspect["<<aspect_factory_key<<"]" << std::endl;
00250 DBG_AI_LUA << "config snippet contains: " << std::endl << cfg << std::endl;
00251 return;
00252 }
00253 aspect_ptr new_aspect = f->second->get_new_instance(ai_,cfg,id,lua_ai_context_);
00254 if (!new_aspect) {
00255 ERR_AI_LUA << "side "<<ai_.get_side()<< " : UNABLE TO CREATE aspect, key=["<<aspect_factory_key<<"]"<< std::endl;
00256 DBG_AI_LUA << "config snippet contains: " << std::endl << cfg << std::endl;
00257 return;
00258 }
00259 *b = new_aspect;
00260 }
00261
00262 void engine_lua::do_parse_goal_from_config(const config &cfg, std::back_insert_iterator<std::vector< goal_ptr > > b )
00263 {
00264 goal_factory::factory_map::iterator f = goal_factory::get_list().find(cfg["name"]);
00265 if (f == goal_factory::get_list().end()){
00266 ERR_AI_LUA << "side "<<ai_.get_side()<< " : UNKNOWN goal["<<cfg["name"]<<"]"<< std::endl;
00267 DBG_AI_LUA << "config snippet contains: " << std::endl << cfg << std::endl;
00268 return;
00269 }
00270 goal_ptr new_goal = f->second->get_new_instance(ai_,cfg);
00271 new_goal->on_create(lua_ai_context_);
00272 if (!new_goal) {
00273 ERR_AI_LUA << "side "<<ai_.get_side()<< " : UNABLE TO CREATE goal["<<cfg["name"]<<"]"<< std::endl;
00274 DBG_AI_LUA << "config snippet contains: " << std::endl << cfg << std::endl;
00275 return;
00276 }
00277 *b = new_goal;
00278 }
00279
00280
00281 std::string engine_lua::evaluate(const std::string &)
00282 {
00283
00284
00285 return "";
00286 }
00287
00288 config engine_lua::to_config() const
00289 {
00290 config cfg = engine::to_config();
00291
00292 cfg["id"] = get_id();
00293 cfg["code"] = this->code_;
00294
00295 config data = config();
00296 lua_ai_context_->get_persistent_data(data);
00297 cfg.add_child("data") = data;
00298
00299 return cfg;
00300 }
00301
00302 #ifdef _MSC_VER
00303 #pragma warning(pop)
00304 #endif
00305
00306 }