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 Sat Jun 23 01:34:32 2001 @@ -710,7 +710,7 @@ } /*************************************************************** -.. +... ***************************************************************/ int map_build_road_time(int x, int y) { @@ -744,6 +744,46 @@ /*************************************************************** ... ***************************************************************/ +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; +} + +/*************************************************************** +... +***************************************************************/ static void clear_infrastructure(int x, int y) { map_clear_special(x, y, S_ROAD); @@ -859,6 +899,58 @@ if (result != T_LAST) change_terrain(x, y, result); +} + +/************************************************************************** +This function returns true if the tile at the given location can be +"reclaimed" from ocean into land. This is the case only when there are +a sufficient number of adjacent tiles that are not ocean. +**************************************************************************/ +int can_reclaim_ocean(int x, int y) +{ + int landtiles; + + if (terrain_control.ocean_reclaim_requirement >= 9) + return 0; + if (terrain_control.ocean_reclaim_requirement <= 0) + return 1; + + landtiles = 0; + adjc_iterate(x, y, x1, y1) { + if (map_get_tile(x1, y1)->terrain != T_OCEAN) { + landtiles++; + } + if (landtiles >= terrain_control.ocean_reclaim_requirement) + return 1; + } adjc_iterate_end; + + return 0; +} + +/************************************************************************** +This function returns true if the tile at the given location can be +"channeled" from land into ocean. This is the case only when there are +a sufficient number of adjacent tiles that are ocean. +**************************************************************************/ +int can_channel_land(int x, int y) +{ + int oceantiles; + + if (terrain_control.land_channel_requirement >= 9) + return 0; + if (terrain_control.land_channel_requirement <= 0) + return 1; + + oceantiles = 0; + adjc_iterate(x, y, x1, y1) { + if (map_get_tile(x1, y1)->terrain == T_OCEAN) { + oceantiles++; + } + if (oceantiles >= terrain_control.land_channel_requirement) + return 1; + } adjc_iterate_end; + + return 0; } /*************************************************************** 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 Sat Jun 23 01:33:51 2001 @@ -249,6 +249,14 @@ 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); + +int can_channel_land(int x, int y); +int can_reclaim_ocean(int x, int y); extern struct civ_map map; diff -Nur -X/mnt/data/freeciv-dev/freeciv/diff_ignore freeciv/common/unit.c codeciv/common/unit.c --- freeciv/common/unit.c Thu Jun 21 22:36:12 2001 +++ codeciv/common/unit.c Sat Jun 23 01:34:24 2001 @@ -553,58 +553,6 @@ } /************************************************************************** -This function returns true if the tile at the given location can be -"reclaimed" from ocean into land. This is the case only when there are -a sufficient number of adjacent tiles that are not ocean. -**************************************************************************/ -static int can_reclaim_ocean(int x, int y) -{ - int landtiles; - - if (terrain_control.ocean_reclaim_requirement >= 9) - return 0; - if (terrain_control.ocean_reclaim_requirement <= 0) - return 1; - - landtiles = 0; - adjc_iterate(x, y, x1, y1) { - if (map_get_tile(x1, y1)->terrain != T_OCEAN) { - landtiles++; - } - if (landtiles >= terrain_control.ocean_reclaim_requirement) - return 1; - } adjc_iterate_end; - - return 0; -} - -/************************************************************************** -This function returns true if the tile at the given location can be -"channeled" from land into ocean. This is the case only when there are -a sufficient number of adjacent tiles that are ocean. -**************************************************************************/ -static int can_channel_land(int x, int y) -{ - int oceantiles; - - if (terrain_control.land_channel_requirement >= 9) - return 0; - if (terrain_control.land_channel_requirement <= 0) - return 1; - - oceantiles = 0; - adjc_iterate(x, y, x1, y1) { - if (map_get_tile(x1, y1)->terrain == T_OCEAN) { - oceantiles++; - } - if (oceantiles >= terrain_control.land_channel_requirement) - return 1; - } adjc_iterate_end; - - return 0; -} - -/************************************************************************** Check if the unit's current activity is actually legal. **************************************************************************/ int can_unit_continue_current_activity(struct unit *punit) diff -Nur -X/mnt/data/freeciv-dev/freeciv/diff_ignore freeciv/game codeciv/game --- freeciv/game Thu Jan 1 01:00:00 1970 +++ codeciv/game Sat Jun 23 01:40:34 2001 @@ -0,0 +1,69 @@ +#FREECIV SERVER COMMAND FILE, version 1.11.5-devel +# These are server options saved from a running civserver. +cmdlevel info new +cmdlevel info first +hard +set xsize 40 +set ysize 25 +set generator 1 +set landmass 85 +set mountains 30 +set rivers 50 +set grass 35 +set forests 20 +set swamps 5 +set deserts 5 +set seed 175311008 +set randseed 993243280 +set specials 250 +set huts 50 +set minplayers 1 +set maxplayers 1 +set aifill 0 +set settlers 10 +set explorer 10 +set dispersion 0 +set gold 50 +set techlevel 3 +set techs default +set governments default +set units default +set buildings default +set terrain default +set nations default +set cities default +set game default +set researchcost 10 +set techpenalty 100 +set diplcost 0 +set conquercost 0 +set freecost 0 +set foodbox 10 +set aqueductloss 0 +set unhappysize 4 +set cityfactor 14 +set razechance 20 +set civstyle 2 +set occupychance 0 +set killcitizen 1 +set barbarians 0 +set onsetbarbs -2000 +set fogofwar 1 +set diplchance 80 +set spacerace 0 +set civilwarsize 10 +set allowconnect NHAhad +set autotoggle 0 +set endyear 5000 +set timeout 0 +set tcptimeout 10 +set netwait 4 +set pingtimeout 60 +set turnblock 0 +set fixedlength 0 +set demography NASRLPEMOqrb +set saveturns 10 +set compress 6 +set savename civgame +set scorelog 0 +set gamelog 20 Binary files freeciv/lala.gz and codeciv/lala.gz differ diff -Nur -X/mnt/data/freeciv-dev/freeciv/diff_ignore freeciv/server/citytools.h codeciv/server/citytools.h --- freeciv/server/citytools.h Thu Jun 21 22:36:24 2001 +++ codeciv/server/citytools.h Sat Jun 23 00:30:05 2001 @@ -26,7 +26,7 @@ 18 is too high */ #define POLLUTION_WEIGHTING 14 /* tentative */ -#define WARMING_FACTOR 32 /* tentative */ +#define WARMING_FACTOR 50 int city_got_barracks(struct city *pcity); int can_sell_building(struct city *pcity, int id); 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 Sat Jun 23 02:17:49 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, @@ -586,6 +585,11 @@ type = get_tile_type(t); s = ptile->special; r = type->transform_result; + + if (t == T_OCEAN && !can_reclaim_ocean(x, y)) + return -1; + if (r == T_OCEAN && !can_channel_land(x, y)) + return -1; if ((t == T_ARCTIC || t == T_DESERT || t == T_JUNGLE || t == T_SWAMP || t == T_TUNDRA || t == T_MOUNTAINS) && r != T_LAST) { @@ -835,17 +839,16 @@ int consider; if (extra >= 0) { - consider = (newv >= 0); + consider = 1; } else { - consider = (newv >= oldv); + consider = (newv > oldv); } if (consider) { - if (extra >= 0) { - newv = MAX(newv, oldv) + extra; - } + int diff = newv-oldv; /* give squares which can be improved and are currently in use a bonus */ - b = MAX((newv - oldv)*((in_use) ? 64:32), MORT); + b = diff * (in_use ? 64 : 16) + extra * 64; + b = MAX(0, b); a = amortize(b, d); newv = ((a * b) / (MAX(1, b - a)))/64; } else { @@ -865,6 +868,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 +909,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 +958,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 +972,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 +1021,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 +1039,42 @@ } } } 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); + int can_rr = player_knows_techs_with_flag(pplayer, TF_RAILROAD); -#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,81 +1082,88 @@ 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) * 5, + 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) * 3, + 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 if (!(map_get_tile(x, y)->special&S_RAILROAD) + && can_rr) { + 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) * 3, + 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; - 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, - x, y); - - d = (3*3 + 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, - x, y); + if (map_get_special(x, y) & S_POLLUTION) { + 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, time, + &best_newv, &best_oldv, best_act, gx, gy, + x, y); + } + + if (map_get_special(x, y) & S_FALLOUT) { + 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, time, + &best_newv, &best_oldv, best_act, gx, gy, + x, y); + } freelog(LOG_DEBUG, "(%d %d) I=%+-4d O=%+-4d M=%+-4d R=%+-4d RR=%+-4d P=%+-4d N=%+-4d", @@ -1151,46 +1176,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 +1297,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 +1337,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); } /************************************************************************** @@ -1333,13 +1379,15 @@ city_list_iterate(pplayer->cities, pcity) initialize_infrastructure_cache(pcity); /* saves oodles of time -- Syela */ city_list_iterate_end; - pplayer->ai.warmth = WARMING_FACTOR * total_player_citizens(pplayer) * 10 * - (game.globalwarming + game.heating) / (map.xsize * - map.ysize * map.landpercent * 2); /* threat of warming */ + + pplayer->ai.warmth = WARMING_FACTOR * (game.heating > game.warminglevel ? 2 : 1); + 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 +1411,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 +1509,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 +1529,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; }