The Battle for Wesnoth  1.17.0-dev
core.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2010 - 2021
3  by Yurii Chernyi <terraninfo@terraninfo.net>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 /**
17  * @file
18  * Provides core classes for the Lua AI.
19  *
20  */
21 
22 #include <cassert>
23 #include <cstring>
24 
25 #include "ai/lua/core.hpp"
26 #include "ai/composite/aspect.hpp"
28 #include "scripting/lua_unit.hpp"
29 #include "scripting/push_check.hpp"
30 #include "ai/lua/lua_object.hpp" // (Nephro)
31 
32 #include "attack_prediction.hpp"
33 #include "game_display.hpp"
34 #include "log.hpp"
35 #include "map/map.hpp"
36 #include "pathfind/pathfind.hpp"
37 #include "play_controller.hpp"
38 #include "resources.hpp"
39 #include "terrain/translation.hpp"
40 #include "terrain/filter.hpp"
41 #include "units/unit.hpp"
42 #include "ai/actions.hpp"
43 #include "ai/lua/engine_lua.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  luaW_tolocation(L, 2, where);
280  ai::recruit_result_ptr recruit_result = ai::actions::execute_recruit_action(side,exec,std::string(unit_name),where,from);
281  return transform_ai_action(L,recruit_result);
282 }
283 
285 {
286  return ai_recruit(L, true);
287 }
288 
290 {
291  return ai_recruit(L, false);
292 }
293 
294 static int ai_recall(lua_State *L, bool exec)
295 {
296  const char *unit_id = luaL_checkstring(L, 1);
297  int side = get_readonly_context(L).get_side();
298  map_location where;
299  luaW_tolocation(L, 2, where);
301  ai::recall_result_ptr recall_result = ai::actions::execute_recall_action(side,exec,std::string(unit_id),where,from);
302  return transform_ai_action(L,recall_result);
303 }
304 
306 {
307  return ai_recall(L, true);
308 }
309 
311 {
312  return ai_recall(L, false);
313 }
314 
316 {
318 }
319 
320 // Goals and targets
321 
323 {
324  move_map enemy_dst_src = get_readonly_context(L).get_enemy_dstsrc();
325  std::vector<target> targets = get_engine(L).get_ai_context()->find_targets(enemy_dst_src);
326  int i = 1;
327 
328  lua_createtable(L, 0, 0);
329  for (std::vector<target>::iterator it = targets.begin(); it != targets.end(); ++it)
330  {
331  lua_pushinteger(L, i);
332 
333  //to factor out
334  lua_createtable(L, 3, 0);
335 
336  lua_pushstring(L, "type");
337  lua_pushstring(L, it->type.to_string().c_str());
338  lua_rawset(L, -3);
339 
340  lua_pushstring(L, "loc");
341  luaW_pushlocation(L, it->loc);
342  lua_rawset(L, -3);
343 
344  lua_pushstring(L, "value");
345  lua_pushnumber(L, it->value);
346  lua_rawset(L, -3);
347 
348  lua_rawset(L, -3);
349  ++i;
350  }
351  return 1;
352 }
353 
354 // Aspect section
356 {
357  double aggression = get_readonly_context(L).get_aggression();
358  lua_pushnumber(L, aggression);
359  return 1;
360 }
361 
363 {
364  // Unlike the other aspect fetchers, this one is not deprecated!
365  // This is because ai.aspects.attacks returns the viable units but this returns a full attack analysis
367  lua_createtable(L, attacks.size(), 0);
368  int table_index = lua_gettop(L);
369 
370  ai::attacks_vector::const_iterator it = attacks.begin();
371  for (int i = 1; it != attacks.end(); ++it, ++i)
372  {
373  push_attack_analysis(L, *it);
374 
375  lua_rawseti(L, table_index, i);
376  }
377  return 1;
378 }
379 
381 {
382  std::set<map_location> locs;
383  terrain_filter avoid = get_readonly_context(L).get_avoid();
384  avoid.get_locations(locs);
385  luaW_push_locationset(L, locs);
386 
387  return 1;
388 }
389 
391 {
392  double caution = get_readonly_context(L).get_caution();
393  lua_pushnumber(L, caution);
394  return 1;
395 }
396 
398 {
399  std::string grouping = get_readonly_context(L).get_grouping();
400  lua_pushstring(L, grouping.c_str());
401  return 1;
402 }
403 
405 {
406  double leader_aggression = get_readonly_context(L).get_leader_aggression();
407  lua_pushnumber(L, leader_aggression);
408  return 1;
409 }
410 
412 {
414  luaW_pushconfig(L, goal);
415  return 1;
416 }
417 
418 namespace
419 {
420 // TODO: name this something better
421 void visit_helper(lua_State* L, const utils::variant<bool, std::vector<std::string>>& input)
422 {
423  utils::visit(
424  [L](const auto& v) {
425  if constexpr(utils::decayed_is_same<bool, decltype(v)>) {
426  lua_pushboolean(L, v);
427  } else {
428  lua_createtable(L, v.size(), 0);
429  for(const std::string& str : v) {
430  lua_pushlstring(L, str.c_str(), str.size());
431  lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
432  }
433  }
434  },
435  input);
436 }
437 } // namespace
438 
440 {
441  visit_helper(L, get_readonly_context(L).get_leader_ignores_keep());
442  return 1;
443 }
444 
446 {
447  double leader_value = get_readonly_context(L).get_leader_value();
448  lua_pushnumber(L, leader_value);
449  return 1;
450 }
451 
453 {
454  visit_helper(L, get_readonly_context(L).get_passive_leader());
455  return 1;
456 }
457 
459 {
460  visit_helper(L, get_readonly_context(L).get_passive_leader_shares_keep());
461  return 1;
462 }
463 
465 {
466  std::vector<std::string> recruiting = get_readonly_context(L).get_recruitment_pattern();
467  int size = recruiting.size();
468  lua_createtable(L, size, 0); // create an empty table with predefined size
469  for (int i = 0; i < size; ++i)
470  {
471  lua_pushinteger(L, i + 1); // Indexing in Lua starts from 1
472  lua_pushstring(L, recruiting[i].c_str());
473  lua_settable(L, -3);
474  }
475  return 1;
476 }
477 
479 {
480  double scout_village_targeting = get_readonly_context(L).get_scout_village_targeting();
481  lua_pushnumber(L, scout_village_targeting);
482  return 1;
483 }
484 
486 {
487  bool simple_targeting = get_readonly_context(L).get_simple_targeting();
488  lua_pushboolean(L, simple_targeting);
489  return 1;
490 }
491 
493 {
494  bool support_villages = get_readonly_context(L).get_support_villages();
495  lua_pushboolean(L, support_villages);
496  return 1;
497 }
498 
500 {
501  double village_value = get_readonly_context(L).get_village_value();
502  lua_pushnumber(L, village_value);
503  return 1;
504 }
505 
507 {
508  int villages_per_scout = get_readonly_context(L).get_villages_per_scout();
509  lua_pushnumber(L, villages_per_scout);
510  return 1;
511 }
512 // End of aspect section
513 
515 {
516  int top = lua_gettop(L);
517  // the attack_analysis table should be on top of the stack
518  lua_getfield(L, -1, "att_ptr"); // [-2: attack_analysis; -1: pointer to attack_analysis object in c++]
519  // now the pointer to our attack_analysis C++ object is on top
520  const attack_analysis* aa_ptr = static_cast< attack_analysis * >(lua_touserdata(L, -1));
521 
522  //[-2: attack_analysis; -1: pointer to attack_analysis object in c++]
523 
524  double aggression = get_readonly_context(L).get_aggression();
525 
526  double rating = aa_ptr->rating(aggression, get_readonly_context(L));
527 
528  lua_settop(L, top);
529 
530  lua_pushnumber(L, rating);
531  return 1;
532 }
533 
534 static void push_movements(lua_State *L, const std::vector< std::pair < map_location, map_location > > & moves)
535 {
536  lua_createtable(L, moves.size(), 0);
537 
538  int table_index = lua_gettop(L);
539 
540  std::vector< std::pair < map_location, map_location > >::const_iterator move = moves.begin();
541 
542  for (int i = 1; move != moves.end(); ++move, ++i)
543  {
544  lua_createtable(L, 2, 0); // Creating a table for a pair of map_location's
545 
546  lua_pushstring(L, "src");
547  luaW_pushlocation(L, move->first);
548  lua_rawset(L, -3);
549 
550  lua_pushstring(L, "dst");
551  luaW_pushlocation(L, move->second);
552  lua_rawset(L, -3);
553 
554  lua_rawseti(L, table_index, i); // setting the pair as an element of the movements table
555  }
556 
557 }
558 
560 {
561  lua_newtable(L);
562 
563  // Pushing a pointer to the current object
564  lua_pushstring(L, "att_ptr");
565  lua_pushlightuserdata(L, const_cast<attack_analysis*>(&aa));
566  lua_rawset(L, -3);
567 
568  // Registering callback function for the rating method
569  lua_pushstring(L, "rating");
572  lua_rawset(L, -3);
573 
574  lua_pushstring(L, "movements");
575  push_movements(L, aa.movements);
576  lua_rawset(L, -3);
577 
578  lua_pushstring(L, "target");
579  luaW_pushlocation(L, aa.target);
580  lua_rawset(L, -3);
581 
582  lua_pushstring(L, "target_value");
584  lua_rawset(L, -3);
585 
586  lua_pushstring(L, "avg_losses");
587  lua_pushnumber(L, aa.avg_losses);
588  lua_rawset(L, -3);
589 
590  lua_pushstring(L, "chance_to_kill");
592  lua_rawset(L, -3);
593 
594  lua_pushstring(L, "avg_damage_inflicted");
596  lua_rawset(L, -3);
597 
598  lua_pushstring(L, "target_starting_damage");
600  lua_rawset(L, -3);
601 
602  lua_pushstring(L, "avg_damage_taken");
604  lua_rawset(L, -3);
605 
606  lua_pushstring(L, "resources_used");
608  lua_rawset(L, -3);
609 
610  lua_pushstring(L, "terrain_quality");
612  lua_rawset(L, -3);
613 
614  lua_pushstring(L, "alternative_terrain_quality");
616  lua_rawset(L, -3);
617 
618  lua_pushstring(L, "vulnerability");
620  lua_rawset(L, -3);
621 
622  lua_pushstring(L, "support");
623  lua_pushnumber(L, aa.support);
624  lua_rawset(L, -3);
625 
626  lua_pushstring(L, "leader_threat");
628  lua_rawset(L, -3);
629 
630  lua_pushstring(L, "uses_leader");
632  lua_rawset(L, -3);
633 
634  lua_pushstring(L, "is_surrounded");
636  lua_rawset(L, -3);
637 }
638 
639 static void push_move_map(lua_State *L, const move_map& m)
640 {
641  lua_createtable(L, 0, 0); // the main table
642 
643  if (m.empty())
644  {
645  return;
646  }
647 
648  move_map::const_iterator it = m.begin();
649 
650  int index = 1;
651 
653 
654  do
655  {
656  map_location key = it->first;
657  lua_pushinteger(L, lhash(key));
658 
659  lua_createtable(L, 0, 0);
660 
661  while (key == it->first) {
662 
663  luaW_pushlocation(L, it->second);
664  lua_rawseti(L, -2, index);
665 
666  ++index;
667  ++it;
668 
669  }
670 
671  lua_settable(L, -3);
672 
673  index = 1;
674 
675  } while (it != m.end());
676 }
677 
679 {
682  push_move_map(L, dst_src);
683  return 1;
684 }
685 
687 {
690  push_move_map(L, src_dst);
691  return 1;
692 }
693 
695 {
696  move_map enemy_dst_src = get_readonly_context(L).get_enemy_dstsrc();
698  push_move_map(L, enemy_dst_src);
699  return 1;
700 }
701 
703 {
704  move_map enemy_src_dst = get_readonly_context(L).get_enemy_srcdst();
706  push_move_map(L, enemy_src_dst);
707  return 1;
708 }
709 
711 {
712  bool valid = get_readonly_context(L).is_dst_src_valid_lua();
713  lua_pushboolean(L, valid);
714  return 1;
715 }
716 
718 {
720  lua_pushboolean(L, valid);
721  return 1;
722 }
723 
725 {
726  bool valid = get_readonly_context(L).is_src_dst_valid_lua();
727  lua_pushboolean(L, valid);
728  return 1;
729 }
730 
732 {
734  lua_pushboolean(L, valid);
735  return 1;
736 }
737 
739 {
741  return 0;
742 }
743 
745 {
747  return 0;
748 }
749 
750 template<typename T>
752 {
753  return std::dynamic_pointer_cast<typesafe_aspect<T> >(p).get();
754 }
755 
757 {
758  const aspect_map& aspects = get_engine(L).get_readonly_context().get_aspects();
759  aspect_map::const_iterator iter = aspects.find(luaL_checkstring(L, 2));
760  if(iter == aspects.end()) {
761  return 0;
762  }
763 
764  // A few aspects require special delicate handling...
765  if(typesafe_aspect<attacks_vector>* aspect_as_attacks_vector = try_aspect_as<attacks_vector>(iter->second)) {
767  aspect_attacks_base* real_aspect = dynamic_cast<aspect_attacks_base*>(aspect_as_attacks_vector);
768  while(real_aspect == nullptr) {
769  // It's probably a composite aspect, so find the active facet
770  composite_aspect<attacks_vector>& composite = dynamic_cast<composite_aspect<attacks_vector>&>(*aspect_as_attacks_vector);
771  aspect_as_attacks_vector = &dynamic_cast<typesafe_aspect<attacks_vector>&>(composite.find_active());
772  real_aspect = dynamic_cast<aspect_attacks_base*>(aspect_as_attacks_vector);
773  }
774  int my_side = get_engine(L).get_readonly_context().get_side();
775  std::vector<unit_const_ptr> attackers, enemies;
776  for(unit_map::const_iterator u = resources::gameboard->units().begin(); u != resources::gameboard->units().end(); ++u) {
777  if(!u.valid()) {
778  continue;
779  }
780  if(u->side() == my_side && real_aspect->is_allowed_attacker(*u)) {
781  attackers.push_back(u.get_shared_ptr());
782  } else if(u->side() != my_side && real_aspect->is_allowed_enemy(*u)) {
783  enemies.push_back(u.get_shared_ptr());
784  }
785  }
786  lua_createtable(L, 0, 2);
787  lua_createtable(L, attackers.size(), 0);
788  for(size_t i = 0; i < attackers.size(); i++) {
789  luaW_pushunit(L, attackers[i]->underlying_id());
790  lua_rawseti(L, -2, i + 1);
791  }
792  lua_setfield(L, -2, "own");
793  lua_createtable(L, enemies.size(), 0);
794  for(size_t i = 0; i < enemies.size(); i++) {
795  luaW_pushunit(L, enemies[i]->underlying_id());
796  lua_rawseti(L, -2, i + 1);
797  }
798  lua_setfield(L, -2, "enemy");
799  } else if(typesafe_aspect<unit_advancements_aspect>* aspect_as_unit_advancements_aspects = try_aspect_as<unit_advancements_aspect>(iter->second)) {
800  const unit_advancements_aspect& val = aspect_as_unit_advancements_aspects->get();
801  int my_side = get_engine(L).get_readonly_context().get_side();
802  lua_newtable(L);
804  for (unit_map::const_iterator u = resources::gameboard->units().begin(); u != resources::gameboard->units().end(); ++u) {
805  if (!u.valid() || u->side() != my_side) {
806  continue;
807  }
808  lua_pushinteger(L, lhash(u->get_location()));
809  lua_push(L, val.get_advancements(u));
810  lua_settable(L, -3);
811  }
812  } else {
813  iter->second->get_lua(L);
814  }
815  return 1;
816 }
817 
819 {
820  lua_pushstring(L, "attempted to write to the ai.aspects table, which is read-only");
821  return lua_error(L);
822 }
823 
824 static int impl_ai_get(lua_State* L)
825 {
826  if(!lua_isstring(L,2)) {
827  return 0;
828  }
830  std::string m = lua_tostring(L,2);
831  if(m == "side") {
833  return 1;
834  }
835  if(m == "aspects") {
836  lua_newtable(L); // [-1: Aspects table]
837  lua_newtable(L); // [-1: Aspects metatable -2: Aspects table]
838  lua_pushlightuserdata(L, &engine); // [-1: Engine -2: Aspects mt -3: Aspects table]
839  lua_pushcclosure(L, &impl_ai_aspect_get, 1); // [-1: Metafunction -2: Aspects mt -3: Aspects table]
840  lua_setfield(L, -2, "__index"); // [-1: Aspects metatable -2: Aspects table]
841  lua_pushcfunction(L, &impl_ai_aspect_set); // [-1: Metafunction -2: Aspects mt -3: Aspects table]
842  lua_setfield(L, -2, "__newindex"); // [-1: Aspects metatable -2: Aspects table]
843  lua_setmetatable(L, -2); // [-1: Aspects table]
844  return 1;
845  }
846  static luaL_Reg const callbacks[] = {
847  // Move maps
848  { "get_new_dst_src", &cfun_ai_get_dstsrc },
849  { "get_new_src_dst", &cfun_ai_get_srcdst },
850  { "get_new_enemy_dst_src", &cfun_ai_get_enemy_dstsrc },
851  { "get_new_enemy_src_dst", &cfun_ai_get_enemy_srcdst },
852  { "recalculate_move_maps", &cfun_ai_recalculate_move_maps },
853  { "recalculate_enemy_move_maps", &cfun_ai_recalculate_move_maps_enemy },
854  // End of move maps
855  // Goals and targets
856  { "get_targets", &cfun_ai_get_targets },
857  // End of G & T
858  // Aspects
859  { "get_aggression", &cfun_ai_get_aggression },
860  { "get_avoid", &cfun_ai_get_avoid },
861  { "get_attacks", &cfun_ai_get_attacks },
862  { "get_caution", &cfun_ai_get_caution },
863  { "get_grouping", &cfun_ai_get_grouping },
864  { "get_leader_aggression", &cfun_ai_get_leader_aggression },
865  { "get_leader_goal", &cfun_ai_get_leader_goal },
866  { "get_leader_ignores_keep", &cfun_ai_get_leader_ignores_keep },
867  { "get_leader_value", &cfun_ai_get_leader_value },
868  { "get_passive_leader", &cfun_ai_get_passive_leader },
869  { "get_passive_leader_shares_keep", &cfun_ai_get_passive_leader_shares_keep },
870  { "get_recruitment_pattern", &cfun_ai_get_recruitment_pattern },
871  { "get_scout_village_targeting", &cfun_ai_get_scout_village_targeting },
872  { "get_simple_targeting", &cfun_ai_get_simple_targeting },
873  { "get_support_villages", &cfun_ai_get_support_villages },
874  { "get_village_value", &cfun_ai_get_village_value },
875  { "get_villages_per_scout", &cfun_ai_get_villages_per_scout },
876  // End of aspects
877  // Validation/cache functions
878  { "is_dst_src_valid", &cfun_ai_is_dst_src_valid },
879  { "is_enemy_dst_src_valid", &cfun_ai_is_dst_src_enemy_valid },
880  { "is_src_dst_valid", &cfun_ai_is_src_dst_valid },
881  { "is_enemy_src_dst_valid", &cfun_ai_is_src_dst_enemy_valid },
882  // End of validation functions
883  { "suitable_keep", &cfun_ai_get_suitable_keep },
884  { "check_recall", &cfun_ai_check_recall },
885  { "check_move", &cfun_ai_check_move },
886  { "check_stopunit", &cfun_ai_check_stopunit },
887  { "check_attack", &cfun_ai_check_attack },
888  { "check_recruit", &cfun_ai_check_recruit },
889  //{ "",},
890  //{ "",},
891  { nullptr, nullptr } };
892  for (const luaL_Reg* p = callbacks; p->name; ++p) {
893  if(m == p->name) {
894  lua_pushlightuserdata(L, &engine); // [-1: engine ...]
895  lua_pushcclosure(L, p->func, 1); // [-1: function ...]
896  // Store the function so that __index doesn't need to be called next time
897  lua_pushstring(L, p->name); // [-1: name -2: function ...]
898  lua_pushvalue(L, -2); // [-1: function -2: name -3: function ...]
899  lua_rawset(L, 1); // [-1: function ...]
900  return 1;
901  }
902  }
903  lua_pushstring(L, "read_only");
904  lua_rawget(L, 1);
905  bool read_only = luaW_toboolean(L, -1);
906  lua_pop(L, 1);
907  if(read_only) {
908  return 0;
909  }
910  static luaL_Reg const mutating_callbacks[] = {
911  { "attack", &cfun_ai_execute_attack },
912  { "move", &cfun_ai_execute_move_partial },
913  { "move_full", &cfun_ai_execute_move_full },
914  { "recall", &cfun_ai_execute_recall },
915  { "recruit", &cfun_ai_execute_recruit },
916  { "stopunit_all", &cfun_ai_execute_stopunit_all },
917  { "stopunit_attacks", &cfun_ai_execute_stopunit_attacks },
918  { "stopunit_moves", &cfun_ai_execute_stopunit_moves },
919  { "fallback_human", &cfun_ai_fallback_human},
920  { nullptr, nullptr } };
921  for (const luaL_Reg* p = mutating_callbacks; p->name; ++p) {
922  if(m == p->name) {
923  lua_pushlightuserdata(L, &engine);
924  lua_pushcclosure(L, p->func, 1);
925  return 1;
926  }
927  }
928  return 0;
929 }
930 
932  //push data table here
933  lua_newtable(L); // [-1: ai table]
934  lua_newtable(L); // [-1: metatable -2: ai table]
935  lua_pushlightuserdata(L, engine); // [-1: engine -2: metatable -3: ai table]
936  lua_pushcclosure(L, &impl_ai_get, 1); // [-1: metafunc -2: metatable -3: ai table]
937  lua_setfield(L, -2, "__index"); // [-1: metatable -2: ai table]
938  lua_setmetatable(L, -2); // [-1: ai table]
939 }
940 
942 {
943  // Retrieve the ai elements table from the registry.
944  lua_getfield(L, LUA_REGISTRYINDEX, aisKey); // [-1: AIs registry table]
945  size_t length_ai = lua_rawlen(L, -1); // length of table
946  lua_newtable(L); // [-1: AI state table -2: AIs registry table]
947  generate_and_push_ai_table(L, engine); // [-1: AI routines -2: AI state -3: AIs registry]
948  lua_setfield(L, -2, "ai"); // [-1: AI state -2: AIs registry]
949  lua_pushvalue(L, -1); // [-1: AI state -2: AI state -3: AIs registry]
950  lua_rawseti(L, -3, length_ai + 1); // [-1: AI state -2: AIs registry]
951  lua_remove(L, -2); // [-1: AI state table]
952  return length_ai + 1;
953 }
954 
956 {
957  luaW_getglobal(L, "wesnoth", "wml_actions", "micro_ai");
958  luaW_pushconfig(L, cfg);
959  luaW_pcall(L, 1, 0);
960 }
961 
963 {
964  int res_ai = luaL_loadbufferx(L, code, strlen(code), /*name*/ code, "t"); // [-1: AI code]
965  if (res_ai != 0)
966  {
967 
968  char const *m = lua_tostring(L, -1);
969  ERR_LUA << "error while initializing ai: " <<m << '\n';
970  lua_pop(L, 2);//return with stack size 0 []
971  return nullptr;
972  }
973  //push data table here
974  size_t idx = generate_and_push_ai_state(L, engine); // [-1: AI state -2: AI code]
975  lua_pushvalue(L, -2); // [-1: AI code -2: AI state -3: AI code]
976  lua_setfield(L, -2, "update_self"); // [-1: AI state -2: AI code]
977  lua_pushlightuserdata(L, engine);
978  lua_setfield(L, -2, "engine"); // [-1: AI state -2: AI code]
979  lua_pop(L, 2);
980  return new lua_ai_context(L, idx, engine->get_readonly_context().get_side());
981 }
982 
984 {
985  lua_ai_load ctx(*this, true); // [-1: AI state table]
986 
987  // Load the AI code and arguments
988  lua_getfield(L, -1, "update_self"); // [-1: AI code -2: AI state]
989  lua_getfield(L, -2, "params"); // [-1: Arguments -2: AI code -3: AI state]
990  lua_getfield(L, -3, "data"); // [-1: Persistent data -2: Arguments -3: AI code -4: AI state]
991 
992  // Call the function
993  if (!luaW_pcall(L, 2, 1, true)) { // [-1: Result -2: AI state]
994  return; // return with stack size 0 []
995  }
996 
997  // Store the state for use by components
998  lua_setfield(L, -2, "self"); // [-1: AI state]
999 
1000  // And return with empty stack.
1001  lua_pop(L, 1);
1002 }
1003 
1005 {
1006  int res = luaL_loadbufferx(L, code, strlen(code), /*name*/ code, "t");//stack size is now 1 [ -1: f]
1007  if (res)
1008  {
1009  char const *m = lua_tostring(L, -1);
1010  ERR_LUA << "error while creating ai function: " <<m << '\n';
1011  lua_pop(L, 2);//return with stack size 0 []
1012  return nullptr;
1013  }
1014 
1015  // Retrieve the ai elements table from the registry.
1016  lua_getfield(L, LUA_REGISTRYINDEX, aisKey); //stack size is now 2 [-1: ais_table -2: f]
1017  // Push the function in the table so that it is not collected.
1018  size_t length = lua_rawlen(L, -1);//length of ais_table
1019  lua_pushvalue(L, -2); //stack size is now 3: [-1: f -2: ais_table -3: f]
1020  lua_rawseti(L, -2, length + 1);// ais_table[length+1]=f. stack size is now 2 [-1: ais_table -2: f]
1021  lua_remove(L, -1);//stack size is now 1 [-1: f]
1022  lua_remove(L, -1);//stack size is now 0 []
1023  // Create the proxy C++ action handler.
1024  return new lua_ai_action_handler(L, context, length + 1);
1025 }
1026 
1027 int lua_ai_load::refcount = 0;
1028 
1029 lua_ai_load::lua_ai_load(lua_ai_context& ctx, bool read_only) : L(ctx.L), was_readonly(false)
1030 {
1031  refcount++;
1032  lua_getfield(L, LUA_REGISTRYINDEX, aisKey); // [-1: AI registry]
1033  lua_rawgeti(L, -1, ctx.num_); // [-1: AI state -2: AI registry]
1034  lua_remove(L,-2); // [-1: AI state]
1035 
1036  // Check if the AI table is already loaded. If so, we have less work to do.
1037  lua_getglobal(L, "ai");
1038  if(!lua_isnoneornil(L, -1)) {
1039  // Save the previous read-only state
1040  lua_getfield(L, -1, "read_only");
1041  was_readonly = luaW_toboolean(L, -1);
1042  lua_pop(L, 1);
1043  // Update the read-only state
1044  lua_pushstring(L, "read_only");
1045  lua_pushboolean(L, read_only);
1046  lua_rawset(L, -3);
1047  lua_pop(L, 1); // Pop the ai table off the stack
1048  } else {
1049  lua_pop(L, 1); // Pop the nil value off the stack
1050  // Load the AI functions table into global scope
1051  lua_getfield(L, -1, "ai"); // [-1: AI functions -2: AI state]
1052  lua_pushstring(L, "read_only"); // [-1: key -2: AI functions -3: AI state]
1053  lua_pushboolean(L, read_only); // [-1: value -2: key -3: AI functions -4: AI state]
1054  lua_rawset(L, -3); // [-1: AI functions -2: AI state]
1055  lua_setglobal(L, "ai"); // [-1: AI state]
1056  }
1057 }
1058 
1060 {
1061  refcount--;
1062  if (refcount == 0) {
1063  // Remove the AI functions from the global scope
1064  lua_pushnil(L);
1065  lua_setglobal(L, "ai");
1066  } else {
1067  // Restore the read-only state
1068  lua_getglobal(L, "ai");
1069  lua_pushstring(L, "read_only");
1071  lua_rawset(L, -3);
1072  lua_pop(L, 1);
1073  }
1074 }
1075 
1077 {
1078  // Remove the ai context from the registry, so that it can be collected.
1080  lua_pushnil(L);
1081  lua_rawseti(L, -2, num_);
1082  lua_pop(L, 1);
1083 }
1084 
1085 void lua_ai_action_handler::handle(const config &cfg, const config &filter_own, bool read_only, lua_object_ptr l_obj)
1086 {
1087  int initial_top = lua_gettop(L);//get the old stack size
1088 
1089  // Load the context
1090  lua_ai_load ctx(context_, read_only); // [-1: AI state table]
1091 
1092  // Load the user function from the registry.
1093  lua_getfield(L, LUA_REGISTRYINDEX, aisKey); // [-1: AI registry -2: AI state]
1094  lua_rawgeti(L, -1, num_); // [-1: AI action -2: AI registry -3: AI state]
1095  lua_remove(L, -2); // [-1: AI action -2: AI state]
1096 
1097  // Load the arguments
1098  int iState = lua_absindex(L, -2);
1099  lua_getfield(L, iState, "self");
1100  luaW_pushconfig(L, cfg);
1101  lua_getfield(L, iState, "data");
1102 
1103  int num = 3;
1104  if (!filter_own.empty()) {
1105  luaW_pushconfig(L, filter_own);
1106  num=4;
1107  }
1108 
1109  // Call the function
1110  luaW_pcall(L, num, l_obj ? 1 : 0, true);
1111  if (l_obj) {
1112  l_obj->store(L, -1);
1113  }
1114 
1115  lua_settop(L, initial_top);//empty stack
1116 }
1117 
1119 {
1120  // Remove the function from the registry, so that it can be collected.
1122  lua_pushnil(L);
1123  lua_rawseti(L, -2, num_);
1124  lua_pop(L, 1);
1125 }
1126 
1127 } // of namespace ai
std::shared_ptr< action_result > action_result_ptr
Definition: game_info.hpp:79
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:124
#define lua_isnoneornil(L, n)
Definition: lua.h:379
static int cfun_ai_get_passive_leader_shares_keep(lua_State *L)
Definition: core.cpp:458
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:639
double avg_damage_taken
The average hitpoints damage taken.
Definition: contexts.hpp:102
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:116
virtual void set_src_dst_enemy_valid_lua()=0
unit_iterator end()
Definition: map.hpp:429
virtual bool is_src_dst_valid_lua() const =0
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:87
virtual const aspect_map & get_aspects() const =0
virtual const unit_map & units() const override
Definition: game_board.hpp:112
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:812
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:121
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:97
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:478
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:284
LUA_API int lua_gettop(lua_State *L)
Definition: lapi.cpp:168
static int cfun_ai_get_avoid(lua_State *L)
Definition: core.cpp:380
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:305
#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:85
map_location target
Definition: contexts.hpp:84
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:678
#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:121
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:499
static lua_ai_context * create(lua_State *L, char const *code, engine_lua *engine)
Definition: core.cpp:962
LUA_API int lua_rawget(lua_State *L, int idx)
Definition: lapi.cpp:698
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:514
#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:84
virtual const move_map & get_enemy_srcdst() const =0
static int cfun_ai_get_srcdst(lua_State *L)
Definition: core.cpp:686
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:105
double chance_to_kill
Estimated % chance to kill the unit.
Definition: contexts.hpp:94
static int cfun_ai_recalculate_move_maps(lua_State *L)
Definition: core.cpp:738
static config unit_name(const unit *u)
Definition: reports.cpp:160
virtual const attacks_vector & get_attacks() const =0
void lua_push(lua_State *L, const T &val)
Definition: push_check.hpp:385
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:775
std::shared_ptr< attack_result > attack_result_ptr
Definition: game_info.hpp:82
static int cfun_ai_get_leader_goal(lua_State *L)
Definition: core.cpp:411
int luaW_push_locationset(lua_State *L, const std::set< map_location > &locs)
Converts a set of map locations to a Lua table pushed at the top of the stack.
Definition: lua_common.cpp:783
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
double terrain_quality
The weighted average of the % chance to hit each attacking unit.
Definition: contexts.hpp:108
static int cfun_ai_get_support_villages(lua_State *L)
Definition: core.cpp:492
static int ai_recall(lua_State *L, bool exec)
Definition: core.cpp:294
#define lua_pop(L, n)
Definition: lua.h:364
std::shared_ptr< aspect > aspect_ptr
Definition: game_info.hpp:95
double target_value
The value of the unit being targeted.
Definition: contexts.hpp:88
std::multimap< map_location, map_location > move_map
The standard way in which a map of possible moves is recorded.
Definition: game_info.hpp:43
std::vector< attack_analysis > attacks_vector
Definition: game_info.hpp:51
static int cfun_ai_get_villages_per_scout(lua_State *L)
Definition: core.cpp:506
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:445
void handle(const config &cfg, const config &filter_own, bool read_only, lua_object_ptr l_obj)
Definition: core.cpp:1085
A small explanation about what&#39;s going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:61
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:87
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:1027
std::shared_ptr< recall_result > recall_result_ptr
Definition: game_info.hpp:83
void set_persistent_data(const config &)
Definition: core.cpp:108
bool was_readonly
Definition: core.hpp:62
static int cfun_ai_is_src_dst_valid(lua_State *L)
Definition: core.cpp:724
bool luaW_getglobal(lua_State *L, const std::vector< std::string > &path)
Pushes the value found by following the variadic names (char *), if the value is not nil...
Definition: lua_common.cpp:953
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:972
virtual const terrain_filter & get_avoid() const =0
static int cfun_ai_get_leader_ignores_keep(lua_State *L)
Definition: core.cpp:439
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:143
double alternative_terrain_quality
The weighted average of the % defense of the best possible terrain that the attacking units could rea...
Definition: contexts.hpp:115
Proxy table for the AI context.
Definition: core.hpp:33
static int ai_move(lua_State *L, bool exec, bool remove_movement)
Definition: core.cpp:176
static lua_ai_action_handler * create(lua_State *L, char const *code, lua_ai_context &context)
Definition: core.cpp:1004
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:355
static void push_attack_analysis(lua_State *L, const attack_analysis &)
Definition: core.cpp:559
lua_ai_load(lua_ai_context &ctx, bool read_only)
Definition: core.cpp:1029
static int impl_ai_aspect_get(lua_State *L)
Definition: core.cpp:756
game_board * gameboard
Definition: resources.cpp:21
static int cfun_ai_get_enemy_dstsrc(lua_State *L)
Definition: core.cpp:694
static int cfun_ai_get_attacks(lua_State *L)
Definition: core.cpp:362
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:60
static int cfun_ai_is_src_dst_enemy_valid(lua_State *L)
Definition: core.cpp:731
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:485
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 both types are passed throgh std::decay first.
Definition: general.hpp:33
static void push_movements(lua_State *L, const std::vector< std::pair< map_location, map_location > > &moves)
Definition: core.cpp:534
static int cfun_ai_get_grouping(lua_State *L)
Definition: core.cpp:397
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:38
bool uses_leader
Is true if this attack sequence makes use of the leader.
Definition: contexts.hpp:127
#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:341
bool luaW_toconfig(lua_State *L, int index, config &cfg)
Converts an optional table or vconfig to a config object.
Definition: lua_common.cpp:824
void push_ai_table()
Definition: core.cpp:132
static int cfun_ai_get_targets(lua_State *L)
Definition: core.cpp:322
static int cfun_ai_check_recruit(lua_State *L)
Definition: core.cpp:289
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:710
static void init(lua_State *L)
Definition: core.cpp:62
std::size_t i
Definition: function.cpp:967
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:39
mock_party p
virtual const team & current_team() const =0
virtual void set_dst_src_enemy_valid_lua()=0
virtual const map_location & suitable_keep(const map_location &leader_location, const pathfind::paths &leader_paths) const =0
get most suitable keep for leader - nearest free that can be reached in 1 turn, if none - return near...
virtual bool is_src_dst_enemy_valid_lua() const =0
std::vector< std::pair< map_location, map_location > > movements
Definition: contexts.hpp:85
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:1003
static int cfun_ai_recalculate_move_maps_enemy(lua_State *L)
Definition: core.cpp:744
double avg_losses
The value on average, of units lost in the combat.
Definition: contexts.hpp:91
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:1038
#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:270
static int impl_ai_aspect_set(lua_State *L)
Definition: core.cpp:818
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:72
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:70
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:1049
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
void apply_micro_ai(const config &cfg)
Definition: core.cpp:955
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:129
static int impl_ai_get(lua_State *L)
Definition: core.cpp:824
LUA_API int lua_error(lua_State *L)
Definition: lapi.cpp:1205
std::map< std::string, aspect_ptr > aspect_map
Definition: game_info.hpp:104
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:715
const map_location & get_location() const
The current map location this unit is at.
Definition: unit.hpp:1346
readonly_context & get_readonly_context()
Definition: engine.cpp:142
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:72
static const map_location & null_location()
Definition: location.hpp:81
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:941
static int cfun_ai_get_caution(lua_State *L)
Definition: core.cpp:390
bool is_surrounded
Is true if the units involved in this attack sequence are surrounded.
Definition: contexts.hpp:130
static int cfun_ai_get_passive_leader(lua_State *L)
Definition: core.cpp:452
virtual double get_scout_village_targeting() const =0
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:61
static void generate_and_push_ai_table(lua_State *L, ai::engine_lua *engine)
Definition: core.cpp:931
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:404
std::string::const_iterator iterator
Definition: tokenizer.hpp:25
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:751
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:702
bool empty() const
Definition: config.cpp:941
void update_state()
Definition: core.cpp:983
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:1015
virtual double get_caution() const =0
static int cfun_ai_is_dst_src_enemy_valid(lua_State *L)
Definition: core.cpp:717
bool luaW_tolocation(lua_State *L, int index, map_location &loc)
Converts an optional table or pair of integers to a map location object.
Definition: lua_common.cpp:726
static int cfun_ai_get_recruitment_pattern(lua_State *L)
Definition: core.cpp:464
static int cfun_ai_fallback_human(lua_State *)
Definition: core.cpp:315
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:1070
std::shared_ptr< lua_object_base > lua_object_ptr
Definition: core.hpp:27
static int cfun_ai_check_recall(lua_State *L)
Definition: core.cpp:310
#define luaL_checkstring(L, n)
Definition: lauxlib.h:138