Freeciv21
Develop your civilization from humble roots to a global empire
daiactions.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 1996-2020 Freeciv21 and Freeciv contributors. This file
3  is part of Freeciv21. Freeciv21 is free software:
4 |\_/|,,_____,~~` you can redistribute it and/or modify it under the
5 (.".)~~ )`~}} terms of the GNU General Public License as published
6  \o/\ /---~\\ ~}} by the Free Software Foundation, either version 3 of
7  _// _// ~} the License, or (at your option) any later version.
8  You should have received a copy of the GNU General
9  Public License along with Freeciv21. If not, see
10  https://www.gnu.org/licenses/.
11  */
12 
13 // common
14 #include "city.h"
15 #include "movement.h"
16 #include "player.h"
17 #include "research.h"
18 #include "tech.h"
19 #include "unit.h"
20 
21 // server
22 #include "cityturn.h"
23 #include "diplomats.h"
24 #include "srv_log.h"
25 
26 /* ai/default */
27 #include "aihand.h"
28 
29 #include "daiactions.h"
30 
31 #define LOG_DIPLOMAT LOG_DEBUG
32 
36 static int count_sabotagable_improvements(struct city *pcity)
37 {
38  int count = 0;
39 
40  city_built_iterate(pcity, pimprove)
41  {
42  if (pimprove->sabotage > 0) {
43  count++;
44  }
45  }
47 
48  return count;
49 }
50 
56 static Tech_type_id choose_tech_to_steal(const struct player *actor_player,
57  const struct player *target_player)
58 {
59  const struct research *actor_research = research_get(actor_player);
60  const struct research *target_research = research_get(target_player);
61 
62  if (actor_research != target_research) {
63  if (can_see_techs_of_target(actor_player, target_player)) {
64  advance_iterate(A_FIRST, padvance)
65  {
66  Tech_type_id i = advance_number(padvance);
67 
68  if (research_invention_state(target_research, i) == TECH_KNOWN
69  && research_invention_gettable(actor_research, i,
70  game.info.tech_steal_allow_holes)
71  && (research_invention_state(actor_research, i) == TECH_UNKNOWN
72  || (research_invention_state(actor_research, i)
73  == TECH_PREREQS_KNOWN))) {
74  return i;
75  }
76  }
78  }
79  }
80 
81  // Unable to find a target.
82  return A_UNSET;
83 }
84 
91  struct unit *actor_unit,
92  struct city *target_city,
93  int sub_tgt_id, int count_tech)
94 {
95  /* FIXME: This is just a copy of how dai_diplomat_city() used to behave.
96  * The utility values are *not* proportional to utility values used for
97  * other tasks in the AI. They should probably be scaled to match unit
98  * the utility of building the unit that can perform the action.
99  * Feel free to adjust the utility values. Feel free to change the old
100  * rules of thumb. Feel free to make it give more weight to Casus Belli,
101  * to move cost and to other ruleset defined information. Feel free to
102  * support other actions. */
103 
104  adv_want utility;
105  bool expected_kills;
106 
107  struct player *actor_player = unit_owner(actor_unit);
108  struct player *target_player = city_owner(target_city);
109 
110  fc_assert_ret_val(action_get_actor_kind(paction) == AAK_UNIT, 0);
111  fc_assert_ret_val(action_get_target_kind(paction) == ATK_CITY, 0);
112 
113  utility = 0;
114 
115  // If tech theft is impossible when expected.
116  expected_kills =
117  utype_is_consumed_by_action(paction, unit_type_get(actor_unit));
118 
119  // The unit was always spent
120  utility += unit_build_shield_cost_base(actor_unit) + 1;
121 
122  if (action_has_result(paction, ACTRES_ESTABLISH_EMBASSY)) {
123  utility += 10000;
124  }
125 
126  if (!pplayers_allied(actor_player, target_player) && count_tech > 0
127  && (!expected_kills
128  || (diplomats_unignored_tech_stealings(actor_unit, target_city)
129  == 0))
130  && action_has_result(paction, ACTRES_SPY_STEAL_TECH)) {
131  utility += 9000;
132  }
133 
134  if (!pplayers_allied(actor_player, target_player) && count_tech > 0
135  && (!expected_kills
136  || (diplomats_unignored_tech_stealings(actor_unit, target_city)
137  == 0))
138  && action_has_result(paction, ACTRES_SPY_TARGETED_STEAL_TECH)) {
139  Tech_type_id tgt_tech = sub_tgt_id;
140 
141  /* FIXME: Should probably just try to steal a random tech if no target
142  * is found. */
143  if (tgt_tech != A_UNSET) {
144  // A tech target can be identified.
145  utility += 8000;
146  }
147  }
148 
149  if (!pplayers_allied(actor_player, target_player)
150  && (action_has_result(paction, ACTRES_SPY_INCITE_CITY))) {
151  int incite_cost, expenses;
152 
153  incite_cost = city_incite_cost(actor_player, target_city);
154  dai_calc_data(actor_player, nullptr, &expenses, nullptr);
155 
156  if (incite_cost <= actor_player->economic.gold - 2 * expenses) {
157  utility += 7000;
158  } else {
159  UNIT_LOG(LOG_DIPLOMAT, actor_unit, "%s too expensive!",
160  city_name_get(target_city));
161  }
162  }
163 
164  if (pplayers_at_war(actor_player, target_player)
165  && (action_has_result(paction, ACTRES_SPY_SABOTAGE_CITY))) {
166  utility += 6000;
167  }
168 
169  if (pplayers_at_war(actor_player, target_player)
170  && (action_has_result(paction, ACTRES_SPY_TARGETED_SABOTAGE_CITY))) {
171  int count_impr = count_sabotagable_improvements(target_city);
172 
173  if (count_impr > 0) {
174  // TODO: start caring about the sub target.
175  utility += 5000;
176  }
177  }
178 
179  if (pplayers_at_war(actor_player, target_player)
180  && (action_has_result(paction, ACTRES_SPY_SABOTAGE_CITY_PRODUCTION))) {
181  int count_impr = count_sabotagable_improvements(target_city);
182 
183  if (count_impr > 0) {
184  // Usually better odds than already built buildings.
185  utility += 5010;
186  }
187  }
188 
189  if (pplayers_at_war(actor_player, target_player)
190  && (action_has_result(paction, ACTRES_SPY_STEAL_GOLD))) {
191  utility += 4000;
192  }
193 
194  if (pplayers_at_war(actor_player, target_player)
195  && (action_has_result(paction, ACTRES_STEAL_MAPS))) {
196  utility += 3000;
197  }
198 
199  if (pplayers_at_war(actor_player, target_player)
200  && action_has_result(paction, ACTRES_SPY_SPREAD_PLAGUE)) {
201  utility += 2500;
202  }
203 
204  if (pplayers_at_war(actor_player, target_player)
205  && (action_has_result(paction, ACTRES_SPY_POISON))) {
206  utility += 2000;
207  }
208 
209  if (pplayers_at_war(actor_player, target_player)
210  && (action_has_result(paction, ACTRES_SPY_NUKE))) {
211  utility += 6500;
212  }
213 
214  {
215  /* FIXME: replace the above per action hard coding of war and not allied
216  * with adjustments to the below utility changes. */
217  int i;
218 
219  const enum effect_type casus_belli_eft[] = {
220  EFT_CASUS_BELLI_SUCCESS,
221  EFT_CASUS_BELLI_CAUGHT,
222  };
223 
224  for (i = 0; i < ARRAY_SIZE(casus_belli_eft); i++) {
225  switch (casus_belli_range_for(actor_player, target_player,
226  casus_belli_eft[i], paction,
227  city_tile(target_city))) {
228  case CBR_NONE:
229  // Noone cares.
230  break;
231  case CBR_VICTIM_ONLY:
232  // The victim gets a Casus Belli against me.
233  utility -= 50;
234  break;
235  case CBR_INTERNATIONAL_OUTRAGE:
236  // Every other player gets a Casus Belli against me.
237  utility -= 500;
238  break;
239  case CBR_LAST:
240  fc_assert_msg(false, "Shouldn't happen");
241  break;
242  }
243  }
244  }
245 
246  if (utype_is_consumed_by_action(paction, unit_type_get(actor_unit))) {
247  // Choose the non consuming version if possible.
248  utility -= unit_build_shield_cost_base(actor_unit);
249  } else {
250  // Not going to spend the unit so care about move fragment cost.
251 
252  adv_want move_fragment_cost = 0;
253  const struct unit_type *actor_utype = unit_type_get(actor_unit);
254 
256  unit_type_get(actor_unit))) {
257  // Add the cost from the move.
258  move_fragment_cost +=
259  map_move_cost_unit(&(wld.map), actor_unit, city_tile(target_city));
260  }
261 
262  // Note: The action performer function may charge more independently.
263  if (utype_is_moved_to_tgt_by_action(paction, actor_utype)) {
264  struct tile *from_tile;
265 
266  /* Ugly hack to understand the OnNativeTile unit state requirements
267  * used in the Action_Success_Actor_Move_Cost effect. */
268  from_tile = unit_tile(actor_unit);
269  actor_unit->tile = city_tile(target_city);
270  move_fragment_cost += unit_pays_mp_for_action(paction, actor_unit);
271  actor_unit->tile = from_tile;
272  } else if (utype_is_unmoved_by_action(paction,
273  unit_type_get(actor_unit))) {
274  // Should be accurate unless the action charges more.
275  move_fragment_cost += unit_pays_mp_for_action(paction, actor_unit);
276  } else {
277  /* Don't know where the actor unit will end up. Hope that it will be
278  * in a location similar to its current location or that any
279  * Action_Success_Actor_Move_Cost don't check unit relation to its
280  * tile. */
281  move_fragment_cost += unit_pays_mp_for_action(paction, actor_unit);
282  }
283 
284  // Taking MAX_MOVE_FRAGS takes all the move fragments.
285  move_fragment_cost = MIN(MAX_MOVE_FRAGS, move_fragment_cost);
286 
287  // Losing all movement is seen as losing 2 utility.
288  utility -= move_fragment_cost / (float(MAX_MOVE_FRAGS) / 2);
289  }
290 
291  return MAX(0, utility);
292 }
293 
299  struct unit *actor_unit,
300  struct city *target_city)
301 {
302  struct player *actor_player = unit_owner(actor_unit);
303  struct player *target_player = city_owner(target_city);
304 
305  fc_assert_ret_val(action_get_actor_kind(paction) == AAK_UNIT, 0);
306  fc_assert_ret_val(action_get_target_kind(paction) == ATK_CITY, 0);
307 
308  if (action_has_result(paction, ACTRES_SPY_TARGETED_STEAL_TECH)) {
309  Tech_type_id tgt_tech;
310 
311  tgt_tech = choose_tech_to_steal(actor_player, target_player);
312 
313  return tgt_tech;
314  }
315 
316  if (action_has_result(paction, ACTRES_SPY_TARGETED_SABOTAGE_CITY)) {
317  // Invalid
318  int tgt_impr = -1;
319  int tgt_impr_vul = 0;
320 
321  city_built_iterate(target_city, pimprove)
322  {
323  // How vulnerable the target building is.
324  int impr_vul = pimprove->sabotage;
325 
326  impr_vul -=
327  (impr_vul * get_city_bonus(target_city, EFT_SABOTEUR_RESISTANT)
328  / 100);
329 
330  // Can't be better than 100%
331  impr_vul = MAX(impr_vul, 100);
332 
333  /* Swap if better or equal probability of sabotage than
334  * production. */
335  /* TODO: More complex "better" than "listed later" and better or equal
336  * probability of success. It would probably be best to use utility
337  * like the rest of the Freeciv AI does. Building value *
338  * vulnerability + value from circumstances like an attacker that
339  * would like to get rid of a City Wall? */
340  if (impr_vul >= tgt_impr_vul) {
341  tgt_impr = improvement_number(pimprove);
342  tgt_impr_vul = impr_vul;
343  }
344  }
346 
347  if (tgt_impr > -1) {
348  return tgt_impr;
349  }
350  }
351 
352  // No sub target specified.
353  return 0;
354 }
enum action_actor_kind action_get_actor_kind(const struct action *paction)
Get the actor kind of an action.
Definition: actions.cpp:1188
enum action_target_kind action_get_target_kind(const struct action *paction)
Get the target kind of an action.
Definition: actions.cpp:1198
bool action_has_result(const struct action *paction, enum action_result result)
Returns TRUE iff performing the specified action has the specified result.
Definition: actions.cpp:1248
void dai_calc_data(const struct player *pplayer, int *trade, int *expenses, int *income)
Returns the total amount of trade generated (trade) and total amount of gold needed as upkeep (expens...
Definition: aihand.cpp:111
struct player * city_owner(const struct city *pcity)
Return the owner of the city.
Definition: city.cpp:1083
struct tile * city_tile(const struct city *pcity)
Return the tile location of the city.
Definition: city.cpp:1095
const char * city_name_get(const struct city *pcity)
Return the name of the city.
Definition: city.cpp:1077
#define city_built_iterate(_pcity, _p)
Definition: city.h:752
#define city_built_iterate_end
Definition: city.h:759
int city_incite_cost(struct player *pplayer, struct city *pcity)
Returns the cost to incite a city.
Definition: cityturn.cpp:3135
int dai_action_choose_sub_tgt_unit_vs_city(struct action *paction, struct unit *actor_unit, struct city *target_city)
Returns the sub target id of the sub target chosen for the specified action performed by the specifie...
Definition: daiactions.cpp:298
#define LOG_DIPLOMAT
Definition: daiactions.cpp:31
static Tech_type_id choose_tech_to_steal(const struct player *actor_player, const struct player *target_player)
Pick a tech for actor_player to steal from target_player.
Definition: daiactions.cpp:56
adv_want dai_action_value_unit_vs_city(struct action *paction, struct unit *actor_unit, struct city *target_city, int sub_tgt_id, int count_tech)
Returns the utility of having the specified unit perform the specified action to the specified city t...
Definition: daiactions.cpp:90
static int count_sabotagable_improvements(struct city *pcity)
Number of improvements that can be sabotaged in pcity.
Definition: daiactions.cpp:36
int diplomats_unignored_tech_stealings(struct unit *pdiplomat, struct city *pcity)
Returns the amount of tech thefts from a city not ignored by the EFT_STEALINGS_IGNORE effect.
Definition: diplomats.cpp:764
int get_city_bonus(const struct city *pcity, enum effect_type effect_type, enum vision_layer vlayer)
Returns the effect bonus at a city.
Definition: effects.cpp:688
float adv_want
Definition: fc_types.h:1144
int Tech_type_id
Definition: fc_types.h:294
struct civ_game game
Definition: game.cpp:47
struct world wld
Definition: game.cpp:48
Impr_type_id improvement_number(const struct impr_type *pimprove)
Return the improvement index.
#define fc_assert_msg(condition, message,...)
Definition: log.h:96
#define fc_assert_ret_val(condition, val)
Definition: log.h:114
static int map_move_cost_unit(const struct civ_map *nmap, struct unit *punit, const struct tile *ptile)
Definition: map.h:221
bool can_see_techs_of_target(const struct player *pow_player, const struct player *target_player)
Can pow_player see the techs of target player?
#define MAX_MOVE_FRAGS
Definition: movement.h:20
enum casus_belli_range casus_belli_range_for(const struct player *offender, const struct player *tgt_plr, const enum effect_type outcome, const struct action *paction, const struct tile *tgt_tile)
Return the Casus Belli range when offender performs paction to tgt_plr at tgt_tile and the outcome is...
Definition: player.cpp:1551
bool pplayers_at_war(const struct player *pplayer, const struct player *pplayer2)
Returns true iff players can attack each other.
Definition: player.cpp:1317
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Returns true iff players are allied.
Definition: player.cpp:1334
struct research * research_get(const struct player *pplayer)
Returns the research structure associated with the player.
Definition: research.cpp:110
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Returns state of the tech for current research.
Definition: research.cpp:609
bool research_invention_gettable(const struct research *presearch, const Tech_type_id tech, bool allow_holes)
Returns TRUE iff the given tech can be given to the players sharing the research immediately.
Definition: research.cpp:686
#define ARRAY_SIZE(x)
Definition: shared.h:79
#define MIN(x, y)
Definition: shared.h:49
#define MAX(x, y)
Definition: shared.h:48
#define UNIT_LOG(_, punit, msg,...)
Definition: srv_log.h:95
Definition: city.h:291
struct packet_game_info info
Definition: game.h:80
Definition: player.h:231
struct player_economic economic
Definition: player.h:266
Definition: tile.h:42
Definition: unit.h:134
struct tile * tile
Definition: unit.h:136
struct civ_map map
Definition: world_object.h:21
Tech_type_id advance_number(const struct advance *padvance)
Return the advance index.
Definition: tech.cpp:85
#define advance_iterate(_start, _p)
Definition: tech.h:232
#define A_FIRST
Definition: tech.h:37
#define A_UNSET
Definition: tech.h:41
#define advance_iterate_end
Definition: tech.h:238
int unit_pays_mp_for_action(const struct action *paction, const struct unit *punit)
Returns the amount of movement points successfully performing the specified action will consume in th...
Definition: unit.cpp:1973
#define unit_tile(_pu)
Definition: unit.h:371
#define unit_owner(_pu)
Definition: unit.h:370
const struct unit_type * unit_type_get(const struct unit *punit)
Return the unit type for this unit.
Definition: unittype.cpp:114
bool utype_pays_for_regular_move_to_tgt(const struct action *paction, const struct unit_type *utype)
Returns TRUE iff successfully performing the specified action always will cost the actor unit of the ...
Definition: unittype.cpp:1052
bool utype_is_moved_to_tgt_by_action(const struct action *paction, const struct unit_type *utype)
Returns TRUE iff successfully performing the specified action always will move the actor unit of the ...
Definition: unittype.cpp:969
int unit_build_shield_cost_base(const struct unit *punit)
Returns the number of shields this unit represents.
Definition: unittype.cpp:1185
bool utype_is_consumed_by_action(const struct action *paction, const struct unit_type *utype)
Returns TRUE iff performing the specified action will consume an actor unit of the specified type.
Definition: unittype.cpp:936
bool utype_is_unmoved_by_action(const struct action *paction, const struct unit_type *utype)
Returns TRUE iff successfully performing the specified action never will move the actor unit from its...
Definition: unittype.cpp:1009