Project

Profile

Help

HostedRedmine.com has moved to the Planio platform. All logins and passwords remained the same. All users will be able to login and use Redmine just as before. *Read more...*

Feature #752058 ยป 0001-Introduce-action-has-a-sub-target-check.patch

Sveinung Kvilhaugsvik, 2018-05-08 10:25 AM

View differences:

common/actions.c
static struct action *action_new(enum gen_action id,
enum action_target_kind target_kind,
bool hostile, bool requires_details,
bool hostile, enum act_tgt_compl tgt_compl,
bool rare_pop_up,
bool unitwaittime_controlled,
const int min_distance,
......
**************************************************************************/
static void hard_code_actions(void)
{
actions[ACTION_SPY_POISON] = action_new(ACTION_SPY_POISON, ATK_CITY,
TRUE, FALSE, FALSE, TRUE,
0, 1, TRUE);
actions[ACTION_SPY_POISON] =
action_new(ACTION_SPY_POISON, ATK_CITY,
TRUE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, TRUE);
actions[ACTION_SPY_POISON_ESC] =
action_new(ACTION_SPY_POISON_ESC, ATK_CITY,
TRUE, FALSE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, FALSE);
actions[ACTION_SPY_SABOTAGE_UNIT] =
action_new(ACTION_SPY_SABOTAGE_UNIT, ATK_UNIT,
TRUE, FALSE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, TRUE);
actions[ACTION_SPY_SABOTAGE_UNIT_ESC] =
action_new(ACTION_SPY_SABOTAGE_UNIT_ESC, ATK_UNIT,
TRUE, FALSE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, FALSE);
actions[ACTION_SPY_BRIBE_UNIT] =
action_new(ACTION_SPY_BRIBE_UNIT, ATK_UNIT,
TRUE, FALSE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, FALSE);
actions[ACTION_SPY_SABOTAGE_CITY] =
action_new(ACTION_SPY_SABOTAGE_CITY, ATK_CITY,
TRUE, FALSE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, TRUE);
actions[ACTION_SPY_SABOTAGE_CITY_ESC] =
action_new(ACTION_SPY_SABOTAGE_CITY_ESC, ATK_CITY,
TRUE, FALSE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, FALSE);
actions[ACTION_SPY_TARGETED_SABOTAGE_CITY] =
action_new(ACTION_SPY_TARGETED_SABOTAGE_CITY, ATK_CITY,
TRUE, TRUE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_MANDATORY, FALSE, TRUE,
0, 1, TRUE);
actions[ACTION_SPY_TARGETED_SABOTAGE_CITY_ESC] =
action_new(ACTION_SPY_TARGETED_SABOTAGE_CITY_ESC, ATK_CITY,
TRUE, TRUE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_MANDATORY, FALSE, TRUE,
0, 1, FALSE);
actions[ACTION_SPY_INCITE_CITY] =
action_new(ACTION_SPY_INCITE_CITY, ATK_CITY,
TRUE, FALSE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, TRUE);
actions[ACTION_SPY_INCITE_CITY_ESC] =
action_new(ACTION_SPY_INCITE_CITY_ESC, ATK_CITY,
TRUE, FALSE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, FALSE);
actions[ACTION_ESTABLISH_EMBASSY] =
action_new(ACTION_ESTABLISH_EMBASSY, ATK_CITY,
FALSE, FALSE, FALSE, TRUE,
FALSE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, FALSE);
actions[ACTION_ESTABLISH_EMBASSY_STAY] =
action_new(ACTION_ESTABLISH_EMBASSY_STAY, ATK_CITY,
FALSE, FALSE, FALSE, TRUE,
FALSE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, TRUE);
actions[ACTION_SPY_STEAL_TECH] =
action_new(ACTION_SPY_STEAL_TECH, ATK_CITY,
TRUE, FALSE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, TRUE);
actions[ACTION_SPY_STEAL_TECH_ESC] =
action_new(ACTION_SPY_STEAL_TECH_ESC, ATK_CITY,
TRUE, FALSE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, FALSE);
actions[ACTION_SPY_TARGETED_STEAL_TECH] =
action_new(ACTION_SPY_TARGETED_STEAL_TECH, ATK_CITY,
TRUE, TRUE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_MANDATORY, FALSE, TRUE,
0, 1, TRUE);
actions[ACTION_SPY_TARGETED_STEAL_TECH_ESC] =
action_new(ACTION_SPY_TARGETED_STEAL_TECH_ESC, ATK_CITY,
TRUE, TRUE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_MANDATORY, FALSE, TRUE,
0, 1, FALSE);
actions[ACTION_SPY_INVESTIGATE_CITY] =
action_new(ACTION_SPY_INVESTIGATE_CITY, ATK_CITY,
TRUE, FALSE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, FALSE);
actions[ACTION_INV_CITY_SPEND] =
action_new(ACTION_INV_CITY_SPEND, ATK_CITY,
TRUE, FALSE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, TRUE);
actions[ACTION_SPY_STEAL_GOLD] =
action_new(ACTION_SPY_STEAL_GOLD, ATK_CITY,
TRUE, FALSE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, TRUE);
actions[ACTION_SPY_STEAL_GOLD_ESC] =
action_new(ACTION_SPY_STEAL_GOLD_ESC, ATK_CITY,
TRUE, FALSE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, FALSE);
actions[ACTION_TRADE_ROUTE] =
action_new(ACTION_TRADE_ROUTE, ATK_CITY,
FALSE, FALSE, FALSE, TRUE,
FALSE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, TRUE);
actions[ACTION_MARKETPLACE] =
action_new(ACTION_MARKETPLACE, ATK_CITY,
FALSE, FALSE, FALSE, TRUE,
FALSE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, TRUE);
actions[ACTION_HELP_WONDER] =
action_new(ACTION_HELP_WONDER, ATK_CITY,
FALSE, FALSE, FALSE, TRUE,
FALSE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, TRUE);
actions[ACTION_CAPTURE_UNITS] =
action_new(ACTION_CAPTURE_UNITS, ATK_UNITS,
TRUE, FALSE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
/* A single domestic unit at the target tile will make the
* action illegal. It must therefore be performed from
* another tile. */
......
FALSE);
actions[ACTION_FOUND_CITY] =
action_new(ACTION_FOUND_CITY, ATK_TILE,
FALSE, FALSE, TRUE, TRUE,
FALSE, ACT_TGT_COMPL_SIMPLE, TRUE, TRUE,
/* Illegal to perform to a target on another tile.
* Reason: The Freeciv code assumes that the city founding
* unit is located at the tile were the new city is
......
TRUE);
actions[ACTION_JOIN_CITY] =
action_new(ACTION_JOIN_CITY, ATK_CITY,
FALSE, FALSE, TRUE, TRUE,
FALSE, ACT_TGT_COMPL_SIMPLE, TRUE, TRUE,
0, 1, TRUE);
actions[ACTION_STEAL_MAPS] =
action_new(ACTION_STEAL_MAPS, ATK_CITY,
TRUE, FALSE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, TRUE);
actions[ACTION_STEAL_MAPS_ESC] =
action_new(ACTION_STEAL_MAPS_ESC, ATK_CITY,
TRUE, FALSE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, FALSE);
actions[ACTION_BOMBARD] =
action_new(ACTION_BOMBARD,
/* FIXME: Target is actually Units + City */
ATK_UNITS,
TRUE, FALSE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
/* A single domestic unit at the target tile will make the
* action illegal. It must therefore be performed from
* another tile. */
......
FALSE);
actions[ACTION_SPY_NUKE] =
action_new(ACTION_SPY_NUKE, ATK_CITY,
TRUE, FALSE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, TRUE);
actions[ACTION_SPY_NUKE_ESC] =
action_new(ACTION_SPY_NUKE_ESC, ATK_CITY,
TRUE, FALSE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, FALSE);
actions[ACTION_NUKE] =
action_new(ACTION_NUKE,
/* FIXME: Target is actually Tile + Units + City */
ATK_TILE,
TRUE, FALSE, TRUE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, TRUE, TRUE,
0, 1, TRUE);
actions[ACTION_DESTROY_CITY] =
action_new(ACTION_DESTROY_CITY, ATK_CITY,
TRUE, FALSE, TRUE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, TRUE, TRUE,
0, 1, FALSE);
actions[ACTION_EXPEL_UNIT] =
action_new(ACTION_EXPEL_UNIT, ATK_UNIT,
TRUE, FALSE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, FALSE);
actions[ACTION_RECYCLE_UNIT] =
action_new(ACTION_RECYCLE_UNIT, ATK_CITY,
FALSE, FALSE, TRUE, TRUE,
FALSE, ACT_TGT_COMPL_SIMPLE, TRUE, TRUE,
/* Illegal to perform to a target on another tile to
* keep the rules exactly as they were for now. */
0, 1,
TRUE);
actions[ACTION_DISBAND_UNIT] =
action_new(ACTION_DISBAND_UNIT, ATK_SELF,
FALSE, FALSE, TRUE, TRUE,
FALSE, ACT_TGT_COMPL_SIMPLE, TRUE, TRUE,
0, 0, TRUE);
actions[ACTION_HOME_CITY] =
action_new(ACTION_HOME_CITY, ATK_CITY,
FALSE, FALSE, TRUE, FALSE,
FALSE, ACT_TGT_COMPL_SIMPLE, TRUE, FALSE,
/* Illegal to perform to a target on another tile to
* keep the rules exactly as they were for now. */
0, 0, FALSE);
actions[ACTION_UPGRADE_UNIT] =
action_new(ACTION_UPGRADE_UNIT, ATK_CITY,
FALSE, FALSE, TRUE, TRUE,
FALSE, ACT_TGT_COMPL_SIMPLE, TRUE, TRUE,
/* Illegal to perform to a target on another tile to
* keep the rules exactly as they were for now. */
0, 0,
FALSE);
actions[ACTION_PARADROP] =
action_new(ACTION_PARADROP, ATK_TILE,
FALSE, FALSE, TRUE, TRUE,
FALSE, ACT_TGT_COMPL_SIMPLE, TRUE, TRUE,
1,
/* Still limited by each unit type's paratroopers_range
* field. */
......
FALSE);
actions[ACTION_AIRLIFT] =
action_new(ACTION_AIRLIFT, ATK_CITY,
FALSE, FALSE, TRUE, TRUE,
FALSE, ACT_TGT_COMPL_SIMPLE, TRUE, TRUE,
1, ACTION_DISTANCE_UNLIMITED,
FALSE);
actions[ACTION_ATTACK] =
......
* setting, each or any *non transported* unit at the
* target tile. */
ATK_UNITS,
TRUE, FALSE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
1, 1, FALSE);
actions[ACTION_CONQUER_CITY] =
action_new(ACTION_CONQUER_CITY, ATK_CITY,
TRUE, FALSE, FALSE, TRUE,
TRUE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
1, 1, FALSE);
actions[ACTION_HEAL_UNIT] =
action_new(ACTION_HEAL_UNIT, ATK_UNIT,
FALSE, FALSE, FALSE, TRUE,
FALSE, ACT_TGT_COMPL_SIMPLE, FALSE, TRUE,
0, 1, FALSE);
actions[ACTION_TRANSFORM_TERRAIN] =
action_new(ACTION_TRANSFORM_TERRAIN, ATK_TILE,
FALSE, FALSE, TRUE, FALSE,
FALSE, ACT_TGT_COMPL_SIMPLE, TRUE, FALSE,
0, 0, FALSE);
actions[ACTION_IRRIGATE_TF] =
action_new(ACTION_IRRIGATE_TF, ATK_TILE,
FALSE, FALSE, TRUE, FALSE,
FALSE, ACT_TGT_COMPL_SIMPLE, TRUE, FALSE,
0, 0, FALSE);
actions[ACTION_MINE_TF] =
action_new(ACTION_MINE_TF, ATK_TILE,
FALSE, FALSE, TRUE, FALSE,
FALSE, ACT_TGT_COMPL_SIMPLE, TRUE, FALSE,
0, 0, FALSE);
actions[ACTION_PILLAGE] =
action_new(ACTION_PILLAGE, ATK_TILE,
FALSE, FALSE, TRUE, FALSE,
FALSE, ACT_TGT_COMPL_FLEXIBLE, TRUE, FALSE,
0, 0, FALSE);
actions[ACTION_FORTIFY] =
action_new(ACTION_FORTIFY, ATK_SELF,
FALSE, FALSE, TRUE, FALSE,
FALSE, ACT_TGT_COMPL_SIMPLE, TRUE, FALSE,
0, 0, FALSE);
actions[ACTION_ROAD] =
action_new(ACTION_ROAD, ATK_TILE,
FALSE, TRUE, TRUE, FALSE,
FALSE, ACT_TGT_COMPL_MANDATORY, TRUE, FALSE,
0, 0, FALSE);
actions[ACTION_CONVERT] =
action_new(ACTION_CONVERT, ATK_SELF,
FALSE, FALSE, TRUE, FALSE,
FALSE, ACT_TGT_COMPL_SIMPLE, TRUE, FALSE,
0, 0, FALSE);
actions[ACTION_BASE] =
action_new(ACTION_BASE, ATK_TILE,
FALSE, TRUE, TRUE, FALSE,
FALSE, ACT_TGT_COMPL_MANDATORY, TRUE, FALSE,
0, 0, FALSE);
}
......
**************************************************************************/
static struct action *action_new(enum gen_action id,
enum action_target_kind target_kind,
bool hostile, bool requires_details,
bool hostile, enum act_tgt_compl tgt_compl,
bool rare_pop_up,
bool unitwaittime_controlled,
const int min_distance,
......
action->target_kind = target_kind;
action->hostile = hostile;
action->requires_details = requires_details;
action->target_complexity = tgt_compl;
action->rare_pop_up = rare_pop_up;
/* The distance between the actor and itself is always 0. */
......
}
/**********************************************************************//**
Returns TRUE iff the specified action allows the player to provide
details in addition to actor and target. Returns FALSE if the action
doesn't support any additional details.
**************************************************************************/
bool action_id_has_complex_target(int action_id)
{
fc_assert_msg(actions[action_id], "Action %d don't exist.", action_id);
return actions[action_id]->target_complexity >= ACT_TGT_COMPL_FLEXIBLE;
}
/**********************************************************************//**
Returns TRUE iff the specified action REQUIRES the player to provide
details in addition to actor and target. Returns FALSE if the action
doesn't support any additional details or if they can be set by Freeciv
......
{
fc_assert_msg(actions[action_id], "Action %d don't exist.", action_id);
return actions[action_id]->requires_details;
return actions[action_id]->target_complexity >= ACT_TGT_COMPL_MANDATORY;
}
/**********************************************************************//**
common/actions.h
/* No action max distance can be bigger than this. */
#define ACTION_DISTANCE_MAX ACTION_DISTANCE_UNLIMITED
/* Action target complexity */
#define SPECENUM_NAME act_tgt_compl
/* The action's target is just the primary target. (Just the tile, unit,
* city, etc). */
#define SPECENUM_VALUE0 ACT_TGT_COMPL_SIMPLE
#define SPECENUM_VALUE0NAME N_("simple")
/* The action's target is complex because its target is the primary target
* and a sub target. (Examples: Tile + Extra and City + Building.) The
* player is able to specify details about this action but the server will
* fill in missing details so a client can choose to not specify the sub
* target. */
#define SPECENUM_VALUE1 ACT_TGT_COMPL_FLEXIBLE
#define SPECENUM_VALUE1NAME N_("flexible")
/* The action's target is complex because its target is the primary target
* and a sub target. (Examples: Tile + Extra and City + Building.) The
* player is required to specify details about this action because the
* server won't fill inn the missing details when unspecified. A client must
* therefore specify the sub target of this action. */
#define SPECENUM_VALUE2 ACT_TGT_COMPL_MANDATORY
#define SPECENUM_VALUE2NAME N_("mandatory")
#include "specenum_gen.h"
struct action
{
enum gen_action id;
......
bool hostile; /* TODO: Should this be a scale in stead? */
/* Is the player required to specify details about this action? Only true
* IFF the action needs details AND the server won't fill them in when
* unspecified. */
bool requires_details;
/* Sub target policy. */
enum act_tgt_compl target_complexity;
/* A unit's ability to perform this action will pop up the action
* selection dialog before the player asks for it only in exceptional
......
bool action_is_hostile(int action_id);
bool action_id_has_complex_target(int action_id);
bool action_requires_details(int action_id);
bool action_id_is_rare_pop_up(int action_id);
    (1-1/1)