[freeciv-ai] (PR#9908) Make AI understand channels
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://rt.freeciv.org/Ticket/Display.html?id=9908 >
> It seems that the transitivity is not taken into account (i.e. A->B and
> B->C => A->C).
Fixed.
> Also you can make it a single array by associating to each ocean the
> smallest of the ocean numbers which are connected to it. But I am not
> sure if it's worth the trouble.
Couldn't do in any reasonable way.
Also fixed:
* in is_goto_sane if we are a boat and happen to be in a city, we still
understand that it is ok to go to an ocean
* in ai_channel we receive the result of map_get_continent which is
negative if it's an ocean, so we treat it correspondingly. if it isn't
negative, we return FALSE.
Index: ai/aidata.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aidata.c,v
retrieving revision 1.46
diff -u -r1.46 aidata.c
--- ai/aidata.c 23 Oct 2004 19:01:01 -0000 1.46
+++ ai/aidata.c 11 Nov 2004 06:09:46 -0000
@@ -134,7 +134,8 @@
void ai_data_turn_init(struct player *pplayer)
{
struct ai_data *ai = &aidata[pplayer->player_no];
- int i, nuke_units = num_role_units(F_NUCLEAR);
+ int i, j, k;
+ int nuke_units = num_role_units(F_NUCLEAR);
bool danger_of_nukes = FALSE;
int ally_strength = -1;
struct player *ally_strongest = NULL;
@@ -225,6 +226,52 @@
/* Increase from fear to terror if opponent actually has nukes */
if (danger_of_nukes) ai->threats.nuclear++; /* sum of both fears */
+ /*** Channels ***/
+
+ /* Ways to cross from one ocean to another through a city. */
+ ai->channels = fc_calloc((ai->num_oceans + 1) * (ai->num_oceans + 1),
sizeof(int));
+ players_iterate(aplayer) {
+ if (pplayers_allied(pplayer, aplayer)) {
+ city_list_iterate(aplayer->cities, pcity) {
+ adjc_iterate(pcity->tile, tile1) {
+ if (is_ocean(tile1->terrain)) {
+ adjc_iterate(pcity->tile, tile2) {
+ if (is_ocean(tile2->terrain)
+ && map_get_continent(tile1) != map_get_continent(tile2)) {
+ ai->channels[(-tile1->continent) * ai->num_oceans
+ + (-tile2->continent)] = TRUE;
+ ai->channels[(-tile2->continent) * ai->num_oceans
+ + (-tile1->continent)] = TRUE;
+ }
+ } adjc_iterate_end;
+ }
+ } adjc_iterate_end;
+ } city_list_iterate_end;
+ }
+ } players_iterate_end;
+
+ /* If we can go i -> j and j -> k, we can also go i -> k. */
+ for(i = 1; i <= ai->num_oceans; i++) {
+ for(j = 1; j <= ai->num_oceans; j++) {
+ if (ai->channels[i * ai->num_oceans + j]) {
+ for(k = 1; k <= ai->num_oceans; k++) {
+ ai->channels[i * ai->num_oceans + k] |=
+ ai->channels[j * ai->num_oceans + k];
+ }
+ }
+ }
+ }
+#if 0
+ freelog(LOG_NORMAL, "Player %s:", pplayer->name);
+ for(i = 1; i <= ai->num_oceans; i++) {
+ for(j = 1; j <= ai->num_oceans; j++) {
+ if (ai->channels[i * ai->num_oceans + j]) {
+ freelog(LOG_NORMAL, "oceans %d and %d are connected", i, j);
+ }
+ }
+ }
+#endif
+
/*** Exploration ***/
ai->explore.land_done = TRUE;
@@ -426,6 +473,9 @@
free(ai->stats.cities);
ai->stats.cities = NULL;
+
+ free(ai->channels);
+ ai->channels = NULL;
}
/**************************************************************************
@@ -458,7 +508,7 @@
* sizeof(*ai->government_want)));
memset(ai->government_want, 0,
(game.government_count + 1) * sizeof(*ai->government_want));
-
+ ai->channels = NULL;
ai->diplomacy.target = NULL;
ai->diplomacy.strategy = WIN_OPEN;
ai->diplomacy.timer = 0;
@@ -481,3 +531,17 @@
ai->diplomacy.player_intel[i].warned_about_space = 0;
}
}
+
+/**************************************************************************
+ Is there a channel going from ocean c1 to ocean c2?
+ Returns FALSE if either is not an ocean.
+**************************************************************************/
+bool ai_channel(struct player *pplayer, Continent_id c1, Continent_id c2)
+{
+ struct ai_data *ai = ai_data_get(pplayer);
+
+ if (c1 >= 0 || c2 >= 0) {
+ return FALSE;
+ }
+ return (c1 == c2 || ai->channels[(-c1) * ai->num_oceans + (-c2)]);
+}
Index: ai/aidata.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aidata.h,v
retrieving revision 1.19
diff -u -r1.19 aidata.h
--- ai/aidata.h 23 Oct 2004 19:01:01 -0000 1.19
+++ ai/aidata.h 11 Nov 2004 06:09:46 -0000
@@ -97,6 +97,9 @@
bool sea_done; /* nothing more to explore at sea */
} explore;
+ /* Keep track of available ocean channels */
+ bool *channels;
+
/* This struct is used for statistical unit building, eg to ensure
* that we don't build too few or too many units of a given type. */
struct {
@@ -149,4 +152,6 @@
struct ai_data *ai_data_get(struct player *pplayer);
+bool ai_channel(struct player *pplayer, Continent_id c1, Continent_id c2);
+
#endif
Index: server/gotohand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/gotohand.c,v
retrieving revision 1.187
diff -u -r1.187 gotohand.c
--- server/gotohand.c 31 Oct 2004 22:32:33 -0000 1.187
+++ server/gotohand.c 11 Nov 2004 06:09:46 -0000
@@ -33,6 +33,7 @@
#include "unithand.h"
#include "unittools.h"
+#include "aidata.h"
#include "aitools.h"
#include "gotohand.h"
@@ -1217,6 +1218,9 @@
bool goto_is_sane(struct unit *punit, struct tile *ptile, bool omni)
{
struct player *pplayer = unit_owner(punit);
+ struct city *pcity = map_get_city(ptile);
+ Continent_id my_cont = map_get_continent(punit->tile);
+ Continent_id target_cont = map_get_continent(ptile);
if (same_pos(punit->tile, ptile)) {
return TRUE;
@@ -1235,36 +1239,57 @@
* and with a boat */
if (ground_unit_transporter_capacity(ptile, pplayer) > 0) {
adjc_iterate(ptile, tmp_tile) {
- if (map_get_continent(tmp_tile) == map_get_continent(punit->tile))
+ if (map_get_continent(tmp_tile) == my_cont) {
/* The target is adjacent to our continent! */
return TRUE;
+ }
} adjc_iterate_end;
}
} else {
/* Going to a land tile: better be our continent */
- if (map_get_continent(punit->tile) == map_get_continent(ptile)) {
+ if (my_cont == target_cont) {
return TRUE;
} else {
/* Well, it's not our continent, but maybe we are on a boat
* adjacent to the target continent? */
adjc_iterate(punit->tile, tmp_tile) {
- if (map_get_continent(tmp_tile) == map_get_continent(ptile)) {
+ if (map_get_continent(tmp_tile) == target_cont) {
return TRUE;
}
} adjc_iterate_end;
}
- }
-
+ }
return FALSE;
case SEA_MOVING:
- if (is_ocean(map_get_terrain(ptile))
- || is_ocean_near_tile(ptile)) {
- /* The target is sea or is accessible from sea
- * (allow for bombardment and visiting ports) */
- return TRUE;
+ if (!is_ocean(map_get_terrain(punit->tile))) {
+ /* Oops, we are not in the open waters. What ocean do we have
+ * access to? We can assume we are in a city and any oceans adjacent
+ * are connected. */
+ adjc_iterate(punit->tile, tmp_tile) {
+ if (is_ocean(map_get_terrain(tmp_tile))) {
+ my_cont = map_get_continent(tmp_tile);
+ break;
+ }
+ } adjc_iterate_end;
}
- return FALSE;
+
+ if (is_ocean(map_get_terrain(ptile))) {
+ if (ai_channel(pplayer, target_cont, my_cont)) {
+ return TRUE; /* Ocean -> Ocean travel ok. */
+ }
+ } else if ((pcity && pplayers_allied(city_owner(pcity), pplayer))
+ || !unit_flag(punit, F_NO_LAND_ATTACK)) {
+ /* Not ocean, but allied city or can bombard, checking if there is
+ * good ocean adjacent */
+ adjc_iterate(ptile, tmp_tile) {
+ if (is_ocean(map_get_terrain(tmp_tile))
+ && ai_channel(pplayer, my_cont, map_get_continent(tmp_tile))) {
+ return TRUE;
+ }
+ } adjc_iterate_end;
+ }
+ return FALSE; /* Not ok. */
default:
return TRUE;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [freeciv-ai] (PR#9908) Make AI understand channels,
Gregory Berkolaiko <=
|
|