80#define CM_MAX_LOOP 27500
82#define CPUHOG_CM_MAX_LOOP (CM_MAX_LOOP * 4)
85#define GATHER_TIME_STATS
93#define PRINT_TIME_STATS_EVERY_QUERY
95#define LOG_TIME_STATS LOG_DEBUG
96#define LOG_CM_STATE LOG_DEBUG
97#define LOG_LATTICE LOG_DEBUG
98#define LOG_REACHED_LEAF LOG_DEBUG
99#define LOG_BETTER_LEAF LOG_DEBUG
100#define LOG_PRUNE_BRANCH LOG_DEBUG
102#ifdef GATHER_TIME_STATS
111 struct one_perf *current;
114static void print_performance(
struct one_perf *counts);
141#define SPECVEC_TAG tile
142#define SPECVEC_TYPE struct cm_tile
146#define SPECVEC_TAG tile_type
147#define SPECVEC_TYPE struct cm_tile_type *
149#define tile_type_vector_iterate(vector, var) { \
150 struct cm_tile_type *var; \
151 TYPED_VECTOR_ITERATE(struct cm_tile_type*, vector, var##p) { \
154#define tile_type_vector_iterate_end }} VECTOR_ITERATE_END; }
244static void real_print_tile_type(
enum log_level level,
const char *file,
245 const char *function,
int line,
248#define print_tile_type(loglevel, ptype, prefix) \
249 if (log_do_output_for_level(loglevel)) { \
250 real_print_tile_type(loglevel, __FILE__, __FUNCTION__, __FC_LINE__, \
254static void real_print_lattice(
enum log_level level,
const char *file,
255 const char *function,
int line,
256 const struct tile_type_vector *lattice);
257#define print_lattice(loglevel, lattice) \
258 if (log_do_output_for_level(loglevel)) { \
259 real_print_lattice(loglevel, __FILE__, __FUNCTION__, __FC_LINE__, \
265 const char *function,
int line,
268#define print_partial_solution(loglevel, soln, state) \
269 if (log_do_output_for_level(loglevel)) { \
270 real_print_partial_solution(loglevel, __FILE__, __FUNCTION__, \
271 __FC_LINE__, soln, state); \
275#define print_tile_type(loglevel, ptype, prefix)
276#define print_lattice(loglevel, lattice)
277#define print_partial_solution(loglevel, soln, state)
281 const struct city *pcity,
bool *workers_map);
284 const int production[]);
296#ifdef GATHER_TIME_STATS
297 memset(&performance, 0,
sizeof(performance));
300 performance.greedy.name =
"greedy";
303 performance.opt.name =
"opt";
330#ifdef GATHER_TIME_STATS
331 print_performance(&performance.greedy);
332 print_performance(&performance.opt);
336 memset(&performance, 0,
sizeof(performance));
368 if (result != NULL) {
386 tile_vector_init(&
type->tiles);
387 tile_type_vector_init(&
type->better_types);
388 tile_type_vector_init(&
type->worse_types);
399 memcpy(newtype, oldtype,
sizeof(*oldtype));
400 tile_vector_init(&newtype->
tiles);
414 tile_vector_free(&
type->tiles);
415 tile_type_vector_free(&
type->better_types);
416 tile_type_vector_free(&
type->worse_types);
431 tile_type_vector_free(vec);
508 const struct tile_type_vector *vec,
513 for (i = 0; i < vec->size; i++) {
529 if (
type->is_specialist) {
532 return tile_vector_size(&
type->tiles);
574 return &ptype->
tiles.p[j];
620 fitness.
weighted += surplus[stat_index] * parameter->factor[stat_index];
621 if (surplus[stat_index] < parameter->minimal_surplus[stat_index]) {
627 fitness.
weighted += parameter->happy_factor;
628 }
else if (parameter->require_happy) {
632 if (disorder && !parameter->allow_disorder) {
650 int ntypes,
int idle,
bool negative_ok)
704#ifndef FREECIV_NDEBUG
705 int citizen_count = 0;
708#ifdef GATHER_TIME_STATS
709 performance.current->apply_count++;
729 for (i = 0 ; i <
num_types(state); i++) {
737#ifndef FREECIV_NDEBUG
738 citizen_count += nworkers;
743 if (
type->is_specialist) {
750 for (j = 0; j < nworkers; j++) {
771 bool *disorder,
bool *happy)
774 surplus[o] = pcity->
surplus[o];
787 struct city *pcity = state->pcity;
789 bool disorder,
happy;
829 if (soln->
idle != 0) {
942 if (valuea != valueb) {
944 return valueb - valuea;
959 const struct tile *ptile,
986 type = lattice->p[i];
996 tile_type_vector_append(&
type->better_types, other);
997 tile_type_vector_append(&other->worse_types,
type);
998 }
else if (
cmp < 0) {
999 tile_type_vector_append(&other->better_types,
type);
1000 tile_type_vector_append(&
type->worse_types, other);
1005 type->lattice_index = lattice->size;
1006 tile_type_vector_append(lattice,
type);
1010 if (!
type->is_specialist) {
1016 tile_vector_append(&
type->tiles,
tile);
1029 const struct city *pcity)
1059 if (lattice->size > 0) {
1061 bool marked[lattice->size];
1062 bool will_mark[lattice->size];
1063 struct tile_type_vector vectors[2];
1064 struct tile_type_vector *current, *next;
1066 memset(marked, 0,
sizeof(marked));
1067 memset(will_mark, 0,
sizeof(will_mark));
1069 tile_type_vector_init(&vectors[0]);
1070 tile_type_vector_init(&vectors[1]);
1071 current = &vectors[0];
1077 tile_type_vector_append(next, ptype);
1083 while (next->size != 0) {
1085 struct tile_type_vector *vtmp = current;
1095 bool can_mark =
TRUE;
1098 if (will_mark[ptype->lattice_index]) {
1102 if (!marked[better->lattice_index]) {
1118 will_mark[ptype->lattice_index] =
TRUE;
1120 tile_type_vector_append(next, worse);
1124 ptype->lattice_depth = sumdepth;
1129 for (i = 0; i < lattice->size; i++) {
1130 marked[i] = marked[i] || will_mark[i];
1131 will_mark[i] =
FALSE;
1135 tile_type_vector_free(&vectors[0]);
1136 tile_type_vector_free(&vectors[1]);
1157 const struct city *pcity)
1160 struct tile_type_vector tofree;
1161 bool forced_loop =
FALSE;
1165 tile_type_vector_init(&tofree);
1170 if (lattice->size > 0) {
1173 for (i = 0, j = 0; i < lattice->size || forced_loop; i++) {
1177 forced_loop =
FALSE;
1180 tile_type_vector_append(&tofree, ptype);
1186 lattice->p[j] = ptype;
1190 for (ci = 0, cj = 0; ci < ptype->
worse_types.size; ci++) {
1212 struct tile_type_vector *lattice)
1222 qsort(lattice->p, lattice->size,
sizeof(*lattice->p),
1226 for (i = 0; i < lattice->size; i++) {
1227 lattice->p[i]->lattice_index = i;
1238 struct tile_type_vector *lattice)
1301 return tile_type_vector_size(&state->
lattice);
1311 int itype,
int number,
1323 newcount = soln->
idle - number;
1326 soln->
idle = newcount;
1362 int itype,
const struct cm_state *state)
1371 int itype,
const struct cm_state *state)
1412 for (newchoice = oldchoice + 1;
1413 newchoice <
num_types(state); newchoice++) {
1417 == tile_vector_size(&ptype->
tiles))) {
1453 newchoice =
next_choice(state, oldchoice, negative_ok);
1476 int oldchoice, newchoice;
1489 newchoice =
next_choice(state, oldchoice - 1, negative_ok);
1510 const struct tile_type_vector *lattice)
1512 int last_worker_choice = -1;
1515 if (soln->
idle == 0) {
1520 for (i = 0; i <
num_types(state); i++) {
1522 last_worker_choice = i;
1534 if (ptype->lattice_index < last_worker_choice) {
1544 touse = total - used;
1545 if (touse > soln->
idle) {
1548 add_workers(soln, ptype->lattice_index, touse, state);
1550 if (soln->
idle == 0) {
1566 for (i = 0 ; i <
num_types(state); i++) {
1588 int check_choice,
bool negative_ok)
1597 if (soln->
idle == 1) {
1637 int base = production[stat_index];
1648 memcpy(production, pcity->
prod,
sizeof(pcity->
prod));
1661 bool beats_best =
FALSE;
1670 if (production[stat_index] < state->
min_production[stat_index]) {
1697 int specialists_suppress_unhappy
1698 =
MAX(specialists_amount + state->
current.
idle - max_content, 0);
1699 int max_luxury = production[
O_LUXURY]
1702 if (max_luxury < state->min_luxury ) {
1706 specialists_suppress_unhappy,
1738 const int SCIENCE = 0, TAX = 1, LUXURY = 2;
1743 rates[TAX] = 100 - rates[SCIENCE] - rates[LUXURY];
1753 rates[LUXURY] = 100;
1769 const int SCIENCE = 0, TAX = 1, LUXURY = 2;
1770 const struct city *pcity = state->
pcity;
1773 double estimates[
O_LAST];
1778 estimates[stat_index] = production[stat_index];
1788 += rates[SCIENCE] * trade / 100.0;
1790 += rates[LUXURY] * trade / 100.0;
1792 += rates[TAX] * trade / 100.0;
1796 estimates[stat_index] *= pcity->
bonus[stat_index] / 100.0;
1860 const int SCIENCE = 0, TAX = 1, LUXURY = 2;
1874 tile_type_vector_init(&state->
lattice);
1876 numtypes = tile_type_vector_size(&state->
lattice);
1882 int lsize = tile_type_vector_size(&state->
lattice);
1889 switch (stat_index) {
1952 if (max_surplus <= 0) {
1956 if (food_needed <= 0) {
1961 int num = tile_vector_size(&ptype->tiles);
1963 if (ptype->is_specialist || workers < num) {
1964 max_surplus += workers * ptype->production[
O_FOOD];
1967 max_surplus += num * ptype->production[
O_FOOD];
1973 min_turns = (food_needed + max_surplus - 1) / max_surplus;
1975 return (food_needed + min_turns - 1) / min_turns;
1986#ifdef GATHER_TIME_STATS
1988 performance.current->query_count++;
2017#ifdef GATHER_TIME_STATS
2020#ifdef PRINT_TIME_STATS_EVERY_QUERY
2021 print_performance(performance.current);
2024 performance.current = NULL;
2050 struct cm_result *result,
bool negative_ok)
2056#ifdef GATHER_TIME_STATS
2057 performance.current = &performance.opt;
2063 memcpy(&backup, state->
pcity,
sizeof(backup));
2074 while (!
bb_next(state, negative_ok)) {
2078 if (loop_count == max_count + 1) {
2079#ifdef FREECIV_TESTMATIC
2091 "Did not find a cm solution in %d iterations for %s.",
2095#ifndef CM_LOOP_NO_LIMIT
2102#ifdef CM_LOOP_NO_LIMIT
2103 if (loop_count > max_count) {
2104 log_warn(
"It took %d iterations to finish.", loop_count);
2111 memcpy(state->
pcity, &backup,
sizeof(backup));
2122 struct cm_result *result,
bool negative_ok)
2185 dest->
factor[stat_index] = 1;
2203 dest->
factor[stat_index] = 1;
2260 const struct city *pcity)
2271 const struct city *pcity,
bool *workers_map)
2282 if (workers_map == NULL) {
2309static void snprint_production(
char *buffer,
size_t bufsz,
2321static void real_print_tile_type(
enum log_level level,
const char *file,
2322 const char *function,
int line,
2328 snprint_production(prodstr,
sizeof(prodstr), ptype->
production);
2330 "%s%s fitness %g depth %d, idx %d; %d tiles", prefix,
2338static void real_print_lattice(
enum log_level level,
const char *file,
2339 const char *function,
int line,
2340 const struct tile_type_vector *lattice)
2343 "lattice has %u terrain types", (
unsigned) lattice->size);
2345 real_print_tile_type(
level, file, function, line, ptype,
" ");
2354 const char *function,
int line,
2362 if (soln->
idle != 0) {
2364 "** partial solution has %d idle workers", soln->
idle);
2369 snprint_production(buf,
sizeof(buf), soln->
production);
2373 for (i = 0; i <
num_types(state); i++) {
2375 fc_snprintf(buf,
sizeof(buf),
" %d tiles of type ",
2377 real_print_tile_type(
level, file, function, line,
2382 for (i = 0; i <
num_types(state); i++) {
2389 for (i = last_type; i <
num_types(state); i++) {
2394 real_print_tile_type(
level, file, function, line,
2402#ifdef GATHER_TIME_STATS
2406static void print_performance(
struct one_perf *counts)
2410 int queries, applies;
2415 queries = counts->query_count;
2418 applies = counts->apply_count;
2421 "CM-%s: overall=%fs queries=%d %fms / query, %d applies",
2422 counts->name, s, queries, ms / q, applies);
2435 log_test(
" size=%d, specialists=%s",
2443 if (NULL != pwork && pwork == pcity) {
2470 sizeof(*city_map_data));
2472 log_test(
"cm_print_result(result=%p)", (
void *) result);
2473 log_test(
" found_a_valid=%d disorder=%d happy=%d",
2478 city_map_data[cindex] = 2;
2480 city_map_data[cindex] = 1;
2482 city_map_data[cindex] = 0;
2485 log_test(
"workers map (2: free worked; 1: worker; 0: not used):");
bool base_city_celebrating(const struct city *pcity)
bool is_free_worked(const struct city *pcity, const struct tile *ptile)
int city_granary_size(int city_size)
struct tile * city_map_to_tile(const struct civ_map *nmap, const struct tile *city_center, int city_radius_sq, int city_map_x, int city_map_y)
const char * city_name_get(const struct city *pcity)
bool city_can_use_specialist(const struct city *pcity, Specialist_type_id type)
bool city_tile_index_to_xy(int *city_map_x, int *city_map_y, int city_tile_index, int city_radius_sq)
citizens player_content_citizens(const struct player *pplayer)
void citylog_map_data(enum log_level level, int radius_sq, int *map_data)
bool city_unhappy(const struct city *pcity)
void set_city_production(struct city *pcity)
const char * get_output_name(Output_type_id output)
void city_refresh_from_main_map(const struct civ_map *nmap, struct city *pcity, bool *workers_map)
bool city_happy(const struct city *pcity)
int city_map_radius_sq_get(const struct city *pcity)
citizens city_specialists(const struct city *pcity)
static int cmp(int v1, int v2)
int city_tile_output(const struct city *pcity, const struct tile *ptile, bool is_celebrating, Output_type_id otype)
int city_map_tiles(int city_radius_sq)
bool city_can_work_tile(const struct city *pcity, const struct tile *ptile)
#define city_tile(_pcity_)
#define city_tile_iterate_index(_nmap, _radius_sq, _city_tile, _tile, _index)
#define CITY_MAP_MAX_RADIUS_SQ
static citizens city_size_get(const struct city *pcity)
#define city_tile_iterate_index_end
#define output_type_iterate(output)
#define city_owner(_pcity_)
#define city_tile_iterate(_nmap, _radius_sq, _city_tile, _tile)
#define city_map_iterate_end
#define city_map_iterate(_radius_sq, _index, _x, _y)
#define city_tile_iterate_end
#define is_free_worked_index(city_tile_index)
#define city_map_tiles_from_city(_pcity)
#define output_type_iterate_end
void cm_init_citymap(void)
static void convert_solution_to_result(struct cm_state *state, const struct partial_solution *soln, struct cm_result *result)
static void sort_lattice_by_fitness(const struct cm_state *state, struct tile_type_vector *lattice)
static double estimate_fitness(const struct cm_state *state, const int production[])
static void get_tax_rates(const struct player *pplayer, int rates[])
static int specialists_in_solution(const struct cm_state *state, const struct partial_solution *soln)
static void begin_search(struct cm_state *state, const struct cm_parameter *parameter, bool negative_ok)
static int min_food_surplus_for_fastest_growth(struct cm_state *state)
static int next_choice(struct cm_state *state, int oldchoice, bool negative_ok)
static void tile_type_destroy(struct cm_tile_type *type)
static struct cm_fitness compute_fitness(const int surplus[], bool disorder, bool happy, const struct cm_parameter *parameter)
static void init_partial_solution(struct partial_solution *into, int ntypes, int idle, bool negative_ok)
static void complete_solution(struct partial_solution *soln, const struct cm_state *state, const struct tile_type_vector *lattice)
static const struct cm_tile * tile_get(const struct cm_tile_type *ptype, int j)
static struct cm_fitness worst_fitness(void)
static bool take_child_choice(struct cm_state *state, bool negative_ok)
static void compute_tile_production(const struct city *pcity, const struct tile *ptile, struct cm_tile_type *out)
void cm_clear_cache(struct city *pcity)
static const struct cm_tile_type * tile_type_get(const struct cm_state *state, int type)
static Output_type_id compare_key
static struct cm_fitness evaluate_solution(struct cm_state *state, const struct partial_solution *soln)
static int tile_type_vector_find_equivalent(const struct tile_type_vector *vec, const struct cm_tile_type *ptype)
void cm_copy_parameter(struct cm_parameter *dest, const struct cm_parameter *const src)
static bool choice_stack_empty(struct cm_state *state)
static void tile_type_vector_free_all(struct tile_type_vector *vec)
static struct cm_state * cm_state_init(struct city *pcity, bool negative_ok)
static struct cm_tile_type * tile_type_dup(const struct cm_tile_type *oldtype)
static bool prereqs_filled(const struct partial_solution *soln, int type, const struct cm_state *state)
static void clean_lattice(struct tile_type_vector *lattice, const struct city *pcity)
void cm_init_parameter(struct cm_parameter *dest)
static int tile_type_num_prereqs(const struct cm_tile_type *ptype)
static void copy_partial_solution(struct partial_solution *dst, const struct partial_solution *src, const struct cm_state *state)
static void cm_state_free(struct cm_state *state)
static int compare_tile_type_by_fitness(const void *va, const void *vb)
struct cm_result * cm_result_new(struct city *pcity)
static void destroy_partial_solution(struct partial_solution *into)
int cm_result_specialists(const struct cm_result *result)
#define print_partial_solution(loglevel, soln, state)
void cm_result_from_main_map(struct cm_result *result, const struct city *pcity)
#define print_lattice(loglevel, lattice)
static bool tile_type_equal(const struct cm_tile_type *a, const struct cm_tile_type *b)
static void tile_type_init(struct cm_tile_type *type)
static void cm_result_copy(struct cm_result *result, const struct city *pcity, bool *workers_map)
#define tile_type_vector_iterate(vector, var)
static void add_worker(struct partial_solution *soln, int itype, const struct cm_state *state)
static bool choice_is_promising(struct cm_state *state, int newchoice, bool negative_ok)
bool cm_are_parameter_equal(const struct cm_parameter *const p1, const struct cm_parameter *const p2)
static double compare_key_trade_bonus
static void init_tile_lattice(struct city *pcity, struct tile_type_vector *lattice)
static bool take_sibling_choice(struct cm_state *state, bool negative_ok)
static void cm_find_best_solution(struct cm_state *state, const struct cm_parameter *const parameter, struct cm_result *result, bool negative_ok)
static void apply_solution(struct cm_state *state, const struct partial_solution *soln)
static void init_min_production(struct cm_state *state)
void cm_result_destroy(struct cm_result *result)
void cm_print_result(const struct cm_result *result)
static void end_search(struct cm_state *state)
static int compare_tile_type_by_stat(const void *va, const void *vb)
static int tile_type_num_tiles(const struct cm_tile_type *type)
static bool fitness_better(struct cm_fitness a, struct cm_fitness b)
void cm_query_result(struct city *pcity, const struct cm_parameter *param, struct cm_result *result, bool negative_ok)
static bool bb_next(struct cm_state *state, bool negative_ok)
static void top_sort_lattice(struct tile_type_vector *lattice)
static void get_city_surplus(const struct city *pcity, int surplus[], bool *disorder, bool *happy)
static void compute_max_stats_heuristic(const struct cm_state *state, const struct partial_solution *soln, int production[], int check_choice, bool negative_ok)
static int last_choice(struct cm_state *state)
#define print_tile_type(loglevel, ptype, prefix)
static int compare_tile_type_by_lattice_order(const struct cm_tile_type *a, const struct cm_tile_type *b)
static void remove_worker(struct partial_solution *soln, int itype, const struct cm_state *state)
#define CPUHOG_CM_MAX_LOOP
static int tile_type_better(const struct cm_tile_type *a, const struct cm_tile_type *b)
static void init_specialist_lattice_nodes(struct tile_type_vector *lattice, const struct city *pcity)
static void add_workers(struct partial_solution *soln, int itype, int number, const struct cm_state *state)
int cm_result_citizens(const struct cm_result *result)
static void tile_type_lattice_add(struct tile_type_vector *lattice, const struct cm_tile_type *newtype, int tindex)
void cm_init_emergency_parameter(struct cm_parameter *dest)
static void pop_choice(struct cm_state *state)
static int num_types(const struct cm_state *state)
#define tile_type_vector_iterate_end
void cm_print_city(const struct city *pcity)
int cm_result_workers(const struct cm_result *result)
struct timer * wall_timer
static void base(QVariant data1, QVariant data2)
enum output_type_id Output_type_id
struct government * government_of_player(const struct player *pplayer)
void do_log(const char *file, const char *function, int line, bool print_from_where, enum log_level level, const char *message,...)
#define fc_assert_ret(condition)
#define log_warn(message,...)
#define fc_assert(condition)
#define fc_assert_ret_val(condition, val)
#define log_base(level, message,...)
#define fc_calloc(n, esz)
static bool player_is_cpuhog(const struct player *pplayer)
struct setting_list * level[OLEVELS_NUM]
const char * specialists_string(const citizens *specialist_list)
int get_specialist_output(const struct city *pcity, Specialist_type_id sp, Output_type_id otype)
#define specialist_type_iterate_end
#define specialist_type_iterate(sp)
struct universal production
citizens specialists[SP_MAX]
struct packet_game_info info
struct government * government_during_revolution
int minimal_surplus[O_LAST]
citizens specialists[SP_MAX]
struct partial_solution best
struct cm_parameter parameter
int min_production[O_LAST]
struct tile_type_vector lattice
struct partial_solution current
struct tile_type_vector lattice_by_prod[O_LAST]
struct cm_fitness best_value
struct cm_state::@15 choice
struct tile_type_vector better_types
struct tile_type_vector worse_types
const struct cm_tile_type * type
struct player_economic economic
int fc_snprintf(char *str, size_t n, const char *format,...)
#define tile_worked(_tile)
struct timer * timer_new(enum timer_timetype type, enum timer_use use)
void timer_destroy(struct timer *t)
void timer_start(struct timer *t)
void timer_stop(struct timer *t)
double timer_read_seconds(struct timer *t)