diff -Nur -X/mnt/data/freeciv-dev/freeciv/diff_ignore freeciv/server/citytools.c codeciv/server/citytools.c --- freeciv/server/citytools.c Sat Dec 29 14:12:43 2001 +++ codeciv/server/citytools.c Sat Dec 29 23:32:01 2001 @@ -517,50 +517,6 @@ } /********************************************************************* -Note: the old unit is not wiped here. -***********************************************************************/ -static void transfer_unit(struct unit *punit, struct city *tocity, - int verbose) -{ - struct player *from_player = unit_owner(punit); - struct player *to_player = city_owner(tocity); - - if (from_player == to_player) { - freelog(LOG_VERBOSE, "Changed homecity of %s's %s to %s", - from_player->name, unit_name(punit->type), tocity->name); - if (verbose) { - notify_player(from_player, _("Game: Changed homecity of %s to %s."), - unit_name(punit->type), tocity->name); - } - } else { - struct city *in_city = map_get_city(punit->x, punit->y); - if (in_city) { - freelog(LOG_VERBOSE, "Transfered %s in %s from %s to %s", - unit_name(punit->type), in_city->name, - from_player->name, to_player->name); - if (verbose) { - notify_player(from_player, _("Game: Transfered %s in %s from %s to %s."), - unit_name(punit->type), in_city->name, - from_player->name, to_player->name); - } - } else { - freelog(LOG_VERBOSE, "Transfered %s from %s to %s", - unit_name(punit->type), - from_player->name, to_player->name); - if (verbose) { - notify_player(from_player, _("Game: Transfered %s from %s to %s."), - unit_name(punit->type), - from_player->name, to_player->name); - } - } - } - - create_unit_full(to_player, punit->x, punit->y, punit->type, - punit->veteran, tocity->id, punit->moves_left, - punit->hp); -} - -/********************************************************************* Units in a bought city are transferred to the new owner, units supported by the city, but held in other cities are updated to reflect those cities as their new homecity. Units supported @@ -592,7 +548,7 @@ unit_list_iterate(map_get_tile(x, y)->units, vunit) { /* Don't transfer units already owned by new city-owner --wegge */ if (unit_owner(vunit) == pvictim) { - transfer_unit(vunit, pcity, verbose); + transfer_unit_to_city(vunit, pcity, verbose); wipe_unit_safe(vunit, &myiter); unit_list_unlink(units, vunit); } @@ -606,11 +562,11 @@ if (new_home_city && new_home_city != exclude_city) { /* unit is in another city: make that the new homecity, unless that city is actually the same city (happens if disbanding) */ - transfer_unit(vunit, new_home_city, verbose); + transfer_unit_to_city(vunit, new_home_city, verbose); } else if (kill_outside == -1 || real_map_distance(vunit->x, vunit->y, x, y) <= kill_outside) { /* else transfer to specified city. */ - transfer_unit(vunit, pcity, verbose); + transfer_unit_to_city(vunit, pcity, verbose); } /* not deleting cargo as it may be carried by units transfered later. diff -Nur -X/mnt/data/freeciv-dev/freeciv/diff_ignore freeciv/server/unittools.c codeciv/server/unittools.c --- freeciv/server/unittools.c Sat Dec 29 14:12:48 2001 +++ codeciv/server/unittools.c Sat Dec 29 23:33:59 2001 @@ -1429,6 +1429,78 @@ return 0; } + +/********************************************************************* +Note: the old unit is not wiped here. +***********************************************************************/ +void transfer_unit_to_city(struct unit *punit, struct city *tocity, + int verbose) +{ + struct player *from_player = unit_owner(punit); + struct player *to_player = city_owner(tocity); + + if (from_player == to_player) { + freelog(LOG_VERBOSE, "Changed homecity of %s's %s to %s", + from_player->name, unit_name(punit->type), tocity->name); + if (verbose) { + notify_player(from_player, _("Game: Changed homecity of %s to %s."), + unit_name(punit->type), tocity->name); + } + } else { + struct city *in_city = map_get_city(punit->x, punit->y); + if (in_city) { + freelog(LOG_VERBOSE, "Transfered %s in %s from %s to %s", + unit_name(punit->type), in_city->name, + from_player->name, to_player->name); + if (verbose) { + notify_player(from_player, _("Game: Transfered %s in %s from %s to %s."), + unit_name(punit->type), in_city->name, + from_player->name, to_player->name); + } + } else { + freelog(LOG_VERBOSE, "Transfered %s from %s to %s", + unit_name(punit->type), + from_player->name, to_player->name); + if (verbose) { + notify_player(from_player, _("Game: Transfered %s from %s to %s."), + unit_name(punit->type), + from_player->name, to_player->name); + } + } + } + + create_unit_full(to_player, punit->x, punit->y, punit->type, + punit->veteran, tocity->id, punit->moves_left, + punit->hp); +} + +/************************************************************************** +Transfers punit to the player owning tounit, using tounit's homecity as +homecity for punit +**************************************************************************/ +static void transfer_unit(struct unit *punit, struct unit *tounit, + int verbose) +{ + if (tounit->homecity) { + transfer_unit_to_city(punit, find_city_by_id(tounit->homecity), verbose); + } else { + struct player *from_player = unit_owner(punit); + struct player *to_player = unit_owner(tounit); + freelog(LOG_VERBOSE, "Transfered %s from %s to %s", + unit_name(punit->type), + from_player->name, to_player->name); + if (verbose) { + notify_player(from_player, _("Game: Transfered %s from %s to %s."), + unit_name(punit->type), + from_player->name, to_player->name); + } + create_unit_full(unit_owner(tounit), punit->x, punit->y, punit->type, + punit->veteran, 0, punit->moves_left, + punit->hp); + } + wipe_unit(punit); +} + /************************************************************************** Resolve unit stack @@ -1515,23 +1587,31 @@ /* There is only one allied units left on this square. If there is not enough transporter capacity left send surplus to the closest friendly city. */ - punit = unit_list_get(&(ptile->units), 0); - if (ptile->terrain == T_OCEAN) { START: + /* Iterate over the players who have units present on the tile. + Some may have more than one, and this loop will then look at + them more than one time, but that is harmless. */ unit_list_iterate(ptile->units, vunit) { - if (ground_unit_transporter_capacity(x, y, unit_owner(punit)) < 0) { - unit_list_iterate(ptile->units, wunit) { - if (is_ground_unit(wunit) && wunit->owner == vunit->owner) { - struct city *wcity = - find_closest_owned_city(unit_owner(wunit), x, y, 0, NULL); - if (wcity) - teleport_unit_to_city(wunit, wcity, 0, verbose); - else - disband_stack_conflict_unit(wunit, verbose); - goto START; - } - } unit_list_iterate_end; /* End of find a unit from that player to disband*/ + if (ground_unit_transporter_capacity(x, y, unit_owner(vunit)) < 0) { + /* Not enough space on player's transporters. + Find a unit owned by the player which doesn't fit. */ + unit_list_iterate(ptile->units, wunit) { + if (is_ground_unit(wunit) && wunit->owner == vunit->owner) { + /* If an allied player has transport capacity on the tile then + transfer the unit to him. */ + unit_list_iterate(ptile->units, ptrans) { + if (is_ground_units_transport(ptrans) + && ground_unit_transporter_capacity(x, y, unit_owner(ptrans)) > 0) { + transfer_unit(wunit, ptrans, verbose); + goto START; + } + } unit_list_iterate_end; + /* Not transferable; disband it instead. */ + disband_stack_conflict_unit(wunit, verbose); + goto START; + } + } unit_list_iterate_end; /* End of find a unit from that player to disband*/ } } unit_list_iterate_end; /* End of find a player */ } diff -Nur -X/mnt/data/freeciv-dev/freeciv/diff_ignore freeciv/server/unittools.h codeciv/server/unittools.h --- freeciv/server/unittools.h Sat Dec 29 14:12:52 2001 +++ codeciv/server/unittools.h Sat Dec 29 23:31:29 2001 @@ -45,6 +45,8 @@ int enemies_at(struct unit *punit, int x, int y); int teleport_unit_to_city(struct unit *punit, struct city *pcity, int move_cost, int verbose); +void transfer_unit_to_city(struct unit *punit, struct city *tocity, + int verbose); void resolve_unit_stack(int x, int y, int verbose); int get_watchtower_vision(struct unit *punit); int unit_profits_of_watchtower(struct unit *punit);