From df8bdc0d49d59e5ce62023f8adf6d44a6637bc83 Mon Sep 17 00:00:00 2001
From: Marko Lindqvist <cazfi74@gmail.com>
Date: Sat, 18 May 2024 03:49:36 +0300
Subject: [PATCH 38/38] Unhardcode wld.map from can_city_build_unit_now()

See RM #646

Signed-off-by: Marko Lindqvist <cazfi74@gmail.com>
---
 ai/default/aiair.c         |  3 ++-
 ai/default/aihunt.c        |  6 ++++--
 ai/default/aiparatrooper.c |  3 ++-
 ai/default/aitech.c        |  8 +++++---
 ai/default/aiunit.c        |  3 ++-
 ai/default/daicity.c       |  5 +++--
 ai/default/daimilitary.c   | 13 ++++++++-----
 ai/tex/texaicity.c         |  2 +-
 ai/threaded/taicity.c      |  2 +-
 client/climisc.c           |  2 +-
 client/gui-sdl2/wldlg.c    |  2 +-
 common/city.c              |  9 +++++----
 common/city.h              |  3 ++-
 common/improvement.c       |  8 ++++++--
 common/unittype.c          |  3 ++-
 server/cityturn.c          |  4 +++-
 server/techtools.c         |  3 ++-
 17 files changed, 50 insertions(+), 29 deletions(-)

