Index: advdomestic.c =================================================================== RCS file: /home/cvs/aiciv/freeciv-a2/ai/advdomestic.c,v retrieving revision 1.1.1.5 retrieving revision 1.20 diff -u -r1.1.1.5 -r1.20 Index: advmilitary.c =================================================================== RCS file: /home/cvs/aiciv/freeciv-a2/ai/advmilitary.c,v retrieving revision 1.1.1.9 retrieving revision 1.4 diff -u -r1.1.1.9 -r1.4 --- advmilitary.c 22 Feb 2002 19:32:40 -0000 1.1.1.9 +++ advmilitary.c 26 Feb 2002 22:49:56 -0000 1.4 @@ -620,10 +620,14 @@ unit_types[i].move_type == HELI_MOVING) && acity && acity->ai.invasion == 2) b0 = f * SHIELD_WEIGHTING; else { - b0 = (b * a - (f + (acity ? acity->ai.f : 0)) * d) * g * SHIELD_WEIGHTING / (a + g * d); - if (acity && b * acity->ai.a * acity->ai.a > acity->ai.f * d) - b0 -= (b * acity->ai.a * acity->ai.a - acity->ai.f * d) * - g * SHIELD_WEIGHTING / (acity->ai.a * acity->ai.a + g * d); + int a_squared = acity->ai.a * acity->ai.a; + + /* See aiunit.c:find_something_to_kill() for comments. */ + + b0 = kill_desire(b, a, (f + (acity ? acity->ai.f : 0)), d, g); + if (acity && b * a_squared > acity->ai.f * d) { + b0 -= kill_desire(b, a_squared, acity->ai.f, d, g); + } } if (b0 > 0) { b0 -= l * SHIELD_WEIGHTING; @@ -826,10 +830,14 @@ unit_types[v].move_type == HELI_MOVING) && acity && acity->ai.invasion == 2) b0 = f * SHIELD_WEIGHTING; else { - b0 = (b * a - (f + (acity ? acity->ai.f : 0)) * d) * g * SHIELD_WEIGHTING / (a + g * d); - if (acity && b * acity->ai.a * acity->ai.a > acity->ai.f * d) - b0 -= (b * acity->ai.a * acity->ai.a - acity->ai.f * d) * - g * SHIELD_WEIGHTING / (acity->ai.a * acity->ai.a + g * d); + int a_squared = acity->ai.a * acity->ai.a; + + /* See aiunit.c:find_something_to_kill() for comments. */ + + b0 = kill_desire(b, a, (f + (acity ? acity->ai.f : 0)), d, g); + if (acity && b * a_squared > acity->ai.f * d) { + b0 -= kill_desire(b, a_squared, acity->ai.f, d, g); + } } b0 -= c * (unhap ? SHIELD_WEIGHTING + 2 * TRADE_WEIGHTING : SHIELD_WEIGHTING); e = military_amortize(b0, MAX(1, c), fprime + needferry); Index: aiunit.c =================================================================== RCS file: /home/cvs/aiciv/freeciv-a2/ai/aiunit.c,v retrieving revision 1.1.1.10 retrieving revision 1.48 diff -u -r1.1.1.10 -r1.48 --- aiunit.c 23 Feb 2002 21:03:31 -0000 1.1.1.10 +++ aiunit.c 26 Feb 2002 22:49:56 -0000 1.48 @@ -616,6 +616,41 @@ } /************************************************************************** +Compute how much we want to kill certain victim we've chosen, counted in +SHIELDs. + +FIXME?: The equation is not accurate as the other values can vary for other +victims on same tile (we take values from best defender) - however I believe +it's accurate just enough now and lost speed isn't worth that. --pasky + +Benefit is something like 'attractiveness' of the victim, how nice it would be +to destroy it. Larger value, worse loss for enemy. + +Attack is the total possible attack power we can throw on the victim. Note that +it usually comes squared. + +Loss is the possible loss when we would lose the unit we are attacking with (in +SHIELDs). + +Vuln is vulnerability of our unit when attacking the enemy. Note that it +usually comes squared as well. + +Victim count is number of victims stacked in the target tile. Note that we +shouldn't treat cities as a stack (despite the code using this function) - the +scaling is probably different. (extremely dodgy usage of it -- GB) +**************************************************************************/ +int kill_desire(int benefit, int attack, int loss, int vuln, int victim_count) +{ + int desire; + + /* attractiveness danger */ + desire = ((benefit * attack - loss * vuln) * victim_count * SHIELD_WEIGHTING + / (attack + vuln * victim_count)); + + return desire; +} + +/************************************************************************** Military "want" estimates are amortized in this complicated way. COMMENTME: Why not use simple amortize? -- GB **************************************************************************/ @@ -805,20 +840,10 @@ unit_owner(pdef)->name, unit_type(pdef)->name); } else { + /* See description of kill_desire() about this variables. */ int vuln = unit_vulnerability(punit, pdef); - - /* The total possible attack power we can throw on the victim. Note - * that we will even square this. */ int attack = reinforcements_value(punit, pdef->x, pdef->y) + bellig; - - /* Something like 'attractiveness' of the victim, how nice it would be - * to destroy it. Larger value, worse loss for enemy. */ int benefit = unit_type(pdef)->build_cost; - - /* We're only dealing with adjacent victims here. */ - int move_cost = 0; - - /* The possible loss when we would lose the unit we want to attack. */ int loss = unit_type(punit)->build_cost; attack *= attack; @@ -836,17 +861,12 @@ /* If we have non-zero belligerence... */ if (attack > 0 && is_my_turn(punit, pdef)) { int desire; + + /* FIXME? Why we don't use stack_size as victim_count? --pasky */ + + desire = kill_desire(benefit, attack, loss, vuln, 1); - /* TODO: This equation is simplified version of much worse ones in - * that long fat routines, but it's still a common pattern, so we - * will can this equation to one separate readable function. We'll - * also be able to remove move_cost and loss variables. */ - - /* attractiveness danger */ - desire = ((benefit * attack - loss * vuln) * SHIELD_WEIGHTING - / (attack + vuln) - move_cost * SHIELD_WEIGHTING); - - /* No need to amortize! We're doing it in one-turn horizon (?). */ + /* No need to amortize! We're doing it in one-turn horizon. */ if (desire > best && ai_fuzzy(pplayer, 1)) { freelog(LOG_DEBUG, "Better than %d is %d (%s)", @@ -1520,10 +1540,19 @@ else if ((is_ground_unit(punit) || is_heli_unit(punit)) && acity->ai.invasion == 2) b0 = f * SHIELD_WEIGHTING; else { - b0 = (b * a - (f + acity->ai.f) * d) * g * SHIELD_WEIGHTING / (a + g * d); - if (b * acity->ai.a * acity->ai.a > acity->ai.f * d) - b0 -= (b * acity->ai.a * acity->ai.a - acity->ai.f * d) * - g * SHIELD_WEIGHTING / (acity->ai.a * acity->ai.a + g * d); + 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) { + /* If there're enough units to do the job, we don't need this + * one. */ + /* FIXME: The problem with ai.f is that bigger it is, less is our + * desire to go help other units. Now suppose we need five + * cavalries to take over a city, we have four (which is not + * enough), then we will be severely discouraged to build the + * fifth one. Where is logic in this??!?! --GB */ + b0 -= kill_desire(b, a_squared, acity->ai.f, d, g); + } } b0 -= c * (unhap ? SHIELD_WEIGHTING + 2 * TRADE_WEIGHTING : SHIELD_WEIGHTING); /* FIXME: build_cost of ferry */ Index: aiunit.h =================================================================== RCS file: /home/cvs/aiciv/freeciv-a2/ai/aiunit.h,v retrieving revision 1.1.1.4 retrieving revision 1.7 diff -u -r1.1.1.4 -r1.7 --- aiunit.h 19 Feb 2002 19:33:54 -0000 1.1.1.4 +++ aiunit.h 24 Feb 2002 21:36:21 -0000 1.7 @@ -37,6 +37,7 @@ int unit_vulnerability_basic(struct unit *punit, struct unit *pdef); int unit_vulnerability_virtual(struct unit *punit); int unit_vulnerability(struct unit *punit, struct unit *pdef); +int kill_desire(int benefit, int attack, int loss, int vuln, int attack_count); int military_amortize(int value, int delay, int build_cost); bool is_on_unit_upgrade_path(Unit_Type_id test, Unit_Type_id base);