Author: cazfi
Date: Mon Mar 17 22:31:34 2014
New Revision: 24693

URL: http://svn.gna.org/viewcvs/freeciv?rev=24693&view=rev
Log:
When doing connect activity with some road type, recursively build also
dependency roads.

Requested by Jacob Nevins <jtn>

See bug #21436

Modified:
    trunk/client/control.c
    trunk/client/control.h
    trunk/client/goto.c
    trunk/common/terrain.c
    trunk/common/terrain.h

Modified: trunk/client/control.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/client/control.c?rev=24693&r1=24692&r2=24693&view=diff
==============================================================================
--- trunk/client/control.c      (original)
+++ trunk/client/control.c      Mon Mar 17 22:31:34 2014
@@ -1145,6 +1145,56 @@
 }
 
 /**************************************************************************
+  Fill orders to build recursive roads. This modifies ptile, so virtual
+  copy of the real tile should be passed.
+**************************************************************************/
+int check_recursive_road_connect(struct tile *ptile, const struct extra_type 
*pextra,
+                                 const struct unit *punit, const struct player 
*pplayer, int rec)
+{
+  int activity_mc = 0;
+  struct terrain *pterrain = tile_terrain(ptile);
+
+  if (rec > MAX_EXTRA_TYPES) {
+    return -1;
+  }
+
+  if (!is_extra_caused_by(pextra, EC_ROAD)) {
+    return -1;
+  }
+
+  extra_deps_iterate(&(pextra->reqs), pdep) {
+    if (!tile_has_extra(ptile, pdep)) {
+      int single_mc;
+
+      single_mc = check_recursive_road_connect(ptile, pdep, punit, pplayer, 
rec + 1);
+
+      if (single_mc < 0) {
+        return -1;
+      }
+
+      activity_mc += single_mc;
+    }
+  } extra_deps_iterate_end;
+
+  /* Can build road after that? */
+  if (punit != NULL) {
+    if (!can_build_road(extra_road_get(pextra), punit, ptile)) {
+      return -1;
+    }
+  } else if (pplayer != NULL) {
+    if (!player_can_build_road(extra_road_get(pextra), pplayer, ptile)) {
+      return -1;
+    }
+  }
+
+  tile_add_extra(ptile, pextra);
+
+  activity_mc += terrain_road_time(pterrain, pextra);
+
+  return activity_mc;
+}
+
+/**************************************************************************
   Return whether the unit can connect with given activity (or with
   any activity if activity arg is set to ACTIVITY_IDLE)
 
@@ -1167,22 +1217,29 @@
    *     (b) it can be done by the unit at this tile. */
   switch (activity) {
   case ACTIVITY_GEN_ROAD:
-    fc_assert(is_extra_caused_by(tgt, EC_ROAD));
-
-    proad = extra_road_get(tgt);
-
-    if (tile_has_road(ptile, proad)) {
-      /* This tile has road, can unit build road to other tiles too? */
-      struct extra_type *pextra = road_extra_get(proad);
-
-      return are_reqs_active(NULL, NULL, NULL, NULL, NULL,
-                             unit_type(punit), NULL, NULL,
-                             &pextra->reqs, RPT_POSSIBLE);
-    }
-
-    /* To start connect, unit must be able to build road to this
-     * particular tile. */
-    return can_build_road(proad, punit, ptile);
+    {
+      struct tile *vtile;
+      int build_time;
+
+      fc_assert(is_extra_caused_by(tgt, EC_ROAD));
+
+      proad = extra_road_get(tgt);
+
+      if (tile_has_road(ptile, proad)) {
+        /* This tile has road, can unit build road to other tiles too? */
+        return are_reqs_active(NULL, NULL, NULL, NULL, NULL,
+                               unit_type(punit), NULL, NULL,
+                               &tgt->reqs, RPT_POSSIBLE);
+      }
+
+      /* To start connect, unit must be able to build road to this
+       * particular tile. */
+      vtile = tile_virtual_new(ptile);
+      build_time = check_recursive_road_connect(vtile, tgt, punit, NULL, 0);
+      tile_virtual_destroy(vtile);
+
+      return build_time >= 0;
+    }
 
   case ACTIVITY_IRRIGATE:
     /* Special case for irrigation: only irrigate to make S_IRRIGATION,
@@ -1209,8 +1266,8 @@
 }
 
 /**************************************************************************
-prompt player for entering destination point for unit connect
-(e.g. connecting with roads)
+  Prompt player for entering destination point for unit connect
+  (e.g. connecting with roads)
 **************************************************************************/
 void request_unit_connect(enum unit_activity activity,
                           struct extra_type *tgt)

Modified: trunk/client/control.h
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/client/control.h?rev=24693&r1=24692&r2=24693&view=diff
==============================================================================
--- trunk/client/control.h      (original)
+++ trunk/client/control.h      Mon Mar 17 22:31:34 2014
@@ -50,6 +50,9 @@
 bool can_unit_do_connect(struct unit *punit,
                          enum unit_activity activity,
                          struct extra_type *tgt);
+
+int check_recursive_road_connect(struct tile *ptile, const struct extra_type 
*pextra,
+                                 const struct unit *punit, const struct player 
*pplayer, int rec);
 
 void do_move_unit(struct unit *punit, struct unit *target_unit);
 void do_unit_goto(struct tile *ptile);

Modified: trunk/client/goto.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/client/goto.c?rev=24693&r1=24692&r2=24693&view=diff
==============================================================================
--- trunk/client/goto.c (original)
+++ trunk/client/goto.c Mon Mar 17 22:31:34 2014
@@ -493,15 +493,20 @@
     break;
   case ACTIVITY_GEN_ROAD:
     fc_assert(is_extra_caused_by(connect_tgt, EC_ROAD));
-    {
-      struct road_type *proad = extra_road_get(connect_tgt);
-
-      if (!tile_has_road(ptile, proad)) {
-        if (!player_can_build_road(proad, pplayer, ptile)) {
-          return -1;
-        }
-        activity_mc += terrain_road_time(pterrain, connect_tgt);
+
+    if (!tile_has_extra(ptile, connect_tgt)) {
+      struct tile *vtile;
+      int single_mc;
+
+      vtile = tile_virtual_new(ptile);
+      single_mc = check_recursive_road_connect(vtile, connect_tgt, NULL, 
pplayer, 0);
+      tile_virtual_destroy(vtile);
+
+      if (single_mc < 0) {
+        return -1;
       }
+
+      activity_mc += single_mc;
     }
     break;
   default:
@@ -1116,6 +1121,37 @@
 }
 
 /**************************************************************************
+  Fill orders to build recursive roads.
+**************************************************************************/
+static bool order_recursive_roads(struct tile *ptile, struct extra_type 
*pextra,
+                                 struct packet_unit_orders *p, int rec)
+{
+  if (rec > MAX_EXTRA_TYPES) {
+    return FALSE;
+  }
+
+  if (!is_extra_caused_by(pextra, EC_ROAD)) {
+    return FALSE;
+  }
+
+  extra_deps_iterate(&(pextra->reqs), pdep) {
+    if (!tile_has_extra(ptile, pdep)) {
+      if (!order_recursive_roads(ptile, pdep, p, rec + 1)) {
+        return FALSE;
+      }
+    }
+  } extra_deps_iterate_end;
+
+  p->orders[p->length] = ORDER_ACTIVITY;
+  p->dir[p->length] = -1;
+  p->activity[p->length] = ACTIVITY_GEN_ROAD;
+  p->target[p->length] = extra_index(pextra);
+  p->length++;
+
+  return TRUE;
+}
+
+/**************************************************************************
   Send the current connect route (i.e., the one generated via HOVER_STATE)
   to the server.
 **************************************************************************/
@@ -1162,13 +1198,7 @@
        }
        break;
       case ACTIVITY_GEN_ROAD:
-        if (!tile_has_extra(old_tile, tgt)) {
-          p.orders[p.length] = ORDER_ACTIVITY;
-          p.dir[p.length] = -1;
-          p.activity[p.length] = ACTIVITY_GEN_ROAD;
-          p.target[p.length] = extra_index(tgt);
-          p.length++;
-        }
+        order_recursive_roads(old_tile, tgt, &p, 0);
         break;
       default:
         log_error("Invalid connect activity: %d.", activity);

Modified: trunk/common/terrain.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/common/terrain.c?rev=24693&r1=24692&r2=24693&view=diff
==============================================================================
--- trunk/common/terrain.c      (original)
+++ trunk/common/terrain.c      Mon Mar 17 22:31:34 2014
@@ -781,7 +781,7 @@
    Time to complete the base building activity on the given terrain.
 ****************************************************************************/
 int terrain_base_time(const struct terrain *pterrain,
-                      struct extra_type *tgt)
+                      const struct extra_type *tgt)
 {
   struct base_type *pbase = extra_base_get(tgt);
 
@@ -798,7 +798,7 @@
   Time to complete the road building activity on the given terrain.
 ****************************************************************************/
 int terrain_road_time(const struct terrain *pterrain,
-                      struct extra_type *tgt)
+                      const struct extra_type *tgt)
 {
   struct road_type *proad = extra_road_get(tgt);
 

Modified: trunk/common/terrain.h
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/common/terrain.h?rev=24693&r1=24692&r2=24693&view=diff
==============================================================================
--- trunk/common/terrain.h      (original)
+++ trunk/common/terrain.h      Mon Mar 17 22:31:34 2014
@@ -310,10 +310,10 @@
 struct extra_type *get_preferred_pillage(bv_extras extras);
 
 int terrain_base_time(const struct terrain *pterrain,
-                      struct extra_type *tgt);
+                      const struct extra_type *tgt);
 
 int terrain_road_time(const struct terrain *pterrain,
-                      struct extra_type *tgt);
+                      const struct extra_type *tgt);
 
 /* Functions to operate on a terrain class. */
 const char *terrain_class_name_translation(enum terrain_class tclass);


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

Reply via email to