From 66d0269c7921ebee49f3ac1b5708f05fac405e6b Mon Sep 17 00:00:00 2001 From: Sveinung Kvilhaugsvik Date: Tue, 9 Feb 2021 21:10:38 +0100 Subject: [PATCH] Forced post action actions to the ruleset. The actions "Bribe Unit" and "Attack" will under certain circumstances force an enabler controlled action or a move if the action is successful. The enabler controlled actions come from the fact that they used to be side effects of regular moves. The code to try various enabler controlled actions and then a regular move has gotten big and ugly. Soft code it by making the list of actions attempted as a part of a forced move a list. Put the list in the ruleset so it can be changed. See osdn #41524 --- common/actions.c | 111 ++++++++++++++++++++++++++++++++ common/actions.h | 9 +++ common/fc_types.h | 2 +- data/alien/game.ruleset | 19 ++++++ data/civ1/game.ruleset | 19 ++++++ data/civ2/game.ruleset | 21 ++++++ data/civ2civ3/game.ruleset | 21 ++++++ data/classic/game.ruleset | 21 ++++++ data/experimental/game.ruleset | 21 ++++++ data/granularity/game.ruleset | 10 +++ data/multiplayer/game.ruleset | 21 ++++++ data/sandbox/game.ruleset | 21 ++++++ data/stub/game.ruleset | 10 +++ data/webperimental/game.ruleset | 15 +++++ doc/README.actions | 4 ++ fc_version | 2 +- server/diplomats.c | 103 ++--------------------------- server/rscompat.c | 33 ++++++++++ server/ruleset.c | 60 +++++++++++++++++ server/unithand.c | 77 ++-------------------- tools/ruleutil/rulesave.c | 44 +++++++++++++ 21 files changed, 474 insertions(+), 170 deletions(-) diff --git a/common/actions.c b/common/actions.c index 0d54f14987..702b8053cd 100644 --- a/common/actions.c +++ b/common/actions.c @@ -8198,3 +8198,114 @@ const char *action_blocked_by_ruleset_var_name(const struct action *act) return NULL; } + +/**********************************************************************//** + Return action post success forced action ruleset variable name for the + action or NULL if it can't be set in the ruleset. +**************************************************************************/ +const char * +action_post_success_forced_ruleset_var_name(const struct action *act) +{ + fc_assert_ret_val(act != NULL, NULL); + + if (!(action_has_result(act, ACTRES_SPY_BRIBE_UNIT) + ||action_has_result(act, ACTRES_ATTACK))) { + /* No support in the action performer function */ + return NULL; + } + + switch ((enum gen_action)action_number(act)) { + case ACTION_SPY_BRIBE_UNIT: + return "bribe_unit_post_success_forced_actions"; + case ACTION_ATTACK: + return "attack_post_success_forced_actions"; + case ACTION_MARKETPLACE: + case ACTION_BOMBARD: + case ACTION_BOMBARD2: + case ACTION_BOMBARD3: + case ACTION_NUKE: + case ACTION_NUKE_CITY: + case ACTION_NUKE_UNITS: + case ACTION_SUICIDE_ATTACK: + case ACTION_CONQUER_CITY: + case ACTION_CONQUER_CITY2: + case ACTION_SPY_POISON: + case ACTION_SPY_POISON_ESC: + case ACTION_SPY_SABOTAGE_UNIT: + case ACTION_SPY_SABOTAGE_UNIT_ESC: + case ACTION_SPY_SABOTAGE_CITY: + case ACTION_SPY_SABOTAGE_CITY_ESC: + case ACTION_SPY_TARGETED_SABOTAGE_CITY: + case ACTION_SPY_SABOTAGE_CITY_PRODUCTION: + case ACTION_SPY_TARGETED_SABOTAGE_CITY_ESC: + case ACTION_SPY_SABOTAGE_CITY_PRODUCTION_ESC: + case ACTION_SPY_INCITE_CITY: + case ACTION_SPY_INCITE_CITY_ESC: + case ACTION_ESTABLISH_EMBASSY: + case ACTION_ESTABLISH_EMBASSY_STAY: + case ACTION_SPY_STEAL_TECH: + case ACTION_SPY_STEAL_TECH_ESC: + case ACTION_SPY_TARGETED_STEAL_TECH: + case ACTION_SPY_TARGETED_STEAL_TECH_ESC: + case ACTION_SPY_INVESTIGATE_CITY: + case ACTION_INV_CITY_SPEND: + case ACTION_SPY_STEAL_GOLD: + case ACTION_SPY_STEAL_GOLD_ESC: + case ACTION_STEAL_MAPS: + case ACTION_STEAL_MAPS_ESC: + case ACTION_TRADE_ROUTE: + case ACTION_HELP_WONDER: + case ACTION_CAPTURE_UNITS: + case ACTION_EXPEL_UNIT: + case ACTION_FOUND_CITY: + case ACTION_JOIN_CITY: + case ACTION_SPY_NUKE: + case ACTION_SPY_NUKE_ESC: + case ACTION_DESTROY_CITY: + case ACTION_RECYCLE_UNIT: + case ACTION_DISBAND_UNIT: + case ACTION_HOME_CITY: + case ACTION_UPGRADE_UNIT: + case ACTION_PARADROP: + case ACTION_AIRLIFT: + case ACTION_STRIKE_BUILDING: + case ACTION_STRIKE_PRODUCTION: + case ACTION_HEAL_UNIT: + case ACTION_TRANSFORM_TERRAIN: + case ACTION_CULTIVATE: + case ACTION_PLANT: + case ACTION_PILLAGE: + case ACTION_CLEAN_POLLUTION: + case ACTION_CLEAN_FALLOUT: + case ACTION_FORTIFY: + case ACTION_ROAD: + case ACTION_CONVERT: + case ACTION_BASE: + case ACTION_MINE: + case ACTION_IRRIGATE: + case ACTION_TRANSPORT_ALIGHT: + case ACTION_TRANSPORT_BOARD: + case ACTION_TRANSPORT_EMBARK: + case ACTION_TRANSPORT_UNLOAD: + case ACTION_TRANSPORT_DISEMBARK1: + case ACTION_TRANSPORT_DISEMBARK2: + case ACTION_SPY_SPREAD_PLAGUE: + case ACTION_SPY_ATTACK: + case ACTION_CONQUER_EXTRAS: + case ACTION_CONQUER_EXTRAS2: + case ACTION_HUT_ENTER: + case ACTION_HUT_ENTER2: + case ACTION_HUT_FRIGHTEN: + case ACTION_HUT_FRIGHTEN2: + case ACTION_USER_ACTION1: + case ACTION_USER_ACTION2: + case ACTION_USER_ACTION3: + /* not ruleset changeable */ + return NULL; + case ACTION_COUNT: + fc_assert_ret_val(action_number(act) != ACTION_COUNT, NULL); + break; + } + + return NULL; +} diff --git a/common/actions.h b/common/actions.h index 46bad3b902..e6bf267b8d 100644 --- a/common/actions.h +++ b/common/actions.h @@ -467,6 +467,10 @@ struct action_enabler /* A unit moved to an adjacent tile (auto attack). */ #define SPECENUM_VALUE1 AAPC_UNIT_MOVED_ADJ #define SPECENUM_VALUE1NAME N_("Moved Adjacent") +/* An action was successfully performed and the (action specific) conditions + * for forcing a post action move are fulfilled. */ +#define SPECENUM_VALUE2 AAPC_POST_ACTION +#define SPECENUM_VALUE2NAME N_("After Successful Action") /* Number of forced action auto performer causes. */ #define SPECENUM_COUNT AAPC_COUNT #include "specenum_gen.h" @@ -532,6 +536,8 @@ action_auto_perf_iterate(_act_perf_) { \ #define ACTION_AUTO_UPKEEP_GOLD 1 #define ACTION_AUTO_UPKEEP_SHIELD 2 #define ACTION_AUTO_MOVED_ADJ 3 +#define ACTION_AUTO_POST_BRIBE 4 +#define ACTION_AUTO_POST_ATTACK 5 /* Initialization */ void actions_init(void); @@ -641,6 +647,9 @@ const char *action_actor_consuming_always_ruleset_var_name(action_id act); const char *action_blocked_by_ruleset_var_name(const struct action *act); +const char * +action_post_success_forced_ruleset_var_name(const struct action *act); + struct action_enabler_list * action_enablers_for_action(action_id action); diff --git a/common/fc_types.h b/common/fc_types.h index 45d5bd30f7..364a68cc81 100644 --- a/common/fc_types.h +++ b/common/fc_types.h @@ -53,7 +53,7 @@ extern "C" { #define MAX_GOODS_TYPES 25 #define MAX_DISASTER_TYPES 10 #define MAX_ACHIEVEMENT_TYPES 40 -#define MAX_NUM_ACTION_AUTO_PERFORMERS 4 +#define MAX_NUM_ACTION_AUTO_PERFORMERS 6 #define MAX_NUM_MULTIPLIERS 15 #define MAX_NUM_LEADERS MAX_NUM_ITEMS /* Used in the network protocol. */ #define MAX_NUM_NATION_SETS 32 /* Used in the network protocol. diff --git a/data/alien/game.ruleset b/data/alien/game.ruleset index 10412eda65..023d3b94ab 100644 --- a/data/alien/game.ruleset +++ b/data/alien/game.ruleset @@ -268,6 +268,25 @@ conquer_city_blocked_by = "Capture Units", "Bombard", "Attack", move_is_blocked_by = "Transport Disembark", "Transport Disembark 2", "Enter Hut", "Enter Hut 2" +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Bribe Unit". +bribe_unit_post_success_forced_actions = "Transport Embark", + "Transport Disembark", + "Transport Disembark 2", + "Conquer Extras", + "Conquer Extras 2", + "Enter Hut", "Enter Hut 2" + +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Attack". +attack_post_success_forced_actions = "Conquer City", "Conquer City 2", + "Transport Disembark", + "Transport Disembark 2", + "Conquer Extras", "Conquer Extras 2", + "Enter Hut", "Enter Hut 2" + ; If poison_empties_food_stock is set to TRUE a successful "Poison City" ; or "Poison City Escape" will empty the food stock. ;poison_empties_food_stock = FALSE diff --git a/data/civ1/game.ruleset b/data/civ1/game.ruleset index 53f1f85239..d8ab3cc371 100644 --- a/data/civ1/game.ruleset +++ b/data/civ1/game.ruleset @@ -251,6 +251,25 @@ conquer_city_blocked_by = "Explode Nuclear", "Nuke City", "Nuke Units", ; Forbid regular unit move if one of the actions below is legal. move_is_blocked_by = "Transport Disembark", "Enter Hut", "Enter Hut 2" +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Bribe Unit". +bribe_unit_post_success_forced_actions = "Transport Embark", + "Transport Disembark", + "Transport Disembark 2", + "Conquer Extras", + "Conquer Extras 2", + "Enter Hut", "Enter Hut 2" + +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Attack". +attack_post_success_forced_actions = "Conquer City", "Conquer City 2", + "Transport Disembark", + "Transport Disembark 2", + "Conquer Extras", "Conquer Extras 2", + "Enter Hut", "Enter Hut 2" + ; If poison_empties_food_stock is set to TRUE a successful "Poison City" ; or "Poison City Escape" will empty the food stock. ;poison_empties_food_stock = FALSE diff --git a/data/civ2/game.ruleset b/data/civ2/game.ruleset index 333cfe6564..0706b93705 100644 --- a/data/civ2/game.ruleset +++ b/data/civ2/game.ruleset @@ -247,6 +247,27 @@ conquer_city_blocked_by = "Explode Nuclear", "Nuke City", "Nuke Units", ; Forbid regular unit move if one of the actions below is legal. move_is_blocked_by = "Transport Disembark", "Enter Hut", "Frighten Hut" +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Bribe Unit". +bribe_unit_post_success_forced_actions = "Transport Embark", + "Transport Disembark", + "Transport Disembark 2", + "Conquer Extras", + "Conquer Extras 2", + "Enter Hut", "Enter Hut 2", + "Frighten Hut", "Frighten Hut 2" + +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Attack". +attack_post_success_forced_actions = "Conquer City", "Conquer City 2", + "Transport Disembark", + "Transport Disembark 2", + "Conquer Extras", "Conquer Extras 2", + "Enter Hut", "Enter Hut 2", + "Frighten Hut", "Frighten Hut 2" + ; If poison_empties_food_stock is set to TRUE a successful "Poison City" ; or "Poison City Escape" will empty the food stock. poison_empties_food_stock = FALSE diff --git a/data/civ2civ3/game.ruleset b/data/civ2civ3/game.ruleset index d7df4a625c..bc5030aa36 100644 --- a/data/civ2civ3/game.ruleset +++ b/data/civ2civ3/game.ruleset @@ -291,6 +291,27 @@ move_is_blocked_by = "Transport Disembark", "Transport Disembark 2", "Enter Hut", "Enter Hut 2", "Frighten Hut", "Frighten Hut 2" +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Bribe Unit". +bribe_unit_post_success_forced_actions = "Transport Embark", + "Transport Disembark", + "Transport Disembark 2", + "Conquer Extras", + "Conquer Extras 2", + "Enter Hut", "Enter Hut 2", + "Frighten Hut", "Frighten Hut 2" + +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Attack". +attack_post_success_forced_actions = "Conquer City", "Conquer City 2", + "Transport Disembark", + "Transport Disembark 2", + "Conquer Extras", "Conquer Extras 2", + "Enter Hut", "Enter Hut 2", + "Frighten Hut", "Frighten Hut 2" + ; If poison_empties_food_stock is set to TRUE a successful "Poison City" ; or "Poison City Escape" will empty the food stock. poison_empties_food_stock = FALSE diff --git a/data/classic/game.ruleset b/data/classic/game.ruleset index b62b93c40b..587aba20fe 100644 --- a/data/classic/game.ruleset +++ b/data/classic/game.ruleset @@ -274,6 +274,27 @@ move_is_blocked_by = "Transport Disembark", "Transport Disembark 2", "Enter Hut", "Enter Hut 2", "Frighten Hut", "Frighten Hut 2" +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Bribe Unit". +bribe_unit_post_success_forced_actions = "Transport Embark", + "Transport Disembark", + "Transport Disembark 2", + "Conquer Extras", + "Conquer Extras 2", + "Enter Hut", "Enter Hut 2", + "Frighten Hut", "Frighten Hut 2" + +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Attack". +attack_post_success_forced_actions = "Conquer City", "Conquer City 2", + "Transport Disembark", + "Transport Disembark 2", + "Conquer Extras", "Conquer Extras 2", + "Enter Hut", "Enter Hut 2", + "Frighten Hut", "Frighten Hut 2" + ; If poison_empties_food_stock is set to TRUE a successful "Poison City" ; or "Poison City Escape" will empty the food stock. poison_empties_food_stock = FALSE diff --git a/data/experimental/game.ruleset b/data/experimental/game.ruleset index 7318afb6fe..e38ed6b737 100644 --- a/data/experimental/game.ruleset +++ b/data/experimental/game.ruleset @@ -279,6 +279,27 @@ move_is_blocked_by = "Transport Disembark", "Transport Disembark 2", "Enter Hut", "Enter Hut 2", "Frighten Hut", "Frighten Hut 2" +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Bribe Unit". +bribe_unit_post_success_forced_actions = "Transport Embark", + "Transport Disembark", + "Transport Disembark 2", + "Conquer Extras", + "Conquer Extras 2", + "Enter Hut", "Enter Hut 2", + "Frighten Hut", "Frighten Hut 2" + +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Attack". +attack_post_success_forced_actions = "Conquer City", "Conquer City 2", + "Transport Disembark", + "Transport Disembark 2", + "Conquer Extras", "Conquer Extras 2", + "Enter Hut", "Enter Hut 2", + "Frighten Hut", "Frighten Hut 2" + ; If poison_empties_food_stock is set to TRUE a successful "Poison City" ; or "Poison City Escape" will empty the food stock. poison_empties_food_stock = FALSE diff --git a/data/granularity/game.ruleset b/data/granularity/game.ruleset index f0af42f2a0..64e3014783 100644 --- a/data/granularity/game.ruleset +++ b/data/granularity/game.ruleset @@ -247,6 +247,16 @@ if_attacker = ; Forbid regular unit move if one of the actions below is legal. move_is_blocked_by = "Transport Disembark", "Transport Disembark 2" +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Bribe Unit". +;bribe_unit_post_success_forced_actions = "Transport Embark" + +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Attack". +;attack_post_success_forced_actions = "Conquer City", "Conquer City 2" + ; If poison_empties_food_stock is set to TRUE a successful "Poison City" ; or "Poison City Escape" will empty the food stock. ;poison_empties_food_stock = FALSE diff --git a/data/multiplayer/game.ruleset b/data/multiplayer/game.ruleset index af54753369..fb9448c3f0 100644 --- a/data/multiplayer/game.ruleset +++ b/data/multiplayer/game.ruleset @@ -272,6 +272,27 @@ conquer_city_2_blocked_by = "Explode Nuclear", "Nuke City", "Nuke Units", move_is_blocked_by = "Transport Disembark", "Transport Disembark 2", "Conquer Extras", "Conquer Extras 2" +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Bribe Unit". +bribe_unit_post_success_forced_actions = "Transport Embark", + "Transport Disembark", + "Transport Disembark 2", + "Conquer Extras", + "Conquer Extras 2", + "Enter Hut", "Enter Hut 2", + "Frighten Hut", "Frighten Hut 2" + +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Attack". +attack_post_success_forced_actions = "Conquer City", "Conquer City 2", + "Transport Disembark", + "Transport Disembark 2", + "Conquer Extras", "Conquer Extras 2", + "Enter Hut", "Enter Hut 2", + "Frighten Hut", "Frighten Hut 2" + ; If poison_empties_food_stock is set to TRUE a successful "Poison City" ; or "Poison City Escape" will empty the food stock. poison_empties_food_stock = FALSE diff --git a/data/sandbox/game.ruleset b/data/sandbox/game.ruleset index 0579a4cee8..4d568c1e9d 100644 --- a/data/sandbox/game.ruleset +++ b/data/sandbox/game.ruleset @@ -291,6 +291,27 @@ move_is_blocked_by = "Transport Disembark", "Transport Disembark 2", "Enter Hut", "Enter Hut 2", "Frighten Hut", "Frighten Hut 2" +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Bribe Unit". +bribe_unit_post_success_forced_actions = "Transport Embark", + "Transport Disembark", + "Transport Disembark 2", + "Conquer Extras", + "Conquer Extras 2", + "Enter Hut", "Enter Hut 2", + "Frighten Hut", "Frighten Hut 2" + +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Attack". +attack_post_success_forced_actions = "Conquer City", "Conquer City 2", + "Transport Disembark", + "Transport Disembark 2", + "Conquer Extras", "Conquer Extras 2", + "Enter Hut", "Enter Hut 2", + "Frighten Hut", "Frighten Hut 2" + ; If poison_empties_food_stock is set to TRUE a successful "Poison City" ; or "Poison City Escape" will empty the food stock. poison_empties_food_stock = FALSE diff --git a/data/stub/game.ruleset b/data/stub/game.ruleset index 6fbc505445..654f81123f 100644 --- a/data/stub/game.ruleset +++ b/data/stub/game.ruleset @@ -237,6 +237,16 @@ nuke_defender_survival_chance_pct = 0 ; Forbid regular unit move if one of the actions below is legal. ;move_is_blocked_by = "Conquer Extras" +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Bribe Unit". +;bribe_unit_post_success_forced_actions = "Transport Embark" + +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Attack". +;attack_post_success_forced_actions = "Conquer City", "Conquer City 2" + ; If poison_empties_food_stock is set to TRUE a successful "Poison City" ; or "Poison City Escape" will empty the food stock. ;poison_empties_food_stock = FALSE diff --git a/data/webperimental/game.ruleset b/data/webperimental/game.ruleset index a418892ead..d0c4829199 100644 --- a/data/webperimental/game.ruleset +++ b/data/webperimental/game.ruleset @@ -272,6 +272,21 @@ conquer_city_blocked_by = "Explode Nuclear", "Nuke City", "Nuke Units", move_is_blocked_by = "Transport Disembark", "Conquer Extras", "Enter Hut", "Frighten Hut" +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Bribe Unit". +bribe_unit_post_success_forced_actions = "Transport Embark", + "Transport Disembark", + "Conquer Extras", + "Enter Hut", "Frighten Hut" + +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Attack". +attack_post_success_forced_actions = "Conquer City", "Transport Disembark", + "Conquer Extras", + "Enter Hut","Frighten Hut" + ; If poison_empties_food_stock is set to TRUE a successful "Poison City" ; or "Poison City Escape" will empty the food stock. poison_empties_food_stock = FALSE diff --git a/doc/README.actions b/doc/README.actions index e8e987554a..b99f42e7b4 100644 --- a/doc/README.actions +++ b/doc/README.actions @@ -572,6 +572,8 @@ Actions done by a unit against another unit "Bribe Unit" - Make the target unit join the actors owners side. * UI name can be set using ui_name_bribe_unit + * forced actions after success can be set with + bribe_unit_post_success_forced_actions * actor must be on the same tile as the target or on the tile next to it. * target must be foreign. (!) * target must be visible for the actor. @@ -705,6 +707,8 @@ Actions done by a unit against all units at a tile "Attack" * UI name can be set using ui_name_attack * any action listed in attack_blocked_by must be impossible + * forced actions after success can be set with + attack_post_success_forced_actions * the actor must be on the tile next to the target. * the actor's attack must be above 0 * the actor can't have the "NonMil" unit type flag (!) diff --git a/fc_version b/fc_version index 4671824970..a6b42c9483 100755 --- a/fc_version +++ b/fc_version @@ -56,7 +56,7 @@ DEFAULT_FOLLOW_TAG=S3_1 # - No new mandatory capabilities can be added to the release branch; doing # so would break network capability of supposedly "compatible" releases. # -NETWORK_CAPSTRING="+Freeciv.Devel-3.1-2021.Feb.09b" +NETWORK_CAPSTRING="+Freeciv.Devel-3.1-2021.Feb.11" FREECIV_DISTRIBUTOR="" diff --git a/server/diplomats.c b/server/diplomats.c index 562b51713e..5b9407f278 100644 --- a/server/diplomats.c +++ b/server/diplomats.c @@ -686,103 +686,12 @@ bool diplomat_bribe(struct player *pplayer, struct unit *pdiplomat, /* Try to move the briber onto the victim's square unless the victim has * been bounced because it couldn't share tile with a unit or city. */ if (!bounce - /* Post bribe embark. */ - && (can_unit_exist_at_tile(&(wld.map), pdiplomat, victim_tile) - || !(is_action_enabled_unit_on_unit(ACTION_TRANSPORT_EMBARK, - pdiplomat, pvictim) - && unit_perform_action(unit_owner(pdiplomat), pdiplomat->id, - pvictim->id, 0, "", - ACTION_TRANSPORT_EMBARK, - ACT_REQ_RULES))) - /* May have died while trying to embark. */ - && unit_is_alive(diplomat_id) - /* Post bribe disembark. */ - && (!unit_transported(pdiplomat) - || !(is_action_enabled_unit_on_tile(ACTION_TRANSPORT_DISEMBARK1, - pdiplomat, victim_tile, NULL) - && unit_perform_action(unit_owner(pdiplomat), pdiplomat->id, - tile_index(victim_tile), 0, "", - ACTION_TRANSPORT_DISEMBARK1, - ACT_REQ_RULES))) - /* May have died while trying to disembark. */ - && unit_is_alive(diplomat_id) - /* Post bribe disembark 2. */ - && (!unit_transported(pdiplomat) - || !(is_action_enabled_unit_on_tile(ACTION_TRANSPORT_DISEMBARK2, - pdiplomat, victim_tile, NULL) - && unit_perform_action(unit_owner(pdiplomat), pdiplomat->id, - tile_index(victim_tile), 0, "", - ACTION_TRANSPORT_DISEMBARK2, - ACT_REQ_RULES))) - /* May have died while trying to disembark. */ - && unit_is_alive(diplomat_id) - /* Post bribe extras conquest. */ - && (!tile_has_claimable_base(victim_tile, unit_type_get(pdiplomat)) - || !(is_action_enabled_unit_on_extras(ACTION_CONQUER_EXTRAS, - pdiplomat, victim_tile, - NULL) - && unit_perform_action(unit_owner(pdiplomat), pdiplomat->id, - tile_index(victim_tile), 0, "", - ACTION_CONQUER_EXTRAS, - ACT_REQ_RULES))) - /* May have died while trying to conquer extra. */ - && unit_is_alive(diplomat_id) - /* Post bribe extras conquest. */ - && (!tile_has_claimable_base(victim_tile, unit_type_get(pdiplomat)) - || !(is_action_enabled_unit_on_extras(ACTION_CONQUER_EXTRAS2, - pdiplomat, victim_tile, - NULL) - && unit_perform_action(unit_owner(pdiplomat), pdiplomat->id, - tile_index(victim_tile), 0, "", - ACTION_CONQUER_EXTRAS2, - ACT_REQ_RULES))) - /* May have died while trying to conquer extra. */ - && unit_is_alive(diplomat_id) - /* Post bribe hut entry. */ - && (!unit_can_enter_hut(pdiplomat, victim_tile) - || !(is_action_enabled_unit_on_tile(ACTION_HUT_ENTER, - pdiplomat, victim_tile, - NULL) - && unit_perform_action(unit_owner(pdiplomat), pdiplomat->id, - tile_index(victim_tile), 0, "", - ACTION_HUT_ENTER, - ACT_REQ_RULES))) - /* May have died while trying to enter hut. */ - && unit_is_alive(diplomat_id) - /* Post bribe hut entry. */ - && (!unit_can_enter_hut(pdiplomat, victim_tile) - || !(is_action_enabled_unit_on_tile(ACTION_HUT_ENTER2, - pdiplomat, victim_tile, - NULL) - && unit_perform_action(unit_owner(pdiplomat), pdiplomat->id, - tile_index(victim_tile), 0, "", - ACTION_HUT_ENTER2, - ACT_REQ_RULES))) - /* May have died while trying to enter hut. */ - && unit_is_alive(diplomat_id) - /* Post bribe hut frightening. */ - && (!(unit_can_enter_hut(pdiplomat, victim_tile) - && HUT_FRIGHTEN == unit_class_get(pdiplomat)->hut_behavior) - || !(is_action_enabled_unit_on_tile(ACTION_HUT_FRIGHTEN, - pdiplomat, victim_tile, - NULL) - && unit_perform_action(unit_owner(pdiplomat), pdiplomat->id, - tile_index(victim_tile), 0, "", - ACTION_HUT_FRIGHTEN, - ACT_REQ_RULES))) - /* May have died while trying to frighten hut. */ - && unit_is_alive(diplomat_id) - /* Post bribe hut frightening. */ - && (!(unit_can_enter_hut(pdiplomat, victim_tile) - && HUT_FRIGHTEN == unit_class_get(pdiplomat)->hut_behavior) - || !(is_action_enabled_unit_on_tile(ACTION_HUT_FRIGHTEN2, - pdiplomat, victim_tile, - NULL) - && unit_perform_action(unit_owner(pdiplomat), pdiplomat->id, - tile_index(victim_tile), 0, "", - ACTION_HUT_FRIGHTEN2, - ACT_REQ_RULES))) - /* May have died while trying to frighten hut. */ + /* Try to perform post move forced actions. */ + && (NULL == action_auto_perf_unit_do(AAPC_POST_ACTION, pdiplomat, + uplayer, NULL, paction, + victim_tile, pcity, pvictim, + NULL)) + /* May have died while trying to do forced actions. */ && unit_is_alive(diplomat_id) /* Post bribe move. */ && !unit_move_handling(pdiplomat, victim_tile, FALSE, TRUE) diff --git a/server/rscompat.c b/server/rscompat.c index e7adf8233b..9503f25ac6 100644 --- a/server/rscompat.c +++ b/server/rscompat.c @@ -1073,6 +1073,39 @@ void rscompat_postprocess(struct rscompat_info *info) BV_SET(game.info.move_is_blocked_by, act_id); } } action_iterate_end; + + { + /* The forced post successful action move action list has moved to the + * ruleset. */ + struct action_auto_perf *auto_perf; + + /* "Bribe Unit" */ + auto_perf = action_auto_perf_slot_number(ACTION_AUTO_POST_BRIBE); + auto_perf->alternatives[0] = ACTION_TRANSPORT_EMBARK; + auto_perf->alternatives[1] = ACTION_TRANSPORT_DISEMBARK1; + auto_perf->alternatives[2] = ACTION_TRANSPORT_DISEMBARK2; + auto_perf->alternatives[3] = ACTION_CONQUER_EXTRAS; + auto_perf->alternatives[4] = ACTION_CONQUER_EXTRAS2; + auto_perf->alternatives[5] = ACTION_HUT_ENTER; + auto_perf->alternatives[6] = ACTION_HUT_ENTER2; + auto_perf->alternatives[7] = ACTION_HUT_FRIGHTEN; + auto_perf->alternatives[8] = ACTION_HUT_FRIGHTEN2; + action_list_end(auto_perf->alternatives, 9); + + /* "Attack" */ + auto_perf = action_auto_perf_slot_number(ACTION_AUTO_POST_ATTACK); + auto_perf->alternatives[0] = ACTION_CONQUER_CITY; + auto_perf->alternatives[1] = ACTION_CONQUER_CITY2; + auto_perf->alternatives[2] = ACTION_TRANSPORT_DISEMBARK1; + auto_perf->alternatives[3] = ACTION_TRANSPORT_DISEMBARK2; + auto_perf->alternatives[4] = ACTION_CONQUER_EXTRAS; + auto_perf->alternatives[5] = ACTION_CONQUER_EXTRAS2; + auto_perf->alternatives[6] = ACTION_HUT_ENTER; + auto_perf->alternatives[7] = ACTION_HUT_ENTER2; + auto_perf->alternatives[8] = ACTION_HUT_FRIGHTEN; + auto_perf->alternatives[9] = ACTION_HUT_FRIGHTEN2; + action_list_end(auto_perf->alternatives, 10); + } } /* The ruleset may need adjustments it didn't need before compatibility diff --git a/server/ruleset.c b/server/ruleset.c index de3d64c1d9..1f64b275e5 100644 --- a/server/ruleset.c +++ b/server/ruleset.c @@ -6007,6 +6007,44 @@ static bool load_action_blocked_by_list(struct section_file *file, return TRUE; } +/**********************************************************************//** + Load what actions an actor under certain circumstances will be forced to + perform after successfully performing this action. +**************************************************************************/ +static bool load_action_post_success_force(struct section_file *file, + const char *filename, + int performer_slot, + struct action *paction) +{ + struct action_auto_perf *auto_perf; + char action_list_path[100]; + + if (action_post_success_forced_ruleset_var_name(paction) == NULL) { + /* Not relevant. */ + return TRUE; + } + + auto_perf = action_auto_perf_slot_number(performer_slot); + auto_perf->cause = AAPC_POST_ACTION; + + /* Limit auto performer to this action. */ + requirement_vector_append(&auto_perf->reqs, + req_from_values(VUT_ACTION, REQ_RANGE_LOCAL, + FALSE, TRUE, TRUE, + paction->id)); + + /* Load the list of actions. */ + fc_snprintf(action_list_path, sizeof(action_list_path), + "actions.%s", + action_post_success_forced_ruleset_var_name(paction)); + if (!load_action_auto_actions(file, auto_perf, + action_list_path, filename)) { + return FALSE; + } + + return TRUE; +} + /**********************************************************************//** Load ruleset file. **************************************************************************/ @@ -6720,6 +6758,28 @@ static bool load_ruleset_game(struct section_file *file, bool act, } } + if (ok) { + /* Forced actions after another action was successfully performed. */ + + /* "Bribe Unit" */ + if (!load_action_post_success_force(file, filename, + ACTION_AUTO_POST_BRIBE, + action_by_number( + ACTION_SPY_BRIBE_UNIT))) { + ok = FALSE; + } + + /* "Attack" */ + if (!load_action_post_success_force(file, filename, + ACTION_AUTO_POST_ATTACK, + action_by_number( + ACTION_ATTACK))) { + ok = FALSE; + } + + /* No "Suicide Attack". Can't act when dead. */ + } + if (ok) { sec = secfile_sections_by_name_prefix(file, ACTION_ENABLER_SECTION_PREFIX); diff --git a/server/unithand.c b/server/unithand.c index 8001666a15..4de87e3bc6 100644 --- a/server/unithand.c +++ b/server/unithand.c @@ -4498,77 +4498,12 @@ static bool do_attack(struct unit *punit, struct tile *def_tile, punit->moves_left = full_moves; /* Post attack occupy move. */ - if (((pcity = tile_city(def_tile)) - && is_action_enabled_unit_on_city(ACTION_CONQUER_CITY, - punit, pcity) - && unit_perform_action(unit_owner(punit), punit->id, pcity->id, - 0, "", - ACTION_CONQUER_CITY, ACT_REQ_RULES)) - || ((pcity = tile_city(def_tile)) - && is_action_enabled_unit_on_city(ACTION_CONQUER_CITY2, - punit, pcity) - && unit_perform_action(unit_owner(punit), punit->id, pcity->id, - 0, "", - ACTION_CONQUER_CITY2, ACT_REQ_RULES)) - || (unit_transported(punit) - && is_action_enabled_unit_on_tile(ACTION_TRANSPORT_DISEMBARK1, - punit, def_tile, NULL) - && unit_perform_action(unit_owner(punit), punit->id, - tile_index(def_tile), 0, "", - ACTION_TRANSPORT_DISEMBARK1, - ACT_REQ_RULES)) - || (unit_transported(punit) - && is_action_enabled_unit_on_tile(ACTION_TRANSPORT_DISEMBARK2, - punit, def_tile, NULL) - && unit_perform_action(unit_owner(punit), punit->id, - tile_index(def_tile), 0, "", - ACTION_TRANSPORT_DISEMBARK2, - ACT_REQ_RULES)) - || (tile_has_claimable_base(def_tile, unit_type_get(punit)) - && is_action_enabled_unit_on_extras(ACTION_CONQUER_EXTRAS, - punit, def_tile, NULL) - && unit_perform_action(unit_owner(punit), punit->id, - tile_index(def_tile), 0, "", - ACTION_CONQUER_EXTRAS, - ACT_REQ_RULES)) - || (tile_has_claimable_base(def_tile, unit_type_get(punit)) - && is_action_enabled_unit_on_extras(ACTION_CONQUER_EXTRAS2, - punit, def_tile, NULL) - && unit_perform_action(unit_owner(punit), punit->id, - tile_index(def_tile), 0, "", - ACTION_CONQUER_EXTRAS2, - ACT_REQ_RULES)) - || (unit_can_enter_hut(punit, def_tile) - && is_action_enabled_unit_on_tile(ACTION_HUT_ENTER, - punit, def_tile, NULL) - && unit_perform_action(unit_owner(punit), punit->id, - tile_index(def_tile), 0, "", - ACTION_HUT_ENTER, - ACT_REQ_RULES)) - || (unit_can_enter_hut(punit, def_tile) - && is_action_enabled_unit_on_tile(ACTION_HUT_ENTER2, - punit, def_tile, NULL) - && unit_perform_action(unit_owner(punit), punit->id, - tile_index(def_tile), 0, "", - ACTION_HUT_ENTER2, - ACT_REQ_RULES)) - || (HUT_FRIGHTEN == unit_class_get(punit)->hut_behavior - && unit_can_displace_hut(punit, def_tile) - && is_action_enabled_unit_on_tile(ACTION_HUT_FRIGHTEN, - punit, def_tile, NULL) - && unit_perform_action(unit_owner(punit), punit->id, - tile_index(def_tile), 0, "", - ACTION_HUT_FRIGHTEN, - ACT_REQ_RULES)) - || (HUT_FRIGHTEN == unit_class_get(punit)->hut_behavior - && unit_can_displace_hut(punit, def_tile) - && is_action_enabled_unit_on_tile(ACTION_HUT_FRIGHTEN2, - punit, def_tile, NULL) - && unit_perform_action(unit_owner(punit), punit->id, - tile_index(def_tile), 0, "", - ACTION_HUT_FRIGHTEN2, - ACT_REQ_RULES)) - || (unit_move_handling(punit, def_tile, FALSE, TRUE))) { + if ((NULL != action_auto_perf_unit_do(AAPC_POST_ACTION, punit, + NULL, NULL, paction, + def_tile, tile_city(def_tile), + NULL, NULL)) + || (unit_is_alive(winner_id) + && unit_move_handling(punit, def_tile, FALSE, TRUE))) { int mcost = MAX(0, full_moves - punit->moves_left - SINGLE_MOVE); /* Move cost is bigger of attack (SINGLE_MOVE) and occupying move costs. diff --git a/tools/ruleutil/rulesave.c b/tools/ruleutil/rulesave.c index 25d5ab1af2..b6f2ffec00 100644 --- a/tools/ruleutil/rulesave.c +++ b/tools/ruleutil/rulesave.c @@ -952,6 +952,37 @@ static bool save_action_blocked_by(struct section_file *sfile, return TRUE; } +/**********************************************************************//** + Save what actions an actor under certain circumstances will be forced to + perform after successfully performing this action. +**************************************************************************/ +static bool save_action_post_success_force(struct section_file *sfile, + int performer_slot, + struct action *paction) +{ + char action_list_path[100]; + + if (action_post_success_forced_ruleset_var_name(paction) == NULL) { + /* Not relevant. */ + return TRUE; + } + + if (action_enabler_list_size(action_enablers_for_action(paction->id)) + == 0) { + /* Don't save value for actions that aren't enabled. */ + return TRUE; + } + + fc_snprintf(action_list_path, sizeof(action_list_path), + "actions.%s", + action_post_success_forced_ruleset_var_name(paction)); + if (!save_action_auto_actions(sfile, performer_slot, action_list_path)) { + return FALSE; + } + + return TRUE; +} + /**********************************************************************//** Save game.ruleset **************************************************************************/ @@ -1198,6 +1229,19 @@ static bool save_game_ruleset(const char *filename, const char *name) return FALSE; } + if (!save_action_post_success_force(sfile, ACTION_AUTO_POST_BRIBE, + action_by_number( + ACTION_SPY_BRIBE_UNIT))) { + log_error("Didn't save all post success forced actions."); + return FALSE; + } + + if (!save_action_post_success_force(sfile, ACTION_AUTO_POST_ATTACK, + action_by_number(ACTION_ATTACK))) { + log_error("Didn't save all post success forced actions."); + return FALSE; + } + save_default_bool(sfile, game.info.poison_empties_food_stock, RS_DEFAULT_POISON_EMPTIES_FOOD_STOCK, "actions.poison_empties_food_stock", NULL); -- 2.20.1