|
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,
|