diff --git a/ai/default/aiair.c b/ai/default/aiair.c
index ab417a3c4d..d7ad3bf67a 100644
--- a/ai/default/aiair.c
+++ b/ai/default/aiair.c
@@ -586,6 +586,7 @@ bool dai_choose_attacker_air(struct ai_type *ait, struct player *pplayer,
                              bool allow_gold_upkeep)
 {
   bool want_something = FALSE;
+  const struct civ_map *nmap = &(wld.map);
 
   /* This AI doesn't know how to build planes */
   if (has_handicap(pplayer, H_NOPLANES)) {
@@ -618,7 +619,7 @@ bool dai_choose_attacker_air(struct ai_type *ait, struct player *pplayer,
       continue;
     }
 
-    if (can_city_build_unit_now(pcity, punittype)) {
+    if (can_city_build_unit_now(nmap, pcity, punittype)) {
       struct unit *virtual_unit =
        unit_virtual_create(
           pplayer, pcity, punittype,
diff --git a/ai/default/aihunt.c b/ai/default/aihunt.c
index 6036499589..84871be2ce 100644
--- a/ai/default/aihunt.c
+++ b/ai/default/aihunt.c
@@ -89,6 +89,7 @@ static struct unit_type *dai_hunter_guess_best(struct city *pcity,
   struct unit_type *bestid = NULL;
   int best = 0;
   struct player *pplayer = city_owner(pcity);
+  const struct civ_map *nmap = &(wld.map);
 
   unit_type_iterate(ut) {
     struct unit_type_ai *utai = utype_ai_data(ut, ait);
@@ -98,7 +99,7 @@ static struct unit_type *dai_hunter_guess_best(struct city *pcity,
       continue;
     }
 
-    if (!can_city_build_unit_now(pcity, ut)
+    if (!can_city_build_unit_now(nmap, pcity, ut)
         || ut->attack_strength < ut->transport_capacity
         || (tc == TC_OCEAN && utype_class(ut)->adv.sea_move == MOVE_NONE)
         || (tc == TC_LAND && utype_class(ut)->adv.land_move == MOVE_NONE)) {
@@ -152,6 +153,7 @@ static void dai_hunter_missile_want(struct player *pplayer,
   adv_want best = -1;
   struct unit_type *best_unit_type = NULL;
   struct unit *hunter = NULL;
+  const struct civ_map *nmap = &(wld.map);
 
   unit_list_iterate(pcity->tile->units, punit) {
     if (dai_hunter_qualify(pplayer, punit)) {
@@ -177,7 +179,7 @@ static void dai_hunter_missile_want(struct player *pplayer,
     int desire;
 
     if (!utype_can_do_action(ut, ACTION_SUICIDE_ATTACK)
-        || !can_city_build_unit_now(pcity, ut)) {
+        || !can_city_build_unit_now(nmap, pcity, ut)) {
       continue;
     }
 
diff --git a/ai/default/aiparatrooper.c b/ai/default/aiparatrooper.c
index 16fe3f8be9..42501513ae 100644
--- a/ai/default/aiparatrooper.c
+++ b/ai/default/aiparatrooper.c
@@ -390,6 +390,7 @@ void dai_choose_paratrooper(struct ai_type *ait,
   int num_requirements = 0;
   int i;
   struct ai_plr *plr_data = def_ai_player_data(pplayer, ait);
+  const struct civ_map *nmap = &(wld.map);
 
   /* military_advisor_choose_build() does something idiotic,
    * this function should not be called if there is danger... */
@@ -432,7 +433,7 @@ void dai_choose_paratrooper(struct ai_type *ait,
     }
 
     /* we only update choice struct if we can build it! */
-    if (!can_city_build_unit_now(pcity, u_type)) {
+    if (!can_city_build_unit_now(nmap, pcity, u_type)) {
       continue;
     }
 
diff --git a/ai/default/aitech.c b/ai/default/aitech.c
index 720bd0d26c..a4cf07467b 100644
--- a/ai/default/aitech.c
+++ b/ai/default/aitech.c
@@ -401,6 +401,7 @@ struct unit_type *dai_wants_defender_against(struct ai_type *ait,
   int att_idx = utype_index(att);
   int defbonus = 100
     + get_unittype_bonus(pplayer, ptile, att, NULL, EFT_DEFEND_BONUS);
+  const struct civ_map *nmap = &(wld.map);
 
   unit_type_iterate(deftype) {
     int mp_pct = deftype->cache.defense_mp_bonuses_pct[att_idx] + 100;
@@ -415,7 +416,7 @@ struct unit_type *dai_wants_defender_against(struct ai_type *ait,
 
     def_values[utype_index(deftype)] = def;
 
-    if (can_city_build_unit_now(pcity, deftype)) {
+    if (can_city_build_unit_now(nmap, pcity, deftype)) {
       if (def > best_avl_def) {
         best_avl_def = def;
         best_avl = deftype;
@@ -425,7 +426,7 @@ struct unit_type *dai_wants_defender_against(struct ai_type *ait,
 
   unit_type_iterate(deftype) {
     if (def_values[utype_index(deftype)] > best_avl_def
-        && !can_city_build_unit_now(pcity, deftype)
+        && !can_city_build_unit_now(nmap, pcity, deftype)
         && can_city_build_unit_later(pcity, deftype)) {
       /* It would be better than current best. Consider researching tech */
       const struct impr_type *building;
@@ -518,13 +519,14 @@ struct unit_type *dai_wants_role_unit(struct ai_type *ait, struct player *pplaye
   struct advance *best_tech = A_NEVER;
   struct unit_type *best_unit = NULL;
   struct unit_type *build_unit = NULL;
+  const struct civ_map *nmap = &(wld.map);
 
   n = num_role_units(role);
   for (i = n - 1; i >= 0; i--) {
     struct unit_type *iunit = get_role_unit(role, i);
     struct advance *itech = iunit->require_advance;
 
-    if (can_city_build_unit_now(pcity, iunit)) {
+    if (can_city_build_unit_now(nmap, pcity, iunit)) {
       build_unit = iunit;
       break;
     } else if (can_city_build_unit_later(pcity, iunit)) {
diff --git a/ai/default/aiunit.c b/ai/default/aiunit.c
index 1e9967b800..2c036f5aa4 100644
--- a/ai/default/aiunit.c
+++ b/ai/default/aiunit.c
@@ -3411,6 +3411,7 @@ static bool role_unit_cb(struct unit_type *ptype, void *data)
 {
   struct role_unit_cb_data *cb_data = (struct role_unit_cb_data *)data;
   struct unit_class *pclass = utype_class(ptype);
+  const struct civ_map *nmap = &(wld.map);
 
   if ((cb_data->tc == TC_LAND && pclass->adv.land_move == MOVE_NONE)
       || (cb_data->tc == TC_OCEAN && pclass->adv.sea_move == MOVE_NONE)) {
@@ -3418,7 +3419,7 @@ static bool role_unit_cb(struct unit_type *ptype, void *data)
   }
 
   if (cb_data->build_city == NULL
-      || can_city_build_unit_now(cb_data->build_city, ptype)) {
+      || can_city_build_unit_now(nmap, cb_data->build_city, ptype)) {
     return TRUE;
   }
 
diff --git a/ai/default/daicity.c b/ai/default/daicity.c
index ada6243dd9..e68657ca6d 100644
--- a/ai/default/daicity.c
+++ b/ai/default/daicity.c
@@ -205,13 +205,14 @@ static void dai_barbarian_choose_build(struct player *pplayer,
 {
   struct unit_type *bestunit = NULL;
   int i, bestattack = 0;
+  const struct civ_map *nmap = &(wld.map);
 
   /* Choose the best unit among the basic ones */
   for (i = 0; i < num_role_units(L_BARBARIAN_BUILD); i++) {
     struct unit_type *iunit = get_role_unit(L_BARBARIAN_BUILD, i);
 
     if (iunit->attack_strength > bestattack
-        && can_city_build_unit_now(pcity, iunit)) {
+        && can_city_build_unit_now(nmap, pcity, iunit)) {
       bestunit = iunit;
       bestattack = iunit->attack_strength;
     }
@@ -222,7 +223,7 @@ static void dai_barbarian_choose_build(struct player *pplayer,
     struct unit_type *iunit = get_role_unit(L_BARBARIAN_BUILD_TECH, i);
 
     if (iunit->attack_strength > bestattack
-        && can_city_build_unit_now(pcity, iunit)) {
+        && can_city_build_unit_now(nmap, pcity, iunit)) {
       bestunit = iunit;
       bestattack = iunit->attack_strength;
     }
diff --git a/ai/default/daimilitary.c b/ai/default/daimilitary.c
index 78f64914af..f308716de2 100644
--- a/ai/default/daimilitary.c
+++ b/ai/default/daimilitary.c
@@ -98,7 +98,7 @@ struct unit_type *dai_choose_defender_versus(struct city *pcity,
   struct civ_map *nmap = &(wld.map);
 
   simple_ai_unit_type_iterate(punittype) {
-    if (can_city_build_unit_now(pcity, punittype)) {
+    if (can_city_build_unit_now(nmap, pcity, punittype)) {
       int fpatt, fpdef, defense, attack;
       double want, loss, cost = utype_build_shield_cost(pcity, NULL, punittype);
       struct unit *defender;
@@ -151,6 +151,7 @@ static struct unit_type *dai_choose_attacker(struct ai_type *ait,
   adv_want best = -1;
   adv_want cur;
   struct player *pplayer = city_owner(pcity);
+  const struct civ_map *nmap = &(wld.map);
 
   simple_ai_unit_type_iterate(putype) {
     if (!allow_gold_upkeep && utype_upkeep_cost(putype, pplayer, O_GOLD) > 0) {
@@ -161,7 +162,7 @@ static struct unit_type *dai_choose_attacker(struct ai_type *ait,
     if ((tc == TC_LAND && utype_class(putype)->adv.land_move != MOVE_NONE)
         || (tc == TC_OCEAN
             && utype_class(putype)->adv.sea_move != MOVE_NONE)) {
-      if (can_city_build_unit_now(pcity, putype)
+      if (can_city_build_unit_now(nmap, pcity, putype)
           && (cur > best
               || (ADV_WANTS_EQ(cur, best)
                   && utype_build_shield_cost(pcity, NULL, putype)
@@ -192,6 +193,7 @@ static struct unit_type *dai_choose_bodyguard(struct ai_type *ait,
   struct unit_type *bestid = NULL;
   adv_want best = 0;
   struct player *pplayer = city_owner(pcity);
+  const struct civ_map *nmap = &(wld.map);
 
   simple_ai_unit_type_iterate(putype) {
     /* Only consider units of given role, or any if invalid given */
@@ -213,7 +215,7 @@ static struct unit_type *dai_choose_bodyguard(struct ai_type *ait,
     }
 
     /* Now find best */
-    if (can_city_build_unit_now(pcity, putype)) {
+    if (can_city_build_unit_now(nmap, pcity, putype)) {
       const adv_want desire = dai_unit_defense_desirability(ait, putype);
 
       if (desire > best
@@ -1050,6 +1052,7 @@ bool dai_process_defender_want(struct ai_type *ait, struct player *pplayer,
   struct ai_city *city_data = def_ai_city_data(pcity, ait);
   struct ai_plr *plr_data = def_ai_player_data(pplayer, ait);
   adv_want total_want = danger + extra_want;
+  const struct civ_map *nmap = &(wld.map);
 
   memset(tech_desire, 0, sizeof(tech_desire));
 
@@ -1085,7 +1088,7 @@ bool dai_process_defender_want(struct ai_type *ait, struct player *pplayer,
       desire /= POWER_DIVIDER / 2; /* Good enough, no rounding errors. */
       desire *= desire;
 
-      if (can_city_build_unit_now(pcity, punittype)) {
+      if (can_city_build_unit_now(nmap, pcity, punittype)) {
         /* We can build the unit now... */
 
         int build_cost = utype_build_shield_cost(pcity, NULL, punittype);
@@ -1416,7 +1419,7 @@ static void process_attacker_want(struct ai_type *ait,
         } else if (want > best_choice->want) {
           const struct impr_type *impr_req;
 
-          if (can_city_build_unit_now(pcity, punittype)) {
+          if (can_city_build_unit_now(nmap, pcity, punittype)) {
             /* This is a real unit and we really want it */
 
             CITY_LOG(LOG_DEBUG, pcity, "overriding %s(" ADV_WANT_PRINTF
diff --git a/ai/tex/texaicity.c b/ai/tex/texaicity.c
index c8e9e20974..de885a8932 100644
--- a/ai/tex/texaicity.c
+++ b/ai/tex/texaicity.c
@@ -461,7 +461,7 @@ static bool texai_city_worker_task_select(struct ai_type *ait,
   case TWTL_BUILDABLE_UNITS:
     units = unit_list_new();
     unit_type_iterate(ptype) {
-      if (can_city_build_unit_now(pcity, ptype)) {
+      if (can_city_build_unit_now(nmap, pcity, ptype)) {
         unit_list_append(units, unit_virtual_create(pplayer, pcity, ptype, 0));
       }
     } unit_type_iterate_end;
diff --git a/ai/threaded/taicity.c b/ai/threaded/taicity.c
index 1de4c1b7dc..815a1620ef 100644
--- a/ai/threaded/taicity.c
+++ b/ai/threaded/taicity.c
@@ -406,7 +406,7 @@ static bool tai_city_worker_task_select(struct ai_type *ait,
   case TWTL_BUILDABLE_UNITS:
     units = unit_list_new();
     unit_type_iterate(ptype) {
-      if (can_city_build_unit_now(pcity, ptype)) {
+      if (can_city_build_unit_now(nmap, pcity, ptype)) {
         unit_list_append(units, unit_virtual_create(pplayer, pcity, ptype, 0));
       }
     } unit_type_iterate_end;
diff --git a/client/climisc.c b/client/climisc.c
index d7fb89291b..d44eddbb12 100644
--- a/client/climisc.c
+++ b/client/climisc.c
@@ -853,7 +853,7 @@ int collect_eventually_buildable_targets(struct universal *targets,
 
     if (NULL != pcity) {
       /* Can the city build? */
-      can_build = can_city_build_unit_now(pcity, punittype);
+      can_build = can_city_build_unit_now(&(wld.map), pcity, punittype);
       can_eventually_build = can_city_build_unit_later(pcity, punittype);
     } else if (NULL != pplayer) {
       /* Can our player build? */
diff --git a/client/gui-sdl2/wldlg.c b/client/gui-sdl2/wldlg.c
index 61be1358da..7e667afb7f 100644
--- a/client/gui-sdl2/wldlg.c
+++ b/client/gui-sdl2/wldlg.c
@@ -1558,7 +1558,7 @@ void popup_worklist_editor(struct city *pcity, struct global_worklist *gwl)
 
     /* If there's a city, can the city build the unit? */
     if (pcity) {
-      can_build = can_build && can_city_build_unit_now(pcity, un);
+      can_build = can_build && can_city_build_unit_now(&(wld.map), pcity, un);
       can_eventually_build = can_eventually_build
         && can_city_build_unit_later(pcity, un);
     }
diff --git a/common/city.c b/common/city.c
index b3bf8d8e44..6cbb3f3b74 100644
--- a/common/city.c
+++ b/common/city.c
@@ -924,11 +924,10 @@ bool can_city_build_unit_direct(const struct civ_map *nmap,
   Return whether given city can build given unit; returns FALSE if unit is 
   obsolete.
 **************************************************************************/
-bool can_city_build_unit_now(const struct city *pcity,
+bool can_city_build_unit_now(const struct civ_map *nmap,
+                             const struct city *pcity,
                              const struct unit_type *punittype)
 {
-  const struct civ_map *nmap = &(wld.map);
-
   if (!can_city_build_unit_direct(nmap, pcity, punittype)) {
     return FALSE;
   }
@@ -994,9 +993,11 @@ bool can_city_build_direct(const struct city *pcity,
 bool can_city_build_now(const struct city *pcity,
                         const struct universal *target)
 {
+  const struct civ_map *nmap = &(wld.map);
+
   switch (target->kind) {
   case VUT_UTYPE:
-    return can_city_build_unit_now(pcity, target->value.utype);
+    return can_city_build_unit_now(nmap, pcity, target->value.utype);
   case VUT_IMPROVEMENT:
     return can_city_build_improvement_now(pcity, target->value.building);
   default:
diff --git a/common/city.h b/common/city.h
index c026cbf9a3..695bd66d77 100644
--- a/common/city.h
+++ b/common/city.h
@@ -589,7 +589,8 @@ bool can_city_build_unit_direct(const struct civ_map *nmap,
                                 const struct unit_type *punittype);
 bool can_city_build_unit_later(const struct city *pcity,
                                const struct unit_type *punittype);
-bool can_city_build_unit_now(const struct city *pcity,
+bool can_city_build_unit_now(const struct civ_map *nmap,
+                             const struct city *pcity,
                              const struct unit_type *punittype);
 
 bool can_city_build_direct(const struct city *pcity,
diff --git a/common/improvement.c b/common/improvement.c
index 1c2929cb6d..4676ea49b7 100644
--- a/common/improvement.c
+++ b/common/improvement.c
@@ -432,6 +432,8 @@ bool improvement_obsolete(const struct player *pplayer,
 static bool impr_provides_buildable_units(const struct city *pcity,
                                           const struct impr_type *pimprove)
 {
+  const struct civ_map *nmap = &(wld.map);
+
   /* Fast check */
   if (!pimprove->allows_units) {
     return FALSE;
@@ -439,7 +441,7 @@ static bool impr_provides_buildable_units(const struct city *pcity,
 
   unit_type_iterate(ut) {
     if (requirement_needs_improvement(pimprove, &ut->build_reqs)
-        && can_city_build_unit_now(pcity, ut)) {
+        && can_city_build_unit_now(nmap, pcity, ut)) {
       return TRUE;
     }
   } unit_type_iterate_end;
@@ -525,6 +527,8 @@ static bool impr_protects_vs_actions(const struct city *pcity,
 static bool impr_allows_actions(const struct city *pcity,
                                 const struct impr_type *pimprove)
 {
+  const struct civ_map *nmap = &(wld.map);
+
   /* Fast check */
   if (!pimprove->allows_actions) {
     return FALSE;
@@ -545,7 +549,7 @@ static bool impr_allows_actions(const struct city *pcity,
             return TRUE;
           }
 
-          if (can_city_build_unit_now(pcity, ut)) {
+          if (can_city_build_unit_now(nmap, pcity, ut)) {
             /* This city can build a unit that uses the building */
             return TRUE;
           }
diff --git a/common/unittype.c b/common/unittype.c
index 52b6bd1fba..ff2d2d83ad 100644
--- a/common/unittype.c
+++ b/common/unittype.c
@@ -2320,6 +2320,7 @@ struct unit_type *best_role_unit(const struct city *pcity, int role)
 {
   struct unit_type *u;
   int j;
+  const struct civ_map *nmap = &(wld.map);
 
   fc_assert_ret_val((role >= 0 && role <= UTYF_LAST_USER_FLAG)
                     || (role >= L_FIRST && role < L_LAST)
@@ -2328,7 +2329,7 @@ struct unit_type *best_role_unit(const struct city *pcity, int role)
 
   for (j = n_with_role[role] - 1; j >= 0; j--) {
     u = with_role[role][j];
-    if (can_city_build_unit_now(pcity, u)) {
+    if (can_city_build_unit_now(nmap, pcity, u)) {
       return u;
     }
   }
diff --git a/server/cityturn.c b/server/cityturn.c
index 9bf14d70ee..b6f5a84db7 100644
--- a/server/cityturn.c
+++ b/server/cityturn.c
@@ -2229,6 +2229,8 @@ static bool worklist_change_build_target(struct player *pplayer,
 **************************************************************************/
 void choose_build_target(struct player *pplayer, struct city *pcity)
 {
+  const struct civ_map *nmap = &(wld.map);
+
   /* Pick the next thing off the worklist. */
   if (worklist_change_build_target(pplayer, pcity)) {
     return;
@@ -2240,7 +2242,7 @@ void choose_build_target(struct player *pplayer, struct city *pcity)
   case VUT_UTYPE:
     /* We can build a unit again unless it's unique or we have lost the tech. */
     if (!utype_has_flag(pcity->production.value.utype, UTYF_UNIQUE)
-        && can_city_build_unit_now(pcity, pcity->production.value.utype)) {
+        && can_city_build_unit_now(nmap, pcity, pcity->production.value.utype)) {
       log_base(LOG_BUILD_TARGET, "%s repeats building %s", city_name_get(pcity),
                utype_rule_name(pcity->production.value.utype));
       return;
diff --git a/server/techtools.c b/server/techtools.c
index cf2e292ea4..d542207f6b 100644
--- a/server/techtools.c
+++ b/server/techtools.c
@@ -801,6 +801,7 @@ static void research_tech_lost(struct research *presearch, Tech_type_id tech)
 {
   char research_name[MAX_LEN_NAME * 2];
   /* Research members will be notified when new tech is chosen. */
+  const struct civ_map *nmap = &(wld.map);
 
   research_pretty_name(presearch, research_name, sizeof(research_name));
 
@@ -878,7 +879,7 @@ static void research_tech_lost(struct research *presearch, Tech_type_id tech)
       bool update = FALSE;
 
       if (pcity->production.kind == VUT_UTYPE
-          && !can_city_build_unit_now(pcity, pcity->production.value.utype)) {
+          && !can_city_build_unit_now(nmap, pcity, pcity->production.value.utype)) {
         notify_player(pplayer, city_tile(pcity),
                       E_CITY_CANTBUILD, ftc_server,
                       _("%s can't build %s. The required technology was "
-- 
2.43.0

