[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: checking in



On Thursday, 21 Sep 2000, Galen Johnson <gjohnson@totalsports.net> said:

>  If we can get the new AI a little more user friendly (I haven't
>won a single battle since I installed Mike and Rob's patch) I'd like to
>include that as well since it does seem to play better. 

I had a closer look at the way skill is managed, and I discovered that it's even messier than I thought. The #defines for FIELD_SKILL_HARD etc were unused, and so were many fields in computer_data. I have changed these all around to work with the new AI. Some fields are still unused and there is room for improvement, e.g. skill_level may need to be revisited for cell-style movement.)

skill_level, as defined in FIELD_SKILL_HARD etc, is the average number of frames for the computer to skip. I probably should have written better comments. Anyway, here's how it works: Each frame, FIELD_SKILL is applied to a simplified random number test that decides whether to skip this frame. If the computer skips a frame, that means it does the same thing it did last frame instead of recalculating its action.

Despite repeated (but brief) attempts, I haven't been able to get SSH working so I can use the CVS archive. Instead, I've included a patch below.

Galen, try the patch out and change the value for FIELD_SKILL_EASY until you think it's the right difficulty. Change the other values as you see fit.

- Mike

--- xarchon-mike.rob/src/computer.c	Thu Aug 24 15:34:45 2000
+++ xarchon-working/src/computer.c	Wed Oct  4 14:42:57 2000
@@ -23,14 +23,20 @@
 
 #define DATA(x)         (computer_data[configs[computer_side]->data_num].x)
 #define FIELD_SKILL     DATA(skill_level)
-#define SHOOT_DISTANCE  DATA(shoot_distance)
-#define ACTOR_DISTANCE  DATA(actor_distance)
+#define TIME_TOLERANCE  DATA(time_tolerance)
+#define DIST_TOLERANCE  DATA(dist_tolerance)
 #define ACTOR_RECHARGE  DATA(actor_recharge)
 #define NUM_GOOD_MOVES  DATA(num_good_moves)
 
-#define FIELD_SKILL_HARD        0
-#define FIELD_SKILL_MEDIUM      10
-#define FIELD_SKILL_EASY        20
+/* these field_skill values are the number of frames to skip between actions */
+#define FIELD_SKILL_HARD        4
+#define FIELD_SKILL_MEDIUM      9
+#define FIELD_SKILL_EASY        13
+
+/* dist_tolerance is the range between max and min distances from enemy */
+#define DIST_TOLERANCE_EASY     CELL_XSIZE * 3
+#define DIST_TOLERANCE_MEDIUM   CELL_XSIZE * 2
+#define DIST_TOLERANCE_HARD     CELL_XSIZE
 
 /*--------------------------------------------------------------------------*/
 /* enums                                                                    */
@@ -66,11 +72,10 @@
 
 typedef struct {
    /* field */
-   int skill_level;                     /* how easy should the computer be */
-   /* the following three are unused in computer.c. Get rid of them? - mhc */
-   int shoot_distance;                  /* escape missiles this close */
-   int actor_distance;                  /* escape actors this close, who */
-   int actor_recharge;                  /*   are at this recharge level */
+   int skill_level;                     /* how many frames to skip on field */
+   int time_tolerance;                  /* (unused) when to dodge missile */
+   int dist_tolerance;                  /* range between min & max dist */
+   int actor_recharge;                  /* (unused) min enemy recharge level */
    /* board */
    int num_good_moves;                  /* good moves to consider (max 32) */
 } COMPUTER_DATA;
@@ -162,9 +167,9 @@
 };
 
 static COMPUTER_DATA computer_data[3] = {
-   { 45, 2, 7, FPS * 0.5, 6 },
-   { 9, 2, 7, FPS * 0.5, 4 },
-   { 4, 5, 5, FPS * 0.3, 1 }
+   { FIELD_SKILL_EASY, 2, DIST_TOLERANCE_EASY, FPS * 0.5, 6 },
+   { FIELD_SKILL_MEDIUM, 2, DIST_TOLERANCE_MEDIUM, FPS * 0.5, 4 },
+   { FIELD_SKILL_HARD, 5, DIST_TOLERANCE_HARD, FPS * 0.3, 1 }
 };
    
 static DAMAGE computer_damage[ACTOR_NUM_LIGHT + 1][ACTOR_NUM_DARK + 1];
@@ -630,41 +635,45 @@
 void computer_field_compute_stats(FIELD_STATS *stats, FIELD_ACTOR *fa,
       FIELD_ACTOR *enemy)
 {
-  int safe_distance, max_unsafe_distance, min_unsafe_distance;
+  int safe_distance, max_safe_distance;
+  int max_unsafe_distance, min_unsafe_distance;
 
-   /* compute the minimum distance fa can be and still dodge a dead-on */
-   /* shot from enemy */
+  /* compute the minimum distance fa can be and still dodge a dead-on */
+  /* shot from enemy */
   if ((enemy->weapon->actor->type & ACTOR_WEAPON_HAND) == ACTOR_WEAPON_HAND) {
-      safe_distance = 3*CELL_XSIZE/2 + enemy->actor->speed;
-      max_unsafe_distance = safe_distance;
+    safe_distance = 3*CELL_XSIZE/2 + enemy->actor->speed;
+    max_unsafe_distance = safe_distance;
+    min_unsafe_distance = CELL_XSIZE/2;
+  }
+  else if ((enemy->weapon->actor->type & ACTOR_WEAPON_CLOUD) ==
+	   ACTOR_WEAPON_CLOUD) {
+    if ((enemy->weapon->actor->type & ACTOR_FREEZE_USER) == 
+	ACTOR_FREEZE_USER) {
+      safe_distance = 7*CELL_XSIZE/2 + enemy->actor->speed;
+      max_unsafe_distance = 3*CELL_XSIZE/2;
+      min_unsafe_distance = 0;
+    }
+    else {
+      safe_distance = 7*CELL_XSIZE/2 + 2*enemy->actor->speed;
+      max_unsafe_distance = 3*CELL_XSIZE/2;
       min_unsafe_distance = CELL_XSIZE/2;
+    }
+  } else {
+    safe_distance = enemy->weapon->actor->speed *
+      (1 + 2*CELL_XSIZE / (3*fa->actor->speed)) + CELL_XSIZE;
+    max_unsafe_distance = safe_distance;
+    min_unsafe_distance = safe_distance - DIST_TOLERANCE;
   }
-   else if ((enemy->weapon->actor->type & ACTOR_WEAPON_CLOUD) ==
-         ACTOR_WEAPON_CLOUD) {
-     if ((enemy->weapon->actor->type & ACTOR_FREEZE_USER) == 
-	 ACTOR_FREEZE_USER) {
-       safe_distance = 7*CELL_XSIZE/2 + enemy->actor->speed;
-       max_unsafe_distance = 3*CELL_XSIZE/2;
-       min_unsafe_distance = 0;
-     }
-     else {
-       safe_distance = 7*CELL_XSIZE/2 + 2*enemy->actor->speed;
-       max_unsafe_distance = 3*CELL_XSIZE/2;
-       min_unsafe_distance = CELL_XSIZE/2;
-     }
-   } else {
-      safe_distance = enemy->weapon->actor->speed*(1 + 2*CELL_XSIZE/
-            (3*fa->actor->speed)) + CELL_XSIZE;
-      max_unsafe_distance = safe_distance;
-      min_unsafe_distance = safe_distance - CELL_XSIZE;
-   }
-   /* store the squares of the distances */
-   stats->min_safe_dist_2 = safe_distance*safe_distance;
-   stats->max_safe_dist_2 = (safe_distance+CELL_XSIZE)*(safe_distance+CELL_XSIZE);
-   stats->max_unsafe_dist_2 = max_unsafe_distance*max_unsafe_distance;
-   stats->min_unsafe_dist_2 = min_unsafe_distance*min_unsafe_distance;
-   stats->dodge_dir = 0;
-   stats->last_dir = 0;
+
+  max_safe_distance = safe_distance + DIST_TOLERANCE;
+
+  /* store the squares of the distances */
+  stats->min_safe_dist_2 = safe_distance*safe_distance;
+  stats->max_safe_dist_2 = max_safe_distance*max_safe_distance;
+  stats->max_unsafe_dist_2 = max_unsafe_distance*max_unsafe_distance;
+  stats->min_unsafe_dist_2 = min_unsafe_distance*min_unsafe_distance;
+  stats->dodge_dir = 0;
+  stats->last_dir = 0;
 }
 
 /*--------------------------------------------------------------------------*/
@@ -687,7 +696,7 @@
       their_stats = &light_stats;
    }
 
-   if (field_frame_time % (random() % (FIELD_SKILL / 5 +1) + 5) != 0) {
+   if (random() % (FIELD_SKILL + 1) != 0) {
      cmd->f.dir = my_stats->last_dir;
      cmd->f.fire = 0;
      return;