Author: sveinung
Date: Thu Mar 24 15:15:43 2016
New Revision: 32267

URL: http://svn.gna.org/viewcvs/freeciv?rev=32267&view=rev
Log:
Separate hard actor action requirements check.

Separate the checking of hard requirements that only applies to the actor
unit but aren't game state independent to the new function
action_hard_reqs_actor(). Have it use action_actor_utype_hard_reqs_ok() to
check hard action requirements that applies to the actor's unit type just
like is_action_possible() did.

See patch #7071

Modified:
    trunk/common/actions.c

Modified: trunk/common/actions.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/common/actions.c?rev=32267&r1=32266&r2=32267&view=diff
==============================================================================
--- trunk/common/actions.c      (original)
+++ trunk/common/actions.c      Thu Mar 24 15:15:43 2016
@@ -1047,6 +1047,104 @@
 }
 
 /**************************************************************************
+  Returns TRUE iff the wanted action is possible as far as the actor is
+  concerned given that an action enabler later will enable it. Will, unlike
+  action_actor_utype_hard_reqs_ok(), check the actor unit's current state.
+
+  Can return maybe when not omniscient. Should always return yes or no when
+  omniscient.
+**************************************************************************/
+static enum fc_tristate
+action_hard_reqs_actor(const enum gen_action wanted_action,
+                       const struct player *actor_player,
+                       const struct city *actor_city,
+                       const struct impr_type *actor_building,
+                       const struct tile *actor_tile,
+                       const struct unit *actor_unit,
+                       const struct unit_type *actor_unittype,
+                       const struct output_type *actor_output,
+                       const struct specialist *actor_specialist,
+                       const bool omniscient)
+{
+  if (!action_actor_utype_hard_reqs_ok(wanted_action, actor_unittype)) {
+    /* Info leak: The actor player knows the type of his unit. */
+    /* The actor unit type can't perform the action because of hard
+     * unit type requirements. */
+    return TRI_NO;
+  }
+
+  switch (wanted_action) {
+  case ACTION_TRADE_ROUTE:
+  case ACTION_MARKETPLACE:
+    /* It isn't possible to establish a trade route from a non existing
+     * 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)) {
+      return TRI_NO;
+    }
+
+    break;
+
+  case ACTION_PARADROP:
+    /* Reason: Keep the old rules. */
+    /* Info leak: The player knows if his unit has paradropped this turn,
+     * how many move fragments it has left and if it is standing in a city
+     * or in a base with the ParadropFrom flag. */
+    if (!can_unit_paradrop(actor_unit)) {
+      return TRI_NO;
+    }
+
+    /* Reason: The paradrop code doesn't check if transported units can
+     * coexist with the target tile city and units. */
+    /* Info leak: The player knows if his unit is transporting a unit. */
+    /* This hard coded limitation is detected in the action not enabled
+     * explanation code. Remember to remove it too if this hard coded
+     * limitation moves to the ruleset. */
+    if (get_transporter_occupancy(actor_unit) > 0) {
+      return TRI_NO;
+    }
+
+    break;
+
+  case ACTION_ESTABLISH_EMBASSY:
+  case ACTION_SPY_INVESTIGATE_CITY:
+  case ACTION_SPY_POISON:
+  case ACTION_SPY_STEAL_GOLD:
+  case ACTION_SPY_SABOTAGE_CITY:
+  case ACTION_SPY_TARGETED_SABOTAGE_CITY:
+  case ACTION_SPY_STEAL_TECH:
+  case ACTION_SPY_TARGETED_STEAL_TECH:
+  case ACTION_SPY_INCITE_CITY:
+  case ACTION_HELP_WONDER:
+  case ACTION_SPY_BRIBE_UNIT:
+  case ACTION_SPY_SABOTAGE_UNIT:
+  case ACTION_CAPTURE_UNITS:
+  case ACTION_FOUND_CITY:
+  case ACTION_JOIN_CITY:
+  case ACTION_STEAL_MAPS:
+  case ACTION_BOMBARD:
+  case ACTION_SPY_NUKE:
+  case ACTION_NUKE:
+  case ACTION_DESTROY_CITY:
+  case ACTION_EXPEL_UNIT:
+  case ACTION_RECYCLE_UNIT:
+  case ACTION_DISBAND_UNIT:
+  case ACTION_HOME_CITY:
+  case ACTION_UPGRADE_UNIT:
+  case ACTION_AIRLIFT:
+    /* No hard unit type requirements. */
+    break;
+
+  case ACTION_COUNT:
+    fc_assert_ret_val(wanted_action != ACTION_COUNT, TRI_NO);
+    break;
+  }
+
+  return TRI_YES;
+}
+
+/**************************************************************************
   Returns if the wanted action is possible given that an action enabler
   later will enable it.
 
@@ -1088,6 +1186,7 @@
 {
   bool can_see_tgt_unit;
   bool can_see_tgt_tile;
+  enum fc_tristate out;
 
   fc_assert_msg((action_get_target_kind(wanted_action) == ATK_CITY
                  && target_city != NULL)
@@ -1113,13 +1212,6 @@
    * omniscient. The player asking about his odds isn't. */
   can_see_tgt_tile = (omniscient
                       || plr_sees_tile(actor_player, target_tile));
