From d272ca96754756a2f52ed78336635e5a9b7148e7 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Thu, 8 Jun 2023 19:53:20 +0300 Subject: [PATCH 24/24] 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 dc95d607f0..da138d7ad4 100644 --- a/server/cityturn.c +++ b/server/cityturn.c @@ -1139,6 +1139,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; @@ -1156,7 +1160,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 6bd665e284..8998e69165 100644 --- a/server/savegame/savecompat.c +++ b/server/savegame/savecompat.c @@ -2346,6 +2346,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", @@ -2752,6 +2755,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); + } } secfile_insert_int(loading->file, wlist_max_length, diff --git a/server/savegame/savegame2.c b/server/savegame/savegame2.c index 63a1c09dbb..4993f83531 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 6746151b15..4492cfec14 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