<URL: http://bugs.freeciv.org/Ticket/Display.html?id=20772 >
Updating the patch for S2_1 at revision 13590.
Seulement dans common/aicore.old: aicore
Seulement dans common/aicore: .deps
diff -uad common/aicore.old/path_finding.c common/aicore/path_finding.c
--- common/aicore.old/path_finding.c 2007-09-14 19:20:47.000000000 +0200
+++ common/aicore/path_finding.c 2007-09-14 19:34:11.000000000 +0200
@@ -66,7 +66,7 @@
* from mainstream node.
*/
struct danger_node {
- bool is_dangerous;
+ enum dangerous_level is_dangerous;
bool waited; /* TRUE if waited to get here */
struct pf_danger_pos {
enum direction8 dir;
@@ -498,8 +498,8 @@
pf_map->lattice[pf_map->tile->index].extra_cost = 0;
pf_map->lattice[pf_map->tile->index].dir_to_here = -1;
if (pf_map->params->is_pos_dangerous) {
- /* The starting point is safe */
- pf_map->d_lattice[pf_map->tile->index].is_dangerous = FALSE;
+ /* The starting point cannot be set dangerous */
+ pf_map->d_lattice[pf_map->tile->index].is_dangerous = DL_SAFE;
}
return pf_map;
@@ -833,7 +833,7 @@
}
/* First iteration for determining segment length */
- while(d_node->is_dangerous) {
+ while(d_node->is_dangerous != DL_SAFE) {
length++;
ptile = mapstep(ptile, DIR_REVERSE(node->dir_to_here));
node = &pf_map->lattice[ptile->index];
@@ -864,14 +864,14 @@
}
/* Make sure we reached a safe node */
- assert(!pf_map->d_lattice[ptile->index].is_dangerous);
+ assert(pf_map->d_lattice[ptile->index].is_dangerous == DL_SAFE);
}
/**********************************************************************
Adjust cost taking into account possibility of making the move
**********************************************************************/
-static int danger_adjust_cost(const struct pf_map *pf_map, int cost,
- bool to_danger, int moves_left)
+static int danger_adjust_cost(const struct pf_map *pf_map, int cost,
+ enum dangerous_level to_danger, int moves_left)
{
if (cost == PF_IMPOSSIBLE_MC) {
@@ -881,7 +881,7 @@
cost = MIN(cost, get_move_rate(pf_map->params));
if (pf_map->params->turn_mode == TM_BEST_TIME) {
- if (to_danger && cost >= moves_left) {
+ if (to_danger != DL_SAFE && cost >= moves_left) {
/* We would have to end the turn on a dangerous tile! */
return PF_IMPOSSIBLE_MC;
}
@@ -889,7 +889,7 @@
/* Default is TM_WORST_TIME.
* It should be specified explicitly though! */
if (cost > moves_left
- || (to_danger && cost == moves_left)) {
+ || (to_danger != DL_SAFE && cost == moves_left)) {
/* This move is impossible (at least without waiting)
* or we would end our turn on a dangerous tile */
return PF_IMPOSSIBLE_MC;
@@ -950,8 +950,8 @@
/* Dangerous tiles can be updated even after being processed */
if ((pf_map->status[index1] == NS_PROCESSED
- || pf_map->status[index1] == NS_WAITING)
- && !d_node1->is_dangerous) {
+ || pf_map->status[index1] == NS_WAITING)
+ && d_node1->is_dangerous == DL_SAFE) {
continue;
}
@@ -999,7 +999,7 @@
}
/* Update costs and add to queue, if this is a better route to xy1 */
- if (!d_node1->is_dangerous) {
+ if (d_node1->is_dangerous != DL_DANGEROUS) {
int cost_of_path = get_total_CC(pf_map, cost, extra);
if (pf_map->status[index1] == NS_UNINIT
@@ -1013,7 +1013,7 @@
free(d_node1->danger_segment);
d_node1->danger_segment = NULL;
}
- if (d_node->is_dangerous) {
+ if (d_node->is_dangerous != DL_SAFE) {
/* Transition from red to blue, need to record the path back */
create_danger_segment(pf_map, d_node1);
} else {
@@ -1051,7 +1051,7 @@
adjc_dir_iterate_end;
}
- if (!d_node->is_dangerous
+ if (d_node->is_dangerous == DL_SAFE
&& pf_map->status[pf_map->tile->index] != NS_WAITING
&& (get_moves_left(pf_map, node->cost)
< get_move_rate(pf_map->params))) {
@@ -1086,7 +1086,7 @@
freelog(LOG_DEBUG, "Considering waiting at (%d, %d)",
pf_map->tile->x, pf_map->tile->y);
return danger_iterate_map(pf_map);
- } else if (pf_map->d_lattice[index].is_dangerous) {
+ } else if (pf_map->d_lattice[index].is_dangerous != DL_SAFE) {
/* We don't return dangerous tiles */
freelog(LOG_DEBUG, "Reached dangerous tile (%d, %d)",
pf_map->tile->x, pf_map->tile->y);
@@ -1124,13 +1124,13 @@
/* First iterate to find path length */
while(!same_pos(iter_tile, pf_map->params->start_tile)) {
- if (!d_node->is_dangerous && d_node->waited) {
+ if (d_node->is_dangerous == DL_SAFE && d_node->waited) {
length += 2;
} else {
length++;
}
- if (!d_node->is_dangerous) {
+ if (d_node->is_dangerous != DL_DANGEROUS) {
/* We are in the normal node and dir_to_here field is valid */
dir_next = node->dir_to_here;
/* d_node->danger_segment is the indicator of what lies ahead
@@ -1165,7 +1165,7 @@
bool old_waited = FALSE;
/* 1: Deal with waiting */
- if (!d_node->is_dangerous) {
+ if (d_node->is_dangerous == DL_SAFE) {
if (waited) {
/* Waited at _this_ tile, need to record it twice in the path.
* Here we record our state _after_ waiting (e.g. full move points) */
@@ -1189,7 +1189,7 @@
/* 2: Fill the current position */
path->positions[i].tile = iter_tile;
- if (!d_node->is_dangerous) {
+ if (d_node->is_dangerous != DL_DANGEROUS) {
path->positions[i].total_MC = node->cost;
path->positions[i].total_EC = node->extra_cost;
} else {
@@ -1214,7 +1214,7 @@
}
/* 4: Calculate the next direction */
- if (!d_node->is_dangerous) {
+ if (d_node->is_dangerous != DL_DANGEROUS) {
/* We are in the normal node and dir_to_here field is valid */
dir_next = node->dir_to_here;
/* d_node->danger_segment is the indicator of what lies ahead
@@ -1249,7 +1249,7 @@
utiny_t status = pf_map->status[index];
struct danger_node *d_node = &pf_map->d_lattice[index];
- if (d_node->is_dangerous) {
+ if (d_node->is_dangerous == DL_DANGEROUS) {
/* "Best" path to a dangerous tile is undefined */
/* TODO: return the "safest" path */
return NULL;
diff -uad common/aicore.old/path_finding.h common/aicore/path_finding.h
--- common/aicore.old/path_finding.h 2007-09-14 19:20:47.000000000 +0200
+++ common/aicore/path_finding.h 2007-09-14 19:28:50.000000000 +0200
@@ -285,6 +285,13 @@
TM_WORST_TIME
};
+/* Dangerous level */
+enum dangerous_level {
+ DL_SAFE, /* Safe tile */
+ DL_UNSAFE, /* Not safe, but ok for move */
+ DL_DANGEROUS, /* Not safe and dangerous move */
+};
+
/* Full specification of a position and time to reach it. */
struct pf_position {
struct tile *tile;
@@ -357,11 +364,12 @@
* If this callback is NULL, ZoC are ignored.*/
bool (*get_zoc) (const struct player *pplayer, const struct tile *ptile);
- /* If this callback is non-NULL and returns TRUE this position is
- * dangerous. The unit will never end a turn at a dangerous
- * position. Can be NULL. */
- bool (*is_pos_dangerous) (const struct tile *ptile, enum known_type,
- struct pf_parameter * param);
+ /* If this callback is non-NULL and returns DL_DANGEROUS this position is
+ * dangerous. If the position is safe, it returns DL_SAFE, else DL_UNSAFE.
+ * The unit will never end a turn at a dangerous position. Can be NULL. */
+ enum dangerous_level (*is_pos_dangerous) (const struct tile *ptile,
+ enum known_type,
+ struct pf_parameter * param);
/* This is a jumbo callback which overrides all previous ones. It takes
* care of everything (ZOC, known, costs etc).
diff -uad common/aicore.old/pf_tools.c common/aicore/pf_tools.c
--- common/aicore.old/pf_tools.c 2007-09-14 19:20:47.000000000 +0200
+++ common/aicore/pf_tools.c 2007-09-14 19:28:34.000000000 +0200
@@ -510,57 +510,90 @@
Allow one move onto land (for use for ferries and land
bombardment)
***********************************************************************/
-static bool trireme_is_pos_dangerous(const struct tile *ptile,
- enum known_type known,
- struct pf_parameter *param)
+static enum dangerous_level trireme_is_pos_dangerous(const struct tile *ptile,
+ enum known_type known,
+ struct pf_parameter *param)
{
/* Assume that unknown tiles are unsafe. */
if (known == TILE_UNKNOWN) {
- return TRUE;
+ return DL_DANGEROUS;
}
/* We test TER_UNSAFE even though under the current ruleset there is no
* way for a trireme to be on a TER_UNSAFE tile. */
/* Unsafe or unsafe-ocean tiles without cities are dangerous. */
/* Pretend all land tiles are safe. */
- return (ptile->city == NULL
- && is_ocean(ptile->terrain)
- && (terrain_has_flag(ptile->terrain, TER_UNSAFE)
- || (is_ocean(ptile->terrain) && !is_safe_ocean(ptile))));
+ if (!tile_get_city(ptile)
+ && (terrain_has_flag(ptile->terrain, TER_UNSAFE)
+ || (is_ocean(ptile->terrain) && !is_safe_ocean(ptile)))) {
+ return DL_DANGEROUS;
+ }
+ return DL_SAFE;
+}
+
+/****************************************************************************
+ Check if there is a safe position to move.
+****************************************************************************/
+static bool is_there_safe_pos_near(const struct tile *src_tile,
+ struct player *pplayer, int max_moves)
+{
+ square_iterate(src_tile, max_moves / SINGLE_MOVE, ptile) {
+ if (tile_get_known(ptile, pplayer) != TILE_KNOWN) {
+ /* Cannot guess if the tile is safe */
+ continue;
+ }
+ if (is_allied_city_tile(ptile, pplayer)
+ || tile_has_special(ptile, S_AIRBASE)) {
+ return TRUE;
+ }
+ } square_iterate_end;
+
+ return FALSE;
}
+
/****************************************************************************
Position-dangerous callback for air units.
****************************************************************************/
-static bool air_is_pos_dangerous(const struct tile *ptile,
- enum known_type known,
- struct pf_parameter *param)
+static enum dangerous_level air_is_pos_dangerous(const struct tile *ptile,
+ enum known_type known,
+ struct pf_parameter *param)
{
- int moves = SINGLE_MOVE * real_map_distance(param->start_tile, ptile);
- int fuel = param->fuel_left_initially - 1;
+ int moves_left;
+ bool is_enemy_tile;
if (is_allied_city_tile(ptile, param->owner)) {
- return FALSE;
+ return DL_SAFE;
}
if (tile_has_special(ptile, S_AIRBASE)) {
/* All airbases are considered non-dangerous, although non-allied ones
* are inaccessible. */
- return FALSE;
+ return DL_SAFE;
}
- if (param->moves_left_initially + param->move_rate * fuel >= moves * 2) {
- if (param->fuel_left_initially > 1
- || ((param->fuel_left_initially > 2
- || !BV_ISSET(param->unit_flags, F_ONEATTACK))
- && (is_enemy_unit_tile(ptile, param->owner)
- || (ptile->city && is_enemy_city_tile(ptile, param->owner))))) {
- /* allow movement if fuelled, and attacks, even suicidal ones */
- return FALSE;
+ moves_left = param->moves_left_initially
+ + param->move_rate * (param->fuel_left_initially - 1)
+ - SINGLE_MOVE * real_map_distance(param->start_tile, ptile);
+ is_enemy_tile = (is_enemy_unit_tile(ptile, param->owner)
+ || (ptile->city && is_enemy_city_tile(ptile, param->owner)));
+
+ if (BV_ISSET(param->unit_flags, F_MISSILE)
+ && moves_left >= 0 && is_enemy_tile) {
+ /* Suicidal attack */
+ return DL_SAFE;
+ }
+
+ if (is_there_safe_pos_near(ptile, param->owner, moves_left)) {
+ if (!BV_ISSET(param->unit_flags, F_ONEATTACK)
+ || param->fuel == 0 || !is_enemy_tile
+ || (param->fuel_left_initially > 1 && moves_left >= param->move_rate)) {
+ /* Safe move or attack */
+ return DL_UNSAFE;
}
}
-
+
/* Carriers are ignored since they are likely to move. */
- return TRUE;
+ return DL_DANGEROUS;
}
/**********************************************************************
@@ -568,35 +601,43 @@
Allow one move onto land (for use for ferries and land
bombardment)
***********************************************************************/
-static bool is_overlap_pos_dangerous(const struct tile *ptile,
- enum known_type known,
- struct pf_parameter *param)
+static enum dangerous_level is_overlap_pos_dangerous(const struct tile *ptile,
+ enum known_type known,
+ struct pf_parameter *param)
{
/* Unsafe tiles without cities are dangerous. */
/* Pretend all land tiles are safe. */
- return (ptile->city == NULL
- && is_ocean(ptile->terrain)
- && terrain_has_flag(ptile->terrain, TER_UNSAFE));
+ if (ptile->city == NULL
+ && is_ocean(ptile->terrain)
+ && terrain_has_flag(ptile->terrain, TER_UNSAFE)) {
+ return DL_DANGEROUS;
+ }
+ return DL_SAFE;
}
/**********************************************************************
Position-dangerous callback for typical units.
***********************************************************************/
-static bool is_pos_dangerous(const struct tile *ptile, enum known_type known,
- struct pf_parameter *param)
+static enum dangerous_level is_pos_dangerous(const struct tile *ptile,
+ enum known_type known,
+ struct pf_parameter *param)
{
/* Unsafe tiles without cities are dangerous. */
- return (ptile->terrain != T_UNKNOWN
- && terrain_has_flag(ptile->terrain, TER_UNSAFE)
- && ptile->city == NULL);
+ if (ptile->terrain != T_UNKNOWN
+ && terrain_has_flag(ptile->terrain, TER_UNSAFE)
+ && ptile->city == NULL) {
+ return DL_DANGEROUS;
+ }
+ return DL_SAFE;
}
/****************************************************************************
Position-dangerous callback for amphibious movement.
****************************************************************************/
-static bool amphibious_is_pos_dangerous(const struct tile *ptile,
- enum known_type known,
- struct pf_parameter *param)
+static enum dangerous_level
+amphibious_is_pos_dangerous(const struct tile *ptile,
+ enum known_type known,
+ struct pf_parameter *param)
{
struct pft_amphibious *amphibious = param->data;
const bool ocean = is_ocean(ptile->terrain);
@@ -607,7 +648,7 @@
} else if (!ocean && amphibious->land.is_pos_dangerous) {
return amphibious->land.is_pos_dangerous(ptile, known, param);
}
- return FALSE;
+ return DL_SAFE;
}
/* ===================== Tools for filling parameters =============== */
@@ -653,7 +694,7 @@
parameter->is_pos_dangerous = NULL;
} else {
/* Otherwise, don't risk fuel loss. */
- parameter->is_pos_dangerous = air_is_pos_dangerous;
+ parameter->is_pos_dangerous = NULL;
parameter->turn_mode = TM_WORST_TIME;
}
break;
Seulement dans common/aicore: .svn
_______________________________________________
Freeciv-dev mailing list
[email protected]
https://mail.gna.org/listinfo/freeciv-dev