The Battle for Wesnoth  1.17.12+dev
actions.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2022
3  by Yurii Chernyi <terraninfo@terraninfo.net>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 /**
17  * Managing the AI-Game interaction - AI actions and their results
18  * @file
19  * */
20 
21 #pragma once
22 
23 #include "ai/game_info.hpp"
24 
25 #include "actions/move.hpp"
26 #include "units/ptr.hpp"
27 
28 namespace pathfind {
29 struct plain_route;
30 } // of namespace pathfind
31 
32 class unit;
33 class unit_type;
34 class team;
35 
36 namespace ai {
37 
39 friend void sim_gamestate_changed(action_result *result, bool gamestate_changed); // Manage gamestate changed in simulated actions.
40 
41 public:
42 
43  enum result {
44  AI_ACTION_SUCCESS = 0,
45  AI_ACTION_STARTED = 1,
46  AI_ACTION_FAILURE = -1
47  };
48 
49  virtual ~action_result();
50 
51  /* check as must as possible without executing anything */
52  void check_before();
53 
54  /* execute the action */
55  void execute();
56 
57  /* has the game state changed during execution ? */
58  bool is_gamestate_changed() const;
59 
60  /* check the return value of the action. mandatory to call. */
61  bool is_ok();
62 
63  /* get the return value of the action */
64  int get_status() const;
65 
66  /* describe the action */
67  virtual std::string do_describe() const =0;
68 protected:
69  action_result( side_number side );
70 
71  /* do check before execution or just check. setting status_ via set_error to != cancels the execution.*/
72  virtual void do_check_before() = 0;
73 
74  /* do some additional checks after execution. */
75  virtual void do_check_after() = 0;
76 
77  /* execute. assert(is_success()) */
78  virtual void do_execute() = 0;
79 
80  /* runs before cheching before execution */
81  virtual void do_init_for_execution() = 0;
82 
83  /* are we going to execute the action now ? */
84  bool is_execution() const;
85 
86  /* return the side number */
87  int get_side() const { return side_; }
88 
89  /* return real information about the game state */
90  game_info& get_info() const;
91 
92  team& get_my_team() const;
93 
94  /* set error code */
95  void set_error(int error_code, bool log_as_error = true);
96 
97  /* is error code equal to 0 (no errors)? */
98  bool is_success() const;
99 
100  /* note that the game state has been changed */
101  void set_gamestate_changed();
102 private:
103 
104  /* Check after the execution */
105  void check_after();
106 
107  /* Initialization before execution */
108  void init_for_execution();
109 
110  /* set the flag that the return value had been checked */
111  void set_ok_checked();
112 
113  /* was the return value checked ? */
115 
116  /* current side number */
117  int side_;
118 
119  /* execution status. if 0, all is ok. if !=0, then there were some problems. */
120  int status_;
121 
122  /* are we going to execute the action now ? */
124 
126 
127 };
128 
129 class attack_result : public action_result {
130 public:
132  const map_location& attacker_loc,
133  const map_location& defender_loc,
134  int attacker_weapon,
135  double aggression);
136 
137  enum result {
138  E_EMPTY_ATTACKER = 1001,
139  E_EMPTY_DEFENDER = 1002,
140  E_INCAPACITATED_ATTACKER = 1003,
141  E_INCAPACITATED_DEFENDER = 1004,
142  E_NOT_OWN_ATTACKER = 1005,
143  E_NOT_ENEMY_DEFENDER = 1006,
144  E_NO_ATTACKS_LEFT = 1007,
145  E_WRONG_ATTACKER_WEAPON = 1008,
146  E_UNABLE_TO_CHOOSE_ATTACKER_WEAPON = 1009,
147  E_ATTACKER_AND_DEFENDER_NOT_ADJACENT = 1010
148  };
149 
150  virtual std::string do_describe() const;
151 protected:
152  virtual void do_check_before();
153  virtual void do_check_after();
154  virtual void do_execute();
155  virtual void do_init_for_execution();
156 private:
160  double aggression_;
161 };
162 
163 class move_result : public action_result {
164 public:
165  move_result( side_number side,
166  const map_location& from,
167  const map_location& to,
168  bool remove_movement,
169  bool unreach_is_ok);
170 
171  enum result {
172  E_EMPTY_MOVE = 2001,
173  E_NO_UNIT = 2002,
174  E_NOT_OWN_UNIT = 2003,
175  E_INCAPACITATED_UNIT = 2004,
176  E_AMBUSHED = 2005,
177  E_FAILED_TELEPORT = 2006,
178  E_OFF_MAP = 2007,
179  E_NO_ROUTE = 2008
180  };
181 
182  virtual std::string do_describe() const;
183  virtual const map_location& get_unit_location() const;
184 protected:
185  virtual void do_check_before();
186  virtual void do_check_after();
187  virtual void do_execute();
188  virtual void do_init_for_execution();
189 private:
190  const unit *get_unit();
191  bool test_route(const unit &un);
195  std::shared_ptr<pathfind::plain_route> route_;
200 };
201 
202 
203 class recall_result : public action_result {
204 public:
205  recall_result (side_number side, const std::string &unit_id, const map_location& where, const map_location& from);
206 
207  enum result {
208  E_NOT_AVAILABLE_FOR_RECALLING = 6001,
209  E_NO_GOLD = 6003,
210  E_NO_LEADER = 6004,
211  E_LEADER_NOT_ON_KEEP = 6005,
212  E_BAD_RECALL_LOCATION = 6006
213  };
214 
215  virtual std::string do_describe() const;
216 protected:
217  virtual void do_check_before();
218  virtual void do_check_after();
219  virtual void do_execute();
220  virtual void do_init_for_execution();
221 private:
222  unit_const_ptr get_recall_unit(
223  const team& my_team);
224  bool test_enough_gold(
225  const team& my_team);
226 
227  const std::string& unit_id_;
232 };
233 
235 public:
236  recruit_result( side_number side, const std::string& unit_name, const map_location& where, const map_location& from);
237 
238  enum result {
239  E_NOT_AVAILABLE_FOR_RECRUITING = 3001,
240  E_UNKNOWN_OR_DUMMY_UNIT_TYPE = 3002,
241  E_NO_GOLD = 3003,
242  E_NO_LEADER = 3004,
243  E_LEADER_NOT_ON_KEEP = 3005,
244  E_BAD_RECRUIT_LOCATION = 3006
245  };
246 
247  virtual std::string do_describe() const;
248 protected:
249  virtual void do_check_before();
250  virtual void do_check_after();
251  virtual void do_execute();
252  virtual void do_init_for_execution();
253 private:
254  const unit_type *get_unit_type_known(
255  const std::string &recruit);
256  bool test_enough_gold(
257  const team& my_team,
258  const unit_type &type );
259 
260  const std::string& unit_name_;
265 };
266 
268 public:
270  const map_location& unit_location,
271  bool remove_movement,
272  bool remove_attacks );
273 
274  enum result {
275  E_NO_UNIT = 4002,
276  E_NOT_OWN_UNIT = 4003,
277  E_INCAPACITATED_UNIT = 4004
278  };
279 
280  virtual std::string do_describe() const;
281 protected:
282  virtual void do_check_before();
283  virtual void do_check_after();
284  virtual void do_execute();
285  virtual void do_init_for_execution();
286 private:
287  const unit *get_unit();
289  const bool remove_movement_;
290  const bool remove_attacks_;
291 };
292 
294 public:
296  const std::string& lua_code,
297  const map_location& location );
298 
299  virtual std::string do_describe() const;
300 protected:
301  virtual void do_check_before();
302  virtual void do_check_after();
303  virtual void do_execute();
304  virtual void do_init_for_execution();
305 private:
306  const std::string& lua_code_;
308 };
309 
310 
311 class actions {
312 
313 public:
314 // =======================================================================
315 // Stateless interface to actions
316 // =======================================================================
317 
318 
319 /**
320  * Ask the game to attack an enemy defender using our unit attacker from attackers current location,
321  * @param side the side which tries to execute the move
322  * @param execute should move be actually executed or not
323  * @param attacker_loc location of attacker
324  * @param defender_loc location of defender
325  * @param attacker_weapon weapon of attacker
326  * @param aggression aggression of attacker, is used to determine attacker's weapon if it is not specified
327  * @retval possible results: ok, something wrong, attacker and/or defender are invalid, or attacker doesn't have the specified weapon
328  */
329 static attack_result_ptr execute_attack_action( side_number side,
330  bool execute,
331  const map_location& attacker_loc,
332  const map_location& defender_loc,
333  int attacker_weapon,
334  double aggression);
335 
336 
337 /**
338  * Ask the game to move our unit from location 'from' to location 'to', optionally - doing a partial move
339  * @param side the side which tries to execute the move
340  * @param execute should move be actually executed or not
341  * @param from location of our unit
342  * @param to where to move
343  * @param remove_movement set unit movement to 0 in case of successful move
344  * @param unreach_is_ok whether it's okay for a destination to be unreachable
345  * @retval possible results: ok, something wrong, move is interrupted, or move is impossible
346  */
347 static move_result_ptr execute_move_action( side_number side,
348  bool execute,
349  const map_location& from,
350  const map_location& to,
351  bool remove_movement,
352  bool unreach_is_ok = false);
353 
354 
355 
356 /**
357  * Ask the game to recall a unit for us on specified location
358  * @param side the side which tries to execute the move
359  * @param execute should move be actually executed or not
360  * @param unit_id the id of the unit to be recalled.
361  * @param where location where the unit is to be recalled.
362  * @param from the location where the unit was recruited from.
363  * @retval possible results: ok, something wrong, leader not on keep, no free space on keep, or not enough gold
364  */
365 static recall_result_ptr execute_recall_action( side_number side,
366  bool execute,
367  const std::string& unit_id,
368  const map_location& where,
369  const map_location& from);
370 
371 
372 
373 /**
374  * Ask the game to recruit a unit for us on specified location
375  * @param side the side which tries to execute the move
376  * @param execute should move be actually executed or not
377  * @param unit_name the name of the unit to be recruited.
378  * @param where location where the unit is to be recruited.
379  * @param from the location where the unit was recruited from.
380  * @retval possible results: ok, something wrong, leader not on keep, no free space on keep, or not enough gold
381  */
382 static recruit_result_ptr execute_recruit_action( side_number side,
383  bool execute,
384  const std::string& unit_name,
385  const map_location& where,
386  const map_location& from);
387 
388 
389 /**
390  * Ask the game to remove unit movements and/or attack
391  * @param side the side which tries to execute the move
392  * @param execute should move be actually executed or not
393  * @param unit_location the location of our unit
394  * @param remove_movement set remaining movements to 0
395  * @param remove_attacks set remaining attacks to 0
396  * @retval possible results: ok, something wrong, or nothing to do
397  */
398 static stopunit_result_ptr execute_stopunit_action( side_number side,
399  bool execute,
400  const map_location& unit_location,
401  bool remove_movement,
402  bool remove_attacks );
403 
404 
405 /**
406  * Ask the game to run Lua code
407  * @param side the side which tries to execute the move
408  * @param execute should move be actually executed or not
409  * @param lua_code the code to be run
410  * @param location location to be passed to the code as x1/y1
411  * @retval possible results: ok, something wrong, or nothing to do
412  */
413 static synced_command_result_ptr execute_synced_command_action( side_number side,
414  bool execute,
415  const std::string& lua_code,
416  const map_location& location );
417 
418 
419 /**
420  * get human-readable name of the error by code.
421  * @param error_code error code.
422  * @retval result the name of the error.
423  */
424 const static std::string& get_error_name(int error_code);
425 
426 private:
427 
428 static const std::map<int, std::string> error_names_;
429 
430 };
431 
432 
433 } //end of namespace ai
434 
435 std::ostream &operator<<(std::ostream &s, const ai::attack_result& r);
436 std::ostream &operator<<(std::ostream &s, const ai::move_result& r);
437 std::ostream &operator<<(std::ostream &s, const ai::recall_result& r);
438 std::ostream &operator<<(std::ostream &s, const ai::recruit_result& r);
439 std::ostream &operator<<(std::ostream &s, const ai::stopunit_result& r);
440 std::ostream &operator<<(std::ostream &s, const ai::synced_command_result& r);
bool unreach_is_ok_
Definition: actions.hpp:197
map_location recruit_location_
Definition: actions.hpp:262
map_location recruit_from_
Definition: actions.hpp:263
bool has_ambusher_
Definition: actions.hpp:198
bool remove_movement_
Definition: actions.hpp:194
map_location recall_from_
Definition: actions.hpp:230
std::shared_ptr< stopunit_result > stopunit_result_ptr
Definition: game_info.hpp:87
This class represents a single unit of a specific type.
Definition: unit.hpp:133
map_location unit_location_
Definition: actions.hpp:196
map_location recall_location_
Definition: actions.hpp:229
const map_location & where_
Definition: actions.hpp:261
const std::string & unit_id_
Definition: actions.hpp:227
std::shared_ptr< move_result > move_result_ptr
Definition: game_info.hpp:85
int get_side() const
Definition: actions.hpp:87
std::shared_ptr< recruit_result > recruit_result_ptr
Definition: game_info.hpp:84
const map_location from_
Definition: actions.hpp:192
static config unit_name(const unit *u)
Definition: reports.cpp:161
const std::string & lua_code_
Definition: actions.hpp:306
std::shared_ptr< attack_result > attack_result_ptr
Definition: game_info.hpp:82
bool has_interrupted_teleport_
Definition: actions.hpp:199
std::shared_ptr< pathfind::plain_route > route_
Definition: actions.hpp:195
A single unit type that the player may recruit.
Definition: types.hpp:45
std::shared_ptr< const unit > unit_const_ptr
Definition: ptr.hpp:27
This class stores all the data for a single &#39;side&#39; (in game nomenclature).
Definition: team.hpp:75
A small explanation about what&#39;s going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:61
std::shared_ptr< recall_result > recall_result_ptr
Definition: game_info.hpp:83
Structure which holds a single route between one location and another.
Definition: pathfind.hpp:132
bool return_value_checked_
Definition: actions.hpp:114
bool location_checked_
Definition: actions.hpp:231
double aggression_
Definition: actions.hpp:160
const bool remove_movement_
Definition: actions.hpp:289
const std::string & unit_name_
Definition: actions.hpp:260
void sim_gamestate_changed(action_result *result, bool gamestate_changed)
Definition: actions.cpp:1124
std::shared_ptr< synced_command_result > synced_command_result_ptr
Definition: game_info.hpp:88
Encapsulates the map of the game.
Definition: location.hpp:38
Various functions related to moving units.
const bool remove_attacks_
Definition: actions.hpp:290
const map_location & defender_loc_
Definition: actions.hpp:158
Game information for the AI.
static const std::map< int, std::string > error_names_
Definition: actions.hpp:428
static map_location::DIRECTION s
bool is_gamestate_changed_
Definition: actions.hpp:125
const map_location & unit_location_
Definition: actions.hpp:288
std::ostream & operator<<(std::ostream &s, const ai::attack_result &r)
Definition: actions.cpp:1134
const map_location to_
Definition: actions.hpp:193
int side_number
Definition: game_info.hpp:40
const map_location where_
Definition: actions.hpp:228
const map_location & attacker_loc_
Definition: actions.hpp:157
const map_location & location_
Definition: actions.hpp:307