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(nmap, 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(nmap, 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(nmap, 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(nmap, 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(nmap, 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 const struct civ_map *nmap = &(wld.map);
2949
2950 struct action *stopped_action = action_by_number(stopped_action_id);
2951
2952 /* Why didn't the game check before trying something illegal? Did a good
2953 * reason to not call is_action_enabled_unit_on...() appear? The game is
2954 * omniscient... */
2955 fc_assert(requester != ACT_REQ_RULES);
2956
2957
2958 information_revealed = action_prob_possible(action_prob_unit_vs_tgt(
2959 nmap,
2960 stopped_action,
2961 actor,
2963 target_tile, NULL));
2964
2965 if (request_kind == REQEST_PLAYER_INITIATED) {
2966 /* This is a foreground request. */
2967 illegal_action_msg(pplayer, (information_revealed
2968 ? E_UNIT_ILLEGAL_ACTION : E_BAD_COMMAND),
2969 actor, stopped_action_id,
2971 }
2972
2973 was_punished = illegal_action_pay_price(pplayer, information_revealed,
2974 actor, stopped_action,
2975 tgt_player, target_tile,
2976 requester);
2977
2978 if (request_kind != REQEST_PLAYER_INITIATED && was_punished) {
2979 /* FIXME: Temporary work around to prevent wrong information and/or
2980 * crashes. See hrm Bug #879880 */
2981 /* TODO: Get the explanation before the punishment and show it here.
2982 * See hrm Bug #879881 */
2983 notify_player(pplayer, unit_tile(actor),
2984 (information_revealed
2985 ? E_UNIT_ILLEGAL_ACTION : E_BAD_COMMAND), ftc_server,
2986 _("No explanation why you couldn't do %s. This is a bug."
2987 " Sorry about that. -- Sveinung"),
2988 action_id_name_translation(stopped_action_id));
2989 }
2990}
2991
2992/**********************************************************************/
2995static void unit_query_impossible(struct connection *pc,
2996 const int actor_id,
2997 const int target_id,
2998 int request_kind)
2999{
3001 actor_id, actor_id,
3002 target_id,
3003 0,
3005 request_kind);
3006}
3007
3008/**********************************************************************/
3016 int actor_id16,
3017 int actor_id32,
3018 const int target_id,
3019 const action_id action_type,
3020 int request_kind)
3021{
3022 struct player *pplayer = pc->playing;
3023 struct unit *pactor;
3024 struct action *paction = action_by_number(action_type);
3025 struct unit *punit = game_unit_by_number(target_id);
3026 struct city *pcity = game_city_by_number(target_id);
3027 const struct civ_map *nmap = &(wld.map);
3028
3029 if (!has_capability("ids32", pc->capability)) {
3030 actor_id32 = actor_id16;
3031 }
3032
3033 pactor = player_unit_by_number(pplayer, actor_id32);
3034
3035 if (NULL == paction) {
3036 /* Non existing action */
3037 log_error("handle_unit_action_query() the action %d doesn't exist.",
3038 action_type);
3039
3040 unit_query_impossible(pc, actor_id32, target_id, request_kind);
3041 return;
3042 }
3043
3044 if (NULL == pactor) {
3045 /* Probably died or bribed. */
3046 log_verbose("handle_unit_action_query() invalid actor %d",
3047 actor_id32);
3048 unit_query_impossible(pc, actor_id32, target_id, request_kind);
3049 return;
3050 }
3051
3052 switch (paction->result) {
3053 case ACTRES_SPY_BRIBE_UNIT:
3054 if (punit
3055 && is_action_enabled_unit_on_unit(nmap, action_type,
3056 pactor, punit)) {
3058 actor_id32, actor_id32, target_id,
3059 unit_bribe_cost(punit, pplayer),
3060 action_type, request_kind);
3061 } else {
3062 illegal_action(pplayer, pactor, action_type,
3063 punit ? unit_owner(punit) : NULL,
3064 NULL, NULL, punit, request_kind, ACT_REQ_PLAYER);
3065 unit_query_impossible(pc, actor_id32, target_id, request_kind);
3066 return;
3067 }
3068 break;
3069 case ACTRES_SPY_INCITE_CITY:
3070 if (pcity
3071 && is_action_enabled_unit_on_city(nmap, action_type,
3072 pactor, pcity)) {
3074 actor_id32, actor_id32, target_id,
3075 city_incite_cost(pplayer, pcity),
3076 action_type, request_kind);
3077 } else {
3078 illegal_action(pplayer, pactor, action_type,
3079 pcity ? city_owner(pcity) : NULL,
3080 NULL, pcity, NULL, request_kind, ACT_REQ_PLAYER);
3081 unit_query_impossible(pc, actor_id32, target_id, request_kind);
3082 return;
3083 }
3084 break;
3085 case ACTRES_UPGRADE_UNIT:
3086 if (pcity
3087 && is_action_enabled_unit_on_city(nmap, action_type,
3088 pactor, pcity)) {
3089 const struct unit_type *tgt_utype;
3090 int upgr_cost;
3091
3092 tgt_utype = can_upgrade_unittype(pplayer, unit_type_get(pactor));
3093 /* Already checked via is_action_enabled_unit_on_city() */
3094 fc_assert_ret(tgt_utype);
3095 upgr_cost = unit_upgrade_price(pplayer,
3096 unit_type_get(pactor), tgt_utype);
3097
3099 actor_id32, actor_id32, target_id,
3100 upgr_cost, action_type,
3101 request_kind);
3102 } else {
3103 illegal_action(pplayer, pactor, action_type,
3104 pcity ? city_owner(pcity) : NULL,
3105 NULL, pcity, NULL, request_kind, ACT_REQ_PLAYER);
3106 unit_query_impossible(pc, actor_id32, target_id, request_kind);
3107 return;
3108 }
3109 break;
3110 case ACTRES_SPY_TARGETED_SABOTAGE_CITY:
3111 case ACTRES_STRIKE_BUILDING:
3112 if (pcity
3113 && is_action_enabled_unit_on_city(nmap, action_type,
3114 pactor, pcity)) {
3115 spy_send_sabotage_list(pc, pactor, pcity,
3116 action_by_number(action_type), request_kind);
3117 } else {
3118 illegal_action(pplayer, pactor, action_type,
3119 pcity ? city_owner(pcity) : NULL,
3120 NULL, pcity, NULL, request_kind, ACT_REQ_PLAYER);
3121 unit_query_impossible(pc, actor_id32, target_id, request_kind);
3122 return;
3123 }
3124 break;
3125 default:
3126 unit_query_impossible(pc, actor_id32, target_id, request_kind);
3127 return;
3128 };
3129}
3130
3131/**********************************************************************/
3136void handle_unit_do_action(struct player *pplayer,
3137 const struct packet_unit_do_action *packet)
3138{
3139 if (!has_capability("ids32", pplayer->current_conn->capability)) {
3140 (void) unit_perform_action(pplayer, packet->actor_id16, packet->target_id,
3141 packet->sub_tgt_id, packet->name,
3142 packet->action_type, ACT_REQ_PLAYER);
3143 } else {
3144 (void) unit_perform_action(pplayer, packet->actor_id32, packet->target_id,
3145 packet->sub_tgt_id, packet->name,
3146 packet->action_type, ACT_REQ_PLAYER);
3147 }
3148}
3149
3150/**********************************************************************/
3155void unit_do_action(struct player *pplayer,
3156 const int actor_id,
3157 const int target_id,
3158 const int sub_tgt_id,
3159 const char *name,
3160 const action_id action_type)
3161{
3162 unit_perform_action(pplayer, actor_id, target_id,
3163 sub_tgt_id, name, action_type, ACT_REQ_PLAYER);
3164}
3165
3166/**********************************************************************/
3175bool unit_perform_action(struct player *pplayer,
3176 const int actor_id,
3177 const int target_id,
3178 const int sub_tgt_id_incoming,
3179 const char *name,
3180 const action_id action_type,
3181 const enum action_requester requester)
3182{
3183 struct action *paction;
3184 int sub_tgt_id;
3185 struct unit *actor_unit = player_unit_by_number(pplayer, actor_id);
3186 struct tile *target_tile = NULL;
3187 struct extra_type *target_extra;
3188 struct impr_type *sub_tgt_impr;
3189 struct unit *punit = NULL;
3190 struct city *pcity = NULL;
3191 const struct civ_map *nmap = &(wld.map);
3192
3193 if (!action_id_exists(action_type)) {
3194 /* Non existing action */
3195 log_error("unit_perform_action() the action %d doesn't exist.",
3196 action_type);
3197
3198 return FALSE;
3199 }
3200
3201 paction = action_by_number(action_type);
3202
3203 if (NULL == actor_unit) {
3204 /* Probably died or bribed. */
3205 log_verbose("unit_perform_action() invalid actor %d",
3206 actor_id);
3207 return FALSE;
3208 }
3209
3210 switch (action_get_target_kind(paction)) {
3211 case ATK_CITY:
3212 pcity = game_city_by_number(target_id);
3213 if (pcity == NULL) {
3214 log_verbose("unit_perform_action() invalid target city %d",
3215 target_id);
3216 return FALSE;
3217 }
3218 target_tile = city_tile(pcity);
3220 break;
3221 case ATK_UNIT:
3222 punit = game_unit_by_number(target_id);
3223 if (punit == NULL) {
3224 log_verbose("unit_perform_action() invalid target unit %d",
3225 target_id);
3226 return FALSE;
3227 }
3230 pcity = tile_city(target_tile);
3231 break;
3232 case ATK_UNITS:
3233 case ATK_TILE:
3234 case ATK_EXTRAS:
3235 target_tile = index_to_tile(nmap, target_id);
3236 if (target_tile == NULL) {
3237 log_verbose("unit_perform_action() invalid target tile %d",
3238 target_id);
3239 return FALSE;
3240 }
3241 pcity = tile_city(target_tile);
3242 break;
3243 case ATK_SELF:
3246 pcity = tile_city(target_tile);
3247 break;
3248 case ATK_COUNT:
3249 fc_assert_ret_val(action_get_target_kind(paction) != ATK_COUNT, FALSE);
3250 break;
3251 }
3252
3253 /* Server side sub target assignment */
3254 if (paction->target_complexity == ACT_TGT_COMPL_FLEXIBLE
3255 && sub_tgt_id_incoming == NO_TARGET) {
3256 sub_tgt_id = action_sub_target_id_for_action(paction, actor_unit);
3257 } else {
3258 sub_tgt_id = sub_tgt_id_incoming;
3259 }
3260
3261 if (sub_tgt_id >= 0 && sub_tgt_id < MAX_EXTRA_TYPES
3262 && sub_tgt_id != NO_TARGET) {
3263 target_extra = extra_by_number(sub_tgt_id);
3264 fc_assert(!(target_extra->ruledit_disabled));
3265 } else {
3266 target_extra = NULL;
3267 }
3268
3269 sub_tgt_impr = improvement_by_number(sub_tgt_id);
3270
3271 /* Sub targets should now be assigned */
3272 switch (paction->sub_target_kind) {
3273 case ASTK_NONE:
3274 /* No sub target. */
3275 break;
3276 case ASTK_BUILDING:
3277 if (sub_tgt_impr == NULL) {
3278 /* Missing sub target */
3279 return FALSE;
3280 }
3281 break;
3282 case ASTK_TECH:
3283 /* Not handled here yet */
3284 break;
3285 case ASTK_EXTRA:
3286 case ASTK_EXTRA_NOT_THERE:
3287 if (target_extra == NULL) {
3288 /* Missing sub target */
3289 return FALSE;
3290 }
3291 break;
3292 case ASTK_COUNT:
3293 break;
3294 }
3295
3296 if (actres_get_activity(paction->result) != ACTIVITY_LAST
3298 actres_get_activity(paction->result))
3299 && target_extra == NULL) {
3300 /* Missing required action extra target. */
3301 log_verbose("unit_perform_action() action %d requires action "
3302 "but extra id %d is invalid.",
3303 action_type, sub_tgt_id);
3304 return FALSE;
3305 }
3306
3309 /* Action not possible due to unitwaittime setting. */
3310 return FALSE;
3311 }
3312
3313#define ACTION_PERFORM_UNIT_CITY(action, actor, target, action_performer) \
3314 if (pcity \
3315 && is_action_enabled_unit_on_city(nmap, action_type, \
3316 actor_unit, pcity)) { \
3317 bool success; \
3318 script_server_signal_emit("action_started_unit_city", \
3319 action_by_number(action), actor, target); \
3320 if (!actor || !unit_is_alive(actor_id)) { \
3321 /* Actor unit was destroyed during pre action Lua. */ \
3322 return FALSE; \
3323 } \
3324 if (!target || !city_exist(target_id)) { \
3325 /* Target city was destroyed during pre action Lua. */ \
3326 return FALSE; \
3327 } \
3328 success = action_performer; \
3329 if (success) { \
3330 action_success_actor_price(paction, actor_id, actor); \
3331 } \
3332 script_server_signal_emit("action_finished_unit_city", \
3333 action_by_number(action), success, \
3334 unit_is_alive(actor_id) ? actor : NULL, \
3335 city_exist(target_id) ? target : NULL); \
3336 return success; \
3337 } else { \
3338 illegal_action(pplayer, actor_unit, action_type, \
3339 pcity ? city_owner(pcity) : NULL, NULL, pcity, NULL, \
3340 TRUE, requester); \
3341 }
3342
3343#define ACTION_PERFORM_UNIT_SELF(action, actor, action_performer) \
3344 if (actor_unit \
3345 && is_action_enabled_unit_on_self(nmap, action_type, actor_unit)) { \
3346 bool success; \
3347 script_server_signal_emit("action_started_unit_self", \
3348 action_by_number(action), actor); \
3349 if (!actor || !unit_is_alive(actor_id)) { \
3350 /* Actor unit was destroyed during pre action Lua. */ \
3351 return FALSE; \
3352 } \
3353 success = action_performer; \
3354 if (success) { \
3355 action_success_actor_price(paction, actor_id, actor); \
3356 } \
3357 script_server_signal_emit("action_finished_unit_self", \
3358 action_by_number(action), success, \
3359 unit_is_alive(actor_id) ? actor : NULL); \
3360 return success; \
3361 } else { \
3362 illegal_action(pplayer, actor_unit, action_type, \
3363 unit_owner(actor_unit), NULL, NULL, actor_unit, \
3364 TRUE, requester); \
3365 }
3366
3367#define ACTION_PERFORM_UNIT_UNIT(action, actor, target, action_performer) \
3368 if (punit \
3369 && is_action_enabled_unit_on_unit(nmap, action_type, actor_unit, punit)) { \
3370 bool success; \
3371 script_server_signal_emit("action_started_unit_unit", \
3372 action_by_number(action), actor, target); \
3373 if (!actor || !unit_is_alive(actor_id)) { \
3374 /* Actor unit was destroyed during pre action Lua. */ \
3375 return FALSE; \
3376 } \
3377 if (!target || !unit_is_alive(target_id)) { \
3378 /* Target unit was destroyed during pre action Lua. */ \
3379 return FALSE; \
3380 } \
3381 success = action_performer; \
3382 if (success) { \
3383 action_success_actor_price(paction, actor_id, actor); \
3384 action_success_target_pay_mp(paction, target_id, punit); \
3385 } \
3386 script_server_signal_emit("action_finished_unit_unit", \
3387 action_by_number(action), success, \
3388 unit_is_alive(actor_id) ? actor : NULL, \
3389 unit_is_alive(target_id) ? target : NULL); \
3390 return success; \
3391 } else { \
3392 illegal_action(pplayer, actor_unit, action_type, \
3393 punit ? unit_owner(punit) : NULL, NULL, NULL, punit, \
3394 TRUE, requester); \
3395 }
3396
3397#define ACTION_PERFORM_UNIT_UNITS(action, actor, target, action_performer)\
3398 if (target_tile \
3399 && is_action_enabled_unit_on_units(nmap, action_type, \
3400 actor_unit, target_tile)) { \
3401 bool success; \
3402 script_server_signal_emit("action_started_unit_units", \
3403 action_by_number(action), actor, target); \
3404 if (!actor || !unit_is_alive(actor_id)) { \
3405 /* Actor unit was destroyed during pre action Lua. */ \
3406 return FALSE; \
3407 } \
3408 success = action_performer; \
3409 if (success) { \
3410 action_success_actor_price(paction, actor_id, actor); \
3411 } \
3412 script_server_signal_emit("action_finished_unit_units", \
3413 action_by_number(action), success, \
3414 unit_is_alive(actor_id) ? actor : NULL, \
3415 target); \
3416 return success; \
3417 } else { \
3418 illegal_action(pplayer, actor_unit, action_type, \
3419 NULL, target_tile, NULL, NULL, \
3420 TRUE, requester); \
3421 }
3422
3423#define ACTION_PERFORM_UNIT_TILE(action, actor, target, action_performer) \
3424 if (target_tile \
3425 && is_action_enabled_unit_on_tile(nmap, action_type, \
3426 actor_unit, target_tile, \
3427 target_extra)) { \
3428 bool success; \
3429 script_server_signal_emit("action_started_unit_tile", \
3430 action_by_number(action), actor, target); \
3431 if (!actor || !unit_is_alive(actor_id)) { \
3432 /* Actor unit was destroyed during pre action Lua. */ \
3433 return FALSE; \
3434 } \
3435 success = action_performer; \
3436 if (success) { \
3437 action_success_actor_price(paction, actor_id, actor); \
3438 } \
3439 script_server_signal_emit("action_finished_unit_tile", \
3440 action_by_number(action), success, \
3441 unit_is_alive(actor_id) ? actor : NULL, \
3442 target); \
3443 return success; \
3444 } else { \
3445 illegal_action(pplayer, actor_unit, action_type, \
3446 target_tile ? tile_owner(target_tile) : NULL, \
3447 target_tile, NULL, NULL, \
3448 TRUE, requester); \
3449 }
3450
3451#define ACTION_PERFORM_UNIT_EXTRAS(action, actor, target, action_performer)\
3452 if (target_tile \
3453 && is_action_enabled_unit_on_extras(nmap, action_type, \
3454 actor_unit, target_tile, \
3455 target_extra)) { \
3456 bool success; \
3457 script_server_signal_emit("action_started_unit_extras", \
3458 action_by_number(action), actor, target); \
3459 if (!actor || !unit_is_alive(actor_id)) { \
3460 /* Actor unit was destroyed during pre action Lua. */ \
3461 return FALSE; \
3462 } \
3463 success = action_performer; \
3464 if (success) { \
3465 action_success_actor_price(paction, actor_id, actor); \
3466 } \
3467 script_server_signal_emit("action_finished_unit_extras", \
3468 action_by_number(action), success, \
3469 unit_is_alive(actor_id) ? actor : NULL, \
3470 target); \
3471 return success; \
3472 } else { \
3473 illegal_action(pplayer, actor_unit, action_type, \
3474 target_tile ? target_tile->extras_owner : NULL, \
3475 target_tile, NULL, NULL, \
3476 TRUE, requester); \
3477 }
3478
3479#define ACTION_PERFORM_UNIT_ANY(paction, actor, \
3480 target_city, target_unit, target_tile, \
3481 action_performer) \
3482 switch (action_get_target_kind(paction)) { \
3483 case ATK_CITY: \
3484 ACTION_PERFORM_UNIT_CITY(paction->id, actor, target_city, \
3485 action_performer); \
3486 break; \
3487 case ATK_UNIT: \
3488 ACTION_PERFORM_UNIT_UNIT(paction->id, actor, target_unit, \
3489 action_performer); \
3490 break; \
3491 case ATK_UNITS: \
3492 ACTION_PERFORM_UNIT_UNITS(paction->id, actor, target_tile, \
3493 action_performer); \
3494 break; \
3495 case ATK_TILE: \
3496 ACTION_PERFORM_UNIT_TILE(paction->id, actor, target_tile, \
3497 action_performer); \
3498 break; \
3499 case ATK_EXTRAS: \
3500 ACTION_PERFORM_UNIT_EXTRAS(paction->id, actor, target_tile, \
3501 action_performer); \
3502 break; \
3503 case ATK_SELF: \
3504 ACTION_PERFORM_UNIT_SELF(paction->id, actor, TRUE); \
3505 break; \
3506 case ATK_COUNT: \
3507 fc_assert(action_get_target_kind(paction) != ATK_COUNT); \
3508 break; \
3509 }
3510
3511 switch (paction->result) {
3512 case ACTRES_SPY_BRIBE_UNIT:
3515 paction));
3516 break;
3517 case ACTRES_SPY_SABOTAGE_UNIT:
3518 /* Difference is caused by data in the action structure. */
3521 punit, paction));
3522 break;
3523 case ACTRES_EXPEL_UNIT:
3525 do_expel_unit(pplayer, actor_unit, punit,
3526 paction));
3527 break;
3528 case ACTRES_HEAL_UNIT:
3530 do_heal_unit(pplayer, actor_unit, punit,
3531 paction));
3532 break;
3533 case ACTRES_TRANSPORT_ALIGHT:
3536 paction));
3537 break;
3538 case ACTRES_TRANSPORT_UNLOAD:
3541 paction));
3542 break;
3543 case ACTRES_TRANSPORT_BOARD:
3545 do_unit_board(pplayer, actor_unit, punit,
3546 paction));
3547 break;
3548 case ACTRES_TRANSPORT_EMBARK:
3551 paction));
3552 break;
3553 case ACTRES_DISBAND_UNIT:
3554 /* All consequences are handled by the action system. */
3556 break;
3557 case ACTRES_FORTIFY:
3559 do_action_activity(actor_unit, paction));
3560 break;
3561 case ACTRES_CONVERT:
3563 do_action_activity(actor_unit, paction));
3564 break;
3565 case ACTRES_HOMELESS:
3568 break;
3569 case ACTRES_SPY_SABOTAGE_CITY:
3570 /* Difference is caused by data in the action structure. */
3571 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3572 diplomat_sabotage(pplayer, actor_unit, pcity,
3573 B_LAST, paction));
3574 break;
3575 case ACTRES_SPY_TARGETED_SABOTAGE_CITY:
3576 /* Difference is caused by data in the action structure. */
3577 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3578 diplomat_sabotage(pplayer, actor_unit, pcity,
3579 sub_tgt_impr->item_number,
3580 paction));
3581 break;
3582 case ACTRES_SPY_SABOTAGE_CITY_PRODUCTION:
3583 /* Difference is caused by data in the action structure. */
3584 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3585 diplomat_sabotage(pplayer, actor_unit, pcity,
3586 -1, paction));
3587 break;
3588 case ACTRES_SPY_POISON:
3589 /* Difference is caused by data in the action structure. */
3590 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3591 spy_poison(pplayer, actor_unit, pcity,
3592 paction));
3593 break;
3594 case ACTRES_SPY_SPREAD_PLAGUE:
3595 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3596 spy_spread_plague(pplayer, actor_unit, pcity,
3597 paction));
3598 break;
3599 case ACTRES_SPY_INVESTIGATE_CITY:
3600 /* Difference is caused by data in the action structure. */
3601 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3602 diplomat_investigate(pplayer,
3603 actor_unit, pcity,
3604 paction));
3605 break;
3606 case ACTRES_ESTABLISH_EMBASSY:
3607 /* Difference is caused by data in the action structure. */
3608 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3609 diplomat_embassy(pplayer, actor_unit, pcity,
3610 paction));
3611 break;
3612 case ACTRES_SPY_INCITE_CITY:
3613 /* Difference is caused by data in the action structure. */
3614 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3615 diplomat_incite(pplayer, actor_unit, pcity,
3616 paction));
3617 break;
3618 case ACTRES_SPY_STEAL_TECH:
3619 /* Difference is caused by data in the action structure. */
3620 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3621 diplomat_get_tech(pplayer, actor_unit, pcity,
3622 A_UNSET, paction));
3623 break;
3624 case ACTRES_SPY_TARGETED_STEAL_TECH:
3625 /* Difference is caused by data in the action structure. */
3626 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3627 diplomat_get_tech(pplayer, actor_unit, pcity,
3628 sub_tgt_id, paction));
3629 break;
3630 case ACTRES_SPY_STEAL_GOLD:
3631 /* Difference is caused by data in the action structure. */
3632 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3633 spy_steal_gold(pplayer, actor_unit, pcity,
3634 paction));
3635 break;
3636 case ACTRES_STEAL_MAPS:
3637 /* Difference is caused by data in the action structure. */
3638 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3640 pcity, paction));
3641 break;
3642 case ACTRES_TRADE_ROUTE:
3643 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3645 pcity, paction));
3646 break;
3647 case ACTRES_MARKETPLACE:
3648 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3650 pcity, paction));
3651 break;
3652 case ACTRES_HELP_WONDER:
3653 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3654 unit_do_help_build(pplayer,
3655 actor_unit, pcity,
3656 paction));
3657 break;
3658 case ACTRES_SPY_NUKE:
3659 /* Difference is caused by data in the action structure. */
3660 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3661 spy_nuke_city(pplayer, actor_unit, pcity,
3662 paction));
3663 break;
3664 case ACTRES_JOIN_CITY:
3665 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3666 city_add_unit(pplayer, actor_unit, pcity,
3667 paction));
3668 break;
3669 case ACTRES_DESTROY_CITY:
3670 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3671 unit_do_destroy_city(pplayer,
3672 actor_unit, pcity,
3673 paction));
3674 break;
3675 case ACTRES_DISBAND_UNIT_RECOVER:
3676 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3677 unit_do_help_build(pplayer, actor_unit, pcity,
3678 paction));
3679 break;
3680 case ACTRES_HOME_CITY:
3681 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3683 paction));
3684 break;
3685 case ACTRES_UPGRADE_UNIT:
3686 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3687 do_unit_upgrade(pplayer, actor_unit,
3688 pcity, requester, paction));
3689 break;
3690 case ACTRES_CONQUER_CITY:
3691 /* Difference is caused by the ruleset. ("Fake generalized" actions) */
3692 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3694 pcity, paction));
3695 break;
3696 case ACTRES_STRIKE_BUILDING:
3697 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3699 actor_unit,
3700 pcity,
3701 sub_tgt_impr->item_number,
3702 paction));
3703 break;
3704 case ACTRES_STRIKE_PRODUCTION:
3705 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3707 actor_unit,
3708 pcity,
3709 paction));
3710 break;
3711 case ACTRES_CONQUER_EXTRAS:
3714 target_tile, paction));
3715 break;
3716 case ACTRES_AIRLIFT:
3717 ACTION_PERFORM_UNIT_CITY(action_type, actor_unit, pcity,
3718 do_airline(actor_unit, pcity, paction));
3719 break;
3720 case ACTRES_CAPTURE_UNITS:
3723 target_tile, paction));
3724 break;
3725 case ACTRES_BOMBARD:
3726 /* Difference is caused by the ruleset. ("Fake generalized" actions) */
3729 paction));
3730 break;
3731 case ACTRES_ATTACK:
3732 /* Difference is caused by data in the action structure. */
3734 do_attack(actor_unit, target_tile, paction));
3735 break;
3736 case ACTRES_NUKE_UNITS:
3739 paction));
3740 break;
3741 case ACTRES_SPY_ATTACK:
3744 paction));
3745 break;
3746 case ACTRES_FOUND_CITY:
3748 city_build(pplayer, actor_unit,
3749 target_tile, name, paction));
3750 break;
3751 case ACTRES_NUKE:
3753 pcity, punit, target_tile,
3755 paction));
3756 break;
3757 case ACTRES_PARADROP:
3758 case ACTRES_PARADROP_CONQUER:
3761 break;
3762 case ACTRES_TRANSPORT_DISEMBARK:
3763 /* Difference is caused by the ruleset. ("Fake generalized" actions) */
3765 do_disembark(pplayer, actor_unit,
3766 target_tile, paction));
3767 break;
3768 case ACTRES_HUT_ENTER:
3770 do_unit_hut(pplayer, actor_unit,
3771 target_tile, paction));
3772 break;
3773 case ACTRES_HUT_FRIGHTEN:
3775 do_unit_hut(pplayer, actor_unit,
3776 target_tile, paction));
3777 break;
3778 case ACTRES_UNIT_MOVE:
3781 target_tile, paction));
3782 break;
3783 case ACTRES_TRANSFORM_TERRAIN:
3785 do_action_activity(actor_unit, paction));
3786 break;
3787 case ACTRES_CULTIVATE:
3789 do_action_activity(actor_unit, paction));
3790 break;
3791 case ACTRES_PLANT:
3793 do_action_activity(actor_unit, paction));
3794 break;
3795 case ACTRES_PILLAGE:
3798 paction,
3799 &target_extra));
3800 break;
3801 case ACTRES_CLEAN_POLLUTION:
3804 paction,
3805 &target_extra));
3806 break;
3807 case ACTRES_CLEAN_FALLOUT:
3810 paction,
3811 &target_extra));
3812 break;
3813 case ACTRES_ROAD:
3816 paction,
3817 &target_extra));
3818 break;
3819 case ACTRES_BASE:
3822 paction,
3823 &target_extra));
3824 break;
3825 case ACTRES_MINE:
3828 paction,
3829 &target_extra));
3830 break;
3831 case ACTRES_IRRIGATE:
3834 paction,
3835 &target_extra));
3836 break;
3837 case ACTRES_NONE:
3838 /* 100% ruleset defined. */
3840 TRUE);
3841 break;
3842 }
3843
3844 /* Something must have gone wrong. */
3845 return FALSE;
3846}
3847
3848/**********************************************************************/
3855void unit_change_homecity_handling(struct unit *punit, struct city *new_pcity,
3856 bool rehome)
3857{
3858 struct city *old_pcity = game_city_by_number(punit->homecity);
3859 struct player *old_owner = unit_owner(punit);
3860 struct player *new_owner = (new_pcity == NULL ? old_owner
3861 : city_owner(new_pcity));
3862 const struct civ_map *nmap = &(wld.map);
3863
3864 /* Calling this function when new_pcity is same as old_pcity should
3865 * be safe with current implementation, but it is not meant to
3866 * be used that way. */
3867 fc_assert_ret(new_pcity != old_pcity);
3868
3869 /* If 'rehome' is not set, this function should only be used to change
3870 * which player owns the unit */
3871 fc_assert_ret(rehome || new_owner != old_owner);
3872
3873 if (old_owner != new_owner) {
3874 struct city *pcity = tile_city(punit->tile);
3875
3878
3881
3882 if (pcity != NULL
3883 && !can_player_see_units_in_city(old_owner, pcity)) {
3884 /* Special case when city is being transferred. At this point city
3885 * itself has changed owner, so it's enemy city now that old owner
3886 * cannot see inside. All the normal methods of removing transferred
3887 * unit from previous owner's client think that there's no need to
3888 * remove unit as client shouldn't have it in first place. */
3889 unit_goes_out_of_sight(old_owner, punit);
3890 }
3891
3892 /* Remove AI control of the old owner. */
3893 CALL_PLR_AI_FUNC(unit_lost, old_owner, punit);
3894
3895 unit_list_remove(old_owner->units, punit);
3896 unit_list_prepend(new_owner->units, punit);
3897 punit->owner = new_owner;
3898
3899 /* Activate AI control of the new owner. */
3900 CALL_PLR_AI_FUNC(unit_got, new_owner, punit);
3901
3902 punit->server.vision = vision_new(new_owner, unit_tile(punit));
3904 }
3905
3906 if (rehome) {
3907 /* Remove from old city first and add to new city only after that. */
3908 if (old_pcity) {
3909 /* Even if unit is dead, we have to unlink unit pointer (punit). */
3910 unit_list_remove(old_pcity->units_supported, punit);
3911 /* update unit upkeep */
3912 city_units_upkeep(old_pcity);
3913 }
3914
3915 if (new_pcity != NULL) {
3916 unit_list_prepend(new_pcity->units_supported, punit);
3917
3918 /* update unit upkeep */
3919 city_units_upkeep(new_pcity);
3920
3921 punit->homecity = new_pcity->id;
3922 } else {
3924 }
3925 }
3926
3928 /* This is mainly for cases where unit owner changes to one not knowing
3929 * Railroad tech when unit is already building railroad.
3930 * Does also send_unit_info() */
3932 } else {
3933 /* Send info to players and observers. */
3934 send_unit_info(NULL, punit);
3935 }
3936
3937 if (new_pcity != NULL) {
3938 city_refresh(new_pcity);
3939 send_city_info(new_owner, new_pcity);
3940 fc_assert(unit_owner(punit) == city_owner(new_pcity));
3941 }
3942
3943 if (old_pcity) {
3944 fc_assert(city_owner(old_pcity) == old_owner);
3945 city_refresh(old_pcity);
3946 send_city_info(old_owner, old_pcity);
3947 }
3948
3950}
3951
3952/**********************************************************************/
3958 struct city *pcity,
3959 const struct action *paction)
3960{
3961 const char *giver = NULL;
3962
3963 if (unit_owner(punit) != city_owner(pcity)) {
3964 /* This is a gift. Tell the receiver. */
3966 }
3967
3969
3970 if (punit->homecity == pcity->id && giver) {
3971 /* Notify the city owner about the gift they received. */
3972 notify_player(city_owner(pcity), city_tile(pcity), E_UNIT_BUILT,
3973 ftc_server,
3974 /* TRANS: other player ... unit type ... city name. */
3975 _("%s transferred control over a %s to you in %s."),
3976 giver,
3978 city_link(pcity));;
3979 }
3980
3981 return punit->homecity == pcity->id;
3982}
3983
3984/**********************************************************************/
3991static bool city_add_unit(struct player *pplayer, struct unit *punit,
3992 struct city *pcity, const struct action *paction)
3993{
3994 int amount = unit_pop_value(punit);
3995 const struct unit_type *act_utype;
3996
3997 /* Sanity check: The actor is still alive. */
3999
4000 act_utype = unit_type_get(punit);
4001
4002 /* Sanity check: The target city still exists. */
4003 fc_assert_ret_val(pcity, FALSE);
4004
4005 fc_assert_ret_val(amount > 0, FALSE);
4006
4007 city_size_add(pcity, amount);
4008 /* Make the new people something, otherwise city fails the checks */
4009 pcity->specialists[DEFAULT_SPECIALIST] += amount;
4011 /* Refresh the city data. */
4012 city_refresh(pcity);
4013
4014 /* Notify the unit owner that the unit successfully joined the city. */
4015 notify_player(pplayer, city_tile(pcity), E_CITY_BUILD, ftc_server,
4016 _("%s added to aid %s in growing."),
4018 city_link(pcity));
4019 if (pplayer != city_owner(pcity)) {
4020 /* Notify the city owner when a foreign unit joins a city. */
4021 notify_player(city_owner(pcity), city_tile(pcity), E_CITY_BUILD,
4022 ftc_server,
4023 /* TRANS: another player had their unit join your city. */
4024 _("%s adds %s to your city %s."),
4027 city_link(pcity));;
4028 }
4029
4030 action_consequence_success(paction, pplayer, act_utype,
4031 city_owner(pcity), city_tile(pcity),
4032 city_link(pcity));
4033
4034 sanity_check_city(pcity);
4035
4036 send_city_info(NULL, pcity);
4037
4038 script_server_signal_emit("city_size_change", pcity,
4039 (lua_Integer)amount, "unit_added");
4040
4041 return TRUE;
4042}
4043
4044/**********************************************************************/
4053static bool city_build(struct player *pplayer, struct unit *punit,
4054 struct tile *ptile, const char *name,
4055 const struct action *paction)
4056{
4057 char message[1024];
4058 int size;
4059 struct player *nationality;
4060 struct player *towner;
4061 const struct unit_type *act_utype;
4062
4063 /* Sanity check: The actor still exists. */
4064 fc_assert_ret_val(pplayer, FALSE);
4066
4067 act_utype = unit_type_get(punit);
4068 towner = tile_owner(ptile);
4069
4070 if (!is_allowed_city_name(pplayer, name, message, sizeof(message))) {
4071 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
4072 "%s", message);
4073 return FALSE;
4074 }
4075
4076 nationality = unit_nationality(punit);
4077
4078 create_city(pplayer, ptile, name, nationality);
4080 if (size > 1) {
4081 struct city *pcity = tile_city(ptile);
4082
4083 fc_assert_ret_val(pcity != NULL, FALSE);
4084
4085 city_change_size(pcity, size, nationality, NULL);
4086 }
4087
4088 /* May cause an incident even if the target tile is unclaimed. A ruleset
4089 * could give everyone a casus belli against the city founder. A rule
4090 * like that would make sense in a story where deep ecology is on the
4091 * table. (See also Voluntary Human Extinction Movement) */
4092 action_consequence_success(paction, pplayer, act_utype, towner,
4093 ptile, tile_link(ptile));
4094
4095 return TRUE;
4096}
4097
4098/**********************************************************************/
4101static void handle_unit_change_activity_real(struct player *pplayer,
4102 int unit_id,
4103 enum unit_activity activity,
4104 struct extra_type *activity_target)
4105{
4106 struct unit *punit = player_unit_by_number(pplayer, unit_id);
4107
4108 if (NULL == punit) {
4109 /* Probably died or bribed. */
4110 log_verbose("handle_unit_change_activity() invalid unit %d", unit_id);
4111 return;
4112 }
4113
4114 if (punit->activity == activity
4116 return;
4117 }
4118
4119 /* Remove city spot reservations for AI settlers on city founding
4120 * mission, before goto_tile reset. */
4121 if (punit->server.adv->task != AUT_NONE) {
4123 }
4124
4125 punit->goto_tile = NULL;
4126
4127 if (activity == ACTIVITY_GOTO) {
4128 /* Don't permit a client to set a unit's activity to ACTIVITY_GOTO.
4129 * Setting ACTIVITY_GOTO from the client results in a unit indicating
4130 * it is going somewhere while it is standing still. The appearance of
4131 * the unit doing something can trick the user to not make use of it.
4132 *
4133 * Handled here because adv_follow_path() uses unit_activity_handling()
4134 * to set a unit's activity to ACTIVITY_GOTO. */
4135 return;
4136 }
4137
4138 if (activity == ACTIVITY_EXPLORE) {
4139 /* Please use unit_server_side_agent_set. */
4140 return;
4141 }
4142
4143 /* The activity can now be set. */
4145}
4146
4147/**********************************************************************/
4151 int unit_id16, int unit_id32,
4152 enum unit_activity activity,
4153 int target_id)
4154{
4155 struct extra_type *activity_target;
4156 int unit_id;
4157
4158 if (!has_capability("ids32", pplayer->current_conn->capability)) {
4159 unit_id = unit_id16;
4160 } else {
4161 unit_id = unit_id32;
4162 }
4163
4164 if (target_id < 0 || target_id >= game.control.num_extra_types) {
4165 activity_target = NULL;
4166 } else {
4167 activity_target = extra_by_number(target_id);
4168 }
4169
4170#ifdef FREECIV_WEB
4171 /* Web-client is not capable of selecting target, so we do it server side */
4172 if (activity_target == NULL) {
4173 struct unit *punit = player_unit_by_number(pplayer, unit_id);
4174 bool required = TRUE;
4175
4176 if (punit == NULL) {
4177 return;
4178 }
4179
4180 if (activity == ACTIVITY_IRRIGATE) {
4181 struct tile *ptile = unit_tile(punit);
4182
4183 activity_target = next_extra_for_tile(ptile, EC_IRRIGATION,
4184 pplayer, punit);
4185 } else if (activity == ACTIVITY_MINE) {
4186 struct tile *ptile = unit_tile(punit);
4187
4188 activity_target = next_extra_for_tile(ptile, EC_MINE,
4189 pplayer, punit);
4190 } else if (activity == ACTIVITY_BASE) {
4191 struct tile *ptile = unit_tile(punit);
4192 struct base_type *pbase =
4193 get_base_by_gui_type(BASE_GUI_FORTRESS, punit, ptile);
4194
4195 if (pbase != NULL) {
4196 activity_target = base_extra_get(pbase);
4197 }
4198
4199 } else if (activity == ACTIVITY_POLLUTION) {
4200 activity_target = prev_extra_in_tile(unit_tile(punit), ERM_CLEANPOLLUTION,
4201 pplayer, punit);
4202 } else if (activity == ACTIVITY_FALLOUT) {
4203 activity_target = prev_extra_in_tile(unit_tile(punit), ERM_CLEANFALLOUT,
4204 pplayer, punit);
4205 } else {
4206 required = FALSE;
4207 }
4208
4209 if (activity_target == NULL && required) {
4210 /* Nothing more we can do */
4211 return;
4212 }
4213 }
4214#endif /* FREECIV_WEB */
4215
4216 handle_unit_change_activity_real(pplayer, unit_id, activity, activity_target);
4217}
4218
4219/**********************************************************************/
4222static void see_combat(struct unit *pattacker, struct unit *pdefender)
4223{
4224 struct packet_unit_short_info unit_att_short_packet, unit_def_short_packet;
4225 struct packet_unit_info unit_att_packet, unit_def_packet;
4226
4227 /*
4228 * Special case for attacking/defending:
4229 *
4230 * Normally the player doesn't get the information about the units inside a
4231 * city. However for attacking/defending the player has to know the unit of
4232 * the other side. After the combat a remove_unit packet will be sent
4233 * to the client to tidy up.
4234 *
4235 * Note these packets must be sent out before unit_versus_unit() is called,
4236 * so that the original unit stats (HP) will be sent.
4237 */
4238 package_short_unit(pattacker, &unit_att_short_packet,
4240 package_short_unit(pdefender, &unit_def_short_packet,
4242 package_unit(pattacker, &unit_att_packet);
4243 package_unit(pdefender, &unit_def_packet);
4244
4246 struct player *pplayer = pconn->playing;
4247
4248 if (pplayer != NULL) {
4249
4250 /* NOTE: this means the player can see combat between submarines even
4251 * if neither sub is visible. See similar comment in send_combat. */
4252 if (map_is_known_and_seen(unit_tile(pattacker), pplayer, V_MAIN)
4253 || map_is_known_and_seen(unit_tile(pdefender), pplayer,
4254 V_MAIN)) {
4255
4256 /* Units are sent even if they were visible already. They may
4257 * have changed orientation for combat. */
4258 if (pplayer == unit_owner(pattacker)) {
4259 send_packet_unit_info(pconn, &unit_att_packet);
4260 } else {
4261 send_packet_unit_short_info(pconn, &unit_att_short_packet, FALSE);
4262 }
4263
4264 if (pplayer == unit_owner(pdefender)) {
4265 send_packet_unit_info(pconn, &unit_def_packet);
4266 } else {
4267 send_packet_unit_short_info(pconn, &unit_def_short_packet, FALSE);
4268 }
4269 }
4270 } else if (pconn->observer) {
4271 /* Global observer sees everything... */
4272 send_packet_unit_info(pconn, &unit_att_packet);
4273 send_packet_unit_info(pconn, &unit_def_packet);
4274 }
4276}
4277
4278/**********************************************************************/
4281static void send_combat(struct unit *pattacker, struct unit *pdefender,
4282 int att_veteran, int def_veteran, int bombard)
4283{
4284 struct packet_unit_combat_info combat;
4285
4286 combat.attacker_unit_id32 = pattacker->id;
4287 combat.attacker_unit_id16 = combat.attacker_unit_id32;
4288 combat.defender_unit_id32 = pdefender->id;
4289 combat.defender_unit_id16 = combat.defender_unit_id32;
4290 combat.attacker_hp = pattacker->hp;
4291 combat.defender_hp = pdefender->hp;
4292 combat.make_att_veteran = att_veteran;
4293 combat.make_def_veteran = def_veteran;
4294
4295 players_iterate(other_player) {
4296 /* NOTE: this means the player can see combat between submarines even
4297 * if neither sub is visible. See similar comment in see_combat. */
4298 if (map_is_known_and_seen(unit_tile(pattacker), other_player, V_MAIN)
4299 || map_is_known_and_seen(unit_tile(pdefender), other_player,
4300 V_MAIN)) {
4301 lsend_packet_unit_combat_info(other_player->connections, &combat);
4302
4303 /*
4304 * Remove the client knowledge of the units. This corresponds to the
4305 * send_packet_unit_short_info calls up above.
4306 */
4307 if (!can_player_see_unit(other_player, pattacker)) {
4308 unit_goes_out_of_sight(other_player, pattacker);
4309 }
4310 if (!can_player_see_unit(other_player, pdefender)) {
4311 unit_goes_out_of_sight(other_player, pdefender);
4312 }
4313 }
4315
4316 /* Send combat info to non-player observers as well. They already know
4317 * about the unit so no unit_info is needed. */
4319 if (NULL == pconn->playing && pconn->observer) {
4320 send_packet_unit_combat_info(pconn, &combat);
4321 }
4323}
4324
4325/**********************************************************************/
4332static bool unit_bombard(struct unit *punit, struct tile *ptile,
4333 const struct action *paction)
4334{
4335 struct player *pplayer = unit_owner(punit);
4336 struct city *pcity = tile_city(ptile);
4337 const struct unit_type *act_utype;
4338 const struct civ_map *nmap = &(wld.map);
4339
4340 /* Sanity check: The actor still exists. */
4341 fc_assert_ret_val(pplayer, FALSE);
4343
4344 act_utype = unit_type_get(punit);
4345
4346 log_debug("Start bombard: %s %s to %d, %d.",
4348 unit_rule_name(punit), TILE_XY(ptile));
4349
4350 unit_list_iterate_safe(ptile->units, pdefender) {
4351 if (is_unit_reachable_at(pdefender, punit, ptile)) {
4352 bool adj;
4353 enum direction8 facing;
4354 int att_hp, def_hp;
4355
4356 adj = base_get_direction_for_step(nmap,
4357 punit->tile, pdefender->tile, &facing);
4358
4359 if (adj) {
4360 punit->facing = facing;
4361
4362 /* Unlike with normal attack, we don't change orientation of
4363 * defenders when bombarding */
4364 }
4365
4366 unit_bombs_unit(punit, pdefender, &att_hp, &def_hp);
4367
4368 notify_player(pplayer, ptile,
4369 E_UNIT_WIN_ATT, ftc_server,
4370 /* TRANS: Your Bomber bombards the English Rifleman.*/
4371 _("Your %s bombards the %s %s."),
4374 unit_name_translation(pdefender));
4375
4376 notify_player(unit_owner(pdefender), ptile,
4377 E_UNIT_WIN_DEF, ftc_server,
4378 /* TRANS: Your Rifleman is bombarded by the French Bomber.*/
4379 _("Your %s is bombarded by the %s %s."),
4380 unit_name_translation(pdefender),
4383
4384 see_combat(punit, pdefender);
4385
4386 punit->hp = att_hp;
4387 pdefender->hp = def_hp;
4388
4389 send_combat(punit, pdefender, 0, 0, 1);
4390
4391 send_unit_info(NULL, pdefender);
4392
4393 /* May cause an incident */
4395 unit_owner(punit), act_utype,
4396 unit_owner(pdefender),
4397 unit_tile(pdefender),
4398 unit_link(pdefender));
4399 }
4400
4402
4405
4406 if (pcity
4407 && city_size_get(pcity) > 1
4408 && get_city_bonus(pcity, EFT_UNIT_NO_LOSE_POP) <= 0
4410 city_reduce_size(pcity, 1, pplayer, "bombard");
4411 city_refresh(pcity);
4412 send_city_info(NULL, pcity);
4413 }
4414
4415 send_unit_info(NULL, punit);
4416
4417 return TRUE;
4418}
4419
4420/**********************************************************************/
4431static bool unit_nuke(struct player *pplayer, struct unit *punit,
4432 struct tile *def_tile, const struct action *paction)
4433{
4434 struct city *pcity;
4435 const struct unit_type *act_utype;
4436 struct civ_map *nmap = &(wld.map);
4437
4438 /* Sanity check: The actor still exists. */
4439 fc_assert_ret_val(pplayer, FALSE);
4441
4442 act_utype = unit_type_get(punit);
4443
4444 log_debug("Start nuclear attack: %s %s against (%d, %d).",
4447 TILE_XY(def_tile));
4448
4449 if ((pcity = sdi_try_defend(nmap, pplayer, def_tile))) {
4450 /* FIXME: Remove the hard coded reference to SDI defense. */
4451 notify_player(pplayer, unit_tile(punit), E_UNIT_LOST_ATT, ftc_server,
4452 _("Your %s was shot down by "
4453 "SDI defenses, what a waste."), unit_tile_link(punit));
4454 notify_player(city_owner(pcity), def_tile, E_UNIT_WIN_DEF, ftc_server,
4455 _("The nuclear attack on %s was avoided by"
4456 " your SDI defense."), city_link(pcity));
4457
4458 /* Trying to nuke something this close can be... unpopular. */
4459 action_consequence_caught(paction, pplayer, act_utype,
4460 city_owner(pcity),
4461 def_tile, unit_tile_link(punit));
4462
4463 /* Remove the destroyed nuke. */
4464 wipe_unit(punit, ULR_SDI, city_owner(pcity));
4465
4466 return FALSE;
4467 }
4468
4470
4471
4472 /* The nuke must be wiped here so it won't be seen as a victim of its own
4473 * detonation. */
4474 if (paction->actor_consuming_always) {
4475 wipe_unit(punit, ULR_DETONATED, NULL);
4476 }
4477
4478 do_nuclear_explosion(pplayer, def_tile);
4479
4480 /* May cause an incident even if the target tile is unclaimed. A ruleset
4481 * could give everyone a casus belli against the tile nuker. A rule
4482 * like that would make sense in a story where detonating any nuke at all
4483 * could be forbidden. */
4484 action_consequence_success(paction, pplayer, act_utype,
4485 tile_owner(def_tile),
4486 def_tile,
4487 tile_link(def_tile));
4488
4489 return TRUE;
4490}
4491
4492/**********************************************************************/
4501static bool unit_do_destroy_city(struct player *act_player,
4502 struct unit *act_unit,
4503 struct city *tgt_city,
4504 const struct action *paction)
4505{
4506 int tgt_city_id;
4507 struct player *tgt_player;
4508 bool capital;
4509 bool try_civil_war = FALSE;
4510 const struct unit_type *act_utype;
4511
4512 /* Sanity check: The actor still exists. */
4513 fc_assert_ret_val(act_player, FALSE);
4514 fc_assert_ret_val(act_unit, FALSE);
4515
4516 act_utype = unit_type_get(act_unit);
4517
4518 /* Sanity check: The target city still exists. */
4519 fc_assert_ret_val(tgt_city, FALSE);
4520
4521 tgt_player = city_owner(tgt_city);
4522
4523 /* How can a city be ownerless? */
4524 fc_assert_ret_val(tgt_player, FALSE);
4525
4526 /* Save city ID. */
4527 tgt_city_id = tgt_city->id;
4528
4529 capital = (player_primary_capital(tgt_player) == tgt_city);
4530
4531 if (capital
4532 && (tgt_player->spaceship.state == SSHIP_STARTED
4533 || tgt_player->spaceship.state == SSHIP_LAUNCHED)) {
4534 /* Destroying this city destroys the victim's space ship. */
4535 spaceship_lost(tgt_player);
4536 }
4537
4538 if (capital
4539 && civil_war_possible(tgt_player, TRUE, TRUE)
4541 && civil_war_triggered(tgt_player)) {
4542 /* Destroying this city can trigger a civil war. */
4543 try_civil_war = TRUE;
4544 }
4545
4546 /* Let the actor know. */
4547 notify_player(act_player, city_tile(tgt_city),
4548 E_UNIT_WIN_ATT, ftc_server,
4549 _("You destroy %s completely."),
4550 city_tile_link(tgt_city));
4551
4552 if (tgt_player != act_player) {
4553 /* This was done to a foreign city. Inform the victim player. */
4554 notify_player(tgt_player, city_tile(tgt_city),
4555 E_CITY_LOST, ftc_server,
4556 _("%s has been destroyed by %s."),
4557 city_tile_link(tgt_city),
4558 player_name(act_player));
4559 }
4560
4561 /* May cause an incident */
4562 action_consequence_success(paction, act_player, act_utype,
4563 tgt_player, city_tile(tgt_city),
4564 city_link(tgt_city));
4565
4566 /* Run post city destruction Lua script. */
4567 script_server_signal_emit("city_destroyed", tgt_city, tgt_player,
4568 act_player);
4569
4570 /* Can't be sure of city existence after running script. */
4571 if (city_exist(tgt_city_id)) {
4572 remove_city(tgt_city);
4573 }
4574
4575 if (try_civil_war) {
4576 /* Try to start the civil war. */
4577 (void) civil_war(tgt_player);
4578 }
4579
4580 /* The city is no more. */
4581 return TRUE;
4582}
4583
4584/**********************************************************************/
4593static bool do_attack(struct unit *punit, struct tile *def_tile,
4594 const struct action *paction)
4595{
4596 char loser_link[MAX_LEN_LINK], winner_link[MAX_LEN_LINK];
4597 char attacker_vet[MAX_LEN_LINK], defender_vet[MAX_LEN_LINK];
4598 char attacker_fp[MAX_LEN_LINK], defender_fp[MAX_LEN_LINK];
4599 char attacker_tired[MAX_LEN_LINK];
4600 struct unit *ploser, *pwinner;
4601 struct city *pcity;
4602 int moves_used, def_moves_used;
4603 int old_unit_vet, old_defender_vet, vet;
4604 int winner_id;
4605 struct player *pplayer = unit_owner(punit);
4606 bool adj;
4607 enum direction8 facing;
4608 int att_hp, def_hp, att_fp, def_fp;
4609 int att_hp_start, def_hp_start;
4610 int def_power, att_power;
4611 int att_vet, def_vet;
4612 struct unit *pdefender;
4613 const struct unit_type *act_utype = unit_type_get(punit);
4614 struct civ_map *nmap = &(wld.map);
4615 bool powerless;
4616
4617 if (!(pdefender = get_defender(nmap, punit, def_tile))) {
4618 /* Can't fight air... */
4619 return FALSE;
4620 }
4621
4622 att_hp_start = punit->hp;
4623 def_hp_start = pdefender->hp;
4624 def_power = get_total_defense_power(punit, pdefender);
4625 att_power = get_total_attack_power(punit, pdefender);
4626 get_modified_firepower(nmap, punit, pdefender, &att_fp, &def_fp);
4627
4628 log_debug("Start attack: %s %s against %s %s.",
4631 nation_rule_name(nation_of_unit(pdefender)),
4632 unit_rule_name(pdefender));
4633
4634 /* Sanity checks */
4636 unit_owner(pdefender)),
4637 FALSE,
4638 "Trying to attack a unit with which you have peace "
4639 "or cease-fire at (%d, %d).", TILE_XY(def_tile));
4640 fc_assert_ret_val_msg(!pplayers_allied(pplayer, unit_owner(pdefender)),
4641 FALSE,
4642 "Trying to attack a unit with which you have "
4643 "alliance at (%d, %d).", TILE_XY(def_tile));
4644
4645 moves_used = unit_move_rate(punit) - punit->moves_left;
4646 def_moves_used = unit_move_rate(pdefender) - pdefender->moves_left;
4647
4648 adj = base_get_direction_for_step(nmap,
4649 punit->tile, pdefender->tile, &facing);
4650
4651 fc_assert(adj);
4652 if (adj) {
4653 punit->facing = facing;
4654 pdefender->facing = opposite_direction(facing);
4655 }
4656
4657 old_unit_vet = punit->veteran;
4658 old_defender_vet = pdefender->veteran;
4659
4660 /* N.B.: unit_veteran_level_string always returns the same pointer. */
4662 sz_strlcpy(defender_vet, unit_veteran_level_string(pdefender));
4663
4664 /* N.B.: unit_firepower_if_not_one always returns the same pointer. */
4665 sz_strlcpy(attacker_fp, unit_firepower_if_not_one(att_fp));
4666 sz_strlcpy(defender_fp, unit_firepower_if_not_one(def_fp));
4667
4668 /* Record tired attack string before attack */
4669 sz_strlcpy(attacker_tired, unit_tired_attack_string(punit));
4670
4671 powerless = unit_versus_unit(punit, pdefender, &att_hp, &def_hp,
4672 &att_vet, &def_vet);
4673
4674 if ((att_hp <= 0 || utype_is_consumed_by_action(paction, punit->utype))
4675 && unit_transported(punit)) {
4676 /* Dying attacker must be first unloaded so it doesn't die inside transport */
4678 }
4679
4680 see_combat(punit, pdefender);
4681
4682 punit->hp = att_hp;
4683 pdefender->hp = def_hp;
4684
4685 combat_veterans(punit, pdefender, powerless, att_vet, def_vet);
4686
4687 /* Adjust attackers moves_left _after_ unit_versus_unit() so that
4688 * the movement attack modifier is correct! --dwp
4689 *
4690 * For greater Civ2 compatibility (and game balance issues), we recompute
4691 * the new total MP based on the HP the unit has left after being damaged,
4692 * and subtract the MPs that had been used before the combat (plus the
4693 * points used in the attack itself, for the attacker). -GJW, Glip
4694 */
4695 punit->moves_left = unit_move_rate(punit) - moves_used;
4696 pdefender->moves_left = unit_move_rate(pdefender) - def_moves_used;
4697
4698 if (punit->moves_left < 0) {
4699 punit->moves_left = 0;
4700 }
4701 if (pdefender->moves_left < 0) {
4702 pdefender->moves_left = 0;
4703 }
4706
4707 /* This may cause a diplomatic incident. */
4708 action_consequence_success(paction, pplayer, act_utype,
4709 unit_owner(pdefender),
4710 def_tile, unit_link(pdefender));
4711
4712 if (pdefender->hp <= 0
4713 && (pcity = tile_city(def_tile))
4714 && city_size_get(pcity) > 1
4715 && get_city_bonus(pcity, EFT_UNIT_NO_LOSE_POP) <= 0
4717 city_reduce_size(pcity, 1, pplayer, "attack");
4718 city_refresh(pcity);
4719 send_city_info(NULL, pcity);
4720 }
4721 if (punit->hp > 0 && pdefender->hp > 0) {
4722 /* Neither died */
4723 send_combat(punit, pdefender, punit->veteran - old_unit_vet,
4724 pdefender->veteran - old_defender_vet, 0);
4725 return TRUE;
4726 }
4727 pwinner = (punit->hp > 0) ? punit : pdefender;
4728 winner_id = pwinner->id;
4729 ploser = (pdefender->hp > 0) ? punit : pdefender;
4730
4731 vet = (pwinner->veteran == ((punit->hp > 0) ? old_unit_vet :
4732 old_defender_vet)) ? 0 : 1;
4733
4734 send_combat(punit, pdefender, punit->veteran - old_unit_vet,
4735 pdefender->veteran - old_defender_vet, 0);
4736
4737 /* N.B.: unit_link always returns the same pointer. */
4738 sz_strlcpy(loser_link, unit_tile_link(ploser));
4739 sz_strlcpy(winner_link,
4740 utype_is_consumed_by_action(paction, pwinner->utype)
4741 ? unit_tile_link(pwinner) : unit_link(pwinner));
4742
4743 if (punit == ploser) {
4744 /* The attacker lost */
4745 log_debug("Attacker lost: %s %s against %s %s.",
4748 nation_rule_name(nation_of_unit(pdefender)),
4749 unit_rule_name(pdefender));
4750
4751 notify_player(unit_owner(pwinner), unit_tile(pwinner),
4752 E_UNIT_WIN_DEF, ftc_server,
4753 /* TRANS: "Your green Legion [id:100 ...D:4.0 lost 1 HP,
4754 * 9 HP remaining] survived the pathetic ...attack from the
4755 * Greek green Warriors [id:90 ...A:1.0 HP:10]. */
4756 _("Your %s %s [id:%d %sD:%.1f lost %d HP, %d HP remaining]"
4757 " survived the pathetic %sattack from the %s %s %s "
4758 "[id:%d %sA:%.1f HP:%d]."),
4759 defender_vet,
4760 winner_link,
4761 pdefender->id,
4762 defender_fp,
4763 (float)def_power/POWER_FACTOR,
4764 def_hp_start - pdefender->hp,
4765 pdefender->hp,
4766 attacker_tired,
4768 attacker_vet,
4769 loser_link,
4770 punit->id,
4771 attacker_fp,
4772 (float)att_power/POWER_FACTOR,
4773 att_hp_start);
4774
4775 if (vet) {
4776 notify_unit_experience(pwinner);
4777 }
4778 notify_player(unit_owner(ploser), def_tile,
4779 E_UNIT_LOST_ATT, ftc_server,
4780 /* TRANS: "Your attacking green Cannon [id:100 ...A:8.0
4781 * failed against the Polish green Destroyer [id:200 lost
4782 * 27 HP, 3 HP remaining%s]!";
4783 * last %s is either "and ..." or empty string */
4784 _("Your attacking %s %s [id:%d %sA:%.1f HP:%d] failed "
4785 "against the %s %s %s [id:%d lost %d HP, %d HP "
4786 "remaining%s]!"),
4787 attacker_vet,
4788 loser_link,
4789 punit->id,
4790 attacker_fp,
4791 (float)att_power/POWER_FACTOR,
4792 att_hp_start,
4794 defender_vet,
4795 winner_link,
4796 pdefender->id,
4797 def_hp_start - pdefender->hp,
4798 pdefender->hp,
4799 vet ? unit_achieved_rank_string(pdefender) : "");
4800
4801 wipe_unit(ploser, ULR_KILLED, unit_owner(pwinner));
4802 } else {
4803 /* The defender lost, the attacker punit lives! */
4804
4805 log_debug("Defender lost: %s %s against %s %s.",
4808 nation_rule_name(nation_of_unit(pdefender)),
4809 unit_rule_name(pdefender));
4810
4811 notify_player(unit_owner(pdefender), unit_tile(pdefender),
4812 E_UNIT_LOST_DEF, ftc_server,
4813 /* TRANS: "Your green Warriors [id:100 ...D:1.0 HP:10]
4814 * lost to an attack by the Greek green Legion
4815 * [id:200 ...A:4.0 lost 1 HP, has 9 HP remaining%s]."
4816 * last %s is either "and ..." or empty string */
4817 _("Your %s %s [id:%d %sD:%.1f HP:%d] lost to an attack by "
4818 "the %s %s %s [id:%d %sA:%.1f lost %d HP, has %d HP "
4819 "remaining%s]."),
4820 defender_vet,
4821 loser_link,
4822 pdefender->id,
4823 defender_fp,
4824 (float)def_power/POWER_FACTOR,
4825 def_hp_start,
4827 attacker_vet,
4828 winner_link,
4829 punit->id,
4830 attacker_fp,
4831 (float)att_power/POWER_FACTOR,
4832 att_hp_start - pwinner->hp,
4833 pwinner->hp,
4834 vet ? unit_achieved_rank_string(punit) : "");
4835
4837 E_UNIT_WIN_ATT, ftc_server,
4838 /* TRANS: "Your attacking green Legion [id:200 ...A:4.0
4839 * lost 1 HP, has 9 HP remaining] succeeded against the
4840 * Greek green Warriors [id:100 HP:10]." */
4841 _("Your attacking %s %s [id:%d %s%sA:%.1f lost %d HP, "
4842 "has %d remaining] succeeded against the %s %s %s "
4843 "[id:%d HP:%d]."),
4844 attacker_vet,
4845 winner_link,
4846 punit->id,
4847 attacker_fp,
4848 attacker_tired,
4849 (float)att_power/POWER_FACTOR,
4850 att_hp_start - pwinner->hp,
4851 pwinner->hp,
4853 defender_vet,
4854 loser_link,
4855 pdefender->id,
4856 def_hp_start);
4857
4858 punit->moved = TRUE; /* We moved */
4859 kill_unit(pwinner, ploser,
4860 vet && !utype_is_consumed_by_action(paction, punit->utype));
4861 if (unit_is_alive(winner_id)) {
4862 if (utype_is_consumed_by_action(paction, pwinner->utype)) {
4863 return TRUE;
4864 }
4865 } else {
4866 return TRUE;
4867 }
4868 }
4869
4870 /* If attacker wins, and occupychance > 0, it might move in. Don't move in
4871 * if there are enemy units in the tile (a fortress, city or air base with
4872 * multiple defenders and unstacked combat). Note that this could mean
4873 * capturing (or destroying) a city. */
4874
4875 if (pwinner == punit && fc_rand(100) < game.server.occupychance
4876 && !is_non_allied_unit_tile(def_tile, pplayer)) {
4877
4878 /* Hack: make sure the unit has enough moves_left for the move to succeed,
4879 and adjust moves_left to afterward (if successful). */
4880
4881 int old_moves = punit->moves_left;
4882 int full_moves = unit_move_rate(punit);
4883 int id = punit->id;
4884
4885 punit->moves_left = full_moves;
4886 /* Post attack occupy move. */
4887 if (NULL != action_auto_perf_unit_do(AAPC_POST_ACTION, punit,
4888 NULL, NULL, paction,
4889 def_tile, tile_city(def_tile),
4890 NULL, NULL)) {
4891 if (unit_is_alive(id)) {
4892 int mcost = MAX(0, full_moves - punit->moves_left - SINGLE_MOVE);
4893
4894 /* Move cost is bigger of attack (SINGLE_MOVE) and occupying move costs.
4895 * Attack SINGLE_COST is already calculated in to old_moves. */
4896 punit->moves_left = old_moves - mcost;
4897 if (punit->moves_left < 0) {
4898 punit->moves_left = 0;
4899 }
4900 }
4901 } else if (unit_is_alive(id)) {
4902 punit->moves_left = old_moves;
4903 }
4904 }
4905
4906 /* The attacker may have died for many reasons */
4907 if (game_unit_by_number(winner_id) != NULL) {
4908 send_unit_info(NULL, pwinner);
4909 }
4910
4911 return TRUE;
4912}
4913
4914/**********************************************************************/
4924static bool do_unit_strike_city_production(const struct player *act_player,
4925 struct unit *act_unit,
4926 struct city *tgt_city,
4927 const struct action *paction)
4928{
4929 struct player *tgt_player;
4930 char prod[256];
4931 const char *clink;
4932
4933 /* Sanity checks */
4934 fc_assert_ret_val(act_player, FALSE);
4935 fc_assert_ret_val(act_unit, FALSE);
4936 fc_assert_ret_val(tgt_city, FALSE);
4937 fc_assert_ret_val(paction, FALSE);
4938
4939 tgt_player = city_owner(tgt_city);
4940 fc_assert_ret_val(tgt_player, FALSE);
4941
4942 /* The surgical strike may miss. */
4943 {
4944 /* Roll the dice. */
4945 if (action_failed_dice_roll(act_player, act_unit,
4946 tgt_city, tgt_player,
4947 paction)) {
4948 /* Notify the player. */
4949 notify_player(act_player, city_tile(tgt_city),
4950 E_UNIT_ACTION_ACTOR_FAILURE, ftc_server,
4951 /* TRANS: unit, action, city */
4952 _("Your %s failed to do %s in %s."),
4953 unit_link(act_unit),
4954 action_name_translation(paction),
4955 city_link(tgt_city));
4956
4957 /* Make the failed attempt cost a single move. */
4958 act_unit->moves_left = MAX(0, act_unit->moves_left - SINGLE_MOVE);
4959
4960 return FALSE;
4961 }
4962 }
4963
4964 /* Get name of the production */
4965 universal_name_translation(&tgt_city->production, prod, sizeof(prod));
4966
4967 /* Destroy the production */
4968 tgt_city->shield_stock = 0;
4970
4971 /* Let the players know. */
4972 clink = city_link(tgt_city); /* Be careful not to call city_link()
4973 * again as long as we need clink */
4974 notify_player(act_player, city_tile(tgt_city),
4975 E_UNIT_ACTION_ACTOR_SUCCESS, ftc_server,
4976 _("Your %s succeeded in destroying"
4977 " the production of %s in %s."),
4978 unit_link(act_unit),
4979 prod, clink);
4980 notify_player(tgt_player, city_tile(tgt_city),
4981 E_UNIT_ACTION_TARGET_HOSTILE, ftc_server,
4982 _("The production of %s was destroyed in %s,"
4983 " %s are suspected."),
4984 prod, clink,
4985 nation_plural_for_player(act_player));
4986
4987 return TRUE;
4988}
4989
4990/**********************************************************************/
5000static bool do_unit_strike_city_building(const struct player *act_player,
5001 struct unit *act_unit,
5002 struct city *tgt_city,
5003 Impr_type_id tgt_bld_id,
5004 const struct action *paction)
5005{
5006 struct player *tgt_player;
5007 struct impr_type *tgt_bld = improvement_by_number(tgt_bld_id);
5008 const char *clink;
5009
5010 /* Sanity checks */
5011 fc_assert_ret_val(act_player, FALSE);
5012 fc_assert_ret_val(act_unit, FALSE);
5013 fc_assert_ret_val(tgt_city, FALSE);
5014 fc_assert_ret_val(paction, FALSE);
5015
5016 tgt_player = city_owner(tgt_city);
5017 fc_assert_ret_val(tgt_player, FALSE);
5018
5019 /* The surgical strike may miss. */
5020 {
5021 /* Roll the dice. */
5022 if (action_failed_dice_roll(act_player, act_unit,
5023 tgt_city, tgt_player,
5024 paction)) {
5025 /* Notify the player. */
5026 notify_player(act_player, city_tile(tgt_city),
5027 E_UNIT_ACTION_ACTOR_FAILURE, ftc_server,
5028 /* TRANS: unit, action, city */
5029 _("Your %s failed to do %s in %s."),
5030 unit_link(act_unit),
5031 action_name_translation(paction),
5032 city_link(tgt_city));
5033
5034 /* Make the failed attempt cost a single move. */
5035 act_unit->moves_left = MAX(0, act_unit->moves_left - SINGLE_MOVE);
5036
5037 return FALSE;
5038 }
5039 }
5040
5041 if (!city_has_building(tgt_city, tgt_bld)) {
5042 /* Nothing to destroy here. */
5043
5044 /* Notify the player. */
5045 notify_player(act_player, city_tile(tgt_city),
5046 E_UNIT_ACTION_ACTOR_FAILURE, ftc_server,
5047 _("Your %s didn't find a %s to %s in %s."),
5048 unit_link(act_unit),
5050 action_name_translation(paction),
5051 city_link(tgt_city));
5052
5053 /* Punish the player for blindly attacking a building. */
5054 act_unit->moves_left = MAX(0, act_unit->moves_left - SINGLE_MOVE);
5055
5056 return FALSE;
5057 }
5058
5059 /* Destroy the building. */
5060 building_lost(tgt_city, tgt_bld, "attacked", act_unit);
5061
5062 /* Update the player's view of the city. */
5063 send_city_info(NULL, tgt_city);
5064
5065 /* Let the players know. */
5066 clink = city_link(tgt_city); /* Be careful not to call city_link()
5067 * again as long as we need clink */
5068 notify_player(act_player, city_tile(tgt_city),
5069 E_UNIT_ACTION_ACTOR_SUCCESS, ftc_server,
5070 _("Your %s destroyed the %s in %s."),
5071 unit_link(act_unit),
5073 clink);
5074 notify_player(tgt_player, city_tile(tgt_city),
5075 E_UNIT_ACTION_TARGET_HOSTILE, ftc_server,
5076 _("The %s destroyed the %s in %s."),
5077 nation_plural_for_player(act_player),
5079 clink);
5080
5081 return TRUE;
5082}
5083
5084/**********************************************************************/
5093static bool do_unit_conquer_city(struct player *act_player,
5094 struct unit *act_unit,
5095 struct city *tgt_city,
5096 struct action *paction)
5097{
5098 bool success;
5099 struct tile *tgt_tile = city_tile(tgt_city);
5100 int move_cost = map_move_cost_unit(&(wld.map), act_unit, tgt_tile);
5101 int tgt_city_id = tgt_city->id;
5102 struct player *tgt_player = city_owner(tgt_city);
5103 const char *victim_link = city_link(tgt_city);
5104 const struct unit_type *act_utype = unit_type_get(act_unit);
5105
5106 /* Sanity check */
5107 fc_assert_ret_val(tgt_tile, FALSE);
5108
5109 unit_move(act_unit, tgt_tile, move_cost, NULL, FALSE, TRUE, TRUE,
5110 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
5111 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_FRIGHTEN));
5112
5113 /* The city may have been destroyed during the conquest. */
5114 success = (!city_exist(tgt_city_id)
5115 || city_owner(tgt_city) == act_player);
5116
5117 if (success) {
5118 /* May cause an incident */
5119 action_consequence_success(paction, act_player, act_utype,
5120 tgt_player, tgt_tile,
5121 victim_link);
5122 }
5123
5124 return success;
5125}
5126
5127/**********************************************************************/
5131 struct tile *dest_tile,
5132 bool igzoc,
5133 struct unit *embark_to,
5134 bool enter_enemy_city)
5135{
5136 struct tile *src_tile = unit_tile(punit);
5137 enum unit_move_result reason =
5139 src_tile, dest_tile, igzoc, TRUE, embark_to,
5140 enter_enemy_city);
5141
5142 switch (reason) {
5143 case MR_OK:
5144 return TRUE;
5145
5146 case MR_NO_WAR:
5147 notify_player(unit_owner(punit), src_tile, E_BAD_COMMAND, ftc_server,
5148 _("Cannot attack unless you declare war first."));
5149 break;
5150
5151 case MR_ZOC:
5152 notify_player(unit_owner(punit), src_tile, E_BAD_COMMAND, ftc_server,
5153 _("%s can only move into your own zone of control."),
5154 unit_link(punit));
5155 break;
5156
5157 case MR_TRIREME:
5158 notify_player(unit_owner(punit), src_tile, E_BAD_COMMAND, ftc_server,
5159 _("%s cannot move that far from the coast line."),
5160 unit_link(punit));
5161 break;
5162
5163 case MR_PEACE:
5164 if (tile_owner(dest_tile)) {
5165 notify_player(unit_owner(punit), src_tile, E_BAD_COMMAND, ftc_server,
5166 _("Cannot invade unless you break peace with "
5167 "%s first."),
5168 player_name(tile_owner(dest_tile)));
5169 }
5170 break;
5171
5173 notify_player(unit_owner(punit), src_tile, E_BAD_COMMAND, ftc_server,
5174 _("%s cannot disembark outside of a city or a native base "
5175 "for %s."),
5179 break;
5180
5181 case MR_NON_NATIVE_MOVE:
5182 notify_player(unit_owner(punit), src_tile, E_BAD_COMMAND, ftc_server,
5183 _("Terrain is unsuitable for %s units."),
5185 break;
5186
5187 default:
5188 /* FIXME: need more explanations someday! */
5189 break;
5190 };
5191
5192 return FALSE;
5193}
5194
5195/**********************************************************************/
5201static bool unit_do_regular_move(struct player *actor_player,
5202 struct unit *actor_unit,
5203 struct tile *target_tile,
5204 const struct action *paction)
5205{
5206 const struct unit_type *act_utype = unit_type_get(actor_unit);
5207 int move_cost = map_move_cost_unit(&(wld.map), actor_unit, target_tile);
5208
5209 unit_move(actor_unit, target_tile, move_cost,
5210 NULL, BV_ISSET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK),
5211 /* Don't override "Conquer City" */
5212 FALSE,
5213 /* Don't override "Conquer Extras" */
5214 FALSE,
5215 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
5216 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_FRIGHTEN));
5217
5218 /* May cause an incident */
5219 action_consequence_success(paction, actor_player, act_utype,
5222
5223 return TRUE;
5224}
5225
5226/**********************************************************************/
5239bool unit_move_handling(struct unit *punit, struct tile *pdesttile,
5240 bool move_do_not_act)
5241{
5242 struct player *pplayer = unit_owner(punit);
5243 struct unit *ptrans;
5244 const struct civ_map *nmap = &(wld.map);
5245
5246 /*** Phase 1: Attempted action interpretation checks ***/
5247
5248 /* Check if the move should be interpreted as an attempt to perform an
5249 * enabler controlled action to the target tile. When the move may be an
5250 * action attempt the server stops moving the unit, marks it as wanting a
5251 * decision based on its own movement to the tile it attempted to move to
5252 * and notifies the client.
5253 *
5254 * In response to the unit being marked as wanting a decision the client
5255 * can query the server for what actions the unit, given the player's
5256 * knowledge, may be able to perform against a target at the tile it tried
5257 * to move to. The server will respond to the query with the actions that
5258 * may be enabled and, when all actions are known to be illegal given the
5259 * player's knowledge, an explanation why no action could be done. The
5260 * client will probably use the list of potentially legal actions, if any,
5261 * to pop up an action selection dialog. See handle_unit_action_query()
5262 *
5263 * If move_do_not_act is TRUE the move is never interpreted as an attempt
5264 * to perform an enabler controlled action.
5265 * Examples of where this is useful is for AI moves, goto, when the player
5266 * attempts to move to a tile occupied by potential targets like allied
5267 * cities or units and during rule forced moves.
5268 *
5269 * A move is not interpreted as an attempted action because the unit is
5270 * able to do a self targeted action.
5271 *
5272 * A move is not interpreted as an attempted action because an action
5273 * with rare_pop_up set to TRUE is legal unless the unit is unable to
5274 * perform a regular move to the tile.
5275 *
5276 * An attempted move to a tile a unit can't move to is always interpreted
5277 * as trying to perform an action (unless move_do_not_act is TRUE) */
5278 if (!move_do_not_act) {
5279 const bool can_not_move = !unit_can_move_to_tile(nmap,
5280 punit, pdesttile,
5281 FALSE, FALSE, FALSE);
5282 bool one_action_may_be_legal
5283 = action_tgt_unit(punit, pdesttile, can_not_move)
5284 || action_tgt_city(punit, pdesttile, can_not_move)
5285 /* A legal action with an extra sub target is a legal action */
5286 || action_tgt_tile_extra(punit, pdesttile, can_not_move)
5287 /* Tile target actions with extra sub targets are handled above */
5288 || action_tgt_tile(punit, pdesttile, NULL, can_not_move);
5289
5290 if (one_action_may_be_legal || can_not_move) {
5291 /* There is a target punit, from the player's point of view, may be
5292 * able to act against OR punit can't do any non action move. The
5293 * client should therefore ask what action(s) the unit can perform
5294 * to any targets at pdesttile.
5295 *
5296 * In the first case the unit needs a decision about what action, if
5297 * any at all, to take. Asking what actions the unit can perform
5298 * will return a list of actions that may, from the players point of
5299 * view, be possible. The client can then show this list to the
5300 * player or, if configured to do so, make the choice it self.
5301 *
5302 * In the last case the player may need an explanation about why no
5303 * action could be taken. Asking what actions the unit can perform
5304 * will provide this explanation. */
5305 punit->action_decision_want = ACT_DEC_ACTIVE;
5306 punit->action_decision_tile = pdesttile;
5308
5309 /* The move wasn't done because the unit wanted the player to
5310 * decide what to do or because the unit couldn't move to the
5311 * target tile. */
5312 return FALSE;
5313 }
5314 }
5315
5316 /*** Phase 2: OK now move the unit ***/
5317 /* This is a regular move, subject to the rules. */
5318 if (is_action_enabled_unit_on_tile(nmap, ACTION_UNIT_MOVE,
5319 punit, pdesttile, NULL)) {
5320 return unit_perform_action(pplayer, punit->id, tile_index(pdesttile),
5321 NO_TARGET, "", ACTION_UNIT_MOVE,
5322 ACT_REQ_PLAYER);
5323 } else if (is_action_enabled_unit_on_tile(nmap, ACTION_UNIT_MOVE2,
5324 punit, pdesttile, NULL)) {
5325 return unit_perform_action(pplayer, punit->id, tile_index(pdesttile),
5326 NO_TARGET, "", ACTION_UNIT_MOVE2,
5327 ACT_REQ_PLAYER);
5328 } else if (is_action_enabled_unit_on_tile(nmap, ACTION_UNIT_MOVE3,
5329 punit, pdesttile, NULL)) {
5330 return unit_perform_action(pplayer, punit->id, tile_index(pdesttile),
5331 NO_TARGET, "", ACTION_UNIT_MOVE3,
5332 ACT_REQ_PLAYER);
5333 } else if (!can_unit_survive_at_tile(nmap, punit, pdesttile)
5334 && ((ptrans = transporter_for_unit_at(punit, pdesttile)))
5335 && is_action_enabled_unit_on_unit(nmap, ACTION_TRANSPORT_EMBARK,
5336 punit, ptrans)) {
5337 /* "Transport Embark". */
5338 return unit_perform_action(pplayer, punit->id, ptrans->id,
5339 NO_TARGET, "", ACTION_TRANSPORT_EMBARK,
5340 ACT_REQ_PLAYER);
5341 } else if (!can_unit_survive_at_tile(nmap, punit, pdesttile)
5342 && ((ptrans = transporter_for_unit_at(punit, pdesttile)))
5343 && is_action_enabled_unit_on_unit(nmap, ACTION_TRANSPORT_EMBARK2,
5344 punit, ptrans)) {
5345 /* "Transport Embark 2". */
5346 return unit_perform_action(pplayer, punit->id, ptrans->id,
5347 NO_TARGET, "", ACTION_TRANSPORT_EMBARK2,
5348 ACT_REQ_PLAYER);
5349 } else if (!can_unit_survive_at_tile(nmap, punit, pdesttile)
5350 && ((ptrans = transporter_for_unit_at(punit, pdesttile)))
5351 && is_action_enabled_unit_on_unit(nmap, ACTION_TRANSPORT_EMBARK3,
5352 punit, ptrans)) {
5353 /* "Transport Embark 3". */
5354 return unit_perform_action(pplayer, punit->id, ptrans->id,
5355 NO_TARGET, "", ACTION_TRANSPORT_EMBARK3,
5356 ACT_REQ_PLAYER);
5357 } else if (is_action_enabled_unit_on_tile(nmap, ACTION_TRANSPORT_DISEMBARK1,
5358 punit, pdesttile, NULL)) {
5359 /* "Transport Disembark". */
5360 return unit_perform_action(pplayer, punit->id, tile_index(pdesttile),
5361 NO_TARGET, "", ACTION_TRANSPORT_DISEMBARK1,
5362 ACT_REQ_PLAYER);
5363 } else if (is_action_enabled_unit_on_tile(nmap, ACTION_TRANSPORT_DISEMBARK2,
5364 punit, pdesttile, NULL)) {
5365 /* "Transport Disembark 2". */
5366 return unit_perform_action(pplayer, punit->id, tile_index(pdesttile),
5367 NO_TARGET, "", ACTION_TRANSPORT_DISEMBARK2,
5368 ACT_REQ_PLAYER);
5369 } else if (is_action_enabled_unit_on_tile(nmap, ACTION_TRANSPORT_DISEMBARK3,
5370 punit, pdesttile, NULL)) {
5371 /* "Transport Disembark 3". */
5372 return unit_perform_action(pplayer, punit->id, tile_index(pdesttile),
5373 NO_TARGET, "", ACTION_TRANSPORT_DISEMBARK3,
5374 ACT_REQ_PLAYER);
5375 } else if (is_action_enabled_unit_on_tile(nmap, ACTION_TRANSPORT_DISEMBARK4,
5376 punit, pdesttile, NULL)) {
5377 /* "Transport Disembark 4". */
5378 return unit_perform_action(pplayer, punit->id, tile_index(pdesttile),
5379 NO_TARGET, "", ACTION_TRANSPORT_DISEMBARK4,
5380 ACT_REQ_PLAYER);
5381 } else if (is_action_enabled_unit_on_tile(nmap, ACTION_HUT_ENTER,
5382 punit, pdesttile, NULL)) {
5383 /* "Enter Hut". */
5384 return unit_perform_action(pplayer, punit->id, tile_index(pdesttile),
5385 NO_TARGET, "", ACTION_HUT_ENTER,
5386 ACT_REQ_PLAYER);
5387 } else if (is_action_enabled_unit_on_tile(nmap, ACTION_HUT_ENTER2,
5388 punit, pdesttile, NULL)) {
5389 /* "Enter Hut 2". */
5390 return unit_perform_action(pplayer, punit->id, tile_index(pdesttile),
5391 NO_TARGET, "", ACTION_HUT_ENTER2,
5392 ACT_REQ_PLAYER);
5393 } else if (is_action_enabled_unit_on_tile(nmap, ACTION_HUT_FRIGHTEN,
5394 punit, pdesttile, NULL)) {
5395 /* "Frighten Hut". */
5396 return unit_perform_action(pplayer, punit->id, tile_index(pdesttile),
5397 NO_TARGET, "", ACTION_HUT_FRIGHTEN,
5398 ACT_REQ_PLAYER);
5399 } else if (is_action_enabled_unit_on_tile(nmap, ACTION_HUT_FRIGHTEN2,
5400 punit, pdesttile, NULL)) {
5401 /* "Frighten Hut 2". */
5402 return unit_perform_action(pplayer, punit->id, tile_index(pdesttile),
5403 NO_TARGET, "", ACTION_HUT_FRIGHTEN2,
5404 ACT_REQ_PLAYER);
5405 } else {
5406 /* TODO: Extend the action not enabled explanation system to cover all
5407 * existing reasons and switch to using it. See hrm Feature #920229 */
5409 NULL, FALSE);
5410 return FALSE;
5411 }
5412}
5413
5414/**********************************************************************/
5424static bool unit_do_help_build(struct player *pplayer,
5425 struct unit *punit,
5426 struct city *pcity_dest,
5427 const struct action *paction)
5428{
5429 const char *work;
5430 const char *prod;
5431 int shields;
5432 const struct unit_type *act_utype;
5433 struct player *cowner;
5434
5435 /* Sanity check: The actor still exists. */
5436 fc_assert_ret_val(pplayer, FALSE);
5438
5439 /* Sanity check: The target city still exists. */
5440 fc_assert_ret_val(pcity_dest, FALSE);
5441
5442 act_utype = unit_type_get(punit);
5443 shields = unit_shield_value(punit, unit_type_get(punit), paction);
5444
5445 if (action_has_result(paction, ACTRES_HELP_WONDER)) {
5446 /* Add the caravan shields */
5447 pcity_dest->shield_stock += shields;
5448
5449 /* Will be punished for changing production to something that can't
5450 * receive "Help Wonder" help. */
5452 &pcity_dest->production));
5453 pcity_dest->caravan_shields += shields;
5454 } else {
5455 fc_assert(action_has_result(paction, ACTRES_DISBAND_UNIT_RECOVER));
5456 /* Add the shields from recycling the unit to the city's current
5457 * production. */
5458 pcity_dest->shield_stock += shields;
5459
5460 /* If we change production later at this turn. No penalty is added. */
5461 pcity_dest->disbanded_shields += shields;
5462 }
5463
5464 cowner = city_owner(pcity_dest);
5465
5467
5468 if (action_has_result(paction, ACTRES_HELP_WONDER)) {
5469 /* Let the player that just donated shields with "Help Wonder" know
5470 * the result of their donation. */
5471 prod = city_production_name_translation(pcity_dest);
5472 } else {
5473 fc_assert(action_has_result(paction, ACTRES_DISBAND_UNIT_RECOVER));
5474 /* TRANS: Your Caravan does "Disband Unit Recover" to help build the
5475 * current production in Bergen (4 surplus).
5476 * "Disband Unit Recover" says "current production" rather than its name. */
5477 prod = _("current production");
5478 }
5479
5480 if (build_points_left(pcity_dest) >= 0) {
5481 /* TRANS: Your Caravan does "Help Wonder" to help build the
5482 * Pyramids in Bergen (4 remaining).
5483 * You can reorder '4' and 'remaining' in the actual format string. */
5484 work = _("remaining");
5485 } else {
5486 /* TRANS: Your Caravan does "Help Wonder" to help build the
5487 * Pyramids in Bergen (4 surplus).
5488 * You can reorder '4' and 'surplus' in the actual format string. */
5489 work = _("surplus");
5490 }
5491
5492 notify_player(pplayer, city_tile(pcity_dest), E_CARAVAN_ACTION,
5493 ftc_server,
5494 /* TRANS: Your Caravan does "Help Wonder" to help build the
5495 * Pyramids in Bergen (4 surplus). */
5496 _("Your %s does %s to help build the %s in %s (%d %s)."),
5498 action_name_translation(paction),
5499 prod,
5500 city_link(pcity_dest),
5501 abs(build_points_left(pcity_dest)),
5502 work);
5503
5504 /* May cause an incident */
5505 action_consequence_success(paction, pplayer, act_utype, cowner,
5506 city_tile(pcity_dest), city_link(pcity_dest));
5507
5508 if (cowner != unit_owner(punit)) {
5509 /* Tell the city owner about the gift they just received. */
5510
5511 notify_player(cowner, city_tile(pcity_dest),
5512 E_CARAVAN_ACTION, ftc_server,
5513 /* TRANS: Help building the Pyramids in Bergen received
5514 * from Persian Caravan (4 surplus). */
5515 _("Help building the %s in %s received from %s %s "
5516 "(%d %s)."),
5518 city_link(pcity_dest),
5521 abs(build_points_left(pcity_dest)),
5522 work);
5523 }
5524
5525 send_player_info_c(cowner, pplayer->connections);
5526 send_city_info(cowner, pcity_dest);
5528
5529 return TRUE;
5530}
5531
5532/**********************************************************************/
5539static bool do_unit_establish_trade(struct player *pplayer,
5540 struct unit *punit,
5541 struct city *pcity_dest,
5542 const struct action *paction)
5543{
5544 char homecity_link[MAX_LEN_LINK], destcity_link[MAX_LEN_LINK];
5545 char punit_link[MAX_LEN_LINK];
5546 int revenue;
5547 bool can_establish;
5548 int home_overbooked = 0;
5549 int dest_overbooked = 0;
5550 int home_max;
5551 int dest_max;
5552 struct city *pcity_homecity;
5553 struct trade_route_list *routes_out_of_dest;
5554 struct trade_route_list *routes_out_of_home;
5555 enum trade_route_bonus_type bonus_type;
5556 struct goods_type *goods;
5557 const char *goods_str;
5558 const struct unit_type *act_utype;
5559
5560 /* Sanity check: The actor still exists. */
5561 fc_assert_ret_val(pplayer, FALSE);
5563
5564 /* Sanity check: The target city still exists. */
5565 fc_assert_ret_val(pcity_dest, FALSE);
5566
5567 act_utype = unit_type_get(punit);
5568 pcity_homecity = player_city_by_number(pplayer, punit->homecity);
5569
5570 if (!pcity_homecity) {
5571 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
5572 _("Sorry, your %s cannot establish"
5573 " a trade route because it has no home city."),
5574 unit_link(punit));
5575 return FALSE;
5576 }
5577
5578 if (game.info.goods_selection == GSM_ARRIVAL) {
5579 goods = goods_from_city_to_unit(pcity_homecity, punit);
5580 } else {
5581 goods = punit->carrying;
5582 }
5583 if (goods == NULL) {
5584 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
5585 _("Sorry, your %s cannot establish"
5586 " a trade route because it's not carrying any goods."),
5587 unit_link(punit));
5588 return FALSE;
5589 }
5590
5591 sz_strlcpy(homecity_link, city_link(pcity_homecity));
5592 sz_strlcpy(destcity_link, city_link(pcity_dest));
5593
5594 if (!can_cities_trade(pcity_homecity, pcity_dest)) {
5595 notify_player(pplayer, city_tile(pcity_dest), E_BAD_COMMAND, ftc_server,
5596 _("Sorry, your %s cannot establish"
5597 " a trade route between %s and %s."),
5599 homecity_link,
5600 destcity_link);
5601 return FALSE;
5602 }
5603
5604 sz_strlcpy(punit_link, unit_tile_link(punit));
5605 routes_out_of_home = trade_route_list_new();
5606 routes_out_of_dest = trade_route_list_new();
5607
5608 /* This part of code works like can_establish_trade_route, except
5609 * that we actually do the action of making the trade route. */
5610
5611 /* If we can't make a new trade route we can still get the trade bonus. */
5612 can_establish = action_has_result(paction, ACTRES_TRADE_ROUTE)
5613 && !have_cities_trade_route(pcity_homecity, pcity_dest);
5614
5615 if (can_establish) {
5616 home_max = max_trade_routes(pcity_homecity);
5617 dest_max = max_trade_routes(pcity_dest);
5618 home_overbooked = city_num_trade_routes(pcity_homecity) - home_max;
5619 dest_overbooked = city_num_trade_routes(pcity_dest) - dest_max;
5620 }
5621
5622 if (can_establish && (home_overbooked >= 0 || dest_overbooked >= 0)) {
5623 int trade = trade_base_between_cities(pcity_homecity, pcity_dest);
5624
5625 /* See if there's a trade route we can cancel at the home city. */
5626 if (home_overbooked >= 0) {
5627 if (home_max <= 0
5628 || (city_trade_removable(pcity_homecity, routes_out_of_home)
5629 >= trade)) {
5630 notify_player(pplayer, city_tile(pcity_dest),
5631 E_BAD_COMMAND, ftc_server,
5632 _("Sorry, your %s cannot establish"
5633 " a trade route here!"),
5634 punit_link);
5635 if (home_max > 0) {
5636 notify_player(pplayer, city_tile(pcity_dest),
5637 E_BAD_COMMAND, ftc_server,
5638 PL_(" The city of %s already has %d "
5639 "better trade route!",
5640 " The city of %s already has %d "
5641 "better trade routes!", home_max),
5642 homecity_link,
5643 home_max);
5644 }
5645 can_establish = FALSE;
5646 }
5647 }
5648
5649 /* See if there's a trade route we can cancel at the dest city. */
5650 if (can_establish && dest_overbooked >= 0) {
5651 if (dest_max <= 0
5652 || (city_trade_removable(pcity_dest, routes_out_of_dest)
5653 >= trade)) {
5654 notify_player(pplayer, city_tile(pcity_dest),
5655 E_BAD_COMMAND, ftc_server,
5656 _("Sorry, your %s cannot establish"
5657 " a trade route here!"),
5658 punit_link);
5659 if (dest_max > 0) {
5660 notify_player(pplayer, city_tile(pcity_dest),
5661 E_BAD_COMMAND, ftc_server,
5662 PL_(" The city of %s already has %d "
5663 "better trade route!",
5664 " The city of %s already has %d "
5665 "better trade routes!", dest_max),
5666 destcity_link,
5667 dest_max);
5668 }
5669 can_establish = FALSE;
5670 }
5671 }
5672 }
5673
5674 /* We now know for sure whether we can establish a trade route. */
5675
5676 /* Calculate and announce initial revenue. */
5677 revenue = get_caravan_enter_city_trade_bonus(pcity_homecity, pcity_dest, goods,
5678 can_establish);
5679
5680 bonus_type = trade_route_settings_by_type(cities_trade_route_type(pcity_homecity, pcity_dest))->bonus_type;
5681
5683
5684 goods_str = goods_name_translation(goods);
5685
5686 /* We want to keep the bonus type string as the part of the format of the PL_() strings
5687 * for supporting proper pluralization for it. */
5688 switch (bonus_type) {
5689 case TBONUS_NONE:
5690 notify_player(pplayer, city_tile(pcity_dest),
5691 E_CARAVAN_ACTION, ftc_server,
5692 /* TRANS: ... Caravan ... Paris ... Stockholm ... Goods */
5693 _("Your %s from %s has arrived in %s carrying %s."),
5694 punit_link,
5695 homecity_link,
5696 destcity_link,
5697 goods_str);
5698 break;
5699 case TBONUS_GOLD:
5700 notify_player(pplayer, city_tile(pcity_dest),
5701 E_CARAVAN_ACTION, ftc_server,
5702 /* TRANS: ... Caravan ... Paris ... Stockholm, ... Goods... */
5703 PL_("Your %s from %s has arrived in %s carrying %s,"
5704 " and revenues amount to %d in gold.",
5705 "Your %s from %s has arrived in %s carrying %s,"
5706 " and revenues amount to %d in gold.",
5707 revenue),
5708 punit_link,
5709 homecity_link,
5710 destcity_link,
5711 goods_str,
5712 revenue);
5713 break;
5714 case TBONUS_SCIENCE:
5715 notify_player(pplayer, city_tile(pcity_dest),
5716 E_CARAVAN_ACTION, ftc_server,
5717 /* TRANS: ... Caravan ... Paris ... Stockholm, ... Goods... */
5718 PL_("Your %s from %s has arrived in %s carrying %s,"
5719 " and revenues amount to %d in research.",
5720 "Your %s from %s has arrived in %s carrying %s,"
5721 " and revenues amount to %d in research.",
5722 revenue),
5723 punit_link,
5724 homecity_link,
5725 destcity_link,
5726 goods_str,
5727 revenue);
5728 break;
5729 case TBONUS_BOTH:
5730 notify_player(pplayer, city_tile(pcity_dest),
5731 E_CARAVAN_ACTION, ftc_server,
5732 /* TRANS: ... Caravan ... Paris ... Stockholm, ... Goods... */
5733 PL_("Your %s from %s has arrived in %s carrying %s,"
5734 " and revenues amount to %d in gold and research.",
5735 "Your %s from %s has arrived in %s carrying %s,"
5736 " and revenues amount to %d in gold and research.",
5737 revenue),
5738 punit_link,
5739 homecity_link,
5740 destcity_link,
5741 goods_str,
5742 revenue);
5743 break;
5744 }
5745
5746 if (bonus_type == TBONUS_GOLD || bonus_type == TBONUS_BOTH) {
5747 pplayer->economic.gold += revenue;
5748
5749 send_player_info_c(pplayer, pplayer->connections);
5750 }
5751
5752 if (bonus_type == TBONUS_SCIENCE || bonus_type == TBONUS_BOTH) {
5753 /* add bulbs and check for finished research */
5754 update_bulbs(pplayer, revenue, TRUE);
5755
5756 /* Inform everyone about tech changes */
5757 send_research_info(research_get(pplayer), NULL);
5758 }
5759
5760 if (can_establish) {
5761 struct trade_route *proute_from, *proute_to;
5762 struct city_list *cities_out_of_home;
5763 struct city_list *cities_out_of_dest;
5764 struct player *partner_player;
5765
5766 /* Announce creation of trade route (it's not actually created until
5767 * later in this function, as we have to cancel existing routes, but
5768 * it makes more sense to announce in this order) */
5769
5770 partner_player = city_owner(pcity_dest);
5771
5772 /* Always tell the unit owner */
5773 notify_player(pplayer, NULL,
5774 E_CARAVAN_ACTION, ftc_server,
5775 _("New trade route established from %s to %s."),
5776 homecity_link,
5777 destcity_link);
5778 if (pplayer != partner_player) {
5779 notify_player(partner_player, city_tile(pcity_dest),
5780 E_CARAVAN_ACTION, ftc_server,
5781 _("The %s established a trade route between their "
5782 "city %s and %s."),
5783 nation_plural_for_player(pplayer),
5784 homecity_link,
5785 destcity_link);
5786 }
5787
5788 cities_out_of_home = city_list_new();
5789 cities_out_of_dest = city_list_new();
5790
5791 /* Now cancel any less profitable trade route from the home city. */
5792 trade_route_list_iterate(routes_out_of_home, premove) {
5793 struct trade_route *pback;
5794
5795 city_list_append(cities_out_of_home, game_city_by_number(premove->partner));
5796
5797 pback = remove_trade_route(pcity_homecity, premove, TRUE, FALSE);
5798 free(premove);
5799 free(pback);
5801
5802 /* And the same for the dest city. */
5803 trade_route_list_iterate(routes_out_of_dest, premove) {
5804 struct trade_route *pback;
5805
5806 city_list_append(cities_out_of_dest, game_city_by_number(premove->partner));
5807
5808 pback = remove_trade_route(pcity_dest, premove, TRUE, FALSE);
5809 free(premove);
5810 free(pback);
5812
5813 /* Actually create the new trade route */
5814 proute_from = fc_malloc(sizeof(struct trade_route));
5815 proute_from->partner = pcity_dest->id;
5816 proute_from->goods = goods;
5817
5818 proute_to = fc_malloc(sizeof(struct trade_route));
5819 proute_to->partner = pcity_homecity->id;
5820 proute_to->goods = goods;
5821
5822 if (goods_has_flag(goods, GF_BIDIRECTIONAL)) {
5823 proute_from->dir = RDIR_BIDIRECTIONAL;
5824 proute_to->dir = RDIR_BIDIRECTIONAL;
5825 } else {
5826 proute_from->dir = RDIR_FROM;
5827 proute_to->dir = RDIR_TO;
5828 }
5829 trade_route_list_append(pcity_homecity->routes, proute_from);
5830 trade_route_list_append(pcity_dest->routes, proute_to);
5831
5832 /* Refresh the cities. */
5833 city_refresh(pcity_homecity);
5834 city_refresh(pcity_dest);
5835 city_list_iterate(cities_out_of_home, pcity) {
5836 city_refresh(pcity);
5838 city_list_iterate(cities_out_of_dest, pcity) {
5839 city_refresh(pcity);
5841
5842 /* Notify the owners of the cities. */
5843 send_city_info(pplayer, pcity_homecity);
5844 send_city_info(partner_player, pcity_dest);
5845 city_list_iterate(cities_out_of_home, pcity) {
5846 send_city_info(city_owner(pcity), pcity);
5848 city_list_iterate(cities_out_of_dest, pcity) {
5849 send_city_info(city_owner(pcity), pcity);
5851
5852 /* Notify each player about the other cities so that they know about
5853 * its size for the trade calculation. */
5854 if (pplayer != partner_player) {
5855 map_show_tile(partner_player, city_tile(pcity_homecity));
5856 send_city_info(partner_player, pcity_homecity);
5857 map_show_tile(pplayer, city_tile(pcity_dest));
5858 send_city_info(pplayer, pcity_dest);
5859 }
5860
5861 city_list_iterate(cities_out_of_home, pcity) {
5862 if (partner_player != city_owner(pcity)) {
5863 send_city_info(partner_player, pcity);
5864 send_city_info(city_owner(pcity), pcity_dest);
5865 }
5866 if (pplayer != city_owner(pcity)) {
5867 send_city_info(pplayer, pcity);
5868 send_city_info(city_owner(pcity), pcity_homecity);
5869 }
5871
5872 city_list_iterate(cities_out_of_dest, pcity) {
5873 if (partner_player != city_owner(pcity)) {
5874 send_city_info(partner_player, pcity);
5875 send_city_info(city_owner(pcity), pcity_dest);
5876 }
5877 if (pplayer != city_owner(pcity)) {
5878 send_city_info(pplayer, pcity);
5879 send_city_info(city_owner(pcity), pcity_homecity);
5880 }
5882
5883 city_list_destroy(cities_out_of_home);
5884 city_list_destroy(cities_out_of_dest);
5885 }
5886
5887 /* May cause an incident */
5889 pplayer, act_utype, city_owner(pcity_dest),
5890 city_tile(pcity_dest),
5891 city_link(pcity_dest));
5892
5894
5895 /* Free data. */
5896 trade_route_list_destroy(routes_out_of_home);
5897 trade_route_list_destroy(routes_out_of_dest);
5898
5899 return TRUE;
5900}
5901
5902/**********************************************************************/
5910void handle_unit_sscs_set(struct player *pplayer,
5911 int unit_id16, int unit_id32,
5912 enum unit_ss_data_type type,
5913 int value)
5914{
5915 struct unit *punit;
5916 const struct civ_map *nmap = &(wld.map);
5917
5918 if (!has_capability("ids32", pplayer->current_conn->capability)) {
5919 unit_id32 = unit_id16;
5920 }
5921
5922 punit = player_unit_by_number(pplayer, unit_id32);
5923
5924 if (NULL == punit) {
5925 /* Being asked to unqueue a "spent" unit because the client haven't
5926 * been told that it's gone is expected. */
5927 if (type != USSDT_UNQUEUE) {
5928 /* Probably died or bribed. */
5929 log_verbose("handle_unit_sscs_set() invalid unit %d", unit_id32);
5930 }
5931
5932 return;
5933 }
5934
5935 switch (type) {
5936 case USSDT_QUEUE:
5937 /* Reminds the client to ask the server about what actions the unit can
5938 * perform against the target tile. Action decision state can be set by
5939 * the server it self too. */
5940
5941 if (index_to_tile(nmap, value) == NULL) {
5942 /* Asked to be reminded to ask what actions the unit can do to a non
5943 * existing target tile. */
5944 log_verbose("unit_sscs_set() invalid target tile %d for unit %d",
5945 value, unit_id32);
5946 break;
5947 }
5948
5949 punit->action_decision_want = ACT_DEC_ACTIVE;
5951
5952 /* Let the client know that this unit needs the player to decide
5953 * what to do. */
5955
5956 break;
5957 case USSDT_UNQUEUE:
5958 /* Delete the reminder for the client to ask the server about what
5959 * actions the unit can perform against a certain target tile.
5960 * Action decision state can be set by the server it self too. */
5961
5962 punit->action_decision_want = ACT_DEC_NOTHING;
5964
5965 /* Let the client know that this unit no longer needs the player to
5966 * decide what to do. */
5967 send_unit_info(pplayer->connections, punit);
5968
5969 break;
5970 case USSDT_BATTLE_GROUP:
5971 /* Battlegroups are handled entirely by the client, so all we have to
5972 do here is save the battlegroup ID so that it'll be persistent. */
5973
5975
5976 break;
5977 case USSDT_SENTRY:
5978 if (value == 0) {
5979 if (punit->activity != ACTIVITY_SENTRY) {
5980 return;
5981 }
5982
5983 if (!unit_activity_internal(punit, ACTIVITY_IDLE)) {
5984 /* Impossible to set to Idle? */
5986 }
5987 } else if (value == 1) {
5988 if (!can_unit_do_activity(nmap, punit, ACTIVITY_SENTRY)) {
5989 return;
5990 }
5991
5992 if (!unit_activity_internal(punit, ACTIVITY_SENTRY)) {
5993 /* Should have been caught above */
5995 }
5996 } else {
5997 log_verbose("handle_unit_sscs_set(): illegal sentry state for %s %d",
5999 }
6000 break;
6001 }
6002}
6003
6004/**********************************************************************/
6007static void unit_plans_clear(struct unit *punit)
6008{
6009 /* Remove city spot reservations for AI settlers on city founding
6010 * mission. */
6012
6013 /* Get rid of old orders. */
6015
6016 /* Make sure that no old goto_tile remains. */
6017 punit->goto_tile = NULL;
6018}
6019
6020/**********************************************************************/
6024 int unit_id16, int unit_id32,
6025 enum server_side_agent agent)
6026{
6027 struct unit *punit;
6028
6029 if (!has_capability("ids32", pplayer->current_conn->capability)) {
6030 unit_id32 = unit_id16;
6031 }
6032
6033 punit = player_unit_by_number(pplayer, unit_id32);
6034
6035 if (NULL == punit) {
6036 /* Probably died or bribed. */
6037 log_verbose("handle_unit_server_side_agent_set() invalid unit %d",
6038 unit_id32);
6039 return;
6040 }
6041
6042 if (!server_side_agent_is_valid(agent)) {
6043 /* Client error. */
6044 log_verbose("handle_unit_server_side_agent_set() invalid agent %d",
6045 agent);
6046 return;
6047 }
6048
6049 /* Set the state or exit */
6050 if (!unit_server_side_agent_set(pplayer, punit, agent)) {
6051 return;
6052 }
6053
6054 /* Give the new agent a blank slate */
6056
6057 if (agent == SSA_AUTOEXPLORE) {
6058 if (!unit_activity_internal(punit, ACTIVITY_EXPLORE)) {
6059 /* Should have been caught above */
6061 punit->ssa_controller = SSA_NONE;
6062 }
6063
6064 /* Exploring is handled here explicitly, since the player expects to
6065 * see an immediate response from setting a unit to auto-explore.
6066 * Handling it deeper in the code leads to some tricky recursive loops -
6067 * see PR#2631. */
6068 if (punit->moves_left > 0) {
6070 }
6071 }
6072}
6073
6074/**********************************************************************/
6079 struct unit *punit,
6080 enum server_side_agent agent)
6081{
6082 const struct civ_map *nmap = &(wld.map);
6083
6084 /* Check that the agent can be activated for this unit. */
6085 switch (agent) {
6086 case SSA_AUTOSETTLER:
6088 return FALSE;
6089 }
6090 break;
6091 case SSA_AUTOEXPLORE:
6092 if (!can_unit_do_activity(nmap, punit, ACTIVITY_EXPLORE)) {
6093 return FALSE;
6094 }
6095 break;
6096 case SSA_NONE:
6097 /* Always possible. */
6098 break;
6099 case SSA_COUNT:
6100 fc_assert_ret_val(agent != SSA_COUNT, FALSE);
6101 break;
6102 }
6103
6104 if (punit->ssa_controller != agent) {
6106 send_unit_info(NULL, punit);
6107 }
6108
6109 return TRUE;
6110}
6111
6112/**********************************************************************/
6117 enum unit_activity old_activity,
6118 struct extra_type *old_target)
6119{
6120 switch (punit->activity) {
6121 case ACTIVITY_IDLE:
6122 switch (old_activity) {
6123 case ACTIVITY_PILLAGE:
6124 {
6125 if (old_target != NULL) {
6126 unit_list_iterate_safe(unit_tile(punit)->units, punit2) {
6127 if (punit2->activity == ACTIVITY_PILLAGE) {
6128 extra_deps_iterate(&(punit2->activity_target->reqs), pdep) {
6129 if (pdep == old_target) {
6130 set_unit_activity(punit2, ACTIVITY_IDLE);
6131 send_unit_info(NULL, punit2);
6132 break;
6133 }
6135 }
6137 }
6138 break;
6139 }
6140 case ACTIVITY_EXPLORE:
6141 /* Restore unit's control status */
6142 punit->ssa_controller = SSA_NONE;
6143 break;
6144 default:
6145 ; /* do nothing */
6146 }
6147 break;
6148 case ACTIVITY_EXPLORE:
6149 punit->ssa_controller = SSA_AUTOEXPLORE;
6150 set_unit_activity(punit, ACTIVITY_EXPLORE);
6151 send_unit_info(NULL, punit);
6152 break;
6153 default:
6154 /* do nothing */
6155 break;
6156 }
6157}
6158
6159/**********************************************************************/
6165static bool do_action_activity(struct unit *punit,
6166 const struct action *paction)
6167{
6168 enum unit_activity new_activity = actres_get_activity(paction->result);
6169
6170 fc_assert_ret_val(new_activity != ACTIVITY_LAST, FALSE);
6172
6173 return unit_activity_internal(punit, new_activity);
6174}
6175
6176/**********************************************************************/
6180 enum unit_activity new_activity)
6181{
6182 const struct civ_map *nmap = &(wld.map);
6183
6184 /* Must specify target for ACTIVITY_BASE */
6185 fc_assert_ret_val(new_activity != ACTIVITY_BASE
6186 && new_activity != ACTIVITY_GEN_ROAD, FALSE);
6187
6188 if (new_activity == ACTIVITY_PILLAGE) {
6189 struct extra_type *target = NULL;
6190
6191 /* Assume untargeted pillaging if no target specified */
6192 unit_activity_handling_targeted(punit, new_activity, &target);
6193 } else if (can_unit_do_activity(nmap, punit, new_activity)) {
6195 unit_activity_internal(punit, new_activity);
6196 }
6197
6198 return TRUE;
6199}
6200
6201/**********************************************************************/
6208 enum unit_activity new_activity)
6209{
6210 if (!can_unit_do_activity(&(wld.map), punit, new_activity)) {
6211 return FALSE;
6212 } else {
6213 enum unit_activity old_activity = punit->activity;
6214 struct extra_type *old_target = punit->activity_target;
6215
6216 set_unit_activity(punit, new_activity);
6217 send_unit_info(NULL, punit);
6218 unit_activity_dependencies(punit, old_activity, old_target);
6219
6220 return TRUE;
6221 }
6222}
6223
6224/**********************************************************************/
6231 const struct action *paction,
6232 struct extra_type **new_target)
6233{
6234 enum unit_activity new_activity = actres_get_activity(paction->result);
6235
6236 fc_assert_ret_val(new_activity != ACTIVITY_LAST, FALSE);
6238 unit_activity_internal(punit, new_activity));
6239
6240 return unit_activity_targeted_internal(punit, new_activity, new_target);
6241}
6242
6243/**********************************************************************/
6247 enum unit_activity new_activity,
6248 struct extra_type **new_target)
6249{
6250 if (!activity_requires_target(new_activity)) {
6251 unit_activity_handling(punit, new_activity);
6253 new_activity, *new_target)) {
6254 struct action_list *list = action_list_by_activity(new_activity);
6255
6257
6258 if (list != NULL && action_list_size(list) > 0) {
6259 /* Trigger action system */
6261 (*new_target) != NULL ? (*new_target)->id : NO_TARGET,
6262 "", action_number(action_list_get(list, 0)));
6263 } else {
6264 unit_activity_targeted_internal(punit, new_activity, new_target);
6265 }
6266 }
6267
6268 return TRUE;
6269}
6270
6271/**********************************************************************/
6278 enum unit_activity new_activity,
6279 struct extra_type **new_target)
6280{
6282 new_activity, *new_target)) {
6283 return FALSE;
6284 } else {
6285 enum unit_activity old_activity = punit->activity;
6286 struct extra_type *old_target = punit->activity_target;
6287 enum unit_activity stored_activity = new_activity;
6288
6290 &new_activity, new_target);
6291 if (new_activity != stored_activity
6292 && !activity_requires_target(new_activity)) {
6293 /* unit_assign_specific_activity_target() changed our target activity
6294 * (to ACTIVITY_IDLE in practice) */
6295 unit_activity_handling(punit, new_activity);
6296 } else {
6297 set_unit_activity_targeted(punit, new_activity, *new_target);
6298 send_unit_info(NULL, punit);
6299 unit_activity_dependencies(punit, old_activity, old_target);
6300
6301 if (new_activity == ACTIVITY_PILLAGE) {
6302 /* Casus Belli for when the activity successfully begins. */
6303 /* TODO: is it more logical to change Casus_Belli_Complete to
6304 * Casus_Belli_Successful_Beginning and trigger it here? */
6310 }
6311 }
6312
6313 return TRUE;
6314 }
6315}
6316
6317/**********************************************************************/
6320void handle_unit_orders(struct player *pplayer,
6321 const struct packet_unit_orders *packet)
6322{
6323 int length = packet->length;
6324 struct unit *punit;
6325 const struct civ_map *nmap = &(wld.map);
6326 struct tile *src_tile = index_to_tile(nmap, packet->src_tile);
6327 struct unit_order *order_list;
6328 int unit_id;
6329#ifdef FREECIV_DEBUG
6330 int i;
6331#endif
6332
6333 if (!has_capability("ids32", pplayer->current_conn->capability)) {
6334 unit_id = packet->unit_id16;
6335 } else {
6336 unit_id = packet->unit_id32;
6337 }
6338
6339 punit = player_unit_by_number(pplayer, unit_id);
6340
6341 if (NULL == punit) {
6342 /* Probably died or bribed. */
6343 log_verbose("handle_unit_orders() invalid unit %d", unit_id);
6344 return;
6345 }
6346
6347 if (0 > length || MAX_LEN_ROUTE < length) {
6348 /* Shouldn't happen */
6349 log_error("handle_unit_orders() invalid %s (%d) "
6350 "packet length %d (max %d)", unit_rule_name(punit),
6351 unit_id, length, MAX_LEN_ROUTE);
6352 return;
6353 }
6354
6355 if (src_tile != unit_tile(punit)) {
6356 /* Failed sanity check. Usually this happens if the orders were sent
6357 * in the previous turn, and the client thought the unit was in a
6358 * different position than it's actually in. The easy solution is to
6359 * discard the packet. We don't send an error message to the client
6360 * here (though maybe we should?). */
6361 log_verbose("handle_unit_orders() invalid %s (%d) tile (%d, %d) "
6362 "!= (%d, %d)", unit_rule_name(punit), punit->id,
6363 TILE_XY(src_tile), TILE_XY(unit_tile(punit)));
6364 return;
6365 }
6366
6367 if (ACTIVITY_IDLE != punit->activity) {
6368 /* New orders implicitly abandon current activity */
6369 unit_activity_handling(punit, ACTIVITY_IDLE);
6370 }
6371
6372 if (length) {
6373 order_list = create_unit_orders(nmap, length, packet->orders);
6374 if (!order_list) {
6375 log_error("received invalid orders from %s for %s (%d).",
6376 player_name(pplayer), unit_rule_name(punit), unit_id);
6377 return;
6378 }
6379 }
6380
6381 /* This must be before old orders are freed. If this is
6382 * settlers on city founding mission, city spot reservation
6383 * from goto_tile must be freed, and free_unit_orders() loses
6384 * goto_tile information */
6386
6388 /* If we waited on a tile, reset punit->done_moving */
6389 punit->done_moving = (punit->moves_left <= 0);
6390
6391 if (length == 0) {
6393 send_unit_info(NULL, punit);
6394 return;
6395 }
6396
6398 punit->orders.length = length;
6399 punit->orders.index = 0;
6400 punit->orders.repeat = packet->repeat;
6401 punit->orders.vigilant = packet->vigilant;
6402 if (length) {
6403 punit->orders.list = order_list;
6404 }
6405
6406 if (!packet->repeat) {
6407 punit->goto_tile = index_to_tile(nmap, packet->dest_tile);
6408 } else {
6409 /* Make sure that no old goto_tile remains. */
6410 punit->goto_tile = NULL;
6411 }
6412
6413#ifdef FREECIV_DEBUG
6414 log_debug("Orders for unit %d: length:%d", unit_id, length);
6415 for (i = 0; i < length; i++) {
6416 log_debug(" %d,%s,%s,%d,%d",
6417 packet->orders[i].order, dir_get_name(packet->orders[i].dir),
6418 packet->orders[i].order == ORDER_PERFORM_ACTION ?
6419 action_id_rule_name(packet->orders[i].action) :
6420 packet->orders[i].order == ORDER_ACTIVITY ?
6421 unit_activity_name(packet->orders[i].activity) :
6422 "no action/activity required",
6423 packet->orders[i].target,
6424 packet->orders[i].sub_target);
6425 }
6426#endif /* FREECIV_DEBUG */
6427
6429 || execute_orders(punit, TRUE)) {
6430 /* Looks like the unit survived. */
6431 send_unit_info(NULL, punit);
6432 }
6433}
6434
6435/**********************************************************************/
6438void handle_worker_task(struct player *pplayer,
6439 const struct packet_worker_task *packet)
6440{
6441 struct city *pcity;
6442 struct worker_task *ptask = NULL;
6443 struct tile *ptile = index_to_tile(&(wld.map), packet->tile_id);
6444
6445 if (!has_capability("ids32", pplayer->current_conn->capability)) {
6446 pcity = game_city_by_number(packet->city_id16);
6447 } else {
6448 pcity = game_city_by_number(packet->city_id32);
6449 }
6450
6451 if (pcity == NULL || pcity->owner != pplayer || ptile == NULL) {
6452 return;
6453 }
6454
6455 worker_task_list_iterate(pcity->task_reqs, ptask_old) {
6456 if (tile_index(ptask_old->ptile) == packet->tile_id) {
6457 ptask = ptask_old;
6458 }
6460
6461 if (ptask == NULL) {
6462 if (packet->activity == ACTIVITY_LAST) {
6463 return;
6464 }
6465
6466 ptask = fc_malloc(sizeof(struct worker_task));
6467 worker_task_init(ptask);
6468 worker_task_list_append(pcity->task_reqs, ptask);
6469 } else {
6470 if (packet->activity == ACTIVITY_LAST) {
6471 worker_task_list_remove(pcity->task_reqs, ptask);
6472 free(ptask);
6473 ptask = NULL;
6474 }
6475 }
6476
6477 if (ptask != NULL) {
6478 ptask->ptile = ptile;
6479 ptask->act = packet->activity;
6480 if (packet->tgt >= 0) {
6481 if (packet->tgt < MAX_EXTRA_TYPES) {
6482 ptask->tgt = extra_by_number(packet->tgt);
6483 } else {
6484 log_debug("Illegal worker task target %d", packet->tgt);
6485 ptask->tgt = NULL;
6486 }
6487 } else {
6488 ptask->tgt = NULL;
6489 }
6490 ptask->want = packet->want;
6491 }
6492
6493 if (ptask && !worker_task_is_sane(ptask)) {
6494 log_debug("Bad worker task");
6495 worker_task_list_remove(pcity->task_reqs, ptask);
6496 free(ptask);
6497 ptask = NULL;
6498 return;
6499 }
6500
6501 lsend_packet_worker_task(pplayer->connections, packet);
6502}
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:7220
const char * action_id_name_translation(action_id act_id)
Definition actions.c:1910
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:6703
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_vs_tile(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:6224
const char * action_id_rule_name(action_id act_id)
Definition actions.c:1899
struct action_list * action_list_by_activity(enum unit_activity activity)
Definition actions.c:9358
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 act_prob action_prob_vs_extras(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:6307
enum unit_activity actres_get_activity(enum action_result result)
Definition actions.c:2136
struct act_prob action_prob_self(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id)
Definition actions.c:6377
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
struct act_prob action_prob_vs_units(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile)
Definition actions.c:6141
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:7165
struct action * action_is_blocked_by(const struct civ_map *nmap, 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
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_unit_vs_tgt(const struct civ_map *nmap, 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:6399
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:941
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:943
#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:939
#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:1833
bool city_has_building(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:1216
bool is_capital(const struct city *pcity)
Definition city.c:1552
const char * city_name_get(const struct city *pcity)
Definition city.c:1115
bool citymindist_prevents_city_on_tile(const struct civ_map *nmap, const struct tile *ptile)
Definition city.c:1438
void city_size_add(struct city *pcity, int add)
Definition city.c:1142
bool city_can_grow_to(const struct city *pcity, int pop_size)
Definition city.c:1985
struct city * tile_non_attack_city(const struct tile *ptile, const struct player *pplayer)
Definition city.c:2024
bool city_exist(int id)
Definition city.c:3471
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:748
#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:2327
void create_city(struct player *pplayer, struct tile *ptile, const char *name, struct player *nationality)
Definition citytools.c:1495
int build_points_left(struct city *pcity)
Definition citytools.c:574
void building_lost(struct city *pcity, const struct impr_type *pimprove, const char *reason, struct unit *destroyer)
Definition citytools.c:2977
void city_units_upkeep(const struct city *pcity)
Definition citytools.c:3026
bool is_allowed_city_name(struct player *pplayer, const char *cityname, char *error_buf, size_t bufsz)
Definition citytools.c:372
void remove_city(struct city *pcity)
Definition citytools.c:1684
struct trade_route * remove_trade_route(struct city *pc1, struct trade_route *proute, bool announce, bool source_gone)
Definition citytools.c:2849
void nullify_prechange_production(struct city *pcity)
Definition cityturn.c:3379
bool city_change_size(struct city *pcity, citizens size, struct player *nationality, const char *reason)
Definition cityturn.c:1061
int city_incite_cost(struct player *pplayer, struct city *pcity)
Definition cityturn.c:3267
bool city_reduce_size(struct city *pcity, citizens pop_loss, struct player *destroyer, const char *reason)
Definition cityturn.c:808
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:714
int get_total_attack_power(const struct unit *attacker, const struct unit *defender)
Definition combat.c:569
struct unit * get_defender(const struct civ_map *nmap, const struct unit *attacker, const struct tile *ptile)
Definition combat.c:783
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:2667
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:291
#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:167
#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:2825
int unit_shield_value(const struct unit *punit, const struct unit_type *punittype, const struct action *paction)
Definition unit.c:216
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1767
void free_unit_orders(struct unit *punit)
Definition unit.c:1753
bool unit_is_alive(int id)
Definition unit.c:2237
struct unit * transporter_for_unit_at(const struct unit *pcargo, const struct tile *ptile)
Definition unit.c:1906
void set_unit_activity(struct unit *punit, enum unit_activity new_activity)
Definition unit.c:1107
struct player * unit_nationality(const struct unit *punit)
Definition unit.c:1271
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2425
bool unit_transport_unload(struct unit *pcargo)
Definition unit.c:2374
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:845
int unit_bribe_cost(struct unit *punit, struct player *briber)
Definition unit.c:2288
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:328
void set_unit_activity_targeted(struct unit *punit, enum unit_activity new_activity, struct extra_type *new_target)
Definition unit.c:1124
bool can_unit_do_activity(const struct civ_map *nmap, const struct unit *punit, enum unit_activity activity)
Definition unit.c:872
enum unit_upgrade_result unit_upgrade_test(const struct civ_map *nmap, const struct unit *punit, bool is_free)
Definition unit.c:1972
bool kills_citizen_after_attack(const struct unit *punit)
Definition unit.c:417
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2409
bool unit_has_orders(const struct unit *punit)
Definition unit.c:204
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:911
#define unit_tile(_pu)
Definition unit.h:395
@ ORDER_ACTIVITY
Definition unit.h:41
@ ORDER_PERFORM_ACTION
Definition unit.h:47
#define unit_owner(_pu)
Definition unit.h:394
@ 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:430
@ 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:4924
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:6023
static bool do_unit_change_homecity(struct unit *punit, struct city *pcity, const struct action *paction)
Definition unithand.c:3957
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:4593
static void send_combat(struct unit *pattacker, struct unit *pdefender, int att_veteran, int def_veteran, int bombard)
Definition unithand.c:4281
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:6320
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:5910
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:5093
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:5000
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:6438
bool unit_activity_handling(struct unit *punit, enum unit_activity new_activity)
Definition unithand.c:6179
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:3175
#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:6116
static void unit_query_impossible(struct connection *pc, const int actor_id, const int target_id, int request_kind)
Definition unithand.c:2995
static bool unit_bombard(struct unit *punit, struct tile *ptile, const struct action *paction)
Definition unithand.c:4332
bool unit_move_handling(struct unit *punit, struct tile *pdesttile, bool move_do_not_act)
Definition unithand.c:5239
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:4501
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:4101
#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:3155
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:6165
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:3015
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:3136
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:3855
static bool unit_activity_targeted_internal(struct unit *punit, enum unit_activity new_activity, struct extra_type **new_target)
Definition unithand.c:6277
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:6230
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:5424
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:3991
static bool unit_activity_internal(struct unit *punit, enum unit_activity new_activity)
Definition unithand.c:6207
bool unit_activity_handling_targeted(struct unit *punit, enum unit_activity new_activity, struct extra_type **new_target)
Definition unithand.c:6246
static bool unit_nuke(struct player *pplayer, struct unit *punit, struct tile *def_tile, const struct action *paction)
Definition unithand.c:4431
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:5130
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:4222
#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:4150
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:5201
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:6078
static bool do_unit_establish_trade(struct player *pplayer, struct unit *punit, struct city *pcity_dest, const struct action *paction)
Definition unithand.c:5539
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:6007
static bool city_build(struct player *pplayer, struct unit *punit, struct tile *ptile, const char *name, const struct action *paction)
Definition unithand.c:4053
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:2963
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:1565
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:2650
void unit_goes_out_of_sight(struct player *pplayer, struct unit *punit)
Definition unittools.c:2781
void send_unit_info(struct conn_list *dest, struct unit *punit)
Definition unittools.c:2794
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:788
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:2733
void unit_forget_last_activity(struct unit *punit)
Definition unittools.c:1069
void unit_refresh_vision(struct unit *punit)
Definition unittools.c:4852
void do_explore(struct unit *punit)
Definition unittools.c:2996
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:2247
bool do_paradrop(struct unit *punit, struct tile *ptile, const struct action *paction)
Definition unittools.c:3032
void do_nuclear_explosion(struct player *pplayer, struct tile *ptile)
Definition unittools.c:2946
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:2307
bool teleport_unit_to_city(struct unit *punit, struct city *pcity, int move_cost, bool verbose)
Definition unittools.c:1203
void unit_assign_specific_activity_target(struct unit *punit, enum unit_activity *activity, struct extra_type **target)
Definition unittools.c:1098
void unit_get_goods(struct unit *punit)
Definition unittools.c:1626
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:2373
void bounce_unit(struct unit *punit, bool verbose)
Definition unittools.c:1241
bool unit_activity_needs_target_from_client(enum unit_activity activity)
Definition unittools.c:1078
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:2547
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:841
#define unit_type_iterate_end
Definition unittype.h:848
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