Index: ai/aitools.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/ai/aitools.c,v retrieving revision 1.62 diff -u -r1.62 aitools.c --- ai/aitools.c 14 Nov 2002 09:14:50 -0000 1.62 +++ ai/aitools.c 23 Nov 2002 00:20:04 -0000 @@ -112,6 +112,76 @@ } /************************************************************************** + This will eventually become the ferry-enabled goto. For now, it just + wraps ai_unit_goto() +**************************************************************************/ +bool ai_unit_gothere(struct unit *punit) +{ + assert(punit->goto_dest_x != -1 && punit->goto_dest_y != -1); + if (ai_unit_goto(punit, punit->goto_dest_x, punit->goto_dest_y)) { + return TRUE; /* ... and survived */ + } else { + return FALSE; /* we died */ + } +} + +/************************************************************************** + Go to specified destination but do not disturb existing role or activity + and do not clear the role's destination. Return FALSE iff we died. + + FIXME: add some logging functionality to replace GOTO_LOG() +**************************************************************************/ +bool ai_unit_goto(struct unit *punit, int x, int y) +{ + enum goto_result result; + int oldx = punit->goto_dest_x, oldy = punit->goto_dest_y; + enum unit_activity activity = punit->activity; + + /* log error on same_pos with punit->x|y */ + punit->goto_dest_x = x; + punit->goto_dest_y = y; + handle_unit_activity_request(punit, ACTIVITY_GOTO); + result = do_unit_goto(punit, GOTO_MOVE_ANY, FALSE); + handle_unit_activity_request(punit, activity); + punit->goto_dest_x = oldx; + punit->goto_dest_y = oldy; + + return (result != GR_DIED); +} + +/************************************************************************** + Check if unit can move to (x, y) without lifting current activity. +**************************************************************************/ +bool ai_unit_can_move(struct unit *punit, int x, int y) +{ + enum unit_activity activity = punit->activity; + bool can_move; + bool igzoc = unit_flag(punit, F_IGZOC); + + punit->activity = ACTIVITY_IDLE; + can_move = can_unit_move_to_tile(punit, x, y, igzoc); + punit->activity = activity; + + return can_move; +} + +/************************************************************************** + Check if unit can attack to (x, y) without lifting current activity. + This also involves checking if we can move there! +**************************************************************************/ +bool ai_unit_can_attack(struct unit *patt, int x, int y) +{ + enum unit_activity activity = patt->activity; + bool can_attack; + + patt->activity = ACTIVITY_IDLE; + can_attack = can_unit_attack_tile(patt, x, y); + patt->activity = activity; + + return can_attack; +} + +/************************************************************************** Ensure unit sanity by telling charge that we won't bodyguard it anymore, add and remove city spot reservation, and set destination. **************************************************************************/ Index: ai/aitools.h =================================================================== RCS file: /home/freeciv/CVS/freeciv/ai/aitools.h,v retrieving revision 1.29 diff -u -r1.29 aitools.h --- ai/aitools.h 15 Nov 2002 22:15:01 -0000 1.29 +++ ai/aitools.h 23 Nov 2002 00:20:04 -0000 @@ -32,9 +32,14 @@ void destroy_unit_virtual(struct unit *punit); int is_stack_vulnerable(int x, int y); +bool ai_unit_gothere(struct unit *punit); +bool ai_unit_goto(struct unit *punit, int x, int y); void ai_unit_new_role(struct unit *punit, enum ai_unit_task task, int x, int y); + bool ai_unit_make_homecity(struct unit *punit, struct city *pcity); +bool ai_unit_can_attack(struct unit *patt, int x, int y); void ai_unit_attack(struct unit *punit, int x, int y); +bool ai_unit_can_move(struct unit *punit, int x, int y); bool ai_unit_move(struct unit *punit, int x, int y); struct city *dist_nearest_city(struct player *pplayer, int x, int y, Index: ai/aiunit.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/ai/aiunit.c,v retrieving revision 1.229 diff -u -r1.229 aiunit.c --- ai/aiunit.c 14 Nov 2002 09:14:50 -0000 1.229 +++ ai/aiunit.c 23 Nov 2002 00:20:04 -0000 @@ -332,20 +332,11 @@ } iterate_outward_end; if (bestcost <= maxmoves * SINGLE_MOVE) { - enum goto_result result; - /* Go there! */ - punit->goto_dest_x = best_x; - punit->goto_dest_y = best_y; - set_unit_activity(punit, ACTIVITY_GOTO); - result = do_unit_goto(punit, GOTO_MOVE_ANY, FALSE); - if (result == GR_DIED) { + if (!ai_unit_goto(punit, best_x, best_y)) { /* We're dead. */ return FALSE; } - GOTO_LOG(LOG_DEBUG, punit, result, "exploring huts"); - - /* TODO: Take more advantage from the do_unit_goto() return value. */ if (punit->moves_left > 0) { /* We can still move on... */ @@ -400,7 +391,7 @@ if (map_get_continent(x1, y1) != continent) continue; - if (!can_unit_move_to_tile(punit, x1, y1, FALSE)) + if (!ai_unit_can_move(punit, x1, y1)) continue; /* We won't travel into cities, unless we are able to do so - diplomats @@ -511,19 +502,10 @@ } whole_map_iterate_end; if (most_unknown > 0) { - enum goto_result result; - /* Go there! */ - punit->goto_dest_x = best_x; - punit->goto_dest_y = best_y; - handle_unit_activity_request(punit, ACTIVITY_GOTO); - result = do_unit_goto(punit, GOTO_MOVE_ANY, FALSE); - if (result == GR_DIED) { + if (!ai_unit_goto(punit, best_x, best_y)) { return FALSE; } - GOTO_LOG(LOG_DEBUG, punit, result, "exploring territory"); - - /* TODO: Take more advantage from the do_unit_goto() return value. */ if (punit->moves_left > 0) { /* We can still move on... */ @@ -574,9 +556,7 @@ ai_military_gohome(pplayer, punit); } else { /* Also try take care of deliberately homeless units */ - punit->goto_dest_x = pcity->x; - punit->goto_dest_y = pcity->y; - (void) do_unit_goto(punit, GOTO_MOVE_ANY, FALSE); + (void) ai_unit_goto(punit, pcity->x, pcity->y); } } else { /* Sea travel */ @@ -585,12 +565,8 @@ UNIT_LOG(LOG_DEBUG, punit, "exploring unit wants a boat, going home"); ai_military_gohome(pplayer, punit); /* until then go home */ } else { - enum goto_result result; UNIT_LOG(LOG_DEBUG, punit, "sending explorer home by boat"); - punit->goto_dest_x = x; - punit->goto_dest_y = y; - result = do_unit_goto(punit, GOTO_MOVE_ANY, FALSE); - GOTO_LOG(LOG_DEBUG, punit, result, "explorer sail home"); + (void) ai_unit_goto(punit, x, y); } } } @@ -774,7 +750,6 @@ int which) { int x, y; - bool want_attack = (dest || punit->activity != ACTIVITY_GOTO); if (dest) { x = punit->goto_dest_x; @@ -789,7 +764,7 @@ if (pcity && pplayers_at_war(city_owner(pcity), unit_owner(punit)) && (pcity->ai.invasion & which) != which - && (want_attack || !has_defense(pcity))) { + && (dest || !has_defense(pcity))) { pcity->ai.invasion |= which; } } square_iterate_end; @@ -900,8 +875,9 @@ unit_list_iterate(ptile->units, aunit) { if (aunit == punit || aunit->owner != punit->owner) continue; - if (!can_unit_attack_unit_at_tile(aunit, pdef, pdef->x, pdef->y)) + if (!ai_unit_can_attack(aunit, pdef->x, pdef->y)) { continue; + } d = get_virtual_defense_power(aunit->type, pdef->type, pdef->x, pdef->y, FALSE, FALSE); if (d == 0) @@ -967,7 +943,7 @@ if (pdef) { struct unit *patt = get_attacker(punit, x1, y1); - if (!can_unit_attack_tile(punit, x1, y1)) { + if (!ai_unit_can_attack(punit, x1, y1)) { continue; } @@ -1117,13 +1093,7 @@ if (!same_pos(punit->x, punit->y, x, y)) { if (goto_is_sane(punit, x, y, TRUE)) { - enum goto_result result; - punit->goto_dest_x = x; - punit->goto_dest_y = y; - result = do_unit_goto(punit, GOTO_MOVE_ANY, FALSE); - if (result != GR_DIED) { - GOTO_LOG(LOGLEVEL_BODYGUARD, punit, result, "bodyguard meet"); - } + (void) ai_unit_goto(punit, x, y); } else { /* can't possibly get there to help */ ai_unit_new_role(punit, AIUNIT_NONE, -1, -1); @@ -1269,10 +1239,7 @@ freelog(LOG_DEBUG, "%s: %d@(%d, %d): Looking for BOAT (id=%d).", pplayer->name, punit->id, punit->x, punit->y, boatid); if (!same_pos(x, y, bx, by)) { - punit->goto_dest_x = bx; - punit->goto_dest_y = by; - set_unit_activity(punit, ACTIVITY_GOTO); - if (do_unit_goto(punit, GOTO_MOVE_ANY, FALSE) == GR_DIED) { + if (!ai_unit_goto(punit, bx, by)) { return -1; /* died */ } } @@ -1288,7 +1255,6 @@ /* the code that worked for settlers wasn't good for piles of cannons */ if (find_beachhead(punit, dest_x, dest_y, &ferryboat->goto_dest_x, &ferryboat->goto_dest_y) != 0) { -/* set_unit_activity(ferryboat, ACTIVITY_GOTO); -- Extremely bad!! -- Syela */ punit->goto_dest_x = dest_x; punit->goto_dest_y = dest_y; set_unit_activity(punit, ACTIVITY_SENTRY); /* anything but GOTO!! */ @@ -1303,7 +1269,7 @@ if (def) set_unit_activity(def, ACTIVITY_SENTRY); } unit_list_iterate_end; /* passengers are safely stowed away */ - if (do_unit_goto(ferryboat, GOTO_MOVE_ANY, FALSE) == GR_DIED) { + if (!ai_unit_goto(ferryboat, dest_x, dest_y)) { return -1; /* died */ } set_unit_activity(punit, ACTIVITY_IDLE); @@ -1349,8 +1315,7 @@ unit_type(punit)->name, punit->id, punit->x, punit->y, dest_x, dest_y); } - set_unit_activity(punit, ACTIVITY_GOTO); - if (do_unit_goto(punit, GOTO_MOVE_ANY, FALSE) == GR_DIED) { + if (!ai_unit_goto(punit, dest_x, dest_y)) { return -1; /* died */ } /* liable to bump into someone that will kill us. Should avoid? */ @@ -1587,12 +1552,8 @@ /* aggro defense goes here -- Syela */ punit = ai_military_rampage(punit, 2); /* 2 is better than pillage */ } else { - freelog(LOG_DEBUG, "GOHOME(%d,%d)", - punit->goto_dest_x, punit->goto_dest_y); - punit->goto_dest_x=pcity->x; - punit->goto_dest_y=pcity->y; - set_unit_activity(punit, ACTIVITY_GOTO); - (void) do_unit_goto(punit, GOTO_MOVE_ANY, FALSE); + UNIT_LOG(LOG_DEBUG, punit, "GOHOME"); + (void) ai_unit_goto(punit, pcity->x, pcity->y); } } else { handle_unit_activity_request(punit, ACTIVITY_FORTIFYING); @@ -1964,7 +1925,6 @@ int dest_x, dest_y; int id = punit->id; int ct = 10; - bool igzoc = unit_flag(punit, F_IGZOC); assert(punit != NULL); if (punit->activity == ACTIVITY_GOTO) { @@ -1992,8 +1952,8 @@ while (repeat < 2) { repeat++; if (!is_tiles_adjacent(punit->x, punit->y, dest_x, dest_y) - || !can_unit_attack_tile(punit, dest_x, dest_y) - || !can_unit_move_to_tile(punit, dest_x, dest_y, igzoc)) { + || !ai_unit_can_attack(punit, dest_x, dest_y) + || !ai_unit_can_move(punit, dest_x, dest_y)) { /* Can't attack or move usually means we are adjacent but * on a ferry. This fixes the problem (usually). */ int i = ai_military_gothere(pplayer, punit, dest_x, dest_y); @@ -2030,7 +1990,7 @@ if (is_sailing_unit(punit) && find_nearest_friendly_port(punit)) { /* Sail somewhere */ - (void) do_unit_goto(punit, GOTO_MOVE_ANY, FALSE); + (void) ai_unit_gothere(punit); } else if (!is_barbarian(pplayer)) { /* Nothing else to do. Worst case, this function will send us back home */ @@ -2082,10 +2042,10 @@ && unit_flag(punit, F_HELP_WONDER) && build_points_left(pcity) > (pcity->shield_surplus * 2)) { if (!same_pos(pcity->x, pcity->y, punit->x, punit->y)) { - if (punit->moves_left == 0) + if (punit->moves_left == 0) { return; - auto_settler_do_goto(pplayer, punit, pcity->x, pcity->y); - handle_unit_activity_request(punit, ACTIVITY_IDLE); + } + (void) ai_unit_goto(punit, pcity->x, pcity->y); } else { /* * We really don't want to just drop all caravans in immediately. @@ -2119,8 +2079,10 @@ if (pcity) { if (!same_pos(pcity->x, pcity->y, punit->x, punit->y)) { - if (punit->moves_left == 0) return; - auto_settler_do_goto(pplayer, punit, pcity->x, pcity->y); + if (punit->moves_left == 0) { + return; + } + (void) ai_unit_goto(punit, pcity->x, pcity->y); } else { req.unit_id = punit->id; req.city_id = pcity->id; @@ -2170,12 +2132,12 @@ if (p != 0) { freelog(LOG_DEBUG, "%s#%d@(%d,%d), p=%d, n=%d", unit_name(punit->type), punit->id, punit->x, punit->y, p, n); - if (punit->moves_left > 0 && n != 0) - (void) do_unit_goto(punit, GOTO_MOVE_ANY, FALSE); - else if (n == 0 && !map_get_city(punit->x, punit->y)) { /* rest in a city, for unhap */ + if (punit->moves_left > 0 && n != 0) { + (void) ai_unit_gothere(punit); + } else if (n == 0 && !map_get_city(punit->x, punit->y)) { /* rest in a city, for unhap */ x = punit->goto_dest_x; y = punit->goto_dest_y; if (find_nearest_friendly_port(punit) - && do_unit_goto(punit, GOTO_MOVE_ANY, FALSE) == GR_DIED) { + && !ai_unit_gothere(punit)) { return; /* oops! */ } punit->goto_dest_x = x; punit->goto_dest_y = y; @@ -2230,12 +2192,9 @@ /* Pickup is within 4 turns to grab, so move it! */ punit->goto_dest_x = x; punit->goto_dest_y = y; - set_unit_activity(punit, ACTIVITY_GOTO); UNIT_LOG(LOG_DEBUG, punit, "Found a friend and going to him @(%d, %d)", x, y); - if (do_unit_goto(punit, GOTO_MOVE_ANY, FALSE) != GR_DIED) { - set_unit_activity(punit, ACTIVITY_IDLE); - } + (void) ai_unit_gothere(punit); return; } @@ -2248,9 +2207,8 @@ unit_move_turns(punit, pcity->x, pcity->y) < p) { punit->goto_dest_x = pcity->x; punit->goto_dest_y = pcity->y; - set_unit_activity(punit, ACTIVITY_GOTO); UNIT_LOG(LOG_DEBUG, punit, "No friends. Going home."); - (void) do_unit_goto(punit, GOTO_MOVE_ANY, FALSE); + (void) ai_unit_gothere(punit); return; } } @@ -2648,7 +2606,7 @@ pdiplomat->goto_dest_x=ctarget->x; pdiplomat->goto_dest_y=ctarget->y; set_unit_activity(pdiplomat, ACTIVITY_GOTO); - (void) do_unit_goto(pdiplomat, GOTO_MOVE_ANY, FALSE); + (void) ai_unit_gothere(pdiplomat); /* whatever */ } } } @@ -2692,8 +2650,7 @@ && !same_pos(closest_unit->x, closest_unit->y, leader->x, leader->y) && (map_get_continent(leader->x, leader->y) == map_get_continent(closest_unit->x, closest_unit->y))) { - auto_settler_do_goto(pplayer, leader, closest_unit->x, closest_unit->y); - handle_unit_activity_request(leader, ACTIVITY_IDLE); + (void) ai_unit_goto(leader, closest_unit->x, closest_unit->y); return; /* sticks better to own units with this -- jk */ } @@ -2743,7 +2700,7 @@ square_iterate(leader->x, leader->y, 1, x, y) { if (warmap.cost[x][y] > safest - && can_unit_move_to_tile(leader, x, y, FALSE)) { + && ai_unit_can_move(leader, x, y)) { safest = warmap.cost[x][y]; freelog(LOG_DEBUG, "Barbarian leader: safest is %d, %d, safeness %d", x, y, @@ -2763,7 +2720,7 @@ freelog(LOG_DEBUG, "Fleeing to %d, %d.", safest_x, safest_y); last_x = leader->x; last_y = leader->y; - auto_settler_do_goto(pplayer, leader, safest_x, safest_y); + (void) ai_unit_goto(leader, safest_x, safest_y); if (same_pos(leader->x, leader->y, last_x, last_y)) { /* Deep inside the goto handling code, in server/unithand.c::handle_unite_move_request(), the server