Freeciv-3.4
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 "specialist.h"
31#include "unit.h"
32#include "unitlist.h"
33
34/* client */
35#include "dialogs_g.h"
36#include "chatline.h"
37#include "choice_dialog.h"
38#include "client_main.h"
39#include "climisc.h"
40#include "connectdlg_common.h"
41#include "control.h"
42#include "gui_main.h"
43#include "gui_stuff.h"
44#include "mapview.h"
45#include "packhand.h"
46#include "text.h"
47
48/* client/gui-gtk-5.0 */
49#include "citydlg.h"
50#include "dialogs.h"
51#include "unitselextradlg.h"
52#include "unitselunitdlg.h"
53#include "wldlg.h"
54
55/* Locations for non action enabler controlled buttons. */
56#define BUTTON_NEW_UNIT_TGT (ACTION_COUNT + 1)
57#define BUTTON_NEW_EXTRA_TGT (BUTTON_NEW_UNIT_TGT + 1)
58#define BUTTON_LOCATION (BUTTON_NEW_EXTRA_TGT + 1)
59#define BUTTON_WAIT (BUTTON_LOCATION + 1)
60#define BUTTON_CANCEL (BUTTON_WAIT + 1)
61#define BUTTON_COUNT (BUTTON_CANCEL + 1)
62
63#define BUTTON_NOT_THERE -1
64
65
68
69static int actor_unit_id;
71static int target_extra_id;
73static bool did_not_decide = FALSE;
75
77
79
80/* A structure to hold parameters for actions inside the GUI instead of
81 * storing the needed data in a global variable. */
82struct action_data {
84 int actor_unit_id;
92};
93
94/* TODO: Maybe this should be in the dialog itself? */
96
97#define FC_TYPE_ACTION_ROW (fc_action_row_get_type())
98
100
108
113
115
116/**********************************************************************/
120{
122
123 free(row->name);
124 row->name = nullptr;
125
127}
128
129/**********************************************************************/
132static void
139
140/**********************************************************************/
143static void
145{
146 self->name = nullptr;
147}
148
149/**********************************************************************/
153{
154 FcActionRow *result;
155
156 result = g_object_new(FC_TYPE_ACTION_ROW, nullptr);
157
158 return result;
159}
160
161/**********************************************************************/
166 int actor_id,
167 int target_city_id,
168 int target_unit_id,
169 int target_tile_id,
171 int target_tech_id,
173 int tgt_extra_id)
174{
175 struct action_data *data = fc_malloc(sizeof(*data));
176
177 data->act_id = act_id;
178 data->actor_unit_id = actor_id;
186
187 return data;
188}
189
190/**********************************************************************/
195{
197 /* The client isn't waiting for information for any unanswered follow
198 * up questions. */
199
200 struct unit *actor_unit;
201
203 /* The action selection dialog wasn't closed because the actor unit
204 * was lost. */
205
206 /* The probabilities didn't just disappear, right? */
209
211 }
212
214 /* The action selection dialog was closed but only so it can be
215 * redrawn with fresh data. */
216
218 } else {
219 /* The action selection process is over, at least for now. */
221 }
222
223 if (did_not_decide) {
224 /* The action selection dialog was closed but the player didn't
225 * decide what the unit should do. */
226
227 /* Reset so the next action selection dialog does the right thing. */
229 } else {
230 /* An action, or no action at all, was selected. */
233 }
234 }
235}
236
237/**********************************************************************/
242{
243 /* Stop waiting. Move on to the next queued unit. */
246}
247
248/**********************************************************************/
255{
256 /* Stop assuming the answer to a follow up question will arrive. */
258}
259
260/**********************************************************************/
265{
266 /* Don't add an action mapping here unless the non targeted version is
267 * selectable in the targeted version's target selection dialog. */
268 switch ((enum gen_action)tgt_action_id) {
277 default:
278 /* No non targeted version found. */
279 return ACTION_NONE;
280 }
281}
282
283/**********************************************************************/
288{
289 /* Don't add an action mapping here unless the non targeted version is
290 * selectable in the targeted version's target selection dialog. */
291 switch ((enum gen_action)tgt_action_id) {
298 default:
299 /* No non targeted version found. */
300 return ACTION_NONE;
301 }
302}
303
304/**********************************************************************/
309{
310 int actor_id, target_id, sub_target;
311 struct action *paction;
312
313 struct action_data *args = act_sel_dialog_data;
314
315 bool failed = FALSE;
316
317 /* Data */
318 args->act_id = GPOINTER_TO_INT(data);
320
321 /* Actor */
323 actor_id = args->actor_unit_id;
324 if (NULL == game_unit_by_number(actor_id)) {
325 /* Probably dead. */
326 failed = TRUE;
327 }
328
329 /* Target */
330 target_id = IDENTITY_NUMBER_ZERO;
332 case ATK_CITY:
333 target_id = args->target_city_id;
334 if (NULL == game_city_by_number(target_id)) {
335 /* Probably destroyed. */
336 failed = TRUE;
337 }
338 break;
339 case ATK_UNIT:
340 target_id = args->target_unit_id;
341 if (NULL == game_unit_by_number(target_id)) {
342 /* Probably dead. */
343 failed = TRUE;
344 }
345 break;
346 case ATK_STACK:
347 case ATK_TILE:
348 case ATK_EXTRAS:
349 target_id = args->target_tile_id;
350 if (NULL == index_to_tile(&(wld.map), target_id)) {
351 /* TODO: Should this be possible at all? If not: add assertion. */
352 failed = TRUE;
353 }
354 break;
355 case ATK_SELF:
356 target_id = IDENTITY_NUMBER_ZERO;
357 break;
358 case ATK_COUNT:
360 failed = TRUE;
361 }
362
363 /* Sub target. */
364 sub_target = NO_TARGET;
365 if (paction->target_complexity != ACT_TGT_COMPL_SIMPLE) {
367 case ASTK_BUILDING:
368 sub_target = args->target_building_id;
369 if (NULL == improvement_by_number(sub_target)) {
370 /* Did the ruleset change? */
371 failed = TRUE;
372 }
373 break;
374 case ASTK_TECH:
375 sub_target = args->target_tech_id;
376 if (NULL == valid_advance_by_number(sub_target)) {
377 /* Did the ruleset change? */
378 failed = TRUE;
379 }
380 break;
381 case ASTK_EXTRA:
383 /* TODO: Validate if the extra is there? */
384 sub_target = args->target_extra_id;
385 if (NULL == extra_by_number(sub_target)) {
386 /* Did the ruleset change? */
387 failed = TRUE;
388 }
389 break;
390 case ASTK_SPECIALIST:
391 sub_target = args->target_specialist_id;
392 if (nullptr == specialist_by_number(sub_target)) {
393 /* Did the ruleset change? */
394 failed = TRUE;
395 }
396 break;
397 case ASTK_NONE:
398 case ASTK_COUNT:
399 /* Shouldn't happen. */
401 failed = TRUE;
402 break;
403 }
404 }
405
406 /* Send request. */
407 if (!failed) {
408 request_do_action(paction->id, actor_id, target_id, sub_target, "");
409 }
410
411 /* Clean up. */
413 /* No follow up questions. */
415 FC_FREE(args);
416}
417
418/**********************************************************************/
423{
424 int actor_id, target_id;
425 struct action *paction;
426
427 struct action_data *args = act_sel_dialog_data;
428
429 bool failed = FALSE;
430
431 /* Data */
432 args->act_id = GPOINTER_TO_INT(data);
434
435 /* Actor */
437 actor_id = args->actor_unit_id;
438 if (NULL == game_unit_by_number(actor_id)) {
439 /* Probably dead. */
440 failed = TRUE;
441 }
442
443 /* Target */
444 target_id = IDENTITY_NUMBER_ZERO;
446 case ATK_CITY:
447 target_id = args->target_city_id;
448 if (NULL == game_city_by_number(target_id)) {
449 /* Probably destroyed. */
450 failed = TRUE;
451 }
452 break;
453 case ATK_UNIT:
454 target_id = args->target_unit_id;
455 if (NULL == game_unit_by_number(target_id)) {
456 /* Probably dead. */
457 failed = TRUE;
458 }
459 break;
460 case ATK_STACK:
461 case ATK_TILE:
462 case ATK_EXTRAS:
463 target_id = args->target_tile_id;
464 if (NULL == index_to_tile(&(wld.map), target_id)) {
465 /* TODO: Should this be possible at all? If not: add assertion. */
466 failed = TRUE;
467 }
468 break;
469 case ATK_SELF:
470 target_id = IDENTITY_NUMBER_ZERO;
471 break;
472 case ATK_COUNT:
474 failed = TRUE;
475 }
476
477 /* Send request. */
478 if (!failed) {
479 request_action_details(paction->id, actor_id, target_id);
480 }
481
482 /* Wait for the server's reply before moving on to the next unit that
483 * needs to know what action to take. */
485
486 /* Clean up. */
488 /* No client side follow up questions. */
490 FC_FREE(args);
491}
492
493/**********************************************************************/
506
507/**********************************************************************/
511{
512 struct unit *punit;
513 struct action_data *args = act_sel_dialog_data;
514
517 struct unit_list *as_list;
518
523 }
524
526 free(args);
527}
528
529/**********************************************************************/
532static void bribe_unit_response(GtkWidget *w, gint response, gpointer data)
533{
534 struct action_data *args = (struct action_data *)data;
535
536 if (response == GTK_RESPONSE_YES) {
538 args->target_unit_id, 0, "");
539 }
540
542 free(args);
543
544 /* The user have answered the follow up question. Move on. */
546}
547
548/**********************************************************************/
551static void bribe_stack_response(GtkWidget *w, gint response, gpointer data)
552{
553 struct action_data *args = (struct action_data *)data;
554
555 if (response == GTK_RESPONSE_YES) {
557 args->target_tile_id, 0, "");
558 }
559
561 free(args);
562
563 /* The user have answered the follow up question. Move on. */
565}
566
567/**********************************************************************/
570void popup_bribe_unit_dialog(struct unit *actor, struct unit *punit, int cost,
571 const struct action *paction)
572{
574 char buf[1024];
575
576 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
577 "Treasury contains %d gold.",
578 client_player()->economic.gold),
579 client_player()->economic.gold);
580
581 if (cost <= client_player()->economic.gold) {
584 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
585 PL_("Bribe unit for %d gold?\n%s",
586 "Bribe unit for %d gold?\n%s", cost), cost, buf);
587 gtk_window_set_title(GTK_WINDOW(shell), _("Bribe Enemy Unit"));
589 } else {
592 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
593 PL_("Bribing the unit costs %d gold.\n%s",
594 "Bribing the unit costs %d gold.\n%s", cost), cost, buf);
595 gtk_window_set_title(GTK_WINDOW(shell), _("Traitors Demand Too Much!"));
597 }
599
601 act_data(paction->id, actor->id,
602 0, punit->id, 0,
603 0, 0, 0, 0));
604}
605
606/**********************************************************************/
609void popup_bribe_stack_dialog(struct unit *actor, struct tile *ptile, int cost,
610 const struct action *paction)
611{
613 char buf[1024];
614
615 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
616 "Treasury contains %d gold.",
617 client_player()->economic.gold),
618 client_player()->economic.gold);
619
620 if (cost <= client_player()->economic.gold) {
623 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
624 PL_("Bribe unit stack for %d gold?\n%s",
625 "Bribe unit stack for %d gold?\n%s", cost), cost, buf);
626 gtk_window_set_title(GTK_WINDOW(shell), _("Bribe Enemy Stack"));
628 } else {
631 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
632 PL_("Bribing units costs %d gold.\n%s",
633 "Bribing units costs %d gold.\n%s", cost), cost, buf);
634 gtk_window_set_title(GTK_WINDOW(shell), _("Traitors Demand Too Much!"));
636 }
638
640 act_data(paction->id, actor->id,
641 0, 0, ptile->index,
642 0, 0, 0, 0));
643}
644
645/**********************************************************************/
648static void spy_advances_response(GtkWidget *w, gint response,
649 gpointer data)
650{
651 struct action_data *args = (struct action_data *)data;
652
653 if (response == GTK_RESPONSE_ACCEPT && args->target_tech_id > 0) {
656 if (args->target_tech_id == A_UNSET) {
657 /* This is the untargeted version. */
659 args->actor_unit_id, args->target_city_id,
660 args->target_tech_id, "");
661 } else {
662 /* This is the targeted version. */
664 args->actor_unit_id, args->target_city_id,
665 args->target_tech_id, "");
666 }
667 }
668 }
669
672 free(data);
673
674 /* The user have answered the follow up question. Move on. */
676}
677
678/**********************************************************************/
702
703/**********************************************************************/
717
718/**********************************************************************/
727
728/**********************************************************************/
731static void create_advances_list(struct player *pplayer,
732 struct player *pvictim,
733 struct action_data *args)
734{
735 GtkWidget *frame, *label, *vgrid;
736 GListStore *store;
740 GtkSingleSelection *selection;
741
743
744 spy_tech_shell = gtk_dialog_new_with_buttons(_("Steal Technology"),
745 NULL, 0,
746 _("_Cancel"), GTK_RESPONSE_CANCEL,
747 _("_Steal"), GTK_RESPONSE_ACCEPT,
748 NULL);
750
753
754 frame = gtk_frame_new(_("Select Advance to Steal"));
756
762
764
765 selection = gtk_single_selection_new(G_LIST_MODEL(store));
767
770 nullptr);
772 nullptr);
773
776
778 "use-underline", TRUE,
779 "mnemonic-widget", list,
780 "label", _("_Advances:"),
781 "xalign", 0.0,
782 "yalign", 0.5,
783 NULL);
784 gtk_grid_attach(GTK_GRID(vgrid), label, 0, 0, 1, 1);
785
786 gtk_grid_attach(GTK_GRID(vgrid), list, 0, 1, 1, 1);
787
788 /* Now populate the list */
789 if (pvictim) { /* You don't want to know what lag can do -- Syela */
790 const struct research *presearch = research_get(pplayer);
791 const struct research *vresearch = research_get(pvictim);
792 GValue value = { 0, };
793
800
802 row->id = i;
803
804 g_list_store_append(store, row);
806 }
808
812
813 {
814 struct astring str = ASTRING_INIT;
815
816 /* TRANS: %s is a unit name, e.g., Spy */
817 astr_set(&str, _("At %s's Discretion"),
820
821 row->name = fc_strdup(astr_str(&str));
822
823 astr_free(&str);
824 }
825
826 row->id = A_UNSET;
827
828 g_list_store_append(store, row);
830 }
831 }
832
835
837 TRUE);
838
839 g_signal_connect(selection, "selection-changed",
843
844 args->target_tech_id = 0;
845}
846
847/**********************************************************************/
850static void spy_improvements_response(GtkWidget *w, gint response, gpointer data)
851{
852 struct action_data *args = (struct action_data *)data;
853
854 if (response == GTK_RESPONSE_ACCEPT && args->target_building_id > -2) {
857 if (args->target_building_id == B_LAST) {
858 /* This is the untargeted version. */
860 args->actor_unit_id,
861 args->target_city_id,
862 args->target_building_id, "");
863 } else if (args->target_building_id == -1) {
864 /* This is the city production version. */
866 args->actor_unit_id,
867 args->target_city_id,
868 args->target_building_id, "");
869 } else {
870 /* This is the targeted version. */
872 args->actor_unit_id,
873 args->target_city_id,
874 args->target_building_id, "");
875 }
876 }
877 }
878
881 free(args);
882
883 /* The user have answered the follow up question. Move on. */
885}
886
887/**********************************************************************/
911
912/**********************************************************************/
915static void create_improvements_list(struct player *pplayer,
916 struct city *pcity,
917 struct action_data *args)
918{
919 GtkWidget *frame, *label, *vgrid;
920 GListStore *store;
924 GtkSingleSelection *selection;
925
927
928 spy_sabotage_shell = gtk_dialog_new_with_buttons(_("Sabotage Improvements"),
929 NULL, 0,
930 _("_Cancel"), GTK_RESPONSE_CANCEL,
931 _("_Sabotage"), GTK_RESPONSE_ACCEPT,
932 NULL);
934
937
938 frame = gtk_frame_new(_("Select Improvement to Sabotage"));
940
946
948
949 selection = gtk_single_selection_new(G_LIST_MODEL(store));
951
954 nullptr);
956 nullptr);
957
958 column = gtk_column_view_column_new(_("Improvement"), factory);
960
962 "use-underline", TRUE,
963 "mnemonic-widget", list,
964 "label", _("_Improvements:"),
965 "xalign", 0.0,
966 "yalign", 0.5,
967 NULL);
968 gtk_grid_attach(GTK_GRID(vgrid), label, 0, 0, 1, 1);
969 gtk_grid_attach(GTK_GRID(vgrid), list, 0, 1, 1, 1);
970
971 /* Now populate the list */
974 args->act_id)])) {
976
977 row->name = fc_strdup(_("City Production"));
978 row->id = -1;
979
980 g_list_store_append(store, row);
982 }
983
984 city_built_iterate(pcity, pimprove) {
985 if (pimprove->sabotage > 0) {
987
989 row->id = improvement_number(pimprove);
990
991 g_list_store_append(store, row);
993 }
995
998 struct astring str = ASTRING_INIT;
1000
1001 /* TRANS: %s is a unit name, e.g., Spy */
1002 astr_set(&str, _("At %s's Discretion"),
1004
1005 row->name = fc_strdup(astr_str(&str));
1006 row->id = B_LAST;
1007
1008 g_list_store_append(store, row);
1010
1011 astr_free(&str);
1012 }
1013
1016
1018 TRUE);
1019
1020 g_signal_connect(selection, "selection-changed",
1024
1025 args->target_building_id = -2;
1026}
1027
1028/**********************************************************************/
1032{
1033 struct action_data *args = (struct action_data *)data;
1034
1035 args->act_id = args->act_id;
1036
1038 struct player *pvictim = NULL;
1039
1040 if (pvcity) {
1042 }
1043
1044/* It is concievable that pvcity will not be found, because something
1045 has happened to the city during latency. Therefore we must initialize
1046 pvictim to NULL and account for !pvictim in create_advances_list. -- Syela */
1047
1048 /* FIXME: Don't discard the second tech choice dialog. */
1049 if (!spy_tech_shell) {
1052 } else {
1053 free(args);
1054 }
1055
1056 /* Wait for the player's reply before moving on to the next unit that
1057 * needs to know what action to take. */
1059
1061}
1062
1063/**********************************************************************/
1072
1073/**********************************************************************/
1082
1083/**********************************************************************/
1088 const struct action *paction)
1089{
1090 /* FIXME: Don't discard the second target choice dialog. */
1091 if (!spy_sabotage_shell) {
1093 act_data(paction->id,
1094 actor->id, pcity->id, 0, 0,
1095 0, 0, 0, 0));
1097 }
1098}
1099
1100/**********************************************************************/
1103static void incite_response(GtkWidget *w, gint response, gpointer data)
1104{
1105 struct action_data *args = (struct action_data *)data;
1106
1107 if (response == GTK_RESPONSE_YES) {
1109 args->target_city_id, 0, "");
1110 }
1111
1113 free(args);
1114
1115 /* The user have answered the follow up question. Move on. */
1117}
1118
1119/**********************************************************************/
1122void popup_incite_dialog(struct unit *actor, struct city *pcity, int cost,
1123 const struct action *paction)
1124{
1126 char buf[1024];
1127
1128 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
1129 "Treasury contains %d gold.",
1130 client_player()->economic.gold),
1131 client_player()->economic.gold);
1132
1136 _("You can't incite a revolt in %s."),
1138 gtk_window_set_title(GTK_WINDOW(shell), _("City can't be incited!"));
1140 } else if (cost <= client_player()->economic.gold) {
1143 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
1144 PL_("Incite a revolt for %d gold?\n%s",
1145 "Incite a revolt for %d gold?\n%s", cost), cost, buf);
1146 gtk_window_set_title(GTK_WINDOW(shell), _("Incite a Revolt!"));
1148 } else {
1150 0,
1152 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
1153 PL_("Inciting a revolt costs %d gold.\n%s",
1154 "Inciting a revolt costs %d gold.\n%s", cost), cost, buf);
1155 gtk_window_set_title(GTK_WINDOW(shell), _("Traitors Demand Too Much!"));
1157 }
1159
1161 act_data(paction->id, actor->id,
1162 pcity->id, 0, 0,
1163 0, 0, 0, 0));
1164}
1165
1166/**********************************************************************/
1170{
1171 int au_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(dlg), "actor"));
1172
1173 if (arg == GTK_RESPONSE_YES) {
1175
1176 if (actor != NULL) {
1178 "target"));
1180 struct tile *tgt_tile = g_object_get_data(G_OBJECT(dlg), "tile");
1181
1182 if (tgt_unit == NULL) {
1183 /* Make the action dialog pop up again. */
1185 actor->id,
1186 /* Let the server choose the target
1187 * unit. */
1189 tgt_tile->index,
1192 } else {
1194 actor->id,
1195 tgt_id,
1196 tgt_tile->index,
1199 }
1200 }
1201 } else {
1202 /* Dialog canceled. This ends the action selection process. */
1204 }
1205
1207}
1208
1209/**********************************************************************/
1213{
1214 struct action_data *args = act_sel_dialog_data;
1215
1216 struct unit *punit;
1217 struct unit *tunit;
1218 struct tile *ptile;
1219
1221 && (ptile = index_to_tile(&(wld.map), args->target_tile_id))
1222 && (tunit = game_unit_by_number(args->target_unit_id))) {
1223 select_tgt_unit(punit, ptile, ptile->units, tunit,
1224 _("Target unit selection"),
1225 _("Looking for target unit:"),
1226 _("Units at tile:"),
1227 _("Select"),
1229 }
1230
1234 free(args);
1235}
1236
1237/**********************************************************************/
1241{
1242 int au_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(dlg), "actor"));
1243
1244 if (arg == GTK_RESPONSE_YES) {
1246
1247 if (actor != NULL) {
1249 "target"));
1251 struct tile *tgt_tile = g_object_get_data(G_OBJECT(dlg), "tile");
1252
1253 if (tgt_extra == NULL) {
1254 /* Make the action dialog pop up again. */
1256 actor->id,
1258 tgt_tile->index,
1259 /* Let the server choose the target
1260 * extra. */
1263 } else {
1265 actor->id,
1267 tgt_tile->index,
1268 tgt_id,
1270 }
1271 }
1272 } else {
1273 /* Dialog canceled. This ends the action selection process. */
1275 }
1276
1278}
1279
1280/**********************************************************************/
1284{
1285 struct action_data *args = act_sel_dialog_data;
1286
1287 struct unit *act_unit;
1288 struct extra_type *tgt_extra;
1289 struct tile *tgt_tile;
1290
1292 && (tgt_tile = index_to_tile(&(wld.map), args->target_tile_id))
1295
1296 /* Start with the extras at the tile */
1298
1300 if (BV_ISSET(potential_targets, extra_number(pextra))) {
1301 /* This extra is at the tile. Can anything be done to it? */
1303 pextra)) {
1305 }
1306 } else {
1307 /* This extra isn't at the tile yet. Can it be created? */
1309 pextra)) {
1311 }
1312 }
1314
1316 /* TRANS: GTK action selection dialog extra target
1317 * selection dialog title. */
1318 _("Target extra selection"),
1319 /* TRANS: GTK action selection dialog extra target
1320 * selection dialog actor unit label. */
1321 _("Looking for target extra:"),
1322 /* TRANS: GTK action selection dialog extra target
1323 * selection dialog extra list label. */
1324 _("Extra targets:"),
1325 _("Select"),
1327 }
1328
1332 free(args);
1333}
1334
1335/**********************************************************************/
1339{
1340 struct action_data *args = act_sel_dialog_data;
1341
1342 struct unit *punit;
1343
1344 if ((punit = game_unit_by_number(args->actor_unit_id))) {
1346 }
1347}
1348
1349/**********************************************************************/
1353{
1354 struct action_data *args = act_sel_dialog_data;
1355
1356 key_unit_wait();
1357
1358 /* The dialog was destroyed when key_unit_wait() resulted in
1359 * action_selection_close() being called. */
1360
1361 free(args);
1362}
1363
1364/**********************************************************************/
1372
1373/**********************************************************************/
1381
1382/**********************************************************************/
1390
1391/* Mapping from an action to the function to call when its button is
1392 * pushed. */
1394 /* Unit acting against a city target. */
1405
1406 /* Unit acting against a unit target. */
1408
1409 /* Unit acting against all units at a tile. */
1411
1412 /* Unit acting against a tile. */
1414
1415 /* Unit acting with no target except itself. */
1416 /* No special callback functions needed for any self targeted actions. */
1417};
1418
1419/**********************************************************************/
1424 const struct act_prob *act_probs,
1425 const char *custom,
1427{
1428 const gchar *label;
1429 const gchar *tooltip;
1430 GCallback cb;
1431
1432 if (af_map[act_id] == NULL) {
1433 /* No special call back function needed for this action. */
1435 } else {
1436 /* Special action specific callback function specified. */
1437 cb = af_map[act_id];
1438 }
1439
1440 /* Don't show disabled actions. */
1442 return;
1443 }
1444
1445 label = action_prepare_ui_name(act_id, "_",
1447 custom);
1448
1450 act_probs[act_id]);
1451
1454 FALSE, tooltip);
1455}
1456
1457/**********************************************************************/
1462 const struct act_prob *act_probs,
1463 const char *custom,
1465{
1466 const gchar *label;
1467 const gchar *tooltip;
1468
1469 /* An action that just became impossible has its button disabled.
1470 * An action that became possible again must be re-enabled. */
1474
1475 /* The probability may have changed. */
1476 label = action_prepare_ui_name(act_id, "_",
1478
1480 act_probs[act_id]);
1481
1484 label);
1487 tooltip);
1488}
1489
1490/**********************************************************************/
1495 struct city *target_city,
1496 struct unit *target_unit,
1497 struct tile *target_tile,
1498 struct extra_type *target_extra,
1499 const struct act_prob *act_probs)
1500{
1501 GtkWidget *shl;
1502 struct astring title = ASTRING_INIT, text = ASTRING_INIT;
1503 struct city *actor_homecity;
1504
1505 int button_id;
1506
1508 act_data(ACTION_ANY, /* Not decided yet */
1509 actor_unit->id,
1513 /* No target_building or target_tech supplied. (Dec 2019) */
1514 B_LAST, A_UNSET, -1,
1516
1517 /* Could be caused by the server failing to reply to a request for more
1518 * information or a bug in the client code. */
1520 "Diplomat queue problem. Is another diplomat window open?");
1521
1522 /* No extra input is required as no action has been chosen yet. */
1524
1525 /* No buttons are added yet. */
1526 for (button_id = 0; button_id < BUTTON_COUNT; button_id++) {
1528 }
1529
1531
1535 target_city->id :
1538 target_unit->id :
1551 EXTRA_NONE;
1552
1553 astr_set(&title,
1554 /* TRANS: %s is a unit name, e.g., Spy */
1555 _("Choose Your %s's Strategy"),
1557
1558 if (target_city && actor_homecity) {
1559 astr_set(&text,
1560 _("Your %s from %s reaches the city of %s.\nWhat now?"),
1564 } else if (target_city) {
1565 astr_set(&text,
1566 _("Your %s has arrived at %s.\nWhat is your command?"),
1569 } else if (target_unit) {
1570 astr_set(&text,
1571 /* TRANS: Your Spy is ready to act against Roman Freight. */
1572 _("Your %s is ready to act against %s %s."),
1576 } else {
1578 "No target specified.");
1579 astr_set(&text,
1580 /* TRANS: %s is a unit name, e.g., Diplomat, Spy */
1581 _("Your %s is waiting for your command."),
1583 }
1584
1586 astr_str(&text));
1587
1588 /* Unit acting against a city */
1589
1590 action_iterate(act) {
1595 act_probs[act],
1596 actor_unit,
1597 target_city),
1598 act);
1599 }
1601
1602 /* Unit acting against another unit */
1603
1604 action_iterate(act) {
1609 act_probs[act],
1610 actor_unit,
1611 target_city),
1612 act);
1613 }
1615
1616 /* Unit acting against all units at a tile */
1617
1618 action_iterate(act) {
1623 act_probs[act],
1624 actor_unit,
1625 target_city),
1626 act);
1627 }
1629
1630 /* Unit acting against a tile */
1631
1632 action_iterate(act) {
1637 act_probs[act],
1638 actor_unit,
1639 target_city),
1640 act);
1641 }
1643
1644 /* Unit acting against a tile's extras */
1645
1646 action_iterate(act) {
1651 act_probs[act],
1652 actor_unit,
1653 target_city),
1654 act);
1655 }
1657
1658 /* Unit acting against itself. */
1659
1660 action_iterate(act) {
1665 act_probs[act],
1666 actor_unit,
1667 target_city),
1668 act);
1669 }
1671
1672 if (target_unit != NULL
1673 && unit_list_size(target_tile->units) > 1) {
1676 choice_dialog_add(shl, _("Change unit target"),
1679 }
1680
1681 if (target_extra != NULL) {
1684 choice_dialog_add(shl, _("Change extra target"),
1687 }
1688
1691 choice_dialog_add(shl, _("Show Location"),
1694 TRUE, NULL);
1695
1698 choice_dialog_add(shl, _("_Wait"),
1701 TRUE, NULL);
1702
1705 choice_dialog_add(shl, _("_Cancel"),
1708 FALSE, NULL);
1709
1711
1713
1715 g_signal_connect(shl, "destroy",
1717 g_signal_connect(shl, "close-request",
1720
1721 /* Give follow up questions access to action probabilities. */
1723 action_iterate(act) {
1726
1727 astr_free(&title);
1728 astr_free(&text);
1729}
1730
1731/**********************************************************************/
1737{
1738 if (act_sel_dialog == NULL) {
1739 return IDENTITY_NUMBER_ZERO;
1740 }
1741 return actor_unit_id;
1742}
1743
1744/**********************************************************************/
1751{
1752 if (act_sel_dialog == NULL) {
1753 return IDENTITY_NUMBER_ZERO;
1754 }
1755 return target_ids[ATK_CITY];
1756}
1757
1758/**********************************************************************/
1765{
1766 if (act_sel_dialog == NULL) {
1767 return IDENTITY_NUMBER_ZERO;
1768 }
1769
1770 return target_ids[ATK_UNIT];
1771}
1772
1773/**********************************************************************/
1780{
1781 if (act_sel_dialog == NULL) {
1782 return TILE_INDEX_NONE;
1783 }
1784
1785 return target_ids[ATK_TILE];
1786}
1787
1788/**********************************************************************/
1795{
1796 if (act_sel_dialog == NULL) {
1797 return EXTRA_NONE;
1798 }
1799
1800 return target_extra_id;
1801}
1802
1803/**********************************************************************/
1807 struct city *target_city,
1808 struct unit *target_unit,
1809 struct tile *target_tile,
1810 struct extra_type *target_extra,
1811 const struct act_prob *act_probs)
1812{
1813 if (act_sel_dialog == NULL) {
1815 "The action selection dialog should have been open");
1816 return;
1817 }
1818
1821 "The action selection dialog is for another actor unit.");
1822 return;
1823 }
1824
1825 /* A new target may have appeared. */
1826 if (target_city) {
1828 }
1829 if (target_unit) {
1831 }
1832 if (target_tile) {
1834 }
1835 /* No target_building or target_tech supplied. (Dec 2019) */
1836 if (target_extra) {
1838 }
1839
1840 action_iterate(act) {
1841 const char *custom;
1842
1843 if (action_id_get_actor_kind(act) != AAK_UNIT) {
1844 /* Not relevant. */
1845 continue;
1846 }
1847
1849 act_probs[act],
1850 actor_unit,
1851 target_city);
1852
1853 if (BUTTON_NOT_THERE == action_button_map[act]) {
1854 /* Add the button (unless its probability is 0). */
1856 } else {
1857 /* Update the existing button. */
1859 }
1861
1862 /* DO NOT change the action_button_map[] for any button to reflect its
1863 * new position. A button keeps its choice dialog internal name when its
1864 * position changes. A button's id number is therefore based on when
1865 * it was added, not on its current position. */
1866
1868 /* Move the wait button below the recently added button. */
1871 }
1872
1874 /* Move the cancel button below the recently added button. */
1877 }
1878
1880}
1881
1882/**********************************************************************/
1886{
1887 if (act_sel_dialog != NULL) {
1890 }
1891}
const char * action_prepare_ui_name(action_id act_id, const char *mnemonic, const struct act_prob prob, const char *custom)
Definition actions.c:1333
enum action_actor_kind action_get_actor_kind(const struct action *paction)
Definition actions.c:1119
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:5306
enum action_sub_target_kind action_get_sub_target_kind(const struct action *paction)
Definition actions.c:1140
enum action_target_kind action_get_target_kind(const struct action *paction)
Definition actions.c:1129
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:94
#define city_owner(_pcity_)
Definition city.h:563
#define city_built_iterate(_pcity, _p)
Definition city.h:835
#define city_built_iterate_end
Definition city.h:841
static struct ai_type * self
Definition classicai.c:46
struct civclient client
#define client_player()
void client_unit_init_act_prob_cache(struct unit *punit)
Definition climisc.c:1259
static struct fc_sockaddr_list * list
Definition clinet.c:102
char * incite_cost
Definition comments.c:76
void action_selection_no_longer_in_progress(const int old_actor_id)
Definition control.c:1051
void request_do_action(action_id action, int actor_id, int target_id, int sub_tgt, const char *name)
Definition control.c:1730
void request_action_details(action_id action, int actor_id, int target_id)
Definition control.c:1798
void action_decision_clear_want(const int old_actor_id)
Definition control.c:1080
void key_unit_wait(void)
Definition control.c:3542
void action_selection_next_in_focus(const int old_actor_id)
Definition control.c:1092
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: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 popup_sabotage_dialog
Definition dialogs_g.h:77
struct unit struct city struct unit * target_unit
Definition dialogs_g.h:56
popup_action_selection
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 * actor
Definition dialogs_g.h:73
struct unit * actor_unit
Definition dialogs_g.h:55
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:69
struct unit struct city struct unit struct tile * target_tile
Definition dialogs_g.h:57
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:74
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:78
struct unit struct city * target_city
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 int cost
Definition dialogs_g.h:74
struct unit struct city struct unit struct tile struct extra_type * target_extra
Definition dialogs_g.h:57
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:62
struct world wld
Definition game.c:63
struct unit * game_unit_by_number(int id)
Definition game.c:116
struct city * game_city_by_number(int id)
Definition game.c:107
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 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 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 target_specialist_id, int tgt_extra_id)
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)
void popup_upgrade_dialog(struct unit_list *punits)
Definition dialogs.c:1435
GtkWidget * toplevel
Definition gui_main.c:126
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)
static void fc_action_row_class_init(FcActionRowClass *klass)
static void fc_action_row_init(FcActionRow *self)
static void fc_action_row_finalize(GObject *gobject)
#define FC_TYPE_ACTION_ROW
static void action_factory_bind(GtkSignalListItemFactory *self, GtkListItem *list_item, gpointer user_data)
static FcActionRow * fc_action_row_new(void)
static void action_factory_setup(GtkSignalListItemFactory *self, GtkListItem *list_item, gpointer user_data)
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
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)
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_strdup(str)
Definition mem.h:43
#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
const char * research_advance_name_translation(const struct research *presearch, Tech_type_id tech)
Definition research.c:276
struct research * research_get(const struct player *pplayer)
Definition research.c:130
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:622
bool research_invention_gettable(const struct research *presearch, const Tech_type_id tech, bool allow_holes)
Definition research.c:696
#define ARRAY_SIZE(x)
Definition shared.h:85
struct specialist * specialist_by_number(const Specialist_type_id id)
Definition specialist.c:110
GObjectClass parent_class
GObject parent_instance
int target_building_id
int target_specialist_id
action_id act_id
char name[MAX_LEN_NAME]
Definition ai.h:51
Definition city.h:318
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:140
int id
Definition unit.h:147
int index
Definition unit.h:198
struct unit::@84::@86 client
struct act_prob * act_prob_cache
Definition unit.h:231
int homecity
Definition unit.h:148
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:246
#define A_FIRST
Definition tech.h:44
#define A_UNSET
Definition tech.h:48
#define advance_index_iterate(_start, _index)
Definition tech.h:242
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:1842
#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:407
#define unit_owner(_pu)
Definition unit.h:406
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:126
bool utype_can_remove_extra(const struct unit_type *putype, const struct extra_type *pextra)
Definition unittype.c:266
const char * unit_name_translation(const struct unit *punit)
Definition unittype.c:1595
bool utype_can_create_extra(const struct unit_type *putype, const struct extra_type *pextra)
Definition unittype.c:242