From 78489164ebf321405050cb056fbb6da95199117a Mon Sep 17 00:00:00 2001
From: Marko Lindqvist <cazfi74@gmail.com>
Date: Mon, 8 Apr 2024 19:47:55 +0300
Subject: [PATCH 53/53] Add support for UnitClassFlag requirements on Tile -
 Adjacent ranges

Requested by alienvalkyrie

See RM #401

Signed-off-by: Marko Lindqvist <cazfi74@gmail.com>
---
 common/requirements.c | 64 ++++++++++++++++++++++++++++++++++++++-----
 doc/README.effects    |  2 +-
 2 files changed, 58 insertions(+), 8 deletions(-)

diff --git a/common/requirements.c b/common/requirements.c
index 7746f536ca..93e1a05bb6 100644
--- a/common/requirements.c
+++ b/common/requirements.c
@@ -1059,7 +1059,7 @@ struct requirement req_from_str(const char *type, const char *range,
   if (invalid) {
     error = "bad type or name";
   } else {
-    /* Scan the range string to find the range.  If no range is given a
+    /* Scan the range string to find the range. If no range is given a
      * default fallback is used rather than giving an error. */
     if (range != NULL) {
       req.range = req_range_by_name(range, fc_strcasecmp);
@@ -1240,7 +1240,6 @@ struct requirement req_from_str(const char *type, const char *range,
                  && req.range != REQ_RANGE_ALLIANCE
                  && req.range != REQ_RANGE_WORLD);
       break;
-    case VUT_UCFLAG:
     case VUT_MINVETERAN:
     case VUT_UNITSTATE:
     case VUT_ACTIVITY:
@@ -1254,6 +1253,7 @@ struct requirement req_from_str(const char *type, const char *range,
     case VUT_UTYPE:
     case VUT_UTFLAG:
     case VUT_UCLASS:
+    case VUT_UCFLAG:
       invalid = (req.range != REQ_RANGE_LOCAL
                  && req.range != REQ_RANGE_TILE
                  && req.range != REQ_RANGE_CADJACENT
@@ -4314,14 +4314,64 @@ is_unitclassflag_req_active(const struct civ_map *nmap,
 
   ucflag = req->source.value.unitclassflag;
 
-  if (req->range != REQ_RANGE_LOCAL) {
+  switch (req->range) {
+  case REQ_RANGE_LOCAL:
+    if (!context->unittype) {
+      return TRI_MAYBE;
+    }
+    return BOOL_TO_TRISTATE(uclass_has_flag(utype_class(context->unittype), ucflag));
+  case REQ_RANGE_TILE:
+  case REQ_RANGE_CADJACENT:
+  case REQ_RANGE_ADJACENT:
+    if (context->tile == nullptr) {
+      return TRI_MAYBE;
+    }
+
+    unit_list_iterate(context->tile->units, punit) {
+      if (unit_has_class_flag(punit, ucflag)) {
+        return TRI_YES;
+      }
+    } unit_list_iterate_end;
+
+    if (req->range == REQ_RANGE_TILE) {
+      return TRI_NO;
+    }
+
+    if (req->range == REQ_RANGE_CADJACENT) {
+      cardinal_adjc_iterate(nmap, context->tile, adjc_tile) {
+        unit_list_iterate(adjc_tile->units, punit) {
+          if (unit_has_class_flag(punit, ucflag)) {
+            return TRI_YES;
+          }
+        } unit_list_iterate_end;
+      } cardinal_adjc_iterate_end;
+    } else {
+      fc_assert(req->range == REQ_RANGE_ADJACENT);
+
+      adjc_iterate(nmap, context->tile, adjc_tile) {
+        unit_list_iterate(adjc_tile->units, punit) {
+          if (unit_has_class_flag(punit, ucflag)) {
+            return TRI_YES;
+          }
+        } unit_list_iterate_end;
+      } adjc_iterate_end;
+    }
+
     return TRI_NO;
-  }
-  if (!context->unittype) {
-    return TRI_MAYBE;
+
+  case REQ_RANGE_CITY:
+  case REQ_RANGE_TRADE_ROUTE:
+  case REQ_RANGE_CONTINENT:
+  case REQ_RANGE_PLAYER:
+  case REQ_RANGE_TEAM:
+  case REQ_RANGE_ALLIANCE:
+  case REQ_RANGE_WORLD:
+  case REQ_RANGE_COUNT:
+    fc_assert(FALSE);
+    break;
   }
 
-  return BOOL_TO_TRISTATE(uclass_has_flag(utype_class(context->unittype), ucflag));
+  return TRI_NO;
 }
 
 /**********************************************************************//**
diff --git a/doc/README.effects b/doc/README.effects
index ff5c2fe099..5e29fc1352 100644
--- a/doc/README.effects
+++ b/doc/README.effects
@@ -74,7 +74,7 @@ Good:            City
 UnitType:        Local, Tile, CAdjacent, Adjacent
 UnitFlag:        Local, Tile, CAdjacent, Adjacent
 UnitClass:       Local, Tile, CAdjacent, Adjacent
-UnitClassFlag:   Local
+UnitClassFlag:   Local, Tile, CAdjacent, Adjacent
 Nation:          World, Alliance, Team, Player
 NationGroup:     World, Alliance, Team, Player
 Nationality:     Traderoute, City
-- 
2.43.0

