Index: common/map.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/map.c,v retrieving revision 1.61 diff -u -r1.61 map.c --- map.c 2000/11/10 19:47:24 1.61 +++ map.c 2001/01/03 12:06:09 @@ -14,10 +14,11 @@ #include #endif +#include +#include #include #include #include -#include #include "city.h" #include "fcintl.h" @@ -29,6 +30,8 @@ #include "map.h" +static enum tile_special_type activity_to_special(int activity); + /* the very map */ struct civ_map map; @@ -707,6 +710,29 @@ || ptile_w->special&S_RIVER || ptile_w->special&S_IRRIGATION); } +/** + FIXME: Document. +**/ +int map_activity_time(int x, int y, int activity) +{ + int terrain = map_get_terrain(x, y); + switch (activity) { + case ACTIVITY_ROAD: + return tile_types[terrain].road_time; + case ACTIVITY_IRRIGATE: + return tile_types[terrain].irrigation_time; + case ACTIVITY_MINE: + return tile_types[terrain].mining_time; + case ACTIVITY_TRANSFORM: + return tile_types[terrain].transform_time; + default: + return 3; + } +} + + + +#if 0 /*************************************************************** .. ***************************************************************/ @@ -738,6 +764,7 @@ { return tile_types[map_get_terrain(x, y)].transform_time; } +#endif /*************************************************************** ... @@ -762,62 +789,91 @@ map_clear_special(x, y, S_FALLOUT); } -/*************************************************************** -... -***************************************************************/ -void map_irrigate_tile(int x, int y) +static enum tile_special_type activity_to_special(int activity) { - enum tile_terrain_type now, result; - - now=map_get_terrain(x, y); - result=tile_types[now].irrigation_result; - - if(now==result) { - if (map_get_special(x, y)&S_IRRIGATION) { - map_set_special(x, y, S_FARMLAND); - } else { - map_set_special(x, y, S_IRRIGATION); - } - } - else if(result!=T_LAST) { - map_set_terrain(x, y, result); - if (result==T_OCEAN) { - clear_infrastructure(x, y); - clear_dirtiness(x, y); - map_clear_special(x, y, S_RIVER); /* FIXME: When rest of code can handle - rivers in oceans, don't clear this! */ - } - reset_move_costs(x, y); + switch (activity) { + case ACTIVITY_POLLUTION: + return S_POLLUTION; + case ACTIVITY_FALLOUT: + return S_FALLOUT; + case ACTIVITY_FORTRESS: + return S_FORTRESS; + case ACTIVITY_AIRBASE: + return S_AIRBASE; + case ACTIVITY_RAILROAD: + return S_RAILROAD; + case ACTIVITY_ROAD: + return S_ROAD; + default: + assert(0); } - map_clear_special(x, y, S_MINE); + return 0; } -/*************************************************************** -... -***************************************************************/ -void map_mine_tile(int x, int y) +void map_act_on_tile(int x, int y, int activity) { enum tile_terrain_type now, result; + int new_spec = 0, new_spec2 = 0; + int rem_spec = 0; - now=map_get_terrain(x, y); - result=tile_types[now].mining_result; + now = map_get_terrain(x, y); + result = now; - if(now==result) - map_set_special(x, y, S_MINE); - else if(result!=T_LAST) { + switch (activity) { + case ACTIVITY_IRRIGATE: + result = tile_types[now].irrigation_result; + new_spec = S_IRRIGATION; + new_spec2 = S_FARMLAND; + rem_spec = S_MINE; + break; + case ACTIVITY_MINE: + result = tile_types[now].mining_result; + new_spec = S_MINE; + rem_spec = S_FARMLAND | S_IRRIGATION; + break; + case ACTIVITY_TRANSFORM: + result = tile_types[now].transform_result; + /* Clear mining/irrigation if resulting terrain type cannot + support that feature. (With current rules, this should only + clear mines, but I'm including both cases in the most general + form for possible future ruleset expansion. -GJW) */ + if (tile_types[result].mining_result != result) + rem_spec = S_MINE; + if (tile_types[result].irrigation_result != result) + rem_spec |= S_IRRIGATION | S_FARMLAND; + break; + case ACTIVITY_POLLUTION: + case ACTIVITY_FALLOUT: + rem_spec = activity_to_special(activity); + break; + case ACTIVITY_FORTRESS: + case ACTIVITY_AIRBASE: + case ACTIVITY_RAILROAD: + case ACTIVITY_ROAD: + new_spec = activity_to_special(activity); + break; + } + if (now == result) { + /* Don't change the tile type, just add some specials. */ + if ((map_get_tile(x, y)->special & new_spec) && new_spec2) + map_set_special(x, y, new_spec2); + else + map_set_special(x, y, new_spec); + } else if (result != T_LAST) { map_set_terrain(x, y, result); - if (result==T_OCEAN) { + if (result == T_OCEAN) { clear_infrastructure(x, y); clear_dirtiness(x, y); - map_clear_special(x, y, S_RIVER); /* FIXME: When rest of code can handle + map_clear_special(x, y, S_RIVER); /* FIXME: When rest of code can handle rivers in oceans, don't clear this! */ } reset_move_costs(x, y); } - map_clear_special(x,y, S_FARMLAND); - map_clear_special(x,y, S_IRRIGATION); + map_clear_special(x, y, rem_spec); } +#if 0 + /*************************************************************** ... ***************************************************************/ @@ -850,6 +906,7 @@ map_clear_special(x, y, S_IRRIGATION); } } +#endif /*************************************************************** The basic cost to move punit from tile t1 to tile t2. @@ -1104,9 +1161,13 @@ ***************************************************************/ void map_set_special(int x, int y, enum tile_special_type spe) { - x = map_adjust_x(x); y = map_adjust_y(y); - (map.tiles+x+y*map.xsize)->special|=spe; - if (spe == S_ROAD || spe == S_RAILROAD) reset_move_costs(x, y); + x = map_adjust_x(x); + y = map_adjust_y(y); + + (map.tiles+x+y*map.xsize)->special |= spe; + + if (spe & S_ROAD || spe & S_RAILROAD) + reset_move_costs(x, y); } /*************************************************************** @@ -1114,9 +1175,13 @@ ***************************************************************/ void map_clear_special(int x, int y, enum tile_special_type spe) { - x = map_adjust_x(x); y = map_adjust_y(y); + x = map_adjust_x(x); + y = map_adjust_y(y); + (map.tiles+x+y*map.xsize)->special&=~spe; - if (spe == S_ROAD || spe == S_RAILROAD) reset_move_costs(x, y); + + if (spe & S_ROAD || spe & S_RAILROAD) + reset_move_costs(x, y); } Index: common/map.h =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/map.h,v retrieving revision 1.67 diff -u -r1.67 map.h --- map.h 2000/10/27 22:20:08 1.67 +++ map.h 2001/01/03 12:06:11 @@ -235,14 +235,20 @@ int map_get_infrastructure_prerequisite(int spe); int get_preferred_pillage(int pset); +void map_act_on_tile(int x, int y, int activity); +#if 0 void map_irrigate_tile(int x, int y); void map_mine_tile(int x, int y); void map_transform_tile(int x, int y); +#endif +int map_activity_time(int x, int y, int activity); +#if 0 int map_build_road_time(int x, int y); int map_build_irrigation_time(int x, int y); int map_build_mine_time(int x, int y); int map_transform_time(int x, int y); +#endif extern struct civ_map map; Index: server/settlers.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/settlers.c,v retrieving revision 1.88 diff -u -r1.88 settlers.c --- settlers.c 2000/12/20 16:53:00 1.88 +++ settlers.c 2001/01/03 12:06:17 @@ -996,7 +996,7 @@ /* now, consider various activities... */ - d = (map_build_irrigation_time(x, y)*3 + mv_rate - 1)/mv_rate + + d = (map_activity_time(x, y, ACTIVITY_IRRIGATE)*3 + mv_rate - 1)/mv_rate + mv_turns; consider_settler_action(pplayer, ACTIVITY_IRRIGATE, -1, pcity->ai.irrigate[i][j], oldv, in_use, d, @@ -1004,7 +1004,7 @@ x, y); if (unit_flag(punit->type, F_TRANSFORM)) { - d = (map_transform_time(x, y)*3 + mv_rate - 1)/mv_rate + + d = (map_activity_time(x, y, ACTIVITY_TRANSFORM)*3 + mv_rate - 1)/mv_rate + mv_turns; consider_settler_action(pplayer, ACTIVITY_TRANSFORM, -1, pcity->ai.transform[i][j], oldv, in_use, d, @@ -1012,7 +1012,7 @@ x, y); } - d = (map_build_mine_time(x, y)*3 + mv_rate - 1)/mv_rate + + d = (map_activity_time(x, y, ACTIVITY_MINE)*3 + mv_rate - 1)/mv_rate + mv_turns; consider_settler_action(pplayer, ACTIVITY_MINE, -1, pcity->ai.mine[i][j], oldv, in_use, d, @@ -1020,7 +1020,7 @@ x, y); if (!(map_get_tile(x,y)->special&S_ROAD)) { - d = (map_build_road_time(x, y)*3 + 3 + mv_rate - 1)/mv_rate + + d = (map_activity_time(x, y, ACTIVITY_ROAD)*3 + 3 + mv_rate - 1)/mv_rate + mv_turns; consider_settler_action(pplayer, ACTIVITY_ROAD, road_bonus(x, y, S_ROAD) * 8, @@ -1028,7 +1028,7 @@ &best_newv, &best_oldv, &best_act, &gx, &gy, x, y); - d = (3*3 + 3*map_build_road_time(x,y) + 3 + mv_rate - 1)/mv_rate + + d = (3*3 + 3*map_activity_time(x, y, ACTIVITY_ROAD) + 3 + mv_rate - 1)/mv_rate + mv_turns; consider_settler_action(pplayer, ACTIVITY_ROAD, road_bonus(x, y, S_RAILROAD) * 4, Index: server/unitfunc.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/unitfunc.c,v retrieving revision 1.214 diff -u -r1.214 unitfunc.c --- unitfunc.c 2000/12/20 16:53:00 1.214 +++ unitfunc.c 2001/01/03 12:06:28 @@ -73,7 +73,7 @@ struct unit *victim_unit, struct city *victim_city); static void update_unit_activity(struct player *pplayer, struct unit *punit, struct genlist_iterator *iter); - +static void handle_terrain_changes(int, int, int, struct genlist_iterator *); static int upgrade_would_strand(struct unit *punit, int upgrade_type); static void sentry_transported_idle_units(struct unit *ptrans); @@ -328,10 +328,9 @@ pcity->x, pcity->y); /* Charge a nominal amount of movement for this. */ - (pdiplomat->moves_left)--; - if (pdiplomat->moves_left < 0) { - pdiplomat->moves_left = 0; - } + if (pdiplomat->moves_left > 0) + pdiplomat->moves_left--; + /* this may cause a diplomatic incident */ maybe_cause_incident(DIPLOMAT_EMBASSY, pplayer, NULL, pcity); @@ -2091,20 +2090,19 @@ } /************************************************************************** - progress settlers in their current tasks, - and units that is pillaging. - also move units that is on a goto. - restore unit move points (information needed for settler tasks) + Progress settlers in their current tasks, and units that are + pillaging. Also move units that are on goto. Restore unit move + points (information needed for settler tasks). **************************************************************************/ static void update_unit_activity(struct player *pplayer, struct unit *punit, struct genlist_iterator *iter) { int id = punit->id; + int x = punit->x, y = punit->y; int mr = get_unit_type (punit->type)->move_rate; int unit_activity_done = 0; int activity = punit->activity; enum ocean_land_change solvency = OLC_NONE; - struct tile *ptile = map_get_tile(punit->x, punit->y); /* to allow a settler to begin a task with no moves left without it counting toward the time to finish */ @@ -2121,148 +2119,96 @@ /* if connecting, automagically build prerequisities first */ if (punit->connecting && activity == ACTIVITY_RAILROAD && - !(map_get_tile(punit->x, punit->y)->special & S_ROAD)) { + !(map_get_tile(x, y)->special & S_ROAD)) { activity = ACTIVITY_ROAD; } - if (activity == ACTIVITY_EXPLORE) { - int more_to_explore = ai_manage_explorer(punit); - if (more_to_explore && player_find_unit_by_id(pplayer, id)) + switch (activity) { + case ACTIVITY_EXPLORE: + if (ai_manage_explorer(punit) && player_find_unit_by_id(pplayer, id)) handle_unit_activity_request(punit, ACTIVITY_EXPLORE); else return; - } - - if (activity==ACTIVITY_PILLAGE) { - if (punit->activity_target == 0) { /* case for old save files */ + break; + case ACTIVITY_FORTIFYING: + if (punit->activity_count >= 1) { + set_unit_activity(punit,ACTIVITY_FORTIFIED); + } + break; + case ACTIVITY_PILLAGE: + if (punit->activity_target == 0) { + /* case for old save files */ + /* FIXME: Move out to savegame loading code if possible. */ if (punit->activity_count >= 1) { - int what = - get_preferred_pillage( - get_tile_infrastructure_set( - map_get_tile(punit->x, punit->y))); + int what; + int tis = get_tile_infrastructure_set(map_get_tile(x, y)); + + what = get_preferred_pillage(tis); + if (what != S_NO_SPECIAL) { - map_clear_special(punit->x, punit->y, what); - send_tile_info(0, punit->x, punit->y); + map_clear_special(x, y, what); + send_tile_info(0, x, y); set_unit_activity(punit, ACTIVITY_IDLE); } } - } - else if (total_activity_targeted (punit->x, punit->y, - ACTIVITY_PILLAGE, punit->activity_target) >= 1) { + } else if (total_activity_targeted (x, y, + 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) + map_clear_special(x, y, what_pillaged); + unit_list_iterate (map_get_tile(x, y)->units, punit2) { if ((punit2->activity == ACTIVITY_PILLAGE) && (punit2->activity_target == what_pillaged)) { set_unit_activity(punit2, ACTIVITY_IDLE); send_unit_info(0, punit2); } - unit_list_iterate_end; - send_tile_info(0, punit->x, punit->y); - } - } - - if (activity==ACTIVITY_POLLUTION) { - if (total_activity (punit->x, punit->y, ACTIVITY_POLLUTION) >= 3) { - map_clear_special(punit->x, punit->y, S_POLLUTION); - unit_activity_done = 1; - } - } - - if (activity==ACTIVITY_FALLOUT) { - if (total_activity (punit->x, punit->y, ACTIVITY_FALLOUT) >= 3) { - map_clear_special(punit->x, punit->y, S_FALLOUT); - unit_activity_done = 1; - } - } - - if (activity==ACTIVITY_FORTRESS) { - if (total_activity (punit->x, punit->y, ACTIVITY_FORTRESS) >= 3) { - map_set_special(punit->x, punit->y, S_FORTRESS); - unit_activity_done = 1; - } - } - - if (activity==ACTIVITY_AIRBASE) { - if (total_activity (punit->x, punit->y, ACTIVITY_AIRBASE) >= 3) { - map_set_special(punit->x, punit->y, S_AIRBASE); - unit_activity_done = 1; - } - } - - if (activity==ACTIVITY_IRRIGATE) { - if (total_activity (punit->x, punit->y, ACTIVITY_IRRIGATE) >= - map_build_irrigation_time(punit->x, punit->y)) { - enum tile_terrain_type old = map_get_terrain(punit->x, punit->y); - map_irrigate_tile(punit->x, punit->y); - solvency = check_terrain_ocean_land_change(punit->x, punit->y, old); - unit_activity_done = 1; - } - } - - if (activity==ACTIVITY_ROAD) { - if (total_activity (punit->x, punit->y, ACTIVITY_ROAD) - + total_activity (punit->x, punit->y, ACTIVITY_RAILROAD) >= - map_build_road_time(punit->x, punit->y)) { - map_set_special(punit->x, punit->y, S_ROAD); - unit_activity_done = 1; + } unit_list_iterate_end; + send_tile_info(0, x, y); } - } - - if (activity==ACTIVITY_RAILROAD) { - if (total_activity (punit->x, punit->y, ACTIVITY_RAILROAD) >= 3) { - map_set_special(punit->x, punit->y, S_RAILROAD); + break; + case ACTIVITY_POLLUTION: + case ACTIVITY_FALLOUT: + case ACTIVITY_FORTRESS: + case ACTIVITY_AIRBASE: + case ACTIVITY_RAILROAD: + case ACTIVITY_ROAD: + case ACTIVITY_MINE: + case ACTIVITY_IRRIGATE: + case ACTIVITY_TRANSFORM: + if (total_activity (x, y, activity) + + (activity != ACTIVITY_ROAD + ? 0 : total_activity(x, y, ACTIVITY_RAILROAD)) + >= map_activity_time(x, y, activity)) { + enum tile_terrain_type old = map_get_terrain(x, y); + map_act_on_tile(x, y, activity); + solvency = check_terrain_ocean_land_change(x, y, old); unit_activity_done = 1; } + break; } - if (activity==ACTIVITY_MINE) { - if (total_activity (punit->x, punit->y, ACTIVITY_MINE) >= - map_build_mine_time(punit->x, punit->y)) { - enum tile_terrain_type old = map_get_terrain(punit->x, punit->y); - map_mine_tile(punit->x, punit->y); - solvency = check_terrain_ocean_land_change(punit->x, punit->y, old); - unit_activity_done = 1; - } - } - - if (activity==ACTIVITY_TRANSFORM) { - if (total_activity (punit->x, punit->y, ACTIVITY_TRANSFORM) >= - map_transform_time(punit->x, punit->y)) { - enum tile_terrain_type old = map_get_terrain(punit->x, punit->y); - map_transform_tile(punit->x, punit->y); - solvency = check_terrain_ocean_land_change(punit->x, punit->y, old); - unit_activity_done = 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) + send_tile_info(0, x, y); + unit_list_iterate (map_get_tile(x, y)->units, punit2) { if (punit2->activity == activity) { if (punit2->connecting) { punit2->activity_count = 0; do_unit_goto(punit2, get_activity_move_restriction(activity), 0); - } - else { + } else set_unit_activity(punit2, ACTIVITY_IDLE); - } send_unit_info(0, punit2); } - unit_list_iterate_end; + } unit_list_iterate_end; } - if (activity==ACTIVITY_FORTIFYING) { - if (punit->activity_count >= 1) { - set_unit_activity(punit,ACTIVITY_FORTIFIED); - } - } - - if (activity==ACTIVITY_GOTO) { - if (!punit->ai.control && (!is_military_unit(punit) || - punit->ai.passenger || !pplayer->ai.control)) { -/* autosettlers otherwise waste time; idling them breaks assignment */ -/* Stalling infantry on GOTO so I can see where they're GOing TO. -- Syela */ + if (activity == ACTIVITY_GOTO) { + if (!punit->ai.control + && (!is_military_unit(punit) + || punit->ai.passenger + || !pplayer->ai.control)) { + /* autosettlers otherwise waste time; idling them breaks assignment */ + /* Stalling infantry on GOTO so I can see where they're GOing TO. -- Syela */ do_unit_goto(punit, GOTO_MOVE_ANY, 1); } return; @@ -2273,22 +2219,30 @@ send_unit_info(0, punit); - /* Any units that landed in water or boats that landed on land as a - result of settlers changing terrain must be moved back into their - right environment. - We advance the unit_list iterator passed into this routine from - update_unit_activities() if we delete the unit it points to. - We go to START each time we moved a unit to avoid problems with the - tile unit list getting corrupted. - - FIXME: We shouldn't do this at all! There seems to be another - bug which is expressed when units wind up on the "wrong" terrain; - this is the bug that should be fixed. Also, introduction of the - "amphibious" movement category would allow the definition of units - that can "safely" change land<->ocean -- in which case all others - would (here) be summarily disbanded (suicide to accomplish their - task, for the greater good :). --jjm - */ + handle_terrain_changes(x, y, solvency, iter); +} + +/* Any units that landed in water or boats that landed on land as a + result of settlers changing terrain must be moved back into their + right environment. + We advance the unit_list iterator passed into this routine from + update_unit_activities() if we delete the unit it points to. + We go to START each time we moved a unit to avoid problems with the + tile unit list getting corrupted. + + FIXME: We shouldn't do this at all! There seems to be another + bug which is expressed when units wind up on the "wrong" terrain; + this is the bug that should be fixed. Also, introduction of the + "amphibious" movement category would allow the definition of units + that can "safely" change land<->ocean -- in which case all others + would (here) be summarily disbanded (suicide to accomplish their + task, for the greater good :). --jjm +*/ + +static void handle_terrain_changes(int x, int y, int solvency, struct genlist_iterator *iter) +{ + struct tile *ptile = map_get_tile(x, y); + START: switch (solvency) { case OLC_NONE: