The Battle for Wesnoth  1.15.10+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("retreat_enemy_weight");
504  double retreat_enemy_weight = get_readonly_context(L).get_retreat_enemy_weight();
505  lua_pushnumber(L, retreat_enemy_weight);
506  return 1;
507 }
508 
510 {
511  DEPRECATED_ASPECT_MESSAGE("retreat_factor");
512  double retreat_factor = get_readonly_context(L).get_retreat_factor();
513  lua_pushnumber(L, retreat_factor);
514  return 1;
515 }
516 
518 {
519  DEPRECATED_ASPECT_MESSAGE("scout_village_targeting");
520  double scout_village_targeting = get_readonly_context(L).get_scout_village_targeting();
521  lua_pushnumber(L, scout_village_targeting);
522  return 1;
523 }
524 
526 {
527  DEPRECATED_ASPECT_MESSAGE("simple_targeting");
528  bool simple_targeting = get_readonly_context(L).get_simple_targeting();
529  lua_pushboolean(L, simple_targeting);
530  return 1;
531 }
532 
534 {
535  DEPRECATED_ASPECT_MESSAGE("support_villages");
536  bool support_villages = get_readonly_context(L).get_support_villages();
537  lua_pushboolean(L, support_villages);
538  return 1;
539 }
540 
542 {
543  DEPRECATED_ASPECT_MESSAGE("village_value");
544  double village_value = get_readonly_context(L).get_village_value();
545  lua_pushnumber(L, village_value);
546  return 1;
547 }
548 
550 {
551  DEPRECATED_ASPECT_MESSAGE("villages_per_scout");
552  int villages_per_scout = get_readonly_context(L).get_villages_per_scout();
553  lua_pushnumber(L, villages_per_scout);
554  return 1;
555 }
556 // End of aspect section
557 
559 {
560  int top = lua_gettop(L);
561  // the attack_analysis table should be on top of the stack
562  lua_getfield(L, -1, "att_ptr"); // [-2: attack_analysis; -1: pointer to attack_analysis object in c++]
563  // now the pointer to our attack_analysis C++ object is on top
564  const attack_analysis* aa_ptr = static_cast< attack_analysis * >(lua_touserdata(L, -1));
565 
566  //[-2: attack_analysis; -1: pointer to attack_analysis object in c++]
567 
568  double aggression = get_readonly_context(L).get_aggression();
569 
570  double rating = aa_ptr->rating(aggression, get_readonly_context(L));
571 
572  lua_settop(L, top);
573 
574  lua_pushnumber(L, rating);
575  return 1;
576 }
577 
578 static void push_movements(lua_State *L, const std::vector< std::pair < map_location, map_location > > & moves)
579 {
580  lua_createtable(L, moves.size(), 0);
581 
582  int table_index = lua_gettop(L);
583 
584  std::vector< std::pair < map_location, map_location > >::const_iterator move = moves.begin();
585 
586  for (int i = 1; move != moves.end(); ++move, ++i)
587  {
588  lua_createtable(L, 2, 0); // Creating a table for a pair of map_location's
589 
590  lua_pushstring(L, "src");
591  luaW_pushlocation(L, move->first);
592  lua_rawset(L, -3);
593 
594  lua_pushstring(L, "dst");
595  luaW_pushlocation(L, move->second);
596  lua_rawset(L, -3);
597 
598  lua_rawseti(L, table_index, i); // setting the pair as an element of the movements table
599  }
600 
601 }
602 
604 {
605  lua_newtable(L);
606 
607  // Pushing a pointer to the current object
608  lua_pushstring(L, "att_ptr");
609  lua_pushlightuserdata(L, const_cast<attack_analysis*>(&aa));
610  lua_rawset(L, -3);
611 
612  // Registering callback function for the rating method
613  lua_pushstring(L, "rating");
616  lua_rawset(L, -3);
617 
618  lua_pushstring(L, "movements");
619  push_movements(L, aa.movements);
620  lua_rawset(L, -3);
621 
622  lua_pushstring(L, "target");
623  luaW_pushlocation(L, aa.target);
624  lua_rawset(L, -3);
625 
626  lua_pushstring(L, "target_value");
628  lua_rawset(L, -3);
629 
630  lua_pushstring(L, "avg_losses");
631  lua_pushnumber(L, aa.avg_losses);
632  lua_rawset(L, -3);
633 
634  lua_pushstring(L, "chance_to_kill");
636  lua_rawset(L, -3);
637 
638  lua_pushstring(L, "avg_damage_inflicted");
640  lua_rawset(L, -3);
641 
642  lua_pushstring(L, "target_starting_damage");
644  lua_rawset(L, -3);
645 
646  lua_pushstring(L, "avg_damage_taken");
648  lua_rawset(L, -3);
649 
650  lua_pushstring(L, "resources_used");
652  lua_rawset(L, -3);
653 
654  lua_pushstring(L, "terrain_quality");
656  lua_rawset(L, -3);
657 
658  lua_pushstring(L, "alternative_terrain_quality");
660  lua_rawset(L, -3);
661 
662  lua_pushstring(L, "vulnerability");
664  lua_rawset(L, -3);
665 
666  lua_pushstring(L, "support");
667  lua_pushnumber(L, aa.support);
668  lua_rawset(L, -3);
669 
670  lua_pushstring(L, "leader_threat");
672  lua_rawset(L, -3);
673 
674  lua_pushstring(L, "uses_leader");
676  lua_rawset(L, -3);
677 
678  lua_pushstring(L, "is_surrounded");
680  lua_rawset(L, -3);
681 }
682 
683 static void push_move_map(lua_State *L, const move_map& m)
684 {
685  lua_createtable(L, 0, 0); // the main table
686 
687  if (m.empty())
688  {
689  return;
690  }
691 
692  move_map::const_iterator it = m.begin();
693 
694  int index = 1;
695 
697 
698  do
699  {
700  map_location key = it->first;
701  lua_pushinteger(L, lhash(key));
702 
703  lua_createtable(L, 0, 0);
704 
705  while (key == it->first) {
706 
707  luaW_pushlocation(L, it->second);
708  lua_rawseti(L, -2, index);
709 
710  ++index;
711  ++it;
712 
713  }
714 
715  lua_settable(L, -3);
716 
717  index = 1;
718 
719  } while (it != m.end());
720 }
721 
723 {
726  push_move_map(L, dst_src);
727  return 1;
728 }
729 
731 {
734  push_move_map(L, src_dst);
735  return 1;
736 }
737 
739 {
740  move_map enemy_dst_src = get_readonly_context(L).get_enemy_dstsrc();
742  push_move_map(L, enemy_dst_src);
743  return 1;
744 }
745 
747 {
748  move_map enemy_src_dst = get_readonly_context(L).get_enemy_srcdst();
750  push_move_map(L, enemy_src_dst);
751  return 1;
752 }
753 
755 {
756  bool valid = get_readonly_context(L).is_dst_src_valid_lua();
757  lua_pushboolean(L, valid);
758  return 1;
759 }
760 
762 {
764  lua_pushboolean(L, valid);
765  return 1;
766 }
767 
769 {
770  bool valid = get_readonly_context(L).is_src_dst_valid_lua();
771  lua_pushboolean(L, valid);
772  return 1;
773 }
774 
776 {
778  lua_pushboolean(L, valid);
779  return 1;
780 }
781 
783 {
785  return 1;
786 }
787 
789 {
791  return 1;
792 }
793 
794 template<typename T>
796 {
797  return std::dynamic_pointer_cast<typesafe_aspect<T> >(p).get();
798 }
799 
801 {
802  const aspect_map& aspects = get_engine(L).get_readonly_context().get_aspects();
803  aspect_map::const_iterator iter = aspects.find(luaL_checkstring(L, 2));
804  if(iter == aspects.end()) {
805  return 0;
806  }
807 
808  // A few aspects require special delicate handling...
809  if(typesafe_aspect<attacks_vector>* aspect_as_attacks_vector = try_aspect_as<attacks_vector>(iter->second)) {
811  aspect_attacks_base* real_aspect = dynamic_cast<aspect_attacks_base*>(aspect_as_attacks_vector);
812  while(real_aspect == nullptr) {
813  // It's probably a composite aspect, so find the active facet
814  composite_aspect<attacks_vector>& composite = dynamic_cast<composite_aspect<attacks_vector>&>(*aspect_as_attacks_vector);
815  aspect_as_attacks_vector = &dynamic_cast<typesafe_aspect<attacks_vector>&>(composite.find_active());
816  real_aspect = dynamic_cast<aspect_attacks_base*>(aspect_as_attacks_vector);
817  }
818  int my_side = get_engine(L).get_readonly_context().get_side();
819  std::vector<unit_const_ptr> attackers, enemies;
820  for(unit_map::const_iterator u = resources::gameboard->units().begin(); u != resources::gameboard->units().end(); ++u) {
821  if(!u.valid()) {
822  continue;
823  }
824  if(u->side() == my_side && real_aspect->is_allowed_attacker(*u)) {
825  attackers.push_back(u.get_shared_ptr());
826  } else if(u->side() != my_side && real_aspect->is_allowed_enemy(*u)) {
827  enemies.push_back(u.get_shared_ptr());
828  }
829  }
830  lua_createtable(L, 0, 2);
831  lua_createtable(L, attackers.size(), 0);
832  for(size_t i = 0; i < attackers.size(); i++) {
833  luaW_pushunit(L, attackers[i]->underlying_id());
834  lua_rawseti(L, -2, i + 1);
835  }
836  lua_setfield(L, -2, "own");
837  lua_createtable(L, enemies.size(), 0);
838  for(size_t i = 0; i < enemies.size(); i++) {
839  luaW_pushunit(L, enemies[i]->underlying_id());
840  lua_rawseti(L, -2, i + 1);
841  }
842  lua_setfield(L, -2, "enemy");
843  } else if(typesafe_aspect<unit_advancements_aspect>* aspect_as_unit_advancements_aspects = try_aspect_as<unit_advancements_aspect>(iter->second)) {
844  const unit_advancements_aspect& val = aspect_as_unit_advancements_aspects->get();
845  int my_side = get_engine(L).get_readonly_context().get_side();
846  lua_newtable(L);
848  for (unit_map::const_iterator u = resources::gameboard->units().begin(); u != resources::gameboard->units().end(); ++u) {
849  if (!u.valid() || u->side() != my_side) {
850  continue;
851  }
852  lua_pushinteger(L, lhash(u->get_location()));
853  lua_push(L, val.get_advancements(u));
854  lua_settable(L, -3);
855  }
856  } else {
857  iter->second->get_lua(L);
858  }
859  return 1;
860 }
861 
863 {
864  lua_pushstring(L, "attempted to write to the ai.aspects table, which is read-only");
865  return lua_error(L);
866 }
867 
868 static int impl_ai_get(lua_State* L)
869 {
870  if(!lua_isstring(L,2)) {
871  return 0;
872  }
874  std::string m = lua_tostring(L,2);
875  if(m == "side") {
877  return 1;
878  }
879  if(m == "aspects") {
880  lua_newtable(L); // [-1: Aspects table]
881  lua_newtable(L); // [-1: Aspects metatable -2: Aspects table]
882  lua_pushlightuserdata(L, &engine); // [-1: Engine -2: Aspects mt -3: Aspects table]
883  lua_pushcclosure(L, &impl_ai_aspect_get, 1); // [-1: Metafunction -2: Aspects mt -3: Aspects table]
884  lua_setfield(L, -2, "__index"); // [-1: Aspects metatable -2: Aspects table]
885  lua_pushcfunction(L, &impl_ai_aspect_set); // [-1: Metafunction -2: Aspects mt -3: Aspects table]
886  lua_setfield(L, -2, "__newindex"); // [-1: Aspects metatable -2: Aspects table]
887  lua_setmetatable(L, -2); // [-1: Aspects table]
888  return 1;
889  }
890  static luaL_Reg const callbacks[] = {
891  // Move maps
892  { "get_new_dst_src", &cfun_ai_get_dstsrc },
893  { "get_new_src_dst", &cfun_ai_get_srcdst },
894  { "get_new_enemy_dst_src", &cfun_ai_get_enemy_dstsrc },
895  { "get_new_enemy_src_dst", &cfun_ai_get_enemy_srcdst },
896  { "recalculate_move_maps", &cfun_ai_recalculate_move_maps },
897  { "recalculate_enemy_move_maps", &cfun_ai_recalculate_move_maps_enemy },
898  // End of move maps
899  // Goals and targets
900  { "get_targets", &cfun_ai_get_targets },
901  // End of G & T
902  // Aspects
903  { "get_aggression", &cfun_ai_get_aggression },
904  { "get_avoid", &cfun_ai_get_avoid },
905  { "get_attacks", &cfun_ai_get_attacks },
906  { "get_caution", &cfun_ai_get_caution },
907  { "get_grouping", &cfun_ai_get_grouping },
908  { "get_leader_aggression", &cfun_ai_get_leader_aggression },
909  { "get_leader_goal", &cfun_ai_get_leader_goal },
910  { "get_leader_ignores_keep", &cfun_ai_get_leader_ignores_keep },
911  { "get_leader_value", &cfun_ai_get_leader_value },
912  { "get_passive_leader", &cfun_ai_get_passive_leader },
913  { "get_passive_leader_shares_keep", &cfun_ai_get_passive_leader_shares_keep },
914  { "get_recruitment_pattern", &cfun_ai_get_recruitment_pattern },
915  { "get_retreat_enemy_weight", &cfun_ai_get_retreat_enemy_weight },
916  { "get_retreat_factor", &cfun_ai_get_retreat_factor },
917  { "get_scout_village_targeting", &cfun_ai_get_scout_village_targeting },
918  { "get_simple_targeting", &cfun_ai_get_simple_targeting },
919  { "get_support_villages", &cfun_ai_get_support_villages },
920  { "get_village_value", &cfun_ai_get_village_value },
921  { "get_villages_per_scout", &cfun_ai_get_villages_per_scout },
922  // End of aspects
923  // Validation/cache functions
924  { "is_dst_src_valid", &cfun_ai_is_dst_src_valid },
925  { "is_enemy_dst_src_valid", &cfun_ai_is_dst_src_enemy_valid },
926  { "is_src_dst_valid", &cfun_ai_is_src_dst_valid },
927  { "is_enemy_src_dst_valid", &cfun_ai_is_src_dst_enemy_valid },
928  // End of validation functions
929  { "suitable_keep", &cfun_ai_get_suitable_keep },
930  { "check_recall", &cfun_ai_check_recall },
931  { "check_move", &cfun_ai_check_move },
932  { "check_stopunit", &cfun_ai_check_stopunit },
933  { "check_attack", &cfun_ai_check_attack },
934  { "check_recruit", &cfun_ai_check_recruit },
935  //{ "",},
936  //{ "",},
937  { nullptr, nullptr } };
938  for (const luaL_Reg* p = callbacks; p->name; ++p) {
939  if(m == p->name) {
940  lua_pushlightuserdata(L, &engine); // [-1: engine ...]
941  lua_pushcclosure(L, p->func, 1); // [-1: function ...]
942  // Store the function so that __index doesn't need to be called next time
943  lua_pushstring(L, p->name); // [-1: name -2: function ...]
944  lua_pushvalue(L, -2); // [-1: function -2: name -3: function ...]
945  lua_rawset(L, 1); // [-1: function ...]
946  return 1;
947  }
948  }
949  lua_pushstring(L, "read_only");
950  lua_rawget(L, 1);
951  bool read_only = luaW_toboolean(L, -1);
952  lua_pop(L, 1);
953  if(read_only) {
954  return 0;
955  }
956  static luaL_Reg const mutating_callbacks[] = {
957  { "attack", &cfun_ai_execute_attack },
958  { "move", &cfun_ai_execute_move_partial },
959  { "move_full", &cfun_ai_execute_move_full },
960  { "recall", &cfun_ai_execute_recall },
961  { "recruit", &cfun_ai_execute_recruit },
962  { "stopunit_all", &cfun_ai_execute_stopunit_all },
963  { "stopunit_attacks", &cfun_ai_execute_stopunit_attacks },
964  { "stopunit_moves", &cfun_ai_execute_stopunit_moves },
965  { "fallback_human", &cfun_ai_fallback_human},
966  { nullptr, nullptr } };
967  for (const luaL_Reg* p = mutating_callbacks; p->name; ++p) {
968  if(m == p->name) {
969  lua_pushlightuserdata(L, &engine);
970  lua_pushcclosure(L, p->func, 1);
971  return 1;
972  }
973  }
974  return 0;
975 }
976 
978  //push data table here
979  lua_newtable(L); // [-1: ai table]
980  lua_newtable(L); // [-1: metatable -2: ai table]
981  lua_pushlightuserdata(L, engine); // [-1: engine -2: metatable -3: ai table]
982  lua_pushcclosure(L, &impl_ai_get, 1); // [-1: metafunc -2: metatable -3: ai table]
983  lua_setfield(L, -2, "__index"); // [-1: metatable -2: ai table]
984  lua_setmetatable(L, -2); // [-1: ai table]
985 }
986 
988 {
989  // Retrieve the ai elements table from the registry.
990  lua_getfield(L, LUA_REGISTRYINDEX, aisKey); // [-1: AIs registry table]
991  size_t length_ai = lua_rawlen(L, -1); // length of table
992  lua_newtable(L); // [-1: AI state table -2: AIs registry table]
993  generate_and_push_ai_table(L, engine); // [-1: AI routines -2: AI state -3: AIs registry]
994  lua_setfield(L, -2, "ai"); // [-1: AI state -2: AIs registry]
995  lua_pushvalue(L, -1); // [-1: AI state -2: AI state -3: AIs registry]
996  lua_rawseti(L, -3, length_ai + 1); // [-1: AI state -2: AIs registry]
997  lua_remove(L, -2); // [-1: AI state table]
998  return length_ai + 1;
999 }
1000 
1002 {
1003  int res_ai = luaL_loadbufferx(L, code, strlen(code), /*name*/ code, "t"); // [-1: AI code]
1004  if (res_ai != 0)
1005  {
1006 
1007  char const *m = lua_tostring(L, -1);
1008  ERR_LUA << "error while initializing ai: " <<m << '\n';
1009  lua_pop(L, 2);//return with stack size 0 []
1010  return nullptr;
1011  }
1012  //push data table here
1013  size_t idx = generate_and_push_ai_state(L, engine); // [-1: AI state -2: AI code]
1014  lua_pushvalue(L, -2); // [-1: AI code -2: AI state -3: AI code]
1015  lua_setfield(L, -2, "update_self"); // [-1: AI state -2: AI code]
1016  lua_pushlightuserdata(L, engine);
1017  lua_setfield(L, -2, "engine"); // [-1: AI state -2: AI code]
1018  lua_pop(L, 2);
1019  return new lua_ai_context(L, idx, engine->get_readonly_context().get_side());
1020 }
1021 
1023 {
1024  lua_ai_load ctx(*this, true); // [-1: AI state table]
1025 
1026  // Load the AI code and arguments
1027  lua_getfield(L, -1, "update_self"); // [-1: AI code -2: AI state]
1028  lua_getfield(L, -2, "params"); // [-1: Arguments -2: AI code -3: AI state]
1029  lua_getfield(L, -3, "data"); // [-1: Persistent data -2: Arguments -3: AI code -4: AI state]
1030 
1031  // Call the function
1032  if (!luaW_pcall(L, 2, 1, true)) { // [-1: Result -2: AI state]
1033  return; // return with stack size 0 []
1034  }
1035 
1036  // Store the state for use by components
1037  lua_setfield(L, -2, "self"); // [-1: AI state]
1038 
1039  // And return with empty stack.
1040  lua_pop(L, 1);
1041 }
1042 
1044 {
1045  int res = luaL_loadbufferx(L, code, strlen(code), /*name*/ code, "t");//stack size is now 1 [ -1: f]
1046  if (res)
1047  {
1048  char const *m = lua_tostring(L, -1);
1049  ERR_LUA << "error while creating ai function: " <<m << '\n';
1050  lua_pop(L, 2);//return with stack size 0 []
1051  return nullptr;
1052  }
1053 
1054  // Retrieve the ai elements table from the registry.
1055  lua_getfield(L, LUA_REGISTRYINDEX, aisKey); //stack size is now 2 [-1: ais_table -2: f]
1056  // Push the function in the table so that it is not collected.
1057  size_t length = lua_rawlen(L, -1);//length of ais_table
1058  lua_pushvalue(L, -2); //stack size is now 3: [-1: f -2: ais_table -3: f]
1059  lua_rawseti(L, -2, length + 1);// ais_table[length+1]=f. stack size is now 2 [-1: ais_table -2: f]
1060  lua_remove(L, -1);//stack size is now 1 [-1: f]
1061  lua_remove(L, -1);//stack size is now 0 []
1062  // Create the proxy C++ action handler.
1063  return new lua_ai_action_handler(L, context, length + 1);
1064 }
1065 
1066 int lua_ai_load::refcount = 0;
1067 
1068 lua_ai_load::lua_ai_load(lua_ai_context& ctx, bool read_only) : L(ctx.L), was_readonly(false)
1069 {
1070  refcount++;
1071  // Check if the AI table is already loaded. If so, we have less work to do.
1072  lua_getglobal(L, "ai");
1073  if(!lua_isnoneornil(L, -1)) {
1074  // Save the previous read-only state
1075  lua_getfield(L, -1, "read_only");
1076  was_readonly = luaW_toboolean(L, -1);
1077  lua_pop(L, 1);
1078  // Update the read-only state
1079  lua_pushstring(L, "read_only");
1080  lua_pushboolean(L, read_only);
1081  lua_rawset(L, -3);
1082  return; // Leave the AI table on the stack, as requested
1083  }
1084  lua_pop(L, 1); // Pop the nil value off the stack
1085  lua_getfield(L, LUA_REGISTRYINDEX, aisKey); // [-1: AI registry]
1086  lua_rawgeti(L, -1, ctx.num_); // [-1: AI state -2: AI registry]
1087  lua_remove(L,-2); // [-1: AI state]
1088 
1089  // Load the AI functions table into global scope
1090  lua_getfield(L, -1, "ai"); // [-1: AI functions -2: AI state]
1091  lua_pushstring(L, "read_only"); // [-1: key -2: AI functions -3: AI state]
1092  lua_pushboolean(L, read_only); // [-1: value -2: key -3: AI functions -4: AI state]
1093  lua_rawset(L, -3); // [-1: AI functions -2: AI state]
1094  lua_setglobal(L, "ai"); // [-1: AI state]
1095 }
1096 
1098 {
1099  refcount--;
1100  if (refcount == 0) {
1101  // Remove the AI functions from the global scope
1102  lua_pushnil(L);
1103  lua_setglobal(L, "ai");
1104  } else {
1105  // Restore the read-only state
1106  lua_getglobal(L, "ai");
1107  lua_pushstring(L, "read_only");
1109  lua_rawset(L, -3);
1110  lua_pop(L, 1);
1111  }
1112 }
1113 
1115 {
1116  // Remove the ai context from the registry, so that it can be collected.
1118  lua_pushnil(L);
1119  lua_rawseti(L, -2, num_);
1120  lua_pop(L, 1);
1121 }
1122 
1123 void lua_ai_action_handler::handle(const config &cfg, const config &filter_own, bool read_only, lua_object_ptr l_obj)
1124 {
1125  int initial_top = lua_gettop(L);//get the old stack size
1126 
1127  // Load the context
1128  lua_ai_load ctx(context_, read_only); // [-1: AI state table]
1129 
1130  // Load the user function from the registry.
1131  lua_getfield(L, LUA_REGISTRYINDEX, aisKey); // [-1: AI registry -2: AI state]
1132  lua_rawgeti(L, -1, num_); // [-1: AI action -2: AI registry -3: AI state]
1133  lua_remove(L, -2); // [-1: AI action -2: AI state]
1134 
1135  // Load the arguments
1136  int iState = lua_absindex(L, -2);
1137  lua_getfield(L, iState, "self");
1138  luaW_pushconfig(L, cfg);
1139  lua_getfield(L, iState, "data");
1140 
1141  int num = 3;
1142  if (!filter_own.empty()) {
1143  luaW_pushconfig(L, filter_own);
1144  num=4;
1145  }
1146 
1147  // Call the function
1148  luaW_pcall(L, num, l_obj ? 1 : 0, true);
1149  if (l_obj) {
1150  l_obj->store(L, -1);
1151  }
1152 
1153  lua_settop(L, initial_top);//empty stack
1154 }
1155 
1157 {
1158  // Remove the function from the registry, so that it can be collected.
1160  lua_pushnil(L);
1161  lua_rawseti(L, -2, num_);
1162  lua_pop(L, 1);
1163 }
1164 
1165 } // 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:683
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
static int cfun_ai_get_retreat_enemy_weight(lua_State *L)
Definition: core.cpp:501
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
virtual double get_retreat_enemy_weight() const =0
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:517
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:722
#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:541
static lua_ai_context * create(lua_State *L, char const *code, engine_lua *engine)
Definition: core.cpp:1001
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:558
#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:730
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:782
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
virtual double get_retreat_factor() const =0
static int cfun_ai_get_support_villages(lua_State *L)
Definition: core.cpp:533
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:549
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:1123
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:768
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:1043
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:603
lua_ai_load(lua_ai_context &ctx, bool read_only)
Definition: core.cpp:1068
static int impl_ai_aspect_get(lua_State *L)
Definition: core.cpp:800
game_board * gameboard
Definition: resources.cpp:20
static int cfun_ai_get_enemy_dstsrc(lua_State *L)
Definition: core.cpp:738
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:775
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:525
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:578
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:754
static void init(lua_State *L)
Definition: core.cpp:62
std::size_t i
Definition: function.cpp:934
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
static int cfun_ai_get_retreat_factor(lua_State *L)
Definition: core.cpp:509
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:788
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:862
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:868
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:987
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:977
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:795
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:746
bool empty() const
Definition: config.cpp:916
void update_state()
Definition: core.cpp:1022
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:761
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