-
-  if (!action_actor_utype_hard_reqs_ok(wanted_action, actor_unittype)) {
-    /* Info leak: The actor player knows the type of his unit. */
-    /* The actor unit type can't perform the action because of hard
-     * unit type requirements. */
-    return TRI_NO;
-  }
 
   /* Info leak: The player knows where his unit is. */
   if (action_get_target_kind(wanted_action) != ATK_SELF) {
@@ -1169,6 +1261,18 @@
     }
   }
 
+  /* Actor specific hard requirements. */
+  out = action_hard_reqs_actor(wanted_action,
+                               actor_player, actor_city, actor_building,
+                               actor_tile, actor_unit, actor_unittype,
+                               actor_output, actor_specialist,
+                               omniscient);
+
+  if (out == TRI_NO) {
+    /* Illegal because of a hard actor requirement. */
+    return TRI_NO;
+  }
+
   /* Hard requirements for individual actions. */
   switch (wanted_action) {
   case ACTION_CAPTURE_UNITS:
@@ -1235,12 +1339,10 @@
     {
       const struct city *actor_homecity;
 
-      /* It isn't possible to establish a trade route from a non existing
-       * city. The Freeciv code assumes this applies to Enter Marketplace
-       * too. */
-      if (!(actor_homecity = game_city_by_number(actor_unit->homecity))) {
-        return TRI_NO;
-      }
+      actor_homecity = game_city_by_number(actor_unit->homecity);
+
+      /* Checked in action_hard_reqs_actor() */
+      fc_assert_ret_val(actor_homecity != NULL, TRI_NO);
 
       /* Can't establish a trade route or enter the market place if the
        * cities can't trade at all. */
@@ -1456,24 +1558,6 @@
 
   case ACTION_PARADROP:
     /* Reason: Keep the old rules. */
-    /* Info leak: The player knows if his unit has paradropped this turn,
-     * how many move fragments it has left and if it is standing in a city
-     * or in a base with the ParadropFrom flag. */
-    if (!can_unit_paradrop(actor_unit)) {
-      return TRI_NO;
-    }
-
-    /* Reason: The paradrop code doesn't check if transported units can
-     * coexist with the target tile city and units. */
-    /* Info leak: The player knows if his unit is transporting a unit. */
-    /* This hard coded limitation is detected in the action not enabled
-     * explanation code. Remember to remove it too if this hard coded
-     * limitation moves to the ruleset. */
-    if (get_transporter_occupancy(actor_unit) > 0) {
-      return TRI_NO;
-    }
-
-    /* Reason: Keep the old rules. */
     /* Info leak: The player knows if he knows the target tile. */
     if (!plr_knows_tile(actor_player, target_tile)) {
       return TRI_NO;
@@ -1523,7 +1607,7 @@
     break;
   }
 
-  return TRI_YES;
+  return out;
 }
 
 /**************************************************************************


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

Reply via email to