Author: cazfi Date: Tue Dec 9 23:49:20 2014 New Revision: 27224 URL: http://svn.gna.org/viewcvs/freeciv?rev=27224&view=rev Log: Threaded AI cities set only such worker tasks that current units can do.
See patch #5496 Modified: trunk/ai/threaded/taicity.c Modified: trunk/ai/threaded/taicity.c URL: http://svn.gna.org/viewcvs/freeciv/trunk/ai/threaded/taicity.c?rev=27224&r1=27223&r2=27224&view=diff ============================================================================== --- trunk/ai/threaded/taicity.c (original) +++ trunk/ai/threaded/taicity.c Tue Dec 9 23:49:20 2014 @@ -45,8 +45,36 @@ struct worker_task task; }; +enum tai_worker_task_limitation { + TWTL_CURRENT_UNITS +}; + +static bool tai_city_worker_task_select(struct player *pplayer, struct city *pcity, + struct worker_task *task, + enum tai_worker_task_limitation limit); + /************************************************************************** - Create worker request for the city. + Create worker request for the city. Only tasks that existing units can + do are created. +**************************************************************************/ +void tai_city_worker_requests_create(struct player *pplayer, struct city *pcity) +{ + struct worker_task task; + + if (tai_city_worker_task_select(pplayer, pcity, &task, TWTL_CURRENT_UNITS)) { + struct tai_worker_task_req *data = fc_malloc(sizeof(*data)); + + data->city_id = pcity->id; + data->task.ptile = task.ptile; + data->task.act = task.act; + data->task.tgt = task.tgt; + + tai_send_req(TAI_REQ_WORKER_TASK, pplayer, data); + } +} + +/************************************************************************** + Select worker task suitable for the city. TODO: This largely duplicates settler_evaluate_improvements(). Should maybe find a way to reuse parts in some common function. OTOH @@ -54,7 +82,9 @@ settler_evaluate_improvements(), this is likely to turn very different function as part of threaded ai with more CPU to burn. **************************************************************************/ -void tai_city_worker_requests_create(struct player *pplayer, struct city *pcity) +static bool tai_city_worker_task_select(struct player *pplayer, struct city *pcity, + struct worker_task *task, + enum tai_worker_task_limitation limit) { struct worker_task *selected; struct worker_task worked = { .ptile = NULL, .want = 0, .act = ACTIVITY_IDLE, .tgt = NULL }; @@ -62,6 +92,13 @@ int uw_max = 0; int worst_worked = FC_INFINITY; int old_worst_worked = FC_INFINITY; + struct unit_list *units = NULL; + + switch (limit) { + case TWTL_CURRENT_UNITS: + units = pplayer->units; + break; + } city_tile_iterate_index(city_map_radius_sq_get(pcity), city_tile(pcity), ptile, cindex) { @@ -99,13 +136,116 @@ || act == ACTIVITY_MINE || act == ACTIVITY_POLLUTION || act == ACTIVITY_FALLOUT) { - int value = adv_city_worker_act_get(pcity, cindex, act); + bool possible = FALSE; + enum extra_cause cause = activity_to_extra_cause(act); + enum extra_rmcause rmcause = activity_to_extra_rmcause(act); + + unit_list_iterate(units, punit) { + struct extra_type *tgt = NULL; + + if (cause != EC_NONE) { + tgt = next_extra_for_tile(ptile, cause, pplayer, punit); + } else if (rmcause != ERM_NONE) { + tgt = prev_extra_in_tile(ptile, rmcause, pplayer, punit); + } + + if (can_unit_do_activity_targeted_at(punit, act, tgt, ptile)) { + possible = TRUE; + break; + } + } unit_list_iterate_end; + + if (possible) { + int value = adv_city_worker_act_get(pcity, cindex, act); + + if (tile_worked(ptile) == pcity) { + if (value - orig_value > worked.want) { + worked.want = value - orig_value; + worked.ptile = ptile; + worked.act = act; + worked.tgt = NULL; + } + if (value > old_worst_worked) { + /* After improvement it would not be the worst */ + potential_worst_worked = FALSE; + } else { + worst_worked = value; + } + } else { + if (value > orig_value && value > uw_max) { + uw_max = value; + unworked.want = value - orig_value; + unworked.ptile = ptile; + unworked.act = act; + unworked.tgt = NULL; + } + } + } + } + } activity_type_iterate_end; + + road_type_iterate(proad) { + bool possible = FALSE; + + unit_list_iterate(units, punit) { + struct extra_type *tgt = road_extra_get(proad); + + if (can_unit_do_activity_targeted_at(punit, ACTIVITY_GEN_ROAD, tgt, ptile)) { + possible = TRUE; + break; + } + } unit_list_iterate_end; + + if (possible) { + int value; + int extra; + struct extra_type *pextra; + + pextra = road_extra_get(proad); + value = adv_city_worker_extra_get(pcity, cindex, pextra); + + if (road_provides_move_bonus(proad)) { + int old_move_cost; + int mc_multiplier = 1; + int mc_divisor = 1; + + old_move_cost = tile_terrain(ptile)->movement_cost * SINGLE_MOVE; + + road_type_iterate(pold) { + if (tile_has_road(ptile, pold)) { + if (road_provides_move_bonus(pold) + && pold->move_cost < old_move_cost) { + old_move_cost = pold->move_cost; + } + } + } road_type_iterate_end; + + if (proad->move_cost < old_move_cost) { + if (proad->move_cost >= terrain_control.move_fragments) { + mc_divisor = proad->move_cost / terrain_control.move_fragments; + } else { + if (proad->move_cost == 0) { + mc_multiplier = 2; + } else { + mc_multiplier = 1 - proad->move_cost; + } + mc_multiplier += old_move_cost; + } + } + + extra = adv_settlers_road_bonus(ptile, proad) * mc_multiplier / mc_divisor; + + } else { + extra = 0; + } + + value += extra; if (tile_worked(ptile) == pcity) { if (value - orig_value > worked.want) { worked.want = value - orig_value; worked.ptile = ptile; - worked.act = act; + worked.act = ACTIVITY_GEN_ROAD; worked.tgt = NULL; } if (value > old_worst_worked) { @@ -119,117 +259,53 @@ uw_max = value; unworked.want = value - orig_value; unworked.ptile = ptile; - unworked.act = act; + unworked.act = ACTIVITY_GEN_ROAD; unworked.tgt = NULL; } } } - } activity_type_iterate_end; - - road_type_iterate(proad) { - int value; - int extra; - struct extra_type *pextra; - - if (!player_can_build_road(proad, pplayer, ptile)) { - continue; - } - - pextra = road_extra_get(proad); - value = adv_city_worker_extra_get(pcity, cindex, pextra); - - if (road_provides_move_bonus(proad)) { - int old_move_cost; - int mc_multiplier = 1; - int mc_divisor = 1; - - old_move_cost = tile_terrain(ptile)->movement_cost * SINGLE_MOVE; - - road_type_iterate(pold) { - if (tile_has_road(ptile, pold)) { - if (road_provides_move_bonus(pold) - && pold->move_cost < old_move_cost) { - old_move_cost = pold->move_cost; - } - } - } road_type_iterate_end; - - if (proad->move_cost < old_move_cost) { - if (proad->move_cost >= terrain_control.move_fragments) { - mc_divisor = proad->move_cost / terrain_control.move_fragments; + } road_type_iterate_end; + + base_type_iterate(pbase) { + bool possible = FALSE; + + unit_list_iterate(units, punit) { + struct extra_type *tgt = base_extra_get(pbase); + + if (can_unit_do_activity_targeted_at(punit, ACTIVITY_BASE, tgt, ptile)) { + possible = TRUE; + break; + } + } unit_list_iterate_end; + + if (possible) { + int value; + struct extra_type *pextra; + + pextra = base_extra_get(pbase); + value = adv_city_worker_extra_get(pcity, cindex, pextra); + + if (tile_worked(ptile) == pcity) { + if (value - orig_value > worked.want) { + worked.want = value - orig_value; + worked.ptile = ptile; + worked.act = ACTIVITY_BASE; + worked.tgt = NULL; + } + if (value > old_worst_worked) { + /* After improvement it would not be the worst */ + potential_worst_worked = FALSE; } else { - if (proad->move_cost == 0) { - mc_multiplier = 2; - } else { - mc_multiplier = 1 - proad->move_cost; - } - mc_multiplier += old_move_cost; - } - } - - extra = adv_settlers_road_bonus(ptile, proad) * mc_multiplier / mc_divisor; - - } else { - extra = 0; - } - - value += extra; - - if (tile_worked(ptile) == pcity) { - if (value - orig_value > worked.want) { - worked.want = value - orig_value; - worked.ptile = ptile; - worked.act = ACTIVITY_GEN_ROAD; - worked.tgt = NULL; - } - if (value > old_worst_worked) { - /* After improvement it would not be the worst */ - potential_worst_worked = FALSE; + worst_worked = value; + } } else { - worst_worked = value; - } - } else { - if (value > orig_value && value > uw_max) { - uw_max = value; - unworked.want = value - orig_value; - unworked.ptile = ptile; - unworked.act = ACTIVITY_GEN_ROAD; - unworked.tgt = NULL; - } - } - } road_type_iterate_end; - - base_type_iterate(pbase) { - int value; - struct extra_type *pextra; - - if (!player_can_build_base(pbase, pplayer, ptile)) { - continue; - } - - pextra = base_extra_get(pbase); - value = adv_city_worker_extra_get(pcity, cindex, pextra); - - if (tile_worked(ptile) == pcity) { - if (value - orig_value > worked.want) { - worked.want = value - orig_value; - worked.ptile = ptile; - worked.act = ACTIVITY_BASE; - worked.tgt = NULL; - } - if (value > old_worst_worked) { - /* After improvement it would not be the worst */ - potential_worst_worked = FALSE; - } else { - worst_worked = value; - } - } else { - if (value > orig_value && value > uw_max) { - uw_max = value; - unworked.want = value - orig_value; - unworked.ptile = ptile; - unworked.act = ACTIVITY_BASE; - unworked.tgt = NULL; + if (value > orig_value && value > uw_max) { + uw_max = value; + unworked.want = value - orig_value; + unworked.ptile = ptile; + unworked.act = ACTIVITY_BASE; + unworked.tgt = NULL; + } } } } base_type_iterate_end; @@ -249,13 +325,9 @@ } if (selected->ptile != NULL) { - struct tai_worker_task_req *data = fc_malloc(sizeof(*data)); struct extra_type *target = NULL; - log_debug("%s: act %d at (%d,%d)", pcity->name, selected->act, - TILE_XY(selected->ptile)); - - if (selected->tgt == NULL) { + if (selected->tgt == NULL) { enum extra_cause cause = activity_to_extra_cause(selected->act); if (cause != EC_NONE) { @@ -271,13 +343,14 @@ target = selected->tgt; } - data->city_id = pcity->id; - data->task.ptile = selected->ptile; - data->task.act = selected->act; - data->task.tgt = target; - - tai_send_req(TAI_REQ_WORKER_TASK, pplayer, data); - } + task->ptile = selected->ptile; + task->act = selected->act; + task->tgt = target; + + return TRUE; + } + + return FALSE; } /************************************************************************** _______________________________________________ Freeciv-commits mailing list Freeciv-commits@gna.org https://mail.gna.org/listinfo/freeciv-commits