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