Author: cazfi
Date: Thu Aug  4 14:53:47 2016
New Revision: 33455

URL: http://svn.gna.org/viewcvs/freeciv?rev=33455&view=rev
Log:
Fixed AI trade route evaluation to use correct speculated homecity instead of 
unit's
current homecity.

See bug #24663

Modified:
    trunk/common/actions.c
    trunk/common/actions.h
    trunk/common/aicore/caravan.c

Modified: trunk/common/actions.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/common/actions.c?rev=33455&r1=33454&r2=33455&view=diff
==============================================================================
--- trunk/common/actions.c      (original)
+++ trunk/common/actions.c      Thu Aug  4 14:53:47 2016
@@ -1,4 +1,4 @@
-/**********************************************************************
+/***********************************************************************
  Freeciv - Copyright (C) 1996-2013 - Freeciv Development Team
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -1126,7 +1126,8 @@
                        const struct unit_type *actor_unittype,
                        const struct output_type *actor_output,
                        const struct specialist *actor_specialist,
-                       const bool omniscient)
+                       const bool omniscient,
+                       const struct city *homecity)
 {
   if (!action_actor_utype_hard_reqs_ok(wanted_action, actor_unittype)) {
     /* Info leak: The actor player knows the type of his unit. */
@@ -1142,7 +1143,7 @@
      * city. The Freeciv code assumes this applies to Enter Marketplace
      * too. */
     /* Info leak: The actor player knowns his unit's home city. */
