The Battle for Wesnoth  1.15.3+dev
core.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2010 - 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  * Provides core classes for the Lua AI.
18  *
19  */
20 
21 #include <cassert>
22 #include <cstring>
23 
24 #include "ai/lua/core.hpp"
25 #include "ai/composite/aspect.hpp"
27 #include "scripting/lua_unit.hpp"
28 #include "scripting/push_check.hpp"
29 #include "ai/lua/lua_object.hpp" // (Nephro)
30 
31 #include "attack_prediction.hpp"
32 #include "game_display.hpp"
33 #include "log.hpp"
34 #include "map/map.hpp"
35 #include "pathfind/pathfind.hpp"
36 #include "play_controller.hpp"
37 #include "resources.hpp"
38 #include "terrain/translation.hpp"
39 #include "terrain/filter.hpp"
40 #include "units/unit.hpp"
41 #include "ai/actions.hpp"
42 #include "ai/lua/engine_lua.hpp"
45 #include "deprecation.hpp"
46 
47 #include "lua/lualib.h"
48 #include "lua/lauxlib.h"
49 #include "lua/llimits.h"
50 
51 static lg::log_domain log_ai_engine_lua("ai/engine/lua");
52 #define LOG_LUA LOG_STREAM(info, log_ai_engine_lua)
53 #define WRN_LUA LOG_STREAM(warn, log_ai_engine_lua)
54 #define ERR_LUA LOG_STREAM(err, log_ai_engine_lua)
55 
56 static char const aisKey[] = "ai contexts";
57 
58 namespace ai {
59 
60 static void push_attack_analysis(lua_State *L, const attack_analysis&);
61 
63 {
64  // Create the ai elements table.
65  lua_newtable(L);
67 }
68 
70 {
71  int top = lua_gettop(L);
72 
74  lua_rawgeti(L, -1, num_);
75 
76  lua_getfield(L, -1, "params");
77  luaW_toconfig(L, -1, cfg);
78 
79  lua_settop(L, top);
80 }
81 
83 {
84  int top = lua_gettop(L);
85 
87  lua_rawgeti(L, -1, num_);
88 
89  luaW_pushconfig(L, cfg);
90  lua_setfield(L, -2, "params");
91 
92  lua_settop(L, top);
93 }
94 
96 {
97  int top = lua_gettop(L);
98 
100  lua_rawgeti(L, -1, num_);
101 
102  lua_getfield(L, -1, "data");
103  luaW_toconfig(L, -1, cfg);
104 
105  lua_settop(L, top);
106 }
107 
109 {
110  int top = lua_gettop(L);
111 
113  lua_rawgeti(L, -1, num_);
114 
115  luaW_pushconfig(L, cfg);
116  lua_setfield(L, -2, "data");
117 
118  lua_settop(L, top);
119 }
120 
122 {
123  return *(static_cast<ai::engine_lua*>(
125 }
126 
128 {
129  return get_engine(L).get_readonly_context();
130 }
131 
133 {
134  lua_ai_load ctx(*this, false);
135 }
136 
138 {
139  lua_newtable(L);
140  lua_pushboolean(L,action_result->is_ok());
141  lua_setfield(L, -2, "ok");
142  lua_pushboolean(L,action_result->is_gamestate_changed());
143  lua_setfield(L, -2, "gamestate_changed");
144  lua_pushinteger(L,action_result->get_status());
145  lua_setfield(L, -2, "status");
146  lua_pushstring(L, actions::get_error_name(action_result->get_status()).c_str());
147  lua_setfield(L, -2, "result");
148  return 1;
149 }
150 
152 {
153  int index = 1;
154 
156  unit* leader = nullptr;
157  if (lua_isuserdata(L, index))
158  {
159  leader = luaW_tounit(L, index);
160  if (!leader) return luaL_argerror(L, 1, "unknown unit");
161  }
162  else return luaW_type_error(L, 1, "unit");
163  const map_location loc = leader->get_location();
164  const pathfind::paths leader_paths(*leader, false, true, context.current_team());
165  const map_location &res = context.suitable_keep(loc,leader_paths);
166  if (!res.valid()) {
167  return 0;
168  }
169  else {
170  lua_pushnumber(L, res.wml_x());
171  lua_pushnumber(L, res.wml_y());
172  return 2;
173  }
174 }
175 
176 static int ai_move(lua_State *L, bool exec, bool remove_movement)
177 {
178  int side = get_readonly_context(L).get_side();
179  map_location from = luaW_checklocation(L, 1);
180  map_location to = luaW_checklocation(L, 2);
181  bool unreach_is_ok = false;
182  if (lua_isboolean(L, 3)) {
183  unreach_is_ok = luaW_toboolean(L, 3);
184  }
185  ai::move_result_ptr move_result = ai::actions::execute_move_action(side,exec,from,to,remove_movement, unreach_is_ok);
186  return transform_ai_action(L,move_result);
187 }
188 
190 {
191  return ai_move(L, true, true);
192 }
193 
195 {
196  return ai_move(L, true, false);
197 }
198 
200 {
201  return ai_move(L, false, false);
202 }
203 
204 static int ai_attack(lua_State *L, bool exec)
205 {
207 
208  int side = context.get_side();
209  map_location attacker = luaW_checklocation(L, 1);
210  map_location defender = luaW_checklocation(L, 2);
211 
212  int attacker_weapon = -1;//-1 means 'select what is best'
213  double aggression = context.get_aggression();//use the aggression from the context
214 
215  if (!lua_isnoneornil(L, 3)) {
216  attacker_weapon = lua_tointeger(L, 3);
217  if (attacker_weapon != -1) {
218  attacker_weapon--; // Done for consistency of the Lua style
219  }
220  }
221 
222  // Note: Right now, aggression is used by the attack execution functions to determine the weapon to be used.
223  // If a decision is made to expand the function that determines the weapon, this block must be refactored
224  // to parse aggression if a single int is on the stack, or create a table of parameters, if a table is on the
225  // stack.
226  if (!lua_isnoneornil(L, 4) && lua_isnumber(L,4)) {
227  aggression = lua_tonumber(L, 4);
228  }
229 
230  ai::attack_result_ptr attack_result = ai::actions::execute_attack_action(side,exec,attacker,defender,attacker_weapon,aggression);
231  return transform_ai_action(L,attack_result);
232 }
233 
235 {
236  return ai_attack(L, true);
237 }
238 
240 {
241  return ai_attack(L, false);
242 }
243 
244 static int ai_stopunit_select(lua_State *L, bool exec, bool remove_movement, bool remove_attacks)
245 {
246  int side = get_readonly_context(L).get_side();
247  map_location loc = luaW_checklocation(L, 1);
248 
249  ai::stopunit_result_ptr stopunit_result = ai::actions::execute_stopunit_action(side,exec,loc,remove_movement,remove_attacks);
250  return transform_ai_action(L,stopunit_result);
251 }
252 
254 {
255  return ai_stopunit_select(L, true, true, false);
256 }
257 
259 {
260  return ai_stopunit_select(L, true, false, true);
261 }
262 
264 {
265  return ai_stopunit_select(L, true, true, true);
266 }
267 
269 {
270  return ai_stopunit_select(L, false, true, true);
271 }
272 
273 static int ai_recruit(lua_State *L, bool exec)
274 {
275  const char *unit_name = luaL_checkstring(L, 1);
276  int side = get_readonly_context(L).get_side();
277  map_location where;
278  if (!lua_isnoneornil(L, 2)) {
279  where.set_wml_x(lua_tonumber(L, 2));
280  where.set_wml_y(lua_tonumber(L, 3));
281  }
283  ai::recruit_result_ptr recruit_result = ai::actions::execute_recruit_action(side,exec,std::string(unit_name),where,from);
284  return transform_ai_action(L,recruit_result);
285 }
286 
288 {
289  return ai_recruit(L, true);
290 }
291 
293 {
294  return ai_recruit(L, false);
295 }
296 
297 static int ai_recall(lua_State *L, bool exec)
298 {
299  const char *unit_id = luaL_checkstring(L, 1);
300  int side = get_readonly_context(L).get_side();
301  map_location where;
302  if (!lua_isnoneornil(L, 2)) {
303  where.set_wml_x(lua_tonumber(L, 2));
304  where.set_wml_y(lua_tonumber(L, 3));
305  }
307  ai::recall_result_ptr recall_result = ai::actions::execute_recall_action(side,exec,std::string(unit_id),where,from);
308  return transform_ai_action(L,recall_result);
309 }
310 
312 {
313  return ai_recall(L, true);
314 }
315 
317 {
318  return ai_recall(L, false);
319 }
320 
322 {
324 }
325 
326 // Goals and targets
327 
328 
330 {
331  move_map enemy_dst_src = get_readonly_context(L).get_enemy_dstsrc();
332  std::vector<target> targets = get_engine(L).get_ai_context()->find_targets(enemy_dst_src);
333  int i = 1;
334 
335  lua_createtable(L, 0, 0);
336  for (std::vector<target>::iterator it = targets.begin(); it != targets.end(); ++it)
337  {
338  lua_pushinteger(L, i);
339 
340  //to factor out
341  lua_createtable(L, 3, 0);
342 
343 
344  lua_pushstring(L, "type");
345  lua_pushstring(L, it->type.to_string().c_str());
346  lua_rawset(L, -3);
347 
348  lua_pushstring(L, "loc");
349  luaW_pushlocation(L, it->loc);
350  lua_rawset(L, -3);
351 
352  lua_pushstring(L, "value");
353  lua_pushnumber(L, it->value);
354  lua_rawset(L, -3);
355 
356  lua_rawset(L, -3);
357  ++i;
358  }
359  return 1;
360 }
361 
362 // Note: If adding new uses of this macro, it will be necessary to either remove the old ones
363 // (and the things so deprecated) OR add a version parameter to the macro.
364 // Also note that the name MUST be a string literal.
365 #define DEPRECATED_ASPECT_MESSAGE(name) \
366  deprecated_message("ai.get_" name, DEP_LEVEL::PREEMPTIVE, {1, 15, 0}, "Use ai.aspects." name " instead")
367 
368 // Aspect section
370 {
371  DEPRECATED_ASPECT_MESSAGE("aggression");
372  double aggression = get_readonly_context(L).get_aggression();
373  lua_pushnumber(L, aggression);
374  return 1;
375 }
376 
378 {
379  // Unlike the other aspect fetchers, this one is not deprecated!
380  // This is because ai.aspects.attacks returns the viable units but this returns a full attack analysis
382  lua_createtable(L, attacks.size(), 0);
383  int table_index = lua_gettop(L);
384 
385  ai::attacks_vector::const_iterator it = attacks.begin();
386  for (int i = 1; it != attacks.end(); ++it, ++i)
387  {
388  push_attack_analysis(L, *it);
389 
390  lua_rawseti(L, table_index, i);
391  }
392  return 1;
393 }
394 
396 {
397  DEPRECATED_ASPECT_MESSAGE("avoid");
398  std::set<map_location> locs;
399  terrain_filter avoid = get_readonly_context(L).get_avoid();
400  avoid.get_locations(locs);
401  lua_push(L, locs);
402 
403  return 1;
404 }
405 
407 {
408  DEPRECATED_ASPECT_MESSAGE("caution");
409  double caution = get_readonly_context(L).get_caution();
410  lua_pushnumber(L, caution);
411  return 1;
412 }
413 
415 {
416  DEPRECATED_ASPECT_MESSAGE("grouping");
417  std::string grouping = get_readonly_context(L).get_grouping();
418  lua_pushstring(L, grouping.c_str());
419  return 1;
420 }
421 
423 {
424  DEPRECATED_ASPECT_MESSAGE("leader_aggression");
425  double leader_aggression = get_readonly_context(L).get_leader_aggression();
426  lua_pushnumber(L, leader_aggression);
427  return 1;
428 }
429 
431 {
432  DEPRECATED_ASPECT_MESSAGE("leader_goal");
434  luaW_pushconfig(L, goal);
435  return 1;
436 }
437 
439 {
440  DEPRECATED_ASPECT_MESSAGE("leader_ignores_keep");
441  boost::variant<bool, std::vector<std::string>> leader_ignores_keep = get_readonly_context(L).get_leader_ignores_keep();
442  if (leader_ignores_keep.which() == 0) {
443  lua_pushboolean(L, boost::get<bool>(leader_ignores_keep));
444  } else {
445  std::vector<std::string> strlist = boost::get<std::vector<std::string>>(leader_ignores_keep);
446  lua_createtable(L, strlist.size(), 0);
447  for(const std::string& str : strlist) {
448  lua_pushlstring(L, str.c_str(), str.size());
449  lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
450  }
451  }
452  return 1;
453 }
454 
456 {
457  DEPRECATED_ASPECT_MESSAGE("leader_value");
458  double leader_value = get_readonly_context(L).get_leader_value();
459  lua_pushnumber(L, leader_value);
460  return 1;
461 }
462 
464 {
465  DEPRECATED_ASPECT_MESSAGE("passive_leader");
466  boost::variant<bool, std::vector<std::string>> passive_leader = get_readonly_context(L).get_passive_leader();
467  if (passive_leader.which() == 0) {
468  lua_pushboolean(L, boost::get<bool>(passive_leader));
469  } else {
470  std::vector<std::string> strlist = boost::get<std::vector<std::string>>(passive_leader);
471  lua_createtable(L, strlist.size(), 0);
472  for(const std::string& str : strlist) {
473  lua_pushlstring(L, str.c_str(), str.size());
474  lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
475  }
476  }
477  return 1;
478 }
479 
481 {
482  DEPRECATED_ASPECT_MESSAGE("passive_leader_shares_keep");
483  boost::variant<bool, std::vector<std::string>> passive_leader_shares_keep = get_readonly_context(L).get_passive_leader_shares_keep();
484  if (passive_leader_shares_keep.which() == 0) {
485  lua_pushboolean(L, boost::get<bool>(passive_leader_shares_keep));
486  } else {
487  std::vector<std::string> strlist = boost::get<std::vector<std::string>>(passive_leader_shares_keep);
488  lua_createtable(L, strlist.size(), 0);
489  for(const std::string& str : strlist) {
490  lua_pushlstring(L, str.c_str(), str.size());
491  lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
492  }
493  }
494  return 1;
495 }
496 
498 {
499  DEPRECATED_ASPECT_MESSAGE("recruitment_pattern");
500  std::vector<std::string> recruiting = get_readonly_context(L).get_recruitment_pattern();
501  int size = recruiting.size();
502  lua_createtable(L, size, 0); // create an empty table with predefined size
503  for (int i = 0; i < size; ++i)
504  {
505  lua_pushinteger(L, i + 1); // Indexing in Lua starts from 1
506  lua_pushstring(L, recruiting[i].c_str());
507  lua_settable(L, -3);
508  }
509  return 1;
510 }
511 
513 {
514  DEPRECATED_ASPECT_MESSAGE("scout_village_targeting");
515  double scout_village_targeting = get_readonly_context(L).get_scout_village_targeting();
516  lua_pushnumber(L, scout_village_targeting);
517  return 1;
518 }
519 
521 {
522  DEPRECATED_ASPECT_MESSAGE("simple_targeting");
523  bool simple_targeting = get_readonly_context(L).get_simple_targeting();
524  lua_pushboolean(L, simple_targeting);
525  return 1;
526 }
527 
529 {
530  DEPRECATED_ASPECT_MESSAGE("support_villages");
531  bool support_villages = get_readonly_context(L).get_support_villages();
532  lua_pushboolean(L, support_villages);
533  return 1;
534 }
535 
537 {
538  DEPRECATED_ASPECT_MESSAGE("village_value");
539  double village_value = get_readonly_context(L).get_village_value();
540  lua_pushnumber(L, village_value);
541  return 1;
542 }
543 
545 {
546  DEPRECATED_ASPECT_MESSAGE("villages_per_scout");
547  int villages_per_scout = get_readonly_context(L).get_villages_per_scout();
548  lua_pushnumber(L, villages_per_scout);
549  return 1;
550 }
551 // End of aspect section
552 
554 {
555  int top = lua_gettop(L);
556  // the attack_analysis table should be on top of the stack
557  lua_getfield(L, -1, "att_ptr"); // [-2: attack_analysis; -1: pointer to attack_analysis object in c++]
558  // now the pointer to our attack_analysis C++ object is on top
559  const attack_analysis* aa_ptr = static_cast< attack_analysis * >(lua_touserdata(L, -1));
560 
561  //[-2: attack_analysis; -1: pointer to attack_analysis object in c++]
562 
563  double aggression = get_readonly_context(L).get_aggression();
564 
565  double rating = aa_ptr->rating(aggression, get_readonly_context(L));
566 
567  lua_settop(L, top);
568 
569  lua_pushnumber(L, rating);
570  return 1;
571 }
572 
573 static void push_movements(lua_State *L, const std::vector< std::pair < map_location, map_location > > & moves)
574 {
575  lua_createtable(L, moves.size(), 0);
576 
577  int table_index = lua_gettop(L);
578 
579  std::vector< std::pair < map_location, map_location > >::const_iterator move = moves.begin();
580 
581  for (int i = 1; move != moves.end(); ++move, ++i)
582  {
583  lua_createtable(L, 2, 0); // Creating a table for a pair of map_location's
584 
585  lua_pushstring(L, "src");
586  luaW_pushlocation(L, move->first);
587  lua_rawset(L, -3);
588 
589  lua_pushstring(L, "dst");
590  luaW_pushlocation(L, move->second);
591  lua_rawset(L, -3);
592 
593  lua_rawseti(L, table_index, i); // setting the pair as an element of the movements table
594  }
595 
596 
597 }
598 
600 {
601  lua_newtable(L);
602 
603  // Pushing a pointer to the current object
604  lua_pushstring(L, "att_ptr");
605  lua_pushlightuserdata(L, const_cast<attack_analysis*>(&aa));
606  lua_rawset(L, -3);
607 
608  // Registering callback function for the rating method
609  lua_pushstring(L, "rating");
612  lua_rawset(L, -3);
613 
614  lua_pushstring(L, "movements");
615  push_movements(L, aa.movements);
616  lua_rawset(L, -3);
617 
618  lua_pushstring(L, "target");
619  luaW_pushlocation(L, aa.target);
620  lua_rawset(L, -3);
621 
622  lua_pushstring(L, "target_value");
624  lua_rawset(L, -3);
625 
626  lua_pushstring(L, "avg_losses");
627  lua_pushnumber(L, aa.avg_losses);
628  lua_rawset(L, -3);
629 
630  lua_pushstring(L, "chance_to_kill");
632  lua_rawset(L, -3);
633 
634  lua_pushstring(L, "avg_damage_inflicted");
636  lua_rawset(L, -3);
637 
638  lua_pushstring(L, "target_starting_damage");
640  lua_rawset(L, -3);
641 
642  lua_pushstring(L, "avg_damage_taken");
644  lua_rawset(L, -3);
645 
646  lua_pushstring(L, "resources_used");
648  lua_rawset(L, -3);
649 
650  lua_pushstring(L, "terrain_quality");
652  lua_rawset(L, -3);
653 
654  lua_pushstring(L, "alternative_terrain_quality");
656  lua_rawset(L, -3);
657 
658  lua_pushstring(L, "vulnerability");
660  lua_rawset(L, -3);
661 
662  lua_pushstring(L, "support");
663  lua_pushnumber(L, aa.support);
664  lua_rawset(L, -3);
665 
666  lua_pushstring(L, "leader_threat");
668  lua_rawset(L, -3);
669 
670  lua_pushstring(L, "uses_leader");
672  lua_rawset(L, -3);
673 
674  lua_pushstring(L, "is_surrounded");
676  lua_rawset(L, -3);
677 }
678 
679 static void push_move_map(lua_State *L, const move_map& m)
680 {
681  lua_createtable(L, 0, 0); // the main table
682 
683  if (m.empty())
684  {
685  return;
686  }
687 
688  move_map::const_iterator it = m.begin();
689 
690  int index = 1;
691 
693 
694  do
695  {
696  map_location key = it->first;
697  lua_pushinteger(L, lhash(key));
698 
699  lua_createtable(L, 0, 0);
700 
701  while (key == it->first) {
702 
703  luaW_pushlocation(L, it->second);
704  lua_rawseti(L, -2, index);
705 
706  ++index;
707  ++it;
708 
709  }
710 
711  lua_settable(L, -3);
712 
713  index = 1;
714 
715  } while (it != m.end());
716 }
717 
719 {
722  push_move_map(L, dst_src);
723  return 1;
724 }
725 
727 {
730  push_move_map(L, src_dst);
731  return 1;
732 }
733 
735 {
736  move_map enemy_dst_src = get_readonly_context(L).get_enemy_dstsrc();
738  push_move_map(L, enemy_dst_src);
739  return 1;
740 }
741 
743 {
744  move_map enemy_src_dst = get_readonly_context(L).get_enemy_srcdst();
746  push_move_map(L, enemy_src_dst);
747  return 1;
748 }
749 
751 {
752  bool valid = get_readonly_context(L).is_dst_src_valid_lua();
753  lua_pushboolean(L, valid);
754  return 1;
755 }
756 
758 {
760  lua_pushboolean(L, valid);
761  return 1;
762 }
763 
765 {
766  bool valid = get_readonly_context(L).is_src_dst_valid_lua();
767  lua_pushboolean(L, valid);
768  return 1;
769 }
770 
772 {
774  lua_pushboolean(L, valid);
775  return 1;
776 }
777 
779 {
781  return 1;
782 }
783 
785 {
787  return 1;
788 }
789 
790 template<typename T>
792 {
793  return std::dynamic_pointer_cast<typesafe_aspect<T> >(p).get();
794 }
795 
797 {
798  const aspect_map& aspects = get_engine(L).get_readonly_context().get_aspects();
799  aspect_map::const_iterator iter = aspects.find(luaL_checkstring(L, 2));
800  if(iter == aspects.end()) {
801  return 0;
802  }
803 
804  // A few aspects require special delicate handling...
805  if(typesafe_aspect<attacks_vector>* aspect_as_attacks_vector = try_aspect_as<attacks_vector>(iter->second)) {
807  aspect_attacks_base* real_aspect = dynamic_cast<aspect_attacks_base*>(aspect_as_attacks_vector);
808  while(real_aspect == nullptr) {
809  // It's probably a composite aspect, so find the active facet
810  composite_aspect<attacks_vector>& composite = dynamic_cast<composite_aspect<attacks_vector>&>(*aspect_as_attacks_vector);
811  aspect_as_attacks_vector = &dynamic_cast<typesafe_aspect<attacks_vector>&>(composite.find_active());
812  real_aspect = dynamic_cast<aspect_attacks_base*>(aspect_as_attacks_vector);
813  }
814  int my_side = get_engine(L).get_readonly_context().get_side();
815  std::vector<unit_const_ptr> attackers, enemies;
816  for(unit_map::const_iterator u = resources::gameboard->units().begin(); u != resources::gameboard->units().end(); ++u) {
817  if(!u.valid()) {
818  continue;
819  }
820  if(u->side() == my_side && real_aspect->is_allowed_attacker(*u)) {
821  attackers.push_back(u.get_shared_ptr());
822  } else if(u->side() != my_side && real_aspect->is_allowed_enemy(*u)) {
823  enemies.push_back(u.get_shared_ptr());
824  }
825  }
826  lua_createtable(L, 0, 2);
827  lua_createtable(L, attackers.size(), 0);
828  for(size_t i = 0; i < attackers.size(); i++) {
829  luaW_pushunit(L, attackers[i]->underlying_id());
830  lua_rawseti(L, -2, i + 1);
831  }
832  lua_setfield(L, -2, "own");
833  lua_createtable(L, enemies.size(), 0);
834  for(size_t i = 0; i < enemies.size(); i++) {
835  luaW_pushunit(L, enemies[i]->underlying_id());
836  lua_rawseti(L, -2, i + 1);
837  }
838  lua_setfield(L, -2, "enemy");
839  } else if(typesafe_aspect<unit_advancements_aspect>* aspect_as_unit_advancements_aspects = try_aspect_as<unit_advancements_aspect>(iter->second)) {
840  const unit_advancements_aspect& val = aspect_as_unit_advancements_aspects->get();
841  int my_side = get_engine(L).get_readonly_context().get_side();
842  lua_newtable(L);
844  for (unit_map::const_iterator u = resources::gameboard->units().begin(); u != resources::gameboard->units().end(); ++u) {
845  if (!u.valid() || u->side() != my_side) {
846  continue;
847  }
848  lua_pushinteger(L, lhash(u->get_location()));
849  lua_push(L, val.get_advancements(u));
850  lua_settable(L, -3);
851  }
852  } else {
853  iter->second->get_lua(L);
854  }
855  return 1;
856 }
857 
859 {
860  lua_pushstring(L, "attempted to write to the ai.aspects table, which is read-only");
861  return lua_error(L);
862 }
863 
864 static int impl_ai_get(lua_State* L)
865 {
866  if(!lua_isstring(L,2)) {
867  return 0;
868  }
870  std::string m = lua_tostring(L,2);
871  if(m == "side") {
873  return 1;
874  }
875  if(m == "aspects") {
876  lua_newtable(L); // [-1: Aspects table]
877  lua_newtable(L); // [-1: Aspects metatable -2: Aspects table]
878  lua_pushlightuserdata(L, &engine); // [-1: Engine -2: Aspects mt -3: Aspects table]
879  lua_pushcclosure(L, &impl_ai_aspect_get, 1); // [-1: Metafunction -2: Aspects mt -3: Aspects table]
880  lua_setfield(L, -2, "__index"); // [-1: Aspects metatable -2: Aspects table]
881  lua_pushcfunction(L, &impl_ai_aspect_set); // [-1: Metafunction -2: Aspects mt -3: Aspects table]
882  lua_setfield(L, -2, "__newindex"); // [-1: Aspects metatable -2: Aspects table]
883  lua_setmetatable(L, -2); // [-1: Aspects table]
884  return 1;
885  }
886  static luaL_Reg const callbacks[] = {
887  // Move maps
888  { "get_new_dst_src", &cfun_ai_get_dstsrc },
889  { "get_new_src_dst", &cfun_ai_get_srcdst },
890  { "get_new_enemy_dst_src", &cfun_ai_get_enemy_dstsrc },
891  { "get_new_enemy_src_dst", &cfun_ai_get_enemy_srcdst },
892  { "recalculate_move_maps", &cfun_ai_recalculate_move_maps },
893  { "recalculate_enemy_move_maps", &cfun_ai_recalculate_move_maps_enemy },
894  // End of move maps
895  // Goals and targets
896  { "get_targets", &cfun_ai_get_targets },
897  // End of G & T
898  // Aspects
899  { "get_aggression", &cfun_ai_get_aggression },
900  { "get_avoid", &cfun_ai_get_avoid },
901  { "get_attacks", &cfun_ai_get_attacks },
902  { "get_caution", &cfun_ai_get_caution },
903  { "get_grouping", &cfun_ai_get_grouping },
904  { "get_leader_aggression", &cfun_ai_get_leader_aggression },
905  { "get_leader_goal", &cfun_ai_get_leader_goal },
906  { "get_leader_ignores_keep", &cfun_ai_get_leader_ignores_keep },
907  { "get_leader_value", &cfun_ai_get_leader_value },
908  { "get_passive_leader", &cfun_ai_get_passive_leader },
909  { "get_passive_leader_shares_keep", &cfun_ai_get_passive_leader_shares_keep },
910  { "get_recruitment_pattern", &cfun_ai_get_recruitment_pattern },
911  { "get_scout_village_targeting", &cfun_ai_get_scout_village_targeting },
912  { "get_simple_targeting", &cfun_ai_get_simple_targeting },
913  { "get_support_villages", &cfun_ai_get_support_villages },
914  { "get_village_value", &cfun_ai_get_village_value },
915  { "get_villages_per_scout", &cfun_ai_get_villages_per_scout },
916  // End of aspects
917  // Validation/cache functions
918  { "is_dst_src_valid", &cfun_ai_is_dst_src_valid },
919  { "is_enemy_dst_src_valid", &cfun_ai_is_dst_src_enemy_valid },
920  { "is_src_dst_valid", &cfun_ai_is_src_dst_valid },
921  { "is_enemy_src_dst_valid", &cfun_ai_is_src_dst_enemy_valid },
922  // End of validation functions
923  { "suitable_keep", &cfun_ai_get_suitable_keep },
924  { "check_recall", &cfun_ai_check_recall },
925  { "check_move", &cfun_ai_check_move },
926  { "check_stopunit", &cfun_ai_check_stopunit },
927  { "check_attack", &cfun_ai_check_attack },
928  { "check_recruit", &cfun_ai_check_recruit },
929  //{ "",},
930  //{ "",},
931  { nullptr, nullptr } };
932  for (const luaL_Reg* p = callbacks; p->name; ++p) {
933  if(m == p->name) {
934  lua_pushlightuserdata(L, &engine); // [-1: engine ...]
935  lua_pushcclosure(L, p->func, 1); // [-1: function ...]
936  // Store the function so that __index doesn't need to be called next time
937  lua_pushstring(L, p->name); // [-1: name -2: function ...]
938  lua_pushvalue(L, -2); // [-1: function -2: name -3: function ...]
939  lua_rawset(L, 1); // [-1: function ...]
940  return 1;
941  }
942  }
943  lua_pushstring(L, "read_only");
944  lua_rawget(L, 1);
945  bool read_only = luaW_toboolean(L, -1);
946  lua_pop(L, 1);
947  if(read_only) {
948  return 0;
949  }
950  static luaL_Reg const mutating_callbacks[] = {
951  { "attack", &cfun_ai_execute_attack },
952  { "move", &cfun_ai_execute_move_partial },
953  { "move_full", &cfun_ai_execute_move_full },
954  { "recall", &cfun_ai_execute_recall },
955  { "recruit", &cfun_ai_execute_recruit },
956  { "stopunit_all", &cfun_ai_execute_stopunit_all },
957  { "stopunit_attacks", &cfun_ai_execute_stopunit_attacks },
958  { "stopunit_moves", &cfun_ai_execute_stopunit_moves },
959  { "fallback_human", &cfun_ai_fallback_human},
960  { nullptr, nullptr } };
961  for (const luaL_Reg* p = mutating_callbacks; p->name; ++p) {
962  if(m == p->name) {
963  lua_pushlightuserdata(L, &engine);
964  lua_pushcclosure(L, p->func, 1);
965  return 1;
966  }
967  }
968  return 0;
969 }
970 
972  //push data table here
973  lua_newtable(L); // [-1: ai table]
974  lua_newtable(L); // [-1: metatable -2: ai table]
975  lua_pushlightuserdata(L, engine); // [-1: engine -2: metatable -3: ai table]
976  lua_pushcclosure(L, &impl_ai_get, 1); // [-1: metafunc -2: metatable -3: ai table]
977  lua_setfield(L, -2, "__index"); // [-1: metatable -2: ai table]
978  lua_setmetatable(L, -2); // [-1: ai table]
979 }
980 
982 {
983  // Retrieve the ai elements table from the registry.
984  lua_getfield(L, LUA_REGISTRYINDEX, aisKey); // [-1: AIs registry table]
985  size_t length_ai = lua_rawlen(L, -1); // length of table
986  lua_newtable(L); // [-1: AI state table -2: AIs registry table]
987  generate_and_push_ai_table(L, engine); // [-1: AI routines -2: AI state -3: AIs registry]
988  lua_setfield(L, -2, "ai"); // [-1: AI state -2: AIs registry]
989  lua_pushvalue(L, -1); // [-1: AI state -2: AI state -3: AIs registry]
990  lua_rawseti(L, -3, length_ai + 1); // [-1: AI state -2: AIs registry]
991  lua_remove(L, -2); // [-1: AI state table]
992  return length_ai + 1;
993 }
994 
996 {
997  int res_ai = luaL_loadbufferx(L, code, strlen(code), /*name*/ code, "t"); // [-1: AI code]
998  if (res_ai != 0)
999  {
1000 
1001  char const *m = lua_tostring(L, -1);
1002  ERR_LUA << "error while initializing ai: " <<m << '\n';
1003  lua_pop(L, 2);//return with stack size 0 []
1004  return nullptr;
1005  }
1006  //push data table here
1007  size_t idx = generate_and_push_ai_state(L, engine); // [-1: AI state -2: AI code]
1008  lua_pushvalue(L, -2); // [-1: AI code -2: AI state -3: AI code]
1009  lua_setfield(L, -2, "update_self"); // [-1: AI state -2: AI code]
1010  lua_pushlightuserdata(L, engine);
1011  lua_setfield(L, -2, "engine"); // [-1: AI state -2: AI code]
1012  lua_pop(L, 2);
1013  return new lua_ai_context(L, idx, engine->get_readonly_context().get_side());
1014 }
1015 
1017 {
1018  lua_ai_load ctx(*this, true); // [-1: AI state table]
1019 
1020  // Load the AI code and arguments
1021  lua_getfield(L, -1, "update_self"); // [-1: AI code -2: AI state]
1022  lua_getfield(L, -2, "params"); // [-1: Arguments -2: AI code -3: AI state]
1023  lua_getfield(L, -3, "data"); // [-1: Persistent data -2: Arguments -3: AI code -4: AI state]
1024 
1025  // Call the function
1026  if (!luaW_pcall(L, 2, 1, true)) { // [-1: Result -2: AI state]
1027  return; // return with stack size 0 []
1028  }
1029 
1030  // Store the state for use by components
1031  lua_setfield(L, -2, "self"); // [-1: AI state]
1032 
1033  // And return with empty stack.
1034  lua_pop(L, 1);
1035 }
1036 
1038 {
1039  int res = luaL_loadbufferx(L, code, strlen(code), /*name*/ code, "t");//stack size is now 1 [ -1: f]
1040  if (res)
1041  {
1042  char const *m = lua_tostring(L, -1);
1043  ERR_LUA << "error while creating ai function: " <<m << '\n';
1044  lua_pop(L, 2);//return with stack size 0 []
1045  return nullptr;
1046  }
1047 
1048  // Retrieve the ai elements table from the registry.
1049  lua_getfield(L, LUA_REGISTRYINDEX, aisKey); //stack size is now 2 [-1: ais_table -2: f]
1050  // Push the function in the table so that it is not collected.
1051  size_t length = lua_rawlen(L, -1);//length of ais_table
1052  lua_pushvalue(L, -2); //stack size is now 3: [-1: f -2: ais_table -3: f]
1053  lua_rawseti(L, -2, length + 1);// ais_table[length+1]=f. stack size is now 2 [-1: ais_table -2: f]
1054  lua_remove(L, -1);//stack size is now 1 [-1: f]
1055  lua_remove(L, -1);//stack size is now 0 []
1056  // Create the proxy C++ action handler.
1057  return new lua_ai_action_handler(L, context, length + 1);
1058 }
1059 
1060 
1061 int lua_ai_load::refcount = 0;
1062 
1063 lua_ai_load::lua_ai_load(lua_ai_context& ctx, bool read_only) : L(ctx.L), was_readonly(false)
1064 {
1065  refcount++;
1066  // Check if the AI table is already loaded. If so, we have less work to do.
1067  lua_getglobal(L, "ai");
1068  if(!lua_isnoneornil(L, -1)) {
1069  // Save the previous read-only state
1070  lua_getfield(L, -1, "read_only");
1071  was_readonly = luaW_toboolean(L, -1);
1072  lua_pop(L, 1);
1073  // Update the read-only state
1074  lua_pushstring(L, "read_only");
1075  lua_pushboolean(L, read_only);
1076  lua_rawset(L, -3);
1077  return; // Leave the AI table on the stack, as requested
1078  }
1079  lua_pop(L, 1); // Pop the nil value off the stack
1080  lua_getfield(L, LUA_REGISTRYINDEX, aisKey); // [-1: AI registry]
1081  lua_rawgeti(L, -1, ctx.num_); // [-1: AI state -2: AI registry]
1082  lua_remove(L,-2); // [-1: AI state]
1083 
1084  // Load the AI functions table into global scope
1085  lua_getfield(L, -1, "ai"); // [-1: AI functions -2: AI state]
1086  lua_pushstring(L, "read_only"); // [-1: key -2: AI functions -3: AI state]
1087  lua_pushboolean(L, read_only); // [-1: value -2: key -3: AI functions -4: AI state]
1088  lua_rawset(L, -3); // [-1: AI functions -2: AI state]
1089  lua_setglobal(L, "ai"); // [-1: AI state]
1090 }
1091 
1093 {
1094  refcount--;
1095  if (refcount == 0) {
1096  // Remove the AI functions from the global scope
1097  lua_pushnil(L);
1098  lua_setglobal(L, "ai");
1099  } else {
1100  // Restore the read-only state
1101  lua_getglobal(L, "ai");
1102  lua_pushstring(L, "read_only");
1104  lua_rawset(L, -3);
1105  lua_pop(L, 1);
1106  }
1107 }
1108 
1110 {
1111  // Remove the ai context from the registry, so that it can be collected.
1113  lua_pushnil(L);
1114  lua_rawseti(L, -2, num_);
1115  lua_pop(L, 1);
1116 }
1117 
1118 void lua_ai_action_handler::handle(const config &cfg, const config &filter_own, bool read_only, lua_object_ptr l_obj)
1119 {
1120  int initial_top = lua_gettop(L);//get the old stack size
1121 
1122  // Load the context
1123  lua_ai_load ctx(context_, read_only); // [-1: AI state table]
1124 
1125  // Load the user function from the registry.
1126  lua_getfield(L, LUA_REGISTRYINDEX, aisKey); // [-1: AI registry -2: AI state]
1127  lua_rawgeti(L, -1, num_); // [-1: AI action -2: AI registry -3: AI state]
1128  lua_remove(L, -2); // [-1: AI action -2: AI state]
1129 
1130  // Load the arguments
1131  int iState = lua_absindex(L, -2);
1132  lua_getfield(L, iState, "self");
1133  luaW_pushconfig(L, cfg);
1134  lua_getfield(L, iState, "data");
1135 
1136  int num = 3;
1137  if (!filter_own.empty()) {
1138  luaW_pushconfig(L, filter_own);
1139  num=4;
1140  }
1141 
1142  // Call the function
1143  luaW_pcall(L, num, l_obj ? 1 : 0, true);
1144  if (l_obj) {
1145  l_obj->store(L, -1);
1146  }
1147 
1148  lua_settop(L, initial_top);//empty stack
1149 }
1150 
1152 {
1153  // Remove the function from the registry, so that it can be collected.
1155  lua_pushnil(L);
1156  lua_rawseti(L, -2, num_);
1157  lua_pop(L, 1);
1158 }
1159 
1160 } // of namespace ai
void set_wml_y(int v)
Definition: location.hpp:161
std::shared_ptr< action_result > action_result_ptr
Definition: game_info.hpp:78
static int ai_stopunit_select(lua_State *L, bool exec, bool remove_movement, bool remove_attacks)
Definition: core.cpp:244
bool leader_threat
Is true if the unit is a threat to our leader.
Definition: contexts.hpp:125
virtual boost::variant< bool, std::vector< std::string > > get_leader_ignores_keep() const =0
#define lua_isnoneornil(L, n)
Definition: lua.h:359
static int cfun_ai_get_passive_leader_shares_keep(lua_State *L)
Definition: core.cpp:480
LUA_API void lua_pushlightuserdata(lua_State *L, void *p)
Definition: lapi.cpp:565
static void push_move_map(lua_State *L, const move_map &m)
Definition: core.cpp:679
double avg_damage_taken
The average hitpoints damage taken.
Definition: contexts.hpp:103
virtual const move_map & get_srcdst() const =0
LUA_API void lua_createtable(lua_State *L, int narray, int nrec)
Definition: lapi.cpp:684
#define lua_pushcfunction(L, f)
Definition: lua.h:350
void get_arguments(config &) const
Definition: core.cpp:69
static ai::readonly_context & get_readonly_context(lua_State *L)
Definition: core.cpp:127
lua_unit * luaW_pushunit(lua_State *L, Args... args)
Definition: lua_unit.hpp:115
virtual void set_src_dst_enemy_valid_lua()=0
unit_iterator end()
Definition: map.hpp:429
virtual bool is_src_dst_valid_lua() const =0
virtual boost::variant< bool, std::vector< std::string > > get_passive_leader() const =0
static int cfun_ai_execute_stopunit_attacks(lua_State *L)
Definition: core.cpp:258
std::shared_ptr< stopunit_result > stopunit_result_ptr
Definition: game_info.hpp:86
virtual const aspect_map & get_aspects() const =0
virtual const unit_map & units() const override
Definition: game_board.hpp:114
virtual void set_src_dst_valid_lua()=0
void luaW_pushconfig(lua_State *L, const config &cfg)
Converts a config object to a Lua table pushed at the top of the stack.
Definition: lua_common.cpp:730
LUA_API void lua_settop(lua_State *L, int idx)
Definition: lapi.cpp:172
bool luaW_pcall(lua_State *L, int nArgs, int nRets, bool allow_wml_error)
Calls a Lua function stored below its nArgs arguments at the top of the stack.
This class represents a single unit of a specific type.
Definition: unit.hpp:129
int luaW_type_error(lua_State *L, int narg, const char *tname)
virtual std::string get_grouping() const =0
LUA_API void lua_pushboolean(lua_State *L, int b)
Definition: lapi.cpp:557
LUA_API int lua_rawgeti(lua_State *L, int idx, lua_Integer n)
Definition: lapi.cpp:658
static int transform_ai_action(lua_State *L, ai::action_result_ptr action_result)
Definition: core.cpp:137
double avg_damage_inflicted
The average hitpoints damage inflicted.
Definition: contexts.hpp:98
Managing the AI-Game interaction - AI actions and their results.
virtual config get_leader_goal() const =0
static int cfun_ai_get_scout_village_targeting(lua_State *L)
Definition: core.cpp:512
LUA_API void lua_rawseti(lua_State *L, int idx, lua_Integer n)
Definition: lapi.cpp:817
static int cfun_ai_execute_stopunit_moves(lua_State *L)
Definition: core.cpp:253
static int cfun_ai_execute_recruit(lua_State *L)
Definition: core.cpp:287
LUA_API int lua_gettop(lua_State *L)
Definition: lapi.cpp:167
static int cfun_ai_get_avoid(lua_State *L)
Definition: core.cpp:395
virtual bool is_dst_src_enemy_valid_lua() const =0
static int cfun_ai_check_attack(lua_State *L)
Definition: core.cpp:239
static int cfun_ai_execute_recall(lua_State *L)
Definition: core.cpp:311
#define lua_remove(L, idx)
Definition: lua.h:371
LUA_API int lua_getglobal(lua_State *L, const char *name)
Definition: lapi.cpp:605
std::shared_ptr< move_result > move_result_ptr
Definition: game_info.hpp:84
map_location target
Definition: contexts.hpp:85
LUA_API void lua_settable(lua_State *L, int idx)
Definition: lapi.cpp:766
static int cfun_ai_get_dstsrc(lua_State *L)
Definition: core.cpp:718
#define lua_tointeger(L, i)
Definition: lua.h:342
double vulnerability
The vulnerability is the power projection of enemy units onto the hex we&#39;re standing on...
Definition: contexts.hpp:122
virtual void set_dst_src_valid_lua()=0
virtual bool get_simple_targeting() const =0
static int cfun_ai_get_village_value(lua_State *L)
Definition: core.cpp:536
static lua_ai_context * create(lua_State *L, char const *code, engine_lua *engine)
Definition: core.cpp:995
LUA_API int lua_rawget(lua_State *L, int idx)
Definition: lapi.cpp:647
void set_wml_x(int v)
Definition: location.hpp:160
virtual bool get_support_villages() const =0
virtual const move_map & get_enemy_dstsrc() const =0
static int cfun_attack_rating(lua_State *L)
Definition: core.cpp:553
#define ERR_LUA
Definition: core.cpp:54
#define lua_tonumber(L, i)
Definition: lua.h:341
std::shared_ptr< recruit_result > recruit_result_ptr
Definition: game_info.hpp:83
virtual const move_map & get_enemy_srcdst() const =0
static int cfun_ai_get_srcdst(lua_State *L)
Definition: core.cpp:726
LUA_API int lua_isuserdata(lua_State *L, int idx)
Definition: lapi.cpp:289
virtual double get_village_value() const =0
LUA_API void lua_pushcclosure(lua_State *L, lua_CFunction fn, int n)
Definition: lapi.cpp:532
double resources_used
The sum of the values of units used in the attack.
Definition: contexts.hpp:106
double chance_to_kill
Estimated % chance to kill the unit.
Definition: contexts.hpp:95
static int cfun_ai_recalculate_move_maps(lua_State *L)
Definition: core.cpp:778
static config unit_name(const unit *u)
Definition: reports.cpp:152
virtual const attacks_vector & get_attacks() const =0
void lua_push(lua_State *L, const T &val)
Definition: push_check.hpp:371
map_location luaW_checklocation(lua_State *L, int index)
Converts an optional table or pair of integers to a map location object.
Definition: lua_common.cpp:722
std::shared_ptr< attack_result > attack_result_ptr
Definition: game_info.hpp:81
static int cfun_ai_get_leader_goal(lua_State *L)
Definition: core.cpp:430
LUA_API int lua_absindex(lua_State *L, int idx)
Definition: lapi.cpp:160
Lua object(value) wrapper implementation.
static int cfun_ai_execute_attack(lua_State *L)
Definition: core.cpp:234
static int cfun_ai_get_support_villages(lua_State *L)
Definition: core.cpp:528
static int ai_recall(lua_State *L, bool exec)
Definition: core.cpp:297
#define lua_pop(L, n)
Definition: lua.h:344
std::shared_ptr< aspect > aspect_ptr
Definition: game_info.hpp:94
double target_value
The value of the unit being targeted.
Definition: contexts.hpp:89
std::multimap< map_location, map_location > move_map
The standard way in which a map of possible moves is recorded.
Definition: game_info.hpp:42
std::vector< attack_analysis > attacks_vector
Definition: game_info.hpp:50
static int cfun_ai_get_villages_per_scout(lua_State *L)
Definition: core.cpp:544
const std::vector< std::string > get_advancements(const unit_map::const_iterator &unit) const
void get_persistent_data(config &) const
Definition: core.cpp:95
static char const aisKey[]
Definition: core.cpp:56
#define lua_upvalueindex(i)
Definition: lua.h:43
static int cfun_ai_get_leader_value(lua_State *L)
Definition: core.cpp:455
void handle(const config &cfg, const config &filter_own, bool read_only, lua_object_ptr l_obj)
Definition: core.cpp:1118
A small explanation about what&#39;s going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:59
void set_arguments(const config &)
Definition: core.cpp:82
LUALIB_API int luaL_argerror(lua_State *L, int arg, const char *extramsg)
Definition: lauxlib.cpp:164
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:86
static recall_result_ptr execute_recall_action(side_number side, bool execute, const std::string &unit_id, const map_location &where, const map_location &from)
Ask the game to recall a unit for us on specified location.
Definition: actions.cpp:1023
std::shared_ptr< recall_result > recall_result_ptr
Definition: game_info.hpp:82
void set_persistent_data(const config &)
Definition: core.cpp:108
bool was_readonly
Definition: core.hpp:61
static int cfun_ai_is_src_dst_valid(lua_State *L)
Definition: core.cpp:764
LUA_API int lua_isstring(lua_State *L, int idx)
Definition: lapi.cpp:283
bool luaW_toboolean(lua_State *L, int n)
Definition: lua_common.cpp:890
virtual const terrain_filter & get_avoid() const =0
static int cfun_ai_get_leader_ignores_keep(lua_State *L)
Definition: core.cpp:438
LUALIB_API int luaL_loadbufferx(lua_State *L, const char *buff, size_t size, const char *name, const char *mode)
Definition: lauxlib.cpp:755
unit * luaW_tounit(lua_State *L, int index, bool only_on_map)
Converts a Lua value to a unit pointer.
Definition: lua_unit.cpp:145
double alternative_terrain_quality
The weighted average of the % defense of the best possible terrain that the attacking units could rea...
Definition: contexts.hpp:116
Proxy table for the AI context.
Definition: core.hpp:33
static int ai_move(lua_State *L, bool exec, bool remove_movement)
Definition: core.cpp:176
static lua_ai_action_handler * create(lua_State *L, char const *code, lua_ai_context &context)
Definition: core.cpp:1037
static int ai_recruit(lua_State *L, bool exec)
Definition: core.cpp:273
static int cfun_ai_get_aggression(lua_State *L)
Definition: core.cpp:369
static void push_attack_analysis(lua_State *L, const attack_analysis &)
Definition: core.cpp:599
lua_ai_load(lua_ai_context &ctx, bool read_only)
Definition: core.cpp:1063
static int impl_ai_aspect_get(lua_State *L)
Definition: core.cpp:796
game_board * gameboard
Definition: resources.cpp:20
static int cfun_ai_get_enemy_dstsrc(lua_State *L)
Definition: core.cpp:734
static int cfun_ai_get_attacks(lua_State *L)
Definition: core.cpp:377
LUA_API const char * lua_pushlstring(lua_State *L, const char *s, size_t len)
Definition: lapi.cpp:479
static int refcount
Definition: core.hpp:59
static int cfun_ai_is_src_dst_enemy_valid(lua_State *L)
Definition: core.cpp:771
LUA_API void lua_setglobal(lua_State *L, const char *name)
Definition: lapi.cpp:759
LUA_API int lua_setmetatable(lua_State *L, int objindex)
Definition: lapi.cpp:846
virtual int get_villages_per_scout() const =0
static int cfun_ai_get_simple_targeting(lua_State *L)
Definition: core.cpp:520
static int cfun_ai_execute_stopunit_all(lua_State *L)
Definition: core.cpp:263
static void push_movements(lua_State *L, const std::vector< std::pair< map_location, map_location > > &moves)
Definition: core.cpp:573
static int cfun_ai_get_grouping(lua_State *L)
Definition: core.cpp:414
static int cfun_ai_check_stopunit(lua_State *L)
Definition: core.cpp:268
#define lua_newtable(L)
Definition: lua.h:346
LUA_API void lua_pushnil(lua_State *L)
Definition: lapi.cpp:450
LUA_API void lua_pushnumber(lua_State *L, lua_Number n)
Definition: lapi.cpp:458
Encapsulates the map of the game.
Definition: location.hpp:42
bool uses_leader
Is true if this attack sequence makes use of the leader.
Definition: contexts.hpp:128
#define lua_isboolean(L, n)
Definition: lua.h:356
static int cfun_ai_execute_move_full(lua_State *L)
Definition: core.cpp:189
aspect & find_active()
Definition: aspect.hpp:366
bool luaW_toconfig(lua_State *L, int index, config &cfg)
Converts an optional table or vconfig to a config object.
Definition: lua_common.cpp:742
void push_ai_table()
Definition: core.cpp:132
static int cfun_ai_get_targets(lua_State *L)
Definition: core.cpp:329
static int cfun_ai_check_recruit(lua_State *L)
Definition: core.cpp:292
LUA_API void * lua_touserdata(lua_State *L, int idx)
Definition: lapi.cpp:413
static int cfun_ai_is_dst_src_valid(lua_State *L)
Definition: core.cpp:750
static void init(lua_State *L)
Definition: core.cpp:62
std::size_t i
Definition: function.cpp:933
virtual boost::variant< bool, std::vector< std::string > > get_passive_leader_shares_keep() const =0
LUA_API void lua_rawset(lua_State *L, int idx)
Definition: lapi.cpp:801
lua_ai_context(lua_State *l, int num, int side)
Definition: core.hpp:39
mock_party p
virtual const team & current_team() const =0
virtual void set_dst_src_enemy_valid_lua()=0
virtual const map_location & suitable_keep(const map_location &leader_location, const pathfind::paths &leader_paths) const =0
get most suitable keep for leader - nearest free that can be reached in 1 turn, if none - return near...
virtual bool is_src_dst_enemy_valid_lua() const =0
std::vector< std::pair< map_location, map_location > > movements
Definition: contexts.hpp:86
static attack_result_ptr execute_attack_action(side_number side, bool execute, const map_location &attacker_loc, const map_location &defender_loc, int attacker_weapon, double aggression)
Ask the game to attack an enemy defender using our unit attacker from attackers current location...
Definition: actions.cpp:999
static int cfun_ai_recalculate_move_maps_enemy(lua_State *L)
Definition: core.cpp:784
double avg_losses
The value on average, of units lost in the combat.
Definition: contexts.hpp:92
static recruit_result_ptr execute_recruit_action(side_number side, bool execute, const std::string &unit_name, const map_location &where, const map_location &from)
Ask the game to recruit a unit for us on specified location.
Definition: actions.cpp:1034
#define lua_tostring(L, i)
Definition: lua.h:366
virtual const std::vector< std::string > get_recruitment_pattern() const =0
double rating(double aggression, const readonly_context &ai_obj) const
Definition: attack.cpp:270
static int impl_ai_aspect_set(lua_State *L)
Definition: core.cpp:858
LUA_API void lua_pushvalue(lua_State *L, int idx)
Definition: lapi.cpp:237
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:71
LUA_API int lua_isnumber(lua_State *L, int idx)
Definition: lapi.cpp:276
static int ai_attack(lua_State *L, bool exec)
Definition: core.cpp:204
virtual double get_leader_value() const =0
Aspect: attacks.
Proxy class for calling AI action handlers defined in Lua.
Definition: core.hpp:69
static stopunit_result_ptr execute_stopunit_action(side_number side, bool execute, const map_location &unit_location, bool remove_movement, bool remove_attacks)
Ask the game to remove unit movements and/or attack.
Definition: actions.cpp:1045
static int cfun_ai_execute_move_partial(lua_State *L)
Definition: core.cpp:194
static int cfun_ai_check_move(lua_State *L)
Definition: core.cpp:199
LUA_API size_t lua_rawlen(lua_State *L, int idx)
Definition: lapi.cpp:392
#define LUA_REGISTRYINDEX
Definition: lua.h:42
virtual ai_context_ptr get_ai_context()
Definition: engine.cpp:133
static int impl_ai_get(lua_State *L)
Definition: core.cpp:864
LUA_API int lua_error(lua_State *L)
Definition: lapi.cpp:1114
std::map< std::string, aspect_ptr > aspect_map
Definition: game_info.hpp:103
static lg::log_domain log_ai_engine_lua("ai/engine/lua")
virtual const move_map & get_dstsrc() const =0
virtual double get_aggression() const =0
void luaW_pushlocation(lua_State *L, const map_location &ml)
Converts a map location object to a Lua table pushed at the top of the stack.
Definition: lua_common.cpp:662
const map_location & get_location() const
The current map location this unit is at.
Definition: unit.hpp:1336
readonly_context & get_readonly_context()
Definition: engine.cpp:146
Composite AI contexts.
Standard logging facilities (interface).
virtual side_number get_side() const =0
Get the side number.
Object which contains all the possible locations a unit can move to, with associated best routes to t...
Definition: pathfind.hpp:70
static const map_location & null_location()
Definition: location.hpp:85
virtual void recalculate_move_maps() const =0
virtual double get_leader_aggression() const =0
static size_t generate_and_push_ai_state(lua_State *L, ai::engine_lua *engine)
Definition: core.cpp:981
static int cfun_ai_get_caution(lua_State *L)
Definition: core.cpp:406
bool is_surrounded
Is true if the units involved in this attack sequence are surrounded.
Definition: contexts.hpp:131
static int cfun_ai_get_passive_leader(lua_State *L)
Definition: core.cpp:463
virtual double get_scout_village_targeting() const =0
#define DEPRECATED_ASPECT_MESSAGE(name)
Definition: core.cpp:365
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:68
static void generate_and_push_ai_table(lua_State *L, ai::engine_lua *engine)
Definition: core.cpp:971
LUA_API int lua_getfield(lua_State *L, int idx, const char *k)
Definition: lapi.cpp:622
LUA AI Support engine - creating specific ai components from config.
virtual void recalculate_move_maps_enemy() const =0
virtual bool is_dst_src_valid_lua() const =0
LUA_API void lua_pushinteger(lua_State *L, lua_Integer n)
Definition: lapi.cpp:466
This module contains various pathfinding functions and utilities.
static int cfun_ai_get_leader_aggression(lua_State *L)
Definition: core.cpp:422
std::string::const_iterator iterator
Definition: tokenizer.hpp:24
virtual std::vector< target > find_targets(const move_map &enemy_dstsrc)=0
LUA_API const char * lua_pushstring(lua_State *L, const char *s)
Definition: lapi.cpp:491
typesafe_aspect< T > * try_aspect_as(aspect_ptr p)
Definition: core.cpp:791
LUA_API void lua_setfield(lua_State *L, int idx, const char *k)
Definition: lapi.cpp:777
static int cfun_ai_get_enemy_srcdst(lua_State *L)
Definition: core.cpp:742
bool empty() const
Definition: config.cpp:884
void update_state()
Definition: core.cpp:1016
static int cfun_ai_get_suitable_keep(lua_State *L)
Definition: core.cpp:151
static move_result_ptr execute_move_action(side_number side, bool execute, const map_location &from, const map_location &to, bool remove_movement, bool unreach_is_ok=false)
Ask the game to move our unit from location &#39;from&#39; to location &#39;to&#39;, optionally - doing a partial mov...
Definition: actions.cpp:1011
virtual double get_caution() const =0
static int cfun_ai_is_dst_src_enemy_valid(lua_State *L)
Definition: core.cpp:757
static int cfun_ai_get_recruitment_pattern(lua_State *L)
Definition: core.cpp:497
static int cfun_ai_fallback_human(lua_State *)
Definition: core.cpp:321
static ai::engine_lua & get_engine(lua_State *L)
Definition: core.cpp:121
static const std::string & get_error_name(int error_code)
get human-readable name of the error by code.
Definition: actions.cpp:1066
std::shared_ptr< lua_object_base > lua_object_ptr
Definition: core.hpp:27
static int cfun_ai_check_recall(lua_State *L)
Definition: core.cpp:316
#define luaL_checkstring(L, n)
Definition: lauxlib.h:124