Complete.Org: Mailing Lists: Archives: freeciv-dev: May 2003:
[Freeciv-Dev] (PR#4328) Disallow attacking tiles with not-at-war units
Home

[Freeciv-Dev] (PR#4328) Disallow attacking tiles with not-at-war units

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] (PR#4328) Disallow attacking tiles with not-at-war units
From: "Per I. Mathisen" <per@xxxxxxxxxxx>
Date: Fri, 30 May 2003 12:30:03 -0700
Reply-to: rt@xxxxxxxxxxxxxx

This patch
 1) Moves can_unit_attack_unit_at_tile() from server to common.
 2) Does some style changes to said function.
 3) Adds check to said function and handle_unit_move_request() to disallow
a unit from attacking a tile that contains any unit that we are not at war
with.

This patch should cut straight through the gordian knot issue of attacks
on mixed-ownership stacks.

Please read, comment and commit as soon as possible.

  - Per

Index: common/combat.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/combat.c,v
retrieving revision 1.30
diff -u -r1.30 combat.c
--- common/combat.c     6 May 2003 08:13:21 -0000       1.30
+++ common/combat.c     30 May 2003 19:24:42 -0000
@@ -26,6 +26,77 @@
 #include "combat.h"
 
 /***********************************************************************
+ Unit can not attack if:
+ 1) it does not have any attack power.
+ 2) it is not a fighter and defender is a flying unit (except city/airbase).
+ 3) it is a ground unit without marine ability and it attacks from ocean.
+ 4) it is a ground unit and it attacks a ship on an ocean square.
+ 5) the players are not at war.
+ 6) a city there is owned by non-attack player.
+ 7) tile contains any unit we are not at war with.
+
+ Does NOT check:
+ 1) Moves left
+ 2) Adjacency
+***********************************************************************/
+bool can_unit_attack_unit_at_tile(struct unit *punit, struct unit *pdefender,
+                                  int dest_x, int dest_y)
+{
+  enum tile_terrain_type fromtile;
+  enum tile_terrain_type totile;
+  struct city *pcity = map_get_city(dest_x, dest_y);
+
+  fromtile = map_get_terrain(punit->x, punit->y);
+  totile   = map_get_terrain(dest_x, dest_y);
+
+  if (!is_military_unit(punit) || unit_type(punit)->attack_strength == 0) {
+    return FALSE;
+  }
+
+  /* only fighters can attack planes, except for city or airbase attacks */
+  if (!unit_flag(punit, F_FIGHTER) && is_air_unit(pdefender)
+      && !(map_get_city(dest_x, dest_y) 
+           || map_has_special(dest_x, dest_y, S_AIRBASE))) {
+    return FALSE;
+  }
+  /* can't attack with ground unit from ocean, except for marines */
+  if (is_ocean(fromtile)
+      && is_ground_unit(punit)
+      && !unit_flag(punit, F_MARINES)) {
+    return FALSE;
+  }
+
+  if (is_ocean(totile) && is_ground_unit(punit)) {
+    return FALSE;
+  }
+
+  if (unit_flag(punit, F_NO_LAND_ATTACK) && !is_ocean(totile)) {
+    return FALSE;
+  }
+
+  if (!pplayers_at_war(unit_owner(punit), unit_owner(pdefender))) {
+    return FALSE;
+  }
+
+  /* Shore bombardement */
+  if (is_ocean(fromtile) && is_sailing_unit(punit) && !is_ocean(totile)) {
+    return (get_attack_power(punit) > 0);
+  }
+
+  if (pcity && !pplayers_at_war(city_owner(pcity), unit_owner(punit))) {
+    return FALSE;
+  }
+
+  unit_list_iterate(map_get_tile(dest_x, dest_y)->units, aunit) {
+    if (!pplayers_at_war(unit_owner(aunit), unit_owner(punit))) {
+      return FALSE; /* Enemy hiding behind a human/diplomatic shield */
+    }
+  } unit_list_iterate_end;
+
+  return TRUE;
+}
+
+/***********************************************************************
 Returns the chance of the attacker winning, a number between 0 and 1.
 If you want the chance that the defender wins just use 1-chance(...)
 
Index: common/combat.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/combat.h,v
retrieving revision 1.8
diff -u -r1.8 combat.h
--- common/combat.h     6 May 2003 08:13:21 -0000       1.8
+++ common/combat.h     30 May 2003 19:24:42 -0000
@@ -26,6 +26,9 @@
 struct unit;
 struct player;
 
+bool can_unit_attack_unit_at_tile(struct unit *punit, struct unit *pdefender,
+                                  int dest_x, int dest_y);
+
 double win_chance(int as, int ahp, int afp, int ds, int dhp, int dfp);
 
 void get_modified_firepower(struct unit *attacker, struct unit *defender,
Index: server/unithand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unithand.c,v
retrieving revision 1.259
diff -u -r1.259 unithand.c
--- server/unithand.c   6 May 2003 08:13:21 -0000       1.259
+++ server/unithand.c   30 May 2003 19:24:42 -0000
@@ -1011,6 +1011,19 @@
       return FALSE;
     }
 
+    /* Tile must contain ONLY enemy units. */
+    unit_list_iterate(map_get_tile(dest_x, dest_y)->units, aunit) {
+      if (!pplayers_at_war(unit_owner(aunit), unit_owner(punit))) {
+        notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT,
+                        _("Game: Can't attack %s's %s since it is "
+                          "stacked with %s's %s."), 
+                         unit_owner(pdefender)->name, 
+                         unit_type(pdefender)->name,
+                         unit_owner(aunit)->name, unit_type(aunit)->name);
+        return FALSE; /* Enemy hiding behind a human/diplomatic shield */
+      }
+    } unit_list_iterate_end;
+
     if (!can_unit_attack_tile(punit, dest_x , dest_y)) {
       notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT,
                       _("Game: You can't attack there."));
