[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]
--- "Per I. Mathisen" <Per.Inge.Mathisen@xxxxxxxxxxx> wrote:
> ===================================================================
> 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
> @@ -45,7 +45,7 @@
> H_TECH=4, /* doesn't know what enemies have researched */
> H_CITYBUILDINGS=8, /* doesn't know what buildings are in enemy cities */
> H_CITYUNITS=16, /* doesn't know what units are in enemy cities */
> - H_STACKS=32, /* doesn't know what units are in stacks */
> + H_DEFENSIVE=32, /* builds lots of defensive buildings without calculating
> need */
There are lots of other kludges elsewhere in the code that raise the priority
of building walls. This patch has not touched them all.
> H_VETERAN=64, /* doesn't know veteran status of enemy units */
> H_SUB=128, /* doesn't know where subs may be lurking */
Since when was H_SUB added? Does it work?
> 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! */
Maybe is strange. What action is taken when it returns 1?
> + bool eval_sam; /* do we need to build SAMs yet? */
> int tech_goal;
> int prev_gold;
> int maxbuycost;
> 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
> @@ -19,6 +19,7 @@
> #include "log.h"
> #include "map.h"
> #include "unit.h"
> +#include "mem.h"
>
> #include "citytools.h"
> #include "settlers.h"
> @@ -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
> +**************************************************************************/
Wrong check. Test if enemy units on continent are good attack units vs unwalled
defenders. If an enemy landed a force composed of 50% tanks 50% howitzers, it
is still legit to build walls.
> +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));
> + 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;
> + }
Do not agree. When you introduce active diplomacy, AI can break alliances.
> + 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;
Sea barbarians. All coastal cities should always have city walls, because they
are at the highest risk of being attacked.
> + 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;
> + }
Love it ;-).
> + /* 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;
> + }
> + /* 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 they have only 5 airborne units, I never bother building SAMs. If the enemy
does have large number(>5) air units, do build sams.
> + pplayer->ai.eval_sam = TRUE;
> + }
> + if (unit_flag(punit, F_NUCLEAR)) { got_nukes = TRUE; }
> + if (pplayer->ai.eval_sam && pplayer->ai.eval_coastal && got_nukes) {
> + break;
> + }
> + } 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);
> + if (can_player_build_unit_direct(aplayer, nuke)) {
> + pplayer->ai.eval_sdi = 1;
> + }
> + }
> + } players_iterate_end;
> + if (got_nukes) { pplayer->ai.eval_sdi++; } /* increase fear */
> +}
> +
I like every part of this except the bits dealing with city wall code.
Everything else looks good, and will help stop the incredible stupidity of the
AI building code.
> +/**************************************************************************
> + 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 */
> + 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;
> +}
> +
Any theories on the 50?
> +/**************************************************************************
> + 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);
> +}
> +
I would replace 20 with a better name. I hate new magic numbers. We still
haven't got rid of the old ones.
> +/**************************************************************************
> Get value of best usable tile on city map.
> **************************************************************************/
> static int ai_best_tile_value(struct city *pcity)
> @@ -277,7 +436,8 @@
> struct player *pplayer = city_owner(pcity);
> int needpower;
> int wwtv = worst_worker_tile_value(pcity);
> -
> +
> + ai_eval_init(pplayer);
> t = pcity->ai.trade_want; /* trade_weighting */
> sci = (pcity->trade_prod * pplayer->economic.science + 50) / 100;
> tax = pcity->trade_prod - sci;
> @@ -374,14 +534,13 @@
> /* and it would have no chance to finish them before it was too late */
>
> if (could_build_improvement(pcity, B_CITY))
> -/* && !built_elsewhere(pcity, B_WALL)) was counterproductive -- Syela
> */
> - values[B_CITY] = 40; /* WAG */
> + values[B_CITY] = ai_eval_walls(pplayer, pcity);
>
> if (could_build_improvement(pcity, B_COASTAL))
> - values[B_COASTAL] = 40; /* WAG */
> + values[B_COASTAL] = ai_eval_coastal(pplayer, pcity);
>
> if (could_build_improvement(pcity, B_SAM))
> - values[B_SAM] = 50; /* WAG */
> + values[B_SAM] = ai_eval_sam(pplayer, pcity);
>
> if (could_build_improvement(pcity, B_COLOSSEUM))
> values[B_COLOSSEUM] = impr_happy_val(get_colosseum_power(pcity), pcity,
> val);
> @@ -439,7 +598,7 @@
> values[B_RESEARCH] = sci/2;
>
> if (could_build_improvement(pcity, B_SDI))
> - values[B_SDI] = 50; /* WAG */
> + values[B_SDI] = ai_eval_sdi(pplayer, pcity);
>
> /* see comments above on B_AQUADUCT (wrt. granary size). --Jing */
> if (could_build_improvement(pcity, B_SEWER)) {
> @@ -630,6 +789,7 @@
> /* handle H_PROD here? -- Syela */
> pcity->ai.building_want[id] = values[id] / j;
> } impr_type_iterate_end;
> + ai_eval_done(pplayer);
> }
>
> /**********************************************************************
> Index: server/stdinhand.c
> ===================================================================
> RCS file: /home/freeciv/CVS/freeciv/server/stdinhand.c,v
> retrieving revision 1.218
> diff -u -r1.218 stdinhand.c
> --- server/stdinhand.c 2002/03/21 05:17:26 1.218
> +++ server/stdinhand.c 2002/04/04 01:42:15
> @@ -1535,7 +1535,7 @@
> int h[11] = { -1,
> H_NONE,
> H_NONE,
> - H_RATES | H_TARGETS | H_HUTS,
> + H_RATES | H_TARGETS | H_HUTS | H_DEFENSIVE,
> H_NONE,
> H_RATES | H_TARGETS | H_HUTS,
> H_NONE,
>
The patch looks ok. I'll have to playtest it to see if there is an improvement.
Is there any way of running two servers, one running unpatched CVS, one with
your patch, so I can see which AI comes on top?
__________________________________________________
Do You Yahoo!?
Yahoo! Tax Center - online filing with TurboTax
http://taxes.yahoo.com/
|
|