Complete.Org: Mailing Lists: Archives: freeciv-dev: March 2002:
[Freeciv-Dev] Re: [PATCH] [1.1] cleanup of proccess_*_want() (PR#1295)
Home

[Freeciv-Dev] Re: [PATCH] [1.1] cleanup of proccess_*_want() (PR#1295)

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: Petr Baudis <pasky@xxxxxxxxxxx>, freeciv-dev@xxxxxxxxxxx
Cc: bugs@xxxxxxxxxxxxxxxxxxx
Subject: [Freeciv-Dev] Re: [PATCH] [1.1] cleanup of proccess_*_want() (PR#1295)
From: Raahul Kumar <raahul_da_man@xxxxxxxxx>
Date: Sun, 3 Mar 2002 19:48:54 -0800 (PST)

--- Petr Baudis <pasky@xxxxxxxxxxx> wrote:
> Hello,
<snip>

>   I think it's ready to actually go in, altough I'm open to objections and
> ideas how to extend/correct it even more (I expect many hints for better and
> more comments, and possibly also for better variable names - in fact, all
> those
> one-letter variables have usually same mean in the whole AI - but I didn't
> i.e.
> renamed f to 'loss', but to 'bcost' here, contrary to findvictim()).
>

I'd like a little consistency.
 

>   Oh, I want to ask for a long time already, but now finally I remembered ;).
> It seems to me that unit_vulnerability() (and assess_danger_unit() etc) are
> returning _higher_ values for _less_ vulnerability (as the defense rate is
> taken as a base) - isn't their name a bit confusing then?
>

Yes. Unit_toughness would be better.
 

>   Enjoy your reviewing ;),
>

Reviewing patches is where all the glamour is ;).
 

> Public PGP key && geekcode && homepage: http://pasky.ji.cz/~pasky/
> > Index: ChangeLog



