Freeciv-3.1
Loading...
Searching...
No Matches
control.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/* utility */
19#include "astring.h"
20#include "bitvector.h"
21#include "fcintl.h"
22#include "log.h"
23#include "mem.h"
24#include "timing.h"
25
26/* common */
27#include "combat.h"
28#include "game.h"
29#include "map.h"
30#include "movement.h"
31#include "unitlist.h"
32
33/* common/aicore */
34#include "path_finding.h"
35
36/* client/include */
37#include "chatline_g.h"
38#include "citydlg_g.h"
39#include "dialogs_g.h"
40#include "gui_main_g.h"
41#include "mapctrl_g.h"
42#include "mapview_g.h"
43#include "menu_g.h"
44
45/* client */
46#include "audio.h"
47#include "client_main.h"
48#include "climap.h"
49#include "climisc.h"
50#include "editor.h"
51#include "goto.h"
52#include "options.h"
53#include "overview_common.h"
54#include "tilespec.h"
55#include "update_queue.h"
56
57#include "control.h"
58
59
64
65/* Ways to disband a unit. Sorted by preference. Starts with the worst. */
66/* TODO: Should other actions that consumes the unit be considered?
67 * Join City may be an appealing alternative. Perhaps it should be a
68 * user configurable client option? */
70 ACTION_DISBAND_UNIT,
71 ACTION_DISBAND_UNIT_RECOVER,
72 ACTION_HELP_WONDER,
73};
74
75/* gui-dep code may adjust depending on tile size etc: */
77
78/* current_focus points to the current unit(s) in focus */
79static struct unit_list *current_focus = NULL;
80
81/* The previously focused unit(s). Focus can generally be recalled
82 * with keypad 5 (or the equivalent). */
83static struct unit_list *previous_focus = NULL;
84
85/* The priority unit(s) for unit_focus_advance(). */
86static struct unit_list *urgent_focus_queue = NULL;
87
88/* These should be set via set_hover_state() */
90enum unit_activity connect_activity;
92
96enum unit_orders goto_last_order; /* Last order for goto */
97
98static struct tile *hover_tile = NULL;
99static struct unit_list *battlegroups[MAX_NUM_BATTLEGROUPS];
100
101/* Current moving unit. */
102static struct unit *punit_moving = NULL;
103
104/* units involved in current combat */
105static struct unit *punit_attacking = NULL;
106static struct unit *punit_defending = NULL;
107
108/* The ID of the unit that currently is in the action selection process.
109 *
110 * The action selection process begins when the client asks the server what
111 * actions a unit can take. It ends when the last follow up question is
112 * answered.
113 *
114 * No common client code using client supports more than one action
115 * selection process at once. The interface between the common client code
116 * and the clients would have to change before that could happen. (See
117 * action_selection_actor_unit() etc)
118 */
120
121/*
122 * This variable is TRUE iff a NON-AI controlled unit was focused this
123 * turn.
124 */
126
127static void key_unit_gen_clean(enum unit_activity act, enum extra_rmcause rmcause);
128
129/*************************************************************************/
130
131static struct unit *quickselect(struct tile *ptile,
132 enum quickselect_type qtype);
133
134/**********************************************************************/
137void control_init(void)
138{
139 int i;
140
141 current_focus = unit_list_new();
142 previous_focus = unit_list_new();
143 urgent_focus_queue = unit_list_new();
144
145 for (i = 0; i < MAX_NUM_BATTLEGROUPS; i++) {
146 battlegroups[i] = unit_list_new();
147 }
148 hover_tile = NULL;
149}
150
151/**********************************************************************/
154void control_free(void)
155{
156 int i;
157
158 unit_list_destroy(current_focus);
159 current_focus = NULL;
160 unit_list_destroy(previous_focus);
161 previous_focus = NULL;
162 unit_list_destroy(urgent_focus_queue);
163 urgent_focus_queue = NULL;
164
165 for (i = 0; i < MAX_NUM_BATTLEGROUPS; i++) {
166 unit_list_destroy(battlegroups[i]);
167 battlegroups[i] = NULL;
168 }
169
172}
173
174/**********************************************************************/
177struct unit_list *get_units_in_focus(void)
178{
179 return current_focus;
180}
181
182/**********************************************************************/
186{
187 return (NULL != current_focus ? unit_list_size(current_focus) : 0);
188}
189
190/**********************************************************************/
194static void store_previous_focus(void)
195{
196 if (get_num_units_in_focus() > 0) {
197 unit_list_clear(previous_focus);
199 unit_list_append(previous_focus, punit);
201 }
202}
203
204/**********************************************************************/
208{
209 unit_list_append(urgent_focus_queue, punit);
210}
211
212/**********************************************************************/
215static void focus_units_changed(void)
216{
218 menus_update();
219 /* Notify the GUI */
221}
222
223/**********************************************************************/
227{
228 int i;
229
231
233 && get_num_units_in_focus() == 1) {
235 }
236
237 unit_list_remove(get_units_in_focus(), punit);
238 if (get_num_units_in_focus() < 1) {
240 }
241
242 unit_list_remove(previous_focus, punit);
243 unit_list_remove(urgent_focus_queue, punit);
244
245 for (i = 0; i < MAX_NUM_BATTLEGROUPS; i++) {
246 unit_list_remove(battlegroups[i], punit);
247 }
248
250}
251
252/**********************************************************************/
255void unit_change_battlegroup(struct unit *punit, int battlegroup)
256{
257 if (battlegroup < 0 || battlegroup >= MAX_NUM_BATTLEGROUPS) {
258 battlegroup = BATTLEGROUP_NONE;
259 }
260
261 if (punit->battlegroup != battlegroup) {
262 if (battlegroup != BATTLEGROUP_NONE) {
263 unit_list_append(battlegroups[battlegroup], punit);
264 }
266 unit_list_remove(battlegroups[punit->battlegroup], punit);
267 }
268 punit->battlegroup = battlegroup;
269 }
270}
271
272/**********************************************************************/
276{
279 } else {
280 unit_list_append(battlegroups[punit->battlegroup], punit);
281 }
282}
283
284/**********************************************************************/
290void set_hover_state(struct unit_list *punits, enum cursor_hover_state state,
291 enum unit_activity activity,
292 struct extra_type *tgt,
293 int last_tgt,
294 int last_sub_tgt,
296 enum unit_orders order)
297{
298 fc_assert_ret((punits && unit_list_size(punits) > 0)
299 || state == HOVER_NONE);
300 fc_assert_ret(state == HOVER_CONNECT || activity == ACTIVITY_LAST);
301 fc_assert_ret((state == HOVER_GOTO || state == HOVER_GOTO_SEL_TGT)
302 || order == ORDER_LAST);
303 fc_assert_ret((state == HOVER_GOTO || state == HOVER_GOTO_SEL_TGT)
304 || action == ACTION_NONE);
305
307 && (state == HOVER_GOTO || state == HOVER_GOTO_SEL_TGT))) {
308 /* Exit goto unless this is a switch between goto states */
310 }
311
312 hover_state = state;
313 connect_activity = activity;
314 if (tgt) {
315 connect_tgt = tgt;
316 } else {
317 connect_tgt = NULL;
318 }
319 goto_last_order = order;
321 goto_last_tgt = last_tgt;
322 goto_last_sub_tgt = last_sub_tgt;
323}
324
325/**********************************************************************/
329{
331 ACTIVITY_LAST, NULL,
333}
334
335/**********************************************************************/
340{
341 return (punit->action_decision_want == ACT_DEC_ACTIVE
342 /* The player is interested in getting a pop up for a mere
343 * arrival. */
344 || (punit->action_decision_want == ACT_DEC_PASSIVE
346}
347
348/**********************************************************************/
353{
354 /* OK as long as no other unit already asked and aren't done yet. */
357}
358
359/**********************************************************************/
367{
370
371 /* Only one action selection dialog at a time is supported. */
373 "Unit %d started action selection before unit %d was done",
376
378 punit->id, punit->id,
384}
385
386/**********************************************************************/
389bool unit_is_in_focus(const struct unit *punit)
390{
391 return unit_list_search(get_units_in_focus(), punit) != NULL;
392}
393
394/**********************************************************************/
397struct unit *get_focus_unit_on_tile(const struct tile *ptile)
398{
400 if (unit_tile(punit) == ptile) {
401 return punit;
402 }
404
405 return NULL;
406}
407
408/**********************************************************************/
412{
413 return unit_list_get(current_focus, 0);
414}
415
416/**********************************************************************/
420{
421 struct unit *punit;
422
424 return unit_tile(punit);
425 } else if (get_num_units_in_focus() > 0) {
427 } else {
428 return NULL;
429 }
430}
431
432/**********************************************************************/
436{
438
442 }
443}
444
445/**********************************************************************/
464
465/**********************************************************************/
468static void current_focus_remove(struct unit *punit)
469{
470 /* Close the action selection dialog if the actor unit lose focus. */
473 }
474
475 unit_list_remove(current_focus, punit);
477}
478
479/**********************************************************************/
483{
484 if (!punit) {
485 return;
486 }
487
488 if (punit->activity != ACTIVITY_IDLE
489 || punit->ssa_controller != SSA_NONE) {
490 punit->ssa_controller = SSA_NONE;
492 request_new_unit_activity(punit, ACTIVITY_IDLE);
493 } else if (unit_has_orders(punit)) {
494 /* Clear the focus unit's orders. */
496 }
497}
498
499/**********************************************************************/
508{
509 bool focus_changed = FALSE;
510
511 if (NULL != punit
512 && NULL != client.conn.playing
514 /* Callers should make sure this never happens. */
515 return;
516 }
517
518 /* FIXME: This won't work quite right; for instance activating a
519 * battlegroup twice in a row will store the focus erroneously. The only
520 * solution would be a set_units_focus() */
521 if (!(get_num_units_in_focus() == 1
522 && punit == head_of_units_in_focus())) {
524 focus_changed = TRUE;
525 }
526
527 /* Close the action selection dialog if the actor unit lose focus. */
528 unit_list_iterate(current_focus, punit_old) {
529 if (action_selection_actor_unit() == punit_old->id) {
531 }
533
534 /* Redraw the old focus unit (to fix blinking or remove the selection
535 * circle). */
536 unit_list_iterate(current_focus, punit_old) {
537 refresh_unit_mapcanvas(punit_old, unit_tile(punit_old), TRUE, FALSE);
539 unit_list_clear(current_focus);
540
541 if (!can_client_change_view()) {
542 /* This function can be called to set the focus to NULL when
543 * disconnecting. In this case we don't want any other actions! */
544 fc_assert(punit == NULL);
545 return;
546 }
547
548 if (NULL != punit) {
551 }
552
553 if (focus_changed) {
556 }
557}
558
559/**********************************************************************/
563{
564 if (NULL != punit
565 && NULL != client.conn.playing
567 /* Callers should make sure this never happens. */
568 return;
569 }
570
571 if (NULL == punit || !can_client_change_view()) {
572 return;
573 }
574
575 if (unit_is_in_focus(punit)) {
576 return;
577 }
578
579 if (hover_state != HOVER_NONE) {
580 /* Can't continue with current goto if set of focus units
581 * change. Cancel it. */
583 }
584
587}
588
589/**********************************************************************/
593{
594 bool keep_in_focus = FALSE;
595
596 if (NULL != punit
597 && NULL != client.conn.playing
599 /* Callers should make sure this never happens. */
600 return;
601 }
602
603 if (NULL == punit || !can_client_change_view()) {
604 return;
605 }
606
607 if (!unit_is_in_focus(punit)) {
608 return;
609 }
610
611 if (hover_state != HOVER_NONE) {
612 /* Can't continue with current goto if set of focus units
613 * change. Cancel it. */
615 }
616
617 if (get_num_units_in_focus() == 1) {
619
620 if (unit_is_in_focus(punit)) {
621 /* Unit was restored to focus (there was no other units to focus to) */
622 keep_in_focus = TRUE;
623 }
624 }
625
626 if (!keep_in_focus) {
628 if (get_num_units_in_focus() > 0) {
630 }
631 }
632}
633
634/**********************************************************************/
644
645/**********************************************************************/
650static struct unit *find_best_focus_candidate(bool accept_current)
651{
652 struct tile *ptile = get_center_tile_mapcanvas();
653
654 if (!get_focus_unit_on_tile(ptile)) {
655 struct unit *pfirst = head_of_units_in_focus();
656
657 if (pfirst) {
658 ptile = unit_tile(pfirst);
659 }
660 }
661
662 iterate_outward(&(wld.map), ptile, FC_INFINITY, ptile2) {
663 unit_list_iterate(ptile2->units, punit) {
664 if ((!unit_is_in_focus(punit) || accept_current)
667 && punit->activity == ACTIVITY_IDLE
669 && (punit->moves_left > 0 || unit_type_get(punit)->move_rate == 0)
670 && !punit->done_moving
671 && punit->ssa_controller == SSA_NONE) {
672 return punit;
673 }
676
677 return NULL;
678}
679
680/**********************************************************************/
689void unit_focus_advance(bool accept_current)
690{
691 struct unit *candidate = NULL;
692 const int num_units_in_old_focus = get_num_units_in_focus();
693
694 if (NULL == client.conn.playing
697 unit_focus_set(NULL);
698 return;
699 }
700
702
704 /*
705 * Is the unit which just lost focus a non-AI unit? If yes this
706 * enables the auto end turn.
707 */
708 if (punit->ssa_controller == SSA_NONE) {
710 break;
711 }
713
714 if (unit_list_size(urgent_focus_queue) > 0) {
715 /* Try top of the urgent list. */
716 struct tile *focus_tile = (get_num_units_in_focus() > 0
718 : NULL);
719
721 if ((ACTIVITY_IDLE != punit->activity
723 /* This isn't an action decision needed because of an
724 * ORDER_ACTION_MOVE located in the middle of an order. */
726 /* We have assigned new orders to this unit since, remove it. */
727 unit_list_remove(urgent_focus_queue, punit);
728 } else if (NULL == focus_tile
729 || focus_tile == unit_tile(punit)) {
730 /* Use the first one found */
731 candidate = punit;
732 break;
733 } else if (NULL == candidate) {
734 candidate = punit;
735 }
737
738 if (NULL != candidate) {
739 unit_list_remove(urgent_focus_queue, candidate);
740
741 /* Autocenter on Wakeup, regardless of the local option
742 * "auto_center_on_unit". */
745 }
746 }
747 }
748
749 if (NULL == candidate) {
750 candidate = find_best_focus_candidate(FALSE);
751
752 if (!candidate) {
753 /* Try for "waiting" units. */
757 }
759 candidate = find_best_focus_candidate(FALSE);
760
761 if (!candidate && accept_current) {
762 /* Accept current focus unit as last resort. */
763 candidate = find_best_focus_candidate(TRUE);
764 }
765 }
766 }
767
768 unit_focus_set(candidate);
769
770 /*
771 * Handle auto-turn-done mode: If a unit was in focus (did move),
772 * but now none are (no more to move) and there was at least one
773 * non-AI unit this turn which was focused, then fake a Turn Done
774 * keypress.
775 */
777 && num_units_in_old_focus > 0
778 && get_num_units_in_focus() == 0
780 key_end_turn();
781 }
782}
783
784/**********************************************************************/
791{
792 if (NULL == client.conn.playing || !can_client_change_view()) {
793 return;
794 }
795
798
799 /* An actor unit is asking the player what to do. Don't change the
800 * focus. */
801 return;
802 }
803
804 /* iterate zero times for no units in focus,
805 * otherwise quit for any of the conditions. */
807 if ((punit->activity == ACTIVITY_IDLE
808 || punit->activity == ACTIVITY_GOTO
810 && punit->moves_left > 0
811 && !punit->done_moving
812 && punit->ssa_controller == SSA_NONE) {
813 return;
814 }
816
818}
819
820/**********************************************************************/
823struct unit *find_visible_unit(struct tile *ptile)
824{
825 struct unit *panyowned = NULL, *panyother = NULL, *ptptother = NULL;
826
827 /* If no units here, return nothing. */
828 if (unit_list_size(ptile->units) == 0) {
829 return NULL;
830 }
831
832 /* If a unit is attacking we should show that on top */
834 unit_list_iterate(ptile->units, punit) {
835 if (punit == punit_attacking) {
836 return punit;
837 }
839 }
840
841 /* If a unit is defending we should show that on top */
843 unit_list_iterate(ptile->units, punit) {
844 if (punit == punit_defending) {
845 return punit;
846 }
848 }
849
850 /* If the unit in focus is at this tile, show that on top */
852 if (punit != punit_moving && unit_tile(punit) == ptile) {
853 return punit;
854 }
856
857 /* If a city is here, return nothing (unit hidden by city). */
858 if (tile_city(ptile)) {
859 return NULL;
860 }
861
862 /* Iterate through the units to find the best one we prioritize this way:
863 1: owned transporter.
864 2: any owned unit
865 3: any transporter
866 4: any unit
867 (always return first in stack). */
870 if (!unit_transported(punit)) {
872 return punit;
873 } else if (!panyowned) {
874 panyowned = punit;
875 }
876 }
877 } else if (!ptptother && !unit_transported(punit)) {
879 ptptother = punit;
880 } else if (!panyother) {
881 panyother = punit;
882 }
883 }
885
886 return (panyowned ? panyowned : (ptptother ? ptptother : panyother));
887}
888
889/**********************************************************************/
894{
895 static struct timer *blink_timer = NULL;
896 const double blink_time = get_focus_unit_toggle_timeout(tileset);
897
898 if (get_num_units_in_focus() > 0) {
899 if (!blink_timer || timer_read_seconds(blink_timer) > blink_time) {
901
902 /* If we lag, we don't try to catch up. Instead we just start a
903 * new blink_time on every update. */
904 blink_timer = timer_renew(blink_timer, TIMER_USER, TIMER_ACTIVE);
905 timer_start(blink_timer);
906
908 /* We used to unqueue here, but that's inherently risky
909 * for a function run from a timer - the UI can be in any
910 * inconsistent state. */
913 }
914
915 return blink_time - timer_read_seconds(blink_timer);
916 }
917
918 return blink_time;
919}
920
921/**********************************************************************/
926{
927 static struct timer *blink_timer = NULL;
928 const double blink_time = 0.5; /* half-second blink interval */
929
930 if (NULL != client.conn.playing
934 if (!blink_timer || timer_read_seconds(blink_timer) > blink_time) {
935 int is_waiting = 0, is_moving = 0;
936 bool blocking_mode;
937 struct option *opt;
938
939 opt = optset_option_by_name(server_optset, "turnblock");
940 if (opt != NULL) {
941 blocking_mode = option_bool_get(opt);
942 } else {
943 blocking_mode = FALSE;
944 }
945
946 players_iterate_alive(pplayer) {
947 if ((pplayer->is_connected || blocking_mode)
948 && is_player_phase(pplayer, game.info.phase)) {
949 if (pplayer->phase_done) {
950 is_waiting++;
951 } else {
952 is_moving++;
953 }
954 }
956
957 if (is_moving == 1 && is_waiting > 0) {
958 update_turn_done_button(FALSE); /* stress the slow player! */
959 }
960 blink_timer = timer_renew(blink_timer, TIMER_USER, TIMER_ACTIVE);
961 timer_start(blink_timer);
962 }
963 return blink_time - timer_read_seconds(blink_timer);
964 }
965
966 return blink_time;
967}
968
969/**********************************************************************/
984void update_unit_pix_label(struct unit_list *punitlist)
985{
986 int i;
987
988 /* Check for any change in the unit's state. This assumes that a unit's
989 * orders cannot be changed directly but must be removed and then reset. */
990 if (punitlist && unit_list_size(punitlist) > 0
991 && C_S_OVER != client_state()) {
992 /* There used to be a complicated and bug-prone check here to see if
993 * the unit had actually changed. This was misguided since the stacked
994 * units (below) are redrawn in any case. Unless we write a general
995 * system for unit updates here we might as well just redraw it every
996 * time. */
997 struct unit *punit = unit_list_get(punitlist, 0);
998
999 set_unit_icon(-1, punit);
1000
1001 i = 0; /* index into unit_below_canvas */
1002 unit_list_iterate(unit_tile(punit)->units, aunit) {
1003 if (aunit != punit) {
1004 if (i < num_units_below) {
1005 set_unit_icon(i, aunit);
1006 }
1007 i++;
1008 }
1009 }
1011
1012 if (i > num_units_below) {
1014 } else {
1016 for (; i < num_units_below; i++) {
1017 set_unit_icon(i, NULL);
1018 }
1019 }
1020 } else {
1021 for (i = -1; i < num_units_below; i++) {
1022 set_unit_icon(i, NULL);
1023 }
1025 }
1026}
1027
1028/**********************************************************************/
1031void set_units_in_combat(struct unit *pattacker, struct unit *pdefender)
1032{
1033 punit_attacking = pattacker;
1034 punit_defending = pdefender;
1035
1038 /* If one of the units is the focus unit, make sure hidden-focus is
1039 * disabled. We don't just do this as a check later because then
1040 * with a blinking unit it would just disappear again right after the
1041 * battle. */
1043 }
1044}
1045
1046/**********************************************************************/
1050void action_selection_no_longer_in_progress(const int old_actor_id)
1051{
1052 struct unit *old_actor_unit;
1053
1054 /* IDENTITY_NUMBER_ZERO is accepted for cases where the unit is gone
1055 * without a trace. */
1057 || old_actor_id == IDENTITY_NUMBER_ZERO
1059 "Decision taken for %d but selection is for %d.",
1060 old_actor_id, action_selection_in_progress_for);
1061
1062 old_actor_unit = game_unit_by_number(old_actor_id);
1063 if (old_actor_unit != NULL
1064 && old_actor_unit->client.act_prob_cache != NULL) {
1065 FC_FREE(old_actor_unit->client.act_prob_cache);
1066 }
1067
1068 /* Stop objecting to allowing the next unit to ask. */
1070
1071 /* Clean up any client specific assumptions. */
1073}
1074
1075/**********************************************************************/
1079void action_decision_clear_want(const int old_actor_id)
1080{
1081 if (game_unit_by_number(old_actor_id) != NULL) {
1082 /* Have the server record that a decision no longer is wanted. */
1083 dsend_packet_unit_sscs_set(&client.conn, old_actor_id, old_actor_id,
1084 USSDT_UNQUEUE, IDENTITY_NUMBER_ZERO);
1085 }
1086}
1087
1088/**********************************************************************/
1091void action_selection_next_in_focus(const int old_actor_id)
1092{
1093 struct unit *old;
1094
1095 old = game_unit_by_number(old_actor_id);
1096
1097 /* Go to the next unit in focus that needs a decision. */
1099 if (old != funit && should_ask_server_for_actions(funit)) {
1101 return;
1102 }
1104}
1105
1106/**********************************************************************/
1110{
1113
1115 /* Getting feed back may be urgent. A unit standing next to an enemy
1116 * could be killed while waiting. */
1118 } else if (can_client_issue_orders()
1120 /* No need to wait. The actor unit is in focus. No other actor unit
1121 * is currently asking about action selection. */
1123 }
1124}
1125
1126/**********************************************************************/
1129void request_unit_goto(enum unit_orders last_order,
1130 action_id act_id, int sub_tgt_id)
1131{
1132 struct unit_list *punits = get_units_in_focus();
1133
1134 fc_assert_ret(act_id == ACTION_NONE
1135 || last_order == ORDER_PERFORM_ACTION);
1136
1137 if (unit_list_size(punits) == 0) {
1138 return;
1139 }
1140
1141 if (last_order == ORDER_PERFORM_ACTION) {
1142 /* An action has been specified. */
1144
1145 unit_list_iterate(punits, punit) {
1146 if (!unit_can_do_action(punit, act_id)) {
1147 /* This unit can't perform the action specified in the last
1148 * order. */
1149
1150 struct astring astr = ASTRING_INIT;
1151
1152 if (role_units_translations(&astr,
1153 action_id_get_role(act_id),
1154 TRUE)) {
1155 /* ...but other units can perform it. */
1156
1157 create_event(unit_tile(punit), E_BAD_COMMAND, ftc_client,
1158 /* TRANS: Only Nuclear or ICBM can do Explode
1159 * Nuclear. */
1160 _("Only %s can do %s."),
1161 astr_str(&astr),
1163
1164 astr_free(&astr);
1165 } else {
1166 create_event(unit_tile(punit), E_BAD_COMMAND, ftc_client,
1167 /* TRANS: Spy can't do Explode Nuclear. */
1168 _("%s can't do %s."),
1171 }
1172
1173 return;
1174 }
1176 }
1177
1179 set_hover_state(punits, HOVER_GOTO, ACTIVITY_LAST, NULL,
1180 NO_TARGET, sub_tgt_id, act_id, last_order);
1181 enter_goto_state(punits);
1183 update_unit_info_label(punits);
1185 } else {
1187 /* Adding a long range action in the middle isn't handled yet */
1190 }
1191}
1192
1193/**********************************************************************/
1196static bool can_units_attack_at(struct unit_list *punits,
1197 const struct tile *ptile)
1198{
1199 unit_list_iterate(punits, punit) {
1201 && can_unit_attack_tile(punit, NULL, ptile)) {
1202 return TRUE;
1203 }
1205
1206 return FALSE;
1207}
1208
1209/**********************************************************************/
1214void control_mouse_cursor(struct tile *ptile)
1215{
1216 struct unit *punit = NULL;
1217 struct city *pcity = NULL;
1218 struct unit_list *active_units = get_units_in_focus();
1220
1222 return;
1223 }
1224
1225 if (C_S_RUNNING != client_state()) {
1227 return;
1228 }
1229
1230 if (is_server_busy()) {
1231 /* Server will not accept any commands. */
1233 return;
1234 }
1235
1236 if (!ptile) {
1237 if (hover_tile) {
1238 /* hover_tile is the tile that was previously under the mouse cursor. */
1239 ptile = hover_tile;
1240 } else {
1242 return;
1243 }
1244 } else {
1245 hover_tile = ptile;
1246 }
1247
1248 punit = find_visible_unit(ptile);
1249 pcity = ptile ? tile_city(ptile) : NULL;
1250
1251 switch (hover_state) {
1252 case HOVER_NONE:
1253 if (NULL != punit
1254 && unit_owner(punit) == client_player()) {
1255 /* Set mouse cursor to select a unit. */
1257 } else if (NULL != pcity
1259 /* Set mouse cursor to select a city. */
1261 } else {
1262 /* Set default mouse cursor, because nothing selectable found. */
1263 }
1264 break;
1265 case HOVER_GOTO:
1266 /* Determine if the goto is valid, invalid, nuke or will attack. */
1267 if (is_valid_goto_destination(ptile)) {
1268 if (action_id_has_result_safe(goto_last_action, ACTRES_NUKE_UNITS)
1270 /* Goto results in nuclear attack. */
1272 } else if (can_units_attack_at(active_units, ptile)) {
1273 /* Goto results in military attack. */
1275 } else if (is_enemy_city_tile(ptile, client.conn.playing)) {
1276 /* Goto results in attack of enemy city. */
1278 } else {
1280 }
1281 } else {
1283 }
1284 break;
1285 case HOVER_PATROL:
1286 if (is_valid_goto_destination(ptile)) {
1288 } else {
1290 }
1291 break;
1292 case HOVER_CONNECT:
1293 if (is_valid_goto_destination(ptile)) {
1295 } else {
1297 }
1298 break;
1299 case HOVER_PARADROP:
1300 /* FIXME: check for invalid tiles. */
1302 break;
1303 case HOVER_ACT_SEL_TGT:
1304 case HOVER_GOTO_SEL_TGT:
1305 /* Select a tile to target / find targets on. */
1307 break;
1308 };
1309
1311}
1312
1313/**********************************************************************/
1316static bool is_activity_on_tile(struct tile *ptile,
1317 enum unit_activity activity)
1318{
1319 unit_list_iterate(ptile->units, punit) {
1320 if (punit->activity == activity) {
1321 return TRUE;
1322 }
1324
1325 return FALSE;
1326}
1327
1328/**********************************************************************/
1333 const struct extra_type *pextra,
1334 const struct unit *punit,
1335 const struct player *pplayer, int rec)
1336{
1337 int activity_mc = 0;
1338 struct terrain *pterrain = tile_terrain(ptile);
1339 const struct civ_map *nmap = &(wld.map);
1340
1341 if (rec > MAX_EXTRA_TYPES) {
1342 return -1;
1343 }
1344
1345 if (!is_extra_caused_by(pextra, EC_ROAD)) {
1346 return -1;
1347 }
1348
1349 extra_deps_iterate(&(pextra->reqs), pdep) {
1350 if (!tile_has_extra(ptile, pdep)) {
1351 int single_mc;
1352
1353 single_mc = check_recursive_road_connect(ptile, pdep, punit,
1354 pplayer, rec + 1);
1355
1356 if (single_mc < 0) {
1357 return -1;
1358 }
1359
1360 activity_mc += single_mc;
1361 }
1363
1364 /* Can build road after that? */
1365 if (punit != NULL) {
1366 if (!can_build_road(nmap, extra_road_get(pextra), punit, ptile)) {
1367 return -1;
1368 }
1369 } else if (pplayer != NULL) {
1370 if (!player_can_build_road(nmap, extra_road_get(pextra),
1371 pplayer, ptile)) {
1372 return -1;
1373 }
1374 }
1375
1376 tile_add_extra(ptile, pextra);
1377
1378 activity_mc += terrain_extra_build_time(pterrain, ACTIVITY_GEN_ROAD, pextra);
1379
1380 return activity_mc;
1381}
1382
1383/*******************************************************************/
1387static bool can_be_irrigated(const struct tile *ptile,
1388 const struct unit *punit)
1389{
1390 struct terrain* pterrain = tile_terrain(ptile);
1391 struct universal for_unit = { .kind = VUT_UTYPE,
1392 .value.utype = unit_type_get(punit)};
1393 struct universal for_tile = { .kind = VUT_TERRAIN,
1394 .value.terrain = tile_terrain(ptile)};
1395
1396 if (T_UNKNOWN == pterrain) {
1397 return FALSE;
1398 }
1399
1400 return action_id_univs_not_blocking(ACTION_IRRIGATE,
1401 &for_unit, &for_tile);
1402}
1403
1404/**********************************************************************/
1411 enum unit_activity activity,
1412 struct extra_type *tgt)
1413{
1414 struct tile *ptile = unit_tile(punit);
1415 struct road_type *proad = NULL;
1416 const struct req_context unit_ctxt = {
1417 .unit = punit,
1418 .unittype = unit_type_get(punit),
1419 };
1420
1421 /* HACK: This code duplicates that in
1422 * can_unit_do_activity_targeted_at(). The general logic here is that
1423 * the connect is allowed if both:
1424 * (1) the unit can do that activity type, in general
1425 * (2) either
1426 * (a) the activity has already been completed at this tile
1427 * (b) it can be done by the unit at this tile. */
1428 switch (activity) {
1429 case ACTIVITY_GEN_ROAD:
1430 {
1431 struct tile *vtile;
1432 int build_time;
1433
1434 fc_assert(is_extra_caused_by(tgt, EC_ROAD));
1435
1436 proad = extra_road_get(tgt);
1437
1438 if (tile_has_road(ptile, proad)) {
1439 /* This tile has road, can unit build road to other tiles too? */
1440 return are_reqs_active(&unit_ctxt, NULL, &tgt->reqs, RPT_POSSIBLE);
1441 }
1442
1443 /* To start connect, unit must be able to build road to this
1444 * particular tile. */
1445 vtile = tile_virtual_new(ptile);
1446 build_time = check_recursive_road_connect(vtile, tgt, punit, NULL, 0);
1447 tile_virtual_destroy(vtile);
1448
1449 return build_time >= 0;
1450 }
1451
1452 case ACTIVITY_IRRIGATE:
1453 /* Special case for irrigation: only irrigate to make S_IRRIGATION,
1454 * never to transform tiles. */
1455 if (!unit_has_type_flag(punit, UTYF_SETTLERS)) {
1456 return FALSE;
1457 }
1458 if (tile_has_extra(ptile, tgt)) {
1459 return are_reqs_active(&unit_ctxt, NULL, &tgt->reqs, RPT_POSSIBLE);
1460 }
1461
1462 return can_be_irrigated(ptile, punit)
1463 && can_build_extra(tgt, punit, ptile)
1464 && !is_activity_on_tile(ptile,
1465 ACTIVITY_MINE);
1466 default:
1467 break;
1468 }
1469
1470 return FALSE;
1471}
1472
1473/**********************************************************************/
1477void request_unit_connect(enum unit_activity activity,
1478 struct extra_type *tgt)
1479{
1480 struct unit_list *punits = get_units_in_focus();
1481
1482 if (!can_units_do_connect(punits, activity, tgt)) {
1483 return;
1484 }
1485
1486 if (hover_state != HOVER_CONNECT || connect_activity != activity
1487 || (connect_tgt != tgt
1488 && (activity == ACTIVITY_GEN_ROAD
1489 || activity == ACTIVITY_IRRIGATE))) {
1491 activity, tgt, NO_TARGET, NO_TARGET,
1493 enter_goto_state(punits);
1495 update_unit_info_label(punits);
1497 } else {
1500 }
1501}
1502
1503/**********************************************************************/
1507{
1508 struct tile *ptile = unit_tile(punit);
1509 struct unit *plast = NULL;
1510
1511 if (get_transporter_capacity(punit) == 0) {
1512 create_event(unit_tile(punit), E_BAD_COMMAND, ftc_client,
1513 _("Only transporter units can be unloaded."));
1514 return NULL;
1515 }
1516
1517 unit_list_iterate(ptile->units, pcargo) {
1518 if (unit_transport_get(pcargo) == punit) {
1519 request_unit_unload(pcargo);
1520
1521 if (pcargo->activity == ACTIVITY_SENTRY) {
1522 dsend_packet_unit_sscs_set(&client.conn, pcargo->id, pcargo->id,
1523 USSDT_SENTRY, 0);
1524 }
1525
1526 if (unit_owner(pcargo) == unit_owner(punit)) {
1527 plast = pcargo;
1528 }
1529 }
1531
1532 return plast;
1533}
1534
1535/**********************************************************************/
1538void request_unit_airlift(struct unit *punit, struct city *pcity)
1539{
1540 request_do_action(ACTION_AIRLIFT, punit->id, pcity->id, 0, "");
1541}
1542
1543/**********************************************************************/
1548{
1549 struct pf_path *path;
1550
1551 if ((path = path_to_nearest_allied_city(punit))) {
1552 int turns = pf_path_last_position(path)->turn;
1553 int max_hp = unit_type_get(punit)->hp;
1554
1555 if (punit->hp + turns *
1556 (get_unit_bonus(punit, EFT_UNIT_RECOVER)
1557 - (max_hp * unit_class_get(punit)->hp_loss_pct / 100))
1558 < max_hp) {
1559 struct unit_order order;
1560
1562 order.dir = DIR8_ORIGIN;
1563 order.activity = ACTIVITY_SENTRY;
1564 order.target = NO_TARGET;
1565 order.sub_target = NO_TARGET;
1566 order.action = ACTION_NONE;
1567 send_goto_path(punit, path, &order);
1568 } else {
1569 send_goto_path(punit, path, NULL);
1570 }
1571 pf_path_destroy(path);
1572 }
1573}
1574
1575/**********************************************************************/
1578void wakeup_sentried_units(struct tile *ptile)
1579{
1580 if (!can_client_issue_orders()) {
1581 return;
1582 }
1583 unit_list_iterate(ptile->units, punit) {
1584 if (punit->activity == ACTIVITY_SENTRY
1586 request_new_unit_activity(punit, ACTIVITY_IDLE);
1587 }
1588 }
1590}
1591
1592/**********************************************************************/
1599
1600/**************************************************************************
1601 Defines specific hash tables needed for request_unit_select().
1602**************************************************************************/
1603#define SPECHASH_TAG unit_type
1604#define SPECHASH_IKEY_TYPE struct unit_type *
1605#define SPECHASH_IDATA_TYPE void *
1606#include "spechash.h"
1607
1608#define SPECHASH_TAG continent
1609#define SPECHASH_INT_KEY_TYPE
1610#define SPECHASH_IDATA_TYPE void *
1611#include "spechash.h"
1612
1613/**********************************************************************/
1616void request_unit_select(struct unit_list *punits,
1617 enum unit_select_type_mode seltype,
1618 enum unit_select_location_mode selloc)
1619{
1620 const struct player *pplayer;
1621 const struct tile *ptile;
1622 struct unit *punit_first;
1623 struct tile_hash *tile_table;
1624 struct unit_type_hash *type_table;
1625 struct continent_hash *cont_table;
1626
1627 if (!can_client_change_view() || !punits
1628 || unit_list_size(punits) < 1) {
1629 return;
1630 }
1631
1632 punit_first = unit_list_get(punits, 0);
1633
1634 if (seltype == SELTYPE_SINGLE) {
1635 unit_focus_set(punit_first);
1636 return;
1637 }
1638
1639 pplayer = unit_owner(punit_first);
1640 tile_table = tile_hash_new();
1641 type_table = unit_type_hash_new();
1642 cont_table = continent_hash_new();
1643
1644 unit_list_iterate(punits, punit) {
1645 if (seltype == SELTYPE_SAME) {
1646 unit_type_hash_insert(type_table, unit_type_get(punit), NULL);
1647 }
1648
1649 ptile = unit_tile(punit);
1650 if (selloc == SELLOC_TILE) {
1651 tile_hash_insert(tile_table, ptile, NULL);
1652 } else if (selloc == SELLOC_CONT) {
1653 continent_hash_insert(cont_table, tile_continent(ptile), NULL);
1654 }
1656
1657 if (selloc == SELLOC_TILE) {
1658 tile_hash_iterate(tile_table, hash_tile) {
1659 unit_list_iterate(hash_tile->units, punit) {
1660 if (unit_owner(punit) != pplayer) {
1661 continue;
1662 }
1663 if (seltype == SELTYPE_SAME
1664 && !unit_type_hash_lookup(type_table, unit_type_get(punit), NULL)) {
1665 continue;
1666 }
1670 } else {
1671 unit_list_iterate(pplayer->units, punit) {
1672 ptile = unit_tile(punit);
1673 if ((seltype == SELTYPE_SAME
1674 && !unit_type_hash_lookup(type_table, unit_type_get(punit), NULL))
1675 || (selloc == SELLOC_CONT
1676 && !continent_hash_lookup(cont_table, tile_continent(ptile),
1677 NULL))) {
1678 continue;
1679 }
1680
1683 }
1684
1685 tile_hash_destroy(tile_table);
1686 unit_type_hash_destroy(type_table);
1687 continent_hash_destroy(cont_table);
1688}
1689
1690/**********************************************************************/
1702 int target_id, int sub_tgt, const char *name)
1703{
1704 struct unit *actor_unit = game_unit_by_number(actor_id);
1705
1706 /* Giving an order takes back control. */
1708
1710 actor_id, actor_id, target_id, sub_tgt, name,
1711 action);
1712}
1713
1714/**********************************************************************/
1722 int target_id)
1723{
1725 actor_id, actor_id, target_id, action,
1726 /* Users that need the answer in the
1727 * background should send the packet them
1728 * self. At least for now. */
1730}
1731
1732/**********************************************************************/
1741{
1742 struct city *pcity;
1743
1744 if ((pcity = tile_city(unit_tile(punit)))) {
1745 /* Try to join the city. */
1746 request_do_action(ACTION_JOIN_CITY, punit->id, pcity->id, 0, "");
1747 } else {
1748 /* The reply will trigger a dialog to name the new city. */
1750 }
1751}
1752
1753/**********************************************************************/
1760 struct tile *dest_tile)
1761{
1762 struct packet_unit_orders p;
1763 int dir;
1764
1766
1767 if (dir == -1) {
1768 /* The unit isn't located next to the destination tile. */
1769 return;
1770 }
1771
1772 memset(&p, 0, sizeof(p));
1773
1774 p.repeat = FALSE;
1775 p.vigilant = FALSE;
1776
1777 p.unit_id32 = punit->id;
1778 p.unit_id16 = p.unit_id32;
1781
1782 p.length = 1;
1783 p.orders[0].order = ORDER_MOVE;
1784 p.orders[0].dir = dir;
1785 p.orders[0].activity = ACTIVITY_LAST;
1786 p.orders[0].target = NO_TARGET;
1788 p.orders[0].action = ACTION_NONE;
1789
1790 request_unit_ssa_set(punit, SSA_NONE);
1792}
1793
1794/**********************************************************************/
1804{
1805 struct packet_unit_orders p;
1806 struct tile *dest_tile;
1807
1808 /* Catches attempts to move off map */
1809 dest_tile = mapstep(&(wld.map), unit_tile(punit), dir);
1810 if (!dest_tile) {
1811 return;
1812 }
1813
1814 if (!can_unit_exist_at_tile(&(wld.map), punit, dest_tile)) {
1815 if (request_transport(punit, dest_tile)) {
1816 return;
1817 }
1818 }
1819
1820 /* The goto system isn't used to send the order because that would
1821 * prevent direction movement from overriding it.
1822 * Example of a situation when overriding the goto system is useful:
1823 * The goto system creates a longer path to make a move legal. The player
1824 * wishes to order the illegal move so the server will explain why the
1825 * short move is illegal. */
1826
1827 memset(&p, 0, sizeof(p));
1828
1829 p.repeat = FALSE;
1830 p.vigilant = FALSE;
1831
1832 p.unit_id32 = punit->id;
1833 p.unit_id16 = p.unit_id32;
1835 p.dest_tile = tile_index(dest_tile);
1836
1837 p.length = 1;
1840 p.orders[0].dir = dir;
1841 p.orders[0].activity = ACTIVITY_LAST;
1842 p.orders[0].target = NO_TARGET;
1844 p.orders[0].action = ACTION_NONE;
1845
1846 request_unit_ssa_set(punit, SSA_NONE);
1848}
1849
1850/**********************************************************************/
1854void request_new_unit_activity(struct unit *punit, enum unit_activity act)
1855{
1857}
1858
1859/**********************************************************************/
1864 enum unit_activity act,
1865 struct extra_type *tgt)
1866{
1867 if (!can_client_issue_orders()) {
1868 return;
1869 }
1870
1871 /* Callers rely on this to take back control from server side agents. */
1872 request_unit_ssa_set(punit, SSA_NONE);
1873
1874 if (tgt == NULL) {
1876 act, EXTRA_NONE);
1877 } else {
1879 act, extra_index(tgt));
1880 }
1881}
1882
1883/**********************************************************************/
1887{
1888 struct client_disband_unit_data *data = p;
1889
1890 free(data);
1891}
1892
1893/**********************************************************************/
1896static void do_disband_alternative(void *p)
1897{
1898 struct unit *punit;
1899 struct city *pcity;
1900 struct tile *ptile;
1901 int last_request_id_used;
1902 struct client_disband_unit_data *next;
1903 struct client_disband_unit_data *data = p;
1904 int act;
1905 const struct civ_map *nmap = &(wld.map);
1906
1908
1909 /* Fetch the unit to get rid of. */
1911
1912 if (punit == NULL) {
1913 /* Success! It is gone. */
1914 return;
1915 }
1916
1917 if (data->alt == -1) {
1918 /* All alternatives have been tried. */
1919 create_event(unit_tile(punit), E_BAD_COMMAND, ftc_client,
1920 /* TRANS: Unable to get rid of Leader. */
1921 _("Unable to get rid of %s."),
1923 return;
1924 }
1925
1926 act = disband_unit_alternatives[data->alt];
1927
1928 /* Prepare the data for the next try in case this try fails. */
1929 next = fc_malloc(sizeof(struct client_disband_unit_data));
1930 next->unit_id = data->unit_id;
1931 next->alt = data->alt - 1;
1932
1933 /* Latest request ID before trying to send a request. */
1934 last_request_id_used = client.conn.client.last_request_id_used;
1935
1936 /* Send a request to the server unless it is known to be pointless. */
1937 switch (action_id_get_target_kind(act)) {
1938 case ATK_CITY:
1939 if ((pcity = tile_city(unit_tile(punit)))
1941 act, pcity))) {
1942 request_do_action(act, punit->id, pcity->id, 0, "");
1943 }
1944 break;
1945 case ATK_UNIT:
1947 request_do_action(act, punit->id, punit->id, 0, "");
1948 }
1949 break;
1950 case ATK_UNITS:
1951 if ((ptile = unit_tile(punit))
1952 && action_prob_possible(action_prob_vs_units(nmap, punit, act, ptile))) {
1953 request_do_action(act, punit->id, ptile->index, 0, "");
1954 }
1955 break;
1956 case ATK_TILE:
1957 if ((ptile = unit_tile(punit))
1959 ptile, NULL))) {
1960 request_do_action(act, punit->id, ptile->index, 0, "");
1961 }
1962 break;
1963 case ATK_EXTRAS:
1964 if ((ptile = unit_tile(punit))
1966 ptile, NULL))) {
1967 request_do_action(act, punit->id, ptile->index, 0, "");
1968 }
1969 break;
1970 case ATK_SELF:
1971 if (action_prob_possible(action_prob_self(nmap, punit, act))) {
1972 request_do_action(act, punit->id, punit->id, 0, "");
1973 }
1974 break;
1975 case ATK_COUNT:
1976 fc_assert(action_id_get_target_kind(act) != ATK_COUNT);
1977 break;
1978 }
1979
1980 if (last_request_id_used != client.conn.client.last_request_id_used) {
1981 /* A request was sent. */
1982
1983 /* Check if it worked. Move on if it didn't. */
1988 } else {
1989 /* No request was sent. */
1990
1991 /* Move on. */
1993
1994 /* Won't be freed by anyone else. */
1996 }
1997}
1998
1999/**********************************************************************/
2003{
2004 struct client_disband_unit_data *data;
2005
2006 /* Set up disband data. Start at the end of the array. */
2007 data = fc_malloc(sizeof(struct client_disband_unit_data));
2008 data->unit_id = punit->id;
2009 data->alt = 2;
2010
2011 /* Begin. */
2013
2014 /* Won't be freed by anyone else. */
2016}
2017
2018/**********************************************************************/
2022{
2023 struct city *pcity=tile_city(unit_tile(punit));
2024
2025 if (pcity) {
2026 request_do_action(ACTION_HOME_CITY, punit->id, pcity->id, 0, "");
2027 }
2028}
2029
2030/**********************************************************************/
2034{
2035 struct city *pcity=tile_city(unit_tile(punit));
2036
2037 if (pcity) {
2038 request_do_action(ACTION_UPGRADE_UNIT, punit->id, pcity->id, 0, "");
2039 }
2040}
2041
2042/**********************************************************************/
2046{
2047 request_new_unit_activity(punit, ACTIVITY_CONVERT);
2048}
2049
2050/**********************************************************************/
2056 enum server_side_agent agent)
2057{
2058 if (punit) {
2060 agent);
2061 }
2062}
2063
2064/**********************************************************************/
2069{
2071 request_unit_ssa_set(punit, SSA_AUTOSETTLER);
2072 } else if (punit) {
2073 create_event(unit_tile(punit), E_BAD_COMMAND, ftc_client,
2074 _("Only settler units can be put into auto mode."));
2075 }
2076}
2077
2078/**********************************************************************/
2083void request_unit_load(struct unit *pcargo, struct unit *ptrans,
2084 struct tile *ptile)
2085{
2086 if (!ptrans) {
2087 ptrans = transporter_for_unit(pcargo);
2088 }
2089
2090 if (ptrans
2092 && could_unit_load(pcargo, ptrans)) {
2094 same_pos(unit_tile(pcargo), ptile)
2095 ? ACTRES_TRANSPORT_BOARD
2096 : ACTRES_TRANSPORT_EMBARK) {
2097 if (action_prob_possible(action_prob_vs_unit(&(wld.map), pcargo, paction->id,
2098 ptrans))) {
2099 /* Try the first action that may be legal. */
2100 /* Implement something like do_disband_alternative() if a ruleset
2101 * appears where this isn't good enough. */
2102 request_do_action(paction->id, pcargo->id, ptrans->id, 0, "");
2103 break;
2104 }
2106
2107 /* Sentry the unit. */
2108 /* FIXME: Should not sentry if above loading fails (transport moved away,
2109 * or filled already in server side) */
2110 dsend_packet_unit_sscs_set(&client.conn, pcargo->id, pcargo->id,
2111 USSDT_SENTRY, 1);
2112 }
2113}
2114
2115/**********************************************************************/
2119void request_unit_unload(struct unit *pcargo)
2120{
2121 struct unit *ptrans = unit_transport_get(pcargo);
2122
2124 && ptrans
2125 && can_unit_unload(pcargo, ptrans)
2126 && can_unit_survive_at_tile(&(wld.map), pcargo, unit_tile(pcargo))) {
2127 if (unit_owner(pcargo) == client.conn.playing) {
2128 request_do_action(ACTION_TRANSPORT_ALIGHT,
2129 pcargo->id, ptrans->id, 0, "");
2130 } else {
2131 request_do_action(ACTION_TRANSPORT_UNLOAD,
2132 ptrans->id, pcargo->id, 0, "");
2133 }
2134
2135 if (unit_owner(pcargo) == client.conn.playing
2136 && pcargo->activity == ACTIVITY_SENTRY) {
2137 /* Activate the unit. */
2138 dsend_packet_unit_sscs_set(&client.conn, pcargo->id, pcargo->id,
2139 USSDT_SENTRY, 0);
2140 }
2141 }
2142}
2143
2144/**********************************************************************/
2149{
2150 struct city *target_city;
2151
2152 if (!((target_city = tile_city(unit_tile(punit))))) {
2153 return;
2154 }
2155
2156 if (action == ACTION_TRADE_ROUTE) {
2157 request_do_action(ACTION_TRADE_ROUTE, punit->id,
2158 target_city->id, 0, "");
2159 } else if (action == ACTION_HELP_WONDER) {
2160 request_do_action(ACTION_HELP_WONDER, punit->id,
2161 target_city->id, 0, "");
2162 } else {
2163 log_error("request_unit_caravan_action() Bad action (%d)", action);
2164 }
2165}
2166
2167/**********************************************************************/
2171void request_unit_paradrop(struct unit_list *punits)
2172{
2173 bool can = FALSE;
2174 struct tile *offender = NULL;
2175
2176 if (unit_list_size(punits) == 0) {
2177 return;
2178 }
2179 unit_list_iterate(punits, punit) {
2180 if (can_unit_paradrop(&(wld.map), punit)) {
2181 can = TRUE;
2182 break;
2183 }
2184 if (!offender) { /* Take first offender tile/unit */
2185 offender = unit_tile(punit);
2186 }
2188 if (can) {
2189 create_event(unit_tile(unit_list_get(punits, 0)), E_BEGINNER_HELP,
2190 ftc_client,
2191 /* TRANS: paradrop target tile. */
2192 _("Click on a tile to paradrop to it."));
2193
2194 set_hover_state(punits, HOVER_PARADROP, ACTIVITY_LAST, NULL,
2196 update_unit_info_label(punits);
2197 } else {
2198 create_event(offender, E_BAD_COMMAND, ftc_client,
2199 _("Only paratrooper units can do this."));
2200 }
2201}
2202
2203/**********************************************************************/
2207{
2208 struct unit_list *punits = get_units_in_focus();
2209
2210 if (unit_list_size(punits) == 0) {
2211 return;
2212 }
2213
2214 if (hover_state != HOVER_PATROL) {
2215 set_hover_state(punits, HOVER_PATROL, ACTIVITY_LAST, NULL,
2217 update_unit_info_label(punits);
2218 enter_goto_state(punits);
2220 } else {
2223 }
2224}
2225
2226/**********************************************************************/
2230{
2231 if (punit->activity != ACTIVITY_SENTRY
2232 && can_unit_do_activity_client(punit, ACTIVITY_SENTRY)) {
2233 request_new_unit_activity(punit, ACTIVITY_SENTRY);
2234 }
2235}
2236
2237/**********************************************************************/
2241{
2242 if (punit->activity != ACTIVITY_FORTIFYING
2243 && can_unit_do_activity_client(punit, ACTIVITY_FORTIFYING)) {
2244 request_new_unit_activity(punit, ACTIVITY_FORTIFYING);
2245 }
2246}
2247
2248/**********************************************************************/
2252{
2253 if (!game.info.pillage_select) {
2254 /* Leave choice up to the server */
2255 request_new_unit_activity_targeted(punit, ACTIVITY_PILLAGE, NULL);
2256 } else {
2257 bv_extras pspossible;
2258 int count = 0;
2259
2260 BV_CLR_ALL(pspossible);
2261 extra_type_iterate(potential) {
2262 if (can_unit_do_activity_targeted_client(punit, ACTIVITY_PILLAGE,
2263 potential)) {
2264 BV_SET(pspossible, extra_index(potential));
2265 count++;
2266 }
2268
2269 if (count > 1) {
2270 popup_pillage_dialog(punit, pspossible);
2271 } else {
2272 /* Should be only one choice... */
2273 struct extra_type *target = get_preferred_pillage(pspossible);
2274
2275 if (target != NULL) {
2276 request_new_unit_activity_targeted(punit, ACTIVITY_PILLAGE, target);
2277 }
2278 }
2279 }
2280}
2281
2282/**********************************************************************/
2294
2295/**********************************************************************/
2307
2308/**********************************************************************/
2312{
2313 if (!can_client_change_view()) {
2314 return;
2315 }
2316
2319}
2320
2321/**********************************************************************/
2325{
2326 if (!can_client_change_view()) {
2327 return;
2328 }
2329
2332}
2333
2334/**********************************************************************/
2338{
2339 if (!can_client_change_view()) {
2340 return;
2341 }
2342
2345}
2346
2347/**********************************************************************/
2351{
2352 if (!can_client_change_view()) {
2353 return;
2354 }
2355
2358}
2359
2360/**********************************************************************/
2364{
2365 if (!can_client_change_view()) {
2366 return;
2367 }
2368
2371}
2372
2373/**********************************************************************/
2377{
2378 if (!can_client_change_view()) {
2379 return;
2380 }
2381
2384}
2385
2386/**********************************************************************/
2390{
2391 if (!can_client_change_view()) {
2392 return;
2393 }
2394
2397}
2398
2399/**********************************************************************/
2403{
2404 if (!can_client_change_view()) {
2405 return;
2406 }
2407
2410}
2411
2412/**********************************************************************/
2416{
2417 if (!can_client_change_view()) {
2418 return;
2419 }
2420
2423}
2424
2425/**********************************************************************/
2429{
2430 if (!can_client_change_view()) {
2431 return;
2432 }
2433
2436}
2437
2438/**********************************************************************/
2442{
2443 if (!can_client_change_view()) {
2444 return;
2445 }
2446
2449}
2450
2451/**********************************************************************/
2455{
2456 if (!can_client_change_view()) {
2457 return;
2458 }
2459
2462}
2463
2464/**********************************************************************/
2468{
2469 if (!can_client_change_view()) {
2470 return;
2471 }
2472
2475}
2476
2477/**********************************************************************/
2481{
2482 if (!can_client_change_view()) {
2483 return;
2484 }
2485
2488}
2489
2490/**********************************************************************/
2494{
2495 if (!can_client_change_view()) {
2496 return;
2497 }
2498
2501}
2502
2503/**********************************************************************/
2507{
2508 if (!can_client_change_view()) {
2509 return;
2510 }
2511
2514}
2515
2516/**********************************************************************/
2520{
2521 if (!can_client_change_view()) {
2522 return;
2523 }
2524
2527}
2528
2529/**********************************************************************/
2533{
2534 if (!can_client_change_view()) {
2535 return;
2536 }
2537
2540}
2541
2542/**********************************************************************/
2546{
2547 if (!can_client_change_view()) {
2548 return;
2549 }
2550
2553}
2554
2555/**********************************************************************/
2559{
2560 if (!can_client_change_view()) {
2561 return;
2562 }
2563
2566}
2567
2568/**********************************************************************/
2572{
2573 if (!can_client_change_view()) {
2574 return;
2575 }
2576
2579}
2580
2581/**********************************************************************/
2585{
2586 if (!can_client_change_view()) {
2587 return;
2588 }
2589
2592}
2593
2594/**********************************************************************/
2598{
2599 if (!can_client_change_view()) {
2600 return;
2601 }
2602
2605}
2606
2607/**********************************************************************/
2611{
2612 if (!can_client_change_view()) {
2613 return;
2614 }
2615
2618}
2619
2620/**********************************************************************/
2624{
2625 if (!can_client_change_view()) {
2626 return;
2627 }
2628
2632}
2633
2634/**********************************************************************/
2638{
2639 struct tile *ptile = find_a_focus_unit_tile_to_center_on();
2640
2641 if (ptile) {
2642 center_tile_mapcanvas(ptile);
2643 }
2644}
2645
2646/**********************************************************************/
2650void request_units_wait(struct unit_list *punits)
2651{
2652 unit_list_iterate(punits, punit) {
2655 if (punits == get_units_in_focus()) {
2657 }
2658}
2659
2660/**********************************************************************/
2664{
2665 if (get_num_units_in_focus() > 0) {
2666 enum unit_focus_status new_status = FOCUS_DONE;
2668 /* If any of the focused units are busy, keep all of them
2669 * in focus; another tap of the key will dismiss them */
2670 if (punit->activity != ACTIVITY_IDLE) {
2671 new_status = FOCUS_WAIT;
2672 }
2676 punit->client.focus_status = new_status;
2678 if (new_status == FOCUS_DONE) {
2680 }
2681 }
2682}
2683
2684/**********************************************************************/
2690{
2691 struct tile *src_tile = unit_tile(punit);
2692 struct tile *dst_tile = unit_tile(target_unit);
2693 bool was_teleported, do_animation;
2694 bool in_focus = unit_is_in_focus(punit);
2695
2696 was_teleported = !is_tiles_adjacent(src_tile, dst_tile);
2697 do_animation = (!was_teleported && gui_options.smooth_move_unit_msec > 0);
2698
2699 if (!was_teleported
2700 && punit->activity != ACTIVITY_SENTRY
2701 && !unit_transported(punit)) {
2703 unit_type_get(punit)->sound_move_alt);
2704 }
2705
2709 && punit->activity != ACTIVITY_GOTO
2710 && punit->activity != ACTIVITY_SENTRY
2712 && punit->ssa_controller != SSA_NONE)
2713 || (punit->ssa_controller == SSA_NONE))
2715 center_tile_mapcanvas(dst_tile);
2716 }
2717
2718 if (hover_state != HOVER_NONE && in_focus) {
2719 /* Cancel current goto/patrol/connect/nuke command. */
2722 }
2723
2724 unit_list_remove(src_tile->units, punit);
2725
2726 if (!unit_transported(punit)) {
2727 /* Mark the unit as moving unit, then find_visible_unit() won't return
2728 * it. It is especially useful to don't draw many times the unit when
2729 * refreshing the canvas. */
2731
2732 /* We have to refresh the tile before moving. This will draw
2733 * the tile without the unit (because it was unlinked above). */
2735
2737 && punit->ssa_controller != SSA_NONE) {
2738 /* Dont animate automatic units */
2739 } else if (do_animation) {
2740 int dx, dy;
2741
2742 /* For the duration of the animation the unit exists at neither
2743 * tile. */
2744 map_distance_vector(&dx, &dy, src_tile, dst_tile);
2745 move_unit_map_canvas(punit, src_tile, dx, dy);
2746 }
2747 }
2748
2749 unit_tile_set(punit, dst_tile);
2750 unit_list_prepend(dst_tile->units, punit);
2751
2752 if (!unit_transported(punit)) {
2753 /* For find_visible_unit(), see above. */
2754 punit_moving = NULL;
2755
2757 }
2758
2759 /* With the "full" city bar we have to update the city bar when units move
2760 * into or out of a city. For foreign cities this is handled separately,
2761 * via the occupied field of the short-city packet. */
2762 if (NULL != tile_city(src_tile)
2765 }
2766 if (NULL != tile_city(dst_tile)
2769 }
2770
2771 if (in_focus) {
2772 menus_update();
2773 }
2774}
2775
2776/**********************************************************************/
2780static void do_unit_act_sel_vs(struct tile *ptile)
2781{
2784 /* Have the server record that an action decision is wanted for
2785 * this unit against this tile. */
2787 USSDT_QUEUE, tile_index(ptile));
2788 }
2790}
2791
2792/**********************************************************************/
2795void do_map_click(struct tile *ptile, enum quickselect_type qtype)
2796{
2797 struct city *pcity = tile_city(ptile);
2798 struct unit_list *punits = get_units_in_focus();
2799 bool maybe_goto = FALSE;
2800
2801 if (hover_state != HOVER_NONE) {
2802 switch (hover_state) {
2803 case HOVER_NONE:
2804 break;
2805 case HOVER_GOTO:
2806 do_unit_goto(ptile);
2807 break;
2808 case HOVER_PARADROP:
2809 unit_list_iterate(punits, punit) {
2810 do_unit_paradrop_to(punit, ptile);
2812 break;
2813 case HOVER_CONNECT:
2815 break;
2816 case HOVER_PATROL:
2817 do_unit_patrol_to(ptile);
2818 break;
2819 case HOVER_ACT_SEL_TGT:
2820 do_unit_act_sel_vs(ptile);
2821 break;
2822 case HOVER_GOTO_SEL_TGT:
2824 do_unit_goto(ptile);
2825 break;
2826 }
2827
2830 } else if (qtype != SELECT_POPUP && qtype != SELECT_APPEND) {
2831 /* Bypass stack or city popup if quickselect is specified. */
2832 struct unit *qunit = quickselect(ptile, qtype);
2833
2834 if (qunit) {
2836 maybe_goto = gui_options.keyboardless_goto;
2837 }
2838 } else if (NULL != pcity
2840 /* Otherwise use popups. */
2841 popup_city_dialog(pcity);
2842 } else if (unit_list_size(ptile->units) == 0
2843 && NULL == pcity
2844 && get_num_units_in_focus() > 0) {
2845 maybe_goto = gui_options.keyboardless_goto;
2846 } else if (unit_list_size(ptile->units) == 1
2847 && !get_transporter_occupancy(unit_list_get(ptile->units, 0))) {
2848 struct unit *punit = unit_list_get(ptile->units, 0);
2849
2851 if (can_unit_do_activity_client(punit, ACTIVITY_IDLE)) {
2852 maybe_goto = gui_options.keyboardless_goto;
2853 if (qtype == SELECT_APPEND) {
2855 } else {
2857 }
2858 }
2859 } else if (pcity) {
2860 /* Don't hide the unit in the city. */
2862 }
2863 } else if (unit_list_size(ptile->units) > 0) {
2864 /* The stack list is always popped up, even if it includes enemy units.
2865 * If the server doesn't want the player to know about them it shouldn't
2866 * tell them! The previous behavior would only pop up the stack if you
2867 * owned a unit on the tile. This gave cheating clients an advantage,
2868 * and also showed you allied units if (and only if) you had a unit on
2869 * the tile (inconsistent). */
2871 }
2872
2873 /* See mapctrl_common.c */
2874 keyboardless_goto_start_tile = maybe_goto ? ptile : NULL;
2875 keyboardless_goto_button_down = maybe_goto;
2877}
2878
2879/**********************************************************************/
2884static struct unit *quickselect(struct tile *ptile,
2885 enum quickselect_type qtype)
2886{
2887 int listsize = unit_list_size(ptile->units);
2888 struct unit *panytransporter = NULL,
2889 *panymovesea = NULL, *panysea = NULL,
2890 *panymoveland = NULL, *panyland = NULL,
2891 *panymoveunit = NULL, *panyunit = NULL;
2892
2893 fc_assert_ret_val(qtype > SELECT_POPUP, NULL);
2894
2895 if (qtype == SELECT_FOCUS) {
2896 return head_of_units_in_focus();
2897 }
2898
2899 if (listsize == 0) {
2900 return NULL;
2901 } else if (listsize == 1) {
2902 struct unit *punit = unit_list_get(ptile->units, 0);
2903 return (unit_owner(punit) == client.conn.playing) ? punit : NULL;
2904 }
2905
2906 /* Quickselect priorities. Units with moves left
2907 * before exhausted. Focus unit is excluded.
2908 *
2909 * SEA: Transporter
2910 * Sea unit
2911 * Any unit
2912 *
2913 * LAND: Military land unit
2914 * Non-combatant
2915 * Sea unit
2916 * Any unit
2917 */
2918
2919 unit_list_iterate(ptile->units, punit) {
2921 continue;
2922 }
2923 if (qtype == SELECT_SEA) {
2924 /* Transporter. */
2926 if (punit->moves_left > 0) {
2927 return punit;
2928 } else if (!panytransporter) {
2929 panytransporter = punit;
2930 }
2931 }
2932 /* Any sea, pref. moves left. */
2933 else if (utype_move_type(unit_type_get(punit)) == UMT_SEA) {
2934 if (punit->moves_left > 0) {
2935 if (!panymovesea) {
2936 panymovesea = punit;
2937 }
2938 } else if (!panysea) {
2939 panysea = punit;
2940 }
2941 }
2942 } else if (qtype == SELECT_LAND) {
2943 if (utype_move_type(unit_type_get(punit)) == UMT_LAND) {
2944 if (punit->moves_left > 0) {
2945 if (is_military_unit(punit)) {
2946 return punit;
2947 } else if (!panymoveland) {
2948 panymoveland = punit;
2949 }
2950 } else if (!panyland) {
2951 panyland = punit;
2952 }
2953 }
2954 else if (utype_move_type(unit_type_get(punit)) == UMT_SEA) {
2955 if (punit->moves_left > 0) {
2956 panymovesea = punit;
2957 } else {
2958 panysea = punit;
2959 }
2960 }
2961 }
2962 if (punit->moves_left > 0 && !panymoveunit) {
2963 panymoveunit = punit;
2964 }
2965 if (!panyunit) {
2966 panyunit = punit;
2967 }
2969
2970 if (qtype == SELECT_SEA) {
2971 if (panytransporter) {
2972 return panytransporter;
2973 } else if (panymovesea) {
2974 return panymovesea;
2975 } else if (panysea) {
2976 return panysea;
2977 } else if (panymoveunit) {
2978 return panymoveunit;
2979 } else if (panyunit) {
2980 return panyunit;
2981 }
2982 }
2983 else if (qtype == SELECT_LAND) {
2984 if (panymoveland) {
2985 return panymoveland;
2986 } else if (panyland) {
2987 return panyland;
2988 } else if (panymovesea) {
2989 return panymovesea;
2990 } else if (panysea) {
2991 return panysea;
2992 } else if (panymoveunit) {
2993 return panymoveunit;
2994 } else if (panyunit) {
2995 return panyunit;
2996 }
2997 }
2998 return NULL;
2999}
3000
3001/**********************************************************************/
3005void do_unit_goto(struct tile *ptile)
3006{
3010
3013 return;
3014 }
3015
3016 if (is_valid_goto_draw_line(ptile)) {
3018 } else {
3019 create_event(ptile, E_BAD_COMMAND, ftc_client,
3020 _("Didn't find a route to the destination!"));
3021 }
3022}
3023
3024/**********************************************************************/
3027void do_unit_paradrop_to(struct unit *punit, struct tile *ptile)
3028{
3029 struct action *paradrop_action = NULL;
3030
3031 action_iterate(act_id) {
3032 struct action *paction = action_by_number(act_id);
3033
3034 if (!(action_has_result(paction, ACTRES_PARADROP_CONQUER)
3035 || action_has_result(paction, ACTRES_PARADROP))) {
3036 /* Not relevant. */
3037 continue;
3038 }
3039
3041 action_prob_unit_vs_tgt(&(wld.map), paction, punit,
3042 tile_city(ptile), NULL,
3043 ptile, NULL))) {
3044 if (paradrop_action == NULL) {
3045 /* This is the first possible paradrop action. */
3046 paradrop_action = paction;
3047 } else {
3048 /* More than one paradrop action may be possible. The user must
3049 * choose. Have the server record that an action decision is wanted
3050 * for this unit so the dialog will be brought up. */
3052 USSDT_QUEUE, tile_index(ptile));
3053 return;
3054 }
3055 }
3057
3058 if (paradrop_action != NULL) {
3059 request_do_action(paradrop_action->id, punit->id,
3060 tile_index(ptile), 0 , "");
3061 }
3062}
3063
3064/**********************************************************************/
3067void do_unit_patrol_to(struct tile *ptile)
3068{
3069 if (is_valid_goto_draw_line(ptile)
3072 } else {
3073 create_event(ptile, E_BAD_COMMAND, ftc_client,
3074 _("Didn't find a route to the destination!"));
3075 }
3076
3078}
3079
3080/**********************************************************************/
3083void do_unit_connect(struct tile *ptile,
3084 enum unit_activity activity,
3085 struct extra_type *tgt)
3086{
3087 if (is_valid_goto_draw_line(ptile)) {
3088 send_connect_route(activity, tgt);
3089 } else {
3090 create_event(ptile, E_BAD_COMMAND, ftc_client,
3091 _("Didn't find a route to the destination!"));
3092 }
3093
3095}
3096
3097/**********************************************************************/
3101{
3102 struct unit_list *punits = get_units_in_focus();
3104
3105 switch (hover_state) {
3106 case HOVER_GOTO_SEL_TGT:
3110 break;
3111 case HOVER_GOTO:
3112 case HOVER_PATROL:
3113 case HOVER_CONNECT:
3114 if (goto_pop_waypoint()) {
3115 break;
3116 }
3117 fc__fallthrough; /* else fall through: */
3118 case HOVER_PARADROP:
3119 case HOVER_ACT_SEL_TGT:
3122
3126 break;
3127 case HOVER_NONE:
3128 break;
3129 };
3130}
3131
3132/**********************************************************************/
3137{
3139
3140 if (capital) {
3141 /* Center on the tile, and pop up the crosshair overlay. */
3144 } else {
3145 create_event(NULL, E_BAD_COMMAND, ftc_client,
3146 _("Oh my! You seem to have no capital!"));
3147 }
3148}
3149
3150/**********************************************************************/
3154{
3156}
3157
3158/**********************************************************************/
3162{
3163 int i = 0;
3164
3165 /* Could use unit_list_copy here instead. Just having safe genlists
3166 * wouldn't be sufficient since we don't want to skip units already
3167 * removed from focus... */
3169 if (i == 0) {
3171 } else {
3173 }
3174 i++;
3176}
3177
3178/**********************************************************************/
3182void key_unit_move(enum direction8 gui_dir)
3183{
3185 enum direction8 map_dir = gui_to_map_dir(gui_dir);
3186
3189}
3190
3191/**********************************************************************/
3200
3201/**********************************************************************/
3205{
3207 if (unit_can_do_action(punit, ACTION_HELP_WONDER)) {
3208 request_unit_caravan_action(punit, ACTION_HELP_WONDER);
3209 }
3211}
3212
3213/**********************************************************************/
3216void key_unit_connect(enum unit_activity activity,
3217 struct extra_type *tgt)
3218{
3219 request_unit_connect(activity, tgt);
3220}
3221
3222/**********************************************************************/
3226{
3227 struct tile *ptile;
3228
3231 && (ptile = unit_tile(punit))) {
3232 /* Have the server record that an action decision is wanted for this
3233 * unit. */
3235 USSDT_QUEUE, tile_index(ptile));
3236 }
3238}
3239
3240/**********************************************************************/
3248{
3249 struct unit_list *punits = get_units_in_focus();
3250
3252 /* The 2nd key press means that the actor should target its own
3253 * tile. */
3255
3256 /* Target tile selected. Clean up hover state. */
3258 update_unit_info_label(punits);
3259
3260 return;
3261 } else if (hover_state == HOVER_GOTO_SEL_TGT) {
3263
3264 /* We don't support long range actions in the middle of orders yet so
3265 * send it at once. */
3267
3268 /* Target tile selected. Clean up hover state. */
3270 update_unit_info_label(punits);
3271
3272 return;
3273 } else if (hover_state == HOVER_GOTO
3275 struct action *paction = action_by_number(goto_last_action);
3276
3277 create_event(unit_tile(unit_list_get(punits, 0)), E_BEGINNER_HELP,
3278 ftc_client,
3279 /* TRANS: Perform action inside a goto. */
3280 _("Click on a tile to do %s against it."),
3281 action_name_translation(paction));
3282
3287
3288 return;
3289 }
3290
3291 create_event(unit_tile(unit_list_get(punits, 0)), E_BEGINNER_HELP,
3292 ftc_client,
3293 /* TRANS: "Do..." action selection dialog target. */
3294 _("Click on a tile to act against it. "
3295 "Press 'd' again to act against own tile."));
3296
3297 set_hover_state(punits, HOVER_ACT_SEL_TGT, ACTIVITY_LAST, NULL,
3299}
3300
3301/**********************************************************************/
3305{
3307}
3308
3309/**********************************************************************/
3313{
3315}
3316
3317/**********************************************************************/
3324
3325/**********************************************************************/
3329{
3331}
3332
3333/**********************************************************************/
3337{
3339 /* TODO: Is falling back on ACTION_MARKETPLACE if not able to establish
3340 * a trade route trade a good idea or an unplecant surprice? */
3341 if (unit_can_do_action(punit, ACTION_TRADE_ROUTE)) {
3342 request_unit_caravan_action(punit, ACTION_TRADE_ROUTE);
3343 }
3345}
3346
3347/**********************************************************************/
3351{
3352 struct unit *pnext_focus = NULL, *plast;
3353
3355 if ((plast = request_unit_unload_all(punit))) {
3356 pnext_focus = plast;
3357 }
3359
3360 if (pnext_focus) {
3362 /* Unfocus the ships, and advance the focus to the last unloaded unit.
3363 * If there is no unit unloaded (which shouldn't happen, but could if
3364 * the caller doesn't check if the transporter is loaded), the we
3365 * don't do anything. */
3368 unit_focus_set(pnext_focus);
3369 }
3370}
3371
3372/**********************************************************************/
3379
3380/**********************************************************************/
3389
3390/**********************************************************************/
3394{
3396 struct base_type *pbase =
3397 get_base_by_gui_type(BASE_GUI_AIRBASE, punit, unit_tile(punit));
3398
3399 if (pbase) {
3400 struct extra_type *pextra = base_extra_get(pbase);
3401
3402 request_new_unit_activity_targeted(punit, ACTIVITY_BASE, pextra);
3403 }
3405}
3406
3407/**********************************************************************/
3411{
3413 if (can_unit_do_activity_client(punit, ACTIVITY_EXPLORE)) {
3414 request_unit_ssa_set(punit, SSA_AUTOEXPLORE);
3415 }
3417}
3418
3419/**********************************************************************/
3431
3432/**********************************************************************/
3441
3442/**********************************************************************/
3446{
3447 key_unit_gen_clean(ACTIVITY_FALLOUT, ERM_CLEANFALLOUT);
3448}
3449
3450/**********************************************************************/
3454{
3456 if (can_unit_do_activity_client(punit, ACTIVITY_FORTIFYING)) {
3457 request_new_unit_activity(punit, ACTIVITY_FORTIFYING);
3458 }
3460}
3461
3462/**********************************************************************/
3466{
3468 struct base_type *pbase =
3469 get_base_by_gui_type(BASE_GUI_FORTRESS, punit, unit_tile(punit));
3470
3471 if (pbase) {
3472 struct extra_type *pextra = base_extra_get(pbase);
3473
3474 request_new_unit_activity_targeted(punit, ACTIVITY_BASE, pextra);
3475 }
3477}
3478
3479/**********************************************************************/
3488
3489/**********************************************************************/
3492static void key_unit_extra(enum unit_activity act, enum extra_cause cause)
3493{
3496 cause,
3498 punit);
3499
3502 }
3504}
3505
3506/**********************************************************************/
3509static void key_unit_gen_clean(enum unit_activity act,
3510 enum extra_rmcause rmcause)
3511{
3514 rmcause,
3516 punit);
3517
3518 if (tgt != NULL
3521 }
3523}
3524
3525/**********************************************************************/
3529{
3530 key_unit_extra(ACTIVITY_IRRIGATE, EC_IRRIGATION);
3531}
3532
3533/**********************************************************************/
3537{
3539 if (can_unit_do_activity_client(punit, ACTIVITY_CULTIVATE)) {
3540 request_new_unit_activity(punit, ACTIVITY_CULTIVATE);
3541 }
3543}
3544
3545/**********************************************************************/
3549{
3550 key_unit_extra(ACTIVITY_MINE, EC_MINE);
3551}
3552
3553/**********************************************************************/
3557{
3559 if (can_unit_do_activity_client(punit, ACTIVITY_PLANT)) {
3560 request_new_unit_activity(punit, ACTIVITY_PLANT);
3561 }
3563}
3564
3565/**********************************************************************/
3569{
3571 if (can_unit_do_activity_client(punit, ACTIVITY_PILLAGE)) {
3573 }
3575}
3576
3577/**********************************************************************/
3581{
3584 ERM_CLEANPOLLUTION,
3586 punit);
3587
3588 if (tgt != NULL
3589 && can_unit_do_activity_targeted_client(punit, ACTIVITY_POLLUTION, tgt)) {
3590 request_new_unit_activity_targeted(punit, ACTIVITY_POLLUTION, tgt);
3591 } else {
3593 ERM_CLEANFALLOUT,
3595 punit);
3596
3597 if (tgt != NULL
3598 && can_unit_do_activity_targeted_client(punit, ACTIVITY_FALLOUT, tgt)) {
3599 request_new_unit_activity_targeted(punit, ACTIVITY_FALLOUT, tgt);
3600 }
3601 }
3603}
3604
3605/**********************************************************************/
3609{
3610 key_unit_gen_clean(ACTIVITY_POLLUTION, ERM_CLEANPOLLUTION);
3611}
3612
3613/**********************************************************************/
3617{
3620 EC_ROAD,
3622 punit);
3623
3624 if (tgt != NULL
3625 && can_unit_do_activity_targeted_client(punit, ACTIVITY_GEN_ROAD, tgt)) {
3626 request_new_unit_activity_targeted(punit, ACTIVITY_GEN_ROAD, tgt);
3627 }
3629}
3630
3631/**********************************************************************/
3635{
3637 if (can_unit_do_activity_client(punit, ACTIVITY_SENTRY)) {
3638 request_new_unit_activity(punit, ACTIVITY_SENTRY);
3639 }
3641}
3642
3643/**********************************************************************/
3647{
3649 if (can_unit_do_activity_client(punit, ACTIVITY_TRANSFORM)) {
3650 request_new_unit_activity(punit, ACTIVITY_TRANSFORM);
3651 }
3653}
3654
3655/**********************************************************************/
3658void key_unit_assign_battlegroup(int battlegroup, bool append)
3659{
3661 && battlegroups >= 0 && battlegroup < MAX_NUM_BATTLEGROUPS) {
3662 if (!append) {
3664 if (!unit_is_in_focus(punit)) {
3667 USSDT_BATTLE_GROUP,
3670 unit_list_remove(battlegroups[battlegroup], punit);
3671 }
3673 }
3675 if (punit->battlegroup != battlegroup) {
3676 if (punit->battlegroup >= 0
3678 unit_list_remove(battlegroups[punit->battlegroup], punit);
3679 }
3680 punit->battlegroup = battlegroup;
3682 USSDT_BATTLE_GROUP,
3683 battlegroup);
3684 unit_list_append(battlegroups[battlegroup], punit);
3686 }
3688 unit_list_iterate(battlegroups[battlegroup], punit) {
3691 }
3692}
3693
3694/**********************************************************************/
3697void key_unit_select_battlegroup(int battlegroup, bool append)
3698{
3699 if (NULL != client.conn.playing && can_client_change_view()
3700 && battlegroups >= 0 && battlegroup < MAX_NUM_BATTLEGROUPS) {
3701 int i = 0;
3702
3703 if (unit_list_size(battlegroups[battlegroup]) == 0 && !append) {
3704 unit_focus_set(NULL);
3705 return;
3706 }
3707
3708 /* FIXME: this is very inefficient and can be improved. */
3709 unit_list_iterate(battlegroups[battlegroup], punit) {
3710 if (i == 0 && !append) {
3712 } else {
3714 }
3715 i++;
3717 }
3718}
3719
3720/**********************************************************************/
3727
3728/**********************************************************************/
3735
3736/**********************************************************************/
3740{
3742}
3743
3744/**********************************************************************/
3751
3752/**********************************************************************/
3759
3760/**********************************************************************/
3767
3768/**********************************************************************/
3775
3776/**********************************************************************/
3784
3785/**********************************************************************/
3793
3794/**********************************************************************/
3801
3802/**********************************************************************/
3810
3811/**********************************************************************/
3818
3819/**********************************************************************/
3823{
3825}
3826
3827/**********************************************************************/
3831{
3833}
3834
3835/**********************************************************************/
3842
3843/**********************************************************************/
3850
3851/**********************************************************************/
3855{
3857}
3858
3859/**********************************************************************/
3863{
3865}
3866
3867/**********************************************************************/
3871{
3873}
3874
3875/**********************************************************************/
3879{
3881}
3882
3883/**********************************************************************/
3887{
3889}
3890
3891/**********************************************************************/
3895{
3897}
3898
3899/**********************************************************************/
3903{
3905}
3906
3907/**********************************************************************/
3914
3915/**********************************************************************/
3922
3923/**********************************************************************/
3930
3931/**********************************************************************/
3938
3939/**********************************************************************/
3946
3947/**********************************************************************/
3954
3955/**********************************************************************/
3965
3966/**********************************************************************/
3969void finish_city(struct tile *ptile, const char *name)
3970{
3971 unit_list_iterate(ptile->units, punit) {
3973 /* Unit will disappear only in case city building still success.
3974 * Cancel city building status just in case something has changed
3975 * to prevent city building in the meanwhile and unit will remain
3976 * alive. */
3978 request_do_action(ACTION_FOUND_CITY, punit->id, ptile->index,
3979 0, name);
3980 }
3982}
3983
3984/**********************************************************************/
3988void cancel_city(struct tile *ptile)
3989{
3990 unit_list_iterate(ptile->units, punit) {
3993}
const char * action_name_translation(const struct action *action)
Definition actions.c:1890
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
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
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
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
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
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_id_exists(const action_id act_id)
Definition actions.c:1697
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
#define action_id_univs_not_blocking(act_id, act_uni, tgt_uni)
Definition actions.h:962
#define action_by_result_iterate(_paction_, _result_)
Definition actions.h:488
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_id_get_role(act_id)
Definition actions.h:708
#define action_by_result_iterate_end
Definition actions.h:492
#define action_iterate_end
Definition actions.h:472
#define action_iterate(_act_)
Definition actions.h:467
#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_NONE
Definition actions.h:293
void astr_free(struct astring *astr)
Definition astring.c:153
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 audio_play_sound(const char *const tag, const char *const alt_tag)
Definition audio.c:521
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
static bool is_enemy_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:712
void popup_city_dialog(struct city *pcity)
int client_player_number(void)
void send_turn_done(void)
struct civclient client
enum client_states client_state(void)
bool can_client_issue_orders(void)
bool client_has_player(void)
bool is_server_busy(void)
bool can_client_change_view(void)
#define client_player()
@ C_S_RUNNING
Definition client_main.h:47
@ C_S_OVER
Definition client_main.h:48
enum direction8 gui_to_map_dir(enum direction8 gui_dir)
Definition climap.c:59
void create_event(struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Definition climisc.c:1086
bool can_units_do_connect(struct unit_list *punits, enum unit_activity activity, struct extra_type *tgt)
Definition climisc.c:1235
bool can_unit_attack_tile(const struct unit *punit, const struct action *paction, const struct tile *dest_tile)
Definition combat.c:271
double blink_turn_done_button(void)
Definition control.c:925
void key_coastline_toggle(void)
Definition control.c:3830
void key_irrigation_toggle(void)
Definition control.c:3846
void request_toggle_huts(void)
Definition control.c:2532
void key_unit_sentry(void)
Definition control.c:3634
void request_toggle_city_outlines(void)
Definition control.c:2285
void key_unit_road(void)
Definition control.c:3616
void request_unit_airlift(struct unit *punit, struct city *pcity)
Definition control.c:1538
void do_move_unit(struct unit *punit, struct unit *target_unit)
Definition control.c:2689
void request_toggle_resources(void)
Definition control.c:2519
void request_toggle_city_names(void)
Definition control.c:2363
void key_recall_previous_focus_unit(void)
Definition control.c:3161
void request_unit_non_action_move(struct unit *punit, struct tile *dest_tile)
Definition control.c:1759
void request_toggle_unit_stack_size(void)
Definition control.c:2428
void key_unit_pollution(void)
Definition control.c:3608
bool unit_is_in_focus(const struct unit *punit)
Definition control.c:389
void key_city_output_toggle(void)
Definition control.c:3731
void request_toggle_focus_unit(void)
Definition control.c:2610
void request_toggle_city_output(void)
Definition control.c:2298
void request_unit_return(struct unit *punit)
Definition control.c:1547
void request_unit_fortify(struct unit *punit)
Definition control.c:2240
void key_unit_build_city(void)
Definition control.c:3194
void key_editor_recalculate_borders(void)
Definition control.c:3950
struct unit * request_unit_unload_all(struct unit *punit)
Definition control.c:1506
void key_roads_rails_toggle(void)
Definition control.c:3838
void request_unit_caravan_action(struct unit *punit, action_id action)
Definition control.c:2148
void action_selection_no_longer_in_progress(const int old_actor_id)
Definition control.c:1050
void request_toggle_roads_rails(void)
Definition control.c:2467
enum unit_orders goto_last_order
Definition control.c:96
void request_units_wait(struct unit_list *punits)
Definition control.c:2650
void request_unit_wakeup(struct unit *punit)
Definition control.c:1595
struct unit * get_focus_unit_on_tile(const struct tile *ptile)
Definition control.c:397
void key_focus_unit_toggle(void)
Definition control.c:3926
void request_toggle_map_grid(void)
Definition control.c:2311
void action_decision_request(struct unit *actor_unit)
Definition control.c:1109
void control_free(void)
Definition control.c:154
void request_toggle_mines(void)
Definition control.c:2493
void set_units_in_combat(struct unit *pattacker, struct unit *pdefender)
Definition control.c:1031
int check_recursive_road_connect(struct tile *ptile, const struct extra_type *pextra, const struct unit *punit, const struct player *pplayer, int rec)
Definition control.c:1332
void key_unit_action_select(void)
Definition control.c:3225
void key_unit_auto_explore(void)
Definition control.c:3410
static int action_selection_in_progress_for
Definition control.c:119
static void do_disband_alternative(void *p)
Definition control.c:1896
void key_cancel_action(void)
Definition control.c:3100
void request_toggle_city_buycost(void)
Definition control.c:2402
void key_unit_auto_settle(void)
Definition control.c:3423
void clear_hover_state(void)
Definition control.c:328
void request_toggle_map_native(void)
Definition control.c:2337
void request_unit_patrol(void)
Definition control.c:2206
int num_units_below
Definition control.c:76
void key_unit_connect(enum unit_activity activity, struct extra_type *tgt)
Definition control.c:3216
void key_city_full_bar_toggle(void)
Definition control.c:3763
void request_unit_load(struct unit *pcargo, struct unit *ptrans, struct tile *ptile)
Definition control.c:2083
void key_bases_toggle(void)
Definition control.c:3862
void do_map_click(struct tile *ptile, enum quickselect_type qtype)
Definition control.c:2795
static void key_unit_extra(enum unit_activity act, enum extra_cause cause)
Definition control.c:3492
void key_map_native_toggle(void)
Definition control.c:3755
void request_toggle_map_borders(void)
Definition control.c:2324
void key_resources_toggle(void)
Definition control.c:3870
static struct unit * punit_attacking
Definition control.c:105
void unit_focus_add(struct unit *punit)
Definition control.c:562
void unit_focus_set(struct unit *punit)
Definition control.c:507
static void do_unit_act_sel_vs(struct tile *ptile)
Definition control.c:2780
void request_unit_goto(enum unit_orders last_order, action_id act_id, int sub_tgt_id)
Definition control.c:1129
void do_unit_paradrop_to(struct unit *punit, struct tile *ptile)
Definition control.c:3027
bool should_ask_server_for_actions(const struct unit *punit)
Definition control.c:339
int goto_last_tgt
Definition control.c:94
struct extra_type * connect_tgt
Definition control.c:91
void key_unit_paradrop(void)
Definition control.c:3320
static bool can_units_attack_at(struct unit_list *punits, const struct tile *ptile)
Definition control.c:1196
struct unit_list * get_units_in_focus(void)
Definition control.c:177
void request_do_action(action_id action, int actor_id, int target_id, int sub_tgt, const char *name)
Definition control.c:1701
void key_end_turn(void)
Definition control.c:3153
void request_unit_disband(struct unit *punit)
Definition control.c:2002
void request_toggle_irrigation(void)
Definition control.c:2480
static struct unit_list * current_focus
Definition control.c:79
static struct unit_list * previous_focus
Definition control.c:83
static void key_unit_gen_clean(enum unit_activity act, enum extra_rmcause rmcause)
Definition control.c:3509
void request_unit_autosettlers(const struct unit *punit)
Definition control.c:2068
void request_unit_pillage(struct unit *punit)
Definition control.c:2251
void request_center_focus_unit(void)
Definition control.c:2637
void unit_focus_urgent(struct unit *punit)
Definition control.c:207
void key_unit_shields_toggle(void)
Definition control.c:3918
void key_city_productions_toggle(void)
Definition control.c:3797
bool can_unit_do_connect(struct unit *punit, enum unit_activity activity, struct extra_type *tgt)
Definition control.c:1410
void key_unit_build_wonder(void)
Definition control.c:3204
void key_unit_plant(void)
Definition control.c:3556
void key_unit_fortress(void)
Definition control.c:3465
void key_unit_mine(void)
Definition control.c:3548
void request_unit_change_homecity(struct unit *punit)
Definition control.c:2021
void request_toggle_fog_of_war(void)
Definition control.c:2623
void key_unit_pillage(void)
Definition control.c:3568
void request_unit_unload(struct unit *pcargo)
Definition control.c:2119
void key_editor_toggle_fogofwar(void)
Definition control.c:3959
static void client_disband_unit_data_destroy(void *p)
Definition control.c:1886
void request_unit_ssa_set(const struct unit *punit, enum server_side_agent agent)
Definition control.c:2055
static struct unit * find_best_focus_candidate(bool accept_current)
Definition control.c:650
void request_action_details(action_id action, int actor_id, int target_id)
Definition control.c:1721
static struct unit * quickselect(struct tile *ptile, enum quickselect_type qtype)
Definition control.c:2884
enum unit_activity connect_activity
Definition control.c:90
void request_toggle_units(void)
Definition control.c:2571
void request_new_unit_activity_targeted(struct unit *punit, enum unit_activity act, struct extra_type *tgt)
Definition control.c:1863
void update_unit_pix_label(struct unit_list *punitlist)
Definition control.c:984
void key_unit_irrigate(void)
Definition control.c:3528
void request_unit_build_city(struct unit *punit)
Definition control.c:1740
void unit_change_battlegroup(struct unit *punit, int battlegroup)
Definition control.c:255
static struct unit_list * urgent_focus_queue
Definition control.c:86
void key_unit_unload_all(void)
Definition control.c:3350
void key_cities_toggle(void)
Definition control.c:3894
void key_unit_move(enum direction8 gui_dir)
Definition control.c:3182
void key_city_outlines_toggle(void)
Definition control.c:3723
void key_unit_homecity(void)
Definition control.c:3482
void request_unit_paradrop(struct unit_list *punits)
Definition control.c:2171
void set_hover_state(struct unit_list *punits, enum cursor_hover_state state, enum unit_activity activity, struct extra_type *tgt, int last_tgt, int last_sub_tgt, action_id action, enum unit_orders order)
Definition control.c:290
static int disband_unit_alternatives[3]
Definition control.c:69
void key_unit_patrol(void)
Definition control.c:3328
void request_toggle_city_full_bar(void)
Definition control.c:2350
void request_toggle_city_growth(void)
Definition control.c:2376
void key_unit_solid_bg_toggle(void)
Definition control.c:3910
void request_toggle_unit_solid_bg(void)
Definition control.c:2584
void key_terrain_toggle(void)
Definition control.c:3822
void request_unit_sentry(struct unit *punit)
Definition control.c:2229
void key_unit_wakeup_others(void)
Definition control.c:3383
bool non_ai_unit_focus
Definition control.c:125
static struct unit * punit_defending
Definition control.c:106
static struct tile * find_a_focus_unit_tile_to_center_on(void)
Definition control.c:419
enum cursor_hover_state hover_state
Definition control.c:89
void key_unit_stack_size_toggle(void)
Definition control.c:3814
static void store_previous_focus(void)
Definition control.c:194
void key_huts_toggle(void)
Definition control.c:3878
void key_fog_of_war_toggle(void)
Definition control.c:3934
void request_unit_connect(enum unit_activity activity, struct extra_type *tgt)
Definition control.c:1477
void clear_unit_orders(struct unit *punit)
Definition control.c:482
void control_init(void)
Definition control.c:137
void request_toggle_terrain(void)
Definition control.c:2441
void action_decision_clear_want(const int old_actor_id)
Definition control.c:1079
void key_unit_wait(void)
Definition control.c:3375
void key_units_toggle(void)
Definition control.c:3902
void do_unit_connect(struct tile *ptile, enum unit_activity activity, struct extra_type *tgt)
Definition control.c:3083
int goto_last_sub_tgt
Definition control.c:95
void unit_focus_remove(struct unit *punit)
Definition control.c:592
void request_toggle_bases(void)
Definition control.c:2506
void do_unit_patrol_to(struct tile *ptile)
Definition control.c:3067
void key_unit_trade_route(void)
Definition control.c:3336
void request_toggle_coastline(void)
Definition control.c:2454
void key_unit_select_battlegroup(int battlegroup, bool append)
Definition control.c:3697
void key_map_grid_toggle(void)
Definition control.c:3739
void finish_city(struct tile *ptile, const char *name)
Definition control.c:3969
static struct unit * punit_moving
Definition control.c:102
void key_pollution_toggle(void)
Definition control.c:3886
struct unit * head_of_units_in_focus(void)
Definition control.c:411
static bool is_activity_on_tile(struct tile *ptile, enum unit_activity activity)
Definition control.c:1316
struct unit * find_visible_unit(struct tile *ptile)
Definition control.c:823
static bool can_be_irrigated(const struct tile *ptile, const struct unit *punit)
Definition control.c:1387
void key_city_growth_toggle(void)
Definition control.c:3780
void key_unit_action_select_tgt(void)
Definition control.c:3247
void key_unit_fallout(void)
Definition control.c:3445
static struct unit_list * battlegroups[MAX_NUM_BATTLEGROUPS]
Definition control.c:99
void key_city_buycost_toggle(void)
Definition control.c:3789
int get_num_units_in_focus(void)
Definition control.c:185
void key_unit_transform(void)
Definition control.c:3646
void request_move_unit_direction(struct unit *punit, int dir)
Definition control.c:1803
static void current_focus_append(struct unit *punit)
Definition control.c:448
void key_unit_done(void)
Definition control.c:3304
static void current_focus_remove(struct unit *punit)
Definition control.c:468
static struct tile * hover_tile
Definition control.c:98
void key_city_trade_routes_toggle(void)
Definition control.c:3806
static void focus_units_changed(void)
Definition control.c:215
void request_toggle_city_trade_routes(void)
Definition control.c:2415
void unit_focus_set_and_select(struct unit *punit)
Definition control.c:637
void request_unit_convert(struct unit *punit)
Definition control.c:2045
void request_toggle_unit_shields(void)
Definition control.c:2597
void key_city_names_toggle(void)
Definition control.c:3771
void unit_register_battlegroup(struct unit *punit)
Definition control.c:275
void request_unit_select(struct unit_list *punits, enum unit_select_type_mode seltype, enum unit_select_location_mode selloc)
Definition control.c:1616
void unit_focus_update(void)
Definition control.c:790
void key_unit_airbase(void)
Definition control.c:3393
void key_unit_goto(void)
Definition control.c:3312
void control_mouse_cursor(struct tile *ptile)
Definition control.c:1214
void key_unit_convert(void)
Definition control.c:3435
void key_unit_clean(void)
Definition control.c:3580
void key_center_capital(void)
Definition control.c:3136
void wakeup_sentried_units(struct tile *ptile)
Definition control.c:1578
void request_toggle_cities(void)
Definition control.c:2558
void key_unit_fortify(void)
Definition control.c:3453
void key_editor_toggle(void)
Definition control.c:3942
void key_unit_assign_battlegroup(int battlegroup, bool append)
Definition control.c:3658
void request_unit_move_done(void)
Definition control.c:2663
void auto_center_on_focus_unit(void)
Definition control.c:435
void key_unit_cultivate(void)
Definition control.c:3536
double blink_active_unit(void)
Definition control.c:893
void unit_focus_advance(bool accept_current)
Definition control.c:689
void request_unit_upgrade(struct unit *punit)
Definition control.c:2033
void control_unit_killed(struct unit *punit)
Definition control.c:226
void request_toggle_city_productions(void)
Definition control.c:2389
void cancel_city(struct tile *ptile)
Definition control.c:3988
static void ask_server_for_actions(struct unit *punit)
Definition control.c:366
void request_new_unit_activity(struct unit *punit, enum unit_activity act)
Definition control.c:1854
void request_toggle_pollution(void)
Definition control.c:2545
action_id goto_last_action
Definition control.c:93
void key_mines_toggle(void)
Definition control.c:3854
void do_unit_goto(struct tile *ptile)
Definition control.c:3005
void action_selection_next_in_focus(const int old_actor_id)
Definition control.c:1091
static bool can_ask_server_for_actions(void)
Definition control.c:352
void key_map_borders_toggle(void)
Definition control.c:3747
#define can_unit_do_activity_targeted_client(_punit_, _act_, _tgt_)
Definition control.h:42
#define MAX_NUM_UNITS_BELOW
Definition control.h:285
quickselect_type
Definition control.h:36
@ SELECT_LAND
Definition control.h:37
@ SELECT_APPEND
Definition control.h:37
@ SELECT_SEA
Definition control.h:37
@ SELECT_POPUP
Definition control.h:37
@ SELECT_FOCUS
Definition control.h:37
cursor_hover_state
Definition control.h:25
@ HOVER_GOTO
Definition control.h:27
@ HOVER_PARADROP
Definition control.h:28
@ HOVER_ACT_SEL_TGT
Definition control.h:31
@ HOVER_NONE
Definition control.h:26
@ HOVER_CONNECT
Definition control.h:29
@ HOVER_PATROL
Definition control.h:30
@ HOVER_GOTO_SEL_TGT
Definition control.h:32
#define can_unit_do_activity_client(_punit_, _act_)
Definition control.h:40
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 action_selection_no_longer_in_progress_gui_specific
Definition dialogs_g.h:68
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
int get_unit_bonus(const struct unit *punit, enum effect_type effect_type)
Definition effects.c:992
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 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
bool can_build_extra(const struct extra_type *pextra, const struct unit *punit, const struct tile *ptile)
Definition extras.c:507
#define extra_type_iterate(_p)
Definition extras.h:291
#define extra_deps_iterate(_reqs, _dep)
Definition extras.h:338
#define extra_type_iterate_end
Definition extras.h:297
#define is_extra_caused_by(e, c)
Definition extras.h:196
#define extra_index(_e_)
Definition extras.h:177
#define extra_deps_iterate_end
Definition extras.h:346
#define EXTRA_NONE
Definition extras.h:82
#define extra_road_get(_e_)
Definition extras.h:185
#define NO_TARGET
Definition fc_types.h:324
@ RPT_POSSIBLE
Definition fc_types.h:585
#define DIR8_ORIGIN
Definition fc_types.h:427
int action_id
Definition fc_types.h:359
#define MAX_EXTRA_TYPES
Definition fc_types.h:50
#define IDENTITY_NUMBER_ZERO
Definition fc_types.h:82
#define _(String)
Definition fcintl.h:67
const struct ft_color ftc_client
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
void exit_goto_state(void)
Definition goto.c:1019
bool goto_is_active(void)
Definition goto.c:1056
struct pf_path * path_to_nearest_allied_city(struct unit *punit)
Definition goto.c:1983
void send_patrol_route(void)
Definition goto.c:1647
bool is_valid_goto_draw_line(struct tile *dest_tile)
Definition goto.c:1335
bool goto_add_waypoint(void)
Definition goto.c:487
bool goto_pop_waypoint(void)
Definition goto.c:524
void send_connect_route(enum unit_activity activity, struct extra_type *tgt)
Definition goto.c:1713
void goto_unit_killed(struct unit *punit)
Definition goto.c:1037
void free_client_goto(void)
Definition goto.c:162
void enter_goto_state(struct unit_list *punits)
Definition goto.c:998
void send_goto_route(void)
Definition goto.c:1870
bool is_valid_goto_destination(const struct tile *ptile)
Definition goto.c:179
void request_orders_cleared(struct unit *punit)
Definition goto.c:1360
void send_goto_path(struct unit *punit, struct pf_path *path, struct unit_order *final_order)
Definition goto.c:1530
int action_selection_actor_unit(void)
void action_selection_close(void)
void refresh_unit_city_dialogs(struct unit *punit)
Definition citydlg.c:538
void unit_select_dialog_popup(struct tile *ptile)
Definition dialogs.c:382
void popup_pillage_dialog(struct unit *punit, bv_extras extras)
Definition dialogs.c:343
void real_focus_units_changed(void)
Definition gui_main.c:1955
void set_unit_icons_more_arrow(bool onoff)
Definition gui_main.c:1932
void set_unit_icon(int idx, struct unit *punit)
Definition gui_main.c:1902
void create_line_at_mouse_pos(void)
Definition mapctrl.c:347
void update_turn_done_button(bool do_restore)
Definition mapview.c:75
void put_cross_overlay_tile(struct tile *ptile)
Definition mapview.c:622
void update_unit_info_label(struct unit_list *punits)
Definition mapview.c:258
void update_mouse_cursor(enum cursor_type new_cursor_type)
Definition mapview.c:240
bool request_transport(struct unit *cargo, struct tile *ptile)
enum cursor_type mouse_cursor_type
Definition gui_mouse.c:46
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 fc_assert(condition)
Definition log.h:176
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define log_error(message,...)
Definition log.h:103
int get_direction_for_step(const struct civ_map *nmap, const struct tile *start_tile, const struct tile *end_tile)
Definition map.c:1345
bool is_tiles_adjacent(const struct tile *tile0, const struct tile *tile1)
Definition map.c:929
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:938
struct tile * mapstep(const struct civ_map *nmap, const struct tile *ptile, enum direction8 dir)
Definition map.c:369
void map_distance_vector(int *dx, int *dy, const struct tile *tile0, const struct tile *tile1)
Definition map.c:1071
#define iterate_outward(nmap, start_tile, max_dist, itr_tile)
Definition map.h:361
#define iterate_outward_end
Definition map.h:365
bool keyboardless_goto_button_down
void cancel_tile_hiliting(void)
bool keyboardless_goto_active
struct tile * keyboardless_goto_start_tile
void update_map_canvas_visible(void)
struct tile * get_center_tile_mapcanvas(void)
void move_unit_map_canvas(struct unit *punit, struct tile *src_tile, int dx, int dy)
void center_tile_mapcanvas(const struct tile *ptile)
void update_city_description(struct city *pcity)
void refresh_unit_mapcanvas(struct unit *punit, struct tile *ptile, bool full_refresh, bool write_to_screen)
bool tile_visible_and_not_on_border_mapcanvas(struct tile *ptile)
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_malloc(sz)
Definition mem.h:34
void menus_update(void)
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:304
bool can_unit_survive_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:476
const struct option_set * server_optset
Definition options.c:4009
bool option_bool_get(const struct option *poption)
Definition options.c:772
struct client_options gui_options
Definition options.c:71
struct option * optset_option_by_name(const struct option_set *poptset, const char *name)
Definition options.c:406
void refresh_overview_canvas(void)
#define REQEST_PLAYER_INITIATED
Definition packets.h:70
int dsend_packet_unit_do_action(struct connection *pc, int actor_id16, int actor_id32, int target_id, int sub_tgt_id, const char *name, action_id action_type)
int dsend_packet_unit_sscs_set(struct connection *pc, int unit_id16, int unit_id32, enum unit_ss_data_type type, int value)
int send_packet_unit_orders(struct connection *pc, const struct packet_unit_orders *packet)
int send_packet_edit_recalculate_borders(struct connection *pc)
int dsend_packet_unit_get_actions(struct connection *pc, int actor_unit_id16, int actor_unit_id32, int target_unit_id16, int target_unit_id32, int target_tile_id, int target_extra_id, int request_kind)
int dsend_packet_unit_action_query(struct connection *pc, int actor_id16, int actor_id32, int target_id, action_id action_type, int request_kind)
int dsend_packet_unit_server_side_agent_set(struct connection *pc, int unit_id16, int unit_id32, enum server_side_agent agent)
int dsend_packet_unit_change_activity(struct connection *pc, int unit_id16, int unit_id32, enum unit_activity activity, int target)
int dsend_packet_city_name_suggestion_req(struct connection *pc, int unit_id16, int unit_id32)
int dsend_packet_edit_toggle_fogofwar(struct connection *pc, int player)
int dsend_packet_edit_mode(struct connection *pc, bool state)
const struct pf_position * pf_path_last_position(const struct pf_path *path)
void pf_path_destroy(struct pf_path *path)
struct unit * player_unit_by_number(const struct player *pplayer, int unit_id)
Definition player.c:1205
struct city * player_primary_capital(const struct player *pplayer)
Definition player.c:1313
bool can_player_see_units_in_city(const struct player *pplayer, const struct city *pcity)
Definition player.c:1113
bool can_player_see_city_internals(const struct player *pplayer, const struct city *pcity)
Definition player.c:1129
#define players_iterate_alive_end
Definition player.h:545
#define players_iterate_alive(_pplayer)
Definition player.h:540
bool are_reqs_active(const struct req_context *context, const struct player *other_player, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
bool can_build_road(const struct civ_map *nmap, struct road_type *proad, const struct unit *punit, const struct tile *ptile)
Definition road.c:295
bool player_can_build_road(const struct civ_map *nmap, const struct road_type *proad, const struct player *pplayer, const struct tile *ptile)
Definition road.c:280
#define FC_INFINITY
Definition shared.h:36
action_id id
Definition actions.h:380
Definition agents.h:40
Definition city.h:309
int id
Definition city.h:315
enum capital_type capital
Definition city.h:317
struct packet_game_info info
Definition game.h:89
struct connection conn
Definition client_main.h:96
bool draw_native
Definition options.h:207
bool enable_cursor_changes
Definition options.h:166
bool auto_turn_done
Definition options.h:157
bool draw_specials
Definition options.h:199
bool draw_city_output
Definition options.h:186
bool draw_city_names
Definition options.h:188
bool draw_city_productions
Definition options.h:190
int smooth_move_unit_msec
Definition options.h:144
bool draw_mines
Definition options.h:197
bool draw_borders
Definition options.h:206
bool draw_fortress_airbase
Definition options.h:198
bool draw_city_buycost
Definition options.h:191
bool draw_unit_stack_size
Definition options.h:210
bool draw_irrigation
Definition options.h:196
bool draw_terrain
Definition options.h:193
bool draw_units
Definition options.h:203
bool auto_center_on_automated
Definition options.h:149
bool draw_fog_of_war
Definition options.h:205
bool draw_city_trade_routes
Definition options.h:192
bool unit_selection_clears_orders
Definition options.h:168
bool draw_unit_shields
Definition options.h:209
bool draw_cities
Definition options.h:202
bool draw_map_grid
Definition options.h:187
bool draw_city_growth
Definition options.h:189
bool draw_focus_unit
Definition options.h:204
bool draw_city_outlines
Definition options.h:185
bool draw_coastline
Definition options.h:194
bool popup_actor_arrival
Definition options.h:161
bool draw_full_citybar
Definition options.h:208
bool draw_roads_rails
Definition options.h:195
bool draw_pollution
Definition options.h:201
bool auto_center_on_unit
Definition options.h:148
bool solid_color_behind_units
Definition options.h:142
bool popup_last_move_to_allied
Definition options.h:163
bool keyboardless_goto
Definition options.h:165
struct player * playing
Definition connection.h:156
struct connection::@57::@62 client
int last_request_id_used
Definition connection.h:192
struct requirement_vector reqs
Definition extras.h:102
struct unit_order orders[MAX_LEN_ROUTE]
struct unit_list * units
Definition player.h:282
bool is_alive
Definition player.h:268
bool phase_done
Definition player.h:263
const struct unit * unit
Definition tile.h:49
int index
Definition tile.h:50
struct unit_list * units
Definition tile.h:57
Definition timing.c:81
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
Definition unit.h:138
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
int hp
Definition unit.h:151
struct unit::@80::@82 client
bool asking_city_name
Definition unit.h:222
struct act_prob * act_prob_cache
Definition unit.h:225
bool done_moving
Definition unit.h:181
struct tile * action_decision_tile
Definition unit.h:203
enum unit_focus_status focus_status
Definition unit.h:211
enum server_side_agent ssa_controller
Definition unit.h:172
enum universals_n kind
Definition fc_types.h:758
struct civ_map map
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define fc__fallthrough
Definition support.h:109
struct extra_type * get_preferred_pillage(bv_extras extras)
Definition terrain.c:538
int terrain_extra_build_time(const struct terrain *pterrain, enum unit_activity activity, const struct extra_type *tgt)
Definition terrain.c:682
#define T_UNKNOWN
Definition terrain.h:57
void tile_add_extra(struct tile *ptile, const struct extra_type *pextra)
Definition tile.c:940
void tile_virtual_destroy(struct tile *vtile)
Definition tile.c:1018
bool tile_has_road(const struct tile *ptile, const struct road_type *proad)
Definition tile.c:829
struct tile * tile_virtual_new(const struct tile *ptile)
Definition tile.c:966
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_index(_pt_)
Definition tile.h:87
#define tile_hash_iterate(hash, ptile)
Definition tile.h:81
#define tile_terrain(_tile)
Definition tile.h:109
#define tile_hash_iterate_end
Definition tile.h:83
#define tile_continent(_tile)
Definition tile.h:91
#define tile_has_extra(ptile, pextra)
Definition tile.h:146
double get_focus_unit_toggle_timeout(const struct tileset *t)
Definition tilespec.c:6257
void toggle_focus_unit_state(struct tileset *t)
Definition tilespec.c:6289
void focus_unit_in_combat(struct tileset *t)
Definition tilespec.c:6278
cursor_type
Definition tilespec.h:285
@ CURSOR_GOTO
Definition tilespec.h:286
@ CURSOR_INVALID
Definition tilespec.h:291
@ CURSOR_PATROL
Definition tilespec.h:287
@ CURSOR_WAIT
Definition tilespec.h:295
@ CURSOR_SELECT
Definition tilespec.h:290
@ CURSOR_DEFAULT
Definition tilespec.h:297
@ CURSOR_PARADROP
Definition tilespec.h:288
@ CURSOR_NUKE
Definition tilespec.h:289
@ CURSOR_ATTACK
Definition tilespec.h:292
void timer_start(struct timer *t)
Definition timing.c:224
double timer_read_seconds(struct timer *t)
Definition timing.c:344
struct timer * timer_renew(struct timer *t, enum timer_timetype type, enum timer_use use)
Definition timing.c:176
@ TIMER_ACTIVE
Definition timing.h:45
@ TIMER_USER
Definition timing.h:41
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1767
bool is_attack_unit(const struct unit *punit)
Definition unit.c:307
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2425
bool is_military_unit(const struct unit *punit)
Definition unit.c:319
bool could_unit_load(const struct unit *pcargo, const struct unit *ptrans)
Definition unit.c:719
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
int get_transporter_capacity(const struct unit *punit)
Definition unit.c:299
bool can_unit_paradrop(const struct civ_map *nmap, const struct unit *punit)
Definition unit.c:826
void unit_tile_set(struct unit *punit, struct tile *ptile)
Definition unit.c:1281
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2409
bool can_unit_unload(const struct unit *pcargo, const struct unit *ptrans)
Definition unit.c:771
bool unit_has_orders(const struct unit *punit)
Definition unit.c:204
struct unit * transporter_for_unit(const struct unit *pcargo)
Definition unit.c:1896
#define unit_tile(_pu)
Definition unit.h:395
unit_focus_status
Definition unit.h:52
@ FOCUS_AVAIL
Definition unit.h:53
@ FOCUS_DONE
Definition unit.h:53
@ FOCUS_WAIT
Definition unit.h:53
#define BATTLEGROUP_NONE
Definition unit.h:190
unit_orders
Definition unit.h:37
@ ORDER_ACTION_MOVE
Definition unit.h:45
@ ORDER_ACTIVITY
Definition unit.h:41
@ ORDER_MOVE
Definition unit.h:39
@ ORDER_LAST
Definition unit.h:49
@ ORDER_PERFORM_ACTION
Definition unit.h:47
#define unit_owner(_pu)
Definition unit.h:394
#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
#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
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
enum unit_move_type utype_move_type(const struct unit_type *punittype)
Definition unittype.c:1603
bool utype_may_act_at_all(const struct unit_type *putype)
Definition unittype.c:431
struct unit_class * unit_class_get(const struct unit *punit)
Definition unittype.c:2547
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:184
bool role_units_translations(struct astring *astr, int flag, bool alts)
Definition unittype.c:1720
void update_queue_connect_processing_finished_full(int request_id, uq_callback_t callback, void *data, uq_free_fn_t free_data_func)