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