From d4ac7b4a0afa483e13d5fdc77d0e4a5567efe53e Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Sun, 1 Oct 2023 08:07:36 +0300 Subject: [PATCH 49/49] Add PlayerFlag requirement type See osdn #45666 Signed-off-by: Marko Lindqvist --- ai/default/daieffects.c | 1 + ai/default/daimilitary.c | 1 + common/fc_types.h | 15 ++++++++ common/player.h | 12 ------- common/reqtext.c | 20 +++++++++++ common/requirements.c | 70 ++++++++++++++++++++++++++++++++++++-- doc/README.effects | 1 + server/cityturn.c | 24 +++++++++++++ server/rssanity.c | 1 + tools/ruledit/univ_value.c | 7 ++++ 10 files changed, 138 insertions(+), 14 deletions(-) diff --git a/ai/default/daieffects.c b/ai/default/daieffects.c index 10b747d076..078f393598 100644 --- a/ai/default/daieffects.c +++ b/ai/default/daieffects.c @@ -868,6 +868,7 @@ bool dai_can_requirement_be_met_in_city(const struct requirement *preq, case VUT_SERVERSETTING: case VUT_MINLATITUDE: case VUT_MAXLATITUDE: + case VUT_PLAYER_FLAG: /* Beyond player control. */ return FALSE; diff --git a/ai/default/daimilitary.c b/ai/default/daimilitary.c index cea18e4356..a55daad827 100644 --- a/ai/default/daimilitary.c +++ b/ai/default/daimilitary.c @@ -445,6 +445,7 @@ tactical_req_cb(const struct req_context *context, case VUT_ACHIEVEMENT: case VUT_IMPR_GENUS: case VUT_IMPR_FLAG: + case VUT_PLAYER_FLAG: case VUT_MINCULTURE: case VUT_MINTECHS: case VUT_ORIGINAL_OWNER: diff --git a/common/fc_types.h b/common/fc_types.h index a3be88b815..586d03e5c2 100644 --- a/common/fc_types.h +++ b/common/fc_types.h @@ -664,6 +664,18 @@ const char *ai_level_name_update_cb(const char *old); #define IF_LAST_USER_FLAG IF_USER_FLAG_8 #define MAX_NUM_USER_BUILDING_FLAGS (IF_LAST_USER_FLAG - IF_USER_FLAG_1 + 1) +#define SPECENUM_NAME plr_flag_id +#define SPECENUM_VALUE0 PLRF_AI +#define SPECENUM_VALUE0NAME "ai" +#define SPECENUM_VALUE1 PLRF_SCENARIO_RESERVED +#define SPECENUM_VALUE1NAME "ScenarioReserved" +/* TRUE if player has ever had a city. */ +#define SPECENUM_VALUE2 PLRF_FIRST_CITY +#define SPECENUM_VALUE2NAME "FirstCity" +#define SPECENUM_COUNT PLRF_COUNT +#define SPECENUM_BITVECTOR bv_plr_flags +#include "specenum_gen.h" + /* A server setting + its value. */ typedef int ssetv; @@ -724,6 +736,7 @@ typedef union { enum unit_activity activity; enum impr_genus_id impr_genus; enum impr_flag_id impr_flag; + enum plr_flag_id plr_flag; int minmoves; int max_tile_units; int minveteran; @@ -855,6 +868,8 @@ typedef union { #define SPECENUM_VALUE53NAME "BuildingFlag" #define SPECENUM_VALUE54 VUT_WRAP #define SPECENUM_VALUE54NAME "Wrap" +#define SPECENUM_VALUE55 VUT_PLAYER_FLAG +#define SPECENUM_VALUE55NAME "PlayerFlag" /* Keep this last. */ #define SPECENUM_COUNT VUT_COUNT diff --git a/common/player.h b/common/player.h index 15dbb28629..d3f9c96038 100644 --- a/common/player.h +++ b/common/player.h @@ -57,18 +57,6 @@ enum plrcolor_mode { PLRCOL_NATION_ORDER }; -#define SPECENUM_NAME plr_flag_id -#define SPECENUM_VALUE0 PLRF_AI -#define SPECENUM_VALUE0NAME "ai" -#define SPECENUM_VALUE1 PLRF_SCENARIO_RESERVED -#define SPECENUM_VALUE1NAME "ScenarioReserved" -/* TRUE if player has ever had a city. */ -#define SPECENUM_VALUE2 PLRF_FIRST_CITY -#define SPECENUM_VALUE2NAME "FirstCity" -#define SPECENUM_COUNT PLRF_COUNT -#define SPECENUM_BITVECTOR bv_plr_flags -#include "specenum_gen.h" - struct player_slot; struct player_economic { diff --git a/common/reqtext.c b/common/reqtext.c index 8e7fa8d35a..f00d6af41c 100644 --- a/common/reqtext.c +++ b/common/reqtext.c @@ -371,6 +371,26 @@ bool req_text_insert(char *buf, size_t bufsz, struct player *pplayer, } break; + case VUT_PLAYER_FLAG: + switch (preq->range) { + case REQ_RANGE_PLAYER: + fc_strlcat(buf, prefix, bufsz); + if (preq->present) { + cat_snprintf(buf, bufsz, _("Applies to players with \"%s\" flag."), + plr_flag_id_translated_name( + preq->source.value.plr_flag)); + } else { + cat_snprintf(buf, bufsz, _("Doesn't apply to players with \"%s\" flag."), + plr_flag_id_translated_name( + preq->source.value.plr_flag)); + } + 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 ce0631dd95..b190a585be 100644 --- a/common/requirements.c +++ b/common/requirements.c @@ -324,6 +324,12 @@ void universal_value_from_str(struct universal *source, const char *value) return; } break; + case VUT_PLAYER_FLAG: + source->value.plr_flag = plr_flag_id_by_name(value, fc_strcasecmp); + if (plr_flag_id_is_valid(source->value.plr_flag)) { + return; + } + break; case VUT_EXTRA: source->value.extra = extra_type_by_rule_name(value); if (source->value.extra != NULL) { @@ -644,6 +650,9 @@ struct universal universal_by_number(const enum universals_n kind, case VUT_IMPR_FLAG: source.value.impr_flag = value; return source; + case VUT_PLAYER_FLAG: + source.value.plr_flag = value; + return source; case VUT_EXTRA: source.value.extra = extra_by_number(value); return source; @@ -855,6 +864,8 @@ int universal_number(const struct universal *source) return source->value.impr_genus; case VUT_IMPR_FLAG: return source->value.impr_flag; + case VUT_PLAYER_FLAG: + return source->value.plr_flag; case VUT_EXTRA: return extra_number(source->value.extra); case VUT_GOOD: @@ -1076,6 +1087,7 @@ struct requirement req_from_str(const char *type, const char *range, case VUT_DIPLREL_TILE: case VUT_DIPLREL_UNITANY: case VUT_AI_LEVEL: + case VUT_PLAYER_FLAG: req.range = REQ_RANGE_PLAYER; break; case VUT_MINYEAR: @@ -1242,6 +1254,9 @@ struct requirement req_from_str(const char *type, const char *range, case VUT_COUNTER: invalid = req.range != REQ_RANGE_CITY; break; + case VUT_PLAYER_FLAG: + invalid = (req.range != REQ_RANGE_PLAYER); + break; case VUT_IMPROVEMENT: /* Valid ranges depend on the building genus (wonder/improvement), * which might not have been loaded from the ruleset yet. @@ -1272,6 +1287,7 @@ struct requirement req_from_str(const char *type, const char *range, case VUT_COUNTER: case VUT_IMPR_GENUS: case VUT_IMPR_FLAG: + case VUT_PLAYER_FLAG: case VUT_GOVERNMENT: case VUT_TERRAIN: case VUT_UTYPE: @@ -1781,7 +1797,6 @@ bool are_requirements_contradictions(const struct requirement *req1, /* No special knowledge exists. The requirements aren't the exact * opposite of each other per the initial check. */ return FALSE; - break; } } @@ -2227,6 +2242,46 @@ is_buildingflag_req_active(const struct req_context *context, return TRI_MAYBE; } +/**********************************************************************//** + Determine whether a player flag 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_flag_req_active(const struct req_context *context, + const struct player *other_player, + const struct requirement *req) +{ + IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_PLAYER_FLAG); + + switch (req->range) { + case REQ_RANGE_PLAYER: + return (context->player != NULL + ? BOOL_TO_TRISTATE(player_has_flag(context->player, + req->source.value.plr_flag)) + : 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 @@ -5109,7 +5164,7 @@ is_serversetting_req_active(const struct req_context *context, static struct req_def req_definitions[VUT_COUNT] = { [VUT_NONE] = {is_none_req_active, REQUCH_YES}, - /* alphabetical order of enum constant */ + /* Alphabetical order of enum constant */ [VUT_ACHIEVEMENT] = {is_achievement_req_active, REQUCH_YES, REQUC_PRESENT}, [VUT_ACTION] = {is_action_req_active, REQUCH_YES}, [VUT_ACTIVITY] = {is_activity_req_active, REQUCH_NO}, @@ -5131,6 +5186,7 @@ static struct req_def req_definitions[VUT_COUNT] = { [VUT_IMPROVEMENT] = {is_building_req_active, REQUCH_NO, REQUC_IMPR}, [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_MAXLATITUDE] = {is_latitude_req_active, REQUCH_YES}, [VUT_MAXTILEUNITS] = {is_maxunitsontile_req_active, REQUCH_NO}, [VUT_MINCALFRAG] = {is_mincalfrag_req_active, REQUCH_NO}, @@ -5643,6 +5699,7 @@ bool universal_never_there(const struct universal *source) case VUT_IMPROVEMENT: case VUT_IMPR_GENUS: case VUT_IMPR_FLAG: + case VUT_PLAYER_FLAG: case VUT_MINSIZE: case VUT_MINCULTURE: case VUT_MINFOREIGNPCT: @@ -6237,6 +6294,8 @@ bool are_universals_equal(const struct universal *psource1, return psource1->value.impr_genus == psource2->value.impr_genus; case VUT_IMPR_FLAG: return psource1->value.impr_flag == psource2->value.impr_flag; + case VUT_PLAYER_FLAG: + return psource1->value.plr_flag == psource2->value.plr_flag; case VUT_EXTRA: return psource1->value.extra == psource2->value.extra; case VUT_GOOD: @@ -6379,6 +6438,8 @@ const char *universal_rule_name(const struct universal *psource) return impr_genus_id_name(psource->value.impr_genus); case VUT_IMPR_FLAG: return impr_flag_id_name(psource->value.impr_flag); + case VUT_PLAYER_FLAG: + return plr_flag_id_name(psource->value.plr_flag); case VUT_EXTRA: return extra_rule_name(psource->value.extra); case VUT_GOOD: @@ -6530,6 +6591,11 @@ const char *universal_name_translation(const struct universal *psource, impr_flag_id_translated_name(psource->value.impr_flag), bufsz); return buf; + case VUT_PLAYER_FLAG: + fc_strlcat(buf, + plr_flag_id_translated_name(psource->value.plr_flag), + 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 19fbb90f14..fc93feb1c3 100644 --- a/doc/README.effects +++ b/doc/README.effects @@ -77,6 +77,7 @@ UnitClassFlag: Local Nation: World, Alliance, Team, Player NationGroup: World, Alliance, Team, Player Nationality: Traderoute, City +PlayerFlag: 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 969bd624a8..985546fcc9 100644 --- a/server/cityturn.c +++ b/server/cityturn.c @@ -1347,6 +1347,30 @@ static bool worklist_item_postpone_req_vec(struct universal *target, } } break; + case VUT_PLAYER_FLAG: + if (preq->present) { + notify_player(pplayer, city_tile(pcity), + E_CITY_CANTBUILD, ftc_server, + _("%s can't build %s from the worklist; " + "need to have %s first. Postponing..."), + city_link(pcity), + tgt_name, + plr_flag_id_translated_name( + preq->source.value.plr_flag)); + script_server_signal_emit(signal_name, ptarget, + pcity, "need_player_flag"); + } else { + notify_player(pplayer, city_tile(pcity), + E_CITY_CANTBUILD, ftc_server, + _("%s can't build %s from the worklist; " + "need to not have %s. Postponing..."), + city_link(pcity), + tgt_name, + plr_flag_id_translated_name( + preq->source.value.plr_flag)); + script_server_signal_emit(signal_name, ptarget, + pcity, "have_player_flag"); + } case VUT_GOVERNMENT: if (preq->present) { notify_player(pplayer, city_tile(pcity), diff --git a/server/rssanity.c b/server/rssanity.c index edfa20413f..616a3f6aed 100644 --- a/server/rssanity.c +++ b/server/rssanity.c @@ -437,6 +437,7 @@ static bool sanity_check_req_set(rs_conversion_logger logger, case VUT_ROADFLAG: case VUT_EXTRAFLAG: case VUT_IMPR_FLAG: + case VUT_PLAYER_FLAG: case VUT_NATIONALITY: case VUT_MINCULTURE: case VUT_ACHIEVEMENT: diff --git a/tools/ruledit/univ_value.c b/tools/ruledit/univ_value.c index 3d8831b8f5..74d88f0232 100644 --- a/tools/ruledit/univ_value.c +++ b/tools/ruledit/univ_value.c @@ -227,6 +227,8 @@ bool universal_value_initial(struct universal *src) case VUT_IMPR_FLAG: src->value.impr_flag = IF_VISIBLE_BY_OTHERS; return TRUE; + case VUT_PLAYER_FLAG: + src->value.plr_flag = PLRF_AI; case VUT_ACTION: src->value.action = action_by_number(0); return TRUE; @@ -460,6 +462,11 @@ void universal_kind_values(struct universal *univ, cb(impr_flag_id_name(i), univ->value.impr_flag == i, data); } break; + case VUT_PLAYER_FLAG: + for (i = 0; i < PLRF_COUNT; i++) { + cb(plr_flag_id_name(i), univ->value.plr_flag == i, data); + } + break; case VUT_ACTION: action_iterate(act) { struct action *pact = action_by_number(act); -- 2.40.1