The Battle for Wesnoth  1.15.12+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 
329 {
330  move_map enemy_dst_src = get_readonly_context(L).get_enemy_dstsrc();
331  std::vector<target> targets = get_engine(L).get_ai_context()->find_targets(enemy_dst_src);
332  int i = 1;
333 
334  lua_createtable(L, 0, 0);
335  for (std::vector<target>::iterator it = targets.begin(); it != targets.end(); ++it)
336  {
337  lua_pushinteger(L, i);
338 
339  //to factor out
340  lua_createtable(L, 3, 0);
341 
342  lua_pushstring(L, "type");
343  lua_pushstring(L, it->type.to_string().c_str());
344  lua_rawset(L, -3);
345 
346  lua_pushstring(L, "loc");
347  luaW_pushlocation(L, it->loc);
348  lua_rawset(L, -3);
349 
350  lua_pushstring(L, "value");
351  lua_pushnumber(L, it->value);
352  lua_rawset(L, -3);
353 
354  lua_rawset(L, -3);
355  ++i;
356  }
357  return 1;
358 }
359 
360 // Note: If adding new uses of this macro, it will be necessary to either remove the old ones
361 // (and the things so deprecated) OR add a version parameter to the macro.
362 // Also note that the name MUST be a string literal.
363 #define DEPRECATED_ASPECT_MESSAGE(name) \
364  deprecated_message("ai.get_" name, DEP_LEVEL::PREEMPTIVE, {1, 15, 0}, "Use ai.aspects." name " instead")
365 
366 // Aspect section
368 {
369  DEPRECATED_ASPECT_MESSAGE("aggression");
370  double aggression = get_readonly_context(L).get_aggression();
371  lua_pushnumber(L, aggression);
372  return 1;
373 }
374 
376 {
377  // Unlike the other aspect fetchers, this one is not deprecated!
378  // This is because ai.aspects.attacks returns the viable units but this returns a full attack analysis
380  lua_createtable(L, attacks.size(), 0);
381  int table_index = lua_gettop(L);
382 
383  ai::attacks_vector::const_iterator it = attacks.begin();
384  for (int i = 1; it != attacks.end(); ++it, ++i)
385  {
386  push_attack_analysis(L, *it);
387 
388  lua_rawseti(L, table_index, i);
389  }
390  return 1;
391 }
392 
394 {
395  DEPRECATED_ASPECT_MESSAGE("avoid");
396  std::set<map_location> locs;
397  terrain_filter avoid = get_readonly_context(L).get_avoid();
398  avoid.get_locations(locs);
399  lua_push(L, locs);
400 
401  return 1;
402 }
403 
405 {
406  DEPRECATED_ASPECT_MESSAGE("caution");
407  double caution = get_readonly_context(L).get_caution();
408  lua_pushnumber(L, caution);
409  return 1;
410 }
411 
413 {
414  DEPRECATED_ASPECT_MESSAGE("grouping");
415  std::string grouping = get_readonly_context(L).get_grouping();
416  lua_pushstring(L, grouping.c_str());
417  return 1;
418 }
419 
421 {
422  DEPRECATED_ASPECT_MESSAGE("leader_aggression");
423  double leader_aggression = get_readonly_context(L).get_leader_aggression();
424  lua_pushnumber(L, leader_aggression);
425  return 1;
426 }
427 
429 {
430  DEPRECATED_ASPECT_MESSAGE("leader_goal");
432  luaW_pushconfig(L, goal);
433  return 1;
434 }
435 
436 namespace
437 {
438 // TODO: name this something better
439 void visit_helper(lua_State* L, const utils::variant<bool, std::vector<std::string>>& input)
440 {
441  utils::visit(
442  [L](const auto& v) {
443  if constexpr(utils::decayed_is_same<bool, decltype(v)>) {
444  lua_pushboolean(L, v);
445  } else {
446  lua_createtable(L, v.size(), 0);
447  for(const std::string& str : v) {
448  lua_pushlstring(L, str.c_str(), str.size());
449  lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
450  }
451  }
452  },
453  input);
454 }
455 } // namespace
456 
458 {
459  DEPRECATED_ASPECT_MESSAGE("leader_ignores_keep");
460  visit_helper(L, get_readonly_context(L).get_leader_ignores_keep());
461  return 1;
462 }
463 
465 {
466  DEPRECATED_ASPECT_MESSAGE("leader_value");
467  double leader_value = get_readonly_context(L).get_leader_value();
468  lua_pushnumber(L, leader_value);
469  return 1;
470 }
471 
473 {
474  DEPRECATED_ASPECT_MESSAGE("passive_leader");
475  visit_helper(L, get_readonly_context(L).get_passive_leader());
476  return 1;
477 }
478 
480 {
481  DEPRECATED_ASPECT_MESSAGE("passive_leader_shares_keep");
482  visit_helper(L, get_readonly_context(L).get_passive_leader_shares_keep());
483  return 1;
484 }
485 
487 {
488  DEPRECATED_ASPECT_MESSAGE("recruitment_pattern");
489  std::vector<std::string> recruiting = get_readonly_context(L).get_recruitment_pattern();
490  int size = recruiting.size();
491  lua_createtable(L, size, 0); // create an empty table with predefined size
492  for (int i = 0; i < size; ++i)
493  {
494  lua_pushinteger(L, i + 1); // Indexing in Lua starts from 1
495  lua_pushstring(L, recruiting[i].c_str());
496  lua_settable(L, -3);
497  }
498  return 1;
499 }
500 
502 {
503  DEPRECATED_ASPECT_MESSAGE("scout_village_targeting");
504  double scout_village_targeting = get_readonly_context(L).get_scout_village_targeting();
505  lua_pushnumber(L, scout_village_targeting);
506  return 1;
507 }
508 
510 {
511  DEPRECATED_ASPECT_MESSAGE("simple_targeting");
512  bool simple_targeting = get_readonly_context(L).get_simple_targeting();
513  lua_pushboolean(L, simple_targeting);
514  return 1;
515 }
516 
518 {
519  DEPRECATED_ASPECT_MESSAGE("support_villages");
520  bool support_villages = get_readonly_context(L).get_support_villages();
521  lua_pushboolean(L, support_villages);
522  return 1;
523 }
524 
526 {
527  DEPRECATED_ASPECT_MESSAGE("village_value");
528  double village_value = get_readonly_context(L).get_village_value();
529  lua_pushnumber(L, village_value);
530  return 1;
531 }
532 
534 {
535  DEPRECATED_ASPECT_MESSAGE("villages_per_scout");
536  int villages_per_scout = get_readonly_context(L).get_villages_per_scout();
537  lua_pushnumber(L, villages_per_scout);
538  return 1;
539 }
540 // End of aspect section
541 
543 {
544  int top = lua_gettop(L);
545  // the attack_analysis table should be on top of the stack
546  lua_getfield(L, -1, "att_ptr"); // [-2: attack_analysis; -1: pointer to attack_analysis object in c++]
547  // now the pointer to our attack_analysis C++ object is on top
548  const attack_analysis* aa_ptr = static_cast< attack_analysis * >(lua_touserdata(L, -1));
549 
550  //[-2: attack_analysis; -1: pointer to attack_analysis object in c++]
551 
552  double aggression = get_readonly_context(L).get_aggression();
553 
554  double rating = aa_ptr->rating(aggression, get_readonly_context(L));
555 
556  lua_settop(L, top);
557 
558  lua_pushnumber(L, rating);
559  return 1;
560 }
561 
562 static void push_movements(lua_State *L, const std::vector< std::pair < map_location, map_location > > & moves)
563 {
564  lua_createtable(L, moves.size(), 0);
565 
566  int table_index = lua_gettop(L);
567 
568  std::vector< std::pair < map_location, map_location > >::const_iterator move = moves.begin();
569 
570  for (int i = 1; move != moves.end(); ++move, ++i)
571  {
572  lua_createtable(L, 2, 0); // Creating a table for a pair of map_location's
573 
574  lua_pushstring(L, "src");
575  luaW_pushlocation(L, move->first);
576  lua_rawset(L, -3);
577 
578  lua_pushstring(L, "dst");
579  luaW_pushlocation(L, move->second);
580  lua_rawset(L, -3);
581 
582  lua_rawseti(L, table_index, i); // setting the pair as an element of the movements table
583  }
584 
585 }
586 
588 {
589  lua_newtable(L);
590 
591  // Pushing a pointer to the current object
592  lua_pushstring(L, "att_ptr");
593  lua_pushlightuserdata(L, const_cast<attack_analysis*>(&aa));
594  lua_rawset(L, -3);
595 
596  // Registering callback function for the rating method
597  lua_pushstring(L, "rating");
600  lua_rawset(L, -3);
601 
602  lua_pushstring(L, "movements");
603  push_movements(L, aa.movements);
604  lua_rawset(L, -3);
605 
606  lua_pushstring(L, "target");
607  luaW_pushlocation(L, aa.target);
608  lua_rawset(L, -3);
609 
610  lua_pushstring(L, "target_value");
612  lua_rawset(L, -3);
613 
614  lua_pushstring(L, "avg_losses");
615  lua_pushnumber(L, aa.avg_losses);
616  lua_rawset(L, -3);
617 
618  lua_pushstring(L, "chance_to_kill");
620  lua_rawset(L, -3);
621 
622  lua_pushstring(L, "avg_damage_inflicted");
624  lua_rawset(L, -3);
625 
626  lua_pushstring(L, "target_starting_damage");
628  lua_rawset(L, -3);
629 
630  lua_pushstring(L, "avg_damage_taken");
632  lua_rawset(L, -3);
633 
634  lua_pushstring(L, "resources_used");
636  lua_rawset(L, -3);
637 
638  lua_pushstring(L, "terrain_quality");
640  lua_rawset(L, -3);
641 
642  lua_pushstring(L, "alternative_terrain_quality");
644  lua_rawset(L, -3);
645 
646  lua_pushstring(L, "vulnerability");
648  lua_rawset(L, -3);
649 
650  lua_pushstring(L, "support");
651  lua_pushnumber(L, aa.support);
652  lua_rawset(L, -3);
653 
654  lua_pushstring(L, "leader_threat");
656  lua_rawset(L, -3);
657 
658  lua_pushstring(L, "uses_leader");
660  lua_rawset(L, -3);
661 
662  lua_pushstring(L, "is_surrounded");
664  lua_rawset(L, -3);
665 }
666 
667 static void push_move_map(lua_State *L, const move_map& m)
668 {
669  lua_createtable(L, 0, 0); // the main table
670 
671  if (m.empty())
672  {
673  return;
674  }
675 
676  move_map::const_iterator it = m.begin();
677 
678  int index = 1;
679 
681 
682  do
683  {
684  map_location key = it->first;
685  lua_pushinteger(L, lhash(key));
686 
687  lua_createtable(L, 0, 0);
688 
689  while (key == it->first) {
690 
691  luaW_pushlocation(L, it->second);
692  lua_rawseti(L, -2, index);
693 
694  ++index;
695  ++it;
696 
697  }
698 
699  lua_settable(L, -3);
700 
701  index = 1;
702 
703  } while (it != m.end());
704 }
705 
707 {
710  push_move_map(L, dst_src);
711  return 1;
712 }
713 
715 {
718  push_move_map(L, src_dst);
719  return 1;
720 }
721 
723 {
724  move_map enemy_dst_src = get_readonly_context(L).get_enemy_dstsrc();
726  push_move_map(L, enemy_dst_src);
727  return 1;
728 }
729 
731 {
732  move_map enemy_src_dst = get_readonly_context(L).get_enemy_srcdst();
734  push_move_map(L, enemy_src_dst);
735  return 1;
736 }
737 
739 {
740  bool valid = get_readonly_context(L).is_dst_src_valid_lua();
741  lua_pushboolean(L, valid);
742  return 1;
743 }
744 
746 {
748  lua_pushboolean(L, valid);
749  return 1;
750 }
751 
753 {
754  bool valid = get_readonly_context(L).is_src_dst_valid_lua();
755  lua_pushboolean(L, valid);
756  return 1;
757 }
758 
760 {
762  lua_pushboolean(L, valid);
763  return 1;
764 }
765 
767 {
769  return 1;
770 }
771 
773 {
775  return 1;
776 }
777 
778 template<typename T>
780 {
781  return std::dynamic_pointer_cast<typesafe_aspect<T> >(p).get();
782 }
783 
785 {
786  const aspect_map& aspects = get_engine(L).get_readonly_context().get_aspects();
787  aspect_map::const_iterator iter = aspects.find(luaL_checkstring(L, 2));
788  if(iter == aspects.end()) {
789  return 0;
790  }
791 
792  // A few aspects require special delicate handling...
793  if(typesafe_aspect<attacks_vector>* aspect_as_attacks_vector = try_aspect_as<attacks_vector>(iter->second)) {
795  aspect_attacks_base* real_aspect = dynamic_cast<aspect_attacks_base*>(aspect_as_attacks_vector);
796  while(real_aspect == nullptr) {
797  // It's probably a composite aspect, so find the active facet
798  composite_aspect<attacks_vector>& composite = dynamic_cast<composite_aspect<attacks_vector>&>(*aspect_as_attacks_vector);
799  aspect_as_attacks_vector = &dynamic_cast<typesafe_aspect<attacks_vector>&>(composite.find_active());
800  real_aspect = dynamic_cast<aspect_attacks_base*>(aspect_as_attacks_vector);
801  }
802  int my_side = get_engine(L).get_readonly_context().get_side();
803  std::vector<unit_const_ptr> attackers, enemies;
804  for(unit_map::const_iterator u = resources::gameboard->units().begin(); u != resources::gameboard->units().end(); ++u) {
805  if(!u.valid()) {
806  continue;
807  }
808  if(u->side() == my_side && real_aspect->is_allowed_attacker(*u)) {
809  attackers.push_back(u.get_shared_ptr());
810  } else if(u->side() != my_side && real_aspect->is_allowed_enemy(*u)) {
811  enemies.push_back(u.get_shared_ptr());
812  }
813  }
814  lua_createtable(L, 0, 2);
815  lua_createtable(L, attackers.size(), 0);
816  for(size_t i = 0; i < attackers.size(); i++) {
817  luaW_pushunit(L, attackers[i]->underlying_id());
818  lua_rawseti(L, -2, i + 1);
819  }
820  lua_setfield(L, -2, "own");
821  lua_createtable(L, enemies.size(), 0);
822  for(size_t i = 0; i < enemies.size(); i++) {
823  luaW_pushunit(L, enemies[i]->underlying_id());
824  lua_rawseti(L, -2, i + 1);
825  }
826  lua_setfield(L, -2, "enemy");
827  } else if(typesafe_aspect<unit_advancements_aspect>* aspect_as_unit_advancements_aspects = try_aspect_as<unit_advancements_aspect>(iter->second)) {
828  const unit_advancements_aspect& val = aspect_as_unit_advancements_aspects->get();
829  int my_side = get_engine(L).get_readonly_context().get_side();
830  lua_newtable(L);
832  for (unit_map::const_iterator u = resources::gameboard->units().begin(); u != resources::gameboard->units().end(); ++u) {
833  if (!u.valid() || u->side() != my_side) {
834  continue;
835  }
836  lua_pushinteger(L, lhash(u->get_location()));
837  lua_push(L, val.get_advancements(u));
838  lua_settable(L, -3);
839  }
840  } else {
841  iter->second->get_lua(L);
842  }
843  return 1;
844 }
845 
847 {
848  lua_pushstring(L, "attempted to write to the ai.aspects table, which is read-only");
849  return lua_error(L);
850 }
851 
852 static int impl_ai_get(lua_State* L)
853 {
854  if(!lua_isstring(L,2)) {
855  return 0;
856  }
858  std::string m = lua_tostring(L,2);
859  if(m == "side") {
861  return 1;
862  }
863  if(m == "aspects") {
864  lua_newtable(L); // [-1: Aspects table]
865  lua_newtable(L); // [-1: Aspects metatable -2: Aspects table]
866  lua_pushlightuserdata(L, &engine); // [-1: Engine -2: Aspects mt -3: Aspects table]
867  lua_pushcclosure(L, &impl_ai_aspect_get, 1); // [-1: Metafunction -2: Aspects mt -3: Aspects table]
868  lua_setfield(L, -2, "__index"); // [-1: Aspects metatable -2: Aspects table]
869  lua_pushcfunction(L, &impl_ai_aspect_set); // [-1: Metafunction -2: Aspects mt -3: Aspects table]
870  lua_setfield(L, -2, "__newindex"); // [-1: Aspects metatable -2: Aspects table]
871  lua_setmetatable(L, -2); // [-1: Aspects table]
872  return 1;
873  }
874  static luaL_Reg const callbacks[] = {
875  // Move maps
876  { "get_new_dst_src", &cfun_ai_get_dstsrc },
877  { "get_new_src_dst", &cfun_ai_get_srcdst },
878  { "get_new_enemy_dst_src", &cfun_ai_get_enemy_dstsrc },
879  { "get_new_enemy_src_dst", &cfun_ai_get_enemy_srcdst },
880  { "recalculate_move_maps", &cfun_ai_recalculate_move_maps },
881  { "recalculate_enemy_move_maps", &cfun_ai_recalculate_move_maps_enemy },
882  // End of move maps
883  // Goals and targets
884  { "get_targets", &cfun_ai_get_targets },
885  // End of G & T
886  // Aspects
887  { "get_aggression", &cfun_ai_get_aggression },
888  { "get_avoid", &cfun_ai_get_avoid },
889  { "get_attacks", &cfun_ai_get_attacks },
890  { "get_caution", &cfun_ai_get_caution },
891  { "get_grouping", &cfun_ai_get_grouping },
892  { "get_leader_aggression", &cfun_ai_get_leader_aggression },
893  { "get_leader_goal", &cfun_ai_get_leader_goal },
894  { "get_leader_ignores_keep", &cfun_ai_get_leader_ignores_keep },
895  { "get_leader_value", &cfun_ai_get_leader_value },
896  { "get_passive_leader", &cfun_ai_get_passive_leader },
897  { "get_passive_leader_shares_keep", &cfun_ai_get_passive_leader_shares_keep },
898  { "get_recruitment_pattern", &cfun_ai_get_recruitment_pattern },
899  { "get_scout_village_targeting", &cfun_ai_get_scout_village_targeting },
900  { "get_simple_targeting", &cfun_ai_get_simple_targeting },
901  { "get_support_villages", &cfun_ai_get_support_villages },
902  { "get_village_value", &cfun_ai_get_village_value },
903  { "get_villages_per_scout", &cfun_ai_get_villages_per_scout },
904  // End of aspects
905  // Validation/cache functions
906  { "is_dst_src_valid", &cfun_ai_is_dst_src_valid },
907  { "is_enemy_dst_src_valid", &cfun_ai_is_dst_src_enemy_valid },
908  { "is_src_dst_valid", &cfun_ai_is_src_dst_valid },
909  { "is_enemy_src_dst_valid", &cfun_ai_is_src_dst_enemy_valid },
910  // End of validation functions
911  { "suitable_keep", &cfun_ai_get_suitable_keep },
912  { "check_recall", &cfun_ai_check_recall },
913  { "check_move", &cfun_ai_check_move },
914  { "check_stopunit", &cfun_ai_check_stopunit },
915  { "check_attack", &cfun_ai_check_attack },
916  { "check_recruit", &cfun_ai_check_recruit },
917  //{ "",},
918  //{ "",},
919  { nullptr, nullptr } };
920  for (const luaL_Reg* p = callbacks; p->name; ++p) {
921  if(m == p->name) {
922  lua_pushlightuserdata(L, &engine); // [-1: engine ...]
923  lua_pushcclosure(L, p->func, 1); // [-1: function ...]
924  // Store the function so that __index doesn't need to be called next time
925  lua_pushstring(L, p->name); // [-1: name -2: function ...]
926  lua_pushvalue(L, -2); // [-1: function -2: name -3: function ...]
927  lua_rawset(L, 1); // [-1: function ...]
928  return 1;
929  }
930  }
931  lua_pushstring(L, "read_only");
932  lua_rawget(L, 1);
933  bool read_only = luaW_toboolean(L, -1);
934  lua_pop(L, 1);
935  if(read_only) {
936  return 0;
937  }
938  static luaL_Reg const mutating_callbacks[] = {
939  { "attack", &cfun_ai_execute_attack },
940  { "move", &cfun_ai_execute_move_partial },
941  { "move_full", &cfun_ai_execute_move_full },
942  { "recall", &cfun_ai_execute_recall },
943  { "recruit", &cfun_ai_execute_recruit },
944  { "stopunit_all", &cfun_ai_execute_stopunit_all },
945  { "stopunit_attacks", &cfun_ai_execute_stopunit_attacks },
946  { "stopunit_moves", &cfun_ai_execute_stopunit_moves },
947  { "fallback_human", &cfun_ai_fallback_human},
948  { nullptr, nullptr } };
949  for (const luaL_Reg* p = mutating_callbacks; p->name; ++p) {
950  if(m == p->name) {
951  lua_pushlightuserdata(L, &engine);
952  lua_pushcclosure(L, p->func, 1);
953  return 1;
954  }
955  }
956  return 0;
957 }
958 
960  //push data table here
961  lua_newtable(L); // [-1: ai table]
962  lua_newtable(L); // [-1: metatable -2: ai table]
963  lua_pushlightuserdata(L, engine); // [-1: engine -2: metatable -3: ai table]
964  lua_pushcclosure(L, &impl_ai_get, 1); // [-1: metafunc -2: metatable -3: ai table]
965  lua_setfield(L, -2, "__index"); // [-1: metatable -2: ai table]
966  lua_setmetatable(L, -2); // [-1: ai table]
967 }
968 
970 {
971  // Retrieve the ai elements table from the registry.
972  lua_getfield(L, LUA_REGISTRYINDEX, aisKey); // [-1: AIs registry table]
973  size_t length_ai = lua_rawlen(L, -1); // length of table
974  lua_newtable(L); // [-1: AI state table -2: AIs registry table]
975  generate_and_push_ai_table(L, engine); // [-1: AI routines -2: AI state -3: AIs registry]
976  lua_setfield(L, -2, "ai"); // [-1: AI state -2: AIs registry]
977  lua_pushvalue(L, -1); // [-1: AI state -2: AI state -3: AIs registry]
978  lua_rawseti(L, -3, length_ai + 1); // [-1: AI state -2: AIs registry]
979  lua_remove(L, -2); // [-1: AI state table]
980  return length_ai + 1;
981 }
982 
984 {
985  int res_ai = luaL_loadbufferx(L, code, strlen(code), /*name*/ code, "t"); // [-1: AI code]
986  if (res_ai != 0)
987  {
988 
989  char const *m = lua_tostring(L, -1);
990  ERR_LUA << "error while initializing ai: " <<m << '\n';
991  lua_pop(L, 2);//return with stack size 0 []
992  return nullptr;
993  }
994  //push data table here
995  size_t idx = generate_and_push_ai_state(L, engine); // [-1: AI state -2: AI code]
996  lua_pushvalue(L, -2); // [-1: AI code -2: AI state -3: AI code]
997  lua_setfield(L, -2, "update_self"); // [-1: AI state -2: AI code]
998  lua_pushlightuserdata(L, engine);
999  lua_setfield(L, -2, "engine"); // [-1: AI state -2: AI code]
1000  lua_pop(L, 2);
1001  return new lua_ai_context(L, idx, engine->get_readonly_context().get_side());
1002 }
1003 
1005 {
1006  lua_ai_load ctx(*this, true); // [-1: AI state table]
1007 
1008  // Load the AI code and arguments
1009  lua_getfield(L, -1, "update_self"); // [-1: AI code -2: AI state]
1010  lua_getfield(L, -2, "params"); // [-1: Arguments -2: AI code -3: AI state]
1011  lua_getfield(L, -3, "data"); // [-1: Persistent data -2: Arguments -3: AI code -4: AI state]
1012 
1013  // Call the function
1014  if (!luaW_pcall(L, 2, 1, true)) { // [-1: Result -2: AI state]
1015  return; // return with stack size 0 []
1016  }
1017 
1018  // Store the state for use by components
1019  lua_setfield(L, -2, "self"); // [-1: AI state]
1020 
1021  // And return with empty stack.
1022  lua_pop(L, 1);
1023 }
1024 
1026 {
1027  int res = luaL_loadbufferx(L, code, strlen(code), /*name*/ code, "t");//stack size is now 1 [ -1: f]
1028  if (res)
1029  {
1030  char const *m = lua_tostring(L, -1);
1031  ERR_LUA << "error while creating ai function: " <<m << '\n';
1032  lua_pop(L, 2);//return with stack size 0 []
1033  return nullptr;
1034  }
1035 
1036  // Retrieve the ai elements table from the registry.
1037  lua_getfield(L, LUA_REGISTRYINDEX, aisKey); //stack size is now 2 [-1: ais_table -2: f]
1038  // Push the function in the table so that it is not collected.
1039  size_t length = lua_rawlen(L, -1);//length of ais_table
1040  lua_pushvalue(L, -2); //stack size is now 3: [-1: f -2: ais_table -3: f]
1041  lua_rawseti(L, -2, length + 1);// ais_table[length+1]=f. stack size is now 2 [-1: ais_table -2: f]
1042  lua_remove(L, -1);//stack size is now 1 [-1: f]
1043  lua_remove(L, -1);//stack size is now 0 []
1044  // Create the proxy C++ action handler.
1045  return new lua_ai_action_handler(L, context, length + 1);
1046 }
1047 
1048 int lua_ai_load::refcount = 0;
1049 
1050 lua_ai_load::lua_ai_load(lua_ai_context& ctx, bool read_only) : L(ctx.L), was_readonly(false)
1051 {
1052  refcount++;
1053  // Check if the AI table is already loaded. If so, we have less work to do.
1054  lua_getglobal(L, "ai");
1055  if(!lua_isnoneornil(L, -1)) {
1056  // Save the previous read-only state
1057  lua_getfield(L, -1, "read_only");
1058  was_readonly = luaW_toboolean(L, -1);
1059  lua_pop(L, 1);
1060  // Update the read-only state
1061  lua_pushstring(L, "read_only");
1062  lua_pushboolean(L, read_only);
1063  lua_rawset(L, -3);
1064  return; // Leave the AI table on the stack, as requested
1065  }
1066  lua_pop(L, 1); // Pop the nil value off the stack
1067  lua_getfield(L, LUA_REGISTRYINDEX, aisKey); // [-1: AI registry]
1068  lua_rawgeti(L, -1, ctx.num_); // [-1: AI state -2: AI registry]
1069  lua_remove(L,-2); // [-1: AI state]
1070 
1071  // Load the AI functions table into global scope
1072  lua_getfield(L, -1, "ai"); // [-1: AI functions -2: AI state]
1073  lua_pushstring(L, "read_only"); // [-1: key -2: AI functions -3: AI state]
1074  lua_pushboolean(L, read_only); // [-1: value -2: key -3: AI functions -4: AI state]
1075  lua_rawset(L, -3); // [-1: AI functions -2: AI state]
1076  lua_setglobal(L, "ai"); // [-1: AI state]
1077 }
1078 
1080 {
1081  refcount--;
1082  if (refcount == 0) {
1083  // Remove the AI functions from the global scope
1084  lua_pushnil(L);
1085  lua_setglobal(L, "ai");
1086  } else {
1087  // Restore the read-only state
1088  lua_getglobal(L, "ai");
1089  lua_pushstring(L, "read_only");
1091  lua_rawset(L, -3);
1092  lua_pop(L, 1);
1093  }
1094 }
1095 
1097 {
1098  // Remove the ai context from the registry, so that it can be collected.
1100  lua_pushnil(L);
1101  lua_rawseti(L, -2, num_);
1102  lua_pop(L, 1);
1103 }
1104 
1105 void lua_ai_action_handler::handle(const config &cfg, const config &filter_own, bool read_only, lua_object_ptr l_obj)
1106 {
1107  int initial_top = lua_gettop(L);//get the old stack size
1108 
1109  // Load the context
1110  lua_ai_load ctx(context_, read_only); // [-1: AI state table]
1111 
1112  // Load the user function from the registry.
1113  lua_getfield(L, LUA_REGISTRYINDEX, aisKey); // [-1: AI registry -2: AI state]
1114  lua_rawgeti(L, -1, num_); // [-1: AI action -2: AI registry -3: AI state]
1115  lua_remove(L, -2); // [-1: AI action -2: AI state]
1116 
1117  // Load the arguments
1118  int iState = lua_absindex(L, -2);
1119  lua_getfield(L, iState, "self");
1120  luaW_pushconfig(L, cfg);
1121  lua_getfield(L, iState, "data");
1122 
1123  int num = 3;
1124  if (!filter_own.empty()) {
1125  luaW_pushconfig(L, filter_own);
1126  num=4;
1127  }
1128 
1129  // Call the function
1130  luaW_pcall(L, num, l_obj ? 1 : 0, true);
1131  if (l_obj) {
1132  l_obj->store(L, -1);
1133  }
1134 
1135  lua_settop(L, initial_top);//empty stack
1136 }
1137 
1139 {
1140  // Remove the function from the registry, so that it can be collected.
1142  lua_pushnil(L);
1143  lua_rawseti(L, -2, num_);
1144  lua_pop(L, 1);
1145 }
1146 
1147 } // of namespace ai
void set_wml_y(int v)
Definition: location.hpp:156
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:123
#define lua_isnoneornil(L, n)
Definition: lua.h:379
static int cfun_ai_get_passive_leader_shares_keep(lua_State *L)
Definition: core.cpp:479
LUA_API void lua_pushlightuserdata(lua_State *L, void *p)
Definition: lapi.cpp:592
static void push_move_map(lua_State *L, const move_map &m)
Definition: core.cpp:667
double avg_damage_taken
The average hitpoints damage taken.
Definition: contexts.hpp:101
virtual const move_map & get_srcdst() const =0
LUA_API void lua_createtable(lua_State *L, int narray, int nrec)
Definition: lapi.cpp:728
#define lua_pushcfunction(L, f)
Definition: lua.h:370
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:428
virtual bool is_src_dst_valid_lua() 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:111
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:733
LUA_API void lua_settop(lua_State *L, int idx)
Definition: lapi.cpp:173
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:120
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:581
LUA_API int lua_rawgeti(lua_State *L, int idx, lua_Integer n)
Definition: lapi.cpp:710
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:96
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:501
LUA_API void lua_rawseti(lua_State *L, int idx, lua_Integer n)
Definition: lapi.cpp:889
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:168
static int cfun_ai_get_avoid(lua_State *L)
Definition: core.cpp:393
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:391
LUA_API int lua_getglobal(lua_State *L, const char *name)
Definition: lapi.cpp:632
std::shared_ptr< move_result > move_result_ptr
Definition: game_info.hpp:84
map_location target
Definition: contexts.hpp:83
LUA_API void lua_settable(lua_State *L, int idx)
Definition: lapi.cpp:821
static int cfun_ai_get_dstsrc(lua_State *L)
Definition: core.cpp:706
#define lua_tointeger(L, i)
Definition: lua.h:362
double vulnerability
The vulnerability is the power projection of enemy units onto the hex we&#39;re standing on...
Definition: contexts.hpp:120
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:525
static lua_ai_context * create(lua_State *L, char const *code, engine_lua *engine)
Definition: core.cpp:983
LUA_API int lua_rawget(lua_State *L, int idx)
Definition: lapi.cpp:698
void set_wml_x(int v)
Definition: location.hpp:155
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:542
#define ERR_LUA
Definition: core.cpp:54
#define lua_tonumber(L, i)
Definition: lua.h:361
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:714
LUA_API int lua_isuserdata(lua_State *L, int idx)
Definition: lapi.cpp:298
virtual double get_village_value() const =0
LUA_API void lua_pushcclosure(lua_State *L, lua_CFunction fn, int n)
Definition: lapi.cpp:555
double resources_used
The sum of the values of units used in the attack.
Definition: contexts.hpp:104
double chance_to_kill
Estimated % chance to kill the unit.
Definition: contexts.hpp:93
static int cfun_ai_recalculate_move_maps(lua_State *L)
Definition: core.cpp:766
static config unit_name(const unit *u)
Definition: reports.cpp:159
virtual const attacks_vector & get_attacks() const =0
void lua_push(lua_State *L, const T &val)
Definition: push_check.hpp:384
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:725
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:428
LUA_API int lua_absindex(lua_State *L, int idx)
Definition: lapi.cpp:161
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:517
static int ai_recall(lua_State *L, bool exec)
Definition: core.cpp:297
#define lua_pop(L, n)
Definition: lua.h:364
std::shared_ptr< aspect > aspect_ptr
Definition: game_info.hpp:94
double target_value
The value of the unit being targeted.
Definition: contexts.hpp:87
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:533
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:45
static int cfun_ai_get_leader_value(lua_State *L)
Definition: core.cpp:464
void handle(const config &cfg, const config &filter_own, bool read_only, lua_object_ptr l_obj)
Definition: core.cpp:1105
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:175
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:60
static int cfun_ai_is_src_dst_valid(lua_State *L)
Definition: core.cpp:752
LUA_API int lua_isstring(lua_State *L, int idx)
Definition: lapi.cpp:292
bool luaW_toboolean(lua_State *L, int n)
Definition: lua_common.cpp:893
virtual const terrain_filter & get_avoid() const =0
static int cfun_ai_get_leader_ignores_keep(lua_State *L)
Definition: core.cpp:457
LUALIB_API int luaL_loadbufferx(lua_State *L, const char *buff, size_t size, const char *name, const char *mode)
Definition: lauxlib.cpp:806
unit * luaW_tounit(lua_State *L, int index, bool only_on_map)
Converts a Lua value to a unit pointer.
Definition: lua_unit.cpp:142
double alternative_terrain_quality
The weighted average of the % defense of the best possible terrain that the attacking units could rea...
Definition: contexts.hpp:114
Proxy table for the AI context.
Definition: core.hpp:32
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:1025
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:367
static void push_attack_analysis(lua_State *L, const attack_analysis &)
Definition: core.cpp:587
lua_ai_load(lua_ai_context &ctx, bool read_only)
Definition: core.cpp:1050
static int impl_ai_aspect_get(lua_State *L)
Definition: core.cpp:784
game_board * gameboard
Definition: resources.cpp:20
static int cfun_ai_get_enemy_dstsrc(lua_State *L)
Definition: core.cpp:722
static int cfun_ai_get_attacks(lua_State *L)
Definition: core.cpp:375
LUA_API const char * lua_pushlstring(lua_State *L, const char *s, size_t len)
Definition: lapi.cpp:502
static int refcount
Definition: core.hpp:58
static int cfun_ai_is_src_dst_enemy_valid(lua_State *L)
Definition: core.cpp:759
LUA_API void lua_setglobal(lua_State *L, const char *name)
Definition: lapi.cpp:813
LUA_API int lua_setmetatable(lua_State *L, int objindex)
Definition: lapi.cpp:901
virtual int get_villages_per_scout() const =0
static int cfun_ai_get_simple_targeting(lua_State *L)
Definition: core.cpp:509
static int cfun_ai_execute_stopunit_all(lua_State *L)
Definition: core.cpp:263
constexpr bool decayed_is_same
Equivalent to as std::is_same_v except it uses the decayed form of V.
Definition: general.hpp:32
static void push_movements(lua_State *L, const std::vector< std::pair< map_location, map_location > > &moves)
Definition: core.cpp:562
static int cfun_ai_get_grouping(lua_State *L)
Definition: core.cpp:412
static int cfun_ai_check_stopunit(lua_State *L)
Definition: core.cpp:268
#define lua_newtable(L)
Definition: lua.h:366
LUA_API void lua_pushnil(lua_State *L)
Definition: lapi.cpp:473
LUA_API void lua_pushnumber(lua_State *L, lua_Number n)
Definition: lapi.cpp:481
Encapsulates the map of the game.
Definition: location.hpp:37
bool uses_leader
Is true if this attack sequence makes use of the leader.
Definition: contexts.hpp:126
#define lua_isboolean(L, n)
Definition: lua.h:376
static int cfun_ai_execute_move_full(lua_State *L)
Definition: core.cpp:189
aspect & find_active()
Definition: aspect.hpp:340
bool luaW_toconfig(lua_State *L, int index, config &cfg)
Converts an optional table or vconfig to a config object.
Definition: lua_common.cpp:745
void push_ai_table()
Definition: core.cpp:132
static int cfun_ai_get_targets(lua_State *L)
Definition: core.cpp:328
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:432
static int cfun_ai_is_dst_src_valid(lua_State *L)
Definition: core.cpp:738
static void init(lua_State *L)
Definition: core.cpp:62
std::size_t i
Definition: function.cpp:940
LUA_API void lua_rawset(lua_State *L, int idx)
Definition: lapi.cpp:877
lua_ai_context(lua_State *l, int num, int side)
Definition: core.hpp:38
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:84
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:772
double avg_losses
The value on average, of units lost in the combat.
Definition: contexts.hpp:90
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:386
virtual const std::vector< std::string > get_recruitment_pattern() const =0
double rating(double aggression, const readonly_context &ai_obj) const
Definition: attack.cpp:269
static int impl_ai_aspect_set(lua_State *L)
Definition: core.cpp:846
LUA_API void lua_pushvalue(lua_State *L, int idx)
Definition: lapi.cpp:246
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:285
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:68
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 lua_Unsigned lua_rawlen(lua_State *L, int idx)
Definition: lapi.cpp:402
#define LUA_REGISTRYINDEX
Definition: lua.h:44
virtual ai_context_ptr get_ai_context()
Definition: engine.cpp:128
static int impl_ai_get(lua_State *L)
Definition: core.cpp:852
LUA_API int lua_error(lua_State *L)
Definition: lapi.cpp:1205
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:665
const map_location & get_location() const
The current map location this unit is at.
Definition: unit.hpp:1348
readonly_context & get_readonly_context()
Definition: engine.cpp:141
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:71
static const map_location & null_location()
Definition: location.hpp:80
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:969
static int cfun_ai_get_caution(lua_State *L)
Definition: core.cpp:404
bool is_surrounded
Is true if the units involved in this attack sequence are surrounded.
Definition: contexts.hpp:129
static int cfun_ai_get_passive_leader(lua_State *L)
Definition: core.cpp:472
virtual double get_scout_village_targeting() const =0
#define DEPRECATED_ASPECT_MESSAGE(name)
Definition: core.cpp:363
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:59
static void generate_and_push_ai_table(lua_State *L, ai::engine_lua *engine)
Definition: core.cpp:959
LUA_API int lua_getfield(lua_State *L, int idx, const char *k)
Definition: lapi.cpp:655
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:489
This module contains various pathfinding functions and utilities.
static int cfun_ai_get_leader_aggression(lua_State *L)
Definition: core.cpp:420
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:514
typesafe_aspect< T > * try_aspect_as(aspect_ptr p)
Definition: core.cpp:779
LUA_API void lua_setfield(lua_State *L, int idx, const char *k)
Definition: lapi.cpp:837
static int cfun_ai_get_enemy_srcdst(lua_State *L)
Definition: core.cpp:730
bool empty() const
Definition: config.cpp:916
void update_state()
Definition: core.cpp:1004
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:745
static int cfun_ai_get_recruitment_pattern(lua_State *L)
Definition: core.cpp:486
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:26
static int cfun_ai_check_recall(lua_State *L)
Definition: core.cpp:316
#define luaL_checkstring(L, n)
Definition: lauxlib.h:138