Complete.Org: Mailing Lists: Archives: freeciv-dev: March 2005:
[Freeciv-Dev] (PR#12559) [Patch] is_ocean() -> can_unit_exist_at_tile()
Home

[Freeciv-Dev] (PR#12559) [Patch] is_ocean() -> can_unit_exist_at_tile()

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#12559) [Patch] is_ocean() -> can_unit_exist_at_tile()
From: "Marko Lindqvist" <marko.lindqvist@xxxxxxxxxxx>
Date: Sun, 20 Mar 2005 01:50:22 -0800
Reply-to: bugs@xxxxxxxxxxx

<URL: http://bugs.freeciv.org/Ticket/Display.html?id=12559 >


  It seems that first version of this patch was never sent, so creating 
new ticket.

  Some is_ocean() calls are used to check if unit can move to certain 
tile. This patch replaces most of those with can_unit_exist_at_tile().

  This patch is needed for gen-movement, but has some potential for 
rare, hard to find bugs:
  if(can_unit_exist_at_tile(punit, ptile))

  ...is really equivalent to...
  if(is_air_unit(punit) || is_heli_unit(punit)
     || (is_sailing_unit(punit) && is_ocean(ptile))
     || (is_ground_unit(punit) && !is_ocean(ptile))

  ... but this patch uses it in places of
if(is_ground_unit(punit) && is_ocean(ptile))


  This also causes some behavior changes:

  1. Air and Heli units can build cities anywhere (previously nowhere)
  2. Sailing units cannot attack inland from harbors
  3. SEA_MOVING diplomats now possible?
  4. Third party ships are not bounced when resolving unit stacks
  5. Probably more


  I just noticed a bug related to 2). Ships need F_MARINES flag for 
harbor -> sea attack. Air/heli/missile units cannot attack at all.


  - ML


diff -Nurd -X.diff_ignore freeciv/ai/aidata.c freeciv/ai/aidata.c
--- freeciv/ai/aidata.c 2005-03-20 00:00:49.593750000 +0200
+++ freeciv/ai/aidata.c 2005-03-20 01:19:47.937500000 +0200
@@ -529,6 +529,8 @@
   unit_list_iterate(pplayer->units, punit) {
     struct tile *ptile = punit->tile;
 
+    /* FIXME: Use can_unit_exist_at_tile() instead of is_ocean(),
+     * when stats.workers[] has space for sea workers. */
     if (!is_ocean(ptile->terrain) && unit_flag(punit, F_SETTLERS)) {
       ai->stats.workers[(int)map_get_continent(punit->tile)]++;
     }
diff -Nurd -X.diff_ignore freeciv/ai/aiferry.c freeciv/ai/aiferry.c
--- freeciv/ai/aiferry.c        2005-03-20 00:00:49.640625000 +0200
+++ freeciv/ai/aiferry.c        2005-03-20 01:19:47.968750000 +0200
@@ -327,6 +327,10 @@
   search_map = pf_create_map(&param);
 
   pf_iterator(search_map, pos) {
+    /* Should this be !can_unit_exist_at_tile() instead of is_ocean() some day?
+     * That would allow special units to wade in shallow coast waters to meet
+     * ferry where deep sea starts. That would require some quite fundamental
+     * code changes elsewhere. */
     int radius = (is_ocean(pos.tile->terrain) ? 1 : 0);
 
     if (pos.turn + pos.total_EC/PF_TURN_FACTOR > best_turns) {
diff -Nurd -X.diff_ignore freeciv/ai/aihunt.c freeciv/ai/aihunt.c
--- freeciv/ai/aihunt.c 2005-03-20 00:00:49.671875000 +0200
+++ freeciv/ai/aihunt.c 2005-03-20 01:19:47.968750000 +0200
@@ -280,7 +280,7 @@
 
       if (ptile->city
           || TEST_BIT(target->ai.hunted, pplayer->player_no)
-          || (!is_ocean(ptile->terrain) && is_sailing_unit(punit))
+          || (!can_unit_exist_at_tile(punit, ptile))
           || (!is_sailing_unit(target) && is_sailing_unit(punit))
           || (is_sailing_unit(target) && !is_sailing_unit(punit))
           || !goto_is_sane(punit, target->tile, TRUE)) {
diff -Nurd -X.diff_ignore freeciv/ai/aiunit.c freeciv/ai/aiunit.c
--- freeciv/ai/aiunit.c 2005-03-20 00:00:49.718750000 +0200
+++ freeciv/ai/aiunit.c 2005-03-20 01:52:28.953125000 +0200
@@ -1855,7 +1855,7 @@
     struct tile *ftile;
 
     if ((pc = dist_nearest_city(pplayer, punit->tile, FALSE, TRUE))) {
-      if (!is_ocean(map_get_terrain(punit->tile))) {
+      if (can_unit_exist_at_tile(punit, punit->tile)) {
         UNIT_LOG(LOG_DEBUG, punit, "Barbarian marching to conquer %s", 
pc->name);
         (void) ai_gothere(pplayer, punit, pc->tile);
       } else {
@@ -2247,9 +2247,9 @@
 
   CHECK_UNIT(leader);
 
-  if (leader->moves_left == 0 || 
-      (!is_ocean(map_get_terrain(leader->tile)) &&
-       unit_list_size(leader->tile->units) > 1) ) {
+  if (leader->moves_left == 0
+      || (can_unit_exist_at_tile(leader, leader->tile)
+          && unit_list_size(leader->tile->units) > 1) ) {
       handle_unit_activity_request(leader, ACTIVITY_SENTRY);
       return;
   }
diff -Nurd -X.diff_ignore freeciv/common/city.c freeciv/common/city.c
--- freeciv/common/city.c       2005-03-20 00:01:05.296875000 +0200
+++ freeciv/common/city.c       2005-03-20 01:19:48.000000000 +0200
@@ -887,16 +887,10 @@
     return FALSE;
   }
 
-  if (punit) {
-    enum unit_move_type move_type = unit_type(punit)->move_type;
-    Terrain_type_id t = ptile->terrain;
-
+  if (punit && !can_unit_exist_at_tile(punit, ptile)) {
     /* We allow land units to build land cities and sea units to build
-     * ocean cities. */
-    if ((move_type == LAND_MOVING && is_ocean(t))
-       || (move_type == SEA_MOVING && !is_ocean(t))) {
-      return FALSE;
-    }
+     * ocean cities. Air units can build cities anywhere. */
+    return FALSE;
   }
 
   /* game.rgame.min_dist_bw_cities minimum is 1, meaning adjacent is okay */
diff -Nurd -X.diff_ignore freeciv/common/combat.c freeciv/common/combat.c
--- freeciv/common/combat.c     2005-03-20 00:01:05.500000000 +0200
+++ freeciv/common/combat.c     2005-03-20 01:43:13.296875000 +0200
@@ -80,7 +80,6 @@
                                  const struct unit *pdefender,
                                   const struct tile *dest_tile)
 {
-  Terrain_type_id fromtile = punit->tile->terrain;
   Terrain_type_id totile = dest_tile->terrain;
   struct city *pcity = dest_tile->city;
 
@@ -95,10 +94,11 @@
     return FALSE;
   }
 
-  /* 3. Can't attack with ground unit from ocean, except for marines */
-  if (is_ocean(fromtile)
-      && is_ground_unit(punit)
-      && !unit_flag(punit, F_MARINES)) {
+  /* 3. Can't attack from hostile terrain, except marines to
+        friendly terrain. */
+  if (!can_unit_survive_at_tile(punit, punit->tile)
+      && !(can_unit_survive_at_tile(punit, dest_tile)
+           && unit_flag(punit, F_MARINES))) {
     return FALSE;
   }
 
diff -Nurd -X.diff_ignore freeciv/common/unit.c freeciv/common/unit.c
--- freeciv/common/unit.c       2005-03-20 00:01:07.312500000 +0200
+++ freeciv/common/unit.c       2005-03-20 01:19:48.046875000 +0200
@@ -77,8 +77,8 @@
 {
   struct city *pcity=map_get_city(ptile);
 
-  if (action!=DIPLOMAT_MOVE
-      && is_ocean(map_get_terrain(pdiplomat->tile))) {
+  if (action != DIPLOMAT_MOVE
+      && !can_unit_exist_at_tile(pdiplomat, ptile)) {
     return FALSE;
   }
 
@@ -1127,12 +1127,12 @@
   unit_list_iterate(ptile->units, punit) {
     if (unit_owner(punit) == pplayer) {
       if (unit_flag(punit, F_CARRIER)
-         && !(is_ground_unit(punit) && is_ocean(ptile->terrain))) {
+          && can_unit_exist_at_tile(punit, ptile)) {
        *airall += get_transporter_capacity(punit);
        continue;
       }
       if (unit_flag(punit, F_MISSILE_CARRIER)
-         && !(is_ground_unit(punit) && is_ocean(ptile->terrain))) {
+         && can_unit_exist_at_tile(punit, ptile)) {
        *misonly += get_transporter_capacity(punit);
        continue;
       }
diff -Nurd -X.diff_ignore freeciv/server/unithand.c freeciv/server/unithand.c
--- freeciv/server/unithand.c   2005-03-20 00:01:32.000000000 +0200
+++ freeciv/server/unithand.c   2005-03-20 01:26:37.828125000 +0200
@@ -1041,10 +1041,7 @@
         return FALSE;
       } else if (!can_unit_move_to_tile(punit, pdesttile, igzoc)) {
         notify_player_ex(pplayer, punit->tile, E_NOEVENT,
-                         is_ocean(map_get_terrain(punit->tile))
-                         ? _("Unit must be on land to "
-                             "perform diplomatic action.")
-                         : _("No diplomat action possible."));
+                         _("No diplomat action possible."));
         return FALSE;
       }
     }
diff -Nurd -X.diff_ignore freeciv/server/unittools.c freeciv/server/unittools.c
--- freeciv/server/unittools.c  2005-03-20 00:01:32.031250000 +0200
+++ freeciv/server/unittools.c  2005-03-20 01:33:19.171875000 +0200
@@ -1269,7 +1269,7 @@
 
 /**************************************************************************
   For each pplayer's unit, check if we stack illegally, if so,
-  bounce both players' units. If on ocean tile, bounce everyone
+  bounce both players' units. If on ocean tile, bounce everyone but ships
   to avoid drowning. This function assumes that cities are clean.
 
   If verbose is true, the unit owner gets messages about where each
@@ -1285,7 +1285,7 @@
       unit_list_iterate_safe(ptile->units, aunit) {
         if (unit_owner(aunit) == pplayer
             || unit_owner(aunit) == aplayer
-            || is_ocean(ptile->terrain)) {
+            || !can_unit_survive_at_tile(aunit, ptile)) {
           bounce_unit(aunit, verbose);
         }
       } unit_list_iterate_safe_end;
@@ -2178,11 +2178,16 @@
     return FALSE;
   }
 
+  /* FIXME: Should check if unit can exist at terrain instead
+   *        of checking if terrain is ocean. */
+  /* FIXME: Should we allow paradropping anyway, player may have
+   *        reason to believe that ocean is terraformed into land? */
   if (is_ocean(map_get_player_tile(ptile, pplayer)->terrain)
       && is_ground_unit(punit)) {
     notify_player_ex(pplayer, ptile, E_NOEVENT,
-                     _("This unit cannot paradrop into ocean."));
-    return FALSE;    
+                     _("This unit cannot paradrop into %s."),
+                       get_terrain_name(map_get_player_tile(ptile, 
pplayer)->terrain));
+    return FALSE;
   }
 
   if (map_is_known_and_seen(ptile, pplayer)
@@ -2206,16 +2211,15 @@
     }
   }
 
-  if (is_ocean(map_get_terrain(ptile))
-      && is_ground_unit(punit)) {
+  if (!can_unit_exist_at_tile(punit, ptile)) {
     int srange = unit_type(punit)->vision_range;
 
     show_area(pplayer, ptile, srange);
 
     notify_player_ex(pplayer, ptile, E_UNIT_LOST,
-                     _("Your %s paradropped into the ocean "
+                     _("Your %s paradropped into the %s."
                        "and was lost."),
-                     unit_type(punit)->name);
+                     unit_type(punit)->name, get_terrain_name(ptile->terrain));
     server_remove_unit(punit);
     return TRUE;
   }
@@ -2589,8 +2593,6 @@
   square_iterate(punit->tile, 3, ptile) {
     unit_list_iterate(ptile->units, penemy) {
       int range;
-      enum unit_move_type move_type = unit_type(penemy)->move_type;
-      Terrain_type_id terrain = map_get_terrain(ptile);
 
       if (map_has_special(ptile, S_FORTRESS)
          && unit_profits_of_watchtower(penemy))
@@ -2603,7 +2605,7 @@
          && range >= real_map_distance(punit->tile, ptile)
          && can_player_see_unit(unit_owner(penemy), punit)
          /* on board transport; don't awaken */
-         && !(move_type == LAND_MOVING && is_ocean(terrain))) {
+          && !can_unit_exist_at_tile(punit, punit->tile)) {
        set_unit_activity(penemy, ACTIVITY_IDLE);
        send_unit_info(NULL, penemy);
       }

[Prev in Thread] Current Thread [Next in Thread]