diff -ru freeciv/ai/aiunit.c freeciv+pasky/ai/aiunit.c --- freeciv/ai/aiunit.c Sat Nov 24 00:42:27 2001 +++ freeciv+pasky/ai/aiunit.c Sat Nov 24 21:05:01 2001 @@ -177,24 +177,23 @@ } /************************************************************************** -Explores unknown territory, finds huts. +Handle eXplore mode of a unit - explores unknown territory, finds huts. Returns whether there is any more territory to be explored. **************************************************************************/ -int ai_manage_explorer(struct unit *punit) +int ai_manage_exploring(struct unit *punit) { struct player *pplayer = unit_owner(punit); - int x, y; /* is the position of the unit; updated inside the function */ - int con; /* continent the unit is on */ - struct city *pcity; + int x, y; /* the position of the unit; updated inside the function */ + int continent; /* continent the unit is on */ int id = punit->id; /* we can now die because easy AI may accidently stumble on huts it fuzzily ignored */ - int best_x = -1, best_y = -1; + int best_x = -1, best_y = -1; /* desired destination */ int move_rate = unit_move_rate(punit); - int range; + int range; /* range of unit's vision */ if (unit_profits_of_watchtower(punit) && map_get_tile(punit->x, punit->y)->special & S_FORTRESS) - range =get_watchtower_vision(punit); + range = get_watchtower_vision(punit); else range = unit_type(punit)->vision_range; @@ -202,17 +201,19 @@ handle_unit_activity_request(punit, ACTIVITY_IDLE); x = punit->x; y = punit->y; - if (is_ground_unit(punit)) con = map_get_continent(x, y); - else con = 0; /* Thanks, Tony */ + if (is_ground_unit(punit)) continent = map_get_continent(x, y); + else continent = 0; /* ships don't care about continents */ /* CPU-expensive but worth it -- Syela */ generate_warmap(map_get_city(x, y), punit); - /* BEGIN PART ONE: Look for huts. Non-Barbarian Ground units ONLY. */ + /* PART ONE: Look for huts. + * Non-Barbarian Ground units ONLY. + */ if (!is_barbarian(pplayer) - && is_ground_unit(punit)) { /* boats don't hunt huts */ + && is_ground_unit(punit)) { int maxcost = pplayer->ai.control ? 2 * THRESHOLD : 3; - int bestcost = maxcost * SINGLE_MOVE + 1; + int bestcost = maxcost * SINGLE_MOVE + 1; /* lower is better */ /* Iterating outward so that with two tiles with the same movecost the nearest is used */ @@ -227,6 +228,7 @@ bestcost = warmap.cost[best_x][best_y]; } } iterate_outward_end; + if (bestcost <= maxcost * SINGLE_MOVE) { punit->goto_dest_x = best_x; punit->goto_dest_y = best_y; @@ -235,15 +237,17 @@ if (!player_find_unit_by_id(pplayer, id)) return 0; /* died */ + /* We can still move on.. */ if (punit->moves_left) { + /* ..and we got into desired place. */ if (punit->x == best_x && punit->y == best_y) { - return ai_manage_explorer(punit); + return ai_manage_exploring(punit); } else { /* Something went wrong; fall through. This should almost never happen. */ if (punit->x != x || punit->y != y) generate_warmap(map_get_city(punit->x, punit->y), punit); x = punit->x; y = punit->y; - /* Fallthough to next fase */ + /* Fallthough to next phase */ } } else { return 1; @@ -251,28 +255,34 @@ } } - /* BEGIN PART TWO: Move into unexplored territory */ - /* move the unit as long as moving will unveil unknown territory */ + /* PART TWO: Move into unexplored territory + * Move the unit as long as moving will unveil unknown territory + */ while (punit->moves_left) { - int most_unknown = 0; - int unknown; + int most_unknown = 0; /* max. number of unknown tiles */ /* evaluate all adjacent tiles */ square_iterate(x, y, 1, x1, y1) { - unknown = 0; + int unknown = 0; /* number of unknown tiles reachable from this tile */ + + /* and all tiles in our vision range around them */ square_iterate(x1, y1, range, x2, y2) { if (!map_get_known(x2, y2, pplayer)) unknown++; } square_iterate_end; + /* We have to be careful with triremes, we won't travel to + * another continents, won't travel into cities (unless we + * are able to do so - diplomats and caravans can) and we + * won't raze huts if we are barbarians. + */ if (unknown > most_unknown && (!unit_flag(punit, F_TRIREME) || trireme_loss_pct(pplayer, x1, y1) == 0) - && map_get_continent(x1, y1) == con + && map_get_continent(x1, y1) == continent && can_unit_move_to_tile_with_notify(punit, x1, y1, 0) - && !((pcity = map_get_city(x1,y1)) - && (unit_flag(punit, F_DIPLOMAT) - || unit_flag(punit, F_CARAVAN))) + && !(map_get_city(x1,y1) && + (unit_flag(punit, F_DIPLOMAT) || unit_flag(punit, F_CARAVAN))) && !(is_barbarian(pplayer) && map_get_special(x1, y1) & S_HUT)) { most_unknown = unknown; best_x = x1; @@ -280,43 +290,55 @@ } } square_iterate_end; - if (most_unknown > 0) { /* a tile have unexplored territory adjacent */ + /* a tile have unexplored territory adjectent, move there */ + if (most_unknown > 0) { int res = handle_unit_move_request(punit, best_x, best_y, FALSE, FALSE); if (!res) /* This shouldn't happen */ break; + if (!player_find_unit_by_id(pplayer, id)) return 0; /* died */ x = punit->x; y = punit->y; } else { - break; + break; /* we explored everything */ } } if (!punit->moves_left) return 1; - /* BEGIN PART THREE: Go towards unexplored territory */ - /* no adjacent squares help us to explore - really slow part follows */ + /* PART THREE: Go towards unexplored territory + * No adjacent squares help us to explore - really slow part follows + */ generate_warmap(map_get_city(x, y), punit); { - int unknown, most_unknown = 0; - int threshold = THRESHOLD * move_rate; + int most_unknown = 0; /* max. number of unknown tiles */ + whole_map_iterate(x1, y1) { struct tile *ptile = map_get_tile(x1, y1); - unknown = 0; - if (ptile->continent == con + int threshold = THRESHOLD * move_rate; + int unknown = 0; /* number of unknown tiles reachable from this tile */ + + /* We won't travel to another continents or into foreign occupied squares. */ + if (ptile->continent == continent && !is_non_allied_unit_tile(ptile, pplayer) && !is_non_allied_city_tile(ptile, pplayer) && tile_is_accessible(punit, x1, y1)) { + + /* evaluate all tiles in our vision range around this tile */ square_iterate(x1, y1, range, x2, y2) { if (!map_get_known(x2, y2, pplayer)) unknown++; } square_iterate_end; + if (unknown) { + /* also care about how fast we can get there */ if (is_sailing_unit(punit)) unknown += 9 * (threshold - warmap.seacost[x1][y1]); else unknown += 9 * (threshold - warmap.cost[x1][y1]); + + /* We won't raze huts if we are barbarians. */ if ((unknown > most_unknown || (unknown == most_unknown && myrand(2))) && !(is_barbarian(pplayer) && ptile->special & S_HUT)) { best_x = x1; @@ -327,41 +349,59 @@ } } whole_map_iterate_end; + /* a tile have unexplored territory adjectent, move there */ if (most_unknown > 0) { punit->goto_dest_x = best_x; punit->goto_dest_y = best_y; handle_unit_activity_request(punit, ACTIVITY_GOTO); do_unit_goto(punit, GOTO_MOVE_ANY, 0); + + /* We can still move on.. */ if (punit->moves_left) { - if (punit->x != best_x || punit->y != best_y) { + /* ..and we got into desired place. */ + if (punit->x == best_x || punit->y == best_y) { + return ai_manage_exploring(punit); + } else { + /* Something wrong; what to do but go idle and return? */ handle_unit_activity_request(punit, ACTIVITY_IDLE); - return 1; /* Something wrong; what to do but return? */ - } else - return ai_manage_explorer(punit); + return 1; + } } else { return 1; } } /* no candidates; fall-through */ } - /* BEGIN PART FOUR: maybe go to another continent */ + /* We have nothing to explore, so we can go idle. */ freelog(LOG_DEBUG, "%s's %s at (%d,%d) failed to explore.", pplayer->name, unit_type(punit)->name, punit->x, punit->y); handle_unit_activity_request(punit, ACTIVITY_IDLE); + + /* PART FOUR: Go home + * If we are AI controlled _military_ unit, we will return to + * our homecity, maybe even to another continent. + */ if (pplayer->ai.control && is_military_unit(punit)) { + struct city *pcity; + + /* If we have a homecity.. */ pcity = find_city_by_id(punit->homecity); - if (pcity && map_get_continent(pcity->x, pcity->y) == con) - ai_military_gohome(pplayer, punit); - else if (pcity) { - if (!find_boat(pplayer, &x, &y, 0)) /* Gilligan's Island */ - punit->ai.ferryboat = -1; + if (pcity) { + if (map_get_continent(pcity->x, pcity->y) == continent) + ai_military_gohome(pplayer, punit); else { - punit->goto_dest_x = x; - punit->goto_dest_y = y; - do_unit_goto(punit, GOTO_MOVE_ANY, 0); + /* Sea travel */ + if (!find_boat(pplayer, &x, &y, 0)) /* Gilligan's Island */ + punit->ai.ferryboat = -1; /* We are out of luck */ + else { + punit->goto_dest_x = x; + punit->goto_dest_y = y; + do_unit_goto(punit, GOTO_MOVE_ANY, 0); + } } } } + return 0; } @@ -1498,7 +1538,7 @@ if (find_nearest_friendly_port(punit)) do_unit_goto(punit, GOTO_MOVE_ANY, 0); } else { - ai_manage_explorer(punit); /* nothing else to do */ + ai_manage_exploring(punit); /* nothing else to do */ /* you can still have some moves left here, but barbarians should not sit helplessly, but advance towards nearest known enemy city */ punit = find_unit_by_id(id); /* unit might die while exploring */ @@ -1658,7 +1698,7 @@ freelog(LOG_DEBUG, "Ferryboat %d@(%d,%d) stalling.", punit->id, punit->x, punit->y); if(is_barbarian(pplayer)) /* just in case */ - ai_manage_explorer(punit); + ai_manage_exploring(punit); } return; } @@ -1724,7 +1764,7 @@ } } if (map_get_terrain(punit->x, punit->y) == T_OCEAN) /* thanks, Tony */ - ai_manage_explorer(punit); + ai_manage_exploring(punit); return; } @@ -1782,7 +1822,7 @@ return; /* when you pillage, you have moves left, avoid later fortify */ break; case AIUNIT_EXPLORE: - ai_manage_explorer(punit); + ai_manage_exploring(punit); break; default: abort(); @@ -1879,7 +1919,7 @@ return; } else { if (!punit->moves_left) return; /* can't do anything with no moves */ - ai_manage_explorer(punit); /* what else could this be? -- Syela */ + ai_manage_exploring(punit); /* what else could this be? -- Syela */ return; } /* should never get here */ diff -ru freeciv/ai/aiunit.h freeciv+pasky/ai/aiunit.h --- freeciv/ai/aiunit.h Wed Jan 10 19:50:45 2001 +++ freeciv+pasky/ai/aiunit.h Sat Nov 24 21:05:01 2001 @@ -23,7 +23,7 @@ int look_for_charge(struct player *pplayer, struct unit *punit, struct unit **aunit, struct city **acity); -int ai_manage_explorer(struct unit *punit); +int ai_manage_exploring(struct unit *punit); int find_something_to_kill(struct player *pplayer, struct unit *punit, int *x, int *y); diff -ru freeciv/server/unithand.c freeciv+pasky/server/unithand.c --- freeciv/server/unithand.c Tue Oct 30 11:37:17 2001 +++ freeciv+pasky/server/unithand.c Sat Nov 24 21:06:15 2001 @@ -1256,8 +1256,8 @@ case ACTIVITY_EXPLORE: if (punit->moves_left > 0) { int id = punit->id; - int more_to_explore = ai_manage_explorer(punit); - /* ai_manage_explorer sets the activity to idle, so we reset it */ + int more_to_explore = ai_manage_exploring(punit); + /* ai_manage_exploring sets the activity to idle, so we reset it */ if (more_to_explore && (punit = find_unit_by_id(id))) { set_unit_activity(punit, ACTIVITY_EXPLORE); send_unit_info(0, punit); diff -ru freeciv/server/unittools.c freeciv+pasky/server/unittools.c --- freeciv/server/unittools.c Mon Nov 12 18:34:12 2001 +++ freeciv+pasky/server/unittools.c Sat Nov 24 21:06:26 2001 @@ -803,7 +803,7 @@ } if (activity == ACTIVITY_EXPLORE) { - int more_to_explore = ai_manage_explorer(punit); + int more_to_explore = ai_manage_exploring(punit); if (more_to_explore && player_find_unit_by_id(pplayer, id)) handle_unit_activity_request(punit, ACTIVITY_EXPLORE); else