Index: server/unitfunc.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unitfunc.c,v
retrieving revision 1.91
diff -u -r1.91 unitfunc.c
--- unitfunc.c	1999/03/13 11:42:09	1.91
+++ unitfunc.c	1999/03/19 04:03:09
@@ -317,27 +317,92 @@
   diplomat_leave_city(pplayer, pdiplomat, pcity);
 }
 
+/**************************************************************************
+compute_subversion_strength
+
+Computes the `power' of a spy or diplomat.  Spies are 50% more sneakier
+than diplomats, veteran spies are twice as sneaky.  Diplomats can be
+verterans after defeating an attacking diplomat or by being communist.
+Spies can become veterans for those reasons plus surviving a mission.
+
+Virgin Diplomat  10
+Veteran Diplomat 15
+Virgin Spy       15
+Veteran Spy      20
+                                                  - Kris Bubendorfer
+
+**************************************************************************/
+
+int compute_subversion_strength(struct unit *pdiplomat){
+  int odds = 10;
+
+  /* Spies are sneakier */
+
+  odds += (!(!unit_flag(pdiplomat->type, F_SPY))) * 5;
+  
+  /* Spies can be veteran, but so can communist Diplomats*/
+  
+  odds += (pdiplomat->veteran * 5);
+  
+  return odds;
+}
+
+/**************************************************************************
+spy_versus_spy
 
+Appologies to Mad Magazine :) Computes the outcome of a spy attacking a spy.
+This is loosely based on unit_versus_unit, but fixes some variables.  By 
+using the loop and reducing the hp of both the attacking and defending 
+spies, we more realistically model Bond vs Goldfinger - that is, both get
+tired :)
+                                - Kris Bubendorfer
+**************************************************************************/
+
+void spy_versus_spy(struct unit *attacker, struct unit *defender)
+{
+  int attackstrength=compute_subversion_strength(attacker);
+  int defensestrength=compute_subversion_strength(defender);
+
+  freelog(LOG_DEBUG, "%s attack:%d, %s defense:%d", unit_name(attacker->type),
+	  attackstrength, unit_name(defender->type), defensestrength);
+  
+  while (attacker->hp>0 && defender->hp>0) 
+    if (myrand(attackstrength+defensestrength)>= defensestrength) 
+      defender->hp -= 1;
+    else
+      attacker->hp -= 1;
+
+  if (attacker->hp)
+    maybe_make_veteran(attacker); 
+  else if (defender->hp)
+    maybe_make_veteran(defender);
+}
+
 /**************************************************************************
 diplomat_infiltrate_city
 
 This code determines if a subverting diplomat/spy succeeds in infiltrating
-the city, that is - if there are defending diplomats/spies they have a 
-n-1/n chance of defeating the infiltrator.
+the city, that is - if there are defending diplomats/spies they have a chance 
+of defeating the infiltrator.  Diplchance now only applies to the 
 **************************************************************************/
 
 int diplomat_infiltrate_city(struct player *pplayer, struct player *cplayer,
 			     struct unit *pdiplomat, struct city *pcity)
 {
-  /* For EVERY diplomat/spy on a square, there is a 1/N chance of succeeding.
-   * This needs to be changed to take into account veteran status.
+  /* 
+   * EVERY diplomat/spy on a city gets to defend against the attacking
+   * Diplomat or Spy.
    */
+
   unit_list_iterate(map_get_tile(pcity->x, pcity->y)->units, punit)
-    if (unit_flag(punit->type, F_DIPLOMAT)) {
-      if (myrand(game.diplchance)) {
-	
-	/* Attacking Spy/Diplomat dies (N-1:N) */
-	
+    if (unit_flag(punit->type, F_DIPLOMAT) || unit_flag(punit->type, F_SPY)) {
+      /* Fight it out */       
+      spy_versus_spy(pdiplomat, punit);
+
+      if (!pdiplomat->hp) {	
+
+	/* Attacking Spy/Diplomat dies */
+
 	notify_player_ex(pplayer, pcity->x, pcity->y, E_MY_DIPLOMAT,
 			 "Game: Your %s was eliminated"
 			 " by a defending %s in %s.", 
@@ -351,11 +416,12 @@
 			 get_race_name(pplayer->race),
 			 unit_name(pdiplomat->type),
 			 pcity->name);
+	send_unit_info(0,punit,0);
 	wipe_unit(0, pdiplomat);
 	return 0;
       } else {
 	
-	/* Defending Spy/Diplomat dies (1:N) */
+	/* Defending Spy/Diplomat dies */
 	
 	notify_player_ex(cplayer, pcity->x, pcity->y, E_DIPLOMATED,
 			 "Game: Your %s has been eliminated defending"
@@ -363,6 +429,7 @@
 			 unit_name(punit->type),
 			 unit_name(pdiplomat->type),
 			 pcity->name);
+	send_unit_info(0,pdiplomat,0);
 	wipe_unit(0, punit);
       }
     }
@@ -374,7 +441,9 @@
 diplomat_leave_city
 
 This code determines if a subverting diplomat/spy survives infiltrating a 
-city.  A diplomats always dies, a spy has a 1/game.diplchance
+city.  A diplomats always dies, a spy has a 1/game.diplchance - this 
+reflects the chance of the spy being captured by the civil authorities
+after commiting the offence.
 **************************************************************************/
 
 void diplomat_leave_city(struct player *pplayer, struct unit *pdiplomat,
@@ -891,13 +960,15 @@
 /**************************************************************************
   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)
+  there is a 50/50% chance for it to happend, (100% if player got SUNTZU
+  unless the unit is a spy/diplomat)
 **************************************************************************/
 void maybe_make_veteran(struct unit *punit)
 {
     if (punit->veteran) 
       return;
-    if(player_owns_active_wonder(get_player(punit->owner), B_SUNTZU)) 
+    if(player_owns_active_wonder(get_player(punit->owner), B_SUNTZU) 
+       && !(unit_flag(punit->type,F_DIPLOMAT)||unit_flag(punit->type,F_SPY))) 
       punit->veteran = 1;
     else
       punit->veteran=myrand(2);