<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 Freeciv-dev@gna.org https://mail.gna.org/listinfo/freeciv-dev