Index: server/unittools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unittools.c,v
retrieving revision 1.224
diff -u -r1.224 unittools.c
--- server/unittools.c  30 May 2003 18:17:01 -0000      1.224
+++ server/unittools.c  30 May 2003 19:24:43 -0000
@@ -104,68 +104,6 @@
 }
 
 /**************************************************************************
- Unit can not attack if:
- 1) it does not have any attack power.
- 2) it is not a fighter and defender is a flying unit (except city/airbase).
- 3) it is a ground unit without marine ability and it attacks from ocean.
- 4) it is a ground unit and it attacks a ship on an ocean square.
- 5) the players are not at war.
- 6) a city there is owned by non-attack player
-
- Does NOT check:
- 1) Moves left
- 2) Adjacency
-**************************************************************************/
-bool can_unit_attack_unit_at_tile(struct unit *punit, struct unit *pdefender,
-                                  int dest_x, int dest_y)
-{
-  enum tile_terrain_type fromtile;
-  enum tile_terrain_type totile;
-  struct city *pcity = map_get_city(dest_x, dest_y);
-
-  fromtile = map_get_terrain(punit->x, punit->y);
-  totile   = map_get_terrain(dest_x, dest_y);
-
-  if (!is_military_unit(punit) || unit_type(punit)->attack_strength == 0) {
-    return FALSE;
-  }
-
-  /* only fighters can attack planes, except for city or airbase attacks */
-  if (!unit_flag(punit, F_FIGHTER) && is_air_unit(pdefender) &&
-      !(map_get_city(dest_x, dest_y) || map_has_special(dest_x, dest_y, 
S_AIRBASE))) {
-    return FALSE;
-  }
-  /* can't attack with ground unit from ocean, except for marines */
-  if (is_ocean(fromtile)
-      && is_ground_unit(punit)
-      && !unit_flag(punit, F_MARINES)) {
-    return FALSE;
-  }
-
-  if (is_ocean(totile) && is_ground_unit(punit)) {
-    return FALSE;
-  }
-
-  if (unit_flag(punit, F_NO_LAND_ATTACK) && !is_ocean(totile)) {
-    return FALSE;
-  }
-  
-  if (!pplayers_at_war(unit_owner(punit), unit_owner(pdefender)))
-    return FALSE;
-
-  /* Shore bombardement */
-  if (is_ocean(fromtile) && is_sailing_unit(punit) && !is_ocean(totile)) {
-    return (get_attack_power(punit)>0);
-  }
-
-  if (pcity && !pplayers_at_war(city_owner(pcity), unit_owner(punit))) {
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
-/**************************************************************************
 ...
 **************************************************************************/
 bool can_unit_attack_tile(struct unit *punit, int dest_x, int dest_y)
Index: server/unittools.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unittools.h,v
retrieving revision 1.50
diff -u -r1.50 unittools.h
--- server/unittools.h  6 May 2003 05:06:07 -0000       1.50
+++ server/unittools.h  30 May 2003 19:24:43 -0000
@@ -23,7 +23,6 @@
 
 /* battle related */
 int find_a_unit_type(int role, int role_tech);
-bool can_unit_attack_unit_at_tile(struct unit *punit, struct unit *pdefender, 
int dest_x, int dest_y);
 bool can_unit_attack_tile(struct unit *punit, int dest_x, int dest_y);
 void maybe_make_veteran(struct unit *punit);
 void unit_versus_unit(struct unit *attacker, struct unit *defender);

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#4328) Disallow attacking tiles with not-at-war units, Per I. Mathisen <=