Author: sveinung
Date: Wed Sep 30 17:52:11 2015
New Revision: 29998

URL: http://svn.gna.org/viewcvs/freeciv?rev=29998&view=rev
Log:
Don't do Help Wonder via Disband Unit

Performing the Help Wonder action in handle_unit_disband() makes the
function more complex than it has to be. It is easy to forget to check if a
change done to do_unit_help_wonder() also should be done in
handle_unit_disband()'s Help Wonder. Remove it.

No hard coded rule has (intentionally) been changed. The Help Wonder action
now blocks Disband Unit. When the game disbands a unit because of upkeep it
should behave like it used to.

Don't upgrade old unit orders. An order to disband a unit in a city was
probably not intended as Help Wonder. ORDER_BUILD_WONDER and ORDER_DISBAND
were added in the same commit.

The AI won't start looking for a better alternative to its current behavior
when it must disband a unit.

See patch #6383

Modified:
    trunk/ai/default/aicity.c
    trunk/common/actions.c
    trunk/common/actions.h
    trunk/fc_version
    trunk/server/cityturn.c
    trunk/server/unithand.c
    trunk/server/unittools.c
    trunk/server/unittools.h

Modified: trunk/ai/default/aicity.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/ai/default/aicity.c?rev=29998&r1=29997&r2=29998&view=diff
==============================================================================
--- trunk/ai/default/aicity.c   (original)
+++ trunk/ai/default/aicity.c   Wed Sep 30 17:52:11 2015
@@ -37,6 +37,7 @@
 #include "plrhand.h"
 #include "srv_log.h"
 #include "unithand.h"
+#include "unittools.h"
 
 /* server/advisors */
 #include "advdata.h"
@@ -459,7 +460,7 @@
           && def_ai_city_data(pcity, ait)->urgency == 0) {
         CITY_LOG(LOG_BUY, pcity, "disbanding %s to increase production",
                  unit_rule_name(punit));
-       handle_unit_disband(pplayer,punit->id);
+        unit_do_disband_trad(pplayer, punit);
       }
     } unit_list_iterate_safe_end;
   } city_list_iterate_end;
@@ -926,7 +927,14 @@
             && (unit_being_aggressive(punit) || is_field_unit(punit)))
         && def_ai_unit_data(punit, ait)->passenger == 0) {
       UNIT_LOG(LOG_EMERGENCY, punit, "is causing unrest, disbanded");
-      handle_unit_disband(pplayer, punit->id);
+      /* TODO: if Help Wonder stops blocking Disband Unit there may be
+       * cases where Disband Unit should be selected. Example: Field unit
+       * in allied city that is building a wonder that makes the ally win
+       * without sharing the victory. */
+      /* TODO: Should the unit try to find legal targets at adjacent tiles?
+       * Should it consider other self eliminating actions than the
+       * components of the traditional disband? */
+      unit_do_disband_trad(pplayer, punit);
       city_refresh(pcity);
     }
   } unit_list_iterate_safe_end;

