From b7a47b88c119c6d7ca7ccbde58ae78612a2ff58c Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Mon, 16 Oct 2023 07:47:49 +0300 Subject: [PATCH 38/38] Add PlayerState requirement type Initial version supports just value "Barbarian" Requested by ihnatus See osdn #41813 Signed-off-by: Marko Lindqvist --- ai/default/daieffects.c | 1 + ai/default/daimilitary.c | 1 + common/fc_types.h | 14 ++++++++ common/player.c | 18 +++++++++++ common/player.h | 2 ++ common/reqtext.c | 18 +++++++++++ common/requirements.c | 65 ++++++++++++++++++++++++++++++++++++++ doc/README.effects | 1 + server/cityturn.c | 3 ++ server/rssanity.c | 1 + tools/ruledit/univ_value.c | 7 ++++ 11 files changed, 131 insertions(+) diff --git a/ai/default/daieffects.c b/ai/default/daieffects.c index 078f393598..811860a6ed 100644 --- a/ai/default/daieffects.c +++ b/ai/default/daieffects.c @@ -869,6 +869,7 @@ bool dai_can_requirement_be_met_in_city(const struct requirement *preq, case VUT_MINLATITUDE: case VUT_MAXLATITUDE: case VUT_PLAYER_FLAG: + case VUT_PLAYER_STATE: /* Beyond player control. */ return FALSE; diff --git a/ai/default/daimilitary.c b/ai/default/daimilitary.c index 6d7014b2eb..1dafcc4648 100644 --- a/ai/default/daimilitary.c +++ b/ai/default/daimilitary.c @@ -446,6 +446,7 @@ tactical_req_cb(const struct req_context *context, case VUT_IMPR_GENUS: case VUT_IMPR_FLAG: case VUT_PLAYER_FLAG: + case VUT_PLAYER_STATE: case VUT_MINCULTURE: case VUT_MINTECHS: case VUT_ORIGINAL_OWNER: diff --git a/common/fc_types.h b/common/fc_types.h index 3541ddab68..1c903880ed 100644 --- a/common/fc_types.h +++ b/common/fc_types.h @@ -572,6 +572,17 @@ const char *ai_level_name_update_cb(const char *old); #define SPECENUM_COUNT CITYS_LAST #include "specenum_gen.h" +/* + * PlayerState requirement types. + * + * Used in the network protocol + */ +#define SPECENUM_NAME plrstate_type +#define SPECENUM_VALUE0 PLRS_BARBARIAN +#define SPECENUM_VALUE0NAME "Barbarian" +#define SPECENUM_COUNT PLRS_LAST +#include "specenum_gen.h" + /* * UnitState requirement property types. * @@ -716,6 +727,7 @@ typedef union { enum ai_level ai_level; enum citytile_type citytile; enum citystatus_type citystatus; + enum plrstate_type plrstate; int minsize; int minculture; int minforeignpct; @@ -870,6 +882,8 @@ typedef union { #define SPECENUM_VALUE54NAME "Wrap" #define SPECENUM_VALUE55 VUT_PLAYER_FLAG #define SPECENUM_VALUE55NAME "PlayerFlag" +#define SPECENUM_VALUE56 VUT_PLAYER_STATE +#define SPECENUM_VALUE56NAME "PlayerState" /* Keep this last. */ #define SPECENUM_COUNT VUT_COUNT diff --git a/common/player.c b/common/player.c index ac833e9d88..e49d59a9b1 100644 --- a/common/player.c +++ b/common/player.c @@ -1980,3 +1980,21 @@ bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag) { return BV_ISSET(pplayer->flags, flag); } + +/*******************************************************************//** + Check if player has given state +***********************************************************************/ +bool player_has_state(const struct player *pplayer, + enum plrstate_type state) +{ + switch (state) { + case PLRS_BARBARIAN: + return is_barbarian(pplayer); + case PLRS_LAST: + fc_assert(state != PLRS_LAST); + break; + } + + fc_assert(plrstate_type_is_valid(state)); + return FALSE; +} diff --git a/common/player.h b/common/player.h index d3f9c96038..12371e017a 100644 --- a/common/player.h +++ b/common/player.h @@ -233,6 +233,8 @@ bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag); #define set_as_human(plr) BV_CLR((plr)->flags, PLRF_AI) #define set_as_ai(plr) BV_SET((plr)->flags, PLRF_AI) +bool player_has_state(const struct player *pplayer, enum plrstate_type state); + struct multiplier_value { /* Value currently in force. */ diff --git a/common/reqtext.c b/common/reqtext.c index f00d6af41c..d078e3371b 100644 --- a/common/reqtext.c +++ b/common/reqtext.c @@ -391,6 +391,24 @@ bool req_text_insert(char *buf, size_t bufsz, struct player *pplayer, } break; + case VUT_PLAYER_STATE: + switch (preq->range) { + case REQ_RANGE_PLAYER: + fc_strlcat(buf, prefix, bufsz); + if (preq->present) { + cat_snprintf(buf, bufsz, _("Applies to \"%s\" players."), + plrstate_type_translated_name(preq->source.value.plrstate)); + } else { + cat_snprintf(buf, bufsz, _("Doesn't apply to \"%s\" players."), + plrstate_type_translated_name(preq->source.value.plrstate)); + } + return TRUE; + default: + /* Not supported. */ + break; + } + break; + case VUT_IMPROVEMENT: switch (preq->range) { case REQ_RANGE_WORLD: diff --git a/common/requirements.c b/common/requirements.c index b190a585be..d371812e55 100644 --- a/common/requirements.c +++ b/common/requirements.c @@ -571,6 +571,12 @@ void universal_value_from_str(struct universal *source, const char *value) return; } break; + case VUT_PLAYER_STATE: + source->value.plrstate = plrstate_type_by_name(value, fc_strcasecmp); + if (source->value.plrstate != PLRS_LAST) { + return; + } + break; case VUT_MINLATITUDE: case VUT_MAXLATITUDE: source->value.latitude = atoi(value); @@ -801,6 +807,9 @@ struct universal universal_by_number(const enum universals_n kind, case VUT_CITYSTATUS: source.value.citystatus = value; return source; + case VUT_PLAYER_STATE: + source.value.plrstate = value; + return source; case VUT_COUNTER: source.value.counter = counter_by_id(value); return source; @@ -948,6 +957,8 @@ int universal_number(const struct universal *source) return source->value.citytile; case VUT_CITYSTATUS: return source->value.citystatus; + case VUT_PLAYER_STATE: + return source->value.plrstate; case VUT_COUNTER: return counter_id(source->value.counter); case VUT_MINLATITUDE: @@ -1088,6 +1099,7 @@ struct requirement req_from_str(const char *type, const char *range, case VUT_DIPLREL_UNITANY: case VUT_AI_LEVEL: case VUT_PLAYER_FLAG: + case VUT_PLAYER_STATE: req.range = REQ_RANGE_PLAYER; break; case VUT_MINYEAR: @@ -1255,6 +1267,7 @@ struct requirement req_from_str(const char *type, const char *range, invalid = req.range != REQ_RANGE_CITY; break; case VUT_PLAYER_FLAG: + case VUT_PLAYER_STATE: invalid = (req.range != REQ_RANGE_PLAYER); break; case VUT_IMPROVEMENT: @@ -1288,6 +1301,7 @@ struct requirement req_from_str(const char *type, const char *range, case VUT_IMPR_GENUS: case VUT_IMPR_FLAG: case VUT_PLAYER_FLAG: + case VUT_PLAYER_STATE: case VUT_GOVERNMENT: case VUT_TERRAIN: case VUT_UTYPE: @@ -2282,6 +2296,46 @@ is_plr_flag_req_active(const struct req_context *context, return TRI_MAYBE; } +/**********************************************************************//** + Determine whether a player state requirement is satisfied in a given + context, ignoring parts of the requirement that can be handled uniformly + for all requirement types. + + context and req must not be null, and req must be a building flag + requirement +**************************************************************************/ +static enum fc_tristate +is_plr_state_req_active(const struct req_context *context, + const struct player *other_player, + const struct requirement *req) +{ + IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_PLAYER_STATE); + + switch (req->range) { + case REQ_RANGE_PLAYER: + return (context->player != NULL + ? BOOL_TO_TRISTATE(player_has_state(context->player, + req->source.value.plrstate)) + : TRI_MAYBE); + case REQ_RANGE_LOCAL: + case REQ_RANGE_CITY: + case REQ_RANGE_TILE: + case REQ_RANGE_CADJACENT: + case REQ_RANGE_ADJACENT: + case REQ_RANGE_TRADE_ROUTE: + case REQ_RANGE_CONTINENT: + case REQ_RANGE_ALLIANCE: + case REQ_RANGE_TEAM: + case REQ_RANGE_WORLD: + case REQ_RANGE_COUNT: + break; + } + + fc_assert_msg(FALSE, "Invalid range %d.", req->range); + + return TRI_MAYBE; +} + /**********************************************************************//** Determine whether a tech requirement is satisfied in a given context, ignoring parts of the requirement that can be handled uniformly for all @@ -5187,6 +5241,7 @@ static struct req_def req_definitions[VUT_COUNT] = { [VUT_IMPR_GENUS] = {is_buildinggenus_req_active, REQUCH_YES}, [VUT_IMPR_FLAG] = {is_buildingflag_req_active, REQUCH_YES}, [VUT_PLAYER_FLAG] = {is_plr_flag_req_active, REQUCH_NO}, + [VUT_PLAYER_STATE] = {is_plr_state_req_active, REQUCH_NO}, [VUT_MAXLATITUDE] = {is_latitude_req_active, REQUCH_YES}, [VUT_MAXTILEUNITS] = {is_maxunitsontile_req_active, REQUCH_NO}, [VUT_MINCALFRAG] = {is_mincalfrag_req_active, REQUCH_NO}, @@ -5700,6 +5755,7 @@ bool universal_never_there(const struct universal *source) case VUT_IMPR_GENUS: case VUT_IMPR_FLAG: case VUT_PLAYER_FLAG: + case VUT_PLAYER_STATE: case VUT_MINSIZE: case VUT_MINCULTURE: case VUT_MINFOREIGNPCT: @@ -6296,6 +6352,8 @@ bool are_universals_equal(const struct universal *psource1, return psource1->value.impr_flag == psource2->value.impr_flag; case VUT_PLAYER_FLAG: return psource1->value.plr_flag == psource2->value.plr_flag; + case VUT_PLAYER_STATE: + return psource1->value.plrstate == psource2->value.plrstate; case VUT_EXTRA: return psource1->value.extra == psource2->value.extra; case VUT_GOOD: @@ -6440,6 +6498,8 @@ const char *universal_rule_name(const struct universal *psource) return impr_flag_id_name(psource->value.impr_flag); case VUT_PLAYER_FLAG: return plr_flag_id_name(psource->value.plr_flag); + case VUT_PLAYER_STATE: + return plrstate_type_name(psource->value.plrstate); case VUT_EXTRA: return extra_rule_name(psource->value.extra); case VUT_GOOD: @@ -6596,6 +6656,11 @@ const char *universal_name_translation(const struct universal *psource, plr_flag_id_translated_name(psource->value.plr_flag), bufsz); return buf; + case VUT_PLAYER_STATE: + fc_strlcat(buf, + plrstate_type_translated_name(psource->value.plrstate), + bufsz); + return buf; case VUT_EXTRA: fc_strlcat(buf, extra_name_translation(psource->value.extra), bufsz); return buf; diff --git a/doc/README.effects b/doc/README.effects index fc93feb1c3..8196be0aad 100644 --- a/doc/README.effects +++ b/doc/README.effects @@ -78,6 +78,7 @@ Nation: World, Alliance, Team, Player NationGroup: World, Alliance, Team, Player Nationality: Traderoute, City PlayerFlag: Player +PlayerState: Player OriginalOwner: City DiplRel: World, Alliance, Team, Player, Local DiplRelTile: Alliance, Team, Player, Local diff --git a/server/cityturn.c b/server/cityturn.c index 985546fcc9..d878bb219b 100644 --- a/server/cityturn.c +++ b/server/cityturn.c @@ -1371,6 +1371,9 @@ static bool worklist_item_postpone_req_vec(struct universal *target, script_server_signal_emit(signal_name, ptarget, pcity, "have_player_flag"); } + case VUT_PLAYER_STATE: + purge = TRUE; + break; case VUT_GOVERNMENT: if (preq->present) { notify_player(pplayer, city_tile(pcity), diff --git a/server/rssanity.c b/server/rssanity.c index 4c45f9efd1..e0239965fc 100644 --- a/server/rssanity.c +++ b/server/rssanity.c @@ -438,6 +438,7 @@ static bool sanity_check_req_set(rs_conversion_logger logger, case VUT_EXTRAFLAG: case VUT_IMPR_FLAG: case VUT_PLAYER_FLAG: + case VUT_PLAYER_STATE: case VUT_NATIONALITY: case VUT_MINCULTURE: case VUT_ACHIEVEMENT: diff --git a/tools/ruledit/univ_value.c b/tools/ruledit/univ_value.c index 74d88f0232..340f9d8b05 100644 --- a/tools/ruledit/univ_value.c +++ b/tools/ruledit/univ_value.c @@ -229,6 +229,8 @@ bool universal_value_initial(struct universal *src) return TRUE; case VUT_PLAYER_FLAG: src->value.plr_flag = PLRF_AI; + case VUT_PLAYER_STATE: + src->value.plrstate = PLRS_BARBARIAN; case VUT_ACTION: src->value.action = action_by_number(0); return TRUE; @@ -467,6 +469,11 @@ void universal_kind_values(struct universal *univ, cb(plr_flag_id_name(i), univ->value.plr_flag == i, data); } break; + case VUT_PLAYER_STATE: + for (i = 0; i < PLRS_LAST; i++) { + cb(plrstate_type_name(i), univ->value.plrstate == i, data); + } + break; case VUT_ACTION: action_iterate(act) { struct action *pact = action_by_number(act); -- 2.42.0