Author: sveinung
Date: Tue Mar 28 22:01:38 2017
New Revision: 35169

URL: http://svn.gna.org/viewcvs/freeciv?rev=35169&view=rev
Log:
unit_get_actions: stop city existence leakage.

Stop leaking if a previously observed city still exists when responding to
a request for action probabilities in handle_unit_get_actions().

See gna bug #25282

Modified:
    branches/S3_0/common/actions.c
    branches/S3_0/server/unithand.c

Modified: branches/S3_0/common/actions.c
URL: 
http://svn.gna.org/viewcvs/freeciv/branches/S3_0/common/actions.c?rev=35169&r1=35168&r2=35169&view=diff
==============================================================================
--- branches/S3_0/common/actions.c      (original)
+++ branches/S3_0/common/actions.c      Tue Mar 28 22:01:38 2017
@@ -3072,6 +3072,12 @@
     return ACTPROB_IMPOSSIBLE;
   }
 
+  if (!player_can_see_city_externals(unit_owner(actor_unit), target_city)) {
+    /* The invisible city at this tile may, as far as the player knows, not
+     * exist anymore. */
+    return act_prob_unseen_target(action_id, actor_unit);
+  }
+
   target_building = tgt_city_local_building(target_city);
   target_utype = tgt_city_local_utype(target_city);
 

Modified: branches/S3_0/server/unithand.c
URL: 
http://svn.gna.org/viewcvs/freeciv/branches/S3_0/server/unithand.c?rev=35169&r1=35168&r2=35169&view=diff
==============================================================================
--- branches/S3_0/server/unithand.c     (original)
+++ branches/S3_0/server/unithand.c     Tue Mar 28 22:01:38 2017
@@ -1443,6 +1443,7 @@
   struct city *target_city;
 
   int actor_target_distance;
+  const struct player_tile *plrtile;
 
   /* No potentially legal action is known yet. If none is found the player
    * should get an explanation. */
@@ -1498,6 +1499,11 @@
     return;
   }
 
+  /* The player may have outdated information about the target tile.
+   * Limiting the player knowledge look up to the target tile is OK since
+   * all targets must be located at it. */
+  plrtile = map_get_player_tile(target_tile, actor_player);
+
   /* Distance between actor and target tile. */
   actor_target_distance = real_map_distance(unit_tile(actor_unit),
                                             target_tile);
@@ -1513,10 +1519,27 @@
 
     switch (action_id_get_target_kind(act)) {
     case ATK_CITY:
-      if (target_city) {
-        /* Calculate the probabilities. */
-        probabilities[act] = action_prob_vs_city(actor_unit, act,
-                                                 target_city);
+      if (plrtile && plrtile->site) {
+        /* Only a known city may be targeted. */
+        if (target_city) {
+          /* Calculate the probabilities. */
+          probabilities[act] = action_prob_vs_city(actor_unit, act,
+                                                   target_city);
+        } else if (!tile_is_seen(target_tile, actor_player)
+                   && action_maybe_possible_actor_unit(act, actor_unit)
+                   && action_id_distance_accepted(act,
+                                                  actor_target_distance)) {
+          /* The target city is non existing. The player isn't aware of this
+           * fact because he can't see the tile it was located on. The
+           * actor unit it self doesn't contradict the requirements to
+           * perform the action. The (no longer existing) target city was
+           * known to be close enough. */
+          probabilities[act] = ACTPROB_NOT_KNOWN;
+        } else {
+          /* The actor unit is known to be unable to act or the target city
+           * is known to be too far away. */
+          probabilities[act] = ACTPROB_IMPOSSIBLE;
+        }
       } else {
         /* No target to act against. */
         probabilities[act] = ACTPROB_IMPOSSIBLE;
@@ -1581,8 +1604,13 @@
       case ATK_CITY:
         /* The city should be sent as a target since it is possible to act
          * against it. */
-        fc_assert(target_city != NULL);
-        target_city_id = target_city->id;
+
+        /* All city targeted actions requires that the player is aware of
+         * the target city. It is therefore in the player's map. */
+        fc_assert_action(plrtile, continue);
+        fc_assert_action(plrtile->site, continue);
+
+        target_city_id = plrtile->site->identity;
         break;
       case ATK_UNIT:
         /* The unit should be sent as a target since it is possible to act


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

Reply via email to