Complete.Org: Mailing Lists: Archives: freeciv-ai: December 2002:
[freeciv-ai] Re: (PR#2477) Improved Auto-Explore
Home

[freeciv-ai] Re: (PR#2477) Improved Auto-Explore

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: cameron@xxxxxxxxxx
Cc: freeciv-ai@xxxxxxxxxxx
Subject: [freeciv-ai] Re: (PR#2477) Improved Auto-Explore
From: "Raimar Falke via RT" <rt@xxxxxxxxxxxxxx>
Date: Tue, 3 Dec 2002 06:44:16 -0800
Reply-to: rt@xxxxxxxxxxxxxx

On Tue, Dec 03, 2002 at 05:19:38AM -0800, Guest via RT wrote:
> 
> [rfalke - Tue Dec  3 07:35:06 2002]:
> 
> > Please remove some unneeded ().
> 
> OK, I think I removed them all. I like to put in "unneeded ()" because I
> once programmed a DSP with a programming language that was almost
> indistinguishable from C; the only difference was '||' bound more
> closely than '&&'. Since then I've been a bit free with the brackets.
> Here I left some in to prevent a warning from gcc.

Mhh I wasn't thinking about the () around && and || but about the x<0
term.

> > Can't 0x80 and co be replaced with an enum?
> 
> Probably. I want it to return a "fuzzy" value, so code that uses it
> could make decisions based on how certain they are that the value is
> ocean. I'm not sure how to do this using enum. How about
> 
> #define OCEAN_CERTAIN_IS  0x80
> #define OCEAN_UNKNOWN     0x40
> #define OCEAN_CERTAIN_NOT 0x00
> 
> ? I you think that's a good idea I'll add it in the next revision.

> Index: ai/aiunit.c
> ===================================================================
> RCS file: /home/freeciv/CVS/freeciv/ai/aiunit.c,v
> retrieving revision 1.231
> diff -u -3 -p -r1.231 aiunit.c
> --- ai/aiunit.c       2002/12/02 22:48:13     1.231
> +++ ai/aiunit.c       2002/12/03 13:14:32
> @@ -256,6 +256,71 @@ static bool tile_is_accessible(struct un
>  }
>   
>  /**************************************************************************
> +  Determine if a tile is likely to be water, given information that
> +  the player actually has. Return the certainty that it's water
> +  (0x80 = certain, 0x40 = no idea, 0 = certainly not).
> +**************************************************************************/
> +int likely_ocean(int x, int y, struct player *pplayer)
> +{
> +  int sum = 0;
> +
> +  if(map_get_known(x,y,pplayer)) {
> +    /* we've seen the tile already. */
> +    if(map_get_terrain(x,y) == T_OCEAN) {
> +      return 0x80;
> +    } else {
> +      return 0;
> +    }
> +  }
> +  
> +  /* without the bounds checks we get segfaults */
> +  if((x - 1 >= 0 && map_get_known(x - 1, y, pplayer) && 
> +      map_get_terrain(x - 1, y) == T_OCEAN) ||
> +     (x + 1 < map.xsize && map_get_known(x + 1, y, pplayer) && 
> +      map_get_terrain(x + 1, y) == T_OCEAN) ||
> +     (y - 1 >= 0 && map_get_known(x, y - 1, pplayer) && 
> +      map_get_terrain(x, y - 1) == T_OCEAN) ||
> +     (y + 1 < map.ysize && map_get_known(x, y + 1, pplayer) && 
> +      map_get_terrain(x, y + 1) == T_OCEAN)) {
> +    /* we can tell by the border if there's land there. */

Please use adjc_iterate and DIR_IS_CARDINAL.

> +    if(map_get_terrain(x,y) == T_OCEAN) {
> +      return 0x80;
> +    } else {
> +      return 0;
> +    }
> +  }

It looks like you referring in this construct here to the kludge we
use in the client to draw correctly the ocean squares.

> +  sum = 0x40;
> +  /* average the adjacent 8 tiles */

> +  square_iterate(x, y, 1, x1, y1) {
> +    if(y1 < 0 || y1 > map.ysize) {
> +      continue;
> +    }

Please use adjc_iterate.

> +    if(map_get_known(x1,y1, pplayer)) {
> +      /* this nearby tile is water */
> +      
> +      if(x != x1 && y != y1) {
> +        /* diagonals count for less. */
> +        if(map_get_terrain(x1,y1) == T_OCEAN) {
> +          sum += 2;
> +        } else {
> +          sum -= 2;
> +        }
> +      }
> +      else {
> +        if(map_get_terrain(x1,y1) == T_OCEAN) {
> +          sum += 4;
> +        } else {
> +          sum -= 4; 
> +        }
> +      }
> +    }
> +  } square_iterate_end;

How did you calibrated these values? 64 + 4*4+4*2 = 88 and 64 -
(4*4+4*2) = 40. Shouldn't these values be nearer 0 and 128?

Can you scale them to 100 and call them percent?

> +  return sum;
> +}
> +
> +/**************************************************************************
>  Handle eXplore mode of a unit (explorers are always in eXplore mode for AI) -
>  explores unknown territory, finds huts.
>  
> @@ -369,21 +434,67 @@ bool ai_manage_explorer(struct unit *pun
>    while (punit->moves_left > 0) {
>      /* Best (highest) number of unknown tiles adjacent (in vision range) */
>      int most_unknown = 0;
> +
> +    /* most desirable tile, given adjacent water */
> +    int most_desirable = 0;

> +    /* relative value of exploring ocean and land */
> +    int landscore = 5;
> +    int oceanscore = 60;
> +
> +    /* relative value of staying near known ocean and land */
> +    int klandscore = 2;
> +    int koceanscore = 25;

What is k?

> +    if(is_sailing_unit(punit)) {
> +      /* for sailing explorer, reverse desirable tiles */
> +      int temp;
> +      
> +      temp = landscore;
> +      landscore = oceanscore;
> +      oceanscore = temp;
> +      
> +      temp = klandscore;
> +      klandscore = koceanscore;
> +      koceanscore = temp;
> +    }

Please make a set of values and then assign in if
(sailing){...}else{...} the final values. This temp usage is just
ugly.

>      square_iterate(x, y, 1, x1, y1) {
>        /* Number of unknown tiles in vision range around this tile */
>        int unknown = 0;
>        
> +      int desirable = 0;
> +      int ocean = 0;
> +
>        square_iterate(x1, y1, range, x2, y2) {
> -        if (!map_get_known(x2, y2, pplayer))
> -          unknown++;
> +     ocean = likely_ocean(x2,y2, pplayer);
> +        if (!map_get_known(x2, y2, pplayer)) {
> +       unknown++;
> +       /* if it's a tile we don't know, weight the value of
> +        * exploring it by if it's likely to be ocean or not. 
> +        */
> +       if(ocean > 0x40) {
> +         desirable += oceanscore;
> +       } else if(ocean < 0x40) {
> +         desirable += landscore;
> +       }
> +     } else {
> +       if(ocean > 0x40) {
> +         desirable += koceanscore;
> +       } else if(ocean < 0x40) {
> +         desirable += klandscore;
> +       }
> +     }
>        } square_iterate_end;
>  
> -      if (unknown > most_unknown) {
> +      /* regardless how desirable a tile is, if we don't discover
> +       * any new territory, don't go there. */

> +      if (unknown && (desirable > most_desirable)) {

unknon > 0

>          if (unit_flag(punit, F_TRIREME)
>              && trireme_loss_pct(pplayer, x1, y1) != 0)
>            continue;
> @@ -405,7 +516,10 @@ bool ai_manage_explorer(struct unit *pun
>          if (is_barbarian(pplayer) && map_has_special(x1, y1, S_HUT))
>            continue;
>            
> -        most_unknown = unknown;
> +     if(unknown > most_unknown) {
> +       most_unknown = unknown;
> +     }
> +     most_desirable = desirable;
>          best_x = x1;
>          best_y = y1;
>        }

I take my request for enums back. The code however should be changed
that likely_ocean is more a ocean_probability with a result range of
0<=x<=100.

        Raimar

-- 
 email: rf13@xxxxxxxxxxxxxxxxx
  "The primary purpose of the DATA statement is to give names to
   constants; instead of referring to pi as 3.141592653589793 at every
   appearance, the variable PI can be given that value with a DATA
   statement and used instead of the longer form of the constant. This
   also simplifies modifying the program, should the value of pi
   change."
    -- FORTRAN manual for Xerox Computers



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