Complete.Org: Mailing Lists: Archives: freeciv-ai: August 2004:
[freeciv-ai] (PR#9887) AI defense code
Home

[freeciv-ai] (PR#9887) AI defense code

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: per@xxxxxxxxxxx
Subject: [freeciv-ai] (PR#9887) AI defense code
From: "Gregory Berkolaiko" <Gregory.Berkolaiko@xxxxxxxxxxxxx>
Date: Tue, 31 Aug 2004 21:59:06 -0700
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=9887 >

> Will you be the good doctor? If not, bandaid it is. For now.

First of all, the present kill_desire turned out to be relatively adequate.

The current behaviour was caused by a spectacular bug:  kill_desire
would return a large negative value meaning "really don't want to do
this", this value would get passed into main rampage loop where it would
now mean "really want to do this (large absolute value) but will have to
move to accomplish the action (the negative sign)".

A simple fix is of course to correctly interpret negative kill_desire.

But I played around with savegames and found a situation where
kill_desire is negative but the real (i.e. taking exact win_chance into
account) average is slightly positive.  The situation is a musketeer in
the city, a fortified Warriors on a mountain adjacent.

The savegame is attached (it's a hacked Pers game).

So I decided to use the real win_chance, the result is attached.

BTW, in avg_benefit I cast double into int because round doesn't want to
work for me:
aiunit.c:507: warning: implicit declaration of function `round'

G.

Attachment: adj.sav.gz
Description: GNU Zip compressed data

Index: ai/aiunit.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aiunit.c,v
retrieving revision 1.332
diff -u -r1.332 aiunit.c
--- ai/aiunit.c 31 Aug 2004 18:21:09 -0000      1.332
+++ ai/aiunit.c 1 Sep 2004 04:50:57 -0000
@@ -502,6 +502,23 @@
 }
 
 /**************************************************************************
+  Compute how much we want to kill certain victim we've chosen, counted in
+  SHIELDs.  See comment to kill_desire.
+
+  chance -- the probability the action will succeed, 
+  benefit -- the benefit (in shields) that we are getting in the case of 
+             success
+  loss -- the loss (in shields) that we suffer in the case of failure
+
+  Essentially returns the probabilistic average win amount:
+      benefit * chance - loss * (1 - chance)
+**************************************************************************/
+static int avg_benefit(int benefit, int loss, double chance)
+{
+  return (int)(((benefit + loss) * chance - loss) * SHIELD_WEIGHTING);
+}
+
+/**************************************************************************
   Calculates the value and cost of nearby allied units to see if we can
   expect any help in our attack. Base function.
 **************************************************************************/
@@ -592,17 +609,8 @@
     {
       /* See description of kill_desire() about these variables. */
       int attack = unit_att_rating_now(punit);
-      int vuln = unit_def_rating_sq(punit, pdef);
       int benefit = stack_cost(pdef);
       int loss = unit_build_shield_cost(punit->type);
-      double chance = unit_win_chance(punit, pdef);
-
-      if (chance < 0.005) {
-        /* Forget it! At least a tiny chance is needed here... */
-        UNIT_LOG(LOG_DEBUG, punit, "Rampage: No chance against %s(%d,%d)!",
-                 unit_name(pdef->type), pdef->x, pdef->y);
-        return 0;
-      }
 
       attack *= attack;
       
@@ -618,8 +626,14 @@
       
       /* If we have non-zero attack rating... */
       if (attack > 0 && is_my_turn(punit, pdef)) {
+       double chance = unit_win_chance(punit, pdef);
+       int desire = avg_benefit(benefit, loss, chance);
+
         /* No need to amortize, our operation takes one turn. */
-        return kill_desire(benefit, attack, loss, vuln, 1);
+       UNIT_LOG(LOG_NORMAL, punit, "Rampage: Desire %d to kill %s(%d,%d)",
+                desire, unit_name(pdef->type), pdef->x, pdef->y);
+
+        return MAX(0, desire);
       }
     }
     

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