Modified: trunk/common/actions.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/common/actions.c?rev=29998&r1=29997&r2=29998&view=diff
==============================================================================
--- trunk/common/actions.c      (original)
+++ trunk/common/actions.c      Wed Sep 30 17:52:11 2015
@@ -666,6 +666,44 @@
 }
 
 /**************************************************************************
+  Returns TRUE iff an action that blocks regular disband is forced and
+  possible.
+
+  TODO: Make regular disband action enabler controlled and delete this
+  function.
+**************************************************************************/
+bool action_blocks_disband(const struct unit *actor_unit)
+{
+  struct city *target_city;
+
+  /* Hard code that Help Wonder blocks regular disband. This must be done
+   * because caravan_shields makes it possible to avoid the consequences of
+   * choosing to disband a unit rather than having it do Help Wonder.
+   *
+   * Explanation: Disband Unit adds 50% of the shields used to produce the
+   * unit to the production of the city where it is located. Help Wonder
+   * adds 100%. If a unit that can do Help Wonder is disbanded in a city
+   * and the production later is changed to something that can receive help
+   * from Help Wonder the remaining 50% of the shields are added. This can
+   * be done because the city remembers them in caravan_shields.
+   *
+   * If a unit that can do Help Wonder intentionally is disbanded rather
+   * than making it do Help Wonder its shields will still be remembered.
+   * The target city that got 50% of the shields can therefore get 100% of
+   * them by changing its production. This trick makes the ability to
+   * select disbanding when Help Wonder is legal pointless. */
+  target_city = tile_city(unit_tile(actor_unit));
+
+  if (target_city == NULL) {
+    /* No city to do Help Wonder to. */
+    return FALSE;
+  }
+
+  return is_action_enabled_unit_on_city(ACTION_HELP_WONDER,
+                                        actor_unit, target_city);
+}
+
+/**************************************************************************
   Returns TRUE if the specified unit type can perform the wanted action
   given that an action enabler later will enable it.
 

Modified: trunk/common/actions.h
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/common/actions.h?rev=29998&r1=29997&r2=29998&view=diff
==============================================================================
--- trunk/common/actions.h      (original)
+++ trunk/common/actions.h      Wed Sep 30 17:52:11 2015
@@ -239,7 +239,8 @@
 void action_enabler_add(struct action_enabler *enabler);
 
 bool action_blocks_attack(const struct unit *actor_unit,
-                                 const struct tile *target_tile);
+                          const struct tile *target_tile);
+bool action_blocks_disband(const struct unit *actor_unit);
 
 bool is_action_enabled_unit_on_city(const enum gen_action wanted_action,
                                     const struct unit *actor_unit,

Modified: trunk/fc_version
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/fc_version?rev=29998&r1=29997&r2=29998&view=diff
==============================================================================
--- trunk/fc_version    (original)
+++ trunk/fc_version    Wed Sep 30 17:52:11 2015
@@ -54,7 +54,7 @@
 #   - Avoid adding a new mandatory capability to the development branch for
 #     as long as possible.  We want to maintain network compatibility with
 #     the stable branch for as long as possible.
-NETWORK_CAPSTRING_MANDATORY="+Freeciv.Devel-3.0-2015.Sep.23"
+NETWORK_CAPSTRING_MANDATORY="+Freeciv.Devel-3.0-2015.Sep.30"
 NETWORK_CAPSTRING_OPTIONAL=""
 
 FREECIV_DISTRIBUTOR=""

Modified: trunk/server/cityturn.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/server/cityturn.c?rev=29998&r1=29997&r2=29998&view=diff
==============================================================================
--- trunk/server/cityturn.c     (original)
+++ trunk/server/cityturn.c     Wed Sep 30 17:52:11 2015
@@ -2027,7 +2027,15 @@
                       E_UNIT_LOST_MISC, ftc_server,
                       _("%s can't upkeep %s, unit disbanded."),
                       city_link(pcity), unit_link(punit));
-        handle_unit_disband(pplayer, punit->id);
+        /* What should be done if the Help Wonder action stops blocking
+         * Disband Unit? Cases where Disband Unit is better for the player
+         * than Help Wonder exists.
+         * Example: Unit in allied city that is building a wonder that
+         * makes the ally win without sharing the victory. */
+        /* TODO: Should the unit try to help cities on adjacent tiles? That
+         * would be a rules change. (This action is performed by the game
+         * it self) */
+        unit_do_disband_trad(pplayer, punit);
        /* pcity->surplus[O_SHIELD] is automatically updated. */
       }
     } unit_list_iterate_safe_end;

Modified: trunk/server/unithand.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/server/unithand.c?rev=29998&r1=29997&r2=29998&view=diff
==============================================================================
--- trunk/server/unithand.c     (original)
+++ trunk/server/unithand.c     Wed Sep 30 17:52:11 2015
@@ -1936,6 +1936,16 @@
     return;
   }
 
