Complete.Org: Mailing Lists: Archives: freeciv-dev: April 2002:
[Freeciv-Dev] Re: patch rfc: stop ai from building useless wall, sam, co
Home

[Freeciv-Dev] Re: patch rfc: stop ai from building useless wall, sam, co

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: freeciv-dev@xxxxxxxxxxx
Cc: bugs@xxxxxxxxxxxxxxxxxxx
Subject: [Freeciv-Dev] Re: patch rfc: stop ai from building useless wall, sam, costal and sdi (PR#199)
From: Petr Baudis <pasky@xxxxxxxxxxx>
Date: Fri, 5 Apr 2002 08:34:28 -0800 (PST)

Dear diary, on Thu, Apr 04, 2002 at 03:47:54AM CEST, I got a letter,
where "Per I. Mathisen" <Per.Inge.Mathisen@xxxxxxxxxxx> told me, that...
> It makes the AI make some crude calculations about whether it needs city
> walls, SAM, coastal fortress and SDI defences before building them. The
> calculations are documented in the source, so I won't go into them here.
> Unlike Peter's code, mine caches everything and uses a minimal extra CPU
> per city.

I think I like it ;).

> Index: common/player.h
> ===================================================================
> RCS file: /home/freeciv/CVS/freeciv/common/player.h,v
> retrieving revision 1.75
> diff -u -r1.75 player.h
> --- common/player.h   2002/03/05 19:13:44     1.75
> +++ common/player.h   2002/04/04 01:42:14
> @@ -115,6 +115,11 @@
>  
>  struct player_ai {
>    bool control;
> +  bool eval_wall_gate; /* check if we need walls to stop invasions */
> +  bool *eval_wall; /* do we need to build city walls yet? */
> +  bool eval_coastal; /* do we need to build coastal defences yet? */
> +  int eval_sdi; /* need to build SDI defences? 0=no, 1=maybe, 2=yes! */
> +  bool eval_sam; /* do we need to build SAMs yet? */
>    int tech_goal;
>    int prev_gold;
>    int maxbuycost;

I vote for special structure for storing these values. I plan to create it for
assess_danger() & family anyway...

> Index: ai/advdomestic.c
> ===================================================================
> RCS file: /home/freeciv/CVS/freeciv/ai/advdomestic.c,v
> retrieving revision 1.83
> diff -u -r1.83 advdomestic.c
> --- ai/advdomestic.c  2002/03/18 01:49:36     1.83
> +++ ai/advdomestic.c  2002/04/04 01:42:14
> @@ -31,8 +32,166 @@
>  
>  #include "advdomestic.h"
>  
> +/**************************************************************************
> +  Make and cache lots of calculations needed for other functions, notably:
> +  ai_eval_walls, ai_eval_sdi, ai_eval_coastal and ai_eval_sam.
> +
> +  FIXME 1: We need to write this so that it will work for generalised
> +  improvements somehow. Need to think about this. - Per
> +
> +  FIXME 2: We should check if many of the enemies units on a continent
> +  have the F_IGWALL ability, and drop want for city walls if that is the 
> +  case. - Per
> +**************************************************************************/
> +static void ai_eval_init(struct player *pplayer) {
> +  int i, nuke_units = num_role_units(F_NUCLEAR);
> +  bool got_nukes = FALSE;
> +
> +  pplayer->ai.eval_wall = fc_calloc(map.num_continents, sizeof(got_nukes));

I think sizeof(bool) is better. What if got_nukes type ever changes?

> +  pplayer->ai.eval_wall_gate = FALSE;
> +  pplayer->ai.eval_sam = FALSE;
> +  pplayer->ai.eval_sdi = FALSE;
> +  pplayer->ai.eval_coastal = FALSE;
> +
> +  players_iterate(aplayer) {
> +    if (pplayers_allied(pplayer, aplayer)) {
> +      /* Just allies, we don't trust peace treaties _that_ much */
> +      continue;
> +    }
> +
> +    city_list_iterate(aplayer->cities, acity) {
> +      /* The idea is that if there aren't any hostile cities on
> +         our continent, the danger of land attacks is not big
> +         enough to warrant city walls. Concentrate instead on 
> +         coastal fortresses and hunting down enemy transports. */
> +      pplayer->ai.eval_wall[map_get_continent(acity->x, acity->y)] = TRUE;
> +    } city_list_iterate_end;
> +
> +    unit_list_iterate(aplayer->units, punit) {
> +      /* If the enemy has not started sailing yet, or we have total
> +         control over the seas, don't worry, keep attacking. */
> +      if (is_sailing_unit(punit)) {
> +        pplayer->ai.eval_wall_gate = TRUE;
> +      }

Blank line please.

> +      /* The idea is that while our enemies don't have any offensive
> +         seaborne units, we don't have to worry. Go on the offensive! */
> +      if (unit_type(punit)->attack_strength > 1 && is_sailing_unit(punit)) {
> +        pplayer->ai.eval_coastal = TRUE;
> +      }

Blank line please.

> +      /* The next idea is that if our enemies don't have any offensive
> +         airborne units, we don't have to worry. Go on the offensive! */
> +      if (unit_type(punit)->attack_strength > 0 && (is_air_unit(punit)
> +                                                    ||is_heli_unit(punit))) {
+      if (unit_type(punit)->attack_strength > 0 && (is_air_unit(punit) ||
+                                                    is_heli_unit(punit))) {
> +        pplayer->ai.eval_sam = TRUE;
> +      }

Blank line please.

> +      if (unit_flag(punit, F_NUCLEAR)) { got_nukes = TRUE; }
> +      if (pplayer->ai.eval_sam && pplayer->ai.eval_coastal && got_nukes) { 
> +        break;
> +      }

Eh? :) I don't get mean of the last if, sorry :).

> +    } unit_list_iterate_end;
> +
> +    /* Check for nuke capability */
> +    for (i = 0; i < nuke_units; i++) {
> +      Unit_Type_id nuke = get_role_unit(F_NUCLEAR, i);

Blank line please.

> +      if (can_player_build_unit_direct(aplayer, nuke)) { 
> +        pplayer->ai.eval_sdi = 1;
> +      }
> +    }
> +  } players_iterate_end;

Blank line please.

> +  if (got_nukes) { pplayer->ai.eval_sdi++; } /* increase fear */
> +}
> +
> +/**************************************************************************
> +  Clean up our mess.
> +**************************************************************************/
> +static void ai_eval_done(struct player *pplayer) {
> +  free(pplayer->ai.eval_wall);
> +}
>  
>  /**************************************************************************
> +  Calculates need for city walls. Looks for potentially hostile cities
> +  on our continent. We quite intentionally don't rely on the great wall,
> +  since we suddenly might find our cities helpless in the field without
> +  city walls. We want city walls also in cities in the shorelines to
> +  stop invasions, but only if a non-allied player has started using sea
> +  units yet. If they are slow to go on the offensive, we should expand or
> +  attack.
> +
> +  FIXME: We should have a concept of "oceans" just like we do for
> +  continents. Too many times I've seen the AI build destroyers and 
> +  coastal defences in inlands cities with a small pond adjacent. - Per
> +**************************************************************************/
> +static int ai_eval_walls(struct player *pplayer, struct city *pcity)
> +{
> +  bool vulnerable = (is_water_adjacent_to_tile(pcity->x, pcity->y) 
> +                     && pplayer->ai.eval_wall_gate)
> +          || pplayer->ai.eval_wall[map_get_continent(pcity->x, pcity->y)];
> +
> +  /* make easy AI dumb */
> +  if (ai_handicap(pplayer, H_DEFENSIVE)) {
> +    return 40;
> +  }
> +
> +  /* 40 is a magic number inherited from Syela */

I think it would be nice to have global #defines for those widely used magic
numbers (just a long-term goal; does NOT apply to your +20 ;).

> +  return vulnerable ? 40 : 1;
> +}
> +
> +/**************************************************************************
> +  Calculates need for costal defence.
> +**************************************************************************/
> +static int ai_eval_coastal(struct player *pplayer, struct city *pcity)
> +{
> +  /* make easy AI stay dumb */
> +  if (ai_handicap(pplayer, H_DEFENSIVE)) {
> +    return 40;
> +  }
> +
> +  /* 40 is a magic number inherited from Syela */
> +  return pplayer->ai.eval_coastal ? 40 : 1;
> +}
> +
> +/**************************************************************************
> +  Calculates need for air defence.
> +**************************************************************************/
> +static int ai_eval_sam(struct player *pplayer, struct city *pcity)
> +{
> +  /* make easy AI dumber */
> +  if (ai_handicap(pplayer, H_DEFENSIVE)) {
> +    return 50;
> +  }
> +
> +  /* 50 is a magic number inherited from Syela */
> +  return pplayer->ai.eval_sam ? 50 : 0;
> +}
> +
> +/**************************************************************************
> +  Calculates need for SDI defence. Looks for players capable of building
> +  nuclear weapons. Capable of building, not has, because at this stage in
> +  the game we can get nukes and use nukes faster than we can manage to
> +  build SDIs. We also look if players _have_ nukes, and increase our
> +  want for SDIs correspondingly. Lastly, we check if we are in a strategic
> +  position (ie near water or on a continent with non-allied cities).
> +**************************************************************************/
> +static int ai_eval_sdi(struct player *pplayer, struct city *pcity)
> +{
> +  int vulnerable = 1;
> +
> +  /* make easy AI really dumb, like it was before */
> +  if (ai_handicap(pplayer, H_DEFENSIVE)) {
> +    return 50;
> +  }
> +
> +  vulnerable += is_water_adjacent_to_tile(pcity->x, pcity->y) ||
> +                pplayer->ai.eval_wall[map_get_continent(pcity->x, pcity->y)];
> +
> +  /* 20 is just a new magic number, which will be +20 if we are
> +     in a vulnerable spot, and +20 if someone we are not allied
> +     with really have built nukes. This might be overkill, but
> +     at least it is not as bad as it used to be. */
> +  return ((pplayer->ai.eval_sdi + vulnerable) * 20);
> +}
> +
> +/**************************************************************************
>  Get value of best usable tile on city map.
>  **************************************************************************/
>  static int ai_best_tile_value(struct city *pcity)

I like the patch. It makes sense ;). Also, nicely commented and formatted!

-- 
 
                                Petr "Pasky" Baudis
 
* ELinks maintainer                * IPv6 guy (XS26 co-coordinator)
* IRCnet operator                  * FreeCiv AI hacker
.
Teamwork is essential -- it allows you to blame someone else.
.
Public PGP key && geekcode && homepage: http://pasky.ji.cz/~pasky/



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