Author: sveinung
Date: Wed Apr  5 16:22:30 2017
New Revision: 35203

URL: http://svn.gna.org/viewcvs/freeciv?rev=35203&view=rev
Log:
Cache target CityTile state action legality.

See hrm Feature #649824

Modified:
    trunk/common/unittype.c
    trunk/common/unittype.h

Modified: trunk/common/unittype.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/common/unittype.c?rev=35203&r1=35202&r2=35203&view=diff
==============================================================================
--- trunk/common/unittype.c     (original)
+++ trunk/common/unittype.c     Wed Apr  5 16:22:30 2017
@@ -340,13 +340,24 @@
  */
 BV_DEFINE(bv_ustate_act_cache, USP_COUNT * 2);
 
+/* Cache what actions may be possible when the target's local citytile state
+ * is
+ * bit 0 to CITYT_LAST - 1: Possible when the corresponding property is TRUE
+ * bit USP_COUNT to ((CITYT_LAST * 2) - 1): Possible when the corresponding
+ * property is FALSE
+ */
+BV_DEFINE(bv_citytile_cache, CITYT_LAST * 2);
+
 /* Cache position lookup functions */
 #define requirement_unit_state_ereq(_id_, _present_)                       \
   requirement_kind_ereq(_id_, REQ_RANGE_LOCAL, _present_, USP_COUNT)
+#define requirement_citytile_ereq(_id_, _present_)                         \
+  requirement_kind_ereq(_id_, REQ_RANGE_LOCAL, _present_, CITYT_LAST)
 
 /* Caches for each unit type */
 static bv_ustate_act_cache ustate_act_cache[U_LAST][ACTION_AND_FAKES];
 static bv_diplrel_all_reqs dipl_rel_action_cache[U_LAST][ACTION_AND_FAKES];
+static bv_citytile_cache ctile_tgt_act_cache[U_LAST][ACTION_AND_FAKES];
 
 /**************************************************************************
   Cache if any action may be possible for a unit of the type putype for
@@ -504,6 +515,84 @@
   }
 }
 
+/**************************************************************************
+  Cache if any action may be possible for a unit of the type putype for
+  each target local city tile property. Both present and !present must be
+  checked since a city tile property could be ignored.
+**************************************************************************/
+static void tgt_citytile_act_cache_set(struct unit_type *putype)
+{
+  struct requirement req;
+  int uidx = utype_index(putype);
+
+  /* The unit is not yet known to be allowed to perform any actions no
+   * matter what its target's CityTile state is. */
+  action_iterate(action_id) {
+    BV_CLR_ALL(ctile_tgt_act_cache[uidx][action_id]);
+  } action_iterate_end;
+  BV_CLR_ALL(ctile_tgt_act_cache[uidx][ACTION_ANY]);
+  BV_CLR_ALL(ctile_tgt_act_cache[uidx][ACTION_HOSTILE]);
+
+  if (!utype_may_act_at_all(putype)) {
+    /* Not an actor unit. */
+    return;
+  }
+
+  /* Common for every situation */
+  req.range = REQ_RANGE_LOCAL;
+  req.survives = FALSE;
+  req.source.kind = VUT_CITYTILE;
+
+  for (req.source.value.citytile = citytile_type_begin();
+       req.source.value.citytile != citytile_type_end();
+       req.source.value.citytile = citytile_type_next(
+         req.source.value.citytile)) {
+
+    /* No action will ever be possible in a target CityTile state if the
+     * opposite target CityTile state is required in all action enablers.
+     * No CityTile property state except present and !present of the same
+     * property implies or conflicts with another so the tests can be
+     * simple. */
+    action_enablers_iterate(enabler) {
+      if (requirement_fulfilled_by_unit_type(putype,
+                                             &(enabler->target_reqs))
+          && action_id_get_actor_kind(enabler->action) == AAK_UNIT) {
+        /* Not required to be absent, so OK if present */
+        req.present = FALSE;
+        if (!is_req_in_vec(&req, &(enabler->target_reqs))) {
+          BV_SET(ctile_tgt_act_cache[utype_index(putype)][enabler->action],
+              requirement_citytile_ereq(req.source.value.citytile,
+                                        TRUE));
+          if (action_is_hostile(enabler->action)) {
+            BV_SET(ctile_tgt_act_cache[utype_index(putype)][ACTION_HOSTILE],
+                requirement_citytile_ereq(req.source.value.citytile,
+                                          TRUE));
+          }
+          BV_SET(ctile_tgt_act_cache[utype_index(putype)][ACTION_ANY],
+              requirement_citytile_ereq(req.source.value.citytile,
+                                        TRUE));
+        }
+
+        /* Not required to be present, so OK if absent */
+        req.present = TRUE;
+        if (!is_req_in_vec(&req, &(enabler->target_reqs))) {
+          BV_SET(ctile_tgt_act_cache[utype_index(putype)][enabler->action],
+              requirement_citytile_ereq(req.source.value.citytile,
+                                        FALSE));
+          if (action_is_hostile(enabler->action)) {
+            BV_SET(ctile_tgt_act_cache[utype_index(putype)][ACTION_HOSTILE],
+                requirement_citytile_ereq(req.source.value.citytile,
+                                          FALSE));
+          }
+          BV_SET(ctile_tgt_act_cache[utype_index(putype)][ACTION_ANY],
+              requirement_citytile_ereq(req.source.value.citytile,
+                                        FALSE));
+        }
+      }
+    } action_enablers_iterate_end;
+  }
+}
+
 struct range {
   int min;
   int max;
@@ -545,6 +634,7 @@
   unit_can_act_cache_set(ptype);
   unit_state_action_cache_set(ptype);
   local_dipl_rel_action_cache_set(ptype);
+  tgt_citytile_act_cache_set(ptype);
 }
 
 /**************************************************************************
@@ -582,6 +672,20 @@
 {
   return BV_ISSET(ustate_act_cache[utype_index(punit_type)][action_id],
       requirement_unit_state_ereq(prop, is_there));
+}
+
+/**************************************************************************
+  Returns TRUE iff the unit type can do the specified (action enabler
+  controlled) action while its target's CityTile property state has the
+  value is_there.
+**************************************************************************/
+bool utype_can_do_act_if_tgt_citytile(const struct unit_type *punit_type,
+                                      const int action_id,
+                                      const enum citytile_type prop,
+                                      const bool is_there)
+{
+  return BV_ISSET(ctile_tgt_act_cache[utype_index(punit_type)][action_id],
+      requirement_citytile_ereq(prop, is_there));
 }
 
 /**************************************************************************

Modified: trunk/common/unittype.h
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/common/unittype.h?rev=35203&r1=35202&r2=35203&view=diff
==============================================================================
--- trunk/common/unittype.h     (original)
+++ trunk/common/unittype.h     Wed Apr  5 16:22:30 2017
@@ -615,6 +615,11 @@
                                   const enum ustate_prop prop,
                                   const bool is_there);
 
+bool utype_can_do_act_if_tgt_citytile(const struct unit_type *punit_type,
+                                      const int action_id,
+                                      const enum citytile_type prop,
+                                      const bool is_there);
+
 bool can_utype_do_act_if_tgt_diplrel(const struct unit_type *punit_type,
                                      const int action_id,
                                      const int prop,


_______________________________________________
Freeciv-commits mailing list
Freeciv-commits@gna.org
https://mail.gna.org/listinfo/freeciv-commits

Reply via email to