[freeciv-ai] Re: (PR#6567) AI has too many boats.
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://rt.freeciv.org/Ticket/Display.html?id=6567 >
On Mon, 17 May 2004, Jason Short wrote:
> <URL: http://rt.freeciv.org/Ticket/Display.html?id=6567 >
>
> It looks like there's nothing to stop us from looking into cities we
> don't own. Maybe the PF takes care of this, but can you at least add an
> assertion?
Added a comparison
pcity->owner == pferry->owner
as Jason mentioned.
Fixed a bug or two and added some clever logic: ferry will try to select
the city basing not only on the distance to it, but also on when the city
will need the boat.
Run a test-game (in highly artificial conditions). With the patch
there were slightly less boats and slightly more cities.
Should probably be committed before it gets too complicated for its own
good.
G.
? test.gz
? ttt.gz
Index: ai/advdomestic.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/advdomestic.c,v
retrieving revision 1.106
diff -u -r1.106 advdomestic.c
--- ai/advdomestic.c 25 Feb 2004 20:23:49 -0000 1.106
+++ ai/advdomestic.c 18 May 2004 22:10:40 -0000
@@ -35,6 +35,7 @@
#include "advmilitary.h"
#include "aicity.h"
#include "aidata.h"
+#include "ailog.h"
#include "aitools.h"
#include "aiunit.h"
@@ -996,9 +997,9 @@
int want = pcity->ai.founder_want;
if (want > choice->want) {
- freelog(LOG_DEBUG, "%s (%d, %d) desires founders with passion %d",
- pcity->name, pcity->x, pcity->y, want);
+ CITY_LOG(LOG_DEBUG, pcity, "desires founders with passion %d", want);
choice->want = want;
+ choice->need_boat = pcity->ai.founder_boat;
choice->type = CT_NONMIL;
ai_choose_role_unit(pplayer, pcity, choice, F_CITIES, want);
Index: ai/aicity.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aicity.c,v
retrieving revision 1.150
diff -u -r1.150 aicity.c
--- ai/aicity.c 22 Apr 2004 23:07:07 -0000 1.150
+++ ai/aicity.c 18 May 2004 22:10:40 -0000
@@ -226,6 +226,7 @@
pcity->ai.choice.choice = bestchoice.choice; /* we want to spend gold
later */
pcity->ai.choice.want = bestchoice.want; /* so that we spend it in the
right city */
pcity->ai.choice.type = bestchoice.type; /* instead of the one atop the
list */
+ pcity->ai.choice.need_boat = bestchoice.need_boat;
}
if (bestchoice.want != 0) { /* Note - on fallbacks, will NOT get stopped
building msg */
Index: ai/aitools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aitools.c,v
retrieving revision 1.103
diff -u -r1.103 aitools.c
--- ai/aitools.c 4 May 2004 17:40:25 -0000 1.103
+++ ai/aitools.c 18 May 2004 22:10:40 -0000
@@ -812,6 +812,7 @@
best->choice =cur->choice;
best->want = cur->want;
best->type = cur->type;
+ best->need_boat = cur->need_boat;
}
}
Index: ai/aiunit.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aiunit.c,v
retrieving revision 1.314
diff -u -r1.314 aiunit.c
--- ai/aiunit.c 4 May 2004 17:40:25 -0000 1.314
+++ ai/aiunit.c 18 May 2004 22:10:40 -0000
@@ -2308,6 +2308,101 @@
}
/****************************************************************************
+ A helper for ai_manage_ferryboat. Finds a city that wants a ferry. It
+ might signal for the ferry using pcity->ai.choice.need_boat field or
+ it might simply be building a ferry of it's own.
+
+ The city found will be set as the goto destination.
+
+ TODO: lift the path off the map
+ TODO (possible): put this and ai_ferry_findcargo into one PF-loop. This
+ will save some code lines but will be faster in the rare cases when there
+ passengers that can not be reached ("false positive").
+****************************************************************************/
+static bool ai_ferry_find_interested_city(struct unit *pferry)
+{
+ /* Path-finding stuff */
+ struct pf_map *map;
+ struct pf_parameter parameter;
+ /* Early termination condition */
+ int turns_horizon = FC_INFINITY;
+ /* Future return value */
+ bool needed = FALSE;
+
+ UNIT_LOG(LOGLEVEL_FERRY, pferry, "Ferry looking for a city that needs it");
+
+ pft_fill_unit_parameter(¶meter, pferry);
+ /* We are looking for our own cities, no need to look into the unknown */
+ parameter.get_TB = no_fights_or_unknown;
+ parameter.omniscience = FALSE;
+
+ map = pf_create_map(¶meter);
+ parameter.turn_mode = TM_WORST_TIME;
+
+ /* We want to consider the place we are currently in too, hence the
+ * do-while loop */
+ do {
+ struct pf_position pos;
+ struct city *pcity;
+
+ pf_next_get_position(map, &pos);
+ if (pos.turn >= turns_horizon) {
+ /* Won't be able to find anything better than what we have */
+ break;
+ }
+
+ pcity = map_get_city(pos.x, pos.y);
+
+ if (pcity && pcity->owner == pferry->owner
+ && (pcity->ai.choice.need_boat
+ || (pcity->is_building_unit
+ && unit_has_role(pcity->currently_building, L_FERRYBOAT)))) {
+ bool really_needed = TRUE;
+ int turns = city_turns_to_build(pcity, pcity->currently_building,
+ pcity->is_building_unit, TRUE);
+
+ UNIT_LOG(LOGLEVEL_FERRY, pferry, "%s (%d, %d) looks promising...",
+ pcity->name, pcity->x, pcity->y);
+
+ if (pos.turn > turns && pcity->is_building_unit
+ && unit_has_role(pcity->currently_building, L_FERRYBOAT)) {
+ UNIT_LOG(LOGLEVEL_FERRY, pferry, "%s is NOT suitable: "
+ "will finish building its own ferry too soon", pcity->name);
+ continue;
+ }
+
+ if (turns >= turns_horizon) {
+ UNIT_LOG(LOGLEVEL_FERRY, pferry, "%s is NOT suitable: "
+ "has just strated building", pcity->name);
+ continue;
+ }
+
+ unit_list_iterate(map_get_tile(pos.x, pos.y)->units, aunit) {
+ if (aunit != pferry && aunit->owner == pferry->owner
+ && unit_has_role(aunit->type, L_FERRYBOAT)) {
+
+ UNIT_LOG(LOGLEVEL_FERRY, pferry, "%s is NOT suitable: "
+ "has another ferry", pcity->name);
+ really_needed = FALSE;
+ break;
+ }
+ } unit_list_iterate_end;
+
+ if (really_needed) {
+ UNIT_LOG(LOGLEVEL_FERRY, pferry, "will go to %s unless find "
+ "something better", pcity->name);
+ set_goto_dest(pferry, pos.x, pos.y);
+ turns_horizon = turns;
+ needed = TRUE;
+ }
+ }
+ } while (pf_next(map));
+
+ pf_destroy_map(map);
+ return needed;
+}
+
+/****************************************************************************
It's about 12 feet square and has a capacity of almost 1000 pounds.
It is well constructed of teak, and looks seaworthy.
@@ -2437,14 +2532,14 @@
return;
}
- CHECK_UNIT(punit);
-
- if (punit->moves_left == 0
- || !is_ocean(map_get_terrain(punit->x, punit->y))) {
+ /* Try to find a city that needs a ferry */
+ if (ai_ferry_find_interested_city(punit)) {
+ (void) ai_unit_goto(punit, goto_dest_x(punit), goto_dest_y(punit));
return;
}
-
+
(void) ai_manage_explorer(punit);
+
if (punit->moves_left > 0) {
struct city *pcity = find_nearest_safe_city(punit);
if (pcity) {
Index: common/city.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.h,v
retrieving revision 1.141
diff -u -r1.141 city.h
--- common/city.h 22 Apr 2004 22:58:28 -0000 1.141
+++ common/city.h 18 May 2004 22:10:41 -0000
@@ -201,6 +201,7 @@
/* so we can contemplate with warmap fresh and decide later */
int settler_want, founder_want; /* for builder (F_SETTLERS) and founder
(F_CITIES) */
+ bool founder_boat; /* if the city founder will need a boat */
int invasion; /* who's coming to kill us, for attack co-ordination */
int attack, bcost; /* This is also for invasion - total power and value of
* all units coming to kill us. */
Index: server/settlers.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/settlers.c,v
retrieving revision 1.180
diff -u -r1.180 settlers.c
--- server/settlers.c 26 Feb 2004 03:24:16 -0000 1.180
+++ server/settlers.c 18 May 2004 22:10:41 -0000
@@ -1532,6 +1532,10 @@
want = -199;
} unit_list_iterate_end;
+ /* Did we count on using an existing boat. If yes we need to keep it
+ * in the city. */
+ pcity->ai.founder_boat = (ferryboat != NULL);
+
if (gx == -1) {
pcity->ai.founder_want = -want;
} else {
|
|