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)
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 ***********************************************************************/
15 #include <fc_config.h>
32 #include "connection.h"
34 #include "government.h"
41 #include "spaceship.h"
42 #include "specialist.h"
45 #include "traderoutes.h"
77 bool am_i_server
= FALSE
;
79 static void game_defaults(void);
81 /**************************************************************************
82 Is program type server?
83 **************************************************************************/
89 /**************************************************************************
90 Set program type to server.
91 **************************************************************************/
92 void i_am_server(void)
97 /**************************************************************************
98 Set program type to client.
99 **************************************************************************/
100 void i_am_client(void)
105 /**************************************************************************
106 Count the # of thousand citizen in a civilisation.
107 **************************************************************************/
108 int civ_population(const struct player
*pplayer
)
111 city_list_iterate(pplayer
->cities
, pcity
)
112 ppl
+=city_population(pcity
);
113 city_list_iterate_end
;
118 /**************************************************************************
119 Find city with given name from any player.
120 **************************************************************************/
121 struct city
*game_city_by_name(const char *name
)
123 players_iterate(pplayer
) {
124 struct city
*pcity
= city_list_find_name(pplayer
->cities
, name
);
129 } players_iterate_end
;
135 /**************************************************************************
136 Often used function to get a city pointer from a city ID.
137 City may be any city in the game. This now always uses fast idex
138 method, instead of looking through all cities of all players.
139 **************************************************************************/
140 struct city
*game_city_by_number(int id
)
142 return idex_lookup_city(id
);
146 /**************************************************************************
147 Find unit out of all units in game: now uses fast idex method,
148 instead of looking through all units of all players.
149 **************************************************************************/
150 struct unit
*game_unit_by_number(int id
)
152 return idex_lookup_unit(id
);
155 /**************************************************************************
156 In the server call wipe_unit(), and never this function directly.
157 **************************************************************************/
158 void game_remove_unit(struct unit
*punit
)
162 /* It's possible that during city transfer homecity/unit owner
163 * information is inconsistent, and client then tries to remove
164 * now unseen unit so that homecity is not in the list of cities
165 * of the player (seemingly) owning the unit.
166 * Thus cannot use player_city_by_number() here, but have to
167 * consider cities of all players. */
168 pcity
= game_city_by_number(punit
->homecity
);
170 unit_list_remove(pcity
->units_supported
, punit
);
172 log_debug("game_remove_unit()"
173 " at (%d,%d) unit %d, %s %s home (%d,%d) city %d, %s %s",
174 TILE_XY(unit_tile(punit
)),
176 nation_rule_name(nation_of_unit(punit
)),
177 unit_rule_name(punit
),
178 TILE_XY(pcity
->tile
),
180 nation_rule_name(nation_of_city(pcity
)),
182 } else if (IDENTITY_NUMBER_ZERO
== punit
->homecity
) {
183 log_debug("game_remove_unit() at (%d,%d) unit %d, %s %s home %d",
184 TILE_XY(unit_tile(punit
)),
186 nation_rule_name(nation_of_unit(punit
)),
187 unit_rule_name(punit
),
190 log_error("game_remove_unit() at (%d,%d) unit %d, %s %s home %d invalid",
191 TILE_XY(unit_tile(punit
)),
193 nation_rule_name(nation_of_unit(punit
)),
194 unit_rule_name(punit
),
198 unit_list_remove(unit_tile(punit
)->units
, punit
);
199 unit_list_remove(unit_owner(punit
)->units
, punit
);
201 idex_unregister_unit(punit
);
203 if (game
.callbacks
.unit_deallocate
) {
204 (game
.callbacks
.unit_deallocate
)(punit
->id
);
206 unit_virtual_destroy(punit
);
209 /**************************************************************************
210 Remove city from game.
211 **************************************************************************/
212 void game_remove_city(struct city
*pcity
)
214 struct tile
*pcenter
= city_tile(pcity
);
215 struct player
*powner
= city_owner(pcity
);
217 if (NULL
!= powner
) {
218 /* always unlink before clearing data */
219 city_list_remove(powner
->cities
, pcity
);
222 if (NULL
== pcenter
) {
223 log_debug("game_remove_city() virtual city %d, %s",
227 log_debug("game_remove_city() at (%d,%d) city %d, %s %s",
230 nation_rule_name(nation_of_player(powner
)),
233 city_tile_iterate(city_map_radius_sq_get(pcity
), pcenter
, ptile
) {
234 if (tile_worked(ptile
) == pcity
) {
235 tile_set_worked(ptile
, NULL
);
237 } city_tile_iterate_end
;
240 idex_unregister_city(pcity
);
241 destroy_city_virtual(pcity
);
244 /****************************************************************************
245 Set default game values.
246 ****************************************************************************/
247 static void game_defaults(void)
251 /* The control packet. */
252 game
.control
.government_count
= 0;
253 game
.control
.nation_count
= 0;
254 game
.control
.num_base_types
= 0;
255 game
.control
.num_road_types
= 0;
256 game
.control
.num_impr_types
= 0;
257 game
.control
.num_specialist_types
= 0;
258 game
.control
.num_tech_types
= 0;
259 game
.control
.num_unit_classes
= 0;
260 game
.control
.num_unit_types
= 0;
261 game
.control
.num_disaster_types
= 0;
262 game
.control
.prefered_tileset
[0] = '\0';
263 game
.control
.resource_count
= 0;
264 game
.control
.styles_count
= 0;
265 game
.control
.terrain_count
= 0;
267 /* The info packet. */
268 game
.info
.aifill
= GAME_DEFAULT_AIFILL
;
269 game
.info
.airlifting_style
= GAME_DEFAULT_AIRLIFTINGSTYLE
;
270 game
.info
.angrycitizen
= GAME_DEFAULT_ANGRYCITIZEN
;
271 game
.info
.borders
= GAME_DEFAULT_BORDERS
;
272 game
.info
.calendar_skip_0
= FALSE
;
273 game
.info
.celebratesize
= GAME_DEFAULT_CELEBRATESIZE
;
274 game
.info
.citymindist
= GAME_DEFAULT_CITYMINDIST
;
275 game
.info
.cooling
= 0;
276 game
.info
.coolinglevel
= 0; /* set later */
277 game
.info
.diplomacy
= GAME_DEFAULT_DIPLOMACY
;
278 game
.info
.fogofwar
= GAME_DEFAULT_FOGOFWAR
;
279 game
.info
.foodbox
= GAME_DEFAULT_FOODBOX
;
280 game
.info
.fulltradesize
= GAME_DEFAULT_FULLTRADESIZE
;
281 for (i
= 0; i
< A_LAST
; i
++) {
282 /* game.num_tech_types = 0 here */
283 game
.info
.global_advances
[i
] = FALSE
;
285 for (i
= 0; i
< B_LAST
; i
++) {
286 /* game.num_impr_types = 0 here */
287 game
.info
.great_wonder_owners
[i
] = WONDER_NOT_OWNED
;
289 game
.info
.globalwarming
= 0;
290 game
.info
.global_warming
= GAME_DEFAULT_GLOBAL_WARMING
;
291 game
.info
.gold
= GAME_DEFAULT_GOLD
;
292 game
.info
.government_during_revolution_id
= G_MAGIC
; /* flag */
293 game
.info
.happyborders
= GAME_DEFAULT_HAPPYBORDERS
;
294 game
.info
.heating
= 0;
295 game
.info
.is_edit_mode
= FALSE
;
296 game
.info
.is_new_game
= TRUE
;
297 game
.info
.killstack
= GAME_DEFAULT_KILLSTACK
;
298 game
.info
.killcitizen
= GAME_DEFAULT_KILLCITIZEN
;
299 game
.info
.negative_year_label
[0] = '\0';
300 game
.info
.notradesize
= GAME_DEFAULT_NOTRADESIZE
;
301 game
.info
.nuclearwinter
= 0;
302 game
.info
.nuclear_winter
= GAME_DEFAULT_NUCLEAR_WINTER
;
303 game
.info
.positive_year_label
[0] = '\0';
304 game
.info
.rapturedelay
= GAME_DEFAULT_RAPTUREDELAY
;
305 game
.info
.restrictinfra
= GAME_DEFAULT_RESTRICTINFRA
;
306 game
.info
.sciencebox
= GAME_DEFAULT_SCIENCEBOX
;
307 game
.info
.shieldbox
= GAME_DEFAULT_SHIELDBOX
;
308 game
.info
.skill_level
= GAME_DEFAULT_SKILL_LEVEL
;
309 game
.info
.slow_invasions
= RS_DEFAULT_SLOW_INVASIONS
;
310 game
.info
.spacerace
= GAME_DEFAULT_SPACERACE
;
311 game
.info
.team_pooled_research
= GAME_DEFAULT_TEAM_POOLED_RESEARCH
;
312 game
.info
.tech
= GAME_DEFAULT_TECHLEVEL
;
313 game
.info
.timeout
= GAME_DEFAULT_TIMEOUT
;
314 game
.info
.trademindist
= GAME_DEFAULT_TRADEMINDIST
;
315 game
.info
.trading_city
= GAME_DEFAULT_TRADING_CITY
;
316 game
.info
.trading_gold
= GAME_DEFAULT_TRADING_GOLD
;
317 game
.info
.trading_tech
= GAME_DEFAULT_TRADING_TECH
;
319 game
.info
.warminglevel
= 0; /* set later */
320 game
.info
.year_0_hack
= FALSE
;
321 game
.info
.year
= GAME_START_YEAR
;
323 /* The scenario packet. */
324 game
.scenario
.description
[0] = '\0';
325 game
.scenario
.is_scenario
= FALSE
;
326 game
.scenario
.name
[0] = '\0';
327 game
.scenario
.players
= TRUE
;
328 game
.scenario
.startpos_nations
= FALSE
;
330 /* Veteran system. */
334 game
.plr_bg_color
= NULL
;
337 /* All settings only used by the server (./server/ and ./ai/ */
338 sz_strlcpy(game
.server
.allow_take
, GAME_DEFAULT_ALLOW_TAKE
);
339 game
.server
.allied_victory
= GAME_DEFAULT_ALLIED_VICTORY
;
340 game
.server
.allowed_city_names
= GAME_DEFAULT_ALLOWED_CITY_NAMES
;
341 game
.server
.aqueductloss
= GAME_DEFAULT_AQUEDUCTLOSS
;
342 game
.server
.auto_ai_toggle
= GAME_DEFAULT_AUTO_AI_TOGGLE
;
343 game
.server
.autoattack
= GAME_DEFAULT_AUTOATTACK
;
344 game
.server
.barbarianrate
= GAME_DEFAULT_BARBARIANRATE
;
345 game
.server
.civilwarsize
= GAME_DEFAULT_CIVILWARSIZE
;
346 game
.server
.connectmsg
[0] = '\0';
347 game
.server
.conquercost
= GAME_DEFAULT_CONQUERCOST
;
348 game
.server
.contactturns
= GAME_DEFAULT_CONTACTTURNS
;
349 for (i
= 0; i
< DEBUG_LAST
; i
++) {
350 game
.server
.debug
[i
] = FALSE
;
352 sz_strlcpy(game
.server
.demography
, GAME_DEFAULT_DEMOGRAPHY
);
353 game
.server
.diplchance
= GAME_DEFAULT_DIPLCHANCE
;
354 game
.server
.diplcost
= GAME_DEFAULT_DIPLCOST
;
355 game
.server
.dispersion
= GAME_DEFAULT_DISPERSION
;
356 game
.server
.endspaceship
= GAME_DEFAULT_END_SPACESHIP
;
357 game
.server
.end_turn
= GAME_DEFAULT_END_TURN
;
358 game
.server
.event_cache
.chat
= GAME_DEFAULT_EVENT_CACHE_CHAT
;
359 game
.server
.event_cache
.info
= GAME_DEFAULT_EVENT_CACHE_INFO
;
360 game
.server
.event_cache
.max_size
= GAME_DEFAULT_EVENT_CACHE_MAX_SIZE
;
361 game
.server
.event_cache
.turns
= GAME_DEFAULT_EVENT_CACHE_TURNS
;
362 game
.server
.foggedborders
= GAME_DEFAULT_FOGGEDBORDERS
;
363 game
.server
.fogofwar_old
= game
.info
.fogofwar
;
364 game
.server
.freecost
= GAME_DEFAULT_FREECOST
;
365 game
.server
.homecaughtunits
= GAME_DEFAULT_HOMECAUGHTUNITS
;
366 game
.server
.kick_time
= GAME_DEFAULT_KICK_TIME
;
367 game
.server
.killunhomed
= GAME_DEFAULT_KILLUNHOMED
;
368 game
.server
.maxconnectionsperhost
= GAME_DEFAULT_MAXCONNECTIONSPERHOST
;
369 game
.server
.last_ping
= 0;
370 game
.server
.max_players
= GAME_DEFAULT_MAX_PLAYERS
;
371 game
.server
.meta_info
.user_message
[0] = '\0';
372 game
.server
.meta_info
.user_message_set
= FALSE
;
373 game
.server
.mgr_distance
= GAME_DEFAULT_MGR_DISTANCE
;
374 game
.server
.mgr_foodneeded
= GAME_DEFAULT_MGR_FOODNEEDED
;
375 game
.server
.mgr_nationchance
= GAME_DEFAULT_MGR_NATIONCHANCE
;
376 game
.server
.mgr_turninterval
= GAME_DEFAULT_MGR_TURNINTERVAL
;
377 game
.server
.mgr_worldchance
= GAME_DEFAULT_MGR_WORLDCHANCE
;
378 game
.server
.migration
= GAME_DEFAULT_MIGRATION
;
379 game
.server
.min_players
= GAME_DEFAULT_MIN_PLAYERS
;
380 game
.server
.natural_city_names
= GAME_DEFAULT_NATURALCITYNAMES
;
381 game
.server
.plrcolormode
= GAME_DEFAULT_PLRCOLORMODE
;
382 game
.server
.netwait
= GAME_DEFAULT_NETWAIT
;
383 game
.server
.occupychance
= GAME_DEFAULT_OCCUPYCHANCE
;
384 game
.server
.onsetbarbarian
= GAME_DEFAULT_ONSETBARBARIAN
;
385 game
.server
.phase_mode_stored
= GAME_DEFAULT_PHASE_MODE
;
386 game
.server
.pingtime
= GAME_DEFAULT_PINGTIME
;
387 game
.server
.pingtimeout
= GAME_DEFAULT_PINGTIMEOUT
;
388 game
.server
.razechance
= GAME_DEFAULT_RAZECHANCE
;
389 game
.server
.revealmap
= GAME_DEFAULT_REVEALMAP
;
390 game
.server
.revolution_length
= GAME_DEFAULT_REVOLUTION_LENGTH
;
391 sz_strlcpy(game
.server
.rulesetdir
, GAME_DEFAULT_RULESETDIR
);
392 game
.server
.save_compress_level
= GAME_DEFAULT_COMPRESS_LEVEL
;
393 game
.server
.save_compress_type
= GAME_DEFAULT_COMPRESS_TYPE
;
394 sz_strlcpy(game
.server
.save_name
, GAME_DEFAULT_SAVE_NAME
);
395 game
.server
.save_nturns
= GAME_DEFAULT_SAVETURNS
;
396 game
.server
.save_options
.save_known
= TRUE
;
397 game
.server
.save_options
.save_private_map
= TRUE
;
398 game
.server
.save_options
.save_random
= TRUE
;
399 game
.server
.save_options
.save_starts
= TRUE
;
400 game
.server
.savepalace
= GAME_DEFAULT_SAVEPALACE
;
401 game
.server
.scorelog
= GAME_DEFAULT_SCORELOG
;
402 game
.server
.scoreturn
= GAME_DEFAULT_SCORETURN
;
403 game
.server
.seed
= GAME_DEFAULT_SEED
;
404 sz_strlcpy(game
.server
.start_units
, GAME_DEFAULT_START_UNITS
);
405 game
.server
.start_year
= GAME_START_YEAR
;
406 game
.server
.tcptimeout
= GAME_DEFAULT_TCPTIMEOUT
;
407 game
.server
.techlost_donor
= GAME_DEFAULT_TECHLOST_DONOR
;
408 game
.server
.techlost_recv
= GAME_DEFAULT_TECHLOST_RECV
;
409 game
.server
.techpenalty
= GAME_DEFAULT_TECHPENALTY
;
410 game
.server
.timeoutaddenemymove
= GAME_DEFAULT_TIMEOUTADDEMOVE
;
411 game
.server
.timeoutcounter
= GAME_DEFAULT_TIMEOUTCOUNTER
;
412 game
.server
.timeoutinc
= GAME_DEFAULT_TIMEOUTINC
;
413 game
.server
.timeoutincmult
= GAME_DEFAULT_TIMEOUTINCMULT
;
414 game
.server
.timeoutint
= GAME_DEFAULT_TIMEOUTINT
;
415 game
.server
.timeoutintinc
= GAME_DEFAULT_TIMEOUTINTINC
;
416 game
.server
.turnblock
= GAME_DEFAULT_TURNBLOCK
;
417 game
.server
.unitwaittime
= GAME_DEFAULT_UNITWAITTIME
;
418 game
.server
.plr_colors
= NULL
;
422 /****************************************************************************
423 Initialise all game settings.
425 The variables are listed in alphabetical order.
426 ****************************************************************************/
436 player_researches_init();
439 /****************************************************************************
440 Initialize map-specific parts of the game structure. Maybe these should
441 be moved into the map structure?
442 ****************************************************************************/
443 void game_map_init(void)
445 /* FIXME: it's not clear where these values should be initialized. It
446 * can't be done in game_init because the map isn't created yet. Maybe it
447 * should be done in the mapgen code or in the maphand code. It should
448 * surely be called when the map is generated. */
449 game
.info
.warminglevel
= (map_num_tiles() + 499) / 500;
450 game
.info
.coolinglevel
= (map_num_tiles() + 499) / 500;
453 /***************************************************************
454 Frees all memory of the game.
455 ***************************************************************/
466 /***************************************************************
467 Do all changes to change view, and not full
468 game_free()/game_init().
469 ***************************************************************/
470 void game_reset(void)
476 /* Reset the players infos. */
477 players_iterate(pplayer
) {
478 player_clear(pplayer
, FALSE
);
479 } players_iterate_end
;
489 /***************************************************************
490 Initialize the objects which will read from a ruleset.
491 ***************************************************************/
492 void game_ruleset_init(void)
494 nation_sets_groups_init();
495 ruleset_cache_init();
496 disaster_types_init();
497 trade_route_types_init();
506 user_unit_type_flags_init();
507 user_terrain_flags_init();
508 user_tech_flags_init();
511 /***************************************************************
512 Frees all memory which in objects which are read from a ruleset.
513 ***************************************************************/
514 void game_ruleset_free(void)
516 CALL_FUNC_EACH_AI(units_ruleset_close
);
518 /* Clear main structures which can points to the ruleset dependent
520 players_iterate(pplayer
) {
521 player_ruleset_close(pplayer
);
522 } players_iterate_end
;
523 game
.government_during_revolution
= NULL
;
531 unit_type_flags_free();
532 role_unit_precalcs_free();
537 disaster_types_free();
539 user_tech_flags_free();
540 user_terrain_flags_free();
541 ruleset_cache_free();
542 nation_sets_groups_free();
544 /* Destroy the default veteran system. */
545 veteran_system_destroy(game
.veteran
);
549 if (game
.plr_bg_color
!= NULL
) {
550 rgbcolor_destroy(game
.plr_bg_color
);
551 game
.plr_bg_color
= NULL
;
555 /***************************************************************
556 Initialize wonder information.
557 ***************************************************************/
558 void initialize_globals(void)
560 players_iterate(pplayer
) {
561 city_list_iterate(pplayer
->cities
, pcity
) {
562 city_built_iterate(pcity
, pimprove
) {
563 if (is_wonder(pimprove
)) {
564 if (is_great_wonder(pimprove
)) {
565 game
.info
.great_wonder_owners
[improvement_index(pimprove
)] =
566 player_number(pplayer
);
568 pplayer
->wonders
[improvement_index(pimprove
)] = pcity
->id
;
570 } city_built_iterate_end
;
571 } city_list_iterate_end
;
572 } players_iterate_end
;
575 /***************************************************************
576 Returns the next year in the game.
577 ***************************************************************/
578 int game_next_year(int year
)
580 int increase
= get_world_bonus(EFT_TURN_YEARS
);
581 const int slowdown
= (game
.info
.spacerace
582 ? get_world_bonus(EFT_SLOW_DOWN_TIMELINE
) : 0);
584 if (game
.info
.year_0_hack
) {
585 /* hacked it to get rid of year 0 */
587 game
.info
.year_0_hack
= FALSE
;
591 - want year += 1 for spaceship.
594 /* test game with 7 normal AI's, gen 4 map, foodbox 10, foodbase 0:
595 * Gunpowder about 0 AD
596 * Railroad about 500 AD
597 * Electricity about 1000 AD
598 * Refining about 1500 AD (212 active units)
603 /* Note the slowdown operates even if Enable_Space is not active. See
604 * README.effects for specifics. */
609 } else if (slowdown
>= 2) {
613 } else if (slowdown
>= 1) {
621 if (year
== 0 && game
.info
.calendar_skip_0
) {
623 game
.info
.year_0_hack
= TRUE
;
629 /***************************************************************
630 Advance the game year.
631 ***************************************************************/
632 void game_advance_year(void)
634 game
.info
.year
= game_next_year(game
.info
.year
);
638 /**************************************************************************
639 Return TRUE if it is this player's phase.
640 NB: The meaning of the 'phase' argument must match its use in the
641 function begin_turn() in server/srv_main.c.
642 NB: The phase mode PMT_TEAMS_ALTERNATE assumes that every player is
643 on a team, i.e. that pplayer->team is never NULL.
644 **************************************************************************/
645 bool is_player_phase(const struct player
*pplayer
, int phase
)
647 switch (game
.info
.phase_mode
) {
651 case PMT_PLAYERS_ALTERNATE
:
652 return player_number(pplayer
) == phase
;
654 case PMT_TEAMS_ALTERNATE
:
655 fc_assert_ret_val(NULL
!= pplayer
->team
, FALSE
);
656 return team_number(pplayer
->team
) == phase
;
662 fc_assert_msg(FALSE
, "Unrecognized phase mode %d in is_player_phase().",
667 /****************************************************************************
668 Return a prettily formatted string containing the population text. The
669 population is passed in as the number of citizens, in unit
670 (tens/hundreds/thousands...) defined in cities.ruleset.
671 ****************************************************************************/
672 const char *population_to_text(int thousand_citizen
)
674 /* big_int_to_text can't handle negative values, and in any case we'd
675 * better not have a negative population. */
676 fc_assert_ret_val(thousand_citizen
>= 0, NULL
);
677 return big_int_to_text(thousand_citizen
, game
.info
.pop_report_zeroes
- 1);
680 /****************************************************************************
681 Produce a statically allocated textual representation of the given
683 ****************************************************************************/
684 const char *textyear(int year
)
688 /* TRANS: <year> <label> -> "1000 BC" */
689 fc_snprintf(y
, sizeof(y
), _("%d %s"), -year
,
690 game
.info
.negative_year_label
);
692 /* TRANS: <year> <label> -> "1000 AD" */
693 fc_snprintf(y
, sizeof(y
), _("%d %s"), year
,
694 game
.info
.positive_year_label
);
699 /**************************************************************************
700 Return a string conaining the save year.
701 **************************************************************************/
702 static char *year_suffix(void)
704 static char buf
[MAX_LEN_NAME
];
705 const char *year_suffix
;
706 char safe_year_suffix
[MAX_LEN_NAME
];
707 const char *max
= safe_year_suffix
+ MAX_LEN_NAME
- 1;
708 char *c
= safe_year_suffix
;
710 if (game
.info
.year
< 0) {
711 year_suffix
= game
.info
.negative_year_label
;
713 year_suffix
= game
.info
.positive_year_label
;
716 /* Remove all non alphanumeric characters from the year suffix. */
717 for (; '\0' != *year_suffix
&& c
< max
; year_suffix
++) {
718 if (fc_isalnum(*year_suffix
)) {
724 fc_snprintf(buf
, sizeof(buf
), "%s", safe_year_suffix
);
729 /**************************************************************************
730 Generate a default save file name and place it in the provided buffer.
731 Within the name the following custom formats are allowed:
735 %T = <game.info.turn>
736 %Y = <game.info.year>
739 'freeciv-T%04T-Y%+04Y-%R' => 'freeciv-T0099-Y-0050-manual'
740 => 'freeciv-T0100-Y00001-auto'
742 Returns the number of characters written, or the number of characters
743 that would have been written if truncation occurs.
745 NB: If you change the format definition, be sure to update the above
746 function comment and the help text for the 'savename' setting.
747 **************************************************************************/
748 int generate_save_name(const char *format
, char *buf
, int buflen
,
751 struct cf_sequence sequences
[] = {
752 cf_str_seq('R', (reason
== NULL
) ? "auto" : reason
),
753 cf_str_seq('S', year_suffix()),
754 cf_int_seq('T', game
.info
.turn
),
755 cf_int_seq('Y', game
.info
.year
),
759 fc_vsnprintcf(buf
, buflen
, format
, sequences
, -1);
761 if (0 == strcmp(format
, buf
)) {
762 /* Use the default savename if 'format' does not contain
763 * printf information. */
766 fc_snprintf(savename
, sizeof(savename
), "%s-T%%04T-Y%%05Y-%%R",
768 fc_vsnprintcf(buf
, buflen
, savename
, sequences
, -1);
771 log_debug("save name generated from '%s': %s", format
, buf
);
776 /**************************************************************************
777 Initialize user flag.
778 **************************************************************************/
779 void user_flag_init(struct user_flag
*flag
)
782 flag
->helptxt
= NULL
;
785 /**************************************************************************
787 **************************************************************************/
788 void user_flag_free(struct user_flag
*flag
)
790 if (flag
->name
!= NULL
) {
794 if (flag
->helptxt
!= NULL
) {
795 FC_FREE(flag
->helptxt
);
796 flag
->helptxt
= NULL
;