Author: cazfi
Date: Thu Nov 19 22:08:59 2015
New Revision: 30699

URL: http://svn.gna.org/viewcvs/freeciv?rev=30699&view=rev
Log:
Cache unit type vs unit type defense multiplier combat bonuses, and use those 
cached
values instead of recalculating them every time they are needed.

See patch #6546

Modified:
    branches/S2_5/ai/default/advmilitary.c
    branches/S2_5/ai/default/aitech.c
    branches/S2_5/client/packhand.c
    branches/S2_5/common/combat.c
    branches/S2_5/common/unittype.c
    branches/S2_5/common/unittype.h

Modified: branches/S2_5/ai/default/advmilitary.c
URL: 
http://svn.gna.org/viewcvs/freeciv/branches/S2_5/ai/default/advmilitary.c?rev=30699&r1=30698&r2=30699&view=diff
==============================================================================
--- branches/S2_5/ai/default/advmilitary.c      (original)
+++ branches/S2_5/ai/default/advmilitary.c      Thu Nov 19 22:08:59 2015
@@ -485,36 +485,24 @@
   } unit_type_iterate_end;
 
   unit_list_iterate(ptile->units, punit) {
-    bool bonuses_exist = FALSE;
     struct unit_type *def = unit_type(punit);
 
     if (unit_has_type_flag(punit, UTYF_DIPLOMAT)) {
       city_data->has_diplomat = TRUE;
     }
     if (!defender_type_handled[utype_index(def)]) {
-      /* This is first defender of this type. Calculate defender type
+      /* This is first defender of this type. Check defender type
        * specific bonuses. */
 
-      /* Vast majority of units have no Defense Multiplier bonus.
-       * Do not waste time on iterating through all unit types in the
-       * typical case by first checking if such bonuses exist against
-       * any units. */
-      combat_bonus_list_iterate(def->bonuses, pbonus) {
-        if (pbonus->type == CBONUS_DEFENSE_MULTIPLIER) {
-          bonuses_exist = TRUE;
-          break;
-        }
-      } combat_bonus_list_iterate_end;
-
-      if (bonuses_exist) {
+      /* Skip defenders that have no bonuses at all. Acceptable
+       * side-effect is that we can't consider negative bonuses at
+       * all ("No bonuses" should be better than "negative bonus") */
+      if (def->cache.max_defense_mp > 0) {
         unit_type_iterate(utype) {
-          int bonus;
           int idx = utype_index(utype);
 
-          bonus = combat_bonus_against(def->bonuses, utype,
-                                       CBONUS_DEFENSE_MULTIPLIER);
-          if (bonus > defense_bonuses[idx]) {
-            defense_bonuses[idx] = bonus;
+          if (def->cache.defense_mp_bonuses[idx] > defense_bonuses[idx]) {
+            defense_bonuses[idx] = def->cache.defense_mp_bonuses[idx];
           }
         } unit_type_iterate_end;
       }
@@ -685,12 +673,7 @@
   desire += punittype->move_rate / SINGLE_MOVE;
   desire += attack;
 
-  combat_bonus_list_iterate(punittype->bonuses, pbonus) {
-    if (pbonus->type == CBONUS_DEFENSE_MULTIPLIER
-        && pbonus->value > maxbonus) {
-      maxbonus = pbonus->value;
-    }
-  } combat_bonus_list_iterate_end;
+  maxbonus = punittype->cache.max_defense_mp;
   if (maxbonus > 1) {
     maxbonus = (maxbonus + 1) / 2;
   }
@@ -698,6 +681,7 @@
   if (utype_has_flag(punittype, UTYF_GAMELOSS)) {
     desire /= 10; /* but might actually be worth it */
   }
+
   return desire;
 }
 

Modified: branches/S2_5/ai/default/aitech.c
URL: 
http://svn.gna.org/viewcvs/freeciv/branches/S2_5/ai/default/aitech.c?rev=30699&r1=30698&r2=30699&view=diff
==============================================================================
--- branches/S2_5/ai/default/aitech.c   (original)
+++ branches/S2_5/ai/default/aitech.c   Thu Nov 19 22:08:59 2015
@@ -253,9 +253,10 @@
   struct advance *best_tech = A_NEVER;
   struct unit_type *best_unit = NULL;
   int def_values[U_LAST];
+  int att_idx = utype_index(att);
 
   unit_type_iterate(deftype) {
-    int mp = combat_bonus_against(deftype->bonuses, att, 
CBONUS_DEFENSE_MULTIPLIER) + 1;
+    int mp = deftype->cache.defense_mp_bonuses[att_idx] + 1;
     int div = combat_bonus_against(att->bonuses, deftype, 
CBONUS_DEFENSE_DIVIDER) + 1;
     int def = deftype->defense_strength * mp / div;
 

Modified: branches/S2_5/client/packhand.c
URL: 
http://svn.gna.org/viewcvs/freeciv/branches/S2_5/client/packhand.c?rev=30699&r1=30698&r2=30699&view=diff
==============================================================================
--- branches/S2_5/client/packhand.c     (original)
+++ branches/S2_5/client/packhand.c     Thu Nov 19 22:08:59 2015
@@ -2972,6 +2972,10 @@
   unit_class_iterate(pclass) {
     set_unit_class_caches(pclass);
   } unit_class_iterate_end;
+
+  unit_type_iterate(ptype) {
+    set_unit_type_caches(ptype);
+  } unit_type_iterate_end;
 
   /* We are not going to crop any more sprites from big sprites, free them. */
   finish_loading_sprites(tileset);

Modified: branches/S2_5/common/combat.c
URL: 
http://svn.gna.org/viewcvs/freeciv/branches/S2_5/common/combat.c?rev=30699&r1=30698&r2=30699&view=diff
==============================================================================
--- branches/S2_5/common/combat.c       (original)
+++ branches/S2_5/common/combat.c       Thu Nov 19 22:08:59 2015
@@ -515,8 +515,7 @@
 
   if (NULL != att_type) {
     int defense_divider;
-    int defense_multiplier = 1 + combat_bonus_against(def_type->bonuses, 
att_type,
-                                                      
CBONUS_DEFENSE_MULTIPLIER);
+    int defense_multiplier = 1 + 
def_type->cache.defense_mp_bonuses[utype_index(att_type)];
 
     defensepower *= defense_multiplier;
 
@@ -747,6 +746,9 @@
 
 /**************************************************************************
   Get bonus value against given unit type from bonus list.
+
+  Consider using cached values instead of calling this recalculation
+  directly.
 **************************************************************************/
 int combat_bonus_against(const struct combat_bonus_list *list,
                          const struct unit_type *enemy,

Modified: branches/S2_5/common/unittype.c
URL: 
http://svn.gna.org/viewcvs/freeciv/branches/S2_5/common/unittype.c?rev=30699&r1=30698&r2=30699&view=diff
==============================================================================
--- branches/S2_5/common/unittype.c     (original)
+++ branches/S2_5/common/unittype.c     Thu Nov 19 22:08:59 2015
@@ -28,6 +28,7 @@
 #include "support.h"
 
 /* common */
+#include "combat.h"
 #include "game.h"
 #include "government.h"
 #include "movement.h"
@@ -1308,6 +1309,24 @@
   return ptype->ais[ai_type_number(ai)];
 }
 
+/****************************************************************************
+  Set caches for unit types.
+****************************************************************************/
+void set_unit_type_caches(struct unit_type *ptype)
+{
+  ptype->cache.max_defense_mp = -FC_INFINITY;
+
+  unit_type_iterate(utype) {
+    int idx = utype_index(utype);
+
+    ptype->cache.defense_mp_bonuses[idx] = 
combat_bonus_against(ptype->bonuses, utype,
+                                                                
CBONUS_DEFENSE_MULTIPLIER);
+    if (ptype->cache.defense_mp_bonuses[idx] > ptype->cache.max_defense_mp) {
+      ptype->cache.max_defense_mp = ptype->cache.defense_mp_bonuses[idx];
+    }
+  } unit_type_iterate_end;
+}
+
 /**************************************************************************
   Attach ai data to unit type
 **************************************************************************/

Modified: branches/S2_5/common/unittype.h
URL: 
http://svn.gna.org/viewcvs/freeciv/branches/S2_5/common/unittype.h?rev=30699&r1=30698&r2=30699&view=diff
==============================================================================
--- branches/S2_5/common/unittype.h     (original)
+++ branches/S2_5/common/unittype.h     Thu Nov 19 22:08:59 2015
@@ -459,6 +459,13 @@
 
   struct strvec *helptext;
 
+  struct {
+    int max_defense_mp; /* Value 0 here does not guarantee that unit never
+                         * has CBONUS_DEFENSE_MULTIPLIER, it merely means
+                         * that there's no POSITIVE one */
+    int defense_mp_bonuses[U_LAST];
+  } cache;
+
   void *ais[FC_AI_LAST];
 };
 
@@ -626,6 +633,7 @@
 void unit_classes_free(void);
 
 void set_unit_class_caches(struct unit_class *pclass);
+void set_unit_type_caches(struct unit_type *ptype);
 
 struct unit_class *unit_class_array_first(void);
 const struct unit_class *unit_class_array_last(void);


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

Reply via email to