From cd256414372fe312acb1c36687701b3be88d1441 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Thu, 8 Jun 2023 19:48:42 +0300 Subject: [PATCH 31/31] Track city worklist cancel behavior Have cities to have different worklist cancel behaviors (what to do when the worlist item cannot be built immediately) This initial patch just stores the value, including having it in savegames, and makes server to consult it when needed. The only way user can set the value is by savegame/scenario file editing. Requested by alain_bkr See osdn #48151 Signed-off-by: Marko Lindqvist --- common/city.c | 1 + common/city.h | 21 ++++++++++++++++++--- server/cityturn.c | 15 ++++++++++++++- server/savegame/savecompat.c | 10 ++++++++++ server/savegame/savegame2.c | 2 ++ server/savegame/savegame3.c | 22 ++++++++++++++-------- 6 files changed, 59 insertions(+), 12 deletions(-) diff --git a/common/city.c b/common/city.c index 12f22e48d2..f5b7e7a196 100644 --- a/common/city.c +++ b/common/city.c @@ -3355,6 +3355,7 @@ struct city *create_city_virtual(struct player *pplayer, pcity->capital = CAPITAL_NOT; city_size_set(pcity, 1); pcity->specialists[DEFAULT_SPECIALIST] = 1; + pcity->wlcb = WLCB_SMART; output_type_iterate(o) { pcity->bonus[o] = 100; diff --git a/common/city.h b/common/city.h index 91ddfa047c..0485dfb4bd 100644 --- a/common/city.h +++ b/common/city.h @@ -42,8 +42,8 @@ enum production_class_type { PCT_LAST }; -/* Various city options. These are stored by the server and can be - * toggled by the user. Each one defaults to off. Adding new ones +/* Various city options. These are stored by the server and can be + * toggled by the user. Each one defaults to off. Adding new ones * will break network compatibility. If you want to reorder or remove * an option remember to load the city option order from the savegame. * It is stored in savefile.city_options_vector @@ -64,6 +64,20 @@ enum production_class_type { #define SPECENUM_BITVECTOR bv_city_options #include "specenum_gen.h" +/* Used in savegames, and there's currently no order of the values + * stored in the savegame. Implement that before touching the values. */ +#define SPECENUM_NAME city_wl_cancel_behavior +#define SPECENUM_VALUE0 WLCB_SMART + /* TRANS: Worklist Cancelling behavior + * (when something cannot be built right away) */ +#define SPECENUM_VALUE0NAME N_("?wlcb:Smart") +#define SPECENUM_VALUE1 WLCB_ALWAYS_PURGE +#define SPECENUM_VALUE1NAME N_("?wlcb:Always Purge") +#define SPECENUM_VALUE2 WLCB_ALWAYS_POSTPONE +#define SPECENUM_VALUE2NAME N_("?wlcb:Always Postpone") +#define SPECENUM_COUNT WLCB_LAST +#include "specenum_gen.h" + /* The city includes all tiles dx^2 + dy^2 <= CITY_MAP_*_RADIUS_SQ */ #define CITY_MAP_DEFAULT_RADIUS_SQ \ (CITY_MAP_DEFAULT_RADIUS * CITY_MAP_DEFAULT_RADIUS + 1) @@ -387,6 +401,7 @@ struct city { struct worklist worklist; bv_city_options city_options; + enum city_wl_cancel_behavior wlcb; struct unit_list *units_supported; @@ -396,7 +411,7 @@ struct city { struct worker_task_list *task_reqs; - int steal; /* diplomats steal once; for spies, gets harder */ + int steal; /* Diplomats steal once; for spies, gets harder */ struct { size_t length; diff --git a/server/cityturn.c b/server/cityturn.c index b9c3a31503..806fb74244 100644 --- a/server/cityturn.c +++ b/server/cityturn.c @@ -1138,6 +1138,10 @@ static bool worklist_item_postpone_req_vec(struct universal *target, bool purge = FALSE; bool known = FALSE; + if (pcity->wlcb == WLCB_ALWAYS_PURGE) { + return TRUE; + } + switch (target->kind) { case VUT_UTYPE: ptarget = target->value.utype; @@ -1155,7 +1159,16 @@ static bool worklist_item_postpone_req_vec(struct universal *target, fc_assert_ret_val((target->kind == VUT_IMPROVEMENT || target->kind == VUT_UTYPE), FALSE); return FALSE; - break; + } + + if (pcity->wlcb == WLCB_ALWAYS_POSTPONE) { + notify_player(pplayer, city_tile(pcity), + E_CITY_CANTBUILD, ftc_server, + _("%s can't build %s from the worklist. " + "Postponing..."), + city_link(pcity), + tgt_name); + return FALSE; } requirement_vector_iterate(build_reqs, preq) { diff --git a/server/savegame/savecompat.c b/server/savegame/savecompat.c index 445f407629..4463f02c42 100644 --- a/server/savegame/savecompat.c +++ b/server/savegame/savecompat.c @@ -2350,6 +2350,9 @@ static void compat_load_030200(struct loaddata *loading, secfile_insert_int(loading->file, CACQ_CONQUEST, "player%d.c%d.acquire_t", plrno, cnro); + secfile_insert_int(loading->file, WLCB_SMART, + "player%d.c%d.wlcb", + plrno, cnro); } else { secfile_insert_int(loading->file, CACQ_FOUNDED, "player%d.c%d.acquire_t", @@ -2977,6 +2980,13 @@ static void compat_load_dev(struct loaddata *loading) plrno, cnro); } } + if (secfile_entry_lookup(loading->file, + "player%d.c%d.wlcb", + plrno, cnro) == NULL) { + secfile_insert_int(loading->file, WLCB_SMART, + "player%d.c%d.wlcb", + plrno, cnro); + } } } player_slots_iterate_end; } diff --git a/server/savegame/savegame2.c b/server/savegame/savegame2.c index ceee5ec457..c31bd7a200 100644 --- a/server/savegame/savegame2.c +++ b/server/savegame/savegame2.c @@ -3745,6 +3745,8 @@ static bool sg_load_player_city(struct loaddata *loading, struct player *plr, BV_SET(pcity->city_options, loading->coptions.order[i]); } } + /* Was never stored to savegame2 saves */ + pcity->wlcb = WLCB_SMART; CALL_FUNC_EACH_AI(city_load, loading->file, pcity, citystr); diff --git a/server/savegame/savegame3.c b/server/savegame/savegame3.c index 324d31ce13..f1b71f78ec 100644 --- a/server/savegame/savegame3.c +++ b/server/savegame/savegame3.c @@ -1627,8 +1627,8 @@ static void sg_load_savefile(struct loaddata *loading) /* Load city options order. */ loading->coptions.size - = secfile_lookup_int_default(loading->file, 0, - "savefile.city_options_size"); + = secfile_lookup_int_default(loading->file, 0, + "savefile.city_options_size"); sg_failure_ret(loading->coptions.size > 0, "Failed to load city options order: %s", @@ -4970,7 +4970,7 @@ static bool sg_load_player_city(struct loaddata *loading, struct player *plr, const char *stylename; int partner; int want; - int acq_t_tmp; + int tmp_int; sg_warn_ret_val(secfile_lookup_int(loading->file, &nat_x, "%s.x", citystr), FALSE, "%s", secfile_error()); @@ -5080,10 +5080,10 @@ static bool sg_load_player_city(struct loaddata *loading, struct player *plr, sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->turn_founded, "%s.turn_founded", citystr), FALSE, "%s", secfile_error()); - sg_warn_ret_val(secfile_lookup_int(loading->file, &acq_t_tmp, + sg_warn_ret_val(secfile_lookup_int(loading->file, &tmp_int, "%s.acquire_t", citystr), FALSE, "%s", secfile_error()); - pcity->acquire_t = acq_t_tmp; + pcity->acquire_t = tmp_int; sg_warn_ret_val(secfile_lookup_bool(loading->file, &pcity->did_buy, "%s.did_buy", citystr), FALSE, "%s", secfile_error()); sg_warn_ret_val(secfile_lookup_bool(loading->file, &pcity->did_sell, "%s.did_sell", @@ -5144,7 +5144,7 @@ static bool sg_load_player_city(struct loaddata *loading, struct player *plr, pcity->style = city_style(pcity); } - pcity->server.synced = FALSE; /* must re-sync with clients */ + pcity->server.synced = FALSE; /* Must re-sync with clients */ /* Initialise list of city improvements. */ for (i = 0; i < ARRAY_SIZE(pcity->built); i++) { @@ -5164,8 +5164,8 @@ static bool sg_load_player_city(struct loaddata *loading, struct player *plr, str[i], citystr) if (str[i] == '1') { - struct impr_type *pimprove = - improvement_by_rule_name(loading->improvement.order[i]); + struct impr_type *pimprove + = improvement_by_rule_name(loading->improvement.order[i]); if (pimprove) { city_add_improvement(pcity, pimprove); @@ -5252,6 +5252,10 @@ static bool sg_load_player_city(struct loaddata *loading, struct player *plr, BV_SET(pcity->city_options, loading->coptions.order[i]); } } + sg_warn_ret_val(secfile_lookup_int(loading->file, &tmp_int, + "%s.wlcb", citystr), + FALSE, "%s", secfile_error()); + pcity->wlcb = tmp_int; /* Load the city rally point. */ { @@ -5647,6 +5651,8 @@ static void sg_save_player_cities(struct savedata *saving, secfile_insert_bool(saving->file, BV_ISSET(pcity->city_options, j), "%s.option%d", buf, j); } + secfile_insert_int(saving->file, pcity->wlcb, + "%s.wlcb", buf); CALL_FUNC_EACH_AI(city_save, saving->file, pcity, buf); -- 2.39.2