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