> +/************************************************************************** 
> +What would be the best defender for that city?


> +  bool defended = has_a_normal_defender(pcity);
> +  /* Technologies we would like to have. */
> +  int tech_desire[U_LAST];
> +  /* Our favourite unit. */
> +  int best = 0;
> +  Unit_Type_id best_unit_type = 0; /* FIXME: 0 is legal value! */
> +  /* Iterator. */
> +  Unit_Type_id unit_type;
> +
> +  memset(tech_desire, 0, sizeof(tech_desire));
> +  
> +  for (unit_type = 0; unit_type < game.num_unit_types; unit_type++) {

Replace this with unit_type_iter.

> +    int move_type = unit_types[unit_type].move_type;
> +

Wahoo.    

> +    if (!is_ai_simple_military(unit_type)) continue;
> +    
> +    if (move_type == LAND_MOVING || move_type == SEA_MOVING) {
> +      /* How many technologies away it is? */
> +      int tech_dist = num_unknown_techs_for_goal(pplayer,
> +                        unit_types[unit_type].tech_requirement);
> +      /* How much we want the unit? */
> +      int desire = unit_desirability(unit_type, TRUE);
> +

The range of unit desirability is ? Does negative numbers have any meaning?
      
> +      /* We won't leave the castle empty when driving out to battlefield. */
> +      if (!defended && unit_type_flag(unit_type, F_FIELDUNIT)) desire = 0;
> +      
> +      desire /= 15; /* Good enough, no rounding errors. */
> +      desire *= desire;
> +      
> +      if (can_build_unit(pcity, unit_type)) {
> +        /* We can build the unit now... */
> +        
> +        if (walls && move_type == LAND_MOVING) {
> +          desire *= pcity->ai.wallvalue;
> +          desire /= 10;
> +        }

Huh??? Is this trying to model the fact that one unit defending behind city
walls is better than 2 without?


> +        
> +        if ((desire > best ||
> +             (desire == best && get_unit_type(unit_type)->build_cost <=
> +                                get_unit_type(best_unit_type)->build_cost))
> +            && unit_types[unit_type].build_cost <= pcity->shield_stock + 40)
> {
> +          best = desire;
> +          best_unit_type = unit_type;
>          }
> -      } else if (k > 0 && (shore || m == LAND_MOVING) &&
> -                unit_types[i].tech_requirement != A_LAST) {
> -        if (m == LAND_MOVING) { j *= pcity->ai.wallvalue; j /= 10; }
> -
> -     /* cost (shield equiv) of gaining these techs */
> -     l = total_bulbs_required_for_goal(pplayer,
> -                                       unit_types[i].tech_requirement);
> -     l /= 4;
> -        l /= city_list_size(&pplayer->cities);
> -/* Katvrr advises that with danger high, l should be weighted more heavily
> */
> -        desire[i] = j * danger / (unit_types[i].build_cost + l);
> +        
> +      } else if (tech_dist > 0 && (shore || move_type == LAND_MOVING)
> +                 && unit_types[unit_type].tech_requirement != A_LAST) {
> +        /* We first need to develop a tech required by the unit... */
> +
> +        /* Cost (shield equivalent) of gaining these techs. */
> +        /* FIXME? Katvrr advises that this should be weighted more heavily
> in
> +         * big danger. */
> +        int tech_cost = total_bulbs_required_for_goal(pplayer,
> +                          unit_types[unit_type].tech_requirement) / 4
> +                        / city_list_size(&pplayer->cities);
> +

Beautiful.
        
> +        /* Contrary above, we don't care if walls are actually built - we're
> +         * looking into future now. */
> +        if (move_type == LAND_MOVING) {
> +          desire *= pcity->ai.wallvalue;
> +          desire /= 10;
> +        }
> +
> +        /* Yes, there's some similarity with kill_desire(). */
> +        tech_desire[unit_type] = desire * danger /
> +                                (unit_types[unit_type].build_cost +
> tech_cost);
>        }
>      }
>    }
> -  if (!walls && unit_types[bestid].move_type == LAND_MOVING) {
> +  
> +  /* I was getting four-figure desire for battleships otherwise. -- Syela */
> +  if (!walls && unit_types[best_unit_type].move_type == LAND_MOVING) {
>      best *= pcity->ai.wallvalue;
>      best /= 10;
> -  } /* was getting four-figure desire for battleships otherwise. -- Syela */
> -/* Phalanx would be 16 * danger / 20.  Pikemen would be 36 * danger / (20 +
> l) */
> +  }
>  
> -  if (best == 0) best = 1;   /* avoid divide-by-zero below */
> +  if (best == 0) best = 1; /* Avoid division by zero bellow. */
>  
> -/* multiply by unit_types[bestid].build_cost / best */
> -  for (i = 0; i < game.num_unit_types; i++) {
> -    if (desire[i] && is_ai_simple_military(i)) {
> -      tech_req = unit_types[i].tech_requirement;
> -      n = desire[i] * unit_types[bestid].build_cost / best;
> -      pplayer->ai.tech_want[tech_req] += n;
> +  /* Develop appropriate techs for units we want to build. */
> +  
> +  for (unit_type = 0; unit_type < game.num_unit_types; unit_type++) {
> +    if (tech_desire[unit_type] && is_ai_simple_military(unit_type)) {
> +      Tech_Type_id tech_req = unit_types[unit_type].tech_requirement;
> +      int desire = tech_desire[unit_type]
> +                   * unit_types[best_unit_type].build_cost / best;
> +      
> +      pplayer->ai.tech_want[tech_req] += desire;
> +      
>        freelog(LOG_DEBUG, "%s wants %s for defense with desire %d <%d>",
> -                 pcity->name, advances[tech_req].name, n, desire[i]);
> +              pcity->name, advances[tech_req].name, desire,
> +              tech_desire[unit_type]);
>      }
>    }
> -  choice->choice = bestid;
> +  
> +  choice->choice = best_unit_type;
>    choice->want = danger;
>    choice->type = CT_DEFENDER;
>    return;
>  }
>  
>  /************************************************************************** 
> -n is type of defender, vet is vet status, x,y is location of target
> -I decided this funct wasn't confusing enough, so I made k_s_w send
> -it some more variables for it to meddle with -- Syela
> +This function decides, what unit would be best for erasing enemy. It is
> called,
> +when we just want to kill something, we've found it but we don't have the
> unit
> +for killing that built yet - here we'll choose the type of that unit.
> +
> +I decided this funct wasn't confusing enough, so I made kill_something_with
> +send it some more variables for it to meddle with. -- Syela
> +
> +TODO: Get rid of these parameters :).
> +
> +(x,y) is location of the target.
> +(best_value,best_choice) is pre-filled with our current choice.
>  **************************************************************************/
> -static void process_attacker_want(struct player *pplayer,
> -                         struct city *pcity, int b, Unit_Type_id n,
> -                            bool vet, int x, int y, int unhap, int *e0, int
> *v,
> -                            int bx, int by, int boatspeed, int needferry)
> +
> +static void process_attacker_want(struct player *pplayer, struct city
> *pcity,
> +                                  int value, Unit_Type_id victim_unit_type,
> +                                  bool veteran, int x, int y, int unhap,
> +                                  int *best_value, int *best_choice,
> +                                  int boatx, int boaty, int boatspeed,
> +                                  int needferry)
>  { 
> -  Unit_Type_id i;
> -  Tech_Type_id j;
> -  int a, c, d, e, b0, f, g, fprime;
> -  int k, l, m, q;
> -  bool shore = is_terrain_near_tile(pcity->x, pcity->y, T_OCEAN);
>    struct city *acity = map_get_city(x, y);
> -  int movetype = unit_types[*v].move_type;
> -
> -  for (i = 0; i < game.num_unit_types; i++) {
> -    if (!is_ai_simple_military(i)) continue;
> -    m = unit_types[i].move_type;
> -    j = unit_types[i].tech_requirement;
> -    if (j != A_LAST) k = num_unknown_techs_for_goal(pplayer,j);
> -    else k = 0;
> -    if ((m == LAND_MOVING || (m == SEA_MOVING && shore)) && j != A_LAST &&
> -         (k || !can_build_unit_direct(pcity, unit_types[i].obsoleted_by)) &&
> -         unit_types[i].attack_strength && /* otherwise we get SIGFPE's */
> -         m == movetype) { /* I don't think I want the duplication otherwise
> -- Syela */
> -      bool will_be_veteran = (m == LAND_MOVING
> -                           || player_knows_improvement_tech(pplayer,
> -                                                            B_PORT));
> -
> -      /* cost (shield equiv) of gaining these techs */
> -      l = total_bulbs_required_for_goal(pplayer,
> -                                     unit_types[i].tech_requirement);
> -      l /= 4;
> -
> -      l /= city_list_size(&pplayer->cities);
> -/* Katvrr advises that with danger high, l should be weighted more heavily
> */
> -
> -      a = base_unit_belligerence_primitive(i, will_be_veteran, SINGLE_MOVE,
> -                                        unit_types[i].hp);
> -      if (acity) a += acity->ai.a;
> -      a *= a;
> -      /* b is unchanged */
> -
> -      m = unit_types[i].move_rate;
> -      q = (acity ? 1 : unit_types[n].move_rate * (unit_type_flag(n, F_IGTER)
> ? 3 : 1));
> -      if (unit_type_flag(i, F_IGTER)) m *= SINGLE_MOVE; /* not quite right
> */
> -      if (unit_types[i].move_type == LAND_MOVING) {
> -        if (boatspeed) { /* has to be a city, so don't bother with q */
> -          c = (warmap.cost[bx][by] + m - 1) / m + 1 +
> -                warmap.seacost[x][y] / boatspeed; /* kluge */
> -          if (unit_type_flag(i, F_MARINES)) c -= 1;
> -        } else if (warmap.cost[x][y] <= m) c = 1;
> -        else c = (warmap.cost[x][y] * q + m - 1) / m;
> -      } else if (unit_types[i].move_type == SEA_MOVING) {
> -        if (warmap.seacost[x][y] <= m) c = 1;
> -        else c = (warmap.seacost[x][y] * q + m - 1) / m;
> -      } else if (real_map_distance(pcity->x, pcity->y, x, y) * SINGLE_MOVE
> <= m) c = 1;
> -      else c = real_map_distance(pcity->x, pcity->y, x, y) * SINGLE_MOVE * q
> / m;
> +  bool shore = is_terrain_near_tile(pcity->x, pcity->y, T_OCEAN);
> +  int orig_move_type = unit_types[*best_choice].move_type;
> +  int victim_move_rate = (acity ? 1 : unit_types[victim_unit_type].move_rate
> *
> +                          (unit_type_flag(victim_unit_type, F_IGTER) ? 3 :
> 1));
> +  int victim_count = (acity ? unit_list_size(&(map_get_tile(x, y)->units)) +
> 1
> +                            : 1);
> +  Unit_Type_id unit_type;
> +
> +  for (unit_type = 0; unit_type < game.num_unit_types; unit_type++) {
> +    Tech_Type_id tech_req = unit_types[unit_type].tech_requirement;
> +    int move_type = unit_types[unit_type].move_type;
> +    int tech_dist;
> +    
> +    if (!is_ai_simple_military(unit_type)) continue;
> +    
> +    if (tech_req != A_LAST) {
> +      tech_dist = num_unknown_techs_for_goal(pplayer, tech_req);
> +    } else {
> +      tech_dist = 0;
> +    }
> +    
> +    if ((move_type == LAND_MOVING || (move_type == SEA_MOVING && shore))
> +        && tech_req != A_LAST
> +        && (tech_dist > 0 ||
> +            !can_build_unit_direct(pcity,
> unit_types[unit_type].obsoleted_by))
> +        && unit_types[unit_type].attack_strength /* or we'll get SIGFPE */
> +        && move_type == orig_move_type) {
> +      bool will_be_veteran = (move_type == LAND_MOVING ||
> +                              player_knows_improvement_tech(pplayer,
> B_PORT));

If you're going to check that, why not check B_AIRPORT as well?

> +      /* Cost (shield equivalent) of gaining these techs. */
> +      /* FIXME? Katvrr advises that this should be weighted more heavily in
> big
> +       * danger. */
> +      int tech_cost = total_bulbs_required_for_goal(pplayer,
> +                        unit_types[unit_type].tech_requirement) / 4
> +                      / city_list_size(&pplayer->cities);
> +      int move_rate = unit_types[unit_type].move_rate;
> +      int move_cost;
> +      int bcost_balanced = build_cost_balanced(unit_type);
> +      /* See description of kill_desire() about this variables. */
> +      int bcost = unit_types[unit_type].build_cost;
> +      int vuln;
> +      int attack = base_unit_belligerence_primitive(unit_type,
> will_be_veteran,
> +                     SINGLE_MOVE, unit_types[unit_type].hp);
> +      /* Computed values.. */
> +      int desire, want;
> +      
> +      if (acity) attack += acity->ai.attack;
> +      
> +      attack *= attack;
> +
> +      if (unit_type_flag(unit_type, F_IGTER)) {
> +        /* Not quite right... */
> +        move_rate *= SINGLE_MOVE;

Bad Petr. Create your own define, IGTER_MOVE_COST.

> +      }
>  
> -      m = get_virtual_defense_power(i, n, x, y);

You're removing those lines. Explanation why they are not needed?

> -      m *= unit_types[n].hp * unit_types[n].firepower;
> -      if (vet) m *= 1.5;
> -      m /= 30;
> -      m *= m;
> -      d = m;
> +      /* Set the move_cost appropriatelly. */
> +      
> +      if (unit_types[unit_type].move_type == LAND_MOVING) {
> +        if (boatspeed) {
> +          /* It's either city or too far away, so don't bother with
> +           * victim_move_rate. */
> +          move_cost = (warmap.cost[boatx][boaty] + move_rate - 1) /
> move_rate
> +                      + 1 + warmap.seacost[x][y] / boatspeed; /* kludge */
> +          if (unit_type_flag(unit_type, F_MARINES)) move_cost -= 1;
> +          
> +        } else if (warmap.cost[x][y] <= move_rate) {
> +          /* It's adjacent. */
> +          move_cost = 1;
> +
> +        } else {
> +          move_cost = (warmap.cost[x][y] * victim_move_rate + move_rate - 1)
> +                      / move_rate;
> +        }
> +        
> +      } else if (unit_types[unit_type].move_type == SEA_MOVING) {
> +        if (warmap.seacost[x][y] <= move_rate) {
> +          /* It's adjectent. */
> +          move_cost = 1;
> +          
> +        } else {
> +          move_cost = (warmap.seacost[x][y] * victim_move_rate + move_rate -
> 1)
> +                      / move_rate;
> +        }
> +        
> +      } else if (real_map_distance(pcity->x, pcity->y, x, y) * SINGLE_MOVE
> <=
> +                 move_rate) {
> +        /* It's adjectent. */
> +        move_cost = 1;
>  
> -      if (unit_types[i].move_type == LAND_MOVING && acity &&
> -          c > (player_knows_improvement_tech(city_owner(acity),
> -                                          B_CITY) ? 2 : 4) &&
> -          !unit_type_flag(i, F_IGWALL) && !city_got_citywalls(acity)) d *=
> 9; 
> +      } else {
> +        move_cost = real_map_distance(pcity->x, pcity->y, x, y) *
> SINGLE_MOVE
> +                    * victim_move_rate / move_rate;
> +      }
>  
> -      f = unit_types[i].build_cost;
> -      fprime = build_cost_balanced(i);
> +      /* Appreciate resistance of the enemy. */
> +      /* It's like assess_defense_unit(), but get_virtual_defense_power()
> +       * instead of get_defense_power(). */
> +      
> +      vuln = get_virtual_defense_power(unit_type, victim_unit_type, x, y);
> +      vuln *= unit_types[victim_unit_type].hp *
> +              unit_types[victim_unit_type].firepower;
> +      if (veteran) vuln *= 1.5;
> +      vuln /= 30;
> +      vuln *= vuln;
> +
> +      if (unit_types[unit_type].move_type == LAND_MOVING && acity
> +          && move_cost > (player_knows_improvement_tech(city_owner(acity),
> +                                                        B_CITY) ? 2 : 4)
> +          && !unit_type_flag(unit_type, F_IGWALL)
> +          && !city_got_citywalls(acity)) {
> +        /* FIXME: Use acity->ai.wallvalue? --pasky */
> +        vuln *= 9;

I wish I knew why used 9 instead of 3. I can only assume this is due to those
goddamn scaling factors, and this probably explains why we divide results by
30.

> +      }
>  
> -      if (acity) g = unit_list_size(&(map_get_tile(acity->x,
> acity->y)->units)) + 1;
> -      else g = 1;
> -      if (unit_types[i].move_type != LAND_MOVING && !d) b0 = 0;
> -/* not bothering to s/!d/!pdef here for the time being -- Syela */
> -      else if ((unit_types[i].move_type == LAND_MOVING ||
> -              unit_types[i].move_type == HELI_MOVING) && acity &&
> -              acity->ai.invasion == 2) b0 = f * SHIELD_WEIGHTING;
> -      else {
> -     if (!acity) {
> -       b0 = kill_desire(b, a, f, d, g);
> -     } else {
> -       int a_squared = acity->ai.a * acity->ai.a;
> -
> -       b0 = kill_desire(b, a, f + acity->ai.f, d, g);
> -       if (b * a_squared > acity->ai.f * d) {
> -         b0 -= kill_desire(b, a_squared, acity->ai.f, d, g);
> -       }
> -     }
> +      /* Not bothering to s/!vuln/!pdef here for the time being. -- Syela
> +       * (this is noted elsewhere as terrible bug making warships yoyoing)
> */
> +      if (unit_types[unit_type].move_type != LAND_MOVING && !vuln) {
> +        desire = 0;
> +        
> +      } else if ((unit_types[unit_type].move_type == LAND_MOVING ||
> +                  unit_types[unit_type].move_type == HELI_MOVING)
> +                 && acity && acity->ai.invasion == 2) {
> +        desire = bcost * SHIELD_WEIGHTING;
> +        
> +      } else {
> +        if (!acity) {
> +          desire = kill_desire(value, attack, bcost, vuln, victim_count);
> +          
> +        } else {
> +          int city_attack = acity->ai.attack * acity->ai.attack;
> +
> +          /* See aiunit.move_cost:find_something_to_kill() for comments. */
> +          
> +          desire = kill_desire(value, attack, (bcost + acity->ai.bcost),
> vuln,
> +                               victim_count);
> +          
> +          if (value * city_attack > acity->ai.bcost * vuln) {
> +            desire -= kill_desire(value, city_attack, acity->ai.bcost, vuln,
> +                                  victim_count);
> +          }
> +        }

> +                                     : SHIELD_WEIGHTING);



> -  pcity->ai.a = val2;
> -  pcity->ai.f = val3;
> +  pcity->ai.attack = val2;
> +  pcity->ai.bcost = val3;

Crap names.


> +        pcity->ai.attack += a;
> +        pcity->ai.bcost += unit_type(aunit)->build_cost;
>        }
<snip>
> +            int a_squared = acity->ai.attack * acity->ai.attack;
Good.




__________________________________________________
Do You Yahoo!?
Yahoo! Sports - sign up for Fantasy Baseball
http://sports.yahoo.com


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