Freeciv-3.3: /fast/freeciv/nightly/main/server/gamehand.c Source File

Freeciv-3.3

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 "modpack.h"
38#include "movement.h"
39#include "nation.h"
40#include "packets.h"
41
42/* server */
43#include "citytools.h"
44#include "connecthand.h"
45#include "maphand.h"
46#include "notify.h"
47#include "plrhand.h"
48#include "srv_main.h"
49#include "stdinhand.h"
50#include "unittools.h"
51
52/* server/advisors */
53#include "advdata.h"
54
55#include "gamehand.h"
56
57#define CHALLENGE_ROOT "challenge"
58
59#define SPECLIST_TAG startpos
60#define SPECLIST_TYPE struct startpos
61#include "speclist.h"
62#define startpos_list_iterate(list, plink, psp) \
63 TYPED_LIST_BOTH_ITERATE(struct startpos_list_link, struct startpos, \
64 list, plink, psp)
65#define startpos_list_iterate_end LIST_BOTH_ITERATE_END
66
67 struct team_placement_config {
68 struct tile **startpos;
69 int flexible_startpos_num;
70 int usable_startpos_num;
71 int total_startpos_num;
72};
73
74 struct team_placement_state {
75 int *startpos;
76 long score;
77};
78
79#define SPECPQ_TAG team_placement
80#define SPECPQ_DATA_TYPE struct team_placement_state *
81#define SPECPQ_PRIORITY_TYPE long
82#include "specpq.h"
83
84/************************************************************************/
87 enum unit_role_id crole_to_role_id(char crole)
88{
89 switch (crole) {
90 case 'c':
91 return L_START_CITIES;
92 case 'w':
93 return L_START_WORKER;
94 case 'x':
95 return L_START_EXPLORER;
96 case 'k':
97 return L_START_KING;
98 case 's':
99 return L_START_DIPLOMAT;
100 case 'f':
101 return L_START_FERRY;
102 case 'd':
103 return L_START_DEFEND_OK;
104 case 'D':
105 return L_START_DEFEND_GOOD;
106 case 'a':
107 return L_START_ATTACK_FAST;
108 case 'A':
109 return L_START_ATTACK_STRONG;
110 default:
111 return 0;
112 }
113}
114
115/************************************************************************/
120 struct unit_type *crole_to_unit_type(char crole, struct player *pplayer)
121{
122 struct unit_type *utype = NULL;
123 enum unit_role_id role = crole_to_role_id(crole);
124 int num;
125
126 if (role == 0) {
127 fc_assert_ret_val(FALSE, NULL);
128 return NULL;
129 }
130
131 /* Create the unit of an appropriate type, if it exists */
132 num = num_role_units(role);
133 if (num > 0) {
134 if (pplayer != NULL) {
135 int i;
136
137 utype = first_role_unit_for_player(pplayer, role);
138 for (i = 0; utype == NULL && i < num; i++) {
139 struct unit_type *ntype = get_role_unit(role, i);
140
141 if (!utype_player_already_has_this_unique(pplayer, ntype)) {
142 utype = ntype;
143 }
144 }
145 } else {
146 utype = get_role_unit(role, 0);
147 }
148 }
149
150 return utype;
151}
152
153/************************************************************************/
158 static struct tile *place_starting_unit(struct tile *starttile,
159 struct player *pplayer,
160 struct unit_type *ptype, char crole)
161{
162 struct tile *ptile = NULL;
163 struct unit_type *utype;
164 bool hut_present = FALSE;
165
166 if (ptype != NULL) {
167 utype = ptype;
168 } else {
169 utype = crole_to_unit_type(crole, pplayer);
170 }
171
172 if (utype != NULL) {
173 iterate_outward(&(wld.map), starttile,
174 MAP_NATIVE_WIDTH + MAP_NATIVE_HEIGHT, itertile) {
175 if (!is_non_allied_unit_tile(itertile, pplayer,
176 utype_has_flag(utype, UTYF_FLAGLESS))
177 && is_native_tile(utype, itertile)) {
178 ptile = itertile;
179 break;
180 }
181 } iterate_outward_end;
182 }
183
184 if (ptile == NULL) {
185 /* No place where unit may exist. */
186 return NULL;
187 }
188
189 fc_assert_ret_val(!is_non_allied_unit_tile(ptile, pplayer,
190 utype_has_flag(utype, UTYF_FLAGLESS)),
191 NULL);
192
193 /* For scenarios or dispersion, huts may coincide with player starts (in
194 * other cases, huts are avoided as start positions). Remove any such hut,
195 * and make sure to tell the client, since we may have already sent this
196 * tile (with the hut) earlier: */
197 /* FIXME: Don't remove under a unit that can't enter or frighten hut */
198 extra_type_by_rmcause_iterate(ERM_ENTER, pextra) {
199 if (tile_has_extra(ptile, pextra)) {
200 tile_extra_rm_apply(ptile, pextra);
201 hut_present = TRUE;
202 }
203 } extra_type_by_rmcause_iterate_end;
204
205 if (hut_present) {
206 update_tile_knowledge(ptile);
207 log_verbose("Removed hut on start position for %s",
208 player_name(pplayer));
209 }
210
211 /* Expose visible area. */
212 map_show_circle(pplayer, ptile, game.server.init_vis_radius_sq);
213
214 if (utype != NULL) {
215 (void) create_unit(pplayer, ptile, utype, FALSE, 0, 0);
216 return ptile;
217 }
218
219 return NULL;
220}
221
222/************************************************************************/
225 static struct tile *find_dispersed_position(struct player *pplayer,
226 struct tile *pcenter)
227{
228 struct tile *ptile;
229 int x, y;
230 int bailout;
231
232 if (game.server.dispersion == 0) {
233 bailout = 1; /* One attempt is guaranteed to cover single tile */
234 } else {
235 bailout = game.server.dispersion * 2 + 1; /* Side of the area */
236 bailout *= bailout; /* Area */
237 bailout *= 5; /* Likely to hit each tile at least once */
238 }
239
240 do {
241 if (!bailout--) {
242 return NULL;
243 }
244 index_to_map_pos(&x, &y, tile_index(pcenter));
245 x += fc_rand(2 * game.server.dispersion + 1) - game.server.dispersion;
246 y += fc_rand(2 * game.server.dispersion + 1) - game.server.dispersion;
247 } while (!((ptile = map_pos_to_tile(&(wld.map), x, y))
248 && tile_continent(pcenter) == tile_continent(ptile)
249 && !is_ocean_tile(ptile)
250 && real_map_distance(pcenter, ptile) < game.server.dispersion
251 + 1
252 && !is_non_allied_unit_tile(ptile, pplayer, TRUE)));
253
254 return ptile;
255}
256
257/* Calculate the distance between tiles, according to the 'teamplacement'
258 * setting set to 'CLOSEST'. */
259#define team_placement_closest sq_map_distance
260
261/************************************************************************/
265 static int team_placement_continent(const struct tile *ptile1,
266 const struct tile *ptile2)
267{
268 return (ptile1->continent == ptile2->continent
269 ? sq_map_distance(ptile1, ptile2)
270 : sq_map_distance(ptile1, ptile2) + MAP_INDEX_SIZE);
271}
272
273/************************************************************************/
277 static int team_placement_horizontal(const struct tile *ptile1,
278 const struct tile *ptile2)
279{
280 int dx, dy;
281
282 map_distance_vector(&dx, &dy, ptile1, ptile2);
283 /* Map vector to natural vector (Y axis). */
284 return abs(MAP_IS_ISOMETRIC ? dx + dy : dy);
285}
286
287/************************************************************************/
291 static int team_placement_vertical(const struct tile *ptile1,
292 const struct tile *ptile2)
293{
294 int dx, dy;
295
296 map_distance_vector(&dx, &dy, ptile1, ptile2);
297 /* Map vector to natural vector (X axis). */
298 return abs(MAP_IS_ISOMETRIC ? dx - dy : dy);
299}
300
301/************************************************************************/
304 static void team_placement_state_destroy(struct team_placement_state *pstate)
305{
306 free(pstate->startpos);
307 free(pstate);
308}
309
310/************************************************************************/
313 static void do_team_placement(const struct team_placement_config *pconfig,
314 struct team_placement_state *pbest_state,
315 int iter_max)
316{
317 const size_t state_array_size = (sizeof(*pbest_state->startpos)
318 * pconfig->total_startpos_num);
319 struct team_placement_pq *pqueue =
320 team_placement_pq_new(pconfig->total_startpos_num * 4);
321 int (*distance)(const struct tile *, const struct tile *) = NULL;
322 struct team_placement_state *pstate, *pnew;
323 const struct tile *ptile1, *ptile2;
324 long base_delta, delta;
325 bool base_delta_calculated;
326 int iter = 0;
327 bool repeat;
328 int i, j, k, t1, t2;
329
330 switch (wld.map.server.team_placement) {
331 case TEAM_PLACEMENT_CLOSEST:
332 distance = team_placement_closest;
333 break;
334 case TEAM_PLACEMENT_CONTINENT:
335 distance = team_placement_continent;
336 break;
337 case TEAM_PLACEMENT_HORIZONTAL:
338 distance = team_placement_horizontal;
339 break;
340 case TEAM_PLACEMENT_VERTICAL:
341 distance = team_placement_vertical;
342 break;
343 case TEAM_PLACEMENT_DISABLED:
344 break;
345 }
346 fc_assert_ret_msg(distance != NULL, "Wrong team_placement variant (%d)",
347 wld.map.server.team_placement);
348
349 /* Initialize starting state. */
350 pstate = fc_malloc(sizeof(*pstate));
351 pstate->startpos = fc_malloc(state_array_size);
352 memcpy(pstate->startpos, pbest_state->startpos, state_array_size);
353 pstate->score = pbest_state->score;
354
355 do {
356 repeat = FALSE;
357 for (i = 0; i < pconfig->usable_startpos_num; i++) {
358 t1 = pstate->startpos[i];
359 if (t1 == -1) {
360 continue; /* Not used. */
361 }
362 ptile1 = pconfig->startpos[i];
363 base_delta_calculated = FALSE;
364 for (j = i + 1; j < (i >= pconfig->flexible_startpos_num
365 ? pconfig->usable_startpos_num
366 : pconfig->flexible_startpos_num); j++) {
367 t2 = pstate->startpos[j];
368 if (t2 == -1) {
369 /* Not assigned yet. */
370 ptile2 = pconfig->startpos[j];
371 if (base_delta_calculated) {
372 delta = base_delta;
373 for (k = 0; k < pconfig->total_startpos_num; k++) {
374 if (k != i && t1 == pstate->startpos[k]) {
375 delta += distance(ptile2, pconfig->startpos[k]);
376 }
377 }
378 } else {
379 delta = 0;
380 base_delta = 0;
381 for (k = 0; k < pconfig->total_startpos_num; k++) {
382 if (k != i && t1 == pstate->startpos[k]) {
383 base_delta -= distance(ptile1, pconfig->startpos[k]);
384 delta += distance(ptile2, pconfig->startpos[k]);
385 }
386 }
387 delta += base_delta;
388 base_delta_calculated = TRUE;
389 }
390 } else if (t1 < t2) {
391 ptile2 = pconfig->startpos[j];
392 if (base_delta_calculated) {
393 delta = base_delta;
394 for (k = 0; k < pconfig->total_startpos_num; k++) {
395 if (k != i && t1 == pstate->startpos[k]) {
396 delta += distance(ptile2, pconfig->startpos[k]);
397 } else if (k != j && t2 == pstate->startpos[k]) {
398 delta -= distance(ptile2, pconfig->startpos[k]);
399 delta += distance(ptile1, pconfig->startpos[k]);
400 }
401 }
402 } else {
403 delta = 0;
404 base_delta = 0;
405 for (k = 0; k < pconfig->total_startpos_num; k++) {
406 if (k != i && t1 == pstate->startpos[k]) {
407 base_delta -= distance(ptile1, pconfig->startpos[k]);
408 delta += distance(ptile2, pconfig->startpos[k]);
409 } else if (k != j && t2 == pstate->startpos[k]) {
410 delta -= distance(ptile2, pconfig->startpos[k]);
411 delta += distance(ptile1, pconfig->startpos[k]);
412 }
413 }
414 delta += base_delta;
415 base_delta_calculated = TRUE;
416 }
417 } else {
418 continue;
419 }
420
421 if (delta <= 0) {
422 repeat = TRUE;
423 pnew = fc_malloc(sizeof(*pnew));
424 pnew->startpos = fc_malloc(state_array_size);
425 memcpy(pnew->startpos, pstate->startpos, state_array_size);
426 pnew->startpos[i] = t2;
427 pnew->startpos[j] = t1;
428 pnew->score = pstate->score + delta;
429 team_placement_pq_insert(pqueue, pnew, -pnew->score);
430
431 if (pnew->score < pbest_state->score) {
432 memcpy(pbest_state->startpos, pnew->startpos, state_array_size);
433 pbest_state->score = pnew->score;
434 }
435 }
436 }
437 }
438
439 team_placement_state_destroy(pstate);
440 if (iter++ >= iter_max) {
441 log_normal(_("Didn't find optimal solution for team placement "
442 "in %d iterations."), iter);
443 break;
444 }
445
446 } while (repeat && team_placement_pq_remove(pqueue, &pstate));
447
448 team_placement_pq_destroy_full(pqueue, team_placement_state_destroy);
449}
450
451/************************************************************************/
454 void init_new_game(void)
455{
456 struct startpos_list *impossible_list, *targeted_list, *flexible_list;
457 struct tile *player_startpos[player_slot_count()];
458 int placed_units[player_slot_count()];
459 int players_to_place = player_count();
460 int sulen;
461
462 randomize_base64url_string(server.game_identifier,
463 sizeof(server.game_identifier));
464
465 /* Assign players to starting positions on the map.
466 * (In scenarios with restrictions on which nations can use which predefined
467 * start positions, this process tries to satisfy those restrictions, but
468 * does not guarantee to. Even if there is a solution to the matching
469 * problem, this algorithm may not find it.) */
470
471 fc_assert(player_count() <= map_startpos_count());
472
473 /* Convert the startposition hash table in a linked lists, as we mostly
474 * need now to iterate it now. And then, we will be able to remove the
475 * assigned start postions one by one. */
476 impossible_list = startpos_list_new();
477 targeted_list = startpos_list_new();
478 flexible_list = startpos_list_new();
479
480 map_startpos_iterate(psp) {
481 if (startpos_allows_all(psp)) {
482 startpos_list_append(flexible_list, psp);
483 } else {
484 startpos_list_append(targeted_list, psp);
485 }
486 } map_startpos_iterate_end;
487
488 fc_assert(startpos_list_size(targeted_list)
489 + startpos_list_size(flexible_list) == map_startpos_count());
490
491 memset(player_startpos, 0, sizeof(player_startpos));
492 log_verbose("Placing players at start positions.");
493
494 /* First assign start positions which have restrictions on which nations
495 * can use them. */
496 if (0 < startpos_list_size(targeted_list)) {
497 log_verbose("Assigning matching nations.");
498
499 startpos_list_shuffle(targeted_list); /* Randomize. */
500 do {
501 struct nation_type *pnation;
502 struct startpos_list_link *choice;
503 bool removed = FALSE;
504
505 /* Assign first players which can pick only one start position. */
506 players_iterate(pplayer) {
507 if (NULL != player_startpos[player_index(pplayer)]) {
508 /* Already assigned. */
509 continue;
510 }
511
512 pnation = nation_of_player(pplayer);
513 choice = NULL;
514 startpos_list_iterate(targeted_list, plink, psp) {
515 if (startpos_nation_allowed(psp, pnation)) {
516 if (NULL != choice) {
517 choice = NULL;
518 break; /* Many choices. */
519 } else {
520 choice = plink;
521 }
522 }
523 } startpos_list_iterate_end;
524
525 if (NULL != choice) {
526 /* Assign this start position to this player and remove
527 * both from consideration. */
528 struct tile *ptile =
529 startpos_tile(startpos_list_link_data(choice));
530
531 player_startpos[player_index(pplayer)] = ptile;
532 startpos_list_erase(targeted_list, choice);
533 players_to_place--;
534 removed = TRUE;
535 log_verbose("Start position (%d, %d) exactly matches player %s (%s).",
536 TILE_XY(ptile), player_name(pplayer),
537 nation_rule_name(pnation));
538 }
539 } players_iterate_end;
540
541 if (!removed) {
542 /* Didn't find any 1:1 matches. For the next restricted start
543 * position, assign a random matching player. (This may create
544 * restrictions such that more 1:1 matches are possible.) */
545 struct startpos *psp = startpos_list_back(targeted_list);
546 struct tile *ptile = startpos_tile(psp);
547 struct player *rand_plr = NULL;
548 int i = 0;
549
550 startpos_list_pop_back(targeted_list); /* Detach 'psp'. */
551 players_iterate(pplayer) {
552 if (NULL != player_startpos[player_index(pplayer)]) {
553 /* Already assigned. */
554 continue;
555 }
556
557 pnation = nation_of_player(pplayer);
558 if (startpos_nation_allowed(psp, pnation) && 0 == fc_rand(++i)) {
559 rand_plr = pplayer;
560 }
561 } players_iterate_end;
562
563 if (NULL != rand_plr) {
564 player_startpos[player_index(rand_plr)] = ptile;
565 players_to_place--;
566 log_verbose("Start position (%d, %d) matches player %s (%s).",
567 TILE_XY(ptile), player_name(rand_plr),
568 nation_rule_name(nation_of_player(rand_plr)));
569 } else {
570 /* This start position cannot be assigned, given the assignments
571 * made so far. We may have to fall back to mismatched
572 * assignments. */
573 log_verbose("Start position (%d, %d) cannot be assigned for "
574 "any player, keeping for the moment...",
575 TILE_XY(ptile));
576 /* Keep it for later, we may need it. */
577 startpos_list_append(impossible_list, psp);
578 }
579 }
580 } while (0 < players_to_place && 0 < startpos_list_size(targeted_list));
581 }
582
583 /* Now try to assign with regard to the 'teamplacement' setting. */
584 if (players_to_place > 0
585 && wld.map.server.team_placement != TEAM_PLACEMENT_DISABLED
586 && player_count() > team_count()) {
587 const struct player_list *members;
588 int team_placement_players_to_place = 0;
589 int real_team_count = 0;
590
591 teams_iterate(pteam) {
592 members = team_members(pteam);
593 fc_assert(0 < player_list_size(members));
594 real_team_count++;
595 if (player_list_size(members) == 1) {
596 /* Single player teams, doesn't count for team placement. */
597 continue;
598 }
599 player_list_iterate(members, pplayer) {
600 if (player_startpos[player_index(pplayer)] == NULL) {
601 team_placement_players_to_place++;
602 }
603 } player_list_iterate_end;
604 } teams_iterate_end;
605
606 if (real_team_count > 1 && team_placement_players_to_place > 0) {
607 /* We really can do something to improve team placement. */
608 struct team_placement_config config;
609 struct team_placement_state state;
610 int i, j, t;
611
612 log_verbose("Do team placement for %d players, using %s variant.",
613 team_placement_players_to_place,
614 team_placement_name(wld.map.server.team_placement));
615
616 /* Initialize configuration. */
617 config.flexible_startpos_num = startpos_list_size(flexible_list);
618 config.usable_startpos_num = config.flexible_startpos_num;
619 if (config.flexible_startpos_num < team_placement_players_to_place) {
620 config.usable_startpos_num += startpos_list_size(impossible_list);
621 }
622 config.total_startpos_num = (config.usable_startpos_num
623 + player_count() - players_to_place);
624 config.startpos = fc_malloc(sizeof(*config.startpos)
625 * config.total_startpos_num);
626 i = 0;
627 startpos_list_iterate(flexible_list, plink, psp) {
628 config.startpos[i++] = startpos_tile(psp);
629 } startpos_list_iterate_end;
630 fc_assert(i == config.flexible_startpos_num);
631 if (i < config.usable_startpos_num) {
632 startpos_list_iterate(impossible_list, plink, psp) {
633 config.startpos[i++] = startpos_tile(psp);
634 } startpos_list_iterate_end;
635 }
636 fc_assert(i == config.usable_startpos_num);
637 while (i < config.total_startpos_num) {
638 config.startpos[i++] = NULL;
639 }
640 fc_assert(i == config.total_startpos_num);
641
642 /* Initialize state. */
643 state.startpos = fc_malloc(sizeof(*state.startpos)
644 * config.total_startpos_num);
645 state.score = 0;
646 i = 0;
647 j = config.usable_startpos_num;
648 teams_iterate(pteam) {
649 members = team_members(pteam);
650 if (player_list_size(members) <= 1) {
651 /* Single player teams, doesn't count for team placement. */
652 continue;
653 }
654 t = team_number(pteam);
655 player_list_iterate(members, pplayer) {
656 struct tile *ptile = player_startpos[player_index(pplayer)];
657
658 if (ptile == NULL) {
659 state.startpos[i++] = t;
660 } else {
661 state.startpos[j] = t;
662 config.startpos[j] = ptile;
663 j++;
664 }
665 } player_list_iterate_end;
666 } teams_iterate_end;
667 while (i < config.usable_startpos_num) {
668 state.startpos[i++] = -1;
669 }
670 fc_assert(i == config.usable_startpos_num);
671 while (j < config.total_startpos_num) {
672 state.startpos[j++] = -1;
673 }
674 fc_assert(j == config.total_startpos_num);
675
676 /* Look for best team placement. */
677 do_team_placement(&config, &state, team_placement_players_to_place);
678
679 /* Apply result. */
680 for (i = 0; i < config.usable_startpos_num; i++) {
681 t = state.startpos[i];
682 if (t != -1) {
683 const struct team *pteam = team_by_number(t);
684 int candidate_index = -1;
685 int candidate_num = 0;
686
687 log_verbose("Start position (%d, %d) assigned to team %d (%s)",
688 TILE_XY(config.startpos[i]),
689 t, team_rule_name(pteam));
690
691 player_list_iterate(team_members(pteam), member) {
692 if (player_startpos[player_index(member)] == NULL
693 && fc_rand(++candidate_num) == 0) {
694 candidate_index = player_index(member);
695 }
696 } player_list_iterate_end;
697 fc_assert(candidate_index >= 0);
698 player_startpos[candidate_index] = config.startpos[i];
699 team_placement_players_to_place--;
700 players_to_place--;
701 }
702 }
703 fc_assert(team_placement_players_to_place == 0);
704
705 /* Free data. */
706 if (players_to_place > 0) {
707 /* We need to remove used startpos from the lists. */
708 i = 0;
709 startpos_list_iterate(flexible_list, plink, psp) {
710 (void)psp; /* To avoid 'set but unused' compiler warning */
711 fc_assert(config.startpos[i] == startpos_tile(psp));
712 if (state.startpos[i] != -1) {
713 startpos_list_erase(flexible_list, plink);
714 }
715 i++;
716 } startpos_list_iterate_end;
717 fc_assert(i == config.flexible_startpos_num);
718 if (i < config.usable_startpos_num) {
719 startpos_list_iterate(impossible_list, plink, psp) {
720 (void)psp; /* To avoid 'set but unused' compiler warning */
721 fc_assert(config.startpos[i] == startpos_tile(psp));
722 if (state.startpos[i] != -1) {
723 startpos_list_erase(impossible_list, plink);
724 }
725 i++;
726 } startpos_list_iterate_end;
727 }
728 fc_assert(i == config.usable_startpos_num);
729 }
730
731 free(state.startpos);
732 free(config.startpos);
733 }
734 }
735
736 /* Now assign unrestricted start positions to any remaining players. */
737 if (0 < players_to_place && 0 < startpos_list_size(flexible_list)) {
738 struct tile *ptile;
739
740 log_verbose("Assigning unrestricted start positions.");
741
742 startpos_list_shuffle(flexible_list); /* Randomize. */
743 players_iterate(pplayer) {
744 if (NULL != player_startpos[player_index(pplayer)]) {
745 /* Already assigned. */
746 continue;
747 }
748
749 ptile = startpos_tile(startpos_list_front(flexible_list));
750 player_startpos[player_index(pplayer)] = ptile;
751 players_to_place--;
752 startpos_list_pop_front(flexible_list);
753 log_verbose("Start position (%d, %d) assigned randomly "
754 "to player %s (%s).", TILE_XY(ptile), player_name(pplayer),
755 nation_rule_name(nation_of_player(pplayer)));
756 if (0 == startpos_list_size(flexible_list)) {
757 break;
758 }
759 } players_iterate_end;
760 }
761
762 if (0 < players_to_place && 0 < startpos_list_size(impossible_list)) {
763 /* We still have players to place, and we have some restricted start
764 * positions whose nation requirements can't be satisfied given existing
765 * assignments. Fall back to making assignments ignoring the positions'
766 * nation requirements. */
767
768 struct tile *ptile;
769
770 log_verbose("Ignoring nation restrictions on remaining start positions.");
771
772 startpos_list_shuffle(impossible_list); /* Randomize. */
773 players_iterate(pplayer) {
774 if (NULL != player_startpos[player_index(pplayer)]) {
775 /* Already assigned. */
776 continue;
777 }
778
779 ptile = startpos_tile(startpos_list_front(impossible_list));
780 player_startpos[player_index(pplayer)] = ptile;
781 players_to_place--;
782 startpos_list_pop_front(impossible_list);
783 log_verbose("Start position (%d, %d) assigned to mismatched "
784 "player %s (%s).", TILE_XY(ptile), player_name(pplayer),
785 nation_rule_name(nation_of_player(pplayer)));
786 if (0 == startpos_list_size(impossible_list)) {
787 break;
788 }
789 } players_iterate_end;
790 }
791
792 fc_assert(0 == players_to_place);
793
794 startpos_list_destroy(impossible_list);
795 startpos_list_destroy(targeted_list);
796 startpos_list_destroy(flexible_list);
797
798 sulen = strlen(game.server.start_units);
799
800 /* Loop over all players, creating their initial units... */
801 shuffled_players_iterate(pplayer) {
802 struct tile *ptile;
803
804 /* We have to initialise the advisor and ai here as we could make contact
805 * to other nations at this point. */
806 adv_data_phase_init(pplayer, FALSE);
807 CALL_PLR_AI_FUNC(phase_begin, pplayer, pplayer, FALSE);
808
809 ptile = player_startpos[player_index(pplayer)];
810
811 fc_assert_action(NULL != ptile, continue);
812
813 /* Place first city */
814 if (game.server.start_city) {
815 create_city(pplayer, ptile, city_name_suggestion(pplayer, ptile),
816 NULL);
817
818 /* Expose visible area. */
819 map_show_circle(pplayer, ptile, game.server.init_vis_radius_sq);
820 }
821
822 if (sulen > 0) {
823 /* Place the first unit. */
824 if (place_starting_unit(ptile, pplayer, NULL,
825 game.server.start_units[0]) != NULL) {
826 placed_units[player_index(pplayer)] = 1;
827 } else {
828 placed_units[player_index(pplayer)] = 0;
829 }
830 } else {
831 placed_units[player_index(pplayer)] = 0;
832 }
833 } shuffled_players_iterate_end;
834
835 /* Place all other units. */
836 shuffled_players_iterate(pplayer) {
837 int i;
838 struct tile *const ptile = player_startpos[player_index(pplayer)];
839 struct nation_type *nation = nation_of_player(pplayer);
840
841 fc_assert_action(NULL != ptile, continue);
842
843 /* Place global start units */
844 for (i = 1; i < sulen; i++) {
845 struct tile *rand_tile = find_dispersed_position(pplayer, ptile);
846
847 /* Create the unit of an appropriate type. */
848 if (rand_tile != NULL
849 && place_starting_unit(rand_tile, pplayer, NULL,
850 game.server.start_units[i]) != NULL) {
851 placed_units[player_index(pplayer)]++;
852 }
853 }
854
855 /* Place nation specific start units (not role based!) */
856 i = 0;
857 while (NULL != nation->init_units[i] && MAX_NUM_UNIT_LIST > i) {
858 struct tile *rand_tile = find_dispersed_position(pplayer, ptile);
859
860 if (rand_tile != NULL
861 && place_starting_unit(rand_tile, pplayer,
862 nation->init_units[i], '\0') != NULL) {
863 placed_units[player_index(pplayer)]++;
864 }
865 i++;
866 }
867 } shuffled_players_iterate_end;
868
869 players_iterate(pplayer) {
870 /* Close the active phase for advisor and ai for all players; it was
871 * opened in the first loop above. */
872 adv_data_phase_done(pplayer);
873 CALL_PLR_AI_FUNC(phase_finished, pplayer, pplayer);
874
875 fc_assert_msg(game.server.start_city || 0 < placed_units[player_index(pplayer)],
876 _("No units placed for %s!"), player_name(pplayer));
877 } players_iterate_end;
878}
879
880/************************************************************************/
884 void send_year_to_clients(void)
885{
886 struct packet_new_year apacket;
887
888 players_iterate(pplayer) {
889 pplayer->nturns_idle++;
890 } players_iterate_end;
891
892 apacket.year = game.info.year;
893 apacket.fragments = game.info.fragment_count;
894 apacket.turn = game.info.turn;
895 lsend_packet_new_year(game.est_connections, &apacket);
896
897 /* Hmm, clients could add this themselves based on above packet? */
898 notify_conn(game.est_connections, NULL, E_NEXT_YEAR, ftc_any,
899 _("Year: %s"), calendar_text());
900}
901
902/************************************************************************/
910 void send_game_info(struct conn_list *dest)
911{
912 struct packet_timeout_info tinfo;
913
914 if (!dest) {
915 dest = game.est_connections;
916 }
917
918 tinfo = game.tinfo;
919
920 /* the following values are computed every
921 time a packet_game_info packet is created */
922
923 /* Sometimes this function is called before the phase_timer is
924 * initialized. In that case we want to send the dummy value. */
925 if (current_turn_timeout() > 0 && game.server.phase_timer) {
926 /* Whenever the client sees this packet, it starts a new timer at 0;
927 * but the server's timer is only ever reset at the start of a phase
928 * (and game.tinfo.seconds_to_phasedone is relative to this).
929 * Account for the difference. */
930 tinfo.seconds_to_phasedone = game.tinfo.seconds_to_phasedone
931 - timer_read_seconds(game.server.phase_timer)
932 - game.server.additional_phase_seconds;
933 } else {
934 /* unused but at least initialized */
935 tinfo.seconds_to_phasedone = -1.0;
936 }
937
938 conn_list_iterate(dest, pconn) {
939 /* Timeout info is separate from other packets since it has to
940 * be sent always (it's not 'is-info') while the others are 'is-info'
941 * Calendar info has been split from Game info packet to make packet
942 * size more tolerable when json protocol is in use. */
943 send_packet_game_info(pconn, &(game.info));
944 send_packet_calendar_info(pconn, &(game.calendar));
945 send_packet_timeout_info(pconn, &tinfo);
946 }
947 conn_list_iterate_end;
948}
949
950/************************************************************************/
953 void send_scenario_info(struct conn_list *dest)
954{
955 if (!dest) {
956 dest = game.est_connections;
957 }
958
959 conn_list_iterate(dest, pconn) {
960 send_packet_scenario_info(pconn, &(game.scenario));
961 } conn_list_iterate_end;
962}
963
964/************************************************************************/
967 void send_scenario_description(struct conn_list *dest)
968{
969 if (!dest) {
970 dest = game.est_connections;
971 }
972
973 conn_list_iterate(dest, pconn) {
974 send_packet_scenario_description(pconn, &(game.scenario_desc));
975 } conn_list_iterate_end;
976}
977
978/************************************************************************/
988 int update_timeout(void)
989{
990 /* if there's no timer or we're doing autogame, do nothing */
991 if (game.info.timeout < 1 || game.server.timeoutint == 0) {
992 return game.info.timeout;
993 }
994
995 if (game.server.timeoutcounter >= game.server.timeoutint) {
996 game.info.timeout += game.server.timeoutinc;
997 game.server.timeoutinc *= game.server.timeoutincmult;
998
999 game.server.timeoutcounter = 1;
1000 game.server.timeoutint += game.server.timeoutintinc;
1001
1002 if (game.info.timeout > GAME_MAX_TIMEOUT) {
1003 notify_conn(game.est_connections, NULL, E_SETTING, ftc_server,
1004 _("The turn timeout has exceeded its maximum value, "
1005 "fixing at its maximum."));
1006 log_debug("game.info.timeout exceeded maximum value");
1007 game.info.timeout = GAME_MAX_TIMEOUT;
1008 game.server.timeoutint = 0;
1009 game.server.timeoutinc = 0;
1010 } else if (game.info.timeout < 0) {
1011 notify_conn(game.est_connections, NULL, E_SETTING, ftc_server,
1012 _("The turn timeout is smaller than zero, "
1013 "fixing at zero."));
1014 log_debug("game.info.timeout less than zero");
1015 game.info.timeout = 0;
1016 }
1017 } else {
1018 game.server.timeoutcounter++;
1019 }
1020
1021 log_debug("timeout=%d, inc=%d incmult=%d\n "
1022 "int=%d, intinc=%d, turns till next=%d",
1023 game.info.timeout, game.server.timeoutinc,
1024 game.server.timeoutincmult, game.server.timeoutint,
1025 game.server.timeoutintinc,
1026 game.server.timeoutint - game.server.timeoutcounter);
1027
1028 return game.info.timeout;
1029}
1030
1031/************************************************************************/
1039 void increase_timeout_because_unit_moved(void)
1040{
1041 if (current_turn_timeout() > 0 && game.server.timeoutaddenemymove > 0) {
1042 double maxsec = (timer_read_seconds(game.server.phase_timer)
1043 + (double) game.server.timeoutaddenemymove);
1044
1045 if (maxsec > game.tinfo.seconds_to_phasedone) {
1046 game.tinfo.seconds_to_phasedone = maxsec;
1047 send_game_info(NULL);
1048 }
1049 }
1050}
1051
1052/************************************************************************/
1055 static void gen_challenge_filename(struct connection *pc)
1056{
1057}
1058
1059/************************************************************************/
1062 static const char *get_challenge_filename(struct connection *pc)
1063{
1064 static char filename[MAX_LEN_PATH];
1065
1066 fc_snprintf(filename, sizeof(filename), "%s_%d_%d",
1067 CHALLENGE_ROOT, srvarg.port, pc->id);
1068
1069 return filename;
1070}
1071
1072/************************************************************************/
1075 static const char *get_challenge_fullname(struct connection *pc)
1076{
1077 static char fullname[MAX_LEN_PATH];
1078 const char *sdir = freeciv_storage_dir();
1079 const char *cname;
1080
1081 if (sdir == NULL) {
1082 return NULL;
1083 }
1084
1085 cname = get_challenge_filename(pc);
1086
1087 if (cname == NULL) {
1088 return NULL;
1089 }
1090
1091 fc_snprintf(fullname, sizeof(fullname), "%s" DIR_SEPARATOR "%s", sdir, cname);
1092
1093 return fullname;
1094}
1095
1096/************************************************************************/
1099 const char *new_challenge_filename(struct connection *pc)
1100{
1101 gen_challenge_filename(pc);
1102 return get_challenge_filename(pc);
1103}
1104
1105 struct mrc_sendclient_data {
1106 int count;
1107 struct packet_ruleset_choices *packet;
1108};
1109
1110/************************************************************************/
1113 static void ruleset_cache_sendclient_cb(const char *mp_name,
1114 const char *filename, void *data_in)
1115{
1116 struct mrc_sendclient_data *data = (struct mrc_sendclient_data *)data_in;
1117 const int maxlen = sizeof(data->packet->rulesets[data->count]);
1118
1119 if (data->count >= MAX_NUM_RULESETS) {
1120 log_verbose("Can't send more than %d ruleset names to client, "
1121 "skipping some", MAX_NUM_RULESETS);
1122 return;
1123 }
1124
1125 if (fc_strlcpy(data->packet->rulesets[data->count], mp_name, maxlen) < maxlen) {
1126 data->count++;
1127 } else {
1128 log_verbose("Modpack name '%s' too long to send to client, skipped",
1129 mp_name);
1130 }
1131}
1132
1133/************************************************************************/
1136 void cache_rulesets(void)
1137{
1138 static bool rulesets_cached = FALSE;
1139
1140 if (!rulesets_cached) {
1141 struct fileinfo_list *ruleset_choices;
1142
1143 ruleset_choices = get_modpacks_list();
1144
1145 fileinfo_list_iterate(ruleset_choices, pfile) {
1146 struct section_file *sf;
1147
1148 sf = secfile_load(pfile->fullname, FALSE);
1149
1150 if (sf != NULL) {
1151 modpack_cache_ruleset(sf);
1152 secfile_destroy(sf);
1153 }
1154 } fileinfo_list_iterate_end;
1155
1156 fileinfo_list_destroy(ruleset_choices);
1157
1158 rulesets_cached = TRUE;
1159 }
1160}
1161
1162/************************************************************************/
1167 static void send_ruleset_choices(struct connection *pc)
1168{
1169 struct packet_ruleset_choices packet;
1170 struct mrc_sendclient_data data;
1171
1172 cache_rulesets();
1173
1174 data.count = 0;
1175 data.packet = &packet;
1176 modpack_ruleset_cache_iterate(ruleset_cache_sendclient_cb, &data);
1177
1178 packet.ruleset_count = data.count;
1179
1180 send_packet_ruleset_choices(pc, &packet);
1181}
1182
1183/************************************************************************/
1186 void handle_ruleset_select(struct connection *pc,
1187 const struct packet_ruleset_select *packet)
1188{
1189 struct section_file *sf;
1190 const char *name;
1191
1192 if (server_state() != S_S_INITIAL) {
1193 log_warn("Unexpected ruleset selection packet from client");
1194 return;
1195 }
1196
1197 if (pc->access_level < ALLOW_HACK) {
1198 log_verbose("Attempt to set ruleset from non-hack level connection");
1199 }
1200
1201 name = modpack_file_from_ruleset_cache(packet->modpack);
1202
1203 if (name == NULL) {
1204 log_error("Modpack \"%s\" not in ruleset cache", packet->modpack);
1205 return;
1206 }
1207
1208 sf = secfile_load(name, FALSE);
1209
1210 if (sf == NULL) {
1211 log_error("Failed to load modpack file \"%s\"", name);
1212 return;
1213 }
1214
1215 name = modpack_serv_file(sf);
1216
1217 if (name != NULL) {
1218 read_init_script(pc, name, FALSE, FALSE);
1219 } else {
1220 name = modpack_rulesetdir(sf);
1221
1222 if (name != NULL) {
1223 set_rulesetdir(pc, name, FALSE, 0);
1224 } else {
1225 log_error("Modpack \"%s\" does not contain ruleset at all",
1226 packet->modpack);
1227 }
1228 }
1229
1230 secfile_destroy(sf);
1231}
1232
1233/************************************************************************/
1237 void handle_single_want_hack_req(struct connection *pc,
1238 const struct packet_single_want_hack_req *
1239 packet)
1240{
1241 struct section_file *secfile;
1242 const char *token = NULL;
1243 bool you_have_hack = FALSE;
1244
1245 if ((secfile = secfile_load(get_challenge_fullname(pc), FALSE))) {
1246 token = secfile_lookup_str(secfile, "challenge.token");
1247 you_have_hack = (token && strcmp(token, packet->token) == 0);
1248 secfile_destroy(secfile);
1249 } else {
1250 log_debug("Error reading '%s':\n%s", get_challenge_fullname(pc),
1251 secfile_error());
1252 }
1253
1254 if (!token) {
1255 log_debug("Failed to read authentication token");
1256 }
1257
1258 if (you_have_hack) {
1259 conn_set_access(pc, ALLOW_HACK, TRUE);
1260 }
1261
1262 dsend_packet_single_want_hack_reply(pc, you_have_hack);
1263
1264 send_ruleset_choices(pc);
1265 send_conn_info(pc->self, NULL);
1266}
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:564
advdata.h
ai.h
CALL_PLR_AI_FUNC
#define CALL_PLR_AI_FUNC(_func, _player,...)
Definition ai.h:377
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:453
create_city
void create_city(struct player *pplayer, struct tile *ptile, const char *name, struct player *nationality)
Definition citytools.c:1514
citytools.h
incite_cost
char * incite_cost
Definition comments.c:74
send_conn_info
void send_conn_info(struct conn_list *src, struct conn_list *dest)
Definition connecthand.c:601
conn_set_access
void conn_set_access(struct connection *pconn, enum cmdlevel new_level, bool granted)
Definition connecthand.c:72
connecthand.h
conn_list_iterate
#define conn_list_iterate(connlist, pconn)
Definition connection.h:108
conn_list_iterate_end
#define conn_list_iterate_end
Definition connection.h:110
events.h
extra_type_by_rmcause_iterate_end
#define extra_type_by_rmcause_iterate_end
Definition extras.h:358
extra_type_by_rmcause_iterate
#define extra_type_by_rmcause_iterate(_rmcause, _extra)
Definition extras.h:353
MAX_NUM_RULESETS
#define MAX_NUM_RULESETS
Definition fc_types.h:416
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:62
current_turn_timeout
int current_turn_timeout(void)
Definition game.c:854
wld
struct world wld
Definition game.c:63
game.h
GAME_MAX_TIMEOUT
#define GAME_MAX_TIMEOUT
Definition game.h:606
gen_challenge_filename
static void gen_challenge_filename(struct connection *pc)
Definition gamehand.c:1055
get_challenge_fullname
static const char * get_challenge_fullname(struct connection *pc)
Definition gamehand.c:1075
send_scenario_description
void send_scenario_description(struct conn_list *dest)
Definition gamehand.c:967
send_year_to_clients
void send_year_to_clients(void)
Definition gamehand.c:884
send_scenario_info
void send_scenario_info(struct conn_list *dest)
Definition gamehand.c:953
place_starting_unit
static struct tile * place_starting_unit(struct tile *starttile, struct player *pplayer, struct unit_type *ptype, char crole)
Definition gamehand.c:158
team_placement_closest
#define team_placement_closest
Definition gamehand.c:259
team_placement_vertical
static int team_placement_vertical(const struct tile *ptile1, const struct tile *ptile2)
Definition gamehand.c:291
update_timeout
int update_timeout(void)
Definition gamehand.c:988
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:1237
send_game_info
void send_game_info(struct conn_list *dest)
Definition gamehand.c:910
CHALLENGE_ROOT
#define CHALLENGE_ROOT
Definition gamehand.c:57
send_ruleset_choices
static void send_ruleset_choices(struct connection *pc)
Definition gamehand.c:1167
find_dispersed_position
static struct tile * find_dispersed_position(struct player *pplayer, struct tile *pcenter)
Definition gamehand.c:225
startpos_list_iterate_end
#define startpos_list_iterate_end
Definition gamehand.c:65
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:313
team_placement_continent
static int team_placement_continent(const struct tile *ptile1, const struct tile *ptile2)
Definition gamehand.c:265
ruleset_cache_sendclient_cb
static void ruleset_cache_sendclient_cb(const char *mp_name, const char *filename, void *data_in)
Definition gamehand.c:1113
startpos_list_iterate
#define startpos_list_iterate(list, plink, psp)
Definition gamehand.c:62
crole_to_role_id
enum unit_role_id crole_to_role_id(char crole)
Definition gamehand.c:87
get_challenge_filename
static const char * get_challenge_filename(struct connection *pc)
Definition gamehand.c:1062
increase_timeout_because_unit_moved
void increase_timeout_because_unit_moved(void)
Definition gamehand.c:1039
handle_ruleset_select
void handle_ruleset_select(struct connection *pc, const struct packet_ruleset_select *packet)
Definition gamehand.c:1186
init_new_game
void init_new_game(void)
Definition gamehand.c:454
crole_to_unit_type
struct unit_type * crole_to_unit_type(char crole, struct player *pplayer)
Definition gamehand.c:120
team_placement_state_destroy
static void team_placement_state_destroy(struct team_placement_state *pstate)
Definition gamehand.c:304
new_challenge_filename
const char * new_challenge_filename(struct connection *pc)
Definition gamehand.c:1099
team_placement_horizontal
static int team_placement_horizontal(const struct tile *ptile1, const struct tile *ptile2)
Definition gamehand.c:277
cache_rulesets
void cache_rulesets(void)
Definition gamehand.c:1136
gamehand.h
improvement.h
name
const char * name
Definition inputfile.c:127
log.h
fc_assert_msg
#define fc_assert_msg(condition, message,...)
Definition log.h:181
log_warn
#define log_warn(message,...)
Definition log.h:105
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
log_error
#define log_error(message,...)
Definition log.h:103
sq_map_distance
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:647
startpos_nation_allowed
bool startpos_nation_allowed(const struct startpos *psp, const struct nation_type *pnation)
Definition map.c:1704
startpos_tile
struct tile * startpos_tile(const struct startpos *psp)
Definition map.c:1694
startpos_allows_all
bool startpos_allows_all(const struct startpos *psp)
Definition map.c:1717
map_pos_to_tile
struct tile * map_pos_to_tile(const struct civ_map *nmap, int map_x, int map_y)
Definition map.c:425
map_startpos_count
int map_startpos_count(void)
Definition map.c:1882
real_map_distance
int real_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:636
map_distance_vector
void map_distance_vector(int *dx, int *dy, const struct tile *tile0, const struct tile *tile1)
Definition map.c:1087
iterate_outward
#define iterate_outward(nmap, start_tile, max_dist, itr_tile)
Definition map.h:353
iterate_outward_end
#define iterate_outward_end
Definition map.h:357
map_startpos_iterate
#define map_startpos_iterate(NAME_psp)
Definition map.h:125
map_startpos_iterate_end
#define map_startpos_iterate_end
Definition map.h:128
index_to_map_pos
#define index_to_map_pos(pmap_x, pmap_y, mindex)
Definition map.h:218
map_show_circle
void map_show_circle(struct player *pplayer, struct tile *ptile, int radius_sq)
Definition maphand.c:871
update_tile_knowledge
void update_tile_knowledge(struct tile *ptile)
Definition maphand.c:1443
maphand.h
mem.h
fc_malloc
#define fc_malloc(sz)
Definition mem.h:34
modpack_ruleset_cache_iterate
void modpack_ruleset_cache_iterate(mrc_cb cb, void *data)
Definition modpack.c:202
modpack_file_from_ruleset_cache
const char * modpack_file_from_ruleset_cache(const char *name)
Definition modpack.c:188
modpack_serv_file
const char * modpack_serv_file(struct section_file *sf)
Definition modpack.c:140
modpack_rulesetdir
const char * modpack_rulesetdir(struct section_file *sf)
Definition modpack.c:152
get_modpacks_list
struct fileinfo_list * get_modpacks_list(void)
Definition modpack.c:107
modpack_cache_ruleset
const char * modpack_cache_ruleset(struct section_file *sf)
Definition modpack.c:165
modpack.h
is_native_tile
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:330
movement.h
nation_rule_name
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:138
nation_of_player
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:444
nation.h
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:39945
send_packet_scenario_info
int send_packet_scenario_info(struct connection *pc, const struct packet_scenario_info *packet)
Definition packets_gen.c:79008
send_packet_ruleset_choices
int send_packet_ruleset_choices(struct connection *pc, const struct packet_ruleset_choices *packet)
Definition packets_gen.c:73719
send_packet_game_info
int send_packet_game_info(struct connection *pc, const struct packet_game_info *packet)
Definition packets_gen.c:9786
send_packet_calendar_info
int send_packet_calendar_info(struct connection *pc, const struct packet_calendar_info *packet)
Definition packets_gen.c:10209
dsend_packet_single_want_hack_reply
int dsend_packet_single_want_hack_reply(struct connection *pc, bool you_have_hack)
Definition packets_gen.c:73405
send_packet_scenario_description
int send_packet_scenario_description(struct connection *pc, const struct packet_scenario_description *packet)
Definition packets_gen.c:79186
send_packet_timeout_info
int send_packet_timeout_info(struct connection *pc, const struct packet_timeout_info *packet)
Definition packets_gen.c:10426
player_count
int player_count(void)
Definition player.c:817
player_slot_count
int player_slot_count(void)
Definition player.c:418
player_name
const char * player_name(const struct player *pplayer)
Definition player.c:895
player_index
int player_index(const struct player *pplayer)
Definition player.c:829
players_iterate_end
#define players_iterate_end
Definition player.h:539
players_iterate
#define players_iterate(_pplayer)
Definition player.h:534
player_list_iterate
#define player_list_iterate(playerlist, pplayer)
Definition player.h:557
player_list_iterate_end
#define player_list_iterate_end
Definition player.h:559
plrhand.h
shuffled_players_iterate_end
#define shuffled_players_iterate_end
Definition plrhand.h:108
shuffled_players_iterate
#define shuffled_players_iterate(NAME_pplayer)
Definition plrhand.h:98
rand.h
fc_rand
#define fc_rand(_size)
Definition rand.h:56
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:2175
randomize_base64url_string
void randomize_base64url_string(char *s, size_t n)
Definition shared.c:339
freeciv_storage_dir
char * freeciv_storage_dir(void)
Definition shared.c:678
shared.h
DIR_SEPARATOR
#define DIR_SEPARATOR
Definition shared.h:127
fileinfo_list_iterate
#define fileinfo_list_iterate(list, pnode)
Definition shared.h:176
MAX_LEN_PATH
#define MAX_LEN_PATH
Definition shared.h:32
fileinfo_list_iterate_end
#define fileinfo_list_iterate_end
Definition shared.h:178
speclist.h
specpq.h
y
struct sprite int int y
Definition sprite_g.h:31
x
struct sprite int x
Definition sprite_g.h:31
srvarg
struct server_arguments srvarg
Definition srv_main.c:180
server_state
enum server_states server_state(void)
Definition srv_main.c:337
srv_main.h
read_init_script
bool read_init_script(struct connection *caller, const char *script_filename, bool from_cmdline, bool check)
Definition stdinhand.c:1168
set_rulesetdir
bool set_rulesetdir(struct connection *caller, const char *str, bool check, int read_recursion)
Definition stdinhand.c:3975
stdinhand.h
string_vector.h
civ_game::dispersion
int dispersion
Definition game.h:143
civ_game::init_vis_radius_sq
int init_vis_radius_sq
Definition game.h:152
civ_game::start_units
char start_units[MAX_LEN_STARTUNIT]
Definition game.h:189
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:207
civ_game::additional_phase_seconds
int additional_phase_seconds
Definition game.h:212
civ_game::scenario
struct packet_scenario_info scenario
Definition game.h:87
civ_game::timeoutint
int timeoutint
Definition game.h:203
civ_game::phase_timer
struct timer * phase_timer
Definition game.h:211
civ_game::server
struct civ_game::@31::@35 server
civ_game::timeoutincmult
int timeoutincmult
Definition game.h:205
civ_game::tinfo
struct packet_timeout_info tinfo
Definition game.h:91
civ_game::timeoutinc
int timeoutinc
Definition game.h:204
civ_game::start_city
bool start_city
Definition game.h:190
civ_game::calendar
struct packet_calendar_info calendar
Definition game.h:90
civ_game::timeoutintinc
int timeoutintinc
Definition game.h:206
civ_game::timeoutaddenemymove
int timeoutaddenemymove
Definition game.h:208
civ_map::server
struct civ_map::@42::@44 server
civ_map::team_placement
enum team_placement team_placement
Definition map_types.h:110
connection
Definition connection.h:136
data_in
Definition dataio_raw.h:30
mrc_sendclient_data
Definition gamehand.c:1105
mrc_sendclient_data::count
int count
Definition gamehand.c:1106
mrc_sendclient_data::packet
struct packet_ruleset_choices * packet
Definition gamehand.c:1107
nation_type
Definition nation.h:98
nation_type::init_units
struct unit_type * init_units[MAX_NUM_UNIT_LIST]
Definition nation.h:125
packet_game_info::fragment_count
int fragment_count
Definition packets_gen.h:252
packet_game_info::turn
int turn
Definition packets_gen.h:247
packet_game_info::year
int year
Definition packets_gen.h:249
packet_game_info::timeout
int timeout
Definition packets_gen.h:239
packet_new_year
Definition packets_gen.h:899
packet_new_year::year
int year
Definition packets_gen.h:900
packet_ruleset_choices
Definition packets_gen.h:1507
packet_ruleset_choices::ruleset_count
int ruleset_count
Definition packets_gen.h:1508
packet_ruleset_choices::rulesets
char rulesets[MAX_NUM_RULESETS][MAX_RULESET_NAME_LENGTH]
Definition packets_gen.h:1509
packet_ruleset_select
Definition packets_gen.h:1512
packet_ruleset_select::modpack
char modpack[MAX_RULESET_NAME_LENGTH]
Definition packets_gen.h:1513
packet_single_want_hack_req
Definition packets_gen.h:1499
packet_single_want_hack_req::token
char token[MAX_LEN_NAME]
Definition packets_gen.h:1500
packet_timeout_info
Definition packets_gen.h:268
packet_timeout_info::seconds_to_phasedone
float seconds_to_phasedone
Definition packets_gen.h:269
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:40
team_placement_config
Definition gamehand.c:67
team_placement_config::total_startpos_num
int total_startpos_num
Definition gamehand.c:71
team_placement_config::startpos
struct tile ** startpos
Definition gamehand.c:68
team_placement_config::flexible_startpos_num
int flexible_startpos_num
Definition gamehand.c:69
team_placement_config::usable_startpos_num
int usable_startpos_num
Definition gamehand.c:70
team_placement_state
Definition gamehand.c:74
team_placement_state::score
long score
Definition gamehand.c:76
team_placement_state::startpos
int * startpos
Definition gamehand.c:75
team
Definition team.c:40
tile
Definition tile.h:50
unit_type
Definition unittype.h:507
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:960
fc_strlcpy
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:777
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:87
teams_iterate
#define teams_iterate(_pteam)
Definition team.h:82
is_ocean_tile
#define is_ocean_tile(ptile)
Definition terrain.h:196
tile_extra_rm_apply
bool tile_extra_rm_apply(struct tile *ptile, struct extra_type *tgt)
Definition tile.c:601
tile_index
#define tile_index(_pt_)
Definition tile.h:89
TILE_XY
#define TILE_XY(ptile)
Definition tile.h:43
tile_continent
#define tile_continent(_tile)
Definition tile.h:93
tile_has_extra
#define tile_has_extra(ptile, pextra)
Definition tile.h:148
timer_read_seconds
double timer_read_seconds(struct timer *t)
Definition timing.c:384
is_non_allied_unit_tile
static bool is_non_allied_unit_tile(const struct tile *ptile, const struct player *pplayer, bool everyone_non_allied)
Definition unit.h:433
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:1605
unittools.h
first_role_unit_for_player
struct unit_type * first_role_unit_for_player(const struct player *pplayer, int role)
Definition unittype.c:2322
get_role_unit
struct unit_type * get_role_unit(int role, int role_index)
Definition unittype.c:2253
num_role_units
int num_role_units(int role)
Definition unittype.c:2203
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:1927
utype_has_flag
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:624
MAP_NATIVE_WIDTH
#define MAP_NATIVE_WIDTH
Definition world_object.h:55
MAP_INDEX_SIZE
#define MAP_INDEX_SIZE
Definition world_object.h:52
MAP_IS_ISOMETRIC
#define MAP_IS_ISOMETRIC
Definition world_object.h:46
MAP_NATIVE_HEIGHT
#define MAP_NATIVE_HEIGHT
Definition world_object.h:56