Index: server/settlers.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/settlers.c,v retrieving revision 1.156 retrieving revision 1.159 diff -u -r1.156 -r1.159 --- server/settlers.c 18 Dec 2002 17:36:20 -0000 1.156 +++ server/settlers.c 21 Dec 2002 11:33:06 -0000 1.159 @@ -61,16 +61,20 @@ **************************************************************************/ static bool ai_do_build_city(struct player *pplayer, struct unit *punit) { - int x, y; + int x = punit->x; + int y = punit->y; struct packet_unit_request req; struct city *pcity; - req.unit_id=punit->id; - x = punit->x; y = punit->y; /* Trevor Pering points out that punit gets freed */ + + req.unit_id = punit->id; sz_strlcpy(req.name, city_name_suggestion(pplayer, x, y)); - handle_unit_build_city(pplayer, &req); - pcity=map_get_city(x, y); /* so we need to cache x and y for a very short time */ - if (!pcity) + handle_unit_build_city(pplayer, &req); + pcity = map_get_city(x, y); + if (!pcity) { + freelog(LOG_ERROR, "%s: Failed to build city at (%d, %d)", + pplayer->name, x, y); return FALSE; + } /* initialize infrastructure cache for both this city and other cities nearby. This is neccesary to avoid having settlers want to transform @@ -282,8 +286,7 @@ if (trade[i][j] != 0) trade[i][j] += ctrade; else if (road[i][j] != 0) road[i][j] += ctrade; } - } - city_map_checked_iterate_end; + } city_map_checked_iterate_end; if (pcity) { /* quick-n-dirty immigration routine -- Syela */ n = pcity->size; @@ -728,23 +731,6 @@ } /************************************************************************** - simply puts the settler unit into goto -**************************************************************************/ -static void auto_settler_do_goto(struct player *pplayer, struct unit *punit, - int x, int y) -{ - CHECK_MAP_POS(x, y); - punit->goto_dest_x = x; - punit->goto_dest_y = y; - set_unit_activity(punit, ACTIVITY_GOTO); - send_unit_info(NULL, punit); - if (!ai_unit_gothere(punit)) { - UNIT_LOG(LOG_DEBUG, punit, "did settler goto to %s", - get_activity_text(punit->activity)); - } -} - -/************************************************************************** Tries to find a boat for our settler. Requires warmap to be initialized with respect to x, y. cap is the requested capacity on the transport. Note that it may return a transport with less than cap capacity if this @@ -1186,52 +1172,72 @@ } /************************************************************************** - Handles GOTO for settlers. Only ever used in auto_settler_findwork below. + Handles GOTO for settlers. Only ever used in auto_settler_findwork + below. **************************************************************************/ static bool ai_gothere(struct unit *punit, int gx, int gy, struct unit *ferryboat) { struct player *pplayer = unit_owner(punit); - int save_id = punit->id; /* in case unit dies */ - if (!same_pos(gx, gy, punit->x, punit->y)) { - if (!goto_is_sane(punit, gx, gy, TRUE) - || (ferryboat - && goto_is_sane(ferryboat, gx, gy, TRUE) - && (!is_tiles_adjacent(punit->x, punit->y, gx, gy) - || could_unit_move_to_tile(punit, gx, gy) == 0))) { - int x, y; - punit->ai.ferryboat = find_boat(pplayer, &x, &y, 1); /* might need 2 */ - freelog(LOG_DEBUG, "%d@(%d, %d): Looking for BOAT.", - punit->id, punit->x, punit->y); - if (!same_pos(x, y, punit->x, punit->y)) { - auto_settler_do_goto(pplayer, punit, x, y); - if (!player_find_unit_by_id(pplayer, save_id)) return FALSE; /* died */ + if (same_pos(gx, gy, punit->x, punit->y)) { + return TRUE; + } + + /* + * Go by boat if we can't go by foot, or we have already found a boat + * (since boat travel is usually faster). + */ + if (!goto_is_sane(punit, gx, gy, TRUE) + || (ferryboat + && goto_is_sane(ferryboat, gx, gy, TRUE) + && (!is_tiles_adjacent(punit->x, punit->y, gx, gy) + || could_unit_move_to_tile(punit, gx, gy) == 0))) { + int x, y; + + punit->ai.ferryboat = find_boat(pplayer, &x, &y, 1); + /* TODO: check if we found a boat */ + freelog(LOG_DEBUG, "%d@(%d, %d): Looking for BOAT.", + punit->id, punit->x, punit->y); + if (!same_pos(x, y, punit->x, punit->y)) { + if (!ai_unit_goto(punit, x, y)) { + return FALSE; /* died */ } - ferryboat = unit_list_find(&(map_get_tile(punit->x, punit->y)->units), - punit->ai.ferryboat); - punit->goto_dest_x = gx; - punit->goto_dest_y = gy; - if (ferryboat && (ferryboat->ai.passenger == 0 - || ferryboat->ai.passenger == punit->id)) { - freelog(LOG_DEBUG, - "We have FOUND BOAT, %d ABOARD %d@(%d,%d)->(%d,%d).", - punit->id, ferryboat->id, punit->x, punit->y, gx, gy); - set_unit_activity(punit, ACTIVITY_SENTRY); - /* kinda cheating -- Syela */ - ferryboat->ai.passenger = punit->id; - auto_settler_do_goto(pplayer, ferryboat, gx, gy); - set_unit_activity(punit, ACTIVITY_IDLE); - } /* need to zero pass & ferryboat at some point. */ } - if (goto_is_sane(punit, gx, gy, TRUE) - && punit->moves_left > 0 - && (!ferryboat - || (is_tiles_adjacent(punit->x, punit->y, gx, gy) - && could_unit_move_to_tile(punit, gx, gy) != 0))) { - auto_settler_do_goto(pplayer, punit, gx, gy); - if (!player_find_unit_by_id(pplayer, save_id)) return FALSE; /* died */ - punit->ai.ferryboat = 0; + ferryboat = unit_list_find(&(map_get_tile(punit->x, punit->y)->units), + punit->ai.ferryboat); + punit->goto_dest_x = gx; + punit->goto_dest_y = gy; + + if (ferryboat && (ferryboat->ai.passenger == 0 + || ferryboat->ai.passenger == punit->id)) { + UNIT_LOG(LOG_DEBUG, punit, "We have FOUND BOAT %d, ABOARD", + ferryboat->id); + handle_unit_activity_request(punit, ACTIVITY_SENTRY); + ferryboat->ai.passenger = punit->id; + ferryboat->goto_dest_x = gx; + ferryboat->goto_dest_y = gy; + if (!ai_unit_goto(ferryboat, gx, gy)) { + return FALSE; /* died */ + } + handle_unit_activity_request(punit, ACTIVITY_IDLE); + } /* need to zero pass & ferryboat at some point. */ + } + + /* + * Now check if we can walk by foot to our destination + * (possibly exiting our ferry) + */ + if (goto_is_sane(punit, gx, gy, TRUE) + && punit->moves_left > 0 + && (!ferryboat + || (is_tiles_adjacent(punit->x, punit->y, gx, gy) + && could_unit_move_to_tile(punit, gx, gy) != 0))) { + punit->goto_dest_x = gx; + punit->goto_dest_y = gy; + if (!ai_unit_goto(punit, gx, gy)) { + return FALSE; /* died */ } + punit->ai.ferryboat = 0; } return TRUE; @@ -1272,7 +1278,7 @@ } /* Mark the square as taken. */ - if (gx!=-1 && gy!=-1) { + if (gx != -1 && gy != -1) { map_get_tile(gx, gy)->assigned = map_get_tile(gx, gy)->assigned | 1<player_no; } else { @@ -1298,19 +1304,17 @@ } /* If we are at the destination then do the activity. */ - if (punit->ai.control - && punit->moves_left > 0 - && punit->activity == ACTIVITY_IDLE) { - if (same_pos(gx, gy, punit->x, punit->y)) { - if (best_act == ACTIVITY_UNKNOWN) { - remove_city_from_minimap(gx, gy); /* yeah, I know. -- Syela */ - (void) ai_do_build_city(pplayer, punit); - return; - } - set_unit_activity(punit, best_act); - send_unit_info(NULL, punit); + if (punit->moves_left > 0 + && same_pos(gx, gy, punit->x, punit->y)) { + if (best_act == ACTIVITY_UNKNOWN) { + remove_city_from_minimap(gx, gy); /* yeah, I know. -- Syela */ + handle_unit_activity_request(punit, ACTIVITY_IDLE); + (void) ai_do_build_city(pplayer, punit); return; } + handle_unit_activity_request(punit, best_act); + send_unit_info(NULL, punit); + return; } } @@ -1372,12 +1376,15 @@ || unit_flag(punit, F_CITIES))) { freelog(LOG_DEBUG, "%s's settler at (%d, %d) is ai controlled.", pplayer->name, punit->x, punit->y); - if(punit->activity == ACTIVITY_SENTRY) - set_unit_activity(punit, ACTIVITY_IDLE); - if (punit->activity == ACTIVITY_GOTO && punit->moves_left > 0) - set_unit_activity(punit, ACTIVITY_IDLE); - if (punit->activity == ACTIVITY_IDLE) + if (punit->activity == ACTIVITY_SENTRY) { + handle_unit_activity_request(punit, ACTIVITY_IDLE); + } + if (punit->activity == ACTIVITY_GOTO && punit->moves_left > 0) { + handle_unit_activity_request(punit, ACTIVITY_IDLE); + } + if (punit->activity == ACTIVITY_IDLE) { auto_settler_findwork(pplayer, punit); + } freelog(LOG_DEBUG, "Has been processed."); } }