diff -ur -Xfreeciv/diff_ignore freeciv/ai/aiunit.c freeciv-mod/ai/aiunit.c --- freeciv/ai/aiunit.c Sun Jun 4 04:30:51 2000 +++ freeciv-mod/ai/aiunit.c Sun Jun 4 04:29:59 2000 @@ -380,15 +380,25 @@ int i, j; struct city *pcity; int x, y; + if (dest) { x = punit->goto_dest_x; y = punit->goto_dest_y; } else { x = punit->x; y = punit->y; } + for (j = y - n; j <= y + n; j++) { if (j < 0 || j >= map.ysize) continue; for (i = x - n; i <= x + n; i++) { pcity = map_get_city(i, j); - if (pcity && pcity->owner != punit->owner) - if (dest || punit->activity != ACTIVITY_GOTO || !has_defense(pcity)) + if (pcity && pcity->owner != punit->owner) { + if (pcity->ai.wait[punit->owner]) { + freelog(LOG_DEBUG,"%s ignore too well protected city %s.", + game.players[punit->owner].name,pcity->name); + pcity->ai.invasion = 0; + return; + } + if (dest || punit->activity != ACTIVITY_GOTO || !has_defense(pcity)) { pcity->ai.invasion |= which; + } + } } } } @@ -1133,6 +1143,11 @@ if (aplayer != pplayer) { /* enemy */ city_list_iterate(aplayer->cities, acity) if (handicap && !map_get_known(acity->x, acity->y, pplayer)) continue; + if (acity->ai.wait[pplayer->player_no]) { + freelog(LOG_DEBUG,"player %s ignore too well protected town %s.", + pplayer->name,acity->name); + continue; + } sanity = (goto_is_sane(pplayer, punit, acity->x, acity->y, 1) && warmap.cost[acity->x][acity->y] < maxd); /* for Tangier->Malaga */ if (ai_fuzzy(pplayer,1) && ((is_ground_unit(punit) && diff -ur -Xfreeciv/diff_ignore freeciv/common/city.h freeciv-mod/common/city.h --- freeciv/common/city.h Sun Jun 4 04:30:57 2000 +++ freeciv-mod/common/city.h Sun Jun 4 04:30:13 2000 @@ -278,6 +278,13 @@ /* so we can contemplate with warmap fresh and decide later */ int settler_want, founder_want; /* for builder (F_SETTLERS) and founder (F_CITIES) */ int a, f, invasion; /* who's coming to kill us, for attack co-ordination */ + int lost[MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS]; + /* number of units lost to defend the town vs this player */ + int killed[MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS]; + /* number of units killed while attacking this city by this player */ + int wait[MAX_NUM_PLAYERS + MAX_NUM_PLAYERS]; + /* this player will have to wait 'wait' turns before retrying to + attack this city. */ }; struct city { diff -ur -Xfreeciv/diff_ignore freeciv/server/cityhand.c freeciv-mod/server/cityhand.c --- freeciv/server/cityhand.c Sun Jun 4 04:31:12 2000 +++ freeciv-mod/server/cityhand.c Sun Jun 4 04:30:22 2000 @@ -191,6 +191,13 @@ memset(pcity->ai.building_want, 0, sizeof(pcity->ai.building_want)); pcity->ai.workremain = 1; /* there's always work to be done! */ pcity->ai.danger = -1; /* flag, may come in handy later */ + memset(pcity->ai.lost,0, + (MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS) * sizeof(int)); + memset(pcity->ai.killed,0, + (MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS) * sizeof(int)); + memset(pcity->ai.wait,0, + (MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS) * sizeof(int)); + pcity->corruption = 0; pcity->shield_bonus = 100; pcity->tax_bonus = 100; diff -ur -Xfreeciv/diff_ignore freeciv/server/cityturn.c freeciv-mod/server/cityturn.c --- freeciv/server/cityturn.c Sun Jun 4 04:31:17 2000 +++ freeciv-mod/server/cityturn.c Sun Jun 4 04:30:22 2000 @@ -88,6 +88,7 @@ static void worker_loop(struct city *pcity, int *foodneed, int *prodneed, int *workers); +static void city_update_military_past (struct city * pcity); /************************************************************************** calculate the incomes according to the taxrates and # of specialists. @@ -1509,6 +1510,7 @@ city_check_workers(pplayer, pcity); city_refresh(pcity); + city_update_military_past (pcity); if (!city_got_effect(pcity,B_GRANARY) && !pcity->is_building_unit && (pcity->currently_building == B_GRANARY) && (pcity->food_surplus > 0) @@ -1649,4 +1651,35 @@ get_nation_name_plural(pplayer->nation)); remove_city(pcity); +} + +/************************************************************************** + These lines prevent AI to loose too many units on too well protected city +**************************************************************************/ + +static void city_update_military_past (struct city * pcity) +{ + int i; + + for(i=0;i< game.nplayers;i++) + if (pcity->ai.wait[i] < 0) { + pcity->ai.wait[i] = 0; + pcity->ai.killed[i] = 0; + pcity->ai.lost[i] = 0; + /* to prevent any problem of initialization */ + } + else if (pcity->ai.wait[i]) { + pcity->ai.wait[i]--; + if (!pcity->ai.wait[i]) + freelog(LOG_NORMAL,"%s can now retry to conquer city %s.", + game.players[i].name,pcity->name); + } + else if (pcity->ai.killed[i] / 2> pcity->ai.lost[i] + 1) { + pcity->ai.wait[i] = 25; /* 25 turns without figth */ + pcity->ai.killed[i] = 0; + pcity->ai.lost[i] = 0; + freelog(LOG_NORMAL,"%s has lost too many units against city %s.", + game.players[i].name,pcity->name); + } + /* else fight will go on */ } diff -ur -Xfreeciv/diff_ignore freeciv/server/unithand.c freeciv-mod/server/unithand.c --- freeciv/server/unithand.c Sun Jun 4 04:31:21 2000 +++ freeciv-mod/server/unithand.c Sun Jun 4 04:30:22 2000 @@ -539,6 +539,22 @@ unit_versus_unit(punit, pdefender); + if ((pcity=map_get_city(def_x,def_y)) || + ((punit->activity == ACTIVITY_GOTO) && + (pcity=map_get_city(punit->goto_dest_x,punit->goto_dest_y)))) { + /* if a unit is going to attack a city and is intercepted before + reaching the city, the result of the action will affect + the destination city. + The case of a boat sunk while transporting units to attack a city + is not implemented. -- nb */ + + if (punit->hp) { + pcity->ai.lost[punit->owner]++; + } else { + pcity->ai.killed[punit->owner]++; + } + } + /* Adjust attackers moves_left _after_ unit_versus_unit() so that * the movement attack modifier is correct! --dwp *