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)
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 ***********************************************************************/
15 #include <fc_config.h>
23 #include "bitvector.h"
37 #include "government.h"
49 /* common/scriptcore */
50 #include "luascript_signal.h"
51 #include "luascript_types.h"
54 #include "path_finding.h"
57 /* server/scripting */
58 #include "script_server.h"
61 #include "actiontools.h"
63 #include "barbarian.h"
64 #include "citytools.h"
71 #include "sanitycheck.h"
74 #include "techtools.h"
79 #include "autoexplorer.h"
80 #include "autosettlers.h"
83 #include "handicaps.h"
85 #include "unittools.h"
88 /* Tools for controlling the client vision of every unit when a unit
89 * moves + script effects. See unit_move(). You can access this data with
90 * punit->server.moving; it may be NULL if the unit is not moving). */
91 struct unit_move_data
{
93 struct unit
*punit
; /* NULL for invalidating. */
94 struct player
*powner
;
95 bv_player can_see_unit
;
96 bv_player can_see_move
;
97 struct vision
*old_vision
;
100 #define SPECLIST_TAG unit_move_data
101 #include "speclist.h"
102 #define unit_move_data_list_iterate(_plist, _pdata) \
103 TYPED_LIST_ITERATE(struct unit_move_data, _plist, _pdata)
104 #define unit_move_data_list_iterate_end LIST_ITERATE_END
105 #define unit_move_data_list_iterate_rev(_plist, _pdata) \
106 TYPED_LIST_ITERATE_REV(struct unit_move_data, _plist, _pdata)
107 #define unit_move_data_list_iterate_rev_end LIST_ITERATE_REV_END
109 /* This data structure lets the auto attack code cache each potential
110 * attacker unit's probability of success against the target unit during
111 * the checks if the unit can do autoattack. It is then reused when the
112 * list of potential attackers is sorted by probability of success. */
113 struct autoattack_prob
{
115 struct act_prob prob
;
118 #define SPECLIST_TAG autoattack_prob
119 #define SPECLIST_TYPE struct autoattack_prob
120 #include "speclist.h"
122 #define autoattack_prob_list_iterate_safe(autoattack_prob_list, _aap_, \
124 TYPED_LIST_ITERATE(struct autoattack_prob, autoattack_prob_list, _aap_) \
125 struct unit *_unit_ = game_unit_by_number(_aap_->unit_id); \
127 if (_unit_ == NULL) { \
131 #define autoattack_prob_list_iterate_safe_end LIST_ITERATE_END
133 static void unit_restore_hitpoints(struct unit
*punit
);
134 static void unit_restore_movepoints(struct player
*pplayer
, struct unit
*punit
);
135 static void update_unit_activity(struct unit
*punit
);
136 static bool try_to_save_unit(struct unit
*punit
, struct unit_type
*pttype
,
137 bool helpless
, bool teleporting
);
138 static void wakeup_neighbor_sentries(struct unit
*punit
);
139 static void do_upgrade_effects(struct player
*pplayer
);
141 static bool maybe_cancel_patrol_due_to_enemy(struct unit
*punit
);
142 static int hp_gain_coord(struct unit
*punit
);
144 static bool maybe_become_veteran_real(struct unit
*punit
, bool settler
);
146 static void unit_transport_load_tp_status(struct unit
*punit
,
150 static void wipe_unit_full(struct unit
*punit
, bool transported
,
151 enum unit_loss_reason reason
,
152 struct player
*killer
);
154 /**************************************************************************
155 Returns a unit type that matches the role_tech or role roles.
157 If role_tech is given, then we look at all units with this role
158 whose requirements are met by any player, and return a random one. This
159 can be used to give a unit to barbarians taken from the set of most
160 advanced units researched by the 'real' players.
162 If role_tech is not give (-1) or if there are no matching unit types,
163 then we look at 'role' value and return a random matching unit type.
165 It is an error if there are no available units. This function will
166 always return a valid unit.
167 **************************************************************************/
168 struct unit_type
*find_a_unit_type(enum unit_role_id role
,
169 enum unit_role_id role_tech
)
171 struct unit_type
*which
[U_LAST
];
174 if (role_tech
!= -1) {
175 for (i
= 0; i
< num_role_units(role_tech
); i
++) {
176 struct unit_type
*iunit
= get_role_unit(role_tech
, i
);
177 const int minplayers
= 2;
180 /* Note, if there's only one player in the game this check will always
182 players_iterate(pplayer
) {
183 if (!is_barbarian(pplayer
)
184 && can_player_build_unit_direct(pplayer
, iunit
)) {
187 } players_iterate_end
;
188 if (players
> minplayers
) {
189 which
[num
++] = iunit
;
194 for (i
= 0; i
< num_role_units(role
); i
++) {
195 which
[num
++] = get_role_unit(role
, i
);
199 /* Ruleset code should ensure there is at least one unit for each
200 * possibly-required role, or check before calling this function. */
201 fc_assert_exit_msg(0 < num
, "No unit types in find_a_unit_type(%d, %d)!",
204 return which
[fc_rand(num
)];
207 /*****************************************************************************
208 Unit has a chance to become veteran. This should not be used for settlers
209 for the work they do.
210 *****************************************************************************/
211 bool maybe_make_veteran(struct unit
*punit
)
213 return maybe_become_veteran_real(punit
, FALSE
);
216 /*****************************************************************************
217 After a battle, after diplomatic aggression and after surviving trireme
218 loss chance, this routine is called to decide whether or not the unit
219 should become more experienced.
221 There is a specified chance for it to happen, (+50% if player got SUNTZU)
222 the chances are specified in the units.ruleset file.
224 If 'settler' is TRUE the veteran level is increased due to work done by
226 *****************************************************************************/
227 static bool maybe_become_veteran_real(struct unit
*punit
, bool settler
)
229 const struct veteran_system
*vsystem
;
230 const struct veteran_level
*vlevel
;
233 fc_assert_ret_val(punit
!= NULL
, FALSE
);
235 vsystem
= utype_veteran_system(unit_type_get(punit
));
236 fc_assert_ret_val(vsystem
!= NULL
, FALSE
);
237 fc_assert_ret_val(vsystem
->levels
> punit
->veteran
, FALSE
);
239 vlevel
= utype_veteran_level(unit_type_get(punit
), punit
->veteran
);
240 fc_assert_ret_val(vlevel
!= NULL
, FALSE
);
242 if (punit
->veteran
+ 1 >= vsystem
->levels
243 || unit_has_type_flag(punit
, UTYF_NO_VETERAN
)) {
245 } else if (!settler
) {
246 int mod
= 100 + get_unit_bonus(punit
, EFT_VETERAN_COMBAT
);
248 /* The modification is tacked on as a multiplier to the base chance.
249 * For example with a base chance of 50% for green units and a modifier
250 * of +50% the end chance is 75%. */
251 chance
= vlevel
->raise_chance
* mod
/ 100;
252 } else if (settler
&& unit_has_type_flag(punit
, UTYF_SETTLERS
)) {
253 chance
= vlevel
->work_raise_chance
;
255 /* No battle and no work done. */
259 if (fc_rand(100) < chance
) {
267 /**************************************************************************
268 This is the basic unit versus unit combat routine.
269 1) ALOT of modifiers bonuses etc is added to the 2 units rates.
270 2) the combat loop, which continues until one of the units are dead
271 3) the aftermath, the loser (and potentially the stack which is below it)
272 is wiped, and the winner gets a chance of gaining veteran status
273 **************************************************************************/
274 void unit_versus_unit(struct unit
*attacker
, struct unit
*defender
,
275 int *att_hp
, int *def_hp
)
277 int attackpower
= get_total_attack_power(attacker
, defender
);
278 int defensepower
= get_total_defense_power(attacker
, defender
);
279 int attack_firepower
, defense_firepower
;
280 struct player
*plr1
= unit_owner(attacker
);
281 struct player
*plr2
= unit_owner(defender
);
283 *att_hp
= attacker
->hp
;
284 *def_hp
= defender
->hp
;
285 get_modified_firepower(attacker
, defender
,
286 &attack_firepower
, &defense_firepower
);
288 log_verbose("attack:%d, defense:%d, attack firepower:%d, "
289 "defense firepower:%d", attackpower
, defensepower
,
290 attack_firepower
, defense_firepower
);
292 plr1
->last_war_action
= game
.info
.turn
;
293 plr2
->last_war_action
= game
.info
.turn
;
295 if (attackpower
== 0) {
297 } else if (defensepower
== 0) {
300 while (*att_hp
> 0 && *def_hp
> 0) {
301 if (fc_rand(attackpower
+ defensepower
) >= defensepower
) {
302 *def_hp
-= attack_firepower
;
304 *att_hp
-= defense_firepower
;
315 /**************************************************************************
316 This is the basic unit versus unit classic bombardment routine.
317 1) ALOT of modifiers bonuses etc is added to the 2 units rates.
318 2) Do rate attacks and don't kill the defender, then return.
319 **************************************************************************/
320 void unit_bombs_unit(struct unit
*attacker
, struct unit
*defender
,
321 int *att_hp
, int *def_hp
)
324 int rate
= unit_type_get(attacker
)->bombard_rate
;
326 int attackpower
= get_total_attack_power(attacker
, defender
);
327 int defensepower
= get_total_defense_power(attacker
, defender
);
328 int attack_firepower
, defense_firepower
;
329 struct player
*plr1
= unit_owner(attacker
);
330 struct player
*plr2
= unit_owner(defender
);
332 *att_hp
= attacker
->hp
;
333 *def_hp
= defender
->hp
;
334 get_modified_firepower(attacker
, defender
,
335 &attack_firepower
, &defense_firepower
);
337 log_verbose("attack:%d, defense:%d, attack firepower:%d, "
338 "defense firepower:%d", attackpower
, defensepower
,
339 attack_firepower
, defense_firepower
);
341 plr1
->last_war_action
= game
.info
.turn
;
342 plr2
->last_war_action
= game
.info
.turn
;
344 for (i
= 0; i
< rate
; i
++) {
345 if (fc_rand(attackpower
+ defensepower
) >= defensepower
) {
346 *def_hp
-= attack_firepower
;
350 /* Don't kill the target. */
356 /***************************************************************************
357 Make maybe make either side of combat veteran
358 ****************************************************************************/
359 void combat_veterans(struct unit
*attacker
, struct unit
*defender
)
361 if (attacker
->hp
> 0) {
362 maybe_make_veteran(attacker
);
363 } else if (defender
->hp
> 0) {
364 maybe_make_veteran(defender
);
368 /***************************************************************************
369 Do unit auto-upgrades to players with the EFT_UNIT_UPGRADE effect
370 (traditionally from Leonardo's Workshop).
371 ****************************************************************************/
372 static void do_upgrade_effects(struct player
*pplayer
)
374 int upgrades
= get_player_bonus(pplayer
, EFT_UPGRADE_UNIT
);
375 struct unit_list
*candidates
;
380 candidates
= unit_list_new();
382 unit_list_iterate(pplayer
->units
, punit
) {
383 /* We have to be careful not to strand units at sea, for example by
384 * upgrading a frigate to an ironclad while it was carrying a unit. */
385 if (UU_OK
== unit_upgrade_test(punit
, TRUE
)) {
386 unit_list_prepend(candidates
, punit
); /* Potential candidate :) */
388 } unit_list_iterate_end
;
390 while (upgrades
> 0 && unit_list_size(candidates
) > 0) {
391 /* Upgrade one unit. The unit is chosen at random from the list of
392 * available candidates. */
393 int candidate_to_upgrade
= fc_rand(unit_list_size(candidates
));
394 struct unit
*punit
= unit_list_get(candidates
, candidate_to_upgrade
);
395 struct unit_type
*type_from
= unit_type_get(punit
);
396 struct unit_type
*type_to
= can_upgrade_unittype(pplayer
, type_from
);
398 transform_unit(punit
, type_to
, TRUE
);
399 notify_player(pplayer
, unit_tile(punit
), E_UNIT_UPGRADED
, ftc_server
,
400 _("%s was upgraded for free to %s."),
401 utype_name_translation(type_from
),
403 unit_list_remove(candidates
, punit
);
407 unit_list_destroy(candidates
);
410 /***************************************************************************
411 1. Do Leonardo's Workshop upgrade if applicable.
413 2. Restore/decrease unit hitpoints.
417 4. Rescue airplanes by returning them to base automatically.
419 5. Decrease fuel of planes in the air.
421 6. Refuel planes that are in bases.
423 7. Kill planes that are out of fuel.
424 ****************************************************************************/
425 void player_restore_units(struct player
*pplayer
)
427 /* 1) get Leonardo out of the way first: */
428 do_upgrade_effects(pplayer
);
430 unit_list_iterate_safe(pplayer
->units
, punit
) {
432 /* 2) Modify unit hitpoints. Helicopters can even lose them. */
433 unit_restore_hitpoints(punit
);
435 /* 3) Check that unit has hitpoints */
436 if (punit
->hp
<= 0) {
437 /* This should usually only happen for heli units, but if any other
438 * units get 0 hp somehow, catch them too. --dwp */
439 /* if 'game.server.killunhomed' is activated unhomed units are slowly
440 * killed; notify player here */
441 if (!punit
->homecity
&& 0 < game
.server
.killunhomed
) {
442 notify_player(pplayer
, unit_tile(punit
), E_UNIT_LOST_MISC
,
443 ftc_server
, _("Your %s has run out of hit points "
444 "because it was not supported by a city."),
445 unit_tile_link(punit
));
447 notify_player(pplayer
, unit_tile(punit
), E_UNIT_LOST_MISC
, ftc_server
,
448 _("Your %s has run out of hit points."),
449 unit_tile_link(punit
));
452 wipe_unit(punit
, ULR_HP_LOSS
, NULL
);
453 continue; /* Continue iterating... */
456 /* 4) Rescue planes if needed */
457 if (utype_fuel(unit_type_get(punit
))) {
458 /* Shall we emergency return home on the last vapors? */
460 /* I think this is strongly against the spirit of client goto.
461 * The problem is (again) that here we know too much. -- Zamar */
464 && !is_unit_being_refueled(punit
)) {
465 struct unit
*carrier
;
467 carrier
= transporter_for_unit(punit
);
469 unit_transport_load_tp_status(punit
, carrier
, FALSE
);
474 struct pf_parameter parameter
;
476 pft_fill_unit_parameter(¶meter
, punit
);
477 parameter
.omniscience
= !has_handicap(pplayer
, H_MAP
);
478 pfm
= pf_map_new(¶meter
);
480 pf_map_move_costs_iterate(pfm
, ptile
, move_cost
, TRUE
) {
481 if (move_cost
> punit
->moves_left
) {
486 if (is_airunit_refuel_point(ptile
, pplayer
, punit
)) {
487 struct pf_path
*path
;
490 /* Client orders may be running for this unit - if so
491 * we free them before engaging goto. */
492 free_unit_orders(punit
);
494 path
= pf_map_path(pfm
, ptile
);
496 alive
= adv_follow_path(punit
, path
, ptile
);
499 log_error("rescue plane: unit %d died enroute!", id
);
500 } else if (!same_pos(unit_tile(punit
), ptile
)) {
501 /* Enemy units probably blocked our route
502 * FIXME: We should try find alternative route around
503 * the enemy unit instead of just giving up and crashing. */
504 log_debug("rescue plane: unit %d could not move to "
505 "refuel point!", punit
->id
);
509 /* Clear activity. Unit info will be sent in the end of
511 unit_activity_handling(punit
, ACTIVITY_IDLE
);
512 adv_unit_new_task(punit
, AUT_NONE
, NULL
);
513 punit
->goto_tile
= NULL
;
515 if (!is_unit_being_refueled(punit
)) {
516 carrier
= transporter_for_unit(punit
);
518 unit_transport_load_tp_status(punit
, carrier
, FALSE
);
522 notify_player(pplayer
, unit_tile(punit
),
523 E_UNIT_ORDERS
, ftc_server
,
524 _("Your %s has returned to refuel."),
527 pf_path_destroy(path
);
530 } pf_map_move_costs_iterate_end
;
534 /* Unit died trying to move to refuel point. */
543 /* 6) Automatically refuel air units in cities, airbases, and
544 * transporters (carriers). */
545 if (is_unit_being_refueled(punit
)) {
546 punit
->fuel
= utype_fuel(unit_type_get(punit
));
549 } unit_list_iterate_safe_end
;
551 /* 7) Check if there are air units without fuel */
552 unit_list_iterate_safe(pplayer
->units
, punit
) {
553 if (punit
->fuel
<= 0 && utype_fuel(unit_type_get(punit
))) {
554 notify_player(pplayer
, unit_tile(punit
), E_UNIT_LOST_MISC
, ftc_server
,
555 _("Your %s has run out of fuel."),
556 unit_tile_link(punit
));
557 wipe_unit(punit
, ULR_FUEL
, NULL
);
559 } unit_list_iterate_safe_end
;
561 /* Send all updates. */
562 unit_list_iterate(pplayer
->units
, punit
) {
563 send_unit_info(NULL
, punit
);
564 } unit_list_iterate_end
;
567 /****************************************************************************
568 add hitpoints to the unit, hp_gain_coord returns the amount to add
569 united nations will speed up the process by 2 hp's / turn, means helicopters
570 will actually not lose hp's every turn if player have that wonder.
571 Units which have moved don't gain hp, except the United Nations and
572 helicopter effects still occur.
574 If 'game.server.killunhomed' is greater than 0, unhomed units lose
575 'game.server.killunhomed' hitpoints each turn, killing the unit at the end.
576 *****************************************************************************/
577 static void unit_restore_hitpoints(struct unit
*punit
)
581 struct unit_class
*pclass
= unit_class_get(punit
);
582 struct city
*pcity
= tile_city(unit_tile(punit
));
584 was_lower
= (punit
->hp
< unit_type_get(punit
)->hp
);
588 punit
->hp
+= hp_gain_coord(punit
);
591 /* Bonus recovery HP (traditionally from the United Nations) */
592 punit
->hp
+= get_unit_bonus(punit
, EFT_UNIT_RECOVER
);
594 if (!punit
->homecity
&& 0 < game
.server
.killunhomed
595 && !unit_has_type_flag(punit
, UTYF_GAMELOSS
)) {
596 /* Hit point loss of units without homecity; at least 1 hp! */
597 /* Gameloss units are immune to this effect. */
598 int hp_loss
= MAX(unit_type_get(punit
)->hp
* game
.server
.killunhomed
/ 100,
600 punit
->hp
= MIN(punit
->hp
- hp_loss
, save_hp
- 1);
603 if (!pcity
&& !tile_has_native_base(unit_tile(punit
), unit_type_get(punit
))
604 && !unit_transported(punit
)) {
605 punit
->hp
-= unit_type_get(punit
)->hp
* pclass
->hp_loss_pct
/ 100;
608 if (punit
->hp
>= unit_type_get(punit
)->hp
) {
609 punit
->hp
= unit_type_get(punit
)->hp
;
610 if (was_lower
&& punit
->activity
== ACTIVITY_SENTRY
) {
611 set_unit_activity(punit
, ACTIVITY_IDLE
);
619 punit
->moved
= FALSE
;
620 punit
->paradropped
= FALSE
;
623 /***************************************************************************
624 Move points are trivial, only modifiers to the base value is if it's
625 sea units and the player has certain wonders/techs. Then add veteran
627 ***************************************************************************/
628 static void unit_restore_movepoints(struct player
*pplayer
, struct unit
*punit
)
630 punit
->moves_left
= unit_move_rate(punit
);
631 punit
->done_moving
= FALSE
;
634 /****************************************************************************
635 Iterate through all units and update them.
636 ****************************************************************************/
637 void update_unit_activities(struct player
*pplayer
)
639 unit_list_iterate_safe(pplayer
->units
, punit
) {
640 update_unit_activity(punit
);
641 } unit_list_iterate_safe_end
;
644 /****************************************************************************
645 Iterate through all units and execute their orders.
646 ****************************************************************************/
647 void execute_unit_orders(struct player
*pplayer
)
649 unit_list_iterate_safe(pplayer
->units
, punit
) {
650 if (unit_has_orders(punit
)) {
651 execute_orders(punit
, FALSE
);
653 } unit_list_iterate_safe_end
;
656 /****************************************************************************
657 Iterate through all units and remember their current activities.
658 ****************************************************************************/
659 void finalize_unit_phase_beginning(struct player
*pplayer
)
661 /* Remember activities only after all knock-on effects of unit activities
662 * on other units have been resolved */
663 unit_list_iterate(pplayer
->units
, punit
) {
664 punit
->changed_from
= punit
->activity
;
665 punit
->changed_from_target
= punit
->activity_target
;
666 punit
->changed_from_count
= punit
->activity_count
;
667 send_unit_info(NULL
, punit
);
668 } unit_list_iterate_end
;
671 /**************************************************************************
672 returns how many hp's a unit will gain on this square
673 depends on whether or not it's inside city or fortress.
674 barracks will regen landunits completely
675 airports will regen airunits completely
676 ports will regen navalunits completely
677 fortify will add a little extra.
678 ***************************************************************************/
679 static int hp_gain_coord(struct unit
*punit
)
682 const int base
= unit_type_get(punit
)->hp
;
684 /* Includes barracks (100%), fortress (25%), etc. */
685 hp
+= base
* get_unit_bonus(punit
, EFT_HP_REGEN
) / 100;
687 if (tile_city(unit_tile(punit
))) {
688 hp
= MAX(hp
, base
/ 3);
691 if (!unit_class_get(punit
)->hp_loss_pct
) {
692 hp
+= (base
+ 9) / 10;
695 if (punit
->activity
== ACTIVITY_FORTIFIED
) {
696 hp
+= (base
+ 9) / 10;
702 /**************************************************************************
703 Calculate the total amount of activity performed by all units on a tile
704 for a given task and target.
705 **************************************************************************/
706 static int total_activity(struct tile
*ptile
, enum unit_activity act
,
707 struct extra_type
*tgt
)
710 bool tgt_matters
= activity_requires_target(act
);
712 unit_list_iterate (ptile
->units
, punit
) {
713 if (punit
->activity
== act
714 && (!tgt_matters
|| punit
->activity_target
== tgt
)) {
715 total
+= punit
->activity_count
;
717 } unit_list_iterate_end
;
722 /**************************************************************************
723 Check the total amount of activity performed by all units on a tile
725 **************************************************************************/
726 static bool total_activity_done(struct tile
*ptile
, enum unit_activity act
,
727 struct extra_type
*tgt
)
729 return total_activity(ptile
, act
, tgt
) >= tile_activity_time(act
, ptile
, tgt
);
732 /**************************************************************************
733 Common notification for all experience levels.
734 **************************************************************************/
735 void notify_unit_experience(struct unit
*punit
)
737 const struct veteran_system
*vsystem
;
738 const struct veteran_level
*vlevel
;
744 vsystem
= utype_veteran_system(unit_type_get(punit
));
745 fc_assert_ret(vsystem
!= NULL
);
746 fc_assert_ret(vsystem
->levels
> punit
->veteran
);
748 vlevel
= utype_veteran_level(unit_type_get(punit
), punit
->veteran
);
749 fc_assert_ret(vlevel
!= NULL
);
751 notify_player(unit_owner(punit
), unit_tile(punit
),
752 E_UNIT_BECAME_VET
, ftc_server
,
753 /* TRANS: Your <unit> became ... rank of <veteran level>. */
754 _("Your %s became more experienced and achieved the rank "
756 unit_link(punit
), name_translation_get(&vlevel
->name
));
759 /**************************************************************************
760 Convert a single unit to another type.
761 **************************************************************************/
762 static void unit_convert(struct unit
*punit
)
764 struct unit_type
*to_type
, *from_type
;
766 from_type
= unit_type_get(punit
);
767 to_type
= from_type
->converted_to
;
769 if (unit_can_convert(punit
)) {
770 transform_unit(punit
, to_type
, TRUE
);
771 notify_player(unit_owner(punit
), unit_tile(punit
),
772 E_UNIT_UPGRADED
, ftc_server
,
773 _("%s converted to %s."),
774 utype_name_translation(from_type
),
775 utype_name_translation(to_type
));
777 notify_player(unit_owner(punit
), unit_tile(punit
),
778 E_UNIT_UPGRADED
, ftc_server
,
779 _("%s cannot be converted."),
780 utype_name_translation(from_type
));
784 /**************************************************************************
785 Cancel all illegal activities done by units at the specified tile.
786 **************************************************************************/
787 void unit_activities_cancel_all_illegal(const struct tile
*ptile
)
789 unit_list_iterate(ptile
->units
, punit2
) {
790 if (!can_unit_continue_current_activity(punit2
)) {
791 if (unit_has_orders(punit2
)) {
792 notify_player(unit_owner(punit2
), unit_tile(punit2
),
793 E_UNIT_ORDERS
, ftc_server
,
794 _("Orders for %s aborted because activity "
795 "is no longer available."),
797 free_unit_orders(punit2
);
800 set_unit_activity(punit2
, ACTIVITY_IDLE
);
801 send_unit_info(NULL
, punit2
);
803 } unit_list_iterate_end
;
806 /**************************************************************************
807 progress settlers in their current tasks,
808 and units that is pillaging.
809 also move units that is on a goto.
810 restore unit move points (information needed for settler tasks)
811 **************************************************************************/
812 static void update_unit_activity(struct unit
*punit
)
814 const enum unit_activity tile_changing_actions
[] =
815 { ACTIVITY_PILLAGE
, ACTIVITY_GEN_ROAD
, ACTIVITY_IRRIGATE
, ACTIVITY_MINE
,
816 ACTIVITY_BASE
, ACTIVITY_TRANSFORM
, ACTIVITY_POLLUTION
,
817 ACTIVITY_FALLOUT
, ACTIVITY_LAST
};
819 struct player
*pplayer
= unit_owner(punit
);
820 bool unit_activity_done
= FALSE
;
821 enum unit_activity activity
= punit
->activity
;
822 struct tile
*ptile
= unit_tile(punit
);
827 case ACTIVITY_EXPLORE
:
828 case ACTIVITY_FORTIFIED
:
829 case ACTIVITY_SENTRY
:
831 case ACTIVITY_PATROL_UNUSED
:
832 case ACTIVITY_UNKNOWN
:
834 /* We don't need the activity_count for the above */
837 case ACTIVITY_FORTIFYING
:
838 case ACTIVITY_CONVERT
:
839 punit
->activity_count
+= get_activity_rate_this_turn(punit
);
842 case ACTIVITY_POLLUTION
:
844 case ACTIVITY_IRRIGATE
:
845 case ACTIVITY_PILLAGE
:
846 case ACTIVITY_TRANSFORM
:
847 case ACTIVITY_FALLOUT
:
849 case ACTIVITY_GEN_ROAD
:
850 punit
->activity_count
+= get_activity_rate_this_turn(punit
);
852 /* settler may become veteran when doing something useful */
853 if (maybe_become_veteran_real(punit
, TRUE
)) {
854 notify_unit_experience(punit
);
857 case ACTIVITY_OLD_ROAD
:
858 case ACTIVITY_OLD_RAILROAD
:
859 case ACTIVITY_FORTRESS
:
860 case ACTIVITY_AIRBASE
:
865 unit_restore_movepoints(pplayer
, punit
);
869 case ACTIVITY_FORTIFIED
:
870 case ACTIVITY_SENTRY
:
872 case ACTIVITY_UNKNOWN
:
873 case ACTIVITY_FORTIFYING
:
874 case ACTIVITY_CONVERT
:
875 case ACTIVITY_PATROL_UNUSED
:
877 /* no default, ensure all handled */
880 case ACTIVITY_EXPLORE
:
884 case ACTIVITY_PILLAGE
:
885 if (total_activity_done(ptile
, ACTIVITY_PILLAGE
,
886 punit
->activity_target
)) {
887 struct player
*victim
= tile_owner(ptile
); /* Owner before fortress gets destroyed */
889 destroy_extra(ptile
, punit
->activity_target
);
890 unit_activity_done
= TRUE
;
892 bounce_units_on_terrain_change(ptile
);
894 call_incident(INCIDENT_PILLAGE
, unit_owner(punit
), victim
);
896 /* Change vision if effects have changed. */
897 unit_list_refresh_vision(ptile
->units
);
901 case ACTIVITY_POLLUTION
:
902 /* TODO: Remove this fallback target setting when target always correctly
904 if (punit
->activity_target
== NULL
) {
905 punit
->activity_target
= prev_extra_in_tile(ptile
, ERM_CLEANPOLLUTION
,
908 if (total_activity_done(ptile
, ACTIVITY_POLLUTION
, punit
->activity_target
)) {
909 destroy_extra(ptile
, punit
->activity_target
);
910 unit_activity_done
= TRUE
;
914 case ACTIVITY_FALLOUT
:
915 /* TODO: Remove this fallback target setting when target always correctly
917 if (punit
->activity_target
== NULL
) {
918 punit
->activity_target
= prev_extra_in_tile(ptile
, ERM_CLEANFALLOUT
,
921 if (total_activity_done(ptile
, ACTIVITY_FALLOUT
, punit
->activity_target
)) {
922 destroy_extra(ptile
, punit
->activity_target
);
923 unit_activity_done
= TRUE
;
929 if (total_activity(ptile
, ACTIVITY_BASE
, punit
->activity_target
)
930 >= tile_activity_time(ACTIVITY_BASE
, ptile
, punit
->activity_target
)) {
931 create_extra(ptile
, punit
->activity_target
, unit_owner(punit
));
932 unit_activity_done
= TRUE
;
937 case ACTIVITY_GEN_ROAD
:
939 if (total_activity(ptile
, ACTIVITY_GEN_ROAD
, punit
->activity_target
)
940 >= tile_activity_time(ACTIVITY_GEN_ROAD
, ptile
, punit
->activity_target
)) {
941 create_extra(ptile
, punit
->activity_target
, unit_owner(punit
));
942 unit_activity_done
= TRUE
;
947 case ACTIVITY_IRRIGATE
:
949 case ACTIVITY_TRANSFORM
:
950 if (total_activity_done(ptile
, activity
, punit
->activity_target
)) {
951 struct terrain
*old
= tile_terrain(ptile
);
953 /* The function below could change the terrain. Therefore, we have to
954 * check the terrain (which will also do a sanity check for the tile). */
955 tile_apply_activity(ptile
, activity
, punit
->activity_target
);
956 check_terrain_change(ptile
, old
);
957 unit_activity_done
= TRUE
;
961 case ACTIVITY_OLD_ROAD
:
962 case ACTIVITY_OLD_RAILROAD
:
963 case ACTIVITY_FORTRESS
:
964 case ACTIVITY_AIRBASE
:
969 if (unit_activity_done
) {
970 update_tile_knowledge(ptile
);
971 if (ACTIVITY_IRRIGATE
== activity
972 || ACTIVITY_MINE
== activity
973 || ACTIVITY_TRANSFORM
== activity
) {
974 /* FIXME: As we might probably do the activity again, because of the
975 * terrain change cycles, we need to treat these cases separatly.
976 * Probably ACTIVITY_TRANSFORM should be associated to its terrain
977 * target, whereas ACTIVITY_IRRIGATE and ACTIVITY_MINE should only
978 * used for extras. */
979 unit_list_iterate(ptile
->units
, punit2
) {
980 if (punit2
->activity
== activity
) {
981 set_unit_activity(punit2
, ACTIVITY_IDLE
);
982 send_unit_info(NULL
, punit2
);
984 } unit_list_iterate_end
;
986 unit_list_iterate(ptile
->units
, punit2
) {
987 if (!can_unit_continue_current_activity(punit2
)) {
988 set_unit_activity(punit2
, ACTIVITY_IDLE
);
989 send_unit_info(NULL
, punit2
);
991 } unit_list_iterate_end
;
994 for (i
= 0; tile_changing_actions
[i
] != ACTIVITY_LAST
; i
++) {
995 if (tile_changing_actions
[i
] == activity
) {
996 /* Some units nearby may not be able to continue their action,
997 * such as building irrigation if we removed the only source
998 * of water from them. */
999 adjc_iterate(ptile
, ptile2
) {
1000 unit_activities_cancel_all_illegal(ptile2
);
1007 if (activity
== ACTIVITY_FORTIFYING
) {
1008 if (punit
->activity_count
>= 1) {
1009 set_unit_activity(punit
, ACTIVITY_FORTIFIED
);
1013 if (activity
== ACTIVITY_CONVERT
) {
1014 if (punit
->activity_count
>= unit_type_get(punit
)->convert_time
* ACTIVITY_FACTOR
) {
1015 unit_convert(punit
);
1016 set_unit_activity(punit
, ACTIVITY_IDLE
);
1021 /**************************************************************************
1022 Forget the unit's last activity so that it can't be resumed. This is
1023 used for example when the unit moves or attacks.
1024 **************************************************************************/
1025 void unit_forget_last_activity(struct unit
*punit
)
1027 punit
->changed_from
= ACTIVITY_IDLE
;
1030 /**************************************************************************
1031 Return TRUE iff activity requires some sort of target to be specified by
1033 **************************************************************************/
1034 bool unit_activity_needs_target_from_client(enum unit_activity activity
)
1037 case ACTIVITY_PILLAGE
:
1038 /* Can be set server side. */
1041 return activity_requires_target(activity
);
1045 /**************************************************************************
1046 For some activities (currently only pillaging), the precise target can
1047 be assigned by the server rather than explicitly requested by the client.
1048 This function assigns a specific activity+target if the current
1049 settings are open-ended (otherwise leaves them unchanged).
1051 Please update unit_activity_needs_target_from_client() if you add server
1052 side unit activity target setting to more activities.
1053 **************************************************************************/
1054 void unit_assign_specific_activity_target(struct unit
*punit
,
1055 enum unit_activity
*activity
,
1056 struct extra_type
**target
)
1058 if (*activity
== ACTIVITY_PILLAGE
1059 && *target
== NULL
) {
1060 struct tile
*ptile
= unit_tile(punit
);
1061 struct extra_type
*tgt
;
1063 bv_extras extras
= *tile_extras(ptile
);
1065 while ((tgt
= get_preferred_pillage(extras
))) {
1067 BV_CLR(extras
, extra_index(tgt
));
1069 if (can_unit_do_activity_targeted(punit
, *activity
, tgt
)) {
1074 /* Nothing we can pillage here. */
1075 *activity
= ACTIVITY_IDLE
;
1079 /**************************************************************************
1080 Find place to place partisans. Returns whether such spot was found, and
1081 if it has been found, dst_tile contains that tile.
1082 **************************************************************************/
1083 static bool find_a_good_partisan_spot(struct tile
*pcenter
,
1084 struct player
*powner
,
1085 struct unit_type
*u_type
,
1087 struct tile
**dst_tile
)
1091 /* coords of best tile in arg pointers */
1092 circle_iterate(pcenter
, sq_radius
, ptile
) {
1095 if (!is_native_tile(u_type
, ptile
)) {
1099 if (NULL
!= tile_city(ptile
)) {
1103 if (0 < unit_list_size(ptile
->units
)) {
1107 /* City may not have changed hands yet; see place_partisans(). */
1108 value
= get_virtual_defense_power(NULL
, u_type
, powner
,
1112 if (tile_continent(ptile
) != tile_continent(pcenter
)) {
1116 value
-= fc_rand(value
/3);
1118 if (value
> bestvalue
) {
1122 } circle_iterate_end
;
1124 return bestvalue
> 0;
1127 /**************************************************************************
1128 Place partisans for powner around pcenter (normally around a city).
1129 **************************************************************************/
1130 void place_partisans(struct tile
*pcenter
, struct player
*powner
,
1131 int count
, int sq_radius
)
1133 struct tile
*ptile
= NULL
;
1134 struct unit_type
*u_type
= get_role_unit(L_PARTISAN
, 0);
1137 && find_a_good_partisan_spot(pcenter
, powner
, u_type
,
1138 sq_radius
, &ptile
)) {
1141 punit
= create_unit(powner
, ptile
, u_type
, 0, 0, -1);
1142 if (can_unit_do_activity(punit
, ACTIVITY_FORTIFYING
)) {
1143 punit
->activity
= ACTIVITY_FORTIFIED
; /* yes; directly fortified */
1144 send_unit_info(NULL
, punit
);
1149 /**************************************************************************
1150 Teleport punit to city at cost specified. Returns success. Note that unit
1151 may die if it succesfully moves, i.e., even when return value is TRUE.
1152 (If specified cost is -1, then teleportation costs all movement.)
1153 **************************************************************************/
1154 bool teleport_unit_to_city(struct unit
*punit
, struct city
*pcity
,
1155 int move_cost
, bool verbose
)
1157 struct tile
*src_tile
= unit_tile(punit
), *dst_tile
= pcity
->tile
;
1159 if (city_owner(pcity
) == unit_owner(punit
)){
1160 log_verbose("Teleported %s %s from (%d,%d) to %s",
1161 nation_rule_name(nation_of_unit(punit
)),
1162 unit_rule_name(punit
), TILE_XY(src_tile
), city_name_get(pcity
));
1164 notify_player(unit_owner(punit
), city_tile(pcity
),
1165 E_UNIT_RELOCATED
, ftc_server
,
1166 _("Teleported your %s to %s."),
1171 /* Silently free orders since they won't be applicable anymore. */
1172 free_unit_orders(punit
);
1174 if (move_cost
== -1) {
1175 move_cost
= punit
->moves_left
;
1177 unit_move(punit
, dst_tile
, move_cost
, NULL
, FALSE
);
1184 /**************************************************************************
1185 Move or remove a unit due to stack conflicts. This function will try to
1186 find a random safe tile within a two tile distance of the unit's current
1187 tile and move the unit there. If no tiles are found, the unit is
1188 disbanded. If 'verbose' is TRUE, a message is sent to the unit owner
1189 regarding what happened.
1190 **************************************************************************/
1191 void bounce_unit(struct unit
*punit
, bool verbose
)
1193 struct player
*pplayer
;
1194 struct tile
*punit_tile
;
1195 struct unit_list
*pcargo_units
;
1198 /* I assume that there are no topologies that have more than
1199 * (2d + 1)^2 tiles in the "square" of "radius" d. */
1201 struct tile
*tiles
[(2 * DIST
+ 1) * (2 * DIST
+ 1)];
1207 pplayer
= unit_owner(punit
);
1208 punit_tile
= unit_tile(punit
);
1210 square_iterate(punit_tile
, DIST
, ptile
) {
1211 if (count
>= ARRAY_SIZE(tiles
)) {
1215 if (ptile
== punit_tile
) {
1219 if (can_unit_survive_at_tile(punit
, ptile
)
1220 && !is_non_allied_city_tile(ptile
, pplayer
)
1221 && !is_non_allied_unit_tile(ptile
, pplayer
)) {
1222 tiles
[count
++] = ptile
;
1224 } square_iterate_end
;
1227 struct tile
*ptile
= tiles
[fc_rand(count
)];
1230 notify_player(pplayer
, ptile
, E_UNIT_RELOCATED
, ftc_server
,
1231 /* TRANS: A unit is moved to resolve stack conflicts. */
1232 _("Moved your %s."),
1235 unit_move(punit
, ptile
, 0, NULL
, FALSE
);
1239 /* Didn't find a place to bounce the unit, going to disband it.
1240 * Try to bounce transported units. */
1241 if (0 < get_transporter_occupancy(punit
)) {
1242 pcargo_units
= unit_transport_cargo(punit
);
1243 unit_list_iterate(pcargo_units
, pcargo
) {
1244 bounce_unit(pcargo
, verbose
);
1245 } unit_list_iterate_end
;
1249 notify_player(pplayer
, punit_tile
, E_UNIT_LOST_MISC
, ftc_server
,
1250 /* TRANS: A unit is disbanded to resolve stack conflicts. */
1251 _("Disbanded your %s."),
1252 unit_tile_link(punit
));
1254 wipe_unit(punit
, ULR_STACK_CONFLICT
, NULL
);
1258 /**************************************************************************
1259 Throw pplayer's units from non allied cities
1261 If verbose is true, pplayer gets messages about where each units goes.
1262 **************************************************************************/
1263 static void throw_units_from_illegal_cities(struct player
*pplayer
,
1268 struct unit
*ptrans
;
1269 struct unit_list
*pcargo_units
;
1271 /* Unload undesired units from transports, if possible. */
1272 unit_list_iterate(pplayer
->units
, punit
) {
1273 ptile
= unit_tile(punit
);
1274 pcity
= tile_city(ptile
);
1276 && !pplayers_allied(city_owner(pcity
), pplayer
)
1277 && 0 < get_transporter_occupancy(punit
)) {
1278 pcargo_units
= unit_transport_cargo(punit
);
1279 unit_list_iterate(pcargo_units
, pcargo
) {
1280 if (!pplayers_allied(unit_owner(pcargo
), pplayer
)) {
1281 if (can_unit_exist_at_tile(pcargo
, ptile
)) {
1282 unit_transport_unload_send(pcargo
);
1285 } unit_list_iterate_end
;
1287 } unit_list_iterate_end
;
1289 /* Bounce units except transported ones which will be bounced with their
1291 unit_list_iterate_safe(pplayer
->units
, punit
) {
1292 ptile
= unit_tile(punit
);
1293 pcity
= tile_city(ptile
);
1295 && !pplayers_allied(city_owner(pcity
), pplayer
)) {
1296 ptrans
= unit_transport_get(punit
);
1297 if (NULL
== ptrans
|| pplayer
!= unit_owner(ptrans
)) {
1298 bounce_unit(punit
, verbose
);
1301 } unit_list_iterate_safe_end
;
1303 #ifdef FREECIV_DEBUG
1305 unit_list_iterate(pplayer
->units
, punit
) {
1306 ptile
= unit_tile(punit
);
1307 pcity
= tile_city(ptile
);
1308 fc_assert_msg(NULL
== pcity
1309 || pplayers_allied(city_owner(pcity
), pplayer
),
1310 "Failed to throw %s %d from %s %d (%d, %d)",
1311 unit_rule_name(punit
),
1313 city_name_get(pcity
),
1316 } unit_list_iterate_end
;
1317 #endif /* FREECIV_DEBUG */
1320 /**************************************************************************
1321 For each pplayer's unit, check if we stack illegally, if so,
1322 bounce both players' units. If on ocean tile, bounce everyone but ships
1323 to avoid drowning. This function assumes that cities are clean.
1325 If verbose is true, the unit owner gets messages about where each
1327 **************************************************************************/
1328 static void resolve_stack_conflicts(struct player
*pplayer
,
1329 struct player
*aplayer
, bool verbose
)
1331 unit_list_iterate_safe(pplayer
->units
, punit
) {
1332 struct tile
*ptile
= unit_tile(punit
);
1334 if (is_non_allied_unit_tile(ptile
, pplayer
)) {
1335 unit_list_iterate_safe(ptile
->units
, aunit
) {
1336 if (unit_owner(aunit
) == pplayer
1337 || unit_owner(aunit
) == aplayer
1338 || !can_unit_survive_at_tile(aunit
, ptile
)) {
1339 bounce_unit(aunit
, verbose
);
1341 } unit_list_iterate_safe_end
;
1343 } unit_list_iterate_safe_end
;
1346 /**************************************************************************
1347 When in civil war or an alliance breaks there will potentially be units
1348 from both sides coexisting on the same squares. This routine resolves
1349 this by first bouncing off non-allied units from their cities, then by
1350 bouncing both players' units in now illegal multiowner stacks. To avoid
1351 drowning due to removal of transports, we bounce everyone (including
1352 third parties' units) from ocean tiles.
1354 If verbose is true, the unit owner gets messages about where each
1356 **************************************************************************/
1357 void resolve_unit_stacks(struct player
*pplayer
, struct player
*aplayer
,
1360 throw_units_from_illegal_cities(pplayer
, verbose
);
1361 throw_units_from_illegal_cities(aplayer
, verbose
);
1363 resolve_stack_conflicts(pplayer
, aplayer
, verbose
);
1364 resolve_stack_conflicts(aplayer
, pplayer
, verbose
);
1367 /****************************************************************************
1368 Returns the list of the units seen by 'pplayer' potentially seen only
1369 thanks to an alliance with 'aplayer'. The returned pointer is newly
1370 allocated and should be freed by the caller, using unit_list_destroy().
1371 ****************************************************************************/
1372 struct unit_list
*get_units_seen_via_ally(const struct player
*pplayer
,
1373 const struct player
*aplayer
)
1375 struct unit_list
*seen_units
= unit_list_new();
1377 /* Anybody's units inside ally's cities */
1378 city_list_iterate(aplayer
->cities
, pcity
) {
1379 unit_list_iterate(city_tile(pcity
)->units
, punit
) {
1380 if (can_player_see_unit(pplayer
, punit
)) {
1381 unit_list_append(seen_units
, punit
);
1383 } unit_list_iterate_end
;
1384 } city_list_iterate_end
;
1386 /* Ally's own units inside transports */
1387 unit_list_iterate(aplayer
->units
, punit
) {
1388 if (unit_transported(punit
) && can_player_see_unit(pplayer
, punit
)) {
1389 unit_list_append(seen_units
, punit
);
1391 } unit_list_iterate_end
;
1393 /* Make sure the same unit is not added in multiple phases
1394 * (unit within transport in a city) */
1395 unit_list_unique(seen_units
);
1400 /****************************************************************************
1401 When two players cancel an alliance, a lot of units that were visible may
1402 no longer be visible (this includes units in transporters and cities).
1403 Call this function to inform the clients that these units are no longer
1404 visible. Pass the list of seen units returned by get_units_seen_via_ally()
1405 before alliance was broken up.
1406 ****************************************************************************/
1407 void remove_allied_visibility(struct player
*pplayer
, struct player
*aplayer
,
1408 const struct unit_list
*seen_units
)
1410 unit_list_iterate(seen_units
, punit
) {
1411 /* We need to hide units previously seen by the client. */
1412 if (!can_player_see_unit(pplayer
, punit
)) {
1413 unit_goes_out_of_sight(pplayer
, punit
);
1415 } unit_list_iterate_end
;
1417 city_list_iterate(aplayer
->cities
, pcity
) {
1418 /* The player used to know what units were in these cities. Now that he
1419 * doesn't, he needs to get a new short city packet updating the
1420 * occupied status. */
1421 if (map_is_known_and_seen(pcity
->tile
, pplayer
, V_MAIN
)) {
1422 send_city_info(pplayer
, pcity
);
1424 } city_list_iterate_end
;
1427 /****************************************************************************
1428 Refresh units visibility of 'aplayer' for 'pplayer' after alliance have
1430 ****************************************************************************/
1431 void give_allied_visibility(struct player
*pplayer
,
1432 struct player
*aplayer
)
1434 unit_list_iterate(aplayer
->units
, punit
) {
1435 if (can_player_see_unit(pplayer
, punit
)) {
1436 send_unit_info(pplayer
->connections
, punit
);
1438 } unit_list_iterate_end
;
1441 /**************************************************************************
1442 Is unit being refueled in its current position
1443 **************************************************************************/
1444 bool is_unit_being_refueled(const struct unit
*punit
)
1446 if (unit_transported(punit
) /* Carrier */
1447 || tile_city(unit_tile(punit
)) /* City */
1448 || tile_has_refuel_extra(unit_tile(punit
),
1449 unit_type_get(punit
))) { /* Airbase */
1452 if (unit_has_type_flag(punit
, UTYF_COAST
)) {
1453 return is_safe_ocean(unit_tile(punit
));
1459 /**************************************************************************
1460 Can unit refuel on tile. Considers also carrier capacity on tile.
1461 **************************************************************************/
1462 bool is_airunit_refuel_point(const struct tile
*ptile
,
1463 const struct player
*pplayer
,
1464 const struct unit
*punit
)
1466 const struct unit_class
*pclass
;
1468 if (NULL
!= is_non_allied_unit_tile(ptile
, pplayer
)) {
1472 if (NULL
!= is_allied_city_tile(ptile
, pplayer
)) {
1476 pclass
= unit_class_get(punit
);
1477 if (NULL
!= pclass
->cache
.refuel_bases
) {
1478 const struct player_tile
*plrtile
= map_get_player_tile(ptile
, pplayer
);
1480 extra_type_list_iterate(pclass
->cache
.refuel_bases
, pextra
) {
1481 if (BV_ISSET(plrtile
->extras
, extra_index(pextra
))) {
1484 } extra_type_list_iterate_end
;
1487 return unit_could_load_at(punit
, ptile
);
1490 /**************************************************************************
1491 Really transforms a single unit to another type.
1493 This function performs no checks. You should perform the appropriate
1494 test first to check that the transformation is legal (test_unit_upgrade()
1495 or test_unit_convert()).
1497 is_free: Does unit owner need to pay upgrade price.
1499 Note that this function is strongly tied to unit.c:test_unit_upgrade().
1500 **************************************************************************/
1501 void transform_unit(struct unit
*punit
, struct unit_type
*to_unit
,
1504 struct player
*pplayer
= unit_owner(punit
);
1505 struct unit_type
*old_type
= punit
->utype
;
1506 int old_mr
= unit_move_rate(punit
);
1507 int old_hp
= unit_type_get(punit
)->hp
;
1510 pplayer
->economic
.gold
-=
1511 unit_upgrade_price(pplayer
, unit_type_get(punit
), to_unit
);
1514 punit
->utype
= to_unit
;
1516 /* New type may not have the same veteran system, and we may want to
1517 * knock some levels off. */
1518 punit
->veteran
= MIN(punit
->veteran
,
1519 utype_veteran_system(to_unit
)->levels
- 1);
1521 punit
->veteran
= MAX(punit
->veteran
1522 - game
.server
.autoupgrade_veteran_loss
, 0);
1524 punit
->veteran
= MAX(punit
->veteran
1525 - game
.server
.upgrade_veteran_loss
, 0);
1528 /* Scale HP and MP, rounding down. Be careful with integer arithmetic,
1529 * and don't kill the unit. unit_move_rate is used to take into account
1530 * global effects like Magellan's Expedition. */
1531 punit
->hp
= MAX(punit
->hp
* unit_type_get(punit
)->hp
/ old_hp
, 1);
1532 punit
->moves_left
= punit
->moves_left
* unit_move_rate(punit
) / old_mr
;
1534 unit_forget_last_activity(punit
);
1536 /* update unit upkeep */
1537 city_units_upkeep(game_city_by_number(punit
->homecity
));
1539 conn_list_do_buffer(pplayer
->connections
);
1541 unit_refresh_vision(punit
);
1543 CALL_PLR_AI_FUNC(unit_transformed
, pplayer
, punit
, old_type
);
1545 send_unit_info(NULL
, punit
);
1546 conn_list_do_unbuffer(pplayer
->connections
);
1549 /*************************************************************************
1550 Wrapper of the below
1551 *************************************************************************/
1552 struct unit
*create_unit(struct player
*pplayer
, struct tile
*ptile
,
1553 struct unit_type
*type
, int veteran_level
,
1554 int homecity_id
, int moves_left
)
1556 return create_unit_full(pplayer
, ptile
, type
, veteran_level
, homecity_id
,
1557 moves_left
, -1, NULL
);
1560 /**************************************************************************
1561 Set carried goods for unit.
1562 **************************************************************************/
1563 void unit_get_goods(struct unit
*punit
)
1565 if (punit
->homecity
!= 0) {
1566 struct city
*home
= game_city_by_number(punit
->homecity
);
1568 if (home
!= NULL
&& game
.info
.goods_selection
== GSM_LEAVING
) {
1569 punit
->carrying
= goods_from_city_to_unit(home
, punit
);
1574 /**************************************************************************
1575 Creates a unit, and set it's initial values, and put it into the right
1577 If moves_left is less than zero, unit will get max moves.
1578 **************************************************************************/
1579 struct unit
*create_unit_full(struct player
*pplayer
, struct tile
*ptile
,
1580 struct unit_type
*type
, int veteran_level
,
1581 int homecity_id
, int moves_left
, int hp_left
,
1582 struct unit
*ptrans
)
1584 struct unit
*punit
= unit_virtual_create(pplayer
, NULL
, type
, veteran_level
);
1588 punit
->id
= identity_number();
1589 idex_register_unit(punit
);
1591 fc_assert_ret_val(ptile
!= NULL
, NULL
);
1592 unit_tile_set(punit
, ptile
);
1594 pcity
= game_city_by_number(homecity_id
);
1595 if (utype_has_flag(type
, UTYF_NOHOME
)) {
1596 punit
->homecity
= 0; /* none */
1598 punit
->homecity
= homecity_id
;
1602 /* Override default full HP */
1603 punit
->hp
= hp_left
;
1606 if (moves_left
>= 0) {
1607 /* Override default full MP */
1608 punit
->moves_left
= MIN(moves_left
, unit_move_rate(punit
));
1612 /* Set transporter for unit. */
1613 unit_transport_load_tp_status(punit
, ptrans
, FALSE
);
1615 fc_assert_ret_val(!ptile
|| can_unit_exist_at_tile(punit
, ptile
), NULL
);
1618 /* Assume that if moves_left < 0 then the unit is "fresh",
1619 * and not moved; else the unit has had something happen
1620 * to it (eg, bribed) which we treat as equivalent to moved.
1621 * (Otherwise could pass moved arg too...) --dwp */
1622 punit
->moved
= (moves_left
>= 0);
1624 unit_list_prepend(pplayer
->units
, punit
);
1625 unit_list_prepend(ptile
->units
, punit
);
1626 if (pcity
&& !utype_has_flag(type
, UTYF_NOHOME
)) {
1627 fc_assert(city_owner(pcity
) == pplayer
);
1628 unit_list_prepend(pcity
->units_supported
, punit
);
1629 /* Refresh the unit's homecity. */
1630 city_refresh(pcity
);
1631 send_city_info(pplayer
, pcity
);
1634 punit
->server
.vision
= vision_new(pplayer
, ptile
);
1635 unit_refresh_vision(punit
);
1637 send_unit_info(NULL
, punit
);
1638 maybe_make_contact(ptile
, unit_owner(punit
));
1639 wakeup_neighbor_sentries(punit
);
1641 /* update unit upkeep */
1642 city_units_upkeep(game_city_by_number(homecity_id
));
1644 /* The unit may have changed the available tiles in nearby cities. */
1645 city_map_update_tile_now(ptile
);
1648 unit_get_goods(punit
);
1650 CALL_PLR_AI_FUNC(unit_got
, pplayer
, punit
);
1655 /**************************************************************************
1656 Set the call back to run when the server removes the unit.
1657 **************************************************************************/
1658 void unit_set_removal_callback(struct unit
*punit
,
1659 void (*callback
)(struct unit
*punit
))
1661 /* Tried to overwrite another call back. If this assertion is triggered
1662 * in a case where two call back are needed it may be time to support
1663 * more than one unit removal call back at a time. */
1664 fc_assert_ret(punit
->server
.removal_callback
== NULL
);
1666 punit
->server
.removal_callback
= callback
;
1669 /**************************************************************************
1670 Remove the call back so nothing runs when the server removes the unit.
1671 **************************************************************************/
1672 void unit_unset_removal_callback(struct unit
*punit
)
1674 punit
->server
.removal_callback
= NULL
;
1677 /****************************************************************************
1678 We remove the unit and see if it's disappearance has affected the homecity
1679 and the city it was in.
1680 ****************************************************************************/
1681 static void server_remove_unit_full(struct unit
*punit
, bool transported
,
1682 enum unit_loss_reason reason
)
1684 struct packet_unit_remove packet
;
1685 struct tile
*ptile
= unit_tile(punit
);
1686 struct city
*pcity
= tile_city(ptile
);
1687 struct city
*phomecity
= game_city_by_number(punit
->homecity
);
1688 struct unit
*ptrans
;
1689 struct player
*pplayer
= unit_owner(punit
);
1691 /* The unit is doomed. */
1692 punit
->server
.dying
= TRUE
;
1694 #ifdef FREECIV_DEBUG
1695 unit_list_iterate(ptile
->units
, pcargo
) {
1696 fc_assert(unit_transport_get(pcargo
) != punit
);
1697 } unit_list_iterate_end
;
1698 #endif /* FREECIV_DEBUG */
1700 CALL_PLR_AI_FUNC(unit_lost
, pplayer
, punit
);
1702 /* Save transporter for updating below. */
1703 ptrans
= unit_transport_get(punit
);
1705 unit_transport_unload(punit
);
1707 /* Since settlers plot in new cities in the minimap before they
1708 are built, so that no two settlers head towards the same city
1709 spot, we need to ensure this reservation is cleared should
1710 the settler disappear on the way. */
1711 adv_unit_new_task(punit
, AUT_NONE
, NULL
);
1713 /* Clear the vision before sending unit remove. Else, we might duplicate
1714 * the PACKET_UNIT_REMOVE if we lose vision of the unit tile. */
1715 vision_clear_sight(punit
->server
.vision
);
1716 vision_free(punit
->server
.vision
);
1717 punit
->server
.vision
= NULL
;
1719 packet
.unit_id
= punit
->id
;
1720 /* Send to onlookers. */
1721 players_iterate(aplayer
) {
1722 if (can_player_see_unit_at(aplayer
, punit
, unit_tile(punit
),
1724 lsend_packet_unit_remove(aplayer
->connections
, &packet
);
1726 } players_iterate_end
;
1727 /* Send to global observers. */
1728 conn_list_iterate(game
.est_connections
, pconn
) {
1729 if (conn_is_global_observer(pconn
)) {
1730 send_packet_unit_remove(pconn
, &packet
);
1732 } conn_list_iterate_end
;
1734 if (punit
->server
.moving
!= NULL
) {
1735 /* Do not care of this unit for running moves. */
1736 punit
->server
.moving
->punit
= NULL
;
1739 if (punit
->server
.removal_callback
!= NULL
) {
1740 /* Run the unit removal call back. */
1741 punit
->server
.removal_callback(punit
);
1744 /* check if this unit had UTYF_GAMELOSS flag */
1745 if (unit_has_type_flag(punit
, UTYF_GAMELOSS
) && unit_owner(punit
)->is_alive
) {
1746 notify_conn(game
.est_connections
, ptile
, E_UNIT_LOST_MISC
, ftc_server
,
1747 _("Unable to defend %s, %s has lost the game."),
1749 player_name(pplayer
));
1750 notify_player(pplayer
, ptile
, E_GAME_END
, ftc_server
,
1751 _("Losing %s meant losing the game! "
1752 "Be more careful next time!"),
1754 player_status_add(unit_owner(punit
), PSTATUS_DYING
);
1757 script_server_signal_emit("unit_lost", 3,
1758 API_TYPE_UNIT
, punit
,
1759 API_TYPE_PLAYER
, unit_owner(punit
),
1760 API_TYPE_STRING
, unit_loss_reason_name(reason
));
1762 script_server_remove_exported_object(punit
);
1763 game_remove_unit(punit
);
1766 if (NULL
!= ptrans
) {
1767 /* Update the occupy info. */
1768 send_unit_info(NULL
, ptrans
);
1771 /* This unit may have blocked tiles of adjacent cities. Update them. */
1772 city_map_update_tile_now(ptile
);
1776 city_refresh(phomecity
);
1777 send_city_info(city_owner(phomecity
), phomecity
);
1780 if (pcity
&& pcity
!= phomecity
) {
1781 city_refresh(pcity
);
1782 send_city_info(city_owner(pcity
), pcity
);
1785 if (pcity
&& unit_list_size(ptile
->units
) == 0) {
1786 /* The last unit in the city was killed: update the occupied flag. */
1787 send_city_info(NULL
, pcity
);
1791 /****************************************************************************
1792 We remove the unit and see if it's disappearance has affected the homecity
1793 and the city it was in.
1794 ****************************************************************************/
1795 static void server_remove_unit(struct unit
*punit
,
1796 enum unit_loss_reason reason
)
1798 server_remove_unit_full(punit
, unit_transported(punit
), reason
);
1801 /**************************************************************************
1802 Handle units destroyed when their transport is destroyed
1803 **************************************************************************/
1804 static void unit_lost_with_transport(const struct player
*pplayer
,
1805 struct unit
*pcargo
,
1806 struct unit_type
*ptransport
,
1807 struct player
*killer
)
1809 notify_player(pplayer
, unit_tile(pcargo
), E_UNIT_LOST_MISC
, ftc_server
,
1810 _("%s lost when %s was lost."),
1811 unit_tile_link(pcargo
),
1812 utype_name_translation(ptransport
));
1813 /* Unit is not transported any more at this point, but it has jumped
1814 * off the transport and drowns outside. So it must be removed from
1816 * However, we don't know if given client has received ANY updates
1817 * about the swimming unit, and we can't remove it if it's not there
1818 * in the first place -> we send it once here just to be sure it's
1820 send_unit_info(NULL
, pcargo
);
1821 wipe_unit_full(pcargo
, FALSE
, ULR_TRANSPORT_LOST
, killer
);
1824 /****************************************************************************
1825 Remove the unit, and passengers if it is a carrying any. Remove the
1826 _minimum_ number, eg there could be another boat on the square.
1827 ****************************************************************************/
1828 static void wipe_unit_full(struct unit
*punit
, bool transported
,
1829 enum unit_loss_reason reason
,
1830 struct player
*killer
)
1832 struct tile
*ptile
= unit_tile(punit
);
1833 struct player
*pplayer
= unit_owner(punit
);
1834 struct unit_type
*putype_save
= unit_type_get(punit
); /* for notify messages */
1835 struct unit_list
*helpless
= unit_list_new();
1836 struct unit_list
*imperiled
= unit_list_new();
1837 struct unit_list
*unsaved
= unit_list_new();
1838 struct unit
*ptrans
= unit_transport_get(punit
);
1840 /* The unit is doomed. */
1841 punit
->server
.dying
= TRUE
;
1843 /* Remove unit itself from its transport */
1844 if (ptrans
!= NULL
) {
1845 unit_transport_unload(punit
);
1846 send_unit_info(NULL
, ptrans
);
1849 /* First pull all units off of the transporter. */
1850 if (get_transporter_occupancy(punit
) > 0) {
1851 /* Use iterate_safe as unloaded units will be removed from the list
1852 * while iterating. */
1853 unit_list_iterate_safe(unit_transport_cargo(punit
), pcargo
) {
1854 bool healthy
= FALSE
;
1856 if (!can_unit_unload(pcargo
, punit
)) {
1857 unit_list_prepend(helpless
, pcargo
);
1859 if (!can_unit_exist_at_tile(pcargo
, ptile
)) {
1860 unit_list_prepend(imperiled
, pcargo
);
1862 /* These units do not need to be saved. */
1867 /* Could use unit_transport_unload_send here, but that would
1868 * call send_unit_info for the transporter unnecessarily.
1869 * Note that this means that unit might to get seen briefly
1870 * by clients other than owner's, for example as a result of
1871 * update of homecity common to this cargo and some other
1872 * destroyed unit. */
1873 unit_transport_unload(pcargo
);
1874 if (pcargo
->activity
== ACTIVITY_SENTRY
) {
1875 /* Activate sentried units - like planes on a disbanded carrier.
1876 * Note this will activate ground units even if they just change
1878 set_unit_activity(pcargo
, ACTIVITY_IDLE
);
1881 /* Unit info for unhealthy units will be sent when they are
1882 * assigned new transport or removed. */
1884 send_unit_info(NULL
, pcargo
);
1886 } unit_list_iterate_safe_end
;
1889 /* Now remove the unit. */
1890 server_remove_unit_full(punit
, transported
, reason
);
1900 case ULR_ELIMINATED
:
1901 case ULR_TRANSPORT_LOST
:
1902 if (killer
!= NULL
) {
1903 killer
->score
.units_killed
++;
1905 pplayer
->score
.units_lost
++;
1907 case ULR_BARB_UNLEASH
:
1910 case ULR_NONNATIVE_TERR
:
1914 case ULR_STACK_CONFLICT
:
1916 pplayer
->score
.units_lost
++;
1922 case ULR_PLAYER_DIED
:
1928 /* First, sort out helpless cargo. */
1929 if (unit_list_size(helpless
) > 0) {
1930 struct unit_list
*remaining
= unit_list_new();
1932 /* Grant priority to gameloss units and units with the EvacuateFirst
1933 * unit type flag. */
1934 unit_list_iterate_safe(helpless
, pcargo
) {
1935 if (unit_has_type_flag(pcargo
, UTYF_EVAC_FIRST
)
1936 || unit_has_type_flag(pcargo
, UTYF_GAMELOSS
)) {
1937 if (!try_to_save_unit(pcargo
, putype_save
, TRUE
,
1938 unit_has_type_flag(pcargo
,
1939 UTYF_EVAC_FIRST
))) {
1940 unit_list_prepend(unsaved
, pcargo
);
1943 unit_list_prepend(remaining
, pcargo
);
1945 } unit_list_iterate_safe_end
;
1947 /* Handle non-priority units. */
1948 unit_list_iterate_safe(remaining
, pcargo
) {
1949 if (!try_to_save_unit(pcargo
, putype_save
, TRUE
, FALSE
)) {
1950 unit_list_prepend(unsaved
, pcargo
);
1952 } unit_list_iterate_safe_end
;
1954 unit_list_destroy(remaining
);
1956 unit_list_destroy(helpless
);
1958 /* Then, save any imperiled cargo. */
1959 if (unit_list_size(imperiled
) > 0) {
1960 struct unit_list
*remaining
= unit_list_new();
1962 /* Grant priority to gameloss units and units with the EvacuateFirst
1963 * unit type flag. */
1964 unit_list_iterate_safe(imperiled
, pcargo
) {
1965 if (unit_has_type_flag(pcargo
, UTYF_EVAC_FIRST
)
1966 || unit_has_type_flag(pcargo
, UTYF_GAMELOSS
)) {
1967 if (!try_to_save_unit(pcargo
, putype_save
, FALSE
,
1968 unit_has_type_flag(pcargo
,
1969 UTYF_EVAC_FIRST
))) {
1970 unit_list_prepend(unsaved
, pcargo
);
1973 unit_list_prepend(remaining
, pcargo
);
1975 } unit_list_iterate_safe_end
;
1977 /* Handle non-priority units. */
1978 unit_list_iterate_safe(remaining
, pcargo
) {
1979 if (!try_to_save_unit(pcargo
, putype_save
, FALSE
, FALSE
)) {
1980 unit_list_prepend(unsaved
, pcargo
);
1982 } unit_list_iterate_safe_end
;
1984 unit_list_destroy(remaining
);
1986 unit_list_destroy(imperiled
);
1988 /* Finally, kill off the unsaved units. */
1989 if (unit_list_size(unsaved
) > 0) {
1990 unit_list_iterate_safe(unsaved
, dying_unit
) {
1991 unit_lost_with_transport(pplayer
, dying_unit
, putype_save
, killer
);
1992 } unit_list_iterate_safe_end
;
1994 unit_list_destroy(unsaved
);
1997 /****************************************************************************
1998 Remove the unit, and passengers if it is a carrying any. Remove the
1999 _minimum_ number, eg there could be another boat on the square.
2000 ****************************************************************************/
2001 void wipe_unit(struct unit
*punit
, enum unit_loss_reason reason
,
2002 struct player
*killer
)
2004 wipe_unit_full(punit
, unit_transported(punit
), reason
, killer
);
2007 /****************************************************************************
2008 Determine if it is possible to save a given unit, and if so, save them.
2009 Note that despite being saved from drowning, teleporting the units to
2010 "safety" may have killed them in the end.
2011 ****************************************************************************/
2012 bool try_to_save_unit(struct unit
*punit
, struct unit_type
*pttype
,
2013 bool helpless
, bool teleporting
)
2015 struct tile
*ptile
= unit_tile(punit
);
2016 struct player
*pplayer
= unit_owner(punit
);
2017 struct unit
*ptransport
= transporter_for_unit(punit
);
2019 /* Helpless units cannot board a transport in their current state. */
2021 && ptransport
!= NULL
) {
2022 unit_transport_load_tp_status(punit
, ptransport
, FALSE
);
2023 send_unit_info(NULL
, punit
);
2026 /* Only units that cannot find transport are considered for teleport. */
2028 struct city
*pcity
= find_closest_city(ptile
, NULL
, unit_owner(punit
),
2029 FALSE
, FALSE
, FALSE
, TRUE
, FALSE
,
2030 utype_class(pttype
));
2031 if (pcity
!= NULL
) {
2032 char tplink
[MAX_LEN_LINK
]; /* In case unit dies when teleported */
2034 sz_strlcpy(tplink
, unit_link(punit
));
2036 if (teleport_unit_to_city(punit
, pcity
, 0, FALSE
)) {
2037 notify_player(pplayer
, ptile
, E_UNIT_RELOCATED
, ftc_server
,
2038 _("%s escaped the destruction of %s, and fled to %s."),
2040 utype_name_translation(pttype
),
2047 /* The unit could not use transport on the tile, and could not teleport. */
2051 /****************************************************************************
2052 We don't really change owner of the unit, but create completely new
2053 unit as its copy. The new pointer to 'punit' is returned.
2054 ****************************************************************************/
2055 struct unit
*unit_change_owner(struct unit
*punit
, struct player
*pplayer
,
2056 int homecity
, enum unit_loss_reason reason
)
2058 struct unit
*gained_unit
;
2060 fc_assert(!utype_player_already_has_this_unique(pplayer
,
2061 unit_type_get(punit
)));
2063 /* Convert the unit to your cause. Fog is lifted in the create algorithm. */
2064 gained_unit
= create_unit_full(pplayer
, unit_tile(punit
),
2065 unit_type_get(punit
), punit
->veteran
,
2066 homecity
, punit
->moves_left
,
2069 /* Owner changes, nationality not. */
2070 gained_unit
->nationality
= punit
->nationality
;
2072 /* Copy some more unit fields */
2073 gained_unit
->fuel
= punit
->fuel
;
2074 gained_unit
->paradropped
= punit
->paradropped
;
2075 gained_unit
->server
.birth_turn
= punit
->server
.birth_turn
;
2077 send_unit_info(NULL
, gained_unit
);
2079 /* update unit upkeep in the homecity of the victim */
2080 if (punit
->homecity
> 0) {
2081 /* update unit upkeep */
2082 city_units_upkeep(game_city_by_number(punit
->homecity
));
2084 /* update unit upkeep in the new homecity */
2086 city_units_upkeep(game_city_by_number(homecity
));
2089 /* Be sure to wipe the converted unit! */
2090 wipe_unit(punit
, reason
, NULL
);
2092 return gained_unit
; /* Returns the replacement. */
2095 /**************************************************************************
2096 Called when one unit kills another in combat (this function is only
2097 called in one place). It handles all side effects including
2098 notifications and killstack.
2099 **************************************************************************/
2100 void kill_unit(struct unit
*pkiller
, struct unit
*punit
, bool vet
)
2102 char pkiller_link
[MAX_LEN_LINK
], punit_link
[MAX_LEN_LINK
];
2103 struct player
*pvictim
= unit_owner(punit
);
2104 struct player
*pvictor
= unit_owner(pkiller
);
2105 int ransom
, unitcount
= 0;
2108 sz_strlcpy(pkiller_link
, unit_link(pkiller
));
2109 sz_strlcpy(punit_link
, unit_tile_link(punit
));
2111 /* The unit is doomed. */
2112 punit
->server
.dying
= TRUE
;
2114 if ((game
.info
.gameloss_style
& GAMELOSS_STYLE_LOOT
)
2115 && unit_has_type_flag(punit
, UTYF_GAMELOSS
)) {
2116 ransom
= fc_rand(1 + pvictim
->economic
.gold
);
2120 give_distorted_map(pvictim
, pvictor
, 1, 1, TRUE
);
2122 log_debug("victim has money: %d", pvictim
->economic
.gold
);
2123 pvictor
->economic
.gold
+= ransom
;
2124 pvictim
->economic
.gold
-= ransom
;
2129 Tech_type_id ttid
= steal_a_tech(pvictor
, pvictim
, A_UNSET
);
2131 if (ttid
== A_NONE
) {
2132 log_debug("Worthless enemy doesn't have more techs to steal.");
2135 log_debug("Pressed tech %s from captured enemy",
2136 research_advance_rule_name(research_get(pvictor
), ttid
));
2138 break; /* out of luck */
2144 { /* try to submit some cities */
2145 int vcsize
= city_list_size(pvictim
->cities
);
2146 int evcsize
= vcsize
;
2147 int conqsize
= evcsize
;
2154 /* about a quarter on average with high numbers less probable */
2155 conqsize
= fc_rand(fc_rand(evcsize
));
2157 log_debug("conqsize=%d", conqsize
);
2160 bool palace
= game
.server
.savepalace
;
2161 bool submit
= FALSE
;
2163 game
.server
.savepalace
= FALSE
; /* moving it around is dumb */
2165 city_list_iterate_safe(pvictim
->cities
, pcity
) {
2166 /* kindly ask the citizens to submit */
2167 if (fc_rand(vcsize
) < conqsize
) {
2173 /* Transfer city to the victorious player
2174 * kill all its units outside of a radius of 7,
2175 * give verbose messages of every unit transferred,
2176 * and raze buildings according to raze chance
2177 * (also removes palace) */
2178 (void) transfer_city(pvictor
, pcity
, 7, TRUE
, TRUE
, TRUE
,
2179 !is_barbarian(pvictor
));
2182 if (conqsize
<= 0) {
2185 } city_list_iterate_safe_end
;
2186 game
.server
.savepalace
= palace
;
2191 /* barbarian leader ransom hack */
2192 if (is_barbarian(pvictim
) && unit_has_type_role(punit
, L_BARBARIAN_LEADER
)
2193 && (unit_list_size(unit_tile(punit
)->units
) == 1)
2194 && uclass_has_flag(unit_class_get(pkiller
), UCF_COLLECT_RANSOM
)) {
2195 /* Occupying units can collect ransom if leader is alone in the tile */
2196 ransom
= (pvictim
->economic
.gold
>= game
.server
.ransom_gold
)
2197 ? game
.server
.ransom_gold
: pvictim
->economic
.gold
;
2198 notify_player(pvictor
, unit_tile(pkiller
), E_UNIT_WIN_ATT
, ftc_server
,
2199 PL_("Barbarian leader captured; %d gold ransom paid.",
2200 "Barbarian leader captured; %d gold ransom paid.",
2203 pvictor
->economic
.gold
+= ransom
;
2204 pvictim
->economic
.gold
-= ransom
;
2205 send_player_info_c(pvictor
, NULL
); /* let me see my new gold :-) */
2209 if (unitcount
== 0) {
2210 unit_list_iterate(unit_tile(punit
)->units
, vunit
) {
2211 if (pplayers_at_war(pvictor
, unit_owner(vunit
))) {
2214 } unit_list_iterate_end
;
2217 if (!is_stack_vulnerable(unit_tile(punit
)) || unitcount
== 1) {
2218 notify_player(pvictor
, unit_tile(pkiller
), E_UNIT_WIN_ATT
, ftc_server
,
2219 /* TRANS: "... Cannon ... the Polish Destroyer." */
2220 _("Your attacking %s succeeded against the %s %s!"),
2222 nation_adjective_for_player(pvictim
),
2225 notify_unit_experience(pkiller
);
2227 notify_player(pvictim
, unit_tile(punit
), E_UNIT_LOST_DEF
, ftc_server
,
2228 /* TRANS: "Cannon ... the Polish Destroyer." */
2229 _("%s lost to an attack by the %s %s."),
2231 nation_adjective_for_player(pvictor
),
2234 wipe_unit(punit
, ULR_KILLED
, pvictor
);
2235 } else { /* unitcount > 1 */
2237 int num_killed
[player_slot_count()];
2238 int num_escaped
[player_slot_count()];
2239 struct unit
*other_killed
[player_slot_count()];
2240 struct tile
*ptile
= unit_tile(punit
);
2242 fc_assert(unitcount
> 1);
2245 for (i
= 0; i
< player_slot_count(); i
++) {
2247 other_killed
[i
] = NULL
;
2251 /* count killed units */
2252 unit_list_iterate(ptile
->units
, vunit
) {
2253 struct player
*vplayer
= unit_owner(vunit
);
2255 if (pplayers_at_war(pvictor
, vplayer
)
2256 && is_unit_reachable_at(vunit
, pkiller
, ptile
)) {
2259 if (unit_has_type_flag(vunit
, UTYF_CANESCAPE
)
2260 && !unit_has_type_flag(pkiller
, UTYF_CANKILLESCAPING
)
2262 && vunit
->moves_left
> pkiller
->moves_left
2266 struct tile
*dsttile
= NULL
;
2269 fc_assert(vunit
->hp
> 0);
2271 adjc_iterate(ptile
, ptile2
) {
2272 if (can_exist_at_tile(vunit
->utype
, ptile2
)
2273 && NULL
== tile_city(ptile2
)) {
2274 move_cost
= map_move_cost_unit(vunit
, ptile2
);
2275 if (pkiller
->moves_left
<= vunit
->moves_left
- move_cost
2276 && (is_allied_unit_tile(ptile2
, pvictim
)
2277 || unit_list_size(ptile2
->units
)) == 0) {
2278 curr_def_bonus
= tile_extras_defense_bonus(ptile2
,
2280 if (def_bonus
<= curr_def_bonus
) {
2281 def_bonus
= curr_def_bonus
;
2288 if (dsttile
!= NULL
) {
2289 move_cost
= map_move_cost_unit(vunit
, dsttile
);
2290 unit_move(vunit
, dsttile
, move_cost
, NULL
, FALSE
);
2291 num_escaped
[player_index(vplayer
)]++;
2298 num_killed
[player_index(vplayer
)]++;
2300 if (vunit
!= punit
) {
2301 other_killed
[player_index(vplayer
)] = vunit
;
2302 other_killed
[player_index(pvictor
)] = vunit
;
2306 } unit_list_iterate_end
;
2308 /* Inform the destroyer: lots of different cases here! */
2309 notify_player(pvictor
, unit_tile(pkiller
), E_UNIT_WIN_ATT
, ftc_server
,
2310 /* TRANS: "... Cannon ... the Polish Destroyer ...." */
2311 PL_("Your attacking %s succeeded against the %s %s "
2312 "(and %d other unit)!",
2313 "Your attacking %s succeeded against the %s %s "
2314 "(and %d other units)!", unitcount
- 1),
2316 nation_adjective_for_player(pvictim
),
2320 notify_unit_experience(pkiller
);
2323 /* inform the owners: this only tells about owned units that were killed.
2324 * there may have been 20 units who died but if only 2 belonged to the
2325 * particular player they'll only learn about those.
2327 * Also if a large number of units die you don't find out what type
2329 for (i
= 0; i
< player_slot_count(); i
++) {
2330 if (num_killed
[i
] == 1) {
2331 if (i
== player_index(pvictim
)) {
2332 fc_assert(other_killed
[i
] == NULL
);
2333 notify_player(player_by_number(i
), ptile
,
2334 E_UNIT_LOST_DEF
, ftc_server
,
2335 /* TRANS: "Cannon ... the Polish Destroyer." */
2336 _("%s lost to an attack by the %s %s."),
2338 nation_adjective_for_player(pvictor
),
2341 fc_assert(other_killed
[i
] != punit
);
2342 notify_player(player_by_number(i
), ptile
,
2343 E_UNIT_LOST_DEF
, ftc_server
,
2344 /* TRANS: "Cannon lost when the Polish Destroyer
2345 * attacked the German Musketeers." */
2346 _("%s lost when the %s %s attacked the %s %s."),
2347 unit_link(other_killed
[i
]),
2348 nation_adjective_for_player(pvictor
),
2350 nation_adjective_for_player(pvictim
),
2353 } else if (num_killed
[i
] > 1) {
2354 if (i
== player_index(pvictim
)) {
2355 int others
= num_killed
[i
] - 1;
2358 notify_player(player_by_number(i
), ptile
,
2359 E_UNIT_LOST_DEF
, ftc_server
,
2360 /* TRANS: "Musketeers (and Cannon) lost to an
2361 * attack from the Polish Destroyer." */
2362 _("%s (and %s) lost to an attack from the %s %s."),
2364 unit_link(other_killed
[i
]),
2365 nation_adjective_for_player(pvictor
),
2368 notify_player(player_by_number(i
), ptile
,
2369 E_UNIT_LOST_DEF
, ftc_server
,
2370 /* TRANS: "Musketeers and 3 other units lost to
2371 * an attack from the Polish Destroyer."
2372 * (only happens with at least 2 other units) */
2373 PL_("%s and %d other unit lost to an attack "
2375 "%s and %d other units lost to an attack "
2376 "from the %s %s.", others
),
2379 nation_adjective_for_player(pvictor
),
2383 notify_player(player_by_number(i
), ptile
,
2384 E_UNIT_LOST_DEF
, ftc_server
,
2385 /* TRANS: "2 units lost when the Polish Destroyer
2386 * attacked the German Musketeers."
2387 * (only happens with at least 2 other units) */
2388 PL_("%d unit lost when the %s %s attacked the %s %s.",
2389 "%d units lost when the %s %s attacked the %s %s.",
2392 nation_adjective_for_player(pvictor
),
2394 nation_adjective_for_player(pvictim
),
2400 /* Inform the owner of the units that escaped. */
2401 for (i
= 0; i
< player_slot_count(); ++i
) {
2402 if (0 < num_escaped
[i
]) {
2403 notify_player(player_by_number(i
), unit_tile(punit
),
2404 E_UNIT_ESCAPED
, ftc_server
,
2405 PL_("%d unit escaped from attack by %s %s",
2406 "%d units escaped from attack by %s %s",
2410 nation_adjective_for_player(pkiller
->nationality
)
2415 /* remove the units - note the logic of which units actually die
2416 * must be mimiced exactly in at least one place up above. */
2417 punit
= NULL
; /* wiped during following iteration so unsafe to use */
2419 unit_list_iterate_safe(ptile
->units
, punit2
) {
2420 if (pplayers_at_war(pvictor
, unit_owner(punit2
))
2421 && is_unit_reachable_at(punit2
, pkiller
, ptile
)) {
2422 wipe_unit(punit2
, ULR_KILLED
, pvictor
);
2424 } unit_list_iterate_safe_end
;
2428 /**************************************************************************
2429 Package a unit_info packet. This packet contains basically all
2430 information about a unit.
2431 **************************************************************************/
2432 void package_unit(struct unit
*punit
, struct packet_unit_info
*packet
)
2434 packet
->id
= punit
->id
;
2435 packet
->owner
= player_number(unit_owner(punit
));
2436 packet
->nationality
= player_number(unit_nationality(punit
));
2437 packet
->tile
= tile_index(unit_tile(punit
));
2438 packet
->facing
= punit
->facing
;
2439 packet
->homecity
= punit
->homecity
;
2440 output_type_iterate(o
) {
2441 packet
->upkeep
[o
] = punit
->upkeep
[o
];
2442 } output_type_iterate_end
;
2443 packet
->veteran
= punit
->veteran
;
2444 packet
->type
= utype_number(unit_type_get(punit
));
2445 packet
->movesleft
= punit
->moves_left
;
2446 packet
->hp
= punit
->hp
;
2447 packet
->activity
= punit
->activity
;
2448 packet
->activity_count
= punit
->activity_count
;
2450 if (punit
->activity_target
!= NULL
) {
2451 packet
->activity_tgt
= extra_index(punit
->activity_target
);
2453 packet
->activity_tgt
= EXTRA_NONE
;
2456 packet
->changed_from
= punit
->changed_from
;
2457 packet
->changed_from_count
= punit
->changed_from_count
;
2459 if (punit
->changed_from_target
!= NULL
) {
2460 packet
->changed_from_tgt
= extra_index(punit
->changed_from_target
);
2462 packet
->changed_from_tgt
= EXTRA_NONE
;
2465 packet
->ai
= punit
->ai_controlled
;
2466 packet
->fuel
= punit
->fuel
;
2467 packet
->goto_tile
= (NULL
!= punit
->goto_tile
2468 ? tile_index(punit
->goto_tile
) : -1);
2469 packet
->paradropped
= punit
->paradropped
;
2470 packet
->done_moving
= punit
->done_moving
;
2471 if (!unit_transported(punit
)) {
2472 packet
->transported
= FALSE
;
2473 packet
->transported_by
= 0;
2475 packet
->transported
= TRUE
;
2476 packet
->transported_by
= unit_transport_get(punit
)->id
;
2478 if (punit
->carrying
!= NULL
) {
2479 packet
->carrying
= goods_index(punit
->carrying
);
2481 packet
->carrying
= -1;
2483 packet
->occupied
= (get_transporter_occupancy(punit
) > 0);
2484 packet
->battlegroup
= punit
->battlegroup
;
2485 packet
->has_orders
= punit
->has_orders
;
2486 if (punit
->has_orders
) {
2489 packet
->orders_length
= punit
->orders
.length
;
2490 packet
->orders_index
= punit
->orders
.index
;
2491 packet
->orders_repeat
= punit
->orders
.repeat
;
2492 packet
->orders_vigilant
= punit
->orders
.vigilant
;
2493 for (i
= 0; i
< punit
->orders
.length
; i
++) {
2494 packet
->orders
[i
] = punit
->orders
.list
[i
].order
;
2495 packet
->orders_dirs
[i
] = punit
->orders
.list
[i
].dir
;
2496 packet
->orders_activities
[i
] = punit
->orders
.list
[i
].activity
;
2497 packet
->orders_targets
[i
] = punit
->orders
.list
[i
].target
;
2498 packet
->orders_actions
[i
] = punit
->orders
.list
[i
].action
;
2501 packet
->orders_length
= packet
->orders_index
= 0;
2502 packet
->orders_repeat
= packet
->orders_vigilant
= FALSE
;
2503 /* No need to initialize array. */
2506 packet
->action_decision_want
= punit
->action_decision_want
;
2507 packet
->action_decision_tile
= (punit
->action_decision_tile
2508 ? tile_index(punit
->action_decision_tile
)
2509 : IDENTITY_NUMBER_ZERO
);
2512 /**************************************************************************
2513 Package a short_unit_info packet. This contains a limited amount of
2514 information about the unit, and is sent to players who shouldn't know
2515 everything (like the unit's owner's enemies).
2516 **************************************************************************/
2517 void package_short_unit(struct unit
*punit
,
2518 struct packet_unit_short_info
*packet
,
2519 enum unit_info_use packet_use
, int info_city_id
)
2521 packet
->packet_use
= packet_use
;
2522 packet
->info_city_id
= info_city_id
;
2524 packet
->id
= punit
->id
;
2525 packet
->owner
= player_number(unit_owner(punit
));
2526 packet
->tile
= tile_index(unit_tile(punit
));
2527 packet
->facing
= punit
->facing
;
2528 packet
->veteran
= punit
->veteran
;
2529 packet
->type
= utype_number(unit_type_get(punit
));
2530 packet
->hp
= punit
->hp
;
2531 packet
->occupied
= (get_transporter_occupancy(punit
) > 0);
2532 if (punit
->activity
== ACTIVITY_EXPLORE
2533 || punit
->activity
== ACTIVITY_GOTO
) {
2534 packet
->activity
= ACTIVITY_IDLE
;
2536 packet
->activity
= punit
->activity
;
2539 if (punit
->activity_target
== NULL
) {
2540 packet
->activity_tgt
= EXTRA_NONE
;
2542 packet
->activity_tgt
= extra_index(punit
->activity_target
);
2545 /* Transported_by information is sent to the client even for units that
2546 * aren't fully known. Note that for non-allied players, any transported
2547 * unit can't be seen at all. For allied players we have to know if
2548 * transporters have room in them so that we can load units properly. */
2549 if (!unit_transported(punit
)) {
2550 packet
->transported
= FALSE
;
2551 packet
->transported_by
= 0;
2553 packet
->transported
= TRUE
;
2554 packet
->transported_by
= unit_transport_get(punit
)->id
;
2558 /**************************************************************************
2559 Handle situation where unit goes out of player sight.
2560 **************************************************************************/
2561 void unit_goes_out_of_sight(struct player
*pplayer
, struct unit
*punit
)
2563 dlsend_packet_unit_remove(pplayer
->connections
, punit
->id
);
2564 if (punit
->server
.moving
!= NULL
) {
2565 /* Update status of 'pplayer' vision for 'punit'. */
2566 BV_CLR(punit
->server
.moving
->can_see_unit
, player_index(pplayer
));
2570 /****************************************************************************
2571 send the unit to the players who need the info.
2572 dest = NULL means all connections (game.est_connections)
2573 ****************************************************************************/
2574 void send_unit_info(struct conn_list
*dest
, struct unit
*punit
)
2576 const struct player
*powner
;
2577 struct packet_unit_info info
;
2578 struct packet_unit_short_info sinfo
;
2579 struct unit_move_data
*pdata
;
2582 dest
= game
.est_connections
;
2587 powner
= unit_owner(punit
);
2588 package_unit(punit
, &info
);
2589 package_short_unit(punit
, &sinfo
, UNIT_INFO_IDENTITY
, 0);
2590 pdata
= punit
->server
.moving
;
2592 conn_list_iterate(dest
, pconn
) {
2593 struct player
*pplayer
= conn_get_player(pconn
);
2595 /* Be careful to consider all cases where pplayer is NULL... */
2596 if (pplayer
== NULL
) {
2597 if (pconn
->observer
) {
2598 send_packet_unit_info(pconn
, &info
);
2600 } else if (pplayer
== powner
) {
2601 send_packet_unit_info(pconn
, &info
);
2602 if (pdata
!= NULL
) {
2603 BV_SET(pdata
->can_see_unit
, player_index(pplayer
));
2605 } else if (can_player_see_unit(pplayer
, punit
)) {
2606 send_packet_unit_short_info(pconn
, &sinfo
, FALSE
);
2607 if (pdata
!= NULL
) {
2608 BV_SET(pdata
->can_see_unit
, player_index(pplayer
));
2611 } conn_list_iterate_end
;
2614 /**************************************************************************
2615 For each specified connections, send information about all the units
2616 known to that player/conn.
2617 **************************************************************************/
2618 void send_all_known_units(struct conn_list
*dest
)
2620 conn_list_do_buffer(dest
);
2621 conn_list_iterate(dest
, pconn
) {
2622 struct player
*pplayer
= pconn
->playing
;
2624 if (NULL
== pplayer
&& !pconn
->observer
) {
2628 players_iterate(unitowner
) {
2629 unit_list_iterate(unitowner
->units
, punit
) {
2630 send_unit_info(dest
, punit
);
2631 } unit_list_iterate_end
;
2632 } players_iterate_end
;
2634 conn_list_iterate_end
;
2635 conn_list_do_unbuffer(dest
);
2639 /**************************************************************************
2640 Nuke a square: 1) remove all units on the square, and 2) halve the
2641 size of the city on the square.
2643 If it isn't a city square or an ocean square then with 50% chance add
2644 some fallout, then notify the client about the changes.
2645 **************************************************************************/
2646 static void do_nuke_tile(struct player
*pplayer
, struct tile
*ptile
)
2648 struct city
*pcity
= NULL
;
2650 unit_list_iterate_safe(ptile
->units
, punit
) {
2651 notify_player(unit_owner(punit
), ptile
, E_UNIT_LOST_MISC
, ftc_server
,
2652 _("Your %s was nuked by %s."),
2653 unit_tile_link(punit
),
2654 pplayer
== unit_owner(punit
)
2656 : nation_plural_for_player(pplayer
));
2657 if (unit_owner(punit
) != pplayer
) {
2658 notify_player(pplayer
, ptile
, E_UNIT_WIN
, ftc_server
,
2659 _("The %s %s was nuked."),
2660 nation_adjective_for_player(unit_owner(punit
)),
2661 unit_tile_link(punit
));
2663 wipe_unit(punit
, ULR_NUKE
, pplayer
);
2664 } unit_list_iterate_safe_end
;
2666 pcity
= tile_city(ptile
);
2669 notify_player(city_owner(pcity
), ptile
, E_CITY_NUKED
, ftc_server
,
2670 _("%s was nuked by %s."),
2672 pplayer
== city_owner(pcity
)
2674 : nation_plural_for_player(pplayer
));
2676 if (city_owner(pcity
) != pplayer
) {
2677 notify_player(pplayer
, ptile
, E_CITY_NUKED
, ftc_server
,
2682 city_reduce_size(pcity
, city_size_get(pcity
) / 2, pplayer
, "nuke");
2685 if (fc_rand(2) == 1) {
2686 struct extra_type
*pextra
;
2688 pextra
= rand_extra_for_tile(ptile
, EC_FALLOUT
);
2689 if (pextra
!= NULL
&& !tile_has_extra(ptile
, pextra
)) {
2690 tile_add_extra(ptile
, pextra
);
2691 update_tile_knowledge(ptile
);
2696 /**************************************************************************
2697 Nuke all the squares in a 3x3 square around the center of the explosion
2698 pplayer is the player that caused the explosion.
2699 **************************************************************************/
2700 void do_nuclear_explosion(struct player
*pplayer
, struct tile
*ptile
)
2702 square_iterate(ptile
, 1, ptile1
) {
2703 do_nuke_tile(pplayer
, ptile1
);
2704 } square_iterate_end
;
2706 notify_conn(NULL
, ptile
, E_NUKE
, ftc_server
,
2707 _("The %s detonated a nuke!"),
2708 nation_plural_for_player(pplayer
));
2711 /**************************************************************************
2712 go by airline, if both cities have an airport and neither has been used this
2713 turn the unit will be transported by it and have its moves set to 0
2714 **************************************************************************/
2715 bool do_airline(struct unit
*punit
, struct city
*pdest_city
)
2717 struct city
*psrc_city
= tile_city(unit_tile(punit
));
2719 notify_player(unit_owner(punit
), city_tile(pdest_city
),
2720 E_UNIT_RELOCATED
, ftc_server
,
2721 _("%s transported successfully."),
2724 unit_move(punit
, pdest_city
->tile
, punit
->moves_left
, NULL
,
2725 /* Can only airlift to allied and domestic cities */
2728 /* Update airlift fields. */
2729 if (!(game
.info
.airlifting_style
& AIRLIFTING_UNLIMITED_SRC
)) {
2730 psrc_city
->airlift
--;
2731 send_city_info(city_owner(psrc_city
), psrc_city
);
2733 if (!(game
.info
.airlifting_style
& AIRLIFTING_UNLIMITED_DEST
)) {
2734 pdest_city
->airlift
--;
2735 send_city_info(city_owner(pdest_city
), pdest_city
);
2741 /**************************************************************************
2742 Autoexplore with unit.
2743 **************************************************************************/
2744 void do_explore(struct unit
*punit
)
2746 switch (manage_auto_explorer(punit
)) {
2748 /* don't use punit! */
2750 case MR_NOT_ALLOWED
:
2751 /* Needed for something else */
2754 /* FIXME: manage_auto_explorer() isn't supposed to change the activity,
2755 * but don't count on this. See PR#39792.
2757 if (punit
->activity
== ACTIVITY_EXPLORE
) {
2762 unit_activity_handling(punit
, ACTIVITY_IDLE
);
2764 /* FIXME: When the manage_auto_explorer() call changes the activity from
2765 * EXPLORE to IDLE, in unit_activity_handling() ai.control is left
2766 * alone. We reset it here. See PR#12931. */
2767 punit
->ai_controlled
= FALSE
;
2771 send_unit_info(NULL
, punit
); /* probably duplicate */
2774 /**************************************************************************
2775 Returns whether the drop was made or not. Note that it also returns 1
2776 in the case where the drop was succesful, but the unit was killed by
2777 barbarians in a hut.
2778 **************************************************************************/
2779 bool do_paradrop(struct unit
*punit
, struct tile
*ptile
)
2781 struct player
*pplayer
= unit_owner(punit
);
2783 if (map_is_known_and_seen(ptile
, pplayer
, V_MAIN
)) {
2784 if (!can_unit_exist_at_tile(punit
, ptile
)
2785 && (!game
.info
.paradrop_to_transport
2786 || !unit_could_load_at(punit
, ptile
))) {
2787 notify_player(pplayer
, ptile
, E_BAD_COMMAND
, ftc_server
,
2788 _("This unit cannot paradrop into %s."),
2789 terrain_name_translation(tile_terrain(ptile
)));
2793 if (NULL
!= is_non_attack_city_tile(ptile
, pplayer
)) {
2794 notify_player(pplayer
, ptile
, E_BAD_COMMAND
, ftc_server
,
2795 _("Cannot attack unless you declare war first."));
2799 unit_list_iterate(ptile
->units
, pother
) {
2800 if (can_player_see_unit(pplayer
, pother
)
2801 && pplayers_non_attack(pplayer
, unit_owner(pother
))) {
2802 notify_player(pplayer
, ptile
, E_BAD_COMMAND
, ftc_server
,
2803 _("Cannot attack unless you declare war first."));
2806 } unit_list_iterate_end
;
2808 if (is_military_unit(punit
)
2809 && !player_can_invade_tile(pplayer
, ptile
)) {
2810 notify_player(pplayer
, ptile
, E_BAD_COMMAND
, ftc_server
,
2811 _("Cannot invade unless you break peace with "
2813 player_name(tile_owner(ptile
)));
2817 /* Only take in account values from player map. */
2818 const struct player_tile
*plrtile
= map_get_player_tile(ptile
, pplayer
);
2820 if (NULL
== plrtile
->site
2821 && !is_native_to_class(unit_class_get(punit
), plrtile
->terrain
,
2822 &(plrtile
->extras
))) {
2823 notify_player(pplayer
, ptile
, E_BAD_COMMAND
, ftc_server
,
2824 _("This unit cannot paradrop into %s."),
2825 terrain_name_translation(plrtile
->terrain
));
2829 if (NULL
!= plrtile
->site
2830 && plrtile
->owner
!= NULL
2831 && pplayers_non_attack(pplayer
, plrtile
->owner
)) {
2832 notify_player(pplayer
, ptile
, E_BAD_COMMAND
, ftc_server
,
2833 _("Cannot attack unless you declare war first."));
2837 if (is_military_unit(punit
)
2838 && NULL
!= plrtile
->owner
2839 && players_non_invade(pplayer
, plrtile
->owner
)) {
2840 notify_player(pplayer
, ptile
, E_BAD_COMMAND
, ftc_server
,
2841 _("Cannot invade unless you break peace with "
2843 player_name(plrtile
->owner
));
2847 /* Safe terrain, really? Not transformed since player last saw it. */
2848 if (!can_unit_exist_at_tile(punit
, ptile
)
2849 && (!game
.info
.paradrop_to_transport
2850 || !unit_could_load_at(punit
, ptile
))) {
2851 map_show_circle(pplayer
, ptile
, unit_type_get(punit
)->vision_radius_sq
);
2852 notify_player(pplayer
, ptile
, E_UNIT_LOST_MISC
, ftc_server
,
2853 _("Your %s paradropped into the %s and was lost."),
2854 unit_tile_link(punit
),
2855 terrain_name_translation(tile_terrain(ptile
)));
2856 pplayer
->score
.units_lost
++;
2857 server_remove_unit(punit
, ULR_NONNATIVE_TERR
);
2862 if (is_non_attack_city_tile(ptile
, pplayer
)
2863 || is_non_allied_unit_tile(ptile
, pplayer
)) {
2864 map_show_circle(pplayer
, ptile
, unit_type_get(punit
)->vision_radius_sq
);
2865 maybe_make_contact(ptile
, pplayer
);
2866 notify_player(pplayer
, ptile
, E_UNIT_LOST_MISC
, ftc_server
,
2867 _("Your %s was killed by enemy units at the "
2868 "paradrop destination."),
2869 unit_tile_link(punit
));
2870 /* TODO: Should defender score.units_killed get increased too?
2871 * What if there's units of several allied players? Should the
2872 * city owner or owner of the first/random unit get the kill? */
2873 pplayer
->score
.units_lost
++;
2874 server_remove_unit(punit
, ULR_KILLED
);
2879 punit
->paradropped
= TRUE
;
2880 if (unit_move(punit
, ptile
, unit_type_get(punit
)->paratroopers_mr_sub
,
2882 /* A paradrop into a non allied city results in a city
2884 /* FIXME: move the following actor requirements to the
2885 * ruleset. One alternative is to split "Paradrop Unit".
2886 * Another is to use different enablers. */
2887 (pplayer
->ai_common
.barbarian_type
!= ANIMAL_BARBARIAN
2888 && uclass_has_flag(unit_class_get(punit
),
2889 UCF_CAN_OCCUPY_CITY
)
2890 && !unit_has_type_flag(punit
, UTYF_CIVILIAN
)
2891 && is_non_allied_city_tile(ptile
, pplayer
)))) {
2892 /* Ensure we finished on valid state. */
2893 fc_assert(can_unit_exist_at_tile(punit
, unit_tile(punit
))
2894 || unit_transported(punit
));
2899 /**************************************************************************
2900 Give 25 Gold or kill the unit. For H_LIMITEDHUTS
2901 Return TRUE if unit is alive, and FALSE if it was killed
2902 **************************************************************************/
2903 static bool hut_get_limited(struct unit
*punit
)
2906 int hut_chance
= fc_rand(12);
2907 struct player
*pplayer
= unit_owner(punit
);
2908 /* 1 in 12 to get barbarians */
2909 if (hut_chance
!= 0) {
2911 notify_player(pplayer
, unit_tile(punit
), E_HUT_GOLD
, ftc_server
,
2912 PL_("You found %d gold.",
2913 "You found %d gold.", cred
), cred
);
2914 pplayer
->economic
.gold
+= cred
;
2915 } else if (city_exists_within_max_city_map(unit_tile(punit
), TRUE
)
2916 || unit_has_type_flag(punit
, UTYF_GAMELOSS
)) {
2917 notify_player(pplayer
, unit_tile(punit
),
2918 E_HUT_BARB_CITY_NEAR
, ftc_server
,
2919 _("An abandoned village is here."));
2921 notify_player(pplayer
, unit_tile(punit
), E_HUT_BARB_KILLED
, ftc_server
,
2922 _("Your %s has been killed by barbarians!"),
2923 unit_tile_link(punit
));
2924 wipe_unit(punit
, ULR_BARB_UNLEASH
, NULL
);
2930 /**************************************************************************
2931 Due to the effects in the scripted hut behavior can not be predicted,
2932 unit_enter_hut returns nothing.
2933 **************************************************************************/
2934 static void unit_enter_hut(struct unit
*punit
)
2936 struct player
*pplayer
= unit_owner(punit
);
2937 enum hut_behavior behavior
= unit_class_get(punit
)->hut_behavior
;
2938 struct tile
*ptile
= unit_tile(punit
);
2940 /* FIXME: Should we still run "hut_enter" script when
2941 * hut_behavior is HUT_NOTHING or HUT_FRIGHTEN? */
2942 if (behavior
== HUT_NOTHING
) {
2946 extra_type_by_category_iterate(ECAT_BONUS
, pextra
) {
2947 if (tile_has_extra(ptile
, pextra
)) {
2948 pplayer
->server
.huts
++;
2950 destroy_extra(ptile
, pextra
);
2951 update_tile_knowledge(unit_tile(punit
));
2953 if (behavior
== HUT_FRIGHTEN
) {
2954 notify_player(pplayer
, unit_tile(punit
), E_HUT_BARB
, ftc_server
,
2955 _("Your overflight frightens the tribe;"
2956 " they scatter in terror."));
2960 /* AI with H_LIMITEDHUTS only gets 25 gold (or barbs if unlucky) */
2961 if (is_ai(pplayer
) && has_handicap(pplayer
, H_LIMITEDHUTS
)) {
2962 (void) hut_get_limited(punit
);
2966 /* FIXME: Should have parameter for hut extra type */
2967 script_server_signal_emit("hut_enter", 1,
2968 API_TYPE_UNIT
, punit
);
2970 } extra_type_by_category_iterate_end
;
2972 send_player_info_c(pplayer
, pplayer
->connections
); /* eg, gold */
2976 /****************************************************************************
2977 Put the unit onto the transporter, and tell everyone.
2978 ****************************************************************************/
2979 void unit_transport_load_send(struct unit
*punit
, struct unit
*ptrans
)
2981 fc_assert_ret(punit
!= NULL
);
2982 fc_assert_ret(ptrans
!= NULL
);
2984 unit_transport_load(punit
, ptrans
, FALSE
);
2986 send_unit_info(NULL
, punit
);
2987 send_unit_info(NULL
, ptrans
);
2990 /****************************************************************************
2991 Load unit to transport, send transport's loaded status to everyone.
2992 ****************************************************************************/
2993 static void unit_transport_load_tp_status(struct unit
*punit
,
2994 struct unit
*ptrans
,
2999 fc_assert_ret(punit
!= NULL
);
3000 fc_assert_ret(ptrans
!= NULL
);
3002 had_cargo
= get_transporter_occupancy(ptrans
) > 0;
3004 unit_transport_load(punit
, ptrans
, force
);
3007 /* Transport's loaded status changed */
3008 send_unit_info(NULL
, ptrans
);
3012 /****************************************************************************
3013 Pull the unit off of the transporter, and tell everyone.
3014 ****************************************************************************/
3015 void unit_transport_unload_send(struct unit
*punit
)
3017 struct unit
*ptrans
;
3019 fc_assert_ret(punit
);
3021 ptrans
= unit_transport_get(punit
);
3023 fc_assert_ret(ptrans
);
3025 unit_transport_unload(punit
);
3027 send_unit_info(NULL
, punit
);
3028 send_unit_info(NULL
, ptrans
);
3031 /*****************************************************************
3032 Used when unit_survive_autoattack()'s autoattack_prob_list
3033 autoattack frees its items.
3034 *****************************************************************/
3035 static void autoattack_prob_free(struct autoattack_prob
*prob
)
3040 /**************************************************************************
3041 This function is passed to autoattack_prob_list_sort() to sort a list of
3042 units and action probabilities according to their win chance against the
3043 autoattack target, modified by transportation relationships.
3045 The reason for making sure that a cargo unit is ahead of its
3046 transporter(s) is to leave transports out of combat if at all possible.
3047 (The transport could be destroyed during combat.)
3048 **************************************************************************/
3049 static int compare_units(const struct autoattack_prob
*const *p1
,
3050 const struct autoattack_prob
*const *q1
)
3052 const struct unit
*p1unit
= game_unit_by_number((*p1
)->unit_id
);
3053 const struct unit
*q1unit
= game_unit_by_number((*q1
)->unit_id
);
3055 /* Sort by transport depth first. This makes sure that no transport
3056 * attacks before its cargo does -- cargo sorts earlier in the list. */
3058 const struct unit
*p1trans
= p1unit
, *q1trans
= q1unit
;
3060 /* Walk the transport stacks in parallel, so as to bail out as soon as
3061 * one of them is empty (avoid walking deep stacks more often than
3063 while (p1trans
&& q1trans
) {
3064 p1trans
= unit_transport_get(p1trans
);
3065 q1trans
= unit_transport_get(q1trans
);
3067 if (!p1trans
&& q1trans
) {
3068 /* q1 is at greater depth (perhaps it's p1's cargo). It should sort
3069 * earlier in the list (p1 > q1). */
3071 } else if (p1trans
&& !q1trans
) {
3072 /* p1 is at greater depth, so should sort earlier (p1 < q1). */
3075 /* else same depth, so move on to checking win chance: */
3078 /* Put the units with the highest probability of success first. The up
3079 * side of this is that units with bonuses against the victim attacks
3080 * before other units. The downside is that strong units can be led
3081 * away by sacrificial units. */
3083 /* Assume the worst. */
3084 * action_prob_cmp_pessimist((*p1
)->prob
, (*q1
)->prob
));
3087 /*****************************************************************
3088 Check if unit survives enemy autoattacks. We assume that any
3089 unit that is adjacent to us can see us.
3090 *****************************************************************/
3091 static bool unit_survive_autoattack(struct unit
*punit
)
3093 struct autoattack_prob_list
*autoattack
;
3094 int moves
= punit
->moves_left
;
3095 int sanity1
= punit
->id
;
3097 if (!game
.server
.autoattack
) {
3101 autoattack
= autoattack_prob_list_new_full(autoattack_prob_free
);
3103 /* Kludge to prevent attack power from dropping to zero during calc */
3104 punit
->moves_left
= MAX(punit
->moves_left
, 1);
3106 adjc_iterate(unit_tile(punit
), ptile
) {
3107 /* First add all eligible units to a autoattack list */
3108 unit_list_iterate(ptile
->units
, penemy
) {
3109 struct autoattack_prob
*probability
= fc_malloc(sizeof(*probability
));
3110 struct tile
*tgt_tile
= unit_tile(punit
);
3112 fc_assert_action(tgt_tile
, continue);
3115 action_auto_perf_unit_prob(AAPC_UNIT_MOVED_ADJ
,
3116 penemy
, unit_owner(punit
), NULL
,
3117 tgt_tile
, tile_city(tgt_tile
),
3120 if (action_prob_possible(probability
->prob
)) {
3121 probability
->unit_id
= penemy
->id
;
3122 autoattack_prob_list_prepend(autoattack
, probability
);
3124 } unit_list_iterate_end
;
3127 /* Sort the potential attackers from highest to lowest success
3129 if (autoattack_prob_list_size(autoattack
) >= 2) {
3130 autoattack_prob_list_sort(autoattack
, &compare_units
);
3133 autoattack_prob_list_iterate_safe(autoattack
, peprob
, penemy
) {
3134 int sanity2
= penemy
->id
;
3135 struct tile
*ptile
= unit_tile(penemy
);
3136 struct unit
*enemy_defender
= get_defender(punit
, ptile
);
3137 double punitwin
, penemywin
;
3138 double threshold
= 0.25;
3139 struct tile
*tgt_tile
= unit_tile(punit
);
3141 fc_assert(tgt_tile
);
3143 if (tile_city(ptile
) && unit_list_size(ptile
->units
) == 1) {
3144 /* Don't leave city defenseless */
3148 if (NULL
!= enemy_defender
) {
3149 punitwin
= unit_win_chance(punit
, enemy_defender
);
3151 /* 'penemy' can attack 'punit' but it may be not reciproque. */
3155 /* Previous attacks may have changed the odds. Recalculate. */
3157 action_auto_perf_unit_prob(AAPC_UNIT_MOVED_ADJ
,
3158 penemy
, unit_owner(punit
), NULL
,
3159 tgt_tile
, tile_city(tgt_tile
),
3162 if (!action_prob_possible(peprob
->prob
)) {
3163 /* No longer legal. */
3167 /* Assume the worst. */
3168 penemywin
= action_prob_to_0_to_1_pessimist(peprob
->prob
);
3170 if ((penemywin
> 1.0 - punitwin
3171 || unit_has_type_flag(punit
, UTYF_PROVOKING
))
3172 && penemywin
> threshold
) {
3174 #ifdef REALLY_DEBUG_THIS
3175 log_test("AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3176 unit_rule_name(penemy
), unit_rule_name(punit
),
3177 TILE_XY(unit_tile(punit
)), penemywin
,
3178 1.0 - punitwin
, threshold
);
3181 unit_activity_handling(penemy
, ACTIVITY_IDLE
);
3182 action_auto_perf_unit_do(AAPC_UNIT_MOVED_ADJ
,
3183 penemy
, unit_owner(punit
), NULL
,
3184 tgt_tile
, tile_city(tgt_tile
), punit
);
3186 #ifdef REALLY_DEBUG_THIS
3187 log_test("!AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3188 unit_rule_name(penemy
), unit_rule_name(punit
),
3189 TILE_XY(unit_tile(punit
)), penemywin
,
3190 1.0 - punitwin
, threshold
);
3195 if (game_unit_by_number(sanity2
)) {
3196 send_unit_info(NULL
, penemy
);
3198 if (game_unit_by_number(sanity1
)) {
3199 send_unit_info(NULL
, punit
);
3201 autoattack_prob_list_destroy(autoattack
);
3202 return FALSE
; /* moving unit dead */
3204 } autoattack_prob_list_iterate_safe_end
;
3206 autoattack_prob_list_destroy(autoattack
);
3207 if (game_unit_by_number(sanity1
)) {
3208 /* We could have lost movement in combat */
3209 punit
->moves_left
= MIN(punit
->moves_left
, moves
);
3210 send_unit_info(NULL
, punit
);
3217 /****************************************************************************
3218 Cancel orders for the unit.
3219 ****************************************************************************/
3220 static void cancel_orders(struct unit
*punit
, char *dbg_msg
)
3222 free_unit_orders(punit
);
3223 send_unit_info(NULL
, punit
);
3224 log_debug("%s", dbg_msg
);
3227 /*****************************************************************
3228 Will wake up any neighboring enemy sentry units or patrolling
3230 *****************************************************************/
3231 static void wakeup_neighbor_sentries(struct unit
*punit
)
3235 if (NULL
!= tile_city(unit_tile(punit
))) {
3238 unit_list_iterate(unit_tile(punit
)->units
, aunit
) {
3239 /* Consider only units not transported. */
3240 if (!unit_transported(aunit
)) {
3243 } unit_list_iterate_end
;
3245 alone_in_city
= (1 == count
);
3247 alone_in_city
= FALSE
;
3250 /* There may be sentried units with a sightrange > 3, but we don't
3251 wake them up if the punit is farther away than 3. */
3252 square_iterate(unit_tile(punit
), 3, ptile
) {
3253 unit_list_iterate(ptile
->units
, penemy
) {
3254 int distance_sq
= sq_map_distance(unit_tile(punit
), ptile
);
3255 int radius_sq
= get_unit_vision_at(penemy
, unit_tile(penemy
), V_MAIN
);
3257 if (!pplayers_allied(unit_owner(punit
), unit_owner(penemy
))
3258 && penemy
->activity
== ACTIVITY_SENTRY
3259 && radius_sq
>= distance_sq
3260 /* If the unit moved on a city, and the unit is alone, consider
3263 || can_player_see_unit(unit_owner(penemy
), punit
))
3264 /* on board transport; don't awaken */
3265 && can_unit_exist_at_tile(penemy
, unit_tile(penemy
))) {
3266 set_unit_activity(penemy
, ACTIVITY_IDLE
);
3267 send_unit_info(NULL
, penemy
);
3269 } unit_list_iterate_end
;
3270 } square_iterate_end
;
3272 /* Wakeup patrolling units we bump into.
3273 We do not wakeup units further away than 3 squares... */
3274 square_iterate(unit_tile(punit
), 3, ptile
) {
3275 unit_list_iterate(ptile
->units
, ppatrol
) {
3276 if (punit
!= ppatrol
3277 && unit_has_orders(ppatrol
)
3278 && ppatrol
->orders
.vigilant
) {
3279 if (maybe_cancel_patrol_due_to_enemy(ppatrol
)) {
3280 cancel_orders(ppatrol
, " stopping because of nearby enemy");
3281 notify_player(unit_owner(ppatrol
), unit_tile(ppatrol
),
3282 E_UNIT_ORDERS
, ftc_server
,
3283 _("Orders for %s aborted after enemy movement was "
3285 unit_link(ppatrol
));
3288 } unit_list_iterate_end
;
3289 } square_iterate_end
;
3292 /**************************************************************************
3293 Does: 1) updates the unit's homecity and the city it enters/leaves (the
3294 city's happiness varies). This also takes into account when the
3295 unit enters/leaves a fortress.
3296 2) updates adjacent cities' unavailable tiles.
3298 FIXME: Sometimes it is not necessary to send cities because the goverment
3299 doesn't care whether a unit is away or not.
3300 **************************************************************************/
3301 static bool unit_move_consequences(struct unit
*punit
,
3302 struct tile
*src_tile
,
3303 struct tile
*dst_tile
,
3305 bool conquer_city_allowed
)
3307 struct city
*fromcity
= tile_city(src_tile
);
3308 struct city
*tocity
= tile_city(dst_tile
);
3309 struct city
*homecity_start_pos
= NULL
;
3310 struct city
*homecity_end_pos
= NULL
;
3311 int homecity_id_start_pos
= punit
->homecity
;
3312 int homecity_id_end_pos
= punit
->homecity
;
3313 struct player
*pplayer_start_pos
= unit_owner(punit
);
3314 struct player
*pplayer_end_pos
= pplayer_start_pos
;
3315 struct unit_type
*type_start_pos
= unit_type_get(punit
);
3316 struct unit_type
*type_end_pos
= type_start_pos
;
3317 bool refresh_homecity_start_pos
= FALSE
;
3318 bool refresh_homecity_end_pos
= FALSE
;
3319 int saved_id
= punit
->id
;
3322 if (tocity
&& conquer_city_allowed
) {
3324 /* The unit that does the move may conquer. */
3325 unit_conquer_city(punit
, tocity
);
3328 /* Run for passengers too. A passenger may have been killed when its
3329 * transport conquered a city. (unit_conquer_city() can cause Lua code
3332 alive
= unit_is_alive(saved_id
);
3334 /* In case script has changed something about unit */
3335 pplayer_end_pos
= unit_owner(punit
);
3336 type_end_pos
= unit_type_get(punit
);
3337 homecity_id_end_pos
= punit
->homecity
;
3341 if (homecity_id_start_pos
!= 0) {
3342 homecity_start_pos
= game_city_by_number(homecity_id_start_pos
);
3344 if (homecity_id_start_pos
!= homecity_id_end_pos
) {
3345 homecity_end_pos
= game_city_by_number(homecity_id_end_pos
);
3347 homecity_end_pos
= homecity_start_pos
;
3350 /* We only do refreshes for non-AI players to now make sure the AI turns
3351 doesn't take too long. Perhaps we should make a special refresh_city
3352 functions that only refreshed happines. */
3354 /* might have changed owners or may be destroyed */
3355 tocity
= tile_city(dst_tile
);
3357 if (tocity
) { /* entering a city */
3358 if (tocity
->owner
== pplayer_end_pos
) {
3359 if (tocity
!= homecity_end_pos
&& is_human(pplayer_end_pos
)) {
3360 city_refresh(tocity
);
3361 send_city_info(pplayer_end_pos
, tocity
);
3364 if (homecity_start_pos
) {
3365 refresh_homecity_start_pos
= TRUE
;
3369 if (fromcity
) { /* leaving a city */
3370 if (homecity_start_pos
) {
3371 refresh_homecity_start_pos
= TRUE
;
3373 if (fromcity
!= homecity_start_pos
3374 && fromcity
->owner
== pplayer_start_pos
3375 && is_human(pplayer_start_pos
)) {
3376 city_refresh(fromcity
);
3377 send_city_info(pplayer_start_pos
, fromcity
);
3381 /* entering/leaving a fortress or friendly territory */
3382 if (homecity_start_pos
|| homecity_end_pos
) {
3383 if ((game
.info
.happyborders
!= HB_DISABLED
&& tile_owner(src_tile
) != tile_owner(dst_tile
))
3384 || (tile_has_base_flag_for_unit(dst_tile
,
3387 && is_friendly_city_near(pplayer_end_pos
, dst_tile
))
3388 || (tile_has_base_flag_for_unit(src_tile
,
3391 && is_friendly_city_near(pplayer_start_pos
, src_tile
))) {
3392 refresh_homecity_start_pos
= TRUE
;
3393 refresh_homecity_end_pos
= TRUE
;
3397 if (refresh_homecity_start_pos
&& is_human(pplayer_start_pos
)) {
3398 city_refresh(homecity_start_pos
);
3399 send_city_info(pplayer_start_pos
, homecity_start_pos
);
3401 if (refresh_homecity_end_pos
3402 && (!refresh_homecity_start_pos
3403 || homecity_start_pos
!= homecity_end_pos
)
3404 && is_human(pplayer_end_pos
)) {
3405 city_refresh(homecity_end_pos
);
3406 send_city_info(pplayer_end_pos
, homecity_end_pos
);
3409 city_map_update_tile_now(dst_tile
);
3415 /**************************************************************************
3416 Check if the units activity is legal for a move , and reset it if it isn't.
3417 **************************************************************************/
3418 static void check_unit_activity(struct unit
*punit
)
3420 switch (punit
->activity
) {
3422 case ACTIVITY_SENTRY
:
3423 case ACTIVITY_EXPLORE
:
3426 case ACTIVITY_POLLUTION
:
3428 case ACTIVITY_IRRIGATE
:
3429 case ACTIVITY_FORTIFIED
:
3430 case ACTIVITY_FORTRESS
:
3431 case ACTIVITY_PILLAGE
:
3432 case ACTIVITY_TRANSFORM
:
3433 case ACTIVITY_UNKNOWN
:
3434 case ACTIVITY_AIRBASE
:
3435 case ACTIVITY_FORTIFYING
:
3436 case ACTIVITY_FALLOUT
:
3437 case ACTIVITY_PATROL_UNUSED
:
3439 case ACTIVITY_GEN_ROAD
:
3440 case ACTIVITY_CONVERT
:
3441 case ACTIVITY_OLD_ROAD
:
3442 case ACTIVITY_OLD_RAILROAD
:
3444 set_unit_activity(punit
, ACTIVITY_IDLE
);
3449 /****************************************************************************
3450 Create a new unit move data, or use previous one if available.
3451 ****************************************************************************/
3452 static struct unit_move_data
*unit_move_data(struct unit
*punit
,
3453 struct tile
*psrctile
,
3454 struct tile
*pdesttile
)
3456 struct unit_move_data
*pdata
;
3457 struct player
*powner
= unit_owner(punit
);
3458 const v_radius_t radius_sq
=
3459 V_RADIUS(get_unit_vision_at(punit
, pdesttile
, V_MAIN
),
3460 get_unit_vision_at(punit
, pdesttile
, V_INVIS
));
3461 struct vision
*new_vision
;
3464 if (punit
->server
.moving
) {
3465 /* Recursive moving (probably due to a script). */
3466 pdata
= punit
->server
.moving
;
3468 fc_assert_msg(pdata
->punit
== punit
,
3469 "Unit number %d (%p) was going to die, but "
3470 "server attempts to move it.",
3472 fc_assert_msg(pdata
->old_vision
== NULL
,
3473 "Unit number %d (%p) has done an incomplete move.",
3476 pdata
= fc_malloc(sizeof(*pdata
));
3477 pdata
->ref_count
= 1;
3478 pdata
->punit
= punit
;
3479 punit
->server
.moving
= pdata
;
3480 BV_CLR_ALL(pdata
->can_see_unit
);
3482 pdata
->powner
= powner
;
3483 BV_CLR_ALL(pdata
->can_see_move
);
3484 pdata
->old_vision
= punit
->server
.vision
;
3486 /* Remove unit from the source tile. */
3487 fc_assert(unit_tile(punit
) == psrctile
);
3488 success
= unit_list_remove(psrctile
->units
, punit
);
3489 fc_assert(success
== TRUE
);
3492 unit_tile_set(punit
, pdesttile
);
3493 unit_list_prepend(pdesttile
->units
, punit
);
3495 if (unit_transported(punit
)) {
3496 /* Silently free orders since they won't be applicable anymore. */
3497 free_unit_orders(punit
);
3500 /* Check unit activity. */
3501 check_unit_activity(punit
);
3502 unit_did_action(punit
);
3503 unit_forget_last_activity(punit
);
3505 /* We first unfog the destination, then send the move,
3506 * and then fog the old territory. This means that the player
3507 * gets a chance to see the newly explored territory while the
3508 * client moves the unit, and both areas are visible during the
3511 /* Enhance vision if unit steps into a fortress */
3512 new_vision
= vision_new(powner
, pdesttile
);
3513 punit
->server
.vision
= new_vision
;
3514 vision_change_sight(new_vision
, radius_sq
);
3515 ASSERT_VISION(new_vision
);
3520 /****************************************************************************
3521 Decrease the reference counter and destroy if needed.
3522 ****************************************************************************/
3523 static void unit_move_data_unref(struct unit_move_data
*pdata
)
3525 fc_assert_ret(pdata
!= NULL
);
3526 fc_assert_ret(pdata
->ref_count
> 0);
3527 fc_assert_msg(pdata
->old_vision
== NULL
,
3528 "Unit number %d (%p) has done an incomplete move.",
3529 pdata
->punit
!= NULL
? pdata
->punit
->id
: -1, pdata
->punit
);
3532 if (pdata
->ref_count
== 0) {
3533 if (pdata
->punit
!= NULL
) {
3534 fc_assert(pdata
->punit
->server
.moving
== pdata
);
3535 pdata
->punit
->server
.moving
= NULL
;
3541 /*****************************************************************************
3542 Moves a unit. No checks whatsoever! This is meant as a practical
3543 function for other functions, like do_airline, which do the checking
3546 If you move a unit you should always use this function, as it also sets
3547 the transport status of the unit correctly. Note that the source tile (the
3548 current tile of the unit) and pdesttile need not be adjacent.
3550 Returns TRUE iff unit still alive.
3551 *****************************************************************************/
3552 bool unit_move(struct unit
*punit
, struct tile
*pdesttile
, int move_cost
,
3553 struct unit
*embark_to
, bool conquer_city_allowed
)
3555 struct player
*pplayer
;
3556 struct tile
*psrctile
;
3558 struct unit
*ptransporter
;
3559 struct packet_unit_info src_info
, dest_info
;
3560 struct packet_unit_short_info src_sinfo
, dest_sinfo
;
3561 struct unit_move_data_list
*plist
=
3562 unit_move_data_list_new_full(unit_move_data_unref
);
3563 struct unit_move_data
*pdata
;
3567 enum direction8 facing
;
3568 struct player
*bowner
;
3571 fc_assert_ret_val(punit
!= NULL
, FALSE
);
3572 fc_assert_ret_val(pdesttile
!= NULL
, FALSE
);
3574 pplayer
= unit_owner(punit
);
3575 saved_id
= punit
->id
;
3576 psrctile
= unit_tile(punit
);
3577 adj
= base_get_direction_for_step(psrctile
, pdesttile
, &facing
);
3579 conn_list_do_buffer(game
.est_connections
);
3581 /* Unload the unit if on a transport. */
3582 ptransporter
= unit_transport_get(punit
);
3583 if (ptransporter
!= NULL
) {
3584 /* Unload unit _before_ setting the new tile! */
3585 unit_transport_unload(punit
);
3586 /* Send updated information to anyone watching that transporter
3587 * was unloading cargo. */
3588 send_unit_info(NULL
, ptransporter
);
3591 /* Wakup units next to us before we move. */
3592 wakeup_neighbor_sentries(punit
);
3594 /* Make info packets at 'psrctile'. */
3596 /* If tiles are adjacent, we will show the move to users able
3598 package_unit(punit
, &src_info
);
3599 package_short_unit(punit
, &src_sinfo
, UNIT_INFO_IDENTITY
, 0);
3602 /* Make new data for 'punit'. */
3603 pdata
= unit_move_data(punit
, psrctile
, pdesttile
);
3604 unit_move_data_list_prepend(plist
, pdata
);
3606 /* Set unit orientation */
3608 /* Only change orientation when moving to adjacent tile */
3609 punit
->facing
= facing
;
3613 punit
->moved
= TRUE
;
3614 punit
->moves_left
= MAX(0, punit
->moves_left
- move_cost
);
3615 if (punit
->moves_left
== 0 && !unit_has_orders(punit
)) {
3616 /* The next order may not require any remaining move fragments. */
3617 punit
->done_moving
= TRUE
;
3620 /* No longer relevant. */
3621 punit
->action_decision_tile
= NULL
;
3622 punit
->action_decision_want
= ACT_DEC_NOTHING
;
3625 && action_tgt_city(punit
, pdesttile
, FALSE
)) {
3626 /* The unit can perform an action to the city at the destination tile.
3627 * A long distance move (like an airlift) doesn't ask what action to
3628 * perform before moving. Ask now. */
3630 punit
->action_decision_want
= ACT_DEC_PASSIVE
;
3631 punit
->action_decision_tile
= pdesttile
;
3634 /* Claim ownership of fortress? */
3635 bowner
= extra_owner(pdesttile
);
3636 if ((bowner
== NULL
|| pplayers_at_war(bowner
, pplayer
))
3637 && tile_has_claimable_base(pdesttile
, unit_type_get(punit
))) {
3638 /* Yes. We claim *all* bases if there's *any* claimable base(s).
3639 * Even if original unit cannot claim other kind of bases, the
3640 * first claimed base will have influence over other bases,
3641 * or something like that. */
3642 tile_claim_bases(pdesttile
, pplayer
);
3645 /* Move all contained units. */
3646 unit_cargo_iterate(punit
, pcargo
) {
3647 pdata
= unit_move_data(pcargo
, psrctile
, pdesttile
);
3648 unit_move_data_list_append(plist
, pdata
);
3649 } unit_cargo_iterate_end
;
3651 /* Get data for 'punit'. */
3652 pdata
= unit_move_data_list_front(plist
);
3654 /* Determine the players able to see the move(s), now that the player
3655 * vision has been increased. */
3657 /* Main unit for adjacent move: the move is visible for every player
3658 * able to see on the matching unit layer. */
3659 enum vision_layer vlayer
= is_hiding_unit(punit
) ? V_INVIS
: V_MAIN
;
3661 players_iterate(oplayer
) {
3662 if (map_is_known_and_seen(psrctile
, oplayer
, vlayer
)
3663 || map_is_known_and_seen(pdesttile
, oplayer
, vlayer
)) {
3664 BV_SET(pdata
->can_see_unit
, player_index(oplayer
));
3665 BV_SET(pdata
->can_see_move
, player_index(oplayer
));
3667 } players_iterate_end
;
3669 unit_move_data_list_iterate(plist
, pmove_data
) {
3670 if (adj
&& pmove_data
== pdata
) {
3671 /* If positions are adjacent, we have already handled 'punit'. See
3676 players_iterate(oplayer
) {
3678 && can_player_see_unit_at(oplayer
, pmove_data
->punit
, psrctile
,
3679 pmove_data
!= pdata
))
3680 || can_player_see_unit_at(oplayer
, pmove_data
->punit
, pdesttile
,
3681 pmove_data
!= pdata
)) {
3682 BV_SET(pmove_data
->can_see_unit
, player_index(oplayer
));
3683 BV_SET(pmove_data
->can_see_move
, player_index(oplayer
));
3685 if (can_player_see_unit_at(oplayer
, pmove_data
->punit
, psrctile
,
3686 pmove_data
!= pdata
)) {
3687 /* The unit was seen with its source tile even if it was
3689 BV_SET(pmove_data
->can_see_unit
, player_index(oplayer
));
3691 } players_iterate_end
;
3692 } unit_move_data_list_iterate_end
;
3694 /* Check timeout settings. */
3695 if (current_turn_timeout() != 0 && game
.server
.timeoutaddenemymove
> 0) {
3696 bool new_information_for_enemy
= FALSE
;
3698 phase_players_iterate(penemy
) {
3699 /* Increase the timeout if an enemy unit moves and the
3700 * timeoutaddenemymove setting is in use. */
3701 if (penemy
->is_connected
3702 && pplayer
!= penemy
3703 && pplayers_at_war(pplayer
, penemy
)
3704 && BV_ISSET(pdata
->can_see_move
, player_index(penemy
))) {
3705 new_information_for_enemy
= TRUE
;
3708 } phase_players_iterate_end
;
3710 if (new_information_for_enemy
) {
3711 increase_timeout_because_unit_moved();
3715 /* Notifications of the move to the clients. */
3717 /* Special case: 'punit' is moving to adjacent position. Then we show
3718 * 'punit' move to all users able to see 'psrctile' or 'pdesttile'. */
3720 /* Make info packets at 'pdesttile'. */
3721 package_unit(punit
, &dest_info
);
3722 package_short_unit(punit
, &dest_sinfo
, UNIT_INFO_IDENTITY
, 0);
3724 conn_list_iterate(game
.est_connections
, pconn
) {
3725 struct player
*aplayer
= conn_get_player(pconn
);
3727 if (aplayer
== NULL
) {
3728 if (pconn
->observer
) {
3729 /* Global observers see all... */
3730 send_packet_unit_info(pconn
, &src_info
);
3731 send_packet_unit_info(pconn
, &dest_info
);
3733 } else if (BV_ISSET(pdata
->can_see_move
, player_index(aplayer
))) {
3734 if (aplayer
== pplayer
) {
3735 send_packet_unit_info(pconn
, &src_info
);
3736 send_packet_unit_info(pconn
, &dest_info
);
3738 send_packet_unit_short_info(pconn
, &src_sinfo
, FALSE
);
3739 send_packet_unit_short_info(pconn
, &dest_sinfo
, FALSE
);
3742 } conn_list_iterate_end
;
3746 unit_move_data_list_iterate(plist
, pmove_data
) {
3747 if (adj
&& pmove_data
== pdata
) {
3748 /* If positions are adjacent, we have already shown 'punit' move.
3753 /* Make info packets at 'pdesttile'. */
3754 package_unit(pmove_data
->punit
, &dest_info
);
3755 package_short_unit(pmove_data
->punit
, &dest_sinfo
,
3756 UNIT_INFO_IDENTITY
, 0);
3758 conn_list_iterate(game
.est_connections
, pconn
) {
3759 struct player
*aplayer
= conn_get_player(pconn
);
3761 if (aplayer
== NULL
) {
3762 if (pconn
->observer
) {
3763 /* Global observers see all... */
3764 send_packet_unit_info(pconn
, &dest_info
);
3766 } else if (BV_ISSET(pmove_data
->can_see_move
, player_index(aplayer
))) {
3767 if (aplayer
== pmove_data
->powner
) {
3768 send_packet_unit_info(pconn
, &dest_info
);
3770 send_packet_unit_short_info(pconn
, &dest_sinfo
, FALSE
);
3773 } conn_list_iterate_end
;
3774 } unit_move_data_list_iterate_end
;
3776 /* Clear old vision. */
3777 unit_move_data_list_iterate(plist
, pmove_data
) {
3778 vision_clear_sight(pmove_data
->old_vision
);
3779 vision_free(pmove_data
->old_vision
);
3780 pmove_data
->old_vision
= NULL
;
3781 } unit_move_data_list_iterate_end
;
3783 /* Move consequences. */
3784 unit_move_data_list_iterate(plist
, pmove_data
) {
3785 struct unit
*aunit
= pmove_data
->punit
;
3788 && unit_owner(aunit
) == pmove_data
->powner
3789 && unit_tile(aunit
) == pdesttile
) {
3790 (void) unit_move_consequences(aunit
, psrctile
, pdesttile
,
3791 pdata
!= pmove_data
,
3792 conquer_city_allowed
);
3794 } unit_move_data_list_iterate_end
;
3796 unit_lives
= (pdata
->punit
== punit
);
3798 /* Wakeup units and make contact. */
3800 wakeup_neighbor_sentries(punit
);
3802 maybe_make_contact(pdesttile
, pplayer
);
3805 /* Special checks for ground units in the ocean. */
3806 if (embark_to
|| !can_unit_survive_at_tile(punit
, pdesttile
)) {
3807 if (embark_to
!= NULL
) {
3808 ptransporter
= embark_to
;
3810 ptransporter
= transporter_for_unit(punit
);
3813 unit_transport_load_tp_status(punit
, ptransporter
, FALSE
);
3815 /* Set activity to sentry if boarding a ship. */
3816 if (is_human(pplayer
)
3817 && !unit_has_orders(punit
)
3818 && !punit
->ai_controlled
3819 && !can_unit_exist_at_tile(punit
, pdesttile
)) {
3820 set_unit_activity(punit
, ACTIVITY_SENTRY
);
3823 send_unit_info(NULL
, punit
);
3828 /* Remove units going out of sight. */
3829 unit_move_data_list_iterate_rev(plist
, pmove_data
) {
3830 struct unit
*aunit
= pmove_data
->punit
;
3832 if (aunit
== NULL
) {
3833 continue; /* Died! */
3836 players_iterate(aplayer
) {
3837 if (BV_ISSET(pmove_data
->can_see_unit
, player_index(aplayer
))
3838 && !can_player_see_unit(aplayer
, aunit
)) {
3839 unit_goes_out_of_sight(aplayer
, aunit
);
3841 } players_iterate_end
;
3842 } unit_move_data_list_iterate_rev_end
;
3844 /* Inform the owner's client about actor unit arrival. Can, depending on
3845 * the client settings, cause the client to start the process that makes
3846 * the action selection dialog pop up. */
3847 if ((pcity
= tile_city(pdesttile
))) {
3848 /* Arrival in a city counts. */
3850 unit_move_data_list_iterate(plist
, pmove_data
) {
3851 struct unit
*ptrans
;
3853 struct unit
*act_unit
;
3854 struct player
*act_player
;
3856 act_unit
= pmove_data
->punit
;
3857 act_player
= unit_owner(act_unit
);
3859 if (act_unit
== NULL
3860 || !unit_is_alive(act_unit
->id
)) {
3861 /* The unit died before reaching this point. */
3865 if (unit_tile(act_unit
) != pdesttile
) {
3866 /* The unit didn't arrive at the destination tile. */
3870 if (!is_human(act_player
)) {
3871 /* Only humans need reminders. */
3875 if (!unit_transported(act_unit
)) {
3876 /* Don't show the action selection dialog again. Non transported
3877 * units are handled before they move to the tile. */
3881 /* Open action dialog only if 'act_unit' and all its transporters
3882 * (recursively) don't have orders. */
3883 if (unit_has_orders(act_unit
)) {
3884 /* The unit it self has orders. */
3888 for (ptrans
= unit_transport_get(act_unit
);;
3889 ptrans
= unit_transport_get(ptrans
)) {
3890 if (NULL
== ptrans
) {
3891 /* No (recursive) transport has orders. */
3894 } else if (unit_has_orders(ptrans
)) {
3895 /* A unit transporting the unit has orders */
3902 /* A unit transporting act_unit has orders. */
3906 if (action_tgt_city(act_unit
, pdesttile
, FALSE
)) {
3907 /* There is a valid target. */
3909 act_unit
->action_decision_want
= ACT_DEC_PASSIVE
;
3910 act_unit
->action_decision_tile
= pdesttile
;
3912 /* Let the client know that this unit wants the player to decide
3914 send_unit_info(player_reply_dest(act_player
), act_unit
);
3916 } unit_move_data_list_iterate_end
;
3919 unit_move_data_list_destroy(plist
);
3921 /* Check cities at source and destination. */
3922 if ((pcity
= tile_city(psrctile
))) {
3923 refresh_dumb_city(pcity
);
3925 if ((pcity
= tile_city(pdesttile
))) {
3926 refresh_dumb_city(pcity
);
3930 /* Let the scripts run ... */
3931 script_server_signal_emit("unit_moved", 3,
3932 API_TYPE_UNIT
, punit
,
3933 API_TYPE_TILE
, psrctile
,
3934 API_TYPE_TILE
, pdesttile
);
3935 unit_lives
= unit_is_alive(saved_id
);
3940 unit_lives
= unit_survive_autoattack(punit
);
3944 /* Is there a hut? */
3945 if (tile_has_cause_extra(pdesttile
, EC_HUT
)) {
3946 unit_enter_hut(punit
);
3947 unit_lives
= unit_is_alive(saved_id
);
3951 conn_list_do_unbuffer(game
.est_connections
);
3956 /**************************************************************************
3957 Maybe cancel the goto if there is an enemy in the way
3958 **************************************************************************/
3959 static bool maybe_cancel_goto_due_to_enemy(struct unit
*punit
,
3962 return (is_non_allied_unit_tile(ptile
, unit_owner(punit
))
3963 || is_non_allied_city_tile(ptile
, unit_owner(punit
)));
3966 /**************************************************************************
3967 Maybe cancel the patrol as there is an enemy near.
3969 If you modify the wakeup range you should change it in
3970 wakeup_neighbor_sentries() too.
3971 **************************************************************************/
3972 static bool maybe_cancel_patrol_due_to_enemy(struct unit
*punit
)
3974 bool cancel
= FALSE
;
3975 int radius_sq
= get_unit_vision_at(punit
, unit_tile(punit
), V_MAIN
);
3976 struct player
*pplayer
= unit_owner(punit
);
3978 circle_iterate(unit_tile(punit
), radius_sq
, ptile
) {
3979 struct unit
*penemy
= is_non_allied_unit_tile(ptile
, pplayer
);
3981 struct vision_site
*pdcity
= map_get_player_site(ptile
, pplayer
);
3983 if ((penemy
&& can_player_see_unit(pplayer
, penemy
))
3984 || (pdcity
&& !pplayers_allied(pplayer
, vision_site_owner(pdcity
))
3985 && pdcity
->occupied
)) {
3989 } circle_iterate_end
;
3994 /**************************************************************************
3995 Returns TRUE iff it is reasonable to assume that the player is wathing
3998 Since the player is watching the unit there is no need to inform him
3999 about things he could see happening. Remember that it still may
4000 be necessary to explain why something happened.
4001 **************************************************************************/
4002 static inline bool player_is_watching(struct unit
*punit
, const bool fresh
)
4004 /* The player just sent the orders to the unit. The unit has moves left.
4005 * It is therefore safe to assume that the player already is paying
4006 * attention to the unit. */
4007 return fresh
&& punit
->moves_left
> 0;
4010 /****************************************************************************
4011 Executes a unit's orders stored in punit->orders. The unit is put on idle
4012 if an action fails or if "patrol" is set and an enemy unit is encountered.
4014 The return value will be TRUE if the unit lives, FALSE otherwise. (This
4015 function used to return a goto_result enumeration, declared in gotohand.h.
4016 But this enumeration was never checked by the caller and just lead to
4017 confusion. All the caller really needs to know is if the unit lived or
4018 died; everything else is handled internally within execute_orders.)
4020 If the orders are repeating the loop starts over at the beginning once it
4021 completes. To avoid infinite loops on railroad we stop for this
4022 turn when the unit is back where it started, even if it have moves left.
4024 A unit will attack under orders only on its final action.
4026 The fresh parameter is true if the order execution happens because the
4027 orders just were received.
4028 ****************************************************************************/
4029 bool execute_orders(struct unit
*punit
, const bool fresh
)
4031 struct tile
*dst_tile
;
4032 struct city
*tgt_city
;
4033 struct unit
*tgt_unit
;
4034 struct act_prob prob
;
4038 bool res
, last_order
;
4039 int unitid
= punit
->id
;
4040 struct player
*pplayer
= unit_owner(punit
);
4042 enum unit_activity activity
;
4044 fc_assert_ret_val(unit_has_orders(punit
), TRUE
);
4046 if (punit
->activity
!= ACTIVITY_IDLE
) {
4047 /* Unit's in the middle of an activity; wait for it to finish. */
4048 punit
->done_moving
= TRUE
;
4052 log_debug("Executing orders for %s %d", unit_rule_name(punit
), punit
->id
);
4054 /* Any time the orders are canceled we should give the player a message. */
4057 struct unit_order order
;
4059 if (punit
->done_moving
) {
4060 log_debug(" stopping because we're done this turn");
4064 if (punit
->orders
.vigilant
&& maybe_cancel_patrol_due_to_enemy(punit
)) {
4065 /* "Patrol" orders are stopped if an enemy is near. */
4066 cancel_orders(punit
, " stopping because of nearby enemy");
4067 notify_player(pplayer
, unit_tile(punit
), E_UNIT_ORDERS
, ftc_server
,
4068 _("Orders for %s aborted as there are units nearby."),
4073 if (moves_made
== punit
->orders
.length
) {
4074 /* For repeating orders, don't repeat more than once per turn. */
4075 log_debug(" stopping because we ran a round");
4076 punit
->done_moving
= TRUE
;
4077 send_unit_info(NULL
, punit
);
4082 order
= punit
->orders
.list
[punit
->orders
.index
];
4084 switch (order
.order
) {
4086 case ORDER_ACTION_MOVE
:
4088 if (0 == punit
->moves_left
) {
4089 log_debug(" stopping because of no more move points");
4093 case ORDER_PERFORM_ACTION
:
4094 if (action_mp_full_makes_legal(punit
, order
.action
)) {
4095 log_debug(" stopping. Not enough move points this turn");
4099 case ORDER_ACTIVITY
:
4101 /* Those actions don't require moves left. */
4105 last_order
= (!punit
->orders
.repeat
4106 && punit
->orders
.index
+ 1 == punit
->orders
.length
);
4109 /* Clear the orders before we engage in the move. That way any
4110 * has_orders checks will yield FALSE and this will be treated as
4111 * a normal move. This is important: for instance a caravan goto
4112 * will popup the caravan dialog on the last move only. */
4113 free_unit_orders(punit
);
4116 /* Advance the orders one step forward. This is needed because any
4117 * updates sent to the client as a result of the action should include
4118 * the new index value. Note that we have to send_unit_info somewhere
4119 * after this point so that the client is properly updated. */
4120 punit
->orders
.index
++;
4122 switch (order
.order
) {
4124 if (punit
->moves_left
< unit_move_rate(punit
)) {
4125 /* If the unit doesn't have full MP then it just waits until the
4126 * next turn. We assume that the next turn it will have full MP
4127 * (there's no check for that). */
4128 punit
->done_moving
= TRUE
;
4129 log_debug(" waiting this turn");
4130 send_unit_info(NULL
, punit
);
4133 case ORDER_ACTIVITY
:
4134 activity
= order
.activity
;
4136 struct extra_type
*pextra
= (order
.target
== EXTRA_NONE
?
4138 extra_by_number(order
.target
));
4140 if (pextra
== NULL
&& activity_requires_target(order
.activity
)) {
4141 /* Try to find a target extra before giving up this order or, if
4142 * serious enough, all orders. */
4144 enum unit_activity new_activity
= order
.activity
;
4146 unit_assign_specific_activity_target(punit
,
4147 &new_activity
, &pextra
);
4149 if (new_activity
!= order
.activity
) {
4150 /* At the time this code was written the only possible activity
4151 * change from unit_assign_specific_activity_target() was from
4152 * ACTIVITY_PILLAGE to ACTIVITY_IDLE. That would only happen
4153 * when a target extra couldn't be found. -- Sveinung */
4154 fc_assert_msg((order
.activity
== ACTIVITY_PILLAGE
4155 && new_activity
== ACTIVITY_IDLE
),
4156 "Skipping an order when canceling all orders may"
4157 " have been the correct thing to do.");
4159 /* Already removed, let's continue. */
4163 /* Should have given up or, if supported, changed the order's
4164 * activity to the activity suggested by
4165 * unit_activity_handling_targeted() before this line was
4167 * Remember that unit_activity_handling_targeted() has the power
4168 * to change the order's target extra directly. */
4169 fc_assert_msg(new_activity
== order
.activity
,
4170 "Activity not updated. Target may have changed.");
4172 /* Should have found a target or given up before reaching this
4174 fc_assert_msg((pextra
!= NULL
4175 || !activity_requires_target(order
.activity
)),
4176 "Activity requires a target. No target found.");
4179 if (can_unit_do_activity_targeted(punit
, activity
, pextra
)) {
4180 punit
->done_moving
= TRUE
;
4181 set_unit_activity_targeted(punit
, activity
, pextra
);
4182 send_unit_info(NULL
, punit
);
4185 if ((activity
== ACTIVITY_BASE
4186 || activity
== ACTIVITY_GEN_ROAD
4187 || activity
== ACTIVITY_IRRIGATE
4188 || activity
== ACTIVITY_MINE
)
4189 && tile_has_extra(unit_tile(punit
), pextra
)) {
4190 break; /* Already built, let's continue. */
4191 } else if ((activity
== ACTIVITY_POLLUTION
4192 || activity
== ACTIVITY_FALLOUT
4193 || activity
== ACTIVITY_PILLAGE
)
4194 && !tile_has_extra(unit_tile(punit
), pextra
)) {
4195 break; /* Already removed, let's continue. */
4200 cancel_orders(punit
, " orders canceled because of failed activity");
4201 notify_player(pplayer
, unit_tile(punit
), E_UNIT_ORDERS
, ftc_server
,
4202 _("Orders for %s aborted since they "
4203 "give an invalid activity."),
4207 case ORDER_ACTION_MOVE
:
4209 if (!(dst_tile
= mapstep(unit_tile(punit
), order
.dir
))) {
4210 cancel_orders(punit
, " move order sent us to invalid location");
4211 notify_player(pplayer
, unit_tile(punit
), E_UNIT_ORDERS
, ftc_server
,
4212 _("Orders for %s aborted since they "
4213 "give an invalid location."),
4218 if (order
.order
!= ORDER_ACTION_MOVE
4219 && maybe_cancel_goto_due_to_enemy(punit
, dst_tile
)) {
4220 /* Plain move required: no attack, trade route etc. */
4221 cancel_orders(punit
, " orders canceled because of enemy");
4222 notify_player(pplayer
, unit_tile(punit
), E_UNIT_ORDERS
, ftc_server
,
4223 _("Orders for %s aborted as there "
4224 "are units in the way."),
4229 log_debug(" moving to %d,%d", TILE_XY(dst_tile
));
4230 res
= unit_move_handling(punit
, dst_tile
, FALSE
,
4231 order
.order
!= ORDER_ACTION_MOVE
, NULL
);
4232 if (!player_unit_by_number(pplayer
, unitid
)) {
4233 log_debug(" unit died while moving.");
4234 /* A player notification should already have been sent. */
4238 if (res
&& !same_pos(dst_tile
, unit_tile(punit
))) {
4239 /* Movement succeeded but unit didn't move. */
4240 log_debug(" orders resulted in combat.");
4241 send_unit_info(NULL
, punit
);
4246 fc_assert(0 <= punit
->moves_left
);
4248 /* Movement failed (ZOC, etc.) */
4249 cancel_orders(punit
, " attempt to move failed.");
4251 if (!player_is_watching(punit
, fresh
)
4252 /* The final move "failed" because the unit needs to ask the
4253 * player what action it should take.
4255 * The action decision request notifies the player. Its
4256 * location at the unit's last order makes it clear to the
4257 * player who the decision is for. ("The Spy I sent to Berlin
4260 * A notification message is therefore redundant. */
4262 && punit
->action_decision_want
== ACT_DEC_ACTIVE
4263 && punit
->action_decision_tile
== dst_tile
)) {
4264 /* The player may have missed this. No one else will announce it
4265 * in a satisfying manner. Inform the player. */
4266 notify_player(pplayer
, unit_tile(punit
),
4267 E_UNIT_ORDERS
, ftc_server
,
4268 _("Orders for %s aborted because of failed move."),
4275 case ORDER_PERFORM_ACTION
:
4276 log_debug(" orders: doing action %d", order
.action
);
4278 if (!direction8_is_valid(order
.dir
)) {
4279 /* The target of the action is on the actor's tile. */
4280 dst_tile
= unit_tile(punit
);
4282 /* The target of the action is on a tile next to the actor. */
4283 dst_tile
= mapstep(unit_tile(punit
), order
.dir
);
4286 if (dst_tile
== NULL
) {
4287 /* Could be at the edge of the map while trying to target a tile
4290 cancel_orders(punit
, " target location doesn't exist");
4291 illegal_action_msg(unit_owner(punit
), E_UNIT_ORDERS
, punit
,
4292 order
.action
, dst_tile
, NULL
, NULL
);
4297 /* Get the target city from the target tile. */
4298 tgt_city
= tile_city(dst_tile
);
4300 if (tgt_city
== NULL
4301 && action_id_get_target_kind(order
.action
) == ATK_CITY
) {
4302 /* This action targets a city but no city target was found. */
4304 cancel_orders(punit
, " perform action vs city with no city");
4305 illegal_action_msg(unit_owner(punit
), E_UNIT_ORDERS
, punit
,
4306 order
.action
, dst_tile
, tgt_city
, NULL
);
4311 /* Get a target unit at the target tile. */
4312 tgt_unit
= action_tgt_unit(punit
, dst_tile
, TRUE
);
4314 if (tgt_unit
== NULL
4315 && action_id_get_target_kind(order
.action
) == ATK_UNIT
) {
4316 /* This action targets a unit but no target unit was found. */
4318 cancel_orders(punit
, " perform action vs unit with no unit");
4319 illegal_action_msg(unit_owner(punit
), E_UNIT_ORDERS
, punit
,
4320 order
.action
, dst_tile
, tgt_city
, tgt_unit
);
4325 /* No target selected. */
4328 /* Assume impossible until told otherwise. */
4329 prob
= ACTPROB_IMPOSSIBLE
;
4331 switch (action_id_get_target_kind(order
.action
)) {
4333 prob
= action_prob_vs_units(punit
, order
.action
,
4335 tgt_id
= dst_tile
->index
;
4338 prob
= action_prob_vs_tile(punit
, order
.action
,
4340 tgt_id
= dst_tile
->index
;
4343 prob
= action_prob_vs_city(punit
, order
.action
,
4345 tgt_id
= tgt_city
->id
;
4348 prob
= action_prob_vs_unit(punit
, order
.action
,
4351 tgt_id
= tgt_unit
->id
;
4354 prob
= action_prob_self(punit
, order
.action
);
4359 log_error("Invalid action target kind");
4361 /* The check below will abort and cancel the orders because prob
4362 * was initialized to impossible above this switch statement. */
4367 if (!action_prob_possible(prob
)) {
4368 /* The player has enough information to know that this action is
4369 * against the rules. Don't risk any punishment by trying to
4372 cancel_orders(punit
, " illegal action");
4373 notify_player(pplayer
, unit_tile(punit
), E_UNIT_ORDERS
, ftc_server
,
4374 _("%s could not do %s to %s."),
4376 action_id_name_translation(order
.action
),
4377 tile_link(dst_tile
));
4379 /* Try to explain what rule made it illegal. */
4380 illegal_action_msg(unit_owner(punit
), E_BAD_COMMAND
, punit
,
4381 order
.action
, dst_tile
, tgt_city
, tgt_unit
);
4386 if (action_id_has_result(order
.action
, ACTION_FOUND_CITY
)) {
4387 /* This action needs a name. */
4388 name
= city_name_suggestion(pplayer
, unit_tile(punit
));
4390 /* This action doesn't need a name. */
4394 performed
= unit_perform_action(pplayer
,
4402 if (!player_unit_by_number(pplayer
, unitid
)) {
4403 /* The unit "died" while performing the action. */
4408 /* The action wasn't performed as ordered. */
4410 cancel_orders(punit
, " failed action");
4411 notify_player(pplayer
, unit_tile(punit
), E_UNIT_ORDERS
, ftc_server
,
4412 _("Orders for %s aborted because "
4413 "doing %s to %s failed."),
4415 action_id_name_translation(order
.action
),
4416 tile_link(dst_tile
));
4423 cancel_orders(punit
, " client sent invalid order!");
4424 notify_player(pplayer
, unit_tile(punit
), E_UNIT_ORDERS
, ftc_server
,
4425 _("Your %s has invalid orders."),
4431 fc_assert(punit
->has_orders
== FALSE
);
4432 log_debug(" stopping because orders are complete");
4436 if (punit
->orders
.index
== punit
->orders
.length
) {
4437 fc_assert(punit
->orders
.repeat
);
4439 log_debug(" repeating orders.");
4440 punit
->orders
.index
= 0;
4445 /****************************************************************************
4446 Return the vision the unit will have at the given tile. The base vision
4447 range may be modified by effects.
4449 Note that vision MUST be independent of transported_by for this to work
4451 ****************************************************************************/
4452 int get_unit_vision_at(struct unit
*punit
, struct tile
*ptile
,
4453 enum vision_layer vlayer
)
4455 const int base
= (unit_type_get(punit
)->vision_radius_sq
4456 + get_unittype_bonus(unit_owner(punit
), ptile
,
4457 unit_type_get(punit
),
4458 EFT_UNIT_VISION_RADIUS_SQ
));
4463 return MIN(base
, 2);
4468 log_error("Unsupported vision layer variant: %d.", vlayer
);
4472 /****************************************************************************
4473 Refresh the unit's vision.
4475 This function has very small overhead and can be called any time effects
4476 may have changed the vision range of the city.
4477 ****************************************************************************/
4478 void unit_refresh_vision(struct unit
*punit
)
4480 struct vision
*uvision
= punit
->server
.vision
;
4481 const v_radius_t radius_sq
=
4482 V_RADIUS(get_unit_vision_at(punit
, unit_tile(punit
), V_MAIN
),
4483 get_unit_vision_at(punit
, unit_tile(punit
), V_INVIS
));
4485 vision_change_sight(uvision
, radius_sq
);
4486 ASSERT_VISION(uvision
);
4489 /****************************************************************************
4490 Refresh the vision of all units in the list - see unit_refresh_vision.
4491 ****************************************************************************/
4492 void unit_list_refresh_vision(struct unit_list
*punitlist
)
4494 unit_list_iterate(punitlist
, punit
) {
4495 unit_refresh_vision(punit
);
4496 } unit_list_iterate_end
;
4499 /****************************************************************************
4500 Used to implement the game rule controlled by the unitwaittime setting.
4501 Notifies the unit owner if the unit is unable to act.
4502 ****************************************************************************/
4503 bool unit_can_do_action_now(const struct unit
*punit
)
4511 if (game
.server
.unitwaittime
<= 0) {
4515 if (punit
->server
.action_turn
!= game
.info
.turn
- 1) {
4519 dt
= time(NULL
) - punit
->server
.action_timestamp
;
4520 if (dt
< game
.server
.unitwaittime
) {
4522 format_time_duration(game
.server
.unitwaittime
- dt
, buf
, sizeof(buf
));
4523 notify_player(unit_owner(punit
), unit_tile(punit
), E_BAD_COMMAND
,
4524 ftc_server
, _("Your unit may not act for another %s "
4525 "this turn. See /help unitwaittime."), buf
);
4532 /****************************************************************************
4533 Mark a unit as having done something at the current time. This is used
4534 in conjunction with unit_can_do_action_now() and the unitwaittime setting.
4535 ****************************************************************************/
4536 void unit_did_action(struct unit
*punit
)
4542 punit
->server
.action_timestamp
= time(NULL
);
4543 punit
->server
.action_turn
= game
.info
.turn
;
4546 /**************************************************************************
4547 Units (usually barbarian units) may disband spontaneously if they are
4548 far from any enemy units or cities. It is to remove barbarians that do
4549 not engage into any activity for a long time.
4550 **************************************************************************/
4551 bool unit_can_be_retired(struct unit
*punit
)
4553 /* check if there is enemy nearby */
4554 square_iterate(unit_tile(punit
), 3, ptile
) {
4555 if (is_enemy_city_tile(ptile
, unit_owner(punit
))
4556 || is_enemy_unit_tile(ptile
, unit_owner(punit
))) {