Freeciv-3.2: /fast/freeciv/nightly/S3_2/server/unithand.c Source File

Freeciv-3.2

Loading...
Searching...
No Matches
unithand.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
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***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21
22/* dependencies/lua */
23#include "lua.h" /* lua_Integer */
24
25/* utility */
26#include "astring.h"
27#include "fcintl.h"
28#include "mem.h"
29#include "rand.h"
30#include "shared.h"
31
32/* common */
33#include "actions.h"
34#include "ai.h"
35#include "city.h"
36#include "combat.h"
37#include "events.h"
38#include "featured_text.h"
39#include "game.h"
40#include "log.h"
41#include "map.h"
42#include "movement.h"
43#include "packets.h"
44#include "player.h"
45#include "research.h"
46#include "specialist.h"
47#include "traderoutes.h"
48#include "unit.h"
49#include "unitlist.h"
50
51/* common/scriptcore */
52#include "luascript_types.h"
53
54/* server */
55#include "actiontools.h"
56#include "barbarian.h"
57#include "citizenshand.h"
58#include "citytools.h"
59#include "cityturn.h"
60#include "diplomats.h"
61#include "maphand.h"
62#include "notify.h"
63#include "plrhand.h"
64#include "sanitycheck.h"
65#include "spacerace.h"
66#include "srv_main.h"
67#include "techtools.h"
68#include "unittools.h"
69
70/* server/advisors */
71#include "autoexplorer.h"
72#include "autosettlers.h"
73
74/* server/scripting */
75#include "script_server.h"
76
77#include "unithand.h"
78
79/* An explanation why an action isn't enabled. */
80 struct ane_expl {
81 /* The kind of reason why an action isn't enabled. */
82 enum ane_kind kind;
83
84 union {
85 /* The city without the needed capacity- */
86 struct city *capacity_city;
87
88 /* The bad terrain in question. */
89 struct terrain *no_act_terrain;
90
91 /* The player to advice declaring war on. */
92 struct player *no_war_with;
93
94 /* The player to advice breaking peace with. */
95 struct player *peace_with;
96
97 /* The nation that can't be involved. */
98 struct nation_type *no_act_nation;
99
100 /* The unit type that can't be targeted. */
101 const struct unit_type *no_tgt_utype;
102
103 /* The action that blocks the action. */
104 struct action *blocker;
105
106 /* The required distance. */
107 int distance;
108
109 /* The required amount of gold. */
110 int gold_needed;
111 };
112};
113
114static bool unit_activity_internal(struct unit *punit,
115 enum unit_activity new_activity);
116static bool unit_activity_targeted_internal(struct unit *punit,
117 enum unit_activity new_activity,
118 struct extra_type **new_target);
119static void illegal_action(struct player *pplayer,
120 struct unit *actor,
121 action_id stopped_action,
122 struct player *tgt_player,
123 struct tile *target_tile,
124 const struct city *target_city,
125 const struct unit *target_unit,
126 int request_kind,
127 const enum action_requester requester);
128static bool city_add_unit(struct player *pplayer, struct unit *punit,
129 struct city *pcity, const struct action *paction);
130static bool city_build(struct player *pplayer, struct unit *punit,
131 struct tile *ptile, const char *name,
132 const struct action *paction);
133static bool do_unit_establish_trade(struct player *pplayer,
134 struct unit *punit,
135 struct city *pcity_dest,
136 const struct action *paction);
137
138static bool unit_do_help_build(struct player *pplayer,
139 struct unit *punit,
140 struct city *pcity_dest,
141 const struct action *paction);
142static bool unit_do_regular_move(struct player *actor_player,
143 struct unit *actor_unit,
144 struct tile *target_tile,
145 const struct action *paction);
146static bool unit_bombard(struct unit *punit, struct tile *ptile,
147 const struct action *paction);
148static bool unit_nuke(struct player *pplayer, struct unit *punit,
149 struct tile *def_tile,
150 const struct action *paction);
151static bool unit_do_destroy_city(struct player *act_player,
152 struct unit *act_unit,
153 struct city *tgt_city,
154 const struct action *paction);
155static bool do_unit_change_homecity(struct unit *punit,
156 struct city *pcity,
157 const struct action *paction);
158static bool do_attack(struct unit *actor_unit, struct tile *target_tile,
159 const struct action *paction);
160static bool do_unit_strike_city_production(struct player *act_player,
161 struct unit *act_unit,
162 struct city *tgt_city,
163 const struct action *paction);
164static bool do_unit_strike_city_building(struct player *act_player,
165 struct unit *act_unit,
166 struct city *tgt_city,
167 Impr_type_id tgt_bld_id,
168 const struct action *paction);
169static bool do_unit_conquer_city(struct player *act_player,
170 struct unit *act_unit,
171 struct city *tgt_city,
172 struct action *paction);
173static bool do_action_activity(struct unit *punit,
174 const struct action *paction);
175static bool do_action_activity_targeted(struct unit *punit,
176 const struct action *paction,
177 struct extra_type **new_target);
178static inline bool
179 non_allied_not_listed_at(const struct player *pplayer,
180 const int *list, int n, const struct tile *ptile);
181
182/**********************************************************************/
185 void handle_unit_type_upgrade(struct player *pplayer, Unit_type_id uti)
186{
187 const struct unit_type *to_unittype;
188 struct unit_type *from_unittype = utype_by_number(uti);
189 int number_of_upgraded_units = 0;
190 struct action *paction = action_by_number(ACTION_UPGRADE_UNIT);
191 const struct civ_map *nmap = &(wld.map);
192
193 if (NULL == from_unittype) {
194 /* Probably died or bribed. */
195 log_verbose("handle_unit_type_upgrade() invalid unit type %d", uti);
196 return;
197 }
198
199 to_unittype = can_upgrade_unittype(pplayer, from_unittype);
200 if (!to_unittype) {
201 notify_player(pplayer, NULL, E_BAD_COMMAND, ftc_server,
202 _("Illegal packet, can't upgrade %s (yet)."),
203 utype_name_translation(from_unittype));
204 return;
205 }
206
207 /*
208 * Try to upgrade units. The order we upgrade in is arbitrary (if
209 * the player really cared they should have done it manually).
210 */
211 conn_list_do_buffer(pplayer->connections);
212 unit_list_iterate(pplayer->units, punit) {
213 if (unit_type_get(punit) == from_unittype) {
214 struct city *pcity = tile_city(unit_tile(punit));
215
216 if (is_action_enabled_unit_on_city(nmap, paction->id, punit, pcity)
217 && unit_perform_action(pplayer, punit->id, pcity->id, 0, "",
218 paction->id, ACT_REQ_SS_AGENT)) {
219 number_of_upgraded_units++;
220 } else if (UU_NO_MONEY == unit_upgrade_test(nmap, punit, FALSE)) {
221 break;
222 }
223 }
224 } unit_list_iterate_end;
225 conn_list_do_unbuffer(pplayer->connections);
226
227 /* Alert the player about what happened. */
228 if (number_of_upgraded_units > 0) {
229 const int cost = unit_upgrade_price(pplayer, from_unittype, to_unittype);
230 notify_player(pplayer, NULL, E_UNIT_UPGRADED, ftc_server,
231 /* FIXME: plurality of number_of_upgraded_units ignored!
232 * (Plurality of unit names is messed up anyway.) */
233 /* TRANS: "2 Musketeers upgraded to Riflemen for 100 gold."
234 * Plurality is in gold (second %d), not units. */
235 PL_("%d %s upgraded to %s for %d gold.",
236 "%d %s upgraded to %s for %d gold.",
237 cost * number_of_upgraded_units),
238 number_of_upgraded_units,
239 utype_name_translation(from_unittype),
240 utype_name_translation(to_unittype),
241 cost * number_of_upgraded_units);
242 send_player_info_c(pplayer, pplayer->connections);
243 } else {
244 notify_player(pplayer, NULL, E_UNIT_UPGRADED, ftc_server,
245 _("No units could be upgraded."));
246 }
247}
248
249/**********************************************************************/
255 static bool do_unit_upgrade(struct player *pplayer,
256 struct unit *punit, struct city *pcity,
257 enum action_requester ordered_by,
258 const struct action *paction)
259{
260 const struct unit_type *from_unit = unit_type_get(punit);
261 const struct unit_type *to_unit = can_upgrade_unittype(pplayer, from_unit);
262 int cost = unit_upgrade_price(pplayer, from_unit, to_unit);
263
264 transform_unit(punit, to_unit, game.server.upgrade_veteran_loss);
265 pplayer->economic.gold -= cost;
266 send_player_info_c(pplayer, pplayer->connections);
267
268 if (ordered_by == ACT_REQ_PLAYER) {
269 notify_player(pplayer, unit_tile(punit), E_UNIT_UPGRADED, ftc_server,
270 PL_("%s upgraded to %s for %d gold.",
271 "%s upgraded to %s for %d gold.", cost),
272 utype_name_translation(from_unit),
273 unit_link(punit),
274 cost);
275 }
276
277 return TRUE;
278}
279
280/**********************************************************************/
284static inline bool
285non_allied_not_listed_at(const struct player *pplayer,
286 const int *list, int n, const struct tile *ptile)
287{
288 unit_list_iterate(ptile->units, punit) {
289 if (!pplayers_allied(pplayer, unit_owner(punit))) {
290 bool listed = FALSE;
291 int id = punit->id;
292 int i;
293
294 for (i = 0; i < n; i++) {
295 if (id == list[i]) {
296 listed = TRUE;
297 break;
298 }
299 }
300 if (!listed) {
301 return TRUE;
302 }
303 }
304 } unit_list_iterate_end;
305 return FALSE;
306}
307
308/**********************************************************************/
314 static bool do_capture_units(struct player *pplayer,
315 struct unit *punit,
316 struct tile *pdesttile,
317 const struct action *paction)
318{
319 struct city *pcity;
320 char capturer_link[MAX_LEN_LINK];
321 char hcity_name[MAX_LEN_NAME] = {'\0'};
322 const char *capturer_nation = nation_plural_for_player(pplayer);
323 bv_unit_types unique_on_tile;
324 const struct unit_type *act_utype;
325 int id, hcity;
326 int n = 0, capt[unit_list_size(pdesttile->units)];
327 bool lost_with_city = FALSE;
328 int i;
329
330 /* Sanity check: The actor still exists. */
331 fc_assert_ret_val(pplayer, FALSE);
332 fc_assert_ret_val(punit, FALSE);
333 id = punit->id;
334
335 act_utype = unit_type_get(punit);
336
337 /* Sanity check: make sure that the capture won't result in the actor
338 * ending up with more than one unit of each unique unit type. */
339 BV_CLR_ALL(unique_on_tile);
340 unit_list_iterate(pdesttile->units, to_capture) {
341 bool unique_conflict = FALSE;
342
343 /* Check what the player already has. */
344 if (utype_player_already_has_this_unique(pplayer,
345 unit_type_get(to_capture))) {
346 /* The player already has a unit of this kind. */
347 unique_conflict = TRUE;
348 }
349
350 if (utype_has_flag(unit_type_get(to_capture), UTYF_UNIQUE)) {
351 /* The type of the units at the tile must also be checked. Two allied
352 * players can both have their unique unit at the same tile.
353 * Capturing them both would give the actor two units of a kind that
354 * is supposed to be unique. */
355
356 if (BV_ISSET(unique_on_tile, utype_index(unit_type_get(to_capture)))) {
357 /* There is another unit of the same kind at this tile. */
358 unique_conflict = TRUE;
359 } else {
360 /* Remember the unit type in case another unit of the same kind is
361 * encountered later. */
362 BV_SET(unique_on_tile, utype_index(unit_type_get(to_capture)));
363 }
364 }
365
366 if (unique_conflict) {
367 log_debug("capture units: already got unique unit");
368 notify_player(pplayer, pdesttile, E_UNIT_ILLEGAL_ACTION, ftc_server,
369 /* TRANS: You can only have one Leader. */
370 _("You can only have one %s."),
371 unit_link(to_capture));
372
373 return FALSE;
374 }
375 /* Remember the units here
376 * for the mess callbacks may do in the process of transferring */
377 capt[n++] = to_capture->id;
378 } unit_list_iterate_end;
379
380 /* N.B: unit_link() always returns the same pointer. */
381 sz_strlcpy(capturer_link, unit_link(punit));
382
383 pcity = tile_city(pdesttile);
384 hcity = game.server.homecaughtunits
385 ? punit->homecity : IDENTITY_NUMBER_ZERO;
386 if (hcity) {
387 /* Rarely, we'll need it... */
388 sz_strlcpy(hcity_name, city_name_get(game_city_by_number(hcity)));
389 }
390
391 for (i = 0; i < n; i++) {
392 struct unit *to_capture = game_unit_by_number(capt[i]);
393 struct player *uplayer;
394 const char *victim_link;
395 const struct unit_type *utype;
396 struct tile *ptile = NULL;
397 bool really_lost = FALSE;
398
399 if (!to_capture) {
400 continue;
401 }
402 uplayer = unit_owner(to_capture);
403 if (uplayer == pplayer) {
404 /* Somehow transferred by scripts (e.g. diplomat incited a city) */
405 continue;
406 }
407 utype = unit_type_get(to_capture);
408 really_lost = lost_with_city && !utype_has_flag(utype, UTYF_NOHOME);
409 uplayer->score.units_lost++;
410 if (!really_lost) {
411 /* A hack: if the captured unit is lost with a capturer's city,
412 * we link the old unit, otherwise the new one */
413 to_capture = unit_change_owner(to_capture, pplayer,
414 hcity, ULR_CAPTURED);
415 }
416 if (!to_capture) {
417 /* Lost during capturing */
418 victim_link = utype_name_translation(utype);
419 } else {
420 /* As unit_change_owner() currently remove the old unit and
421 * replace by a new one (with a new id), we want to make link to
422 * the new unit. */
423 victim_link = unit_link(to_capture);
424 ptile = unit_tile(to_capture);
425 /* Notify capturer only if there is a gain */
426 notify_player(pplayer, pdesttile, E_MY_DIPLOMAT_BRIBE, ftc_server,
427 /* TRANS: <unit> ... <unit> */
428 _("Your %s succeeded in capturing the %s %s."),
429 capturer_link, nation_adjective_for_player(uplayer),
430 victim_link);
431 }
432
433 /* Notify loser */
434 notify_player(uplayer, pdesttile,
435 E_ENEMY_DIPLOMAT_BRIBE, ftc_server,
436 /* TRANS: <unit> ... <Poles> */
437 _("Your %s was captured by the %s."),
438 victim_link, capturer_nation);
439
440 /* May cause an incident */
441 action_consequence_success(paction, pplayer, act_utype, uplayer,
442 pdesttile, victim_link);
443
444 if (really_lost) {
445 /* The city for which the unit was captured has perished! */
446 /* Nobody actually gets the unit. */
447 pplayer->score.units_lost++;
448 notify_player(pplayer, pdesttile,
449 E_UNIT_LOST_MISC, ftc_server,
450 _("%s lost along with control of %s."),
451 victim_link, hcity_name);
452 /* As in unit_change_owner(), don't say pplayer is killer */
453 wipe_unit(to_capture, ULR_CAPTURED, NULL);
454 continue;
455 }
456
457 if (to_capture
458 && (NULL != pcity /* Keep old behavior */
459 || is_non_allied_city_tile(ptile, unit_owner(to_capture))
460 || (unit_owner(to_capture) == pplayer
461 ? non_allied_not_listed_at(pplayer, capt + (i + 1),
462 n - (i + 1), ptile)
463 : (bool)
464 is_non_allied_unit_tile(ptile, unit_owner(to_capture))))) {
465 /* The captured unit is in a city or with a foreign unit
466 * that its owner is not capturing. Bounce it. */
467 bounce_unit(to_capture, TRUE);
468 }
469
470 /* Check if the city we are going to home units in stays. */
471 if (hcity && i + 1 < n && !player_city_by_number(pplayer, hcity)) {
472 /* Oops, it's lost. Maybe the capturer is rehomed? */
473 if (player_unit_by_number(pplayer, id)) {
474 /* Well, it's natural to home them here now */
475 hcity = punit->homecity;
476 } else {
477 /* Removing the rest of the stack (except "NoHome" units) */
478 lost_with_city = TRUE;
479 }
480 }
481 }
482
483 if (!unit_is_alive(id)) {
484 /* Callbacks took the capturer, nothing more to do */
485 return TRUE;
486 }
487 unit_did_action(punit);
488 unit_forget_last_activity(punit);
489
490 send_unit_info(NULL, punit);
491
492 return TRUE;
493}
494
495/**********************************************************************/
498 static bool occupy_move(struct tile *def_tile, struct unit *punit,
499 const struct action *paction)
500{
501 if (!is_non_allied_unit_tile(def_tile, unit_owner(punit))) {
502 /* Hack: make sure the unit has enough moves_left for the move to succeed,
503 * and adjust moves_left to afterward (if successful). */
504 int old_moves = punit->moves_left;
505 int full_moves = unit_move_rate(punit);
506 int id = punit->id;
507
508 punit->moves_left = full_moves;
509 /* Post attack occupy move. */
510 if (NULL != action_auto_perf_unit_do(AAPC_POST_ACTION, punit,
511 NULL, NULL, paction,
512 def_tile, tile_city(def_tile),
513 NULL, NULL)) {
514 if (unit_is_alive(id)) {
515 int mcost = MAX(0, full_moves - punit->moves_left - SINGLE_MOVE);
516
517 /* Move cost is bigger of attack (SINGLE_MOVE) and occupying move costs.
518 * Attack SINGLE_COST is already calculated in to old_moves. */
519 punit->moves_left = old_moves - mcost;
520 if (punit->moves_left < 0) {
521 punit->moves_left = 0;
522 }
523 } else {
524 return FALSE;
525 }
526 } else if (unit_is_alive(id)) {
527 punit->moves_left = old_moves;
528 } else {
529 return FALSE;
530 }
531 }
532
533 return TRUE;
534}
535
536/**********************************************************************/
542 static bool do_wipe_units(struct unit *punit,
543 struct tile *pdesttile,
544 const struct action *paction)
545{
546 struct player *wiper = unit_owner(punit);
547 int wid = punit->id;
548 char wiper_link[MAX_LEN_LINK];
549 const char *wiper_nation = nation_plural_for_player(wiper);
550 const struct unit_type *act_utype = unit_type_get(punit);
551
552 /* N.B: unit_link() always returns the same pointer. */
553 sz_strlcpy(wiper_link, unit_link(punit));
554
555 unit_list_iterate_safe(pdesttile->units, to_wipe) {
556 struct player *owner = unit_owner(to_wipe);
557 const char *victim_link = unit_link(to_wipe);
558
559 wipe_unit(to_wipe, ULR_KILLED, wiper);
560
561 /* Notify players */
562 notify_player(wiper, pdesttile, E_UNIT_WIN_ATT, ftc_server,
563 /* TRANS: <unit> ... <unit> */
564 _("Your %s wiped the %s %s."),
565 wiper_link, nation_adjective_for_player(owner),
566 victim_link);
567 notify_player(owner, pdesttile,
568 E_UNIT_LOST_DEF, ftc_server,
569 /* TRANS: <unit> ... <Poles> */
570 _("Your %s was wiped by the %s."),
571 victim_link, wiper_nation);
572
573 /* May cause an incident */
574 action_consequence_success(paction, wiper, act_utype, owner,
575 pdesttile, victim_link);
576
577 } unit_list_iterate_safe_end;
578
579 if (unit_is_alive(wid) && occupy_move(pdesttile, punit, paction)) {
580 unit_did_action(punit);
581 unit_forget_last_activity(punit);
582
583 send_unit_info(NULL, punit);
584 }
585
586 return TRUE;
587}
588
589/**********************************************************************/
595 static bool do_expel_unit(struct player *pplayer,
596 struct unit *actor,
597 struct unit *target,
598 const struct action *paction)
599{
600 char target_link[MAX_LEN_LINK];
601 struct player *uplayer;
602 struct tile *target_tile;
603 struct city *pcity;
604 const struct unit_type *act_utype;
605
606 /* Maybe it didn't survive the Lua call back. Why wasn't this caught by
607 * the caller? Check in the code that emits the signal. */
608 fc_assert_ret_val(target, FALSE);
609
610 uplayer = unit_owner(target);
611
612 /* A unit is supposed to have an owner. */
613 fc_assert_ret_val(uplayer, FALSE);
614
615 /* Maybe it didn't survive the Lua call back. Why wasn't this caught by
616 * the caller? Check in the code that emits the signal. */
617 fc_assert_ret_val(actor, FALSE);
618 act_utype = unit_type_get(actor);
619
620 /* Where is the actor player? */
621 fc_assert_ret_val(pplayer, FALSE);
622
623 target_tile = unit_tile(target);
624
625 /* Expel the target unit to its owner's primary capital. */
626 /* TODO: Could be also nearest secondary capital */
627 pcity = player_primary_capital(uplayer);
628
629 /* N.B: unit_link() always returns the same pointer. */
630 sz_strlcpy(target_link, unit_link(target));
631
632 if (pcity == NULL) {
633 /* No where to send the expelled unit. */
634
635 /* The price of failing an expulsion is a single move. */
636 actor->moves_left = MAX(0, actor->moves_left - SINGLE_MOVE);
637 send_unit_info(NULL, actor);
638
639 /* Notify the actor player. */
640 notify_player(pplayer, target_tile, E_UNIT_ACTION_FAILED, ftc_server,
641 /* TRANS: <Poles> <Spy> */
642 _("The %s don't have a capital to expel their %s to."),
643 nation_plural_for_player(uplayer), target_link);
644
645 /* Nothing more could be done. */
646 return FALSE;
647 }
648
649 /* Please review the code below and above (including the strings sent to
650 * the players) before allowing expulsion to non capital cities. */
651 fc_assert(is_capital(pcity));
652
653 /* Notify everybody involved. */
654 notify_player(pplayer, target_tile, E_UNIT_DID_EXPEL, ftc_server,
655 /* TRANS: <Border Patrol> ... <Spy> */
656 _("Your %s succeeded in expelling the %s %s."),
657 unit_link(actor), nation_adjective_for_player(uplayer),
658 target_link);
659 notify_player(uplayer, target_tile, E_UNIT_WAS_EXPELLED, ftc_server,
660 /* TRANS: <unit> ... <Poles> */
661 _("Your %s was expelled by the %s."),
662 target_link, nation_plural_for_player(pplayer));
663
664 /* Being expelled destroys all remaining movement. */
665 if (!teleport_unit_to_city(target, pcity, 0, FALSE)) {
666 log_error("Bug in unit expulsion: unit can't teleport.");
667
668 return FALSE;
669 }
670
671 /* This may cause a diplomatic incident */
672 action_consequence_success(paction, pplayer, act_utype, uplayer,
673 target_tile, target_link);
674
675 /* Mission accomplished. */
676 return TRUE;
677}
678
679/**********************************************************************/
685 static bool do_conquer_extras(struct player *act_player,
686 struct unit *act_unit,
687 struct tile *tgt_tile,
688 const struct action *paction)
689{
690 bool success;
691 int move_cost = map_move_cost_unit(&(wld.map), act_unit, tgt_tile);
692 struct player *tgt_player = extra_owner(tgt_tile);
693
694 /* Sanity check */
695 fc_assert_ret_val(act_unit, FALSE);
696 fc_assert_ret_val(tgt_tile, FALSE);
697
698 unit_move(act_unit, tgt_tile, move_cost,
699 NULL, BV_ISSET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK),
700 FALSE, TRUE,
701 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
702 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_FRIGHTEN));
703
704 success = extra_owner(tgt_tile) == act_player;
705
706 if (success) {
707 const struct unit_type *act_utype = unit_type_get(act_unit);
708
709 /* May cause an incident */
710 action_consequence_success(paction, act_player, act_utype,
711 tgt_player, tgt_tile,
712 tile_link(tgt_tile));
713 }
714
715 return success;
716}
717
718/**********************************************************************/
724 static bool do_heal_unit(struct player *act_player,
725 struct unit *act_unit,
726 struct unit *tgt_unit,
727 const struct action *paction)
728{
729 int healing_limit;
730 int tgt_hp_max;
731 struct player *tgt_player;
732 struct tile *tgt_tile;
733 char act_unit_link[MAX_LEN_LINK];
734 char tgt_unit_link[MAX_LEN_LINK];
735 const char *tgt_unit_owner;
736 const struct unit_type *act_utype;
737
738 /* Sanity checks: got all the needed input. */
739 fc_assert_ret_val(act_player, FALSE);
740 fc_assert_ret_val(act_unit, FALSE);
741 fc_assert_ret_val(tgt_unit, FALSE);
742
743 act_utype = unit_type_get(act_unit);
744
745 /* The target unit can't have more HP than this. */
746 tgt_hp_max = unit_type_get(tgt_unit)->hp;
747
748 /* Sanity check: target isn't at full health and can therefore can be
749 * healed. */
750 fc_assert_ret_val(tgt_unit->hp < tgt_hp_max, FALSE);
751
752 /* Fetch the target unit's owner. */
753 tgt_player = unit_owner(tgt_unit);
754 fc_assert_ret_val(tgt_player, FALSE);
755
756 /* Fetch the target unit's tile. */
757 tgt_tile = unit_tile(tgt_unit);
758 fc_assert_ret_val(tgt_tile, FALSE);
759
760 /* The max amount of HP that can be added. */
761 healing_limit = ((get_target_bonus_effects(
762 NULL,
763 &(const struct req_context) {
764 .player = unit_owner(act_unit),
765 .city = tile_city(unit_tile(act_unit)),
766 .tile = unit_tile(act_unit),
767 .unit = act_unit,
768 .unittype = unit_type_get(act_unit),
769 .action = paction,
770 },
771 unit_owner(tgt_unit),
772 EFT_HEAL_UNIT_PCT
773 ) + 100)
774 * tgt_hp_max) / 100;
775
776 /* Heal the target unit. */
777 tgt_unit->hp = MIN(tgt_unit->hp + healing_limit, tgt_hp_max);
778 send_unit_info(NULL, tgt_unit);
779
780 send_unit_info(NULL, act_unit);
781
782 /* Every call to unit_link() overwrites the previous. Two units are being
783 * linked to. */
784 sz_strlcpy(act_unit_link, unit_link(act_unit));
785 sz_strlcpy(tgt_unit_link, unit_link(tgt_unit));
786
787 /* Notify everybody involved. */
788 if (act_player == tgt_player) {
789 /* TRANS: used instead of nation adjective when the nation is
790 * domestic. */
791 tgt_unit_owner = _("your");
792 } else {
793 tgt_unit_owner = nation_adjective_for_player(unit_nationality(tgt_unit));
794 }
795
796 notify_player(act_player, tgt_tile, E_MY_UNIT_DID_HEAL, ftc_server,
797 /* TRANS: If foreign: Your Leader heals Finnish Warrior.
798 * If domestic: Your Leader heals your Warrior. */
799 _("Your %s heals %s %s."),
800 act_unit_link, tgt_unit_owner, tgt_unit_link);
801
802 if (act_player != tgt_player) {
803 notify_player(tgt_player, tgt_tile, E_MY_UNIT_WAS_HEALED, ftc_server,
804 /* TRANS: Norwegian ... Leader ... Warrior */
805 _("%s %s heals your %s."),
806 nation_adjective_for_player(unit_nationality(act_unit)),
807 act_unit_link, tgt_unit_link);
808 }
809
810 /* This may have diplomatic consequences. */
811 action_consequence_success(paction, act_player, act_utype, tgt_player,
812 tgt_tile, unit_link(tgt_unit));
813
814 return TRUE;
815}
816
817/**********************************************************************/
823 static bool do_unit_deboard(struct player *act_player,
824 struct unit *act_unit,
825 struct unit *tgt_unit,
826 const struct action *paction)
827{
828 /* Unload the unit and send out info to clients. */
829 unit_transport_unload_send(act_unit);
830
831 return TRUE;
832}
833
834/**********************************************************************/
842 static bool do_unit_board(struct player *act_player,
843 struct unit *act_unit,
844 struct unit *tgt_unit,
845 const struct action *paction)
846{
847 if (unit_transported(act_unit)) {
848 unit_transport_unload(act_unit);
849 }
850
851 /* Load the unit and send out info to clients. */
852 unit_transport_load_send(act_unit, tgt_unit);
853
854 return TRUE;
855}
856
857/**********************************************************************/
865 static bool do_unit_load(struct player *act_player,
866 struct unit *act_unit,
867 struct unit *tgt_unit,
868 const struct action *paction)
869{
870 if (unit_transported(tgt_unit)) {
871 unit_transport_unload(tgt_unit);
872 }
873
874 /* Load the unit and send out info to clients. */
875 unit_transport_load_send(tgt_unit, act_unit);
876
877 return TRUE;
878}
879
880/**********************************************************************/
886 static bool do_unit_unload(struct player *act_player,
887 struct unit *act_unit,
888 struct unit *tgt_unit,
889 const struct action *paction)
890{
891 /* Unload the unit and send out info to clients. */
892 unit_transport_unload_send(tgt_unit);
893
894 return TRUE;
895}
896
897/**********************************************************************/
903 static bool do_disembark(struct player *act_player,
904 struct unit *act_unit,
905 struct tile *tgt_tile,
906 const struct action *paction)
907{
908 int move_cost = map_move_cost_unit(&(wld.map), act_unit, tgt_tile);
909
910 /* Sanity checks */
911 fc_assert_ret_val(act_player, FALSE);
912 fc_assert_ret_val(act_unit, FALSE);
913 fc_assert_ret_val(tgt_tile, FALSE);
914 fc_assert_ret_val(paction, FALSE);
915
916 unit_move(act_unit, tgt_tile, move_cost,
917 NULL, BV_ISSET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK),
918 FALSE, FALSE,
919 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
920 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_FRIGHTEN));
921
922 return TRUE;
923}
924
925/**********************************************************************/
931 static bool do_unit_hut(struct player *act_player,
932 struct unit *act_unit,
933 struct tile *tgt_tile,
934 const struct action *paction)
935{
936 int move_cost = map_move_cost_unit(&(wld.map), act_unit, tgt_tile);
937
938 /* Sanity checks */
939 fc_assert_ret_val(act_player, FALSE);
940 fc_assert_ret_val(act_unit, FALSE);
941 fc_assert_ret_val(tgt_tile, FALSE);
942 fc_assert_ret_val(paction, FALSE);
943
944 unit_move(act_unit, tgt_tile, move_cost,
945 NULL, BV_ISSET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK),
946 FALSE, FALSE,
947 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
948 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_FRIGHTEN));
949
950 return TRUE;
951}
952
953/**********************************************************************/
961 static bool do_unit_embark(struct player *act_player,
962 struct unit *act_unit,
963 struct unit *tgt_unit,
964 const struct action *paction)
965{
966 struct tile *tgt_tile;
967 int move_cost;
968
969 /* Sanity checks */
970 fc_assert_ret_val(act_player, FALSE);
971 fc_assert_ret_val(act_unit, FALSE);
972 fc_assert_ret_val(tgt_unit, FALSE);
973 fc_assert_ret_val(paction, FALSE);
974
975 if (unit_transported(act_unit)) {
976 /* Assumed to be legal. */
977 unit_transport_unload(act_unit);
978 }
979
980 /* Do it. */
981 tgt_tile = unit_tile(tgt_unit);
982 move_cost = map_move_cost_unit(&(wld.map), act_unit, tgt_tile);
983 unit_move(act_unit, tgt_tile, move_cost,
984 tgt_unit, BV_ISSET(paction->sub_results,
985 ACT_SUB_RES_MAY_EMBARK),
986 FALSE, FALSE,
987 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
988 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_FRIGHTEN));
989
990 return TRUE;
991}
992
993/**********************************************************************/
998 static bool do_unit_make_homeless(struct unit *punit,
999 const struct action *paction)
1000{
1001 unit_change_homecity_handling(punit, NULL, TRUE);
1002
1003 return punit->homecity == IDENTITY_NUMBER_ZERO;
1004}
1005
1006/**********************************************************************/
1013 static bool rel_may_become_war(const struct player *pplayer,
1014 const struct player *oplayer)
1015{
1016 enum diplstate_type ds;
1017
1018 fc_assert_ret_val(pplayer, FALSE);
1019 fc_assert_ret_val(oplayer, FALSE);
1020
1021 ds = player_diplstate_get(pplayer, oplayer)->type;
1022
1023 /* The player can't declare war on
1024 * someone they already are at war with. */
1025 return ds != DS_WAR
1026 /* The player can't declare war on a teammate or on themself. */
1027 && ds != DS_TEAM && pplayer != oplayer;
1028}
1029
1030/**********************************************************************/
1036static bool
1037need_war_enabler(const struct unit_type *actor_utype,
1038 const struct action *paction,
1039 struct player *player1,
1040 struct player *player2,
1041 bool act_if_diplrel_kind(const struct unit_type *,
1042 const action_id,
1043 const int,
1044 const bool))
1045{
1046 if (player2 == NULL) {
1047 /* No one to declare war on */
1048 return FALSE;
1049 }
1050
1051 if (!rel_may_become_war(player1, player2)) {
1052 /* Can't declare war. */
1053 return FALSE;
1054 }
1055
1056 if (act_if_diplrel_kind(actor_utype, paction->id,
1057 player_diplstate_get(player1,
1058 player2)->type,
1059 TRUE)) {
1060 /* The current diplrel isn't the problem. */
1061 return FALSE;
1062 }
1063
1064 if (!act_if_diplrel_kind(actor_utype, paction->id, DS_WAR, TRUE)) {
1065 /* War won't make this action legal. */
1066 return FALSE;
1067 }
1068
1069 return TRUE;
1070}
1071
1072/**********************************************************************/
1078 static struct player *need_war_player_hlp(const struct unit *actor,
1079 const action_id act,
1080 const struct tile *target_tile,
1081 const struct city *target_city,
1082 const struct unit *target_unit)
1083{
1084 struct player *target_player = NULL;
1085 struct player *actor_player = unit_owner(actor);
1086 struct action *paction = action_by_number(act);
1087
1088 fc_assert_ret_val(paction != NULL, NULL);
1089
1090 if (action_id_get_actor_kind(act) != AAK_UNIT) {
1091 /* No unit can ever do this action so it isn't relevant. */
1092 return NULL;
1093 }
1094
1095 if (!unit_can_do_action(actor, act)) {
1096 /* The unit can't do the action no matter if there is war or not. */
1097 return NULL;
1098 }
1099
1100 /* Look for hard coded war requirements without support for looking up in
1101 * an action enabler requirement. */
1102 switch (paction->result) {
1103 case ACTRES_ATTACK:
1104 case ACTRES_WIPE_UNITS:
1105 case ACTRES_COLLECT_RANSOM:
1106 /* Target is a unit stack but a city can block it. */
1107 fc_assert_action(action_get_target_kind(paction) == ATK_UNITS, break);
1108
1109 if (target_tile) {
1110 struct city *tcity;
1111
1112 if ((tcity = tile_city(target_tile))
1113 && rel_may_become_war(unit_owner(actor), city_owner(tcity))) {
1114 return city_owner(tcity);
1115 }
1116 }
1117 break;
1118
1119 case ACTRES_PARADROP:
1120 case ACTRES_PARADROP_CONQUER:
1121 /* Target is a tile but a city can block it. */
1122 fc_assert_action(action_get_target_kind(paction) == ATK_TILE, break);
1123 if (target_tile != NULL
1124 && map_is_known_and_seen(target_tile, actor_player, V_MAIN)) {
1125 /* Seen tile unit savers */
1126
1127 struct city *tcity;
1128
1129 if ((tcity = tile_non_attack_city(target_tile, actor_player))) {
1130 return city_owner(tcity);
1131 }
1132 }
1133 break;
1134 case ACTRES_CONQUER_EXTRAS:
1135 case ACTRES_ESTABLISH_EMBASSY:
1136 case ACTRES_SPY_INVESTIGATE_CITY:
1137 case ACTRES_SPY_POISON:
1138 case ACTRES_SPY_SPREAD_PLAGUE:
1139 case ACTRES_SPY_STEAL_GOLD:
1140 case ACTRES_SPY_SABOTAGE_CITY:
1141 case ACTRES_SPY_TARGETED_SABOTAGE_CITY:
1142 case ACTRES_SPY_SABOTAGE_CITY_PRODUCTION:
1143 case ACTRES_SPY_STEAL_TECH:
1144 case ACTRES_SPY_TARGETED_STEAL_TECH:
1145 case ACTRES_SPY_INCITE_CITY:
1146 case ACTRES_TRADE_ROUTE:
1147 case ACTRES_MARKETPLACE:
1148 case ACTRES_HELP_WONDER:
1149 case ACTRES_SPY_BRIBE_UNIT:
1150 case ACTRES_SPY_SABOTAGE_UNIT:
1151 case ACTRES_CAPTURE_UNITS: /* Only foreign is a hard req. */
1152 case ACTRES_FOUND_CITY:
1153 case ACTRES_JOIN_CITY:
1154 case ACTRES_STEAL_MAPS:
1155 case ACTRES_SPY_NUKE:
1156 case ACTRES_NUKE:
1157 case ACTRES_NUKE_UNITS:
1158 case ACTRES_DESTROY_CITY:
1159 case ACTRES_EXPEL_UNIT:
1160 case ACTRES_DISBAND_UNIT_RECOVER:
1161 case ACTRES_DISBAND_UNIT:
1162 case ACTRES_HOME_CITY:
1163 case ACTRES_HOMELESS:
1164 case ACTRES_UPGRADE_UNIT:
1165 case ACTRES_AIRLIFT:
1166 case ACTRES_HEAL_UNIT:
1167 case ACTRES_STRIKE_BUILDING:
1168 case ACTRES_STRIKE_PRODUCTION:
1169 case ACTRES_BOMBARD:
1170 case ACTRES_CONQUER_CITY:
1171 case ACTRES_TRANSFORM_TERRAIN:
1172 case ACTRES_CULTIVATE:
1173 case ACTRES_PLANT:
1174 case ACTRES_PILLAGE:
1175 case ACTRES_CLEAN:
1176 case ACTRES_FORTIFY:
1177 case ACTRES_CONVERT:
1178 case ACTRES_ROAD:
1179 case ACTRES_BASE:
1180 case ACTRES_MINE:
1181 case ACTRES_IRRIGATE:
1182 case ACTRES_TRANSPORT_DEBOARD:
1183 case ACTRES_TRANSPORT_UNLOAD:
1184 case ACTRES_TRANSPORT_DISEMBARK:
1185 case ACTRES_TRANSPORT_BOARD:
1186 case ACTRES_TRANSPORT_LOAD:
1187 case ACTRES_TRANSPORT_EMBARK:
1188 case ACTRES_SPY_ATTACK:
1189 case ACTRES_HUT_ENTER:
1190 case ACTRES_HUT_FRIGHTEN:
1191 case ACTRES_UNIT_MOVE:
1192 case ACTRES_TELEPORT:
1193 case ACTRES_TELEPORT_CONQUER:
1194 case ACTRES_ENABLER_CHECK:
1195 case ACTRES_SPY_ESCAPE:
1196 case ACTRES_NONE:
1197 /* No special help. */
1198 break;
1199
1200 ASSERT_UNUSED_ACTRES_CASES;
1201 }
1202
1203 /* Look for war requirements from the action enablers. */
1204 switch (action_get_target_kind(paction)) {
1205 case ATK_CITY:
1206 if (target_city == NULL) {
1207 /* No target city. */
1208 return NULL;
1209 }
1210
1211 target_player = city_owner(target_city);
1212 break;
1213 case ATK_UNIT:
1214 if (target_unit == NULL) {
1215 /* No target unit. */
1216 return NULL;
1217 }
1218 target_player = unit_owner(target_unit);
1219 break;
1220 case ATK_UNITS:
1221 if (target_tile == NULL) {
1222 /* No target units since no target tile. */
1223 return NULL;
1224 }
1225
1226 unit_list_iterate(target_tile->units, tunit) {
1227 if (rel_may_become_war(actor_player, unit_owner(tunit))) {
1228 target_player = unit_owner(tunit);
1229 break;
1230 }
1231 } unit_list_iterate_end;
1232 break;
1233 case ATK_TILE:
1234 if (target_tile == NULL) {
1235 /* No target tile. */
1236 return NULL;
1237 }
1238 target_player = tile_owner(target_tile);
1239 break;
1240 case ATK_EXTRAS:
1241 if (target_tile == NULL) {
1242 /* No target tile. */
1243 return NULL;
1244 }
1245 target_player = target_tile->owner;
1246 break;
1247 case ATK_SELF:
1248 /* Can't declare war on itself. */
1249 return NULL;
1250 break;
1251 case ATK_COUNT:
1252 /* Nothing to check. */
1253 fc_assert(action_id_get_target_kind(act) != ATK_COUNT);
1254 return NULL;
1255 }
1256
1257 if (target_player == NULL) {
1258 /* Declaring war won't enable the specified action. */
1259 return NULL;
1260 }
1261
1262 /* Look for DiplRelTileOther war requirements from the action enablers. */
1263 if (target_tile != NULL
1264 && need_war_enabler(unit_type_get(actor), paction,
1265 actor_player, tile_owner(target_tile),
1266 utype_can_act_if_tgt_diplrel_tile_other)) {
1267 return tile_owner(target_tile);
1268 }
1269
1270 /* Look for DiplRel war requirements from the action enablers. */
1271 if (need_war_enabler(unit_type_get(actor), paction,
1272 actor_player, target_player,
1273 can_utype_do_act_if_tgt_diplrel)) {
1274 return target_player;
1275 }
1276
1277 /* No check if other, non war, diplomatic states also could make the
1278 * action legal. This is need_war_player() so war is always the answer.
1279 * If you disagree and decide to add support please check that
1280 * webperimental's "can't found a city on a tile belonging to a non enemy"
1281 * rule still is detected. */
1282
1283 return NULL;
1284}
1285
1286/**********************************************************************/
1291 static struct player *need_war_player(const struct unit *actor,
1292 const action_id act_id,
1293 const struct tile *target_tile,
1294 const struct city *target_city,
1295 const struct unit *target_unit)
1296{
1297 if (act_id == ACTION_ANY) {
1298 /* Any action at all will do. */
1299 action_iterate(act) {
1300 struct player *war_player;
1301
1302 war_player = need_war_player_hlp(actor, act,
1303 target_tile, target_city,
1304 target_unit);
1305
1306 if (war_player != NULL) {
1307 /* Declaring war on this player may enable this action. */
1308 return war_player;
1309 }
1310 } action_iterate_end;
1311
1312 /* No action at all may be enabled by declaring war. */
1313 return NULL;
1314 } else {
1315 /* Look for the specified action. */
1316 return need_war_player_hlp(actor, act_id,
1317 target_tile, target_city,
1318 target_unit);
1319 }
1320}
1321
1322/**********************************************************************/
1326static bool
1327tile_has_units_not_allied_to_but_seen_by(const struct tile *ptile,
1328 const struct player *pplayer)
1329{
1330 unit_list_iterate(ptile->units, pother) {
1331 if (can_player_see_unit(pplayer, pother)
1332 && !pplayers_allied(pplayer, unit_owner(pother))) {
1333 return TRUE;
1334 }
1335 } unit_list_iterate_end;
1336
1337 return FALSE;
1338}
1339
1340/**********************************************************************/
1345 static bool does_terrain_block_action(const action_id act_id,
1346 bool is_target,
1347 struct unit *actor_unit,
1348 struct terrain *pterrain)
1349{
1350 if (act_id == ACTION_ANY) {
1351 /* Any action is OK. */
1352 action_iterate(alt_act) {
1353 if (utype_can_do_action(unit_type_get(actor_unit), alt_act)
1354 && !does_terrain_block_action(alt_act, is_target,
1355 actor_unit, pterrain)) {
1356 /* Only one action has to be possible. */
1357 return FALSE;
1358 }
1359 } action_iterate_end;
1360
1361 /* No action enabled. */
1362 return TRUE;
1363 }
1364
1365 /* ACTION_ANY is handled above. */
1366 fc_assert_ret_val(action_id_exists(act_id), FALSE);
1367
1368 action_enabler_list_iterate(action_enablers_for_action(act_id),
1369 enabler) {
1370 if (requirement_fulfilled_by_terrain(pterrain,
1371 (is_target ? &enabler->target_reqs : &enabler->actor_reqs))
1372 && requirement_fulfilled_by_unit_type(unit_type_get(actor_unit),
1373 &enabler->actor_reqs)) {
1374 /* This terrain kind doesn't block this action enabler. */
1375 return FALSE;
1376 }
1377 } action_enabler_list_iterate_end;
1378
1379 return TRUE;
1380}
1381
1382/**********************************************************************/
1387 static bool does_nation_block_action(const action_id act_id,
1388 bool is_target,
1389 struct unit *actor_unit,
1390 struct nation_type *pnation)
1391{
1392 if (act_id == ACTION_ANY) {
1393 /* Any action is OK. */
1394 action_iterate(alt_act) {
1395 if (utype_can_do_action(unit_type_get(actor_unit), alt_act)
1396 && !does_nation_block_action(alt_act, is_target,
1397 actor_unit, pnation)) {
1398 /* Only one action has to be possible. */
1399 return FALSE;
1400 }
1401 } action_iterate_end;
1402
1403 /* No action enabled. */
1404 return TRUE;
1405 }
1406
1407 /* ACTION_ANY is handled above. */
1408 fc_assert_ret_val(action_id_exists(act_id), FALSE);
1409
1410 action_enabler_list_iterate(action_enablers_for_action(act_id),
1411 enabler) {
1412 if (requirement_fulfilled_by_nation(pnation,
1413 (is_target ? &enabler->target_reqs
1414 : &enabler->actor_reqs))
1415 && requirement_fulfilled_by_unit_type(unit_type_get(actor_unit),
1416 &enabler->actor_reqs)) {
1417 /* This nation doesn't block this action enabler. */
1418 return FALSE;
1419 }
1420 } action_enabler_list_iterate_end;
1421
1422 return TRUE;
1423}
1424
1425/**********************************************************************/
1429 static struct ane_expl *expl_act_not_enabl(struct unit *punit,
1430 const action_id act_id,
1431 const struct tile *target_tile,
1432 const struct city *target_city,
1433 const struct unit *target_unit)
1434{
1435 struct player *must_war_player;
1436 const struct action *paction;
1437 struct action *blocker;
1438 struct player *act_player = unit_owner(punit);
1439 struct player *tgt_player = NULL;
1440 struct ane_expl *explnat = fc_malloc(sizeof(struct ane_expl));
1441 struct civ_map *nmap = &(wld.map);
1442 bool can_exist = can_unit_exist_at_tile(nmap, punit, unit_tile(punit));
1443 bool on_native = is_native_tile(unit_type_get(punit), unit_tile(punit));
1444 int action_custom;
1445
1446 /* Not know yet. (Initialize before the below check.) */
1447 explnat->kind = ANEK_UNKNOWN;
1448
1449 paction = action_by_number(act_id);
1450
1451 if (act_id != ACTION_ANY) {
1452 /* A specific action should have a suitable target. */
1453 switch (action_get_target_kind(paction)) {
1454 case ATK_CITY:
1455 if (target_city == NULL) {
1456 explnat->kind = ANEK_MISSING_TARGET;
1457 }
1458 break;
1459 case ATK_UNIT:
1460 if (target_unit == NULL) {
1461 explnat->kind = ANEK_MISSING_TARGET;
1462 }
1463 break;
1464 case ATK_UNITS:
1465 case ATK_TILE:
1466 case ATK_EXTRAS:
1467 if (target_tile == NULL) {
1468 explnat->kind = ANEK_MISSING_TARGET;
1469 }
1470 break;
1471 case ATK_SELF:
1472 /* No other target. */
1473 break;
1474 case ATK_COUNT:
1475 fc_assert(action_get_target_kind(paction) != ATK_COUNT);
1476 break;
1477 }
1478 }
1479
1480 if (explnat->kind == ANEK_MISSING_TARGET) {
1481 /* No point continuing. */
1482 return explnat;
1483 }
1484
1485 if (act_id == ACTION_ANY) {
1486 /* Find the target player of some actions. */
1487 if (target_city) {
1488 /* Individual city targets have the highest priority. */
1489 tgt_player = city_owner(target_city);
1490 } else if (target_unit) {
1491 /* Individual unit targets have the next priority. */
1492 tgt_player = unit_owner(target_unit);
1493 } else if (target_tile) {
1494 /* Tile targets have the lowest priority. */
1495 tgt_player = tile_owner(target_tile);
1496 }
1497 } else {
1498 /* Find the target player of this action. */
1499 switch (action_get_target_kind(paction)) {
1500 case ATK_CITY:
1501 tgt_player = city_owner(target_city);
1502 break;
1503 case ATK_UNIT:
1504 tgt_player = unit_owner(target_unit);
1505 break;
1506 case ATK_TILE:
1507 tgt_player = tile_owner(target_tile);
1508 break;
1509 case ATK_EXTRAS:
1510 tgt_player = target_tile->extras_owner;
1511 break;
1512 case ATK_UNITS:
1513 /* A unit stack may contain units with multiple owners. Pick the
1514 * first one. */
1515 if (target_tile
1516 && unit_list_size(target_tile->units) > 0) {
1517 tgt_player = unit_owner(unit_list_get(target_tile->units, 0));
1518 }
1519 break;
1520 case ATK_SELF:
1521 /* A unit acting against itself. */
1522 tgt_player = act_player;
1523 break;
1524 case ATK_COUNT:
1525 fc_assert(action_get_target_kind(paction) != ATK_COUNT);
1526 break;
1527 }
1528 }
1529
1530 if (act_id == ACTION_ANY) {
1531 action_custom = 0;
1532 } else {
1533 switch (paction->result) {
1534 case ACTRES_UPGRADE_UNIT:
1535 action_custom = unit_upgrade_test(nmap, punit, FALSE);
1536 break;
1537 case ACTRES_AIRLIFT:
1538 action_custom = test_unit_can_airlift_to(nmap, NULL, punit, target_city);
1539 break;
1540 case ACTRES_NUKE_UNITS:
1541 action_custom = unit_attack_units_at_tile_result(punit, paction,
1542 target_tile);
1543 break;
1544 case ACTRES_ATTACK:
1545 action_custom = unit_attack_units_at_tile_result(punit, paction,
1546 target_tile);
1547 break;
1548 case ACTRES_WIPE_UNITS:
1549 action_custom = unit_wipe_units_at_tile_result(punit, target_tile);
1550 break;
1551 case ACTRES_CONQUER_CITY:
1552 if (target_city) {
1553 action_custom = unit_move_to_tile_test(nmap, punit,
1554 punit->activity,
1555 unit_tile(punit),
1556 city_tile(target_city),
1557 FALSE, FALSE, NULL, TRUE);
1558 } else {
1559 action_custom = MR_OK;
1560 }
1561 break;
1562 case ACTRES_TRANSPORT_EMBARK:
1563 if (target_unit) {
1564 action_custom = unit_move_to_tile_test(nmap, punit,
1565 punit->activity,
1566 unit_tile(punit),
1567 unit_tile(target_unit),
1568 FALSE, TRUE, NULL, FALSE);
1569 } else {
1570 action_custom = MR_OK;
1571 }
1572 break;
1573 case ACTRES_TRANSPORT_DISEMBARK:
1574 case ACTRES_HUT_ENTER:
1575 case ACTRES_HUT_FRIGHTEN:
1576 case ACTRES_CONQUER_EXTRAS:
1577 case ACTRES_UNIT_MOVE:
1578 if (target_tile) {
1579 action_custom = unit_move_to_tile_test(nmap, punit,
1580 punit->activity,
1581 unit_tile(punit),
1582 target_tile,
1583 FALSE, FALSE, NULL, FALSE);
1584 } else {
1585 action_custom = MR_OK;
1586 }
1587 break;
1588 case ACTRES_TELEPORT:
1589 if (target_tile != NULL) {
1590 action_custom = unit_teleport_to_tile_test(nmap, punit,
1591 punit->activity,
1592 unit_tile(punit),
1593 target_tile,
1594 FALSE, NULL, FALSE);
1595 } else {
1596 action_custom = MR_OK;
1597 }
1598 break;
1599 default:
1600 action_custom = 0;
1601 break;
1602 }
1603 }
1604
1605 if (!unit_can_do_action(punit, act_id)) {
1606 explnat->kind = ANEK_ACTOR_UNIT;
1607 } else if (action_has_result_safe(paction, ACTRES_FOUND_CITY)
1608 && tile_city(target_tile)) {
1609 explnat->kind = ANEK_BAD_TARGET;
1610 } else if ((action_has_result_safe(paction, ACTRES_PARADROP_CONQUER)
1611 || action_has_result_safe(paction, ACTRES_PARADROP))
1612 && tile_has_units_not_allied_to_but_seen_by(target_tile,
1613 act_player)) {
1614 explnat->kind = ANEK_TGT_NON_ALLIED_UNITS_ON_TILE;
1615 } else if ((!can_exist
1616 && !utype_can_do_act_when_ustate(unit_type_get(punit), act_id,
1617 USP_LIVABLE_TILE, FALSE))
1618 || (can_exist
1619 && !utype_can_do_act_when_ustate(unit_type_get(punit), act_id,
1620 USP_LIVABLE_TILE, TRUE))) {
1621 explnat->kind = ANEK_BAD_TERRAIN_ACT;
1622 explnat->no_act_terrain = tile_terrain(unit_tile(punit));
1623 } else if ((!on_native
1624 && !utype_can_do_act_when_ustate(unit_type_get(punit), act_id,
1625 USP_NATIVE_TILE, FALSE))
1626 || (on_native
1627 && !utype_can_do_act_when_ustate(unit_type_get(punit), act_id,
1628 USP_NATIVE_TILE, TRUE))) {
1629 explnat->kind = ANEK_BAD_TERRAIN_ACT;
1630 explnat->no_act_terrain = tile_terrain(unit_tile(punit));
1631 } else if (punit
1632 && does_terrain_block_action(act_id, FALSE,
1633 punit, tile_terrain(unit_tile(punit)))) {
1634 /* No action enabler allows acting against this terrain kind. */
1635 explnat->kind = ANEK_BAD_TERRAIN_ACT;
1636 explnat->no_act_terrain = tile_terrain(unit_tile(punit));
1637 } else if (action_has_result_safe(paction, ACTRES_FOUND_CITY)
1638 && target_tile
1639 && terrain_has_flag(tile_terrain(target_tile),
1640 TER_NO_CITIES)) {
1641 explnat->kind = ANEK_BAD_TERRAIN_TGT;
1642 explnat->no_act_terrain = tile_terrain(target_tile);
1643 } else if ((action_has_result_safe(paction, ACTRES_PARADROP)
1644 || action_has_result_safe(paction, ACTRES_PARADROP_CONQUER))
1645 && target_tile != NULL
1646 && map_is_known_and_seen(target_tile, act_player,
1647 V_MAIN)
1648 && (!can_unit_exist_at_tile(nmap, punit, target_tile)
1649 && (!BV_ISSET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK)
1650 || !unit_could_load_at(punit, target_tile)))) {
1651 explnat->kind = ANEK_BAD_TERRAIN_TGT;
1652 explnat->no_act_terrain = tile_terrain(target_tile);
1653 } else if (target_tile
1654 && does_terrain_block_action(act_id, TRUE,
1655 punit, tile_terrain(target_tile))) {
1656 /* No action enabler allows acting against this terrain kind. */
1657 explnat->kind = ANEK_BAD_TERRAIN_TGT;
1658 explnat->no_act_terrain = tile_terrain(target_tile);
1659 } else if (unit_transported(punit)
1660 && !utype_can_do_act_when_ustate(unit_type_get(punit), act_id,
1661 USP_TRANSPORTED, TRUE)) {
1662 explnat->kind = ANEK_IS_TRANSPORTED;
1663 } else if (!unit_transported(punit)
1664 && !utype_can_do_act_when_ustate(unit_type_get(punit), act_id,
1665 USP_TRANSPORTED, FALSE)) {
1666 explnat->kind = ANEK_IS_NOT_TRANSPORTED;
1667 } else if (0 < get_transporter_occupancy(punit)
1668 && !utype_can_do_act_when_ustate(unit_type_get(punit), act_id,
1669 USP_TRANSPORTING, TRUE)) {
1670 explnat->kind = ANEK_IS_TRANSPORTING;
1671 } else if (!(0 < get_transporter_occupancy(punit))
1672 && !utype_can_do_act_when_ustate(unit_type_get(punit), act_id,
1673 USP_TRANSPORTING, FALSE)) {
1674 explnat->kind = ANEK_IS_NOT_TRANSPORTING;
1675 } else if ((punit->homecity > 0)
1676 && !utype_can_do_act_when_ustate(unit_type_get(punit), act_id,
1677 USP_HAS_HOME_CITY, TRUE)) {
1678 explnat->kind = ANEK_ACTOR_HAS_HOME_CITY;
1679 } else if ((punit->homecity <= 0)
1680 && !utype_can_do_act_when_ustate(unit_type_get(punit), act_id,
1681 USP_HAS_HOME_CITY, FALSE)) {
1682 explnat->kind = ANEK_ACTOR_HAS_NO_HOME_CITY;
1683 } else if ((punit->homecity <= 0)
1684 && (action_has_result_safe(paction, ACTRES_TRADE_ROUTE)
1685 || action_has_result_safe(paction, ACTRES_MARKETPLACE))) {
1686 explnat->kind = ANEK_ACTOR_HAS_NO_HOME_CITY;
1687 } else if (act_player && tgt_player
1688 && (player_diplstate_get(act_player, tgt_player)->type
1689 == DS_PEACE)
1690 && can_utype_do_act_if_tgt_diplrel(unit_type_get(punit),
1691 act_id,
1692 DS_PEACE,
1693 FALSE)
1694 && !can_utype_do_act_if_tgt_diplrel(unit_type_get(punit),
1695 act_id,
1696 DS_PEACE,
1697 TRUE)) {
1698 explnat->kind = ANEK_PEACE;
1699 explnat->peace_with = tgt_player;
1700 } else if ((must_war_player = need_war_player(punit,
1701 act_id,
1702 target_tile,
1703 target_city,
1704 target_unit))) {
1705 explnat->kind = ANEK_NO_WAR;
1706 explnat->no_war_with = must_war_player;
1707 } else if (action_mp_full_makes_legal(punit, act_id)) {
1708 explnat->kind = ANEK_LOW_MP;
1709 } else if (tgt_player != NULL
1710 && act_player != tgt_player
1711 && !can_utype_do_act_if_tgt_diplrel(unit_type_get(punit),
1712 act_id,
1713 DRO_FOREIGN,
1714 TRUE)) {
1715 explnat->kind = ANEK_FOREIGN;
1716 } else if (tgt_player != NULL
1717 && act_player == tgt_player
1718 && !can_utype_do_act_if_tgt_diplrel(unit_type_get(punit),
1719 act_id,
1720 DRO_FOREIGN,
1721 FALSE)) {
1722 explnat->kind = ANEK_DOMESTIC;
1723 } else if (punit != NULL
1724 && does_nation_block_action(act_id, FALSE,
1725 punit, act_player->nation)) {
1726 explnat->kind = ANEK_NATION_ACT;
1727 explnat->no_act_nation = act_player->nation;
1728 } else if (tgt_player
1729 && does_nation_block_action(act_id, TRUE,
1730 punit, tgt_player->nation)) {
1731 explnat->kind = ANEK_NATION_TGT;
1732 explnat->no_act_nation = tgt_player->nation;
1733 } else if ((target_tile && tile_city(target_tile))
1734 && !utype_may_act_tgt_city_tile(unit_type_get(punit),
1735 act_id,
1736 CITYT_CENTER,
1737 TRUE)) {
1738 explnat->kind = ANEK_IS_CITY_CENTER;
1739 } else if ((target_tile && !tile_city(target_tile))
1740 && !utype_may_act_tgt_city_tile(unit_type_get(punit),
1741 act_id,
1742 CITYT_CENTER,
1743 FALSE)) {
1744 explnat->kind = ANEK_IS_NOT_CITY_CENTER;
1745 } else if ((target_tile && tile_owner(target_tile) != NULL)
1746 && !utype_may_act_tgt_city_tile(unit_type_get(punit),
1747 act_id,
1748 CITYT_CLAIMED,
1749 TRUE)) {
1750 explnat->kind = ANEK_TGT_IS_CLAIMED;
1751 } else if ((target_tile && tile_owner(target_tile) == NULL)
1752 && !utype_may_act_tgt_city_tile(unit_type_get(punit),
1753 act_id,
1754 CITYT_CLAIMED,
1755 FALSE)) {
1756 explnat->kind = ANEK_TGT_IS_UNCLAIMED;
1757 } else if (paction && punit
1758 && ((target_tile
1759 && !action_distance_inside_max(paction,
1760 real_map_distance(unit_tile(punit), target_tile)))
1761 || (target_city
1762 && !action_distance_inside_max(paction,
1763 real_map_distance(unit_tile(punit),
1764 city_tile(target_city))))
1765 || (target_unit
1766 && !action_distance_inside_max(paction,
1767 real_map_distance(unit_tile(punit),
1768 unit_tile(target_unit)))))) {
1769 explnat->kind = ANEK_DISTANCE_FAR;
1770 explnat->distance = paction->max_distance;
1771 } else if ((action_has_result_safe(paction, ACTRES_PARADROP_CONQUER)
1772 || action_has_result_safe(paction, ACTRES_PARADROP))
1773 && punit && target_tile
1774 && real_map_distance(unit_tile(punit), target_tile)
1775 > unit_type_get(punit)->paratroopers_range) {
1776 explnat->kind = ANEK_DISTANCE_FAR;
1777 explnat->distance = unit_type_get(punit)->paratroopers_range;
1778 } else if (paction && punit
1779 && ((target_tile
1780 && real_map_distance(unit_tile(punit), target_tile)
1781 < paction->min_distance)
1782 || (target_city
1783 && real_map_distance(unit_tile(punit),
1784 city_tile(target_city))
1785 < paction->min_distance)
1786 || (target_unit
1787 && real_map_distance(unit_tile(punit),
1788 unit_tile(target_unit))
1789 < paction->min_distance))) {
1790 explnat->kind = ANEK_DISTANCE_NEAR;
1791 explnat->distance = paction->min_distance;
1792 } else if (target_city
1793 && (action_has_result_safe(paction, ACTRES_JOIN_CITY)
1794 && action_actor_utype_hard_reqs_ok(paction,
1795 unit_type_get(punit))
1796 && (city_size_get(target_city) + unit_pop_value(punit)
1797 > game.info.add_to_size_limit))) {
1798 /* TODO: Check max city size requirements from action enabler target
1799 * vectors. */
1800 explnat->kind = ANEK_CITY_TOO_BIG;
1801 } else if (target_city
1802 && (action_has_result_safe(paction, ACTRES_JOIN_CITY)
1803 && action_actor_utype_hard_reqs_ok(paction,
1804 unit_type_get(punit))
1805 && (!city_can_grow_to(target_city,
1806 city_size_get(target_city)
1807 + unit_pop_value(punit))))) {
1808 explnat->kind = ANEK_CITY_POP_LIMIT;
1809 } else if ((action_has_result_safe(paction, ACTRES_NUKE_UNITS)
1810 || action_has_result_safe(paction, ACTRES_ATTACK)
1811 || action_has_result_safe(paction, ACTRES_WIPE_UNITS))
1812 && action_custom != ATT_OK) {
1813 switch (action_custom) {
1814 case ATT_NON_ATTACK:
1815 explnat->kind = ANEK_ACTOR_UNIT;
1816 break;
1817 case ATT_UNREACHABLE:
1818 explnat->kind = ANEK_TGT_UNREACHABLE;
1819 break;
1820 case ATT_NONNATIVE_SRC:
1821 explnat->kind = ANEK_BAD_TERRAIN_ACT;
1822 explnat->no_act_terrain = tile_terrain(unit_tile(punit));
1823 break;
1824 case ATT_NONNATIVE_DST:
1825 explnat->kind = ANEK_BAD_TERRAIN_TGT;
1826 explnat->no_act_terrain = tile_terrain(target_tile);
1827 break;
1828 case ATT_NOT_WIPABLE:
1829 explnat->kind = ANEK_NOT_WIPABLE;
1830 break;
1831 default:
1832 fc_assert(action_custom != ATT_OK);
1833 explnat->kind = ANEK_UNKNOWN;
1834 break;
1835 }
1836 } else if (action_has_result_safe(paction, ACTRES_AIRLIFT)
1837 && action_custom == AR_SRC_NO_FLIGHTS) {
1838 explnat->kind = ANEK_CITY_NO_CAPACITY;
1839 explnat->capacity_city = tile_city(unit_tile(punit));
1840 } else if (action_has_result_safe(paction, ACTRES_AIRLIFT)
1841 && action_custom == AR_DST_NO_FLIGHTS) {
1842 explnat->kind = ANEK_CITY_NO_CAPACITY;
1843 explnat->capacity_city = game_city_by_number(target_city->id);
1844 } else if (action_has_result_safe(paction, ACTRES_FOUND_CITY)
1845 && citymindist_prevents_city_on_tile(nmap, target_tile)) {
1846 explnat->kind = ANEK_CITY_TOO_CLOSE_TGT;
1847 } else if ((action_has_result_safe(paction, ACTRES_PARADROP_CONQUER)
1848 || action_has_result_safe(paction, ACTRES_PARADROP))
1849 && target_tile != NULL
1850 && !map_is_known(target_tile, act_player)) {
1851 explnat->kind = ANEK_TGT_TILE_UNKNOWN;
1852 } else if ((action_has_result_safe(paction, ACTRES_CONQUER_CITY)
1853 || action_id_has_result_safe(act_id, ACTRES_CONQUER_EXTRAS)
1854 || action_id_has_result_safe(act_id, ACTRES_HUT_ENTER)
1855 || action_id_has_result_safe(act_id, ACTRES_HUT_FRIGHTEN)
1856 || action_id_has_result_safe(act_id, ACTRES_UNIT_MOVE)
1857 || action_has_result_safe(paction,
1858 ACTRES_TRANSPORT_EMBARK)
1859 || action_has_result_safe(paction,
1860 ACTRES_TRANSPORT_DISEMBARK))
1861 && action_custom != MR_OK) {
1862 switch (action_custom) {
1863 case MR_CANNOT_DISEMBARK:
1864 explnat->kind = ANEK_DISEMBARK_ACT;
1865 break;
1866 case MR_TRIREME:
1867 explnat->kind = ANEK_TRIREME_MOVE;
1868 break;
1869 case MR_DESTINATION_OCCUPIED_BY_NON_ALLIED_UNIT:
1870 explnat->kind = ANEK_TGT_NON_ALLIED_UNITS_ON_TILE;
1871 break;
1872 default:
1873 fc_assert(action_custom != MR_OK);
1874 explnat->kind = ANEK_UNKNOWN;
1875 break;
1876 }
1877 } else if (action_has_result_safe(paction, ACTRES_SPY_BRIBE_UNIT)
1878 && utype_player_already_has_this_unique(act_player,
1879 unit_type_get(target_unit))) {
1880 explnat->kind = ANEK_TGT_IS_UNIQUE_ACT_HAS;
1881 explnat->no_tgt_utype = unit_type_get(target_unit);
1882 } else if ((game.scenario.prevent_new_cities
1883 && utype_can_do_action(unit_type_get(punit), ACTION_FOUND_CITY))
1884 && (action_has_result_safe(paction, ACTRES_FOUND_CITY)
1885 || act_id == ACTION_ANY)) {
1886 /* Please add a check for any new action forbidding scenario setting
1887 * above this comment. */
1888 explnat->kind = ANEK_SCENARIO_DISABLED;
1889 } else if (action_has_result_safe(paction, ACTRES_UPGRADE_UNIT)
1890 && action_custom == UU_NO_MONEY) {
1891 const struct unit_type *act_utype = unit_type_get(punit);
1892
1893 explnat->kind = ANEK_ACT_NOT_ENOUGH_MONEY;
1894 explnat->gold_needed = unit_upgrade_price(act_player, act_utype,
1895 can_upgrade_unittype(
1896 act_player, act_utype));
1897 } else if (paction
1898 && (blocker = action_is_blocked_by(paction, punit,
1899 target_tile, target_city,
1900 target_unit))) {
1901 explnat->kind = ANEK_ACTION_BLOCKS;
1902 explnat->blocker = blocker;
1903 } else {
1904 explnat->kind = ANEK_UNKNOWN;
1905 }
1906
1907 return explnat;
1908}
1909
1910/**********************************************************************/
1913 enum ane_kind action_not_enabled_reason(struct unit *punit,
1914 action_id act_id,
1915 const struct tile *target_tile,
1916 const struct city *target_city,
1917 const struct unit *target_unit)
1918{
1919 struct ane_expl *explnat = expl_act_not_enabl(punit, act_id,
1920 target_tile,
1921 target_city, target_unit);
1922 enum ane_kind out = explnat->kind;
1923
1924 free(explnat);
1925
1926 return out;
1927}
1928
1929/**********************************************************************/
1933 static void explain_why_no_action_enabled(struct unit *punit,
1934 const struct tile *target_tile,
1935 const struct city *target_city,
1936 const struct unit *target_unit)
1937{
1938 struct player *pplayer = unit_owner(punit);
1939 struct ane_expl *explnat = expl_act_not_enabl(punit, ACTION_ANY,
1940 target_tile,
1941 target_city, target_unit);
1942 const struct civ_map *nmap = &(wld.map);
1943
1944 switch (explnat->kind) {
1945 case ANEK_ACTOR_UNIT:
1946 /* This shouldn't happen unless the client is buggy given the current
1947 * users. */
1948 fc_assert_msg(explnat->kind != ANEK_ACTOR_UNIT,
1949 "Asked to explain why a non actor can't act.");
1950
1951 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
1952 _("Unit cannot do anything."));
1953 break;
1954 case ANEK_MISSING_TARGET:
1955 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
1956 _("Your %s found no suitable target."),
1957 unit_name_translation(punit));
1958 break;
1959 case ANEK_BAD_TARGET:
1960 /* This shouldn't happen at the moment. Only specific action checks
1961 * will trigger bad target checks. This is a reply to a question about
1962 * any action. */
1963 fc_assert(explnat->kind != ANEK_BAD_TARGET);
1964
1965 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
1966 _("Your %s found no suitable target."),
1967 unit_name_translation(punit));
1968 break;
1969 case ANEK_BAD_TERRAIN_ACT:
1970 {
1971 const char *types[utype_count()];
1972 int i = 0;
1973
1974 if (!utype_can_do_act_when_ustate(unit_type_get(punit),
1975 ACTION_ANY, USP_LIVABLE_TILE,
1976 FALSE)
1977 && !can_unit_exist_at_tile(nmap, punit, unit_tile(punit))) {
1978 unit_type_iterate(utype) {
1979 if (utype_can_do_act_when_ustate(utype, ACTION_ANY,
1980 USP_LIVABLE_TILE, FALSE)) {
1981 types[i++] = utype_name_translation(utype);
1982 }
1983 } unit_type_iterate_end;
1984 }
1985
1986 if (0 < i) {
1987 struct astring astr = ASTRING_INIT;
1988
1989 notify_player(pplayer, unit_tile(punit),
1990 E_BAD_COMMAND, ftc_server,
1991 /* TRANS: terrain name
1992 * "Your Diplomat cannot act from Ocean. Only
1993 * Spy or Partisan ... */
1994 _("Your %s cannot act from %s. "
1995 "Only %s can act from a non livable tile."),
1996 unit_name_translation(punit),
1997 terrain_name_translation(explnat->no_act_terrain),
1998 astr_build_or_list(&astr, types, i));
1999
2000 astr_free(&astr);
2001 } else {
2002 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2003 /* TRANS: terrain name */
2004 _("Unit cannot act from %s."),
2005 terrain_name_translation(explnat->no_act_terrain));
2006 }
2007 }
2008 break;
2009 case ANEK_BAD_TERRAIN_TGT:
2010 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2011 /* TRANS: terrain name */
2012 _("Unit cannot act against %s."),
2013 terrain_name_translation(explnat->no_act_terrain));
2014 break;
2015 case ANEK_IS_TRANSPORTED:
2016 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2017 _("This unit is being transported, and"
2018 " so cannot act."));
2019 break;
2020 case ANEK_IS_NOT_TRANSPORTED:
2021 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2022 _("This unit cannot act when it isn't being "
2023 "transported."));
2024 break;
2025 case ANEK_IS_TRANSPORTING:
2026 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2027 _("This unit is transporting, and"
2028 " so cannot act."));
2029 break;
2030 case ANEK_IS_NOT_TRANSPORTING:
2031 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2032 _("This unit cannot act when it isn't transporting."));
2033 break;
2034 case ANEK_ACTOR_HAS_HOME_CITY:
2035 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2036 _("This unit has a home city, and so cannot act."));
2037 break;
2038 case ANEK_ACTOR_HAS_NO_HOME_CITY:
2039 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2040 _("This unit cannot act unless it has a home city."));
2041 break;
2042 case ANEK_NO_WAR:
2043 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2044 _("You must declare war on %s first. Try using "
2045 "the Nations report"
2046#ifndef FREECIV_WEB
2047 " (F3)"
2048#endif /* FREECIV_WEB */
2049 "."),
2050 player_name(explnat->no_war_with));
2051 break;
2052 case ANEK_PEACE:
2053 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2054 _("You must break peace with %s first. Try using "
2055 "the Nations report to declare war"
2056#ifndef FREECIV_WEB
2057 " (F3)"
2058#endif /* FREECIV_WEB */
2059 "."),
2060 player_name(explnat->peace_with));
2061 break;
2062 case ANEK_DOMESTIC:
2063 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2064 _("This unit cannot act against domestic targets."));
2065 break;
2066 case ANEK_FOREIGN:
2067 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2068 _("This unit cannot act against foreign targets."));
2069 break;
2070 case ANEK_TGT_NON_ALLIED_UNITS_ON_TILE:
2071 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2072 /* TRANS: Riflemen */
2073 _("%s cannot act against tiles with non allied units."),
2074 unit_name_translation(punit));
2075 break;
2076 case ANEK_NATION_ACT:
2077 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2078 /* TRANS: Swedish ... Riflemen */
2079 _("%s %s cannot act."),
2080 nation_adjective_translation(explnat->no_act_nation),
2081 unit_name_translation(punit));
2082 break;
2083 case ANEK_NATION_TGT:
2084 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2085 /* TRANS: ... Pirate ... */
2086 _("This unit cannot act against %s targets."),
2087 nation_adjective_translation(explnat->no_act_nation));
2088 break;
2089 case ANEK_LOW_MP:
2090 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2091 _("This unit has too few moves left to act."));
2092 break;
2093 case ANEK_IS_CITY_CENTER:
2094 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2095 _("This unit cannot act against city centers."));
2096 break;
2097 case ANEK_IS_NOT_CITY_CENTER:
2098 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2099 _("This unit cannot act against non city centers."));
2100 break;
2101 case ANEK_TGT_IS_CLAIMED:
2102 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2103 _("This unit cannot act against claimed tiles."));
2104 break;
2105 case ANEK_TGT_IS_UNCLAIMED:
2106 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2107 _("This unit cannot act against unclaimed tiles."));
2108 break;
2109 case ANEK_DISTANCE_NEAR:
2110 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2111 _("This unit is too near its target to act."));
2112 break;
2113 case ANEK_DISTANCE_FAR:
2114 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2115 _("This unit is too far away from its target to act."));
2116 break;
2117 case ANEK_SCENARIO_DISABLED:
2118 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2119 _("Can't perform any action this scenario permits."));
2120 break;
2121 case ANEK_CITY_TOO_CLOSE_TGT:
2122 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2123 _("Can't perform any action this close to a city."));
2124 break;
2125 case ANEK_CITY_TOO_BIG:
2126 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2127 /* TRANS: Settler ... Berlin */
2128 _("%s can't do anything to %s. It is too big."),
2129 unit_name_translation(punit),
2130 city_name_get(target_city));
2131 break;
2132 case ANEK_CITY_POP_LIMIT:
2133 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2134 /* TRANS: London ... Settlers */
2135 _("%s needs an improvement to grow, so "
2136 "%s cannot do anything to it."),
2137 city_name_get(target_city),
2138 unit_name_translation(punit));
2139 break;
2140 case ANEK_CITY_NO_CAPACITY:
2141 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2142 /* TRANS: Paris ... Warriors (think: airlift) */
2143 _("%s don't have enough capacity, so "
2144 "%s cannot do anything."),
2145 city_name_get(explnat->capacity_city),
2146 unit_name_translation(punit));
2147 break;
2148 case ANEK_TGT_TILE_UNKNOWN:
2149 notify_player(pplayer, target_tile, E_BAD_COMMAND, ftc_server,
2150 /* TRANS: Paratroopers ... */
2151 _("%s can't do anything to an unknown target tile."),
2152 unit_name_translation(punit));
2153 break;
2154 case ANEK_ACT_NOT_ENOUGH_MONEY:
2155 {
2156 char tbuf[MAX_LEN_MSG];
2157
2158 /* TRANS: Used below. Separate so treasury content too can determine
2159 * if this is plural. */
2160 fc_snprintf(tbuf, ARRAY_SIZE(tbuf), PL_("Treasury contains %d gold.",
2161 "Treasury contains %d gold.",
2162 pplayer->economic.gold),
2163 pplayer->economic.gold);
2164
2165 notify_player(pplayer, target_tile, E_BAD_COMMAND, ftc_server,
2166 /* TRANS: "Spy can't do anything. 154 gold may help.
2167 * Treasury contains 100 gold." */
2168 PL_("%s can't do anything. %d gold may help. %s",
2169 "%s can't do anything. %d gold may help. %s",
2170 explnat->gold_needed),
2171 unit_name_translation(punit),
2172 explnat->gold_needed, tbuf);
2173 }
2174 break;
2175 case ANEK_TRIREME_MOVE:
2176 notify_player(pplayer, target_tile, E_BAD_COMMAND, ftc_server,
2177 _("%s cannot move that far from the coast line."),
2178 unit_link(punit));
2179 break;
2180 case ANEK_DISEMBARK_ACT:
2181 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2182 _("%s cannot disembark outside of a city or a native base "
2183 "for %s."),
2184 unit_link(punit),
2185 utype_name_translation(
2186 unit_type_get(unit_transport_get(punit))));
2187 break;
2188 case ANEK_TGT_UNREACHABLE:
2189 notify_player(pplayer, target_tile, E_BAD_COMMAND, ftc_server,
2190 _("%s can't do anything since there is an unreachable "
2191 "unit."),
2192 unit_name_translation(punit));
2193 break;
2194 case ANEK_NOT_WIPABLE:
2195 notify_player(pplayer, target_tile, E_BAD_COMMAND, ftc_server,
2196 _("%s can't do anything since there is unit with a positive "
2197 "defense value."),
2198 unit_name_translation(punit));
2199 break;
2200 case ANEK_TGT_IS_UNIQUE_ACT_HAS:
2201 notify_player(pplayer, target_tile, E_BAD_COMMAND, ftc_server,
2202 _("%s can't do anything since you already have a %s."),
2203 unit_name_translation(punit),
2204 utype_name_translation(explnat->no_tgt_utype));
2205 break;
2206 case ANEK_ACTION_BLOCKS:
2207 /* If an action blocked another action the blocking action must be
2208 * possible. */
2209 fc_assert(explnat->kind != ANEK_ACTION_BLOCKS);
2210 fc__fallthrough; /* Fall through to unknown cause. */
2211 case ANEK_UNKNOWN:
2212 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2213 _("No action possible."));
2214 break;
2215 }
2216
2217 free(explnat);
2218}
2219
2220/**********************************************************************/
2228 void handle_unit_get_actions(struct connection *pc,
2229 const int actor_unit_id,
2230 const int target_unit_id_client,
2231 const int target_tile_id,
2232 const int target_extra_id_client,
2233 const int request_kind)
2234{
2235 struct player *actor_player;
2236 struct unit *actor_unit;
2237 struct tile *target_tile;
2238 struct act_prob probabilities[MAX_NUM_ACTIONS];
2239 struct unit *target_unit;
2240 struct city *target_city;
2241 struct extra_type *target_extra;
2242 int actor_target_distance;
2243 const struct player_tile *plrtile;
2244 int target_extra_id = target_extra_id_client;
2245 const struct civ_map *nmap = &(wld.map);
2246
2247 /* No potentially legal action is known yet. If none is found the player
2248 * should get an explanation. */
2249 bool at_least_one_action = FALSE;
2250
2251 /* A target should only be sent if it is possible to act against it */
2252 int target_city_id = IDENTITY_NUMBER_ZERO;
2253 int target_unit_id = IDENTITY_NUMBER_ZERO;
2254
2255 actor_player = pc->playing;
2256 actor_unit = game_unit_by_number(actor_unit_id);
2257 target_tile = index_to_tile(nmap, target_tile_id);
2258
2259 /* Initialize the action probabilities. */
2260 action_iterate(act) {
2261 probabilities[act] = ACTPROB_NA;
2262 } action_iterate_end;
2263
2264 /* Check if the request is valid. */
2265 if (!target_tile || !actor_unit || !actor_player
2266 || actor_unit->owner != actor_player) {
2267 dsend_packet_unit_actions(pc, actor_unit_id,
2268 IDENTITY_NUMBER_ZERO, IDENTITY_NUMBER_ZERO,
2269 target_tile_id, target_extra_id,
2270 request_kind,
2271 probabilities);
2272 return;
2273 }
2274
2275 /* Select the targets. */
2276
2277 if (target_unit_id_client == IDENTITY_NUMBER_ZERO) {
2278 /* Find a new target unit. */
2279 target_unit = action_tgt_unit(actor_unit, target_tile, TRUE);
2280 } else {
2281 /* Prepare the client selected target unit. */
2282 target_unit = game_unit_by_number(target_unit_id_client);
2283 }
2284
2285 /* Find the target city. */
2286 target_city = action_tgt_city(actor_unit, target_tile, TRUE);
2287
2288 /* The specified target unit must be located at the target tile. */
2289 if (target_unit && unit_tile(target_unit) != target_tile) {
2290 notify_player(actor_player, unit_tile(actor_unit),
2291 E_BAD_COMMAND, ftc_server,
2292 _("Target not at target tile."));
2293 dsend_packet_unit_actions(pc, actor_unit_id,
2294 IDENTITY_NUMBER_ZERO, IDENTITY_NUMBER_ZERO,
2295 target_tile_id, target_extra_id,
2296 request_kind,
2297 probabilities);
2298 return;
2299 }
2300
2301 if (target_extra_id_client == EXTRA_NONE) {
2302 /* See if a target extra can be found. */
2303 target_extra = action_tgt_tile_extra(actor_unit, target_tile, TRUE);
2304 } else {
2305 /* Use the client selected target extra. */
2306 target_extra = extra_by_number(target_extra_id_client);
2307 }
2308
2309 /* The player may have outdated information about the target tile.
2310 * Limiting the player knowledge look up to the target tile is OK since
2311 * all targets must be located at it. */
2312 plrtile = map_get_player_tile(target_tile, actor_player);
2313
2314 /* Distance between actor and target tile. */
2315 actor_target_distance = real_map_distance(unit_tile(actor_unit),
2316 target_tile);
2317
2318 /* Find out what can be done to the targets. */
2319
2320 /* Set the probability for the actions. */
2321 action_iterate(act) {
2322 if (action_id_get_actor_kind(act) != AAK_UNIT) {
2323 /* Not relevant. */
2324 continue;
2325 }
2326
2327 switch (action_id_get_target_kind(act)) {
2328 case ATK_CITY:
2329 if (plrtile && plrtile->site) {
2330 /* Only a known city may be targeted. */
2331 if (target_city) {
2332 /* Calculate the probabilities. */
2333 probabilities[act] = action_prob_vs_city(actor_unit, act,
2334 target_city);
2335 } else if (!tile_is_seen(target_tile, actor_player)
2336 && action_maybe_possible_actor_unit(nmap, act, actor_unit)
2337 && action_id_distance_accepted(act,
2338 actor_target_distance)) {
2339 /* The target city is non existing. The player isn't aware of this
2340 * fact because they can't see the tile it was located on. The
2341 * actor unit it self doesn't contradict the requirements to
2342 * perform the action. The (no longer existing) target city was
2343 * known to be close enough. */
2344 probabilities[act] = ACTPROB_NOT_KNOWN;
2345 } else {
2346 /* The actor unit is known to be unable to act or the target city
2347 * is known to be too far away. */
2348 probabilities[act] = ACTPROB_IMPOSSIBLE;
2349 }
2350 } else {
2351 /* No target to act against. */
2352 probabilities[act] = ACTPROB_IMPOSSIBLE;
2353 }
2354 break;
2355 case ATK_UNIT:
2356 if (target_unit) {
2357 /* Calculate the probabilities. */
2358 probabilities[act] = action_prob_vs_unit(actor_unit, act,
2359 target_unit);
2360 } else {
2361 /* No target to act against. */
2362 probabilities[act] = ACTPROB_IMPOSSIBLE;
2363 }
2364 break;
2365 case ATK_UNITS:
2366 if (target_tile) {
2367 /* Calculate the probabilities. */
2368 probabilities[act] = action_prob_vs_stack(actor_unit, act,
2369 target_tile);
2370 } else {
2371 /* No target to act against. */
2372 probabilities[act] = ACTPROB_IMPOSSIBLE;
2373 }
2374 break;
2375 case ATK_TILE:
2376 if (target_tile) {
2377 /* Calculate the probabilities. */
2378 probabilities[act] = action_prob_vs_tile(actor_unit, act,
2379 target_tile, target_extra);
2380 } else {
2381 /* No target to act against. */
2382 probabilities[act] = ACTPROB_IMPOSSIBLE;
2383 }
2384 break;
2385 case ATK_EXTRAS:
2386 if (target_tile) {
2387 /* Calculate the probabilities. */
2388 probabilities[act] = action_prob_vs_extras(actor_unit, act,
2389 target_tile,
2390 target_extra);
2391 } else {
2392 /* No target to act against. */
2393 probabilities[act] = ACTPROB_IMPOSSIBLE;
2394 }
2395 break;
2396 case ATK_SELF:
2397 if (actor_target_distance == 0) {
2398 /* Calculate the probabilities. */
2399 probabilities[act] = action_prob_self(actor_unit, act);
2400 } else {
2401 /* Don't bother with self targeted actions unless the actor is
2402 * asking about what can be done to its own tile. */
2403 probabilities[act] = ACTPROB_IMPOSSIBLE;
2404 }
2405 break;
2406 case ATK_COUNT:
2407 fc_assert_action(action_id_get_target_kind(act) != ATK_COUNT,
2408 probabilities[act] = ACTPROB_IMPOSSIBLE);
2409 break;
2410 }
2411 } action_iterate_end;
2412
2413 /* Analyze the probabilities. Decide what targets to send and if an
2414 * explanation is needed. */
2415 action_iterate(act) {
2416 if (action_prob_possible(probabilities[act])) {
2417 /* An action can be done. No need to explain why no action can be
2418 * done. */
2419 at_least_one_action = TRUE;
2420
2421 switch (action_id_get_target_kind(act)) {
2422 case ATK_CITY:
2423 /* The city should be sent as a target since it is possible to act
2424 * against it. */
2425
2426 /* All city targeted actions requires that the player is aware of
2427 * the target city. It is therefore in the player's map. */
2428 fc_assert_action(plrtile, continue);
2429 fc_assert_action(plrtile->site, continue);
2430
2431 target_city_id = plrtile->site->identity;
2432 break;
2433 case ATK_UNIT:
2434 /* The unit should be sent as a target since it is possible to act
2435 * against it. */
2436 fc_assert(target_unit != NULL);
2437 target_unit_id = target_unit->id;
2438 break;
2439 case ATK_TILE:
2440 case ATK_EXTRAS:
2441 /* The target tile isn't selected here so it hasn't changed. */
2442 fc_assert(target_tile != NULL);
2443
2444 if (target_extra && action_id_has_complex_target(act)) {
2445 /* The target extra may have been set here. */
2446 target_extra_id = target_extra->id;
2447 }
2448 break;
2449 case ATK_UNITS:
2450 /* The target tile isn't selected here so it hasn't changed. */
2451 fc_assert(target_tile != NULL);
2452 break;
2453 case ATK_SELF:
2454 /* The target unit is the actor unit. It is already sent. */
2455 fc_assert(actor_unit != NULL);
2456 break;
2457 case ATK_COUNT:
2458 fc_assert_msg(action_id_get_target_kind(act) != ATK_COUNT,
2459 "Invalid action target kind.");
2460 break;
2461 }
2462
2463 if (target_city_id != IDENTITY_NUMBER_ZERO
2464 && target_unit_id != IDENTITY_NUMBER_ZERO) {
2465 /* No need to find out more. */
2466 break;
2467 }
2468 }
2469 } action_iterate_end;
2470
2471 /* Send possible actions and targets. */
2472 dsend_packet_unit_actions(pc,
2473 actor_unit_id, target_unit_id, target_city_id,
2474 target_tile_id, target_extra_id,
2475 request_kind,
2476 probabilities);
2477
2478 if (request_kind == REQEST_PLAYER_INITIATED && !at_least_one_action) {
2479 /* The user should get an explanation why no action is possible. */
2480 explain_why_no_action_enabled(actor_unit,
2481 target_tile, target_city, target_unit);
2482 }
2483}
2484
2485/**********************************************************************/
2492 void illegal_action_msg(struct player *pplayer,
2493 const enum event_type event,
2494 struct unit *actor,
2495 const action_id stopped_action,
2496 const struct tile *target_tile,
2497 const struct city *target_city,
2498 const struct unit *target_unit)
2499{
2500 struct ane_expl *explnat;
2501 const struct civ_map *nmap = &(wld.map);
2502
2503 /* Explain why the action was illegal. */
2504 explnat = expl_act_not_enabl(actor, stopped_action,
2505 target_tile, target_city, target_unit);
2506 switch (explnat->kind) {
2507 case ANEK_ACTOR_UNIT:
2508 {
2509 struct astring astr = ASTRING_INIT;
2510
2511 if (role_units_translations(&astr,
2512 action_id_get_role(stopped_action),
2513 TRUE)) {
2514 notify_player(pplayer, unit_tile(actor),
2515 event, ftc_server,
2516 /* TRANS: Only Diplomat or Spy can do Steal Gold. */
2517 _("Only %s can do %s."),
2518 astr_str(&astr),
2519 action_id_name_translation(stopped_action));
2520 astr_free(&astr);
2521 } else {
2522 notify_player(pplayer, unit_tile(actor),
2523 event, ftc_server,
2524 /* TRANS: Spy can't do Capture Units. */
2525 _("%s can't do %s."),
2526 unit_name_translation(actor),
2527 action_id_name_translation(stopped_action));
2528 }
2529 }
2530 break;
2531 case ANEK_MISSING_TARGET:
2532 notify_player(pplayer, unit_tile(actor), event, ftc_server,
2533 /* TRANS: "Your Spy found ... suitable for
2534 * Bribe Enemy Unit." */
2535 _("Your %s found no target suitable for %s."),
2536 unit_name_translation(actor),
2537 action_id_name_translation(stopped_action));
2538 break;
2539 case ANEK_BAD_TARGET:
2540 notify_player(pplayer, unit_tile(actor), event, ftc_server,
2541 /* TRANS: "Having your Spy do Bribe Enemy Unit to
2542 * this target ..." */
2543 _("Having your %s do %s to this target is redundant."),
2544 unit_name_translation(actor),
2545 action_id_name_translation(stopped_action));
2546 break;
2547 case ANEK_BAD_TERRAIN_ACT:
2548 {
2549 const char *types[utype_count()];
2550 int i = 0;
2551
2552 if (!utype_can_do_act_when_ustate(unit_type_get(actor),
2553 stopped_action, USP_LIVABLE_TILE,
2554 FALSE)
2555 && !can_unit_exist_at_tile(nmap, actor, unit_tile(actor))) {
2556 unit_type_iterate(utype) {
2557 if (utype_can_do_act_when_ustate(utype, stopped_action,
2558 USP_LIVABLE_TILE, FALSE)) {
2559 types[i++] = utype_name_translation(utype);
2560 }
2561 } unit_type_iterate_end;
2562 }
2563
2564 if (0 < i) {
2565 struct astring astr = ASTRING_INIT;
2566
2567 notify_player(pplayer, unit_tile(actor),
2568 event, ftc_server,
2569 /* TRANS: action name.
2570 * "Your Spy can't do Steal Gold from Ocean.
2571 * Only Explorer or Partisan can do Steal Gold ..." */
2572 _("Your %s can't do %s from %s. "
2573 "Only %s can do %s from a non livable tile."),
2574 unit_name_translation(actor),
2575 action_id_name_translation(stopped_action),
2576 terrain_name_translation(explnat->no_act_terrain),
2577 astr_build_or_list(&astr, types, i),
2578 action_id_name_translation(stopped_action));
2579
2580 astr_free(&astr);
2581 } else {
2582 notify_player(pplayer, unit_tile(actor),
2583 event, ftc_server,
2584 /* TRANS: action name.
2585 * "Your Spy can't do Steal Gold from Ocean." */
2586 _("Your %s can't do %s from %s."),
2587 unit_name_translation(actor),
2588 action_id_name_translation(stopped_action),
2589 terrain_name_translation(explnat->no_act_terrain));
2590 }
2591 }
2592 break;
2593 case ANEK_BAD_TERRAIN_TGT:
2594 notify_player(pplayer, unit_tile(actor),
2595 event, ftc_server,
2596 /* TRANS: action name.
2597 * "Your Spy can't do Industrial Sabotage to Mountains." */
2598 _("Your %s can't do %s to %s."),
2599 unit_name_translation(actor),
2600 action_id_name_translation(stopped_action),
2601 terrain_name_translation(explnat->no_act_terrain));
2602 break;
2603 case ANEK_IS_TRANSPORTED:
2604 notify_player(pplayer, unit_tile(actor),
2605 event, ftc_server,
2606 /* TRANS: action name.
2607 * "Your Spy can't do Industrial Sabotage while ..." */
2608 _("Your %s can't do %s while being transported."),
2609 unit_name_translation(actor),
2610 action_id_name_translation(stopped_action));
2611 break;
2612 case ANEK_IS_NOT_TRANSPORTED:
2613 notify_player(pplayer, unit_tile(actor),
2614 event, ftc_server,
2615 /* TRANS: action name.
2616 * "Your Spy can't do Industrial Sabotage while ..." */
2617 _("Your %s can't do %s while not being transported."),
2618 unit_name_translation(actor),
2619 action_id_name_translation(stopped_action));
2620 break;
2621 case ANEK_IS_TRANSPORTING:
2622 notify_player(pplayer, unit_tile(actor),
2623 event, ftc_server,
2624 /* TRANS: action name.
2625 * "Your Spy can't do Industrial Sabotage while ..." */
2626 _("Your %s can't do %s while transporting."),
2627 unit_name_translation(actor),
2628 action_id_name_translation(stopped_action));
2629 break;
2630 case ANEK_IS_NOT_TRANSPORTING:
2631 notify_player(pplayer, unit_tile(actor),
2632 event, ftc_server,
2633 /* TRANS: action name.
2634 * "Your Spy can't do Industrial Sabotage while ..." */
2635 _("Your %s can't do %s while not transporting."),
2636 unit_name_translation(actor),
2637 action_id_name_translation(stopped_action));
2638 break;
2639 case ANEK_ACTOR_HAS_HOME_CITY:
2640 notify_player(pplayer, unit_tile(actor),
2641 event, ftc_server,
2642 /* TRANS: action name.
2643 * "Your Spy can't do Industrial Sabotage because ..." */
2644 _("Your %s can't do %s because it has a home city."),
2645 unit_name_translation(actor),
2646 action_id_name_translation(stopped_action));
2647 break;
2648 case ANEK_ACTOR_HAS_NO_HOME_CITY:
2649 notify_player(pplayer, unit_tile(actor),
2650 event, ftc_server,
2651 /* TRANS: action name.
2652 * "Your Spy can't do Industrial Sabotage because ..." */
2653 _("Your %s can't do %s because it is homeless."),
2654 unit_name_translation(actor),
2655 action_id_name_translation(stopped_action));
2656 break;
2657 case ANEK_NO_WAR:
2658 notify_player(pplayer, unit_tile(actor),
2659 event, ftc_server,
2660 /* TRANS: action name.
2661 * "Your Spy can't do Industrial Sabotage while you
2662 * aren't at war with Prester John." */
2663 _("Your %s can't do %s while you"
2664 " aren't at war with %s."),
2665 unit_name_translation(actor),
2666 action_id_name_translation(stopped_action),
2667 player_name(explnat->no_war_with));
2668 break;
2669 case ANEK_PEACE:
2670 notify_player(pplayer, unit_tile(actor),
2671 event, ftc_server,
2672 /* TRANS: action name.
2673 * "Your Spy can't do Industrial Sabotage while you
2674 * are at peace with Prester John. Try using the
2675 * Nations report (F3)." */
2676 _("Your %s can't do %s while you "
2677 "are at peace with %s. Try using "
2678 "the Nations report to declare war"
2679#ifndef FREECIV_WEB
2680 " (F3)"
2681#endif /* FREECIV_WEB */
2682 "."),
2683 unit_name_translation(actor),
2684 action_id_name_translation(stopped_action),
2685 player_name(explnat->peace_with));
2686 break;
2687 case ANEK_DOMESTIC:
2688 notify_player(pplayer, unit_tile(actor),
2689 event, ftc_server,
2690 /* TRANS: action name.
2691 * "Your Riflemen can't do Expel Unit to domestic
2692 * unit stacks." */
2693 _("Your %s can't do %s to domestic %s."),
2694 unit_name_translation(actor),
2695 action_id_name_translation(stopped_action),
2696 action_target_kind_translated_name(
2697 action_id_get_target_kind(stopped_action)));
2698 break;
2699 case ANEK_FOREIGN:
2700 notify_player(pplayer, unit_tile(actor),
2701 event, ftc_server,
2702 /* TRANS: action name.
2703 * "Your Leader can't do Use Court Physician to foreign
2704 * unit stacks." */
2705 _("Your %s can't do %s to foreign %s."),
2706 unit_name_translation(actor),
2707 action_id_name_translation(stopped_action),
2708 action_target_kind_translated_name(
2709 action_id_get_target_kind(stopped_action)));
2710 break;
2711 case ANEK_TGT_NON_ALLIED_UNITS_ON_TILE:
2712 notify_player(pplayer, unit_tile(actor),
2713 event, ftc_server,
2714 /* TRANS: Paratroopers ... Drop Paratrooper */
2715 _("Your %s can't do %s to tiles with non allied units."),
2716 unit_name_translation(actor),
2717 action_id_name_translation(stopped_action));
2718 break;
2719 case ANEK_NATION_ACT:
2720 notify_player(pplayer, unit_tile(actor),
2721 event, ftc_server,
2722 /* TRANS: action name.
2723 * "Swedish Riflemen can't do Expel Unit." */
2724 _("%s %s can't do %s."),
2725 nation_adjective_translation(explnat->no_act_nation),
2726 unit_name_translation(actor),
2727 action_id_name_translation(stopped_action));
2728 break;
2729 case ANEK_NATION_TGT:
2730 notify_player(pplayer, unit_tile(actor),
2731 event, ftc_server,
2732 /* TRANS: action name.
2733 * "Riflemen... Expel Unit... Pirate Migrants." */
2734 _("Your %s can't do %s to %s %s."),
2735 unit_name_translation(actor),
2736 action_id_name_translation(stopped_action),
2737 nation_adjective_translation(explnat->no_act_nation),
2738 action_target_kind_translated_name(
2739 action_id_get_target_kind(stopped_action)));
2740 break;
2741 case ANEK_LOW_MP:
2742 notify_player(pplayer, unit_tile(actor),
2743 event, ftc_server,
2744 /* TRANS: action name.
2745 * "Your Spy has ... to do Bribe Enemy Unit." */
2746 _("Your %s has too few moves left to do %s."),
2747 unit_name_translation(actor),
2748 action_id_name_translation(stopped_action));
2749 break;
2750 case ANEK_IS_CITY_CENTER:
2751 notify_player(pplayer, unit_tile(actor),
2752 event, ftc_server,
2753 /* TRANS: action name.
2754 * "Your Spy can't do Bribe Enemy Unit to city centers." */
2755 _("Your %s can't do %s to city centers."),
2756 unit_name_translation(actor),
2757 action_id_name_translation(stopped_action));
2758 break;
2759 case ANEK_IS_NOT_CITY_CENTER:
2760 notify_player(pplayer, unit_tile(actor),
2761 event, ftc_server,
2762 /* TRANS: action name.
2763 * "Your Spy can only do Investigate City to
2764 * city centers." */
2765 _("Your %s can only do %s to city centers."),
2766 unit_name_translation(actor),
2767 action_id_name_translation(stopped_action));
2768 break;
2769 case ANEK_TGT_IS_CLAIMED:
2770 notify_player(pplayer, unit_tile(actor),
2771 event, ftc_server,
2772 /* TRANS: action name.
2773 * "Your Settlers can't do Build City to claimed tiles." */
2774 _("Your %s can't do %s to claimed tiles."),
2775 unit_name_translation(actor),
2776 action_id_name_translation(stopped_action));
2777 break;
2778 case ANEK_TGT_IS_UNCLAIMED:
2779 notify_player(pplayer, unit_tile(actor),
2780 event, ftc_server,
2781 /* TRANS: action name.
2782 * "Your Spy can't do Bribe Enemy Unit to
2783 * unclaimed tiles." */
2784 _("Your %s can't do %s to unclaimed tiles."),
2785 unit_name_translation(actor),
2786 action_id_name_translation(stopped_action));
2787 break;
2788 case ANEK_DISTANCE_NEAR:
2789 notify_player(pplayer, unit_tile(actor),
2790 event, ftc_server,
2791 /* TRANS: action name.
2792 * "Your Spy must be at least 2 tiles away to do
2793 * Incite a Revolt and Escape." */
2794 PL_("Your %s must be at least %d tile away to do %s.",
2795 "Your %s must be at least %d tiles away to do %s.",
2796 explnat->distance),
2797 unit_name_translation(actor),
2798 explnat->distance,
2799 action_id_name_translation(stopped_action));
2800 break;
2801 case ANEK_DISTANCE_FAR:
2802 notify_player(pplayer, unit_tile(actor),
2803 event, ftc_server,
2804 /* TRANS: action name.
2805 * "Your Diplomat can't be more than 1 tile away to do
2806 * Establish Embassy." */
2807 PL_("Your %s can't be more than %d tile away to do %s.",
2808 "Your %s can't be more than %d tiles away to do %s.",
2809 explnat->distance),
2810 unit_name_translation(actor),
2811 explnat->distance,
2812 action_id_name_translation(stopped_action));
2813 break;
2814 case ANEK_SCENARIO_DISABLED:
2815 notify_player(pplayer, unit_tile(actor),
2816 event, ftc_server,
2817 /* TRANS: Can't do Build City in this scenario. */
2818 _("Can't do %s in this scenario."),
2819 action_id_name_translation(stopped_action));
2820 break;
2821 case ANEK_CITY_TOO_CLOSE_TGT:
2822 notify_player(pplayer, unit_tile(actor),
2823 event, ftc_server,
2824 /* TRANS: Can't do Build City this close to a city. */
2825 _("Can't do %s this close to a city."),
2826 action_id_name_translation(stopped_action));
2827 break;
2828 case ANEK_CITY_TOO_BIG:
2829 notify_player(pplayer, unit_tile(actor),
2830 event, ftc_server,
2831 /* TRANS: Settlers ... Join City ... London */
2832 _("%s can't do %s to %s. It is too big."),
2833 unit_name_translation(actor),
2834 action_id_name_translation(stopped_action),
2835 city_name_get(target_city));
2836 break;
2837 case ANEK_CITY_POP_LIMIT:
2838 notify_player(pplayer, unit_tile(actor),
2839 event, ftc_server,
2840 /* TRANS: London ... Settlers ... Join City */
2841 _("%s needs an improvement to grow, so "
2842 "%s cannot do %s."),
2843 city_name_get(target_city),
2844 unit_name_translation(actor),
2845 action_id_name_translation(stopped_action));
2846 break;
2847 case ANEK_CITY_NO_CAPACITY:
2848 notify_player(pplayer, unit_tile(actor),
2849 event, ftc_server,
2850 /* TRANS: Paris ... Airlift to City ... Warriors */
2851 _("%s has no capacity to %s %s."),
2852 city_name_get(explnat->capacity_city),
2853 action_id_name_translation(stopped_action),
2854 unit_name_translation(actor));
2855 break;
2856 case ANEK_TGT_TILE_UNKNOWN:
2857 notify_player(pplayer, unit_tile(actor),
2858 event, ftc_server,
2859 /* TRANS: Paratroopers ... Drop Paratrooper */
2860 _("%s can't do %s to an unknown tile."),
2861 unit_name_translation(actor),
2862 action_id_name_translation(stopped_action));
2863 break;
2864 case ANEK_ACT_NOT_ENOUGH_MONEY:
2865 {
2866 char tbuf[MAX_LEN_MSG];
2867
2868 /* TRANS: Used below. Separate so treasury content too can determine
2869 * if this is plural. */
2870 fc_snprintf(tbuf, ARRAY_SIZE(tbuf), PL_("Treasury contains %d gold.",
2871 "Treasury contains %d gold.",
2872 pplayer->economic.gold),
2873 pplayer->economic.gold);
2874
2875 notify_player(pplayer, unit_tile(actor),
2876 event, ftc_server,
2877 /* TRANS: "Spy can't do Bribe Unit for 154 gold.
2878 * Treasury contains 100 gold." */
2879 PL_("%s can't do %s for %d gold. %s",
2880 "%s can't do %s for %d gold. %s",
2881 explnat->gold_needed),
2882 unit_name_translation(actor),
2883 action_id_name_translation(stopped_action),
2884 explnat->gold_needed, tbuf);
2885 }
2886 break;
2887 case ANEK_TRIREME_MOVE:
2888 notify_player(pplayer, target_tile, event, ftc_server,
2889 /* TRANS: "Trireme cannot move ..." */
2890 _("%s cannot move that far from the coast line."),
2891 unit_link(actor));
2892 break;
2893 case ANEK_DISEMBARK_ACT:
2894 notify_player(pplayer, unit_tile(actor), event, ftc_server,
2895 /* TRANS: "Riflemen cannot disembark ... native base
2896 * for Helicopter." */
2897 _("%s cannot disembark outside of a city or a native base "
2898 "for %s."),
2899 unit_link(actor),
2900 utype_name_translation(
2901 unit_type_get(unit_transport_get(actor))));
2902 break;
2903 case ANEK_TGT_UNREACHABLE:
2904 notify_player(pplayer, target_tile,
2905 event, ftc_server,
2906 /* TRANS: "Your Spy can't do Bribe Enemy Unit there ..." */
2907 _("Your %s can't do %s there since there's an "
2908 "unreachable unit."),
2909 unit_name_translation(actor),
2910 action_id_name_translation(stopped_action));
2911 break;
2912 case ANEK_NOT_WIPABLE:
2913 notify_player(pplayer, target_tile,
2914 event, ftc_server,
2915 /* TRANS: "Your Legion can't do Wipe Units there ..." */
2916 _("Your %s can't do %s there since there's an "
2917 "unit with positive defense value."),
2918 unit_name_translation(actor),
2919 action_id_name_translation(stopped_action));
2920 break;
2921 case ANEK_TGT_IS_UNIQUE_ACT_HAS:
2922 notify_player(pplayer, target_tile, event, ftc_server,
2923 /* TRANS: "You already have a Leader." */
2924 _("You already have a %s."),
2925 utype_name_translation(explnat->no_tgt_utype));
2926 break;
2927 case ANEK_ACTION_BLOCKS:
2928 {
2929 char *stop_act_name = fc_strdup(action_id_name_translation(stopped_action));
2930
2931 notify_player(pplayer, unit_tile(actor),
2932 event, ftc_server,
2933 /* TRANS: Freight ... Disband Unit Recover ... Help Wonder ... */
2934 _("Your %s can't do %s when %s is legal."),
2935 unit_name_translation(actor),
2936 stop_act_name,
2937 action_id_name_translation(explnat->blocker->id));
2938 free(stop_act_name);
2939 }
2940 break;
2941 case ANEK_UNKNOWN:
2942 notify_player(pplayer, unit_tile(actor),
2943 event, ftc_server,
2944 /* TRANS: action name.
2945 * "Your Spy was unable to do Bribe Enemy Unit." */
2946 _("Your %s was unable to do %s."),
2947 unit_name_translation(actor),
2948 action_id_name_translation(stopped_action));
2949 break;
2950 }
2951
2952 free(explnat);
2953}
2954
2955/**********************************************************************/
2968 static bool illegal_action_pay_price(struct player *pplayer,
2969 bool information_revealed,
2970 struct unit *act_unit,
2971 struct action *stopped_action,
2972 struct player *tgt_player,
2973 struct tile *tgt_tile,
2974 const enum action_requester requester)
2975{
2976 int punishment_mp;
2977 int punishment_hp;
2978
2979 const struct req_context actor_ctxt = {
2980 .player = unit_owner(act_unit),
2981 .unit = act_unit,
2982 .unittype = unit_type_get(act_unit),
2983 .action = stopped_action,
2984 };
2985
2986 /* Don't punish the player for something the game did. Don't tell the
2987 * player that the rules required the game to try to do something
2988 * illegal. */
2989 fc_assert_ret_val_msg((requester == ACT_REQ_PLAYER
2990 || requester == ACT_REQ_SS_AGENT),
2991 FALSE,
2992 "The player wasn't responsible for this.");
2993
2994 if (!information_revealed) {
2995 /* The player already had enough information to determine that this
2996 * action is illegal. Don't punish a client error or an accident. */
2997 return FALSE;
2998 }
2999
3000 /* The mistake may have a cost. */
3001
3002 /* HP cost */
3003 punishment_hp = get_target_bonus_effects(NULL, &actor_ctxt, tgt_player,
3004 EFT_ILLEGAL_ACTION_HP_COST);
3005
3006 /* Stay in range */
3007 punishment_hp = MAX(0, punishment_hp);
3008
3009 /* Punish the unit's hit points. */
3010 act_unit->hp = MAX(0, act_unit->hp - punishment_hp);
3011
3012 if (punishment_hp != 0) {
3013 if (utype_is_moved_to_tgt_by_action(stopped_action,
3014 unit_type_get(act_unit))) {
3015 /* The consolation prize is some information about the potentially
3016 * distant target tile and maybe some contacts. */
3017 map_show_circle(pplayer, tgt_tile,
3018 unit_type_get(act_unit)->vision_radius_sq);
3019 maybe_make_contact(tgt_tile, pplayer);
3020 }
3021
3022 if (act_unit->hp > 0) {
3023 /* The actor unit survived */
3024
3025 /* The player probably wants to be disturbed if their unit was punished
3026 * with the loss of hit points. */
3027 notify_player(pplayer, unit_tile(act_unit),
3028 E_UNIT_ILLEGAL_ACTION, ftc_server,
3029 /* TRANS: Spy ... 5 ... Drop Paratrooper */
3030 _("Your %s lost %d hit points while attempting to"
3031 " do %s."),
3032 unit_name_translation(act_unit), punishment_hp,
3033 action_name_translation(stopped_action));
3034 send_unit_info(NULL, act_unit);
3035 } else {
3036 /* The unit didn't survive */
3037
3038 /* The player probably wants to be disturbed if their unit was punished
3039 * with death. */
3040 notify_player(pplayer, unit_tile(act_unit),
3041 E_UNIT_ILLEGAL_ACTION, ftc_server,
3042 /* TRANS: Spy ... Drop Paratrooper */
3043 _("Your %s was killed while attempting to do %s."),
3044 unit_name_translation(act_unit),
3045 action_name_translation(stopped_action));
3046
3047 wipe_unit(act_unit, ULR_KILLED, NULL);
3048 act_unit = NULL;
3049
3050 return TRUE;
3051 }
3052 }
3053
3054 /* MP cost */
3055 punishment_mp = get_target_bonus_effects(NULL, &actor_ctxt, tgt_player,
3056 EFT_ILLEGAL_ACTION_MOVE_COST);
3057
3058 /* Stay in range */
3059 punishment_mp = MAX(0, punishment_mp);
3060
3061 /* Punish the unit's move fragments. */
3062 act_unit->moves_left = MAX(0, act_unit->moves_left - punishment_mp);
3063 send_unit_info(NULL, act_unit);
3064
3065 if (punishment_mp != 0) {
3066 /* The player probably wants to be disturbed if their unit was punished
3067 * with the loss of movement points. */
3068 notify_player(pplayer, unit_tile(act_unit),
3069 E_UNIT_ILLEGAL_ACTION, ftc_server,
3070 /* TRANS: Spy ... movement point text that may include
3071 * fractions. */
3072 _("Your %s lost %s MP for attempting an illegal action."),
3073 unit_name_translation(act_unit),
3074 move_points_text(punishment_mp, TRUE));
3075 }
3076
3077 return punishment_mp != 0 || punishment_hp != 0;
3078}
3079
3080/**********************************************************************/
3085 static void illegal_action(struct player *pplayer,
3086 struct unit *actor,
3087 action_id stopped_action_id,
3088 struct player *tgt_player,
3089 struct tile *target_tile,
3090 const struct city *target_city,
3091 const struct unit *target_unit,
3092 int request_kind,
3093 const enum action_requester requester)
3094{
3095 bool information_revealed;
3096 bool was_punished;
3097
3098 struct action *stopped_action = action_by_number(stopped_action_id);
3099
3100 /* Why didn't the game check before trying something illegal? Did a good
3101 * reason to not call is_action_enabled_unit_on...() appear? The game is
3102 * omniscient... */
3103 fc_assert(requester != ACT_REQ_RULES);
3104
3105
3106 information_revealed = action_prob_possible(action_prob_unit_vs_tgt(
3107 stopped_action,
3108 actor,
3109 target_city, target_unit,
3110 target_tile, NULL));
3111
3112 if (request_kind == REQEST_PLAYER_INITIATED) {
3113 /* This is a foreground request. */
3114 illegal_action_msg(pplayer, (information_revealed
3115 ? E_UNIT_ILLEGAL_ACTION : E_BAD_COMMAND),
3116 actor, stopped_action_id,
3117 target_tile, target_city, target_unit);
3118 }
3119
3120 was_punished = illegal_action_pay_price(pplayer, information_revealed,
3121 actor, stopped_action,
3122 tgt_player, target_tile,
3123 requester);
3124
3125 if (request_kind != REQEST_PLAYER_INITIATED && was_punished) {
3126 /* FIXME: Temporary work around to prevent wrong information and/or
3127 * crashes. See hrm Bug #879880 */
3128 /* TODO: Get the explanation before the punishment and show it here.
3129 * See hrm Bug #879881 */
3130 notify_player(pplayer, unit_tile(actor),
3131 (information_revealed
3132 ? E_UNIT_ILLEGAL_ACTION : E_BAD_COMMAND), ftc_server,
3133 _("No explanation why you couldn't do %s. This is a bug."
3134 " Sorry about that. -- Sveinung"),
3135 action_id_name_translation(stopped_action_id));
3136 }
3137}
3138
3139/**********************************************************************/
3142 static void unit_query_impossible(struct connection *pc,
3143 const int actor_id,
3144 const int target_id,
3145 int request_kind)
3146{
3147 dsend_packet_unit_action_answer(pc,
3148 actor_id, target_id,
3149 0,
3150 ACTION_NONE,
3151 request_kind);
3152}
3153
3154/**********************************************************************/
3161 void handle_unit_action_query(struct connection *pc,
3162 const int actor_id,
3163 const int target_id,
3164 const action_id action_type,
3165 int request_kind)
3166{
3167 struct player *pplayer = pc->playing;
3168 struct unit *pactor = player_unit_by_number(pplayer, actor_id);
3169 struct action *paction = action_by_number(action_type);
3170 struct unit *punit = game_unit_by_number(target_id);
3171 struct city *pcity = game_city_by_number(target_id);
3172 const struct civ_map *nmap = &(wld.map);
3173
3174 if (NULL == paction) {
3175 /* Non existing action */
3176 log_error("handle_unit_action_query() the action %d doesn't exist.",
3177 action_type);
3178
3179 unit_query_impossible(pc, actor_id, target_id, request_kind);
3180 return;
3181 }
3182
3183 if (NULL == pactor) {
3184 /* Probably died or bribed. */
3185 log_verbose("handle_unit_action_query() invalid actor %d",
3186 actor_id);
3187 unit_query_impossible(pc, actor_id, target_id, request_kind);
3188 return;
3189 }
3190
3191 switch (paction->result) {
3192 case ACTRES_SPY_BRIBE_UNIT:
3193 if (punit
3194 && is_action_enabled_unit_on_unit(nmap, action_type,
3195 pactor, punit)) {
3196 dsend_packet_unit_action_answer(pc,
3197 actor_id, target_id,
3198 unit_bribe_cost(punit, pplayer),
3199 action_type, request_kind);
3200 } else {
3201 illegal_action(pplayer, pactor, action_type,
3202 punit ? unit_owner(punit) : NULL,
3203 NULL, NULL, punit, request_kind, ACT_REQ_PLAYER);
3204 unit_query_impossible(pc, actor_id, target_id, request_kind);
3205 return;
3206 }
3207 break;
3208 case ACTRES_SPY_INCITE_CITY:
3209 if (pcity
3210 && is_action_enabled_unit_on_city(nmap, action_type,
3211 pactor, pcity)) {
3212 dsend_packet_unit_action_answer(pc,
3213 actor_id, target_id,
3214 city_incite_cost(pplayer, pcity),
3215 action_type, request_kind);
3216 } else {
3217 illegal_action(pplayer, pactor, action_type,
3218 pcity ? city_owner(pcity) : NULL,
3219 NULL, pcity, NULL, request_kind, ACT_REQ_PLAYER);
3220 unit_query_impossible(pc, actor_id, target_id, request_kind);
3221 return;
3222 }
3223 break;
3224 case ACTRES_UPGRADE_UNIT:
3225 if (pcity
3226 && is_action_enabled_unit_on_city(nmap, action_type,
3227 pactor, pcity)) {
3228 const struct unit_type *tgt_utype;
3229 int upgr_cost;
3230
3231 tgt_utype = can_upgrade_unittype(pplayer, unit_type_get(pactor));
3232 /* Already checked via is_action_enabled_unit_on_city() */
3233 fc_assert_ret(tgt_utype);
3234 upgr_cost = unit_upgrade_price(pplayer,
3235 unit_type_get(pactor), tgt_utype);
3236
3237 dsend_packet_unit_action_answer(pc,
3238 actor_id, target_id,
3239 upgr_cost, action_type,
3240 request_kind);
3241 } else {
3242 illegal_action(pplayer, pactor, action_type,
3243 pcity ? city_owner(pcity) : NULL,
3244 NULL, pcity, NULL, request_kind, ACT_REQ_PLAYER);
3245 unit_query_impossible(pc, actor_id, target_id, request_kind);
3246 return;
3247 }
3248 break;
3249 case ACTRES_SPY_TARGETED_SABOTAGE_CITY:
3250 case ACTRES_STRIKE_BUILDING:
3251 if (pcity
3252 && is_action_enabled_unit_on_city(nmap, action_type,
3253 pactor, pcity)) {
3254 spy_send_sabotage_list(pc, pactor, pcity,
3255 action_by_number(action_type), request_kind);
3256 } else {
3257 illegal_action(pplayer, pactor, action_type,
3258 pcity ? city_owner(pcity) : NULL,
3259 NULL, pcity, NULL, request_kind, ACT_REQ_PLAYER);
3260 unit_query_impossible(pc, actor_id, target_id, request_kind);
3261 return;
3262 }
3263 break;
3264 default:
3265 unit_query_impossible(pc, actor_id, target_id, request_kind);
3266 return;
3267 };
3268}
3269
3270/**********************************************************************/
3275 void handle_unit_do_action(struct player *pplayer,
3276 const int actor_id,
3277 const int target_id,
3278 const int sub_tgt_id,
3279 const char *name,
3280 const action_id action_type)
3281{
3282 (void) unit_perform_action(pplayer, actor_id, target_id, sub_tgt_id, name,
3283 action_type, ACT_REQ_PLAYER);
3284}
3285
3286/**********************************************************************/
3291 void unit_do_action(struct player *pplayer,
3292 const int actor_id,
3293 const int target_id,
3294 const int sub_tgt_id,
3295 const char *name,
3296 const action_id action_type)
3297{
3298 unit_perform_action(pplayer, actor_id, target_id,
3299 sub_tgt_id, name, action_type, ACT_REQ_PLAYER);
3300}
3301
3302/**********************************************************************/
3311 bool unit_perform_action(struct player *pplayer,
3312 const int actor_id,
3313 const int target_id,
3314 const int sub_tgt_id_incoming,
3315 const char *name,
3316 const action_id action_type,
3317 const enum action_requester requester)
3318{
3319 struct action *paction;
3320 int sub_tgt_id;
3321 struct unit *actor_unit = player_unit_by_number(pplayer, actor_id);
3322 struct tile *target_tile = NULL;
3323 struct extra_type *target_extra;
3324 struct impr_type *sub_tgt_impr;
3325 struct unit *punit = NULL;
3326 struct city *pcity = NULL;
3327 const struct civ_map *nmap = &(wld.map);
3328
3329 if (!action_id_exists(action_type)) {
3330 /* Non existing action */
3331 log_error("unit_perform_action() the action %d doesn't exist.",
3332 action_type);
3333
3334 return FALSE;
3335 }
3336
3337 paction = action_by_number(action_type);
3338
3339 if (NULL == actor_unit) {
3340 /* Probably died or bribed. */
3341 log_verbose("unit_perform_action() invalid actor %d",
3342 actor_id);
3343 return FALSE;
3344 }
3345
3346 switch (action_get_target_kind(paction)) {
3347 case ATK_CITY:
3348 pcity = game_city_by_number(target_id);
3349 if (pcity == NULL) {
3350 log_verbose("unit_perform_action() invalid target city %d",
3351 target_id);
3352 return FALSE;
3353 }
3354 target_tile = city_tile(pcity);
3355 fc_assert_ret_val(target_tile != NULL, FALSE);
3356 break;
3357 case ATK_UNIT:
3358 punit = game_unit_by_number(target_id);
3359 if (punit == NULL) {
3360 log_verbose("unit_perform_action() invalid target unit %d",
3361 target_id);
3362 return FALSE;
3363 }
3364 target_tile = unit_tile(punit);
3365 fc_assert_ret_val(target_tile != NULL, FALSE);
3366 pcity = tile_city(target_tile);
3367 break;
3368 case ATK_UNITS:
3369 case ATK_TILE:
3370 case ATK_EXTRAS:
3371 target_tile = index_to_tile(nmap, target_id);
3372 if (target_tile == NULL) {
3373 log_verbose("unit_perform_action() invalid target tile %d",
3374 target_id);
3375 return FALSE;
3376 }
3377 pcity = tile_city(target_tile);
3378 break;
3379 case ATK_SELF:
3380 target_tile = unit_tile(actor_unit);
3381 fc_assert_ret_val(target_tile != NULL, FALSE);
3382 pcity = tile_city(target_tile);
3383 break;
3384 case ATK_COUNT:
3385 fc_assert_ret_val(action_get_target_kind(paction) != ATK_COUNT, FALSE);
3386 break;
3387 }
3388
3389 /* Server side sub target assignment */
3390 if (paction->target_complexity == ACT_TGT_COMPL_FLEXIBLE
3391 && sub_tgt_id_incoming == NO_TARGET) {
3392 sub_tgt_id = action_sub_target_id_for_action(paction, actor_unit);
3393 } else {
3394 sub_tgt_id = sub_tgt_id_incoming;
3395 }
3396
3397 if (sub_tgt_id >= 0 && sub_tgt_id < MAX_EXTRA_TYPES
3398 && sub_tgt_id != NO_TARGET) {
3399 target_extra = extra_by_number(sub_tgt_id);
3400 fc_assert(!(target_extra->ruledit_disabled));
3401 } else {
3402 target_extra = NULL;
3403 }
3404
3405 sub_tgt_impr = improvement_by_number(sub_tgt_id);
3406
3407 /* Sub targets should now be assigned */
3408 switch (paction->sub_target_kind) {
3409 case ASTK_NONE:
3410 /* No sub target. */
3411 break;
3412 case ASTK_BUILDING:
3413 if (sub_tgt_impr == NULL) {
3414 /* Missing sub target */
3415 return FALSE;
3416 }
3417 break;
3418 case ASTK_TECH:
3419 /* Not handled here yet */
3420 break;
3421 case ASTK_EXTRA:
3422 case ASTK_EXTRA_NOT_THERE:
3423 if (target_extra == NULL) {
3424 /* Missing sub target */
3425 return FALSE;
3426 }
3427 break;
3428 case ASTK_COUNT:
3429 break;
3430 }
3431
3432 if (action_get_activity(paction) != ACTIVITY_LAST
3433 && unit_activity_needs_target_from_client(
3434 action_get_activity(paction))
3435 && target_extra == NULL) {
3436 /* Missing required action extra target. */
3437 log_verbose("unit_perform_action() action %d requires action "
3438 "but extra id %d is invalid.",
3439 action_type, sub_tgt_id);
3440 return FALSE;
3441 }
3442
3443 if (paction->actor.is_unit.unitwaittime_controlled
3444 && !unit_can_do_action_now(actor_unit)) {
3445 /* Action not possible due to unitwaittime setting. */
3446 return FALSE;
3447 }
3448
3449#define ACTION_PERFORM_UNIT_CITY(action, actor, target, action_performer) \
3450 if (pcity \
3451 && is_action_enabled_unit_on_city(nmap, action_type, \
3452 actor_unit, pcity)) { \
3453 bool success; \
3454 script_server_signal_emit("action_started_unit_city", \
3455 action_by_number(action), actor, target); \
3456 if (!actor || !unit_is_alive(actor_id)) { \
3457 /* Actor unit was destroyed during pre action Lua. */ \
3458 return FALSE; \
3459 } \
3460 if (!target || !city_exist(target_id)) { \
3461 /* Target city was destroyed during pre action Lua. */ \
3462 return FALSE; \
3463 } \
3464 success = action_performer; \
3465 if (success) { \
3466 action_success_actor_price(paction, actor_id, actor); \
3467 } \
3468 script_server_signal_emit("action_finished_unit_city", \
3469 action_by_number(action), success, \
3470 unit_is_alive(actor_id) ? actor : NULL, \
3471 city_exist(target_id) ? target : NULL); \
3472 return success; \
3473 } else { \
3474 illegal_action(pplayer, actor_unit, action_type, \
3475 pcity ? city_owner(pcity) : NULL, NULL, pcity, NULL, \
3476 TRUE, requester); \
3477 }
3478
3479#define ACTION_PERFORM_UNIT_SELF(action, actor, action_performer) \
3480 if (actor_unit \
3481 && is_action_enabled_unit_on_self(action_type, actor_unit)) { \
3482 bool success; \
3483 script_server_signal_emit("action_started_unit_self", \
3484 action_by_number(action), actor); \
3485 if (!actor || !unit_is_alive(actor_id)) { \
3486 /* Actor unit was destroyed during pre action Lua. */ \
3487 return FALSE; \
3488 } \
3489 success = action_performer; \
3490 if (success) { \
3491 action_success_actor_price(paction, actor_id, actor); \
3492 } \
3493 script_server_signal_emit("action_finished_unit_self", \
3494 action_by_number(action), success, \
3495 unit_is_alive(actor_id) ? actor : NULL); \
3496 return success; \
3497 } else { \
3498 illegal_action(pplayer, actor_unit, action_type, \
3499 unit_owner(actor_unit), NULL, NULL, actor_unit, \
3500 TRUE, requester); \
3501 }
3502
3503#define ACTION_PERFORM_UNIT_UNIT(action, actor, target, action_performer) \
3504 if (punit \
3505 && is_action_enabled_unit_on_unit(nmap, action_type, actor_unit, punit)) { \
3506 bool success; \
3507 script_server_signal_emit("action_started_unit_unit", \
3508 action_by_number(action), actor, target); \
3509 if (!actor || !unit_is_alive(actor_id)) { \
3510 /* Actor unit was destroyed during pre action Lua. */ \
3511 return FALSE; \
3512 } \
3513 if (!target || !unit_is_alive(target_id)) { \
3514 /* Target unit was destroyed during pre action Lua. */ \
3515 return FALSE; \
3516 } \
3517 success = action_performer; \
3518 if (success) { \
3519 action_success_actor_price(paction, actor_id, actor); \
3520 action_success_target_pay_mp(paction, target_id, punit); \
3521 } \
3522 script_server_signal_emit("action_finished_unit_unit", \
3523 action_by_number(action), success, \
3524 unit_is_alive(actor_id) ? actor : NULL, \
3525 unit_is_alive(target_id) ? target : NULL); \
3526 return success; \
3527 } else { \
3528 illegal_action(pplayer, actor_unit, action_type, \
3529 punit ? unit_owner(punit) : NULL, NULL, NULL, punit, \
3530 TRUE, requester); \
3531 }
3532
3533#define ACTION_PERFORM_UNIT_UNITS(action, actor, target, action_performer)\
3534 if (target_tile \
3535 && is_action_enabled_unit_on_stack(nmap, action_type, \
3536 actor_unit, target_tile)) { \
3537 bool success; \
3538 script_server_signal_emit("action_started_unit_units", \
3539 action_by_number(action), actor, target); \
3540 if (!actor || !unit_is_alive(actor_id)) { \
3541 /* Actor unit was destroyed during pre action Lua. */ \
3542 return FALSE; \
3543 } \
3544 success = action_performer; \
3545 if (success) { \
3546 action_success_actor_price(paction, actor_id, actor); \
3547 } \
3548 script_server_signal_emit("action_finished_unit_units", \
3549 action_by_number(action), success, \
3550 unit_is_alive(actor_id) ? actor : NULL, \
3551 target); \
3552 return success; \
3553 } else { \
3554 illegal_action(pplayer, actor_unit, action_type, \
3555 NULL, target_tile, NULL, NULL, \
3556 TRUE, requester); \
3557 }
3558
3559#define ACTION_PERFORM_UNIT_TILE(action, actor, target, action_performer) \
3560 if (target_tile \
3561 && is_action_enabled_unit_on_tile(nmap, action_type, \
3562 actor_unit, target_tile, \
3563 target_extra)) { \
3564 bool success; \
3565 script_server_signal_emit("action_started_unit_tile", \
3566 action_by_number(action), actor, target); \
3567 if (!actor || !unit_is_alive(actor_id)) { \
3568 /* Actor unit was destroyed during pre action Lua. */ \
3569 return FALSE; \
3570 } \
3571 success = action_performer; \
3572 if (success) { \
3573 action_success_actor_price(paction, actor_id, actor); \
3574 } \
3575 script_server_signal_emit("action_finished_unit_tile", \
3576 action_by_number(action), success, \
3577 unit_is_alive(actor_id) ? actor : NULL, \
3578 target); \
3579 return success; \
3580 } else { \
3581 illegal_action(pplayer, actor_unit, action_type, \
3582 target_tile ? tile_owner(target_tile) : NULL, \
3583 target_tile, NULL, NULL, \
3584 TRUE, requester); \
3585 }
3586
3587#define ACTION_PERFORM_UNIT_EXTRAS(action, actor, target, action_performer)\
3588 if (target_tile \
3589 && is_action_enabled_unit_on_extras(action_type, \
3590 actor_unit, target_tile, \
3591 target_extra)) { \
3592 bool success; \
3593 script_server_signal_emit("action_started_unit_extras", \
3594 action_by_number(action), actor, target); \
3595 if (!actor || !unit_is_alive(actor_id)) { \
3596 /* Actor unit was destroyed during pre action Lua. */ \
3597 return FALSE; \
3598 } \
3599 success = action_performer; \
3600 if (success) { \
3601 action_success_actor_price(paction, actor_id, actor); \
3602 } \
3603 script_server_signal_emit("action_finished_unit_extras", \
3604 action_by_number(action), success, \
3605 unit_is_alive(actor_id) ? actor : NULL, \
3606 target); \
3607 return success; \
3608 } else { \
3609 illegal_action(pplayer, actor_unit, action_type, \
3610 target_tile ? target_tile->extras_owner : NULL, \
3611 target_tile, NULL, NULL, \
3612 TRUE, requester); \
3613 }
3614
3615#define ACTION_PERFORM_UNIT_ANY(paction, actor, \
3616 target_city, target_unit, target_tile, \
3617 action_performer) \
3618 switch (action_get_target_kind(paction)) { \
3619 case ATK_CITY: \
3620 ACTION_PERFORM_UNIT_CITY(paction->id, actor, target_city, \
3621 action_performer); \
3622 break; \
3623 case ATK_UNIT: \
3624 ACTION_PERFORM_UNIT_UNIT(paction->id, actor, target_unit, \
3625 action_performer); \
3626 break; \
3627 case ATK_UNITS: \
3628 ACTION_PERFORM_UNIT_UNITS(paction->id, actor, target_tile, \
3629 action_performer); \
3630 break; \
3631 case ATK_TILE: \
3632 ACTION_PERFORM_UNIT_TILE(paction->id, actor, target_tile, \
3633 action_performer); \
3634 break; \
3635 case ATK_EXTRAS: \
3636 ACTION_PERFORM_UNIT_EXTRAS(paction->id, actor, target_tile, \
3637 action_performer); \
3638 break; \
3639 case ATK_SELF: \
3640 ACTION_PERFORM_UNIT_SELF(paction->id, actor, TRUE); \
3641 break; \
3642 case ATK_COUNT: \
3643 fc_assert(action_get_target_kind(paction) != ATK_COUNT); \
3644 break; \
3645 }
3646
3647 switch (paction->result) {
3648 case ACTRES_SPY_BRIBE_UNIT:
3649 ACTION_PERFORM_UNIT_UNIT(action_type, actor_unit, punit,
3650 diplomat_bribe(pplayer, actor_unit, punit,
3651 paction));
3652 break;
3653 case ACTRES_SPY_SABOTAGE_UNIT:
3654 /* Difference is caused by data in the action structure. */
3655 ACTION_PERFORM_UNIT_UNIT(action_type, actor_unit, punit,
3656 spy_sabotage_unit(pplayer, actor_unit,
3657 punit, paction));
3658 break;
3659 case ACTRES_EXPEL_UNIT:
3660 ACTION_PERFORM_UNIT_UNIT(action_type, actor_unit, punit,
3661 do_expel_unit(pplayer, actor_unit, punit,
3662 paction));
3663 break;
3664 case ACTRES_HEAL_UNIT:
3665 ACTION_PERFORM_UNIT_UNIT(action_type, actor_unit, punit,
3666 do_heal_unit(pplayer, actor_unit, punit,
3667 paction));
3668 break;
3669 case ACTRES_TRANSPORT_DEBOARD:
3670 ACTION_PERFORM_UNIT_UNIT(action_type, actor_unit, punit,
3671 do_unit_deboard(pplayer, actor_unit, punit,
3672 paction));
3673 break;
3674 case ACTRES_TRANSPORT_UNLOAD:
3675 ACTION_PERFORM_UNIT_UNIT(action_type, actor_unit, punit,
3676 do_unit_unload(pplayer, actor_unit, punit,
3677 paction));
3678 break;
3679 case ACTRES_TRANSPORT_BOARD:
3680 ACTION_PERFORM_UNIT_UNIT(action_type, actor_unit, punit,
3681 do_unit_board(pplayer, actor_unit, punit,
3682 paction));
3683 break;
3684 case ACTRES_TRANSPORT_LOAD:
3685 ACTION_PERFORM_UNIT_UNIT(action_type, actor_unit, punit,
3686 do_unit_load(pplayer, actor_unit, punit,
3687 paction));
3688 break;
3689 case ACTRES_TRANSPORT_EMBARK:
3690 ACTION_PERFORM_UNIT_UNIT(action_type, actor_unit, punit,
3691 do_unit_embark(pplayer, actor_unit, punit,
3692 paction));
3693 break;
3694 case ACTRES_DISBAND_UNIT:
3695 /* All consequences are handled by the action system. */
3696 ACTION_PERFORM_UNIT_SELF(action_type, actor_unit, TRUE);
3697 break;
3698 case ACTRES_FORTIFY:
3699 ACTION_PERFORM_UNIT_SELF(action_type, actor_unit,
3700 do_action_activity(actor_unit, paction));
3701 break;
3702 case ACTRES_CONVERT:
3703 ACTION_PERFORM_UNIT_SELF(action_type, actor_unit,
3704 do_action_activity(actor_unit, paction));
3705 break;
3706 case ACTRES_HOMELESS:
3707 ACTION_PERFORM_UNIT_SELF(action_type, actor_unit,
3708 do_unit_make_homeless(actor_unit, paction));
3709 break;
3710 case ACTRES_SPY_ESCAPE:
3711 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3712 spy_escape(pplayer, actor_unit,
3713 pcity, target_tile, paction));
3714 break;
3715 case ACTRES_SPY_SABOTAGE_CITY:
3716 /* Difference is caused by data in the action structure. */
3717 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3718 diplomat_sabotage(pplayer, actor_unit, pcity,
3719 B_LAST, paction));
3720 break;
3721 case ACTRES_SPY_TARGETED_SABOTAGE_CITY:
3722 /* Difference is caused by data in the action structure. */
3723 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3724 diplomat_sabotage(pplayer, actor_unit, pcity,
3725 sub_tgt_impr->item_number,
3726 paction));
3727 break;
3728 case ACTRES_SPY_SABOTAGE_CITY_PRODUCTION:
3729 /* Difference is caused by data in the action structure. */
3730 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3731 diplomat_sabotage(pplayer, actor_unit, pcity,
3732 -1, paction));
3733 break;
3734 case ACTRES_SPY_POISON:
3735 /* Difference is caused by data in the action structure. */
3736 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3737 spy_poison(pplayer, actor_unit, pcity,
3738 paction));
3739 break;
3740 case ACTRES_SPY_SPREAD_PLAGUE:
3741 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3742 spy_spread_plague(pplayer, actor_unit, pcity,
3743 paction));
3744 break;
3745 case ACTRES_SPY_INVESTIGATE_CITY:
3746 /* Difference is caused by data in the action structure. */
3747 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3748 diplomat_investigate(pplayer,
3749 actor_unit, pcity,
3750 paction));
3751 break;
3752 case ACTRES_ESTABLISH_EMBASSY:
3753 /* Difference is caused by data in the action structure. */
3754 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3755 diplomat_embassy(pplayer, actor_unit, pcity,
3756 paction));
3757 break;
3758 case ACTRES_SPY_INCITE_CITY:
3759 /* Difference is caused by data in the action structure. */
3760 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3761 diplomat_incite(pplayer, actor_unit, pcity,
3762 paction));
3763 break;
3764 case ACTRES_SPY_STEAL_TECH:
3765 /* Difference is caused by data in the action structure. */
3766 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3767 diplomat_get_tech(pplayer, actor_unit, pcity,
3768 A_UNSET, paction));
3769 break;
3770 case ACTRES_SPY_TARGETED_STEAL_TECH:
3771 /* Difference is caused by data in the action structure. */
3772 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3773 diplomat_get_tech(pplayer, actor_unit, pcity,
3774 sub_tgt_id, paction));
3775 break;
3776 case ACTRES_SPY_STEAL_GOLD:
3777 /* Difference is caused by data in the action structure. */
3778 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3779 spy_steal_gold(pplayer, actor_unit, pcity,
3780 paction));
3781 break;
3782 case ACTRES_STEAL_MAPS:
3783 /* Difference is caused by data in the action structure. */
3784 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3785 spy_steal_some_maps(pplayer, actor_unit,
3786 pcity, paction));
3787 break;
3788 case ACTRES_TRADE_ROUTE:
3789 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3790 do_unit_establish_trade(pplayer, actor_unit,
3791 pcity, paction));
3792 break;
3793 case ACTRES_MARKETPLACE:
3794 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3795 do_unit_establish_trade(pplayer, actor_unit,
3796 pcity, paction));
3797 break;
3798 case ACTRES_HELP_WONDER:
3799 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3800 unit_do_help_build(pplayer,
3801 actor_unit, pcity,
3802 paction));
3803 break;
3804 case ACTRES_SPY_NUKE:
3805 /* Difference is caused by data in the action structure. */
3806 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3807 spy_nuke_city(pplayer, actor_unit, pcity,
3808 paction));
3809 break;
3810 case ACTRES_JOIN_CITY:
3811 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3812 city_add_unit(pplayer, actor_unit, pcity,
3813 paction));
3814 break;
3815 case ACTRES_DESTROY_CITY:
3816 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3817 unit_do_destroy_city(pplayer,
3818 actor_unit, pcity,
3819 paction));
3820 break;
3821 case ACTRES_DISBAND_UNIT_RECOVER:
3822 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3823 unit_do_help_build(pplayer, actor_unit, pcity,
3824 paction));
3825 break;
3826 case ACTRES_HOME_CITY:
3827 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3828 do_unit_change_homecity(actor_unit, pcity,
3829 paction));
3830 break;
3831 case ACTRES_UPGRADE_UNIT:
3832 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3833 do_unit_upgrade(pplayer, actor_unit,
3834 pcity, requester, paction));
3835 break;
3836 case ACTRES_CONQUER_CITY:
3837 /* Difference is caused by the ruleset. ("Fake generalized" actions) */
3838 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3839 do_unit_conquer_city(pplayer, actor_unit,
3840 pcity, paction));
3841 break;
3842 case ACTRES_STRIKE_BUILDING:
3843 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3844 do_unit_strike_city_building(pplayer,
3845 actor_unit,
3846 pcity,
3847 sub_tgt_impr->item_number,
3848 paction));
3849 break;
3850 case ACTRES_STRIKE_PRODUCTION:
3851 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3852 do_unit_strike_city_production(pplayer,
3853 actor_unit,
3854 pcity,
3855 paction));
3856 break;
3857 case ACTRES_CONQUER_EXTRAS:
3858 ACTION_PERFORM_UNIT_EXTRAS(action_type, actor_unit, target_tile,
3859 do_conquer_extras(pplayer, actor_unit,
3860 target_tile, paction));
3861 break;
3862 case ACTRES_AIRLIFT:
3863 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3864 do_airline(actor_unit, pcity, paction));
3865 break;
3866 case ACTRES_CAPTURE_UNITS:
3867 ACTION_PERFORM_UNIT_UNITS(action_type, actor_unit, target_tile,
3868 do_capture_units(pplayer, actor_unit,
3869 target_tile, paction));
3870 break;
3871 case ACTRES_BOMBARD:
3872 /* Difference is caused by the ruleset. ("Fake generalized" actions) */
3873 ACTION_PERFORM_UNIT_UNITS(action_type, actor_unit, target_tile,
3874 unit_bombard(actor_unit, target_tile,
3875 paction));
3876 break;
3877 case ACTRES_ATTACK:
3878 case ACTRES_COLLECT_RANSOM:
3879 /* Difference is caused by data in the action structure. */
3880 ACTION_PERFORM_UNIT_UNITS(action_type, actor_unit, target_tile,
3881 do_attack(actor_unit, target_tile, paction));
3882 break;
3883 case ACTRES_WIPE_UNITS:
3884 ACTION_PERFORM_UNIT_UNITS(action_type, actor_unit, target_tile,
3885 do_wipe_units(actor_unit, target_tile, paction));
3886 break;
3887 case ACTRES_NUKE_UNITS:
3888 ACTION_PERFORM_UNIT_UNITS(action_type, actor_unit, target_tile,
3889 unit_nuke(pplayer, actor_unit, target_tile,
3890 paction));
3891 break;
3892 case ACTRES_SPY_ATTACK:
3893 ACTION_PERFORM_UNIT_UNITS(action_type, actor_unit, target_tile,
3894 spy_attack(pplayer, actor_unit, target_tile,
3895 paction));
3896 break;
3897 case ACTRES_FOUND_CITY:
3898 ACTION_PERFORM_UNIT_TILE(action_type, actor_unit, target_tile,
3899 city_build(pplayer, actor_unit,
3900 target_tile, name, paction));
3901 break;
3902 case ACTRES_NUKE:
3903 ACTION_PERFORM_UNIT_ANY(paction, actor_unit,
3904 pcity, punit, target_tile,
3905 unit_nuke(pplayer, actor_unit, target_tile,
3906 paction));
3907 break;
3908 case ACTRES_PARADROP:
3909 case ACTRES_PARADROP_CONQUER:
3910 ACTION_PERFORM_UNIT_TILE(action_type, actor_unit, target_tile,
3911 do_paradrop(actor_unit, target_tile, paction));
3912 break;
3913 case ACTRES_TRANSPORT_DISEMBARK:
3914 /* Difference is caused by the ruleset. ("Fake generalized" actions) */
3915 ACTION_PERFORM_UNIT_TILE(action_type, actor_unit, target_tile,
3916 do_disembark(pplayer, actor_unit,
3917 target_tile, paction));
3918 break;
3919 case ACTRES_HUT_ENTER:
3920 ACTION_PERFORM_UNIT_TILE(action_type, actor_unit, target_tile,
3921 do_unit_hut(pplayer, actor_unit,
3922 target_tile, paction));
3923 break;
3924 case ACTRES_HUT_FRIGHTEN:
3925 ACTION_PERFORM_UNIT_TILE(action_type, actor_unit, target_tile,
3926 do_unit_hut(pplayer, actor_unit,
3927 target_tile, paction));
3928 break;
3929 case ACTRES_UNIT_MOVE:
3930 ACTION_PERFORM_UNIT_TILE(action_type, actor_unit, target_tile,
3931 unit_do_regular_move(pplayer, actor_unit,
3932 target_tile, paction));
3933 break;
3934 case ACTRES_TELEPORT:
3935 case ACTRES_TELEPORT_CONQUER:
3936 ACTION_PERFORM_UNIT_TILE(action_type, actor_unit, target_tile,
3937 unit_move(actor_unit, target_tile, 0,
3938 NULL, FALSE,
3939 paction->result == ACTRES_TELEPORT_CONQUER,
3940 paction->result == ACTRES_TELEPORT_CONQUER,
3941 FALSE, FALSE));
3942 break;
3943 case ACTRES_TRANSFORM_TERRAIN:
3944 ACTION_PERFORM_UNIT_TILE(action_type, actor_unit, target_tile,
3945 do_action_activity(actor_unit, paction));
3946 break;
3947 case ACTRES_CULTIVATE:
3948 ACTION_PERFORM_UNIT_TILE(action_type, actor_unit, target_tile,
3949 do_action_activity(actor_unit, paction));
3950 break;
3951 case ACTRES_PLANT:
3952 ACTION_PERFORM_UNIT_TILE(action_type, actor_unit, target_tile,
3953 do_action_activity(actor_unit, paction));
3954 break;
3955 case ACTRES_PILLAGE:
3956 ACTION_PERFORM_UNIT_ANY(paction, actor_unit, pcity, punit, target_tile,
3957 do_action_activity_targeted(actor_unit,
3958 paction,
3959 &target_extra));
3960 break;
3961 case ACTRES_CLEAN:
3962 ACTION_PERFORM_UNIT_TILE(action_type, actor_unit, target_tile,
3963 do_action_activity_targeted(actor_unit,
3964 paction,
3965 &target_extra));
3966 break;
3967 case ACTRES_ROAD:
3968 ACTION_PERFORM_UNIT_TILE(action_type, actor_unit, target_tile,
3969 do_action_activity_targeted(actor_unit,
3970 paction,
3971 &target_extra));
3972 break;
3973 case ACTRES_BASE:
3974 ACTION_PERFORM_UNIT_TILE(action_type, actor_unit, target_tile,
3975 do_action_activity_targeted(actor_unit,
3976 paction,
3977 &target_extra));
3978 break;
3979 case ACTRES_MINE:
3980 ACTION_PERFORM_UNIT_TILE(action_type, actor_unit, target_tile,
3981 do_action_activity_targeted(actor_unit,
3982 paction,
3983 &target_extra));
3984 break;
3985 case ACTRES_IRRIGATE:
3986 ACTION_PERFORM_UNIT_TILE(action_type, actor_unit, target_tile,
3987 do_action_activity_targeted(actor_unit,
3988 paction,
3989 &target_extra));
3990 break;
3991 case ACTRES_NONE:
3992 /* 100% ruleset defined. */
3993 ACTION_PERFORM_UNIT_ANY(paction, actor_unit, pcity, punit, target_tile,
3994 TRUE);
3995 break;
3996 case ACTRES_ENABLER_CHECK:
3997 fc_assert(paction->result != ACTRES_ENABLER_CHECK);
3998 return FALSE;
3999
4000 ASSERT_UNUSED_ACTRES_CASES;
4001 }
4002
4003 /* Something must have gone wrong. */
4004 return FALSE;
4005}
4006
4007/**********************************************************************/
4014 void unit_change_homecity_handling(struct unit *punit, struct city *new_pcity,
4015 bool rehome)
4016{
4017 struct city *old_pcity = game_city_by_number(punit->homecity);
4018 struct player *old_owner = unit_owner(punit);
4019 struct player *new_owner = (new_pcity == NULL ? old_owner
4020 : city_owner(new_pcity));
4021 const struct civ_map *nmap = &(wld.map);
4022
4023 /* Calling this function when new_pcity is same as old_pcity should
4024 * be safe with current implementation, but it is not meant to
4025 * be used that way. */
4026 fc_assert_ret(new_pcity != old_pcity);
4027
4028 /* If 'rehome' is not set, this function should only be used to change
4029 * which player owns the unit */
4030 fc_assert_ret(rehome || new_owner != old_owner);
4031
4032 if (old_owner != new_owner) {
4033 struct city *pcity = tile_city(punit->tile);
4034
4035 fc_assert(!utype_player_already_has_this_unique(new_owner,
4036 unit_type_get(punit)));
4037
4038 vision_clear_sight(punit->server.vision);
4039 vision_free(punit->server.vision);
4040
4041 if (pcity != NULL
4042 && !can_player_see_units_in_city(old_owner, pcity)) {
4043 /* Special case when city is being transferred. At this point city
4044 * itself has changed owner, so it's enemy city now that old owner
4045 * cannot see inside. All the normal methods of removing transferred
4046 * unit from previous owner's client think that there's no need to
4047 * remove unit as client shouldn't have it in first place. */
4048 unit_goes_out_of_sight(old_owner, punit);
4049 }
4050
4051 /* Remove AI control of the old owner. */
4052 CALL_PLR_AI_FUNC(unit_lost, old_owner, punit);
4053
4054 unit_list_remove(old_owner->units, punit);
4055 unit_list_prepend(new_owner->units, punit);
4056 punit->owner = new_owner;
4057
4058 /* Activate AI control of the new owner. */
4059 CALL_PLR_AI_FUNC(unit_got, new_owner, punit);
4060
4061 punit->server.vision = vision_new(new_owner, unit_tile(punit));
4062 unit_refresh_vision(punit);
4063 }
4064
4065 if (rehome) {
4066 /* Remove from old city first and add to new city only after that. */
4067 if (old_pcity) {
4068 /* Even if unit is dead, we have to unlink unit pointer (punit). */
4069 unit_list_remove(old_pcity->units_supported, punit);
4070 /* update unit upkeep */
4071 city_units_upkeep(old_pcity);
4072 }
4073
4074 if (new_pcity != NULL) {
4075 unit_list_prepend(new_pcity->units_supported, punit);
4076
4077 /* update unit upkeep */
4078 city_units_upkeep(new_pcity);
4079
4080 punit->homecity = new_pcity->id;
4081 } else {
4082 punit->homecity = IDENTITY_NUMBER_ZERO;
4083 }
4084 }
4085
4086 if (!can_unit_continue_current_activity(nmap, punit)) {
4087 /* This is mainly for cases where unit owner changes to one not knowing
4088 * Railroad tech when unit is already building railroad.
4089 * Does also send_unit_info() */
4090 unit_activities_cancel(punit);
4091 } else {
4092 /* Send info to players and observers. */
4093 send_unit_info(NULL, punit);
4094 }
4095
4096 if (new_pcity != NULL) {
4097 city_refresh(new_pcity);
4098 send_city_info(new_owner, new_pcity);
4099 fc_assert(unit_owner(punit) == city_owner(new_pcity));
4100 }
4101
4102 if (old_pcity) {
4103 fc_assert(city_owner(old_pcity) == old_owner);
4104 city_refresh(old_pcity);
4105 send_city_info(old_owner, old_pcity);
4106 }
4107
4108 unit_get_goods(punit);
4109}
4110
4111/**********************************************************************/
4116 static bool do_unit_change_homecity(struct unit *punit,
4117 struct city *pcity,
4118 const struct action *paction)
4119{
4120 const char *giver = NULL;
4121
4122 if (unit_owner(punit) != city_owner(pcity)) {
4123 /* This is a gift. Tell the receiver. */
4124 giver = player_name(unit_owner(punit));
4125 }
4126
4127 unit_change_homecity_handling(punit, pcity, TRUE);
4128
4129 if (punit->homecity == pcity->id && giver) {
4130 /* Notify the city owner about the gift they received. */
4131 notify_player(city_owner(pcity), city_tile(pcity), E_UNIT_BUILT,
4132 ftc_server,
4133 /* TRANS: other player ... unit type ... city name. */
4134 _("%s transferred control over a %s to you in %s."),
4135 giver,
4136 unit_tile_link(punit),
4137 city_link(pcity));;
4138 }
4139
4140 return punit->homecity == pcity->id;
4141}
4142
4143/**********************************************************************/
4150 static bool city_add_unit(struct player *pplayer, struct unit *punit,
4151 struct city *pcity, const struct action *paction)
4152{
4153 int amount = unit_pop_value(punit);
4154 const struct unit_type *act_utype;
4155
4156 /* Sanity check: The actor is still alive. */
4157 fc_assert_ret_val(punit, FALSE);
4158
4159 act_utype = unit_type_get(punit);
4160
4161 /* Sanity check: The target city still exists. */
4162 fc_assert_ret_val(pcity, FALSE);
4163
4164 fc_assert_ret_val(amount > 0, FALSE);
4165
4166 city_size_add(pcity, amount);
4167 /* Make the new people something, otherwise city fails the checks */
4168 pcity->specialists[DEFAULT_SPECIALIST] += amount;
4169 citizens_update(pcity, unit_nationality(punit));
4170 /* Refresh the city data. */
4171 city_refresh(pcity);
4172
4173 /* Notify the unit owner that the unit successfully joined the city. */
4174 notify_player(pplayer, city_tile(pcity), E_CITY_BUILD, ftc_server,
4175 _("%s added to aid %s in growing."),
4176 unit_tile_link(punit),
4177 city_link(pcity));
4178 if (pplayer != city_owner(pcity)) {
4179 /* Notify the city owner when a foreign unit joins a city. */
4180 notify_player(city_owner(pcity), city_tile(pcity), E_CITY_BUILD,
4181 ftc_server,
4182 /* TRANS: another player had their unit join your city. */
4183 _("%s adds %s to your city %s."),
4184 player_name(unit_owner(punit)),
4185 unit_tile_link(punit),
4186 city_link(pcity));;
4187 }
4188
4189 action_consequence_success(paction, pplayer, act_utype,
4190 city_owner(pcity), city_tile(pcity),
4191 city_link(pcity));
4192
4193 sanity_check_city(pcity);
4194
4195 send_city_info(NULL, pcity);
4196
4197 script_server_signal_emit("city_size_change", pcity,
4198 (lua_Integer)amount, "unit_added");
4199
4200 return TRUE;
4201}
4202
4203/**********************************************************************/
4212 static bool city_build(struct player *pplayer, struct unit *punit,
4213 struct tile *ptile, const char *name,
4214 const struct action *paction)
4215{
4216 char message[1024];
4217 int size;
4218 struct player *nationality;
4219 struct player *towner;
4220 const struct unit_type *act_utype;
4221
4222 /* Sanity check: The actor still exists. */
4223 fc_assert_ret_val(pplayer, FALSE);
4224 fc_assert_ret_val(punit, FALSE);
4225
4226 towner = tile_owner(ptile);
4227
4228 if (!is_allowed_city_name(pplayer, name, message, sizeof(message))) {
4229 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
4230 "%s", message);
4231 return FALSE;
4232 }
4233
4234 act_utype = unit_type_get(punit);
4235
4236 nationality = unit_nationality(punit);
4237
4238 create_city(pplayer, ptile, name, nationality);
4239 size = unit_type_get(punit)->city_size;
4240 if (size > 1) {
4241 struct city *pcity = tile_city(ptile);
4242
4243 fc_assert_ret_val(pcity != NULL, FALSE);
4244
4245 city_change_size(pcity, size, nationality, NULL);
4246 }
4247
4248 /* May cause an incident even if the target tile is unclaimed. A ruleset
4249 * could give everyone a casus belli against the city founder. A rule
4250 * like that would make sense in a story where deep ecology is on the
4251 * table. (See also Voluntary Human Extinction Movement) */
4252 action_consequence_success(paction, pplayer, act_utype, towner,
4253 ptile, tile_link(ptile));
4254
4255 return TRUE;
4256}
4257
4258/**********************************************************************/
4261 static void handle_unit_change_activity_real(struct player *pplayer,
4262 int unit_id,
4263 enum unit_activity activity,
4264 struct extra_type *activity_target)
4265{
4266 struct unit *punit = player_unit_by_number(pplayer, unit_id);
4267
4268 if (NULL == punit) {
4269 /* Probably died or bribed. */
4270 log_verbose("handle_unit_change_activity() invalid unit %d", unit_id);
4271 return;
4272 }
4273
4274 if (punit->activity == activity
4275 && punit->activity_target == activity_target) {
4276 return;
4277 }
4278
4279 /* Remove city spot reservations for AI settlers on city founding
4280 * mission, before goto_tile reset. */
4281 if (punit->server.adv->task != AUT_NONE) {
4282 adv_unit_new_task(punit, AUT_NONE, NULL);
4283 }
4284
4285 punit->goto_tile = NULL;
4286
4287 if (activity == ACTIVITY_GOTO) {
4288 /* Don't permit a client to set a unit's activity to ACTIVITY_GOTO.
4289 * Setting ACTIVITY_GOTO from the client results in a unit indicating
4290 * it is going somewhere while it is standing still. The appearance of
4291 * the unit doing something can trick the user to not make use of it.
4292 *
4293 * Handled here because adv_follow_path() uses unit_activity_handling()
4294 * to set a unit's activity to ACTIVITY_GOTO. */
4295 return;
4296 }
4297
4298 if (activity == ACTIVITY_EXPLORE) {
4299 /* Please use unit_server_side_agent_set. */
4300 return;
4301 }
4302
4303 /* The activity can now be set. */
4304 unit_activity_handling_targeted(punit, activity, &activity_target);
4305}
4306
4307/**********************************************************************/
4310 void handle_unit_change_activity(struct player *pplayer, int unit_id,
4311 enum unit_activity activity,
4312 int target_id)
4313{
4314 struct extra_type *activity_target;
4315
4316 if (target_id < 0 || target_id >= game.control.num_extra_types) {
4317 activity_target = NULL;
4318 } else {
4319 activity_target = extra_by_number(target_id);
4320 }
4321
4322#ifdef FREECIV_WEB
4323 /* Web-client is not capable of selecting target, so we do it server side */
4324 if (activity_target == NULL) {
4325 struct unit *punit = player_unit_by_number(pplayer, unit_id);
4326 bool required = TRUE;
4327
4328 if (punit == NULL) {
4329 return;
4330 }
4331
4332 if (activity == ACTIVITY_IRRIGATE) {
4333 struct tile *ptile = unit_tile(punit);
4334
4335 activity_target = next_extra_for_tile(ptile, EC_IRRIGATION,
4336 pplayer, punit);
4337 } else if (activity == ACTIVITY_MINE) {
4338 struct tile *ptile = unit_tile(punit);
4339
4340 activity_target = next_extra_for_tile(ptile, EC_MINE,
4341 pplayer, punit);
4342 } else if (activity == ACTIVITY_BASE) {
4343 struct tile *ptile = unit_tile(punit);
4344 struct base_type *pbase =
4345 get_base_by_gui_type(BASE_GUI_FORTRESS, punit, ptile);
4346
4347 if (pbase != NULL) {
4348 activity_target = base_extra_get(pbase);
4349 }
4350
4351 } else if (activity == ACTIVITY_CLEAN) {
4352 activity_target = prev_extra_in_tile(unit_tile(punit), ERM_CLEAN,
4353 pplayer, punit);
4354 } else {
4355 required = FALSE;
4356 }
4357
4358 if (activity_target == NULL && required) {
4359 /* Nothing more we can do */
4360 return;
4361 }
4362 }
4363#endif /* FREECIV_WEB */
4364
4365 handle_unit_change_activity_real(pplayer, unit_id, activity, activity_target);
4366}
4367
4368/**********************************************************************/
4371 static void see_combat(struct unit *pattacker, struct unit *pdefender)
4372{
4373 struct packet_unit_short_info unit_att_short_packet, unit_def_short_packet;
4374 struct packet_unit_info unit_att_packet, unit_def_packet;
4375
4376 /*
4377 * Special case for attacking/defending:
4378 *
4379 * Normally the player doesn't get the information about the units inside a
4380 * city. However for attacking/defending the player has to know the unit of
4381 * the other side. After the combat a remove_unit packet will be sent
4382 * to the client to tidy up.
4383 *
4384 * Note these packets must be sent out before unit_versus_unit() is called,
4385 * so that the original unit stats (HP) will be sent.
4386 */
4387 package_short_unit(pattacker, &unit_att_short_packet,
4388 UNIT_INFO_IDENTITY, 0);
4389 package_short_unit(pdefender, &unit_def_short_packet,
4390 UNIT_INFO_IDENTITY, 0);
4391 package_unit(pattacker, &unit_att_packet);
4392 package_unit(pdefender, &unit_def_packet);
4393
4394 conn_list_iterate(game.est_connections, pconn) {
4395 struct player *pplayer = pconn->playing;
4396
4397 if (pplayer != NULL) {
4398
4399 /* NOTE: this means the player can see combat between submarines even
4400 * if neither sub is visible. See similar comment in send_combat. */
4401 if (map_is_known_and_seen(unit_tile(pattacker), pplayer, V_MAIN)
4402 || map_is_known_and_seen(unit_tile(pdefender), pplayer,
4403 V_MAIN)) {
4404
4405 /* Units are sent even if they were visible already. They may
4406 * have changed orientation for combat. */
4407 if (pplayer == unit_owner(pattacker)) {
4408 send_packet_unit_info(pconn, &unit_att_packet);
4409 } else {
4410 send_packet_unit_short_info(pconn, &unit_att_short_packet, FALSE);
4411 }
4412
4413 if (pplayer == unit_owner(pdefender)) {
4414 send_packet_unit_info(pconn, &unit_def_packet);
4415 } else {
4416 send_packet_unit_short_info(pconn, &unit_def_short_packet, FALSE);
4417 }
4418 }
4419 } else if (pconn->observer) {
4420 /* Global observer sees everything... */
4421 send_packet_unit_info(pconn, &unit_att_packet);
4422 send_packet_unit_info(pconn, &unit_def_packet);
4423 }
4424 } conn_list_iterate_end;
4425}
4426
4427/**********************************************************************/
4430 static void send_combat(struct unit *pattacker, struct unit *pdefender,
4431 int att_veteran, int def_veteran, int bombard)
4432{
4433 struct packet_unit_combat_info combat;
4434
4435 combat.attacker_unit_id = pattacker->id;
4436 combat.defender_unit_id = pdefender->id;
4437 combat.attacker_hp = pattacker->hp;
4438 combat.defender_hp = pdefender->hp;
4439 combat.make_att_veteran = att_veteran;
4440 combat.make_def_veteran = def_veteran;
4441
4442 players_iterate(other_player) {
4443 /* NOTE: this means the player can see combat between submarines even
4444 * if neither sub is visible. See similar comment in see_combat. */
4445 if (map_is_known_and_seen(unit_tile(pattacker), other_player, V_MAIN)
4446 || map_is_known_and_seen(unit_tile(pdefender), other_player,
4447 V_MAIN)) {
4448 lsend_packet_unit_combat_info(other_player->connections, &combat);
4449
4450 /*
4451 * Remove the client knowledge of the units. This corresponds to the
4452 * send_packet_unit_short_info calls up above.
4453 */
4454 if (!can_player_see_unit(other_player, pattacker)) {
4455 unit_goes_out_of_sight(other_player, pattacker);
4456 }
4457 if (!can_player_see_unit(other_player, pdefender)) {
4458 unit_goes_out_of_sight(other_player, pdefender);
4459 }
4460 }
4461 } players_iterate_end;
4462
4463 /* Send combat info to non-player observers as well. They already know
4464 * about the unit so no unit_info is needed. */
4465 conn_list_iterate(game.est_connections, pconn) {
4466 if (NULL == pconn->playing && pconn->observer) {
4467 send_packet_unit_combat_info(pconn, &combat);
4468 }
4469 } conn_list_iterate_end;
4470}
4471
4472/**********************************************************************/
4475 static void unit_attack_civilian_casualties(const struct unit *punit,
4476 struct city *pcity,
4477 const struct action *paction,
4478 const char *reason)
4479{
4480 struct player *pplayer = unit_owner(punit);
4481
4482 if (pcity
4483 && get_target_bonus_effects(NULL,
4484 &(const struct req_context) {
4485 .player = city_owner(pcity),
4486 .city = pcity,
4487 .tile = city_tile(pcity),
4488 .unit = punit,
4489 .unittype = unit_type_get(punit),
4490 .action = paction,
4491 },
4492 NULL, EFT_UNIT_NO_LOSE_POP) <= 0
4493 && (game.info.killcitizen
4494 && uclass_has_flag(unit_class_get(punit), UCF_KILLCITIZEN))) {
4495 struct player *cplayer = city_owner(pcity);
4496 struct tile *ctile = city_tile(pcity);
4497 const char *clink = city_link(pcity);
4498
4499 if (city_reduce_size(pcity, 1, pplayer, reason)) {
4500 city_refresh(pcity);
4501 send_city_info(NULL, pcity);
4502 } else {
4503 notify_player(pplayer, ctile, E_UNIT_ACTION_ACTOR_SUCCESS, ftc_server,
4504 /* TRANS: Battleship ... Los Angeles ... Bombard */
4505 _("Your %s destroyed %s by doing %s."),
4506 unit_link(punit), clink,
4507 action_name_translation(paction));
4508 notify_player(cplayer, ctile,
4509 E_UNIT_ACTION_TARGET_HOSTILE, ftc_server,
4510 /* TRANS: Sigurd I Magnusson ... Alkasse ... Attack */
4511 _("%s destroyed %s by doing %s."),
4512 player_name(pplayer), clink,
4513 action_name_translation(paction));
4514 }
4515 }
4516}
4517
4518/**********************************************************************/
4525 static bool unit_bombard(struct unit *punit, struct tile *ptile,
4526 const struct action *paction)
4527{
4528 struct player *pplayer = unit_owner(punit);
4529 struct city *pcity = tile_city(ptile);
4530 const struct unit_type *act_utype;
4531 const struct civ_map *nmap = &(wld.map);
4532
4533 /* Sanity check: The actor still exists. */
4534 fc_assert_ret_val(pplayer, FALSE);
4535 fc_assert_ret_val(punit, FALSE);
4536
4537 act_utype = unit_type_get(punit);
4538
4539 log_debug("Start bombard: %s %s to %d, %d.",
4540 nation_rule_name(nation_of_player(pplayer)),
4541 unit_rule_name(punit), TILE_XY(ptile));
4542
4543 unit_list_iterate_safe(ptile->units, pdefender) {
4544 if (is_unit_reachable_at(pdefender, punit, ptile)) {
4545 bool adj;
4546 enum direction8 facing;
4547 int att_hp, def_hp;
4548
4549 adj = base_get_direction_for_step(nmap,
4550 punit->tile, pdefender->tile, &facing);
4551
4552 if (adj) {
4553 punit->facing = facing;
4554
4555 /* Unlike with normal attack, we don't change orientation of
4556 * defenders when bombarding */
4557 }
4558
4559 unit_bombs_unit(punit, pdefender, &att_hp, &def_hp, paction);
4560
4561 if (def_hp <= 0) {
4562 notify_player(pplayer, ptile,
4563 E_UNIT_WIN_ATT, ftc_server,
4564 /* TRANS: Your Bomber killed the English Rifleman by
4565 * doing Bombard. */
4566 _("Your %s killed the %s %s by doing %s."),
4567 unit_name_translation(punit),
4568 nation_adjective_for_player(unit_owner(pdefender)),
4569 unit_name_translation(pdefender),
4570 action_name_translation(paction));
4571 notify_player(unit_owner(pdefender), ptile,
4572 E_UNIT_WIN_DEF, ftc_server,
4573 /* TRANS: Your Rifleman was killed by the French
4574 * Bomber doing Bombard. */
4575 _("Your %s was killed by the %s %s doing %s."),
4576 unit_name_translation(pdefender),
4577 nation_adjective_for_player(pplayer),
4578 unit_name_translation(punit),
4579 action_name_translation(paction));
4580 } else {
4581 notify_player(pplayer, ptile,
4582 E_UNIT_WIN_ATT, ftc_server,
4583 /* TRANS: Your Bomber bombards the English Rifleman. */
4584 _("Your %s bombards the %s %s."),
4585 unit_name_translation(punit),
4586 nation_adjective_for_player(unit_owner(pdefender)),
4587 unit_name_translation(pdefender));
4588 notify_player(unit_owner(pdefender), ptile,
4589 E_UNIT_WIN_DEF, ftc_server,
4590 /* TRANS: Your Rifleman is bombarded by the French
4591 * Bomber. */
4592 _("Your %s is bombarded by the %s %s."),
4593 unit_name_translation(pdefender),
4594 nation_adjective_for_player(pplayer),
4595 unit_name_translation(punit));
4596 }
4597
4598 see_combat(punit, pdefender);
4599
4600 punit->hp = att_hp;
4601 pdefender->hp = def_hp;
4602
4603 send_combat(punit, pdefender, 0, 0, 1);
4604
4605 /* May cause an incident */
4606 action_consequence_success(paction,
4607 unit_owner(punit), act_utype,
4608 unit_owner(pdefender),
4609 unit_tile(pdefender),
4610 unit_link(pdefender));
4611
4612 if (def_hp <= 0) {
4613 wipe_unit(pdefender, ULR_KILLED, unit_owner(pdefender));
4614 } else {
4615 send_unit_info(NULL, pdefender);
4616 }
4617 }
4618
4619 } unit_list_iterate_safe_end;
4620
4621 unit_did_action(punit);
4622 unit_forget_last_activity(punit);
4623
4624 unit_attack_civilian_casualties(punit, pcity, paction, "bombard");
4625
4626 send_unit_info(NULL, punit);
4627
4628 return TRUE;
4629}
4630
4631/**********************************************************************/
4642 static bool unit_nuke(struct player *pplayer, struct unit *punit,
4643 struct tile *def_tile, const struct action *paction)
4644{
4645 struct city *pcity;
4646 const struct unit_type *act_utype;
4647 struct civ_map *nmap = &(wld.map);
4648
4649 /* Sanity check: The actor still exists. */
4650 fc_assert_ret_val(pplayer, FALSE);
4651 fc_assert_ret_val(punit, FALSE);
4652
4653 act_utype = unit_type_get(punit);
4654
4655 log_debug("Start nuclear attack: %s %s against (%d, %d).",
4656 nation_rule_name(nation_of_player(pplayer)),
4657 unit_rule_name(punit),
4658 TILE_XY(def_tile));
4659
4660 if ((pcity = sdi_try_defend(nmap, pplayer, def_tile))) {
4661 /* FIXME: Remove the hard coded reference to SDI defense. */
4662 notify_player(pplayer, unit_tile(punit), E_UNIT_LOST_ATT, ftc_server,
4663 _("Your %s was shot down by "
4664 "SDI defenses, what a waste."), unit_tile_link(punit));
4665 notify_player(city_owner(pcity), def_tile, E_UNIT_WIN_DEF, ftc_server,
4666 _("The nuclear attack on %s was avoided by"
4667 " your SDI defense."), city_link(pcity));
4668
4669 /* Trying to nuke something this close can be... unpopular. */
4670 action_consequence_caught(paction, pplayer, act_utype,
4671 city_owner(pcity),
4672 def_tile, unit_tile_link(punit));
4673
4674 /* Remove the destroyed nuke. */
4675 wipe_unit(punit, ULR_SDI, city_owner(pcity));
4676
4677 return FALSE;
4678 }
4679
4680 dlsend_packet_nuke_tile_info(game.est_connections, tile_index(def_tile));
4681
4682
4683 /* The nuke must be wiped here so it won't be seen as a victim of its own
4684 * detonation. */
4685 if (paction->actor_consuming_always) {
4686 wipe_unit(punit, ULR_DETONATED, NULL);
4687 }
4688
4689 do_nuclear_explosion(paction, act_utype, pplayer, def_tile);
4690
4691 /* May cause an incident even if the target tile is unclaimed. A ruleset
4692 * could give everyone a casus belli against the tile nuker. A rule
4693 * like that would make sense in a story where detonating any nuke at all
4694 * could be forbidden. */
4695 action_consequence_success(paction, pplayer, act_utype,
4696 tile_owner(def_tile),
4697 def_tile,
4698 tile_link(def_tile));
4699
4700 return TRUE;
4701}
4702
4703/**********************************************************************/
4712 static bool unit_do_destroy_city(struct player *act_player,
4713 struct unit *act_unit,
4714 struct city *tgt_city,
4715 const struct action *paction)
4716{
4717 int tgt_city_id;
4718 struct player *tgt_player;
4719 bool capital;
4720 bool try_civil_war = FALSE;
4721 const struct unit_type *act_utype;
4722
4723 /* Sanity check: The actor still exists. */
4724 fc_assert_ret_val(act_player, FALSE);
4725 fc_assert_ret_val(act_unit, FALSE);
4726
4727 act_utype = unit_type_get(act_unit);
4728
4729 /* Sanity check: The target city still exists. */
4730 fc_assert_ret_val(tgt_city, FALSE);
4731
4732 tgt_player = city_owner(tgt_city);
4733
4734 /* How can a city be ownerless? */
4735 fc_assert_ret_val(tgt_player, FALSE);
4736
4737 /* Save city ID. */
4738 tgt_city_id = tgt_city->id;
4739
4740 capital = (player_primary_capital(tgt_player) == tgt_city);
4741
4742 if (capital
4743 && (tgt_player->spaceship.state == SSHIP_STARTED
4744 || tgt_player->spaceship.state == SSHIP_LAUNCHED)) {
4745 /* Destroying this city destroys the victim's space ship. */
4746 spaceship_lost(tgt_player);
4747 }
4748
4749 if (capital
4750 && civil_war_possible(tgt_player, TRUE, TRUE)
4751 && normal_player_count() < MAX_NUM_PLAYERS
4752 && civil_war_triggered(tgt_player)) {
4753 /* Destroying this city can trigger a civil war. */
4754 try_civil_war = TRUE;
4755 }
4756
4757 /* Let the actor know. */
4758 notify_player(act_player, city_tile(tgt_city),
4759 E_CITY_CONQUERED, ftc_server,
4760 _("You destroy %s completely."),
4761 city_tile_link(tgt_city));
4762
4763 if (tgt_player != act_player) {
4764 /* This was done to a foreign city. Inform the victim player. */
4765 notify_player(tgt_player, city_tile(tgt_city),
4766 E_CITY_LOST, ftc_server,
4767 _("%s has been destroyed by %s."),
4768 city_tile_link(tgt_city),
4769 player_name(act_player));
4770 }
4771
4772 /* May cause an incident */
4773 action_consequence_success(paction, act_player, act_utype,
4774 tgt_player, city_tile(tgt_city),
4775 city_link(tgt_city));
4776
4777 /* Run post city destruction Lua script. */
4778 script_server_signal_emit("city_destroyed", tgt_city, tgt_player,
4779 act_player);
4780
4781 /* Can't be sure of city existence after running script. */
4782 if (city_exist(tgt_city_id)) {
4783 remove_city(tgt_city);
4784 }
4785
4786 if (try_civil_war) {
4787 /* Try to start the civil war. */
4788 (void) civil_war(tgt_player);
4789 }
4790
4791 /* The city is no more. */
4792 return TRUE;
4793}
4794
4795/**********************************************************************/
4800 static const char *unit_veteran_level_string(const struct unit *punit)
4801{
4802 static char buf[MAX_LEN_LINK];
4803 const struct veteran_level *vlevel;
4804
4805 if (!punit) {
4806 buf[0] = '\0'; /* If no unit, return empty string */
4807 return buf;
4808 }
4809
4810 vlevel = utype_veteran_level(unit_type_get(punit), punit->veteran);
4811 fc_snprintf(buf, sizeof(buf), "%s", name_translation_get(&vlevel->name));
4812
4813 return buf;
4814}
4815
4816/**********************************************************************/
4821 static const char *unit_achieved_rank_string(const struct unit *punit)
4822{
4823 static char buf[MAX_LEN_LINK];
4824
4825 fc_snprintf(buf, sizeof(buf),
4826 /* TRANS: " and achieved the rank of <veteran level>";
4827 * preserve leading space */
4828 _(" and achieved the rank of %s"),
4829 unit_veteran_level_string(punit));
4830 return buf;
4831}
4832
4833/**********************************************************************/
4838 static const char *unit_tired_attack_string(const struct unit *punit)
4839{
4840 static char buf[MAX_LEN_LINK];
4841
4842 if (is_tired_attack(punit->moves_left)) {
4843 fc_snprintf(buf, sizeof(buf),
4844 /* TRANS: tired; note trailing space */
4845 _("tired "));
4846 } else {
4847 buf[0] = '\0';
4848 }
4849
4850 return buf;
4851}
4852
4853/**********************************************************************/
4860 static const char *unit_firepower_if_not_one(int firepower)
4861{
4862 static char buf[MAX_LEN_LINK];
4863
4864 if (firepower == 1) {
4865 buf[0] = '\0';
4866 } else {
4867 fc_snprintf(buf, sizeof(buf),
4868 /* TRANS: FP = Firepower of a unit; note trailing space */
4869 _("FP:%d "),
4870 firepower);
4871 }
4872
4873 return buf;
4874}
4875
4876/**********************************************************************/
4885 static bool do_attack(struct unit *punit, struct tile *def_tile,
4886 const struct action *paction)
4887{
4888 char loser_link[MAX_LEN_LINK], winner_link[MAX_LEN_LINK];
4889 char attacker_vet[MAX_LEN_LINK], defender_vet[MAX_LEN_LINK];
4890 char attacker_fp[MAX_LEN_LINK], defender_fp[MAX_LEN_LINK];
4891 char attacker_tired[MAX_LEN_LINK];
4892 struct unit *ploser, *pwinner;
4893 int moves_used, def_moves_used;
4894 int old_unit_vet, old_defender_vet, vet;
4895 int winner_id;
4896 struct player *pplayer = unit_owner(punit);
4897 bool adj;
4898 enum direction8 facing;
4899 int att_hp, def_hp, att_fp, def_fp;
4900 int att_hp_start, def_hp_start;
4901 int def_power, att_power;
4902 int att_vet, def_vet;
4903 struct unit *pdefender;
4904 const struct unit_type *act_utype = unit_type_get(punit);
4905 struct civ_map *nmap = &(wld.map);
4906 bool powerless;
4907
4908 if (!(pdefender = get_defender(nmap, punit, def_tile, paction))) {
4909 /* Can't fight air... */
4910 return FALSE;
4911 }
4912
4913 att_hp_start = punit->hp;
4914 def_hp_start = pdefender->hp;
4915 def_power = get_total_defense_power(punit, pdefender);
4916 att_power = get_total_attack_power(punit, pdefender, paction);
4917 get_modified_firepower(nmap, punit, pdefender, &att_fp, &def_fp);
4918
4919 log_debug("Start attack: %s %s against %s %s.",
4920 nation_rule_name(nation_of_player(pplayer)),
4921 unit_rule_name(punit),
4922 nation_rule_name(nation_of_unit(pdefender)),
4923 unit_rule_name(pdefender));
4924
4925 /* Sanity checks */
4926 fc_assert_ret_val_msg(!pplayers_non_attack(pplayer,
4927 unit_owner(pdefender)),
4928 FALSE,
4929 "Trying to attack a unit with which you have peace "
4930 "or cease-fire at (%d, %d).", TILE_XY(def_tile));
4931 fc_assert_ret_val_msg(!pplayers_allied(pplayer, unit_owner(pdefender)),
4932 FALSE,
4933 "Trying to attack a unit with which you have "
4934 "alliance at (%d, %d).", TILE_XY(def_tile));
4935
4936 moves_used = unit_move_rate(punit) - punit->moves_left;
4937 def_moves_used = unit_move_rate(pdefender) - pdefender->moves_left;
4938
4939 adj = base_get_direction_for_step(nmap,
4940 punit->tile, pdefender->tile, &facing);
4941
4942 fc_assert(adj);
4943 if (adj) {
4944 punit->facing = facing;
4945 pdefender->facing = opposite_direction(facing);
4946 }
4947
4948 old_unit_vet = punit->veteran;
4949 old_defender_vet = pdefender->veteran;
4950
4951 /* N.B.: unit_veteran_level_string always returns the same pointer. */
4952 sz_strlcpy(attacker_vet, unit_veteran_level_string(punit));
4953 sz_strlcpy(defender_vet, unit_veteran_level_string(pdefender));
4954
4955 /* N.B.: unit_firepower_if_not_one always returns the same pointer. */
4956 sz_strlcpy(attacker_fp, unit_firepower_if_not_one(att_fp));
4957 sz_strlcpy(defender_fp, unit_firepower_if_not_one(def_fp));
4958
4959 /* Record tired attack string before attack */
4960 sz_strlcpy(attacker_tired, unit_tired_attack_string(punit));
4961
4962 powerless = unit_versus_unit(punit, pdefender, &att_hp, &def_hp,
4963 &att_vet, &def_vet, paction);
4964
4965 if ((att_hp <= 0 || utype_is_consumed_by_action(paction, punit->utype))
4966 && unit_transported(punit)) {
4967 /* Dying attacker must be first unloaded so it doesn't die inside transport */
4968 unit_transport_unload_send(punit);
4969 }
4970
4971 see_combat(punit, pdefender);
4972
4973 punit->hp = att_hp;
4974 pdefender->hp = def_hp;
4975
4976 combat_veterans(punit, pdefender, powerless, att_vet, def_vet);
4977
4978 /* Adjust attackers moves_left _after_ unit_versus_unit() so that
4979 * the movement attack modifier is correct! --dwp
4980 *
4981 * For greater Civ2 compatibility (and game balance issues), we recompute
4982 * the new total MP based on the HP the unit has left after being damaged,
4983 * and subtract the MPs that had been used before the combat (plus the
4984 * points used in the attack itself, for the attacker). -GJW, Glip
4985 */
4986 punit->moves_left = unit_move_rate(punit) - moves_used;
4987 pdefender->moves_left = unit_move_rate(pdefender) - def_moves_used;
4988
4989 if (punit->moves_left < 0) {
4990 punit->moves_left = 0;
4991 }
4992 if (pdefender->moves_left < 0) {
4993 pdefender->moves_left = 0;
4994 }
4995 unit_did_action(punit);
4996 unit_forget_last_activity(punit);
4997
4998 /* This may cause a diplomatic incident. */
4999 action_consequence_success(paction, pplayer, act_utype,
5000 unit_owner(pdefender),
5001 def_tile, unit_link(pdefender));
5002
5003 if (punit->hp > 0 && pdefender->hp > 0) {
5004 /* Neither died */
5005 send_combat(punit, pdefender, punit->veteran - old_unit_vet,
5006 pdefender->veteran - old_defender_vet, 0);
5007 return TRUE;
5008 }
5009 pwinner = (punit->hp > 0) ? punit : pdefender;
5010 winner_id = pwinner->id;
5011 ploser = (pdefender->hp > 0) ? punit : pdefender;
5012
5013 vet = (pwinner->veteran == ((punit->hp > 0) ? old_unit_vet :
5014 old_defender_vet)) ? 0 : 1;
5015
5016 send_combat(punit, pdefender, punit->veteran - old_unit_vet,
5017 pdefender->veteran - old_defender_vet, 0);
5018
5019 /* N.B.: unit_link always returns the same pointer. */
5020 sz_strlcpy(loser_link, unit_tile_link(ploser));
5021 sz_strlcpy(winner_link,
5022 utype_is_consumed_by_action(paction, pwinner->utype)
5023 ? unit_tile_link(pwinner) : unit_link(pwinner));
5024
5025 if (punit == ploser) {
5026 /* The attacker lost */
5027 log_debug("Attacker lost: %s %s against %s %s.",
5028 nation_rule_name(nation_of_player(pplayer)),
5029 unit_rule_name(punit),
5030 nation_rule_name(nation_of_unit(pdefender)),
5031 unit_rule_name(pdefender));
5032
5033 notify_player(unit_owner(pwinner), unit_tile(pwinner),
5034 E_UNIT_WIN_DEF, ftc_server,
5035 /* TRANS: "Your green Legion [id:100 ...D:4.0 lost 1 HP,
5036 * 9 HP remaining] survived the pathetic ...attack from the
5037 * Greek green Warriors [id:90 ...A:1.0 HP:10]. */
5038 _("Your %s %s [id:%d %sD:%.1f lost %d HP, %d HP remaining]"
5039 " survived the pathetic %sattack from the %s %s %s "
5040 "[id:%d %sA:%.1f HP:%d]."),
5041 defender_vet,
5042 winner_link,
5043 pdefender->id,
5044 defender_fp,
5045 (float)def_power/POWER_FACTOR,
5046 def_hp_start - pdefender->hp,
5047 pdefender->hp,
5048 attacker_tired,
5049 nation_adjective_for_player(unit_owner(ploser)),
5050 attacker_vet,
5051 loser_link,
5052 punit->id,
5053 attacker_fp,
5054 (float)att_power/POWER_FACTOR,
5055 att_hp_start);
5056
5057 if (vet) {
5058 notify_unit_experience(pwinner);
5059 }
5060 notify_player(unit_owner(ploser), def_tile,
5061 E_UNIT_LOST_ATT, ftc_server,
5062 /* TRANS: "Your attacking green Cannon [id:100 ...A:8.0
5063 * failed against the Polish green Destroyer [id:200 lost
5064 * 27 HP, 3 HP remaining%s]!";
5065 * last %s is either "and ..." or empty string */
5066 _("Your attacking %s %s [id:%d %sA:%.1f HP:%d] failed "
5067 "against the %s %s %s [id:%d lost %d HP, %d HP "
5068 "remaining%s]!"),
5069 attacker_vet,
5070 loser_link,
5071 punit->id,
5072 attacker_fp,
5073 (float)att_power/POWER_FACTOR,
5074 att_hp_start,
5075 nation_adjective_for_player(unit_owner(pdefender)),
5076 defender_vet,
5077 winner_link,
5078 pdefender->id,
5079 def_hp_start - pdefender->hp,
5080 pdefender->hp,
5081 vet ? unit_achieved_rank_string(pdefender) : "");
5082
5083 wipe_unit(ploser, ULR_KILLED, unit_owner(pwinner));
5084 } else {
5085 /* The defender lost, the attacker punit lives! */
5086 struct city *pcity;
5087
5088 log_debug("Defender lost: %s %s against %s %s.",
5089 nation_rule_name(nation_of_player(pplayer)),
5090 unit_rule_name(punit),
5091 nation_rule_name(nation_of_unit(pdefender)),
5092 unit_rule_name(pdefender));
5093
5094 notify_player(unit_owner(pdefender), unit_tile(pdefender),
5095 E_UNIT_LOST_DEF, ftc_server,
5096 /* TRANS: "Your green Warriors [id:100 ...D:1.0 HP:10]
5097 * lost to an attack by the Greek green Legion
5098 * [id:200 ...A:4.0 lost 1 HP, has 9 HP remaining%s]."
5099 * last %s is either "and ..." or empty string */
5100 _("Your %s %s [id:%d %sD:%.1f HP:%d] lost to an attack by "
5101 "the %s %s %s [id:%d %sA:%.1f lost %d HP, has %d HP "
5102 "remaining%s]."),
5103 defender_vet,
5104 loser_link,
5105 pdefender->id,
5106 defender_fp,
5107 (float)def_power/POWER_FACTOR,
5108 def_hp_start,
5109 nation_adjective_for_player(unit_owner(punit)),
5110 attacker_vet,
5111 winner_link,
5112 punit->id,
5113 attacker_fp,
5114 (float)att_power/POWER_FACTOR,
5115 att_hp_start - pwinner->hp,
5116 pwinner->hp,
5117 vet ? unit_achieved_rank_string(punit) : "");
5118
5119 notify_player(unit_owner(punit), unit_tile(punit),
5120 E_UNIT_WIN_ATT, ftc_server,
5121 /* TRANS: "Your attacking green Legion [id:200 ...A:4.0
5122 * lost 1 HP, has 9 HP remaining] succeeded against the
5123 * Greek green Warriors [id:100 HP:10]." */
5124 _("Your attacking %s %s [id:%d %s%sA:%.1f lost %d HP, "
5125 "has %d remaining] succeeded against the %s %s %s "
5126 "[id:%d HP:%d]."),
5127 attacker_vet,
5128 winner_link,
5129 punit->id,
5130 attacker_fp,
5131 attacker_tired,
5132 (float)att_power/POWER_FACTOR,
5133 att_hp_start - pwinner->hp,
5134 pwinner->hp,
5135 nation_adjective_for_player(unit_owner(pdefender)),
5136 defender_vet,
5137 loser_link,
5138 pdefender->id,
5139 def_hp_start);
5140
5141 punit->moved = TRUE; /* We moved */
5142
5143 if (paction->result == ACTRES_COLLECT_RANSOM) {
5144 collect_ransom(pwinner, ploser,
5145 vet && !utype_is_consumed_by_action(paction, punit->utype));
5146 } else {
5147 kill_unit(pwinner, ploser,
5148 vet && !utype_is_consumed_by_action(paction, punit->utype));
5149 }
5150
5151 /* Now that dead defender is certainly no longer listed as unit
5152 * supported by the city, we may even remove the city
5153 * (if it shrinks from size 1) */
5154 pcity = tile_city(def_tile);
5155 if (pcity != NULL) {
5156 unit_attack_civilian_casualties(punit, pcity, paction, "attack");
5157 }
5158 if (unit_is_alive(winner_id)) {
5159 if (utype_is_consumed_by_action(paction, pwinner->utype)) {
5160 return TRUE;
5161 }
5162 } else {
5163 return TRUE;
5164 }
5165 }
5166
5167 /* If attacker wins, and occupychance > 0, it might move in. Don't move in
5168 * if there are enemy units in the tile (a fortress, city or air base with
5169 * multiple defenders and unstacked combat). Note that this could mean
5170 * capturing (or destroying) a city. */
5171
5172 if (pwinner == punit && fc_rand(100) < game.server.occupychance) {
5173 occupy_move(def_tile, punit, paction);
5174 }
5175
5176 /* The attacker may have died for many reasons */
5177 if (game_unit_by_number(winner_id) != NULL) {
5178 send_unit_info(NULL, pwinner);
5179 }
5180
5181 return TRUE;
5182}
5183
5184/**********************************************************************/
5194 static bool do_unit_strike_city_production(struct player *act_player,
5195 struct unit *act_unit,
5196 struct city *tgt_city,
5197 const struct action *paction)
5198{
5199 struct player *tgt_player;
5200 char prod[256];
5201 const struct unit_type *act_utype;
5202 const struct tile *tgt_tile;
5203 const char *clink;
5204
5205 /* Sanity checks */
5206 fc_assert_ret_val(act_player, FALSE);
5207 fc_assert_ret_val(act_unit, FALSE);
5208 fc_assert_ret_val(tgt_city, FALSE);
5209 fc_assert_ret_val(paction, FALSE);
5210
5211 tgt_player = city_owner(tgt_city);
5212 fc_assert_ret_val(tgt_player, FALSE);
5213
5214 tgt_tile = city_tile(tgt_city);
5215
5216 /* The surgical strike may miss. */
5217 {
5218 /* Roll the dice. */
5219 if (action_failed_dice_roll(act_player, act_unit,
5220 tgt_city, tgt_player,
5221 paction)) {
5222 /* Notify the player. */
5223 notify_player(act_player, tgt_tile,
5224 E_UNIT_ACTION_ACTOR_FAILURE, ftc_server,
5225 /* TRANS: unit, action, city */
5226 _("Your %s failed to do %s in %s."),
5227 unit_link(act_unit),
5228 action_name_translation(paction),
5229 city_link(tgt_city));
5230
5231 /* Make the failed attempt cost a single move. */
5232 act_unit->moves_left = MAX(0, act_unit->moves_left - SINGLE_MOVE);
5233
5234 return FALSE;
5235 }
5236 }
5237
5238 /* Get name of the production */
5239 universal_name_translation(&tgt_city->production, prod, sizeof(prod));
5240
5241 /* Destroy the production */
5242 tgt_city->shield_stock = 0;
5243 nullify_prechange_production(tgt_city);
5244
5245 /* Let the players know. */
5246 clink = city_link(tgt_city); /* Be careful not to call city_link()
5247 * again as long as we need clink */
5248 notify_player(act_player, tgt_tile,
5249 E_UNIT_ACTION_ACTOR_SUCCESS, ftc_server,
5250 _("Your %s succeeded in destroying"
5251 " the production of %s in %s."),
5252 unit_link(act_unit),
5253 prod, clink);
5254 notify_player(tgt_player, tgt_tile,
5255 E_UNIT_ACTION_TARGET_HOSTILE, ftc_server,
5256 _("The production of %s was destroyed in %s,"
5257 " %s are suspected."),
5258 prod, clink,
5259 nation_plural_for_player(act_player));
5260
5261 act_utype = unit_type_get(act_unit);
5262
5263 /* May cause an incident */
5264 action_consequence_success(paction, act_player, act_utype,
5265 tgt_player, tgt_tile,
5266 clink);
5267
5268 return TRUE;
5269}
5270
5271/**********************************************************************/
5281 static bool do_unit_strike_city_building(struct player *act_player,
5282 struct unit *act_unit,
5283 struct city *tgt_city,
5284 Impr_type_id tgt_bld_id,
5285 const struct action *paction)
5286{
5287 struct player *tgt_player;
5288 struct impr_type *tgt_bld = improvement_by_number(tgt_bld_id);
5289 const struct tile *tgt_tile;
5290 const struct unit_type *act_utype;
5291 const char *clink;
5292
5293 /* Sanity checks */
5294 fc_assert_ret_val(act_player, FALSE);
5295 fc_assert_ret_val(act_unit, FALSE);
5296 fc_assert_ret_val(tgt_city, FALSE);
5297 fc_assert_ret_val(paction, FALSE);
5298
5299 tgt_tile = city_tile(tgt_city);
5300
5301 tgt_player = city_owner(tgt_city);
5302 fc_assert_ret_val(tgt_player, FALSE);
5303
5304 /* The surgical strike may miss. */
5305 {
5306 /* Roll the dice. */
5307 if (action_failed_dice_roll(act_player, act_unit,
5308 tgt_city, tgt_player,
5309 paction)) {
5310 /* Notify the player. */
5311 notify_player(act_player, tgt_tile,
5312 E_UNIT_ACTION_ACTOR_FAILURE, ftc_server,
5313 /* TRANS: unit, action, city */
5314 _("Your %s failed to do %s in %s."),
5315 unit_link(act_unit),
5316 action_name_translation(paction),
5317 city_link(tgt_city));
5318
5319 /* Make the failed attempt cost a single move. */
5320 act_unit->moves_left = MAX(0, act_unit->moves_left - SINGLE_MOVE);
5321
5322 return FALSE;
5323 }
5324 }
5325
5326 if (!city_has_building(tgt_city, tgt_bld)) {
5327 /* Nothing to destroy here. */
5328
5329 /* Notify the player. */
5330 notify_player(act_player, tgt_tile,
5331 E_UNIT_ACTION_ACTOR_FAILURE, ftc_server,
5332 _("Your %s didn't find a %s to %s in %s."),
5333 unit_link(act_unit),
5334 improvement_name_translation(tgt_bld),
5335 action_name_translation(paction),
5336 city_link(tgt_city));
5337
5338 /* Punish the player for blindly attacking a building. */
5339 act_unit->moves_left = MAX(0, act_unit->moves_left - SINGLE_MOVE);
5340
5341 return FALSE;
5342 }
5343
5344 act_utype = unit_type_get(act_unit);
5345
5346 /* Destroy the building. */
5347 building_lost(tgt_city, tgt_bld, "attacked", act_unit);
5348
5349 /* Update the player's view of the city. */
5350 send_city_info(NULL, tgt_city);
5351
5352 /* Let the players know. */
5353 clink = city_link(tgt_city); /* Be careful not to call city_link()
5354 * again as long as we need clink */
5355 notify_player(act_player, tgt_tile,
5356 E_UNIT_ACTION_ACTOR_SUCCESS, ftc_server,
5357 _("Your %s destroyed the %s in %s."),
5358 unit_link(act_unit),
5359 improvement_name_translation(tgt_bld),
5360 clink);
5361 notify_player(tgt_player, tgt_tile,
5362 E_UNIT_ACTION_TARGET_HOSTILE, ftc_server,
5363 _("The %s destroyed the %s in %s."),
5364 nation_plural_for_player(act_player),
5365 improvement_name_translation(tgt_bld),
5366 clink);
5367
5368 /* May cause an incident */
5369 action_consequence_success(paction, act_player, act_utype,
5370 tgt_player, tgt_tile, clink);
5371
5372 return TRUE;
5373}
5374
5375/**********************************************************************/
5384 static bool do_unit_conquer_city(struct player *act_player,
5385 struct unit *act_unit,
5386 struct city *tgt_city,
5387 struct action *paction)
5388{
5389 bool success;
5390 struct tile *tgt_tile = city_tile(tgt_city);
5391 int move_cost = map_move_cost_unit(&(wld.map), act_unit, tgt_tile);
5392 int tgt_city_id = tgt_city->id;
5393 struct player *tgt_player = city_owner(tgt_city);
5394 const char *victim_link = city_link(tgt_city);
5395
5396 /* Sanity check */
5397 fc_assert_ret_val(tgt_tile, FALSE);
5398
5399 unit_move(act_unit, tgt_tile, move_cost, NULL, FALSE, TRUE, TRUE,
5400 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
5401 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_FRIGHTEN));
5402
5403 /* The city may have been destroyed during the conquest. */
5404 success = (!city_exist(tgt_city_id)
5405 || city_owner(tgt_city) == act_player);
5406
5407 if (success) {
5408 const struct unit_type *act_utype = unit_type_get(act_unit);
5409
5410 /* May cause an incident */
5411 action_consequence_success(paction, act_player, act_utype,
5412 tgt_player, tgt_tile,
5413 victim_link);
5414 }
5415
5416 return success;
5417}
5418
5419/**********************************************************************/
5422 static bool can_unit_move_to_tile_with_notify(struct unit *punit,
5423 struct tile *dest_tile,
5424 bool igzoc,
5425 struct unit *embark_to,
5426 bool enter_enemy_city)
5427{
5428 struct tile *src_tile = unit_tile(punit);
5429 enum unit_move_result reason =
5430 unit_move_to_tile_test(&(wld.map), punit, punit->activity,
5431 src_tile, dest_tile, igzoc, TRUE, embark_to,
5432 enter_enemy_city);
5433
5434 switch (reason) {
5435 case MR_OK:
5436 return TRUE;
5437
5438 case MR_NO_WAR:
5439 notify_player(unit_owner(punit), src_tile, E_BAD_COMMAND, ftc_server,
5440 _("Cannot attack unless you declare war first."));
5441 break;
5442
5443 case MR_ZOC:
5444 notify_player(unit_owner(punit), src_tile, E_BAD_COMMAND, ftc_server,
5445 _("%s can only move into your own zone of control."),
5446 unit_link(punit));
5447 break;
5448
5449 case MR_TRIREME:
5450 notify_player(unit_owner(punit), src_tile, E_BAD_COMMAND, ftc_server,
5451 _("%s cannot move that far from the coast line."),
5452 unit_link(punit));
5453 break;
5454
5455 case MR_PEACE:
5456 if (tile_owner(dest_tile)) {
5457 notify_player(unit_owner(punit), src_tile, E_BAD_COMMAND, ftc_server,
5458 _("Cannot invade unless you break peace with "
5459 "%s first."),
5460 player_name(tile_owner(dest_tile)));
5461 }
5462 break;
5463
5464 case MR_CANNOT_DISEMBARK:
5465 notify_player(unit_owner(punit), src_tile, E_BAD_COMMAND, ftc_server,
5466 _("%s cannot disembark outside of a city or a native base "
5467 "for %s."),
5468 unit_link(punit),
5469 utype_name_translation(
5470 unit_type_get(unit_transport_get(punit))));
5471 break;
5472
5473 case MR_NON_NATIVE_MOVE:
5474 notify_player(unit_owner(punit), src_tile, E_BAD_COMMAND, ftc_server,
5475 _("Terrain is unsuitable for %s units."),
5476 uclass_name_translation(unit_class_get(punit)));
5477 break;
5478
5479 default:
5480 /* FIXME: need more explanations someday! */
5481 break;
5482 };
5483
5484 return FALSE;
5485}
5486
5487/**********************************************************************/
5493 static bool unit_do_regular_move(struct player *actor_player,
5494 struct unit *actor_unit,
5495 struct tile *target_tile,
5496 const struct action *paction)
5497{
5498 const struct unit_type *act_utype = unit_type_get(actor_unit);
5499 int move_cost = map_move_cost_unit(&(wld.map), actor_unit, target_tile);
5500
5501 unit_move(actor_unit, target_tile, move_cost,
5502 NULL, BV_ISSET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK),
5503 /* Don't override "Conquer City" */
5504 FALSE,
5505 /* Don't override "Conquer Extras" */
5506 FALSE,
5507 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
5508 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_FRIGHTEN));
5509
5510 /* May cause an incident */
5511 action_consequence_success(paction, actor_player, act_utype,
5512 tile_owner(target_tile),
5513 target_tile, tile_link(target_tile));
5514
5515 return TRUE;
5516}
5517
5518/**********************************************************************/
5531 bool unit_move_handling(struct unit *punit, struct tile *pdesttile,
5532 bool move_do_not_act)
5533{
5534 struct player *pplayer = unit_owner(punit);
5535 struct unit *ptrans;
5536 const struct civ_map *nmap = &(wld.map);
5537
5538 /*** Phase 1: Attempted action interpretation checks ***/
5539
5540 /* Check if the move should be interpreted as an attempt to perform an
5541 * enabler controlled action to the target tile. When the move may be an
5542 * action attempt the server stops moving the unit, marks it as wanting a
5543 * decision based on its own movement to the tile it attempted to move to
5544 * and notifies the client.
5545 *
5546 * In response to the unit being marked as wanting a decision the client
5547 * can query the server for what actions the unit, given the player's
5548 * knowledge, may be able to perform against a target at the tile it tried
5549 * to move to. The server will respond to the query with the actions that
5550 * may be enabled and, when all actions are known to be illegal given the
5551 * player's knowledge, an explanation why no action could be done. The
5552 * client will probably use the list of potentially legal actions, if any,
5553 * to pop up an action selection dialog. See handle_unit_action_query()
5554 *
5555 * If move_do_not_act is TRUE the move is never interpreted as an attempt
5556 * to perform an enabler controlled action.
5557 * Examples of where this is useful is for AI moves, goto, when the player
5558 * attempts to move to a tile occupied by potential targets like allied
5559 * cities or units and during rule forced moves.
5560 *
5561 * A move is not interpreted as an attempted action because the unit is
5562 * able to do a self targeted action.
5563 *
5564 * A move is not interpreted as an attempted action because an action
5565 * with rare_pop_up set to TRUE is legal unless the unit is unable to
5566 * perform a regular move to the tile.
5567 *
5568 * An attempted move to a tile a unit can't move to is always interpreted
5569 * as trying to perform an action (unless move_do_not_act is TRUE) */
5570 if (!move_do_not_act) {
5571 const bool can_not_move = !unit_can_move_to_tile(nmap,
5572 punit, pdesttile,
5573 FALSE, FALSE, FALSE);
5574 bool one_action_may_be_legal
5575 = action_tgt_unit(punit, pdesttile, can_not_move)
5576 || action_tgt_city(punit, pdesttile, can_not_move)
5577 /* A legal action with an extra sub target is a legal action */
5578 || action_tgt_tile_extra(punit, pdesttile, can_not_move)
5579 /* Tile target actions with extra sub targets are handled above */
5580 || action_tgt_tile(punit, pdesttile, NULL, can_not_move);
5581
5582 if (one_action_may_be_legal || can_not_move) {
5583 /* There is a target punit, from the player's point of view, may be
5584 * able to act against OR punit can't do any non action move. The
5585 * client should therefore ask what action(s) the unit can perform
5586 * to any targets at pdesttile.
5587 *
5588 * In the first case the unit needs a decision about what action, if
5589 * any at all, to take. Asking what actions the unit can perform
5590 * will return a list of actions that may, from the players point of
5591 * view, be possible. The client can then show this list to the
5592 * player or, if configured to do so, make the choice it self.
5593 *
5594 * In the last case the player may need an explanation about why no
5595 * action could be taken. Asking what actions the unit can perform
5596 * will provide this explanation. */
5597 punit->action_decision_want = ACT_DEC_ACTIVE;
5598 punit->action_decision_tile = pdesttile;
5599 send_unit_info(player_reply_dest(pplayer), punit);
5600
5601 /* The move wasn't done because the unit wanted the player to
5602 * decide what to do or because the unit couldn't move to the
5603 * target tile. */
5604 return FALSE;
5605 }
5606 }
5607
5608 /*** Phase 2: OK now move the unit ***/
5609 /* This is a regular move, subject to the rules. */
5610 if (is_action_enabled_unit_on_tile(nmap, ACTION_UNIT_MOVE,
5611 punit, pdesttile, NULL)) {
5612 return unit_perform_action(pplayer, punit->id, tile_index(pdesttile),
5613 NO_TARGET, "", ACTION_UNIT_MOVE,
5614 ACT_REQ_PLAYER);
5615 } else if (is_action_enabled_unit_on_tile(nmap, ACTION_UNIT_MOVE2,
5616 punit, pdesttile, NULL)) {
5617 return unit_perform_action(pplayer, punit->id, tile_index(pdesttile),
5618 NO_TARGET, "", ACTION_UNIT_MOVE2,
5619 ACT_REQ_PLAYER);
5620 } else if (is_action_enabled_unit_on_tile(nmap, ACTION_UNIT_MOVE3,
5621 punit, pdesttile, NULL)) {
5622 return unit_perform_action(pplayer, punit->id, tile_index(pdesttile),
5623 NO_TARGET, "", ACTION_UNIT_MOVE3,
5624 ACT_REQ_PLAYER);
5625 } else if (!can_unit_survive_at_tile(nmap, punit, pdesttile)
5626 && ((ptrans = transporter_for_unit_at(punit, pdesttile)))
5627 && is_action_enabled_unit_on_unit(nmap, ACTION_TRANSPORT_EMBARK,
5628 punit, ptrans)) {
5629 /* "Transport Embark". */
5630 return unit_perform_action(pplayer, punit->id, ptrans->id,
5631 NO_TARGET, "", ACTION_TRANSPORT_EMBARK,
5632 ACT_REQ_PLAYER);
5633 } else if (!can_unit_survive_at_tile(nmap, punit, pdesttile)
5634 && ((ptrans = transporter_for_unit_at(punit, pdesttile)))
5635 && is_action_enabled_unit_on_unit(nmap, ACTION_TRANSPORT_EMBARK2,
5636 punit, ptrans)) {
5637 /* "Transport Embark 2". */
5638 return unit_perform_action(pplayer, punit->id, ptrans->id,
5639 NO_TARGET, "", ACTION_TRANSPORT_EMBARK2,
5640 ACT_REQ_PLAYER);
5641 } else if (!can_unit_survive_at_tile(nmap, punit, pdesttile)
5642 && ((ptrans = transporter_for_unit_at(punit, pdesttile)))
5643 && is_action_enabled_unit_on_unit(nmap, ACTION_TRANSPORT_EMBARK3,
5644 punit, ptrans)) {
5645 /* "Transport Embark 3". */
5646 return unit_perform_action(pplayer, punit->id, ptrans->id,
5647 NO_TARGET, "", ACTION_TRANSPORT_EMBARK3,
5648 ACT_REQ_PLAYER);
5649 } else if (!can_unit_survive_at_tile(nmap, punit, pdesttile)
5650 && ((ptrans = transporter_for_unit_at(punit, pdesttile)))
5651 && is_action_enabled_unit_on_unit(nmap, ACTION_TRANSPORT_EMBARK4,
5652 punit, ptrans)) {
5653 /* "Transport Embark 4". */
5654 return unit_perform_action(pplayer, punit->id, ptrans->id,
5655 NO_TARGET, "", ACTION_TRANSPORT_EMBARK4,
5656 ACT_REQ_PLAYER);
5657 } else if (is_action_enabled_unit_on_tile(nmap, ACTION_TRANSPORT_DISEMBARK1,
5658 punit, pdesttile, NULL)) {
5659 /* "Transport Disembark". */
5660 return unit_perform_action(pplayer, punit->id, tile_index(pdesttile),
5661 NO_TARGET, "", ACTION_TRANSPORT_DISEMBARK1,
5662 ACT_REQ_PLAYER);
5663 } else if (is_action_enabled_unit_on_tile(nmap, ACTION_TRANSPORT_DISEMBARK2,
5664 punit, pdesttile, NULL)) {
5665 /* "Transport Disembark 2". */
5666 return unit_perform_action(pplayer, punit->id, tile_index(pdesttile),
5667 NO_TARGET, "", ACTION_TRANSPORT_DISEMBARK2,
5668 ACT_REQ_PLAYER);
5669 } else if (is_action_enabled_unit_on_tile(nmap, ACTION_TRANSPORT_DISEMBARK3,
5670 punit, pdesttile, NULL)) {
5671 /* "Transport Disembark 3". */
5672 return unit_perform_action(pplayer, punit->id, tile_index(pdesttile),
5673 NO_TARGET, "", ACTION_TRANSPORT_DISEMBARK3,
5674 ACT_REQ_PLAYER);
5675 } else if (is_action_enabled_unit_on_tile(nmap, ACTION_TRANSPORT_DISEMBARK4,
5676 punit, pdesttile, NULL)) {
5677 /* "Transport Disembark 4". */
5678 return unit_perform_action(pplayer, punit->id, tile_index(pdesttile),
5679 NO_TARGET, "", ACTION_TRANSPORT_DISEMBARK4,
5680 ACT_REQ_PLAYER);
5681 } else if (is_action_enabled_unit_on_tile(nmap, ACTION_HUT_ENTER,
5682 punit, pdesttile, NULL)) {
5683 /* "Enter Hut". */
5684 return unit_perform_action(pplayer, punit->id, tile_index(pdesttile),
5685 NO_TARGET, "", ACTION_HUT_ENTER,
5686 ACT_REQ_PLAYER);
5687 } else if (is_action_enabled_unit_on_tile(nmap, ACTION_HUT_ENTER2,
5688 punit, pdesttile, NULL)) {
5689 /* "Enter Hut 2". */
5690 return unit_perform_action(pplayer, punit->id, tile_index(pdesttile),
5691 NO_TARGET, "", ACTION_HUT_ENTER2,
5692 ACT_REQ_PLAYER);
5693 } else if (is_action_enabled_unit_on_tile(nmap, ACTION_HUT_FRIGHTEN,
5694 punit, pdesttile, NULL)) {
5695 /* "Frighten Hut". */
5696 return unit_perform_action(pplayer, punit->id, tile_index(pdesttile),
5697 NO_TARGET, "", ACTION_HUT_FRIGHTEN,
5698 ACT_REQ_PLAYER);
5699 } else if (is_action_enabled_unit_on_tile(nmap, ACTION_HUT_FRIGHTEN2,
5700 punit, pdesttile, NULL)) {
5701 /* "Frighten Hut 2". */
5702 return unit_perform_action(pplayer, punit->id, tile_index(pdesttile),
5703 NO_TARGET, "", ACTION_HUT_FRIGHTEN2,
5704 ACT_REQ_PLAYER);
5705 } else {
5706 /* TODO: Extend the action not enabled explanation system to cover all
5707 * existing reasons and switch to using it. See hrm Feature #920229 */
5708 can_unit_move_to_tile_with_notify(punit, pdesttile, FALSE,
5709 NULL, FALSE);
5710 return FALSE;
5711 }
5712}
5713
5714/**********************************************************************/
5724 static bool unit_do_help_build(struct player *pplayer,
5725 struct unit *punit,
5726 struct city *pcity_dest,
5727 const struct action *paction)
5728{
5729 const char *work;
5730 const char *prod;
5731 int shields;
5732 const struct unit_type *act_utype;
5733 struct player *cowner;
5734
5735 /* Sanity check: The actor still exists. */
5736 fc_assert_ret_val(pplayer, FALSE);
5737 fc_assert_ret_val(punit, FALSE);
5738
5739 /* Sanity check: The target city still exists. */
5740 fc_assert_ret_val(pcity_dest, FALSE);
5741
5742 act_utype = unit_type_get(punit);
5743 shields = unit_shield_value(punit, unit_type_get(punit), paction);
5744
5745 if (action_has_result(paction, ACTRES_HELP_WONDER)) {
5746 /* Add the caravan shields */
5747 pcity_dest->shield_stock += shields;
5748
5749 /* Will be punished for changing production to something that can't
5750 * receive "Help Wonder" help. */
5751 fc_assert(city_production_gets_caravan_shields(
5752 &pcity_dest->production));
5753 pcity_dest->caravan_shields += shields;
5754 } else {
5755 fc_assert(action_has_result(paction, ACTRES_DISBAND_UNIT_RECOVER));
5756 /* Add the shields from recycling the unit to the city's current
5757 * production. */
5758 pcity_dest->shield_stock += shields;
5759
5760 /* If we change production later at this turn. No penalty is added. */
5761 pcity_dest->disbanded_shields += shields;
5762 }
5763
5764 cowner = city_owner(pcity_dest);
5765
5766 conn_list_do_buffer(cowner->connections);
5767
5768 if (action_has_result(paction, ACTRES_HELP_WONDER)) {
5769 /* Let the player that just donated shields with "Help Wonder" know
5770 * the result of their donation. */
5771 prod = city_production_name_translation(pcity_dest);
5772 } else {
5773 fc_assert(action_has_result(paction, ACTRES_DISBAND_UNIT_RECOVER));
5774 /* TRANS: Your Caravan does "Disband Unit Recover" to help build the
5775 * current production in Bergen (4 surplus).
5776 * "Disband Unit Recover" says "current production" rather than its name. */
5777 prod = _("current production");
5778 }
5779
5780 if (build_points_left(pcity_dest) >= 0) {
5781 /* TRANS: Your Caravan does "Help Wonder" to help build the
5782 * Pyramids in Bergen (4 remaining).
5783 * You can reorder '4' and 'remaining' in the actual format string. */
5784 work = _("remaining");
5785 } else {
5786 /* TRANS: Your Caravan does "Help Wonder" to help build the
5787 * Pyramids in Bergen (4 surplus).
5788 * You can reorder '4' and 'surplus' in the actual format string. */
5789 work = _("surplus");
5790 }
5791
5792 notify_player(pplayer, city_tile(pcity_dest), E_CARAVAN_ACTION,
5793 ftc_server,
5794 /* TRANS: Your Caravan does "Help Wonder" to help build the
5795 * Pyramids in Bergen (4 surplus). */
5796 _("Your %s does %s to help build the %s in %s (%d %s)."),
5797 unit_link(punit),
5798 action_name_translation(paction),
5799 prod,
5800 city_link(pcity_dest),
5801 abs(build_points_left(pcity_dest)),
5802 work);
5803
5804 /* May cause an incident */
5805 action_consequence_success(paction, pplayer, act_utype, cowner,
5806 city_tile(pcity_dest), city_link(pcity_dest));
5807
5808 if (cowner != unit_owner(punit)) {
5809 /* Tell the city owner about the gift they just received. */
5810
5811 notify_player(cowner, city_tile(pcity_dest),
5812 E_CARAVAN_ACTION, ftc_server,
5813 /* TRANS: Help building the Pyramids in Bergen received
5814 * from Persian Caravan (4 surplus). */
5815 _("Help building the %s in %s received from %s %s "
5816 "(%d %s)."),
5817 city_production_name_translation(pcity_dest),
5818 city_link(pcity_dest),
5819 nation_adjective_for_player(pplayer),
5820 unit_link(punit),
5821 abs(build_points_left(pcity_dest)),
5822 work);
5823 }
5824
5825 send_player_info_c(cowner, pplayer->connections);
5826 send_city_info(cowner, pcity_dest);
5827 conn_list_do_unbuffer(cowner->connections);
5828
5829 return TRUE;
5830}
5831
5832/**********************************************************************/
5839 static bool do_unit_establish_trade(struct player *pplayer,
5840 struct unit *punit,
5841 struct city *pcity_dest,
5842 const struct action *paction)
5843{
5844 char homecity_link[MAX_LEN_LINK], destcity_link[MAX_LEN_LINK];
5845 char punit_link[MAX_LEN_LINK];
5846 int revenue;
5847 bool can_establish;
5848 int home_overbooked = 0;
5849 int dest_overbooked = 0;
5850 int home_max;
5851 int dest_max;
5852 struct city *pcity_homecity;
5853 struct trade_route_list *routes_out_of_dest;
5854 struct trade_route_list *routes_out_of_home;
5855 enum trade_route_bonus_type bonus_type;
5856 struct goods_type *goods;
5857 const char *goods_str;
5858 const struct unit_type *act_utype;
5859
5860 /* Sanity check: The actor still exists. */
5861 fc_assert_ret_val(pplayer, FALSE);
5862 fc_assert_ret_val(punit, FALSE);
5863
5864 /* Sanity check: The target city still exists. */
5865 fc_assert_ret_val(pcity_dest, FALSE);
5866
5867 pcity_homecity = player_city_by_number(pplayer, punit->homecity);
5868
5869 if (!pcity_homecity) {
5870 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
5871 _("Sorry, your %s cannot establish"
5872 " a trade route because it has no home city."),
5873 unit_link(punit));
5874 return FALSE;
5875 }
5876
5877 if (game.info.goods_selection == GSM_ARRIVAL) {
5878 goods = goods_from_city_to_unit(pcity_homecity, punit);
5879 } else {
5880 goods = punit->carrying;
5881 }
5882 if (goods == NULL) {
5883 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
5884 _("Sorry, your %s cannot establish"
5885 " a trade route because it's not carrying any goods."),
5886 unit_link(punit));
5887 return FALSE;
5888 }
5889
5890 sz_strlcpy(homecity_link, city_link(pcity_homecity));
5891 sz_strlcpy(destcity_link, city_link(pcity_dest));
5892
5893 if (!can_cities_trade(pcity_homecity, pcity_dest)) {
5894 notify_player(pplayer, city_tile(pcity_dest), E_BAD_COMMAND, ftc_server,
5895 _("Sorry, your %s cannot establish"
5896 " a trade route between %s and %s."),
5897 unit_link(punit),
5898 homecity_link,
5899 destcity_link);
5900 return FALSE;
5901 }
5902
5903 act_utype = unit_type_get(punit);
5904
5905 sz_strlcpy(punit_link, unit_tile_link(punit));
5906 routes_out_of_home = trade_route_list_new();
5907 routes_out_of_dest = trade_route_list_new();
5908
5909 /* This part of code works like can_establish_trade_route, except
5910 * that we actually do the action of making the trade route. */
5911
5912 /* If we can't make a new trade route we can still get the trade bonus. */
5913 can_establish = action_has_result(paction, ACTRES_TRADE_ROUTE)
5914 && !have_cities_trade_route(pcity_homecity, pcity_dest);
5915
5916 if (can_establish) {
5917 home_max = max_trade_routes(pcity_homecity);
5918 dest_max = max_trade_routes(pcity_dest);
5919 home_overbooked = city_num_trade_routes(pcity_homecity) - home_max;
5920 dest_overbooked = city_num_trade_routes(pcity_dest) - dest_max;
5921 }
5922
5923 if (can_establish && (home_overbooked >= 0 || dest_overbooked >= 0)) {
5924 int trade = trade_base_between_cities(pcity_homecity, pcity_dest);
5925
5926 /* See if there's a trade route we can cancel at the home city. */
5927 if (home_overbooked >= 0) {
5928 if (home_max <= 0
5929 || (city_trade_removable(pcity_homecity, routes_out_of_home)
5930 >= trade)) {
5931 notify_player(pplayer, city_tile(pcity_dest),
5932 E_BAD_COMMAND, ftc_server,
5933 _("Sorry, your %s cannot establish"
5934 " a trade route here!"),
5935 punit_link);
5936 if (home_max > 0) {
5937 notify_player(pplayer, city_tile(pcity_dest),
5938 E_BAD_COMMAND, ftc_server,
5939 PL_(" The city of %s already has %d "
5940 "better trade route!",
5941 " The city of %s already has %d "
5942 "better trade routes!", home_max),
5943 homecity_link,
5944 home_max);
5945 }
5946 can_establish = FALSE;
5947 }
5948 }
5949
5950 /* See if there's a trade route we can cancel at the dest city. */
5951 if (can_establish && dest_overbooked >= 0) {
5952 if (dest_max <= 0
5953 || (city_trade_removable(pcity_dest, routes_out_of_dest)
5954 >= trade)) {
5955 notify_player(pplayer, city_tile(pcity_dest),
5956 E_BAD_COMMAND, ftc_server,
5957 _("Sorry, your %s cannot establish"
5958 " a trade route here!"),
5959 punit_link);
5960 if (dest_max > 0) {
5961 notify_player(pplayer, city_tile(pcity_dest),
5962 E_BAD_COMMAND, ftc_server,
5963 PL_(" The city of %s already has %d "
5964 "better trade route!",
5965 " The city of %s already has %d "
5966 "better trade routes!", dest_max),
5967 destcity_link,
5968 dest_max);
5969 }
5970 can_establish = FALSE;
5971 }
5972 }
5973 }
5974
5975 /* We now know for sure whether we can establish a trade route. */
5976
5977 /* Calculate and announce initial revenue. */
5978 revenue
5979 = get_caravan_enter_city_trade_bonus(pcity_homecity, pcity_dest, act_utype,
5980 goods, can_establish);
5981
5982 bonus_type = trade_route_settings_by_type
5983 (cities_trade_route_type(pcity_homecity, pcity_dest))->bonus_type;
5984
5985 conn_list_do_buffer(pplayer->connections);
5986
5987 goods_str = goods_name_translation(goods);
5988
5989 /* We want to keep the bonus type string as the part of the format of the PL_() strings
5990 * for supporting proper pluralization for it. */
5991 switch (bonus_type) {
5992 case TBONUS_NONE:
5993 notify_player(pplayer, city_tile(pcity_dest),
5994 E_CARAVAN_ACTION, ftc_server,
5995 /* TRANS: ... Caravan ... Paris ... Stockholm ... Goods */
5996 _("Your %s from %s has arrived in %s carrying %s."),
5997 punit_link,
5998 homecity_link,
5999 destcity_link,
6000 goods_str);
6001 break;
6002 case TBONUS_GOLD:
6003 notify_player(pplayer, city_tile(pcity_dest),
6004 E_CARAVAN_ACTION, ftc_server,
6005 /* TRANS: ... Caravan ... Paris ... Stockholm, ... Goods... */
6006 PL_("Your %s from %s has arrived in %s carrying %s,"
6007 " and revenues amount to %d in gold.",
6008 "Your %s from %s has arrived in %s carrying %s,"
6009 " and revenues amount to %d in gold.",
6010 revenue),
6011 punit_link,
6012 homecity_link,
6013 destcity_link,
6014 goods_str,
6015 revenue);
6016 break;
6017 case TBONUS_SCIENCE:
6018 notify_player(pplayer, city_tile(pcity_dest),
6019 E_CARAVAN_ACTION, ftc_server,
6020 /* TRANS: ... Caravan ... Paris ... Stockholm, ... Goods... */
6021 PL_("Your %s from %s has arrived in %s carrying %s,"
6022 " and revenues amount to %d in research.",
6023 "Your %s from %s has arrived in %s carrying %s,"
6024 " and revenues amount to %d in research.",
6025 revenue),
6026 punit_link,
6027 homecity_link,
6028 destcity_link,
6029 goods_str,
6030 revenue);
6031 break;
6032 case TBONUS_BOTH:
6033 notify_player(pplayer, city_tile(pcity_dest),
6034 E_CARAVAN_ACTION, ftc_server,
6035 /* TRANS: ... Caravan ... Paris ... Stockholm, ... Goods... */
6036 PL_("Your %s from %s has arrived in %s carrying %s,"
6037 " and revenues amount to %d in gold and research.",
6038 "Your %s from %s has arrived in %s carrying %s,"
6039 " and revenues amount to %d in gold and research.",
6040 revenue),
6041 punit_link,
6042 homecity_link,
6043 destcity_link,
6044 goods_str,
6045 revenue);
6046 break;
6047 }
6048
6049 if (bonus_type == TBONUS_GOLD || bonus_type == TBONUS_BOTH) {
6050 pplayer->economic.gold += revenue;
6051
6052 send_player_info_c(pplayer, pplayer->connections);
6053 }
6054
6055 if (bonus_type == TBONUS_SCIENCE || bonus_type == TBONUS_BOTH) {
6056 /* add bulbs and check for finished research */
6057 update_bulbs(pplayer, revenue, TRUE, TRUE);
6058
6059 /* Inform everyone about tech changes */
6060 send_research_info(research_get(pplayer), NULL);
6061 }
6062
6063 if (can_establish) {
6064 struct trade_route *proute_from, *proute_to;
6065 struct city_list *cities_out_of_home;
6066 struct city_list *cities_out_of_dest;
6067 struct player *partner_player;
6068
6069 /* Announce creation of trade route (it's not actually created until
6070 * later in this function, as we have to cancel existing routes, but
6071 * it makes more sense to announce in this order) */
6072
6073 partner_player = city_owner(pcity_dest);
6074
6075 /* Always tell the unit owner */
6076 notify_player(pplayer, NULL,
6077 E_CARAVAN_ACTION, ftc_server,
6078 _("New trade route established from %s to %s."),
6079 homecity_link,
6080 destcity_link);
6081 if (pplayer != partner_player) {
6082 notify_player(partner_player, city_tile(pcity_dest),
6083 E_CARAVAN_ACTION, ftc_server,
6084 _("The %s established a trade route between their "
6085 "city %s and %s."),
6086 nation_plural_for_player(pplayer),
6087 homecity_link,
6088 destcity_link);
6089 }
6090
6091 cities_out_of_home = city_list_new();
6092 cities_out_of_dest = city_list_new();
6093
6094 /* Now cancel any less profitable trade route from the home city. */
6095 trade_route_list_iterate(routes_out_of_home, premove) {
6096 struct trade_route *pback;
6097
6098 city_list_append(cities_out_of_home, game_city_by_number(premove->partner));
6099
6100 pback = remove_trade_route(pcity_homecity, premove, TRUE, FALSE);
6101 free(premove);
6102 free(pback);
6103 } trade_route_list_iterate_end;
6104
6105 /* And the same for the dest city. */
6106 trade_route_list_iterate(routes_out_of_dest, premove) {
6107 struct trade_route *pback;
6108
6109 city_list_append(cities_out_of_dest, game_city_by_number(premove->partner));
6110
6111 pback = remove_trade_route(pcity_dest, premove, TRUE, FALSE);
6112 free(premove);
6113 free(pback);
6114 } trade_route_list_iterate_end;
6115
6116 /* Actually create the new trade route */
6117 proute_from = fc_malloc(sizeof(struct trade_route));
6118 proute_from->partner = pcity_dest->id;
6119 proute_from->goods = goods;
6120
6121 proute_to = fc_malloc(sizeof(struct trade_route));
6122 proute_to->partner = pcity_homecity->id;
6123 proute_to->goods = goods;
6124
6125 if (goods_has_flag(goods, GF_BIDIRECTIONAL)) {
6126 proute_from->dir = RDIR_BIDIRECTIONAL;
6127 proute_to->dir = RDIR_BIDIRECTIONAL;
6128 } else {
6129 proute_from->dir = RDIR_FROM;
6130 proute_to->dir = RDIR_TO;
6131 }
6132 trade_route_list_append(pcity_homecity->routes, proute_from);
6133 trade_route_list_append(pcity_dest->routes, proute_to);
6134
6135 /* Refresh the cities. */
6136 city_refresh(pcity_homecity);
6137 city_refresh(pcity_dest);
6138 city_list_iterate(cities_out_of_home, pcity) {
6139 city_refresh(pcity);
6140 } city_list_iterate_end;
6141 city_list_iterate(cities_out_of_dest, pcity) {
6142 city_refresh(pcity);
6143 } city_list_iterate_end;
6144
6145 /* Notify the owners of the cities. */
6146 send_city_info(pplayer, pcity_homecity);
6147 send_city_info(partner_player, pcity_dest);
6148 city_list_iterate(cities_out_of_home, pcity) {
6149 send_city_info(city_owner(pcity), pcity);
6150 } city_list_iterate_end;
6151 city_list_iterate(cities_out_of_dest, pcity) {
6152 send_city_info(city_owner(pcity), pcity);
6153 } city_list_iterate_end;
6154
6155 /* Notify each player about the other's cities. */
6156 if (pplayer != partner_player && game.info.reveal_trade_partner) {
6157 map_show_tile(partner_player, city_tile(pcity_homecity));
6158 send_city_info(partner_player, pcity_homecity);
6159 map_show_tile(pplayer, city_tile(pcity_dest));
6160 send_city_info(pplayer, pcity_dest);
6161 }
6162
6163 city_list_iterate(cities_out_of_home, pcity) {
6164 if (partner_player != city_owner(pcity)) {
6165 send_city_info(partner_player, pcity);
6166 send_city_info(city_owner(pcity), pcity_dest);
6167 }
6168 if (pplayer != city_owner(pcity)) {
6169 send_city_info(pplayer, pcity);
6170 send_city_info(city_owner(pcity), pcity_homecity);
6171 }
6172 } city_list_iterate_end;
6173
6174 city_list_iterate(cities_out_of_dest, pcity) {
6175 if (partner_player != city_owner(pcity)) {
6176 send_city_info(partner_player, pcity);
6177 send_city_info(city_owner(pcity), pcity_dest);
6178 }
6179 if (pplayer != city_owner(pcity)) {
6180 send_city_info(pplayer, pcity);
6181 send_city_info(city_owner(pcity), pcity_homecity);
6182 }
6183 } city_list_iterate_end;
6184
6185 city_list_destroy(cities_out_of_home);
6186 city_list_destroy(cities_out_of_dest);
6187 }
6188
6189 /* May cause an incident */
6190 action_consequence_success(paction,
6191 pplayer, act_utype, city_owner(pcity_dest),
6192 city_tile(pcity_dest),
6193 city_link(pcity_dest));
6194
6195 conn_list_do_unbuffer(pplayer->connections);
6196
6197 /* Free data. */
6198 trade_route_list_destroy(routes_out_of_home);
6199 trade_route_list_destroy(routes_out_of_dest);
6200
6201 return TRUE;
6202}
6203
6204/**********************************************************************/
6212 void handle_unit_sscs_set(struct player *pplayer,
6213 int unit_id,
6214 enum unit_ss_data_type type,
6215 int value)
6216{
6217 struct unit *punit = player_unit_by_number(pplayer, unit_id);
6218 const struct civ_map *nmap = &(wld.map);
6219
6220 if (NULL == punit) {
6221 /* Being asked to unqueue a "spent" unit because the client haven't
6222 * been told that it's gone is expected. */
6223 if (type != USSDT_UNQUEUE) {
6224 /* Probably died or bribed. */
6225 log_verbose("handle_unit_sscs_set() invalid unit %d", unit_id);
6226 }
6227
6228 return;
6229 }
6230
6231 switch (type) {
6232 case USSDT_QUEUE:
6233 /* Reminds the client to ask the server about what actions the unit can
6234 * perform against the target tile. Action decision state can be set by
6235 * the server it self too. */
6236
6237 if (index_to_tile(nmap, value) == NULL) {
6238 /* Asked to be reminded to ask what actions the unit can do to a non
6239 * existing target tile. */
6240 log_verbose("unit_sscs_set() invalid target tile %d for unit %d",
6241 value, unit_id);
6242 break;
6243 }
6244
6245 punit->action_decision_want = ACT_DEC_ACTIVE;
6246 punit->action_decision_tile = index_to_tile(nmap, value);
6247
6248 /* Let the client know that this unit needs the player to decide
6249 * what to do. */
6250 send_unit_info(player_reply_dest(pplayer), punit);
6251
6252 break;
6253 case USSDT_UNQUEUE:
6254 /* Delete the reminder for the client to ask the server about what
6255 * actions the unit can perform against a certain target tile.
6256 * Action decision state can be set by the server it self too. */
6257
6258 punit->action_decision_want = ACT_DEC_NOTHING;
6259 punit->action_decision_tile = NULL;
6260
6261 /* Let the client know that this unit no longer needs the player to
6262 * decide what to do. */
6263 send_unit_info(player_reply_dest(pplayer), punit);
6264
6265 break;
6266 case USSDT_BATTLE_GROUP:
6267 /* Battlegroups are handled entirely by the client, so all we have to
6268 do here is save the battlegroup ID so that it'll be persistent. */
6269
6270 punit->battlegroup = CLIP(-1, value, MAX_NUM_BATTLEGROUPS);
6271
6272 break;
6273 case USSDT_SENTRY:
6274 if (value == 0) {
6275 if (punit->activity != ACTIVITY_SENTRY) {
6276 return;
6277 }
6278
6279 if (!unit_activity_internal(punit, ACTIVITY_IDLE)) {
6280 /* Impossible to set to Idle? */
6281 fc_assert(FALSE);
6282 }
6283 } else if (value == 1) {
6284 if (!can_unit_do_activity(nmap, punit, ACTIVITY_SENTRY)) {
6285 return;
6286 }
6287
6288 if (!unit_activity_internal(punit, ACTIVITY_SENTRY)) {
6289 /* Should have been caught above */
6290 fc_assert(FALSE);
6291 }
6292 } else {
6293 log_verbose("handle_unit_sscs_set(): illegal sentry state for %s %d",
6294 unit_rule_name(punit), punit->id);
6295 }
6296 break;
6297 }
6298}
6299
6300/**********************************************************************/
6303 static void unit_plans_clear(struct unit *punit)
6304{
6305 /* Remove city spot reservations for AI settlers on city founding
6306 * mission. */
6307 adv_unit_new_task(punit, AUT_NONE, NULL);
6308
6309 /* Get rid of old orders. */
6310 free_unit_orders(punit);
6311
6312 /* Make sure that no old goto_tile remains. */
6313 punit->goto_tile = NULL;
6314}
6315
6316/**********************************************************************/
6319 void handle_unit_server_side_agent_set(struct player *pplayer,
6320 int unit_id,
6321 enum server_side_agent agent)
6322{
6323 struct unit *punit = player_unit_by_number(pplayer, unit_id);
6324
6325 if (NULL == punit) {
6326 /* Probably died or bribed. */
6327 log_verbose("handle_unit_server_side_agent_set() invalid unit %d",
6328 unit_id);
6329 return;
6330 }
6331
6332 if (!server_side_agent_is_valid(agent)) {
6333 /* Client error. */
6334 log_verbose("handle_unit_server_side_agent_set() invalid agent %d",
6335 agent);
6336 return;
6337 }
6338
6339 /* Set the state or exit */
6340 if (!unit_server_side_agent_set(pplayer, punit, agent)) {
6341 return;
6342 }
6343
6344 /* Give the new agent a blank slate */
6345 unit_plans_clear(punit);
6346
6347 if (agent == SSA_AUTOEXPLORE) {
6348 if (!unit_activity_internal(punit, ACTIVITY_EXPLORE)) {
6349 /* Should have been caught above */
6350 fc_assert(FALSE);
6351 punit->ssa_controller = SSA_NONE;
6352 }
6353
6354 /* Exploring is handled here explicitly, since the player expects to
6355 * see an immediate response from setting a unit to auto-explore.
6356 * Handling it deeper in the code leads to some tricky recursive loops -
6357 * see PR#2631. */
6358 if (punit->moves_left > 0) {
6359 do_explore(punit);
6360 }
6361 }
6362}
6363
6364/**********************************************************************/
6368 bool unit_server_side_agent_set(struct player *pplayer,
6369 struct unit *punit,
6370 enum server_side_agent agent)
6371{
6372 const struct civ_map *nmap = &(wld.map);
6373
6374 /* Check that the agent can be activated for this unit. */
6375 switch (agent) {
6376 case SSA_AUTOSETTLER:
6377 if (!can_unit_do_autosettlers(punit)) {
6378 return FALSE;
6379 }
6380 break;
6381 case SSA_AUTOEXPLORE:
6382 if (!can_unit_do_activity(nmap, punit, ACTIVITY_EXPLORE)) {
6383 return FALSE;
6384 }
6385 break;
6386 case SSA_NONE:
6387 /* Always possible. */
6388 break;
6389 case SSA_COUNT:
6390 fc_assert_ret_val(agent != SSA_COUNT, FALSE);
6391 break;
6392 }
6393
6394 punit->ssa_controller = agent;
6395
6396 send_unit_info(NULL, punit);
6397
6398 return TRUE;
6399}
6400
6401/**********************************************************************/
6405 static void unit_activity_dependencies(struct unit *punit,
6406 enum unit_activity old_activity,
6407 struct extra_type *old_target)
6408{
6409 switch (punit->activity) {
6410 case ACTIVITY_IDLE:
6411 switch (old_activity) {
6412 case ACTIVITY_PILLAGE:
6413 {
6414 if (old_target != NULL) {
6415 unit_list_iterate_safe(unit_tile(punit)->units, punit2) {
6416 if (punit2->activity == ACTIVITY_PILLAGE) {
6417 extra_deps_iterate(&(punit2->activity_target->reqs), pdep) {
6418 if (pdep == old_target) {
6419 set_unit_activity(punit2, ACTIVITY_IDLE);
6420 send_unit_info(NULL, punit2);
6421 break;
6422 }
6423 } extra_deps_iterate_end;
6424 }
6425 } unit_list_iterate_safe_end;
6426 }
6427 break;
6428 }
6429 case ACTIVITY_EXPLORE:
6430 /* Restore unit's control status */
6431 punit->ssa_controller = SSA_NONE;
6432 break;
6433 default:
6434 ; /* do nothing */
6435 }
6436 break;
6437 case ACTIVITY_EXPLORE:
6438 punit->ssa_controller = SSA_AUTOEXPLORE;
6439 set_unit_activity(punit, ACTIVITY_EXPLORE);
6440 send_unit_info(NULL, punit);
6441 break;
6442 default:
6443 /* do nothing */
6444 break;
6445 }
6446}
6447
6448/**********************************************************************/
6454 static bool do_action_activity(struct unit *punit,
6455 const struct action *paction)
6456{
6457 enum unit_activity new_activity = action_get_activity(paction);
6458
6459 fc_assert_ret_val(new_activity != ACTIVITY_LAST, FALSE);
6460 fc_assert_ret_val(!activity_requires_target(new_activity), FALSE);
6461
6462 return unit_activity_internal(punit, new_activity);
6463}
6464
6465/**********************************************************************/
6468 bool unit_activity_handling(struct unit *punit,
6469 enum unit_activity new_activity)
6470{
6471 const struct civ_map *nmap = &(wld.map);
6472
6473 /* Must specify target for ACTIVITY_BASE */
6474 fc_assert_ret_val(new_activity != ACTIVITY_BASE
6475 && new_activity != ACTIVITY_GEN_ROAD, FALSE);
6476
6477 if (new_activity == ACTIVITY_PILLAGE) {
6478 struct extra_type *target = NULL;
6479
6480 /* Assume untargeted pillaging if no target specified */
6481 unit_activity_handling_targeted(punit, new_activity, &target);
6482 } else if (can_unit_do_activity(nmap, punit, new_activity)) {
6483 free_unit_orders(punit);
6484 unit_activity_internal(punit, new_activity);
6485 }
6486
6487 return TRUE;
6488}
6489
6490/**********************************************************************/
6496 static bool unit_activity_internal(struct unit *punit,
6497 enum unit_activity new_activity)
6498{
6499 if (!can_unit_do_activity(&(wld.map), punit, new_activity)) {
6500 return FALSE;
6501 } else {
6502 enum unit_activity old_activity = punit->activity;
6503 struct extra_type *old_target = punit->activity_target;
6504
6505 set_unit_activity(punit, new_activity);
6506 send_unit_info(NULL, punit);
6507 unit_activity_dependencies(punit, old_activity, old_target);
6508
6509 return TRUE;
6510 }
6511}
6512
6513/**********************************************************************/
6519 static bool do_action_activity_targeted(struct unit *punit,
6520 const struct action *paction,
6521 struct extra_type **new_target)
6522{
6523 enum unit_activity new_activity = action_get_activity(paction);
6524
6525 fc_assert_ret_val(new_activity != ACTIVITY_LAST, FALSE);
6526 fc_assert_ret_val(activity_requires_target(new_activity),
6527 unit_activity_internal(punit, new_activity));
6528
6529 return unit_activity_targeted_internal(punit, new_activity, new_target);
6530}
6531
6532/**********************************************************************/
6535 bool unit_activity_handling_targeted(struct unit *punit,
6536 enum unit_activity new_activity,
6537 struct extra_type **new_target)
6538{
6539 if (!activity_requires_target(new_activity)) {
6540 unit_activity_handling(punit, new_activity);
6541 } else if (can_unit_do_activity_targeted(&(wld.map), punit,
6542 new_activity, *new_target)) {
6543 free_unit_orders(punit);
6544 unit_activity_targeted_internal(punit, new_activity, new_target);
6545 }
6546
6547 return TRUE;
6548}
6549
6550/**********************************************************************/
6556 static bool unit_activity_targeted_internal(struct unit *punit,
6557 enum unit_activity new_activity,
6558 struct extra_type **new_target)
6559{
6560 if (!can_unit_do_activity_targeted(&(wld.map), punit,
6561 new_activity, *new_target)) {
6562 return FALSE;
6563 } else {
6564 enum unit_activity old_activity = punit->activity;
6565 struct extra_type *old_target = punit->activity_target;
6566 enum unit_activity stored_activity = new_activity;
6567
6568 unit_assign_specific_activity_target(punit,
6569 &new_activity, new_target);
6570 if (new_activity != stored_activity
6571 && !activity_requires_target(new_activity)) {
6572 /* unit_assign_specific_activity_target() changed our target activity
6573 * (to ACTIVITY_IDLE in practice) */
6574 unit_activity_handling(punit, new_activity);
6575 } else {
6576 set_unit_activity_targeted(punit, new_activity, *new_target);
6577 send_unit_info(NULL, punit);
6578 unit_activity_dependencies(punit, old_activity, old_target);
6579
6580 if (new_activity == ACTIVITY_PILLAGE) {
6581 /* Casus Belli for when the activity successfully begins. */
6582 /* TODO: is it more logical to change Casus_Belli_Complete to
6583 * Casus_Belli_Successful_Beginning and trigger it here? */
6584 action_consequence_success(action_by_number(ACTION_PILLAGE),
6585 unit_owner(punit), unit_type_get(punit),
6586 tile_owner(unit_tile(punit)),
6587 unit_tile(punit),
6588 tile_link(unit_tile(punit)));
6589 }
6590 }
6591
6592 return TRUE;
6593 }
6594}
6595
6596/**********************************************************************/
6599 void handle_unit_orders(struct player *pplayer,
6600 const struct packet_unit_orders *packet)
6601{
6602 int length = packet->length;
6603 struct unit *punit = player_unit_by_number(pplayer, packet->unit_id);
6604 const struct civ_map *nmap = &(wld.map);
6605 struct tile *src_tile = index_to_tile(nmap, packet->src_tile);
6606 struct unit_order *order_list;
6607#ifdef FREECIV_DEBUG
6608 int i;
6609#endif
6610
6611 if (NULL == punit) {
6612 /* Probably died or bribed. */
6613 log_verbose("handle_unit_orders() invalid unit %d", packet->unit_id);
6614 return;
6615 }
6616
6617 if (0 > length || MAX_LEN_ROUTE < length) {
6618 /* Shouldn't happen */
6619 log_error("handle_unit_orders() invalid %s (%d) "
6620 "packet length %d (max %d)", unit_rule_name(punit),
6621 packet->unit_id, length, MAX_LEN_ROUTE);
6622 return;
6623 }
6624
6625 if (src_tile != unit_tile(punit)) {
6626 /* Failed sanity check. Usually this happens if the orders were sent
6627 * in the previous turn, and the client thought the unit was in a
6628 * different position than it's actually in. The easy solution is to
6629 * discard the packet. We don't send an error message to the client
6630 * here (though maybe we should?). */
6631 log_verbose("handle_unit_orders() invalid %s (%d) tile (%d, %d) "
6632 "!= (%d, %d)", unit_rule_name(punit), punit->id,
6633 TILE_XY(src_tile), TILE_XY(unit_tile(punit)));
6634 return;
6635 }
6636
6637 if (ACTIVITY_IDLE != punit->activity) {
6638 /* New orders implicitly abandon current activity */
6639 unit_activity_handling(punit, ACTIVITY_IDLE);
6640 }
6641
6642 if (length) {
6643 order_list = create_unit_orders(nmap, length, packet->orders);
6644 if (!order_list) {
6645 log_error("received invalid orders from %s for %s (%d).",
6646 player_name(pplayer), unit_rule_name(punit), packet->unit_id);
6647 return;
6648 }
6649 }
6650
6651 /* This must be before old orders are freed. If this is
6652 * settlers on city founding mission, city spot reservation
6653 * from goto_tile must be freed, and free_unit_orders() loses
6654 * goto_tile information */
6655 adv_unit_new_task(punit, AUT_NONE, NULL);
6656
6657 free_unit_orders(punit);
6658 /* If we waited on a tile, reset punit->done_moving */
6659 punit->done_moving = (punit->moves_left <= 0);
6660
6661 if (length == 0) {
6662 fc_assert(!unit_has_orders(punit));
6663 send_unit_info(NULL, punit);
6664 return;
6665 }
6666
6667 punit->has_orders = TRUE;
6668 punit->orders.length = length;
6669 punit->orders.index = 0;
6670 punit->orders.repeat = packet->repeat;
6671 punit->orders.vigilant = packet->vigilant;
6672 if (length) {
6673 punit->orders.list = order_list;
6674 }
6675
6676 if (!packet->repeat) {
6677 punit->goto_tile = index_to_tile(nmap, packet->dest_tile);
6678 } else {
6679 /* Make sure that no old goto_tile remains. */
6680 punit->goto_tile = NULL;
6681 }
6682
6683#ifdef FREECIV_DEBUG
6684 log_debug("Orders for unit %d: length:%d", packet->unit_id, length);
6685 for (i = 0; i < length; i++) {
6686 log_debug(" %d,%s,%s,%d,%d",
6687 packet->orders[i].order, dir_get_name(packet->orders[i].dir),
6688 packet->orders[i].order == ORDER_PERFORM_ACTION ?
6689 action_id_rule_name(packet->orders[i].action) :
6690 packet->orders[i].order == ORDER_ACTIVITY ?
6691 unit_activity_name(packet->orders[i].activity) :
6692 "no action/activity required",
6693 packet->orders[i].target,
6694 packet->orders[i].sub_target);
6695 }
6696#endif /* FREECIV_DEBUG */
6697
6698 if (!is_player_phase(unit_owner(punit), game.info.phase)
6699 || execute_orders(punit, TRUE)) {
6700 /* Looks like the unit survived. */
6701 send_unit_info(NULL, punit);
6702 }
6703}
6704
6705/**********************************************************************/
6708 void handle_worker_task(struct player *pplayer,
6709 const struct packet_worker_task *packet)
6710{
6711 struct city *pcity = game_city_by_number(packet->city_id);
6712 struct worker_task *ptask = NULL;
6713 struct tile *ptile = index_to_tile(&(wld.map), packet->tile_id);
6714
6715 if (pcity == NULL || pcity->owner != pplayer || ptile == NULL) {
6716 return;
6717 }
6718
6719 worker_task_list_iterate(pcity->task_reqs, ptask_old) {
6720 if (tile_index(ptask_old->ptile) == packet->tile_id) {
6721 ptask = ptask_old;
6722 }
6723 } worker_task_list_iterate_end;
6724
6725 if (ptask == NULL) {
6726 if (packet->activity == ACTIVITY_LAST) {
6727 return;
6728 }
6729
6730 ptask = fc_malloc(sizeof(struct worker_task));
6731 worker_task_init(ptask);
6732 worker_task_list_append(pcity->task_reqs, ptask);
6733 } else {
6734 if (packet->activity == ACTIVITY_LAST) {
6735 worker_task_list_remove(pcity->task_reqs, ptask);
6736 free(ptask);
6737 ptask = NULL;
6738 }
6739 }
6740
6741 if (ptask != NULL) {
6742 ptask->ptile = ptile;
6743 ptask->act = packet->activity;
6744 if (packet->tgt >= 0) {
6745 if (packet->tgt < MAX_EXTRA_TYPES) {
6746 ptask->tgt = extra_by_number(packet->tgt);
6747 } else {
6748 log_debug("Illegal worker task target %d", packet->tgt);
6749 ptask->tgt = NULL;
6750 }
6751 } else {
6752 ptask->tgt = NULL;
6753 }
6754 ptask->want = packet->want;
6755 }
6756
6757 if (ptask && !worker_task_is_sane(ptask)) {
6758 log_debug("Bad worker task");
6759 worker_task_list_remove(pcity->task_reqs, ptask);
6760 free(ptask);
6761 ptask = NULL;
6762 return;
6763 }
6764
6765 lsend_packet_worker_task(pplayer->connections, packet);
6766}
action_name_translation
const char * action_name_translation(const struct action *action)
Definition actions.c:1982
action_distance_inside_max
bool action_distance_inside_max(const struct action *action, const int distance)
Definition actions.c:1925
action_mp_full_makes_legal
bool action_mp_full_makes_legal(const struct unit *actor, const action_id act_id)
Definition actions.c:6294
action_id_name_translation
const char * action_id_name_translation(action_id act_id)
Definition actions.c:2002
action_prob_self
struct act_prob action_prob_self(const struct unit *actor_unit, const action_id act_id)
Definition actions.c:5497
action_prob_possible
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:5823
action_actor_utype_hard_reqs_ok
bool action_actor_utype_hard_reqs_ok(const struct action *paction, const struct unit_type *actor_unittype)
Definition actions.c:3347
action_prob_unit_vs_tgt
struct act_prob action_prob_unit_vs_tgt(const struct action *paction, const struct unit *act_unit, const struct city *tgt_city, const struct unit *tgt_unit, const struct tile *tgt_tile, const struct extra_type *extra_tgt)
Definition actions.c:5519
action_prob_vs_city
struct act_prob action_prob_vs_city(const struct unit *actor_unit, const action_id act_id, const struct city *target_city)
Definition actions.c:4981
action_prob_vs_unit
struct act_prob action_prob_vs_unit(const struct unit *actor_unit, const action_id act_id, const struct unit *target_unit)
Definition actions.c:5065
action_id_rule_name
const char * action_id_rule_name(action_id act_id)
Definition actions.c:1991
action_prob_vs_tile
struct act_prob action_prob_vs_tile(const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:5342
is_action_enabled_unit_on_tile
bool is_action_enabled_unit_on_tile(const struct civ_map *nmap, const action_id wanted_action, const struct unit *actor_unit, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:4073
action_is_blocked_by
struct action * action_is_blocked_by(const struct action *act, const struct unit *actor_unit, const struct tile *target_tile_arg, const struct city *target_city_arg, const struct unit *target_unit)
Definition actions.c:3027
action_prob_vs_stack
struct act_prob action_prob_vs_stack(const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile)
Definition actions.c:5258
is_action_enabled_unit_on_city
bool is_action_enabled_unit_on_city(const struct civ_map *nmap, const action_id wanted_action, const struct unit *actor_unit, const struct city *target_city)
Definition actions.c:3832
is_action_enabled_unit_on_unit
bool is_action_enabled_unit_on_unit(const struct civ_map *nmap, const action_id wanted_action, const struct unit *actor_unit, const struct unit *target_unit)
Definition actions.c:3909
action_maybe_possible_actor_unit
bool action_maybe_possible_actor_unit(const struct civ_map *nmap, const action_id act_id, const struct unit *actor_unit)
Definition actions.c:6239
action_prob_vs_extras
struct act_prob action_prob_vs_extras(const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:5426
action_id_exists
bool action_id_exists(const action_id act_id)
Definition actions.c:1820
action_get_target_kind
enum action_target_kind action_get_target_kind(const struct action *paction)
Definition actions.c:1860
action_enablers_for_action
struct action_enabler_list * action_enablers_for_action(action_id action)
Definition actions.c:2306
actions.h
ACTPROB_NA
#define ACTPROB_NA
Definition actions.h:906
action_by_number
static struct action * action_by_number(action_id act_id)
Definition actions.h:633
action_has_result
#define action_has_result(_act_, _res_)
Definition actions.h:429
action_enabler_list_iterate_end
#define action_enabler_list_iterate_end
Definition actions.h:439
action_id_get_role
#define action_id_get_role(act_id)
Definition actions.h:694
action_iterate_end
#define action_iterate_end
Definition actions.h:463
MAX_NUM_ACTIONS
#define MAX_NUM_ACTIONS
Definition actions.h:312
action_id_get_actor_kind
#define action_id_get_actor_kind(act_id)
Definition actions.h:646
ACTPROB_NOT_KNOWN
#define ACTPROB_NOT_KNOWN
Definition actions.h:908
action_get_activity
#define action_get_activity(_pact_)
Definition actions.h:697
action_has_result_safe
#define action_has_result_safe(paction, result)
Definition actions.h:661
action_enabler_list_iterate
#define action_enabler_list_iterate(action_enabler_list, aenabler)
Definition actions.h:437
action_id_distance_accepted
#define action_id_distance_accepted(act_id, distance)
Definition actions.h:682
ACTPROB_IMPOSSIBLE
#define ACTPROB_IMPOSSIBLE
Definition actions.h:904
action_iterate
#define action_iterate(_act_)
Definition actions.h:459
ACTION_ANY
#define ACTION_ANY
Definition actions.h:306
action_id_get_target_kind
#define action_id_get_target_kind(act_id)
Definition actions.h:650
action_id_has_result_safe
#define action_id_has_result_safe(act_id, result)
Definition actions.h:663
action_id_has_complex_target
#define action_id_has_complex_target(act_id)
Definition actions.h:668
ACTION_NONE
#define ACTION_NONE
Definition actions.h:309
action_tgt_tile
struct tile * action_tgt_tile(struct unit *actor, struct tile *target, const struct extra_type *target_extra, bool accept_all_actions)
Definition actiontools.c:729
action_consequence_caught
void action_consequence_caught(const struct action *paction, struct player *offender, const struct unit_type *offender_utype, struct player *victim_player, const struct tile *victim_tile, const char *victim_link)
Definition actiontools.c:374
action_auto_perf_unit_do
const struct action * action_auto_perf_unit_do(const enum action_auto_perf_cause cause, struct unit *actor, const struct player *other_player, const struct output_type *eval_output, const struct action *eval_action, const struct tile *target_tile, const struct city *target_city, const struct unit *target_unit, const struct extra_type *target_extra)
Definition actiontools.c:991
action_tgt_unit
struct unit * action_tgt_unit(struct unit *actor, struct tile *target_tile, bool accept_all_actions)
Definition actiontools.c:703
action_consequence_success
void action_consequence_success(const struct action *paction, struct player *offender, const struct unit_type *offender_utype, struct player *victim_player, const struct tile *victim_tile, const char *victim_link)
Definition actiontools.c:551
action_tgt_city
struct city * action_tgt_city(struct unit *actor, struct tile *target_tile, bool accept_all_actions)
Definition actiontools.c:638
action_tgt_tile_extra
struct extra_type * action_tgt_tile_extra(const struct unit *actor, const struct tile *target_tile, bool accept_all_actions)
Definition actiontools.c:864
action_failed_dice_roll
bool action_failed_dice_roll(const struct player *act_player, const struct unit *act_unit, const struct city *tgt_city, const struct player *tgt_player, const struct action *paction)
Definition actiontools.c:1185
action_sub_target_id_for_action
int action_sub_target_id_for_action(const struct action *paction, struct unit *actor_unit)
Definition actiontools.c:881
actiontools.h
ASSERT_UNUSED_ACTRES_CASES
#define ASSERT_UNUSED_ACTRES_CASES
Definition actres.h:37
ai.h
CALL_PLR_AI_FUNC
#define CALL_PLR_AI_FUNC(_func, _player,...)
Definition ai.h:374
astr_free
void astr_free(struct astring *astr)
Definition astring.c:153
astr_build_or_list
const char * astr_build_or_list(struct astring *astr, const char *const *items, size_t number)
Definition astring.c:329
n
#define n
Definition astring.c:77
astring.h
astr_str
static const char * astr_str(const struct astring *astr) fc__attribute((nonnull(1)))
Definition astring.h:93
ASTRING_INIT
#define ASTRING_INIT
Definition astring.h:44
autoexplorer.h
adv_unit_new_task
void adv_unit_new_task(struct unit *punit, enum adv_unit_task task, struct tile *ptile)
Definition autosettlers.c:1267
autosettlers.h
barbarian.h
base_extra_get
struct extra_type * base_extra_get(const struct base_type *pbase)
Definition base.c:101
get_base_by_gui_type
struct base_type * get_base_by_gui_type(enum base_gui_type type, const struct unit *punit, const struct tile *ptile)
Definition base.c:139
BV_CLR_ALL
#define BV_CLR_ALL(bv)
Definition bitvector.h:95
BV_SET
#define BV_SET(bv, bit)
Definition bitvector.h:81
BV_ISSET
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
citizens_update
void citizens_update(struct city *pcity, struct player *plr)
Definition citizenshand.c:202
citizenshand.h
city_production_gets_caravan_shields
bool city_production_gets_caravan_shields(const struct universal *tgt)
Definition city.c:1852
city_has_building
bool city_has_building(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:1231
is_capital
bool is_capital(const struct city *pcity)
Definition city.c:1571
city_name_get
const char * city_name_get(const struct city *pcity)
Definition city.c:1128
citymindist_prevents_city_on_tile
bool citymindist_prevents_city_on_tile(const struct civ_map *nmap, const struct tile *ptile)
Definition city.c:1456
city_size_add
void city_size_add(struct city *pcity, int add)
Definition city.c:1155
city_can_grow_to
bool city_can_grow_to(const struct city *pcity, int pop_size)
Definition city.c:2004
tile_non_attack_city
struct city * tile_non_attack_city(const struct tile *ptile, const struct player *pplayer)
Definition city.c:2043
city_exist
bool city_exist(int id)
Definition city.c:3560
city_production_name_translation
const char * city_production_name_translation(const struct city *pcity)
Definition city.c:699
city.h
is_non_allied_city_tile
static bool is_non_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:762
city_list_iterate
#define city_list_iterate(citylist, pcity)
Definition city.h:508
city_tile
#define city_tile(_pcity_)
Definition city.h:564
city_size_get
static citizens city_size_get(const struct city *pcity)
Definition city.h:569
city_owner
#define city_owner(_pcity_)
Definition city.h:563
city_list_iterate_end
#define city_list_iterate_end
Definition city.h:510
send_city_info
void send_city_info(struct player *dest, struct city *pcity)
Definition citytools.c:2343
create_city
void create_city(struct player *pplayer, struct tile *ptile, const char *name, struct player *nationality)
Definition citytools.c:1513
build_points_left
int build_points_left(struct city *pcity)
Definition citytools.c:571
building_lost
void building_lost(struct city *pcity, const struct impr_type *pimprove, const char *reason, struct unit *destroyer)
Definition citytools.c:3039
city_units_upkeep
void city_units_upkeep(const struct city *pcity)
Definition citytools.c:3127
is_allowed_city_name
bool is_allowed_city_name(struct player *pplayer, const char *cityname, char *error_buf, size_t bufsz)
Definition citytools.c:369
remove_city
void remove_city(struct city *pcity)
Definition citytools.c:1699
remove_trade_route
struct trade_route * remove_trade_route(struct city *pc1, struct trade_route *proute, bool announce, bool source_gone)
Definition citytools.c:2907
citytools.h
nullify_prechange_production
void nullify_prechange_production(struct city *pcity)
Definition cityturn.c:3536
city_change_size
bool city_change_size(struct city *pcity, citizens size, struct player *nationality, const char *reason)
Definition cityturn.c:1031
city_incite_cost
int city_incite_cost(struct player *pplayer, struct city *pcity)
Definition cityturn.c:3424
city_reduce_size
bool city_reduce_size(struct city *pcity, citizens pop_loss, struct player *destroyer, const char *reason)
Definition cityturn.c:762
city_refresh
bool city_refresh(struct city *pcity)
Definition cityturn.c:159
cityturn.h
list
static struct fc_sockaddr_list * list
Definition clinet.c:102
is_unit_reachable_at
bool is_unit_reachable_at(const struct unit *defender, const struct unit *attacker, const struct tile *location)
Definition combat.c:85
unit_attack_units_at_tile_result
enum unit_attack_result unit_attack_units_at_tile_result(const struct unit *punit, const struct action *paction, const struct tile *ptile)
Definition combat.c:256
sdi_try_defend
struct city * sdi_try_defend(const struct civ_map *nmap, const struct player *owner, const struct tile *ptile)
Definition combat.c:501
get_total_defense_power
int get_total_defense_power(const struct unit *attacker, const struct unit *defender)
Definition combat.c:765
get_total_attack_power
int get_total_attack_power(const struct unit *attacker, const struct unit *defender, const struct action *paction)
Definition combat.c:608
is_tired_attack
bool is_tired_attack(int moves_left)
Definition combat.c:527
unit_wipe_units_at_tile_result
enum unit_attack_result unit_wipe_units_at_tile_result(const struct unit *punit, const struct tile *ptile)
Definition combat.c:271
get_defender
struct unit * get_defender(const struct civ_map *nmap, const struct unit *attacker, const struct tile *ptile, const struct action *paction)
Definition combat.c:834
get_modified_firepower
void get_modified_firepower(const struct civ_map *nmap, const struct unit *attacker, const struct unit *defender, int *att_fp, int *def_fp)
Definition combat.c:409
combat.h
POWER_FACTOR
#define POWER_FACTOR
Definition combat.h:32
ATT_NOT_WIPABLE
@ ATT_NOT_WIPABLE
Definition combat.h:40
ATT_NONNATIVE_DST
@ ATT_NONNATIVE_DST
Definition combat.h:39
ATT_OK
@ ATT_OK
Definition combat.h:35
ATT_NON_ATTACK
@ ATT_NON_ATTACK
Definition combat.h:36
ATT_UNREACHABLE
@ ATT_UNREACHABLE
Definition combat.h:37
ATT_NONNATIVE_SRC
@ ATT_NONNATIVE_SRC
Definition combat.h:38
incite_cost
char * incite_cost
Definition comments.c:74
MAX_LEN_MSG
#define MAX_LEN_MSG
Definition conn_types.h:37
MAX_LEN_ROUTE
#define MAX_LEN_ROUTE
Definition conn_types.h:38
conn_list_do_unbuffer
void conn_list_do_unbuffer(struct conn_list *dest)
Definition connection.c:366
conn_list_do_buffer
void conn_list_do_buffer(struct conn_list *dest)
Definition connection.c:356
conn_list_iterate
#define conn_list_iterate(connlist, pconn)
Definition connection.h:108
conn_list_iterate_end
#define conn_list_iterate_end
Definition connection.h:110
bombard
static void bombard(QVariant data1, QVariant data2)
Definition dialogs.cpp:2766
target_unit
struct unit struct city struct unit * target_unit
Definition dialogs_g.h:56
actor_unit
struct unit * actor_unit
Definition dialogs_g.h:55
actor
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit * actor
Definition dialogs_g.h:73
target_tile
struct unit struct city struct unit struct tile * target_tile
Definition dialogs_g.h:57
punit
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
target_city
struct unit struct city * target_city
Definition dialogs_g.h:56
cost
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int cost
Definition dialogs_g.h:74
target_extra
struct unit struct city struct unit struct tile struct extra_type * target_extra
Definition dialogs_g.h:57
spy_escape
bool spy_escape(struct player *pplayer, struct unit *actor_unit, struct city *target_city, struct tile *target_tile, const struct action *paction)
Definition diplomats.c:2343
spy_steal_some_maps
bool spy_steal_some_maps(struct player *act_player, struct unit *act_unit, struct city *tgt_city, const struct action *paction)
Definition diplomats.c:1698
spy_sabotage_unit
bool spy_sabotage_unit(struct player *pplayer, struct unit *pdiplomat, struct unit *pvictim, const struct action *paction)
Definition diplomats.c:548
diplomat_embassy
bool diplomat_embassy(struct player *pplayer, struct unit *pdiplomat, struct city *pcity, const struct action *paction)
Definition diplomats.c:483
spy_send_sabotage_list
void spy_send_sabotage_list(struct connection *pc, struct unit *pdiplomat, struct city *pcity, const struct action *paction, int request_kind)
Definition diplomats.c:429
diplomat_get_tech
bool diplomat_get_tech(struct player *pplayer, struct unit *pdiplomat, struct city *pcity, Tech_type_id technology, const struct action *paction)
Definition diplomats.c:891
diplomat_sabotage
bool diplomat_sabotage(struct player *pplayer, struct unit *pdiplomat, struct city *pcity, Impr_type_id improvement, const struct action *paction)
Definition diplomats.c:1284
diplomat_incite
bool diplomat_incite(struct player *pplayer, struct unit *pdiplomat, struct city *pcity, const struct action *paction)
Definition diplomats.c:1135
spy_steal_gold
bool spy_steal_gold(struct player *act_player, struct unit *act_unit, struct city *tgt_city, const struct action *paction)
Definition diplomats.c:1556
spy_spread_plague
bool spy_spread_plague(struct player *act_player, struct unit *act_unit, struct city *tgt_city, const struct action *paction)
Definition diplomats.c:214
spy_nuke_city
bool spy_nuke_city(struct player *act_player, struct unit *act_unit, struct city *tgt_city, const struct action *paction)
Definition diplomats.c:1834
diplomat_investigate
bool diplomat_investigate(struct player *pplayer, struct unit *pdiplomat, struct city *pcity, const struct action *paction)
Definition diplomats.c:324
diplomat_bribe
bool diplomat_bribe(struct player *pplayer, struct unit *pdiplomat, struct unit *pvictim, const struct action *paction)
Definition diplomats.c:643
spy_attack
bool spy_attack(struct player *act_player, struct unit *act_unit, struct tile *tgt_tile, const struct action *paction)
Definition diplomats.c:807
spy_poison
bool spy_poison(struct player *pplayer, struct unit *pdiplomat, struct city *pcity, const struct action *paction)
Definition diplomats.c:97
diplomats.h
id
int int id
Definition editgui_g.h:28
get_target_bonus_effects
int get_target_bonus_effects(struct effect_list *plist, const struct req_context *context, const struct player *other_player, enum effect_type effect_type)
Definition effects.c:748
event
enum event_type event
Definition events.c:81
events.h
ane_kind
ane_kind
Definition explanation.h:22
ANEK_IS_CITY_CENTER
@ ANEK_IS_CITY_CENTER
Definition explanation.h:62
ANEK_ACTION_BLOCKS
@ ANEK_ACTION_BLOCKS
Definition explanation.h:98
ANEK_DOMESTIC
@ ANEK_DOMESTIC
Definition explanation.h:50
ANEK_LOW_MP
@ ANEK_LOW_MP
Definition explanation.h:60
ANEK_TGT_TILE_UNKNOWN
@ ANEK_TGT_TILE_UNKNOWN
Definition explanation.h:94
ANEK_BAD_TERRAIN_TGT
@ ANEK_BAD_TERRAIN_TGT
Definition explanation.h:32
ANEK_TRIREME_MOVE
@ ANEK_TRIREME_MOVE
Definition explanation.h:74
ANEK_CITY_TOO_CLOSE_TGT
@ ANEK_CITY_TOO_CLOSE_TGT
Definition explanation.h:83
ANEK_CITY_NO_CAPACITY
@ ANEK_CITY_NO_CAPACITY
Definition explanation.h:89
ANEK_NATION_TGT
@ ANEK_NATION_TGT
Definition explanation.h:58
ANEK_BAD_TARGET
@ ANEK_BAD_TARGET
Definition explanation.h:28
ANEK_MISSING_TARGET
@ ANEK_MISSING_TARGET
Definition explanation.h:26
ANEK_TGT_IS_CLAIMED
@ ANEK_TGT_IS_CLAIMED
Definition explanation.h:66
ANEK_FOREIGN
@ ANEK_FOREIGN
Definition explanation.h:52
ANEK_DISEMBARK_ACT
@ ANEK_DISEMBARK_ACT
Definition explanation.h:77
ANEK_IS_TRANSPORTED
@ ANEK_IS_TRANSPORTED
Definition explanation.h:34
ANEK_IS_NOT_CITY_CENTER
@ ANEK_IS_NOT_CITY_CENTER
Definition explanation.h:64
ANEK_TGT_IS_UNCLAIMED
@ ANEK_TGT_IS_UNCLAIMED
Definition explanation.h:68
ANEK_TGT_NON_ALLIED_UNITS_ON_TILE
@ ANEK_TGT_NON_ALLIED_UNITS_ON_TILE
Definition explanation.h:54
ANEK_BAD_TERRAIN_ACT
@ ANEK_BAD_TERRAIN_ACT
Definition explanation.h:30
ANEK_SCENARIO_DISABLED
@ ANEK_SCENARIO_DISABLED
Definition explanation.h:81
ANEK_ACTOR_HAS_HOME_CITY
@ ANEK_ACTOR_HAS_HOME_CITY
Definition explanation.h:42
ANEK_PEACE
@ ANEK_PEACE
Definition explanation.h:48
ANEK_DISTANCE_NEAR
@ ANEK_DISTANCE_NEAR
Definition explanation.h:70
ANEK_UNKNOWN
@ ANEK_UNKNOWN
Definition explanation.h:102
ANEK_ACT_NOT_ENOUGH_MONEY
@ ANEK_ACT_NOT_ENOUGH_MONEY
Definition explanation.h:96
ANEK_IS_NOT_TRANSPORTING
@ ANEK_IS_NOT_TRANSPORTING
Definition explanation.h:40
ANEK_TGT_UNREACHABLE
@ ANEK_TGT_UNREACHABLE
Definition explanation.h:79
ANEK_ACTOR_HAS_NO_HOME_CITY
@ ANEK_ACTOR_HAS_NO_HOME_CITY
Definition explanation.h:44
ANEK_NOT_WIPABLE
@ ANEK_NOT_WIPABLE
Definition explanation.h:100
ANEK_CITY_TOO_BIG
@ ANEK_CITY_TOO_BIG
Definition explanation.h:85
ANEK_NO_WAR
@ ANEK_NO_WAR
Definition explanation.h:46
ANEK_DISTANCE_FAR
@ ANEK_DISTANCE_FAR
Definition explanation.h:72
ANEK_ACTOR_UNIT
@ ANEK_ACTOR_UNIT
Definition explanation.h:24
ANEK_NATION_ACT
@ ANEK_NATION_ACT
Definition explanation.h:56
ANEK_IS_NOT_TRANSPORTED
@ ANEK_IS_NOT_TRANSPORTED
Definition explanation.h:36
ANEK_IS_TRANSPORTING
@ ANEK_IS_TRANSPORTING
Definition explanation.h:38
ANEK_CITY_POP_LIMIT
@ ANEK_CITY_POP_LIMIT
Definition explanation.h:87
ANEK_TGT_IS_UNIQUE_ACT_HAS
@ ANEK_TGT_IS_UNIQUE_ACT_HAS
Definition explanation.h:92
next_extra_for_tile
struct extra_type * next_extra_for_tile(const struct tile *ptile, enum extra_cause cause, const struct player *pplayer, const struct unit *punit)
Definition extras.c:765
extra_owner
struct player * extra_owner(const struct tile *ptile)
Definition extras.c:1114
prev_extra_in_tile
struct extra_type * prev_extra_in_tile(const struct tile *ptile, enum extra_rmcause rmcause, const struct player *pplayer, const struct unit *punit)
Definition extras.c:790
extra_by_number
struct extra_type * extra_by_number(int id)
Definition extras.c:183
extra_deps_iterate
#define extra_deps_iterate(_reqs, _dep)
Definition extras.h:371
extra_deps_iterate_end
#define extra_deps_iterate_end
Definition extras.h:379
EXTRA_NONE
#define EXTRA_NONE
Definition extras.h:85
NO_TARGET
#define NO_TARGET
Definition fc_types.h:357
Impr_type_id
int Impr_type_id
Definition fc_types.h:379
MAX_NUM_PLAYERS
#define MAX_NUM_PLAYERS
Definition fc_types.h:36
AUT_NONE
@ AUT_NONE
Definition fc_types.h:373
action_id
int action_id
Definition fc_types.h:392
ACTRES_NONE
#define ACTRES_NONE
Definition fc_types.h:330
MAX_EXTRA_TYPES
#define MAX_EXTRA_TYPES
Definition fc_types.h:50
MAX_LEN_NAME
#define MAX_LEN_NAME
Definition fc_types.h:66
Unit_type_id
int Unit_type_id
Definition fc_types.h:385
IDENTITY_NUMBER_ZERO
#define IDENTITY_NUMBER_ZERO
Definition fc_types.h:92
fcintl.h
PL_
#define PL_(String1, String2, n)
Definition fcintl.h:71
_
#define _(String)
Definition fcintl.h:67
city_tile_link
const char * city_tile_link(const struct city *pcity)
Definition featured_text.c:1089
tile_link
const char * tile_link(const struct tile *ptile)
Definition featured_text.c:1106
ftc_server
const struct ft_color ftc_server
Definition featured_text.c:77
city_link
const char * city_link(const struct city *pcity)
Definition featured_text.c:1072
unit_link
const char * unit_link(const struct unit *punit)
Definition featured_text.c:1122
unit_tile_link
const char * unit_tile_link(const struct unit *punit)
Definition featured_text.c:1139
featured_text.h
MAX_LEN_LINK
#define MAX_LEN_LINK
Definition featured_text.h:138
game
struct civ_game game
Definition game.c:62
is_player_phase
bool is_player_phase(const struct player *pplayer, int phase)
Definition game.c:705
wld
struct world wld
Definition game.c:63
game_unit_by_number
struct unit * game_unit_by_number(int id)
Definition game.c:116
game_city_by_number
struct city * game_city_by_number(int id)
Definition game.c:107
game.h
actor_unit_id
static int actor_unit_id
Definition action_dialog.c:68
target_extra_id
static int target_extra_id
Definition action_dialog.c:70
owner
struct city * owner
Definition citydlg.c:220
type
GType type
Definition repodlgs.c:1313
improvement_by_number
struct impr_type * improvement_by_number(const Impr_type_id id)
Definition improvement.c:194
improvement_name_translation
const char * improvement_name_translation(const struct impr_type *pimprove)
Definition improvement.c:243
B_LAST
#define B_LAST
Definition improvement.h:42
name
const char * name
Definition inputfile.c:127
log.h
fc_assert_msg
#define fc_assert_msg(condition, message,...)
Definition log.h:181
fc_assert_ret
#define fc_assert_ret(condition)
Definition log.h:191
log_verbose
#define log_verbose(message,...)
Definition log.h:109
fc_assert
#define fc_assert(condition)
Definition log.h:176
fc_assert_ret_val
#define fc_assert_ret_val(condition, val)
Definition log.h:194
fc_assert_action
#define fc_assert_action(condition, action)
Definition log.h:187
log_debug
#define log_debug(message,...)
Definition log.h:115
log_error
#define log_error(message,...)
Definition log.h:103
fc_assert_ret_val_msg
#define fc_assert_ret_val_msg(condition, val, message,...)
Definition log.h:208
luascript_types.h
opposite_direction
enum direction8 opposite_direction(enum direction8 dir)
Definition map.c:1937
dir_get_name
const char * dir_get_name(enum direction8 dir)
Definition map.c:1146
index_to_tile
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:456
real_map_distance
int real_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:630
base_get_direction_for_step
bool base_get_direction_for_step(const struct civ_map *nmap, const struct tile *start_tile, const struct tile *end_tile, enum direction8 *dir)
Definition map.c:1328
map.h
map_move_cost_unit
static int map_move_cost_unit(const struct civ_map *nmap, struct unit *punit, const struct tile *ptile)
Definition map.h:293
vision_clear_sight
void vision_clear_sight(struct vision *vision)
Definition maphand.c:2511
map_is_known
bool map_is_known(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:894
map_show_tile
void map_show_tile(struct player *src_player, struct tile *ptile)
Definition maphand.c:768
map_is_known_and_seen
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Definition maphand.c:920
map_show_circle
void map_show_circle(struct player *pplayer, struct tile *ptile, int radius_sq)
Definition maphand.c:864
map_get_player_tile
struct player_tile * map_get_player_tile(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1379
maphand.h
mem.h
fc_strdup
#define fc_strdup(str)
Definition mem.h:43
fc_malloc
#define fc_malloc(sz)
Definition mem.h:34
move_points_text
const char * move_points_text(int mp, bool reduce)
Definition movement.c:1015
unit_move_to_tile_test
enum unit_move_result unit_move_to_tile_test(const struct civ_map *nmap, const struct unit *punit, enum unit_activity activity, const struct tile *src_tile, const struct tile *dst_tile, bool igzoc, bool enter_transport, struct unit *embark_to, bool enter_enemy_city)
Definition movement.c:630
can_unit_exist_at_tile
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:319
is_native_tile
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:331
unit_move_rate
int unit_move_rate(const struct unit *punit)
Definition movement.c:90
unit_could_load_at
bool unit_could_load_at(const struct unit *punit, const struct tile *ptile)
Definition movement.c:911
unit_teleport_to_tile_test
enum unit_move_result unit_teleport_to_tile_test(const struct civ_map *nmap, const struct unit *punit, enum unit_activity activity, const struct tile *src_tile, const struct tile *dst_tile, bool enter_transport, struct unit *embark_to, bool enter_enemy_city)
Definition movement.c:774
can_unit_survive_at_tile
bool can_unit_survive_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:491
unit_can_move_to_tile
bool unit_can_move_to_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *dst_tile, bool igzoc, bool enter_transport, bool enter_enemy_city)
Definition movement.c:572
movement.h
SINGLE_MOVE
#define SINGLE_MOVE
Definition movement.h:26
unit_move_result
unit_move_result
Definition movement.h:34
MR_CANNOT_DISEMBARK
@ MR_CANNOT_DISEMBARK
Definition movement.h:48
MR_OK
@ MR_OK
Definition movement.h:35
MR_DESTINATION_OCCUPIED_BY_NON_ALLIED_UNIT
@ MR_DESTINATION_OCCUPIED_BY_NON_ALLIED_UNIT
Definition movement.h:45
MR_TRIREME
@ MR_TRIREME
Definition movement.h:47
MR_NON_NATIVE_MOVE
@ MR_NON_NATIVE_MOVE
Definition movement.h:49
MR_PEACE
@ MR_PEACE
Definition movement.h:39
MR_ZOC
@ MR_ZOC
Definition movement.h:40
MR_NO_WAR
@ MR_NO_WAR
Definition movement.h:38
name_translation_get
static const char * name_translation_get(const struct name_translation *ptrans)
Definition name_translation.h:121
nation_rule_name
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:138
nation_of_unit
struct nation_type * nation_of_unit(const struct unit *punit)
Definition nation.c:463
nation_adjective_for_player
const char * nation_adjective_for_player(const struct player *pplayer)
Definition nation.c:169
nation_adjective_translation
const char * nation_adjective_translation(const struct nation_type *pnation)
Definition nation.c:149
nation_of_player
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:444
nation_plural_for_player
const char * nation_plural_for_player(const struct player *pplayer)
Definition nation.c:178
notify_player
void notify_player(const struct player *pplayer, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Definition notify.c:292
notify.h
packets.h
REQEST_PLAYER_INITIATED
#define REQEST_PLAYER_INITIATED
Definition packets.h:63
UNIT_INFO_IDENTITY
@ UNIT_INFO_IDENTITY
Definition packets.h:67
dlsend_packet_nuke_tile_info
void dlsend_packet_nuke_tile_info(struct conn_list *dest, int tile)
Definition packets_gen.c:10724
lsend_packet_worker_task
void lsend_packet_worker_task(struct conn_list *dest, const struct packet_worker_task *packet)
Definition packets_gen.c:21632
dsend_packet_unit_actions
int dsend_packet_unit_actions(struct connection *pc, int actor_unit_id, int target_unit_id, int target_city_id, int target_tile_id, int target_extra_id, int request_kind, const struct act_prob *action_probabilities)
Definition packets_gen.c:33339
send_packet_unit_short_info
int send_packet_unit_short_info(struct connection *pc, const struct packet_unit_short_info *packet, bool force_to_send)
Definition packets_gen.c:30029
lsend_packet_unit_combat_info
void lsend_packet_unit_combat_info(struct conn_list *dest, const struct packet_unit_combat_info *packet)
Definition packets_gen.c:30371
dsend_packet_unit_action_answer
int dsend_packet_unit_action_answer(struct connection *pc, int actor_id, int target_id, int cost, action_id action_type, int request_kind)
Definition packets_gen.c:32497
send_packet_unit_info
int send_packet_unit_info(struct connection *pc, const struct packet_unit_info *packet)
Definition packets_gen.c:29318
send_packet_unit_combat_info
int send_packet_unit_combat_info(struct connection *pc, const struct packet_unit_combat_info *packet)
Definition packets_gen.c:30359
player_unit_by_number
struct unit * player_unit_by_number(const struct player *pplayer, int unit_id)
Definition player.c:1229
player_name
const char * player_name(const struct player *pplayer)
Definition player.c:895
can_player_see_unit
bool can_player_see_unit(const struct player *pplayer, const struct unit *punit)
Definition player.c:1104
player_city_by_number
struct city * player_city_by_number(const struct player *pplayer, int city_id)
Definition player.c:1203
player_primary_capital
struct city * player_primary_capital(const struct player *pplayer)
Definition player.c:1337
player_diplstate_get
struct player_diplstate * player_diplstate_get(const struct player *plr1, const struct player *plr2)
Definition player.c:324
pplayers_allied
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1405
pplayers_non_attack
bool pplayers_non_attack(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1459
can_player_see_units_in_city
bool can_player_see_units_in_city(const struct player *pplayer, const struct city *pcity)
Definition player.c:1133
player.h
players_iterate_end
#define players_iterate_end
Definition player.h:537
players_iterate
#define players_iterate(_pplayer)
Definition player.h:532
normal_player_count
int normal_player_count(void)
Definition plrhand.c:3200
civil_war_triggered
bool civil_war_triggered(struct player *pplayer)
Definition plrhand.c:2951
maybe_make_contact
void maybe_make_contact(struct tile *ptile, struct player *pplayer)
Definition plrhand.c:2357
send_player_info_c
void send_player_info_c(struct player *src, struct conn_list *dest)
Definition plrhand.c:1142
civil_war
struct player * civil_war(struct player *pplayer)
Definition plrhand.c:3001
player_reply_dest
struct conn_list * player_reply_dest(struct player *pplayer)
Definition plrhand.c:1589
civil_war_possible
bool civil_war_possible(struct player *pplayer, bool conquering_city, bool honour_server_option)
Definition plrhand.c:2904
plrhand.h
rand.h
fc_rand
#define fc_rand(_size)
Definition rand.h:56
universal_name_translation
const char * universal_name_translation(const struct universal *psource, char *buf, size_t bufsz)
Definition requirements.c:6755
requirement_fulfilled_by_unit_type
#define requirement_fulfilled_by_unit_type(_ut_, _rqs_)
Definition requirements.h:426
requirement_fulfilled_by_terrain
#define requirement_fulfilled_by_terrain(_ter_, _rqs_)
Definition requirements.h:419
requirement_fulfilled_by_nation
#define requirement_fulfilled_by_nation(_nat_, _rqs_)
Definition requirements.h:412
research_get
struct research * research_get(const struct player *pplayer)
Definition research.c:128
research.h
sanitycheck.h
sanity_check_city
#define sanity_check_city(x)
Definition sanitycheck.h:41
script_server_signal_emit
void script_server_signal_emit(const char *signal_name,...)
Definition script_server.c:408
script_server.h
shared.h
CLIP
#define CLIP(lower, current, upper)
Definition shared.h:57
ARRAY_SIZE
#define ARRAY_SIZE(x)
Definition shared.h:85
MIN
#define MIN(x, y)
Definition shared.h:55
MAX
#define MAX(x, y)
Definition shared.h:54
spaceship_lost
void spaceship_lost(struct player *pplayer)
Definition spacerace.c:431
spacerace.h
SSHIP_STARTED
@ SSHIP_STARTED
Definition spaceship.h:84
SSHIP_LAUNCHED
@ SSHIP_LAUNCHED
Definition spaceship.h:85
specialist.h
DEFAULT_SPECIALIST
#define DEFAULT_SPECIALIST
Definition specialist.h:43
size
size_t size
Definition specvec.h:72
srv_main.h
act_prob
Definition fc_types.h:1241
action
Definition actions.h:360
agent
Definition agents.h:40
ane_expl
Definition unithand.c:80
ane_expl::distance
int distance
Definition unithand.c:107
ane_expl::no_war_with
struct player * no_war_with
Definition unithand.c:92
ane_expl::blocker
struct action * blocker
Definition unithand.c:104
ane_expl::no_tgt_utype
const struct unit_type * no_tgt_utype
Definition unithand.c:101
ane_expl::no_act_terrain
struct terrain * no_act_terrain
Definition unithand.c:89
ane_expl::capacity_city
struct city * capacity_city
Definition unithand.c:86
ane_expl::peace_with
struct player * peace_with
Definition unithand.c:95
ane_expl::no_act_nation
struct nation_type * no_act_nation
Definition unithand.c:98
ane_expl::gold_needed
int gold_needed
Definition unithand.c:110
ane_expl::kind
enum ane_kind kind
Definition unithand.c:82
astring
Definition astring.h:36
base_type
Definition base.h:41
city
Definition city.h:320
city::task_reqs
struct worker_task_list * task_reqs
Definition city.h:412
city::id
int id
Definition city.h:326
city::owner
struct player * owner
Definition city.h:323
city::nationality
citizens * nationality
Definition city.h:341
city::specialists
citizens specialists[SP_MAX]
Definition city.h:336
city::tile
struct tile * tile
Definition city.h:322
civ_game::upgrade_veteran_loss
int upgrade_veteran_loss
Definition game.h:199
civ_game::control
struct packet_ruleset_control control
Definition game.h:83
civ_game::est_connections
struct conn_list * est_connections
Definition game.h:97
civ_game::info
struct packet_game_info info
Definition game.h:89
civ_game::scenario
struct packet_scenario_info scenario
Definition game.h:87
civ_game::occupychance
int occupychance
Definition game.h:170
civ_game::server
struct civ_game::@31::@35 server
civ_game::homecaughtunits
bool homecaughtunits
Definition game.h:188
civ_map
Definition map_types.h:71
connection
Definition connection.h:136
extra_type
Definition extras.h:88
goods_type
Definition traderoutes.h:183
impr_type
Definition improvement.h:50
message
Definition messagewin_common.h:29
nation_type
Definition nation.h:98
packet_game_info::goods_selection
enum goods_selection_method goods_selection
Definition packets_gen.h:160
packet_game_info::add_to_size_limit
int add_to_size_limit
Definition packets_gen.h:116
packet_game_info::reveal_trade_partner
bool reveal_trade_partner
Definition packets_gen.h:159
packet_game_info::phase
int phase
Definition packets_gen.h:206
packet_game_info::killcitizen
bool killcitizen
Definition packets_gen.h:187
packet_ruleset_control::num_extra_types
int num_extra_types
Definition packets_gen.h:1454
packet_scenario_info::prevent_new_cities
bool prevent_new_cities
Definition packets_gen.h:1610
packet_unit_combat_info
Definition packets_gen.h:690
packet_unit_combat_info::attacker_unit_id
int attacker_unit_id
Definition packets_gen.h:691
packet_unit_info
Definition packets_gen.h:632
packet_unit_orders
Definition packets_gen.h:705
packet_unit_orders::src_tile
int src_tile
Definition packets_gen.h:707
packet_unit_orders::length
int length
Definition packets_gen.h:708
packet_unit_orders::unit_id
int unit_id
Definition packets_gen.h:706
packet_unit_orders::dest_tile
int dest_tile
Definition packets_gen.h:712
packet_unit_orders::repeat
bool repeat
Definition packets_gen.h:709
packet_unit_orders::vigilant
bool vigilant
Definition packets_gen.h:710
packet_unit_orders::orders
struct unit_order orders[MAX_LEN_ROUTE]
Definition packets_gen.h:711
packet_unit_short_info
Definition packets_gen.h:673
packet_worker_task
Definition packets_gen.h:496
packet_worker_task::city_id
int city_id
Definition packets_gen.h:497
packet_worker_task::tile_id
int tile_id
Definition packets_gen.h:498
packet_worker_task::activity
enum unit_activity activity
Definition packets_gen.h:499
packet_worker_task::want
int want
Definition packets_gen.h:501
packet_worker_task::tgt
int tgt
Definition packets_gen.h:500
player_diplstate::type
enum diplstate_type type
Definition player.h:197
player_economic::gold
int gold
Definition player.h:61
player_score::units_lost
int units_lost
Definition player.h:104
player_tile
Definition maphand.h:30
player
Definition player.h:247
player::units
struct unit_list * units
Definition player.h:280
player::connections
struct conn_list * connections
Definition player.h:296
player::economic
struct player_economic economic
Definition player.h:282
player::score
struct player_score score
Definition player.h:281
req_context
Definition requirements.h:100
req_context::player
const struct player * player
Definition requirements.h:101
terrain
Definition terrain.h:182
tile
Definition tile.h:50
tile::units
struct unit_list * units
Definition tile.h:58
trade_route_settings::bonus_type
enum trade_route_bonus_type bonus_type
Definition traderoutes.h:78
trade_route
Definition traderoutes.h:83
trade_route::value
int value
Definition traderoutes.h:85
unit_adv::task
enum adv_unit_task task
Definition unit.h:89
unit_order
Definition unit.h:92
unit_order::activity
enum unit_activity activity
Definition unit.h:94
unit_order::order
enum unit_orders order
Definition unit.h:93
unit_order::action
int action
Definition unit.h:100
unit_order::dir
enum direction8 dir
Definition unit.h:102
unit_order::target
int target
Definition unit.h:97
unit_order::sub_target
int sub_target
Definition unit.h:98
unit_type
Definition unittype.h:500
unit_type::paratroopers_range
int paratroopers_range
Definition unittype.h:541
unit_type::city_size
int city_size
Definition unittype.h:550
unit_type::hp
int hp
Definition unittype.h:524
unit
Definition unit.h:138
unit::length
int length
Definition unit.h:195
unit::has_orders
bool has_orders
Definition unit.h:193
unit::orders
struct unit::@80 orders
unit::action_decision_want
enum action_decision action_decision_want
Definition unit.h:202
unit::battlegroup
int battlegroup
Definition unit.h:191
unit::activity
enum unit_activity activity
Definition unit.h:157
unit::moves_left
int moves_left
Definition unit.h:150
unit::id
int id
Definition unit.h:145
unit::moved
bool moved
Definition unit.h:173
unit::index
int index
Definition unit.h:195
unit::vision
struct vision * vision
Definition unit.h:244
unit::vigilant
bool vigilant
Definition unit.h:197
unit::hp
int hp
Definition unit.h:151
unit::facing
enum direction8 facing
Definition unit.h:142
unit::server
struct unit::@81::@84 server
unit::tile
struct tile * tile
Definition unit.h:140
unit::activity_target
struct extra_type * activity_target
Definition unit.h:164
unit::list
struct unit_order * list
Definition unit.h:198
unit::adv
struct unit_adv * adv
Definition unit.h:236
unit::repeat
bool repeat
Definition unit.h:196
unit::homecity
int homecity
Definition unit.h:146
unit::done_moving
bool done_moving
Definition unit.h:181
unit::carrying
struct goods_type * carrying
Definition unit.h:186
unit::goto_tile
struct tile * goto_tile
Definition unit.h:155
unit::action_decision_tile
struct tile * action_decision_tile
Definition unit.h:203
unit::utype
const struct unit_type * utype
Definition unit.h:139
unit::veteran
int veteran
Definition unit.h:152
unit::owner
struct player * owner
Definition unit.h:143
unit::ssa_controller
enum server_side_agent ssa_controller
Definition unit.h:172
veteran_level
Definition unittype.h:486
worker_task
Definition workertask.h:21
world::map
struct civ_map map
Definition world_object.h:38
fc_snprintf
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:974
sz_strlcpy
#define sz_strlcpy(dest, src)
Definition support.h:189
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
bool
#define bool
Definition support.h:71
fc__fallthrough
#define fc__fallthrough
Definition support.h:119
A_UNSET
#define A_UNSET
Definition tech.h:48
send_research_info
void send_research_info(const struct research *presearch, const struct conn_list *dest)
Definition techtools.c:293
update_bulbs
void update_bulbs(struct player *pplayer, int bulbs, bool check_tech, bool free_bulbs)
Definition techtools.c:654
techtools.h
terrain_name_translation
const char * terrain_name_translation(const struct terrain *pterrain)
Definition terrain.c:238
terrain_has_flag
#define terrain_has_flag(terr, flag)
Definition terrain.h:283
tile_is_seen
bool tile_is_seen(const struct tile *target_tile, const struct player *pow_player)
Definition tile.c:407
tile_city
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
tile_index
#define tile_index(_pt_)
Definition tile.h:88
tile_terrain
#define tile_terrain(_tile)
Definition tile.h:110
TILE_XY
#define TILE_XY(ptile)
Definition tile.h:43
tile_owner
#define tile_owner(_tile)
Definition tile.h:96
goods_from_city_to_unit
struct goods_type * goods_from_city_to_unit(struct city *src, struct unit *punit)
Definition traderoutes.c:723
can_cities_trade
bool can_cities_trade(const struct city *pc1, const struct city *pc2)
Definition traderoutes.c:214
cities_trade_route_type
enum trade_route_type cities_trade_route_type(const struct city *pcity1, const struct city *pcity2)
Definition traderoutes.c:58
trade_base_between_cities
int trade_base_between_cities(const struct city *pc1, const struct city *pc2)
Definition traderoutes.c:322
city_num_trade_routes
int city_num_trade_routes(const struct city *pcity)
Definition traderoutes.c:383
goods
static struct goods_type goods[MAX_GOODS_TYPES]
Definition traderoutes.c:43
goods_has_flag
bool goods_has_flag(const struct goods_type *pgood, enum goods_flag_id flag)
Definition traderoutes.c:668
trade_route_settings_by_type
struct trade_route_settings * trade_route_settings_by_type(enum trade_route_type type)
Definition traderoutes.c:201
max_trade_routes
unsigned max_trade_routes(const struct city *pcity)
Definition traderoutes.c:48
goods_name_translation
const char * goods_name_translation(struct goods_type *pgood)
Definition traderoutes.c:614
city_trade_removable
int city_trade_removable(const struct city *pcity, struct trade_route_list *would_remove)
Definition traderoutes.c:231
have_cities_trade_route
bool have_cities_trade_route(const struct city *pc1, const struct city *pc2)
Definition traderoutes.c:534
get_caravan_enter_city_trade_bonus
int get_caravan_enter_city_trade_bonus(const struct city *pc1, const struct city *pc2, const struct unit_type *ut, struct goods_type *pgood, const bool establish_trade)
Definition traderoutes.c:467
traderoutes.h
trade_route_list_iterate
#define trade_route_list_iterate(trade_route_list, proute)
Definition traderoutes.h:95
trade_route_list_iterate_end
#define trade_route_list_iterate_end
Definition traderoutes.h:97
create_unit_orders
struct unit_order * create_unit_orders(const struct civ_map *nmap, int length, const struct unit_order *orders)
Definition unit.c:2830
unit_shield_value
int unit_shield_value(const struct unit *punit, const struct unit_type *punittype, const struct action *paction)
Definition unit.c:217
get_transporter_occupancy
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1779
free_unit_orders
void free_unit_orders(struct unit *punit)
Definition unit.c:1765
unit_is_alive
bool unit_is_alive(int id)
Definition unit.c:2249
transporter_for_unit_at
struct unit * transporter_for_unit_at(const struct unit *pcargo, const struct tile *ptile)
Definition unit.c:1918
set_unit_activity
void set_unit_activity(struct unit *punit, enum unit_activity new_activity)
Definition unit.c:1085
unit_nationality
struct player * unit_nationality(const struct unit *punit)
Definition unit.c:1242
unit_transport_get
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2437
unit_transport_unload
bool unit_transport_unload(struct unit *pcargo)
Definition unit.c:2386
test_unit_can_airlift_to
enum unit_airlift_result test_unit_can_airlift_to(const struct civ_map *nmap, const struct player *restriction, const struct unit *punit, const struct city *pdest_city)
Definition unit.c:81
can_unit_continue_current_activity
bool can_unit_continue_current_activity(const struct civ_map *nmap, struct unit *punit)
Definition unit.c:838
unit_bribe_cost
int unit_bribe_cost(struct unit *punit, struct player *briber)
Definition unit.c:2300
can_unit_do_autosettlers
bool can_unit_do_autosettlers(const struct unit *punit)
Definition unit.c:602
unit_can_do_action
bool unit_can_do_action(const struct unit *punit, const action_id act_id)
Definition unit.c:361
set_unit_activity_targeted
void set_unit_activity_targeted(struct unit *punit, enum unit_activity new_activity, struct extra_type *new_target)
Definition unit.c:1102
can_unit_do_activity
bool can_unit_do_activity(const struct civ_map *nmap, const struct unit *punit, enum unit_activity activity)
Definition unit.c:865
unit_upgrade_test
enum unit_upgrade_result unit_upgrade_test(const struct civ_map *nmap, const struct unit *punit, bool is_free)
Definition unit.c:1984
unit_transported
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2421
unit_has_orders
bool unit_has_orders(const struct unit *punit)
Definition unit.c:205
activity_requires_target
bool activity_requires_target(enum unit_activity activity)
Definition unit.c:562
can_unit_do_activity_targeted
bool can_unit_do_activity_targeted(const struct civ_map *nmap, const struct unit *punit, enum unit_activity activity, struct extra_type *target)
Definition unit.c:904
unit.h
unit_tile
#define unit_tile(_pu)
Definition unit.h:390
ORDER_ACTIVITY
@ ORDER_ACTIVITY
Definition unit.h:41
ORDER_PERFORM_ACTION
@ ORDER_PERFORM_ACTION
Definition unit.h:47
unit_owner
#define unit_owner(_pu)
Definition unit.h:389
UU_NO_MONEY
@ UU_NO_MONEY
Definition unit.h:63
MAX_NUM_BATTLEGROUPS
#define MAX_NUM_BATTLEGROUPS
Definition unit.h:189
is_non_allied_unit_tile
static bool is_non_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:425
AR_SRC_NO_FLIGHTS
@ AR_SRC_NO_FLIGHTS
Definition unit.h:84
AR_DST_NO_FLIGHTS
@ AR_DST_NO_FLIGHTS
Definition unit.h:85
ACTION_PERFORM_UNIT_CITY
#define ACTION_PERFORM_UNIT_CITY(action, actor, target, action_performer)
rel_may_become_war
static bool rel_may_become_war(const struct player *pplayer, const struct player *oplayer)
Definition unithand.c:1013
do_unit_change_homecity
static bool do_unit_change_homecity(struct unit *punit, struct city *pcity, const struct action *paction)
Definition unithand.c:4116
do_unit_upgrade
static bool do_unit_upgrade(struct player *pplayer, struct unit *punit, struct city *pcity, enum action_requester ordered_by, const struct action *paction)
Definition unithand.c:255
handle_unit_do_action
void handle_unit_do_action(struct player *pplayer, const int actor_id, const int target_id, const int sub_tgt_id, const char *name, const action_id action_type)
Definition unithand.c:3275
do_attack
static bool do_attack(struct unit *actor_unit, struct tile *target_tile, const struct action *paction)
Definition unithand.c:4885
send_combat
static void send_combat(struct unit *pattacker, struct unit *pdefender, int att_veteran, int def_veteran, int bombard)
Definition unithand.c:4430
ACTION_PERFORM_UNIT_UNITS
#define ACTION_PERFORM_UNIT_UNITS(action, actor, target, action_performer)
do_unit_make_homeless
static bool do_unit_make_homeless(struct unit *punit, const struct action *paction)
Definition unithand.c:998
non_allied_not_listed_at
static bool non_allied_not_listed_at(const struct player *pplayer, const int *list, int n, const struct tile *ptile)
Definition unithand.c:285
handle_unit_orders
void handle_unit_orders(struct player *pplayer, const struct packet_unit_orders *packet)
Definition unithand.c:6599
illegal_action_msg
void illegal_action_msg(struct player *pplayer, const enum event_type event, struct unit *actor, const action_id stopped_action, const struct tile *target_tile, const struct city *target_city, const struct unit *target_unit)
Definition unithand.c:2492
do_heal_unit
static bool do_heal_unit(struct player *act_player, struct unit *act_unit, struct unit *tgt_unit, const struct action *paction)
Definition unithand.c:724
do_capture_units
static bool do_capture_units(struct player *pplayer, struct unit *punit, struct tile *pdesttile, const struct action *paction)
Definition unithand.c:314
do_expel_unit
static bool do_expel_unit(struct player *pplayer, struct unit *actor, struct unit *target, const struct action *paction)
Definition unithand.c:595
do_unit_conquer_city
static bool do_unit_conquer_city(struct player *act_player, struct unit *act_unit, struct city *tgt_city, struct action *paction)
Definition unithand.c:5384
does_nation_block_action
static bool does_nation_block_action(const action_id act_id, bool is_target, struct unit *actor_unit, struct nation_type *pnation)
Definition unithand.c:1387
ACTION_PERFORM_UNIT_UNIT
#define ACTION_PERFORM_UNIT_UNIT(action, actor, target, action_performer)
handle_unit_change_activity
void handle_unit_change_activity(struct player *pplayer, int unit_id, enum unit_activity activity, int target_id)
Definition unithand.c:4310
handle_worker_task
void handle_worker_task(struct player *pplayer, const struct packet_worker_task *packet)
Definition unithand.c:6708
unit_activity_handling
bool unit_activity_handling(struct unit *punit, enum unit_activity new_activity)
Definition unithand.c:6468
occupy_move
static bool occupy_move(struct tile *def_tile, struct unit *punit, const struct action *paction)
Definition unithand.c:498
do_unit_embark
static bool do_unit_embark(struct player *act_player, struct unit *act_unit, struct unit *tgt_unit, const struct action *paction)
Definition unithand.c:961
unit_perform_action
bool unit_perform_action(struct player *pplayer, const int actor_id, const int target_id, const int sub_tgt_id_incoming, const char *name, const action_id action_type, const enum action_requester requester)
Definition unithand.c:3311
ACTION_PERFORM_UNIT_TILE
#define ACTION_PERFORM_UNIT_TILE(action, actor, target, action_performer)
do_unit_strike_city_production
static bool do_unit_strike_city_production(struct player *act_player, struct unit *act_unit, struct city *tgt_city, const struct action *paction)
Definition unithand.c:5194
illegal_action_pay_price
static bool illegal_action_pay_price(struct player *pplayer, bool information_revealed, struct unit *act_unit, struct action *stopped_action, struct player *tgt_player, struct tile *tgt_tile, const enum action_requester requester)
Definition unithand.c:2968
explain_why_no_action_enabled
static void explain_why_no_action_enabled(struct unit *punit, const struct tile *target_tile, const struct city *target_city, const struct unit *target_unit)
Definition unithand.c:1933
unit_tired_attack_string
static const char * unit_tired_attack_string(const struct unit *punit)
Definition unithand.c:4838
do_unit_deboard
static bool do_unit_deboard(struct player *act_player, struct unit *act_unit, struct unit *tgt_unit, const struct action *paction)
Definition unithand.c:823
does_terrain_block_action
static bool does_terrain_block_action(const action_id act_id, bool is_target, struct unit *actor_unit, struct terrain *pterrain)
Definition unithand.c:1345
unit_activity_dependencies
static void unit_activity_dependencies(struct unit *punit, enum unit_activity old_activity, struct extra_type *old_target)
Definition unithand.c:6405
unit_query_impossible
static void unit_query_impossible(struct connection *pc, const int actor_id, const int target_id, int request_kind)
Definition unithand.c:3142
unit_bombard
static bool unit_bombard(struct unit *punit, struct tile *ptile, const struct action *paction)
Definition unithand.c:4525
unit_move_handling
bool unit_move_handling(struct unit *punit, struct tile *pdesttile, bool move_do_not_act)
Definition unithand.c:5531
unit_do_destroy_city
static bool unit_do_destroy_city(struct player *act_player, struct unit *act_unit, struct city *tgt_city, const struct action *paction)
Definition unithand.c:4712
handle_unit_change_activity_real
static void handle_unit_change_activity_real(struct player *pplayer, int unit_id, enum unit_activity activity, struct extra_type *activity_target)
Definition unithand.c:4261
ACTION_PERFORM_UNIT_SELF
#define ACTION_PERFORM_UNIT_SELF(action, actor, action_performer)
handle_unit_server_side_agent_set
void handle_unit_server_side_agent_set(struct player *pplayer, int unit_id, enum server_side_agent agent)
Definition unithand.c:6319
unit_do_action
void unit_do_action(struct player *pplayer, const int actor_id, const int target_id, const int sub_tgt_id, const char *name, const action_id action_type)
Definition unithand.c:3291
expl_act_not_enabl
static struct ane_expl * expl_act_not_enabl(struct unit *punit, const action_id act_id, const struct tile *target_tile, const struct city *target_city, const struct unit *target_unit)
Definition unithand.c:1429
do_action_activity
static bool do_action_activity(struct unit *punit, const struct action *paction)
Definition unithand.c:6454
do_unit_strike_city_building
static bool do_unit_strike_city_building(struct player *act_player, struct unit *act_unit, struct city *tgt_city, Impr_type_id tgt_bld_id, const struct action *paction)
Definition unithand.c:5281
need_war_enabler
static bool need_war_enabler(const struct unit_type *actor_utype, const struct action *paction, struct player *player1, struct player *player2, bool act_if_diplrel_kind(const struct unit_type *, const action_id, const int, const bool))
Definition unithand.c:1037
do_unit_unload
static bool do_unit_unload(struct player *act_player, struct unit *act_unit, struct unit *tgt_unit, const struct action *paction)
Definition unithand.c:886
unit_change_homecity_handling
void unit_change_homecity_handling(struct unit *punit, struct city *new_pcity, bool rehome)
Definition unithand.c:4014
unit_activity_targeted_internal
static bool unit_activity_targeted_internal(struct unit *punit, enum unit_activity new_activity, struct extra_type **new_target)
Definition unithand.c:6556
tile_has_units_not_allied_to_but_seen_by
static bool tile_has_units_not_allied_to_but_seen_by(const struct tile *ptile, const struct player *pplayer)
Definition unithand.c:1327
do_action_activity_targeted
static bool do_action_activity_targeted(struct unit *punit, const struct action *paction, struct extra_type **new_target)
Definition unithand.c:6519
need_war_player
static struct player * need_war_player(const struct unit *actor, const action_id act_id, const struct tile *target_tile, const struct city *target_city, const struct unit *target_unit)
Definition unithand.c:1291
unit_do_help_build
static bool unit_do_help_build(struct player *pplayer, struct unit *punit, struct city *pcity_dest, const struct action *paction)
Definition unithand.c:5724
handle_unit_type_upgrade
void handle_unit_type_upgrade(struct player *pplayer, Unit_type_id uti)
Definition unithand.c:185
city_add_unit
static bool city_add_unit(struct player *pplayer, struct unit *punit, struct city *pcity, const struct action *paction)
Definition unithand.c:4150
do_unit_load
static bool do_unit_load(struct player *act_player, struct unit *act_unit, struct unit *tgt_unit, const struct action *paction)
Definition unithand.c:865
unit_activity_internal
static bool unit_activity_internal(struct unit *punit, enum unit_activity new_activity)
Definition unithand.c:6496
handle_unit_action_query
void handle_unit_action_query(struct connection *pc, const int actor_id, const int target_id, const action_id action_type, int request_kind)
Definition unithand.c:3161
do_wipe_units
static bool do_wipe_units(struct unit *punit, struct tile *pdesttile, const struct action *paction)
Definition unithand.c:542
unit_activity_handling_targeted
bool unit_activity_handling_targeted(struct unit *punit, enum unit_activity new_activity, struct extra_type **new_target)
Definition unithand.c:6535
unit_nuke
static bool unit_nuke(struct player *pplayer, struct unit *punit, struct tile *def_tile, const struct action *paction)
Definition unithand.c:4642
can_unit_move_to_tile_with_notify
static bool can_unit_move_to_tile_with_notify(struct unit *punit, struct tile *dest_tile, bool igzoc, struct unit *embark_to, bool enter_enemy_city)
Definition unithand.c:5422
handle_unit_get_actions
void handle_unit_get_actions(struct connection *pc, const int actor_unit_id, const int target_unit_id_client, const int target_tile_id, const int target_extra_id_client, const int request_kind)
Definition unithand.c:2228
handle_unit_sscs_set
void handle_unit_sscs_set(struct player *pplayer, int unit_id, enum unit_ss_data_type type, int value)
Definition unithand.c:6212
do_unit_board
static bool do_unit_board(struct player *act_player, struct unit *act_unit, struct unit *tgt_unit, const struct action *paction)
Definition unithand.c:842
see_combat
static void see_combat(struct unit *pattacker, struct unit *pdefender)
Definition unithand.c:4371
ACTION_PERFORM_UNIT_ANY
#define ACTION_PERFORM_UNIT_ANY(paction, actor, target_city, target_unit, target_tile, action_performer)
need_war_player_hlp
static struct player * need_war_player_hlp(const struct unit *actor, const action_id act, const struct tile *target_tile, const struct city *target_city, const struct unit *target_unit)
Definition unithand.c:1078
unit_achieved_rank_string
static const char * unit_achieved_rank_string(const struct unit *punit)
Definition unithand.c:4821
unit_do_regular_move
static bool unit_do_regular_move(struct player *actor_player, struct unit *actor_unit, struct tile *target_tile, const struct action *paction)
Definition unithand.c:5493
do_conquer_extras
static bool do_conquer_extras(struct player *act_player, struct unit *act_unit, struct tile *tgt_tile, const struct action *paction)
Definition unithand.c:685
unit_server_side_agent_set
bool unit_server_side_agent_set(struct player *pplayer, struct unit *punit, enum server_side_agent agent)
Definition unithand.c:6368
do_unit_establish_trade
static bool do_unit_establish_trade(struct player *pplayer, struct unit *punit, struct city *pcity_dest, const struct action *paction)
Definition unithand.c:5839
do_disembark
static bool do_disembark(struct player *act_player, struct unit *act_unit, struct tile *tgt_tile, const struct action *paction)
Definition unithand.c:903
unit_plans_clear
static void unit_plans_clear(struct unit *punit)
Definition unithand.c:6303
city_build
static bool city_build(struct player *pplayer, struct unit *punit, struct tile *ptile, const char *name, const struct action *paction)
Definition unithand.c:4212
unit_attack_civilian_casualties
static void unit_attack_civilian_casualties(const struct unit *punit, struct city *pcity, const struct action *paction, const char *reason)
Definition unithand.c:4475
do_unit_hut
static bool do_unit_hut(struct player *act_player, struct unit *act_unit, struct tile *tgt_tile, const struct action *paction)
Definition unithand.c:931
action_not_enabled_reason
enum ane_kind action_not_enabled_reason(struct unit *punit, action_id act_id, const struct tile *target_tile, const struct city *target_city, const struct unit *target_unit)
Definition unithand.c:1913
ACTION_PERFORM_UNIT_EXTRAS
#define ACTION_PERFORM_UNIT_EXTRAS(action, actor, target, action_performer)
unit_firepower_if_not_one
static const char * unit_firepower_if_not_one(int firepower)
Definition unithand.c:4860
unit_veteran_level_string
static const char * unit_veteran_level_string(const struct unit *punit)
Definition unithand.c:4800
illegal_action
static void illegal_action(struct player *pplayer, struct unit *actor, action_id stopped_action, struct player *tgt_player, struct tile *target_tile, const struct city *target_city, const struct unit *target_unit, int request_kind, const enum action_requester requester)
Definition unithand.c:3085
unithand.h
unitlist.h
unit_list_iterate
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
unit_list_iterate_safe
#define unit_list_iterate_safe(unitlist, _unit)
Definition unitlist.h:39
unit_list_iterate_end
#define unit_list_iterate_end
Definition unitlist.h:33
unit_list_iterate_safe_end
#define unit_list_iterate_safe_end
Definition unitlist.h:61
unit_bombs_unit
void unit_bombs_unit(struct unit *attacker, struct unit *defender, int *att_hp, int *def_hp, const struct action *paction)
Definition unittools.c:355
unit_did_action
void unit_did_action(struct unit *punit)
Definition unittools.c:4899
collect_ransom
void collect_ransom(struct unit *pcollector, struct unit *punit, bool vet)
Definition unittools.c:2497
do_airline
bool do_airline(struct unit *punit, struct city *pdest_city, const struct action *paction)
Definition unittools.c:2914
execute_orders
bool execute_orders(struct unit *punit, const bool fresh)
Definition unittools.c:4352
transform_unit
void transform_unit(struct unit *punit, const struct unit_type *to_unit, int vet_loss)
Definition unittools.c:1549
unit_versus_unit
bool unit_versus_unit(struct unit *attacker, struct unit *defender, int *att_hp, int *def_hp, int *att_vet, int *def_vet, const struct action *paction)
Definition unittools.c:288
combat_veterans
void combat_veterans(struct unit *attacker, struct unit *defender, bool powerless, int att_vet, int def_vet)
Definition unittools.c:400
do_nuclear_explosion
void do_nuclear_explosion(const struct action *paction, const struct unit_type *act_utype, struct player *pplayer, struct tile *ptile)
Definition unittools.c:2882
package_unit
void package_unit(struct unit *punit, struct packet_unit_info *packet)
Definition unittools.c:2587
unit_goes_out_of_sight
void unit_goes_out_of_sight(struct player *pplayer, struct unit *punit)
Definition unittools.c:2712
send_unit_info
void send_unit_info(struct conn_list *dest, struct unit *punit)
Definition unittools.c:2725
notify_unit_experience
void notify_unit_experience(struct unit *punit)
Definition unittools.c:743
unit_activities_cancel
void unit_activities_cancel(struct unit *punit)
Definition unittools.c:800
package_short_unit
void package_short_unit(struct unit *punit, struct packet_unit_short_info *packet, enum unit_info_use packet_use, int info_city_id)
Definition unittools.c:2668
unit_forget_last_activity
void unit_forget_last_activity(struct unit *punit)
Definition unittools.c:1053
unit_refresh_vision
void unit_refresh_vision(struct unit *punit)
Definition unittools.c:4838
do_explore
void do_explore(struct unit *punit)
Definition unittools.c:2947
unit_transport_load_send
void unit_transport_load_send(struct unit *punit, struct unit *ptrans)
Definition unittools.c:3228
unit_can_do_action_now
bool unit_can_do_action_now(const struct unit *punit)
Definition unittools.c:4866
wipe_unit
void wipe_unit(struct unit *punit, enum unit_loss_reason reason, struct player *killer)
Definition unittools.c:2135
do_paradrop
bool do_paradrop(struct unit *punit, struct tile *ptile, const struct action *paction)
Definition unittools.c:2983
unit_transport_unload_send
void unit_transport_unload_send(struct unit *punit)
Definition unittools.c:3280
unit_change_owner
struct unit * unit_change_owner(struct unit *punit, struct player *pplayer, int homecity, enum unit_loss_reason reason)
Definition unittools.c:2195
teleport_unit_to_city
bool teleport_unit_to_city(struct unit *punit, struct city *pcity, int move_cost, bool verbose)
Definition unittools.c:1187
unit_assign_specific_activity_target
void unit_assign_specific_activity_target(struct unit *punit, enum unit_activity *activity, struct extra_type **target)
Definition unittools.c:1082
unit_get_goods
void unit_get_goods(struct unit *punit)
Definition unittools.c:1612
unit_move
bool unit_move(struct unit *punit, struct tile *pdesttile, int move_cost, struct unit *embark_to, bool find_embark_target, bool conquer_city_allowed, bool conquer_extras_allowed, bool enter_hut, bool frighten_hut)
Definition unittools.c:3916
kill_unit
void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
Definition unittools.c:2262
bounce_unit
void bounce_unit(struct unit *punit, bool verbose)
Definition unittools.c:1225
unit_activity_needs_target_from_client
bool unit_activity_needs_target_from_client(enum unit_activity activity)
Definition unittools.c:1062
unittools.h
utype_may_act_tgt_city_tile
bool utype_may_act_tgt_city_tile(const struct unit_type *punit_type, const action_id act_id, const enum citytile_type prop, const bool is_there)
Definition unittype.c:1124
uclass_name_translation
const char * uclass_name_translation(const struct unit_class *pclass)
Definition unittype.c:1632
unit_type_get
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
unit_name_translation
const char * unit_name_translation(const struct unit *punit)
Definition unittype.c:1569
utype_is_moved_to_tgt_by_action
bool utype_is_moved_to_tgt_by_action(const struct action *paction, const struct unit_type *utype)
Definition unittype.c:1249
unit_rule_name
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1587
utype_player_already_has_this_unique
bool utype_player_already_has_this_unique(const struct player *pplayer, const struct unit_type *putype)
Definition unittype.c:1927
can_upgrade_unittype
const struct unit_type * can_upgrade_unittype(const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1703
utype_count
Unit_type_id utype_count(void)
Definition unittype.c:80
utype_can_do_act_when_ustate
bool utype_can_do_act_when_ustate(const struct unit_type *punit_type, const action_id act_id, const enum ustate_prop prop, const bool is_there)
Definition unittype.c:955
unit_class_get
struct unit_class * unit_class_get(const struct unit *punit)
Definition unittype.c:2498
utype_by_number
struct unit_type * utype_by_number(const Unit_type_id id)
Definition unittype.c:112
utype_veteran_level
const struct veteran_level * utype_veteran_level(const struct unit_type *punittype, int level)
Definition unittype.c:2583
utype_is_consumed_by_action
bool utype_is_consumed_by_action(const struct action *paction, const struct unit_type *utype)
Definition unittype.c:1219
utype_can_act_if_tgt_diplrel_tile_other
bool utype_can_act_if_tgt_diplrel_tile_other(const struct unit_type *punit_type, const action_id act_id, const int prop, const bool is_there)
Definition unittype.c:1036
utype_index
Unit_type_id utype_index(const struct unit_type *punittype)
Definition unittype.c:91
unit_pop_value
int unit_pop_value(const struct unit *punit)
Definition unittype.c:1543
utype_name_translation
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1560
can_utype_do_act_if_tgt_diplrel
bool can_utype_do_act_if_tgt_diplrel(const struct unit_type *punit_type, const action_id act_id, const int prop, const bool is_there)
Definition unittype.c:1017
utype_can_do_action
bool utype_can_do_action(const struct unit_type *putype, const action_id act_id)
Definition unittype.c:371
role_units_translations
bool role_units_translations(struct astring *astr, int flag, bool alts)
Definition unittype.c:1668
unit_upgrade_price
int unit_upgrade_price(const struct player *pplayer, const struct unit_type *from, const struct unit_type *to)
Definition unittype.c:1731
uclass_has_flag
static bool uclass_has_flag(const struct unit_class *punitclass, enum unit_class_flag_id flag)
Definition unittype.h:766
utype_has_flag
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:617
unit_type_iterate
#define unit_type_iterate(_p)
Definition unittype.h:852
unit_type_iterate_end
#define unit_type_iterate_end
Definition unittype.h:859
vision_new
struct vision * vision_new(struct player *pplayer, struct tile *ptile)
Definition vision.c:33
vision_free
void vision_free(struct vision *vision)
Definition vision.c:50
worker_task_is_sane
bool worker_task_is_sane(struct worker_task *ptask)
Definition workertask.c:40
worker_task_init
void worker_task_init(struct worker_task *ptask)
Definition workertask.c:31
worker_task_list_iterate
#define worker_task_list_iterate(tasklist, ptask)
Definition workertask.h:33
worker_task_list_iterate_end
#define worker_task_list_iterate_end
Definition workertask.h:35