Author: cazfi Date: Fri Apr 24 17:34:48 2015 New Revision: 28857 URL: http://svn.gna.org/viewcvs/freeciv?rev=28857&view=rev Log: Turned inner part of tai_city_worker_task_select(), checking single tile, to a separate function
See patch #6025 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=28857&r1=28856&r2=28857&view=diff ============================================================================== --- trunk/ai/threaded/taicity.c (original) +++ trunk/ai/threaded/taicity.c Fri Apr 24 17:34:48 2015 @@ -77,57 +77,135 @@ } } +struct tai_tile_state +{ + int uw_max; + int worst_worked; + int orig_worst_worked; + int old_worst_worked; +}; + /************************************************************************** - 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 - though this has started as almost-copy of - settler_evaluate_improvements(), this is likely to turn very different - function as part of threaded ai with more CPU to burn. + Select worker task suitable for the tile. **************************************************************************/ -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 }; - struct worker_task unworked = { .ptile = NULL, .want = 0, .act = ACTIVITY_IDLE, .tgt = NULL }; - int uw_max = 0; - int worst_worked = FC_INFINITY; - int old_worst_worked = FC_INFINITY; - int orig_worst_worked = 0; - 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) { - int orig_value; - bool potential_worst_worked = FALSE; - - if (!city_can_work_tile(pcity, ptile)) { +static void tai_tile_worker_task_select(struct player *pplayer, + struct city *pcity, struct tile *ptile, + int cindex, struct unit_list *units, + struct worker_task *worked, + struct worker_task *unworked, + struct tai_tile_state *state) +{ + int orig_value; + bool potential_worst_worked = FALSE; + + if (!city_can_work_tile(pcity, ptile)) { + return; + } + + orig_value = city_tile_value(pcity, ptile, 0, 0); + + if (tile_worked(ptile) == pcity + && orig_value < state->worst_worked) { + state->worst_worked = orig_value; + state->orig_worst_worked = orig_value; + potential_worst_worked = TRUE; + } + + as_transform_activity_iterate(act) { + bool consider = TRUE; + bool possible = FALSE; + enum extra_cause cause; + enum extra_rmcause rmcause; + + /* Do not request activities that already are under way. */ + unit_list_iterate(ptile->units, punit) { + if (unit_owner(punit) == pplayer + && unit_has_type_flag(punit, UTYF_SETTLERS) + && punit->activity == act) { + consider = FALSE; + break; + } + } unit_list_iterate_end; + + if (!consider) { continue; } - orig_value = city_tile_value(pcity, ptile, 0, 0); - - if (tile_worked(ptile) == pcity - && orig_value < worst_worked) { - worst_worked = orig_value; - orig_worst_worked = orig_value; - potential_worst_worked = TRUE; + cause = activity_to_extra_cause(act); + 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) * TWMP > worked->want) { + worked->want = TWMP * (value - orig_value); + worked->ptile = ptile; + worked->act = act; + worked->tgt = NULL; + } + if (value > state->old_worst_worked) { + /* After improvement it would not be the worst */ + potential_worst_worked = FALSE; + } else { + state->worst_worked = value; + } + } else { + if (value > orig_value && value > state->uw_max) { + state->uw_max = value; + unworked->want = TWMP * (value - orig_value); + unworked->ptile = ptile; + unworked->act = act; + unworked->tgt = NULL; + } + } } - - as_transform_activity_iterate(act) { + } as_transform_activity_iterate_end; + + extra_type_iterate(tgt) { + enum unit_activity act = ACTIVITY_LAST; + bool removing = tile_has_extra(ptile, tgt); + + unit_list_iterate(units, punit) { + if (removing) { + as_rmextra_activity_iterate(try_act) { + if (is_extra_removed_by_action(tgt, try_act) + && can_unit_do_activity_targeted_at(punit, try_act, tgt, ptile)) { + act = try_act; + break; + } + } as_rmextra_activity_iterate_end; + } else { + as_extra_activity_iterate(try_act) { + if (is_extra_caused_by_action(tgt, try_act) + && can_unit_do_activity_targeted_at(punit, try_act, tgt, ptile)) { + act = try_act; + break; + } + } as_extra_activity_iterate_end; + } + } unit_list_iterate_end; + + if (act != ACTIVITY_LAST) { + int value; + int extra; bool consider = TRUE; - bool possible = FALSE; - enum extra_cause cause; - enum extra_rmcause rmcause; + struct road_type *proad; /* Do not request activities that already are under way. */ unit_list_iterate(ptile->units, punit) { @@ -143,175 +221,112 @@ continue; } - cause = activity_to_extra_cause(act); - 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) * TWMP > worked.want) { - worked.want = TWMP * (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 = TWMP * (value - orig_value); - unworked.ptile = ptile; - unworked.act = act; - unworked.tgt = NULL; - } - } - } - } as_transform_activity_iterate_end; - - extra_type_iterate(tgt) { - enum unit_activity act = ACTIVITY_LAST; - bool removing = tile_has_extra(ptile, tgt); - - unit_list_iterate(units, punit) { - if (removing) { - as_rmextra_activity_iterate(try_act) { - if (is_extra_removed_by_action(tgt, try_act) - && can_unit_do_activity_targeted_at(punit, try_act, tgt, ptile)) { - act = try_act; - break; - } - } as_rmextra_activity_iterate_end; - } else { - as_extra_activity_iterate(try_act) { - if (is_extra_caused_by_action(tgt, try_act) - && can_unit_do_activity_targeted_at(punit, try_act, tgt, ptile)) { - act = try_act; - break; - } - } as_extra_activity_iterate_end; - } - } unit_list_iterate_end; - - if (act != ACTIVITY_LAST) { - int value; - int extra; - bool consider = TRUE; - struct road_type *proad; - - /* Do not request activities that already are under way. */ - unit_list_iterate(ptile->units, punit) { - if (unit_owner(punit) == pplayer - && unit_has_type_flag(punit, UTYF_SETTLERS) - && punit->activity == act) { - consider = FALSE; - break; - } - } unit_list_iterate_end; - - if (!consider) { - continue; - } - - proad = extra_road_get(tgt); - - value = adv_city_worker_extra_get(pcity, cindex, tgt); - - if (proad != NULL && road_provides_move_bonus(proad)) { - int old_move_cost; - int mc_multiplier = 1; - int mc_divisor = 1; - - /* Here 'old' means actually 'without the evaluated': In case of - * removal activity it's the value after the removal. */ - old_move_cost = tile_terrain(ptile)->movement_cost * SINGLE_MOVE; - - road_type_iterate(pold) { - if (tile_has_road(ptile, pold) && pold != proad) { - 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; + proad = extra_road_get(tgt); + + value = adv_city_worker_extra_get(pcity, cindex, tgt); + + if (proad != NULL && road_provides_move_bonus(proad)) { + int old_move_cost; + int mc_multiplier = 1; + int mc_divisor = 1; + + /* Here 'old' means actually 'without the evaluated': In case of + * removal activity it's the value after the removal. */ + old_move_cost = tile_terrain(ptile)->movement_cost * SINGLE_MOVE; + + road_type_iterate(pold) { + if (tile_has_road(ptile, pold) && pold != proad) { + if (road_provides_move_bonus(pold) + && pold->move_cost < old_move_cost) { + old_move_cost = pold->move_cost; } } - - extra = adv_settlers_road_bonus(ptile, proad) * mc_multiplier / mc_divisor; - - if (removing) { - extra = -extra; + } 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; + + if (removing) { + extra = -extra; + } + } else { + extra = 0; + } + + value += extra; + + if (tile_worked(ptile) == pcity) { + if ((value - orig_value) * TWMP > worked->want) { + worked->want = TWMP * (value - orig_value); + worked->ptile = ptile; + worked->act = act; + worked->tgt = tgt; + } + if (value > state->old_worst_worked) { + /* After improvement it would not be the worst */ + potential_worst_worked = FALSE; } else { - extra = 0; - } - - value += extra; - - if (tile_worked(ptile) == pcity) { - if ((value - orig_value) * TWMP > worked.want) { - worked.want = TWMP * (value - orig_value); - worked.ptile = ptile; - worked.act = act; - worked.tgt = tgt; - } - 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 = TWMP * (value - orig_value); - unworked.ptile = ptile; - unworked.act = act; - unworked.tgt = tgt; - } - } - } - } extra_type_iterate_end; - - if (potential_worst_worked) { - /* Would still be worst worked even if we improved *it*. */ - old_worst_worked = worst_worked; + state->worst_worked = value; + } + } else { + if (value > orig_value && value > state->uw_max) { + state->uw_max = value; + unworked->want = TWMP * (value - orig_value); + unworked->ptile = ptile; + unworked->act = act; + unworked->tgt = tgt; + } + } } + } extra_type_iterate_end; + + if (potential_worst_worked) { + /* Would still be worst worked even if we improved *it*. */ + state->old_worst_worked = state->worst_worked; + } +} + +/************************************************************************** + Select worker task suitable for the city. +**************************************************************************/ +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 }; + struct worker_task unworked = { .ptile = NULL, .want = 0, .act = ACTIVITY_IDLE, .tgt = NULL }; + struct tai_tile_state state = { .uw_max = 0, .worst_worked = FC_INFINITY, + .orig_worst_worked = 0, .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) { + tai_tile_worker_task_select(pplayer, pcity, ptile, cindex, units, &worked, &unworked, + &state); } city_tile_iterate_end; if (worked.ptile == NULL - || (old_worst_worked < uw_max && (uw_max - orig_worst_worked) * TWMP > worked.want)) { + || (state.old_worst_worked < state.uw_max + && (state.uw_max - state.orig_worst_worked) * TWMP > worked.want)) { /* It's better to improve best yet unworked tile and take it to use after that, than to improve already worked tile. */ selected = &unworked; _______________________________________________ Freeciv-commits mailing list Freeciv-commits@gna.org https://mail.gna.org/listinfo/freeciv-commits