+  if (action_blocks_disband(punit)) {
+    /* Disband is blocked by the fact that another action is legal. */
+    notify_player(unit_owner(punit), unit_tile(punit),
+                  E_BAD_COMMAND, ftc_server,
+                  /* TRANS: ... Help Wonder ... */
+                  _("Regular disband not allowed. Try %s in stead."),
+                  action_get_ui_name(ACTION_HELP_WONDER));
+    return;
+  }
+
   pcity = tile_city(unit_tile(punit));
   if (pcity) {
     /* If you disband inside a city, it gives some shields to that city.
@@ -1944,20 +1954,16 @@
      * your ally receives those shields. Should it be like this? Why not?
      * That's why we must use city_owner instead of pplayer -- Zamar */
 
+    /* Add the shields from recycling the unit to the city's current
+     * production. */
+    pcity->shield_stock += unit_disband_shields(punit);
+
     if (unit_can_do_action(punit, ACTION_HELP_WONDER)) {
       /* Count this just like a caravan that was added to a wonder.
-       * However don't actually give the city the extra shields unless
-       * they are building a wonder (but switching to a wonder later in
-       * the turn will give the extra shields back). */
+       * However don't actually give the city the extra shields. Switching
+       * to a wonder later in the turn will give the extra shields back. */
       pcity->caravan_shields += unit_build_shield_cost(punit);
-      if (is_action_enabled_unit_on_city(ACTION_HELP_WONDER,
-                                         punit, pcity)) {
-       pcity->shield_stock += unit_build_shield_cost(punit);
-      } else {
-       pcity->shield_stock += unit_disband_shields(punit);
-      }
     } else {
-      pcity->shield_stock += unit_disband_shields(punit);
       /* If we change production later at this turn. No penalty is added. */
       pcity->disbanded_shields += unit_disband_shields(punit);
     }

Modified: trunk/server/unittools.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/server/unittools.c?rev=29998&r1=29997&r2=29998&view=diff
==============================================================================
--- trunk/server/unittools.c    (original)
+++ trunk/server/unittools.c    Wed Sep 30 17:52:11 2015
@@ -3679,6 +3679,40 @@
 }
 
 /**************************************************************************
+  Try to disband punit in the traditional way.
+
+  Try to disband the specified unit. Match the old behavior in what kind
+  of disbanding is tried and who benefits from it.
+**************************************************************************/
+void unit_do_disband_trad(struct player *owner, struct unit *punit)
+{
+  fc_assert_ret(owner == unit_owner(punit));
+
+  /* Help Wonder gives 100% of the shields used to produce the unit to the
+   * city where it is located. */
+  if (unit_can_do_action(punit, ACTION_HELP_WONDER)) {
+    struct city *tgt_city;
+
+    /* Only a city at the same tile as the unit can benefit. */
+    tgt_city = tile_city(unit_tile(punit));
+
+    if (tgt_city
+        && is_action_enabled_unit_on_city(ACTION_HELP_WONDER,
+                                          punit, tgt_city)) {
+      if (unit_perform_action(owner, punit->id, tgt_city->id,
+                              0, NULL, ACTION_HELP_WONDER)) {
+        /* No shields wasted. The unit did Help Wonder. */
+        return;
+      }
+    }
+  }
+
+  /* Disbanding a unit inside a city gives it 50% of the shields used to
+   * produce the unit. */
+  handle_unit_disband(owner, punit->id);
+}
+
+/**************************************************************************
   Maybe cancel the goto if there is an enemy in the way
 **************************************************************************/
 static bool maybe_cancel_goto_due_to_enemy(struct unit *punit, 

Modified: trunk/server/unittools.h
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/server/unittools.h?rev=29998&r1=29997&r2=29998&view=diff
==============================================================================
--- trunk/server/unittools.h    (original)
+++ trunk/server/unittools.h    Wed Sep 30 17:52:11 2015
@@ -150,6 +150,7 @@
 void unit_transport_load_send(struct unit *punit, struct unit *ptrans);
 void unit_transport_unload_send(struct unit *punit);
 bool unit_move(struct unit *punit, struct tile *ptile, int move_cost);
+void unit_do_disband_trad(struct player *owner, struct unit *punit);
 bool execute_orders(struct unit *punit, const bool fresh);
 
 bool unit_can_do_action_now(const struct unit *punit);


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

Reply via email to