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 if (actor == NULL || target == NULL) {
737 /* Can't do any actions if actor or target are missing. */
738 return NULL;
739 }
740
741 action_iterate(act) {
742 struct act_prob prob;
743
744 if (action_id_get_actor_kind(act) != AAK_UNIT) {
745 /* Not a relevant action. */
746 continue;
747 }
748
749 if (action_id_is_rare_pop_up(act) && !accept_all_actions) {
750 /* Not relevant since not accepted here. */
751 continue;
752 }
753
754 switch (action_id_get_target_kind(act)) {
755 case ATK_TILE:
756 prob = action_prob_vs_tile(actor, act, target, target_extra);
757 break;
758 case ATK_EXTRAS:
759 prob = action_prob_vs_extras(actor, act, target, target_extra);
760 break;
761 case ATK_UNITS:
762 prob = action_prob_vs_units(actor, act, target);
763 break;
764 case ATK_CITY:
765 case ATK_UNIT:
766 case ATK_SELF:
767 /* Target not specified by tile. */
768 continue;
769 case ATK_COUNT:
770 /* Invalid target kind */
771 fc_assert(action_id_get_target_kind(act) != ATK_COUNT);
772 continue;
773 }
774
775 if (action_prob_possible(prob)) {
776 /* The actor unit may be able to do this action to the target
777 * tile. */
778 return target;
779 }
781
782 return NULL;
783}
784
785/**********************************************************************/
797static bool may_unit_act_vs_tile_extra(const struct unit *actor,
798 const struct tile *tgt_tile,
799 const struct extra_type *tgt_extra,
800 bool accept_all_actions)
801{
802 if (actor == NULL || tgt_tile == NULL || tgt_extra == NULL) {
803 /* Can't do any actions if actor or target are missing. */
804 return FALSE;
805 }
806
807 action_iterate(act) {
808 if (!(action_id_get_actor_kind(act) == AAK_UNIT
809 && (action_id_get_target_kind(act) == ATK_TILE
810 || action_id_get_target_kind(act) == ATK_EXTRAS)
812 /* Not a relevant action. */
813 continue;
814 }
815
816 if (action_id_is_rare_pop_up(act) && !accept_all_actions) {
817 /* Not relevant since not accepted here. */
818 continue;
819 }
820
821 switch (action_id_get_target_kind(act)) {
822 case ATK_TILE:
824 tgt_tile, tgt_extra))) {
825 /* The actor unit may be able to do this action to the target
826 * extra. */
827 return TRUE;
828 }
829 break;
830 case ATK_EXTRAS:
832 tgt_tile,
833 tgt_extra))) {
834 /* The actor unit may be able to do this action to the target
835 * extra. */
836 return TRUE;
837 }
838 break;
839 case ATK_CITY:
840 case ATK_UNIT:
841 case ATK_UNITS:
842 case ATK_SELF:
843 /* Not supported. */
844 break;
845 case ATK_COUNT:
846 fc_assert(action_id_get_target_kind(act) != ATK_COUNT);
847 break;
848 }
850
851 return FALSE;
852}
853
854/**********************************************************************/
867 const struct tile *target_tile,
868 bool accept_all_actions)
869{
872 accept_all_actions)) {
873 return target;
874 }
876
877 return NULL;
878}
879
880/**********************************************************************/
883int action_sub_target_id_for_action(const struct action *paction,
884 struct unit *actor_unit)
885{
886 const struct tile *tgt_tile = unit_tile(actor_unit);
887
888 fc_assert_ret_val(paction->target_complexity == ACT_TGT_COMPL_FLEXIBLE,
889 NO_TARGET);
890
891 switch (action_get_sub_target_kind(paction)) {
892 case ASTK_NONE:
893 /* Should not be reached */
894 fc_assert_ret_val(action_get_sub_target_kind(paction) != ASTK_NONE,
895 NO_TARGET);
896 break;
897 case ASTK_BUILDING:
898 /* Implement if a building sub targeted action becomes flexible */
899 fc_assert_ret_val(paction->target_complexity == ACT_TGT_COMPL_FLEXIBLE,
900 NO_TARGET);
901 break;
902 case ASTK_TECH:
903 /* Implement if a tech 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_EXTRA:
908 case ASTK_EXTRA_NOT_THERE:
909 if (action_has_result(paction, ACTRES_PILLAGE)) {
910 /* Special treatment for "Pillage" */
911 struct extra_type *pextra = NULL;
912 enum unit_activity activity = actres_get_activity(paction->result);
913
915
916 if (pextra != NULL) {
917 return extra_number(pextra);
918 }
919 }
922 tgt_tile, tgt_extra))) {
923 /* The actor unit may be able to do this action to the target
924 * extra. */
925 return extra_number(tgt_extra);
926 }
928 break;
929 case ASTK_COUNT:
930 /* Should not exist. */
931 fc_assert_ret_val(action_get_sub_target_kind(paction) != ASTK_COUNT,
932 NO_TARGET);
933 break;
934 }
935
936 return NO_TARGET;
937}
938
939/**********************************************************************/
944const struct action_auto_perf *
945action_auto_perf_unit_sel(const enum action_auto_perf_cause cause,
946 const struct unit *actor,
947 const struct player *other_player,
948 const struct output_type *eval_output,
949 const struct action *eval_action)
950{
951 const struct req_context actor_ctxt = {
953 .tile = unit_tile(actor),
954 .unit = actor,
955 .unittype = unit_type_get(actor),
956 .output = eval_output,
957 .action = eval_action,
958 };
959
960 action_auto_perf_by_cause_iterate(cause, autoperformer) {
961 if (are_reqs_active(&actor_ctxt, other_player,
962 &autoperformer->reqs, RPT_CERTAIN)) {
963 /* Select this action auto performer. */
964 return autoperformer;
965 }
967
968 /* Can't even try to force an action. */
969 return NULL;
970}
971
972#define action_auto_perf_acquire_targets(_target_extra_) \
973 tgt_city = (target_city ? target_city \
974 : action_tgt_city(actor, unit_tile(actor), \
975 TRUE)); \
976 tgt_tile = (target_tile ? target_tile \
977 : action_tgt_tile(actor, unit_tile(actor), \
978 _target_extra_, \
979 TRUE)); \
980 tgt_unit = (target_unit ? target_unit \
981 : action_tgt_unit(actor, unit_tile(actor), \
982 TRUE));
983
984/**********************************************************************/
992const struct action *
993action_auto_perf_unit_do(const enum action_auto_perf_cause cause,
994 struct unit *actor,
995 const struct player *other_player,
996 const struct output_type *eval_output,
997 const struct action *eval_action,
998 const struct tile *target_tile,
999 const struct city *target_city,
1000 const struct unit *target_unit,
1001 const struct extra_type *target_extra)
1002{
1003 int actor_id;
1004
1005 const struct city *tgt_city;
1006 const struct tile *tgt_tile;
1007 const struct unit *tgt_unit;
1008 const struct civ_map *nmap = &(wld.map);
1009
1010 const struct action_auto_perf *autoperf
1011 = action_auto_perf_unit_sel(cause, actor, other_player,
1012 eval_output, eval_action);
1013
1014 if (!autoperf) {
1015 /* No matching Action Auto Performer. */
1016 return NULL;
1017 }
1018
1019 actor_id = actor->id;
1020
1021 /* Acquire the targets. */
1023
1024 action_auto_perf_actions_iterate(autoperf, act) {
1025 if (action_id_get_actor_kind(act) == AAK_UNIT) {
1026 /* This action can be done by units. */
1027
1028#define perform_action_to(act, actor, tgtid, tgt_extra) \
1029 if (unit_perform_action(unit_owner(actor), \
1030 actor->id, tgtid, tgt_extra, \
1031 NULL, act, ACT_REQ_RULES)) { \
1032 return action_by_number(act); \
1033 }
1034
1035 switch (action_id_get_target_kind(act)) {
1036 case ATK_UNITS:
1037 if (tgt_tile
1038 && is_action_enabled_unit_on_units(nmap, act, actor, tgt_tile)) {
1039 perform_action_to(act, actor, tgt_tile->index, EXTRA_NONE);
1040 }
1041 break;
1042 case ATK_TILE:
1043 if (tgt_tile
1045 tgt_tile, target_extra)) {
1046 perform_action_to(act, actor, tgt_tile->index,
1048 }
1049 break;
1050 case ATK_EXTRAS:
1051 if (tgt_tile
1053 tgt_tile, target_extra)) {
1054 perform_action_to(act, actor, tgt_tile->index,
1056 }
1057 break;
1058 case ATK_CITY:
1059 if (tgt_city
1060 && is_action_enabled_unit_on_city(nmap, act, actor, tgt_city)) {
1061 perform_action_to(act, actor, tgt_city->id, EXTRA_NONE)
1062 }
1063 break;
1064 case ATK_UNIT:
1065 if (tgt_unit
1066 && is_action_enabled_unit_on_unit(nmap, act, actor, tgt_unit)) {
1067 perform_action_to(act, actor, tgt_unit->id, EXTRA_NONE);
1068 }
1069 break;
1070 case ATK_SELF:
1071 if (actor
1072 && is_action_enabled_unit_on_self(nmap, act, actor)) {
1074 }
1075 break;
1076 case ATK_COUNT:
1077 fc_assert(action_id_get_target_kind(act) != ATK_COUNT);
1078 }
1079
1080 if (!unit_is_alive(actor_id)) {
1081 /* The unit is gone. Maybe it was killed in Lua? */
1082 return NULL;
1083 }
1084 }
1086
1087 return NULL;
1088}
1089
1090/**********************************************************************/
1094struct act_prob
1095action_auto_perf_unit_prob(const enum action_auto_perf_cause cause,
1096 struct unit *actor,
1097 const struct player *other_player,
1098 const struct output_type *eval_output,
1099 const struct action *eval_action,
1100 const struct tile *target_tile,
1101 const struct city *target_city,
1102 const struct unit *target_unit,
1103 const struct extra_type *target_extra)
1104{
1105 struct act_prob out;
1106
1107 const struct city *tgt_city;
1108 const struct tile *tgt_tile;
1109 const struct unit *tgt_unit;
1110 const struct civ_map *nmap = &(wld.map);
1111
1112 const struct action_auto_perf *autoperf
1113 = action_auto_perf_unit_sel(cause, actor, other_player,
1114 eval_output, eval_action);
1115
1116 if (!autoperf) {
1117 /* No matching Action Auto Performer. */
1118 return ACTPROB_IMPOSSIBLE;
1119 }
1120
1121 out = ACTPROB_IMPOSSIBLE;
1122
1123 /* Acquire the targets. */
1125
1126 action_auto_perf_actions_iterate(autoperf, act) {
1127 struct act_prob current = ACTPROB_IMPOSSIBLE;
1128
1129 if (action_id_get_actor_kind(act) == AAK_UNIT) {
1130 /* This action can be done by units. */
1131
1132 switch (action_id_get_target_kind(act)) {
1133 case ATK_UNITS:
1134 if (tgt_tile
1135 && is_action_enabled_unit_on_units(nmap, act, actor, tgt_tile)) {
1136 current = action_prob_vs_units(actor, act, tgt_tile);
1137 }
1138 break;
1139 case ATK_TILE:
1140 if (tgt_tile
1142 tgt_tile, target_extra)) {
1143 current = action_prob_vs_tile(actor, act, tgt_tile, target_extra);
1144 }
1145 break;
1146 case ATK_EXTRAS:
1147 if (tgt_tile
1149 tgt_tile, target_extra)) {
1150 current = action_prob_vs_extras(actor, act,
1151 tgt_tile, target_extra);
1152 }
1153 break;
1154 case ATK_CITY:
1155 if (tgt_city
1156 && is_action_enabled_unit_on_city(nmap, act, actor, tgt_city)) {
1157 current = action_prob_vs_city(nmap, actor, act, tgt_city);
1158 }
1159 break;
1160 case ATK_UNIT:
1161 if (tgt_unit
1162 && is_action_enabled_unit_on_unit(nmap, act, actor, tgt_unit)) {
1163 current = action_prob_vs_unit(nmap, actor, act, tgt_unit);
1164 }
1165 break;
1166 case ATK_SELF:
1167 if (actor
1168 && is_action_enabled_unit_on_self(nmap, act, actor)) {
1169 current = action_prob_self(actor, act);
1170 }
1171 break;
1172 case ATK_COUNT:
1173 fc_assert(action_id_get_target_kind(act) != ATK_COUNT);
1174 }
1175 }
1176
1177 out = action_prob_fall_back(&out, &current);
1179
1180 return out;
1181}
1182
1183/************************************************************************/
1187bool action_failed_dice_roll(const struct player *act_player,
1188 const struct unit *act_unit,
1189 const struct city *tgt_city,
1190 const struct player *tgt_player,
1191 const struct action *paction)
1192{
1193 int odds = action_dice_roll_odds(act_player, act_unit,
1194 tgt_city, tgt_player,
1195 paction);
1196
1197 /* Roll the dice. */
1198 return fc_rand (100) >= odds;
1199}
const char * action_name_translation(const struct action *action)
Definition actions.c:1890
struct act_prob action_prob_self(const struct unit *actor_unit, const action_id act_id)
Definition actions.c:6380
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:6707
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:7068
enum action_sub_target_kind action_get_sub_target_kind(const struct action *paction)
Definition actions.c:1751
struct act_prob action_prob_vs_tile(const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:6225
struct act_prob action_prob_vs_units(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_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
enum unit_activity actres_get_activity(enum action_result result)
Definition actions.c:2136
struct act_prob action_prob_fall_back(const struct act_prob *ap1, const struct act_prob *ap2)
Definition actions.c:6915
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
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
struct act_prob action_prob_vs_extras(const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:6309
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:927
#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:292
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:2239
int unit_pays_mp_for_action(const struct action *paction, const struct unit *punit)
Definition unit.c:2121
#define unit_tile(_pu)
Definition unit.h:388
#define unit_owner(_pu)
Definition unit.h:387
#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:2798
void wipe_unit(struct unit *punit, enum unit_loss_reason reason, struct player *killer)
Definition unittools.c:2251
void unit_assign_specific_activity_target(struct unit *punit, enum unit_activity *activity, struct extra_type **target)
Definition unittools.c:1102
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