Freeciv-3.4
Loading...
Searching...
No Matches
ruleload.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 <stdarg.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22
23/* utility */
24#include "bitvector.h"
25#include "deprecations.h"
26#include "fcintl.h"
27#include "log.h"
28#include "mem.h"
29#include "registry.h"
30#include "shared.h"
31#include "string_vector.h"
32#include "support.h"
33
34/* common */
35#include "accessarea.h"
36#include "achievements.h"
37#include "actions.h"
38#include "ai.h"
39#include "base.h"
40#include "capability.h"
41#include "city.h"
42#include "counters.h"
43#include "effects.h"
44#include "extras.h"
45#include "fc_types.h"
46#include "featured_text.h"
47#include "game.h"
48#include "government.h"
49#include "map.h"
50#include "movement.h"
51#include "multipliers.h"
52#include "name_translation.h"
53#include "nation.h"
54#include "packets.h"
55#include "player.h"
56#include "requirements.h"
57#include "rgbcolor.h"
58#include "road.h"
59#include "sex.h"
60#include "specialist.h"
61#include "style.h"
62#include "tech.h"
63#include "tiledef.h"
64#include "traderoutes.h"
65#include "unit.h"
66#include "unittype.h"
67
68/* server */
69#include "citytools.h"
70#include "notify.h"
71#include "plrhand.h"
72#include "rscompat.h"
73#include "rssanity.h"
74#include "settings.h"
75#include "srv_main.h"
76
77/* server/advisors */
78#include "advruleset.h"
79
80/* server/scripting */
81#include "script_server.h"
82
83#include "ruleload.h"
84
85/* RULESET_SUFFIX already used, no leading dot here */
86#define RULES_SUFFIX "ruleset"
87#define SCRIPT_SUFFIX "lua"
88
89#define ADVANCE_SECTION_PREFIX "advance_"
90#define TECH_CLASS_SECTION_PREFIX "techclass_"
91#define BUILDING_SECTION_PREFIX "building_"
92#define CITYSTYLE_SECTION_PREFIX "citystyle_"
93#define MUSICSTYLE_SECTION_PREFIX "musicstyle_"
94#define UEFF_SECTION_PREFIX "ueff_"
95#define EFFECT_SECTION_PREFIX "effect_"
96#define GOVERNMENT_SECTION_PREFIX "government_"
97#define NATION_SET_SECTION_PREFIX "nset" /* without underscore? */
98#define NATION_GROUP_SECTION_PREFIX "ngroup" /* without underscore? */
99#define NATION_SECTION_PREFIX "nation" /* without underscore? */
100#define STYLE_SECTION_PREFIX "style_"
101#define CLAUSE_SECTION_PREFIX "clause_"
102#define EXTRA_SECTION_PREFIX "extra_"
103#define BASE_SECTION_PREFIX "base_"
104#define ROAD_SECTION_PREFIX "road_"
105#define RESOURCE_SECTION_PREFIX "resource_"
106#define TILEDEF_SECTION_PREFIX "tiledef_"
107#define GOODS_SECTION_PREFIX "goods_"
108#define SPECIALIST_SECTION_PREFIX "specialist_"
109#define SUPER_SPECIALIST_SECTION_PREFIX "super_specialist_"
110#define TERRAIN_SECTION_PREFIX "terrain_"
111#define UNIT_CLASS_SECTION_PREFIX "unitclass_"
112#define UNIT_SECTION_PREFIX "unit_"
113#define DISASTER_SECTION_PREFIX "disaster_"
114#define ACHIEVEMENT_SECTION_PREFIX "achievement_"
115#define ENABLER_SECTION_PREFIX "enabler_"
116#define ACTION_SECTION_PREFIX "action_"
117#define MULTIPLIER_SECTION_PREFIX "multiplier_"
118#define COUNTER_SECTION_PREFIX "counter_"
119
120#define check_name(name) (check_strlen(name, MAX_LEN_NAME, NULL))
121#define check_cityname(name) (check_strlen(name, MAX_LEN_CITYNAME, NULL))
122
123/* Avoid re-reading files */
124static const char name_too_long[] = "Name \"%s\" too long; truncating.";
125#define MAX_SECTION_LABEL 64
126#define section_strlcpy(dst, src) \
127 (void) loud_strlcpy(dst, src, MAX_SECTION_LABEL, name_too_long)
128static char *resource_sections = NULL;
129static char *terrain_sections = NULL;
130static char *extra_sections = NULL;
131static char *base_sections = NULL;
132static char *road_sections = NULL;
133static char *tiledef_sections = nullptr;
134
136
137static bool load_rulesetdir(const char *rsdir, bool compat_mode,
139 bool act, bool buffer_script, bool load_luadata);
140static struct section_file *openload_ruleset_file(const char *whichset,
141 const char *rsdir);
142
143static bool load_game_names(struct section_file *file,
144 struct rscompat_info *compat);
145static bool load_action_names(struct section_file *file,
146 struct rscompat_info *compat);
147static bool load_tech_names(struct section_file *file,
148 struct rscompat_info *compat);
149static bool load_unit_names(struct section_file *file,
150 struct rscompat_info *compat);
151static bool load_building_names(struct section_file *file,
152 struct rscompat_info *compat);
153static bool load_government_names(struct section_file *file,
154 struct rscompat_info *compat);
155static bool load_terrain_names(struct section_file *file,
156 struct rscompat_info *compat);
157static bool load_style_names(struct section_file *file,
158 struct rscompat_info *compat);
159static bool load_nation_names(struct section_file *file,
160 struct rscompat_info *compat);
161static bool load_city_name_list(struct section_file *file,
162 struct nation_type *pnation,
163 const char *secfile_str1,
164 const char *secfile_str2,
165 const char **allowed_terrains,
166 size_t atcount);
167
168static bool load_ruleset_techs(struct section_file *file,
169 struct rscompat_info *compat);
170static bool load_ruleset_units(struct section_file *file,
171 struct rscompat_info *compat);
172static bool load_ruleset_buildings(struct section_file *file,
173 struct rscompat_info *compat);
174static bool load_ruleset_governments(struct section_file *file,
175 struct rscompat_info *compat);
176static bool load_ruleset_terrain(struct section_file *file,
177 struct rscompat_info *compat);
178static bool load_ruleset_styles(struct section_file *file,
179 struct rscompat_info *compat);
180static bool load_ruleset_cities(struct section_file *file,
181 struct rscompat_info *compat);
182static bool load_ruleset_effects(struct section_file *file,
183 struct rscompat_info *compat);
184static bool load_ruleset_game(struct section_file *file, bool act,
185 struct rscompat_info *compat);
186static bool load_ruleset_actions(struct section_file *file,
187 struct section_file *gamefile,
188 struct rscompat_info *compat);
189
190static void send_ruleset_tech_classes(struct conn_list *dest);
191static void send_ruleset_techs(struct conn_list *dest);
192static void send_ruleset_unit_classes(struct conn_list *dest);
193static void send_ruleset_units(struct conn_list *dest);
194static void send_ruleset_buildings(struct conn_list *dest);
195static void send_ruleset_terrain(struct conn_list *dest);
196static void send_ruleset_resources(struct conn_list *dest);
197static void send_ruleset_extras(struct conn_list *dest);
198static void send_ruleset_bases(struct conn_list *dest);
199static void send_ruleset_roads(struct conn_list *dest);
200static void send_ruleset_tiledefs(struct conn_list *dest);
201static void send_ruleset_goods(struct conn_list *dest);
202static void send_ruleset_governments(struct conn_list *dest);
203static void send_ruleset_styles(struct conn_list *dest);
204static void send_ruleset_clauses(struct conn_list *dest);
205static void send_ruleset_musics(struct conn_list *dest);
206static void send_ruleset_cities(struct conn_list *dest);
207static void send_ruleset_game(struct conn_list *dest);
208static void send_ruleset_team_names(struct conn_list *dest);
209
210static bool load_ruleset_veteran(struct section_file *file,
211 const char *path,
212 struct veteran_system **vsystem, char *err,
213 size_t err_len);
214static bool load_specialist(const struct section *psection,
215 struct specialist *s,
216 struct section_file *file);
217
220
221/**********************************************************************/
226 const char *file, const char *function,
227 int line, enum log_level level,
228 const char *format, ...)
229{
230 va_list args;
231 char buf[MAX_LEN_LOG_LINE];
232
233 if (logger == NULL && !log_do_output_for_level(level)) {
234 return;
235 }
236
237 va_start(args, format);
238 if (logger != NULL) {
239 fc_vsnprintf(buf, sizeof(buf), format, args);
240 logger(buf);
241 } else {
242 vdo_log(file, function, line, FALSE, level, buf, sizeof(buf), format, args);
243 }
244 va_end(args);
245
246 if (LOG_FATAL >= level) {
248 }
249}
250
251/**********************************************************************/
255{
256 int purged = 0;
257
258 action_iterate(act_id) {
259 struct action *paction = action_by_number(act_id);
260
262 == 0) {
263 /* Not relevant. */
264 continue;
265 }
266
267 /* Impossible hard requirement. */
269 /* Make sure that all action enablers are disabled. */
271 ae) {
272 ae->rulesave.ruledit_disabled = TRUE;
273 purged++;
275
276 log_normal("Purged all action enablers for %s",
278 }
279
280 /* Impossible requirement vector requirement. */
282 ae) {
283 if (!ae->rulesave.ruledit_disabled
285 || req_vec_is_impossible_to_fulfill(&ae->target_reqs))) {
286 ae->rulesave.ruledit_disabled = TRUE;
287 purged++;
288 log_normal("Purged unused action enabler for %s",
290 }
293
294 return purged;
295}
296
297/**********************************************************************/
301{
302 int purged = 0;
303 enum effect_type type;
304
309 eft->rulesave.do_not_save = TRUE;
310 purged++;
311 log_normal("Purged unused effect for %s",
312 effect_type_name(eft->type));
313 }
315 }
316
317 return purged;
318}
319
320/**********************************************************************/
324{
325 int purged = 0;
326
329
330 return purged;
331}
332
333/**********************************************************************/
338 const char *msg)
339{
340 struct req_vec_problem *problem;
341 bool result;
342
344 reqs);
345
346 if (problem == NULL) {
347 /* No problem. */
348 return FALSE;
349 }
350
351 if (problem->num_suggested_solutions == 0) {
352 /* No solution. */
354 return FALSE;
355 }
356
357 if (problem->num_suggested_solutions == 1
358 && problem->suggested_solutions[0].operation == RVCO_REMOVE) {
359 /* Remove !present req that never is there. */
360 log_normal("%s", msg);
361 result = req_vec_change_apply(&problem->suggested_solutions[0],
364 return result;
365 }
366
367 /* Not handled. Don't know what this is. */
368 fc_assert(problem->num_suggested_solutions == 1);
370 return FALSE;
371}
372
373/**********************************************************************/
378 const char *msg)
379{
380 struct req_vec_problem *problem;
381 bool result;
382
384 reqs);
385
386 if (problem == NULL) {
387 /* No problem. */
388 return FALSE;
389 }
390
391 if (problem->num_suggested_solutions == 0) {
392 /* No solution. */
394 return FALSE;
395 }
396
397 if (problem->num_suggested_solutions == 2
398 && problem->suggested_solutions[0].operation == RVCO_REMOVE
399 && problem->suggested_solutions[1].operation == RVCO_REMOVE
400 && are_requirements_equal(&problem->suggested_solutions[0].req,
401 &problem->suggested_solutions[1].req)) {
402 /* Simple duplication is handled. */
403 log_normal("%s", msg);
404 result = req_vec_change_apply(&problem->suggested_solutions[1],
407 return result;
408 }
409
410 /* Requirements of different kinds making each other redundant isn't
411 * supported yet. It could be done by always removing the most general
412 * requirement. So unit type is kept when redundant with unit flag, unit
413 * class and unit class flag etc. */
415 return FALSE;
416}
417
418/**********************************************************************/
423 const char *msg)
424{
425 return (purge_unused_req_vec(reqs, msg)
427}
428
429/**********************************************************************/
434{
435 int purged = 0;
436
437 action_iterate(act_id) {
438 struct action *paction = action_by_number(act_id);
439 char actor_reqs[MAX_LEN_NAME * 2];
440 char target_reqs[MAX_LEN_NAME * 2];
441
442 /* Error log text */
443 fc_snprintf(actor_reqs, sizeof(actor_reqs),
444 "Purged redundant requirement in"
445 " %s in action enabler for %s",
446 "actor_reqs", action_rule_name(paction));
447 fc_snprintf(target_reqs, sizeof(target_reqs),
448 "Purged redundant requirement in"
449 " %s in action enabler for %s",
450 "target_reqs", action_rule_name(paction));
451
452 /* Do the purging. */
454 ae) {
455 while (!ae->rulesave.ruledit_disabled
456 && (purge_redundant_req_vec(&ae->actor_reqs, actor_reqs)
457 || purge_redundant_req_vec(&ae->target_reqs,
458 target_reqs))) {
459 purged++;
460 }
463
464 return purged;
465}
466
467/**********************************************************************/
472{
473 int purged = 0;
474 enum effect_type type;
475
478 char msg[MAX_LEN_NAME * 2];
479
480 /* Error log text */
481 fc_snprintf(msg, sizeof(msg),
482 "Purged redundant requirement in effect of type %s",
484
485 /* Do the purging. */
487 while (purge_redundant_req_vec(&eft->reqs, msg)) {
488 purged++;
489 }
491 }
492
493 return purged;
494}
495
496/**********************************************************************/
501{
502 int purged = 0;
503
506
507 if (purged > 0) {
508 /* An unused requirement may be an obligatory hard requirement. */
510 }
511
512 return purged;
513}
514
515/**********************************************************************/
519static const char *valid_ruleset_filename(const char *subdir,
520 const char *name,
521 const char *extension,
522 bool optional)
523{
524 char filename[512];
525 const char *dfilename;
526
528
529 fc_snprintf(filename, sizeof(filename), "%s" DIR_SEPARATOR "%s.%s",
531 log_verbose("Trying \"%s\".", filename);
532 dfilename = fileinfoname(get_data_dirs(), filename);
533 if (dfilename) {
534 return dfilename;
535 }
536
537 fc_snprintf(filename, sizeof(filename), "default" DIR_SEPARATOR "%s.%s", name, extension);
538 log_verbose("Trying \"%s\": default ruleset directory.", filename);
539 dfilename = fileinfoname(get_data_dirs(), filename);
540 if (dfilename) {
541 return dfilename;
542 }
543
544 fc_snprintf(filename, sizeof(filename), "%s_%s.%s",
546 log_verbose("Trying \"%s\": alternative ruleset filename syntax.",
547 filename);
548 dfilename = fileinfoname(get_data_dirs(), filename);
549 if (dfilename) {
550 return dfilename;
551 } else if (!optional) {
553 /* TRANS: message about an installation error. */
554 _("Could not find a readable \"%s.%s\" ruleset file."),
555 name, extension);
556 }
557
558 return NULL;
559}
560
561/**********************************************************************/
565{
566 return script_buffer;
567}
568
569/**********************************************************************/
573{
574 return parser_buffer;
575}
576
577/**********************************************************************/
581static struct section_file *openload_ruleset_file(const char *whichset,
582 const char *rsdir)
583{
584 char sfilename[512];
587 struct section_file *secfile;
588
589 if (dfilename == NULL) {
590 return NULL;
591 }
592
593 /* Need to save a copy of the filename for following message, since
594 section_file_load() may call datafilename() for includes. */
596 secfile = secfile_load(sfilename, FALSE);
597
598 if (secfile == NULL) {
599 ruleset_error(NULL, LOG_ERROR, "Could not load ruleset '%s':\n%s",
601 }
602
603 return secfile;
604}
605
606/**********************************************************************/
609static enum fc_tristate openload_script_file(const char *whichset, const char *rsdir,
610 char **buffer, bool optional)
611{
614
615 if (dfilename == NULL) {
616 return optional ? TRI_MAYBE : TRI_NO;
617 }
618
619 if (buffer == NULL) {
621 ruleset_error(NULL, LOG_ERROR, "\"%s\": could not load ruleset script.",
622 dfilename);
623
624 return TRI_NO;
625 }
626 } else {
628 }
629
630 return TRI_YES;
631}
632
633/**********************************************************************/
636static struct section_file *openload_luadata_file(const char *rsdir)
637{
638 struct section_file *secfile;
639 char sfilename[512];
640 const char *dfilename = valid_ruleset_filename(rsdir, "luadata",
641 "txt", TRUE);
642
643 if (dfilename == NULL) {
644 return NULL;
645 }
646
647 /* Need to save a copy of the filename for following message, since
648 section_file_load() may call datafilename() for includes. */
650 secfile = secfile_load(sfilename, FALSE);
651
652 if (secfile == NULL) {
653 ruleset_error(NULL, LOG_ERROR, "Could not load luadata '%s':\n%s",
655 }
656
657 return secfile;
658}
659
660/**********************************************************************/
665 const char *sec,
666 const char *sub,
667 const char *rfor)
668{
669 const char *type, *name;
670 int j;
671 const char *filename;
672
673 filename = secfile_name(file);
674
676
677 for (j = 0; (type = secfile_lookup_str_default(file, NULL, "%s.%s%d.type",
678 sec, sub, j)); j++) {
679 char buf[MAX_LEN_NAME];
680 const char *range;
681 bool survives, present, quiet;
682 struct entry *pentry;
683 struct requirement req;
684
685 if (!(pentry = secfile_entry_lookup(file, "%s.%s%d.name",
686 sec, sub, j))) {
688
689 return NULL;
690 }
691 name = NULL;
692 switch (entry_type_get(pentry)) {
693 case ENTRY_BOOL:
694 {
695 bool val;
696
697 if (entry_bool_get(pentry, &val)) {
698 fc_snprintf(buf, sizeof(buf), "%d", val);
699 name = buf;
700 }
701 }
702 break;
703 case ENTRY_INT:
704 {
705 int val;
706
707 if (entry_int_get(pentry, &val)) {
708 fc_snprintf(buf, sizeof(buf), "%d", val);
709 name = buf;
710 }
711 }
712 break;
713 case ENTRY_STR:
715 break;
716 case ENTRY_FLOAT:
719 "\"%s\": trying to have an floating point entry as a requirement name in '%s.%s%d'.",
720 filename, sec, sub, j);
721 break;
724 break;
727 break;
728 case ENTRY_ILLEGAL:
730 break;
731 }
732 if (NULL == name) {
734 "\"%s\": error in handling requirement name for '%s.%s%d'.",
735 filename, sec, sub, j);
736 return NULL;
737 }
738
739 if (!(range = secfile_lookup_str(file, "%s.%s%d.range", sec, sub, j))) {
741
742 return NULL;
743 }
744
745 survives = FALSE;
746 if ((pentry = secfile_entry_lookup(file, "%s.%s%d.survives",
747 sec, sub, j))
750 "\"%s\": invalid boolean value for survives for "
751 "'%s.%s%d'.", filename, sec, sub, j);
752 }
753
754 present = TRUE;
755 if ((pentry = secfile_entry_lookup(file, "%s.%s%d.present",
756 sec, sub, j))
759 "\"%s\": invalid boolean value for present for "
760 "'%s.%s%d'.", filename, sec, sub, j);
761 }
762 quiet = FALSE;
763 if ((pentry = secfile_entry_lookup(file, "%s.%s%d.quiet",
764 sec, sub, j))
765 && !entry_bool_get(pentry, &quiet)) {
767 "\"%s\": invalid boolean value for quiet for "
768 "'%s.%s%d'.", filename, sec, sub, j);
769 }
770
772 if (req.source.kind == universals_n_invalid()) {
774 "\"%s\" [%s] has invalid or unknown req: "
775 "\"%s\" \"%s\".",
776 filename, sec, type, name);
777
778 return NULL;
779 }
780
782 }
783
784 return &reqs_list;
785}
786
787/**********************************************************************/
791 struct section_file *file,
792 const char *sec,
793 const char *sub)
794{
795 const char *flag;
796 int j;
797 const char *filename;
798 bool success = TRUE;
799
800 filename = secfile_name(file);
801
802 for (j = 0; (flag = secfile_lookup_str_default(file, NULL, "%s.%s%d.flag",
803 sec, sub, j)); j++) {
804 struct combat_bonus *bonus = fc_malloc(sizeof(*bonus));
805 const char *type;
806
808 if (!unit_type_flag_id_is_valid(bonus->flag)) {
809 log_error("\"%s\": unknown flag name \"%s\" in '%s.%s'.",
810 filename, flag, sec, sub);
811 FC_FREE(bonus);
812 success = FALSE;
813 continue;
814 }
815 type = secfile_lookup_str(file, "%s.%s%d.type", sec, sub, j);
817 if (!combat_bonus_type_is_valid(bonus->type)) {
818 log_error("\"%s\": unknown bonus type \"%s\" in '%s.%s'.",
819 filename, type, sec, sub);
820 FC_FREE(bonus);
821 success = FALSE;
822 continue;
823 }
824 if (!secfile_lookup_int(file, &bonus->value, "%s.%s%d.value",
825 sec, sub, j)) {
826 log_error("\"%s\": failed to get value from '%s.%s%d'.",
827 filename, sec, sub, j);
828 FC_FREE(bonus);
829 success = FALSE;
830 continue;
831 }
833 "%s.%s%d.quiet",
834 sec, sub, j);
836 }
837
838 return success;
839}
840
841/**********************************************************************/
849static bool lookup_tech(struct section_file *file,
850 struct advance **result,
851 const char *prefix, const char *entry,
852 const char *filename,
853 const char *description)
854{
855 const char *sval;
856
857 sval = secfile_lookup_str_default(file, NULL, "%s.%s", prefix, entry);
858 if (!sval || !strcmp(sval, "Never")) {
859 *result = A_NEVER;
860 } else {
861 *result = advance_by_rule_name(sval);
862
863 if (A_NEVER == *result) {
865 "\"%s\" %s %s: couldn't match \"%s\".",
866 filename, (description ? description : prefix), entry, sval);
867 return FALSE;
868 }
869 }
870
871 return TRUE;
872}
873
874/**********************************************************************/
881static bool lookup_unit_list(struct section_file *file, const char *prefix,
882 const char *entry,
883 struct unit_type **output,
884 const char *filename)
885{
886 const char **slist;
887 size_t nval;
888 int i;
889 bool ok = TRUE;
890
891 /* pre-fill with NULL: */
892 for (i = 0; i < MAX_NUM_UNIT_LIST; i++) {
893 output[i] = NULL;
894 }
895 slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
896 if (nval == 0) {
897 /* 'No vector' is considered same as empty vector */
898 if (slist != NULL) {
899 free(slist);
900 }
901 return TRUE;
902 }
903 if (nval > MAX_NUM_UNIT_LIST) {
905 "\"%s\": string vector %s.%s too long (%d, max %d)",
906 filename, prefix, entry, (int) nval, MAX_NUM_UNIT_LIST);
907 ok = FALSE;
908 } else if (nval == 1 && strcmp(slist[0], "") == 0) {
909 free(slist);
910 return TRUE;
911 }
912 if (ok) {
913 for (i = 0; i < nval; i++) {
914 const char *sval = slist[i];
916
917 if (!punittype) {
919 "\"%s\" %s.%s (%d): couldn't match \"%s\".",
920 filename, prefix, entry, i, sval);
921 ok = FALSE;
922 break;
923 }
924 output[i] = punittype;
925 log_debug("\"%s\" %s.%s (%d): %s (%d)", filename, prefix, entry, i, sval,
927 }
928 }
929 free(slist);
930
931 return ok;
932}
933
934/**********************************************************************/
941static bool lookup_tech_list(struct section_file *file, const char *prefix,
942 const char *entry, int *output,
943 const char *filename)
944{
945 const char **slist;
946 size_t nval;
947 int i;
948 bool ok = TRUE;
949
950 /* pre-fill with A_LAST: */
951 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
952 output[i] = A_LAST;
953 }
954 slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
955 if (slist == NULL || nval == 0) {
956 return TRUE;
957 } else if (nval > MAX_NUM_TECH_LIST) {
959 "\"%s\": string vector %s.%s too long (%d, max %d)",
960 filename, prefix, entry, (int) nval, MAX_NUM_TECH_LIST);
961 ok = FALSE;
962 }
963
964 if (ok) {
965 if (nval == 1 && strcmp(slist[0], "") == 0) {
966 FC_FREE(slist);
967 return TRUE;
968 }
969 for (i = 0; i < nval && ok; i++) {
970 const char *sval = slist[i];
972
973 if (NULL == padvance) {
975 "\"%s\" %s.%s (%d): couldn't match \"%s\".",
976 filename, prefix, entry, i, sval);
977 ok = FALSE;
978 }
979 if (!valid_advance(padvance)) {
981 "\"%s\" %s.%s (%d): \"%s\" is removed.",
982 filename, prefix, entry, i, sval);
983 ok = FALSE;
984 }
985
986 if (ok) {
987 output[i] = advance_number(padvance);
988 log_debug("\"%s\" %s.%s (%d): %s (%d)", filename, prefix, entry, i, sval,
990 }
991 }
992 }
993 FC_FREE(slist);
994
995 return ok;
996}
997
998/**********************************************************************/
1005static bool lookup_building_list(struct section_file *file,
1006 const char *prefix, const char *entry,
1007 int *output, const char *filename)
1008{
1009 const char **slist;
1010 size_t nval;
1011 int i;
1012 bool ok = TRUE;
1013
1014 /* pre-fill with B_LAST: */
1015 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
1016 output[i] = B_LAST;
1017 }
1018 slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
1021 "\"%s\": string vector %s.%s too long (%d, max %d)",
1022 filename, prefix, entry, (int) nval, MAX_NUM_BUILDING_LIST);
1023 ok = FALSE;
1024 } else if (nval == 0 || (nval == 1 && strcmp(slist[0], "") == 0)) {
1025 if (slist != NULL) {
1026 FC_FREE(slist);
1027 }
1028 return TRUE;
1029 }
1030 if (ok) {
1031 for (i = 0; i < nval; i++) {
1032 const char *sval = slist[i];
1033 struct impr_type *pimprove = improvement_by_rule_name(sval);
1034
1035 if (NULL == pimprove) {
1037 "\"%s\" %s.%s (%d): couldn't match \"%s\".",
1038 filename, prefix, entry, i, sval);
1039 ok = FALSE;
1040 break;
1041 }
1042 output[i] = improvement_number(pimprove);
1043 log_debug("%s.%s,%d %s %d", prefix, entry, i, sval, output[i]);
1044 }
1045 }
1046 free(slist);
1047
1048 return ok;
1049}
1050
1051/**********************************************************************/
1057static bool lookup_unit_type(struct section_file *file,
1058 const char *prefix,
1059 const char *entry,
1060 const struct unit_type **result,
1061 const char *filename,
1062 const char *description)
1063{
1064 const char *sval;
1065
1066 sval = secfile_lookup_str_default(file, "None", "%s.%s", prefix, entry);
1067
1068 if (strcmp(sval, "None") == 0) {
1069 *result = NULL;
1070 } else {
1071 *result = unit_type_by_rule_name(sval);
1072 if (*result == NULL) {
1074 "\"%s\" %s %s: couldn't match \"%s\".",
1075 filename, (description ? description : prefix), entry, sval);
1076
1077 return FALSE;
1078 }
1079 }
1080
1081 return TRUE;
1082}
1083
1084/**********************************************************************/
1088static struct government *lookup_government(struct section_file *file,
1089 const char *entry,
1090 const char *filename,
1091 struct government *fallback)
1092{
1093 const char *sval;
1094 struct government *gov;
1095
1096 sval = secfile_lookup_str_default(file, NULL, "%s", entry);
1097 if (!sval) {
1098 gov = fallback;
1099 } else {
1101 }
1102 if (!gov) {
1104 "\"%s\" %s: couldn't match \"%s\".",
1105 filename, entry, sval);
1106 }
1107 return gov;
1108}
1109
1110/**********************************************************************/
1113static char *lookup_string(struct section_file *file, const char *prefix,
1114 const char *suffix)
1115{
1116 const char *sval = secfile_lookup_str(file, "%s.%s", prefix, suffix);
1117
1118 if (NULL != sval) {
1119 char copy[strlen(sval) + 1];
1120
1121 strcpy(copy, sval);
1123 if (strlen(copy) > 0) {
1124 return fc_strdup(copy);
1125 }
1126 }
1127 return NULL;
1128}
1129
1130/**********************************************************************/
1133static struct strvec *lookup_strvec(struct section_file *file,
1134 const char *prefix, const char *suffix)
1135{
1136 size_t dim;
1137 const char **vec = secfile_lookup_str_vec(file, &dim,
1138 "%s.%s", prefix, suffix);
1139
1140 if (NULL != vec) {
1141 struct strvec *dest = strvec_new();
1142
1143 strvec_store(dest, vec, dim);
1144 free(vec);
1145 return dest;
1146 }
1147 return NULL;
1148}
1149
1150/**********************************************************************/
1153static struct extra_type *lookup_resource(const char *filename,
1154 const char *name,
1155 const char *jsection)
1156{
1157 struct extra_type *pres;
1158
1160
1161 if (pres == NULL) {
1163 "\"%s\" [%s] has unknown \"%s\".",
1164 filename, jsection, name);
1165 }
1166
1167 return pres;
1168}
1169
1170/**********************************************************************/
1174static bool lookup_terrain(struct section_file *file,
1175 const char *entry,
1176 const char *filename,
1177 struct terrain *pthis,
1178 struct terrain **result,
1179 bool null_acceptable)
1180{
1181 const int j = terrain_index(pthis);
1182 const char *jsection = &terrain_sections[j * MAX_SECTION_LABEL];
1183 const char *name = secfile_lookup_str(file, "%s.%s", jsection, entry);
1184 struct terrain *pterr;
1185
1186 if (NULL == name && !null_acceptable) {
1187 return FALSE;
1188 }
1189
1190 if (NULL == name
1191 || *name == '\0'
1192 || (0 == strcmp(name, "none"))
1193 || (0 == strcmp(name, "no"))) {
1194 *result = T_NONE;
1195
1196 return TRUE;
1197 }
1198 if (0 == strcmp(name, "yes")) {
1199 *result = pthis;
1200
1201 return TRUE;
1202 }
1203
1205 *result = pterr;
1206
1207 if (pterr == NULL) {
1209 "\"%s\" [%s] has unknown \"%s\".",
1210 secfile_name(file), jsection, name);
1211 return FALSE;
1212 }
1213
1214 return TRUE;
1215}
1216
1217/**********************************************************************/
1224static bool lookup_time(const struct section_file *secfile, int *turns,
1225 const char *sec_name, const char *property_name,
1226 const char *filename, const char *item_name,
1227 bool *ok)
1228{
1229 /* Assumes that PACKET_UNIT_INFO.activity_count in packets.def is UINT16 */
1230 const int max_turns = 65535 / ACTIVITY_FACTOR;
1231
1232 if (!secfile_lookup_int(secfile, turns, "%s.%s", sec_name, property_name)) {
1233 return FALSE;
1234 }
1235
1236 if (*turns > max_turns) {
1238 "\"%s\": \"%s\": \"%s\" value %d too large (max %d)",
1239 filename, item_name ? item_name : sec_name,
1240 property_name, *turns, max_turns);
1241 *ok = FALSE;
1242 }
1243
1244 return TRUE; /* we found _something */
1245}
1246
1247/**********************************************************************/
1251 const char *domain,
1252 struct section_file *file,
1253 const char *sec_name)
1254{
1255 const char *name = secfile_lookup_str(file, "%s.name", sec_name);
1256 const char *rule_name = secfile_lookup_str(file, "%s.rule_name", sec_name);
1257
1258 if (!name) {
1260 "\"%s\" [%s]: no \"name\" specified.",
1261 secfile_name(file), sec_name);
1262 return FALSE;
1263 }
1264
1265 names_set(pname, domain, name, rule_name);
1266
1267 return TRUE;
1268}
1269
1270/**********************************************************************/
1274 struct section_file *file,
1275 const char *secname, const char *field_prefix)
1276{
1277 enum trait tr;
1278
1279 /* FIXME: Use specenum trait names without duplicating them here.
1280 * Just needs to take care of case.
1281 * This list is also duplicated in rulesave.c:save_traits() */
1282 const char *trait_names[] = {
1283 "expansionist",
1284 "trader",
1285 "aggressive",
1286 "builder",
1287 NULL
1288 };
1289
1290 for (tr = trait_begin(); tr != trait_end() && trait_names[tr] != NULL; tr = trait_next(tr)) {
1291 out[tr].min = secfile_lookup_int_default(file, -1, "%s.%s%s_min",
1292 secname,
1294 trait_names[tr]);
1295 out[tr].max = secfile_lookup_int_default(file, -1, "%s.%s%s_max",
1296 secname,
1298 trait_names[tr]);
1299 out[tr].fixed = secfile_lookup_int_default(file, -1, "%s.%s%s_default",
1300 secname,
1302 trait_names[tr]);
1303 }
1304
1305 fc_assert(tr == trait_end()); /* number of trait_names correct */
1306}
1307
1308/**********************************************************************/
1312static bool load_game_names(struct section_file *file,
1313 struct rscompat_info *compat)
1314{
1315 struct section_list *sec;
1316 int nval;
1317 const char *filename = secfile_name(file);
1318 bool ok = TRUE;
1319
1320 /* section: datafile */
1322 if (compat->version <= 0) {
1323 return FALSE;
1324 }
1325
1326 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
1327 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
1328
1330 nval = (NULL != sec ? section_list_size(sec) : 0);
1332 int num = nval; /* No "size_t" to printf */
1333
1335 "\"%s\": Too many achievement types (%d, max %d)",
1336 filename, num, MAX_ACHIEVEMENT_TYPES);
1337 ok = FALSE;
1338 } else {
1340 }
1341
1342 if (ok) {
1345
1346 if (!ruleset_load_names(&pach->name, NULL, file, sec_name)) {
1348 "\"%s\": Cannot load achievement names",
1349 filename);
1350 ok = FALSE;
1351 break;
1352 }
1354 }
1355
1357
1358 if (ok) {
1360
1361 nval = (NULL != sec ? section_list_size(sec) : 0);
1362 if (nval > MAX_GOODS_TYPES) {
1363 int num = nval; /* No "size_t" to printf */
1364
1366 "\"%s\": Too many goods types (%d, max %d)",
1367 filename, num, MAX_GOODS_TYPES);
1369 ok = FALSE;
1370 } else if (nval < 1) {
1372 "\"%s\": At least one goods type needed",
1373 filename);
1375 ok = FALSE;
1376 } else {
1378 }
1379
1380 if (ok) {
1382 const char *sec_name
1384
1385 if (!ruleset_load_names(&pgood->name, NULL, file, sec_name)) {
1387 "\"%s\": Cannot load goods names",
1388 filename);
1389 ok = FALSE;
1390 break;
1391 }
1393 }
1395 }
1396
1397 if (ok) {
1398
1400
1401 nval = (NULL != sec ? section_list_size(sec) : 0);
1402 if (nval > MAX_COUNTERS) {
1403 size_t num = nval;
1404
1406 "\"%s\": Too many counters (" SIZE_T_PRINTF ", max %d)",
1407 filename, num, MAX_COUNTERS);
1408 ok = FALSE;
1409 }
1410
1411 if (ok) {
1412 int count_idx;
1413
1415
1416 for (count_idx = 0; count_idx < nval; count_idx++) {
1417
1419 const char *sec_name
1421
1422 if (!ruleset_load_names(&pcount->name, NULL, file, sec_name)) {
1424 "\"%s\": Cannot load counters names",
1425 filename);
1426 ok = FALSE;
1427 break;
1428 }
1429 }
1430 }
1431
1433 }
1434
1435 return ok;
1436}
1437
1438/**********************************************************************/
1442static bool load_action_names(struct section_file *file,
1443 struct rscompat_info *compat)
1444{
1445 const char *filename = secfile_name(file);
1446 bool ok = TRUE;
1447
1448 if (!rscompat_check_cap_and_version(file, filename, compat)) {
1449 return FALSE;
1450 }
1451
1452 (void) secfile_entry_by_path(file, "datafile.description"); /* Unused */
1453 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* Unused */
1454
1455 return ok;
1456}
1457
1458/**********************************************************************/
1462static bool load_tech_names(struct section_file *file,
1463 struct rscompat_info *compat)
1464{
1465 struct section_list *sec = NULL;
1466 /* Number of techs in the ruleset (means without A_NONE). */
1467 int num_techs = 0;
1468 int i;
1469 const char *filename = secfile_name(file);
1470 bool ok = TRUE;
1471 const char *flag;
1472
1473 if (!rscompat_check_cap_and_version(file, filename, compat)) {
1474 return FALSE;
1475 }
1476
1477 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
1478 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
1479
1480 /* User tech flag names */
1481 for (i = 0; (flag = secfile_lookup_str_default(file, NULL, "control.flags%d.name", i)) ;
1482 i++) {
1483 const char *helptxt = secfile_lookup_str_default(file, NULL, "control.flags%d.helptxt",
1484 i);
1487 "\"%s\": Duplicate tech flag name '%s'",
1488 filename, flag);
1489 ok = FALSE;
1490 break;
1491 }
1492 if (i > MAX_NUM_USER_TECH_FLAGS) {
1494 "\"%s\": Too many user tech flags!",
1495 filename);
1496 ok = FALSE;
1497 break;
1498 }
1499
1500 set_user_tech_flag_name(TECH_USER_1 + i, flag, helptxt);
1501 }
1502
1503 if (ok) {
1504 size_t nval;
1505
1506 for (; i < MAX_NUM_USER_TECH_FLAGS; i++) {
1508 }
1509
1510 /* Tech classes */
1512
1513 nval = (NULL != sec ? section_list_size(sec) : 0);
1514 if (nval > MAX_NUM_TECH_CLASSES) {
1515 int num = nval; /* No "size_t" to printf */
1516
1518 "\"%s\": Too many tech classes (%d, max %d)",
1519 filename, num, MAX_NUM_TECH_CLASSES);
1521 ok = FALSE;
1522 } else {
1524 }
1525
1526 if (ok) {
1528 const char *sec_name
1530
1531 if (!ruleset_load_names(&ptclass->name, NULL, file, sec_name)) {
1532 ruleset_error(NULL, LOG_ERROR, "\"%s\": Cannot load tech class names",
1533 filename);
1534 ok = FALSE;
1535 break;
1536 }
1538 }
1539 }
1540
1541 if (ok) {
1542 /* The techs: */
1544 if (NULL == sec || 0 == (num_techs = section_list_size(sec))) {
1546 "\"%s\": No Advances?!?", filename);
1547 ok = FALSE;
1548 } else {
1549 log_verbose("%d advances (including possibly unused)", num_techs);
1550 if (num_techs + A_FIRST > A_LAST) {
1552 "\"%s\": Too many advances (%d, max %d)",
1553 filename, num_techs, A_LAST - A_FIRST);
1554 ok = FALSE;
1555 }
1556 }
1557 }
1558
1559 if (ok) {
1560 game.control.num_tech_types = num_techs + A_FIRST; /* includes A_NONE */
1561
1562 i = 0;
1563 advance_iterate(adv) {
1564 if (!ruleset_load_names(&adv->name, NULL, file,
1566 ok = FALSE;
1567 break;
1568 }
1569 i++;
1571 }
1573
1574 return ok;
1575}
1576
1577/**********************************************************************/
1580static bool load_ruleset_techs(struct section_file *file,
1581 struct rscompat_info *compat)
1582{
1583 struct section_list *sec;
1584 const char **slist;
1585 int i;
1586 size_t nval;
1588 const char *filename = secfile_name(file);
1589 bool ok = TRUE;
1590
1592
1593 i = 0;
1595 const char *sec_name = section_name(section_list_get(sec, i));
1596
1597 ptclass->cost_pct = secfile_lookup_int_default(file, 100, "%s.%s",
1598 sec_name, "cost_pct");
1599
1600 i++;
1602
1604
1605 i = 0;
1606 advance_iterate(a) {
1607 const char *sec_name = section_name(section_list_get(sec, i));
1608 const char *sval;
1609 int j, ival;
1610 struct requirement_vector *research_reqs;
1611
1612 if (!lookup_tech(file, &a->require[AR_ONE], sec_name, "req1",
1613 filename, rule_name_get(&a->name))
1614 || !lookup_tech(file, &a->require[AR_TWO], sec_name, "req2",
1615 filename, rule_name_get(&a->name))
1616 || !lookup_tech(file, &a->require[AR_ROOT], sec_name, "root_req",
1617 filename, rule_name_get(&a->name))) {
1618 ok = FALSE;
1619 break;
1620 }
1621
1622 if ((A_NEVER == a->require[AR_ONE] && A_NEVER != a->require[AR_TWO])
1623 || (A_NEVER != a->require[AR_ONE] && A_NEVER == a->require[AR_TWO])) {
1625 "\"%s\" [%s] \"%s\": \"Never\" with non-\"Never\".",
1626 filename, sec_name, rule_name_get(&a->name));
1627 ok = FALSE;
1628 break;
1629 }
1630 if (a_none == a->require[AR_ONE] && a_none != a->require[AR_TWO]) {
1632 "\"%s\" [%s] \"%s\": should have \"None\" second.",
1633 filename, sec_name, rule_name_get(&a->name));
1634 ok = FALSE;
1635 break;
1636 }
1637
1638 if (game.control.num_tech_classes == 0) {
1639 a->tclass = NULL;
1640 } else {
1641 const char *classname;
1642
1643 classname = lookup_string(file, sec_name, "class");
1644 if (classname != NULL) {
1647 if (a->tclass == NULL) {
1649 "\"%s\" [%s] \"%s\": Unknown tech class \"%s\".",
1650 filename, sec_name, rule_name_get(&a->name), classname);
1651 ok = FALSE;
1652 break;
1653 }
1654 } else {
1655 a->tclass = NULL; /* Default */
1656 }
1657 }
1658
1659 research_reqs = lookup_req_list(file, sec_name, "research_reqs",
1660 rule_name_get(&a->name));
1661 if (research_reqs == NULL) {
1662 ok = FALSE;
1663 break;
1664 }
1665
1666 requirement_vector_copy(&a->research_reqs, research_reqs);
1667
1668 BV_CLR_ALL(a->flags);
1669
1670 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
1671 for (j = 0; j < nval; j++) {
1672 sval = slist[j];
1673 if (strcmp(sval, "") == 0) {
1674 continue;
1675 }
1679 "\"%s\" [%s] \"%s\": bad flag name \"%s\".",
1680 filename, sec_name, rule_name_get(&a->name), sval);
1681 ok = FALSE;
1682 break;
1683 } else {
1684 BV_SET(a->flags, ival);
1685 }
1686 }
1687 free(slist);
1688
1689 if (!ok) {
1690 break;
1691 }
1692
1693 sz_strlcpy(a->graphic_str,
1694 secfile_lookup_str_default(file, "-", "%s.graphic", sec_name));
1695 sz_strlcpy(a->graphic_alt,
1697 "%s.graphic_alt", sec_name));
1698
1699 a->helptext = lookup_strvec(file, sec_name, "helptext");
1700 a->bonus_message = lookup_string(file, sec_name, "bonus_message");
1701 a->cost = secfile_lookup_int_default(file, -1, "%s.%s",
1702 sec_name, "cost");
1703 a->num_reqs = 0;
1704
1705 i++;
1707
1708 /* Propagate a root tech up into the tech tree. If a technology
1709 * X has Y has a root tech, then any technology requiring X (in the
1710 * normal way or as a root tech) also has Y as a root tech.
1711 * Later techs may gain a whole set of root techs in this way. The one
1712 * we store in AR_ROOT is a more or less arbitrary one of these,
1713 * also signalling that the set is non-empty; after this, you'll still
1714 * have to walk the tech tree to find them all. */
1715restart:
1716
1717 if (ok) {
1718 advance_iterate(a) {
1719 if (valid_advance(a)
1720 && A_NEVER != a->require[AR_ROOT]) {
1721 bool out_of_order = FALSE;
1722
1723 /* Now find any tech depending on this technology and update its
1724 * root_req. */
1725 advance_iterate(b) {
1726 if (valid_advance(b)
1727 && A_NEVER == b->require[AR_ROOT]
1728 && (a == b->require[AR_ONE] || a == b->require[AR_TWO])) {
1729 b->require[AR_ROOT] = a->require[AR_ROOT];
1730 b->inherited_root_req = TRUE;
1731 if (b < a) {
1733 }
1734 }
1736
1737 if (out_of_order) {
1738 /* HACK: If we just changed the root_tech of a lower-numbered
1739 * technology, we need to go back so that we can propagate the
1740 * root_tech up to that technology's parents... */
1741 goto restart;
1742 }
1743 }
1745
1746 /* Now rename A_NEVER to A_NONE for consistency */
1748 if (A_NEVER == a->require[AR_ROOT]) {
1749 a->require[AR_ROOT] = a_none;
1750 }
1752
1753 /* Some more consistency checking:
1754 Non-removed techs depending on removed techs is too
1755 broken to fix by default, so die.
1756 */
1757 advance_iterate(a) {
1758 if (valid_advance(a)) {
1759 /* We check for recursive tech loops later,
1760 * in build_required_techs_helper. */
1761 if (!valid_advance(a->require[AR_ONE])) {
1763 "\"%s\" tech \"%s\": req1 leads to removed tech.",
1764 filename, advance_rule_name(a));
1765 ok = FALSE;
1766 break;
1767 }
1768 if (!valid_advance(a->require[AR_TWO])) {
1770 "\"%s\" tech \"%s\": req2 leads to removed tech.",
1771 filename, advance_rule_name(a));
1772 ok = FALSE;
1773 break;
1774 }
1775 }
1777 }
1778
1780 if (ok) {
1782 }
1783
1784 return ok;
1785}
1786
1787/**********************************************************************/
1791static bool load_unit_names(struct section_file *file,
1792 struct rscompat_info *compat)
1793{
1794 struct section_list *sec = NULL;
1795 int nval = 0;
1796 int i;
1797 const char *filename = secfile_name(file);
1798 const char *flag;
1799 bool ok = TRUE;
1800
1801 if (!rscompat_check_cap_and_version(file, filename, compat)) {
1802 return FALSE;
1803 }
1804
1805 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
1806 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
1807
1808 /* User unit flag names */
1809 for (i = 0; (flag = secfile_lookup_str_default(file, NULL, "control.flags%d.name", i)) ;
1810 i++) {
1811 const char *helptxt = secfile_lookup_str_default(file, NULL, "control.flags%d.helptxt",
1812 i);
1813
1817 "\"%s\": Duplicate unit flag name '%s'",
1818 filename, flag);
1819 ok = FALSE;
1820 break;
1821 }
1822 if (i > MAX_NUM_USER_UNIT_FLAGS) {
1824 "\"%s\": Too many user unit type flags!",
1825 filename);
1826 ok = FALSE;
1827 break;
1828 }
1829
1831 }
1832
1833 if (ok) {
1834 /* Blank the remaining unit type user flags. */
1835 for (; i < MAX_NUM_USER_UNIT_FLAGS; i++) {
1837 }
1838 }
1839
1840 if (ok) {
1841 /* User unit class flag names */
1842 for (i = 0;
1843 (flag = secfile_lookup_str_default(file, NULL,
1844 "control.class_flags%d.name",
1845 i));
1846 i++) {
1847 const char *helptxt = secfile_lookup_str_default(file, NULL,
1848 "control.class_flags%d.helptxt", i);
1849
1853 "\"%s\": Duplicate unit class flag name '%s'",
1854 filename, flag);
1855 ok = FALSE;
1856 break;
1857 }
1860 "\"%s\": Too many user unit class flags!",
1861 filename);
1862 ok = FALSE;
1863 break;
1864 }
1865
1867 }
1868 }
1869
1870 if (ok) {
1871 /* Blank the remaining unit class user flags. */
1872 for (; i < MAX_NUM_USER_UCLASS_FLAGS; i++) {
1874 }
1875 }
1876
1877 if (ok) {
1878 /* Unit classes */
1880 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
1882 "\"%s\": No unit classes?!?", filename);
1883 ok = FALSE;
1884 } else {
1885 log_verbose("%d unit classes", nval);
1886 if (nval > UCL_LAST) {
1888 "\"%s\": Too many unit classes (%d, max %d)",
1889 filename, nval, UCL_LAST);
1890 ok = FALSE;
1891 }
1892 }
1893 }
1894
1895 if (ok) {
1897
1899 const int pci = uclass_index(punitclass);
1900
1901 if (!ruleset_load_names(&punitclass->name, NULL, file,
1903 ok = FALSE;
1904 break;
1905 }
1907 }
1909 sec = NULL;
1910
1911 /* The names: */
1912 if (ok) {
1914 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
1916 "\"%s\": No unit types?!?", filename);
1917 ok = FALSE;
1918 } else {
1919 log_verbose("%d unit types (including possibly unused)", nval);
1920 if (nval > U_LAST) {
1922 "\"%s\": Too many unit types (%d, max %d)",
1923 filename, nval, U_LAST);
1924 ok = FALSE;
1925 }
1926 }
1927 }
1928
1929 if (ok) {
1931
1933 const int utypei = utype_index(punittype);
1934 if (!ruleset_load_names(&punittype->name, NULL, file,
1936 ok = FALSE;
1937 break;
1938 }
1940 }
1942
1943 return ok;
1944}
1945
1946/**********************************************************************/
1949static bool load_ruleset_veteran(struct section_file *file,
1950 const char *path,
1951 struct veteran_system **vsystem, char *err,
1952 size_t err_len)
1953{
1954 const char **vlist_name;
1957 int i;
1958 bool ret = TRUE;
1959
1960 /* The pointer should be uninitialised. */
1961 if (*vsystem != NULL) {
1962 fc_snprintf(err, err_len, "Veteran system is defined?!");
1963 return FALSE;
1964 }
1965
1966 /* Load data. */
1968 "%s.veteran_names", path);
1970 "%s.veteran_power_fact", path);
1972 "%s.veteran_base_raise_chance", path);
1974 "%s.veteran_work_raise_chance",
1975 path);
1977 "%s.veteran_move_bonus", path);
1978
1979 if (count_name > MAX_VET_LEVELS) {
1980 ret = FALSE;
1981 fc_snprintf(err, err_len, "\"%s\": Too many veteran levels (section "
1982 "'%s': %lu, max %d)", secfile_name(file), path,
1983 (long unsigned)count_name, MAX_VET_LEVELS);
1984 } else if (count_name != count_power
1987 || count_name != count_move) {
1988 ret = FALSE;
1989 fc_snprintf(err, err_len, "\"%s\": Different lengths for the veteran "
1990 "settings in section '%s'", secfile_name(file),
1991 path);
1992 } else if (count_name == 0) {
1993 /* Nothing defined. */
1994 *vsystem = NULL;
1995 } else {
1996 /* Generate the veteran system. */
1998
1999#define rs_sanity_veteran(_path, _entry, _i, _condition, _action) \
2000 if (_condition) { \
2001 log_error("Invalid veteran definition '%s.%s[%d]'!", \
2002 _path, _entry, _i); \
2003 log_debug("Failed check: '%s'. Update value: '%s'.", \
2004 #_condition, #_action); \
2005 _action; \
2006 }
2007 for (i = 0; i < count_name; i++) {
2008 /* Some sanity checks. */
2009 rs_sanity_veteran(path, "veteran_power_fact", i,
2010 (vlist_power[i] < 0), vlist_power[i] = 0);
2011 rs_sanity_veteran(path, "veteran_base_raise_chance", i,
2012 (vlist_raise[i] < 0), vlist_raise[i] = 0);
2013 rs_sanity_veteran(path, "veteran_work_raise_chance", i,
2014 (vlist_wraise[i] < 0), vlist_wraise[i] = 0);
2015 rs_sanity_veteran(path, "veteran_move_bonus", i,
2016 (vlist_move[i] < 0), vlist_move[i] = 0);
2017 if (i == 0) {
2018 /* First element.*/
2019 rs_sanity_veteran(path, "veteran_power_fact", i,
2020 (vlist_power[i] != 100), vlist_power[i] = 100);
2021 } else if (i == count_name - 1) {
2022 /* Last element. */
2023 rs_sanity_veteran(path, "veteran_power_fact", i,
2024 (vlist_power[i] < vlist_power[i - 1]),
2025 vlist_power[i] = vlist_power[i - 1]);
2026 rs_sanity_veteran(path, "veteran_base_raise_chance", i,
2027 (vlist_raise[i] != 0), vlist_raise[i] = 0);
2028 rs_sanity_veteran(path, "veteran_work_raise_chance", i,
2029 (vlist_wraise[i] != 0), vlist_wraise[i] = 0);
2030 } else {
2031 /* All elements in between. */
2032 rs_sanity_veteran(path, "veteran_power_fact", i,
2033 (vlist_power[i] < vlist_power[i - 1]),
2034 vlist_power[i] = vlist_power[i - 1]);
2035 rs_sanity_veteran(path, "veteran_base_raise_chance", i,
2036 (vlist_raise[i] > 100), vlist_raise[i] = 100);
2037 rs_sanity_veteran(path, "veteran_work_raise_chance", i,
2038 (vlist_wraise[i] > 100), vlist_wraise[i] = 100);
2039 }
2040
2043 vlist_wraise[i]);
2044 }
2045#undef rs_sanity_veteran
2046 }
2047
2048 if (vlist_name) {
2050 }
2051 if (vlist_power) {
2053 }
2054 if (vlist_raise) {
2056 }
2057 if (vlist_wraise) {
2059 }
2060 if (vlist_move) {
2062 }
2063
2064 return ret;
2065}
2066
2067/**********************************************************************/
2070static bool load_ruleset_units(struct section_file *file,
2071 struct rscompat_info *compat)
2072{
2073 int j, ival;
2074 size_t nval;
2075 struct section_list *sec, *csec;
2076 const char *sval, **slist;
2077 const char *filename = secfile_name(file);
2078 char msg[MAX_LEN_MSG];
2079 bool ok = TRUE;
2080
2081 if (!load_ruleset_veteran(file, "veteran_system", &game.veteran, msg,
2082 sizeof(msg))
2083 || game.veteran == NULL) {
2085 "Error loading the default veteran system: %s",
2086 msg);
2087 ok = FALSE;
2088 }
2089
2091 nval = (NULL != sec ? section_list_size(sec) : 0);
2092
2094 nval = (NULL != csec ? section_list_size(csec) : 0);
2095
2096 if (ok) {
2098 int i = uclass_index(uc);
2099 const char *sec_name = section_name(section_list_get(csec, i));
2100
2101 if (secfile_lookup_int(file, &uc->min_speed, "%s.min_speed", sec_name)) {
2102 uc->min_speed *= SINGLE_MOVE;
2103 } else {
2105 ok = FALSE;
2106 break;
2107 }
2108 if (!secfile_lookup_int(file, &uc->hp_loss_pct,
2109 "%s.hp_loss_pct", sec_name)) {
2111 ok = FALSE;
2112 break;
2113 }
2114
2115 uc->non_native_def_pct = secfile_lookup_int_default(file, 100,
2116 "%s.non_native_def_pct",
2117 sec_name);
2118
2119 BV_CLR_ALL(uc->flags);
2120 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
2121 for (j = 0; j < nval; j++) {
2122 sval = slist[j];
2123 if (strcmp(sval, "") == 0) {
2124 continue;
2125 }
2126
2129 ok = FALSE;
2133 "\"%s\" unit_class \"%s\": unit_type flag \"%s\"!",
2134 filename, uclass_rule_name(uc), sval);
2135 } else {
2137 "\"%s\" unit_class \"%s\": bad flag name \"%s\".",
2138 filename, uclass_rule_name(uc), sval);
2139 }
2140 break;
2141 } else {
2142 BV_SET(uc->flags, ival);
2143 }
2144 }
2145 free(slist);
2146
2147 uc->helptext = lookup_strvec(file, sec_name, "helptext");
2148
2149 if (!ok) {
2150 break;
2151 }
2153 }
2154
2155 if (ok) {
2156 /* Tech and Gov requirements; per unit veteran system */
2158 const int i = utype_index(u);
2159 const struct section *psection = section_list_get(sec, i);
2160 const char *sec_name = section_name(psection);
2161 struct requirement_vector *reqs;
2162
2163 reqs = lookup_req_list(file, sec_name, "reqs",
2164 utype_rule_name(u));
2165
2166 if (reqs == NULL) {
2167 ok = FALSE;
2168 break;
2169 }
2170
2171 requirement_vector_copy(&u->build_reqs, reqs);
2172
2173 if (!load_ruleset_veteran(file, sec_name, &u->veteran,
2174 msg, sizeof(msg))) {
2176 "Error loading the veteran system: %s",
2177 msg);
2178 ok = FALSE;
2179 break;
2180 }
2181
2182 if (!lookup_unit_type(file, sec_name, "obsolete_by",
2183 &u->obsoleted_by, filename,
2184 rule_name_get(&u->name))
2185 || !lookup_unit_type(file, sec_name, "convert_to",
2186 &u->converted_to, filename,
2187 rule_name_get(&u->name))) {
2188 ok = FALSE;
2189 break;
2190 }
2191 u->convert_time = 1; /* default */
2192 lookup_time(file, &u->convert_time, sec_name, "convert_time",
2193 filename, rule_name_get(&u->name), &ok);
2195 }
2196
2197 if (ok) {
2198 /* main stats: */
2200 const int i = utype_index(u);
2201 struct unit_class *pclass;
2202 const char *sec_name = section_name(section_list_get(sec, i));
2203 const char *str;
2204
2205 sval = secfile_lookup_str(file, "%s.class", sec_name);
2207 if (!pclass) {
2209 "\"%s\" unit_type \"%s\": bad class \"%s\".",
2210 filename, utype_rule_name(u), sval);
2211 ok = FALSE;
2212 break;
2213 }
2214 u->uclass = pclass;
2215
2216 sz_strlcpy(u->sound_move,
2217 secfile_lookup_str_default(file, "-", "%s.sound_move",
2218 sec_name));
2219 sz_strlcpy(u->sound_move_alt,
2220 secfile_lookup_str_default(file, "-", "%s.sound_move_alt",
2221 sec_name));
2222 sz_strlcpy(u->sound_fight,
2223 secfile_lookup_str_default(file, "-", "%s.sound_fight",
2224 sec_name));
2225 sz_strlcpy(u->sound_fight_alt,
2226 secfile_lookup_str_default(file, "-", "%s.sound_fight_alt",
2227 sec_name));
2228
2229 if ((str = secfile_lookup_str(file, "%s.graphic", sec_name))) {
2230 sz_strlcpy(u->graphic_str, str);
2231 } else {
2233 ok = FALSE;
2234 break;
2235 }
2236 sz_strlcpy(u->graphic_alt,
2237 secfile_lookup_str_default(file, "-", "%s.graphic_alt",
2238 sec_name));
2239 sz_strlcpy(u->graphic_alt2,
2240 secfile_lookup_str_default(file, "-", "%s.graphic_alt2",
2241 sec_name));
2242
2243 if (!secfile_lookup_int(file, &u->build_cost,
2244 "%s.build_cost", sec_name)
2245 || !secfile_lookup_int(file, &u->pop_cost,
2246 "%s.pop_cost", sec_name)
2247 || !secfile_lookup_int(file, &u->attack_strength,
2248 "%s.attack", sec_name)
2249 || !secfile_lookup_int(file, &u->defense_strength,
2250 "%s.defense", sec_name)
2251 || !secfile_lookup_int(file, &u->move_rate,
2252 "%s.move_rate", sec_name)
2253 || !secfile_lookup_int(file, &u->vision_radius_sq,
2254 "%s.vision_radius_sq", sec_name)
2255 || !secfile_lookup_int(file, &u->transport_capacity,
2256 "%s.transport_cap", sec_name)
2257 || !secfile_lookup_int(file, &u->hp,
2258 "%s.hitpoints", sec_name)
2259 || !secfile_lookup_int(file, &u->firepower,
2260 "%s.firepower", sec_name)
2261 || !secfile_lookup_int(file, &u->fuel,
2262 "%s.fuel", sec_name)
2263 || !secfile_lookup_int(file, &u->happy_cost,
2264 "%s.uk_happy", sec_name)) {
2266 ok = FALSE;
2267 break;
2268 }
2269 u->move_rate *= SINGLE_MOVE;
2270
2271 if (u->firepower <= 0) {
2273 "\"%s\" unit_type \"%s\":"
2274 " firepower is %d,"
2275 " but must be at least 1. "
2276 " If you want no attack ability,"
2277 " set the unit's attack strength to 0.",
2278 filename, utype_rule_name(u), u->firepower);
2279 ok = FALSE;
2280 break;
2281 }
2282
2283 lookup_cbonus_list(u->bonuses, file, sec_name, "bonuses");
2284
2286 u->upkeep[o] = secfile_lookup_int_default(file, 0, "%s.uk_%s",
2287 sec_name,
2290
2291 slist = secfile_lookup_str_vec(file, &nval, "%s.cargo", sec_name);
2292
2293 BV_CLR_ALL(u->cargo);
2294 for (j = 0; j < nval; j++) {
2295 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2296
2297 if (!uclass) {
2299 "\"%s\" unit_type \"%s\":"
2300 "has unknown unit class %s as cargo.",
2301 filename, utype_rule_name(u), slist[j]);
2302 ok = FALSE;
2303 break;
2304 }
2305
2306 BV_SET(u->cargo, uclass_index(uclass));
2307 }
2308 free(slist);
2309
2310 if (!ok) {
2311 break;
2312 }
2313
2314 slist = secfile_lookup_str_vec(file, &nval, "%s.targets", sec_name);
2315 BV_CLR_ALL(u->targets);
2316 for (j = 0; j < nval; j++) {
2317 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2318
2319 if (!uclass) {
2321 "\"%s\" unit_type \"%s\":"
2322 "has unknown unit class %s as target.",
2323 filename, utype_rule_name(u), slist[j]);
2324 ok = FALSE;
2325 break;
2326 }
2327
2328 BV_SET(u->targets, uclass_index(uclass));
2329 }
2330 free(slist);
2331
2332 if (!ok) {
2333 break;
2334 }
2335
2336 slist = secfile_lookup_str_vec(file, &nval, "%s.embarks", sec_name);
2337 BV_CLR_ALL(u->embarks);
2338 for (j = 0; j < nval; j++) {
2339 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2340
2341 if (!uclass) {
2343 "\"%s\" unit_type \"%s\":"
2344 "has unknown unit class %s as embarkable.",
2345 filename, utype_rule_name(u), slist[j]);
2346 ok = FALSE;
2347 break;
2348 }
2349
2350 BV_SET(u->embarks, uclass_index(uclass));
2351 }
2352 free(slist);
2353
2354 if (!ok) {
2355 break;
2356 }
2357
2358 slist = secfile_lookup_str_vec(file, &nval, "%s.disembarks", sec_name);
2359 BV_CLR_ALL(u->disembarks);
2360 for (j = 0; j < nval; j++) {
2361 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2362
2363 if (!uclass) {
2365 "\"%s\" unit_type \"%s\":"
2366 "has unknown unit class %s as disembarkable.",
2367 filename, utype_rule_name(u), slist[j]);
2368 ok = FALSE;
2369 break;
2370 }
2371
2372 BV_SET(u->disembarks, uclass_index(uclass));
2373 }
2374 free(slist);
2375
2376 if (!ok) {
2377 break;
2378 }
2379
2380 /* Set also all classes that are never unreachable as targets,
2381 * embarks, and disembarks. */
2384 BV_SET(u->targets, uclass_index(preachable));
2385 BV_SET(u->embarks, uclass_index(preachable));
2386 BV_SET(u->disembarks, uclass_index(preachable));
2387 }
2389
2390 str = secfile_lookup_str_default(file, "Main", "%s.vision_layer",
2391 sec_name);
2393 if (!vision_layer_is_valid(u->vlayer)) {
2395 "\"%s\" unit_type \"%s\":"
2396 "has unknown vision layer %s.",
2397 filename, utype_rule_name(u), str);
2398 ok = FALSE;
2399 break;
2400 }
2401
2402 u->helptext = lookup_strvec(file, sec_name, "helptext");
2403
2404 u->paratroopers_range = secfile_lookup_int_default(file,
2405 0, "%s.paratroopers_range", sec_name);
2406
2407 u->bombard_rate = secfile_lookup_int_default(file, 0,
2408 "%s.bombard_rate", sec_name);
2409 u->city_slots = secfile_lookup_int_default(file, 0,
2410 "%s.city_slots", sec_name);
2411 u->city_size = secfile_lookup_int_default(file, 1,
2412 "%s.city_size", sec_name);
2413 if ((sval
2414 = secfile_lookup_str_default(file, nullptr, "%s.specialist", sec_name))) {
2415 if (!(u->spec_type = specialist_by_rule_name(sval))) {
2416 ruleset_error(nullptr, LOG_ERROR,
2417 "\"%s\" unit_type \"%s\":"
2418 " bad specialist \"%s\".",
2419 filename, utype_rule_name(u), sval);
2420 ok = FALSE;
2421 }
2422 } else {
2423 /* Specialists must have been processed before */
2426 ok = FALSE; break);
2428 }
2429
2431 "%s.tp_defense", sec_name);
2432 u->tp_defense = transp_def_type_by_name(sval, fc_strcasecmp);
2433 if (!transp_def_type_is_valid(u->tp_defense)) {
2435 "\"%s\" unit_type \"%s\":"
2436 " bad tp_defense \"%s\".",
2437 filename, utype_rule_name(u), sval);
2438 ok = FALSE;
2439 break;
2440 }
2442 }
2443
2444 if (ok) {
2445 /* Flags */
2447 const int i = utype_index(u);
2448
2449 BV_CLR_ALL(u->flags);
2451
2452 slist = secfile_lookup_str_vec(file, &nval, "%s.flags",
2454 for (j = 0; j < nval; j++) {
2455 sval = slist[j];
2456 if (0 == strcmp(sval, "")) {
2457 continue;
2458 }
2461 ok = FALSE;
2465 "\"%s\" unit_type \"%s\": unit_class flag!",
2466 filename, utype_rule_name(u));
2467 } else {
2469 "\"%s\" unit_type \"%s\": bad flag name \"%s\".",
2470 filename, utype_rule_name(u), sval);
2471 }
2472 break;
2473 } else {
2474 BV_SET(u->flags, ival);
2475 }
2476 }
2477 free(slist);
2478
2479 if (!ok) {
2480 break;
2481 }
2483 }
2484
2485 /* Roles */
2486 if (ok) {
2488 const int i = utype_index(u);
2489
2490 BV_CLR_ALL(u->roles);
2491
2492 slist = secfile_lookup_str_vec(file, &nval, "%s.roles",
2494 for (j = 0; j < nval; j++) {
2495 sval = slist[j];
2496 if (strcmp(sval, "") == 0) {
2497 continue;
2498 }
2502 "\"%s\" unit_type \"%s\": bad role name \"%s\".",
2503 filename, utype_rule_name(u), sval);
2504 ok = FALSE;
2505 break;
2506 } else {
2507 BV_SET(u->roles, ival - L_FIRST);
2508 }
2510 }
2511 free(slist);
2513 }
2514
2515 if (ok) {
2516 /* Some more consistency checking: */
2519 if (!valid_advance(padv)) {
2521 "\"%s\" unit_type \"%s\": depends on removed tech \"%s\".",
2522 filename, utype_rule_name(u),
2524 ok = FALSE;
2525 break;
2526 }
2528
2529 if (!ok) {
2530 break;
2531 }
2533 }
2534
2537
2538 if (ok) {
2540 }
2541
2542 return ok;
2543}
2544
2545/**********************************************************************/
2549static bool load_building_names(struct section_file *file,
2550 struct rscompat_info *compat)
2551{
2552 struct section_list *sec;
2553 int i, nval = 0;
2554 const char *filename = secfile_name(file);
2555 bool ok = TRUE;
2556 const char *flag;
2557
2558 if (!rscompat_check_cap_and_version(file, filename, compat)) {
2559 return FALSE;
2560 }
2561
2562 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
2563 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
2564
2565 /* The names: */
2567 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
2569 "\"%s\": No improvements?!?", filename);
2570 ok = FALSE;
2571 } else {
2572 log_verbose("%d improvement types (including possibly unused)", nval);
2573 if (nval > B_LAST) {
2575 "\"%s\": Too many improvements (%d, max %d)",
2576 filename, nval, B_LAST);
2577 ok = FALSE;
2578 }
2579 }
2580
2581 if (ok) {
2583
2584 for (i = 0; i < nval; i++) {
2585 struct impr_type *b = improvement_by_number(i);
2586
2587 if (!ruleset_load_names(&b->name, NULL, file, section_name(section_list_get(sec, i)))) {
2588 ok = FALSE;
2589 break;
2590 }
2591 }
2592 }
2593
2594 /* User building flag names */
2595 for (i = 0;
2596 (flag = secfile_lookup_str_default(file, NULL,
2597 "control.building_flags%d.name",
2598 i));
2599 i++) {
2600 const char *helptxt = secfile_lookup_str_default(file, NULL,
2601 "control.building_flags%d.helptxt", i);
2602
2604 != impr_flag_id_invalid()) {
2606 "\"%s\": Duplicate building flag name '%s'",
2607 filename, flag);
2608 ok = FALSE;
2609 break;
2610 }
2613 "\"%s\": Too many user building flags!",
2614 filename);
2615 ok = FALSE;
2616 break;
2617 }
2618
2619 set_user_impr_flag_name(IF_USER_FLAG_1 + i, flag, helptxt);
2620 }
2621
2623
2624 return ok;
2625}
2626
2627/**********************************************************************/
2630static bool load_ruleset_buildings(struct section_file *file,
2631 struct rscompat_info *compat)
2632{
2633 struct section_list *sec;
2634 const char *item;
2635 int i, nval;
2636 const char *filename = secfile_name(file);
2637 bool ok = TRUE;
2638
2640 nval = (NULL != sec ? section_list_size(sec) : 0);
2641
2642 for (i = 0; i < nval && ok; i++) {
2643 struct impr_type *b = improvement_by_number(i);
2644 const char *sec_name = section_name(section_list_get(sec, i));
2645 struct requirement_vector *reqs
2646 = lookup_req_list(file, sec_name, "reqs",
2648
2649 if (reqs == NULL) {
2650 ok = FALSE;
2651 break;
2652 } else {
2653 const char *sval, **slist;
2654 int j, ival;
2655 size_t nflags;
2656
2657 item = secfile_lookup_str(file, "%s.genus", sec_name);
2659 if (!impr_genus_id_is_valid(b->genus)) {
2661 "\"%s\" improvement \"%s\": couldn't match "
2662 "genus \"%s\".", filename,
2664 ok = FALSE;
2665 break;
2666 }
2667
2668 slist = secfile_lookup_str_vec(file, &nflags, "%s.flags", sec_name);
2669 BV_CLR_ALL(b->flags);
2670
2671 for (j = 0; j < nflags; j++) {
2672 sval = slist[j];
2673 if (strcmp(sval, "") == 0) {
2674 continue;
2675 }
2679 "\"%s\" improvement \"%s\": bad flag name \"%s\".",
2680 filename, improvement_rule_name(b), sval);
2681 ok = FALSE;
2682 break;
2683 } else {
2684 BV_SET(b->flags, ival);
2685 }
2686 }
2687 free(slist);
2688
2689 if (!ok) {
2690 break;
2691 }
2692
2694
2695 {
2696 struct requirement_vector *obs_reqs
2697 = lookup_req_list(file, sec_name, "obsolete_by",
2699
2700 if (obs_reqs == NULL) {
2701 ok = FALSE;
2702 break;
2703 } else {
2704 requirement_vector_copy(&b->obsolete_by, obs_reqs);
2705 }
2706 }
2707
2708 if (!secfile_lookup_int(file, &b->build_cost,
2709 "%s.build_cost", sec_name)
2710 || !secfile_lookup_int(file, &b->upkeep,
2711 "%s.upkeep", sec_name)
2712 || !secfile_lookup_int(file, &b->sabotage,
2713 "%s.sabotage", sec_name)) {
2715 ok = FALSE;
2716 break;
2717 }
2718
2721 "%s.graphic", sec_name));
2724 "%s.graphic_alt", sec_name));
2727 "%s.graphic_alt2", sec_name));
2728
2731 "%s.sound", sec_name));
2734 "%s.sound_alt", sec_name));
2737 "%s.sound_alt2", sec_name));
2738 b->helptext = lookup_strvec(file, sec_name, "helptext");
2739 }
2740 }
2741
2743 if (ok) {
2745 }
2746
2747 return ok;
2748}
2749
2750/**********************************************************************/
2754static bool load_terrain_names(struct section_file *file,
2755 struct rscompat_info *compat)
2756{
2757 int nval = 0;
2758 struct section_list *sec = NULL;
2759 const char *flag;
2760 int i;
2761 const char *filename = secfile_name(file);
2762 bool ok = TRUE;
2763
2764 if (!rscompat_check_cap_and_version(file, filename, compat)) {
2765 return FALSE;
2766 }
2767
2768 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
2769 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
2770
2771 /* User terrain flag names */
2772 for (i = 0; (flag = secfile_lookup_str_default(file, NULL, "control.flags%d.name", i)) ;
2773 i++) {
2774 const char *helptxt = secfile_lookup_str_default(file, NULL, "control.flags%d.helptxt",
2775 i);
2776
2780 "\"%s\": Duplicate terrain flag name '%s'",
2781 filename, flag);
2782 ok = FALSE;
2783 break;
2784 }
2785 if (i > MAX_NUM_USER_TER_FLAGS) {
2787 "\"%s\": Too many user terrain flags!",
2788 filename);
2789 ok = FALSE;
2790 break;
2791 }
2792
2793 set_user_terrain_flag_name(TER_USER_1 + i, flag, helptxt);
2794 }
2795
2796 if (ok) {
2797 /* Blank the remaining terrain user flag slots. */
2798 for (; i < MAX_NUM_USER_TER_FLAGS; i++) {
2800 }
2801 }
2802
2803 /* User extra flag names */
2804 for (i = 0;
2805 (flag = secfile_lookup_str_default(file, NULL,
2806 "control.extra_flags%d.name",
2807 i));
2808 i++) {
2809 const char *helptxt = secfile_lookup_str_default(file, NULL,
2810 "control.extra_flags%d.helptxt", i);
2811
2813 != extra_flag_id_invalid()) {
2815 "\"%s\": Duplicate extra flag name '%s'",
2816 filename, flag);
2817 ok = FALSE;
2818 break;
2819 }
2822 "\"%s\": Too many user extra flags!",
2823 filename);
2824 ok = FALSE;
2825 break;
2826 }
2827
2828 set_user_extra_flag_name(EF_USER_FLAG_1 + i, flag, helptxt);
2829 }
2830
2831 if (ok) {
2832 /* Blank the remaining extra user flag slots. */
2833 for (; i < MAX_NUM_USER_EXTRA_FLAGS; i++) {
2835 }
2836
2837 /* Terrain names */
2838
2840 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
2842 "\"%s\": ruleset doesn't have any terrains.",
2843 filename);
2844 ok = FALSE;
2845 } else {
2846 if (nval > MAX_NUM_TERRAINS) {
2848 "\"%s\": Too many terrains (%d, max %d)",
2849 filename, nval, MAX_NUM_TERRAINS);
2850 ok = FALSE;
2851 }
2852 }
2853 }
2854
2855 if (ok) {
2857
2858 /* Avoid re-reading files */
2859 if (terrain_sections) {
2861 }
2863
2864 terrain_type_iterate(pterrain) {
2865 const int terri = terrain_index(pterrain);
2866 const char *sec_name = section_name(section_list_get(sec, terri));
2867
2868 if (!ruleset_load_names(&pterrain->name, NULL, file, sec_name)) {
2869 ok = FALSE;
2870 break;
2871 }
2872
2875 }
2876
2878 sec = NULL;
2879
2880 /* Extra names */
2881
2882 if (ok) {
2884 nval = (NULL != sec ? section_list_size(sec) : 0);
2885 if (nval > MAX_EXTRA_TYPES) {
2887 "\"%s\": Too many extra types (%d, max %d)",
2888 filename, nval, MAX_EXTRA_TYPES);
2889 ok = FALSE;
2890 }
2891 }
2892
2893 if (ok) {
2894 int idx;
2895
2897
2898 if (extra_sections) {
2900 }
2902
2903 if (ok) {
2904 for (idx = 0; idx < nval; idx++) {
2905 const char *sec_name = section_name(section_list_get(sec, idx));
2906 struct extra_type *pextra = extra_by_number(idx);
2907
2908 if (!ruleset_load_names(&pextra->name, NULL, file, sec_name)) {
2909 ok = FALSE;
2910 break;
2911 }
2913 }
2914 }
2915 }
2916
2918 sec = NULL;
2919
2920 /* Base names */
2921
2922 if (ok) {
2924 nval = (NULL != sec ? section_list_size(sec) : 0);
2925 if (nval > MAX_EXTRA_TYPES) {
2927 "\"%s\": Too many base types (%d, max %d)",
2928 filename, nval, MAX_EXTRA_TYPES);
2929 ok = FALSE;
2930 }
2931
2933 }
2934
2935 if (ok) {
2936 int idx;
2937
2938 if (base_sections) {
2940 }
2942
2943 /* Cannot use base_type_iterate() before bases are added to
2944 * EC_BASE caused_by list. Have to get them by extra_type_by_rule_name() */
2945 for (idx = 0; idx < nval; idx++) {
2946 const char *sec_name = section_name(section_list_get(sec, idx));
2947 const char *base_name = secfile_lookup_str(file, "%s.extra", sec_name);
2948
2949 if (base_name != NULL) {
2951
2952 if (pextra != NULL) {
2953 base_type_init(pextra, idx);
2955 } else {
2957 "No extra definition matching base definition \"%s\"",
2958 base_name);
2959 ok = FALSE;
2960 }
2961 } else {
2963 "Base section \"%s\" does not associate base with any extra",
2964 sec_name);
2965 ok = FALSE;
2966 }
2967 }
2968 }
2969
2971 sec = NULL;
2972
2973 /* Road names */
2974
2975 if (ok) {
2977 nval = (NULL != sec ? section_list_size(sec) : 0);
2978 if (nval > MAX_EXTRA_TYPES) {
2980 "\"%s\": Too many road types (%d, max %d)",
2981 filename, nval, MAX_EXTRA_TYPES);
2982 ok = FALSE;
2983 }
2984
2986 }
2987
2988 if (ok) {
2989 int idx;
2990
2991 if (road_sections) {
2993 }
2995
2996 /* Cannot use extra_type_by_cause_iterate(EC_ROAD) before roads are added to
2997 * EC_ROAD caused_by list. Have to get them by extra_type_by_rule_name() */
2998 for (idx = 0; idx < nval; idx++) {
2999 const char *sec_name = section_name(section_list_get(sec, idx));
3000 const char *road_name = secfile_lookup_str(file, "%s.extra", sec_name);
3001
3002 if (road_name != NULL) {
3004
3005 if (pextra != NULL) {
3006 road_type_init(pextra, idx);
3008 } else {
3010 "No extra definition matching road definition \"%s\"",
3011 road_name);
3012 ok = FALSE;
3013 }
3014 } else {
3016 "Road section \"%s\" does not associate road with any extra",
3017 sec_name);
3018 ok = FALSE;
3019 }
3020 }
3021 }
3022
3024 sec = NULL;
3025
3026 /* Resource names */
3027 if (ok) {
3029 nval = (NULL != sec ? section_list_size(sec) : 0);
3030 if (nval > MAX_EXTRA_TYPES) {
3032 "\"%s\": Too many resource types (%d, max %d)",
3033 filename, nval, MAX_EXTRA_TYPES);
3034 ok = FALSE;
3035 }
3036
3038 }
3039
3040 if (ok) {
3041 int idx;
3042
3043 if (resource_sections) {
3045 }
3047
3048 /* Cannot use resource_type_iterate() before resource are added to
3049 * EC_RESOURCE caused_by list. Have to get them by extra_type_by_rule_name() */
3050 for (idx = 0; idx < nval; idx++) {
3051 const char *sec_name = section_name(section_list_get(sec, idx));
3052 const char *resource_name;
3053 struct extra_type *pextra = NULL;
3054
3056
3057 if (resource_name != NULL) {
3059
3060 if (pextra != NULL) {
3061 resource_type_init(pextra);
3063 } else {
3065 "No extra definition matching resource definition \"%s\"",
3067 ok = FALSE;
3068 }
3069 } else {
3071 "Resource section %s does not list extra this resource belongs to.",
3072 sec_name);
3073 ok = FALSE;
3074 }
3075 }
3076 }
3077
3079 sec = nullptr;
3080
3081 /* Tiledef names */
3082
3083 if (ok) {
3085 nval = (NULL != sec ? section_list_size(sec) : 0);
3086 if (nval > MAX_TILEDEFS) {
3088 "\"%s\": Too many tiledefs (%d, max %d)",
3089 filename, nval, MAX_TILEDEFS);
3090 ok = FALSE;
3091 }
3092 }
3093
3094 if (ok) {
3095 int idx;
3096
3098
3099 if (tiledef_sections) {
3101 }
3103
3104 if (ok) {
3105 for (idx = 0; idx < nval; idx++) {
3106 const char *sec_name = section_name(section_list_get(sec, idx));
3107 struct tiledef *td = tiledef_by_number(idx);
3108
3109 if (!ruleset_load_names(&td->name, NULL, file, sec_name)) {
3110 ok = FALSE;
3111 break;
3112 }
3114 }
3115 }
3116 }
3117
3119
3120 return ok;
3121}
3122
3123/**********************************************************************/
3126static bool load_ruleset_terrain(struct section_file *file,
3127 struct rscompat_info *compat)
3128{
3129 size_t nval, nval2;
3130 int j;
3131 bool compat_road = FALSE;
3132 bool compat_rail = FALSE;
3133 bool compat_river = FALSE;
3134 const char **res;
3135 const char *filename = secfile_name(file);
3136 const char *text;
3137 int *res_freq;
3138 bool ok = TRUE;
3139
3140 /* parameters */
3141
3142 terrain_control.ocean_reclaim_requirement_pct
3143 = secfile_lookup_int_default(file, 101,
3144 "parameters.ocean_reclaim_requirement");
3145 terrain_control.land_channel_requirement_pct
3146 = secfile_lookup_int_default(file, 101,
3147 "parameters.land_channel_requirement");
3148 terrain_control.terrain_thaw_requirement_pct
3149 = secfile_lookup_int_default(file, 101,
3150 "parameters.thaw_requirement");
3151 terrain_control.terrain_freeze_requirement_pct
3152 = secfile_lookup_int_default(file, 101,
3153 "parameters.freeze_requirement");
3154 terrain_control.lake_max_size
3156 "parameters.lake_max_size");
3157 terrain_control.min_start_native_area
3159 "parameters.min_start_native_area");
3160 terrain_control.move_fragments
3162 "parameters.move_fragments");
3163 if (terrain_control.move_fragments < 1) {
3165 "\"%s\": move_fragments must be at least 1",
3166 filename);
3167 ok = FALSE;
3168 }
3170 terrain_control.igter_cost
3172 "parameters.igter_cost");
3173 if (terrain_control.igter_cost < 1) {
3175 "\"%s\": igter_cost must be at least 1",
3176 filename);
3177 ok = FALSE;
3178 }
3179 terrain_control.infrapoints = FALSE; /* This will be updated if we find
3180 * an placeable extra. */
3181
3182 terrain_control.pythagorean_diagonal
3184 "parameters.pythagorean_diagonal");
3185
3188 "parameters.ocean_resources");
3189
3190 text = secfile_lookup_str_default(file,
3191 N_("?gui_type:Build Type A Base"),
3192 "extraui.ui_name_base_fortress");
3193 sz_strlcpy(terrain_control.gui_type_base0, text);
3194
3195 text = secfile_lookup_str_default(file,
3196 N_("?gui_type:Build Type B Base"),
3197 "extraui.ui_name_base_airbase");
3198 sz_strlcpy(terrain_control.gui_type_base1, text);
3199
3200 if (ok) {
3201 /* Terrain details */
3202
3203 terrain_type_iterate(pterrain) {
3204 const char **slist;
3205 const int i = terrain_index(pterrain);
3206 const char *tsection = &terrain_sections[i * MAX_SECTION_LABEL];
3207 const char *cstr;
3208 const char *ename;
3209
3210 sz_strlcpy(pterrain->graphic_str,
3211 secfile_lookup_str(file, "%s.graphic", tsection));
3212 sz_strlcpy(pterrain->graphic_alt,
3214 "%s.graphic_alt", tsection));
3215 sz_strlcpy(pterrain->graphic_alt2,
3217 "%s.graphic_alt2", tsection));
3218
3219 pterrain->identifier
3220 = secfile_lookup_str(file, "%s.identifier", tsection)[0];
3221 if ('\0' == pterrain->identifier) {
3223 "\"%s\" [%s] identifier missing value.",
3224 filename, tsection);
3225 ok = FALSE;
3226 break;
3227 }
3228 if (TERRAIN_UNKNOWN_IDENTIFIER == pterrain->identifier) {
3230 "\"%s\" [%s] cannot use '%c' as an identifier;"
3231 " it is reserved for unknown terrain.",
3232 filename, tsection, pterrain->identifier);
3233 ok = FALSE;
3234 break;
3235 }
3236 for (j = T_FIRST; j < i; j++) {
3237 if (pterrain->identifier == terrain_by_number(j)->identifier) {
3239 "\"%s\" [%s] has the same identifier as [%s].",
3240 filename, tsection,
3242 ok = FALSE;
3243 break;
3244 }
3245 }
3246
3247 if (!ok) {
3248 break;
3249 }
3250
3251 cstr = secfile_lookup_str(file, "%s.class", tsection);
3252 pterrain->tclass = terrain_class_by_name(cstr, fc_strcasecmp);
3253 if (!terrain_class_is_valid(pterrain->tclass)) {
3255 "\"%s\": [%s] unknown class \"%s\"",
3256 filename, tsection, cstr);
3257 ok = FALSE;
3258 break;
3259 }
3260
3261 if (!secfile_lookup_int(file, &pterrain->movement_cost,
3262 "%s.movement_cost", tsection)
3263 || !secfile_lookup_int(file, &pterrain->defense_bonus,
3264 "%s.defense_bonus", tsection)) {
3266 ok = FALSE;
3267 break;
3268 }
3269
3271 pterrain->output[o]
3272 = secfile_lookup_int_default(file, 0, "%s.%s", tsection,
3275
3276 res = secfile_lookup_str_vec(file, &nval, "%s.resources", tsection);
3278 "%s.resource_freq", tsection);
3279 if (nval2 > 0 && nval2 != nval) {
3281 "\"%s\": [%s] Different lengths for resources "
3282 "and resource frequencies",
3283 filename, tsection);
3284 ok = FALSE;
3285 }
3286 pterrain->resources = fc_calloc(nval + 1, sizeof(*pterrain->resources));
3287 pterrain->resource_freq = fc_calloc(nval + 1,
3288 sizeof(*pterrain->resource_freq));
3289 for (j = 0; j < nval; j++) {
3290 pterrain->resources[j] = lookup_resource(filename, res[j], tsection);
3291 if (pterrain->resources[j] == NULL) {
3292 ok = FALSE;
3293 break;
3294 }
3295 pterrain->resource_freq[j] = j < nval2
3296 ? res_freq[j]
3298 if (pterrain->resource_freq[j] < RESOURCE_FREQUENCY_MINIMUM
3299 || pterrain->resource_freq[j] > RESOURCE_FREQUENCY_MAXIMUM) {
3301 "\"%s\": [%s] Resource frequency '%d' "
3302 "outside allowed range",
3303 filename, tsection,
3304 pterrain->resource_freq[j]);
3305 ok = FALSE;
3306 break;
3307 }
3308 }
3309 pterrain->resources[nval] = NULL;
3310 /* Terminating zero technically not necessary */
3311 pterrain->resource_freq[nval] = 0;
3312 free(res);
3313 res = NULL;
3314 free(res_freq);
3315 res_freq = NULL;
3316
3317 if (!ok) {
3318 break;
3319 }
3320
3322 pterrain->road_output_incr_pct[o]
3323 = secfile_lookup_int_default(file, 0, "%s.road_%s_incr_pct",
3326
3327 if (!lookup_time(file, &pterrain->base_time, tsection, "base_time",
3328 filename, NULL, &ok)
3329 || !lookup_time(file, &pterrain->road_time, tsection, "road_time",
3330 filename, NULL, &ok)) {
3332 ok = FALSE;
3333 break;
3334 }
3335
3336 if (!lookup_terrain(file, "cultivate_result", filename, pterrain,
3337 &pterrain->cultivate_result, FALSE)) {
3338 ruleset_error(NULL, LOG_ERROR, "%s: No cultivate_result", tsection);
3339 ok = FALSE;
3340 break;
3341 }
3342 if (pterrain->cultivate_result == pterrain) {
3344 "%s: Cultivating result in terrain itself.",
3345 tsection);
3346 ok = FALSE;
3347 break;
3348 }
3349 if (!secfile_lookup_int(file, &pterrain->irrigation_food_incr,
3350 "%s.irrigation_food_incr", tsection)
3351 || !lookup_time(file, &pterrain->irrigation_time,
3352 tsection, "irrigation_time", filename, NULL, &ok)) {
3354 ok = FALSE;
3355 break;
3356 }
3357
3358 if (!lookup_terrain(file, "plant_result", filename, pterrain,
3359 &pterrain->plant_result, FALSE)) {
3360 ruleset_error(NULL, LOG_ERROR, "%s: No plant_result", tsection);
3361 ok = FALSE;
3362 break;
3363 }
3364 if (pterrain->plant_result == pterrain) {
3366 "%s: Planting result in terrain itself.",
3367 tsection);
3368 ok = FALSE;
3369 break;
3370 }
3371 if (!secfile_lookup_int(file, &pterrain->mining_shield_incr,
3372 "%s.mining_shield_incr", tsection)
3373 || !lookup_time(file, &pterrain->mining_time,
3374 tsection, "mining_time", filename, NULL, &ok)) {
3376 ok = FALSE;
3377 break;
3378 }
3379
3380 if (!lookup_time(file, &pterrain->cultivate_time,
3381 tsection, "cultivate_time", filename, NULL, &ok)) {
3383 "%s: Missing cultivate_time", tsection);
3384 ok = FALSE;
3385 break;
3386 }
3387 if ((pterrain->cultivate_result != NULL
3388 && pterrain->cultivate_time <= 0)
3389 || (pterrain->cultivate_result == NULL
3390 && pterrain->cultivate_time > 0)) {
3392 "%s: cultivate_result and cultivate_time disagree "
3393 "whether cultivating is enabled", tsection);
3394 ok = FALSE;
3395 break;
3396 }
3397
3398 if (!lookup_time(file, &pterrain->plant_time,
3399 tsection, "plant_time", filename, NULL, &ok)) {
3401 "%s: Missing plant_time", tsection);
3402 ok = FALSE;
3403 break;
3404 }
3405 if ((pterrain->plant_result != NULL
3406 && pterrain->plant_time <= 0)
3407 || (pterrain->plant_result == NULL
3408 && pterrain->plant_time > 0)) {
3410 "%s: plant_result and plant_time disagree "
3411 "whether planting is enabled", tsection);
3412 ok = FALSE;
3413 break;
3414 }
3415
3416 if (!lookup_unit_type(file, tsection, "animal",
3417 &pterrain->animal, filename,
3418 rule_name_get(&pterrain->name))) {
3419 ok = FALSE;
3420 break;
3421 }
3422
3423 if (!lookup_terrain(file, "transform_result", filename, pterrain,
3424 &pterrain->transform_result, TRUE)) {
3425 ok = FALSE;
3426 break;
3427 }
3428 if (!lookup_time(file, &pterrain->transform_time,
3429 tsection, "transform_time", filename, NULL, &ok)) {
3431 ok = FALSE;
3432 break;
3433 }
3434 if ((pterrain->transform_result != NULL
3435 && pterrain->transform_time <= 0)
3436 || (pterrain->transform_result == NULL
3437 && pterrain->transform_time > 0)) {
3439 "%s: transform_result and transform_time disagree "
3440 "whether transforming is enabled", tsection);
3441 ok = FALSE;
3442 break;
3443 }
3444
3445 pterrain->placing_time = 1; /* Default */
3446 lookup_time(file, &pterrain->placing_time,
3447 tsection, "placing_time", filename, NULL, &ok);
3448
3449 pterrain->pillage_time = 1; /* Default */
3450 lookup_time(file, &pterrain->pillage_time,
3451 tsection, "pillage_time", filename, NULL, &ok);
3452
3453 if (!lookup_terrain(file, "warmer_wetter_result", filename, pterrain,
3454 &pterrain->warmer_wetter_result, TRUE)
3455 || !lookup_terrain(file, "warmer_drier_result", filename, pterrain,
3456 &pterrain->warmer_drier_result, TRUE)
3457 || !lookup_terrain(file, "cooler_wetter_result", filename, pterrain,
3458 &pterrain->cooler_wetter_result, TRUE)
3459 || !lookup_terrain(file, "cooler_drier_result", filename, pterrain,
3460 &pterrain->cooler_drier_result, TRUE)) {
3461 ok = FALSE;
3462 break;
3463 }
3464
3465 /* Set default removal times */
3466 extra_type_iterate(pextra) {
3467 pterrain->extra_removal_times[extra_index(pextra)] = 0;
3469
3470 for (j = 0; (ename = secfile_lookup_str_default(file, NULL,
3471 "%s.extra_settings%d.extra",
3472 tsection, j)); j++) {
3473 const struct extra_type *pextra = extra_type_by_rule_name(ename);
3474
3475 if (pextra != NULL) {
3476 char time_sections[512];
3477
3479 "%s.extra_settings%d", tsection, j);
3480
3481 lookup_time(file, &pterrain->extra_removal_times[extra_index(pextra)],
3482 time_sections, "removal_time", filename, NULL, &ok);
3483 } else {
3485 "\"%s\" [%s] has settings for unknown extra \"%s\".",
3486 filename, tsection, ename);
3487 ok = FALSE;
3488 break;
3489 }
3490 }
3491
3492 if (ok) {
3493 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", tsection);
3494 BV_CLR_ALL(pterrain->flags);
3495 for (j = 0; j < nval; j++) {
3496 const char *sval = slist[j];
3497 enum terrain_flag_id flag
3499
3500 if (!terrain_flag_id_is_valid(flag)) {
3502 "\"%s\" [%s] has unknown flag \"%s\".",
3503 filename, tsection, sval);
3504 ok = FALSE;
3505 break;
3506 } else {
3507 BV_SET(pterrain->flags, flag);
3508 }
3509 }
3510
3511 free(slist);
3512 }
3513
3514 if (!ok) {
3515 break;
3516 }
3517
3518 {
3520
3524 pterrain->property[mtp]
3525 = secfile_lookup_int_default(file, 0, "%s.property_%s", tsection,
3527 }
3528 }
3529
3530 slist = secfile_lookup_str_vec(file, &nval, "%s.native_to", tsection);
3531 BV_CLR_ALL(pterrain->native_to);
3532 for (j = 0; j < nval; j++) {
3533 struct unit_class *class = unit_class_by_rule_name(slist[j]);
3534
3535 if (!class) {
3537 "\"%s\" [%s] is native to unknown unit class \"%s\".",
3538 filename, tsection, slist[j]);
3539 ok = FALSE;
3540 break;
3541 } else {
3542 BV_SET(pterrain->native_to, uclass_index(class));
3543 }
3544 }
3545 free(slist);
3546
3547 if (!ok) {
3548 break;
3549 }
3550
3551 /* Get terrain color */
3552 {
3553 fc_assert_ret_val(pterrain->rgb == NULL, FALSE);
3554
3555 if (!rgbcolor_load(file, &pterrain->rgb, "%s.color", tsection)) {
3557 "Missing terrain color definition: %s",
3558 secfile_error());
3559 ok = FALSE;
3560 break;
3561 }
3562 }
3563
3564 pterrain->helptext = lookup_strvec(file, tsection, "helptext");
3566 }
3567
3568 if (ok) {
3569 /* Extra details */
3570 extra_type_iterate(pextra) {
3571 BV_CLR_ALL(pextra->conflicts);
3573
3574 extra_type_iterate(pextra) {
3575 int eidx = extra_index(pextra);
3576 const char *section = &extra_sections[eidx * MAX_SECTION_LABEL];
3577 const char **slist;
3578 struct requirement_vector *reqs;
3579 const char *catname;
3580 int cj;
3581 enum extra_cause cause;
3583 const char *eus_name;
3584 const char *vis_req_name;
3585 const struct advance *vis_req;
3586
3587 catname = secfile_lookup_str(file, "%s.category", section);
3588 if (catname == NULL) {
3590 "\"%s\" extra \"%s\" has no category.",
3591 filename, extra_rule_name(pextra));
3592 ok = FALSE;
3593 break;
3594 }
3595 pextra->category = extra_category_by_name(catname, fc_strcasecmp);
3596 if (!extra_category_is_valid(pextra->category)) {
3598 "\"%s\" extra \"%s\" has invalid category \"%s\".",
3599 filename, extra_rule_name(pextra), catname);
3600 ok = FALSE;
3601 break;
3602 }
3603
3604 slist = secfile_lookup_str_vec(file, &nval, "%s.causes", section);
3605 pextra->causes = 0;
3606 for (cj = 0; cj < nval; cj++) {
3607 const char *sval = slist[cj];
3609
3610 if (!extra_cause_is_valid(cause)) {
3612 "\"%s\" extra \"%s\": unknown cause \"%s\".",
3613 filename, extra_rule_name(pextra), sval);
3614 ok = FALSE;
3615 break;
3616 } else {
3617 pextra->causes |= (1 << cause);
3618 extra_to_caused_by_list(pextra, cause);
3619 }
3620 }
3621
3622 if (pextra->causes == 0) {
3623 /* Extras that do not have any causes added to EC_NONE list */
3625 }
3626
3627 if (!is_extra_caused_by(pextra, EC_BASE)
3628 && !is_extra_caused_by(pextra, EC_ROAD)
3629 && !is_extra_caused_by(pextra, EC_RESOURCE)) {
3630 /* Not a base, road, nor resource, so special */
3631 pextra->data.special_idx = extra_type_list_size(extra_type_list_by_cause(EC_SPECIAL));
3633 }
3634
3635 free(slist);
3636
3637 slist = secfile_lookup_str_vec(file, &nval, "%s.rmcauses", section);
3638 pextra->rmcauses = 0;
3639 for (j = 0; j < nval; j++) {
3640 const char *sval = slist[j];
3641
3643
3646 "\"%s\" extra \"%s\": unknown rmcause \"%s\".",
3647 filename, extra_rule_name(pextra), sval);
3648 ok = FALSE;
3649 break;
3650 } else {
3651 pextra->rmcauses |= (1 << rmcause);
3653 }
3654 }
3655
3656 free(slist);
3657
3658 sz_strlcpy(pextra->activity_gfx,
3660 "%s.activity_gfx", section));
3661 sz_strlcpy(pextra->act_gfx_alt,
3663 "%s.act_gfx_alt", section));
3664 sz_strlcpy(pextra->act_gfx_alt2,
3666 "%s.act_gfx_alt2", section));
3667 sz_strlcpy(pextra->rmact_gfx,
3669 "%s.rmact_gfx", section));
3670 sz_strlcpy(pextra->rmact_gfx_alt,
3672 "%s.rmact_gfx_alt", section));
3673 sz_strlcpy(pextra->rmact_gfx_alt2,
3675 "%s.rmact_gfx_alt2", section));
3676 sz_strlcpy(pextra->graphic_str,
3677 secfile_lookup_str_default(file, "-", "%s.graphic", section));
3678 sz_strlcpy(pextra->graphic_alt,
3680 "%s.graphic_alt", section));
3681
3682 reqs = lookup_req_list(file, section, "reqs", extra_rule_name(pextra));
3683 if (reqs == NULL) {
3684 ok = FALSE;
3685 break;
3686 }
3687 requirement_vector_copy(&pextra->reqs, reqs);
3688
3689 reqs = lookup_req_list(file, section, "rmreqs", extra_rule_name(pextra));
3690 if (reqs == NULL) {
3691 ok = FALSE;
3692 break;
3693 }
3694 requirement_vector_copy(&pextra->rmreqs, reqs);
3695
3696 reqs = lookup_req_list(file, section, "appearance_reqs", extra_rule_name(pextra));
3697 if (reqs == NULL) {
3698 ok = FALSE;
3699 break;
3700 }
3701 requirement_vector_copy(&pextra->appearance_reqs, reqs);
3702
3703 reqs = lookup_req_list(file, section, "disappearance_reqs", extra_rule_name(pextra));
3704 if (reqs == NULL) {
3705 ok = FALSE;
3706 break;
3707 }
3708 requirement_vector_copy(&pextra->disappearance_reqs, reqs);
3709
3710 pextra->buildable = secfile_lookup_bool_default(file,
3712 "%s.buildable", section);
3713 pextra->generated = secfile_lookup_bool_default(file, TRUE,
3714 "%s.generated", section);
3715
3716 pextra->build_time = 0; /* default */
3717 lookup_time(file, &pextra->build_time, section, "build_time",
3718 filename, extra_rule_name(pextra), &ok);
3719 pextra->build_time_factor = secfile_lookup_int_default(file, 1,
3720 "%s.build_time_factor", section);
3721 pextra->removal_time = 0; /* default */
3722 lookup_time(file, &pextra->removal_time, section, "removal_time",
3723 filename, extra_rule_name(pextra), &ok);
3724 pextra->removal_time_factor = secfile_lookup_int_default(file, 1,
3725 "%s.removal_time_factor", section);
3726 pextra->infracost = secfile_lookup_int_default(file, 0,
3727 "%s.infracost", section);
3728 if (pextra->infracost > 0) {
3729 terrain_control.infrapoints = TRUE;
3730 }
3731
3732 pextra->defense_bonus = secfile_lookup_int_default(file, 0,
3733 "%s.defense_bonus",
3734 section);
3735 if (pextra->defense_bonus != 0) {
3736 if (extra_has_flag(pextra, EF_NATURAL_DEFENSE)) {
3738 } else {
3740 }
3741 }
3742
3743 eus_name = secfile_lookup_str_default(file, "Normal", "%s.unit_seen", section);
3745 if (!extra_unit_seen_type_is_valid(pextra->eus)) {
3747 "\"%s\" extra \"%s\" has illegal unit_seen value \"%s\".",
3748 filename, extra_rule_name(pextra), eus_name);
3749 ok = FALSE;
3750 break;
3751 }
3752 if (pextra->eus == EUS_HIDDEN) {
3754 }
3755
3756 pextra->appearance_chance = secfile_lookup_int_default(file, RS_DEFAULT_EXTRA_APPEARANCE,
3757 "%s.appearance_chance",
3758 section);
3759 pextra->disappearance_chance = secfile_lookup_int_default(file,
3761 "%s.disappearance_chance",
3762 section);
3763
3764 pextra->no_aggr_near_city = secfile_lookup_int_default(file, -1,
3765 "%s.no_aggr_near_city",
3766 section);
3767
3768 slist = secfile_lookup_str_vec(file, &nval, "%s.native_to", section);
3769 BV_CLR_ALL(pextra->native_to);
3770 for (j = 0; j < nval; j++) {
3771 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
3772
3773 if (uclass == NULL) {
3775 "\"%s\" extra \"%s\" is native to unknown unit class \"%s\".",
3776 filename, extra_rule_name(pextra), slist[j]);
3777 ok = FALSE;
3778 break;
3779 } else {
3780 BV_SET(pextra->native_to, uclass_index(uclass));
3781 }
3782 }
3783 free(slist);
3784
3785 if (!ok) {
3786 break;
3787 }
3788
3789 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", section);
3790 BV_CLR_ALL(pextra->flags);
3791 for (j = 0; j < nval; j++) {
3792 const char *sval = slist[j];
3793 enum extra_flag_id flag;
3794
3796
3797 if (!extra_flag_id_is_valid(flag)) {
3799 "\"%s\" extra \"%s\": unknown flag \"%s\".",
3800 filename, extra_rule_name(pextra), sval);
3801 ok = FALSE;
3802 break;
3803 } else {
3804 BV_SET(pextra->flags, flag);
3805 }
3806 }
3807 free(slist);
3808
3809 if (pextra->no_aggr_near_city >= 0) {
3811 }
3812
3813 if (extra_has_flag(pextra, EF_CAUSE_ZOC)) {
3815 }
3816
3817 if (!ok) {
3818 break;
3819 }
3820
3821 slist = secfile_lookup_str_vec(file, &nval, "%s.conflicts", section);
3822 for (j = 0; j < nval; j++) {
3823 const char *sval = slist[j];
3825
3826 if (pextra2 == NULL) {
3828 "\"%s\" extra \"%s\": unknown conflict extra \"%s\".",
3829 filename, extra_rule_name(pextra), sval);
3830 ok = FALSE;
3831 break;
3832 } else {
3833 BV_SET(pextra->conflicts, extra_index(pextra2));
3834 BV_SET(pextra2->conflicts, extra_index(pextra));
3835 }
3836 }
3837
3838 free(slist);
3839
3840 if (!ok) {
3841 break;
3842 }
3843
3844 slist = secfile_lookup_str_vec(file, &nval, "%s.hidden_by", section);
3845 BV_CLR_ALL(pextra->hidden_by);
3846 for (j = 0; j < nval; j++) {
3847 const char *sval = slist[j];
3848 const struct extra_type *top = extra_type_by_rule_name(sval);
3849
3850 if (top == NULL) {
3852 "\"%s\" extra \"%s\" hidden by unknown extra \"%s\".",
3853 filename, extra_rule_name(pextra), sval);
3854 ok = FALSE;
3855 break;
3856 } else {
3857 BV_SET(pextra->hidden_by, extra_index(top));
3858 }
3859 }
3860 free(slist);
3861
3862 if (!ok) {
3863 break;
3864 }
3865
3866 slist = secfile_lookup_str_vec(file, &nval, "%s.bridged_over", section);
3867 BV_CLR_ALL(pextra->bridged_over);
3868 for (j = 0; j < nval; j++) {
3869 const char *sval = slist[j];
3870 const struct extra_type *top = extra_type_by_rule_name(sval);
3871
3872 if (top == NULL) {
3874 "\"%s\" extra \"%s\" bridged over unknown extra \"%s\".",
3875 filename, extra_rule_name(pextra), sval);
3876 ok = FALSE;
3877 break;
3878 } else {
3879 BV_SET(pextra->bridged_over, extra_index(top));
3880 }
3881 }
3882 free(slist);
3883
3884 if (!ok) {
3885 break;
3886 }
3887
3889 "%s.visibility_req", section);
3891
3892 if (vis_req == NULL) {
3894 "\"%s\" %s: unknown visibility_req %s.",
3895 filename, section, vis_req_name);
3896 ok = FALSE;
3897 break;
3898 }
3899
3900 pextra->visibility_req = advance_number(vis_req);
3901
3902 pextra->helptext = lookup_strvec(file, section, "helptext");
3904 }
3905
3906 if (ok) {
3907 int i = 0;
3908 /* Resource details */
3909
3911 char identifier[MAX_LEN_NAME];
3912 const char *id;
3914
3915 if (!presource->data.resource) {
3917 "\"%s\" extra \"%s\" has \"Resource\" cause but no "
3918 "corresponding [resource_*] section",
3919 filename, extra_rule_name(presource));
3920 ok = FALSE;
3921 break;
3922 }
3923
3925 presource->data.resource->output[o] =
3926 secfile_lookup_int_default(file, 0, "%s.%s", rsection,
3929
3930 id = secfile_lookup_str_default(file, NULL, "%s.identifier", rsection);
3931
3932 if (id == NULL) {
3933 presource->data.resource->id_old_save = '\0';
3934 } else {
3935 sz_strlcpy(identifier, id);
3936
3937 presource->data.resource->id_old_save = identifier[0];
3938 if (RESOURCE_NULL_IDENTIFIER == presource->data.resource->id_old_save) {
3940 "\"%s\" [%s] identifier missing value.",
3941 filename, rsection);
3942 ok = FALSE;
3943 break;
3944 }
3945 if (RESOURCE_NONE_IDENTIFIER == presource->data.resource->id_old_save) {
3947 "\"%s\" [%s] cannot use '%c' as an identifier;"
3948 " it is reserved.",
3949 filename, rsection, presource->data.resource->id_old_save);
3950 ok = FALSE;
3951 break;
3952 }
3953 }
3954
3955 if (!ok) {
3956 break;
3957 }
3958
3959 i++;
3961
3962 for (j = 0; ok && j < game.control.num_resource_types; j++) {
3963 const char *section = &resource_sections[j * MAX_SECTION_LABEL];
3964 const char *extra_name = secfile_lookup_str(file, "%s.extra", section);
3966
3967 if (!is_extra_caused_by(pextra, EC_RESOURCE)) {
3969 "\"%s\" resource section [%s]: extra \"%s\" does not "
3970 "have \"Resource\" in its causes",
3971 filename, section, extra_name);
3972 ok = FALSE;
3973 }
3974 }
3975 }
3976
3977 if (ok) {
3978 /* This can't be part of previous loop as we don't want random data from previous
3979 * ruleset to play havoc on us when we have only some resource identifiers loaded
3980 * from the new ruleset. */
3982 if (pres->data.resource->id_old_save != '\0') {
3984 if (pres->data.resource->id_old_save == pres2->data.resource->id_old_save
3985 && pres != pres2) {
3987 "\"%s\" [%s] has the same identifier as [%s].",
3988 filename,
3991 ok = FALSE;
3992 break;
3993 }
3995
3996 if (!ok) {
3997 break;
3998 }
3999 }
4001 }
4002
4003 if (ok) {
4004 /* Base details */
4006 struct base_type *pbase = extra_base_get(pextra);
4007 const char *section;
4008 const char *gui_str;
4009
4010 if (!pbase) {
4012 "\"%s\" extra \"%s\" has \"Base\" cause but no "
4013 "corresponding [base_*] section",
4014 filename, extra_rule_name(pextra));
4015 ok = FALSE;
4016 break;
4017 }
4019
4020 gui_str = secfile_lookup_str(file, "%s.gui_type", section);
4022 if (!base_gui_type_is_valid(pbase->gui_type)) {
4024 "\"%s\" base \"%s\": unknown gui_type \"%s\".",
4025 filename, extra_rule_name(pextra), gui_str);
4026 ok = FALSE;
4027 break;
4028 }
4029
4030 pbase->border_sq = secfile_lookup_int_default(file, -1, "%s.border_sq",
4031 section);
4032 pbase->vision_main_sq = secfile_lookup_int_default(file, -1,
4033 "%s.vision_main_sq",
4034 section);
4035 pbase->vision_invis_sq = secfile_lookup_int_default(file, -1,
4036 "%s.vision_invis_sq",
4037 section);
4038 pbase->vision_subs_sq = secfile_lookup_int_default(file, -1,
4039 "%s.vision_subs_sq",
4040 section);
4041
4042 if (!ok) {
4043 break;
4044 }
4045
4048
4050 struct base_type *pbase2;
4051
4052 if (pextra == pextra2) {
4053 /* End of the fully initialized bases iteration. */
4054 break;
4055 }
4056
4059 BV_SET(pextra->conflicts, extra_index(pextra2));
4060 BV_SET(pextra2->conflicts, extra_index(pextra));
4061 }
4063 }
4065
4066 for (j = 0; ok && j < game.control.num_base_types; j++) {
4067 const char *section = &base_sections[j * MAX_SECTION_LABEL];
4068 const char *extra_name = secfile_lookup_str(file, "%s.extra", section);
4070
4071 if (!is_extra_caused_by(pextra, EC_BASE)) {
4073 "\"%s\" base section [%s]: extra \"%s\" does not have "
4074 "\"Base\" in its causes",
4075 filename, section, extra_name);
4076 ok = FALSE;
4077 }
4078 }
4079 }
4080
4081 if (ok) {
4083 struct road_type *proad = extra_road_get(pextra);
4084 const char *section;
4085 const char **slist;
4086 const char *special;
4087 const char *modestr;
4088 struct requirement_vector *reqs;
4089 const char *gui_str;
4090
4091 if (!proad) {
4093 "\"%s\" extra \"%s\" has \"Road\" cause but no "
4094 "corresponding [road_*] section",
4095 filename, extra_rule_name(pextra));
4096 ok = FALSE;
4097 break;
4098 }
4100
4101 gui_str = secfile_lookup_str(file, "%s.gui_type", section);
4103 if (!road_gui_type_is_valid(proad->gui_type)) {
4105 "\"%s\" road \"%s\": unknown gui_type \"%s\".",
4106 filename, extra_rule_name(pextra), gui_str);
4107 ok = FALSE;
4108 break;
4109 }
4110
4111 reqs = lookup_req_list(file, section, "first_reqs", extra_rule_name(pextra));
4112 if (reqs == NULL) {
4113 ok = FALSE;
4114 break;
4115 }
4116 requirement_vector_copy(&proad->first_reqs, reqs);
4117
4118 if (!secfile_lookup_int(file, &proad->move_cost,
4119 "%s.move_cost", section)) {
4120 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4121 ok = FALSE;
4122 break;
4123 }
4124
4125 modestr = secfile_lookup_str_default(file, "FastAlways", "%s.move_mode",
4126 section);
4128 if (!road_move_mode_is_valid(proad->move_mode)) {
4130 "Illegal move_mode \"%s\" for road \"%s\"",
4131 modestr, extra_rule_name(pextra));
4132 ok = FALSE;
4133 break;
4134 }
4135
4137 proad->tile_incr_const[o] =
4138 secfile_lookup_int_default(file, 0, "%s.%s_incr_const",
4140 proad->tile_incr[o] =
4141 secfile_lookup_int_default(file, 0, "%s.%s_incr",
4143 proad->tile_bonus[o] =
4144 secfile_lookup_int_default(file, 0, "%s.%s_bonus",
4147
4148 special = secfile_lookup_str_default(file, "None", "%s.compat_special", section);
4149 if (!fc_strcasecmp(special, "Road")) {
4150 if (compat_road) {
4152 "Multiple roads marked as compatibility \"Road\"");
4153 ok = FALSE;
4154 }
4155 compat_road = TRUE;
4156 proad->compat = ROCO_ROAD;
4157 } else if (!fc_strcasecmp(special, "Railroad")) {
4158 if (compat_rail) {
4160 "Multiple roads marked as compatibility \"Railroad\"");
4161 ok = FALSE;
4162 }
4163 compat_rail = TRUE;
4164 proad->compat = ROCO_RAILROAD;
4165 } else if (!fc_strcasecmp(special, "River")) {
4166 if (compat_river) {
4168 "Multiple roads marked as compatibility \"River\"");
4169 ok = FALSE;
4170 }
4172 proad->compat = ROCO_RIVER;
4173 } else if (!fc_strcasecmp(special, "None")) {
4174 proad->compat = ROCO_NONE;
4175 } else {
4177 "Illegal compatibility special \"%s\" for road %s",
4178 special, extra_rule_name(pextra));
4179 ok = FALSE;
4180 }
4181
4182 if (!ok) {
4183 break;
4184 }
4185
4186 slist = secfile_lookup_str_vec(file, &nval, "%s.integrates", section);
4187 BV_CLR_ALL(proad->integrates);
4188 for (j = 0; j < nval; j++) {
4189 const char *sval = slist[j];
4191 struct road_type *top = NULL;
4192
4193 if (textra != NULL) {
4194 top = extra_road_get(textra);
4195 }
4196
4197 if (top == NULL) {
4199 "\"%s\" road \"%s\" integrates with unknown road \"%s\".",
4200 filename, extra_rule_name(pextra), sval);
4201 ok = FALSE;
4202 break;
4203 } else {
4204 BV_SET(proad->integrates, road_number(top));
4205 }
4206 }
4207 free(slist);
4208
4209 if (!ok) {
4210 break;
4211 }
4212
4213 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", section);
4214 BV_CLR_ALL(proad->flags);
4215 for (j = 0; j < nval; j++) {
4216 const char *sval = slist[j];
4218
4219 if (!road_flag_id_is_valid(flag)) {
4221 "\"%s\" road \"%s\": unknown flag \"%s\".",
4222 filename, extra_rule_name(pextra), sval);
4223 ok = FALSE;
4224 break;
4225 } else {
4226 BV_SET(proad->flags, flag);
4227 }
4228 }
4229 free(slist);
4230
4231 if (!ok) {
4232 break;
4233 }
4235
4236 for (j = 0; ok && j < game.control.num_road_types; j++) {
4237 const char *section = &road_sections[j * MAX_SECTION_LABEL];
4238 const char *extra_name = secfile_lookup_str(file, "%s.extra", section);
4240
4241 if (!is_extra_caused_by(pextra, EC_ROAD)) {
4243 "\"%s\" road section [%s]: extra \"%s\" does not have "
4244 "\"Road\" in its causes",
4245 filename, section, extra_name);
4246 ok = FALSE;
4247 }
4248 }
4249 }
4250
4251 if (ok) {
4252 extra_type_iterate(pextra) {
4253 pextra->bridged = extra_type_list_new();
4255 if (BV_ISSET(pextra->bridged_over, pbridged->id)) {
4256 extra_type_list_append(pextra->bridged, pbridged);
4257 }
4260 }
4261
4262 if (ok) {
4263 /* Tiledef details */
4265 int tdidx = tiledef_index(td);
4267 const char **slist;
4268 int ej;
4269
4270 slist = secfile_lookup_str_vec(file, &nval, "%s.extras", section);
4271 for (ej = 0; ej < nval; ej++) {
4272 const char *sval = slist[ej];
4273 struct extra_type *pextra = extra_type_by_rule_name(sval);
4274
4275 if (pextra != nullptr) {
4277 if (pextra == old_extra) {
4278 ruleset_error(nullptr, LOG_ERROR,
4279 "%s: Duplicate extra %s.",
4280 section, extra_rule_name(pextra));
4281 ok = FALSE;
4282 break;
4283 }
4285
4286 if (ok) {
4287 extra_type_list_append(td->extras, pextra);
4288 }
4289 } else {
4290 ruleset_error(nullptr, LOG_ERROR,
4291 "%s: Unknown extra name \"%s\".",
4292 section, sval);
4293 ok = FALSE;
4294 }
4295
4296 if (!ok) {
4297 break;
4298 }
4299 }
4301 }
4302
4303 if (ok) {
4305 }
4306
4307 return ok;
4308}
4309
4310/**********************************************************************/
4314static bool load_government_names(struct section_file *file,
4315 struct rscompat_info *compat)
4316{
4317 int nval = 0;
4318 struct section_list *sec;
4319 const char *filename = secfile_name(file);
4320 bool ok = TRUE;
4321 const char *flag;
4322 int i;
4323
4324 if (!rscompat_check_cap_and_version(file, filename, compat)) {
4325 return FALSE;
4326 }
4327
4328 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
4329 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
4330
4332 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
4333 ruleset_error(NULL, LOG_ERROR, "\"%s\": No governments?!?", filename);
4334 ok = FALSE;
4335 } else if (nval > G_LAST) {
4337 "\"%s\": Too many governments (%d, max %d)",
4338 filename, nval, G_LAST);
4339 ok = FALSE;
4340 }
4341
4342 if (ok) {
4344
4345 /* Government names are needed early so that get_government_by_name will
4346 * work. */
4347 governments_iterate(gov) {
4348 const char *sec_name =
4350
4351 if (!ruleset_load_names(&gov->name, NULL, file, sec_name)) {
4352 ok = FALSE;
4353 break;
4354 }
4356 }
4357
4359
4360 if (ok) {
4362 nval = (NULL != sec ? section_list_size(sec) : 0);
4363
4364 if (nval > MAX_NUM_MULTIPLIERS) {
4366 "\"%s\": Too many multipliers (%d, max %d)",
4367 filename, nval, MAX_NUM_MULTIPLIERS);
4368
4369 ok = FALSE;
4370 } else {
4372 }
4373
4374 if (ok) {
4375 multipliers_iterate(pmul) {
4376 const char *sec_name =
4378
4379 if (!ruleset_load_names(&pmul->name, NULL, file, sec_name)) {
4381 "\"%s\": Cannot load multiplier names",
4382 filename);
4383 ok = FALSE;
4384 break;
4385 }
4387 }
4388 }
4389
4390 /* User government flag names */
4391 for (i = 0;
4392 (flag = secfile_lookup_str_default(file, nullptr,
4393 "control.government_flags%d.name",
4394 i));
4395 i++) {
4396 const char *helptxt = secfile_lookup_str_default(file, nullptr,
4397 "control.government_flags%d.helptxt", i);
4398
4400 != gov_flag_id_invalid()) {
4401 ruleset_error(nullptr, LOG_ERROR,
4402 "\"%s\": Duplicate government flag name '%s'",
4403 filename, flag);
4404 ok = FALSE;
4405 break;
4406 }
4409 "\"%s\": Too many user government flags!",
4410 filename);
4411 ok = FALSE;
4412 break;
4413 }
4414
4415 set_user_gov_flag_name(GOVF_USER_FLAG_1 + i, flag, helptxt);
4416 }
4417
4419
4420 return ok;
4421}
4422
4423/**********************************************************************/
4427 struct rscompat_info *compat)
4428{
4429 struct section_list *sec;
4430 const char *filename = secfile_name(file);
4431 bool ok = TRUE;
4432
4434
4436 = lookup_government(file, "governments.during_revolution", filename, NULL);
4438 ok = FALSE;
4439 }
4440
4441 if (ok) {
4444
4445 /* Easy ones: */
4447 const int i = government_index(g);
4448 const char *sec_name = section_name(section_list_get(sec, i));
4449 struct requirement_vector *reqs
4450 = lookup_req_list(file, sec_name, "reqs", government_rule_name(g));
4451 const char **slist;
4452 int j;
4453 const char *sval;
4454 size_t nval;
4455
4456 if (reqs == NULL) {
4457 ok = FALSE;
4458 break;
4459 }
4460
4461 if (NULL != secfile_entry_lookup(file, "%s.ai_better", sec_name)) {
4462 char entry[100];
4463
4464 fc_snprintf(entry, sizeof(entry), "%s.ai_better", sec_name);
4465 g->ai.better = lookup_government(file, entry, filename, NULL);
4466 if (g->ai.better == NULL) {
4467 ok = FALSE;
4468 break;
4469 }
4470 } else {
4471 g->ai.better = NULL;
4472 }
4473 requirement_vector_copy(&g->reqs, reqs);
4474
4475 sz_strlcpy(g->graphic_str,
4476 secfile_lookup_str(file, "%s.graphic", sec_name));
4477 sz_strlcpy(g->graphic_alt,
4478 secfile_lookup_str(file, "%s.graphic_alt", sec_name));
4479 sz_strlcpy(g->sound_str,
4480 secfile_lookup_str_default(file, "-", "%s.sound", sec_name));
4481 sz_strlcpy(g->sound_alt,
4482 secfile_lookup_str_default(file, "-", "%s.sound_alt", sec_name));
4483 sz_strlcpy(g->sound_alt2,
4484 secfile_lookup_str_default(file, "-", "%s.sound_alt2", sec_name));
4485
4486 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
4487 BV_CLR_ALL(g->flags);
4488 for (j = 0; j < nval; j++) {
4489 enum gov_flag_id flag;
4490
4491 sval = slist[j];
4493 if (!gov_flag_id_is_valid(flag)) {
4494 ruleset_error(NULL, LOG_ERROR, "\"%s\" government \"%s\": unknown flag \"%s\".",
4495 filename, government_rule_name(g), sval);
4496 ok = FALSE;
4497 break;
4498 } else {
4499 BV_SET(g->flags, flag);
4500 }
4501 }
4502 free(slist);
4503
4504 g->helptext = lookup_strvec(file, sec_name, "helptext");
4506 }
4507
4508
4509 if (ok) {
4510 /* Titles */
4512 const char *sec_name
4514 const char *male, *female;
4515
4516 if (!(male = secfile_lookup_str(file, "%s.ruler_male_title", sec_name))
4517 || !(female = secfile_lookup_str(file, "%s.ruler_female_title",
4518 sec_name))) {
4520 "Lack of default ruler titles for "
4521 "government \"%s\" (nb %d): %s",
4523 secfile_error());
4524 ok = FALSE;
4525 break;
4526 } else if (NULL == government_ruler_title_new(g, NULL, male, female)) {
4528 "Lack of default ruler titles for "
4529 "government \"%s\" (nb %d).",
4531 ok = FALSE;
4532 break;
4533 }
4535 }
4536
4538
4539 if (ok) {
4541 multipliers_iterate(pmul) {
4542 int id = multiplier_index(pmul);
4543 const char *sec_name = section_name(section_list_get(sec, id));
4544 struct requirement_vector *reqs;
4545
4546 if (!secfile_lookup_int(file, &pmul->start, "%s.start", sec_name)) {
4547 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4548 ok = FALSE;
4549 break;
4550 }
4551 if (!secfile_lookup_int(file, &pmul->stop, "%s.stop", sec_name)) {
4552 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4553 ok = FALSE;
4554 break;
4555 }
4556 if (pmul->stop <= pmul->start) {
4558 "Multiplier \"%s\" stop (%d) must be greater "
4559 "than start (%d)", multiplier_rule_name(pmul),
4560 pmul->stop, pmul->start);
4561 ok = FALSE;
4562 break;
4563 }
4564 if (!secfile_lookup_int(file, &pmul->step, "%s.step", sec_name)) {
4565 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4566 ok = FALSE;
4567 break;
4568 }
4569 if (((pmul->stop - pmul->start) % pmul->step) != 0) {
4571 "Multiplier \"%s\" step (%d) does not fit "
4572 "exactly into interval start-stop (%d to %d)",
4573 multiplier_rule_name(pmul), pmul->step,
4574 pmul->start, pmul->stop);
4575 ok = FALSE;
4576 break;
4577 }
4578 if (!secfile_lookup_int(file, &pmul->def, "%s.default", sec_name)) {
4579 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4580 ok = FALSE;
4581 break;
4582 }
4583 if (pmul->def < pmul->start || pmul->def > pmul->stop) {
4585 "Multiplier \"%s\" default (%d) not within "
4586 "legal range (%d to %d)", multiplier_rule_name(pmul),
4587 pmul->def, pmul->start, pmul->stop);
4588 ok = FALSE;
4589 break;
4590 }
4591 if (((pmul->def - pmul->start) % pmul->step) != 0) {
4593 "Multiplier \"%s\" default (%d) not legal "
4594 "with respect to step size %d",
4595 multiplier_rule_name(pmul), pmul->def, pmul->step);
4596 ok = FALSE;
4597 break;
4598 }
4599 pmul->offset = secfile_lookup_int_default(file, 0,
4600 "%s.offset", sec_name);
4601 pmul->factor = secfile_lookup_int_default(file, 100,
4602 "%s.factor", sec_name);
4603 if (pmul->factor == 0) {
4605 "Multiplier \"%s\" scaling factor must "
4606 "not be zero", multiplier_rule_name(pmul));
4607 ok = FALSE;
4608 break;
4609 }
4610
4611 pmul->minimum_turns = secfile_lookup_int_default(file, 0,
4612 "%s.minimum_turns",
4613 sec_name);
4614
4615 reqs = lookup_req_list(file, sec_name, "reqs",
4616 multiplier_rule_name(pmul));
4617 if (reqs == NULL) {
4618 ok = FALSE;
4619 break;
4620 }
4621 requirement_vector_copy(&pmul->reqs, reqs);
4622
4623 pmul->helptext = lookup_strvec(file, sec_name, "helptext");
4626 }
4627
4628 if (ok) {
4630 }
4631
4632 return ok;
4633}
4634
4635/**********************************************************************/
4646static void send_ruleset_control(struct conn_list *dest)
4647{
4649 int idx = 0;
4650
4652
4653 if (game.ruleset_summary != NULL) {
4654 struct packet_ruleset_summary summary;
4655
4657
4658 lsend_packet_ruleset_summary(dest, &summary);
4659 }
4660
4661 while (desc_left > 0) {
4663 int this_len = desc_left;
4664
4665 if (this_len > MAX_LEN_CONTENT - 21) {
4667 }
4668
4669 part.text[this_len] = '\0';
4670
4672 idx += this_len;
4674
4676 }
4677}
4678
4679/**********************************************************************/
4684static const char *check_leader_names(struct nation_type *pnation)
4685{
4687 const char *name = nation_leader_name(pleader);
4688
4690 if (prev_leader == pleader) {
4691 break;
4692 } else if (0 == fc_strcasecmp(name, nation_leader_name(prev_leader))) {
4693 return name;
4694 }
4697 return NULL;
4698}
4699
4700/**********************************************************************/
4704static bool load_nation_names(struct section_file *file,
4705 struct rscompat_info *compat)
4706{
4707 struct section_list *sec;
4708 int j;
4709 bool ok = TRUE;
4710 const char *filename = secfile_name(file);
4711
4712 if (!rscompat_check_cap_and_version(file, filename, compat)) {
4713 return FALSE;
4714 }
4715
4716 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
4717 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
4718
4720 if (NULL == sec) {
4722 "No available nations in this ruleset!");
4723 ok = FALSE;
4724 } else if (section_list_size(sec) > MAX_NUM_NATIONS) {
4726 "Too many nations (max %d, we have %d)!",
4728 ok = FALSE;
4729 } else {
4732
4734 const int i = nation_index(pl);
4735 const char *sec_name = section_name(section_list_get(sec, i));
4736 const char *domain = secfile_lookup_str_default(file, NULL,
4737 "%s.translation_domain", sec_name);
4738 const char *noun_plural = secfile_lookup_str(file,
4739 "%s.plural", sec_name);
4740
4741
4742 if (domain == NULL) {
4743 domain = "freeciv-nations";
4744 }
4745
4746 if (!strcmp("freeciv-core", domain)) {
4747 pl->translation_domain = NULL;
4748 } else if (!strcmp("freeciv-nations", domain)) {
4749 pl->translation_domain = fc_strdup(domain);
4750 } else {
4752 "Unsupported translation domain \"%s\" for %s",
4753 domain, sec_name);
4754 ok = FALSE;
4755 break;
4756 }
4757
4758 if (!ruleset_load_names(&pl->adjective, pl->translation_domain, file, sec_name)) {
4759 ok = FALSE;
4760 break;
4761 }
4762 name_set(&pl->noun_plural, pl->translation_domain, noun_plural);
4763
4764 /* Check if nation name is already defined. */
4765 for (j = 0; j < i && ok; j++) {
4766 struct nation_type *n2 = nation_by_number(j);
4767
4768 /* Compare strings after stripping off qualifiers -- we don't want
4769 * two nations to end up with identical adjectives displayed to users.
4770 * (This check only catches English, not localisations, of course.) */
4771 if (0 == strcmp(Qn_(untranslated_name(&n2->adjective)),
4772 Qn_(untranslated_name(&pl->adjective)))) {
4774 "Two nations defined with the same adjective \"%s\": "
4775 "in section \'%s\' and section \'%s\'",
4776 Qn_(untranslated_name(&pl->adjective)),
4778 ok = FALSE;
4779 } else if (!strcmp(rule_name_get(&n2->adjective),
4780 rule_name_get(&pl->adjective))) {
4781 /* We cannot have the same rule name, as the game needs them to be
4782 * distinct. */
4784 "Two nations defined with the same rule_name \"%s\": "
4785 "in section \'%s\' and section \'%s\'",
4786 rule_name_get(&pl->adjective),
4788 ok = FALSE;
4789 } else if (0 == strcmp(Qn_(untranslated_name(&n2->noun_plural)),
4790 Qn_(untranslated_name(&pl->noun_plural)))) {
4791 /* We don't want identical English plural names either. */
4793 "Two nations defined with the same plural name \"%s\": "
4794 "in section \'%s\' and section \'%s\'",
4795 Qn_(untranslated_name(&pl->noun_plural)),
4797 ok = FALSE;
4798 }
4799 }
4800 if (!ok) {
4801 break;
4802 }
4804 }
4805
4807
4808 if (ok) {
4810 if (sec != NULL) {
4812
4813 section_list_iterate(sec, psection) {
4814 struct nation_group *pgroup;
4815 const char *name;
4816
4817 name = secfile_lookup_str(file, "%s.name", section_name(psection));
4818 if (NULL == name) {
4819 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4820 ok = FALSE;
4821 break;
4822 }
4824 if (pgroup == NULL) {
4825 ok = FALSE;
4826 break;
4827 }
4830 sec = NULL;
4831 }
4832 }
4833
4834 return ok;
4835}
4836
4837/**********************************************************************/
4840static bool is_on_allowed_list(const char *name, const char **list, size_t len)
4841{
4842 int i;
4843
4844 for (i = 0; i < len; i++) {
4845 if (!fc_strcasecmp(name, list[i])) {
4846 return TRUE;
4847 }
4848 }
4849 return FALSE;
4850}
4851
4852/**********************************************************************/
4856static bool load_city_name_list(struct section_file *file,
4857 struct nation_type *pnation,
4858 const char *secfile_str1,
4859 const char *secfile_str2,
4860 const char **allowed_terrains,
4861 size_t atcount)
4862{
4863 size_t dim, j;
4864 bool ok = TRUE;
4865 const char **cities = secfile_lookup_str_vec(file, &dim, "%s.%s",
4867
4868 /* Each string will be of the form "<cityname> (<label>, <label>, ...)".
4869 * The cityname is just the name for this city, while each "label" matches
4870 * a terrain type for the city (or "river"), with a preceding ! to negate
4871 * it. The parentheses are optional (but necessary to have the settings,
4872 * of course). Our job is now to parse it. */
4873 for (j = 0; j < dim; j++) {
4874 size_t len = strlen(cities[j]);
4875 char city_name[len + 1], *p, *next, *end;
4876 struct nation_city *pncity;
4877
4879
4880 /* Now we wish to determine values for all of the city labels. A value
4881 * of NCP_NONE means no preference (which is necessary so that the use
4882 * of this is optional); NCP_DISLIKE means the label is negated and
4883 * NCP_LIKE means it's labelled. Mostly the parsing just involves
4884 * a lot of ugly string handling... */
4885 if ((p = strchr(city_name, '('))) {
4886 *p++ = '\0';
4887
4888 if (!(end = strchr(p, ')'))) {
4890 "\"%s\" [%s] %s: city name \"%s\" "
4891 "unmatched parenthesis.", secfile_name(file),
4893 ok = FALSE;
4894 } else {
4895 for (*end++ = '\0'; '\0' != *end; end++) {
4896 if (!fc_isspace(*end)) {
4898 "\"%s\" [%s] %s: city name \"%s\" "
4899 "contains characters after last parenthesis.",
4901 cities[j]);
4902 ok = FALSE;
4903 break;
4904 }
4905 }
4906 }
4907 }
4908
4909 /* Build the nation_city. */
4912 /* The ruleset contains a name that is too long. This shouldn't
4913 * happen - if it does, the author should get immediate feedback. */
4915 "\"%s\" [%s] %s: city name \"%s\" is too long.",
4916 secfile_name(file),
4918 ok = FALSE;
4919 city_name[MAX_LEN_CITYNAME - 1] = '\0';
4920 }
4921 pncity = nation_city_new(pnation, city_name);
4922
4923 if (NULL != p) {
4924 /* Handle the labels one at a time. */
4925 do {
4926 enum nation_city_preference prefer;
4927
4928 if ((next = strchr(p, ','))) {
4929 *next = '\0';
4930 }
4932
4933 /* The ! is used to mark a negative, which is recorded with
4934 * NCP_DISLIKE. Otherwise we use a NCP_LIKE.
4935 */
4936 if (*p == '!') {
4937 p++;
4938 prefer = NCP_DISLIKE;
4939 } else {
4940 prefer = NCP_LIKE;
4941 }
4942
4943 if (0 == fc_strcasecmp(p, "river")) {
4945 && !is_on_allowed_list(p,
4948 "\"%s\" [%s] %s: city \"%s\" "
4949 "has terrain hint \"%s\" not in allowed_terrains.",
4951 city_name, p);
4952 ok = FALSE;
4953 } else {
4955 }
4956 } else {
4957 const struct terrain *pterrain = terrain_by_rule_name(p);
4958
4959 if (NULL == pterrain) {
4960 /* Try with removing frequent trailing 's'. */
4961 size_t l = strlen(p);
4962
4963 if (0 < l && 's' == fc_tolower(p[l - 1])) {
4964 char saved = p[l - 1];
4965
4966 p[l - 1] = '\0';
4967 pterrain = terrain_by_rule_name(p);
4968 if (pterrain == NULL) {
4969 /* Didn't help, restore for later allowed_terrains check */
4970 p[l - 1] = saved;
4971 }
4972 }
4973 }
4974
4975 /* Nationset may have been devised with a specific set of terrains
4976 * in mind which don't quite match this ruleset, in which case we
4977 * (a) quietly ignore any hints mentioned that don't happen to be in
4978 * the current ruleset, (b) enforce that terrains mentioned by nations
4979 * must be on the list */
4980 if (pterrain != NULL && game.server.ruledit.allowed_terrains != NULL) {
4981 if (!is_on_allowed_list(p,
4983 /* Terrain exists, but not intended for these nations */
4985 "\"%s\" [%s] %s: city \"%s\" "
4986 "has terrain hint \"%s\" not in allowed_terrains.",
4988 city_name, p);
4989 ok = FALSE;
4990 break;
4991 }
4992 } else if (!pterrain) {
4993 /* Terrain doesn't exist; only complain if it's not on any list */
4995 || !is_on_allowed_list(p,
4998 "\"%s\" [%s] %s: city \"%s\" "
4999 "has unknown terrain hint \"%s\".",
5001 city_name, p);
5002 ok = FALSE;
5003 break;
5004 }
5005 }
5006 if (NULL != pterrain) {
5007 nation_city_set_terrain_preference(pncity, pterrain, prefer);
5008 }
5009 }
5010
5011 p = next ? next + 1 : NULL;
5012 } while (NULL != p && '\0' != *p);
5013 }
5014 }
5015
5016 if (NULL != cities) {
5017 free(cities);
5018 }
5019
5020 return ok;
5021}
5022
5023/**********************************************************************/
5026static bool load_ruleset_nations(struct section_file *file,
5027 struct rscompat_info *compat)
5028{
5029 struct government *gov;
5030 int j;
5031 size_t dim;
5032 char temp_name[MAX_LEN_NAME];
5033 const char **vec;
5034 const char *name, *bad_leader;
5035 const char *sval;
5036 int default_set;
5037 const char *filename = secfile_name(file);
5038 struct section_list *sec = NULL;
5039 enum trait tr;
5040 bool ok = TRUE;
5041
5042 name = secfile_lookup_str_default(file, NULL, "ruledit.nationlist");
5043 if (name != NULL) {
5045 }
5047 "ruledit.embedded_nations");
5048
5049 if (vec != NULL) {
5050 /* Copy to persistent vector */
5053
5054 for (j = 0; j < game.server.ruledit.embedded_nations_count; j++) {
5056 }
5057
5058 free(vec);
5059 }
5060
5062
5063 ruleset_load_traits(game.server.default_traits, file, "default_traits", "");
5064 for (tr = trait_begin(); tr != trait_end(); tr = trait_next(tr)) {
5065 if (game.server.default_traits[tr].min < 0) {
5067 }
5068 if (game.server.default_traits[tr].max < 0) {
5070 }
5071 if (game.server.default_traits[tr].fixed < 0) {
5073
5074 /* TODO: Should sometimes round the a / 2 = x.5 results up */
5076 }
5079 "Default values for trait %s not sane.",
5080 trait_name(tr));
5081 ok = FALSE;
5082 break;
5083 }
5084 }
5085
5086 if (ok) {
5088 "compatibility.allowed_govs");
5089 if (vec != NULL) {
5090 /* Copy to persistent vector */
5092 = fc_malloc(game.server.ruledit.ag_count * sizeof(char *));
5094 (const char **)game.server.ruledit.nc_agovs;
5095
5096 for (j = 0; j < game.server.ruledit.ag_count; j++) {
5098 }
5099
5100 free(vec);
5101 }
5102
5104 "compatibility.allowed_terrains");
5105 if (vec != NULL) {
5106 /* Copy to persistent vector */
5108 = fc_malloc(game.server.ruledit.at_count * sizeof(char *));
5110 (const char **)game.server.ruledit.nc_aterrs;
5111
5112 for (j = 0; j < game.server.ruledit.at_count; j++) {
5114 }
5115
5116 free(vec);
5117 }
5118
5120 "compatibility.allowed_styles");
5121 if (vec != NULL) {
5122 /* Copy to persistent vector */
5124 = fc_malloc(game.server.ruledit.as_count * sizeof(char *));
5126 (const char **)game.server.ruledit.nc_astyles;
5127
5128 for (j = 0; j < game.server.ruledit.as_count; j++) {
5130 }
5131
5132 free(vec);
5133 }
5134
5136 "compatibility.default_government");
5137 /* We deliberately don't check this against allowed_govs. It's only
5138 * specified once so not vulnerable to typos, and may usefully be set in
5139 * a specific ruleset to a gov not explicitly known by the nation set. */
5140 if (sval != NULL) {
5142 if (game.default_government == NULL) {
5144 "Tried to set unknown government type \"%s\" as default_government!",
5145 sval);
5146 ok = FALSE;
5147 } else {
5150 }
5151 }
5152 }
5153
5154 if (ok) {
5156 if (sec != NULL) {
5158
5159 section_list_iterate(sec, psection) {
5160 const char *set_name, *set_rule_name, *set_description;
5161
5162 set_name = secfile_lookup_str(file, "%s.name", section_name(psection));
5164 secfile_lookup_str(file, "%s.rule_name", section_name(psection));
5165 set_description = secfile_lookup_str_default(file, "", "%s.description",
5166 section_name(psection));
5167 if (NULL == set_name || NULL == set_rule_name) {
5168 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
5169 ok = FALSE;
5170 break;
5171 }
5173 ok = FALSE;
5174 break;
5175 }
5178 sec = NULL;
5179 } else {
5181 "At least one nation set [" NATION_SET_SECTION_PREFIX "_*] "
5182 "must be defined.");
5183 ok = FALSE;
5184 }
5185 }
5186
5187 if (ok) {
5188 /* Default set that every nation is a member of. */
5190 "compatibility.default_nationset");
5191 if (sval != NULL) {
5193 if (pset != NULL) {
5195 } else {
5197 "Unknown default_nationset \"%s\".", sval);
5198 ok = FALSE;
5199 }
5200 } else if (nation_set_count() == 1) {
5201 /* If there's only one set defined, every nation is implicitly a
5202 * member of that set. */
5203 default_set = 0;
5204 } else {
5205 /* No default nation set; every nation must explicitly specify at
5206 * least one set to be a member of. */
5207 default_set = -1;
5208 }
5209 }
5210
5211 if (ok) {
5213 if (sec) {
5214 section_list_iterate(sec, psection) {
5215 struct nation_group *pgroup;
5216 bool hidden;
5217
5218 name = secfile_lookup_str(file, "%s.name", section_name(psection));
5220 if (pgroup == NULL) {
5221 ok = FALSE;
5222 break;
5223 }
5224
5225 hidden = secfile_lookup_bool_default(file, FALSE, "%s.hidden",
5226 section_name(psection));
5228
5229 if (!secfile_lookup_int(file, &j, "%s.match", section_name(psection))) {
5230 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
5231 ok = FALSE;
5232 break;
5233 }
5237 sec = NULL;
5238 }
5239 }
5240
5241 if (ok) {
5243 nations_iterate(pnation) {
5244 struct nation_type *pconflict;
5245 const int i = nation_index(pnation);
5246 char tmp[200] = "\0";
5247 const char *barb_type;
5248 const char *sec_name = section_name(section_list_get(sec, i));
5249 const char *legend;
5250
5251 /* Nation sets and groups. */
5252 if (default_set >= 0) {
5253 nation_set_list_append(pnation->sets,
5255 }
5256 vec = secfile_lookup_str_vec(file, &dim, "%s.groups", sec_name);
5257 for (j = 0; j < dim; j++) {
5258 struct nation_set *pset = nation_set_by_rule_name(vec[j]);
5260
5261 fc_assert(pset == NULL || pgroup == NULL);
5262
5263 if (NULL != pset) {
5264 nation_set_list_append(pnation->sets, pset);
5265 } else if (NULL != pgroup) {
5266 nation_group_list_append(pnation->groups, pgroup);
5267 } else {
5268 /* For nation authors, this would probably be considered an error.
5269 * But it can happen normally. The civ1 compatibility ruleset only
5270 * uses the nations that were in civ1, so not all of the links will
5271 * exist. */
5272 log_verbose("Nation %s: Unknown set/group \"%s\".",
5273 nation_rule_name(pnation), vec[j]);
5274 }
5275 }
5276 if (NULL != vec) {
5277 free(vec);
5278 }
5279 if (nation_set_list_size(pnation->sets) < 1) {
5281 "Nation %s is not a member of any nation set",
5282 nation_rule_name(pnation));
5283 ok = FALSE;
5284 break;
5285 }
5286
5287 /* Nation conflicts. */
5288 vec = secfile_lookup_str_vec(file, &dim, "%s.conflicts_with", sec_name);
5289 for (j = 0; j < dim; j++) {
5291
5292 if (pnation == pconflict) {
5294 "Nation %s conflicts with itself",
5295 nation_rule_name(pnation));
5296 ok = FALSE;
5297 break;
5298 } else if (NULL != pconflict) {
5299 nation_list_append(pnation->server.conflicts_with, pconflict);
5300 } else {
5301 /* For nation authors, this would probably be considered an error.
5302 * But it can happen normally. The civ1 compatibility ruleset only
5303 * uses the nations that were in civ1, so not all of the links will
5304 * exist. */
5305 log_verbose("Nation %s: conflicts_with nation \"%s\" is unknown.",
5306 nation_rule_name(pnation), vec[j]);
5307 }
5308 }
5309 if (NULL != vec) {
5310 free(vec);
5311 }
5312 if (!ok) {
5313 break;
5314 }
5315
5316 /* Nation leaders. */
5317 for (j = 0; j < MAX_NUM_LEADERS; j++) {
5318 const char *sexstr;
5319 sex_t sex;
5320 bool is_male = FALSE;
5321
5322 name = secfile_lookup_str(file, "%s.leaders%d.name", sec_name, j);
5323 if (NULL == name) {
5324 /* No more to read. */
5325 break;
5326 }
5327
5328 if (check_name(name)) {
5329 /* The ruleset contains a name that is too long. This shouldn't
5330 * happen - if it does, the author should get immediate feedback */
5333 "Nation %s: leader name \"%s\" is too long.",
5334 nation_rule_name(pnation), name);
5335 ok = FALSE;
5336 break;
5337 }
5338
5339 sexstr = secfile_lookup_str(file, "%s.leaders%d.sex", sec_name, j);
5340 if (NULL == sexstr) {
5342 "Nation %s: leader \"%s\": %s.",
5343 nation_rule_name(pnation), name, secfile_error());
5344 ok = FALSE;
5345 break;
5346 }
5347
5349
5350 switch (sex) {
5351 case SEX_MALE:
5352 is_male = TRUE;
5353 break;
5354 case SEX_FEMALE:
5355 is_male = FALSE;
5356 break;
5357 case SEX_UNKNOWN:
5359 "Nation %s: leader \"%s\" has unsupported "
5360 "sex variant \"%s\".",
5361 nation_rule_name(pnation), name, sexstr);
5362 ok = FALSE;
5363 break;
5364 }
5365
5366 if (ok) {
5367 (void) nation_leader_new(pnation, name, is_male);
5368 }
5369 }
5370 if (!ok) {
5371 break;
5372 }
5373
5374 /* Check the number of leaders. */
5375 if (MAX_NUM_LEADERS == j) {
5376 /* Too much leaders, get the real number defined in the ruleset. */
5377 while (NULL != secfile_entry_lookup(file, "%s.leaders%d.name",
5378 sec_name, j)) {
5379 j++;
5380 }
5382 "Nation %s: Too many leaders; max is %d",
5384 ok = FALSE;
5385 break;
5386 } else if (0 == j) {
5388 "Nation %s: no leaders; at least one is required.",
5389 nation_rule_name(pnation));
5390 ok = FALSE;
5391 break;
5392 }
5393
5394 /* Check if leader name is not already defined in this nation. */
5395 if ((bad_leader = check_leader_names(pnation))) {
5397 "Nation %s: leader \"%s\" defined more than once.",
5398 nation_rule_name(pnation), bad_leader);
5399 ok = FALSE;
5400 break;
5401 }
5402
5403 /* Nation player color preference, if any */
5404 fc_assert_ret_val(pnation->server.rgb == NULL, FALSE);
5405 (void) rgbcolor_load(file, &pnation->server.rgb, "%s.color", sec_name);
5406
5407 /* Load nation traits */
5408 ruleset_load_traits(pnation->server.traits, file, sec_name, "trait_");
5409 for (tr = trait_begin(); tr != trait_end(); tr = trait_next(tr)) {
5410 bool server_traits_used = TRUE;
5411
5412 if (pnation->server.traits[tr].min < 0) {
5413 pnation->server.traits[tr].min = game.server.default_traits[tr].min;
5414 } else {
5416 }
5417 if (pnation->server.traits[tr].max < 0) {
5418 pnation->server.traits[tr].max = game.server.default_traits[tr].max;
5419 } else {
5421 }
5422 if (pnation->server.traits[tr].fixed < 0) {
5423 if (server_traits_used) {
5424 pnation->server.traits[tr].fixed = game.server.default_traits[tr].fixed;
5425 } else {
5426 int diff = pnation->server.traits[tr].max - pnation->server.traits[tr].min;
5427
5428 /* TODO: Should sometimes round the a / 2 = x.5 results up */
5429 pnation->server.traits[tr].fixed = diff / 2 + pnation->server.traits[tr].min;
5430 }
5431 }
5432 if (pnation->server.traits[tr].max < pnation->server.traits[tr].min) {
5434 "%s values for trait %s not sane.",
5435 nation_rule_name(pnation), trait_name(tr));
5436 ok = FALSE;
5437 break;
5438 }
5439 }
5440
5441 if (!ok) {
5442 break;
5443 }
5444
5445 pnation->is_playable =
5446 secfile_lookup_bool_default(file, TRUE, "%s.is_playable", sec_name);
5447
5448 /* Check barbarian type. Default is "None" meaning not a barbarian */
5449 barb_type = secfile_lookup_str_default(file, "None",
5450 "%s.barbarian_type", sec_name);
5451 pnation->barb_type = barbarian_type_by_name(barb_type, fc_strcasecmp);
5452 if (!barbarian_type_is_valid(pnation->barb_type)) {
5454 "Nation %s, barbarian_type is invalid (\"%s\")",
5455 nation_rule_name(pnation), barb_type);
5456 ok = FALSE;
5457 break;
5458 }
5459
5460 if (pnation->barb_type != NOT_A_BARBARIAN
5461 && pnation->is_playable) {
5462 /* We can't allow players to use barbarian nations, barbarians
5463 * may run out of nations */
5465 "Nation %s marked both barbarian and playable.",
5466 nation_rule_name(pnation));
5467 ok = FALSE;
5468 break;
5469 }
5470
5471 /* Flags */
5472 sz_strlcpy(pnation->flag_graphic_str,
5473 secfile_lookup_str_default(file, "-", "%s.flag", sec_name));
5474 sz_strlcpy(pnation->flag_graphic_alt,
5476 "%s.flag_alt", sec_name));
5477
5478 /* Ruler titles */
5479 for (j = 0;; j++) {
5480 const char *male, *female;
5481
5483 "%s.ruler_titles%d.government",
5484 sec_name, j);
5485 if (NULL == name) {
5486 /* End of the list of ruler titles. */
5487 break;
5488 }
5489
5490 /* NB: even if the government doesn't exist, we load the entries for
5491 * the ruler titles to avoid warnings about unused entries. */
5492 male = secfile_lookup_str(file, "%s.ruler_titles%d.male_title",
5493 sec_name, j);
5494 female = secfile_lookup_str(file, "%s.ruler_titles%d.female_title",
5495 sec_name, j);
5497
5498 /* Nationset may have been devised with a specific set of govs in
5499 * mind which don't quite match this ruleset, in which case we
5500 * (a) quietly ignore any govs mentioned that don't happen to be in
5501 * the current ruleset, (b) enforce that govs mentioned by nations
5502 * must be on the list */
5503 if (gov != NULL && game.server.ruledit.allowed_govs != NULL) {
5507 /* Gov exists, but not intended for these nations */
5508 gov = NULL;
5510 "Nation %s: government \"%s\" not in allowed_govs.",
5511 nation_rule_name(pnation), name);
5512 ok = FALSE;
5513 break;
5514 }
5515 } else if (!gov) {
5516 /* Gov doesn't exist; only complain if it's not on any list */
5522 "Nation %s: government \"%s\" not found.",
5523 nation_rule_name(pnation), name);
5524 ok = FALSE;
5525 break;
5526 }
5527 }
5528 if (NULL != male && NULL != female) {
5529 if (gov) {
5530 (void) government_ruler_title_new(gov, pnation, male, female);
5531 }
5532 } else {
5534 ok = FALSE;
5535 break;
5536 }
5537 }
5538 if (!ok) {
5539 break;
5540 }
5541
5542 /* City styles */
5543 name = secfile_lookup_str(file, "%s.style", sec_name);
5544 if (!name) {
5546 ok = FALSE;
5547 break;
5548 }
5549 pnation->style = style_by_rule_name(name);
5550 if (pnation->style == NULL) {
5556 "Nation %s: Illegal style \"%s\"",
5557 nation_rule_name(pnation), name);
5558 ok = FALSE;
5559 break;
5560 } else {
5561 log_verbose("Nation %s: style \"%s\" not supported in this "
5562 "ruleset; using default.",
5563 nation_rule_name(pnation), name);
5564 pnation->style = style_by_number(0);
5565 }
5566 }
5567
5568 /* Civilwar nations */
5569 vec = secfile_lookup_str_vec(file, &dim,
5570 "%s.civilwar_nations", sec_name);
5571 for (j = 0; j < dim; j++) {
5573
5574 /* No test for duplicate nations is performed. If there is a duplicate
5575 * entry it will just cause that nation to have an increased
5576 * probability of being chosen. */
5577 if (pconflict == pnation) {
5579 "Nation %s is its own civil war nation",
5580 nation_rule_name(pnation));
5581 ok = FALSE;
5582 break;
5583 } else if (NULL != pconflict) {
5584 nation_list_append(pnation->server.civilwar_nations, pconflict);
5585 nation_list_append(pconflict->server.parent_nations, pnation);
5586 } else {
5587 /* For nation authors, this would probably be considered an error.
5588 * But it can happen normally. The civ1 compatibility ruleset only
5589 * uses the nations that were in civ1, so not all of the links will
5590 * exist. */
5591 log_verbose("Nation %s: civil war nation \"%s\" is unknown.",
5592 nation_rule_name(pnation), vec[j]);
5593 }
5594 }
5595 if (NULL != vec) {
5596 free(vec);
5597 }
5598 if (!ok) {
5599 break;
5600 }
5601
5602 /* Load nation specific initial items */
5603 if (!lookup_tech_list(file, sec_name, "init_techs",
5604 pnation->init_techs, filename)) {
5605 ok = FALSE;
5606 break;
5607 }
5608 if (!lookup_building_list(file, sec_name, "init_buildings",
5609 pnation->init_buildings, filename)) {
5610 ok = FALSE;
5611 break;
5612 }
5613 if (!lookup_unit_list(file, sec_name, "init_units",
5614 pnation->init_units, filename)) {
5615 ok = FALSE;
5616 break;
5617 }
5618 fc_strlcat(tmp, sec_name, 200);
5619 fc_strlcat(tmp, ".init_government", 200);
5620 if (secfile_entry_by_path(file, tmp)) {
5621 pnation->init_government = lookup_government(file, tmp, filename,
5622 NULL);
5623 /* If specified, init_government has to be in this specific ruleset,
5624 * not just allowed_govs */
5625 if (pnation->init_government == NULL) {
5626 ok = FALSE;
5627 break;
5628 }
5629 /* ...but if a list of govs has been specified, enforce that this
5630 * nation's init_government is on the list. */
5632 && !is_on_allowed_list(government_rule_name(pnation->init_government),
5636 "Nation %s: init_government \"%s\" not allowed.",
5637 nation_rule_name(pnation),
5638 government_rule_name(pnation->init_government));
5639 ok = FALSE;
5640 break;
5641 }
5642 }
5643
5644 /* Read default city names. */
5645 if (!load_city_name_list(file, pnation, sec_name, "cities",
5648 ok = FALSE;
5649 break;
5650 }
5651
5652 legend = secfile_lookup_str_default(file, "", "%s.legend", sec_name);
5653 pnation->legend = fc_strdup(legend);
5654 if (check_strlen(pnation->legend, MAX_LEN_MSG, NULL)) {
5656 "Nation %s: legend \"%s\" is too long.",
5657 nation_rule_name(pnation),
5658 pnation->legend);
5659 ok = FALSE;
5660 break;
5661 }
5662
5663 pnation->player = NULL;
5666 sec = NULL;
5667 }
5668
5669 /* Clean up on aborted load */
5670 if (sec != NULL) {
5671 fc_assert(!ok);
5673 }
5674
5675 if (ok) {
5677 }
5678
5679 if (ok) {
5680 /* Update cached number of playable nations in the current set */
5682
5683 /* Sanity checks on all sets */
5686
5687 nations_iterate(pnation) {
5688 if (nation_is_in_set(pnation, pset)) {
5689 switch (nation_barbarian_type(pnation)) {
5690 case NOT_A_BARBARIAN:
5691 if (is_nation_playable(pnation)) {
5692 num_playable++;
5693 }
5694 break;
5695 case LAND_BARBARIAN:
5697 break;
5698 case SEA_BARBARIAN:
5700 break;
5701 case ANIMAL_BARBARIAN:
5702 /* Animals are optional */
5703 break;
5706 break;
5707 default:
5709 }
5710 }
5712 if (num_playable < 1) {
5714 "Nation set \"%s\" has no playable nations. "
5715 "At least one required!", nation_set_rule_name(pset));
5716 ok = FALSE;
5717 break;
5718 }
5719 if (barb_land_count == 0 && barb_both_count == 0) {
5721 "No land barbarian nation defined in set \"%s\". "
5722 "At least one required!", nation_set_rule_name(pset));
5723 ok = FALSE;
5724 break;
5725 }
5726 if (barb_sea_count == 0 && barb_both_count == 0) {
5728 "No sea barbarian nation defined in set \"%s\". "
5729 "At least one required!", nation_set_rule_name(pset));
5730 ok = FALSE;
5731 break;
5732 }
5734 }
5735
5736 return ok;
5737}
5738
5739/**********************************************************************/
5743static bool load_style_names(struct section_file *file,
5744 struct rscompat_info *compat)
5745{
5746 bool ok = TRUE;
5747 struct section_list *sec;
5748 const char *filename = secfile_name(file);
5749
5750 if (!rscompat_check_cap_and_version(file, filename, compat)) {
5751 return FALSE;
5752 }
5753
5754 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
5755 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
5756
5758 if (NULL == sec) {
5760 "No available nation styles in this ruleset!");
5761 ok = FALSE;
5762 } else {
5764
5766
5768 const int i = style_index(ps);
5769 const char *sec_name = section_name(section_list_get(sec, i));
5770
5771 ruleset_load_names(&ps->name, NULL, file, sec_name);
5773 }
5774
5776
5777 if (ok) {
5778 /* The citystyle sections: */
5779 int i = 0;
5780
5782 if (NULL != sec) {
5784 section_list_iterate(sec, style) {
5785 if (!ruleset_load_names(&city_styles[i].name, NULL, file, section_name(style))) {
5786 ok = FALSE;
5787 break;
5788 }
5789 i++;
5791
5793 } else {
5795 }
5796 }
5797
5798 return ok;
5799}
5800
5801/**********************************************************************/
5804static bool load_ruleset_styles(struct section_file *file,
5805 struct rscompat_info *compat)
5806{
5807 struct section_list *sec;
5808 int i;
5809 bool ok = TRUE;
5810
5811 /* City Styles ... */
5812
5814
5815 /* Get rest: */
5816 for (i = 0; i < game.control.num_city_styles; i++) {
5817 struct requirement_vector *reqs;
5818 const char *sec_name = section_name(section_list_get(sec, i));
5819
5820 sz_strlcpy(city_styles[i].graphic,
5821 secfile_lookup_str(file, "%s.graphic", sec_name));
5822 sz_strlcpy(city_styles[i].graphic_alt,
5823 secfile_lookup_str(file, "%s.graphic_alt", sec_name));
5824 sz_strlcpy(city_styles[i].citizens_graphic,
5826 "%s.citizens_graphic", sec_name));
5827
5829 if (reqs == NULL) {
5830 ok = FALSE;
5831 break;
5832 }
5834 }
5835
5837
5838 if (ok) {
5840
5841 if (sec != NULL) {
5842 int musi;
5843
5846 musi = 0;
5847
5848 section_list_iterate(sec, psection) {
5849 struct requirement_vector *reqs;
5851 const char *sec_name = section_name(psection);
5852
5853 sz_strlcpy(pmus->music_peaceful,
5855 "%s.music_peaceful", sec_name));
5856 sz_strlcpy(pmus->music_combat,
5858 "%s.music_combat", sec_name));
5859
5860 reqs = lookup_req_list(file, sec_name, "reqs", "Music Style");
5861 if (reqs == NULL) {
5862 ok = FALSE;
5863 break;
5864 }
5866
5867 musi++;
5869 }
5870
5872 }
5873
5874 return ok;
5875}
5876
5877/**********************************************************************/
5884 const char *uflags_path,
5885 const char *filename)
5886{
5887 /* Add each listed protected unit type flag as a !present
5888 * requirement. */
5889 if (secfile_entry_lookup(file, "%s", uflags_path)) {
5891 size_t psize;
5892 int i;
5893
5896 "%s", uflags_path);
5897
5898 if (!protecor_flag) {
5899 /* Entity exists but couldn't read it. */
5901 "\"%s\": %s: bad unit type flag list.",
5902 filename, uflags_path);
5903
5904 return FALSE;
5905 }
5906
5907 for (i = 0; i < psize; i++) {
5911 FALSE, FALSE, TRUE,
5912 protecor_flag[i]));
5913 }
5914
5916 }
5917
5918 return TRUE;
5919}
5920
5921/**********************************************************************/
5927 const char *actions_path,
5928 const char *filename)
5929{
5930 /* Read the alternative actions. */
5931 if (secfile_entry_lookup(file, "%s", actions_path)) {
5932 enum gen_action *unit_acts;
5933 size_t asize;
5934 int i;
5935
5937 "%s", actions_path);
5938
5939 if (!unit_acts) {
5940 /* Entity exists but couldn't read it. */
5942 "\"%s\": %s: bad action list",
5943 filename, actions_path);
5944
5945 return FALSE;
5946 }
5947
5948 for (i = 0; i < asize; i++) {
5949 auto_perf->alternatives[i] = unit_acts[i];
5950 }
5951
5952 free(unit_acts);
5953 }
5954
5955 return TRUE;
5956}
5957
5958/**********************************************************************/
5963 const char *item,
5964 const char *filename)
5965{
5966 char uflags_path[100];
5967 char action_path[100];
5968
5970 "missing_unit_upkeep.%s_protected", item);
5972 "missing_unit_upkeep.%s_unit_act", item);
5973
5975 filename)
5977 filename));
5978}
5979
5980/**********************************************************************/
5984static bool load_specialist(const struct section *psection,
5985 struct specialist *s,
5986 struct section_file *file)
5987{
5988 struct requirement_vector *reqs;
5989 const char *sec_name = section_name(psection);
5990 const char *item, *tag;
5991
5992 if (!ruleset_load_names(&s->name, nullptr, file, sec_name)) {
5993 return FALSE;
5994 }
5995
5997 "%s.short_name", sec_name);
5998 name_set(&s->abbreviation, nullptr, item);
5999
6000 tag = secfile_lookup_str(file, "%s.graphic", sec_name);
6001 if (nullptr == tag) {
6002 ruleset_error(nullptr, LOG_ERROR,
6003 "\"%s\": No graphic tag for specialist at %s.",
6004 secfile_name(file), sec_name);
6005 return FALSE;
6006 }
6007 sz_strlcpy(s->graphic_str, tag);
6010 "%s.graphic_alt", sec_name));
6011
6013 if (nullptr == reqs) {
6014 return FALSE;
6015 }
6017
6018 s->helptext = lookup_strvec(file, sec_name, "helptext");
6019
6020 return TRUE;
6021}
6022
6023/**********************************************************************/
6026static bool load_ruleset_cities(struct section_file *file,
6027 struct rscompat_info *compat)
6028{
6029 const char *filename = secfile_name(file);
6030 struct section_list *sec, *ssec = nullptr;
6031 int specs_count;
6032 bool ok = TRUE;
6033 int i = 0;
6034
6035 if (!rscompat_check_cap_and_version(file, filename, compat)) {
6036 return FALSE;
6037 }
6038
6039 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
6040 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
6041
6042 /* Specialist options */
6044
6045 if (!sec) {
6046 ruleset_error(nullptr, LOG_ERROR, "\"%s\": No normal specialists.", filename);
6047
6048 ok = FALSE;
6049 } else {
6052 /* Superspecialists are optional */
6053 if (ssec) {
6055 }
6056 if (specs_count >= SP_MAX) {
6057 ruleset_error(nullptr, LOG_ERROR,
6058 "\"%s\": Too many specialists (%d, max %d).",
6059 filename, specs_count, SP_MAX);
6060 ok = FALSE;
6061 }
6062 }
6063
6064
6065 if (ok) {
6067
6068 section_list_iterate(sec, psection) {
6069 struct specialist *s = specialist_by_number(i);
6070
6071 ok = load_specialist(psection, s, file);
6072
6073 if (!ok) {
6074 break;
6075 }
6076
6077 if (requirement_vector_size(&s->reqs) == 0 && DEFAULT_SPECIALIST == -1) {
6079 }
6080 i++;
6082 }
6083
6084 if (ok){
6085 if (DEFAULT_SPECIALIST == -1) {
6086 ruleset_error(nullptr, LOG_ERROR,
6087 "\"%s\": must have zero reqs for at least one "
6088 "specialist type.", filename);
6089 ok = FALSE;
6090 } else {
6092 }
6093 }
6095 sec = nullptr;
6096
6097 if (ssec) {
6098 if (ok) {
6099 section_list_iterate(ssec, psection) {
6100 struct specialist *s = specialist_by_number(i);
6101
6102 ok = load_specialist(psection, s, file);
6103
6104 if (!ok) {
6105 break;
6106 }
6107
6108 i++;
6110 }
6111
6113 ssec = nullptr;
6114 }
6115
6116 if (ok) {
6117 /* City Parameters */
6118
6121 "parameters.celebrate_size_limit");
6123 secfile_lookup_int_default(file, GAME_DEFAULT_ADDTOSIZE, "parameters.add_to_size_limit");
6126 "parameters.angry_citizens");
6127
6129 secfile_lookup_bool_default(file, GAME_DEFAULT_CHANGABLE_TAX, "parameters.changable_tax");
6131 secfile_lookup_int_default(file, 0, "parameters.forced_science");
6133 secfile_lookup_int_default(file, 100, "parameters.forced_luxury");
6135 secfile_lookup_int_default(file, 0, "parameters.forced_gold");
6137 + game.info.forced_gold != 100) {
6139 "\"%s\": Forced taxes do not add up in ruleset!",
6140 filename);
6141 ok = FALSE;
6142 }
6143 }
6144
6145 if (ok) {
6146 /* civ1 & 2 didn't reveal tiles */
6149 "parameters.vision_reveal_tiles");
6150
6152 secfile_lookup_int_default(file, 1, "parameters.pop_report_zeroes");
6153
6154 /* Citizens configuration. */
6157 "citizen.nationality");
6160 "citizen.ubuilder_nationality");
6163 "citizen.convert_speed");
6165 secfile_lookup_int_default(file, 0, "citizen.partisans_pct");
6167 secfile_lookup_int_default(file, 0, "citizen.conquest_convert_pct");
6168 }
6169
6170 if (ok) {
6171 /* Missing unit upkeep. */
6173
6174 /* Can't pay food upkeep! */
6176 auto_perf->cause = AAPC_UNIT_UPKEEP;
6177
6178 /* This is about food upkeep. */
6180 req_from_str("OutputType", "Local",
6181 FALSE, TRUE, TRUE,
6182 "Food"));
6183
6184 /* Internally represented as an action auto performer rule. */
6185 if (!load_muuk_as_action_auto(file, auto_perf, "food", filename)) {
6186 ok = FALSE;
6187 }
6188
6191 "missing_unit_upkeep.food_wipe");
6192
6193 /* Can't pay gold upkeep! */
6195 auto_perf->cause = AAPC_UNIT_UPKEEP;
6196
6197 /* This is about gold upkeep. */
6199 req_from_str("OutputType", "Local",
6200 FALSE, TRUE, TRUE,
6201 "Gold"));
6202
6203 /* Internally represented as an action auto performer rule. */
6204 if (!load_muuk_as_action_auto(file, auto_perf, "gold", filename)) {
6205 ok = FALSE;
6206 }
6207
6210 "missing_unit_upkeep.gold_wipe");
6211
6212 /* Can't pay shield upkeep! */
6214 auto_perf->cause = AAPC_UNIT_UPKEEP;
6215
6216 /* This is about shield upkeep. */
6218 req_from_str("OutputType", "Local",
6219 FALSE, TRUE, TRUE,
6220 "Shield"));
6221
6222 /* Internally represented as an action auto performer rule. */
6223 if (!load_muuk_as_action_auto(file, auto_perf, "shield", filename)) {
6224 ok = FALSE;
6225 }
6226
6229 "missing_unit_upkeep.shield_wipe");
6230 }
6231
6232 if (ok) {
6234 }
6235
6236 return ok;
6237}
6238
6239/**********************************************************************/
6242static bool load_ruleset_effects(struct section_file *file,
6243 struct rscompat_info *compat)
6244{
6245 struct section_list *sec;
6246 const char *filename;
6247 bool ok = TRUE;
6248
6249 filename = secfile_name(file);
6250
6251 if (!rscompat_check_cap_and_version(file, filename, compat)) {
6252 return FALSE;
6253 }
6254
6255 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
6256 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
6257
6259
6260 if (sec != NULL) {
6261 section_list_iterate(sec, psection) {
6262 const char *sec_name = section_name(psection);
6263 enum effect_type main_type;
6264 enum effect_type ai_valued_as;
6265 const char *type;
6266
6267 type = secfile_lookup_str(file, "%s.type", sec_name);
6268 if (type == NULL) {
6270 "\"%s\" [%s] missing effect type.",
6271 filename, sec_name);
6272 ok = FALSE;
6273 break;
6274 }
6278 "\"%s\" [%s] lists unknown effect type \"%s\".",
6279 filename, sec_name, type);
6280 ok = FALSE;
6281 break;
6282 }
6283 if (!is_user_effect(main_type)) {
6285 "\"%s\" [%s] type \"%s\" is not an user effect.",
6286 filename, sec_name, type);
6287 ok = FALSE;
6288 break;
6289 }
6290
6291 type = secfile_lookup_str(file, "%s.ai_valued_as", sec_name);
6292 if (type == NULL) {
6294 "\"%s\" [%s] missing ai_valued_as.",
6295 filename, sec_name);
6296 ok = FALSE;
6297 break;
6298 }
6302 "\"%s\" [%s] lists unknown ai_valued_as \"%s\".",
6303 filename, sec_name, type);
6304 ok = FALSE;
6305 break;
6306 }
6309 "\"%s\" [%s] ai_valued_as \"%s\" is an user effect.",
6310 filename, sec_name, type);
6311 ok = FALSE;
6312 break;
6313 }
6314
6316 /* It has been set already! */
6318 "\"%s\" [%s] Duplicate \"%s\" entry.",
6319 filename, sec_name, type);
6320 ok = FALSE;
6321 break;
6322 }
6323
6326
6328 }
6329
6330 /* Parse effects and add them to the effects ruleset cache. */
6332 section_list_iterate(sec, psection) {
6333 enum effect_type eff;
6334 int value;
6335 struct multiplier *pmul;
6336 struct effect *peffect;
6337 const char *sec_name = section_name(psection);
6338 struct requirement_vector *reqs;
6339 const char *type;
6340 const char *comment;
6341
6342 type = secfile_lookup_str(file, "%s.type", sec_name);
6343
6344 if (type == NULL) {
6346 "\"%s\" [%s] missing effect type.",
6347 filename, sec_name);
6348 ok = FALSE;
6349 break;
6350 }
6351
6352 if (compat->compat_mode && compat->version < RSFORMAT_3_4) {
6354 }
6355
6357 if (!effect_type_is_valid(eff)) {
6359 "\"%s\" [%s] lists unknown effect type \"%s\".",
6360 filename, sec_name, type);
6361 ok = FALSE;
6362 break;
6363 }
6364
6365 value = secfile_lookup_int_default(file, 1, "%s.value", sec_name);
6366
6367 {
6368 const char *multiplier_name
6369 = secfile_lookup_str(file, "%s.multiplier", sec_name);
6370
6371 if (multiplier_name) {
6373 if (!pmul) {
6375 "\"%s\" [%s] has unknown multiplier \"%s\".",
6376 filename, sec_name, multiplier_name);
6377 ok = FALSE;
6378 break;
6379 }
6380 } else {
6381 pmul = NULL;
6382 }
6383 }
6384
6385 peffect = effect_new(eff, value, pmul);
6386
6387 reqs = lookup_req_list(file, sec_name, "reqs", type);
6388 if (reqs == NULL) {
6389 ok = FALSE;
6390 break;
6391 }
6392
6396
6397 comment = secfile_lookup_str_default(file, NULL, "%s.comment", sec_name);
6398
6399 if (comment != NULL) {
6400 peffect->rulesave.comment = fc_strdup(comment);
6401 }
6402
6405
6406 if (ok) {
6408 }
6409
6410 return ok;
6411}
6412
6413/**********************************************************************/
6416static int secfile_lookup_int_default_min_max(struct section_file *file,
6417 int def, int min, int max,
6418 const char *path, ...)
6421 int def, int min, int max,
6422 const char *path, ...)
6423{
6424 char fullpath[256];
6425 int ival;
6426 va_list args;
6427
6428 va_start(args, path);
6429 fc_vsnprintf(fullpath, sizeof(fullpath), path, args);
6430 va_end(args);
6431
6432 if (!secfile_lookup_int(file, &ival, "%s", fullpath)) {
6433 ival = def;
6434 }
6435
6436 if (ival < min) {
6438 "\"%s\" should be in the interval [%d, %d] "
6439 "but is %d; using the minimal value.",
6440 fullpath, min, max, ival);
6441 ival = min;
6442 }
6443
6444 if (ival > max) {
6446 "\"%s\" should be in the interval [%d, %d] "
6447 "but is %d; using the maximal value.",
6448 fullpath, min, max, ival);
6449 ival = max;
6450 }
6451
6452 return ival;
6453}
6454
6455/**********************************************************************/
6458static bool load_action_range_max(struct section_file *file, action_id act)
6459{
6460 struct action *paction = action_by_number(act);
6461 const char *vname = action_max_range_ruleset_var_name(act);
6462
6463 if (vname != NULL) {
6464 struct entry *pentry;
6465 int max_range;
6466
6467 pentry = secfile_entry_lookup(file, "actions.%s", vname);
6468
6469 if (pentry == NULL) {
6471 } else {
6472 const char *custom;
6473
6476 /* max_range already assigned */
6477 } else if (entry_type_get(pentry) == ENTRY_STR
6481 } else {
6482 ruleset_error(NULL, LOG_ERROR, "Bad actions.%s",
6485
6486 return FALSE;
6487 }
6488 }
6489
6491 }
6492
6493 return TRUE;
6494}
6495
6496/**********************************************************************/
6499static bool load_action_range(struct section_file *file, action_id act)
6500{
6501 struct action *paction = action_by_number(act);
6502 const char *vname;
6503
6504 if (!load_action_range_max(file, act)) {
6505 return FALSE;
6506 }
6507
6509 if (vname != NULL) {
6510 /* Min range can be loaded from the ruleset. */
6514 "actions.%s",
6515 vname);
6516 }
6517
6518 return TRUE;
6519}
6520
6521/**********************************************************************/
6524static bool load_action_kind(struct section_file *file, action_id act)
6525{
6526 struct action *paction = action_by_number(act);
6528
6529 if (var_name != NULL) {
6533 paction->result),
6535 "actions.%s", var_name);
6536 } else {
6539 }
6540
6541 return TRUE;
6542}
6543
6544/**********************************************************************/
6548 action_id act)
6549{
6551 /* Actor consumption can be loaded from the ruleset. */
6554 file, RS_DEFAULT_ACTION_ACTOR_CONSUMING_ALWAYS, "actions.%s",
6556 }
6557
6558 return TRUE;
6559}
6560
6561/**********************************************************************/
6565 const char *filename,
6566 struct action *paction,
6567 struct rscompat_info *compat)
6568{
6570
6571 if (var_name != nullptr) {
6572 /* Action blocking can be loaded from the ruleset. */
6573 char fullpath[1024];
6574
6575 fc_snprintf(fullpath, sizeof(fullpath), "actions.%s", var_name);
6576
6577 if (secfile_entry_by_path(file, fullpath)) {
6579 size_t asize;
6580 int j;
6581
6584
6585 if (!blocking_actions) {
6586 /* Entity exists but couldn't read it. */
6588 "\"%s\": %s: bad action list",
6589 filename, fullpath);
6590
6591 return FALSE;
6592 }
6593
6594 for (j = 0; j < asize; j++) {
6595 BV_SET(paction->blocked_by, blocking_actions[j]);
6596 }
6597
6599 }
6600 }
6601
6602 return TRUE;
6603}
6604
6605/**********************************************************************/
6610 const char *filename,
6611 int performer_slot,
6612 struct action *paction)
6613{
6615 char action_list_path[100];
6616
6618 /* Not relevant. */
6619 return TRUE;
6620 }
6621
6623 auto_perf->cause = AAPC_POST_ACTION;
6624
6625 /* Limit auto performer to this action. */
6628 FALSE, TRUE, TRUE,
6629 paction->id));
6630
6631 /* Load the list of actions. */
6633 "actions.%s",
6636 action_list_path, filename)) {
6637 return FALSE;
6638 }
6639
6640 return TRUE;
6641}
6642
6643/**********************************************************************/
6646static bool lookup_bv_actions(struct section_file *file,
6647 const char *filename,
6648 bv_actions *target,
6649 const char *path)
6650{
6651 if (secfile_entry_by_path(file, path)) {
6653 size_t asize;
6654 int j;
6655
6657 "%s", path);
6658
6659 if (!listed_actions) {
6660 /* Entity exists but couldn't read it. */
6661 ruleset_error(NULL, LOG_ERROR, "\"%s\": %s: bad action list",
6662 filename, path);
6663
6664 return FALSE;
6665 }
6666
6667 for (j = 0; j < asize; j++) {
6668 BV_SET(*target, listed_actions[j]);
6669 }
6670
6672 }
6673
6674 return TRUE;
6675}
6676
6677/**********************************************************************/
6680static bool load_ruleset_game(struct section_file *file, bool act,
6681 struct rscompat_info *compat)
6682{
6683 const char *sval, **svec;
6684 const char *filename;
6685 int *food_ini;
6686 int i;
6687 size_t teams;
6688 const char *pref_text;
6689 size_t gni_tmp;
6690 struct section_list *sec;
6691 size_t nval;
6692 const char *name;
6693 bool ok = TRUE;
6694
6695 if (file == NULL) {
6696 return FALSE;
6697 }
6698 filename = secfile_name(file);
6699
6700 name = secfile_lookup_str_default(file, NULL, "ruledit.description_file");
6701 if (name != NULL) {
6703 }
6705 = secfile_lookup_bool_default(file, FALSE, "ruledit.std_tileset_compat");
6706
6707 /* Section: tileset */
6708 pref_text = secfile_lookup_str_default(file, "", "tileset.preferred");
6709 if (pref_text[0] != '\0') {
6710 /* There was tileset suggestion */
6712 } else {
6713 /* No tileset suggestions */
6714 game.control.preferred_tileset[0] = '\0';
6715 }
6716
6717 /* Section: soundset */
6718 pref_text = secfile_lookup_str_default(file, "", "soundset.preferred");
6719 if (pref_text[0] != '\0') {
6720 /* There was soundset suggestion */
6722 } else {
6723 /* No soundset suggestions */
6725 }
6726
6727 /* Section: musicset */
6728 pref_text = secfile_lookup_str_default(file, "", "musicset.preferred");
6729 if (pref_text[0] != '\0') {
6730 /* There was musicset suggestion */
6732 } else {
6733 /* No musicset suggestions */
6735 }
6736
6737 /* Section: about */
6738 pref_text = secfile_lookup_str(file, "about.name");
6739 /* Ruleset/modpack name found */
6741
6742 pref_text = secfile_lookup_str_default(file, "", "about.version");
6743 if (pref_text[0] != '\0') {
6744 /* Ruleset/modpack version found */
6746 } else {
6747 /* No version information */
6748 game.control.version[0] = '\0';
6749 }
6750
6751 pref_text = secfile_lookup_str_default(file, "", "about.alt_dir");
6752 if (pref_text[0] != '\0') {
6753 /* Alt directory definition found. */
6755 } else {
6756 /* No alt directory information */
6757 game.control.alt_dir[0] = '\0';
6758 }
6759
6760 pref_text = secfile_lookup_str_default(file, "", "about.summary");
6761 if (pref_text[0] != '\0') {
6762 int len;
6763
6764 /* Ruleset/modpack summary found */
6765 len = strlen(pref_text);
6768 } else {
6769 /* No summary */
6770 if (game.ruleset_summary != NULL) {
6773 }
6774 }
6775
6776 pref_text = secfile_lookup_str_default(file, "", "about.description");
6777 if (pref_text[0] != '\0') {
6778 int len;
6779
6780 /* Ruleset/modpack description found */
6781 len = strlen(pref_text);
6785 } else {
6786 /* No description */
6787 if (game.ruleset_description != NULL) {
6790 }
6792 }
6793
6794 pref_text = secfile_lookup_str_default(file, "", "about.capabilities");
6795 if (pref_text[0] != '\0') {
6796 int len = strlen(pref_text);
6797
6800 } else {
6802 game.ruleset_capabilities[0] = '\0';
6803 }
6804
6805 /* Section: options */
6806 if (!lookup_tech_list(file, "options", "global_init_techs",
6807 game.rgame.global_init_techs, filename)) {
6808 ok = FALSE;
6809 }
6810
6811 if (ok) {
6812 if (!lookup_building_list(file, "options", "global_init_buildings",
6813 game.rgame.global_init_buildings, filename)) {
6814 ok = FALSE;
6815 }
6816 }
6817
6818 if (ok) {
6819 const char **slist;
6820 int j;
6821
6823 "options.popup_tech_help");
6824
6825 /* section: civstyle */
6828 "civstyle.base_pollution");
6829
6831
6832 slist = secfile_lookup_str_vec(file, &nval, "civstyle.gameloss_style");
6833 for (j = 0; j < nval; j++) {
6834 enum gameloss_style style;
6835
6836 sval = slist[j];
6837 if (strcmp(sval, "") == 0) {
6838 continue;
6839 }
6841 if (!gameloss_style_is_valid(style)) {
6843 "\"%s\": bad value \"%s\" for gameloss_style.",
6844 filename, sval);
6845 ok = FALSE;
6846 break;
6847 } else {
6848 game.info.gameloss_style |= style;
6849 }
6850 }
6851 free(slist);
6852 }
6853
6854 if (ok) {
6860 "civstyle.happy_cost");
6866 "civstyle.food_cost");
6872 "civstyle.base_bribe_cost");
6878 "civstyle.ransom_gold");
6881 "civstyle.pillage_select");
6882
6885 "civstyle.tech_steal_allow_holes");
6888 "civstyle.tech_trade_allow_holes");
6891 "civstyle.tech_trade_loss_allow_holes");
6894 "civstyle.tech_parasite_allow_holes");
6897 "civstyle.tech_loss_allow_holes");
6898
6904 "civstyle.upgrade_veteran_loss");
6910 "civstyle.autoupgrade_veteran_loss");
6911
6917 "research.base_tech_cost");
6918
6924 "research.min_tech_cost");
6925
6927 "civstyle.granary_food_ini");
6929
6932 "Too many granary_food_ini entries (%d, max %d)",
6934 ok = FALSE;
6935 } else if (game.info.granary_num_inis == 0) {
6936 log_error("No values for granary_food_ini. Using default "
6937 "value %d.", RS_DEFAULT_GRANARY_FOOD_INI);
6940 } else {
6941 int gi;
6942
6943 /* check for <= 0 entries */
6944 for (gi = 0; gi < game.info.granary_num_inis; gi++) {
6945 if (food_ini[gi] <= 0) {
6946 if (gi == 0) {
6948 } else {
6949 food_ini[gi] = food_ini[gi - 1];
6950 }
6951 log_error("Bad value for granary_food_ini[%i]. Using %i.",
6952 gi, food_ini[gi]);
6953 }
6955 }
6956 }
6957 free(food_ini);
6958 }
6959
6960 if (ok) {
6966 "civstyle.granary_food_inc");
6967
6974 "civstyle.min_city_center_%s",
6977 }
6978
6979 if (ok) {
6980 const char *tus_text;
6981
6987 "civstyle.init_vis_radius_sq");
6988
6994 "civstyle.init_city_radius_sq");
6995
6997 "civstyle.gold_upkeep_style");
7002 "Unknown gold upkeep style \"%s\"",
7003 tus_text);
7004 ok = FALSE;
7005 }
7006
7007 if (compat->compat_mode
7008 && compat->version < RSFORMAT_3_4) {
7010 = secfile_lookup_bool_default(file, FALSE, "civstyle.homeless_gold_upkeep");
7011
7015 "Cannot have homeless_gold_upkeep while gold_upkeep_style \"City\".");
7016 ok = FALSE;
7017 }
7018 } else {
7020 }
7021
7023 "civstyle.output_granularity");
7024
7026 = secfile_lookup_bool_default(file, FALSE, "civstyle.airlift_from_always_enabled");
7027
7029 = secfile_lookup_bool_default(file, TRUE, "civstyle.airlift_to_always_enabled");
7030
7031 /* Section: wonder_visibility */
7032 if (ok) {
7033 const char *text;
7034
7035 text = secfile_lookup_str_default(file,
7037 "wonder_visibility.small_wonders");
7038
7043 "Unknown wonder visibility type \"%s\"",
7044 text);
7045 ok = FALSE;
7046 }
7047 }
7048
7049 /* section: illness */
7052 "illness.illness_on");
7058 "illness.illness_base_factor");
7064 "illness.illness_min_size");
7070 "illness.illness_trade_infection");
7076 "illness.illness_pollution_factor");
7077
7078 /* section: incite_cost */
7084 "incite_cost.base_incite_cost");
7090 "incite_cost.improvement_factor");
7096 "incite_cost.unit_factor");
7102 "incite_cost.total_factor");
7103 }
7104
7105 if (ok) {
7106 const char *tus_text;
7107
7108 /* Section: combat_rules */
7111 "combat_rules.tired_attack");
7112
7115 "combat_rules.only_killing_makes_veteran");
7116
7119 "combat_rules.only_real_fight_makes_veteran");
7120
7123 "combat_rules.combat_odds_scaled_veterancy");
7124
7127 "combat_rules.damage_reduces_bombard_rate");
7128
7131 "combat_rules.low_firepower_badwallattacker");
7134 "combat_rules.low_firepower_pearl_harbor");
7135
7138 "combat_rules.low_firepower_combat_bonus");
7141 "combat_rules.low_firepower_nonnat_bombard");
7142
7147 "combat_rules.nuke_pop_loss_pct");
7148
7153 "combat_rules.nuke_defender_survival_chance_pct");
7154
7155 /* section: borders */
7161 "borders.radius_sq_city");
7167 "borders.size_effect");
7168
7174 "borders.radius_sq_city_permanent");
7175
7176 /* section: research */
7178 "research.tech_cost_style");
7183 "Unknown tech cost style \"%s\"",
7184 tus_text);
7185 ok = FALSE;
7186 }
7187
7189 "research.tech_leakage");
7194 "Unknown tech leakage \"%s\"",
7195 tus_text);
7196 ok = FALSE;
7197 }
7200 log_error("Only tech_leakage \"%s\" supported with "
7201 "tech_cost_style \"%s\". ",
7204 log_error("Switching to tech_leakage \"%s\".",
7207 }
7213 "research.base_tech_cost");
7214
7216 "research.tech_upkeep_style");
7217
7219
7222 "Unknown tech upkeep style \"%s\"",
7223 tus_text);
7224 ok = FALSE;
7225 }
7226 }
7227
7228 if (ok) {
7234 "research.tech_upkeep_divider");
7235
7236 sval = secfile_lookup_str_default(file, NULL, "research.free_tech_method");
7237 if (sval == NULL) {
7239 "No free_tech_method given");
7240 ok = FALSE;
7241 } else {
7245 "Bad value %s for free_tech_method.", sval);
7246 ok = FALSE;
7247 }
7248 }
7249 }
7250
7251 if (ok) {
7252 int cf;
7253
7254 /* section: culture */
7257 "culture.victory_min_points");
7260 "culture.victory_lead_pct");
7263 "culture.migration_pml");
7266 "culture.history_interest_pml");
7267
7268 /* section: world_peace */
7271 "world_peace.victory_turns");
7272
7273 /* section: calendar */
7276 "calendar.skip_year_0");
7279 "calendar.start_year");
7281 = secfile_lookup_int_default(file, 0, "calendar.fragments");
7282
7285 "Too many calendar fragments. Max is %d",
7287 ok = FALSE;
7289 }
7293 "calendar.positive_label"));
7297 "calendar.negative_label"));
7298
7299 for (cf = 0; cf < game.calendar.calendar_fragments; cf++) {
7300 const char *fname;
7301
7302 fname = secfile_lookup_str_default(file, NULL, "calendar.fragment_name%d", cf);
7303 if (fname != NULL) {
7306 }
7307 }
7308 }
7309
7310 if (ok) {
7311 /* section playercolors */
7312 struct rgbcolor *prgbcolor = NULL;
7313 bool color_read = TRUE;
7314
7315 /* Check if the player list is defined and empty. */
7316 if (playercolor_count() != 0) {
7317 ok = FALSE;
7318 } else {
7319 i = 0;
7320
7321 while (color_read) {
7322 prgbcolor = NULL;
7323
7324 color_read = rgbcolor_load(file, &prgbcolor, "playercolors.colorlist%d", i);
7325 if (color_read) {
7327 }
7328
7329 i++;
7330 }
7331
7332 if (playercolor_count() == 0) {
7333 ruleset_error(NULL, LOG_ERROR, "No player colors defined!");
7334 ok = FALSE;
7335 }
7336
7337 if (ok) {
7339 if (!rgbcolor_load(file, &game.plr_bg_color, "playercolors.background")) {
7341 "No background player color defined! (%s)",
7342 secfile_error());
7343 ok = FALSE;
7344 }
7345 }
7346 }
7347 }
7348
7349 if (ok) {
7350 /* section: teams */
7351 svec = secfile_lookup_str_vec(file, &teams, "teams.names");
7352 if (team_slot_count() < teams) {
7354 }
7356 for (i = 0; i < teams; i++) {
7358 }
7359 free(svec);
7360
7362 nval = (NULL != sec ? section_list_size(sec) : 0);
7363 if (nval > MAX_DISASTER_TYPES) {
7364 int num = nval; /* No "size_t" to printf */
7365
7367 "\"%s\": Too many disaster types (%d, max %d)",
7368 filename, num, MAX_DISASTER_TYPES);
7370 ok = FALSE;
7371 } else {
7373 }
7374 }
7375
7376 if (ok) {
7378 int id = disaster_index(pdis);
7379 int j;
7380 size_t eff_count;
7381 struct requirement_vector *reqs;
7382 const char *sec_name = section_name(section_list_get(sec, id));
7383
7384 if (!ruleset_load_names(&pdis->name, NULL, file, sec_name)) {
7386 "\"%s\": Cannot load disaster names",
7387 filename);
7388 ok = FALSE;
7389 break;
7390 }
7391
7393 if (reqs == NULL) {
7394 ok = FALSE;
7395 break;
7396 }
7398
7400 "%s.frequency", sec_name);
7401
7402 svec = secfile_lookup_str_vec(file, &eff_count, "%s.effects", sec_name);
7403
7404 BV_CLR_ALL(pdis->effects);
7405 for (j = 0; j < eff_count; j++) {
7406 const char *dsval = svec[j];
7408
7410
7413 "\"%s\" disaster \"%s\": unknown effect \"%s\".",
7414 filename, disaster_rule_name(pdis), dsval);
7415 ok = FALSE;
7416 break;
7417 } else {
7418 BV_SET(pdis->effects, effect);
7419 }
7420 }
7421
7422 free(svec);
7423
7424 if (!ok) {
7425 break;
7426 }
7429 }
7430
7431 if (ok) {
7433
7435 int id = achievement_index(pach);
7436 const char *sec_name = section_name(section_list_get(sec, id));
7437 const char *typename;
7438 const char *msg;
7439
7440 typename = secfile_lookup_str_default(file, NULL, "%s.type", sec_name);
7441
7442 pach->type = achievement_type_by_name(typename, fc_strcasecmp);
7443 if (!achievement_type_is_valid(pach->type)) {
7445 "Achievement has unknown type \"%s\".",
7446 typename != NULL ? typename : "(NULL)");
7447 ok = FALSE;
7448 }
7449
7450 if (ok) {
7452 "%s.unique", sec_name);
7453
7455 "%s.value", sec_name);
7456 pach->culture = secfile_lookup_int_default(file, 0,
7457 "%s.culture", sec_name);
7458
7459 msg = secfile_lookup_str_default(file, NULL, "%s.first_msg", sec_name);
7460 if (msg == NULL) {
7462 "Achievement %s has no first msg!", sec_name);
7463 ok = FALSE;
7464 } else {
7465 pach->first_msg = fc_strdup(msg);
7466 }
7467 }
7468
7469 if (ok) {
7470 msg = secfile_lookup_str_default(file, NULL, "%s.cons_msg", sec_name);
7471 if (msg == NULL) {
7472 if (!pach->unique) {
7474 "Achievement %s has no msg for consecutive gainers!",
7475 sec_name);
7476 ok = FALSE;
7477 }
7478 } else {
7479 pach->cons_msg = fc_strdup(msg);
7480 }
7481 }
7482
7483 if (!ok) {
7484 break;
7485 }
7488 }
7489
7490 if (ok) {
7491 for (i = 0; (name = secfile_lookup_str_default(file, NULL,
7492 "trade.settings%d.type",
7493 i)); i++) {
7495
7496 if (type == TRT_LAST) {
7498 "\"%s\" unknown trade route type \"%s\".",
7499 filename, name);
7500 ok = FALSE;
7501 } else {
7503 const char *cancelling;
7504 const char *bonus;
7505
7506 set->trade_pct = secfile_lookup_int_default(file, 100,
7507 "trade.settings%d.pct", i);
7508 cancelling = secfile_lookup_str_default(file, "Active",
7509 "trade.settings%d.cancelling", i);
7511 if (set->cancelling == TRI_LAST) {
7513 "\"%s\" unknown trade route cancelling type \"%s\".",
7514 filename, cancelling);
7515 ok = FALSE;
7516 }
7517
7518 bonus = secfile_lookup_str_default(file, "None", "trade.settings%d.bonus", i);
7519
7521
7524 "\"%s\" unknown trade route bonus type \"%s\".",
7525 filename, bonus);
7526 ok = FALSE;
7527 }
7528 }
7529 }
7530 }
7531
7532 if (ok) {
7533 const char *str;
7534
7536 = secfile_lookup_int_default(file, 0, "trade.min_trade_route_val");
7537
7540 "trade.reveal_trade_partner");
7541
7544 "trade.goods_selection");
7545
7547
7550 "\"%s\" goods selection method \"%s\" unknown.",
7551 filename, str);
7552 ok = FALSE;
7553 }
7554 }
7555
7556 if (ok) {
7558
7560 int id = goods_index(pgood);
7561 const char *sec_name = section_name(section_list_get(sec, id));
7562 struct requirement_vector *reqs;
7563 const char **slist;
7564 int j;
7565
7567 if (reqs == NULL) {
7568 ok = FALSE;
7569 break;
7570 }
7572
7573 pgood->from_pct = secfile_lookup_int_default(file, 100,
7574 "%s.from_pct", sec_name);
7575 pgood->to_pct = secfile_lookup_int_default(file, 100,
7576 "%s.to_pct", sec_name);
7577 pgood->onetime_pct = secfile_lookup_int_default(file, 100,
7578 "%s.onetime_pct", sec_name);
7579 pgood->select_priority = secfile_lookup_int_default(file, 1,
7580 "%s.select_priority", sec_name);
7581 pgood->replace_priority = secfile_lookup_int_default(file, 1,
7582 "%s.replace_priority", sec_name);
7583
7584 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
7585 BV_CLR_ALL(pgood->flags);
7586 for (j = 0; j < nval; j++) {
7587 enum goods_flag_id flag;
7588
7589 sval = slist[j];
7591 if (!goods_flag_id_is_valid(flag)) {
7592 ruleset_error(NULL, LOG_ERROR, "\"%s\" good \"%s\": unknown flag \"%s\".",
7593 filename, goods_rule_name(pgood), sval);
7594 ok = FALSE;
7595 break;
7596 } else {
7597 BV_SET(pgood->flags, flag);
7598 }
7599 }
7600 free(slist);
7601
7602 pgood->helptext = lookup_strvec(file, sec_name, "helptext");
7605 }
7606
7607 if (ok) {
7608 const char *uname = secfile_lookup_str_default(file, nullptr,
7609 "aarea.access_unit");
7610 const struct unit_type *access_unit = nullptr;
7611
7612 if (uname != nullptr && uname[0] != '\0') {
7613 access_unit = unit_type_by_rule_name(uname);
7614
7615 if (access_unit == nullptr) {
7616 ruleset_error(nullptr, LOG_ERROR, "%s: access unit %s unknown.",
7617 filename, uname);
7618 ok = FALSE;
7619 }
7620 }
7621
7622 access_info_init(access_unit);
7623 }
7624
7625 if (ok) {
7627
7628 if (sec != NULL) {
7629 int num = section_list_size(sec);
7630
7631 for (i = 0; i < num; i++) {
7632 const char *sec_name = section_name(section_list_get(sec, i));
7633 const char *clause_name = secfile_lookup_str_default(file, NULL,
7634 "%s.type", sec_name);
7636 struct clause_info *info;
7637 struct requirement_vector *reqs;
7638
7639 if (!clause_type_is_valid(type)) {
7641 "\"%s\" unknown clause type \"%s\".",
7642 filename, clause_name);
7643 ok = FALSE;
7644 break;
7645 }
7646
7647 info = clause_info_get(type);
7648
7649 if (info->enabled) {
7651 "\"%s\" duplicate clause type \"%s\" definition.",
7652 filename, clause_name);
7653 ok = FALSE;
7654 break;
7655 }
7656
7657 reqs = lookup_req_list(file, sec_name, "giver_reqs", clause_name);
7658 if (reqs == NULL) {
7659 ok = FALSE;
7660 break;
7661 }
7663
7664 reqs = lookup_req_list(file, sec_name, "receiver_reqs", clause_name);
7665 if (reqs == NULL) {
7666 ok = FALSE;
7667 break;
7668 }
7670
7671 reqs = lookup_req_list(file, sec_name, "either_reqs", clause_name);
7672 if (reqs == NULL) {
7673 ok = FALSE;
7674 break;
7675 }
7677
7678 info->enabled = TRUE;
7679 }
7680 }
7682 }
7683
7684 if (ok) {
7686
7687 if (sec != NULL) {
7688 int num = section_list_size(sec);
7689 int curr;
7690
7691 for (curr = 0; curr < num; curr++) {
7692
7693 struct counter *pcount = counter_by_id(curr);
7694 const char *sec_name = section_name(section_list_get(sec, curr));
7695 const char *counter_type = secfile_lookup_str_default(file, NULL,
7696 "%s.type",
7697 sec_name);
7698
7701 if (!counter_behavior_is_valid(cb)) {
7703 "\"%s\" unknown counter type \"%s\".",
7704 filename, counter_type);
7705 ok = FALSE;
7706 break;
7707 }
7708
7709 if (!ruleset_load_names(&pcount->name, NULL, file, sec_name)) {
7711 "\"%s\": Cannot load counter names",
7712 filename);
7713 ok = FALSE;
7714 break;
7715 }
7716
7717 pcount->helptext = lookup_strvec(file, sec_name, "helptext");
7718 pcount->type = cb;
7719 if (!secfile_lookup_int(file, &pcount->checkpoint,
7720 "%s.checkpoint", sec_name)) {
7721
7723 "\"%s\": No checkpoint value",
7724 filename);
7725 ok = FALSE;
7726 break;
7727 }
7728
7729 pcount->target = CTGT_CITY;
7730 pcount->index = curr;
7731 pcount->def = secfile_lookup_int_default(file, 0,
7732 "%s.def",
7733 sec_name);
7735 }
7736 }
7737 }
7738
7739 /* secfile_check_unused() is not here, but only after also settings section
7740 * has been loaded. */
7741
7742 return ok;
7743}
7744
7745/**********************************************************************/
7748static bool load_ruleset_actions(struct section_file *file,
7749 struct section_file *gamefile,
7750 struct rscompat_info *compat)
7751{
7752 bool ok = TRUE;
7753 const char *filename = secfile_name(file);
7754 struct section_list *sec;
7756 struct requirement_vector *reqs;
7757
7758 /* Auto attack. */
7759
7760 /* Action auto performers aren't ready to be exposed in the ruleset
7761 * yet. The behavior when two action auto performers for the same
7762 * cause can fire isn't set in stone yet. How is one of them chosen?
7763 * What if all the actions of the chosen action auto performer turned
7764 * out to be illegal but one of the other action auto performers that
7765 * fired has legal actions? These issues can decide what other action
7766 * rules action auto performers can represent in the future. Deciding
7767 * should therefore wait until a rule needs action auto performers to
7768 * work a certain way. */
7769 /* Only one action auto performer, ACTION_AUTO_MOVED_ADJ, is caused
7770 * by AAPC_UNIT_MOVED_ADJ. It is therefore safe to expose the full
7771 * requirement vector to the ruleset. */
7772
7773 /* A unit moved next to this unit and the autoattack server setting
7774 * is enabled. */
7777
7778 reqs = lookup_req_list(file,
7779 "auto_attack", "if_attacker",
7780 "auto_attack");
7781 if (reqs == NULL) {
7782 ok = FALSE;
7783 } else {
7785
7787 "auto_attack.attack_actions",
7788 filename)) {
7789 /* Failed to load auto attack actions */
7791 "\"%s\": %s: failed load %s.",
7792 filename, "auto_attack", "attack_actions");
7793 ok = FALSE;
7794 }
7795 }
7796
7797 /* Section: actions */
7798 if (ok) {
7799 action_iterate(act_id) {
7800 struct action *paction = action_by_number(act_id);
7801
7802 if (!load_action_blocked_by_list(file, filename, paction, compat)) {
7803 ok = FALSE;
7804 break;
7805 }
7807
7808 if (ok) {
7809 if (!lookup_bv_actions(file, filename,
7811 "actions.diplchance_initial_odds")) {
7812 ok = FALSE;
7813 }
7814 }
7815
7816 if (ok) {
7817 /* If the "Poison City" action or the "Poison City Escape" action
7818 * should empty the granary. */
7819 /* TODO: empty granary and reduce population should become separate
7820 * action effect flags when actions are generalized. */
7824 "actions.poison_empties_food_stock");
7825
7826 /* If the "Steal Maps" action or the "Steal Maps Escape" action always
7827 * will reveal all cities when successful. */
7831 "actions.steal_maps_reveals_all_cities");
7832
7833 /* Allow setting certain properties for some actions before
7834 * generalized actions. */
7835 action_iterate(act_id) {
7836 if (!load_action_range(file, act_id)) {
7837 ok = FALSE;
7838 } else if (!load_action_kind(file, act_id)) {
7839 ok = FALSE;
7840 } else if (!load_action_actor_consuming_always(file, act_id)) {
7841 ok = FALSE;
7842 }
7843
7844 if (!ok) {
7845 break;
7846 }
7848 }
7849
7850 if (ok) {
7851 /* The quiet (don't auto generate help for) property of all actions
7852 * live in a single enum vector. This avoids generic action
7853 * expectations. */
7854 if (secfile_entry_by_path(file, "actions.quiet_actions")) {
7856 size_t asize;
7857 int j;
7858
7861 "actions.quiet_actions");
7862
7863 if (!quiet_actions) {
7864 /* Entity exists but couldn't read it. */
7866 "\"%s\": actions.quiet_actions: bad action list",
7867 filename);
7868
7869 ok = FALSE;
7870 } else {
7871 for (j = 0; j < asize; j++) {
7872 /* Don't auto generate help text for this action. */
7874 }
7875
7877 }
7878 }
7879 }
7880
7881 if (ok) {
7882 /* Hard code action sub results for now. */
7883
7884 /* Unit Enter Hut */
7886 BV_SET(paction->sub_results, ACT_SUB_RES_HUT_ENTER);
7896
7897 /* Unit Frighten Hut */
7909
7910 /* Unit May Embark */
7911 action_iterate(act_id) {
7912 struct action *paction = action_by_number(act_id);
7913
7915 "civstyle.paradrop_to_transport")
7918 BV_SET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK);
7919 }
7920
7921 /* Embark actions will always embark, not maybe embark. */
7923
7924 /* Non Lethal bombard */
7931 }
7932 }
7933
7934 if (ok) {
7935 /* Forced actions after another action was successfully performed. */
7936
7937 if (!load_action_post_success_force(file, filename,
7941 ok = FALSE;
7942 } else if (!load_action_post_success_force(file, filename,
7946 ok = FALSE;
7947 } else if (!load_action_post_success_force(file, filename,
7950 ACTION_ATTACK))) {
7951 ok = FALSE;
7952 } else if (!load_action_post_success_force(file, filename,
7955 ACTION_ATTACK2))) {
7956 ok = FALSE;
7957 } else if (!load_action_post_success_force(file, filename,
7961 ok = FALSE;
7962 } else if (!load_action_post_success_force(file, filename,
7966 ok = FALSE;
7967 }
7968
7969 /* No "Suicide Attack". Can't act when dead. */
7970 }
7971
7972 if (ok) {
7973 /* The city that made the unit's current tile native is gone.
7974 * Evaluated against an adjacent tile. */
7976 auto_perf->cause = AAPC_CITY_GONE;
7977
7978 /* I have no objections to moving this out of game's actions to
7979 * cities.ruleset, units.ruleset or an other location in game.ruleset
7980 * you find more suitable. -- Sveinung */
7982 "actions.escape_city", filename)) {
7983 ok = FALSE;
7984 }
7985 }
7986
7987 if (ok) {
7988 /* The unit's stack has been defeated and is scheduled for execution
7989 * but the unit has the CanEscape unit type flag.
7990 * Evaluated against an adjacent tile. */
7993
7994 /* I have no objections to moving this out of game's actions to
7995 * cities.ruleset, units.ruleset or an other location in game.ruleset
7996 * you find more suitable. -- Sveinung */
7998 "actions.unit_stack_death", filename)) {
7999 ok = FALSE;
8000 }
8001 }
8002
8003 if (ok) {
8005 if (sec != nullptr) {
8006 section_list_iterate(sec, psection) {
8007 const char *sec_name = section_name(psection);
8008 const char *action_text;
8009 struct action *paction;
8010 const char *ui_name;
8011
8012 action_text = secfile_lookup_str(file, "%s.action", sec_name);
8013
8014 if (action_text == nullptr) {
8015 ruleset_error(nullptr, LOG_ERROR,
8016 "\"%s\" [%s] missing action to configure.",
8017 filename, sec_name);
8018 ok = FALSE;
8019 break;
8020 }
8021
8023 if (paction == nullptr) {
8024 ruleset_error(nullptr, LOG_ERROR,
8025 "\"%s\" [%s] lists unknown action type \"%s\".",
8026 filename, sec_name, action_text);
8027 ok = FALSE;
8028 break;
8029 }
8030
8031 if (paction->configured) {
8032 ruleset_error(nullptr, LOG_ERROR,
8033 "\"%s\" [%s] duplicate configuration for action \"%s\".",
8034 filename, sec_name, action_text);
8035 ok = FALSE;
8036 break;
8037 }
8038
8039 paction->configured = TRUE;
8040
8041 ui_name = secfile_lookup_str_default(file, nullptr,
8042 "%s.ui_name", sec_name);
8043 if (ui_name == nullptr) {
8045 }
8046 sz_strlcpy(paction->ui_name, ui_name);
8048 }
8049 }
8050
8051 if (ok) {
8052 action_iterate(act) {
8053 struct action *paction = action_by_number(act);
8054
8055 if (!paction->configured) {
8057 }
8059 }
8060
8061 if (ok) {
8063
8064 if (sec != nullptr) {
8065 section_list_iterate(sec, psection) {
8066 struct action_enabler *enabler;
8067 const char *sec_name = section_name(psection);
8068 struct action *paction;
8069 struct requirement_vector *actor_reqs;
8070 struct requirement_vector *target_reqs;
8071 const char *action_text;
8072 const char *comment;
8073
8075
8076 action_text = secfile_lookup_str(file, "%s.action", sec_name);
8077
8078 if (action_text == nullptr) {
8079 ruleset_error(nullptr, LOG_ERROR,
8080 "\"%s\" [%s] missing action to enable.",
8081 filename, sec_name);
8082 ok = FALSE;
8083 break;
8084 }
8085
8087 if (paction == nullptr) {
8088 ruleset_error(nullptr, LOG_ERROR,
8089 "\"%s\" [%s] lists unknown action type \"%s\".",
8090 filename, sec_name, action_text);
8091 ok = FALSE;
8092 break;
8093 }
8094
8095 enabler->action = action_id(paction);
8096
8097 actor_reqs = lookup_req_list(file, sec_name, "actor_reqs", action_text);
8098 if (actor_reqs == NULL) {
8099 ok = FALSE;
8100 break;
8101 }
8102
8103 requirement_vector_copy(&enabler->actor_reqs, actor_reqs);
8104
8105 target_reqs = lookup_req_list(file, sec_name, "target_reqs", action_text);
8106 if (target_reqs == NULL) {
8107 ok = FALSE;
8108 break;
8109 }
8110
8111 requirement_vector_copy(&enabler->target_reqs, target_reqs);
8112
8113 comment = secfile_lookup_str(file, "%s.comment", sec_name);
8114 if (comment != nullptr) {
8115 enabler->rulesave.comment = fc_strdup(comment);
8116 }
8117
8120
8122 }
8123 }
8124
8125 return ok;
8126}
8127
8128/**********************************************************************/
8132static void send_ruleset_unit_classes(struct conn_list *dest)
8133{
8134 struct packet_ruleset_unit_class packet;
8136 int i;
8137
8138 for (i = 0; i < MAX_NUM_USER_UCLASS_FLAGS; i++) {
8139 const char *flagname;
8140 const char *helptxt;
8141
8143
8145 if (flagname == NULL) {
8146 fpacket.name[0] = '\0';
8147 } else {
8149 }
8150
8152 if (helptxt == NULL) {
8153 fpacket.helptxt[0] = '\0';
8154 } else {
8155 sz_strlcpy(fpacket.helptxt, helptxt);
8156 }
8157
8159 }
8160
8162 packet.id = uclass_number(c);
8163 sz_strlcpy(packet.name, untranslated_name(&c->name));
8164 sz_strlcpy(packet.rule_name, rule_name_get(&c->name));
8165 packet.min_speed = c->min_speed;
8166 packet.hp_loss_pct = c->hp_loss_pct;
8167 packet.non_native_def_pct = c->non_native_def_pct;
8168 packet.flags = c->flags;
8169
8170 PACKET_STRVEC_INSERT(packet.helptext, c->helptext);
8171
8172 lsend_packet_ruleset_unit_class(dest, &packet);
8174}
8175
8176/**********************************************************************/
8180static void send_ruleset_units(struct conn_list *dest)
8181{
8182 struct packet_ruleset_unit packet;
8183#ifdef FREECIV_WEB
8185#endif /* FREECIV_WEB */
8187 int i;
8188
8189 for (i = 0; i < MAX_NUM_USER_UNIT_FLAGS; i++) {
8190 const char *flagname;
8191 const char *helptxt;
8192
8194
8196 if (flagname == NULL) {
8197 fpacket.name[0] = '\0';
8198 } else {
8200 }
8201
8203 if (helptxt == NULL) {
8204 fpacket.helptxt[0] = '\0';
8205 } else {
8206 sz_strlcpy(fpacket.helptxt, helptxt);
8207 }
8208
8210 }
8211
8213 packet.id = utype_number(u);
8214 sz_strlcpy(packet.name, untranslated_name(&u->name));
8215 sz_strlcpy(packet.rule_name, rule_name_get(&u->name));
8216 sz_strlcpy(packet.sound_move, u->sound_move);
8217 sz_strlcpy(packet.sound_move_alt, u->sound_move_alt);
8218 sz_strlcpy(packet.sound_fight, u->sound_fight);
8219 sz_strlcpy(packet.sound_fight_alt, u->sound_fight_alt);
8220 sz_strlcpy(packet.graphic_str, u->graphic_str);
8221 sz_strlcpy(packet.graphic_alt, u->graphic_alt);
8222 sz_strlcpy(packet.graphic_alt2, u->graphic_alt2);
8224 packet.build_cost = u->build_cost;
8225 packet.pop_cost = u->pop_cost;
8226 packet.spectype_id = specialist_index(u->spec_type);
8227 packet.attack_strength = u->attack_strength;
8228 packet.defense_strength = u->defense_strength;
8229 packet.move_rate = u->move_rate;
8230
8231 /* Shallow-copy (borrow) requirement vector */
8232 packet.build_reqs = u->build_reqs;
8233
8234 packet.vision_radius_sq = u->vision_radius_sq;
8235 packet.transport_capacity = u->transport_capacity;
8236 packet.hp = u->hp;
8237 packet.firepower = u->firepower;
8238 packet.obsoleted_by = u->obsoleted_by
8239 ? utype_number(u->obsoleted_by)
8240 : utype_count();
8241 packet.converted_to = u->converted_to
8242 ? utype_number(u->converted_to)
8243 : utype_count();
8244 packet.convert_time = u->convert_time;
8245 packet.fuel = u->fuel;
8246 packet.flags = u->flags;
8247 packet.roles = u->roles;
8248 packet.happy_cost = u->happy_cost;
8250 packet.upkeep[o] = u->upkeep[o];
8252 packet.paratroopers_range = u->paratroopers_range;
8253 packet.bombard_rate = u->bombard_rate;
8254 packet.city_size = u->city_size;
8255 packet.city_slots = u->city_slots;
8256 packet.tp_defense = u->tp_defense;
8257 packet.cargo = u->cargo;
8258 packet.targets = u->targets;
8259 packet.embarks = u->embarks;
8260 packet.disembarks = u->disembarks;
8261 packet.vlayer = u->vlayer;
8262
8263 if (u->veteran == NULL) {
8264 /* Use the default veteran system. */
8265 packet.veteran_levels = 0;
8266 } else {
8267 /* Per unit veteran system definition. */
8269
8270 for (i = 0; i < packet.veteran_levels; i++) {
8271 const struct veteran_level *vlevel = utype_veteran_level(u, i);
8272
8274 packet.power_fact[i] = vlevel->power_fact;
8275 packet.move_bonus[i] = vlevel->move_bonus;
8276 packet.base_raise_chance[i] = vlevel->base_raise_chance;
8277 packet.work_raise_chance[i] = vlevel->work_raise_chance;
8278 }
8279 }
8280 PACKET_STRVEC_INSERT(packet.helptext, u->helptext);
8281
8282 packet.worker = u->adv.worker;
8283
8284#ifdef FREECIV_WEB
8285 web_packet.id = utype_number(u);
8286
8287 BV_CLR_ALL(web_packet.utype_actions);
8288
8289 action_iterate(act) {
8290 if (utype_can_do_action(u, act)) {
8291 BV_SET(web_packet.utype_actions, act);
8292 }
8294#endif /* FREECIV_WEB */
8295
8296 lsend_packet_ruleset_unit(dest, &packet);
8298
8299 combat_bonus_list_iterate(u->bonuses, pbonus) {
8301
8302 bonuspacket.unit = packet.id;
8303 bonuspacket.flag = pbonus->flag;
8304 bonuspacket.type = pbonus->type;
8305 bonuspacket.value = pbonus->value;
8306 bonuspacket.quiet = pbonus->quiet;
8307
8311}
8312
8313/**********************************************************************/
8317static void send_ruleset_specialists(struct conn_list *dest)
8318{
8319 struct packet_ruleset_specialist packet;
8320
8323
8324 packet.id = spec_id;
8326 sz_strlcpy(packet.rule_name, rule_name_get(&s->name));
8330
8331 /* Shallow-copy (borrow) requirement vector */
8332 packet.reqs = s->reqs;
8333
8335
8336 lsend_packet_ruleset_specialist(dest, &packet);
8338}
8339/**********************************************************************/
8342static void send_ruleset_tech_classes(struct conn_list *dest)
8343{
8344 struct packet_ruleset_tech_class packet;
8345
8347 packet.id = ptclass->idx;
8348 sz_strlcpy(packet.name, untranslated_name(&ptclass->name));
8349 sz_strlcpy(packet.rule_name, rule_name_get(&ptclass->name));
8350 packet.cost_pct = ptclass->cost_pct;
8351
8352 lsend_packet_ruleset_tech_class(dest, &packet);
8354}
8355
8356/**********************************************************************/
8360static void send_ruleset_techs(struct conn_list *dest)
8361{
8362 struct packet_ruleset_tech packet;
8364 int i;
8365
8366 for (i = 0; i < MAX_NUM_USER_TECH_FLAGS; i++) {
8367 const char *flagname;
8368 const char *helptxt;
8369
8370 fpacket.id = i + TECH_USER_1;
8371
8373 if (flagname == NULL) {
8374 fpacket.name[0] = '\0';
8375 } else {
8377 }
8378
8380 if (helptxt == NULL) {
8381 fpacket.helptxt[0] = '\0';
8382 } else {
8383 sz_strlcpy(fpacket.helptxt, helptxt);
8384 }
8385
8387 }
8388
8389 /* Since we have to prepend the tech requirements to the requirement
8390 * vector, we need to initialize a separate vector and deep-copy the
8391 * other requirements into it. */
8393
8394 advance_iterate(a) {
8395 packet.id = advance_number(a);
8396 packet.removed = !valid_advance(a);
8397 if (a->tclass == NULL) {
8398 packet.tclass = 0;
8399 } else {
8400 packet.tclass = a->tclass->idx;
8401 }
8402 sz_strlcpy(packet.name, untranslated_name(&a->name));
8403 sz_strlcpy(packet.rule_name, rule_name_get(&a->name));
8404 sz_strlcpy(packet.graphic_str, a->graphic_str);
8405 sz_strlcpy(packet.graphic_alt, a->graphic_alt);
8406
8407 /* Reset requirement vector. */
8409
8410 /* The requirements req1 and req2 are needed to research a tech. Send
8411 * them in the research_reqs requirement vector. Range is set to player
8412 * since pooled research is configurable. */
8413
8414 if ((a->require[AR_ONE] != A_NEVER)
8415 && advance_number(a->require[AR_ONE]) > A_NONE) {
8416 struct requirement req
8418 FALSE, TRUE, FALSE,
8419 advance_number(a->require[AR_ONE]));
8421 }
8422
8423 if ((a->require[AR_TWO] != A_NEVER)
8424 && advance_number(a->require[AR_TWO]) > A_NONE) {
8425 struct requirement req
8427 FALSE, TRUE, FALSE,
8428 advance_number(a->require[AR_TWO]));
8430 }
8431
8432 /* The requirements of the tech's research_reqs also goes in the
8433 * packet's research_reqs requirement vector. */
8434 requirement_vector_iterate(&a->research_reqs, req) {
8437
8438 packet.root_req = a->require[AR_ROOT]
8439 ? advance_number(a->require[AR_ROOT])
8440 : advance_count();
8441
8442 packet.flags = a->flags;
8443 packet.cost = a->cost;
8444 packet.num_reqs = a->num_reqs;
8445 PACKET_STRVEC_INSERT(packet.helptext, a->helptext);
8446
8447 lsend_packet_ruleset_tech(dest, &packet);
8449
8451}
8452
8453/**********************************************************************/
8456static void send_ruleset_counters(struct conn_list *dest)
8457{
8459 struct packet_ruleset_counter packet;
8460
8461 sz_strlcpy(packet.name, untranslated_name(&pcount->name));
8462 sz_strlcpy(packet.rule_name, rule_name_get(&pcount->name));
8463 packet.checkpoint = pcount->checkpoint;
8464 packet.behavior = pcount->type;
8465 packet.type = pcount->target;
8466 packet.def = pcount->def;
8467
8468 PACKET_STRVEC_INSERT(packet.helptext, pcount->helptext);
8469 lsend_packet_ruleset_counter(dest, &packet);
8471}
8472
8473/**********************************************************************/
8477static void send_ruleset_buildings(struct conn_list *dest)
8478{
8479 int i;
8480
8481 for (i = 0; i < MAX_NUM_USER_BUILDING_FLAGS; i++) {
8483 const char *flagname;
8484 const char *helptxt;
8485
8487
8489 if (flagname == NULL) {
8490 fpacket.name[0] = '\0';
8491 } else {
8493 }
8494
8496 if (helptxt == NULL) {
8497 fpacket.helptxt[0] = '\0';
8498 } else {
8499 sz_strlcpy(fpacket.helptxt, helptxt);
8500 }
8501
8503 }
8504
8506 struct packet_ruleset_building packet;
8507
8508 packet.id = improvement_number(b);
8509 packet.genus = b->genus;
8510 sz_strlcpy(packet.name, untranslated_name(&b->name));
8511 sz_strlcpy(packet.rule_name, rule_name_get(&b->name));
8512 sz_strlcpy(packet.graphic_str, b->graphic_str);
8513 sz_strlcpy(packet.graphic_alt, b->graphic_alt);
8514 sz_strlcpy(packet.graphic_alt2, b->graphic_alt2);
8515
8516 /* Shallow-copy (borrow) requirement vectors */
8517 packet.reqs = b->reqs;
8518 packet.obs_reqs = b->obsolete_by;
8519
8520 packet.build_cost = b->build_cost;
8521 packet.upkeep = b->upkeep;
8522 packet.sabotage = b->sabotage;
8523 packet.flags = b->flags;
8524 sz_strlcpy(packet.soundtag, b->soundtag);
8525 sz_strlcpy(packet.soundtag_alt, b->soundtag_alt);
8526 sz_strlcpy(packet.soundtag_alt2, b->soundtag_alt2);
8527 PACKET_STRVEC_INSERT(packet.helptext, b->helptext);
8528
8529 lsend_packet_ruleset_building(dest, &packet);
8531}
8532
8533/**********************************************************************/
8537static void send_ruleset_terrain(struct conn_list *dest)
8538{
8539 struct packet_ruleset_terrain packet;
8541 int i;
8542
8544
8545 for (i = 0; i < MAX_NUM_USER_TER_FLAGS; i++) {
8546 const char *flagname;
8547 const char *helptxt;
8548
8549 fpacket.id = i + TER_USER_1;
8550
8552 if (flagname == NULL) {
8553 fpacket.name[0] = '\0';
8554 } else {
8556 }
8557
8559 if (helptxt == NULL) {
8560 fpacket.helptxt[0] = '\0';
8561 } else {
8562 sz_strlcpy(fpacket.helptxt, helptxt);
8563 }
8564
8566 }
8567
8568 terrain_type_iterate(pterrain) {
8569 packet.id = terrain_number(pterrain);
8570 packet.tclass = pterrain->tclass;
8571 packet.native_to = pterrain->native_to;
8572
8573 sz_strlcpy(packet.name, untranslated_name(&pterrain->name));
8574 sz_strlcpy(packet.rule_name, rule_name_get(&pterrain->name));
8575 sz_strlcpy(packet.graphic_str, pterrain->graphic_str);
8576 sz_strlcpy(packet.graphic_alt, pterrain->graphic_alt);
8577 sz_strlcpy(packet.graphic_alt2, pterrain->graphic_alt2);
8578
8579 packet.movement_cost = pterrain->movement_cost;
8580 packet.defense_bonus = pterrain->defense_bonus;
8581
8583 packet.output[o] = pterrain->output[o];
8585
8586 packet.num_resources = 0;
8587 terrain_resources_iterate(pterrain, res, freq) {
8588 packet.resources[packet.num_resources] = extra_number(res);
8589 packet.resource_freq[packet.num_resources] = freq;
8590 packet.num_resources++;
8592
8594 packet.road_output_incr_pct[o] = pterrain->road_output_incr_pct[o];
8596
8597 packet.base_time = pterrain->base_time;
8598 packet.road_time = pterrain->road_time;
8599
8600 packet.cultivate_result = (pterrain->cultivate_result
8601 ? terrain_number(pterrain->cultivate_result)
8602 : terrain_count());
8603 packet.cultivate_time = pterrain->cultivate_time;
8604
8605 packet.plant_result = (pterrain->plant_result
8606 ? terrain_number(pterrain->plant_result)
8607 : terrain_count());
8608 packet.plant_time = pterrain->plant_time;
8609
8610 packet.irrigation_food_incr = pterrain->irrigation_food_incr;
8611 packet.irrigation_time = pterrain->irrigation_time;
8612
8613 packet.mining_shield_incr = pterrain->mining_shield_incr;
8614 packet.mining_time = pterrain->mining_time;
8615
8616 packet.animal = (pterrain->animal == NULL ? -1 : utype_number(pterrain->animal));
8617 packet.transform_result = (pterrain->transform_result
8618 ? terrain_number(pterrain->transform_result)
8619 : terrain_count());
8620 packet.placing_time = pterrain->placing_time;
8621 packet.pillage_time = pterrain->pillage_time;
8622 packet.transform_time = pterrain->transform_time;
8623
8625 for (i = 0; i < game.control.num_extra_types; i++) {
8626 packet.extra_removal_times[i] = pterrain->extra_removal_times[i];
8627 }
8628
8629 packet.flags = pterrain->flags;
8630
8631 packet.color_red = pterrain->rgb->r;
8632 packet.color_green = pterrain->rgb->g;
8633 packet.color_blue = pterrain->rgb->b;
8634
8635 PACKET_STRVEC_INSERT(packet.helptext, pterrain->helptext);
8636
8637 lsend_packet_ruleset_terrain(dest, &packet);
8639}
8640
8641/**********************************************************************/
8644static void send_ruleset_resources(struct conn_list *dest)
8645{
8646 struct packet_ruleset_resource packet;
8647
8649 packet.id = extra_index(presource);
8650
8652 packet.output[o] = presource->data.resource->output[o];
8654
8655 lsend_packet_ruleset_resource(dest, &packet);
8657}
8658
8659/**********************************************************************/
8663static void send_ruleset_extras(struct conn_list *dest)
8664{
8665 int i;
8666
8667 for (i = 0; i < MAX_NUM_USER_EXTRA_FLAGS; i++) {
8669 const char *flagname;
8670 const char *helptxt;
8671
8673
8675 if (flagname == NULL) {
8676 fpacket.name[0] = '\0';
8677 } else {
8679 }
8680
8682 if (helptxt == NULL) {
8683 fpacket.helptxt[0] = '\0';
8684 } else {
8685 sz_strlcpy(fpacket.helptxt, helptxt);
8686 }
8687
8689 }
8690
8692 struct packet_ruleset_extra packet;
8693 int j;
8694
8695 packet.id = extra_number(e);
8696 sz_strlcpy(packet.name, untranslated_name(&e->name));
8697 sz_strlcpy(packet.rule_name, rule_name_get(&e->name));
8698
8699 packet.category = e->category;
8700
8701 BV_CLR_ALL(packet.causes);
8702 for (j = 0; j < EC_COUNT; j++) {
8703 if (is_extra_caused_by(e, j)) {
8704 BV_SET(packet.causes, j);
8705 }
8706 }
8707
8708 BV_CLR_ALL(packet.rmcauses);
8709 for (j = 0; j < ERM_COUNT; j++) {
8710 if (is_extra_removed_by(e, j)) {
8711 BV_SET(packet.rmcauses, j);
8712 }
8713 }
8714
8715 sz_strlcpy(packet.activity_gfx, e->activity_gfx);
8716 sz_strlcpy(packet.act_gfx_alt, e->act_gfx_alt);
8717 sz_strlcpy(packet.act_gfx_alt2, e->act_gfx_alt2);
8718 sz_strlcpy(packet.rmact_gfx, e->rmact_gfx);
8719 sz_strlcpy(packet.rmact_gfx_alt, e->rmact_gfx_alt);
8720 sz_strlcpy(packet.rmact_gfx_alt2, e->rmact_gfx_alt2);
8721 sz_strlcpy(packet.graphic_str, e->graphic_str);
8722 sz_strlcpy(packet.graphic_alt, e->graphic_alt);
8723
8724 /* Shallow-copy (borrow) requirement vectors */
8725 packet.reqs = e->reqs;
8726 packet.rmreqs = e->rmreqs;
8727
8728 packet.appearance_chance = e->appearance_chance;
8729 /* Shallow-copy (borrow) requirement vector */
8730 packet.appearance_reqs = e->appearance_reqs;
8731
8732 packet.disappearance_chance = e->disappearance_chance;
8733 /* Shallow-copy (borrow) requirement vector */
8734 packet.disappearance_reqs = e->disappearance_reqs;
8735
8736 packet.visibility_req = e->visibility_req;
8737 packet.buildable = e->buildable;
8738 packet.generated = e->generated;
8739 packet.build_time = e->build_time;
8740 packet.build_time_factor = e->build_time_factor;
8741 packet.removal_time = e->removal_time;
8742 packet.removal_time_factor = e->removal_time_factor;
8743 packet.infracost = e->infracost;
8744 packet.defense_bonus = e->defense_bonus;
8745 packet.eus = e->eus;
8746 packet.no_aggr_near_city = e->no_aggr_near_city;
8747
8748 packet.native_to = e->native_to;
8749
8750 packet.flags = e->flags;
8751 packet.hidden_by = e->hidden_by;
8752 packet.bridged_over = e->bridged_over;
8753 packet.conflicts = e->conflicts;
8754
8755 PACKET_STRVEC_INSERT(packet.helptext, e->helptext);
8756
8757 lsend_packet_ruleset_extra(dest, &packet);
8759}
8760
8761/**********************************************************************/
8765static void send_ruleset_bases(struct conn_list *dest)
8766{
8768 struct base_type *b = extra_base_get(pextra);
8769 struct packet_ruleset_base packet;
8770
8771 packet.id = base_number(b);
8772
8773 packet.gui_type = b->gui_type;
8774 packet.border_sq = b->border_sq;
8775 packet.vision_main_sq = b->vision_main_sq;
8776 packet.vision_invis_sq = b->vision_invis_sq;
8777 packet.vision_subs_sq = b->vision_subs_sq;
8778
8779 lsend_packet_ruleset_base(dest, &packet);
8781}
8782
8783/**********************************************************************/
8787static void send_ruleset_roads(struct conn_list *dest)
8788{
8789 struct packet_ruleset_road packet;
8790
8792 struct road_type *r = extra_road_get(pextra);
8793
8794 packet.id = road_number(r);
8795
8796 packet.gui_type = r->gui_type;
8797
8798 /* Shallow-copy (borrow) requirement vector */
8799 packet.first_reqs = r->first_reqs;
8800
8801 packet.move_cost = r->move_cost;
8802 packet.move_mode = r->move_mode;
8803
8805 packet.tile_incr_const[o] = r->tile_incr_const[o];
8806 packet.tile_incr[o] = r->tile_incr[o];
8807 packet.tile_bonus[o] = r->tile_bonus[o];
8809
8810 packet.compat = r->compat;
8811
8812 packet.integrates = r->integrates;
8813 packet.flags = r->flags;
8814
8815 lsend_packet_ruleset_road(dest, &packet);
8817}
8818
8819/**********************************************************************/
8823static void send_ruleset_tiledefs(struct conn_list *dest)
8824{
8825 struct packet_ruleset_tiledef packet;
8826
8829
8830 packet.id = tiledef_number(td);
8831 sz_strlcpy(packet.name, untranslated_name(&td->name));
8832 sz_strlcpy(packet.rule_name, rule_name_get(&td->name));
8833
8835 extra_type_list_iterate(td->extras, pextra) {
8836 BV_SET(extras, extra_index(pextra));
8838
8839 packet.extras = extras;
8840
8841 lsend_packet_ruleset_tiledef(dest, &packet);
8843}
8844
8845/**********************************************************************/
8849static void send_ruleset_goods(struct conn_list *dest)
8850{
8851 struct packet_ruleset_goods packet;
8852
8854 packet.id = goods_number(g);
8855 sz_strlcpy(packet.name, untranslated_name(&g->name));
8856 sz_strlcpy(packet.rule_name, rule_name_get(&g->name));
8857
8858 /* Shallow-copy (borrow) requirement vector */
8859 packet.reqs = g->reqs;
8860
8861 packet.from_pct = g->from_pct;
8862 packet.to_pct = g->to_pct;
8863 packet.onetime_pct = g->onetime_pct;
8864 packet.select_priority = g->select_priority;
8865 packet.replace_priority = g->replace_priority;
8866 packet.flags = g->flags;
8867
8868 PACKET_STRVEC_INSERT(packet.helptext, g->helptext);
8869
8870 lsend_packet_ruleset_goods(dest, &packet);
8872}
8873
8874/**********************************************************************/
8878static void send_ruleset_disasters(struct conn_list *dest)
8879{
8880 struct packet_ruleset_disaster packet;
8881
8883 packet.id = disaster_number(d);
8884
8885 sz_strlcpy(packet.name, untranslated_name(&d->name));
8886 sz_strlcpy(packet.rule_name, rule_name_get(&d->name));
8887
8888 /* Shallow-copy (borrow) requirement vector */
8889 packet.reqs = d->reqs;
8890
8891 packet.frequency = d->frequency;
8892
8893 packet.effects = d->effects;
8894
8895 lsend_packet_ruleset_disaster(dest, &packet);
8897}
8898
8899/**********************************************************************/
8903static void send_ruleset_achievements(struct conn_list *dest)
8904{
8905 struct packet_ruleset_achievement packet;
8906
8908 packet.id = achievement_number(a);
8909
8910 sz_strlcpy(packet.name, untranslated_name(&a->name));
8911 sz_strlcpy(packet.rule_name, rule_name_get(&a->name));
8912
8913 packet.type = a->type;
8914 packet.unique = a->unique;
8915 packet.value = a->value;
8916
8917 lsend_packet_ruleset_achievement(dest, &packet);
8919}
8920
8921/**********************************************************************/
8924static void send_ruleset_actions(struct conn_list *dest)
8925{
8926 struct packet_ruleset_action packet;
8927
8928 action_iterate(act) {
8929 struct action *paction = action_by_number(act);
8930
8931 packet.id = act;
8933 packet.quiet = action_by_number(act)->quiet;
8934
8935 packet.result = paction->result;
8936 packet.sub_results = paction->sub_results;
8937 packet.actor_consuming_always = paction->actor_consuming_always;
8938
8939 packet.act_kind = action_by_number(act)->actor_kind;
8940 packet.tgt_kind = action_by_number(act)->target_kind;
8942
8945 packet.blocked_by = action_by_number(act)->blocked_by;
8946
8947 lsend_packet_ruleset_action(dest, &packet);
8949}
8950
8951/**********************************************************************/
8955{
8956 struct packet_ruleset_action_enabler packet;
8957
8960
8961 /* Shallow-copy (borrow) requirement vectors */
8962 packet.actor_reqs = enabler->actor_reqs;
8963 packet.target_reqs = enabler->target_reqs;
8964
8967}
8968
8969/**********************************************************************/
8974{
8975 int counter;
8976 int id;
8977 struct packet_ruleset_action_auto packet;
8978
8979 id = 0;
8981 packet.id = id++;
8982
8983 packet.cause = aperf->cause;
8984
8985 /* Shallow-copy (borrow) requirement vector */
8986 packet.reqs = aperf->reqs;
8987
8988 for (counter = 0;
8989 /* Can't list more actions than all actions. */
8991 /* ACTION_NONE terminates the list. */
8992 && aperf->alternatives[counter] != ACTION_NONE;
8993 counter++) {
8994 packet.alternatives[counter] = aperf->alternatives[counter];
8995 }
8996 packet.alternatives_count = counter;
8997
8998 lsend_packet_ruleset_action_auto(dest, &packet);
9000}
9001
9002/**********************************************************************/
9006static void send_ruleset_trade_routes(struct conn_list *dest)
9007{
9008 struct packet_ruleset_trade packet;
9010
9011 for (type = TRT_NATIONAL; type < TRT_LAST; type++) {
9013
9014 packet.id = type;
9015 packet.trade_pct = set->trade_pct;
9016 packet.cancelling = set->cancelling;
9017 packet.bonus_type = set->bonus_type;
9018
9019 lsend_packet_ruleset_trade(dest, &packet);
9020 }
9021}
9022
9023/**********************************************************************/
9027static void send_ruleset_governments(struct conn_list *dest)
9028{
9029 struct packet_ruleset_government gov;
9031 int i;
9032
9033 for (i = 0; i < MAX_NUM_USER_GOVERNMENT_FLAGS; i++) {
9035 const char *flagname;
9036 const char *helptxt;
9037
9039
9041 if (flagname == nullptr) {
9042 fpacket.name[0] = '\0';
9043 } else {
9045 }
9046
9048 if (helptxt == nullptr) {
9049 fpacket.helptxt[0] = '\0';
9050 } else {
9051 sz_strlcpy(fpacket.helptxt, helptxt);
9052 }
9053
9055 }
9056
9058 /* Send one packet_government */
9059 gov.id = government_number(g);
9060
9061 /* Shallow-copy (borrow) requirement vector */
9062 gov.reqs = g->reqs;
9063
9064 gov.flags = g->flags;
9065
9066 sz_strlcpy(gov.name, untranslated_name(&g->name));
9067 sz_strlcpy(gov.rule_name, rule_name_get(&g->name));
9068 sz_strlcpy(gov.graphic_str, g->graphic_str);
9069 sz_strlcpy(gov.graphic_alt, g->graphic_alt);
9070 sz_strlcpy(gov.sound_str, g->sound_str);
9071 sz_strlcpy(gov.sound_alt, g->sound_alt);
9072 sz_strlcpy(gov.sound_alt2, g->sound_alt2);
9073 PACKET_STRVEC_INSERT(gov.helptext, g->helptext);
9074
9076
9077 /* Send one packet_government_ruler_title per ruler title. */
9079 const struct nation_type *pnation = ruler_title_nation(pruler_title);
9080
9081 title.gov = government_number(g);
9082 title.nation = pnation ? nation_number(pnation) : nation_count();
9083 sz_strlcpy(title.male_title,
9085 sz_strlcpy(title.female_title,
9090}
9091
9092/**********************************************************************/
9096static void send_ruleset_nations(struct conn_list *dest)
9097{
9100 struct packet_ruleset_nation packet;
9101 int i;
9102
9104 i = 0;
9109 i++;
9112
9114 i = 0;
9116 sz_strlcpy(groups_packet.groups[i],
9118 groups_packet.hidden[i] = pgroup->hidden;
9119 i++;
9122
9124 packet.id = nation_number(n);
9125 if (n->translation_domain == NULL) {
9126 packet.translation_domain[0] = '\0';
9127 } else {
9128 sz_strlcpy(packet.translation_domain, n->translation_domain);
9129 }
9130 sz_strlcpy(packet.adjective, untranslated_name(&n->adjective));
9131 sz_strlcpy(packet.rule_name, rule_name_get(&n->adjective));
9132 sz_strlcpy(packet.noun_plural, untranslated_name(&n->noun_plural));
9133 sz_strlcpy(packet.graphic_str, n->flag_graphic_str);
9134 sz_strlcpy(packet.graphic_alt, n->flag_graphic_alt);
9135
9136 i = 0;
9140 i++;
9142 packet.leader_count = i;
9143
9144 packet.style = style_number(n->style);
9145 packet.is_playable = n->is_playable;
9146 packet.barbarian_type = n->barb_type;
9147
9148 sz_strlcpy(packet.legend, n->legend);
9149
9150 i = 0;
9152 packet.sets[i++] = nation_set_number(pset);
9154 packet.nsets = i;
9155
9156 i = 0;
9158 packet.groups[i++] = nation_group_number(pgroup);
9160 packet.ngroups = i;
9161
9162 packet.init_government_id = n->init_government
9163 ? government_number(n->init_government) : government_count();
9164 fc_assert(ARRAY_SIZE(packet.init_techs) == ARRAY_SIZE(n->init_techs));
9165 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
9166 if (n->init_techs[i] != A_LAST) {
9167 packet.init_techs[i] = n->init_techs[i];
9168 } else {
9169 break;
9170 }
9171 }
9172 packet.init_techs_count = i;
9173 fc_assert(ARRAY_SIZE(packet.init_units) == ARRAY_SIZE(n->init_units));
9174 for (i = 0; i < MAX_NUM_UNIT_LIST; i++) {
9175 const struct unit_type *t = n->init_units[i];
9176 if (t) {
9177 packet.init_units[i] = utype_number(t);
9178 } else {
9179 break;
9180 }
9181 }
9182 packet.init_units_count = i;
9184 == ARRAY_SIZE(n->init_buildings));
9185 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
9186 if (n->init_buildings[i] != B_LAST) {
9187 /* Impr_type_id to int */
9188 packet.init_buildings[i] = n->init_buildings[i];
9189 } else {
9190 break;
9191 }
9192 }
9193 packet.init_buildings_count = i;
9194
9195 lsend_packet_ruleset_nation(dest, &packet);
9197
9198 /* Send initial values of is_pickable */
9200}
9201
9202/**********************************************************************/
9206static void send_ruleset_styles(struct conn_list *dest)
9207{
9208 struct packet_ruleset_style packet;
9209
9210 styles_iterate(s) {
9211 packet.id = style_index(s);
9212 sz_strlcpy(packet.name, untranslated_name(&s->name));
9213 sz_strlcpy(packet.rule_name, rule_name_get(&s->name));
9214
9215 lsend_packet_ruleset_style(dest, &packet);
9217}
9218
9219/**********************************************************************/
9222static void send_ruleset_clauses(struct conn_list *dest)
9223{
9224 struct packet_ruleset_clause packet;
9225 int i;
9226
9227 for (i = 0; i < CLAUSE_COUNT; i++) {
9228 struct clause_info *info = clause_info_get(i);
9229
9230 packet.type = i;
9231 packet.enabled = info->enabled;
9232
9233 /* Shallow-copy (borrow) requirement vectors */
9234 packet.giver_reqs = info->giver_reqs;
9235 packet.receiver_reqs = info->receiver_reqs;
9236 packet.either_reqs = info->either_reqs;
9237
9238 lsend_packet_ruleset_clause(dest, &packet);
9239 }
9240}
9241
9242/**********************************************************************/
9246static void send_ruleset_multipliers(struct conn_list *dest)
9247{
9248 multipliers_iterate(pmul) {
9249 struct packet_ruleset_multiplier packet;
9250
9251 packet.id = multiplier_number(pmul);
9252 packet.start = pmul->start;
9253 packet.stop = pmul->stop;
9254 packet.step = pmul->step;
9255 packet.def = pmul->def;
9256 packet.offset = pmul->offset;
9257 packet.factor = pmul->factor;
9258 packet.minimum_turns = pmul->minimum_turns;
9259
9260 sz_strlcpy(packet.name, untranslated_name(&pmul->name));
9261 sz_strlcpy(packet.rule_name, rule_name_get(&pmul->name));
9262
9263 /* Shallow-copy (borrow) requirement vector */
9264 packet.reqs = pmul->reqs;
9265
9266 PACKET_STRVEC_INSERT(packet.helptext, pmul->helptext);
9267
9268 lsend_packet_ruleset_multiplier(dest, &packet);
9270}
9271
9272/**********************************************************************/
9276static void send_ruleset_cities(struct conn_list *dest)
9277{
9279 int k;
9280
9281 for (k = 0; k < game.control.num_city_styles; k++) {
9282 city_p.style_id = k;
9283
9284 /* Shallow-copy (borrow) requirement vector */
9285 city_p.reqs = city_styles[k].reqs;
9286
9289 sz_strlcpy(city_p.graphic, city_styles[k].graphic);
9290 sz_strlcpy(city_p.graphic_alt, city_styles[k].graphic_alt);
9291 sz_strlcpy(city_p.citizens_graphic, city_styles[k].citizens_graphic);
9292
9294 }
9295}
9296
9297/**********************************************************************/
9301static void send_ruleset_musics(struct conn_list *dest)
9302{
9303 struct packet_ruleset_music packet;
9304
9306 packet.id = pmus->id;
9307
9308 sz_strlcpy(packet.music_peaceful, pmus->music_peaceful);
9309 sz_strlcpy(packet.music_combat, pmus->music_combat);
9310
9311 /* Shallow-copy (borrow) requirement vector */
9312 packet.reqs = pmus->reqs;
9313
9314 lsend_packet_ruleset_music(dest, &packet);
9316}
9317
9318/**********************************************************************/
9322static void send_ruleset_game(struct conn_list *dest)
9323{
9325 int i;
9326
9328
9329 /* Per unit veteran system definition. */
9330 misc_p.veteran_levels = game.veteran->levels;
9331
9332 for (i = 0; i < misc_p.veteran_levels; i++) {
9333 const struct veteran_level *vlevel = game.veteran->definitions + i;
9334
9335 sz_strlcpy(misc_p.veteran_name[i], untranslated_name(&vlevel->name));
9336 misc_p.power_fact[i] = vlevel->power_fact;
9337 misc_p.move_bonus[i] = vlevel->move_bonus;
9338 misc_p.base_raise_chance[i] = vlevel->base_raise_chance;
9339 misc_p.work_raise_chance[i] = vlevel->work_raise_chance;
9340 }
9341
9342 fc_assert(sizeof(misc_p.global_init_techs)
9343 == sizeof(game.rgame.global_init_techs));
9344 fc_assert(ARRAY_SIZE(misc_p.global_init_techs)
9346 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
9348 misc_p.global_init_techs[i] = game.rgame.global_init_techs[i];
9349 } else {
9350 break;
9351 }
9352 }
9353 misc_p.global_init_techs_count = i;
9354
9355 fc_assert(ARRAY_SIZE(misc_p.global_init_buildings)
9357 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
9359 /* Impr_type_id to int */
9360 misc_p.global_init_buildings[i] =
9362 } else {
9363 break;
9364 }
9365 }
9366 misc_p.global_init_buildings_count = i;
9367
9368 misc_p.default_specialist = DEFAULT_SPECIALIST;
9369
9371
9372 misc_p.background_red = game.plr_bg_color->r;
9373 misc_p.background_green = game.plr_bg_color->g;
9374 misc_p.background_blue = game.plr_bg_color->b;
9375
9377}
9378
9379/**********************************************************************/
9383static void send_ruleset_team_names(struct conn_list *dest)
9384{
9386
9388 const char *name = team_slot_defined_name(tslot);
9389
9390 if (NULL == name) {
9391 /* End of defined names. */
9392 break;
9393 }
9394
9396 sz_strlcpy(team_name_info_p.team_name, name);
9397
9400}
9401
9402/**********************************************************************/
9405static void notify_ruleset_fallback(const char *msg)
9406{
9408}
9409
9410/**********************************************************************/
9413bool load_rulesets(const char *restore, const char *alt, bool compat_mode,
9414 rs_conversion_logger logger,
9415 bool act, bool buffer_script, bool load_luadata)
9416{
9417 set_ruleset_compat_mode(compat_mode);
9418
9419 if (load_rulesetdir(game.server.rulesetdir, compat_mode, logger,
9420 act, buffer_script, load_luadata)) {
9422 return TRUE;
9423 }
9424
9425 if (alt != NULL) {
9426 if (load_rulesetdir(alt, compat_mode, logger, act, buffer_script,
9427 load_luadata)) {
9429
9431 return TRUE;
9432 }
9433 }
9434
9435 /* Fallback to previous one. */
9436 if (restore != NULL) {
9437 if (load_rulesetdir(restore, compat_mode, logger, act, buffer_script, TRUE)) {
9439
9440 notify_ruleset_fallback(_("Ruleset couldn't be loaded. Keeping previous one."));
9441
9443
9444 /* We're in sane state as restoring previous ruleset succeeded,
9445 * but return failure to indicate that this is not what caller
9446 * wanted. */
9447 return FALSE;
9448 }
9449 }
9450
9452
9453 /* Fallback to default one, but not if that's what we tried already */
9457 /* We're in sane state as fallback ruleset loading succeeded,
9458 * but return failure to indicate that this is not what caller
9459 * wanted. */
9461
9462 notify_ruleset_fallback(_("Ruleset couldn't be loaded. Switching to default one."));
9463
9464 return FALSE;
9465 }
9466 }
9467
9468#ifdef FREECIV_WEB
9469 log_normal(_("Cannot load any ruleset. Freeciv-web ruleset is available from "
9470 "https://github.com/freeciv/freeciv-web"));
9471#endif /* FREECIV_WEB */
9472
9473 /* Cannot load even default ruleset, we're in completely unusable state */
9475
9477}
9478
9479/**********************************************************************/
9483{
9484 if (file != NULL) {
9485 secfile_destroy(file);
9486 }
9487}
9488
9489/**********************************************************************/
9499
9500/**********************************************************************/
9504static bool load_rulesetdir(const char *rsdir, bool compat_mode,
9505 rs_conversion_logger logger,
9506 bool act, bool buffer_script, bool load_luadata)
9507{
9510 struct section_file *actionfile;
9511 bool ok = TRUE;
9513
9514 log_normal(_("Loading rulesets."));
9515
9517 compat_info.compat_mode = compat_mode;
9518 compat_info.log_cb = logger;
9519
9522 /* Reset the list of available player colors. */
9526
9527 if (script_buffer != NULL) {
9530 }
9531 if (parser_buffer != NULL) {
9534 }
9535
9536 server.playable_nations = 0;
9537
9541 buildfile = openload_ruleset_file("buildings", rsdir);
9542 govfile = openload_ruleset_file("governments", rsdir);
9544 terrfile = openload_ruleset_file("terrain", rsdir);
9549
9550 if (load_luadata) {
9552 } else {
9554 }
9555
9556 if (techfile == NULL
9557 || buildfile == NULL
9558 || govfile == NULL
9559 || unitfile == NULL
9560 || terrfile == NULL
9561 || stylefile == NULL
9562 || cityfile == NULL
9563 || nationfile == NULL
9564 || effectfile == NULL
9565 || actionfile == NULL
9566 || gamefile == NULL) {
9567 ok = FALSE;
9568 }
9569
9570 if (ok) {
9571 /* Note: Keep load_game_names() first so that compat_info.version is
9572 * correctly initialized. */
9582 }
9583
9584 if (ok) {
9586 }
9587
9588 if (ok) {
9590 }
9591 if (ok) {
9593 }
9594 if (ok) {
9596 }
9597 if (ok) {
9599 }
9600 if (ok) {
9601 /* Terrain must precede nations and units */
9603 }
9604 if (ok) {
9606 }
9607 if (ok) {
9609 }
9610 if (ok) {
9612 }
9613 if (ok) {
9615 }
9616 if (ok) {
9618 }
9619 if (ok) {
9621 }
9622
9623 if (ok) {
9624 /* Init nations we just loaded. */
9626
9627 /* Needed by role_unit_precalcs(). */
9629
9630 /* Prepare caches we want to sanity check. */
9634
9637 }
9638
9639 if (ok) {
9640 /* Only load settings for a sane ruleset */
9641 ok = settings_ruleset(gamefile, "settings", act,
9642 compat_info.compat_mode
9643 && compat_info.version < RSFORMAT_CURRENT);
9644
9645 if (ok) {
9647 }
9648 }
9649
9661
9662 if (extra_sections) {
9665 }
9666 if (base_sections) {
9669 }
9670 if (road_sections) {
9673 }
9674 if (resource_sections) {
9677 }
9678 if (terrain_sections) {
9681 }
9682
9683 if (ok) {
9685 }
9686
9687 if (ok) {
9688 char **buffer = buffer_script ? &script_buffer : NULL;
9689
9691
9693
9694 ok = (openload_script_file("script", rsdir, buffer, FALSE) == TRI_YES);
9695 }
9696
9697 if (ok) {
9698 enum fc_tristate pret;
9699 char **buffer = buffer_script ? &parser_buffer : NULL;
9700
9701 pret = openload_script_file("parser", rsdir, buffer, compat_info.compat_mode);
9702
9703 if (pret == TRI_MAYBE && buffer_script) {
9705 "-- This file is for lua-functionality for parsing luadata.txt\n-- of this ruleset.");
9706 }
9707
9708 ok = (pret != TRI_NO);
9709 }
9710
9711 if (ok && !buffer_script) {
9712 ok = (openload_script_file("default", rsdir, NULL, FALSE) == TRI_YES);
9713 }
9714
9715 if (ok && act) {
9716 /* Populate remaining caches. */
9723 ptype->unknown_move_cost = utype_unknown_move_cost(ptype);
9727
9728 /* Build advisors unit class cache corresponding to loaded rulesets */
9730 CALL_FUNC_EACH_AI(units_ruleset_init);
9731
9732 /* We may need to adjust the number of AI players
9733 * if the number of available nations changed. */
9735 }
9736
9737 return ok;
9738}
9739
9740/**********************************************************************/
9744{
9745 struct section_file *file;
9746 bool ok = TRUE;
9747
9749 if (file == NULL) {
9751 "Could not load game.ruleset:\n%s",
9752 secfile_error());
9753 ok = FALSE;
9754 }
9755 if (ok) {
9756 settings_ruleset(file, "settings", TRUE, FALSE);
9757 secfile_destroy(file);
9758 }
9759
9760 return ok;
9761}
9762
9763/**********************************************************************/
9766void send_rulesets(struct conn_list *dest)
9767{
9769
9770 /* ruleset_control also indicates to client that ruleset sending starts. */
9772
9773 /* Currently containing control-kind of data of nation sets and groups,
9774 * this too must be sent before any requirement vector may depend on
9775 * that data. */
9777
9778 send_ruleset_game(dest);
9788 send_ruleset_techs(dest);
9791 send_ruleset_units(dest);
9793 send_ruleset_extras(dest);
9794 send_ruleset_bases(dest);
9795 send_ruleset_roads(dest);
9799 send_ruleset_goods(dest);
9801 send_ruleset_styles(dest);
9803 send_ruleset_cities(dest);
9805 send_ruleset_musics(dest);
9806 send_ruleset_cache(dest);
9807
9808 /* Indicate client that all rulesets have now been sent. */
9810
9811 /* changed game settings will be send in
9812 * connecthand.c:establish_new_connection() */
9813
9815}
void access_info_init(const struct unit_type *aunit)
Definition accessarea.c:40
void access_info_close(void)
Definition accessarea.c:56
int achievement_index(const struct achievement *pach)
int achievement_number(const struct achievement *pach)
#define achievements_iterate_end
#define achievements_iterate(_ach_)
struct action_auto_perf * action_auto_perf_slot_number(const int num)
Definition actions.c:5945
void actions_rs_pre_san_gen(void)
Definition actions.c:899
const char * action_min_range_ruleset_var_name(int act)
Definition actions.c:6396
const char * action_blocked_by_ruleset_var_name(const struct action *act)
Definition actions.c:7114
bool action_is_in_use(struct action *paction)
Definition actions.c:5899
const char * action_post_success_forced_ruleset_var_name(const struct action *act)
Definition actions.c:7310
struct action * action_by_rule_name(const char *name)
Definition actions.c:1100
const char * action_rule_name(const struct action *action)
Definition actions.c:1237
const char * action_actor_consuming_always_ruleset_var_name(action_id act)
Definition actions.c:6939
const char * action_max_range_ruleset_var_name(int act)
Definition actions.c:6576
const char * action_target_kind_ruleset_var_name(int act)
Definition actions.c:6765
void action_enabler_add(struct action_enabler *enabler)
Definition actions.c:1547
const char * action_ui_name_default(int act)
Definition actions.c:6028
struct action_enabler * action_enabler_new(void)
Definition actions.c:1496
bool action_enabler_possible_actor(const struct action_enabler *ae)
Definition actions.c:5834
struct action_enabler_list * action_enablers_for_action(action_id action)
Definition actions.c:1580
#define action_by_result_iterate(_paction_, _result_)
Definition actions.h:245
#define action_auto_perf_iterate_end
Definition actions.h:350
#define action_enablers_iterate_end
Definition actions.h:283
#define ACTION_AUTO_MOVED_ADJ
Definition actions.h:375
#define ACTION_AUTO_POST_BRIBE_UNIT
Definition actions.h:376
#define action_id_get_sub_target_kind(act_id)
Definition actions.h:421
#define ACTION_AUTO_UPKEEP_GOLD
Definition actions.h:373
#define enabler_get_action_id(_enabler_)
Definition actions.h:187
static struct action * action_by_number(action_id act_id)
Definition actions.h:400
#define NUM_ACTIONS
Definition actions.h:63
#define ACTION_AUTO_ESCAPE_STACK
Definition actions.h:382
#define action_has_result(_act_, _res_)
Definition actions.h:184
#define ACTION_AUTO_ESCAPE_CITY
Definition actions.h:381
#define action_enabler_list_iterate_end
Definition actions.h:194
#define ACTION_DISTANCE_UNLIMITED
Definition actions.h:105
#define action_by_result_iterate_end
Definition actions.h:249
#define ACTION_AUTO_POST_WIPE_UNITS
Definition actions.h:383
#define ACTION_AUTO_UPKEEP_SHIELD
Definition actions.h:374
#define action_iterate_end
Definition actions.h:218
#define ACTION_AUTO_POST_BRIBE_STACK
Definition actions.h:377
#define action_enablers_iterate(_enabler_)
Definition actions.h:277
#define ACTION_AUTO_POST_ATTACK2
Definition actions.h:379
#define action_enabler_list_iterate(action_enabler_list, aenabler)
Definition actions.h:192
#define action_id(_act_)
Definition actions.h:426
#define action_iterate(_act_)
Definition actions.h:214
#define action_auto_perf_iterate(_act_perf_)
Definition actions.h:338
#define ACTION_AUTO_UPKEEP_FOOD
Definition actions.h:372
#define ACTION_AUTO_POST_ATTACK
Definition actions.h:378
#define ACTION_AUTO_POST_COLLECT_RANSOM
Definition actions.h:380
#define ACTION_NONE
Definition actions.h:59
int actres_min_range_default(enum action_result result)
Definition actres.c:377
int actres_max_range_default(enum action_result result)
Definition actres.c:467
enum action_target_kind actres_target_kind_default(enum action_result result)
Definition actres.c:771
void adv_units_ruleset_init(void)
Definition advruleset.c:33
#define CALL_FUNC_EACH_AI(_func,...)
Definition ai.h:387
#define str
Definition astring.c:76
#define n
Definition astring.c:77
Base_type_id base_number(const struct base_type *pbase)
Definition base.c:96
void base_type_init(struct extra_type *pextra, int idx)
Definition base.c:121
bool territory_claiming_base(const struct base_type *pbase)
Definition base.c:162
#define BV_CLR_ALL(bv)
Definition bitvector.h:103
#define BV_SET(bv, bit)
Definition bitvector.h:89
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
void city_styles_alloc(int num)
Definition city.c:3436
void city_production_caravan_shields_init(void)
Definition city.c:1778
const char * city_style_rule_name(const int style)
Definition city.c:1765
const char * get_output_identifier(Output_type_id output)
Definition city.c:619
static const struct city struct citystyle * city_styles
Definition city.c:84
#define output_type_iterate(output)
Definition city.h:846
#define output_type_iterate_end
Definition city.h:852
static struct fc_sockaddr_list * list
Definition clinet.c:102
char * incite_cost
Definition comments.c:76
#define MAX_LEN_CONTENT
Definition conn_types.h:32
#define MAX_LEN_MSG
Definition conn_types.h:37
void conn_list_compression_thaw(const struct conn_list *pconn_list)
Definition connection.c:734
void conn_list_compression_freeze(const struct conn_list *pconn_list)
Definition connection.c:722
struct counter * counter_by_id(int id)
Definition counters.c:82
void attach_city_counter(struct counter *counter)
Definition counters.c:94
#define city_counters_iterate_end
Definition counters.h:64
#define city_counters_iterate(pcount)
Definition counters.h:57
struct clause_info * clause_info_get(enum clause_type type)
Definition diptreaty.c:292
const char * disaster_rule_name(struct disaster_type *pdis)
Definition disaster.c:105
Disaster_type_id disaster_number(const struct disaster_type *pdis)
Definition disaster.c:56
Disaster_type_id disaster_index(const struct disaster_type *pdis)
Definition disaster.c:69
#define disaster_type_iterate(_p)
Definition disaster.h:82
#define disaster_type_iterate_end
Definition disaster.h:88
int int id
Definition editgui_g.h:28
struct @22::@23 reqs
void send_ruleset_cache(struct conn_list *dest)
Definition effects.c:609
struct effect * effect_new(enum effect_type type, int value, struct multiplier *pmul)
Definition effects.c:186
void user_effect_ai_valued_set(enum effect_type tgt, enum effect_type valued_as)
Definition effects.c:1346
struct effect_list * get_effects(enum effect_type effect_type)
Definition effects.c:143
enum effect_type user_effect_ai_valued_as(enum effect_type real)
Definition effects.c:1357
void effect_req_append(struct effect *peffect, struct requirement req)
Definition effects.c:266
bool is_user_effect(enum effect_type eff)
Definition effects.c:1337
#define effect_list_iterate_end
Definition effects.h:81
#define effect_list_iterate(effect_list, peffect)
Definition effects.h:79
struct extra_type * extra_type_by_rule_name(const char *name)
Definition extras.c:212
const char * extra_flag_helptxt(enum extra_flag_id id)
Definition extras.c:988
void set_user_extra_flag_name(enum extra_flag_id id, const char *name, const char *helptxt)
Definition extras.c:947
bool is_extra_caused_by_worker_action(const struct extra_type *pextra)
Definition extras.c:1046
struct extra_type_list * extra_type_list_of_zoccers(void)
Definition extras.c:267
int extra_number(const struct extra_type *pextra)
Definition extras.c:161
bool extra_has_flag(const struct extra_type *pextra, enum extra_flag_id flag)
Definition extras.c:875
struct extra_type_list * extra_type_list_by_cause(enum extra_cause cause)
Definition extras.c:249
void extra_to_caused_by_list(struct extra_type *pextra, enum extra_cause cause)
Definition extras.c:312
struct extra_type * extra_by_number(int id)
Definition extras.c:183
static struct extra_type extras[MAX_EXTRA_TYPES]
Definition extras.c:31
struct extra_type_list * extra_type_list_of_terr_claimers(void)
Definition extras.c:275
const char * extra_rule_name(const struct extra_type *pextra)
Definition extras.c:203
bool is_extra_removed_by(const struct extra_type *pextra, enum extra_rmcause rmcause)
Definition extras.c:353
struct extra_type_list * extra_type_list_of_unit_hiders(void)
Definition extras.c:259
#define extra_type_iterate(_p)
Definition extras.h:315
static void extra_to_removed_by_list(struct extra_type *pextra, enum extra_rmcause rmcause)
Definition extras.h:214
#define extra_type_list_iterate(extralist, pextra)
Definition extras.h:165
#define extra_type_iterate_end
Definition extras.h:321
#define is_extra_caused_by(e, c)
Definition extras.h:203
#define extra_index(_e_)
Definition extras.h:183
#define extra_type_list_iterate_end
Definition extras.h:167
#define extra_base_get(_e_)
Definition extras.h:190
#define extra_road_get(_e_)
Definition extras.h:191
#define extra_type_by_cause_iterate_end
Definition extras.h:339
#define MAX_NUM_USER_EXTRA_FLAGS
Definition extras.h:83
#define extra_type_by_cause_iterate(_cause, _extra)
Definition extras.h:333
#define MAX_NUM_USER_BUILDING_FLAGS
Definition fc_types.h:492
#define MAX_DISASTER_TYPES
Definition fc_types.h:52
#define MAX_VET_LEVELS
Definition fc_types.h:49
@ ROCO_RAILROAD
Definition fc_types.h:946
@ ROCO_NONE
Definition fc_types.h:946
@ ROCO_RIVER
Definition fc_types.h:946
@ ROCO_ROAD
Definition fc_types.h:946
#define MAX_GRANARY_INIS
Definition fc_types.h:73
#define MAX_NUM_NATIONS
Definition fc_types.h:61
#define MAX_NUM_BUILDING_LIST
Definition fc_types.h:46
#define MAX_GOODS_TYPES
Definition fc_types.h:51
#define EC_NATURAL_DEFENSIVE
Definition fc_types.h:809
#define EC_SPECIAL
Definition fc_types.h:807
int action_id
Definition fc_types.h:249
#define SP_MAX
Definition fc_types.h:268
#define EC_NONE
Definition fc_types.h:806
#define EC_NOT_AGGRESSIVE
Definition fc_types.h:810
#define EC_DEFENSIVE
Definition fc_types.h:808
#define MAX_CALENDAR_FRAGMENTS
Definition fc_types.h:63
#define MAX_TILEDEFS
Definition fc_types.h:56
#define MAX_NUM_TECH_CLASSES
Definition fc_types.h:64
#define MAX_NUM_LEADERS
Definition fc_types.h:57
#define MAX_NUM_MULTIPLIERS
Definition fc_types.h:55
#define MAX_NUM_UNIT_LIST
Definition fc_types.h:45
#define MAX_EXTRA_TYPES
Definition fc_types.h:50
@ CTGT_CITY
Definition fc_types.h:127
#define MAX_ACHIEVEMENT_TYPES
Definition fc_types.h:53
#define MAX_LEN_NAME
Definition fc_types.h:67
#define MAX_NUM_TECH_LIST
Definition fc_types.h:44
#define MAX_LEN_CITYNAME
Definition fc_types.h:68
#define MAX_COUNTERS
Definition fc_types.h:107
#define UCL_LAST
Definition fc_types.h:275
#define Q_(String)
Definition fcintl.h:70
#define _(String)
Definition fcintl.h:67
#define Qn_(String)
Definition fcintl.h:89
#define N_(String)
Definition fcintl.h:69
const struct ft_color ftc_warning
struct civ_game game
Definition game.c:62
void game_ruleset_init(void)
Definition game.c:518
void game_ruleset_free(void)
Definition game.c:568
struct world wld
Definition game.c:63
#define RS_DEFAULT_RANSOM_GOLD
Definition game.h:874
#define RS_DEFAULT_GRANARY_FOOD_INI
Definition game.h:826
#define RS_DEFAULT_NUKE_DEFENDER_SURVIVAL_CHANCE_PCT
Definition game.h:866
#define RS_MIN_BORDER_RADIUS_SQ_CITY_PERMANENT
Definition game.h:807
#define RS_MAX_TECH_UPKEEP_DIVIDER
Definition game.h:886
#define RS_MIN_ILLNESS_POLLUTION_PCT
Definition game.h:793
#define RS_DEFAULT_NUKE_POP_LOSS_PCT
Definition game.h:863
#define RS_MAX_BORDER_RADIUS_SQ_CITY
Definition game.h:800
#define RS_DEFAULT_BASE_POLLUTION
Definition game.h:849
#define RS_MIN_ILLNESS_TRADE_INFECTION_PCT
Definition game.h:789
#define RS_MAX_ILLNESS_BASE_FACTOR
Definition game.h:782
#define RS_DEFAULT_INCITE_TOTAL_FCT
Definition game.h:822
#define RS_DEFAULT_ILLNESS_BASE_FACTOR
Definition game.h:780
#define RS_DEFAULT_NEG_YEAR_LABEL
Definition game.h:776
#define RS_MIN_NUKE_POP_LOSS_PCT
Definition game.h:864
#define RS_MIN_INCITE_IMPROVEMENT_FCT
Definition game.h:815
#define RS_MIN_FOOD_COST
Definition game.h:859
#define RS_MIN_BASE_BRIBE_COST
Definition game.h:871
#define RS_MAX_NUKE_POP_LOSS_PCT
Definition game.h:865
#define RS_DEFAULT_INCITE_IMPROVEMENT_FCT
Definition game.h:814
#define RS_MAX_INCITE_IMPROVEMENT_FCT
Definition game.h:816
#define RS_MIN_RANSOM_GOLD
Definition game.h:875
#define RS_ACTION_NO_MAX_DISTANCE
Definition game.h:898
#define RS_DEFAULT_BASE_BRIBE_COST
Definition game.h:870
#define RS_MAX_INCITE_BASE_COST
Definition game.h:812
#define RS_DEFAULT_TECH_UPKEEP_DIVIDER
Definition game.h:884
#define RS_DEFAULT_HAPPY_COST
Definition game.h:854
#define RS_MIN_UPGRADE_VETERAN_LOSS
Definition game.h:881
#define RS_MIN_ILLNESS_MIN_SIZE
Definition game.h:785
#define RS_DEFAULT_POISON_EMPTIES_FOOD_STOCK
Definition game.h:888
#define RS_DEFAULT_GRANARY_FOOD_INC
Definition game.h:828
#define RS_DEFAULT_ILLNESS_ON
Definition game.h:778
#define RS_MAX_FOOD_COST
Definition game.h:860
#define RS_MAX_HAPPY_COST
Definition game.h:856
#define GAME_DEFAULT_CELEBRATESIZE
Definition game.h:507
#define RS_MIN_ILLNESS_BASE_FACTOR
Definition game.h:781
#define RS_DEFAULT_STEAL_MAP_REVEALS_CITIES
Definition game.h:889
#define RS_MIN_TECH_UPKEEP_DIVIDER
Definition game.h:885
#define RS_MAX_RANSOM_GOLD
Definition game.h:876
#define RS_MIN_HAPPY_COST
Definition game.h:855
#define RS_MIN_BORDER_RADIUS_SQ_CITY
Definition game.h:799
#define GAME_DEFAULT_RULESETDIR
Definition game.h:681
#define RS_MIN_NUKE_DEFENDER_SURVIVAL_CHANCE_PCT
Definition game.h:867
#define RS_MAX_BORDER_RADIUS_SQ_CITY_PERMANENT
Definition game.h:808
#define RS_DEFAULT_UPGRADE_VETERAN_LOSS
Definition game.h:880
#define RS_MAX_NUKE_DEFENDER_SURVIVAL_CHANCE_PCT
Definition game.h:868
#define RS_MAX_INCITE_UNIT_FCT
Definition game.h:820
#define RS_MIN_VIS_RADIUS_SQ
Definition game.h:846
#define RS_DEFAULT_CALENDAR_SKIP_0
Definition game.h:796
#define RS_MAX_ILLNESS_MIN_SIZE
Definition game.h:786
#define RS_DEFAULT_CITY_RADIUS_SQ
Definition game.h:841
#define GAME_DEFAULT_START_YEAR
Definition game.h:748
#define RS_MAX_BORDER_SIZE_EFFECT
Definition game.h:804
#define RS_DEFAULT_BORDER_SIZE_EFFECT
Definition game.h:802
#define RS_MAX_BASE_BRIBE_COST
Definition game.h:872
#define RS_MIN_INCITE_BASE_COST
Definition game.h:811
#define RS_DEFAULT_PILLAGE_SELECT
Definition game.h:878
#define RS_MIN_CITY_RADIUS_SQ
Definition game.h:842
#define RS_MIN_CITY_CENTER_OUTPUT
Definition game.h:833
#define RS_MAX_GRANARY_FOOD_INC
Definition game.h:830
#define RS_MAX_CITY_CENTER_OUTPUT
Definition game.h:834
#define RS_MAX_CITY_RADIUS_SQ
Definition game.h:843
#define RS_DEFAULT_POS_YEAR_LABEL
Definition game.h:774
#define RS_MIN_INCITE_UNIT_FCT
Definition game.h:819
#define RS_MIN_BORDER_SIZE_EFFECT
Definition game.h:803
#define RS_DEFAULT_VIS_RADIUS_SQ
Definition game.h:845
#define RS_DEFAULT_BORDER_RADIUS_SQ_CITY_PERMANENT
Definition game.h:806
#define RS_DEFAULT_TIRED_ATTACK
Definition game.h:862
#define RS_DEFAULT_ACTION_ACTOR_CONSUMING_ALWAYS
Definition game.h:890
#define RS_MAX_ILLNESS_POLLUTION_PCT
Definition game.h:794
#define RS_DEFAULT_ILLNESS_TRADE_INFECTION_PCT
Definition game.h:788
#define RS_DEFAULT_FOOD_COST
Definition game.h:858
#define RS_DEFAULT_INCITE_UNIT_FCT
Definition game.h:818
#define RS_MAX_INCITE_TOTAL_FCT
Definition game.h:824
#define RS_DEFAULT_INCITE_BASE_COST
Definition game.h:810
#define GAME_DEFAULT_ANGRYCITIZEN
Definition game.h:398
#define RS_DEFAULT_CITY_CENTER_OUTPUT
Definition game.h:832
#define RS_MIN_INCITE_TOTAL_FCT
Definition game.h:823
#define RS_DEFAULT_ILLNESS_POLLUTION_PCT
Definition game.h:792
#define RS_MAX_UPGRADE_VETERAN_LOSS
Definition game.h:882
static void set_ruleset_compat_mode(bool active)
Definition game.h:362
#define RS_MAX_VIS_RADIUS_SQ
Definition game.h:847
#define RS_MIN_GRANARY_FOOD_INC
Definition game.h:829
#define RS_MAX_ILLNESS_TRADE_INFECTION_PCT
Definition game.h:790
#define RS_DEFAULT_ILLNESS_MIN_SIZE
Definition game.h:784
#define RS_DEFAULT_BORDER_RADIUS_SQ_CITY
Definition game.h:798
const struct nation_type * ruler_title_nation(const struct ruler_title *pruler_title)
Definition government.c:367
struct ruler_title * government_ruler_title_new(struct government *pgovern, const struct nation_type *pnation, const char *ruler_male_title, const char *ruler_female_title)
Definition government.c:327
const char * ruler_title_female_untranslated_name(const struct ruler_title *pruler_title)
Definition government.c:385
Government_type_id government_count(void)
Definition government.c:73
const char * ruler_title_male_untranslated_name(const struct ruler_title *pruler_title)
Definition government.c:376
const char * gov_flag_helptxt(enum gov_flag_id id)
Definition government.c:656
void governments_alloc(int num)
Definition government.c:531
Government_type_id government_number(const struct government *pgovern)
Definition government.c:93
const struct ruler_title_hash * government_ruler_titles(const struct government *pgovern)
Definition government.c:316
Government_type_id government_index(const struct government *pgovern)
Definition government.c:84
const char * government_rule_name(const struct government *pgovern)
Definition government.c:135
struct government * government_by_rule_name(const char *name)
Definition government.c:57
void set_user_gov_flag_name(enum gov_flag_id id, const char *name, const char *helptxt)
Definition government.c:619
#define governments_iterate(NAME_pgov)
Definition government.h:127
#define G_LAST
Definition government.h:50
#define ruler_titles_iterate(ARG_hash, NAME_rule_title)
Definition government.h:40
#define ruler_titles_iterate_end
Definition government.h:43
#define governments_iterate_end
Definition government.h:130
#define MAX_NUM_USER_GOVERNMENT_FLAGS
Definition government.h:29
const char * title
Definition repodlgs.c:1314
GType type
Definition repodlgs.c:1313
struct impr_type * improvement_by_number(const Impr_type_id id)
Impr_type_id improvement_number(const struct impr_type *pimprove)
const char * improvement_rule_name(const struct impr_type *pimprove)
void improvement_feature_cache_init(void)
Definition improvement.c:92
struct impr_type * improvement_by_rule_name(const char *name)
void set_user_impr_flag_name(enum impr_flag_id id, const char *name, const char *helptxt)
const char * impr_flag_helptxt(enum impr_flag_id id)
#define improvement_iterate_end
#define improvement_iterate(_p)
#define B_LAST
Definition improvement.h:42
const char * name
Definition inputfile.c:127
void vdo_log(const char *file, const char *function, int line, bool print_from_where, enum log_level level, char *buf, int buflen, const char *message, va_list args)
Definition log.c:403
#define fc_assert_ret(condition)
Definition log.h:192
#define log_verbose(message,...)
Definition log.h:110
#define fc_assert(condition)
Definition log.h:177
#define MAX_LEN_LOG_LINE
Definition log.h:27
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define log_do_output_for_level(level)
Definition log.h:90
#define fc_assert_action(condition, action)
Definition log.h:188
#define log_debug(message,...)
Definition log.h:116
#define log_normal(message,...)
Definition log.h:108
log_level
Definition log.h:29
@ LOG_ERROR
Definition log.h:31
@ LOG_FATAL
Definition log.h:30
#define log_error(message,...)
Definition log.h:104
void lsend_packet_ruleset_summary(struct conn_list *dest, const struct packet_ruleset_summary *packet)
void lsend_packet_ruleset_building(struct conn_list *dest, const struct packet_ruleset_building *packet)
void lsend_packet_ruleset_unit_class_flag(struct conn_list *dest, const struct packet_ruleset_unit_class_flag *packet)
void lsend_packet_ruleset_achievement(struct conn_list *dest, const struct packet_ruleset_achievement *packet)
void lsend_packet_ruleset_nation_sets(struct conn_list *dest, const struct packet_ruleset_nation_sets *packet)
void lsend_packet_ruleset_multiplier(struct conn_list *dest, const struct packet_ruleset_multiplier *packet)
void lsend_packet_ruleset_city(struct conn_list *dest, const struct packet_ruleset_city *packet)
void lsend_packet_ruleset_unit(struct conn_list *dest, const struct packet_ruleset_unit *packet)
void lsend_packet_ruleset_clause(struct conn_list *dest, const struct packet_ruleset_clause *packet)
void lsend_packet_ruleset_unit_flag(struct conn_list *dest, const struct packet_ruleset_unit_flag *packet)
void lsend_packet_ruleset_action(struct conn_list *dest, const struct packet_ruleset_action *packet)
void lsend_packet_ruleset_extra(struct conn_list *dest, const struct packet_ruleset_extra *packet)
void lsend_packet_ruleset_nation_groups(struct conn_list *dest, const struct packet_ruleset_nation_groups *packet)
void lsend_packet_ruleset_terrain_control(struct conn_list *dest, const struct packet_ruleset_terrain_control *packet)
void lsend_packet_ruleset_government_ruler_title(struct conn_list *dest, const struct packet_ruleset_government_ruler_title *packet)
void lsend_packet_ruleset_music(struct conn_list *dest, const struct packet_ruleset_music *packet)
void lsend_packet_ruleset_control(struct conn_list *dest, const struct packet_ruleset_control *packet)
void lsend_packet_team_name_info(struct conn_list *dest, const struct packet_team_name_info *packet)
void lsend_packet_ruleset_terrain_flag(struct conn_list *dest, const struct packet_ruleset_terrain_flag *packet)
void lsend_packet_ruleset_unit_class(struct conn_list *dest, const struct packet_ruleset_unit_class *packet)
void lsend_packet_ruleset_disaster(struct conn_list *dest, const struct packet_ruleset_disaster *packet)
void lsend_packet_ruleset_tiledef(struct conn_list *dest, const struct packet_ruleset_tiledef *packet)
void lsend_packet_ruleset_description_part(struct conn_list *dest, const struct packet_ruleset_description_part *packet)
void lsend_packet_ruleset_government(struct conn_list *dest, const struct packet_ruleset_government *packet)
void lsend_packet_ruleset_unit_bonus(struct conn_list *dest, const struct packet_ruleset_unit_bonus *packet)
void lsend_packet_ruleset_base(struct conn_list *dest, const struct packet_ruleset_base *packet)
void lsend_packet_ruleset_resource(struct conn_list *dest, const struct packet_ruleset_resource *packet)
void lsend_packet_ruleset_specialist(struct conn_list *dest, const struct packet_ruleset_specialist *packet)
void lsend_packet_ruleset_tech(struct conn_list *dest, const struct packet_ruleset_tech *packet)
void lsend_packet_ruleset_trade(struct conn_list *dest, const struct packet_ruleset_trade *packet)
void lsend_packet_ruleset_action_enabler(struct conn_list *dest, const struct packet_ruleset_action_enabler *packet)
void lsend_packet_ruleset_gov_flag(struct conn_list *dest, const struct packet_ruleset_gov_flag *packet)
void lsend_packet_ruleset_style(struct conn_list *dest, const struct packet_ruleset_style *packet)
void lsend_packet_ruleset_tech_flag(struct conn_list *dest, const struct packet_ruleset_tech_flag *packet)
void lsend_packet_ruleset_tech_class(struct conn_list *dest, const struct packet_ruleset_tech_class *packet)
void lsend_packet_ruleset_goods(struct conn_list *dest, const struct packet_ruleset_goods *packet)
void lsend_packet_ruleset_game(struct conn_list *dest, const struct packet_ruleset_game *packet)
void lsend_packet_ruleset_nation(struct conn_list *dest, const struct packet_ruleset_nation *packet)
void lsend_packet_ruleset_counter(struct conn_list *dest, const struct packet_ruleset_counter *packet)
void lsend_packet_rulesets_ready(struct conn_list *dest)
void lsend_packet_ruleset_impr_flag(struct conn_list *dest, const struct packet_ruleset_impr_flag *packet)
void lsend_packet_ruleset_extra_flag(struct conn_list *dest, const struct packet_ruleset_extra_flag *packet)
void lsend_packet_ruleset_road(struct conn_list *dest, const struct packet_ruleset_road *packet)
void lsend_packet_ruleset_terrain(struct conn_list *dest, const struct packet_ruleset_terrain *packet)
void lsend_packet_ruleset_action_auto(struct conn_list *dest, const struct packet_ruleset_action_auto *packet)
struct terrain_misc terrain_control
Definition map.c:68
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_strdup(str)
Definition mem.h:43
#define fc_malloc(sz)
Definition mem.h:34
int utype_unknown_move_cost(const struct unit_type *utype)
Definition movement.c:104
void init_move_fragments(void)
Definition movement.c:960
#define SINGLE_MOVE
Definition movement.h:26
const char * multiplier_rule_name(const struct multiplier *pmul)
Multiplier_type_id multiplier_number(const struct multiplier *pmul)
Definition multipliers.c:67
struct multiplier * multiplier_by_rule_name(const char *name)
Multiplier_type_id multiplier_index(const struct multiplier *pmul)
Definition multipliers.c:80
#define multipliers_iterate(_mul_)
Definition multipliers.h:61
#define multipliers_iterate_end
Definition multipliers.h:67
static void name_set(struct name_translation *ptrans, const char *domain, const char *vernacular_name)
static const char * rule_name_get(const struct name_translation *ptrans)
static const char * untranslated_name(const struct name_translation *ptrans)
static void names_set(struct name_translation *ptrans, const char *domain, const char *vernacular_name, const char *rule_name)
void nation_group_set_match(struct nation_group *pgroup, int match)
Definition nation.c:1082
const char * nation_group_untranslated_name(const struct nation_group *pgroup)
Definition nation.c:1106
struct nation_group * nation_group_by_rule_name(const char *name)
Definition nation.c:1055
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:138
Nation_type_id nation_count(void)
Definition nation.c:528
Nation_type_id nation_number(const struct nation_type *pnation)
Definition nation.c:505
struct nation_group * nation_group_new(const char *name)
Definition nation.c:992
bool nation_leader_is_male(const struct nation_leader *pleader)
Definition nation.c:296
struct nation_set * nation_set_new(const char *set_name, const char *set_rule_name, const char *set_description)
Definition nation.c:741
struct nation_type * nation_by_number(const Nation_type_id nation)
Definition nation.c:493
struct nation_city * nation_city_new(struct nation_type *pnation, const char *name)
Definition nation.c:350
const struct nation_leader_list * nation_leaders(const struct nation_type *pnation)
Definition nation.c:230
const char * nation_set_untranslated_name(const struct nation_set *pset)
Definition nation.c:824
bool is_nation_playable(const struct nation_type *nation)
Definition nation.c:200
int nation_set_number(const struct nation_set *pset)
Definition nation.c:733
void nation_city_set_terrain_preference(struct nation_city *pncity, const struct terrain *pterrain, enum nation_city_preference prefer)
Definition nation.c:400
void nation_city_set_river_preference(struct nation_city *pncity, enum nation_city_preference prefer)
Definition nation.c:413
bool nation_is_in_set(const struct nation_type *pnation, const struct nation_set *pset)
Definition nation.c:867
const char * nation_set_description(const struct nation_set *pset)
Definition nation.c:857
int nation_set_count(void)
Definition nation.c:715
struct nation_set * nation_set_by_number(int id)
Definition nation.c:789
struct nation_type * nation_by_rule_name(const char *name)
Definition nation.c:121
struct nation_set * nation_set_by_rule_name(const char *name)
Definition nation.c:806
Nation_type_id nation_index(const struct nation_type *pnation)
Definition nation.c:518
const char * nation_leader_name(const struct nation_leader *pleader)
Definition nation.c:286
int nation_group_count(void)
Definition nation.c:966
const char * nation_set_rule_name(const struct nation_set *pset)
Definition nation.c:835
struct nation_leader * nation_leader_new(struct nation_type *pnation, const char *name, bool is_male)
Definition nation.c:240
void nation_group_set_hidden(struct nation_group *pgroup, bool hidden)
Definition nation.c:1071
void nations_alloc(int num)
Definition nation.c:645
enum barbarian_type nation_barbarian_type(const struct nation_type *nation)
Definition nation.c:211
int nation_group_number(const struct nation_group *pgroup)
Definition nation.c:984
#define nation_leader_list_iterate(leaderlist, pleader)
Definition nation.h:57
#define nation_sets_iterate_end
Definition nation.h:307
#define nation_set_list_iterate_end
Definition nation.h:68
#define nation_group_list_iterate(grouplist, pgroup)
Definition nation.h:75
#define nation_sets_iterate(NAME_pset)
Definition nation.h:303
#define nations_iterate_end
Definition nation.h:338
nation_city_preference
Definition nation.h:39
@ NCP_DISLIKE
Definition nation.h:40
@ NCP_LIKE
Definition nation.h:42
#define nations_iterate(NAME_pnation)
Definition nation.h:335
#define nation_leader_list_iterate_end
Definition nation.h:59
#define nation_group_list_iterate_end
Definition nation.h:77
#define nation_set_list_iterate(setlist, pset)
Definition nation.h:66
#define nation_groups_iterate(NAME_pgroup)
Definition nation.h:313
#define nation_groups_iterate_end
Definition nation.h:317
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:238
#define web_lsend_packet(packetname,...)
Definition packets.h:57
#define PACKET_STRVEC_INSERT(dest, src)
Definition packets.h:188
struct city_list * cities
Definition packhand.c:120
int len
Definition packhand.c:128
void send_nation_availability(struct conn_list *dest, bool nationset_change)
Definition plrhand.c:2647
void playercolor_free(void)
Definition plrhand.c:3348
void playercolor_init(void)
Definition plrhand.c:3338
int playercolor_count(void)
Definition plrhand.c:3387
void playercolor_add(struct rgbcolor *prgbcolor)
Definition plrhand.c:3367
void count_playable_nations(void)
Definition plrhand.c:2604
struct section_file * secfile_load(const char *filename, bool allow_duplicates)
Definition registry.c:51
const char * secfile_error(void)
const char * section_name(const struct section *psection)
void secfile_destroy(struct section_file *secfile)
bool entry_bool_get(const struct entry *pentry, bool *value)
void secfile_check_unused(const struct section_file *secfile)
bool secfile_lookup_int(const struct section_file *secfile, int *ival, const char *path,...)
struct section_list * secfile_sections_by_name_prefix(const struct section_file *secfile, const char *prefix)
const char ** secfile_lookup_str_vec(const struct section_file *secfile, size_t *dim, const char *path,...)
struct entry * secfile_entry_lookup(const struct section_file *secfile, const char *path,...)
bool entry_str_get(const struct entry *pentry, const char **value)
const char * secfile_lookup_str(const struct section_file *secfile, const char *path,...)
int * secfile_lookup_int_vec(const struct section_file *secfile, size_t *dim, const char *path,...)
bool secfile_lookup_bool_default(const struct section_file *secfile, bool def, const char *path,...)
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
bool entry_int_get(const struct entry *pentry, int *value)
const char * secfile_name(const struct section_file *secfile)
struct entry * secfile_entry_by_path(const struct section_file *secfile, const char *path)
const char * secfile_lookup_str_default(const struct section_file *secfile, const char *def, const char *path,...)
int secfile_lookup_int_def_min_max(const struct section_file *secfile, int defval, int minval, int maxval, const char *path,...)
enum entry_type entry_type_get(const struct entry *pentry)
@ ENTRY_FILEREFERENCE
@ ENTRY_LONG_COMMENT
@ ENTRY_INT
@ ENTRY_FLOAT
@ ENTRY_STR
@ ENTRY_ILLEGAL
@ ENTRY_BOOL
#define secfile_lookup_enum_vec(secfile, dim, specenum_type, path,...)
#define secfile_lookup_enum_default(secfile, defval, specenum_type, path,...)
#define section_list_iterate(seclist, psection)
#define section_list_iterate_end
req_vec_num_in_item req_vec_vector_number(const void *parent_item, const struct requirement_vector *vec)
struct requirement_vector * req_vec_by_number(const void *parent_item, req_vec_num_in_item number)
bool req_vec_change_apply(const struct req_vec_change *modification, requirement_vector_by_number getter, const void *parent_item)
bool are_requirements_equal(const struct requirement *req1, const struct requirement *req2)
struct requirement req_from_str(const char *type, const char *range, bool survives, bool present, bool quiet, const char *value)
struct requirement req_from_values(int type, int range, bool survives, bool present, bool quiet, int value)
void req_vec_problem_free(struct req_vec_problem *issue)
struct req_vec_problem * req_vec_get_first_missing_univ(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
struct req_vec_problem * req_vec_get_first_redundant_req(const struct requirement_vector *vec, requirement_vector_number get_num, const void *parent_item)
bool req_vec_is_impossible_to_fulfill(const struct requirement_vector *reqs)
#define requirement_vector_iterate_end
#define requirement_vector_iterate(req_vec, preq)
bool rgbcolor_load(struct section_file *file, struct rgbcolor **prgbcolor, char *path,...)
Definition rgbcolor.c:90
Road_type_id road_number(const struct road_type *proad)
Definition road.c:32
void road_integrators_cache_init(void)
Definition road.c:111
void road_type_init(struct extra_type *pextra, int idx)
Definition road.c:93
bool rscompat_names(struct rscompat_info *info)
Definition rscompat.c:335
void rscompat_postprocess(struct rscompat_info *info)
Definition rscompat.c:493
const char * rscompat_effect_name_3_4(const char *old_name)
Definition rscompat.c:569
int rscompat_check_capabilities(struct section_file *file, const char *filename, const struct rscompat_info *info)
Definition rscompat.c:70
void rscompat_enablers_add_obligatory_hard_reqs(void)
Definition rscompat.c:290
void rscompat_init_info(struct rscompat_info *info)
Definition rscompat.c:61
bool rscompat_check_cap_and_version(struct section_file *file, const char *filename, const struct rscompat_info *info)
Definition rscompat.c:135
bool sanity_check_ruleset_data(struct rscompat_info *compat)
Definition rssanity.c:907
bool autoadjust_ruleset_data(void)
Definition rssanity.c:1620
#define ENABLER_SECTION_PREFIX
Definition ruleload.c:115
#define check_cityname(name)
Definition ruleload.c:121
static int ruleset_purge_redundant_reqs_enablers(void)
Definition ruleload.c:433
static void ruleset_load_traits(struct trait_limits *out, struct section_file *file, const char *secname, const char *field_prefix)
Definition ruleload.c:1273
static bool load_rulesetdir(const char *rsdir, bool compat_mode, rs_conversion_logger logger, bool act, bool buffer_script, bool load_luadata)
Definition ruleload.c:9504
#define STYLE_SECTION_PREFIX
Definition ruleload.c:100
static bool lookup_terrain(struct section_file *file, const char *entry, const char *filename, struct terrain *pthis, struct terrain **result, bool null_acceptable)
Definition ruleload.c:1174
static bool load_ruleset_veteran(struct section_file *file, const char *path, struct veteran_system **vsystem, char *err, size_t err_len)
Definition ruleload.c:1949
static bool load_terrain_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:2754
static bool load_style_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:5743
int ruleset_purge_unused_entities(void)
Definition ruleload.c:323
#define MUSICSTYLE_SECTION_PREFIX
Definition ruleload.c:93
static char * road_sections
Definition ruleload.c:132
static bool load_ruleset_governments(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:4426
#define MULTIPLIER_SECTION_PREFIX
Definition ruleload.c:117
static struct requirement_vector reqs_list
Definition ruleload.c:135
static void send_ruleset_techs(struct conn_list *dest)
Definition ruleload.c:8360
#define section_strlcpy(dst, src)
Definition ruleload.c:126
static bool load_action_range(struct section_file *file, action_id act)
Definition ruleload.c:6499
#define check_name(name)
Definition ruleload.c:120
static bool load_specialist(const struct section *psection, struct specialist *s, struct section_file *file)
Definition ruleload.c:5984
static void send_ruleset_units(struct conn_list *dest)
Definition ruleload.c:8180
static void send_ruleset_governments(struct conn_list *dest)
Definition ruleload.c:9027
static bool load_action_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:1442
static struct extra_type * lookup_resource(const char *filename, const char *name, const char *jsection)
Definition ruleload.c:1153
static struct section_file * openload_luadata_file(const char *rsdir)
Definition ruleload.c:636
#define TILEDEF_SECTION_PREFIX
Definition ruleload.c:106
static bool load_ruleset_techs(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:1580
static bool purge_unused_req_vec(const struct requirement_vector *reqs, const char *msg)
Definition ruleload.c:337
void rulesets_deinit(void)
Definition ruleload.c:9493
static void send_ruleset_resources(struct conn_list *dest)
Definition ruleload.c:8644
static bool load_ruleset_buildings(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:2630
static char * terrain_sections
Definition ruleload.c:129
static bool lookup_building_list(struct section_file *file, const char *prefix, const char *entry, int *output, const char *filename)
Definition ruleload.c:1005
static void nullcheck_secfile_destroy(struct section_file *file)
Definition ruleload.c:9482
static void send_ruleset_clauses(struct conn_list *dest)
Definition ruleload.c:9222
static void send_ruleset_game(struct conn_list *dest)
Definition ruleload.c:9322
char * parser_buffer
Definition ruleload.c:219
#define NATION_SECTION_PREFIX
Definition ruleload.c:99
static bool load_ruleset_effects(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:6242
static bool lookup_cbonus_list(struct combat_bonus_list *list, struct section_file *file, const char *sec, const char *sub)
Definition ruleload.c:790
static void send_ruleset_nations(struct conn_list *dest)
Definition ruleload.c:9096
static void send_ruleset_roads(struct conn_list *dest)
Definition ruleload.c:8787
static int ruleset_purge_unused_enablers(void)
Definition ruleload.c:254
#define UEFF_SECTION_PREFIX
Definition ruleload.c:94
static char * tiledef_sections
Definition ruleload.c:133
static bool is_on_allowed_list(const char *name, const char **list, size_t len)
Definition ruleload.c:4840
static void send_ruleset_tech_classes(struct conn_list *dest)
Definition ruleload.c:8342
static void send_ruleset_action_enablers(struct conn_list *dest)
Definition ruleload.c:8954
static void send_ruleset_control(struct conn_list *dest)
Definition ruleload.c:4646
bool load_rulesets(const char *restore, const char *alt, bool compat_mode, rs_conversion_logger logger, bool act, bool buffer_script, bool load_luadata)
Definition ruleload.c:9413
static void send_ruleset_tiledefs(struct conn_list *dest)
Definition ruleload.c:8823
#define GOODS_SECTION_PREFIX
Definition ruleload.c:107
void ruleset_error_real(rs_conversion_logger logger, const char *file, const char *function, int line, enum log_level level, const char *format,...)
Definition ruleload.c:225
#define TERRAIN_SECTION_PREFIX
Definition ruleload.c:110
static struct section_file * openload_ruleset_file(const char *whichset, const char *rsdir)
Definition ruleload.c:581
struct requirement_vector * lookup_req_list(struct section_file *file, const char *sec, const char *sub, const char *rfor)
Definition ruleload.c:664
static void send_ruleset_musics(struct conn_list *dest)
Definition ruleload.c:9301
int ruleset_purge_redundant_reqs(void)
Definition ruleload.c:500
static int secfile_lookup_int_default_min_max(struct section_file *file, int def, int min, int max, const char *path,...) fc__attribute((__format__(__printf__
Definition ruleload.c:6420
static char * base_sections
Definition ruleload.c:131
#define DISASTER_SECTION_PREFIX
Definition ruleload.c:113
static void send_ruleset_goods(struct conn_list *dest)
Definition ruleload.c:8849
static const char name_too_long[]
Definition ruleload.c:124
bool reload_rulesets_settings(void)
Definition ruleload.c:9743
static struct strvec * lookup_strvec(struct section_file *file, const char *prefix, const char *suffix)
Definition ruleload.c:1133
#define CITYSTYLE_SECTION_PREFIX
Definition ruleload.c:92
static bool lookup_tech(struct section_file *file, struct advance **result, const char *prefix, const char *entry, const char *filename, const char *description)
Definition ruleload.c:849
static bool load_game_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:1312
static void send_ruleset_counters(struct conn_list *dest)
Definition ruleload.c:8456
static void send_ruleset_specialists(struct conn_list *dest)
Definition ruleload.c:8317
#define ADVANCE_SECTION_PREFIX
Definition ruleload.c:89
#define EFFECT_SECTION_PREFIX
Definition ruleload.c:95
static void send_ruleset_action_auto_performers(struct conn_list *dest)
Definition ruleload.c:8973
static bool load_government_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:4314
static bool load_action_blocked_by_list(struct section_file *file, const char *filename, struct action *paction, struct rscompat_info *compat)
Definition ruleload.c:6564
static void send_ruleset_team_names(struct conn_list *dest)
Definition ruleload.c:9383
static void send_ruleset_cities(struct conn_list *dest)
Definition ruleload.c:9276
static bool purge_redundant_req_vec(const struct requirement_vector *reqs, const char *msg)
Definition ruleload.c:422
static char * lookup_string(struct section_file *file, const char *prefix, const char *suffix)
Definition ruleload.c:1113
static const char * check_leader_names(struct nation_type *pnation)
Definition ruleload.c:4684
#define BASE_SECTION_PREFIX
Definition ruleload.c:103
static int ruleset_purge_redundant_reqs_effects(void)
Definition ruleload.c:471
static enum fc_tristate openload_script_file(const char *whichset, const char *rsdir, char **buffer, bool optional)
Definition ruleload.c:609
char * get_parser_buffer(void)
Definition ruleload.c:572
#define ACTION_SECTION_PREFIX
Definition ruleload.c:116
static bool load_building_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:2549
#define EXTRA_SECTION_PREFIX
Definition ruleload.c:102
void send_rulesets(struct conn_list *dest)
Definition ruleload.c:9766
#define CLAUSE_SECTION_PREFIX
Definition ruleload.c:101
static bool lookup_unit_list(struct section_file *file, const char *prefix, const char *entry, struct unit_type **output, const char *filename)
Definition ruleload.c:881
static char * resource_sections
Definition ruleload.c:128
#define UNIT_SECTION_PREFIX
Definition ruleload.c:112
#define ACHIEVEMENT_SECTION_PREFIX
Definition ruleload.c:114
static bool load_ruleset_cities(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:6026
static bool load_ruleset_styles(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:5804
static struct government * lookup_government(struct section_file *file, const char *entry, const char *filename, struct government *fallback)
Definition ruleload.c:1088
#define SUPER_SPECIALIST_SECTION_PREFIX
Definition ruleload.c:109
static bool load_ruleset_units(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:2070
char * script_buffer
Definition ruleload.c:218
static bool lookup_time(const struct section_file *secfile, int *turns, const char *sec_name, const char *property_name, const char *filename, const char *item_name, bool *ok)
Definition ruleload.c:1224
static void send_ruleset_styles(struct conn_list *dest)
Definition ruleload.c:9206
#define NATION_GROUP_SECTION_PREFIX
Definition ruleload.c:98
static char * extra_sections
Definition ruleload.c:130
#define RULES_SUFFIX
Definition ruleload.c:86
static void send_ruleset_disasters(struct conn_list *dest)
Definition ruleload.c:8878
static bool purge_duplicate_req_vec(const struct requirement_vector *reqs, const char *msg)
Definition ruleload.c:377
static bool lookup_tech_list(struct section_file *file, const char *prefix, const char *entry, int *output, const char *filename)
Definition ruleload.c:941
#define MAX_SECTION_LABEL
Definition ruleload.c:125
#define BUILDING_SECTION_PREFIX
Definition ruleload.c:91
static bool load_ruleset_game(struct section_file *file, bool act, struct rscompat_info *compat)
Definition ruleload.c:6680
static bool load_nation_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:4704
static void send_ruleset_achievements(struct conn_list *dest)
Definition ruleload.c:8903
#define SCRIPT_SUFFIX
Definition ruleload.c:87
static void send_ruleset_bases(struct conn_list *dest)
Definition ruleload.c:8765
static bool load_ruleset_terrain(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:3126
static int ruleset_purge_unused_effects(void)
Definition ruleload.c:300
static bool load_action_actor_consuming_always(struct section_file *file, action_id act)
Definition ruleload.c:6547
static bool load_action_post_success_force(struct section_file *file, const char *filename, int performer_slot, struct action *paction)
Definition ruleload.c:6609
static bool load_tech_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:1462
#define SPECIALIST_SECTION_PREFIX
Definition ruleload.c:108
#define COUNTER_SECTION_PREFIX
Definition ruleload.c:118
static bool load_action_kind(struct section_file *file, action_id act)
Definition ruleload.c:6524
static void send_ruleset_multipliers(struct conn_list *dest)
Definition ruleload.c:9246
char * get_script_buffer(void)
Definition ruleload.c:564
static void send_ruleset_actions(struct conn_list *dest)
Definition ruleload.c:8924
static bool load_city_name_list(struct section_file *file, struct nation_type *pnation, const char *secfile_str1, const char *secfile_str2, const char **allowed_terrains, size_t atcount)
Definition ruleload.c:4856
static bool load_action_auto_uflag_block(struct section_file *file, struct action_auto_perf *auto_perf, const char *uflags_path, const char *filename)
Definition ruleload.c:5882
static bool load_ruleset_nations(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:5026
static bool load_action_auto_actions(struct section_file *file, struct action_auto_perf *auto_perf, const char *actions_path, const char *filename)
Definition ruleload.c:5925
static void send_ruleset_unit_classes(struct conn_list *dest)
Definition ruleload.c:8132
#define TECH_CLASS_SECTION_PREFIX
Definition ruleload.c:90
#define RESOURCE_SECTION_PREFIX
Definition ruleload.c:105
static bool lookup_unit_type(struct section_file *file, const char *prefix, const char *entry, const struct unit_type **result, const char *filename, const char *description)
Definition ruleload.c:1057
static void send_ruleset_extras(struct conn_list *dest)
Definition ruleload.c:8663
#define rs_sanity_veteran(_path, _entry, _i, _condition, _action)
static void send_ruleset_terrain(struct conn_list *dest)
Definition ruleload.c:8537
#define GOVERNMENT_SECTION_PREFIX
Definition ruleload.c:96
static bool load_unit_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:1791
static void send_ruleset_trade_routes(struct conn_list *dest)
Definition ruleload.c:9006
static bool load_ruleset_actions(struct section_file *file, struct section_file *gamefile, struct rscompat_info *compat)
Definition ruleload.c:7748
static void notify_ruleset_fallback(const char *msg)
Definition ruleload.c:9405
static bool lookup_bv_actions(struct section_file *file, const char *filename, bv_actions *target, const char *path)
Definition ruleload.c:6646
static void send_ruleset_buildings(struct conn_list *dest)
Definition ruleload.c:8477
#define UNIT_CLASS_SECTION_PREFIX
Definition ruleload.c:111
static bool ruleset_load_names(struct name_translation *pname, const char *domain, struct section_file *file, const char *sec_name)
Definition ruleload.c:1250
#define ROAD_SECTION_PREFIX
Definition ruleload.c:104
static const char * valid_ruleset_filename(const char *subdir, const char *name, const char *extension, bool optional)
Definition ruleload.c:519
static bool load_action_range_max(struct section_file *file, action_id act)
Definition ruleload.c:6458
static bool load_muuk_as_action_auto(struct section_file *file, struct action_auto_perf *auto_perf, const char *item, const char *filename)
Definition ruleload.c:5961
#define NATION_SET_SECTION_PREFIX
Definition ruleload.c:97
#define RS_DEFAULT_CONVERT_SPEED
Definition ruleload.h:122
#define RS_DEFAULT_DAMAGE_REDUCES_BOMBARD_RATE
Definition ruleload.h:108
#define RS_DEFAULT_WORLD_PEACE_TURNS
Definition ruleload.h:98
#define RS_DEFAULT_TECH_TRADE_LOSS_HOLES
Definition ruleload.h:83
#define RS_DEFAULT_TECH_COST_STYLE
Definition ruleload.h:89
#define RS_DEFAULT_EXTRA_APPEARANCE
Definition ruleload.h:102
#define RS_DEFAULT_TECH_PARASITE_HOLES
Definition ruleload.h:84
#define GAME_DEFAULT_ACH_VALUE
Definition ruleload.h:77
#define RS_DEFAULT_TECH_TRADE_HOLES
Definition ruleload.h:82
#define RS_DEFAULT_CULTURE_VIC_POINTS
Definition ruleload.h:93
#define RS_DEFAULT_CULTURE_MIGRATION_PML
Definition ruleload.h:95
void(* rs_conversion_logger)(const char *msg)
Definition ruleload.h:41
#define RS_DEFAULT_SMALL_WONDER_VISIBILITY
Definition ruleload.h:110
#define ruleset_error(logger, level, format,...)
Definition ruleload.h:58
#define RS_DEFAULT_ONLY_KILLING_VETERAN
Definition ruleload.h:105
#define RS_DEFAULT_TECH_LOSS_HOLES
Definition ruleload.h:85
#define RS_DEFAULT_HISTORY_INTEREST_PML
Definition ruleload.h:96
#define RS_DEFAULT_TECH_UPKEEP_STYLE
Definition ruleload.h:91
#define RS_DEFAULT_GOODS_SELECTION
Definition ruleload.h:100
#define RS_DEFAULT_PYTHAGOREAN_DIAGONAL
Definition ruleload.h:86
#define RS_DEFAULT_TECH_STEAL_HOLES
Definition ruleload.h:81
#define RS_MIN_MIN_TECH_COST
Definition ruleload.h:117
#define GAME_DEFAULT_ACH_UNIQUE
Definition ruleload.h:76
#define RS_MAX_BASE_TECH_COST
Definition ruleload.h:114
#define RS_DEFAULT_COMBAT_ODDS_SCALED_VETERANCY
Definition ruleload.h:107
#define RS_DEFAULT_MUUK_FOOD_WIPE
Definition ruleload.h:78
#define RS_DEFAULT_MUUK_GOLD_WIPE
Definition ruleload.h:79
#define RS_DEFAULT_BASE_TECH_COST
Definition ruleload.h:112
#define RS_DEFAULT_NATIONALITY
Definition ruleload.h:120
#define GAME_DEFAULT_CHANGABLE_TAX
Definition ruleload.h:73
#define RS_DEFAULT_MUUK_SHIELD_WIPE
Definition ruleload.h:80
#define RSFORMAT_CURRENT
Definition ruleload.h:37
#define RS_DEFAULT_GOLD_UPKEEP_STYLE
Definition ruleload.h:88
#define GAME_DEFAULT_ADDTOSIZE
Definition ruleload.h:72
#define RS_DEFAULT_ONLY_REAL_FIGHT_VETERAN
Definition ruleload.h:106
#define RS_DEFAULT_EXTRA_DISAPPEARANCE
Definition ruleload.h:103
#define RS_MAX_MIN_TECH_COST
Definition ruleload.h:118
#define RS_DEFAULT_MIN_TECH_COST
Definition ruleload.h:116
#define GAME_DEFAULT_VISION_REVEAL_TILES
Definition ruleload.h:74
#define RS_DEFAULT_CULTURE_VIC_LEAD
Definition ruleload.h:94
#define RS_DEFAULT_TECH_LEAKAGE
Definition ruleload.h:90
#define GAME_DEFAULT_DISASTER_FREQ
Definition ruleload.h:75
#define RSFORMAT_3_4
Definition ruleload.h:36
#define RS_MIN_BASE_TECH_COST
Definition ruleload.h:113
static struct compatibility compat[]
Definition savecompat.c:117
bool script_server_init(void)
bool script_server_load_file(const char *filename, char **buf)
void script_server_free(void)
bool script_server_do_file(struct connection *caller, const char *filename)
struct setting_list * level[OLEVELS_NUM]
Definition settings.c:190
bool settings_ruleset(struct section_file *file, const char *section, bool act, bool compat)
Definition settings.c:4423
sex_t sex_by_name(const char *name)
Definition sex.c:27
sex_t
Definition sex.h:20
@ SEX_UNKNOWN
Definition sex.h:21
@ SEX_FEMALE
Definition sex.h:22
@ SEX_MALE
Definition sex.h:23
bool check_strlen(const char *str, size_t len, const char *errmsg)
Definition shared.c:493
const char * fileinfoname(const struct strvec *dirs, const char *filename)
Definition shared.c:1094
void remove_leading_trailing_spaces(char *s)
Definition shared.c:444
const struct strvec * get_data_dirs(void)
Definition shared.c:886
fc_tristate
Definition shared.h:46
@ TRI_YES
Definition shared.h:46
@ TRI_NO
Definition shared.h:46
@ TRI_MAYBE
Definition shared.h:46
#define DIR_SEPARATOR
Definition shared.h:127
#define ARRAY_SIZE(x)
Definition shared.h:85
struct specialist * specialist_by_rule_name(const char *name)
Definition specialist.c:123
struct specialist * specialist_by_number(const Specialist_type_id id)
Definition specialist.c:110
Specialist_type_id specialist_index(const struct specialist *sp)
Definition specialist.c:90
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:157
#define specialist_type_iterate_end
Definition specialist.h:85
#define specialist_type_iterate(sp)
Definition specialist.h:79
#define DEFAULT_SPECIALIST
Definition specialist.h:43
const char * aifill(int amount)
Definition srv_main.c:2511
void update_nations_with_startpos(void)
Definition srv_main.c:2316
void strvec_store(struct strvec *psv, const char *const *vec, size_t size)
struct strvec * strvec_new(void)
bool actor_consuming_always
Definition actions.h:144
int max_distance
Definition actions.h:127
bool quiet
Definition actions.h:134
char ui_name[MAX_LEN_NAME]
Definition actions.h:130
bv_action_sub_results sub_results
Definition actions.h:115
enum action_actor_kind actor_kind
Definition actions.h:117
bv_actions blocked_by
Definition actions.h:138
enum action_target_kind target_kind
Definition actions.h:118
int min_distance
Definition actions.h:127
struct advance * require[AR_SIZE]
Definition tech.h:129
int border_sq
Definition base.h:44
int vision_main_sq
Definition base.h:45
enum base_gui_type gui_type
Definition base.h:43
int vision_invis_sq
Definition base.h:46
int vision_subs_sq
Definition base.h:47
char * nationlist
Definition game.h:289
int named_teams
Definition game.h:301
size_t as_count
Definition game.h:300
struct civ_game::@32::@36::@42 ruledit
const char ** allowed_govs
Definition game.h:292
int upgrade_veteran_loss
Definition game.h:206
struct rgbcolor * plr_bg_color
Definition game.h:103
int incite_total_factor
Definition game.h:157
int init_vis_radius_sq
Definition game.h:159
bool vision_reveal_tiles
Definition game.h:207
char * description_file
Definition game.h:288
struct packet_ruleset_control control
Definition game.h:83
char * ruleset_summary
Definition game.h:84
char ** nc_agovs
Definition game.h:293
int base_incite_cost
Definition game.h:141
int global_init_techs[MAX_NUM_TECH_LIST]
Definition game.h:110
struct packet_game_info info
Definition game.h:89
int autoupgrade_veteran_loss
Definition game.h:139
char rulesetdir[MAX_LEN_NAME]
Definition game.h:246
int start_year
Definition game.h:198
int incite_improvement_factor
Definition game.h:156
struct section_file * luadata
Definition game.h:254
char ** embedded_nations
Definition game.h:290
int global_init_buildings[MAX_NUM_BUILDING_LIST]
Definition game.h:111
struct trait_limits default_traits[TRAIT_COUNT]
Definition game.h:281
char ** nc_astyles
Definition game.h:299
const char ** allowed_terrains
Definition game.h:295
char * ruleset_description
Definition game.h:85
size_t ag_count
Definition game.h:294
const char ** allowed_styles
Definition game.h:298
bool std_tileset_compat
Definition game.h:302
struct civ_game::@31 rgame
char ** nc_aterrs
Definition game.h:296
size_t embedded_nations_count
Definition game.h:291
int incite_unit_factor
Definition game.h:158
char * ruleset_capabilities
Definition game.h:86
int ransom_gold
Definition game.h:182
struct civ_game::@32::@36 server
size_t at_count
Definition game.h:297
struct veteran_system * veteran
Definition game.h:101
bool homeless_gold_upkeep
Definition game.h:131
struct packet_calendar_info calendar
Definition game.h:90
struct government * default_government
Definition game.h:93
struct civ_game::@32::@36::@37 deprecated
struct government * government_during_revolution
Definition game.h:94
struct civ_map::@44::@46 server
bool ocean_resources
Definition map_types.h:119
struct requirement_vector receiver_reqs
Definition diptreaty.h:61
struct requirement_vector giver_reqs
Definition diptreaty.h:60
struct requirement_vector either_reqs
Definition diptreaty.h:62
bool enabled
Definition diptreaty.h:59
enum unit_type_flag_id flag
Definition unittype.h:472
enum combat_bonus_type type
Definition unittype.h:473
struct name_translation name
Definition extras.h:90
int build_cost
Definition improvement.h:60
char graphic_str[MAX_LEN_NAME]
Definition improvement.h:55
char graphic_alt2[MAX_LEN_NAME]
Definition improvement.h:57
enum impr_genus_id genus
Definition improvement.h:63
char graphic_alt[MAX_LEN_NAME]
Definition improvement.h:56
struct requirement_vector obsolete_by
Definition improvement.h:59
char soundtag_alt[MAX_LEN_NAME]
Definition improvement.h:67
char soundtag_alt2[MAX_LEN_NAME]
Definition improvement.h:68
struct requirement_vector reqs
Definition improvement.h:58
struct strvec * helptext
Definition improvement.h:65
struct name_translation name
Definition improvement.h:52
bv_impr_flags flags
Definition improvement.h:64
char soundtag[MAX_LEN_NAME]
Definition improvement.h:66
Definition climisc.h:82
bool hidden
Definition nation.h:171
char * legend
Definition nation.h:107
enum barbarian_type barb_type
Definition nation.h:110
char calendar_fragment_name[MAX_CALENDAR_FRAGMENTS][MAX_LEN_NAME]
char negative_year_label[MAX_LEN_NAME]
char positive_year_label[MAX_LEN_NAME]
bool tech_steal_allow_holes
enum gameloss_style gameloss_style
int granary_food_ini[MAX_GRANARY_INIS]
enum goods_selection_method goods_selection
Government_type_id government_during_revolution_id
enum gold_upkeep_style gold_upkeep_style
int low_firepower_pearl_harbor
bool damage_reduces_bombard_rate
int nuke_defender_survival_chance_pct
enum tech_upkeep_style tech_upkeep_style
bool tech_trade_loss_allow_holes
enum free_tech_method free_tech_method
bool steal_maps_reveals_all_cities
bool only_real_fight_makes_veteran
enum tech_leakage_style tech_leakage
int min_city_center_output[O_LAST]
bool airlift_from_always_enabled
bool only_killing_makes_veteran
bool poison_empties_food_stock
bv_actions diplchance_initial_odds
bool tech_trade_allow_holes
int low_firepower_nonnat_bombard
bool tech_parasite_allow_holes
int low_firepower_combat_bonus
int border_city_permanent_radius_sq
int low_firepower_badwallattacker
bool airlift_to_always_enabled
enum wonder_visib_type small_wonder_visibility
enum tech_cost_style tech_cost_style
bool combat_odds_scaled_veterancy
bool unit_builders_nationality
Government_type_id default_government_id
char rule_name[MAX_LEN_NAME]
char name[MAX_LEN_NAME]
enum achievement_type type
action_id alternatives[MAX_NUM_ACTIONS]
struct requirement_vector reqs
enum action_auto_perf_cause cause
struct requirement_vector actor_reqs
struct requirement_vector target_reqs
char ui_name[MAX_LEN_NAME]
enum action_sub_target_kind sub_tgt_kind
enum action_actor_kind act_kind
bv_action_sub_results sub_results
enum action_target_kind tgt_kind
enum action_result result
enum base_gui_type gui_type
char graphic_alt2[MAX_LEN_NAME]
char name[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
char graphic_alt[MAX_LEN_NAME]
char graphic_str[MAX_LEN_NAME]
struct requirement_vector reqs
struct requirement_vector obs_reqs
char soundtag_alt2[MAX_LEN_NAME]
enum impr_genus_id genus
char soundtag[MAX_LEN_NAME]
char soundtag_alt[MAX_LEN_NAME]
struct strvec * helptext
struct requirement_vector giver_reqs
enum clause_type type
struct requirement_vector receiver_reqs
struct requirement_vector either_reqs
char alt_dir[MAX_LEN_NAME]
char version[MAX_LEN_NAME]
char preferred_musicset[MAX_LEN_NAME]
char name[MAX_LEN_NAME]
char preferred_tileset[MAX_LEN_NAME]
char preferred_soundset[MAX_LEN_NAME]
enum counter_target type
char name[MAX_LEN_NAME]
struct strvec * helptext
char rule_name[MAX_LEN_NAME]
enum counter_behavior behavior
char name[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
struct requirement_vector reqs
bv_disaster_effects effects
char helptxt[MAX_LEN_PACKET]
char graphic_str[MAX_LEN_NAME]
struct strvec * helptext
bv_unit_classes native_to
char graphic_alt[MAX_LEN_NAME]
char rmact_gfx[MAX_LEN_NAME]
struct requirement_vector appearance_reqs
char act_gfx_alt[MAX_LEN_NAME]
char act_gfx_alt2[MAX_LEN_NAME]
struct requirement_vector disappearance_reqs
bv_extra_flags flags
char rmact_gfx_alt[MAX_LEN_NAME]
struct requirement_vector rmreqs
enum extra_unit_seen_type eus
char activity_gfx[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
char name[MAX_LEN_NAME]
struct requirement_vector reqs
char rmact_gfx_alt2[MAX_LEN_NAME]
struct requirement_vector reqs
bv_goods_flags flags
char rule_name[MAX_LEN_NAME]
char name[MAX_LEN_NAME]
struct strvec * helptext
char helptxt[MAX_LEN_PACKET]
char sound_alt2[MAX_LEN_NAME]
char sound_str[MAX_LEN_NAME]
struct requirement_vector reqs
char graphic_alt[MAX_LEN_NAME]
Government_type_id id
char graphic_str[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
char sound_alt[MAX_LEN_NAME]
char name[MAX_LEN_NAME]
char helptxt[MAX_LEN_PACKET]
struct requirement_vector reqs
char name[MAX_LEN_NAME]
Multiplier_type_id id
char rule_name[MAX_LEN_NAME]
struct requirement_vector reqs
char music_peaceful[MAX_LEN_NAME]
char music_combat[MAX_LEN_NAME]
char graphic_alt[MAX_LEN_NAME]
char graphic_str[MAX_LEN_NAME]
bool leader_is_male[MAX_NUM_LEADERS]
int sets[MAX_NUM_NATION_SETS]
Impr_type_id init_buildings[MAX_NUM_BUILDING_LIST]
char adjective[MAX_LEN_NAME]
char translation_domain[MAX_LEN_NAME]
char leader_name[MAX_NUM_LEADERS][MAX_LEN_NAME]
int init_techs[MAX_NUM_TECH_LIST]
Unit_type_id init_units[MAX_NUM_UNIT_LIST]
char legend[MAX_LEN_MSG]
int groups[MAX_NUM_NATION_GROUPS]
Government_type_id init_government_id
enum barbarian_type barbarian_type
char noun_plural[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
bv_road_flags flags
enum road_gui_type gui_type
bv_max_extras integrates
int tile_incr_const[O_LAST]
enum road_compat compat
int tile_incr[O_LAST]
enum road_move_mode move_mode
int tile_bonus[O_LAST]
struct requirement_vector first_reqs
char plural_name[MAX_LEN_NAME]
struct requirement_vector reqs
Specialist_type_id id
char rule_name[MAX_LEN_NAME]
char short_name[MAX_LEN_NAME]
char graphic_alt[MAX_LEN_NAME]
char graphic_str[MAX_LEN_NAME]
char name[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
char text[MAX_LEN_CONTENT]
char rule_name[MAX_LEN_NAME]
char name[MAX_LEN_NAME]
char helptxt[MAX_LEN_PACKET]
struct strvec * helptext
char name[MAX_LEN_NAME]
char graphic_str[MAX_LEN_NAME]
char rule_name[MAX_LEN_NAME]
char graphic_alt[MAX_LEN_NAME]
bv_tech_flags flags
struct requirement_vector research_reqs
char helptxt[MAX_LEN_PACKET]
Terrain_type_id transform_result
char name[MAX_LEN_NAME]
int resource_freq[MAX_EXTRA_TYPES]
bv_terrain_flags flags
Resource_type_id resources[MAX_EXTRA_TYPES]
char graphic_alt[MAX_LEN_NAME]
bv_unit_classes native_to
int road_output_incr_pct[O_LAST]
char graphic_alt2[MAX_LEN_NAME]
Terrain_type_id cultivate_result
int extra_removal_times[MAX_EXTRA_TYPES]
Terrain_type_id plant_result
char rule_name[MAX_LEN_NAME]
char graphic_str[MAX_LEN_NAME]
struct strvec * helptext
char rule_name[MAX_LEN_NAME]
char name[MAX_LEN_NAME]
enum trade_route_illegal_cancelling cancelling
enum trade_route_bonus_type bonus_type
char helptxt[MAX_LEN_PACKET]
bv_unit_class_flags flags
char rule_name[MAX_LEN_NAME]
char name[MAX_LEN_NAME]
char helptxt[MAX_LEN_PACKET]
enum vision_layer vlayer
enum transp_def_type tp_defense
char rule_name[MAX_LEN_NAME]
int base_raise_chance[MAX_VET_LEVELS]
int move_bonus[MAX_VET_LEVELS]
int work_raise_chance[MAX_VET_LEVELS]
char sound_move[MAX_LEN_NAME]
bv_unit_classes disembarks
bv_unit_classes cargo
bv_unit_type_flags flags
char sound_fight_alt[MAX_LEN_NAME]
char graphic_str[MAX_LEN_NAME]
bv_unit_classes targets
struct requirement_vector build_reqs
int power_fact[MAX_VET_LEVELS]
char veteran_name[MAX_VET_LEVELS][MAX_LEN_NAME]
bv_unit_classes embarks
char sound_fight[MAX_LEN_NAME]
char sound_move_alt[MAX_LEN_NAME]
struct strvec * helptext
char graphic_alt2[MAX_LEN_NAME]
char graphic_alt[MAX_LEN_NAME]
char name[MAX_LEN_NAME]
bv_unit_type_roles roles
Definition goto.c:52
struct universal source
int g
Definition rgbcolor.h:34
int b
Definition rgbcolor.h:34
int r
Definition rgbcolor.h:34
enum road_gui_type gui_type
Definition road.h:80
struct requirement_vector first_reqs
Definition road.h:82
enum road_move_mode move_mode
Definition road.h:75
int tile_bonus[O_LAST]
Definition road.h:78
int tile_incr_const[O_LAST]
Definition road.h:76
int tile_incr[O_LAST]
Definition road.h:77
bv_road_flags flags
Definition road.h:85
int move_cost
Definition road.h:74
enum road_compat compat
Definition road.h:79
bv_max_extras integrates
Definition road.h:84
bool compat_mode
Definition rscompat.h:31
struct requirement_vector reqs
Definition specialist.h:38
char graphic_alt[MAX_LEN_NAME]
Definition specialist.h:36
struct strvec * helptext
Definition specialist.h:40
char graphic_str[MAX_LEN_NAME]
Definition specialist.h:35
struct name_translation name
Definition specialist.h:31
struct name_translation abbreviation
Definition specialist.h:32
char ** vec
enum trade_route_bonus_type bonus_type
Definition traderoutes.h:78
enum trade_route_illegal_cancelling cancelling
Definition traderoutes.h:77
int fixed
Definition traits.h:46
enum universals_n kind
Definition fc_types.h:593
struct veteran_level * definitions
Definition unittype.h:502
struct civ_map map
struct nation_style * style_by_rule_name(const char *name)
Definition style.c:117
struct nation_style * style_by_number(int id)
Definition style.c:88
void styles_alloc(int count)
Definition style.c:36
struct music_style * music_style_by_number(int id)
Definition style.c:171
int style_number(const struct nation_style *pstyle)
Definition style.c:68
void music_styles_alloc(int count)
Definition style.c:133
int style_index(const struct nation_style *pstyle)
Definition style.c:78
#define music_styles_iterate(_p)
Definition style.h:72
#define music_styles_iterate_end
Definition style.h:79
#define styles_iterate(_p)
Definition style.h:46
#define styles_iterate_end
Definition style.h:52
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:777
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
bool fc_isspace(char c)
Definition support.c:1240
size_t fc_strlcat(char *dest, const char *src, size_t n)
Definition support.c:822
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:886
char fc_tolower(char c)
Definition support.c:1273
#define sz_strlcpy(dest, src)
Definition support.h:195
#define RETURN_VALUE_AFTER_EXIT(_val_)
Definition support.h:146
#define fc__attribute(x)
Definition support.h:99
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
struct team_slot * team_slot_by_number(int team_id)
Definition team.c:175
const char * team_slot_defined_name(const struct team_slot *tslot)
Definition team.c:277
int team_slot_index(const struct team_slot *tslot)
Definition team.c:138
int team_slot_count(void)
Definition team.c:112
void team_slot_set_defined_name(struct team_slot *tslot, const char *team_name)
Definition team.c:288
#define team_slots_iterate_end
Definition team.h:77
#define team_slots_iterate(_tslot)
Definition team.h:72
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:107
const char * tech_flag_id_name_cb(enum tech_flag_id flag)
Definition tech.c:433
void set_user_tech_flag_name(enum tech_flag_id id, const char *name, const char *helptxt)
Definition tech.c:404
struct advance * valid_advance(struct advance *padvance)
Definition tech.c:152
void techs_precalc_data(void)
Definition tech.c:225
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:309
const char * tech_flag_helptxt(enum tech_flag_id id)
Definition tech.c:445
struct advance * advance_by_rule_name(const char *name)
Definition tech.c:200
struct tech_class * tech_class_by_rule_name(const char *name)
Definition tech.c:361
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:98
#define tech_class_index(_ptclass_)
Definition tech.h:190
#define A_NEVER
Definition tech.h:51
#define tech_class_iterate_end
Definition tech.h:201
#define MAX_NUM_USER_TECH_FLAGS
Definition tech.h:105
#define advance_iterate_all_end
Definition tech.h:277
@ AR_TWO
Definition tech.h:109
@ AR_ROOT
Definition tech.h:110
@ AR_ONE
Definition tech.h:108
#define advance_iterate_all(_p)
Definition tech.h:276
static Tech_type_id advance_count(void)
Definition tech.h:167
#define A_FIRST
Definition tech.h:44
#define A_NONE
Definition tech.h:43
#define advance_iterate(_p)
Definition tech.h:273
#define tech_class_iterate(_p)
Definition tech.h:195
#define advance_iterate_end
Definition tech.h:274
#define A_LAST
Definition tech.h:45
struct terrain * terrain_by_rule_name(const char *name)
Definition terrain.c:189
Terrain_type_id terrain_count(void)
Definition terrain.c:120
const char * terrain_flag_id_name_cb(enum terrain_flag_id flag)
Definition terrain.c:821
Terrain_type_id terrain_index(const struct terrain *pterrain)
Definition terrain.c:140
struct terrain * terrain_by_number(const Terrain_type_id type)
Definition terrain.c:158
const char * terrain_flag_helptxt(enum terrain_flag_id id)
Definition terrain.c:833
struct resource_type * resource_type_init(struct extra_type *pextra)
Definition terrain.c:276
void set_user_terrain_flag_name(enum terrain_flag_id id, const char *name, const char *helptxt)
Definition terrain.c:792
Terrain_type_id terrain_number(const struct terrain *pterrain)
Definition terrain.c:149
#define RESOURCE_FREQUENCY_MAXIMUM
Definition terrain.h:102
#define terrain_type_iterate(_p)
Definition terrain.h:266
#define T_NONE
Definition terrain.h:61
#define TERRAIN_UNKNOWN_IDENTIFIER
Definition terrain.h:88
#define terrain_type_iterate_end
Definition terrain.h:272
#define RESOURCE_NONE_IDENTIFIER
Definition terrain.h:52
#define RESOURCE_NULL_IDENTIFIER
Definition terrain.h:51
#define RESOURCE_FREQUENCY_MINIMUM
Definition terrain.h:100
#define MAX_NUM_TERRAINS
Definition terrain.h:69
#define T_FIRST
Definition terrain.h:65
#define MAX_NUM_USER_TER_FLAGS
Definition terrain.h:32
#define terrain_resources_iterate_end
Definition terrain.h:294
#define terrain_resources_iterate(pterrain, _res, _freq)
Definition terrain.h:285
#define RESOURCE_FREQUENCY_DEFAULT
Definition terrain.h:101
#define ACTIVITY_FACTOR
Definition tile.h:170
int tiledef_number(const struct tiledef *td)
Definition tiledef.c:61
struct tiledef * tiledef_by_number(int id)
Definition tiledef.c:83
#define tiledef_index(_td_)
Definition tiledef.h:41
#define tiledef_iterate_end
Definition tiledef.h:54
#define tiledef_iterate(_p)
Definition tiledef.h:48
Goods_type_id goods_number(const struct goods_type *pgood)
enum trade_route_illegal_cancelling trade_route_cancelling_type_by_name(const char *name)
struct trade_route_settings * trade_route_settings_by_type(enum trade_route_type type)
const char * goods_rule_name(struct goods_type *pgood)
Goods_type_id goods_index(const struct goods_type *pgood)
enum trade_route_type trade_route_type_by_name(const char *name)
#define goods_type_iterate_end
@ TRI_LAST
Definition traderoutes.h:33
#define goods_type_iterate(_p)
trade_route_type
Definition traderoutes.h:37
@ TRT_NATIONAL
Definition traderoutes.h:38
@ TRT_LAST
Definition traderoutes.h:48
#define TRAIT_DEFAULT_VALUE
Definition traits.h:32
void set_unit_class_caches(struct unit_class *pclass)
Definition unittype.c:2788
const char * unit_class_flag_helptxt(enum unit_class_flag_id id)
Definition unittype.c:1880
struct unit_type * unit_type_by_rule_name(const char *name)
Definition unittype.c:1793
bool utype_has_role(const struct unit_type *punittype, int role)
Definition unittype.c:224
void unit_type_action_cache_init(void)
Definition unittype.c:956
void set_unit_type_caches(struct unit_type *ptype)
Definition unittype.c:2847
void role_unit_precalcs(void)
Definition unittype.c:2201
void veteran_system_definition(struct veteran_system *vsystem, int level, const char *vlist_name, int vlist_power, int vlist_move, int vlist_raise, int vlist_wraise)
Definition unittype.c:2717
Unit_type_id utype_count(void)
Definition unittype.c:82
int utype_veteran_levels(const struct unit_type *punittype)
Definition unittype.c:2657
const char * utype_rule_name(const struct unit_type *punittype)
Definition unittype.c:1604
const struct veteran_level * utype_veteran_level(const struct unit_type *punittype, int level)
Definition unittype.c:2629
const char * uclass_rule_name(const struct unit_class *pclass)
Definition unittype.c:1667
Unit_type_id utype_number(const struct unit_type *punittype)
Definition unittype.c:102
struct unit_class * unit_class_by_rule_name(const char *s)
Definition unittype.c:1810
const char * unit_type_flag_helptxt(enum unit_type_flag_id id)
Definition unittype.c:1943
Unit_type_id utype_index(const struct unit_type *punittype)
Definition unittype.c:93
void set_user_unit_class_flag_name(enum unit_class_flag_id id, const char *name, const char *helptxt)
Definition unittype.c:1838
struct veteran_system * veteran_system_new(int count)
Definition unittype.c:2686
Unit_Class_id uclass_number(const struct unit_class *pclass)
Definition unittype.c:2497
bool utype_can_do_action(const struct unit_type *putype, const action_id act_id)
Definition unittype.c:396
void set_user_unit_type_flag_name(enum unit_type_flag_id id, const char *name, const char *helptxt)
Definition unittype.c:1902
static bool uclass_has_flag(const struct unit_class *punitclass, enum unit_class_flag_id flag)
Definition unittype.h:773
#define utype_class(_t_)
Definition unittype.h:756
#define combat_bonus_list_iterate_end
Definition unittype.h:487
#define L_FIRST
Definition unittype.h:354
#define combat_bonus_list_iterate(bonuslist, pbonus)
Definition unittype.h:485
#define unit_tech_reqs_iterate_end
Definition unittype.h:889
#define unit_class_iterate(_p)
Definition unittype.h:916
#define unit_tech_reqs_iterate(_utype_, _p)
Definition unittype.h:883
#define MAX_NUM_USER_UNIT_FLAGS
Definition unittype.h:336
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:624
#define UTYF_LAST_USER_FLAG
Definition unittype.h:335
#define unit_type_iterate(_p)
Definition unittype.h:863
#define U_LAST
Definition unittype.h:40
#define uclass_index(_c_)
Definition unittype.h:749
#define unit_class_iterate_end
Definition unittype.h:923
#define unit_type_iterate_end
Definition unittype.h:870
#define MAX_NUM_USER_UCLASS_FLAGS
Definition unittype.h:128