Complete.Org:
Mailing Lists:
Archives:
freeciv-ai:
August 2002: [freeciv-ai] Re: [Freeciv-Dev] Re: Patch for units recovering hit points |
[freeciv-ai] Re: [Freeciv-Dev] Re: Patch for units recovering hit points[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Patch atached for yesterday's cvs. Now the patch also makes the ferryboats wait to recover hitpoints. Does not select a better tile to fortify. Per I. Mathisen wrote: On Fri, 9 Aug 2002, Jordi Negrevernis i Font wrote:> > Also, if a unit's in a city, it only goes after huts.You might want to change that to also attack enemies that it really wants to diff -Nur -b -Xfreeciv-cvs-Aug-10/diff_ignore freeciv-cvs-Aug-10/ai/aiunit.c freeciv-cvs-Aug-10-mod/ai/aiunit.c --- freeciv-cvs-Aug-10/ai/aiunit.c Fri Aug 9 13:33:46 2002 +++ freeciv-cvs-Aug-10-mod/ai/aiunit.c Sun Aug 11 20:32:13 2002 @@ -29,6 +29,7 @@ #include "shared.h" #include "timing.h" #include "unit.h" +#include "unittype.h" #include "barbarian.h" #include "citytools.h" @@ -47,6 +48,9 @@ #include "aiunit.h" +static bool find_nearest_friendly_port(struct unit *punit); +static bool find_nearest_friendly_barrack(struct unit *punit); + static void ai_manage_diplomat(struct player *pplayer, struct unit *pdiplomat); static void ai_manage_military(struct player *pplayer,struct unit *punit); static void ai_manage_caravan(struct player *pplayer, struct unit *punit); @@ -1402,6 +1406,7 @@ struct unit *aunit; int val, def; int q = 0; + struct unit_type *punittype=get_unit_type(punit->type); /* tired of AI abandoning its cities! -- Syela */ if (punit->homecity != 0 && (pcity = find_city_by_id(punit->homecity))) { @@ -1466,6 +1471,12 @@ } } + /* is the unit damaged? */ + if ((punit->hp < punittype->hp * 0.25) || ((punit->ai.ai_role == AIUNIT_RECOVER_HIT_POINTS) && (punit->hp < punittype->hp))) { + punit->ai.ai_role = AIUNIT_RECOVER_HIT_POINTS; + return; + } + /* I'm not 100% sure this is the absolute best place for this... -- Syela */ generate_warmap(map_get_city(punit->x, punit->y), punit); /* I need this in order to call unit_move_turns, here and in look_for_charge */ @@ -1884,6 +1895,43 @@ return TRUE; } +/********************************************************************** + Find safe city (preferably with Barracks). An allied player's city is + just as good as one of our own, since both replenish our hitpoints and + reduce unhappiness. + Returns TRUE with punit->goto_dest_* set or FALSE. + Be aware that the function destroys punit->goto_dest_* +***********************************************************************/ +static bool find_nearest_friendly_barrack(struct unit *punit) +{ + struct player *pplayer = unit_owner(punit); + int best = 6 * THRESHOLD + 1, cur; + + generate_warmap(map_get_city(punit->x, punit->y), punit); + players_iterate(aplayer) { + if (pplayers_allied(pplayer,aplayer)) { + city_list_iterate(aplayer->cities, pcity) { + cur = warmap.cost[pcity->x][pcity->y]; + /* we favour cities which barracks */ + if (city_got_building(pcity, B_BARRACKS)) cur /= 3; + if (city_got_building(pcity, B_BARRACKS2)) cur /= 3; + if (city_got_building(pcity, B_BARRACKS3)) cur /= 3; + if (cur < best) { + punit->goto_dest_x = pcity->x; + punit->goto_dest_y = pcity->y; + best = cur; + } + } city_list_iterate_end; + } + } players_iterate_end; + if (best > 6 * THRESHOLD) return FALSE; + freelog(LOG_DEBUG, "Friendly city nearest to (%d,%d) is %s@(%d,%d) [%d]", + punit->x, punit->y, + map_get_city(punit->goto_dest_x, punit->goto_dest_y)->name, + punit->goto_dest_x, punit->goto_dest_y, best); + return TRUE; +} + /************************************************************************* This seems to do the attack. First find victim on the neighbouring tiles. If no enemies nearby find_something_to_kill() anywhere else. If there is @@ -2042,6 +2090,7 @@ struct unit *bodyguard; int best = 4 * unit_type(punit)->move_rate, x = punit->x, y = punit->y; int n = 0, p = 0; + struct unit_type *punittype=get_unit_type(punit->type); if (!unit_list_find(&map_get_tile(punit->x, punit->y)->units, punit->ai.passenger)) punit->ai.passenger = 0; @@ -2065,6 +2114,15 @@ } } unit_list_iterate_end; + + /* we try to recover hitpoints, if we are in a city, before leave */ + if ((punit->hp < punittype->hp) && (pcity = map_get_city(punit->x, punit->y))) { + /* don't do nothing, just wait in the city */ + freelog(LOG_DEBUG, "Waiting in %s to recover hitpoints before ferrying to (%d,%d).", pcity->name, + punit->goto_dest_x, punit->goto_dest_y); + return; + } + if (p != 0) { freelog(LOG_DEBUG, "%s#%d@(%d,%d), p=%d, n=%d", unit_name(punit->type), punit->id, punit->x, punit->y, p, n); @@ -2152,6 +2210,97 @@ return; } +/************************************************************************* + This function goes wait a unit in a city for the hitpoints to recover. + If something is attacking your city, kill it yeahhh!!!. +**************************************************************************/ +static void ai_manage_hitpoint_recovery(struct player *pplayer,struct unit *punit) +{ + int dest_x, dest_y; + int id = punit->id; + bool flag; + int ct = 10; + enum goto_result res; + struct city *pcity=map_get_city(punit->x, punit->y); + struct unit_type *punittype=get_unit_type(punit->type); + + if (pcity) { + /* rest in city until the hitpoints are recovered */ + do { + flag = FALSE; + res=ai_military_findvictim(pplayer, punit, &dest_x, &dest_y); + if ((res <= 1) || (res = 99998)) { + /* nothing to kill and no huts to find, so wait to recover all the hitpoints */ + } else { /* goto does NOT work for fast units */ + freelog(LOG_DEBUG, "%s's %s at (%d, %d) bashing (%d, %d) while recovering hit points.", + pplayer->name, unit_type(punit)->name, + punit->x, punit->y, dest_x, dest_y); + ai_unit_attack(punit, dest_x, dest_y); + punit = find_unit_by_id(id); + if (punit) flag = punit->moves_left > 0; else flag = FALSE; + } + ct--; /* infinite loops from railroads must be stopped */ + } while (flag && ct > 0); /* want units to attack multiple times */ + + if (punit) + freelog(LOG_DEBUG, "%s's %s(%d) at (%d, %d) recovering hit points.", + pplayer->name, unit_type(punit)->name, punit->id, punit->x, punit->y); + + } else { + /* goto to nearest city to recover hit points */ + /* just before, check to see if we can occupy at enemy city undefended */ + flag = FALSE; + res=ai_military_findvictim(pplayer, punit, &dest_x, &dest_y); + if (res > 1) { + /* we find and undefended city near us, occupy!!! */ + /* or we find something to kill */ + freelog(LOG_DEBUG, "%s's %s at (%d, %d) attacking (%d, %d) while trying to recover hit points.", + pplayer->name, unit_type(punit)->name, + punit->x, punit->y, dest_x, dest_y); + ai_unit_attack(punit, dest_x, dest_y); + punit = find_unit_by_id(id); + return; + } + + /* find city to stay and go there */ + res = -1; + if (is_sailing_unit(punit)) { + if (find_nearest_friendly_port(punit)) { + res=do_unit_goto(punit, GOTO_MOVE_ANY, FALSE); + } + } else { + if (find_nearest_friendly_barrack(punit)) { + res=do_unit_goto(punit, GOTO_MOVE_ANY, FALSE); + } + } + punit = find_unit_by_id(id); + if (punit) { + if (res == -1) { + freelog(LOG_DEBUG, "%s's %s(%d) at (%d, %d) failed to go to recover hit points, fortying.", + pplayer->name, unit_type(punit)->name, punit->id, + punit->x, punit->y); + /* TODO: find best tile to fortify */ + handle_unit_activity_request(punit, ACTIVITY_FORTIFYING); + } else { + freelog(LOG_DEBUG, "%s's %s(%d) at (%d, %d) going to (%d, %d) to recover hit points.", + pplayer->name, unit_type(punit)->name, punit->id, punit->x, punit->y, + punit->goto_dest_x, punit->goto_dest_y); + } + } else { + freelog(LOG_DEBUG, "%s's unit (%d) died trying to recover hit points.", + pplayer->name, id); + } + } + + /* is the unit stil damaged?, if true recover hit points, if not idle */ + if (punit) { + if (punit->hp == punittype->hp) { + punit->ai.ai_role = AIUNIT_NONE; + return; + } + } +} + /************************************************************************** decides what to do with a military unit. **************************************************************************/ @@ -2164,7 +2313,12 @@ if (punit->activity != ACTIVITY_IDLE) handle_unit_activity_request(punit, ACTIVITY_IDLE); - punit->ai.ai_role = AIUNIT_NONE; + /* prevent losing the long term objective of recovering hit points */ + if(punit->ai.ai_role == AIUNIT_RECOVER_HIT_POINTS) { + } else { + punit->ai.ai_role = AIUNIT_NONE; + }; + /* was getting a bad bug where a settlers caused a defender to leave home */ /* and then all other supported units went on DEFEND_HOME/goto */ ai_military_findjob(pplayer, punit); @@ -2207,6 +2361,9 @@ case AIUNIT_EXPLORE: ai_manage_explorer(punit); break; + case AIUNIT_RECOVER_HIT_POINTS: + ai_manage_hitpoint_recovery(pplayer, punit); + return; default: abort(); } diff -Nur -b -Xfreeciv-cvs-Aug-10/diff_ignore freeciv-cvs-Aug-10/common/unit.h freeciv-cvs-Aug-10-mod/common/unit.h --- freeciv-cvs-Aug-10/common/unit.h Wed Aug 7 13:21:49 2002 +++ freeciv-cvs-Aug-10-mod/common/unit.h Sun Aug 11 12:00:37 2002 @@ -51,7 +51,7 @@ enum ai_unit_task { AIUNIT_NONE, AIUNIT_AUTO_SETTLER, AIUNIT_BUILD_CITY, AIUNIT_DEFEND_HOME, AIUNIT_ATTACK, AIUNIT_FORTIFY, AIUNIT_RUNAWAY, AIUNIT_ESCORT, AIUNIT_EXPLORE, - AIUNIT_PILLAGE }; + AIUNIT_PILLAGE, AIUNIT_RECOVER_HIT_POINTS }; enum goto_move_restriction { GOTO_MOVE_ANY,
|