From 93ec29de4f43f14a92e2cd0ee5c4a09fd3cf06c2 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Mon, 18 Sep 2023 12:54:34 +0300 Subject: [PATCH 24/24] Fake Generalize "Attack" and "Suicide Attack" actions Add second action for each. Requested by Lexxie See osdn #42688 Signed-off-by: Marko Lindqvist --- common/actions.c | 41 ++++++++++++++-- common/actions.h | 111 +++++++++++++++++++++---------------------- common/fc_types.h | 2 +- doc/README.actions | 14 +++++- server/actiontools.c | 8 ++-- server/ruleset.c | 5 ++ 6 files changed, 112 insertions(+), 69 deletions(-) diff --git a/common/actions.c b/common/actions.c index 2d4d4fef70..356e3c1773 100644 --- a/common/actions.c +++ b/common/actions.c @@ -1265,10 +1265,22 @@ static void hard_code_actions(void) * tells it to move. */ MAK_FORCED, 1, 1, FALSE); + actions[ACTION_ATTACK2] = + unit_action_new(ACTION_ATTACK2, ACTRES_ATTACK, + FALSE, TRUE, + /* Tries a forced move if the target unit's tile has + * no non-allied units and the occupychance dice roll + * tells it to move. */ + MAK_FORCED, + 1, 1, FALSE); actions[ACTION_SUICIDE_ATTACK] = unit_action_new(ACTION_SUICIDE_ATTACK, ACTRES_ATTACK, FALSE, TRUE, MAK_FORCED, 1, 1, TRUE); + actions[ACTION_SUICIDE_ATTACK2] = + unit_action_new(ACTION_SUICIDE_ATTACK2, ACTRES_ATTACK, + FALSE, TRUE, + MAK_FORCED, 1, 1, TRUE); actions[ACTION_WIPE_UNITS] = unit_action_new(ACTION_WIPE_UNITS, ACTRES_WIPE_UNITS, FALSE, TRUE, @@ -1513,16 +1525,14 @@ static void hard_code_actions(void) /* The structure even for these need to be created, for * the action_id_rule_name() to work on iterations. */ + + /* actions[ACTION_UNUSED_1] = unit_action_new(ACTION_UNUSED_1, ACTRES_NONE, FALSE, FALSE, MAK_UNREPRESENTABLE, 0, 0, FALSE); - actions[ACTION_UNUSED_2] - = unit_action_new(ACTION_UNUSED_2, ACTRES_NONE, - FALSE, FALSE, - MAK_UNREPRESENTABLE, - 0, 0, FALSE); + */ } /**********************************************************************//** @@ -6744,8 +6754,12 @@ const char *action_ui_name_ruleset_var_name(int act) return "ui_name_airlift_unit"; case ACTION_ATTACK: return "ui_name_attack"; + case ACTION_ATTACK2: + return "ui_name_attack_2"; case ACTION_SUICIDE_ATTACK: return "ui_name_suicide_attack"; + case ACTION_SUICIDE_ATTACK2: + return "ui_name_suicide_attack_2"; case ACTION_WIPE_UNITS: return "ui_name_wipe_units"; case ACTION_STRIKE_BUILDING: @@ -7046,9 +7060,11 @@ const char *action_ui_name_default(int act) /* TRANS: _Airlift to City (100% chance of success). */ return N_("%sAirlift to City%s"); case ACTION_ATTACK: + case ACTION_ATTACK2: /* TRANS: _Attack (100% chance of success). */ return N_("%sAttack%s"); case ACTION_SUICIDE_ATTACK: + case ACTION_SUICIDE_ATTACK2: /* TRANS: _Suicide Attack (100% chance of success). */ return N_("%sSuicide Attack%s"); case ACTION_WIPE_UNITS: @@ -7244,7 +7260,9 @@ const char *action_min_range_ruleset_var_name(int act) case ACTION_PARADROP_ENTER_CONQUER: case ACTION_AIRLIFT: case ACTION_ATTACK: + case ACTION_ATTACK2: case ACTION_SUICIDE_ATTACK: + case ACTION_SUICIDE_ATTACK2: case ACTION_WIPE_UNITS: case ACTION_STRIKE_BUILDING: case ACTION_STRIKE_PRODUCTION: @@ -7473,7 +7491,9 @@ const char *action_max_range_ruleset_var_name(int act) case ACTION_PARADROP_ENTER: case ACTION_PARADROP_ENTER_CONQUER: case ACTION_ATTACK: + case ACTION_ATTACK2: case ACTION_SUICIDE_ATTACK: + case ACTION_SUICIDE_ATTACK2: case ACTION_WIPE_UNITS: case ACTION_STRIKE_BUILDING: case ACTION_STRIKE_PRODUCTION: @@ -7719,7 +7739,9 @@ const char *action_target_kind_ruleset_var_name(int act) case ACTION_PARADROP_ENTER_CONQUER: case ACTION_AIRLIFT: case ACTION_ATTACK: + case ACTION_ATTACK2: case ACTION_SUICIDE_ATTACK: + case ACTION_SUICIDE_ATTACK2: case ACTION_WIPE_UNITS: case ACTION_STRIKE_BUILDING: case ACTION_STRIKE_PRODUCTION: @@ -8156,7 +8178,9 @@ const char *action_actor_consuming_always_ruleset_var_name(action_id act) case ACTION_PARADROP_ENTER_CONQUER: case ACTION_AIRLIFT: case ACTION_ATTACK: + case ACTION_ATTACK2: case ACTION_SUICIDE_ATTACK: + case ACTION_SUICIDE_ATTACK2: case ACTION_WIPE_UNITS: case ACTION_STRIKE_BUILDING: case ACTION_STRIKE_PRODUCTION: @@ -8276,8 +8300,12 @@ const char *action_blocked_by_ruleset_var_name(const struct action *act) return "nuke_units_blocked_by"; case ACTION_ATTACK: return "attack_blocked_by"; + case ACTION_ATTACK2: + return "attack_2_blocked_by"; case ACTION_SUICIDE_ATTACK: return "suicide_attack_blocked_by"; + case ACTION_SUICIDE_ATTACK2: + return "suicide_attack_2_blocked_by"; case ACTION_WIPE_UNITS: return "wipe_units_blocked_by"; case ACTION_CONQUER_CITY: @@ -8425,6 +8453,8 @@ action_post_success_forced_ruleset_var_name(const struct action *act) return "bribe_unit_post_success_forced_actions"; case ACTION_ATTACK: return "attack_post_success_forced_actions"; + case ACTION_ATTACK2: + return "attack_2_post_success_forced_actions"; case ACTION_WIPE_UNITS: return "wipe_units_post_success_forced_actions"; case ACTION_MARKETPLACE: @@ -8436,6 +8466,7 @@ action_post_success_forced_ruleset_var_name(const struct action *act) case ACTION_NUKE_CITY: case ACTION_NUKE_UNITS: case ACTION_SUICIDE_ATTACK: + case ACTION_SUICIDE_ATTACK2: case ACTION_CONQUER_CITY: case ACTION_CONQUER_CITY2: case ACTION_CONQUER_CITY3: diff --git a/common/actions.h b/common/actions.h index 5d10ecb524..e19773c713 100644 --- a/common/actions.h +++ b/common/actions.h @@ -35,12 +35,7 @@ extern "C" { * break; */ #define ASSERT_UNUSED_ACTION_CASES \ - case ACTION_UNUSED_1: \ - fc_assert_msg(FALSE, "ACTION_UNUSED_1"); \ - break; \ - case ACTION_UNUSED_2: \ - fc_assert_msg(FALSE, "ACTION_UNUSED_2"); \ - break; + #define SPECENUM_NAME action_actor_kind #define SPECENUM_VALUE0 AAK_UNIT @@ -145,51 +140,50 @@ const char *gen_action_name_update_cb(const char *old_name); #define SPECENUM_VALUE44NAME "Airlift Unit" #define SPECENUM_VALUE45 ACTION_ATTACK #define SPECENUM_VALUE45NAME "Attack" -#define SPECENUM_VALUE46 ACTION_SUICIDE_ATTACK -#define SPECENUM_VALUE46NAME "Suicide Attack" -#define SPECENUM_VALUE47 ACTION_STRIKE_BUILDING -#define SPECENUM_VALUE47NAME "Surgical Strike Building" -#define SPECENUM_VALUE48 ACTION_STRIKE_PRODUCTION -#define SPECENUM_VALUE48NAME "Surgical Strike Production" -#define SPECENUM_VALUE49 ACTION_CONQUER_CITY -#define SPECENUM_VALUE49NAME "Conquer City" -#define SPECENUM_VALUE50 ACTION_CONQUER_CITY2 -#define SPECENUM_VALUE50NAME "Conquer City 2" -#define SPECENUM_VALUE51 ACTION_CONQUER_CITY3 -#define SPECENUM_VALUE51NAME "Conquer City 3" -#define SPECENUM_VALUE52 ACTION_CONQUER_CITY4 -#define SPECENUM_VALUE52NAME "Conquer City 4" -#define SPECENUM_VALUE53 ACTION_BOMBARD -#define SPECENUM_VALUE53NAME "Bombard" -#define SPECENUM_VALUE54 ACTION_BOMBARD2 -#define SPECENUM_VALUE54NAME "Bombard 2" -#define SPECENUM_VALUE55 ACTION_BOMBARD3 -#define SPECENUM_VALUE55NAME "Bombard 3" -#define SPECENUM_VALUE56 ACTION_BOMBARD_LETHAL -#define SPECENUM_VALUE56NAME "Bombard Lethal" -#define SPECENUM_VALUE57 ACTION_FORTIFY -#define SPECENUM_VALUE57NAME "Fortify" -#define SPECENUM_VALUE58 ACTION_CULTIVATE -#define SPECENUM_VALUE58NAME "Cultivate" -#define SPECENUM_VALUE59 ACTION_PLANT -#define SPECENUM_VALUE59NAME "Plant" -#define SPECENUM_VALUE60 ACTION_TRANSFORM_TERRAIN -#define SPECENUM_VALUE60NAME "Transform Terrain" -#define SPECENUM_VALUE61 ACTION_ROAD -#define SPECENUM_VALUE61NAME "Build Road" -#define SPECENUM_VALUE62 ACTION_IRRIGATE -#define SPECENUM_VALUE62NAME "Build Irrigation" -#define SPECENUM_VALUE63 ACTION_MINE -#define SPECENUM_VALUE63NAME "Build Mine" -#define SPECENUM_VALUE64 ACTION_BASE -#define SPECENUM_VALUE64NAME "Build Base" -#define SPECENUM_VALUE65 ACTION_PILLAGE -#define SPECENUM_VALUE65NAME "Pillage" -/* TODO: Rearrange actions to get rid of these */ -#define SPECENUM_VALUE66 ACTION_UNUSED_1 -#define SPECENUM_VALUE66NAME "Unused1" -#define SPECENUM_VALUE67 ACTION_UNUSED_2 -#define SPECENUM_VALUE67NAME "Unused2" +#define SPECENUM_VALUE46 ACTION_ATTACK2 +#define SPECENUM_VALUE46NAME "Attack 2" +#define SPECENUM_VALUE47 ACTION_SUICIDE_ATTACK +#define SPECENUM_VALUE47NAME "Suicide Attack" +#define SPECENUM_VALUE48 ACTION_SUICIDE_ATTACK2 +#define SPECENUM_VALUE48NAME "Suicide Attack 2" +#define SPECENUM_VALUE49 ACTION_STRIKE_BUILDING +#define SPECENUM_VALUE49NAME "Surgical Strike Building" +#define SPECENUM_VALUE50 ACTION_STRIKE_PRODUCTION +#define SPECENUM_VALUE50NAME "Surgical Strike Production" +#define SPECENUM_VALUE51 ACTION_CONQUER_CITY +#define SPECENUM_VALUE51NAME "Conquer City" +#define SPECENUM_VALUE52 ACTION_CONQUER_CITY2 +#define SPECENUM_VALUE52NAME "Conquer City 2" +#define SPECENUM_VALUE53 ACTION_CONQUER_CITY3 +#define SPECENUM_VALUE53NAME "Conquer City 3" +#define SPECENUM_VALUE54 ACTION_CONQUER_CITY4 +#define SPECENUM_VALUE54NAME "Conquer City 4" +#define SPECENUM_VALUE55 ACTION_BOMBARD +#define SPECENUM_VALUE55NAME "Bombard" +#define SPECENUM_VALUE56 ACTION_BOMBARD2 +#define SPECENUM_VALUE56NAME "Bombard 2" +#define SPECENUM_VALUE57 ACTION_BOMBARD3 +#define SPECENUM_VALUE57NAME "Bombard 3" +#define SPECENUM_VALUE58 ACTION_BOMBARD_LETHAL +#define SPECENUM_VALUE58NAME "Bombard Lethal" +#define SPECENUM_VALUE59 ACTION_FORTIFY +#define SPECENUM_VALUE59NAME "Fortify" +#define SPECENUM_VALUE60 ACTION_CULTIVATE +#define SPECENUM_VALUE60NAME "Cultivate" +#define SPECENUM_VALUE61 ACTION_PLANT +#define SPECENUM_VALUE61NAME "Plant" +#define SPECENUM_VALUE62 ACTION_TRANSFORM_TERRAIN +#define SPECENUM_VALUE62NAME "Transform Terrain" +#define SPECENUM_VALUE63 ACTION_ROAD +#define SPECENUM_VALUE63NAME "Build Road" +#define SPECENUM_VALUE64 ACTION_IRRIGATE +#define SPECENUM_VALUE64NAME "Build Irrigation" +#define SPECENUM_VALUE65 ACTION_MINE +#define SPECENUM_VALUE65NAME "Build Mine" +#define SPECENUM_VALUE66 ACTION_BASE +#define SPECENUM_VALUE66NAME "Build Base" +#define SPECENUM_VALUE67 ACTION_PILLAGE +#define SPECENUM_VALUE67NAME "Pillage" #define SPECENUM_VALUE68 ACTION_TRANSPORT_BOARD #define SPECENUM_VALUE68NAME "Transport Board" #define SPECENUM_VALUE69 ACTION_TRANSPORT_BOARD2 @@ -447,13 +441,12 @@ struct action_enabler } \ } +/* Filter out unused action slots, in versions where those exist */ #define action_iterate(_act_) \ { \ - action_iterate_all(_act_) { \ - if (_act_ != ACTION_UNUSED_1 && _act_ != ACTION_UNUSED_2) { + action_iterate_all(_act_) { #define action_iterate_end \ - } \ } action_iterate_all_end; \ } @@ -594,16 +587,18 @@ action_auto_perf_iterate(_act_perf_) { \ action_array_iterate_end /* Hard coded location of action auto performers. Used for conversion while - * action auto performers aren't directly exposed to the ruleset. */ + * action auto performers aren't directly exposed to the ruleset. + * Remember to update also MAX_NUM_ACTION_AUTO_PERFORMERS when changing these. */ #define ACTION_AUTO_UPKEEP_FOOD 0 #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 -#define ACTION_AUTO_ESCAPE_CITY 6 -#define ACTION_AUTO_ESCAPE_STACK 7 -#define ACTION_AUTO_POST_WIPE_UNITS 8 +#define ACTION_AUTO_POST_ATTACK2 6 +#define ACTION_AUTO_ESCAPE_CITY 7 +#define ACTION_AUTO_ESCAPE_STACK 8 +#define ACTION_AUTO_POST_WIPE_UNITS 9 /* Initialization */ void actions_init(void); diff --git a/common/fc_types.h b/common/fc_types.h index cc72905cfd..ea632f7f8d 100644 --- a/common/fc_types.h +++ b/common/fc_types.h @@ -51,7 +51,7 @@ extern "C" { #define MAX_GOODS_TYPES 25 #define MAX_DISASTER_TYPES 10 #define MAX_ACHIEVEMENT_TYPES 40 -#define MAX_NUM_ACTION_AUTO_PERFORMERS 9 +#define MAX_NUM_ACTION_AUTO_PERFORMERS 10 #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/doc/README.actions b/doc/README.actions index 1e77403eda..5963bc0cd1 100644 --- a/doc/README.actions +++ b/doc/README.actions @@ -832,10 +832,17 @@ Actions done by a unit against all units at a tile - it is in a city - it is on a tile with a native Extra +"Attack 2" + * UI name can be set using ui_name_attack_2 + * any action listed in attack_2_blocked_by must be impossible + * forced actions after success can be set with + attack_2_post_success_forced_actions + * See "Attack" for everything else. + "Suicide Attack" * UI name can be set using ui_name_suicide_attack - * spends the actor unit * any action listed in suicide_attack_blocked_by must be impossible + * spends the actor unit * 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 (!) @@ -852,6 +859,11 @@ Actions done by a unit against all units at a tile - it is in a city - it is on a tile with a native Extra +"Suicide Attack 2" + * UI name can be set using ui_name_suicide_attack_2 + * any action listed in suicide_attack_2_blocked_by must be impossible + * See "Suicide Attack" for everything else. + "Wipe Units" * UI name can be set using ui_name_wipe_units * any action listed in wipe_units_blocked_by must be impossible diff --git a/server/actiontools.c b/server/actiontools.c index 6e28ae7a83..82f91c6834 100644 --- a/server/actiontools.c +++ b/server/actiontools.c @@ -1005,8 +1005,8 @@ action_auto_perf_unit_do(const enum action_auto_perf_cause cause, const struct unit *tgt_unit; const struct action_auto_perf *autoperf - = action_auto_perf_unit_sel(cause, actor, other_player, - eval_output, eval_action); + = action_auto_perf_unit_sel(cause, actor, other_player, + eval_output, eval_action); if (!autoperf) { /* No matching Action Auto Performer. */ @@ -1106,8 +1106,8 @@ action_auto_perf_unit_prob(const enum action_auto_perf_cause cause, const struct unit *tgt_unit; const struct action_auto_perf *autoperf - = action_auto_perf_unit_sel(cause, actor, other_player, - eval_output, eval_action); + = action_auto_perf_unit_sel(cause, actor, other_player, + eval_output, eval_action); if (!autoperf) { /* No matching Action Auto Performer. */ diff --git a/server/ruleset.c b/server/ruleset.c index 09d3d9bc48..ae6794079b 100644 --- a/server/ruleset.c +++ b/server/ruleset.c @@ -7928,6 +7928,11 @@ static bool load_ruleset_actions(struct section_file *file, action_by_number( ACTION_ATTACK))) { ok = FALSE; + } else if (!load_action_post_success_force(file, filename, + ACTION_AUTO_POST_ATTACK2, + action_by_number( + ACTION_ATTACK2))) { + ok = FALSE; } else if (!load_action_post_success_force(file, filename, ACTION_AUTO_POST_WIPE_UNITS, action_by_number( -- 2.40.1