[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 <=
|
|