[Freeciv-Dev] Recover Hit Points (PR#1874)
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
This patch makes ground units go to a nearby city - preferably with
Content-Type: multipart/mixed;
boundary="------------080504000401000404010001"
This is a multi-part message in MIME format.
--------------080504000401000404010001
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
This patch makes ground units go to a nearby city - preferably with
barracks - and sealing units go to
a city - preferably with port facility - to recover hit points.
This one makes the unit wait in the city until they recover all the
hit points even there isn't port or barracks.
I think that it follows the style guide and fixes a TODO for the ai.
--------------080504000401000404010001
Content-Type: text/plain;
name="recover_hp4.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="recover_hp4.diff"
diff -Nur -b -Xfreeciv-cvs/diff_ignore freeciv-cvs/ai/aiunit.c
freeciv-mod1/ai/aiunit.c
--- freeciv-cvs/ai/aiunit.c Tue Jul 16 08:51:03 2002
+++ freeciv-mod1/ai/aiunit.c Thu Aug 1 12:14:30 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_city(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);
@@ -1401,6 +1405,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))) {
@@ -1465,6 +1470,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 */
@@ -1882,6 +1893,41 @@
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.
+***********************************************************************/
+static bool find_nearest_friendly_city(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
@@ -2150,6 +2196,92 @@
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_recover_hit_points(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 ((dest_x == punit->x && dest_y == punit->y) || (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);
+ handle_unit_move_request(punit, dest_x, dest_y, FALSE, FALSE);
+ 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 == 99999) {
+ /* we find and undefended city near us, occupy!!! */
+ freelog(LOG_DEBUG, "%s's %s at (%d, %d) occuping (%d, %d) while trying
to recover hit points.",
+ pplayer->name, unit_type(punit)->name,
+ punit->x, punit->y, dest_x, dest_y);
+ handle_unit_move_request(punit, dest_x, dest_y, FALSE, FALSE);
+ punit = find_unit_by_id(id);
+ return;
+ }
+
+ /* find city to stay and wait*/
+ 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_city(punit)) {
+ res=do_unit_goto(punit, GOTO_MOVE_ANY, FALSE);
+ }
+ }
+ punit = find_unit_by_id(id);
+ if (punit) {
+ if ((res != GR_FAILED) || (res == -1)) {
+ freelog(LOG_DEBUG, "%s's %s(%d) at (%d, %d) failed to go to recover
hit points.",
+ pplayer->name, unit_type(punit)->name, punit->id, punit->x,
punit->y);
+ } 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) die trying to recover hit points.",
+ pplayer->name, id);
+ }
+ }
+
+ /* is the unit 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.
**************************************************************************/
@@ -2162,7 +2294,12 @@
if (punit->activity != ACTIVITY_IDLE)
handle_unit_activity_request(punit, ACTIVITY_IDLE);
+ /* 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);
@@ -2205,6 +2342,9 @@
case AIUNIT_EXPLORE:
ai_manage_explorer(punit);
break;
+ case AIUNIT_RECOVER_HIT_POINTS:
+ ai_recover_hit_points(pplayer, punit);
+ break;
default:
abort();
}
diff -Nur -b -Xfreeciv-cvs/diff_ignore freeciv-cvs/common/unit.h
freeciv-mod1/common/unit.h
--- freeciv-cvs/common/unit.h Sat Apr 13 08:15:29 2002
+++ freeciv-mod1/common/unit.h Mon Jul 29 11:49:52 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,
--------------080504000401000404010001--
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Freeciv-Dev] Recover Hit Points (PR#1874),
Jordi Negrevernis i Font <=
|
|