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