Skip to content

Commit

Permalink
Cache specialists outputs in governor code
Browse files Browse the repository at this point in the history
This avoids a large number of effect evaluations, speeding things up
significantly.
  • Loading branch information
lmoureaux committed Jul 7, 2024
1 parent 059db33 commit 018b46e
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 11 deletions.
18 changes: 13 additions & 5 deletions common/aicore/cm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,9 @@ struct cm_state {
// the output of tiles the city works for free.
std::array<int, O_LAST> city_center_output = {0};

// specialist outputs
std::vector<std::array<int, O_LAST>> specialist_outputs = {};

// cached government centers to avoid looping through all cities
std::vector<city *> gov_centers;

Expand Down Expand Up @@ -698,7 +701,7 @@ static void apply_solution(struct cm_state *state,

// Finally we must refresh the city to reset all the precomputed fields.
city_refresh_from_main_map(pcity, state->workers_map, state->gov_centers,
&state->waste);
&state->waste, &state->specialist_outputs);
fc_assert_ret(citizen_count == city_size_get(pcity));
}

Expand Down Expand Up @@ -969,7 +972,7 @@ static void tile_type_lattice_add(struct tile_type_vector *lattice,
Create lattice nodes for each type of specialist. This adds a new
tile_type for each specialist type.
*/
static void init_specialist_lattice_nodes(struct tile_type_vector *lattice,
static void init_specialist_lattice_nodes(struct cm_state *state,
const struct city *pcity)
{
struct cm_tile_type type;
Expand All @@ -981,16 +984,21 @@ static void init_specialist_lattice_nodes(struct tile_type_vector *lattice,
* the bonus for the specialist (if the city is allowed to use it) */
specialist_type_iterate(i)
{
std::array<int, O_LAST> outputs = {0};

if (city_can_use_specialist(pcity, i)) {
type.spec = i;
output_type_iterate(output)
{
type.production[output] = get_specialist_output(pcity, i, output);
outputs[output] = get_specialist_output(pcity, i, output);
type.production[output] = outputs[output];
}
output_type_iterate_end;

tile_type_lattice_add(lattice, &type, 0);
tile_type_lattice_add(&state->lattice, &type, 0);
}

state->specialist_outputs.push_back(outputs);
}
specialist_type_iterate_end;
}
Expand Down Expand Up @@ -1220,7 +1228,7 @@ static void init_tile_lattice(struct city *pcity, struct cm_state *state)

// Add all the specialists into the lattice.
if (state->parameter.allow_specialists) {
init_specialist_lattice_nodes(&state->lattice, pcity);
init_specialist_lattice_nodes(state, pcity);
}

// Set the lattice_depth fields, and clean up unreachable nodes.
Expand Down
12 changes: 8 additions & 4 deletions common/city.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2235,15 +2235,18 @@ static inline void get_worked_tile_output(const struct city *pcity,
Calculate output (gold, science, and luxury) generated by the specialists
of a city. The output[] array is not cleared but is just added to.
*/
void add_specialist_output(const struct city *pcity, int *output)
void add_specialist_output(
const struct city *pcity, int *output,
const std::vector<std::array<int, O_LAST>> *pcsoutputs)
{
specialist_type_iterate(sp)
{
int count = pcity->specialists[sp];

output_type_iterate(stat_index)
{
int amount = get_specialist_output(pcity, sp, stat_index);
int amount = pcsoutputs ? pcsoutputs->at(sp)[stat_index]
: get_specialist_output(pcity, sp, stat_index);

output[stat_index] += count * amount;
}
Expand Down Expand Up @@ -3027,7 +3030,8 @@ static inline void city_support(struct city *pcity)
void city_refresh_from_main_map(
struct city *pcity, bool *workers_map,
const std::vector<city *> &gov_centers,
const std::array<cached_waste, O_LAST> *pcwaste)
const std::array<cached_waste, O_LAST> *pcwaste,
const std::vector<std::array<int, O_LAST>> *pcsoutputs)
{
if (workers_map == nullptr) {
// do a full refresh
Expand All @@ -3042,7 +3046,7 @@ void city_refresh_from_main_map(

// Calculate output from citizens (uses city_tile_cache_get_output()).
get_worked_tile_output(pcity, pcity->citizen_base, workers_map);
add_specialist_output(pcity, pcity->citizen_base);
add_specialist_output(pcity, pcity->citizen_base, pcsoutputs);

set_city_production(pcity, gov_centers, pcwaste);
citizen_base_mood(pcity);
Expand Down
7 changes: 5 additions & 2 deletions common/city.h
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,9 @@ const char *get_output_identifier(Output_type_id output);
const char *get_output_name(Output_type_id output);
struct output_type *get_output_type(Output_type_id output);
Output_type_id output_type_by_identifier(const char *id);
void add_specialist_output(const struct city *pcity, int *output);
void add_specialist_output(
const struct city *pcity, int *output,
const std::vector<std::array<int, O_LAST>> *pcsoutputs = nullptr);
void set_city_production(
struct city *pcity, const std::vector<city *> &gov_centers,
const std::array<cached_waste, O_LAST> *pcwaste = nullptr);
Expand Down Expand Up @@ -706,7 +708,8 @@ void city_remove_improvement(struct city *pcity,
void city_refresh_from_main_map(
struct city *pcity, bool *workers_map,
const std::vector<city *> &gov_centers,
const std::array<cached_waste, O_LAST> *pcwaste = nullptr);
const std::array<cached_waste, O_LAST> *pcwaste = nullptr,
const std::vector<std::array<int, O_LAST>> *pcsoutputs = nullptr);
int city_waste(const struct city *pcity, Output_type_id otype, int total,
int *breakdown, const std::vector<city *> &gov_centers,
const cached_waste *pcwaste = nullptr);
Expand Down

0 comments on commit 018b46e

Please sign in to comment.