Freeciv-3.1: /fast/freeciv/nightly/S3_1/server/gamehand.c Source File

Freeciv-3.1

Loading...
Searching...
No Matches
gamehand.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <stdio.h> /* for remove() */
19
20/* utility */
21#include "capability.h"
22#include "fcintl.h"
23#include "log.h"
24#include "mem.h"
25#include "rand.h"
26#include "registry.h"
27#include "shared.h"
28#include "string_vector.h"
29#include "support.h"
30
31/* common */
32#include "ai.h"
33#include "calendar.h"
34#include "events.h"
35#include "game.h"
36#include "improvement.h"
37#include "movement.h"
38#include "packets.h"
39
40/* server */
41#include "citytools.h"
42#include "connecthand.h"
43#include "maphand.h"
44#include "notify.h"
45#include "plrhand.h"
46#include "srv_main.h"
47#include "stdinhand.h"
48#include "unittools.h"
49
50/* server/advisors */
51#include "advdata.h"
52
53#include "gamehand.h"
54
55#define CHALLENGE_ROOT "challenge"
56
57#define SPECLIST_TAG startpos
58#define SPECLIST_TYPE struct startpos
59#include "speclist.h"
60#define startpos_list_iterate(list, plink, psp) \
61 TYPED_LIST_BOTH_ITERATE(struct startpos_list_link, struct startpos, \
62 list, plink, psp)
63#define startpos_list_iterate_end LIST_BOTH_ITERATE_END
64
65 struct team_placement_config {
66 struct tile **startpos;
67 int flexible_startpos_num;
68 int usable_startpos_num;
69 int total_startpos_num;
70};
71
72 struct team_placement_state {
73 int *startpos;
74 long score;
75};
76
77#define SPECPQ_TAG team_placement
78#define SPECPQ_DATA_TYPE struct team_placement_state *
79#define SPECPQ_PRIORITY_TYPE long
80#include "specpq.h"
81
82/************************************************************************/
85 enum unit_role_id crole_to_role_id(char crole)
86{
87 switch (crole) {
88 case 'c':
89 return L_START_CITIES;
90 case 'w':
91 return L_START_WORKER;
92 case 'x':
93 return L_START_EXPLORER;
94 case 'k':
95 return L_START_KING;
96 case 's':
97 return L_START_DIPLOMAT;
98 case 'f':
99 return L_START_FERRY;
100 case 'd':
101 return L_START_DEFEND_OK;
102 case 'D':
103 return L_START_DEFEND_GOOD;
104 case 'a':
105 return L_START_ATTACK_FAST;
106 case 'A':
107 return L_START_ATTACK_STRONG;
108 default:
109 return 0;
110 }
111}
112
113/************************************************************************/
118 struct unit_type *crole_to_unit_type(char crole, struct player *pplayer)
119{
120 struct unit_type *utype = NULL;
121 enum unit_role_id role = crole_to_role_id(crole);
122 int num;
123
124 if (role == 0) {
125 fc_assert_ret_val(FALSE, NULL);
126 return NULL;
127 }
128
129 /* Create the unit of an appropriate type, if it exists */
130 num = num_role_units(role);
131 if (num > 0) {
132 if (pplayer != NULL) {
133 int i;
134
135 utype = first_role_unit_for_player(pplayer, role);
136 for (i = 0; utype == NULL && i < num; i++) {
137 struct unit_type *ntype = get_role_unit(role, i);
138
139 if (!utype_player_already_has_this_unique(pplayer, ntype)) {
140 utype = ntype;
141 }
142 }
143 } else {
144 utype = get_role_unit(role, 0);
145 }
146 }
147
148 return utype;
149}
150
151/************************************************************************/
156 static struct tile *place_starting_unit(struct tile *starttile,
157 struct player *pplayer,
158 struct unit_type *ptype, char crole)
159{
160 struct tile *ptile = NULL;
161 struct unit_type *utype;
162 bool hut_present = FALSE;
163
164 if (ptype != NULL) {
165 utype = ptype;
166 } else {
167 utype = crole_to_unit_type(crole, pplayer);
168 }
169
170 if (utype != NULL) {
171 iterate_outward(&(wld.map), starttile,
172 wld.map.xsize + wld.map.ysize, itertile) {
173 if (!is_non_allied_unit_tile(itertile, pplayer)
174 && is_native_tile(utype, itertile)) {
175 ptile = itertile;
176 break;
177 }
178 } iterate_outward_end;
179 }
180
181 if (ptile == NULL) {
182 /* No place where unit may exist. */
183 return NULL;
184 }
185
186 fc_assert_ret_val(!is_non_allied_unit_tile(ptile, pplayer), NULL);
187
188 /* For scenarios or dispersion, huts may coincide with player starts (in
189 * other cases, huts are avoided as start positions). Remove any such hut,
190 * and make sure to tell the client, since we may have already sent this
191 * tile (with the hut) earlier: */
192 /* FIXME: don't remove under a HUT_NOTHING unit */
193 extra_type_by_rmcause_iterate(ERM_ENTER, pextra) {
194 if (tile_has_extra(ptile, pextra)) {
195 tile_extra_rm_apply(ptile, pextra);
196 hut_present = TRUE;
197 }
198 } extra_type_by_rmcause_iterate_end;
199
200 if (hut_present) {
201 update_tile_knowledge(ptile);
202 log_verbose("Removed hut on start position for %s",
203 player_name(pplayer));
204 }
205
206 /* Expose visible area. */
207 map_show_circle(pplayer, ptile, game.server.init_vis_radius_sq);
208
209 if (utype != NULL) {
210 (void) create_unit(pplayer, ptile, utype, FALSE, 0, 0);
211 return ptile;
212 }
213
214 return NULL;
215}
216
217/************************************************************************/
220 static struct tile *find_dispersed_position(struct player *pplayer,
221 struct tile *pcenter)
222{
223 struct tile *ptile;
224 int x, y;
225 int bailout;
226
227 if (game.server.dispersion == 0) {
228 bailout = 1; /* One attempt is guaranteed to cover single tile */
229 } else {
230 bailout = game.server.dispersion * 2 + 1; /* Side of the area */
231 bailout *= bailout; /* Area */
232 bailout *= 5; /* Likely to hit each tile at least once */
233 }
234
235 do {
236 if (!bailout--) {
237 return NULL;
238 }
239 index_to_map_pos(&x, &y, tile_index(pcenter));
240 x += fc_rand(2 * game.server.dispersion + 1) - game.server.dispersion;
241 y += fc_rand(2 * game.server.dispersion + 1) - game.server.dispersion;
242 } while (!((ptile = map_pos_to_tile(&(wld.map), x, y))
243 && tile_continent(pcenter) == tile_continent(ptile)
244 && !is_ocean_tile(ptile)
245 && real_map_distance(pcenter, ptile) < game.server.dispersion
246 + 1
247 && !is_non_allied_unit_tile(ptile, pplayer)));
248
249 return ptile;
250}
251
252/* Calculate the distance between tiles, according to the 'teamplacement'
253 * setting set to 'CLOSEST'. */
254#define team_placement_closest sq_map_distance
255
256/************************************************************************/
260 static int team_placement_continent(const struct tile *ptile1,
261 const struct tile *ptile2)
262{
263 return (ptile1->continent == ptile2->continent
264 ? sq_map_distance(ptile1, ptile2)
265 : sq_map_distance(ptile1, ptile2) + MAP_INDEX_SIZE);
266}
267
268/************************************************************************/
272 static int team_placement_horizontal(const struct tile *ptile1,
273 const struct tile *ptile2)
274{
275 int dx, dy;
276
277 map_distance_vector(&dx, &dy, ptile1, ptile2);
278 /* Map vector to natural vector (Y axis). */
279 return abs(MAP_IS_ISOMETRIC ? dx + dy : dy);
280}
281
282/************************************************************************/
286 static int team_placement_vertical(const struct tile *ptile1,
287 const struct tile *ptile2)
288{
289 int dx, dy;
290
291 map_distance_vector(&dx, &dy, ptile1, ptile2);
292 /* Map vector to natural vector (X axis). */
293 return abs(MAP_IS_ISOMETRIC ? dx - dy : dy);
294}
295
296/************************************************************************/
299 static void team_placement_state_destroy(struct team_placement_state *pstate)
300{
301 free(pstate->startpos);
302 free(pstate);
303}
304
305/************************************************************************/
308 static void do_team_placement(const struct team_placement_config *pconfig,
309 struct team_placement_state *pbest_state,
310 int iter_max)
311{
312 const size_t state_array_size = (sizeof(*pbest_state->startpos)
313 * pconfig->total_startpos_num);
314 struct team_placement_pq *pqueue =
315 team_placement_pq_new(pconfig->total_startpos_num * 4);
316 int (*distance)(const struct tile *, const struct tile *) = NULL;
317 struct team_placement_state *pstate, *pnew;
318 const struct tile *ptile1, *ptile2;
319 long base_delta, delta;
320 bool base_delta_calculated;
321 int iter = 0;
322 bool repeat;
323 int i, j, k, t1, t2;
324
325 switch (wld.map.server.team_placement) {
326 case TEAM_PLACEMENT_CLOSEST:
327 distance = team_placement_closest;
328 break;
329 case TEAM_PLACEMENT_CONTINENT:
330 distance = team_placement_continent;
331 break;
332 case TEAM_PLACEMENT_HORIZONTAL:
333 distance = team_placement_horizontal;
334 break;
335 case TEAM_PLACEMENT_VERTICAL:
336 distance = team_placement_vertical;
337 break;
338 case TEAM_PLACEMENT_DISABLED:
339 break;
340 }
341 fc_assert_ret_msg(distance != NULL, "Wrong team_placement variant (%d)",
342 wld.map.server.team_placement);
343
344 /* Initialize starting state. */
345 pstate = fc_malloc(sizeof(*pstate));
346 pstate->startpos = fc_malloc(state_array_size);
347 memcpy(pstate->startpos, pbest_state->startpos, state_array_size);
348 pstate->score = pbest_state->score;
349
350 do {
351 repeat = FALSE;
352 for (i = 0; i < pconfig->usable_startpos_num; i++) {
353 t1 = pstate->startpos[i];
354 if (t1 == -1) {
355 continue; /* Not used. */
356 }
357 ptile1 = pconfig->startpos[i];
358 base_delta_calculated = FALSE;
359 for (j = i + 1; j < (i >= pconfig->flexible_startpos_num
360 ? pconfig->usable_startpos_num
361 : pconfig->flexible_startpos_num); j++) {
362 t2 = pstate->startpos[j];
363 if (t2 == -1) {
364 /* Not assigned yet. */
365 ptile2 = pconfig->startpos[j];
366 if (base_delta_calculated) {
367 delta = base_delta;
368 for (k = 0; k < pconfig->total_startpos_num; k++) {
369 if (k != i && t1 == pstate->startpos[k]) {
370 delta += distance(ptile2, pconfig->startpos[k]);
371 }
372 }
373 } else {
374 delta = 0;
375 base_delta = 0;
376 for (k = 0; k < pconfig->total_startpos_num; k++) {
377 if (k != i && t1 == pstate->startpos[k]) {
378 base_delta -= distance(ptile1, pconfig->startpos[k]);
379 delta += distance(ptile2, pconfig->startpos[k]);
380 }
381 }
382 delta += base_delta;
383 base_delta_calculated = TRUE;
384 }
385 } else if (t1 < t2) {
386 ptile2 = pconfig->startpos[j];
387 if (base_delta_calculated) {
388 delta = base_delta;
389 for (k = 0; k < pconfig->total_startpos_num; k++) {
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]);
395 }
396 }
397 } else {
398 delta = 0;
399 base_delta = 0;
400 for (k = 0; k < pconfig->total_startpos_num; 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]);
407 }
408 }
409 delta += base_delta;
410 base_delta_calculated = TRUE;
411 }
412 } else {
413 continue;
414 }
415
416 if (delta <= 0) {
417 repeat = TRUE;
418 pnew = fc_malloc(sizeof(*pnew));
419 pnew->startpos = fc_malloc(state_array_size);
420 memcpy(pnew->startpos, pstate->startpos, state_array_size);
421 pnew->startpos[i] = t2;
422 pnew->startpos[j] = t1;
423 pnew->score = pstate->score + delta;
424 team_placement_pq_insert(pqueue, pnew, -pnew->score);
425
426 if (pnew->score < pbest_state->score) {
427 memcpy(pbest_state->startpos, pnew->startpos, state_array_size);
428 pbest_state->score = pnew->score;
429 }
430 }
431 }
432 }
433
434 team_placement_state_destroy(pstate);
435 if (iter++ >= iter_max) {
436 log_normal(_("Didn't find optimal solution for team placement "
437 "in %d iterations."), iter);
438 break;
439 }
440
441 } while (repeat && team_placement_pq_remove(pqueue, &pstate));
442
443 team_placement_pq_destroy_full(pqueue, team_placement_state_destroy);
444}
445
446/************************************************************************/
449 void init_new_game(void)
450{
451 struct startpos_list *impossible_list, *targeted_list, *flexible_list;
452 struct tile *player_startpos[player_slot_count()];
453 int placed_units[player_slot_count()];
454 int players_to_place = player_count();
455 int sulen;
456
457 randomize_base64url_string(server.game_identifier,
458 sizeof(server.game_identifier));
459
460 /* Assign players to starting positions on the map.
461 * (In scenarios with restrictions on which nations can use which predefined
462 * start positions, this process tries to satisfy those restrictions, but
463 * does not guarantee to. Even if there is a solution to the matching
464 * problem, this algorithm may not find it.) */
465
466 fc_assert(player_count() <= map_startpos_count());
467
468 /* Convert the startposition hash table in a linked lists, as we mostly
469 * need now to iterate it now. And then, we will be able to remove the
470 * assigned start postions one by one. */
471 impossible_list = startpos_list_new();
472 targeted_list = startpos_list_new();
473 flexible_list = startpos_list_new();
474
475 map_startpos_iterate(psp) {
476 if (startpos_allows_all(psp)) {
477 startpos_list_append(flexible_list, psp);
478 } else {
479 startpos_list_append(targeted_list, psp);
480 }
481 } map_startpos_iterate_end;
482
483 fc_assert(startpos_list_size(targeted_list)
484 + startpos_list_size(flexible_list) == map_startpos_count());
485
486 memset(player_startpos, 0, sizeof(player_startpos));
487 log_verbose("Placing players at start positions.");
488
489 /* First assign start positions which have restrictions on which nations
490 * can use them. */
491 if (0 < startpos_list_size(targeted_list)) {
492 log_verbose("Assigning matching nations.");
493
494 startpos_list_shuffle(targeted_list); /* Randomize. */
495 do {
496 struct nation_type *pnation;
497 struct startpos_list_link *choice;
498 bool removed = FALSE;
499
500 /* Assign first players which can pick only one start position. */
501 players_iterate(pplayer) {
502 if (NULL != player_startpos[player_index(pplayer)]) {
503 /* Already assigned. */
504 continue;
505 }
506
507 pnation = nation_of_player(pplayer);
508 choice = NULL;
509 startpos_list_iterate(targeted_list, plink, psp) {
510 if (startpos_nation_allowed(psp, pnation)) {
511 if (NULL != choice) {
512 choice = NULL;
513 break; /* Many choices. */
514 } else {
515 choice = plink;
516 }
517 }
518 } startpos_list_iterate_end;
519
520 if (NULL != choice) {
521 /* Assign this start position to this player and remove
522 * both from consideration. */
523 struct tile *ptile =
524 startpos_tile(startpos_list_link_data(choice));
525
526 player_startpos[player_index(pplayer)] = ptile;
527 startpos_list_erase(targeted_list, choice);
528 players_to_place--;
529 removed = TRUE;
530 log_verbose("Start position (%d, %d) exactly matches player %s (%s).",
531 TILE_XY(ptile), player_name(pplayer),
532 nation_rule_name(pnation));
533 }
534 } players_iterate_end;
535
536 if (!removed) {
537 /* Didn't find any 1:1 matches. For the next restricted start
538 * position, assign a random matching player. (This may create
539 * restrictions such that more 1:1 matches are possible.) */
540 struct startpos *psp = startpos_list_back(targeted_list);
541 struct tile *ptile = startpos_tile(psp);
542 struct player *rand_plr = NULL;
543 int i = 0;
544
545 startpos_list_pop_back(targeted_list); /* Detach 'psp'. */
546 players_iterate(pplayer) {
547 if (NULL != player_startpos[player_index(pplayer)]) {
548 /* Already assigned. */
549 continue;
550 }
551
552 pnation = nation_of_player(pplayer);
553 if (startpos_nation_allowed(psp, pnation) && 0 == fc_rand(++i)) {
554 rand_plr = pplayer;
555 }
556 } players_iterate_end;
557
558 if (NULL != rand_plr) {
559 player_startpos[player_index(rand_plr)] = ptile;
560 players_to_place--;
561 log_verbose("Start position (%d, %d) matches player %s (%s).",
562 TILE_XY(ptile), player_name(rand_plr),
563 nation_rule_name(nation_of_player(rand_plr)));
564 } else {
565 /* This start position cannot be assigned, given the assignments
566 * made so far. We may have to fall back to mismatched
567 * assignments. */
568 log_verbose("Start position (%d, %d) cannot be assigned for "
569 "any player, keeping for the moment...",
570 TILE_XY(ptile));
571 /* Keep it for later, we may need it. */
572 startpos_list_append(impossible_list, psp);
573 }
574 }
575 } while (0 < players_to_place && 0 < startpos_list_size(targeted_list));
576 }
577
578 /* Now try to assign with regard to the 'teamplacement' setting. */
579 if (players_to_place > 0
580 && wld.map.server.team_placement != TEAM_PLACEMENT_DISABLED
581 && player_count() > team_count()) {
582 const struct player_list *members;
583 int team_placement_players_to_place = 0;
584 int real_team_count = 0;
585
586 teams_iterate(pteam) {
587 members = team_members(pteam);
588 fc_assert(0 < player_list_size(members));
589 real_team_count++;
590 if (player_list_size(members) == 1) {
591 /* Single player teams, doesn't count for team placement. */
592 continue;
593 }
594 player_list_iterate(members, pplayer) {
595 if (player_startpos[player_index(pplayer)] == NULL) {
596 team_placement_players_to_place++;
597 }
598 } player_list_iterate_end;
599 } teams_iterate_end;
600
601 if (real_team_count > 1 && team_placement_players_to_place > 0) {
602 /* We really can do something to improve team placement. */
603 struct team_placement_config config;
604 struct team_placement_state state;
605 int i, j, t;
606
607 log_verbose("Do team placement for %d players, using %s variant.",
608 team_placement_players_to_place,
609 team_placement_name(wld.map.server.team_placement));
610
611 /* Initialize configuration. */
612 config.flexible_startpos_num = startpos_list_size(flexible_list);
613 config.usable_startpos_num = config.flexible_startpos_num;
614 if (config.flexible_startpos_num < team_placement_players_to_place) {
615 config.usable_startpos_num += startpos_list_size(impossible_list);
616 }
617 config.total_startpos_num = (config.usable_startpos_num
618 + player_count() - players_to_place);
619 config.startpos = fc_malloc(sizeof(*config.startpos)
620 * config.total_startpos_num);
621 i = 0;
622 startpos_list_iterate(flexible_list, plink, psp) {
623 config.startpos[i++] = startpos_tile(psp);
624 } startpos_list_iterate_end;
625 fc_assert(i == config.flexible_startpos_num);
626 if (i < config.usable_startpos_num) {
627 startpos_list_iterate(impossible_list, plink, psp) {
628 config.startpos[i++] = startpos_tile(psp);
629 } startpos_list_iterate_end;
630 }
631 fc_assert(i == config.usable_startpos_num);
632 while (i < config.total_startpos_num) {
633 config.startpos[i++] = NULL;
634 }
635 fc_assert(i == config.total_startpos_num);
636
637 /* Initialize state. */
638 state.startpos = fc_malloc(sizeof(*state.startpos)
639 * config.total_startpos_num);
640 state.score = 0;
641 i = 0;
642 j = config.usable_startpos_num;
643 teams_iterate(pteam) {
644 members = team_members(pteam);
645 if (player_list_size(members) <= 1) {
646 /* Single player teams, doesn't count for team placement. */
647 continue;
648 }
649 t = team_number(pteam);
650 player_list_iterate(members, pplayer) {
651 struct tile *ptile = player_startpos[player_index(pplayer)];
652
653 if (ptile == NULL) {
654 state.startpos[i++] = t;
655 } else {
656 state.startpos[j] = t;
657 config.startpos[j] = ptile;
658 j++;
659 }
660 } player_list_iterate_end;
661 } teams_iterate_end;
662 while (i < config.usable_startpos_num) {
663 state.startpos[i++] = -1;
664 }
665 fc_assert(i == config.usable_startpos_num);
666 while (j < config.total_startpos_num) {
667 state.startpos[j++] = -1;
668 }
669 fc_assert(j == config.total_startpos_num);
670
671 /* Look for best team placement. */
672 do_team_placement(&config, &state, team_placement_players_to_place);
673
674 /* Apply result. */
675 for (i = 0; i < config.usable_startpos_num; i++) {
676 t = state.startpos[i];
677 if (t != -1) {
678 const struct team *pteam = team_by_number(t);
679 int candidate_index = -1;
680 int candidate_num = 0;
681
682 log_verbose("Start position (%d, %d) assigned to team %d (%s)",
683 TILE_XY(config.startpos[i]),
684 t, team_rule_name(pteam));
685
686 player_list_iterate(team_members(pteam), member) {
687 if (player_startpos[player_index(member)] == NULL
688 && fc_rand(++candidate_num) == 0) {
689 candidate_index = player_index(member);
690 }
691 } player_list_iterate_end;
692 fc_assert(candidate_index >= 0);
693 player_startpos[candidate_index] = config.startpos[i];
694 team_placement_players_to_place--;
695 players_to_place--;
696 }
697 }
698 fc_assert(team_placement_players_to_place == 0);
699
700 /* Free data. */
701 if (players_to_place > 0) {
702 /* We need to remove used startpos from the lists. */
703 i = 0;
704 startpos_list_iterate(flexible_list, plink, psp) {
705 (void)psp; /* To avoid 'set but unused' compiler warning */
706 fc_assert(config.startpos[i] == startpos_tile(psp));
707 if (state.startpos[i] != -1) {
708 startpos_list_erase(flexible_list, plink);
709 }
710 i++;
711 } startpos_list_iterate_end;
712 fc_assert(i == config.flexible_startpos_num);
713 if (i < config.usable_startpos_num) {
714 startpos_list_iterate(impossible_list, plink, psp) {
715 (void)psp; /* To avoid 'set but unused' compiler warning */
716 fc_assert(config.startpos[i] == startpos_tile(psp));
717 if (state.startpos[i] != -1) {
718 startpos_list_erase(impossible_list, plink);
719 }
720 i++;
721 } startpos_list_iterate_end;
722 }
723 fc_assert(i == config.usable_startpos_num);
724 }
725
726 free(state.startpos);
727 free(config.startpos);
728 }
729 }
730
731 /* Now assign unrestricted start positions to any remaining players. */
732 if (0 < players_to_place && 0 < startpos_list_size(flexible_list)) {
733 struct tile *ptile;
734
735 log_verbose("Assigning unrestricted start positions.");
736
737 startpos_list_shuffle(flexible_list); /* Randomize. */
738 players_iterate(pplayer) {
739 if (NULL != player_startpos[player_index(pplayer)]) {
740 /* Already assigned. */
741 continue;
742 }
743
744 ptile = startpos_tile(startpos_list_front(flexible_list));
745 player_startpos[player_index(pplayer)] = ptile;
746 players_to_place--;
747 startpos_list_pop_front(flexible_list);
748 log_verbose("Start position (%d, %d) assigned randomly "
749 "to player %s (%s).", TILE_XY(ptile), player_name(pplayer),
750 nation_rule_name(nation_of_player(pplayer)));
751 if (0 == startpos_list_size(flexible_list)) {
752 break;
753 }
754 } players_iterate_end;
755 }
756
757 if (0 < players_to_place && 0 < startpos_list_size(impossible_list)) {
758 /* We still have players to place, and we have some restricted start
759 * positions whose nation requirements can't be satisfied given existing
760 * assignments. Fall back to making assignments ignoring the positions'
761 * nation requirements. */
762
763 struct tile *ptile;
764
765 log_verbose("Ignoring nation restrictions on remaining start positions.");
766
767 startpos_list_shuffle(impossible_list); /* Randomize. */
768 players_iterate(pplayer) {
769 if (NULL != player_startpos[player_index(pplayer)]) {
770 /* Already assigned. */
771 continue;
772 }
773
774 ptile = startpos_tile(startpos_list_front(impossible_list));
775 player_startpos[player_index(pplayer)] = ptile;
776 players_to_place--;
777 startpos_list_pop_front(impossible_list);
778 log_verbose("Start position (%d, %d) assigned to mismatched "
779 "player %s (%s).", TILE_XY(ptile), player_name(pplayer),
780 nation_rule_name(nation_of_player(pplayer)));
781 if (0 == startpos_list_size(impossible_list)) {
782 break;
783 }
784 } players_iterate_end;
785 }
786
787 fc_assert(0 == players_to_place);
788
789 startpos_list_destroy(impossible_list);
790 startpos_list_destroy(targeted_list);
791 startpos_list_destroy(flexible_list);
792
793 sulen = strlen(game.server.start_units);
794
795 /* Loop over all players, creating their initial units... */
796 shuffled_players_iterate(pplayer) {
797 struct tile *ptile;
798
799 /* We have to initialise the advisor and ai here as we could make contact
800 * to other nations at this point. */
801 adv_data_phase_init(pplayer, FALSE);
802 CALL_PLR_AI_FUNC(phase_begin, pplayer, pplayer, FALSE);
803
804 ptile = player_startpos[player_index(pplayer)];
805
806 fc_assert_action(NULL != ptile, continue);
807
808 /* Place first city */
809 if (game.server.start_city) {
810 create_city(pplayer, ptile, city_name_suggestion(pplayer, ptile),
811 NULL);
812
813 /* Expose visible area. */
814 map_show_circle(pplayer, ptile, game.server.init_vis_radius_sq);
815 }
816
817 if (sulen > 0) {
818 /* Place the first unit. */
819 if (place_starting_unit(ptile, pplayer, NULL,
820 game.server.start_units[0]) != NULL) {
821 placed_units[player_index(pplayer)] = 1;
822 } else {
823 placed_units[player_index(pplayer)] = 0;
824 }
825 } else {
826 placed_units[player_index(pplayer)] = 0;
827 }
828 } shuffled_players_iterate_end;
829
830 /* Place all other units. */
831 shuffled_players_iterate(pplayer) {
832 int i;
833 struct tile *const ptile = player_startpos[player_index(pplayer)];
834 struct nation_type *nation = nation_of_player(pplayer);
835
836 fc_assert_action(NULL != ptile, continue);
837
838 /* Place global start units */
839 for (i = 1; i < sulen; i++) {
840 struct tile *rand_tile = find_dispersed_position(pplayer, ptile);
841
842 /* Create the unit of an appropriate type. */
843 if (rand_tile != NULL
844 && place_starting_unit(rand_tile, pplayer, NULL,
845 game.server.start_units[i]) != NULL) {
846 placed_units[player_index(pplayer)]++;
847 }
848 }
849
850 /* Place nation specific start units (not role based!) */
851 i = 0;
852 while (NULL != nation->init_units[i] && MAX_NUM_UNIT_LIST > i) {
853 struct tile *rand_tile = find_dispersed_position(pplayer, ptile);
854
855 if (rand_tile != NULL
856 && place_starting_unit(rand_tile, pplayer,
857 nation->init_units[i], '\0') != NULL) {
858 placed_units[player_index(pplayer)]++;
859 }
860 i++;
861 }
862 } shuffled_players_iterate_end;
863
864 players_iterate(pplayer) {
865 /* Close the active phase for advisor and ai for all players; it was
866 * opened in the first loop above. */
867 adv_data_phase_done(pplayer);
868 CALL_PLR_AI_FUNC(phase_finished, pplayer, pplayer);
869
870 fc_assert_msg(game.server.start_city || 0 < placed_units[player_index(pplayer)],
871 _("No units placed for %s!"), player_name(pplayer));
872 } players_iterate_end;
873}
874
875/************************************************************************/
879 void send_year_to_clients(void)
880{
881 struct packet_new_year apacket;
882
883 players_iterate(pplayer) {
884 pplayer->nturns_idle++;
885 } players_iterate_end;
886
887 apacket.year = game.info.year;
888 apacket.fragments = game.info.fragment_count;
889 apacket.turn = game.info.turn;
890 lsend_packet_new_year(game.est_connections, &apacket);
891
892 /* Hmm, clients could add this themselves based on above packet? */
893 notify_conn(game.est_connections, NULL, E_NEXT_YEAR, ftc_any,
894 _("Year: %s"), calendar_text());
895}
896
897/************************************************************************/
905 void send_game_info(struct conn_list *dest)
906{
907 struct packet_timeout_info tinfo;
908
909 if (!dest) {
910 dest = game.est_connections;
911 }
912
913 tinfo = game.tinfo;
914
915 /* the following values are computed every
916 time a packet_game_info packet is created */
917
918 /* Sometimes this function is called before the phase_timer is
919 * initialized. In that case we want to send the dummy value. */
920 if (current_turn_timeout() > 0 && game.server.phase_timer) {
921 /* Whenever the client sees this packet, it starts a new timer at 0;
922 * but the server's timer is only ever reset at the start of a phase
923 * (and game.tinfo.seconds_to_phasedone is relative to this).
924 * Account for the difference. */
925 tinfo.seconds_to_phasedone = game.tinfo.seconds_to_phasedone
926 - timer_read_seconds(game.server.phase_timer)
927 - game.server.additional_phase_seconds;
928 } else {
929 /* unused but at least initialized */
930 tinfo.seconds_to_phasedone = -1.0;
931 }
932
933 conn_list_iterate(dest, pconn) {
934 /* Timeout info is separate from other packets since it has to
935 * be sent always (it's not 'is-info') while the others are 'is-info'
936 * Calendar info has been split from Game info packet to make packet
937 * size more tolerable when json protocol is in use. */
938 send_packet_game_info(pconn, &(game.info));
939 send_packet_calendar_info(pconn, &(game.calendar));
940 send_packet_timeout_info(pconn, &tinfo);
941 }
942 conn_list_iterate_end;
943}
944
945/************************************************************************/
948 void send_scenario_info(struct conn_list *dest)
949{
950 if (!dest) {
951 dest = game.est_connections;
952 }
953
954 conn_list_iterate(dest, pconn) {
955 send_packet_scenario_info(pconn, &(game.scenario));
956 } conn_list_iterate_end;
957}
958
959/************************************************************************/
962 void send_scenario_description(struct conn_list *dest)
963{
964 if (!dest) {
965 dest = game.est_connections;
966 }
967
968 conn_list_iterate(dest, pconn) {
969 send_packet_scenario_description(pconn, &(game.scenario_desc));
970 } conn_list_iterate_end;
971}
972
973/************************************************************************/
983 int update_timeout(void)
984{
985 /* if there's no timer or we're doing autogame, do nothing */
986 if (game.info.timeout < 1 || game.server.timeoutint == 0) {
987 return game.info.timeout;
988 }
989
990 if (game.server.timeoutcounter >= game.server.timeoutint) {
991 game.info.timeout += game.server.timeoutinc;
992 game.server.timeoutinc *= game.server.timeoutincmult;
993
994 game.server.timeoutcounter = 1;
995 game.server.timeoutint += game.server.timeoutintinc;
996
997 if (game.info.timeout > GAME_MAX_TIMEOUT) {
998 notify_conn(game.est_connections, NULL, E_SETTING, ftc_server,
999 _("The turn timeout has exceeded its maximum value, "
1000 "fixing at its maximum."));
1001 log_debug("game.info.timeout exceeded maximum value");
1002 game.info.timeout = GAME_MAX_TIMEOUT;
1003 game.server.timeoutint = 0;
1004 game.server.timeoutinc = 0;
1005 } else if (game.info.timeout < 0) {
1006 notify_conn(game.est_connections, NULL, E_SETTING, ftc_server,
1007 _("The turn timeout is smaller than zero, "
1008 "fixing at zero."));
1009 log_debug("game.info.timeout less than zero");
1010 game.info.timeout = 0;
1011 }
1012 } else {
1013 game.server.timeoutcounter++;
1014 }
1015
1016 log_debug("timeout=%d, inc=%d incmult=%d\n "
1017 "int=%d, intinc=%d, turns till next=%d",
1018 game.info.timeout, game.server.timeoutinc,
1019 game.server.timeoutincmult, game.server.timeoutint,
1020 game.server.timeoutintinc,
1021 game.server.timeoutint - game.server.timeoutcounter);
1022
1023 return game.info.timeout;
1024}
1025
1026/************************************************************************/
1034 void increase_timeout_because_unit_moved(void)
1035{
1036 if (current_turn_timeout() > 0 && game.server.timeoutaddenemymove > 0) {
1037 double maxsec = (timer_read_seconds(game.server.phase_timer)
1038 + (double) game.server.timeoutaddenemymove);
1039
1040 if (maxsec > game.tinfo.seconds_to_phasedone) {
1041 game.tinfo.seconds_to_phasedone = maxsec;
1042 send_game_info(NULL);
1043 }
1044 }
1045}
1046
1047/************************************************************************/
1050 static void gen_challenge_filename(struct connection *pc)
1051{
1052}
1053
1054/************************************************************************/
1057 static const char *get_challenge_filename(struct connection *pc)
1058{
1059 static char filename[MAX_LEN_PATH];
1060
1061 fc_snprintf(filename, sizeof(filename), "%s_%d_%d",
1062 CHALLENGE_ROOT, srvarg.port, pc->id);
1063
1064 return filename;
1065}
1066
1067/************************************************************************/
1070 static const char *get_challenge_fullname(struct connection *pc)
1071{
1072 static char fullname[MAX_LEN_PATH];
1073 const char *sdir = freeciv_storage_dir();
1074 const char *cname;
1075
1076 if (sdir == NULL) {
1077 return NULL;
1078 }
1079
1080 cname = get_challenge_filename(pc);
1081
1082 if (cname == NULL) {
1083 return NULL;
1084 }
1085
1086 fc_snprintf(fullname, sizeof(fullname), "%s" DIR_SEPARATOR "%s", sdir, cname);
1087
1088 return fullname;
1089}
1090
1091/************************************************************************/
1094 const char *new_challenge_filename(struct connection *pc)
1095{
1096 gen_challenge_filename(pc);
1097 return get_challenge_filename(pc);
1098}
1099
1100/************************************************************************/
1105 static void send_ruleset_choices(struct connection *pc)
1106{
1107 struct strvec *ruleset_choices;
1108 struct packet_ruleset_choices packet;
1109 size_t i = 0;
1110
1111 ruleset_choices = get_init_script_choices();
1112
1113 strvec_iterate(ruleset_choices, s) {
1114 const int maxlen = sizeof packet.rulesets[i];
1115 if (i >= MAX_NUM_RULESETS) {
1116 log_verbose("Can't send more than %d ruleset names to client, "
1117 "skipping some", MAX_NUM_RULESETS);
1118 break;
1119 }
1120 if (fc_strlcpy(packet.rulesets[i], s, maxlen) < maxlen) {
1121 i++;
1122 } else {
1123 log_verbose("Ruleset name '%s' too long to send to client, skipped", s);
1124 }
1125 } strvec_iterate_end;
1126 packet.ruleset_count = i;
1127
1128 send_packet_ruleset_choices(pc, &packet);
1129
1130 strvec_destroy(ruleset_choices);
1131}
1132
1133/************************************************************************/
1137 void handle_single_want_hack_req(struct connection *pc,
1138 const struct packet_single_want_hack_req *
1139 packet)
1140{
1141 struct section_file *secfile;
1142 const char *token = NULL;
1143 bool you_have_hack = FALSE;
1144
1145 if ((secfile = secfile_load(get_challenge_fullname(pc), FALSE))) {
1146 token = secfile_lookup_str(secfile, "challenge.token");
1147 you_have_hack = (token && strcmp(token, packet->token) == 0);
1148 secfile_destroy(secfile);
1149 } else {
1150 log_debug("Error reading '%s':\n%s", get_challenge_fullname(pc),
1151 secfile_error());
1152 }
1153
1154 if (!token) {
1155 log_debug("Failed to read authentication token");
1156 }
1157
1158 if (you_have_hack) {
1159 conn_set_access(pc, ALLOW_HACK, TRUE);
1160 }
1161
1162 dsend_packet_single_want_hack_reply(pc, you_have_hack);
1163
1164 send_ruleset_choices(pc);
1165 send_conn_info(pc->self, NULL);
1166}
adv_data_phase_init
bool adv_data_phase_init(struct player *pplayer, bool is_new_phase)
Definition advdata.c:262
adv_data_phase_done
void adv_data_phase_done(struct player *pplayer)
Definition advdata.c:553
advdata.h
ai.h
CALL_PLR_AI_FUNC
#define CALL_PLR_AI_FUNC(_func, _player,...)
Definition ai.h:374
calendar_text
const char * calendar_text(void)
Definition calendar.c:141
calendar.h
capability.h
city_name_suggestion
const char * city_name_suggestion(struct player *pplayer, struct tile *ptile)
Definition citytools.c:451
create_city
void create_city(struct player *pplayer, struct tile *ptile, const char *name, struct player *nationality)
Definition citytools.c:1489
citytools.h
send_conn_info
void send_conn_info(struct conn_list *src, struct conn_list *dest)
Definition connecthand.c:557
conn_set_access
void conn_set_access(struct connection *pconn, enum cmdlevel new_level, bool granted)
Definition connecthand.c:68
connecthand.h
conn_list_iterate
#define conn_list_iterate(connlist, pconn)
Definition connection.h:113
conn_list_iterate_end
#define conn_list_iterate_end
Definition connection.h:115
events.h
extra_type_by_rmcause_iterate_end
#define extra_type_by_rmcause_iterate_end
Definition extras.h:334
extra_type_by_rmcause_iterate
#define extra_type_by_rmcause_iterate(_rmcause, _extra)
Definition extras.h:329
MAX_NUM_RULESETS
#define MAX_NUM_RULESETS
Definition fc_types.h:382
MAX_NUM_UNIT_LIST
#define MAX_NUM_UNIT_LIST
Definition fc_types.h:45
fcintl.h
_
#define _(String)
Definition fcintl.h:67
ftc_server
const struct ft_color ftc_server
Definition featured_text.c:77
ftc_any
const struct ft_color ftc_any
Definition featured_text.c:73
game
struct civ_game game
Definition game.c:57
current_turn_timeout
int current_turn_timeout(void)
Definition game.c:828
wld
struct world wld
Definition game.c:58
game.h
GAME_MAX_TIMEOUT
#define GAME_MAX_TIMEOUT
Definition game.h:587
gen_challenge_filename
static void gen_challenge_filename(struct connection *pc)
Definition gamehand.c:1050
get_challenge_fullname
static const char * get_challenge_fullname(struct connection *pc)
Definition gamehand.c:1070
send_scenario_description
void send_scenario_description(struct conn_list *dest)
Definition gamehand.c:962
send_year_to_clients
void send_year_to_clients(void)
Definition gamehand.c:879
send_scenario_info
void send_scenario_info(struct conn_list *dest)
Definition gamehand.c:948
place_starting_unit
static struct tile * place_starting_unit(struct tile *starttile, struct player *pplayer, struct unit_type *ptype, char crole)
Definition gamehand.c:156
team_placement_closest
#define team_placement_closest
Definition gamehand.c:254
team_placement_vertical
static int team_placement_vertical(const struct tile *ptile1, const struct tile *ptile2)
Definition gamehand.c:286
update_timeout
int update_timeout(void)
Definition gamehand.c:983
handle_single_want_hack_req
void handle_single_want_hack_req(struct connection *pc, const struct packet_single_want_hack_req *packet)
Definition gamehand.c:1137
send_game_info
void send_game_info(struct conn_list *dest)
Definition gamehand.c:905
CHALLENGE_ROOT
#define CHALLENGE_ROOT
Definition gamehand.c:55
send_ruleset_choices
static void send_ruleset_choices(struct connection *pc)
Definition gamehand.c:1105
find_dispersed_position
static struct tile * find_dispersed_position(struct player *pplayer, struct tile *pcenter)
Definition gamehand.c:220
startpos_list_iterate_end
#define startpos_list_iterate_end
Definition gamehand.c:63
do_team_placement
static void do_team_placement(const struct team_placement_config *pconfig, struct team_placement_state *pbest_state, int iter_max)
Definition gamehand.c:308
team_placement_continent
static int team_placement_continent(const struct tile *ptile1, const struct tile *ptile2)
Definition gamehand.c:260
startpos_list_iterate
#define startpos_list_iterate(list, plink, psp)
Definition gamehand.c:60
crole_to_role_id
enum unit_role_id crole_to_role_id(char crole)
Definition gamehand.c:85
get_challenge_filename
static const char * get_challenge_filename(struct connection *pc)
Definition gamehand.c:1057
increase_timeout_because_unit_moved
void increase_timeout_because_unit_moved(void)
Definition gamehand.c:1034
init_new_game
void init_new_game(void)
Definition gamehand.c:449
crole_to_unit_type
struct unit_type * crole_to_unit_type(char crole, struct player *pplayer)
Definition gamehand.c:118
team_placement_state_destroy
static void team_placement_state_destroy(struct team_placement_state *pstate)
Definition gamehand.c:299
new_challenge_filename
const char * new_challenge_filename(struct connection *pc)
Definition gamehand.c:1094
team_placement_horizontal
static int team_placement_horizontal(const struct tile *ptile1, const struct tile *ptile2)
Definition gamehand.c:272
gamehand.h
improvement.h
log.h
fc_assert_msg
#define fc_assert_msg(condition, message,...)
Definition log.h:181
log_verbose
#define log_verbose(message,...)
Definition log.h:109
fc_assert
#define fc_assert(condition)
Definition log.h:176
fc_assert_ret_msg
#define fc_assert_ret_msg(condition, message,...)
Definition log.h:205
fc_assert_ret_val
#define fc_assert_ret_val(condition, val)
Definition log.h:194
fc_assert_action
#define fc_assert_action(condition, action)
Definition log.h:187
log_debug
#define log_debug(message,...)
Definition log.h:115
log_normal
#define log_normal(message,...)
Definition log.h:107
sq_map_distance
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:639
startpos_nation_allowed
bool startpos_nation_allowed(const struct startpos *psp, const struct nation_type *pnation)
Definition map.c:1488
startpos_tile
struct tile * startpos_tile(const struct startpos *psp)
Definition map.c:1479
startpos_allows_all
bool startpos_allows_all(const struct startpos *psp)
Definition map.c:1499
map_pos_to_tile
struct tile * map_pos_to_tile(const struct civ_map *nmap, int map_x, int map_y)
Definition map.c:417
map_startpos_count
int map_startpos_count(void)
Definition map.c:1656
real_map_distance
int real_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:628
map_distance_vector
void map_distance_vector(int *dx, int *dy, const struct tile *tile0, const struct tile *tile1)
Definition map.c:1071
iterate_outward
#define iterate_outward(nmap, start_tile, max_dist, itr_tile)
Definition map.h:361
iterate_outward_end
#define iterate_outward_end
Definition map.h:365
map_startpos_iterate
#define map_startpos_iterate(NAME_psp)
Definition map.h:124
MAP_INDEX_SIZE
#define MAP_INDEX_SIZE
Definition map.h:131
MAP_IS_ISOMETRIC
#define MAP_IS_ISOMETRIC
Definition map.h:40
map_startpos_iterate_end
#define map_startpos_iterate_end
Definition map.h:127
index_to_map_pos
#define index_to_map_pos(pmap_x, pmap_y, mindex)
Definition map.h:227
map_show_circle
void map_show_circle(struct player *pplayer, struct tile *ptile, int radius_sq)
Definition maphand.c:856
update_tile_knowledge
void update_tile_knowledge(struct tile *ptile)
Definition maphand.c:1424
maphand.h
mem.h
fc_malloc
#define fc_malloc(sz)
Definition mem.h:34
is_native_tile
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:316
movement.h
nation_rule_name
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:137
nation_of_player
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:443
notify_conn
void notify_conn(struct conn_list *dest, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Definition notify.c:239
notify.h
packets.h
lsend_packet_new_year
void lsend_packet_new_year(struct conn_list *dest, const struct packet_new_year *packet)
Definition packets_gen.c:52786
send_packet_scenario_info
int send_packet_scenario_info(struct connection *pc, const struct packet_scenario_info *packet)
Definition packets_gen.c:83744
send_packet_ruleset_choices
int send_packet_ruleset_choices(struct connection *pc, const struct packet_ruleset_choices *packet)
Definition packets_gen.c:79290
send_packet_game_info
int send_packet_game_info(struct connection *pc, const struct packet_game_info *packet)
Definition packets_gen.c:9096
send_packet_calendar_info
int send_packet_calendar_info(struct connection *pc, const struct packet_calendar_info *packet)
Definition packets_gen.c:9479
dsend_packet_single_want_hack_reply
int dsend_packet_single_want_hack_reply(struct connection *pc, bool you_have_hack)
Definition packets_gen.c:78997
send_packet_scenario_description
int send_packet_scenario_description(struct connection *pc, const struct packet_scenario_description *packet)
Definition packets_gen.c:83898
send_packet_timeout_info
int send_packet_timeout_info(struct connection *pc, const struct packet_timeout_info *packet)
Definition packets_gen.c:9664
player_count
int player_count(void)
Definition player.c:808
player_slot_count
int player_slot_count(void)
Definition player.c:411
player_name
const char * player_name(const struct player *pplayer)
Definition player.c:886
player_index
int player_index(const struct player *pplayer)
Definition player.c:820
players_iterate_end
#define players_iterate_end
Definition player.h:535
players_iterate
#define players_iterate(_pplayer)
Definition player.h:530
player_list_iterate
#define player_list_iterate(playerlist, pplayer)
Definition player.h:553
player_list_iterate_end
#define player_list_iterate_end
Definition player.h:555
plrhand.h
shuffled_players_iterate_end
#define shuffled_players_iterate_end
Definition plrhand.h:106
shuffled_players_iterate
#define shuffled_players_iterate(NAME_pplayer)
Definition plrhand.h:96
rand.h
fc_rand
#define fc_rand(_size)
Definition rand.h:34
secfile_load
struct section_file * secfile_load(const char *filename, bool allow_duplicates)
Definition registry.c:50
registry.h
secfile_error
const char * secfile_error(void)
Definition section_file.c:36
secfile_destroy
void secfile_destroy(struct section_file *secfile)
Definition section_file.c:95
secfile_lookup_str
const char * secfile_lookup_str(const struct section_file *secfile, const char *path,...)
Definition registry_ini.c:2112
randomize_base64url_string
void randomize_base64url_string(char *s, size_t n)
Definition shared.c:338
freeciv_storage_dir
char * freeciv_storage_dir(void)
Definition shared.c:672
shared.h
DIR_SEPARATOR
#define DIR_SEPARATOR
Definition shared.h:127
MAX_LEN_PATH
#define MAX_LEN_PATH
Definition shared.h:32
speclist.h
specpq.h
srvarg
struct server_arguments srvarg
Definition srv_main.c:173
srv_main.h
get_init_script_choices
struct strvec * get_init_script_choices(void)
Definition stdinhand.c:1268
stdinhand.h
strvec_destroy
void strvec_destroy(struct strvec *psv)
Definition string_vector.c:71
string_vector.h
strvec_iterate
#define strvec_iterate(psv, str)
Definition string_vector.h:61
strvec_iterate_end
#define strvec_iterate_end
Definition string_vector.h:68
civ_game::dispersion
int dispersion
Definition game.h:142
civ_game::init_vis_radius_sq
int init_vis_radius_sq
Definition game.h:151
civ_game::server
struct civ_game::@30::@34 server
civ_game::start_units
char start_units[MAX_LEN_STARTUNIT]
Definition game.h:188
civ_game::scenario_desc
struct packet_scenario_description scenario_desc
Definition game.h:88
civ_game::est_connections
struct conn_list * est_connections
Definition game.h:97
civ_game::info
struct packet_game_info info
Definition game.h:89
civ_game::timeoutcounter
int timeoutcounter
Definition game.h:206
civ_game::additional_phase_seconds
int additional_phase_seconds
Definition game.h:211
civ_game::scenario
struct packet_scenario_info scenario
Definition game.h:87
civ_game::timeoutint
int timeoutint
Definition game.h:202
civ_game::phase_timer
struct timer * phase_timer
Definition game.h:210
civ_game::timeoutincmult
int timeoutincmult
Definition game.h:204
civ_game::tinfo
struct packet_timeout_info tinfo
Definition game.h:91
civ_game::timeoutinc
int timeoutinc
Definition game.h:203
civ_game::start_city
bool start_city
Definition game.h:189
civ_game::calendar
struct packet_calendar_info calendar
Definition game.h:90
civ_game::timeoutintinc
int timeoutintinc
Definition game.h:205
civ_game::timeoutaddenemymove
int timeoutaddenemymove
Definition game.h:207
civ_map::xsize
int xsize
Definition map_types.h:77
civ_map::ysize
int ysize
Definition map_types.h:77
civ_map::server
struct civ_map::@41::@43 server
civ_map::team_placement
enum team_placement team_placement
Definition map_types.h:108
connection
Definition connection.h:141
connection::self
struct conn_list * self
Definition connection.h:168
connection::id
int id
Definition connection.h:142
nation_type
Definition nation.h:97
nation_type::init_units
struct unit_type * init_units[MAX_NUM_UNIT_LIST]
Definition nation.h:124
packet_game_info::fragment_count
int fragment_count
Definition packets_gen.h:245
packet_game_info::turn
int turn
Definition packets_gen.h:241
packet_game_info::year
int year
Definition packets_gen.h:243
packet_game_info::timeout
int timeout
Definition packets_gen.h:233
packet_new_year
Definition packets_gen.h:920
packet_new_year::year
int year
Definition packets_gen.h:921
packet_new_year::turn
int turn
Definition packets_gen.h:923
packet_new_year::fragments
int fragments
Definition packets_gen.h:922
packet_ruleset_choices
Definition packets_gen.h:1504
packet_ruleset_choices::ruleset_count
int ruleset_count
Definition packets_gen.h:1505
packet_ruleset_choices::rulesets
char rulesets[MAX_NUM_RULESETS][MAX_RULESET_NAME_LENGTH]
Definition packets_gen.h:1506
packet_single_want_hack_req
Definition packets_gen.h:1496
packet_single_want_hack_req::token
char token[MAX_LEN_NAME]
Definition packets_gen.h:1497
packet_timeout_info
Definition packets_gen.h:261
packet_timeout_info::seconds_to_phasedone
float seconds_to_phasedone
Definition packets_gen.h:262
player
Definition player.h:249
section_file
Definition section_file.h:36
server_arguments::port
int port
Definition srv_main.h:36
server
Definition servers.h:29
startpos
Definition map.c:41
strvec
Definition string_vector.c:29
team_placement_config
Definition gamehand.c:65
team_placement_config::total_startpos_num
int total_startpos_num
Definition gamehand.c:69
team_placement_config::startpos
struct tile ** startpos
Definition gamehand.c:66
team_placement_config::flexible_startpos_num
int flexible_startpos_num
Definition gamehand.c:67
team_placement_config::usable_startpos_num
int usable_startpos_num
Definition gamehand.c:68
team_placement_state
Definition gamehand.c:72
team_placement_state::score
long score
Definition gamehand.c:74
team_placement_state::startpos
int * startpos
Definition gamehand.c:73
team
Definition team.c:40
tile
Definition tile.h:49
tile::continent
Continent_id continent
Definition tile.h:53
unit_type
Definition unittype.h:481
world::map
struct civ_map map
Definition world_object.h:38
fc_snprintf
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:969
fc_strlcpy
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:787
support.h
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
team_count
int team_count(void)
Definition team.c:375
team_by_number
struct team * team_by_number(const int team_id)
Definition team.c:400
team_rule_name
const char * team_rule_name(const struct team *pteam)
Definition team.c:410
team_number
int team_number(const struct team *pteam)
Definition team.c:391
team_members
const struct player_list * team_members(const struct team *pteam)
Definition team.c:456
teams_iterate_end
#define teams_iterate_end
Definition team.h:85
teams_iterate
#define teams_iterate(_pteam)
Definition team.h:80
is_ocean_tile
#define is_ocean_tile(ptile)
Definition terrain.h:289
tile_extra_rm_apply
bool tile_extra_rm_apply(struct tile *ptile, struct extra_type *tgt)
Definition tile.c:578
tile_index
#define tile_index(_pt_)
Definition tile.h:87
TILE_XY
#define TILE_XY(ptile)
Definition tile.h:42
tile_continent
#define tile_continent(_tile)
Definition tile.h:91
tile_has_extra
#define tile_has_extra(ptile, pextra)
Definition tile.h:146
timer_read_seconds
double timer_read_seconds(struct timer *t)
Definition timing.c:344
is_non_allied_unit_tile
static bool is_non_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:423
create_unit
struct unit * create_unit(struct player *pplayer, struct tile *ptile, const struct unit_type *type, int veteran_level, int homecity_id, int moves_left)
Definition unittools.c:1619
unittools.h
first_role_unit_for_player
struct unit_type * first_role_unit_for_player(const struct player *pplayer, int role)
Definition unittype.c:2370
get_role_unit
struct unit_type * get_role_unit(int role, int role_index)
Definition unittype.c:2301
num_role_units
int num_role_units(int role)
Definition unittype.c:2251
utype_player_already_has_this_unique
bool utype_player_already_has_this_unique(const struct player *pplayer, const struct unit_type *putype)
Definition unittype.c:1979