Freeciv21
Develop your civilization from humble roots to a global empire
aiparatrooper.cpp
Go to the documentation of this file.
1 /*
2 Copyright (c) 1996-2020 Freeciv21 and Freeciv contributors. This file is
3  /\/\ part of Freeciv21. Freeciv21 is free software: you can
4  \_\ _..._ redistribute it and/or modify it under the terms of the
5  (" )(_..._) GNU General Public License as published by the Free
6  ^^ // \\ Software Foundation, either version 3 of the License,
7  or (at your option) any later version. You should have
8 received a copy of the GNU General Public License along with Freeciv21.
9  If not, see https://www.gnu.org/licenses/.
10  */
11 
12 // utility
13 #include "log.h"
14 
15 // common
16 #include "city.h"
17 #include "game.h"
18 #include "player.h"
19 #include "research.h"
20 #include "unit.h"
21 #include "unitlist.h"
22 
23 // server
24 #include "maphand.h"
25 #include "srv_log.h"
26 #include "unithand.h"
27 #include "unittools.h"
28 
29 /* server/advisors */
30 #include "advdata.h"
31 
32 /* server/generator */
33 #include "mapgen_utils.h"
34 
35 // ai
36 #include "handicaps.h"
37 
38 /* ai/default */
39 #include "aidata.h"
40 #include "ailog.h"
41 #include "aiplayer.h"
42 #include "aitools.h"
43 #include "aiunit.h"
44 #include "daicity.h"
45 
46 #include "aiparatrooper.h"
47 
48 #define LOGLEVEL_PARATROOPER LOG_DEBUG
49 
53 static struct tile *find_best_tile_to_paradrop_to(struct ai_type *ait,
54  struct unit *punit)
55 {
56  int best = 0;
57  int val;
58  struct tile *best_tile = nullptr;
60  struct city *acity;
61  struct player *pplayer = unit_owner(punit);
62 
63  // First, we search for undefended cities in danger
64  square_iterate(&(wld.map), unit_tile(punit), range, ptile)
65  {
66  if (!map_is_known(ptile, pplayer)) {
67  continue;
68  }
69 
70  acity = tile_city(ptile);
71  if (acity && city_owner(acity) == unit_owner(punit)
72  && unit_list_size(ptile->units) == 0) {
73  val = city_size_get(acity) * def_ai_city_data(acity, ait)->urgency;
74  if (val > best) {
75  best = val;
76  best_tile = ptile;
77  }
78  }
79  }
81 
82  if (best_tile != nullptr) {
83  acity = tile_city(best_tile);
85  "Choose to jump in order to protect allied city %s (%d %d). "
86  "Benefit: %d",
87  city_name_get(acity), TILE_XY(best_tile), best);
88  return best_tile;
89  }
90 
91  // Second, we search for undefended enemy cities
92  square_iterate(&(wld.map), unit_tile(punit), range, ptile)
93  {
94  acity = tile_city(ptile);
95  if (acity && pplayers_at_war(unit_owner(punit), city_owner(acity))
96  && (unit_list_size(ptile->units) == 0)) {
97  if (!map_is_known_and_seen(ptile, pplayer, V_MAIN)
98  && has_handicap(pplayer, H_FOG)) {
99  continue;
100  }
101  // Prefer big cities on other continents
102  val = city_size_get(acity)
103  + (tile_continent(unit_tile(punit)) != tile_continent(ptile));
104  if (val > best) {
105  best = val;
106  best_tile = ptile;
107  }
108  }
109  }
111 
112  if (best_tile != nullptr) {
113  acity = tile_city(best_tile);
115  "Choose to jump into enemy city %s (%d %d). Benefit: %d",
116  city_name_get(acity), TILE_XY(best_tile), best);
117  return best_tile;
118  }
119 
120  // Jump to kill adjacent units
121  square_iterate(&(wld.map), unit_tile(punit), range, ptile)
122  {
123  struct terrain *pterrain = tile_terrain(ptile);
124  if (is_ocean(pterrain)) {
125  continue;
126  }
127  if (!map_is_known(ptile, pplayer)) {
128  continue;
129  }
130  acity = tile_city(ptile);
131  if (acity && !pplayers_allied(city_owner(acity), pplayer)) {
132  continue;
133  }
134  if (!acity && unit_list_size(ptile->units) > 0) {
135  continue;
136  }
137  // Iterate over adjacent tile to find good victim
138  adjc_iterate(&(wld.map), ptile, target)
139  {
140  if (unit_list_size(target->units) == 0
141  || !can_unit_attack_tile(punit, target) || is_ocean_tile(target)
142  || (has_handicap(pplayer, H_FOG)
143  && !map_is_known_and_seen(target, pplayer, V_MAIN))) {
144  continue;
145  }
146  val = 0;
147  if (is_stack_vulnerable(target)) {
148  unit_list_iterate(target->units, victim)
149  {
150  if ((!has_handicap(pplayer, H_FOG)
151  || can_player_see_unit(pplayer, victim))
152  && (unit_attack_unit_at_tile_result(punit, victim, target)
153  == ATT_OK)) {
154  val += victim->hp * 100;
155  }
156  }
158  } else {
159  val += get_defender(punit, target)->hp * 100;
160  }
161  val *= unit_win_chance(punit, get_defender(punit, target));
162  val += pterrain->defense_bonus / 10;
163  val -= punit->hp * 100;
164 
165  if (val > best) {
166  best = val;
167  best_tile = ptile;
168  }
169  }
171  }
173 
174  if (best_tile != nullptr) {
175  UNIT_LOG(LOG_DEBUG, punit,
176  "Choose to jump at (%d, %d) to attack "
177  "adjacent units. Benefit: %d",
178  TILE_XY(best_tile), best);
179  }
180 
181  return best_tile;
182 }
183 
187 void dai_manage_paratrooper(struct ai_type *ait, struct player *pplayer,
188  struct unit *punit)
189 {
190  struct city *pcity = tile_city(unit_tile(punit));
191  struct tile *ptile_dest = nullptr;
192 
193  int sanity = punit->id;
194 
195  // defend attacking (and be opportunistic too)
198  // dead
199  return;
200  }
201 
202  // check to recover hit points
203  if ((punit->hp < unit_type_get(punit)->hp / 2) && pcity) {
204  UNIT_LOG(LOGLEVEL_PARATROOPER, punit, "Recovering hit points.");
205  return;
206  }
207 
208  // nothing to do!
209  if (punit->moves_left == 0) {
210  return;
211  }
212 
213  if (pcity && unit_list_size(unit_tile(punit)->units) == 1) {
214  UNIT_LOG(LOGLEVEL_PARATROOPER, punit, "Defending the city.");
215  return;
216  }
217 
218  if (can_unit_paradrop(punit)) {
219  ptile_dest = find_best_tile_to_paradrop_to(ait, punit);
220 
221  if (ptile_dest) {
222  if (unit_perform_action(unit_owner(punit), punit->id,
223  tile_index(ptile_dest), 0, "", ACTION_PARADROP,
224  ACT_REQ_PLAYER)) {
225  // successfull!
226  if (nullptr == game_unit_by_number(sanity)) {
227  // the unit did not survive the move
228  return;
229  }
230  // and we attack the target
233  }
234  }
235  } else {
236  // we can't paradrop :-(
237  struct city *acity = nullptr;
238 
239  // we are in a city, so don't try to find another
240  if (pcity) {
242  "waiting in a city for next turn.");
243  return;
244  }
245 
246  // find a city to go to recover and paradrop from
247  acity = find_nearest_safe_city(punit);
248 
249  if (acity) {
250  UNIT_LOG(LOGLEVEL_PARATROOPER, punit, "Going to %s",
251  city_name_get(acity));
252  if (!dai_unit_goto(ait, punit, acity->tile)) {
253  // die or unsuccessfull move
254  return;
255  }
256  } else {
258  "didn't find city to go and recover.");
259  dai_manage_military(ait, pplayer, punit);
260  }
261  }
262 }
263 
268 static int calculate_want_for_paratrooper(struct unit *punit,
269  struct tile *ptile_city)
270 {
271  const struct unit_type *u_type = unit_type_get(punit);
272  int range = u_type->paratroopers_range;
273  int profit = 0;
274  struct player *pplayer = unit_owner(punit);
275  int total, total_cities;
276 
277  profit +=
278  u_type->defense_strength + u_type->move_rate + u_type->attack_strength;
279 
280  square_iterate(&(wld.map), ptile_city, range, ptile)
281  {
282  int multiplier;
283  struct city *pcity = tile_city(ptile);
284 
285  if (!pcity) {
286  continue;
287  }
288 
289  if (!map_is_known(ptile, pplayer)) {
290  continue;
291  }
292 
293  /* We prefer jumping to other continents. On the same continent we
294  * can fight traditionally.
295  * FIXME: Handle ocean cities we can attack. */
296  if (!is_ocean_tile(ptile)
297  && tile_continent(ptile_city) != tile_continent(ptile)) {
298  if (get_continent_size(tile_continent(ptile)) < 3) {
299  // Tiny island are hard to conquer with traditional units
300  multiplier = 10;
301  } else {
302  multiplier = 5;
303  }
304  } else {
305  multiplier = 1;
306  }
307 
308  /* There are lots of units, the city will be safe against paratroopers.
309  */
310  if (unit_list_size(ptile->units) > 2) {
311  continue;
312  }
313 
314  /* Prefer long jumps.
315  * If a city is near we can take/protect it with normal units */
316  if (pplayers_allied(pplayer, city_owner(pcity))) {
317  profit += city_size_get(pcity) * multiplier
318  * real_map_distance(ptile_city, ptile) / 2;
319  } else {
320  profit += city_size_get(pcity) * multiplier
321  * real_map_distance(ptile_city, ptile);
322  }
323  }
325 
326  total = adv_data_get(pplayer, nullptr)->stats.units.paratroopers;
327  total_cities = city_list_size(pplayer->cities);
328 
329  if (total > total_cities) {
330  profit = profit * total_cities / total;
331  }
332 
333  return profit;
334 }
335 
339 void dai_choose_paratrooper(struct ai_type *ait, struct player *pplayer,
340  struct city *pcity, struct adv_choice *choice,
341  bool allow_gold_upkeep)
342 {
343  const struct research *presearch;
344  int profit;
346  Tech_type_id requirements[A_LAST];
347  int num_requirements = 0;
348  int i;
349  struct ai_plr *plr_data = def_ai_player_data(pplayer, ait);
350 
351  /* military_advisor_choose_build does something idiotic,
352  * this function should not be called if there is danger... */
353  if (choice->want >= 100 && choice->type != CT_ATTACKER) {
354  return;
355  }
356 
357  unit_type_iterate(u_type)
358  {
359  struct unit *virtual_unit;
360 
361  if (!utype_can_do_action(u_type, ACTION_PARADROP)) {
362  continue;
363  }
364  if (A_NEVER == u_type->require_advance) {
365  continue;
366  }
367 
368  if (!allow_gold_upkeep
369  && utype_upkeep_cost(u_type, pplayer, O_GOLD) > 0) {
370  continue;
371  }
372 
373  // Temporary hack because pathfinding can't handle Fighters.
374  if (!utype_is_consumed_by_action_result(ACTRES_ATTACK, u_type)
375  && 1 == utype_fuel(u_type)) {
376  continue;
377  }
378 
379  // assign tech for paratroopers
380  tech_req = advance_index(u_type->require_advance);
381  if (tech_req != A_NONE && tech_req != A_UNSET) {
382  for (i = 0; i < num_requirements; i++) {
383  if (requirements[i] == tech_req) {
384  break;
385  }
386  }
387  if (i == num_requirements) {
388  requirements[num_requirements++] = tech_req;
389  }
390  }
391 
392  // we only update choice struct if we can build it!
393  if (!can_city_build_unit_now(pcity, u_type)) {
394  continue;
395  }
396 
397  // it's worth building that unit?
398  virtual_unit = unit_virtual_create(
399  pplayer, pcity, u_type,
400  city_production_unit_veteran_level(pcity, u_type));
401  profit = calculate_want_for_paratrooper(virtual_unit, pcity->tile);
402  unit_virtual_destroy(virtual_unit);
403 
404  // update choice struct if it's worth
405  if (profit > choice->want) {
406  // Update choice
407  choice->want = profit;
408  choice->value.utype = u_type;
409  choice->type = CT_ATTACKER;
410  choice->need_boat = false;
411  adv_choice_set_use(choice, "paratrooper");
412  log_base(LOGLEVEL_PARATROOPER, "%s wants to build %s (want=%d)",
413  city_name_get(pcity), utype_rule_name(u_type), profit);
414  }
415  }
417 
418  // we raise want if the required tech is not known
419  presearch = research_get(pplayer);
420  for (i = 0; i < num_requirements; i++) {
421  tech_req = requirements[i];
422  plr_data->tech_want[tech_req] += 2;
424  "Raising tech want in city %s for %s "
425  "stimulating %s with %d (" ADV_WANT_PRINTF ") and req",
426  city_name_get(pcity), player_name(pplayer),
428  plr_data->tech_want[tech_req]);
429 
430  // now, we raise want for prerequisites
432  {
433  if (research_goal_tech_req(presearch, tech_req, k)) {
434  plr_data->tech_want[k] += 1;
435  }
436  }
438  }
439 }
#define adv_choice_set_use(_choice, _use)
Definition: advchoice.h:69
@ CT_ATTACKER
Definition: advchoice.h:26
struct adv_data * adv_data_get(struct player *pplayer, bool *caller_closes)
Return a pointer to our data.
Definition: advdata.cpp:591
void dai_manage_paratrooper(struct ai_type *ait, struct player *pplayer, struct unit *punit)
This function does manage the paratrooper units of the AI.
void dai_choose_paratrooper(struct ai_type *ait, struct player *pplayer, struct city *pcity, struct adv_choice *choice, bool allow_gold_upkeep)
Chooses to build a paratroopers if necessary.
#define LOGLEVEL_PARATROOPER
static struct tile * find_best_tile_to_paradrop_to(struct ai_type *ait, struct unit *punit)
Find best tile the paratrooper should jump to.
static int calculate_want_for_paratrooper(struct unit *punit, struct tile *ptile_city)
Evaluate value of the unit.
static struct ai_plr * def_ai_player_data(const struct player *pplayer, struct ai_type *deftype)
Definition: aiplayer.h:47
static struct ai_city * def_ai_city_data(const struct city *pcity, struct ai_type *deftype)
Definition: aiplayer.h:35
bool dai_unit_goto(struct ai_type *ait, struct unit *punit, struct tile *ptile)
Go to specified destination but do not disturb existing role or activity and do not clear the role's ...
Definition: aitools.cpp:609
void dai_manage_military(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Decide what to do with a military unit.
Definition: aiunit.cpp:2399
struct city * find_nearest_safe_city(struct unit *punit)
Find safe city to recover in.
Definition: aiunit.cpp:1620
bool dai_military_rampage(struct unit *punit, int thresh_adj, int thresh_move)
Find and kill anything reachable within this turn and worth more than the relevant of the given thres...
Definition: aiunit.cpp:592
#define RAMPAGE_ANYTHING
Definition: aiunit.h:90
#define RAMPAGE_FREE_CITY_OR_BETTER
Definition: aiunit.h:92
struct player * city_owner(const struct city *pcity)
Return the owner of the city.
Definition: city.cpp:1083
int city_production_unit_veteran_level(struct city *pcity, const struct unit_type *punittype)
How many veteran levels will created unit of this type get?
Definition: city.cpp:768
const char * city_name_get(const struct city *pcity)
Return the name of the city.
Definition: city.cpp:1077
citizens city_size_get(const struct city *pcity)
Get the city size.
Definition: city.cpp:1101
bool can_city_build_unit_now(const struct city *pcity, const struct unit_type *punittype)
Return whether given city can build given unit; returns FALSE if unit is obsolete.
Definition: city.cpp:894
struct unit * get_defender(const struct unit *attacker, const struct tile *ptile)
Finds the best defender on the tile, given an attacker.
Definition: combat.cpp:721
enum unit_attack_result unit_attack_unit_at_tile_result(const struct unit *punit, const struct unit *pdefender, const struct tile *dest_tile)
Checks if a unit can physically attack pdefender at the tile (assuming it is adjacent and at war).
Definition: combat.cpp:121
bool is_stack_vulnerable(const struct tile *ptile)
Is it a city/fortress/air base or will the whole stack die in an attack.
Definition: combat.cpp:839
double unit_win_chance(const struct unit *attacker, const struct unit *defender)
Returns a double in the range [0;1] indicating the attackers chance of winning.
Definition: combat.cpp:408
bool can_unit_attack_tile(const struct unit *punit, const struct tile *dest_tile)
Is unit (1) diplomatically allowed to attack and (2) physically able to do so?
Definition: combat.cpp:251
@ ATT_OK
Definition: combat.h:26
int Tech_type_id
Definition: fc_types.h:294
#define ADV_WANT_PRINTF
Definition: fc_types.h:1145
@ O_GOLD
Definition: fc_types.h:88
struct unit * game_unit_by_number(int id)
Find unit out of all units in game: now uses fast idex method, instead of looking through all units o...
Definition: game.cpp:112
struct world wld
Definition: game.cpp:48
bool has_handicap(const struct player *pplayer, enum handicap_type htype)
AI players may have handicaps - allowing them to cheat or preventing them from using certain algorith...
Definition: handicaps.cpp:62
@ H_FOG
Definition: handicaps.h:25
constexpr auto LOG_DEBUG
Definition: log.h:27
#define log_base(level, message,...)
Definition: log.h:41
int real_map_distance(const struct tile *tile0, const struct tile *tile1)
Return real distance between two tiles.
Definition: map.cpp:599
#define adjc_iterate_end
Definition: map.h:358
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition: map.h:312
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition: map.h:351
#define square_iterate_end
Definition: map.h:315
int get_continent_size(Continent_id id)
Return size in tiles of the given continent (not ocean)
bool map_is_known(const struct tile *ptile, const struct player *pplayer)
Return whether the player knows the tile.
Definition: maphand.cpp:884
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Returns whether the layer 'vlayer' of the tile 'ptile' is known and seen by the player 'pplayer'.
Definition: maphand.cpp:894
bool can_player_see_unit(const struct player *pplayer, const struct unit *punit)
Checks if a unit can be seen by pplayer at its current location.
Definition: player.cpp:1016
bool pplayers_at_war(const struct player *pplayer, const struct player *pplayer2)
Returns true iff players can attack each other.
Definition: player.cpp:1317
const char * player_name(const struct player *pplayer)
Return the leader name of the player.
Definition: player.cpp:816
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Returns true iff players are allied.
Definition: player.cpp:1334
bool research_goal_tech_req(const struct research *presearch, Tech_type_id goal, Tech_type_id tech)
Returns if the given tech has to be researched to reach the goal.
Definition: research.cpp:794
struct research * research_get(const struct player *pplayer)
Returns the research structure associated with the player.
Definition: research.cpp:110
#define UNIT_LOG(_, punit, msg,...)
Definition: srv_log.h:95
enum choice_type type
Definition: advchoice.h:32
adv_want want
Definition: advchoice.h:34
universals_u value
Definition: advchoice.h:33
bool need_boat
Definition: advchoice.h:35
struct adv_data::@87 stats
struct adv_data::@87::@90 units
int urgency
Definition: daicity.h:46
Definition: aidata.h:63
adv_want tech_want[A_LAST+1]
Definition: aidata.h:95
Definition: ai.h:42
Definition: city.h:291
struct tile * tile
Definition: city.h:293
Definition: player.h:231
struct city_list * cities
Definition: player.h:263
int defense_bonus
Definition: terrain.h:186
Definition: tile.h:42
struct unit_list * units
Definition: tile.h:50
int defense_strength
Definition: unittype.h:480
int paratroopers_range
Definition: unittype.h:506
int move_rate
Definition: unittype.h:481
int attack_strength
Definition: unittype.h:479
Definition: unit.h:134
int moves_left
Definition: unit.h:147
int id
Definition: unit.h:141
int hp
Definition: unit.h:148
struct civ_map map
Definition: world_object.h:21
const char * advance_rule_name(const struct advance *padvance)
Return the (untranslated) rule name of the advance/technology.
Definition: tech.cpp:283
struct advance * advance_by_number(const Tech_type_id atype)
Return the advance for the given advance index.
Definition: tech.cpp:94
Tech_type_id advance_index(const struct advance *padvance)
Return the advance index.
Definition: tech.cpp:76
#define A_NEVER
Definition: tech.h:44
#define advance_index_iterate_end
Definition: tech.h:226
tech_req
Definition: tech.h:104
#define A_FIRST
Definition: tech.h:37
#define A_NONE
Definition: tech.h:36
#define A_UNSET
Definition: tech.h:41
#define A_LAST
Definition: tech.h:38
#define advance_index_iterate(_start, _index)
Definition: tech.h:221
#define is_ocean(pterrain)
Definition: terrain.h:276
#define is_ocean_tile(ptile)
Definition: terrain.h:279
struct city * tile_city(const struct tile *ptile)
Return the city on this tile (or nullptr), checking for city center.
Definition: tile.cpp:72
#define tile_index(_pt_)
Definition: tile.h:70
#define tile_terrain(_tile)
Definition: tile.h:93
#define TILE_XY(ptile)
Definition: tile.h:36
#define tile_continent(_tile)
Definition: tile.h:74
const struct unit_type * utype
Definition: fc_types.h:585
bool can_unit_paradrop(const struct unit *punit)
Return whether the unit can be paradropped - that is, if the unit is in a friendly city or on an airb...
Definition: unit.cpp:772
void unit_virtual_destroy(struct unit *punit)
Free the memory used by virtual unit.
Definition: unit.cpp:1588
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Create a virtual unit skeleton.
Definition: unit.cpp:1490
#define unit_tile(_pu)
Definition: unit.h:371
#define unit_owner(_pu)
Definition: unit.h:370
bool unit_perform_action(struct player *pplayer, const int actor_id, const int target_id, const int sub_tgt_id_incoming, const char *name, const action_id action_type, const enum action_requester requester)
Execute a request to perform an action and let the caller know if it was performed or not.
Definition: unithand.cpp:2737
#define unit_list_iterate(unitlist, punit)
Definition: unitlist.h:25
#define unit_list_iterate_end
Definition: unitlist.h:27
const struct unit_type * unit_type_get(const struct unit *punit)
Return the unit type for this unit.
Definition: unittype.cpp:114
int utype_upkeep_cost(const struct unit_type *ut, struct player *pplayer, Output_type_id otype)
Returns the upkeep of a unit of this type under the given government.
Definition: unittype.cpp:123
const char * utype_rule_name(const struct unit_type *punittype)
Return the (untranslated) rule name of the unit type.
Definition: unittype.cpp:1274
bool utype_is_consumed_by_action_result(enum action_result result, const struct unit_type *utype)
Returns TRUE iff performing an action with the specified action result will consume an actor unit of ...
Definition: unittype.cpp:947
bool utype_can_do_action(const struct unit_type *putype, const action_id act_id)
Return TRUE iff units of the given type can do the specified generalized (ruleset defined) action ena...
Definition: unittype.cpp:386
#define utype_fuel(ptype)
Definition: unittype.h:772
#define unit_type_iterate(_p)
Definition: unittype.h:785
#define unit_type_iterate_end
Definition: unittype.h:791