Complete.Org: Mailing Lists: Archives: freeciv-dev: June 2005:
[Freeciv-Dev] (PR#13384) [Patch] unit_class_transporter_capacity()
Home

[Freeciv-Dev] (PR#13384) [Patch] unit_class_transporter_capacity()

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#13384) [Patch] unit_class_transporter_capacity()
From: "Marko Lindqvist" <marko.lindqvist@xxxxxxxxxxx>
Date: Thu, 30 Jun 2005 08:18:51 -0700
Reply-to: bugs@xxxxxxxxxxx

<URL: http://bugs.freeciv.org/Ticket/Display.html?id=13384 >


  This patch replaces ground_unit_transporter_capacity() and 
is_ground_units_transport() with more generic 
unit_class_transporter_capacity() and can_unit_type_transport().
  Biggest change is that ground_unit_transporter_capacity() used to 
subtract even not transported units from capacity, for instance when 
transporter is in a city, but unit_class_transporter_capacity() returns 
actual free space in transporters. As a side effect #11064 is solved to 
the extend that it does not cause real problems (allied transporter 
filled with allys allies is not considered empty)

  Developed on top of #13344, patch may apply without it or maybe not.


  - ML


diff -Nurd -X.diff_ignore freeciv/ai/advmilitary.c freeciv/ai/advmilitary.c
--- freeciv/ai/advmilitary.c    2005-06-29 02:13:46.328125000 +0300
+++ freeciv/ai/advmilitary.c    2005-06-30 00:33:18.890625000 +0300
@@ -489,7 +489,7 @@
       }
 
       if ((is_ground_unit(punit) && vulnerability != 0)
-          || (is_ground_units_transport(punit))) {
+          || (can_unit_type_transport(punit->type, UCL_LAND))) {
         if (dist <= move_rate * 3 || dist <= paramove + move_rate) {
           urgency++;
         }
diff -Nurd -X.diff_ignore freeciv/ai/aidata.c freeciv/ai/aidata.c
--- freeciv/ai/aidata.c 2005-06-29 02:13:46.328125000 +0300
+++ freeciv/ai/aidata.c 2005-06-30 00:33:18.984375000 +0300
@@ -458,7 +458,7 @@
       if (is_sailing_unit(punit)) {
         /* If the enemy has not started sailing yet, or we have total
          * control over the seas, don't worry, keep attacking. */
-        if (is_ground_units_transport(punit)) {
+        if (can_unit_type_transport(punit->type, UCL_LAND)) {
           ai->threats.invasions = TRUE;
         }
 
diff -Nurd -X.diff_ignore freeciv/ai/aiferry.c freeciv/ai/aiferry.c
--- freeciv/ai/aiferry.c        2005-06-29 02:13:46.343750000 +0300
+++ freeciv/ai/aiferry.c        2005-06-30 00:33:19.109375000 +0300
@@ -76,7 +76,7 @@
   ai->stats.available_boats = 0;
  
   unit_list_iterate(pplayer->units, punit) {
-    if (is_sailing_unit(punit) && is_ground_units_transport(punit)) {
+    if (is_sailing_unit(punit) && can_unit_type_transport(punit->type, 
UCL_LAND)) {
       ai->stats.boats++;
       if (punit->ai.passenger == FERRY_AVAILABLE) {
        ai->stats.available_boats++;
@@ -103,8 +103,8 @@
   freelog(LOG_NORMAL, "Registered: %d free out of total %d",
          ai->stats.available_boats, ai->stats.boats);
   unit_list_iterate(pplayer->units, punit) {
-    if (is_sailing_unit(punit) && is_ground_units_transport(punit)) {
-      freelog(LOG_NORMAL, "#%d. %s[%d], psngr=%d", 
+    if (is_sailing_unit(punit) && can_unit_type_transport(punit->type, 
UCL_LAND)) {
+      freelog(LOG_NORMAL, "#%d. %s[%d], psngr=%d",
              n, unit_type(punit)->name, punit->id, punit->ai.passenger);
       n++;
     }
@@ -203,7 +203,7 @@
   int boats = 0;
 
   unit_list_iterate(pplayer->units, punit) {
-    if (is_sailing_unit(punit) && is_ground_units_transport(punit) 
+    if (is_sailing_unit(punit) && can_unit_type_transport(punit->type, 
UCL_LAND) 
        && punit->ai.passenger == FERRY_AVAILABLE) {
       boats++;
     }
diff -Nurd -X.diff_ignore freeciv/common/aicore/pf_tools.c 
freeciv/common/aicore/pf_tools.c
--- freeciv/common/aicore/pf_tools.c    2005-06-29 02:13:46.343750000 +0300
+++ freeciv/common/aicore/pf_tools.c    2005-06-30 00:33:19.203125000 +0300
@@ -126,7 +126,7 @@
   int move_cost;
 
   if (is_ocean(terrain1)) {
-    if (ground_unit_transporter_capacity(ptile1, param->owner) > 0) {
+    if (unit_class_transporter_capacity(ptile1, param->owner, UCL_LAND) > 0) {
       move_cost = SINGLE_MOVE;
     } else {
       move_cost = PF_IMPOSSIBLE_MC;
@@ -159,7 +159,7 @@
   if (is_ocean(tgt_tile->terrain)) {
 
     /* Any-to-Sea */
-    if (ground_unit_transporter_capacity(tgt_tile, param->owner) > 0) {
+    if (unit_class_transporter_capacity(tgt_tile, param->owner, UCL_LAND) > 0) 
{
       move_cost = SINGLE_MOVE;
     } else {
       move_cost = PF_IMPOSSIBLE_MC;
@@ -245,7 +245,7 @@
   int move_cost = PF_IMPOSSIBLE_MC;
 
   if (is_ocean(terrain1)) {
-    if (ground_unit_transporter_capacity(ptile, param->owner) > 0) {
+    if (unit_class_transporter_capacity(ptile, param->owner, UCL_LAND) > 0) {
       /* Landing */
       move_cost = get_tile_type(terrain0)->movement_cost * SINGLE_MOVE;
     } else {
@@ -273,7 +273,7 @@
   int move_cost;
 
   if (is_ocean(ptile1->terrain)) {
-    if (ground_unit_transporter_capacity(ptile1, param->owner) > 0) {
+    if (unit_class_transporter_capacity(ptile1, param->owner, UCL_LAND) > 0) {
       move_cost = MOVE_COST_ROAD;
     } else {
       move_cost = PF_IMPOSSIBLE_MC;
@@ -306,7 +306,7 @@
   int move_cost;
 
   if (is_ocean(tile_get_terrain(ptile))) {
-    if (ground_unit_transporter_capacity(ptile, param->owner) > 0) {
+    if (unit_class_transporter_capacity(ptile, param->owner, UCL_LAND) > 0) {
       /* Landing */
       move_cost = MOVE_COST_ROAD;
     } else {
diff -Nurd -X.diff_ignore freeciv/common/movement.c freeciv/common/movement.c
--- freeciv/common/movement.c   2005-06-30 00:32:36.234375000 +0300
+++ freeciv/common/movement.c   2005-06-30 00:36:32.953125000 +0300
@@ -23,6 +23,7 @@
 #include "support.h"
 
 #include "fc_types.h"
+#include "game.h"
 #include "map.h"
 #include "movement.h"
 #include "unit.h"
@@ -30,9 +31,6 @@
 #include "terrain.h"
 
 
-static bool can_unit_type_transport(Unit_type_id transporter,
-                                    Unit_type_id transported);
-
 /****************************************************************************
   This function calculates the move rate of the unit, taking into 
   account the penalty for reduced hitpoints (affects sea and land 
@@ -354,10 +352,11 @@
     return MR_DESTINATION_OCCUPIED_BY_NON_ALLIED_UNIT;
   }
 
+  /* 4) */
   if (unit_types[type].move_type == LAND_MOVING) {
-    /* 4) */
-    if (is_ocean(dst_tile->terrain) &&
-       ground_unit_transporter_capacity(dst_tile, unit_owner) <= 0) {
+    if (is_ocean(dst_tile->terrain)
+        && unit_class_transporter_capacity(dst_tile, unit_owner,
+                                           get_unit_type(type)->class) <= 0) {
       /* Ground units can't move onto ocean tiles unless there's enough
        * room on transporters for them. */
       return MR_NO_SEA_TRANSPORTER_CAPACITY;
@@ -423,20 +422,24 @@
 bool can_unit_transport(const struct unit *transporter,
                         const struct unit *transported)
 {
-  return can_unit_type_transport(transporter->type, transported->type);
+  return can_unit_type_transport(transporter->type,
+                                 get_unit_type(transported->type)->class);
 }
 
 /**************************************************************************
-  Return TRUE iff transporter type has ability to transport transported type.
+  Return TRUE iff transporter type has ability to transport transported class
 **************************************************************************/
-static bool can_unit_type_transport(Unit_type_id transporter,
-                                    Unit_type_id transported)
+bool can_unit_type_transport(Unit_type_id transporter,
+                             Unit_Class_id transported)
 {
+  struct unit_class *pclass = unit_class_from_id(transported);
+
   if (get_unit_type(transporter)->transport_capacity <= 0) {
     return FALSE;
   }
 
-  if (get_unit_type(transported)->move_type == LAND_MOVING) {
+  /* TODO: Should not be hardcoded into class enum */
+  if (pclass->id == UCL_LAND) {
     if ((unit_type_flag(transporter, F_CARRIER)
          || unit_type_flag(transporter, F_MISSILE_CARRIER))) {
       return FALSE;
@@ -444,26 +447,53 @@
     return TRUE;
   }
 
-  if (!unit_type_flag(transported, F_MISSILE)
-     && unit_type_flag(transporter, F_MISSILE_CARRIER)) {
+  if (pclass->id != UCL_MISSILE && pclass->id != UCL_NUCLEAR
+      && unit_type_flag(transporter, F_MISSILE_CARRIER)) {
     return FALSE;
   }
 
-  if (unit_type_flag(transported, F_MISSILE)) {
+  if (pclass->id == UCL_MISSILE || pclass->id == UCL_NUCLEAR) {
     if (!unit_type_flag(transporter, F_MISSILE_CARRIER)
         && !unit_type_flag(transporter, F_CARRIER)) {
       return FALSE;
     }
-  } else if ((get_unit_type(transported)->move_type == AIR_MOVING
-              || get_unit_type(transported)->move_type == HELI_MOVING)
+  } else if ((pclass->id == UCL_AIR || pclass->id == UCL_HELICOPTER)
              && !unit_type_flag(transporter, F_CARRIER)) {
     return FALSE;
   }
 
-  if (get_unit_type(transported)->move_type == SEA_MOVING) {
+  if (pclass->id == UCL_SEA) {
     /* No unit can transport sea units at the moment */
     return FALSE;
   }
 
   return TRUE;
 }
+
+/**************************************************************************
+ Returns the number of free spaces for units of given class.
+ Can be 0.
+**************************************************************************/
+int unit_class_transporter_capacity(const struct tile *ptile,
+                                    const struct player *pplayer,
+                                    Unit_Class_id class)
+{
+  int availability = 0;
+
+  unit_list_iterate(ptile->units, punit) {
+    if (unit_owner(punit) == pplayer
+        || pplayers_allied(unit_owner(punit), pplayer)) {
+
+      if (can_unit_type_transport(punit->type, class)) {
+        availability += get_transporter_capacity(punit);
+        unit_list_iterate(ptile->units, cargo) {
+          if (cargo->transported_by == punit->id) {
+            availability--;
+          }
+        } unit_list_iterate_end;
+      }
+    }
+  } unit_list_iterate_end;
+
+  return availability;
+}
diff -Nurd -X.diff_ignore freeciv/common/movement.h freeciv/common/movement.h
--- freeciv/common/movement.h   2005-06-29 02:13:46.359375000 +0300
+++ freeciv/common/movement.h   2005-06-30 00:33:19.421875000 +0300
@@ -49,5 +49,10 @@
                                             const struct tile *dst_tile,
                                             bool igzoc);
 bool can_unit_transport(const struct unit *transporter, const struct unit 
*transported);
+bool can_unit_type_transport(Unit_type_id transporter,
+                             Unit_Class_id transported);
+int unit_class_transporter_capacity(const struct tile *ptile,
+                                    const struct player *pplayer,
+                                    Unit_Class_id class);
 
 #endif  /* FC__MOVEMENT_H */
diff -Nurd -X.diff_ignore freeciv/common/unit.c freeciv/common/unit.c
--- freeciv/common/unit.c       2005-06-29 02:13:46.359375000 +0300
+++ freeciv/common/unit.c       2005-06-30 00:33:19.546875000 +0300
@@ -213,31 +213,6 @@
          && can_cities_trade(phomecity, pdestcity));
 }
 
-
-/**************************************************************************
-Returns the number of free spaces for ground units. Can be 0 or negative.
-**************************************************************************/
-int ground_unit_transporter_capacity(const struct tile *ptile,
-                                    const struct player *pplayer)
-{
-  int availability = 0;
-
-  unit_list_iterate(ptile->units, punit) {
-    if (unit_owner(punit) == pplayer
-        || pplayers_allied(unit_owner(punit), pplayer)) {
-      if (is_ground_units_transport(punit)
-         && !(is_ground_unit(punit) && is_ocean(ptile->terrain))) {
-       availability += get_transporter_capacity(punit);
-      } else if (is_ground_unit(punit)) {
-       availability--;
-      }
-    }
-  }
-  unit_list_iterate_end;
-
-  return availability;
-}
-
 /**************************************************************************
   Return the number of units the transporter can hold (or 0).
 **************************************************************************/
@@ -247,16 +222,6 @@
 }
 
 /**************************************************************************
-  Return TRUE iff the unit is a transporter of ground units.
-**************************************************************************/
-bool is_ground_units_transport(const struct unit *punit)
-{
-  return (get_transporter_capacity(punit) > 0
-         && !unit_flag(punit, F_MISSILE_CARRIER)
-         && !unit_flag(punit, F_CARRIER));
-}
-
-/**************************************************************************
   Is the unit capable of attacking?
 **************************************************************************/
 bool is_attack_unit(const struct unit *punit)
@@ -1580,7 +1545,7 @@
   if (get_transporter_occupancy(punit) >
       unit_types[to_unittype].transport_capacity) {
     /* TODO: allow transported units to be reassigned.  Check for
-     * ground_unit_transporter_capacity here and make changes to
+     * unit_class_transporter_capacity(UCL_LAND) here and make changes to
      * upgrade_unit. */
     return UR_NOT_ENOUGH_ROOM;
   }
diff -Nurd -X.diff_ignore freeciv/common/unit.h freeciv/common/unit.h
--- freeciv/common/unit.h       2005-06-29 02:13:46.375000000 +0300
+++ freeciv/common/unit.h       2005-06-30 00:33:19.640625000 +0300
@@ -287,10 +287,7 @@
 bool kills_citizen_after_attack(const struct unit *punit);
 
 const char *unit_activity_text(const struct unit *punit);
-int ground_unit_transporter_capacity(const struct tile *ptile,
-                                    const struct player *pplayer);
 int get_transporter_capacity(const struct unit *punit);
-bool is_ground_units_transport(const struct unit *punit);
 int missile_carrier_capacity(const struct tile *ptile,
                             const struct player *pplayer,
                             bool count_units_with_extra_fuel);
diff -Nurd -X.diff_ignore freeciv/common/unittype.c freeciv/common/unittype.c
--- freeciv/common/unittype.c   2005-06-30 00:32:36.328125000 +0300
+++ freeciv/common/unittype.c   2005-06-30 00:33:19.765625000 +0300
@@ -61,7 +61,7 @@
   "Sea",
   "Helicopter",
   "Air",
-  "Nuclear",
+  "Nuclear"
 };
 
 struct unit_class unit_classes[] = {
@@ -685,3 +685,11 @@
 {
   return &unit_classes[get_unit_type(type)->class];
 }
+
+/***************************************************************
+ Returns unit class structure
+***************************************************************/
+struct unit_class *unit_class_from_id(Unit_Class_id class)
+{
+  return &unit_classes[class];
+}
diff -Nurd -X.diff_ignore freeciv/common/unittype.h freeciv/common/unittype.h
--- freeciv/common/unittype.h   2005-06-30 00:32:36.421875000 +0300
+++ freeciv/common/unittype.h   2005-06-30 00:33:19.875000000 +0300
@@ -230,6 +230,8 @@
 int unit_pop_value(Unit_type_id id);
 
 struct unit_class *get_unit_class(Unit_type_id type);
+struct unit_class *unit_class_from_id(Unit_Class_id class);
+
 const char *unit_name(Unit_type_id id);
 const char *unit_name_orig(Unit_type_id id);
 const char *unit_class_name(Unit_Class_id id);
diff -Nurd -X.diff_ignore freeciv/server/gotohand.c freeciv/server/gotohand.c
--- freeciv/server/gotohand.c   2005-06-29 02:13:46.390625000 +0300
+++ freeciv/server/gotohand.c   2005-06-30 00:33:20.000000000 +0300
@@ -306,7 +306,7 @@
          continue; /* No need for all the calculations */
 
         if (is_ocean(tile_get_terrain(tile1))) {
-          if (punit && ground_unit_transporter_capacity(tile1, pplayer) > 0)
+          if (punit && unit_class_transporter_capacity(tile1, pplayer, 
UCL_LAND) > 0)
            move_cost = SINGLE_MOVE;
           else
            continue;
@@ -650,7 +650,7 @@
                       RR loops, ie you can't create a cycle with the same 
move_cost */
 
        if (is_ocean(pdesttile->terrain)) {
-         if (ground_unit_transporter_capacity(tile1, unit_owner(punit)) <= 0)
+         if (unit_class_transporter_capacity(tile1, unit_owner(punit), 
UCL_LAND) <= 0)
            continue;
          else
            move_cost = 3;
@@ -1247,7 +1247,7 @@
     if (is_ocean(tile_get_terrain(ptile))) {
       /* Going to a sea tile, the target should be next to our continent 
        * and with a boat */
-      if (ground_unit_transporter_capacity(ptile, pplayer) > 0) {
+      if (unit_class_transporter_capacity(ptile, pplayer, UCL_LAND) > 0) {
         adjc_iterate(ptile, tmp_tile) {
           if (tile_get_continent(tmp_tile) == tile_get_continent(punit->tile))
             /* The target is adjacent to our continent! */
diff -Nurd -X.diff_ignore freeciv/server/settlers.c freeciv/server/settlers.c
--- freeciv/server/settlers.c   2005-06-29 02:13:46.406250000 +0300
+++ freeciv/server/settlers.c   2005-06-30 00:33:20.093750000 +0300
@@ -666,8 +666,6 @@
   The "virtual boats" code is not used. It is probably too unreliable, 
   since the AI switches its production back and forth continously.
 
-  FIXME: if there is a (free) boat in a city filled with units, 
-  ground_unit_transporter_capacity will return negative.
   TODO: Kill me.  There is a reliable version of this, find_ferry.
 **************************************************************************/
 Unit_type_id find_boat(struct player *pplayer, struct tile **ptile, int cap)
@@ -675,11 +673,11 @@
   int best = 22; /* arbitrary maximum distance, I will admit! */
   Unit_type_id id = 0;
   unit_list_iterate(pplayer->units, aunit)
-    if (is_ground_units_transport(aunit)) {
+    if (can_unit_type_transport(aunit->type, UCL_LAND)) {
       if (WARMAP_COST(aunit->tile) < best &&
          (WARMAP_COST(aunit->tile) == 0 ||
-          ground_unit_transporter_capacity(aunit->tile,
-                                           pplayer) >= cap)) {
+          unit_class_transporter_capacity(aunit->tile,
+                                           pplayer, UCL_LAND) >= cap)) {
         id = aunit->id;
         best = WARMAP_COST(aunit->tile);
        *ptile = aunit->tile;
diff -Nurd -X.diff_ignore freeciv/server/unittools.c freeciv/server/unittools.c
--- freeciv/server/unittools.c  2005-06-30 00:32:36.515625000 +0300
+++ freeciv/server/unittools.c  2005-06-30 00:52:36.515625000 +0300
@@ -926,8 +926,8 @@
        /* look for nearby transport */
        adjc_iterate(ptile, ptile2) {
          if (is_ocean(ptile2->terrain)
-             && ground_unit_transporter_capacity(ptile2,
-                                                 unit_owner(punit2)) > 0) {
+             && unit_class_transporter_capacity(ptile2, unit_owner(punit2),
+                                                 UCL_LAND) > 0) {
            if (get_transporter_capacity(punit2) > 0)
              sentry_transported_idle_units(punit2);
            freelog(LOG_VERBOSE,
@@ -1641,6 +1641,19 @@
   struct tile *ptile = punit->tile;
   struct player *pplayer = unit_owner(punit);
   struct unit_type *ptype = unit_type(punit);
+  int capacity = 0;
+
+  if (wipe_cargo) {
+    if (can_unit_type_transport(punit->type, UCL_LAND)) {
+      /* Old free capacity */
+      capacity = unit_class_transporter_capacity(ptile, pplayer, UCL_LAND);
+      /* Minus capacity of removed transporter */
+      capacity -= get_transporter_capacity(punit);
+    } else {
+      /* No need to wipe the cargo unless it's a ground transporter. */
+      wipe_cargo = FALSE;
+    }
+  }
 
   /* First pull all units off of the transporter. */
   if (get_transporter_capacity(punit) > 0) {
@@ -1660,9 +1673,6 @@
     } unit_list_iterate_end;
   }
 
-  /* No need to wipe the cargo unless it's a ground transporter. */
-  wipe_cargo &= is_ground_units_transport(punit);
-
   /* Now remove the unit. */
   server_remove_unit(punit);
 
@@ -1672,7 +1682,6 @@
       && is_ocean(tile_get_terrain(ptile))
       && !tile_get_city(ptile)) {
     struct city *pcity = NULL;
-    int capacity = ground_unit_transporter_capacity(ptile, pplayer);
 
     /* Get rid of excess standard units. */
     if (capacity < 0) {
@@ -1720,7 +1729,7 @@
 
     /* Reassign existing units.  This is an O(n^2) operation as written. */
     unit_list_iterate(ptile->units, ptrans) {
-      if (is_ground_units_transport(ptrans)) {
+      if (can_unit_type_transport(ptrans->type, UCL_LAND)) {
        int occupancy = get_transporter_occupancy(ptrans);
 
        unit_list_iterate(ptile->units, pcargo) {

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#13384) [Patch] unit_class_transporter_capacity(), Marko Lindqvist <=