webperimental: killstack decides stack protects.
[freeciv.git] / server / advisors / advgoto.c
blob0d2568b1f29b9d5b6006346739589014b84da8ad
1 /***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 /* common */
19 #include "ai.h"
20 #include "combat.h"
21 #include "game.h"
22 #include "movement.h"
23 #include "unit.h"
24 #include "tile.h"
26 /* aicore */
27 #include "path_finding.h"
29 /* server */
30 #include "maphand.h"
31 #include "srv_log.h"
32 #include "unithand.h"
33 #include "unittools.h"
35 /* server/advisors */
36 #include "advtools.h"
38 #include "advgoto.h"
40 static bool adv_unit_move(struct unit *punit, struct tile *ptile);
42 /**************************************************************************
43 Move a unit along a path without disturbing its activity, role
44 or assigned destination
45 Return FALSE iff we died.
46 **************************************************************************/
47 bool adv_follow_path(struct unit *punit, struct pf_path *path,
48 struct tile *ptile)
50 struct tile *old_tile = punit->goto_tile;
51 enum unit_activity activity = punit->activity;
52 struct extra_type *tgt = punit->activity_target;
53 bool alive;
55 if (punit->moves_left <= 0) {
56 return TRUE;
58 punit->goto_tile = ptile;
59 unit_activity_handling(punit, ACTIVITY_GOTO);
60 alive = adv_unit_execute_path(punit, path);
61 if (alive) {
62 if (activity != ACTIVITY_GOTO) {
63 /* Only go via ACTIVITY_IDLE if we are actually changing the activity */
64 unit_activity_handling(punit, ACTIVITY_IDLE);
65 send_unit_info(NULL, punit); /* FIXME: probably duplicate */
66 unit_activity_handling_targeted(punit, activity, &tgt);
68 punit->goto_tile = old_tile; /* May be NULL. */
69 send_unit_info(NULL, punit);
71 return alive;
75 /*************************************************************************
76 This is a function to execute paths returned by the path-finding engine,
77 for units controlled by advisors.
79 Brings our bodyguard along.
80 Returns FALSE only if died.
81 *************************************************************************/
82 bool adv_unit_execute_path(struct unit *punit, struct pf_path *path)
84 const bool is_plr_ai = is_ai(unit_owner(punit));
85 int i;
87 /* We start with i = 1 for i = 0 is our present position */
88 for (i = 1; i < path->length; i++) {
89 struct tile *ptile = path->positions[i].tile;
90 int id = punit->id;
92 if (same_pos(unit_tile(punit), ptile)) {
93 UNIT_LOG(LOG_DEBUG, punit, "execute_path: waiting this turn");
94 return TRUE;
97 /* We use ai_unit_move() for everything but the last step
98 * of the way so that we abort if unexpected opposition
99 * shows up. Any enemy on the target tile is expected to
100 * be our target and any attack there intentional.
101 * However, do not annoy human players by automatically attacking
102 * using units temporarily under AI control (such as auto-explorers)
105 if (is_plr_ai) {
106 CALL_PLR_AI_FUNC(unit_move, unit_owner(punit), punit, ptile, path, i);
107 } else {
108 (void) adv_unit_move(punit, ptile);
110 if (!game_unit_by_number(id)) {
111 /* Died... */
112 return FALSE;
115 if (!same_pos(unit_tile(punit), ptile) || punit->moves_left <= 0) {
116 /* Stopped (or maybe fought) or ran out of moves */
117 return TRUE;
121 return TRUE;
124 /**************************************************************************
125 Move a unit. Do not attack. Do not leave bodyguard.
126 For advisor controlled units.
128 This function returns only when we have a reply from the server and
129 we can tell the calling function what happened to the move request.
130 (Right now it is not a big problem, since we call the server directly.)
131 **************************************************************************/
132 static bool adv_unit_move(struct unit *punit, struct tile *ptile)
134 struct player *pplayer = unit_owner(punit);
135 int mcost;
137 /* if enemy, stop and give a chance for the human player to
138 handle this case */
139 if (is_enemy_unit_tile(ptile, pplayer)
140 || is_enemy_city_tile(ptile, pplayer)) {
141 UNIT_LOG(LOG_DEBUG, punit, "movement halted due to enemy presence");
142 return FALSE;
145 /* Try not to end move next to an enemy if we can avoid it by waiting */
146 mcost = map_move_cost_unit(&(wld.map), punit, ptile);
147 if (punit->moves_left <= mcost
148 && unit_move_rate(punit) > mcost
149 && adv_danger_at(punit, ptile)
150 && !adv_danger_at(punit, unit_tile(punit))) {
151 UNIT_LOG(LOG_DEBUG, punit, "ending move early to stay out of trouble");
152 return FALSE;
155 /* go */
156 unit_activity_handling(punit, ACTIVITY_IDLE);
157 /* Move */
158 (void) unit_move_handling(punit, ptile, FALSE, TRUE, NULL);
160 return TRUE;
163 /**************************************************************************
164 Similar to is_my_zoc(), but with some changes:
165 - destination (x0,y0) need not be adjacent?
166 - don't care about some directions?
168 Fix to bizarre did-not-find bug. Thanks, Katvrr -- Syela
169 **************************************************************************/
170 static bool adv_could_be_my_zoc(struct unit *myunit, struct tile *ptile)
172 if (same_pos(ptile, unit_tile(myunit))) {
173 return FALSE; /* can't be my zoc */
175 if (is_tiles_adjacent(ptile, unit_tile(myunit))
176 && !is_non_allied_unit_tile(ptile, unit_owner(myunit))) {
177 return FALSE;
180 adjc_iterate(&(wld.map), ptile, atile) {
181 if (!terrain_has_flag(tile_terrain(atile), TER_NO_ZOC)
182 && is_non_allied_unit_tile(atile, unit_owner(myunit))) {
183 return FALSE;
185 } adjc_iterate_end;
187 return TRUE;
190 /**************************************************************************
191 returns:
192 0 if can't move
193 1 if zoc_ok
194 -1 if zoc could be ok?
196 see also unithand can_unit_move_to_tile_with_notify()
197 **************************************************************************/
198 int adv_could_unit_move_to_tile(struct unit *punit, struct tile *dest_tile)
200 enum unit_move_result reason =
201 unit_move_to_tile_test(&(wld.map), punit, ACTIVITY_IDLE, unit_tile(punit),
202 dest_tile, unit_has_type_flag(punit, UTYF_IGZOC),
203 NULL, FALSE);
205 switch (reason) {
206 case MR_OK:
207 return 1;
209 case MR_ZOC:
210 if (adv_could_be_my_zoc(punit, unit_tile(punit))) {
211 return -1;
213 break;
215 default:
216 break;
218 return 0;
221 /****************************************************************************
222 Attack rating of this kind of unit.
223 ****************************************************************************/
224 int adv_unittype_att_rating(const struct unit_type *punittype, int veteran,
225 int moves_left, int hp)
227 return base_get_attack_power(punittype, veteran, moves_left) * hp
228 * punittype->firepower / POWER_DIVIDER;
231 /****************************************************************************
232 Attack rating of this particular unit assuming that it has a
233 complete move left.
234 ****************************************************************************/
235 int adv_unit_att_rating(const struct unit *punit)
237 return adv_unittype_att_rating(unit_type_get(punit), punit->veteran,
238 SINGLE_MOVE, punit->hp);
241 /****************************************************************************
242 Basic (i.e. not taking attacker specific corections into account)
243 defense rating of this particular unit.
244 ****************************************************************************/
245 int adv_unit_def_rating_basic(const struct unit *punit)
247 return base_get_defense_power(punit) * punit->hp *
248 unit_type_get(punit)->firepower / POWER_DIVIDER;
251 /****************************************************************************
252 Square of the previous function - used in actual computations.
253 ****************************************************************************/
254 int adv_unit_def_rating_basic_squared(const struct unit *punit)
256 int v = adv_unit_def_rating_basic(punit);
258 return v * v;
261 /**************************************************************************
262 Are there dangerous enemies at or adjacent to the tile 'ptile'?
263 **************************************************************************/
264 bool adv_danger_at(struct unit *punit, struct tile *ptile)
266 int a = 0, d, db;
267 struct player *pplayer = unit_owner(punit);
268 struct city *pcity = tile_city(ptile);
269 enum override_bool dc = NO_OVERRIDE;
270 int extras_bonus = 0;
272 /* Give AI code possibility to decide itself */
273 CALL_PLR_AI_FUNC(consider_tile_dangerous, unit_owner(punit), ptile, punit, &dc);
274 if (dc == OVERRIDE_TRUE) {
275 return TRUE;
276 } else if (dc == OVERRIDE_FALSE) {
277 return FALSE;
280 if (pcity && pplayers_allied(city_owner(pcity), unit_owner(punit))
281 && !is_non_allied_unit_tile(ptile, pplayer)) {
282 /* We will be safe in a friendly city */
283 return FALSE;
286 /* Calculate how well we can defend at (x,y) */
287 db = 10 + tile_terrain(ptile)->defense_bonus / 10;
288 extras_bonus += tile_extras_defense_bonus(ptile, unit_type_get(punit));
289 db += (db * extras_bonus) / 100;
290 d = adv_unit_def_rating_basic_squared(punit) * db;
292 adjc_iterate(&(wld.map), ptile, ptile1) {
293 if (!map_is_known_and_seen(ptile1, unit_owner(punit), V_MAIN)) {
294 /* We cannot see danger at (ptile1) => assume there is none */
295 continue;
297 unit_list_iterate(ptile1->units, enemy) {
298 if (pplayers_at_war(unit_owner(enemy), unit_owner(punit))
299 && unit_attack_unit_at_tile_result(enemy, punit, ptile) == ATT_OK
300 && unit_attack_units_at_tile_result(enemy, ptile) == ATT_OK) {
301 a += adv_unit_att_rating(enemy);
302 if ((a * a * 10) >= d) {
303 /* The enemies combined strength is too big! */
304 return TRUE;
307 } unit_list_iterate_end;
308 } adjc_iterate_end;
310 return FALSE; /* as good a quick'n'dirty should be -- Syela */
313 /*********************************************************************
314 The value of the units belonging to a given player on a given tile.
315 *********************************************************************/
316 static int stack_value(const struct tile *ptile,
317 const struct player *pplayer)
319 int cost = 0;
321 if (is_stack_vulnerable(ptile)) {
322 unit_list_iterate(ptile->units, punit) {
323 if (unit_owner(punit) == pplayer) {
324 cost += unit_build_shield_cost(punit);
326 } unit_list_iterate_end;
329 return cost;
333 /*********************************************************************
334 How dangerous would it be stop on a particular tile,
335 because of enemy attacks,
336 expressed as the probability of being killed.
338 TODO: This implementation is a kludge until we compute a more accurate
339 probability using the movemap.
340 Also, we should take into account the reduced probability of death
341 if we have a bodyguard travelling with us.
342 *********************************************************************/
343 static double chance_killed_at(const struct tile *ptile,
344 struct adv_risk_cost *risk_cost,
345 const struct pf_parameter *param)
347 double db;
348 int extras_bonus = 0;
349 /* Compute the basic probability */
350 /* WAG */
351 /* In the early stages of a typical game, ferries
352 * are effectively invulnerable (not until Frigates set sail),
353 * so we make seas appear safer.
354 * If we don't do this, the amphibious movement code has too strong a
355 * desire to minimise the length of the path,
356 * leading to poor choice for landing beaches */
357 double p = is_ocean_tile(ptile)? 0.05: 0.15;
359 /* If we are on defensive terrain, we are more likely to survive */
360 db = 10 + tile_terrain(ptile)->defense_bonus / 10;
361 extras_bonus += tile_extras_class_defense_bonus(ptile,
362 utype_class(param->utype));
363 db += (extras_bonus) / 100;
364 p *= 10.0 / db;
366 return p;
369 /*********************************************************************
370 PF stack risk cost. How undesirable is passing through a tile
371 because of risks?
372 Weight by the cost of destruction, for risks that can kill the unit.
374 Why use the build cost when assessing the cost of destruction?
375 The reasoning is thus.
376 - Assume that all our units are doing necessary jobs;
377 none are surplus to requirements.
378 If that is not the case, we have problems elsewhere :-)
379 - Then any units that are destroyed will have to be replaced.
380 - The cost of replacing them will be their build cost.
381 - Therefore the total (re)build cost is a good representation of the
382 the cost of destruction.
383 *********************************************************************/
384 static int stack_risk(const struct tile *ptile,
385 struct adv_risk_cost *risk_cost,
386 const struct pf_parameter *param)
388 double risk = 0;
389 /* Compute the risk of destruction, assuming we will stop at this tile */
390 const double value = risk_cost->base_value
391 + stack_value(ptile, param->owner);
392 const double p_killed = chance_killed_at(ptile, risk_cost, param);
393 double danger = value * p_killed;
395 /* Adjust for the fact that we might not stop at this tile,
396 * and for our fearfulness */
397 risk += danger * risk_cost->fearfulness;
399 /* Adjust for the risk that we might become stuck (for an indefinite period)
400 * if we enter or try to enter the tile. */
401 if (risk_cost->enemy_zoc_cost != 0
402 && (is_non_allied_city_tile(ptile, param->owner)
403 || !is_my_zoc(param->owner, ptile)
404 || is_non_allied_unit_tile(ptile, param->owner))) {
405 /* We could become stuck. */
406 risk += risk_cost->enemy_zoc_cost;
409 return risk;
412 /*********************************************************************
413 PF extra cost call back to avoid creating tall stacks or
414 crossing dangerous tiles.
415 By setting this as an extra-cost call-back, paths will avoid tall stacks.
416 Avoiding tall stacks *all* along a path is useful because a unit following a
417 path might have to stop early because of ZoCs.
418 *********************************************************************/
419 static int prefer_short_stacks(const struct tile *ptile,
420 enum known_type known,
421 const struct pf_parameter *param)
423 return stack_risk(ptile, (struct adv_risk_cost *)param->data, param);
426 /**********************************************************************
427 Set PF call-backs to favour paths that do not create tall stacks
428 or cross dangerous tiles.
429 ***********************************************************************/
430 void adv_avoid_risks(struct pf_parameter *parameter,
431 struct adv_risk_cost *risk_cost,
432 struct unit *punit,
433 const double fearfulness)
435 /* If we stay a short time on each tile, the danger of each individual tile
436 * is reduced. If we do not do this,
437 * we will not favour longer but faster routs. */
438 const double linger_fraction = (double)SINGLE_MOVE / parameter->move_rate;
440 parameter->data = risk_cost;
441 parameter->get_EC = prefer_short_stacks;
442 risk_cost->base_value = unit_build_shield_cost(punit);
443 risk_cost->fearfulness = fearfulness * linger_fraction;
445 risk_cost->enemy_zoc_cost = PF_TURN_FACTOR * 20;