Complete.Org: Mailing Lists: Archives: freeciv-dev: September 2003:
[Freeciv-Dev] (PR#6179) more rigorous handling of transported_by
Home

[Freeciv-Dev] (PR#6179) more rigorous handling of transported_by

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] (PR#6179) more rigorous handling of transported_by
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Tue, 16 Sep 2003 20:53:20 -0700
Reply-to: rt@xxxxxxxxxxxxxx

This patch primarily adds a couple of sanity checks on the 
transported_by field.

Secondarily it makes two code changes that allow these sanity checks to 
pass:

1.  Barbarians created on ships must be transported by the ship.

2.  When moving a ground unit onto ocean, find a transporter for it.

This should ensure that the transported_by field has a valid value, 
which will allow PR#5789 to go forward.  It should also allow the 
removal of some or most (not all - see Per's explanation in PR#6174) 
calls to assign_unit_to_transport.

The only issue is that the sanity check may have some rules issues.  It 
declares that a ground unit in the ocean must be transported by a 
non-ground unit: it cannot be transported by another ground unit which 
is then transported by a non-ground unit.  This is the case under the 
default ruleset (which has no transporters that are ground units) but 
possibly not under alternate rulesets.  What _should_ be the behavior in 
this case?  Should we allow recursive transporting?

My suggestion is that a transporter with a capacity of C should use C+1 
"spots" if you put it in another transporter.  This makes some sense to 
me from a realism perspective, and prevents recursive transporting.  It 
also makes the problem simpler from a technical perspective.

jason

? rc
Index: server/barbarian.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/barbarian.c,v
retrieving revision 1.67
diff -u -r1.67 barbarian.c
--- server/barbarian.c  2003/08/04 15:42:47     1.67
+++ server/barbarian.c  2003/09/17 03:44:57
@@ -383,17 +383,21 @@
     (void) create_unit(barbarians, xu, yu,
                       get_role_unit(L_BARBARIAN_LEADER, 0), FALSE, 0, -1);
   } else {                   /* sea raiders - their units will be veteran */
+    struct unit *punit, ptrans;
+
     barbarians = create_barbarian_player(FALSE);
     boat = find_a_unit_type(L_BARBARIAN_BOAT,-1);
-    (void) create_unit(barbarians, xu, yu, boat, TRUE, 0, -1);
+    ptrans = create_unit(barbarians, xu, yu, boat, TRUE, 0, -1);
     cap = get_transporter_capacity(unit_list_get(&map_get_tile(xu, yu)->units, 
0));
     for (i = 0; i < cap-1; i++) {
       unit = find_a_unit_type(L_BARBARIAN_SEA,L_BARBARIAN_SEA_TECH);
-      (void) create_unit(barbarians, xu, yu, unit, TRUE, 0, -1);
+      punit = create_unit(barbarians, xu, yu, unit, TRUE, 0, -1);
+      punit->transported_by = ptrans->id;
       freelog(LOG_DEBUG, "Created barbarian unit %s", unit_types[unit].name);
     }
-    (void) create_unit(barbarians, xu, yu,
-                      get_role_unit(L_BARBARIAN_LEADER, 0), FALSE, 0, -1);
+    punit = create_unit(barbarians, xu, yu,
+                       get_role_unit(L_BARBARIAN_LEADER, 0), FALSE, 0, -1);
+    punit->transported_by = ptrans->id;
   }
 
   unit_list_iterate(map_get_tile(x, y)->units, punit2) {
Index: server/sanitycheck.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/sanitycheck.c,v
retrieving revision 1.31
diff -u -r1.31 sanitycheck.c
--- server/sanitycheck.c        2003/08/01 15:58:08     1.31
+++ server/sanitycheck.c        2003/09/17 03:44:57
@@ -22,11 +22,12 @@
 #include "log.h"
 #include "map.h"
 #include "player.h"
+#include "terrain.h"
 #include "unit.h"
 
 #include "maphand.h"
-
 #include "sanitycheck.h"
+#include "unittools.h"
 
 #ifndef NDEBUG
 
@@ -261,6 +262,17 @@
 
       assert(punit->moves_left >= 0);
       assert(punit->hp > 0);
+
+      /* Check for ground units in the ocean. */
+      if (is_ocean(map_get_terrain(punit->x, punit->y))
+         && is_ground_unit(punit)) {
+       assert(punit->transported_by != -1);
+       assert(!is_ground_unit(find_unit_by_id(punit->transported_by)));
+      }
+
+      /* Check for over-full transports. */
+      assert(get_transporter_occupancy(punit)
+            <= get_transporter_capacity(punit));
     } unit_list_iterate_end;
   } players_iterate_end;
 }
Index: server/unittools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unittools.c,v
retrieving revision 1.250
diff -u -r1.250 unittools.c
--- server/unittools.c  2003/09/17 02:57:21     1.250
+++ server/unittools.c  2003/09/17 03:44:57
@@ -1404,6 +1404,22 @@
   }
 }
 
+/****************************************************************************
+  Expensive function to check how many units are in the transport.
+****************************************************************************/
+int get_transporter_occupancy(struct unit *ptrans)
+{
+  int occupied = 0;
+
+  unit_list_iterate(map_get_tile(ptrans->x, ptrans->y)->units, pcargo) {
+    if (pcargo->transported_by == ptrans->id) {
+      occupied++;
+    }
+  } unit_list_iterate_end;
+
+  return occupied;
+}
+
 /**************************************************************************
 ...
 **************************************************************************/
@@ -2894,6 +2910,20 @@
   punit->moves_left = MAX(0, punit->moves_left - move_cost);
   unit_list_insert(&pdesttile->units, punit);
   check_unit_activity(punit);
+
+  /* If the unit needs a transporter, put it on one. */
+  if (is_ground_unit(punit)
+      && is_ocean(pdesttile->terrain)) {
+    unit_list_iterate(map_get_tile(punit->x, punit->y)->units, ptrans) {
+      if (is_ground_units_transport(ptrans)
+         && (get_transporter_occupancy(ptrans)
+             < get_transporter_capacity(ptrans))) {
+       punit->transported_by = ptrans->id;
+       break;
+      }
+    } unit_list_iterate_end;
+    assert(punit->transported_by != -1);
+  }
 
   /* set activity to sentry if boarding a ship unless the unit is just 
    * passing through the ship on its way somewhere else.  If the unit is
Index: server/unittools.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unittools.h,v
retrieving revision 1.54
diff -u -r1.54 unittools.h
--- server/unittools.h  2003/09/09 20:10:28     1.54
+++ server/unittools.h  2003/09/17 03:44:57
@@ -29,6 +29,7 @@
 /* move check related */
 bool is_airunit_refuel_point(int x, int y, struct player *pplayer,
                             Unit_Type_id type, bool unit_is_on_tile);
+int get_transporter_occupancy(struct unit *ptrans);
 
 /* turn update related */
 void player_restore_units(struct player *pplayer);

[Prev in Thread] Current Thread [Next in Thread]