diff -Nur -X/mnt/data/freeciv-dev/freeciv/diff_ignore freeciv/README.rulesets codeciv/README.rulesets --- freeciv/README.rulesets Thu Jun 21 22:35:53 2001 +++ codeciv/README.rulesets Wed Jun 20 23:13:30 2001 @@ -200,8 +200,6 @@ - There must be at least one unit with flag "Cities". - - Every unit with flag "Cities" must have also flag "Settlers". - Limitations: - These unit flag combinations won't work: diff -Nur -X/mnt/data/freeciv-dev/freeciv/diff_ignore freeciv/ai/advdomestic.c codeciv/ai/advdomestic.c --- freeciv/ai/advdomestic.c Thu Jun 21 22:35:49 2001 +++ codeciv/ai/advdomestic.c Thu Jun 21 03:06:52 2001 @@ -528,7 +528,6 @@ want is a value between 1 and 100. if want is 0 this advisor doesn't want anything ***********************************************************************/ - void domestic_advisor_choose_build(struct player *pplayer, struct city *pcity, struct ai_choice *choice) { diff -Nur -X/mnt/data/freeciv-dev/freeciv/diff_ignore freeciv/ai/aicity.c codeciv/ai/aicity.c --- freeciv/ai/aicity.c Thu Jun 21 22:35:49 2001 +++ codeciv/ai/aicity.c Thu Jun 21 22:29:48 2001 @@ -410,7 +410,7 @@ if (!pcity->shield_stock) ; else if (!bestchoice.type && is_wonder(bestchoice.choice) && buycost >= 200) ; /* wait for more vans */ - else if (bestchoice.type && unit_flag(bestchoice.choice, F_SETTLERS) && + else if (bestchoice.type && unit_flag(bestchoice.choice, F_CITIES) && !city_got_effect(pcity, B_GRANARY) && (pcity->size < 2 || pcity->food_stock < city_granary_size(pcity->size-1))) ; else if (bestchoice.type && bestchoice.type < 3 && /* not a defender */ @@ -530,7 +530,8 @@ establish_city_distances(pplayer, pcity); /* in advmilitary for warmap */ /* e_c_d doesn't even look at the seamap */ /* determines downtown and distance_to_wondercity, which a_c_c_b will need */ - contemplate_settling(pplayer, pcity); /* while we have the warmap handy */ + contemplate_terrain_improvements(pcity); + contemplate_new_city(pcity); /* while we have the warmap handy */ /* seacost may have been munged if we found a boat, but if we found a boat we don't rely on the seamap being current since we will recalculate. -- Syela */ @@ -621,33 +622,6 @@ unit_list_iterate_end; return def; } - -#ifdef UNUSED -/************************************************************************** -... -**************************************************************************/ -int city_get_settlers(struct city *pcity) -{ - int set=0; - unit_list_iterate(pcity->units_supported, punit) { - if (unit_flag(punit->type, F_SETTLERS)) - set++; - } - unit_list_iterate_end; - return set; -} -#endif - -#ifdef UNUSED -/************************************************************************** -... (unused) -**************************************************************************/ -int ai_in_initial_expand(struct player *pplayer) -{ - int expand_cities [3] = {3, 5, 7}; - return (pplayer->score.cities < expand_cities[get_nation_by_plr(pplayer)->expand]); -} -#endif void ai_choose_ferryboat(struct player *pplayer, struct city *pcity, struct ai_choice *choice) { diff -Nur -X/mnt/data/freeciv-dev/freeciv/diff_ignore freeciv/common/map.c codeciv/common/map.c --- freeciv/common/map.c Thu Jun 21 22:36:11 2001 +++ codeciv/common/map.c Fri Jun 22 17:14:38 2001 @@ -710,7 +710,7 @@ } /*************************************************************** -.. +... ***************************************************************/ int map_build_road_time(int x, int y) { @@ -739,6 +739,46 @@ int map_transform_time(int x, int y) { return tile_types[map_get_terrain(x, y)].transform_time; +} + +/*************************************************************** +... +***************************************************************/ +int map_build_rail_time(int x, int y) +{ + return 3; +} + +/*************************************************************** +... +***************************************************************/ +int map_build_airbase_time(int x, int y) +{ + return 3; +} + +/*************************************************************** +... +***************************************************************/ +int map_build_fortress_time(int x, int y) +{ + return 3; +} + +/*************************************************************** +... +***************************************************************/ +int map_clean_pollution_time(int x, int y) +{ + return 3; +} + +/*************************************************************** +... +***************************************************************/ +int map_clean_fallout_time(int x, int y) +{ + return 3; } /*************************************************************** diff -Nur -X/mnt/data/freeciv-dev/freeciv/diff_ignore freeciv/common/map.h codeciv/common/map.h --- freeciv/common/map.h Thu Jun 21 22:36:11 2001 +++ codeciv/common/map.h Fri Jun 22 17:11:37 2001 @@ -249,6 +249,12 @@ 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); +int map_build_rail_time(int x, int y); +int map_build_airbase_time(int x, int y); +int map_build_fortress_time(int x, int y); +int map_clean_pollution_time(int x, int y); +int map_clean_fallout_time(int x, int y); + extern struct civ_map map; Binary files freeciv/lala.sav.gz and codeciv/lala.sav.gz differ diff -Nur -X/mnt/data/freeciv-dev/freeciv/diff_ignore freeciv/server/ruleset.c codeciv/server/ruleset.c --- freeciv/server/ruleset.c Thu Jun 21 22:36:25 2001 +++ codeciv/server/ruleset.c Wed Jun 20 23:13:13 2001 @@ -699,14 +699,6 @@ } } free(slist); - - /* For now, if F_CITIES flag, we require the F_SETTLERS flag. -- jjm */ - if (unit_flag(i, F_CITIES) && !(unit_flag(i, F_SETTLERS))) { - freelog(LOG_FATAL, - "for unit_type \"%s\": \"Cities\" flag without \"Settlers\" flag (%s)", - u->name, filename); - exit(1); - } } /* roles */ diff -Nur -X/mnt/data/freeciv-dev/freeciv/diff_ignore freeciv/server/settlers.c codeciv/server/settlers.c --- freeciv/server/settlers.c Thu Jun 21 22:36:26 2001 +++ codeciv/server/settlers.c Fri Jun 22 17:32:38 2001 @@ -43,7 +43,6 @@ static int city_desirability(struct player *pplayer, int x, int y); -static int auto_settler_findwork(struct player *pplayer, struct unit *punit); static void auto_settlers_player(struct player *pplayer); static int is_already_assigned(struct unit *myunit, struct player *pplayer, @@ -865,6 +864,40 @@ } /************************************************************************** +... +**************************************************************************/ +static int unit_food_cost(struct unit *punit) +{ + int cost; + + if (punit->id) { + cost = 30; + } else { + /* It is a virtuel unit, so must start in a city... */ + struct city *pcity = map_get_city(punit->x, punit->y); + cost = city_granary_size(pcity->size); + if (city_got_effect(pcity, B_GRANARY)) + cost /= 2; + } + + return cost; +} + +/************************************************************************** +... +**************************************************************************/ +static int unit_food_upkeep(struct unit *punit) +{ + struct player *pplayer = unit_owner(punit); + int upkeep = utype_food_cost(get_unit_type(punit->type), + get_gov_pplayer(pplayer)); + if (punit->id && !punit->homecity) + upkeep = 0; /* thanks, Peter */ + + return upkeep; +} + +/************************************************************************** Evaluates all squares within 11 squares of the settler for city building. best_newv is the current best activity value for the settler. @@ -872,23 +905,36 @@ takes place. If this function finds a better alternative it will modify these values. -ferryboat is a ferryboat the unit can use. boatid is it's id. bx, by is -where ferryboat and punit will rendevous. -**************************************************************************/ -static void evaluate_city_building(struct unit *punit, - int *best_act, int *best_newv, int *gx, int *gy, - struct unit *ferryboat, - int boatid, int bx, int by, - struct city *mycity, int food_cost, - struct ai_choice *choice) +ferryboat is a ferryboat the unit can use to go to the tile with value +best_newv. +if gx is -1 and the return value is != 0 then we want to go to another +continent, but need to build a ferryboat first. +**************************************************************************/ +static int evaluate_city_building(struct unit *punit, + int *gx, int *gy, + struct unit **ferryboat) { + struct city *mycity = map_get_city(punit->x, punit->y); int newv, b, d; struct player *pplayer = unit_owner(punit); int nav_known = (get_invention(pplayer, game.rtech.nav) == TECH_KNOWN); int ucont = map_get_continent(punit->x, punit->y); int mv_rate = unit_types[punit->type].move_rate; - int food_upkeep = utype_food_cost(get_unit_type(punit->type), - get_gov_pplayer(pplayer)); + int food_upkeep = unit_food_upkeep(punit); + int food_cost = unit_food_cost(punit); + + int boatid, bx = 0, by = 0; /* as returned by find_boat */ + int best_newv = 0; + + if (pplayer->ai.control) + boatid = find_boat(pplayer, &bx, &by, 1); /* might need 2 for bodyguard */ + else + boatid = 0; + *ferryboat = unit_list_find(&(map_get_tile(punit->x, punit->y)->units), boatid); + if (*ferryboat) + really_generate_warmap(mycity, *ferryboat, SEA_MOVING); + + generate_warmap(mycity, punit); if (punit->ai.ai_role == AIUNIT_BUILD_CITY) { remove_city_from_minimap(punit->goto_dest_x, punit->goto_dest_y); @@ -908,13 +954,13 @@ && !city_exists_within_city_radius(x, y, 0)) { /* potential target, calculate mv_cost: */ - if (ferryboat) { + if (*ferryboat) { /* already aboard ship, can use real warmap */ if (!is_terrain_near_tile(x, y, T_OCEAN)) { mv_cost = 9999; } else { mv_cost = warmap.seacost[x][y] * mv_rate / - unit_types[ferryboat->type].move_rate; + unit_types[(*ferryboat)->type].move_rate; } } else if (!goto_is_sane(punit, x, y, 1) || warmap.cost[x][y] > THRESHOLD * mv_rate) { @@ -922,7 +968,9 @@ if (!is_terrain_near_tile(x, y, T_OCEAN)) { mv_cost = 9999; } else if (boatid) { - if (!punit->id && mycity->id == boatid) w_virtual = 1; + if (!punit->id && mycity->id == boatid) { + w_virtual = 1; + } mv_cost = warmap.cost[bx][by] + real_map_distance(bx, by, x, y) + mv_rate; } else if (punit->id || @@ -969,18 +1017,16 @@ if (w_virtual) { freelog(LOG_DEBUG, "%s: best_newv = %d, w_virtual = 1, newv = %d", - mycity->name, *best_newv, newv); + mycity->name, best_newv, newv); } if (map_get_continent(x, y) != ucont && !nav_known && near >= 8) { - if (newv > choice->want && !punit->id) choice->want = newv; freelog(LOG_DEBUG, "%s @(%d, %d) city_des (%d, %d) = %d, newv = %d, d = %d", (punit->id ? unit_types[punit->type].name : mycity->name), punit->x, punit->y, x, y, b, newv, d); - } else if (newv > *best_newv) { - *best_act = ACTIVITY_UNKNOWN; /* flag value */ - *best_newv = newv; + } else if (newv > best_newv) { + best_newv = newv; if (w_virtual) { *gx = -1; *gy = -1; } else { @@ -989,74 +1035,41 @@ } } } square_iterate_end; + + return best_newv; } /************************************************************************** - find some work for the settler +Finds tiles to improve, using punit. +How nice a tile it finds is returned. If it returns >0 gx,gy indicates the +tile it has chosen, and bestact indicates the activity it wants to do. **************************************************************************/ -static int auto_settler_findwork(struct player *pplayer, struct unit *punit) +static int evaluate_improvements(struct unit *punit, + int *best_act, int *gx, int *gy) { struct city *mycity = map_get_city(punit->x, punit->y); + struct player *pplayer = unit_owner(punit); + int in_use; /* true if the target square is being used + by one of our cities */ int ucont = map_get_continent(punit->x, punit->y); int mv_rate = unit_types[punit->type].move_rate; - int player_num = pplayer->player_no; - int save_id = punit->id; /* in case unit dies */ - - int gx,gy; /* x,y of target (goto) square */ int mv_turns; /* estimated turns to move to target square */ int oldv; /* current value of consideration tile */ - int best_newv = 0; /* newv of best target so far, all cities */ int best_oldv = 9999; /* oldv of best target so far; compared if newv==best_newv; not initialized to zero, so that newv=0 activities are not chosen */ - int in_use; /* true if the target square is being used - by one of our cities */ - int best_act = 0; /* ACTIVITY_ of best target so far */ - /* upkeep food value for single settler */ - int food_upkeep = utype_food_cost(get_unit_type(punit->type), - get_gov_pplayer(pplayer)); - int food_cost; /* estimated food cost to produce settler */ - - int boatid, bx = 0, by = 0; /* as returned by find_boat */ - struct unit *ferryboat; /* if non-null, boatid boat at unit's x,y */ - - int x, y; - int d; - - struct ai_choice choice; /* for nav want only */ + int food_upkeep = unit_food_upkeep(punit); + int food_cost = unit_food_cost(punit); -#ifdef DEBUG - /* for debugging only */ - int save_newv; -#endif - - choice.type = 1; - choice.want = 0; /* will change as needed */ - choice.choice = get_role_unit(L_FERRYBOAT, -1); - /* was U_CARAVEL (first non-trireme boat?) but gets set - * properly later anyway */ - - if (punit->id) food_cost = 30; - else { - if (mycity->size == 1) food_cost = 20; - else food_cost = 40 * (mycity->size - 1) / mycity->size; - if (city_got_effect(mycity, B_GRANARY)) food_cost -= 20; - } - if (punit->id && !punit->homecity) food_upkeep = 0; /* thanks, Peter */ + int best_newv = 0; - /** First find the best square to upgrade, - ** results in: gx, gy, best_oldv, best_newv, best_act */ - - gx = -1; - gy = -1; - /* iterating over the whole map is just ridiculous. let's only look at - our own cities. The old method wasted billions of CPU cycles and led to - AI settlers improving enemy cities. arguably should include city_spot */ generate_warmap(mycity, punit); + city_list_iterate(pplayer->cities, pcity) { freelog(LOG_DEBUG, "%s", pcity->name); /* try to work near the city */ city_map_iterate_outwards(i, j) { + int x, y; if (get_worker_city(pcity, i, j) == C_TILE_UNAVAILABLE) continue; in_use = (get_worker_city(pcity, i, j) == C_TILE_WORKER); x = pcity->x + i - CITY_MAP_SIZE/2; @@ -1064,80 +1077,82 @@ if (normalize_map_pos(&x, &y) && map_get_continent(x, y) == ucont && warmap.cost[x][y] <= THRESHOLD * mv_rate - && (territory[x][y]&(1<player_no)) + /* pretty good, hope it's enough! -- Syela */ + && !is_already_assigned(punit, pplayer, x, y)) { /* calling is_already_assigned once instead of four times for obvious reasons; structure is much the same as it once was but subroutines are not -- Syela */ + int time; mv_turns = (warmap.cost[x][y]) / mv_rate; - oldv = city_tile_value(pcity, i, j, 0, 0); + oldv = city_tile_value(pcity, i, j, 0, 0); /* now, consider various activities... */ - d = (map_build_irrigation_time(x, y)*3 + mv_rate - 1)/mv_rate + + time = (map_build_irrigation_time(x, y)*SINGLE_MOVE + mv_rate - 1)/mv_rate + mv_turns; consider_settler_action(pplayer, ACTIVITY_IRRIGATE, -1, - pcity->ai.irrigate[i][j], oldv, in_use, d, - &best_newv, &best_oldv, &best_act, &gx, &gy, + pcity->ai.irrigate[i][j], oldv, in_use, time, + &best_newv, &best_oldv, best_act, gx, gy, x, y); if (unit_flag(punit->type, F_TRANSFORM)) { - d = (map_transform_time(x, y)*3 + mv_rate - 1)/mv_rate + + time = (map_transform_time(x, y)*SINGLE_MOVE + mv_rate - 1)/mv_rate + mv_turns; consider_settler_action(pplayer, ACTIVITY_TRANSFORM, -1, - pcity->ai.transform[i][j], oldv, in_use, d, - &best_newv, &best_oldv, &best_act, &gx, &gy, + pcity->ai.transform[i][j], oldv, in_use, time, + &best_newv, &best_oldv, best_act, gx, gy, x, y); } - d = (map_build_mine_time(x, y)*3 + mv_rate - 1)/mv_rate + + time = (map_build_mine_time(x, y)*SINGLE_MOVE + mv_rate - 1)/mv_rate + mv_turns; consider_settler_action(pplayer, ACTIVITY_MINE, -1, - pcity->ai.mine[i][j], oldv, in_use, d, - &best_newv, &best_oldv, &best_act, &gx, &gy, + pcity->ai.mine[i][j], oldv, in_use, time, + &best_newv, &best_oldv, best_act, gx, gy, 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 + + if (!(map_get_tile(x,y)->special&S_ROAD)) { + time = (map_build_road_time(x, y)*SINGLE_MOVE + mv_rate - 1)/mv_rate + mv_turns; consider_settler_action(pplayer, ACTIVITY_ROAD, - road_bonus(x, y, S_ROAD) * 8, - pcity->ai.road[i][j], oldv, in_use, d, - &best_newv, &best_oldv, &best_act, &gx, &gy, + road_bonus(x, y, S_ROAD) * 4, + pcity->ai.road[i][j], oldv, in_use, time, + &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 + - mv_turns; + time = (map_build_rail_time(x, y) * SINGLE_MOVE + + map_build_road_time(x, y) * SINGLE_MOVE + + mv_rate - 1)/mv_rate + mv_turns; consider_settler_action(pplayer, ACTIVITY_ROAD, - road_bonus(x, y, S_RAILROAD) * 4, - pcity->ai.railroad[i][j], oldv, in_use, d, - &best_newv, &best_oldv, &best_act, &gx, &gy, + road_bonus(x, y, S_RAILROAD) * 2, + pcity->ai.railroad[i][j], oldv, in_use, time, + &best_newv, &best_oldv, best_act, gx, gy, x, y); - } else { - d = (3*3 + mv_rate - 1)/mv_rate + - mv_turns; + } else { + time = (map_build_rail_time(x, y) *SINGLE_MOVE + + mv_rate - 1)/mv_rate + mv_turns; consider_settler_action(pplayer, ACTIVITY_RAILROAD, - road_bonus(x, y, S_RAILROAD) * 4, - pcity->ai.railroad[i][j], oldv, in_use, d, - &best_newv, &best_oldv, &best_act, &gx, &gy, + road_bonus(x, y, S_RAILROAD) * 2, + pcity->ai.railroad[i][j], oldv, in_use, time, + &best_newv, &best_oldv, best_act, gx, gy, x, y); - } /* end S_ROAD else */ + } /* end S_ROAD else */ - d = (3*3 + mv_rate - 1)/mv_rate + - mv_turns; + time = (map_clean_pollution_time(x, y) * SINGLE_MOVE + + mv_rate - 1)/mv_rate + mv_turns; consider_settler_action(pplayer, ACTIVITY_POLLUTION, pplayer->ai.warmth, - pcity->ai.detox[i][j], oldv, in_use, d, - &best_newv, &best_oldv, &best_act, &gx, &gy, + pcity->ai.detox[i][j], oldv, in_use, time, + &best_newv, &best_oldv, best_act, gx, gy, x, y); - d = (3*3 + mv_rate - 1)/mv_rate + - mv_turns; + time = (map_clean_fallout_time(x, y) * SINGLE_MOVE + + mv_rate - 1)/mv_rate + mv_turns; consider_settler_action(pplayer, ACTIVITY_FALLOUT, pplayer->ai.warmth, - pcity->ai.derad[i][j], oldv, in_use, d, - &best_newv, &best_oldv, &best_act, &gx, &gy, + pcity->ai.derad[i][j], oldv, in_use, time, + &best_newv, &best_oldv, best_act, gx, gy, x, y); freelog(LOG_DEBUG, @@ -1151,46 +1166,117 @@ } city_map_iterate_outwards_end; } city_list_iterate_end; - /** Found the best square to upgrade, have gx, gy, best_newv, best_act **/ - - best_newv = (best_newv - food_upkeep * FOOD_WEIGHTING) * 100 / - (40 + food_cost); + best_newv = (best_newv - food_upkeep * FOOD_WEIGHTING) * 100 / (40 + food_cost); if (best_newv < 0) best_newv = 0; /* Bad Things happen without this line! :( -- Syela */ if (best_newv > 0) { freelog(LOG_DEBUG, "Settler %d@(%d,%d) wants to %s at (%d,%d) with desire %d", - punit->id, punit->x, punit->y, get_activity_text(best_act), - gx, gy, best_newv); + punit->id, punit->x, punit->y, get_activity_text(*best_act), + *gx, *gy, best_newv); + } + + return best_newv; +} + +/************************************************************************** +... +**************************************************************************/ +static int ai_gothere(struct unit *punit, int gx, int gy, struct unit *ferryboat) +{ + struct player *pplayer = unit_owner(punit); + int save_id = punit->id; /* in case unit dies */ + + if (!same_pos(gx, gy, punit->x, punit->y)) { + if (!goto_is_sane(punit, gx, gy, 1) + || (ferryboat + && goto_is_sane(ferryboat, gx, gy, 1) + && (!is_tiles_adjacent(punit->x, punit->y, gx, gy) + || !could_unit_move_to_tile(punit, punit->x, punit->y, + gx, gy)))) { + int x, y; + punit->ai.ferryboat = find_boat(pplayer, &x, &y, 1); /* might need 2 */ + freelog(LOG_DEBUG, "%d@(%d, %d): Looking for BOAT.", + punit->id, punit->x, punit->y); + if (!same_pos(x, y, punit->x, punit->y)) { + auto_settler_do_goto(pplayer, punit, x, y); + if (!player_find_unit_by_id(pplayer, save_id)) return 0; /* died */ + } + ferryboat = unit_list_find(&(map_get_tile(punit->x, punit->y)->units), + punit->ai.ferryboat); + punit->goto_dest_x = gx; + punit->goto_dest_y = gy; + if (ferryboat && (!ferryboat->ai.passenger + || ferryboat->ai.passenger == punit->id)) { + freelog(LOG_DEBUG, + "We have FOUND BOAT, %d ABOARD %d@(%d,%d)->(%d,%d).", + punit->id, ferryboat->id, punit->x, punit->y, gx, gy); + set_unit_activity(punit, ACTIVITY_SENTRY); + /* kinda cheating -- Syela */ + ferryboat->ai.passenger = punit->id; + auto_settler_do_goto(pplayer, ferryboat, gx, gy); + set_unit_activity(punit, ACTIVITY_IDLE); + } /* need to zero pass & ferryboat at some point. */ + } + if (goto_is_sane(punit, gx, gy, 1) + && punit->moves_left + && ((!ferryboat) + || (is_tiles_adjacent(punit->x, punit->y, gx, gy) + && could_unit_move_to_tile(punit, punit->x, punit->y, + gx, gy)))) { + auto_settler_do_goto(pplayer, punit, gx, gy); + if (!player_find_unit_by_id(pplayer, save_id)) return 0; /* died */ + punit->ai.ferryboat = 0; + } } + + return 1; +} + +/************************************************************************** + find some work for the settler +**************************************************************************/ +static void auto_settler_findwork(struct player *pplayer, struct unit *punit) +{ + int gx = -1, gy = -1; /* x,y of target (goto) square */ + int best_newv = 0; /* newv of best target so far, all cities */ + int best_act = 0; /* ACTIVITY_ of best target so far */ + struct unit *ferryboat = NULL; /* if non-null, boatid boat at unit's x,y */ + #ifdef DEBUG - save_newv = best_newv; + int save_newv; #endif - if (pplayer->ai.control) - boatid = find_boat(pplayer, &bx, &by, 1); /* might need 2 for bodyguard */ - else - boatid = 0; - ferryboat = unit_list_find(&(map_get_tile(punit->x, punit->y)->units), boatid); - if (ferryboat) - really_generate_warmap(mycity, ferryboat, SEA_MOVING); + /* First find the best square to upgrade, + * results in: gx, gy, best_newv, best_act + */ + if (unit_flag(punit->type, F_SETTLERS)) { + best_newv = evaluate_improvements(punit, &best_act,&gx, &gy); + } - /** Decide whether to build a new city: - ** if so, modify: gx, gy, best_newv, best_act */ + /* Found the best square to upgrade, have gx, gy, best_newv, best_act */ +#ifdef DEBUG + save_newv = best_newv; +#endif + + /* Decide whether to build a new city: + * if so, modify: gx, gy, best_newv, best_act + */ if (unit_flag(punit->type, F_CITIES) && pplayer->ai.control && ai_fuzzy(pplayer,1)) { /* don't want to make cities otherwise */ - evaluate_city_building(punit, - &best_act, &best_newv, &gx, &gy, - ferryboat, - boatid, bx, by, - mycity, food_cost, &choice); - } + int nx, ny; + int want = evaluate_city_building(punit, &nx, &ny, &ferryboat); - choice.want -= best_newv; - if (choice.want > 0) ai_choose_ferryboat(pplayer, mycity, &choice); + if (want > best_newv) { + best_newv = want; + best_act = ACTIVITY_UNKNOWN; + gx = nx; + gy = ny; + } + } #ifdef DEBUG if ((best_newv != save_newv) || @@ -1201,88 +1287,39 @@ get_activity_text(best_act), gx, gy, best_newv); } #endif - - /* I had the return here, but it led to stupidity where several engineers - would be built to solve one problem. Moving the return down will solve - this. -- Syela */ + /* Mark the square as taken. */ if (gx!=-1 && gy!=-1) { - map_get_tile(gx, gy)->assigned = - map_get_tile(gx, gy)->assigned | 1<player_no; + map_get_tile(gx, gy)->assigned = + map_get_tile(gx, gy)->assigned | 1<player_no; } else if (pplayer->ai.control) { /* settler has no purpose */ /* possibly add Gilligan's Island here */ ; } - /** If this is a virtual unit for assessing settler want: **/ - if (!punit->id) { - /* has to be before we try to send_unit_info()! -- Syela */ - freelog(LOG_DEBUG, - "%s (%d, %d) settler-want = %d, task = %s, target = (%d, %d)", - mycity->name, mycity->x, mycity->y, best_newv, - get_activity_text(best_act), gx, gy); - if (gx < 0 && gy < 0) { - return(0 - best_newv); - } else { - return(best_newv); - } + /* If we intent on building a city then reserve the square. */ + if (unit_flag(punit->type, F_CITIES) && + best_act == ACTIVITY_UNKNOWN /* flag */) { + punit->ai.ai_role = AIUNIT_BUILD_CITY; + /* FIXME: is the unit taken off the minimap if it dies? */ + add_city_to_minimap(gx, gy); + } else { + punit->ai.ai_role = AIUNIT_AUTO_SETTLER; } - /** We've now worked out what to do; go to it! **/ - if (gx!=-1 && gy!=-1) { - if (unit_flag(punit->type, F_CITIES) && - (best_act == ACTIVITY_UNKNOWN /* flag */)) { - punit->ai.ai_role = AIUNIT_BUILD_CITY; - add_city_to_minimap(gx, gy); - } else { - punit->ai.ai_role = AIUNIT_AUTO_SETTLER; - } - if (!same_pos(gx, gy, punit->x, punit->y)) { - if (!goto_is_sane(punit, gx, gy, 1) - || (ferryboat - && goto_is_sane(ferryboat, gx, gy, 1) - && (!is_tiles_adjacent(punit->x, punit->y, gx, gy) - || !could_unit_move_to_tile(punit, punit->x, punit->y, - gx, gy)))) { - punit->ai.ferryboat = find_boat(pplayer, &x, &y, 1); /* might need 2 */ - freelog(LOG_DEBUG, "%d@(%d, %d): Looking for BOAT.", - punit->id, punit->x, punit->y); - if (!same_pos(x, y, punit->x, punit->y)) { - auto_settler_do_goto(pplayer, punit, x, y); - if (!player_find_unit_by_id(pplayer, save_id)) return(0); /* died */ - } - ferryboat = unit_list_find(&(map_get_tile(punit->x, punit->y)->units), - punit->ai.ferryboat); - punit->goto_dest_x = gx; - punit->goto_dest_y = gy; - if (ferryboat && (!ferryboat->ai.passenger - || ferryboat->ai.passenger == punit->id)) { - freelog(LOG_DEBUG, - "We have FOUND BOAT, %d ABOARD %d@(%d,%d)->(%d,%d).", - punit->id, ferryboat->id, punit->x, punit->y, gx, gy); - set_unit_activity(punit, ACTIVITY_SENTRY); - /* kinda cheating -- Syela */ - ferryboat->ai.passenger = punit->id; - auto_settler_do_goto(pplayer, ferryboat, gx, gy); - set_unit_activity(punit, ACTIVITY_IDLE); - } /* need to zero pass & ferryboat at some point. */ - } - if (goto_is_sane(punit, gx, gy, 1) - && punit->moves_left - && ((!ferryboat) - || (is_tiles_adjacent(punit->x, punit->y, gx, gy) - && could_unit_move_to_tile(punit, punit->x, punit->y, - gx, gy)))) { - auto_settler_do_goto(pplayer, punit, gx, gy); - if (!player_find_unit_by_id(pplayer, save_id)) return(0); /* died */ - punit->ai.ferryboat = 0; - } - } - } else punit->ai.control=0; - /* The above line makes non-AI autosettlers go off auto When they run - out of squares to improve. I would like keep them on, prepared for - future pollution and warming, but there wasn't consensus to do so. */ + /* We've now worked out what to do; go to it! */ + if (gx != -1 && gy != -1) { + int survived = ai_gothere(punit, gx, gy, ferryboat); + if (!survived) + return; + } else { + /* This line makes non-AI autosettlers go off auto when they run + out of squares to improve. I would like keep them on, prepared for + future pollution and warming, but there wasn't consensus to do so. */ + punit->ai.control=0; + } + /* If we are at the destination then do the activity. */ if (punit->ai.control && punit->moves_left && punit->activity == ACTIVITY_IDLE) { @@ -1290,14 +1327,13 @@ if (best_act == ACTIVITY_UNKNOWN) { remove_city_from_minimap(gx, gy); /* yeah, I know. -- Syela */ ai_do_build_city(pplayer, punit); - return(0); + return; } set_unit_activity(punit, best_act); send_unit_info(0, punit); - return(0); + return; } } - return(0); } /************************************************************************** @@ -1339,7 +1375,9 @@ freelog(LOG_DEBUG, "Warmth = %d, game.globalwarming=%d", pplayer->ai.warmth, game.globalwarming); unit_list_iterate(pplayer->units, punit) { - if (punit->ai.control && unit_flag(punit->type, F_SETTLERS)) { + if (punit->ai.control + && (unit_flag(punit->type, F_SETTLERS) + || unit_flag(punit->type, F_CITIES))) { freelog(LOG_DEBUG, "%s's settler at (%d, %d) is ai controlled.", pplayer->name, punit->x, punit->y); if(punit->activity == ACTIVITY_SENTRY) @@ -1363,7 +1401,8 @@ int i = 1<player_no; struct tile *ptile; unit_list_iterate(pplayer->units, punit) - if (unit_flag(punit->type, F_SETTLERS)) { + if (unit_flag(punit->type, F_SETTLERS) + || unit_flag(punit->type, F_CITIES)) { if (punit->activity == ACTIVITY_GOTO) { ptile = map_get_tile(punit->goto_dest_x, punit->goto_dest_y); ptile->assigned = ptile->assigned | i; /* assigned for us only */ @@ -1460,12 +1499,17 @@ } } -void contemplate_settling(struct player *pplayer, struct city *pcity) +/************************************************************************** +used to use old crappy formulas for settler want, but now using actual +want! +**************************************************************************/ +void contemplate_new_city(struct city *pcity) { + struct player *pplayer = city_owner(pcity); struct unit virtualunit; int want; - -/* used to use old crappy formulas for settler want, but now using actual want! */ + int gx, gy; + struct unit *ferryboat = NULL; /* dummy */ memset(&virtualunit, 0, sizeof(struct unit)); virtualunit.id = 0; @@ -1475,30 +1519,49 @@ virtualunit.owner = pplayer->player_no; virtualunit.x = pcity->x; virtualunit.y = pcity->y; - virtualunit.type = best_role_unit(pcity, F_SETTLERS); + virtualunit.type = best_role_unit(pcity, F_CITIES); virtualunit.moves_left = unit_types[virtualunit.type].move_rate; virtualunit.hp = unit_types[virtualunit.type].hp; - want = auto_settler_findwork(pplayer, &virtualunit); - unit_list_iterate(pplayer->units, qpass) - if (qpass->ai.ferryboat == pcity->id) want = -199; - unit_list_iterate_end; - pcity->ai.settler_want = want; + want = evaluate_city_building(&virtualunit, &gx, &gy, &ferryboat); + unit_list_iterate(pplayer->units, qpass) { + /* We want a ferryboat with want 199 */ + if (qpass->ai.ferryboat == pcity->id) + want = -199; + } unit_list_iterate_end; - if (unit_flag(virtualunit.type, F_CITIES)) { - pcity->ai.founder_want = pcity->ai.settler_want; + if (gx == -1) { + pcity->ai.founder_want = -want; } else { - memset(&virtualunit, 0, sizeof(struct unit)); - virtualunit.id = 0; - virtualunit.owner = pplayer->player_no; - virtualunit.x = pcity->x; - virtualunit.y = pcity->y; - virtualunit.type = best_role_unit(pcity, F_CITIES); - virtualunit.moves_left = unit_types[virtualunit.type].move_rate; - virtualunit.hp = unit_types[virtualunit.type].hp; - want = auto_settler_findwork(pplayer, &virtualunit); - unit_list_iterate(pplayer->units, qpass) - if (qpass->ai.ferryboat == pcity->id) want = -199; - unit_list_iterate_end; - pcity->ai.founder_want = want; + pcity->ai.founder_want = want; /* boat */ } +} + +/************************************************************************** +used to use old crappy formulas for settler want, but now using actual +want! +**************************************************************************/ +void contemplate_terrain_improvements(struct city *pcity) +{ + struct player *pplayer = city_owner(pcity); + struct unit virtualunit; + int want; + int best_act, gx, gy; /* dummies */ + + memset(&virtualunit, 0, sizeof(struct unit)); + virtualunit.id = 0; + virtualunit.owner = pplayer->player_no; + virtualunit.x = pcity->x; + virtualunit.y = pcity->y; + virtualunit.type = best_role_unit(pcity, F_SETTLERS); + virtualunit.moves_left = unit_types[virtualunit.type].move_rate; + virtualunit.hp = unit_types[virtualunit.type].hp; + want = evaluate_improvements(&virtualunit, &best_act, &gx, &gy); + unit_list_iterate(pplayer->units, qpass) { + /* We want a ferryboat with want 199 */ + if (qpass->ai.ferryboat == pcity->id) + want = -199; + } unit_list_iterate_end; + + + pcity->ai.settler_want = want; } diff -Nur -X/mnt/data/freeciv-dev/freeciv/diff_ignore freeciv/server/settlers.h codeciv/server/settlers.h --- freeciv/server/settlers.h Thu Jun 21 22:36:26 2001 +++ codeciv/server/settlers.h Fri Jun 22 00:55:02 2001 @@ -32,7 +32,10 @@ void remove_city_from_minimap(int x, int y); void add_city_to_minimap(int x, int y); void initialize_infrastructure_cache(struct city *pcity); -void contemplate_settling(struct player *pplayer, struct city *pcity); + +void contemplate_terrain_improvements(struct city *pcity); +void contemplate_new_city(struct city *pcity); + struct unit *other_passengers(struct unit *punit); extern signed int minimap[MAP_MAX_WIDTH][MAP_MAX_HEIGHT]; diff -Nur -X/mnt/data/freeciv-dev/freeciv/diff_ignore freeciv/server/unittools.c codeciv/server/unittools.c --- freeciv/server/unittools.c Thu Jun 21 22:36:26 2001 +++ codeciv/server/unittools.c Fri Jun 22 17:26:49 2001 @@ -940,7 +940,7 @@ /* to allow a settler to begin a task with no moves left without it counting toward the time to finish */ if (punit->moves_left){ - punit->activity_count += mr/3; + punit->activity_count += mr/SINGLE_MOVE; } unit_restore_movepoints(pplayer, punit); @@ -994,28 +994,32 @@ } if (activity==ACTIVITY_POLLUTION) { - if (total_activity (punit->x, punit->y, ACTIVITY_POLLUTION) >= 3) { + if (total_activity (punit->x, punit->y, ACTIVITY_POLLUTION) + >= map_clean_pollution_time(punit->x, punit->y)) { 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) { + if (total_activity (punit->x, punit->y, ACTIVITY_FALLOUT) + >= map_clean_fallout_time(punit->x, punit->y)) { 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) { + if (total_activity (punit->x, punit->y, ACTIVITY_FORTRESS) + >= map_build_fortress_time(punit->x, punit->y)) { 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) { + if (total_activity (punit->x, punit->y, ACTIVITY_AIRBASE) + >= map_build_airbase_time(punit->x, punit->y)) { map_set_special(punit->x, punit->y, S_AIRBASE); unit_activity_done = 1; } @@ -1041,7 +1045,8 @@ } if (activity==ACTIVITY_RAILROAD) { - if (total_activity (punit->x, punit->y, ACTIVITY_RAILROAD) >= 3) { + if (total_activity (punit->x, punit->y, ACTIVITY_RAILROAD) + >= map_build_rail_time(punit->x, punit->y)) { map_set_special(punit->x, punit->y, S_RAILROAD); unit_activity_done = 1; }