diff -Nur -X/home/thue/freeciv-dev/no.freeciv transfer_problems/server/citytools.c transfer_problems2/server/citytools.c --- transfer_problems/server/citytools.c Mon Apr 10 18:25:18 2000 +++ transfer_problems2/server/citytools.c Mon Apr 10 21:05:28 2000 @@ -696,23 +696,22 @@ * there must be a similar function somewhere, I just can't find it. * * - Kris Bubendorfer + * + * returns NULL if no satisfactory city can be found. */ -struct city *find_closest_owned_city(struct player *pplayer, int x, int y) +struct city *find_closest_owned_city(struct player *pplayer, int x, int y, int sea_required) { - int dist; - struct city *rcity = city_list_get(&pplayer->cities, 0); - - if(rcity){ - dist = real_map_distance(x, y, rcity->x, rcity->y); - - city_list_iterate(pplayer->cities, pcity) - if (real_map_distance(x, y, pcity->x, pcity->y) < dist){ - dist = real_map_distance(x, y, pcity->x, pcity->y); - rcity = pcity; - } - city_list_iterate_end; - } + int dist = -1; + struct city *rcity = NULL; + city_list_iterate(pplayer->cities, pcity) + if ((real_map_distance(x, y, pcity->x, pcity->y) < dist || dist == -1) && + (!sea_required || is_terrain_near_tile(pcity->x, pcity->y, T_OCEAN))) { + dist = real_map_distance(x, y, pcity->x, pcity->y); + rcity = pcity; + } + city_list_iterate_end; + return rcity; } @@ -1030,10 +1029,14 @@ map_unfog_city_area(pnewcity); + /* We don't want the unit-transfer functions to find old city when iterating */ + city_list_unlink(&game.players[pcity->owner].cities, pcity); transfer_city_units(pplayer, cplayer, pnewcity, pcity, kill_outside, transfer_unit_verbose, resolve_stack); + city_list_insert(&game.players[pcity->owner].cities, pcity); + remove_city(pcity); - map_set_city(pnewcity->x, pnewcity->y, pnewcity); + map_set_city(pnewcity->x, pnewcity->y, pnewcity); reestablish_city_trade_routes(pnewcity); city_check_workers(pplayer ,pnewcity); diff -Nur -X/home/thue/freeciv-dev/no.freeciv transfer_problems/server/citytools.h transfer_problems2/server/citytools.h --- transfer_problems/server/citytools.h Mon Apr 10 18:21:10 2000 +++ transfer_problems2/server/citytools.h Mon Apr 10 18:33:51 2000 @@ -65,7 +65,7 @@ struct city *transfer_city(struct player *pplayer, struct player *cplayer, struct city *pcity, int kill_outside, int transfer_unit_verbose, int resolve_stack); -struct city *find_closest_owned_city(struct player *pplayer, int x, int y); +struct city *find_closest_owned_city(struct player *pplayer, int x, int y, int sea_required); void adjust_city_free_cost(int *num_free, int *this_cost); diff -Nur -X/home/thue/freeciv-dev/no.freeciv transfer_problems/server/unitfunc.c transfer_problems2/server/unitfunc.c --- transfer_problems/server/unitfunc.c Mon Apr 10 18:21:11 2000 +++ transfer_problems2/server/unitfunc.c Mon Apr 10 18:34:30 2000 @@ -1146,7 +1146,7 @@ maybe_make_veteran (pdiplomat); /* being teleported costs all movement */ - if (!teleport_unit_to_city (pdiplomat, spyhome, -1)) { + if (!teleport_unit_to_city (pdiplomat, spyhome, -1, 0)) { send_unit_info (pplayer, pdiplomat); freelog (LOG_NORMAL, "Bug in diplomat_escape: Spy can't teleport."); return; diff -Nur -X/home/thue/freeciv-dev/no.freeciv transfer_problems/server/unittools.c transfer_problems2/server/unittools.c --- transfer_problems/server/unittools.c Mon Apr 10 18:29:28 2000 +++ transfer_problems2/server/unittools.c Mon Apr 10 21:12:34 2000 @@ -693,8 +693,7 @@ (If specified cost is <0, then teleportation costs all movement.) - Kris Bubendorfer **************************************************************************/ - -int teleport_unit_to_city(struct unit *punit, struct city *pcity, int mov_cost) +int teleport_unit_to_city(struct unit *punit, struct city *pcity, int mov_cost, int verbose) { int src_x = punit->x,src_y = punit->y; if(pcity->owner == punit->owner){ @@ -710,6 +709,15 @@ unit_list_insert(&map_get_tile(pcity->x, pcity->y)->units, punit); send_unit_info_to_onlookers(0, punit, src_x,src_y); + freelog(LOG_VERBOSE, "Teleported %s's %s from (%d, %d) to %s", + get_player(punit->owner)->name, unit_name(punit->type), + src_x, src_y, pcity->name); + if (verbose) { + notify_player(get_player(punit->owner), + _("Game: Teleported your %s from (%d, %d) to %s."), + unit_name(punit->type), src_x, src_y, pcity->name); + } + return 1; } return 0; @@ -730,73 +738,59 @@ If verbose is true, the unit owner gets messages about where each units goes. --dwp **************************************************************************/ - void resolve_unit_stack(int x, int y, int verbose) { struct unit *punit, *cunit; - - punit = unit_list_get(&map_get_tile(x, y)->units, 0); - if (!punit) - return; - cunit = is_enemy_unit_on_tile(x, y, punit->owner); - - while(punit && cunit){ - struct city *pcity = find_closest_owned_city(get_player(punit->owner), x, y); - struct city *ccity = find_closest_owned_city(get_player(cunit->owner), x, y); - - if(map_distance(x, y, pcity->x, pcity->y) - < map_distance(x, y, ccity->x, ccity->y)){ - teleport_unit_to_city(cunit, ccity, 0); - freelog(LOG_VERBOSE, "Teleported %s's %s from (%d, %d) to %s", - get_player(cunit->owner)->name, unit_name(cunit->type), - x, y,ccity->name); - if (verbose) { - notify_player(get_player(cunit->owner), - _("Game: Teleported your %s from (%d, %d) to %s."), - unit_name(cunit->type), x, y,ccity->name); - } - }else{ - teleport_unit_to_city(punit, pcity, 0); - freelog(LOG_VERBOSE, "Teleported %s's %s from (%d, %d) to %s", - get_player(punit->owner)->name, unit_name(punit->type), - x, y, pcity->name); - if (verbose) { - notify_player(get_player(punit->owner), - _("Game: Teleported your %s from (%d, %d) to %s."), - unit_name(punit->type), x, y, pcity->name); - } - } - + + /* We start by reducing the unit list until we only have units from one nation */ + while(1){ + struct city *pcity, *ccity; punit = unit_list_get(&map_get_tile(x, y)->units, 0); if (!punit) - break; + return; cunit = is_enemy_unit_on_tile(x, y, punit->owner); + if (!cunit) + break; + pcity = find_closest_owned_city(get_player(punit->owner), x, y, is_sailing_unit(punit)); + ccity = find_closest_owned_city(get_player(cunit->owner), x, y, is_sailing_unit(cunit)); + + /* First look if both cities exist. */ + if (!pcity) { + if (!ccity) { + wipe_unit(get_player(punit->owner), punit); /* Nowhere to go. Wipe a unit */ + continue; + } else { + teleport_unit_to_city(cunit, ccity, 0, verbose); /*Only one of them has a homecity. Send it home */ + continue; + } + } else if (!ccity) {/* pcity is non-NULL */ + teleport_unit_to_city(punit, pcity, 0, verbose); + continue; + } + + /* Both cities exist. Send the unit that is fathest from home home */ + if(map_distance(x, y, pcity->x, pcity->y) + < map_distance(x, y, ccity->x, ccity->y)) + teleport_unit_to_city(cunit, ccity, 0, verbose); + else + teleport_unit_to_city(punit, pcity, 0, verbose); } /* There is only one players units left on this square. If there is not - enough transporter capacity left , send surplus to the closest friendly + enough transporter capacity left send surplus to the closest friendly city. */ + punit = unit_list_get(&map_get_tile(x, y)->units, 0); - if(!punit && cunit) - punit = cunit; - - if(punit && map_get_terrain(punit->x, punit->y)==T_OCEAN) { + if(punit && map_get_terrain(x, y) == T_OCEAN) { while(!is_enough_transporter_space(get_player(punit->owner), x, y)) { unit_list_iterate(map_get_tile(x, y)->units, vunit) { if(is_ground_unit(vunit)) { - struct city *vcity = - find_closest_owned_city(get_player(vunit->owner), x, y); - teleport_unit_to_city(vunit, vcity, 0); - freelog(LOG_VERBOSE, "Teleported %s's %s to %s" - " as there is no transport space on square (%d, %d)", - get_player(vunit->owner)->name, unit_name(vunit->type), - vcity->name, x, y); - if (verbose) { - notify_player(get_player(vunit->owner), - _("Game: Teleported your %s to %s as there is" - " no transport space on square (%d, %d)."), - unit_name(vunit->type), vcity->name, x, y); - } + struct city *vcity = find_closest_owned_city(get_player(vunit->owner), x, y, 0); + printf("%s\n", vcity->name); + if (vcity) + teleport_unit_to_city(vunit, vcity, 0, verbose); + else + wipe_unit(get_player(vunit->owner), vunit); break; /* break out of unit_list_iterate loop */ } } diff -Nur -X/home/thue/freeciv-dev/no.freeciv transfer_problems/server/unittools.h transfer_problems2/server/unittools.h --- transfer_problems/server/unittools.h Mon Apr 10 18:21:11 2000 +++ transfer_problems2/server/unittools.h Mon Apr 10 18:51:10 2000 @@ -51,7 +51,7 @@ int build_points_left(struct city *pcity); int can_place_partisan(int x, int y); int enemies_at(struct unit *punit, int x, int y); -int teleport_unit_to_city(struct unit *punit, struct city *pcity, int mov_cost); +int teleport_unit_to_city(struct unit *punit, struct city *pcity, int mov_cost, int verbose); struct unit *is_enemy_unit_on_tile(int x, int y, int owner); void resolve_unit_stack(int x, int y, int verbose);