diff -Nur -X/home/thue/freeciv-dev/freeciv/diff_ignore freeciv/server/unitfunc.c air/server/unitfunc.c --- freeciv/server/unitfunc.c Tue May 16 01:33:41 2000 +++ air/server/unitfunc.c Tue May 16 01:36:40 2000 @@ -64,6 +64,8 @@ struct unit *pdiplomat, struct city *pcity); static void diplomat_escape (struct player *pplayer, struct unit *pdiplomat, struct city *pcity); +static void update_unit_activity(struct player *pplayer, struct unit *punit, + struct genlist_iterator *iter); static int upgrade_would_strand(struct unit *punit, int upgrade_type); @@ -1762,7 +1764,7 @@ void update_unit_activities(struct player *pplayer) { unit_list_iterate(pplayer->units, punit) - update_unit_activity(pplayer, punit); + update_unit_activity(pplayer, punit, &myiter); unit_list_iterate_end; } @@ -1874,12 +1876,13 @@ also move units that is on a goto. restore unit move points (information needed for settler tasks) **************************************************************************/ -void update_unit_activity(struct player *pplayer, struct unit *punit) +static void update_unit_activity(struct player *pplayer, struct unit *punit, + struct genlist_iterator *iter) { int id = punit->id; int mr = get_unit_type (punit->type)->move_rate; int unit_activity_done = 0; - + int transformed = 0; int activity = punit->activity; /* to allow a settler to begin a task with no moves left @@ -1926,7 +1929,7 @@ ACTIVITY_PILLAGE, punit->activity_target) >= 1) { int what_pillaged = punit->activity_target; map_clear_special(punit->x, punit->y, what_pillaged); - unit_list_iterate (map_get_tile (punit->x, punit->y)->units, punit2) + unit_list_iterate (map_get_tile(punit->x, punit->y)->units, punit2) if ((punit2->activity == ACTIVITY_PILLAGE) && (punit2->activity_target == what_pillaged)) { set_unit_activity(punit2, ACTIVITY_IDLE); @@ -2001,12 +2004,13 @@ map_transform_tile(punit->x, punit->y); check_terrain_ocean_land_change(punit->x, punit->y, old); unit_activity_done = 1; + transformed = 1; } } if (unit_activity_done) { send_tile_info(0, punit->x, punit->y); - unit_list_iterate (map_get_tile (punit->x, punit->y)->units, punit2) + unit_list_iterate (map_get_tile(punit->x, punit->y)->units, punit2) if (punit2->activity == activity) { if (punit2->connecting) { punit2->activity_count = 0; @@ -2037,14 +2041,72 @@ return; } - if (punit->activity==ACTIVITY_IDLE && - map_get_terrain(punit->x, punit->y)==T_OCEAN && - is_ground_unit(punit)) - set_unit_activity(punit, ACTIVITY_SENTRY); - send_unit_info(0, punit); -} + /* Any units that landed in water or boats that landed on land as a + result of settlers transforming must be moved back into their right + environment. + We advance the unit_list iterator from update_unit_activities() if + we delete the unit it points to. */ + if (transformed) { + struct tile *ptile = map_get_tile(punit->x, punit->y); + unit_list_iterate(ptile->units, punit2) { + int x, y; + if (is_ground_unit(punit2) + && ptile->terrain == T_OCEAN + && ground_unit_transporter_capacity(punit->x, punit->y, punit->owner) < 0) { + for (x = punit2->x-1; x <= punit2->x+1; x++) + for (y = punit2->y-1; y <= punit2->y+1; y++) { + struct tile *ptile2; + x = map_adjust_x(x); + y = map_adjust_y(y); + ptile2 = map_get_tile(x, y); + if (ptile2->terrain != T_OCEAN + && !is_enemy_unit_tile(x, y, punit2->owner)) { + freelog(LOG_VERBOSE, _("Moving %s due to transform " + "to sea at %i,%i"), + get_unit_name(punit2->type), punit2->x, punit2->y); + move_unit(punit2, x, y, 0, 0, 0); + goto NEXTUNIT; + } + } + /* if we get here we could not move punit2 */ + freelog(LOG_VERBOSE, _("Disbanding %s due to transform " + "to sea at %i,%i"), + get_unit_name(punit2->type), punit2->x, punit2->y); + if (iter && ((struct unit*)ITERATOR_PTR((*iter))) == punit2) + ITERATOR_NEXT((*iter)); + wipe_unit_spec_safe(NULL, punit2, NULL, 0); + } else if (is_sailing_unit(punit2) + && ptile->terrain != T_OCEAN + && !ptile->city) { + for (x = punit2->x-1; x <= punit2->x+1; x++) + for (y = punit2->y-1; y <= punit2->y+1; y++) { + struct tile *ptile2; + x = map_adjust_x(x); + y = map_adjust_y(y); + ptile2 = map_get_tile(x, y); + if (ptile2->terrain == T_OCEAN + && !is_enemy_unit_tile(x, y, punit2->owner)) { + freelog(LOG_VERBOSE, _("Moving %s due to transform " + "to land at %i,%i"), + get_unit_name(punit2->type), punit2->x, punit2->y); + move_unit(punit2, x, y, 0, 0, 0); + goto NEXTUNIT; + } + } + /* if we get here we could not move punit2 */ + freelog(LOG_VERBOSE, _("Disbanding %s due to transform " + "to land at %i,%i"), + get_unit_name(punit2->type), punit2->x, punit2->y); + if (iter && ((struct unit*)ITERATOR_PTR((*iter))) == punit2) + ITERATOR_NEXT((*iter)); + wipe_unit_spec_safe(NULL, punit2, NULL, 0); + } + NEXTUNIT: + } unit_list_iterate_end; + } +} /************************************************************************** nuke a square diff -Nur -X/home/thue/freeciv-dev/freeciv/diff_ignore freeciv/server/unitfunc.h air/server/unitfunc.h --- freeciv/server/unitfunc.h Tue May 16 01:33:41 2000 +++ air/server/unitfunc.h Tue May 16 00:02:56 2000 @@ -40,7 +40,6 @@ void unit_restore_hitpoints(struct player *pplayer, struct unit *punit); void unit_restore_movepoints(struct player *pplayer, struct unit *punit); void update_unit_activities(struct player *pplayer); -void update_unit_activity(struct player *pplayer, struct unit *punit); void create_unit(struct player *pplayer, int x, int y, Unit_Type_id type, int make_veteran, int homecity_id, int moves_left);