(PR#12129) AI & Tech Exchange

"Mateusz Stefek" <mstefek-IjDXvh/[email protected]> Sat, 5 Feb 2005 08:15:53 -0800
Newsgroups gmane.games.freeciv.ai
Message-ID <[email protected]>
<URL: http://bugs.freeciv.org/Ticket/Display.html?id=12129 >

AI is so easy to beat, because it never exchanges techs.
This is serious problem. 2 player alliance human+AI will easily win with
5 allied AI.

The attached patch makes AI exchange techs with it's allies.
It is done in different way than it used to be done before.
AI won't give you techs for free, it will ask for an exchange (and
offer/ask for some money to make the deal fair)

The fastest way to see how it works is to start a game with high
techlevel and other AIs near.
--
mateusz
tech_exchange2.diff (application/octet-stream, 5.6 KB)
--- freeciv/ai/advdiplomacy.c	2004-11-22 16:02:04.000000000 +0100
+++ changed/ai/advdiplomacy.c	2005-01-23 12:40:42.000000000 +0100
@@ -173,6 +173,49 @@
 }
 
 /********************************************************************** 
+  Calculate a price of a tech.
+  Note that both AI players always evaluate the tech worth symetrically
+  This eases tech exchange.
+**********************************************************************/
+static int ai_gives_away_tech(struct player* giver, struct player* taker,
+				int tech_id)
+{
+    int worth;
+    
+    worth = ai_goldequiv_tech(taker, tech_id);
+    
+    /* Share and expect being shared brotherly between allies */
+    if (pplayers_allied(giver, taker)) {
+      worth /= 2;
+    }
+    if (players_on_same_team(giver, taker)) {
+      return 0;
+    }
+
+    /* Do not bother wanting a tech that we already have. */
+    if (get_invention(taker, tech_id) == TECH_KNOWN) {
+      return 0;
+    }
+
+    /* Calculate in tech leak to our opponents, guess 50% chance */
+    players_iterate(eplayer) {
+      if (eplayer == giver
+          || eplayer == taker
+          || !eplayer->is_alive
+          || get_invention(eplayer, tech_id) == TECH_KNOWN) {
+        continue;
+      }
+
+      if (pplayers_allied(taker, eplayer) &&
+          !pplayers_allied(giver, eplayer)) {
+        /* We can enrichen our side with this tech */
+        worth += ai_goldequiv_tech(eplayer, tech_id) / 4;
+      }
+    } players_iterate_end;
+    return worth;
+}
+
+/********************************************************************** 
   Evaluate gold worth of a single clause in a treaty. Note that it
   sometimes matter a great deal who is giving what to whom, and
   sometimes (such as with treaties) it does not matter at all.
@@ -196,46 +239,13 @@
 
   switch (pclause->type) {
   case CLAUSE_ADVANCE:
+    
     if (give) {
-      worth -= ai_goldequiv_tech(aplayer, pclause->value);
+      worth -= ai_gives_away_tech(pplayer, aplayer, pclause->value);
     } else if (get_invention(pplayer, pclause->value) != TECH_KNOWN) {
-      worth += ai_goldequiv_tech(pplayer, pclause->value);
+      worth += ai_gives_away_tech(aplayer, pplayer, pclause->value);
     }
 
-    /* Share and expect being shared brotherly between allies */
-    if (pplayers_allied(pplayer, aplayer)) {
-      worth /= 2;
-    }
-    if (players_on_same_team(pplayer, aplayer)) {
-      worth = 0;
-      break;
-    }
-
-    /* Do not bother wanting a tech that we already have. */
-    if (!give && get_invention(pplayer, pclause->value) == TECH_KNOWN) {
-      break;
-    }
-
-    /* Calculate in tech leak to our opponents, guess 50% chance */
-    players_iterate(eplayer) {
-      if (eplayer == aplayer
-          || eplayer == pplayer
-          || !eplayer->is_alive
-          || get_invention(eplayer, pclause->value) == TECH_KNOWN) {
-        continue;
-      }
-      if (give && pplayers_allied(aplayer, eplayer)) {
-        if (is_player_dangerous(pplayer, eplayer)) {
-          /* Don't risk it falling into enemy hands */
-          worth = -BIG_NUMBER;
-          break;
-        }
-        worth -= ai_goldequiv_tech(eplayer, pclause->value) / 2;
-      } else if (!give && pplayers_allied(pplayer, eplayer)) {
-        /* We can enrichen our side with this tech */
-        worth += ai_goldequiv_tech(eplayer, pclause->value) / 4;
-      }
-    } players_iterate_end;
   break;
 
   case CLAUSE_TEAM:
@@ -881,7 +891,60 @@
     } players_iterate_end;
   }
 }
-
+/********************************************************************** 
+  Find two techs that can be exchanged and suggest that
+***********************************************************************/
+static void suggest_tech_exchange(struct player* player1,
+                                  struct player* player2)
+{
+  int worth[game.num_tech_types];
+    
+  tech_type_iterate(tech) {
+    if (tech == A_NONE) {
+      worth[tech] = 0;
+      continue;
+    }
+    if (get_invention(player1, tech) == TECH_KNOWN) {
+      if (get_invention(player2, tech) != TECH_KNOWN) {
+        worth[tech] = -ai_gives_away_tech(player1, player2, tech);
+      } else {
+        worth[tech] = 0;
+      }
+    } else {
+      if (get_invention(player2, tech) == TECH_KNOWN) {
+        worth[tech] = ai_gives_away_tech(player2, player1, tech);
+      } else {
+        worth[tech] = 0;
+      }
+    }
+  } tech_type_iterate_end;
+    
+    
+  tech_type_iterate(tech) {
+    if (worth[tech] <= 0) {
+      continue;
+    }
+    tech_type_iterate(tech2) {
+      if (worth[tech2] >= 0) {
+        continue;
+      }
+      /* tech2 is given by player1, tech is given by player2 */
+      int diff = worth[tech] + worth[tech2];
+      if ((diff > 0 && player1->economic.gold >= diff)
+          || (diff < 0 && player2->economic.gold >= -diff)
+	  || diff == 0) {
+        ai_diplomacy_suggest(player1, player2, CLAUSE_ADVANCE, tech2);
+	ai_diplomacy_suggest(player2, player1, CLAUSE_ADVANCE, tech);
+	if (diff > 0) {
+	  ai_diplomacy_suggest(player1, player2, CLAUSE_GOLD, diff);
+	} else if (diff < 0) {
+	  ai_diplomacy_suggest(player2, player1, CLAUSE_GOLD, -diff);
+	}
+	return;
+      }
+    } tech_type_iterate_end;
+  } tech_type_iterate_end;
+}
 /********************************************************************** 
   Offer techs and stuff to other player and ask for techs we need.
 ***********************************************************************/
@@ -915,6 +978,7 @@
   if (!player_has_embassy(aplayer, pplayer)) {
     ai_diplomacy_suggest(pplayer, aplayer, CLAUSE_EMBASSY, 0);
   }
+  suggest_tech_exchange(pplayer, aplayer);
 }
 
 /**********************************************************************