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"
62 #include "barbarian.h"
63 #include "citytools.h"
70 #include "sanitycheck.h"
73 #include "techtools.h"
78 #include "autoexplorer.h"
79 #include "autosettlers.h"
82 #include "handicaps.h"
84 #include "unittools.h"
87 /* Tools for controlling the client vision of every unit when a unit
88 * moves + script effects. See unit_move(). You can access this data with
89 * punit->server.moving; it may be NULL if the unit is not moving). */
90 struct unit_move_data
{
92 struct unit
*punit
; /* NULL for invalidating. */
93 struct player
*powner
;
94 bv_player can_see_unit
;
95 bv_player can_see_move
;
96 struct vision
*old_vision
;
99 #define SPECLIST_TAG unit_move_data
100 #include "speclist.h"
101 #define unit_move_data_list_iterate(_plist, _pdata) \
102 TYPED_LIST_ITERATE(struct unit_move_data, _plist, _pdata)
103 #define unit_move_data_list_iterate_end LIST_ITERATE_END
104 #define unit_move_data_list_iterate_rev(_plist, _pdata) \
105 TYPED_LIST_ITERATE_REV(struct unit_move_data, _plist, _pdata)
106 #define unit_move_data_list_iterate_rev_end LIST_ITERATE_REV_END
108 /* We need this global variable for our sort algorithm */
109 static struct tile
*autoattack_target
;
111 static void unit_restore_hitpoints(struct unit
*punit
);
112 static void unit_restore_movepoints(struct player
*pplayer
, struct unit
*punit
);
113 static void update_unit_activity(struct unit
*punit
);
114 static bool try_to_save_unit(struct unit
*punit
, struct unit_type
*pttype
,
115 bool helpless
, bool teleporting
);
116 static void wakeup_neighbor_sentries(struct unit
*punit
);
117 static void do_upgrade_effects(struct player
*pplayer
);
119 static bool maybe_cancel_patrol_due_to_enemy(struct unit
*punit
);
120 static int hp_gain_coord(struct unit
*punit
);
122 static bool maybe_become_veteran_real(struct unit
*punit
, bool settler
);
124 static void unit_transport_load_tp_status(struct unit
*punit
,
128 static void wipe_unit_full(struct unit
*punit
, bool transported
,
129 enum unit_loss_reason reason
,
130 struct player
*killer
);
132 /**************************************************************************
133 Returns a unit type that matches the role_tech or role roles.
135 If role_tech is given, then we look at all units with this role
136 whose requirements are met by any player, and return a random one. This
137 can be used to give a unit to barbarians taken from the set of most
138 advanced units researched by the 'real' players.
140 If role_tech is not give (-1) or if there are no matching unit types,
141 then we look at 'role' value and return a random matching unit type.
143 It is an error if there are no available units. This function will
144 always return a valid unit.
145 **************************************************************************/
146 struct unit_type
*find_a_unit_type(enum unit_role_id role
,
147 enum unit_role_id role_tech
)
149 struct unit_type
*which
[U_LAST
];
152 if (role_tech
!= -1) {
153 for(i
=0; i
<num_role_units(role_tech
); i
++) {
154 struct unit_type
*iunit
= get_role_unit(role_tech
, i
);
155 const int minplayers
= 2;
158 /* Note, if there's only one player in the game this check will always
160 players_iterate(pplayer
) {
161 if (!is_barbarian(pplayer
)
162 && can_player_build_unit_direct(pplayer
, iunit
)) {
165 } players_iterate_end
;
166 if (players
> minplayers
) {
167 which
[num
++] = iunit
;
172 for(i
=0; i
<num_role_units(role
); i
++) {
173 which
[num
++] = get_role_unit(role
, i
);
177 /* Ruleset code should ensure there is at least one unit for each
178 * possibly-required role, or check before calling this function. */
179 fc_assert_exit_msg(0 < num
, "No unit types in find_a_unit_type(%d, %d)!",
182 return which
[fc_rand(num
)];
185 /*****************************************************************************
186 Unit has a chance to become veteran. This should not be used for settlers
187 for the work they do.
188 *****************************************************************************/
189 bool maybe_make_veteran(struct unit
*punit
)
191 return maybe_become_veteran_real(punit
, FALSE
);
194 /*****************************************************************************
195 After a battle, after diplomatic aggression and after surviving trireme
196 loss chance, this routine is called to decide whether or not the unit
197 should become more experienced.
199 There is a specified chance for it to happen, (+50% if player got SUNTZU)
200 the chances are specified in the units.ruleset file.
202 If 'settler' is TRUE the veteran level is increased due to work done by
204 *****************************************************************************/
205 static bool maybe_become_veteran_real(struct unit
*punit
, bool settler
)
207 const struct veteran_system
*vsystem
;
208 const struct veteran_level
*vlevel
;
211 fc_assert_ret_val(punit
!= NULL
, FALSE
);
213 vsystem
= utype_veteran_system(unit_type_get(punit
));
214 fc_assert_ret_val(vsystem
!= NULL
, FALSE
);
215 fc_assert_ret_val(vsystem
->levels
> punit
->veteran
, FALSE
);
217 vlevel
= utype_veteran_level(unit_type_get(punit
), punit
->veteran
);
218 fc_assert_ret_val(vlevel
!= NULL
, FALSE
);
220 if (punit
->veteran
+ 1 >= vsystem
->levels
221 || unit_has_type_flag(punit
, UTYF_NO_VETERAN
)) {
223 } else if (!settler
) {
224 int mod
= 100 + get_unit_bonus(punit
, EFT_VETERAN_COMBAT
);
226 /* The modification is tacked on as a multiplier to the base chance.
227 * For example with a base chance of 50% for green units and a modifier
228 * of +50% the end chance is 75%. */
229 chance
= vlevel
->raise_chance
* mod
/ 100;
230 } else if (settler
&& unit_has_type_flag(punit
, UTYF_SETTLERS
)) {
231 chance
= vlevel
->work_raise_chance
;
233 /* No battle and no work done. */
237 if (fc_rand(100) < chance
) {
245 /**************************************************************************
246 This is the basic unit versus unit combat routine.
247 1) ALOT of modifiers bonuses etc is added to the 2 units rates.
248 2) If the attack is a bombardment, do rate attacks and don't kill the
249 defender, then return.
250 3) the combat loop, which continues until one of the units are dead
251 4) the aftermath, the loser (and potentially the stack which is below it)
252 is wiped, and the winner gets a chance of gaining veteran status
253 **************************************************************************/
254 void unit_versus_unit(struct unit
*attacker
, struct unit
*defender
,
255 bool bombard
, int *att_hp
, int *def_hp
)
257 int attackpower
= get_total_attack_power(attacker
, defender
);
258 int defensepower
= get_total_defense_power(attacker
, defender
);
259 int attack_firepower
, defense_firepower
;
260 struct player
*plr1
= unit_owner(attacker
);
261 struct player
*plr2
= unit_owner(defender
);
263 *att_hp
= attacker
->hp
;
264 *def_hp
= defender
->hp
;
265 get_modified_firepower(attacker
, defender
,
266 &attack_firepower
, &defense_firepower
);
268 log_verbose("attack:%d, defense:%d, attack firepower:%d, "
269 "defense firepower:%d", attackpower
, defensepower
,
270 attack_firepower
, defense_firepower
);
272 plr1
->last_war_action
= game
.info
.turn
;
273 plr2
->last_war_action
= game
.info
.turn
;
277 int rate
= unit_type_get(attacker
)->bombard_rate
;
279 for (i
= 0; i
< rate
; i
++) {
280 if (fc_rand(attackpower
+defensepower
) >= defensepower
) {
281 *def_hp
-= attack_firepower
;
285 /* Don't kill the target. */
292 if (attackpower
== 0) {
294 } else if (defensepower
== 0) {
297 while (*att_hp
> 0 && *def_hp
> 0) {
298 if (fc_rand(attackpower
+ defensepower
) >= defensepower
) {
299 *def_hp
-= attack_firepower
;
301 *att_hp
-= defense_firepower
;
312 /***************************************************************************
313 Make maybe make either side of combat veteran
314 ****************************************************************************/
315 void combat_veterans(struct unit
*attacker
, struct unit
*defender
)
317 if (attacker
->hp
> 0) {
318 maybe_make_veteran(attacker
);
319 } else if (defender
->hp
> 0) {
320 maybe_make_veteran(defender
);
324 /***************************************************************************
325 Do unit auto-upgrades to players with the EFT_UNIT_UPGRADE effect
326 (traditionally from Leonardo's Workshop).
327 ****************************************************************************/
328 static void do_upgrade_effects(struct player
*pplayer
)
330 int upgrades
= get_player_bonus(pplayer
, EFT_UPGRADE_UNIT
);
331 struct unit_list
*candidates
;
336 candidates
= unit_list_new();
338 unit_list_iterate(pplayer
->units
, punit
) {
339 /* We have to be careful not to strand units at sea, for example by
340 * upgrading a frigate to an ironclad while it was carrying a unit. */
341 if (UU_OK
== unit_upgrade_test(punit
, TRUE
)) {
342 unit_list_prepend(candidates
, punit
); /* Potential candidate :) */
344 } unit_list_iterate_end
;
346 while (upgrades
> 0 && unit_list_size(candidates
) > 0) {
347 /* Upgrade one unit. The unit is chosen at random from the list of
348 * available candidates. */
349 int candidate_to_upgrade
= fc_rand(unit_list_size(candidates
));
350 struct unit
*punit
= unit_list_get(candidates
, candidate_to_upgrade
);
351 struct unit_type
*type_from
= unit_type_get(punit
);
352 struct unit_type
*type_to
= can_upgrade_unittype(pplayer
, type_from
);
354 transform_unit(punit
, type_to
, TRUE
);
355 notify_player(pplayer
, unit_tile(punit
), E_UNIT_UPGRADED
, ftc_server
,
356 _("%s was upgraded for free to %s."),
357 utype_name_translation(type_from
),
359 unit_list_remove(candidates
, punit
);
363 unit_list_destroy(candidates
);
366 /***************************************************************************
367 1. Do Leonardo's Workshop upgrade if applicable.
369 2. Restore/decrease unit hitpoints.
373 4. Rescue airplanes by returning them to base automatically.
375 5. Decrease fuel of planes in the air.
377 6. Refuel planes that are in bases.
379 7. Kill planes that are out of fuel.
380 ****************************************************************************/
381 void player_restore_units(struct player
*pplayer
)
383 /* 1) get Leonardo out of the way first: */
384 do_upgrade_effects(pplayer
);
386 unit_list_iterate_safe(pplayer
->units
, punit
) {
388 /* 2) Modify unit hitpoints. Helicopters can even lose them. */
389 unit_restore_hitpoints(punit
);
391 /* 3) Check that unit has hitpoints */
392 if (punit
->hp
<= 0) {
393 /* This should usually only happen for heli units, but if any other
394 * units get 0 hp somehow, catch them too. --dwp */
395 /* if 'game.server.killunhomed' is activated unhomed units are slowly
396 * killed; notify player here */
397 if (!punit
->homecity
&& 0 < game
.server
.killunhomed
) {
398 notify_player(pplayer
, unit_tile(punit
), E_UNIT_LOST_MISC
,
399 ftc_server
, _("Your %s has run out of hit points "
400 "because it was not supported by a city."),
401 unit_tile_link(punit
));
403 notify_player(pplayer
, unit_tile(punit
), E_UNIT_LOST_MISC
, ftc_server
,
404 _("Your %s has run out of hit points."),
405 unit_tile_link(punit
));
408 wipe_unit(punit
, ULR_HP_LOSS
, NULL
);
409 continue; /* Continue iterating... */
412 /* 4) Rescue planes if needed */
413 if (utype_fuel(unit_type_get(punit
))) {
414 /* Shall we emergency return home on the last vapors? */
416 /* I think this is strongly against the spirit of client goto.
417 * The problem is (again) that here we know too much. -- Zamar */
420 && !is_unit_being_refueled(punit
)) {
421 struct unit
*carrier
;
423 carrier
= transporter_for_unit(punit
);
425 unit_transport_load_tp_status(punit
, carrier
, FALSE
);
430 struct pf_parameter parameter
;
432 pft_fill_unit_parameter(¶meter
, punit
);
433 parameter
.omniscience
= !has_handicap(pplayer
, H_MAP
);
434 pfm
= pf_map_new(¶meter
);
436 pf_map_move_costs_iterate(pfm
, ptile
, move_cost
, TRUE
) {
437 if (move_cost
> punit
->moves_left
) {
442 if (is_airunit_refuel_point(ptile
, pplayer
, punit
)) {
443 struct pf_path
*path
;
446 /* Client orders may be running for this unit - if so
447 * we free them before engaging goto. */
448 free_unit_orders(punit
);
450 path
= pf_map_path(pfm
, ptile
);
452 alive
= adv_follow_path(punit
, path
, ptile
);
455 log_error("rescue plane: unit %d died enroute!", id
);
456 } else if (!same_pos(unit_tile(punit
), ptile
)) {
457 /* Enemy units probably blocked our route
458 * FIXME: We should try find alternative route around
459 * the enemy unit instead of just giving up and crashing. */
460 log_debug("rescue plane: unit %d could not move to "
461 "refuel point!", punit
->id
);
465 /* Clear activity. Unit info will be sent in the end of
467 unit_activity_handling(punit
, ACTIVITY_IDLE
);
468 adv_unit_new_task(punit
, AUT_NONE
, NULL
);
469 punit
->goto_tile
= NULL
;
471 if (!is_unit_being_refueled(punit
)) {
472 carrier
= transporter_for_unit(punit
);
474 unit_transport_load_tp_status(punit
, carrier
, FALSE
);
478 notify_player(pplayer
, unit_tile(punit
),
479 E_UNIT_ORDERS
, ftc_server
,
480 _("Your %s has returned to refuel."),
483 pf_path_destroy(path
);
486 } pf_map_move_costs_iterate_end
;
490 /* Unit died trying to move to refuel point. */
499 /* 6) Automatically refuel air units in cities, airbases, and
500 * transporters (carriers). */
501 if (is_unit_being_refueled(punit
)) {
502 punit
->fuel
= utype_fuel(unit_type_get(punit
));
505 } unit_list_iterate_safe_end
;
507 /* 7) Check if there are air units without fuel */
508 unit_list_iterate_safe(pplayer
->units
, punit
) {
509 if (punit
->fuel
<= 0 && utype_fuel(unit_type_get(punit
))) {
510 notify_player(pplayer
, unit_tile(punit
), E_UNIT_LOST_MISC
, ftc_server
,
511 _("Your %s has run out of fuel."),
512 unit_tile_link(punit
));
513 wipe_unit(punit
, ULR_FUEL
, NULL
);
515 } unit_list_iterate_safe_end
;
517 /* Send all updates. */
518 unit_list_iterate(pplayer
->units
, punit
) {
519 send_unit_info(NULL
, punit
);
520 } unit_list_iterate_end
;
523 /****************************************************************************
524 add hitpoints to the unit, hp_gain_coord returns the amount to add
525 united nations will speed up the process by 2 hp's / turn, means helicopters
526 will actually not lose hp's every turn if player have that wonder.
527 Units which have moved don't gain hp, except the United Nations and
528 helicopter effects still occur.
530 If 'game.server.killunhomed' is greater than 0, unhomed units lose
531 'game.server.killunhomed' hitpoints each turn, killing the unit at the end.
532 *****************************************************************************/
533 static void unit_restore_hitpoints(struct unit
*punit
)
537 struct unit_class
*pclass
= unit_class_get(punit
);
538 struct city
*pcity
= tile_city(unit_tile(punit
));
540 was_lower
= (punit
->hp
< unit_type_get(punit
)->hp
);
544 punit
->hp
+= hp_gain_coord(punit
);
547 /* Bonus recovery HP (traditionally from the United Nations) */
548 punit
->hp
+= get_unit_bonus(punit
, EFT_UNIT_RECOVER
);
550 if (!punit
->homecity
&& 0 < game
.server
.killunhomed
551 && !unit_has_type_flag(punit
, UTYF_GAMELOSS
)) {
552 /* Hit point loss of units without homecity; at least 1 hp! */
553 /* Gameloss units are immune to this effect. */
554 int hp_loss
= MAX(unit_type_get(punit
)->hp
* game
.server
.killunhomed
/ 100,
556 punit
->hp
= MIN(punit
->hp
- hp_loss
, save_hp
- 1);
559 if (!pcity
&& !tile_has_native_base(unit_tile(punit
), unit_type_get(punit
))
560 && !unit_transported(punit
)) {
561 punit
->hp
-= unit_type_get(punit
)->hp
* pclass
->hp_loss_pct
/ 100;
564 if (punit
->hp
>= unit_type_get(punit
)->hp
) {
565 punit
->hp
= unit_type_get(punit
)->hp
;
566 if (was_lower
&& punit
->activity
== ACTIVITY_SENTRY
) {
567 set_unit_activity(punit
, ACTIVITY_IDLE
);
575 punit
->moved
= FALSE
;
576 punit
->paradropped
= FALSE
;
579 /***************************************************************************
580 Move points are trivial, only modifiers to the base value is if it's
581 sea units and the player has certain wonders/techs. Then add veteran
583 ***************************************************************************/
584 static void unit_restore_movepoints(struct player
*pplayer
, struct unit
*punit
)
586 punit
->moves_left
= unit_move_rate(punit
);
587 punit
->done_moving
= FALSE
;
590 /****************************************************************************
591 Iterate through all units and update them.
592 ****************************************************************************/
593 void update_unit_activities(struct player
*pplayer
)
595 unit_list_iterate_safe(pplayer
->units
, punit
) {
596 update_unit_activity(punit
);
597 } unit_list_iterate_safe_end
;
600 /****************************************************************************
601 Iterate through all units and execute their orders.
602 ****************************************************************************/
603 void execute_unit_orders(struct player
*pplayer
)
605 unit_list_iterate_safe(pplayer
->units
, punit
) {
606 if (unit_has_orders(punit
)) {
607 execute_orders(punit
, FALSE
);
609 } unit_list_iterate_safe_end
;
612 /****************************************************************************
613 Iterate through all units and remember their current activities.
614 ****************************************************************************/
615 void finalize_unit_phase_beginning(struct player
*pplayer
)
617 /* Remember activities only after all knock-on effects of unit activities
618 * on other units have been resolved */
619 unit_list_iterate(pplayer
->units
, punit
) {
620 punit
->changed_from
= punit
->activity
;
621 punit
->changed_from_target
= punit
->activity_target
;
622 punit
->changed_from_count
= punit
->activity_count
;
623 send_unit_info(NULL
, punit
);
624 } unit_list_iterate_end
;
627 /**************************************************************************
628 returns how many hp's a unit will gain on this square
629 depends on whether or not it's inside city or fortress.
630 barracks will regen landunits completely
631 airports will regen airunits completely
632 ports will regen navalunits completely
633 fortify will add a little extra.
634 ***************************************************************************/
635 static int hp_gain_coord(struct unit
*punit
)
638 const int base
= unit_type_get(punit
)->hp
;
640 /* Includes barracks (100%), fortress (25%), etc. */
641 hp
+= base
* get_unit_bonus(punit
, EFT_HP_REGEN
) / 100;
643 if (tile_city(unit_tile(punit
))) {
644 hp
= MAX(hp
, base
/ 3);
647 if (!unit_class_get(punit
)->hp_loss_pct
) {
648 hp
+= (base
+ 9) / 10;
651 if (punit
->activity
== ACTIVITY_FORTIFIED
) {
652 hp
+= (base
+ 9) / 10;
658 /**************************************************************************
659 Calculate the total amount of activity performed by all units on a tile
660 for a given task and target.
661 **************************************************************************/
662 static int total_activity(struct tile
*ptile
, enum unit_activity act
,
663 struct extra_type
*tgt
)
666 bool tgt_matters
= activity_requires_target(act
);
668 unit_list_iterate (ptile
->units
, punit
) {
669 if (punit
->activity
== act
670 && (!tgt_matters
|| punit
->activity_target
== tgt
)) {
671 total
+= punit
->activity_count
;
673 } unit_list_iterate_end
;
678 /**************************************************************************
679 Check the total amount of activity performed by all units on a tile
681 **************************************************************************/
682 static bool total_activity_done(struct tile
*ptile
, enum unit_activity act
,
683 struct extra_type
*tgt
)
685 return total_activity(ptile
, act
, tgt
) >= tile_activity_time(act
, ptile
, tgt
);
688 /**************************************************************************
689 Common notification for all experience levels.
690 **************************************************************************/
691 void notify_unit_experience(struct unit
*punit
)
693 const struct veteran_system
*vsystem
;
694 const struct veteran_level
*vlevel
;
700 vsystem
= utype_veteran_system(unit_type_get(punit
));
701 fc_assert_ret(vsystem
!= NULL
);
702 fc_assert_ret(vsystem
->levels
> punit
->veteran
);
704 vlevel
= utype_veteran_level(unit_type_get(punit
), punit
->veteran
);
705 fc_assert_ret(vlevel
!= NULL
);
707 notify_player(unit_owner(punit
), unit_tile(punit
),
708 E_UNIT_BECAME_VET
, ftc_server
,
709 /* TRANS: Your <unit> became ... rank of <veteran level>. */
710 _("Your %s became more experienced and achieved the rank "
712 unit_link(punit
), name_translation_get(&vlevel
->name
));
715 /**************************************************************************
716 Convert a single unit to another type.
717 **************************************************************************/
718 static void unit_convert(struct unit
*punit
)
720 struct unit_type
*to_type
, *from_type
;
722 from_type
= unit_type_get(punit
);
723 to_type
= from_type
->converted_to
;
725 if (unit_can_convert(punit
)) {
726 transform_unit(punit
, to_type
, TRUE
);
727 notify_player(unit_owner(punit
), unit_tile(punit
),
728 E_UNIT_UPGRADED
, ftc_server
,
729 _("%s converted to %s."),
730 utype_name_translation(from_type
),
731 utype_name_translation(to_type
));
733 notify_player(unit_owner(punit
), unit_tile(punit
),
734 E_UNIT_UPGRADED
, ftc_server
,
735 _("%s cannot be converted."),
736 utype_name_translation(from_type
));
740 /**************************************************************************
741 progress settlers in their current tasks,
742 and units that is pillaging.
743 also move units that is on a goto.
744 restore unit move points (information needed for settler tasks)
745 **************************************************************************/
746 static void update_unit_activity(struct unit
*punit
)
748 const enum unit_activity tile_changing_actions
[] =
749 { ACTIVITY_PILLAGE
, ACTIVITY_GEN_ROAD
, ACTIVITY_IRRIGATE
, ACTIVITY_MINE
,
750 ACTIVITY_BASE
, ACTIVITY_TRANSFORM
, ACTIVITY_POLLUTION
,
751 ACTIVITY_FALLOUT
, ACTIVITY_LAST
};
753 struct player
*pplayer
= unit_owner(punit
);
754 bool unit_activity_done
= FALSE
;
755 enum unit_activity activity
= punit
->activity
;
756 struct tile
*ptile
= unit_tile(punit
);
761 case ACTIVITY_EXPLORE
:
762 case ACTIVITY_FORTIFIED
:
763 case ACTIVITY_SENTRY
:
765 case ACTIVITY_PATROL_UNUSED
:
766 case ACTIVITY_UNKNOWN
:
768 /* We don't need the activity_count for the above */
771 case ACTIVITY_FORTIFYING
:
772 case ACTIVITY_CONVERT
:
773 punit
->activity_count
+= get_activity_rate_this_turn(punit
);
776 case ACTIVITY_POLLUTION
:
778 case ACTIVITY_IRRIGATE
:
779 case ACTIVITY_PILLAGE
:
780 case ACTIVITY_TRANSFORM
:
781 case ACTIVITY_FALLOUT
:
783 case ACTIVITY_GEN_ROAD
:
784 punit
->activity_count
+= get_activity_rate_this_turn(punit
);
786 /* settler may become veteran when doing something useful */
787 if (maybe_become_veteran_real(punit
, TRUE
)) {
788 notify_unit_experience(punit
);
791 case ACTIVITY_OLD_ROAD
:
792 case ACTIVITY_OLD_RAILROAD
:
793 case ACTIVITY_FORTRESS
:
794 case ACTIVITY_AIRBASE
:
799 unit_restore_movepoints(pplayer
, punit
);
803 case ACTIVITY_FORTIFIED
:
804 case ACTIVITY_SENTRY
:
806 case ACTIVITY_UNKNOWN
:
807 case ACTIVITY_FORTIFYING
:
808 case ACTIVITY_CONVERT
:
809 case ACTIVITY_PATROL_UNUSED
:
811 /* no default, ensure all handled */
814 case ACTIVITY_EXPLORE
:
818 case ACTIVITY_PILLAGE
:
819 if (total_activity_done(ptile
, ACTIVITY_PILLAGE
,
820 punit
->activity_target
)) {
821 struct player
*victim
= tile_owner(ptile
); /* Owner before fortress gets destroyed */
823 destroy_extra(ptile
, punit
->activity_target
);
824 unit_activity_done
= TRUE
;
826 bounce_units_on_terrain_change(ptile
);
828 call_incident(INCIDENT_PILLAGE
, unit_owner(punit
), victim
);
830 /* Change vision if effects have changed. */
831 unit_list_refresh_vision(ptile
->units
);
835 case ACTIVITY_POLLUTION
:
836 /* TODO: Remove this fallback target setting when target always correctly
838 if (punit
->activity_target
== NULL
) {
839 punit
->activity_target
= prev_extra_in_tile(ptile
, ERM_CLEANPOLLUTION
,
842 if (total_activity_done(ptile
, ACTIVITY_POLLUTION
, punit
->activity_target
)) {
843 destroy_extra(ptile
, punit
->activity_target
);
844 unit_activity_done
= TRUE
;
848 case ACTIVITY_FALLOUT
:
849 /* TODO: Remove this fallback target setting when target always correctly
851 if (punit
->activity_target
== NULL
) {
852 punit
->activity_target
= prev_extra_in_tile(ptile
, ERM_CLEANFALLOUT
,
855 if (total_activity_done(ptile
, ACTIVITY_FALLOUT
, punit
->activity_target
)) {
856 destroy_extra(ptile
, punit
->activity_target
);
857 unit_activity_done
= TRUE
;
863 if (total_activity(ptile
, ACTIVITY_BASE
, punit
->activity_target
)
864 >= tile_activity_time(ACTIVITY_BASE
, ptile
, punit
->activity_target
)) {
865 create_extra(ptile
, punit
->activity_target
, unit_owner(punit
));
866 unit_activity_done
= TRUE
;
871 case ACTIVITY_GEN_ROAD
:
873 if (total_activity(ptile
, ACTIVITY_GEN_ROAD
, punit
->activity_target
)
874 >= tile_activity_time(ACTIVITY_GEN_ROAD
, ptile
, punit
->activity_target
)) {
875 create_extra(ptile
, punit
->activity_target
, unit_owner(punit
));
876 unit_activity_done
= TRUE
;
881 case ACTIVITY_IRRIGATE
:
883 case ACTIVITY_TRANSFORM
:
884 if (total_activity_done(ptile
, activity
, punit
->activity_target
)) {
885 struct terrain
*old
= tile_terrain(ptile
);
887 /* The function below could change the terrain. Therefore, we have to
888 * check the terrain (which will also do a sanity check for the tile). */
889 tile_apply_activity(ptile
, activity
, punit
->activity_target
);
890 check_terrain_change(ptile
, old
);
891 unit_activity_done
= TRUE
;
895 case ACTIVITY_OLD_ROAD
:
896 case ACTIVITY_OLD_RAILROAD
:
897 case ACTIVITY_FORTRESS
:
898 case ACTIVITY_AIRBASE
:
903 if (unit_activity_done
) {
904 update_tile_knowledge(ptile
);
905 if (ACTIVITY_IRRIGATE
== activity
906 || ACTIVITY_MINE
== activity
907 || ACTIVITY_TRANSFORM
== activity
) {
908 /* FIXME: As we might probably do the activity again, because of the
909 * terrain change cycles, we need to treat these cases separatly.
910 * Probably ACTIVITY_TRANSFORM should be associated to its terrain
911 * target, whereas ACTIVITY_IRRIGATE and ACTIVITY_MINE should only
912 * used for extras. */
913 unit_list_iterate(ptile
->units
, punit2
) {
914 if (punit2
->activity
== activity
) {
915 set_unit_activity(punit2
, ACTIVITY_IDLE
);
916 send_unit_info(NULL
, punit2
);
918 } unit_list_iterate_end
;
920 unit_list_iterate(ptile
->units
, punit2
) {
921 if (!can_unit_continue_current_activity(punit2
)) {
922 set_unit_activity(punit2
, ACTIVITY_IDLE
);
923 send_unit_info(NULL
, punit2
);
925 } unit_list_iterate_end
;
928 for (i
= 0; tile_changing_actions
[i
] != ACTIVITY_LAST
; i
++) {
929 if (tile_changing_actions
[i
] == activity
) {
930 /* Some units nearby may not be able to continue their action,
931 * such as building irrigation if we removed the only source
932 * of water from them. */
933 adjc_iterate(ptile
, ptile2
) {
934 unit_list_iterate(ptile2
->units
, punit2
) {
935 if (!can_unit_continue_current_activity(punit2
)) {
936 if (unit_has_orders(punit2
)) {
937 notify_player(unit_owner(punit2
), unit_tile(punit2
),
938 E_UNIT_ORDERS
, ftc_server
,
939 _("Orders for %s aborted because activity "
940 "is no longer available."),
942 free_unit_orders(punit2
);
944 set_unit_activity(punit2
, ACTIVITY_IDLE
);
945 send_unit_info(NULL
, punit2
);
947 } unit_list_iterate_end
;
954 if (activity
== ACTIVITY_FORTIFYING
) {
955 if (punit
->activity_count
>= 1) {
956 set_unit_activity(punit
, ACTIVITY_FORTIFIED
);
960 if (activity
== ACTIVITY_CONVERT
) {
961 if (punit
->activity_count
>= unit_type_get(punit
)->convert_time
* ACTIVITY_FACTOR
) {
963 set_unit_activity(punit
, ACTIVITY_IDLE
);
968 /**************************************************************************
969 Forget the unit's last activity so that it can't be resumed. This is
970 used for example when the unit moves or attacks.
971 **************************************************************************/
972 void unit_forget_last_activity(struct unit
*punit
)
974 punit
->changed_from
= ACTIVITY_IDLE
;
977 /**************************************************************************
978 Return TRUE iff activity requires some sort of target to be specified by
980 **************************************************************************/
981 bool unit_activity_needs_target_from_client(enum unit_activity activity
)
984 case ACTIVITY_PILLAGE
:
985 /* Can be set server side. */
988 return activity_requires_target(activity
);
992 /**************************************************************************
993 For some activities (currently only pillaging), the precise target can
994 be assigned by the server rather than explicitly requested by the client.
995 This function assigns a specific activity+target if the current
996 settings are open-ended (otherwise leaves them unchanged).
998 Please update unit_activity_needs_target_from_client() if you add server
999 side unit activity target setting to more activities.
1000 **************************************************************************/
1001 void unit_assign_specific_activity_target(struct unit
*punit
,
1002 enum unit_activity
*activity
,
1003 struct extra_type
**target
)
1005 if (*activity
== ACTIVITY_PILLAGE
1006 && *target
== NULL
) {
1007 struct tile
*ptile
= unit_tile(punit
);
1008 struct extra_type
*tgt
;
1010 bv_extras extras
= *tile_extras(ptile
);
1012 while ((tgt
= get_preferred_pillage(extras
))) {
1014 BV_CLR(extras
, extra_index(tgt
));
1016 if (can_unit_do_activity_targeted(punit
, *activity
, tgt
)) {
1021 /* Nothing we can pillage here. */
1022 *activity
= ACTIVITY_IDLE
;
1026 /**************************************************************************
1027 Find place to place partisans. Returns whether such spot was found, and
1028 if it has been found, dst_tile contains that tile.
1029 **************************************************************************/
1030 static bool find_a_good_partisan_spot(struct tile
*pcenter
,
1031 struct player
*powner
,
1032 struct unit_type
*u_type
,
1034 struct tile
**dst_tile
)
1038 /* coords of best tile in arg pointers */
1039 circle_iterate(pcenter
, sq_radius
, ptile
) {
1042 if (!is_native_tile(u_type
, ptile
)) {
1046 if (NULL
!= tile_city(ptile
)) {
1050 if (0 < unit_list_size(ptile
->units
)) {
1054 /* City may not have changed hands yet; see place_partisans(). */
1055 value
= get_virtual_defense_power(NULL
, u_type
, powner
,
1059 if (tile_continent(ptile
) != tile_continent(pcenter
)) {
1063 value
-= fc_rand(value
/3);
1065 if (value
> bestvalue
) {
1069 } circle_iterate_end
;
1071 return bestvalue
> 0;
1074 /**************************************************************************
1075 Place partisans for powner around pcenter (normally around a city).
1076 **************************************************************************/
1077 void place_partisans(struct tile
*pcenter
, struct player
*powner
,
1078 int count
, int sq_radius
)
1080 struct tile
*ptile
= NULL
;
1081 struct unit_type
*u_type
= get_role_unit(L_PARTISAN
, 0);
1084 && find_a_good_partisan_spot(pcenter
, powner
, u_type
,
1085 sq_radius
, &ptile
)) {
1088 punit
= create_unit(powner
, ptile
, u_type
, 0, 0, -1);
1089 if (can_unit_do_activity(punit
, ACTIVITY_FORTIFYING
)) {
1090 punit
->activity
= ACTIVITY_FORTIFIED
; /* yes; directly fortified */
1091 send_unit_info(NULL
, punit
);
1096 /**************************************************************************
1097 Teleport punit to city at cost specified. Returns success. Note that unit
1098 may die if it succesfully moves, i.e., even when return value is TRUE.
1099 (If specified cost is -1, then teleportation costs all movement.)
1100 **************************************************************************/
1101 bool teleport_unit_to_city(struct unit
*punit
, struct city
*pcity
,
1102 int move_cost
, bool verbose
)
1104 struct tile
*src_tile
= unit_tile(punit
), *dst_tile
= pcity
->tile
;
1106 if (city_owner(pcity
) == unit_owner(punit
)){
1107 log_verbose("Teleported %s %s from (%d,%d) to %s",
1108 nation_rule_name(nation_of_unit(punit
)),
1109 unit_rule_name(punit
), TILE_XY(src_tile
), city_name_get(pcity
));
1111 notify_player(unit_owner(punit
), city_tile(pcity
),
1112 E_UNIT_RELOCATED
, ftc_server
,
1113 _("Teleported your %s to %s."),
1118 /* Silently free orders since they won't be applicable anymore. */
1119 free_unit_orders(punit
);
1121 if (move_cost
== -1) {
1122 move_cost
= punit
->moves_left
;
1124 unit_move(punit
, dst_tile
, move_cost
, NULL
);
1131 /**************************************************************************
1132 Move or remove a unit due to stack conflicts. This function will try to
1133 find a random safe tile within a two tile distance of the unit's current
1134 tile and move the unit there. If no tiles are found, the unit is
1135 disbanded. If 'verbose' is TRUE, a message is sent to the unit owner
1136 regarding what happened.
1137 **************************************************************************/
1138 void bounce_unit(struct unit
*punit
, bool verbose
)
1140 struct player
*pplayer
;
1141 struct tile
*punit_tile
;
1142 struct unit_list
*pcargo_units
;
1145 /* I assume that there are no topologies that have more than
1146 * (2d + 1)^2 tiles in the "square" of "radius" d. */
1148 struct tile
*tiles
[(2 * DIST
+ 1) * (2 * DIST
+ 1)];
1154 pplayer
= unit_owner(punit
);
1155 punit_tile
= unit_tile(punit
);
1157 square_iterate(punit_tile
, DIST
, ptile
) {
1158 if (count
>= ARRAY_SIZE(tiles
)) {
1162 if (ptile
== punit_tile
) {
1166 if (can_unit_survive_at_tile(punit
, ptile
)
1167 && !is_non_allied_city_tile(ptile
, pplayer
)
1168 && !is_non_allied_unit_tile(ptile
, pplayer
)) {
1169 tiles
[count
++] = ptile
;
1171 } square_iterate_end
;
1174 struct tile
*ptile
= tiles
[fc_rand(count
)];
1177 notify_player(pplayer
, ptile
, E_UNIT_RELOCATED
, ftc_server
,
1178 /* TRANS: A unit is moved to resolve stack conflicts. */
1179 _("Moved your %s."),
1182 unit_move(punit
, ptile
, 0, NULL
);
1186 /* Didn't find a place to bounce the unit, going to disband it.
1187 * Try to bounce transported units. */
1188 if (0 < get_transporter_occupancy(punit
)) {
1189 pcargo_units
= unit_transport_cargo(punit
);
1190 unit_list_iterate(pcargo_units
, pcargo
) {
1191 bounce_unit(pcargo
, verbose
);
1192 } unit_list_iterate_end
;
1196 notify_player(pplayer
, punit_tile
, E_UNIT_LOST_MISC
, ftc_server
,
1197 /* TRANS: A unit is disbanded to resolve stack conflicts. */
1198 _("Disbanded your %s."),
1199 unit_tile_link(punit
));
1201 wipe_unit(punit
, ULR_STACK_CONFLICT
, NULL
);
1205 /**************************************************************************
1206 Throw pplayer's units from non allied cities
1208 If verbose is true, pplayer gets messages about where each units goes.
1209 **************************************************************************/
1210 static void throw_units_from_illegal_cities(struct player
*pplayer
,
1215 struct unit
*ptrans
;
1216 struct unit_list
*pcargo_units
;
1218 /* Unload undesired units from transports, if possible. */
1219 unit_list_iterate(pplayer
->units
, punit
) {
1220 ptile
= unit_tile(punit
);
1221 pcity
= tile_city(ptile
);
1223 && !pplayers_allied(city_owner(pcity
), pplayer
)
1224 && 0 < get_transporter_occupancy(punit
)) {
1225 pcargo_units
= unit_transport_cargo(punit
);
1226 unit_list_iterate(pcargo_units
, pcargo
) {
1227 if (!pplayers_allied(unit_owner(pcargo
), pplayer
)) {
1228 if (can_unit_exist_at_tile(pcargo
, ptile
)) {
1229 unit_transport_unload_send(pcargo
);
1232 } unit_list_iterate_end
;
1234 } unit_list_iterate_end
;
1236 /* Bounce units except transported ones which will be bounced with their
1238 unit_list_iterate_safe(pplayer
->units
, punit
) {
1239 ptile
= unit_tile(punit
);
1240 pcity
= tile_city(ptile
);
1242 && !pplayers_allied(city_owner(pcity
), pplayer
)) {
1243 ptrans
= unit_transport_get(punit
);
1244 if (NULL
== ptrans
|| pplayer
!= unit_owner(ptrans
)) {
1245 bounce_unit(punit
, verbose
);
1248 } unit_list_iterate_safe_end
;
1250 #ifdef FREECIV_DEBUG
1252 unit_list_iterate(pplayer
->units
, punit
) {
1253 ptile
= unit_tile(punit
);
1254 pcity
= tile_city(ptile
);
1255 fc_assert_msg(NULL
== pcity
1256 || pplayers_allied(city_owner(pcity
), pplayer
),
1257 "Failed to throw %s %d from %s %d (%d, %d)",
1258 unit_rule_name(punit
),
1260 city_name_get(pcity
),
1263 } unit_list_iterate_end
;
1264 #endif /* FREECIV_DEBUG */
1267 /**************************************************************************
1268 For each pplayer's unit, check if we stack illegally, if so,
1269 bounce both players' units. If on ocean tile, bounce everyone but ships
1270 to avoid drowning. This function assumes that cities are clean.
1272 If verbose is true, the unit owner gets messages about where each
1274 **************************************************************************/
1275 static void resolve_stack_conflicts(struct player
*pplayer
,
1276 struct player
*aplayer
, bool verbose
)
1278 unit_list_iterate_safe(pplayer
->units
, punit
) {
1279 struct tile
*ptile
= unit_tile(punit
);
1281 if (is_non_allied_unit_tile(ptile
, pplayer
)) {
1282 unit_list_iterate_safe(ptile
->units
, aunit
) {
1283 if (unit_owner(aunit
) == pplayer
1284 || unit_owner(aunit
) == aplayer
1285 || !can_unit_survive_at_tile(aunit
, ptile
)) {
1286 bounce_unit(aunit
, verbose
);
1288 } unit_list_iterate_safe_end
;
1290 } unit_list_iterate_safe_end
;
1293 /**************************************************************************
1294 When in civil war or an alliance breaks there will potentially be units
1295 from both sides coexisting on the same squares. This routine resolves
1296 this by first bouncing off non-allied units from their cities, then by
1297 bouncing both players' units in now illegal multiowner stacks. To avoid
1298 drowning due to removal of transports, we bounce everyone (including
1299 third parties' units) from ocean tiles.
1301 If verbose is true, the unit owner gets messages about where each
1303 **************************************************************************/
1304 void resolve_unit_stacks(struct player
*pplayer
, struct player
*aplayer
,
1307 throw_units_from_illegal_cities(pplayer
, verbose
);
1308 throw_units_from_illegal_cities(aplayer
, verbose
);
1310 resolve_stack_conflicts(pplayer
, aplayer
, verbose
);
1311 resolve_stack_conflicts(aplayer
, pplayer
, verbose
);
1314 /****************************************************************************
1315 Returns the list of the units seen by 'pplayer' potentially seen only
1316 thanks to an alliance with 'aplayer'. The returned pointer is newly
1317 allocated and should be freed by the caller, using unit_list_destroy().
1318 ****************************************************************************/
1319 struct unit_list
*get_units_seen_via_ally(const struct player
*pplayer
,
1320 const struct player
*aplayer
)
1322 struct unit_list
*seen_units
= unit_list_new();
1324 /* Anybody's units inside ally's cities */
1325 city_list_iterate(aplayer
->cities
, pcity
) {
1326 unit_list_iterate(city_tile(pcity
)->units
, punit
) {
1327 if (can_player_see_unit(pplayer
, punit
)) {
1328 unit_list_append(seen_units
, punit
);
1330 } unit_list_iterate_end
;
1331 } city_list_iterate_end
;
1333 /* Ally's own units inside transports */
1334 unit_list_iterate(aplayer
->units
, punit
) {
1335 if (unit_transported(punit
) && can_player_see_unit(pplayer
, punit
)) {
1336 unit_list_append(seen_units
, punit
);
1338 } unit_list_iterate_end
;
1340 /* Make sure the same unit is not added in multiple phases
1341 * (unit within transport in a city) */
1342 unit_list_unique(seen_units
);
1347 /****************************************************************************
1348 When two players cancel an alliance, a lot of units that were visible may
1349 no longer be visible (this includes units in transporters and cities).
1350 Call this function to inform the clients that these units are no longer
1351 visible. Pass the list of seen units returned by get_units_seen_via_ally()
1352 before alliance was broken up.
1353 ****************************************************************************/
1354 void remove_allied_visibility(struct player
*pplayer
, struct player
*aplayer
,
1355 const struct unit_list
*seen_units
)
1357 unit_list_iterate(seen_units
, punit
) {
1358 /* We need to hide units previously seen by the client. */
1359 if (!can_player_see_unit(pplayer
, punit
)) {
1360 unit_goes_out_of_sight(pplayer
, punit
);
1362 } unit_list_iterate_end
;
1364 city_list_iterate(aplayer
->cities
, pcity
) {
1365 /* The player used to know what units were in these cities. Now that he
1366 * doesn't, he needs to get a new short city packet updating the
1367 * occupied status. */
1368 if (map_is_known_and_seen(pcity
->tile
, pplayer
, V_MAIN
)) {
1369 send_city_info(pplayer
, pcity
);
1371 } city_list_iterate_end
;
1374 /****************************************************************************
1375 Refresh units visibility of 'aplayer' for 'pplayer' after alliance have
1377 ****************************************************************************/
1378 void give_allied_visibility(struct player
*pplayer
,
1379 struct player
*aplayer
)
1381 unit_list_iterate(aplayer
->units
, punit
) {
1382 if (can_player_see_unit(pplayer
, punit
)) {
1383 send_unit_info(pplayer
->connections
, punit
);
1385 } unit_list_iterate_end
;
1388 /**************************************************************************
1389 Is unit being refueled in its current position
1390 **************************************************************************/
1391 bool is_unit_being_refueled(const struct unit
*punit
)
1393 return (unit_transported(punit
) /* Carrier */
1394 || tile_city(unit_tile(punit
)) /* City */
1395 || tile_has_refuel_extra(unit_tile(punit
),
1396 unit_type_get(punit
))); /* Airbase */
1399 /**************************************************************************
1400 Can unit refuel on tile. Considers also carrier capacity on tile.
1401 **************************************************************************/
1402 bool is_airunit_refuel_point(const struct tile
*ptile
,
1403 const struct player
*pplayer
,
1404 const struct unit
*punit
)
1406 const struct unit_class
*pclass
;
1408 if (NULL
!= is_non_allied_unit_tile(ptile
, pplayer
)) {
1412 if (NULL
!= is_allied_city_tile(ptile
, pplayer
)) {
1416 pclass
= unit_class_get(punit
);
1417 if (NULL
!= pclass
->cache
.refuel_bases
) {
1418 const struct player_tile
*plrtile
= map_get_player_tile(ptile
, pplayer
);
1420 extra_type_list_iterate(pclass
->cache
.refuel_bases
, pextra
) {
1421 if (BV_ISSET(plrtile
->extras
, extra_index(pextra
))) {
1424 } extra_type_list_iterate_end
;
1427 return unit_could_load_at(punit
, ptile
);
1430 /**************************************************************************
1431 Really transforms a single unit to another type.
1433 This function performs no checks. You should perform the appropriate
1434 test first to check that the transformation is legal (test_unit_upgrade()
1435 or test_unit_convert()).
1437 is_free: Does unit owner need to pay upgrade price.
1439 Note that this function is strongly tied to unit.c:test_unit_upgrade().
1440 **************************************************************************/
1441 void transform_unit(struct unit
*punit
, struct unit_type
*to_unit
,
1444 struct player
*pplayer
= unit_owner(punit
);
1445 struct unit_type
*old_type
= punit
->utype
;
1446 int old_mr
= unit_move_rate(punit
);
1447 int old_hp
= unit_type_get(punit
)->hp
;
1450 pplayer
->economic
.gold
-=
1451 unit_upgrade_price(pplayer
, unit_type_get(punit
), to_unit
);
1454 punit
->utype
= to_unit
;
1456 /* New type may not have the same veteran system, and we may want to
1457 * knock some levels off. */
1458 punit
->veteran
= MIN(punit
->veteran
,
1459 utype_veteran_system(to_unit
)->levels
- 1);
1461 punit
->veteran
= MAX(punit
->veteran
1462 - game
.server
.autoupgrade_veteran_loss
, 0);
1464 punit
->veteran
= MAX(punit
->veteran
1465 - game
.server
.upgrade_veteran_loss
, 0);
1468 /* Scale HP and MP, rounding down. Be careful with integer arithmetic,
1469 * and don't kill the unit. unit_move_rate is used to take into account
1470 * global effects like Magellan's Expedition. */
1471 punit
->hp
= MAX(punit
->hp
* unit_type_get(punit
)->hp
/ old_hp
, 1);
1472 punit
->moves_left
= punit
->moves_left
* unit_move_rate(punit
) / old_mr
;
1474 unit_forget_last_activity(punit
);
1476 /* update unit upkeep */
1477 city_units_upkeep(game_city_by_number(punit
->homecity
));
1479 conn_list_do_buffer(pplayer
->connections
);
1481 unit_refresh_vision(punit
);
1483 CALL_PLR_AI_FUNC(unit_transformed
, pplayer
, punit
, old_type
);
1485 send_unit_info(NULL
, punit
);
1486 conn_list_do_unbuffer(pplayer
->connections
);
1489 /*************************************************************************
1490 Wrapper of the below
1491 *************************************************************************/
1492 struct unit
*create_unit(struct player
*pplayer
, struct tile
*ptile
,
1493 struct unit_type
*type
, int veteran_level
,
1494 int homecity_id
, int moves_left
)
1496 return create_unit_full(pplayer
, ptile
, type
, veteran_level
, homecity_id
,
1497 moves_left
, -1, NULL
);
1500 /**************************************************************************
1501 Creates a unit, and set it's initial values, and put it into the right
1503 If moves_left is less than zero, unit will get max moves.
1504 **************************************************************************/
1505 struct unit
*create_unit_full(struct player
*pplayer
, struct tile
*ptile
,
1506 struct unit_type
*type
, int veteran_level
,
1507 int homecity_id
, int moves_left
, int hp_left
,
1508 struct unit
*ptrans
)
1510 struct unit
*punit
= unit_virtual_create(pplayer
, NULL
, type
, veteran_level
);
1514 punit
->id
= identity_number();
1515 idex_register_unit(punit
);
1517 fc_assert_ret_val(ptile
!= NULL
, NULL
);
1518 unit_tile_set(punit
, ptile
);
1520 pcity
= game_city_by_number(homecity_id
);
1521 if (utype_has_flag(type
, UTYF_NOHOME
)) {
1522 punit
->homecity
= 0; /* none */
1524 punit
->homecity
= homecity_id
;
1528 /* Override default full HP */
1529 punit
->hp
= hp_left
;
1532 if (moves_left
>= 0) {
1533 /* Override default full MP */
1534 punit
->moves_left
= MIN(moves_left
, unit_move_rate(punit
));
1538 /* Set transporter for unit. */
1539 unit_transport_load_tp_status(punit
, ptrans
, FALSE
);
1541 fc_assert_ret_val(!ptile
|| can_unit_exist_at_tile(punit
, ptile
), NULL
);
1544 /* Assume that if moves_left < 0 then the unit is "fresh",
1545 * and not moved; else the unit has had something happen
1546 * to it (eg, bribed) which we treat as equivalent to moved.
1547 * (Otherwise could pass moved arg too...) --dwp */
1548 punit
->moved
= (moves_left
>= 0);
1550 unit_list_prepend(pplayer
->units
, punit
);
1551 unit_list_prepend(ptile
->units
, punit
);
1552 if (pcity
&& !utype_has_flag(type
, UTYF_NOHOME
)) {
1553 fc_assert(city_owner(pcity
) == pplayer
);
1554 unit_list_prepend(pcity
->units_supported
, punit
);
1555 /* Refresh the unit's homecity. */
1556 city_refresh(pcity
);
1557 send_city_info(pplayer
, pcity
);
1560 punit
->server
.vision
= vision_new(pplayer
, ptile
);
1561 unit_refresh_vision(punit
);
1563 send_unit_info(NULL
, punit
);
1564 maybe_make_contact(ptile
, unit_owner(punit
));
1565 wakeup_neighbor_sentries(punit
);
1567 /* update unit upkeep */
1568 city_units_upkeep(game_city_by_number(homecity_id
));
1570 /* The unit may have changed the available tiles in nearby cities. */
1571 city_map_update_tile_now(ptile
);
1574 CALL_PLR_AI_FUNC(unit_got
, pplayer
, punit
);
1579 /****************************************************************************
1580 We remove the unit and see if it's disappearance has affected the homecity
1581 and the city it was in.
1582 ****************************************************************************/
1583 static void server_remove_unit_full(struct unit
*punit
, bool transported
,
1584 enum unit_loss_reason reason
)
1586 struct packet_unit_remove packet
;
1587 struct tile
*ptile
= unit_tile(punit
);
1588 struct city
*pcity
= tile_city(ptile
);
1589 struct city
*phomecity
= game_city_by_number(punit
->homecity
);
1590 struct unit
*ptrans
;
1591 struct player
*pplayer
= unit_owner(punit
);
1593 /* The unit is doomed. */
1594 punit
->server
.dying
= TRUE
;
1597 unit_list_iterate(ptile
->units
, pcargo
) {
1598 fc_assert(unit_transport_get(pcargo
) != punit
);
1599 } unit_list_iterate_end
;
1602 CALL_PLR_AI_FUNC(unit_lost
, pplayer
, punit
);
1604 /* Save transporter for updating below. */
1605 ptrans
= unit_transport_get(punit
);
1607 unit_transport_unload(punit
);
1609 /* Since settlers plot in new cities in the minimap before they
1610 are built, so that no two settlers head towards the same city
1611 spot, we need to ensure this reservation is cleared should
1612 the settler disappear on the way. */
1613 adv_unit_new_task(punit
, AUT_NONE
, NULL
);
1615 /* Clear the vision before sending unit remove. Else, we might duplicate
1616 * the PACKET_UNIT_REMOVE if we lose vision of the unit tile. */
1617 vision_clear_sight(punit
->server
.vision
);
1618 vision_free(punit
->server
.vision
);
1619 punit
->server
.vision
= NULL
;
1621 packet
.unit_id
= punit
->id
;
1622 /* Send to onlookers. */
1623 players_iterate(aplayer
) {
1624 if (can_player_see_unit_at(aplayer
, punit
, unit_tile(punit
),
1626 lsend_packet_unit_remove(aplayer
->connections
, &packet
);
1628 } players_iterate_end
;
1629 /* Send to global observers. */
1630 conn_list_iterate(game
.est_connections
, pconn
) {
1631 if (conn_is_global_observer(pconn
)) {
1632 send_packet_unit_remove(pconn
, &packet
);
1634 } conn_list_iterate_end
;
1636 if (punit
->server
.moving
!= NULL
) {
1637 /* Do not care of this unit for running moves. */
1638 punit
->server
.moving
->punit
= NULL
;
1641 /* check if this unit had UTYF_GAMELOSS flag */
1642 if (unit_has_type_flag(punit
, UTYF_GAMELOSS
) && unit_owner(punit
)->is_alive
) {
1643 notify_conn(game
.est_connections
, ptile
, E_UNIT_LOST_MISC
, ftc_server
,
1644 _("Unable to defend %s, %s has lost the game."),
1646 player_name(pplayer
));
1647 notify_player(pplayer
, ptile
, E_GAME_END
, ftc_server
,
1648 _("Losing %s meant losing the game! "
1649 "Be more careful next time!"),
1651 player_status_add(unit_owner(punit
), PSTATUS_DYING
);
1654 script_server_signal_emit("unit_lost", 3,
1655 API_TYPE_UNIT
, punit
,
1656 API_TYPE_PLAYER
, unit_owner(punit
),
1657 API_TYPE_STRING
, unit_loss_reason_name(reason
));
1659 script_server_remove_exported_object(punit
);
1660 game_remove_unit(punit
);
1663 if (NULL
!= ptrans
) {
1664 /* Update the occupy info. */
1665 send_unit_info(NULL
, ptrans
);
1668 /* This unit may have blocked tiles of adjacent cities. Update them. */
1669 city_map_update_tile_now(ptile
);
1673 city_refresh(phomecity
);
1674 send_city_info(city_owner(phomecity
), phomecity
);
1677 if (pcity
&& pcity
!= phomecity
) {
1678 city_refresh(pcity
);
1679 send_city_info(city_owner(pcity
), pcity
);
1682 if (pcity
&& unit_list_size(ptile
->units
) == 0) {
1683 /* The last unit in the city was killed: update the occupied flag. */
1684 send_city_info(NULL
, pcity
);
1688 /****************************************************************************
1689 We remove the unit and see if it's disappearance has affected the homecity
1690 and the city it was in.
1691 ****************************************************************************/
1692 static void server_remove_unit(struct unit
*punit
,
1693 enum unit_loss_reason reason
)
1695 server_remove_unit_full(punit
, unit_transported(punit
), reason
);
1698 /**************************************************************************
1699 Handle units destroyed when their transport is destroyed
1700 **************************************************************************/
1701 static void unit_lost_with_transport(const struct player
*pplayer
,
1702 struct unit
*pcargo
,
1703 struct unit_type
*ptransport
,
1704 struct player
*killer
)
1706 notify_player(pplayer
, unit_tile(pcargo
), E_UNIT_LOST_MISC
, ftc_server
,
1707 _("%s lost when %s was lost."),
1708 unit_tile_link(pcargo
),
1709 utype_name_translation(ptransport
));
1710 /* Unit is not transported any more at this point, but it has jumped
1711 * off the transport and drowns outside. So it must be removed from
1713 * However, we don't know if given client has received ANY updates
1714 * about the swimming unit, and we can't remove it if it's not there
1715 * in the first place -> we send it once here just to be sure it's
1717 send_unit_info(NULL
, pcargo
);
1718 wipe_unit_full(pcargo
, FALSE
, ULR_TRANSPORT_LOST
, killer
);
1721 /****************************************************************************
1722 Remove the unit, and passengers if it is a carrying any. Remove the
1723 _minimum_ number, eg there could be another boat on the square.
1724 ****************************************************************************/
1725 static void wipe_unit_full(struct unit
*punit
, bool transported
,
1726 enum unit_loss_reason reason
,
1727 struct player
*killer
)
1729 struct tile
*ptile
= unit_tile(punit
);
1730 struct player
*pplayer
= unit_owner(punit
);
1731 struct unit_type
*putype_save
= unit_type_get(punit
); /* for notify messages */
1732 struct unit_list
*helpless
= unit_list_new();
1733 struct unit_list
*imperiled
= unit_list_new();
1734 struct unit_list
*unsaved
= unit_list_new();
1735 struct unit
*ptrans
= unit_transport_get(punit
);
1737 /* The unit is doomed. */
1738 punit
->server
.dying
= TRUE
;
1740 /* Remove unit itself from its transport */
1741 if (ptrans
!= NULL
) {
1742 unit_transport_unload(punit
);
1743 send_unit_info(NULL
, ptrans
);
1746 /* First pull all units off of the transporter. */
1747 if (get_transporter_occupancy(punit
) > 0) {
1748 /* Use iterate_safe as unloaded units will be removed from the list
1749 * while iterating. */
1750 unit_list_iterate_safe(unit_transport_cargo(punit
), pcargo
) {
1751 bool healthy
= FALSE
;
1753 if (!can_unit_unload(pcargo
, punit
)) {
1754 unit_list_prepend(helpless
, pcargo
);
1756 if (!can_unit_exist_at_tile(pcargo
, ptile
)) {
1757 unit_list_prepend(imperiled
, pcargo
);
1759 /* These units do not need to be saved. */
1764 /* Could use unit_transport_unload_send here, but that would
1765 * call send_unit_info for the transporter unnecessarily.
1766 * Note that this means that unit might to get seen briefly
1767 * by clients other than owner's, for example as a result of
1768 * update of homecity common to this cargo and some other
1769 * destroyed unit. */
1770 unit_transport_unload(pcargo
);
1771 if (pcargo
->activity
== ACTIVITY_SENTRY
) {
1772 /* Activate sentried units - like planes on a disbanded carrier.
1773 * Note this will activate ground units even if they just change
1775 set_unit_activity(pcargo
, ACTIVITY_IDLE
);
1778 /* Unit info for unhealthy units will be sent when they are
1779 * assigned new transport or removed. */
1781 send_unit_info(NULL
, pcargo
);
1783 } unit_list_iterate_safe_end
;
1786 /* Now remove the unit. */
1787 server_remove_unit_full(punit
, transported
, reason
);
1797 case ULR_ELIMINATED
:
1798 case ULR_TRANSPORT_LOST
:
1799 if (killer
!= NULL
) {
1800 killer
->score
.units_killed
++;
1802 pplayer
->score
.units_lost
++;
1804 case ULR_BARB_UNLEASH
:
1807 case ULR_NONNATIVE_TERR
:
1811 case ULR_STACK_CONFLICT
:
1813 pplayer
->score
.units_lost
++;
1819 case ULR_PLAYER_DIED
:
1825 /* First, sort out helpless cargo. */
1826 if (unit_list_size(helpless
) > 0) {
1827 struct unit_list
*remaining
= unit_list_new();
1829 /* Grant priority to undisbandable and gameloss units. */
1830 unit_list_iterate_safe(helpless
, pcargo
) {
1831 if (unit_has_type_flag(pcargo
, UTYF_UNDISBANDABLE
)
1832 || unit_has_type_flag(pcargo
, UTYF_GAMELOSS
)) {
1833 if (!try_to_save_unit(pcargo
, putype_save
, TRUE
,
1834 unit_has_type_flag(pcargo
,
1835 UTYF_UNDISBANDABLE
))) {
1836 unit_list_prepend(unsaved
, pcargo
);
1839 unit_list_prepend(remaining
, pcargo
);
1841 } unit_list_iterate_safe_end
;
1843 /* Handle non-priority units. */
1844 unit_list_iterate_safe(remaining
, pcargo
) {
1845 if (!try_to_save_unit(pcargo
, putype_save
, TRUE
, FALSE
)) {
1846 unit_list_prepend(unsaved
, pcargo
);
1848 } unit_list_iterate_safe_end
;
1850 unit_list_destroy(remaining
);
1852 unit_list_destroy(helpless
);
1854 /* Then, save any imperiled cargo. */
1855 if (unit_list_size(imperiled
) > 0) {
1856 struct unit_list
*remaining
= unit_list_new();
1858 /* Grant priority to undisbandable and gameloss units. */
1859 unit_list_iterate_safe(imperiled
, pcargo
) {
1860 if (unit_has_type_flag(pcargo
, UTYF_UNDISBANDABLE
)
1861 || unit_has_type_flag(pcargo
, UTYF_GAMELOSS
)) {
1862 if (!try_to_save_unit(pcargo
, putype_save
, FALSE
,
1863 unit_has_type_flag(pcargo
,
1864 UTYF_UNDISBANDABLE
))) {
1865 unit_list_prepend(unsaved
, pcargo
);
1868 unit_list_prepend(remaining
, pcargo
);
1870 } unit_list_iterate_safe_end
;
1872 /* Handle non-priority units. */
1873 unit_list_iterate_safe(remaining
, pcargo
) {
1874 if (!try_to_save_unit(pcargo
, putype_save
, FALSE
, FALSE
)) {
1875 unit_list_prepend(unsaved
, pcargo
);
1877 } unit_list_iterate_safe_end
;
1879 unit_list_destroy(remaining
);
1881 unit_list_destroy(imperiled
);
1883 /* Finally, kill off the unsaved units. */
1884 if (unit_list_size(unsaved
) > 0) {
1885 unit_list_iterate_safe(unsaved
, dying_unit
) {
1886 unit_lost_with_transport(pplayer
, dying_unit
, putype_save
, killer
);
1887 } unit_list_iterate_safe_end
;
1889 unit_list_destroy(unsaved
);
1892 /****************************************************************************
1893 Remove the unit, and passengers if it is a carrying any. Remove the
1894 _minimum_ number, eg there could be another boat on the square.
1895 ****************************************************************************/
1896 void wipe_unit(struct unit
*punit
, enum unit_loss_reason reason
,
1897 struct player
*killer
)
1899 wipe_unit_full(punit
, unit_transported(punit
), reason
, killer
);
1902 /****************************************************************************
1903 Determine if it is possible to save a given unit, and if so, save them.
1904 Note that despite being saved from drowning, teleporting the units to
1905 "safety" may have killed them in the end.
1906 ****************************************************************************/
1907 bool try_to_save_unit(struct unit
*punit
, struct unit_type
*pttype
,
1908 bool helpless
, bool teleporting
)
1910 struct tile
*ptile
= unit_tile(punit
);
1911 struct player
*pplayer
= unit_owner(punit
);
1912 struct unit
*ptransport
= transporter_for_unit(punit
);
1914 /* Helpless units cannot board a transport in their current state. */
1916 && ptransport
!= NULL
) {
1917 unit_transport_load_tp_status(punit
, ptransport
, FALSE
);
1918 send_unit_info(NULL
, punit
);
1921 /* Only units that cannot find transport are considered for teleport. */
1923 struct city
*pcity
= find_closest_city(ptile
, NULL
, unit_owner(punit
),
1924 FALSE
, FALSE
, FALSE
, TRUE
, FALSE
,
1925 utype_class(pttype
));
1926 if (pcity
!= NULL
) {
1927 char tplink
[MAX_LEN_LINK
]; /* In case unit dies when teleported */
1929 sz_strlcpy(tplink
, unit_link(punit
));
1931 if (teleport_unit_to_city(punit
, pcity
, 0, FALSE
)) {
1932 notify_player(pplayer
, ptile
, E_UNIT_RELOCATED
, ftc_server
,
1933 _("%s escaped the destruction of %s, and fled to %s."),
1935 utype_name_translation(pttype
),
1942 /* The unit could not use transport on the tile, and could not teleport. */
1946 /****************************************************************************
1947 We don't really change owner of the unit, but create completely new
1948 unit as its copy. The new pointer to 'punit' is returned.
1949 ****************************************************************************/
1950 struct unit
*unit_change_owner(struct unit
*punit
, struct player
*pplayer
,
1951 int homecity
, enum unit_loss_reason reason
)
1953 struct unit
*gained_unit
;
1955 fc_assert(!utype_player_already_has_this_unique(pplayer
,
1956 unit_type_get(punit
)));
1958 /* Convert the unit to your cause. Fog is lifted in the create algorithm. */
1959 gained_unit
= create_unit_full(pplayer
, unit_tile(punit
),
1960 unit_type_get(punit
), punit
->veteran
,
1961 homecity
, punit
->moves_left
,
1964 /* Owner changes, nationality not. */
1965 gained_unit
->nationality
= punit
->nationality
;
1967 /* Copy some more unit fields */
1968 gained_unit
->fuel
= punit
->fuel
;
1969 gained_unit
->paradropped
= punit
->paradropped
;
1970 gained_unit
->server
.birth_turn
= punit
->server
.birth_turn
;
1972 send_unit_info(NULL
, gained_unit
);
1974 /* update unit upkeep in the homecity of the victim */
1975 if (punit
->homecity
> 0) {
1976 /* update unit upkeep */
1977 city_units_upkeep(game_city_by_number(punit
->homecity
));
1979 /* update unit upkeep in the new homecity */
1981 city_units_upkeep(game_city_by_number(homecity
));
1984 /* Be sure to wipe the converted unit! */
1985 wipe_unit(punit
, reason
, NULL
);
1987 return gained_unit
; /* Returns the replacement. */
1990 /**************************************************************************
1991 Called when one unit kills another in combat (this function is only
1992 called in one place). It handles all side effects including
1993 notifications and killstack.
1994 **************************************************************************/
1995 void kill_unit(struct unit
*pkiller
, struct unit
*punit
, bool vet
)
1997 char pkiller_link
[MAX_LEN_LINK
], punit_link
[MAX_LEN_LINK
];
1998 struct player
*pvictim
= unit_owner(punit
);
1999 struct player
*pvictor
= unit_owner(pkiller
);
2000 int ransom
, unitcount
= 0;
2002 sz_strlcpy(pkiller_link
, unit_link(pkiller
));
2003 sz_strlcpy(punit_link
, unit_tile_link(punit
));
2005 /* The unit is doomed. */
2006 punit
->server
.dying
= TRUE
;
2008 if ((game
.info
.gameloss_style
& GAMELOSS_STYLE_LOOT
)
2009 && unit_has_type_flag(punit
, UTYF_GAMELOSS
)) {
2010 ransom
= fc_rand(1 + pvictim
->economic
.gold
);
2014 give_distorted_map(pvictim
, pvictor
, 1, 1, TRUE
);
2016 log_debug("victim has money: %d", pvictim
->economic
.gold
);
2017 pvictor
->economic
.gold
+= ransom
;
2018 pvictim
->economic
.gold
-= ransom
;
2023 Tech_type_id ttid
= steal_a_tech(pvictor
, pvictim
, A_UNSET
);
2025 if (ttid
== A_NONE
) {
2026 log_debug("Worthless enemy doesn't have more techs to steal.");
2029 log_debug("Pressed tech %s from captured enemy",
2030 research_advance_rule_name(research_get(pvictor
), ttid
));
2032 break; /* out of luck */
2038 { /* try to submit some cities */
2039 int vcsize
= city_list_size(pvictim
->cities
);
2040 int evcsize
= vcsize
;
2041 int conqsize
= evcsize
;
2048 /* about a quarter on average with high numbers less probable */
2049 conqsize
= fc_rand(fc_rand(evcsize
));
2051 log_debug("conqsize=%d", conqsize
);
2054 bool palace
= game
.server
.savepalace
;
2055 bool submit
= FALSE
;
2057 game
.server
.savepalace
= FALSE
; /* moving it around is dumb */
2059 city_list_iterate_safe(pvictim
->cities
, pcity
) {
2060 /* kindly ask the citizens to submit */
2061 if (fc_rand(vcsize
) < conqsize
) {
2067 /* Transfer city to the victorious player
2068 * kill all its units outside of a radius of 7,
2069 * give verbose messages of every unit transferred,
2070 * and raze buildings according to raze chance
2071 * (also removes palace) */
2072 (void) transfer_city(pvictor
, pcity
, 7, TRUE
, TRUE
, TRUE
,
2073 !is_barbarian(pvictor
));
2076 if (conqsize
<= 0) {
2079 } city_list_iterate_safe_end
;
2080 game
.server
.savepalace
= palace
;
2085 /* barbarian leader ransom hack */
2086 if( is_barbarian(pvictim
) && unit_has_type_role(punit
, L_BARBARIAN_LEADER
)
2087 && (unit_list_size(unit_tile(punit
)->units
) == 1)
2088 && uclass_has_flag(unit_class_get(pkiller
), UCF_COLLECT_RANSOM
)) {
2089 /* Occupying units can collect ransom if leader is alone in the tile */
2090 ransom
= (pvictim
->economic
.gold
>= game
.server
.ransom_gold
)
2091 ? game
.server
.ransom_gold
: pvictim
->economic
.gold
;
2092 notify_player(pvictor
, unit_tile(pkiller
), E_UNIT_WIN_ATT
, ftc_server
,
2093 PL_("Barbarian leader captured; %d gold ransom paid.",
2094 "Barbarian leader captured; %d gold ransom paid.",
2097 pvictor
->economic
.gold
+= ransom
;
2098 pvictim
->economic
.gold
-= ransom
;
2099 send_player_info_c(pvictor
, NULL
); /* let me see my new gold :-) */
2103 if (unitcount
== 0) {
2104 unit_list_iterate(unit_tile(punit
)->units
, vunit
) {
2105 if (pplayers_at_war(pvictor
, unit_owner(vunit
))) {
2108 } unit_list_iterate_end
;
2111 if (!is_stack_vulnerable(unit_tile(punit
)) || unitcount
== 1) {
2112 notify_player(pvictor
, unit_tile(pkiller
), E_UNIT_WIN_ATT
, ftc_server
,
2113 /* TRANS: "... Cannon ... the Polish Destroyer." */
2114 _("Your attacking %s succeeded against the %s %s!"),
2116 nation_adjective_for_player(pvictim
),
2119 notify_unit_experience(pkiller
);
2121 notify_player(pvictim
, unit_tile(punit
), E_UNIT_LOST_DEF
, ftc_server
,
2122 /* TRANS: "Cannon ... the Polish Destroyer." */
2123 _("%s lost to an attack by the %s %s."),
2125 nation_adjective_for_player(pvictor
),
2128 wipe_unit(punit
, ULR_KILLED
, pvictor
);
2129 } else { /* unitcount > 1 */
2131 int num_killed
[player_slot_count()];
2132 struct unit
*other_killed
[player_slot_count()];
2133 struct tile
*ptile
= unit_tile(punit
);
2135 fc_assert(unitcount
> 1);
2138 for (i
= 0; i
< player_slot_count(); i
++) {
2140 other_killed
[i
] = NULL
;
2143 /* count killed units */
2144 unit_list_iterate(ptile
->units
, vunit
) {
2145 struct player
*vplayer
= unit_owner(vunit
);
2146 if (pplayers_at_war(pvictor
, vplayer
)
2147 && is_unit_reachable_at(vunit
, pkiller
, ptile
)) {
2148 num_killed
[player_index(vplayer
)]++;
2149 if (vunit
!= punit
) {
2150 other_killed
[player_index(vplayer
)] = vunit
;
2151 other_killed
[player_index(pvictor
)] = vunit
;
2154 } unit_list_iterate_end
;
2156 /* Inform the destroyer: lots of different cases here! */
2157 notify_player(pvictor
, unit_tile(pkiller
), E_UNIT_WIN_ATT
, ftc_server
,
2158 /* TRANS: "... Cannon ... the Polish Destroyer ...." */
2159 PL_("Your attacking %s succeeded against the %s %s "
2160 "(and %d other unit)!",
2161 "Your attacking %s succeeded against the %s %s "
2162 "(and %d other units)!", unitcount
- 1),
2164 nation_adjective_for_player(pvictim
),
2168 notify_unit_experience(pkiller
);
2171 /* inform the owners: this only tells about owned units that were killed.
2172 * there may have been 20 units who died but if only 2 belonged to the
2173 * particular player they'll only learn about those.
2175 * Also if a large number of units die you don't find out what type
2177 for (i
= 0; i
< player_slot_count(); i
++) {
2178 if (num_killed
[i
] == 1) {
2179 if (i
== player_index(pvictim
)) {
2180 fc_assert(other_killed
[i
] == NULL
);
2181 notify_player(player_by_number(i
), ptile
,
2182 E_UNIT_LOST_DEF
, ftc_server
,
2183 /* TRANS: "Cannon ... the Polish Destroyer." */
2184 _("%s lost to an attack by the %s %s."),
2186 nation_adjective_for_player(pvictor
),
2189 fc_assert(other_killed
[i
] != punit
);
2190 notify_player(player_by_number(i
), ptile
,
2191 E_UNIT_LOST_DEF
, ftc_server
,
2192 /* TRANS: "Cannon lost when the Polish Destroyer
2193 * attacked the German Musketeers." */
2194 _("%s lost when the %s %s attacked the %s %s."),
2195 unit_link(other_killed
[i
]),
2196 nation_adjective_for_player(pvictor
),
2198 nation_adjective_for_player(pvictim
),
2201 } else if (num_killed
[i
] > 1) {
2202 if (i
== player_index(pvictim
)) {
2203 int others
= num_killed
[i
] - 1;
2206 notify_player(player_by_number(i
), ptile
,
2207 E_UNIT_LOST_DEF
, ftc_server
,
2208 /* TRANS: "Musketeers (and Cannon) lost to an
2209 * attack from the Polish Destroyer." */
2210 _("%s (and %s) lost to an attack from the %s %s."),
2212 unit_link(other_killed
[i
]),
2213 nation_adjective_for_player(pvictor
),
2216 notify_player(player_by_number(i
), ptile
,
2217 E_UNIT_LOST_DEF
, ftc_server
,
2218 /* TRANS: "Musketeers and 3 other units lost to
2219 * an attack from the Polish Destroyer."
2220 * (only happens with at least 2 other units) */
2221 PL_("%s and %d other unit lost to an attack "
2223 "%s and %d other units lost to an attack "
2224 "from the %s %s.", others
),
2227 nation_adjective_for_player(pvictor
),
2231 notify_player(player_by_number(i
), ptile
,
2232 E_UNIT_LOST_DEF
, ftc_server
,
2233 /* TRANS: "2 units lost when the Polish Destroyer
2234 * attacked the German Musketeers."
2235 * (only happens with at least 2 other units) */
2236 PL_("%d unit lost when the %s %s attacked the %s %s.",
2237 "%d units lost when the %s %s attacked the %s %s.",
2240 nation_adjective_for_player(pvictor
),
2242 nation_adjective_for_player(pvictim
),
2248 /* remove the units - note the logic of which units actually die
2249 * must be mimiced exactly in at least one place up above. */
2250 punit
= NULL
; /* wiped during following iteration so unsafe to use */
2252 unit_list_iterate_safe(ptile
->units
, punit2
) {
2253 if (pplayers_at_war(pvictor
, unit_owner(punit2
))
2254 && is_unit_reachable_at(punit2
, pkiller
, ptile
)) {
2255 wipe_unit(punit2
, ULR_KILLED
, pvictor
);
2257 } unit_list_iterate_safe_end
;
2261 /**************************************************************************
2262 Package a unit_info packet. This packet contains basically all
2263 information about a unit.
2264 **************************************************************************/
2265 void package_unit(struct unit
*punit
, struct packet_unit_info
*packet
)
2267 packet
->id
= punit
->id
;
2268 packet
->owner
= player_number(unit_owner(punit
));
2269 packet
->nationality
= player_number(unit_nationality(punit
));
2270 packet
->tile
= tile_index(unit_tile(punit
));
2271 packet
->facing
= punit
->facing
;
2272 packet
->homecity
= punit
->homecity
;
2273 output_type_iterate(o
) {
2274 packet
->upkeep
[o
] = punit
->upkeep
[o
];
2275 } output_type_iterate_end
;
2276 packet
->veteran
= punit
->veteran
;
2277 packet
->type
= utype_number(unit_type_get(punit
));
2278 packet
->movesleft
= punit
->moves_left
;
2279 packet
->hp
= punit
->hp
;
2280 packet
->activity
= punit
->activity
;
2281 packet
->activity_count
= punit
->activity_count
;
2283 if (punit
->activity_target
!= NULL
) {
2284 packet
->activity_tgt
= extra_index(punit
->activity_target
);
2286 packet
->activity_tgt
= EXTRA_NONE
;
2289 packet
->changed_from
= punit
->changed_from
;
2290 packet
->changed_from_count
= punit
->changed_from_count
;
2292 if (punit
->changed_from_target
!= NULL
) {
2293 packet
->changed_from_tgt
= extra_index(punit
->changed_from_target
);
2295 packet
->changed_from_tgt
= EXTRA_NONE
;
2298 packet
->ai
= punit
->ai_controlled
;
2299 packet
->fuel
= punit
->fuel
;
2300 packet
->goto_tile
= (NULL
!= punit
->goto_tile
2301 ? tile_index(punit
->goto_tile
) : -1);
2302 packet
->paradropped
= punit
->paradropped
;
2303 packet
->done_moving
= punit
->done_moving
;
2304 if (!unit_transported(punit
)) {
2305 packet
->transported
= FALSE
;
2306 packet
->transported_by
= 0;
2308 packet
->transported
= TRUE
;
2309 packet
->transported_by
= unit_transport_get(punit
)->id
;
2311 packet
->occupied
= (get_transporter_occupancy(punit
) > 0);
2312 packet
->battlegroup
= punit
->battlegroup
;
2313 packet
->has_orders
= punit
->has_orders
;
2314 if (punit
->has_orders
) {
2317 packet
->orders_length
= punit
->orders
.length
;
2318 packet
->orders_index
= punit
->orders
.index
;
2319 packet
->orders_repeat
= punit
->orders
.repeat
;
2320 packet
->orders_vigilant
= punit
->orders
.vigilant
;
2321 for (i
= 0; i
< punit
->orders
.length
; i
++) {
2322 packet
->orders
[i
] = punit
->orders
.list
[i
].order
;
2323 packet
->orders_dirs
[i
] = punit
->orders
.list
[i
].dir
;
2324 packet
->orders_activities
[i
] = punit
->orders
.list
[i
].activity
;
2325 packet
->orders_targets
[i
] = punit
->orders
.list
[i
].target
;
2328 packet
->orders_length
= packet
->orders_index
= 0;
2329 packet
->orders_repeat
= packet
->orders_vigilant
= FALSE
;
2330 /* No need to initialize array. */
2333 packet
->action_decision_want
= punit
->action_decision_want
;
2334 packet
->action_decision_tile
= (punit
->action_decision_tile
2335 ? tile_index(punit
->action_decision_tile
)
2336 : IDENTITY_NUMBER_ZERO
);
2339 /**************************************************************************
2340 Package a short_unit_info packet. This contains a limited amount of
2341 information about the unit, and is sent to players who shouldn't know
2342 everything (like the unit's owner's enemies).
2343 **************************************************************************/
2344 void package_short_unit(struct unit
*punit
,
2345 struct packet_unit_short_info
*packet
,
2346 enum unit_info_use packet_use
, int info_city_id
)
2348 packet
->packet_use
= packet_use
;
2349 packet
->info_city_id
= info_city_id
;
2351 packet
->id
= punit
->id
;
2352 packet
->owner
= player_number(unit_owner(punit
));
2353 packet
->tile
= tile_index(unit_tile(punit
));
2354 packet
->facing
= punit
->facing
;
2355 packet
->veteran
= punit
->veteran
;
2356 packet
->type
= utype_number(unit_type_get(punit
));
2357 packet
->hp
= punit
->hp
;
2358 packet
->occupied
= (get_transporter_occupancy(punit
) > 0);
2359 if (punit
->activity
== ACTIVITY_EXPLORE
2360 || punit
->activity
== ACTIVITY_GOTO
) {
2361 packet
->activity
= ACTIVITY_IDLE
;
2363 packet
->activity
= punit
->activity
;
2366 if (punit
->activity_target
== NULL
) {
2367 packet
->activity_tgt
= EXTRA_NONE
;
2369 packet
->activity_tgt
= extra_index(punit
->activity_target
);
2372 /* Transported_by information is sent to the client even for units that
2373 * aren't fully known. Note that for non-allied players, any transported
2374 * unit can't be seen at all. For allied players we have to know if
2375 * transporters have room in them so that we can load units properly. */
2376 if (!unit_transported(punit
)) {
2377 packet
->transported
= FALSE
;
2378 packet
->transported_by
= 0;
2380 packet
->transported
= TRUE
;
2381 packet
->transported_by
= unit_transport_get(punit
)->id
;
2385 /**************************************************************************
2386 Handle situation where unit goes out of player sight.
2387 **************************************************************************/
2388 void unit_goes_out_of_sight(struct player
*pplayer
, struct unit
*punit
)
2390 dlsend_packet_unit_remove(pplayer
->connections
, punit
->id
);
2391 if (punit
->server
.moving
!= NULL
) {
2392 /* Update status of 'pplayer' vision for 'punit'. */
2393 BV_CLR(punit
->server
.moving
->can_see_unit
, player_index(pplayer
));
2397 /****************************************************************************
2398 send the unit to the players who need the info.
2399 dest = NULL means all connections (game.est_connections)
2400 ****************************************************************************/
2401 void send_unit_info(struct conn_list
*dest
, struct unit
*punit
)
2403 const struct player
*powner
;
2404 struct packet_unit_info info
;
2405 struct packet_unit_short_info sinfo
;
2406 struct unit_move_data
*pdata
;
2409 dest
= game
.est_connections
;
2414 powner
= unit_owner(punit
);
2415 package_unit(punit
, &info
);
2416 package_short_unit(punit
, &sinfo
, UNIT_INFO_IDENTITY
, 0);
2417 pdata
= punit
->server
.moving
;
2419 conn_list_iterate(dest
, pconn
) {
2420 struct player
*pplayer
= conn_get_player(pconn
);
2422 /* Be careful to consider all cases where pplayer is NULL... */
2423 if (pplayer
== NULL
) {
2424 if (pconn
->observer
) {
2425 send_packet_unit_info(pconn
, &info
);
2427 } else if (pplayer
== powner
) {
2428 send_packet_unit_info(pconn
, &info
);
2429 if (pdata
!= NULL
) {
2430 BV_SET(pdata
->can_see_unit
, player_index(pplayer
));
2432 } else if (can_player_see_unit(pplayer
, punit
)) {
2433 send_packet_unit_short_info(pconn
, &sinfo
, FALSE
);
2434 if (pdata
!= NULL
) {
2435 BV_SET(pdata
->can_see_unit
, player_index(pplayer
));
2438 } conn_list_iterate_end
;
2441 /**************************************************************************
2442 For each specified connections, send information about all the units
2443 known to that player/conn.
2444 **************************************************************************/
2445 void send_all_known_units(struct conn_list
*dest
)
2447 conn_list_do_buffer(dest
);
2448 conn_list_iterate(dest
, pconn
) {
2449 struct player
*pplayer
= pconn
->playing
;
2451 if (NULL
== pplayer
&& !pconn
->observer
) {
2455 players_iterate(unitowner
) {
2456 unit_list_iterate(unitowner
->units
, punit
) {
2457 send_unit_info(dest
, punit
);
2458 } unit_list_iterate_end
;
2459 } players_iterate_end
;
2461 conn_list_iterate_end
;
2462 conn_list_do_unbuffer(dest
);
2466 /**************************************************************************
2467 Nuke a square: 1) remove all units on the square, and 2) halve the
2468 size of the city on the square.
2470 If it isn't a city square or an ocean square then with 50% chance add
2471 some fallout, then notify the client about the changes.
2472 **************************************************************************/
2473 static void do_nuke_tile(struct player
*pplayer
, struct tile
*ptile
)
2475 struct city
*pcity
= NULL
;
2477 unit_list_iterate_safe(ptile
->units
, punit
) {
2478 notify_player(unit_owner(punit
), ptile
, E_UNIT_LOST_MISC
, ftc_server
,
2479 _("Your %s was nuked by %s."),
2480 unit_tile_link(punit
),
2481 pplayer
== unit_owner(punit
)
2483 : nation_plural_for_player(pplayer
));
2484 if (unit_owner(punit
) != pplayer
) {
2485 notify_player(pplayer
, ptile
, E_UNIT_WIN
, ftc_server
,
2486 _("The %s %s was nuked."),
2487 nation_adjective_for_player(unit_owner(punit
)),
2488 unit_tile_link(punit
));
2490 wipe_unit(punit
, ULR_NUKE
, pplayer
);
2491 } unit_list_iterate_safe_end
;
2493 pcity
= tile_city(ptile
);
2496 notify_player(city_owner(pcity
), ptile
, E_CITY_NUKED
, ftc_server
,
2497 _("%s was nuked by %s."),
2499 pplayer
== city_owner(pcity
)
2501 : nation_plural_for_player(pplayer
));
2503 if (city_owner(pcity
) != pplayer
) {
2504 notify_player(pplayer
, ptile
, E_CITY_NUKED
, ftc_server
,
2509 city_reduce_size(pcity
, city_size_get(pcity
) / 2, pplayer
, "nuke");
2512 if (fc_rand(2) == 1) {
2513 struct extra_type
*pextra
;
2515 pextra
= rand_extra_for_tile(ptile
, EC_FALLOUT
);
2516 if (pextra
!= NULL
&& !tile_has_extra(ptile
, pextra
)) {
2517 tile_add_extra(ptile
, pextra
);
2518 update_tile_knowledge(ptile
);
2523 /**************************************************************************
2524 Nuke all the squares in a 3x3 square around the center of the explosion
2525 pplayer is the player that caused the explosion.
2526 **************************************************************************/
2527 void do_nuclear_explosion(struct player
*pplayer
, struct tile
*ptile
)
2529 struct player
*victim
= tile_owner(ptile
);
2531 call_incident(INCIDENT_NUCLEAR
, pplayer
, victim
);
2533 if (pplayer
== victim
) {
2534 players_iterate(oplayer
) {
2535 if (victim
!= oplayer
) {
2536 call_incident(INCIDENT_NUCLEAR_SELF
, pplayer
, oplayer
);
2538 } players_iterate_end
;
2540 players_iterate(oplayer
) {
2541 if (victim
!= oplayer
) {
2542 call_incident(INCIDENT_NUCLEAR_NOT_TARGET
, pplayer
, oplayer
);
2544 } players_iterate_end
;
2547 square_iterate(ptile
, 1, ptile1
) {
2548 do_nuke_tile(pplayer
, ptile1
);
2549 } square_iterate_end
;
2551 notify_conn(NULL
, ptile
, E_NUKE
, ftc_server
,
2552 _("The %s detonated a nuke!"),
2553 nation_plural_for_player(pplayer
));
2556 /**************************************************************************
2557 go by airline, if both cities have an airport and neither has been used this
2558 turn the unit will be transported by it and have its moves set to 0
2559 **************************************************************************/
2560 bool do_airline(struct unit
*punit
, struct city
*pdest_city
)
2562 struct city
*psrc_city
= tile_city(unit_tile(punit
));
2565 enum unit_airlift_result result
=
2566 test_unit_can_airlift_to(NULL
, punit
, pdest_city
);
2567 if (!is_successful_airlift_result(result
)) {
2569 /* These two can happen through no fault of the client (for allied
2570 * airlifts), so we give useful messages. */
2571 case AR_SRC_NO_FLIGHTS
:
2572 notify_player(unit_owner(punit
), unit_tile(punit
),
2573 E_UNIT_RELOCATED
, ftc_server
,
2574 /* TRANS: Airlift failure message.
2575 * "Paris has no capacity to transport Warriors." */
2576 _("%s has no capacity to transport %s."),
2577 city_link(psrc_city
), unit_link(punit
));
2579 case AR_DST_NO_FLIGHTS
:
2580 notify_player(unit_owner(punit
), unit_tile(punit
),
2581 E_UNIT_RELOCATED
, ftc_server
,
2582 /* TRANS: Airlift failure message.
2583 * "Paris has no capacity to transport Warriors." */
2584 _("%s has no capacity to transport %s."),
2585 city_link(pdest_city
), unit_link(punit
));
2588 /* The client should have been able to foresee all the other
2589 * causes of failure, so it's not worth having specific messages for
2591 notify_player(unit_owner(punit
), unit_tile(punit
),
2592 E_UNIT_RELOCATED
, ftc_server
,
2593 /* TRANS: Airlift failure message.
2594 * "Warriors cannot be transported to Paris." */
2595 _("%s cannot be transported to %s."),
2596 unit_link(punit
), city_link(pdest_city
));
2603 notify_player(unit_owner(punit
), city_tile(pdest_city
),
2604 E_UNIT_RELOCATED
, ftc_server
,
2605 _("%s transported successfully."),
2608 unit_move(punit
, pdest_city
->tile
, punit
->moves_left
, NULL
);
2610 /* Update airlift fields. */
2611 if (!(game
.info
.airlifting_style
& AIRLIFTING_UNLIMITED_SRC
)) {
2612 psrc_city
->airlift
--;
2613 send_city_info(city_owner(psrc_city
), psrc_city
);
2615 if (!(game
.info
.airlifting_style
& AIRLIFTING_UNLIMITED_DEST
)) {
2616 pdest_city
->airlift
--;
2617 send_city_info(city_owner(pdest_city
), pdest_city
);
2623 /**************************************************************************
2624 Autoexplore with unit.
2625 **************************************************************************/
2626 void do_explore(struct unit
*punit
)
2628 switch (manage_auto_explorer(punit
)) {
2630 /* don't use punit! */
2632 case MR_NOT_ALLOWED
:
2633 /* Needed for something else */
2636 /* FIXME: manage_auto_explorer() isn't supposed to change the activity,
2637 * but don't count on this. See PR#39792.
2639 if (punit
->activity
== ACTIVITY_EXPLORE
) {
2644 unit_activity_handling(punit
, ACTIVITY_IDLE
);
2646 /* FIXME: When the manage_auto_explorer() call changes the activity from
2647 * EXPLORE to IDLE, in unit_activity_handling() ai.control is left
2648 * alone. We reset it here. See PR#12931. */
2649 punit
->ai_controlled
= FALSE
;
2653 send_unit_info(NULL
, punit
); /* probably duplicate */
2656 /**************************************************************************
2657 Returns whether the drop was made or not. Note that it also returns 1
2658 in the case where the drop was succesful, but the unit was killed by
2659 barbarians in a hut.
2660 **************************************************************************/
2661 bool do_paradrop(struct unit
*punit
, struct tile
*ptile
)
2663 struct player
*pplayer
= unit_owner(punit
);
2664 int range
, distance
;
2666 if (!unit_has_type_flag(punit
, UTYF_PARATROOPERS
)) {
2667 notify_player(pplayer
, unit_tile(punit
), E_BAD_COMMAND
, ftc_server
,
2668 _("This unit type can not be paradropped."));
2672 if (!can_unit_paradrop(punit
)) {
2676 if (get_transporter_occupancy(punit
) > 0) {
2677 notify_player(pplayer
, unit_tile(punit
), E_BAD_COMMAND
, ftc_server
,
2678 _("You cannot paradrop a unit that is "
2679 "transporting other units."));
2683 if (!map_is_known(ptile
, pplayer
)) {
2684 notify_player(pplayer
, ptile
, E_BAD_COMMAND
, ftc_server
,
2685 _("The destination location is not known."));
2689 range
= unit_type_get(punit
)->paratroopers_range
;
2690 distance
= real_map_distance(unit_tile(punit
), ptile
);
2691 if (distance
> range
) {
2692 notify_player(pplayer
, ptile
, E_BAD_COMMAND
, ftc_server
,
2693 _("The distance to the target (%i) "
2694 "is greater than the unit's range (%i)."),
2699 if (map_is_known_and_seen(ptile
, pplayer
, V_MAIN
)) {
2700 if (!can_unit_exist_at_tile(punit
, ptile
)
2701 && (!game
.info
.paradrop_to_transport
2702 || !unit_could_load_at(punit
, ptile
))) {
2703 notify_player(pplayer
, ptile
, E_BAD_COMMAND
, ftc_server
,
2704 _("This unit cannot paradrop into %s."),
2705 terrain_name_translation(tile_terrain(ptile
)));
2709 if (NULL
!= is_non_attack_city_tile(ptile
, pplayer
)) {
2710 notify_player(pplayer
, ptile
, E_BAD_COMMAND
, ftc_server
,
2711 _("Cannot attack unless you declare war first."));
2715 unit_list_iterate(ptile
->units
, pother
) {
2716 if (can_player_see_unit(pplayer
, pother
)
2717 && pplayers_non_attack(pplayer
, unit_owner(pother
))) {
2718 notify_player(pplayer
, ptile
, E_BAD_COMMAND
, ftc_server
,
2719 _("Cannot attack unless you declare war first."));
2722 } unit_list_iterate_end
;
2724 if (is_military_unit(punit
)
2725 && !player_can_invade_tile(pplayer
, ptile
)) {
2726 notify_player(pplayer
, ptile
, E_BAD_COMMAND
, ftc_server
,
2727 _("Cannot invade unless you break peace with "
2729 player_name(tile_owner(ptile
)));
2733 /* Only take in account values from player map. */
2734 const struct player_tile
*plrtile
= map_get_player_tile(ptile
, pplayer
);
2736 if (NULL
== plrtile
->site
2737 && !is_native_to_class(unit_class_get(punit
), plrtile
->terrain
,
2738 &(plrtile
->extras
))) {
2739 notify_player(pplayer
, ptile
, E_BAD_COMMAND
, ftc_server
,
2740 _("This unit cannot paradrop into %s."),
2741 terrain_name_translation(plrtile
->terrain
));
2745 if (NULL
!= plrtile
->site
2746 && plrtile
->owner
!= NULL
2747 && pplayers_non_attack(pplayer
, plrtile
->owner
)) {
2748 notify_player(pplayer
, ptile
, E_BAD_COMMAND
, ftc_server
,
2749 _("Cannot attack unless you declare war first."));
2753 if (is_military_unit(punit
)
2754 && NULL
!= plrtile
->owner
2755 && players_non_invade(pplayer
, plrtile
->owner
)) {
2756 notify_player(pplayer
, ptile
, E_BAD_COMMAND
, ftc_server
,
2757 _("Cannot invade unless you break peace with "
2759 player_name(plrtile
->owner
));
2763 /* Safe terrain, really? Not transformed since player last saw it. */
2764 if (!can_unit_exist_at_tile(punit
, ptile
)
2765 && (!game
.info
.paradrop_to_transport
2766 || !unit_could_load_at(punit
, ptile
))) {
2767 map_show_circle(pplayer
, ptile
, unit_type_get(punit
)->vision_radius_sq
);
2768 notify_player(pplayer
, ptile
, E_UNIT_LOST_MISC
, ftc_server
,
2769 _("Your %s paradropped into the %s and was lost."),
2770 unit_tile_link(punit
),
2771 terrain_name_translation(tile_terrain(ptile
)));
2772 pplayer
->score
.units_lost
++;
2773 server_remove_unit(punit
, ULR_NONNATIVE_TERR
);
2778 if (is_non_attack_city_tile(ptile
, pplayer
)
2779 || is_non_allied_unit_tile(ptile
, pplayer
)) {
2780 map_show_circle(pplayer
, ptile
, unit_type_get(punit
)->vision_radius_sq
);
2781 maybe_make_contact(ptile
, pplayer
);
2782 notify_player(pplayer
, ptile
, E_UNIT_LOST_MISC
, ftc_server
,
2783 _("Your %s was killed by enemy units at the "
2784 "paradrop destination."),
2785 unit_tile_link(punit
));
2786 /* TODO: Should defender score.units_killed get increased too?
2787 * What if there's units of several allied players? Should the
2788 * city owner or owner of the first/random unit get the kill? */
2789 pplayer
->score
.units_lost
++;
2790 server_remove_unit(punit
, ULR_KILLED
);
2795 punit
->paradropped
= TRUE
;
2796 if (unit_move(punit
, ptile
, unit_type_get(punit
)->paratroopers_mr_sub
, NULL
)) {
2797 /* Ensure we finished on valid state. */
2798 fc_assert(can_unit_exist_at_tile(punit
, unit_tile(punit
))
2799 || unit_transported(punit
));
2804 /**************************************************************************
2805 Give 25 Gold or kill the unit. For H_LIMITEDHUTS
2806 Return TRUE if unit is alive, and FALSE if it was killed
2807 **************************************************************************/
2808 static bool hut_get_limited(struct unit
*punit
)
2811 int hut_chance
= fc_rand(12);
2812 struct player
*pplayer
= unit_owner(punit
);
2813 /* 1 in 12 to get barbarians */
2814 if (hut_chance
!= 0) {
2816 notify_player(pplayer
, unit_tile(punit
), E_HUT_GOLD
, ftc_server
,
2817 PL_("You found %d gold.",
2818 "You found %d gold.", cred
), cred
);
2819 pplayer
->economic
.gold
+= cred
;
2820 } else if (city_exists_within_max_city_map(unit_tile(punit
), TRUE
)
2821 || unit_has_type_flag(punit
, UTYF_GAMELOSS
)) {
2822 notify_player(pplayer
, unit_tile(punit
),
2823 E_HUT_BARB_CITY_NEAR
, ftc_server
,
2824 _("An abandoned village is here."));
2826 notify_player(pplayer
, unit_tile(punit
), E_HUT_BARB_KILLED
, ftc_server
,
2827 _("Your %s has been killed by barbarians!"),
2828 unit_tile_link(punit
));
2829 wipe_unit(punit
, ULR_BARB_UNLEASH
, NULL
);
2835 /**************************************************************************
2836 Due to the effects in the scripted hut behavior can not be predicted,
2837 unit_enter_hut returns nothing.
2838 **************************************************************************/
2839 static void unit_enter_hut(struct unit
*punit
)
2841 struct player
*pplayer
= unit_owner(punit
);
2842 enum hut_behavior behavior
= unit_class_get(punit
)->hut_behavior
;
2843 struct tile
*ptile
= unit_tile(punit
);
2845 /* FIXME: Should we still run "hut_enter" script when
2846 * hut_behavior is HUT_NOTHING or HUT_FRIGHTEN? */
2847 if (behavior
== HUT_NOTHING
) {
2851 extra_type_by_category_iterate(ECAT_BONUS
, pextra
) {
2852 if (tile_has_extra(ptile
, pextra
)) {
2853 pplayer
->server
.huts
++;
2855 destroy_extra(ptile
, pextra
);
2856 update_tile_knowledge(unit_tile(punit
));
2858 if (behavior
== HUT_FRIGHTEN
) {
2859 notify_player(pplayer
, unit_tile(punit
), E_HUT_BARB
, ftc_server
,
2860 _("Your overflight frightens the tribe;"
2861 " they scatter in terror."));
2865 /* AI with H_LIMITEDHUTS only gets 25 gold (or barbs if unlucky) */
2866 if (pplayer
->ai_controlled
&& has_handicap(pplayer
, H_LIMITEDHUTS
)) {
2867 (void) hut_get_limited(punit
);
2871 /* FIXME: Should have parameter for hut extra type */
2872 script_server_signal_emit("hut_enter", 1,
2873 API_TYPE_UNIT
, punit
);
2875 } extra_type_by_category_iterate_end
;
2877 send_player_info_c(pplayer
, pplayer
->connections
); /* eg, gold */
2881 /****************************************************************************
2882 Put the unit onto the transporter, and tell everyone.
2883 ****************************************************************************/
2884 void unit_transport_load_send(struct unit
*punit
, struct unit
*ptrans
)
2886 fc_assert_ret(punit
!= NULL
);
2887 fc_assert_ret(ptrans
!= NULL
);
2889 unit_transport_load(punit
, ptrans
, FALSE
);
2891 send_unit_info(NULL
, punit
);
2892 send_unit_info(NULL
, ptrans
);
2895 /****************************************************************************
2896 Load unit to transport, send transport's loaded status to everyone.
2897 ****************************************************************************/
2898 static void unit_transport_load_tp_status(struct unit
*punit
,
2899 struct unit
*ptrans
,
2904 fc_assert_ret(punit
!= NULL
);
2905 fc_assert_ret(ptrans
!= NULL
);
2907 had_cargo
= get_transporter_occupancy(ptrans
) > 0;
2909 unit_transport_load(punit
, ptrans
, force
);
2912 /* Transport's loaded status changed */
2913 send_unit_info(NULL
, ptrans
);
2917 /****************************************************************************
2918 Pull the unit off of the transporter, and tell everyone.
2919 ****************************************************************************/
2920 void unit_transport_unload_send(struct unit
*punit
)
2922 struct unit
*ptrans
;
2924 fc_assert_ret(punit
);
2926 ptrans
= unit_transport_get(punit
);
2928 fc_assert_ret(ptrans
);
2930 unit_transport_unload(punit
);
2932 send_unit_info(NULL
, punit
);
2933 send_unit_info(NULL
, ptrans
);
2936 /*****************************************************************
2937 This function is passed to unit_list_sort() to sort a list of
2938 units according to their win chance against autoattack_x|y.
2939 If the unit is being transported, then push it to the front of
2940 the list, since we wish to leave its transport out of combat
2942 *****************************************************************/
2943 static int compare_units(const struct unit
*const *p1
,
2944 const struct unit
*const *q1
)
2946 struct unit
*p1def
= get_defender(*p1
, autoattack_target
);
2947 struct unit
*q1def
= get_defender(*q1
, autoattack_target
);
2948 int p1uwc
= unit_win_chance(*p1
, p1def
);
2949 int q1uwc
= unit_win_chance(*q1
, q1def
);
2951 if (p1uwc
< q1uwc
|| unit_transport_get(*q1
)) {
2952 return -1; /* q is better */
2953 } else if (p1uwc
== q1uwc
) {
2956 return 1; /* p is better */
2960 /*****************************************************************
2961 Can this unit be used in autoattack
2962 *****************************************************************/
2963 static bool is_suitable_autoattack_unit(struct unit
*punit
)
2965 if (unit_has_type_flag(punit
, UTYF_NUCLEAR
)) {
2966 /* Not a good idea to nuke our own area */
2973 /*****************************************************************
2974 Check if unit survives enemy autoattacks. We assume that any
2975 unit that is adjacent to us can see us.
2976 *****************************************************************/
2977 static bool unit_survive_autoattack(struct unit
*punit
)
2979 struct unit_list
*autoattack
;
2980 int moves
= punit
->moves_left
;
2981 int sanity1
= punit
->id
;
2983 if (!game
.server
.autoattack
) {
2987 autoattack
= unit_list_new();
2989 /* Kludge to prevent attack power from dropping to zero during calc */
2990 punit
->moves_left
= MAX(punit
->moves_left
, 1);
2992 adjc_iterate(unit_tile(punit
), ptile
) {
2993 /* First add all eligible units to a unit list */
2994 unit_list_iterate(ptile
->units
, penemy
) {
2995 struct player
*enemyplayer
= unit_owner(penemy
);
2996 enum diplstate_type ds
=
2997 player_diplstate_get(unit_owner(punit
), enemyplayer
)->type
;
2999 if (penemy
->moves_left
> 0
3001 && is_suitable_autoattack_unit(penemy
)
3002 && (unit_attack_unit_at_tile_result(penemy
, punit
, unit_tile(punit
))
3004 unit_list_prepend(autoattack
, penemy
);
3006 } unit_list_iterate_end
;
3009 /* The unit list is now sorted according to win chance against punit */
3010 autoattack_target
= unit_tile(punit
); /* global variable */
3011 if (unit_list_size(autoattack
) >= 2) {
3012 unit_list_sort(autoattack
, &compare_units
);
3015 unit_list_iterate_safe(autoattack
, penemy
) {
3016 int sanity2
= penemy
->id
;
3017 struct tile
*ptile
= unit_tile(penemy
);
3018 struct unit
*enemy_defender
= get_defender(punit
, ptile
);
3019 struct unit
*punit_defender
= get_defender(penemy
, unit_tile(punit
));
3020 double punitwin
, penemywin
;
3021 double threshold
= 0.25;
3023 fc_assert_action(NULL
!= punit_defender
, continue);
3025 if (tile_city(ptile
) && unit_list_size(ptile
->units
) == 1) {
3026 /* Don't leave city defenseless */
3030 if (NULL
!= enemy_defender
) {
3031 punitwin
= unit_win_chance(punit
, enemy_defender
);
3033 /* 'penemy' can attack 'punit' but it may be not reciproque. */
3036 penemywin
= unit_win_chance(penemy
, punit_defender
);
3038 if ((penemywin
> 1.0 - punitwin
3039 || utype_acts_hostile(unit_type_get(punit
))
3040 || get_transporter_capacity(punit
) > 0)
3041 && penemywin
> threshold
) {
3042 #ifdef REALLY_DEBUG_THIS
3043 log_test("AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3044 unit_rule_name(penemy
), unit_rule_name(punit
),
3045 TILE_XY(unit_tile(punit
)), penemywin
,
3046 1.0 - punitwin
, threshold
);
3049 unit_activity_handling(penemy
, ACTIVITY_IDLE
);
3051 (void) unit_move_handling(penemy
, unit_tile(punit
),
3054 #ifdef REALLY_DEBUG_THIS
3055 log_test("!AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3056 unit_rule_name(penemy
), unit_rule_name(punit
),
3057 TILE_XY(unit_tile(punit
)), penemywin
,
3058 1.0 - punitwin
, threshold
);
3063 if (game_unit_by_number(sanity2
)) {
3064 send_unit_info(NULL
, penemy
);
3066 if (game_unit_by_number(sanity1
)) {
3067 send_unit_info(NULL
, punit
);
3069 unit_list_destroy(autoattack
);
3070 return FALSE
; /* moving unit dead */
3072 } unit_list_iterate_safe_end
;
3074 unit_list_destroy(autoattack
);
3075 if (game_unit_by_number(sanity1
)) {
3076 /* We could have lost movement in combat */
3077 punit
->moves_left
= MIN(punit
->moves_left
, moves
);
3078 send_unit_info(NULL
, punit
);
3085 /****************************************************************************
3086 Cancel orders for the unit.
3087 ****************************************************************************/
3088 static void cancel_orders(struct unit
*punit
, char *dbg_msg
)
3090 free_unit_orders(punit
);
3091 send_unit_info(NULL
, punit
);
3092 log_debug("%s", dbg_msg
);
3095 /*****************************************************************
3096 Will wake up any neighboring enemy sentry units or patrolling
3098 *****************************************************************/
3099 static void wakeup_neighbor_sentries(struct unit
*punit
)
3103 if (NULL
!= tile_city(unit_tile(punit
))) {
3106 unit_list_iterate(unit_tile(punit
)->units
, aunit
) {
3107 /* Consider only units not transported. */
3108 if (!unit_transported(aunit
)) {
3111 } unit_list_iterate_end
;
3113 alone_in_city
= (1 == count
);
3115 alone_in_city
= FALSE
;
3118 /* There may be sentried units with a sightrange > 3, but we don't
3119 wake them up if the punit is farther away than 3. */
3120 square_iterate(unit_tile(punit
), 3, ptile
) {
3121 unit_list_iterate(ptile
->units
, penemy
) {
3122 int distance_sq
= sq_map_distance(unit_tile(punit
), ptile
);
3123 int radius_sq
= get_unit_vision_at(penemy
, unit_tile(penemy
), V_MAIN
);
3125 if (!pplayers_allied(unit_owner(punit
), unit_owner(penemy
))
3126 && penemy
->activity
== ACTIVITY_SENTRY
3127 && radius_sq
>= distance_sq
3128 /* If the unit moved on a city, and the unit is alone, consider
3131 || can_player_see_unit(unit_owner(penemy
), punit
))
3132 /* on board transport; don't awaken */
3133 && can_unit_exist_at_tile(penemy
, unit_tile(penemy
))) {
3134 set_unit_activity(penemy
, ACTIVITY_IDLE
);
3135 send_unit_info(NULL
, penemy
);
3137 } unit_list_iterate_end
;
3138 } square_iterate_end
;
3140 /* Wakeup patrolling units we bump into.
3141 We do not wakeup units further away than 3 squares... */
3142 square_iterate(unit_tile(punit
), 3, ptile
) {
3143 unit_list_iterate(ptile
->units
, ppatrol
) {
3144 if (punit
!= ppatrol
3145 && unit_has_orders(ppatrol
)
3146 && ppatrol
->orders
.vigilant
) {
3147 if (maybe_cancel_patrol_due_to_enemy(ppatrol
)) {
3148 cancel_orders(ppatrol
, " stopping because of nearby enemy");
3149 notify_player(unit_owner(ppatrol
), unit_tile(ppatrol
),
3150 E_UNIT_ORDERS
, ftc_server
,
3151 _("Orders for %s aborted after enemy movement was "
3153 unit_link(ppatrol
));
3156 } unit_list_iterate_end
;
3157 } square_iterate_end
;
3160 /**************************************************************************
3161 Does: 1) updates the unit's homecity and the city it enters/leaves (the
3162 city's happiness varies). This also takes into account when the
3163 unit enters/leaves a fortress.
3164 2) updates adjacent cities' unavailable tiles.
3166 FIXME: Sometimes it is not necessary to send cities because the goverment
3167 doesn't care whether a unit is away or not.
3168 **************************************************************************/
3169 static bool unit_move_consequences(struct unit
*punit
,
3170 struct tile
*src_tile
,
3171 struct tile
*dst_tile
,
3174 struct city
*fromcity
= tile_city(src_tile
);
3175 struct city
*tocity
= tile_city(dst_tile
);
3176 struct city
*homecity_start_pos
= NULL
;
3177 struct city
*homecity_end_pos
= NULL
;
3178 int homecity_id_start_pos
= punit
->homecity
;
3179 int homecity_id_end_pos
= punit
->homecity
;
3180 struct player
*pplayer_start_pos
= unit_owner(punit
);
3181 struct player
*pplayer_end_pos
= pplayer_start_pos
;
3182 struct unit_type
*type_start_pos
= unit_type_get(punit
);
3183 struct unit_type
*type_end_pos
= type_start_pos
;
3184 bool refresh_homecity_start_pos
= FALSE
;
3185 bool refresh_homecity_end_pos
= FALSE
;
3186 int saved_id
= punit
->id
;
3190 unit_enter_city(punit
, tocity
, passenger
);
3192 alive
= unit_is_alive(saved_id
);
3194 /* In case script has changed something about unit */
3195 pplayer_end_pos
= unit_owner(punit
);
3196 type_end_pos
= unit_type_get(punit
);
3197 homecity_id_end_pos
= punit
->homecity
;
3201 if (homecity_id_start_pos
!= 0) {
3202 homecity_start_pos
= game_city_by_number(homecity_id_start_pos
);
3204 if (homecity_id_start_pos
!= homecity_id_end_pos
) {
3205 homecity_end_pos
= game_city_by_number(homecity_id_end_pos
);
3207 homecity_end_pos
= homecity_start_pos
;
3210 /* We only do refreshes for non-AI players to now make sure the AI turns
3211 doesn't take too long. Perhaps we should make a special refresh_city
3212 functions that only refreshed happines. */
3214 /* might have changed owners or may be destroyed */
3215 tocity
= tile_city(dst_tile
);
3217 if (tocity
) { /* entering a city */
3218 if (tocity
->owner
== pplayer_end_pos
) {
3219 if (tocity
!= homecity_end_pos
&& !pplayer_end_pos
->ai_controlled
) {
3220 city_refresh(tocity
);
3221 send_city_info(pplayer_end_pos
, tocity
);
3224 if (homecity_start_pos
) {
3225 refresh_homecity_start_pos
= TRUE
;
3229 if (fromcity
) { /* leaving a city */
3230 if (homecity_start_pos
) {
3231 refresh_homecity_start_pos
= TRUE
;
3233 if (fromcity
!= homecity_start_pos
3234 && fromcity
->owner
== pplayer_start_pos
3235 && !pplayer_start_pos
->ai_controlled
) {
3236 city_refresh(fromcity
);
3237 send_city_info(pplayer_start_pos
, fromcity
);
3241 /* entering/leaving a fortress or friendly territory */
3242 if (homecity_start_pos
|| homecity_end_pos
) {
3243 if ((game
.info
.happyborders
!= HB_DISABLED
&& tile_owner(src_tile
) != tile_owner(dst_tile
))
3244 || (tile_has_base_flag_for_unit(dst_tile
,
3247 && is_friendly_city_near(pplayer_end_pos
, dst_tile
))
3248 || (tile_has_base_flag_for_unit(src_tile
,
3251 && is_friendly_city_near(pplayer_start_pos
, src_tile
))) {
3252 refresh_homecity_start_pos
= TRUE
;
3253 refresh_homecity_end_pos
= TRUE
;
3257 if (refresh_homecity_start_pos
&& !pplayer_start_pos
->ai_controlled
) {
3258 city_refresh(homecity_start_pos
);
3259 send_city_info(pplayer_start_pos
, homecity_start_pos
);
3261 if (refresh_homecity_end_pos
3262 && (!refresh_homecity_start_pos
3263 || homecity_start_pos
!= homecity_end_pos
)
3264 && !pplayer_end_pos
->ai_controlled
) {
3265 city_refresh(homecity_end_pos
);
3266 send_city_info(pplayer_end_pos
, homecity_end_pos
);
3269 city_map_update_tile_now(dst_tile
);
3275 /**************************************************************************
3276 Check if the units activity is legal for a move , and reset it if it isn't.
3277 **************************************************************************/
3278 static void check_unit_activity(struct unit
*punit
)
3280 switch (punit
->activity
) {
3282 case ACTIVITY_SENTRY
:
3283 case ACTIVITY_EXPLORE
:
3286 case ACTIVITY_POLLUTION
:
3288 case ACTIVITY_IRRIGATE
:
3289 case ACTIVITY_FORTIFIED
:
3290 case ACTIVITY_FORTRESS
:
3291 case ACTIVITY_PILLAGE
:
3292 case ACTIVITY_TRANSFORM
:
3293 case ACTIVITY_UNKNOWN
:
3294 case ACTIVITY_AIRBASE
:
3295 case ACTIVITY_FORTIFYING
:
3296 case ACTIVITY_FALLOUT
:
3297 case ACTIVITY_PATROL_UNUSED
:
3299 case ACTIVITY_GEN_ROAD
:
3300 case ACTIVITY_CONVERT
:
3301 case ACTIVITY_OLD_ROAD
:
3302 case ACTIVITY_OLD_RAILROAD
:
3304 set_unit_activity(punit
, ACTIVITY_IDLE
);
3309 /****************************************************************************
3310 Create a new unit move data, or use previous one if available.
3311 ****************************************************************************/
3312 static struct unit_move_data
*unit_move_data(struct unit
*punit
,
3313 struct tile
*psrctile
,
3314 struct tile
*pdesttile
)
3316 struct unit_move_data
*pdata
;
3317 struct player
*powner
= unit_owner(punit
);
3318 const v_radius_t radius_sq
=
3319 V_RADIUS(get_unit_vision_at(punit
, pdesttile
, V_MAIN
),
3320 get_unit_vision_at(punit
, pdesttile
, V_INVIS
));
3321 struct vision
*new_vision
;
3324 if (punit
->server
.moving
) {
3325 /* Recursive moving (probably due to a script). */
3326 pdata
= punit
->server
.moving
;
3328 fc_assert_msg(pdata
->punit
== punit
,
3329 "Unit number %d (%p) was going to die, but "
3330 "server attempts to move it.",
3332 fc_assert_msg(pdata
->old_vision
== NULL
,
3333 "Unit number %d (%p) has done an incomplete move.",
3336 pdata
= fc_malloc(sizeof(*pdata
));
3337 pdata
->ref_count
= 1;
3338 pdata
->punit
= punit
;
3339 punit
->server
.moving
= pdata
;
3340 BV_CLR_ALL(pdata
->can_see_unit
);
3342 pdata
->powner
= powner
;
3343 BV_CLR_ALL(pdata
->can_see_move
);
3344 pdata
->old_vision
= punit
->server
.vision
;
3346 /* Remove unit from the source tile. */
3347 fc_assert(unit_tile(punit
) == psrctile
);
3348 success
= unit_list_remove(psrctile
->units
, punit
);
3349 fc_assert(success
== TRUE
);
3352 unit_tile_set(punit
, pdesttile
);
3353 unit_list_prepend(pdesttile
->units
, punit
);
3355 if (unit_transported(punit
)) {
3356 /* Silently free orders since they won't be applicable anymore. */
3357 free_unit_orders(punit
);
3360 /* Check unit activity. */
3361 check_unit_activity(punit
);
3362 unit_did_action(punit
);
3363 unit_forget_last_activity(punit
);
3365 /* We first unfog the destination, then send the move,
3366 * and then fog the old territory. This means that the player
3367 * gets a chance to see the newly explored territory while the
3368 * client moves the unit, and both areas are visible during the
3371 /* Enhance vision if unit steps into a fortress */
3372 new_vision
= vision_new(powner
, pdesttile
);
3373 punit
->server
.vision
= new_vision
;
3374 vision_change_sight(new_vision
, radius_sq
);
3375 ASSERT_VISION(new_vision
);
3380 /****************************************************************************
3381 Decrease the reference counter and destroy if needed.
3382 ****************************************************************************/
3383 static void unit_move_data_unref(struct unit_move_data
*pdata
)
3385 fc_assert_ret(pdata
!= NULL
);
3386 fc_assert_ret(pdata
->ref_count
> 0);
3387 fc_assert_msg(pdata
->old_vision
== NULL
,
3388 "Unit number %d (%p) has done an incomplete move.",
3389 pdata
->punit
!= NULL
? pdata
->punit
->id
: -1, pdata
->punit
);
3392 if (pdata
->ref_count
== 0) {
3393 if (pdata
->punit
!= NULL
) {
3394 fc_assert(pdata
->punit
->server
.moving
== pdata
);
3395 pdata
->punit
->server
.moving
= NULL
;
3401 /*****************************************************************************
3402 Moves a unit. No checks whatsoever! This is meant as a practical
3403 function for other functions, like do_airline, which do the checking
3406 If you move a unit you should always use this function, as it also sets
3407 the transport status of the unit correctly. Note that the source tile (the
3408 current tile of the unit) and pdesttile need not be adjacent.
3410 Returns TRUE iff unit still alive.
3411 *****************************************************************************/
3412 bool unit_move(struct unit
*punit
, struct tile
*pdesttile
, int move_cost
,
3413 struct unit
*embark_to
)
3415 struct player
*pplayer
;
3416 struct tile
*psrctile
;
3418 struct unit
*ptransporter
;
3419 struct packet_unit_info src_info
, dest_info
;
3420 struct packet_unit_short_info src_sinfo
, dest_sinfo
;
3421 struct unit_move_data_list
*plist
=
3422 unit_move_data_list_new_full(unit_move_data_unref
);
3423 struct unit_move_data
*pdata
;
3427 enum direction8 facing
;
3428 struct player
*bowner
;
3431 fc_assert_ret_val(punit
!= NULL
, FALSE
);
3432 fc_assert_ret_val(pdesttile
!= NULL
, FALSE
);
3434 pplayer
= unit_owner(punit
);
3435 saved_id
= punit
->id
;
3436 psrctile
= unit_tile(punit
);
3437 adj
= base_get_direction_for_step(psrctile
, pdesttile
, &facing
);
3439 conn_list_do_buffer(game
.est_connections
);
3441 /* Unload the unit if on a transport. */
3442 ptransporter
= unit_transport_get(punit
);
3443 if (ptransporter
!= NULL
) {
3444 /* Unload unit _before_ setting the new tile! */
3445 unit_transport_unload(punit
);
3446 /* Send updated information to anyone watching that transporter
3447 * was unloading cargo. */
3448 send_unit_info(NULL
, ptransporter
);
3451 /* Wakup units next to us before we move. */
3452 wakeup_neighbor_sentries(punit
);
3454 /* Make info packets at 'psrctile'. */
3456 /* If tiles are adjacent, we will show the move to users able
3458 package_unit(punit
, &src_info
);
3459 package_short_unit(punit
, &src_sinfo
, UNIT_INFO_IDENTITY
, 0);
3462 /* Make new data for 'punit'. */
3463 pdata
= unit_move_data(punit
, psrctile
, pdesttile
);
3464 unit_move_data_list_prepend(plist
, pdata
);
3466 /* Set unit orientation */
3468 /* Only change orientation when moving to adjacent tile */
3469 punit
->facing
= facing
;
3473 punit
->moved
= TRUE
;
3474 punit
->moves_left
= MAX(0, punit
->moves_left
- move_cost
);
3475 if (punit
->moves_left
== 0 && !unit_has_orders(punit
)) {
3476 /* The next order may not require any remaining move fragments. */
3477 punit
->done_moving
= TRUE
;
3480 /* No longer relevant. */
3481 punit
->action_decision_tile
= NULL
;
3482 punit
->action_decision_want
= ACT_DEC_NOTHING
;
3485 && action_tgt_city(punit
, pdesttile
)) {
3486 /* The unit can perform an action to the city at the destination tile.
3487 * A long distance move (like an airlift) doesn't ask what action to
3488 * perform before moving. Ask now. */
3490 punit
->action_decision_want
= ACT_DEC_PASSIVE
;
3491 punit
->action_decision_tile
= pdesttile
;
3493 /* Let the client know that this unit wants the player to decide
3495 send_unit_info(player_reply_dest(pplayer
), punit
);
3498 /* Claim ownership of fortress? */
3499 bowner
= extra_owner(pdesttile
);
3500 if ((bowner
== NULL
|| pplayers_at_war(bowner
, pplayer
))
3501 && tile_has_claimable_base(pdesttile
, unit_type_get(punit
))) {
3502 /* Yes. We claim *all* bases if there's *any* claimable base(s).
3503 * Even if original unit cannot claim other kind of bases, the
3504 * first claimed base will have influence over other bases,
3505 * or something like that. */
3506 tile_claim_bases(pdesttile
, pplayer
);
3509 /* Move all contained units. */
3510 unit_cargo_iterate(punit
, pcargo
) {
3511 pdata
= unit_move_data(pcargo
, psrctile
, pdesttile
);
3512 unit_move_data_list_append(plist
, pdata
);
3513 } unit_cargo_iterate_end
;
3515 /* Get data for 'punit'. */
3516 pdata
= unit_move_data_list_front(plist
);
3518 /* Determine the players able to see the move(s), now that the player
3519 * vision has been increased. */
3521 /* Main unit for adjacent move: the move is visible for every player
3522 * able to see on the matching unit layer. */
3523 enum vision_layer vlayer
= is_hiding_unit(punit
) ? V_INVIS
: V_MAIN
;
3525 players_iterate(oplayer
) {
3526 if (map_is_known_and_seen(psrctile
, oplayer
, vlayer
)
3527 || map_is_known_and_seen(pdesttile
, oplayer
, vlayer
)) {
3528 BV_SET(pdata
->can_see_unit
, player_index(oplayer
));
3529 BV_SET(pdata
->can_see_move
, player_index(oplayer
));
3531 } players_iterate_end
;
3533 unit_move_data_list_iterate(plist
, pmove_data
) {
3534 if (adj
&& pmove_data
== pdata
) {
3535 /* If positions are adjacent, we have already handled 'punit'. See
3540 players_iterate(oplayer
) {
3542 && can_player_see_unit_at(oplayer
, pmove_data
->punit
, psrctile
,
3543 pmove_data
!= pdata
))
3544 || can_player_see_unit_at(oplayer
, pmove_data
->punit
, pdesttile
,
3545 pmove_data
!= pdata
)) {
3546 BV_SET(pmove_data
->can_see_unit
, player_index(oplayer
));
3547 BV_SET(pmove_data
->can_see_move
, player_index(oplayer
));
3549 if (can_player_see_unit_at(oplayer
, pmove_data
->punit
, psrctile
,
3550 pmove_data
!= pdata
)) {
3551 /* The unit was seen with its source tile even if it was
3553 BV_SET(pmove_data
->can_see_unit
, player_index(oplayer
));
3555 } players_iterate_end
;
3556 } unit_move_data_list_iterate_end
;
3558 /* Check timeout settings. */
3559 if (current_turn_timeout() != 0 && game
.server
.timeoutaddenemymove
> 0) {
3560 bool new_information_for_enemy
= FALSE
;
3562 phase_players_iterate(penemy
) {
3563 /* Increase the timeout if an enemy unit moves and the
3564 * timeoutaddenemymove setting is in use. */
3565 if (penemy
->is_connected
3566 && pplayer
!= penemy
3567 && pplayers_at_war(pplayer
, penemy
)
3568 && BV_ISSET(pdata
->can_see_move
, player_index(penemy
))) {
3569 new_information_for_enemy
= TRUE
;
3572 } phase_players_iterate_end
;
3574 if (new_information_for_enemy
) {
3575 increase_timeout_because_unit_moved();
3579 /* Notifications of the move to the clients. */
3581 /* Special case: 'punit' is moving to adjacent position. Then we show
3582 * 'punit' move to all users able to see 'psrctile' or 'pdesttile'. */
3584 /* Make info packets at 'pdesttile'. */
3585 package_unit(punit
, &dest_info
);
3586 package_short_unit(punit
, &dest_sinfo
, UNIT_INFO_IDENTITY
, 0);
3588 conn_list_iterate(game
.est_connections
, pconn
) {
3589 struct player
*aplayer
= conn_get_player(pconn
);
3591 if (aplayer
== NULL
) {
3592 if (pconn
->observer
) {
3593 /* Global observers see all... */
3594 send_packet_unit_info(pconn
, &src_info
);
3595 send_packet_unit_info(pconn
, &dest_info
);
3597 } else if (BV_ISSET(pdata
->can_see_move
, player_index(aplayer
))) {
3598 if (aplayer
== pplayer
) {
3599 send_packet_unit_info(pconn
, &src_info
);
3600 send_packet_unit_info(pconn
, &dest_info
);
3602 send_packet_unit_short_info(pconn
, &src_sinfo
, FALSE
);
3603 send_packet_unit_short_info(pconn
, &dest_sinfo
, FALSE
);
3606 } conn_list_iterate_end
;
3610 unit_move_data_list_iterate(plist
, pmove_data
) {
3611 if (adj
&& pmove_data
== pdata
) {
3612 /* If positions are adjacent, we have already shown 'punit' move.
3617 /* Make info packets at 'pdesttile'. */
3618 package_unit(pmove_data
->punit
, &dest_info
);
3619 package_short_unit(pmove_data
->punit
, &dest_sinfo
,
3620 UNIT_INFO_IDENTITY
, 0);
3622 conn_list_iterate(game
.est_connections
, pconn
) {
3623 struct player
*aplayer
= conn_get_player(pconn
);
3625 if (aplayer
== NULL
) {
3626 if (pconn
->observer
) {
3627 /* Global observers see all... */
3628 send_packet_unit_info(pconn
, &dest_info
);
3630 } else if (BV_ISSET(pmove_data
->can_see_move
, player_index(aplayer
))) {
3631 if (aplayer
== pmove_data
->powner
) {
3632 send_packet_unit_info(pconn
, &dest_info
);
3634 send_packet_unit_short_info(pconn
, &dest_sinfo
, FALSE
);
3637 } conn_list_iterate_end
;
3638 } unit_move_data_list_iterate_end
;
3640 /* Clear old vision. */
3641 unit_move_data_list_iterate(plist
, pmove_data
) {
3642 vision_clear_sight(pmove_data
->old_vision
);
3643 vision_free(pmove_data
->old_vision
);
3644 pmove_data
->old_vision
= NULL
;
3645 } unit_move_data_list_iterate_end
;
3647 /* Move consequences. */
3648 unit_move_data_list_iterate(plist
, pmove_data
) {
3649 struct unit
*aunit
= pmove_data
->punit
;
3652 && unit_owner(aunit
) == pmove_data
->powner
3653 && unit_tile(aunit
) == pdesttile
) {
3654 (void) unit_move_consequences(aunit
, psrctile
, pdesttile
,
3655 pdata
!= pmove_data
);
3657 } unit_move_data_list_iterate_end
;
3659 unit_lives
= (pdata
->punit
== punit
);
3661 /* Wakeup units and make contact. */
3663 wakeup_neighbor_sentries(punit
);
3665 maybe_make_contact(pdesttile
, pplayer
);
3668 /* Special checks for ground units in the ocean. */
3669 if (embark_to
|| !can_unit_survive_at_tile(punit
, pdesttile
)) {
3670 if (embark_to
!= NULL
) {
3671 ptransporter
= embark_to
;
3673 ptransporter
= transporter_for_unit(punit
);
3676 unit_transport_load_tp_status(punit
, ptransporter
, FALSE
);
3678 /* Set activity to sentry if boarding a ship. */
3679 if (!pplayer
->ai_controlled
3680 && !unit_has_orders(punit
)
3681 && !punit
->ai_controlled
3682 && !can_unit_exist_at_tile(punit
, pdesttile
)) {
3683 set_unit_activity(punit
, ACTIVITY_SENTRY
);
3686 send_unit_info(NULL
, punit
);
3691 /* Remove units going out of sight. */
3692 unit_move_data_list_iterate_rev(plist
, pmove_data
) {
3693 struct unit
*aunit
= pmove_data
->punit
;
3695 if (aunit
== NULL
) {
3696 continue; /* Died! */
3699 players_iterate(aplayer
) {
3700 if (BV_ISSET(pmove_data
->can_see_unit
, player_index(aplayer
))
3701 && !can_player_see_unit(aplayer
, aunit
)) {
3702 unit_goes_out_of_sight(aplayer
, aunit
);
3704 } players_iterate_end
;
3705 } unit_move_data_list_iterate_rev_end
;
3707 /* Inform the owner's client about actor unit arrival. Can, depending on
3708 * the client settings, cause the client to start the process that makes
3709 * the action selection dialog pop up. */
3710 if ((pcity
= tile_city(pdesttile
))) {
3711 /* Arrival in a city counts. */
3713 unit_move_data_list_iterate(plist
, pmove_data
) {
3714 struct unit
*ptrans
;
3716 struct unit
*act_unit
;
3717 struct player
*act_player
;
3719 act_unit
= pmove_data
->punit
;
3720 act_player
= unit_owner(act_unit
);
3722 if (act_unit
== NULL
3723 || !unit_is_alive(act_unit
->id
)) {
3724 /* The unit died before reaching this point. */
3728 if (unit_tile(act_unit
) != pdesttile
) {
3729 /* The unit didn't arrive at the destination tile. */
3733 if (act_player
->ai_controlled
) {
3734 /* The AI doesn't need reminders. */
3738 if (!unit_transported(act_unit
)) {
3739 /* Don't show the action selection dialog again. Non transported
3740 * units are handled before they move to the tile. */
3744 /* Open action dialog only if 'act_unit' and all its transporters
3745 * (recursively) don't have orders. */
3746 if (unit_has_orders(act_unit
)) {
3747 /* The unit it self has orders. */
3751 for (ptrans
= unit_transport_get(act_unit
);;
3752 ptrans
= unit_transport_get(ptrans
)) {
3753 if (NULL
== ptrans
) {
3754 /* No (recursive) transport has orders. */
3757 } else if (unit_has_orders(ptrans
)) {
3758 /* A unit transporting the unit has orders */
3765 /* A unit transporting act_unit has orders. */
3769 if (action_tgt_city(act_unit
, pdesttile
)) {
3770 /* There is a valid target. */
3772 act_unit
->action_decision_want
= ACT_DEC_PASSIVE
;
3773 act_unit
->action_decision_tile
= pdesttile
;
3775 /* Let the client know that this unit wants the player to decide
3777 send_unit_info(player_reply_dest(act_player
), act_unit
);
3779 } unit_move_data_list_iterate_end
;
3782 unit_move_data_list_destroy(plist
);
3784 /* Check cities at source and destination. */
3785 if ((pcity
= tile_city(psrctile
))) {
3786 refresh_dumb_city(pcity
);
3788 if ((pcity
= tile_city(pdesttile
))) {
3789 refresh_dumb_city(pcity
);
3793 /* Let the scripts run ... */
3794 script_server_signal_emit("unit_moved", 3,
3795 API_TYPE_UNIT
, punit
,
3796 API_TYPE_TILE
, psrctile
,
3797 API_TYPE_TILE
, pdesttile
);
3798 unit_lives
= unit_is_alive(saved_id
);
3803 unit_lives
= unit_survive_autoattack(punit
);
3807 /* Is there a hut? */
3808 if (tile_has_cause_extra(pdesttile
, EC_HUT
)) {
3809 unit_enter_hut(punit
);
3810 unit_lives
= unit_is_alive(saved_id
);
3814 conn_list_do_unbuffer(game
.est_connections
);
3819 /**************************************************************************
3820 Maybe cancel the goto if there is an enemy in the way
3821 **************************************************************************/
3822 static bool maybe_cancel_goto_due_to_enemy(struct unit
*punit
,
3825 return (is_non_allied_unit_tile(ptile
, unit_owner(punit
))
3826 || is_non_allied_city_tile(ptile
, unit_owner(punit
)));
3829 /**************************************************************************
3830 Maybe cancel the patrol as there is an enemy near.
3832 If you modify the wakeup range you should change it in
3833 wakeup_neighbor_sentries() too.
3834 **************************************************************************/
3835 static bool maybe_cancel_patrol_due_to_enemy(struct unit
*punit
)
3837 bool cancel
= FALSE
;
3838 int radius_sq
= get_unit_vision_at(punit
, unit_tile(punit
), V_MAIN
);
3839 struct player
*pplayer
= unit_owner(punit
);
3841 circle_iterate(unit_tile(punit
), radius_sq
, ptile
) {
3842 struct unit
*penemy
= is_non_allied_unit_tile(ptile
, pplayer
);
3844 struct vision_site
*pdcity
= map_get_player_site(ptile
, pplayer
);
3846 if ((penemy
&& can_player_see_unit(pplayer
, penemy
))
3847 || (pdcity
&& !pplayers_allied(pplayer
, vision_site_owner(pdcity
))
3848 && pdcity
->occupied
)) {
3852 } circle_iterate_end
;
3857 /**************************************************************************
3858 Returns TRUE iff punit currently don't have enough move fragments to
3859 perform the specified action but will have it next turn.
3860 **************************************************************************/
3861 static bool should_wait_for_mp(struct unit
*punit
, int action_id
)
3863 return !utype_may_act_move_frags(unit_type_get(punit
),
3866 && utype_may_act_move_frags(unit_type_get(punit
),
3868 unit_move_rate(punit
));
3871 /**************************************************************************
3872 Returns the action id corresponding to the specified order id.
3873 **************************************************************************/
3874 static int order_to_action(struct unit
*punit
, enum unit_orders order
)
3877 case ORDER_BUILD_WONDER
:
3878 return ACTION_HELP_WONDER
;
3879 case ORDER_TRADE_ROUTE
:
3880 return ACTION_TRADE_ROUTE
;
3882 case ORDER_ACTION_MOVE
:
3884 case ORDER_BUILD_CITY
:
3885 case ORDER_ACTIVITY
:
3887 case ORDER_HOMECITY
:
3889 /* Not action enabler controlled. */
3893 fc_assert_msg(FALSE
, "No action to map order to.");
3894 return ACTION_COUNT
;
3897 /**************************************************************************
3898 Returns TRUE iff it is reasonable to assume that the player is wathing
3901 Since the player is watching the unit there is no need to inform him
3902 about things he could see happening. Remember that it still may
3903 be necessary to explain why something happened.
3904 **************************************************************************/
3905 static inline bool player_is_watching(struct unit
*punit
, const bool fresh
)
3907 /* The player just sent the orders to the unit. The unit has moves left.
3908 * It is therefore safe to assume that the player already is paying
3909 * attention to the unit. */
3910 return fresh
&& punit
->moves_left
> 0;
3913 /****************************************************************************
3914 Executes a unit's orders stored in punit->orders. The unit is put on idle
3915 if an action fails or if "patrol" is set and an enemy unit is encountered.
3917 The return value will be TRUE if the unit lives, FALSE otherwise. (This
3918 function used to return a goto_result enumeration, declared in gotohand.h.
3919 But this enumeration was never checked by the caller and just lead to
3920 confusion. All the caller really needs to know is if the unit lived or
3921 died; everything else is handled internally within execute_orders.)
3923 If the orders are repeating the loop starts over at the beginning once it
3924 completes. To avoid infinite loops on railroad we stop for this
3925 turn when the unit is back where it started, even if it have moves left.
3927 A unit will attack under orders only on its final action.
3929 The fresh parameter is true if the order execution happens because the
3930 orders just were received.
3931 ****************************************************************************/
3932 bool execute_orders(struct unit
*punit
, const bool fresh
)
3934 struct tile
*dst_tile
;
3935 bool res
, last_order
;
3936 int unitid
= punit
->id
;
3937 struct player
*pplayer
= unit_owner(punit
);
3939 enum unit_activity activity
;
3941 fc_assert_ret_val(unit_has_orders(punit
), TRUE
);
3943 if (punit
->activity
!= ACTIVITY_IDLE
) {
3944 /* Unit's in the middle of an activity; wait for it to finish. */
3945 punit
->done_moving
= TRUE
;
3949 log_debug("Executing orders for %s %d", unit_rule_name(punit
), punit
->id
);
3951 /* Any time the orders are canceled we should give the player a message. */
3954 struct unit_order order
;
3956 if (punit
->done_moving
) {
3957 log_debug(" stopping because we're done this turn");
3961 if (punit
->orders
.vigilant
&& maybe_cancel_patrol_due_to_enemy(punit
)) {
3962 /* "Patrol" orders are stopped if an enemy is near. */
3963 cancel_orders(punit
, " stopping because of nearby enemy");
3964 notify_player(pplayer
, unit_tile(punit
), E_UNIT_ORDERS
, ftc_server
,
3965 _("Orders for %s aborted as there are units nearby."),
3970 if (moves_made
== punit
->orders
.length
) {
3971 /* For repeating orders, don't repeat more than once per turn. */
3972 log_debug(" stopping because we ran a round");
3973 punit
->done_moving
= TRUE
;
3974 send_unit_info(NULL
, punit
);
3979 order
= punit
->orders
.list
[punit
->orders
.index
];
3981 switch (order
.order
) {
3983 case ORDER_ACTION_MOVE
:
3985 case ORDER_BUILD_CITY
:
3986 if (0 == punit
->moves_left
) {
3987 log_debug(" stopping because of no more move points");
3991 case ORDER_BUILD_WONDER
:
3992 case ORDER_TRADE_ROUTE
:
3993 if (should_wait_for_mp(punit
, order_to_action(punit
, order
.order
))) {
3994 log_debug(" stopping. Not enough move points this turn");
3998 case ORDER_ACTIVITY
:
4000 case ORDER_HOMECITY
:
4002 /* Those actions don't require moves left. */
4006 last_order
= (!punit
->orders
.repeat
4007 && punit
->orders
.index
+ 1 == punit
->orders
.length
);
4010 /* Clear the orders before we engage in the move. That way any
4011 * has_orders checks will yield FALSE and this will be treated as
4012 * a normal move. This is important: for instance a caravan goto
4013 * will popup the caravan dialog on the last move only. */
4014 free_unit_orders(punit
);
4017 /* Advance the orders one step forward. This is needed because any
4018 * updates sent to the client as a result of the action should include
4019 * the new index value. Note that we have to send_unit_info somewhere
4020 * after this point so that the client is properly updated. */
4021 punit
->orders
.index
++;
4023 switch (order
.order
) {
4025 if (punit
->moves_left
< unit_move_rate(punit
)) {
4026 /* If the unit doesn't have full MP then it just waits until the
4027 * next turn. We assume that the next turn it will have full MP
4028 * (there's no check for that). */
4029 punit
->done_moving
= TRUE
;
4030 log_debug(" waiting this turn");
4031 send_unit_info(NULL
, punit
);
4034 case ORDER_BUILD_CITY
:
4035 unit_build_city(pplayer
, punit
,
4036 city_name_suggestion(pplayer
, unit_tile(punit
)));
4037 log_debug(" building city");
4038 if (player_unit_by_number(pplayer
, unitid
)) {
4040 cancel_orders(punit
, " orders canceled; failed to build city");
4041 notify_player(pplayer
, unit_tile(punit
), E_UNIT_ORDERS
, ftc_server
,
4042 _("Orders for %s aborted because building "
4047 /* Build succeeded => unit "died" */
4050 case ORDER_ACTIVITY
:
4051 activity
= order
.activity
;
4053 struct extra_type
*pextra
= (order
.target
== EXTRA_NONE
?
4055 extra_by_number(order
.target
));
4057 if (pextra
== NULL
&& activity_requires_target(order
.activity
)) {
4058 /* Try to find a target extra before giving up this order or, if
4059 * serious enough, all orders. */
4061 enum unit_activity new_activity
= order
.activity
;
4063 unit_assign_specific_activity_target(punit
,
4064 &new_activity
, &pextra
);
4066 if (new_activity
!= order
.activity
) {
4067 /* At the time this code was written the only possible activity
4068 * change from unit_assign_specific_activity_target() was from
4069 * ACTIVITY_PILLAGE to ACTIVITY_IDLE. That would only happen
4070 * when a target extra couldn't be found. -- Sveinung */
4071 fc_assert_msg((order
.activity
== ACTIVITY_PILLAGE
4072 && new_activity
== ACTIVITY_IDLE
),
4073 "Skipping an order when canceling all orders may"
4074 " have been the correct thing to do.");
4076 /* Already removed, let's continue. */
4080 /* Should have given up or, if supported, changed the order's
4081 * activity to the activity suggested by
4082 * unit_activity_handling_targeted() before this line was
4084 * Remember that unit_activity_handling_targeted() has the power
4085 * to change the order's target extra directly. */
4086 fc_assert_msg(new_activity
== order
.activity
,
4087 "Activity not updated. Target may have changed.");
4089 /* Should have found a target or given up before reaching this
4091 fc_assert_msg((pextra
!= NULL
4092 || !activity_requires_target(order
.activity
)),
4093 "Activity requires a target. No target found.");
4096 if (can_unit_do_activity_targeted(punit
, activity
, pextra
)) {
4097 punit
->done_moving
= TRUE
;
4098 set_unit_activity_targeted(punit
, activity
, pextra
);
4099 send_unit_info(NULL
, punit
);
4102 if ((activity
== ACTIVITY_BASE
4103 || activity
== ACTIVITY_GEN_ROAD
4104 || activity
== ACTIVITY_IRRIGATE
4105 || activity
== ACTIVITY_MINE
)
4106 && tile_has_extra(unit_tile(punit
), pextra
)) {
4107 break; /* Already built, let's continue. */
4108 } else if ((activity
== ACTIVITY_POLLUTION
4109 || activity
== ACTIVITY_FALLOUT
4110 || activity
== ACTIVITY_PILLAGE
)
4111 && !tile_has_extra(unit_tile(punit
), pextra
)) {
4112 break; /* Already removed, let's continue. */
4117 cancel_orders(punit
, " orders canceled because of failed activity");
4118 notify_player(pplayer
, unit_tile(punit
), E_UNIT_ORDERS
, ftc_server
,
4119 _("Orders for %s aborted since they "
4120 "give an invalid activity."),
4124 case ORDER_ACTION_MOVE
:
4126 if (!(dst_tile
= mapstep(unit_tile(punit
), order
.dir
))) {
4127 cancel_orders(punit
, " move order sent us to invalid location");
4128 notify_player(pplayer
, unit_tile(punit
), E_UNIT_ORDERS
, ftc_server
,
4129 _("Orders for %s aborted since they "
4130 "give an invalid location."),
4135 if (order
.order
!= ORDER_ACTION_MOVE
4136 && maybe_cancel_goto_due_to_enemy(punit
, dst_tile
)) {
4137 /* Plain move required: no attack, trade route etc. */
4138 cancel_orders(punit
, " orders canceled because of enemy");
4139 notify_player(pplayer
, unit_tile(punit
), E_UNIT_ORDERS
, ftc_server
,
4140 _("Orders for %s aborted as there "
4141 "are units in the way."),
4146 log_debug(" moving to %d,%d", TILE_XY(dst_tile
));
4147 res
= unit_move_handling(punit
, dst_tile
, FALSE
,
4148 order
.order
!= ORDER_ACTION_MOVE
, NULL
);
4149 if (!player_unit_by_number(pplayer
, unitid
)) {
4150 log_debug(" unit died while moving.");
4151 /* A player notification should already have been sent. */
4155 if (res
&& !same_pos(dst_tile
, unit_tile(punit
))) {
4156 /* Movement succeeded but unit didn't move. */
4157 log_debug(" orders resulted in combat.");
4158 send_unit_info(NULL
, punit
);
4163 fc_assert(0 <= punit
->moves_left
);
4165 /* Movement failed (ZOC, etc.) */
4166 cancel_orders(punit
, " attempt to move failed.");
4168 if (!player_is_watching(punit
, fresh
)
4169 /* The final move "failed" because the unit needs to ask the
4170 * player what action it should take.
4172 * The action decision request notifies the player. Its
4173 * location at the unit's last order makes it clear to the
4174 * player who the decision is for. ("The Spy I sent to Berlin
4177 * A notification message is therefore redundant. */
4179 && punit
->action_decision_want
== ACT_DEC_ACTIVE
4180 && punit
->action_decision_tile
== dst_tile
)) {
4181 /* The player may have missed this. No one else will announce it
4182 * in a satisfying manner. Inform the player. */
4183 notify_player(pplayer
, unit_tile(punit
),
4184 E_UNIT_ORDERS
, ftc_server
,
4185 _("Orders for %s aborted because of failed move."),
4193 log_debug(" orders: disbanding");
4194 handle_unit_disband(pplayer
, unitid
);
4196 case ORDER_HOMECITY
:
4197 log_debug(" orders: changing homecity");
4198 if (tile_city(unit_tile(punit
))) {
4199 handle_unit_change_homecity(pplayer
, unitid
,
4200 tile_city(unit_tile(punit
))->id
);
4202 cancel_orders(punit
, " no homecity");
4203 notify_player(pplayer
, unit_tile(punit
), E_UNIT_ORDERS
, ftc_server
,
4204 _("Attempt to change homecity for %s failed."),
4209 case ORDER_TRADE_ROUTE
:
4210 log_debug(" orders: establishing trade route.");
4211 dst_tile
= unit_tile(punit
);
4213 fc_assert_ret_val_msg(dst_tile
, FALSE
, "No tile for ordered unit");
4215 if (tile_city(dst_tile
) == NULL
) {
4216 cancel_orders(punit
, " trade route order with no city");
4217 notify_player(pplayer
, unit_tile(punit
), E_UNIT_ORDERS
, ftc_server
,
4218 _("Orders for %s aborted since they "
4219 "give a location without a city."),
4224 handle_unit_do_action(pplayer
,
4225 unitid
, tile_city(dst_tile
)->id
,
4226 0, ACTION_TRADE_ROUTE
);
4227 if (player_unit_by_number(pplayer
, unitid
)) {
4228 cancel_orders(punit
, " no trade route city");
4229 notify_player(pplayer
, unit_tile(punit
), E_UNIT_ORDERS
, ftc_server
,
4230 _("Attempt to establish trade route for %s failed."),
4236 case ORDER_BUILD_WONDER
:
4237 log_debug(" orders: building wonder");
4238 dst_tile
= unit_tile(punit
);
4240 fc_assert_ret_val_msg(dst_tile
, FALSE
, "No tile for ordered unit");
4242 if (tile_city(dst_tile
) == NULL
) {
4243 cancel_orders(punit
, " build wonder order with no city");
4244 notify_player(pplayer
, unit_tile(punit
), E_UNIT_ORDERS
, ftc_server
,
4245 _("Orders for %s aborted since they "
4246 "give a location without a city."),
4251 handle_unit_do_action(pplayer
,
4253 tile_city(dst_tile
)->id
,
4254 0, ACTION_HELP_WONDER
);
4255 if (player_unit_by_number(pplayer
, unitid
)) {
4256 cancel_orders(punit
, " no wonder city");
4257 notify_player(pplayer
, unit_tile(punit
), E_UNIT_ORDERS
, ftc_server
,
4258 _("Attempt to build wonder for %s failed."),
4265 cancel_orders(punit
, " client sent invalid order!");
4266 notify_player(pplayer
, unit_tile(punit
), E_UNIT_ORDERS
, ftc_server
,
4267 _("Your %s has invalid orders."),
4273 fc_assert(punit
->has_orders
== FALSE
);
4274 log_debug(" stopping because orders are complete");
4278 if (punit
->orders
.index
== punit
->orders
.length
) {
4279 fc_assert(punit
->orders
.repeat
);
4281 log_debug(" repeating orders.");
4282 punit
->orders
.index
= 0;
4287 /****************************************************************************
4288 Return the vision the unit will have at the given tile. The base vision
4289 range may be modified by effects.
4291 Note that vision MUST be independent of transported_by for this to work
4293 ****************************************************************************/
4294 int get_unit_vision_at(struct unit
*punit
, struct tile
*ptile
,
4295 enum vision_layer vlayer
)
4297 const int base
= (unit_type_get(punit
)->vision_radius_sq
4298 + get_unittype_bonus(unit_owner(punit
), ptile
,
4299 unit_type_get(punit
),
4300 EFT_UNIT_VISION_RADIUS_SQ
));
4305 return MIN(base
, 2);
4310 log_error("Unsupported vision layer variant: %d.", vlayer
);
4314 /****************************************************************************
4315 Refresh the unit's vision.
4317 This function has very small overhead and can be called any time effects
4318 may have changed the vision range of the city.
4319 ****************************************************************************/
4320 void unit_refresh_vision(struct unit
*punit
)
4322 struct vision
*uvision
= punit
->server
.vision
;
4323 const v_radius_t radius_sq
=
4324 V_RADIUS(get_unit_vision_at(punit
, unit_tile(punit
), V_MAIN
),
4325 get_unit_vision_at(punit
, unit_tile(punit
), V_INVIS
));
4327 vision_change_sight(uvision
, radius_sq
);
4328 ASSERT_VISION(uvision
);
4331 /****************************************************************************
4332 Refresh the vision of all units in the list - see unit_refresh_vision.
4333 ****************************************************************************/
4334 void unit_list_refresh_vision(struct unit_list
*punitlist
)
4336 unit_list_iterate(punitlist
, punit
) {
4337 unit_refresh_vision(punit
);
4338 } unit_list_iterate_end
;
4341 /****************************************************************************
4342 Used to implement the game rule controlled by the unitwaittime setting.
4343 Notifies the unit owner if the unit is unable to act.
4344 ****************************************************************************/
4345 bool unit_can_do_action_now(const struct unit
*punit
)
4353 if (game
.server
.unitwaittime
<= 0) {
4357 if (punit
->server
.action_turn
!= game
.info
.turn
- 1) {
4361 dt
= time(NULL
) - punit
->server
.action_timestamp
;
4362 if (dt
< game
.server
.unitwaittime
) {
4364 format_time_duration(game
.server
.unitwaittime
- dt
, buf
, sizeof(buf
));
4365 notify_player(unit_owner(punit
), unit_tile(punit
), E_BAD_COMMAND
,
4366 ftc_server
, _("Your unit may not act for another %s "
4367 "this turn. See /help unitwaittime."), buf
);
4374 /****************************************************************************
4375 Mark a unit as having done something at the current time. This is used
4376 in conjunction with unit_can_do_action_now() and the unitwaittime setting.
4377 ****************************************************************************/
4378 void unit_did_action(struct unit
*punit
)
4384 punit
->server
.action_timestamp
= time(NULL
);
4385 punit
->server
.action_turn
= game
.info
.turn
;
4388 /**************************************************************************
4389 Barbarian units may disband spontaneously if their age is more than
4390 BARBARIAN_MIN_LIFESPAN, they are not in cities, and they are far from
4391 any enemy units. It is to remove barbarians that do not engage into any
4392 activity for a long time.
4393 **************************************************************************/
4394 bool unit_can_be_retired(struct unit
*punit
)
4396 /* check if there is enemy nearby */
4397 square_iterate(unit_tile(punit
), 3, ptile
) {
4398 if (is_enemy_city_tile(ptile
, unit_owner(punit
))
4399 || is_enemy_unit_tile(ptile
, unit_owner(punit
))) {