55#define CHALLENGE_ROOT "challenge"
57#define SPECLIST_TAG startpos
58#define SPECLIST_TYPE struct startpos
60#define startpos_list_iterate(list, plink, psp) \
61 TYPED_LIST_BOTH_ITERATE(struct startpos_list_link, struct startpos, \
63#define startpos_list_iterate_end LIST_BOTH_ITERATE_END
77#define SPECPQ_TAG team_placement
78#define SPECPQ_DATA_TYPE struct team_placement_state *
79#define SPECPQ_PRIORITY_TYPE long
89 return L_START_CITIES;
91 return L_START_WORKER;
93 return L_START_EXPLORER;
97 return L_START_DIPLOMAT;
101 return L_START_DEFEND_OK;
103 return L_START_DEFEND_GOOD;
105 return L_START_ATTACK_FAST;
107 return L_START_ATTACK_STRONG;
132 if (pplayer != NULL) {
136 for (i = 0; utype == NULL && i < num; i++) {
160 struct tile *ptile = NULL;
162 bool hut_present =
FALSE;
202 log_verbose(
"Removed hut on start position for %s",
221 struct tile *pcenter)
254#define team_placement_closest sq_map_distance
261 const struct tile *ptile2)
273 const struct tile *ptile2)
287 const struct tile *ptile2)
312 const size_t state_array_size = (
sizeof(*pbest_state->
startpos)
314 struct team_placement_pq *pqueue =
316 int (*distance)(
const struct tile *,
const struct tile *) = NULL;
318 const struct tile *ptile1, *ptile2;
319 long base_delta, delta;
320 bool base_delta_calculated;
326 case TEAM_PLACEMENT_CLOSEST:
329 case TEAM_PLACEMENT_CONTINENT:
332 case TEAM_PLACEMENT_HORIZONTAL:
335 case TEAM_PLACEMENT_VERTICAL:
338 case TEAM_PLACEMENT_DISABLED:
358 base_delta_calculated =
FALSE;
366 if (base_delta_calculated) {
369 if (k != i && t1 == pstate->
startpos[k]) {
370 delta += distance(ptile2, pconfig->
startpos[k]);
377 if (k != i && t1 == pstate->
startpos[k]) {
378 base_delta -= distance(ptile1, pconfig->
startpos[k]);
379 delta += distance(ptile2, pconfig->
startpos[k]);
383 base_delta_calculated =
TRUE;
385 }
else if (t1 < t2) {
387 if (base_delta_calculated) {
390 if (k != i && t1 == pstate->
startpos[k]) {
391 delta += distance(ptile2, pconfig->
startpos[k]);
392 }
else if (k != j && t2 == pstate->
startpos[k]) {
393 delta -= distance(ptile2, pconfig->
startpos[k]);
394 delta += distance(ptile1, pconfig->
startpos[k]);
401 if (k != i && t1 == pstate->
startpos[k]) {
402 base_delta -= distance(ptile1, pconfig->
startpos[k]);
403 delta += distance(ptile2, pconfig->
startpos[k]);
404 }
else if (k != j && t2 == pstate->
startpos[k]) {
405 delta -= distance(ptile2, pconfig->
startpos[k]);
406 delta += distance(ptile1, pconfig->
startpos[k]);
410 base_delta_calculated =
TRUE;
424 team_placement_pq_insert(pqueue, pnew, -pnew->
score);
435 if (iter++ >= iter_max) {
436 log_normal(
_(
"Didn't find optimal solution for team placement "
437 "in %d iterations."), iter);
441 }
while (repeat && team_placement_pq_remove(pqueue, &pstate));
451 struct startpos_list *impossible_list, *targeted_list, *flexible_list;
458 sizeof(
server.game_identifier));
471 impossible_list = startpos_list_new();
472 targeted_list = startpos_list_new();
473 flexible_list = startpos_list_new();
477 startpos_list_append(flexible_list, psp);
479 startpos_list_append(targeted_list, psp);
483 fc_assert(startpos_list_size(targeted_list)
486 memset(player_startpos, 0,
sizeof(player_startpos));
487 log_verbose(
"Placing players at start positions.");
491 if (0 < startpos_list_size(targeted_list)) {
494 startpos_list_shuffle(targeted_list);
497 struct startpos_list_link *choice;
498 bool removed =
FALSE;
511 if (NULL != choice) {
520 if (NULL != choice) {
527 startpos_list_erase(targeted_list, choice);
530 log_verbose(
"Start position (%d, %d) exactly matches player %s (%s).",
540 struct startpos *psp = startpos_list_back(targeted_list);
542 struct player *rand_plr = NULL;
545 startpos_list_pop_back(targeted_list);
558 if (NULL != rand_plr) {
561 log_verbose(
"Start position (%d, %d) matches player %s (%s).",
568 log_verbose(
"Start position (%d, %d) cannot be assigned for "
569 "any player, keeping for the moment...",
572 startpos_list_append(impossible_list, psp);
575 }
while (0 < players_to_place && 0 < startpos_list_size(targeted_list));
579 if (players_to_place > 0
582 const struct player_list *members;
583 int team_placement_players_to_place = 0;
584 int real_team_count = 0;
588 fc_assert(0 < player_list_size(members));
590 if (player_list_size(members) == 1) {
596 team_placement_players_to_place++;
601 if (real_team_count > 1 && team_placement_players_to_place > 0) {
607 log_verbose(
"Do team placement for %d players, using %s variant.",
608 team_placement_players_to_place,
645 if (player_list_size(members) <= 1) {
679 int candidate_index = -1;
680 int candidate_num = 0;
682 log_verbose(
"Start position (%d, %d) assigned to team %d (%s)",
688 &&
fc_rand(++candidate_num) == 0) {
693 player_startpos[candidate_index] = config.
startpos[i];
694 team_placement_players_to_place--;
698 fc_assert(team_placement_players_to_place == 0);
701 if (players_to_place > 0) {
708 startpos_list_erase(flexible_list, plink);
718 startpos_list_erase(impossible_list, plink);
732 if (0 < players_to_place && 0 < startpos_list_size(flexible_list)) {
735 log_verbose(
"Assigning unrestricted start positions.");
737 startpos_list_shuffle(flexible_list);
747 startpos_list_pop_front(flexible_list);
748 log_verbose(
"Start position (%d, %d) assigned randomly "
751 if (0 == startpos_list_size(flexible_list)) {
757 if (0 < players_to_place && 0 < startpos_list_size(impossible_list)) {
765 log_verbose(
"Ignoring nation restrictions on remaining start positions.");
767 startpos_list_shuffle(impossible_list);
777 startpos_list_pop_front(impossible_list);
778 log_verbose(
"Start position (%d, %d) assigned to mismatched "
781 if (0 == startpos_list_size(impossible_list)) {
789 startpos_list_destroy(impossible_list);
790 startpos_list_destroy(targeted_list);
791 startpos_list_destroy(flexible_list);
839 for (i = 1; i < sulen; i++) {
843 if (rand_tile != NULL
855 if (rand_tile != NULL
884 pplayer->nturns_idle++;
999 _(
"The turn timeout has exceeded its maximum value, "
1000 "fixing at its maximum."));
1001 log_debug(
"game.info.timeout exceeded maximum value");
1007 _(
"The turn timeout is smaller than zero, "
1008 "fixing at zero."));
1009 log_debug(
"game.info.timeout less than zero");
1016 log_debug(
"timeout=%d, inc=%d incmult=%d\n "
1017 "int=%d, intinc=%d, turns till next=%d",
1061 fc_snprintf(filename,
sizeof(filename),
"%s_%d_%d",
1082 if (cname == NULL) {
1107 struct strvec *ruleset_choices;
1114 const int maxlen =
sizeof packet.
rulesets[i];
1116 log_verbose(
"Can't send more than %d ruleset names to client, "
1123 log_verbose(
"Ruleset name '%s' too long to send to client, skipped", s);
1142 const char *token = NULL;
1143 bool you_have_hack =
FALSE;
1147 you_have_hack = (token && strcmp(token, packet->
token) == 0);
1155 log_debug(
"Failed to read authentication token");
1158 if (you_have_hack) {
bool adv_data_phase_init(struct player *pplayer, bool is_new_phase)
void adv_data_phase_done(struct player *pplayer)
#define CALL_PLR_AI_FUNC(_func, _player,...)
const char * calendar_text(void)
void send_conn_info(struct conn_list *src, struct conn_list *dest)
void conn_set_access(struct connection *pconn, enum cmdlevel new_level, bool granted)
#define conn_list_iterate(connlist, pconn)
#define conn_list_iterate_end
#define MAX_NUM_UNIT_LIST
const struct ft_color ftc_server
const struct ft_color ftc_any
int current_turn_timeout(void)
static void gen_challenge_filename(struct connection *pc)
static const char * get_challenge_fullname(struct connection *pc)
void send_scenario_description(struct conn_list *dest)
void send_year_to_clients(void)
void send_scenario_info(struct conn_list *dest)
static struct tile * place_starting_unit(struct tile *starttile, struct player *pplayer, struct unit_type *ptype, char crole)
#define team_placement_closest
static int team_placement_vertical(const struct tile *ptile1, const struct tile *ptile2)
void handle_single_want_hack_req(struct connection *pc, const struct packet_single_want_hack_req *packet)
void send_game_info(struct conn_list *dest)
static void send_ruleset_choices(struct connection *pc)
static struct tile * find_dispersed_position(struct player *pplayer, struct tile *pcenter)
#define startpos_list_iterate_end
static void do_team_placement(const struct team_placement_config *pconfig, struct team_placement_state *pbest_state, int iter_max)
static int team_placement_continent(const struct tile *ptile1, const struct tile *ptile2)
#define startpos_list_iterate(list, plink, psp)
enum unit_role_id crole_to_role_id(char crole)
static const char * get_challenge_filename(struct connection *pc)
void increase_timeout_because_unit_moved(void)
struct unit_type * crole_to_unit_type(char crole, struct player *pplayer)
static void team_placement_state_destroy(struct team_placement_state *pstate)
const char * new_challenge_filename(struct connection *pc)
static int team_placement_horizontal(const struct tile *ptile1, const struct tile *ptile2)
#define fc_assert_msg(condition, message,...)
#define log_verbose(message,...)
#define fc_assert(condition)
#define fc_assert_ret_msg(condition, message,...)
#define fc_assert_ret_val(condition, val)
#define fc_assert_action(condition, action)
#define log_debug(message,...)
#define log_normal(message,...)
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
bool startpos_nation_allowed(const struct startpos *psp, const struct nation_type *pnation)
struct tile * startpos_tile(const struct startpos *psp)
bool startpos_allows_all(const struct startpos *psp)
struct tile * map_pos_to_tile(const struct civ_map *nmap, int map_x, int map_y)
int map_startpos_count(void)
int real_map_distance(const struct tile *tile0, const struct tile *tile1)
void map_distance_vector(int *dx, int *dy, const struct tile *tile0, const struct tile *tile1)
#define iterate_outward(nmap, start_tile, max_dist, itr_tile)
#define iterate_outward_end
#define map_startpos_iterate(NAME_psp)
#define map_startpos_iterate_end
#define index_to_map_pos(pmap_x, pmap_y, mindex)
void map_show_circle(struct player *pplayer, struct tile *ptile, int radius_sq)
void update_tile_knowledge(struct tile *ptile)
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
const char * nation_rule_name(const struct nation_type *pnation)
struct nation_type * nation_of_player(const struct player *pplayer)
void notify_conn(struct conn_list *dest, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
void lsend_packet_new_year(struct conn_list *dest, const struct packet_new_year *packet)
int send_packet_scenario_info(struct connection *pc, const struct packet_scenario_info *packet)
int send_packet_ruleset_choices(struct connection *pc, const struct packet_ruleset_choices *packet)
int send_packet_game_info(struct connection *pc, const struct packet_game_info *packet)
int send_packet_calendar_info(struct connection *pc, const struct packet_calendar_info *packet)
int dsend_packet_single_want_hack_reply(struct connection *pc, bool you_have_hack)
int send_packet_scenario_description(struct connection *pc, const struct packet_scenario_description *packet)
int send_packet_timeout_info(struct connection *pc, const struct packet_timeout_info *packet)
int player_slot_count(void)
const char * player_name(const struct player *pplayer)
int player_index(const struct player *pplayer)
#define players_iterate_end
#define players_iterate(_pplayer)
#define player_list_iterate(playerlist, pplayer)
#define player_list_iterate_end
#define shuffled_players_iterate_end
#define shuffled_players_iterate(NAME_pplayer)
struct section_file * secfile_load(const char *filename, bool allow_duplicates)
const char * secfile_error(void)
void secfile_destroy(struct section_file *secfile)
const char * secfile_lookup_str(const struct section_file *secfile, const char *path,...)
void randomize_base64url_string(char *s, size_t n)
char * freeciv_storage_dir(void)
struct server_arguments srvarg
struct strvec * get_init_script_choices(void)
void strvec_destroy(struct strvec *psv)
#define strvec_iterate(psv, str)
#define strvec_iterate_end
struct civ_game::@30::@34 server
char start_units[MAX_LEN_STARTUNIT]
struct packet_scenario_description scenario_desc
struct conn_list * est_connections
struct packet_game_info info
int additional_phase_seconds
struct packet_scenario_info scenario
struct timer * phase_timer
struct packet_timeout_info tinfo
struct packet_calendar_info calendar
struct civ_map::@41::@43 server
enum team_placement team_placement
struct unit_type * init_units[MAX_NUM_UNIT_LIST]
char rulesets[MAX_NUM_RULESETS][MAX_RULESET_NAME_LENGTH]
float seconds_to_phasedone
int flexible_startpos_num
int fc_snprintf(char *str, size_t n, const char *format,...)
size_t fc_strlcpy(char *dest, const char *src, size_t n)
struct team * team_by_number(const int team_id)
const char * team_rule_name(const struct team *pteam)
int team_number(const struct team *pteam)
const struct player_list * team_members(const struct team *pteam)
#define teams_iterate_end
#define teams_iterate(_pteam)
#define is_ocean_tile(ptile)
bool tile_extra_rm_apply(struct tile *ptile, struct extra_type *tgt)
#define tile_continent(_tile)
#define tile_has_extra(ptile, pextra)
double timer_read_seconds(struct timer *t)
static bool is_non_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
struct unit_type * first_role_unit_for_player(const struct player *pplayer, int role)
struct unit_type * get_role_unit(int role, int role_index)
int num_role_units(int role)
bool utype_player_already_has_this_unique(const struct player *pplayer, const struct unit_type *putype)