Freeciv-3.3
Loading...
Searching...
No Matches
action_dialog.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996-2005 - Freeciv Development Team
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <gtk/gtk.h>
19
20/* utility */
21#include "astring.h"
22#include "support.h"
23
24/* common */
25#include "actions.h"
26#include "game.h"
27#include "traderoutes.h"
28#include "movement.h"
29#include "research.h"
30#include "unit.h"
31#include "unitlist.h"
32
33/* client */
34#include "dialogs_g.h"
35#include "chatline.h"
36#include "choice_dialog.h"
37#include "client_main.h"
38#include "climisc.h"
39#include "connectdlg_common.h"
40#include "control.h"
41#include "gui_main.h"
42#include "gui_stuff.h"
43#include "mapview.h"
44#include "packhand.h"
45#include "text.h"
46
47/* client/gui-gtk-4.0 */
48#include "citydlg.h"
49#include "dialogs.h"
50#include "unitselextradlg.h"
51#include "unitselunitdlg.h"
52#include "wldlg.h"
53
54/* Locations for non action enabler controlled buttons. */
55#define BUTTON_NEW_UNIT_TGT (ACTION_COUNT + 1)
56#define BUTTON_NEW_EXTRA_TGT (BUTTON_NEW_UNIT_TGT + 1)
57#define BUTTON_LOCATION (BUTTON_NEW_EXTRA_TGT + 1)
58#define BUTTON_WAIT (BUTTON_LOCATION + 1)
59#define BUTTON_CANCEL (BUTTON_WAIT + 1)
60#define BUTTON_COUNT (BUTTON_CANCEL + 1)
61
62#define BUTTON_NOT_THERE -1
63
64
67
68static int actor_unit_id;
70static int target_extra_id;
72static bool did_not_decide = FALSE;
74
76
78
79/* A structure to hold parameters for actions inside the GUI instead of
80 * storing the needed data in a global variable. */
81struct action_data {
83 int actor_unit_id;
90};
91
92/* TODO: Maybe this should be in the dialog itself? */
94
95/**********************************************************************/
100 int actor_id,
101 int target_city_id,
102 int target_unit_id,
103 int target_tile_id,
105 int target_tech_id,
106 int tgt_extra_id)
107{
108 struct action_data *data = fc_malloc(sizeof(*data));
109
110 data->act_id = act_id;
111 data->actor_unit_id = actor_id;
118
119 return data;
120}
121
122/**********************************************************************/
127{
129 /* The client isn't waiting for information for any unanswered follow
130 * up questions. */
131
132 struct unit *actor_unit;
133
135 /* The action selection dialog wasn't closed because the actor unit
136 * was lost. */
137
138 /* The probabilities didn't just disappear, right? */
141
143 }
144
146 /* The action selection dialog was closed but only so it can be
147 * redrawn with fresh data. */
148
150 } else {
151 /* The action selection process is over, at least for now. */
153 }
154
155 if (did_not_decide) {
156 /* The action selection dialog was closed but the player didn't
157 * decide what the unit should do. */
158
159 /* Reset so the next action selection dialog does the right thing. */
161 } else {
162 /* An action, or no action at all, was selected. */
165 }
166 }
167}
168
169/**********************************************************************/
174{
175 /* Stop waiting. Move on to the next queued unit. */
178}
179
180/**********************************************************************/
187{
188 /* Stop assuming the answer to a follow up question will arrive. */
190}
191
192/**********************************************************************/
197{
198 /* Don't add an action mapping here unless the non targeted version is
199 * selectable in the targeted version's target selection dialog. */
200 switch ((enum gen_action)tgt_action_id) {
209 default:
210 /* No non targeted version found. */
211 return ACTION_NONE;
212 }
213}
214
215/**********************************************************************/
220{
221 /* Don't add an action mapping here unless the non targeted version is
222 * selectable in the targeted version's target selection dialog. */
223 switch ((enum gen_action)tgt_action_id) {
230 default:
231 /* No non targeted version found. */
232 return ACTION_NONE;
233 }
234}
235
236/**********************************************************************/
241{
242 int actor_id, target_id, sub_target;
243 struct action *paction;
244
245 struct action_data *args = act_sel_dialog_data;
246
247 bool failed = FALSE;
248
249 /* Data */
250 args->act_id = GPOINTER_TO_INT(data);
252
253 /* Actor */
255 actor_id = args->actor_unit_id;
256 if (NULL == game_unit_by_number(actor_id)) {
257 /* Probably dead. */
258 failed = TRUE;
259 }
260
261 /* Target */
262 target_id = IDENTITY_NUMBER_ZERO;
264 case ATK_CITY:
265 target_id = args->target_city_id;
266 if (NULL == game_city_by_number(target_id)) {
267 /* Probably destroyed. */
268 failed = TRUE;
269 }
270 break;
271 case ATK_UNIT:
272 target_id = args->target_unit_id;
273 if (NULL == game_unit_by_number(target_id)) {
274 /* Probably dead. */
275 failed = TRUE;
276 }
277 break;
278 case ATK_STACK:
279 case ATK_TILE:
280 case ATK_EXTRAS:
281 target_id = args->target_tile_id;
282 if (NULL == index_to_tile(&(wld.map), target_id)) {
283 /* TODO: Should this be possible at all? If not: add assertion. */
284 failed = TRUE;
285 }
286 break;
287 case ATK_SELF:
288 target_id = IDENTITY_NUMBER_ZERO;
289 break;
290 case ATK_COUNT:
292 failed = TRUE;
293 }
294
295 /* Sub target. */
296 sub_target = NO_TARGET;
297 if (paction->target_complexity != ACT_TGT_COMPL_SIMPLE) {
299 case ASTK_BUILDING:
300 sub_target = args->target_building_id;
301 if (NULL == improvement_by_number(sub_target)) {
302 /* Did the ruleset change? */
303 failed = TRUE;
304 }
305 break;
306 case ASTK_TECH:
307 sub_target = args->target_tech_id;
308 if (NULL == valid_advance_by_number(sub_target)) {
309 /* Did the ruleset change? */
310 failed = TRUE;
311 }
312 break;
313 case ASTK_EXTRA:
315 /* TODO: Validate if the extra is there? */
316 sub_target = args->target_extra_id;
317 if (NULL == extra_by_number(sub_target)) {
318 /* Did the ruleset change? */
319 failed = TRUE;
320 }
321 break;
322 case ASTK_NONE:
323 case ASTK_COUNT:
324 /* Shouldn't happen. */
326 failed = TRUE;
327 break;
328 }
329 }
330
331 /* Send request. */
332 if (!failed) {
333 request_do_action(paction->id, actor_id, target_id, sub_target, "");
334 }
335
336 /* Clean up. */
338 /* No follow up questions. */
340 FC_FREE(args);
341}
342
343/**********************************************************************/
348{
349 int actor_id, target_id;
350 struct action *paction;
351
352 struct action_data *args = act_sel_dialog_data;
353
354 bool failed = FALSE;
355
356 /* Data */
357 args->act_id = GPOINTER_TO_INT(data);
359
360 /* Actor */
362 actor_id = args->actor_unit_id;
363 if (NULL == game_unit_by_number(actor_id)) {
364 /* Probably dead. */
365 failed = TRUE;
366 }
367
368 /* Target */
369 target_id = IDENTITY_NUMBER_ZERO;
371 case ATK_CITY:
372 target_id = args->target_city_id;
373 if (NULL == game_city_by_number(target_id)) {
374 /* Probably destroyed. */
375 failed = TRUE;
376 }
377 break;
378 case ATK_UNIT:
379 target_id = args->target_unit_id;
380 if (NULL == game_unit_by_number(target_id)) {
381 /* Probably dead. */
382 failed = TRUE;
383 }
384 break;
385 case ATK_STACK:
386 case ATK_TILE:
387 case ATK_EXTRAS:
388 target_id = args->target_tile_id;
389 if (NULL == index_to_tile(&(wld.map), target_id)) {
390 /* TODO: Should this be possible at all? If not: add assertion. */
391 failed = TRUE;
392 }
393 break;
394 case ATK_SELF:
395 target_id = IDENTITY_NUMBER_ZERO;
396 break;
397 case ATK_COUNT:
399 failed = TRUE;
400 }
401
402 /* Send request. */
403 if (!failed) {
404 request_action_details(paction->id, actor_id, target_id);
405 }
406
407 /* Wait for the server's reply before moving on to the next unit that
408 * needs to know what action to take. */
410
411 /* Clean up. */
413 /* No client side follow up questions. */
415 FC_FREE(args);
416}
417
418/**********************************************************************/
431
432/**********************************************************************/
436{
437 struct unit *punit;
438 struct action_data *args = act_sel_dialog_data;
439
442 struct unit_list *as_list;
443
448 }
449
451 free(args);
452}
453
454/**********************************************************************/
457static void bribe_unit_response(GtkWidget *w, gint response, gpointer data)
458{
459 struct action_data *args = (struct action_data *)data;
460
461 if (response == GTK_RESPONSE_YES) {
463 args->target_unit_id, 0, "");
464 }
465
467 free(args);
468
469 /* The user have answered the follow up question. Move on. */
471}
472
473/**********************************************************************/
476static void bribe_stack_response(GtkWidget *w, gint response, gpointer data)
477{
478 struct action_data *args = (struct action_data *)data;
479
480 if (response == GTK_RESPONSE_YES) {
482 args->target_tile_id, 0, "");
483 }
484
486 free(args);
487
488 /* The user have answered the follow up question. Move on. */
490}
491
492/**********************************************************************/
495void popup_bribe_unit_dialog(struct unit *actor, struct unit *punit, int cost,
496 const struct action *paction)
497{
499 char buf[1024];
500
501 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
502 "Treasury contains %d gold.",
503 client_player()->economic.gold),
504 client_player()->economic.gold);
505
506 if (cost <= client_player()->economic.gold) {
509 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
510 PL_("Bribe unit for %d gold?\n%s",
511 "Bribe unit for %d gold?\n%s", cost), cost, buf);
512 gtk_window_set_title(GTK_WINDOW(shell), _("Bribe Enemy Unit"));
514 } else {
517 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
518 PL_("Bribing the unit costs %d gold.\n%s",
519 "Bribing the unit costs %d gold.\n%s", cost), cost, buf);
520 gtk_window_set_title(GTK_WINDOW(shell), _("Traitors Demand Too Much!"));
522 }
524
526 act_data(paction->id, actor->id,
527 0, punit->id, 0,
528 0, 0, 0));
529}
530
531/**********************************************************************/
534void popup_bribe_stack_dialog(struct unit *actor, struct tile *ptile, int cost,
535 const struct action *paction)
536{
538 char buf[1024];
539
540 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
541 "Treasury contains %d gold.",
542 client_player()->economic.gold),
543 client_player()->economic.gold);
544
545 if (cost <= client_player()->economic.gold) {
548 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
549 PL_("Bribe unit stack for %d gold?\n%s",
550 "Bribe unit stack for %d gold?\n%s", cost), cost, buf);
551 gtk_window_set_title(GTK_WINDOW(shell), _("Bribe Enemy Unit"));
553 } else {
556 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
557 PL_("Bribing units costs %d gold.\n%s",
558 "Bribing units costs %d gold.\n%s", cost), cost, buf);
559 gtk_window_set_title(GTK_WINDOW(shell), _("Traitors Demand Too Much!"));
561 }
563
565 act_data(paction->id, actor->id,
566 0, 0, ptile->index,
567 0, 0, 0));
568}
569
570/**********************************************************************/
573static void spy_advances_response(GtkWidget *w, gint response,
574 gpointer data)
575{
576 struct action_data *args = (struct action_data *)data;
577
578 if (response == GTK_RESPONSE_ACCEPT && args->target_tech_id > 0) {
581 if (args->target_tech_id == A_UNSET) {
582 /* This is the untargeted version. */
584 args->actor_unit_id, args->target_city_id,
585 args->target_tech_id, "");
586 } else {
587 /* This is the targeted version. */
589 args->actor_unit_id, args->target_city_id,
590 args->target_tech_id, "");
591 }
592 }
593 }
594
597 free(data);
598
599 /* The user have answered the follow up question. Move on. */
601}
602
603/**********************************************************************/
607 gpointer data)
608{
609 struct action_data *args = (struct action_data *)data;
610
611 GtkTreeModel *model;
612 GtkTreeIter it;
613
614 if (gtk_tree_selection_get_selected(select, &model, &it)) {
615 gtk_tree_model_get(model, &it, 1, &(args->target_tech_id), -1);
616
619 } else {
620 args->target_tech_id = 0;
621
624 }
625}
626
627/**********************************************************************/
630static void create_advances_list(struct player *pplayer,
631 struct player *pvictim,
632 struct action_data *args)
633{
634 GtkWidget *sw, *frame, *label, *vgrid, *view;
635 GtkListStore *store;
638
640
641 spy_tech_shell = gtk_dialog_new_with_buttons(_("Steal Technology"),
642 NULL, 0,
643 _("_Cancel"), GTK_RESPONSE_CANCEL,
644 _("_Steal"), GTK_RESPONSE_ACCEPT,
645 NULL);
647
650
651 frame = gtk_frame_new(_("Select Advance to Steal"));
653
659
661
665 g_object_unref(store);
667
670 "text", 0, NULL);
672
674 "use-underline", TRUE,
675 "mnemonic-widget", view,
676 "label", _("_Advances:"),
677 "xalign", 0.0,
678 "yalign", 0.5,
679 NULL);
680 gtk_grid_attach(GTK_GRID(vgrid), label, 0, 0, 1, 1);
681
685
688 gtk_widget_set_size_request(sw, -1, 200);
689
690 gtk_grid_attach(GTK_GRID(vgrid), sw, 0, 1, 1, 1);
691
692 /* Now populate the list */
693 if (pvictim) { /* You don't want to know what lag can do -- Syela */
694 const struct research *presearch = research_get(pplayer);
695 const struct research *vresearch = research_get(pvictim);
696 GtkTreeIter it;
697 GValue value = { 0, };
698
704 gtk_list_store_append(store, &it);
705
708 (presearch, i));
709 gtk_list_store_set_value(store, &it, 0, &value);
710 g_value_unset(&value);
711 gtk_list_store_set(store, &it, 1, i, -1);
712 }
714
717 gtk_list_store_append(store, &it);
718
720 {
721 struct astring str = ASTRING_INIT;
722 /* TRANS: %s is a unit name, e.g., Spy */
723 astr_set(&str, _("At %s's Discretion"),
726 astr_free(&str);
727 }
728 gtk_list_store_set_value(store, &it, 0, &value);
729 g_value_unset(&value);
730 gtk_list_store_set(store, &it, 1, A_UNSET, -1);
731 }
732 }
733
736
738 TRUE);
739
744
745 args->target_tech_id = 0;
746
748}
749
750/**********************************************************************/
753static void spy_improvements_response(GtkWidget *w, gint response, gpointer data)
754{
755 struct action_data *args = (struct action_data *)data;
756
757 if (response == GTK_RESPONSE_ACCEPT && args->target_building_id > -2) {
760 if (args->target_building_id == B_LAST) {
761 /* This is the untargeted version. */
763 args->actor_unit_id,
764 args->target_city_id,
765 args->target_building_id, "");
766 } else if (args->target_building_id == -1) {
767 /* This is the city production version. */
769 args->actor_unit_id,
770 args->target_city_id,
771 args->target_building_id, "");
772 } else {
773 /* This is the targeted version. */
775 args->actor_unit_id,
776 args->target_city_id,
777 args->target_building_id, "");
778 }
779 }
780 }
781
784 free(args);
785
786 /* The user have answered the follow up question. Move on. */
788}
789
790/**********************************************************************/
794{
795 struct action_data *args = (struct action_data *)data;
796
797 GtkTreeModel *model;
798 GtkTreeIter it;
799
800 if (gtk_tree_selection_get_selected(select, &model, &it)) {
801 gtk_tree_model_get(model, &it, 1, &(args->target_building_id), -1);
802
805 } else {
806 args->target_building_id = -2;
807
810 }
811}
812
813/**********************************************************************/
816static void create_improvements_list(struct player *pplayer,
817 struct city *pcity,
818 struct action_data *args)
819{
820 GtkWidget *sw, *frame, *label, *vgrid, *view;
821 GtkListStore *store;
824 GtkTreeIter it;
825 struct action *paction = action_by_number(args->act_id);
827
828 if (paction->result == ACTRES_STRIKE_BUILDING) {
829 spy_sabotage_shell = gtk_dialog_new_with_buttons(_("Strike Improvements"),
830 NULL, 0,
831 _("_Cancel"), GTK_RESPONSE_CANCEL,
832 _("_Strike"), GTK_RESPONSE_ACCEPT,
833 NULL);
834 } else {
835 spy_sabotage_shell = gtk_dialog_new_with_buttons(_("Sabotage Improvements"),
836 NULL, 0,
837 _("_Cancel"), GTK_RESPONSE_CANCEL,
838 _("_Sabotage"), GTK_RESPONSE_ACCEPT,
839 NULL);
840 }
842
845
846 if (paction->result == ACTRES_STRIKE_BUILDING) {
847 frame = gtk_frame_new(_("Select Improvement to Strike"));
848 } else {
849 frame = gtk_frame_new(_("Select Improvement to Sabotage"));
850 }
852
858
860
864 g_object_unref(store);
866
869 "text", 0, NULL);
871
873 "use-underline", TRUE,
874 "mnemonic-widget", view,
875 "label", _("_Improvements:"),
876 "xalign", 0.0,
877 "yalign", 0.5,
878 NULL);
879 gtk_grid_attach(GTK_GRID(vgrid), label, 0, 0, 1, 1);
880
884
888
889 gtk_grid_attach(GTK_GRID(vgrid), sw, 0, 1, 1, 1);
890
891 /* Now populate the list */
894 args->act_id)])) {
895 gtk_list_store_append(store, &it);
896 gtk_list_store_set(store, &it, 0, _("City Production"), 1, -1, -1);
897 }
898
899 city_built_iterate(pcity, pimprove) {
900 if (pimprove->sabotage > 0) {
901 gtk_list_store_append(store, &it);
902 gtk_list_store_set(store, &it,
904 1, improvement_number(pimprove),
905 -1);
906 }
908
911 struct astring str = ASTRING_INIT;
912
913 gtk_list_store_append(store, &it);
914
915 /* TRANS: %s is a unit name, e.g., Spy */
916 astr_set(&str, _("At %s's Discretion"),
918 gtk_list_store_set(store, &it, 0, astr_str(&str), 1, B_LAST, -1);
919
920 astr_free(&str);
921 }
922
925
927 TRUE);
928
933
934 args->target_building_id = -2;
935
937}
938
939/**********************************************************************/
943{
944 struct action_data *args = (struct action_data *)data;
945
947 struct player *pvictim = NULL;
948
949 if (pvcity) {
951 }
952
953/* It is concievable that pvcity will not be found, because something
954 has happened to the city during latency. Therefore we must initialize
955 pvictim to NULL and account for !pvictim in create_advances_list. -- Syela */
956
957 /* FIXME: Don't discard the second tech choice dialog. */
958 if (!spy_tech_shell) {
961 } else {
962 free(args);
963 }
964
965 /* Wait for the player's reply before moving on to the next unit that
966 * needs to know what action to take. */
968
970}
971
972/**********************************************************************/
981
982/**********************************************************************/
991
992/**********************************************************************/
997 const struct action *paction)
998{
999 /* FIXME: Don't discard the second target choice dialog. */
1000 if (!spy_sabotage_shell) {
1002 act_data(paction->id,
1003 actor->id, pcity->id, 0, 0,
1004 0, 0, 0));
1006 }
1007}
1008
1009/**********************************************************************/
1012static void incite_response(GtkWidget *w, gint response, gpointer data)
1013{
1014 struct action_data *args = (struct action_data *)data;
1015
1016 if (response == GTK_RESPONSE_YES) {
1018 args->target_city_id, 0, "");
1019 }
1020
1022 free(args);
1023
1024 /* The user have answered the follow up question. Move on. */
1026}
1027
1028/**********************************************************************/
1031void popup_incite_dialog(struct unit *actor, struct city *pcity, int cost,
1032 const struct action *paction)
1033{
1035 char buf[1024];
1036
1037 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
1038 "Treasury contains %d gold.",
1039 client_player()->economic.gold),
1040 client_player()->economic.gold);
1041
1045 _("You can't incite a revolt in %s."),
1047 gtk_window_set_title(GTK_WINDOW(shell), _("City can't be incited!"));
1049 } else if (cost <= client_player()->economic.gold) {
1052 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
1053 PL_("Incite a revolt for %d gold?\n%s",
1054 "Incite a revolt for %d gold?\n%s", cost), cost, buf);
1055 gtk_window_set_title(GTK_WINDOW(shell), _("Incite a Revolt!"));
1057 } else {
1059 0,
1061 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
1062 PL_("Inciting a revolt costs %d gold.\n%s",
1063 "Inciting a revolt costs %d gold.\n%s", cost), cost, buf);
1064 gtk_window_set_title(GTK_WINDOW(shell), _("Traitors Demand Too Much!"));
1066 }
1068
1070 act_data(paction->id, actor->id,
1071 pcity->id, 0, 0,
1072 0, 0, 0));
1073}
1074
1075/**********************************************************************/
1079{
1080 int au_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(dlg), "actor"));
1081
1082 if (arg == GTK_RESPONSE_YES) {
1084
1085 if (actor != NULL) {
1087 "target"));
1089 struct tile *tgt_tile = g_object_get_data(G_OBJECT(dlg), "tile");
1090
1091 if (tgt_unit == NULL) {
1092 /* Make the action dialog pop up again. */
1094 actor->id,
1095 /* Let the server choose the target
1096 * unit. */
1098 tgt_tile->index,
1101 } else {
1103 actor->id,
1104 tgt_id,
1105 tgt_tile->index,
1108 }
1109 }
1110 } else {
1111 /* Dialog canceled. This ends the action selection process. */
1113 }
1114
1116}
1117
1118/**********************************************************************/
1122{
1123 struct action_data *args = act_sel_dialog_data;
1124
1125 struct unit *punit;
1126 struct unit *tunit;
1127 struct tile *ptile;
1128
1130 && (ptile = index_to_tile(&(wld.map), args->target_tile_id))
1131 && (tunit = game_unit_by_number(args->target_unit_id))) {
1132 select_tgt_unit(punit, ptile, ptile->units, tunit,
1133 _("Target unit selection"),
1134 _("Looking for target unit:"),
1135 _("Units at tile:"),
1136 _("Select"),
1138 }
1139
1143 free(args);
1144}
1145
1146/**********************************************************************/
1150{
1151 int au_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(dlg), "actor"));
1152
1153 if (arg == GTK_RESPONSE_YES) {
1155
1156 if (actor != NULL) {
1158 "target"));
1160 struct tile *tgt_tile = g_object_get_data(G_OBJECT(dlg), "tile");
1161
1162 if (tgt_extra == NULL) {
1163 /* Make the action dialog pop up again. */
1165 actor->id,
1167 tgt_tile->index,
1168 /* Let the server choose the target
1169 * extra. */
1172 } else {
1174 actor->id,
1176 tgt_tile->index,
1177 tgt_id,
1179 }
1180 }
1181 } else {
1182 /* Dialog canceled. This ends the action selection process. */
1184 }
1185
1187}
1188
1189/**********************************************************************/
1193{
1194 struct action_data *args = act_sel_dialog_data;
1195
1196 struct unit *act_unit;
1197 struct extra_type *tgt_extra;
1198 struct tile *tgt_tile;
1199
1201 && (tgt_tile = index_to_tile(&(wld.map), args->target_tile_id))
1204
1205 /* Start with the extras at the tile */
1207
1209 if (BV_ISSET(potential_targets, extra_number(pextra))) {
1210 /* This extra is at the tile. Can anything be done to it? */
1212 pextra)) {
1214 }
1215 } else {
1216 /* This extra isn't at the tile yet. Can it be created? */
1218 pextra)) {
1220 }
1221 }
1223
1225 /* TRANS: GTK action selection dialog extra target
1226 * selection dialog title. */
1227 _("Target extra selection"),
1228 /* TRANS: GTK action selection dialog extra target
1229 * selection dialog actor unit label. */
1230 _("Looking for target extra:"),
1231 /* TRANS: GTK action selection dialog extra target
1232 * selection dialog extra list label. */
1233 _("Extra targets:"),
1234 _("Select"),
1236 }
1237
1241 free(args);
1242}
1243
1244/**********************************************************************/
1248{
1249 struct action_data *args = act_sel_dialog_data;
1250
1251 struct unit *punit;
1252
1253 if ((punit = game_unit_by_number(args->actor_unit_id))) {
1255 }
1256}
1257
1258/**********************************************************************/
1262{
1263 struct action_data *args = act_sel_dialog_data;
1264
1265 key_unit_wait();
1266
1267 /* The dialog was destroyed when key_unit_wait() resulted in
1268 * action_selection_close() being called. */
1269
1270 free(args);
1271}
1272
1273/**********************************************************************/
1281
1282/**********************************************************************/
1290
1291/**********************************************************************/
1299
1300/* Mapping from an action to the function to call when its button is
1301 * pushed. */
1303 /* Unit acting against a city target. */
1314
1315 /* Unit acting against a unit target. */
1317
1318 /* Unit acting against all units at a tile. */
1320
1321 /* Unit acting against a tile. */
1323
1324 /* Unit acting with no target except itself. */
1325 /* No special callback functions needed for any self targeted actions. */
1326};
1327
1328/**********************************************************************/
1333 const struct act_prob *act_probs,
1334 const char *custom,
1336{
1337 const gchar *label;
1338 const gchar *tooltip;
1339 GCallback cb;
1340
1341 if (af_map[act_id] == NULL) {
1342 /* No special call back function needed for this action. */
1344 } else {
1345 /* Special action specific callback function specified. */
1346 cb = af_map[act_id];
1347 }
1348
1349 /* Don't show disabled actions. */
1351 return;
1352 }
1353
1354 label = action_prepare_ui_name(act_id, "_",
1356 custom);
1357
1359 act_probs[act_id]);
1360
1363 FALSE, tooltip);
1364}
1365
1366/**********************************************************************/
1371 const struct act_prob *act_probs,
1372 const char *custom,
1374{
1375 const gchar *label;
1376 const gchar *tooltip;
1377
1378 /* An action that just became impossible has its button disabled.
1379 * An action that became possible again must be re-enabled. */
1383
1384 /* The probability may have changed. */
1385 label = action_prepare_ui_name(act_id, "_",
1387
1389 act_probs[act_id]);
1390
1393 label);
1396 tooltip);
1397}
1398
1399/**********************************************************************/
1404 struct city *target_city,
1405 struct unit *target_unit,
1406 struct tile *target_tile,
1407 struct extra_type *target_extra,
1408 const struct act_prob *act_probs)
1409{
1410 GtkWidget *shl;
1411 struct astring title = ASTRING_INIT, text = ASTRING_INIT;
1412 struct city *actor_homecity;
1413
1414 int button_id;
1415
1417 act_data(ACTION_ANY, /* Not decided yet */
1418 actor_unit->id,
1422 /* No target_building or target_tech supplied. (Dec 2019) */
1423 B_LAST, A_UNSET,
1425
1426 /* Could be caused by the server failing to reply to a request for more
1427 * information or a bug in the client code. */
1429 "Diplomat queue problem. Is another diplomat window open?");
1430
1431 /* No extra input is required as no action has been chosen yet. */
1433
1434 /* No buttons are added yet. */
1435 for (button_id = 0; button_id < BUTTON_COUNT; button_id++) {
1437 }
1438
1440
1444 target_city->id :
1447 target_unit->id :
1460 EXTRA_NONE;
1461
1462 astr_set(&title,
1463 /* TRANS: %s is a unit name, e.g., Spy */
1464 _("Choose Your %s's Strategy"),
1466
1467 if (target_city && actor_homecity) {
1468 astr_set(&text,
1469 _("Your %s from %s reaches the city of %s.\nWhat now?"),
1473 } else if (target_city) {
1474 astr_set(&text,
1475 _("Your %s has arrived at %s.\nWhat is your command?"),
1478 } else if (target_unit != nullptr) {
1480
1481 if (owner != nullptr) {
1482 astr_set(&text,
1483 /* TRANS: Your Spy is ready to act against Roman Freight. */
1484 _("Your %s is ready to act against %s %s."),
1488 } else {
1489 /* Flagless unit */
1490 astr_set(&text,
1491 /* TRANS: Your Spy is ready to act against Freight. */
1492 _("Your %s is ready to act against %s."),
1495 }
1496 } else {
1498 "No target specified.");
1499 astr_set(&text,
1500 /* TRANS: %s is a unit name, e.g., Diplomat, Spy */
1501 _("Your %s is waiting for your command."),
1503 }
1504
1506 astr_str(&text));
1507
1508 /* Unit acting against a city */
1509
1510 action_iterate(act) {
1515 act_probs[act],
1516 actor_unit,
1517 target_city),
1518 act);
1519 }
1521
1522 /* Unit acting against another unit */
1523
1524 action_iterate(act) {
1529 act_probs[act],
1530 actor_unit,
1531 target_city),
1532 act);
1533 }
1535
1536 /* Unit acting against all units at a tile */
1537
1538 action_iterate(act) {
1543 act_probs[act],
1544 actor_unit,
1545 target_city),
1546 act);
1547 }
1549
1550 /* Unit acting against a tile */
1551
1552 action_iterate(act) {
1557 act_probs[act],
1558 actor_unit,
1559 target_city),
1560 act);
1561 }
1563
1564 /* Unit acting against a tile's extras */
1565
1566 action_iterate(act) {
1571 act_probs[act],
1572 actor_unit,
1573 target_city),
1574 act);
1575 }
1577
1578 /* Unit acting against itself. */
1579
1580 action_iterate(act) {
1585 act_probs[act],
1586 actor_unit,
1587 target_city),
1588 act);
1589 }
1591
1592 if (target_unit != NULL
1593 && unit_list_size(target_tile->units) > 1) {
1596 choice_dialog_add(shl, _("Change unit target"),
1599 }
1600
1601 if (target_extra != NULL) {
1604 choice_dialog_add(shl, _("Change extra target"),
1607 }
1608
1611 choice_dialog_add(shl, _("Show Location"),
1614 TRUE, NULL);
1615
1618 choice_dialog_add(shl, _("_Wait"),
1621 TRUE, NULL);
1622
1625 choice_dialog_add(shl, _("_Cancel"),
1628 FALSE, NULL);
1629
1631
1633
1635 g_signal_connect(shl, "destroy",
1637 g_signal_connect(shl, "close-request",
1640
1641 /* Give follow up questions access to action probabilities. */
1643 action_iterate(act) {
1646
1647 astr_free(&title);
1648 astr_free(&text);
1649}
1650
1651/**********************************************************************/
1657{
1658 if (act_sel_dialog == NULL) {
1659 return IDENTITY_NUMBER_ZERO;
1660 }
1661 return actor_unit_id;
1662}
1663
1664/**********************************************************************/
1671{
1672 if (act_sel_dialog == NULL) {
1673 return IDENTITY_NUMBER_ZERO;
1674 }
1675 return target_ids[ATK_CITY];
1676}
1677
1678/**********************************************************************/
1685{
1686 if (act_sel_dialog == NULL) {
1687 return IDENTITY_NUMBER_ZERO;
1688 }
1689
1690 return target_ids[ATK_UNIT];
1691}
1692
1693/**********************************************************************/
1700{
1701 if (act_sel_dialog == NULL) {
1702 return TILE_INDEX_NONE;
1703 }
1704
1705 return target_ids[ATK_TILE];
1706}
1707
1708/**********************************************************************/
1715{
1716 if (act_sel_dialog == NULL) {
1717 return EXTRA_NONE;
1718 }
1719
1720 return target_extra_id;
1721}
1722
1723/**********************************************************************/
1727 struct city *target_city,
1728 struct unit *target_unit,
1729 struct tile *target_tile,
1730 struct extra_type *target_extra,
1731 const struct act_prob *act_probs)
1732{
1733 if (act_sel_dialog == NULL) {
1735 "The action selection dialog should have been open");
1736 return;
1737 }
1738
1741 "The action selection dialog is for another actor unit.");
1742 return;
1743 }
1744
1745 /* A new target may have appeared. */
1746 if (target_city) {
1748 }
1749 if (target_unit) {
1751 }
1752 if (target_tile) {
1754 }
1755 /* No target_building or target_tech supplied. (Dec 2019) */
1756 if (target_extra) {
1758 }
1759
1760 action_iterate(act) {
1761 const char *custom;
1762
1763 if (action_id_get_actor_kind(act) != AAK_UNIT) {
1764 /* Not relevant. */
1765 continue;
1766 }
1767
1769 act_probs[act],
1770 actor_unit,
1771 target_city);
1772
1773 if (BUTTON_NOT_THERE == action_button_map[act]) {
1774 /* Add the button (unless its probability is 0). */
1776 } else {
1777 /* Update the existing button. */
1779 }
1781
1782 /* DO NOT change the action_button_map[] for any button to reflect its
1783 * new position. A button keeps its choice dialog internal name when its
1784 * position changes. A button's id number is therefore based on when
1785 * it was added, not on its current position. */
1786
1788 /* Move the wait button below the recently added button. */
1791 }
1792
1794 /* Move the cancel button below the recently added button. */
1797 }
1798
1800}
1801
1802/**********************************************************************/
1806{
1807 if (act_sel_dialog != NULL) {
1810 }
1811}
const char * action_prepare_ui_name(action_id act_id, const char *mnemonic, const struct act_prob prob, const char *custom)
Definition actions.c:1312
enum action_actor_kind action_get_actor_kind(const struct action *paction)
Definition actions.c:1098
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:5079
enum action_sub_target_kind action_get_sub_target_kind(const struct action *paction)
Definition actions.c:1119
enum action_target_kind action_get_target_kind(const struct action *paction)
Definition actions.c:1108
static struct action * action_by_number(action_id act_id)
Definition actions.h:400
#define action_iterate_end
Definition actions.h:218
#define action_id_get_actor_kind(act_id)
Definition actions.h:413
#define action_iterate(_act_)
Definition actions.h:214
#define ACTION_ANY
Definition actions.h:56
#define action_id_get_target_kind(act_id)
Definition actions.h:417
#define ACTION_NONE
Definition actions.h:59
void astr_free(struct astring *astr)
Definition astring.c:148
void astr_set(struct astring *astr, const char *format,...)
Definition astring.c:251
#define str
Definition astring.c:76
static const char * astr_str(const struct astring *astr) fc__attribute((nonnull(1)))
Definition astring.h:93
#define ASTRING_INIT
Definition astring.h:44
#define BV_SET(bv, bit)
Definition bitvector.h:89
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
#define BV_CLR(bv, bit)
Definition bitvector.h:94
const char * city_improvement_name_translation(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:663
const char * city_name_get(const struct city *pcity)
Definition city.c:1137
#define INCITE_IMPOSSIBLE_COST
Definition city.h:93
#define city_owner(_pcity_)
Definition city.h:560
#define city_built_iterate(_pcity, _p)
Definition city.h:831
#define city_built_iterate_end
Definition city.h:837
struct civclient client
#define client_player()
void client_unit_init_act_prob_cache(struct unit *punit)
Definition climisc.c:1259
char * incite_cost
Definition comments.c:76
void action_selection_no_longer_in_progress(const int old_actor_id)
Definition control.c:1063
void request_do_action(action_id action, int actor_id, int target_id, int sub_tgt, const char *name)
Definition control.c:1742
void request_action_details(action_id action, int actor_id, int target_id)
Definition control.c:1810
void action_decision_clear_want(const int old_actor_id)
Definition control.c:1092
void key_unit_wait(void)
Definition control.c:3554
void action_selection_next_in_focus(const int old_actor_id)
Definition control.c:1104
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id popup_bribe_unit_dialog
Definition dialogs_g.h:72
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int const struct action *paction popup_sabotage_dialog
Definition dialogs_g.h:76
struct unit struct city struct unit * target_unit
Definition dialogs_g.h:55
popup_action_selection
Definition dialogs_g.h:54
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit * actor
Definition dialogs_g.h:72
struct unit * actor_unit
Definition dialogs_g.h:54
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs action_selection_no_longer_in_progress_gui_specific
Definition dialogs_g.h:68
struct unit struct city struct unit struct tile * target_tile
Definition dialogs_g.h:56
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:73
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:77
struct unit struct city * target_city
Definition dialogs_g.h:55
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int cost
Definition dialogs_g.h:73
struct unit struct city struct unit struct tile struct extra_type * target_extra
Definition dialogs_g.h:56
int extra_number(const struct extra_type *pextra)
Definition extras.c:161
struct extra_type * extra_by_number(int id)
Definition extras.c:183
#define EXTRA_NONE
Definition extras.h:85
#define extra_type_re_active_iterate_end
Definition extras.h:329
#define extra_type_re_active_iterate(_p)
Definition extras.h:325
#define NO_TARGET
Definition fc_types.h:214
int action_id
Definition fc_types.h:249
#define IDENTITY_NUMBER_ZERO
Definition fc_types.h:93
#define PL_(String1, String2, n)
Definition fcintl.h:71
#define _(String)
Definition fcintl.h:67
struct civ_game game
Definition game.c:61
struct world wld
Definition game.c:62
struct unit * game_unit_by_number(int id)
Definition game.c:115
struct city * game_city_by_number(int id)
Definition game.c:106
static GtkWidget * spy_sabotage_shell
int action_selection_target_extra(void)
static void incite_response(GtkWidget *w, gint response, gpointer data)
static int action_button_map[BUTTON_COUNT]
static void spy_improvements_callback(GtkTreeSelection *select, gpointer data)
static int actor_unit_id
#define BUTTON_NEW_EXTRA_TGT
static void act_sel_new_extra_tgt_callback(GtkWidget *w, gpointer data)
int action_selection_target_tile(void)
static void create_improvements_list(struct player *pplayer, struct city *pcity, struct action_data *args)
static void act_sel_destroy_callback(GtkWidget *w, gpointer data)
int action_selection_actor_unit(void)
void popup_bribe_stack_dialog(struct unit *actor, struct tile *ptile, int cost, const struct action *paction)
static void spy_advances_response(GtkWidget *w, gint response, gpointer data)
static void tgt_extra_change_callback(GtkWidget *dlg, gint arg)
static GtkWidget * act_sel_dialog
static void spy_steal_popup_shared(GtkWidget *w, gpointer data)
static void diplomat_queue_handle_primary(void)
void action_selection_close(void)
static void spy_improvements_response(GtkWidget *w, gint response, gpointer data)
int action_selection_target_city(void)
#define BUTTON_WAIT
static void action_entry(GtkWidget *shl, action_id act_id, const struct act_prob *act_probs, const char *custom, action_id act_num)
static void spy_steal_esc_popup(GtkWidget *w, gpointer data)
static void spy_steal_popup(GtkWidget *w, gpointer data)
static void act_sel_close_callback(GtkWidget *w, gint response_id, gpointer data)
static void diplomat_queue_handle_secondary(void)
static action_id get_non_targeted_action_id(action_id tgt_action_id)
static void request_action_details_callback(GtkWidget *w, gpointer data)
static bool action_selection_restart
#define BUTTON_NEW_UNIT_TGT
#define BUTTON_COUNT
static struct action_data * act_sel_dialog_data
static void found_city_callback(GtkWidget *w, gpointer data)
static void bribe_stack_response(GtkWidget *w, gint response, gpointer data)
static void act_sel_location_callback(GtkWidget *w, gpointer data)
void action_selection_refresh(struct unit *actor_unit, struct city *target_city, struct unit *target_unit, struct tile *target_tile, struct extra_type *target_extra, const struct act_prob *act_probs)
static struct action_data * act_data(action_id act_id, int actor_id, int target_city_id, int target_unit_id, int target_tile_id, int target_building_id, int target_tech_id, int tgt_extra_id)
static void simple_action_callback(GtkWidget *w, gpointer data)
static void create_advances_list(struct player *pplayer, struct player *pvictim, struct action_data *args)
static bool is_more_user_input_needed
static int target_extra_id
static void act_sel_wait_callback(GtkWidget *w, gpointer data)
static void act_sel_new_unit_tgt_callback(GtkWidget *w, gpointer data)
static void tgt_unit_change_callback(GtkWidget *dlg, gint arg)
#define BUTTON_NOT_THERE
static action_id get_production_targeted_action_id(action_id tgt_action_id)
static bool did_not_decide
#define BUTTON_CANCEL
static GtkWidget * spy_tech_shell
static int target_ids[ATK_COUNT]
static void act_sel_cancel_callback(GtkWidget *w, gpointer data)
static void action_entry_update(GtkWidget *shl, action_id act_id, const struct act_prob *act_probs, const char *custom, action_id act_num)
int action_selection_target_unit(void)
void popup_incite_dialog(struct unit *actor, struct city *pcity, int cost, const struct action *paction)
static const GCallback af_map[ACTION_COUNT]
static void upgrade_callback(GtkWidget *w, gpointer data)
static void bribe_unit_response(GtkWidget *w, gint response, gpointer data)
static void spy_advances_callback(GtkTreeSelection *select, gpointer data)
#define BUTTON_LOCATION
GtkWidget * choice_dialog_start(GtkWindow *parent, const gchar *name, const gchar *text)
void choice_dialog_end(GtkWidget *dshell)
int choice_dialog_get_number_of_buttons(GtkWidget *cd)
void choice_dialog_button_set_tooltip(GtkWidget *cd, int number, const char *tool_tip)
void choice_dialog_button_move_to_the_end(GtkWidget *cd, const int number)
void choice_dialog_set_hide(GtkWidget *dshell, gboolean setting)
void choice_dialog_add(GtkWidget *dshell, const gchar *label, GCallback handler, gpointer data, bool meta, const gchar *tool_tip)
void choice_dialog_button_set_label(GtkWidget *cd, int number, const char *label)
void choice_dialog_button_set_sensitive(GtkWidget *cd, int button, gboolean state)
struct city * owner
Definition citydlg.c:226
void popup_upgrade_dialog(struct unit_list *punits)
Definition dialogs.c:1435
GtkWidget * toplevel
Definition gui_main.c:126
void gtk_tree_view_focus(GtkTreeView *view)
Definition gui_stuff.c:236
void setup_dialog(GtkWidget *shell, GtkWidget *parent)
Definition gui_stuff.c:287
static struct gui_dialog * shell
Definition messagedlg.c:39
const char * tooltip
Definition repodlgs.c:1315
const char * title
Definition repodlgs.c:1314
bool select_tgt_extra(struct unit *actor, struct tile *ptile, bv_extras potential_tgt_extras, struct extra_type *suggested_tgt_extra, const gchar *dlg_title, const gchar *actor_label, const gchar *tgt_label, const gchar *do_label, GCallback do_callback)
bool select_tgt_unit(struct unit *actor, struct tile *ptile, struct unit_list *potential_tgt_units, struct unit *suggested_tgt_unit, const gchar *dlg_title, const gchar *actor_label, const gchar *tgt_label, const gchar *do_label, GCallback do_callback)
void choice_dialog_destroy(GtkWidget *dlg)
struct impr_type * improvement_by_number(const Impr_type_id id)
Impr_type_id improvement_number(const struct impr_type *pimprove)
#define B_LAST
Definition improvement.h:42
#define fc_assert_msg(condition, message,...)
Definition log.h:182
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_action(condition, action)
Definition log.h:188
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:471
void center_tile_mapcanvas(const struct tile *ptile)
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_malloc(sz)
Definition mem.h:34
const char * nation_adjective_for_player(const struct player *pplayer)
Definition nation.c:169
#define REQEST_PLAYER_INITIATED
Definition packets.h:63
int dsend_packet_unit_get_actions(struct connection *pc, int actor_unit_id, int target_unit_id, int target_tile_id, int target_extra_id, int request_kind)
int dsend_packet_city_name_suggestion_req(struct connection *pc, int unit_id)
const char * research_advance_name_translation(const struct research *presearch, Tech_type_id tech)
Definition research.c:273
struct research * research_get(const struct player *pplayer)
Definition research.c:128
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:619
bool research_invention_gettable(const struct research *presearch, const Tech_type_id tech, bool allow_holes)
Definition research.c:693
#define ARRAY_SIZE(x)
Definition shared.h:85
int target_building_id
action_id act_id
Definition city.h:317
struct packet_game_info info
Definition game.h:89
struct connection conn
Definition client_main.h:96
struct player * playing
Definition connection.h:151
bool tech_steal_allow_holes
Definition tile.h:50
int index
Definition tile.h:51
struct unit_list * units
Definition tile.h:58
Definition unit.h:139
int id
Definition unit.h:146
int index
Definition unit.h:197
struct unit::@84::@86 client
struct act_prob * act_prob_cache
Definition unit.h:230
int homecity
Definition unit.h:147
struct civ_map map
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
struct advance * valid_advance_by_number(const Tech_type_id id)
Definition tech.c:176
#define advance_index_iterate_end
Definition tech.h:244
#define A_FIRST
Definition tech.h:44
#define A_UNSET
Definition tech.h:48
#define advance_index_iterate(_start, _index)
Definition tech.h:240
const char * get_act_sel_action_custom_text(struct action *paction, const struct act_prob prob, const struct unit *actor_unit, const struct city *target_city)
Definition text.c:1763
const char * act_sel_action_tool_tip(const struct action *paction, const struct act_prob prob)
Definition text.c:1868
#define tile_index(_pt_)
Definition tile.h:89
static const bv_extras * tile_extras(const struct tile *ptile)
Definition tile.h:125
#define TILE_INDEX_NONE
Definition tile.h:48
#define unit_tile(_pu)
Definition unit.h:406
#define unit_owner(_pu)
Definition unit.h:405
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
bool utype_can_remove_extra(const struct unit_type *putype, const struct extra_type *pextra)
Definition unittype.c:245
const char * unit_name_translation(const struct unit *punit)
Definition unittype.c:1573
bool utype_can_create_extra(const struct unit_type *putype, const struct extra_type *pextra)
Definition unittype.c:221