--- freeciv/ai/aiunit.c Fri Nov 23 18:46:32 2001 +++ freeciv/ai/aiunit.c2 Fri Nov 23 18:43:40 2001 @@ -62,6 +62,8 @@ /************************************************************************** + For curious - ZOC is Zone Of Control + Similar to is_my_zoc(), but with some changes: - destination (x0,y0) need not be adjacent? - don't care about some directions? @@ -76,15 +78,15 @@ if (same_pos(x0, y0, myunit->x, myunit->y)) return 0; /* can't be my zoc */ - if (is_tiles_adjacent(x0, y0, myunit->x, myunit->y) - && !is_non_allied_unit_tile(map_get_tile(x0, y0), - unit_owner(myunit))) + + if (is_tiles_adjacent(x0, y0, myunit->x, myunit->y) && + !is_non_allied_unit_tile(map_get_tile(x0, y0), unit_owner(myunit))) return 0; adjc_iterate(x0, y0, ax, ay) { - if (map_get_terrain(ax, ay) != T_OCEAN - && is_non_allied_unit_tile(map_get_tile(ax, ay), - unit_owner(myunit))) return 0; + if (map_get_terrain(ax, ay) != T_OCEAN && + is_non_allied_unit_tile(map_get_tile(ax, ay), unit_owner(myunit))) + return 0; } adjc_iterate_end; return 1; @@ -101,17 +103,16 @@ { enum unit_move_result result; - result = - test_unit_move_to_tile(punit->type, unit_owner(punit), - punit->activity, punit->connecting, - punit->x, punit->y, dest_x, dest_y, 0); + result = test_unit_move_to_tile(punit->type, unit_owner(punit), + punit->activity, punit->connecting, + punit->x, punit->y, dest_x, dest_y, 0); if (result == MR_OK) return 1; - if (result == MR_ZOC) { + if (result == MR_ZOC) if (could_be_my_zoc(punit, src_x, src_y)) return -1; - } + return 0; } @@ -138,50 +139,46 @@ all other units it can only produce an estimation. Things like railroad, roads will make the actual move cost lower than the given estimation. Mountains, swamps will increase actual move cost. - ***********************************************************************/ - - static int unit_move_turns(struct unit *punit, int x, int y) - { - int result, move_rate = unit_type(punit)->move_rate; +***********************************************************************/ +static int unit_move_turns(struct unit *punit, int x, int y) +{ + int result, move_rate = unit_type(punit)->move_rate; - switch (unit_type(punit)->move_type) { - case LAND_MOVING: - if (unit_flag(punit, F_IGTER)) { - move_rate *= SINGLE_MOVE; - } - result = warmap.cost[x][y] / move_rate; - break; - - case SEA_MOVING: - if (player_owns_active_wonder(unit_owner(punit), B_LIGHTHOUSE)) { - move_rate += SINGLE_MOVE; - } - if (player_owns_active_wonder(unit_owner(punit), B_MAGELLAN)) { - move_rate += (improvement_variant(B_MAGELLAN) == 1) ? - SINGLE_MOVE : 2 * SINGLE_MOVE; - } - if (player_knows_techs_with_flag(unit_owner(punit), TF_BOAT_FAST)) { - move_rate += SINGLE_MOVE; - } - result = warmap.seacost[x][y] / move_rate; - break; - - case HELI_MOVING: - case AIR_MOVING: - result = real_map_distance(punit->x, punit->y, x,y) * SINGLE_MOVE / move_rate; - break; - - default: - assert(0); - exit(1); - result = -1; - } - return result; - } + switch (unit_type(punit)->move_type) { + case LAND_MOVING: + if (unit_flag(punit, F_IGTER)) { + move_rate *= SINGLE_MOVE; + } + result = warmap.cost[x][y] / move_rate; + break; - + case SEA_MOVING: + if (player_owns_active_wonder(unit_owner(punit), B_LIGHTHOUSE)) { + move_rate += SINGLE_MOVE; + } + if (player_owns_active_wonder(unit_owner(punit), B_MAGELLAN)) { + move_rate += (improvement_variant(B_MAGELLAN) == 1) ? + SINGLE_MOVE : 2 * SINGLE_MOVE; + } + if (player_knows_techs_with_flag(unit_owner(punit), TF_BOAT_FAST)) { + move_rate += SINGLE_MOVE; + } + result = warmap.seacost[x][y] / move_rate; + break; + case HELI_MOVING: + case AIR_MOVING: + result = real_map_distance(punit->x, punit->y, x,y) * SINGLE_MOVE / move_rate; + break; + + default: + assert(0); + exit(1); + result = -1; + } + return result; +} /************************************************************************** is there any hope of reaching this tile without violating ZOC? @@ -627,32 +624,39 @@ int *dest_x, int *dest_y) { int x, y; - int best = 0, a, b, c, d, e, f; + int best = 0, belligerence; struct unit *pdef; struct unit *patt; struct city *pcity; + x = punit->x; y = punit->y; *dest_y = y; *dest_x = x; if (punit->unhappiness) best = 0 - 2 * MORT * TRADE_WEIGHTING; /* desperation */ - f = unit_type(punit)->build_cost; - c = 0; /* only dealing with adjacent victims here */ + + belligerence = unit_belligerence_primitive(punit); + /* ferryboats do not attack. no. -- Syela */ if (get_transporter_capacity(punit)) { unit_list_iterate(map_get_tile(x, y)->units, aunit) - if (!is_sailing_unit(aunit)) return(0); + if (!is_sailing_unit(aunit)) + return(0); unit_list_iterate_end; - } /* ferryboats do not attack. no. -- Syela */ + } adjc_iterate(x, y, x1, y1) { pdef = get_defender(punit, x1, y1); if (pdef) { + + /* horsemen in city refused to attack phalanx just outside that was + bodyguarding catapult - patt will resolve this bug nicely -- Syela */ patt = get_attacker(punit, x1, y1); -/* horsemen in city refused to attack phalanx just outside that was -bodyguarding catapult - patt will resolve this bug nicely -- Syela */ + if (can_unit_attack_tile(punit, x1, y1)) { /* thanks, Roar */ - d = unit_vulnerability(punit, pdef); + int vuln; + vuln = unit_vulnerability(punit, pdef); + if (map_get_city(x, y) && /* pikemen defend Knights, attack Catapults */ get_total_defense_power(pdef, punit) * get_total_defense_power(punit, pdef) >= /* didn't like > -- Syela */ @@ -664,51 +668,63 @@ unit_type(punit)->name, map_get_city(x, y)->name, unit_owner(pdef)->name, unit_type(pdef)->name); + } else { - a = reinforcements_value(punit, pdef->x, pdef->y); - a += unit_belligerence_primitive(punit); - a *= a; - b = unit_type(pdef)->build_cost; + int agress, bonus, coef; + + agress = reinforcements_value(punit, pdef->x, pdef->y); + agress += belligerence; + agress *= agress; + + bonus = unit_type(pdef)->build_cost; if (map_get_city(x1, y1)) /* bonus restored 980804 -- Syela */ - b = (b + 40) * punit->hp / unit_type(punit)->hp; -/* c is always equal to zero in this routine, and f is already known */ -/* arguable that I should use reinforcement_cost here?? -- Syela */ - if (a && is_my_turn(punit, pdef)) { - e = ((b * a - f * d) * SHIELD_WEIGHTING / (a + d) - c * SHIELD_WEIGHTING); -/* no need to amortize! */ - if (e > best && ai_fuzzy(pplayer,1)) { + bonus = (bonus + 40) * punit->hp / unit_type(punit)->hp; + + /* arguable that I should use reinforcement_cost here?? -- Syela */ + if (agress && is_my_turn(punit, pdef)) { + coef = ((bonus * agress - unit_type(punit)->build_cost * vuln) * SHIELD_WEIGHTING / + (agress + vuln) * SHIELD_WEIGHTING); + + /* no need to amortize! */ + if (coef > best && ai_fuzzy(pplayer, 1)) { freelog(LOG_DEBUG, "Better than %d is %d (%s)", - best, e, unit_type(pdef)->name); - best = e; *dest_y = y1; *dest_x = x1; + best, coef, unit_type(pdef)->name); + best = coef; *dest_y = y1; *dest_x = x1; } else { freelog(LOG_DEBUG, "NOT better than %d is %d (%s)", - best, e, unit_type(pdef)->name); + best, coef, unit_type(pdef)->name); } } /* end if we have non-zero belligerence */ } } + } else { /* no pdef */ pcity = map_get_city(x1, y1); + if (pcity && is_ground_unit(punit) && - map_get_terrain(punit->x, punit->y) != T_OCEAN) { - if (pcity->owner != pplayer->player_no) { /* free goodies */ - best = 99999; *dest_y = y1; *dest_x = x1; - } + map_get_terrain(punit->x, punit->y) != T_OCEAN && + pcity->owner != pplayer->player_no) { /* free goodies */ + best = 99999; *dest_y = y1; *dest_x = x1; } - if (map_get_tile(x1, y1)->special & S_HUT && best < 99999 && + + if (map_get_tile(x1, y1)->special & S_HUT && + best < 99999 && could_unit_move_to_tile(punit, punit->x, punit->y, x1, y1) && !is_barbarian(unit_owner(punit)) && -/* zoc_ok_move(punit, x1, y1) && !is_sailing_unit(punit) &&*/ +/* zoc_ok_move(punit, x1, y1) && + !is_sailing_unit(punit) && */ punit->ai.ai_role != AIUNIT_ESCORT && /* makes life easier */ !punit->ai.charge && /* above line seems not to work. :( */ punit->ai.ai_role != AIUNIT_DEFEND_HOME) { /* Oops! -- Syela */ best = 99998; *dest_y = y1; *dest_x = x1; } - if( is_land_barbarian(pplayer) && best == 0 && + + /* next to nothing is better than nothing */ + if (is_land_barbarian(pplayer) && best == 0 && get_tile_infrastructure_set(map_get_tile(x1, y1)) && - could_unit_move_to_tile(punit, punit->x, punit->y, x1, y1) ) { + could_unit_move_to_tile(punit, punit->x, punit->y, x1, y1)) { best = 1; *dest_y = y1; *dest_x = x1; - } /* next to nothing is better than nothing */ + } } } adjc_iterate_end; --- freeciv/ai/advmilitary.c Fri Nov 23 18:46:32 2001 +++ freeciv/ai/advmilitary.c2 Fri Nov 23 18:50:15 2001 @@ -159,7 +159,7 @@ **************************************************************************/ static int assess_danger_unit(struct city *pcity, struct unit *punit) { - int v, sailing; + int danger, sailing; struct unit_type *ptype; if (unit_flag(punit, F_NO_LAND_ATTACK)) return(0); @@ -168,12 +168,12 @@ ptype = unit_type(punit); /* get_attack_power will be wrong if moves_left == 1 || == 2 */ - v = ptype->attack_strength * 10 * punit->hp * ptype->firepower; - if (punit->veteran) v += v/2; - if (sailing && city_got_building(pcity, B_COASTAL)) v /= 2; - if (is_air_unit(punit) && city_got_building(pcity, B_SAM)) v /= 2; - v /= 30; /* rescaling factor to stop the overflow nonsense */ - return(v); + danger = ptype->attack_strength * 10 * punit->hp * ptype->firepower; + if (punit->veteran) danger += danger/2; + if (sailing && city_got_building(pcity, B_COASTAL)) danger /= 2; + if (is_air_unit(punit) && city_got_building(pcity, B_SAM)) danger /= 2; + danger /= 30; /* rescaling factor to stop the overflow nonsense */ + return(danger); } /************************************************************************** @@ -228,7 +228,7 @@ ***********************************************************************/ int assess_danger(struct city *pcity) { - int i, danger = 0, v, dist, m; + int i, danger = 0; Unit_Type_id utype; int danger2 = 0; /* linear for walls */ int danger3 = 0; /* linear for coastal */ @@ -237,7 +237,7 @@ struct player *aplayer, *pplayer; int pikemen = 0; int diplomat = 0; /* > 0 mean that this town can defend - * against diplomats or spies */ + against diplomats or spies */ int urgency = 0; int igwall; int badmojo = 0; @@ -260,20 +260,22 @@ if (unit_flag(punit, F_DIPLOMAT)) diplomat++; unit_list_iterate_end; - for(i=0; iowner) { aplayer = &game.players[i]; - boatspeed = (get_invention(aplayer, game.rtech.nav) - == TECH_KNOWN ? 4*SINGLE_MOVE : 2*SINGLE_MOVE); + + boatspeed = (get_invention(aplayer, game.rtech.nav) == TECH_KNOWN ? + 4*SINGLE_MOVE : 2*SINGLE_MOVE); boatid = find_boat(aplayer, &x, &y, 0); if (boatid) boatdist = warmap.seacost[x][y]; else boatdist = -1; + /* should I treat empty enemy cities as danger? */ /* After much contemplation, I've decided the answer is sometimes -- Syela */ city_list_iterate(aplayer->cities, acity) if (acity->is_building_unit && build_points_left(acity) <= acity->shield_surplus && - ai_fuzzy(pplayer,1)) { + ai_fuzzy(pplayer, 1)) { virtualunit.owner = i; virtualunit.x = acity->x; virtualunit.y = acity->y; @@ -281,16 +283,23 @@ virtualunit.type = utype; virtualunit.veteran = do_make_unit_veteran(acity, utype); virtualunit.hp = unit_types[utype].hp; + /* yes, I know cloning all this code is bad form. I don't really want to write a funct that takes nine ints by reference. -- Syela */ - m = unit_type(funit)->move_rate; - v = assess_danger_unit(pcity, funit); - dist = assess_distance(pcity, funit, m, boatid, boatdist, boatspeed); - igwall = unit_really_ignores_citywalls(funit); - if ((is_ground_unit(funit) && v) || - (is_ground_units_transport(funit))) { - if (dist <= m * 3) urgency++; - if (dist <= m) pcity->ai.grave_danger++; +/* TODO maybe make some little struct for dangers and then move this +to the separate function at last --pasky */ + { + int move, udanger, dist; + + move = unit_type(funit)->move_rate; + udanger = assess_danger_unit(pcity, funit); + dist = assess_distance(pcity, funit, move, boatid, boatdist, boatspeed); + igwall = unit_really_ignores_citywalls(funit); + + if ((is_ground_unit(funit) && udanger) || + (is_ground_units_transport(funit))) { + if (dist <= move * 3) urgency++; + if (dist <= move) pcity->ai.grave_danger++; /* NOTE: This should actually implement grave_danger, which is supposed to be a feedback-sensitive formula for immediate danger. I'm having second thoughts about the best implementation, and therefore this @@ -298,41 +307,50 @@ not totally sure about and can't thoroughly test in the hours before the release. The AI is in fact vulnerable to gang-attacks, but I'm content to let it remain that way for now. -- Syela 980805 */ - } + } - if (unit_flag(funit, F_HORSE)) { - if (pikemen) v /= 2; - else ai_wants_role_unit(pplayer, pcity, F_PIKEMEN, - (v * m / (dist*2))); - } - - if (unit_flag(funit, F_DIPLOMAT) && (dist <= 2 * m)) - pcity->ai.diplomat_threat = !diplomat; - - v *= v; - - if (!igwall) danger2 += v * m / dist; - else if (is_sailing_unit(funit)) danger3 += v * m / dist; - else if (is_air_unit(funit) && !unit_flag(funit, F_NUCLEAR)) danger4 += v * m / dist; - if (unit_flag(funit, F_MISSILE)) danger5 += v * m / MAX(m, dist); - if (!unit_flag(funit, F_NUCLEAR)) { /* only SDI helps against NUCLEAR */ - v = dangerfunct(v, m, dist); - danger += v; - if (igwall) badmojo += v; - } + if (unit_flag(funit, F_HORSE)) { + if (pikemen) udanger /= 2; + else ai_wants_role_unit(pplayer, pcity, F_PIKEMEN, + (udanger * move / (dist*2))); + } + + if (unit_flag(funit, F_DIPLOMAT) && (dist <= 2 * move)) + pcity->ai.diplomat_threat = !diplomat; + + udanger *= udanger; + + if (!igwall) + danger2 += udanger * move / dist; + else if (is_sailing_unit(funit)) + danger3 += udanger * move / dist; + else if (is_air_unit(funit) && !unit_flag(funit, F_NUCLEAR)) + danger4 += udanger * move / dist; + + if (unit_flag(funit, F_MISSILE)) + danger5 += udanger * move / MAX(move, dist); + + if (!unit_flag(funit, F_NUCLEAR)) { /* only SDI helps against NUCLEAR */ + udanger = dangerfunct(v, move, dist); + danger += udanger; + if (igwall) badmojo += udanger; + } + } } city_list_iterate_end; - unit_list_iterate(aplayer->units, punit) - m = unit_type(punit)->move_rate; - v = assess_danger_unit(pcity, punit); - dist = assess_distance(pcity, punit, m, boatid, boatdist, boatspeed); - igwall = unit_really_ignores_citywalls(punit); - - if ((is_ground_unit(punit) && v) || - (is_ground_units_transport(punit))) { - if (dist <= m * 3) urgency++; - if (dist <= m) pcity->ai.grave_danger++; + unit_list_iterate(aplayer->units, punit) { + int move, udanger, dist; + + move = unit_type(funit)->move_rate; + udanger = assess_danger_unit(pcity, funit); + dist = assess_distance(pcity, funit, move, boatid, boatdist, boatspeed); + igwall = unit_really_ignores_citywalls(funit); + + if ((is_ground_unit(funit) && udanger) || + (is_ground_units_transport(funit))) { + if (dist <= move * 3) urgency++; + if (dist <= move) pcity->ai.grave_danger++; /* NOTE: This should actually implement grave_danger, which is supposed to be a feedback-sensitive formula for immediate danger. I'm having second thoughts about the best implementation, and therefore this @@ -340,36 +358,42 @@ not totally sure about and can't thoroughly test in the hours before the release. The AI is in fact vulnerable to gang-attacks, but I'm content to let it remain that way for now. -- Syela 980805 */ - } + } - if (unit_flag(punit, F_HORSE)) { - if (pikemen) v /= 2; + if (unit_flag(funit, F_HORSE)) { + if (pikemen) udanger /= 2; else ai_wants_role_unit(pplayer, pcity, F_PIKEMEN, - (v * m / (dist*2))); - } + (udanger * move / (dist*2))); + } - if (unit_flag(punit, F_DIPLOMAT) && (dist <= 2 * m)) - pcity->ai.diplomat_threat = !diplomat; + if (unit_flag(funit, F_DIPLOMAT) && (dist <= 2 * move)) + pcity->ai.diplomat_threat = !diplomat; - v *= v; + udanger *= udanger; - if (!igwall) danger2 += v * m / dist; - else if (is_sailing_unit(punit)) danger3 += v * m / dist; - else if (is_air_unit(punit) && !unit_flag(punit, F_NUCLEAR)) danger4 += v * m / dist; - if (unit_flag(punit, F_MISSILE)) danger5 += v * m / MAX(m, dist); - if (!unit_flag(punit, F_NUCLEAR)) { /* only SDI helps against NUCLEAR */ - v = dangerfunct(v, m, dist); - danger += v; - if (igwall) badmojo += v; - } - unit_list_iterate_end; + if (!igwall) + danger2 += udanger * move / dist; + else if (is_sailing_unit(funit)) + danger3 += udanger * move / dist; + else if (is_air_unit(funit) && !unit_flag(funit, F_NUCLEAR)) + danger4 += udanger * move / dist; + + if (unit_flag(funit, F_MISSILE)) + danger5 += udanger * move / MAX(move, dist); + + if (!unit_flag(funit, F_NUCLEAR)) { /* only SDI helps against NUCLEAR */ + udanger = dangerfunct(v, move, dist); + danger += udanger; + if (igwall) badmojo += udanger; + } + } unit_list_iterate_end; } } /* end for */ if (!badmojo) pcity->ai.wallvalue = 90; else pcity->ai.wallvalue = (danger * 9 - badmojo * 8) * 10 / (danger); -/* afraid *100 would create integer overflow, but *10 surely won't */ - + /* afraid *100 would create integer overflow, but *10 surely won't */ + if (danger < 0 || danger > 1<<24) /* I hope never to see this! */ freelog(LOG_ERROR, "Dangerous danger (%d) in %s. Beware of overflow.", danger, pcity->name); @@ -385,11 +409,21 @@ if (danger5 < 0 || danger5 > 1<<24) /* I hope never to see this! */ freelog(LOG_ERROR, "Dangerous danger5 (%d) in %s. Beware of overflow.", danger5, pcity->name); + if (pcity->ai.grave_danger) urgency += 10; /* really, REALLY urgent to defend */ + pcity->ai.danger = danger; + +/* My first attempt to allow ng_wa >= 200 led to stupidity in cities with +no defenders and danger = 0 but danger > 0. Capping ng_wa at 100 + urgency +led to a failure to buy walls as required. Allowing want > 100 with !urgency +led to the AI spending too much gold and falling behind on science. I'm +trying again, but this will require yet more tedious observation -- Syela */ + if (pcity->ai.building_want[B_CITY] > 0 && danger2) { i = assess_defense(pcity); + if (!i) pcity->ai.building_want[B_CITY] = 100 + urgency; else if (urgency) { if (danger2 > i * 2) pcity->ai.building_want[B_CITY] = 200 + urgency; @@ -398,14 +432,14 @@ if (danger2 > i) pcity->ai.building_want[B_CITY] = 100; else pcity->ai.building_want[B_CITY] = danger2 * 100 / i; } - } -/* My first attempt to allow ng_wa >= 200 led to stupidity in cities with -no defenders and danger = 0 but danger > 0. Capping ng_wa at 100 + urgency -led to a failure to buy walls as required. Allowing want > 100 with !urgency -led to the AI spending too much gold and falling behind on science. I'm -trying again, but this will require yet more tedious observation -- Syela */ + } + +/* COASTAL and SAM are TOTALLY UNTESTED and could be VERY WRONG -- Syela */ +/* update 980803; COASTAL seems to work; still don't know about SAM. -- Syela */ + if (pcity->ai.building_want[B_COASTAL] > 0 && danger3) { i = assess_defense_igwall(pcity); + if (!i) pcity->ai.building_want[B_COASTAL] = 100 + urgency; else if (urgency) { if (danger3 > i * 2) pcity->ai.building_want[B_COASTAL] = 200 + urgency; @@ -415,20 +449,23 @@ else pcity->ai.building_want[B_COASTAL] = danger3 * 100 / i; } } -/* COASTAL and SAM are TOTALLY UNTESTED and could be VERY WRONG -- Syela */ -/* update 980803; COASTAL seems to work; still don't know about SAM. -- Syela */ + if (pcity->ai.building_want[B_SAM] > 0 && danger4) { i = assess_defense_igwall(pcity); + if (!i) pcity->ai.building_want[B_SAM] = 100 + urgency; else if (danger4 > i * 2) pcity->ai.building_want[B_SAM] = 200 + urgency; else pcity->ai.building_want[B_SAM] = danger4 * 100 / i; } + if (pcity->ai.building_want[B_SDI] > 0 && danger5) { i = assess_defense_igwall(pcity); + if (!i) pcity->ai.building_want[B_SDI] = 100 + urgency; else if (danger5 > i * 2) pcity->ai.building_want[B_SDI] = 200 + urgency; else pcity->ai.building_want[B_SDI] = danger5 * 100 / i; } + pcity->ai.urgency = urgency; /* need to cache this for bodyguards now -- Syela */ return(urgency); } @@ -471,7 +508,7 @@ Unit_Type_id i; Unit_Type_id bestid = 0; /* ??? Zero is legal value! (Settlers by default) */ Tech_Type_id tech_req; - int j, k, l, move_type, n; + int move_type; int best= 0; int walls = city_got_citywalls(pcity); int desire[U_LAST]; /* what you get is what you seek */ @@ -479,54 +516,74 @@ int isdef = has_a_normal_defender(pcity); memset(desire, 0, sizeof(desire)); + for (i = 0; i < game.num_unit_types; i++) { if (!is_ai_simple_military(i)) continue; + move_type = unit_types[i].move_type; if ((move_type == LAND_MOVING || move_type == SEA_MOVING)) { - k = pplayer->ai.tech_turns[unit_types[i].tech_requirement]; - j = unit_desirability(i, 1); - if (!isdef && unit_type_flag(i, F_FIELDUNIT)) j = 0; - j /= 15; /* good enough, no rounding errors */ - j *= j; + int udesire, techdist, techcost; + + techdist = pplayer->ai.tech_turns[unit_types[i].tech_requirement]; + + udesire = unit_desirability(i, 1); + if (!isdef && unit_type_flag(i, F_FIELDUNIT)) udesire = 0; + udesire /= 15; /* good enough, no rounding errors */ + udesire *= desire; + if (can_build_unit(pcity, i)) { - if (walls && move_type == LAND_MOVING) { j *= pcity->ai.wallvalue; j /= 10; } - if ((j > best || (j == best && get_unit_type(i)->build_cost <= - get_unit_type(bestid)->build_cost)) && + if (walls && move_type == LAND_MOVING) { + udesire *= pcity->ai.wallvalue; udesire /= 10; + } + + if ((udesire > best || + (udesire == best && + get_unit_type(i)->build_cost <= get_unit_type(bestid)->build_cost)) && unit_types[i].build_cost <= pcity->shield_stock + 40) { - best = j; + best = udesire; bestid = i; } - } else if (k > 0 && (shore || move_type == LAND_MOVING) && - unit_types[i].tech_requirement != A_LAST) { - if (move_type == LAND_MOVING) { j *= pcity->ai.wallvalue; j /= 10; } - l = k * (k + pplayer->research.researchpoints) * game.researchcost / - (game.year > 0 ? 2 : 4); /* cost (shield equiv) of gaining these techs */ - 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 (techdist > 0 && (shore || move_type == LAND_MOVING) && + unit_types[i].tech_requirement != A_LAST) { + if (move_type == LAND_MOVING) { + udesire *= pcity->ai.wallvalue; udesire /= 10; + } + + /* cost (shield equiv) of gaining these techs */ + techcost = techdist * (techdist + pplayer->research.researchpoints) * + game.researchcost / (game.year > 0 ? 2 : 4); + techcost /= city_list_size(&pplayer->cities); + /* Katvrr advises that with danger high, techcost should be weighted more heavily */ + + desire[i] = udesire * danger / (unit_types[i].build_cost + techcost); } } } + if (!walls && unit_types[bestid].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) */ + /* Phalanx would be 16 * danger / 20. Pikemen would be 36 * danger / (20 + l) */ if (best == 0) best = 1; /* avoid divide-by-zero below */ -/* multiply by unit_types[bestid].build_cost / best */ + /* 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)) { + int tdesire; + tech_req = unit_types[i].tech_requirement; - n = desire[i] * unit_types[bestid].build_cost / best; - pplayer->ai.tech_want[tech_req] += n; /* not the totally idiotic - pplayer->ai.tech_want[tech_req] += n * pplayer->ai.tech_turns[tech_req]; - I amaze myself. -- Syela */ + tdesire = desire[i] * unit_types[bestid].build_cost / best; + pplayer->ai.tech_want[tech_req] += tdesire; /* not the totally idiotic + pplayer->ai.tech_want[tech_req] += tdesire * pplayer->ai.tech_turns[tech_req]; + I amaze myself. -- Syela */ 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, tdesire, desire[i]); } } + choice->choice = bestid; choice->want = danger; choice->type = CT_DEFENDER;