Correctly handle negated requirements in client help describing which
[freeciv.git] / client / control.c
blob0e98e37667f33db5f8b1d6fc9720947ab3077d47
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.
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 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 /* utility */
19 #include "bitvector.h"
20 #include "fcintl.h"
21 #include "log.h"
22 #include "mem.h"
23 #include "timing.h"
25 /* common */
26 #include "game.h"
27 #include "map.h"
28 #include "movement.h"
30 /* client */
31 #include "audio.h"
32 #include "chatline_g.h"
33 #include "citydlg_g.h"
34 #include "client_main.h"
35 #include "climap.h"
36 #include "climisc.h"
37 #include "combat.h"
38 #include "dialogs_g.h"
39 #include "editor.h"
40 #include "goto.h"
41 #include "gui_main_g.h"
42 #include "mapctrl_g.h"
43 #include "mapview_g.h"
44 #include "menu_g.h"
45 #include "options.h"
46 #include "overview_common.h"
47 #include "tilespec.h"
48 #include "unitlist.h"
50 #include "control.h"
52 /* gui-dep code may adjust depending on tile size etc: */
53 int num_units_below = MAX_NUM_UNITS_BELOW;
55 /* current_focus points to the current unit(s) in focus */
56 static struct unit_list *current_focus = NULL;
58 /* The previously focused unit(s). Focus can generally be recalled
59 * with keypad 5 (or the equivalent). */
60 static struct unit_list *previous_focus = NULL;
62 /* The priority unit(s) for unit_focus_advance(). */
63 static struct unit_list *urgent_focus_queue = NULL;
65 /* These should be set via set_hover_state() */
66 enum cursor_hover_state hover_state = HOVER_NONE;
67 enum unit_activity connect_activity;
68 struct act_tgt connect_tgt;
69 enum unit_orders goto_last_order; /* Last order for goto */
71 static struct tile *hover_tile = NULL;
72 static struct unit_list *battlegroups[MAX_NUM_BATTLEGROUPS];
74 /* units involved in current combat */
75 static struct unit *punit_attacking = NULL;
76 static struct unit *punit_defending = NULL;
78 /* unit arrival lists */
79 static struct genlist *caravan_arrival_queue = NULL;
80 static struct genlist *diplomat_arrival_queue = NULL;
83 * This variable is TRUE iff a NON-AI controlled unit was focused this
84 * turn.
86 bool non_ai_unit_focus;
88 /*************************************************************************/
90 static struct unit *quickselect(struct tile *ptile,
91 enum quickselect_type qtype);
93 /**************************************************************************
94 Called only by client_game_init() in client/client_main.c
95 **************************************************************************/
96 void control_init(void)
98 int i;
100 caravan_arrival_queue = genlist_new();
101 diplomat_arrival_queue = genlist_new_full(free);
103 current_focus = unit_list_new();
104 previous_focus = unit_list_new();
105 urgent_focus_queue = unit_list_new();
107 for (i = 0; i < MAX_NUM_BATTLEGROUPS; i++) {
108 battlegroups[i] = unit_list_new();
110 hover_tile = NULL;
113 /**************************************************************************
114 Called only by client_game_free() in client/client_main.c
115 **************************************************************************/
116 void control_free(void)
118 int i;
120 genlist_destroy(caravan_arrival_queue);
121 caravan_arrival_queue = NULL;
123 genlist_destroy(diplomat_arrival_queue);
124 diplomat_arrival_queue = NULL;
126 unit_list_destroy(current_focus);
127 current_focus = NULL;
128 unit_list_destroy(previous_focus);
129 previous_focus = NULL;
130 unit_list_destroy(urgent_focus_queue);
131 urgent_focus_queue = NULL;
133 for (i = 0; i < MAX_NUM_BATTLEGROUPS; i++) {
134 unit_list_destroy(battlegroups[i]);
135 battlegroups[i] = NULL;
138 set_hover_state(NULL, HOVER_NONE, ACTIVITY_LAST, NULL, ORDER_LAST);
139 free_client_goto();
142 /**************************************************************************
143 Returns list of units currently in focus.
144 **************************************************************************/
145 struct unit_list *get_units_in_focus(void)
147 return current_focus;
150 /****************************************************************************
151 Return the number of units currently in focus (0 or more).
152 ****************************************************************************/
153 int get_num_units_in_focus(void)
155 return (NULL != current_focus ? unit_list_size(current_focus) : 0);
158 /**************************************************************************
159 Store the focus unit(s). This is used so that we can return to the
160 previously focused unit with an appropriate keypress.
161 **************************************************************************/
162 static void store_previous_focus(void)
164 if (get_num_units_in_focus() > 0) {
165 unit_list_clear(previous_focus);
166 unit_list_iterate(get_units_in_focus(), punit) {
167 unit_list_append(previous_focus, punit);
168 } unit_list_iterate_end;
172 /****************************************************************************
173 Store a priority focus unit.
174 ****************************************************************************/
175 void unit_focus_urgent(struct unit *punit)
177 unit_list_append(urgent_focus_queue, punit);
180 /**************************************************************************
181 Do various updates required when the set of units in focus changes.
182 **************************************************************************/
183 static void focus_units_changed(void)
185 update_unit_info_label(get_units_in_focus());
186 menus_update();
187 /* Notify the GUI */
188 real_focus_units_changed();
191 /**************************************************************************
192 Called when a unit is killed; this removes it from the control lists.
193 **************************************************************************/
194 void control_unit_killed(struct unit *punit)
196 int i;
198 goto_unit_killed(punit);
200 unit_list_remove(get_units_in_focus(), punit);
201 if (get_num_units_in_focus() < 1) {
202 set_hover_state(NULL, HOVER_NONE, ACTIVITY_LAST, NULL, ORDER_LAST);
205 unit_list_remove(previous_focus, punit);
206 unit_list_remove(urgent_focus_queue, punit);
208 for (i = 0; i < MAX_NUM_BATTLEGROUPS; i++) {
209 unit_list_remove(battlegroups[i], punit);
212 focus_units_changed();
215 /**************************************************************************
216 Change the battlegroup for this unit.
217 **************************************************************************/
218 void unit_change_battlegroup(struct unit *punit, int battlegroup)
220 if (battlegroup < 0 || battlegroup >= MAX_NUM_BATTLEGROUPS) {
221 battlegroup = BATTLEGROUP_NONE;
224 if (punit->battlegroup != battlegroup) {
225 if (battlegroup != BATTLEGROUP_NONE) {
226 unit_list_append(battlegroups[battlegroup], punit);
228 if (punit->battlegroup != BATTLEGROUP_NONE) {
229 unit_list_remove(battlegroups[punit->battlegroup], punit);
231 punit->battlegroup = battlegroup;
235 /**************************************************************************
236 Call this on new units to enter them in the battlegroup lists.
237 **************************************************************************/
238 void unit_register_battlegroup(struct unit *punit)
240 if (punit->battlegroup < 0 || punit->battlegroup >= MAX_NUM_BATTLEGROUPS) {
241 punit->battlegroup = BATTLEGROUP_NONE;
242 } else {
243 unit_list_append(battlegroups[punit->battlegroup], punit);
247 /**************************************************************************
248 Enter the given hover state.
250 activity => The connect activity (ACTIVITY_IRRIGATE, etc.)
251 order => The last order (ORDER_BUILD_CITY, ORDER_LAST, etc.)
252 **************************************************************************/
253 void set_hover_state(struct unit_list *punits, enum cursor_hover_state state,
254 enum unit_activity activity,
255 struct act_tgt *tgt,
256 enum unit_orders order)
258 fc_assert_ret((punits && unit_list_size(punits) > 0)
259 || state == HOVER_NONE);
260 fc_assert_ret(state == HOVER_CONNECT || activity == ACTIVITY_LAST);
261 fc_assert_ret(state == HOVER_GOTO || order == ORDER_LAST);
262 hover_state = state;
263 connect_activity = activity;
264 if (tgt) {
265 connect_tgt = *tgt;
266 } else {
267 connect_tgt.type = ATT_SPECIAL;
268 connect_tgt.obj.spe = S_LAST;
270 goto_last_order = order;
271 exit_goto_state();
274 /****************************************************************************
275 Return TRUE iff this unit is in focus.
276 ****************************************************************************/
277 bool unit_is_in_focus(const struct unit *punit)
279 return unit_list_search(get_units_in_focus(), punit) != NULL;
282 /****************************************************************************
283 Return TRUE iff a unit on this tile is in focus.
284 ****************************************************************************/
285 struct unit *get_focus_unit_on_tile(const struct tile *ptile)
287 unit_list_iterate(get_units_in_focus(), punit) {
288 if (unit_tile(punit) == ptile) {
289 return punit;
291 } unit_list_iterate_end;
293 return NULL;
296 /****************************************************************************
297 Return head of focus units list.
298 ****************************************************************************/
299 struct unit *head_of_units_in_focus(void)
301 return unit_list_get(current_focus, 0);
304 /****************************************************************************
305 Finds a single focus unit that we can center on. May return NULL.
306 ****************************************************************************/
307 static struct tile *find_a_focus_unit_tile_to_center_on(void)
309 struct unit *punit;
311 if (NULL != (punit = get_focus_unit_on_tile(get_center_tile_mapcanvas()))) {
312 return unit_tile(punit);
313 } else if (get_num_units_in_focus() > 0) {
314 return unit_tile(head_of_units_in_focus());
315 } else {
316 return NULL;
320 /**************************************************************************
321 Center on the focus unit, if off-screen and auto_center_on_unit is true.
322 **************************************************************************/
323 void auto_center_on_focus_unit(void)
325 struct tile *ptile = find_a_focus_unit_tile_to_center_on();
327 if (ptile && auto_center_on_unit &&
328 !tile_visible_and_not_on_border_mapcanvas(ptile)) {
329 center_tile_mapcanvas(ptile);
333 /**************************************************************************
334 Add unit to list of units currently in focus.
335 **************************************************************************/
336 static void current_focus_append(struct unit *punit)
338 unit_list_append(current_focus, punit);
340 punit->client.focus_status = FOCUS_AVAIL;
341 refresh_unit_mapcanvas(punit, unit_tile(punit), TRUE, FALSE);
343 if (unit_selection_clears_orders) {
344 clear_unit_orders(punit);
348 /**************************************************************************
349 Remove focus from unit.
350 **************************************************************************/
351 static void current_focus_remove(struct unit *punit)
353 unit_list_remove(current_focus, punit);
354 refresh_unit_mapcanvas(punit, unit_tile(punit), TRUE, FALSE);
357 /**************************************************************************
358 Clear all orders for the given unit.
359 **************************************************************************/
360 void clear_unit_orders(struct unit *punit)
362 if (!punit) {
363 return;
366 if (punit->activity != ACTIVITY_IDLE
367 || punit->ai_controlled) {
368 punit->ai_controlled = FALSE;
369 refresh_unit_city_dialogs(punit);
370 request_new_unit_activity(punit, ACTIVITY_IDLE);
371 } else if (unit_has_orders(punit)) {
372 /* Clear the focus unit's orders. */
373 request_orders_cleared(punit);
377 /**************************************************************************
378 Sets the focus unit directly. The unit given will be given the
379 focus; if NULL the focus will be cleared.
381 This function is called for several reasons. Sometimes a fast-focus
382 happens immediately as a result of a client action. Other times it
383 happens because of a server-sent packet that wakes up a unit.
384 **************************************************************************/
385 void unit_focus_set(struct unit *punit)
387 bool focus_changed = FALSE;
389 if (NULL != punit
390 && NULL != client.conn.playing
391 && unit_owner(punit) != client.conn.playing) {
392 /* Callers should make sure this never happens. */
393 return;
396 /* FIXME: this won't work quite right; for instance activating a
397 * battlegroup twice in a row will store the focus erronously. The only
398 * solution would be a set_units_focus() */
399 if (!(get_num_units_in_focus() == 1
400 && punit == head_of_units_in_focus())) {
401 store_previous_focus();
402 focus_changed = TRUE;
405 /* Redraw the old focus unit (to fix blinking or remove the selection
406 * circle). */
407 unit_list_iterate(current_focus, punit_old) {
408 refresh_unit_mapcanvas(punit_old, unit_tile(punit_old), TRUE, FALSE);
409 } unit_list_iterate_end;
410 unit_list_clear(current_focus);
412 if (!can_client_change_view()) {
413 /* This function can be called to set the focus to NULL when
414 * disconnecting. In this case we don't want any other actions! */
415 fc_assert(punit == NULL);
416 return;
419 if (NULL != punit) {
420 current_focus_append(punit);
421 auto_center_on_focus_unit();
424 if (focus_changed) {
425 set_hover_state(NULL, HOVER_NONE, ACTIVITY_LAST, NULL, ORDER_LAST);
426 focus_units_changed();
430 /**************************************************************************
431 Adds this unit to the list of units in focus.
432 **************************************************************************/
433 void unit_focus_add(struct unit *punit)
435 if (NULL != punit
436 && NULL != client.conn.playing
437 && unit_owner(punit) != client.conn.playing) {
438 /* Callers should make sure this never happens. */
439 return;
442 if (NULL == punit || !can_client_change_view()) {
443 return;
446 if (unit_is_in_focus(punit)) {
447 return;
450 if (hover_state != HOVER_NONE) {
451 /* Can't continue with current goto if set of focus units
452 * change. Cancel it. */
453 set_hover_state(NULL, HOVER_NONE, ACTIVITY_LAST, NULL, ORDER_LAST);
456 current_focus_append(punit);
457 focus_units_changed();
460 /**************************************************************************
461 Removes this unit from the list of units in focus.
462 **************************************************************************/
463 void unit_focus_remove(struct unit *punit)
465 if (NULL != punit
466 && NULL != client.conn.playing
467 && unit_owner(punit) != client.conn.playing) {
468 /* Callers should make sure this never happens. */
469 return;
472 if (NULL == punit || !can_client_change_view()) {
473 return;
476 if (!unit_is_in_focus(punit)) {
477 return;
480 current_focus_remove(punit);
481 focus_units_changed();
484 /**************************************************************************
485 The only difference is that here we draw the "cross".
486 **************************************************************************/
487 void unit_focus_set_and_select(struct unit *punit)
489 unit_focus_set(punit);
490 if (punit) {
491 put_cross_overlay_tile(unit_tile(punit));
495 /**************************************************************************
496 Find the nearest available unit for focus, excluding any current unit
497 in focus unless "accept_current" is TRUE. If the current focus unit
498 is the only possible unit, or if there is no possible unit, returns NULL.
499 **************************************************************************/
500 static struct unit *find_best_focus_candidate(bool accept_current)
502 struct tile *ptile = get_center_tile_mapcanvas();
504 if (!get_focus_unit_on_tile(ptile)) {
505 struct unit *pfirst = head_of_units_in_focus();
507 if (pfirst) {
508 ptile = unit_tile(pfirst);
512 iterate_outward(ptile, FC_INFINITY, ptile2) {
513 unit_list_iterate(ptile2->units, punit) {
514 if ((!unit_is_in_focus(punit) || accept_current)
515 && unit_owner(punit) == client.conn.playing
516 && punit->client.focus_status == FOCUS_AVAIL
517 && punit->activity == ACTIVITY_IDLE
518 && !unit_has_orders(punit)
519 && (punit->moves_left > 0 || unit_type(punit)->move_rate == 0)
520 && !punit->done_moving
521 && !punit->ai_controlled) {
522 return punit;
524 } unit_list_iterate_end;
525 } iterate_outward_end;
527 return NULL;
530 /**************************************************************************
531 This function may be called from packhand.c, via unit_focus_update(),
532 as a result of packets indicating change in activity for a unit. Also
533 called when user press the "Wait" command.
535 FIXME: Add feature to focus only units of a certain category.
536 **************************************************************************/
537 void unit_focus_advance(void)
539 struct unit *candidate = NULL;
540 const int num_units_in_old_focus = get_num_units_in_focus();
542 if (NULL == client.conn.playing
543 || !is_player_phase(client.conn.playing, game.info.phase)
544 || !can_client_change_view()) {
545 unit_focus_set(NULL);
546 return;
549 set_hover_state(NULL, HOVER_NONE, ACTIVITY_LAST, NULL, ORDER_LAST);
551 unit_list_iterate(get_units_in_focus(), punit) {
553 * Is the unit which just lost focus a non-AI unit? If yes this
554 * enables the auto end turn.
556 if (!punit->ai_controlled) {
557 non_ai_unit_focus = TRUE;
558 break;
560 } unit_list_iterate_end;
562 if (unit_list_size(urgent_focus_queue) > 0) {
563 /* Try top of the urgent list. */
564 candidate = unit_list_get(urgent_focus_queue, 0);
566 if (get_num_units_in_focus() > 0) {
567 /* Rarely, more than one unit on the same tile will be in the list. */
568 unit_list_iterate(urgent_focus_queue, punit) {
569 if (unit_tile(head_of_units_in_focus()) == unit_tile(punit)) {
570 /* Use the first one found */
571 candidate = punit;
572 break;
574 } unit_list_iterate_end;
576 unit_list_remove(urgent_focus_queue, candidate);
578 /* Autocenter on Wakeup, regardless of the local option
579 * "auto_center_on_unit". */
580 if (!tile_visible_and_not_on_border_mapcanvas(unit_tile(candidate))) {
581 center_tile_mapcanvas(unit_tile(candidate));
583 } else {
584 candidate = find_best_focus_candidate(FALSE);
586 if (!candidate) {
587 /* Try for "waiting" units. */
588 unit_list_iterate(client.conn.playing->units, punit) {
589 if(punit->client.focus_status == FOCUS_WAIT) {
590 punit->client.focus_status = FOCUS_AVAIL;
592 } unit_list_iterate_end;
593 candidate = find_best_focus_candidate(FALSE);
595 if (!candidate) {
596 /* Accept current focus unit as last resort. */
597 candidate = find_best_focus_candidate(TRUE);
602 unit_focus_set(candidate);
605 * Handle auto-turn-done mode: If a unit was in focus (did move),
606 * but now none are (no more to move) and there was at least one
607 * non-AI unit this turn which was focused, then fake a Turn Done
608 * keypress.
610 if (auto_turn_done
611 && num_units_in_old_focus > 0
612 && get_num_units_in_focus() == 0
613 && non_ai_unit_focus) {
614 key_end_turn();
618 /**************************************************************************
619 If there is no unit currently in focus, or if the current unit in
620 focus should not be in focus, then get a new focus unit.
621 We let GOTO-ing units stay in focus, so that if they have moves left
622 at the end of the goto, then they are still in focus.
623 **************************************************************************/
624 void unit_focus_update(void)
626 if (NULL == client.conn.playing || !can_client_change_view()) {
627 return;
630 /* iterate zero times for no units in focus,
631 * otherwise quit for any of the conditions. */
632 unit_list_iterate(get_units_in_focus(), punit) {
633 if ((punit->activity == ACTIVITY_IDLE
634 || punit->activity == ACTIVITY_GOTO
635 || unit_has_orders(punit))
636 && punit->moves_left > 0
637 && !punit->done_moving
638 && !punit->ai_controlled) {
639 return;
641 } unit_list_iterate_end;
643 unit_focus_advance();
646 /**************************************************************************
647 Return a pointer to a visible unit, if there is one.
648 **************************************************************************/
649 struct unit *find_visible_unit(struct tile *ptile)
651 struct unit *panyowned = NULL, *panyother = NULL, *ptptother = NULL;
652 struct unit *pfocus;
654 /* If no units here, return nothing. */
655 if (unit_list_size(ptile->units)==0) {
656 return NULL;
659 /* If a unit is attacking we should show that on top */
660 if (punit_attacking && same_pos(unit_tile(punit_attacking), ptile)) {
661 unit_list_iterate(ptile->units, punit)
662 if(punit == punit_attacking) return punit;
663 unit_list_iterate_end;
666 /* If a unit is defending we should show that on top */
667 if (punit_defending && same_pos(unit_tile(punit_defending), ptile)) {
668 unit_list_iterate(ptile->units, punit)
669 if(punit == punit_defending) return punit;
670 unit_list_iterate_end;
673 /* If the unit in focus is at this tile, show that on top */
674 if ((pfocus = get_focus_unit_on_tile(ptile))) {
675 return pfocus;
678 /* If a city is here, return nothing (unit hidden by city). */
679 if (tile_city(ptile)) {
680 return NULL;
683 /* Iterate through the units to find the best one we prioritize this way:
684 1: owned transporter.
685 2: any owned unit
686 3: any transporter
687 4: any unit
688 (always return first in stack). */
689 unit_list_iterate(ptile->units, punit)
690 if (unit_owner(punit) == client.conn.playing) {
691 if (!unit_transported(punit)) {
692 if (get_transporter_capacity(punit) > 0) {
693 return punit;
694 } else if (!panyowned) {
695 panyowned = punit;
698 } else if (!ptptother && !unit_transported(punit)) {
699 if (get_transporter_capacity(punit) > 0) {
700 ptptother = punit;
701 } else if (!panyother) {
702 panyother = punit;
705 unit_list_iterate_end;
707 return (panyowned ? panyowned : (ptptother ? ptptother : panyother));
710 /**************************************************************************
711 Blink the active unit (if necessary). Return the time until the next
712 blink (in seconds).
713 **************************************************************************/
714 double blink_active_unit(void)
716 static struct timer *blink_timer = NULL;
717 const double blink_time = get_focus_unit_toggle_timeout(tileset);
719 if (get_num_units_in_focus() > 0) {
720 if (!blink_timer || timer_read_seconds(blink_timer) > blink_time) {
721 toggle_focus_unit_state(tileset);
723 /* If we lag, we don't try to catch up. Instead we just start a
724 * new blink_time on every update. */
725 blink_timer = timer_renew(blink_timer, TIMER_USER, TIMER_ACTIVE);
726 timer_start(blink_timer);
728 unit_list_iterate(get_units_in_focus(), punit) {
729 /* We flush to screen directly here. This is most likely faster
730 * since these drawing operations are all small but may be spread
731 * out widely. */
732 refresh_unit_mapcanvas(punit, unit_tile(punit), FALSE, TRUE);
733 } unit_list_iterate_end;
736 return blink_time - timer_read_seconds(blink_timer);
739 return blink_time;
742 /****************************************************************************
743 Blink the turn done button (if necessary). Return the time until the next
744 blink (in seconds).
745 ****************************************************************************/
746 double blink_turn_done_button(void)
748 static struct timer *blink_timer = NULL;
749 const double blink_time = 0.5; /* half-second blink interval */
751 if (NULL != client.conn.playing
752 && client.conn.playing->is_alive
753 && !client.conn.playing->phase_done) {
754 if (!blink_timer || timer_read_seconds(blink_timer) > blink_time) {
755 int is_waiting = 0, is_moving = 0;
757 players_iterate_alive(pplayer) {
758 if (pplayer->is_connected) {
759 if (pplayer->phase_done) {
760 is_waiting++;
761 } else {
762 is_moving++;
765 } players_iterate_alive_end;
767 if (is_moving == 1 && is_waiting > 0) {
768 update_turn_done_button(FALSE); /* stress the slow player! */
770 blink_timer = timer_renew(blink_timer, TIMER_USER, TIMER_ACTIVE);
771 timer_start(blink_timer);
773 return blink_time - timer_read_seconds(blink_timer);
776 return blink_time;
779 /**************************************************************************
780 Update unit icons (and arrow) in the information display, for specified
781 punit as the active unit and other units on the same square. In practice
782 punit is almost always (or maybe strictly always?) the focus unit.
784 Static vars store some info on current (ie previous) state, to avoid
785 unnecessary redraws; initialise to "flag" values to always redraw first
786 time. In principle we _might_ need more info (eg ai.control, connecting),
787 but in practice this is enough?
789 Used to store unit_ids for below units, to use for callbacks (now done
790 inside gui-dep set_unit_icon()), but even with ids here they would not
791 be enough information to know whether to redraw -- instead redraw every
792 time. (Could store enough info to know, but is it worth it?)
793 **************************************************************************/
794 void update_unit_pix_label(struct unit_list *punitlist)
796 int i;
798 /* Check for any change in the unit's state. This assumes that a unit's
799 * orders cannot be changed directly but must be removed and then reset. */
800 if (punitlist && unit_list_size(punitlist) > 0
801 && C_S_OVER != client_state()) {
802 /* There used to be a complicated and bug-prone check here to see if
803 * the unit had actually changed. This was misguided since the stacked
804 * units (below) are redrawn in any case. Unless we write a general
805 * system for unit updates here we might as well just redraw it every
806 * time. */
807 struct unit *punit = unit_list_get(punitlist, 0);
809 set_unit_icon(-1, punit);
811 i = 0; /* index into unit_below_canvas */
812 unit_list_iterate(unit_tile(punit)->units, aunit) {
813 if (aunit != punit) {
814 if (i < num_units_below) {
815 set_unit_icon(i, aunit);
817 i++;
820 unit_list_iterate_end;
822 if (i > num_units_below) {
823 set_unit_icons_more_arrow(TRUE);
824 } else {
825 set_unit_icons_more_arrow(FALSE);
826 for(; i < num_units_below; i++) {
827 set_unit_icon(i, NULL);
830 } else {
831 for(i=-1; i<num_units_below; i++) {
832 set_unit_icon(i, NULL);
834 set_unit_icons_more_arrow(FALSE);
838 /**************************************************************************
839 Adjusts way combatants are displayed suitable for combat.
840 **************************************************************************/
841 void set_units_in_combat(struct unit *pattacker, struct unit *pdefender)
843 punit_attacking = pattacker;
844 punit_defending = pdefender;
846 if (unit_is_in_focus(punit_attacking)
847 || unit_is_in_focus(punit_defending)) {
848 /* If one of the units is the focus unit, make sure hidden-focus is
849 * disabled. We don't just do this as a check later because then
850 * with a blinking unit it would just disappear again right after the
851 * battle. */
852 focus_unit_in_combat(tileset);
856 /**************************************************************************
857 Add punit to queue of caravan arrivals, and popup a window for the
858 next arrival in the queue, if there is not already a popup, and
859 re-checking that a popup is appropriate.
860 If punit is NULL, just do for the next arrival in the queue.
861 **************************************************************************/
862 void process_caravan_arrival(struct unit *punit)
864 if (NULL == caravan_arrival_queue) {
865 /* Can happen when the user left a game. */
866 return;
869 if (NULL != punit) {
870 genlist_prepend(caravan_arrival_queue, FC_INT_TO_PTR(punit->id));
873 /* There can only be one dialog at a time: */
874 if (caravan_dialog_is_open(NULL, NULL)) {
875 return;
878 while (0 < genlist_size(caravan_arrival_queue)) {
879 void *data;
881 data = genlist_get(caravan_arrival_queue, 0);
882 genlist_remove(caravan_arrival_queue, data);
883 punit = game_unit_by_number(FC_PTR_TO_INT(data));
885 if (punit && (unit_can_help_build_wonder_here(punit)
886 || unit_can_est_trade_route_here(punit))
887 && (NULL == client.conn.playing
888 || (unit_owner(punit) == client.conn.playing
889 && !client.conn.playing->ai_controlled))) {
890 struct city *pcity_dest = tile_city(unit_tile(punit));
891 struct city *pcity_homecity = game_city_by_number(punit->homecity);
893 if (pcity_dest && pcity_homecity) {
894 popup_caravan_dialog(punit, pcity_homecity, pcity_dest);
895 return;
901 /**************************************************************************
902 Add punit/pcity to queue of diplomat arrivals, and popup a window for
903 the next arrival in the queue, if there is not already a popup, and
904 re-checking that a popup is appropriate.
905 If punit is NULL, just do for the next arrival in the queue.
906 **************************************************************************/
907 void process_diplomat_arrival(struct unit *pdiplomat, int victim_id)
909 int *p_ids;
911 if (NULL == diplomat_arrival_queue) {
912 /* Can happen when the user left a game. */
913 return;
916 /* diplomat_arrival_queue is a list of individually malloc-ed int[2]s with
917 punit.id and pcity.id values, for units which have arrived. */
919 if (pdiplomat && victim_id != 0) {
920 p_ids = fc_malloc(2*sizeof(int));
921 p_ids[0] = pdiplomat->id;
922 p_ids[1] = victim_id;
923 genlist_prepend(diplomat_arrival_queue, p_ids);
926 /* There can only be one dialog at a time: */
927 if (diplomat_handled_in_diplomat_dialog() != -1) {
928 return;
931 while (genlist_size(diplomat_arrival_queue) > 0) {
932 int diplomat_id, victim_id;
933 struct city *pcity;
934 struct unit *punit;
936 p_ids = genlist_get(diplomat_arrival_queue, 0);
937 diplomat_id = p_ids[0];
938 victim_id = p_ids[1];
939 genlist_remove(diplomat_arrival_queue, p_ids); /* Do free(p_ids). */
940 pdiplomat = player_unit_by_number(client_player(), diplomat_id);
941 pcity = game_city_by_number(victim_id);
942 punit = game_unit_by_number(victim_id);
944 if (!pdiplomat || !unit_has_type_flag(pdiplomat, UTYF_DIPLOMAT))
945 continue;
947 if (punit
948 && is_diplomat_action_available(pdiplomat, DIPLOMAT_ANY_ACTION,
949 unit_tile(punit))
950 && diplomat_can_do_action(pdiplomat, DIPLOMAT_ANY_ACTION,
951 unit_tile(punit))) {
952 popup_diplomat_dialog(pdiplomat, unit_tile(punit));
953 return;
954 } else if (pcity
955 && is_diplomat_action_available(pdiplomat, DIPLOMAT_ANY_ACTION,
956 pcity->tile)
957 && diplomat_can_do_action(pdiplomat, DIPLOMAT_ANY_ACTION,
958 pcity->tile)) {
959 popup_diplomat_dialog(pdiplomat, pcity->tile);
960 return;
965 /**************************************************************************
966 Do a goto with an order at the end (or ORDER_LAST).
967 **************************************************************************/
968 void request_unit_goto(enum unit_orders last_order)
970 struct unit_list *punits = get_units_in_focus();
972 if (unit_list_size(punits) == 0) {
973 return;
976 if (hover_state != HOVER_GOTO) {
977 set_hover_state(punits, HOVER_GOTO, ACTIVITY_LAST, NULL,
978 last_order);
979 enter_goto_state(punits);
980 create_line_at_mouse_pos();
981 update_unit_info_label(punits);
982 control_mouse_cursor(NULL);
983 } else {
984 fc_assert_ret(goto_is_active());
985 goto_add_waypoint();
989 /****************************************************************************
990 Return TRUE if at least one of the untis can do an attack at the tile.
991 ****************************************************************************/
992 static bool can_units_attack_at(struct unit_list *punits,
993 const struct tile *ptile)
995 unit_list_iterate(punits, punit) {
996 if (is_attack_unit(punit) && can_unit_attack_tile(punit, ptile)) {
997 return TRUE;
999 } unit_list_iterate_end;
1001 return FALSE;
1004 /**************************************************************************
1005 Determines which mouse cursor should be used, according to hover_state,
1006 and the information gathered from the tile which is under the mouse
1007 cursor (ptile).
1008 **************************************************************************/
1009 void control_mouse_cursor(struct tile *ptile)
1011 struct unit *punit = NULL;
1012 struct city *pcity = NULL;
1013 struct unit_list *active_units = get_units_in_focus();
1014 enum cursor_type mouse_cursor_type = CURSOR_DEFAULT;
1016 if (!enable_cursor_changes) {
1017 return;
1020 if (C_S_RUNNING != client_state()) {
1021 update_mouse_cursor(CURSOR_DEFAULT);
1022 return;
1025 if (is_server_busy()) {
1026 /* Server will not accept any commands. */
1027 update_mouse_cursor(CURSOR_WAIT);
1028 return;
1031 if (!ptile) {
1032 if (hover_tile) {
1033 /* hover_tile is the tile that was previously under the mouse cursor. */
1034 ptile = hover_tile;
1035 } else {
1036 update_mouse_cursor(CURSOR_DEFAULT);
1037 return;
1039 } else {
1040 hover_tile = ptile;
1043 punit = find_visible_unit(ptile);
1044 pcity = ptile ? tile_city(ptile) : NULL;
1046 switch (hover_state) {
1047 case HOVER_NONE:
1048 if (NULL != punit
1049 && unit_owner(punit) == client_player()) {
1050 /* Set mouse cursor to select a unit. */
1051 mouse_cursor_type = CURSOR_SELECT;
1052 } else if (NULL != pcity
1053 && can_player_see_city_internals(client.conn.playing, pcity)) {
1054 /* Set mouse cursor to select a city. */
1055 mouse_cursor_type = CURSOR_SELECT;
1056 } else {
1057 /* Set default mouse cursor, because nothing selectable found. */
1059 break;
1060 case HOVER_GOTO:
1061 /* Determine if the goto is valid, invalid or will attack. */
1062 if (is_valid_goto_destination(ptile)) {
1063 if (can_units_attack_at(active_units, ptile)) {
1064 /* Goto results in military attack. */
1065 mouse_cursor_type = CURSOR_ATTACK;
1066 } else if (is_enemy_city_tile(ptile, client.conn.playing)) {
1067 /* Goto results in attack of enemy city. */
1068 mouse_cursor_type = CURSOR_ATTACK;
1069 } else {
1070 mouse_cursor_type = CURSOR_GOTO;
1072 } else {
1073 mouse_cursor_type = CURSOR_INVALID;
1075 break;
1076 case HOVER_PATROL:
1077 if (is_valid_goto_destination(ptile)) {
1078 mouse_cursor_type = CURSOR_PATROL;
1079 } else {
1080 mouse_cursor_type = CURSOR_INVALID;
1082 break;
1083 case HOVER_CONNECT:
1084 if (is_valid_goto_destination(ptile)) {
1085 mouse_cursor_type = CURSOR_GOTO;
1086 } else {
1087 mouse_cursor_type = CURSOR_INVALID;
1089 break;
1090 case HOVER_NUKE:
1091 /* FIXME: check for invalid tiles. */
1092 mouse_cursor_type = CURSOR_NUKE;
1093 break;
1094 case HOVER_PARADROP:
1095 /* FIXME: check for invalid tiles. */
1096 mouse_cursor_type = CURSOR_PARADROP;
1097 break;
1100 update_mouse_cursor(mouse_cursor_type);
1103 /**************************************************************************
1104 Return TRUE if there are any units doing the activity on the tile.
1105 **************************************************************************/
1106 static bool is_activity_on_tile(struct tile *ptile,
1107 enum unit_activity activity)
1109 unit_list_iterate(ptile->units, punit) {
1110 if (punit->activity == activity) {
1111 return TRUE;
1113 } unit_list_iterate_end;
1115 return FALSE;
1118 /**************************************************************************
1119 Return whether the unit can connect with given activity (or with
1120 any activity if activity arg is set to ACTIVITY_IDLE)
1122 This function is client-specific.
1123 **************************************************************************/
1124 bool can_unit_do_connect(struct unit *punit,
1125 enum unit_activity activity,
1126 struct act_tgt *tgt)
1128 struct tile *ptile = unit_tile(punit);
1129 struct terrain *pterrain = tile_terrain(ptile);
1130 struct road_type *proad = NULL;
1132 /* HACK: This code duplicates that in
1133 * can_unit_do_activity_targeted_at(). The general logic here is that
1134 * the connect is allowed if both:
1135 * (1) the unit can do that activity type, in general
1136 * (2) either
1137 * (a) the activity has already been completed at this tile
1138 * (b) it can be done by the unit at this tile. */
1139 switch (activity) {
1140 case ACTIVITY_GEN_ROAD:
1141 fc_assert(tgt->type == ATT_ROAD);
1143 proad = road_by_number(tgt->obj.road);
1145 if (proad == NULL) {
1146 return FALSE;
1149 if (tile_has_road(ptile, proad)) {
1150 /* This tile has road, can unit build road to other tiles too? */
1151 return are_reqs_active(NULL, NULL, NULL, NULL,
1152 unit_type(punit), NULL, NULL,
1153 &proad->reqs, RPT_POSSIBLE);
1156 /* To start connect, unit must be able to build road to this
1157 * particular tile. */
1158 return can_build_road(proad, punit, ptile);
1160 case ACTIVITY_IRRIGATE:
1161 /* Special case for irrigation: only irrigate to make S_IRRIGATION,
1162 * never to transform tiles. */
1163 return (unit_has_type_flag(punit, UTYF_SETTLERS)
1164 && (tile_has_special(ptile, S_IRRIGATION)
1165 || (pterrain == pterrain->irrigation_result
1166 && can_be_irrigated(ptile, punit)
1167 && !is_activity_on_tile(ptile,
1168 ACTIVITY_MINE))));
1169 default:
1170 break;
1173 return FALSE;
1176 /**************************************************************************
1177 prompt player for entering destination point for unit connect
1178 (e.g. connecting with roads)
1179 **************************************************************************/
1180 void request_unit_connect(enum unit_activity activity,
1181 struct act_tgt *tgt)
1183 struct unit_list *punits = get_units_in_focus();
1185 if (!can_units_do_connect(punits, activity, tgt)) {
1186 return;
1189 if (hover_state != HOVER_CONNECT || connect_activity != activity
1190 || (activity == ACTIVITY_GEN_ROAD
1191 && !cmp_act_tgt(&connect_tgt, tgt))) {
1192 set_hover_state(punits, HOVER_CONNECT, activity, tgt, ORDER_LAST);
1193 enter_goto_state(punits);
1194 create_line_at_mouse_pos();
1195 update_unit_info_label(punits);
1196 control_mouse_cursor(NULL);
1197 } else {
1198 fc_assert_ret(goto_is_active());
1199 goto_add_waypoint();
1203 /**************************************************************************
1204 Returns one of the unit of the transporter which can have focus next.
1205 **************************************************************************/
1206 struct unit *request_unit_unload_all(struct unit *punit)
1208 struct tile *ptile = unit_tile(punit);
1209 struct unit *plast = NULL;
1211 if (get_transporter_capacity(punit) == 0) {
1212 create_event(unit_tile(punit), E_BAD_COMMAND, ftc_client,
1213 _("Only transporter units can be unloaded."));
1214 return NULL;
1217 unit_list_iterate(ptile->units, pcargo) {
1218 if (unit_transport_get(pcargo) == punit) {
1219 request_unit_unload(pcargo);
1221 if (pcargo->activity == ACTIVITY_SENTRY) {
1222 request_new_unit_activity(pcargo, ACTIVITY_IDLE);
1225 if (unit_owner(pcargo) == unit_owner(punit)) {
1226 plast = pcargo;
1229 } unit_list_iterate_end;
1231 return plast;
1234 /**************************************************************************
1235 Send unit airlift request to server.
1236 **************************************************************************/
1237 void request_unit_airlift(struct unit *punit, struct city *pcity)
1239 dsend_packet_unit_airlift(&client.conn, punit->id, pcity->id);
1242 /**************************************************************************
1243 Return-and-recover for a particular unit. This sets the unit to GOTO
1244 the nearest city.
1245 **************************************************************************/
1246 void request_unit_return(struct unit *punit)
1248 struct pf_path *path;
1250 if ((path = path_to_nearest_allied_city(punit))) {
1251 int turns = pf_path_last_position(path)->turn;
1252 int max_hp = unit_type(punit)->hp;
1254 if (punit->hp + turns *
1255 (get_unit_bonus(punit, EFT_UNIT_RECOVER)
1256 - (max_hp * unit_class(punit)->hp_loss_pct / 100))
1257 < max_hp) {
1258 struct unit_order order;
1260 order.order = ORDER_ACTIVITY;
1261 order.dir = -1;
1262 order.activity = ACTIVITY_SENTRY;
1263 order.base = BASE_NONE;
1264 order.road = ROAD_NONE;
1265 send_goto_path(punit, path, &order);
1266 } else {
1267 send_goto_path(punit, path, NULL);
1269 pf_path_destroy(path);
1273 /**************************************************************************
1274 Wakes all owned sentried units on tile.
1275 **************************************************************************/
1276 void wakeup_sentried_units(struct tile *ptile)
1278 if (!can_client_issue_orders()) {
1279 return;
1281 unit_list_iterate(ptile->units, punit) {
1282 if (punit->activity == ACTIVITY_SENTRY
1283 && unit_owner(punit) == client.conn.playing) {
1284 request_new_unit_activity(punit, ACTIVITY_IDLE);
1287 unit_list_iterate_end;
1290 /**************************************************************************
1291 (RP:) un-sentry all my own sentried units on punit's tile
1292 **************************************************************************/
1293 void request_unit_wakeup(struct unit *punit)
1295 wakeup_sentried_units(unit_tile(punit));
1298 /****************************************************************************
1299 Defines specific hash tables needed for request_unit_select().
1300 ****************************************************************************/
1301 #define SPECHASH_TAG unit_type
1302 #define SPECHASH_KEY_TYPE struct unit_type *
1303 #define SPECHASH_DATA_TYPE void *
1304 #include "spechash.h"
1306 #define SPECHASH_TAG continent
1307 #define SPECHASH_KEY_TYPE Continent_id
1308 #define SPECHASH_DATA_TYPE void *
1309 #define SPECHASH_KEY_TO_PTR FC_INT_TO_PTR
1310 #define SPECHASH_PTR_TO_KEY FC_PTR_TO_INT
1311 #include "spechash.h"
1313 /****************************************************************************
1314 Select all units based on the given list of units and the selection modes.
1315 ****************************************************************************/
1316 void request_unit_select(struct unit_list *punits,
1317 enum unit_select_type_mode seltype,
1318 enum unit_select_location_mode selloc)
1320 const struct player *pplayer;
1321 const struct tile *ptile;
1322 struct unit *punit_first;
1323 struct tile_hash *tile_table;
1324 struct unit_type_hash *type_table;
1325 struct continent_hash *cont_table;
1327 if (!can_client_change_view() || !punits
1328 || unit_list_size(punits) < 1) {
1329 return;
1332 punit_first = unit_list_get(punits, 0);
1334 if (seltype == SELTYPE_SINGLE) {
1335 unit_focus_set(punit_first);
1336 return;
1339 pplayer = unit_owner(punit_first);
1340 tile_table = tile_hash_new();
1341 type_table = unit_type_hash_new();
1342 cont_table = continent_hash_new();
1344 unit_list_iterate(punits, punit) {
1345 if (seltype == SELTYPE_SAME) {
1346 unit_type_hash_insert(type_table, unit_type(punit), NULL);
1349 ptile = unit_tile(punit);
1350 if (selloc == SELLOC_TILE) {
1351 tile_hash_insert(tile_table, ptile, NULL);
1352 } else if (selloc == SELLOC_CONT) {
1353 continent_hash_insert(cont_table, tile_continent(ptile), NULL);
1355 } unit_list_iterate_end;
1357 if (selloc == SELLOC_TILE) {
1358 tile_hash_iterate(tile_table, ptile) {
1359 unit_list_iterate(ptile->units, punit) {
1360 if (unit_owner(punit) != pplayer) {
1361 continue;
1363 if (seltype == SELTYPE_SAME
1364 && !unit_type_hash_lookup(type_table, unit_type(punit), NULL)) {
1365 continue;
1367 unit_focus_add(punit);
1368 } unit_list_iterate_end;
1369 } tile_hash_iterate_end;
1370 } else {
1371 unit_list_iterate(pplayer->units, punit) {
1372 ptile = unit_tile(punit);
1373 if ((seltype == SELTYPE_SAME
1374 && !unit_type_hash_lookup(type_table, unit_type(punit), NULL))
1375 || (selloc == SELLOC_CONT
1376 && !continent_hash_lookup(cont_table, tile_continent(ptile),
1377 NULL))) {
1378 continue;
1381 unit_focus_add(punit);
1382 } unit_list_iterate_end;
1385 tile_hash_destroy(tile_table);
1386 unit_type_hash_destroy(type_table);
1387 continent_hash_destroy(cont_table);
1390 /**************************************************************************
1391 Request a diplomat to do a specific action.
1392 - action : The action to be requested.
1393 - dipl_id : The unit ID of the diplomatic unit.
1394 - target_id : The ID of the target unit or city.
1395 - value : For DIPLOMAT_STEAL or DIPLOMAT_SABOTAGE, the technology
1396 or building to aim for (spies only).
1397 **************************************************************************/
1398 void request_diplomat_action(enum diplomat_actions action, int dipl_id,
1399 int target_id, int value)
1401 dsend_packet_unit_diplomat_action(&client.conn, dipl_id,target_id,value,action);
1404 /**************************************************************************
1405 Query a diplomat about costs and infrastructure.
1406 - action : The action to be requested.
1407 - dipl_id : The unit ID of the diplomatic unit.
1408 - target_id : The ID of the target unit or city.
1409 - value : For DIPLOMAT_STEAL or DIPLOMAT_SABOTAGE, the technology
1410 or building to aim for (spies only).
1411 **************************************************************************/
1412 void request_diplomat_answer(enum diplomat_actions action, int dipl_id,
1413 int target_id, int value)
1415 dsend_packet_unit_diplomat_query(&client.conn, dipl_id,target_id,value,action);
1418 /**************************************************************************
1419 Player pressed 'b' or otherwise instructed unit to build or add to city.
1420 If the unit can build a city, we popup the appropriate dialog.
1421 Otherwise, we just send a packet to the server.
1422 If this action is not appropriate, the server will respond
1423 with an appropriate message. (This is to avoid duplicating
1424 all the server checks and messages here.)
1425 **************************************************************************/
1426 void request_unit_build_city(struct unit *punit)
1428 if (unit_can_build_city(punit)) {
1429 dsend_packet_city_name_suggestion_req(&client.conn, punit->id);
1430 /* the reply will trigger a dialog to name the new city */
1431 } else {
1432 char name[] = "";
1433 dsend_packet_unit_build_city(&client.conn, punit->id, name);
1437 /**************************************************************************
1438 This function is called whenever the player pressed an arrow key.
1440 We do NOT take into account that punit might be a caravan or a diplomat
1441 trying to move into a city, or a diplomat going into a tile with a unit;
1442 the server will catch those cases and send the client a package to pop up
1443 a dialog. (the server code has to be there anyway as goto's are entirely
1444 in the server)
1445 **************************************************************************/
1446 void request_move_unit_direction(struct unit *punit, int dir)
1448 struct tile *dest_tile;
1450 /* Catches attempts to move off map */
1451 dest_tile = mapstep(unit_tile(punit), dir);
1452 if (!dest_tile) {
1453 return;
1456 if (punit->moves_left > 0) {
1457 dsend_packet_unit_move(&client.conn, punit->id, tile_index(dest_tile));
1458 } else {
1459 /* Initiate a "goto" with direction keys for exhausted units. */
1460 send_goto_tile(punit, dest_tile);
1464 /**************************************************************************
1465 Send request for unit activity changing to server. If activity has
1466 target, use request_new_unit_activity_targeted() instead.
1467 **************************************************************************/
1468 void request_new_unit_activity(struct unit *punit, enum unit_activity act)
1470 if (!can_client_issue_orders()) {
1471 return;
1474 dsend_packet_unit_change_activity(&client.conn, punit->id, act,
1475 S_LAST);
1478 /**************************************************************************
1479 Send request for unit activity changing to server. This is for
1480 activities that are targeted to certain special or base type.
1481 **************************************************************************/
1482 void request_new_unit_activity_targeted(struct unit *punit,
1483 enum unit_activity act,
1484 struct act_tgt *tgt)
1486 switch (tgt->type) {
1487 case ATT_SPECIAL:
1488 dsend_packet_unit_change_activity(&client.conn, punit->id, act, tgt->obj.spe);
1489 break;
1490 case ATT_BASE:
1491 dsend_packet_unit_change_activity_base(&client.conn, punit->id, act, tgt->obj.base);
1492 break;
1493 case ATT_ROAD:
1494 dsend_packet_unit_change_activity_road(&client.conn, punit->id, act, tgt->obj.road);
1495 break;
1499 /**************************************************************************
1500 Request base building activity for unit
1501 **************************************************************************/
1502 void request_new_unit_activity_base(struct unit *punit,
1503 const struct base_type *pbase)
1505 if (!can_client_issue_orders()) {
1506 return;
1509 dsend_packet_unit_change_activity_base(&client.conn, punit->id, ACTIVITY_BASE,
1510 base_number(pbase));
1513 /**************************************************************************
1514 Request road building activity for unit
1515 **************************************************************************/
1516 void request_new_unit_activity_road(struct unit *punit,
1517 const struct road_type *proad)
1519 if (!can_client_issue_orders()) {
1520 return;
1523 dsend_packet_unit_change_activity_road(&client.conn, punit->id,
1524 ACTIVITY_GEN_ROAD,
1525 road_number(proad));
1528 /**************************************************************************
1529 Send request to disband unit to server.
1530 **************************************************************************/
1531 void request_unit_disband(struct unit *punit)
1533 dsend_packet_unit_disband(&client.conn, punit->id);
1536 /**************************************************************************
1537 Send request to change unit homecity to server.
1538 **************************************************************************/
1539 void request_unit_change_homecity(struct unit *punit)
1541 struct city *pcity=tile_city(unit_tile(punit));
1543 if (pcity) {
1544 dsend_packet_unit_change_homecity(&client.conn, punit->id, pcity->id);
1548 /**************************************************************************
1549 Send request to upgrade unit to server.
1550 **************************************************************************/
1551 void request_unit_upgrade(struct unit *punit)
1553 struct city *pcity=tile_city(unit_tile(punit));
1555 if (pcity) {
1556 dsend_packet_unit_upgrade(&client.conn, punit->id);
1560 /**************************************************************************
1561 Sends unit convert packet.
1562 **************************************************************************/
1563 void request_unit_convert(struct unit *punit)
1565 request_new_unit_activity(punit, ACTIVITY_CONVERT);
1568 /****************************************************************************
1569 Call to request (from the server) that the settler unit is put into
1570 autosettler mode.
1571 ****************************************************************************/
1572 void request_unit_autosettlers(const struct unit *punit)
1574 if (punit && can_unit_do_autosettlers(punit)) {
1575 dsend_packet_unit_autosettlers(&client.conn, punit->id);
1576 } else if (punit) {
1577 create_event(unit_tile(punit), E_BAD_COMMAND, ftc_client,
1578 _("Only settler units can be put into auto mode."));
1582 /****************************************************************************
1583 Send a request to the server that the cargo be loaded into the transporter.
1585 If ptransporter is NULL a transporter will be picked at random.
1586 ****************************************************************************/
1587 void request_unit_load(struct unit *pcargo, struct unit *ptrans)
1589 if (!ptrans) {
1590 ptrans = transporter_for_unit(pcargo);
1593 if (ptrans
1594 && can_client_issue_orders()
1595 && can_unit_load(pcargo, ptrans)) {
1596 dsend_packet_unit_load(&client.conn, pcargo->id, ptrans->id);
1598 /* Sentry the unit. Don't request_unit_sentry since this can give a
1599 * recursive loop. */
1600 dsend_packet_unit_change_activity(&client.conn, pcargo->id,
1601 ACTIVITY_SENTRY, S_LAST);
1605 /****************************************************************************
1606 Send a request to the server that the cargo be unloaded from its current
1607 transporter.
1608 ****************************************************************************/
1609 void request_unit_unload(struct unit *pcargo)
1611 struct unit *ptrans = unit_transport_get(pcargo);
1613 if (can_client_issue_orders()
1614 && ptrans
1615 && can_unit_unload(pcargo, ptrans)
1616 && can_unit_survive_at_tile(pcargo, unit_tile(pcargo))) {
1617 dsend_packet_unit_unload(&client.conn, pcargo->id, ptrans->id);
1619 if (unit_owner(pcargo) == client.conn.playing
1620 && pcargo->activity == ACTIVITY_SENTRY) {
1621 /* Activate the unit. */
1622 dsend_packet_unit_change_activity(&client.conn, pcargo->id,
1623 ACTIVITY_IDLE, S_LAST);
1628 /**************************************************************************
1629 Send request to do caravan action - establishing traderoute or
1630 helping in wonder building - to server.
1631 **************************************************************************/
1632 void request_unit_caravan_action(struct unit *punit, enum packet_type action)
1634 if (!tile_city(unit_tile(punit))) {
1635 return;
1638 if (action == PACKET_UNIT_ESTABLISH_TRADE) {
1639 dsend_packet_unit_establish_trade(&client.conn, punit->id);
1640 } else if (action == PACKET_UNIT_HELP_BUILD_WONDER) {
1641 dsend_packet_unit_help_build_wonder(&client.conn, punit->id);
1642 } else {
1643 log_error("request_unit_caravan_action() Bad action (%d)", action);
1647 /**************************************************************************
1648 Explode nuclear at a tile without enemy units
1649 **************************************************************************/
1650 void request_unit_nuke(struct unit_list *punits)
1652 bool can = FALSE;
1653 struct tile *offender = NULL;
1655 if (unit_list_size(punits) == 0) {
1656 return;
1658 unit_list_iterate(punits, punit) {
1659 if (unit_has_type_flag(punit, UTYF_NUCLEAR)) {
1660 can = TRUE;
1661 break;
1663 if (!offender) { /* Take first offender tile/unit */
1664 offender = unit_tile(punit);
1666 } unit_list_iterate_end;
1667 if (can) {
1668 set_hover_state(punits, HOVER_NUKE, ACTIVITY_LAST, NULL,
1669 ORDER_LAST);
1670 update_unit_info_label(punits);
1671 enter_goto_state(punits);
1672 } else {
1673 create_event(offender, E_BAD_COMMAND, ftc_client,
1674 _("Only nuclear units can do this."));
1678 /**************************************************************************
1679 Send paradrop request to server.
1680 **************************************************************************/
1681 void request_unit_paradrop(struct unit_list *punits)
1683 bool can = FALSE;
1684 struct tile *offender = NULL;
1686 if (unit_list_size(punits) == 0) {
1687 return;
1689 unit_list_iterate(punits, punit) {
1690 if (can_unit_paradrop(punit)) {
1691 can = TRUE;
1692 break;
1694 if (!offender) { /* Take first offender tile/unit */
1695 offender = unit_tile(punit);
1697 } unit_list_iterate_end;
1698 if (can) {
1699 set_hover_state(punits, HOVER_PARADROP, ACTIVITY_LAST, NULL,
1700 ORDER_LAST);
1701 update_unit_info_label(punits);
1702 } else {
1703 create_event(offender, E_BAD_COMMAND, ftc_client,
1704 _("Only paratrooper units can do this."));
1708 /**************************************************************************
1709 Either start new patrol route planning, or add waypoint to current one.
1710 **************************************************************************/
1711 void request_unit_patrol(void)
1713 struct unit_list *punits = get_units_in_focus();
1715 if (unit_list_size(punits) == 0) {
1716 return;
1719 if (hover_state != HOVER_PATROL) {
1720 set_hover_state(punits, HOVER_PATROL, ACTIVITY_LAST, NULL,
1721 ORDER_LAST);
1722 update_unit_info_label(punits);
1723 enter_goto_state(punits);
1724 create_line_at_mouse_pos();
1725 } else {
1726 fc_assert_ret(goto_is_active());
1727 goto_add_waypoint();
1731 /****************************************************************
1732 Try to sentry unit.
1733 *****************************************************************/
1734 void request_unit_sentry(struct unit *punit)
1736 if(punit->activity!=ACTIVITY_SENTRY &&
1737 can_unit_do_activity(punit, ACTIVITY_SENTRY))
1738 request_new_unit_activity(punit, ACTIVITY_SENTRY);
1741 /****************************************************************
1742 Try to fortify unit.
1743 *****************************************************************/
1744 void request_unit_fortify(struct unit *punit)
1746 if(punit->activity!=ACTIVITY_FORTIFYING &&
1747 can_unit_do_activity(punit, ACTIVITY_FORTIFYING))
1748 request_new_unit_activity(punit, ACTIVITY_FORTIFYING);
1751 /**************************************************************************
1752 Send pillage request to server.
1753 **************************************************************************/
1754 void request_unit_pillage(struct unit *punit)
1756 struct act_tgt target = { .type = ATT_SPECIAL, .obj.spe = S_LAST };
1758 if (!game.info.pillage_select) {
1759 /* Leave choice up to the server */
1760 request_new_unit_activity_targeted(punit, ACTIVITY_PILLAGE, &target);
1761 } else {
1762 struct tile *ptile = unit_tile(punit);
1763 bv_special pspossible;
1764 bv_bases bspossible;
1765 bv_roads rspossible;
1766 int count = 0;
1768 BV_CLR_ALL(pspossible);
1769 tile_special_type_iterate(spe) {
1770 target.obj.spe = spe;
1772 if (can_unit_do_activity_targeted_at(punit, ACTIVITY_PILLAGE,
1773 &target, ptile)) {
1774 BV_SET(pspossible, spe);
1775 count++;
1777 } tile_special_type_iterate_end;
1779 BV_CLR_ALL(bspossible);
1780 target.type = ATT_BASE;
1781 base_type_iterate(pbase) {
1782 target.obj.base = base_index(pbase);
1784 if (can_unit_do_activity_targeted_at(punit, ACTIVITY_PILLAGE,
1785 &target, ptile)) {
1786 BV_SET(bspossible, target.obj.base);
1787 count++;
1789 } base_type_iterate_end;
1791 BV_CLR_ALL(rspossible);
1792 target.type = ATT_ROAD;
1793 road_type_iterate(proad) {
1794 target.obj.road = road_index(proad);
1796 if (can_unit_do_activity_targeted_at(punit, ACTIVITY_PILLAGE,
1797 &target, ptile)) {
1798 BV_SET(rspossible, target.obj.road);
1799 count++;
1801 } road_type_iterate_end;
1803 if (count > 1) {
1804 popup_pillage_dialog(punit, pspossible, bspossible, rspossible);
1805 } else {
1806 /* Should be only one choice... */
1807 bool found = get_preferred_pillage(&target, pspossible, bspossible, rspossible);
1809 if (found) {
1810 request_new_unit_activity_targeted(punit, ACTIVITY_PILLAGE, &target);
1816 /**************************************************************************
1817 Toggle display of city outlines on the map
1818 **************************************************************************/
1819 void request_toggle_city_outlines(void)
1821 if (!can_client_change_view()) {
1822 return;
1825 draw_city_outlines = !draw_city_outlines;
1826 update_map_canvas_visible();
1829 /**************************************************************************
1830 Toggle display of worker output of cities on the map
1831 **************************************************************************/
1832 void request_toggle_city_output(void)
1834 if (!can_client_change_view()) {
1835 return;
1838 draw_city_output = !draw_city_output;
1839 update_map_canvas_visible();
1842 /**************************************************************************
1843 Toggle display of grid lines on the map
1844 **************************************************************************/
1845 void request_toggle_map_grid(void)
1847 if (!can_client_change_view()) {
1848 return;
1851 draw_map_grid^=1;
1852 update_map_canvas_visible();
1855 /**************************************************************************
1856 Toggle display of national borders on the map
1857 **************************************************************************/
1858 void request_toggle_map_borders(void)
1860 if (!can_client_change_view()) {
1861 return;
1864 draw_borders ^= 1;
1865 update_map_canvas_visible();
1868 /**************************************************************************
1869 Toggle display of native tiles on the map
1870 **************************************************************************/
1871 void request_toggle_map_native(void)
1873 if (!can_client_change_view()) {
1874 return;
1877 draw_native ^= 1;
1878 update_map_canvas_visible();
1881 /**************************************************************************
1882 Toggle display of city full bar.
1883 **************************************************************************/
1884 void request_toggle_city_full_bar(void)
1886 if (!can_client_change_view()) {
1887 return;
1890 draw_full_citybar ^= 1;
1891 update_map_canvas_visible();
1894 /**************************************************************************
1895 Toggle display of city names
1896 **************************************************************************/
1897 void request_toggle_city_names(void)
1899 if (!can_client_change_view()) {
1900 return;
1903 draw_city_names ^= 1;
1904 update_map_canvas_visible();
1907 /**************************************************************************
1908 Toggle display of city growth (turns-to-grow)
1909 **************************************************************************/
1910 void request_toggle_city_growth(void)
1912 if (!can_client_change_view()) {
1913 return;
1916 draw_city_growth ^= 1;
1917 update_map_canvas_visible();
1920 /**************************************************************************
1921 Toggle display of city productions
1922 **************************************************************************/
1923 void request_toggle_city_productions(void)
1925 if (!can_client_change_view()) {
1926 return;
1929 draw_city_productions ^= 1;
1930 update_map_canvas_visible();
1933 /**************************************************************************
1934 Toggle display of city buycost
1935 **************************************************************************/
1936 void request_toggle_city_buycost(void)
1938 if (!can_client_change_view()) {
1939 return;
1942 draw_city_buycost ^= 1;
1943 update_map_canvas_visible();
1946 /**************************************************************************
1947 Toggle display of city trade routes
1948 **************************************************************************/
1949 void request_toggle_city_trade_routes(void)
1951 if (!can_client_change_view()) {
1952 return;
1955 draw_city_trade_routes ^= 1;
1956 update_map_canvas_visible();
1959 /**************************************************************************
1960 Toggle display of terrain
1961 **************************************************************************/
1962 void request_toggle_terrain(void)
1964 if (!can_client_change_view()) {
1965 return;
1968 draw_terrain ^= 1;
1969 update_map_canvas_visible();
1972 /**************************************************************************
1973 Toggle display of coastline
1974 **************************************************************************/
1975 void request_toggle_coastline(void)
1977 if (!can_client_change_view()) {
1978 return;
1981 draw_coastline ^= 1;
1982 update_map_canvas_visible();
1985 /**************************************************************************
1986 Toggle display of roads and rails
1987 **************************************************************************/
1988 void request_toggle_roads_rails(void)
1990 if (!can_client_change_view()) {
1991 return;
1994 draw_roads_rails ^= 1;
1995 update_map_canvas_visible();
1998 /**************************************************************************
1999 Toggle display of irrigation
2000 **************************************************************************/
2001 void request_toggle_irrigation(void)
2003 if (!can_client_change_view()) {
2004 return;
2007 draw_irrigation ^= 1;
2008 update_map_canvas_visible();
2011 /**************************************************************************
2012 Toggle display of mines
2013 **************************************************************************/
2014 void request_toggle_mines(void)
2016 if (!can_client_change_view()) {
2017 return;
2020 draw_mines ^= 1;
2021 update_map_canvas_visible();
2024 /**************************************************************************
2025 Toggle display of bases
2026 **************************************************************************/
2027 void request_toggle_bases(void)
2029 if (!can_client_change_view()) {
2030 return;
2033 draw_fortress_airbase ^= 1;
2034 update_map_canvas_visible();
2037 /**************************************************************************
2038 Toggle display of specials
2039 **************************************************************************/
2040 void request_toggle_specials(void)
2042 if (!can_client_change_view()) {
2043 return;
2046 draw_specials ^= 1;
2047 update_map_canvas_visible();
2050 /**************************************************************************
2051 Toggle display of pollution
2052 **************************************************************************/
2053 void request_toggle_pollution(void)
2055 if (!can_client_change_view()) {
2056 return;
2059 draw_pollution ^= 1;
2060 update_map_canvas_visible();
2063 /**************************************************************************
2064 Toggle display of cities
2065 **************************************************************************/
2066 void request_toggle_cities(void)
2068 if (!can_client_change_view()) {
2069 return;
2072 draw_cities ^= 1;
2073 update_map_canvas_visible();
2076 /**************************************************************************
2077 Toggle display of units
2078 **************************************************************************/
2079 void request_toggle_units(void)
2081 if (!can_client_change_view()) {
2082 return;
2085 draw_units ^= 1;
2086 update_map_canvas_visible();
2089 /**************************************************************************
2090 Toggle display of unit solid background.
2091 **************************************************************************/
2092 void request_toggle_unit_solid_bg(void)
2094 if (!can_client_change_view()) {
2095 return;
2098 solid_color_behind_units ^= 1;
2099 update_map_canvas_visible();
2102 /**************************************************************************
2103 Toggle display of unit shields.
2104 **************************************************************************/
2105 void request_toggle_unit_shields(void)
2107 if (!can_client_change_view()) {
2108 return;
2111 draw_unit_shields ^= 1;
2112 update_map_canvas_visible();
2115 /**************************************************************************
2116 Toggle display of focus unit
2117 **************************************************************************/
2118 void request_toggle_focus_unit(void)
2120 if (!can_client_change_view()) {
2121 return;
2124 draw_focus_unit ^= 1;
2125 update_map_canvas_visible();
2128 /**************************************************************************
2129 Toggle display of fog of war
2130 **************************************************************************/
2131 void request_toggle_fog_of_war(void)
2133 if (!can_client_change_view()) {
2134 return;
2137 draw_fog_of_war ^= 1;
2138 update_map_canvas_visible();
2139 refresh_overview_canvas();
2142 /**************************************************************************
2143 Center to focus unit.
2144 **************************************************************************/
2145 void request_center_focus_unit(void)
2147 struct tile *ptile = find_a_focus_unit_tile_to_center_on();
2149 if (ptile) {
2150 center_tile_mapcanvas(ptile);
2154 /**************************************************************************
2155 Set units in list to waiting focus. If they are current focus units,
2156 advance focus.
2157 **************************************************************************/
2158 void request_units_wait(struct unit_list *punits)
2160 unit_list_iterate(punits, punit) {
2161 punit->client.focus_status = FOCUS_WAIT;
2162 } unit_list_iterate_end;
2163 if (punits == get_units_in_focus()) {
2164 unit_focus_advance();
2168 /**************************************************************************
2169 Set focus units to FOCUS_DONE state.
2170 **************************************************************************/
2171 void request_unit_move_done(void)
2173 if (get_num_units_in_focus() > 0) {
2174 enum unit_focus_status new_status = FOCUS_DONE;
2175 unit_list_iterate(get_units_in_focus(), punit) {
2176 /* If any of the focused units are busy, keep all of them
2177 * in focus; another tap of the key will dismiss them */
2178 if (punit->activity != ACTIVITY_IDLE) {
2179 new_status = FOCUS_WAIT;
2181 } unit_list_iterate_end;
2182 unit_list_iterate(get_units_in_focus(), punit) {
2183 clear_unit_orders(punit);
2184 punit->client.focus_status = new_status;
2185 } unit_list_iterate_end;
2186 if (new_status == FOCUS_DONE) {
2187 unit_focus_advance();
2192 /**************************************************************************
2193 Called to have the client move a unit from one location to another,
2194 updating the graphics if necessary. The caller must redraw the target
2195 location after the move.
2196 **************************************************************************/
2197 void do_move_unit(struct unit *punit, struct unit *target_unit)
2199 struct tile *src_tile = unit_tile(punit);
2200 struct tile *dst_tile = unit_tile(target_unit);
2201 bool was_teleported, do_animation;
2203 was_teleported = !is_tiles_adjacent(src_tile, dst_tile);
2204 do_animation = (!was_teleported && smooth_move_unit_msec > 0);
2206 if (!was_teleported
2207 && punit->activity != ACTIVITY_SENTRY
2208 && !unit_transported(punit)) {
2209 audio_play_sound(unit_type(punit)->sound_move,
2210 unit_type(punit)->sound_move_alt);
2213 unit_list_remove(src_tile->units, punit);
2215 if (unit_owner(punit) == client.conn.playing
2216 && auto_center_on_unit
2217 && !unit_has_orders(punit)
2218 && punit->activity != ACTIVITY_GOTO
2219 && punit->activity != ACTIVITY_SENTRY
2220 && !tile_visible_and_not_on_border_mapcanvas(dst_tile)) {
2221 center_tile_mapcanvas(dst_tile);
2224 /* Set the tile before the movement animation is done, so that everything
2225 * drawn there will be up-to-date. */
2226 unit_tile_set(punit, dst_tile);
2228 if (!unit_transported(punit)) {
2229 /* We have to refresh the tile before moving. This will draw
2230 * the tile without the unit (because it was unlinked above). */
2231 refresh_unit_mapcanvas(punit, src_tile, TRUE, FALSE);
2233 if (do_animation) {
2234 int dx, dy;
2236 /* For the duration of the animation the unit exists at neither
2237 * tile. */
2238 map_distance_vector(&dx, &dy, src_tile, dst_tile);
2239 move_unit_map_canvas(punit, src_tile, dx, dy);
2243 unit_list_prepend(dst_tile->units, punit);
2245 if (!unit_transported(punit)) {
2246 refresh_unit_mapcanvas(punit, dst_tile, TRUE, FALSE);
2249 /* With the "full" city bar we have to update the city bar when units move
2250 * into or out of a city. For foreign cities this is handled separately,
2251 * via the occupied field of the short-city packet. */
2252 if (NULL != tile_city(src_tile)
2253 && can_player_see_units_in_city(client.conn.playing, tile_city(src_tile))) {
2254 update_city_description(tile_city(src_tile));
2256 if (NULL != tile_city(dst_tile)
2257 && can_player_see_units_in_city(client.conn.playing, tile_city(dst_tile))) {
2258 update_city_description(tile_city(dst_tile));
2261 if (unit_is_in_focus(punit)) {
2262 menus_update();
2266 /**************************************************************************
2267 Handles everything when the user clicked a tile
2268 **************************************************************************/
2269 void do_map_click(struct tile *ptile, enum quickselect_type qtype)
2271 struct city *pcity = tile_city(ptile);
2272 struct unit_list *punits = get_units_in_focus();
2273 bool maybe_goto = FALSE;
2274 bool possible = FALSE;
2275 struct tile *offender = NULL;
2277 if (hover_state != HOVER_NONE) {
2278 switch (hover_state) {
2279 case HOVER_NONE:
2280 break;
2281 case HOVER_GOTO:
2282 do_unit_goto(ptile);
2283 break;
2284 case HOVER_NUKE:
2285 unit_list_iterate(punits, punit) {
2286 if (SINGLE_MOVE * real_map_distance(unit_tile(punit), ptile)
2287 <= punit->moves_left) {
2288 possible = TRUE;
2289 break;
2291 offender = unit_tile(punit);
2292 } unit_list_iterate_end;
2293 if (!possible) {
2294 create_event(offender, E_BAD_COMMAND, ftc_client,
2295 _("Too far for this unit."));
2296 } else {
2297 do_unit_goto(ptile);
2298 if (!pcity) {
2299 unit_list_iterate(punits, punit) {
2300 /* note that this will be executed by the server after the goto */
2301 do_unit_nuke(punit);
2302 } unit_list_iterate_end;
2305 break;
2306 case HOVER_PARADROP:
2307 unit_list_iterate(punits, punit) {
2308 do_unit_paradrop_to(punit, ptile);
2309 } unit_list_iterate_end;
2310 break;
2311 case HOVER_CONNECT:
2312 do_unit_connect(ptile, connect_activity, &connect_tgt);
2313 break;
2314 case HOVER_PATROL:
2315 do_unit_patrol_to(ptile);
2316 break;
2319 set_hover_state(NULL, HOVER_NONE, ACTIVITY_LAST, NULL, ORDER_LAST);
2320 update_unit_info_label(get_units_in_focus());
2323 /* Bypass stack or city popup if quickselect is specified. */
2324 else if (qtype != SELECT_POPUP && qtype != SELECT_APPEND) {
2325 struct unit *qunit = quickselect(ptile, qtype);
2326 if (qunit) {
2327 unit_focus_set_and_select(qunit);
2328 maybe_goto = keyboardless_goto;
2331 /* Otherwise use popups. */
2332 else if (NULL != pcity
2333 && can_player_see_city_internals(client.conn.playing, pcity)) {
2334 popup_city_dialog(pcity);
2336 else if (unit_list_size(ptile->units) == 0
2337 && NULL == pcity
2338 && get_num_units_in_focus() > 0) {
2339 maybe_goto = keyboardless_goto;
2341 else if (unit_list_size(ptile->units) == 1
2342 && !get_transporter_occupancy(unit_list_get(ptile->units, 0))) {
2343 struct unit *punit=unit_list_get(ptile->units, 0);
2345 if (unit_owner(punit) == client.conn.playing) {
2346 if(can_unit_do_activity(punit, ACTIVITY_IDLE)) {
2347 maybe_goto = keyboardless_goto;
2348 if (qtype == SELECT_APPEND) {
2349 unit_focus_add(punit);
2350 } else {
2351 unit_focus_set_and_select(punit);
2354 } else if (pcity) {
2355 /* Don't hide the unit in the city. */
2356 unit_select_dialog_popup(ptile);
2359 else if(unit_list_size(ptile->units) > 0) {
2360 /* The stack list is always popped up, even if it includes enemy units.
2361 * If the server doesn't want the player to know about them it shouldn't
2362 * tell him! The previous behavior would only pop up the stack if you
2363 * owned a unit on the tile. This gave cheating clients an advantage,
2364 * and also showed you allied units if (and only if) you had a unit on
2365 * the tile (inconsistent). */
2366 unit_select_dialog_popup(ptile);
2369 /* See mapctrl_common.c */
2370 keyboardless_goto_start_tile = maybe_goto ? ptile : NULL;
2371 keyboardless_goto_button_down = maybe_goto;
2372 keyboardless_goto_active = FALSE;
2375 /**************************************************************************
2376 Quickselecting a unit is normally done with <control> left, right click,
2377 for the current tile. Bypassing the stack popup is quite convenient,
2378 and can be tactically important in furious multiplayer games.
2379 **************************************************************************/
2380 static struct unit *quickselect(struct tile *ptile,
2381 enum quickselect_type qtype)
2383 int listsize = unit_list_size(ptile->units);
2384 struct unit *panytransporter = NULL,
2385 *panymovesea = NULL, *panysea = NULL,
2386 *panymoveland = NULL, *panyland = NULL,
2387 *panymoveunit = NULL, *panyunit = NULL;
2389 fc_assert_ret_val(qtype > SELECT_POPUP, NULL);
2391 if (listsize == 0) {
2392 return NULL;
2393 } else if (listsize == 1) {
2394 struct unit *punit = unit_list_get(ptile->units, 0);
2395 return (unit_owner(punit) == client.conn.playing) ? punit : NULL;
2398 /* Quickselect priorities. Units with moves left
2399 * before exhausted. Focus unit is excluded.
2401 * SEA: Transporter
2402 * Sea unit
2403 * Any unit
2405 * LAND: Military land unit
2406 * Non-combatant
2407 * Sea unit
2408 * Any unit
2411 unit_list_iterate(ptile->units, punit) {
2412 if (unit_owner(punit) != client.conn.playing || unit_is_in_focus(punit)) {
2413 continue;
2415 if (qtype == SELECT_SEA) {
2416 /* Transporter. */
2417 if (get_transporter_capacity(punit)) {
2418 if (punit->moves_left > 0) {
2419 return punit;
2420 } else if (!panytransporter) {
2421 panytransporter = punit;
2424 /* Any sea, pref. moves left. */
2425 else if (is_sailing_unit(punit)) {
2426 if (punit->moves_left > 0) {
2427 if (!panymovesea) {
2428 panymovesea = punit;
2430 } else if (!panysea) {
2431 panysea = punit;
2434 } else if (qtype == SELECT_LAND) {
2435 if (is_ground_unit(punit)) {
2436 if (punit->moves_left > 0) {
2437 if (is_military_unit(punit)) {
2438 return punit;
2439 } else if (!panymoveland) {
2440 panymoveland = punit;
2442 } else if (!panyland) {
2443 panyland = punit;
2446 else if (is_sailing_unit(punit)) {
2447 if (punit->moves_left > 0) {
2448 panymovesea = punit;
2449 } else {
2450 panysea = punit;
2454 if (punit->moves_left > 0 && !panymoveunit) {
2455 panymoveunit = punit;
2457 if (!panyunit) {
2458 panyunit = punit;
2460 } unit_list_iterate_end;
2462 if (qtype == SELECT_SEA) {
2463 if (panytransporter) {
2464 return panytransporter;
2465 } else if (panymovesea) {
2466 return panymovesea;
2467 } else if (panysea) {
2468 return panysea;
2469 } else if (panymoveunit) {
2470 return panymoveunit;
2471 } else if (panyunit) {
2472 return panyunit;
2475 else if (qtype == SELECT_LAND) {
2476 if (panymoveland) {
2477 return panymoveland;
2478 } else if (panyland) {
2479 return panyland;
2480 } else if (panymovesea) {
2481 return panymovesea;
2482 } else if (panysea) {
2483 return panysea;
2484 } else if (panymoveunit) {
2485 return panymoveunit;
2486 } else if (panyunit) {
2487 return panyunit;
2490 return NULL;
2493 /**************************************************************************
2494 Finish the goto mode and let the units stored in goto_map_list move
2495 to a given location.
2496 **************************************************************************/
2497 void do_unit_goto(struct tile *ptile)
2499 if (hover_state != HOVER_GOTO && hover_state != HOVER_NUKE) {
2500 return;
2503 if (is_valid_goto_draw_line(ptile)) {
2504 send_goto_route();
2505 } else {
2506 create_event(ptile, E_BAD_COMMAND, ftc_client,
2507 _("Didn't find a route to the destination!"));
2511 /**************************************************************************
2512 Explode nuclear at a tile without enemy units
2513 **************************************************************************/
2514 void do_unit_nuke(struct unit *punit)
2516 dsend_packet_unit_nuke(&client.conn, punit->id);
2519 /**************************************************************************
2520 Paradrop to a location.
2521 **************************************************************************/
2522 void do_unit_paradrop_to(struct unit *punit, struct tile *ptile)
2524 dsend_packet_unit_paradrop_to(&client.conn, punit->id, tile_index(ptile));
2527 /**************************************************************************
2528 Patrol to a location.
2529 **************************************************************************/
2530 void do_unit_patrol_to(struct tile *ptile)
2532 if (is_valid_goto_draw_line(ptile)
2533 && !is_non_allied_unit_tile(ptile, client.conn.playing)) {
2534 send_patrol_route();
2535 } else {
2536 create_event(ptile, E_BAD_COMMAND, ftc_client,
2537 _("Didn't find a route to the destination!"));
2540 set_hover_state(NULL, HOVER_NONE, ACTIVITY_LAST, NULL, ORDER_LAST);
2543 /**************************************************************************
2544 "Connect" to the given location.
2545 **************************************************************************/
2546 void do_unit_connect(struct tile *ptile,
2547 enum unit_activity activity,
2548 struct act_tgt *tgt)
2550 if (is_valid_goto_draw_line(ptile)) {
2551 send_connect_route(activity, tgt);
2552 } else {
2553 create_event(ptile, E_BAD_COMMAND, ftc_client,
2554 _("Didn't find a route to the destination!"));
2557 set_hover_state(NULL, HOVER_NONE, ACTIVITY_LAST, NULL, ORDER_LAST);
2560 /**************************************************************************
2561 The 'Escape' key.
2562 **************************************************************************/
2563 void key_cancel_action(void)
2565 cancel_tile_hiliting();
2567 switch (hover_state) {
2568 case HOVER_GOTO:
2569 case HOVER_PATROL:
2570 case HOVER_CONNECT:
2571 if (goto_pop_waypoint()) {
2572 break;
2574 /* else fall through: */
2575 case HOVER_NUKE:
2576 case HOVER_PARADROP:
2577 set_hover_state(NULL, HOVER_NONE, ACTIVITY_LAST, NULL, ORDER_LAST);
2578 update_unit_info_label(get_units_in_focus());
2580 keyboardless_goto_button_down = FALSE;
2581 keyboardless_goto_active = FALSE;
2582 keyboardless_goto_start_tile = NULL;
2583 break;
2584 default:
2585 break;
2589 /**************************************************************************
2590 Center the mapview on the player's capital, or print a failure message.
2591 **************************************************************************/
2592 void key_center_capital(void)
2594 struct city *capital = player_capital(client_player());
2596 if (capital) {
2597 /* Center on the tile, and pop up the crosshair overlay. */
2598 center_tile_mapcanvas(capital->tile);
2599 put_cross_overlay_tile(capital->tile);
2600 } else {
2601 create_event(NULL, E_BAD_COMMAND, ftc_client,
2602 _("Oh my! You seem to have no capital!"));
2606 /**************************************************************************
2607 Handle user 'end turn' input.
2608 **************************************************************************/
2609 void key_end_turn(void)
2611 send_turn_done();
2614 /**************************************************************************
2615 Recall the previous focus unit(s). See store_previous_focus().
2616 **************************************************************************/
2617 void key_recall_previous_focus_unit(void)
2619 int i = 0;
2621 /* Could use unit_list_copy here instead. Just having safe genlists
2622 * wouldn't be sufficient since we don't want to skip units already
2623 * removed from focus... */
2624 unit_list_iterate_safe(previous_focus, punit) {
2625 if (i == 0) {
2626 unit_focus_set(punit);
2627 } else {
2628 unit_focus_add(punit);
2630 i++;
2631 } unit_list_iterate_safe_end;
2634 /**************************************************************************
2635 Move the focus unit in the given direction. Here directions are
2636 defined according to the GUI, so that north is "up" in the interface.
2637 **************************************************************************/
2638 void key_unit_move(enum direction8 gui_dir)
2640 unit_list_iterate(get_units_in_focus(), punit) {
2641 enum direction8 map_dir = gui_to_map_dir(gui_dir);
2643 request_move_unit_direction(punit, map_dir);
2644 } unit_list_iterate_end;
2647 /**************************************************************************
2648 Handle use 'build city' input.
2649 **************************************************************************/
2650 void key_unit_build_city(void)
2652 unit_list_iterate(get_units_in_focus(), punit) {
2653 request_unit_build_city(punit);
2654 } unit_list_iterate_end;
2657 /**************************************************************************
2658 Handle user 'help build wonder' input
2659 **************************************************************************/
2660 void key_unit_build_wonder(void)
2662 unit_list_iterate(get_units_in_focus(), punit) {
2663 if (unit_has_type_flag(punit, UTYF_HELP_WONDER)) {
2664 request_unit_caravan_action(punit, PACKET_UNIT_HELP_BUILD_WONDER);
2666 } unit_list_iterate_end;
2669 /**************************************************************************
2670 handle user pressing key for 'Connect' command
2671 **************************************************************************/
2672 void key_unit_connect(enum unit_activity activity,
2673 struct act_tgt *tgt)
2675 request_unit_connect(activity, tgt);
2678 /**************************************************************************
2679 Handle user 'diplomatic actions' input
2680 **************************************************************************/
2681 void key_unit_diplomat_actions(void)
2683 struct city *pcity; /* need pcity->id */
2684 unit_list_iterate(get_units_in_focus(), punit) {
2685 if (is_diplomat_unit(punit)
2686 && (pcity = tile_city(unit_tile(punit)))
2687 && diplomat_handled_in_diplomat_dialog() != -1 /* confusing otherwise? */
2688 && diplomat_can_do_action(punit, DIPLOMAT_ANY_ACTION,
2689 unit_tile(punit))) {
2690 process_diplomat_arrival(punit, pcity->id);
2691 return;
2692 /* FIXME: diplomat dialog for more than one unit at a time. */
2694 } unit_list_iterate_end;
2697 /**************************************************************************
2698 Handle user 'unit done' input
2699 **************************************************************************/
2700 void key_unit_done(void)
2702 request_unit_move_done();
2705 /**************************************************************************
2706 Handle user 'unit goto' input
2707 **************************************************************************/
2708 void key_unit_goto(void)
2710 request_unit_goto(ORDER_LAST);
2713 /**************************************************************************
2714 Explode nuclear at a tile without enemy units
2715 **************************************************************************/
2716 void key_unit_nuke(void)
2718 request_unit_nuke(get_units_in_focus());
2721 /**************************************************************************
2722 Handle user 'paradrop' input
2723 **************************************************************************/
2724 void key_unit_paradrop(void)
2726 request_unit_paradrop(get_units_in_focus());
2729 /**************************************************************************
2730 Handle user 'patrol' input
2731 **************************************************************************/
2732 void key_unit_patrol(void)
2734 request_unit_patrol();
2737 /**************************************************************************
2738 Handle user 'establish traderoute' input
2739 **************************************************************************/
2740 void key_unit_trade_route(void)
2742 unit_list_iterate(get_units_in_focus(), punit) {
2743 if (unit_has_type_flag(punit, UTYF_TRADE_ROUTE)) {
2744 request_unit_caravan_action(punit, PACKET_UNIT_ESTABLISH_TRADE);
2746 } unit_list_iterate_end;
2749 /**************************************************************************
2750 Handle user 'unload all' input
2751 **************************************************************************/
2752 void key_unit_unload_all(void)
2754 struct unit *pnext_focus = NULL, *plast;
2756 unit_list_iterate(get_units_in_focus(), punit) {
2757 if ((plast = request_unit_unload_all(punit))) {
2758 pnext_focus = plast;
2760 } unit_list_iterate_end;
2762 if (pnext_focus) {
2763 unit_list_iterate(get_units_in_focus(), punit) {
2764 /* Unfocus the ships, and advance the focus to the last unloaded unit.
2765 * If there is no unit unloaded (which shouldn't happen, but could if
2766 * the caller doesn't check if the transporter is loaded), the we
2767 * don't do anything. */
2768 punit->client.focus_status = FOCUS_WAIT;
2769 } unit_list_iterate_end;
2770 unit_focus_set(pnext_focus);
2774 /**************************************************************************
2775 Handle user 'wait' input
2776 **************************************************************************/
2777 void key_unit_wait(void)
2779 request_units_wait(get_units_in_focus());
2782 /**************************************************************************
2783 Handle user 'wakeup others' input
2784 ***************************************************************************/
2785 void key_unit_wakeup_others(void)
2787 unit_list_iterate(get_units_in_focus(), punit) {
2788 request_unit_wakeup(punit);
2789 } unit_list_iterate_end;
2792 /**************************************************************************
2793 Handle user 'build base of class airbase' input
2794 **************************************************************************/
2795 void key_unit_airbase(void)
2797 unit_list_iterate(get_units_in_focus(), punit) {
2798 struct base_type *pbase =
2799 get_base_by_gui_type(BASE_GUI_AIRBASE, punit, unit_tile(punit));
2801 if (pbase) {
2802 request_new_unit_activity_base(punit, pbase);
2804 } unit_list_iterate_end;
2807 /**************************************************************************
2808 Handle user 'autoexplore' input
2809 **************************************************************************/
2810 void key_unit_auto_explore(void)
2812 unit_list_iterate(get_units_in_focus(), punit) {
2813 if (can_unit_do_activity(punit, ACTIVITY_EXPLORE)) {
2814 request_new_unit_activity(punit, ACTIVITY_EXPLORE);
2816 } unit_list_iterate_end;
2819 /**************************************************************************
2820 Call to request (from the server) that the focus unit is put into
2821 autosettler mode.
2822 **************************************************************************/
2823 void key_unit_auto_settle(void)
2825 unit_list_iterate(get_units_in_focus(), punit) {
2826 if (can_unit_do_autosettlers(punit)) {
2827 request_unit_autosettlers(punit);
2829 } unit_list_iterate_end;
2832 /**************************************************************************
2833 Unit convert key pressed or respective menu entry selected.
2834 **************************************************************************/
2835 void key_unit_convert(void)
2837 unit_list_iterate(get_units_in_focus(), punit) {
2838 request_unit_convert(punit);
2839 } unit_list_iterate_end;
2842 /**************************************************************************
2843 Handle user 'clean fallout' input
2844 **************************************************************************/
2845 void key_unit_fallout(void)
2847 unit_list_iterate(get_units_in_focus(), punit) {
2848 if (can_unit_do_activity(punit, ACTIVITY_FALLOUT)) {
2849 request_new_unit_activity(punit, ACTIVITY_FALLOUT);
2851 } unit_list_iterate_end;
2854 /**************************************************************************
2855 Handle user 'fortify' input
2856 **************************************************************************/
2857 void key_unit_fortify(void)
2859 unit_list_iterate(get_units_in_focus(), punit) {
2860 if (can_unit_do_activity(punit, ACTIVITY_FORTIFYING)) {
2861 request_new_unit_activity(punit, ACTIVITY_FORTIFYING);
2863 } unit_list_iterate_end;
2866 /**************************************************************************
2867 Handle user 'build base of class fortress' input
2868 **************************************************************************/
2869 void key_unit_fortress(void)
2871 unit_list_iterate(get_units_in_focus(), punit) {
2872 struct base_type *pbase =
2873 get_base_by_gui_type(BASE_GUI_FORTRESS, punit, unit_tile(punit));
2875 if (pbase) {
2876 request_new_unit_activity_base(punit, pbase);
2878 } unit_list_iterate_end;
2881 /**************************************************************************
2882 Handle user 'change homecity' input
2883 **************************************************************************/
2884 void key_unit_homecity(void)
2886 unit_list_iterate(get_units_in_focus(), punit) {
2887 request_unit_change_homecity(punit);
2888 } unit_list_iterate_end;
2891 /**************************************************************************
2892 Handle user 'irrigate' input
2893 **************************************************************************/
2894 void key_unit_irrigate(void)
2896 unit_list_iterate(get_units_in_focus(), punit) {
2897 if (can_unit_do_activity(punit, ACTIVITY_IRRIGATE)) {
2898 request_new_unit_activity(punit, ACTIVITY_IRRIGATE);
2900 } unit_list_iterate_end;
2903 /**************************************************************************
2904 Handle user 'build mine' input
2905 **************************************************************************/
2906 void key_unit_mine(void)
2908 unit_list_iterate(get_units_in_focus(), punit) {
2909 if (can_unit_do_activity(punit, ACTIVITY_MINE)) {
2910 request_new_unit_activity(punit, ACTIVITY_MINE);
2912 } unit_list_iterate_end;
2915 /**************************************************************************
2916 Handle user 'pillage' input
2917 **************************************************************************/
2918 void key_unit_pillage(void)
2920 unit_list_iterate(get_units_in_focus(), punit) {
2921 if (can_unit_do_activity(punit, ACTIVITY_PILLAGE)) {
2922 request_unit_pillage(punit);
2924 } unit_list_iterate_end;
2927 /**************************************************************************
2928 Handle user 'clean pollution' input
2929 **************************************************************************/
2930 void key_unit_pollution(void)
2932 unit_list_iterate(get_units_in_focus(), punit) {
2933 if (can_unit_do_activity(punit, ACTIVITY_POLLUTION)) {
2934 request_new_unit_activity(punit, ACTIVITY_POLLUTION);
2936 } unit_list_iterate_end;
2939 /**************************************************************************
2940 Handle user 'build road or railroad' input
2941 **************************************************************************/
2942 void key_unit_road(void)
2944 unit_list_iterate(get_units_in_focus(), punit) {
2945 struct road_type *proad = next_road_for_tile(unit_tile(punit),
2946 unit_owner(punit),
2947 punit);
2949 if (proad != NULL) {
2950 struct act_tgt tgt = { .type = ATT_ROAD, .obj.road = road_number(proad) };
2952 if (can_unit_do_activity_targeted(punit, ACTIVITY_GEN_ROAD, &tgt)) {
2953 request_new_unit_activity_road(punit, proad);
2956 } unit_list_iterate_end;
2959 /**************************************************************************
2960 Handle user 'sentry' input
2961 **************************************************************************/
2962 void key_unit_sentry(void)
2964 unit_list_iterate(get_units_in_focus(), punit) {
2965 if (can_unit_do_activity(punit, ACTIVITY_SENTRY)) {
2966 request_new_unit_activity(punit, ACTIVITY_SENTRY);
2968 } unit_list_iterate_end;
2971 /**************************************************************************
2972 Handle user 'transform unit' input
2973 **************************************************************************/
2974 void key_unit_transform(void)
2976 unit_list_iterate(get_units_in_focus(), punit) {
2977 if (can_unit_do_activity(punit, ACTIVITY_TRANSFORM)) {
2978 request_new_unit_activity(punit, ACTIVITY_TRANSFORM);
2980 } unit_list_iterate_end;
2983 /****************************************************************************
2984 Assign all focus units to this battlegroup.
2985 ****************************************************************************/
2986 void key_unit_assign_battlegroup(int battlegroup, bool append)
2988 if (NULL != client.conn.playing && can_client_issue_orders()
2989 && battlegroups >= 0 && battlegroup < MAX_NUM_BATTLEGROUPS) {
2990 if (!append) {
2991 unit_list_iterate_safe(battlegroups[battlegroup], punit) {
2992 if (!unit_is_in_focus(punit)) {
2993 punit->battlegroup = BATTLEGROUP_NONE;
2994 dsend_packet_unit_battlegroup(&client.conn,
2995 punit->id, BATTLEGROUP_NONE);
2996 refresh_unit_mapcanvas(punit, unit_tile(punit), TRUE, FALSE);
2997 unit_list_remove(battlegroups[battlegroup], punit);
2999 } unit_list_iterate_safe_end;
3001 unit_list_iterate(get_units_in_focus(), punit) {
3002 if (punit->battlegroup != battlegroup) {
3003 if (punit->battlegroup >= 0
3004 && punit->battlegroup < MAX_NUM_BATTLEGROUPS) {
3005 unit_list_remove(battlegroups[punit->battlegroup], punit);
3007 punit->battlegroup = battlegroup;
3008 dsend_packet_unit_battlegroup(&client.conn,
3009 punit->id, battlegroup);
3010 unit_list_append(battlegroups[battlegroup], punit);
3011 refresh_unit_mapcanvas(punit, unit_tile(punit), TRUE, FALSE);
3013 } unit_list_iterate_end;
3014 unit_list_iterate(battlegroups[battlegroup], punit) {
3015 unit_focus_add(punit);
3016 } unit_list_iterate_end;
3020 /****************************************************************************
3021 Bring this battlegroup into focus.
3022 ****************************************************************************/
3023 void key_unit_select_battlegroup(int battlegroup, bool append)
3025 if (NULL != client.conn.playing && can_client_change_view()
3026 && battlegroups >= 0 && battlegroup < MAX_NUM_BATTLEGROUPS) {
3027 int i = 0;
3029 if (unit_list_size(battlegroups[battlegroup]) == 0 && !append) {
3030 unit_focus_set(NULL);
3031 return;
3034 /* FIXME: this is very inefficient and can be improved. */
3035 unit_list_iterate(battlegroups[battlegroup], punit) {
3036 if (i == 0 && !append) {
3037 unit_focus_set(punit);
3038 } else {
3039 unit_focus_add(punit);
3041 i++;
3042 } unit_list_iterate_end;
3046 /**************************************************************************
3047 Toggle drawing of city outlines.
3048 **************************************************************************/
3049 void key_city_outlines_toggle(void)
3051 request_toggle_city_outlines();
3054 /**************************************************************************
3055 Toggle drawing of city output produced by workers of the city.
3056 **************************************************************************/
3057 void key_city_output_toggle(void)
3059 request_toggle_city_output();
3062 /**************************************************************************
3063 Handle user 'toggle map grid' input
3064 **************************************************************************/
3065 void key_map_grid_toggle(void)
3067 request_toggle_map_grid();
3070 /**************************************************************************
3071 Toggle map borders on the mapview on/off based on a keypress.
3072 **************************************************************************/
3073 void key_map_borders_toggle(void)
3075 request_toggle_map_borders();
3078 /**************************************************************************
3079 Toggle native tiles on the mapview on/off based on a keypress.
3080 **************************************************************************/
3081 void key_map_native_toggle(void)
3083 request_toggle_map_native();
3086 /**************************************************************************
3087 Toggle the "Draw the city bar" option.
3088 **************************************************************************/
3089 void key_city_full_bar_toggle(void)
3091 request_toggle_city_full_bar();
3094 /**************************************************************************
3095 Handle user 'toggle city names display' input
3096 **************************************************************************/
3097 void key_city_names_toggle(void)
3099 request_toggle_city_names();
3102 /**************************************************************************
3103 Toggles the "show city growth turns" option by passing off the
3104 request to another function...
3105 **************************************************************************/
3106 void key_city_growth_toggle(void)
3108 request_toggle_city_growth();
3111 /**************************************************************************
3112 Toggles the showing of the buy cost of the current production in the
3113 city descriptions.
3114 **************************************************************************/
3115 void key_city_buycost_toggle(void)
3117 request_toggle_city_buycost();
3120 /**************************************************************************
3121 Handle user 'toggle city production display' input
3122 **************************************************************************/
3123 void key_city_productions_toggle(void)
3125 request_toggle_city_productions();
3128 /**************************************************************************
3129 Handle client request to toggle drawing of trade route information
3130 by the city name for cities visible on the main map view.
3131 **************************************************************************/
3132 void key_city_trade_routes_toggle(void)
3134 request_toggle_city_trade_routes();
3137 /**************************************************************************
3138 Handle user 'toggle terrain display' input
3139 **************************************************************************/
3140 void key_terrain_toggle(void)
3142 request_toggle_terrain();
3145 /**************************************************************************
3146 Handle user 'toggle coastline display' input
3147 **************************************************************************/
3148 void key_coastline_toggle(void)
3150 request_toggle_coastline();
3153 /**************************************************************************
3154 Handle user 'toggle road/railroad display' input
3155 **************************************************************************/
3156 void key_roads_rails_toggle(void)
3158 request_toggle_roads_rails();
3161 /**************************************************************************
3162 Handle user 'toggle irrigation display' input
3163 **************************************************************************/
3164 void key_irrigation_toggle(void)
3166 request_toggle_irrigation();
3169 /**************************************************************************
3170 Handle user 'toggle mine display' input
3171 **************************************************************************/
3172 void key_mines_toggle(void)
3174 request_toggle_mines();
3177 /**************************************************************************
3178 Handle user 'toggle bases display' input
3179 **************************************************************************/
3180 void key_bases_toggle(void)
3182 request_toggle_bases();
3185 /**************************************************************************
3186 Handle user 'toggle specials display' input
3187 **************************************************************************/
3188 void key_specials_toggle(void)
3190 request_toggle_specials();
3193 /**************************************************************************
3194 Handle user 'toggle pollution display' input
3195 **************************************************************************/
3196 void key_pollution_toggle(void)
3198 request_toggle_pollution();
3201 /**************************************************************************
3202 Handle user 'toggle cities display' input
3203 **************************************************************************/
3204 void key_cities_toggle(void)
3206 request_toggle_cities();
3209 /**************************************************************************
3210 Handle user 'toggle units display' input
3211 **************************************************************************/
3212 void key_units_toggle(void)
3214 request_toggle_units();
3217 /**************************************************************************
3218 Toggle the "Solid unit background color" option.
3219 **************************************************************************/
3220 void key_unit_solid_bg_toggle(void)
3222 request_toggle_unit_solid_bg();
3225 /**************************************************************************
3226 Toggle the "Draw shield graphics for units" option.
3227 **************************************************************************/
3228 void key_unit_shields_toggle(void)
3230 request_toggle_unit_shields();
3233 /**************************************************************************
3234 Handle user 'toggle key units display' input
3235 **************************************************************************/
3236 void key_focus_unit_toggle(void)
3238 request_toggle_focus_unit();
3241 /**************************************************************************
3242 Handle user 'toggle fog of war display' input
3243 **************************************************************************/
3244 void key_fog_of_war_toggle(void)
3246 request_toggle_fog_of_war();
3249 /**************************************************************************
3250 Toggle editor mode in the server.
3251 **************************************************************************/
3252 void key_editor_toggle(void)
3254 dsend_packet_edit_mode(&client.conn, !game.info.is_edit_mode);
3257 /**************************************************************************
3258 Recalculate borders.
3259 **************************************************************************/
3260 void key_editor_recalculate_borders(void)
3262 send_packet_edit_recalculate_borders(&client.conn);
3265 /**************************************************************************
3266 Send a request to the server to toggle fog-of-war for the current
3267 player (only applies in edit mode).
3268 **************************************************************************/
3269 void key_editor_toggle_fogofwar(void)
3271 if (client_has_player()) {
3272 dsend_packet_edit_toggle_fogofwar(&client.conn, client_player_number());
3276 /**************************************************************************
3277 All units ready to build city to the tile should now proceed.
3278 **************************************************************************/
3279 void finish_city(struct tile *ptile, const char *name)
3281 unit_list_iterate(ptile->units, punit) {
3282 if (punit->client.asking_city_name) {
3283 /* Unit will disappear only in case city building still success.
3284 * Cancel city building status just in case something has changed
3285 * to prevent city building in the meanwhile and unit will remain
3286 * alive. */
3287 punit->client.asking_city_name = FALSE;
3288 dsend_packet_unit_build_city(&client.conn, punit->id, name);
3290 } unit_list_iterate_end;
3293 /**************************************************************************
3294 Do not build city after all. Cancel city building mark from all units
3295 prepared for it.
3296 **************************************************************************/
3297 void cancel_city(struct tile *ptile)
3299 unit_list_iterate(ptile->units, punit) {
3300 punit->client.asking_city_name = FALSE;
3301 } unit_list_iterate_end;