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