-    if (!game_city_by_number(actor_unit->homecity)) {
+    if (homecity == NULL) {
       return TRI_NO;
     }
 
@@ -1249,7 +1250,8 @@
                    const struct unit_type *target_unittype,
                    const struct output_type *target_output,
                    const struct specialist *target_specialist,
-                   const bool omniscient)
+                   const bool omniscient,
+                   const struct city *homecity)
 {
   bool can_see_tgt_unit;
   bool can_see_tgt_tile;
@@ -1312,7 +1314,7 @@
                                actor_player, actor_city, actor_building,
                                actor_tile, actor_unit, actor_unittype,
                                actor_output, actor_specialist,
-                               omniscient);
+                               omniscient, homecity);
 
   if (out == TRI_NO) {
     /* Illegal because of a hard actor requirement. */
@@ -1383,25 +1385,21 @@
   case ACTION_TRADE_ROUTE:
   case ACTION_MARKETPLACE:
     {
-      const struct city *actor_homecity;
-
-      actor_homecity = game_city_by_number(actor_unit->homecity);
-
       /* Checked in action_hard_reqs_actor() */
-      fc_assert_ret_val(actor_homecity != NULL, TRI_NO);
+      fc_assert_ret_val(homecity != NULL, TRI_NO);
 
       /* Can't establish a trade route or enter the market place if the
        * cities can't trade at all. */
       /* TODO: Should this restriction (and the above restriction that the
        * actor unit must have a home city) be kept for Enter Marketplace? */
-      if (!can_cities_trade(actor_homecity, target_city)) {
+      if (!can_cities_trade(homecity, target_city)) {
         return TRI_NO;
       }
 
       /* There are more restrictions on establishing a trade route than on
        * entering the market place. */
-      if (wanted_action == ACTION_TRADE_ROUTE &&
-          !can_establish_trade_route(actor_homecity, target_city)) {
+      if (wanted_action == ACTION_TRADE_ROUTE
+          && !can_establish_trade_route(homecity, target_city)) {
         return TRI_NO;
       }
     }
@@ -1571,7 +1569,7 @@
   case ACTION_HOME_CITY:
     /* Reason: can't change to what is. */
     /* Info leak: The player knows his unit's current home city. */
-    if (actor_unit->homecity == target_city->id) {
+    if (homecity->id == target_city->id) {
       /* This is already the unit's home city. */
       return TRI_NO;
     }
@@ -1718,7 +1716,8 @@
                               const struct unit *target_unit,
                              const struct unit_type *target_unittype,
                              const struct output_type *target_output,
-                             const struct specialist *target_specialist)
+                             const struct specialist *target_specialist,
+                              const struct city *homecity)
 {
   enum fc_tristate possible;
 
@@ -1731,7 +1730,7 @@
                                 target_building, target_tile,
                                 target_unit, target_unittype,
                                 target_output, target_specialist,
-                                TRUE);
+                                TRUE, homecity);
 
   if (possible != TRI_YES) {
     /* This context is omniscient. Should be yes or no. */
@@ -1770,6 +1769,22 @@
                                     const struct unit *actor_unit,
                                     const struct city *target_city)
 {
+  return is_action_enabled_unit_on_city_full(wanted_action, actor_unit,
+                                             target_city,
+                                             
game_city_by_number(actor_unit->homecity));
+}
+
+/**************************************************************************
+  Returns TRUE if actor_unit can do wanted_action to target_city as far as
+  action enablers are concerned.
+
+  See note in is_action_enabled for why the action may still be disabled.
+**************************************************************************/
+bool is_action_enabled_unit_on_city_full(const enum gen_action wanted_action,
+                                         const struct unit *actor_unit,
+                                         const struct city *target_city,
+                                         const struct city *homecity)
+{
   struct tile *actor_tile = unit_tile(actor_unit);
   struct impr_type *target_building;
   struct unit_type *target_utype;
@@ -1808,7 +1823,7 @@
                            NULL, NULL,
                            city_owner(target_city), target_city,
                            target_building, city_tile(target_city),
-                           NULL, target_utype, NULL, NULL);
+                           NULL, target_utype, NULL, NULL, homecity);
 }
 
 /**************************************************************************
@@ -1856,7 +1871,8 @@
                            tile_city(unit_tile(target_unit)), NULL,
                            unit_tile(target_unit),
                            target_unit, unit_type_get(target_unit),
-                           NULL, NULL);
+                           NULL, NULL,
+                           game_city_by_number(actor_unit->homecity));
 }
 
 /**************************************************************************
@@ -1870,6 +1886,7 @@
                                      const struct tile *target_tile)
 {
   struct tile *actor_tile = unit_tile(actor_unit);
+  struct city *homecity;
 
   if (actor_unit == NULL || target_tile == NULL
       || unit_list_size(target_tile->units) == 0) {
@@ -1895,6 +1912,8 @@
     /* No point in continuing. */
     return FALSE;
   }
+
+  homecity = game_city_by_number(actor_unit->homecity);
 
   unit_list_iterate(target_tile->units, target_unit) {
     if (!is_action_enabled(wanted_action,
@@ -1906,7 +1925,7 @@
                            tile_city(unit_tile(target_unit)), NULL,
                            unit_tile(target_unit),
                            target_unit, unit_type_get(target_unit),
-                           NULL, NULL)) {
+                           NULL, NULL, homecity)) {
       /* One unit makes it impossible for all units. */
       return FALSE;
     }
@@ -1958,7 +1977,8 @@
                            actor_unit, unit_type_get(actor_unit),
                            NULL, NULL,
                            tile_owner(target_tile), NULL, NULL,
