[Freeciv-Dev] Re: (PR#4328) Disallow attacking tiles with not-at-war uni
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Some alterations done to Per's patch:
On Fri, 30 May 2003, Per I. Mathisen wrote:
> This patch
> 1) Moves can_unit_attack_unit_at_tile() from server to common.
Also move can_unit_attack_tile
> 2) Does some style changes to said function.
Much more style changes (major clean I would say)
> 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.
Such check is written as a separate function in common. I didn't change
much in handle_unit_move_request though, as this function is a pandora box
and should be cleaned asap!
G.
? ai/aisettler.c
? ai/aisettler.h
? ai/aiunit.cy
? common/aicore/citymap.c
? common/aicore/citymap.h
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 2003/05/06 08:13:21 1.30
+++ common/combat.c 2003/05/31 16:36:35
@@ -26,6 +26,121 @@
#include "combat.h"
/***********************************************************************
+ Checks if player is restricted diplomatically from attacking the tile.
+ Returns FLASE if
+ 1) the tile is empty or
+ 2) the tile contains a non-enemy city or
+ 3) the tile contains a non-enemy unit
+***********************************************************************/
+bool can_player_attack_tile(struct player *pplayer, int x, int y)
+{
+ struct city *pcity = map_get_city(x, y);
+ struct tile *ptile = map_get_tile(x, y);
+
+ /* 1. Is there anyone there at all? */
+ if (!pcity && unit_list_size(&(ptile->units)) == 0) {
+ return FALSE;
+ }
+
+ /* 2. If there is a city there, can we attack it? */
+ if (pcity && !pplayers_at_war(city_owner(pcity), pplayer)) {
+ return FALSE;
+ }
+
+ /* 3. Are we allowed to attack _all_ cities there? */
+ unit_list_iterate(ptile->units, aunit) {
+ if (!pplayers_at_war(unit_owner(aunit), pplayer)) {
+ /* Enemy hiding behind a human/diplomatic shield */
+ return FALSE;
+ }
+ } unit_list_iterate_end;
+
+ return TRUE;
+}
+
+/***********************************************************************
+ Checks if a unit can physically attack pdefender at the tile
+ (assuming it is adjacent and at war).
+
+ 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 target on an ocean square.
+ 5) it is a sailing unit without shore bombardment capability and it
+ attempts to attack land.
+
+ Does NOT check:
+ 1) Moves left
+ 2) Adjacency
+ 3) Diplomatic status
+***********************************************************************/
+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);
+
+ /* 1. Can we attack _anything_ ? */
+ if (!is_military_unit(punit) || unit_type(punit)->attack_strength == 0) {
+ return FALSE;
+ }
+
+ /* 2. Only fighters can attack planes, except in city or airbase attacks */
+ if (!unit_flag(punit, F_FIGHTER) && is_air_unit(pdefender)
+ && !(pcity || map_has_special(dest_x, dest_y, S_AIRBASE))) {
+ 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)) {
+ return FALSE;
+ }
+
+ /* 4. Ground units cannot attack water units */
+ if (is_ocean(totile) && is_ground_unit(punit)) {
+ return FALSE;
+ }
+
+ /* 5. Shore bombardement can be done by certain units only */
+ if (unit_flag(punit, F_NO_LAND_ATTACK) && !is_ocean(totile)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/***********************************************************************
+ Is unit (1) diplomatically allowed to attack and (2) physically able
+ to do so?
+
+ FIXME: Will need to check if can physically attack every unit in the
+ target tile in the future (layers etc).
+***********************************************************************/
+bool can_unit_attack_tile(struct unit *punit, int dest_x, int dest_y)
+{
+ struct unit *pdefender;
+
+ if (!can_player_attack_tile(unit_owner(punit), dest_x, dest_y)) {
+ return FALSE;
+ }
+
+ pdefender = get_defender(punit, dest_x, dest_y);
+ if (!pdefender) {
+ /* It must be the empty city! */
+ return TRUE;
+ }
+
+ return can_unit_attack_unit_at_tile(punit, pdefender, dest_x, dest_y);
+}
+
+/***********************************************************************
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 2003/05/06 08:13:21 1.8
+++ common/combat.h 2003/05/31 16:36:35
@@ -26,6 +26,11 @@
struct unit;
struct player;
+bool can_player_attack_tile(struct player *pplayer, int x, int y);
+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);
+
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 2003/05/06 08:13:21 1.259
+++ server/unithand.c 2003/05/31 16:36:35
@@ -923,6 +923,8 @@
'move_diplomat_city' is another special case which should normally be
FALSE. If TRUE, try to move diplomat (or spy) into city (should be
allied) instead of telling client to popup diplomat/spy dialog.
+
+ FIXME: This function needs a good cleaning.
**************************************************************************/
bool handle_unit_move_request(struct unit *punit, int dest_x, int dest_y,
bool igzoc, bool move_diplomat_city)
@@ -1010,8 +1012,23 @@
how_to_declare_war(pplayer);
return FALSE;
}
+
+ /* Tile must contain ONLY enemy units. */
+ unit_list_iterate(pdesttile->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 unit since it is "
+ "stacked with %s's unit(s) and you are not "
+ "at war with %s."),
+ unit_owner(pdefender)->name,
+ unit_owner(aunit)->name,
+ unit_owner(aunit)->name);
+ how_to_declare_war(pplayer);
+ return FALSE;
+ }
+ } unit_list_iterate_end;
- if (!can_unit_attack_tile(punit, dest_x , dest_y)) {
+ if (!can_unit_attack_unit_at_tile(punit, pdefender, dest_x , dest_y)) {
notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT,
_("Game: You can't attack there."));
return FALSE;
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 2003/05/30 18:17:01 1.224
+++ server/unittools.c 2003/05/31 16:36:35
@@ -104,87 +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)
-{
- struct unit *pdefender;
- pdefender=get_defender(punit, dest_x, dest_y);
- if (!pdefender) {
- struct city *pcity = map_get_city(dest_x, dest_y);
- if (pcity && pplayers_at_war(city_owner(pcity), unit_owner(punit))) {
- /* empty city, yummy! */
- return TRUE;
- }
- /* nothing to attack */
- return FALSE;
- }
- return(can_unit_attack_unit_at_tile(punit, pdefender, dest_x, dest_y));
-}
-
-/**************************************************************************
after a battle this routine is called to decide whether or not the unit
should become a veteran, if unit isn't already.
there is a 50/50% chance for it to happend, (100% if player got SUNTZU)
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 2003/05/06 05:06:07 1.50
+++ server/unittools.h 2003/05/31 16:36:35
@@ -23,8 +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);
|
|