Freeciv-3.1
Loading...
Searching...
No Matches
actiontools.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996-2015 - 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/* utility */
19#include "rand.h"
20
21/* common */
22#include "actions.h"
23
24/* server */
25#include "aiiface.h"
26#include "notify.h"
27#include "plrhand.h"
28#include "unithand.h"
29#include "unittools.h"
30
31#include "actiontools.h"
32
33typedef void (*action_notify)(struct player *,
34 const struct action *,
35 struct player *,
36 struct player *,
37 const struct tile *,
38 const char *);
39
40/**********************************************************************/
43static void action_success_actor_consume(struct action *paction,
44 int actor_id, struct unit *actor)
45{
46 if (unit_is_alive(actor_id)
48 if (action_has_result(paction, ACTRES_DISBAND_UNIT)
49 || action_has_result(paction, ACTRES_DISBAND_UNIT_RECOVER)) {
50 wipe_unit(actor, ULR_DISBANDED, NULL);
51 } else if (action_has_result(paction, ACTRES_NUKE)
52 || action_has_result(paction, ACTRES_NUKE_UNITS)) {
53 wipe_unit(actor, ULR_DETONATED, NULL);
54 } else if (action_has_result(paction, ACTRES_ATTACK)) {
55 wipe_unit(actor, ULR_MISSILE, NULL);
56 } else {
57 wipe_unit(actor, ULR_USED, NULL);
58 }
59 }
60}
61
62/**********************************************************************/
65static void action_success_pay_mp(struct action *paction,
66 int actor_id, struct unit *actor)
67{
68 if (unit_is_alive(actor_id)) {
69 int spent_mp = unit_pays_mp_for_action(paction, actor);
70 actor->moves_left = MAX(0, actor->moves_left - spent_mp);
71 send_unit_info(NULL, actor);
72 }
73}
74
75/**********************************************************************/
79 int target_id, struct unit *target)
80{
81 if (unit_is_alive(target_id)) {
82 int spent_mp = get_target_bonus_effects(
83 NULL,
84 &(const struct req_context) {
85 .player = unit_owner(target),
86 .city = unit_tile(target) ? tile_city(unit_tile(target)) : NULL,
87 .tile = unit_tile(target),
88 .unit = target,
89 .unittype = unit_type_get(target),
90 .action = paction,
91 },
92 NULL,
93 EFT_ACTION_SUCCESS_TARGET_MOVE_COST);
94
95 target->moves_left = MAX(0, target->moves_left - spent_mp);
96 send_unit_info(NULL, target);
97 }
98}
99
100/**********************************************************************/
104 int actor_id, struct unit *actor)
105{
106 action_success_actor_consume(paction, actor_id, actor);
107 action_success_pay_mp(paction, actor_id, actor);
108}
109
110/**********************************************************************/
113static void action_give_casus_belli(struct player *offender,
114 struct player *victim_player,
115 const bool int_outrage)
116{
117 if (int_outrage) {
118 /* This action is seen as a reason for any other player, no matter who
119 * the victim was, to declare war on the actor. It could be used to
120 * label certain actions atrocities in rule sets where international
121 * outrage over an action fits the setting. */
122
123 players_iterate(oplayer) {
124 if (oplayer != offender) {
125 player_diplstate_get(oplayer, offender)->has_reason_to_cancel = 2;
127 }
129 } else if (victim_player && offender != victim_player) {
130 /* If an unclaimed tile is nuked there is no victim to give casus
131 * belli. If an actor nukes their own tile, they are more than willing
132 * to forgive themself. */
133
134 /* Give the victim player a casus belli. */
135 player_diplstate_get(victim_player, offender)->has_reason_to_cancel =
136 2;
137 player_update_last_war_action(victim_player);
138 }
140}
141
142/**********************************************************************/
148static void action_consequence_common(const struct action *paction,
149 struct player *offender,
150 const struct unit_type *offender_utype,
151 struct player *victim_player,
152 const struct tile *victim_tile,
153 const char *victim_link,
154 const action_notify notify_actor,
155 const action_notify notify_victim,
156 const action_notify notify_global,
157 const enum effect_type eft)
158{
159 enum casus_belli_range cbr;
160
161 cbr = casus_belli_range_for(offender, offender_utype, victim_player,
162 eft, paction, victim_tile);
163
164 if (cbr >= CBR_VICTIM_ONLY) {
165 /* In this situation the specified action provides a casus belli
166 * against the actor. */
167
168 /* International outrage: This isn't just between the offender and the
169 * victim. */
170 const bool int_outrage = (cbr == CBR_INTERNATIONAL_OUTRAGE);
171
172 /* Notify the involved players by sending them a message. */
173 notify_actor(offender, paction, offender, victim_player,
174 victim_tile, victim_link);
175 notify_victim(victim_player, paction, offender, victim_player,
176 victim_tile, victim_link);
177
178 if (int_outrage) {
179 /* Every other player gets a casus belli against the actor. Tell each
180 * players about it. */
181 players_iterate(oplayer) {
182 notify_global(oplayer, paction, offender,
183 victim_player, victim_tile, victim_link);
185 }
186
187 /* Give casus belli. */
188 action_give_casus_belli(offender, victim_player, int_outrage);
189
190 /* Notify players controlled by the built in AI. */
191 call_incident(INCIDENT_ACTION, cbr, paction, offender, victim_player);
192
193 /* Update the clients. */
194 send_player_all_c(offender, NULL);
195
196 if (victim_player != NULL && victim_player != offender) {
197 /* The actor player was just sent. */
198 /* An action against an ownerless tile is victimless. */
199 send_player_all_c(victim_player, NULL);
200 }
201 }
202}
203
204/**********************************************************************/
208static void notify_actor_caught(struct player *receiver,
209 const struct action *paction,
210 struct player *offender,
211 struct player *victim_player,
212 const struct tile *victim_tile,
213 const char *victim_link)
214{
215 if (!victim_player || offender == victim_player) {
216 /* There is no victim or the actor did this to themself. */
217 return;
218 }
219
220 /* Custom message based on action type. */
221 switch (action_get_target_kind(paction)) {
222 case ATK_CITY:
223 notify_player(receiver, victim_tile,
224 E_DIPLOMATIC_INCIDENT, ftc_server,
225 /* TRANS: Suitcase Nuke ... San Francisco */
226 _("You have caused an diplomatic incident getting caught"
227 " trying to do %s to %s."),
229 victim_link);
230 break;
231 case ATK_UNIT:
232 case ATK_UNITS:
233 notify_player(receiver, victim_tile,
234 E_DIPLOMATIC_INCIDENT, ftc_server,
235 /* TRANS: Bribe Enemy Unit ... American ... Partisan */
236 _("You have caused an diplomatic incident getting caught"
237 " trying to do %s to %s %s."),
239 nation_adjective_for_player(victim_player),
240 victim_link);
241 break;
242 case ATK_TILE:
243 case ATK_EXTRAS:
244 notify_player(receiver, victim_tile,
245 E_DIPLOMATIC_INCIDENT, ftc_server,
246 /* TRANS: Explode Nuclear ... (54, 26) */
247 _("You have caused an diplomatic incident getting caught"
248 " trying to do %s at %s."),
250 victim_link);
251 break;
252 case ATK_SELF:
253 /* Special actor notice not needed. Actor is victim. */
254 break;
255 case ATK_COUNT:
256 fc_assert(ATK_COUNT != ATK_COUNT);
257 break;
258 }
259}
260
261/**********************************************************************/
265static void notify_victim_caught(struct player *receiver,
266 const struct action *paction,
267 struct player *offender,
268 struct player *victim_player,
269 const struct tile *victim_tile,
270 const char *victim_link)
271{
272 if (!victim_player || offender == victim_player) {
273 /* There is no victim or the actor did this to themself. */
274 return;
275 }
276
277 /* Custom message based on action type. */
278 switch (action_get_target_kind(paction)) {
279 case ATK_CITY:
280 notify_player(receiver, victim_tile,
281 E_DIPLOMATIC_INCIDENT, ftc_server,
282 /* TRANS: Europeans ... Suitcase Nuke ... San Francisco */
283 _("The %s have caused an diplomatic incident getting caught"
284 " trying to do %s to %s."),
285 nation_plural_for_player(offender),
287 victim_link);
288 break;
289 case ATK_UNIT:
290 case ATK_UNITS:
291 notify_player(receiver, victim_tile,
292 E_DIPLOMATIC_INCIDENT, ftc_server,
293 /* TRANS: Europeans ... Bribe Enemy Unit ... Partisan */
294 _("The %s have caused an diplomatic incident getting caught"
295 " trying to do %s to your %s."),
296 nation_plural_for_player(offender),
298 victim_link);
299 break;
300 case ATK_TILE:
301 case ATK_EXTRAS:
302 notify_player(receiver, victim_tile,
303 E_DIPLOMATIC_INCIDENT, ftc_server,
304 /* TRANS: Europeans ... Explode Nuclear ... (54, 26) */
305 _("The %s have caused an diplomatic incident getting caught"
306 " trying to do %s at %s."),
307 nation_plural_for_player(offender),
309 victim_link);
310 break;
311 case ATK_SELF:
312 /* Special victim notice not needed. Actor is victim. */
313 break;
314 case ATK_COUNT:
315 fc_assert(ATK_COUNT != ATK_COUNT);
316 break;
317 }
318}
319
320/**********************************************************************/
324static void notify_global_caught(struct player *receiver,
325 const struct action *paction,
326 struct player *offender,
327 struct player *victim_player,
328 const struct tile *victim_tile,
329 const char *victim_link)
330{
331 if (receiver == offender) {
332 notify_player(receiver, victim_tile,
333 E_DIPLOMATIC_INCIDENT, ftc_server,
334 /* TRANS: Suitcase Nuke */
335 _("Getting caught while trying to do %s gives "
336 "everyone a casus belli against you."),
337 action_name_translation(paction));
338 } else if (receiver == victim_player) {
339 notify_player(receiver, victim_tile,
340 E_DIPLOMATIC_INCIDENT, ftc_server,
341 /* TRANS: Suitcase Nuke ... Europeans */
342 _("Getting caught while trying to do %s to you gives "
343 "everyone a casus belli against the %s."),
345 nation_plural_for_player(offender));
346 } else if (victim_player == NULL) {
347 notify_player(receiver, victim_tile,
348 E_DIPLOMATIC_INCIDENT, ftc_server,
349 /* TRANS: Europeans ... Suitcase Nuke */
350 _("You now have a casus belli against the %s. "
351 "They got caught trying to do %s."),
352 nation_plural_for_player(offender),
353 action_name_translation(paction));
354 } else {
355 notify_player(receiver, victim_tile,
356 E_DIPLOMATIC_INCIDENT, ftc_server,
357 /* TRANS: Europeans ... Suitcase Nuke ... Americans */
358 _("You now have a casus belli against the %s. "
359 "They got caught trying to do %s to the %s."),
360 nation_plural_for_player(offender),
362 nation_plural_for_player(victim_player));
363 }
364}
365
366/**********************************************************************/
372void action_consequence_caught(const struct action *paction,
373 struct player *offender,
374 const struct unit_type *offender_utype,
375 struct player *victim_player,
376 const struct tile *victim_tile,
377 const char *victim_link)
378{
379 action_consequence_common(paction, offender, offender_utype,
380 victim_player, victim_tile, victim_link,
384 EFT_CASUS_BELLI_CAUGHT);
385}
386
387/**********************************************************************/
391static void notify_actor_success(struct player *receiver,
392 const struct action *paction,
393 struct player *offender,
394 struct player *victim_player,
395 const struct tile *victim_tile,
396 const char *victim_link)
397{
398 if (!victim_player || offender == victim_player) {
399 /* There is no victim or the actor did this to themself. */
400 return;
401 }
402
403 /* Custom message based on action type. */
404 switch (action_get_target_kind(paction)) {
405 case ATK_CITY:
406 notify_player(receiver, victim_tile,
407 E_DIPLOMATIC_INCIDENT, ftc_server,
408 /* TRANS: Suitcase Nuke ... San Francisco */
409 _("You have caused an diplomatic incident doing %s to %s."),
411 victim_link);
412 break;
413 case ATK_UNIT:
414 case ATK_UNITS:
415 notify_player(receiver, victim_tile,
416 E_DIPLOMATIC_INCIDENT, ftc_server,
417 /* TRAND: Bribe Enemy Unit ... American ... Partisan */
418 _("You have caused an diplomatic incident doing %s to %s %s."),
420 nation_adjective_for_player(victim_player),
421 victim_link);
422 break;
423 case ATK_TILE:
424 case ATK_EXTRAS:
425 notify_player(receiver, victim_tile,
426 E_DIPLOMATIC_INCIDENT, ftc_server,
427 /* TRANS: Explode Nuclear ... (54, 26) */
428 _("You have caused an diplomatic incident doing %s at %s."),
430 victim_link);
431 break;
432 case ATK_SELF:
433 /* Special actor notice not needed. Actor is victim. */
434 break;
435 case ATK_COUNT:
436 fc_assert(ATK_COUNT != ATK_COUNT);
437 break;
438 }
439}
440
441/**********************************************************************/
445static void notify_victim_success(struct player *receiver,
446 const struct action *paction,
447 struct player *offender,
448 struct player *victim_player,
449 const struct tile *victim_tile,
450 const char *victim_link)
451{
452 if (!victim_player || offender == victim_player) {
453 /* There is no victim or the actor did this to themself. */
454 return;
455 }
456
457 /* Custom message based on action type. */
458 switch (action_get_target_kind(paction)) {
459 case ATK_CITY:
460 notify_player(receiver, victim_tile,
461 E_DIPLOMATIC_INCIDENT, ftc_server,
462 /* TRANS: Europeans ... Suitcase Nuke ... San Francisco */
463 _("The %s have caused an diplomatic incident doing %s to %s."),
464 nation_plural_for_player(offender),
466 victim_link);
467 break;
468 case ATK_UNIT:
469 case ATK_UNITS:
470 notify_player(receiver, victim_tile,
471 E_DIPLOMATIC_INCIDENT, ftc_server,
472 /* TRANS: Europeans ... Bribe Enemy Unit ... Partisan */
473 _("The %s have caused an diplomatic incident doing "
474 "%s to your %s."),
475 nation_plural_for_player(offender),
477 victim_link);
478 break;
479 case ATK_TILE:
480 case ATK_EXTRAS:
481 notify_player(receiver, victim_tile,
482 E_DIPLOMATIC_INCIDENT, ftc_server,
483 /* TRANS: Europeans ... Explode Nuclear ... (54, 26) */
484 _("The %s have caused an diplomatic incident doing %s at %s."),
485 nation_plural_for_player(offender),
487 victim_link);
488 break;
489 case ATK_SELF:
490 /* Special victim notice not needed. Actor is victim. */
491 break;
492 case ATK_COUNT:
493 fc_assert(ATK_COUNT != ATK_COUNT);
494 break;
495 }
496}
497
498/**********************************************************************/
502static void notify_global_success(struct player *receiver,
503 const struct action *paction,
504 struct player *offender,
505 struct player *victim_player,
506 const struct tile *victim_tile,
507 const char *victim_link)
508{
509 if (receiver == offender) {
510 notify_player(receiver, victim_tile,
511 E_DIPLOMATIC_INCIDENT, ftc_server,
512 /* TRANS: Suitcase Nuke */
513 _("Doing %s gives everyone a casus belli against you."),
514 action_name_translation(paction));
515 } else if (receiver == victim_player) {
516 notify_player(receiver, victim_tile,
517 E_DIPLOMATIC_INCIDENT, ftc_server,
518 /* TRANS: Suitcase Nuke ... Europeans */
519 _("Doing %s to you gives everyone a casus belli against "
520 "the %s."),
522 nation_plural_for_player(offender));
523 } else if (victim_player == NULL) {
524 notify_player(receiver, victim_tile,
525 E_DIPLOMATIC_INCIDENT, ftc_server,
526 /* TRANS: Europeans ... Suitcase Nuke */
527 _("You now have a casus belli against the %s. "
528 "They did %s."),
529 nation_plural_for_player(offender),
530 action_name_translation(paction));
531 } else {
532 notify_player(receiver, victim_tile,
533 E_DIPLOMATIC_INCIDENT, ftc_server,
534 /* TRANS: Europeans ... Suitcase Nuke ... Americans */
535 _("You now have a casus belli against the %s. "
536 "They did %s to the %s."),
537 nation_plural_for_player(offender),
539 nation_plural_for_player(victim_player));
540 }
541}
542
543/**********************************************************************/
549void action_consequence_success(const struct action *paction,
550 struct player *offender,
551 const struct unit_type *offender_utype,
552 struct player *victim_player,
553 const struct tile *victim_tile,
554 const char *victim_link)
555{
556 action_consequence_common(paction, offender, offender_utype,
557 victim_player, victim_tile, victim_link,
561 EFT_CASUS_BELLI_SUCCESS);
562}
563
564/**************************************************************************
565 Take care of any consequences (like casus belli) of successfully
566 completing the given action.
567
568 victim_player can be NULL
569**************************************************************************/
570void action_consequence_complete(const struct action *paction,
571 struct player *offender,
572 const struct unit_type *offender_utype,
573 struct player *victim_player,
574 const struct tile *victim_tile,
575 const char *victim_link)
576{
577 action_consequence_common(paction, offender, offender_utype,
578 victim_player, victim_tile, victim_link,
582 EFT_CASUS_BELLI_COMPLETE);
583}
584
585/**********************************************************************/
597static bool may_unit_act_vs_city(struct unit *actor, struct city *target,
598 bool accept_all_actions)
599{
600 const struct civ_map *nmap = &(wld.map);
601
602 if (actor == NULL || target == NULL) {
603 /* Can't do any actions if actor or target are missing. */
604 return FALSE;
605 }
606
607 action_iterate(act) {
608 if (!(action_id_get_actor_kind(act) == AAK_UNIT
609 && action_id_get_target_kind(act) == ATK_CITY)) {
610 /* Not a relevant action. */
611 continue;
612 }
613
614 if (action_id_is_rare_pop_up(act) && !accept_all_actions) {
615 /* Not relevant since not accepted here. */
616 continue;
617 }
618
619 if (action_prob_possible(action_prob_vs_city(nmap, actor, act, target))) {
620 /* The actor unit may be able to do this action to the target
621 * city. */
622 return TRUE;
623 }
625
626 return FALSE;
627}
628
629/**********************************************************************/
639 bool accept_all_actions)
640{
641 struct city *target = tile_city(target_tile);
642
643 if (target && may_unit_act_vs_city(actor, target, accept_all_actions)) {
644 /* It may be possible to act against this city. */
645 return target;
646 }
647
648 return NULL;
649}
650
651/**********************************************************************/
663static bool may_unit_act_vs_unit(struct unit *actor, struct unit *target,
664 bool accept_all_actions)
665{
666 const struct civ_map *nmap = &(wld.map);
667
668 if (actor == NULL || target == NULL) {
669 /* Can't do any actions if actor or target are missing. */
670 return FALSE;
671 }
672
673 action_iterate(act) {
674 if (!(action_id_get_actor_kind(act) == AAK_UNIT
675 && action_id_get_target_kind(act) == ATK_UNIT)) {
676 /* Not a relevant action. */
677 continue;
678 }
679
680 if (action_id_is_rare_pop_up(act) && !accept_all_actions) {
681 /* Not relevant since not accepted here. */
682 continue;
683 }
684
685 if (action_prob_possible(action_prob_vs_unit(nmap, actor, act, target))) {
686 /* The actor unit may be able to do this action to the target
687 * unit. */
688 return TRUE;
689 }
691
692 return FALSE;
693}
694
695/**********************************************************************/
706 bool accept_all_actions)
707{
708 unit_list_iterate(target_tile->units, target) {
709 if (may_unit_act_vs_unit(actor, target, accept_all_actions)) {
710 return target;
711 }
713
714 return NULL;
715}
716
717/**********************************************************************/
732 struct tile *target,
733 const struct extra_type *target_extra,
734 bool accept_all_actions)
735{
736 const struct civ_map *nmap = &(wld.map);
737
738 if (actor == NULL || target == NULL) {
739 /* Can't do any actions if actor or target are missing. */
740 return NULL;
741 }
742
743 action_iterate(act) {
744 struct act_prob prob;
745
746 if (action_id_get_actor_kind(act) != AAK_UNIT) {
747 /* Not a relevant action. */
748 continue;
749 }
750
751 if (action_id_is_rare_pop_up(act) && !accept_all_actions) {
752 /* Not relevant since not accepted here. */
753 continue;
754 }
755
756 switch (action_id_get_target_kind(act)) {
757 case ATK_TILE:
758 prob = action_prob_vs_tile(nmap, actor, act, target, target_extra);
759 break;
760 case ATK_EXTRAS:
761 prob = action_prob_vs_extras(nmap, actor, act, target, target_extra);
762 break;
763 case ATK_UNITS:
764 prob = action_prob_vs_units(nmap, actor, act, target);
765 break;
766 case ATK_CITY:
767 case ATK_UNIT:
768 case ATK_SELF:
769 /* Target not specified by tile. */
770 continue;
771 case ATK_COUNT:
772 /* Invalid target kind */
773 fc_assert(action_id_get_target_kind(act) != ATK_COUNT);
774 continue;
775 }
776
777 if (action_prob_possible(prob)) {
778 /* The actor unit may be able to do this action to the target
779 * tile. */
780 return target;
781 }
783
784 return NULL;
785}
786
787/**********************************************************************/
799static bool may_unit_act_vs_tile_extra(const struct unit *actor,
800 const struct tile *tgt_tile,
801 const struct extra_type *tgt_extra,
802 bool accept_all_actions)
803{
804 const struct civ_map *nmap = &(wld.map);
805
806 if (actor == NULL || tgt_tile == NULL || tgt_extra == NULL) {
807 /* Can't do any actions if actor or target are missing. */
808 return FALSE;
809 }
810
811 action_iterate(act) {
812 if (!(action_id_get_actor_kind(act) == AAK_UNIT
813 && (action_id_get_target_kind(act) == ATK_TILE
814 || action_id_get_target_kind(act) == ATK_EXTRAS)
816 /* Not a relevant action. */
817 continue;
818 }
819
820 if (action_id_is_rare_pop_up(act) && !accept_all_actions) {
821 /* Not relevant since not accepted here. */
822 continue;
823 }
824
825 switch (action_id_get_target_kind(act)) {
826 case ATK_TILE:
828 tgt_tile, tgt_extra))) {
829 /* The actor unit may be able to do this action to the target
830 * extra. */
831 return TRUE;
832 }
833 break;
834 case ATK_EXTRAS:
836 tgt_tile,
837 tgt_extra))) {
838 /* The actor unit may be able to do this action to the target
839 * extra. */
840 return TRUE;
841 }
842 break;
843 case ATK_CITY:
844 case ATK_UNIT:
845 case ATK_UNITS:
846 case ATK_SELF:
847 /* Not supported. */
848 break;
849 case ATK_COUNT:
850 fc_assert(action_id_get_target_kind(act) != ATK_COUNT);
851 break;
852 }
854
855 return FALSE;
856}
857
858/**********************************************************************/
871 const struct tile *target_tile,
872 bool accept_all_actions)
873{
876 accept_all_actions)) {
877 return target;
878 }
880
881 return NULL;
882}
883
884/**********************************************************************/
887int action_sub_target_id_for_action(const struct action *paction,
888 struct unit *actor_unit)
889{
890 const struct tile *tgt_tile = unit_tile(actor_unit);
891 const struct civ_map *nmap = &(wld.map);
892
893 fc_assert_ret_val(paction->target_complexity == ACT_TGT_COMPL_FLEXIBLE,
894 NO_TARGET);
895
896 switch (action_get_sub_target_kind(paction)) {
897 case ASTK_NONE:
898 /* Should not be reached */
899 fc_assert_ret_val(action_get_sub_target_kind(paction) != ASTK_NONE,
900 NO_TARGET);
901 break;
902 case ASTK_BUILDING:
903 /* Implement if a building sub targeted action becomes flexible */
904 fc_assert_ret_val(paction->target_complexity == ACT_TGT_COMPL_FLEXIBLE,
905 NO_TARGET);
906 break;
907 case ASTK_TECH:
908 /* Implement if a tech sub targeted action becomes flexible */
909 fc_assert_ret_val(paction->target_complexity == ACT_TGT_COMPL_FLEXIBLE,
910 NO_TARGET);
911 break;
912 case ASTK_EXTRA:
913 case ASTK_EXTRA_NOT_THERE:
914 if (action_has_result(paction, ACTRES_PILLAGE)) {
915 /* Special treatment for "Pillage" */
916 struct extra_type *pextra = NULL;
917 enum unit_activity activity = actres_get_activity(paction->result);
918
920
921 if (pextra != NULL) {
922 return extra_number(pextra);
923 }
924 }
927 tgt_tile, tgt_extra))) {
928 /* The actor unit may be able to do this action to the target
929 * extra. */
930 return extra_number(tgt_extra);
931 }
933 break;
934 case ASTK_COUNT:
935 /* Should not exist. */
936 fc_assert_ret_val(action_get_sub_target_kind(paction) != ASTK_COUNT,
937 NO_TARGET);
938 break;
939 }
940
941 return NO_TARGET;
942}
943
944/**********************************************************************/
949const struct action_auto_perf *
950action_auto_perf_unit_sel(const enum action_auto_perf_cause cause,
951 const struct unit *actor,
952 const struct player *other_player,
953 const struct output_type *eval_output,
954 const struct action *eval_action)
955{
956 const struct req_context actor_ctxt = {
958 .tile = unit_tile(actor),
959 .unit = actor,
960 .unittype = unit_type_get(actor),
961 .output = eval_output,
962 .action = eval_action,
963 };
964
965 action_auto_perf_by_cause_iterate(cause, autoperformer) {
966 if (are_reqs_active(&actor_ctxt, other_player,
967 &autoperformer->reqs, RPT_CERTAIN)) {
968 /* Select this action auto performer. */
969 return autoperformer;
970 }
972
973 /* Can't even try to force an action. */
974 return NULL;
975}
976
977#define action_auto_perf_acquire_targets(_target_extra_) \
978 tgt_city = (target_city ? target_city \
979 : action_tgt_city(actor, unit_tile(actor), \
980 TRUE)); \
981 tgt_tile = (target_tile ? target_tile \
982 : action_tgt_tile(actor, unit_tile(actor), \
983 _target_extra_, \
984 TRUE)); \
985 tgt_unit = (target_unit ? target_unit \
986 : action_tgt_unit(actor, unit_tile(actor), \
987 TRUE));
988
989/**********************************************************************/
997const struct action *
998action_auto_perf_unit_do(const enum action_auto_perf_cause cause,
999 struct unit *actor,
1000 const struct player *other_player,
1001 const struct output_type *eval_output,
1002 const struct action *eval_action,
1003 const struct tile *target_tile,
1004 const struct city *target_city,
1005 const struct unit *target_unit,
1006 const struct extra_type *target_extra)
1007{
1008 int actor_id;
1009
1010 const struct city *tgt_city;
1011 const struct tile *tgt_tile;
1012 const struct unit *tgt_unit;
1013 const struct civ_map *nmap = &(wld.map);
1014
1015 const struct action_auto_perf *autoperf
1016 = action_auto_perf_unit_sel(cause, actor, other_player,
1017 eval_output, eval_action);
1018
1019 if (!autoperf) {
1020 /* No matching Action Auto Performer. */
1021 return NULL;
1022 }
1023
1024 actor_id = actor->id;
1025
1026 /* Acquire the targets. */
1028
1029 action_auto_perf_actions_iterate(autoperf, act) {
1030 if (action_id_get_actor_kind(act) == AAK_UNIT) {
1031 /* This action can be done by units. */
1032
1033#define perform_action_to(act, actor, tgtid, tgt_extra) \
1034 if (unit_perform_action(unit_owner(actor), \
1035 actor->id, tgtid, tgt_extra, \
1036 NULL, act, ACT_REQ_RULES)) { \
1037 return action_by_number(act); \
1038 }
1039
1040 switch (action_id_get_target_kind(act)) {
1041 case ATK_UNITS:
1042 if (tgt_tile
1043 && is_action_enabled_unit_on_units(nmap, act, actor, tgt_tile)) {
1044 perform_action_to(act, actor, tgt_tile->index, EXTRA_NONE);
1045 }
1046 break;
1047 case ATK_TILE:
1048 if (tgt_tile
1050 tgt_tile, target_extra)) {
1051 perform_action_to(act, actor, tgt_tile->index,
1053 }
1054 break;
1055 case ATK_EXTRAS:
1056 if (tgt_tile
1058 tgt_tile, target_extra)) {
1059 perform_action_to(act, actor, tgt_tile->index,
1061 }
1062 break;
1063 case ATK_CITY:
1064 if (tgt_city
1065 && is_action_enabled_unit_on_city(nmap, act, actor, tgt_city)) {
1066 perform_action_to(act, actor, tgt_city->id, EXTRA_NONE)
1067 }
1068 break;
1069 case ATK_UNIT:
1070 if (tgt_unit
1071 && is_action_enabled_unit_on_unit(nmap, act, actor, tgt_unit)) {
1072 perform_action_to(act, actor, tgt_unit->id, EXTRA_NONE);
1073 }
1074 break;
1075 case ATK_SELF:
1076 if (actor
1077 && is_action_enabled_unit_on_self(nmap, act, actor)) {
1079 }
1080 break;
1081 case ATK_COUNT:
1082 fc_assert(action_id_get_target_kind(act) != ATK_COUNT);
1083 }
1084
1085 if (!unit_is_alive(actor_id)) {
1086 /* The unit is gone. Maybe it was killed in Lua? */
1087 return NULL;
1088 }
1089 }
1091
1092 return NULL;
1093}
1094
1095/**********************************************************************/
1099struct act_prob
1100action_auto_perf_unit_prob(const enum action_auto_perf_cause cause,
1101 struct unit *actor,
1102 const struct player *other_player,
1103 const struct output_type *eval_output,
1104 const struct action *eval_action,
1105 const struct tile *target_tile,
1106 const struct city *target_city,
1107 const struct unit *target_unit,
1108 const struct extra_type *target_extra)
1109{
1110 struct act_prob out;
1111
1112 const struct city *tgt_city;
1113 const struct tile *tgt_tile;
1114 const struct unit *tgt_unit;
1115 const struct civ_map *nmap = &(wld.map);
1116
1117 const struct action_auto_perf *autoperf
1118 = action_auto_perf_unit_sel(cause, actor, other_player,
1119 eval_output, eval_action);
1120
1121 if (!autoperf) {
1122 /* No matching Action Auto Performer. */
1123 return ACTPROB_IMPOSSIBLE;
1124 }
1125
1126 out = ACTPROB_IMPOSSIBLE;
1127
1128 /* Acquire the targets. */
1130
1131 action_auto_perf_actions_iterate(autoperf, act) {
1132 struct act_prob current = ACTPROB_IMPOSSIBLE;
1133
1134 if (action_id_get_actor_kind(act) == AAK_UNIT) {
1135 /* This action can be done by units. */
1136
1137 switch (action_id_get_target_kind(act)) {
1138 case ATK_UNITS:
1139 if (tgt_tile
1140 && is_action_enabled_unit_on_units(nmap, act, actor, tgt_tile)) {
1141 current = action_prob_vs_units(nmap, actor, act, tgt_tile);
1142 }
1143 break;
1144 case ATK_TILE:
1145 if (tgt_tile
1147 tgt_tile, target_extra)) {
1148 current = action_prob_vs_tile(nmap, actor, act, tgt_tile, target_extra);
1149 }
1150 break;
1151 case ATK_EXTRAS:
1152 if (tgt_tile
1154 tgt_tile, target_extra)) {
1155 current = action_prob_vs_extras(nmap, actor, act,
1156 tgt_tile, target_extra);
1157 }
1158 break;
1159 case ATK_CITY:
1160 if (tgt_city
1161 && is_action_enabled_unit_on_city(nmap, act, actor, tgt_city)) {
1162 current = action_prob_vs_city(nmap, actor, act, tgt_city);
1163 }
1164 break;
1165 case ATK_UNIT:
1166 if (tgt_unit
1167 && is_action_enabled_unit_on_unit(nmap, act, actor, tgt_unit)) {
1168 current = action_prob_vs_unit(nmap, actor, act, tgt_unit);
1169 }
1170 break;
1171 case ATK_SELF:
1172 if (actor
1173 && is_action_enabled_unit_on_self(nmap, act, actor)) {
1174 current = action_prob_self(nmap, actor, act);
1175 }
1176 break;
1177 case ATK_COUNT:
1178 fc_assert(action_id_get_target_kind(act) != ATK_COUNT);
1179 }
1180 }
1181
1182 out = action_prob_fall_back(&out, &current);
1184
1185 return out;
1186}
1187
1188/************************************************************************/
1192bool action_failed_dice_roll(const struct player *act_player,
1193 const struct unit *act_unit,
1194 const struct city *tgt_city,
1195 const struct player *tgt_player,
1196 const struct action *paction)
1197{
1198 int odds = action_dice_roll_odds(act_player, act_unit,
1199 tgt_city, tgt_player,
1200 paction);
1201
1202 /* Roll the dice. */
1203 return fc_rand (100) >= odds;
1204}
const char * action_name_translation(const struct action *action)
Definition actions.c:1890
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:6703
int action_dice_roll_odds(const struct player *act_player, const struct unit *act_unit, const struct city *tgt_city, const struct player *tgt_player, const struct action *paction)
Definition actions.c:7064
struct act_prob action_prob_vs_tile(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:6224
enum action_sub_target_kind action_get_sub_target_kind(const struct action *paction)
Definition actions.c:1751
bool is_action_enabled_unit_on_tile(const struct civ_map *nmap, const action_id wanted_action, const struct unit *actor_unit, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:4996
bool is_action_enabled_unit_on_units(const struct civ_map *nmap, const action_id wanted_action, const struct unit *actor_unit, const struct tile *target_tile)
Definition actions.c:4920
struct act_prob action_prob_vs_extras(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:6307
enum unit_activity actres_get_activity(enum action_result result)
Definition actions.c:2136
struct act_prob action_prob_self(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id)
Definition actions.c:6377
struct act_prob action_prob_fall_back(const struct act_prob *ap1, const struct act_prob *ap2)
Definition actions.c:6911
bool is_action_enabled_unit_on_city(const struct civ_map *nmap, const action_id wanted_action, const struct unit *actor_unit, const struct city *target_city)
Definition actions.c:4755
struct act_prob action_prob_vs_units(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile)
Definition actions.c:6141
bool is_action_enabled_unit_on_unit(const struct civ_map *nmap, const action_id wanted_action, const struct unit *actor_unit, const struct unit *target_unit)
Definition actions.c:4832
struct act_prob action_prob_vs_city(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id, const struct city *target_city)
Definition actions.c:5870
enum action_target_kind action_get_target_kind(const struct action *paction)
Definition actions.c:1740
bool is_action_enabled_unit_on_self(const struct civ_map *nmap, const action_id wanted_action, const struct unit *actor_unit)
Definition actions.c:5145
bool action_id_is_rare_pop_up(action_id act_id)
Definition actions.c:1820
struct act_prob action_prob_vs_unit(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id, const struct unit *target_unit)
Definition actions.c:5953
bool is_action_enabled_unit_on_extras(const struct civ_map *nmap, const action_id wanted_action, const struct unit *actor_unit, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:5073
#define action_auto_perf_by_cause_iterate(_cause_, _act_perf_)
Definition actions.h:597
#define action_auto_perf_actions_iterate_end
Definition actions.h:609
#define action_auto_perf_by_cause_iterate_end
Definition actions.h:603
#define action_has_result(_act_, _res_)
Definition actions.h:448
#define action_auto_perf_actions_iterate(_autoperf_, _act_id_)
Definition actions.h:606
#define action_iterate_end
Definition actions.h:472
#define action_id_get_actor_kind(act_id)
Definition actions.h:651
#define ACTPROB_IMPOSSIBLE
Definition actions.h:939
#define action_iterate(_act_)
Definition actions.h:467
#define action_id_get_target_kind(act_id)
Definition actions.h:655
#define action_id_has_complex_target(act_id)
Definition actions.h:673
static void notify_actor_success(struct player *receiver, const struct action *paction, struct player *offender, struct player *victim_player, const struct tile *victim_tile, const char *victim_link)
void action_consequence_complete(const struct action *paction, struct player *offender, const struct unit_type *offender_utype, struct player *victim_player, const struct tile *victim_tile, const char *victim_link)
const struct action_auto_perf * action_auto_perf_unit_sel(const enum action_auto_perf_cause cause, const struct unit *actor, const struct player *other_player, const struct output_type *eval_output, const struct action *eval_action)
struct tile * action_tgt_tile(struct unit *actor, struct tile *target, const struct extra_type *target_extra, bool accept_all_actions)
static void notify_victim_success(struct player *receiver, const struct action *paction, struct player *offender, struct player *victim_player, const struct tile *victim_tile, const char *victim_link)
void action_success_target_pay_mp(struct action *paction, int target_id, struct unit *target)
Definition actiontools.c:78
void action_consequence_caught(const struct action *paction, struct player *offender, const struct unit_type *offender_utype, struct player *victim_player, const struct tile *victim_tile, const char *victim_link)
static bool may_unit_act_vs_city(struct unit *actor, struct city *target, bool accept_all_actions)
void(* action_notify)(struct player *, const struct action *, struct player *, struct player *, const struct tile *, const char *)
Definition actiontools.c:33
struct act_prob action_auto_perf_unit_prob(const enum action_auto_perf_cause cause, struct unit *actor, const struct player *other_player, const struct output_type *eval_output, const struct action *eval_action, const struct tile *target_tile, const struct city *target_city, const struct unit *target_unit, const struct extra_type *target_extra)
static void notify_global_success(struct player *receiver, const struct action *paction, struct player *offender, struct player *victim_player, const struct tile *victim_tile, const char *victim_link)
static void notify_victim_caught(struct player *receiver, const struct action *paction, struct player *offender, struct player *victim_player, const struct tile *victim_tile, const char *victim_link)
const struct action * action_auto_perf_unit_do(const enum action_auto_perf_cause cause, struct unit *actor, const struct player *other_player, const struct output_type *eval_output, const struct action *eval_action, const struct tile *target_tile, const struct city *target_city, const struct unit *target_unit, const struct extra_type *target_extra)
struct unit * action_tgt_unit(struct unit *actor, struct tile *target_tile, bool accept_all_actions)
void action_consequence_success(const struct action *paction, struct player *offender, const struct unit_type *offender_utype, struct player *victim_player, const struct tile *victim_tile, const char *victim_link)
#define perform_action_to(act, actor, tgtid, tgt_extra)
static void notify_global_caught(struct player *receiver, const struct action *paction, struct player *offender, struct player *victim_player, const struct tile *victim_tile, const char *victim_link)
static void action_success_actor_consume(struct action *paction, int actor_id, struct unit *actor)
Definition actiontools.c:43
static void notify_actor_caught(struct player *receiver, const struct action *paction, struct player *offender, struct player *victim_player, const struct tile *victim_tile, const char *victim_link)
struct city * action_tgt_city(struct unit *actor, struct tile *target_tile, bool accept_all_actions)
static void action_give_casus_belli(struct player *offender, struct player *victim_player, const bool int_outrage)
struct extra_type * action_tgt_tile_extra(const struct unit *actor, const struct tile *target_tile, bool accept_all_actions)
static void action_consequence_common(const struct action *paction, struct player *offender, const struct unit_type *offender_utype, struct player *victim_player, const struct tile *victim_tile, const char *victim_link, const action_notify notify_actor, const action_notify notify_victim, const action_notify notify_global, const enum effect_type eft)
void action_success_actor_price(struct action *paction, int actor_id, struct unit *actor)
static bool may_unit_act_vs_unit(struct unit *actor, struct unit *target, bool accept_all_actions)
bool action_failed_dice_roll(const struct player *act_player, const struct unit *act_unit, const struct city *tgt_city, const struct player *tgt_player, const struct action *paction)
int action_sub_target_id_for_action(const struct action *paction, struct unit *actor_unit)
static void action_success_pay_mp(struct action *paction, int actor_id, struct unit *actor)
Definition actiontools.c:65
#define action_auto_perf_acquire_targets(_target_extra_)
static bool may_unit_act_vs_tile_extra(const struct unit *actor, const struct tile *tgt_tile, const struct extra_type *tgt_extra, bool accept_all_actions)
@ INCIDENT_ACTION
Definition ai.h:46
void call_incident(enum incident_type type, enum casus_belli_range scope, const struct action *paction, struct player *violator, struct player *victim)
Definition aiiface.c:233
struct unit struct city struct unit * target_unit
Definition dialogs_g.h:55
struct unit * actor_unit
Definition dialogs_g.h:54
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit * actor
Definition dialogs_g.h:72
struct unit struct city struct unit struct tile * target_tile
Definition dialogs_g.h:56
struct unit struct city * target_city
Definition dialogs_g.h:55
struct unit struct city struct unit struct tile struct extra_type * target_extra
Definition dialogs_g.h:56
int get_target_bonus_effects(struct effect_list *plist, const struct req_context *context, const struct player *other_player, enum effect_type effect_type)
Definition effects.c:691
int extra_number(const struct extra_type *pextra)
Definition extras.c:153
#define EXTRA_NONE
Definition extras.h:82
#define extra_type_re_active_iterate_end
Definition extras.h:305
#define extra_type_re_active_iterate(_p)
Definition extras.h:301
#define NO_TARGET
Definition fc_types.h:324
@ RPT_CERTAIN
Definition fc_types.h:586
#define _(String)
Definition fcintl.h:67
const struct ft_color ftc_server
struct world wld
Definition game.c:58
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_ret_val(condition, val)
Definition log.h:194
const char * nation_adjective_for_player(const struct player *pplayer)
Definition nation.c:168
const char * nation_plural_for_player(const struct player *pplayer)
Definition nation.c:177
void notify_player(const struct player *pplayer, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Definition notify.c:291
struct player_diplstate * player_diplstate_get(const struct player *plr1, const struct player *plr2)
Definition player.c:317
enum casus_belli_range casus_belli_range_for(const struct player *offender, const struct unit_type *off_ut, const struct player *tgt_plr, const enum effect_type outcome, const struct action *paction, const struct tile *tgt_tile)
Definition player.c:1604
#define players_iterate_end
Definition player.h:535
#define players_iterate(_pplayer)
Definition player.h:530
void send_player_all_c(struct player *src, struct conn_list *dest)
Definition plrhand.c:983
void player_update_last_war_action(struct player *pplayer)
Definition plrhand.c:746
#define fc_rand(_size)
Definition rand.h:34
bool are_reqs_active(const struct req_context *context, const struct player *other_player, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
#define MAX(x, y)
Definition shared.h:54
enum action_auto_perf_cause cause
Definition actions.h:570
action_id id
Definition actions.h:380
enum action_result result
Definition actions.h:382
enum act_tgt_compl target_complexity
Definition actions.h:390
Definition city.h:309
int id
Definition city.h:315
char has_reason_to_cancel
Definition player.h:205
const struct player * player
Definition tile.h:49
int index
Definition tile.h:50
Definition unit.h:138
int moves_left
Definition unit.h:150
int id
Definition unit.h:145
struct civ_map map
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
bool unit_is_alive(int id)
Definition unit.c:2237
int unit_pays_mp_for_action(const struct action *paction, const struct unit *punit)
Definition unit.c:2119
#define unit_tile(_pu)
Definition unit.h:395
#define unit_owner(_pu)
Definition unit.h:394
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33
void send_unit_info(struct conn_list *dest, struct unit *punit)
Definition unittools.c:2794
void wipe_unit(struct unit *punit, enum unit_loss_reason reason, struct player *killer)
Definition unittools.c:2247
void unit_assign_specific_activity_target(struct unit *punit, enum unit_activity *activity, struct extra_type **target)
Definition unittools.c:1098
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
bool utype_is_consumed_by_action(const struct action *paction, const struct unit_type *utype)
Definition unittype.c:1271