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 14:10:22 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 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 14:10:22 2001 @@ -1429,6 +1429,77 @@ return 0; } + +/********************************************************************* +Note: the old unit is not wiped here. +***********************************************************************/ +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); +} + +/************************************************************************** +... +**************************************************************************/ +static void transfer_unit_wrapper(struct unit *punit, struct unit *tounit, + int verbose) +{ + if (tounit->homecity) { + transfer_unit(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 +1586,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_wrapper(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 14:10:22 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(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);