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