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);
218 int def, int min, int max,
219 const char *path, ...)
221
224
225/**********************************************************************/
230 const char *file, const char *function,
232 const char *format, ...)
233{
234 va_list args;
235 char buf[MAX_LEN_LOG_LINE];
236
237 if (logger == NULL && !log_do_output_for_level(level)) {
238 return;
239 }
240
241 va_start(args, format);
242 if (logger != NULL) {
243 fc_vsnprintf(buf, sizeof(buf), format, args);
244 logger(buf);
245 } else {
246 vdo_log(file, function, line, FALSE, level, buf, sizeof(buf), format, args);
247 }
248 va_end(args);
249
250 if (LOG_FATAL >= level) {
252 }
253}
254
255/**********************************************************************/
259{
260 int purged = 0;
261
262 action_iterate(act_id) {
263 struct action *paction = action_by_number(act_id);
264
266 == 0) {
267 /* Not relevant. */
268 continue;
269 }
270
271 /* Impossible hard requirement. */
273 /* Make sure that all action enablers are disabled. */
275 ae) {
276 ae->rulesave.ruledit_disabled = TRUE;
277 purged++;
279
280 log_normal("Purged all action enablers for %s",
282 }
283
284 /* Impossible requirement vector requirement. */
286 ae) {
287 if (!ae->rulesave.ruledit_disabled
289 || req_vec_is_impossible_to_fulfill(&ae->target_reqs))) {
290 ae->rulesave.ruledit_disabled = TRUE;
291 purged++;
292 log_normal("Purged unused action enabler for %s",
294 }
297
298 return purged;
299}
300
301/**********************************************************************/
305{
306 int purged = 0;
307 enum effect_type type;
308
313 eft->rulesave.do_not_save = TRUE;
314 purged++;
315 log_normal("Purged unused effect for %s",
316 effect_type_name(eft->type));
317 }
319 }
320
321 return purged;
322}
323
324/**********************************************************************/
328{
329 int purged = 0;
330
333
334 return purged;
335}
336
337/**********************************************************************/
342 const char *msg)
343{
344 struct req_vec_problem *problem;
345 bool result;
346
348 reqs);
349
350 if (problem == NULL) {
351 /* No problem. */
352 return FALSE;
353 }
354
355 if (problem->num_suggested_solutions == 0) {
356 /* No solution. */
358 return FALSE;
359 }
360
361 if (problem->num_suggested_solutions == 1
362 && problem->suggested_solutions[0].operation == RVCO_REMOVE) {
363 /* Remove !present req that never is there. */
364 log_normal("%s", msg);
365 result = req_vec_change_apply(&problem->suggested_solutions[0],
368 return result;
369 }
370
371 /* Not handled. Don't know what this is. */
372 fc_assert(problem->num_suggested_solutions == 1);
374 return FALSE;
375}
376
377/**********************************************************************/
382 const char *msg)
383{
384 struct req_vec_problem *problem;
385 bool result;
386
388 reqs);
389
390 if (problem == NULL) {
391 /* No problem. */
392 return FALSE;
393 }
394
395 if (problem->num_suggested_solutions == 0) {
396 /* No solution. */
398 return FALSE;
399 }
400
401 if (problem->num_suggested_solutions == 2
402 && problem->suggested_solutions[0].operation == RVCO_REMOVE
403 && problem->suggested_solutions[1].operation == RVCO_REMOVE
404 && are_requirements_equal(&problem->suggested_solutions[0].req,
405 &problem->suggested_solutions[1].req)) {
406 /* Simple duplication is handled. */
407 log_normal("%s", msg);
408 result = req_vec_change_apply(&problem->suggested_solutions[1],
411 return result;
412 }
413
414 /* Requirements of different kinds making each other redundant isn't
415 * supported yet. It could be done by always removing the most general
416 * requirement. So unit type is kept when redundant with unit flag, unit
417 * class and unit class flag etc. */
419 return FALSE;
420}
421
422/**********************************************************************/
427 const char *msg)
428{
429 return (purge_unused_req_vec(reqs, msg)
431}
432
433/**********************************************************************/
438{
439 int purged = 0;
440
441 action_iterate(act_id) {
442 struct action *paction = action_by_number(act_id);
443 char actor_reqs[MAX_LEN_NAME * 2];
444 char target_reqs[MAX_LEN_NAME * 2];
445
446 /* Error log text */
447 fc_snprintf(actor_reqs, sizeof(actor_reqs),
448 "Purged redundant requirement in"
449 " %s in action enabler for %s",
450 "actor_reqs", action_rule_name(paction));
451 fc_snprintf(target_reqs, sizeof(target_reqs),
452 "Purged redundant requirement in"
453 " %s in action enabler for %s",
454 "target_reqs", action_rule_name(paction));
455
456 /* Do the purging. */
458 ae) {
459 while (!ae->rulesave.ruledit_disabled
460 && (purge_redundant_req_vec(&ae->actor_reqs, actor_reqs)
461 || purge_redundant_req_vec(&ae->target_reqs,
462 target_reqs))) {
463 purged++;
464 }
467
468 return purged;
469}
470
471/**********************************************************************/
476{
477 int purged = 0;
478 enum effect_type type;
479
482 char msg[MAX_LEN_NAME * 2];
483
484 /* Error log text */
485 fc_snprintf(msg, sizeof(msg),
486 "Purged redundant requirement in effect of type %s",
488
489 /* Do the purging. */
491 while (purge_redundant_req_vec(&eft->reqs, msg)) {
492 purged++;
493 }
495 }
496
497 return purged;
498}
499
500/**********************************************************************/
505{
506 int purged = 0;
507
510
511 if (purged > 0) {
512 /* An unused requirement may be an obligatory hard requirement. */
514 }
515
516 return purged;
517}
518
519/**********************************************************************/
523static const char *valid_ruleset_filename(const char *subdir,
524 const char *name,
525 const char *extension,
526 bool optional)
527{
528 char filename[512];
529 const char *dfilename;
530
532
533 fc_snprintf(filename, sizeof(filename), "%s" DIR_SEPARATOR "%s.%s",
535 log_verbose("Trying \"%s\".", filename);
536 dfilename = fileinfoname(get_data_dirs(), filename);
537 if (dfilename) {
538 return dfilename;
539 }
540
541 fc_snprintf(filename, sizeof(filename), "default" DIR_SEPARATOR "%s.%s", name, extension);
542 log_verbose("Trying \"%s\": default ruleset directory.", filename);
543 dfilename = fileinfoname(get_data_dirs(), filename);
544 if (dfilename) {
545 return dfilename;
546 }
547
548 fc_snprintf(filename, sizeof(filename), "%s_%s.%s",
550 log_verbose("Trying \"%s\": alternative ruleset filename syntax.",
551 filename);
552 dfilename = fileinfoname(get_data_dirs(), filename);
553 if (dfilename) {
554 return dfilename;
555 } else if (!optional) {
557 /* TRANS: message about an installation error. */
558 _("Could not find a readable \"%s.%s\" ruleset file."),
559 name, extension);
560 }
561
562 return NULL;
563}
564
565/**********************************************************************/
569{
570 return script_buffer;
571}
572
573/**********************************************************************/
577{
578 return parser_buffer;
579}
580
581/**********************************************************************/
585static struct section_file *openload_ruleset_file(const char *whichset,
586 const char *rsdir)
587{
588 char sfilename[512];
591 struct section_file *secfile;
592
593 if (dfilename == NULL) {
594 return NULL;
595 }
596
597 /* Need to save a copy of the filename for following message, since
598 section_file_load() may call datafilename() for includes. */
600 secfile = secfile_load(sfilename, FALSE);
601
602 if (secfile == NULL) {
603 ruleset_error(NULL, LOG_ERROR, "Could not load ruleset '%s':\n%s",
605 }
606
607 return secfile;
608}
609
610/**********************************************************************/
613static enum fc_tristate openload_script_file(const char *whichset, const char *rsdir,
614 char **buffer, bool optional)
615{
618
619 if (dfilename == NULL) {
620 return optional ? TRI_MAYBE : TRI_NO;
621 }
622
623 if (buffer == NULL) {
625 ruleset_error(NULL, LOG_ERROR, "\"%s\": could not load ruleset script.",
626 dfilename);
627
628 return TRI_NO;
629 }
630 } else {
632 }
633
634 return TRI_YES;
635}
636
637/**********************************************************************/
640static struct section_file *openload_luadata_file(const char *rsdir)
641{
642 struct section_file *secfile;
643 char sfilename[512];
644 const char *dfilename = valid_ruleset_filename(rsdir, "luadata",
645 "txt", TRUE);
646
647 if (dfilename == NULL) {
648 return NULL;
649 }
650
651 /* Need to save a copy of the filename for following message, since
652 section_file_load() may call datafilename() for includes. */
654 secfile = secfile_load(sfilename, FALSE);
655
656 if (secfile == NULL) {
657 ruleset_error(NULL, LOG_ERROR, "Could not load luadata '%s':\n%s",
659 }
660
661 return secfile;
662}
663
664/**********************************************************************/
669 const char *sec,
670 const char *sub,
671 const char *rfor)
672{
673 const char *type, *name;
674 int j;
675 const char *filename;
676
677 filename = secfile_name(file);
678
680
681 for (j = 0; (type = secfile_lookup_str_default(file, NULL, "%s.%s%d.type",
682 sec, sub, j)); j++) {
683 char buf[MAX_LEN_NAME];
684 const char *range;
685 bool survives, present, quiet;
686 struct entry *pentry;
687 struct requirement req;
688
689 if (!(pentry = secfile_entry_lookup(file, "%s.%s%d.name",
690 sec, sub, j))) {
692
693 return NULL;
694 }
695 name = NULL;
696 switch (entry_type_get(pentry)) {
697 case ENTRY_BOOL:
698 {
699 bool val;
700
701 if (entry_bool_get(pentry, &val)) {
702 fc_snprintf(buf, sizeof(buf), "%d", val);
703 name = buf;
704 }
705 }
706 break;
707 case ENTRY_INT:
708 {
709 int val;
710
711 if (entry_int_get(pentry, &val)) {
712 fc_snprintf(buf, sizeof(buf), "%d", val);
713 name = buf;
714 }
715 }
716 break;
717 case ENTRY_STR:
719 break;
720 case ENTRY_FLOAT:
723 "\"%s\": trying to have an floating point entry as a requirement name in '%s.%s%d'.",
724 filename, sec, sub, j);
725 break;
728 break;
731 break;
732 case ENTRY_ILLEGAL:
734 break;
735 }
736 if (NULL == name) {
738 "\"%s\": error in handling requirement name for '%s.%s%d'.",
739 filename, sec, sub, j);
740 return NULL;
741 }
742
743 if (!(range = secfile_lookup_str(file, "%s.%s%d.range", sec, sub, j))) {
745
746 return NULL;
747 }
748
749 survives = FALSE;
750 if ((pentry = secfile_entry_lookup(file, "%s.%s%d.survives",
751 sec, sub, j))
754 "\"%s\": invalid boolean value for survives for "
755 "'%s.%s%d'.", filename, sec, sub, j);
756 }
757
758 present = TRUE;
759 if ((pentry = secfile_entry_lookup(file, "%s.%s%d.present",
760 sec, sub, j))
763 "\"%s\": invalid boolean value for present for "
764 "'%s.%s%d'.", filename, sec, sub, j);
765 }
766 quiet = FALSE;
767 if ((pentry = secfile_entry_lookup(file, "%s.%s%d.quiet",
768 sec, sub, j))
769 && !entry_bool_get(pentry, &quiet)) {
771 "\"%s\": invalid boolean value for quiet for "
772 "'%s.%s%d'.", filename, sec, sub, j);
773 }
774
776 if (req.source.kind == universals_n_invalid()) {
778 "\"%s\" [%s] has invalid or unknown req: "
779 "\"%s\" \"%s\".",
780 filename, sec, type, name);
781
782 return NULL;
783 }
784
786 }
787
788 return &reqs_list;
789}
790
791/**********************************************************************/
795 struct section_file *file,
796 const char *sec,
797 const char *sub)
798{
799 const char *flag;
800 int j;
801 const char *filename;
802 bool success = TRUE;
803
804 filename = secfile_name(file);
805
806 for (j = 0; (flag = secfile_lookup_str_default(file, NULL, "%s.%s%d.flag",
807 sec, sub, j)); j++) {
808 struct combat_bonus *bonus = fc_malloc(sizeof(*bonus));
809 const char *type;
810
812 if (!unit_type_flag_id_is_valid(bonus->flag)) {
813 log_error("\"%s\": unknown flag name \"%s\" in '%s.%s'.",
814 filename, flag, sec, sub);
815 FC_FREE(bonus);
816 success = FALSE;
817 continue;
818 }
819 type = secfile_lookup_str(file, "%s.%s%d.type", sec, sub, j);
821 if (!combat_bonus_type_is_valid(bonus->type)) {
822 log_error("\"%s\": unknown bonus type \"%s\" in '%s.%s'.",
823 filename, type, sec, sub);
824 FC_FREE(bonus);
825 success = FALSE;
826 continue;
827 }
828 if (!secfile_lookup_int(file, &bonus->value, "%s.%s%d.value",
829 sec, sub, j)) {
830 log_error("\"%s\": failed to get value from '%s.%s%d'.",
831 filename, sec, sub, j);
832 FC_FREE(bonus);
833 success = FALSE;
834 continue;
835 }
837 "%s.%s%d.quiet",
838 sec, sub, j);
840 }
841
842 return success;
843}
844
845/**********************************************************************/
853static bool lookup_tech(struct section_file *file,
854 struct advance **result,
855 const char *prefix, const char *entry,
856 const char *filename,
857 const char *description)
858{
859 const char *sval;
860
861 sval = secfile_lookup_str_default(file, NULL, "%s.%s", prefix, entry);
862 if (!sval || !strcmp(sval, "Never")) {
863 *result = A_NEVER;
864 } else {
865 *result = advance_by_rule_name(sval);
866
867 if (A_NEVER == *result) {
869 "\"%s\" %s %s: couldn't match \"%s\".",
870 filename, (description ? description : prefix), entry, sval);
871 return FALSE;
872 }
873 }
874
875 return TRUE;
876}
877
878/**********************************************************************/
885static bool lookup_unit_list(struct section_file *file, const char *prefix,
886 const char *entry,
887 struct unit_type **output,
888 const char *filename)
889{
890 const char **slist;
891 size_t nval;
892 int i;
893 bool ok = TRUE;
894
895 /* pre-fill with NULL: */
896 for (i = 0; i < MAX_NUM_UNIT_LIST; i++) {
897 output[i] = NULL;
898 }
899 slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
900 if (nval == 0) {
901 /* 'No vector' is considered same as empty vector */
902 if (slist != NULL) {
903 free(slist);
904 }
905 return TRUE;
906 }
907 if (nval > MAX_NUM_UNIT_LIST) {
909 "\"%s\": string vector %s.%s too long (%d, max %d)",
910 filename, prefix, entry, (int) nval, MAX_NUM_UNIT_LIST);
911 ok = FALSE;
912 } else if (nval == 1 && strcmp(slist[0], "") == 0) {
913 free(slist);
914 return TRUE;
915 }
916 if (ok) {
917 for (i = 0; i < nval; i++) {
918 const char *sval = slist[i];
920
921 if (!punittype) {
923 "\"%s\" %s.%s (%d): couldn't match \"%s\".",
924 filename, prefix, entry, i, sval);
925 ok = FALSE;
926 break;
927 }
928 output[i] = punittype;
929 log_debug("\"%s\" %s.%s (%d): %s (%d)", filename, prefix, entry, i, sval,
931 }
932 }
933 free(slist);
934
935 return ok;
936}
937
938/**********************************************************************/
945static bool lookup_tech_list(struct section_file *file, const char *prefix,
946 const char *entry, int *output,
947 const char *filename)
948{
949 const char **slist;
950 size_t nval;
951 int i;
952 bool ok = TRUE;
953
954 /* pre-fill with A_LAST: */
955 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
956 output[i] = A_LAST;
957 }
958 slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
959 if (slist == NULL || nval == 0) {
960 return TRUE;
961 } else if (nval > MAX_NUM_TECH_LIST) {
963 "\"%s\": string vector %s.%s too long (%d, max %d)",
964 filename, prefix, entry, (int) nval, MAX_NUM_TECH_LIST);
965 ok = FALSE;
966 }
967
968 if (ok) {
969 if (nval == 1 && strcmp(slist[0], "") == 0) {
970 FC_FREE(slist);
971 return TRUE;
972 }
973 for (i = 0; i < nval && ok; i++) {
974 const char *sval = slist[i];
976
977 if (NULL == padvance) {
979 "\"%s\" %s.%s (%d): couldn't match \"%s\".",
980 filename, prefix, entry, i, sval);
981 ok = FALSE;
982 }
983 if (!valid_advance(padvance)) {
985 "\"%s\" %s.%s (%d): \"%s\" is removed.",
986 filename, prefix, entry, i, sval);
987 ok = FALSE;
988 }
989
990 if (ok) {
991 output[i] = advance_number(padvance);
992 log_debug("\"%s\" %s.%s (%d): %s (%d)", filename, prefix, entry, i, sval,
994 }
995 }
996 }
997 FC_FREE(slist);
998
999 return ok;
1000}
1001
1002/**********************************************************************/
1009static bool lookup_building_list(struct section_file *file,
1010 const char *prefix, const char *entry,
1011 int *output, const char *filename)
1012{
1013 const char **slist;
1014 size_t nval;
1015 int i;
1016 bool ok = TRUE;
1017
1018 /* pre-fill with B_LAST: */
1019 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
1020 output[i] = B_LAST;
1021 }
1022 slist = secfile_lookup_str_vec(file, &nval, "%s.%s", prefix, entry);
1025 "\"%s\": string vector %s.%s too long (%d, max %d)",
1026 filename, prefix, entry, (int) nval, MAX_NUM_BUILDING_LIST);
1027 ok = FALSE;
1028 } else if (nval == 0 || (nval == 1 && strcmp(slist[0], "") == 0)) {
1029 if (slist != NULL) {
1030 FC_FREE(slist);
1031 }
1032 return TRUE;
1033 }
1034 if (ok) {
1035 for (i = 0; i < nval; i++) {
1036 const char *sval = slist[i];
1037 struct impr_type *pimprove = improvement_by_rule_name(sval);
1038
1039 if (NULL == pimprove) {
1041 "\"%s\" %s.%s (%d): couldn't match \"%s\".",
1042 filename, prefix, entry, i, sval);
1043 ok = FALSE;
1044 break;
1045 }
1046 output[i] = improvement_number(pimprove);
1047 log_debug("%s.%s,%d %s %d", prefix, entry, i, sval, output[i]);
1048 }
1049 }
1050 free(slist);
1051
1052 return ok;
1053}
1054
1055/**********************************************************************/
1061static bool lookup_unit_type(struct section_file *file,
1062 const char *prefix,
1063 const char *entry,
1064 const struct unit_type **result,
1065 const char *filename,
1066 const char *description)
1067{
1068 const char *sval;
1069
1070 sval = secfile_lookup_str_default(file, "None", "%s.%s", prefix, entry);
1071
1072 if (strcmp(sval, "None") == 0) {
1073 *result = NULL;
1074 } else {
1075 *result = unit_type_by_rule_name(sval);
1076 if (*result == NULL) {
1078 "\"%s\" %s %s: couldn't match \"%s\".",
1079 filename, (description ? description : prefix), entry, sval);
1080
1081 return FALSE;
1082 }
1083 }
1084
1085 return TRUE;
1086}
1087
1088/**********************************************************************/
1092static struct government *lookup_government(struct section_file *file,
1093 const char *entry,
1094 const char *filename,
1095 struct government *fallback)
1096{
1097 const char *sval;
1098 struct government *gov;
1099
1100 sval = secfile_lookup_str_default(file, NULL, "%s", entry);
1101 if (!sval) {
1102 gov = fallback;
1103 } else {
1105 }
1106 if (!gov) {
1108 "\"%s\" %s: couldn't match \"%s\".",
1109 filename, entry, sval);
1110 }
1111 return gov;
1112}
1113
1114/**********************************************************************/
1117static char *lookup_string(struct section_file *file, const char *prefix,
1118 const char *suffix)
1119{
1120 const char *sval = secfile_lookup_str(file, "%s.%s", prefix, suffix);
1121
1122 if (NULL != sval) {
1123 char copy[strlen(sval) + 1];
1124
1125 strcpy(copy, sval);
1127 if (strlen(copy) > 0) {
1128 return fc_strdup(copy);
1129 }
1130 }
1131 return NULL;
1132}
1133
1134/**********************************************************************/
1137static struct strvec *lookup_strvec(struct section_file *file,
1138 const char *prefix, const char *suffix)
1139{
1140 size_t dim;
1141 const char **vec = secfile_lookup_str_vec(file, &dim,
1142 "%s.%s", prefix, suffix);
1143
1144 if (NULL != vec) {
1145 struct strvec *dest = strvec_new();
1146
1147 strvec_store(dest, vec, dim);
1148 free(vec);
1149 return dest;
1150 }
1151 return NULL;
1152}
1153
1154/**********************************************************************/
1157static struct extra_type *lookup_resource(const char *filename,
1158 const char *name,
1159 const char *jsection)
1160{
1161 struct extra_type *pres;
1162
1164
1165 if (pres == NULL) {
1167 "\"%s\" [%s] has unknown \"%s\".",
1168 filename, jsection, name);
1169 }
1170
1171 return pres;
1172}
1173
1174/**********************************************************************/
1178static bool lookup_terrain(struct section_file *file,
1179 const char *entry,
1180 const char *filename,
1181 struct terrain *pthis,
1182 struct terrain **result,
1183 bool null_acceptable)
1184{
1185 const int j = terrain_index(pthis);
1186 const char *jsection = &terrain_sections[j * MAX_SECTION_LABEL];
1187 const char *name = secfile_lookup_str(file, "%s.%s", jsection, entry);
1188 struct terrain *pterr;
1189
1190 if (NULL == name && !null_acceptable) {
1191 return FALSE;
1192 }
1193
1194 if (NULL == name
1195 || *name == '\0'
1196 || (0 == strcmp(name, "none"))
1197 || (0 == strcmp(name, "no"))) {
1198 *result = T_NONE;
1199
1200 return TRUE;
1201 }
1202 if (0 == strcmp(name, "yes")) {
1203 *result = pthis;
1204
1205 return TRUE;
1206 }
1207
1209 *result = pterr;
1210
1211 if (pterr == NULL) {
1213 "\"%s\" [%s] has unknown \"%s\".",
1214 secfile_name(file), jsection, name);
1215 return FALSE;
1216 }
1217
1218 return TRUE;
1219}
1220
1221/**********************************************************************/
1228static bool lookup_time(const struct section_file *secfile, int *turns,
1229 const char *sec_name, const char *property_name,
1230 const char *filename, const char *item_name,
1231 bool *ok)
1232{
1233 /* Assumes that PACKET_UNIT_INFO.activity_count in packets.def is UINT16 */
1234 const int max_turns = 65535 / ACTIVITY_FACTOR;
1235
1236 if (!secfile_lookup_int(secfile, turns, "%s.%s", sec_name, property_name)) {
1237 return FALSE;
1238 }
1239
1240 if (*turns > max_turns) {
1242 "\"%s\": \"%s\": \"%s\" value %d too large (max %d)",
1243 filename, item_name ? item_name : sec_name,
1244 property_name, *turns, max_turns);
1245 *ok = FALSE;
1246 }
1247
1248 return TRUE; /* we found _something */
1249}
1250
1251/**********************************************************************/
1255 const char *domain,
1256 struct section_file *file,
1257 const char *sec_name)
1258{
1259 const char *name = secfile_lookup_str(file, "%s.name", sec_name);
1260 const char *rule_name = secfile_lookup_str(file, "%s.rule_name", sec_name);
1261
1262 if (!name) {
1264 "\"%s\" [%s]: no \"name\" specified.",
1265 secfile_name(file), sec_name);
1266 return FALSE;
1267 }
1268
1269 names_set(pname, domain, name, rule_name);
1270
1271 return TRUE;
1272}
1273
1274/**********************************************************************/
1278 struct section_file *file,
1279 const char *secname, const char *field_prefix)
1280{
1281 enum trait tr;
1282
1283 /* FIXME: Use specenum trait names without duplicating them here.
1284 * Just needs to take care of case.
1285 * This list is also duplicated in rulesave.c:save_traits() */
1286 const char *trait_names[] = {
1287 "expansionist",
1288 "trader",
1289 "aggressive",
1290 "builder",
1291 NULL
1292 };
1293
1294 for (tr = trait_begin(); tr != trait_end() && trait_names[tr] != NULL; tr = trait_next(tr)) {
1295 out[tr].min = secfile_lookup_int_default(file, -1, "%s.%s%s_min",
1296 secname,
1298 trait_names[tr]);
1299 out[tr].max = secfile_lookup_int_default(file, -1, "%s.%s%s_max",
1300 secname,
1302 trait_names[tr]);
1303 out[tr].fixed = secfile_lookup_int_default(file, -1, "%s.%s%s_default",
1304 secname,
1306 trait_names[tr]);
1307 }
1308
1309 fc_assert(tr == trait_end()); /* number of trait_names correct */
1310}
1311
1312/**********************************************************************/
1316static bool load_game_names(struct section_file *file,
1317 struct rscompat_info *compat)
1318{
1319 struct section_list *sec;
1320 int nval;
1321 const char *filename = secfile_name(file);
1322 bool ok = TRUE;
1323
1324 /* section: datafile */
1326 if (compat->version <= 0) {
1327 return FALSE;
1328 }
1329
1330 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
1331 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
1332
1334 nval = (NULL != sec ? section_list_size(sec) : 0);
1336 int num = nval; /* No "size_t" to printf */
1337
1339 "\"%s\": Too many achievement types (%d, max %d)",
1340 filename, num, MAX_ACHIEVEMENT_TYPES);
1341 ok = FALSE;
1342 } else {
1344 }
1345
1346 if (ok) {
1349
1350 if (!ruleset_load_names(&pach->name, NULL, file, sec_name)) {
1352 "\"%s\": Cannot load achievement names",
1353 filename);
1354 ok = FALSE;
1355 break;
1356 }
1358 }
1359
1361
1362 if (ok) {
1364
1365 nval = (NULL != sec ? section_list_size(sec) : 0);
1366 if (nval > MAX_GOODS_TYPES) {
1367 int num = nval; /* No "size_t" to printf */
1368
1370 "\"%s\": Too many goods types (%d, max %d)",
1371 filename, num, MAX_GOODS_TYPES);
1373 ok = FALSE;
1374 } else if (nval < 1) {
1376 "\"%s\": At least one goods type needed",
1377 filename);
1379 ok = FALSE;
1380 } else {
1382 }
1383
1384 if (ok) {
1386 const char *sec_name
1388
1389 if (!ruleset_load_names(&pgood->name, NULL, file, sec_name)) {
1391 "\"%s\": Cannot load goods names",
1392 filename);
1393 ok = FALSE;
1394 break;
1395 }
1397 }
1399 }
1400
1401 if (ok) {
1402
1404
1405 nval = (NULL != sec ? section_list_size(sec) : 0);
1406 if (nval > MAX_COUNTERS) {
1407 size_t num = nval;
1408
1410 "\"%s\": Too many counters (" SIZE_T_PRINTF ", max %d)",
1411 filename, num, MAX_COUNTERS);
1412 ok = FALSE;
1413 }
1414
1415 if (ok) {
1416 int count_idx;
1417
1419
1420 for (count_idx = 0; count_idx < nval; count_idx++) {
1421
1423 const char *sec_name
1425
1426 if (!ruleset_load_names(&pcount->name, NULL, file, sec_name)) {
1428 "\"%s\": Cannot load counters names",
1429 filename);
1430 ok = FALSE;
1431 break;
1432 }
1433 }
1434 }
1435
1437 }
1438
1439 return ok;
1440}
1441
1442/**********************************************************************/
1446static bool load_action_names(struct section_file *file,
1447 struct rscompat_info *compat)
1448{
1449 const char *filename = secfile_name(file);
1450 bool ok = TRUE;
1451
1452 if (!rscompat_check_cap_and_version(file, filename, compat)) {
1453 return FALSE;
1454 }
1455
1456 (void) secfile_entry_by_path(file, "datafile.description"); /* Unused */
1457 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* Unused */
1458
1459 return ok;
1460}
1461
1462/**********************************************************************/
1466static bool load_tech_names(struct section_file *file,
1467 struct rscompat_info *compat)
1468{
1469 struct section_list *sec = NULL;
1470 /* Number of techs in the ruleset (means without A_NONE). */
1471 int num_techs = 0;
1472 int i;
1473 const char *filename = secfile_name(file);
1474 bool ok = TRUE;
1475 const char *flag;
1476
1477 if (!rscompat_check_cap_and_version(file, filename, compat)) {
1478 return FALSE;
1479 }
1480
1481 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
1482 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
1483
1484 /* User tech flag names */
1485 for (i = 0; (flag = secfile_lookup_str_default(file, NULL, "control.flags%d.name", i)) ;
1486 i++) {
1487 const char *helptxt = secfile_lookup_str_default(file, NULL, "control.flags%d.helptxt",
1488 i);
1491 "\"%s\": Duplicate tech flag name '%s'",
1492 filename, flag);
1493 ok = FALSE;
1494 break;
1495 }
1496 if (i > MAX_NUM_USER_TECH_FLAGS) {
1498 "\"%s\": Too many user tech flags!",
1499 filename);
1500 ok = FALSE;
1501 break;
1502 }
1503
1504 set_user_tech_flag_name(TECH_USER_1 + i, flag, helptxt);
1505 }
1506
1507 if (ok) {
1508 size_t nval;
1509
1510 for (; i < MAX_NUM_USER_TECH_FLAGS; i++) {
1512 }
1513
1514 /* Tech classes */
1516
1517 nval = (NULL != sec ? section_list_size(sec) : 0);
1518 if (nval > MAX_NUM_TECH_CLASSES) {
1519 int num = nval; /* No "size_t" to printf */
1520
1522 "\"%s\": Too many tech classes (%d, max %d)",
1523 filename, num, MAX_NUM_TECH_CLASSES);
1525 ok = FALSE;
1526 } else {
1528 }
1529
1530 if (ok) {
1532 const char *sec_name
1534
1535 if (!ruleset_load_names(&ptclass->name, NULL, file, sec_name)) {
1536 ruleset_error(NULL, LOG_ERROR, "\"%s\": Cannot load tech class names",
1537 filename);
1538 ok = FALSE;
1539 break;
1540 }
1542 }
1543 }
1544
1545 if (ok) {
1546 /* The techs: */
1548 if (NULL == sec || 0 == (num_techs = section_list_size(sec))) {
1550 "\"%s\": No Advances?!?", filename);
1551 ok = FALSE;
1552 } else {
1553 log_verbose("%d advances (including possibly unused)", num_techs);
1554 if (num_techs + A_FIRST > A_LAST) {
1556 "\"%s\": Too many advances (%d, max %d)",
1557 filename, num_techs, A_LAST - A_FIRST);
1558 ok = FALSE;
1559 }
1560 }
1561 }
1562
1563 if (ok) {
1564 game.control.num_tech_types = num_techs + A_FIRST; /* includes A_NONE */
1565
1566 i = 0;
1567 advance_iterate(adv) {
1568 if (!ruleset_load_names(&adv->name, NULL, file,
1570 ok = FALSE;
1571 break;
1572 }
1573 i++;
1575 }
1577
1578 return ok;
1579}
1580
1581/**********************************************************************/
1584static bool load_ruleset_techs(struct section_file *file,
1585 struct rscompat_info *compat)
1586{
1587 struct section_list *sec;
1588 const char **slist;
1589 int i;
1590 size_t nval;
1592 const char *filename = secfile_name(file);
1593 bool ok = TRUE;
1594
1596
1597 i = 0;
1599 const char *sec_name = section_name(section_list_get(sec, i));
1600
1601 ptclass->cost_pct = secfile_lookup_int_default(file, 100, "%s.%s",
1602 sec_name, "cost_pct");
1603
1604 i++;
1606
1608
1609 i = 0;
1610 advance_iterate(a) {
1611 const char *sec_name = section_name(section_list_get(sec, i));
1612 const char *sval;
1613 int j, ival;
1614 struct requirement_vector *research_reqs;
1615
1616 if (!lookup_tech(file, &a->require[AR_ONE], sec_name, "req1",
1617 filename, rule_name_get(&a->name))
1618 || !lookup_tech(file, &a->require[AR_TWO], sec_name, "req2",
1619 filename, rule_name_get(&a->name))
1620 || !lookup_tech(file, &a->require[AR_ROOT], sec_name, "root_req",
1621 filename, rule_name_get(&a->name))) {
1622 ok = FALSE;
1623 break;
1624 }
1625
1626 if ((A_NEVER == a->require[AR_ONE] && A_NEVER != a->require[AR_TWO])
1627 || (A_NEVER != a->require[AR_ONE] && A_NEVER == a->require[AR_TWO])) {
1629 "\"%s\" [%s] \"%s\": \"Never\" with non-\"Never\".",
1630 filename, sec_name, rule_name_get(&a->name));
1631 ok = FALSE;
1632 break;
1633 }
1634 if (a_none == a->require[AR_ONE] && a_none != a->require[AR_TWO]) {
1636 "\"%s\" [%s] \"%s\": should have \"None\" second.",
1637 filename, sec_name, rule_name_get(&a->name));
1638 ok = FALSE;
1639 break;
1640 }
1641
1642 if (game.control.num_tech_classes == 0) {
1643 a->tclass = NULL;
1644 } else {
1645 const char *classname;
1646
1647 classname = lookup_string(file, sec_name, "class");
1648 if (classname != NULL) {
1651 if (a->tclass == NULL) {
1653 "\"%s\" [%s] \"%s\": Unknown tech class \"%s\".",
1654 filename, sec_name, rule_name_get(&a->name), classname);
1655 ok = FALSE;
1656 break;
1657 }
1658 } else {
1659 a->tclass = NULL; /* Default */
1660 }
1661 }
1662
1663 research_reqs = lookup_req_list(file, sec_name, "research_reqs",
1664 rule_name_get(&a->name));
1665 if (research_reqs == NULL) {
1666 ok = FALSE;
1667 break;
1668 }
1669
1670 requirement_vector_copy(&a->research_reqs, research_reqs);
1671
1672 BV_CLR_ALL(a->flags);
1673
1674 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
1675 for (j = 0; j < nval; j++) {
1676 sval = slist[j];
1677 if (strcmp(sval, "") == 0) {
1678 continue;
1679 }
1683 "\"%s\" [%s] \"%s\": bad flag name \"%s\".",
1684 filename, sec_name, rule_name_get(&a->name), sval);
1685 ok = FALSE;
1686 break;
1687 } else {
1688 BV_SET(a->flags, ival);
1689 }
1690 }
1691 free(slist);
1692
1693 if (!ok) {
1694 break;
1695 }
1696
1697 sz_strlcpy(a->graphic_str,
1698 secfile_lookup_str_default(file, "-", "%s.graphic", sec_name));
1699 sz_strlcpy(a->graphic_alt,
1701 "%s.graphic_alt", sec_name));
1702
1703 a->helptext = lookup_strvec(file, sec_name, "helptext");
1704 a->bonus_message = lookup_string(file, sec_name, "bonus_message");
1705 a->cost = secfile_lookup_int_default(file, -1, "%s.%s",
1706 sec_name, "cost");
1707 a->num_reqs = 0;
1708
1709 i++;
1711
1712 /* Propagate a root tech up into the tech tree. If a technology
1713 * X has Y has a root tech, then any technology requiring X (in the
1714 * normal way or as a root tech) also has Y as a root tech.
1715 * Later techs may gain a whole set of root techs in this way. The one
1716 * we store in AR_ROOT is a more or less arbitrary one of these,
1717 * also signalling that the set is non-empty; after this, you'll still
1718 * have to walk the tech tree to find them all. */
1719restart:
1720
1721 if (ok) {
1722 advance_iterate(a) {
1723 if (valid_advance(a)
1724 && A_NEVER != a->require[AR_ROOT]) {
1725 bool out_of_order = FALSE;
1726
1727 /* Now find any tech depending on this technology and update its
1728 * root_req. */
1729 advance_iterate(b) {
1730 if (valid_advance(b)
1731 && A_NEVER == b->require[AR_ROOT]
1732 && (a == b->require[AR_ONE] || a == b->require[AR_TWO])) {
1733 b->require[AR_ROOT] = a->require[AR_ROOT];
1734 b->inherited_root_req = TRUE;
1735 if (b < a) {
1737 }
1738 }
1740
1741 if (out_of_order) {
1742 /* HACK: If we just changed the root_tech of a lower-numbered
1743 * technology, we need to go back so that we can propagate the
1744 * root_tech up to that technology's parents... */
1745 goto restart;
1746 }
1747 }
1749
1750 /* Now rename A_NEVER to A_NONE for consistency */
1752 if (A_NEVER == a->require[AR_ROOT]) {
1753 a->require[AR_ROOT] = a_none;
1754 }
1756
1757 /* Some more consistency checking:
1758 Non-removed techs depending on removed techs is too
1759 broken to fix by default, so die.
1760 */
1761 advance_iterate(a) {
1762 if (valid_advance(a)) {
1763 /* We check for recursive tech loops later,
1764 * in build_required_techs_helper. */
1765 if (!valid_advance(a->require[AR_ONE])) {
1767 "\"%s\" tech \"%s\": req1 leads to removed tech.",
1768 filename, advance_rule_name(a));
1769 ok = FALSE;
1770 break;
1771 }
1772 if (!valid_advance(a->require[AR_TWO])) {
1774 "\"%s\" tech \"%s\": req2 leads to removed tech.",
1775 filename, advance_rule_name(a));
1776 ok = FALSE;
1777 break;
1778 }
1779 }
1781 }
1782
1784 if (ok) {
1786 }
1787
1788 return ok;
1789}
1790
1791/**********************************************************************/
1795static bool load_unit_names(struct section_file *file,
1796 struct rscompat_info *compat)
1797{
1798 struct section_list *sec = NULL;
1799 int nval = 0;
1800 int i;
1801 const char *filename = secfile_name(file);
1802 const char *flag;
1803 bool ok = TRUE;
1804
1805 if (!rscompat_check_cap_and_version(file, filename, compat)) {
1806 return FALSE;
1807 }
1808
1809 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
1810 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
1811
1812 /* User unit flag names */
1813 for (i = 0; (flag = secfile_lookup_str_default(file, NULL, "control.flags%d.name", i)) ;
1814 i++) {
1815 const char *helptxt = secfile_lookup_str_default(file, NULL, "control.flags%d.helptxt",
1816 i);
1817
1821 "\"%s\": Duplicate unit flag name '%s'",
1822 filename, flag);
1823 ok = FALSE;
1824 break;
1825 }
1826 if (i > MAX_NUM_USER_UNIT_FLAGS) {
1828 "\"%s\": Too many user unit type flags!",
1829 filename);
1830 ok = FALSE;
1831 break;
1832 }
1833
1835 }
1836
1837 if (ok) {
1838 /* Blank the remaining unit type user flags. */
1839 for (; i < MAX_NUM_USER_UNIT_FLAGS; i++) {
1841 }
1842 }
1843
1844 if (ok) {
1845 /* User unit class flag names */
1846 for (i = 0;
1847 (flag = secfile_lookup_str_default(file, NULL,
1848 "control.class_flags%d.name",
1849 i));
1850 i++) {
1851 const char *helptxt = secfile_lookup_str_default(file, NULL,
1852 "control.class_flags%d.helptxt", i);
1853
1857 "\"%s\": Duplicate unit class flag name '%s'",
1858 filename, flag);
1859 ok = FALSE;
1860 break;
1861 }
1864 "\"%s\": Too many user unit class flags!",
1865 filename);
1866 ok = FALSE;
1867 break;
1868 }
1869
1871 }
1872 }
1873
1874 if (ok) {
1875 /* Blank the remaining unit class user flags. */
1876 for (; i < MAX_NUM_USER_UCLASS_FLAGS; i++) {
1878 }
1879 }
1880
1881 if (ok) {
1882 /* Unit classes */
1884 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
1886 "\"%s\": No unit classes?!?", filename);
1887 ok = FALSE;
1888 } else {
1889 log_verbose("%d unit classes", nval);
1890 if (nval > UCL_LAST) {
1892 "\"%s\": Too many unit classes (%d, max %d)",
1893 filename, nval, UCL_LAST);
1894 ok = FALSE;
1895 }
1896 }
1897 }
1898
1899 if (ok) {
1901
1903 const int pci = uclass_index(punitclass);
1904
1905 if (!ruleset_load_names(&punitclass->name, NULL, file,
1907 ok = FALSE;
1908 break;
1909 }
1911 }
1913 sec = NULL;
1914
1915 /* The names: */
1916 if (ok) {
1918 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
1920 "\"%s\": No unit types?!?", filename);
1921 ok = FALSE;
1922 } else {
1923 log_verbose("%d unit types (including possibly unused)", nval);
1924 if (nval > U_LAST) {
1926 "\"%s\": Too many unit types (%d, max %d)",
1927 filename, nval, U_LAST);
1928 ok = FALSE;
1929 }
1930 }
1931 }
1932
1933 if (ok) {
1935
1937 const int utypei = utype_index(punittype);
1938 if (!ruleset_load_names(&punittype->name, NULL, file,
1940 ok = FALSE;
1941 break;
1942 }
1944 }
1946
1947 return ok;
1948}
1949
1950/**********************************************************************/
1953static bool load_ruleset_veteran(struct section_file *file,
1954 const char *path,
1955 struct veteran_system **vsystem, char *err,
1956 size_t err_len)
1957{
1958 const char **vlist_name;
1961 int i;
1962 bool ret = TRUE;
1963
1964 /* The pointer should be uninitialised. */
1965 if (*vsystem != NULL) {
1966 fc_snprintf(err, err_len, "Veteran system is defined?!");
1967 return FALSE;
1968 }
1969
1970 /* Load data. */
1972 "%s.veteran_names", path);
1974 "%s.veteran_power_fact", path);
1976 "%s.veteran_base_raise_chance", path);
1978 "%s.veteran_work_raise_chance",
1979 path);
1981 "%s.veteran_move_bonus", path);
1982
1983 if (count_name > MAX_VET_LEVELS) {
1984 ret = FALSE;
1985 fc_snprintf(err, err_len, "\"%s\": Too many veteran levels (section "
1986 "'%s': %lu, max %d)", secfile_name(file), path,
1987 (long unsigned)count_name, MAX_VET_LEVELS);
1988 } else if (count_name != count_power
1991 || count_name != count_move) {
1992 ret = FALSE;
1993 fc_snprintf(err, err_len, "\"%s\": Different lengths for the veteran "
1994 "settings in section '%s'", secfile_name(file),
1995 path);
1996 } else if (count_name == 0) {
1997 /* Nothing defined. */
1998 *vsystem = NULL;
1999 } else {
2000 /* Generate the veteran system. */
2002
2003#define rs_sanity_veteran(_path, _entry, _i, _condition, _action) \
2004 if (_condition) { \
2005 log_error("Invalid veteran definition '%s.%s[%d]'!", \
2006 _path, _entry, _i); \
2007 log_debug("Failed check: '%s'. Update value: '%s'.", \
2008 #_condition, #_action); \
2009 _action; \
2010 }
2011 for (i = 0; i < count_name; i++) {
2012 /* Some sanity checks. */
2013 rs_sanity_veteran(path, "veteran_power_fact", i,
2014 (vlist_power[i] < 0), vlist_power[i] = 0);
2015 rs_sanity_veteran(path, "veteran_base_raise_chance", i,
2016 (vlist_raise[i] < 0), vlist_raise[i] = 0);
2017 rs_sanity_veteran(path, "veteran_work_raise_chance", i,
2018 (vlist_wraise[i] < 0), vlist_wraise[i] = 0);
2019 rs_sanity_veteran(path, "veteran_move_bonus", i,
2020 (vlist_move[i] < 0), vlist_move[i] = 0);
2021 if (i == 0) {
2022 /* First element.*/
2023 rs_sanity_veteran(path, "veteran_power_fact", i,
2024 (vlist_power[i] != 100), vlist_power[i] = 100);
2025 } else if (i == count_name - 1) {
2026 /* Last element. */
2027 rs_sanity_veteran(path, "veteran_power_fact", i,
2028 (vlist_power[i] < vlist_power[i - 1]),
2029 vlist_power[i] = vlist_power[i - 1]);
2030 rs_sanity_veteran(path, "veteran_base_raise_chance", i,
2031 (vlist_raise[i] != 0), vlist_raise[i] = 0);
2032 rs_sanity_veteran(path, "veteran_work_raise_chance", i,
2033 (vlist_wraise[i] != 0), vlist_wraise[i] = 0);
2034 } else {
2035 /* All elements in between. */
2036 rs_sanity_veteran(path, "veteran_power_fact", i,
2037 (vlist_power[i] < vlist_power[i - 1]),
2038 vlist_power[i] = vlist_power[i - 1]);
2039 rs_sanity_veteran(path, "veteran_base_raise_chance", i,
2040 (vlist_raise[i] > 100), vlist_raise[i] = 100);
2041 rs_sanity_veteran(path, "veteran_work_raise_chance", i,
2042 (vlist_wraise[i] > 100), vlist_wraise[i] = 100);
2043 }
2044
2047 vlist_wraise[i]);
2048 }
2049#undef rs_sanity_veteran
2050 }
2051
2052 if (vlist_name) {
2054 }
2055 if (vlist_power) {
2057 }
2058 if (vlist_raise) {
2060 }
2061 if (vlist_wraise) {
2063 }
2064 if (vlist_move) {
2066 }
2067
2068 return ret;
2069}
2070
2071/**********************************************************************/
2074static bool load_ruleset_units(struct section_file *file,
2075 struct rscompat_info *compat)
2076{
2077 int j, ival;
2078 size_t nval;
2079 struct section_list *sec, *csec;
2080 const char *sval, **slist;
2081 const char *filename = secfile_name(file);
2082 char msg[MAX_LEN_MSG];
2083 bool ok = TRUE;
2084
2085 if (!load_ruleset_veteran(file, "veteran_system", &game.veteran, msg,
2086 sizeof(msg))
2087 || game.veteran == NULL) {
2089 "Error loading the default veteran system: %s",
2090 msg);
2091 ok = FALSE;
2092 }
2093
2095 nval = (NULL != sec ? section_list_size(sec) : 0);
2096
2098 nval = (NULL != csec ? section_list_size(csec) : 0);
2099
2100 if (ok) {
2102 int i = uclass_index(uc);
2103 const char *sec_name = section_name(section_list_get(csec, i));
2104
2105 if (secfile_lookup_int(file, &uc->min_speed, "%s.min_speed", sec_name)) {
2106 uc->min_speed *= SINGLE_MOVE;
2107 } else {
2109 ok = FALSE;
2110 break;
2111 }
2112 if (!secfile_lookup_int(file, &uc->hp_loss_pct,
2113 "%s.hp_loss_pct", sec_name)) {
2115 ok = FALSE;
2116 break;
2117 }
2118
2119 uc->non_native_def_pct = secfile_lookup_int_default(file, 100,
2120 "%s.non_native_def_pct",
2121 sec_name);
2122
2123 BV_CLR_ALL(uc->flags);
2124 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
2125 for (j = 0; j < nval; j++) {
2126 sval = slist[j];
2127 if (strcmp(sval, "") == 0) {
2128 continue;
2129 }
2130
2133 ok = FALSE;
2137 "\"%s\" unit_class \"%s\": unit_type flag \"%s\"!",
2138 filename, uclass_rule_name(uc), sval);
2139 } else {
2141 "\"%s\" unit_class \"%s\": bad flag name \"%s\".",
2142 filename, uclass_rule_name(uc), sval);
2143 }
2144 break;
2145 } else {
2146 BV_SET(uc->flags, ival);
2147 }
2148 }
2149 free(slist);
2150
2151 uc->helptext = lookup_strvec(file, sec_name, "helptext");
2152
2153 if (!ok) {
2154 break;
2155 }
2157 }
2158
2159 if (ok) {
2160 /* Tech and Gov requirements; per unit veteran system */
2162 const int i = utype_index(u);
2163 const struct section *psection = section_list_get(sec, i);
2164 const char *sec_name = section_name(psection);
2165 struct requirement_vector *reqs;
2166
2167 reqs = lookup_req_list(file, sec_name, "reqs",
2168 utype_rule_name(u));
2169
2170 if (reqs == NULL) {
2171 ok = FALSE;
2172 break;
2173 }
2174
2175 requirement_vector_copy(&u->build_reqs, reqs);
2176
2177 if (!load_ruleset_veteran(file, sec_name, &u->veteran,
2178 msg, sizeof(msg))) {
2180 "Error loading the veteran system: %s",
2181 msg);
2182 ok = FALSE;
2183 break;
2184 }
2185
2186 if (!lookup_unit_type(file, sec_name, "obsolete_by",
2187 &u->obsoleted_by, filename,
2188 rule_name_get(&u->name))
2189 || !lookup_unit_type(file, sec_name, "convert_to",
2190 &u->converted_to, filename,
2191 rule_name_get(&u->name))) {
2192 ok = FALSE;
2193 break;
2194 }
2195 u->convert_time = 1; /* default */
2196 lookup_time(file, &u->convert_time, sec_name, "convert_time",
2197 filename, rule_name_get(&u->name), &ok);
2199 }
2200
2201 if (ok) {
2202 /* main stats: */
2204 const int i = utype_index(u);
2205 struct unit_class *pclass;
2206 const char *sec_name = section_name(section_list_get(sec, i));
2207 const char *str;
2208
2209 sval = secfile_lookup_str(file, "%s.class", sec_name);
2211 if (!pclass) {
2213 "\"%s\" unit_type \"%s\": bad class \"%s\".",
2214 filename, utype_rule_name(u), sval);
2215 ok = FALSE;
2216 break;
2217 }
2218 u->uclass = pclass;
2219
2220 sz_strlcpy(u->sound_move,
2221 secfile_lookup_str_default(file, "-", "%s.sound_move",
2222 sec_name));
2223 sz_strlcpy(u->sound_move_alt,
2224 secfile_lookup_str_default(file, "-", "%s.sound_move_alt",
2225 sec_name));
2226 sz_strlcpy(u->sound_fight,
2227 secfile_lookup_str_default(file, "-", "%s.sound_fight",
2228 sec_name));
2229 sz_strlcpy(u->sound_fight_alt,
2230 secfile_lookup_str_default(file, "-", "%s.sound_fight_alt",
2231 sec_name));
2232
2233 if ((str = secfile_lookup_str(file, "%s.graphic", sec_name))) {
2234 sz_strlcpy(u->graphic_str, str);
2235 } else {
2237 ok = FALSE;
2238 break;
2239 }
2240 sz_strlcpy(u->graphic_alt,
2241 secfile_lookup_str_default(file, "-", "%s.graphic_alt",
2242 sec_name));
2243 sz_strlcpy(u->graphic_alt2,
2244 secfile_lookup_str_default(file, "-", "%s.graphic_alt2",
2245 sec_name));
2246
2247 if (!secfile_lookup_int(file, &u->build_cost,
2248 "%s.build_cost", sec_name)
2249 || !secfile_lookup_int(file, &u->pop_cost,
2250 "%s.pop_cost", sec_name)
2251 || !secfile_lookup_int(file, &u->attack_strength,
2252 "%s.attack", sec_name)
2253 || !secfile_lookup_int(file, &u->defense_strength,
2254 "%s.defense", sec_name)
2255 || !secfile_lookup_int(file, &u->move_rate,
2256 "%s.move_rate", sec_name)
2257 || !secfile_lookup_int(file, &u->vision_radius_sq,
2258 "%s.vision_radius_sq", sec_name)
2259 || !secfile_lookup_int(file, &u->transport_capacity,
2260 "%s.transport_cap", sec_name)
2261 || !secfile_lookup_int(file, &u->firepower,
2262 "%s.firepower", sec_name)
2263 || !secfile_lookup_int(file, &u->fuel,
2264 "%s.fuel", sec_name)
2265 || !secfile_lookup_int(file, &u->happy_cost,
2266 "%s.uk_happy", sec_name)) {
2268 ok = FALSE;
2269 break;
2270 }
2271 u->hp
2274 RS_MIN_HP,
2275 RS_MAX_HP,
2276 "%s.hitpoints", sec_name);
2277
2278 u->move_rate *= SINGLE_MOVE;
2279
2280 if (u->firepower <= 0) {
2282 "\"%s\" unit_type \"%s\":"
2283 " firepower is %d,"
2284 " but must be at least 1. "
2285 " If you want no attack ability,"
2286 " set the unit's attack strength to 0.",
2287 filename, utype_rule_name(u), u->firepower);
2288 ok = FALSE;
2289 break;
2290 }
2291
2292 lookup_cbonus_list(u->bonuses, file, sec_name, "bonuses");
2293
2295 u->upkeep[o] = secfile_lookup_int_default(file, 0, "%s.uk_%s",
2296 sec_name,
2299
2300 slist = secfile_lookup_str_vec(file, &nval, "%s.cargo", sec_name);
2301
2302 BV_CLR_ALL(u->cargo);
2303 for (j = 0; j < nval; j++) {
2304 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2305
2306 if (!uclass) {
2308 "\"%s\" unit_type \"%s\":"
2309 "has unknown unit class %s as cargo.",
2310 filename, utype_rule_name(u), slist[j]);
2311 ok = FALSE;
2312 break;
2313 }
2314
2315 BV_SET(u->cargo, uclass_index(uclass));
2316 }
2317 free(slist);
2318
2319 if (!ok) {
2320 break;
2321 }
2322
2323 slist = secfile_lookup_str_vec(file, &nval, "%s.targets", sec_name);
2324 BV_CLR_ALL(u->targets);
2325 for (j = 0; j < nval; j++) {
2326 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2327
2328 if (!uclass) {
2330 "\"%s\" unit_type \"%s\":"
2331 "has unknown unit class %s as target.",
2332 filename, utype_rule_name(u), slist[j]);
2333 ok = FALSE;
2334 break;
2335 }
2336
2337 BV_SET(u->targets, uclass_index(uclass));
2338 }
2339 free(slist);
2340
2341 if (!ok) {
2342 break;
2343 }
2344
2345 slist = secfile_lookup_str_vec(file, &nval, "%s.embarks", sec_name);
2346 BV_CLR_ALL(u->embarks);
2347 for (j = 0; j < nval; j++) {
2348 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2349
2350 if (!uclass) {
2352 "\"%s\" unit_type \"%s\":"
2353 "has unknown unit class %s as embarkable.",
2354 filename, utype_rule_name(u), slist[j]);
2355 ok = FALSE;
2356 break;
2357 }
2358
2359 BV_SET(u->embarks, uclass_index(uclass));
2360 }
2361 free(slist);
2362
2363 if (!ok) {
2364 break;
2365 }
2366
2367 slist = secfile_lookup_str_vec(file, &nval, "%s.disembarks", sec_name);
2368 BV_CLR_ALL(u->disembarks);
2369 for (j = 0; j < nval; j++) {
2370 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
2371
2372 if (!uclass) {
2374 "\"%s\" unit_type \"%s\":"
2375 "has unknown unit class %s as disembarkable.",
2376 filename, utype_rule_name(u), slist[j]);
2377 ok = FALSE;
2378 break;
2379 }
2380
2381 BV_SET(u->disembarks, uclass_index(uclass));
2382 }
2383 free(slist);
2384
2385 if (!ok) {
2386 break;
2387 }
2388
2389 /* Set also all classes that are never unreachable as targets,
2390 * embarks, and disembarks. */
2393 BV_SET(u->targets, uclass_index(preachable));
2394 BV_SET(u->embarks, uclass_index(preachable));
2395 BV_SET(u->disembarks, uclass_index(preachable));
2396 }
2398
2399 str = secfile_lookup_str_default(file, "Main", "%s.vision_layer",
2400 sec_name);
2402 if (!vision_layer_is_valid(u->vlayer)) {
2404 "\"%s\" unit_type \"%s\":"
2405 "has unknown vision layer %s.",
2406 filename, utype_rule_name(u), str);
2407 ok = FALSE;
2408 break;
2409 }
2410
2411 u->helptext = lookup_strvec(file, sec_name, "helptext");
2412
2413 u->paratroopers_range = secfile_lookup_int_default(file,
2414 0, "%s.paratroopers_range", sec_name);
2415
2416 u->bombard_rate = secfile_lookup_int_default(file, 0,
2417 "%s.bombard_rate", sec_name);
2418 u->city_slots = secfile_lookup_int_default(file, 0,
2419 "%s.city_slots", sec_name);
2420 u->city_size = secfile_lookup_int_default(file, 1,
2421 "%s.city_size", sec_name);
2422 if ((sval
2423 = secfile_lookup_str_default(file, nullptr, "%s.specialist", sec_name))) {
2424 if (!(u->spec_type = specialist_by_rule_name(sval))) {
2425 ruleset_error(nullptr, LOG_ERROR,
2426 "\"%s\" unit_type \"%s\":"
2427 " bad specialist \"%s\".",
2428 filename, utype_rule_name(u), sval);
2429 ok = FALSE;
2430 }
2431 } else {
2432 /* Specialists must have been processed before */
2435 ok = FALSE; break);
2437 }
2438
2440 "%s.tp_defense", sec_name);
2441 u->tp_defense = transp_def_type_by_name(sval, fc_strcasecmp);
2442 if (!transp_def_type_is_valid(u->tp_defense)) {
2444 "\"%s\" unit_type \"%s\":"
2445 " bad tp_defense \"%s\".",
2446 filename, utype_rule_name(u), sval);
2447 ok = FALSE;
2448 break;
2449 }
2451 }
2452
2453 if (ok) {
2454 /* Flags */
2456 const int i = utype_index(u);
2457
2458 BV_CLR_ALL(u->flags);
2460
2461 slist = secfile_lookup_str_vec(file, &nval, "%s.flags",
2463 for (j = 0; j < nval; j++) {
2464 sval = slist[j];
2465 if (0 == strcmp(sval, "")) {
2466 continue;
2467 }
2470 ok = FALSE;
2474 "\"%s\" unit_type \"%s\": unit_class flag!",
2475 filename, utype_rule_name(u));
2476 } else {
2478 "\"%s\" unit_type \"%s\": bad flag name \"%s\".",
2479 filename, utype_rule_name(u), sval);
2480 }
2481 break;
2482 } else {
2483 BV_SET(u->flags, ival);
2484 }
2485 }
2486 free(slist);
2487
2488 if (!ok) {
2489 break;
2490 }
2492 }
2493
2494 /* Roles */
2495 if (ok) {
2497 const int i = utype_index(u);
2498
2499 BV_CLR_ALL(u->roles);
2500
2501 slist = secfile_lookup_str_vec(file, &nval, "%s.roles",
2503 for (j = 0; j < nval; j++) {
2504 sval = slist[j];
2505 if (strcmp(sval, "") == 0) {
2506 continue;
2507 }
2511 "\"%s\" unit_type \"%s\": bad role name \"%s\".",
2512 filename, utype_rule_name(u), sval);
2513 ok = FALSE;
2514 break;
2515 } else {
2516 BV_SET(u->roles, ival - L_FIRST);
2517 }
2519 }
2520 free(slist);
2522 }
2523
2524 if (ok) {
2525 /* Some more consistency checking: */
2528 if (!valid_advance(padv)) {
2530 "\"%s\" unit_type \"%s\": depends on removed tech \"%s\".",
2531 filename, utype_rule_name(u),
2533 ok = FALSE;
2534 break;
2535 }
2537
2538 if (!ok) {
2539 break;
2540 }
2542 }
2543
2546
2547 if (ok) {
2549 }
2550
2551 return ok;
2552}
2553
2554/**********************************************************************/
2558static bool load_building_names(struct section_file *file,
2559 struct rscompat_info *compat)
2560{
2561 struct section_list *sec;
2562 int i, nval = 0;
2563 const char *filename = secfile_name(file);
2564 bool ok = TRUE;
2565 const char *flag;
2566
2567 if (!rscompat_check_cap_and_version(file, filename, compat)) {
2568 return FALSE;
2569 }
2570
2571 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
2572 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
2573
2574 /* The names: */
2576 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
2578 "\"%s\": No improvements?!?", filename);
2579 ok = FALSE;
2580 } else {
2581 log_verbose("%d improvement types (including possibly unused)", nval);
2582 if (nval > B_LAST) {
2584 "\"%s\": Too many improvements (%d, max %d)",
2585 filename, nval, B_LAST);
2586 ok = FALSE;
2587 }
2588 }
2589
2590 if (ok) {
2592
2593 for (i = 0; i < nval; i++) {
2594 struct impr_type *b = improvement_by_number(i);
2595
2596 if (!ruleset_load_names(&b->name, NULL, file, section_name(section_list_get(sec, i)))) {
2597 ok = FALSE;
2598 break;
2599 }
2600 }
2601 }
2602
2603 /* User building flag names */
2604 for (i = 0;
2605 (flag = secfile_lookup_str_default(file, NULL,
2606 "control.building_flags%d.name",
2607 i));
2608 i++) {
2609 const char *helptxt = secfile_lookup_str_default(file, NULL,
2610 "control.building_flags%d.helptxt", i);
2611
2613 != impr_flag_id_invalid()) {
2615 "\"%s\": Duplicate building flag name '%s'",
2616 filename, flag);
2617 ok = FALSE;
2618 break;
2619 }
2622 "\"%s\": Too many user building flags!",
2623 filename);
2624 ok = FALSE;
2625 break;
2626 }
2627
2628 set_user_impr_flag_name(IF_USER_FLAG_1 + i, flag, helptxt);
2629 }
2630
2632
2633 return ok;
2634}
2635
2636/**********************************************************************/
2639static bool load_ruleset_buildings(struct section_file *file,
2640 struct rscompat_info *compat)
2641{
2642 struct section_list *sec;
2643 const char *item;
2644 int i, nval;
2645 const char *filename = secfile_name(file);
2646 bool ok = TRUE;
2647
2649 nval = (NULL != sec ? section_list_size(sec) : 0);
2650
2651 for (i = 0; i < nval && ok; i++) {
2652 struct impr_type *b = improvement_by_number(i);
2653 const char *sec_name = section_name(section_list_get(sec, i));
2654 struct requirement_vector *reqs
2655 = lookup_req_list(file, sec_name, "reqs",
2657
2658 if (reqs == NULL) {
2659 ok = FALSE;
2660 break;
2661 } else {
2662 const char *sval, **slist;
2663 int j, ival;
2664 size_t nflags;
2665
2666 item = secfile_lookup_str(file, "%s.genus", sec_name);
2668 if (!impr_genus_id_is_valid(b->genus)) {
2670 "\"%s\" improvement \"%s\": couldn't match "
2671 "genus \"%s\".", filename,
2673 ok = FALSE;
2674 break;
2675 }
2676
2677 slist = secfile_lookup_str_vec(file, &nflags, "%s.flags", sec_name);
2678 BV_CLR_ALL(b->flags);
2679
2680 for (j = 0; j < nflags; j++) {
2681 sval = slist[j];
2682 if (strcmp(sval, "") == 0) {
2683 continue;
2684 }
2688 "\"%s\" improvement \"%s\": bad flag name \"%s\".",
2689 filename, improvement_rule_name(b), sval);
2690 ok = FALSE;
2691 break;
2692 } else {
2693 BV_SET(b->flags, ival);
2694 }
2695 }
2696 free(slist);
2697
2698 if (!ok) {
2699 break;
2700 }
2701
2703
2704 {
2705 struct requirement_vector *obs_reqs
2706 = lookup_req_list(file, sec_name, "obsolete_by",
2708
2709 if (obs_reqs == NULL) {
2710 ok = FALSE;
2711 break;
2712 } else {
2713 requirement_vector_copy(&b->obsolete_by, obs_reqs);
2714 }
2715 }
2716
2717 if (!secfile_lookup_int(file, &b->build_cost,
2718 "%s.build_cost", sec_name)
2719 || !secfile_lookup_int(file, &b->upkeep,
2720 "%s.upkeep", sec_name)
2721 || !secfile_lookup_int(file, &b->sabotage,
2722 "%s.sabotage", sec_name)) {
2724 ok = FALSE;
2725 break;
2726 }
2727
2730 "%s.graphic", sec_name));
2733 "%s.graphic_alt", sec_name));
2736 "%s.graphic_alt2", sec_name));
2737
2740 "%s.sound", sec_name));
2743 "%s.sound_alt", sec_name));
2746 "%s.sound_alt2", sec_name));
2747 b->helptext = lookup_strvec(file, sec_name, "helptext");
2748 }
2749 }
2750
2752 if (ok) {
2754 }
2755
2756 return ok;
2757}
2758
2759/**********************************************************************/
2763static bool load_terrain_names(struct section_file *file,
2764 struct rscompat_info *compat)
2765{
2766 int nval = 0;
2767 struct section_list *sec = NULL;
2768 const char *flag;
2769 int i;
2770 const char *filename = secfile_name(file);
2771 bool ok = TRUE;
2772
2773 if (!rscompat_check_cap_and_version(file, filename, compat)) {
2774 return FALSE;
2775 }
2776
2777 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
2778 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
2779
2780 /* User terrain flag names */
2781 for (i = 0; (flag = secfile_lookup_str_default(file, NULL, "control.flags%d.name", i)) ;
2782 i++) {
2783 const char *helptxt = secfile_lookup_str_default(file, NULL, "control.flags%d.helptxt",
2784 i);
2785
2789 "\"%s\": Duplicate terrain flag name '%s'",
2790 filename, flag);
2791 ok = FALSE;
2792 break;
2793 }
2794 if (i > MAX_NUM_USER_TER_FLAGS) {
2796 "\"%s\": Too many user terrain flags!",
2797 filename);
2798 ok = FALSE;
2799 break;
2800 }
2801
2802 set_user_terrain_flag_name(TER_USER_1 + i, flag, helptxt);
2803 }
2804
2805 if (ok) {
2806 /* Blank the remaining terrain user flag slots. */
2807 for (; i < MAX_NUM_USER_TER_FLAGS; i++) {
2809 }
2810 }
2811
2812 /* User extra flag names */
2813 for (i = 0;
2814 (flag = secfile_lookup_str_default(file, NULL,
2815 "control.extra_flags%d.name",
2816 i));
2817 i++) {
2818 const char *helptxt = secfile_lookup_str_default(file, NULL,
2819 "control.extra_flags%d.helptxt", i);
2820
2822 != extra_flag_id_invalid()) {
2824 "\"%s\": Duplicate extra flag name '%s'",
2825 filename, flag);
2826 ok = FALSE;
2827 break;
2828 }
2831 "\"%s\": Too many user extra flags!",
2832 filename);
2833 ok = FALSE;
2834 break;
2835 }
2836
2837 set_user_extra_flag_name(EF_USER_FLAG_1 + i, flag, helptxt);
2838 }
2839
2840 if (ok) {
2841 /* Blank the remaining extra user flag slots. */
2842 for (; i < MAX_NUM_USER_EXTRA_FLAGS; i++) {
2844 }
2845
2846 /* Terrain names */
2847
2849 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
2851 "\"%s\": ruleset doesn't have any terrains.",
2852 filename);
2853 ok = FALSE;
2854 } else {
2855 if (nval > MAX_NUM_TERRAINS) {
2857 "\"%s\": Too many terrains (%d, max %d)",
2858 filename, nval, MAX_NUM_TERRAINS);
2859 ok = FALSE;
2860 }
2861 }
2862 }
2863
2864 if (ok) {
2866
2867 /* Avoid re-reading files */
2868 if (terrain_sections) {
2870 }
2872
2873 terrain_type_iterate(pterrain) {
2874 const int terri = terrain_index(pterrain);
2875 const char *sec_name = section_name(section_list_get(sec, terri));
2876
2877 if (!ruleset_load_names(&pterrain->name, NULL, file, sec_name)) {
2878 ok = FALSE;
2879 break;
2880 }
2881
2884 }
2885
2887 sec = NULL;
2888
2889 /* Extra names */
2890
2891 if (ok) {
2893 nval = (NULL != sec ? section_list_size(sec) : 0);
2894 if (nval > MAX_EXTRA_TYPES) {
2896 "\"%s\": Too many extra types (%d, max %d)",
2897 filename, nval, MAX_EXTRA_TYPES);
2898 ok = FALSE;
2899 }
2900 }
2901
2902 if (ok) {
2903 int idx;
2904
2906
2907 if (extra_sections) {
2909 }
2911
2912 if (ok) {
2913 for (idx = 0; idx < nval; idx++) {
2914 const char *sec_name = section_name(section_list_get(sec, idx));
2915 struct extra_type *pextra = extra_by_number(idx);
2916
2917 if (!ruleset_load_names(&pextra->name, NULL, file, sec_name)) {
2918 ok = FALSE;
2919 break;
2920 }
2922 }
2923 }
2924 }
2925
2927 sec = NULL;
2928
2929 /* Base names */
2930
2931 if (ok) {
2933 nval = (NULL != sec ? section_list_size(sec) : 0);
2934 if (nval > MAX_EXTRA_TYPES) {
2936 "\"%s\": Too many base types (%d, max %d)",
2937 filename, nval, MAX_EXTRA_TYPES);
2938 ok = FALSE;
2939 }
2940
2942 }
2943
2944 if (ok) {
2945 int idx;
2946
2947 if (base_sections) {
2949 }
2951
2952 /* Cannot use base_type_iterate() before bases are added to
2953 * EC_BASE caused_by list. Have to get them by extra_type_by_rule_name() */
2954 for (idx = 0; idx < nval; idx++) {
2955 const char *sec_name = section_name(section_list_get(sec, idx));
2956 const char *base_name = secfile_lookup_str(file, "%s.extra", sec_name);
2957
2958 if (base_name != NULL) {
2960
2961 if (pextra != NULL) {
2962 base_type_init(pextra, idx);
2964 } else {
2966 "No extra definition matching base definition \"%s\"",
2967 base_name);
2968 ok = FALSE;
2969 }
2970 } else {
2972 "Base section \"%s\" does not associate base with any extra",
2973 sec_name);
2974 ok = FALSE;
2975 }
2976 }
2977 }
2978
2980 sec = NULL;
2981
2982 /* Road names */
2983
2984 if (ok) {
2986 nval = (NULL != sec ? section_list_size(sec) : 0);
2987 if (nval > MAX_EXTRA_TYPES) {
2989 "\"%s\": Too many road types (%d, max %d)",
2990 filename, nval, MAX_EXTRA_TYPES);
2991 ok = FALSE;
2992 }
2993
2995 }
2996
2997 if (ok) {
2998 int idx;
2999
3000 if (road_sections) {
3002 }
3004
3005 /* Cannot use extra_type_by_cause_iterate(EC_ROAD) before roads are added to
3006 * EC_ROAD caused_by list. Have to get them by extra_type_by_rule_name() */
3007 for (idx = 0; idx < nval; idx++) {
3008 const char *sec_name = section_name(section_list_get(sec, idx));
3009 const char *road_name = secfile_lookup_str(file, "%s.extra", sec_name);
3010
3011 if (road_name != NULL) {
3013
3014 if (pextra != NULL) {
3015 road_type_init(pextra, idx);
3017 } else {
3019 "No extra definition matching road definition \"%s\"",
3020 road_name);
3021 ok = FALSE;
3022 }
3023 } else {
3025 "Road section \"%s\" does not associate road with any extra",
3026 sec_name);
3027 ok = FALSE;
3028 }
3029 }
3030 }
3031
3033 sec = NULL;
3034
3035 /* Resource names */
3036 if (ok) {
3038 nval = (NULL != sec ? section_list_size(sec) : 0);
3039 if (nval > MAX_EXTRA_TYPES) {
3041 "\"%s\": Too many resource types (%d, max %d)",
3042 filename, nval, MAX_EXTRA_TYPES);
3043 ok = FALSE;
3044 }
3045
3047 }
3048
3049 if (ok) {
3050 int idx;
3051
3052 if (resource_sections) {
3054 }
3056
3057 /* Cannot use resource_type_iterate() before resource are added to
3058 * EC_RESOURCE caused_by list. Have to get them by extra_type_by_rule_name() */
3059 for (idx = 0; idx < nval; idx++) {
3060 const char *sec_name = section_name(section_list_get(sec, idx));
3061 const char *resource_name;
3062 struct extra_type *pextra = NULL;
3063
3065
3066 if (resource_name != NULL) {
3068
3069 if (pextra != NULL) {
3070 resource_type_init(pextra);
3072 } else {
3074 "No extra definition matching resource definition \"%s\"",
3076 ok = FALSE;
3077 }
3078 } else {
3080 "Resource section %s does not list extra this resource belongs to.",
3081 sec_name);
3082 ok = FALSE;
3083 }
3084 }
3085 }
3086
3088 sec = nullptr;
3089
3090 /* Tiledef names */
3091
3092 if (ok) {
3094 nval = (NULL != sec ? section_list_size(sec) : 0);
3095 if (nval > MAX_TILEDEFS) {
3097 "\"%s\": Too many tiledefs (%d, max %d)",
3098 filename, nval, MAX_TILEDEFS);
3099 ok = FALSE;
3100 }
3101 }
3102
3103 if (ok) {
3104 int idx;
3105
3107
3108 if (tiledef_sections) {
3110 }
3112
3113 if (ok) {
3114 for (idx = 0; idx < nval; idx++) {
3115 const char *sec_name = section_name(section_list_get(sec, idx));
3116 struct tiledef *td = tiledef_by_number(idx);
3117
3118 if (!ruleset_load_names(&td->name, NULL, file, sec_name)) {
3119 ok = FALSE;
3120 break;
3121 }
3123 }
3124 }
3125 }
3126
3128
3129 return ok;
3130}
3131
3132/**********************************************************************/
3135static bool load_ruleset_terrain(struct section_file *file,
3136 struct rscompat_info *compat)
3137{
3138 size_t nval, nval2;
3139 int j;
3140 bool compat_road = FALSE;
3141 bool compat_rail = FALSE;
3142 bool compat_river = FALSE;
3143 const char **res;
3144 const char *filename = secfile_name(file);
3145 const char *text;
3146 int *res_freq;
3147 bool ok = TRUE;
3148
3149 /* parameters */
3150
3151 terrain_control.ocean_reclaim_requirement_pct
3152 = secfile_lookup_int_default(file, 101,
3153 "parameters.ocean_reclaim_requirement");
3154 terrain_control.land_channel_requirement_pct
3155 = secfile_lookup_int_default(file, 101,
3156 "parameters.land_channel_requirement");
3157 terrain_control.terrain_thaw_requirement_pct
3158 = secfile_lookup_int_default(file, 101,
3159 "parameters.thaw_requirement");
3160 terrain_control.terrain_freeze_requirement_pct
3161 = secfile_lookup_int_default(file, 101,
3162 "parameters.freeze_requirement");
3163 terrain_control.lake_max_size
3165 "parameters.lake_max_size");
3166 terrain_control.min_start_native_area
3168 "parameters.min_start_native_area");
3169 terrain_control.move_fragments
3171 "parameters.move_fragments");
3172 if (terrain_control.move_fragments < 1) {
3174 "\"%s\": move_fragments must be at least 1",
3175 filename);
3176 ok = FALSE;
3177 }
3179 terrain_control.igter_cost
3181 "parameters.igter_cost");
3182 if (terrain_control.igter_cost < 1) {
3184 "\"%s\": igter_cost must be at least 1",
3185 filename);
3186 ok = FALSE;
3187 }
3188 terrain_control.infrapoints = FALSE; /* This will be updated if we find
3189 * an placeable extra. */
3190
3191 terrain_control.pythagorean_diagonal
3193 "parameters.pythagorean_diagonal");
3194
3197 "parameters.ocean_resources");
3198
3199 text = secfile_lookup_str_default(file,
3200 N_("?gui_type:Build Type A Base"),
3201 "extraui.ui_name_base_fortress");
3202 sz_strlcpy(terrain_control.gui_type_base0, text);
3203
3204 text = secfile_lookup_str_default(file,
3205 N_("?gui_type:Build Type B Base"),
3206 "extraui.ui_name_base_airbase");
3207 sz_strlcpy(terrain_control.gui_type_base1, text);
3208
3209 if (ok) {
3210 /* Terrain details */
3211
3212 terrain_type_iterate(pterrain) {
3213 const char **slist;
3214 const int i = terrain_index(pterrain);
3215 const char *tsection = &terrain_sections[i * MAX_SECTION_LABEL];
3216 const char *cstr;
3217 const char *ename;
3218
3219 sz_strlcpy(pterrain->graphic_str,
3220 secfile_lookup_str(file, "%s.graphic", tsection));
3221 sz_strlcpy(pterrain->graphic_alt,
3223 "%s.graphic_alt", tsection));
3224 sz_strlcpy(pterrain->graphic_alt2,
3226 "%s.graphic_alt2", tsection));
3227
3228 pterrain->identifier
3229 = secfile_lookup_str(file, "%s.identifier", tsection)[0];
3230 if ('\0' == pterrain->identifier) {
3232 "\"%s\" [%s] identifier missing value.",
3233 filename, tsection);
3234 ok = FALSE;
3235 break;
3236 }
3237 if (TERRAIN_UNKNOWN_IDENTIFIER == pterrain->identifier) {
3239 "\"%s\" [%s] cannot use '%c' as an identifier;"
3240 " it is reserved for unknown terrain.",
3241 filename, tsection, pterrain->identifier);
3242 ok = FALSE;
3243 break;
3244 }
3245 for (j = T_FIRST; j < i; j++) {
3246 if (pterrain->identifier == terrain_by_number(j)->identifier) {
3248 "\"%s\" [%s] has the same identifier as [%s].",
3249 filename, tsection,
3251 ok = FALSE;
3252 break;
3253 }
3254 }
3255
3256 if (!ok) {
3257 break;
3258 }
3259
3260 cstr = secfile_lookup_str(file, "%s.class", tsection);
3261 pterrain->tclass = terrain_class_by_name(cstr, fc_strcasecmp);
3262 if (!terrain_class_is_valid(pterrain->tclass)) {
3264 "\"%s\": [%s] unknown class \"%s\"",
3265 filename, tsection, cstr);
3266 ok = FALSE;
3267 break;
3268 }
3269
3270 if (!secfile_lookup_int(file, &pterrain->movement_cost,
3271 "%s.movement_cost", tsection)
3272 || !secfile_lookup_int(file, &pterrain->defense_bonus,
3273 "%s.defense_bonus", tsection)) {
3275 ok = FALSE;
3276 break;
3277 }
3278
3280 pterrain->output[o]
3281 = secfile_lookup_int_default(file, 0, "%s.%s", tsection,
3284
3285 res = secfile_lookup_str_vec(file, &nval, "%s.resources", tsection);
3287 "%s.resource_freq", tsection);
3288 if (nval2 > 0 && nval2 != nval) {
3290 "\"%s\": [%s] Different lengths for resources "
3291 "and resource frequencies",
3292 filename, tsection);
3293 ok = FALSE;
3294 }
3295 pterrain->resources = fc_calloc(nval + 1, sizeof(*pterrain->resources));
3296 pterrain->resource_freq = fc_calloc(nval + 1,
3297 sizeof(*pterrain->resource_freq));
3298 for (j = 0; j < nval; j++) {
3299 pterrain->resources[j] = lookup_resource(filename, res[j], tsection);
3300 if (pterrain->resources[j] == NULL) {
3301 ok = FALSE;
3302 break;
3303 }
3304 pterrain->resource_freq[j] = j < nval2
3305 ? res_freq[j]
3307 if (pterrain->resource_freq[j] < RESOURCE_FREQUENCY_MINIMUM
3308 || pterrain->resource_freq[j] > RESOURCE_FREQUENCY_MAXIMUM) {
3310 "\"%s\": [%s] Resource frequency '%d' "
3311 "outside allowed range",
3312 filename, tsection,
3313 pterrain->resource_freq[j]);
3314 ok = FALSE;
3315 break;
3316 }
3317 }
3318 pterrain->resources[nval] = NULL;
3319 /* Terminating zero technically not necessary */
3320 pterrain->resource_freq[nval] = 0;
3321 free(res);
3322 res = NULL;
3323 free(res_freq);
3324 res_freq = NULL;
3325
3326 if (!ok) {
3327 break;
3328 }
3329
3331 pterrain->road_output_incr_pct[o]
3332 = secfile_lookup_int_default(file, 0, "%s.road_%s_incr_pct",
3335
3336 if (!lookup_time(file, &pterrain->base_time, tsection, "base_time",
3337 filename, NULL, &ok)
3338 || !lookup_time(file, &pterrain->road_time, tsection, "road_time",
3339 filename, NULL, &ok)) {
3341 ok = FALSE;
3342 break;
3343 }
3344
3345 if (!lookup_terrain(file, "cultivate_result", filename, pterrain,
3346 &pterrain->cultivate_result, FALSE)) {
3347 ruleset_error(NULL, LOG_ERROR, "%s: No cultivate_result", tsection);
3348 ok = FALSE;
3349 break;
3350 }
3351 if (pterrain->cultivate_result == pterrain) {
3353 "%s: Cultivating result in terrain itself.",
3354 tsection);
3355 ok = FALSE;
3356 break;
3357 }
3358 if (!secfile_lookup_int(file, &pterrain->irrigation_food_incr,
3359 "%s.irrigation_food_incr", tsection)
3360 || !lookup_time(file, &pterrain->irrigation_time,
3361 tsection, "irrigation_time", filename, NULL, &ok)) {
3363 ok = FALSE;
3364 break;
3365 }
3366
3367 if (!lookup_terrain(file, "plant_result", filename, pterrain,
3368 &pterrain->plant_result, FALSE)) {
3369 ruleset_error(NULL, LOG_ERROR, "%s: No plant_result", tsection);
3370 ok = FALSE;
3371 break;
3372 }
3373 if (pterrain->plant_result == pterrain) {
3375 "%s: Planting result in terrain itself.",
3376 tsection);
3377 ok = FALSE;
3378 break;
3379 }
3380 if (!secfile_lookup_int(file, &pterrain->mining_shield_incr,
3381 "%s.mining_shield_incr", tsection)
3382 || !lookup_time(file, &pterrain->mining_time,
3383 tsection, "mining_time", filename, NULL, &ok)) {
3385 ok = FALSE;
3386 break;
3387 }
3388
3389 if (!lookup_time(file, &pterrain->cultivate_time,
3390 tsection, "cultivate_time", filename, NULL, &ok)) {
3392 "%s: Missing cultivate_time", tsection);
3393 ok = FALSE;
3394 break;
3395 }
3396 if ((pterrain->cultivate_result != NULL
3397 && pterrain->cultivate_time <= 0)
3398 || (pterrain->cultivate_result == NULL
3399 && pterrain->cultivate_time > 0)) {
3401 "%s: cultivate_result and cultivate_time disagree "
3402 "whether cultivating is enabled", tsection);
3403 ok = FALSE;
3404 break;
3405 }
3406
3407 if (!lookup_time(file, &pterrain->plant_time,
3408 tsection, "plant_time", filename, NULL, &ok)) {
3410 "%s: Missing plant_time", tsection);
3411 ok = FALSE;
3412 break;
3413 }
3414 if ((pterrain->plant_result != NULL
3415 && pterrain->plant_time <= 0)
3416 || (pterrain->plant_result == NULL
3417 && pterrain->plant_time > 0)) {
3419 "%s: plant_result and plant_time disagree "
3420 "whether planting is enabled", tsection);
3421 ok = FALSE;
3422 break;
3423 }
3424
3425 res = secfile_lookup_str_vec(file, &nval, "%s.animals", tsection);
3426 pterrain->num_animals = nval;
3427 if (pterrain->num_animals == 0) {
3428 pterrain->animals = nullptr;
3429 } else {
3430 pterrain->animals = fc_calloc(pterrain->num_animals,
3431 sizeof(*pterrain->animals));
3432 for (j = 0; j < pterrain->num_animals; j++) {
3433 pterrain->animals[j] = unit_type_by_rule_name(res[j]);
3434 if (pterrain->animals[j] == NULL) {
3435 ok = FALSE;
3436 break;
3437 }
3438 }
3439 }
3440 free(res);
3441 res = NULL;
3442 if (!ok) {
3443 break;
3444 }
3445
3446 if (!lookup_terrain(file, "transform_result", filename, pterrain,
3447 &pterrain->transform_result, TRUE)) {
3448 ok = FALSE;
3449 break;
3450 }
3451 if (!lookup_time(file, &pterrain->transform_time,
3452 tsection, "transform_time", filename, NULL, &ok)) {
3454 ok = FALSE;
3455 break;
3456 }
3457 if ((pterrain->transform_result != NULL
3458 && pterrain->transform_time <= 0)
3459 || (pterrain->transform_result == NULL
3460 && pterrain->transform_time > 0)) {
3462 "%s: transform_result and transform_time disagree "
3463 "whether transforming is enabled", tsection);
3464 ok = FALSE;
3465 break;
3466 }
3467
3468 pterrain->placing_time = 1; /* Default */
3469 lookup_time(file, &pterrain->placing_time,
3470 tsection, "placing_time", filename, NULL, &ok);
3471
3472 pterrain->pillage_time = 1; /* Default */
3473 lookup_time(file, &pterrain->pillage_time,
3474 tsection, "pillage_time", filename, NULL, &ok);
3475
3476 if (!lookup_terrain(file, "warmer_wetter_result", filename, pterrain,
3477 &pterrain->warmer_wetter_result, TRUE)
3478 || !lookup_terrain(file, "warmer_drier_result", filename, pterrain,
3479 &pterrain->warmer_drier_result, TRUE)
3480 || !lookup_terrain(file, "cooler_wetter_result", filename, pterrain,
3481 &pterrain->cooler_wetter_result, TRUE)
3482 || !lookup_terrain(file, "cooler_drier_result", filename, pterrain,
3483 &pterrain->cooler_drier_result, TRUE)) {
3484 ok = FALSE;
3485 break;
3486 }
3487
3488 /* Set default removal times */
3489 extra_type_iterate(pextra) {
3490 pterrain->extra_removal_times[extra_index(pextra)] = 0;
3492
3493 for (j = 0; (ename = secfile_lookup_str_default(file, NULL,
3494 "%s.extra_settings%d.extra",
3495 tsection, j)); j++) {
3496 const struct extra_type *pextra = extra_type_by_rule_name(ename);
3497
3498 if (pextra != NULL) {
3499 char time_sections[512];
3500
3502 "%s.extra_settings%d", tsection, j);
3503
3504 lookup_time(file, &pterrain->extra_removal_times[extra_index(pextra)],
3505 time_sections, "removal_time", filename, NULL, &ok);
3506 } else {
3508 "\"%s\" [%s] has settings for unknown extra \"%s\".",
3509 filename, tsection, ename);
3510 ok = FALSE;
3511 break;
3512 }
3513 }
3514
3515 if (ok) {
3516 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", tsection);
3517 BV_CLR_ALL(pterrain->flags);
3518 for (j = 0; j < nval; j++) {
3519 const char *sval = slist[j];
3520 enum terrain_flag_id flag
3522
3523 if (!terrain_flag_id_is_valid(flag)) {
3525 "\"%s\" [%s] has unknown flag \"%s\".",
3526 filename, tsection, sval);
3527 ok = FALSE;
3528 break;
3529 } else {
3530 BV_SET(pterrain->flags, flag);
3531 }
3532 }
3533
3534 free(slist);
3535 }
3536
3537 if (!ok) {
3538 break;
3539 }
3540
3541 {
3543
3547 pterrain->property[mtp]
3548 = secfile_lookup_int_default(file, 0, "%s.property_%s", tsection,
3550 }
3551 }
3552
3553 slist = secfile_lookup_str_vec(file, &nval, "%s.native_to", tsection);
3554 BV_CLR_ALL(pterrain->native_to);
3555 for (j = 0; j < nval; j++) {
3556 struct unit_class *class = unit_class_by_rule_name(slist[j]);
3557
3558 if (!class) {
3560 "\"%s\" [%s] is native to unknown unit class \"%s\".",
3561 filename, tsection, slist[j]);
3562 ok = FALSE;
3563 break;
3564 } else {
3565 BV_SET(pterrain->native_to, uclass_index(class));
3566 }
3567 }
3568 free(slist);
3569
3570 if (!ok) {
3571 break;
3572 }
3573
3574 /* Get terrain color */
3575 {
3576 fc_assert_ret_val(pterrain->rgb == NULL, FALSE);
3577
3578 if (!rgbcolor_load(file, &pterrain->rgb, "%s.color", tsection)) {
3580 "Missing terrain color definition: %s",
3581 secfile_error());
3582 ok = FALSE;
3583 break;
3584 }
3585 }
3586
3587 pterrain->helptext = lookup_strvec(file, tsection, "helptext");
3589 }
3590
3591 if (ok) {
3592 /* Extra details */
3593 extra_type_iterate(pextra) {
3594 BV_CLR_ALL(pextra->conflicts);
3596
3597 extra_type_iterate(pextra) {
3598 int eidx = extra_index(pextra);
3599 const char *section = &extra_sections[eidx * MAX_SECTION_LABEL];
3600 const char **slist;
3601 struct requirement_vector *reqs;
3602 const char *catname;
3603 int cj;
3604 enum extra_cause cause;
3606 const char *eus_name;
3607 const char *vis_req_name;
3608 const struct advance *vis_req;
3609
3610 catname = secfile_lookup_str(file, "%s.category", section);
3611 if (catname == NULL) {
3613 "\"%s\" extra \"%s\" has no category.",
3614 filename, extra_rule_name(pextra));
3615 ok = FALSE;
3616 break;
3617 }
3618 pextra->category = extra_category_by_name(catname, fc_strcasecmp);
3619 if (!extra_category_is_valid(pextra->category)) {
3621 "\"%s\" extra \"%s\" has invalid category \"%s\".",
3622 filename, extra_rule_name(pextra), catname);
3623 ok = FALSE;
3624 break;
3625 }
3626
3627 slist = secfile_lookup_str_vec(file, &nval, "%s.causes", section);
3628 pextra->causes = 0;
3629 for (cj = 0; cj < nval; cj++) {
3630 const char *sval = slist[cj];
3632
3633 if (!extra_cause_is_valid(cause)) {
3635 "\"%s\" extra \"%s\": unknown cause \"%s\".",
3636 filename, extra_rule_name(pextra), sval);
3637 ok = FALSE;
3638 break;
3639 } else {
3640 pextra->causes |= (1 << cause);
3641 extra_to_caused_by_list(pextra, cause);
3642 }
3643 }
3644
3645 if (pextra->causes == 0) {
3646 /* Extras that do not have any causes added to EC_NONE list */
3648 }
3649
3650 if (!is_extra_caused_by(pextra, EC_BASE)
3651 && !is_extra_caused_by(pextra, EC_ROAD)
3652 && !is_extra_caused_by(pextra, EC_RESOURCE)) {
3653 /* Not a base, road, nor resource, so special */
3654 pextra->data.special_idx = extra_type_list_size(extra_type_list_by_cause(EC_SPECIAL));
3656 }
3657
3658 free(slist);
3659
3660 slist = secfile_lookup_str_vec(file, &nval, "%s.rmcauses", section);
3661 pextra->rmcauses = 0;
3662 for (j = 0; j < nval; j++) {
3663 const char *sval = slist[j];
3664
3666
3669 "\"%s\" extra \"%s\": unknown rmcause \"%s\".",
3670 filename, extra_rule_name(pextra), sval);
3671 ok = FALSE;
3672 break;
3673 } else {
3674 pextra->rmcauses |= (1 << rmcause);
3676 }
3677 }
3678
3679 free(slist);
3680
3681 sz_strlcpy(pextra->activity_gfx,
3683 "%s.activity_gfx", section));
3684 sz_strlcpy(pextra->act_gfx_alt,
3686 "%s.act_gfx_alt", section));
3687 sz_strlcpy(pextra->act_gfx_alt2,
3689 "%s.act_gfx_alt2", section));
3690 sz_strlcpy(pextra->rmact_gfx,
3692 "%s.rmact_gfx", section));
3693 sz_strlcpy(pextra->rmact_gfx_alt,
3695 "%s.rmact_gfx_alt", section));
3696 sz_strlcpy(pextra->rmact_gfx_alt2,
3698 "%s.rmact_gfx_alt2", section));
3699 sz_strlcpy(pextra->graphic_str,
3700 secfile_lookup_str_default(file, "-", "%s.graphic", section));
3701 sz_strlcpy(pextra->graphic_alt,
3703 "%s.graphic_alt", section));
3704
3705 reqs = lookup_req_list(file, section, "reqs", extra_rule_name(pextra));
3706 if (reqs == NULL) {
3707 ok = FALSE;
3708 break;
3709 }
3710 requirement_vector_copy(&pextra->reqs, reqs);
3711
3712 reqs = lookup_req_list(file, section, "rmreqs", extra_rule_name(pextra));
3713 if (reqs == NULL) {
3714 ok = FALSE;
3715 break;
3716 }
3717 requirement_vector_copy(&pextra->rmreqs, reqs);
3718
3719 reqs = lookup_req_list(file, section, "appearance_reqs", extra_rule_name(pextra));
3720 if (reqs == NULL) {
3721 ok = FALSE;
3722 break;
3723 }
3724 requirement_vector_copy(&pextra->appearance_reqs, reqs);
3725
3726 reqs = lookup_req_list(file, section, "disappearance_reqs", extra_rule_name(pextra));
3727 if (reqs == NULL) {
3728 ok = FALSE;
3729 break;
3730 }
3731 requirement_vector_copy(&pextra->disappearance_reqs, reqs);
3732
3733 pextra->buildable = secfile_lookup_bool_default(file,
3735 "%s.buildable", section);
3736 pextra->generated = secfile_lookup_bool_default(file, TRUE,
3737 "%s.generated", section);
3738
3739 pextra->build_time = 0; /* default */
3740 lookup_time(file, &pextra->build_time, section, "build_time",
3741 filename, extra_rule_name(pextra), &ok);
3742 pextra->build_time_factor = secfile_lookup_int_default(file, 1,
3743 "%s.build_time_factor", section);
3744 pextra->removal_time = 0; /* default */
3745 lookup_time(file, &pextra->removal_time, section, "removal_time",
3746 filename, extra_rule_name(pextra), &ok);
3747 pextra->removal_time_factor = secfile_lookup_int_default(file, 1,
3748 "%s.removal_time_factor", section);
3749 pextra->infracost = secfile_lookup_int_default(file, 0,
3750 "%s.infracost", section);
3751 if (pextra->infracost > 0) {
3752 terrain_control.infrapoints = TRUE;
3753 }
3754
3755 pextra->defense_bonus = secfile_lookup_int_default(file, 0,
3756 "%s.defense_bonus",
3757 section);
3758 if (pextra->defense_bonus != 0) {
3759 if (extra_has_flag(pextra, EF_NATURAL_DEFENSE)) {
3761 } else {
3763 }
3764 }
3765
3766 eus_name = secfile_lookup_str_default(file, "Normal", "%s.unit_seen", section);
3768 if (!extra_unit_seen_type_is_valid(pextra->eus)) {
3770 "\"%s\" extra \"%s\" has illegal unit_seen value \"%s\".",
3771 filename, extra_rule_name(pextra), eus_name);
3772 ok = FALSE;
3773 break;
3774 }
3775 if (pextra->eus == EUS_HIDDEN) {
3777 }
3778
3779 pextra->appearance_chance = secfile_lookup_int_default(file, RS_DEFAULT_EXTRA_APPEARANCE,
3780 "%s.appearance_chance",
3781 section);
3782 pextra->disappearance_chance = secfile_lookup_int_default(file,
3784 "%s.disappearance_chance",
3785 section);
3786
3787 pextra->no_aggr_near_city = secfile_lookup_int_default(file, -1,
3788 "%s.no_aggr_near_city",
3789 section);
3790
3791 slist = secfile_lookup_str_vec(file, &nval, "%s.native_to", section);
3792 BV_CLR_ALL(pextra->native_to);
3793 for (j = 0; j < nval; j++) {
3794 struct unit_class *uclass = unit_class_by_rule_name(slist[j]);
3795
3796 if (uclass == NULL) {
3798 "\"%s\" extra \"%s\" is native to unknown unit class \"%s\".",
3799 filename, extra_rule_name(pextra), slist[j]);
3800 ok = FALSE;
3801 break;
3802 } else {
3803 BV_SET(pextra->native_to, uclass_index(uclass));
3804 }
3805 }
3806 free(slist);
3807
3808 if (!ok) {
3809 break;
3810 }
3811
3812 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", section);
3813 BV_CLR_ALL(pextra->flags);
3814 for (j = 0; j < nval; j++) {
3815 const char *sval = slist[j];
3816 enum extra_flag_id flag;
3817
3819
3820 if (!extra_flag_id_is_valid(flag)) {
3822 "\"%s\" extra \"%s\": unknown flag \"%s\".",
3823 filename, extra_rule_name(pextra), sval);
3824 ok = FALSE;
3825 break;
3826 } else {
3827 BV_SET(pextra->flags, flag);
3828 }
3829 }
3830 free(slist);
3831
3832 if (pextra->no_aggr_near_city >= 0) {
3834 }
3835
3836 if (extra_has_flag(pextra, EF_CAUSE_ZOC)) {
3838 }
3839
3840 if (!ok) {
3841 break;
3842 }
3843
3844 slist = secfile_lookup_str_vec(file, &nval, "%s.conflicts", section);
3845 for (j = 0; j < nval; j++) {
3846 const char *sval = slist[j];
3848
3849 if (pextra2 == NULL) {
3851 "\"%s\" extra \"%s\": unknown conflict extra \"%s\".",
3852 filename, extra_rule_name(pextra), sval);
3853 ok = FALSE;
3854 break;
3855 } else {
3856 BV_SET(pextra->conflicts, extra_index(pextra2));
3857 BV_SET(pextra2->conflicts, extra_index(pextra));
3858 }
3859 }
3860
3861 free(slist);
3862
3863 if (!ok) {
3864 break;
3865 }
3866
3867 slist = secfile_lookup_str_vec(file, &nval, "%s.hidden_by", section);
3868 BV_CLR_ALL(pextra->hidden_by);
3869 for (j = 0; j < nval; j++) {
3870 const char *sval = slist[j];
3871 const struct extra_type *top = extra_type_by_rule_name(sval);
3872
3873 if (top == NULL) {
3875 "\"%s\" extra \"%s\" hidden by unknown extra \"%s\".",
3876 filename, extra_rule_name(pextra), sval);
3877 ok = FALSE;
3878 break;
3879 } else {
3880 BV_SET(pextra->hidden_by, extra_index(top));
3881 }
3882 }
3883 free(slist);
3884
3885 if (!ok) {
3886 break;
3887 }
3888
3889 slist = secfile_lookup_str_vec(file, &nval, "%s.bridged_over", section);
3890 BV_CLR_ALL(pextra->bridged_over);
3891 for (j = 0; j < nval; j++) {
3892 const char *sval = slist[j];
3893 const struct extra_type *top = extra_type_by_rule_name(sval);
3894
3895 if (top == NULL) {
3897 "\"%s\" extra \"%s\" bridged over unknown extra \"%s\".",
3898 filename, extra_rule_name(pextra), sval);
3899 ok = FALSE;
3900 break;
3901 } else {
3902 BV_SET(pextra->bridged_over, extra_index(top));
3903 }
3904 }
3905 free(slist);
3906
3907 if (!ok) {
3908 break;
3909 }
3910
3912 "%s.visibility_req", section);
3914
3915 if (vis_req == NULL) {
3917 "\"%s\" %s: unknown visibility_req %s.",
3918 filename, section, vis_req_name);
3919 ok = FALSE;
3920 break;
3921 }
3922
3923 pextra->visibility_req = advance_number(vis_req);
3924
3925 pextra->helptext = lookup_strvec(file, section, "helptext");
3927 }
3928
3929 if (ok) {
3930 int i = 0;
3931 /* Resource details */
3932
3934 char identifier[MAX_LEN_NAME];
3935 const char *id;
3937
3938 if (!presource->data.resource) {
3940 "\"%s\" extra \"%s\" has \"Resource\" cause but no "
3941 "corresponding [resource_*] section",
3942 filename, extra_rule_name(presource));
3943 ok = FALSE;
3944 break;
3945 }
3946
3948 presource->data.resource->output[o] =
3949 secfile_lookup_int_default(file, 0, "%s.%s", rsection,
3952
3953 id = secfile_lookup_str_default(file, NULL, "%s.identifier", rsection);
3954
3955 if (id == NULL) {
3956 presource->data.resource->id_old_save = '\0';
3957 } else {
3958 sz_strlcpy(identifier, id);
3959
3960 presource->data.resource->id_old_save = identifier[0];
3961 if (RESOURCE_NULL_IDENTIFIER == presource->data.resource->id_old_save) {
3963 "\"%s\" [%s] identifier missing value.",
3964 filename, rsection);
3965 ok = FALSE;
3966 break;
3967 }
3968 if (RESOURCE_NONE_IDENTIFIER == presource->data.resource->id_old_save) {
3970 "\"%s\" [%s] cannot use '%c' as an identifier;"
3971 " it is reserved.",
3972 filename, rsection, presource->data.resource->id_old_save);
3973 ok = FALSE;
3974 break;
3975 }
3976 }
3977
3978 if (!ok) {
3979 break;
3980 }
3981
3982 i++;
3984
3985 for (j = 0; ok && j < game.control.num_resource_types; j++) {
3986 const char *section = &resource_sections[j * MAX_SECTION_LABEL];
3987 const char *extra_name = secfile_lookup_str(file, "%s.extra", section);
3989
3990 if (!is_extra_caused_by(pextra, EC_RESOURCE)) {
3992 "\"%s\" resource section [%s]: extra \"%s\" does not "
3993 "have \"Resource\" in its causes",
3994 filename, section, extra_name);
3995 ok = FALSE;
3996 }
3997 }
3998 }
3999
4000 if (ok) {
4001 /* This can't be part of previous loop as we don't want random data from previous
4002 * ruleset to play havoc on us when we have only some resource identifiers loaded
4003 * from the new ruleset. */
4005 if (pres->data.resource->id_old_save != '\0') {
4007 if (pres->data.resource->id_old_save == pres2->data.resource->id_old_save
4008 && pres != pres2) {
4010 "\"%s\" [%s] has the same identifier as [%s].",
4011 filename,
4014 ok = FALSE;
4015 break;
4016 }
4018
4019 if (!ok) {
4020 break;
4021 }
4022 }
4024 }
4025
4026 if (ok) {
4027 /* Base details */
4029 struct base_type *pbase = extra_base_get(pextra);
4030 const char *section;
4031 const char *gui_str;
4032
4033 if (!pbase) {
4035 "\"%s\" extra \"%s\" has \"Base\" cause but no "
4036 "corresponding [base_*] section",
4037 filename, extra_rule_name(pextra));
4038 ok = FALSE;
4039 break;
4040 }
4042
4043 gui_str = secfile_lookup_str(file, "%s.gui_type", section);
4045 if (!base_gui_type_is_valid(pbase->gui_type)) {
4047 "\"%s\" base \"%s\": unknown gui_type \"%s\".",
4048 filename, extra_rule_name(pextra), gui_str);
4049 ok = FALSE;
4050 break;
4051 }
4052
4053 pbase->border_sq = secfile_lookup_int_default(file, -1, "%s.border_sq",
4054 section);
4055 pbase->vision_main_sq = secfile_lookup_int_default(file, -1,
4056 "%s.vision_main_sq",
4057 section);
4058 pbase->vision_invis_sq = secfile_lookup_int_default(file, -1,
4059 "%s.vision_invis_sq",
4060 section);
4061 pbase->vision_subs_sq = secfile_lookup_int_default(file, -1,
4062 "%s.vision_subs_sq",
4063 section);
4064
4065 if (!ok) {
4066 break;
4067 }
4068
4071
4073 struct base_type *pbase2;
4074
4075 if (pextra == pextra2) {
4076 /* End of the fully initialized bases iteration. */
4077 break;
4078 }
4079
4082 BV_SET(pextra->conflicts, extra_index(pextra2));
4083 BV_SET(pextra2->conflicts, extra_index(pextra));
4084 }
4086 }
4088
4089 for (j = 0; ok && j < game.control.num_base_types; j++) {
4090 const char *section = &base_sections[j * MAX_SECTION_LABEL];
4091 const char *extra_name = secfile_lookup_str(file, "%s.extra", section);
4093
4094 if (!is_extra_caused_by(pextra, EC_BASE)) {
4096 "\"%s\" base section [%s]: extra \"%s\" does not have "
4097 "\"Base\" in its causes",
4098 filename, section, extra_name);
4099 ok = FALSE;
4100 }
4101 }
4102 }
4103
4104 if (ok) {
4106 struct road_type *proad = extra_road_get(pextra);
4107 const char *section;
4108 const char **slist;
4109 const char *special;
4110 const char *modestr;
4111 struct requirement_vector *reqs;
4112 const char *gui_str;
4113
4114 if (!proad) {
4116 "\"%s\" extra \"%s\" has \"Road\" cause but no "
4117 "corresponding [road_*] section",
4118 filename, extra_rule_name(pextra));
4119 ok = FALSE;
4120 break;
4121 }
4123
4124 gui_str = secfile_lookup_str(file, "%s.gui_type", section);
4126 if (!road_gui_type_is_valid(proad->gui_type)) {
4128 "\"%s\" road \"%s\": unknown gui_type \"%s\".",
4129 filename, extra_rule_name(pextra), gui_str);
4130 ok = FALSE;
4131 break;
4132 }
4133
4134 reqs = lookup_req_list(file, section, "first_reqs", extra_rule_name(pextra));
4135 if (reqs == NULL) {
4136 ok = FALSE;
4137 break;
4138 }
4139 requirement_vector_copy(&proad->first_reqs, reqs);
4140
4141 if (!secfile_lookup_int(file, &proad->move_cost,
4142 "%s.move_cost", section)) {
4143 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4144 ok = FALSE;
4145 break;
4146 }
4147
4148 modestr = secfile_lookup_str_default(file, "FastAlways", "%s.move_mode",
4149 section);
4151 if (!road_move_mode_is_valid(proad->move_mode)) {
4153 "Illegal move_mode \"%s\" for road \"%s\"",
4154 modestr, extra_rule_name(pextra));
4155 ok = FALSE;
4156 break;
4157 }
4158
4160 proad->tile_incr_const[o] =
4161 secfile_lookup_int_default(file, 0, "%s.%s_incr_const",
4163 proad->tile_incr[o] =
4164 secfile_lookup_int_default(file, 0, "%s.%s_incr",
4166 proad->tile_bonus[o] =
4167 secfile_lookup_int_default(file, 0, "%s.%s_bonus",
4170
4171 special = secfile_lookup_str_default(file, "None", "%s.compat_special", section);
4172 if (!fc_strcasecmp(special, "Road")) {
4173 if (compat_road) {
4175 "Multiple roads marked as compatibility \"Road\"");
4176 ok = FALSE;
4177 }
4178 compat_road = TRUE;
4179 proad->compat = ROCO_ROAD;
4180 } else if (!fc_strcasecmp(special, "Railroad")) {
4181 if (compat_rail) {
4183 "Multiple roads marked as compatibility \"Railroad\"");
4184 ok = FALSE;
4185 }
4186 compat_rail = TRUE;
4187 proad->compat = ROCO_RAILROAD;
4188 } else if (!fc_strcasecmp(special, "River")) {
4189 if (compat_river) {
4191 "Multiple roads marked as compatibility \"River\"");
4192 ok = FALSE;
4193 }
4195 proad->compat = ROCO_RIVER;
4196 } else if (!fc_strcasecmp(special, "None")) {
4197 proad->compat = ROCO_NONE;
4198 } else {
4200 "Illegal compatibility special \"%s\" for road %s",
4201 special, extra_rule_name(pextra));
4202 ok = FALSE;
4203 }
4204
4205 if (!ok) {
4206 break;
4207 }
4208
4209 slist = secfile_lookup_str_vec(file, &nval, "%s.integrates", section);
4210 BV_CLR_ALL(proad->integrates);
4211 for (j = 0; j < nval; j++) {
4212 const char *sval = slist[j];
4214 struct road_type *top = NULL;
4215
4216 if (textra != NULL) {
4217 top = extra_road_get(textra);
4218 }
4219
4220 if (top == NULL) {
4222 "\"%s\" road \"%s\" integrates with unknown road \"%s\".",
4223 filename, extra_rule_name(pextra), sval);
4224 ok = FALSE;
4225 break;
4226 } else {
4227 BV_SET(proad->integrates, road_number(top));
4228 }
4229 }
4230 free(slist);
4231
4232 if (!ok) {
4233 break;
4234 }
4235
4236 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", section);
4237 BV_CLR_ALL(proad->flags);
4238 for (j = 0; j < nval; j++) {
4239 const char *sval = slist[j];
4241
4242 if (!road_flag_id_is_valid(flag)) {
4244 "\"%s\" road \"%s\": unknown flag \"%s\".",
4245 filename, extra_rule_name(pextra), sval);
4246 ok = FALSE;
4247 break;
4248 } else {
4249 BV_SET(proad->flags, flag);
4250 }
4251 }
4252 free(slist);
4253
4254 if (!ok) {
4255 break;
4256 }
4258
4259 for (j = 0; ok && j < game.control.num_road_types; j++) {
4260 const char *section = &road_sections[j * MAX_SECTION_LABEL];
4261 const char *extra_name = secfile_lookup_str(file, "%s.extra", section);
4263
4264 if (!is_extra_caused_by(pextra, EC_ROAD)) {
4266 "\"%s\" road section [%s]: extra \"%s\" does not have "
4267 "\"Road\" in its causes",
4268 filename, section, extra_name);
4269 ok = FALSE;
4270 }
4271 }
4272 }
4273
4274 if (ok) {
4275 extra_type_iterate(pextra) {
4276 pextra->bridged = extra_type_list_new();
4278 if (BV_ISSET(pextra->bridged_over, pbridged->id)) {
4279 extra_type_list_append(pextra->bridged, pbridged);
4280 }
4283 }
4284
4285 if (ok) {
4286 /* Tiledef details */
4288 int tdidx = tiledef_index(td);
4290 const char **slist;
4291 int ej;
4292 const char *flag_name;
4293
4294 flag_name = secfile_lookup_str_default(file, nullptr,
4295 "%s.terrain_flag", section);
4296
4297 if (flag_name == nullptr) {
4298 td->terr_flag = terrain_flag_id_invalid();
4299 } else {
4301
4302 if (!terrain_flag_id_is_valid(td->terr_flag)) {
4303 ruleset_error(nullptr, LOG_ERROR,
4304 "%s: Invalid terrain flag %s.",
4306 ok = FALSE;
4307 break;
4308 }
4309 }
4310
4311 slist = secfile_lookup_str_vec(file, &nval, "%s.extras", section);
4312 for (ej = 0; ej < nval; ej++) {
4313 const char *sval = slist[ej];
4314 struct extra_type *pextra = extra_type_by_rule_name(sval);
4315
4316 if (pextra != nullptr) {
4318 if (pextra == old_extra) {
4319 ruleset_error(nullptr, LOG_ERROR,
4320 "%s: Duplicate extra %s.",
4321 section, extra_rule_name(pextra));
4322 ok = FALSE;
4323 break;
4324 }
4326
4327 if (ok) {
4328 extra_type_list_append(td->extras, pextra);
4329 }
4330 } else {
4331 ruleset_error(nullptr, LOG_ERROR,
4332 "%s: Unknown extra name \"%s\".",
4333 section, sval);
4334 ok = FALSE;
4335 }
4336
4337 if (!ok) {
4338 break;
4339 }
4340 }
4342 }
4343
4344 if (ok) {
4346 }
4347
4348 return ok;
4349}
4350
4351/**********************************************************************/
4355static bool load_government_names(struct section_file *file,
4356 struct rscompat_info *compat)
4357{
4358 int nval = 0;
4359 struct section_list *sec;
4360 const char *filename = secfile_name(file);
4361 bool ok = TRUE;
4362 const char *flag;
4363 int i;
4364
4365 if (!rscompat_check_cap_and_version(file, filename, compat)) {
4366 return FALSE;
4367 }
4368
4369 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
4370 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
4371
4373 if (NULL == sec || 0 == (nval = section_list_size(sec))) {
4374 ruleset_error(NULL, LOG_ERROR, "\"%s\": No governments?!?", filename);
4375 ok = FALSE;
4376 } else if (nval > G_LAST) {
4378 "\"%s\": Too many governments (%d, max %d)",
4379 filename, nval, G_LAST);
4380 ok = FALSE;
4381 }
4382
4383 if (ok) {
4385
4386 /* Government names are needed early so that get_government_by_name will
4387 * work. */
4388 governments_iterate(gov) {
4389 const char *sec_name =
4391
4392 if (!ruleset_load_names(&gov->name, NULL, file, sec_name)) {
4393 ok = FALSE;
4394 break;
4395 }
4397 }
4398
4400
4401 if (ok) {
4403 nval = (NULL != sec ? section_list_size(sec) : 0);
4404
4405 if (nval > MAX_NUM_MULTIPLIERS) {
4407 "\"%s\": Too many multipliers (%d, max %d)",
4408 filename, nval, MAX_NUM_MULTIPLIERS);
4409
4410 ok = FALSE;
4411 } else {
4413 }
4414
4415 if (ok) {
4416 multipliers_iterate(pmul) {
4417 const char *sec_name =
4419
4420 if (!ruleset_load_names(&pmul->name, NULL, file, sec_name)) {
4422 "\"%s\": Cannot load multiplier names",
4423 filename);
4424 ok = FALSE;
4425 break;
4426 }
4428 }
4429 }
4430
4431 /* User government flag names */
4432 for (i = 0;
4433 (flag = secfile_lookup_str_default(file, nullptr,
4434 "control.flags%d.name",
4435 i));
4436 i++) {
4437 const char *helptxt = secfile_lookup_str_default(file, nullptr,
4438 "control.flags%d.helptxt", i);
4439
4441 != gov_flag_id_invalid()) {
4442 ruleset_error(nullptr, LOG_ERROR,
4443 "\"%s\": Duplicate government flag name '%s'",
4444 filename, flag);
4445 ok = FALSE;
4446 break;
4447 }
4450 "\"%s\": Too many user government flags!",
4451 filename);
4452 ok = FALSE;
4453 break;
4454 }
4455
4456 set_user_gov_flag_name(GOVF_USER_FLAG_1 + i, flag, helptxt);
4457 }
4458
4460
4461 return ok;
4462}
4463
4464/**********************************************************************/
4468 struct rscompat_info *compat)
4469{
4470 struct section_list *sec;
4471 const char *filename = secfile_name(file);
4472 bool ok = TRUE;
4473
4475
4477 = lookup_government(file, "governments.during_revolution", filename, NULL);
4479 ok = FALSE;
4480 }
4481
4482 if (ok) {
4485
4486 /* Easy ones: */
4488 const int i = government_index(g);
4489 const char *sec_name = section_name(section_list_get(sec, i));
4490 struct requirement_vector *reqs
4491 = lookup_req_list(file, sec_name, "reqs", government_rule_name(g));
4492 const char **slist;
4493 int j;
4494 const char *sval;
4495 size_t nval;
4496
4497 if (reqs == NULL) {
4498 ok = FALSE;
4499 break;
4500 }
4501
4502 if (NULL != secfile_entry_lookup(file, "%s.ai_better", sec_name)) {
4503 char entry[100];
4504
4505 fc_snprintf(entry, sizeof(entry), "%s.ai_better", sec_name);
4506 g->ai.better = lookup_government(file, entry, filename, NULL);
4507 if (g->ai.better == NULL) {
4508 ok = FALSE;
4509 break;
4510 }
4511 } else {
4512 g->ai.better = NULL;
4513 }
4514 requirement_vector_copy(&g->reqs, reqs);
4515
4516 sz_strlcpy(g->graphic_str,
4517 secfile_lookup_str(file, "%s.graphic", sec_name));
4518 sz_strlcpy(g->graphic_alt,
4519 secfile_lookup_str(file, "%s.graphic_alt", sec_name));
4520 sz_strlcpy(g->sound_str,
4521 secfile_lookup_str_default(file, "-", "%s.sound", sec_name));
4522 sz_strlcpy(g->sound_alt,
4523 secfile_lookup_str_default(file, "-", "%s.sound_alt", sec_name));
4524 sz_strlcpy(g->sound_alt2,
4525 secfile_lookup_str_default(file, "-", "%s.sound_alt2", sec_name));
4526
4527 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
4528 BV_CLR_ALL(g->flags);
4529 for (j = 0; j < nval; j++) {
4530 enum gov_flag_id flag;
4531
4532 sval = slist[j];
4534 if (!gov_flag_id_is_valid(flag)) {
4535 ruleset_error(NULL, LOG_ERROR, "\"%s\" government \"%s\": unknown flag \"%s\".",
4536 filename, government_rule_name(g), sval);
4537 ok = FALSE;
4538 break;
4539 } else {
4540 BV_SET(g->flags, flag);
4541 }
4542 }
4543 free(slist);
4544
4545 g->helptext = lookup_strvec(file, sec_name, "helptext");
4547 }
4548
4549
4550 if (ok) {
4551 /* Titles */
4553 const char *sec_name
4555 const char *male, *female;
4556
4557 if (!(male = secfile_lookup_str(file, "%s.ruler_male_title", sec_name))
4558 || !(female = secfile_lookup_str(file, "%s.ruler_female_title",
4559 sec_name))) {
4561 "Lack of default ruler titles for "
4562 "government \"%s\" (nb %d): %s",
4564 secfile_error());
4565 ok = FALSE;
4566 break;
4567 } else if (NULL == government_ruler_title_new(g, NULL, male, female)) {
4569 "Lack of default ruler titles for "
4570 "government \"%s\" (nb %d).",
4572 ok = FALSE;
4573 break;
4574 }
4576 }
4577
4579
4580 if (ok) {
4582 multipliers_iterate(pmul) {
4583 int id = multiplier_index(pmul);
4584 const char *sec_name = section_name(section_list_get(sec, id));
4585 struct requirement_vector *reqs;
4586
4587 if (!secfile_lookup_int(file, &pmul->start, "%s.start", sec_name)) {
4588 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4589 ok = FALSE;
4590 break;
4591 }
4592 if (!secfile_lookup_int(file, &pmul->stop, "%s.stop", sec_name)) {
4593 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4594 ok = FALSE;
4595 break;
4596 }
4597 if (pmul->stop <= pmul->start) {
4599 "Multiplier \"%s\" stop (%d) must be greater "
4600 "than start (%d)", multiplier_rule_name(pmul),
4601 pmul->stop, pmul->start);
4602 ok = FALSE;
4603 break;
4604 }
4605 if (!secfile_lookup_int(file, &pmul->step, "%s.step", sec_name)) {
4606 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4607 ok = FALSE;
4608 break;
4609 }
4610 if (((pmul->stop - pmul->start) % pmul->step) != 0) {
4612 "Multiplier \"%s\" step (%d) does not fit "
4613 "exactly into interval start-stop (%d to %d)",
4614 multiplier_rule_name(pmul), pmul->step,
4615 pmul->start, pmul->stop);
4616 ok = FALSE;
4617 break;
4618 }
4619 if (!secfile_lookup_int(file, &pmul->def, "%s.default", sec_name)) {
4620 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4621 ok = FALSE;
4622 break;
4623 }
4624 if (pmul->def < pmul->start || pmul->def > pmul->stop) {
4626 "Multiplier \"%s\" default (%d) not within "
4627 "legal range (%d to %d)", multiplier_rule_name(pmul),
4628 pmul->def, pmul->start, pmul->stop);
4629 ok = FALSE;
4630 break;
4631 }
4632 if (((pmul->def - pmul->start) % pmul->step) != 0) {
4634 "Multiplier \"%s\" default (%d) not legal "
4635 "with respect to step size %d",
4636 multiplier_rule_name(pmul), pmul->def, pmul->step);
4637 ok = FALSE;
4638 break;
4639 }
4640 pmul->offset = secfile_lookup_int_default(file, 0,
4641 "%s.offset", sec_name);
4642 pmul->factor = secfile_lookup_int_default(file, 100,
4643 "%s.factor", sec_name);
4644 if (pmul->factor == 0) {
4646 "Multiplier \"%s\" scaling factor must "
4647 "not be zero", multiplier_rule_name(pmul));
4648 ok = FALSE;
4649 break;
4650 }
4651
4652 pmul->minimum_turns = secfile_lookup_int_default(file, 0,
4653 "%s.minimum_turns",
4654 sec_name);
4655
4656 reqs = lookup_req_list(file, sec_name, "reqs",
4657 multiplier_rule_name(pmul));
4658 if (reqs == NULL) {
4659 ok = FALSE;
4660 break;
4661 }
4662 requirement_vector_copy(&pmul->reqs, reqs);
4663
4664 pmul->helptext = lookup_strvec(file, sec_name, "helptext");
4667 }
4668
4669 if (ok) {
4671 }
4672
4673 return ok;
4674}
4675
4676/**********************************************************************/
4687static void send_ruleset_control(struct conn_list *dest)
4688{
4690 int idx = 0;
4691
4693
4694 if (game.ruleset_summary != NULL) {
4695 struct packet_ruleset_summary summary;
4696
4698
4699 lsend_packet_ruleset_summary(dest, &summary);
4700 }
4701
4702 while (desc_left > 0) {
4704 int this_len = desc_left;
4705
4706 if (this_len > MAX_LEN_CONTENT - 21) {
4708 }
4709
4710 part.text[this_len] = '\0';
4711
4713 idx += this_len;
4715
4717 }
4718}
4719
4720/**********************************************************************/
4725static const char *check_leader_names(struct nation_type *pnation)
4726{
4728 const char *name = nation_leader_name(pleader);
4729
4731 if (prev_leader == pleader) {
4732 break;
4733 } else if (0 == fc_strcasecmp(name, nation_leader_name(prev_leader))) {
4734 return name;
4735 }
4738 return NULL;
4739}
4740
4741/**********************************************************************/
4745static bool load_nation_names(struct section_file *file,
4746 struct rscompat_info *compat)
4747{
4748 struct section_list *sec;
4749 int j;
4750 bool ok = TRUE;
4751 const char *filename = secfile_name(file);
4752
4753 if (!rscompat_check_cap_and_version(file, filename, compat)) {
4754 return FALSE;
4755 }
4756
4757 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
4758 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
4759
4761 if (NULL == sec) {
4763 "No available nations in this ruleset!");
4764 ok = FALSE;
4765 } else if (section_list_size(sec) > MAX_NUM_NATIONS) {
4767 "Too many nations (max %d, we have %d)!",
4769 ok = FALSE;
4770 } else {
4773
4775 const int i = nation_index(pl);
4776 const char *sec_name = section_name(section_list_get(sec, i));
4777 const char *domain = secfile_lookup_str_default(file, NULL,
4778 "%s.translation_domain", sec_name);
4779 const char *noun_plural = secfile_lookup_str(file,
4780 "%s.plural", sec_name);
4781
4782
4783 if (domain == NULL) {
4784 domain = "freeciv-nations";
4785 }
4786
4787 if (!strcmp("freeciv-core", domain)) {
4788 pl->translation_domain = NULL;
4789 } else if (!strcmp("freeciv-nations", domain)) {
4790 pl->translation_domain = fc_strdup(domain);
4791 } else {
4793 "Unsupported translation domain \"%s\" for %s",
4794 domain, sec_name);
4795 ok = FALSE;
4796 break;
4797 }
4798
4799 if (!ruleset_load_names(&pl->adjective, pl->translation_domain, file, sec_name)) {
4800 ok = FALSE;
4801 break;
4802 }
4803 name_set(&pl->noun_plural, pl->translation_domain, noun_plural);
4804
4805 /* Check if nation name is already defined. */
4806 for (j = 0; j < i && ok; j++) {
4807 struct nation_type *n2 = nation_by_number(j);
4808
4809 /* Compare strings after stripping off qualifiers -- we don't want
4810 * two nations to end up with identical adjectives displayed to users.
4811 * (This check only catches English, not localisations, of course.) */
4812 if (0 == strcmp(Qn_(untranslated_name(&n2->adjective)),
4813 Qn_(untranslated_name(&pl->adjective)))) {
4815 "Two nations defined with the same adjective \"%s\": "
4816 "in section \'%s\' and section \'%s\'",
4817 Qn_(untranslated_name(&pl->adjective)),
4819 ok = FALSE;
4820 } else if (!strcmp(rule_name_get(&n2->adjective),
4821 rule_name_get(&pl->adjective))) {
4822 /* We cannot have the same rule name, as the game needs them to be
4823 * distinct. */
4825 "Two nations defined with the same rule_name \"%s\": "
4826 "in section \'%s\' and section \'%s\'",
4827 rule_name_get(&pl->adjective),
4829 ok = FALSE;
4830 } else if (0 == strcmp(Qn_(untranslated_name(&n2->noun_plural)),
4831 Qn_(untranslated_name(&pl->noun_plural)))) {
4832 /* We don't want identical English plural names either. */
4834 "Two nations defined with the same plural name \"%s\": "
4835 "in section \'%s\' and section \'%s\'",
4836 Qn_(untranslated_name(&pl->noun_plural)),
4838 ok = FALSE;
4839 }
4840 }
4841 if (!ok) {
4842 break;
4843 }
4845 }
4846
4848
4849 if (ok) {
4851 if (sec != NULL) {
4853
4854 section_list_iterate(sec, psection) {
4855 struct nation_group *pgroup;
4856 const char *name;
4857
4858 name = secfile_lookup_str(file, "%s.name", section_name(psection));
4859 if (NULL == name) {
4860 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
4861 ok = FALSE;
4862 break;
4863 }
4865 if (pgroup == NULL) {
4866 ok = FALSE;
4867 break;
4868 }
4871 sec = NULL;
4872 }
4873 }
4874
4875 return ok;
4876}
4877
4878/**********************************************************************/
4881static bool is_on_allowed_list(const char *name, const char **list, size_t len)
4882{
4883 int i;
4884
4885 for (i = 0; i < len; i++) {
4886 if (!fc_strcasecmp(name, list[i])) {
4887 return TRUE;
4888 }
4889 }
4890 return FALSE;
4891}
4892
4893/**********************************************************************/
4897static bool load_city_name_list(struct section_file *file,
4898 struct nation_type *pnation,
4899 const char *secfile_str1,
4900 const char *secfile_str2,
4901 const char **allowed_terrains,
4902 size_t atcount)
4903{
4904 size_t dim, j;
4905 bool ok = TRUE;
4906 const char **cities = secfile_lookup_str_vec(file, &dim, "%s.%s",
4908
4909 /* Each string will be of the form "<cityname> (<label>, <label>, ...)".
4910 * The cityname is just the name for this city, while each "label" matches
4911 * a terrain type for the city (or "river"), with a preceding ! to negate
4912 * it. The parentheses are optional (but necessary to have the settings,
4913 * of course). Our job is now to parse it. */
4914 for (j = 0; j < dim; j++) {
4915 size_t len = strlen(cities[j]);
4916 char city_name[len + 1], *p, *next, *end;
4917 struct nation_city *pncity;
4918
4920
4921 /* Now we wish to determine values for all of the city labels. A value
4922 * of NCP_NONE means no preference (which is necessary so that the use
4923 * of this is optional); NCP_DISLIKE means the label is negated and
4924 * NCP_LIKE means it's labelled. Mostly the parsing just involves
4925 * a lot of ugly string handling... */
4926 if ((p = strchr(city_name, '('))) {
4927 *p++ = '\0';
4928
4929 if (!(end = strchr(p, ')'))) {
4931 "\"%s\" [%s] %s: city name \"%s\" "
4932 "unmatched parenthesis.", secfile_name(file),
4934 ok = FALSE;
4935 } else {
4936 for (*end++ = '\0'; '\0' != *end; end++) {
4937 if (!fc_isspace(*end)) {
4939 "\"%s\" [%s] %s: city name \"%s\" "
4940 "contains characters after last parenthesis.",
4942 cities[j]);
4943 ok = FALSE;
4944 break;
4945 }
4946 }
4947 }
4948 }
4949
4950 /* Build the nation_city. */
4953 /* The ruleset contains a name that is too long. This shouldn't
4954 * happen - if it does, the author should get immediate feedback. */
4956 "\"%s\" [%s] %s: city name \"%s\" is too long.",
4957 secfile_name(file),
4959 ok = FALSE;
4960 city_name[MAX_LEN_CITYNAME - 1] = '\0';
4961 }
4962 pncity = nation_city_new(pnation, city_name);
4963
4964 if (NULL != p) {
4965 /* Handle the labels one at a time. */
4966 do {
4967 enum nation_city_preference prefer;
4968
4969 if ((next = strchr(p, ','))) {
4970 *next = '\0';
4971 }
4973
4974 /* The ! is used to mark a negative, which is recorded with
4975 * NCP_DISLIKE. Otherwise we use a NCP_LIKE.
4976 */
4977 if (*p == '!') {
4978 p++;
4979 prefer = NCP_DISLIKE;
4980 } else {
4981 prefer = NCP_LIKE;
4982 }
4983
4984 if (0 == fc_strcasecmp(p, "river")) {
4986 && !is_on_allowed_list(p,
4989 "\"%s\" [%s] %s: city \"%s\" "
4990 "has terrain hint \"%s\" not in allowed_terrains.",
4992 city_name, p);
4993 ok = FALSE;
4994 } else {
4996 }
4997 } else {
4998 const struct terrain *pterrain = terrain_by_rule_name(p);
4999
5000 if (NULL == pterrain) {
5001 /* Try with removing frequent trailing 's'. */
5002 size_t l = strlen(p);
5003
5004 if (0 < l && 's' == fc_tolower(p[l - 1])) {
5005 char saved = p[l - 1];
5006
5007 p[l - 1] = '\0';
5008 pterrain = terrain_by_rule_name(p);
5009 if (pterrain == NULL) {
5010 /* Didn't help, restore for later allowed_terrains check */
5011 p[l - 1] = saved;
5012 }
5013 }
5014 }
5015
5016 /* Nationset may have been devised with a specific set of terrains
5017 * in mind which don't quite match this ruleset, in which case we
5018 * (a) quietly ignore any hints mentioned that don't happen to be in
5019 * the current ruleset, (b) enforce that terrains mentioned by nations
5020 * must be on the list */
5021 if (pterrain != NULL && game.server.ruledit.allowed_terrains != NULL) {
5022 if (!is_on_allowed_list(p,
5024 /* Terrain exists, but not intended for these nations */
5026 "\"%s\" [%s] %s: city \"%s\" "
5027 "has terrain hint \"%s\" not in allowed_terrains.",
5029 city_name, p);
5030 ok = FALSE;
5031 break;
5032 }
5033 } else if (!pterrain) {
5034 /* Terrain doesn't exist; only complain if it's not on any list */
5036 || !is_on_allowed_list(p,
5039 "\"%s\" [%s] %s: city \"%s\" "
5040 "has unknown terrain hint \"%s\".",
5042 city_name, p);
5043 ok = FALSE;
5044 break;
5045 }
5046 }
5047 if (NULL != pterrain) {
5048 nation_city_set_terrain_preference(pncity, pterrain, prefer);
5049 }
5050 }
5051
5052 p = next ? next + 1 : NULL;
5053 } while (NULL != p && '\0' != *p);
5054 }
5055 }
5056
5057 if (NULL != cities) {
5058 free(cities);
5059 }
5060
5061 return ok;
5062}
5063
5064/**********************************************************************/
5067static bool load_ruleset_nations(struct section_file *file,
5068 struct rscompat_info *compat)
5069{
5070 struct government *gov;
5071 int j;
5072 size_t dim;
5073 char temp_name[MAX_LEN_NAME];
5074 const char **vec;
5075 const char *name, *bad_leader;
5076 const char *sval;
5077 int default_set;
5078 const char *filename = secfile_name(file);
5079 struct section_list *sec = NULL;
5080 enum trait tr;
5081 bool ok = TRUE;
5082
5083 name = secfile_lookup_str_default(file, NULL, "ruledit.nationlist");
5084 if (name != NULL) {
5086 }
5088 "ruledit.embedded_nations");
5089
5090 if (vec != NULL) {
5091 /* Copy to persistent vector */
5094
5095 for (j = 0; j < game.server.ruledit.embedded_nations_count; j++) {
5097 }
5098
5099 free(vec);
5100 }
5101
5103
5104 ruleset_load_traits(game.server.default_traits, file, "default_traits", "");
5105 for (tr = trait_begin(); tr != trait_end(); tr = trait_next(tr)) {
5106 if (game.server.default_traits[tr].min < 0) {
5108 }
5109 if (game.server.default_traits[tr].max < 0) {
5111 }
5112 if (game.server.default_traits[tr].fixed < 0) {
5114
5115 /* TODO: Should sometimes round the a / 2 = x.5 results up */
5117 }
5120 "Default values for trait %s not sane.",
5121 trait_name(tr));
5122 ok = FALSE;
5123 break;
5124 }
5125 }
5126
5127 if (ok) {
5129 "compatibility.allowed_govs");
5130 if (vec != NULL) {
5131 /* Copy to persistent vector */
5133 = fc_malloc(game.server.ruledit.ag_count * sizeof(char *));
5135 (const char **)game.server.ruledit.nc_agovs;
5136
5137 for (j = 0; j < game.server.ruledit.ag_count; j++) {
5139 }
5140
5141 free(vec);
5142 }
5143
5145 "compatibility.allowed_terrains");
5146 if (vec != NULL) {
5147 /* Copy to persistent vector */
5149 = fc_malloc(game.server.ruledit.at_count * sizeof(char *));
5151 (const char **)game.server.ruledit.nc_aterrs;
5152
5153 for (j = 0; j < game.server.ruledit.at_count; j++) {
5155 }
5156
5157 free(vec);
5158 }
5159
5161 "compatibility.allowed_styles");
5162 if (vec != NULL) {
5163 /* Copy to persistent vector */
5165 = fc_malloc(game.server.ruledit.as_count * sizeof(char *));
5167 (const char **)game.server.ruledit.nc_astyles;
5168
5169 for (j = 0; j < game.server.ruledit.as_count; j++) {
5171 }
5172
5173 free(vec);
5174 }
5175
5177 "compatibility.default_government");
5178 /* We deliberately don't check this against allowed_govs. It's only
5179 * specified once so not vulnerable to typos, and may usefully be set in
5180 * a specific ruleset to a gov not explicitly known by the nation set. */
5181 if (sval != NULL) {
5183 if (game.default_government == NULL) {
5185 "Tried to set unknown government type \"%s\" as default_government!",
5186 sval);
5187 ok = FALSE;
5188 } else {
5191 }
5192 }
5193 }
5194
5195 if (ok) {
5197 if (sec != NULL) {
5199
5200 section_list_iterate(sec, psection) {
5201 const char *set_name, *set_rule_name, *set_description;
5202
5203 set_name = secfile_lookup_str(file, "%s.name", section_name(psection));
5205 secfile_lookup_str(file, "%s.rule_name", section_name(psection));
5206 set_description = secfile_lookup_str_default(file, "", "%s.description",
5207 section_name(psection));
5208 if (NULL == set_name || NULL == set_rule_name) {
5209 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
5210 ok = FALSE;
5211 break;
5212 }
5214 ok = FALSE;
5215 break;
5216 }
5219 sec = NULL;
5220 } else {
5222 "At least one nation set [" NATION_SET_SECTION_PREFIX "_*] "
5223 "must be defined.");
5224 ok = FALSE;
5225 }
5226 }
5227
5228 if (ok) {
5229 /* Default set that every nation is a member of. */
5231 "compatibility.default_nationset");
5232 if (sval != NULL) {
5234 if (pset != NULL) {
5236 } else {
5238 "Unknown default_nationset \"%s\".", sval);
5239 ok = FALSE;
5240 }
5241 } else if (nation_set_count() == 1) {
5242 /* If there's only one set defined, every nation is implicitly a
5243 * member of that set. */
5244 default_set = 0;
5245 } else {
5246 /* No default nation set; every nation must explicitly specify at
5247 * least one set to be a member of. */
5248 default_set = -1;
5249 }
5250 }
5251
5252 if (ok) {
5254 if (sec) {
5255 section_list_iterate(sec, psection) {
5256 struct nation_group *pgroup;
5257 bool hidden;
5258
5259 name = secfile_lookup_str(file, "%s.name", section_name(psection));
5261 if (pgroup == NULL) {
5262 ok = FALSE;
5263 break;
5264 }
5265
5266 hidden = secfile_lookup_bool_default(file, FALSE, "%s.hidden",
5267 section_name(psection));
5269
5270 if (!secfile_lookup_int(file, &j, "%s.match", section_name(psection))) {
5271 ruleset_error(NULL, LOG_ERROR, "Error: %s", secfile_error());
5272 ok = FALSE;
5273 break;
5274 }
5278 sec = NULL;
5279 }
5280 }
5281
5282 if (ok) {
5284 nations_iterate(pnation) {
5285 struct nation_type *pconflict;
5286 const int i = nation_index(pnation);
5287 char tmp[200] = "\0";
5288 const char *barb_type;
5289 const char *sec_name = section_name(section_list_get(sec, i));
5290 const char *legend;
5291
5292 /* Nation sets and groups. */
5293 if (default_set >= 0) {
5294 nation_set_list_append(pnation->sets,
5296 }
5297 vec = secfile_lookup_str_vec(file, &dim, "%s.groups", sec_name);
5298 for (j = 0; j < dim; j++) {
5299 struct nation_set *pset = nation_set_by_rule_name(vec[j]);
5301
5302 fc_assert(pset == NULL || pgroup == NULL);
5303
5304 if (NULL != pset) {
5305 nation_set_list_append(pnation->sets, pset);
5306 } else if (NULL != pgroup) {
5307 nation_group_list_append(pnation->groups, pgroup);
5308 } else {
5309 /* For nation authors, this would probably be considered an error.
5310 * But it can happen normally. The civ1 compatibility ruleset only
5311 * uses the nations that were in civ1, so not all of the links will
5312 * exist. */
5313 log_verbose("Nation %s: Unknown set/group \"%s\".",
5314 nation_rule_name(pnation), vec[j]);
5315 }
5316 }
5317 if (NULL != vec) {
5318 free(vec);
5319 }
5320 if (nation_set_list_size(pnation->sets) < 1) {
5322 "Nation %s is not a member of any nation set",
5323 nation_rule_name(pnation));
5324 ok = FALSE;
5325 break;
5326 }
5327
5328 /* Nation conflicts. */
5329 vec = secfile_lookup_str_vec(file, &dim, "%s.conflicts_with", sec_name);
5330 for (j = 0; j < dim; j++) {
5332
5333 if (pnation == pconflict) {
5335 "Nation %s conflicts with itself",
5336 nation_rule_name(pnation));
5337 ok = FALSE;
5338 break;
5339 } else if (NULL != pconflict) {
5340 nation_list_append(pnation->server.conflicts_with, pconflict);
5341 } else {
5342 /* For nation authors, this would probably be considered an error.
5343 * But it can happen normally. The civ1 compatibility ruleset only
5344 * uses the nations that were in civ1, so not all of the links will
5345 * exist. */
5346 log_verbose("Nation %s: conflicts_with nation \"%s\" is unknown.",
5347 nation_rule_name(pnation), vec[j]);
5348 }
5349 }
5350 if (NULL != vec) {
5351 free(vec);
5352 }
5353 if (!ok) {
5354 break;
5355 }
5356
5357 /* Nation leaders. */
5358 for (j = 0; j < MAX_NUM_LEADERS; j++) {
5359 const char *sexstr;
5360 sex_t sex;
5361 bool is_male = FALSE;
5362
5363 name = secfile_lookup_str(file, "%s.leaders%d.name", sec_name, j);
5364 if (NULL == name) {
5365 /* No more to read. */
5366 break;
5367 }
5368
5369 if (check_name(name)) {
5370 /* The ruleset contains a name that is too long. This shouldn't
5371 * happen - if it does, the author should get immediate feedback */
5374 "Nation %s: leader name \"%s\" is too long.",
5375 nation_rule_name(pnation), name);
5376 ok = FALSE;
5377 break;
5378 }
5379
5380 sexstr = secfile_lookup_str(file, "%s.leaders%d.sex", sec_name, j);
5381 if (NULL == sexstr) {
5383 "Nation %s: leader \"%s\": %s.",
5384 nation_rule_name(pnation), name, secfile_error());
5385 ok = FALSE;
5386 break;
5387 }
5388
5390
5391 switch (sex) {
5392 case SEX_MALE:
5393 is_male = TRUE;
5394 break;
5395 case SEX_FEMALE:
5396 is_male = FALSE;
5397 break;
5398 case SEX_UNKNOWN:
5400 "Nation %s: leader \"%s\" has unsupported "
5401 "sex variant \"%s\".",
5402 nation_rule_name(pnation), name, sexstr);
5403 ok = FALSE;
5404 break;
5405 }
5406
5407 if (ok) {
5408 (void) nation_leader_new(pnation, name, is_male);
5409 }
5410 }
5411 if (!ok) {
5412 break;
5413 }
5414
5415 /* Check the number of leaders. */
5416 if (MAX_NUM_LEADERS == j) {
5417 /* Too much leaders, get the real number defined in the ruleset. */
5418 while (NULL != secfile_entry_lookup(file, "%s.leaders%d.name",
5419 sec_name, j)) {
5420 j++;
5421 }
5423 "Nation %s: Too many leaders; max is %d",
5425 ok = FALSE;
5426 break;
5427 } else if (0 == j) {
5429 "Nation %s: no leaders; at least one is required.",
5430 nation_rule_name(pnation));
5431 ok = FALSE;
5432 break;
5433 }
5434
5435 /* Check if leader name is not already defined in this nation. */
5436 if ((bad_leader = check_leader_names(pnation))) {
5438 "Nation %s: leader \"%s\" defined more than once.",
5439 nation_rule_name(pnation), bad_leader);
5440 ok = FALSE;
5441 break;
5442 }
5443
5444 /* Nation player color preference, if any */
5445 fc_assert_ret_val(pnation->server.rgb == NULL, FALSE);
5446 (void) rgbcolor_load(file, &pnation->server.rgb, "%s.color", sec_name);
5447
5448 /* Load nation traits */
5449 ruleset_load_traits(pnation->server.traits, file, sec_name, "trait_");
5450 for (tr = trait_begin(); tr != trait_end(); tr = trait_next(tr)) {
5451 bool server_traits_used = TRUE;
5452
5453 if (pnation->server.traits[tr].min < 0) {
5454 pnation->server.traits[tr].min = game.server.default_traits[tr].min;
5455 } else {
5457 }
5458 if (pnation->server.traits[tr].max < 0) {
5459 pnation->server.traits[tr].max = game.server.default_traits[tr].max;
5460 } else {
5462 }
5463 if (pnation->server.traits[tr].fixed < 0) {
5464 if (server_traits_used) {
5465 pnation->server.traits[tr].fixed = game.server.default_traits[tr].fixed;
5466 } else {
5467 int diff = pnation->server.traits[tr].max - pnation->server.traits[tr].min;
5468
5469 /* TODO: Should sometimes round the a / 2 = x.5 results up */
5470 pnation->server.traits[tr].fixed = diff / 2 + pnation->server.traits[tr].min;
5471 }
5472 }
5473 if (pnation->server.traits[tr].max < pnation->server.traits[tr].min) {
5475 "%s values for trait %s not sane.",
5476 nation_rule_name(pnation), trait_name(tr));
5477 ok = FALSE;
5478 break;
5479 }
5480 }
5481
5482 if (!ok) {
5483 break;
5484 }
5485
5486 pnation->is_playable =
5487 secfile_lookup_bool_default(file, TRUE, "%s.is_playable", sec_name);
5488
5489 /* Check barbarian type. Default is "None" meaning not a barbarian */
5490 barb_type = secfile_lookup_str_default(file, "None",
5491 "%s.barbarian_type", sec_name);
5492 pnation->barb_type = barbarian_type_by_name(barb_type, fc_strcasecmp);
5493 if (!barbarian_type_is_valid(pnation->barb_type)) {
5495 "Nation %s, barbarian_type is invalid (\"%s\")",
5496 nation_rule_name(pnation), barb_type);
5497 ok = FALSE;
5498 break;
5499 }
5500
5501 if (pnation->barb_type != NOT_A_BARBARIAN
5502 && pnation->is_playable) {
5503 /* We can't allow players to use barbarian nations, barbarians
5504 * may run out of nations */
5506 "Nation %s marked both barbarian and playable.",
5507 nation_rule_name(pnation));
5508 ok = FALSE;
5509 break;
5510 }
5511
5512 /* Flags */
5513 sz_strlcpy(pnation->flag_graphic_str,
5514 secfile_lookup_str_default(file, "-", "%s.flag", sec_name));
5515 sz_strlcpy(pnation->flag_graphic_alt,
5517 "%s.flag_alt", sec_name));
5518
5519 /* Ruler titles */
5520 for (j = 0;; j++) {
5521 const char *male, *female;
5522
5524 "%s.ruler_titles%d.government",
5525 sec_name, j);
5526 if (NULL == name) {
5527 /* End of the list of ruler titles. */
5528 break;
5529 }
5530
5531 /* NB: even if the government doesn't exist, we load the entries for
5532 * the ruler titles to avoid warnings about unused entries. */
5533 male = secfile_lookup_str(file, "%s.ruler_titles%d.male_title",
5534 sec_name, j);
5535 female = secfile_lookup_str(file, "%s.ruler_titles%d.female_title",
5536 sec_name, j);
5538
5539 /* Nationset may have been devised with a specific set of govs in
5540 * mind which don't quite match this ruleset, in which case we
5541 * (a) quietly ignore any govs mentioned that don't happen to be in
5542 * the current ruleset, (b) enforce that govs mentioned by nations
5543 * must be on the list */
5544 if (gov != NULL && game.server.ruledit.allowed_govs != NULL) {
5548 /* Gov exists, but not intended for these nations */
5549 gov = NULL;
5551 "Nation %s: government \"%s\" not in allowed_govs.",
5552 nation_rule_name(pnation), name);
5553 ok = FALSE;
5554 break;
5555 }
5556 } else if (!gov) {
5557 /* Gov doesn't exist; only complain if it's not on any list */
5563 "Nation %s: government \"%s\" not found.",
5564 nation_rule_name(pnation), name);
5565 ok = FALSE;
5566 break;
5567 }
5568 }
5569 if (NULL != male && NULL != female) {
5570 if (gov) {
5571 (void) government_ruler_title_new(gov, pnation, male, female);
5572 }
5573 } else {
5575 ok = FALSE;
5576 break;
5577 }
5578 }
5579 if (!ok) {
5580 break;
5581 }
5582
5583 /* City styles */
5584 name = secfile_lookup_str(file, "%s.style", sec_name);
5585 if (!name) {
5587 ok = FALSE;
5588 break;
5589 }
5590 pnation->style = style_by_rule_name(name);
5591 if (pnation->style == NULL) {
5597 "Nation %s: Illegal style \"%s\"",
5598 nation_rule_name(pnation), name);
5599 ok = FALSE;
5600 break;
5601 } else {
5602 log_verbose("Nation %s: style \"%s\" not supported in this "
5603 "ruleset; using default.",
5604 nation_rule_name(pnation), name);
5605 pnation->style = style_by_number(0);
5606 }
5607 }
5608
5609 /* Civilwar nations */
5610 vec = secfile_lookup_str_vec(file, &dim,
5611 "%s.civilwar_nations", sec_name);
5612 for (j = 0; j < dim; j++) {
5614
5615 /* No test for duplicate nations is performed. If there is a duplicate
5616 * entry it will just cause that nation to have an increased
5617 * probability of being chosen. */
5618 if (pconflict == pnation) {
5620 "Nation %s is its own civil war nation",
5621 nation_rule_name(pnation));
5622 ok = FALSE;
5623 break;
5624 } else if (NULL != pconflict) {
5625 nation_list_append(pnation->server.civilwar_nations, pconflict);
5626 nation_list_append(pconflict->server.parent_nations, pnation);
5627 } else {
5628 /* For nation authors, this would probably be considered an error.
5629 * But it can happen normally. The civ1 compatibility ruleset only
5630 * uses the nations that were in civ1, so not all of the links will
5631 * exist. */
5632 log_verbose("Nation %s: civil war nation \"%s\" is unknown.",
5633 nation_rule_name(pnation), vec[j]);
5634 }
5635 }
5636 if (NULL != vec) {
5637 free(vec);
5638 }
5639 if (!ok) {
5640 break;
5641 }
5642
5643 /* Load nation specific initial items */
5644 if (!lookup_tech_list(file, sec_name, "init_techs",
5645 pnation->init_techs, filename)) {
5646 ok = FALSE;
5647 break;
5648 }
5649 if (!lookup_building_list(file, sec_name, "init_buildings",
5650 pnation->init_buildings, filename)) {
5651 ok = FALSE;
5652 break;
5653 }
5654 if (!lookup_unit_list(file, sec_name, "init_units",
5655 pnation->init_units, filename)) {
5656 ok = FALSE;
5657 break;
5658 }
5659 fc_strlcat(tmp, sec_name, 200);
5660 fc_strlcat(tmp, ".init_government", 200);
5661 if (secfile_entry_by_path(file, tmp)) {
5662 pnation->init_government = lookup_government(file, tmp, filename,
5663 NULL);
5664 /* If specified, init_government has to be in this specific ruleset,
5665 * not just allowed_govs */
5666 if (pnation->init_government == NULL) {
5667 ok = FALSE;
5668 break;
5669 }
5670 /* ...but if a list of govs has been specified, enforce that this
5671 * nation's init_government is on the list. */
5673 && !is_on_allowed_list(government_rule_name(pnation->init_government),
5677 "Nation %s: init_government \"%s\" not allowed.",
5678 nation_rule_name(pnation),
5679 government_rule_name(pnation->init_government));
5680 ok = FALSE;
5681 break;
5682 }
5683 }
5684
5685 /* Read default city names. */
5686 if (!load_city_name_list(file, pnation, sec_name, "cities",
5689 ok = FALSE;
5690 break;
5691 }
5692
5693 legend = secfile_lookup_str_default(file, "", "%s.legend", sec_name);
5694 pnation->legend = fc_strdup(legend);
5695 if (check_strlen(pnation->legend, MAX_LEN_MSG, NULL)) {
5697 "Nation %s: legend \"%s\" is too long.",
5698 nation_rule_name(pnation),
5699 pnation->legend);
5700 ok = FALSE;
5701 break;
5702 }
5703
5704 pnation->player = NULL;
5707 sec = NULL;
5708 }
5709
5710 /* Clean up on aborted load */
5711 if (sec != NULL) {
5712 fc_assert(!ok);
5714 }
5715
5716 if (ok) {
5718 }
5719
5720 if (ok) {
5721 /* Update cached number of playable nations in the current set */
5723
5724 /* Sanity checks on all sets */
5727
5728 nations_iterate(pnation) {
5729 if (nation_is_in_set(pnation, pset)) {
5730 switch (nation_barbarian_type(pnation)) {
5731 case NOT_A_BARBARIAN:
5732 if (is_nation_playable(pnation)) {
5733 num_playable++;
5734 }
5735 break;
5736 case LAND_BARBARIAN:
5738 break;
5739 case SEA_BARBARIAN:
5741 break;
5742 case ANIMAL_BARBARIAN:
5743 /* Animals are optional */
5744 break;
5747 break;
5748 default:
5750 }
5751 }
5753 if (num_playable < 1) {
5755 "Nation set \"%s\" has no playable nations. "
5756 "At least one required!", nation_set_rule_name(pset));
5757 ok = FALSE;
5758 break;
5759 }
5760 if (barb_land_count == 0 && barb_both_count == 0) {
5762 "No land barbarian nation defined in set \"%s\". "
5763 "At least one required!", nation_set_rule_name(pset));
5764 ok = FALSE;
5765 break;
5766 }
5767 if (barb_sea_count == 0 && barb_both_count == 0) {
5769 "No sea barbarian nation defined in set \"%s\". "
5770 "At least one required!", nation_set_rule_name(pset));
5771 ok = FALSE;
5772 break;
5773 }
5775 }
5776
5777 return ok;
5778}
5779
5780/**********************************************************************/
5784static bool load_style_names(struct section_file *file,
5785 struct rscompat_info *compat)
5786{
5787 bool ok = TRUE;
5788 struct section_list *sec;
5789 const char *filename = secfile_name(file);
5790
5791 if (!rscompat_check_cap_and_version(file, filename, compat)) {
5792 return FALSE;
5793 }
5794
5795 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
5796 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
5797
5799 if (NULL == sec) {
5801 "No available nation styles in this ruleset!");
5802 ok = FALSE;
5803 } else {
5805
5807
5809 const int i = style_index(ps);
5810 const char *sec_name = section_name(section_list_get(sec, i));
5811
5812 ruleset_load_names(&ps->name, NULL, file, sec_name);
5814 }
5815
5817
5818 if (ok) {
5819 /* The citystyle sections: */
5820 int i = 0;
5821
5823 if (NULL != sec) {
5825 section_list_iterate(sec, style) {
5826 if (!ruleset_load_names(&city_styles[i].name, NULL, file, section_name(style))) {
5827 ok = FALSE;
5828 break;
5829 }
5830 i++;
5832
5834 } else {
5836 }
5837 }
5838
5839 return ok;
5840}
5841
5842/**********************************************************************/
5845static bool load_ruleset_styles(struct section_file *file,
5846 struct rscompat_info *compat)
5847{
5848 struct section_list *sec;
5849 int i;
5850 bool ok = TRUE;
5851
5852 /* City Styles ... */
5853
5855
5856 /* Get rest: */
5857 for (i = 0; i < game.control.num_city_styles; i++) {
5858 struct requirement_vector *reqs;
5859 const char *sec_name = section_name(section_list_get(sec, i));
5860
5861 sz_strlcpy(city_styles[i].graphic,
5862 secfile_lookup_str(file, "%s.graphic", sec_name));
5863 sz_strlcpy(city_styles[i].graphic_alt,
5864 secfile_lookup_str(file, "%s.graphic_alt", sec_name));
5865 sz_strlcpy(city_styles[i].citizens_graphic,
5867 "%s.citizens_graphic", sec_name));
5868
5870 if (reqs == NULL) {
5871 ok = FALSE;
5872 break;
5873 }
5875 }
5876
5878
5879 if (ok) {
5881
5882 if (sec != NULL) {
5883 int musi;
5884
5887 musi = 0;
5888
5889 section_list_iterate(sec, psection) {
5890 struct requirement_vector *reqs;
5892 const char *sec_name = section_name(psection);
5893
5894 sz_strlcpy(pmus->music_peaceful,
5896 "%s.music_peaceful", sec_name));
5897 sz_strlcpy(pmus->music_combat,
5899 "%s.music_combat", sec_name));
5900
5901 reqs = lookup_req_list(file, sec_name, "reqs", "Music Style");
5902 if (reqs == NULL) {
5903 ok = FALSE;
5904 break;
5905 }
5907
5908 musi++;
5910 }
5911
5913 }
5914
5915 return ok;
5916}
5917
5918/**********************************************************************/
5925 const char *uflags_path,
5926 const char *filename)
5927{
5928 /* Add each listed protected unit type flag as a !present
5929 * requirement. */
5930 if (secfile_entry_lookup(file, "%s", uflags_path)) {
5932 size_t psize;
5933 int i;
5934
5937 "%s", uflags_path);
5938
5939 if (!protecor_flag) {
5940 /* Entity exists but couldn't read it. */
5942 "\"%s\": %s: bad unit type flag list.",
5943 filename, uflags_path);
5944
5945 return FALSE;
5946 }
5947
5948 for (i = 0; i < psize; i++) {
5952 FALSE, FALSE, TRUE,
5953 protecor_flag[i]));
5954 }
5955
5957 }
5958
5959 return TRUE;
5960}
5961
5962/**********************************************************************/
5968 const char *actions_path,
5969 const char *filename)
5970{
5971 /* Read the alternative actions. */
5972 if (secfile_entry_lookup(file, "%s", actions_path)) {
5973 enum gen_action *unit_acts;
5974 size_t asize;
5975 int i;
5976
5978 "%s", actions_path);
5979
5980 if (!unit_acts) {
5981 /* Entity exists but couldn't read it. */
5983 "\"%s\": %s: bad action list",
5984 filename, actions_path);
5985
5986 return FALSE;
5987 }
5988
5989 for (i = 0; i < asize; i++) {
5990 auto_perf->alternatives[i] = unit_acts[i];
5991 }
5992
5993 free(unit_acts);
5994 }
5995
5996 return TRUE;
5997}
5998
5999/**********************************************************************/
6004 const char *item,
6005 const char *filename)
6006{
6007 char uflags_path[100];
6008 char action_path[100];
6009
6011 "missing_unit_upkeep.%s_protected", item);
6013 "missing_unit_upkeep.%s_unit_act", item);
6014
6016 filename)
6018 filename));
6019}
6020
6021/**********************************************************************/
6025static bool load_specialist(const struct section *psection,
6026 struct specialist *s,
6027 struct section_file *file)
6028{
6029 struct requirement_vector *reqs;
6030 const char *sec_name = section_name(psection);
6031 const char *item, *tag;
6032
6033 if (!ruleset_load_names(&s->name, nullptr, file, sec_name)) {
6034 return FALSE;
6035 }
6036
6038 "%s.short_name", sec_name);
6039 name_set(&s->abbreviation, nullptr, item);
6040
6041 tag = secfile_lookup_str(file, "%s.graphic", sec_name);
6042 if (nullptr == tag) {
6043 ruleset_error(nullptr, LOG_ERROR,
6044 "\"%s\": No graphic tag for specialist at %s.",
6045 secfile_name(file), sec_name);
6046 return FALSE;
6047 }
6048 sz_strlcpy(s->graphic_str, tag);
6051 "%s.graphic_alt", sec_name));
6052
6054 if (nullptr == reqs) {
6055 return FALSE;
6056 }
6058
6059 s->helptext = lookup_strvec(file, sec_name, "helptext");
6060
6061 return TRUE;
6062}
6063
6064/**********************************************************************/
6067static bool load_ruleset_cities(struct section_file *file,
6068 struct rscompat_info *compat)
6069{
6070 const char *filename = secfile_name(file);
6071 struct section_list *sec, *ssec = nullptr;
6072 int specs_count;
6073 bool ok = TRUE;
6074 int i = 0;
6075
6076 if (!rscompat_check_cap_and_version(file, filename, compat)) {
6077 return FALSE;
6078 }
6079
6080 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
6081 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
6082
6083 /* Specialist options */
6085
6086 if (!sec) {
6087 ruleset_error(nullptr, LOG_ERROR, "\"%s\": No normal specialists.", filename);
6088
6089 ok = FALSE;
6090 } else {
6093 /* Superspecialists are optional */
6094 if (ssec) {
6096 }
6097 if (specs_count >= SP_MAX) {
6098 ruleset_error(nullptr, LOG_ERROR,
6099 "\"%s\": Too many specialists (%d, max %d).",
6100 filename, specs_count, SP_MAX);
6101 ok = FALSE;
6102 }
6103 }
6104
6105
6106 if (ok) {
6108
6109 section_list_iterate(sec, psection) {
6110 struct specialist *s = specialist_by_number(i);
6111
6112 ok = load_specialist(psection, s, file);
6113
6114 if (!ok) {
6115 break;
6116 }
6117
6118 if (requirement_vector_size(&s->reqs) == 0 && DEFAULT_SPECIALIST == -1) {
6120 }
6121 i++;
6123 }
6124
6125 if (ok){
6126 if (DEFAULT_SPECIALIST == -1) {
6127 ruleset_error(nullptr, LOG_ERROR,
6128 "\"%s\": must have zero reqs for at least one "
6129 "specialist type.", filename);
6130 ok = FALSE;
6131 } else {
6133 }
6134 }
6136 sec = nullptr;
6137
6138 if (ssec) {
6139 if (ok) {
6140 section_list_iterate(ssec, psection) {
6141 struct specialist *s = specialist_by_number(i);
6142
6143 ok = load_specialist(psection, s, file);
6144
6145 if (!ok) {
6146 break;
6147 }
6148
6149 i++;
6151 }
6152
6154 ssec = nullptr;
6155 }
6156
6157 if (ok) {
6158 /* City Parameters */
6159
6162 "parameters.celebrate_size_limit");
6164 secfile_lookup_int_default(file, GAME_DEFAULT_ADDTOSIZE, "parameters.add_to_size_limit");
6167 "parameters.angry_citizens");
6168
6170 secfile_lookup_bool_default(file, GAME_DEFAULT_CHANGABLE_TAX, "parameters.changable_tax");
6172 secfile_lookup_int_default(file, 0, "parameters.forced_science");
6174 secfile_lookup_int_default(file, 100, "parameters.forced_luxury");
6176 secfile_lookup_int_default(file, 0, "parameters.forced_gold");
6178 + game.info.forced_gold != 100) {
6180 "\"%s\": Forced taxes do not add up in ruleset!",
6181 filename);
6182 ok = FALSE;
6183 }
6184 }
6185
6186 if (ok) {
6187 /* civ1 & 2 didn't reveal tiles */
6190 "parameters.vision_reveal_tiles");
6191
6193 secfile_lookup_int_default(file, 1, "parameters.pop_report_zeroes");
6194
6195 /* Citizens configuration. */
6198 "citizen.nationality");
6201 "citizen.ubuilder_nationality");
6204 "citizen.convert_speed");
6206 secfile_lookup_int_default(file, 0, "citizen.partisans_pct");
6208 secfile_lookup_int_default(file, 0, "citizen.conquest_convert_pct");
6209 }
6210
6211 if (ok) {
6212 /* Missing unit upkeep. */
6214
6215 /* Can't pay food upkeep! */
6217 auto_perf->cause = AAPC_UNIT_UPKEEP;
6218
6219 /* This is about food upkeep. */
6221 req_from_str("OutputType", "Local",
6222 FALSE, TRUE, TRUE,
6223 "Food"));
6224
6225 /* Internally represented as an action auto performer rule. */
6226 if (!load_muuk_as_action_auto(file, auto_perf, "food", filename)) {
6227 ok = FALSE;
6228 }
6229
6232 "missing_unit_upkeep.food_wipe");
6233
6234 /* Can't pay gold upkeep! */
6236 auto_perf->cause = AAPC_UNIT_UPKEEP;
6237
6238 /* This is about gold upkeep. */
6240 req_from_str("OutputType", "Local",
6241 FALSE, TRUE, TRUE,
6242 "Gold"));
6243
6244 /* Internally represented as an action auto performer rule. */
6245 if (!load_muuk_as_action_auto(file, auto_perf, "gold", filename)) {
6246 ok = FALSE;
6247 }
6248
6251 "missing_unit_upkeep.gold_wipe");
6252
6253 /* Can't pay shield upkeep! */
6255 auto_perf->cause = AAPC_UNIT_UPKEEP;
6256
6257 /* This is about shield upkeep. */
6259 req_from_str("OutputType", "Local",
6260 FALSE, TRUE, TRUE,
6261 "Shield"));
6262
6263 /* Internally represented as an action auto performer rule. */
6264 if (!load_muuk_as_action_auto(file, auto_perf, "shield", filename)) {
6265 ok = FALSE;
6266 }
6267
6270 "missing_unit_upkeep.shield_wipe");
6271 }
6272
6273 if (ok) {
6275 }
6276
6277 return ok;
6278}
6279
6280/**********************************************************************/
6283static bool load_ruleset_effects(struct section_file *file,
6284 struct rscompat_info *compat)
6285{
6286 struct section_list *sec;
6287 const char *filename;
6288 bool ok = TRUE;
6289
6290 filename = secfile_name(file);
6291
6292 if (!rscompat_check_cap_and_version(file, filename, compat)) {
6293 return FALSE;
6294 }
6295
6296 (void) secfile_entry_by_path(file, "datafile.description"); /* unused */
6297 (void) secfile_entry_by_path(file, "datafile.ruledit"); /* unused */
6298
6300
6301 if (sec != NULL) {
6302 section_list_iterate(sec, psection) {
6303 const char *sec_name = section_name(psection);
6304 enum effect_type main_type;
6305 enum effect_type ai_valued_as;
6306 const char *type;
6307
6308 type = secfile_lookup_str(file, "%s.type", sec_name);
6309 if (type == NULL) {
6311 "\"%s\" [%s] missing effect type.",
6312 filename, sec_name);
6313 ok = FALSE;
6314 break;
6315 }
6319 "\"%s\" [%s] lists unknown effect type \"%s\".",
6320 filename, sec_name, type);
6321 ok = FALSE;
6322 break;
6323 }
6324 if (!is_user_effect(main_type)) {
6326 "\"%s\" [%s] type \"%s\" is not an user effect.",
6327 filename, sec_name, type);
6328 ok = FALSE;
6329 break;
6330 }
6331
6332 type = secfile_lookup_str(file, "%s.ai_valued_as", sec_name);
6333 if (type == NULL) {
6335 "\"%s\" [%s] missing ai_valued_as.",
6336 filename, sec_name);
6337 ok = FALSE;
6338 break;
6339 }
6343 "\"%s\" [%s] lists unknown ai_valued_as \"%s\".",
6344 filename, sec_name, type);
6345 ok = FALSE;
6346 break;
6347 }
6350 "\"%s\" [%s] ai_valued_as \"%s\" is an user effect.",
6351 filename, sec_name, type);
6352 ok = FALSE;
6353 break;
6354 }
6355
6357 /* It has been set already! */
6359 "\"%s\" [%s] Duplicate \"%s\" entry.",
6360 filename, sec_name, type);
6361 ok = FALSE;
6362 break;
6363 }
6364
6367
6369 }
6370
6371 /* Parse effects and add them to the effects ruleset cache. */
6373 section_list_iterate(sec, psection) {
6374 enum effect_type eff;
6375 int value;
6376 struct multiplier *pmul;
6377 struct effect *peffect;
6378 const char *sec_name = section_name(psection);
6379 struct requirement_vector *reqs;
6380 const char *type;
6381 const char *comment;
6382
6383 type = secfile_lookup_str(file, "%s.type", sec_name);
6384
6385 if (type == NULL) {
6387 "\"%s\" [%s] missing effect type.",
6388 filename, sec_name);
6389 ok = FALSE;
6390 break;
6391 }
6392
6393 if (compat->compat_mode && compat->version < RSFORMAT_3_4) {
6395 }
6396
6398 if (!effect_type_is_valid(eff)) {
6400 "\"%s\" [%s] lists unknown effect type \"%s\".",
6401 filename, sec_name, type);
6402 ok = FALSE;
6403 break;
6404 }
6405
6406 value = secfile_lookup_int_default(file, 1, "%s.value", sec_name);
6407
6408 {
6409 const char *multiplier_name
6410 = secfile_lookup_str(file, "%s.multiplier", sec_name);
6411
6412 if (multiplier_name) {
6414 if (!pmul) {
6416 "\"%s\" [%s] has unknown multiplier \"%s\".",
6417 filename, sec_name, multiplier_name);
6418 ok = FALSE;
6419 break;
6420 }
6421 } else {
6422 pmul = NULL;
6423 }
6424 }
6425
6426 peffect = effect_new(eff, value, pmul);
6427
6428 reqs = lookup_req_list(file, sec_name, "reqs", type);
6429 if (reqs == NULL) {
6430 ok = FALSE;
6431 break;
6432 }
6433
6437
6438 comment = secfile_lookup_str_default(file, NULL, "%s.comment", sec_name);
6439
6440 if (comment != NULL) {
6441 peffect->rulesave.comment = fc_strdup(comment);
6442 }
6443
6446
6447 if (ok) {
6449 }
6450
6451 return ok;
6452}
6453
6454/**********************************************************************/
6458 int def, int min, int max,
6459 const char *path, ...)
6460{
6461 char fullpath[256];
6462 int ival;
6463 va_list args;
6464
6465 va_start(args, path);
6466 fc_vsnprintf(fullpath, sizeof(fullpath), path, args);
6467 va_end(args);
6468
6469 if (!secfile_lookup_int(file, &ival, "%s", fullpath)) {
6470 ival = def;
6471 }
6472
6473 if (ival < min) {
6475 "\"%s\" should be in the interval [%d, %d] "
6476 "but is %d; using the minimal value.",
6477 fullpath, min, max, ival);
6478 ival = min;
6479 }
6480
6481 if (ival > max) {
6483 "\"%s\" should be in the interval [%d, %d] "
6484 "but is %d; using the maximal value.",
6485 fullpath, min, max, ival);
6486 ival = max;
6487 }
6488
6489 return ival;
6490}
6491
6492/**********************************************************************/
6495static bool load_action_range_max(struct section_file *file, action_id act)
6496{
6497 struct action *paction = action_by_number(act);
6498 const char *vname = action_max_range_ruleset_var_name(act);
6499
6500 if (vname != NULL) {
6501 struct entry *pentry;
6502 int max_range;
6503
6504 pentry = secfile_entry_lookup(file, "actions.%s", vname);
6505
6506 if (pentry == NULL) {
6508 } else {
6509 const char *custom;
6510
6513 /* max_range already assigned */
6514 } else if (entry_type_get(pentry) == ENTRY_STR
6518 } else {
6519 ruleset_error(NULL, LOG_ERROR, "Bad actions.%s",
6522
6523 return FALSE;
6524 }
6525 }
6526
6528 }
6529
6530 return TRUE;
6531}
6532
6533/**********************************************************************/
6536static bool load_action_range(struct section_file *file, action_id act)
6537{
6538 struct action *paction = action_by_number(act);
6539 const char *vname;
6540
6541 if (!load_action_range_max(file, act)) {
6542 return FALSE;
6543 }
6544
6546 if (vname != NULL) {
6547 /* Min range can be loaded from the ruleset. */
6551 "actions.%s",
6552 vname);
6553 }
6554
6555 return TRUE;
6556}
6557
6558/**********************************************************************/
6561static bool load_action_kind(struct section_file *file, action_id act)
6562{
6563 struct action *paction = action_by_number(act);
6565
6566 if (var_name != NULL) {
6570 paction->result),
6572 "actions.%s", var_name);
6573 } else {
6576 }
6577
6578 return TRUE;
6579}
6580
6581/**********************************************************************/
6585 action_id act)
6586{
6588 /* Actor consumption can be loaded from the ruleset. */
6591 file, RS_DEFAULT_ACTION_ACTOR_CONSUMING_ALWAYS, "actions.%s",
6593 }
6594
6595 return TRUE;
6596}
6597
6598/**********************************************************************/
6602 const char *filename,
6603 struct action *paction,
6604 struct rscompat_info *compat)
6605{
6607
6608 if (var_name != nullptr) {
6609 /* Action blocking can be loaded from the ruleset. */
6610 char fullpath[1024];
6611
6612 fc_snprintf(fullpath, sizeof(fullpath), "actions.%s", var_name);
6613
6614 if (secfile_entry_by_path(file, fullpath)) {
6616 size_t asize;
6617 int j;
6618
6621
6622 if (!blocking_actions) {
6623 /* Entity exists but couldn't read it. */
6625 "\"%s\": %s: bad action list",
6626 filename, fullpath);
6627
6628 return FALSE;
6629 }
6630
6631 for (j = 0; j < asize; j++) {
6632 BV_SET(paction->blocked_by, blocking_actions[j]);
6633 }
6634
6636 }
6637 }
6638
6639 return TRUE;
6640}
6641
6642/**********************************************************************/
6647 const char *filename,
6648 int performer_slot,
6649 struct action *paction)
6650{
6652 char action_list_path[100];
6653
6655 /* Not relevant. */
6656 return TRUE;
6657 }
6658
6660 auto_perf->cause = AAPC_POST_ACTION;
6661
6662 /* Limit auto performer to this action. */
6665 FALSE, TRUE, TRUE,
6666 paction->id));
6667
6668 /* Load the list of actions. */
6670 "actions.%s",
6673 action_list_path, filename)) {
6674 return FALSE;
6675 }
6676
6677 return TRUE;
6678}
6679
6680/**********************************************************************/
6683static bool lookup_bv_actions(struct section_file *file,
6684 const char *filename,
6685 bv_actions *target,
6686 const char *path)
6687{
6688 if (secfile_entry_by_path(file, path)) {
6690 size_t asize;
6691 int j;
6692
6694 "%s", path);
6695
6696 if (!listed_actions) {
6697 /* Entity exists but couldn't read it. */
6698 ruleset_error(NULL, LOG_ERROR, "\"%s\": %s: bad action list",
6699 filename, path);
6700
6701 return FALSE;
6702 }
6703
6704 for (j = 0; j < asize; j++) {
6705 BV_SET(*target, listed_actions[j]);
6706 }
6707
6709 }
6710
6711 return TRUE;
6712}
6713
6714/**********************************************************************/
6717static bool load_ruleset_game(struct section_file *file, bool act,
6718 struct rscompat_info *compat)
6719{
6720 const char *sval, **svec;
6721 const char *filename;
6722 int *food_ini;
6723 int i;
6724 size_t teams;
6725 const char *pref_text;
6726 size_t gni_tmp;
6727 struct section_list *sec;
6728 size_t nval;
6729 const char *name;
6730 bool ok = TRUE;
6731
6732 if (file == NULL) {
6733 return FALSE;
6734 }
6735 filename = secfile_name(file);
6736
6737 name = secfile_lookup_str_default(file, NULL, "ruledit.description_file");
6738 if (name != NULL) {
6740 }
6742 = secfile_lookup_bool_default(file, FALSE, "ruledit.std_tileset_compat");
6743
6744 /* Section: tileset */
6745 pref_text = secfile_lookup_str_default(file, "", "tileset.preferred");
6746 if (pref_text[0] != '\0') {
6747 /* There was tileset suggestion */
6749 } else {
6750 /* No tileset suggestions */
6751 game.control.preferred_tileset[0] = '\0';
6752 }
6753
6754 /* Section: soundset */
6755 pref_text = secfile_lookup_str_default(file, "", "soundset.preferred");
6756 if (pref_text[0] != '\0') {
6757 /* There was soundset suggestion */
6759 } else {
6760 /* No soundset suggestions */
6762 }
6763
6764 /* Section: musicset */
6765 pref_text = secfile_lookup_str_default(file, "", "musicset.preferred");
6766 if (pref_text[0] != '\0') {
6767 /* There was musicset suggestion */
6769 } else {
6770 /* No musicset suggestions */
6772 }
6773
6774 /* Section: about */
6775 pref_text = secfile_lookup_str(file, "about.name");
6776 /* Ruleset/modpack name found */
6778
6779 pref_text = secfile_lookup_str_default(file, "", "about.version");
6780 if (pref_text[0] != '\0') {
6781 /* Ruleset/modpack version found */
6783 } else {
6784 /* No version information */
6785 game.control.version[0] = '\0';
6786 }
6787
6788 pref_text = secfile_lookup_str_default(file, "", "about.alt_dir");
6789 if (pref_text[0] != '\0') {
6790 /* Alt directory definition found. */
6792 } else {
6793 /* No alt directory information */
6794 game.control.alt_dir[0] = '\0';
6795 }
6796
6797 pref_text = secfile_lookup_str_default(file, "", "about.summary");
6798 if (pref_text[0] != '\0') {
6799 int len;
6800
6801 /* Ruleset/modpack summary found */
6802 len = strlen(pref_text);
6805 } else {
6806 /* No summary */
6807 if (game.ruleset_summary != NULL) {
6810 }
6811 }
6812
6813 pref_text = secfile_lookup_str_default(file, "", "about.description");
6814 if (pref_text[0] != '\0') {
6815 int len;
6816
6817 /* Ruleset/modpack description found */
6818 len = strlen(pref_text);
6822 } else {
6823 /* No description */
6824 if (game.ruleset_description != NULL) {
6827 }
6829 }
6830
6831 pref_text = secfile_lookup_str_default(file, "", "about.capabilities");
6832 if (pref_text[0] != '\0') {
6833 int len = strlen(pref_text);
6834
6837 } else {
6839 game.ruleset_capabilities[0] = '\0';
6840 }
6841
6842 /* Section: options */
6843 if (!lookup_tech_list(file, "options", "global_init_techs",
6844 game.rgame.global_init_techs, filename)) {
6845 ok = FALSE;
6846 }
6847
6848 if (ok) {
6849 if (!lookup_building_list(file, "options", "global_init_buildings",
6850 game.rgame.global_init_buildings, filename)) {
6851 ok = FALSE;
6852 }
6853 }
6854
6855 if (ok) {
6856 const char **slist;
6857 int j;
6858
6860 "options.popup_tech_help");
6861
6862 /* section: civstyle */
6865 "civstyle.base_pollution");
6866
6868
6869 slist = secfile_lookup_str_vec(file, &nval, "civstyle.gameloss_style");
6870 for (j = 0; j < nval; j++) {
6871 enum gameloss_style style;
6872
6873 sval = slist[j];
6874 if (strcmp(sval, "") == 0) {
6875 continue;
6876 }
6878 if (!gameloss_style_is_valid(style)) {
6880 "\"%s\": bad value \"%s\" for gameloss_style.",
6881 filename, sval);
6882 ok = FALSE;
6883 break;
6884 } else {
6885 game.info.gameloss_style |= style;
6886 }
6887 }
6888 free(slist);
6889 }
6890
6891 if (ok) {
6897 "civstyle.happy_cost");
6903 "civstyle.food_cost");
6909 "civstyle.base_bribe_cost");
6915 "civstyle.ransom_gold");
6918 "civstyle.pillage_select");
6919
6922 "civstyle.tech_steal_allow_holes");
6925 "civstyle.tech_trade_allow_holes");
6928 "civstyle.tech_trade_loss_allow_holes");
6931 "civstyle.tech_parasite_allow_holes");
6934 "civstyle.tech_loss_allow_holes");
6935
6941 "civstyle.upgrade_veteran_loss");
6947 "civstyle.autoupgrade_veteran_loss");
6948
6954 "research.base_tech_cost");
6955
6961 "research.min_tech_cost");
6962
6964 "civstyle.granary_food_ini");
6966
6969 "Too many granary_food_ini entries (%d, max %d)",
6971 ok = FALSE;
6972 } else if (game.info.granary_num_inis == 0) {
6973 log_error("No values for granary_food_ini. Using default "
6974 "value %d.", RS_DEFAULT_GRANARY_FOOD_INI);
6977 } else {
6978 int gi;
6979
6980 /* check for <= 0 entries */
6981 for (gi = 0; gi < game.info.granary_num_inis; gi++) {
6982 if (food_ini[gi] <= 0) {
6983 if (gi == 0) {
6985 } else {
6986 food_ini[gi] = food_ini[gi - 1];
6987 }
6988 log_error("Bad value for granary_food_ini[%i]. Using %i.",
6989 gi, food_ini[gi]);
6990 }
6992 }
6993 }
6994 free(food_ini);
6995 }
6996
6997 if (ok) {
7003 "civstyle.granary_food_inc");
7004
7011 "civstyle.min_city_center_%s",
7014 }
7015
7016 if (ok) {
7017 const char *tus_text;
7018
7024 "civstyle.init_vis_radius_sq");
7025
7031 "civstyle.init_city_radius_sq");
7032
7034 "civstyle.gold_upkeep_style");
7039 "Unknown gold upkeep style \"%s\"",
7040 tus_text);
7041 ok = FALSE;
7042 }
7043
7044 if (compat->compat_mode
7045 && compat->version < RSFORMAT_3_4) {
7047 = secfile_lookup_bool_default(file, FALSE, "civstyle.homeless_gold_upkeep");
7048
7052 "Cannot have homeless_gold_upkeep while gold_upkeep_style \"City\".");
7053 ok = FALSE;
7054 }
7055 } else {
7057 }
7058
7060 "civstyle.output_granularity");
7061
7063 = secfile_lookup_bool_default(file, FALSE, "civstyle.airlift_from_always_enabled");
7064
7066 = secfile_lookup_bool_default(file, TRUE, "civstyle.airlift_to_always_enabled");
7067
7068 /* Section: wonder_visibility */
7069 if (ok) {
7070 const char *text;
7071
7072 text = secfile_lookup_str_default(file,
7074 "wonder_visibility.small_wonders");
7075
7080 "Unknown wonder visibility type \"%s\"",
7081 text);
7082 ok = FALSE;
7083 }
7084 }
7085
7086 /* section: illness */
7089 "illness.illness_on");
7095 "illness.illness_base_factor");
7101 "illness.illness_min_size");
7107 "illness.illness_trade_infection");
7113 "illness.illness_pollution_factor");
7114
7115 /* section: incite_cost */
7121 "incite_cost.base_incite_cost");
7127 "incite_cost.improvement_factor");
7133 "incite_cost.unit_factor");
7139 "incite_cost.total_factor");
7140 }
7141
7142 if (ok) {
7143 const char *tus_text;
7144
7145 /* Section: combat_rules */
7148 "combat_rules.tired_attack");
7149
7152 "combat_rules.only_killing_makes_veteran");
7153
7156 "combat_rules.only_real_fight_makes_veteran");
7157
7160 "combat_rules.combat_odds_scaled_veterancy");
7161
7164 "combat_rules.damage_reduces_bombard_rate");
7165
7168 "combat_rules.low_firepower_badwallattacker");
7171 "combat_rules.low_firepower_pearl_harbor");
7172
7175 "combat_rules.low_firepower_combat_bonus");
7178 "combat_rules.low_firepower_nonnat_bombard");
7179
7184 "combat_rules.nuke_pop_loss_pct");
7185
7190 "combat_rules.nuke_defender_survival_chance_pct");
7191
7192 /* section: borders */
7198 "borders.radius_sq_city");
7204 "borders.size_effect");
7205
7211 "borders.radius_sq_city_permanent");
7212
7213 /* section: research */
7215 "research.tech_cost_style");
7220 "Unknown tech cost style \"%s\"",
7221 tus_text);
7222 ok = FALSE;
7223 }
7224
7226 "research.tech_leakage");
7231 "Unknown tech leakage \"%s\"",
7232 tus_text);
7233 ok = FALSE;
7234 }
7237 log_error("Only tech_leakage \"%s\" supported with "
7238 "tech_cost_style \"%s\". ",
7241 log_error("Switching to tech_leakage \"%s\".",
7244 }
7250 "research.base_tech_cost");
7251
7253 "research.tech_upkeep_style");
7254
7256
7259 "Unknown tech upkeep style \"%s\"",
7260 tus_text);
7261 ok = FALSE;
7262 }
7263 }
7264
7265 if (ok) {
7271 "research.tech_upkeep_divider");
7272
7273 sval = secfile_lookup_str_default(file, NULL, "research.free_tech_method");
7274 if (sval == NULL) {
7276 "No free_tech_method given");
7277 ok = FALSE;
7278 } else {
7282 "Bad value %s for free_tech_method.", sval);
7283 ok = FALSE;
7284 }
7285 }
7286 }
7287
7288 if (ok) {
7289 int cf;
7290
7291 /* section: culture */
7294 "culture.victory_min_points");
7297 "culture.victory_lead_pct");
7300 "culture.migration_pml");
7303 "culture.history_interest_pml");
7304
7305 /* section: world_peace */
7308 "world_peace.victory_turns");
7309
7310 /* section: calendar */
7313 "calendar.skip_year_0");
7316 "calendar.start_year");
7318 = secfile_lookup_int_default(file, 0, "calendar.fragments");
7319
7322 "Too many calendar fragments. Max is %d",
7324 ok = FALSE;
7326 }
7330 "calendar.positive_label"));
7334 "calendar.negative_label"));
7335
7336 for (cf = 0; cf < game.calendar.calendar_fragments; cf++) {
7337 const char *fname;
7338
7339 fname = secfile_lookup_str_default(file, NULL, "calendar.fragment_name%d", cf);
7340 if (fname != NULL) {
7343 }
7344 }
7345 }
7346
7347 if (ok) {
7348 /* section playercolors */
7349 struct rgbcolor *prgbcolor = NULL;
7350 bool color_read = TRUE;
7351
7352 /* Check if the player list is defined and empty. */
7353 if (playercolor_count() != 0) {
7354 ok = FALSE;
7355 } else {
7356 i = 0;
7357
7358 while (color_read) {
7359 prgbcolor = NULL;
7360
7361 color_read = rgbcolor_load(file, &prgbcolor, "playercolors.colorlist%d", i);
7362 if (color_read) {
7364 }
7365
7366 i++;
7367 }
7368
7369 if (playercolor_count() == 0) {
7370 ruleset_error(NULL, LOG_ERROR, "No player colors defined!");
7371 ok = FALSE;
7372 }
7373
7374 if (ok) {
7376 if (!rgbcolor_load(file, &game.plr_bg_color, "playercolors.background")) {
7378 "No background player color defined! (%s)",
7379 secfile_error());
7380 ok = FALSE;
7381 }
7382 }
7383 }
7384 }
7385
7386 if (ok) {
7387 /* section: teams */
7388 svec = secfile_lookup_str_vec(file, &teams, "teams.names");
7389 if (team_slot_count() < teams) {
7391 }
7393 for (i = 0; i < teams; i++) {
7395 }
7396 free(svec);
7397
7399 nval = (NULL != sec ? section_list_size(sec) : 0);
7400 if (nval > MAX_DISASTER_TYPES) {
7401 int num = nval; /* No "size_t" to printf */
7402
7404 "\"%s\": Too many disaster types (%d, max %d)",
7405 filename, num, MAX_DISASTER_TYPES);
7407 ok = FALSE;
7408 } else {
7410 }
7411 }
7412
7413 if (ok) {
7415 int id = disaster_index(pdis);
7416 int j;
7417 size_t eff_count;
7418 struct requirement_vector *reqs;
7419 const char *sec_name = section_name(section_list_get(sec, id));
7420
7421 if (!ruleset_load_names(&pdis->name, NULL, file, sec_name)) {
7423 "\"%s\": Cannot load disaster names",
7424 filename);
7425 ok = FALSE;
7426 break;
7427 }
7428
7430 if (reqs == NULL) {
7431 ok = FALSE;
7432 break;
7433 }
7435
7437 "%s.frequency", sec_name);
7438
7439 svec = secfile_lookup_str_vec(file, &eff_count, "%s.effects", sec_name);
7440
7441 BV_CLR_ALL(pdis->effects);
7442 for (j = 0; j < eff_count; j++) {
7443 const char *dsval = svec[j];
7445
7447
7450 "\"%s\" disaster \"%s\": unknown effect \"%s\".",
7451 filename, disaster_rule_name(pdis), dsval);
7452 ok = FALSE;
7453 break;
7454 } else {
7455 BV_SET(pdis->effects, effect);
7456 }
7457 }
7458
7459 free(svec);
7460
7461 if (!ok) {
7462 break;
7463 }
7466 }
7467
7468 if (ok) {
7470
7472 int id = achievement_index(pach);
7473 const char *sec_name = section_name(section_list_get(sec, id));
7474 const char *typename;
7475 const char *msg;
7476
7477 typename = secfile_lookup_str_default(file, NULL, "%s.type", sec_name);
7478
7479 pach->type = achievement_type_by_name(typename, fc_strcasecmp);
7480 if (!achievement_type_is_valid(pach->type)) {
7482 "Achievement has unknown type \"%s\".",
7483 typename != NULL ? typename : "(NULL)");
7484 ok = FALSE;
7485 }
7486
7487 if (ok) {
7489 "%s.unique", sec_name);
7490
7492 "%s.value", sec_name);
7493 pach->culture = secfile_lookup_int_default(file, 0,
7494 "%s.culture", sec_name);
7495
7496 msg = secfile_lookup_str_default(file, NULL, "%s.first_msg", sec_name);
7497 if (msg == NULL) {
7499 "Achievement %s has no first msg!", sec_name);
7500 ok = FALSE;
7501 } else {
7502 pach->first_msg = fc_strdup(msg);
7503 }
7504 }
7505
7506 if (ok) {
7507 msg = secfile_lookup_str_default(file, NULL, "%s.cons_msg", sec_name);
7508 if (msg == NULL) {
7509 if (!pach->unique) {
7511 "Achievement %s has no msg for consecutive gainers!",
7512 sec_name);
7513 ok = FALSE;
7514 }
7515 } else {
7516 pach->cons_msg = fc_strdup(msg);
7517 }
7518 }
7519
7520 if (!ok) {
7521 break;
7522 }
7525 }
7526
7527 if (ok) {
7528 for (i = 0; (name = secfile_lookup_str_default(file, NULL,
7529 "trade.settings%d.type",
7530 i)); i++) {
7532
7533 if (type == TRT_LAST) {
7535 "\"%s\" unknown trade route type \"%s\".",
7536 filename, name);
7537 ok = FALSE;
7538 } else {
7540 const char *cancelling;
7541 const char *bonus;
7542
7543 set->trade_pct = secfile_lookup_int_default(file, 100,
7544 "trade.settings%d.pct", i);
7545 cancelling = secfile_lookup_str_default(file, "Active",
7546 "trade.settings%d.cancelling", i);
7548 if (set->cancelling == TRI_LAST) {
7550 "\"%s\" unknown trade route cancelling type \"%s\".",
7551 filename, cancelling);
7552 ok = FALSE;
7553 }
7554
7555 bonus = secfile_lookup_str_default(file, "None", "trade.settings%d.bonus", i);
7556
7558
7561 "\"%s\" unknown trade route bonus type \"%s\".",
7562 filename, bonus);
7563 ok = FALSE;
7564 }
7565 }
7566 }
7567 }
7568
7569 if (ok) {
7570 const char *str;
7571
7573 = secfile_lookup_int_default(file, 0, "trade.min_trade_route_val");
7574
7577 "trade.reveal_trade_partner");
7578
7581 "trade.goods_selection");
7582
7584
7587 "\"%s\" goods selection method \"%s\" unknown.",
7588 filename, str);
7589 ok = FALSE;
7590 }
7591 }
7592
7593 if (ok) {
7595
7597 int id = goods_index(pgood);
7598 const char *sec_name = section_name(section_list_get(sec, id));
7599 struct requirement_vector *reqs;
7600 const char **slist;
7601 int j;
7602
7604 if (reqs == NULL) {
7605 ok = FALSE;
7606 break;
7607 }
7609
7610 pgood->from_pct = secfile_lookup_int_default(file, 100,
7611 "%s.from_pct", sec_name);
7612 pgood->to_pct = secfile_lookup_int_default(file, 100,
7613 "%s.to_pct", sec_name);
7614 pgood->onetime_pct = secfile_lookup_int_default(file, 100,
7615 "%s.onetime_pct", sec_name);
7616 pgood->select_priority = secfile_lookup_int_default(file, 1,
7617 "%s.select_priority", sec_name);
7618 pgood->replace_priority = secfile_lookup_int_default(file, 1,
7619 "%s.replace_priority", sec_name);
7620
7621 slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec_name);
7622 BV_CLR_ALL(pgood->flags);
7623 for (j = 0; j < nval; j++) {
7624 enum goods_flag_id flag;
7625
7626 sval = slist[j];
7628 if (!goods_flag_id_is_valid(flag)) {
7629 ruleset_error(NULL, LOG_ERROR, "\"%s\" good \"%s\": unknown flag \"%s\".",
7630 filename, goods_rule_name(pgood), sval);
7631 ok = FALSE;
7632 break;
7633 } else {
7634 BV_SET(pgood->flags, flag);
7635 }
7636 }
7637 free(slist);
7638
7639 pgood->helptext = lookup_strvec(file, sec_name, "helptext");
7642 }
7643
7644 if (ok) {
7645 const char *uname = secfile_lookup_str_default(file, nullptr,
7646 "aarea.access_unit");
7647 const struct unit_type *access_unit = nullptr;
7648
7649 if (uname != nullptr && uname[0] != '\0') {
7650 access_unit = unit_type_by_rule_name(uname);
7651
7652 if (access_unit == nullptr) {
7653 ruleset_error(nullptr, LOG_ERROR, "%s: access unit %s unknown.",
7654 filename, uname);
7655 ok = FALSE;
7656 }
7657 }
7658
7659 access_info_init(access_unit);
7660 }
7661
7662 if (ok) {
7664
7665 if (sec != NULL) {
7666 int num = section_list_size(sec);
7667
7668 for (i = 0; i < num; i++) {
7669 const char *sec_name = section_name(section_list_get(sec, i));
7670 const char *clause_name = secfile_lookup_str_default(file, NULL,
7671 "%s.type", sec_name);
7673 struct clause_info *info;
7674 struct requirement_vector *reqs;
7675
7676 if (!clause_type_is_valid(type)) {
7678 "\"%s\" unknown clause type \"%s\".",
7679 filename, clause_name);
7680 ok = FALSE;
7681 break;
7682 }
7683
7684 info = clause_info_get(type);
7685
7686 if (info->enabled) {
7688 "\"%s\" duplicate clause type \"%s\" definition.",
7689 filename, clause_name);
7690 ok = FALSE;
7691 break;
7692 }
7693
7694 reqs = lookup_req_list(file, sec_name, "giver_reqs", clause_name);
7695 if (reqs == NULL) {
7696 ok = FALSE;
7697 break;
7698 }
7700
7701 reqs = lookup_req_list(file, sec_name, "receiver_reqs", clause_name);
7702 if (reqs == NULL) {
7703 ok = FALSE;
7704 break;
7705 }
7707
7708 reqs = lookup_req_list(file, sec_name, "either_reqs", clause_name);
7709 if (reqs == NULL) {
7710 ok = FALSE;
7711 break;
7712 }
7714
7715 info->enabled = TRUE;
7716 }
7717 }
7719 }
7720
7721 if (ok) {
7723
7724 if (sec != NULL) {
7725 int num = section_list_size(sec);
7726 int curr;
7727
7728 for (curr = 0; curr < num; curr++) {
7729
7730 struct counter *pcount = counter_by_id(curr);
7731 const char *sec_name = section_name(section_list_get(sec, curr));
7732 const char *counter_type = secfile_lookup_str_default(file, NULL,
7733 "%s.type",
7734 sec_name);
7735
7738 if (!counter_behavior_is_valid(cb)) {
7740 "\"%s\" unknown counter type \"%s\".",
7741 filename, counter_type);
7742 ok = FALSE;
7743 break;
7744 }
7745
7746 if (!ruleset_load_names(&pcount->name, NULL, file, sec_name)) {
7748 "\"%s\": Cannot load counter names",
7749 filename);
7750 ok = FALSE;
7751 break;
7752 }
7753
7754 pcount->helptext = lookup_strvec(file, sec_name, "helptext");
7755 pcount->type = cb;
7756 if (!secfile_lookup_int(file, &pcount->checkpoint,
7757 "%s.checkpoint", sec_name)) {
7758
7760 "\"%s\": No checkpoint value",
7761 filename);
7762 ok = FALSE;
7763 break;
7764 }
7765
7766 pcount->target = CTGT_CITY;
7767 pcount->index = curr;
7768 pcount->def = secfile_lookup_int_default(file, 0,
7769 "%s.def",
7770 sec_name);
7772 }
7773 }
7774 }
7775
7776 /* secfile_check_unused() is not here, but only after also settings section
7777 * has been loaded. */
7778
7779 return ok;
7780}
7781
7782/**********************************************************************/
7785static bool load_ruleset_actions(struct section_file *file,
7786 struct section_file *gamefile,
7787 struct rscompat_info *compat)
7788{
7789 bool ok = TRUE;
7790 const char *filename = secfile_name(file);
7791 struct section_list *sec;
7793 struct requirement_vector *reqs;
7794
7795 /* Auto attack. */
7796
7797 /* Action auto performers aren't ready to be exposed in the ruleset
7798 * yet. The behavior when two action auto performers for the same
7799 * cause can fire isn't set in stone yet. How is one of them chosen?
7800 * What if all the actions of the chosen action auto performer turned
7801 * out to be illegal but one of the other action auto performers that
7802 * fired has legal actions? These issues can decide what other action
7803 * rules action auto performers can represent in the future. Deciding
7804 * should therefore wait until a rule needs action auto performers to
7805 * work a certain way. */
7806 /* Only one action auto performer, ACTION_AUTO_MOVED_ADJ, is caused
7807 * by AAPC_UNIT_MOVED_ADJ. It is therefore safe to expose the full
7808 * requirement vector to the ruleset. */
7809
7810 /* A unit moved next to this unit and the autoattack server setting
7811 * is enabled. */
7814
7815 reqs = lookup_req_list(file,
7816 "auto_attack", "if_attacker",
7817 "auto_attack");
7818 if (reqs == NULL) {
7819 ok = FALSE;
7820 } else {
7822
7824 "auto_attack.attack_actions",
7825 filename)) {
7826 /* Failed to load auto attack actions */
7828 "\"%s\": %s: failed load %s.",
7829 filename, "auto_attack", "attack_actions");
7830 ok = FALSE;
7831 }
7832 }
7833
7834 /* Section: actions */
7835 if (ok) {
7836 action_iterate(act_id) {
7837 struct action *paction = action_by_number(act_id);
7838
7839 if (!load_action_blocked_by_list(file, filename, paction, compat)) {
7840 ok = FALSE;
7841 break;
7842 }
7844
7845 if (ok) {
7846 if (!lookup_bv_actions(file, filename,
7848 "actions.diplchance_initial_odds")) {
7849 ok = FALSE;
7850 }
7851 }
7852
7853 if (ok) {
7854 /* If the "Poison City" action or the "Poison City Escape" action
7855 * should empty the granary. */
7856 /* TODO: empty granary and reduce population should become separate
7857 * action effect flags when actions are generalized. */
7861 "actions.poison_empties_food_stock");
7862
7863 /* If the "Steal Maps" action or the "Steal Maps Escape" action always
7864 * will reveal all cities when successful. */
7868 "actions.steal_maps_reveals_all_cities");
7869
7870 /* Allow setting certain properties for some actions before
7871 * generalized actions. */
7872 action_iterate(act_id) {
7873 if (!load_action_range(file, act_id)) {
7874 ok = FALSE;
7875 } else if (!load_action_kind(file, act_id)) {
7876 ok = FALSE;
7877 } else if (!load_action_actor_consuming_always(file, act_id)) {
7878 ok = FALSE;
7879 }
7880
7881 if (!ok) {
7882 break;
7883 }
7885 }
7886
7887 if (ok) {
7888 /* The quiet (don't auto generate help for) property of all actions
7889 * live in a single enum vector. This avoids generic action
7890 * expectations. */
7891 if (secfile_entry_by_path(file, "actions.quiet_actions")) {
7893 size_t asize;
7894 int j;
7895
7898 "actions.quiet_actions");
7899
7900 if (!quiet_actions) {
7901 /* Entity exists but couldn't read it. */
7903 "\"%s\": actions.quiet_actions: bad action list",
7904 filename);
7905
7906 ok = FALSE;
7907 } else {
7908 for (j = 0; j < asize; j++) {
7909 /* Don't auto generate help text for this action. */
7911 }
7912
7914 }
7915 }
7916 }
7917
7918 if (ok) {
7919 /* Hard code action sub results for now. */
7920
7921 /* Unit Enter Hut */
7923 BV_SET(paction->sub_results, ACT_SUB_RES_HUT_ENTER);
7933
7934 /* Unit Frighten Hut */
7946
7947 /* Unit May Embark */
7948 action_iterate(act_id) {
7949 struct action *paction = action_by_number(act_id);
7950
7952 "civstyle.paradrop_to_transport")
7955 BV_SET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK);
7956 }
7957
7958 /* Embark actions will always embark, not maybe embark. */
7960
7961 /* Non Lethal bombard */
7968 }
7969 }
7970
7971 if (ok) {
7972 /* Forced actions after another action was successfully performed. */
7973
7974 if (!load_action_post_success_force(file, filename,
7978 ok = FALSE;
7979 } else if (!load_action_post_success_force(file, filename,
7983 ok = FALSE;
7984 } else if (!load_action_post_success_force(file, filename,
7987 ACTION_ATTACK))) {
7988 ok = FALSE;
7989 } else if (!load_action_post_success_force(file, filename,
7992 ACTION_ATTACK2))) {
7993 ok = FALSE;
7994 } else if (!load_action_post_success_force(file, filename,
7998 ok = FALSE;
7999 } else if (!load_action_post_success_force(file, filename,
8003 ok = FALSE;
8004 }
8005
8006 /* No "Suicide Attack". Can't act when dead. */
8007 }
8008
8009 if (ok) {
8010 /* The city that made the unit's current tile native is gone.
8011 * Evaluated against an adjacent tile. */
8013 auto_perf->cause = AAPC_CITY_GONE;
8014
8015 /* I have no objections to moving this out of game's actions to
8016 * cities.ruleset, units.ruleset or an other location in game.ruleset
8017 * you find more suitable. -- Sveinung */
8019 "actions.escape_city", filename)) {
8020 ok = FALSE;
8021 }
8022 }
8023
8024 if (ok) {
8025 /* The unit's stack has been defeated and is scheduled for execution
8026 * but the unit has the CanEscape unit type flag.
8027 * Evaluated against an adjacent tile. */
8030
8031 /* I have no objections to moving this out of game's actions to
8032 * cities.ruleset, units.ruleset or an other location in game.ruleset
8033 * you find more suitable. -- Sveinung */
8035 "actions.unit_stack_death", filename)) {
8036 ok = FALSE;
8037 }
8038 }
8039
8040 if (ok) {
8042 if (sec != nullptr) {
8043 section_list_iterate(sec, psection) {
8044 const char *sec_name = section_name(psection);
8045 const char *action_text;
8046 struct action *paction;
8047 const char *ui_name;
8048
8049 action_text = secfile_lookup_str(file, "%s.action", sec_name);
8050
8051 if (action_text == nullptr) {
8052 ruleset_error(nullptr, LOG_ERROR,
8053 "\"%s\" [%s] missing action to configure.",
8054 filename, sec_name);
8055 ok = FALSE;
8056 break;
8057 }
8058
8060 if (paction == nullptr) {
8061 ruleset_error(nullptr, LOG_ERROR,
8062 "\"%s\" [%s] lists unknown action type \"%s\".",
8063 filename, sec_name, action_text);
8064 ok = FALSE;
8065 break;
8066 }
8067
8068 if (paction->configured) {
8069 ruleset_error(nullptr, LOG_ERROR,
8070 "\"%s\" [%s] duplicate configuration for action \"%s\".",
8071 filename, sec_name, action_text);
8072 ok = FALSE;
8073 break;
8074 }
8075
8076 paction->configured = TRUE;
8077
8078 ui_name = secfile_lookup_str_default(file, nullptr,
8079 "%s.ui_name", sec_name);
8080 if (ui_name == nullptr) {
8082 }
8083 sz_strlcpy(paction->ui_name, ui_name);
8085 }
8086 }
8087
8088 if (ok) {
8089 action_iterate(act) {
8090 struct action *paction = action_by_number(act);
8091
8092 if (!paction->configured) {
8094 }
8096 }
8097
8098 if (ok) {
8100
8101 if (sec != nullptr) {
8102 section_list_iterate(sec, psection) {
8103 struct action_enabler *enabler;
8104 const char *sec_name = section_name(psection);
8105 struct action *paction;
8106 struct requirement_vector *actor_reqs;
8107 struct requirement_vector *target_reqs;
8108 const char *action_text;
8109 const char *comment;
8110
8112
8113 action_text = secfile_lookup_str(file, "%s.action", sec_name);
8114
8115 if (action_text == nullptr) {
8116 ruleset_error(nullptr, LOG_ERROR,
8117 "\"%s\" [%s] missing action to enable.",
8118 filename, sec_name);
8119 ok = FALSE;
8120 break;
8121 }
8122
8124 if (paction == nullptr) {
8125 ruleset_error(nullptr, LOG_ERROR,
8126 "\"%s\" [%s] lists unknown action type \"%s\".",
8127 filename, sec_name, action_text);
8128 ok = FALSE;
8129 break;
8130 }
8131
8132 enabler->action = action_id(paction);
8133
8134 actor_reqs = lookup_req_list(file, sec_name, "actor_reqs", action_text);
8135 if (actor_reqs == NULL) {
8136 ok = FALSE;
8137 break;
8138 }
8139
8140 requirement_vector_copy(&enabler->actor_reqs, actor_reqs);
8141
8142 target_reqs = lookup_req_list(file, sec_name, "target_reqs", action_text);
8143 if (target_reqs == NULL) {
8144 ok = FALSE;
8145 break;
8146 }
8147
8148 requirement_vector_copy(&enabler->target_reqs, target_reqs);
8149
8150 comment = secfile_lookup_str(file, "%s.comment", sec_name);
8151 if (comment != nullptr) {
8152 enabler->rulesave.comment = fc_strdup(comment);
8153 }
8154
8157
8159 }
8160 }
8161
8162 return ok;
8163}
8164
8165/**********************************************************************/
8169static void send_ruleset_unit_classes(struct conn_list *dest)
8170{
8171 struct packet_ruleset_unit_class packet;
8173 int i;
8174
8175 for (i = 0; i < MAX_NUM_USER_UCLASS_FLAGS; i++) {
8176 const char *flagname;
8177 const char *helptxt;
8178
8180
8182 if (flagname == NULL) {
8183 fpacket.name[0] = '\0';
8184 } else {
8186 }
8187
8189 if (helptxt == NULL) {
8190 fpacket.helptxt[0] = '\0';
8191 } else {
8192 sz_strlcpy(fpacket.helptxt, helptxt);
8193 }
8194
8196 }
8197
8199 packet.id = uclass_number(c);
8200 sz_strlcpy(packet.name, untranslated_name(&c->name));
8201 sz_strlcpy(packet.rule_name, rule_name_get(&c->name));
8202 packet.min_speed = c->min_speed;
8203 packet.hp_loss_pct = c->hp_loss_pct;
8204 packet.non_native_def_pct = c->non_native_def_pct;
8205 packet.flags = c->flags;
8206
8207 PACKET_STRVEC_INSERT(packet.helptext, c->helptext);
8208
8209 lsend_packet_ruleset_unit_class(dest, &packet);
8211}
8212
8213/**********************************************************************/
8217static void send_ruleset_units(struct conn_list *dest)
8218{
8219 struct packet_ruleset_unit packet;
8220#ifdef FREECIV_WEB
8222#endif /* FREECIV_WEB */
8224 int i;
8225
8226 for (i = 0; i < MAX_NUM_USER_UNIT_FLAGS; i++) {
8227 const char *flagname;
8228 const char *helptxt;
8229
8231
8233 if (flagname == NULL) {
8234 fpacket.name[0] = '\0';
8235 } else {
8237 }
8238
8240 if (helptxt == NULL) {
8241 fpacket.helptxt[0] = '\0';
8242 } else {
8243 sz_strlcpy(fpacket.helptxt, helptxt);
8244 }
8245
8247 }
8248
8250 packet.id = utype_number(u);
8251 sz_strlcpy(packet.name, untranslated_name(&u->name));
8252 sz_strlcpy(packet.rule_name, rule_name_get(&u->name));
8253 sz_strlcpy(packet.sound_move, u->sound_move);
8254 sz_strlcpy(packet.sound_move_alt, u->sound_move_alt);
8255 sz_strlcpy(packet.sound_fight, u->sound_fight);
8256 sz_strlcpy(packet.sound_fight_alt, u->sound_fight_alt);
8257 sz_strlcpy(packet.graphic_str, u->graphic_str);
8258 sz_strlcpy(packet.graphic_alt, u->graphic_alt);
8259 sz_strlcpy(packet.graphic_alt2, u->graphic_alt2);
8261 packet.build_cost = u->build_cost;
8262 packet.pop_cost = u->pop_cost;
8263 packet.spectype_id = specialist_index(u->spec_type);
8264 packet.attack_strength = u->attack_strength;
8265 packet.defense_strength = u->defense_strength;
8266 packet.move_rate = u->move_rate;
8267
8268 /* Shallow-copy (borrow) requirement vector */
8269 packet.build_reqs = u->build_reqs;
8270
8271 packet.vision_radius_sq = u->vision_radius_sq;
8272 packet.transport_capacity = u->transport_capacity;
8273 packet.hp = u->hp;
8274 packet.firepower = u->firepower;
8275 packet.obsoleted_by = u->obsoleted_by
8276 ? utype_number(u->obsoleted_by)
8277 : utype_count();
8278 packet.converted_to = u->converted_to
8279 ? utype_number(u->converted_to)
8280 : utype_count();
8281 packet.convert_time = u->convert_time;
8282 packet.fuel = u->fuel;
8283 packet.flags = u->flags;
8284 packet.roles = u->roles;
8285 packet.happy_cost = u->happy_cost;
8287 packet.upkeep[o] = u->upkeep[o];
8289 packet.paratroopers_range = u->paratroopers_range;
8290 packet.bombard_rate = u->bombard_rate;
8291 packet.city_size = u->city_size;
8292 packet.city_slots = u->city_slots;
8293 packet.tp_defense = u->tp_defense;
8294 packet.cargo = u->cargo;
8295 packet.targets = u->targets;
8296 packet.embarks = u->embarks;
8297 packet.disembarks = u->disembarks;
8298 packet.vlayer = u->vlayer;
8299
8300 if (u->veteran == NULL) {
8301 /* Use the default veteran system. */
8302 packet.veteran_levels = 0;
8303 } else {
8304 /* Per unit veteran system definition. */
8306
8307 for (i = 0; i < packet.veteran_levels; i++) {
8308 const struct veteran_level *vlevel = utype_veteran_level(u, i);
8309
8311 packet.power_fact[i] = vlevel->power_fact;
8312 packet.move_bonus[i] = vlevel->move_bonus;
8313 packet.base_raise_chance[i] = vlevel->base_raise_chance;
8314 packet.work_raise_chance[i] = vlevel->work_raise_chance;
8315 }
8316 }
8317 PACKET_STRVEC_INSERT(packet.helptext, u->helptext);
8318
8319 packet.worker = u->adv.worker;
8320
8321#ifdef FREECIV_WEB
8322 web_packet.id = utype_number(u);
8323
8324 BV_CLR_ALL(web_packet.utype_actions);
8325
8326 action_iterate(act) {
8327 if (utype_can_do_action(u, act)) {
8328 BV_SET(web_packet.utype_actions, act);
8329 }
8331#endif /* FREECIV_WEB */
8332
8333 lsend_packet_ruleset_unit(dest, &packet);
8335
8336 combat_bonus_list_iterate(u->bonuses, pbonus) {
8338
8339 bonuspacket.unit = packet.id;
8340 bonuspacket.flag = pbonus->flag;
8341 bonuspacket.type = pbonus->type;
8342 bonuspacket.value = pbonus->value;
8343 bonuspacket.quiet = pbonus->quiet;
8344
8348}
8349
8350/**********************************************************************/
8354static void send_ruleset_specialists(struct conn_list *dest)
8355{
8356 struct packet_ruleset_specialist packet;
8357
8360
8361 packet.id = spec_id;
8363 sz_strlcpy(packet.rule_name, rule_name_get(&s->name));
8367
8368 /* Shallow-copy (borrow) requirement vector */
8369 packet.reqs = s->reqs;
8370
8372
8373 lsend_packet_ruleset_specialist(dest, &packet);
8375}
8376/**********************************************************************/
8379static void send_ruleset_tech_classes(struct conn_list *dest)
8380{
8381 struct packet_ruleset_tech_class packet;
8382
8384 packet.id = ptclass->idx;
8385 sz_strlcpy(packet.name, untranslated_name(&ptclass->name));
8386 sz_strlcpy(packet.rule_name, rule_name_get(&ptclass->name));
8387 packet.cost_pct = ptclass->cost_pct;
8388
8389 lsend_packet_ruleset_tech_class(dest, &packet);
8391}
8392
8393/**********************************************************************/
8397static void send_ruleset_techs(struct conn_list *dest)
8398{
8399 struct packet_ruleset_tech packet;
8401 int i;
8402
8403 for (i = 0; i < MAX_NUM_USER_TECH_FLAGS; i++) {
8404 const char *flagname;
8405 const char *helptxt;
8406
8407 fpacket.id = i + TECH_USER_1;
8408
8410 if (flagname == NULL) {
8411 fpacket.name[0] = '\0';
8412 } else {
8414 }
8415
8417 if (helptxt == NULL) {
8418 fpacket.helptxt[0] = '\0';
8419 } else {
8420 sz_strlcpy(fpacket.helptxt, helptxt);
8421 }
8422
8424 }
8425
8426 /* Since we have to prepend the tech requirements to the requirement
8427 * vector, we need to initialize a separate vector and deep-copy the
8428 * other requirements into it. */
8430
8431 advance_iterate(a) {
8432 packet.id = advance_number(a);
8433 packet.removed = !valid_advance(a);
8434 if (a->tclass == NULL) {
8435 packet.tclass = 0;
8436 } else {
8437 packet.tclass = a->tclass->idx;
8438 }
8439 sz_strlcpy(packet.name, untranslated_name(&a->name));
8440 sz_strlcpy(packet.rule_name, rule_name_get(&a->name));
8441 sz_strlcpy(packet.graphic_str, a->graphic_str);
8442 sz_strlcpy(packet.graphic_alt, a->graphic_alt);
8443
8444 /* Reset requirement vector. */
8446
8447 /* The requirements req1 and req2 are needed to research a tech. Send
8448 * them in the research_reqs requirement vector. Range is set to player
8449 * since pooled research is configurable. */
8450
8451 if ((a->require[AR_ONE] != A_NEVER)
8452 && advance_number(a->require[AR_ONE]) > A_NONE) {
8453 struct requirement req
8455 FALSE, TRUE, FALSE,
8456 advance_number(a->require[AR_ONE]));
8458 }
8459
8460 if ((a->require[AR_TWO] != A_NEVER)
8461 && advance_number(a->require[AR_TWO]) > A_NONE) {
8462 struct requirement req
8464 FALSE, TRUE, FALSE,
8465 advance_number(a->require[AR_TWO]));
8467 }
8468
8469 /* The requirements of the tech's research_reqs also goes in the
8470 * packet's research_reqs requirement vector. */
8471 requirement_vector_iterate(&a->research_reqs, req) {
8474
8475 packet.root_req = a->require[AR_ROOT]
8476 ? advance_number(a->require[AR_ROOT])
8477 : advance_count();
8478
8479 packet.flags = a->flags;
8480 packet.cost = a->cost;
8481 packet.num_reqs = a->num_reqs;
8482 PACKET_STRVEC_INSERT(packet.helptext, a->helptext);
8483
8484 lsend_packet_ruleset_tech(dest, &packet);
8486
8488}
8489
8490/**********************************************************************/
8493static void send_ruleset_counters(struct conn_list *dest)
8494{
8496 struct packet_ruleset_counter packet;
8497
8498 sz_strlcpy(packet.name, untranslated_name(&pcount->name));
8499 sz_strlcpy(packet.rule_name, rule_name_get(&pcount->name));
8500 packet.checkpoint = pcount->checkpoint;
8501 packet.behavior = pcount->type;
8502 packet.type = pcount->target;
8503 packet.def = pcount->def;
8504
8505 PACKET_STRVEC_INSERT(packet.helptext, pcount->helptext);
8506 lsend_packet_ruleset_counter(dest, &packet);
8508}
8509
8510/**********************************************************************/
8514static void send_ruleset_buildings(struct conn_list *dest)
8515{
8516 int i;
8517
8518 for (i = 0; i < MAX_NUM_USER_BUILDING_FLAGS; i++) {
8520 const char *flagname;
8521 const char *helptxt;
8522
8524
8526 if (flagname == NULL) {
8527 fpacket.name[0] = '\0';
8528 } else {
8530 }
8531
8533 if (helptxt == NULL) {
8534 fpacket.helptxt[0] = '\0';
8535 } else {
8536 sz_strlcpy(fpacket.helptxt, helptxt);
8537 }
8538
8540 }
8541
8543 struct packet_ruleset_building packet;
8544
8545 packet.id = improvement_number(b);
8546 packet.genus = b->genus;
8547 sz_strlcpy(packet.name, untranslated_name(&b->name));
8548 sz_strlcpy(packet.rule_name, rule_name_get(&b->name));
8549 sz_strlcpy(packet.graphic_str, b->graphic_str);
8550 sz_strlcpy(packet.graphic_alt, b->graphic_alt);
8551 sz_strlcpy(packet.graphic_alt2, b->graphic_alt2);
8552
8553 /* Shallow-copy (borrow) requirement vectors */
8554 packet.reqs = b->reqs;
8555 packet.obs_reqs = b->obsolete_by;
8556
8557 packet.build_cost = b->build_cost;
8558 packet.upkeep = b->upkeep;
8559 packet.sabotage = b->sabotage;
8560 packet.flags = b->flags;
8561 sz_strlcpy(packet.soundtag, b->soundtag);
8562 sz_strlcpy(packet.soundtag_alt, b->soundtag_alt);
8563 sz_strlcpy(packet.soundtag_alt2, b->soundtag_alt2);
8564 PACKET_STRVEC_INSERT(packet.helptext, b->helptext);
8565
8566 lsend_packet_ruleset_building(dest, &packet);
8568}
8569
8570/**********************************************************************/
8574static void send_ruleset_terrain(struct conn_list *dest)
8575{
8576 struct packet_ruleset_terrain packet;
8578 int i;
8579
8581
8582 for (i = 0; i < MAX_NUM_USER_TER_FLAGS; i++) {
8583 const char *flagname;
8584 const char *helptxt;
8585
8586 fpacket.id = i + TER_USER_1;
8587
8589 if (flagname == NULL) {
8590 fpacket.name[0] = '\0';
8591 } else {
8593 }
8594
8596 if (helptxt == NULL) {
8597 fpacket.helptxt[0] = '\0';
8598 } else {
8599 sz_strlcpy(fpacket.helptxt, helptxt);
8600 }
8601
8603 }
8604
8605 terrain_type_iterate(pterrain) {
8606 packet.id = terrain_number(pterrain);
8607 packet.tclass = pterrain->tclass;
8608 packet.native_to = pterrain->native_to;
8609
8610 sz_strlcpy(packet.name, untranslated_name(&pterrain->name));
8611 sz_strlcpy(packet.rule_name, rule_name_get(&pterrain->name));
8612 sz_strlcpy(packet.graphic_str, pterrain->graphic_str);
8613 sz_strlcpy(packet.graphic_alt, pterrain->graphic_alt);
8614 sz_strlcpy(packet.graphic_alt2, pterrain->graphic_alt2);
8615
8616 packet.movement_cost = pterrain->movement_cost;
8617 packet.defense_bonus = pterrain->defense_bonus;
8618
8620 packet.output[o] = pterrain->output[o];
8622
8623 packet.num_resources = 0;
8624 terrain_resources_iterate(pterrain, res, freq) {
8625 packet.resources[packet.num_resources] = extra_number(res);
8626 packet.resource_freq[packet.num_resources] = freq;
8627 packet.num_resources++;
8629
8631 packet.road_output_incr_pct[o] = pterrain->road_output_incr_pct[o];
8633
8634 packet.base_time = pterrain->base_time;
8635 packet.road_time = pterrain->road_time;
8636
8637 packet.cultivate_result = (pterrain->cultivate_result
8638 ? terrain_number(pterrain->cultivate_result)
8639 : terrain_count());
8640 packet.cultivate_time = pterrain->cultivate_time;
8641
8642 packet.plant_result = (pterrain->plant_result
8643 ? terrain_number(pterrain->plant_result)
8644 : terrain_count());
8645 packet.plant_time = pterrain->plant_time;
8646
8647 packet.irrigation_food_incr = pterrain->irrigation_food_incr;
8648 packet.irrigation_time = pterrain->irrigation_time;
8649
8650 packet.mining_shield_incr = pterrain->mining_shield_incr;
8651 packet.mining_time = pterrain->mining_time;
8652
8653 packet.num_animals = 0;
8654 terrain_animals_iterate(pterrain, panimal) {
8655 packet.animals[packet.num_animals] = utype_number(panimal);
8656 packet.num_animals++;
8658
8659 packet.transform_result = (pterrain->transform_result
8660 ? terrain_number(pterrain->transform_result)
8661 : terrain_count());
8662 packet.placing_time = pterrain->placing_time;
8663 packet.pillage_time = pterrain->pillage_time;
8664 packet.transform_time = pterrain->transform_time;
8665
8667 for (i = 0; i < game.control.num_extra_types; i++) {
8668 packet.extra_removal_times[i] = pterrain->extra_removal_times[i];
8669 }
8670
8671 packet.flags = pterrain->flags;
8672
8673 packet.color_red = pterrain->rgb->r;
8674 packet.color_green = pterrain->rgb->g;
8675 packet.color_blue = pterrain->rgb->b;
8676
8677 PACKET_STRVEC_INSERT(packet.helptext, pterrain->helptext);
8678
8679 lsend_packet_ruleset_terrain(dest, &packet);
8681}
8682
8683/**********************************************************************/
8686static void send_ruleset_resources(struct conn_list *dest)
8687{
8688 struct packet_ruleset_resource packet;
8689
8691 packet.id = extra_index(presource);
8692
8694 packet.output[o] = presource->data.resource->output[o];
8696
8697 lsend_packet_ruleset_resource(dest, &packet);
8699}
8700
8701/**********************************************************************/
8705static void send_ruleset_extras(struct conn_list *dest)
8706{
8707 int i;
8708
8709 for (i = 0; i < MAX_NUM_USER_EXTRA_FLAGS; i++) {
8711 const char *flagname;
8712 const char *helptxt;
8713
8715
8717 if (flagname == NULL) {
8718 fpacket.name[0] = '\0';
8719 } else {
8721 }
8722
8724 if (helptxt == NULL) {
8725 fpacket.helptxt[0] = '\0';
8726 } else {
8727 sz_strlcpy(fpacket.helptxt, helptxt);
8728 }
8729
8731 }
8732
8734 struct packet_ruleset_extra packet;
8735 int j;
8736
8737 packet.id = extra_number(e);
8738 sz_strlcpy(packet.name, untranslated_name(&e->name));
8739 sz_strlcpy(packet.rule_name, rule_name_get(&e->name));
8740
8741 packet.category = e->category;
8742
8743 BV_CLR_ALL(packet.causes);
8744 for (j = 0; j < EC_COUNT; j++) {
8745 if (is_extra_caused_by(e, j)) {
8746 BV_SET(packet.causes, j);
8747 }
8748 }
8749
8750 BV_CLR_ALL(packet.rmcauses);
8751 for (j = 0; j < ERM_COUNT; j++) {
8752 if (is_extra_removed_by(e, j)) {
8753 BV_SET(packet.rmcauses, j);
8754 }
8755 }
8756
8757 sz_strlcpy(packet.activity_gfx, e->activity_gfx);
8758 sz_strlcpy(packet.act_gfx_alt, e->act_gfx_alt);
8759 sz_strlcpy(packet.act_gfx_alt2, e->act_gfx_alt2);
8760 sz_strlcpy(packet.rmact_gfx, e->rmact_gfx);
8761 sz_strlcpy(packet.rmact_gfx_alt, e->rmact_gfx_alt);
8762 sz_strlcpy(packet.rmact_gfx_alt2, e->rmact_gfx_alt2);
8763 sz_strlcpy(packet.graphic_str, e->graphic_str);
8764 sz_strlcpy(packet.graphic_alt, e->graphic_alt);
8765
8766 /* Shallow-copy (borrow) requirement vectors */
8767 packet.reqs = e->reqs;
8768 packet.rmreqs = e->rmreqs;
8769
8770 packet.appearance_chance = e->appearance_chance;
8771 /* Shallow-copy (borrow) requirement vector */
8772 packet.appearance_reqs = e->appearance_reqs;
8773
8774 packet.disappearance_chance = e->disappearance_chance;
8775 /* Shallow-copy (borrow) requirement vector */
8776 packet.disappearance_reqs = e->disappearance_reqs;
8777
8778 packet.visibility_req = e->visibility_req;
8779 packet.buildable = e->buildable;
8780 packet.generated = e->generated;
8781 packet.build_time = e->build_time;
8782 packet.build_time_factor = e->build_time_factor;
8783 packet.removal_time = e->removal_time;
8784 packet.removal_time_factor = e->removal_time_factor;
8785 packet.infracost = e->infracost;
8786 packet.defense_bonus = e->defense_bonus;
8787 packet.eus = e->eus;
8788 packet.no_aggr_near_city = e->no_aggr_near_city;
8789
8790 packet.native_to = e->native_to;
8791
8792 packet.flags = e->flags;
8793 packet.hidden_by = e->hidden_by;
8794 packet.bridged_over = e->bridged_over;
8795 packet.conflicts = e->conflicts;
8796
8797 PACKET_STRVEC_INSERT(packet.helptext, e->helptext);
8798
8799 lsend_packet_ruleset_extra(dest, &packet);
8801}
8802
8803/**********************************************************************/
8807static void send_ruleset_bases(struct conn_list *dest)
8808{
8810 struct base_type *b = extra_base_get(pextra);
8811 struct packet_ruleset_base packet;
8812
8813 packet.id = base_number(b);
8814
8815 packet.gui_type = b->gui_type;
8816 packet.border_sq = b->border_sq;
8817 packet.vision_main_sq = b->vision_main_sq;
8818 packet.vision_invis_sq = b->vision_invis_sq;
8819 packet.vision_subs_sq = b->vision_subs_sq;
8820
8821 lsend_packet_ruleset_base(dest, &packet);
8823}
8824
8825/**********************************************************************/
8829static void send_ruleset_roads(struct conn_list *dest)
8830{
8831 struct packet_ruleset_road packet;
8832
8834 struct road_type *r = extra_road_get(pextra);
8835
8836 packet.id = road_number(r);
8837
8838 packet.gui_type = r->gui_type;
8839
8840 /* Shallow-copy (borrow) requirement vector */
8841 packet.first_reqs = r->first_reqs;
8842
8843 packet.move_cost = r->move_cost;
8844 packet.move_mode = r->move_mode;
8845
8847 packet.tile_incr_const[o] = r->tile_incr_const[o];
8848 packet.tile_incr[o] = r->tile_incr[o];
8849 packet.tile_bonus[o] = r->tile_bonus[o];
8851
8852 packet.compat = r->compat;
8853
8854 packet.integrates = r->integrates;
8855 packet.flags = r->flags;
8856
8857 lsend_packet_ruleset_road(dest, &packet);
8859}
8860
8861/**********************************************************************/
8865static void send_ruleset_tiledefs(struct conn_list *dest)
8866{
8867 struct packet_ruleset_tiledef packet;
8868
8871
8872 packet.id = tiledef_number(td);
8873 sz_strlcpy(packet.name, untranslated_name(&td->name));
8874 sz_strlcpy(packet.rule_name, rule_name_get(&td->name));
8875
8877 extra_type_list_iterate(td->extras, pextra) {
8878 BV_SET(extras, extra_index(pextra));
8880
8881 packet.extras = extras;
8882
8883 lsend_packet_ruleset_tiledef(dest, &packet);
8885}
8886
8887/**********************************************************************/
8891static void send_ruleset_goods(struct conn_list *dest)
8892{
8893 struct packet_ruleset_goods packet;
8894
8896 packet.id = goods_number(g);
8897 sz_strlcpy(packet.name, untranslated_name(&g->name));
8898 sz_strlcpy(packet.rule_name, rule_name_get(&g->name));
8899
8900 /* Shallow-copy (borrow) requirement vector */
8901 packet.reqs = g->reqs;
8902
8903 packet.from_pct = g->from_pct;
8904 packet.to_pct = g->to_pct;
8905 packet.onetime_pct = g->onetime_pct;
8906 packet.select_priority = g->select_priority;
8907 packet.replace_priority = g->replace_priority;
8908 packet.flags = g->flags;
8909
8910 PACKET_STRVEC_INSERT(packet.helptext, g->helptext);
8911
8912 lsend_packet_ruleset_goods(dest, &packet);
8914}
8915
8916/**********************************************************************/
8920static void send_ruleset_disasters(struct conn_list *dest)
8921{
8922 struct packet_ruleset_disaster packet;
8923
8925 packet.id = disaster_number(d);
8926
8927 sz_strlcpy(packet.name, untranslated_name(&d->name));
8928 sz_strlcpy(packet.rule_name, rule_name_get(&d->name));
8929
8930 /* Shallow-copy (borrow) requirement vector */
8931 packet.reqs = d->reqs;
8932
8933 packet.frequency = d->frequency;
8934
8935 packet.effects = d->effects;
8936
8937 lsend_packet_ruleset_disaster(dest, &packet);
8939}
8940
8941/**********************************************************************/
8945static void send_ruleset_achievements(struct conn_list *dest)
8946{
8947 struct packet_ruleset_achievement packet;
8948
8950 packet.id = achievement_number(a);
8951
8952 sz_strlcpy(packet.name, untranslated_name(&a->name));
8953 sz_strlcpy(packet.rule_name, rule_name_get(&a->name));
8954
8955 packet.type = a->type;
8956 packet.unique = a->unique;
8957 packet.value = a->value;
8958
8959 lsend_packet_ruleset_achievement(dest, &packet);
8961}
8962
8963/**********************************************************************/
8966static void send_ruleset_actions(struct conn_list *dest)
8967{
8968 struct packet_ruleset_action packet;
8969
8970 action_iterate(act) {
8971 struct action *paction = action_by_number(act);
8972
8973 packet.id = act;
8975 packet.quiet = action_by_number(act)->quiet;
8976
8977 packet.result = paction->result;
8978 packet.sub_results = paction->sub_results;
8979 packet.actor_consuming_always = paction->actor_consuming_always;
8980
8981 packet.act_kind = action_by_number(act)->actor_kind;
8982 packet.tgt_kind = action_by_number(act)->target_kind;
8984
8987 packet.blocked_by = action_by_number(act)->blocked_by;
8988
8989 lsend_packet_ruleset_action(dest, &packet);
8991}
8992
8993/**********************************************************************/
8997{
8998 struct packet_ruleset_action_enabler packet;
8999
9002
9003 /* Shallow-copy (borrow) requirement vectors */
9004 packet.actor_reqs = enabler->actor_reqs;
9005 packet.target_reqs = enabler->target_reqs;
9006
9009}
9010
9011/**********************************************************************/
9016{
9017 int counter;
9018 int id;
9019 struct packet_ruleset_action_auto packet;
9020
9021 id = 0;
9023 packet.id = id++;
9024
9025 packet.cause = aperf->cause;
9026
9027 /* Shallow-copy (borrow) requirement vector */
9028 packet.reqs = aperf->reqs;
9029
9030 for (counter = 0;
9031 /* Can't list more actions than all actions. */
9033 /* ACTION_NONE terminates the list. */
9034 && aperf->alternatives[counter] != ACTION_NONE;
9035 counter++) {
9036 packet.alternatives[counter] = aperf->alternatives[counter];
9037 }
9038 packet.alternatives_count = counter;
9039
9040 lsend_packet_ruleset_action_auto(dest, &packet);
9042}
9043
9044/**********************************************************************/
9048static void send_ruleset_trade_routes(struct conn_list *dest)
9049{
9050 struct packet_ruleset_trade packet;
9052
9053 for (type = TRT_NATIONAL; type < TRT_LAST; type++) {
9055
9056 packet.id = type;
9057 packet.trade_pct = set->trade_pct;
9058 packet.cancelling = set->cancelling;
9059 packet.bonus_type = set->bonus_type;
9060
9061 lsend_packet_ruleset_trade(dest, &packet);
9062 }
9063}
9064
9065/**********************************************************************/
9069static void send_ruleset_governments(struct conn_list *dest)
9070{
9071 struct packet_ruleset_government gov;
9073 int i;
9074
9075 for (i = 0; i < MAX_NUM_USER_GOVERNMENT_FLAGS; i++) {
9077 const char *flagname;
9078 const char *helptxt;
9079
9081
9083 if (flagname == nullptr) {
9084 fpacket.name[0] = '\0';
9085 } else {
9087 }
9088
9090 if (helptxt == nullptr) {
9091 fpacket.helptxt[0] = '\0';
9092 } else {
9093 sz_strlcpy(fpacket.helptxt, helptxt);
9094 }
9095
9097 }
9098
9100 /* Send one packet_government */
9101 gov.id = government_number(g);
9102
9103 /* Shallow-copy (borrow) requirement vector */
9104 gov.reqs = g->reqs;
9105
9106 gov.flags = g->flags;
9107
9108 sz_strlcpy(gov.name, untranslated_name(&g->name));
9109 sz_strlcpy(gov.rule_name, rule_name_get(&g->name));
9110 sz_strlcpy(gov.graphic_str, g->graphic_str);
9111 sz_strlcpy(gov.graphic_alt, g->graphic_alt);
9112 sz_strlcpy(gov.sound_str, g->sound_str);
9113 sz_strlcpy(gov.sound_alt, g->sound_alt);
9114 sz_strlcpy(gov.sound_alt2, g->sound_alt2);
9115 PACKET_STRVEC_INSERT(gov.helptext, g->helptext);
9116
9118
9119 /* Send one packet_government_ruler_title per ruler title. */
9121 const struct nation_type *pnation = ruler_title_nation(pruler_title);
9122
9123 title.gov = government_number(g);
9124 title.nation = pnation ? nation_number(pnation) : nation_count();
9125 sz_strlcpy(title.male_title,
9127 sz_strlcpy(title.female_title,
9132}
9133
9134/**********************************************************************/
9138static void send_ruleset_nations(struct conn_list *dest)
9139{
9142 struct packet_ruleset_nation packet;
9143 int i;
9144
9146 i = 0;
9151 i++;
9154
9156 i = 0;
9158 sz_strlcpy(groups_packet.groups[i],
9160 groups_packet.hidden[i] = pgroup->hidden;
9161 i++;
9164
9166 packet.id = nation_number(n);
9167 if (n->translation_domain == NULL) {
9168 packet.translation_domain[0] = '\0';
9169 } else {
9170 sz_strlcpy(packet.translation_domain, n->translation_domain);
9171 }
9172 sz_strlcpy(packet.adjective, untranslated_name(&n->adjective));
9173 sz_strlcpy(packet.rule_name, rule_name_get(&n->adjective));
9174 sz_strlcpy(packet.noun_plural, untranslated_name(&n->noun_plural));
9175 sz_strlcpy(packet.graphic_str, n->flag_graphic_str);
9176 sz_strlcpy(packet.graphic_alt, n->flag_graphic_alt);
9177
9178 i = 0;
9182 i++;
9184 packet.leader_count = i;
9185
9186 packet.style = style_number(n->style);
9187 packet.is_playable = n->is_playable;
9188 packet.barbarian_type = n->barb_type;
9189
9190 sz_strlcpy(packet.legend, n->legend);
9191
9192 i = 0;
9194 packet.sets[i++] = nation_set_number(pset);
9196 packet.nsets = i;
9197
9198 i = 0;
9200 packet.groups[i++] = nation_group_number(pgroup);
9202 packet.ngroups = i;
9203
9204 packet.init_government_id = n->init_government
9205 ? government_number(n->init_government) : government_count();
9206 fc_assert(ARRAY_SIZE(packet.init_techs) == ARRAY_SIZE(n->init_techs));
9207 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
9208 if (n->init_techs[i] != A_LAST) {
9209 packet.init_techs[i] = n->init_techs[i];
9210 } else {
9211 break;
9212 }
9213 }
9214 packet.init_techs_count = i;
9215 fc_assert(ARRAY_SIZE(packet.init_units) == ARRAY_SIZE(n->init_units));
9216 for (i = 0; i < MAX_NUM_UNIT_LIST; i++) {
9217 const struct unit_type *t = n->init_units[i];
9218 if (t) {
9219 packet.init_units[i] = utype_number(t);
9220 } else {
9221 break;
9222 }
9223 }
9224 packet.init_units_count = i;
9226 == ARRAY_SIZE(n->init_buildings));
9227 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
9228 if (n->init_buildings[i] != B_LAST) {
9229 /* Impr_type_id to int */
9230 packet.init_buildings[i] = n->init_buildings[i];
9231 } else {
9232 break;
9233 }
9234 }
9235 packet.init_buildings_count = i;
9236
9237 lsend_packet_ruleset_nation(dest, &packet);
9239
9240 /* Send initial values of is_pickable */
9242}
9243
9244/**********************************************************************/
9248static void send_ruleset_styles(struct conn_list *dest)
9249{
9250 struct packet_ruleset_style packet;
9251
9252 styles_iterate(s) {
9253 packet.id = style_index(s);
9254 sz_strlcpy(packet.name, untranslated_name(&s->name));
9255 sz_strlcpy(packet.rule_name, rule_name_get(&s->name));
9256
9257 lsend_packet_ruleset_style(dest, &packet);
9259}
9260
9261/**********************************************************************/
9264static void send_ruleset_clauses(struct conn_list *dest)
9265{
9266 struct packet_ruleset_clause packet;
9267 int i;
9268
9269 for (i = 0; i < CLAUSE_COUNT; i++) {
9270 struct clause_info *info = clause_info_get(i);
9271
9272 packet.type = i;
9273 packet.enabled = info->enabled;
9274
9275 /* Shallow-copy (borrow) requirement vectors */
9276 packet.giver_reqs = info->giver_reqs;
9277 packet.receiver_reqs = info->receiver_reqs;
9278 packet.either_reqs = info->either_reqs;
9279
9280 lsend_packet_ruleset_clause(dest, &packet);
9281 }
9282}
9283
9284/**********************************************************************/
9288static void send_ruleset_multipliers(struct conn_list *dest)
9289{
9290 multipliers_iterate(pmul) {
9291 struct packet_ruleset_multiplier packet;
9292
9293 packet.id = multiplier_number(pmul);
9294 packet.start = pmul->start;
9295 packet.stop = pmul->stop;
9296 packet.step = pmul->step;
9297 packet.def = pmul->def;
9298 packet.offset = pmul->offset;
9299 packet.factor = pmul->factor;
9300 packet.minimum_turns = pmul->minimum_turns;
9301
9302 sz_strlcpy(packet.name, untranslated_name(&pmul->name));
9303 sz_strlcpy(packet.rule_name, rule_name_get(&pmul->name));
9304
9305 /* Shallow-copy (borrow) requirement vector */
9306 packet.reqs = pmul->reqs;
9307
9308 PACKET_STRVEC_INSERT(packet.helptext, pmul->helptext);
9309
9310 lsend_packet_ruleset_multiplier(dest, &packet);
9312}
9313
9314/**********************************************************************/
9318static void send_ruleset_cities(struct conn_list *dest)
9319{
9321 int k;
9322
9323 for (k = 0; k < game.control.num_city_styles; k++) {
9324 city_p.style_id = k;
9325
9326 /* Shallow-copy (borrow) requirement vector */
9327 city_p.reqs = city_styles[k].reqs;
9328
9331 sz_strlcpy(city_p.graphic, city_styles[k].graphic);
9332 sz_strlcpy(city_p.graphic_alt, city_styles[k].graphic_alt);
9333 sz_strlcpy(city_p.citizens_graphic, city_styles[k].citizens_graphic);
9334
9336 }
9337}
9338
9339/**********************************************************************/
9343static void send_ruleset_musics(struct conn_list *dest)
9344{
9345 struct packet_ruleset_music packet;
9346
9348 packet.id = pmus->id;
9349
9350 sz_strlcpy(packet.music_peaceful, pmus->music_peaceful);
9351 sz_strlcpy(packet.music_combat, pmus->music_combat);
9352
9353 /* Shallow-copy (borrow) requirement vector */
9354 packet.reqs = pmus->reqs;
9355
9356 lsend_packet_ruleset_music(dest, &packet);
9358}
9359
9360/**********************************************************************/
9364static void send_ruleset_game(struct conn_list *dest)
9365{
9367 int i;
9368
9370
9371 /* Per unit veteran system definition. */
9372 misc_p.veteran_levels = game.veteran->levels;
9373
9374 for (i = 0; i < misc_p.veteran_levels; i++) {
9375 const struct veteran_level *vlevel = game.veteran->definitions + i;
9376
9377 sz_strlcpy(misc_p.veteran_name[i], untranslated_name(&vlevel->name));
9378 misc_p.power_fact[i] = vlevel->power_fact;
9379 misc_p.move_bonus[i] = vlevel->move_bonus;
9380 misc_p.base_raise_chance[i] = vlevel->base_raise_chance;
9381 misc_p.work_raise_chance[i] = vlevel->work_raise_chance;
9382 }
9383
9384 fc_assert(sizeof(misc_p.global_init_techs)
9385 == sizeof(game.rgame.global_init_techs));
9386 fc_assert(ARRAY_SIZE(misc_p.global_init_techs)
9388 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
9390 misc_p.global_init_techs[i] = game.rgame.global_init_techs[i];
9391 } else {
9392 break;
9393 }
9394 }
9395 misc_p.global_init_techs_count = i;
9396
9397 fc_assert(ARRAY_SIZE(misc_p.global_init_buildings)
9399 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
9401 /* Impr_type_id to int */
9402 misc_p.global_init_buildings[i] =
9404 } else {
9405 break;
9406 }
9407 }
9408 misc_p.global_init_buildings_count = i;
9409
9410 misc_p.default_specialist = DEFAULT_SPECIALIST;
9411
9413
9414 misc_p.background_red = game.plr_bg_color->r;
9415 misc_p.background_green = game.plr_bg_color->g;
9416 misc_p.background_blue = game.plr_bg_color->b;
9417
9419}
9420
9421/**********************************************************************/
9425static void send_ruleset_team_names(struct conn_list *dest)
9426{
9428
9430 const char *name = team_slot_defined_name(tslot);
9431
9432 if (NULL == name) {
9433 /* End of defined names. */
9434 break;
9435 }
9436
9438 sz_strlcpy(team_name_info_p.team_name, name);
9439
9442}
9443
9444/**********************************************************************/
9447static void notify_ruleset_fallback(const char *msg)
9448{
9450}
9451
9452/**********************************************************************/
9455bool load_rulesets(const char *restore, const char *alt, bool compat_mode,
9456 rs_conversion_logger logger,
9457 bool act, bool buffer_script, bool load_luadata)
9458{
9459 set_ruleset_compat_mode(compat_mode);
9460
9461 if (load_rulesetdir(game.server.rulesetdir, compat_mode, logger,
9462 act, buffer_script, load_luadata)) {
9464 return TRUE;
9465 }
9466
9467 if (alt != NULL) {
9468 if (load_rulesetdir(alt, compat_mode, logger, act, buffer_script,
9469 load_luadata)) {
9471
9473 return TRUE;
9474 }
9475 }
9476
9477 /* Fallback to previous one. */
9478 if (restore != NULL) {
9479 if (load_rulesetdir(restore, compat_mode, logger, act, buffer_script, TRUE)) {
9481
9482 notify_ruleset_fallback(_("Ruleset couldn't be loaded. Keeping previous one."));
9483
9485
9486 /* We're in sane state as restoring previous ruleset succeeded,
9487 * but return failure to indicate that this is not what caller
9488 * wanted. */
9489 return FALSE;
9490 }
9491 }
9492
9494
9495 /* Fallback to default one, but not if that's what we tried already */
9499 /* We're in sane state as fallback ruleset loading succeeded,
9500 * but return failure to indicate that this is not what caller
9501 * wanted. */
9503
9504 notify_ruleset_fallback(_("Ruleset couldn't be loaded. Switching to default one."));
9505
9506 return FALSE;
9507 }
9508 }
9509
9510#ifdef FREECIV_WEB
9511 log_normal(_("Cannot load any ruleset. Freeciv-web ruleset is available from "
9512 "https://github.com/freeciv/freeciv-web"));
9513#endif /* FREECIV_WEB */
9514
9515 /* Cannot load even default ruleset, we're in completely unusable state */
9517
9519}
9520
9521/**********************************************************************/
9525{
9526 if (file != NULL) {
9527 secfile_destroy(file);
9528 }
9529}
9530
9531/**********************************************************************/
9541
9542/**********************************************************************/
9546static bool load_rulesetdir(const char *rsdir, bool compat_mode,
9547 rs_conversion_logger logger,
9548 bool act, bool buffer_script, bool load_luadata)
9549{
9552 struct section_file *actionfile;
9553 bool ok = TRUE;
9555
9556 log_normal(_("Loading rulesets."));
9557
9559 compat_info.compat_mode = compat_mode;
9560 compat_info.log_cb = logger;
9561
9564 /* Reset the list of available player colors. */
9568
9569 if (script_buffer != NULL) {
9572 }
9573 if (parser_buffer != NULL) {
9576 }
9577
9578 server.playable_nations = 0;
9579
9583 buildfile = openload_ruleset_file("buildings", rsdir);
9584 govfile = openload_ruleset_file("governments", rsdir);
9586 terrfile = openload_ruleset_file("terrain", rsdir);
9591
9592 if (load_luadata) {
9594 } else {
9596 }
9597
9598 if (techfile == NULL
9599 || buildfile == NULL
9600 || govfile == NULL
9601 || unitfile == NULL
9602 || terrfile == NULL
9603 || stylefile == NULL
9604 || cityfile == NULL
9605 || nationfile == NULL
9606 || effectfile == NULL
9607 || actionfile == NULL
9608 || gamefile == NULL) {
9609 ok = FALSE;
9610 }
9611
9612 if (ok) {
9613 /* Note: Keep load_game_names() first so that compat_info.version is
9614 * correctly initialized. */
9624 }
9625
9626 if (ok) {
9628 }
9629
9630 if (ok) {
9632 }
9633 if (ok) {
9635 }
9636 if (ok) {
9638 }
9639 if (ok) {
9641 }
9642 if (ok) {
9643 /* Terrain must precede nations and units */
9645 }
9646 if (ok) {
9648 }
9649 if (ok) {
9651 }
9652 if (ok) {
9654 }
9655 if (ok) {
9657 }
9658 if (ok) {
9660 }
9661 if (ok) {
9663 }
9664
9665 if (ok) {
9666 /* Init nations we just loaded. */
9668
9669 /* Needed by role_unit_precalcs(). */
9671
9672 /* Prepare caches we want to sanity check. */
9676
9679 }
9680
9681 if (ok) {
9682 /* Only load settings for a sane ruleset */
9683 ok = settings_ruleset(gamefile, "settings", act,
9684 compat_info.compat_mode
9685 && compat_info.version < RSFORMAT_CURRENT);
9686
9687 if (ok) {
9689 }
9690 }
9691
9703
9704 if (extra_sections) {
9707 }
9708 if (base_sections) {
9711 }
9712 if (road_sections) {
9715 }
9716 if (resource_sections) {
9719 }
9720 if (terrain_sections) {
9723 }
9724
9725 if (ok) {
9727 }
9728
9729 if (ok) {
9730 char **buffer = buffer_script ? &script_buffer : NULL;
9731
9733
9735
9736 ok = (openload_script_file("script", rsdir, buffer, FALSE) == TRI_YES);
9737 }
9738
9739 if (ok) {
9740 enum fc_tristate pret;
9741 char **buffer = buffer_script ? &parser_buffer : NULL;
9742
9743 pret = openload_script_file("parser", rsdir, buffer, compat_info.compat_mode);
9744
9745 if (pret == TRI_MAYBE && buffer_script) {
9747 "-- This file is for lua-functionality for parsing luadata.txt\n-- of this ruleset.");
9748 }
9749
9750 ok = (pret != TRI_NO);
9751 }
9752
9753 if (ok && !buffer_script) {
9754 ok = (openload_script_file("default", rsdir, NULL, FALSE) == TRI_YES);
9755 }
9756
9757 if (ok && act) {
9758 /* Populate remaining caches. */
9765 ptype->unknown_move_cost = utype_unknown_move_cost(ptype);
9769
9770 /* Build advisors unit class cache corresponding to loaded rulesets */
9772 CALL_FUNC_EACH_AI(units_ruleset_init);
9773
9774 /* We may need to adjust the number of AI players
9775 * if the number of available nations changed. */
9777 }
9778
9779 return ok;
9780}
9781
9782/**********************************************************************/
9786{
9787 struct section_file *file;
9788 bool ok = TRUE;
9789
9791 if (file == NULL) {
9793 "Could not load game.ruleset:\n%s",
9794 secfile_error());
9795 ok = FALSE;
9796 }
9797 if (ok) {
9798 settings_ruleset(file, "settings", TRUE, FALSE);
9799 secfile_destroy(file);
9800 }
9801
9802 return ok;
9803}
9804
9805/**********************************************************************/
9808void send_rulesets(struct conn_list *dest)
9809{
9811
9812 /* ruleset_control also indicates to client that ruleset sending starts. */
9814
9815 /* Currently containing control-kind of data of nation sets and groups,
9816 * this too must be sent before any requirement vector may depend on
9817 * that data. */
9819
9820 send_ruleset_game(dest);
9830 send_ruleset_techs(dest);
9833 send_ruleset_units(dest);
9835 send_ruleset_extras(dest);
9836 send_ruleset_bases(dest);
9837 send_ruleset_roads(dest);
9841 send_ruleset_goods(dest);
9843 send_ruleset_styles(dest);
9845 send_ruleset_cities(dest);
9847 send_ruleset_musics(dest);
9848 send_ruleset_cache(dest);
9849
9850 /* Indicate client that all rulesets have now been sent. */
9852
9853 /* changed game settings will be send in
9854 * connecthand.c:establish_new_connection() */
9855
9857}
void access_info_init(const struct unit_type *aunit)
Definition accessarea.c:41
void access_info_close(void)
Definition accessarea.c:57
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:5956
void actions_rs_pre_san_gen(void)
Definition actions.c:899
const char * action_min_range_ruleset_var_name(int act)
Definition actions.c:6407
const char * action_blocked_by_ruleset_var_name(const struct action *act)
Definition actions.c:7125
bool action_is_in_use(struct action *paction)
Definition actions.c:5910
const char * action_post_success_forced_ruleset_var_name(const struct action *act)
Definition actions.c:7321
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:6950
const char * action_max_range_ruleset_var_name(int act)
Definition actions.c:6587
const char * action_target_kind_ruleset_var_name(int act)
Definition actions.c:6776
void action_enabler_add(struct action_enabler *enabler)
Definition actions.c:1547
const char * action_ui_name_default(int act)
Definition actions.c:6039
struct action_enabler * action_enabler_new(void)
Definition actions.c:1496
bool action_enabler_possible_actor(const struct action_enabler *ae)
Definition actions.c:5845
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:390
#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:122
bool territory_claiming_base(const struct base_type *pbase)
Definition base.c:163
#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:3485
void city_production_caravan_shields_init(void)
Definition city.c:1826
const char * city_style_rule_name(const int style)
Definition city.c:1813
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:849
#define output_type_iterate_end
Definition city.h:855
static struct fc_sockaddr_list * list
Definition clinet.c:102
char * incite_cost
Definition comments.c:77
#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:1354
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:1365
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:1345
#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:493
#define MAX_DISASTER_TYPES
Definition fc_types.h:52
#define MAX_VET_LEVELS
Definition fc_types.h:49
@ ROCO_RAILROAD
Definition fc_types.h:948
@ ROCO_NONE
Definition fc_types.h:948
@ ROCO_RIVER
Definition fc_types.h:948
@ ROCO_ROAD
Definition fc_types.h:948
#define MAX_GRANARY_INIS
Definition fc_types.h:74
#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:811
#define EC_SPECIAL
Definition fc_types.h:809
int action_id
Definition fc_types.h:250
#define SP_MAX
Definition fc_types.h:269
#define EC_NONE
Definition fc_types.h:808
#define EC_NOT_AGGRESSIVE
Definition fc_types.h:812
#define EC_DEFENSIVE
Definition fc_types.h:810
#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:128
#define MAX_ACHIEVEMENT_TYPES
Definition fc_types.h:53
#define MAX_LEN_NAME
Definition fc_types.h:68
#define MAX_NUM_TECH_LIST
Definition fc_types.h:44
#define MAX_LEN_CITYNAME
Definition fc_types.h:69
#define MAX_COUNTERS
Definition fc_types.h:108
#define UCL_LAST
Definition fc_types.h:276
#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:517
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:902
#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:892
#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:893
#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 RS_DEFAULT_HP
Definition game.h:888
#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:894
#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_HP
Definition game.h:889
#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_MAX_HP
Definition game.h:890
#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:371
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:331
const char * ruler_title_female_untranslated_name(const struct ruler_title *pruler_title)
Definition government.c:389
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:380
const char * gov_flag_helptxt(enum gov_flag_id id)
Definition government.c:660
void governments_alloc(int num)
Definition government.c:535
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:320
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:623
#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:978
#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:1041
const char * nation_group_untranslated_name(const struct nation_group *pgroup)
Definition nation.c:1062
struct nation_group * nation_group_by_rule_name(const char *name)
Definition nation.c:1016
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:138
Nation_type_id nation_count(void)
Definition nation.c:503
Nation_type_id nation_number(const struct nation_type *pnation)
Definition nation.c:484
struct nation_group * nation_group_new(const char *name)
Definition nation.c:953
bool nation_leader_is_male(const struct nation_leader *pleader)
Definition nation.c:295
struct nation_set * nation_set_new(const char *set_name, const char *set_rule_name, const char *set_description)
Definition nation.c:714
struct nation_type * nation_by_number(const Nation_type_id nation)
Definition nation.c:472
struct nation_city * nation_city_new(struct nation_type *pnation, const char *name)
Definition nation.c:347
const struct nation_leader_list * nation_leaders(const struct nation_type *pnation)
Definition nation.c:231
const char * nation_set_untranslated_name(const struct nation_set *pset)
Definition nation.c:797
bool is_nation_playable(const struct nation_type *nation)
Definition nation.c:201
int nation_set_number(const struct nation_set *pset)
Definition nation.c:706
void nation_city_set_terrain_preference(struct nation_city *pncity, const struct terrain *pterrain, enum nation_city_preference prefer)
Definition nation.c:397
void nation_city_set_river_preference(struct nation_city *pncity, enum nation_city_preference prefer)
Definition nation.c:407
bool nation_is_in_set(const struct nation_type *pnation, const struct nation_set *pset)
Definition nation.c:832
const char * nation_set_description(const struct nation_set *pset)
Definition nation.c:824
int nation_set_count(void)
Definition nation.c:690
struct nation_set * nation_set_by_number(int id)
Definition nation.c:762
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:779
Nation_type_id nation_index(const struct nation_type *pnation)
Definition nation.c:495
const char * nation_leader_name(const struct nation_leader *pleader)
Definition nation.c:287
int nation_group_count(void)
Definition nation.c:929
const char * nation_set_rule_name(const struct nation_set *pset)
Definition nation.c:806
struct nation_leader * nation_leader_new(struct nation_type *pnation, const char *name, bool is_male)
Definition nation.c:241
void nation_group_set_hidden(struct nation_group *pgroup, bool hidden)
Definition nation.c:1032
void nations_alloc(int num)
Definition nation.c:620
enum barbarian_type nation_barbarian_type(const struct nation_type *nation)
Definition nation.c:212
int nation_group_number(const struct nation_group *pgroup)
Definition nation.c:945
#define nation_leader_list_iterate(leaderlist, pleader)
Definition nation.h:57
#define nation_sets_iterate_end
Definition nation.h:333
#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:329
#define nations_iterate_end
Definition nation.h:364
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:361
#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:339
#define nation_groups_iterate_end
Definition nation.h:343
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:191
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:2650
void playercolor_free(void)
Definition plrhand.c:3351
void playercolor_init(void)
Definition plrhand.c:3341
int playercolor_count(void)
Definition plrhand.c:3390
void playercolor_add(struct rgbcolor *prgbcolor)
Definition plrhand.c:3370
void count_playable_nations(void)
Definition plrhand.c:2607
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:909
bool autoadjust_ruleset_data(void)
Definition rssanity.c:1623
#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:437
static void ruleset_load_traits(struct trait_limits *out, struct section_file *file, const char *secname, const char *field_prefix)
Definition ruleload.c:1277
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:9546
#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:1178
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:1953
static bool load_terrain_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:2763
static bool load_style_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:5784
int ruleset_purge_unused_entities(void)
Definition ruleload.c:327
#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:4467
#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:8397
#define section_strlcpy(dst, src)
Definition ruleload.c:126
static bool load_action_range(struct section_file *file, action_id act)
Definition ruleload.c:6536
#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:6025
static void send_ruleset_units(struct conn_list *dest)
Definition ruleload.c:8217
static void send_ruleset_governments(struct conn_list *dest)
Definition ruleload.c:9069
static bool load_action_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:1446
static struct extra_type * lookup_resource(const char *filename, const char *name, const char *jsection)
Definition ruleload.c:1157
static struct section_file * openload_luadata_file(const char *rsdir)
Definition ruleload.c:640
#define TILEDEF_SECTION_PREFIX
Definition ruleload.c:106
static bool load_ruleset_techs(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:1584
static bool purge_unused_req_vec(const struct requirement_vector *reqs, const char *msg)
Definition ruleload.c:341
void rulesets_deinit(void)
Definition ruleload.c:9535
static void send_ruleset_resources(struct conn_list *dest)
Definition ruleload.c:8686
static bool load_ruleset_buildings(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:2639
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:1009
static void nullcheck_secfile_destroy(struct section_file *file)
Definition ruleload.c:9524
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:6457
static void send_ruleset_clauses(struct conn_list *dest)
Definition ruleload.c:9264
static void send_ruleset_game(struct conn_list *dest)
Definition ruleload.c:9364
char * parser_buffer
Definition ruleload.c:223
#define NATION_SECTION_PREFIX
Definition ruleload.c:99
static bool load_ruleset_effects(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:6283
static bool lookup_cbonus_list(struct combat_bonus_list *list, struct section_file *file, const char *sec, const char *sub)
Definition ruleload.c:794
static void send_ruleset_nations(struct conn_list *dest)
Definition ruleload.c:9138
static void send_ruleset_roads(struct conn_list *dest)
Definition ruleload.c:8829
static int ruleset_purge_unused_enablers(void)
Definition ruleload.c:258
#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:4881
static void send_ruleset_tech_classes(struct conn_list *dest)
Definition ruleload.c:8379
static void send_ruleset_action_enablers(struct conn_list *dest)
Definition ruleload.c:8996
static void send_ruleset_control(struct conn_list *dest)
Definition ruleload.c:4687
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:9455
static void send_ruleset_tiledefs(struct conn_list *dest)
Definition ruleload.c:8865
#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:229
#define TERRAIN_SECTION_PREFIX
Definition ruleload.c:110
static struct section_file * openload_ruleset_file(const char *whichset, const char *rsdir)
Definition ruleload.c:585
struct requirement_vector * lookup_req_list(struct section_file *file, const char *sec, const char *sub, const char *rfor)
Definition ruleload.c:668
static void send_ruleset_musics(struct conn_list *dest)
Definition ruleload.c:9343
int ruleset_purge_redundant_reqs(void)
Definition ruleload.c:504
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:8891
static const char name_too_long[]
Definition ruleload.c:124
bool reload_rulesets_settings(void)
Definition ruleload.c:9785
static struct strvec * lookup_strvec(struct section_file *file, const char *prefix, const char *suffix)
Definition ruleload.c:1137
#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:853
static bool load_game_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:1316
static void send_ruleset_counters(struct conn_list *dest)
Definition ruleload.c:8493
static void send_ruleset_specialists(struct conn_list *dest)
Definition ruleload.c:8354
#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:9015
static bool load_government_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:4355
static int char * script_buffer
Definition ruleload.c:222
static bool load_action_blocked_by_list(struct section_file *file, const char *filename, struct action *paction, struct rscompat_info *compat)
Definition ruleload.c:6601
static void send_ruleset_team_names(struct conn_list *dest)
Definition ruleload.c:9425
static void send_ruleset_cities(struct conn_list *dest)
Definition ruleload.c:9318
static bool purge_redundant_req_vec(const struct requirement_vector *reqs, const char *msg)
Definition ruleload.c:426
static char * lookup_string(struct section_file *file, const char *prefix, const char *suffix)
Definition ruleload.c:1117
static const char * check_leader_names(struct nation_type *pnation)
Definition ruleload.c:4725
#define BASE_SECTION_PREFIX
Definition ruleload.c:103
static int ruleset_purge_redundant_reqs_effects(void)
Definition ruleload.c:475
static enum fc_tristate openload_script_file(const char *whichset, const char *rsdir, char **buffer, bool optional)
Definition ruleload.c:613
char * get_parser_buffer(void)
Definition ruleload.c:576
#define ACTION_SECTION_PREFIX
Definition ruleload.c:116
static bool load_building_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:2558
#define EXTRA_SECTION_PREFIX
Definition ruleload.c:102
void send_rulesets(struct conn_list *dest)
Definition ruleload.c:9808
#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:885
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:6067
static bool load_ruleset_styles(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:5845
static struct government * lookup_government(struct section_file *file, const char *entry, const char *filename, struct government *fallback)
Definition ruleload.c:1092
#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:2074
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:1228
static void send_ruleset_styles(struct conn_list *dest)
Definition ruleload.c:9248
#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:8920
static bool purge_duplicate_req_vec(const struct requirement_vector *reqs, const char *msg)
Definition ruleload.c:381
static bool lookup_tech_list(struct section_file *file, const char *prefix, const char *entry, int *output, const char *filename)
Definition ruleload.c:945
#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:6717
static bool load_nation_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:4745
static void send_ruleset_achievements(struct conn_list *dest)
Definition ruleload.c:8945
#define SCRIPT_SUFFIX
Definition ruleload.c:87
static void send_ruleset_bases(struct conn_list *dest)
Definition ruleload.c:8807
static bool load_ruleset_terrain(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:3135
static int ruleset_purge_unused_effects(void)
Definition ruleload.c:304
static bool load_action_actor_consuming_always(struct section_file *file, action_id act)
Definition ruleload.c:6584
static bool load_action_post_success_force(struct section_file *file, const char *filename, int performer_slot, struct action *paction)
Definition ruleload.c:6646
static bool load_tech_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:1466
#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:6561
static void send_ruleset_multipliers(struct conn_list *dest)
Definition ruleload.c:9288
char * get_script_buffer(void)
Definition ruleload.c:568
static void send_ruleset_actions(struct conn_list *dest)
Definition ruleload.c:8966
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:4897
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:5923
static bool load_ruleset_nations(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:5067
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:5966
static void send_ruleset_unit_classes(struct conn_list *dest)
Definition ruleload.c:8169
#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:1061
static void send_ruleset_extras(struct conn_list *dest)
Definition ruleload.c:8705
#define rs_sanity_veteran(_path, _entry, _i, _condition, _action)
static void send_ruleset_terrain(struct conn_list *dest)
Definition ruleload.c:8574
#define GOVERNMENT_SECTION_PREFIX
Definition ruleload.c:96
static bool load_unit_names(struct section_file *file, struct rscompat_info *compat)
Definition ruleload.c:1795
static void send_ruleset_trade_routes(struct conn_list *dest)
Definition ruleload.c:9048
static bool load_ruleset_actions(struct section_file *file, struct section_file *gamefile, struct rscompat_info *compat)
Definition ruleload.c:7785
static void notify_ruleset_fallback(const char *msg)
Definition ruleload.c:9447
static bool lookup_bv_actions(struct section_file *file, const char *filename, bv_actions *target, const char *path)
Definition ruleload.c:6683
static void send_ruleset_buildings(struct conn_list *dest)
Definition ruleload.c:8514
#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:1254
#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:523
static bool load_action_range_max(struct section_file *file, action_id act)
Definition ruleload.c:6495
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:6002
#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:2552
void update_nations_with_startpos(void)
Definition srv_main.c:2357
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 animals[MAX_NUM_ANIMALS]
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:595
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:113
struct nation_style * style_by_number(int id)
Definition style.c:84
void styles_alloc(int count)
Definition style.c:36
struct music_style * music_style_by_number(int id)
Definition style.c:165
int style_number(const struct nation_style *pstyle)
Definition style.c:68
void music_styles_alloc(int count)
Definition style.c:129
int style_index(const struct nation_style *pstyle)
Definition style.c:76
#define music_styles_iterate(_p)
Definition style.h:75
#define music_styles_iterate_end
Definition style.h:82
#define styles_iterate(_p)
Definition style.h:48
#define styles_iterate_end
Definition style.h:54
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:173
const char * team_slot_defined_name(const struct team_slot *tslot)
Definition team.c:271
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:281
#define team_slots_iterate_end
Definition team.h:89
#define team_slots_iterate(_tslot)
Definition team.h:84
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:110
const char * tech_flag_id_name_cb(enum tech_flag_id flag)
Definition tech.c:438
void set_user_tech_flag_name(enum tech_flag_id id, const char *name, const char *helptxt)
Definition tech.c:409
struct advance * valid_advance(struct advance *padvance)
Definition tech.c:157
void techs_precalc_data(void)
Definition tech.c:230
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:314
const char * tech_flag_helptxt(enum tech_flag_id id)
Definition tech.c:450
struct advance * advance_by_rule_name(const char *name)
Definition tech.c:205
struct tech_class * tech_class_by_rule_name(const char *name)
Definition tech.c:366
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:100
#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:188
Terrain_type_id terrain_count(void)
Definition terrain.c:119
const char * terrain_flag_id_name_cb(enum terrain_flag_id flag)
Definition terrain.c:820
Terrain_type_id terrain_index(const struct terrain *pterrain)
Definition terrain.c:139
struct terrain * terrain_by_number(const Terrain_type_id type)
Definition terrain.c:157
const char * terrain_flag_helptxt(enum terrain_flag_id id)
Definition terrain.c:832
struct resource_type * resource_type_init(struct extra_type *pextra)
Definition terrain.c:275
void set_user_terrain_flag_name(enum terrain_flag_id id, const char *name, const char *helptxt)
Definition terrain.c:791
Terrain_type_id terrain_number(const struct terrain *pterrain)
Definition terrain.c:148
#define RESOURCE_FREQUENCY_MAXIMUM
Definition terrain.h:102
#define terrain_type_iterate(_p)
Definition terrain.h:267
#define terrain_animals_iterate(pterrain, _animal)
Definition terrain.h:299
#define T_NONE
Definition terrain.h:61
#define TERRAIN_UNKNOWN_IDENTIFIER
Definition terrain.h:88
#define terrain_type_iterate_end
Definition terrain.h:273
#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:295
#define terrain_resources_iterate(pterrain, _res, _freq)
Definition terrain.h:286
#define terrain_animals_iterate_end
Definition terrain.h:307
#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:62
struct tiledef * tiledef_by_number(int id)
Definition tiledef.c:84
#define tiledef_index(_td_)
Definition tiledef.h:43
#define tiledef_iterate_end
Definition tiledef.h:56
#define tiledef_iterate(_p)
Definition tiledef.h:50
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:2790
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:2849
void role_unit_precalcs(void)
Definition unittype.c:2203
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:2719
Unit_type_id utype_count(void)
Definition unittype.c:82
int utype_veteran_levels(const struct unit_type *punittype)
Definition unittype.c:2659
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:2631
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:2688
Unit_Class_id uclass_number(const struct unit_class *pclass)
Definition unittype.c:2499
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