Some miscellaneous updates to main help, for new features and otherwise.
[freeciv.git] / server / gamehand.c
blob6ea0fcacd0826a5cc6cf96b20fc634c17a6ecfcf
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.
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 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 #include <stdio.h> /* for remove() */
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"
31 /* common */
32 #include "ai.h"
33 #include "events.h"
34 #include "game.h"
35 #include "improvement.h"
36 #include "movement.h"
37 #include "packets.h"
39 /* server */
40 #include "citytools.h"
41 #include "connecthand.h"
42 #include "ggzserver.h"
43 #include "maphand.h"
44 #include "notify.h"
45 #include "plrhand.h"
46 #include "srv_main.h"
47 #include "unittools.h"
49 /* server/advisors */
50 #include "advdata.h"
52 #include "gamehand.h"
54 #define CHALLENGE_ROOT "challenge"
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
65 /****************************************************************************
66 Get unit_type for given role character
67 ****************************************************************************/
68 struct unit_type *crole_to_unit_type(char crole,struct player *pplayer)
70 struct unit_type *utype = NULL;
71 enum unit_role_id role;
73 switch(crole) {
74 case 'c':
75 role = L_CITIES;
76 break;
77 case 'w':
78 role = L_SETTLERS;
79 break;
80 case 'x':
81 role = L_EXPLORER;
82 break;
83 case 'k':
84 role = L_GAMELOSS;
85 break;
86 case 's':
87 role = L_DIPLOMAT;
88 break;
89 case 'f':
90 role = L_FERRYBOAT;
91 break;
92 case 'd':
93 role = L_DEFEND_OK;
94 break;
95 case 'D':
96 role = L_DEFEND_GOOD;
97 break;
98 case 'a':
99 role = L_ATTACK_FAST;
100 break;
101 case 'A':
102 role = L_ATTACK_STRONG;
103 break;
104 default:
105 fc_assert_ret_val(FALSE, NULL);
106 return NULL;
109 /* Create the unit of an appropriate type, if it exists */
110 if (num_role_units(role) > 0) {
111 if (pplayer != NULL) {
112 utype = first_role_unit_for_player(pplayer, role);
114 if (utype == NULL) {
115 utype = get_role_unit(role, 0);
119 return utype;
122 /****************************************************************************
123 Place a starting unit for the player. Returns tile where unit was really
124 placed.
125 ****************************************************************************/
126 static struct tile *place_starting_unit(struct tile *starttile,
127 struct player *pplayer,
128 char crole)
130 struct tile *ptile = NULL;
131 struct unit_type *utype = crole_to_unit_type(crole, pplayer);
133 if (utype != NULL) {
134 iterate_outward(starttile, map.xsize + map.ysize, itertile) {
135 if (!is_non_allied_unit_tile(itertile, pplayer)
136 && is_native_tile(utype, itertile)) {
137 ptile = itertile;
138 break;
140 } iterate_outward_end;
143 if (ptile == NULL) {
144 /* No place where unit may exist. */
145 return NULL;
148 fc_assert_ret_val(!is_non_allied_unit_tile(ptile, pplayer), NULL);
150 /* For scenarios or dispersion, huts may coincide with player starts (in
151 * other cases, huts are avoided as start positions). Remove any such hut,
152 * and make sure to tell the client, since we may have already sent this
153 * tile (with the hut) earlier: */
154 if (tile_has_special(ptile, S_HUT)) {
155 tile_clear_special(ptile, S_HUT);
156 update_tile_knowledge(ptile);
157 log_verbose("Removed hut on start position for %s",
158 player_name(pplayer));
161 /* Expose visible area. */
162 map_show_circle(pplayer, ptile, game.server.init_vis_radius_sq);
164 if (utype != NULL) {
165 /* We cannot currently handle sea units as start units.
166 * TODO: remove this code block when we can. */
167 if (utype_move_type(utype) == UMT_SEA) {
168 log_error("Sea moving start units are not yet supported, "
169 "%s not created.",
170 utype_rule_name(utype));
171 notify_player(pplayer, NULL, E_BAD_COMMAND, ftc_server,
172 _("Sea moving start units are not yet supported. "
173 "Nobody gets %s."),
174 utype_name_translation(utype));
175 return NULL;
178 (void) create_unit(pplayer, ptile, utype, FALSE, 0, 0);
179 return ptile;
182 return NULL;
185 /****************************************************************************
186 Find a valid position not far from our starting position.
187 ****************************************************************************/
188 static struct tile *find_dispersed_position(struct player *pplayer,
189 struct tile *pcenter)
191 struct tile *ptile;
192 int x, y;
194 do {
195 index_to_map_pos(&x, &y, tile_index(pcenter));
196 x += fc_rand(2 * game.server.dispersion + 1) - game.server.dispersion;
197 y += fc_rand(2 * game.server.dispersion + 1) - game.server.dispersion;
198 } while (!((ptile = map_pos_to_tile(x, y))
199 && tile_continent(pcenter) == tile_continent(ptile)
200 && !is_ocean_tile(ptile)
201 && !is_non_allied_unit_tile(ptile, pplayer)));
203 return ptile;
206 /****************************************************************************
207 Initialize a new game: place the players' units onto the map, etc.
208 ****************************************************************************/
209 void init_new_game(void)
211 struct startpos_list *impossible_list, *targeted_list, *flexible_list;
212 struct tile *player_startpos[player_slot_count()];
213 int placed_units[player_slot_count()];
214 int players_to_place = player_count();
216 randomize_base64url_string(server.game_identifier,
217 sizeof(server.game_identifier));
219 /* Assign players to starting positions on the map.
220 * (In scenarios with restrictions on which nations can use which predefined
221 * start positions, this process tries to satisfy those restrictions, but
222 * does not guarantee to. Even if there is a solution to the matching
223 * problem, this algorithm may not find it.) */
225 fc_assert(player_count() <= map_startpos_count());
227 /* Convert the startposition hash table in a linked lists, as we mostly
228 * need now to iterate it now. And then, we will be able to remove the
229 * assigned start postions one by one. */
230 impossible_list = startpos_list_new();
231 targeted_list = startpos_list_new();
232 flexible_list = startpos_list_new();
234 map_startpos_iterate(psp) {
235 if (startpos_allows_all(psp)) {
236 startpos_list_append(flexible_list, psp);
237 } else {
238 startpos_list_append(targeted_list, psp);
240 } map_startpos_iterate_end;
242 fc_assert(startpos_list_size(targeted_list)
243 + startpos_list_size(flexible_list) == map_startpos_count());
245 memset(player_startpos, 0, sizeof(player_startpos));
246 log_verbose("Placing players at start positions.");
248 /* First assign start positions which have restrictions on which nations
249 * can use them. */
250 if (0 < startpos_list_size(targeted_list)) {
251 log_verbose("Assigning matching nations.");
253 startpos_list_shuffle(targeted_list); /* Randomize. */
254 do {
255 struct nation_type *pnation;
256 struct startpos_list_link *choice;
257 bool removed = FALSE;
259 /* Assign first players which can pick only one start position. */
260 players_iterate(pplayer) {
261 if (NULL != player_startpos[player_index(pplayer)]) {
262 /* Already assigned. */
263 continue;
266 pnation = nation_of_player(pplayer);
267 choice = NULL;
268 startpos_list_iterate(targeted_list, plink, psp) {
269 if (startpos_nation_allowed(psp, pnation)) {
270 if (NULL != choice) {
271 choice = NULL;
272 break; /* Many choices. */
273 } else {
274 choice = plink;
277 } startpos_list_iterate_end;
279 if (NULL != choice) {
280 /* Assign this start position to this player and remove
281 * both from consideration. */
282 struct tile *ptile =
283 startpos_tile(startpos_list_link_data(choice));
285 player_startpos[player_index(pplayer)] = ptile;
286 startpos_list_erase(targeted_list, choice);
287 players_to_place--;
288 removed = TRUE;
289 log_verbose("Start position (%d, %d) exactly matches player %s (%s).",
290 TILE_XY(ptile), player_name(pplayer),
291 nation_rule_name(pnation));
293 } players_iterate_end;
295 if (!removed) {
296 /* Didn't find any 1:1 matches. For the next restricted start
297 * position, assign a random matching player. (This may create
298 * restrictions such that more 1:1 matches are possible.) */
299 struct startpos *psp = startpos_list_back(targeted_list);
300 struct tile *ptile = startpos_tile(psp);
301 struct player *rand_plr = NULL;
302 int i = 0;
304 startpos_list_pop_back(targeted_list); /* Detach 'psp'. */
305 players_iterate(pplayer) {
306 if (NULL != player_startpos[player_index(pplayer)]) {
307 /* Already assigned. */
308 continue;
311 pnation = nation_of_player(pplayer);
312 if (startpos_nation_allowed(psp, pnation) && 0 == fc_rand(++i)) {
313 rand_plr = pplayer;
315 } players_iterate_end;
317 if (NULL != rand_plr) {
318 player_startpos[player_index(rand_plr)] = ptile;
319 players_to_place--;
320 log_verbose("Start position (%d, %d) matches player %s (%s).",
321 TILE_XY(ptile), player_name(rand_plr),
322 nation_rule_name(nation_of_player(rand_plr)));
323 } else {
324 /* This start position cannot be assigned, given the assignments
325 * made so far. We may have to fall back to mismatched
326 * assignments. */
327 log_verbose("Start position (%d, %d) cannot be assigned for "
328 "any player, keeping for the moment...",
329 TILE_XY(ptile));
330 /* Keep it for later, we may need it. */
331 startpos_list_append(impossible_list, psp);
334 } while (0 < players_to_place && 0 < startpos_list_size(targeted_list));
337 /* Now assign unrestricted start positions to any remaining players. */
338 if (0 < players_to_place && 0 < startpos_list_size(flexible_list)) {
339 struct tile *ptile;
341 log_verbose("Assigning unrestricted start positions.");
343 startpos_list_shuffle(flexible_list); /* Randomize. */
344 players_iterate(pplayer) {
345 if (NULL != player_startpos[player_index(pplayer)]) {
346 /* Already assigned. */
347 continue;
350 ptile = startpos_tile(startpos_list_front(flexible_list));
351 player_startpos[player_index(pplayer)] = ptile;
352 players_to_place--;
353 startpos_list_pop_front(flexible_list);
354 log_verbose("Start position (%d, %d) assigned randomly "
355 "to player %s (%s).", TILE_XY(ptile), player_name(pplayer),
356 nation_rule_name(nation_of_player(pplayer)));
357 if (0 == startpos_list_size(flexible_list)) {
358 break;
360 } players_iterate_end;
363 if (0 < players_to_place && 0 < startpos_list_size(impossible_list)) {
364 /* We still have players to place, and we have some restricted start
365 * positions whose nation requirements can't be satisfied given existing
366 * assignments. Fall back to making assignments ignoring the positions'
367 * nation requirements. */
369 struct tile *ptile;
371 log_verbose("Ignoring nation restrictions on remaining start positions.");
373 startpos_list_shuffle(impossible_list); /* Randomize. */
374 players_iterate(pplayer) {
375 if (NULL != player_startpos[player_index(pplayer)]) {
376 /* Already assigned. */
377 continue;
380 ptile = startpos_tile(startpos_list_front(impossible_list));
381 player_startpos[player_index(pplayer)] = ptile;
382 players_to_place--;
383 startpos_list_pop_front(impossible_list);
384 log_verbose("Start position (%d, %d) assigned to mismatched "
385 "player %s (%s).", TILE_XY(ptile), player_name(pplayer),
386 nation_rule_name(nation_of_player(pplayer)));
387 if (0 == startpos_list_size(impossible_list)) {
388 break;
390 } players_iterate_end;
393 fc_assert(0 == players_to_place);
395 startpos_list_destroy(impossible_list);
396 startpos_list_destroy(targeted_list);
397 startpos_list_destroy(flexible_list);
400 /* Loop over all players, creating their initial units... */
401 players_iterate(pplayer) {
402 /* We have to initialise the advisor and ai here as we could make contact
403 * to other nations at this point. */
404 adv_data_phase_init(pplayer, FALSE);
405 CALL_PLR_AI_FUNC(phase_begin, pplayer, pplayer, FALSE);
407 struct tile *ptile = player_startpos[player_index(pplayer)];
409 fc_assert_action(NULL != ptile, continue);
411 /* Place first city */
412 if (game.server.start_city) {
413 create_city(pplayer, ptile, city_name_suggestion(pplayer, ptile),
414 NULL);
417 /* Place the first unit. */
418 if (place_starting_unit(ptile, pplayer,
419 game.server.start_units[0]) != NULL) {
420 placed_units[player_index(pplayer)] = 1;
421 } else {
422 placed_units[player_index(pplayer)] = 0;
424 } players_iterate_end;
426 /* Place all other units. */
427 players_iterate(pplayer) {
428 int i;
429 struct tile *const ptile = player_startpos[player_index(pplayer)];
430 struct nation_type *nation = nation_of_player(pplayer);
432 fc_assert_action(NULL != ptile, continue);
434 /* Place global start units */
435 for (i = 1; i < strlen(game.server.start_units); i++) {
436 struct tile *rand_tile = find_dispersed_position(pplayer, ptile);
438 /* Create the unit of an appropriate type. */
439 if (place_starting_unit(rand_tile, pplayer,
440 game.server.start_units[i]) != NULL) {
441 placed_units[player_index(pplayer)]++;
445 /* Place nation specific start units (not role based!) */
446 i = 0;
447 while (NULL != nation->init_units[i] && MAX_NUM_UNIT_LIST > i) {
448 struct tile *rand_tile = find_dispersed_position(pplayer, ptile);
450 create_unit(pplayer, rand_tile, nation->init_units[i], FALSE, 0, 0);
451 placed_units[player_index(pplayer)]++;
452 i++;
454 } players_iterate_end;
456 players_iterate(pplayer) {
457 /* Close the active phase for advisor and ai for all players; it was
458 * opened in the first loop above. */
459 adv_data_phase_done(pplayer);
460 CALL_PLR_AI_FUNC(phase_finished, pplayer, pplayer);
462 fc_assert_msg(0 < placed_units[player_index(pplayer)],
463 _("No units placed for %s!"), player_name(pplayer));
464 } players_iterate_end;
466 shuffle_players();
469 /**************************************************************************
470 Tell clients the year, and also update turn_done and nturns_idle fields
471 for all players.
472 **************************************************************************/
473 void send_year_to_clients(int year)
475 struct packet_new_year apacket;
477 players_iterate(pplayer) {
478 pplayer->nturns_idle++;
479 } players_iterate_end;
481 apacket.year = year;
482 apacket.turn = game.info.turn;
483 lsend_packet_new_year(game.est_connections, &apacket);
485 /* Hmm, clients could add this themselves based on above packet? */
486 notify_conn(game.est_connections, NULL, E_NEXT_YEAR, ftc_any,
487 _("Year: %s"), textyear(year));
490 /**************************************************************************
491 Send game_info packet; some server options and various stuff...
492 dest==NULL means game.est_connections
494 It may be sent at any time. It MUST be sent before any player info,
495 as it contains the number of players. To avoid inconsistency, it
496 SHOULD be sent after rulesets and any other server settings.
497 **************************************************************************/
498 void send_game_info(struct conn_list *dest)
500 struct packet_game_info ginfo;
502 if (!dest) {
503 dest = game.est_connections;
506 ginfo = game.info;
508 /* the following values are computed every
509 time a packet_game_info packet is created */
511 /* Sometimes this function is called before the phase_timer is
512 * initialized. In that case we want to send the dummy value. */
513 if (game.info.timeout > 0 && game.server.phase_timer) {
514 /* Whenever the client sees this packet, it starts a new timer at 0;
515 * but the server's timer is only ever reset at the start of a phase
516 * (and game.info.seconds_to_phasedone is relative to this).
517 * Account for the difference. */
518 ginfo.seconds_to_phasedone = game.info.seconds_to_phasedone
519 - timer_read_seconds(game.server.phase_timer);
520 } else {
521 /* unused but at least initialized */
522 ginfo.seconds_to_phasedone = -1.0;
525 conn_list_iterate(dest, pconn) {
526 send_packet_game_info(pconn, &ginfo);
528 conn_list_iterate_end;
531 /**************************************************************************
532 Send current scenario info. dest NULL causes send to everyone
533 **************************************************************************/
534 void send_scenario_info(struct conn_list *dest)
536 struct packet_scenario_info sinfo;
538 if (!dest) {
539 dest = game.est_connections;
542 sinfo = game.scenario;
544 conn_list_iterate(dest, pconn) {
545 send_packet_scenario_info(pconn, &sinfo);
546 } conn_list_iterate_end;
549 /**************************************************************************
550 adjusts game.info.timeout based on various server options
552 timeoutint: adjust game.info.timeout every timeoutint turns
553 timeoutinc: adjust game.info.timeout by adding timeoutinc to it.
554 timeoutintinc: every time we adjust game.info.timeout, we add timeoutintinc
555 to timeoutint.
556 timeoutincmult: every time we adjust game.info.timeout, we multiply timeoutinc
557 by timeoutincmult
558 **************************************************************************/
559 int update_timeout(void)
561 /* if there's no timer or we're doing autogame, do nothing */
562 if (game.info.timeout < 1 || game.server.timeoutint == 0) {
563 return game.info.timeout;
566 if (game.server.timeoutcounter >= game.server.timeoutint) {
567 game.info.timeout += game.server.timeoutinc;
568 game.server.timeoutinc *= game.server.timeoutincmult;
570 game.server.timeoutcounter = 1;
571 game.server.timeoutint += game.server.timeoutintinc;
573 if (game.info.timeout > GAME_MAX_TIMEOUT) {
574 notify_conn(game.est_connections, NULL, E_SETTING, ftc_server,
575 _("The turn timeout has exceeded its maximum value, "
576 "fixing at its maximum."));
577 log_debug("game.info.timeout exceeded maximum value");
578 game.info.timeout = GAME_MAX_TIMEOUT;
579 game.server.timeoutint = 0;
580 game.server.timeoutinc = 0;
581 } else if (game.info.timeout < 0) {
582 notify_conn(game.est_connections, NULL, E_SETTING, ftc_server,
583 _("The turn timeout is smaller than zero, "
584 "fixing at zero."));
585 log_debug("game.info.timeout less than zero");
586 game.info.timeout = 0;
588 } else {
589 game.server.timeoutcounter++;
592 log_debug("timeout=%d, inc=%d incmult=%d\n "
593 "int=%d, intinc=%d, turns till next=%d",
594 game.info.timeout, game.server.timeoutinc,
595 game.server.timeoutincmult, game.server.timeoutint,
596 game.server.timeoutintinc,
597 game.server.timeoutint - game.server.timeoutcounter);
599 return game.info.timeout;
602 /**************************************************************************
603 adjusts game.seconds_to_turn_done when enemy moves a unit, we see it and
604 the remaining timeout is smaller than the timeoutaddenemymove option.
606 It's possible to use a similar function to do that per-player. In
607 theory there should be a separate timeout for each player and the
608 added time should only go onto the victim's timer.
609 **************************************************************************/
610 void increase_timeout_because_unit_moved(void)
612 if (game.info.timeout > 0 && game.server.timeoutaddenemymove > 0) {
613 double maxsec = (timer_read_seconds(game.server.phase_timer)
614 + (double) game.server.timeoutaddenemymove);
616 if (maxsec > game.info.seconds_to_phasedone) {
617 game.info.seconds_to_phasedone = maxsec;
618 send_game_info(NULL);
623 /**************************************************************************
624 generate challenge filename for this connection, cannot fail.
625 **************************************************************************/
626 static void gen_challenge_filename(struct connection *pc)
630 /**************************************************************************
631 get challenge filename for this connection.
632 **************************************************************************/
633 static const char *get_challenge_filename(struct connection *pc)
635 static char filename[MAX_LEN_PATH];
637 fc_snprintf(filename, sizeof(filename), "%s_%d_%d",
638 CHALLENGE_ROOT, srvarg.port, pc->id);
640 return filename;
643 /**************************************************************************
644 get challenge full filename for this connection.
645 **************************************************************************/
646 static const char *get_challenge_fullname(struct connection *pc)
648 static char fullname[MAX_LEN_PATH];
650 interpret_tilde(fullname, sizeof(fullname), "~/.freeciv/");
651 sz_strlcat(fullname, get_challenge_filename(pc));
653 return fullname;
656 /**************************************************************************
657 find a file that we can write too, and return it's name.
658 **************************************************************************/
659 const char *new_challenge_filename(struct connection *pc)
661 gen_challenge_filename(pc);
662 return get_challenge_filename(pc);
666 /**************************************************************************
667 Call this on a connection with HACK access to send it a set of ruleset
668 choices. Probably this should be called immediately when granting
669 HACK access to a connection.
670 **************************************************************************/
671 static void send_ruleset_choices(struct connection *pc)
673 struct packet_ruleset_choices packet;
674 static struct strvec *rulesets = NULL;
675 size_t i;
677 if (!rulesets) {
678 /* This is only read once per server invocation. Add a new ruleset
679 * and you have to restart the server. */
680 rulesets = fileinfolist(get_data_dirs(), RULESET_SUFFIX);
683 packet.ruleset_count = MIN(MAX_NUM_RULESETS, strvec_size(rulesets));
684 for (i = 0; i < packet.ruleset_count; i++) {
685 sz_strlcpy(packet.rulesets[i], strvec_get(rulesets, i));
688 send_packet_ruleset_choices(pc, &packet);
692 /****************************************************************************
693 Opens a file specified by the packet and compares the packet values with
694 the file values. Sends an answer to the client once it's done.
695 ****************************************************************************/
696 void handle_single_want_hack_req(struct connection *pc,
697 const struct packet_single_want_hack_req *
698 packet)
700 struct section_file *secfile;
701 const char *token = NULL;
702 bool you_have_hack = FALSE;
704 if (!with_ggz) {
705 if ((secfile = secfile_load(get_challenge_fullname(pc), FALSE))) {
706 token = secfile_lookup_str(secfile, "challenge.token");
707 you_have_hack = (token && strcmp(token, packet->token) == 0);
708 secfile_destroy(secfile);
709 } else {
710 log_debug("Error reading '%s':\n%s", get_challenge_fullname(pc),
711 secfile_error());
714 if (!token) {
715 log_debug("Failed to read authentication token");
719 if (you_have_hack) {
720 conn_set_access(pc, ALLOW_HACK, TRUE);
723 dsend_packet_single_want_hack_reply(pc, you_have_hack);
725 send_ruleset_choices(pc);
726 send_conn_info(pc->self, NULL);