Complete.Org: Mailing Lists: Archives: freeciv-dev: December 1998:
Re: [Freeciv-Dev] Diplomat can't "attack" city
Home

Re: [Freeciv-Dev] Diplomat can't "attack" city

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: David Pfitzner <dwp@xxxxxxxxxxxxxx>
Cc: freeciv-dev@xxxxxxxxxxx
Subject: Re: [Freeciv-Dev] Diplomat can't "attack" city
From: Patrick Smith <patsmith@xxxxxxxxx>
Date: Thu, 10 Dec 1998 05:56:24 +0000

> > Sometimes when I try to send a diplomat into a city, I get the message
> > "You can't attack there".  This is an enemy city I've never sent a
> > diplomat into previously.
> 
> This means the diplomat doesn't have enough movement left
> to move onto the square where the city is.  It's kind of a
> bug that this isn't handled more gracefully.

I see.  Looking at the code and experimenting a bit, it seems three
different
things can happen in this situation:

- The message "You can't attack there", if the city is occupied.

- The message "Only ground troops can take over a city", if the city is
empty
  and a random number goes in favor of allowing you to move.

- Nothing at all, if the city is empty and the random number goes
against
  letting you move.

Anyway, here's a patch so we always get the message "You don't have
enough movement left".

This patch also fixes what I assume is another bug -- a diplomat can't
infiltrate a city built on a mountain, even if the diplomat hasn't moved
at all this turn.  Please feel free to apply the patch in CVS, if you so
desire.  It is based on the Dec 7 CVS snapshot.

-- 
patsmith@xxxxxxxxx


diff -r -u old/client/mapctrl.c freeciv/client/mapctrl.c
--- old/client/mapctrl.c        Fri Oct 23 06:35:42 1998
+++ freeciv/client/mapctrl.c    Wed Dec  9 23:52:16 1998
@@ -191,17 +191,16 @@
       }
     }
   }