-                           target_tile, NULL, NULL, NULL, NULL);
+                           target_tile, NULL, NULL, NULL, NULL,
+                           game_city_by_number(actor_unit->homecity));
 }
 
 /**************************************************************************
@@ -2002,7 +2022,8 @@
                            NULL, actor_tile,
                            actor_unit, unit_type_get(actor_unit),
                            NULL, NULL,
-                           NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+                           NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                           game_city_by_number(actor_unit->homecity));
 }
 
 /**************************************************************************
@@ -2271,9 +2292,9 @@
 {
   int known;
   struct act_prob chance;
-
   const struct unit_type *actor_unittype;
   const struct unit_type *target_unittype;
+  const struct city *homecity;
 
   if (actor_unittype_p == NULL && actor_unit != NULL) {
     actor_unittype = unit_type_get(actor_unit);
@@ -2285,6 +2306,12 @@
     target_unittype = unit_type_get(target_unit);
   } else {
     target_unittype = target_unittype_p;
+  }
+
+  if (actor_unit != NULL) {
+    homecity = game_city_by_number(actor_unit->homecity);
+  } else {
+    homecity = NULL;
   }
 
   known = is_action_possible(wanted_action,
@@ -2296,7 +2323,7 @@
                              target_building, target_tile,
                              target_unit, target_unittype,
                              target_output, target_specialist,
-                             FALSE);
+                             FALSE, homecity);
 
   if (known == TRI_NO) {
     /* The action enablers are irrelevant since the action it self is
@@ -2918,7 +2945,7 @@
   is provided.
 **************************************************************************/
 bool action_maybe_possible_actor_unit(const int action_id,
-                                      const struct unit* actor_unit)
+                                      const struct unit *actor_unit)
 {
   const struct player *actor_player = unit_owner(actor_unit);
   const struct tile *actor_tile = unit_tile(actor_unit);
@@ -2937,7 +2964,8 @@
   result = action_hard_reqs_actor(action_id,
                                   actor_player, actor_city, NULL,
                                   actor_tile, actor_unit, actor_unittype,
-                                  NULL, NULL, FALSE);
+                                  NULL, NULL, FALSE,
+                                  game_city_by_number(actor_unit->homecity));
 
   if (result == TRI_NO) {
     /* The hard requirements aren't fulfilled. */

Modified: trunk/common/actions.h
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/common/actions.h?rev=33455&r1=33454&r2=33455&view=diff
==============================================================================
--- trunk/common/actions.h      (original)
+++ trunk/common/actions.h      Thu Aug  4 14:53:47 2016
@@ -1,4 +1,4 @@
-/**********************************************************************
+/***********************************************************************
  Freeciv - Copyright (C) 1996-2013 - Freeciv Development Team
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -339,6 +339,11 @@
                                     const struct unit *actor_unit,
                                     const struct city *target_city);
 
+bool is_action_enabled_unit_on_city_full(const enum gen_action wanted_action,
+                                         const struct unit *actor_unit,
+                                         const struct city *target_city,
+                                         const struct city *homecity);
+
 bool is_action_enabled_unit_on_unit(const enum gen_action wanted_action,
                                     const struct unit *actor_unit,
                                     const struct unit *target_unit);

Modified: trunk/common/aicore/caravan.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/common/aicore/caravan.c?rev=33455&r1=33454&r2=33455&view=diff
==============================================================================
--- trunk/common/aicore/caravan.c       (original)
+++ trunk/common/aicore/caravan.c       Thu Aug  4 14:53:47 2016
@@ -485,12 +485,15 @@
      * theoretically possible case. (More than one city is rare.) The
      * computations are therefore worth it. */
 
-    if (!(is_action_enabled_unit_on_city(ACTION_HELP_WONDER,
-                                         caravan, dest)
-          || is_action_enabled_unit_on_city(ACTION_TRADE_ROUTE,
-                                            caravan, dest)
-          || is_action_enabled_unit_on_city(ACTION_MARKETPLACE,
-                                            caravan, dest))) {
+    if (!(is_action_enabled_unit_on_city_full(ACTION_HELP_WONDER,
+                                              caravan, dest,
+                                              src)
+          || is_action_enabled_unit_on_city_full(ACTION_TRADE_ROUTE,
+                                                 caravan, dest,
+                                                 src)
+          || is_action_enabled_unit_on_city_full(ACTION_MARKETPLACE,
+                                                 caravan, dest,
+                                                 src))) {
       /* No caravan action is possible against this target. */
       caravan_result_init_zero(result);
       return FALSE;


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

Reply via email to