-  else if(unit_flag(punit->type, F_DIPLOMAT)) {
-    if(diplomat_can_do_action(punit, DIPLOMAT_BRIBE, dest_x, dest_y) ||
-       diplomat_can_do_action(punit, DIPLOMAT_SABOTAGE, dest_x, dest_y)
||
-       (unit_flag(punit->type, F_SPY) && 
-       diplomat_can_do_action(punit, SPY_SABOTAGE_UNIT, dest_x,
dest_y)) ||
-       diplomat_can_do_action(punit, DIPLOMAT_EMBASSY, dest_x, dest_y))
{
+  else if(unit_flag(punit->type, F_DIPLOMAT) &&
+          is_diplomat_action_available(punit, DIPLOMAT_ANY_ACTION,
+                                       dest_x, dest_y)) {
+    if (diplomat_can_do_action(punit, DIPLOMAT_ANY_ACTION, dest_x,
dest_y))
       popup_diplomat_dialog(punit, dest_x, dest_y);
-      return;
-    }
+    else
+      append_output_window("Game: You don't have enough movement
left");
+    return;
   }
-  
+
   req_unit=*punit;
   req_unit.x=dest_x;
   req_unit.y=dest_y;
diff -r -u old/common/unit.c freeciv/common/unit.c
--- old/common/unit.c   Mon Nov  9 06:34:15 1998
+++ freeciv/common/unit.c       Wed Dec  9 23:50:44 1998
@@ -150,46 +150,72 @@

**************************************************************************/
 

/**************************************************************************
-...
+Whether a diplomat can move to a particular tile and perform a
+particular action there.

**************************************************************************/
 int diplomat_can_do_action(struct unit *pdiplomat,
                           enum diplomat_actions action, 
                           int destx, int desty)
 {
+  if(!is_diplomat_action_available(pdiplomat, action, destx, desty))
+    return 0;
+
+  if(!is_tiles_adjacent(pdiplomat->x, pdiplomat->y, destx, desty))
+    return 0;
+
+  if(pdiplomat->moves_left >= unit_move_rate(pdiplomat))
+    return 1;   /* Hasn't moved yet this turn */
+
+  if(pdiplomat->moves_left >= map_move_cost(pdiplomat, destx, desty))
+    return 1;
+
+  return 0;
+}
+
+/**************************************************************************
+Whether a diplomat can perform a particular action at a particular
+tile.  This does _not_ check whether the diplomat can move there.
+If the action is DIPLOMAT_ANY_ACTION, checks whether there is any
+action the diplomat can perform at the tile.
+**************************************************************************/
+int is_diplomat_action_available(struct unit *pdiplomat,
+                                enum diplomat_actions action, 
+                                int destx, int desty)
+{
   struct city *pcity=map_get_city(destx, desty);
-  struct tile *ptile=map_get_tile(destx, desty);
-  int move_cost = tile_move_cost(pdiplomat,pdiplomat->x,pdiplomat->y,
destx, desty);
   
-  if(is_tiles_adjacent(pdiplomat->x, pdiplomat->y, destx, desty) &&
pdiplomat->moves_left >= move_cost) {
-    
-    if(pcity) {  
-      if(pcity->owner!=pdiplomat->owner) {
-       if(action==DIPLOMAT_SABOTAGE)
-         return 1;
-
-        if(action==DIPLOMAT_EMBASSY &&
-          !player_has_embassy(&game.players[pdiplomat->owner], 
-                              &game.players[pcity->owner]))
-          return 1;
-       if(action==SPY_POISON && unit_flag(pdiplomat->type, F_SPY))
-         return 1;
-       if(action==DIPLOMAT_INVESTIGATE)
-         return 1;
-       if(action==DIPLOMAT_STEAL)
-         return 1;
-       if(action==DIPLOMAT_INCITE)
-         return 1;
-      }
-    }
-    else {
-      if(action==SPY_SABOTAGE_UNIT && unit_list_size(&ptile->units)>=1
&&
-        unit_list_get(&ptile->units, 0)->owner!=pdiplomat->owner &&
-        unit_flag(pdiplomat->type, F_SPY))
-       return 1;
-      if(action==DIPLOMAT_BRIBE && unit_list_size(&ptile->units)==1 &&
-        unit_list_get(&ptile->units, 0)->owner!=pdiplomat->owner)
-       return 1;
+  if(pcity) {  
+    if(pcity->owner!=pdiplomat->owner) {
+      if(action==DIPLOMAT_SABOTAGE)
+        return 1;
+
+      if(action==DIPLOMAT_EMBASSY &&
+          !player_has_embassy(&game.players[pdiplomat->owner], 
+                              &game.players[pcity->owner]))
+          return 1;
+      if(action==SPY_POISON && unit_flag(pdiplomat->type, F_SPY))
+        return 1;
+      if(action==DIPLOMAT_INVESTIGATE)
+        return 1;
+      if(action==DIPLOMAT_STEAL)
+        return 1;
+      if(action==DIPLOMAT_INCITE)
+        return 1;
+      if(action==DIPLOMAT_ANY_ACTION)
+        return 1;
     }
+  }
+  else {
+    struct tile *ptile=map_get_tile(destx, desty);
+    if((action==SPY_SABOTAGE_UNIT || action==DIPLOMAT_ANY_ACTION) &&
+        unit_list_size(&ptile->units)>=1 &&
+        unit_list_get(&ptile->units, 0)->owner!=pdiplomat->owner &&
+        unit_flag(pdiplomat->type, F_SPY))
+      return 1;
+    if((action==DIPLOMAT_BRIBE || action==DIPLOMAT_ANY_ACTION) &&
+        unit_list_size(&ptile->units)==1 &&
+        unit_list_get(&ptile->units, 0)->owner!=pdiplomat->owner)
+      return 1;
   }
   return 0;
 }
diff -r -u old/common/unit.h freeciv/common/unit.h
--- old/common/unit.h   Thu Nov  5 06:30:15 1998
+++ freeciv/common/unit.h       Wed Dec  9 21:05:14 1998
@@ -92,7 +92,8 @@
 enum diplomat_actions {
   DIPLOMAT_BRIBE, DIPLOMAT_EMBASSY, DIPLOMAT_SABOTAGE,
   DIPLOMAT_STEAL, DIPLOMAT_INCITE, SPY_POISON, 
-  DIPLOMAT_INVESTIGATE, SPY_SABOTAGE_UNIT
+  DIPLOMAT_INVESTIGATE, SPY_SABOTAGE_UNIT,
+  DIPLOMAT_ANY_ACTION
 };
 
 struct unit_ai {
@@ -198,6 +199,11 @@
 int diplomat_can_do_action(struct unit *pdiplomat,
                           enum diplomat_actions action, 
                           int destx, int desty);
+
+int is_diplomat_action_available(struct unit *pdiplomat,
+                                 enum diplomat_actions action,
+                                 int destx, int desty);
+
 struct unit *find_unit_by_id(int id);
 
 char *get_unit_name(enum unit_type_id id);
diff -r -u old/server/unithand.c freeciv/server/unithand.c
--- old/server/unithand.c       Thu Nov 12 06:38:04 1998
+++ freeciv/server/unithand.c   Thu Dec 10 00:35:42 1998
@@ -187,7 +187,8 @@
   }
   move_cost = tile_move_cost(pdiplomat,pdiplomat->x,pdiplomat->y, x,
y);
   
-  if(pdiplomat && pdiplomat->moves_left >= move_cost) {
+  if(pdiplomat->moves_left >= move_cost ||
+     pdiplomat->moves_left >= unit_move_rate(pdiplomat)) {
 
     switch(packet->action_type) {
     case DIPLOMAT_BRIBE:


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